dsh-plugin-guide 0.2.0 → 0.3.2

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 (373) hide show
  1. package/README.es.md +36 -18
  2. package/README.hi.md +36 -18
  3. package/README.md +38 -18
  4. package/README.pt.md +36 -18
  5. package/README.zh.md +38 -18
  6. package/SKILL.md +1 -1
  7. package/dist/dsh-plugin-dev.js +5 -5
  8. package/guide/links.md +1 -1
  9. package/guide/plugin-dev-guide.md +1 -1
  10. package/guide/quick-reference.es.md +2 -2
  11. package/guide/quick-reference.hi.md +2 -2
  12. package/guide/quick-reference.md +2 -2
  13. package/guide/quick-reference.pt.md +2 -2
  14. package/guide/quick-reference.zh-CN.md +3 -3
  15. package/package.json +13 -4
  16. package/references/cordis-paper-and-community.md +1 -1
  17. package/references/harness-repo.md +1 -1
  18. package/references/official-docs/AGENTS.md +27 -22
  19. package/references/official-docs/README.i18n.yaml +2 -2
  20. package/references/official-docs/README.md +1 -1
  21. package/references/official-docs/README.zh.md +19 -9
  22. package/references/official-docs/SNAPSHOT.md +5 -5
  23. package/references/official-docs/THIRD_PARTY_NOTICES.md +36 -13
  24. package/references/official-docs/docs/AGENTS.md +4 -4
  25. package/references/official-docs/docs/agent-lifecycle.i18n.yaml +2 -2
  26. package/references/official-docs/docs/agent-lifecycle.md +1 -1
  27. package/references/official-docs/docs/agent-lifecycle.zh.md +2 -2
  28. package/references/official-docs/docs/api-gateway.i18n.yaml +2 -2
  29. package/references/official-docs/docs/api-gateway.md +8 -8
  30. package/references/official-docs/docs/api-gateway.zh.md +8 -8
  31. package/references/official-docs/docs/architecture.i18n.yaml +2 -2
  32. package/references/official-docs/docs/architecture.md +23 -7
  33. package/references/official-docs/docs/architecture.zh.md +36 -20
  34. package/references/official-docs/docs/capability-seams.i18n.yaml +2 -2
  35. package/references/official-docs/docs/capability-seams.md +132 -67
  36. package/references/official-docs/docs/capability-seams.zh.md +132 -67
  37. package/references/official-docs/docs/config-catalog.i18n.yaml +2 -2
  38. package/references/official-docs/docs/config-catalog.md +659 -373
  39. package/references/official-docs/docs/config-catalog.zh.md +677 -391
  40. package/references/official-docs/docs/cookbook/adding-a-package.i18n.yaml +2 -2
  41. package/references/official-docs/docs/cookbook/adding-a-package.md +2 -3
  42. package/references/official-docs/docs/cookbook/adding-a-package.zh.md +8 -7
  43. package/references/official-docs/docs/cookbook/{adding-a-conversation-node.i18n.yaml → adding-a-remote-api.i18n.yaml} +3 -3
  44. package/references/official-docs/docs/cookbook/adding-a-remote-api.md +197 -0
  45. package/references/official-docs/docs/cookbook/adding-a-remote-api.zh.md +197 -0
  46. package/references/official-docs/docs/cookbook/adding-a-settings-card.i18n.yaml +6 -0
  47. package/references/official-docs/docs/cookbook/adding-a-settings-card.md +102 -0
  48. package/references/official-docs/docs/cookbook/adding-a-settings-card.zh.md +102 -0
  49. package/references/official-docs/docs/cookbook/adding-a-tool.i18n.yaml +2 -2
  50. package/references/official-docs/docs/cookbook/adding-a-tool.md +11 -4
  51. package/references/official-docs/docs/cookbook/adding-a-tool.zh.md +16 -9
  52. package/references/official-docs/docs/cookbook/adding-a-vendored-package.i18n.yaml +2 -2
  53. package/references/official-docs/docs/cookbook/adding-a-vendored-package.md +2 -2
  54. package/references/official-docs/docs/cookbook/adding-a-vendored-package.zh.md +4 -4
  55. package/references/official-docs/docs/cookbook/adding-an-llm-adapter.i18n.yaml +2 -2
  56. package/references/official-docs/docs/cookbook/adding-an-llm-adapter.md +1 -1
  57. package/references/official-docs/docs/cookbook/adding-an-llm-adapter.zh.md +3 -3
  58. package/references/official-docs/docs/cookbook/extension-cookbook.i18n.yaml +2 -2
  59. package/references/official-docs/docs/cookbook/extension-cookbook.md +9 -8
  60. package/references/official-docs/docs/cookbook/extension-cookbook.zh.md +17 -14
  61. package/references/official-docs/docs/cookbook/maintaining-dsh-code-review.i18n.yaml +1 -1
  62. package/references/official-docs/docs/cookbook/maintaining-dsh-code-review.zh.md +1 -1
  63. package/references/official-docs/docs/cookbook/responding-to-pr-review-on-a-stack.i18n.yaml +1 -1
  64. package/references/official-docs/docs/cookbook/responding-to-pr-review-on-a-stack.zh.md +1 -1
  65. package/references/official-docs/docs/cordis-api/context.i18n.yaml +1 -1
  66. package/references/official-docs/docs/cordis-api/context.zh.md +1 -1
  67. package/references/official-docs/docs/cordis-api/events.i18n.yaml +1 -1
  68. package/references/official-docs/docs/cordis-api/events.zh.md +1 -1
  69. package/references/official-docs/docs/cordis-api/inherited.md +1 -1
  70. package/references/official-docs/docs/cordis-primer.i18n.yaml +2 -2
  71. package/references/official-docs/docs/cordis-primer.md +2 -1
  72. package/references/official-docs/docs/cordis-primer.zh.md +3 -2
  73. package/references/official-docs/docs/cordis-tutorial/01-first-plugin.i18n.yaml +1 -1
  74. package/references/official-docs/docs/cordis-tutorial/01-first-plugin.zh.md +4 -4
  75. package/references/official-docs/docs/cordis-tutorial/02-lifecycle-and-effects.i18n.yaml +1 -1
  76. package/references/official-docs/docs/cordis-tutorial/02-lifecycle-and-effects.zh.md +4 -4
  77. package/references/official-docs/docs/cordis-tutorial/03-services.i18n.yaml +1 -1
  78. package/references/official-docs/docs/cordis-tutorial/03-services.zh.md +4 -4
  79. package/references/official-docs/docs/cordis-tutorial/04-events.i18n.yaml +1 -1
  80. package/references/official-docs/docs/cordis-tutorial/04-events.zh.md +4 -4
  81. package/references/official-docs/docs/cordis-tutorial/05-config.i18n.yaml +1 -1
  82. package/references/official-docs/docs/cordis-tutorial/05-config.zh.md +2 -2
  83. package/references/official-docs/docs/cordis-tutorial/06-composition-and-hmr.i18n.yaml +1 -1
  84. package/references/official-docs/docs/cordis-tutorial/06-composition-and-hmr.zh.md +3 -3
  85. package/references/official-docs/docs/cordis-tutorial/07-into-the-harness.i18n.yaml +2 -2
  86. package/references/official-docs/docs/cordis-tutorial/07-into-the-harness.md +5 -4
  87. package/references/official-docs/docs/cordis-tutorial/07-into-the-harness.zh.md +11 -10
  88. package/references/official-docs/docs/cordis-tutorial/index.i18n.yaml +1 -1
  89. package/references/official-docs/docs/cordis-tutorial/index.zh.md +10 -10
  90. package/references/official-docs/docs/deepseek-llm-api-wire-extensions.i18n.yaml +6 -0
  91. package/references/official-docs/docs/deepseek-llm-api-wire-extensions.md +159 -0
  92. package/references/official-docs/docs/deepseek-llm-api-wire-extensions.zh.md +159 -0
  93. package/references/official-docs/docs/defensive-patterns.i18n.yaml +1 -1
  94. package/references/official-docs/docs/defensive-patterns.zh.md +3 -1
  95. package/references/official-docs/docs/development.i18n.yaml +2 -2
  96. package/references/official-docs/docs/development.md +9 -13
  97. package/references/official-docs/docs/development.zh.md +23 -21
  98. package/references/official-docs/docs/event-producer-consumer.i18n.yaml +2 -2
  99. package/references/official-docs/docs/event-producer-consumer.md +55 -46
  100. package/references/official-docs/docs/event-producer-consumer.zh.md +55 -46
  101. package/references/official-docs/docs/glossary.i18n.yaml +2 -2
  102. package/references/official-docs/docs/glossary.md +1 -1
  103. package/references/official-docs/docs/glossary.zh.md +1 -1
  104. package/references/official-docs/docs/graph-atlas.i18n.yaml +2 -2
  105. package/references/official-docs/docs/graph-atlas.md +0 -2
  106. package/references/official-docs/docs/graph-atlas.zh.md +7 -9
  107. package/references/official-docs/docs/i18n/README.i18n.yaml +2 -2
  108. package/references/official-docs/docs/i18n/README.md +7 -7
  109. package/references/official-docs/docs/i18n/README.zh.md +11 -9
  110. package/references/official-docs/docs/i18n/style-samples.md +3 -3
  111. package/references/official-docs/docs/i18n/translation-prompt.md +3 -3
  112. package/references/official-docs/docs/i18n/translation-rules.i18n.yaml +2 -2
  113. package/references/official-docs/docs/i18n/translation-rules.md +2 -2
  114. package/references/official-docs/docs/i18n/translation-rules.zh.md +3 -3
  115. package/references/official-docs/docs/module-graph.i18n.yaml +2 -2
  116. package/references/official-docs/docs/module-graph.md +666 -747
  117. package/references/official-docs/docs/module-graph.zh.md +668 -749
  118. package/references/official-docs/docs/persistence-catalog.i18n.yaml +2 -2
  119. package/references/official-docs/docs/persistence-catalog.md +160 -39
  120. package/references/official-docs/docs/persistence-catalog.zh.md +169 -48
  121. package/references/official-docs/docs/postmortem/0001-acp-default-export-drops-inject.i18n.yaml +2 -2
  122. package/references/official-docs/docs/postmortem/0001-acp-default-export-drops-inject.md +2 -2
  123. package/references/official-docs/docs/postmortem/0001-acp-default-export-drops-inject.zh.md +3 -3
  124. package/references/official-docs/docs/postmortem/0002-js-expression-disabled-filesystem-tools.i18n.yaml +2 -2
  125. package/references/official-docs/docs/postmortem/0002-js-expression-disabled-filesystem-tools.md +2 -2
  126. package/references/official-docs/docs/postmortem/0002-js-expression-disabled-filesystem-tools.zh.md +2 -2
  127. package/references/official-docs/docs/postmortem/0003-web-agent-gui-feedback-loop.i18n.yaml +2 -2
  128. package/references/official-docs/docs/postmortem/0003-web-agent-gui-feedback-loop.md +2 -2
  129. package/references/official-docs/docs/postmortem/0003-web-agent-gui-feedback-loop.zh.md +2 -2
  130. package/references/official-docs/docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.i18n.yaml +2 -2
  131. package/references/official-docs/docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.md +1 -1
  132. package/references/official-docs/docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.zh.md +2 -2
  133. package/references/official-docs/docs/postmortem/README.i18n.yaml +1 -1
  134. package/references/official-docs/docs/postmortem/README.zh.md +5 -5
  135. package/references/official-docs/docs/rescope.i18n.yaml +2 -2
  136. package/references/official-docs/docs/rescope.md +2 -2
  137. package/references/official-docs/docs/rescope.zh.md +3 -3
  138. package/references/official-docs/docs/subsystems/README.i18n.yaml +2 -2
  139. package/references/official-docs/docs/subsystems/README.md +8 -2
  140. package/references/official-docs/docs/subsystems/README.zh.md +53 -47
  141. package/references/official-docs/docs/subsystems/agent-team.i18n.yaml +6 -0
  142. package/references/official-docs/docs/subsystems/agent-team.md +206 -0
  143. package/references/official-docs/docs/subsystems/agent-team.zh.md +206 -0
  144. package/references/official-docs/docs/subsystems/approval.i18n.yaml +2 -2
  145. package/references/official-docs/docs/subsystems/approval.md +12 -12
  146. package/references/official-docs/docs/subsystems/approval.zh.md +13 -13
  147. package/references/official-docs/docs/subsystems/attachment.i18n.yaml +2 -2
  148. package/references/official-docs/docs/subsystems/attachment.md +90 -7
  149. package/references/official-docs/docs/subsystems/attachment.zh.md +90 -7
  150. package/references/official-docs/docs/subsystems/client-modules.i18n.yaml +2 -2
  151. package/references/official-docs/docs/subsystems/client-modules.md +69 -19
  152. package/references/official-docs/docs/subsystems/client-modules.zh.md +69 -19
  153. package/references/official-docs/docs/subsystems/code-runtime.i18n.yaml +2 -2
  154. package/references/official-docs/docs/subsystems/code-runtime.md +5 -5
  155. package/references/official-docs/docs/subsystems/code-runtime.zh.md +6 -6
  156. package/references/official-docs/docs/subsystems/commands.i18n.yaml +2 -2
  157. package/references/official-docs/docs/subsystems/commands.md +29 -6
  158. package/references/official-docs/docs/subsystems/commands.zh.md +30 -7
  159. package/references/official-docs/docs/subsystems/compaction.i18n.yaml +2 -2
  160. package/references/official-docs/docs/subsystems/compaction.md +5 -5
  161. package/references/official-docs/docs/subsystems/compaction.zh.md +11 -11
  162. package/references/official-docs/docs/subsystems/conversation.i18n.yaml +6 -0
  163. package/references/official-docs/docs/{cookbook/adding-a-conversation-node.md → subsystems/conversation.md} +49 -24
  164. package/references/official-docs/docs/{cookbook/adding-a-conversation-node.zh.md → subsystems/conversation.zh.md} +49 -24
  165. package/references/official-docs/docs/subsystems/core.i18n.yaml +2 -2
  166. package/references/official-docs/docs/subsystems/core.md +110 -33
  167. package/references/official-docs/docs/subsystems/core.zh.md +141 -62
  168. package/references/official-docs/docs/subsystems/credentials.i18n.yaml +2 -2
  169. package/references/official-docs/docs/subsystems/credentials.md +207 -11
  170. package/references/official-docs/docs/subsystems/credentials.zh.md +207 -11
  171. package/references/official-docs/docs/subsystems/extensions.i18n.yaml +2 -2
  172. package/references/official-docs/docs/subsystems/extensions.md +27 -9
  173. package/references/official-docs/docs/subsystems/extensions.zh.md +30 -12
  174. package/references/official-docs/docs/subsystems/feedback.i18n.yaml +2 -2
  175. package/references/official-docs/docs/subsystems/feedback.md +4 -4
  176. package/references/official-docs/docs/subsystems/feedback.zh.md +4 -4
  177. package/references/official-docs/docs/subsystems/filesystem.i18n.yaml +2 -2
  178. package/references/official-docs/docs/subsystems/filesystem.md +17 -7
  179. package/references/official-docs/docs/subsystems/filesystem.zh.md +19 -9
  180. package/references/official-docs/docs/subsystems/goal.i18n.yaml +2 -2
  181. package/references/official-docs/docs/subsystems/goal.md +4 -4
  182. package/references/official-docs/docs/subsystems/goal.zh.md +8 -8
  183. package/references/official-docs/docs/subsystems/invariants.i18n.yaml +2 -2
  184. package/references/official-docs/docs/subsystems/invariants.md +2 -2
  185. package/references/official-docs/docs/subsystems/invariants.zh.md +5 -5
  186. package/references/official-docs/docs/subsystems/jobs.i18n.yaml +2 -2
  187. package/references/official-docs/docs/subsystems/jobs.md +3 -3
  188. package/references/official-docs/docs/subsystems/jobs.zh.md +6 -6
  189. package/references/official-docs/docs/subsystems/llm-streaming.i18n.yaml +2 -2
  190. package/references/official-docs/docs/subsystems/llm-streaming.md +193 -22
  191. package/references/official-docs/docs/subsystems/llm-streaming.zh.md +199 -28
  192. package/references/official-docs/docs/subsystems/lsp.i18n.yaml +2 -2
  193. package/references/official-docs/docs/subsystems/lsp.md +2 -2
  194. package/references/official-docs/docs/subsystems/lsp.zh.md +3 -3
  195. package/references/official-docs/docs/subsystems/permission-presets.i18n.yaml +2 -2
  196. package/references/official-docs/docs/subsystems/permission-presets.md +8 -8
  197. package/references/official-docs/docs/subsystems/permission-presets.zh.md +8 -8
  198. package/references/official-docs/docs/subsystems/persistence.i18n.yaml +2 -2
  199. package/references/official-docs/docs/subsystems/persistence.md +35 -17
  200. package/references/official-docs/docs/subsystems/persistence.zh.md +38 -20
  201. package/references/official-docs/docs/subsystems/plan.i18n.yaml +2 -2
  202. package/references/official-docs/docs/subsystems/plan.md +4 -4
  203. package/references/official-docs/docs/subsystems/plan.zh.md +10 -10
  204. package/references/official-docs/docs/subsystems/sandbox.i18n.yaml +2 -2
  205. package/references/official-docs/docs/subsystems/sandbox.md +5 -3
  206. package/references/official-docs/docs/subsystems/sandbox.zh.md +8 -6
  207. package/references/official-docs/docs/subsystems/schedule.i18n.yaml +2 -2
  208. package/references/official-docs/docs/subsystems/schedule.md +9 -3
  209. package/references/official-docs/docs/subsystems/schedule.zh.md +11 -5
  210. package/references/official-docs/docs/subsystems/scope.i18n.yaml +1 -1
  211. package/references/official-docs/docs/subsystems/scope.zh.md +1 -1
  212. package/references/official-docs/docs/subsystems/session-projection.i18n.yaml +2 -2
  213. package/references/official-docs/docs/subsystems/session-projection.md +136 -67
  214. package/references/official-docs/docs/subsystems/session-projection.zh.md +136 -67
  215. package/references/official-docs/docs/subsystems/session-query.i18n.yaml +2 -2
  216. package/references/official-docs/docs/subsystems/session-query.md +11 -3
  217. package/references/official-docs/docs/subsystems/session-query.zh.md +12 -4
  218. package/references/official-docs/docs/subsystems/session-reference.i18n.yaml +2 -2
  219. package/references/official-docs/docs/subsystems/session-reference.md +94 -7
  220. package/references/official-docs/docs/subsystems/session-reference.zh.md +95 -8
  221. package/references/official-docs/docs/subsystems/session-telemetry.i18n.yaml +2 -2
  222. package/references/official-docs/docs/subsystems/session-telemetry.md +5 -6
  223. package/references/official-docs/docs/subsystems/session-telemetry.zh.md +9 -10
  224. package/references/official-docs/docs/subsystems/session-title.i18n.yaml +2 -2
  225. package/references/official-docs/docs/subsystems/session-title.md +3 -3
  226. package/references/official-docs/docs/subsystems/session-title.zh.md +5 -5
  227. package/references/official-docs/docs/subsystems/session.i18n.yaml +2 -2
  228. package/references/official-docs/docs/subsystems/session.md +273 -39
  229. package/references/official-docs/docs/subsystems/session.zh.md +290 -54
  230. package/references/official-docs/docs/subsystems/settings.i18n.yaml +2 -2
  231. package/references/official-docs/docs/subsystems/settings.md +105 -10
  232. package/references/official-docs/docs/subsystems/settings.zh.md +105 -10
  233. package/references/official-docs/docs/subsystems/shell.i18n.yaml +2 -2
  234. package/references/official-docs/docs/subsystems/shell.md +3 -3
  235. package/references/official-docs/docs/subsystems/shell.zh.md +11 -11
  236. package/references/official-docs/docs/subsystems/skills.i18n.yaml +2 -2
  237. package/references/official-docs/docs/subsystems/skills.md +26 -3
  238. package/references/official-docs/docs/subsystems/skills.zh.md +29 -6
  239. package/references/official-docs/docs/subsystems/slots.i18n.yaml +6 -0
  240. package/references/official-docs/docs/subsystems/slots.md +174 -0
  241. package/references/official-docs/docs/subsystems/slots.zh.md +174 -0
  242. package/references/official-docs/docs/subsystems/spill.i18n.yaml +2 -2
  243. package/references/official-docs/docs/subsystems/spill.md +4 -4
  244. package/references/official-docs/docs/subsystems/spill.zh.md +6 -6
  245. package/references/official-docs/docs/subsystems/storage.i18n.yaml +2 -2
  246. package/references/official-docs/docs/subsystems/storage.md +13 -5
  247. package/references/official-docs/docs/subsystems/storage.zh.md +16 -8
  248. package/references/official-docs/docs/subsystems/subagent.i18n.yaml +2 -2
  249. package/references/official-docs/docs/subsystems/subagent.md +120 -32
  250. package/references/official-docs/docs/subsystems/subagent.zh.md +131 -41
  251. package/references/official-docs/docs/subsystems/subprocess.i18n.yaml +2 -2
  252. package/references/official-docs/docs/subsystems/subprocess.md +3 -3
  253. package/references/official-docs/docs/subsystems/subprocess.zh.md +5 -5
  254. package/references/official-docs/docs/subsystems/system-prompt.i18n.yaml +2 -2
  255. package/references/official-docs/docs/subsystems/system-prompt.md +21 -8
  256. package/references/official-docs/docs/subsystems/system-prompt.zh.md +23 -10
  257. package/references/official-docs/docs/subsystems/terminal.i18n.yaml +2 -2
  258. package/references/official-docs/docs/subsystems/terminal.md +2 -2
  259. package/references/official-docs/docs/subsystems/terminal.zh.md +4 -4
  260. package/references/official-docs/docs/subsystems/todo.i18n.yaml +6 -0
  261. package/references/official-docs/docs/subsystems/todo.md +32 -0
  262. package/references/official-docs/docs/subsystems/todo.zh.md +32 -0
  263. package/references/official-docs/docs/subsystems/token-meter.i18n.yaml +2 -2
  264. package/references/official-docs/docs/subsystems/token-meter.md +27 -12
  265. package/references/official-docs/docs/subsystems/token-meter.zh.md +28 -13
  266. package/references/official-docs/docs/subsystems/tools.i18n.yaml +2 -2
  267. package/references/official-docs/docs/subsystems/tools.md +46 -46
  268. package/references/official-docs/docs/subsystems/tools.zh.md +54 -54
  269. package/references/official-docs/docs/subsystems/typert.i18n.yaml +2 -2
  270. package/references/official-docs/docs/subsystems/typert.md +65 -58
  271. package/references/official-docs/docs/subsystems/typert.zh.md +67 -60
  272. package/references/official-docs/docs/subsystems/user-questions.i18n.yaml +2 -2
  273. package/references/official-docs/docs/subsystems/user-questions.md +35 -35
  274. package/references/official-docs/docs/subsystems/user-questions.zh.md +35 -35
  275. package/references/official-docs/docs/subsystems/web-client.i18n.yaml +6 -0
  276. package/references/official-docs/docs/subsystems/web-client.md +95 -0
  277. package/references/official-docs/docs/subsystems/web-client.zh.md +95 -0
  278. package/references/official-docs/docs/subsystems/web-server.i18n.yaml +2 -2
  279. package/references/official-docs/docs/subsystems/web-server.md +55 -9
  280. package/references/official-docs/docs/subsystems/web-server.zh.md +56 -10
  281. package/references/official-docs/docs/subsystems/web.i18n.yaml +2 -2
  282. package/references/official-docs/docs/subsystems/web.md +14 -7
  283. package/references/official-docs/docs/subsystems/web.zh.md +16 -9
  284. package/references/official-docs/docs/subsystems/webhook.i18n.yaml +6 -0
  285. package/references/official-docs/docs/subsystems/webhook.md +70 -0
  286. package/references/official-docs/docs/subsystems/webhook.zh.md +70 -0
  287. package/references/official-docs/docs/subsystems/workflow.i18n.yaml +2 -2
  288. package/references/official-docs/docs/subsystems/workflow.md +8 -8
  289. package/references/official-docs/docs/subsystems/workflow.zh.md +13 -13
  290. package/references/official-docs/docs/subsystems/workspace.i18n.yaml +2 -2
  291. package/references/official-docs/docs/subsystems/workspace.md +98 -5
  292. package/references/official-docs/docs/subsystems/workspace.zh.md +102 -9
  293. package/references/official-docs/docs/testing.i18n.yaml +2 -2
  294. package/references/official-docs/docs/testing.md +15 -10
  295. package/references/official-docs/docs/testing.zh.md +15 -10
  296. package/references/official-docs/docs/tool-catalog.i18n.yaml +2 -2
  297. package/references/official-docs/docs/tool-catalog.md +433 -27
  298. package/references/official-docs/docs/tool-catalog.zh.md +438 -29
  299. package/references/official-docs/docs/tool-execution-pipeline.i18n.yaml +2 -2
  300. package/references/official-docs/docs/tool-execution-pipeline.md +1 -1
  301. package/references/official-docs/docs/tool-execution-pipeline.zh.md +1 -1
  302. package/references/official-docs/docs/user/develop/basic/config.i18n.yaml +2 -2
  303. package/references/official-docs/docs/user/develop/basic/config.md +1 -1
  304. package/references/official-docs/docs/user/develop/basic/config.zh.md +4 -4
  305. package/references/official-docs/docs/user/develop/basic/index.i18n.yaml +1 -1
  306. package/references/official-docs/docs/user/develop/basic/index.zh.md +5 -5
  307. package/references/official-docs/docs/user/develop/basic/publish.i18n.yaml +2 -2
  308. package/references/official-docs/docs/user/develop/basic/publish.md +3 -3
  309. package/references/official-docs/docs/user/develop/basic/publish.zh.md +7 -7
  310. package/references/official-docs/docs/user/develop/basic/tool.i18n.yaml +2 -2
  311. package/references/official-docs/docs/user/develop/basic/tool.md +3 -3
  312. package/references/official-docs/docs/user/develop/basic/tool.zh.md +4 -4
  313. package/references/official-docs/docs/user/develop/framework/events.i18n.yaml +2 -2
  314. package/references/official-docs/docs/user/develop/framework/events.md +2 -2
  315. package/references/official-docs/docs/user/develop/framework/events.zh.md +3 -3
  316. package/references/official-docs/docs/user/develop/framework/index.i18n.yaml +1 -1
  317. package/references/official-docs/docs/user/develop/framework/index.zh.md +3 -3
  318. package/references/official-docs/docs/user/develop/framework/service.i18n.yaml +2 -2
  319. package/references/official-docs/docs/user/develop/framework/service.md +1 -1
  320. package/references/official-docs/docs/user/develop/framework/service.zh.md +3 -3
  321. package/references/official-docs/docs/user/develop/practice/dynamic-cordis.i18n.yaml +6 -0
  322. package/references/official-docs/docs/user/develop/practice/dynamic-cordis.md +15 -0
  323. package/references/official-docs/docs/user/develop/practice/dynamic-cordis.zh.md +15 -0
  324. package/references/official-docs/docs/user/develop/practice/index.i18n.yaml +2 -2
  325. package/references/official-docs/docs/user/develop/practice/index.md +1 -1
  326. package/references/official-docs/docs/user/develop/practice/index.zh.md +3 -3
  327. package/references/official-docs/docs/user/develop/practice/llm-adapter.i18n.yaml +2 -2
  328. package/references/official-docs/docs/user/develop/practice/llm-adapter.md +4 -3
  329. package/references/official-docs/docs/user/develop/practice/llm-adapter.zh.md +4 -3
  330. package/references/official-docs/docs/user/guide/github-review.i18n.yaml +6 -0
  331. package/references/official-docs/docs/user/guide/github-review.md +102 -0
  332. package/references/official-docs/docs/user/guide/github-review.zh.md +102 -0
  333. package/references/official-docs/docs/user/guide/index.i18n.yaml +2 -2
  334. package/references/official-docs/docs/user/guide/index.md +2 -2
  335. package/references/official-docs/docs/user/guide/index.zh.md +8 -8
  336. package/references/official-docs/docs/user/guide/mcp-memory.i18n.yaml +6 -0
  337. package/references/official-docs/docs/user/guide/mcp-memory.md +101 -0
  338. package/references/official-docs/docs/user/guide/mcp-memory.zh.md +101 -0
  339. package/references/official-docs/docs/user/guide/providers.i18n.yaml +2 -2
  340. package/references/official-docs/docs/user/guide/providers.md +40 -1
  341. package/references/official-docs/docs/user/guide/providers.zh.md +41 -2
  342. package/references/official-docs/docs/user/guide/python-sdk.i18n.yaml +2 -2
  343. package/references/official-docs/docs/user/guide/python-sdk.md +80 -34
  344. package/references/official-docs/docs/user/guide/python-sdk.zh.md +87 -41
  345. package/references/official-docs/docs/user/guide/schedule.i18n.yaml +6 -0
  346. package/references/official-docs/docs/user/guide/schedule.md +21 -0
  347. package/references/official-docs/docs/user/guide/schedule.zh.md +21 -0
  348. package/references/official-docs/docs/web-styling.i18n.yaml +1 -1
  349. package/references/official-docs/docs/web-styling.zh.md +2 -2
  350. package/references/official-docs/packages/AGENTS.md +3 -2
  351. package/references/official-docs/packages/README.md +104 -59
  352. package/references/official-docs/vendor/README.md +1 -0
  353. package/references/official-docs/website-docs.ts +52 -11
  354. package/references/sources.md +2 -2
  355. package/references/website-pages.md +3 -3
  356. package/scripts/check-docs-drift.ps1 +55 -0
  357. package/scripts/check-readme-sync.mjs +91 -0
  358. package/scripts/download-sources.ps1 +1 -1
  359. package/scripts/sync-official-docs.ps1 +19 -11
  360. package/scripts/verify-kit.ps1 +0 -4
  361. package/templates/js/README.es.md +1 -1
  362. package/templates/js/README.hi.md +1 -1
  363. package/templates/js/README.md +1 -1
  364. package/templates/js/README.pt.md +1 -1
  365. package/templates/js/README.zh.md +1 -1
  366. package/templates/js/package.json +4 -4
  367. package/templates/ts/README.es.md +1 -1
  368. package/templates/ts/README.hi.md +1 -1
  369. package/templates/ts/README.md +1 -1
  370. package/templates/ts/README.pt.md +1 -1
  371. package/templates/ts/README.zh.md +1 -1
  372. package/templates/ts/package.json +4 -4
  373. package/references/official-docs/examples/AGENTS.md +0 -20
@@ -0,0 +1,95 @@
1
+ # Web Client 架构
2
+
3
+ [English](web-client.md) | 中文
4
+
5
+ Web Client 是由独立加载插件组装而成的浏览器侧 Cordis 应用。它有四个可复用底座:[Client Modules](client-modules.zh.md) 加载插件图,[API Gateway](../api-gateway.zh.md) 提供类型化 Host 通信,[Slots](slots.zh.md) 组合 React UI,[Conversation](conversation.zh.md) 把 Session 历史窗口变成各 target 自有的视图。本文串联这些系统,并规定 Client model 与功能包各自所在的位置。
6
+
7
+ ## 分层与所有权
8
+
9
+ | 层 | 主要 owner | 职责 |
10
+ |---|---|---|
11
+ | Host 应用 | 业务 service 与 `packages/api/*-controller` Host entry | 拥有权威状态、持久化、mutation 顺序、访问策略与 stream 生产。 |
12
+ | 传输与 API assembly | `client/connection`、`api/gateway`、`api/remotes` | 建立 Client generation,公开生成的 `ctx.remote` method 与 stream,转发选定的 Cordis event,并承载取消和结果。 |
13
+ | Client model | `api/session-controller/client`、`api/workspace-controller/client` | 维护不依赖 React 的 Host 状态镜像,处理 stream/unary 竞态,拥有对象 identity 与订阅,并公开收窄的 command service。 |
14
+ | UI adapter | `client/ui-session`、`client/ui-workspace` | 把 model observable 转换为 root 或 Session scope 的标准 Slot source,不接管业务状态所有权。 |
15
+ | Conversation 数据 | `client/ui-conversation`、`ui-chat` 与 `ui-trajectory` 等 target package | 把标准 event 与紧凑的 Assistant 历史批次组装成相互独立的 target snapshot,并拥有共享的 Conversation shell 与输入流程。 |
16
+ | 组合与渲染 | `client/ui-slots`、`client/ui-renderer`、`client/ui-layout`、各 UI 功能包 | 声明扩展位置、推导组件 props、把 observable 绑定成 React hook,并挂载最终组件树。 |
17
+
18
+ 依赖方向是 Host 状态 → Remote 传输 → Client model → UI adapter → Conversation 或 presentation → Slots → React。用户操作通过 callback 反向进入注入的 Client service 或生成的 Remote namespace。Presentation component 绝不接收 Cordis `ctx`、transport object 或其他功能插件的实现。
19
+
20
+ ## 浏览器启动
21
+
22
+ Host 把组合后的 `WebBootGraph` 写入 `window.__DSH_BOOT__`,并在 parser-preloaded script 执行前安装浏览器 module-loader facade。模块系统是一张 lazy CommonJS 表:加载 bundle 只注册 factory;materialize entry 时才以同步 `require` 运行 factory,并解析 platform module 和已声明的动态依赖。
23
+
24
+ Web boot kernel 创建模块系统、预取 `immediately` entry、挂载 vendored Cordis Loader,再创建图中的每个 entry。Cordis service injection 决定激活顺序;module graph 顺序只决定同步 import 能否被 materialize。完整 roster 到达 settled 状态后,`ui-renderer` hydrate 不依赖框架的 boot DOM,并调用唯一一次 context 级 `renderSlot('root')`。[Client Modules](client-modules.zh.md)负责 graph、bundle route、cache revision 与 loader 细节。
25
+
26
+ ## Remote 通信
27
+
28
+ Host 业务 service 使用 Typert Remote decorator 标记可调用 method。Host generation 产出严格 descriptor、runtime codec、declaration merge 与 source map。Client 侧 `api-remotes` assembly 选择这些生成贡献,并把具体 method 挂到 `ctx.remote.<namespace>` 与 Session scope 的 `agentCtx.remote.<namespace>`。功能包依赖生成的 service face,而不依赖 Gateway 实现或 Host 包的运行时 entry。
29
+
30
+ Connection 拥有 request correlation、`/api` carrier、trust check、精确 Fetch 路由与 connection generation。API Gateway 拥有 Remote dispatch、取消、logical stream 与选定 Host event 的转发。Controller 操作应进入生成的 Remote method 或显式 Remote stream;功能自有的下载则注册精确 Fetch 路由。[API Gateway 参考](../api-gateway.zh.md)定义 generation 与调用,[Connection README](../../packages/client/connection/README.zh.md)定义物理 carrier 与信任策略。
31
+
32
+ 内部 `$events` logical stream 是 Connection generation source。它的 opening `ready` frame 携带用于路径显示的 Host home,并在 Host listener 已挂载、任何 controller 开始 baseline read 之前建立 generation。`ctx.remote.$on()` 把 allowlist 内的普通 event 交付给 root Client Context,并把 scoped waterfall event 交付给已解析的 Session Context;waterfall listener 可以返回结果、调用 `next()` 或拒绝。
33
+
34
+ ## Client models
35
+
36
+ 每个 API controller 包都拥有配对的 Host face 与 Client face。Host 侧拥有权威 mutation 与 stream 生产;Client 侧基于相同的生成 wire type 维护 identity 稳定、与 React 无关的 model,并公开 observable snapshot 与 command。UI 包消费这些 Client service,不在 component store 中复制 transport state。
37
+
38
+ ### Sessions
39
+
40
+ [`api/session-controller`](../../packages/api/session-controller/README.zh.md)公开 Session list、search、creation、selection data、prompt、queue、cancellation、pagination 及 follow/control stream 等 Host command。其 Client 侧按 `ClientSessions → SessionManager → Session` 组织:
41
+
42
+ - `ClientSessions` 提供 `ctx.sessions`,拥有 Session scope 与稳定的 `SessionBinding` object,并投影选中的 list state。
43
+ - `SessionManager` 拥有 list baseline、实时 list/control update、惰性 Session instance、queue、projection store、subagent catalog,以及 pull 与后到 update 之间的冲突顺序。
44
+ - 每个 `Session` 拥有一段由 `SessionEventLikeEntry` value 表示的连续逻辑 event window、pagination、follow、prompt/control state 与供 adapter 消费的 observable snapshot。
45
+
46
+ 持久 event 路径打开 `follow()`,其首帧包含当前 header、tail page、cursor 与完整 projection baseline。历史 record 带有显式 `event` 或 `chunks` 判别字段和字段对齐的内部 `event`;journal 先校验每条 record 的逻辑 seq 闭区间,Client 再直接把这些 record 保留为 `SessionEventLikeEntry`,无需逐 record 转换。每个物理 generation 都根据该 snapshot 原子替换保留窗口,随后按 seq append 标准实时 event。`page()` 只用于更早历史与 gap repair。瞬态 control stream 每代以完整 baseline 开始,随后应用 queue、job 与 projection update。
47
+
48
+ ### Workspaces
49
+
50
+ [`api/workspace-controller`](../../packages/api/workspace-controller/README.zh.md)把 Workspace mutation policy 与权威 follow feed 留在 Host。`ClientWorkspaceModel` 拥有浏览器侧 row、order、archived Session id、command echo,以及 stream/unary 竞态合并。每代 stream 先给出完整 baseline,再给出 `upsert`、`remove`、`order` 和 `archived` increment;重连时以新 baseline 替换 model。`WorkspaceController` 把该 model 作为 `ctx.workspaces` 公开,而 `ui-workspace` 向 UI 提供 `useWorkspaces` 与 navigation callback。
51
+
52
+ 这种配对不会产生第二份业务真相。Host controller 决定持久状态与 mutation outcome;Client model 维护最新可用的本地 projection,在有利于渲染时保持 object identity,并明确 delayed response 与 replacement baseline 的合并规则。
53
+
54
+ ## Conversation 与 presentation
55
+
56
+ `ui-session` 安装 `session` scope adapter,并提供 `useSessions`、`useSession`、`sessionId` 和 `useProjection`。领域 adapter 可以继续添加标准 source,但不会把 React hook 放进 model object。
57
+
58
+ `ui-conversation` 对每个 `SessionBinding.eventSource` 只绑定一次。它的 event registry 把标准 event 与 Client-only `chunkrow/*` 历史 event 关联成稳定的业务 Context,view registry 则 materialize target snapshot。packed run 在 replay 全程保持为单个 input 与 Match;Chat Assistant、Trajectory Assistant 和 Turn Tail 是解释它的三个内建 Definition。`ui-chat` 与 `ui-trajectory` 分别注册自己的 Definition 和 builder:它们可以解释同一 event family,但不会导入或共享彼此的最终 display model。Shell 选择一个已注册 view,再通过标准 hook 与 Slot 交付其 snapshot。[Conversation](conversation.zh.md)定义 Context identity、replay、Location data、target builder 与 keyed renderer。
59
+
60
+ `ui-slots` 提供类型化 registry 与 lifecycle ledger;`ui-renderer` 是唯一通过 `useSyncExternalStore` 绑定裸 observable、拥有 React context 并渲染 root tree 的包。功能 component 通过推导出的 props 接收 framework hook、owner prop、store action 与显式 injection。[Web Client Slots](slots.zh.md)列出这些输入、扩展 API 与当前 Slot 层级。
61
+
62
+ ## 数据通路
63
+
64
+ | 路径 | 顺序 |
65
+ |---|---|
66
+ | 持久 Session 展示 | Host Session log → packed Remote `follow`/`page` 历史 → Client `SessionEventLikeEntry` window → Conversation Context → target snapshot(`chat`、`trajectory` 或其他已注册 target)→ Slot view → React |
67
+ | 瞬态 Session control | Host control baseline → Remote snapshot stream → `SessionManager` queue/job/projection store → Session 与 list snapshot → 标准 hook → component |
68
+ | Workspace 状态 | Host Workspace baseline 与 increment → `ClientWorkspaceModel` → `ctx.workspaces.list` → `useWorkspaces` → sidebar、hero 与 navigation entry |
69
+ | scoped interaction | Host Cordis waterfall → API Remotes `$events` → Session Context 上的 `ctx.remote.$on()` → 所属 UI 包 → result 或 `next()` |
70
+ | 用户 command | component callback → 注册项 inject face 或 Slot owner → `ctx.sessions`、`ctx.workspaces` 或生成的 scoped Remote → Host Controller → 权威 update → stream 或 event projection 回到 Client |
71
+
72
+ ## 重连
73
+
74
+ 物理恢复与逻辑恢复彼此独立。Gateway mux 恢复物理 WebSocket;Connection 发布可用 generation 后,每个 `RemoteStream` 分别重开自己的 logical source。Carrier failure 可以重试;business error、非法 opening item 或 protocol violation 会令所属 logical stream 终止。
75
+
76
+ 恢复方式由数据语义决定:
77
+
78
+ - 持久 Session journal 校验逻辑 seq range,并根据每个 generation 的 opening snapshot 替换窗口;`page()` 提供更早历史并修复后续 range gap。
79
+ - Session control 与 Workspace stream 在断开期间保留最后一次发布的值,再用新的 opening baseline 原子替换。
80
+ - 普通 forwarded notification 不会 replay。需要可靠恢复的 stateful domain 必须提供 baseline、cursor 或显式 query;scoped waterfall 保留自身的 request lifetime。
81
+
82
+ 架构中没有统一的 Client `Runtime`、`HostFrame`、`events.mux`、`events.host` 或通用 `resync()` API。Connection 公开 generation state,Gateway 管理 logical stream,Client model 则按自身数据定义 replacement 或 resume 语义。
83
+
84
+ ## 包边界
85
+
86
+ 功能插件包可以通过 `import type` 共享声明;不得运行时导入或转发另一个功能插件的值。跨包行为使用注入的 Cordis service,跨包 UI 使用 Slots。特定 target 的 Conversation Definition、projection helper 与最终 view data 留在所属 target 包中,即使 Chat 和 Trajectory 有意实现平行逻辑。
87
+
88
+ 共享运行时值需要一个职责收窄、没有功能生命周期的静态 owner,例如 `client/store`、`ui-primitives` 或浏览器安全的 util 包。Transport 与生成 API assembly 可以导入运行时 contribution,因为组装同一个 protocol 正是它们的显式职责。功能包不能只为绕过此规则而添加 `dsh.client.external`。
89
+
90
+ 根据所添加的扩展查阅四篇详细参考:
91
+
92
+ - [Client Modules](client-modules.zh.md):package discovery、loading、共享 module identity 与 boot order。
93
+ - [API Gateway](../api-gateway.zh.md):Host method、生成的 Remote contribution、stream 与 forwarded event。
94
+ - [Web Client Slots](slots.zh.md):component、hook、store、injection 与 placement。
95
+ - [Conversation](conversation.zh.md):持久 event correlation、target snapshot,以及 Chat 或 Trajectory view contribution。
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write docs/subsystems/web-server.md
5
- web-server.md: 414863d88cdc34163882cdc3dfe8dc7c1471ac77
6
- web-server.zh.md: d756192ce733a3fe79c9eaf44e5d556c4bac90a8
5
+ web-server.md: d9b1ec007bc73274bb0c8b5d58745da1c76e6cb6
6
+ web-server.zh.md: 66375534a89e2c4674e748d4178cb7a31761e57e
@@ -2,7 +2,7 @@
2
2
 
3
3
  English | [中文](web-server.zh.md)
4
4
 
5
- [dsh-host-webserver](../../packages/host/webserver) is the browser HTTP carrier for the GUI host: a single `node:http` plugin providing `ctx.webServer`, a named-route registry, index.html transform callbacks, and one fallback handler that a plugin may claim. It is not part of the agent loop and not a capability seam; it knows no harness concepts, and another plugin registers every feature route, including the `/api` bridge, plugin bundles, and the HMR event stream ([layering note](../../.agents/notes/implemented/architecture/2026-07-19-gui-layering-and-rpc-protocol.md)). It serves browsers only: Electron loads the built files over `file://` and sends fetch requests through an IPC bridge instead of this server.
5
+ [dsh-host-webserver](../../packages/host/webserver) is the browser HTTP carrier for the GUI host: a single `node:http` plugin providing `ctx.webServer`, a named-route registry, optional gzip response compression, index.html transform callbacks, and one fallback handler that a plugin may claim. It is not part of the agent loop and not a capability seam; it knows no harness concepts, and another plugin registers every feature route, including the `/api` bridge, plugin bundles, and the HMR event stream ([layering note](../../.agents/notes/implemented/architecture/2026-07-24-web-config-tree-boot-and-transport-layering.md)). It serves browsers only: Electron loads the built files over `file://` and sends fetch requests through an IPC bridge instead of this server.
6
6
 
7
7
  Source: [`packages/host/webserver/src/index.ts`](../../packages/host/webserver/src/index.ts)
8
8
 
@@ -24,25 +24,31 @@ interface WebRoute {
24
24
  }
25
25
  ```
26
26
 
27
- Match order is fixed: exact table first, then longest matching prefix, then the registered fallback. Registration order carries no request-facing semantics — named routes are composed to be disjoint, and the fallback seat answers anything no named route claims; one owner only, a second registration throws. The shipped Web composition claims the seat with [`dsh-host-frontend-static`](../../packages/host/frontend-static/src/index.ts), the SPA dist server with locked semantics: non-GET/HEAD is 405, traversal outside the dist root is 403, any miss falls back to `index.html` with HTTP 200 (SPA routing), and unknown extensions ship as octet-stream.
27
+ Match order is fixed: exact table first, then longest matching prefix, then the registered fallback. Registration order carries no request-facing semantics — named routes are composed to be disjoint, and the fallback seat answers anything no named route claims; one owner only, a second registration throws. The shipped Web composition claims the seat with [`dsh-host-frontend-static`](../../packages/host/frontend-static/src/index.ts), the SPA dist server with locked semantics: Connection authenticates the dist root and configured index before their HTML is read; non-index assets remain public; non-GET/HEAD is 405, traversal outside the dist root is 403, existing files are served directly, absent or non-file targets are empty 404 responses, and unknown extensions ship as octet-stream.
28
28
 
29
29
  ## Config
30
30
 
31
31
  ```ts type-equiv
32
- /** Gateway config: the listen address. */
32
+ /** Web server listen and response-compression config. */
33
33
  interface Config {
34
34
  /** Listen host; the two supported values are loopback and all-interfaces. */
35
35
  host: '127.0.0.1' | '0.0.0.0'
36
36
  /** Listen port; zero requests an OS-assigned port. */
37
37
  port: number
38
+ /** Response compression for socket-backed HTTP requests. @default 'none' */
39
+ compression?: 'none' | 'gzip'
40
+ /** Gzip DEFLATE level from 0 through 9. @default 1 */
41
+ compressionLevel?: number
42
+ /** Minimum known response length eligible for gzip; unknown-length streams are eligible. @default 1024 */
43
+ compressionThresholdBytes?: number
38
44
  }
39
45
  ```
40
46
 
41
- `host` accepts only `127.0.0.1` (default posture) and `0.0.0.0` (deliberate network exposure); there is no TLS, auth, or origin policy, so a non-loopback bind exposes the server to that network. The dist location is an assembly fact of the frontend plugin that claims the seat.
47
+ `host` accepts only `127.0.0.1` (default posture) and `0.0.0.0` (deliberate network exposure). The carrier itself owns no TLS, authentication, or Origin policy, so a non-loopback bind exposes the server unless the composition supplies those controls. `compression` defaults to `none`; the shipped Web bundle selects gzip level 1 with a 1024-byte threshold. The shipped `dsh web` command selects loopback and rejects `--host 0.0.0.0`; its Connection plugin supplies Host/Origin checks plus browser-session authentication for every Host API route and stream. Other compositions own their bind and route-authentication policy. The dist location is an assembly fact of the frontend plugin that claims the seat.
42
48
 
43
49
  ## The service
44
50
 
45
- `WebServer` (`ctx.webServer`) listens immediately on activation; a listen failure (EADDRINUSE…) rejects initialization, and the boot process reports the failed fiber. `register(route)` adds one named route and returns its disposer; a duplicate `(kind, path)` throws because route patterns are a composition-level contract and a collision is a misconfiguration. `tapIndex(transform)` adds a pure html-to-html transform applied to every index response `/` and each SPA fallback in registration order; [dsh-client-modules](../../packages/client/modules) uses it to inject the boot manifest. `port` reads the listening port, including the port assigned by the OS when `config.port` is 0.
51
+ `WebServer` (`ctx.webServer`) listens immediately on activation; a listen failure (EADDRINUSE…) rejects initialization, and the boot process reports the failed fiber. `register(route)` adds one named route and returns its disposer; a duplicate `(kind, path)` throws because route patterns are a composition-level contract and a collision is a misconfiguration. Gzip wraps eligible socket-backed responses inside the server, so route handlers retain direct `ServerResponse` ownership and no response-writing API is added to the service. Existing content encodings, `Cache-Control: no-transform`, ranges, SSE, ZIP, and the packaged `.gz` Worker image remain identity responses. `collectIndexInjections()` gathers structured `IndexInjection` rows over one `webserver/index-inject` emit, and `renderIndex(html)` renders them into successful root and configured index responses before applying the raw `tapIndex(transform)` escape-hatch transforms in registration order; [dsh-client-modules](../../packages/client/modules) answers the event with the boot manifest rows. `port` reads the listening port, including the port assigned by the OS when `config.port` is 0.
46
52
 
47
53
  A request whose handling throws (a malformed %-escape hitting `decodeURIComponent`, a client dropping mid-body) is logged as a warning and answered 400 — or the socket destroyed when headers are already out — never a process exit. Disposal pairs `close()` with `closeAllConnections()` because a handler may hold its response open (SSE) and such connections never end on their own; without the force-close, teardown would hang. The package never prints: the URL line belongs to the shell. Per-package operational detail, including the dev-mode bundle watch pipeline, stays in the [README](../../packages/host/webserver/README.md).
48
54
 
@@ -52,7 +58,7 @@ A request whose handling throws (a malformed %-escape hitting `decodeURIComponen
52
58
 
53
59
  ## Cordis API
54
60
 
55
- 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).
61
+ 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`) — the language sides differ only in locale-specific paired document paths. 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).
56
62
 
57
63
  <a id="ctxwebserver--webserver"></a>
58
64
 
@@ -88,8 +94,9 @@ registerUpgrade(route: WebUpgradeRoute): () => void
88
94
  registerFallback(handler: WebRoute['handler']): () => void
89
95
 
90
96
  /**
91
- * Register an index.html transform, applied by the fallback owner to every
92
- * index response ({@link applyIndexTaps}) in registration order.
97
+ * Register a raw-HTML index transform, the escape hatch for markup no
98
+ * {@link IndexInjection} row expresses: {@link renderIndex} applies taps in
99
+ * registration order after rendering the structured rows.
93
100
  * @param transform - pure html-to-html function.
94
101
  * @returns the disposer removing the transform.
95
102
  */
@@ -102,7 +109,46 @@ tapIndex(transform: (html: string) => string): () => void
102
109
  * @returns the transformed body.
103
110
  */
104
111
  applyIndexTaps(html: string): string
112
+
113
+ /**
114
+ * Gather the structured injection table: one `webserver/index-inject` emit,
115
+ * every subscriber pushes its current rows. Fresh per call, so subscribers
116
+ * read live state (module graph, theme preference) at emit time.
117
+ * @returns rows in subscriber activation order.
118
+ */
119
+ collectIndexInjections(): IndexInjection[]
120
+
121
+ /**
122
+ * Render one index.html body: the structured injection table first, then
123
+ * the raw `tapIndex` transforms over the result.
124
+ * @param html - the raw index.html body.
125
+ * @returns the transformed body.
126
+ */
127
+ renderIndex(html: string): string
105
128
  ```
106
129
 
107
- Source: [`packages/host/webserver/src/index.ts:59`](../../packages/host/webserver/src/index.ts)
130
+ Source: [`packages/host/webserver/src/index.ts`](../../packages/host/webserver/src/index.ts)
131
+
132
+ <a id="webserver-events"></a>
133
+
134
+ ### `webserver/*` events
135
+
136
+ <a id="webserverindex-inject--emit"></a>
137
+
138
+ #### `webserver/index-inject` — emit
139
+
140
+ Collect the structured index injection table. Emitted on every index render and every worker boot-payload request; listeners push their current rows, so a row's data is read fresh at emit time.
141
+
142
+ ```ts cordis-catalog
143
+ /**
144
+ * Collect the structured index injection table. Emitted on every index
145
+ * render and every worker boot-payload request; listeners push their
146
+ * current rows, so a row's data is read fresh at emit time.
147
+ * @param table - Mutable row table; listeners append in activation order.
148
+ * @mode emit
149
+ */
150
+ 'webserver/index-inject'(table: IndexInjection[]): void
151
+ ```
152
+
153
+ Source: [`packages/host/webserver/src/index.ts`](../../packages/host/webserver/src/index.ts)
108
154
  <!-- END GENERATED cordis-surface -->
@@ -2,7 +2,7 @@
2
2
 
3
3
  [English](web-server.md) | 中文
4
4
 
5
- [dsh-host-webserver](../../packages/host/webserver) 是 GUI 宿主的浏览器 HTTP 载体:它是一个提供 `ctx.webServer` 的 `node:http` 插件,包含具名路由注册表、index.html 转换回调,以及一个可由插件认领的回退处理器。它不属于 agent loop(智能体循环),也不是能力 seam;它不了解任何 harness 概念。其他插件负责注册所有功能路由,包括 `/api` 桥接、插件 bundle 和 HMR(热模块替换)事件流([分层说明](../../.agents/notes/implemented/architecture/2026-07-19-gui-layering-and-rpc-protocol.md))。该服务器只服务浏览器:Electron 通过 `file://` 加载已构建文件,并经 IPC 桥接发送 fetch 请求,不使用本服务器。
5
+ [dsh-host-webserver](../../packages/host/webserver) 是 GUI Host 的浏览器 HTTP 载体:它是一个提供 `ctx.webServer` 的 `node:http` 插件,包含具名路由注册表、可选的 gzip 响应压缩、index.html 转换回调,以及一个可由插件认领的回退处理器。它不属于 agent loop(智能体循环),也不是能力 seam;它不了解任何 harness 概念。其他插件负责注册所有功能路由,包括 `/api` 桥接、插件 bundle 和 HMR(热模块替换)事件流([分层说明](../../.agents/notes/implemented/architecture/2026-07-24-web-config-tree-boot-and-transport-layering.zh.md))。该服务器只服务浏览器:Electron 通过 `file://` 加载已构建文件,并经 IPC 桥接发送 fetch 请求,不使用本服务器。
6
6
 
7
7
  源码:[`packages/host/webserver/src/index.ts`](../../packages/host/webserver/src/index.ts)
8
8
 
@@ -24,27 +24,33 @@ interface WebRoute {
24
24
  }
25
25
  ```
26
26
 
27
- 匹配顺序固定:先查 exact 表,再取最长匹配前缀,最后落到已注册的回退。注册顺序不携带任何面向请求的语义:具名路由在组合上互不相交,任何未被具名路由认领的请求都由回退席位应答;席位只有一个所有者,第二次注册会抛出异常。发布的 Web 组合用 [`dsh-host-frontend-static`](../../packages/host/frontend-static/src/index.ts) 认领席位,即遵循固定语义的 SPA dist 服务器:非 GET/HEAD 返回 405,越出 dist 根目录的遍历返回 403,任何未命中都以 HTTP 200 回退到 `index.html`(SPA 路由),未知扩展名按 octet-stream 发送。
27
+ 匹配顺序固定:先查 exact 表,再取最长匹配前缀,最后落到已注册的回退。注册顺序不携带任何面向请求的语义:具名路由在组合上互不相交,任何未被具名路由认领的请求都由回退席位应答;席位只有一个所有者,第二次注册会抛出异常。发布的 Web 组合用 [`dsh-host-frontend-static`](../../packages/host/frontend-static/src/index.ts) 认领席位,即遵循固定语义的 SPA dist 服务器:Connection 在读取 dist 根目录和配置 index 的 HTML 前完成认证;非 index 资产保持公开;非 GET/HEAD 返回 405,越出 dist 根目录的遍历返回 403,现有文件直接提供,缺失或不是文件的目标返回空的 404,未知扩展名按 octet-stream 发送。
28
28
 
29
29
  ## 配置
30
30
 
31
31
  ```ts type-equiv
32
- /** Gateway config: the listen address. */
32
+ /** Web server listen and response-compression config. */
33
33
  interface Config {
34
34
  /** Listen host; the two supported values are loopback and all-interfaces. */
35
35
  host: '127.0.0.1' | '0.0.0.0'
36
36
  /** Listen port; zero requests an OS-assigned port. */
37
37
  port: number
38
+ /** Response compression for socket-backed HTTP requests. @default 'none' */
39
+ compression?: 'none' | 'gzip'
40
+ /** Gzip DEFLATE level from 0 through 9. @default 1 */
41
+ compressionLevel?: number
42
+ /** Minimum known response length eligible for gzip; unknown-length streams are eligible. @default 1024 */
43
+ compressionThresholdBytes?: number
38
44
  }
39
45
  ```
40
46
 
41
- `host` 只接受 `127.0.0.1`(默认姿态)和 `0.0.0.0`(刻意的网络暴露);没有 TLS、认证或 origin 策略,因此绑定到非回环地址会把服务器暴露给该网络。dist 位置是认领席位的前端插件的组装事实。
47
+ `host` 只接受 `127.0.0.1`(默认姿态)和 `0.0.0.0`(刻意的网络暴露)。载体本身不拥有 TLS、认证或 Origin 策略,因此绑定到非回环地址会暴露服务器,除非组合层提供这些控制。`compression` 默认为 `none`;随附的 Web 组合选择 gzip level 1 和 1024 字节阈值。随附的 `dsh web` 命令选择 loopback 并拒绝 `--host 0.0.0.0`;其 Connection 插件为每个 Host API route 与 stream 提供 Host/Origin 校验和浏览器会话认证。其他组合自行拥有绑定与路由认证策略。dist 位置是认领席位的前端插件的组装事实。
42
48
 
43
49
  ## 服务
44
50
 
45
- `WebServer`(`ctx.webServer`)在激活时立即监听;监听失败(EADDRINUSE 等)会使初始化被拒绝,启动进程会报告失败的 fiber。`register(route)` 添加一条具名路由并返回其 disposer;重复的 `(kind, path)` 抛出异常,因为路由模式是组合层约定,冲突即配置错误。`tapIndex(transform)` 添加一个纯 HTML HTML 转换函数,按注册顺序应用于每个 index 响应(`/` 和每次 SPA 回退);[dsh-client-modules](../../packages/client/modules) 用它注入启动 manifest(元数据清单)。`port` 读取监听端口,包括 `config.port` 为 0 时操作系统分配的端口。
51
+ `WebServer`(`ctx.webServer`)在激活时立即监听;监听失败(EADDRINUSE 等)会使初始化被拒绝,启动进程会报告失败的 fiber。`register(route)` 添加一条具名路由并返回其 disposer;重复的 `(kind, path)` 抛出异常,因为路由模式是组合层约定,冲突即配置错误。Gzip 在服务器内部包装符合条件且基于 socket 的响应,因此 route handler 继续直接持有 `ServerResponse`,服务也不新增响应写出 API。已有内容编码、`Cache-Control: no-transform`、范围响应、SSE、ZIP 与打包后的 `.gz` Worker 镜像均保持 identity 响应。`collectIndexInjections()` 经一次 `webserver/index-inject` emit 收集结构化 `IndexInjection` 行,`renderIndex(html)` 把它们渲染进成功的根路径和配置 index 响应,随后再按注册顺序应用原始的 `tapIndex(transform)` 逃生口转换;[dsh-client-modules](../../packages/client/modules) 以启动 manifest(元数据清单)行回应该事件。`port` 读取监听端口,包括 `config.port` 为 0 时操作系统分配的端口。
46
52
 
47
- 处理过程中抛出异常的请求(畸形的 % 转义撞上 `decodeURIComponent`、客户端在请求体中途断开)会记录为警告并应答 400(响应头已发出时则销毁 socket),绝不导致进程退出。dispose(资源释放)把 `close()` 与 `closeAllConnections()` 配对使用,因为处理器可能像 SSE(Server-Sent Events)那样保持响应打开,而这类连接永远不会自行结束;没有强制关闭,拆卸就会挂起。该包从不打印输出:URL 行归 shell 所有。逐包运维细节(含开发模式的 bundle 监视流水线)留在 [README](../../packages/host/webserver/README.md) 中。
53
+ 处理过程中抛出异常的请求(畸形的 % 转义撞上 `decodeURIComponent`、客户端在请求体中途断开)会记录为警告并应答 400(响应头已发出时则销毁 socket),绝不导致进程退出。dispose(资源释放)把 `close()` 与 `closeAllConnections()` 配对使用,因为处理器可能像 SSE(Server-Sent Events)那样保持响应打开,而这类连接永远不会自行结束;没有强制关闭,拆卸就会挂起。该包从不打印输出:URL 行归 shell 所有。逐包运维细节(含开发模式的 bundle 监视流水线)留在 [README](../../packages/host/webserver/README.zh.md) 中。
48
54
 
49
55
  <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
50
56
 
@@ -52,7 +58,7 @@ interface Config {
52
58
 
53
59
  ## Cordis API
54
60
 
55
- 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).
61
+ 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`) — the language sides differ only in locale-specific paired document paths. Signature blocks use a `ts cordis-catalog` fence and keep the original source JSDoc; dispatch modes are defined in the [primer](../cordis-primer.zh.md#dispatch-modes), and the framework-inherited `ctx` API lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
56
62
 
57
63
  <a id="ctxwebserver--webserver"></a>
58
64
 
@@ -88,8 +94,9 @@ registerUpgrade(route: WebUpgradeRoute): () => void
88
94
  registerFallback(handler: WebRoute['handler']): () => void
89
95
 
90
96
  /**
91
- * Register an index.html transform, applied by the fallback owner to every
92
- * index response ({@link applyIndexTaps}) in registration order.
97
+ * Register a raw-HTML index transform, the escape hatch for markup no
98
+ * {@link IndexInjection} row expresses: {@link renderIndex} applies taps in
99
+ * registration order after rendering the structured rows.
93
100
  * @param transform - pure html-to-html function.
94
101
  * @returns the disposer removing the transform.
95
102
  */
@@ -102,7 +109,46 @@ tapIndex(transform: (html: string) => string): () => void
102
109
  * @returns the transformed body.
103
110
  */
104
111
  applyIndexTaps(html: string): string
112
+
113
+ /**
114
+ * Gather the structured injection table: one `webserver/index-inject` emit,
115
+ * every subscriber pushes its current rows. Fresh per call, so subscribers
116
+ * read live state (module graph, theme preference) at emit time.
117
+ * @returns rows in subscriber activation order.
118
+ */
119
+ collectIndexInjections(): IndexInjection[]
120
+
121
+ /**
122
+ * Render one index.html body: the structured injection table first, then
123
+ * the raw `tapIndex` transforms over the result.
124
+ * @param html - the raw index.html body.
125
+ * @returns the transformed body.
126
+ */
127
+ renderIndex(html: string): string
128
+ ```
129
+
130
+ Source: [`packages/host/webserver/src/index.ts`](../../packages/host/webserver/src/index.ts)
131
+
132
+ <a id="webserver-events"></a>
133
+
134
+ ### `webserver/*` events
135
+
136
+ <a id="webserverindex-inject--emit"></a>
137
+
138
+ #### `webserver/index-inject` — emit
139
+
140
+ Collect the structured index injection table. Emitted on every index render and every worker boot-payload request; listeners push their current rows, so a row's data is read fresh at emit time.
141
+
142
+ ```ts cordis-catalog
143
+ /**
144
+ * Collect the structured index injection table. Emitted on every index
145
+ * render and every worker boot-payload request; listeners push their
146
+ * current rows, so a row's data is read fresh at emit time.
147
+ * @param table - Mutable row table; listeners append in activation order.
148
+ * @mode emit
149
+ */
150
+ 'webserver/index-inject'(table: IndexInjection[]): void
105
151
  ```
106
152
 
107
- Source: [`packages/host/webserver/src/index.ts:59`](../../packages/host/webserver/src/index.ts)
153
+ Source: [`packages/host/webserver/src/index.ts`](../../packages/host/webserver/src/index.ts)
108
154
  <!-- END GENERATED cordis-surface -->
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write docs/subsystems/web.md
5
- web.md: 3bcd3ac24927c8c51baeabd770e2bd91c5ad1b77
6
- web.zh.md: 3348be2b808dc286364f5a795b236cb299acd6a6
5
+ web.md: fe6f1ca357eec19f55848ffbe54ed339eb638924
6
+ web.zh.md: bef3803abcd9c23582ee94479c89a05c7e3943ef
@@ -12,13 +12,14 @@ Search and fetch share no request schema and no business logic, but they are del
12
12
 
13
13
  ## Search request and result
14
14
 
15
- The model-facing tool argument is just a `query`; `maxResults` is a consumer-owned bound (`dsh-tool-web`'s `searchMaxResults` config, default `8`) passed through the seam and enforced on the way back — if a provider over-returns, the seam truncates `sources[]` and sets `truncated`.
15
+ Each seam request carries exactly one `query`. The `dsh-tool-web` consumer accepts a required `queries` array and fans it out into separate seam requests; a one-item array performs one search. `maxResults` is a consumer-owned bound (`dsh-tool-web`'s `searchMaxResults` config, default `8`) passed through the seam and enforced on the way back — if a provider over-returns, the seam truncates `sources[]` and sets `truncated`.
16
16
 
17
17
  ```ts type-equiv
18
18
  /**
19
- * What one search-capable backend can return. The model-facing argument is just
20
- * a query; `maxResults` is a `dsh-tool-web`-layer bound passed through unchanged
21
- * and enforced on the way back by the seam (see {@link WebSearchResult}).
19
+ * What one search-capable backend is asked to search. Each request carries one
20
+ * query; a consumer may issue several requests. `maxResults` is a
21
+ * `dsh-tool-web`-layer bound passed through unchanged and enforced on the way
22
+ * back by the seam (see {@link WebSearchResult}).
22
23
  */
23
24
  interface WebSearchRequest {
24
25
  readonly query: string
@@ -123,13 +124,19 @@ A provider's `available(): boolean` is a cheap LOCAL check (credential presence,
123
124
 
124
125
  Selection never depends on registration, config, or HMR order: a capability has an explicit provider id (config `searchProvider`/`fetchProvider`, or the matching env var feeding the same field), or auto-selects when exactly one usable provider is registered; multiple usable providers with no configured id is `WEB_PROVIDER_AMBIGUOUS`, not first-wins.
125
126
 
127
+ ## Fetch network policy
128
+
129
+ The shipped Cordis, Code, and Standard presets expose `web_fetch` in every sandbox and approval mode without per-call confirmation. File sandbox presets do not govern Web network access. A deployment that needs confirmation must add a `tools/pre-execute` policy or disable fetch.
130
+
131
+ The HTTP provider resolves each actual request, rejects non-public answers including private IPv4 reached through the active DNS64 prefix, pins the validated address set, and repeats enforcement for each same-origin redirect. A cross-origin redirect requires a new tool call and fresh public-address validation. These checks prevent SSRF access to non-public destinations but do not stop a model from sending data to a public URL.
132
+
126
133
  ## Errors
127
134
 
128
135
  `WebError extends HarnessError` ([core.md](core.md) error taxonomy) with a `code: string` (open, like every other seam's error — `LlmError`, `SubagentError`), not a closed union: a provider may raise its own codes without editing `dsh-web`, and consumers must tolerate an unknown code. The codes split by owner. Seam-neutral codes are raised by the shared `WebRuntime` contract: `WEB_PROVIDER_UNAVAILABLE`, `WEB_PROVIDER_CONFIGURED_MISSING`, `WEB_PROVIDER_CONFIGURED_UNAVAILABLE`, `WEB_PROVIDER_AMBIGUOUS`, `WEB_DUPLICATE_PROVIDER` (a registration-time programming error, the analogue of `LlmRuntime`'s `DUPLICATE_ADAPTER`), `WEB_ABORTED`, and `WEB_PROVIDER_ERROR` (the catch-all for a provider's own failure surfaced through the seam, including network/transport failure — DNS, connection refused, TLS). Fetch-transport codes are owned by the `dsh-web-fetch-http` implementation and a different fetch backend need not raise them: `WEB_INVALID_URL`, `WEB_BLOCKED_URL`, `WEB_REDIRECT_BLOCKED`, `WEB_FETCH_TOO_LARGE`, `WEB_FETCH_TIMEOUT`, `WEB_UNSUPPORTED_CONTENT_TYPE`.
129
136
 
130
137
  ## The service
131
138
 
132
- `WebRuntime` registers search and fetch providers, rejects duplicate ids with `WEB_DUPLICATE_PROVIDER`, and resolves providers at execution time with structured selection errors. The local fetch backend accepts only HTTP(S), rejects credentials, caps redirects, bytes, characters, and time, revalidates every same-origin redirect hop, and decodes the body; the tool owns presentation. The local backend does not block private-network targets; do not enable `web_fetch` where it can reach sensitive internal ones.
139
+ `WebRuntime` registers search and fetch providers, rejects duplicate ids with `WEB_DUPLICATE_PROVIDER`, and resolves providers at execution time with structured selection errors. The local fetch backend accepts only HTTP(S), rejects credentials, resolves each hostname once, rejects any answer set containing a non-public IPv4 or IPv6 destination or an active-prefix NAT64 translation to non-public IPv4, pins the request connection to the validated addresses, repeats those checks for every same-origin redirect hop, caps redirects, bytes, characters, and time, and decodes the body; the tool owns presentation.
133
140
 
134
141
  <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
135
142
 
@@ -137,7 +144,7 @@ Selection never depends on registration, config, or HMR order: a capability has
137
144
 
138
145
  ## Cordis API
139
146
 
140
- 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).
147
+ 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`) — the language sides differ only in locale-specific paired document paths. 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).
141
148
 
142
149
  <a id="ctxweb--webruntime"></a>
143
150
 
@@ -195,5 +202,5 @@ async search(request: WebSearchRequest, signal?: AbortSignal): Promise<WebSearch
195
202
  async fetch(request: WebFetchRequest, signal?: AbortSignal): Promise<WebFetchResult>
196
203
  ```
197
204
 
198
- Source: [`packages/web/web/src/index.ts:74`](../../packages/web/web/src/index.ts)
205
+ Source: [`packages/web/web/src/index.ts`](../../packages/web/web/src/index.ts)
199
206
  <!-- END GENERATED cordis-surface -->
@@ -2,7 +2,7 @@
2
2
 
3
3
  [English](web.md) | 中文
4
4
 
5
- Web 访问 seam 是一个[能力 seam](../../.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.md),在同一个 `ctx.web` 服务上横跨**两项操作**(search 与 fetch),并拆分到多个包:Service Definition([dsh-web](../../packages/web/web),`ctx.web` + 提供方注册表)、Service Provider([dsh-web-search-exa](../../packages/web/web-search-exa)、[dsh-web-search-perplexity](../../packages/web/web-search-perplexity)、[dsh-web-search-deepseek](../../packages/web/web-search-deepseek)、[dsh-web-fetch-http](../../packages/web/web-fetch-http))与 Consumer([dsh-tool-web](../../packages/web/tool-web),即 `web_search`/`web_fetch` 工具 schema)。Web 是**一项可选能力**,不属于 agent loop(智能体循环)主干,因此其词汇定义在此而非 [core.md](core.md) 中。更换 search 提供方不会改变模型提交查询的方式,更换 fetch 提供方也不会改变模型请求 URL 的方式。
5
+ Web 访问 seam 是一个[能力 seam](../../.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.zh.md),在同一个 `ctx.web` 服务上横跨**两项操作**(search 与 fetch),并拆分到多个包:Service Definition([dsh-web](../../packages/web/web),`ctx.web` + 提供方注册表)、Service Provider([dsh-web-search-exa](../../packages/web/web-search-exa)、[dsh-web-search-perplexity](../../packages/web/web-search-perplexity)、[dsh-web-search-deepseek](../../packages/web/web-search-deepseek)、[dsh-web-fetch-http](../../packages/web/web-fetch-http))与 Consumer([dsh-tool-web](../../packages/web/tool-web),即 `web_search`/`web_fetch` 工具 schema)。Web 是**一项可选能力**,不属于 agent loop(智能体循环)主干,因此其词汇定义在此而非 [core.md](core.zh.md) 中。更换 search 提供方不会改变模型提交查询的方式,更换 fetch 提供方也不会改变模型请求 URL 的方式。
6
6
 
7
7
  源码:[`packages/web/web/src/types.ts`](../../packages/web/web/src/types.ts)
8
8
 
@@ -12,13 +12,14 @@ Web 访问 seam 是一个[能力 seam](../../.agents/notes/implemented/architect
12
12
 
13
13
  ## 搜索请求与结果
14
14
 
15
- 面向模型的工具参数仅为一个 `query`;`maxResults` 是消费方自有的上限(`dsh-tool-web` 的 `searchMaxResults` 配置,默认 `8`),通过 seam 传递并在返回时强制执行——如果提供方返回超量,seam 截断 `sources[]` 并设置 `truncated`。
15
+ 每个 seam 请求只携带一个 `query`。消费方 `dsh-tool-web` 接受必填的 `queries` 数组,并把它扇出为多个独立 seam 请求;单元素数组执行一次搜索。`maxResults` 是消费方自有的上限(`dsh-tool-web` 的 `searchMaxResults` 配置,默认 `8`),通过 seam 传递并在返回时强制执行——如果提供方返回超量,seam 截断 `sources[]` 并设置 `truncated`。
16
16
 
17
17
  ```ts type-equiv
18
18
  /**
19
- * What one search-capable backend can return. The model-facing argument is just
20
- * a query; `maxResults` is a `dsh-tool-web`-layer bound passed through unchanged
21
- * and enforced on the way back by the seam (see {@link WebSearchResult}).
19
+ * What one search-capable backend is asked to search. Each request carries one
20
+ * query; a consumer may issue several requests. `maxResults` is a
21
+ * `dsh-tool-web`-layer bound passed through unchanged and enforced on the way
22
+ * back by the seam (see {@link WebSearchResult}).
22
23
  */
23
24
  interface WebSearchRequest {
24
25
  readonly query: string
@@ -123,13 +124,19 @@ type WebFetchBody =
123
124
 
124
125
  选择从不依赖注册顺序、配置顺序或 HMR(热模块替换)顺序:一项能力要么有显式的提供方 id(配置 `searchProvider`/`fetchProvider`,或填充同一字段的对应环境变量),要么在恰好只有一个可用提供方注册时自动选择;如果存在多个可用提供方却未配置 id,则抛出 `WEB_PROVIDER_AMBIGUOUS`,而不会选用最先注册的提供方。
125
126
 
127
+ ## 抓取网络策略
128
+
129
+ 已交付的 Cordis、Code 与 Standard preset 会在所有 sandbox 和审批模式下暴露 `web_fetch`,无需逐次确认。文件 sandbox preset 不管辖 Web 网络访问。需要确认步骤的部署必须添加 `tools/pre-execute` 策略或禁用抓取。
130
+
131
+ HTTP 提供方会解析每个实际请求,拒绝包括通过当前 DNS64 前缀抵达私有 IPv4 在内的非公开结果,固定已验证的地址集合,并在每次同源重定向时重复强制执行。跨源重定向需要新的工具调用和新的公开地址校验。这些检查会阻止通过 SSRF 访问非公开目的地址,但不会阻止模型把数据发送到公开 URL。
132
+
126
133
  ## 错误
127
134
 
128
- `WebError extends HarnessError`([core.md](core.md) 错误分类体系),带有 `code: string`(开放式,与其他 seam 的错误一致——`LlmError`、`SubagentError`),而非封闭联合类型:提供方可以在不修改 `dsh-web` 的情况下抛出自己的错误代码,消费方必须容忍未知错误代码。错误代码按所有者划分。共享的 `WebRuntime` 约定会抛出与 seam 无关的错误代码:`WEB_PROVIDER_UNAVAILABLE`、`WEB_PROVIDER_CONFIGURED_MISSING`、`WEB_PROVIDER_CONFIGURED_UNAVAILABLE`、`WEB_PROVIDER_AMBIGUOUS`、`WEB_DUPLICATE_PROVIDER`(注册时的编程错误,类似 `LlmRuntime` 的 `DUPLICATE_ADAPTER`)、`WEB_ABORTED`,以及 `WEB_PROVIDER_ERROR`(提供方自身故障经 seam 暴露时使用的兜底代码,包括 DNS、连接被拒绝、TLS 等网络或传输故障)。抓取传输层错误代码由 `dsh-web-fetch-http` 实现拥有,不同的抓取后端无需抛出它们:`WEB_INVALID_URL`、`WEB_BLOCKED_URL`、`WEB_REDIRECT_BLOCKED`、`WEB_FETCH_TOO_LARGE`、`WEB_FETCH_TIMEOUT`、`WEB_UNSUPPORTED_CONTENT_TYPE`。
135
+ `WebError extends HarnessError`([core.md](core.zh.md) 错误分类体系),带有 `code: string`(开放式,与其他 seam 的错误一致——`LlmError`、`SubagentError`),而非封闭联合类型:提供方可以在不修改 `dsh-web` 的情况下抛出自己的错误代码,消费方必须容忍未知错误代码。错误代码按所有者划分。共享的 `WebRuntime` 约定会抛出与 seam 无关的错误代码:`WEB_PROVIDER_UNAVAILABLE`、`WEB_PROVIDER_CONFIGURED_MISSING`、`WEB_PROVIDER_CONFIGURED_UNAVAILABLE`、`WEB_PROVIDER_AMBIGUOUS`、`WEB_DUPLICATE_PROVIDER`(注册时的编程错误,类似 `LlmRuntime` 的 `DUPLICATE_ADAPTER`)、`WEB_ABORTED`,以及 `WEB_PROVIDER_ERROR`(提供方自身故障经 seam 暴露时使用的兜底代码,包括 DNS、连接被拒绝、TLS 等网络或传输故障)。抓取传输层错误代码由 `dsh-web-fetch-http` 实现拥有,不同的抓取后端无需抛出它们:`WEB_INVALID_URL`、`WEB_BLOCKED_URL`、`WEB_REDIRECT_BLOCKED`、`WEB_FETCH_TOO_LARGE`、`WEB_FETCH_TIMEOUT`、`WEB_UNSUPPORTED_CONTENT_TYPE`。
129
136
 
130
137
  ## 服务
131
138
 
132
- `WebRuntime` 注册搜索与抓取提供方,以 `WEB_DUPLICATE_PROVIDER` 拒绝重复 id,并在执行时以结构化的选择错误解析提供方。本地抓取后端仅接受 HTTP(S)、拒绝凭证、限制重定向次数、字节数、字符数和时间、对每一次同源重定向跳转重新进行安全校验,并解码正文;展示由工具负责。本地后端不会拦截私有网络目标;在能够触及敏感内部目标的环境中,禁止启用 `web_fetch`。
139
+ `WebRuntime` 注册搜索与抓取提供方,以 `WEB_DUPLICATE_PROVIDER` 拒绝重复 id,并在执行时以结构化的选择错误解析提供方。本地抓取后端仅接受 HTTP(S)、拒绝凭证、对每个 hostname 只解析一次、拒绝包含任一非公开 IPv4/IPv6 目的地址或经当前前缀转换到非公开 IPv4 的 NAT64 地址的解析结果、把请求连接固定到已验证地址、对每一次同源重定向跳转重复这些校验、限制重定向次数、字节数、字符数和时间,并解码正文;展示由工具负责。
133
140
 
134
141
  <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
135
142
 
@@ -137,7 +144,7 @@ type WebFetchBody =
137
144
 
138
145
  ## Cordis API
139
146
 
140
- 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).
147
+ 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`) — the language sides differ only in locale-specific paired document paths. Signature blocks use a `ts cordis-catalog` fence and keep the original source JSDoc; dispatch modes are defined in the [primer](../cordis-primer.zh.md#dispatch-modes), and the framework-inherited `ctx` API lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
141
148
 
142
149
  <a id="ctxweb--webruntime"></a>
143
150
 
@@ -195,5 +202,5 @@ async search(request: WebSearchRequest, signal?: AbortSignal): Promise<WebSearch
195
202
  async fetch(request: WebFetchRequest, signal?: AbortSignal): Promise<WebFetchResult>
196
203
  ```
197
204
 
198
- Source: [`packages/web/web/src/index.ts:74`](../../packages/web/web/src/index.ts)
205
+ Source: [`packages/web/web/src/index.ts`](../../packages/web/web/src/index.ts)
199
206
  <!-- END GENERATED cordis-surface -->
@@ -0,0 +1,6 @@
1
+ # Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
2
+ # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
+ # after editing either side, bring the other along and re-record with:
4
+ # pnpm run verify-translation-pairing --write docs/subsystems/webhook.md
5
+ webhook.md: 5f04c99141c5630add46db3b55c3af78e2df2bdf
6
+ webhook.zh.md: 2eadf03aa5f32ae6f384e6b32a95e67bc0fdab7e
@@ -0,0 +1,70 @@
1
+ # Webhook runtime
2
+
3
+ English | [中文](webhook.zh.md)
4
+
5
+ The Webhook subsystem turns authenticated external deliveries into optional ordinary root Sessions. Provider adapters own authentication and generic JSON intake; trusted programmatic rules own conditions and external calls; `ctx.webhookRuntime` owns callback lifetime plus Workspace-backed Session creation. The [implemented decision](../../.agents/notes/implemented/feature/2026-08-22-fire-and-forget-webhook-sessions.md) records why the runtime keeps no delivery or completion state.
6
+
7
+ ## Shared values
8
+
9
+ `WebhookRuleId`, `WebhookSourceId`, and `WebhookDeliveryId` are opaque strings. A delivery id is provenance only: the runtime neither stores nor deduplicates it.
10
+
11
+ `WebhookEventMap` is merge-extensible by provider kind. `WebhookEventOf<K>` selects a known provider event and otherwise admits generic lossless JSON, allowing an out-of-tree adapter without changing the runtime package.
12
+
13
+ `VerifiedWebhookDelivery<K>` contains `kind`, configured `source`, provider `deliveryId`, normalized `event`, and non-negative safe-integer `receivedAt`. The runtime validates, detaches, and freezes the entire value before dispatching it to more than one rule.
14
+
15
+ `WebhookRule<K>` contains a unique id, provider kind, and `run(delivery, signal)`. The callback may execute arbitrary trusted code. It returns `null` or one `WebhookSessionRequest`, and it must observe the signal for asynchronous work that should stop when the registration unloads.
16
+
17
+ `WebhookSessionRequest` requires an absolute `workspacePath`, title, text prompt, agent preset, and permission preset. Optional `model` names an explicit provider/model route plus optional output-token cap and uses that adapter's reasoning default. Omission snapshots the complete current deployment selection, including reasoning effort, until the first request records its durable header.
18
+
19
+ ## Fire-and-forget dispatch
20
+
21
+ `dispatch()` snapshots the matching rules, schedules each independently, and returns before any callback settles. Throws and rejections are contained per rule. Registration disposal removes the rule before aborting and draining its active calls, so no later delivery can enter code that is unloading.
22
+
23
+ The runtime has no queue, retry, deduplication, execution status, crash replay, Agent-status listener, or completion result. Repeated delivery may create repeated Sessions. The only active-operation table is private teardown bookkeeping and disappears with the process.
24
+
25
+ ## Session creation
26
+
27
+ A non-null result is snapshotted before asynchronous preflight. The runtime validates permission and agent presets, resolves or creates the canonical Workspace, creates an Agent whose Session cwd equals the Workspace path, mounts the selected agent preset before publication, and durably attaches the Session before applying permission, title, and the initial follow-up.
28
+
29
+ The follow-up is a normal durable user-role message with `source.kind: "webhook"` and provider/source/delivery/rule provenance. Its accepted inbox insertion commits the webhook operation. The runtime does not specially flush or wait for the turn; ordinary Session persistence and Agent lifecycle apply afterward.
30
+
31
+ Failed attachment disposes the new Agent before a prompt exists. A failure between attachment and prompt admission attempts Workspace detach and Agent disposal without replacing the original error. A Workspace automatically created during preflight remains because another concurrent caller may already use it.
32
+
33
+ ## GitHub adapter
34
+
35
+ `@deepseek-ai/dsh-webhook-github` registers an exact route on an injected WebServer, resolves its credential reference for each request, verifies the untouched `application/json` body before parsing, and returns `202` immediately after in-memory dispatch. Its normalized event guarantees a signed lossless-JSON object; rules validate the event-specific fields they consume.
36
+
37
+ The [GitHub review guide](../user/guide/github-review.md) mounts this route on an isolated second WebServer so exposing webhook ingress does not expose the browser API.
38
+
39
+ <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
40
+
41
+ <a id="cordis-surface"></a>
42
+
43
+ ## Cordis API
44
+
45
+ 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`) — the language sides differ only in locale-specific paired document paths. 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).
46
+
47
+ <a id="ctxwebhookruntime--webhookruntime"></a>
48
+
49
+ ### `ctx.webhookRuntime` — `WebhookRuntime`
50
+
51
+ Fire-and-forget rule runtime. Session creation is the only built-in action.
52
+
53
+ ```ts cordis-catalog
54
+ /**
55
+ * Register one trusted programmatic rule.
56
+ * @param rule - unique id, provider kind, and arbitrary callback.
57
+ * @returns awaitable effect disposer that aborts and drains this rule's active callbacks.
58
+ */
59
+ register<K extends string>(rule: WebhookRule<K>): () => Promise<void>
60
+
61
+ /**
62
+ * Start every currently matching rule and return before any callback settles.
63
+ * @param delivery - authenticated provider data; snapshotted before dispatch.
64
+ * @throws synchronously when the runtime is closing or the delivery is malformed.
65
+ */
66
+ dispatch<K extends string>(delivery: VerifiedWebhookDelivery<K>): void
67
+ ```
68
+
69
+ Source: [`packages/webhook/webhook/src/index.ts`](../../packages/webhook/webhook/src/index.ts)
70
+ <!-- END GENERATED cordis-surface -->