refactor: brand the command lifecycle pairing id as CommandId

commandId crosses three boundaries (session log, wire admission response,
client flow pairing), so per the branded-id rule it becomes
Branded<'CommandId'>, declared in a new pure @deepseek-ai/dsh-commands/brand
outlet (the dsh-llm/brand shape: type + constructor, no Context merges, so
wire and client programs can name it without loading the host plugin). The
event payloads, CommandExecution, and the executor mint carry the brand; the
wire schema gains commandIdSchema as the domain's single brand-cast point
(the approvals precedent); CommandNode and the fixture's fabrication cast
follow type-only.
This commit is contained in:
imccyu
2026-07-28 01:37:45 +08:00
parent 4d7b30ab72
commit 755ce21334
19 changed files with 91 additions and 18 deletions

View File

@@ -4,6 +4,7 @@
*/
import { z } from 'zod'
import type { CommandId } from '@deepseek-ai/dsh-commands/brand'
import type { RequestPayload, ResponseValue } from './rpc-map.ts'
import type { Wire } from './rpc.schema.ts'
import { sessionIdSchema } from './sessions.schema.ts'
@@ -32,8 +33,11 @@ export const commandExecuteRequestSchema = z.object({
line: z.string(),
}) satisfies z.ZodType<Wire<RequestPayload<'command.execute'>>>
/** CommandId: one brand cast after shape validation (the only cast point in this domain). */
export const commandIdSchema = z.string().min(1) as unknown as z.ZodType<CommandId>
/** command.execute response value: pure admission — outcomes ride the logged lifecycle events; commandId (present exactly when matched) correlates with them. */
export const commandExecuteValueSchema = z.object({
matched: z.boolean(),
commandId: z.string().min(1).optional(),
commandId: commandIdSchema.optional(),
}) satisfies z.ZodType<Wire<ResponseValue<'command.execute'>>>

View File

@@ -5,6 +5,7 @@
* together), so there is no agent-less surface on this wire.
*/
import type { CommandId } from '@deepseek-ai/dsh-commands/brand'
import type { SessionId } from '@deepseek-ai/dsh-session/types'
import type { RpcRequest, RpcResponse } from './rpc.ts'
@@ -43,5 +44,5 @@ export interface CommandsApi {
* wire: the fetch carrier's request signal cancels the running handler.
*/
execute(request: RpcRequest<{ sessionId: SessionId; line: string }>, signal: AbortSignal):
Promise<RpcResponse<{ matched: boolean; commandId?: string }>>
Promise<RpcResponse<{ matched: boolean; commandId?: CommandId }>>
}

View File

@@ -1,3 +1,4 @@
import { CommandId } from '@deepseek-ai/dsh-commands/brand'
import { describe, expect, it, vi } from 'vitest'
import type { ApiProxy, HostFrame, MuxFrame } from '../src/api/index.ts'
import type { ClientResponse, RpcMessage, RpcReceipt, RpcRequest } from '../src/api/rpc.ts'
@@ -91,7 +92,7 @@ function fakeApi(overrides: Partial<{ muxFrames: MuxFrame[]; hostFrames: HostFra
return { rpcId: request.rpcId, result: { ok: false, error: { code: 'cancelled', message: 'aborted', details: {} } } }
}
if (request.payload.line.startsWith('/plan')) {
return { rpcId: request.rpcId, result: { ok: true, value: { matched: true, commandId: 'cmd-x' } } }
return { rpcId: request.rpcId, result: { ok: true, value: { matched: true, commandId: CommandId('cmd-x') } } }
}
return { rpcId: request.rpcId, result: { ok: true, value: { matched: false } } }
},