chore(web): drop plan RPC residue and stale carriers after merge

Sweep the silently auto-merged leftovers of the superseded #587 wire layer:
the PlanModeState interface and planMode/setPlanMode entries in the sessions
API and rpc map, the fixture plan RPC spec, the composer.controls README
paragraph and spec assertions, the old-format plan-mode snapshot, and the
two Agent Notes written against the RPC design (to be rewritten for the
projection reattachment). ChatView/PendingCard keep the approval-only
pending rendering; QuestionComposer improvements ride along unchanged.
This commit is contained in:
imccyu
2026-07-28 20:28:43 +08:00
parent ae55771511
commit 2ecc89a186
14 changed files with 2 additions and 386 deletions
-2
View File
@@ -24,8 +24,6 @@ Workspace and Session lists are separate reconnect baselines. `workspace.create`
The `command.*` and `skill.*` domains expose the host command registry and skill catalog to clients. Every method addresses one session's agent by `sessionId` (a served session always has an Agent; `command.*` resumes cold sessions through the same path as `session.*`, while `skill.list` resolves the project root from the session header without touching the Agent registry). `command.execute` runs a slash-command line host-side with pure admission semantics: the response reports whether the line resolved to a handler plus the minted lifecycle `commandId` when it did (correlating the acknowledgment with the flow node), while the outcome rides the durably logged `command/run`/`command/done` lifecycle pair broadcast on the mux stream; the carrier's request signal cancels the running handler. `host/commands-changed` is the catalog invalidation frame: clients refetch `command.list` instead of diffing.
Plan mode uses two unary methods instead of deriving current state from a history page: `session.planMode` returns the committed state plus any boundary-pending selection, and `session.setPlanMode` records a selection and returns the same authoritative shape. A present `pending` target must differ from `active`; a net-zero service cleanup intent projects as `{ active }`, and the wire schema rejects equal values. Both methods return `null` when the optional host service is absent; `null` is capability absence, while `{ active: false }` is a supported inactive session. Committed changes still arrive through the raw logged `plan/mode` session event. `session.prompt` may carry a `planMode` target so the host records that selection immediately before accepting the prompt; it fails when the capability is absent and restores the prior target after a synchronous prompt rejection.
## Carrier layer (`/client` + root)
`AbstractApiClient` holds every protocol invariant — rpcId minting, envelope wrap/unwrap, zod parsing, SSE frame decoding, unary timeout, microtask-batched envelope observation (`subscribeEnvelopes`) — while platform subclasses supply only the `doFetch` transport aspect. `InProcessApiClient` over `toFetchHandler(api)` is the isomorphic point: the full wire serialization/validation path with no network, used by `dsh -p` headless.
@@ -24,8 +24,6 @@ export interface RpcMethodMap {
'session.selectModel': SessionsApi['selectModel']
'session.prompt': SessionsApi['prompt']
'session.cancel': SessionsApi['cancel']
'session.planMode': SessionsApi['planMode']
'session.setPlanMode': SessionsApi['setPlanMode']
'host.describe': HostApi['describe']
'host.pickDirectory': HostApi['pickDirectory']
'host.openPath': HostApi['openPath']
+2 -35
View File
@@ -145,16 +145,6 @@ export interface SessionSummary {
cwd?: string
}
/**
* Plan collaboration state exposed to clients. `active` is the logged state
* shaping the current request; `pending`, when present, is the user's
* next-boundary selection and differs from `active`.
*/
export interface PlanModeState {
active: boolean
pending?: boolean
}
/** Session-domain unary methods (the map keys session.* of RpcMethodMap). */
export interface SessionsApi {
/** Lists persisted sessions (updatedAt descending). v1 returns everything; cursor is a reserved seat, unimplemented. */
@@ -204,33 +194,10 @@ export interface SessionsApi {
}>):
Promise<RpcResponse<{ selected: ModelTarget }>>
/**
* Sends a message. `content` is core's ContentBlock[] verbatim and `mode`
* maps 1:1 — queue→send, steer→steer. An optional `planMode` target is
* admitted atomically with the prompt.
*/
prompt(request: RpcRequest<{
sessionId: SessionId
mode: 'queue' | 'steer'
content: ContentBlock[]
planMode?: boolean
}>):
/** Sends a message. content is core's ContentBlock[] verbatim; mode maps 1:1 — queue→send, steer→steer. */
prompt(request: RpcRequest<{ sessionId: SessionId; mode: 'queue' | 'steer'; content: ContentBlock[] }>):
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 }>>
/**
* Reads plan collaboration state. `null` means the host did not compose the
* optional plan-mode service; it is distinct from inactive state.
*/
planMode(request: RpcRequest<{ sessionId: SessionId }>): Promise<RpcResponse<PlanModeState | null>>
/**
* Selects plan collaboration state for the next model-request boundary.
* The returned state exposes the still-committed value and pending target;
* `null` means plan mode is unavailable on this host.
*/
setPlanMode(request: RpcRequest<{ sessionId: SessionId; active: boolean }>):
Promise<RpcResponse<PlanModeState | null>>
}
@@ -45,8 +45,6 @@ function scriptedApi(overrides: {
}),
prompt: r => ok(r, { accepted: true as const }),
cancel: r => ok(r, { accepted: true as const }),
planMode: r => ok(r, null),
setPlanMode: r => ok(r, null),
...overrides.sessions,
},
host: {