Merge branch 'worktree-llm-dynamic-config' into worktree-llm-web-config
# Conflicts: # apps/cli/cordis.yml # apps/web/tests/snapshots/code-mode-round/session.jsonl # apps/web/tests/snapshots/cordis-tool-round/session.jsonl # apps/web/tests/snapshots/fresh-round-trip/session.jsonl # apps/web/tests/snapshots/lifecycle-chrome/session.jsonl # apps/web/tests/snapshots/live-interactions/session.jsonl # apps/web/tests/snapshots/navigation-panes/seed.jsonl # apps/web/tests/snapshots/question-composer/session.jsonl # apps/web/tests/snapshots/seeded-history/seed.jsonl # apps/web/tests/snapshots/steering/session.jsonl # docs/cordis-catalog/events.md # docs/cordis-catalog/services.md # docs/core-data-structures/core.i18n.yaml # docs/core-data-structures/settings.i18n.yaml # docs/event-producer-consumer.md # docs/module-graph.md # examples/acp-agent/tests/snapshots/workspace-context/session.jsonl # packages/client/connection/README.i18n.yaml # packages/client/connection/src/index.ts # packages/client/connection/tests/node-half.spec.ts # packages/client/runtime/README.i18n.yaml # packages/client/runtime/README.md # packages/client/runtime/README.zh.md # packages/client/runtime/src/client/index.ts # packages/client/runtime/tests/fake-api.ts # packages/client/ui-models/README.i18n.yaml # packages/examples/tui-demo/README.i18n.yaml # packages/host/apiproxy/README.i18n.yaml # packages/host/apiproxy/package.json # packages/host/apiproxy/src/api-proxy.ts # packages/host/apiproxy/src/api/rpc.schema.ts # packages/host/apiproxy/src/api/rpc.ts # packages/llm/llm-deepseek/README.i18n.yaml # packages/llm/llm-deepseek/README.zh.md # packages/llm/llm-pi-ai/README.i18n.yaml # packages/llm/llm/README.i18n.yaml # packages/llm/llm/README.zh.md # packages/sdk/sdk-client/README.i18n.yaml # packages/settings/settings/README.i18n.yaml # packages/settings/settings/README.md # packages/settings/settings/README.zh.md # packages/subagent/subagent-dsh-sdk/README.i18n.yaml # packages/subagent/subagent-dsh-sdk/README.zh.md # packages/support/llm-replay/README.i18n.yaml # packages/ui/jsonrpc/README.i18n.yaml # packages/ui/jsonrpc/README.zh.md # packages/ui/tui/tests/snapshots/model-selector.expected.txt # packages/ui/tui/tests/snapshots/model-switching.expected.txt # packages/ui/tui/tests/snapshots/resume-sessions.expected.txt # packages/ui/tui/tests/snapshots/status-diagnostics-narrow.expected.txt # packages/ui/tui/tests/snapshots/status-diagnostics.expected.txt # packages/ui/tui/tests/tui.snapshot.ts # pnpm-lock.yaml # python/sdk/README.i18n.yaml # scripts/snapshots/translation-prompt-v4/request-response.expected.json
This commit is contained in:
@@ -10,7 +10,9 @@ import type { HostFrame, MuxFrame } from './events.ts'
|
||||
import type { Wire } from './rpc.schema.ts'
|
||||
import { rpcErrorSchema, rpcIdSchema } from './rpc.schema.ts'
|
||||
import { approvalRequestIdSchema } from './approvals.schema.ts'
|
||||
import { contentBlockSchema, sessionEventSchema, sessionIdSchema, toolEventViewSchema } from './sessions.schema.ts'
|
||||
import {
|
||||
contentBlockSchema, inboxItemIdSchema, sessionEventSchema, sessionIdSchema, toolEventViewSchema,
|
||||
} from './sessions.schema.ts'
|
||||
import { workspaceIdSchema, workspaceViewSchema } from './workspace.schema.ts'
|
||||
|
||||
/** Question shape validated strictly against core dsh-user-interaction. */
|
||||
@@ -42,7 +44,14 @@ export const muxFrameSchema = z.discriminatedUnion('type', [
|
||||
// and must fail loud here, not reach the composer.
|
||||
z.object({ type: z.literal('question/requested'), sessionId: sessionIdSchema, questions: z.array(askUserQuestionItemSchema).min(1) }),
|
||||
z.object({ type: z.literal('question/resolved'), sessionId: sessionIdSchema, questionRpcId: rpcIdSchema, outcome: z.union([z.literal('answered'), z.literal('cancelled')]) }),
|
||||
z.object({ type: z.literal('session/queued'), sessionId: sessionIdSchema, message: messageSchema, steering: z.boolean() }),
|
||||
z.object({
|
||||
type: z.literal('session/queue'),
|
||||
sessionId: sessionIdSchema,
|
||||
items: z.array(z.object({
|
||||
id: inboxItemIdSchema,
|
||||
message: messageSchema,
|
||||
})),
|
||||
}),
|
||||
// value stays wide: it already passed its unit's own schema on the host,
|
||||
// and deep-validating here would import every domain's schema into the carrier.
|
||||
z.object({ type: z.literal('session/projection'), sessionId: sessionIdSchema, key: z.string().min(1), value: z.unknown(), seq: z.number().int().nonnegative() }),
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
import type { AskUserQuestionItem } from '@deepseek-ai/dsh-user-interaction/types'
|
||||
import type { ApprovalOutcome, ApprovalRequestId } from '@deepseek-ai/dsh-user-approval/types'
|
||||
import type { Message } from '@deepseek-ai/dsh-llm/types'
|
||||
import type { InboxItemId } from '@deepseek-ai/dsh-agent/brand'
|
||||
import type { CallId } from '@deepseek-ai/dsh-llm/brand'
|
||||
import type { SessionEvent, SessionId } from '@deepseek-ai/dsh-session/types'
|
||||
import type { ToolCallView, ToolResultView } from '@deepseek-ai/dsh-tools/presentation'
|
||||
@@ -31,6 +32,14 @@ export type ToolEventView =
|
||||
| { for: 'call'; view: ToolCallView }
|
||||
| { for: 'result'; view: ToolResultView }
|
||||
|
||||
/** One pending queued occurrence in an authoritative queue snapshot. */
|
||||
export interface QueuedInboxItem {
|
||||
/** Agent-owned occurrence identity used by queue mutations. */
|
||||
id: InboxItemId
|
||||
/** Complete pending message; it is not durable until the Agent claims it. */
|
||||
message: Message
|
||||
}
|
||||
|
||||
/** Streaming face of the contract: the two SSE stream openers (mux + host). */
|
||||
export interface EventsApi {
|
||||
/**
|
||||
@@ -62,18 +71,13 @@ export type MuxFrame =
|
||||
| { type: 'question/requested'; sessionId: SessionId; questions: AskUserQuestionItem[] }
|
||||
| { type: 'question/resolved'; sessionId: SessionId; questionRpcId: RpcId; outcome: 'answered' | 'cancelled' }
|
||||
/**
|
||||
* A message entered the addressed agent's inbox. A queued message is not
|
||||
* model-visible, so there is no session event to carry it; this transient
|
||||
* frame is the only wire signal. On stream open the
|
||||
* host replays the current queue snapshot for every attached session (same
|
||||
* refresh-recovery baseline as pending questions); queue clearing on cancel
|
||||
* has no dedicated frame — clients fold it from the status flip.
|
||||
* `steering` is the host's acceptance-time queue classification and remains
|
||||
* authoritative in reconnect snapshots. `message.source` carries the prompt's rpcId
|
||||
* when the message came over this wire (the client's provisional-echo
|
||||
* reconciliation key).
|
||||
* Complete transient queue state after every enqueue, mutation, claim, or
|
||||
* discard. Pending work is not model-visible and therefore has no durable
|
||||
* session event; the whole snapshot makes edit, deletion, cancel, and
|
||||
* reconnect converge through one authoritative signal. Pending steering is
|
||||
* outside this Web queue projection.
|
||||
*/
|
||||
| { type: 'session/queued'; sessionId: SessionId; message: Message; steering: boolean }
|
||||
| { type: 'session/queue'; sessionId: SessionId; items: QueuedInboxItem[] }
|
||||
/**
|
||||
* One projection unit's finished value changed (session-projection RFC).
|
||||
* Live push state, never logged — replay recomputes on the host (the
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
import type { DirectoryEntry } from './host.ts'
|
||||
import type { RequestPayload, ResponseValue } from './rpc-map.ts'
|
||||
import type { Wire } from './rpc.schema.ts'
|
||||
|
||||
@@ -16,6 +17,8 @@ export const hostDescribeValueSchema = z.object({
|
||||
provider: z.string().optional(),
|
||||
model: z.string().optional(),
|
||||
attachedSessions: z.number().int().nonnegative(),
|
||||
// Open string, not a literal union: unknown kinds must survive the wire so
|
||||
// a merge-added capability can advertise (the client hides the affordance).
|
||||
}) satisfies z.ZodType<Wire<ResponseValue<'host.describe'>>>
|
||||
|
||||
/** host.pickDirectory request payload (empty object literal). */
|
||||
@@ -26,6 +29,41 @@ export const hostPickDirectoryValueSchema = z.object({
|
||||
path: z.string().nullable(),
|
||||
}) satisfies z.ZodType<Wire<ResponseValue<'host.pickDirectory'>>>
|
||||
|
||||
/** Directory row shared by listing entries and breadcrumb crumbs. */
|
||||
export const directoryEntrySchema = z.object({
|
||||
name: z.string(),
|
||||
path: z.string(),
|
||||
hidden: z.boolean(),
|
||||
}) satisfies z.ZodType<Wire<DirectoryEntry>>
|
||||
|
||||
/** host.listDirectory request payload; an absent path lists the home directory. */
|
||||
export const hostListDirectoryRequestSchema = z.object({
|
||||
path: z.string().optional(),
|
||||
}) satisfies z.ZodType<Wire<RequestPayload<'host.listDirectory'>>>
|
||||
|
||||
/** host.listDirectory response value. */
|
||||
export const hostListDirectoryValueSchema = z.object({
|
||||
path: z.string(),
|
||||
home: z.string(),
|
||||
crumbs: z.array(directoryEntrySchema),
|
||||
entries: z.array(directoryEntrySchema),
|
||||
truncated: z.boolean(),
|
||||
}) satisfies z.ZodType<Wire<ResponseValue<'host.listDirectory'>>>
|
||||
|
||||
/** host.createDirectory request payload: name must be one plain path segment. */
|
||||
export const hostCreateDirectoryRequestSchema = z.object({
|
||||
path: z.string(),
|
||||
name: z.string(),
|
||||
}).refine(
|
||||
payload => payload.name.trim() !== '' && payload.name !== '.' && payload.name !== '..'
|
||||
&& !/[/\\]/.test(payload.name),
|
||||
{ message: 'host.createDirectory requires a single non-blank path segment name' },
|
||||
) satisfies z.ZodType<Wire<RequestPayload<'host.createDirectory'>>>
|
||||
|
||||
/** host.createDirectory response value: the created directory's absolute path. */
|
||||
export const hostCreateDirectoryValueSchema = z.object({
|
||||
path: z.string(),
|
||||
}) satisfies z.ZodType<Wire<ResponseValue<'host.createDirectory'>>>
|
||||
/** host.openPath request payload. */
|
||||
export const hostOpenPathRequestSchema = z.object({
|
||||
path: z.string().min(1),
|
||||
|
||||
@@ -5,6 +5,33 @@
|
||||
|
||||
import type { RpcRequest, RpcResponse } from './rpc.ts'
|
||||
|
||||
/** One directory row of a listing: a child entry or a breadcrumb ancestor. */
|
||||
export interface DirectoryEntry {
|
||||
/** Base name shown in a browser row (a root crumb carries its full path). */
|
||||
name: string
|
||||
/** Absolute host path — the client never joins path segments itself. */
|
||||
path: string
|
||||
/** Hidden by the host platform's convention (dot-prefixed on POSIX); the client owns whether to show it. */
|
||||
hidden: boolean
|
||||
}
|
||||
|
||||
/** host.listDirectory response value: one directory level plus its ancestry. */
|
||||
export interface DirectoryListing {
|
||||
/** Absolute path of the listed directory. */
|
||||
path: string
|
||||
/** The host account's home directory (breadcrumb "Home" rooting). */
|
||||
home: string
|
||||
/**
|
||||
* Ancestor chain from the filesystem root to the listed directory
|
||||
* inclusive; every crumb is a jump target (crumb `hidden` is always false).
|
||||
*/
|
||||
crumbs: DirectoryEntry[]
|
||||
/** Direct child directories, name-sorted; symlinks to directories included. */
|
||||
entries: DirectoryEntry[]
|
||||
/** True when the backend cut `entries` at its complete-result bound (the name-sorted tail is absent). */
|
||||
truncated: boolean
|
||||
}
|
||||
|
||||
/** Host-level unary methods. */
|
||||
export interface HostApi {
|
||||
/**
|
||||
@@ -13,7 +40,7 @@ export interface HostApi {
|
||||
* directory (root for session persistence and tool execution); provider/model = the defaults
|
||||
* applied when a new agent doesn't specify them explicitly, absent when the host configures
|
||||
* no explicit default (the adapter falls back internally);
|
||||
* attachedSessions = count of currently attached sessions (those with a live agent).
|
||||
* attachedSessions = count of currently attached sessions (those with a live agent);
|
||||
*/
|
||||
describe(request: RpcRequest<{}>): Promise<RpcResponse<{
|
||||
version: string
|
||||
@@ -23,16 +50,42 @@ export interface HostApi {
|
||||
attachedSessions: number
|
||||
}>>
|
||||
|
||||
/** Open the operating system's single-directory picker; cancellation returns null. */
|
||||
/**
|
||||
* Open the operating system's single-directory picker; cancellation returns
|
||||
* null. Only served under the `native` capability.
|
||||
*/
|
||||
pickDirectory(
|
||||
request: RpcRequest<{}>,
|
||||
signal: AbortSignal,
|
||||
): Promise<RpcResponse<{ path: string | null }>>
|
||||
|
||||
/**
|
||||
* List one directory level for the in-app browser; an absent path lists the
|
||||
* host account's home directory. Only served under the `browse` capability;
|
||||
* unreadable or missing targets fail with `directory-unreadable`. The
|
||||
* carrier's request signal follows the caller, stopping the backend's scan
|
||||
* on disconnect or timeout.
|
||||
*/
|
||||
listDirectory(
|
||||
request: RpcRequest<{ path?: string }>,
|
||||
signal: AbortSignal,
|
||||
): Promise<RpcResponse<DirectoryListing>>
|
||||
|
||||
/**
|
||||
* Create one child directory under an existing parent (the browser's
|
||||
* "New folder"). Only served under the `browse` capability; an existing
|
||||
* child fails with `directory-exists`, every other filesystem failure with
|
||||
* `directory-create-failed`.
|
||||
*/
|
||||
createDirectory(
|
||||
request: RpcRequest<{ path: string; name: string }>,
|
||||
): Promise<RpcResponse<{ path: string }>>
|
||||
|
||||
/**
|
||||
* Open a filesystem path with the operating system's default application
|
||||
* (Finder / Explorer / xdg-open hand-off). The browser carrier restricts this
|
||||
* privileged method to loopback, same-origin requests.
|
||||
* (Finder / Explorer / xdg-open hand-off). The browser carrier's
|
||||
* prefix-wide trust fence covers this privileged method like every other
|
||||
* `/api` request.
|
||||
*/
|
||||
openPath(
|
||||
request: RpcRequest<{ path: string }>,
|
||||
|
||||
@@ -35,13 +35,13 @@ export interface ApiProxy {
|
||||
// ---- Domain interfaces and payload entities ----
|
||||
export type {
|
||||
HistoryEntry, ModelCatalogFailure, ModelCatalogModel, ModelProviderGroup, ModelReasoning,
|
||||
ModelReasoningEffort, ModelTarget, SessionModels, SessionProjectionsBlock, SessionsApi, SessionSummary,
|
||||
ModelReasoningEffort, ModelTarget, QueueAction, SessionModels, SessionProjectionsBlock, SessionsApi, SessionSummary,
|
||||
} from './sessions.ts'
|
||||
export type { HostApi } from './host.ts'
|
||||
export type { DirectoryEntry, DirectoryListing, HostApi } from './host.ts'
|
||||
export type { WorkspaceApi, WorkspaceId, WorkspaceView } from './workspace.ts'
|
||||
export type { CommandsApi, CommandDescriptor } from './commands.ts'
|
||||
export type { SkillsApi, SkillEntry } from './skills.ts'
|
||||
export type { EventsApi, MuxFrame, HostFrame, ToolCallView, ToolEventView, ToolResultView } from './events.ts'
|
||||
export type { EventsApi, MuxFrame, HostFrame, QueuedInboxItem, ToolCallView, ToolEventView, ToolResultView } from './events.ts'
|
||||
export type { GoalsApi, GoalId, GoalRef } from './goals.ts'
|
||||
export type { SettingsApi, SettingsNamespaceView, SettingsSecretView } from './settings.ts'
|
||||
export type { CredentialsApi, CredentialView } from './credentials.ts'
|
||||
@@ -65,6 +65,7 @@ export type {
|
||||
// ---- Errors and ids ----
|
||||
export { RpcId, transportError } from './rpc.ts'
|
||||
export type { RpcError, RpcErrorCode, RpcErrorDetailsMap, RpcResult } from './rpc.ts'
|
||||
export type { InboxItemId } from '@deepseek-ai/dsh-agent/brand'
|
||||
|
||||
// ---- Method registry and derived generics ----
|
||||
export type { RequestPayload, ResponseValue, RpcMethodMap } from './rpc-map.ts'
|
||||
|
||||
@@ -26,10 +26,14 @@ export interface RpcMethodMap {
|
||||
'session.history': SessionsApi['history']
|
||||
'session.models': SessionsApi['models']
|
||||
'session.selectModel': SessionsApi['selectModel']
|
||||
'session.rename': SessionsApi['rename']
|
||||
'session.prompt': SessionsApi['prompt']
|
||||
'session.updateQueue': SessionsApi['updateQueue']
|
||||
'session.cancel': SessionsApi['cancel']
|
||||
'host.describe': HostApi['describe']
|
||||
'host.pickDirectory': HostApi['pickDirectory']
|
||||
'host.listDirectory': HostApi['listDirectory']
|
||||
'host.createDirectory': HostApi['createDirectory']
|
||||
'host.openPath': HostApi['openPath']
|
||||
'workspace.list': WorkspaceApi['list']
|
||||
'workspace.create': WorkspaceApi['create']
|
||||
|
||||
@@ -42,11 +42,17 @@ export const rpcErrorSchema: z.ZodType<RpcError> = z.discriminatedUnion('code',
|
||||
z.object({ code: z.literal('workspace-invalid-path'), message: z.string(), details: z.object({ path: z.string() }) }),
|
||||
z.object({ code: z.literal('workspace-name-conflict'), message: z.string(), details: z.object({ name: z.string() }) }),
|
||||
z.object({ code: z.literal('workspace-move-invalid'), message: z.string(), details: z.object({ workspaceId: z.string(), sessionId: z.string(), beforeSessionId: z.string().optional() }) }),
|
||||
z.object({ code: z.literal('directory-unreadable'), message: z.string(), details: z.object({ path: z.string() }) }),
|
||||
z.object({ code: z.literal('directory-exists'), message: z.string(), details: z.object({ path: z.string() }) }),
|
||||
z.object({ code: z.literal('directory-create-failed'), message: z.string(), details: z.object({ path: z.string() }) }),
|
||||
z.object({ code: z.literal('directory-picker-unavailable'), message: z.string(), details: z.object({ capability: z.string() }) }),
|
||||
z.object({ code: z.literal('agent-busy'), message: z.string(), details: z.object({ reason: z.string() }) }),
|
||||
z.object({ code: z.literal('queue-item-not-found'), message: z.string(), details: z.object({ itemId: z.string() }) }),
|
||||
z.object({ code: z.literal('command-error'), message: z.string(), details: z.object({}) }),
|
||||
z.object({ code: z.literal('unknown-command'), message: z.string(), details: z.object({}) }),
|
||||
z.object({ code: z.literal('settings-rejected'), message: z.string(), details: z.object({ ns: z.string() }) }),
|
||||
z.object({ code: z.literal('credential-rejected'), message: z.string(), details: z.object({ ref: z.string() }) }),
|
||||
z.object({ code: z.literal('title-invalid'), message: z.string(), details: z.object({ sessionId: z.string() }) }),
|
||||
z.object({ code: z.literal('internal'), message: z.string(), details: z.object({}) }),
|
||||
]) as unknown as z.ZodType<RpcError>
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import type { z as zCore } from 'zod'
|
||||
type ZodIssue = zCore.core.$ZodIssue
|
||||
import type { Branded } from '@deepseek-ai/dsh-brand'
|
||||
import type { SessionId } from '@deepseek-ai/dsh-session/types'
|
||||
import type { InboxItemId } from '@deepseek-ai/dsh-agent/brand'
|
||||
|
||||
/**
|
||||
* Message correlation id: the initiator mints it on a request; a response
|
||||
@@ -39,7 +40,12 @@ export interface RpcErrorDetailsMap {
|
||||
'workspace-invalid-path': { path: string }
|
||||
'workspace-name-conflict': { name: string }
|
||||
'workspace-move-invalid': { workspaceId: string; sessionId: SessionId; beforeSessionId?: SessionId }
|
||||
'directory-unreadable': { path: string }
|
||||
'directory-exists': { path: string }
|
||||
'directory-create-failed': { path: string }
|
||||
'directory-picker-unavailable': { capability: string }
|
||||
'agent-busy': { reason: string }
|
||||
'queue-item-not-found': { itemId: InboxItemId }
|
||||
/** A known slash command reported a usage/state error; the message is the command's own text. */
|
||||
'command-error': {}
|
||||
/** A leading-/ prompt named no registered command; the message names the token. */
|
||||
@@ -51,6 +57,7 @@ export interface RpcErrorDetailsMap {
|
||||
'settings-rejected': { ns: string }
|
||||
/** A credential write was refused (read-only shadowing layer or storage failure); the message is the seam's own text. */
|
||||
'credential-rejected': { ref: string }
|
||||
'title-invalid': { sessionId: SessionId }
|
||||
'internal': {}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
import { z } from 'zod'
|
||||
import type { SessionEvent, SessionId } from '@deepseek-ai/dsh-session/types'
|
||||
import type { InboxItemId } from '@deepseek-ai/dsh-agent/brand'
|
||||
import type { RequestPayload, ResponseValue } from './rpc-map.ts'
|
||||
import type { Wire } from './rpc.schema.ts'
|
||||
import type {
|
||||
@@ -19,6 +20,9 @@ import type { WorkspaceId } from './workspace.ts'
|
||||
/** SessionId: one brand cast after shape validation (the only cast point in this domain). */
|
||||
export const sessionIdSchema = z.string().min(1) as unknown as z.ZodType<SessionId>
|
||||
|
||||
/** InboxItemId: one brand cast after non-empty string validation. */
|
||||
export const inboxItemIdSchema = z.string().min(1) as unknown as z.ZodType<InboxItemId>
|
||||
|
||||
/**
|
||||
* WorkspaceId: the workspace domain's one brand cast. Hosted here rather
|
||||
* than in workspace.schema because session.create references it while
|
||||
@@ -73,6 +77,18 @@ export const sessionCreateValueSchema = z.object({
|
||||
sessionId: sessionIdSchema,
|
||||
}) satisfies z.ZodType<Wire<ResponseValue<'session.create'>>>
|
||||
|
||||
/** session.rename request payload (raw title; host-side normalization decides acceptance). */
|
||||
export const sessionRenameRequestSchema = z.object({
|
||||
sessionId: sessionIdSchema,
|
||||
title: z.string(),
|
||||
}) satisfies z.ZodType<Wire<RequestPayload<'session.rename'>>>
|
||||
|
||||
/** session.rename response value (the normalized accepted title and its event seq). */
|
||||
export const sessionRenameValueSchema = z.object({
|
||||
title: z.string().min(1),
|
||||
seq: z.number().int().nonnegative(),
|
||||
}) satisfies z.ZodType<Wire<ResponseValue<'session.rename'>>>
|
||||
|
||||
/** session.history request payload (beforeSeq/maxMessages page backwards from the window tail). */
|
||||
export const sessionHistoryRequestSchema = z.object({
|
||||
sessionId: sessionIdSchema,
|
||||
@@ -202,6 +218,21 @@ export const sessionPromptValueSchema = z.object({
|
||||
}).optional(),
|
||||
}) satisfies z.ZodType<Wire<ResponseValue<'session.prompt'>>>
|
||||
|
||||
/** session.updateQueue request payload. */
|
||||
export const sessionUpdateQueueRequestSchema = z.object({
|
||||
sessionId: sessionIdSchema,
|
||||
itemId: inboxItemIdSchema,
|
||||
action: z.discriminatedUnion('kind', [
|
||||
z.object({ kind: z.literal('edit'), content: z.array(contentBlockSchema) }),
|
||||
z.object({ kind: z.literal('remove') }),
|
||||
]),
|
||||
}) as unknown as z.ZodType<RequestPayload<'session.updateQueue'>>
|
||||
|
||||
/** session.updateQueue response value. */
|
||||
export const sessionUpdateQueueValueSchema = z.object({
|
||||
accepted: z.literal(true),
|
||||
}) satisfies z.ZodType<Wire<ResponseValue<'session.updateQueue'>>>
|
||||
|
||||
/** session.cancel request payload. */
|
||||
export const sessionCancelRequestSchema = z.object({
|
||||
sessionId: sessionIdSchema,
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
import type { ContentBlock } from '@deepseek-ai/dsh-llm/types'
|
||||
import type { InboxItemId } from '@deepseek-ai/dsh-agent/brand'
|
||||
import type { SessionEvent, SessionId } from '@deepseek-ai/dsh-session/types'
|
||||
// The pure-type outlet: api/ is browser-importable, and the package root's
|
||||
// cordis Context merge (via dsh-agent) must not enter client aggregates.
|
||||
@@ -124,6 +125,11 @@ export interface SessionModels {
|
||||
failures: ModelCatalogFailure[]
|
||||
}
|
||||
|
||||
/** A client-requested mutation of one still-pending queue item. */
|
||||
export type QueueAction =
|
||||
| { kind: 'edit'; content: ContentBlock[] }
|
||||
| { kind: 'remove' }
|
||||
|
||||
/** Session list entry (v1 builds no index: list does readdir+stat). */
|
||||
export interface SessionSummary {
|
||||
sessionId: SessionId
|
||||
@@ -208,6 +214,16 @@ export interface SessionsApi {
|
||||
}>):
|
||||
Promise<RpcResponse<{ selected: ModelTarget }>>
|
||||
|
||||
/**
|
||||
* Renames a session: appends a `session/title` event with the `user`
|
||||
* source, which pins the title against automatic regeneration. The
|
||||
* normalized accepted title and the title event's seq return so the caller
|
||||
* can settle its projection cell without waiting for the push frame. A
|
||||
* title that normalizes to empty fails with `title-invalid`.
|
||||
*/
|
||||
rename(request: RpcRequest<{ sessionId: SessionId; title: string }>):
|
||||
Promise<RpcResponse<{ title: string; seq: number }>>
|
||||
|
||||
/**
|
||||
* Sends a message. content is core's ContentBlock[] verbatim; mode maps 1:1 — queue→send, steer→steer.
|
||||
* A prompt whose content is exactly one text block starting with '/' is a slash command: the host
|
||||
@@ -219,6 +235,13 @@ export interface SessionsApi {
|
||||
prompt(request: RpcRequest<{ sessionId: SessionId; mode: 'queue' | 'steer'; content: ContentBlock[] }>):
|
||||
Promise<RpcResponse<{ accepted: true; command?: { kind: 'success'; text?: string } }>>
|
||||
|
||||
/**
|
||||
* Edits or removes one pending queued occurrence.
|
||||
*/
|
||||
updateQueue(request: RpcRequest<{ sessionId: SessionId; itemId: InboxItemId; action: QueueAction }>):
|
||||
Promise<RpcResponse<{ accepted: true }>>
|
||||
|
||||
/** Stops: clears both FIFOs + aborts the current step (1:1 with agent.cancel). */
|
||||
cancel(request: RpcRequest<{ sessionId: SessionId }>): Promise<RpcResponse<{ accepted: true }>>
|
||||
|
||||
}
|
||||
|
||||
@@ -20,6 +20,6 @@ export interface SkillEntry {
|
||||
|
||||
/** Skill-domain unary methods (the map key skill.* of RpcMethodMap). */
|
||||
export interface SkillsApi {
|
||||
/** Lists model-invocable skills for the addressed session's project root. */
|
||||
/** Lists skills usable by the browser's user-selected model-reference path. */
|
||||
list(request: RpcRequest<{ sessionId: SessionId }>): Promise<RpcResponse<{ skills: readonly SkillEntry[] }>>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user