fix inbox lifecycle downstream contracts
This commit is contained in:
@@ -27,7 +27,7 @@ sequenceDiagram
|
||||
Driver->>Hooks: <code>agent/pre-step</code> waterfall
|
||||
Hooks-->>Driver: authoritative reject or enter(messages)
|
||||
alt proposed step rejected or pre-step failed
|
||||
Driver-->>Driver: claimed batch stays removed; no turn opens
|
||||
Driver-->>Driver: claimed batch stays removed, no turn opens
|
||||
else enter proposed step
|
||||
Driver->>Session: <code>turn/start</code>
|
||||
Driver->>Session: <code>step/start</code>
|
||||
|
||||
@@ -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: d2e094be43f22abb6d829cd6484c09e8f34130b0
|
||||
architecture.zh.md: f9588b52ac220d509d340270bed36036ef8f8b03
|
||||
architecture.md: d85756ec33b9ec2c179dd7bbefa0847d3fd02753
|
||||
architecture.zh.md: 147bafb388de44a7feb2c8b7c1de2c80ad65439b
|
||||
|
||||
@@ -6,9 +6,7 @@ English | [中文](architecture.zh.md)
|
||||
|
||||
## Overview
|
||||
|
||||
Harnesses are [Cordis](cordis-primer.md) contexts; packages contribute services, typed events, and disposable registrations.
|
||||
|
||||
`packages/core/` groups the default agent flow; capabilities remain plugins.
|
||||
Harnesses are [Cordis](cordis-primer.md) contexts; packages contribute services, typed events, and disposable registrations. `packages/core/` groups the default flow; capabilities remain plugins.
|
||||
|
||||
### Default Services
|
||||
|
||||
@@ -59,8 +57,8 @@ Events are the service extension API ([catalog](cordis-catalog/events.md), [prod
|
||||
### Event Domains
|
||||
|
||||
- **Session events** are durable log facts emitted through `session/event`.
|
||||
- **Agent events** carry live `Agent` for inbox notifications, step entry, status, request shaping, validation, and continuation.
|
||||
- **Capability events** let owning seams attach policy and adapters without a loop import.
|
||||
- **Agent events** carry live `Agent` for inbox, step, status, request, validation, and continuation.
|
||||
- **Capability events** attach policy and adapters without a loop import.
|
||||
|
||||
### Interception Semantics
|
||||
|
||||
@@ -68,9 +66,9 @@ Waterfalls are around-middleware: listeners delegate with `next()`; returning wi
|
||||
|
||||
## Default Loop Lifecycle
|
||||
|
||||
A **session** is append-only. An ordinary **turn** claims one queued follow-up; injection claims none. A successor awaits its predecessor's checkpoint but may share its `running` interval ([decision](../.agents/notes/implemented/simplification/2026-07-17-one-send-one-turn.md)). A turn ends when model or plugins stop it; a **step** is one model request plus tools. Quotes in the [sequence below](agent-lifecycle.md) mark durable events.
|
||||
A **session** is append-only. A **turn** claims one queued follow-up, waits for its predecessor's checkpoint, and may share its `running` interval ([decision](../.agents/notes/implemented/simplification/2026-07-17-one-send-one-turn.md)); injection claims none. A **step** is one model request plus tools. Quotes in the [sequence](agent-lifecycle.md) mark durable events.
|
||||
|
||||
Creation without an id mints `<config-id>-session-<uuid>`; `sessionId` resumes or creates, while `resumeSessionId` requires history. Resume restores lineage and delegation depth before publication. Setup failures emit `agent-loop/config-start-failed`; teardown is silent.
|
||||
Creation without an id mints `<config-id>-session-<uuid>`; `sessionId` resumes or creates, while `resumeSessionId` requires history. Resume restores lineage and delegation depth before publication; setup failure emits `agent-loop/config-start-failed`.
|
||||
|
||||
### Turn Flow
|
||||
|
||||
@@ -81,31 +79,27 @@ choose declarative identity and fresh/resume path
|
||||
-> enable driving -> agent/session-start(source) -> start driver
|
||||
forever:
|
||||
wait for waking inbox work
|
||||
claim next-step input plus one next-turn message with a pure deletion splice
|
||||
claim next-step input plus one next-turn message
|
||||
-> emit agent/inbox/claimed({ message, turn }) for each claimed message
|
||||
-> emit agent/status(running) if starting an interval
|
||||
-> agent/pre-step(messages, { turn, step, signal })
|
||||
reject or listener failure -> the claimed batch stays removed; stop the driver
|
||||
enter:
|
||||
'turn/start'
|
||||
STEP loop:
|
||||
step loop:
|
||||
'step/start'
|
||||
append the returned batch as separate 'user/message' events
|
||||
assemble system prompt and tool schemas
|
||||
snapshot the derived messages (the reconstruction boundary)
|
||||
agent/request (config only) -> prepare adapter defaults/provenance under turn signal -> log request/header -> llm/stream (frozen, registration-bound)
|
||||
'assistant/chunk'
|
||||
'assistant/message'
|
||||
assemble prompt and schemas -> snapshot derived messages
|
||||
agent/request -> prepare adapter defaults/provenance -> request/header -> llm/stream
|
||||
'assistant/chunk' -> 'assistant/message'
|
||||
schedule tool calls by ctx.tools.executionMode:
|
||||
exclusive -> barrier
|
||||
parallel -> rolling pool, <= maxParallelToolCalls; reclassify-at-start; scheduler failure -> stop starts, drain dispatches
|
||||
start -> 'tool/call' -> ordered tools/pre-execute -> concurrent tools/execute
|
||||
parallel -> rolling pool, <= maxParallelToolCalls; reclassify at start
|
||||
start -> 'tool/call' -> tools/pre-execute -> concurrent tools/execute
|
||||
model-order result -> ordered tools/post-execute -> 'tool/result'
|
||||
'step/end'
|
||||
tools owe another request or next-step inbox is nonempty
|
||||
-> claim next-step messages
|
||||
-> agent/pre-step (messages may be empty for a tool continuation)
|
||||
-> append the entered batch and continue
|
||||
-> claim -> agent/pre-step -> append entered batch -> continue
|
||||
otherwise agent/turn-stopping -> re-check the next-step inbox
|
||||
'turn/end' -> agent/settled
|
||||
start the next waking queued message, or emit agent/status(idle)
|
||||
@@ -117,23 +111,21 @@ 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)).
|
||||
|
||||
`inject()` always queues non-waking `next-step` context. A collecting or running driver claims it at the nearest later prompt boundary; an idle driver leaves it pending until `followup()` or `steer()` wakes the driver. Post-tool `additionalContexts` enter the same next-step inbox after their tool results.
|
||||
`inject()` queues non-waking `next-step` context; an idle driver leaves it pending until `followup()` or `steer()` wakes the driver. Post-tool `additionalContexts` use the same inbox. `agent/pre-step` receives the exclusive claimed batch and upcoming turn, step, and signal. Reject opens no step; enter supplies the complete batch appended after `step/start`. Empty tool continuations still traverse the waterfall, whose final value settles all rewrites.
|
||||
|
||||
`agent/pre-step` receives the exclusive batch already removed from the inbox and finalizes whether the loop enters the proposed step. Its `PreStepContext` carries the exact upcoming turn and step plus the cancellation signal. `{ kind: 'reject' }` opens no step; `{ kind: 'enter', messages }` supplies the complete batch appended after `step/start`. A tool continuation with no newly claimed inbox input submits an empty batch so listeners can still contribute current-step context. Waterfall rewrites settle only in the final returned `messages` value.
|
||||
|
||||
Pruning precedes summaries; overflow retries require durable progress. `agent/request-error` may authorize a same-step retry before the step closes; cancellation wins, and the retry reuses that step's frozen prompt assembly. Adapter-owned `retryPolicy` makes normal mode bounded; always mode delegates specialized recovery before retrying until success or cancellation ([compaction](../.agents/notes/implemented/architecture/2026-07-10-after-call-compaction-pressure-and-overflow-recovery.md), [retry foundation](../.agents/notes/implemented/architecture/2026-06-21-bounded-llm-request-recovery.md), [provider policy](../.agents/notes/implemented/feature/2026-07-24-provider-retry-policies.md)).
|
||||
Pruning precedes summaries; overflow retries require durable progress. `agent/request-error` may authorize a same-step retry of the frozen prompt; cancellation wins. Adapter `retryPolicy` bounds normal mode, while always mode retries after specialized recovery ([compaction](../.agents/notes/implemented/architecture/2026-07-10-after-call-compaction-pressure-and-overflow-recovery.md), [retry foundation](../.agents/notes/implemented/architecture/2026-06-21-bounded-llm-request-recovery.md), [provider policy](../.agents/notes/implemented/feature/2026-07-24-provider-retry-policies.md)).
|
||||
|
||||
### Failure Boundaries
|
||||
|
||||
Final-adapter selection, dispatch, and iteration failures become terminal `finish { kind: 'error' | 'aborted', failure }` chunks before the loop handles them. `agent/request-error` receives request coordinates, normalized `LlmFailure`, the prepared registration's retry policy when available, and the signal; middleware and consumer errors remain thrown outside request recovery. Failed chunks commit neither messages nor tool calls.
|
||||
Adapter selection, dispatch, and iteration failures become terminal error or aborted `finish` chunks. `agent/request-error` receives request coordinates, normalized `LlmFailure`, available retry policy, and signal; middleware and consumer errors remain outside recovery. Failed chunks commit neither messages nor tool calls.
|
||||
|
||||
Other failures use `agent/error`. Cancellation and disposal beat recovery. Before request-header commit, the turn signal cancels asynchronous model-capability preparation; undispatched tools get synthetic `tool/call`/`ABORTED_BEFORE_DISPATCH` pairs. Effective `cancel(cause)` emits its cause before queue clearing and abort; observers cannot veto; idle calls emit nothing. Durability records user or parent cancellation as `aborted`, teardown as `disposed`; teardown awaits quiescence. The cause affects reporting, not late result-context handling ([decision](../.agents/notes/implemented/architecture/2026-07-16-explicit-turn-cancellation.md)).
|
||||
Other failures use `agent/error`; cancellation and disposal beat recovery. Before request-header commit, the turn signal cancels capability preparation; undispatched tools get synthetic `tool/call`/`ABORTED_BEFORE_DISPATCH` pairs. Effective `cancel(cause)` reports its cause before clearing and aborting; idle calls emit nothing. Durability distinguishes `aborted` cancellation from `disposed` teardown, which awaits quiescence ([decision](../.agents/notes/implemented/architecture/2026-07-16-explicit-turn-cancellation.md)).
|
||||
|
||||
Turn and step events are turn-enclosed; the loop appends injected `user/message` events only from entered batches inside a turn. Reload closes an interrupted tail with a synthetic turn end. After close, only `agent/error` reports failures. Each turn has one [TurnEndReason](core-data-structures/session.md#why-a-turn-ended-turnendreasonmap).
|
||||
|
||||
### Agent Handles
|
||||
|
||||
`ctx.agents` returns `AgentHandle { agent, dispose() }`. Plugins drive agents with `followup()`, `steer()`, and `inject()`; `cancel()` stops work, while the awaited disposer owns teardown. `followup()` only queues an identified message: its `MessageId` follows durable inbox insertion, claiming, and discard notifications, not a prompt-specific output or turn ending. `agent/status` and `whenIdle()` describe whole-agent activity; only a caller that explicitly owns an activity interval may summarize that interval as a run result ([decision](../.agents/notes/implemented/architecture/2026-07-30-followup-enqueue-and-owned-runs.md)).
|
||||
`ctx.agents` returns `AgentHandle { agent, dispose() }`. Plugins drive agents with `followup()`, `steer()`, and `inject()`; `cancel()` stops work and the awaited disposer tears down. A follow-up `MessageId` follows durable inbox insertion, claiming, and discard notifications, not prompt output or turn ending. `agent/status` and `whenIdle()` describe whole-agent activity; only an interval owner may summarize a run result ([decision](../.agents/notes/implemented/architecture/2026-07-30-followup-enqueue-and-owned-runs.md)).
|
||||
|
||||
### Agent Scope
|
||||
|
||||
@@ -147,9 +139,9 @@ The session log is authoritative. `deriveMessages()` projects model history; raw
|
||||
|
||||
**Model-visible ⟺ logged**: messages at `step/start` plus the folded `request/header` reconstruct every request; the header also marks adapter-materialized defaults so the next proposal can discard them and resolve the selected route without losing explicit conversation settings. Package-owned `dsh-agent-loop/invariant` can assert reconstructability through `ctx.invariants` ([reconstructability](../.agents/notes/implemented/architecture/2026-07-05-reconstructable-requests.md)).
|
||||
|
||||
Durability is a plugin concern. Backends eagerly drain synchronous `session/event` notifications. `session/flush` barriers precede each request and top-level tool dispatch, then follow `turn/end` before another queued turn or idle observation. `SessionPersistence` stores `SessionEvent` directly and metadata in `SessionHeader`; JSONL defaults to checksummed Zstandard, while SQLite shares the contract ([decision](../.agents/notes/implemented/bug-fix/2026-07-21-semantic-session-checkpoints.md)).
|
||||
Durability is a plugin concern. Backends eagerly drain synchronous `session/event` notifications. `session/flush` precedes requests and top-level tool dispatch, and follows `turn/end` before another turn or idle. `SessionPersistence` stores events and header metadata; JSONL defaults to checksummed Zstandard and SQLite shares the contract ([decision](../.agents/notes/implemented/bug-fix/2026-07-21-semantic-session-checkpoints.md)).
|
||||
|
||||
Log-only events may sit between turns. Owners append through `Session`, flushing only for durability. `session/title` relies on eager persistence and lifecycle drains. Latest title wins with provenance; fallback and provider work never delays responses. Such records are fork boundaries, so forks inherit titles ([decision](../.agents/notes/implemented/feature/2026-07-21-log-backed-session-titles.md)).
|
||||
Log-only events may sit between turns. Owners append through `Session`, flushing only for durability. Latest `session/title` wins with provenance without delaying responses; title records are fork boundaries ([decision](../.agents/notes/implemented/feature/2026-07-21-log-backed-session-titles.md)).
|
||||
|
||||
### Model Content
|
||||
|
||||
@@ -165,7 +157,7 @@ A swappable capability usually has **interface / implementation / consumer** lay
|
||||
|
||||
Exceptions combine LLM interface/consumer, filesystem policy, web registries, and named skill/subagent providers. Subagents spawn fresh, fork a completed-turn prefix, or use ACP children ([subagent.md](core-data-structures/subagent.md)).
|
||||
|
||||
`dsh-workspace-context` uses the first `agent/pre-step` to prepend its baseline directly to the next-step inbox, replacing any still-pending predecessor, and appends `ctx.fs`-discovered changes through `tools/post-execute`; its [decision](../.agents/notes/implemented/feature/2026-06-24-workspace-context.md) records isolation. Because claim precedes pre-step, that baseline may miss the current request. `dsh-paths` owns shared paths.
|
||||
`dsh-workspace-context` prepends its baseline to the next-step inbox on first `agent/pre-step`, replacing a pending predecessor, and adds `ctx.fs` changes after tools. Because claim precedes pre-step, the baseline may miss the current request ([decision](../.agents/notes/implemented/feature/2026-06-24-workspace-context.md)). `dsh-paths` owns shared paths.
|
||||
|
||||
### Bundles And Apps
|
||||
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
|
||||
## 概览
|
||||
|
||||
每个 harness 都是 [Cordis](cordis-primer.md) 上下文;各包(package)贡献服务、类型化事件和可释放的注册项。
|
||||
|
||||
`packages/core/` 汇集默认的 agent(智能体)流程;各项功能仍以插件形式存在。
|
||||
每个 harness 都是 [Cordis](cordis-primer.md) 上下文;各包(package)贡献服务、类型化事件和可释放的注册项。`packages/core/` 汇集默认流程;各项功能仍以插件形式存在。
|
||||
|
||||
### 默认服务
|
||||
|
||||
@@ -18,7 +16,7 @@
|
||||
| `ctx.sessions` | `dsh-session` | 内存中的事件溯源会话 |
|
||||
| `ctx.systemPrompt` | `dsh-system-prompt` | 有序提示词片段、工具 schema 和变量 |
|
||||
| `ctx.tools` | `dsh-tools` | 工具注册表和[执行流水线](tool-execution-pipeline.md) |
|
||||
| `ctx.agents` | `dsh-agent` | 活跃 agent、委托创建、`agent/*` 事件、进程内发起方作用域 |
|
||||
| `ctx.agents` | `dsh-agent` | 活跃 agent(智能体)、委托创建、`agent/*` 事件、进程内发起方作用域 |
|
||||
| `ctx.agentLoop` | `dsh-agent-loop` | 实体 `Agent` 驱动器 |
|
||||
|
||||
### 功能服务
|
||||
@@ -59,8 +57,8 @@
|
||||
### 事件域
|
||||
|
||||
- **会话事件**是通过 `session/event` 发出的持久日志事实。
|
||||
- **Agent 事件**携带活跃 `Agent`,用于 inbox 通知、步骤进入、状态、请求塑形、验证和续跑。
|
||||
- **功能事件**让所属服务边界无需导入循环即可附加策略和适配器。
|
||||
- **Agent 事件**携带活跃 `Agent`,用于 inbox、步骤、状态、请求、验证和续跑。
|
||||
- **功能事件**无需导入循环即可附加策略和适配器。
|
||||
|
||||
### 拦截语义
|
||||
|
||||
@@ -68,9 +66,9 @@ waterfall(瀑布式事件)是环绕中间件:监听器通过 `next()` 委
|
||||
|
||||
## 默认循环生命周期
|
||||
|
||||
**会话**采用仅追加方式。普通**轮次**领取一条已排队的后续消息;注入不领取输入。后续轮次会等待前一轮次的检查点,但可以与其共用同一个 `running` 区间([决策](../.agents/notes/implemented/simplification/2026-07-17-one-send-one-turn.md))。模型或插件停止轮次时,该轮次结束;一个**步骤**包含一次模型请求及其工具。[下文时序](agent-lifecycle.md)中的引号标记持久事件。
|
||||
**会话**采用仅追加方式。一个**轮次**领取一条已排队的后续消息,等待前一轮次的检查点,并可与其共用 `running` 区间([决策](../.agents/notes/implemented/simplification/2026-07-17-one-send-one-turn.md));注入不领取输入。一个**步骤**包含一次模型请求及其工具。[时序](agent-lifecycle.md)中的引号标记持久事件。
|
||||
|
||||
创建时若未提供 id,流程会生成 `<config-id>-session-<uuid>`;`sessionId` 用于恢复或创建会话,而 `resumeSessionId` 要求已有历史。恢复流程在发布前还原沿袭关系和委托深度。初始化失败会发出 `agent-loop/config-start-failed`;拆卸过程保持静默。
|
||||
创建时若未提供 id,流程会生成 `<config-id>-session-<uuid>`;`sessionId` 用于恢复或创建会话,而 `resumeSessionId` 要求已有历史。恢复流程在发布前还原沿袭关系和委托深度;初始化失败会发出 `agent-loop/config-start-failed`。
|
||||
|
||||
### 轮次流程
|
||||
|
||||
@@ -81,31 +79,27 @@ choose declarative identity and fresh/resume path
|
||||
-> enable driving -> agent/session-start(source) -> start driver
|
||||
forever:
|
||||
wait for waking inbox work
|
||||
claim next-step input plus one next-turn message with a pure deletion splice
|
||||
claim next-step input plus one next-turn message
|
||||
-> emit agent/inbox/claimed({ message, turn }) for each claimed message
|
||||
-> emit agent/status(running) if starting an interval
|
||||
-> agent/pre-step(messages, { turn, step, signal })
|
||||
reject or listener failure -> the claimed batch stays removed; stop the driver
|
||||
enter:
|
||||
'turn/start'
|
||||
STEP loop:
|
||||
step loop:
|
||||
'step/start'
|
||||
append the returned batch as separate 'user/message' events
|
||||
assemble system prompt and tool schemas
|
||||
snapshot the derived messages (the reconstruction boundary)
|
||||
agent/request (config only) -> prepare adapter defaults/provenance under turn signal -> log request/header -> llm/stream (frozen, registration-bound)
|
||||
'assistant/chunk'
|
||||
'assistant/message'
|
||||
assemble prompt and schemas -> snapshot derived messages
|
||||
agent/request -> prepare adapter defaults/provenance -> request/header -> llm/stream
|
||||
'assistant/chunk' -> 'assistant/message'
|
||||
schedule tool calls by ctx.tools.executionMode:
|
||||
exclusive -> barrier
|
||||
parallel -> rolling pool, <= maxParallelToolCalls; reclassify-at-start; scheduler failure -> stop starts, drain dispatches
|
||||
start -> 'tool/call' -> ordered tools/pre-execute -> concurrent tools/execute
|
||||
parallel -> rolling pool, <= maxParallelToolCalls; reclassify at start
|
||||
start -> 'tool/call' -> tools/pre-execute -> concurrent tools/execute
|
||||
model-order result -> ordered tools/post-execute -> 'tool/result'
|
||||
'step/end'
|
||||
tools owe another request or next-step inbox is nonempty
|
||||
-> claim next-step messages
|
||||
-> agent/pre-step (messages may be empty for a tool continuation)
|
||||
-> append the entered batch and continue
|
||||
-> claim -> agent/pre-step -> append entered batch -> continue
|
||||
otherwise agent/turn-stopping -> re-check the next-step inbox
|
||||
'turn/end' -> agent/settled
|
||||
start the next waking queued message, or emit agent/status(idle)
|
||||
@@ -117,23 +111,21 @@ idle inject:
|
||||
|
||||
每个步骤都会组装有序提示词片段、工具 schema 和变量;未知引用会使该轮次失败。`dsh-system-prompt` 负责身份和角色设定;循环提供 `provider`、`model` 和 `cwd`([提示词归属](../.agents/notes/implemented/architecture/2026-07-05-prompt-variables-and-tool-guidance-ownership.md))。
|
||||
|
||||
`inject()` 始终将不会唤醒的上下文排入 `next-step`。collecting 或 running 驱动器会在最近的后续提示词边界领取它;idle 驱动器则会让它保持待处理,直至 `followup()` 或 `steer()` 唤醒驱动器。工具执行后的 `additionalContexts` 会在对应工具结果之后进入同一个 next-step inbox。
|
||||
`inject()` 将不会唤醒驱动器的上下文排入 `next-step`;空闲驱动器会让它保持待处理,直至 `followup()` 或 `steer()` 唤醒。工具执行后的 `additionalContexts` 使用同一个 inbox。`agent/pre-step` 接收独占的已领取批次,以及即将使用的轮次、步骤和信号。拒绝则不进入步骤;进入则提供在 `step/start` 后追加的完整批次。空的工具续跑仍会经过 waterfall,其最终值一次性结算所有改写。
|
||||
|
||||
`agent/pre-step` 接收已经从 inbox 删除的独占批次,并最终决定循环是否进入拟议步骤。它的 `PreStepContext` 携带准确的 turn、step 与取消 signal。`{ kind: 'reject' }` 不会打开步骤;`{ kind: 'enter', messages }` 提供在 `step/start` 后追加的完整批次。当工具 continuation 没有新领取的 inbox 输入时,批次为空,listener 仍可为当前步骤贡献上下文。waterfall 的全部改写只在最终返回的 `messages` 中一次性结算。
|
||||
|
||||
裁剪先于摘要;溢出重试必须取得持久进展。`agent/request-error` 可以在步骤关闭前授权一次同步骤重试;取消优先,且重试会复用该步骤已冻结的 prompt assembly。适配器拥有的 `retryPolicy` 使 normal mode 保持有界;always mode 先委托专门恢复,再持续重试直至成功或取消([压缩](../.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)、[提供方策略](../.agents/notes/implemented/feature/2026-07-24-provider-retry-policies.md))。
|
||||
裁剪先于摘要;溢出重试必须取得持久进展。`agent/request-error` 可以授权使用冻结提示词进行同步骤重试;取消优先。适配器的 `retryPolicy` 使 normal mode 保持有界,always mode 则在专门恢复后重试([压缩](../.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)、[提供方策略](../.agents/notes/implemented/feature/2026-07-24-provider-retry-policies.md))。
|
||||
|
||||
### 失败边界
|
||||
|
||||
最终适配器选择、分发与迭代失败会在 loop 处理前成为终止 `finish { kind: 'error' | 'aborted', failure }` chunk。`agent/request-error` 接收请求坐标、标准化 `LlmFailure`、可用时已准备注册项的重试策略以及信号;middleware 与消费方错误仍在请求恢复之外抛出。失败分片既不提交消息,也不提交工具调用。
|
||||
适配器选择、分发与迭代失败会成为 error 或 aborted 类型的终止 `finish` 分片。`agent/request-error` 接收请求坐标、标准化 `LlmFailure`、可用的重试策略和信号;middleware 与消费方错误仍在恢复之外。失败分片既不提交消息,也不提交工具调用。
|
||||
|
||||
其他故障使用 `agent/error`。取消和资源释放优先于恢复。在提交请求头之前,轮次信号会取消异步模型能力准备;尚未分派的工具会得到合成的 `tool/call`/`ABORTED_BEFORE_DISPATCH` 对。实际生效的 `cancel(cause)` 在清空队列和中止前发出原因;观察方不能否决;空闲调用不发事件。持久化层将用户或父级取消记录为 `aborted`,拆卸记录为 `disposed`;拆卸会等待完全停稳。原因只影响报告方式,不影响延迟完成的结果上下文处理([决策](../.agents/notes/implemented/architecture/2026-07-16-explicit-turn-cancellation.md))。
|
||||
其他故障使用 `agent/error`;取消和资源释放优先于恢复。在提交请求头之前,轮次信号会取消功能准备;尚未分派的工具会得到合成的 `tool/call`/`ABORTED_BEFORE_DISPATCH` 对。实际生效的 `cancel(cause)` 会在清空队列和中止前报告原因;空闲调用不发事件。持久化层以 `aborted` 区分取消,以 `disposed` 区分会等待完全停稳的拆卸([决策](../.agents/notes/implemented/architecture/2026-07-16-explicit-turn-cancellation.md))。
|
||||
|
||||
轮次和步骤事件均位于轮次边界内;loop 只会在轮次内从进入步骤的批次追加注入的 `user/message`。重新加载会用合成的轮次结束事件闭合中断尾部。关闭后仅由 `agent/error` 报告故障。每个轮次有一个 [TurnEndReason](core-data-structures/session.md#why-a-turn-ended-turnendreasonmap)。
|
||||
|
||||
### Agent 句柄
|
||||
|
||||
`ctx.agents` 返回 `AgentHandle { agent, dispose() }`。插件用 `followup()`、`steer()` 和 `inject()` 驱动 agent;`cancel()` 停止工作,而拆卸由需等待完成的 disposer 负责。`followup()` 只会将一条带标识的消息排队:其 `MessageId` 跟踪持久 inbox 的插入、领取与丢弃通知,而不标识某个提示词特有的输出或轮次结束。`agent/status` 与 `whenIdle()` 描述整个 agent 的活动;只有显式拥有某个活动区间的调用方才能将该区间概括为一次运行的结果([决策](../.agents/notes/implemented/architecture/2026-07-30-followup-enqueue-and-owned-runs.md))。
|
||||
`ctx.agents` 返回 `AgentHandle { agent, dispose() }`。插件用 `followup()`、`steer()` 和 `inject()` 驱动 agent;`cancel()` 停止工作,需等待完成的 disposer 负责拆卸。后续消息的 `MessageId` 跟踪持久 inbox 的插入、领取与丢弃通知,而不标识提示词输出或轮次结束。`agent/status` 与 `whenIdle()` 描述整个 agent 的活动;只有区间所有方才能将其概括为一次运行结果([决策](../.agents/notes/implemented/architecture/2026-07-30-followup-enqueue-and-owned-runs.md))。
|
||||
|
||||
### Agent 作用域
|
||||
|
||||
@@ -147,9 +139,9 @@ idle inject:
|
||||
|
||||
**模型可见 ⟺ 已记录**:`step/start` 时的消息与折叠后的 `request/header` 可以重建每个请求;该 header 还会标记适配器填入的默认值,使下一次提议可以丢弃这些值并解析所选路由,同时不丢失显式对话设置。该包的 `dsh-agent-loop/invariant` 可通过 `ctx.invariants` 断言可重建性([可重建性](../.agents/notes/implemented/architecture/2026-07-05-reconstructable-requests.md))。
|
||||
|
||||
持久性由插件负责。后端会尽快排空同步的 `session/event` 通知。`session/flush` 屏障位于每次请求与顶层工具分发之前,并在 `turn/end` 之后、处理另一个已排队轮次或观察到空闲状态之前执行。`SessionPersistence` 直接存储 `SessionEvent`,并将元数据存入 `SessionHeader`;JSONL 默认采用带校验和的 Zstandard,SQLite 遵循同一契约([决策](../.agents/notes/implemented/bug-fix/2026-07-21-semantic-session-checkpoints.md))。
|
||||
持久性由插件负责。后端会尽快排空同步的 `session/event` 通知。`session/flush` 位于请求与顶层工具分发之前,并在 `turn/end` 之后、另一个轮次或空闲状态之前执行。`SessionPersistence` 存储事件和 header 元数据;JSONL 默认采用带校验和的 Zstandard,SQLite 遵循同一契约([决策](../.agents/notes/implemented/bug-fix/2026-07-21-semantic-session-checkpoints.md))。
|
||||
|
||||
纯日志事件可以位于轮次之间。事件所有方通过 `Session` 追加,仅为持久性而刷写。`session/title` 依赖尽快持久化与生命周期排空。最新标题按后写覆盖并携带来源信息;回退与提供方工作绝不会延迟响应。这类记录可作为 fork 边界,因此 fork 会继承标题([决策](../.agents/notes/implemented/feature/2026-07-21-log-backed-session-titles.md))。
|
||||
纯日志事件可以位于轮次之间。事件所有方通过 `Session` 追加,仅为持久性而刷写。最新的 `session/title` 携带来源信息并按后写覆盖,且不会延迟响应;标题记录可作为 fork 边界([决策](../.agents/notes/implemented/feature/2026-07-21-log-backed-session-titles.md))。
|
||||
|
||||
### 模型内容
|
||||
|
||||
@@ -165,7 +157,7 @@ idle inject:
|
||||
|
||||
例外情况包括 LLM(大语言模型)合并接口和消费方、文件系统整合策略、web 使用注册表、skill 和 subagent 使用具名提供方。subagent 可以通过 spawn 创建全新实例、fork 一个已完成轮次的前缀,或使用 ACP(Agent Client Protocol)子 agent([subagent.md](core-data-structures/subagent.md))。
|
||||
|
||||
`dsh-workspace-context` 在第一次 `agent/pre-step` 将基线直接 prepend 到 next-step inbox,并替换仍在等待的前序消息;它通过 `tools/post-execute` 追加 `ctx.fs` 发现的变更。其[决策](../.agents/notes/implemented/feature/2026-06-24-workspace-context.md)记录隔离方式。由于领取发生在 pre-step 之前,该基线可能赶不上当前请求。`dsh-paths` 负责共享路径。
|
||||
`dsh-workspace-context` 在第一次 `agent/pre-step` 将基线 prepend 到 next-step inbox,替换仍在等待的前序消息,并在工具执行后添加 `ctx.fs` 变更。由于领取发生在 pre-step 之前,该基线可能赶不上当前请求([决策](../.agents/notes/implemented/feature/2026-06-24-workspace-context.md))。`dsh-paths` 负责共享路径。
|
||||
|
||||
### 组合包与应用
|
||||
|
||||
|
||||
@@ -467,7 +467,7 @@ export interface Config {
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/goal/goal/src/index.ts:118`](../packages/goal/goal/src/index.ts)
|
||||
Source: [`packages/goal/goal/src/index.ts:130`](../packages/goal/goal/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-hooks-claude`
|
||||
|
||||
@@ -765,7 +765,7 @@ export interface ReplayModelConfig {
|
||||
|
||||
Depends on: [`RetryPolicyConfig`](../packages/llm/llm/src/index.ts)
|
||||
|
||||
Source: [`packages/support/llm-replay/src/index.ts:617`](../packages/support/llm-replay/src/index.ts)
|
||||
Source: [`packages/support/llm-replay/src/index.ts:620`](../packages/support/llm-replay/src/index.ts)
|
||||
|
||||
## `@deepseek-ai/dsh-llm-retry`
|
||||
|
||||
@@ -1600,7 +1600,7 @@ Requires: `agents`
|
||||
export interface Config {
|
||||
/** IANA time zone used for the rendered timestamp. Omit to resolve the Node process's system zone at plugin load. */
|
||||
timeZone?: string
|
||||
/** Minimum milliseconds between durable injections in one session. Omit or set to 0 to inject on every eligible pre-step attempt. */
|
||||
/** Minimum milliseconds between durable injections in one session. Omit or set to 0 to inject at every eligible step. */
|
||||
refreshIntervalMs?: number
|
||||
}
|
||||
```
|
||||
|
||||
@@ -444,13 +444,13 @@ Source: [`packages/fs/fs/src/index.ts:54`](../../packages/fs/fs/src/index.ts)
|
||||
|
||||
### `goal/changed` — emit
|
||||
|
||||
Goal mutation accepted by one live agent. The matching context event is already appended or queued in that agent's active tool-batch FIFO. Listener failures are contained. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
|
||||
Goal mutation accepted by one live agent. The matching message has already committed through a durable inbox insertion; later admission or discard does not change that fact. Listener failures are contained. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Goal mutation accepted by one live agent. The matching context event is
|
||||
* already appended or queued in that agent's active tool-batch FIFO.
|
||||
* Listener failures are contained.
|
||||
* Goal mutation accepted by one live agent. The matching message has
|
||||
* already committed through a durable inbox insertion; later admission or
|
||||
* discard does not change that fact. Listener failures are contained.
|
||||
* Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
|
||||
* @param agent - agent whose session owns the goal.
|
||||
* @param change - fresh current projection or clear tombstone.
|
||||
|
||||
@@ -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: d5fb4b1efb4a74d7a01ee09e4086863e981e2122
|
||||
core.zh.md: 2cb15e20a87160e0ff0bc375752282969d77124b
|
||||
core.md: 6bb01c91446fbb51e3c472bba3ed3a51b56704ff
|
||||
core.zh.md: c52bf426020c591aab66d66658b46dfd8dc9b8af
|
||||
|
||||
@@ -485,7 +485,7 @@ Source: [`packages/core/agent/src/types.ts`](../../packages/core/agent/src/types
|
||||
type InboxTarget = 'next-turn' | 'next-step'
|
||||
```
|
||||
|
||||
Every pending occurrence is its `UserMessage`; `MessageId` is the sole identity. `Inbox.append`, `prepend`, `update`, `remove`, and `splice` record normalized durable `agent/inbox/spliced` mutations and reject duplicate pending ids. Ordinary removals are cancellations. `claim(target)` atomically removes the proposed step batch through pure deletion splices; the loop separately emits per-message claimed notifications. Whole-queue consumers such as UI projections reconstruct `nextTurn` and `nextStep` from the durable splices, while consumers following one message use the exact `agent/inbox/inserted`, `claimed`, and `discarded` notifications.
|
||||
Every pending occurrence is its `UserMessage`; `MessageId` is the sole identity. `Inbox.append`, `prepend`, `update`, `remove`, `clear`, and `splice` record normalized durable `agent/inbox/spliced` mutations and reject duplicate pending ids. Ordinary removals and `clear()` are cancellations. `claim(target)` atomically removes the proposed step batch through pure deletion splices; the loop separately emits per-message claimed notifications. Whole-queue consumers such as UI projections reconstruct `nextTurn` and `nextStep` from the durable splices, while consumers following one message use the exact `agent/inbox/inserted`, `claimed`, and `discarded` notifications.
|
||||
|
||||
```ts type-equiv
|
||||
/** Options for {@link Agent.cancel}. */
|
||||
|
||||
@@ -493,7 +493,7 @@ type SessionEvent<T extends SessionEventType = SessionEventType> = {
|
||||
type InboxTarget = 'next-turn' | 'next-step'
|
||||
```
|
||||
|
||||
每个待处理入队项就是其 `UserMessage`;`MessageId` 是唯一标识。`Inbox.append`、`prepend`、`update`、`remove` 与 `splice` 会记录规范化的持久 `agent/inbox/spliced` 变更,并拒绝重复的待处理 id。普通删除表示取消。`claim(target)` 通过纯删除 splice 原子移除拟进入步骤的批次;循环另行逐条发出 claimed 通知。UI 投影等整体队列消费方通过持久 splice 重建 `nextTurn` 与 `nextStep`,而跟踪单条消息的消费方使用精确的 `agent/inbox/inserted`、`claimed` 与 `discarded` 通知。
|
||||
每个待处理入队项就是其 `UserMessage`;`MessageId` 是唯一标识。`Inbox.append`、`prepend`、`update`、`remove`、`clear` 与 `splice` 会记录规范化的持久 `agent/inbox/spliced` 变更,并拒绝重复的待处理 id。普通删除和 `clear()` 都表示取消。`claim(target)` 通过纯删除 splice 原子移除拟进入步骤的批次;循环另行逐条发出 claimed 通知。UI 投影等整体队列消费方通过持久 splice 重建 `nextTurn` 与 `nextStep`,而跟踪单条消息的消费方使用精确的 `agent/inbox/inserted`、`claimed` 与 `discarded` 通知。
|
||||
|
||||
```ts type-equiv
|
||||
/** Options for {@link Agent.cancel}. */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# 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
|
||||
goal.md: 704a93320cc38d1b9400edc2d9ad2342bc11dccd
|
||||
goal.zh.md: b2e083843a70823bf6a6b43e046b1f38f4e11e22
|
||||
# pnpm run verify-translation-pairing --write docs/core-data-structures/goal.md
|
||||
goal.md: bb8b4525f7e12a904b1ba77cdefa4e4e1650ffe8
|
||||
goal.zh.md: c61bfcf7683b3aa835ee7cca58aba861af847d17
|
||||
|
||||
@@ -71,10 +71,10 @@ interface GoalView extends GoalSnapshot {
|
||||
|
||||
## Durable changes
|
||||
|
||||
Every mutation is a round-zero goal-sourced `user/message` whose metadata is either a complete snapshot or a clear tombstone. The version, metadata, goal source, and verbatim rendered content form one replay invariant.
|
||||
Every mutation is a round-zero goal-sourced message whose metadata is either a complete snapshot or a clear tombstone. It commits when `agent.inject()` records that message in the `inserted` payload of a durable `agent/inbox/spliced` event. The strict fold and persisted projection derive mutations only from these insertions, so deleting the queued context does not roll back goal state. A later `user/message` with the same id verifies the source, metadata, and verbatim rendered content against the insertion without applying the mutation again.
|
||||
|
||||
```ts type-equiv
|
||||
/** Full-snapshot goal mutation retained in a model-visible context event. */
|
||||
/** Full-snapshot goal mutation committed by an injected inbox message. */
|
||||
interface GoalSnapshotChangeMeta {
|
||||
readonly kind: 'goal/change'
|
||||
readonly version: 1
|
||||
@@ -97,7 +97,7 @@ interface GoalClearChangeMeta {
|
||||
}
|
||||
```
|
||||
|
||||
Goal state changes use round `0`. A continuation consumer attributes each admitted user-message turn with a positive, sequential round number and the current revision; replay rejects gaps, stale revisions, stopped phases, and cap overflow.
|
||||
Goal state changes use round `0`. A continuation consumer attributes each admitted user-message turn with a positive, sequential round number and the current revision; only these admitted `user/message` events advance `roundsStarted`. Replay rejects gaps, stale revisions, stopped phases, and cap overflow.
|
||||
|
||||
```ts type-equiv
|
||||
/** Message attribution for durable goal state and continuation rounds. */
|
||||
@@ -133,7 +133,7 @@ interface EditGoalRequest {
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
/** Live notification after one goal mutation has been accepted for logging. */
|
||||
/** Live notification after one goal mutation commits through inbox insertion. */
|
||||
interface GoalChanged {
|
||||
readonly operation: GoalOperation
|
||||
readonly ref: GoalRef
|
||||
@@ -144,4 +144,4 @@ interface GoalChanged {
|
||||
|
||||
## Service behavior
|
||||
|
||||
[`GoalService`](../../packages/goal/goal/src/index.ts) resolves creation defaults, folds strict replay, enforces exact-live-agent identity and compare-and-set mutations, overlays deferred injections, and emits contained `goal/changed` notifications. The package [README](../../packages/goal/goal/README.md) owns the callable and model-visible contract.
|
||||
[`GoalService`](../../packages/goal/goal/src/index.ts) resolves creation defaults, folds strict replay from durable inbox insertions, enforces exact-live-agent identity and compare-and-set mutations, reconciles later admission by message id, and emits contained `goal/changed` notifications. The package [README](../../packages/goal/goal/README.md) owns the callable and model-visible contract.
|
||||
|
||||
@@ -71,10 +71,10 @@ interface GoalView extends GoalSnapshot {
|
||||
|
||||
## 持久变更
|
||||
|
||||
每次变更都是 Round 编号为 0、来源为目标的 `user/message`,其元数据要么是完整快照,要么是清除墓碑。版本、元数据、目标来源和逐字渲染内容共同构成一项回放不变量。
|
||||
每次变更都是 Round 编号为 0、来源为目标的消息,其元数据要么是完整快照,要么是清除墓碑。当 `agent.inject()` 将该消息记录到持久 `agent/inbox/spliced` 事件的 `inserted` 载荷时,变更即已提交。严格折叠与持久投影只从这些插入项派生变更,因此删除队列中的上下文不会回滚目标状态。随后具有相同 id 的 `user/message` 会对照插入项验证来源、元数据和逐字渲染内容,而不会再次应用变更。
|
||||
|
||||
```ts type-equiv
|
||||
/** Full-snapshot goal mutation retained in a model-visible context event. */
|
||||
/** Full-snapshot goal mutation committed by an injected inbox message. */
|
||||
interface GoalSnapshotChangeMeta {
|
||||
readonly kind: 'goal/change'
|
||||
readonly version: 1
|
||||
@@ -97,7 +97,7 @@ interface GoalClearChangeMeta {
|
||||
}
|
||||
```
|
||||
|
||||
目标状态变更使用 Round `0`。续跑消费方会为每个获准的用户消息轮次标注正数且连续的 Round 编号和当前修订号;回放会拒绝编号缺口、陈旧修订号、已停止阶段和超出上限。
|
||||
目标状态变更使用 Round `0`。续跑消费方会为每个获准的用户消息轮次标注正数且连续的 Round 编号和当前修订号;只有这些获准的 `user/message` 事件会推进 `roundsStarted`。回放会拒绝编号缺口、陈旧修订号、已停止阶段和超出上限。
|
||||
|
||||
```ts type-equiv
|
||||
/** Message attribution for durable goal state and continuation rounds. */
|
||||
@@ -133,7 +133,7 @@ interface EditGoalRequest {
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
/** Live notification after one goal mutation has been accepted for logging. */
|
||||
/** Live notification after one goal mutation commits through inbox insertion. */
|
||||
interface GoalChanged {
|
||||
readonly operation: GoalOperation
|
||||
readonly ref: GoalRef
|
||||
@@ -144,4 +144,4 @@ interface GoalChanged {
|
||||
|
||||
## 服务行为
|
||||
|
||||
[`GoalService`](../../packages/goal/goal/src/index.ts) 解析创建默认值、执行严格回放折叠、校验确切的活跃 agent 身份、以比较并设置方式执行变更、叠加延迟注入,并发出 `goal/changed` 通知;监听器故障会被隔离。包 [README](../../packages/goal/goal/README.md) 负责记录可调用契约和面向模型的契约。
|
||||
[`GoalService`](../../packages/goal/goal/src/index.ts) 解析创建默认值、从持久 inbox 插入项执行严格回放折叠、校验确切的活跃 agent 身份、以比较并设置方式执行变更、按消息 id 对账后续准入,并发出 `goal/changed` 通知;监听器故障会被隔离。包 [README](../../packages/goal/goal/README.md) 负责记录可调用契约和面向模型的契约。
|
||||
|
||||
@@ -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/session.md
|
||||
session.md: 05c993755cc50fe9f1c6fe8836fc6a6fb4196ed2
|
||||
session.zh.md: ac7e59c8563a0319609557c7346919b6e1d78ad2
|
||||
session.md: 829a52c5ec4017b47f8fa6c7d45f20b0ff9630d4
|
||||
session.zh.md: 6a70c1548fdd3b2b13bbcd1b102fadecdb34bf11
|
||||
|
||||
@@ -26,9 +26,9 @@ interface UserMessage extends Message {
|
||||
*/
|
||||
interface SessionEventMap {
|
||||
/**
|
||||
* Opens turn `turn`. Every turn begins when the loop admits queued input;
|
||||
* the following identified `user/message` event or batch records the
|
||||
* admitted input.
|
||||
* Opens turn `turn`. Every turn begins after the loop claims queued input
|
||||
* and accepts the pre-step result; the following identified `user/message`
|
||||
* event or batch records the messages entering the step.
|
||||
*/
|
||||
'turn/start': { turn: number }
|
||||
/**
|
||||
@@ -46,7 +46,7 @@ interface SessionEventMap {
|
||||
* A user-role message on the model-visible surface: a direct human prompt
|
||||
* (the queued message claimed for this turn), a synthetic `agent.inject()`
|
||||
* context (file-change notices, subdir AGENTS.md, skill content, cron
|
||||
* notifications, …), or an admitted goal continuation round. All three
|
||||
* notifications, …), or an entered goal continuation round. All three
|
||||
* project their `content` verbatim; `source` tells them apart.
|
||||
*/
|
||||
'user/message': UserMessage
|
||||
@@ -494,6 +494,8 @@ interface TurnEndReasonMap {
|
||||
completed: { kind: 'completed' }
|
||||
/** A cancellation request interrupted the live turn. */
|
||||
aborted: { kind: 'aborted'; reason: AgentCancelCause }
|
||||
|
||||
blocked: { kind: 'blocked' }
|
||||
/**
|
||||
* The turn failed.
|
||||
*/
|
||||
|
||||
@@ -26,9 +26,9 @@ interface UserMessage extends Message {
|
||||
*/
|
||||
interface SessionEventMap {
|
||||
/**
|
||||
* Opens turn `turn`. Every turn begins when the loop admits queued input;
|
||||
* the following identified `user/message` event or batch records the
|
||||
* admitted input.
|
||||
* Opens turn `turn`. Every turn begins after the loop claims queued input
|
||||
* and accepts the pre-step result; the following identified `user/message`
|
||||
* event or batch records the messages entering the step.
|
||||
*/
|
||||
'turn/start': { turn: number }
|
||||
/**
|
||||
@@ -46,7 +46,7 @@ interface SessionEventMap {
|
||||
* A user-role message on the model-visible surface: a direct human prompt
|
||||
* (the queued message claimed for this turn), a synthetic `agent.inject()`
|
||||
* context (file-change notices, subdir AGENTS.md, skill content, cron
|
||||
* notifications, …), or an admitted goal continuation round. All three
|
||||
* notifications, …), or an entered goal continuation round. All three
|
||||
* project their `content` verbatim; `source` tells them apart.
|
||||
*/
|
||||
'user/message': UserMessage
|
||||
@@ -498,6 +498,8 @@ interface TurnEndReasonMap {
|
||||
completed: { kind: 'completed' }
|
||||
/** A cancellation request interrupted the live turn. */
|
||||
aborted: { kind: 'aborted'; reason: AgentCancelCause }
|
||||
|
||||
blocked: { kind: 'blocked' }
|
||||
/**
|
||||
* The turn failed.
|
||||
*/
|
||||
|
||||
@@ -8,18 +8,18 @@ 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:157`](../packages/core/agent-loop/src/index.ts) | [`agent-loop`](../packages/core/agent-loop) (`events.dispatch`) | [`tui`](../packages/ui/tui) |
|
||||
| `agent/created` | `emit` | [`packages/core/agent/src/types.ts:171`](../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:180`](../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:281`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | `apiproxy`, [`goal-session`](../packages/goal/goal-session), [`session-telemetry`](../packages/telemetry/session-telemetry), [`tui`](../packages/ui/tui) |
|
||||
| `agent/inbox/claimed` | `emit` | [`packages/core/agent/src/types.ts:201`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`tui`](../packages/ui/tui) |
|
||||
| `agent/inbox/discarded` | `emit` | [`packages/core/agent/src/types.ts:209`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`tui`](../packages/ui/tui) |
|
||||
| `agent/inbox/inserted` | `emit` | [`packages/core/agent/src/types.ts:193`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | — |
|
||||
| `agent/pre-step` | `waterfall` | [`packages/core/agent/src/types.ts:225`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`compact-basic`](../packages/compact/compact-basic), [`goal-session`](../packages/goal/goal-session), [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`plan-mode`](../packages/plan/plan-mode), [`repeat-tool-guard`](../packages/guard/repeat-tool-guard), [`session-checkpoint-policy`](../packages/session-persistence/session-checkpoint-policy), [`time-context`](../packages/context/time-context), [`tmux-context`](../packages/context/tmux-context), [`tool-skill`](../packages/skill/tool-skill), [`tui`](../packages/ui/tui), [`user-approval`](../packages/ui/user-approval), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `agent/request` | `waterfall` | [`packages/core/agent/src/types.ts:242`](../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:254`](../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:202`](../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/status` | `emit` | [`packages/core/agent/src/types.ts:190`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`agent`](../packages/core/agent), `apiproxy`, [`compact-basic`](../packages/compact/compact-basic), [`goal-session`](../packages/goal/goal-session), [`jsonrpc`](../packages/ui/jsonrpc), [`tui`](../packages/ui/tui) |
|
||||
| `agent/turn-stopping` | `serial` | [`packages/core/agent/src/types.ts:269`](../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/created` | `emit` | [`packages/core/agent/src/types.ts:166`](../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:175`](../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:285`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | `apiproxy`, [`goal-session`](../packages/goal/goal-session), [`session-telemetry`](../packages/telemetry/session-telemetry), [`tui`](../packages/ui/tui) |
|
||||
| `agent/inbox/claimed` | `emit` | [`packages/core/agent/src/types.ts:201`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`goal-session`](../packages/goal/goal-session), [`tui`](../packages/ui/tui) |
|
||||
| `agent/inbox/discarded` | `emit` | [`packages/core/agent/src/types.ts:209`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`goal-session`](../packages/goal/goal-session), [`tui`](../packages/ui/tui) |
|
||||
| `agent/inbox/inserted` | `emit` | [`packages/core/agent/src/types.ts:193`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`goal-session`](../packages/goal/goal-session) |
|
||||
| `agent/pre-step` | `waterfall` | [`packages/core/agent/src/types.ts:233`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`waterfall`) | [`compact-basic`](../packages/compact/compact-basic), [`goal-session`](../packages/goal/goal-session), [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`plan-mode`](../packages/plan/plan-mode), [`repeat-tool-guard`](../packages/guard/repeat-tool-guard), [`session-checkpoint-policy`](../packages/session-persistence/session-checkpoint-policy), [`time-context`](../packages/context/time-context), [`tmux-context`](../packages/context/tmux-context), [`tool-skill`](../packages/skill/tool-skill), [`tui`](../packages/ui/tui), [`user-approval`](../packages/ui/user-approval), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `agent/request` | `waterfall` | [`packages/core/agent/src/types.ts:246`](../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:258`](../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:221`](../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) |
|
||||
| `agent/status` | `emit` | [`packages/core/agent/src/types.ts:185`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | [`agent`](../packages/core/agent), `apiproxy`, [`compact-basic`](../packages/compact/compact-basic), [`goal-session`](../packages/goal/goal-session), [`jsonrpc`](../packages/ui/jsonrpc), [`tui`](../packages/ui/tui) |
|
||||
| `agent/turn-stopping` | `serial` | [`packages/core/agent/src/types.ts:273`](../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), `apiproxy` |
|
||||
| `commands/change` | `emit` | [`packages/ui/commands/src/index.ts:154`](../packages/ui/commands/src/index.ts) | [`commands`](../packages/ui/commands) (`events.dispatch`) | `apiproxy`, [`tui`](../packages/ui/tui) |
|
||||
| `credentials/updated` | `emit` | [`packages/credentials/credentials/src/index.ts:67`](../packages/credentials/credentials/src/index.ts) | [`credentials`](../packages/credentials/credentials) (`events.dispatch`) | `apiproxy`, [`credentials`](../packages/credentials/credentials) |
|
||||
@@ -32,7 +32,7 @@ This matrix shows which packages dispatch each harness-owned event and which pac
|
||||
| `llm/stream` | `waterfall` | [`packages/llm/llm/src/index.ts:57`](../packages/llm/llm/src/index.ts) | [`llm`](../packages/llm/llm) (`waterfall`) | [`agent-loop`](../packages/core/agent-loop), [`llm`](../packages/llm/llm), [`llm-replay`](../packages/support/llm-replay), [`session-checkpoint-policy`](../packages/session-persistence/session-checkpoint-policy), [`session-title`](../packages/session-title/session-title) |
|
||||
| `session/created` | `emit` | [`packages/core/session/src/index.ts:50`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | `apiproxy`, [`compact`](../packages/compact/compact), [`goal`](../packages/goal/goal), [`hook-protocol`](../packages/hooks/hook-protocol), [`jsonrpc`](../packages/ui/jsonrpc), [`llm-retry`](../packages/llm/llm-retry), [`plan-mode`](../packages/plan/plan-mode), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`session-telemetry`](../packages/telemetry/session-telemetry), [`tools`](../packages/core/tools), [`user-approval`](../packages/ui/user-approval) |
|
||||
| `session/disposed` | `emit` | [`packages/core/session/src/index.ts:60`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`agent-loop`](../packages/core/agent-loop), `apiproxy`, [`session-persistence`](../packages/session-persistence/session-persistence), [`session-projection-cache`](../packages/session-projection/session-projection-cache), [`session-telemetry`](../packages/telemetry/session-telemetry), [`session-title`](../packages/session-title/session-title) |
|
||||
| `session/event` | `emit` | [`packages/core/session/src/index.ts:72`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`acp`](../packages/acp/acp), `apiproxy`, [`cli-demo`](../packages/examples/cli-demo), [`compact`](../packages/compact/compact), [`compact-basic`](../packages/compact/compact-basic), [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hook-protocol`](../packages/hooks/hook-protocol), [`jsonrpc`](../packages/ui/jsonrpc), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`session-projection`](../packages/session-projection/session-projection), [`session-projection-cache`](../packages/session-projection/session-projection-cache), [`session-telemetry`](../packages/telemetry/session-telemetry), [`session-title`](../packages/session-title/session-title), [`token-meter`](../packages/llm/token-meter), [`tools`](../packages/core/tools), [`tui`](../packages/ui/tui), [`user-approval`](../packages/ui/user-approval), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `session/event` | `emit` | [`packages/core/session/src/index.ts:72`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`acp`](../packages/acp/acp), `apiproxy`, [`cli-demo`](../packages/examples/cli-demo), [`compact`](../packages/compact/compact), [`compact-basic`](../packages/compact/compact-basic), [`goal`](../packages/goal/goal), [`goal-session`](../packages/goal/goal-session), [`hook-protocol`](../packages/hooks/hook-protocol), [`jsonrpc`](../packages/ui/jsonrpc), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`session-projection`](../packages/session-projection/session-projection), [`session-projection-cache`](../packages/session-projection/session-projection-cache), [`session-telemetry`](../packages/telemetry/session-telemetry), [`session-title`](../packages/session-title/session-title), [`token-meter`](../packages/llm/token-meter), [`tools`](../packages/core/tools), [`tui`](../packages/ui/tui), [`user-approval`](../packages/ui/user-approval) |
|
||||
| `session/flush` | `parallel` | [`packages/core/session/src/index.ts:82`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`session-persistence`](../packages/session-persistence/session-persistence), [`session-telemetry`](../packages/telemetry/session-telemetry) |
|
||||
| `settings/document-updated` | `emit` | [`packages/settings/settings/src/index.ts:150`](../packages/settings/settings/src/index.ts) | [`settings`](../packages/settings/settings) (`events.dispatch`) | `apiproxy` |
|
||||
| `settings/updated` | `emit` | [`packages/settings/settings/src/index.ts:137`](../packages/settings/settings/src/index.ts) | [`settings`](../packages/settings/settings) (`events.dispatch`) | [`settings`](../packages/settings/settings) |
|
||||
@@ -47,7 +47,7 @@ This matrix shows which packages dispatch each harness-owned event and which pac
|
||||
| `tools/change` | `emit` | [`packages/core/tools/src/index.ts:160`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`emit`) | - |
|
||||
| `tools/code-dispatch-log` | `waterfall` | [`packages/core/tools/src/index.ts:142`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`spill-policy`](../packages/spill/spill-policy) |
|
||||
| `tools/execute` | `waterfall` | [`packages/core/tools/src/index.ts:117`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`session-checkpoint-policy`](../packages/session-persistence/session-checkpoint-policy), [`timeout-policy`](../packages/timeout/timeout-policy) |
|
||||
| `tools/post-execute` | `waterfall` | [`packages/core/tools/src/index.ts:129`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`repeat-tool-guard`](../packages/guard/repeat-tool-guard), [`spill-policy`](../packages/spill/spill-policy), [`tool-fs-search`](../packages/fs/tool-fs-search), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `tools/post-execute` | `waterfall` | [`packages/core/tools/src/index.ts:129`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`repeat-tool-guard`](../packages/guard/repeat-tool-guard), [`spill-policy`](../packages/spill/spill-policy), [`tool-fs-search`](../packages/fs/tool-fs-search) |
|
||||
| `tools/pre-execute` | `waterfall` | [`packages/core/tools/src/index.ts:106`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`tool-tasks`](../packages/tasks/tool-tasks) |
|
||||
| `tools/result` | `emit` | [`packages/core/tools/src/index.ts:150`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`events.dispatch`) | [`subagent-inprocess`](../packages/subagent/subagent-inprocess), [`workspace-context`](../packages/context/workspace-context) |
|
||||
| `workflow/agent-end` | `emit` | [`packages/workflow/workflow/src/index.ts:81`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | [`workflow`](../packages/workflow/workflow) |
|
||||
|
||||
@@ -97,11 +97,11 @@ Sources: [`packages/core/session/src/types.ts:262`](../packages/core/session/src
|
||||
start: number
|
||||
removedCount?: number
|
||||
inserted: UserMessage[]
|
||||
outcome?: 'admitted' | 'canceled'
|
||||
outcome?: 'canceled'
|
||||
}
|
||||
```
|
||||
|
||||
Source: [`packages/core/agent/src/types.ts:292`](../packages/core/agent/src/types.ts)
|
||||
Source: [`packages/core/agent/src/types.ts:296`](../packages/core/agent/src/types.ts)
|
||||
|
||||
### `approval/*`
|
||||
|
||||
@@ -636,9 +636,9 @@ Source: [`packages/core/session/src/types.ts:181`](../packages/core/session/src/
|
||||
|
||||
```ts persistence-catalog
|
||||
/**
|
||||
* Opens turn `turn`. Every turn begins when the loop admits queued input;
|
||||
* the following identified `user/message` event or batch records the
|
||||
* admitted input.
|
||||
* Opens turn `turn`. Every turn begins after the loop claims queued input
|
||||
* and accepts the pre-step result; the following identified `user/message`
|
||||
* event or batch records the messages entering the step.
|
||||
*/
|
||||
'turn/start': { turn: number }
|
||||
```
|
||||
@@ -654,7 +654,7 @@ Source: [`packages/core/session/src/types.ts:174`](../packages/core/session/src/
|
||||
* A user-role message on the model-visible surface: a direct human prompt
|
||||
* (the queued message claimed for this turn), a synthetic `agent.inject()`
|
||||
* context (file-change notices, subdir AGENTS.md, skill content, cron
|
||||
* notifications, …), or an admitted goal continuation round. All three
|
||||
* notifications, …), or an entered goal continuation round. All three
|
||||
* project their `content` verbatim; `source` tells them apart.
|
||||
*/
|
||||
'user/message': UserMessage
|
||||
|
||||
@@ -25,7 +25,7 @@ This table connects model-visible tool names to the plugin package and service s
|
||||
| `@deepseek-ai/dsh-tool-fs` | `edit`, `read`, `write` | `ctx.tools`, `ctx.fs`, `ctx.systemPrompt` | `tool/call`, `fs/write-intent or fs/edit-intent for mutations`, `fs/observed after successful file operations`, `tool/result` | - | The read-before-write/edit policy is added by `@deepseek-ai/dsh-fs-policy` (an `fs/*` event-gate plugin, no schema change); a deployment that loads these tools is expected to also load it. The tool schemas above are identical with or without the policy plugin. |
|
||||
| `@deepseek-ai/dsh-tool-fs-search` | `glob`, `grep` | `ctx.tools`, `ctx.bash`, `ctx.systemPrompt` | `tool/call`, `tool/result` | - | glob and grep are conditional bash-backed discovery tools: they register only when ctx.bash can find `rg`, then run fixed ripgrep commands through ctx.bash as ordinary foreground calls (never background tasks). The catalog uses `sampleOverCapGlobResults: true`; deployments must choose that behavior explicitly. Capped results save the complete formatted list through the optional ctx.spillStore backend; returned locators are follow-up-readable/searchable when the backend exposes local paths in co-located deployments. |
|
||||
| `@deepseek-ai/dsh-tool-pty` | `terminal_close`, `terminal_list`, `terminal_open`, `terminal_read`, `terminal_send`, `terminal_signal` | `ctx.tools`, `ctx.pty`, `ctx.systemPrompt`, `ctx.tasks at call time for run_in_background` | `tool/call`, `tool/result` | - | The six terminal tools are opt-in and complement one-shot bash/filesystem tools. `terminal_send(run_in_background: true)` registers with `ctx.tasks`; TUI, named key sequences, BEL, resize, auto-start, and cross-agent sharing are absent from the schema. |
|
||||
| `@deepseek-ai/dsh-tool-goal` | `create_goal`, `get_goal`, `update_goal` | `ctx.tools`, `ctx.agents`, `ctx.goals`, `ctx.systemPrompt`, `a calling Agent in an authorized open turn` | `tool/call`, `user/message goal snapshot for mutations`, `tool/result` | - | create, edit, pause, and resume require direct-human root authority; complete and blocked also accept the exact current goal round. The default blocked lower bound is three admitted rounds. |
|
||||
| `@deepseek-ai/dsh-tool-goal` | `create_goal`, `get_goal`, `update_goal` | `ctx.tools`, `ctx.agents`, `ctx.goals`, `ctx.systemPrompt`, `a calling Agent in an authorized open turn` | `tool/call`, `agent/inbox/spliced goal snapshot for mutations`, `tool/result` | - | create, edit, pause, and resume require direct-human root authority; complete and blocked also accept the exact current goal round. The default blocked lower bound is three admitted rounds. |
|
||||
| `@deepseek-ai/dsh-tool-lsp` | `lsp` | `ctx.tools`, `ctx.lsp`, `ctx.systemPrompt` | `tool/call`, `tool/result` | - | The lsp tool keeps provider selection and language-server subprocesses behind ctx.lsp, so its model-visible schema stays stable across providers. Requires a registered provider (e.g. `@deepseek-ai/dsh-lsp-local`) at runtime; without one, a query returns the structured `LSP_UNAVAILABLE` error rather than changing the schema. |
|
||||
| `@deepseek-ai/dsh-tool-ralph` | `ralph` | `ctx.tools`, `ctx.workflows`, `ctx.subagents`, `ctx.systemPrompt`, `a calling Agent (exec.agent parents every fresh round)` | `tool/call`, `tool/result`, `workflow and child session events during execution` | - | A fixed foreground workflow starts one fresh structured child per round; the model selects only the immutable objective and an optional round cap. |
|
||||
| `@deepseek-ai/dsh-tool-skill` | `skill` | `ctx.tools`, `ctx.agents`, `ctx.skills` | `tool/call`, `tool/result`, `user/message replacement catalogs via agent.inject()` | - | - |
|
||||
|
||||
Reference in New Issue
Block a user