dsh-plugin-dev-kb 1.0.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 (234) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +56 -0
  3. package/cordis.patch.yml +12 -0
  4. package/kb/INDEX.md +210 -0
  5. package/kb/README.md +69 -0
  6. package/kb/extra/AGENTS.md +75 -0
  7. package/kb/extra/api-gateway.md +164 -0
  8. package/kb/extra/api-gateway.zh.md +164 -0
  9. package/kb/extra/cookbook/adding-a-vendored-package.md +59 -0
  10. package/kb/extra/cookbook/adding-a-vendored-package.zh.md +59 -0
  11. package/kb/extra/cookbook/maintaining-dsh-code-review.md +64 -0
  12. package/kb/extra/cookbook/maintaining-dsh-code-review.zh.md +64 -0
  13. package/kb/extra/cookbook/responding-to-pr-review-on-a-stack.md +32 -0
  14. package/kb/extra/cookbook/responding-to-pr-review-on-a-stack.zh.md +32 -0
  15. package/kb/extra/defensive-patterns.md +33 -0
  16. package/kb/extra/defensive-patterns.zh.md +33 -0
  17. package/kb/extra/development.md +171 -0
  18. package/kb/extra/development.zh.md +171 -0
  19. package/kb/extra/event-producer-consumer.md +76 -0
  20. package/kb/extra/event-producer-consumer.zh.md +78 -0
  21. package/kb/extra/glossary.md +45 -0
  22. package/kb/extra/glossary.zh.md +45 -0
  23. package/kb/extra/graph-atlas.md +24 -0
  24. package/kb/extra/graph-atlas.zh.md +26 -0
  25. package/kb/extra/i18n/README.md +60 -0
  26. package/kb/extra/i18n/README.zh.md +60 -0
  27. package/kb/extra/i18n/style-samples.md +87 -0
  28. package/kb/extra/i18n/terminology.md +214 -0
  29. package/kb/extra/i18n/translation-prompt.md +263 -0
  30. package/kb/extra/i18n/translation-rules.md +69 -0
  31. package/kb/extra/i18n/translation-rules.zh.md +69 -0
  32. package/kb/extra/module-graph.md +1641 -0
  33. package/kb/extra/module-graph.zh.md +1643 -0
  34. package/kb/extra/postmortem/0001-acp-default-export-drops-inject.md +113 -0
  35. package/kb/extra/postmortem/0001-acp-default-export-drops-inject.zh.md +113 -0
  36. package/kb/extra/postmortem/0002-js-expression-disabled-filesystem-tools.md +47 -0
  37. package/kb/extra/postmortem/0002-js-expression-disabled-filesystem-tools.zh.md +47 -0
  38. package/kb/extra/postmortem/0003-web-agent-gui-feedback-loop.md +53 -0
  39. package/kb/extra/postmortem/0003-web-agent-gui-feedback-loop.zh.md +53 -0
  40. package/kb/extra/postmortem/0004-landlock-partial-notice-misclassified-child-failures.md +55 -0
  41. package/kb/extra/postmortem/0004-landlock-partial-notice-misclassified-child-failures.zh.md +55 -0
  42. package/kb/extra/postmortem/README.md +18 -0
  43. package/kb/extra/postmortem/README.zh.md +18 -0
  44. package/kb/extra/rescope.md +53 -0
  45. package/kb/extra/rescope.zh.md +53 -0
  46. package/kb/extra/subsystems/attachment.md +125 -0
  47. package/kb/extra/subsystems/attachment.zh.md +125 -0
  48. package/kb/extra/subsystems/extensions.md +364 -0
  49. package/kb/extra/subsystems/extensions.zh.md +364 -0
  50. package/kb/extra/subsystems/feedback.md +266 -0
  51. package/kb/extra/subsystems/feedback.zh.md +266 -0
  52. package/kb/extra/testing.md +49 -0
  53. package/kb/extra/testing.zh.md +49 -0
  54. package/kb/extra/web-styling.md +25 -0
  55. package/kb/extra/web-styling.zh.md +25 -0
  56. package/kb/meta/search-index.json +1328 -0
  57. package/kb/meta/site-pages.txt +168 -0
  58. package/kb/meta/source.json +13 -0
  59. package/kb/meta/topics.md +75 -0
  60. package/kb/site/develop/basic/config.md +108 -0
  61. package/kb/site/develop/basic/index.md +146 -0
  62. package/kb/site/develop/basic/publish.md +185 -0
  63. package/kb/site/develop/basic/tool.md +54 -0
  64. package/kb/site/develop/cordis-tutorial/01-first-plugin.md +95 -0
  65. package/kb/site/develop/cordis-tutorial/02-lifecycle-and-effects.md +98 -0
  66. package/kb/site/develop/cordis-tutorial/03-services.md +98 -0
  67. package/kb/site/develop/cordis-tutorial/04-events.md +144 -0
  68. package/kb/site/develop/cordis-tutorial/05-config.md +84 -0
  69. package/kb/site/develop/cordis-tutorial/06-composition-and-hmr.md +113 -0
  70. package/kb/site/develop/cordis-tutorial/07-into-the-harness.md +107 -0
  71. package/kb/site/develop/cordis-tutorial/index.md +62 -0
  72. package/kb/site/develop/framework/events.md +145 -0
  73. package/kb/site/develop/framework/index.md +139 -0
  74. package/kb/site/develop/framework/service.md +152 -0
  75. package/kb/site/develop/practice/index.md +157 -0
  76. package/kb/site/develop/practice/llm-adapter.md +190 -0
  77. package/kb/site/en/develop/basic/config.md +108 -0
  78. package/kb/site/en/develop/basic/index.md +146 -0
  79. package/kb/site/en/develop/basic/publish.md +185 -0
  80. package/kb/site/en/develop/basic/tool.md +54 -0
  81. package/kb/site/en/develop/cordis-tutorial/01-first-plugin.md +95 -0
  82. package/kb/site/en/develop/cordis-tutorial/02-lifecycle-and-effects.md +98 -0
  83. package/kb/site/en/develop/cordis-tutorial/03-services.md +98 -0
  84. package/kb/site/en/develop/cordis-tutorial/04-events.md +144 -0
  85. package/kb/site/en/develop/cordis-tutorial/05-config.md +84 -0
  86. package/kb/site/en/develop/cordis-tutorial/06-composition-and-hmr.md +113 -0
  87. package/kb/site/en/develop/cordis-tutorial/07-into-the-harness.md +107 -0
  88. package/kb/site/en/develop/cordis-tutorial/index.md +60 -0
  89. package/kb/site/en/develop/framework/events.md +145 -0
  90. package/kb/site/en/develop/framework/index.md +139 -0
  91. package/kb/site/en/develop/framework/service.md +150 -0
  92. package/kb/site/en/develop/practice/index.md +157 -0
  93. package/kb/site/en/develop/practice/llm-adapter.md +190 -0
  94. package/kb/site/en/guide/providers-custom-form.png +0 -0
  95. package/kb/site/en/guide/providers-models-page.png +0 -0
  96. package/kb/site/en/guide/providers.md +100 -0
  97. package/kb/site/en/guide/python-sdk.md +106 -0
  98. package/kb/site/en/guide/quickstart.md +32 -0
  99. package/kb/site/en/index.md +8 -0
  100. package/kb/site/en/reference/agent-lifecycle.md +86 -0
  101. package/kb/site/en/reference/capability-seams.md +475 -0
  102. package/kb/site/en/reference/config-catalog.md +3155 -0
  103. package/kb/site/en/reference/cookbook/adding-a-conversation-node.md +235 -0
  104. package/kb/site/en/reference/cookbook/adding-a-package.md +120 -0
  105. package/kb/site/en/reference/cookbook/adding-a-settings-card.md +102 -0
  106. package/kb/site/en/reference/cookbook/adding-a-tool.md +96 -0
  107. package/kb/site/en/reference/cookbook/adding-an-llm-adapter.md +45 -0
  108. package/kb/site/en/reference/cookbook/extension-cookbook.md +131 -0
  109. package/kb/site/en/reference/cordis-api/context.md +368 -0
  110. package/kb/site/en/reference/cordis-api/events.md +211 -0
  111. package/kb/site/en/reference/cordis-api/fiber.md +379 -0
  112. package/kb/site/en/reference/cordis-api/inherited.md +43 -0
  113. package/kb/site/en/reference/cordis-api/registry.md +156 -0
  114. package/kb/site/en/reference/cordis-api/service.md +106 -0
  115. package/kb/site/en/reference/cordis-primer.md +46 -0
  116. package/kb/site/en/reference/index.md +131 -0
  117. package/kb/site/en/reference/persistence-catalog.md +949 -0
  118. package/kb/site/en/reference/subsystems/approval.md +173 -0
  119. package/kb/site/en/reference/subsystems/client-modules.md +121 -0
  120. package/kb/site/en/reference/subsystems/code-runtime.md +194 -0
  121. package/kb/site/en/reference/subsystems/commands.md +190 -0
  122. package/kb/site/en/reference/subsystems/compaction.md +241 -0
  123. package/kb/site/en/reference/subsystems/core.md +1073 -0
  124. package/kb/site/en/reference/subsystems/credentials.md +136 -0
  125. package/kb/site/en/reference/subsystems/filesystem.md +498 -0
  126. package/kb/site/en/reference/subsystems/goal.md +280 -0
  127. package/kb/site/en/reference/subsystems/index.md +58 -0
  128. package/kb/site/en/reference/subsystems/invariants.md +91 -0
  129. package/kb/site/en/reference/subsystems/jobs.md +293 -0
  130. package/kb/site/en/reference/subsystems/llm-streaming.md +920 -0
  131. package/kb/site/en/reference/subsystems/lsp.md +205 -0
  132. package/kb/site/en/reference/subsystems/permission-presets.md +134 -0
  133. package/kb/site/en/reference/subsystems/persistence.md +388 -0
  134. package/kb/site/en/reference/subsystems/plan.md +90 -0
  135. package/kb/site/en/reference/subsystems/sandbox.md +221 -0
  136. package/kb/site/en/reference/subsystems/schedule.md +189 -0
  137. package/kb/site/en/reference/subsystems/scope.md +62 -0
  138. package/kb/site/en/reference/subsystems/session-projection.md +265 -0
  139. package/kb/site/en/reference/subsystems/session-query.md +498 -0
  140. package/kb/site/en/reference/subsystems/session-reference.md +111 -0
  141. package/kb/site/en/reference/subsystems/session-telemetry.md +197 -0
  142. package/kb/site/en/reference/subsystems/session-title.md +207 -0
  143. package/kb/site/en/reference/subsystems/session.md +852 -0
  144. package/kb/site/en/reference/subsystems/settings.md +313 -0
  145. package/kb/site/en/reference/subsystems/shell.md +306 -0
  146. package/kb/site/en/reference/subsystems/skills.md +334 -0
  147. package/kb/site/en/reference/subsystems/spill.md +120 -0
  148. package/kb/site/en/reference/subsystems/storage.md +232 -0
  149. package/kb/site/en/reference/subsystems/subagent.md +737 -0
  150. package/kb/site/en/reference/subsystems/subprocess.md +327 -0
  151. package/kb/site/en/reference/subsystems/system-prompt.md +210 -0
  152. package/kb/site/en/reference/subsystems/terminal.md +187 -0
  153. package/kb/site/en/reference/subsystems/token-meter.md +93 -0
  154. package/kb/site/en/reference/subsystems/tools.md +723 -0
  155. package/kb/site/en/reference/subsystems/typert.md +339 -0
  156. package/kb/site/en/reference/subsystems/user-questions.md +181 -0
  157. package/kb/site/en/reference/subsystems/web-server.md +111 -0
  158. package/kb/site/en/reference/subsystems/web.md +202 -0
  159. package/kb/site/en/reference/subsystems/workflow.md +281 -0
  160. package/kb/site/en/reference/subsystems/workspace.md +231 -0
  161. package/kb/site/en/reference/tool-catalog.md +1877 -0
  162. package/kb/site/en/reference/tool-execution-pipeline.md +66 -0
  163. package/kb/site/guide/providers-custom-form.zh.png +0 -0
  164. package/kb/site/guide/providers-models-page.zh.png +0 -0
  165. package/kb/site/guide/providers.md +100 -0
  166. package/kb/site/guide/python-sdk.md +106 -0
  167. package/kb/site/guide/quickstart.md +32 -0
  168. package/kb/site/index.md +8 -0
  169. package/kb/site/reference/agent-lifecycle.md +86 -0
  170. package/kb/site/reference/capability-seams.md +475 -0
  171. package/kb/site/reference/config-catalog.md +3154 -0
  172. package/kb/site/reference/cookbook/adding-a-conversation-node.md +235 -0
  173. package/kb/site/reference/cookbook/adding-a-package.md +120 -0
  174. package/kb/site/reference/cookbook/adding-a-settings-card.md +102 -0
  175. package/kb/site/reference/cookbook/adding-a-tool.md +98 -0
  176. package/kb/site/reference/cookbook/adding-an-llm-adapter.md +45 -0
  177. package/kb/site/reference/cookbook/extension-cookbook.md +133 -0
  178. package/kb/site/reference/cordis-api/context.md +368 -0
  179. package/kb/site/reference/cordis-api/events.md +211 -0
  180. package/kb/site/reference/cordis-api/fiber.md +379 -0
  181. package/kb/site/reference/cordis-api/inherited.md +43 -0
  182. package/kb/site/reference/cordis-api/registry.md +156 -0
  183. package/kb/site/reference/cordis-api/service.md +106 -0
  184. package/kb/site/reference/cordis-primer.md +52 -0
  185. package/kb/site/reference/index.md +135 -0
  186. package/kb/site/reference/persistence-catalog.md +949 -0
  187. package/kb/site/reference/subsystems/approval.md +173 -0
  188. package/kb/site/reference/subsystems/client-modules.md +121 -0
  189. package/kb/site/reference/subsystems/code-runtime.md +194 -0
  190. package/kb/site/reference/subsystems/commands.md +190 -0
  191. package/kb/site/reference/subsystems/compaction.md +241 -0
  192. package/kb/site/reference/subsystems/core.md +1081 -0
  193. package/kb/site/reference/subsystems/credentials.md +136 -0
  194. package/kb/site/reference/subsystems/filesystem.md +498 -0
  195. package/kb/site/reference/subsystems/goal.md +280 -0
  196. package/kb/site/reference/subsystems/index.md +58 -0
  197. package/kb/site/reference/subsystems/invariants.md +91 -0
  198. package/kb/site/reference/subsystems/jobs.md +293 -0
  199. package/kb/site/reference/subsystems/llm-streaming.md +926 -0
  200. package/kb/site/reference/subsystems/lsp.md +205 -0
  201. package/kb/site/reference/subsystems/permission-presets.md +134 -0
  202. package/kb/site/reference/subsystems/persistence.md +388 -0
  203. package/kb/site/reference/subsystems/plan.md +90 -0
  204. package/kb/site/reference/subsystems/sandbox.md +221 -0
  205. package/kb/site/reference/subsystems/schedule.md +189 -0
  206. package/kb/site/reference/subsystems/scope.md +62 -0
  207. package/kb/site/reference/subsystems/session-projection.md +265 -0
  208. package/kb/site/reference/subsystems/session-query.md +498 -0
  209. package/kb/site/reference/subsystems/session-reference.md +111 -0
  210. package/kb/site/reference/subsystems/session-telemetry.md +197 -0
  211. package/kb/site/reference/subsystems/session-title.md +207 -0
  212. package/kb/site/reference/subsystems/session.md +854 -0
  213. package/kb/site/reference/subsystems/settings.md +313 -0
  214. package/kb/site/reference/subsystems/shell.md +306 -0
  215. package/kb/site/reference/subsystems/skills.md +334 -0
  216. package/kb/site/reference/subsystems/spill.md +120 -0
  217. package/kb/site/reference/subsystems/storage.md +232 -0
  218. package/kb/site/reference/subsystems/subagent.md +739 -0
  219. package/kb/site/reference/subsystems/subprocess.md +327 -0
  220. package/kb/site/reference/subsystems/system-prompt.md +210 -0
  221. package/kb/site/reference/subsystems/terminal.md +187 -0
  222. package/kb/site/reference/subsystems/token-meter.md +93 -0
  223. package/kb/site/reference/subsystems/tools.md +723 -0
  224. package/kb/site/reference/subsystems/typert.md +339 -0
  225. package/kb/site/reference/subsystems/user-questions.md +181 -0
  226. package/kb/site/reference/subsystems/web-server.md +111 -0
  227. package/kb/site/reference/subsystems/web.md +202 -0
  228. package/kb/site/reference/subsystems/workflow.md +281 -0
  229. package/kb/site/reference/subsystems/workspace.md +231 -0
  230. package/kb/site/reference/tool-catalog.md +1880 -0
  231. package/kb/site/reference/tool-execution-pipeline.md +66 -0
  232. package/package.json +40 -0
  233. package/scripts/rebuild-index.mjs +88 -0
  234. package/skills/dsh-plugin-dev-kb.md +66 -0
@@ -0,0 +1,327 @@
1
+ ---
2
+ editSource: "docs/subsystems/subprocess.zh.md"
3
+ outline: [2,3]
4
+ ---
5
+
6
+ # 子进程
7
+
8
+ 子进程 seam 分为 Service Definition([dsh-subprocess](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/subprocess/subprocess),`ctx.subprocess`)与 Service Provider([dsh-subprocess-local](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/subprocess/subprocess-local));它的 Consumer 是其他能力 seam 与进程外后端:[bash 执行器家族](./shell.md)使用收集模式的批量输出,LSP 使用原始协议管道,PTY 后端使用终端原语,ACP(Agent Client Protocol)subagent 后端则使用通过管道传输的 ndjson,并让 stderr 采用 inherit。该 seam 拥有受管的 `DSH_*` 环境命名空间、共享的凭据清除(`scrubbedParentEnv`)与 `CollectedOutput` 形状;[dsh-shell](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/shell/shell) 重导出这套词汇,使 bash 消费方保持单一导入入口。
9
+
10
+ 源码:[`packages/subprocess/subprocess/src/types.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/subprocess/subprocess/src/types.ts) 与 [`packages/subprocess/subprocess/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/subprocess/subprocess/src/index.ts)
11
+
12
+ ## 可执行文件查找
13
+
14
+ 一个提供方的 spawn 工作目录、可执行文件路径、普通进程与终端会话,和挂载的文件系统提供方处于同一路径与进程命名空间。`resolveExecutable(command, env?, signal?)` 验证绝对可执行文件路径,或通过提供方清理后的 `PATH` 加有意覆盖来解析裸名称。
15
+
16
+ ## 受管环境命名空间与捕获的输出
17
+
18
+ `DSH_*` 变量是归 Harness 所有的子进程事实;实现会在合并调用方显式 `env` 之前丢弃环境中已有的 `DSH_*` 名称,因此当前事实只会以有意提供的字符串条目形式到达,而显式的 `undefined` tombstone 会删除普通环境中已有的值。每条被收集的流都通过 `CollectedOutput` 报告自身的截断与 spill 恢复状态。
19
+
20
+ ```ts type-equiv
21
+ /** One environment key inside the managed {@link DSH_ENV_PREFIX} namespace. */
22
+ type DshEnvironmentKey = `${typeof DSH_ENV_PREFIX}${string}`
23
+ ```
24
+
25
+ ```ts type-equiv
26
+ /** Trusted DeepSeek Harness variables for one child-process execution. */
27
+ type DshEnvironment = Readonly<Record<DshEnvironmentKey, string>>
28
+ ```
29
+
30
+ ```ts type-equiv
31
+ /** One captured stream: the (possibly truncated) text plus recovery info. */
32
+ interface CollectedOutput {
33
+ /** Collected text — the TAIL of the stream when truncated. */
34
+ text: string
35
+ /** True when bytes were dropped from `text`. */
36
+ truncated: boolean
37
+ /** Path to a file holding the COMPLETE stream, when truncated and available. */
38
+ spillPath?: string
39
+ }
40
+ ```
41
+
42
+ ## Node 风格的 stdio 处置方式(disposition)
43
+
44
+ 每条流的处置方式都显式给出,由各消费方自行选择:原始管道用于协议分帧(LSP JSON-RPC、ACP ndjson),inherit 用于直通的诊断输出,收集模式用于有界的批量输出;其中 spill 文件是可选的,因此诊断尾部(语言服务器的 stderr)可以只在内存中缓冲,不留下任何文件。
45
+
46
+ ```ts type-equiv
47
+ /**
48
+ * stdin disposition. `'ignore'` leaves fd 0 on `/dev/null`; `'pipe'` exposes
49
+ * {@link SubprocessHandle.stdin} for the caller's ongoing protocol writes;
50
+ * `{ data }` writes the bytes and closes (the batch shape).
51
+ */
52
+ type SubprocessStdinMode = 'ignore' | 'pipe' | { readonly data: string }
53
+ ```
54
+
55
+ ```ts type-equiv
56
+ /**
57
+ * Bounded in-memory collection for one output stream, with an optional
58
+ * full-stream spill file. Omitting `spill` keeps only the in-memory tail —
59
+ * the diagnostic-tail shape (a language server's stderr); including it makes
60
+ * the complete stream recoverable up to its cap (the bash tool shape).
61
+ */
62
+ interface SubprocessCollect {
63
+ /** In-memory cap in bytes; overflow keeps the TAIL. */
64
+ maxBytes: number
65
+ /** Full-stream spill file; absent disables spilling entirely. */
66
+ spill?: {
67
+ /** Whole-stream byte cap; a larger stream discards its now-incomplete spill. */
68
+ maxBytes: number
69
+ }
70
+ }
71
+ ```
72
+
73
+ ```ts type-equiv
74
+ /**
75
+ * stdout/stderr disposition. `'pipe'` exposes the raw `Readable` for the
76
+ * caller's protocol decoding; `'inherit'` passes the parent's descriptor
77
+ * through (child diagnostics land on the harness's own stream); a
78
+ * {@link SubprocessCollect} object buffers boundedly with offset-based reads.
79
+ */
80
+ type SubprocessOutputMode = 'pipe' | 'inherit' | SubprocessCollect
81
+ ```
82
+
83
+ ```ts type-equiv
84
+ /** Per-stream stdio dispositions, all explicit — this seam applies no defaults. */
85
+ interface SubprocessStdio {
86
+ stdin: SubprocessStdinMode
87
+ stdout: SubprocessOutputMode
88
+ stderr: SubprocessOutputMode
89
+ }
90
+ ```
91
+
92
+ ## 完全显式的 spawn spec
93
+
94
+ 该 seam 不应用任何默认值:每项处置方式、限制与目录都在 spec 上显式给出,因此由调用方自己的配置决定它们,而不是由某个隐藏的子进程服务默认值决定。`argv` 绝不经过 shell 解释。
95
+
96
+ ```ts type-equiv
97
+ /**
98
+ * A fully-specified spawn request. This seam applies no defaults: every
99
+ * disposition, limit, and directory is explicit, so the caller's own config —
100
+ * not a hidden subprocess-service default — decides them (the `dsh-shell`
101
+ * request/spec split is the owning template).
102
+ */
103
+ interface SubprocessSpawnSpec {
104
+ /** Executable and arguments; `argv[0]` is the program. Never shell-interpreted here. */
105
+ argv: readonly string[]
106
+ /** Working directory for the child. */
107
+ cwd: string
108
+ /** Per-stream stdio dispositions. */
109
+ stdio: SubprocessStdio
110
+ /**
111
+ * Positive finite grace period in milliseconds, no greater than
112
+ * `MAX_TIMER_DELAY_MS`, for the {@link SubprocessHandle.terminate} escalation
113
+ * and for draining still-open collected pipes after the process exits (an
114
+ * inherited descriptor held by a surviving descendant cannot hold the
115
+ * outcome open indefinitely).
116
+ */
117
+ graceMs: number
118
+ /**
119
+ * Abort signal — starts the terminate escalation on the process tree when
120
+ * it fires. The caller owns deadlines and cause classification; this seam
121
+ * only reacts to the abort.
122
+ */
123
+ signal?: AbortSignal | undefined
124
+ /**
125
+ * Explicit environment entries merged onto the implementation's scrubbed
126
+ * parent base (see `scrubbedParentEnv`), with no namespace validation. A
127
+ * string is a deliberate caller opt-in, so a forwarded credential-shaped
128
+ * entry or current `DSH_*` fact survives the scrub; `undefined` is a
129
+ * tombstone that removes an ordinary ambient entry from the child.
130
+ */
131
+ env?: NodeJS.ProcessEnv | undefined
132
+ }
133
+ ```
134
+
135
+ ## 句柄:流、读取器与以进程树为范围的终止
136
+
137
+ spawn 会立即返回一个活动句柄。收集模式的读取器接受全流字节偏移量且从不消费,因此独立的读取器不会抢走彼此的增量;管道化的流归调用方所有。终止在每个平台上都以进程树为范围:`terminate()`(唯一的终止动词)执行 SIGTERM→宽限期→SIGKILL 升级,`waitForExit()` 观察整棵进程树。这足以让消费方构建自己的分级清理流程;ACP 后端的 `disposeAcpChild` 会先关闭 stdin,让子进程收到 EOF,是仓库内的参考实现。
138
+
139
+ ```ts type-equiv
140
+ /**
141
+ * A live child process rooted in its own process tree. Collected output
142
+ * remains readable after exit; piped streams belong to the caller.
143
+ *
144
+ * Termination is tree-scoped everywhere: POSIX signals the detached process
145
+ * group (falling back to the direct child when the group is gone), Windows
146
+ * terminates the tree via `taskkill /T`, so helper processes cannot outlive
147
+ * the handle unnoticed.
148
+ */
149
+ interface SubprocessHandle {
150
+ /** Process id (tree root); -1 when the spawn itself failed. */
151
+ readonly pid: number
152
+ /** The child's stdin, present iff spawned with `stdin: 'pipe'`. */
153
+ readonly stdin: Writable | undefined
154
+ /** The child's raw stdout, present iff spawned with `stdout: 'pipe'`. */
155
+ readonly stdout: Readable | undefined
156
+ /** The child's raw stderr, present iff spawned with `stderr: 'pipe'`. */
157
+ readonly stderr: Readable | undefined
158
+ /** Offset-based readers for collect-mode streams (also readable after exit). */
159
+ readonly collected: SubprocessCollectedOutputs
160
+ /** Resolves at process close with exit facts; rejects only for spawn-level failures. */
161
+ readonly done: Promise<SubprocessOutcome>
162
+ /**
163
+ * Begin the SIGTERM → `graceMs` → SIGKILL escalation on the process tree
164
+ * (Windows force-terminates immediately) — the seam's only termination
165
+ * verb. Idempotent, a no-op once the tree is gone (the pid may be reused),
166
+ * and also triggered by the spec's abort signal.
167
+ */
168
+ terminate(): void
169
+ /**
170
+ * Wait until the process tree has exited — the tree, not just the direct
171
+ * child, so a still-running helper is observable before teardown returns.
172
+ * @param signal - optional bound for the wait.
173
+ * @returns `true` when the tree exited, `false` when the signal aborted first.
174
+ */
175
+ waitForExit(signal?: AbortSignal): Promise<boolean>
176
+ }
177
+ ```
178
+
179
+ ```ts type-equiv
180
+ /**
181
+ * Cursor-free incremental access to one collected output stream. Offsets are
182
+ * whole-stream byte coordinates owned by the caller, so independent readers
183
+ * cannot consume one another's output; `readFrom(0)` after settlement is the
184
+ * batch result (`lossy` then means the in-memory tail lost its head — the
185
+ * {@link CollectedOutput.truncated} fact).
186
+ */
187
+ interface SubprocessOutputReader {
188
+ /**
189
+ * Read everything captured since `fromByte`. When that offset has slid out
190
+ * of the in-memory tail window the read is `lossy` — it returns the whole
191
+ * retained tail and the gap is only recoverable from the spill file.
192
+ * @param fromByte - whole-stream offset to resume from (a prior read's `nextOffset`; 0 for the first read).
193
+ * @returns the delta text, the next offset, the `lossy` flag, and the spill path when one exists.
194
+ */
195
+ readFrom(fromByte: number): SubprocessOutputRead
196
+ }
197
+ ```
198
+
199
+ ```ts type-equiv
200
+ /** One incremental {@link SubprocessOutputReader.readFrom} read. */
201
+ interface SubprocessOutputRead {
202
+ /** Stream text from the requested offset (the whole retained tail when lossy). */
203
+ text: string
204
+ /** Whole-stream offset to resume from on the next read. */
205
+ nextOffset: number
206
+ /** True when the requested offset slid out of the in-memory tail window. */
207
+ lossy: boolean
208
+ /** Path to the full-stream spill file, when one was created and remains intact. */
209
+ spillPath?: string
210
+ }
211
+ ```
212
+
213
+ ```ts type-equiv
214
+ /** Offset-based readers for the streams spawned in collect mode. */
215
+ interface SubprocessCollectedOutputs {
216
+ /** Present iff stdout is a {@link SubprocessCollect}. */
217
+ readonly stdout?: SubprocessOutputReader
218
+ /** Present iff stderr is a {@link SubprocessCollect}. */
219
+ readonly stderr?: SubprocessOutputReader
220
+ }
221
+ ```
222
+
223
+
224
+ ## 结果只承载退出事实
225
+
226
+ `done` 报告 Node close 事件的词汇,不携带原因分类:服务会在中止时终止进程,但绝不判定原因(调用方读取归自己所有的 deadline 信号,例如 bash 执行器的 `timedOut`/`aborted` 拆分)。收集到的输出在结算后仍可经 `handle.collected` 读取,因此批量与流式调用方共用一条访问路径。
227
+
228
+ ```ts type-equiv
229
+ /**
230
+ * Exit facts of one closed process — Node's `close`-event vocabulary.
231
+ * Deliberately carries NO timeout or cancellation classification (the caller
232
+ * reads the signal it owns to classify causes) and NO output: collected
233
+ * streams stay readable through {@link SubprocessHandle.collected} after
234
+ * settlement, so batch and streaming callers share one access path.
235
+ */
236
+ interface SubprocessOutcome {
237
+ /** Exit code; null when the process died from a signal. */
238
+ exitCode: number | null
239
+ /** Terminating signal (e.g. 'SIGTERM'); null on normal exit. */
240
+ signal: NodeJS.Signals | null
241
+ }
242
+ ```
243
+
244
+ ## 终端进程原语
245
+
246
+ `spawnTerminal(spec)` 是非管道进程原语。提供方分配控制终端,并负责 UTF-8 文本传输、前台进程组检查与信号发送,以及一项须等待的 TERM→KILL 操作;该操作会使提供方仍可观察到的每个会话成员完全停稳,提供方则会记录执行基底特有的可观察性限制。PTY 后端仍负责提示符检测、就绪推断、scrollback、沙箱策略和持久会话所有权;普通 `spawn()` 无法重建控制终端语义。
247
+
248
+ 终端 spec 完全指定 argv、cwd、环境覆盖、尺寸、清理宽限期与可选的分配取消。其句柄公开 `pid`、有序输出、`done`、`write`、`inspectForeground`、`signalForeground` 和须等待的 `terminate`;确切的公共形状生成到 [`ctx.subprocess` 服务目录](#ctxsubprocess--subprocessruntime-abstract-seam)中。
249
+
250
+ ## 服务行为
251
+
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) 以 detached 进程树、按处置方式接线、凭据清除、`node-pty`、平台进程检查,以及先终止再等待退出的资源释放提供这些能力。Service Definition 约定见 [`dsh-subprocess`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/subprocess/subprocess/README.md),本地机制见 [`dsh-subprocess-local`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/subprocess/subprocess-local/README.md)。
253
+
254
+ <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
255
+
256
+ <a id="cordis-surface"></a>
257
+
258
+ ## Cordis API
259
+
260
+ Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnpm run verify-cordis-catalog` in doc-sync; regenerate with `pnpm run gen-cordis-catalog`) — this section is byte-identical in both language sides of the page. Signature blocks use a `ts cordis-catalog` fence and keep the original source JSDoc; dispatch modes are defined in the [primer](../cordis-primer.md#dispatch-modes), and the framework-inherited `ctx` API lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
261
+
262
+ <a id="ctxe2b--e2bruntime"></a>
263
+
264
+ ### `ctx.e2b` — `E2BRuntime`
265
+
266
+ Creates one lazily consumable E2B SDK handle and deletes the sandbox at timeout or disposal. Creation begins at plugin construction; adapters await getSandbox before their first operation.
267
+
268
+ ```ts cordis-catalog
269
+ /**
270
+ * Return the shared live SDK handle.
271
+ * @returns the created sandbox after the configured cwd exists.
272
+ * @throws when E2B rejects creation or the service is disposing.
273
+ */
274
+ async getSandbox(): Promise<Sandbox>
275
+ ```
276
+
277
+ Source: [`packages/e2b/e2b/src/index.ts:74`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/e2b/e2b/src/index.ts)
278
+
279
+ <a id="ctxsubprocess--subprocessruntime-abstract-seam"></a>
280
+
281
+ ### `ctx.subprocess` — `SubprocessRuntime` (abstract seam)
282
+
283
+ Abstract subprocess service. Subclass, implement spawn, and load the subclass as a plugin — it registers as `ctx.subprocess` (one implementation per context; loading a second throws, which is cordis' standard duplicate-service behavior).
284
+
285
+ Implementations must honor these semantics:
286
+
287
+ - Executable paths belong to one execution world shared with the mounted filesystem provider.
288
+ - spawn returns immediately with a live handle; `done` resolves at process close with exit facts and rejects only for spawn-level failures.
289
+ - 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) escalates SIGTERM→grace→SIGKILL — the only termination verb — tree-scoped on every platform. SubprocessHandle.waitForExit observes whole-tree liveness, so a consumer-owned teardown ladder can hold each tier on real quiescence.
291
+ - Disposal of the service terminates all still-running managed processes and awaits their exit.
292
+ - 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
+
294
+ ```ts cordis-catalog
295
+ /**
296
+ * Resolve one configured executable in this provider's execution world.
297
+ * Absolute paths are verified; bare names use the provider's scrubbed PATH
298
+ * plus explicit environment overrides. Relative paths containing separators
299
+ * are rejected: the resolution base is undefined, so providers fail loud
300
+ * instead of guessing.
301
+ * @param command - absolute executable path or bare PATH name.
302
+ * @param env - explicit environment entries used for lookup.
303
+ * @param signal - aborts remote or local lookup.
304
+ * @returns a canonical executable path.
305
+ */
306
+ abstract resolveExecutable( command: string, env?: Readonly<Record<string, string>>, signal?: AbortSignal, ): Promise<string>
307
+
308
+ /**
309
+ * Start one managed child process from a fully-specified spec; this seam
310
+ * applies no defaults.
311
+ * @param spec - argv, directory, stdio dispositions, grace, cancellation, and environment.
312
+ * @returns the live process handle (streams/readers, signalling, outcome promise).
313
+ */
314
+ abstract spawn(spec: SubprocessSpawnSpec): SubprocessHandle
315
+
316
+ /**
317
+ * Allocate a real terminal and start one owned process session. This is the
318
+ * only non-pipe process primitive: implementations own terminal byte I/O,
319
+ * foreground groups, signals, and complete session-tree cleanup.
320
+ * @param spec - fully specified argv, cwd, environment, dimensions, grace, and allocation cancellation.
321
+ * @returns the live terminal handle after allocation succeeds.
322
+ */
323
+ abstract spawnTerminal(spec: SubprocessTerminalSpawnSpec): Promise<SubprocessTerminalHandle>
324
+ ```
325
+
326
+ Source: [`packages/subprocess/subprocess/src/index.ts:102`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/subprocess/subprocess/src/index.ts)
327
+ <!-- END GENERATED cordis-surface -->
@@ -0,0 +1,210 @@
1
+ ---
2
+ editSource: "docs/subsystems/system-prompt.zh.md"
3
+ outline: [2,3]
4
+ ---
5
+
6
+ # 系统提示词组装
7
+
8
+ [system-prompt 包](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/core/system-prompt)负责管理提示词贡献者与一次组装调用之间交换的数据。该包的 [README](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/system-prompt/README.md) 记录注册、排序、作用域与渲染行为;本页记录各插件实现或传递的确切跨包类型。
9
+
10
+ 源码:[`packages/core/system-prompt/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/system-prompt/src/index.ts)。
11
+
12
+ ## 组装上下文
13
+
14
+ `AssembleContext` 标识一次组装所解析的作用域层,并可携带该请求的显式控制信号。它可合并扩展:`dsh-agent` 添加可选字段 `agent`,用于携带当前的 agent(智能体)实例;`assembleContextFor(agent, signal)` 则一起设置这些显式字段。裸组装既没有作用域,也没有信号。
15
+
16
+ ```ts type-equiv
17
+ /** Merge-extensible context for one prompt assembly. */
18
+ interface AssembleContext {
19
+ /**
20
+ * Scope whose providers and waterfall listeners participate. When absent,
21
+ * only global providers and subject-less listeners participate.
22
+ */
23
+ scope?: ScopeKey
24
+ /** Explicit control signal for the turn that requested this assembly, when any. */
25
+ signal?: AbortSignal
26
+ }
27
+ ```
28
+
29
+ ## 工具提供方结果
30
+
31
+ `ToolProviderResult.schemas` 是当前组装中对模型可见的工具 schema 集合。`knownNames` 是提供方在限制前的名称全集,用于区分「配置名拼写错误」与「已知工具在此作用域中被有意隐藏」。
32
+
33
+ ```ts type-equiv
34
+ /** Tool schemas visible in one assembly and their pre-restriction name set. */
35
+ interface ToolProviderResult {
36
+ /** The schemas this provider contributes to THIS assembly. */
37
+ readonly schemas: readonly ToolSchema[]
38
+ /** The pre-restriction name universe for config validation (defaults to `schemas`' names). */
39
+ readonly knownNames?: readonly string[]
40
+ }
41
+ ```
42
+
43
+ ## 提示词段落
44
+
45
+ `PromptSection` 是一份只读的同进程注册约定。其文本可以是静态的,也可以从当前组装上下文动态解析。协作式组装完成后,一个有效的 `complete` 段会成为唯一的提示词段落。
46
+
47
+ ```ts type-equiv
48
+ /** One contributed section of the system prompt (registry input). */
49
+ interface PromptSection {
50
+ /** Unique name — a duplicate registration throws (see {@link SystemPrompt.section}). */
51
+ readonly name: string
52
+ /**
53
+ * Sections are concatenated in ascending order. Convention: `-100` is the
54
+ * harness identity, `0` the deployment persona, tool guidance uses 100–199;
55
+ * other negative orders also render before the persona.
56
+ */
57
+ readonly order: number
58
+ /**
59
+ * Static text or a provider evaluated at each assembly with that assembly's
60
+ * {@link AssembleContext}. The text may reference `{{variable}}`s — they are
61
+ * interpolated later, by {@link renderPrompt}.
62
+ */
63
+ readonly text: string | ((context: AssembleContext) => string)
64
+ /**
65
+ * Treat this contribution as the complete system prompt. Assembly still
66
+ * runs the cooperative waterfall so tools, contexts, and variables can be
67
+ * resolved, then restores this exact section as the sole prompt section.
68
+ * More than one effective complete section makes assembly fail.
69
+ */
70
+ readonly complete?: boolean
71
+ }
72
+ ```
73
+
74
+ ## 动态提示词上下文
75
+
76
+ `PromptContext` 是与 `PromptSection` 对应的缓存安全结构。组装会解析这些贡献并排序;agent loop(智能体循环)仅在完整当前快照发生变化或被压缩(compaction)移除时,才会将其记录在保留的模型历史之后。
77
+
78
+ ```ts type-equiv
79
+ /** Dynamic model context materialized as a durable user-role snapshot. */
80
+ interface PromptContext {
81
+ /** Unique name — a duplicate registration throws (see {@link SystemPrompt.context}). */
82
+ readonly name: string
83
+ /** Contexts are joined in ascending order. */
84
+ readonly order: number
85
+ /** Static text or a provider evaluated for each assembly. Empty text contributes nothing. */
86
+ readonly text: string | ((context: AssembleContext) => string)
87
+ }
88
+ ```
89
+
90
+ <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
91
+
92
+ <a id="cordis-surface"></a>
93
+
94
+ ## Cordis API
95
+
96
+ Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnpm run verify-cordis-catalog` in doc-sync; regenerate with `pnpm run gen-cordis-catalog`) — this section is byte-identical in both language sides of the page. Signature blocks use a `ts cordis-catalog` fence and keep the original source JSDoc; dispatch modes are defined in the [primer](../cordis-primer.md#dispatch-modes), and the framework-inherited `ctx` API lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
97
+
98
+ <a id="ctxsystemprompt--systemprompt"></a>
99
+
100
+ ### `ctx.systemPrompt` — `SystemPrompt`
101
+
102
+ Registry service for the prompt inputs assembled before each model step.
103
+
104
+ ```ts cordis-catalog
105
+ /**
106
+ * Register an ordered prompt section in the calling context's scope. A scoped
107
+ * section shadows a global section with the same name; duplicates within one
108
+ * layer and non-finite orders throw. Registration and disposal emit
109
+ * `system-prompt/change`.
110
+ * @param section - the section to register.
111
+ * @returns the exact Cordis effect disposer.
112
+ */
113
+ section(section: PromptSection): () => void
114
+
115
+ /**
116
+ * Register ordered dynamic context in the calling context's scope. Scoped
117
+ * entries shadow global entries with the same name.
118
+ * @param context - the context contribution to register.
119
+ * @returns the exact Cordis effect disposer.
120
+ */
121
+ context(context: PromptContext): () => void
122
+
123
+ /**
124
+ * Suppress every dynamic runtime-context contribution in the calling
125
+ * context's scope without changing the services that own or enforce those
126
+ * facts. Multiple suppressors remain independently disposable.
127
+ * @returns the exact Cordis effect disposer.
128
+ */
129
+ suppressRuntimeContext(): () => void
130
+
131
+ /**
132
+ * Register a tool-schema provider in the calling context's scope. Global and
133
+ * matching scoped providers both contribute; returning the reserved
134
+ * {@link TOOL_ORDER_REST} name makes assembly fail.
135
+ * @param provider - evaluated for each assembly with its context.
136
+ * @returns the exact Cordis effect disposer.
137
+ */
138
+ tools(provider: (context: AssembleContext) => ToolProviderResult): () => void
139
+
140
+ /**
141
+ * Register a prompt variable in the calling context's scope. Scoped values
142
+ * shadow globals; invalid or duplicate names throw. A provider may return
143
+ * `undefined`, but rendering a section that references that value then fails.
144
+ * @param name - the `[a-z][a-z0-9_]*` reference name.
145
+ * @param provider - evaluated for each assembly.
146
+ * @returns the exact Cordis effect disposer.
147
+ */
148
+ variable(name: string, provider: (context: AssembleContext) => string | undefined): () => void
149
+
150
+ /**
151
+ * Assemble global and scoped providers, detach tool parameters, apply
152
+ * canonical ordering, then run the assembly waterfall. Scoped sections and
153
+ * variables shadow globals. The returned waterfall value is authoritative
154
+ * except that an effective complete section is restored afterwards as the
155
+ * sole prompt section.
156
+ * @param context - the optional scope and plugin-defined assembly fields.
157
+ * @returns the post-waterfall assembly with any complete prompt enforced.
158
+ */
159
+ async assemble(context: AssembleContext = {}): Promise<PromptAssembly>
160
+ ```
161
+
162
+ Source: [`packages/core/system-prompt/src/index.ts:338`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/system-prompt/src/index.ts)
163
+
164
+ <a id="system-prompt-events"></a>
165
+
166
+ ### `system-prompt/*` events
167
+
168
+ <a id="system-promptassemble--waterfall"></a>
169
+
170
+ #### `system-prompt/assemble` — waterfall
171
+
172
+ Expert waterfall over the assembled sections, contexts, tools, and variables. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): scoped listeners receive only that scope's assemblies. The returned value is authoritative. A supplied signal controls only this explicit assembly request and must not be retained to control later turns. A registered complete section is restored after this waterfall, so listeners cannot add to or replace that scope's system prompt.
173
+
174
+ ```ts cordis-catalog
175
+ /**
176
+ * Expert waterfall over the assembled sections, contexts, tools, and variables.
177
+ * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): scoped listeners
178
+ * receive only that scope's assemblies. The returned value is authoritative.
179
+ * A supplied signal controls only this explicit assembly request and must not
180
+ * be retained to control later turns. A registered complete section is
181
+ * restored after this waterfall, so listeners cannot add to or replace
182
+ * that scope's system prompt.
183
+ * @param assembly - the mutable assembly built from registered providers.
184
+ * @param context - the caller's per-assembly context.
185
+ * @mode waterfall
186
+ */
187
+ 'system-prompt/assemble'(this: Scoped<SystemPrompt>, assembly: PromptAssembly, context: AssembleContext, next: () => Promise<PromptAssembly>): Promise<PromptAssembly>
188
+ ```
189
+
190
+ Types: [Scoped](./scope.md)
191
+
192
+ Source: [`packages/core/system-prompt/src/index.ts:31`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/system-prompt/src/index.ts)
193
+
194
+ <a id="system-promptchange--emit"></a>
195
+
196
+ #### `system-prompt/change` — emit
197
+
198
+ Emitted when any prompt provider changes. This registry notification is unfiltered because a global change affects every scope.
199
+
200
+ ```ts cordis-catalog
201
+ /**
202
+ * Emitted when any prompt provider changes. This registry notification is
203
+ * unfiltered because a global change affects every scope.
204
+ * @mode emit
205
+ */
206
+ 'system-prompt/change'(): void
207
+ ```
208
+
209
+ Source: [`packages/core/system-prompt/src/index.ts:37`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/system-prompt/src/index.ts)
210
+ <!-- END GENERATED cordis-surface -->