docs(agent): document next-step acceptance window

This commit is contained in:
_Kerman
2026-07-27 18:07:51 +08:00
parent f63d937496
commit ff7792b17c
35 changed files with 267 additions and 206 deletions

View File

@@ -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.