refactor: command.execute degrades to pure admission; composer notice channel retired

The wire response now carries only the matched bit — CommandExecuteResult
is deleted from the api, schema, and client mirrors (pre-release, no shim);
outcomes ride the durably logged command/run/command/done pair broadcast on
the mux stream and render as flow nodes. ui-command's runDetached→noticeFor
outcome routing is retired: admitted commands surface nothing through the
composer, while admission misses (matched:false, syntax feedback) and
transport failures keep their immediate notice. The connection fixture
mirrors the host: an admitted command appends the lifecycle pair to the
session log instead of returning result text.
This commit is contained in:
imccyu
2026-07-27 23:06:49 +08:00
parent ba928c5517
commit 4ddec0ba2f
17 files changed
+110 -90

No files matched your search

@@ -7,7 +7,7 @@ import { z } from 'zod'
import type { RequestPayload, ResponseValue } from './rpc-map.ts'
import type { Wire } from './rpc.schema.ts'
import { sessionIdSchema } from './sessions.schema.ts'
import type { CommandDescriptor, CommandExecuteResult } from './commands.ts'
import type { CommandDescriptor } from './commands.ts'
/** CommandDescriptor row of command.list. */
export const commandDescriptorSchema = z.object({
@@ -32,14 +32,7 @@ export const commandExecuteRequestSchema = z.object({
line: z.string(),
}) satisfies z.ZodType<Wire<RequestPayload<'command.execute'>>>
/** Detached command outcome (result slot of command.execute's value). */
export const commandExecuteResultSchema = z.object({
kind: z.union([z.literal('success'), z.literal('error')]),
text: z.string().optional(),
}) satisfies z.ZodType<Wire<CommandExecuteResult>>
/** command.execute response value (matched=false carries no result). */
/** command.execute response value: pure admission — outcomes ride the logged lifecycle events, never this response. */
export const commandExecuteValueSchema = z.object({
matched: z.boolean(),
result: commandExecuteResultSchema.optional(),
}) satisfies z.ZodType<Wire<ResponseValue<'command.execute'>>>
+8 -11
View File
@@ -22,12 +22,6 @@ export interface CommandDescriptor {
readonly input?: { readonly hint: string }
}
/** Detached command outcome rendered directly by the requesting client. */
export interface CommandExecuteResult {
readonly kind: 'success' | 'error'
readonly text?: string
}
/** Command-domain unary methods (the map keys command.* of RpcMethodMap). */
export interface CommandsApi {
/**
@@ -38,11 +32,14 @@ export interface CommandsApi {
/**
* Parses and executes one slash-command line against the addressed agent
* without sending it to the model. matched=false when syntax or name does
* not resolve (the client falls back to its default sink). The signal rides
* beside the request, never on the wire: the fetch carrier's request signal
* cancels the running handler.
* without sending it to the model — pure admission semantics. matched=false
* when syntax or name does not resolve (the client falls back to its
* default sink). The handler's outcome does NOT ride the response: the host
* executor durably logs the lifecycle (`command/run`/`command/done`), which
* broadcasts on the mux stream and renders as a persistent flow node. The
* signal rides beside the request, never on the wire: the fetch carrier's
* request signal cancels the running handler.
*/
execute(request: RpcRequest<{ sessionId: SessionId; line: string }>, signal: AbortSignal):
Promise<RpcResponse<{ matched: boolean; result?: CommandExecuteResult }>>
Promise<RpcResponse<{ matched: boolean }>>
}
+1 -1
View File
@@ -28,7 +28,7 @@ export interface ApiProxy {
export type { HistoryEntry, SessionProjectionsBlock, SessionsApi, SessionSummary } from './sessions.ts'
export type { HostApi } from './host.ts'
export type { WorkspaceApi, WorkspaceId, WorkspaceView } from './workspace.ts'
export type { CommandsApi, CommandDescriptor, CommandExecuteResult } from './commands.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 { ApprovalResponsePayload } from './approvals.ts'