Merge remote-tracking branch 'origin/master' into worktree/custom-deepseek-models
# Conflicts: # packages/host/apiproxy/README.i18n.yaml
This commit is contained in:
@@ -21,7 +21,7 @@ import { SessionQueryError, type SessionSearchCursor } from '@deepseek-ai/dsh-se
|
||||
import type { Workspace, WorkspaceRecord } from '@deepseek-ai/dsh-workspace'
|
||||
import {
|
||||
workspaceDomainState, workspaceRecord, WorkspaceId as brandWorkspaceId,
|
||||
WorkspaceMoveInvalidError, WorkspaceNameConflictError,
|
||||
WorkspaceMoveInvalidError, WorkspaceNameConflictError, WorkspaceUnknownSessionError,
|
||||
} from '@deepseek-ai/dsh-workspace'
|
||||
// Type-only: brings the `ctx.tools` Context merge into this program (viewFor reads presenters).
|
||||
import type {} from '@deepseek-ai/dsh-tools'
|
||||
@@ -1565,7 +1565,10 @@ export function createApiProxy(ctx: Context, defaults: ApiProxyDefaults): ApiPro
|
||||
|
||||
workspace: {
|
||||
list(request) {
|
||||
return Promise.resolve(ok(request, { items: ctx.workspace.list().map(workspaceView) }))
|
||||
return Promise.resolve(ok(request, {
|
||||
items: ctx.workspace.list().map(workspaceView),
|
||||
archivedSessionIds: [...ctx.workspace.archivedSessionIds],
|
||||
}))
|
||||
},
|
||||
|
||||
// Exactly one of path/name arrives (schema refine). Existing-folder
|
||||
@@ -1681,6 +1684,23 @@ export function createApiProxy(ctx: Context, defaults: ApiProxyDefaults): ApiPro
|
||||
}
|
||||
return ok(request, { workspace: workspaceView(workspace) })
|
||||
},
|
||||
|
||||
async archiveSession(request) {
|
||||
const { sessionId } = request.payload
|
||||
try {
|
||||
await ctx.workspace.archiveSession(sessionId)
|
||||
} catch (error: unknown) {
|
||||
// Only the registry's unknown-session rejection is the business
|
||||
// code; storage/durability failures propagate as internal errors.
|
||||
if (!(error instanceof WorkspaceUnknownSessionError)) throw error
|
||||
return err(request, {
|
||||
code: 'session-not-found',
|
||||
message: error.message,
|
||||
details: { sessionId },
|
||||
})
|
||||
}
|
||||
return ok(request, { archivedSessionIds: [...ctx.workspace.archivedSessionIds] })
|
||||
},
|
||||
},
|
||||
|
||||
host: {
|
||||
@@ -2092,6 +2112,10 @@ export function createApiProxy(ctx: Context, defaults: ApiProxyDefaults): ApiPro
|
||||
const committedWorkspaceIds = new Set(
|
||||
ctx.workspace.list().map(workspace => String(workspace.id)),
|
||||
)
|
||||
// Frame-dedup baseline, same posture as committedWorkspaceIds: the
|
||||
// stream opens against the current set; workspace.list re-baselines
|
||||
// reconnecting clients, so only later changes need frames.
|
||||
let archivedSessionIds = ctx.workspace.archivedSessionIds
|
||||
const disposers = [
|
||||
ctx.on('session/created', (session: Session) => {
|
||||
queue.push(frame({
|
||||
@@ -2128,6 +2152,14 @@ export function createApiProxy(ctx: Context, defaults: ApiProxyDefaults): ApiPro
|
||||
committedWorkspaceIds.add(workspaceId)
|
||||
queue.push(frame({ type: 'host/workspace-changed', workspace: workspaceView(workspace) }))
|
||||
}
|
||||
if (state.archivedSessionIds.length !== archivedSessionIds.length
|
||||
|| state.archivedSessionIds.some((id, index) => id !== archivedSessionIds[index])) {
|
||||
archivedSessionIds = state.archivedSessionIds
|
||||
queue.push(frame({
|
||||
type: 'host/archived-sessions-changed',
|
||||
archivedSessionIds: [...state.archivedSessionIds],
|
||||
}))
|
||||
}
|
||||
return
|
||||
}
|
||||
if (change.table !== 'workspaces') return
|
||||
|
||||
Reference in New Issue
Block a user