docs(agent): document next-step acceptance window
This commit is contained in:
@@ -20,10 +20,14 @@ sequenceDiagram
|
||||
Agent-->>SDK: <code>agent/inbox/enqueue</code>
|
||||
Agent->>Driver: queued work wakes driver
|
||||
Driver-->>SDK: <code>agent/status</code> running
|
||||
Driver->>Session: <code>turn/start</code>
|
||||
Note over Agent,Driver: next-step acceptance window opens
|
||||
Driver->>Hooks: <code>agent/prompt-submit</code> waterfall
|
||||
Hooks-->>Driver: authoritative allow, block, or add context
|
||||
Driver->>Session: <code>user/message</code> or rejected <code>turn/end</code>
|
||||
alt prompt blocked or admission failed
|
||||
Driver-->>Driver: close window and keep caller-staged next-step input pending
|
||||
else prompt allowed
|
||||
Driver->>Session: <code>turn/start</code>
|
||||
Driver->>Session: <code>user/message</code>
|
||||
Driver->>Prompt: <code>system-prompt/assemble</code> waterfall
|
||||
Driver-->>Driver: <code>agent/step</code> serial checkpoint
|
||||
Driver->>Session: <code>step/start</code>
|
||||
@@ -53,7 +57,9 @@ sequenceDiagram
|
||||
Driver->>Session: <code>step/end</code>
|
||||
Driver->>Hooks: <code>agent/turn-stopping</code> serial terminal checkpoint
|
||||
end
|
||||
Note over Agent,Driver: next-step acceptance window closes
|
||||
Driver->>Session: <code>turn/end</code>
|
||||
end
|
||||
Driver-->>SDK: <code>agent/status</code> idle
|
||||
```
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/architecture.md
|
||||
architecture.md: e293d3f3996210fd6b4d9784379eef58cd6c9f0b
|
||||
architecture.zh.md: 9760511e979fa9bb20b812fbbbefcefa09565c55
|
||||
architecture.md: 702e81b09e4671bb46d7ca2a6e7ae0f8ceeeaf14
|
||||
architecture.zh.md: 4c7fe539ef5e9c96a85207a8531bc3de7743b140
|
||||
|
||||
@@ -76,10 +76,12 @@ choose declarative identity and fresh/resume path
|
||||
-> enable driving -> agent/session-start(source) -> start driver
|
||||
forever:
|
||||
wait for a queued message
|
||||
claimed message -> agent/prompt-submit
|
||||
blocked prompt -> park without opening a turn
|
||||
claim message -> emit agent/status(running) if starting an interval
|
||||
open the next-step acceptance window
|
||||
-> agent/prompt-submit
|
||||
blocked or failed prompt -> close the window without opening a turn
|
||||
caller-staged context and steering remain pending for a later admitted turn
|
||||
allowed prompt:
|
||||
emit agent/status(running)
|
||||
'turn/start'
|
||||
append prompt + additional contexts as separate 'user/message' events
|
||||
STEP loop:
|
||||
@@ -100,6 +102,7 @@ forever:
|
||||
'step/end'
|
||||
continue for tools or steering unless a result concluded the turn
|
||||
otherwise agent/turn-stopping -> drain -> continue only for steering
|
||||
close the next-step acceptance window
|
||||
'turn/end' -> agent/settled
|
||||
start the next waking queued message, or emit agent/status(idle)
|
||||
|
||||
@@ -110,7 +113,7 @@ idle inject:
|
||||
|
||||
Each step assembles ordered prompt sections, tool schemas, and variables; unknown references fail the turn. `dsh-system-prompt` owns identity and persona; the loop supplies `provider`, `model`, and `cwd` ([prompt ownership](../.agents/notes/implemented/architecture/2026-07-05-prompt-variables-and-tool-guidance-ownership.md)).
|
||||
|
||||
Tool-time context—active-turn `inject()` and post-tool `additionalContexts`—settles after results; steering drains there and requests another step. Idle `inject()` appends immediately without changing turn numbers; persistence drains eagerly.
|
||||
Admission-time and active-turn `inject()` stage for the next step; post-tool `additionalContexts` settles after results. Steering shares that staging boundary and requests another step. Idle `inject()` appends immediately without changing turn numbers; persistence drains eagerly.
|
||||
|
||||
Pruning precedes summaries; overflow retries require durable progress. Recovery uses `agent/request-error` after the failed step and before turn close. Its policy calls `agent.retry()` to schedule one retry turn; cancellation wins ([compaction](../.agents/notes/implemented/architecture/2026-07-10-after-call-compaction-pressure-and-overflow-recovery.md), [retry](../.agents/notes/implemented/architecture/2026-06-21-bounded-llm-request-recovery.md)).
|
||||
|
||||
|
||||
@@ -76,10 +76,12 @@ choose declarative identity and fresh/resume path
|
||||
-> enable driving -> agent/session-start(source) -> start driver
|
||||
forever:
|
||||
wait for a queued message
|
||||
claimed message -> agent/prompt-submit
|
||||
blocked prompt -> park without opening a turn
|
||||
claim message -> emit agent/status(running) if starting an interval
|
||||
open the next-step acceptance window
|
||||
-> agent/prompt-submit
|
||||
blocked or failed prompt -> close the window without opening a turn
|
||||
caller-staged context and steering remain pending for a later admitted turn
|
||||
allowed prompt:
|
||||
emit agent/status(running)
|
||||
'turn/start'
|
||||
append prompt + additional contexts as separate 'user/message' events
|
||||
STEP loop:
|
||||
@@ -100,6 +102,7 @@ forever:
|
||||
'step/end'
|
||||
continue for tools or steering unless a result concluded the turn
|
||||
otherwise agent/turn-stopping -> drain -> continue only for steering
|
||||
close the next-step acceptance window
|
||||
'turn/end' -> agent/settled
|
||||
start the next waking queued message, or emit agent/status(idle)
|
||||
|
||||
@@ -110,7 +113,7 @@ idle inject:
|
||||
|
||||
每个步骤都会组装有序提示词片段、工具 schema 和变量;未知引用会使该轮次失败。`dsh-system-prompt` 负责身份和角色设定;循环提供 `provider`、`model` 和 `cwd`([提示词归属](../.agents/notes/implemented/architecture/2026-07-05-prompt-variables-and-tool-guidance-ownership.md))。
|
||||
|
||||
工具执行阶段的上下文,包括活跃轮次内的 `inject()` 和工具执行后的 `additionalContexts`,会在结果记录完毕后落定;steering 在此排空并请求再执行一个步骤。空闲状态下的 `inject()` 会立即追加,且不改变轮次编号;持久化层会尽快排空。
|
||||
接纳期间和活跃轮次内的 `inject()` 会为下一步骤暂存;工具执行后的 `additionalContexts` 会在结果记录完毕后落定。steering 与其共用这一暂存边界,并请求再执行一个步骤。空闲状态下的 `inject()` 会立即追加,且不改变轮次编号;持久化层会尽快排空。
|
||||
|
||||
裁剪先于摘要;溢出重试必须取得持久进展。恢复会在失败步骤关闭后、轮次关闭前使用 `agent/request-error`。其策略调用 `agent.retry()` 安排一个重试轮次;取消优先([压缩](../.agents/notes/implemented/architecture/2026-07-10-after-call-compaction-pressure-and-overflow-recovery.md)、[重试](../.agents/notes/implemented/architecture/2026-06-21-bounded-llm-request-recovery.md))。
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ Effective broad cancellation was requested, before queued/outbox work is cleared
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md) · [AgentCancelCause](../core-data-structures/core.md) · [Scoped](../core-data-structures/scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:294`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:309`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
### `agent/created` — emit
|
||||
|
||||
@@ -54,7 +54,7 @@ A fully configured agent and live session were published. Setup is composition-o
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md) · [Scoped](../core-data-structures/scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:236`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:248`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
### `agent/disposed` — emit
|
||||
|
||||
@@ -74,7 +74,7 @@ An agent left the registry; AgentLoop emits this after driver quiescence and sco
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md) · [Scoped](../core-data-structures/scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:245`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:257`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
### `agent/error` — emit
|
||||
|
||||
@@ -96,7 +96,7 @@ A step or turn errored. The machine reports a failure here (plus the logger) eve
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md) · [Scoped](../core-data-structures/scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:405`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:420`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
### `agent/inbox/dequeue` — emit
|
||||
|
||||
@@ -117,7 +117,7 @@ The driver claimed one item out of the inbox: a queued item at a turn boundary,
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md) · [AgentMessage](../core-data-structures/core.md) · [Scoped](../core-data-structures/scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:272`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:287`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
### `agent/inbox/discard` — emit
|
||||
|
||||
@@ -140,26 +140,29 @@ Pending inbox items were dropped without delivering them, so every enqueued id r
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md) · [AgentMessage](../core-data-structures/core.md) · [Scoped](../core-data-structures/scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:284`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:299`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
### `agent/inbox/enqueue` — emit
|
||||
|
||||
An item entered the queued or steering inbox.
|
||||
An item entered the queued or steering inbox. `placement` is the acceptance-time routing result; listeners must not reconstruct it from later agent or session state.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* An item entered the queued or steering inbox.
|
||||
* An item entered the queued or steering inbox. `placement` is the
|
||||
* acceptance-time routing result; listeners must not reconstruct it from
|
||||
* later agent or session state.
|
||||
* @param agent - the owning agent.
|
||||
* @param message - accepted content, source, and correlation identity.
|
||||
* @param placement - resolved queued or steering placement.
|
||||
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
|
||||
* @mode emit
|
||||
*/
|
||||
'agent/inbox/enqueue'(this: Scoped<Agent>, agent: Agent, message: AgentMessage): void
|
||||
'agent/inbox/enqueue'(this: Scoped<Agent>, agent: Agent, message: AgentMessage, placement: InboxPlacement): void
|
||||
```
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md) · [AgentMessage](../core-data-structures/core.md) · [Scoped](../core-data-structures/scope.md)
|
||||
Types: [Agent](../core-data-structures/core.md) · [AgentMessage](../core-data-structures/core.md) · [InboxPlacement](../core-data-structures/core.md) · [Scoped](../core-data-structures/scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:262`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:277`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
### `agent/prompt-submit` — waterfall
|
||||
|
||||
@@ -183,7 +186,7 @@ Allow, rewrite, or block one claimed prompt before it becomes a user message or
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md) · [ContentBlock](../core-data-structures/core.md) · [MessageSource](../core-data-structures/core.md) · [PromptDecision](../core-data-structures/core.md) · [Scoped](../core-data-structures/scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:322`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:337`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
### `agent/request` — waterfall
|
||||
|
||||
@@ -207,7 +210,7 @@ Replace the frozen call configuration. `await next()` yields the config the mach
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md) · [LlmCallConfig](../core-data-structures/core.md) · [Scoped](../core-data-structures/scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:348`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:363`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
### `agent/request-error` — waterfall
|
||||
|
||||
@@ -233,7 +236,7 @@ Handle a model-request failure after its failed step has closed but before the f
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md) · [LlmFailure](../core-data-structures/llm-streaming.md) · [RequestError](../core-data-structures/core.md) · [Scoped](../core-data-structures/scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:363`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:378`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
### `agent/session-start` — emit
|
||||
|
||||
@@ -255,7 +258,7 @@ The session lifecycle began, once before the first turn. Use `agent.inject()` to
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md) · [Scoped](../core-data-structures/scope.md) · [SessionStartSource](../core-data-structures/core.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:307`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:322`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
### `agent/settled` — emit
|
||||
|
||||
@@ -280,7 +283,7 @@ One drain chain reached its terminal turn: that turn's `turn/end` is already com
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md) · [Scoped](../core-data-structures/scope.md) · [SettleReason](../core-data-structures/core.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:392`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:407`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
### `agent/status` — emit
|
||||
|
||||
@@ -300,7 +303,7 @@ Agent status changed (`idle` ⇄ `running`). `send()` does not enter `running` s
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md) · [AgentStatus](../core-data-structures/core.md) · [Scoped](../core-data-structures/scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:254`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:266`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
### `agent/step` — serial
|
||||
|
||||
@@ -324,7 +327,7 @@ Awaited serial checkpoint before EVERY request of a turn is built (the first as
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md) · [Scoped](../core-data-structures/scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:335`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:350`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
### `agent/turn-stopping` — serial
|
||||
|
||||
@@ -350,7 +353,7 @@ The turn is about to close: the model owes no response (no live tool calls, no f
|
||||
|
||||
Types: [Agent](../core-data-structures/core.md) · [Scoped](../core-data-structures/scope.md)
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:378`](../../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:393`](../../packages/core/agent/src/types.ts)
|
||||
|
||||
## `agent-loop/*`
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/core-data-structures/core.md
|
||||
core.md: bc4288872a9b1e47a82c86b095c13ae9defc957b
|
||||
core.zh.md: abd1b7bd0aa5563e86cf652db354ad30e4fb74cc
|
||||
core.md: 855e4f6a041e62ef124d9b093332b5c23e7f9813
|
||||
core.zh.md: aebe0147d25836ad124d3957a50d3d10b45d634c
|
||||
|
||||
@@ -412,12 +412,18 @@ Source: [`packages/core/agent/src/types.ts`](../../packages/core/agent/src/types
|
||||
/**
|
||||
* Which inbox queue a {@link Agent.send} item joins:
|
||||
* - `next-turn` — the item becomes its own turn, claimed at a turn boundary.
|
||||
* - `next-step` — the item joins the active turn between steps as steering,
|
||||
* or, when no turn is active, is promoted per its `wakeup` flag.
|
||||
* - `next-step` — during prompt admission or an open turn, the item stages for
|
||||
* the next safe step boundary; otherwise it is promoted per its `wakeup`
|
||||
* flag.
|
||||
*/
|
||||
type SendTarget = 'next-turn' | 'next-step'
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
/** Resolved inbox placement reported when an accepted message is enqueued. */
|
||||
type InboxPlacement = 'queued' | 'steering'
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
/**
|
||||
* Options for the unified {@link Agent.send} primitive over the
|
||||
@@ -500,6 +506,12 @@ interface Agent {
|
||||
readonly session: Session
|
||||
/** The current lifecycle state, mirrored on every `agent/status` transition. */
|
||||
readonly status: AgentStatus
|
||||
/**
|
||||
* Whether a `next-step` send currently stages for prompt admission or the
|
||||
* open turn. Unlike {@link status}, this excludes admission exit and turn
|
||||
* settlement, when a waking `next-step` send becomes a queued follow-up.
|
||||
*/
|
||||
readonly acceptsNextStep: boolean
|
||||
/** Agent-scoped context; its contributions are agent-local, unwind on disposal, and reject registration afterward. */
|
||||
readonly ctx: Context
|
||||
|
||||
@@ -510,12 +522,13 @@ interface Agent {
|
||||
* - `next-turn` queues an item that becomes the sole ordinary message of its
|
||||
* own FIFO-ordered turn; `wakeup:true` wakes a
|
||||
* parked driver, while `wakeup:false` queues without waking.
|
||||
* - `next-step` with `wakeup:true` submits steering into the active turn
|
||||
* (idle falls back to a woken `next-turn`).
|
||||
* - `next-step` with `wakeup:true` stages steering during prompt admission
|
||||
* or an open turn; outside that window it falls back to a woken
|
||||
* `next-turn`.
|
||||
* - `next-step` with `wakeup:false` injects durable model-facing context
|
||||
* without running the model: an open turn stages it for the next safe log
|
||||
* position, while an idle injection appends it immediately without opening
|
||||
* a turn.
|
||||
* without running the model: admission or an open turn stages it for the
|
||||
* next safe log position, while an injection outside that window appends
|
||||
* immediately without opening a turn.
|
||||
* @param input - model-facing content and its producer provenance.
|
||||
* @param options - target queue and wakeup decision.
|
||||
* @returns the accepted message's {@link AgentMessageId}, stable across its `agent/inbox/*` events.
|
||||
@@ -546,12 +559,13 @@ interface Agent {
|
||||
followup(input: UserMessageData): AgentMessageId
|
||||
|
||||
/**
|
||||
* Submit steering into the running turn — the `next-step`/wakeup preset of
|
||||
* {@link send}. An open turn records it at the next steering checkpoint before
|
||||
* a request or stop decision. If the turn fails before that boundary, the
|
||||
* remainder stays staged without waking the agent; retry or a later prompt
|
||||
* takes it. Idle steering falls back to a woken follow-up turn, while
|
||||
* cancellation or disposal may discard pending steering.
|
||||
* Submit steering during prompt admission or an open turn — the
|
||||
* `next-step`/wakeup preset of {@link send}. It stages for the next steering
|
||||
* checkpoint before a request or stop decision. If the activity fails before
|
||||
* that boundary, the remainder stays staged without waking the agent; retry
|
||||
* or a later prompt takes it. Outside that window steering falls back to a
|
||||
* woken follow-up turn, while cancellation or disposal may discard pending
|
||||
* steering.
|
||||
* @param input - steering content and its producer provenance.
|
||||
* @returns the accepted message's {@link AgentMessageId}.
|
||||
*/
|
||||
@@ -559,9 +573,9 @@ interface Agent {
|
||||
|
||||
/**
|
||||
* Append model-facing context without running the model — the
|
||||
* `next-step`/no-wakeup preset of {@link send}. An open-turn injection stages
|
||||
* at the next safe log position; an idle injection appends immediately
|
||||
* without opening a turn.
|
||||
* `next-step`/no-wakeup preset of {@link send}. Admission or an open turn
|
||||
* stages it at the next safe log position; outside that window it appends
|
||||
* immediately without opening a turn.
|
||||
* @param input - injected context and its producer provenance.
|
||||
* @returns the accepted message's {@link AgentMessageId}.
|
||||
*/
|
||||
@@ -578,7 +592,7 @@ interface Agent {
|
||||
}
|
||||
```
|
||||
|
||||
`AgentStatus` is `'idle' | 'running'`, and `SessionId` is branded. Disposal removes the agent from the registry and emits `agent/disposed`; it is not a terminal status value. `running` describes the driver-wide drain interval and may span consecutive queued turns; it does not prove a turn is still open. `AgentOptions` is merge-extensible: core declares `provider?` and `model?` (dispatch requires both after `agent/request`). Persona belongs to `dsh-system-prompt`: an agent-scoped `deployment:persona` may shadow the global default.
|
||||
`AgentStatus` is `'idle' | 'running'`, and `SessionId` is branded. Disposal removes the agent from the registry and emits `agent/disposed`; it is not a terminal status value. `running` describes the driver-wide drain interval and may span consecutive queued turns; it does not prove a turn is still open. `acceptsNextStep` is the narrower routing predicate for callers that must choose between steering the current admission/turn and submitting a fresh admitted prompt. `AgentOptions` is merge-extensible: core declares `provider?` and `model?` (dispatch requires both after `agent/request`). Persona belongs to `dsh-system-prompt`: an agent-scoped `deployment:persona` may shadow the global default.
|
||||
|
||||
The cause is a TypeScript-enforced same-process input. An active `TurnCancellation` holder copies its discriminant into the runtime-only `AbortSignal.reason` and is retired before `turn/end` publication; the frozen `AbortSignal.reason` remains readable after that retirement. Only the loop reads the cause (`user`, `parent`, or lifecycle-only `disposed`) back off its own machine-private signal at settlement — there is no public reader, and a signal grants cooperating listeners no classification authority. Durable `turn/end` retains the coarse `{ kind: 'aborted' }` outcome; request provenance would require a separate durable event rather than overloading the terminal result.
|
||||
|
||||
|
||||
@@ -420,12 +420,18 @@ type SessionEvent<T extends SessionEventType = SessionEventType> = {
|
||||
/**
|
||||
* Which inbox queue a {@link Agent.send} item joins:
|
||||
* - `next-turn` — the item becomes its own turn, claimed at a turn boundary.
|
||||
* - `next-step` — the item joins the active turn between steps as steering,
|
||||
* or, when no turn is active, is promoted per its `wakeup` flag.
|
||||
* - `next-step` — during prompt admission or an open turn, the item stages for
|
||||
* the next safe step boundary; otherwise it is promoted per its `wakeup`
|
||||
* flag.
|
||||
*/
|
||||
type SendTarget = 'next-turn' | 'next-step'
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
/** Resolved inbox placement reported when an accepted message is enqueued. */
|
||||
type InboxPlacement = 'queued' | 'steering'
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
/**
|
||||
* Options for the unified {@link Agent.send} primitive over the
|
||||
@@ -508,6 +514,12 @@ interface Agent {
|
||||
readonly session: Session
|
||||
/** The current lifecycle state, mirrored on every `agent/status` transition. */
|
||||
readonly status: AgentStatus
|
||||
/**
|
||||
* Whether a `next-step` send currently stages for prompt admission or the
|
||||
* open turn. Unlike {@link status}, this excludes admission exit and turn
|
||||
* settlement, when a waking `next-step` send becomes a queued follow-up.
|
||||
*/
|
||||
readonly acceptsNextStep: boolean
|
||||
/** Agent-scoped context; its contributions are agent-local, unwind on disposal, and reject registration afterward. */
|
||||
readonly ctx: Context
|
||||
|
||||
@@ -518,12 +530,13 @@ interface Agent {
|
||||
* - `next-turn` queues an item that becomes the sole ordinary message of its
|
||||
* own FIFO-ordered turn; `wakeup:true` wakes a
|
||||
* parked driver, while `wakeup:false` queues without waking.
|
||||
* - `next-step` with `wakeup:true` submits steering into the active turn
|
||||
* (idle falls back to a woken `next-turn`).
|
||||
* - `next-step` with `wakeup:true` stages steering during prompt admission
|
||||
* or an open turn; outside that window it falls back to a woken
|
||||
* `next-turn`.
|
||||
* - `next-step` with `wakeup:false` injects durable model-facing context
|
||||
* without running the model: an open turn stages it for the next safe log
|
||||
* position, while an idle injection appends it immediately without opening
|
||||
* a turn.
|
||||
* without running the model: admission or an open turn stages it for the
|
||||
* next safe log position, while an injection outside that window appends
|
||||
* immediately without opening a turn.
|
||||
* @param input - model-facing content and its producer provenance.
|
||||
* @param options - target queue and wakeup decision.
|
||||
* @returns the accepted message's {@link AgentMessageId}, stable across its `agent/inbox/*` events.
|
||||
@@ -554,12 +567,13 @@ interface Agent {
|
||||
followup(input: UserMessageData): AgentMessageId
|
||||
|
||||
/**
|
||||
* Submit steering into the running turn — the `next-step`/wakeup preset of
|
||||
* {@link send}. An open turn records it at the next steering checkpoint before
|
||||
* a request or stop decision. If the turn fails before that boundary, the
|
||||
* remainder stays staged without waking the agent; retry or a later prompt
|
||||
* takes it. Idle steering falls back to a woken follow-up turn, while
|
||||
* cancellation or disposal may discard pending steering.
|
||||
* Submit steering during prompt admission or an open turn — the
|
||||
* `next-step`/wakeup preset of {@link send}. It stages for the next steering
|
||||
* checkpoint before a request or stop decision. If the activity fails before
|
||||
* that boundary, the remainder stays staged without waking the agent; retry
|
||||
* or a later prompt takes it. Outside that window steering falls back to a
|
||||
* woken follow-up turn, while cancellation or disposal may discard pending
|
||||
* steering.
|
||||
* @param input - steering content and its producer provenance.
|
||||
* @returns the accepted message's {@link AgentMessageId}.
|
||||
*/
|
||||
@@ -567,9 +581,9 @@ interface Agent {
|
||||
|
||||
/**
|
||||
* Append model-facing context without running the model — the
|
||||
* `next-step`/no-wakeup preset of {@link send}. An open-turn injection stages
|
||||
* at the next safe log position; an idle injection appends immediately
|
||||
* without opening a turn.
|
||||
* `next-step`/no-wakeup preset of {@link send}. Admission or an open turn
|
||||
* stages it at the next safe log position; outside that window it appends
|
||||
* immediately without opening a turn.
|
||||
* @param input - injected context and its producer provenance.
|
||||
* @returns the accepted message's {@link AgentMessageId}.
|
||||
*/
|
||||
@@ -586,7 +600,7 @@ interface Agent {
|
||||
}
|
||||
```
|
||||
|
||||
`AgentStatus` 为 `'idle' | 'running'`,`SessionId` 是品牌类型。dispose(资源释放)会把 agent 从注册表移除并发出 `agent/disposed`;它不是一个终态 status 值。`running` 描述整个驱动器的排空区间,可能跨越连续的排队轮次;它不能证明某个轮次仍然打开。`AgentOptions` 可合并扩展:core 声明 `provider?` 与 `model?`(在 `agent/request` 后,分发要求两者都存在)。Persona 归 `dsh-system-prompt` 所有:agent 作用域的 `deployment:persona` 可以遮蔽全局默认值。
|
||||
`AgentStatus` 为 `'idle' | 'running'`,`SessionId` 是品牌类型。dispose(资源释放)会把 agent 从注册表移除并发出 `agent/disposed`;它不是一个终态 status 值。`running` 描述整个驱动器的排空区间,可能跨越连续的排队轮次;它不能证明某个轮次仍然打开。对于需要在把输入作为 steering 加入当前提示词准入/轮次,还是提交为一个新的待准入提示词之间做选择的调用方,`acceptsNextStep` 才是更窄且准确的路由判断条件。`AgentOptions` 可合并扩展:core 声明 `provider?` 与 `model?`(在 `agent/request` 后,分发要求两者都存在)。Persona 归 `dsh-system-prompt` 所有:agent 作用域的 `deployment:persona` 可以遮蔽全局默认值。
|
||||
|
||||
cause 是由 TypeScript 强制约束的同进程输入。活跃的 `TurnCancellation` 持有者会把其判别字段复制到仅运行时的 `AbortSignal.reason`,并在发布 `turn/end` 前退役;冻结后的 `AbortSignal.reason` 仍可读取。只有 loop 会在结算时从自己机器私有的 signal 上读回 cause(`user`、`parent` 或仅用于生命周期的 `disposed`)——不存在公开的读取器,signal 也不授予协作监听器任何分类权限。持久 `turn/end` 保留粗粒度 `{ kind: 'aborted' }` 结果;若需记录请求 provenance,应使用单独的持久事件,而不是让终态结果承担额外含义。
|
||||
|
||||
|
||||
@@ -8,21 +8,21 @@ This matrix shows which packages dispatch each harness-owned event and which pac
|
||||
| Event | Mode | Declared in | Dispatchers | Listeners |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `agent-loop/config-start-failed` | `emit` | [`packages/core/agent-loop/src/index.ts:140`](../packages/core/agent-loop/src/index.ts) | [`agent-loop`](../packages/core/agent-loop) (`events.dispatch`) | [`tui`](../packages/ui/tui) |
|
||||
| `agent/cancel-requested` | `emit` | [`packages/core/agent/src/types.ts:294`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`goal-session`](../packages/goal/goal-session) |
|
||||
| `agent/created` | `emit` | [`packages/core/agent/src/types.ts:236`](../packages/core/agent/src/types.ts) | [`agent`](../packages/core/agent) (`events.dispatch`) | [`goal-session`](../packages/goal/goal-session), [`tui`](../packages/ui/tui) |
|
||||
| `agent/disposed` | `emit` | [`packages/core/agent/src/types.ts:245`](../packages/core/agent/src/types.ts) | [`agent`](../packages/core/agent) (`events.dispatch`) | [`agent-loop`](../packages/core/agent-loop), [`goal-session`](../packages/goal/goal-session), [`tui`](../packages/ui/tui) |
|
||||
| `agent/error` | `emit` | [`packages/core/agent/src/types.ts:405`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | `apiproxy`, [`goal-session`](../packages/goal/goal-session), [`tui`](../packages/ui/tui) |
|
||||
| `agent/inbox/dequeue` | `emit` | [`packages/core/agent/src/types.ts:272`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`agent`](../packages/core/agent), `apiproxy`, [`tui`](../packages/ui/tui) |
|
||||
| `agent/inbox/discard` | `emit` | [`packages/core/agent/src/types.ts:284`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`agent`](../packages/core/agent), `apiproxy`, [`tui`](../packages/ui/tui) |
|
||||
| `agent/inbox/enqueue` | `emit` | [`packages/core/agent/src/types.ts:262`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`agent`](../packages/core/agent), `apiproxy`, [`goal-session`](../packages/goal/goal-session) |
|
||||
| `agent/prompt-submit` | `waterfall` | [`packages/core/agent/src/types.ts:322`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`goal-session`](../packages/goal/goal-session), [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`repeat-tool-guard`](../packages/guard/repeat-tool-guard), [`tui`](../packages/ui/tui) |
|
||||
| `agent/request` | `waterfall` | [`packages/core/agent/src/types.ts:348`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`agent`](../packages/core/agent) |
|
||||
| `agent/request-error` | `waterfall` | [`packages/core/agent/src/types.ts:363`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`compact-basic`](../packages/compact/compact-basic), [`llm-retry`](../packages/llm/llm-retry) |
|
||||
| `agent/session-start` | `emit` | [`packages/core/agent/src/types.ts:307`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `agent/settled` | `emit` | [`packages/core/agent/src/types.ts:392`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`compact-basic`](../packages/compact/compact-basic), [`llm-retry`](../packages/llm/llm-retry) |
|
||||
| `agent/status` | `emit` | [`packages/core/agent/src/types.ts:254`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`agent`](../packages/core/agent), `apiproxy`, [`goal-session`](../packages/goal/goal-session), [`tui`](../packages/ui/tui) |
|
||||
| `agent/step` | `serial` | [`packages/core/agent/src/types.ts:335`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`serial`) | [`compact-basic`](../packages/compact/compact-basic), [`plan-mode`](../packages/plan/plan-mode), [`session-checkpoint-policy`](../packages/session-persistence/session-checkpoint-policy), [`time-context`](../packages/context/time-context), [`tool-skill`](../packages/skill/tool-skill), [`user-approval`](../packages/ui/user-approval), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `agent/turn-stopping` | `serial` | [`packages/core/agent/src/types.ts:378`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`serial`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex) |
|
||||
| `agent/cancel-requested` | `emit` | [`packages/core/agent/src/types.ts:309`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`goal-session`](../packages/goal/goal-session) |
|
||||
| `agent/created` | `emit` | [`packages/core/agent/src/types.ts:248`](../packages/core/agent/src/types.ts) | [`agent`](../packages/core/agent) (`events.dispatch`) | [`goal-session`](../packages/goal/goal-session), [`tui`](../packages/ui/tui) |
|
||||
| `agent/disposed` | `emit` | [`packages/core/agent/src/types.ts:257`](../packages/core/agent/src/types.ts) | [`agent`](../packages/core/agent) (`events.dispatch`) | [`agent-loop`](../packages/core/agent-loop), [`goal-session`](../packages/goal/goal-session), [`tui`](../packages/ui/tui) |
|
||||
| `agent/error` | `emit` | [`packages/core/agent/src/types.ts:420`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | `apiproxy`, [`goal-session`](../packages/goal/goal-session), [`tui`](../packages/ui/tui) |
|
||||
| `agent/inbox/dequeue` | `emit` | [`packages/core/agent/src/types.ts:287`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`agent`](../packages/core/agent), `apiproxy`, [`tui`](../packages/ui/tui) |
|
||||
| `agent/inbox/discard` | `emit` | [`packages/core/agent/src/types.ts:299`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`agent`](../packages/core/agent), `apiproxy`, [`tui`](../packages/ui/tui) |
|
||||
| `agent/inbox/enqueue` | `emit` | [`packages/core/agent/src/types.ts:277`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`agent`](../packages/core/agent), `apiproxy`, [`goal-session`](../packages/goal/goal-session) |
|
||||
| `agent/prompt-submit` | `waterfall` | [`packages/core/agent/src/types.ts:337`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`goal-session`](../packages/goal/goal-session), [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`repeat-tool-guard`](../packages/guard/repeat-tool-guard), [`tui`](../packages/ui/tui) |
|
||||
| `agent/request` | `waterfall` | [`packages/core/agent/src/types.ts:363`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`agent`](../packages/core/agent) |
|
||||
| `agent/request-error` | `waterfall` | [`packages/core/agent/src/types.ts:378`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`compact-basic`](../packages/compact/compact-basic), [`llm-retry`](../packages/llm/llm-retry) |
|
||||
| `agent/session-start` | `emit` | [`packages/core/agent/src/types.ts:322`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `agent/settled` | `emit` | [`packages/core/agent/src/types.ts:407`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`compact-basic`](../packages/compact/compact-basic), [`llm-retry`](../packages/llm/llm-retry) |
|
||||
| `agent/status` | `emit` | [`packages/core/agent/src/types.ts:266`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`agent`](../packages/core/agent), `apiproxy`, [`goal-session`](../packages/goal/goal-session), [`tui`](../packages/ui/tui) |
|
||||
| `agent/step` | `serial` | [`packages/core/agent/src/types.ts:350`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`serial`) | [`compact-basic`](../packages/compact/compact-basic), [`plan-mode`](../packages/plan/plan-mode), [`session-checkpoint-policy`](../packages/session-persistence/session-checkpoint-policy), [`time-context`](../packages/context/time-context), [`tool-skill`](../packages/skill/tool-skill), [`user-approval`](../packages/ui/user-approval), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `agent/turn-stopping` | `serial` | [`packages/core/agent/src/types.ts:393`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`serial`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex) |
|
||||
| `approval/request` | `waterfall` | [`packages/ui/user-approval/src/index.ts:30`](../packages/ui/user-approval/src/index.ts) | [`user-approval`](../packages/ui/user-approval) (`waterfall`) | [`acp`](../packages/acp/acp) |
|
||||
| `commands/change` | `emit` | [`packages/ui/commands/src/index.ts:103`](../packages/ui/commands/src/index.ts) | [`commands`](../packages/ui/commands) (`events.dispatch`) | `apiproxy`, [`tui`](../packages/ui/tui) |
|
||||
| `domain/changed` | `emit` | [`packages/storage/storage-domain/src/events.ts:46`](../packages/storage/storage-domain/src/events.ts) | [`storage-domain`](../packages/storage/storage-domain) (`emit`) | `apiproxy`, [`storage-domain`](../packages/storage/storage-domain), [`workspace`](../packages/workspace/workspace) |
|
||||
|
||||
Reference in New Issue
Block a user