dsh-plugin-dev-kb 1.0.9 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/README.en.md +14 -8
- package/README.md +14 -8
- package/docs/banner.svg +25 -0
- package/kb/INDEX.md +8 -2
- package/kb/README.md +4 -4
- package/kb/extra/AGENTS.md +3 -3
- package/kb/extra/cookbook/adding-a-remote-api.md +197 -0
- package/kb/extra/cookbook/adding-a-remote-api.zh.md +197 -0
- package/kb/extra/cookbook/adding-a-session-format-version.md +109 -0
- package/kb/extra/cookbook/adding-a-session-format-version.zh.md +109 -0
- package/kb/extra/cookbook/adding-a-vendored-package.md +1 -1
- package/kb/extra/cookbook/adding-a-vendored-package.zh.md +1 -1
- package/kb/extra/cookbook/responding-to-pr-review-on-a-stack.md +1 -1
- package/kb/extra/cookbook/responding-to-pr-review-on-a-stack.zh.md +1 -1
- package/kb/extra/deepseek-llm-api-wire-extensions.md +19 -15
- package/kb/extra/deepseek-llm-api-wire-extensions.zh.md +19 -15
- package/kb/extra/development.md +13 -3
- package/kb/extra/development.zh.md +13 -3
- package/kb/extra/event-producer-consumer.md +49 -46
- package/kb/extra/event-producer-consumer.zh.md +52 -49
- package/kb/extra/i18n/README.md +2 -1
- package/kb/extra/i18n/README.zh.md +3 -2
- package/kb/extra/i18n/style-samples.md +2 -2
- package/kb/extra/i18n/translation-prompt.md +1 -1
- package/kb/extra/module-graph.md +493 -1002
- package/kb/extra/module-graph.zh.md +495 -1004
- package/kb/extra/rescope.md +1 -1
- package/kb/extra/rescope.zh.md +1 -1
- package/kb/extra/session-format-status.md +47 -0
- package/kb/extra/session-format-status.zh.md +47 -0
- package/kb/extra/subsystems/agent-team.md +3 -2
- package/kb/extra/subsystems/agent-team.zh.md +3 -2
- package/kb/extra/subsystems/attachment.md +157 -4
- package/kb/extra/subsystems/attachment.zh.md +157 -4
- package/kb/extra/subsystems/feedback.md +164 -30
- package/kb/extra/subsystems/feedback.zh.md +164 -30
- package/kb/extra/testing.md +9 -4
- package/kb/extra/testing.zh.md +9 -4
- package/kb/extra/web-styling.md +5 -0
- package/kb/extra/web-styling.zh.md +5 -0
- package/kb/meta/search-index.json +223 -151
- package/kb/meta/site-pages.txt +187 -181
- package/kb/meta/source.json +5 -5
- package/kb/meta/topics.md +5 -5
- package/kb/site/develop/basic/publish.md +1 -1
- package/kb/site/develop/cordis-tutorial/07-into-the-harness.md +3 -2
- package/kb/site/develop/practice/llm-adapter.md +4 -3
- package/kb/site/en/develop/basic/publish.md +1 -1
- package/kb/site/en/develop/cordis-tutorial/07-into-the-harness.md +3 -2
- package/kb/site/en/develop/practice/llm-adapter.md +4 -3
- package/kb/site/en/guide/network-proxy.md +87 -0
- package/kb/site/en/guide/providers.md +70 -17
- package/kb/site/en/guide/python-sdk.md +19 -3
- package/kb/site/en/guide/schedule.md +2 -0
- package/kb/site/en/reference/agent-lifecycle.md +17 -8
- package/kb/site/en/reference/api-gateway.md +2 -2
- package/kb/site/en/reference/capability-seams.md +24 -10
- package/kb/site/en/reference/config-catalog.md +322 -264
- package/kb/site/en/reference/cookbook/adding-a-package.md +1 -2
- package/kb/site/en/reference/cookbook/adding-a-settings-card.md +10 -8
- package/kb/site/en/reference/cookbook/adding-a-tool.md +1 -1
- package/kb/site/en/reference/cookbook/extension-cookbook.md +16 -13
- package/kb/site/en/reference/index.md +26 -9
- package/kb/site/en/reference/persistence-catalog.md +189 -95
- package/kb/site/en/reference/subsystems/approval.md +1 -1
- package/kb/site/en/reference/subsystems/client-modules.md +9 -0
- package/kb/site/en/reference/subsystems/client-resources.md +94 -0
- package/kb/site/en/reference/subsystems/code-runtime.md +7 -3
- package/kb/site/en/reference/subsystems/commands.md +25 -16
- package/kb/site/en/reference/subsystems/compaction.md +10 -10
- package/kb/site/en/reference/subsystems/conversation.md +11 -4
- package/kb/site/en/reference/subsystems/core.md +173 -29
- package/kb/site/en/reference/subsystems/credentials.md +5 -4
- package/kb/site/en/reference/subsystems/filesystem.md +15 -0
- package/kb/site/en/reference/subsystems/goal.md +38 -2
- package/kb/site/en/reference/subsystems/index.md +3 -1
- package/kb/site/en/reference/subsystems/invariants.md +1 -1
- package/kb/site/en/reference/subsystems/llm-streaming.md +43 -12
- package/kb/site/en/reference/subsystems/lsp.md +1 -1
- package/kb/site/en/reference/subsystems/permission-presets.md +5 -5
- package/kb/site/en/reference/subsystems/persistence.md +211 -199
- package/kb/site/en/reference/subsystems/plan.md +3 -3
- package/kb/site/en/reference/subsystems/sandbox.md +2 -0
- package/kb/site/en/reference/subsystems/schedule.md +9 -3
- package/kb/site/en/reference/subsystems/scope.md +1 -1
- package/kb/site/en/reference/subsystems/session-projection.md +50 -24
- package/kb/site/en/reference/subsystems/session-query.md +19 -13
- package/kb/site/en/reference/subsystems/session-reference.md +29 -1
- package/kb/site/en/reference/subsystems/session-telemetry.md +27 -10
- package/kb/site/en/reference/subsystems/session-title.md +6 -6
- package/kb/site/en/reference/subsystems/session.md +208 -103
- package/kb/site/en/reference/subsystems/settings.md +30 -12
- package/kb/site/en/reference/subsystems/shell.md +9 -6
- package/kb/site/en/reference/subsystems/sidebar-right.md +151 -0
- package/kb/site/en/reference/subsystems/skills.md +1 -1
- package/kb/site/en/reference/subsystems/slots.md +41 -32
- package/kb/site/en/reference/subsystems/spill.md +13 -6
- package/kb/site/en/reference/subsystems/storage.md +28 -5
- package/kb/site/en/reference/subsystems/subagent.md +58 -105
- package/kb/site/en/reference/subsystems/subprocess.md +25 -26
- package/kb/site/en/reference/subsystems/system-prompt.md +18 -3
- package/kb/site/en/reference/subsystems/token-meter.md +4 -3
- package/kb/site/en/reference/subsystems/tools.md +5 -5
- package/kb/site/en/reference/subsystems/typert.md +18 -18
- package/kb/site/en/reference/subsystems/web-client.md +1 -1
- package/kb/site/en/reference/subsystems/workspace.md +88 -9
- package/kb/site/en/reference/tool-catalog.md +56 -66
- package/kb/site/en/reference/tool-execution-pipeline.md +2 -2
- package/kb/site/guide/network-proxy.md +87 -0
- package/kb/site/guide/providers.md +70 -17
- package/kb/site/guide/python-sdk.md +19 -3
- package/kb/site/guide/schedule.md +2 -0
- package/kb/site/reference/agent-lifecycle.md +17 -8
- package/kb/site/reference/api-gateway.md +2 -2
- package/kb/site/reference/capability-seams.md +24 -10
- package/kb/site/reference/config-catalog.md +321 -263
- package/kb/site/reference/cookbook/adding-a-package.md +1 -2
- package/kb/site/reference/cookbook/adding-a-settings-card.md +10 -8
- package/kb/site/reference/cookbook/adding-a-tool.md +1 -1
- package/kb/site/reference/cookbook/extension-cookbook.md +16 -13
- package/kb/site/reference/index.md +26 -9
- package/kb/site/reference/persistence-catalog.md +190 -96
- package/kb/site/reference/subsystems/approval.md +1 -1
- package/kb/site/reference/subsystems/client-modules.md +9 -0
- package/kb/site/reference/subsystems/client-resources.md +94 -0
- package/kb/site/reference/subsystems/code-runtime.md +7 -3
- package/kb/site/reference/subsystems/commands.md +25 -16
- package/kb/site/reference/subsystems/compaction.md +10 -10
- package/kb/site/reference/subsystems/conversation.md +11 -4
- package/kb/site/reference/subsystems/core.md +173 -29
- package/kb/site/reference/subsystems/credentials.md +5 -4
- package/kb/site/reference/subsystems/filesystem.md +15 -0
- package/kb/site/reference/subsystems/goal.md +38 -2
- package/kb/site/reference/subsystems/index.md +14 -12
- package/kb/site/reference/subsystems/invariants.md +1 -1
- package/kb/site/reference/subsystems/llm-streaming.md +43 -12
- package/kb/site/reference/subsystems/lsp.md +1 -1
- package/kb/site/reference/subsystems/permission-presets.md +5 -5
- package/kb/site/reference/subsystems/persistence.md +210 -198
- package/kb/site/reference/subsystems/plan.md +3 -3
- package/kb/site/reference/subsystems/schedule.md +9 -3
- package/kb/site/reference/subsystems/scope.md +1 -1
- package/kb/site/reference/subsystems/session-projection.md +50 -24
- package/kb/site/reference/subsystems/session-query.md +19 -13
- package/kb/site/reference/subsystems/session-reference.md +29 -1
- package/kb/site/reference/subsystems/session-telemetry.md +27 -10
- package/kb/site/reference/subsystems/session-title.md +6 -6
- package/kb/site/reference/subsystems/session.md +208 -103
- package/kb/site/reference/subsystems/settings.md +30 -12
- package/kb/site/reference/subsystems/shell.md +9 -6
- package/kb/site/reference/subsystems/sidebar-right.md +151 -0
- package/kb/site/reference/subsystems/skills.md +1 -1
- package/kb/site/reference/subsystems/slots.md +41 -32
- package/kb/site/reference/subsystems/spill.md +13 -6
- package/kb/site/reference/subsystems/storage.md +28 -5
- package/kb/site/reference/subsystems/subagent.md +58 -105
- package/kb/site/reference/subsystems/subprocess.md +25 -26
- package/kb/site/reference/subsystems/system-prompt.md +18 -3
- package/kb/site/reference/subsystems/token-meter.md +4 -3
- package/kb/site/reference/subsystems/tools.md +5 -5
- package/kb/site/reference/subsystems/typert.md +18 -18
- package/kb/site/reference/subsystems/web-client.md +1 -1
- package/kb/site/reference/subsystems/workspace.md +88 -9
- package/kb/site/reference/tool-catalog.md +55 -65
- package/kb/site/reference/tool-execution-pipeline.md +2 -2
- package/lib/index.js +25 -44
- package/package.json +3 -2
- package/skills/dsh-plugin-dev-kb.md +4 -4
|
@@ -7,10 +7,12 @@ outline: [2,3]
|
|
|
7
7
|
|
|
8
8
|
subagent seam 让一个 agent(智能体)将工作委派给子 agent。与 [bash](./shell.md) 一样,它是**一项可选能力**,不属于 agent loop(智能体循环),因此其类型定义在此而非 [core.md](./core.md) 中。它不同于其他能力 seam,因为**同一上下文中可共存多个提供方实现**,并按名称注册(`ctx.subagents`),而 bash 只允许一个执行器。该注册表遵循 [LLM(大语言模型)适配器注册表](./llm-streaming.md),而非单服务的 bash 执行器。
|
|
9
9
|
|
|
10
|
-
Service Definition:[dsh-subagent](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/subagent/subagent)(`ctx.subagents` + 下文词汇)。Service Provider 是六个兄弟包:`dsh-subagent-spawn-in-process`、`dsh-subagent-fork-in-process`、`dsh-subagent-acp`、`dsh-subagent-codex`、`dsh-subagent-claude-code`、`dsh-subagent-dsh-sdk`;面向模型的 Consumer 包括 [dsh-tool-subagent](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/subagent/tool-subagent)
|
|
10
|
+
Service Definition:[dsh-subagent](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/subagent/subagent)(`ctx.subagents` + 下文词汇)。Service Provider 是六个兄弟包:`dsh-subagent-spawn-in-process`、`dsh-subagent-fork-in-process`、`dsh-subagent-acp`、`dsh-subagent-codex`、`dsh-subagent-claude-code`、`dsh-subagent-dsh-sdk`;面向模型的 Consumer 包括 [dsh-tool-subagent](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/subagent/tool-subagent)(按提供方委派)和 [dsh-tool-subagent-control](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/subagent/tool-subagent-control)(可选的全局 `send_message`、`interrupt_agent` 与 `list_agents` 控制工具)。同一个 `ctx.subagents` 服务通过内部激活管理器负责可继续子 agent 编排,并直接基于会话存储和可选的会话持久化提供只读的 child 与后代发现。产品提供方设计理由见 [Codex 与 Claude Code Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/feature/2026-08-04-claude-code-and-codex-subagent-backends.zh.md);通用 seam 的设计理由见 [subagent Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.zh.md)、[可继续 subagent Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/feature/2026-07-28-continuable-subagent-conversations.zh.md)和[相邻 Agent 消息 Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/architecture/2026-08-27-adjacent-agent-steer-messaging.zh.md);[已归档的列表身份投影记录](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/archived/architecture/2026-08-06-subagent-list-identity-projection.md)记录了最初的列表身份决策。
|
|
11
11
|
|
|
12
12
|
源码:[`packages/subagent/subagent/src/types.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/subagent/subagent/src/types.ts)、[`packages/subagent/subagent/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/subagent/subagent/src/index.ts)和 [`packages/subagent/subagent/src/continuation.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/subagent/subagent/src/continuation.ts)
|
|
13
13
|
|
|
14
|
+
`subagentCatalog` projection 通过 Session 观察和客户端快照暴露按父会话事件排序的 `SubagentCatalogEntry[]`。每个条目包含子级 id、创建时间、模式和依模式确定的标签;fork 继承的目录事实不在其中。[subagent 包](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/subagent/subagent/README.zh.md) 定义目录创建和持久化语义。
|
|
15
|
+
|
|
14
16
|
## 两类能力,两种发现方式
|
|
15
17
|
|
|
16
18
|
提供方通过一个静态描述符公布其**启动时**功能,服务会在单次 run 存在之前即行检查;如果请求依赖提供方不具备的功能,会被明确拒绝(`SubagentError('UNSUPPORTED_CAPABILITY')`),绝不会被接受后静默忽略。这些 flag 仅描述单次 [`start()`](#the-provider-contract-subagentprovider) 路径,即由提供方组合子 agent 的路径。**可继续**子 agent 由继续执行管理器自行组合,因此它们由唯一一个可选方法把关,方法存在即为能力,并以 TypeScript 的类型收窄作为发现机制:[`SubagentProvider.prepareContinuable`](#the-provider-contract-subagentprovider)。
|
|
@@ -99,7 +101,7 @@ interface SubagentStartRequest {
|
|
|
99
101
|
/**
|
|
100
102
|
* Optional per-child persona. Requires {@link SubagentCapabilities.persona};
|
|
101
103
|
* rejected at start otherwise. In-process backends register it as a scoped
|
|
102
|
-
* `deployment:persona` section on the child, SHADOWING the deployment's
|
|
104
|
+
* `deployment:persona-prefix` section on the child, SHADOWING the deployment's
|
|
103
105
|
* persona for this child alone — same template semantics as the deployment
|
|
104
106
|
* persona (strict `{{…}}` interpolation against the registered variables).
|
|
105
107
|
*/
|
|
@@ -136,21 +138,23 @@ persisted Session
|
|
|
136
138
|
|
|
137
139
|
`SubagentRuntime.startContinuable()` 会预留稳定的子 agent id,对版本化的 `subagent/descriptor` payload 建立快照,向指定提供方索取其分离的 `ContinuableCreateSpec`,通过私有的 activation-owner 作用域创建子 Agent,建立任何可继续父级的所有权,并提交初始提示词。当收件箱(inbox)准入产出消息 id 时,它以 `{ childId, messageId }` resolve——无需等待轮次开始,也无需等待消息进入会话日志。在该准入之前的任何失败都会以两个 id 都不返回的方式 reject,并 dispose(资源释放)任何已创建的 handle,回滚 Activation 与父级所有权。
|
|
138
140
|
|
|
139
|
-
`SubagentRuntime.
|
|
141
|
+
`SubagentRuntime.sendMessage()` 是唯一由模型编写消息的操作。它接收确切在线 sender 与目标 id,只允许直接 parent 或直接可继续 child,自行推导 sender 来源信息,并根据目标 child 的 Activation 驻留状态路由:
|
|
140
142
|
|
|
141
|
-
| Activation 状态 | `
|
|
143
|
+
| 目标 Activation 状态 | `sendMessage` |
|
|
142
144
|
|---|---|
|
|
143
|
-
| `running` | 在同一 Activation
|
|
144
|
-
| `waiting` |
|
|
145
|
-
| 无 Activation |
|
|
145
|
+
| `running` | 在同一 Activation 中 steer 最近的 step |
|
|
146
|
+
| `waiting` | 唤醒并 steer 同一 Activation |
|
|
147
|
+
| 无 Activation | 冷恢复新的 Activation,然后 steer |
|
|
148
|
+
|
|
149
|
+
`running` 表示 Agent 拥有活跃的 driver 或 maintenance 任务;`waiting` 表示没有活跃的 Agent 工作,但其 Inbox 非空或仍拥有至少一个尚未完成 dispose 的子 Activation;`settled` 表示没有活跃的 Agent 工作、Inbox 为空且其拥有的每个子级都已 dispose,此时管理器会 dispose [`AgentHandle`](./core.md#creation-and-ownership) 并移除该 Activation。管理器根据 `Agent.whenIdle()`、`Agent.inbox.hasPending`、其拥有的子级集合,以及让过期观察失效的 Activation generation 推导这些内部条件,而非维护第二套执行状态机。最终 Session flush 之后,child-lock 决策会通过 `Agent.runMaintenance()` 的同步 task 入口占用 idle 阶段,并在同一个 JavaScript turn 内关闭准入。这条保守规则不区分投递模式:`Agent.inject()` 停放的 context 可以让空闲 Activation 及其在线祖先继续驻留,直到唤醒投递将其 claim、queue 变更将其移除,或 manager teardown 将其丢弃。
|
|
146
150
|
|
|
147
|
-
|
|
151
|
+
Agent 收件箱是唯一队列。每条 Agent 消息都使用 `Agent.steer()`:空闲目标会启动一个轮次,运行中目标则在最近的 step 边界领取消息。浏览器 `subagent.prompt` Remote 会另行通过同一条内部准入路径携带 `delivery: 'queue' | 'steer'`;Queue 开启后续 FIFO 轮次,Steer 保留 Agent loop 的 best-effort 最近 step 行为以及消息的人类来源。投递成功会返回被接受的 `MessageId`;既有的 `agent/inbox/inserted`、`agent/inbox/claimed` 与 `agent/inbox/discarded` 事件仍是消息生命周期的观测点,继续执行层不定义第二条队列。
|
|
148
152
|
|
|
149
|
-
|
|
153
|
+
权限来自确切在线 sender。parent 到 child 的投递要求目标的 `SessionHeader.parentSession` 指向 sender;child 到 parent 的投递要求 sender 的驻留 Activation 指向目标。sibling、相隔多于一条边的 ancestor、self-target、陈旧 Agent 对象与一次性 child 都会被拒绝。每条已接受消息都以 `Agent <sender-id> sent a message:` 作为前缀,并记录 `AgentMessageSource`;来源信息记录 sender,但不授予权限。
|
|
150
154
|
|
|
151
|
-
|
|
155
|
+
对于 `startContinuable()`、`sendMessage()` 与浏览器 prompt 投递,调用方 signal 仅在收件箱接受之前掌管查找、物化与准入。此后管理器独立掌管该 Activation:之后的调用方取消既不会取消已接受的轮次,也不会 dispose 子 agent。公开 subagent 服务不暴露由调用方选择的 Agent 消息调度;浏览器人类 Queue 与 Steer 仍是内部适配器选择。
|
|
152
156
|
|
|
153
|
-
|
|
157
|
+
在线 queue occurrence 变更属于 Session 域。只有在线 subagent-owned Agent 的当前 projection identity 为 continuable,且其 descriptor 序号位于该 child 自身的非 seed suffix 时,`session.updateQueue` 才会接纳普通 Edit、Remove 与 QueueDock Steer。Identity projection 以 last-wins 方式折叠 descriptor,因此 child descriptor 会覆盖 fork lineage 保留的 descriptor;own-suffix 序号检查会阻止仅来自 seed 的祖先 identity 授权变更。One-shot、缺失、未知、损坏或冷 child 会被拒绝,queue 变更绝不会冷恢复 child。这些变更以目标 Session id 作为人类权限,包括待处理 `nextStep` steering 或注入 context。Steer 要求 queued `MessageId`,且 command 开始时 Agent 必须报告 running;准入后发生取消时,会使用 Agent 已接受的唤醒 `nextTurn` fallback。Edit 会在同一个 `MessageId` 下改写内容,且 Edit 与 Steer 都会同步完成 Inbox 变更,因此 settlement 只会观察最终状态。`agent/inbox/claimed` 与 `agent/inbox/discarded` 都会唤醒 watcher 重新读取是否仍有待处理 occurrence;这样,直接 Agent 投递可以恢复停放工作,而移除最后一个停放 occurrence 可使 idle child 结算。[人类 inbox 控制 Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/feature/2026-08-27-continuable-subagent-human-inbox-control.zh.md)拥有这些语义。
|
|
154
158
|
|
|
155
159
|
`SubagentRuntime.interrupt(targetSessionId, authority)` 是唯一的公开停止操作:它同步完成鉴权,对在线目标发出 `Agent.cancel(cause, { keepInbox: true })`,然后不等待完全停稳即返回。Activation、其尚未领取的待处理 inbox 工作与已发布的后代均不受影响;已被领取进入中断轮次的工作不会重新入队。被中断的 driver 进入 idle 后,一次唤醒发送会恢复被暂停的 FIFO 队列。不存在的目标——未知、一次性或已结算——以及未绑定管理器的组合是被接受的 no-op。对在线目标,错误的 parent 地址或不在其在线祖先链中的调用方会以 `UNAUTHORIZED` 拒绝;陈旧的 ancestor 对象和指向自身的 ancestor 请求会在查找目标前拒绝。
|
|
156
160
|
|
|
@@ -165,26 +169,24 @@ type SubagentInterruptAuthority =
|
|
|
165
169
|
| { readonly kind: 'ancestor'; readonly agent: Agent }
|
|
166
170
|
```
|
|
167
171
|
|
|
168
|
-
每个 Activation 都拥有自己的 `AgentHandle` 和一个 `ownedChildren: Set<SessionId>`;由于一份会话至多有一个存活 Activation,子会话 id 无需另一个运行时化身引用即可标识存活的子 agent。启动子 agent 或提交源自 parent 的工作,会在子 agent 能够运行之前将其注册到受继续执行管理的父级集合中;只要该集合非空,该父级就无法 settle。顶层或其他非继续执行的 Agent 没有 Activation,处于 waiting 图之外。只有当子 Agent
|
|
172
|
+
每个 Activation 都拥有自己的 `AgentHandle` 和一个 `ownedChildren: Set<SessionId>`;由于一份会话至多有一个存活 Activation,子会话 id 无需另一个运行时化身引用即可标识存活的子 agent。启动子 agent 或提交源自 parent 的工作,会在子 agent 能够运行之前将其注册到受继续执行管理的父级集合中;只要该集合非空,该父级就无法 settle。顶层或其他非继续执行的 Agent 没有 Activation,处于 waiting 图之外。只有当子 Agent 没有活跃工作、其 Inbox 为空、该子 agent 的每个子级都已 dispose、best-effort 的最终会话 flush 结算完毕,且子 agent 的 `AgentHandle` 完成 dispose 之后,才会释放子 agent。
|
|
169
173
|
|
|
170
174
|
最终结算会等待 `ctx.sessions.flush(session)`,但会忽略其参与布尔值,因为任意 listener 都无法证明某个持久化后端已存储该状态。rejection 会被记录,但不会使 Activation 失败;管理器仍会 dispose 该 handle 并释放所有权,此后持久化的子 agent 状态在后续恢复时可能缺失或陈旧。管理器卸载会调用内部的管理器全局 drain,关闭准入并 dispose 每片在线森林;`drainContinuableDescendants(parents)` 只关闭由 host 确切拥有的在线 Agent 之下的准入,并 dispose 其可继续后代,而无关森林保持在线。两者都会等待各自作用域内已获准的物化过程,自顶向下传播取消,按 child-first 顺序释放 handle,并且即使个别分支失败也会等待所有选中分支。持久化子会话不受该进程内拆卸的影响。
|
|
171
175
|
|
|
172
176
|
```ts type-equiv
|
|
173
|
-
/**
|
|
174
|
-
interface
|
|
175
|
-
readonly kind: '
|
|
177
|
+
/** Durable attribution for one model-authored message between adjacent Agents. */
|
|
178
|
+
interface AgentMessageSource {
|
|
179
|
+
readonly kind: 'agent-message'
|
|
176
180
|
/** A message another agent addressed to this one (`relay` context form). */
|
|
177
181
|
readonly form: 'relay'
|
|
178
|
-
/** Session id of the
|
|
182
|
+
/** Session id of the Agent whose tool call produced the message. */
|
|
179
183
|
readonly senderSessionId: SessionId
|
|
180
184
|
}
|
|
181
185
|
```
|
|
182
186
|
|
|
183
187
|
```ts type-equiv
|
|
184
|
-
/** Options for
|
|
185
|
-
interface
|
|
186
|
-
/** Durable attribution retained on the delivered message; it grants no authority. */
|
|
187
|
-
readonly source: MessageSource
|
|
188
|
+
/** Options for one model-authored message between adjacent Agents. */
|
|
189
|
+
interface SubagentSendMessageOptions {
|
|
188
190
|
/** Caller cancellation, owning the operation only until inbox acceptance. */
|
|
189
191
|
readonly signal: AbortSignal
|
|
190
192
|
}
|
|
@@ -200,33 +202,13 @@ interface ContinuableStart {
|
|
|
200
202
|
}
|
|
201
203
|
```
|
|
202
204
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
`SubagentRuntime.reportFrom()` 通过该扩展点实现报告,无需新增第二条队列或承载结果的 child 包装层。调用由确切的在线 child Agent 授权,调用方不能指定接收方。管理器从 child 的持久化 `parentSession` 中推导唯一接收方,要求该 parent Agent 必须在线,将选中内容封装为一条 `subagent-report` 用户消息,并返回该消息的稳定 `MessageId`。静默投递使用 `Agent.inject()`,不会唤醒 parent;next-step 投递使用 `Agent.steer()`,会唤醒空闲 parent,或加入运行中 parent 最近的 step 边界。两种模式都不会结束 child 轮次,最终回答也不会隐式报告。
|
|
206
|
-
|
|
207
|
-
```ts type-equiv
|
|
208
|
-
/** Durable attribution for a continuable child's explicit parent report. */
|
|
209
|
-
interface SubagentReportMessageSource {
|
|
210
|
-
readonly kind: 'subagent-report'
|
|
211
|
-
/** A message another agent addressed to this one (`relay` context form). */
|
|
212
|
-
readonly form: 'relay'
|
|
213
|
-
/** Session id of the reporting child. */
|
|
214
|
-
readonly senderSessionId: SessionId
|
|
215
|
-
}
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
```ts type-equiv
|
|
219
|
-
/** Deployment scheduling policy for accepted child reports. */
|
|
220
|
-
type SubagentReportDelivery = 'quiet' | 'next-step'
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
上报是 child 自己的选择,因此管理器还保有一份属于自己的记账:当驻留 Activation 结算时,它会向该 child 持久化的直接 parent 投递一条通知,说明该 epoch 如何结束,并携带其最终 assistant 内容。对每个调用方拿到过 id 的 child,这条投递都是无条件的;它发生在会让 parent 被判定为已结算的所有权释放之前,并通过与上报相同的唤醒准入记账到达驻留 parent。若 parent 自身所在的谱系已在拆卸中,这条通知会以不唤醒的方式送达,因为唤醒一个静息 Agent 是开启一个轮次,而不是排队等待工作。其来源信息使用一个独立的 kind,因此 transcript(文本记录)绝不会把运行时的记账呈现为 child 自己写下的内容。
|
|
205
|
+
当驻留 Activation 结算时,管理器会向该 child 持久化的直接 parent 投递一条通知,说明该 epoch 如何结束,并携带其最终 assistant 内容。对每个调用方拿到过 id 的 child,这条投递都是无条件的;它发生在会让 parent 被判定为已结算的所有权释放之前,并通过与 Agent 消息相同的唤醒 Agent 投递到达驻留 parent。若 parent 自身所在的谱系已在拆卸中,这条通知会以不唤醒的方式送达,因为唤醒一个 idle Agent 是开启一个轮次,而不是排队等待工作。其来源信息使用一个独立的 kind,因此 transcript(文本记录)绝不会把运行时的记账呈现为 child 自己写下的内容。
|
|
224
206
|
|
|
225
207
|
```ts type-equiv
|
|
226
208
|
/**
|
|
227
209
|
* Durable attribution for the runtime's own account of a continuable child
|
|
228
210
|
* settling. Deliberately a different kind from
|
|
229
|
-
* {@link
|
|
211
|
+
* {@link AgentMessageSource}: an Agent message is content the sender chose,
|
|
230
212
|
* while this message is the manager stating what became of the child, and a
|
|
231
213
|
* transcript that merged them would credit the child with words it never wrote.
|
|
232
214
|
*/
|
|
@@ -241,16 +223,6 @@ interface SubagentSettledMessageSource {
|
|
|
241
223
|
}
|
|
242
224
|
```
|
|
243
225
|
|
|
244
|
-
```ts type-equiv
|
|
245
|
-
/** Options for one continuable child's report to its direct parent. */
|
|
246
|
-
interface SubagentReportOptions {
|
|
247
|
-
/** Already-resolved parent scheduling policy. */
|
|
248
|
-
readonly delivery: SubagentReportDelivery
|
|
249
|
-
/** Caller cancellation, owning authorization and admission until acceptance. */
|
|
250
|
-
readonly signal: AbortSignal
|
|
251
|
-
}
|
|
252
|
-
```
|
|
253
|
-
|
|
254
226
|
提供方只参与准备初始创建 spec,`spawn` 与 `fork` 在此有所不同。其返回的 spec 只携带分离的、提供方专属的创建输入——即可选的父级历史种子——不含 Agent、`AgentHandle`、提示词投递、结果、dispose 或恢复操作。冷恢复根本不经由提供方分发:管理器折叠通用描述符,通过同一个 activation-owner 作用域调用 `ctx.agents.resume()`,并提交等待中的轮次。
|
|
255
227
|
|
|
256
228
|
```ts type-equiv
|
|
@@ -293,11 +265,11 @@ interface ContinuableCreateSpec {
|
|
|
293
265
|
|
|
294
266
|
描述符([descriptor.ts](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/subagent/subagent/src/descriptor.ts) 中的 `SubagentDescriptorData`)是每个由会话支撑的 subagent 所使用、按模式判别的持久化身份。两种模式都携带提供方名称。`one-shot` 描述符可以携带调用方拥有的可选显示 `label`;`continuable` 描述符要求以委派 `description` 作为持久化创建标签,并另外对已解析的子 agent `agentOptions.provider`/`model`/`reasoningEffort` 与可选的 `persona`/`toolFilter` 建立快照,用于冷恢复。它绝不会对可合并扩展的 `AgentOptions` 对象建立快照,因此无关的扩展值不会破坏继续执行,后续新增组合配置输入则是一次有意的版本更改。描述符省略 `subagentDepth`(冷恢复以持久化 header 中的 `delegationDepth` 作为单调下界)和 `outputSchema`(单次运行或 Activation 的结果约定,而非持久化身份)。
|
|
295
267
|
|
|
296
|
-
本地一次性提供方会在子 agent 的初始轮次内、首次请求前追加描述符。继续执行管理器会在任何提供方提供的谱系之后、初始提示词获准之前追加描述符;`
|
|
268
|
+
本地一次性提供方会在子 agent 的初始轮次内、首次请求前追加描述符。继续执行管理器会在任何提供方提供的谱系之后、初始提示词获准之前追加描述符;`Session.inheritedEventCount` 仍是 fork 谱系边界:恢复时的描述符权威读取子 agent 自身的后缀,而供列表使用的身份投影以 last-wins 折叠 `subagent/descriptor`,子 agent 自己的描述符会覆盖 fork seed 中祖先的描述符。seeded cold list 会跳过 cache hint,直到权威 observation 提供该精确 cut。该事件只进入日志:不含 `surfaceOp`,绝不进入模型历史,并由仅追加日志跨压缩保留。格式错误的当前版本描述符属于损坏;本运行时无法对不受支持的版本进行分类。
|
|
297
269
|
|
|
298
270
|
## 持久化枚举:`listChildren()`、`listDescendants()` 与其条目
|
|
299
271
|
|
|
300
|
-
`SubagentRuntime.listChildren(parentSessionId)` 从 `ctx.sessions
|
|
272
|
+
`SubagentRuntime.listChildren(parentSessionId)` 从 `ctx.sessions` 与会话查询引擎 `listSessions()` 的实时优先合并中枚举 parent 直接且由会话支撑的 subagent——不会加载或恢复任何 Agent。候选是持久 header 携带 `origin: 'subagent'` 的直接 child;该标记只负责枚举分类与粗粒度的通用路由拒绝,不能证明描述符有效、child 可恢复或操作已获授权——身份由投影折叠负责,恢复由 Activation 约定负责。每行的 `mode`/`label` 是已注册 `subagent` projection unit 的值,经三级阶梯供值:存活 child 由注册表水位缓存供值(零日志读取);冷 child 先读可选的投影 checkpoint 缓存(`cachedSnapshot`——过 own-suffix seq 门的身份即定值,own descriptor 一经追加不可变);否则在一次 `query.observeSession()` 冷观察上经注册表折叠(有界并发,每次列表重新计算)。该缓存是纯可选加速层:服务缺席、行里是 `null` 哨兵或 key 缺席、seq 门不过、读取出错,都静默落到权威重折。折叠规则是 `subagent/descriptor` last-wins 且没有失败通道:子 agent 自己的描述符覆盖 fork seed 中祖先的描述符,格式错误或版本不认识的载荷折叠为可序列化的 `null` 哨兵,视同无值。结果是按 `createdAt`、再按 id 排序的 `SubagentListEntry[]`:取到身份即生成带有 `mode: 'one-shot' | 'continuable'` 和 `activity: 'running' | 'inactive'` 的 `child` 条目;可继续条目始终携带 `label`,一次性条目则只在启动调用方提供展示元数据时携带该字段。已定局而折叠无身份的候选生成 `corrupt` diagnostic——缺失、格式错误与版本不认识的描述符有意不再细分(`unsupported` 仍保留在类型中但从不产出);运行中而无身份的候选被省略(描述符落盘前的创建窗口);冷检查失败生成一条 `unavailable` diagnostic 并在下次列表自然重试,因此一个损坏的 sibling 不会隐藏健康 child。`hasChildren` 标记存在持久 subagent origin 的直接后代,读取自同一份合并材料。活动状态只表示逻辑记录是否在 `ctx.sessions` 中存活,而不表示结果或可恢复性。缺少持久化时,枚举退化为仅存活枚举而不是报错——此时冷 child 本就无法恢复。缺少 `ctx.sessionProjections` 注册表时,`listChildren()` 抛出携带错误码 `SUBAGENT_CONTROL_PROJECTIONS_UNAVAILABLE` 的 `SubagentError`,缺少会话存储时则抛出 `SUBAGENT_CONTROL_SESSION_STORE_UNAVAILABLE`,两者都在任何读取之前检查,因此零 child 的部署同样确定失败;列表工具在插件加载时要求 `ctx.subagents` 与 `ctx.agents`。UI 等服务消费方可以展示两种模式,并为无标签的一次性 child 选择回退展示;面向模型的 `list_agents` 适配器([dsh-tool-subagent-control](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/subagent/tool-subagent-control) 中可单独加载的 `/list-agents` 插件)则只保留可继续条目,并通过在线 Agent 注册表将状态细化为自己的 `running`/`idle`/`ready` 词汇,其中 `ready` 把仅存于存储的 child 命名为可恢复而非终态。枚举不会查询继续执行管理器的 Activation map、Agent 注册表或提供方可用性;`send_message` 仍是消息送达时的权威操作,列表中的运行中可继续 child 仍可能因所有权冲突而拒绝投递。[已归档的列表身份投影记录](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/archived/architecture/2026-08-06-subagent-list-identity-projection.md)记录了最初的读路径决策。
|
|
301
273
|
|
|
302
274
|
`SubagentRuntime.listDescendants(rootSessionId)` 将同一份实时优先语料与基于投影的解释应用到根的完整后代树,并按稳定 pre-order 输出。普通会话和一次性 child 仍作为遍历节点,因此其下的可继续后代仍可发现;只有 `origin: 'subagent'` 的候选会生成条目。每个返回的 child 或 diagnostic 都从枚举所得的持久 header 附加树位置;冷检查在提供身份前还会重新校验完整生命周期:
|
|
303
275
|
|
|
@@ -508,11 +480,11 @@ Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnp
|
|
|
508
480
|
|
|
509
481
|
### `ctx.subagentModelSelection` — `SubagentModelSelectionConfig`
|
|
510
482
|
|
|
511
|
-
Singleton settings owner read
|
|
483
|
+
Singleton settings owner read when delegation tools are composed for a Session.
|
|
512
484
|
|
|
513
485
|
```ts cordis-catalog
|
|
514
486
|
/**
|
|
515
|
-
* Read a detached selection preference for the next eligible
|
|
487
|
+
* Read a detached selection preference for the next eligible Session composition.
|
|
516
488
|
* @returns the enabled state and exact allowed routes.
|
|
517
489
|
*/
|
|
518
490
|
current(): SubagentModelSelectionSettings
|
|
@@ -539,21 +511,20 @@ Named provider registry with one-shot runs, durable discovery, and continuable-c
|
|
|
539
511
|
async startContinuable(spec: ContinuableStartSpec): Promise<ContinuableStart>
|
|
540
512
|
|
|
541
513
|
/**
|
|
542
|
-
*
|
|
543
|
-
*
|
|
544
|
-
*
|
|
545
|
-
*
|
|
546
|
-
*
|
|
547
|
-
* @param
|
|
548
|
-
* @param
|
|
549
|
-
* @param content -
|
|
550
|
-
* @param options -
|
|
551
|
-
* operation only before inbox acceptance.
|
|
514
|
+
* Steer one model-authored message to the sender's direct parent or direct
|
|
515
|
+
* continuable child. A running target admits it at the nearest step boundary;
|
|
516
|
+
* an idle target starts a turn, and an absent direct child cold-resumes from
|
|
517
|
+
* persistence. The service derives durable sender attribution from the exact
|
|
518
|
+
* live sender. Caller cancellation stops only pre-acceptance work.
|
|
519
|
+
* @param sender - exact live Agent authorizing and originating the message.
|
|
520
|
+
* @param targetId - durable direct-parent or direct-child session id.
|
|
521
|
+
* @param content - model-authored content to deliver.
|
|
522
|
+
* @param options - caller cancellation before inbox acceptance.
|
|
552
523
|
* @returns the accepted message's inbox id.
|
|
553
|
-
* @throws when continuation services are unavailable,
|
|
554
|
-
*
|
|
524
|
+
* @throws when continuation services are unavailable, adjacency is rejected,
|
|
525
|
+
* or the message was not admitted.
|
|
555
526
|
*/
|
|
556
|
-
async
|
|
527
|
+
async sendMessage( sender: Agent, targetId: SessionId, content: ContentBlock[], options: SubagentSendMessageOptions, ): Promise<MessageId>
|
|
557
528
|
|
|
558
529
|
/**
|
|
559
530
|
* Interrupt one live continuable child's current turn under a human parent
|
|
@@ -572,29 +543,6 @@ async followup( parent: Agent, childId: SessionId, content: ContentBlock[], opti
|
|
|
572
543
|
*/
|
|
573
544
|
interrupt(targetSessionId: SessionId, authority: SubagentInterruptAuthority): void
|
|
574
545
|
|
|
575
|
-
/**
|
|
576
|
-
* Deliver selected content from one live continuable child to its durable
|
|
577
|
-
* direct parent. The child is the authority credential; callers cannot name a
|
|
578
|
-
* recipient. Reporting does not conclude the child's turn or Activation.
|
|
579
|
-
* @param child - exact live reporting child.
|
|
580
|
-
* @param content - selected model-facing content.
|
|
581
|
-
* @param options - parent scheduling and pre-acceptance cancellation.
|
|
582
|
-
* @returns the stable identity of the parent-accepted message.
|
|
583
|
-
* @throws when continuation services are unavailable, sender authorization
|
|
584
|
-
* fails, or the direct parent is not live.
|
|
585
|
-
*/
|
|
586
|
-
async reportFrom( child: Agent, content: ContentBlock[], options: SubagentReportOptions, ): Promise<MessageId>
|
|
587
|
-
|
|
588
|
-
/**
|
|
589
|
-
* Compose one deployment capability into every continuable child's
|
|
590
|
-
* unpublished creation context on fresh creation and cold resume. Grants wait
|
|
591
|
-
* for the next Activation; removing the contribution revokes every resident
|
|
592
|
-
* installation immediately.
|
|
593
|
-
* @param contribution - synchronous child-scope installer.
|
|
594
|
-
* @returns the exact Cordis effect disposer.
|
|
595
|
-
*/
|
|
596
|
-
registerContinuableSetup(contribution: ContinuableSetupContribution): () => void
|
|
597
|
-
|
|
598
546
|
/**
|
|
599
547
|
* Close continuable admission below exact live parent Agents, stop only their
|
|
600
548
|
* visible descendant Activations synchronously, then await admitted scoped
|
|
@@ -664,9 +612,9 @@ listDescendants(rootSessionId: SessionId, signal?: AbortSignal): Promise<Subagen
|
|
|
664
612
|
* @param parentSessionId - parent session whose direct children are listed.
|
|
665
613
|
* @param signal - carrier cancellation forwarded to Session queries.
|
|
666
614
|
* @returns the catalog view for that parent.
|
|
667
|
-
* @throws {
|
|
668
|
-
* `cancelled` for an aborted read, `subagent
|
|
669
|
-
* the deployment has no projection registry, otherwise `internal`.
|
|
615
|
+
* @throws {RemoteError} `gateway/bad-request` for an empty parent id,
|
|
616
|
+
* `gateway/cancelled` for an aborted read, `subagent/projections-unavailable` when
|
|
617
|
+
* the deployment has no projection registry, otherwise `gateway/internal`.
|
|
670
618
|
*/
|
|
671
619
|
@Remote('list') async remoteExportList(parentSessionId: SessionId, signal: AbortSignal): Promise<SubagentCatalog>
|
|
672
620
|
|
|
@@ -674,15 +622,18 @@ listDescendants(rootSessionId: SessionId, signal?: AbortSignal): Promise<Subagen
|
|
|
674
622
|
* Deliver one browser-authored message to a continuable child through the
|
|
675
623
|
* exact live direct parent, retaining the caller-minted request identity and
|
|
676
624
|
* validated browser zone on the accepted message. Success identifies the
|
|
677
|
-
* message the child's
|
|
678
|
-
*
|
|
679
|
-
*
|
|
625
|
+
* message the child's inbox accepted; later execution is independent of this
|
|
626
|
+
* call. Queue delivery targets a later turn; steer delivery targets the
|
|
627
|
+
* nearest step and retains the Agent loop's best-effort fallback semantics.
|
|
628
|
+
* Image parts are admitted and persisted through the attachment store
|
|
629
|
+
* before delivery, and the child's model must accept image input.
|
|
630
|
+
* @param request - durable address, delivery, minted identity, content, and optional browser zone.
|
|
680
631
|
* @param signal - carrier cancellation, owning the call until inbox acceptance.
|
|
681
632
|
* @returns the accepted message's inbox identity.
|
|
682
|
-
* @throws {
|
|
683
|
-
* `subagent-
|
|
684
|
-
* `subagent-
|
|
685
|
-
* `internal`.
|
|
633
|
+
* @throws {RemoteError} `gateway/bad-request`, `subagent/attachment-invalid`,
|
|
634
|
+
* `subagent/invalid-time-zone`, `subagent/parent-unavailable`,
|
|
635
|
+
* `subagent/not-resumable`, `subagent/unauthorized`,
|
|
636
|
+
* `subagent/delivery-unavailable`, `gateway/cancelled`, or `gateway/internal`.
|
|
686
637
|
*/
|
|
687
638
|
@Remote('prompt') async prompt(request: SubagentPromptRequest, signal: AbortSignal): Promise<SubagentPromptReceipt>
|
|
688
639
|
|
|
@@ -696,9 +647,9 @@ listDescendants(rootSessionId: SessionId, signal?: AbortSignal): Promise<Subagen
|
|
|
696
647
|
* @param parentSessionId - durable direct parent whose authority is claimed.
|
|
697
648
|
* @param mode - required continuable-address discriminator.
|
|
698
649
|
* @returns acknowledgement that the cancel signal was admitted, not that the target is quiescent.
|
|
699
|
-
* @throws {
|
|
700
|
-
* `subagent
|
|
701
|
-
* otherwise `internal`.
|
|
650
|
+
* @throws {RemoteError} `gateway/bad-request` for an empty id,
|
|
651
|
+
* `subagent/unauthorized` when the address does not own the live target,
|
|
652
|
+
* otherwise `gateway/internal`.
|
|
702
653
|
*/
|
|
703
654
|
@Remote('interruptByParent') interruptByParent( childSessionId: SessionId, parentSessionId: SessionId, mode: 'continuable', ): SubagentInterruptReceipt
|
|
704
655
|
|
|
@@ -730,6 +681,8 @@ list(): string[]
|
|
|
730
681
|
* fulfills; a rejection therefore has no run for the caller to dispose and
|
|
731
682
|
* emits no run lifecycle events. Post-publication turn and infrastructure
|
|
732
683
|
* failures settle through the returned run.
|
|
684
|
+
* A catalog append failure disposes the run and handles its result rejection;
|
|
685
|
+
* the caller receives the catalog error even if disposal also fails.
|
|
733
686
|
* @param name - the provider to use.
|
|
734
687
|
* @param request - child label, prompt, parent, signal, and optional capabilities.
|
|
735
688
|
* @returns the published holder-owned run.
|
|
@@ -109,14 +109,15 @@ interface SubprocessSpawnSpec {
|
|
|
109
109
|
stdio: SubprocessStdio
|
|
110
110
|
/**
|
|
111
111
|
* Positive finite grace period in milliseconds, no greater than
|
|
112
|
-
* `MAX_TIMER_DELAY_MS`,
|
|
113
|
-
* and for draining still-open collected pipes after the process exits
|
|
114
|
-
* inherited descriptor held by a
|
|
115
|
-
*
|
|
112
|
+
* `MAX_TIMER_DELAY_MS`, available to the provider's termination procedure
|
|
113
|
+
* and used for draining still-open collected pipes after the process exits
|
|
114
|
+
* (an inherited descriptor held by a survivor cannot hold the outcome open
|
|
115
|
+
* indefinitely). Providers document whether range termination is staged or
|
|
116
|
+
* immediate.
|
|
116
117
|
*/
|
|
117
118
|
graceMs: number
|
|
118
119
|
/**
|
|
119
|
-
* Abort signal — starts the terminate escalation on the
|
|
120
|
+
* Abort signal — starts the terminate escalation on the managed range when
|
|
120
121
|
* it fires. The caller owns deadlines and cause classification; this seam
|
|
121
122
|
* only reacts to the abort.
|
|
122
123
|
*/
|
|
@@ -132,23 +133,20 @@ interface SubprocessSpawnSpec {
|
|
|
132
133
|
}
|
|
133
134
|
```
|
|
134
135
|
|
|
135
|
-
##
|
|
136
|
+
## 句柄:流、读取器与 managed-range 终止
|
|
136
137
|
|
|
137
|
-
spawn
|
|
138
|
+
spawn 会同步返回活动句柄,目标与受管范围标识则保留在 provider 内部。收集模式的读取器接受全流字节偏移量且从不消费,因此独立读取器不会抢走彼此的增量;管道化的流归调用方所有。`terminate()` 启动 provider 记录的终止过程,`waitForExit()` 观察同一个 provider-managed range;分阶段 provider 可以使用 `graceMs`,立即终止的 provider 不会等待。消费方可以在这两项操作上构建自己的分级清理流程;ACP 后端先关闭 stdin 的 `disposeAcpChild` 是参考实现。
|
|
138
139
|
|
|
139
140
|
```ts type-equiv
|
|
140
141
|
/**
|
|
141
|
-
* A live
|
|
142
|
+
* A live subprocess and its provider-managed process range. Collected output
|
|
142
143
|
* remains readable after exit; piped streams belong to the caller.
|
|
143
144
|
*
|
|
144
|
-
* Termination
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
* the handle unnoticed.
|
|
145
|
+
* Termination and {@link SubprocessHandle.waitForExit} use the same managed
|
|
146
|
+
* range. Each provider documents the range it can observe and its signalling
|
|
147
|
+
* and observation limits.
|
|
148
148
|
*/
|
|
149
149
|
interface SubprocessHandle {
|
|
150
|
-
/** Process id (tree root); -1 when the spawn itself failed. */
|
|
151
|
-
readonly pid: number
|
|
152
150
|
/** The child's stdin, present iff spawned with `stdin: 'pipe'`. */
|
|
153
151
|
readonly stdin: Writable | undefined
|
|
154
152
|
/** The child's raw stdout, present iff spawned with `stdout: 'pipe'`. */
|
|
@@ -157,20 +155,20 @@ interface SubprocessHandle {
|
|
|
157
155
|
readonly stderr: Readable | undefined
|
|
158
156
|
/** Offset-based readers for collect-mode streams (also readable after exit). */
|
|
159
157
|
readonly collected: SubprocessCollectedOutputs
|
|
160
|
-
/** Resolves
|
|
158
|
+
/** Resolves with spawned-command exit facts; rejects for spawn or provider failures. */
|
|
161
159
|
readonly done: Promise<SubprocessOutcome>
|
|
162
160
|
/**
|
|
163
|
-
* Begin the
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
* and also triggered by the spec's abort signal.
|
|
161
|
+
* Begin the provider's documented termination procedure on the managed range
|
|
162
|
+
* — the seam's only termination verb. Idempotent, a no-op once that range is
|
|
163
|
+
* gone, and also triggered by the spec's abort signal.
|
|
167
164
|
*/
|
|
168
165
|
terminate(): void
|
|
169
166
|
/**
|
|
170
|
-
* Wait until the
|
|
171
|
-
*
|
|
167
|
+
* Wait until the same managed range is empty — not just until the spawned
|
|
168
|
+
* command reports its outcome, so surviving work remains observable.
|
|
172
169
|
* @param signal - optional bound for the wait.
|
|
173
|
-
* @returns `true` when the
|
|
170
|
+
* @returns `true` when the managed range is empty, `false` when the signal aborted first.
|
|
171
|
+
* @throws when the selected provider can no longer observe its managed range.
|
|
174
172
|
*/
|
|
175
173
|
waitForExit(signal?: AbortSignal): Promise<boolean>
|
|
176
174
|
}
|
|
@@ -249,7 +247,7 @@ interface SubprocessOutcome {
|
|
|
249
247
|
|
|
250
248
|
## 服务行为
|
|
251
249
|
|
|
252
|
-
抽象的 [`SubprocessRuntime`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/subprocess/subprocess/src/index.ts) Service Definition 规定执行世界坐标、可执行文件查找、普通 `spawn` 与 `spawnTerminal`。[`LocalSubprocessRuntime`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/subprocess/subprocess-local/src/index.ts)
|
|
250
|
+
抽象的 [`SubprocessRuntime`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/subprocess/subprocess/src/index.ts) Service Definition 规定执行世界坐标、可执行文件查找、普通 `spawn` 与 `spawnTerminal`。[`LocalSubprocessRuntime`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/subprocess/subprocess-local/src/index.ts) 以平台选择的 managed range、按处置方式接线、凭据清除、`node-pty`、平台进程检查,以及先终止再等待退出的资源释放提供这些能力。Service Definition 约定见 [`dsh-subprocess`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/subprocess/subprocess/README.zh.md),本地机制见 [`dsh-subprocess-local`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/subprocess/subprocess-local/README.zh.md)。
|
|
253
251
|
|
|
254
252
|
<!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
|
|
255
253
|
|
|
@@ -285,9 +283,9 @@ Abstract subprocess service. Subclass, implement spawn, and load the subclass as
|
|
|
285
283
|
Implementations must honor these semantics:
|
|
286
284
|
|
|
287
285
|
- Executable paths belong to one execution world shared with the mounted filesystem provider.
|
|
288
|
-
- spawn returns
|
|
286
|
+
- spawn returns a live handle synchronously. Target identity remains provider-private; `done` resolves with the spawned command's exit facts and may reject for spawn or provider failures.
|
|
289
287
|
- Collect-mode readers are offset-based and non-consuming, so independent readers never consume one another's output; lossy reads report truncation and the spill file holding the complete stream when one exists. Piped streams are handed to the caller raw and never buffered here.
|
|
290
|
-
- SubprocessHandle.terminate (and the spec's abort signal)
|
|
288
|
+
- SubprocessHandle.terminate (and the spec's abort signal) starts the provider's documented procedure against its managed range. SubprocessHandle.waitForExit observes that same range so a consumer-owned teardown ladder can hold each tier on real quiescence; each provider documents its signalling and observability limits.
|
|
291
289
|
- Disposal of the service terminates all still-running managed processes and awaits their exit.
|
|
292
290
|
- spawnTerminal owns terminal allocation, text transport, foreground groups, signalling, and whole-session quiescence behind one awaited termination method; readiness and persistent-shell policy stay in the PTY consumer. Its output stream ends after queued terminal output when the top-level process exits.
|
|
293
291
|
|
|
@@ -310,13 +308,14 @@ abstract resolveExecutable( command: string, env?: Readonly<Record<string, strin
|
|
|
310
308
|
* applies no defaults.
|
|
311
309
|
* @param spec - argv, directory, stdio dispositions, grace, cancellation, and environment.
|
|
312
310
|
* @returns the live process handle (streams/readers, signalling, outcome promise).
|
|
311
|
+
* @throws synchronously when pre-aborted or when argv, cwd, environment, or grace is invalid before handle creation.
|
|
313
312
|
*/
|
|
314
313
|
abstract spawn(spec: SubprocessSpawnSpec): SubprocessHandle
|
|
315
314
|
|
|
316
315
|
/**
|
|
317
316
|
* Allocate a real terminal and start one owned process session. This is the
|
|
318
317
|
* only non-pipe process primitive: implementations own terminal byte I/O,
|
|
319
|
-
* foreground groups, signals, and
|
|
318
|
+
* foreground groups, signals, and whole-session quiescence.
|
|
320
319
|
* @param spec - fully specified argv, cwd, environment, dimensions, grace, and allocation cancellation.
|
|
321
320
|
* @returns the live terminal handle after allocation succeeds.
|
|
322
321
|
*/
|
|
@@ -42,7 +42,9 @@ interface ToolProviderResult {
|
|
|
42
42
|
|
|
43
43
|
## 提示词段落
|
|
44
44
|
|
|
45
|
-
`
|
|
45
|
+
导出的 `PERSONA_PREFIX_SECTION`(`deployment:persona-prefix`)与 `PERSONA_SUFFIX_SECTION`(`deployment:persona-suffix`)为全局配置和带作用域贡献所共享的段落命名。它们对应的 `PromptSectionOrderName` 项为 `DEPLOYMENT_PERSONA_PREFIX` 与 `DEPLOYMENT_PERSONA_SUFFIX`;[包 README](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/system-prompt/README.zh.md#configure-the-prompt)规定其位置与模板配置。
|
|
46
|
+
|
|
47
|
+
`PromptSection` 是一份只读的同进程注册约定。其文本可以是静态的,也可以从当前组装上下文动态解析。各段先按 order 升序排列,再按名称的代码单元顺序排列;仓库贡献方通过 `getSectionOrder()` 解析服务持有的具名分配。Runtime-context 贡献方通过 `getContextOrder()` 解析独立分配。协作式组装完成后,一个有效的 `complete` 段会成为唯一的提示词段落。agent loop(智能体循环)用 `renderPrompt` 渲染组装后的各段,并把文本作为 `system/message` surface 节点提交——首个步骤作为 surface 第 0 号节点追加,之后在渲染文本变化时原地替换,或者当已准备调用声明 `systemPromptUpdate: 'in-history'` 时,在序列延续期间把非空更新追加到已缓存历史之后——因此提示词作为派生历史中的消息而不是请求字段到达模型([决策](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/architecture/2026-09-02-system-prompt-as-surface-node.zh.md);[决策规则](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/agent-loop/README.zh.md#understand-the-implementation))。
|
|
46
48
|
|
|
47
49
|
```ts type-equiv
|
|
48
50
|
/** One contributed section of the system prompt (registry input). */
|
|
@@ -51,8 +53,7 @@ interface PromptSection {
|
|
|
51
53
|
readonly name: string
|
|
52
54
|
/**
|
|
53
55
|
* Sections are concatenated in ascending order. Equal orders use code-unit
|
|
54
|
-
* name order.
|
|
55
|
-
* {@link FIRST_PARTY_SECTION_ORDER}.
|
|
56
|
+
* name order.
|
|
56
57
|
*/
|
|
57
58
|
readonly order: number
|
|
58
59
|
/**
|
|
@@ -112,6 +113,20 @@ Registry service for the prompt inputs assembled before each model step.
|
|
|
112
113
|
*/
|
|
113
114
|
section(section: PromptSection): () => void
|
|
114
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Resolve the centrally owned placement of a repository prompt section.
|
|
118
|
+
* @param name - stable section placement name.
|
|
119
|
+
* @returns the section's numeric sort order.
|
|
120
|
+
*/
|
|
121
|
+
getSectionOrder(name: PromptSectionOrderName): number
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Resolve the centrally owned placement of a repository runtime context.
|
|
125
|
+
* @param name - stable context placement name.
|
|
126
|
+
* @returns the context's numeric sort order.
|
|
127
|
+
*/
|
|
128
|
+
getContextOrder(name: PromptContextOrderName): number
|
|
129
|
+
|
|
115
130
|
/**
|
|
116
131
|
* Register ordered dynamic context in the calling context's scope. Scoped
|
|
117
132
|
* entries shadow global entries with the same name.
|
|
@@ -15,7 +15,7 @@ outline: [2,3]
|
|
|
15
15
|
/** Detached immutable request-pressure and surface snapshot at one consumed log revision. */
|
|
16
16
|
interface TokenMeasurement {
|
|
17
17
|
/** Number of durable events consumed; equal to the next unread event seq. */
|
|
18
|
-
readonly logRevision:
|
|
18
|
+
readonly logRevision: SessionLogOffset
|
|
19
19
|
/** Provider or heuristic anchor used for this measurement. */
|
|
20
20
|
readonly baseline: TokenMeasurementBaseline
|
|
21
21
|
/** Signed repricing of current surface content relative to the baseline anchor. */
|
|
@@ -37,7 +37,7 @@ interface TokenMeasurement {
|
|
|
37
37
|
/** One token-priced node in the current ordered session surface. */
|
|
38
38
|
interface TokenSurfaceNode {
|
|
39
39
|
/** Durable sequence number of the surface event. */
|
|
40
|
-
readonly seq:
|
|
40
|
+
readonly seq: SessionSeq
|
|
41
41
|
/**
|
|
42
42
|
* Request-pressure tokens for the exact message projected by this node under
|
|
43
43
|
* the measured route: image occurrences carry the route's declared visual
|
|
@@ -81,7 +81,8 @@ Replay owner for one service-wide estimator and isolated per-session folds.
|
|
|
81
81
|
* usage is reused only when the latest successful call's canonical request
|
|
82
82
|
* envelope matches `requestHeader` and its total is no lower than that
|
|
83
83
|
* call's full route-priced anchor; otherwise the complete envelope and
|
|
84
|
-
* surface are repriced.
|
|
84
|
+
* surface are repriced. The anchor includes all surface nodes immediately
|
|
85
|
+
* before the assistant message, including inputs admitted after step/start.
|
|
85
86
|
*
|
|
86
87
|
* `requestHeader` replaces the latest logged envelope for pressure and node
|
|
87
88
|
* pricing; the node set always describes the current session surface. Every
|
|
@@ -265,14 +265,14 @@ PTC mode 的桥接层还会把每个已结算的子分派暴露给 `tools/ptc-di
|
|
|
265
265
|
* copy a listener may reshape. `content` is the RENDERED result projection
|
|
266
266
|
* (what a native `tool/result` would carry) — the program itself received
|
|
267
267
|
* the structured `value` (or just the error message on failure); only the
|
|
268
|
-
* `tool/
|
|
268
|
+
* `tool/ptc-dispatch` event's copy changes.
|
|
269
269
|
*/
|
|
270
270
|
interface PtcDispatchLog {
|
|
271
271
|
/** The outer `run_code` execution. */
|
|
272
272
|
readonly exec: ToolExecution
|
|
273
273
|
/** The calling agent (the scope routing key and the spill owner), when the outer call has one. */
|
|
274
274
|
readonly agent?: Agent
|
|
275
|
-
/**
|
|
275
|
+
/** Opaque sub-call id; new calls use `<parent>:ptc:<n>`. */
|
|
276
276
|
readonly subCallId: ToolCallId
|
|
277
277
|
/** The dispatched sub-tool name. */
|
|
278
278
|
readonly name: string
|
|
@@ -370,7 +370,7 @@ interface ToolExecutionFailure {
|
|
|
370
370
|
type ToolExecutionResult = ToolExecutionSuccess | ToolExecutionFailure
|
|
371
371
|
```
|
|
372
372
|
|
|
373
|
-
结果仅承载产出。调用身份保留在不可变的 `ToolExecution` 上,后者伴随结果经过每个钩子,并出现在持久化的 `tool/call` / `tool/result` 会话事件上,因此包装层无法创建第二个相互矛盾的身份。规范的 `value` 仅存在于执行期间:循环只持久化 `content`、`error` 和 `meta`,`tool/
|
|
373
|
+
结果仅承载产出。调用身份保留在不可变的 `ToolExecution` 上,后者伴随结果经过每个钩子,并出现在持久化的 `tool/call` / `tool/result` 会话事件上,因此包装层无法创建第二个相互矛盾的身份。规范的 `value` 仅存在于执行期间:循环只持久化 `content`、`error` 和 `meta`,`tool/ptc-dispatch` 则原样存储子调用渲染后的 `content` 与 `isError`。回放可以重现展示,却无法重建规范的中间值。
|
|
374
374
|
|
|
375
375
|
成功时,注册表会快照并校验函数体返回值,将其冻结,然后调用纯渲染器;对于直接的外层调用,还会调用可选的元数据投影器。注册表会在 `tools/result` 之前另行物化持久展示字段;无效值、渲染器/投影器失败或非 JSON 展示都会转为 JSON 安全的 `isError`。因此,最终实时观察者能看到精确的执行期值,以及可安全用于后续持久追加的字段。
|
|
376
376
|
|
|
@@ -677,13 +677,13 @@ Source: [`packages/core/tools/src/index.ts`](https://github.com/deepseek-ai/deep
|
|
|
677
677
|
|
|
678
678
|
#### `tools/ptc-dispatch-log` — waterfall
|
|
679
679
|
|
|
680
|
-
Allow a listener to replace content in the DURABLE LOG COPY of one `run_code` sub-dispatch outcome before the bridge appends its `tool/
|
|
680
|
+
Allow a listener to replace content in the DURABLE LOG COPY of one `run_code` sub-dispatch outcome before the bridge appends its `tool/ptc-dispatch` event. `next()` keeps the content unchanged; a listener may return replacement blocks (e.g. the spill policy's preview + locator for an oversized text result). Only the logged copy is affected — the program already received the complete value, and the model sees neither. A throwing listener is contained: the bridge falls back to logging the original settled content. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent's dispatches.
|
|
681
681
|
|
|
682
682
|
```ts cordis-catalog
|
|
683
683
|
/**
|
|
684
684
|
* Allow a listener to replace content in the DURABLE LOG COPY of one
|
|
685
685
|
* `run_code` sub-dispatch outcome before the bridge appends its
|
|
686
|
-
* `tool/
|
|
686
|
+
* `tool/ptc-dispatch` event. `next()` keeps the
|
|
687
687
|
* content unchanged; a listener may return replacement blocks (e.g. the
|
|
688
688
|
* spill policy's preview + locator for an oversized text result). Only the
|
|
689
689
|
* logged copy is affected — the program already received the complete
|