dsh-plugin-dev-kb 1.0.8 → 1.1.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.
Files changed (188) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.en.md +6 -6
  3. package/README.md +6 -6
  4. package/kb/INDEX.md +21 -5
  5. package/kb/README.md +11 -10
  6. package/kb/extra/AGENTS.md +4 -4
  7. package/kb/extra/cookbook/adding-a-remote-api.md +197 -0
  8. package/kb/extra/cookbook/adding-a-remote-api.zh.md +197 -0
  9. package/kb/extra/cookbook/adding-a-vendored-package.md +2 -2
  10. package/kb/extra/cookbook/adding-a-vendored-package.zh.md +2 -2
  11. package/kb/extra/deepseek-llm-api-wire-extensions.md +163 -0
  12. package/kb/extra/deepseek-llm-api-wire-extensions.zh.md +163 -0
  13. package/kb/extra/development.md +8 -14
  14. package/kb/extra/development.zh.md +8 -14
  15. package/kb/extra/event-producer-consumer.md +55 -48
  16. package/kb/extra/event-producer-consumer.zh.md +58 -51
  17. package/kb/extra/glossary.md +1 -1
  18. package/kb/extra/glossary.zh.md +1 -1
  19. package/kb/extra/graph-atlas.md +0 -2
  20. package/kb/extra/graph-atlas.zh.md +0 -2
  21. package/kb/extra/i18n/README.md +4 -4
  22. package/kb/extra/i18n/README.zh.md +4 -4
  23. package/kb/extra/i18n/style-samples.md +2 -2
  24. package/kb/extra/module-graph.md +646 -926
  25. package/kb/extra/module-graph.zh.md +648 -928
  26. package/kb/extra/postmortem/0001-acp-default-export-drops-inject.md +2 -2
  27. package/kb/extra/postmortem/0001-acp-default-export-drops-inject.zh.md +2 -2
  28. package/kb/extra/postmortem/0002-js-expression-disabled-filesystem-tools.md +2 -2
  29. package/kb/extra/postmortem/0002-js-expression-disabled-filesystem-tools.zh.md +2 -2
  30. package/kb/extra/postmortem/0003-web-agent-gui-feedback-loop.md +2 -2
  31. package/kb/extra/postmortem/0003-web-agent-gui-feedback-loop.zh.md +2 -2
  32. package/kb/extra/postmortem/0004-landlock-partial-notice-misclassified-child-failures.md +1 -1
  33. package/kb/extra/postmortem/0004-landlock-partial-notice-misclassified-child-failures.zh.md +1 -1
  34. package/kb/extra/rescope.md +2 -2
  35. package/kb/extra/rescope.zh.md +2 -2
  36. package/kb/extra/subsystems/agent-team.md +28 -4
  37. package/kb/extra/subsystems/agent-team.zh.md +28 -4
  38. package/kb/extra/subsystems/attachment.md +168 -7
  39. package/kb/extra/subsystems/attachment.zh.md +168 -7
  40. package/kb/extra/subsystems/extensions.md +18 -0
  41. package/kb/extra/subsystems/extensions.zh.md +18 -0
  42. package/kb/extra/subsystems/feedback.md +4 -4
  43. package/kb/extra/subsystems/feedback.zh.md +4 -4
  44. package/kb/extra/subsystems/todo.md +32 -0
  45. package/kb/extra/subsystems/todo.zh.md +32 -0
  46. package/kb/extra/subsystems/webhook.md +70 -0
  47. package/kb/extra/subsystems/webhook.zh.md +70 -0
  48. package/kb/extra/testing.md +15 -10
  49. package/kb/extra/testing.zh.md +13 -8
  50. package/kb/extra/web-styling.md +4 -0
  51. package/kb/extra/web-styling.zh.md +4 -0
  52. package/kb/meta/search-index.json +309 -177
  53. package/kb/meta/site-pages.txt +183 -167
  54. package/kb/meta/source.json +5 -5
  55. package/kb/meta/topics.md +14 -6
  56. package/kb/site/develop/basic/publish.md +2 -2
  57. package/kb/site/develop/basic/tool.md +1 -1
  58. package/kb/site/develop/cordis-tutorial/07-into-the-harness.md +5 -4
  59. package/kb/site/develop/framework/events.md +1 -1
  60. package/kb/site/develop/practice/dynamic-cordis.md +17 -0
  61. package/kb/site/develop/practice/llm-adapter.md +4 -3
  62. package/kb/site/en/develop/basic/publish.md +2 -2
  63. package/kb/site/en/develop/basic/tool.md +1 -1
  64. package/kb/site/en/develop/cordis-tutorial/07-into-the-harness.md +5 -4
  65. package/kb/site/en/develop/framework/events.md +1 -1
  66. package/kb/site/en/develop/practice/dynamic-cordis.md +17 -0
  67. package/kb/site/en/develop/practice/llm-adapter.md +4 -3
  68. package/kb/site/en/guide/github-review.md +104 -0
  69. package/kb/site/en/guide/mcp-memory.md +103 -0
  70. package/kb/site/en/guide/network-proxy.md +87 -0
  71. package/kb/site/en/guide/providers.md +70 -17
  72. package/kb/site/en/guide/python-sdk.md +80 -34
  73. package/kb/site/en/guide/schedule.md +23 -0
  74. package/kb/site/en/reference/agent-lifecycle.md +6 -4
  75. package/kb/{extra → site/en/reference}/api-gateway.md +12 -10
  76. package/kb/site/en/reference/capability-seams.md +128 -73
  77. package/kb/site/en/reference/config-catalog.md +481 -360
  78. package/kb/site/en/reference/cookbook/adding-a-package.md +3 -4
  79. package/kb/site/en/reference/cookbook/adding-a-settings-card.md +12 -10
  80. package/kb/site/en/reference/cookbook/adding-a-tool.md +11 -4
  81. package/kb/site/en/reference/cookbook/adding-an-llm-adapter.md +1 -1
  82. package/kb/site/en/reference/cookbook/extension-cookbook.md +20 -17
  83. package/kb/site/en/reference/cordis-api/inherited.md +1 -1
  84. package/kb/site/en/reference/cordis-primer.md +2 -1
  85. package/kb/site/en/reference/index.md +30 -11
  86. package/kb/site/en/reference/persistence-catalog.md +148 -80
  87. package/kb/site/en/reference/subsystems/approval.md +10 -10
  88. package/kb/site/en/reference/subsystems/client-modules.md +58 -16
  89. package/kb/site/en/reference/subsystems/code-runtime.md +10 -6
  90. package/kb/site/en/reference/subsystems/commands.md +25 -16
  91. package/kb/site/en/reference/subsystems/compaction.md +11 -11
  92. package/kb/site/en/reference/{cookbook/adding-a-conversation-node.md → subsystems/conversation.md} +50 -24
  93. package/kb/site/en/reference/subsystems/core.md +156 -17
  94. package/kb/site/en/reference/subsystems/credentials.md +44 -3
  95. package/kb/site/en/reference/subsystems/filesystem.md +12 -2
  96. package/kb/site/en/reference/subsystems/goal.md +1 -1
  97. package/kb/site/en/reference/subsystems/index.md +7 -2
  98. package/kb/site/en/reference/subsystems/jobs.md +1 -1
  99. package/kb/site/en/reference/subsystems/llm-streaming.md +154 -12
  100. package/kb/site/en/reference/subsystems/permission-presets.md +6 -6
  101. package/kb/site/en/reference/subsystems/persistence.md +185 -175
  102. package/kb/site/en/reference/subsystems/plan.md +2 -2
  103. package/kb/site/en/reference/subsystems/sandbox.md +2 -0
  104. package/kb/site/en/reference/subsystems/schedule.md +9 -3
  105. package/kb/site/en/reference/subsystems/session-projection.md +115 -48
  106. package/kb/site/en/reference/subsystems/session-query.md +28 -14
  107. package/kb/site/en/reference/subsystems/session-reference.md +53 -8
  108. package/kb/site/en/reference/subsystems/session-telemetry.md +8 -8
  109. package/kb/site/en/reference/subsystems/session-title.md +6 -6
  110. package/kb/site/en/reference/subsystems/session.md +401 -99
  111. package/kb/site/en/reference/subsystems/settings.md +101 -6
  112. package/kb/site/en/reference/subsystems/skills.md +23 -0
  113. package/kb/site/en/reference/subsystems/slots.md +178 -0
  114. package/kb/site/en/reference/subsystems/spill.md +2 -2
  115. package/kb/site/en/reference/subsystems/storage.md +34 -3
  116. package/kb/site/en/reference/subsystems/subagent.md +122 -109
  117. package/kb/site/en/reference/subsystems/system-prompt.md +17 -4
  118. package/kb/site/en/reference/subsystems/token-meter.md +27 -12
  119. package/kb/site/en/reference/subsystems/tools.md +39 -39
  120. package/kb/site/en/reference/subsystems/typert.md +62 -55
  121. package/kb/site/en/reference/subsystems/user-questions.md +33 -33
  122. package/kb/site/en/reference/subsystems/web-client.md +98 -0
  123. package/kb/site/en/reference/subsystems/web-server.md +11 -5
  124. package/kb/site/en/reference/subsystems/web.md +7 -1
  125. package/kb/site/en/reference/subsystems/workspace.md +102 -9
  126. package/kb/site/en/reference/tool-catalog.md +86 -82
  127. package/kb/site/en/reference/tool-execution-pipeline.md +1 -1
  128. package/kb/site/guide/github-review.md +104 -0
  129. package/kb/site/guide/mcp-memory.md +103 -0
  130. package/kb/site/guide/network-proxy.md +87 -0
  131. package/kb/site/guide/providers.md +70 -17
  132. package/kb/site/guide/python-sdk.md +87 -41
  133. package/kb/site/guide/schedule.md +23 -0
  134. package/kb/site/reference/agent-lifecycle.md +6 -4
  135. package/kb/{extra/api-gateway.zh.md → site/reference/api-gateway.md} +12 -10
  136. package/kb/site/reference/capability-seams.md +128 -73
  137. package/kb/site/reference/config-catalog.md +481 -360
  138. package/kb/site/reference/cookbook/adding-a-package.md +3 -4
  139. package/kb/site/reference/cookbook/adding-a-settings-card.md +12 -10
  140. package/kb/site/reference/cookbook/adding-a-tool.md +11 -4
  141. package/kb/site/reference/cookbook/adding-an-llm-adapter.md +1 -1
  142. package/kb/site/reference/cookbook/extension-cookbook.md +20 -17
  143. package/kb/site/reference/cordis-api/inherited.md +1 -1
  144. package/kb/site/reference/cordis-primer.md +2 -1
  145. package/kb/site/reference/index.md +30 -11
  146. package/kb/site/reference/persistence-catalog.md +148 -80
  147. package/kb/site/reference/subsystems/approval.md +10 -10
  148. package/kb/site/reference/subsystems/client-modules.md +58 -16
  149. package/kb/site/reference/subsystems/code-runtime.md +10 -6
  150. package/kb/site/reference/subsystems/commands.md +25 -16
  151. package/kb/site/reference/subsystems/compaction.md +11 -11
  152. package/kb/site/reference/{cookbook/adding-a-conversation-node.md → subsystems/conversation.md} +50 -24
  153. package/kb/site/reference/subsystems/core.md +156 -17
  154. package/kb/site/reference/subsystems/credentials.md +44 -3
  155. package/kb/site/reference/subsystems/filesystem.md +12 -2
  156. package/kb/site/reference/subsystems/goal.md +1 -1
  157. package/kb/site/reference/subsystems/index.md +7 -2
  158. package/kb/site/reference/subsystems/jobs.md +1 -1
  159. package/kb/site/reference/subsystems/llm-streaming.md +154 -12
  160. package/kb/site/reference/subsystems/permission-presets.md +5 -5
  161. package/kb/site/reference/subsystems/persistence.md +184 -174
  162. package/kb/site/reference/subsystems/plan.md +2 -2
  163. package/kb/site/reference/subsystems/schedule.md +9 -3
  164. package/kb/site/reference/subsystems/session-projection.md +115 -48
  165. package/kb/site/reference/subsystems/session-query.md +28 -14
  166. package/kb/site/reference/subsystems/session-reference.md +53 -8
  167. package/kb/site/reference/subsystems/session-telemetry.md +8 -8
  168. package/kb/site/reference/subsystems/session-title.md +6 -6
  169. package/kb/site/reference/subsystems/session.md +401 -99
  170. package/kb/site/reference/subsystems/settings.md +101 -6
  171. package/kb/site/reference/subsystems/skills.md +23 -0
  172. package/kb/site/reference/subsystems/slots.md +178 -0
  173. package/kb/site/reference/subsystems/spill.md +2 -2
  174. package/kb/site/reference/subsystems/storage.md +34 -3
  175. package/kb/site/reference/subsystems/subagent.md +122 -109
  176. package/kb/site/reference/subsystems/system-prompt.md +17 -4
  177. package/kb/site/reference/subsystems/token-meter.md +27 -12
  178. package/kb/site/reference/subsystems/tools.md +39 -39
  179. package/kb/site/reference/subsystems/typert.md +62 -55
  180. package/kb/site/reference/subsystems/user-questions.md +33 -33
  181. package/kb/site/reference/subsystems/web-client.md +98 -0
  182. package/kb/site/reference/subsystems/web-server.md +11 -5
  183. package/kb/site/reference/subsystems/web.md +7 -1
  184. package/kb/site/reference/subsystems/workspace.md +102 -9
  185. package/kb/site/reference/tool-catalog.md +85 -81
  186. package/kb/site/reference/tool-execution-pipeline.md +1 -1
  187. package/package.json +2 -2
  188. package/skills/dsh-plugin-dev-kb.md +8 -6
@@ -20,7 +20,7 @@ outline: [2,3]
20
20
  | `agent-loop/` | 实现公开 `Agent` 约定的具体 driver(`ctx.agentLoop`) | 本页 |
21
21
  | `scope/` | 注册表与循环用于构建按 agent 作用域的注册原语 | [scope.md](./scope.md) |
22
22
 
23
- `scope/` 是这里唯一的非服务包:一个零依赖库(`createScope`/`scopeOf`/`scopeTarget`),在模块图中位于 `session/` 与 `system-prompt/` 之下,正是为了让它们消费它而不形成环。`agent-loop` 是公开 `Agent` 约定的唯一具体实现,放在这里因为它是 harness 的默认产品循环;它在 `ctx.agents.withInitiator()` 内运行每个 driver。扩展插件依赖 `agent`——包括需要发起 Agent 时——而绝不直接依赖 `agent-loop`,因此循环保持可替换。把这条主干接成可运行 agent 的默认组合是 [`examples/agent-spine-demo`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/examples/agent-spine-demo/README.zh.md)
23
+ `scope/` 是这里唯一的非服务包:一个零依赖库(`createScope`/`scopeOf`/`scopeTarget`),在模块图中位于 `session/` 与 `system-prompt/` 之下,正是为了让它们消费它而不形成环。`agent-loop` 是公开 `Agent` 约定的唯一具体实现,放在这里因为它是 harness 的默认产品循环;它在 `ctx.agents.withInitiator()` 内运行每个 driver。扩展插件依赖 `agent`——包括需要发起 Agent 时——而绝不直接依赖 `agent-loop`,因此循环保持可替换。[`dsh-base`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/bundle/base/README.zh.md) 是默认产品组合,[`dsh-sdk-minimal`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/bundle/sdk-minimal/README.zh.md) 则声明一棵更小的独立配置树。
24
24
 
25
25
  <a id="creation-and-ownership"></a>
26
26
 
@@ -51,7 +51,7 @@ interface AgentHandle {
51
51
  }
52
52
  ```
53
53
 
54
- `CreateAgentOptions` 携带共享标识以及新 agent 发布前所需的一切:会话元数据(`meta`——已校验的 `cwd`、fork 谱系、seed 边界、来源分类、委派深度)、fork 用的可选 `seed` 回放前缀、按 agent 的 `AgentOptions`、仅创建期有效的取消 `signal`,以及 `setup`。`ResumeAgentOptions` 是持久标识的对应项:`resumeSessionId`、`agentOptions`、`signal` 与 `setup`。`setup` 回调(`AgentSetup`)在两个 id 都尚未发布时组装 agent 的作用域世界——凡经 `agentCtx` 注册的内容都先于 `agent/created` 与第一次提示词组装存在——并可返回一个在发布前一刻调用的同步 commit;setup 拒绝、commit 抛出或所有者 dispose(资源释放)都会回滚事务,两个 id 均不发布。
54
+ `CreateAgentOptions` 携带共享标识以及新 agent 发布前所需的一切:会话元数据(`meta`——已校验的 `cwd`、fork 谱系、`isSeeded` 标记、来源分类、委派深度与 `agentPreset`)、同级字段 `inheritedEventCount` 所表示的精确 fork cut、可选的 `seed` 回放前缀、按 agent 的 `AgentOptions`、仅创建期有效的取消 `signal`,以及 `setup`。`ResumeAgentOptions` 是持久标识的对应项:`resumeSessionId`、`agentOptions`、`signal` 与 `setup`。`setup` 回调(`AgentSetup`)在两个 id 都尚未发布时组装 agent 的作用域世界——凡经 `agentCtx` 注册的内容都先于 `agent/created` 与第一次提示词组装存在——并可返回一个在发布前一刻调用的同步 commit;setup 拒绝、commit 抛出或所有者 dispose(资源释放)都会回滚事务,两个 id 均不发布。
55
55
 
56
56
  `AgentFactory` 是注册表背后的创建接口:循环经 `ctx.agents.setFactory()` 注册其工厂,因此消费方使用 `ctx.agents` 时无需依赖具体循环包。确切的 `create`/`resume` 签名及回滚约定见下方[生成区块](#ctxagents--agentregistry)。
57
57
 
@@ -64,9 +64,9 @@ interface AgentHandle {
64
64
  源码:[`packages/core/agent/src/types.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/agent/src/types.ts)
65
65
 
66
66
  ```ts type-equiv
67
- /** Public live-agent handle. */
67
+ /** Public live-agent handle; the runtime face augments its live capabilities. */
68
68
  interface Agent {
69
- /** The single identity shared with {@link session}. */
69
+ /** Session-backed Agent identity. */
70
70
  readonly id: SessionId
71
71
  /** The provider route and model this agent's requests use. */
72
72
  readonly options: AgentOptions
@@ -159,6 +159,44 @@ interface Agent {
159
159
  type AgentStatus = 'idle' | 'running'
160
160
  ```
161
161
 
162
+ ```ts type-equiv
163
+ /** One process-local live assistant streaming publication. */
164
+ type AssistantStreamFrame =
165
+ | {
166
+ readonly type: 'start'
167
+ readonly attemptId: LlmAttemptId
168
+ /** Monotone within one attached Agent lifecycle; replacement restarts at 1. */
169
+ readonly revision: number
170
+ readonly turn: number
171
+ readonly step: number
172
+ }
173
+ | {
174
+ readonly type: 'chunk'
175
+ readonly attemptId: LlmAttemptId
176
+ readonly revision: number
177
+ /** Dense zero-based position within the attempt. */
178
+ readonly index: number
179
+ /** Safe-integer timestamp reused by the durable embedded stream. */
180
+ readonly time: number
181
+ readonly chunk: StreamChunk
182
+ }
183
+ | {
184
+ readonly type: 'end'
185
+ readonly attemptId: LlmAttemptId
186
+ readonly revision: number
187
+ /** Number of chunk frames emitted by this attempt. */
188
+ readonly index: number
189
+ /** Durable settlement committed before this notification, or live abandonment without one. */
190
+ readonly outcome:
191
+ | {
192
+ readonly kind: 'committed'
193
+ readonly eventType: 'assistant/message' | 'assistant/attempt'
194
+ readonly seq: SessionSeq
195
+ }
196
+ | { readonly kind: 'abandoned' }
197
+ }
198
+ ```
199
+
162
200
  `running` 描述整个驱动器的排空区间,可能跨越连续的排队轮次;它不能证明某个轮次仍然打开。dispose 会把 agent 从注册表移除并发出 `agent/disposed`;它不是一个终态 status 值。`followup()` 不返回句柄:其 `MessageId` 标识的是持久的 inbox 插入、认领与丢弃事实,而非之后的助手输出或轮次结束。`whenIdle()` 观察的是整个 agent,因此只有当调用方明确拥有从回执到空闲的这段区间时,才能把它称为一次 run([决策](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/architecture/2026-07-30-followup-enqueue-and-owned-runs.zh.md))。
163
201
 
164
202
  ```ts type-equiv
@@ -168,12 +206,14 @@ interface AgentOptions {
168
206
  provider?: string
169
207
  /** Model id interpreted by the selected provider adapter. */
170
208
  model?: string
209
+ /** Adapter-owned reasoning effort for the selected provider/model route. */
210
+ reasoningEffort?: ReasoningEffortId
171
211
  /** Maximum output tokens for each conversation-model request. */
172
212
  maxTokens?: number
173
213
  }
174
214
  ```
175
215
 
176
- 在 `agent/request` 之后,分发要求 `provider` 与 `model` 都存在。提供 `maxTokens` 时,它必须是正安全整数,并限制每次对话模型请求的输出;省略时,系统会在写入请求 header 前填入确切模型的适配器默认值,否则提供方行为保持不变。agent 作用域的 `deployment:persona` 提示词段落可以遮蔽全局默认 persona。
216
+ 在 `agent/request` 之后,分发要求 `provider` 与 `model` 都存在。显式 `reasoningEffort` 会为该路由的首次请求提供初始值;确切模型解析会校验该值,省略时则允许填入适配器默认值。提供 `maxTokens` 时,它必须是正安全整数,并限制每次对话模型请求的输出;省略时,系统会在写入请求 header 前填入确切模型的适配器默认值,否则提供方行为保持不变。agent 作用域的 `deployment:persona` 提示词段落可以遮蔽全局默认 persona。
177
217
 
178
218
  inbox 即投递词汇——agent 以持久投影形式拥有的两条有序待处理消息列表:
179
219
 
@@ -207,7 +247,7 @@ type AgentCancelCause =
207
247
  | { readonly kind: 'disposed' }
208
248
  ```
209
249
 
210
- cause 是由 TypeScript 强制约束的同进程输入。活跃的取消持有者会将它复制到仅运行时的 `AbortSignal.reason`;signal 不授予协作监听器任何分类权限。持久 `turn/end` 保留粗粒度 `{ kind: 'aborted' }` 结果;若需记录谁请求了取消,应使用单独的持久事件,而不是让终态结果承担额外含义。
250
+ cause 是由 TypeScript 强制约束的同进程输入。活跃的取消持有者会将它复制到仅运行时的 `AbortSignal.reason`;signal 不授予协作监听器任何分类权限。持久 `turn/end` `{ kind: 'aborted', reason: TurnEndCancelCause }` 记录结果,取消原因随终态结果一起持久化。
211
251
 
212
252
  [事件分类](../index.md#events)负责 `agent/*` 生命周期、检查点与 waterfall(瀑布式事件)约定。轮次和步骤边界是持久会话事件,而不是 agent emit。
213
253
 
@@ -233,7 +273,12 @@ pre-step 决策使用与持久 user-role 输入相同、带标识的 `UserMessag
233
273
  /** Whether and with which messages the loop enters a proposed step. */
234
274
  type PreStepDecision =
235
275
  | { kind: 'reject' }
236
- | { kind: 'enter'; messages: UserMessage[] }
276
+ | {
277
+ kind: 'enter'
278
+ messages: UserMessage[]
279
+ /** Start a distinct model-message series before this step's admitted messages. */
280
+ startsRequestSeries?: true
281
+ }
237
282
  ```
238
283
 
239
284
  `agent/request-error` 在失败的模型步骤关闭之后、其轮次关闭之前运行。listener 可以在失败轮次的 signal 仍然存活时修复持久状态或 await 策略工作。处理该错误的 listener 返回 `{ kind: 'retry' }` 且不调用 `next()`;默认的 `undefined` 会让失败保持终态。
@@ -243,7 +288,7 @@ type PreStepDecision =
243
288
  type RequestErrorAction = { kind: 'retry' } | undefined
244
289
  ```
245
290
 
246
- `agent/pre-step` 是请求推导前唯一的串行监听器链。`agent/turn-stopping` 在轮次没有工具或 steering(中途引导)后续时运行,先于最后一次 steering 排空。
291
+ `agent/pre-step` 是请求推导前唯一的 waterfall(瀑布式)监听器链。`agent/turn-stopping` 在轮次没有工具或 steering(中途引导)后续时运行,先于最后一次 steering 排空。
247
292
 
248
293
  `agent/session-start` 携带 `SessionStartSource`(会话生命周期为何开始;桥接层据此匹配其 SessionStart):
249
294
 
@@ -256,7 +301,7 @@ type SessionStartSource = 'startup' | 'resume' | 'clear' | 'compact'
256
301
 
257
302
  `Session` 是一份类型化 `SessionEvent` 的**仅追加日志**——唯一的真源。LLM 消息历史从日志*派生*(`deriveMessages()`),而非单独存储。每个条目携带单调的 `seq`、`time` 与按 `type` 判别的 `data` payload;surface 变体还可以在 `sourceEventSeqs` 中列出被引用的较早事件,并携带 `surfaceOp`。
258
303
 
259
- `SessionEvent` 信封的确切条件字段、十二种事件变体(`turn/start`、`turn/end`、`step/start`、`step/end`、`user/message`、`assistant/chunk`、`assistant/message`、`tool/call`、`tool/result`、`steering/message`、`todo/write`、`request/header`)、`deriveMessages()` 投影规则、`TurnTrigger`/`TurnEndReason` 原因以及执行封闭和独立事件规则都在 **[session.md](./session.md)** 中。日志如何持久化——`SessionPersistence` 接口、JSONL/SQLite 后端、`session/flush` 检查点、崩溃恢复与 `SessionHeader`——则在 **[persistence.md](./persistence.md)** 中。
304
+ `SessionEvent` 信封的确切条件字段、十二种核心事件变体(`turn/start`、`turn/end`、`step/start`、`step/end`、`user/message`、`assistant/message`、`assistant/attempt`、`tool/call`、`tool/result`、`request/header`、`request/context`、`session/end-seed`)、`deriveMessages()` 投影规则、`TurnEndReason` 原因以及执行封闭和独立事件规则都在 **[session.md](./session.md)** 中。日志如何持久化——`SessionPersistence` 接口、JSONL provider、`session/flush` 检查点、崩溃恢复与 `SessionHeader`——则在 **[persistence.md](./persistence.md)** 中。
260
305
 
261
306
  ## `ToolDefinition`
262
307
 
@@ -291,14 +336,13 @@ declare module '@deepseek-ai/dsh-llm' {
291
336
  }
292
337
  ```
293
338
 
294
- 六个规范 map 使用此模式;插件作者扩展它们:
339
+ 五个规范 map 使用此模式;插件作者扩展它们:
295
340
 
296
341
  | Map | 包 | 派生 | 目录 |
297
342
  |---|---|---|---|
298
343
  | `ContentBlockMap` | dsh-llm | `ContentBlock` | [llm-streaming.md](./llm-streaming.md#content-blocks-and-messages) |
299
344
  | `MessageSourceMap` | dsh-llm | `MessageSource` | [llm-streaming.md](./llm-streaming.md#content-blocks-and-messages) |
300
345
  | `FinishReasonMap` | dsh-llm | `FinishReason` | [llm-streaming.md](./llm-streaming.md#the-model-request-and-result) |
301
- | `TurnTriggerMap` | dsh-session | `TurnTrigger` | [session.md](./session.md) |
302
346
  | `TurnEndReasonMap` | dsh-session | `TurnEndReason` | [session.md](./session.md) |
303
347
  | `SessionEventMap` | dsh-session | `SessionEvent` | [session.md](./session.md) |
304
348
 
@@ -308,9 +352,9 @@ declare module '@deepseek-ai/dsh-llm' {
308
352
 
309
353
  ### 品牌化 ID
310
354
 
311
- 在包之间传递的 ID 都经过**品牌化**——结构上是字符串,但在类型层面不可互换(不能把 `SessionId` 传给需要 `CallId` 的位置)。每种类型通过各自的工厂构造;比较、日志记录和 JSON 行为与普通字符串相同。
355
+ 在包之间传递的 ID 都经过**品牌化**——结构上是字符串,但在类型层面不可互换(不能把 `SessionId` 传给需要 `ToolCallId` 的位置)。构造使用共享 `brandString<T>()` helper 或所属方自定义的校验工厂;比较、日志记录和 JSON 行为与普通字符串相同。
312
356
 
313
- `Branded<B>` 原语位于独立的纯类型包 [dsh-brand](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/util/brand) 中(没有运行时代码,也不依赖 harness 包),因此任何包都能品牌化其拥有的 id,而无需依赖无关的能力包。
357
+ `Branded<B>` 原语与无状态构造函数位于 [dsh-brand](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/util/brand),该包不依赖 harness 能力。`brandString<T>()` 应用仅编译期存在的字符串品牌。
314
358
 
315
359
  源码:[`packages/util/brand/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/util/brand/src/index.ts)
316
360
 
@@ -319,7 +363,7 @@ declare module '@deepseek-ai/dsh-llm' {
319
363
  type Branded<B extends string> = string & { readonly [BRAND]: B }
320
364
  ```
321
365
 
322
- 两个核心 ID 是 `CallId`(关联工具调用及其结果;dsh-llm)和 `SessionId`(活跃 agent 与持久会话共享的标识;dsh-session)。能力包也会品牌化各自的 id,例如 [jobs.md](./jobs.md) 中的 `JobId`。
366
+ 两个核心 ID 是 `ToolCallId`(关联工具调用及其结果;dsh-llm)和 `SessionId`(活跃 agent 与持久会话共享的标识;dsh-session)。能力包也会品牌化各自的 id,例如 [jobs.md](./jobs.md) 中的 `JobId`。
323
367
 
324
368
  <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
325
369
 
@@ -363,13 +407,14 @@ Concrete agent factory and driver service.
363
407
  /**
364
408
  * Create an agent and session under one caller-supplied identity, owned by
365
409
  * the accessing fiber. Constructor-driven config calls mint a fresh combined
366
- * id before entering this boundary.
410
+ * id before entering this boundary. When a persistence backend is mounted,
411
+ * the session's durable identity and any seed are stored before publication.
367
412
  * @param id - shared agent/session identity.
368
413
  * @param options - concrete loop options.
369
414
  * @param meta - optional fresh-session workspace metadata.
370
415
  * @returns the published running agent.
371
416
  */
372
- create(id: SessionId, options: AgentOptions = {}, meta: Pick<SessionHeader, 'cwd'> = {}): Agent
417
+ async create(id: SessionId, options: AgentOptions = {}, meta: Pick<SessionHeader, 'cwd'> = {}): Promise<Agent>
373
418
 
374
419
  /**
375
420
  * Create an owned agent on a caller-supplied session id.
@@ -407,6 +452,35 @@ Discovery is unmemoized: `list()` and `resolve()` re-read the roots on every cal
407
452
  */
408
453
  async list(): Promise<AgentPreset[]>
409
454
 
455
+ /**
456
+ * The roster off the Host: {@link list} projected to path-free rows, with
457
+ * the default marked and this deployment's authoring capability beside it.
458
+ *
459
+ * Whether a client can open a preset's directory is the Host's own opener
460
+ * capability, not a roster property — a caller needing both joins them.
461
+ * @returns the rows and the authoring capability.
462
+ */
463
+ @Remote('list') async remoteExportList(): Promise<AgentPresetRoster>
464
+
465
+ /**
466
+ * Every preset's composition as flattened plugin rows, for plugin-listing
467
+ * surfaces beside the roster's own picker.
468
+ *
469
+ * A preset with a live standing mount answers from its newest generation's
470
+ * Loader entries — the composition new sessions join — even when the file
471
+ * behind it has since been edited into an unreadable state: the mount is
472
+ * what sessions actually run, so the broken verdict only applies to a
473
+ * preset nothing composed. One never composed since boot answers from its
474
+ * file, with `!!js` disabled gates evaluated against the Loader context so
475
+ * both answers reflect the same host. Reading never mounts: an unmounted
476
+ * preset is parsed, not composed, so listing a preset's plugins cannot
477
+ * activate them early. A composition that stopped reading between
478
+ * discovery's health verdict and this read is reported broken with the
479
+ * raced reason rather than dropped.
480
+ * @returns one composition per roster preset, in roster order.
481
+ */
482
+ async compositionInventory(): Promise<AgentPresetComposition[]>
483
+
410
484
  /**
411
485
  * Resolve one preset by id.
412
486
  *
@@ -481,6 +555,15 @@ composedPreset(agentCtx: Context): string | undefined
481
555
  */
482
556
  async read(id: string): Promise<string>
483
557
 
558
+ /**
559
+ * One preset's composition text with the roster row it belongs to.
560
+ * @param agentPreset - the preset id.
561
+ * @returns the composition beside its trust and published metadata.
562
+ * @throws {RemoteError} `gateway/bad-request` for an empty id, or
563
+ * `agent-preset/not-found` when no configured root supplies it.
564
+ */
565
+ @Remote('read') async readDocument(agentPreset: string): Promise<AgentPresetDocument>
566
+
484
567
  /**
485
568
  * Create a locally authored preset by copying an existing one whole.
486
569
  *
@@ -498,13 +581,34 @@ async read(id: string): Promise<string>
498
581
  */
499
582
  async copy(from: string, id: string, name?: string): Promise<void>
500
583
 
584
+ /**
585
+ * Copy one preset through the Remote API.
586
+ * @param from - the source preset id.
587
+ * @param id - the new preset id.
588
+ * @param name - the copy's optional display name.
589
+ * @returns once the copy is stored.
590
+ * @throws {RemoteError} with the corresponding stable preset code and
591
+ * details when the copy is refused.
592
+ */
593
+ @Remote('copy') async remoteExportCopy(from: string, id: string, name?: string): Promise<void>
594
+
501
595
  /**
502
596
  * Delete a locally authored preset.
597
+ *
503
598
  * @param id - the preset id.
504
599
  * @throws when the preset is unknown or ships with the deployment.
505
600
  */
506
601
  async remove(id: string): Promise<void>
507
602
 
603
+ /**
604
+ * Delete one preset through the Remote API.
605
+ * @param id - the preset id.
606
+ * @returns once the preset is deleted.
607
+ * @throws {RemoteError} with the corresponding stable preset code and
608
+ * details when deletion is refused.
609
+ */
610
+ @Remote('deletePreset') async remoteExportDelete(id: string): Promise<void>
611
+
508
612
  /**
509
613
  * One agent's instance of a service its preset mounted.
510
614
  *
@@ -537,7 +641,9 @@ serviceFor<K extends string & keyof Context>(agent: { ctx: Context }, name: K):
537
641
  * state to restore. The re-link runs through the binding this roster kept
538
642
  * from the agent's mount — dsh-scope's only re-link authority. An agent
539
643
  * that never composed one has nothing to re-link: the switch is then the
540
- * agent's first bind, exactly a mount.
644
+ * agent's first bind, exactly a mount. A committed re-link emits
645
+ * `tools/change` because changing the parent scope changes the Agent's
646
+ * resolved tool set without adding or removing registry entries.
541
647
  * @param agentCtx - the agent's scope context.
542
648
  * @param id - the preset to compose the agent from instead.
543
649
  * @returns the preset now installed.
@@ -545,6 +651,16 @@ serviceFor<K extends string & keyof Context>(agent: { ctx: Context }, name: K):
545
651
  */
546
652
  async recompose(agentCtx: Context, id: string): Promise<AgentPreset>
547
653
 
654
+ /**
655
+ * Compose a blank session's agent from a different preset and record it.
656
+ * @param agent - the session's live agent, resolved from the wire identity.
657
+ * @param agentPreset - the preset to compose the agent from instead.
658
+ * @returns the preset id that was recorded.
659
+ * @throws {RemoteError} with `gateway/bad-request`, `agent-preset/locked`,
660
+ * `agent-preset/not-found`, or `agent-preset/invalid` when refused.
661
+ */
662
+ @Remote('select') async select(agent: Agent, agentPreset: string): Promise<string>
663
+
548
664
  /**
549
665
  * The standing scope key of one preset, for a host reader with no agent.
550
666
  *
@@ -739,6 +855,29 @@ Source: [`packages/core/agent/src/index.ts`](https://github.com/deepseek-ai/deep
739
855
 
740
856
  ### `agent/*` events
741
857
 
858
+ <a id="agentassistant-stream--emit"></a>
859
+
860
+ #### `agent/assistant-stream` — emit
861
+
862
+ Process-local assistant-stream publication. Chunk frames are transient; the loop appends one final v2 `assistant/message` or `assistant/attempt` with the same stream before a committed end frame.
863
+
864
+ ```ts cordis-catalog
865
+ /**
866
+ * Process-local assistant-stream publication. Chunk frames are transient;
867
+ * the loop appends one final v2 `assistant/message` or `assistant/attempt`
868
+ * with the same stream before a committed end frame.
869
+ * @param payload.agent - the agent whose attempt produced the frame.
870
+ * @param payload.frame - one ordered start, chunk, or end publication.
871
+ * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
872
+ * @mode emit
873
+ */
874
+ 'agent/assistant-stream'(this: Scoped<Agent>, payload: { agent: Agent; frame: AssistantStreamFrame }): void
875
+ ```
876
+
877
+ Types: [Scoped](./scope.md)
878
+
879
+ Source: [`packages/core/agent/src/runtime-types.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/agent/src/runtime-types.ts)
880
+
742
881
  <a id="agentcreated--emit"></a>
743
882
 
744
883
  #### `agent/created` — emit
@@ -37,13 +37,17 @@ interface ResolvedCredential {
37
37
  `describe(ref)` 在绝不暴露值的前提下回应配置界面:引用当前是否可解析、来自哪一层、`set` 当前能否成功。本地提供方把由当前进程环境供值的引用报告为 `writable: false`——那样的写入会表面成功而解析持续返回遮蔽值,因此 seam 直接拒绝,界面也得以提前把该引用渲染为只读。
38
38
 
39
39
  ```ts type-equiv
40
- /** Source and writability facts for one reference, safe for configuration UIs — never the value. */
40
+ /**
41
+ * Source and writability facts for one reference, safe for configuration UIs —
42
+ * never the value. The view has no slot a value could ride in, which is what
43
+ * lets the whole read half cross the Remote wire.
44
+ */
41
45
  interface CredentialInfo {
42
- /** Whether {@link CredentialProvider.resolve} would currently return a value. */
46
+ /** Whether resolving the reference would currently return a value. */
43
47
  configured: boolean
44
48
  /** Source layer currently supplying the value; absent while unconfigured. */
45
49
  source?: string
46
- /** Whether {@link CredentialProvider.set} would currently succeed for this reference. */
50
+ /** Whether the active provider can write this reference. */
47
51
  writable: boolean
48
52
  }
49
53
  ```
@@ -215,6 +219,43 @@ abstract deleteRecord(key: CredentialKey): Promise<void>
215
219
 
216
220
  Source: [`packages/credentials/credentials/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/credentials/credentials/src/index.ts)
217
221
 
222
+ <a id="ctxcredentialscontroller--credentialscontroller"></a>
223
+
224
+ ### `ctx.credentialsController` — `CredentialsController`
225
+
226
+ Host service backing the generated `ctx.remote.credentials` namespace. It carries every wire obligation the credential seam itself does not: the batch fan-out bound, the field-by-field view projection, the reference-grammar guard, and the refusal mapping. Secret values cross in one direction only — no method here returns one.
227
+
228
+ ```ts cordis-catalog
229
+ /**
230
+ * Describe several references for one configuration surface. Batched because
231
+ * a settings page describes every reference its rows name at once, and one
232
+ * round trip keeps those rows from settling separately.
233
+ * @param refs - reference names, at most {@link MAX_DESCRIBE_REFS}; a name outside the grammar
234
+ * rejects the whole call as `gateway/bad-request`.
235
+ * @returns one view per requested name, keyed by that name.
236
+ * @throws RemoteError when the request is invalid or no credential provider is mounted.
237
+ */
238
+ @Remote async describe(refs: string[]): Promise<Record<string, CredentialInfo>>
239
+
240
+ /**
241
+ * Store one value from a configuration surface. The value crosses the wire in
242
+ * this direction only: no read path returns it.
243
+ * @param ref - reference name to store under.
244
+ * @param value - the non-empty secret value.
245
+ * @throws RemoteError when the request is invalid, no provider is mounted, or the provider refuses the write.
246
+ */
247
+ @Remote async set(ref: string, value: string): Promise<void>
248
+
249
+ /**
250
+ * Remove one reference from a configuration surface.
251
+ * @param ref - reference name to remove.
252
+ * @throws RemoteError when the request is invalid, no provider is mounted, or the provider refuses the write.
253
+ */
254
+ @Remote async unset(ref: string): Promise<void>
255
+ ```
256
+
257
+ Source: [`packages/api/settings-controller/src/credentials.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/api/settings-controller/src/credentials.ts)
258
+
218
259
  <a id="authorization-events"></a>
219
260
 
220
261
  ### `authorization/*` events
@@ -15,7 +15,7 @@ outline: [2,3]
15
15
 
16
16
  每个操作首先将用户提供的路径解析为不透明的后端目标。消费方可以显示 `displayPath`,但禁止解析 `targetKey`(一个品牌化的不透明 id),也不得假设它是本地绝对路径。
17
17
 
18
- 与文件系统共享执行世界的消费方通过提供方获取跨能力坐标,而不是解释该身份:`processPath(target)` 返回子进程可以打开的规范化绝对路径,`fileUrl(target)` 返回采用提供方平台语法的 `file:` URI,`contains(parent, child)` 则检查规范化身份相等或后代包含关系。
18
+ 与文件系统共享执行世界的消费方通过提供方获取跨能力坐标,而不是解释该身份:`processPath(target)` 返回子进程可以打开的规范化绝对路径;`processPathFromHostPath(hostPath)` 只在该执行世界共享相应宿主文件时映射其绝对路径;`fileUrl(target)` 返回采用提供方平台语法的 `file:` URI;`contains(parent, child)` 检查规范化身份相等或后代包含关系。
19
19
 
20
20
  ```ts type-equiv
21
21
  /**
@@ -278,7 +278,7 @@ type FsErrorCode =
278
278
 
279
279
  ## 服务与插件
280
280
 
281
- `FileSystem`(`ctx.fs`,abstract)拥有提供方原语:`resolve`、`processPath`、`fileUrl`、`contains`、`stat`、`lstat`、`readText`、`streamText`、`readBytes`、`listDir`、`writeText` 与 `editText`。`dsh-fs-observation-policy` **不注册服务**——它是一个通过 `fs/*` 事件门禁添加策略的插件:根据未见/缺失/存在状态对写入与编辑意图 waterfall 作出决策,并记录 `FsObservation` 值。执行器是 `dsh-tool-fs`:它通过 `ctx.fs` 读取/写入/编辑,分发 waterfall,并 emit 记录事件。下方生成的 [`ctx.fs` 小节](#ctxfs--filesystem-abstract-seam) 展示确切的 `ctx.fs` 签名。
281
+ `FileSystem`(`ctx.fs`,abstract)拥有提供方原语:`resolve`、`processPath`、`processPathFromHostPath`、`fileUrl`、`contains`、`stat`、`lstat`、`readText`、`streamText`、`readBytes`、`listDir`、`writeText` 与 `editText`。`dsh-fs-observation-policy` **不注册服务**。它通过 `fs/*` 事件门禁添加策略,根据未见、缺失或存在状态对写入与编辑意图 waterfall 作出决策,并记录 `FsObservation` 值。执行器是 `dsh-tool-fs`:它通过 `ctx.fs` 读取、写入或编辑,分发 waterfall,并 emit 记录事件。下方生成的 [`ctx.fs` 小节](#ctxfs--filesystem-abstract-seam) 展示确切的 `ctx.fs` 签名。
282
282
 
283
283
  <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
284
284
 
@@ -316,6 +316,16 @@ abstract resolve(path: string, opts?: { cwd?: string; signal?: AbortSignal }): P
316
316
  */
317
317
  abstract processPath(target: FsTarget): string
318
318
 
319
+ /**
320
+ * Map an absolute path from the harness host into this filesystem's
321
+ * execution world when both paths identify the same file. The base provider
322
+ * exposes no mapping; host-backed or explicitly shared backends override it.
323
+ * @param hostPath - absolute path in the harness host filesystem.
324
+ * @returns the process path for the same file, or undefined when this
325
+ * execution world cannot read that host file.
326
+ */
327
+ processPathFromHostPath(hostPath: string): string | undefined
328
+
319
329
  /**
320
330
  * Return the canonical `file:` URI for a target in this filesystem's
321
331
  * execution world. Backends own URI encoding because the host platform may
@@ -145,7 +145,7 @@ interface GoalChanged {
145
145
 
146
146
  ## 服务行为
147
147
 
148
- [`GoalService`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/goal/goal/src/index.ts) 解析创建默认值、从持久 `goal/change` 事件执行严格回放折叠、校验传入的 agent(智能体)是注册表中的确切活跃实例、以比较并设置方式执行变更,并发出 `goal/changed` 通知;监听器故障会被隔离。包 [README](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/goal/goal/README.zh.md) 定义可调用 API 和面向模型的约定。
148
+ [`GoalService`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/goal/goal/src/index.ts) 解析创建默认值、从可选注册的 `goal` 投影读取严格回放结果、校验传入的 agent(智能体)是注册表中的确切活跃实例、以比较并设置方式执行变更,并发出 `goal/changed` 通知;监听器故障会被隔离。注册表或 key 缺失时,第一次依赖它们的访问会失败。包 [README](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/goal/goal/README.zh.md) 定义可调用 API 和面向模型的约定。
149
149
 
150
150
  <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
151
151
 
@@ -16,9 +16,10 @@ outline: [2,3]
16
16
  | [typert.md](./typert.md) | 远程调用描述符、lookup/Context 声明、Typert 注册表,以及 Host Gateway/Client API 边界 |
17
17
  | [goal.md](./goal.md) | 持久 goal 标识、生命周期快照、激活、变更记录与 Round 归属 |
18
18
  | [schedule.md](./schedule.md) | 仅限 Session 内的提醒记录、持久转换、活动视图与普通对话交付 |
19
+ | [todo.md](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/todo.zh.md) | todo 包的整列表条目类型、持久事件所有权、投影和开放轮次不变量 |
19
20
  | [commands.md](./commands.md) | 人类命令注册表服务:定义、适配器发现、直接调用、结果与解析视图 |
20
- | [session.md](./session.md) | 完整的 `SessionEventMap` 变体目录、`TurnTrigger`/`TurnEndReason`、`deriveMessages()`、执行封闭与独立事件 |
21
- | [persistence.md](./persistence.md) | 持久性 seam:`SessionPersistence`、JSONL + SQLite 后端、`session/flush`、崩溃恢复、`SessionHeader` |
21
+ | [session.md](./session.md) | 完整的 `SessionEventMap` 变体目录、`TurnEndReason`、`deriveMessages()`、执行封闭与独立事件 |
22
+ | [persistence.md](./persistence.md) | 持久性 seam:`SessionPersistence`、JSONL provider、`session/flush`、崩溃恢复、`SessionHeader` |
22
23
  | [settings.md](./settings.md) | 用户设置 seam:`SettingsNamespace` 注册、分层解析(默认值 → 组合 `base` → 用户文档)、owner scope、热提交 |
23
24
  | [credentials.md](./credentials.md) | 凭据 seam:配置中的 `CredentialRef` 引用(绝不含值)、按操作解析、对 UI 安全的 `CredentialInfo`、提供方来源层 |
24
25
  | [session-query.md](./session-query.md) | 逻辑记录、有界精确事件读取、关系追踪、语义筛选器/文档与全文检索结果页 |
@@ -50,9 +51,13 @@ outline: [2,3]
50
51
  | [plan.md](./plan.md) | 计划模式:仅记日志的 `plan/mode` 状态、待定选择的冲刷、`PlanModeConfig`、`exit_plan_mode` 审阅流程 |
51
52
  | [invariants.md](./invariants.md) | 运行时不变式注册表:选择配置 `Config`、`InvariantInstaller`/`InvariantFailure`、空配套插件约定 |
52
53
  | [web-server.md](./web-server.md) | HTTP 载体:`WebRouteKind`/`WebRoute`、匹配顺序、可认领的回退席位、index 渲染挂接点 |
54
+ | [webhook.md](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/webhook.zh.md) | 通过身份验证的提供方交付、任意程序化规则,以及 fire-and-forget 的 Workspace Session 创建 |
53
55
  | [storage.md](./storage.md) | 存储子系统:后端约定(`StorageBackend`)、`StorageForms`、`DomainSpec`/`Domain`、`domain/changed` |
54
56
  | [workspace.md](./workspace.md) | 工作区注册表:`Workspace`/`WorkspaceId`、注册与解析、与会话 `cwd` 的关系 |
57
+ | [web-client.md](./web-client.md) | 浏览器架构:启动、Remote 通信、配对的 Client model、UI adapter、Conversation 组装、Slots 与重连语义 |
55
58
  | [client-modules.md](./client-modules.md) | Web 插件表:`dsh.client` 声明、`WebBootGraph` 线上组合、bundle 路由与 index 转换 |
59
+ | [slots.md](./slots.md) | 类型化 Web UI 组合:声明所有权、cardinality 与 scope、框架与功能注入、props 推导及当前层级 |
60
+ | [conversation.md](./conversation.md) | target-neutral Session event 组装:Context identity、Location data、replay 路径、view builder 与 target 自有 render node |
56
61
  | [session-projection.md](./session-projection.md) | 投影 seam:`SessionProjectionMap`、纯函数 `ProjectionDefinition` 单元、`ProjectionSnapshot` 的一致切面、变更馈送 |
57
62
  | [session-telemetry.md](./session-telemetry.md) | 对外会话上报能力 seam:`SessionTelemetryRecord`/`SessionTelemetrySeverity`、`SessionTelemetrySink` 约定和 `session-telemetry/record` 脱敏 waterfall |
58
63
 
@@ -157,7 +157,7 @@ interface JobRead {
157
157
 
158
158
  ## 服务行为
159
159
 
160
- 抽象的 [`JobRegistry`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/jobs/jobs/src/index.ts) Service Definition 规定原子 `start`、限定调用方作用域的 `get` 和 `list`、`read`、`kill`、有界 `wait`、故障隔离的 `onJobDone` 与 `onJobsChanged` 监听器,以及 `attachController` 何时可用;[`LocalJobRegistry`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/jobs/jobs-local/src/index.ts) 是其进程局部 Service Provider。授权会比较拥有者会话;拥有者清理与准入会使用确切的已注册 `Agent` 实例。本地 Service Provider 的 `maxConcurrentJobsPerOwner` 配置必须是正的安全整数,默认值为 `10`;它按确切 owner 统计 `running` 与 `stopping` 记录,所有无 owner 任务共享一个服务级桶,并在生产方终止结算后释放容量。Service Definition 约定见 [`dsh-jobs`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/jobs/jobs/README.zh.md),注册表生命周期与准入策略见 [`dsh-jobs-local`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/jobs/jobs-local/README.zh.md),面向模型的 Consumer 见 [`dsh-tool-jobs`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/jobs/tool-jobs/README.zh.md)。
160
+ 抽象的 [`JobRegistry`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/jobs/jobs/src/index.ts) Service Definition 规定原子 `start`、限定调用方作用域的 `get` 和 `list`、`read`、`kill`、有界 `wait`、故障隔离的 `onJobDone` 与 `onJobsChanged` 监听器,以及 `attachController`;[`LocalJobRegistry`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/jobs/jobs-local/src/index.ts) 是其进程局部 Service Provider。授权会比较拥有者会话;拥有者清理与准入会使用确切的已注册 `Agent` 实例。本地 Service Provider 的 `maxConcurrentJobsPerOwner` 配置必须是正的安全整数,默认值为 `10`;它按确切 owner 统计 `running` 与 `stopping` 记录,所有无 owner 任务共享一个服务级桶,并在生产方终止结算后释放容量。Service Definition 约定见 [`dsh-jobs`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/jobs/jobs/README.zh.md),注册表生命周期与准入策略见 [`dsh-jobs-local`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/jobs/jobs-local/README.zh.md),面向模型的 Consumer 见 [`dsh-tool-jobs`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/jobs/tool-jobs/README.zh.md)。
161
161
 
162
162
  <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
163
163