docs(events): fix stale turn-mirror / tools-execute prose caught in review
Codex review of the interception-seams merge flagged current-state prose still describing removed/renamed surfaces: - packages/core/agent/src/types.ts module doc: the agent/* "transient emits" list still ended with "the turn boundaries" — corrected to state turn/step boundaries are durable session/event records, not agent/* emits, and to list the actual interception seams (prompt-submit/pre-step/request/step-result/ turn-continuation) + agent/session-start. - interception-seams RFC: "agent/turn-end fires and the ACP bridge settles" → the durable turn/end is appended and ACP settles off it (no turn mirror). - two proposed RFCs (acp-agent-client-protocol, optional-code-mode) named the pre-split `tools/execute` waterfall → the `tools/pre-execute`/`tools/post-execute` pair. Regenerated the cordis catalog (module-doc change). No code/behavior change.
This commit is contained in:
@@ -25,7 +25,7 @@ An agent was registered in the AgentRegistry and is ready to receive messages.
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:227`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:229`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
#### `agent/disposed` — emit
|
||||
|
||||
@@ -37,7 +37,7 @@ An agent was disposed and removed from the registry; its fiber and any in-flight
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:233`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:235`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
#### `agent/error` — emit
|
||||
|
||||
@@ -49,7 +49,7 @@ A step or turn errored. The loop reports a failure here (plus the logger) even w
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:352`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:354`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
#### `agent/pre-step` — serial
|
||||
|
||||
@@ -63,7 +63,7 @@ Serial (awaited in registration order), not a waterfall: a listener mutates the
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:299`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:301`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
#### `agent/prompt-submit` — waterfall
|
||||
|
||||
@@ -75,7 +75,7 @@ Waterfall: decide what happens to ONE drained queued message before it becomes a
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md) · [ContentBlock](../core-data-structures/core.md) · [MessageSource](../core-data-structures/core.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:309`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:311`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
#### `agent/queued` — emit
|
||||
|
||||
@@ -87,7 +87,7 @@ A message entered the agent's inbox (queued or steering). `source` is the resolv
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md) · [ContentBlock](../core-data-structures/core.md) · [MessageSource](../core-data-structures/core.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:246`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:248`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
#### `agent/request` — waterfall
|
||||
|
||||
@@ -99,7 +99,7 @@ Waterfall: mutate the fully-assembled GenerateOptions before the model call (hoo
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md) · [GenerateOptions](../core-data-structures/core.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:318`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:320`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
#### `agent/session-start` — emit
|
||||
|
||||
@@ -111,7 +111,7 @@ The agent's session lifecycle began, fired once before its first turn. `source`
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:259`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:261`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
#### `agent/status` — emit
|
||||
|
||||
@@ -123,7 +123,7 @@ Agent status changed (`idle` ⇄ `running`, or → `disposed`). Drive lifecycle
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:240`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:242`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
#### `agent/steering` — emit
|
||||
|
||||
@@ -135,7 +135,7 @@ Steering content was injected into a running turn.
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md) · [ContentBlock](../core-data-structures/core.md) · [MessageSource](../core-data-structures/core.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:346`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:348`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
#### `agent/step-result` — waterfall
|
||||
|
||||
@@ -147,7 +147,7 @@ Waterfall: post-process the assembled assistant Message before tool dispatch (va
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md) · [Message](../core-data-structures/core.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:324`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:326`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
#### `agent/stream-chunk` — emit
|
||||
|
||||
@@ -159,7 +159,7 @@ A raw StreamChunk arrived from the model (token-level UI/log feed).
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md) · [StreamChunk](../core-data-structures/llm-streaming.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:341`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:343`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
#### `agent/turn-continuation` — waterfall
|
||||
|
||||
@@ -171,7 +171,7 @@ Waterfall: override the turn-continuation decision via a typed ContinuationDecis
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:334`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:336`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
### `llm/*`
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ Add/reshape the interception seams so every one returns a small, seam-specifi
|
||||
|
||||
### Three load-bearing loop decisions
|
||||
|
||||
1. **Always open the turn first; a fully-blocked batch is a zero-step `rejected` turn.** `prompt-submit` fires AFTER `turn/start`, per message. A batch whose every prompt is blocked does NOT skip the turn — it opens a zero-step turn that closes with `rejected`. This one move resolves three problems at once: (1) turn-enclosure holds (every event has an open turn to live in); (2) `agent/turn-end` fires and the ACP bridge settles normally (mapping `rejected`→`cancelled`) instead of hanging; (3) the block reason is a durable in-turn fact. An `allow`'s `additionalContext` is `inject()`ed into this now-open turn.
|
||||
1. **Always open the turn first; a fully-blocked batch is a zero-step `rejected` turn.** `prompt-submit` fires AFTER `turn/start`, per message. A batch whose every prompt is blocked does NOT skip the turn — it opens a zero-step turn that closes with `rejected`. This one move resolves three problems at once: (1) turn-enclosure holds (every event has an open turn to live in); (2) the durable `turn/end` is appended and the ACP bridge settles normally off it (mapping `rejected`→`cancelled`) instead of hanging; (3) the block reason is a durable in-turn fact. An `allow`'s `additionalContext` is `inject()`ed into this now-open turn.
|
||||
|
||||
2. **Post-tool `additionalContext` is buffered and appended AFTER all `tool/result`s.** `content`/`feedback` shape the result `execute()` returns, but `additionalContext` is a SEPARATE `context/message`, and a single step can carry multiple tool calls. Appending context right after each result would interleave `result(c1) → context → result(c2)` and break tool-call/result adjacency. So `execute()` surfaces `additionalContext` on its `ToolExecutionResult`, and the loop buffers every per-call context for the step and appends them as `context/message`(s) only after every `tool/result` is appended.
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ This RFC has a hard prerequisite on [session persistence](../../implemented/arch
|
||||
|
||||
## Proposal
|
||||
|
||||
A new plugin package `@deepseek-ai/dsh-acp` — a client-driver / UI plugin, the structured analogue of `stdio-chat`. It is NOT a change to the loop and NOT an [capability seams](../../implemented/architecture/2026-06-13-capability-seams.md) interface/implementation/consumer capability split; it consumes the existing `agent/*` event taxonomy and the `tools/execute` waterfall.
|
||||
A new plugin package `@deepseek-ai/dsh-acp` — a client-driver / UI plugin, the structured analogue of `stdio-chat`. It is NOT a change to the loop and NOT an [capability seams](../../implemented/architecture/2026-06-13-capability-seams.md) interface/implementation/consumer capability split; it consumes the existing `agent/*` event taxonomy and the `tools/pre-execute`/`tools/post-execute` waterfalls.
|
||||
|
||||
It depends on the official `@agentclientprotocol/sdk` (the `AgentSideConnection` class) — Apache-2.0, actively versioned. The SDK declares a `zod` peer dependency and imports `zod/v4` at runtime, so `packages/ui/acp` must declare `zod` itself (per the workspace dependency constraints). This is the renamed successor to `@zed-industries/agent-client-protocol`, which is now deprecated on npm.
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ These are illustrations of the seam's reach, **not commitments** — the MVP shi
|
||||
|
||||
**3c. The single tool — `run_code`.** Registered normally in `ctx.tools` with one parameter `{ code: string (required) }`. Because it is an ordinary tool, the unchanged loop dispatches it through the normal path — this is the crux of "zero loop changes." Its `execute(args, exec)`:
|
||||
|
||||
1. Builds the SDK bindings. For each real tool, an async `invoke(callArgs)` that **checks `exec.signal?.aborted` (throwing if set) before and after** calling `ctx.tools.execute({ callId: <deterministic sub-id>, name, arguments: callArgs, agent: exec.agent, signal: exec.signal })`, then maps the resulting `ContentBlock[]` to a simplified `{ output, isError }` (text blocks for the MVP), and emits an observability event. The explicit abort check matters because `ctx.tools.execute()` *catches* thrown tool errors and converts them to `isError` results — without the check, an aborted sub-call would look like ordinary error data and the program would keep running instead of stopping. Sub-dispatch still flows through the `tools/execute` waterfall, so permission/sandbox/hook plugins apply to code-mode calls exactly as to native ones.
|
||||
1. Builds the SDK bindings. For each real tool, an async `invoke(callArgs)` that **checks `exec.signal?.aborted` (throwing if set) before and after** calling `ctx.tools.execute({ callId: <deterministic sub-id>, name, arguments: callArgs, agent: exec.agent, signal: exec.signal })`, then maps the resulting `ContentBlock[]` to a simplified `{ output, isError }` (text blocks for the MVP), and emits an observability event. The explicit abort check matters because `ctx.tools.execute()` *catches* thrown tool errors and converts them to `isError` results — without the check, an aborted sub-call would look like ordinary error data and the program would keep running instead of stopping. Sub-dispatch still flows through the `tools/pre-execute`/`tools/post-execute` waterfalls, so permission/sandbox/hook plugins apply to code-mode calls exactly as to native ones.
|
||||
2. Calls `ctx.codeRuntime.run({ code: args.code, sdk: bindings, signal: exec.signal })`.
|
||||
3. Surfaces the outcome. A *successful* run returns `[{ type: 'text', text: <console logs + return value> }]`. A *runtime-error* result cannot be reported by returning content, because a normal `ToolDefinition.execute()` returns only `Promise<ContentBlock[]>` and `ToolRegistry.execute()` hardcodes `isError: false` on any successful return — `isError: true` arises only from the registry's catch path. So on an error result the tool **throws a `CodeRunError extends HarnessError`** (`HarnessError` is exported from `dsh-llm`; the registry catch turns any throw into `isError: true` with the message as text, and a `HarnessError` additionally carries structured `{ name, code }`). An alternative — registering `run_code` handling as a `tools/execute` listener that returns a full `ToolExecutionResult` and can set `isError` directly — is noted; the throw is simpler and preferred.
|
||||
|
||||
|
||||
@@ -16,12 +16,14 @@
|
||||
* durability checkpoint. Answers "what happened, durably/replayably." A
|
||||
* consumer that wants the live transcript subscribes here.
|
||||
* - **`agent/*`** (this module) — the LIVE runtime surface. Always carries the
|
||||
* live `Agent`. Two shapes: INTERCEPTION waterfalls (`agent/request`,
|
||||
* `agent/step-result`, `agent/turn-continuation`) that mutate/veto, and
|
||||
* TRANSIENT emits (`agent/status`, `agent/stream-chunk`, `agent/error`,
|
||||
* `agent/created`/`agent/disposed`, `agent/queued`, `agent/steering`, and the
|
||||
* turn boundaries) that notify with the `Agent` in hand. Answers "right now,
|
||||
* with the agent object — intercept or observe."
|
||||
* live `Agent`. Two shapes: INTERCEPTION seams (the `agent/prompt-submit`/
|
||||
* `agent/request`/`agent/step-result`/`agent/turn-continuation` waterfalls and
|
||||
* the serial `agent/pre-step`) that mutate/veto, and TRANSIENT emits
|
||||
* (`agent/status`, `agent/stream-chunk`, `agent/error`, `agent/created`/
|
||||
* `agent/disposed`, `agent/queued`, `agent/steering`, `agent/session-start`)
|
||||
* that notify with the `Agent` in hand. Turn/step boundaries are NOT here —
|
||||
* they are durable `session/event` records. Answers "right now, with the agent
|
||||
* object — intercept or observe."
|
||||
* - **`tools/*`** (`@deepseek-ai/dsh-tools`) — the tool registry + execution.
|
||||
*
|
||||
* **The rule:** a durable, replayable fact is a SessionEvent; a live
|
||||
|
||||
Reference in New Issue
Block a user