dsh-plugin-dev-kb 1.6.0 → 1.8.1

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 (622) hide show
  1. package/CHANGELOG.md +186 -141
  2. package/README.en.md +172 -155
  3. package/README.md +183 -163
  4. package/kb/INDEX.md +236 -234
  5. package/kb/README.md +88 -83
  6. package/kb/extra/AGENTS.md +77 -77
  7. package/kb/extra/cli-help.md +15 -7
  8. package/kb/extra/cli-help.zh.md +15 -7
  9. package/kb/extra/cookbook/adding-a-plugin-preview.md +18 -25
  10. package/kb/extra/cookbook/adding-a-plugin-preview.zh.md +18 -25
  11. package/kb/extra/cookbook/reviewing-persistence-type-changes.md +1 -1
  12. package/kb/extra/cookbook/reviewing-persistence-type-changes.zh.md +1 -1
  13. package/kb/extra/cookbook/reviewing-ui-design.md +166 -0
  14. package/kb/extra/cookbook/reviewing-ui-design.zh.md +166 -0
  15. package/kb/extra/deepseek-llm-api-wire-extensions.md +162 -162
  16. package/kb/extra/deepseek-llm-api-wire-extensions.zh.md +162 -162
  17. package/kb/extra/defensive-patterns/conversation-and-session.md +2 -2
  18. package/kb/extra/defensive-patterns/conversation-and-session.zh.md +2 -2
  19. package/kb/extra/defensive-patterns/general.md +2 -0
  20. package/kb/extra/defensive-patterns/general.zh.md +2 -0
  21. package/kb/extra/defensive-patterns/package-surface.md +233 -231
  22. package/kb/extra/defensive-patterns/package-surface.zh.md +233 -231
  23. package/kb/extra/defensive-patterns/remote-and-api.md +117 -115
  24. package/kb/extra/defensive-patterns/remote-and-api.zh.md +117 -115
  25. package/kb/extra/development.md +221 -214
  26. package/kb/extra/development.zh.md +228 -221
  27. package/kb/extra/event-producer-consumer.md +133 -110
  28. package/kb/extra/event-producer-consumer.zh.md +135 -112
  29. package/kb/extra/i18n/README.md +2 -0
  30. package/kb/extra/i18n/README.zh.md +2 -0
  31. package/kb/extra/module-graph.md +1961 -1776
  32. package/kb/extra/module-graph.zh.md +1963 -1778
  33. package/kb/extra/persistence-changes/2026-10-13-liveshare-share-viewer-principal.md +60 -0
  34. package/kb/extra/persistence-changes/2026-10-13-liveshare-share-viewer-principal.zh.md +60 -0
  35. package/kb/extra/persistence-changes/2026-10-19-session-team-mode.md +48 -0
  36. package/kb/extra/persistence-changes/2026-10-19-session-team-mode.zh.md +48 -0
  37. package/kb/extra/persistence-changes/2026-10-22-action-card-status.md +60 -0
  38. package/kb/extra/persistence-changes/2026-10-22-action-card-status.zh.md +60 -0
  39. package/kb/extra/persistence-changes/2026-10-25-skill-catalog-incomplete.md +60 -0
  40. package/kb/extra/persistence-changes/2026-10-25-skill-catalog-incomplete.zh.md +60 -0
  41. package/kb/extra/persistence-changes/2026-10-27-retry-control-input.md +60 -0
  42. package/kb/extra/persistence-changes/2026-10-27-retry-control-input.zh.md +60 -0
  43. package/kb/extra/persistence-changes/2026-10-27-subagent-settlement-attribution.md +60 -0
  44. package/kb/extra/persistence-changes/2026-10-27-subagent-settlement-attribution.zh.md +60 -0
  45. package/kb/extra/persistence-changes/2026-11-02-subagent-catalog-names.md +48 -0
  46. package/kb/extra/persistence-changes/2026-11-02-subagent-catalog-names.zh.md +48 -0
  47. package/kb/extra/persistence-changes/2026-11-02-team-task-owner-names.md +48 -0
  48. package/kb/extra/persistence-changes/2026-11-02-team-task-owner-names.zh.md +48 -0
  49. package/kb/extra/persistence-changes/2026-11-05-timeline-priority-notice.md +60 -0
  50. package/kb/extra/persistence-changes/2026-11-05-timeline-priority-notice.zh.md +60 -0
  51. package/kb/extra/persistence-changes/README.md +92 -90
  52. package/kb/extra/persistence-changes/README.zh.md +92 -90
  53. package/kb/extra/persistence-changes/historical-formats/README.md +75 -75
  54. package/kb/extra/persistence-changes/historical-formats/README.zh.md +75 -75
  55. package/kb/extra/persistence-changes/releases/README.md +103 -103
  56. package/kb/extra/persistence-changes/releases/README.zh.md +103 -103
  57. package/kb/extra/rescope.md +55 -53
  58. package/kb/extra/rescope.zh.md +55 -53
  59. package/kb/extra/subsystems/agent-team.md +38 -75
  60. package/kb/extra/subsystems/agent-team.zh.md +38 -75
  61. package/kb/extra/subsystems/attachment.md +36 -13
  62. package/kb/extra/subsystems/attachment.zh.md +36 -13
  63. package/kb/extra/subsystems/boot.md +631 -447
  64. package/kb/extra/subsystems/boot.zh.md +631 -447
  65. package/kb/extra/subsystems/computer-use.md +179 -59
  66. package/kb/extra/subsystems/computer-use.zh.md +179 -59
  67. package/kb/extra/subsystems/deliverables.md +2 -0
  68. package/kb/extra/subsystems/deliverables.zh.md +2 -0
  69. package/kb/extra/subsystems/extensions.md +387 -384
  70. package/kb/extra/subsystems/extensions.zh.md +387 -384
  71. package/kb/extra/subsystems/feedback.md +418 -400
  72. package/kb/extra/subsystems/feedback.zh.md +418 -400
  73. package/kb/extra/subsystems/forge.md +2169 -0
  74. package/kb/extra/subsystems/forge.zh.md +2171 -0
  75. package/kb/extra/subsystems/liveshare.md +167 -0
  76. package/kb/extra/subsystems/liveshare.zh.md +167 -0
  77. package/kb/extra/subsystems/mcp.md +237 -139
  78. package/kb/extra/subsystems/mcp.zh.md +237 -139
  79. package/kb/extra/subsystems/office-kit.md +122 -0
  80. package/kb/extra/subsystems/office-kit.zh.md +122 -0
  81. package/kb/extra/subsystems/working-directory.md +95 -64
  82. package/kb/extra/subsystems/working-directory.zh.md +95 -64
  83. package/kb/extra/subsystems/worktrees.md +187 -76
  84. package/kb/extra/subsystems/worktrees.zh.md +187 -76
  85. package/kb/extra/testing.md +1 -1
  86. package/kb/extra/testing.zh.md +1 -1
  87. package/kb/extra/ui-design-review-cases.md +445 -0
  88. package/kb/extra/ui-design-review-cases.zh.md +445 -0
  89. package/kb/extra/ui-radius.md +3 -1
  90. package/kb/extra/ui-radius.zh.md +3 -1
  91. package/kb/extra/upgrade-guide/v0.2.1-alpha.1/python-ptc-sandbox/guide.md +21 -21
  92. package/kb/extra/upgrade-guide/v0.2.1-alpha.1/python-ptc-sandbox/guide.zh.md +21 -21
  93. package/kb/extra/upgrade-guide/v0.2.1-alpha.1/team-direct-inbox/guide.md +1 -1
  94. package/kb/extra/upgrade-guide/v0.2.1-alpha.1/team-direct-inbox/guide.zh.md +1 -1
  95. package/kb/extra/upgrade-guide/v0.2.1-alpha.2/cordis-timer-wrappers/guide.md +24 -0
  96. package/kb/extra/upgrade-guide/v0.2.1-alpha.2/cordis-timer-wrappers/guide.zh.md +24 -0
  97. package/kb/extra/upgrade-guide/v0.2.1-alpha.2/plugin-manager-view-fields/guide.md +25 -0
  98. package/kb/extra/upgrade-guide/v0.2.1-alpha.2/plugin-manager-view-fields/guide.zh.md +25 -0
  99. package/kb/extra/upgrade-guide/v0.2.1-alpha.4/model-switch-compaction/guide.md +30 -0
  100. package/kb/extra/upgrade-guide/v0.2.1-alpha.4/model-switch-compaction/guide.zh.md +30 -0
  101. package/kb/extra/upgrade-guide/v0.2.1-alpha.4/session-model-selection/guide.md +28 -0
  102. package/kb/extra/upgrade-guide/v0.2.1-alpha.4/session-model-selection/guide.zh.md +28 -0
  103. package/kb/extra/upgrade-guide/v0.2.1-rc.1/agent-instructions-chain-budgets/guide.md +24 -0
  104. package/kb/extra/upgrade-guide/v0.2.1-rc.1/agent-instructions-chain-budgets/guide.zh.md +24 -0
  105. package/kb/extra/upgrade-guide/v0.2.1-rc.1/subagent-control-tools/guide.md +23 -0
  106. package/kb/extra/upgrade-guide/v0.2.1-rc.1/subagent-control-tools/guide.zh.md +23 -0
  107. package/kb/extra/upgrade-guide/v0.2.1-rc.2/agent-runtime-owner/guide.md +20 -0
  108. package/kb/extra/upgrade-guide/v0.2.1-rc.2/agent-runtime-owner/guide.zh.md +20 -0
  109. package/kb/extra/upgrade-guide/v0.2.1-rc.2/agent-team-subagents/guide.md +31 -0
  110. package/kb/extra/upgrade-guide/v0.2.1-rc.2/agent-team-subagents/guide.zh.md +31 -0
  111. package/kb/extra/upgrade-guide/v0.2.1-rc.2/approval-projection-dependency/guide.md +34 -0
  112. package/kb/extra/upgrade-guide/v0.2.1-rc.2/approval-projection-dependency/guide.zh.md +34 -0
  113. package/kb/extra/upgrade-guide/v0.2.1-rc.2/auto-review-shutdown/guide.md +20 -0
  114. package/kb/extra/upgrade-guide/v0.2.1-rc.2/auto-review-shutdown/guide.zh.md +20 -0
  115. package/kb/extra/upgrade-guide/v0.2.1-rc.2/auto-review-user-sources/guide.md +18 -0
  116. package/kb/extra/upgrade-guide/v0.2.1-rc.2/auto-review-user-sources/guide.zh.md +18 -0
  117. package/kb/extra/upgrade-guide/v0.2.1-rc.2/built-in-japanese/guide.md +18 -0
  118. package/kb/extra/upgrade-guide/v0.2.1-rc.2/built-in-japanese/guide.zh.md +18 -0
  119. package/kb/extra/upgrade-guide/v0.2.1-rc.2/conditional-tools/guide.md +25 -0
  120. package/kb/extra/upgrade-guide/v0.2.1-rc.2/conditional-tools/guide.zh.md +25 -0
  121. package/kb/extra/upgrade-guide/v0.2.1-rc.2/context-menu-services/guide.md +23 -0
  122. package/kb/extra/upgrade-guide/v0.2.1-rc.2/context-menu-services/guide.zh.md +23 -0
  123. package/kb/extra/upgrade-guide/v0.2.1-rc.2/cua-consent-storage/guide.md +22 -0
  124. package/kb/extra/upgrade-guide/v0.2.1-rc.2/cua-consent-storage/guide.zh.md +22 -0
  125. package/kb/extra/upgrade-guide/v0.2.1-rc.2/cua-preset-scope/guide.md +18 -0
  126. package/kb/extra/upgrade-guide/v0.2.1-rc.2/cua-preset-scope/guide.zh.md +18 -0
  127. package/kb/extra/upgrade-guide/v0.2.1-rc.2/cua-relative-coordinates/guide.md +17 -0
  128. package/kb/extra/upgrade-guide/v0.2.1-rc.2/cua-relative-coordinates/guide.zh.md +17 -0
  129. package/kb/extra/upgrade-guide/v0.2.1-rc.2/file-drag-callbacks/guide.md +19 -0
  130. package/kb/extra/upgrade-guide/v0.2.1-rc.2/file-drag-callbacks/guide.zh.md +19 -0
  131. package/kb/extra/upgrade-guide/v0.2.1-rc.2/headless-policy-composition/guide.md +27 -0
  132. package/kb/extra/upgrade-guide/v0.2.1-rc.2/headless-policy-composition/guide.zh.md +27 -0
  133. package/kb/extra/upgrade-guide/v0.2.1-rc.2/model-badge-package-removal/guide.md +18 -0
  134. package/kb/extra/upgrade-guide/v0.2.1-rc.2/model-badge-package-removal/guide.zh.md +18 -0
  135. package/kb/extra/upgrade-guide/v0.2.1-rc.2/new-session-blank-reuse/guide.md +22 -0
  136. package/kb/extra/upgrade-guide/v0.2.1-rc.2/new-session-blank-reuse/guide.zh.md +22 -0
  137. package/kb/extra/upgrade-guide/v0.2.1-rc.2/node-24/guide.md +17 -0
  138. package/kb/extra/upgrade-guide/v0.2.1-rc.2/node-24/guide.zh.md +17 -0
  139. package/kb/extra/upgrade-guide/v0.2.1-rc.2/official-bundle-lists/guide.md +18 -0
  140. package/kb/extra/upgrade-guide/v0.2.1-rc.2/official-bundle-lists/guide.zh.md +18 -0
  141. package/kb/extra/upgrade-guide/v0.2.1-rc.2/persistent-terminal-controls/guide.md +18 -0
  142. package/kb/extra/upgrade-guide/v0.2.1-rc.2/persistent-terminal-controls/guide.zh.md +18 -0
  143. package/kb/extra/upgrade-guide/v0.2.1-rc.2/pi-ai-default-capacities/guide.md +18 -0
  144. package/kb/extra/upgrade-guide/v0.2.1-rc.2/pi-ai-default-capacities/guide.zh.md +18 -0
  145. package/kb/extra/upgrade-guide/v0.2.1-rc.2/pi-ai-model-catalog/guide.md +53 -0
  146. package/kb/extra/upgrade-guide/v0.2.1-rc.2/pi-ai-model-catalog/guide.zh.md +53 -0
  147. package/kb/extra/upgrade-guide/v0.2.1-rc.2/pi-ai-protocol-replay/guide.md +30 -0
  148. package/kb/extra/upgrade-guide/v0.2.1-rc.2/pi-ai-protocol-replay/guide.zh.md +30 -0
  149. package/kb/extra/upgrade-guide/v0.2.1-rc.2/ptc-script-format/guide.md +20 -0
  150. package/kb/extra/upgrade-guide/v0.2.1-rc.2/ptc-script-format/guide.zh.md +20 -0
  151. package/kb/extra/upgrade-guide/v0.2.1-rc.2/sdk-desktop-context/guide.md +18 -0
  152. package/kb/extra/upgrade-guide/v0.2.1-rc.2/sdk-desktop-context/guide.zh.md +18 -0
  153. package/kb/extra/upgrade-guide/v0.2.1-rc.2/sdk-minimal-checkpoints/guide.md +18 -0
  154. package/kb/extra/upgrade-guide/v0.2.1-rc.2/sdk-minimal-checkpoints/guide.zh.md +18 -0
  155. package/kb/extra/upgrade-guide/v0.2.1-rc.2/session-projection-handles/guide.md +24 -0
  156. package/kb/extra/upgrade-guide/v0.2.1-rc.2/session-projection-handles/guide.zh.md +24 -0
  157. package/kb/extra/upgrade-guide/v0.2.1-rc.2/session-store-writes/guide.md +25 -0
  158. package/kb/extra/upgrade-guide/v0.2.1-rc.2/session-store-writes/guide.zh.md +25 -0
  159. package/kb/extra/upgrade-guide/v0.2.1-rc.2/session-team-mode/guide.md +22 -0
  160. package/kb/extra/upgrade-guide/v0.2.1-rc.2/session-team-mode/guide.zh.md +22 -0
  161. package/kb/extra/upgrade-guide/v0.2.1-rc.2/subagent-activation-options/guide.md +18 -0
  162. package/kb/extra/upgrade-guide/v0.2.1-rc.2/subagent-activation-options/guide.zh.md +18 -0
  163. package/kb/extra/upgrade-guide/v0.2.1-rc.2/subagent-service-methods/guide.md +19 -0
  164. package/kb/extra/upgrade-guide/v0.2.1-rc.2/subagent-service-methods/guide.zh.md +19 -0
  165. package/kb/extra/upgrade-guide/v0.2.1-rc.2/subagent-user-controls/guide.md +26 -0
  166. package/kb/extra/upgrade-guide/v0.2.1-rc.2/subagent-user-controls/guide.zh.md +26 -0
  167. package/kb/extra/upgrade-guide/v0.2.1-rc.2/tool-executor-plugins/guide.md +35 -0
  168. package/kb/extra/upgrade-guide/v0.2.1-rc.2/tool-executor-plugins/guide.zh.md +35 -0
  169. package/kb/extra/upgrade-guide/v0.2.1-rc.2/web-fetch-private-destinations/guide.md +21 -0
  170. package/kb/extra/upgrade-guide/v0.2.1-rc.2/web-fetch-private-destinations/guide.zh.md +21 -0
  171. package/kb/extra/upgrade-guide/v0.2.1-rc.2/webserver-index-peer/guide.md +17 -0
  172. package/kb/extra/upgrade-guide/v0.2.1-rc.2/webserver-index-peer/guide.zh.md +17 -0
  173. package/kb/extra/upgrade-guide/v0.2.1-rc.3/attachment-read-access/guide.md +23 -0
  174. package/kb/extra/upgrade-guide/v0.2.1-rc.3/attachment-read-access/guide.zh.md +23 -0
  175. package/kb/extra/upgrade-guide/v0.2.1-rc.3/computer-use-helper-permissions/guide.md +21 -0
  176. package/kb/extra/upgrade-guide/v0.2.1-rc.3/computer-use-helper-permissions/guide.zh.md +21 -0
  177. package/kb/extra/upgrade-guide/v0.2.1-rc.3/cua-bundle-id-consent/guide.md +20 -0
  178. package/kb/extra/upgrade-guide/v0.2.1-rc.3/cua-bundle-id-consent/guide.zh.md +20 -0
  179. package/kb/extra/upgrade-guide/v0.2.1-rc.3/generated-worktree-names/guide.md +20 -0
  180. package/kb/extra/upgrade-guide/v0.2.1-rc.3/generated-worktree-names/guide.zh.md +20 -0
  181. package/kb/extra/upgrade-guide/v0.2.1-rc.3/inbox-only-agent-wait/guide.md +19 -0
  182. package/kb/extra/upgrade-guide/v0.2.1-rc.3/inbox-only-agent-wait/guide.zh.md +19 -0
  183. package/kb/extra/upgrade-guide/v0.2.1-rc.3/independent-session-forks/guide.md +23 -0
  184. package/kb/extra/upgrade-guide/v0.2.1-rc.3/independent-session-forks/guide.zh.md +23 -0
  185. package/kb/extra/upgrade-guide/v0.2.1-rc.3/ptc-caller-cancellation/guide.md +20 -0
  186. package/kb/extra/upgrade-guide/v0.2.1-rc.3/ptc-caller-cancellation/guide.zh.md +20 -0
  187. package/kb/extra/upgrade-guide/v0.2.1-rc.3/session-follow-activation/guide.md +21 -0
  188. package/kb/extra/upgrade-guide/v0.2.1-rc.3/session-follow-activation/guide.zh.md +21 -0
  189. package/kb/extra/upgrade-guide/v0.2.1-rc.3/subagent-runtime-ownership/guide.md +21 -0
  190. package/kb/extra/upgrade-guide/v0.2.1-rc.3/subagent-runtime-ownership/guide.zh.md +21 -0
  191. package/kb/extra/upgrade-guide/v0.2.1-rc.3/team-mode-menu/guide.md +18 -0
  192. package/kb/extra/upgrade-guide/v0.2.1-rc.3/team-mode-menu/guide.zh.md +18 -0
  193. package/kb/extra/upgrade-guide/v0.2.1-rc.3/team-projection/guide.md +20 -0
  194. package/kb/extra/upgrade-guide/v0.2.1-rc.3/team-projection/guide.zh.md +20 -0
  195. package/kb/extra/upgrade-guide/v0.2.1-rc.3/web-file-downloads/guide.md +19 -0
  196. package/kb/extra/upgrade-guide/v0.2.1-rc.3/web-file-downloads/guide.zh.md +19 -0
  197. package/kb/extra/upgrade-guide/v0.2.1-rc.3/web-search-defaults/guide.md +18 -0
  198. package/kb/extra/upgrade-guide/v0.2.1-rc.3/web-search-defaults/guide.zh.md +18 -0
  199. package/kb/extra/upgrade-guide/v0.2.1-rc.4/model-listing-refresh/guide.md +22 -0
  200. package/kb/extra/upgrade-guide/v0.2.1-rc.4/model-listing-refresh/guide.zh.md +22 -0
  201. package/kb/extra/upgrade-guide/v0.2.1-rc.4/reasoning-body-props/guide.md +20 -0
  202. package/kb/extra/upgrade-guide/v0.2.1-rc.4/reasoning-body-props/guide.zh.md +20 -0
  203. package/kb/extra/upgrade-guide/v0.2.1-rc.4/sandbox-unsupported-policy-error/guide.md +18 -0
  204. package/kb/extra/upgrade-guide/v0.2.1-rc.4/sandbox-unsupported-policy-error/guide.zh.md +18 -0
  205. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/context-menu-target/guide.md +19 -0
  206. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/context-menu-target/guide.zh.md +19 -0
  207. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/cordis-loader-entry-trees/guide.md +24 -0
  208. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/cordis-loader-entry-trees/guide.zh.md +24 -0
  209. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/css-anchored-menus/guide.md +21 -0
  210. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/css-anchored-menus/guide.zh.md +21 -0
  211. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/cua-source-dev-helper/guide.md +19 -0
  212. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/cua-source-dev-helper/guide.zh.md +19 -0
  213. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/desktop-stable-channel/guide.md +18 -0
  214. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/desktop-stable-channel/guide.zh.md +18 -0
  215. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/forge-git-permissions/guide.md +21 -0
  216. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/forge-git-permissions/guide.zh.md +21 -0
  217. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/forge-worktree-entry/guide.md +29 -0
  218. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/forge-worktree-entry/guide.zh.md +29 -0
  219. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/fs-observation-policy-default-off/guide.md +29 -0
  220. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/fs-observation-policy-default-off/guide.zh.md +29 -0
  221. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/llm-error-builtin-codes/guide.md +18 -0
  222. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/llm-error-builtin-codes/guide.zh.md +18 -0
  223. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/llm-request-purpose-declarations/guide.md +29 -0
  224. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/llm-request-purpose-declarations/guide.zh.md +29 -0
  225. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/pi-ai-request-image-count/guide.md +18 -0
  226. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/pi-ai-request-image-count/guide.zh.md +18 -0
  227. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/projection-event-frames/guide.md +32 -0
  228. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/projection-event-frames/guide.zh.md +32 -0
  229. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/projection-released-checkpoint/guide.md +30 -0
  230. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/projection-released-checkpoint/guide.zh.md +30 -0
  231. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/projection-snapshot-scope/guide.md +19 -0
  232. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/projection-snapshot-scope/guide.zh.md +19 -0
  233. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/retained-ptc-timeout/guide.md +21 -0
  234. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/retained-ptc-timeout/guide.zh.md +21 -0
  235. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/schedule-agent-tools/guide.md +37 -0
  236. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/schedule-agent-tools/guide.zh.md +37 -0
  237. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/schedule-remote-host-tasks/guide.md +22 -0
  238. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/schedule-remote-host-tasks/guide.zh.md +22 -0
  239. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/sdk-run-commands/guide.md +24 -0
  240. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/sdk-run-commands/guide.zh.md +24 -0
  241. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/session-header-menu/guide.md +20 -0
  242. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/session-header-menu/guide.zh.md +20 -0
  243. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/subagent-explicit-reasoning/guide.md +20 -0
  244. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/subagent-explicit-reasoning/guide.zh.md +20 -0
  245. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/web-search-credential-modes/guide.md +17 -0
  246. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/web-search-credential-modes/guide.zh.md +17 -0
  247. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/web-search-default-provider/guide.md +19 -0
  248. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/web-search-default-provider/guide.zh.md +19 -0
  249. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/chat-process-activity-context/guide.md +18 -0
  250. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/chat-process-activity-context/guide.zh.md +18 -0
  251. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-kit-package/guide.md +34 -0
  252. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-kit-package/guide.zh.md +34 -0
  253. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-operation-tools/guide.md +49 -0
  254. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-operation-tools/guide.zh.md +49 -0
  255. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-skill-resources/guide.md +36 -0
  256. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-skill-resources/guide.zh.md +36 -0
  257. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/subagent-names/guide.md +29 -0
  258. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/subagent-names/guide.zh.md +29 -0
  259. package/kb/extra/upgrade-guide/v0.2.2-rc.1/account-notification-fields/guide.md +26 -0
  260. package/kb/extra/upgrade-guide/v0.2.2-rc.1/account-notification-fields/guide.zh.md +26 -0
  261. package/kb/extra/upgrade-guide/v0.2.2-rc.1/account-remote-provider/guide.md +22 -0
  262. package/kb/extra/upgrade-guide/v0.2.2-rc.1/account-remote-provider/guide.zh.md +22 -0
  263. package/kb/extra/upgrade-guide/v0.2.2-rc.1/archive-worktrees/guide.md +21 -0
  264. package/kb/extra/upgrade-guide/v0.2.2-rc.1/archive-worktrees/guide.zh.md +21 -0
  265. package/kb/extra/upgrade-guide/v0.2.2-rc.1/attachment-error-codes/guide.md +23 -0
  266. package/kb/extra/upgrade-guide/v0.2.2-rc.1/attachment-error-codes/guide.zh.md +23 -0
  267. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-ax-read-limits/guide.md +20 -0
  268. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-ax-read-limits/guide.zh.md +20 -0
  269. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-hover-ax-only/guide.md +18 -0
  270. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-hover-ax-only/guide.zh.md +18 -0
  271. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-native-platform/guide.md +23 -0
  272. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-native-platform/guide.zh.md +23 -0
  273. package/kb/extra/upgrade-guide/v0.2.2-rc.1/dsh-doc-skill/guide.md +35 -0
  274. package/kb/extra/upgrade-guide/v0.2.2-rc.1/dsh-doc-skill/guide.zh.md +35 -0
  275. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-change-request-overview/guide.md +26 -0
  276. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-change-request-overview/guide.zh.md +26 -0
  277. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-pinned-diff/guide.md +26 -0
  278. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-pinned-diff/guide.zh.md +26 -0
  279. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-review-reads/guide.md +19 -0
  280. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-review-reads/guide.zh.md +19 -0
  281. package/kb/extra/upgrade-guide/v0.2.2-rc.1/package-export-cleanup/guide.md +26 -0
  282. package/kb/extra/upgrade-guide/v0.2.2-rc.1/package-export-cleanup/guide.zh.md +26 -0
  283. package/kb/extra/upgrade-guide/v0.2.2-rc.1/plugin-update-method/guide.md +22 -0
  284. package/kb/extra/upgrade-guide/v0.2.2-rc.1/plugin-update-method/guide.zh.md +22 -0
  285. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-bootstrap-protocol/guide.md +25 -0
  286. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-bootstrap-protocol/guide.zh.md +25 -0
  287. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-inspect-output/guide.md +48 -0
  288. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-inspect-output/guide.zh.md +48 -0
  289. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-scoped-repl-default/guide.md +45 -0
  290. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-scoped-repl-default/guide.zh.md +45 -0
  291. package/kb/extra/upgrade-guide/v0.2.2-rc.1/runtime-context-reminders/guide.md +19 -0
  292. package/kb/extra/upgrade-guide/v0.2.2-rc.1/runtime-context-reminders/guide.zh.md +19 -0
  293. package/kb/extra/upgrade-guide/v0.2.2-rc.1/session-append-overloads/guide.md +17 -0
  294. package/kb/extra/upgrade-guide/v0.2.2-rc.1/session-append-overloads/guide.zh.md +17 -0
  295. package/kb/extra/upgrade-guide/v0.2.2-rc.1/subagent-interrupt-default/guide.md +27 -0
  296. package/kb/extra/upgrade-guide/v0.2.2-rc.1/subagent-interrupt-default/guide.zh.md +27 -0
  297. package/kb/extra/upgrade-guide/v0.2.2-rc.1/terminal-backend-cleanup-error/guide.md +20 -0
  298. package/kb/extra/upgrade-guide/v0.2.2-rc.1/terminal-backend-cleanup-error/guide.zh.md +20 -0
  299. package/kb/extra/upgrade-guide/v0.2.2-rc.1/terminal-bundle-sidebar-backend/guide.md +19 -0
  300. package/kb/extra/upgrade-guide/v0.2.2-rc.1/terminal-bundle-sidebar-backend/guide.zh.md +19 -0
  301. package/kb/extra/upgrade-guide/v0.2.2-rc.1/web-fetch-transport-error-codes/guide.md +18 -0
  302. package/kb/extra/upgrade-guide/v0.2.2-rc.1/web-fetch-transport-error-codes/guide.zh.md +18 -0
  303. package/kb/extra/upgrade-guide/v0.2.2-rc.1/web-search-billing/guide.md +41 -0
  304. package/kb/extra/upgrade-guide/v0.2.2-rc.1/web-search-billing/guide.zh.md +41 -0
  305. package/kb/extra/upgrade-guide/v0.2.2-rc.1/window-drag-regions/guide.md +21 -0
  306. package/kb/extra/upgrade-guide/v0.2.2-rc.1/window-drag-regions/guide.zh.md +21 -0
  307. package/kb/extra/upgrade-guide/v0.2.2-rc.2/client-module-metadata/guide.md +29 -0
  308. package/kb/extra/upgrade-guide/v0.2.2-rc.2/client-module-metadata/guide.zh.md +29 -0
  309. package/kb/extra/upgrade-guide/v0.2.2-rc.2/connection-page-peer/guide.md +25 -0
  310. package/kb/extra/upgrade-guide/v0.2.2-rc.2/connection-page-peer/guide.zh.md +25 -0
  311. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cordis-root-and-intercept-metadata/guide.md +31 -0
  312. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cordis-root-and-intercept-metadata/guide.zh.md +31 -0
  313. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-agents-without-preset/guide.md +24 -0
  314. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-agents-without-preset/guide.zh.md +24 -0
  315. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-macos-provider/guide.md +24 -0
  316. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-macos-provider/guide.zh.md +24 -0
  317. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-partial-observations/guide.md +19 -0
  318. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-partial-observations/guide.zh.md +19 -0
  319. package/kb/extra/upgrade-guide/v0.2.2-rc.2/deepseek-files-timeout/guide.md +15 -0
  320. package/kb/extra/upgrade-guide/v0.2.2-rc.2/deepseek-files-timeout/guide.zh.md +15 -0
  321. package/kb/extra/upgrade-guide/v0.2.2-rc.2/experimental-tool-error-codes/guide.md +28 -0
  322. package/kb/extra/upgrade-guide/v0.2.2-rc.2/experimental-tool-error-codes/guide.zh.md +28 -0
  323. package/kb/extra/upgrade-guide/v0.2.2-rc.2/package-export-cleanup/guide.md +36 -0
  324. package/kb/extra/upgrade-guide/v0.2.2-rc.2/package-export-cleanup/guide.zh.md +36 -0
  325. package/kb/extra/upgrade-guide/v0.2.2-rc.2/python-ptc-removal/guide.md +22 -0
  326. package/kb/extra/upgrade-guide/v0.2.2-rc.2/python-ptc-removal/guide.zh.md +22 -0
  327. package/kb/extra/upgrade-guide/v0.2.2-rc.2/session-status-package/guide.md +31 -0
  328. package/kb/extra/upgrade-guide/v0.2.2-rc.2/session-status-package/guide.zh.md +31 -0
  329. package/kb/extra/upgrade-guide/v0.2.2-rc.2/shared-search-filter/guide.md +18 -0
  330. package/kb/extra/upgrade-guide/v0.2.2-rc.2/shared-search-filter/guide.zh.md +18 -0
  331. package/kb/extra/upgrade-guide/v0.2.2-rc.2/shell-fs-tool-error-codes/guide.md +30 -0
  332. package/kb/extra/upgrade-guide/v0.2.2-rc.2/shell-fs-tool-error-codes/guide.zh.md +30 -0
  333. package/kb/extra/web-styling.md +57 -39
  334. package/kb/extra/web-styling.zh.md +57 -39
  335. package/kb/meta/search-index.json +4508 -3806
  336. package/kb/meta/source.json +18 -14
  337. package/kb/site/develop/cordis-tutorial/04-events.md +1 -1
  338. package/kb/site/develop/cordis-tutorial/07-into-the-harness.md +5 -4
  339. package/kb/site/develop/framework/events.md +1 -1
  340. package/kb/site/develop/practice/dynamic-cordis.md +1 -1
  341. package/kb/site/develop/practice/llm-adapter.md +192 -192
  342. package/kb/site/en/develop/cordis-tutorial/04-events.md +1 -1
  343. package/kb/site/en/develop/cordis-tutorial/07-into-the-harness.md +5 -4
  344. package/kb/site/en/develop/framework/events.md +1 -1
  345. package/kb/site/en/develop/practice/dynamic-cordis.md +1 -1
  346. package/kb/site/en/develop/practice/llm-adapter.md +192 -192
  347. package/kb/site/en/guide/desktop-uninstall-cleanup.md +63 -0
  348. package/kb/site/en/guide/network-proxy.md +1 -1
  349. package/kb/site/en/guide/plugin-market.md +153 -151
  350. package/kb/site/en/guide/providers.md +234 -230
  351. package/kb/site/en/guide/python-sdk.md +17 -2
  352. package/kb/site/en/guide/quickstart.md +35 -34
  353. package/kb/site/en/guide/schedule.md +45 -26
  354. package/kb/site/en/reference/agent-lifecycle.md +3 -1
  355. package/kb/site/en/reference/api-gateway.md +4 -4
  356. package/kb/site/en/reference/capability-seams.md +789 -719
  357. package/kb/site/en/reference/config-catalog.md +5432 -4806
  358. package/kb/site/en/reference/cookbook/adding-a-package.md +175 -173
  359. package/kb/site/en/reference/cookbook/adding-a-tool.md +105 -104
  360. package/kb/site/en/reference/cookbook/extension-cookbook.md +178 -135
  361. package/kb/site/en/reference/cordis-api/context.md +373 -369
  362. package/kb/site/en/reference/cordis-api/events.md +9 -9
  363. package/kb/site/en/reference/cordis-api/fiber.md +457 -380
  364. package/kb/site/en/reference/cordis-api/inherited.md +44 -43
  365. package/kb/site/en/reference/cordis-api/service.md +118 -107
  366. package/kb/site/en/reference/experimental-persistence-catalog.md +36 -20
  367. package/kb/site/en/reference/index.md +174 -168
  368. package/kb/site/en/reference/persistence-catalog.md +9453 -9146
  369. package/kb/site/en/reference/subsystems/client-modules.md +19 -11
  370. package/kb/site/en/reference/subsystems/compaction.md +288 -288
  371. package/kb/site/en/reference/subsystems/conversation.md +2 -0
  372. package/kb/site/en/reference/subsystems/core.md +1172 -1117
  373. package/kb/site/en/reference/subsystems/credentials.md +526 -497
  374. package/kb/site/en/reference/subsystems/filesystem.md +708 -534
  375. package/kb/site/en/reference/subsystems/index.md +82 -80
  376. package/kb/site/en/reference/subsystems/llm-streaming.md +1290 -1200
  377. package/kb/site/en/reference/subsystems/lsp.md +230 -206
  378. package/kb/site/en/reference/subsystems/persistence.md +451 -422
  379. package/kb/site/en/reference/subsystems/plan.md +91 -91
  380. package/kb/site/en/reference/subsystems/ptc-runtime.md +295 -254
  381. package/kb/site/en/reference/subsystems/sandbox.md +250 -225
  382. package/kb/site/en/reference/subsystems/schedule.md +194 -430
  383. package/kb/site/en/reference/subsystems/session-projection.md +186 -44
  384. package/kb/site/en/reference/subsystems/session-query.md +525 -515
  385. package/kb/site/en/reference/subsystems/session-reference.md +231 -228
  386. package/kb/site/en/reference/subsystems/session.md +1478 -1343
  387. package/kb/site/en/reference/subsystems/sidebar-right.md +165 -164
  388. package/kb/site/en/reference/subsystems/skills.md +356 -356
  389. package/kb/site/en/reference/subsystems/slots.md +235 -204
  390. package/kb/site/en/reference/subsystems/storage.md +26 -9
  391. package/kb/site/en/reference/subsystems/subagent.md +119 -102
  392. package/kb/site/en/reference/subsystems/system-prompt.md +13 -11
  393. package/kb/site/en/reference/subsystems/terminal.md +188 -188
  394. package/kb/site/en/reference/subsystems/token-meter.md +45 -0
  395. package/kb/site/en/reference/subsystems/tools.md +902 -751
  396. package/kb/site/en/reference/subsystems/typert.md +21 -11
  397. package/kb/site/en/reference/subsystems/user-questions.md +330 -311
  398. package/kb/site/en/reference/subsystems/web-client.md +161 -104
  399. package/kb/site/en/reference/subsystems/web-server.md +434 -306
  400. package/kb/site/en/reference/subsystems/web.md +268 -210
  401. package/kb/site/en/reference/subsystems/workflow.md +287 -282
  402. package/kb/site/en/reference/subsystems/workspace.md +743 -651
  403. package/kb/site/en/reference/tool-catalog.md +2867 -2829
  404. package/kb/site/en/reference/tool-execution-pipeline.md +5 -4
  405. package/kb/site/guide/desktop-uninstall-cleanup.md +63 -0
  406. package/kb/site/guide/network-proxy.md +1 -1
  407. package/kb/site/guide/plugin-market.md +153 -151
  408. package/kb/site/guide/providers.md +234 -230
  409. package/kb/site/guide/python-sdk.md +17 -2
  410. package/kb/site/guide/quickstart.md +35 -34
  411. package/kb/site/guide/schedule.md +45 -26
  412. package/kb/site/reference/agent-lifecycle.md +3 -1
  413. package/kb/site/reference/api-gateway.md +4 -4
  414. package/kb/site/reference/capability-seams.md +789 -719
  415. package/kb/site/reference/config-catalog.md +5432 -4806
  416. package/kb/site/reference/cookbook/adding-a-package.md +175 -173
  417. package/kb/site/reference/cookbook/adding-a-tool.md +107 -106
  418. package/kb/site/reference/cookbook/extension-cookbook.md +182 -139
  419. package/kb/site/reference/cordis-api/context.md +373 -369
  420. package/kb/site/reference/cordis-api/events.md +9 -9
  421. package/kb/site/reference/cordis-api/fiber.md +459 -380
  422. package/kb/site/reference/cordis-api/inherited.md +44 -43
  423. package/kb/site/reference/cordis-api/service.md +118 -107
  424. package/kb/site/reference/experimental-persistence-catalog.md +36 -20
  425. package/kb/site/reference/index.md +178 -172
  426. package/kb/site/reference/persistence-catalog.md +9453 -9146
  427. package/kb/site/reference/subsystems/client-modules.md +19 -11
  428. package/kb/site/reference/subsystems/compaction.md +288 -288
  429. package/kb/site/reference/subsystems/conversation.md +4 -0
  430. package/kb/site/reference/subsystems/core.md +1184 -1129
  431. package/kb/site/reference/subsystems/credentials.md +526 -497
  432. package/kb/site/reference/subsystems/filesystem.md +708 -534
  433. package/kb/site/reference/subsystems/index.md +82 -80
  434. package/kb/site/reference/subsystems/llm-streaming.md +1296 -1206
  435. package/kb/site/reference/subsystems/lsp.md +230 -206
  436. package/kb/site/reference/subsystems/persistence.md +451 -422
  437. package/kb/site/reference/subsystems/plan.md +91 -91
  438. package/kb/site/reference/subsystems/ptc-runtime.md +295 -254
  439. package/kb/site/reference/subsystems/sandbox.md +250 -225
  440. package/kb/site/reference/subsystems/schedule.md +197 -433
  441. package/kb/site/reference/subsystems/session-projection.md +186 -44
  442. package/kb/site/reference/subsystems/session-query.md +525 -515
  443. package/kb/site/reference/subsystems/session-reference.md +231 -228
  444. package/kb/site/reference/subsystems/session.md +1482 -1347
  445. package/kb/site/reference/subsystems/sidebar-right.md +165 -164
  446. package/kb/site/reference/subsystems/skills.md +356 -356
  447. package/kb/site/reference/subsystems/slots.md +239 -208
  448. package/kb/site/reference/subsystems/storage.md +26 -9
  449. package/kb/site/reference/subsystems/subagent.md +119 -102
  450. package/kb/site/reference/subsystems/system-prompt.md +13 -11
  451. package/kb/site/reference/subsystems/terminal.md +188 -188
  452. package/kb/site/reference/subsystems/token-meter.md +45 -0
  453. package/kb/site/reference/subsystems/tools.md +902 -751
  454. package/kb/site/reference/subsystems/typert.md +21 -11
  455. package/kb/site/reference/subsystems/user-questions.md +330 -311
  456. package/kb/site/reference/subsystems/web-client.md +161 -104
  457. package/kb/site/reference/subsystems/web-server.md +434 -306
  458. package/kb/site/reference/subsystems/web.md +268 -210
  459. package/kb/site/reference/subsystems/workflow.md +287 -282
  460. package/kb/site/reference/subsystems/workspace.md +743 -651
  461. package/kb/site/reference/tool-catalog.md +2872 -2835
  462. package/kb/site/reference/tool-execution-pipeline.md +4 -3
  463. package/lib/index.js +359 -244
  464. package/lib/kb-version.js +118 -0
  465. package/package.json +68 -66
  466. package/scripts/refresh-kb.mjs +153 -0
  467. package/scripts/selfcheck.mjs +18 -0
  468. package/scripts/smoke.mjs +77 -0
  469. package/skills/dsh-plugin-dev-kb.md +71 -69
  470. package/skills/dsh-plugin-starter.md +65 -0
  471. package/skills/dsh-upgrade-assistant.md +62 -0
  472. package/kb/extra/agent-lifecycle.md +0 -91
  473. package/kb/extra/agent-lifecycle.zh.md +0 -93
  474. package/kb/extra/api-gateway.md +0 -172
  475. package/kb/extra/api-gateway.zh.md +0 -178
  476. package/kb/extra/architecture.md +0 -165
  477. package/kb/extra/architecture.zh.md +0 -169
  478. package/kb/extra/capability-seams.md +0 -714
  479. package/kb/extra/capability-seams.zh.md +0 -716
  480. package/kb/extra/config-catalog.md +0 -4801
  481. package/kb/extra/config-catalog.zh.md +0 -4803
  482. package/kb/extra/cookbook/adding-a-package.md +0 -170
  483. package/kb/extra/cookbook/adding-a-package.zh.md +0 -170
  484. package/kb/extra/cookbook/adding-a-settings-card.md +0 -72
  485. package/kb/extra/cookbook/adding-a-settings-card.zh.md +0 -72
  486. package/kb/extra/cookbook/adding-a-tool.md +0 -101
  487. package/kb/extra/cookbook/adding-a-tool.zh.md +0 -103
  488. package/kb/extra/cookbook/adding-an-llm-adapter.md +0 -43
  489. package/kb/extra/cookbook/adding-an-llm-adapter.zh.md +0 -43
  490. package/kb/extra/cookbook/extension-cookbook.md +0 -132
  491. package/kb/extra/cookbook/extension-cookbook.zh.md +0 -136
  492. package/kb/extra/cordis-api/context.md +0 -364
  493. package/kb/extra/cordis-api/context.zh.md +0 -366
  494. package/kb/extra/cordis-api/events.md +0 -207
  495. package/kb/extra/cordis-api/events.zh.md +0 -209
  496. package/kb/extra/cordis-api/fiber.md +0 -375
  497. package/kb/extra/cordis-api/fiber.zh.md +0 -377
  498. package/kb/extra/cordis-api/inherited.md +0 -38
  499. package/kb/extra/cordis-api/registry.md +0 -152
  500. package/kb/extra/cordis-api/registry.zh.md +0 -154
  501. package/kb/extra/cordis-api/service.md +0 -102
  502. package/kb/extra/cordis-api/service.zh.md +0 -104
  503. package/kb/extra/cordis-tutorial/01-first-plugin.md +0 -95
  504. package/kb/extra/cordis-tutorial/01-first-plugin.zh.md +0 -95
  505. package/kb/extra/cordis-tutorial/02-lifecycle-and-effects.md +0 -98
  506. package/kb/extra/cordis-tutorial/02-lifecycle-and-effects.zh.md +0 -98
  507. package/kb/extra/cordis-tutorial/03-services.md +0 -98
  508. package/kb/extra/cordis-tutorial/03-services.zh.md +0 -98
  509. package/kb/extra/cordis-tutorial/04-events.md +0 -144
  510. package/kb/extra/cordis-tutorial/04-events.zh.md +0 -144
  511. package/kb/extra/cordis-tutorial/05-config.md +0 -111
  512. package/kb/extra/cordis-tutorial/05-config.zh.md +0 -111
  513. package/kb/extra/cordis-tutorial/06-composition-and-hmr.md +0 -113
  514. package/kb/extra/cordis-tutorial/06-composition-and-hmr.zh.md +0 -113
  515. package/kb/extra/cordis-tutorial/07-into-the-harness.md +0 -108
  516. package/kb/extra/cordis-tutorial/07-into-the-harness.zh.md +0 -108
  517. package/kb/extra/cordis-tutorial/index.md +0 -60
  518. package/kb/extra/cordis-tutorial/index.zh.md +0 -62
  519. package/kb/extra/experimental-persistence-catalog.md +0 -17
  520. package/kb/extra/experimental-persistence-catalog.zh.md +0 -17
  521. package/kb/extra/persistence-catalog.md +0 -9140
  522. package/kb/extra/persistence-catalog.zh.md +0 -9142
  523. package/kb/extra/subsystems/README.md +0 -76
  524. package/kb/extra/subsystems/README.zh.md +0 -76
  525. package/kb/extra/subsystems/approval.md +0 -170
  526. package/kb/extra/subsystems/approval.zh.md +0 -170
  527. package/kb/extra/subsystems/client-modules.md +0 -198
  528. package/kb/extra/subsystems/client-modules.zh.md +0 -198
  529. package/kb/extra/subsystems/client-resources.md +0 -92
  530. package/kb/extra/subsystems/client-resources.zh.md +0 -92
  531. package/kb/extra/subsystems/commands.md +0 -223
  532. package/kb/extra/subsystems/commands.zh.md +0 -223
  533. package/kb/extra/subsystems/compaction.md +0 -284
  534. package/kb/extra/subsystems/compaction.zh.md +0 -284
  535. package/kb/extra/subsystems/conversation.md +0 -301
  536. package/kb/extra/subsystems/conversation.zh.md +0 -303
  537. package/kb/extra/subsystems/core.md +0 -1113
  538. package/kb/extra/subsystems/core.zh.md +0 -1125
  539. package/kb/extra/subsystems/credentials.md +0 -493
  540. package/kb/extra/subsystems/credentials.zh.md +0 -493
  541. package/kb/extra/subsystems/filesystem.md +0 -530
  542. package/kb/extra/subsystems/filesystem.zh.md +0 -530
  543. package/kb/extra/subsystems/goal.md +0 -313
  544. package/kb/extra/subsystems/goal.zh.md +0 -313
  545. package/kb/extra/subsystems/jobs.md +0 -554
  546. package/kb/extra/subsystems/jobs.zh.md +0 -554
  547. package/kb/extra/subsystems/llm-streaming.md +0 -1196
  548. package/kb/extra/subsystems/llm-streaming.zh.md +0 -1202
  549. package/kb/extra/subsystems/lsp.md +0 -202
  550. package/kb/extra/subsystems/lsp.zh.md +0 -202
  551. package/kb/extra/subsystems/office-to-pdf.md +0 -87
  552. package/kb/extra/subsystems/office-to-pdf.zh.md +0 -87
  553. package/kb/extra/subsystems/permission-presets.md +0 -167
  554. package/kb/extra/subsystems/permission-presets.zh.md +0 -167
  555. package/kb/extra/subsystems/persistence.md +0 -418
  556. package/kb/extra/subsystems/persistence.zh.md +0 -418
  557. package/kb/extra/subsystems/plan.md +0 -87
  558. package/kb/extra/subsystems/plan.zh.md +0 -87
  559. package/kb/extra/subsystems/ptc-runtime.md +0 -250
  560. package/kb/extra/subsystems/ptc-runtime.zh.md +0 -250
  561. package/kb/extra/subsystems/sandbox.md +0 -221
  562. package/kb/extra/subsystems/sandbox.zh.md +0 -221
  563. package/kb/extra/subsystems/schedule.md +0 -550
  564. package/kb/extra/subsystems/schedule.zh.md +0 -550
  565. package/kb/extra/subsystems/scope.md +0 -59
  566. package/kb/extra/subsystems/scope.zh.md +0 -61
  567. package/kb/extra/subsystems/session-projection.md +0 -356
  568. package/kb/extra/subsystems/session-projection.zh.md +0 -356
  569. package/kb/extra/subsystems/session-query.md +0 -511
  570. package/kb/extra/subsystems/session-query.zh.md +0 -511
  571. package/kb/extra/subsystems/session-reference.md +0 -224
  572. package/kb/extra/subsystems/session-reference.zh.md +0 -224
  573. package/kb/extra/subsystems/session-telemetry.md +0 -212
  574. package/kb/extra/subsystems/session-telemetry.zh.md +0 -212
  575. package/kb/extra/subsystems/session-title.md +0 -213
  576. package/kb/extra/subsystems/session-title.zh.md +0 -213
  577. package/kb/extra/subsystems/session.md +0 -1339
  578. package/kb/extra/subsystems/session.zh.md +0 -1343
  579. package/kb/extra/subsystems/settings.md +0 -155
  580. package/kb/extra/subsystems/settings.zh.md +0 -155
  581. package/kb/extra/subsystems/shell.md +0 -314
  582. package/kb/extra/subsystems/shell.zh.md +0 -314
  583. package/kb/extra/subsystems/sidebar-right.md +0 -160
  584. package/kb/extra/subsystems/sidebar-right.zh.md +0 -160
  585. package/kb/extra/subsystems/skills.md +0 -352
  586. package/kb/extra/subsystems/skills.zh.md +0 -352
  587. package/kb/extra/subsystems/slots.md +0 -200
  588. package/kb/extra/subsystems/slots.zh.md +0 -204
  589. package/kb/extra/subsystems/spill.md +0 -124
  590. package/kb/extra/subsystems/spill.zh.md +0 -124
  591. package/kb/extra/subsystems/storage.md +0 -259
  592. package/kb/extra/subsystems/storage.zh.md +0 -259
  593. package/kb/extra/subsystems/subagent.md +0 -686
  594. package/kb/extra/subsystems/subagent.zh.md +0 -688
  595. package/kb/extra/subsystems/subprocess.md +0 -321
  596. package/kb/extra/subsystems/subprocess.zh.md +0 -321
  597. package/kb/extra/subsystems/system-prompt.md +0 -254
  598. package/kb/extra/subsystems/system-prompt.zh.md +0 -254
  599. package/kb/extra/subsystems/terminal.md +0 -184
  600. package/kb/extra/subsystems/terminal.zh.md +0 -184
  601. package/kb/extra/subsystems/token-meter.md +0 -106
  602. package/kb/extra/subsystems/token-meter.zh.md +0 -106
  603. package/kb/extra/subsystems/tools.md +0 -747
  604. package/kb/extra/subsystems/tools.zh.md +0 -747
  605. package/kb/extra/subsystems/typert.md +0 -690
  606. package/kb/extra/subsystems/typert.zh.md +0 -690
  607. package/kb/extra/subsystems/user-questions.md +0 -307
  608. package/kb/extra/subsystems/user-questions.zh.md +0 -307
  609. package/kb/extra/subsystems/web-client.md +0 -100
  610. package/kb/extra/subsystems/web-client.zh.md +0 -100
  611. package/kb/extra/subsystems/web-server.md +0 -302
  612. package/kb/extra/subsystems/web-server.zh.md +0 -302
  613. package/kb/extra/subsystems/web.md +0 -206
  614. package/kb/extra/subsystems/web.zh.md +0 -206
  615. package/kb/extra/subsystems/workflow.md +0 -278
  616. package/kb/extra/subsystems/workflow.zh.md +0 -278
  617. package/kb/extra/subsystems/workspace.md +0 -647
  618. package/kb/extra/subsystems/workspace.zh.md +0 -647
  619. package/kb/extra/tool-catalog.md +0 -2824
  620. package/kb/extra/tool-catalog.zh.md +0 -2832
  621. package/kb/extra/tool-execution-pipeline.md +0 -65
  622. package/kb/extra/tool-execution-pipeline.zh.md +0 -67
@@ -1,751 +1,902 @@
1
- ---
2
- editSource: "docs/subsystems/tools.md"
3
- rawMarkdownPath: "en/reference/subsystems/tools.md"
4
- outline: [2,3]
5
- ---
6
-
7
- # Tools
8
-
9
- The tool pipeline of [dsh-tools](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/core/tools). [core.md](./core.md) introduces `ToolDefinition` as the pipeline-authoring type shared by the core packages; the model-facing [`ToolSchema`](./llm-streaming.md#the-model-request-and-result) wire type is declared with the model request. This page documents every `ToolDefinition` field, the typed schema DSL that builds it, the guarded execution types, and the UI-presentation types.
10
-
11
- Source: [`packages/core/tools/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/index.ts) · [`packages/core/tools/src/schema.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/schema.ts) · [`packages/core/tools/src/presentation.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/presentation.ts)
12
-
13
- ## `ToolDefinition` — a registered tool
14
-
15
- A `ToolSchema` (the model-facing fields) plus a mandatory canonical output declaration, the `execute` function, host-only scheduler metadata, an optional final-content callback, and optional UI presenters. The registry holds these; the loop dispatches calls through them. The registry's `schemas()` builds the model-facing `ToolSchema[]` by an explicit allowlist — `output`/`execute`/`projectContent`/`finalizeContent`/`timeoutMs`/`isConcurrencySafe`/`presentCall`/`presentResult` must never leak into a model request.
16
-
17
- ```ts type-equiv
18
- /** Tool-owned canonical output contract used after the body returns a JSON value. */
19
- interface ToolOutputDefinition {
20
- /** Raw supported JSON Schema enforced against every successful canonical value. */
21
- readonly schema: JsonSchemaNode
22
- /** Pure projection from validated arguments and value to Native/model content. */
23
- render(args: unknown, value: JsonValue): ContentBlock[]
24
- /** Pure replayable presentation projection for native and nested calls. */
25
- presentationMeta?(args: unknown, value: JsonValue): JsonValue
26
- }
27
- ```
28
-
29
- ```ts type-equiv
30
- /** A registered tool: its schema plus the execution function. */
31
- interface ToolDefinition extends ToolSchema {
32
- /** Mandatory canonical output declaration. */
33
- readonly output: ToolOutputDefinition
34
- /**
35
- * Run one accepted call and return only its canonical lossless-JSON value.
36
- * Async work must observe or forward `exec.signal` and settle only after its
37
- * owned work reaches quiescence. The registry preserves caller cancellation
38
- * through around-dispatch signal replacement and does not abandon this
39
- * promise, but it cannot hard-kill same-process code.
40
- * @param args - losslessly snapshotted, frozen model arguments.
41
- * @param exec - execution identity, cancellation signal, and context deferral.
42
- * @returns the canonical value declared by `output.schema`.
43
- */
44
- execute(args: unknown, exec: ToolRunContext): Promise<unknown>
45
- /**
46
- * Install execution-prepared content before `tools/post-execute` policies.
47
- * The callback is captured when the call starts and runs once for a
48
- * normalized outcome entering post-execute. Policy replacements remain
49
- * authoritative; pipeline failures that bypass post-execute skip projection.
50
- * @param exec - immutable execution identity and arguments.
51
- * @param result - normalized result before post-execute policy.
52
- * @returns replacement content, or undefined to preserve the renderer output.
53
- */
54
- projectContent?(exec: Readonly<ToolExecution>, result: Readonly<ToolExecutionResult>): ContentBlock[] | undefined
55
- /**
56
- * Synchronous last-mile transform for model-facing content. The registry
57
- * snapshots this callback when execution starts and invokes it exactly once
58
- * for every normalized outcome, including pipeline failures that bypass
59
- * `tools/post-execute`, immediately before lossless materialization.
60
- * Returning `undefined` preserves the content; every other result field
61
- * remains registry-owned. The callback must be total and must not throw.
62
- * @param exec - immutable execution identity and arguments.
63
- * @param result - complete normalized outcome before materialization.
64
- * @returns replacement content, or `undefined` to preserve it.
65
- */
66
- finalizeContent?(exec: Readonly<ToolExecution>, result: Readonly<ToolExecutionResult>): ContentBlock[] | undefined
67
- /**
68
- * Cooperative tool-call timeout budget in milliseconds. Omit for no deadline.
69
- * Enforced by `@deepseek-ai/dsh-tool-call-timeout-policy` (a `tools/execute` wrapper); it
70
- * is NEVER sent to the model — `schemas()` whitelists only name/description/
71
- * parameters. Declaring it asserts this tool forwards `exec.signal` to a
72
- * cooperative implementation that can reach quiescence when the signal aborts.
73
- */
74
- timeoutMs?: number
75
- /**
76
- * Pure synchronous classifier for overlap with sibling tool calls. Only
77
- * `true` opts in; omission, exceptions, non-`true` returns, and invalid
78
- * `defineTool` arguments are exclusive. This metadata is never model-visible.
79
- *
80
- * Opted-in executions must not mutate parent-owned state. Shared state must
81
- * tolerate concurrent dispatch; recorder races are permitted only when they
82
- * commute or fail closed. See the
83
- * [parallel-tool-call Agent Note](../../../../.agents/notes/implemented/feature/2026-07-10-parallel-tool-call-execution.md)
84
- * for the full contract.
85
- * @param args - parsed arguments; `defineTool` validates before calling.
86
- * @returns Whether this call may join a parallel group.
87
- */
88
- isConcurrencySafe?(args: unknown): boolean
89
- /**
90
- * Optional: how to present the PENDING state of one call in a UI, derived from
91
- * the call's `args` (parsed arguments, `unknown` — the tool validates/narrows
92
- * its own input). Returns a {@link ToolCallView} (a `card`-tagged render intent),
93
- * or `undefined` (or omit the method) to fall back to a generic presentation
94
- * (title = tool name, raw args as input). Pure and side-effect-free: a UI may
95
- * call it during live streaming AND a session-log replay, so it must depend
96
- * only on `args`.
97
- */
98
- presentCall?(args: unknown): ToolCallView | undefined
99
- /**
100
- * Optional: how to present the COMPLETED state, given the same `args` and the
101
- * durable result projection (`content`, failure state, and optional `meta`). Returns a
102
- * {@link ToolResultView}, or `undefined` (or omit the method) to keep the
103
- * pending title and render the raw result content. Pure and side-effect-free
104
- * for the same replay reason.
105
- */
106
- presentResult?(args: unknown, result: ToolResult): ToolResultView | undefined
107
- }
108
- ```
109
-
110
- `execute` receives `args: unknown` — a raw `ToolDefinition` validates its own input. First-party tools don't write that by hand; they use `defineTool`, which validates and narrows the arguments, infers the body return from `output.schema`, and types both output projectors. `finalizeContent` deliberately receives the immutable execution instead of typed arguments because invalid-input and outer pipeline failures reach it too; it may enforce a tool-owned content bound while preserving `isError`, canonical value, structured error identity, deferred contexts, and presentation metadata.
111
-
112
- ## The unified JSON-value schema DSL
113
-
114
- Plugin authors use one vocabulary for typed parameters and typed output values. `ValueSchemaSpec` supports `string`, `number`, `integer`, `boolean`, `null`, `array`, `object`, author-only `json`, and exact-one `oneOf`; scalar `enum` and `const` values must match their node type. An explicit object node always declares `additionalProperties: true | false`. Parameter definitions remain an implicit open object property map, with `required: true` attached to each required property.
115
-
116
- Source: [`packages/core/tools/src/schema.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/schema.ts)
117
-
118
- ```ts type-equiv
119
- /** One author-facing schema for any lossless JSON value root. */
120
- type ValueSchemaSpec =
121
- | StringValueSchemaSpec
122
- | NumberValueSchemaSpec
123
- | IntegerValueSchemaSpec
124
- | BooleanValueSchemaSpec
125
- | NullValueSchemaSpec
126
- | ArrayValueSchemaSpec
127
- | ObjectValueSchemaSpec
128
- | JsonValueSchemaSpec
129
- | OneOfValueSchemaSpec
130
- ```
131
-
132
- ```ts type-equiv
133
- /** One implicit parameter-root property, optionally required. */
134
- type ParameterPropertySpec = ValueSchemaSpec & { required?: true }
135
- ```
136
-
137
- ```ts type-equiv
138
- /**
139
- * Tool parameter schema. The map itself is an implicit open object root;
140
- * requiredness remains a per-property `required: true` annotation.
141
- */
142
- type ParameterSchemaSpec = {
143
- [key: string]: ParameterPropertySpec
144
- [key: symbol]: never
145
- }
146
- ```
147
-
148
- `{ type: 'json' }` infers `JsonValue` and compiles to an annotation-only unconstrained raw schema. Output roots can be objects, arrays, scalars, or null. `InferValue<S>` honors literal constraints and object openness through 16 container levels, then falls back to `JsonValue` instead of exhausting TypeScript's type-instantiation stack. `InferArgs<P>` turns per-property requiredness into required and optional string keys:
149
-
150
- ```ts type-equiv
151
- /**
152
- * Infer the TypeScript value accepted by an author-facing value schema. Exact
153
- * inference is bounded to 16 container levels, then falls back to `JsonValue`.
154
- */
155
- type InferValue<S> = InferValueAt<S, []>
156
- ```
157
-
158
- ```ts type-equiv
159
- /** Infer the TypeScript argument object for an implicit parameter schema. */
160
- type InferArgs<S> = InferProperties<S, []>
161
- ```
162
-
163
- `defineTool({ name, description, parameters, output, execute, … })` ties parameter inference to `parameterSchemaSpecToJsonSchema()` and `validateArgs()`, and ties `execute`/`render`/`presentationMeta` to `InferValue<OutputSchema>`. Schema records contain only own enumerable string keys, and schema arrays are dense intrinsic arrays, so inference, compilation, and validation observe the same declaration. Inference stays exact through 16 container levels and then widens to `JsonValue`; runtime validation keeps walking the complete schema. `valueSchemaSpecToJsonSchema()` compiles output declarations through the same enforced raw subset. A parameter mismatch throws `ToolArgsError` (`INVALID_ARGS`); an invalid body or post-policy value throws `ToolOutputError` (`INVALID_TOOL_OUTPUT`). Both use the normal tool-error path. Raw JSON Schema remains open by default; unsupported keywords reject instead of being accepted without enforcement.
164
-
165
- Registration is a trusted same-process contract. The registry borrows the typed definition as readonly input, requires `output`, validates its raw schema, and checks semantic requirements such as a positive finite `timeoutMs`; `schemas()` constructs the model-facing projection when building a request, so execution and presentation share one resolved definition without leaking callbacks onto the wire.
166
-
167
- ## `ToolRestriction` — one scope's live filter over what it inherits
168
-
169
- `ToolRestriction` applies to the tools a scope inherits: the deployment-global layer plus every ancestor scope on its chain. The registry compiles readonly names into private sets, intersects multiple restrictions, then overlays the scope's OWN registrations, which stay exempt so a delegated child keeps the tools it answers through. A deny-only filter admits later unlisted inherited tools, while an allow-list excludes them.
170
-
171
- ```ts type-equiv
172
- /**
173
- * Per-scope filter over global tools. Restrictions intersect and do not affect
174
- * scoped registrations or the reserved PTC mode transport.
175
- */
176
- interface ToolRestriction {
177
- /** Global tool names that stay visible; everything else is removed. */
178
- readonly allow?: readonly string[]
179
- /** Global tool names removed from visibility. */
180
- readonly deny?: readonly string[]
181
- }
182
- ```
183
-
184
- ## Execution: extensible waterfalls plus monotonic policy
185
-
186
- `ctx.tools.execute()` accepts a caller-owned `ToolExecutionInput` with a required readonly `signal`, materializes its parsed JSON arguments once into a pipeline-owned `ToolExecution`, and runs that call through `tools/pre-execute` (the reorderable allow/deny/ask waterfall) → registered monotonic guards → `tools/execute` (around-dispatch wrappers) → `projectContent` → `tools/post-execute` (inspect/replace the result) → optional definition-owned `finalizeContent` → `tools/result` (the immutable authoritative outcome). Only the `tools/execute` view may replace the required signal. The outcome is a `ToolExecutionResult`.
187
-
188
- ```ts type-equiv
189
- /** Opaque call identity that permits correlation without exposing mutable execution state. */
190
- type ToolExecutionToken = symbol & { readonly [toolExecutionTokenBrand]: true }
191
- ```
192
-
193
- ```ts type-equiv
194
- /**
195
- * Caller-supplied description of one tool call. {@link ToolRuntime.execute}
196
- * adds the registry-owned token to form a pipeline {@link ToolExecution};
197
- * callers do not choose that token.
198
- */
199
- interface ToolExecutionInput {
200
- readonly callId: ToolCallId
201
- /**
202
- * Root model-requested call owning this execution tree. Callers omit it for
203
- * a root execution; nested dispatchers propagate the enclosing value.
204
- */
205
- readonly rootCallId?: ToolCallId
206
- readonly name: string
207
- /** Binding-time tool schema for a PTC inner call; frozen by its producer and never logged. */
208
- readonly schema?: ToolSchema
209
- /** Losslessly JSON-serializable parsed arguments (tools validate their own schema). */
210
- readonly arguments: unknown
211
- /** The agent on whose behalf the call runs (set by the agent loop). */
212
- readonly agent?: Agent
213
- /**
214
- * Opaque token of the enclosing transport execution, when one exists. PTC
215
- * mode sets this on SDK sub-dispatches so commit-style observers can wait for
216
- * the outer `run_code` outcome without receiving its live mutable execution.
217
- * The token also marks the call as a transport sub-dispatch rather than a
218
- * model-direct call: under `mode: 'ptc'`, only calls WITH a parent may
219
- * execute a native tool name — a model-direct call (no parent) is denied as
220
- * `UNKNOWN_TOOL` before the policy pipeline. See {@link ToolRuntime.execute}.
221
- */
222
- readonly parent?: ToolExecutionToken
223
- /** Required caller-owned cancellation for this invocation. */
224
- readonly signal: AbortSignal
225
- }
226
- ```
227
-
228
- A tool body receives the runtime extension. `deferContext()` attaches context to the execution's own result — the composite-tool nested-dispatch channel, also usable by a leaf tool minting a plugin-sourced instruction — without injecting inside the still-open outer call.
229
-
230
- ```ts type-equiv
231
- /**
232
- * Runtime context handed to a tool implementation after the registry has
233
- * accepted a {@link ToolExecution}. {@link deferContext} attaches context to
234
- * this execution's own result — a composite tool ferries nested-dispatch
235
- * context back to the outer result, and a leaf tool may mint a fresh
236
- * plugin-sourced instruction; the loop appends it only after the
237
- * `tool/result`.
238
- */
239
- interface ToolRunContext extends ToolExecution {
240
- /**
241
- * Defer one context — typically a nested-dispatch context ferried by a
242
- * composite tool, or a fresh plugin-sourced instruction — until this tool's
243
- * final result reaches the agent loop. Contexts retain their individual
244
- * source and metadata and are emitted in call order.
245
- */
246
- deferContext(context: UserMessage): void
247
- /**
248
- * Mark a successful final result as terminal for the current agent turn.
249
- * The marker rides this execution's own result (`concludesTurn` exists only
250
- * on {@link ToolExecutionSuccess}); a composite that dispatches nested
251
- * calls forwards it from the nested result, exactly like
252
- * `additionalContexts`, so only an authoritative nested success can
253
- * conclude the enclosing run.
254
- */
255
- concludeTurn(): void
256
- }
257
- ```
258
-
259
- The agent loop asks the registry for each pending call's execution mode and uses it to form exclusive barriers and rolling-pool parallel runs:
260
-
261
- ```ts type-equiv
262
- /**
263
- * Scheduling mode for one pending call. `parallel` may overlap with siblings;
264
- * `exclusive` runs alone and forms an ordering barrier.
265
- */
266
- type ToolExecutionMode =
267
- | { kind: 'parallel' }
268
- | { kind: 'exclusive' }
269
- ```
270
-
271
- PTC bindings freeze their ToolSchema at construction and pass it through the scheduler into `ToolExecution.schema`; it is transient execution metadata. Before policy, each actually started sub-dispatch records only pairing ids, name, and normalized arguments. Neither start nor settle events serialize description, parameters, or schema. The bridge later exposes the settled call to the `tools/ptc-dispatch-log` waterfall, which may change the durable content copy while preserving the program value, model-visible outer result, and structured failure identity:
272
-
273
- ```ts type-equiv
274
- /**
275
- * One settled `run_code` sub-dispatch about to be logged, as seen by the
276
- * `tools/ptc-dispatch-log` waterfall: the parent execution (session owner,
277
- * outer call identity), the sub-call identity, and the outcome whose durable
278
- * copy a listener may reshape. `content` is the RENDERED result projection
279
- * (what a native `tool/result` would carry) — the program itself received
280
- * the structured `value` (or just the error message on failure); only the
281
- * `tool/ptc-dispatch` event's copy changes.
282
- */
283
- interface PtcDispatchLog {
284
- /** The outer `run_code` execution. */
285
- readonly exec: ToolExecution
286
- /** The calling agent (the scope routing key and the spill owner), when the outer call has one. */
287
- readonly agent?: Agent
288
- /** Opaque sub-call id; new calls use `<parent>:ptc:<n>`. */
289
- readonly subCallId: ToolCallId
290
- /** The dispatched sub-tool name. */
291
- readonly name: string
292
- /** Whether the sub-call settled as an error. */
293
- readonly isError: boolean
294
- /** The sub-call's complete model-facing content (the settle event's default payload). */
295
- readonly content: ContentBlock[]
296
- }
297
- ```
298
-
299
- ```ts type-equiv
300
- /**
301
- * One pending tool call inside the registry pipeline. Parsed arguments cross
302
- * one lossless-JSON materialization boundary before policy and are deep-frozen;
303
- * call identity, the caller signal, and the registry-assigned {@link token} are
304
- * readonly. The registry freezes the complete object before `tools/result`
305
- * observers run.
306
- */
307
- interface ToolExecution extends ToolExecutionInput {
308
- /** Root model-requested call, resolved for every root and nested execution. */
309
- readonly rootCallId: ToolCallId
310
- /** Registry-assigned identity shared with nested calls only as their opaque `parent` token. */
311
- readonly token: ToolExecutionToken
312
- }
313
- ```
314
-
315
- ```ts type-equiv
316
- /**
317
- * Around-dispatch view of a {@link ToolExecution}. A `tools/execute` wrapper
318
- * may replace the signal for its delegated lifetime, but it cannot remove it.
319
- * The registry fuses every replacement with the captured caller signal.
320
- */
321
- interface ToolDispatchExecution extends Omit<ToolExecution, 'signal'> {
322
- /** Cancellation signal visible to the next wrapper or tool body. */
323
- signal: AbortSignal
324
- }
325
- ```
326
-
327
- `ToolExecutionToken` is an opaque runtime `Symbol` used only for identity comparison. Before policy, `execute()` materializes and freezes arguments, rejects non-JSON input, and assigns the token. Identity fields, the required caller signal, and the optional parent token remain readonly. A `ToolDispatchExecution` wrapper may replace but not remove the signal; the registry re-fuses the caller signal before invoking the body. Final observers receive the frozen execution identity.
328
-
329
- A `ToolGuard` is scope-aware final pre-dispatch policy. Its return type deliberately has no allow result: `undefined` preserves the waterfall decision, while a returned reason can only reduce permission, so a later listener cannot undo it.
330
-
331
- ```ts type-equiv
332
- /**
333
- * A monotonic execution guard evaluated after every `tools/pre-execute`
334
- * listener and before the tool body. Returning a reason denies the call;
335
- * returning `undefined` leaves it unchanged. Because guards have no allow
336
- * result, listener ordering cannot turn a denial back into permission.
337
- * @param execution - the identity-protected call after extensible pre-execute policy completed.
338
- * @returns a final denial reason, or `undefined` to leave the call allowed.
339
- */
340
- type ToolGuard = (execution: Readonly<ToolExecution>) => string | undefined
341
- ```
342
-
343
- ```ts type-equiv
344
- /** Canonical failure detail; internal routing information remains optional. */
345
- interface ToolFailure {
346
- /** Human-readable failure message without the Native `Error: ` envelope. */
347
- message: string
348
- /** Internal error class/code used by policy and durable diagnostics. */
349
- info?: ToolErrorInfo
350
- }
351
- ```
352
-
353
- ```ts type-equiv
354
- /** Successful canonical tool execution, including its Native/model projection. */
355
- interface ToolExecutionSuccess {
356
- readonly isError: false
357
- /** Execution-local canonical value; deliberately omitted from durable events. */
358
- readonly value: JsonValue
359
- readonly content: ContentBlock[]
360
- readonly error?: never
361
- readonly meta?: JsonValue
362
- readonly additionalContexts?: UserMessage[]
363
- /** The agent loop stops after committing this successful result batch. */
364
- readonly concludesTurn?: true
365
- }
366
- ```
367
-
368
- ```ts type-equiv
369
- /** Failed canonical tool execution; failures never carry a successful value. */
370
- interface ToolExecutionFailure {
371
- readonly isError: true
372
- readonly error: ToolFailure
373
- readonly value?: never
374
- readonly content: ContentBlock[]
375
- readonly meta?: JsonValue
376
- readonly additionalContexts?: UserMessage[]
377
- readonly concludesTurn?: never
378
- }
379
- ```
380
-
381
- ```ts type-equiv
382
- /** The discriminated, execution-local outcome of one tool call. */
383
- type ToolExecutionResult = ToolExecutionSuccess | ToolExecutionFailure
384
- ```
385
-
386
- ```ts type-equiv
387
- /** Structured error metadata for a failed tool call (alongside the model-facing text). */
388
- interface ToolErrorInfo {
389
- name: string
390
- code: string
391
- /** Optional raw user-facing detail; durable projections preserve it but model-facing content does not include it. */
392
- reason?: string
393
- }
394
- ```
395
-
396
- The result carries only the outcome. Call identity remains on the immutable `ToolExecution` that accompanies it through every hook and on the durable `tool/call` / `tool/result` session events, so wrappers cannot create a second, disagreeing identity. The canonical `value` is execution-local: the loop persists only `content`, `error`, and `meta`, while `tool/ptc-dispatch` stores the sub-call's rendered `content`, `isError`, optional structured `error`, and presentation `meta`. Replay reproduces presentation but cannot reconstruct canonical intermediate values. Optional `ToolErrorInfo.reason` retains raw user-facing detail without adding it to model-facing content.
397
-
398
- On success the registry snapshots and validates the body value, freezes it, and invokes the pure renderer plus the optional presentation metadata projector for native and nested calls. It separately materializes the durable presentation fields immediately before `tools/result`; an invalid value, renderer/projector failure, or non-JSON presentation becomes a JSON-safe `isError`. The final live observer therefore sees the exact execution-local value beside fields safe for the later durable append.
399
-
400
- Before final content, the registry materializes the candidate result; a failure in content, structured error, additional context, or presentation metadata becomes a JSON-safe `isError` result that still reaches `finalizeContent`. The registry invokes that callback exactly once, then materializes and freezes the accepted result immediately before `tools/result`, so the observed live outcome is safe for the later durable `tool/result` append.
401
-
402
- Each interception waterfall returns a typed **Decision** (the idiom shared with the `agent/*` waterfalls). `tools/pre-execute` listeners receive `(exec, next)` and return a `PreToolDecision`; `tools/execute` wrappers return a `ToolExecutionResult`; `tools/post-execute` listeners receive `(exec, result, next)` and return a `PostToolDecision`:
403
-
404
- ```ts type-equiv
405
- /**
406
- * Pre-dispatch decision. `allow` runs the call; `deny` materializes its
407
- * model-facing reason and optional structured error identity; `cancel` selects
408
- * the canonical cancellation result without presenting a policy denial; `ask`
409
- * runs only after an approval service returns `allowed-once` and otherwise
410
- * denies; its `reason` is the audited approval reason and its optional
411
- * `displayReason` is the localized prompt text. Input rewriting is excluded because arguments are already logged and
412
- * presented.
413
- */
414
- type PreToolDecision =
415
- | { kind: 'allow' }
416
- | { kind: 'deny'; reason: string; info?: ToolErrorInfo }
417
- | { kind: 'cancel' }
418
- | { kind: 'ask'; reason?: string; displayReason?: { readonly en: string; readonly [locale: string]: string } }
419
- ```
420
-
421
- ```ts type-equiv
422
- /**
423
- * Post-dispatch decision: accept, replace one projection, attach context for the
424
- * next request, or block by turning corrective feedback into an error result.
425
- */
426
- type PostToolDecision =
427
- | { kind: 'accept'; content?: ContentBlock[]; value?: never; additionalContexts?: UserMessage[] }
428
- | { kind: 'accept'; value: JsonValue; content?: never; additionalContexts?: UserMessage[] }
429
- | { kind: 'block'; feedback: ContentBlock[]; additionalContexts?: UserMessage[] }
430
- ```
431
-
432
- Call `next()` for the default or return a decision to short-circuit. Pre-policy may deny or ask; only `allowed-once` proceeds, while a non-grant, missing approval channel or service, or agent-less request becomes a denial. A deny may attach structured identity and user-facing detail without changing its model-facing reason. Guards may still impose a final denial. Arguments cannot be rewritten because history, audit, UI, and execution must agree.
433
-
434
- Post-policy may replace either content or value, never both. Content replacement preserves the canonical value and existing metadata; value replacement is revalidated and recomputes content/metadata; a block removes the value and becomes an `isError` containing corrective feedback. Content replacement is presentation policy, not confidentiality policy: a listener that must hide the programmatic value blocks or replaces it. `tools/result` receives the frozen execution and result after normalization; observers cannot transform them, and observer failures are contained. Unknown and throwing tools both become structured errors (`ToolNotFoundError` maps to `UNKNOWN_TOOL`), so the call fails without ending the turn.
435
-
436
- ## The enforced raw JSON Schema subset
437
-
438
- Raw schemas from subagents, workflows, MCP, and dynamic registrations use the wire-level counterpart of the author DSL. `assertSupportedJsonSchema()` accepts any JSON root, `validateJsonSchemaValue()` enforces it, and `JsonSchemaError` reports every unsupported or malformed schema path. The empty annotation-only node means unconstrained lossless JSON. `oneOf` requires at least two branches and a value must match exactly one. Consumers that still require an object root call `assertObjectJsonSchema()` and carry `ObjectJsonSchema`; this is how subagent/workflow caller-defined structured output remains object-rooted without restricting the shared vocabulary.
439
-
440
- ```ts type-equiv
441
- /** Scalar JSON values supported by `enum` and `const`. */
442
- type JsonSchemaScalar = string | number | boolean | null
443
- ```
444
-
445
- ```ts type-equiv
446
- /** Single-type keywords accepted by the enforced subset. */
447
- type JsonSchemaType = 'object' | 'array' | 'string' | 'number' | 'integer' | 'boolean' | 'null'
448
- ```
449
-
450
- ```ts type-equiv
451
- /**
452
- * One raw JSON Schema node in the enforced subset. The optional fields express
453
- * the external wire schema; {@link assertSupportedJsonSchema} rejects invalid
454
- * combinations before a caller treats the node as trusted.
455
- */
456
- interface JsonSchemaNode {
457
- /** Omit with no constraints for any JSON value, or use `oneOf`. */
458
- type?: JsonSchemaType
459
- /** Exactly one branch must validate; at least two branches are required. */
460
- oneOf?: JsonSchemaNode[]
461
- /** Nested property schemas (`type: 'object'` only). */
462
- properties?: Record<string, JsonSchemaNode>
463
- /** Required property names; each must appear in `properties`. */
464
- required?: string[]
465
- /** `false` rejects undeclared keys; absent/`true` follows JSON Schema's open default. */
466
- additionalProperties?: boolean
467
- /** Item schema (`type: 'array'` only); absent accepts any JSON item. */
468
- items?: JsonSchemaNode
469
- /** Allowed values for a scalar node. */
470
- enum?: JsonSchemaScalar[]
471
- /** The single allowed value for a scalar node. */
472
- const?: JsonSchemaScalar
473
- /** Annotation, ignored for validation. */
474
- description?: string
475
- /** Annotation, ignored for validation. */
476
- title?: string
477
- /** Annotation, ignored for validation but required to be lossless JSON. */
478
- default?: JsonValue
479
- /** Annotation, ignored for validation but required to be lossless JSON. */
480
- examples?: JsonValue
481
- }
482
- ```
483
-
484
- ```ts type-equiv
485
- /** A consumer-constrained object-rooted schema. */
486
- type ObjectJsonSchema = JsonSchemaNode & { type: 'object' }
487
- ```
488
-
489
- ## Tool-presentation UI vocabulary
490
-
491
- How a tool wants its call shown in a UI (an editor tool-call card, a CLI log line), provider-neutral so a tool describes itself without depending on any client protocol. `presentCall`/`presentResult` return a **`card`-tagged render intent** — a discriminated union a UI bridge switches on:
492
-
493
- - `ToolCallView` (pending): `{ card: 'generic', title, kind?, rawInput?, content?, locations? }` (the default card; `locations` is `{ path, line? }[]` files the call reads/modifies, for editor follow-along), `{ card: 'terminal', title, description?, cwd? }` (a shell command → a terminal card), or `{ card: 'diff', title, diffs, locations? }` (a file create/modify → an inline diff card; `diffs` is `{ path, oldText, newText }[]`, `oldText: null` for a new file).
494
- - `ToolResultView` (completed): `{ card: 'generic', title?, content? }`, `{ card: 'terminal', title?, output?, exitCode?, signal? }` (the captured run output + exit; a capable UI shows an exit-status pill, while another may derive a fenced ` ```console ` fallback), `{ card: 'diff', title?, diffs }` (a completed file mutation → the change to show, typically the applied hunks with context lines computed from the before/after content, or a whole-file diff when there is no before-image), `{ card: 'search', shape, title?, truncated, total, … }` (a completed discovery search → grouped-by-file matches for `shape: 'matches'` (grep) or a flat path list for `shape: 'paths'` (glob); `truncated`/`total` report whether the inline result was capped so a UI never presents a partial result as complete; the view carries no result text — a UI without a search card falls back to the raw result content), `{ card: 'read', title?, path, offset, lines, totalLines, lang?, content? }` (a completed file read → a line-numbered, optionally syntax-highlighted code view; `offset` is the 1-based first line the window requested, kept even when `lines` is empty; `lang` is a language hint from the extension, and `content` is the envelope-stripped text a UI without read support falls back to), or `{ card: 'web', kind: 'search' | 'fetch', title?, … }` (a completed web retrieval; `kind: 'search'` carries the structured `sources`/`answer?`/`truncated`, `kind: 'fetch'` carries `url`/`statusCode`/`truncated`, and a UI without the `web` capability falls back to the raw result content — the body is not duplicated into the view). Completed views replace pending views, so mutation tools return a diff result even when it duplicates the call-time snippet; a search and a web retrieval have no `card` call-time analogue (their pending state stays a generic card, since the structured result exists only after `execute`).
495
-
496
- `ToolCallKind` (`'read' | 'edit' | 'delete' | 'move' | 'search' | 'execute' | 'fetch' | 'other'`) picks an icon on a generic card. `FileLocation` (`{ path, line? }`), `FileDiff` (`{ path, oldText, newText }`), and `ReadFileLine` (`{ number, text }`, one 1-based numbered line of a read window) are the shared file-card vocabulary. The design is pinned in [the render-intent-union Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/architecture/2026-07-02-tool-render-intent-union.md); host/client runtimes project this neutral vocabulary into their own views.
497
-
498
- The full presentation field docs live in [`packages/core/tools/src/presentation.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/presentation.ts). The `bash` schema and executor are on [shell.md](./shell.md); generic background controls are on [jobs.md](./jobs.md).
499
-
500
- <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
501
-
502
- <a id="cordis-surface"></a>
503
-
504
- ## Cordis API
505
-
506
- 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).
507
-
508
- <a id="ctxtools--toolruntime"></a>
509
-
510
- ### `ctx.tools` — `ToolRuntime`
511
-
512
- Tool registry and execution pipeline. Scoped registrations shadow globals; one visibility resolver feeds presentation, lookup, and dispatch.
513
-
514
- ```ts cordis-catalog
515
- /**
516
- * Present the calling scope's tools in `mode` instead of the deployment
517
- * default. Nearest scope on the chain wins, so a preset's standing
518
- * declaration covers every agent joined under it.
519
- *
520
- * Scoped only, and one declaration per scope: this is how an agent preset
521
- * composes PTC mode agents beside native ones in the same process, and a
522
- * process-global override would be the `mode` config field instead.
523
- * @param mode - the presentation the covered agents' models see.
524
- * @returns the exact disposer that restores the deployment default.
525
- */
526
- presentAs(mode: ToolPresentationMode): () => void
527
-
528
- /**
529
- * Register globally or in the calling agent scope. Scoped tools shadow
530
- * globals; duplicates within one layer and the reserved `run_code` name fail.
531
- * @param definition - tool schema, execution, and optional finalization/presentation callbacks.
532
- * @returns the exact disposer that unregisters the tool.
533
- */
534
- register(definition: ToolDefinition): () => void
535
-
536
- /**
537
- * Restrict global tools for the calling agent scope. Empty filters, unknown
538
- * names, scope-local names, and reserved transport names fail. Restrictions
539
- * intersect; scoped registrations remain visible.
540
- * @param filter - global-tool mask: `allow` (keep only) and/or `deny` (remove).
541
- * @returns the exact disposer that lifts this restriction.
542
- */
543
- restrict(filter: ToolRestriction): () => void
544
-
545
- /**
546
- * Register a monotonic guard after the extensible `tools/pre-execute`
547
- * waterfall. A plain-context guard applies globally; one registered through
548
- * `agent.ctx` applies only to that agent. Any matching guard may deny by
549
- * returning a reason, while no guard can force-allow a call another guard
550
- * denied. The exact effect disposer is returned for ordered ownership and
551
- * HMR cleanup.
552
- * @param guard - synchronous check; a returned string denies the execution.
553
- * @returns the exact disposer that unregisters the guard.
554
- */
555
- guard(guard: ToolGuard): () => void
556
-
557
- /**
558
- * Look up a tool as one scope sees it (scoped
559
- * shadows global; a restricted-away global reads as absent). Presenters pass
560
- * the calling agent so the rendered card matches the definition that
561
- * actually executed.
562
- * @param name - the tool name as registered.
563
- * @param scope - the viewing scope (the agent); omitted = the global view.
564
- * @returns the definition the scope resolves, or undefined when none is visible.
565
- */
566
- get(name: string, scope?: ScopeKey): ToolDefinition | undefined
567
-
568
- /**
569
- * Project visible definitions onto the allowlisted model-facing schema fields,
570
- * excluding execution and presentation callbacks.
571
- * @param scope - the viewing scope (the agent); omitted = the global view.
572
- * @returns one deep-cloned schema per visible tool.
573
- */
574
- schemas(scope?: ScopeKey): ToolSchema[]
575
-
576
- /**
577
- * Classify a pending call through the caller's visible tool definition. Only
578
- * an exact `true` is parallel; unknown, hidden, undeclared, invalid, or
579
- * throwing classifiers are exclusive.
580
- * @param exec - call name, parsed arguments, and optional agent scope.
581
- * @returns the fail-closed scheduling mode.
582
- */
583
- executionMode(exec: ToolExecutionInput): ToolExecutionMode
584
-
585
- /**
586
- * Execute through pre-policy, guards, around-dispatch, post-policy,
587
- * definition-owned content finalization, and final notification. Tool and
588
- * listener failures resolve as materialized error results; an invisible tool
589
- * reports `UNKNOWN_TOOL`. The returned outcome is the same lossless, frozen
590
- * snapshot final observers receive. Cancellation
591
- * arriving after entry and before final result materialization skips a
592
- * not-yet-started body with `ABORTED_BEFORE_DISPATCH` or replaces a
593
- * successful started outcome with `ABORTED`; already-started work is still
594
- * drained and may retain a tool-owned structured error.
595
- * @param exec - the typed same-process call input. The registry assigns its
596
- * correlation token before policy begins.
597
- * @returns the materialized final result.
598
- */
599
- async execute(exec: ToolExecutionInput): Promise<ToolExecutionResult>
600
- ```
601
-
602
- Types: [ScopeKey](./scope.md)
603
-
604
- Source: [`packages/core/tools/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/index.ts)
605
-
606
- <a id="tools-events"></a>
607
-
608
- ### `tools/*` events
609
-
610
- <a id="toolschange--emit"></a>
611
-
612
- #### `tools/change` — emit
613
-
614
- A tool was registered or unregistered, or a scoped restriction changed (the available tool set changed — possibly for one scope only). An UNFILTERED registry-subject notification, deliberately not scope-filtered dispatch: a global change concerns every agent's next assembly, so a scoped listener subscribing here sees every change, not just its own scope's.
615
-
616
- ```ts cordis-catalog
617
- /**
618
- * A tool was registered or unregistered, or a scoped restriction changed
619
- * (the available tool set changed — possibly for one scope only). An
620
- * UNFILTERED registry-subject notification, deliberately not scope-filtered
621
- * dispatch: a global change concerns every agent's next assembly, so a
622
- * scoped listener subscribing here sees every change, not just its own
623
- * scope's.
624
- * @mode emit
625
- */
626
- 'tools/change'(): void
627
- ```
628
-
629
- Source: [`packages/core/tools/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/index.ts)
630
-
631
- <a id="toolsexecute--waterfall"></a>
632
-
633
- #### `tools/execute` — waterfall
634
-
635
- Around-dispatch waterfall for timeout, retry, or metrics. `next()` returns a normalized result; wrappers may change only `exec.signal`, while call identity remains immutable. The registry re-fuses the original caller signal before the body, so replacement cannot detach caller cancellation; wrappers must still restore their signal and reach quiescence. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent's calls.
636
-
637
- ```ts cordis-catalog
638
- /**
639
- * Around-dispatch waterfall for timeout, retry, or metrics. `next()` returns
640
- * a normalized result; wrappers may change only `exec.signal`, while call
641
- * identity remains immutable. The registry re-fuses the original caller
642
- * signal before the body, so replacement cannot detach caller cancellation;
643
- * wrappers must still restore their signal and reach quiescence.
644
- * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent's calls.
645
- * @param exec - the allowed call about to dispatch (name, parsed arguments, caller agent, signal).
646
- * @mode waterfall
647
- */
648
- 'tools/execute'(this: Scoped<ToolRuntime>, exec: ToolDispatchExecution, next: () => Promise<ToolExecutionResult>): Promise<ToolExecutionResult>
649
- ```
650
-
651
- Types: [Scoped](./scope.md)
652
-
653
- Source: [`packages/core/tools/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/index.ts)
654
-
655
- <a id="toolspost-execute--waterfall"></a>
656
-
657
- #### `tools/post-execute` — waterfall
658
-
659
- Accept, replace, enrich, or block a normalized dispatch result. `next()` accepts it unchanged; thrown tools still reach this waterfall as errors. Async listeners must observe `exec.signal`; after they settle, caller cancellation replaces only a successful accepted outcome with the code selected by whether the tool body was invoked. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent's calls.
660
-
661
- ```ts cordis-catalog
662
- /**
663
- * Accept, replace, enrich, or block a normalized dispatch result. `next()`
664
- * accepts it unchanged; thrown tools still reach this waterfall as errors. Async
665
- * listeners must observe `exec.signal`; after they settle, caller
666
- * cancellation replaces only a successful accepted outcome with the code
667
- * selected by whether the tool body was invoked.
668
- * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent's calls.
669
- * @param exec - the call that just ran (name, parsed arguments, caller agent).
670
- * @param result - the dispatch outcome a listener may accept, replace, or block.
671
- * @mode waterfall
672
- */
673
- 'tools/post-execute'(this: Scoped<ToolRuntime>, exec: ToolExecution, result: Readonly<ToolExecutionResult>, next: () => Promise<PostToolDecision>): Promise<PostToolDecision>
674
- ```
675
-
676
- Types: [Scoped](./scope.md)
677
-
678
- Source: [`packages/core/tools/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/index.ts)
679
-
680
- <a id="toolspre-execute--waterfall"></a>
681
-
682
- #### `tools/pre-execute` — waterfall
683
-
684
- Allow, deny, cancel, or ask before dispatch. `next()` delegates to allow; `cancel` selects the canonical pre-dispatch cancellation result, and missing approval support turns `ask` into denial. Async gates must observe `exec.signal`; the registry rechecks cancellation after they settle but never abandons their promise. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent's calls.
685
-
686
- ```ts cordis-catalog
687
- /**
688
- * Allow, deny, cancel, or ask before dispatch. `next()` delegates to allow;
689
- * `cancel` selects the canonical pre-dispatch cancellation result, and missing
690
- * approval support turns `ask` into denial. Async gates must observe
691
- * `exec.signal`; the registry rechecks cancellation after they settle but
692
- * never abandons their promise.
693
- * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent's calls.
694
- * @param exec - the pending call (name, parsed arguments, caller agent).
695
- * @mode waterfall
696
- */
697
- 'tools/pre-execute'(this: Scoped<ToolRuntime>, exec: ToolExecution, next: () => Promise<PreToolDecision>): Promise<PreToolDecision>
698
- ```
699
-
700
- Types: [Scoped](./scope.md)
701
-
702
- Source: [`packages/core/tools/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/index.ts)
703
-
704
- <a id="toolsptc-dispatch-log--waterfall"></a>
705
-
706
- #### `tools/ptc-dispatch-log` — waterfall
707
-
708
- Allow a listener to replace content in the DURABLE LOG COPY of one `run_code` sub-dispatch outcome before the bridge appends its `tool/ptc-dispatch` event. `next()` keeps the content unchanged; a listener may return replacement blocks (e.g. the spill policy's preview + locator for an oversized text result). Only the logged copy is affected — the program already received the complete value, and the model sees neither. A throwing listener is contained: the bridge falls back to logging the original settled content. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent's dispatches.
709
-
710
- ```ts cordis-catalog
711
- /**
712
- * Allow a listener to replace content in the DURABLE LOG COPY of one
713
- * `run_code` sub-dispatch outcome before the bridge appends its
714
- * `tool/ptc-dispatch` event. `next()` keeps the
715
- * content unchanged; a listener may return replacement blocks (e.g. the
716
- * spill policy's preview + locator for an oversized text result). Only the
717
- * logged copy is affected — the program already received the complete
718
- * value, and the model sees neither. A throwing listener is contained:
719
- * the bridge falls back to logging the original settled content.
720
- * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent's dispatches.
721
- * @param dispatch - the parent execution, sub-call identity, and the settled content to log.
722
- * @mode waterfall
723
- */
724
- 'tools/ptc-dispatch-log'(this: Scoped<ToolRuntime>, dispatch: PtcDispatchLog, next: () => Promise<ContentBlock[]>): Promise<ContentBlock[]>
725
- ```
726
-
727
- Types: [ContentBlock](./llm-streaming.md) · [Scoped](./scope.md)
728
-
729
- Source: [`packages/core/tools/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/index.ts)
730
-
731
- <a id="toolsresult--emit"></a>
732
-
733
- #### `tools/result` — emit
734
-
735
- Observe the frozen, lossless-JSON final outcome. Listener failures are contained. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): keyed by `exec.agent`.
736
-
737
- ```ts cordis-catalog
738
- /**
739
- * Observe the frozen, lossless-JSON final outcome. Listener failures are contained.
740
- * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): keyed by `exec.agent`.
741
- * @param exec - the execution object that traversed the pipeline.
742
- * @param result - a deep-frozen snapshot of the final returned result.
743
- * @mode emit
744
- */
745
- 'tools/result'(this: Scoped<ToolRuntime>, exec: Readonly<ToolExecution>, result: Readonly<ToolExecutionResult>): undefined
746
- ```
747
-
748
- Types: [Scoped](./scope.md)
749
-
750
- Source: [`packages/core/tools/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/index.ts)
751
- <!-- END GENERATED cordis-surface -->
1
+ ---
2
+ editSource: "docs/subsystems/tools.md"
3
+ rawMarkdownPath: "en/reference/subsystems/tools.md"
4
+ outline: [2,3]
5
+ ---
6
+
7
+ # Tools
8
+
9
+ The tool pipeline of [dsh-tools](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/core/tools). [core.md](./core.md) introduces `ToolDefinition` as the pipeline-authoring type shared by the core packages; the model-facing [`ToolSchema`](./llm-streaming.md#the-model-request-and-result) wire type is declared with the model request. This page documents every `ToolDefinition` field, the typed schema DSL that builds it, the guarded execution types, and the UI-presentation types.
10
+
11
+ Source: [`packages/core/tools/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/index.ts) · [`packages/core/tools/src/schema.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/schema.ts) · [`packages/core/tools/src/presentation.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/presentation.ts)
12
+
13
+ ## `ToolDefinition` — a registered tool
14
+
15
+ A `ToolSchema` (the model-facing fields) plus a mandatory canonical output declaration, the `execute` function, host-only scheduler metadata, an optional final-content callback, and optional UI presenters. The registry holds these; the loop dispatches calls through them. The registry's `schemas()` builds the model-facing `ToolSchema[]` by an explicit allowlist — `output`/`execute`/`projectContent`/`finalizeContent`/`timeoutMs`/`isConcurrencySafe`/`presentCall`/`presentResult` must never leak into a model request.
16
+
17
+ ```ts type-equiv
18
+ /** Tool-owned canonical output contract used after the body returns a JSON value. */
19
+ interface ToolOutputDefinition {
20
+ /** Raw supported JSON Schema enforced against every successful canonical value. */
21
+ readonly schema: JsonSchemaNode
22
+ /** Pure projection from validated arguments and value to Native/model content. */
23
+ render(args: unknown, value: JsonValue): ContentBlock[]
24
+ /** Pure replayable presentation projection for native and nested calls. */
25
+ presentationMeta?(args: unknown, value: JsonValue): JsonValue
26
+ }
27
+ ```
28
+
29
+ ```ts type-equiv
30
+ /** A registered tool: its schema plus the execution function. */
31
+ interface ToolDefinition extends ToolSchema {
32
+ /** Mandatory canonical output declaration. */
33
+ readonly output: ToolOutputDefinition
34
+ /**
35
+ * Run one accepted call and return only its canonical lossless-JSON value.
36
+ * Async work must observe or forward `exec.signal` and settle only after its
37
+ * owned work reaches quiescence. The executor preserves caller cancellation
38
+ * through around-dispatch signal replacement and does not abandon this
39
+ * promise, but it cannot hard-kill same-process code.
40
+ * @param args - losslessly snapshotted, frozen model arguments.
41
+ * @param exec - execution identity, cancellation signal, and context deferral.
42
+ * @returns the canonical value declared by `output.schema`.
43
+ */
44
+ execute(args: unknown, exec: ToolRunContext): Promise<unknown>
45
+ /**
46
+ * Install execution-prepared content before `tools/post-execute` policies.
47
+ * The callback is captured when the call starts and runs once for a
48
+ * normalized outcome entering post-execute. Policy replacements remain
49
+ * authoritative; pipeline failures that bypass post-execute skip projection.
50
+ * @param exec - immutable execution identity and arguments.
51
+ * @param result - normalized result before post-execute policy.
52
+ * @returns replacement content, or undefined to preserve the renderer output.
53
+ */
54
+ projectContent?(exec: Readonly<ToolExecution>, result: Readonly<ToolExecutionResult>): ContentBlock[] | undefined
55
+ /**
56
+ * Synchronous last-mile transform for model-facing content. The executor
57
+ * snapshots this callback when execution starts and invokes it exactly once
58
+ * for every normalized outcome, including pipeline failures that bypass
59
+ * `tools/post-execute`, immediately before lossless materialization.
60
+ * Returning `undefined` preserves the content; every other result field
61
+ * remains executor-owned. The callback must be total and must not throw.
62
+ * @param exec - immutable execution identity and arguments.
63
+ * @param result - complete normalized outcome before materialization.
64
+ * @returns replacement content, or `undefined` to preserve it.
65
+ */
66
+ finalizeContent?(exec: Readonly<ToolExecution>, result: Readonly<ToolExecutionResult>): ContentBlock[] | undefined
67
+ /**
68
+ * Cooperative tool-call timeout budget in milliseconds. Omit for no deadline.
69
+ * Enforced by `@deepseek-ai/dsh-tool-call-timeout-policy` (a `tools/execute` wrapper); it
70
+ * is NEVER sent to the model — `schemas()` whitelists only name/description/
71
+ * parameters. Declaring it asserts this tool forwards `exec.signal` to a
72
+ * cooperative implementation that can reach quiescence when the signal aborts.
73
+ */
74
+ timeoutMs?: number
75
+ /**
76
+ * Pure synchronous classifier for overlap with sibling tool calls. Only
77
+ * `true` opts in; omission, exceptions, non-`true` returns, and invalid
78
+ * `defineTool` arguments are exclusive. This metadata is never model-visible.
79
+ *
80
+ * Opted-in executions must not mutate parent-owned state. Shared state must
81
+ * tolerate concurrent dispatch; recorder races are permitted only when they
82
+ * commute or fail closed. See the
83
+ * [parallel-tool-call Agent Note](../../../../.agents/notes/implemented/feature/2026-07-10-parallel-tool-call-execution.md)
84
+ * for the full contract.
85
+ * @param args - parsed arguments; `defineTool` validates before calling.
86
+ * @returns Whether this call may join a parallel group.
87
+ */
88
+ isConcurrencySafe?(args: unknown): boolean
89
+ /**
90
+ * Optional: how to present the PENDING state of one call in a UI, derived from
91
+ * the call's `args` (parsed arguments, `unknown` — the tool validates/narrows
92
+ * its own input). Returns a {@link ToolCallView} (a `card`-tagged render intent),
93
+ * or `undefined` (or omit the method) to fall back to a generic presentation
94
+ * (title = tool name, raw args as input). Pure and side-effect-free: a UI may
95
+ * call it during live streaming AND a session-log replay, so it must depend
96
+ * only on `args`.
97
+ */
98
+ presentCall?(args: unknown): ToolCallView | undefined
99
+ /**
100
+ * Optional: how to present the COMPLETED state, given the same `args` and the
101
+ * durable result projection (`content`, failure state, and optional `meta`). Returns a
102
+ * {@link ToolResultView}, or `undefined` (or omit the method) to keep the
103
+ * pending title and render the raw result content. Pure and side-effect-free
104
+ * for the same replay reason.
105
+ */
106
+ presentResult?(args: unknown, result: ToolResult): ToolResultView | undefined
107
+ }
108
+ ```
109
+
110
+ `execute` receives `args: unknown` — a raw `ToolDefinition` validates its own input. First-party tools don't write that by hand; they use `defineTool`, which validates and narrows the arguments, infers the body return from `output.schema`, and types both output projectors. `finalizeContent` deliberately receives the immutable execution instead of typed arguments because invalid-input and outer pipeline failures reach it too; it may enforce a tool-owned content bound while preserving `isError`, canonical value, structured error identity, deferred contexts, and presentation metadata.
111
+
112
+ ## The unified JSON-value schema DSL
113
+
114
+ Plugin authors use one vocabulary for typed parameters and typed output values. `ValueSchemaSpec` supports `string`, `number`, `integer`, `boolean`, `null`, `array`, `object`, author-only `json`, and exact-one `oneOf`; scalar `enum` and `const` values must match their node type. An explicit object node always declares `additionalProperties: true | false`. Parameter definitions remain an implicit open object property map, with `required: true` attached to each required property.
115
+
116
+ Source: [`packages/core/tools/src/schema.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/schema.ts)
117
+
118
+ ```ts type-equiv
119
+ /** One author-facing schema for any lossless JSON value root. */
120
+ type ValueSchemaSpec =
121
+ | StringValueSchemaSpec
122
+ | NumberValueSchemaSpec
123
+ | IntegerValueSchemaSpec
124
+ | BooleanValueSchemaSpec
125
+ | NullValueSchemaSpec
126
+ | ArrayValueSchemaSpec
127
+ | ObjectValueSchemaSpec
128
+ | JsonValueSchemaSpec
129
+ | OneOfValueSchemaSpec
130
+ ```
131
+
132
+ ```ts type-equiv
133
+ /** One implicit parameter-root property, optionally required. */
134
+ type ParameterPropertySpec = ValueSchemaSpec & { required?: true }
135
+ ```
136
+
137
+ ```ts type-equiv
138
+ /**
139
+ * Tool parameter schema. The map itself is an implicit open object root;
140
+ * requiredness remains a per-property `required: true` annotation.
141
+ */
142
+ type ParameterSchemaSpec = {
143
+ [key: string]: ParameterPropertySpec
144
+ [key: symbol]: never
145
+ }
146
+ ```
147
+
148
+ `{ type: 'json' }` infers `JsonValue` and compiles to an annotation-only unconstrained raw schema. Output roots can be objects, arrays, scalars, or null. `InferValue<S>` honors literal constraints and object openness through 16 container levels, then falls back to `JsonValue` instead of exhausting TypeScript's type-instantiation stack. `InferArgs<P>` turns per-property requiredness into required and optional string keys:
149
+
150
+ ```ts type-equiv
151
+ /**
152
+ * Infer the TypeScript value accepted by an author-facing value schema. Exact
153
+ * inference is bounded to 16 container levels, then falls back to `JsonValue`.
154
+ */
155
+ type InferValue<S> = InferValueAt<S, []>
156
+ ```
157
+
158
+ ```ts type-equiv
159
+ /** Infer the TypeScript argument object for an implicit parameter schema. */
160
+ type InferArgs<S> = InferProperties<S, []>
161
+ ```
162
+
163
+ `defineTool({ name, description, parameters, output, execute, … })` ties parameter inference to `parameterSchemaSpecToJsonSchema()` and `validateArgs()`, and ties `execute`/`render`/`presentationMeta` to `InferValue<OutputSchema>`. Schema records contain only own enumerable string keys, and schema arrays are dense intrinsic arrays, so inference, compilation, and validation observe the same declaration. Inference stays exact through 16 container levels and then widens to `JsonValue`; runtime validation keeps walking the complete schema. `valueSchemaSpecToJsonSchema()` compiles output declarations through the same enforced raw subset. A parameter mismatch throws `ToolArgsError` (`INVALID_ARGS`); an invalid body or post-policy value throws `ToolOutputError` (`INVALID_TOOL_OUTPUT`). Both use the normal tool-error path. Raw JSON Schema remains open by default; unsupported keywords reject instead of being accepted without enforcement.
164
+
165
+ Registration is a trusted same-process contract. The registry borrows the typed definition as readonly input, requires `output`, validates its raw schema, and checks semantic requirements such as a positive finite `timeoutMs`; `schemas()` constructs the model-facing projection when building a request, so execution and presentation share one resolved definition without leaking callbacks onto the wire.
166
+
167
+ ## `ToolRestriction` — one scope's live filter over what it inherits
168
+
169
+ `ToolRestriction` applies to the tools a scope inherits: the deployment-global layer plus every ancestor scope on its chain. The registry compiles readonly names into private sets, intersects multiple restrictions, then overlays the scope's OWN registrations, which stay exempt so a delegated child keeps the tools it answers through. A deny-only filter admits later unlisted inherited tools, while an allow-list excludes them.
170
+
171
+ ```ts type-equiv
172
+ /**
173
+ * Per-scope filter over global tools. Restrictions intersect and do not affect
174
+ * scoped registrations or the reserved PTC mode transport.
175
+ */
176
+ interface ToolRestriction {
177
+ /** Global tool names that stay visible; everything else is removed. */
178
+ readonly allow?: readonly string[]
179
+ /** Global tool names removed from visibility. */
180
+ readonly deny?: readonly string[]
181
+ }
182
+ ```
183
+
184
+ ## Conditional activation — step-owned admission
185
+
186
+ A registration may carry a `when` condition. AgentLoop calls `ctx.tools.resolve()` once per proposed step with the captured model selection; the returned set decides that step's tool declarations, executor sections, and every call in its batch, including PTC program subcalls. `ctx.tools.executable()` applies the set at execution and, without one, excludes conditional registrations. A same-name replacement or a new restriction stops unstarted calls from using an admitted registration, and the loop disposes the set once the step's batch settles.
187
+
188
+ ```ts type-equiv
189
+ /** Inputs for a tool's step-time activation condition. */
190
+ interface ToolActivationContext {
191
+ /** Agent preparing the step. */
192
+ readonly agent: Agent
193
+ /** Provider, model, and optional reasoning effort captured for the step. */
194
+ readonly modelSelection: Readonly<ModelSelection>
195
+ /** Cancellation of step preparation; asynchronous conditions must observe it. */
196
+ readonly signal: AbortSignal
197
+ }
198
+ ```
199
+
200
+ ```ts type-equiv
201
+ /** Lifecycle-owned conditions for a registered tool. */
202
+ interface ToolRegistrationOptions {
203
+ /**
204
+ * Decide whether the step's requests may call the tool. Omission enables
205
+ * it. False excludes it from both declarations and dispatch; rejection fails
206
+ * step preparation. Conditions must not mutate registrations or start tool work.
207
+ * @param context - preparing agent, captured model selection, and cancellation signal.
208
+ * @returns whether the tool participates in this step.
209
+ */
210
+ readonly when?: (context: ToolActivationContext) => boolean | Promise<boolean>
211
+ }
212
+ ```
213
+
214
+ ```ts type-equiv
215
+ /** One step's admitted registrations, also used by nested PTC calls. */
216
+ interface ResolvedToolSet {
217
+ /** Close admission after the step's tool batch settles. */
218
+ dispose(): void
219
+ /**
220
+ * Read admitted registrations that remain visible in their original scope.
221
+ * @param scope - exact requesting agent; another scope is never admitted.
222
+ * @returns original definitions excluding removed or restricted registrations.
223
+ */
224
+ view(scope: ScopeKey | undefined): ReadonlyMap<string, ToolDefinition>
225
+ }
226
+ ```
227
+
228
+ ## Executors and raw call batches
229
+
230
+ `ctx.tools.execute()` delegates a complete raw model-call batch to the nearest scoped executor. The service selects the current provider when each batch starts; prompt assembly returns only model input. `agent` is absent for standalone service calls; `log` is absent for programmatic calls outside a model step, such as initialization hooks. An Agent without `log` still scopes tool access but produces no root call/result events. Tool-owned events may still use its Session.
231
+
232
+ ```ts type-equiv
233
+ /** Model-call schemas produced by an executor. */
234
+ type ToolModelInput = Pick<ToolProviderResult, 'schemas' | 'knownNames'>
235
+ ```
236
+
237
+ ```ts type-equiv
238
+ /** Raw model calls, with optional Agent ownership and model-step logging. */
239
+ interface ToolBatchInput {
240
+ readonly calls: readonly ToolCallBlock[]
241
+ readonly signal: AbortSignal
242
+ /**
243
+ * Positive integer overriding the executor's concurrency limit for this batch.
244
+ * Applies to concurrency-safe root calls; program subcall limits remain separate.
245
+ * Undefined uses the executor's configured limit.
246
+ */
247
+ readonly maxParallelToolCalls?: number
248
+ /**
249
+ * Owning Agent supplies scoped tools and execution context, including outside a turn.
250
+ * Undefined for standalone calls outside an Agent, such as a service invocation.
251
+ */
252
+ readonly agent?: Agent
253
+ /**
254
+ * Step admission for every call in the batch, including program subcalls.
255
+ * Undefined admits only unconditional registrations.
256
+ */
257
+ readonly toolSet?: ResolvedToolSet
258
+ /**
259
+ * Committed model step receiving root call/result events; requires `agent`.
260
+ * Undefined when `agent` is absent or for calls outside a model response, such
261
+ * as session initialization hooks. Without `log`, root call/result events are
262
+ * omitted while `agent`, when provided, still supplies scope and execution context.
263
+ */
264
+ readonly log?: {
265
+ readonly turn: number
266
+ readonly step: number
267
+ }
268
+ }
269
+ ```
270
+
271
+ ```ts type-equiv
272
+ /** One settled result correlated with its original model call. */
273
+ interface ToolCallResult {
274
+ readonly callId: ToolCallId
275
+ readonly result: ToolExecutionResult
276
+ }
277
+ ```
278
+
279
+ ```ts type-equiv
280
+ /** Model-ordered outcomes and context accepted for the next step. */
281
+ interface ToolBatchResult {
282
+ readonly results: readonly ToolCallResult[]
283
+ readonly additionalContexts: readonly UserMessage[]
284
+ readonly concluded: boolean
285
+ }
286
+ ```
287
+
288
+ ```ts type-equiv
289
+ /** A plugin owns argument parsing, dispatch, scheduling, cancellation, and logging. */
290
+ interface ToolExecutor {
291
+ /** Guidance registered and disposed with this executor; absent means no executor-owned sections. */
292
+ readonly sections?: readonly ToolPromptSection[]
293
+ /**
294
+ * Describe the model's callable tools.
295
+ * @param tools - currently visible capability definitions, after scoped restrictions.
296
+ * @returns schemas and names used to validate tool ordering.
297
+ */
298
+ describe(tools: readonly ToolDefinition[]): ToolModelInput
299
+ /**
300
+ * Execute a complete batch. With log, commit root call/result events to the
301
+ * Agent's Session; without log, omit those events. Tool-owned events may still
302
+ * use the owning Agent's Session. Return
303
+ * one outcome per input call in input order, including skipped calls on abort.
304
+ * Never settle while started work is still running. Internal failures reject
305
+ * with ToolBatchExecutionError after draining, preserving committed outcomes
306
+ * and context; callers must stop dependent work and repair missing log results.
307
+ * An explicit maxParallelToolCalls takes precedence over executor configuration.
308
+ * @param input - original calls, cancellation, optional concurrency override, Agent and logging step.
309
+ * @returns settled results, deferred context, and whether a success concludes the turn.
310
+ */
311
+ execute(input: ToolBatchInput): Promise<ToolBatchResult>
312
+ }
313
+ ```
314
+
315
+ ## Execution: extensible waterfalls plus monotonic policy
316
+
317
+ Built-in executors pass parsed `ToolExecutionInput` values to the shared `ToolExecutionPipeline`. The pipeline owns argument snapshots, execution identities, policy waterfalls, dispatch, and final-result notification, returning one `ToolExecutionResult` per invocation. Custom executors can implement their own execution; the public `ToolExecutor` requires only descriptions and batch execution.
318
+
319
+ ```ts type-equiv
320
+ /** Opaque call identity that permits correlation without exposing mutable execution state. */
321
+ type ToolExecutionToken = symbol & { readonly [toolExecutionTokenBrand]: true }
322
+ ```
323
+
324
+ ```ts type-equiv
325
+ /**
326
+ * Parsed input to the shared invocation pipeline. The pipeline
327
+ * adds its own token to form a {@link ToolExecution};
328
+ * callers do not choose that token.
329
+ */
330
+ interface ToolExecutionInput {
331
+ readonly callId: ToolCallId
332
+ /**
333
+ * Root model-requested call owning this execution tree. Callers omit it for
334
+ * a root execution; nested dispatchers propagate the enclosing value.
335
+ */
336
+ readonly rootCallId?: ToolCallId
337
+ readonly name: string
338
+ /** Binding-time tool schema for a PTC inner call; frozen by its producer and never logged. */
339
+ readonly schema?: ToolSchema
340
+ /** Losslessly JSON-serializable parsed arguments (tools validate their own schema). */
341
+ readonly arguments: unknown
342
+ /** The agent on whose behalf the call runs (set by the agent loop). */
343
+ readonly agent?: Agent
344
+ /** Step admission shared by Native and PTC dispatch. Conditional tools require it. */
345
+ readonly toolSet?: ResolvedToolSet
346
+ /**
347
+ * Opaque token of the enclosing transport execution, when one exists. PTC
348
+ * mode sets this on SDK sub-dispatches so commit-style observers can wait for
349
+ * the outer `run_code` outcome without receiving its live mutable execution.
350
+ * The token also marks the call as a transport sub-dispatch rather than a
351
+ * model-direct call: with the PTC executor selected, only calls with a parent may
352
+ * execute a native tool name — a model-direct call (no parent) is denied as
353
+ * `UNKNOWN_TOOL` before the policy pipeline.
354
+ */
355
+ readonly parent?: ToolExecutionToken
356
+ /** Required caller-owned cancellation for this invocation. */
357
+ readonly signal: AbortSignal
358
+ }
359
+ ```
360
+
361
+ A tool body receives the runtime extension. `deferContext()` attaches context to the execution's own result — the composite-tool nested-dispatch channel, also usable by a leaf tool minting a plugin-sourced instruction — without injecting inside the still-open outer call.
362
+
363
+ ```ts type-equiv
364
+ /**
365
+ * Runtime context handed to a tool implementation after the executor has
366
+ * accepted a {@link ToolExecution}. {@link deferContext} attaches context to
367
+ * this execution's own result — a composite tool ferries nested-dispatch
368
+ * context back to the outer result, and a leaf tool may mint a fresh
369
+ * plugin-sourced instruction; the loop appends it only after the
370
+ * `tool/result`.
371
+ */
372
+ interface ToolRunContext extends ToolExecution {
373
+ /**
374
+ * Defer one context — typically a nested-dispatch context ferried by a
375
+ * composite tool, or a fresh plugin-sourced instruction — until this tool's
376
+ * final result reaches the agent loop. Contexts retain their individual
377
+ * source and metadata and are emitted in call order.
378
+ */
379
+ deferContext(context: UserMessage): void
380
+ /**
381
+ * Mark a successful final result as terminal for the current agent turn.
382
+ * The marker rides this execution's own result (`concludesTurn` exists only
383
+ * on {@link ToolExecutionSuccess}); a composite that dispatches nested
384
+ * calls forwards it from the nested result, exactly like
385
+ * `additionalContexts`, so only an authoritative nested success can
386
+ * conclude the enclosing run.
387
+ */
388
+ concludeTurn(): void
389
+ }
390
+ ```
391
+
392
+ The agent loop asks the registry for each pending call's execution mode and uses it to form exclusive barriers and rolling-pool parallel runs:
393
+
394
+ ```ts type-equiv
395
+ /**
396
+ * Scheduling mode for one pending call. `parallel` may overlap with siblings;
397
+ * `exclusive` runs alone and forms an ordering barrier.
398
+ */
399
+ type ToolExecutionMode =
400
+ | { kind: 'parallel' }
401
+ | { kind: 'exclusive' }
402
+ ```
403
+
404
+ PTC bindings freeze their ToolSchema at construction and pass it through the scheduler into `ToolExecution.schema`; it is transient execution metadata. Before policy, each actually started sub-dispatch records only pairing ids, name, and normalized arguments. Neither start nor settle events serialize description, parameters, or schema. The bridge later exposes the settled call to the `tools/ptc-dispatch-log` waterfall, which may change the durable content copy while preserving the program value, model-visible outer result, and structured failure identity:
405
+
406
+ ```ts type-equiv
407
+ /**
408
+ * One settled `run_code` sub-dispatch about to be logged, as seen by the
409
+ * `tools/ptc-dispatch-log` waterfall: the parent execution (session owner,
410
+ * outer call identity), the sub-call identity, and the outcome whose durable
411
+ * copy a listener may reshape. `content` is the RENDERED result projection
412
+ * (what a native `tool/result` would carry) — the program itself received
413
+ * the structured `value` (or just the error message on failure); only the
414
+ * `tool/ptc-dispatch` event's copy changes.
415
+ */
416
+ interface PtcDispatchLog {
417
+ /** The outer `run_code` execution. */
418
+ readonly exec: ToolExecution
419
+ /** The calling agent (the scope routing key and the spill owner), when the outer call has one. */
420
+ readonly agent?: Agent
421
+ /** Opaque sub-call id; new calls use `<parent>:ptc:<n>`. */
422
+ readonly subCallId: ToolCallId
423
+ /** The dispatched sub-tool name. */
424
+ readonly name: string
425
+ /** Whether the sub-call settled as an error. */
426
+ readonly isError: boolean
427
+ /** The sub-call's complete model-facing content (the settle event's default payload). */
428
+ readonly content: ContentBlock[]
429
+ }
430
+ ```
431
+
432
+ ```ts type-equiv
433
+ /**
434
+ * One pending tool call inside the executor pipeline. Parsed arguments cross
435
+ * one lossless-JSON materialization boundary before policy and are deep-frozen;
436
+ * call identity, the caller signal, and the executor-assigned {@link token} are
437
+ * readonly. The executor freezes the complete object before `tools/result`
438
+ * observers run.
439
+ */
440
+ interface ToolExecution extends ToolExecutionInput {
441
+ /** Root model-requested call, resolved for every root and nested execution. */
442
+ readonly rootCallId: ToolCallId
443
+ /** Executor-assigned identity shared with nested calls only as their opaque `parent` token. */
444
+ readonly token: ToolExecutionToken
445
+ }
446
+ ```
447
+
448
+ ```ts type-equiv
449
+ /**
450
+ * Around-dispatch view of a {@link ToolExecution}. A `tools/execute` wrapper
451
+ * may replace the signal for its delegated lifetime, but it cannot remove it.
452
+ * The executor fuses every replacement with the captured caller signal.
453
+ */
454
+ interface ToolDispatchExecution extends Omit<ToolExecution, 'signal'> {
455
+ /** Cancellation signal visible to the next wrapper or tool body. */
456
+ signal: AbortSignal
457
+ }
458
+ ```
459
+
460
+ `ToolExecutionToken` is an opaque runtime `Symbol` used only for identity comparison. Before policy, `execute()` materializes and freezes arguments, rejects non-JSON input, and assigns the token. Identity fields, the required caller signal, and the optional parent token remain readonly. A `ToolDispatchExecution` wrapper may replace but not remove the signal; the registry re-fuses the caller signal before invoking the body. Final observers receive the frozen execution identity.
461
+
462
+ A `ToolGuard` is scope-aware final pre-dispatch policy. Its return type deliberately has no allow result: `undefined` preserves the waterfall decision, while a returned reason or `ToolGuardDenial` can only reduce permission, so a later listener cannot undo it. A denial's optional `info` becomes the failed result's structured error identity.
463
+
464
+ ```ts type-equiv
465
+ /**
466
+ * A monotonic execution guard evaluated after every `tools/pre-execute`
467
+ * listener and before the tool body. Returning a reason denies the call;
468
+ * returning `undefined` leaves it unchanged. Because guards have no allow
469
+ * result, listener ordering cannot turn a denial back into permission.
470
+ * @param execution - the identity-protected call after extensible pre-execute policy completed.
471
+ * @returns a final denial reason, a denial with structured error identity, or `undefined` to leave the call allowed.
472
+ */
473
+ type ToolGuard = (execution: Readonly<ToolExecution>) => string | ToolGuardDenial | undefined
474
+ ```
475
+
476
+ ```ts type-equiv
477
+ /** A guard denial: the model-facing reason and optional structured error identity recorded on the result. */
478
+ interface ToolGuardDenial {
479
+ /** Model-facing reason rendered as the failed call's content. */
480
+ readonly reason: string
481
+ /** Structured error identity persisted beside the reason. */
482
+ readonly info?: ToolErrorInfo
483
+ }
484
+ ```
485
+
486
+ ```ts type-equiv
487
+ /** Canonical failure detail; internal routing information remains optional. */
488
+ interface ToolFailure {
489
+ /** Human-readable failure message without the Native `Error: ` envelope. */
490
+ message: string
491
+ /** Internal error class/code used by policy and durable diagnostics. */
492
+ info?: ToolErrorInfo
493
+ }
494
+ ```
495
+
496
+ ```ts type-equiv
497
+ /** Successful canonical tool execution, including its Native/model projection. */
498
+ interface ToolExecutionSuccess {
499
+ readonly isError: false
500
+ /** Execution-local canonical value; deliberately omitted from durable events. */
501
+ readonly value: JsonValue
502
+ readonly content: ContentBlock[]
503
+ readonly error?: never
504
+ readonly meta?: JsonValue
505
+ readonly additionalContexts?: UserMessage[]
506
+ /** The agent loop stops after committing this successful result batch. */
507
+ readonly concludesTurn?: true
508
+ }
509
+ ```
510
+
511
+ ```ts type-equiv
512
+ /** Failed canonical tool execution; failures never carry a successful value. */
513
+ interface ToolExecutionFailure {
514
+ readonly isError: true
515
+ readonly error: ToolFailure
516
+ readonly value?: never
517
+ readonly content: ContentBlock[]
518
+ readonly meta?: JsonValue
519
+ readonly additionalContexts?: UserMessage[]
520
+ readonly concludesTurn?: never
521
+ }
522
+ ```
523
+
524
+ ```ts type-equiv
525
+ /** The discriminated, execution-local outcome of one tool call. */
526
+ type ToolExecutionResult = ToolExecutionSuccess | ToolExecutionFailure
527
+ ```
528
+
529
+ ```ts type-equiv
530
+ /** Structured error metadata for a failed tool call (alongside the model-facing text). */
531
+ interface ToolErrorInfo {
532
+ name: string
533
+ code: string
534
+ /** Optional raw user-facing detail; durable projections preserve it but model-facing content does not include it. */
535
+ reason?: string
536
+ }
537
+ ```
538
+
539
+ The result carries only the outcome. Call identity remains on the immutable `ToolExecution` that accompanies it through every hook and on the durable `tool/call` / `tool/result` session events, so wrappers cannot create a second, disagreeing identity. The canonical `value` is execution-local: the loop persists only `content`, `error`, and `meta`, while `tool/ptc-dispatch` stores the sub-call's rendered `content`, `isError`, optional structured `error`, and presentation `meta`. Replay reproduces presentation but cannot reconstruct canonical intermediate values. Optional `ToolErrorInfo.reason` retains raw user-facing detail without adding it to model-facing content. The registry sets `info` from a thrown `HarnessError` (its `name` and `code`), from a pre-execute `deny` that supplies it, and on its own cancellation results (`AbortError` with `ABORTED` or `ABORTED_BEFORE_DISPATCH`); when a started body throws the signal's reason or an `Error` named `AbortError` after cancellation, the result keeps that message and carries `AbortError` with `ABORTED`, and a `tools/execute` wrapper that throws such a value after caller cancellation gets the same identity, with `ABORTED_BEFORE_DISPATCH` when the body never started; a `tools/execute` wrapper may also return a result with `info`, such as the timeout policy's `TOOL_TIMEOUT`. An `ask` that approval does not grant becomes a denial with the name `ApprovalError`, which identifies the registry's denial and is not a thrown class, and `APPROVAL_REJECTED`, `APPROVAL_CANCELLED`, or `APPROVAL_UNAVAILABLE`. A guard denial or post-execute block carries `info` only when it supplies one; any other thrown value produces an `error` without `info`.
540
+
541
+ On success the registry snapshots and validates the body value, freezes it, and invokes the pure renderer plus the optional presentation metadata projector for native and nested calls. It separately materializes the durable presentation fields immediately before `tools/result`; an invalid value, renderer/projector failure, or non-JSON presentation becomes a JSON-safe `isError`. The final live observer therefore sees the exact execution-local value beside fields safe for the later durable append.
542
+
543
+ Before final content, the registry materializes the candidate result; a failure in content, structured error, additional context, or presentation metadata becomes a JSON-safe `isError` result that still reaches `finalizeContent`. The registry invokes that callback exactly once, then materializes and freezes the accepted result immediately before `tools/result`, so the observed live outcome is safe for the later durable `tool/result` append.
544
+
545
+ Each interception waterfall returns a typed **Decision** (the idiom shared with the `agent/*` waterfalls). `tools/pre-execute` listeners receive `(exec, next)` and return a `PreToolDecision`; `tools/execute` wrappers return a `ToolExecutionResult`; `tools/post-execute` listeners receive `(exec, result, next)` and return a `PostToolDecision`:
546
+
547
+ ```ts type-equiv
548
+ /**
549
+ * Pre-dispatch decision. `allow` runs the call; `deny` materializes its
550
+ * model-facing reason and optional structured error identity; `cancel` selects
551
+ * the canonical cancellation result without presenting a policy denial; `ask`
552
+ * runs only after an approval service returns `allowed-once` and otherwise
553
+ * denies; its `reason` is the audited approval reason and its optional
554
+ * `displayReason` is the localized prompt text. Input rewriting is excluded because arguments are already logged and
555
+ * presented.
556
+ */
557
+ type PreToolDecision =
558
+ | { kind: 'allow' }
559
+ | { kind: 'deny'; reason: string; info?: ToolErrorInfo }
560
+ | { kind: 'cancel' }
561
+ | { kind: 'ask'; reason?: string; displayReason?: { readonly en: string; readonly [locale: string]: string } }
562
+ ```
563
+
564
+ ```ts type-equiv
565
+ /**
566
+ * Post-dispatch decision: accept, replace one projection, attach context for the
567
+ * next request, or block by turning corrective feedback into an error result
568
+ * whose optional `info` is its structured error identity.
569
+ */
570
+ type PostToolDecision =
571
+ | { kind: 'accept'; content?: ContentBlock[]; value?: never; additionalContexts?: UserMessage[] }
572
+ | { kind: 'accept'; value: JsonValue; content?: never; additionalContexts?: UserMessage[] }
573
+ | { kind: 'block'; feedback: ContentBlock[]; info?: ToolErrorInfo; additionalContexts?: UserMessage[] }
574
+ ```
575
+
576
+ Call `next()` for the default or return a decision to short-circuit. Pre-policy may deny or ask; only `allowed-once` proceeds, while a non-grant, missing approval channel or service, or agent-less request becomes a denial. A deny may attach structured identity and user-facing detail without changing its model-facing reason. Guards may still impose a final denial. Arguments cannot be rewritten because history, audit, UI, and execution must agree.
577
+
578
+ Post-policy may replace either content or value, never both. Content replacement preserves the canonical value and existing metadata; value replacement is revalidated and recomputes content/metadata; a block removes the value and becomes an `isError` containing corrective feedback. Content replacement is presentation policy, not confidentiality policy: a listener that must hide the programmatic value blocks or replaces it. `tools/result` receives the frozen execution and result after normalization; observers cannot transform them, and observer failures are contained. Unknown and throwing tools both become structured errors (`ToolNotFoundError` maps to `UNKNOWN_TOOL`), so the call fails without ending the turn. A tool body whose composition or call lacks a required Agent, service, or open turn throws `ToolContextUnavailableError` (`TOOL_CONTEXT_UNAVAILABLE`).
579
+
580
+ ## The enforced raw JSON Schema subset
581
+
582
+ Raw schemas from subagents, workflows, MCP, and dynamic registrations use the wire-level counterpart of the author DSL. `assertSupportedJsonSchema()` accepts any JSON root, `validateJsonSchemaValue()` enforces it, and `JsonSchemaError` reports every unsupported or malformed schema path. The empty annotation-only node means unconstrained lossless JSON. `oneOf` requires at least two branches and a value must match exactly one. Consumers that still require an object root call `assertObjectJsonSchema()` and carry `ObjectJsonSchema`; this is how subagent/workflow caller-defined structured output remains object-rooted without restricting the shared vocabulary.
583
+
584
+ ```ts type-equiv
585
+ /** Scalar JSON values supported by `enum` and `const`. */
586
+ type JsonSchemaScalar = string | number | boolean | null
587
+ ```
588
+
589
+ ```ts type-equiv
590
+ /** Single-type keywords accepted by the enforced subset. */
591
+ type JsonSchemaType = 'object' | 'array' | 'string' | 'number' | 'integer' | 'boolean' | 'null'
592
+ ```
593
+
594
+ ```ts type-equiv
595
+ /**
596
+ * One raw JSON Schema node in the enforced subset. The optional fields express
597
+ * the external wire schema; {@link assertSupportedJsonSchema} rejects invalid
598
+ * combinations before a caller treats the node as trusted.
599
+ */
600
+ interface JsonSchemaNode {
601
+ /** Omit with no constraints for any JSON value, or use `oneOf`. */
602
+ type?: JsonSchemaType
603
+ /** Exactly one branch must validate; at least two branches are required. */
604
+ oneOf?: JsonSchemaNode[]
605
+ /** Nested property schemas (`type: 'object'` only). */
606
+ properties?: Record<string, JsonSchemaNode>
607
+ /** Required property names; each must appear in `properties`. */
608
+ required?: string[]
609
+ /** `false` rejects undeclared keys; absent/`true` follows JSON Schema's open default. */
610
+ additionalProperties?: boolean
611
+ /** Item schema (`type: 'array'` only); absent accepts any JSON item. */
612
+ items?: JsonSchemaNode
613
+ /** Allowed values for a scalar node. */
614
+ enum?: JsonSchemaScalar[]
615
+ /** The single allowed value for a scalar node. */
616
+ const?: JsonSchemaScalar
617
+ /** Annotation, ignored for validation. */
618
+ description?: string
619
+ /** Annotation, ignored for validation. */
620
+ title?: string
621
+ /** Annotation, ignored for validation but required to be lossless JSON. */
622
+ default?: JsonValue
623
+ /** Annotation, ignored for validation but required to be lossless JSON. */
624
+ examples?: JsonValue
625
+ }
626
+ ```
627
+
628
+ ```ts type-equiv
629
+ /** A consumer-constrained object-rooted schema. */
630
+ type ObjectJsonSchema = JsonSchemaNode & { type: 'object' }
631
+ ```
632
+
633
+ ## Tool-presentation UI vocabulary
634
+
635
+ How a tool wants its call shown in a UI (an editor tool-call card, a CLI log line), provider-neutral so a tool describes itself without depending on any client protocol. `presentCall`/`presentResult` return a **`card`-tagged render intent** — a discriminated union a UI bridge switches on:
636
+
637
+ - `ToolCallView` (pending): `{ card: 'generic', title, kind?, rawInput?, content?, locations? }` (the default card; `locations` is `{ path, line? }[]` files the call reads/modifies, for editor follow-along), `{ card: 'terminal', title, description?, cwd? }` (a shell command → a terminal card), or `{ card: 'diff', title, diffs, locations? }` (a file create/modify → an inline diff card; `diffs` is `{ path, oldText, newText }[]`, `oldText: null` for a new file).
638
+ - `ToolResultView` (completed): `{ card: 'generic', title?, content? }`, `{ card: 'terminal', title?, output?, exitCode?, signal? }` (the captured run output + exit; a capable UI shows an exit-status pill, while another may derive a fenced ` ```console ` fallback), `{ card: 'diff', title?, diffs }` (a completed file mutation → the change to show, typically the applied hunks with context lines computed from the before/after content, or a whole-file diff when there is no before-image), `{ card: 'search', shape, title?, truncated, total, … }` (a completed discovery search → grouped-by-file matches for `shape: 'matches'` (grep) or a flat path list for `shape: 'paths'` (glob); `truncated`/`total` report whether the inline result was capped so a UI never presents a partial result as complete; the view carries no result text — a UI without a search card falls back to the raw result content), `{ card: 'read', title?, path, offset, lines, totalLines, lang?, content? }` (a completed file read → a line-numbered, optionally syntax-highlighted code view; `offset` is the 1-based first line the window requested, kept even when `lines` is empty; `lang` is a language hint from the extension, and `content` is the envelope-stripped text a UI without read support falls back to), or `{ card: 'web', kind: 'search' | 'fetch', title?, … }` (a completed web retrieval; `kind: 'search'` carries the structured `sources`/`answer?`/`truncated`, `kind: 'fetch'` carries `url`/`statusCode`/`truncated`, and a UI without the `web` capability falls back to the raw result content — the body is not duplicated into the view). Completed views replace pending views, so mutation tools return a diff result even when it duplicates the call-time snippet; a search and a web retrieval have no `card` call-time analogue (their pending state stays a generic card, since the structured result exists only after `execute`).
639
+
640
+ `ToolCallKind` (`'read' | 'edit' | 'delete' | 'move' | 'search' | 'execute' | 'fetch' | 'other'`) picks an icon on a generic card. `FileLocation` (`{ path, line? }`), `FileDiff` (`{ path, oldText, newText }`), and `ReadFileLine` (`{ number, text }`, one 1-based numbered line of a read window) are the shared file-card vocabulary. The design is pinned in [the render-intent-union Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/architecture/2026-07-02-tool-render-intent-union.md); host/client runtimes project this neutral vocabulary into their own views.
641
+
642
+ The full presentation field docs live in [`packages/core/tools/src/presentation.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/presentation.ts). The `bash` schema and executor are on [shell.md](./shell.md); generic background controls are on [jobs.md](./jobs.md).
643
+
644
+ <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
645
+
646
+ <a id="cordis-surface"></a>
647
+
648
+ ## Cordis API
649
+
650
+ 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).
651
+
652
+ <a id="ctxtools--toolsservice"></a>
653
+
654
+ ### `ctx.tools` — `ToolsService`
655
+
656
+ Concrete tool registry and scoped executor dispatcher.
657
+
658
+ ```ts cordis-catalog
659
+ /**
660
+ * Register globally or in the calling agent scope. Scoped tools shadow
661
+ * globals; duplicates within one layer and the reserved `run_code` name fail.
662
+ * @param definition - tool schema, execution, and optional finalization/presentation callbacks.
663
+ * @param options - optional step-time activation condition.
664
+ * @returns the exact disposer that unregisters the tool.
665
+ */
666
+ register(definition: ToolDefinition, options: ToolRegistrationOptions = {}): () => void
667
+
668
+ /**
669
+ * Restrict global tools for the calling agent scope. Empty filters, unknown
670
+ * names, scope-local names, and reserved transport names fail. Restrictions
671
+ * intersect; scoped registrations remain visible.
672
+ * @param filter - global-tool mask: `allow` (keep only) and/or `deny` (remove).
673
+ * @returns the exact disposer that lifts this restriction.
674
+ */
675
+ restrict(filter: ToolRestriction): () => void
676
+
677
+ /**
678
+ * Look up a tool as one scope sees it (scoped
679
+ * shadows global; a restricted-away global reads as absent). Presenters pass
680
+ * the calling agent so the rendered card matches the definition that
681
+ * actually executed.
682
+ * @param name - the tool name as registered.
683
+ * @param scope - the viewing scope (the agent); omitted = the global view.
684
+ * @param toolSet - step admission; omit only to inspect registered definitions.
685
+ * @returns the definition the scope resolves, or undefined when none is visible.
686
+ */
687
+ get(name: string, scope?: ScopeKey, toolSet?: ResolvedToolSet): ToolDefinition | undefined
688
+
689
+ /**
690
+ * Resolve the definition a call may execute. With a step's admitted set, the
691
+ * set decides; without one, conditional registrations are unavailable.
692
+ * @param name - the tool name as registered.
693
+ * @param scope - the calling agent; omitted = the global view.
694
+ * @param toolSet - step admission, or omitted for a call outside a model step.
695
+ * @returns the executable definition, or undefined when the call must fail as `UNKNOWN_TOOL`.
696
+ */
697
+ executable(name: string, scope?: ScopeKey, toolSet?: ResolvedToolSet): ToolDefinition | undefined
698
+
699
+ /**
700
+ * Resolve conditions once for this step without changing shared registrations.
701
+ * Cancellation or a rejected condition publishes no partial selection. Removed
702
+ * registrations cannot be restored by a late condition result.
703
+ * @param context - preparing agent, captured model selection, and cancellation.
704
+ * @returns the complete selection; the caller disposes it after its tool batch settles.
705
+ */
706
+ async resolve(context: ToolActivationContext): Promise<ResolvedToolSet>
707
+
708
+ /**
709
+ * Read the visible capability definitions for descriptions and program bindings.
710
+ * @param scope - viewing Agent or preset; omitted selects the global view.
711
+ * @param toolSet - step admission; omit only to inspect registered definitions.
712
+ * @returns definitions after scoped shadowing and restrictions, limited to the step's admission when given.
713
+ */
714
+ definitions(scope?: ScopeKey, toolSet?: ResolvedToolSet): readonly ToolDefinition[]
715
+
716
+ /**
717
+ * Project visible definitions onto the allowlisted model-facing schema fields,
718
+ * excluding execution and presentation callbacks.
719
+ * @param scope - the viewing scope (the agent); omitted = the global view.
720
+ * @param toolSet - step admission, or omitted for registered-definition inspection.
721
+ * @returns one deep-cloned schema per visible tool.
722
+ */
723
+ schemas(scope?: ScopeKey, toolSet?: ResolvedToolSet): ToolSchema[]
724
+
725
+ /**
726
+ * Provide the executor for the calling scope; an unscoped contribution is the deployment default.
727
+ * Rendering any executor-owned section requires the viewing scope's selection to remain available.
728
+ * @param executor - initialized provider owned by the contributing plugin.
729
+ * @returns the effect disposer. Unloading leaves the selection unavailable until it is replaced.
730
+ */
731
+ setExecutor(executor: ToolExecutor): () => void
732
+
733
+ /**
734
+ * Delegate a raw call batch to its Agent's provider or the deployment default.
735
+ * Select at dispatch; accepted batches settle through that provider even if it unloads.
736
+ * @param input - original calls, optional owning Agent, and optional logging step.
737
+ * @returns the selected executor's settled batch; unavailable selections reject.
738
+ */
739
+ async execute(input: ToolBatchInput): Promise<ToolBatchResult>
740
+
741
+ /**
742
+ * Register a monotonic denial in the calling scope.
743
+ * @param guard - evaluated after extensible pre-execute policy by the shared pipeline.
744
+ * @returns the effect disposer that removes this guard.
745
+ */
746
+ guard(guard: ToolGuard): () => void
747
+
748
+ /**
749
+ * Check global and inherited guards after pre-execute policy and approval resolve.
750
+ * @param exec - invocation whose guards are checked before dispatch.
751
+ * @returns the first denial with its optional structured identity, or undefined when no guard denies.
752
+ */
753
+ checkGuards(exec: ToolExecution): ToolGuardDenial | undefined
754
+ ```
755
+
756
+ Types: [ScopeKey](./scope.md)
757
+
758
+ Source: [`packages/core/tools/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/index.ts)
759
+
760
+ <a id="tools-events"></a>
761
+
762
+ ### `tools/*` events
763
+
764
+ <a id="toolschange--emit"></a>
765
+
766
+ #### `tools/change` — emit
767
+
768
+ A tool was registered or unregistered, or a scoped restriction changed. Unfiltered registry notification: scoped listeners receive changes from every scope because a global contribution can affect every agent's next assembly.
769
+
770
+ ```ts cordis-catalog
771
+ /**
772
+ * A tool was registered or unregistered, or a scoped restriction changed.
773
+ * Unfiltered registry notification: scoped listeners receive changes from every
774
+ * scope because a global contribution can affect every agent's next assembly.
775
+ * @mode emit
776
+ */
777
+ 'tools/change'(): void
778
+ ```
779
+
780
+ Source: [`packages/core/tools/src/events.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/events.ts)
781
+
782
+ <a id="toolsexecute--waterfall"></a>
783
+
784
+ #### `tools/execute` — waterfall
785
+
786
+ Around-dispatch waterfall for timeout, retry, or metrics. `next()` returns a normalized result; wrappers may change only `exec.signal`, while call identity remains immutable. The registry re-fuses the original caller signal before the body, so replacement cannot detach caller cancellation; wrappers must still restore their signal and reach quiescence. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent's calls.
787
+
788
+ ```ts cordis-catalog
789
+ /**
790
+ * Around-dispatch waterfall for timeout, retry, or metrics. `next()` returns
791
+ * a normalized result; wrappers may change only `exec.signal`, while call
792
+ * identity remains immutable. The registry re-fuses the original caller
793
+ * signal before the body, so replacement cannot detach caller cancellation;
794
+ * wrappers must still restore their signal and reach quiescence.
795
+ * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent's calls.
796
+ * @param exec - the allowed call about to dispatch (name, parsed arguments, caller agent, signal).
797
+ * @mode waterfall
798
+ */
799
+ 'tools/execute'(this: Scoped<ToolsService>, exec: ToolDispatchExecution, next: () => Promise<ToolExecutionResult>): Promise<ToolExecutionResult>
800
+ ```
801
+
802
+ Types: [Scoped](./scope.md)
803
+
804
+ Source: [`packages/core/tools/src/events.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/events.ts)
805
+
806
+ <a id="toolspost-execute--waterfall"></a>
807
+
808
+ #### `tools/post-execute` — waterfall
809
+
810
+ Accept, replace, enrich, or block a normalized dispatch result. `next()` accepts it unchanged; thrown tools still reach this waterfall as errors. Async listeners must observe `exec.signal`; after they settle, caller cancellation replaces only a successful accepted outcome with the code selected by whether the tool body was invoked. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent's calls.
811
+
812
+ ```ts cordis-catalog
813
+ /**
814
+ * Accept, replace, enrich, or block a normalized dispatch result. `next()`
815
+ * accepts it unchanged; thrown tools still reach this waterfall as errors. Async
816
+ * listeners must observe `exec.signal`; after they settle, caller
817
+ * cancellation replaces only a successful accepted outcome with the code
818
+ * selected by whether the tool body was invoked.
819
+ * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent's calls.
820
+ * @param exec - the call that just ran (name, parsed arguments, caller agent).
821
+ * @param result - the dispatch outcome a listener may accept, replace, or block.
822
+ * @mode waterfall
823
+ */
824
+ 'tools/post-execute'(this: Scoped<ToolsService>, exec: ToolExecution, result: Readonly<ToolExecutionResult>, next: () => Promise<PostToolDecision>): Promise<PostToolDecision>
825
+ ```
826
+
827
+ Types: [Scoped](./scope.md)
828
+
829
+ Source: [`packages/core/tools/src/events.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/events.ts)
830
+
831
+ <a id="toolspre-execute--waterfall"></a>
832
+
833
+ #### `tools/pre-execute` — waterfall
834
+
835
+ Allow, deny, cancel, or ask before dispatch. `next()` delegates to allow; `cancel` selects the canonical pre-dispatch cancellation result, and missing approval support turns `ask` into denial. Async gates must observe `exec.signal`; the registry rechecks cancellation after they settle but never abandons their promise. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent's calls.
836
+
837
+ ```ts cordis-catalog
838
+ /**
839
+ * Allow, deny, cancel, or ask before dispatch. `next()` delegates to allow;
840
+ * `cancel` selects the canonical pre-dispatch cancellation result, and missing
841
+ * approval support turns `ask` into denial. Async gates must observe
842
+ * `exec.signal`; the registry rechecks cancellation after they settle but
843
+ * never abandons their promise.
844
+ * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent's calls.
845
+ * @param exec - the pending call (name, parsed arguments, caller agent).
846
+ * @mode waterfall
847
+ */
848
+ 'tools/pre-execute'(this: Scoped<ToolsService>, exec: ToolExecution, next: () => Promise<PreToolDecision>): Promise<PreToolDecision>
849
+ ```
850
+
851
+ Types: [Scoped](./scope.md)
852
+
853
+ Source: [`packages/core/tools/src/events.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/events.ts)
854
+
855
+ <a id="toolsptc-dispatch-log--waterfall"></a>
856
+
857
+ #### `tools/ptc-dispatch-log` — waterfall
858
+
859
+ Allow a listener to replace content in the DURABLE LOG COPY of one `run_code` sub-dispatch outcome before the bridge appends its `tool/ptc-dispatch` event. `next()` keeps the content unchanged; a listener may return replacement blocks (e.g. the spill policy's preview + locator for an oversized text result). Only the logged copy is affected — the program already received the complete value, and the model sees neither. A throwing listener is contained: the bridge falls back to logging the original settled content. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent's dispatches.
860
+
861
+ ```ts cordis-catalog
862
+ /**
863
+ * Allow a listener to replace content in the DURABLE LOG COPY of one
864
+ * `run_code` sub-dispatch outcome before the bridge appends its
865
+ * `tool/ptc-dispatch` event. `next()` keeps the
866
+ * content unchanged; a listener may return replacement blocks (e.g. the
867
+ * spill policy's preview + locator for an oversized text result). Only the
868
+ * logged copy is affected — the program already received the complete
869
+ * value, and the model sees neither. A throwing listener is contained:
870
+ * the bridge falls back to logging the original settled content.
871
+ * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent's dispatches.
872
+ * @param dispatch - the parent execution, sub-call identity, and the settled content to log.
873
+ * @mode waterfall
874
+ */
875
+ 'tools/ptc-dispatch-log'(this: Scoped<ToolsService>, dispatch: PtcDispatchLog, next: () => Promise<ContentBlock[]>): Promise<ContentBlock[]>
876
+ ```
877
+
878
+ Types: [ContentBlock](./llm-streaming.md) · [Scoped](./scope.md)
879
+
880
+ Source: [`packages/core/tool-executor-ptc/src/runtime-types.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tool-executor-ptc/src/runtime-types.ts)
881
+
882
+ <a id="toolsresult--emit"></a>
883
+
884
+ #### `tools/result` — emit
885
+
886
+ Observe the frozen, lossless-JSON final outcome. Listener failures are contained. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): keyed by `exec.agent`.
887
+
888
+ ```ts cordis-catalog
889
+ /**
890
+ * Observe the frozen, lossless-JSON final outcome. Listener failures are contained.
891
+ * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): keyed by `exec.agent`.
892
+ * @param exec - the execution object that traversed the pipeline.
893
+ * @param result - a deep-frozen snapshot of the final returned result.
894
+ * @mode emit
895
+ */
896
+ 'tools/result'(this: Scoped<ToolsService>, exec: Readonly<ToolExecution>, result: Readonly<ToolExecutionResult>): undefined
897
+ ```
898
+
899
+ Types: [Scoped](./scope.md)
900
+
901
+ Source: [`packages/core/tools/src/events.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/events.ts)
902
+ <!-- END GENERATED cordis-surface -->