dsh-plugin-dev-kb 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +56 -0
  3. package/cordis.patch.yml +12 -0
  4. package/kb/INDEX.md +210 -0
  5. package/kb/README.md +69 -0
  6. package/kb/extra/AGENTS.md +75 -0
  7. package/kb/extra/api-gateway.md +164 -0
  8. package/kb/extra/api-gateway.zh.md +164 -0
  9. package/kb/extra/cookbook/adding-a-vendored-package.md +59 -0
  10. package/kb/extra/cookbook/adding-a-vendored-package.zh.md +59 -0
  11. package/kb/extra/cookbook/maintaining-dsh-code-review.md +64 -0
  12. package/kb/extra/cookbook/maintaining-dsh-code-review.zh.md +64 -0
  13. package/kb/extra/cookbook/responding-to-pr-review-on-a-stack.md +32 -0
  14. package/kb/extra/cookbook/responding-to-pr-review-on-a-stack.zh.md +32 -0
  15. package/kb/extra/defensive-patterns.md +33 -0
  16. package/kb/extra/defensive-patterns.zh.md +33 -0
  17. package/kb/extra/development.md +171 -0
  18. package/kb/extra/development.zh.md +171 -0
  19. package/kb/extra/event-producer-consumer.md +76 -0
  20. package/kb/extra/event-producer-consumer.zh.md +78 -0
  21. package/kb/extra/glossary.md +45 -0
  22. package/kb/extra/glossary.zh.md +45 -0
  23. package/kb/extra/graph-atlas.md +24 -0
  24. package/kb/extra/graph-atlas.zh.md +26 -0
  25. package/kb/extra/i18n/README.md +60 -0
  26. package/kb/extra/i18n/README.zh.md +60 -0
  27. package/kb/extra/i18n/style-samples.md +87 -0
  28. package/kb/extra/i18n/terminology.md +214 -0
  29. package/kb/extra/i18n/translation-prompt.md +263 -0
  30. package/kb/extra/i18n/translation-rules.md +69 -0
  31. package/kb/extra/i18n/translation-rules.zh.md +69 -0
  32. package/kb/extra/module-graph.md +1641 -0
  33. package/kb/extra/module-graph.zh.md +1643 -0
  34. package/kb/extra/postmortem/0001-acp-default-export-drops-inject.md +113 -0
  35. package/kb/extra/postmortem/0001-acp-default-export-drops-inject.zh.md +113 -0
  36. package/kb/extra/postmortem/0002-js-expression-disabled-filesystem-tools.md +47 -0
  37. package/kb/extra/postmortem/0002-js-expression-disabled-filesystem-tools.zh.md +47 -0
  38. package/kb/extra/postmortem/0003-web-agent-gui-feedback-loop.md +53 -0
  39. package/kb/extra/postmortem/0003-web-agent-gui-feedback-loop.zh.md +53 -0
  40. package/kb/extra/postmortem/0004-landlock-partial-notice-misclassified-child-failures.md +55 -0
  41. package/kb/extra/postmortem/0004-landlock-partial-notice-misclassified-child-failures.zh.md +55 -0
  42. package/kb/extra/postmortem/README.md +18 -0
  43. package/kb/extra/postmortem/README.zh.md +18 -0
  44. package/kb/extra/rescope.md +53 -0
  45. package/kb/extra/rescope.zh.md +53 -0
  46. package/kb/extra/subsystems/attachment.md +125 -0
  47. package/kb/extra/subsystems/attachment.zh.md +125 -0
  48. package/kb/extra/subsystems/extensions.md +364 -0
  49. package/kb/extra/subsystems/extensions.zh.md +364 -0
  50. package/kb/extra/subsystems/feedback.md +266 -0
  51. package/kb/extra/subsystems/feedback.zh.md +266 -0
  52. package/kb/extra/testing.md +49 -0
  53. package/kb/extra/testing.zh.md +49 -0
  54. package/kb/extra/web-styling.md +25 -0
  55. package/kb/extra/web-styling.zh.md +25 -0
  56. package/kb/meta/search-index.json +1328 -0
  57. package/kb/meta/site-pages.txt +168 -0
  58. package/kb/meta/source.json +13 -0
  59. package/kb/meta/topics.md +75 -0
  60. package/kb/site/develop/basic/config.md +108 -0
  61. package/kb/site/develop/basic/index.md +146 -0
  62. package/kb/site/develop/basic/publish.md +185 -0
  63. package/kb/site/develop/basic/tool.md +54 -0
  64. package/kb/site/develop/cordis-tutorial/01-first-plugin.md +95 -0
  65. package/kb/site/develop/cordis-tutorial/02-lifecycle-and-effects.md +98 -0
  66. package/kb/site/develop/cordis-tutorial/03-services.md +98 -0
  67. package/kb/site/develop/cordis-tutorial/04-events.md +144 -0
  68. package/kb/site/develop/cordis-tutorial/05-config.md +84 -0
  69. package/kb/site/develop/cordis-tutorial/06-composition-and-hmr.md +113 -0
  70. package/kb/site/develop/cordis-tutorial/07-into-the-harness.md +107 -0
  71. package/kb/site/develop/cordis-tutorial/index.md +62 -0
  72. package/kb/site/develop/framework/events.md +145 -0
  73. package/kb/site/develop/framework/index.md +139 -0
  74. package/kb/site/develop/framework/service.md +152 -0
  75. package/kb/site/develop/practice/index.md +157 -0
  76. package/kb/site/develop/practice/llm-adapter.md +190 -0
  77. package/kb/site/en/develop/basic/config.md +108 -0
  78. package/kb/site/en/develop/basic/index.md +146 -0
  79. package/kb/site/en/develop/basic/publish.md +185 -0
  80. package/kb/site/en/develop/basic/tool.md +54 -0
  81. package/kb/site/en/develop/cordis-tutorial/01-first-plugin.md +95 -0
  82. package/kb/site/en/develop/cordis-tutorial/02-lifecycle-and-effects.md +98 -0
  83. package/kb/site/en/develop/cordis-tutorial/03-services.md +98 -0
  84. package/kb/site/en/develop/cordis-tutorial/04-events.md +144 -0
  85. package/kb/site/en/develop/cordis-tutorial/05-config.md +84 -0
  86. package/kb/site/en/develop/cordis-tutorial/06-composition-and-hmr.md +113 -0
  87. package/kb/site/en/develop/cordis-tutorial/07-into-the-harness.md +107 -0
  88. package/kb/site/en/develop/cordis-tutorial/index.md +60 -0
  89. package/kb/site/en/develop/framework/events.md +145 -0
  90. package/kb/site/en/develop/framework/index.md +139 -0
  91. package/kb/site/en/develop/framework/service.md +150 -0
  92. package/kb/site/en/develop/practice/index.md +157 -0
  93. package/kb/site/en/develop/practice/llm-adapter.md +190 -0
  94. package/kb/site/en/guide/providers-custom-form.png +0 -0
  95. package/kb/site/en/guide/providers-models-page.png +0 -0
  96. package/kb/site/en/guide/providers.md +100 -0
  97. package/kb/site/en/guide/python-sdk.md +106 -0
  98. package/kb/site/en/guide/quickstart.md +32 -0
  99. package/kb/site/en/index.md +8 -0
  100. package/kb/site/en/reference/agent-lifecycle.md +86 -0
  101. package/kb/site/en/reference/capability-seams.md +475 -0
  102. package/kb/site/en/reference/config-catalog.md +3155 -0
  103. package/kb/site/en/reference/cookbook/adding-a-conversation-node.md +235 -0
  104. package/kb/site/en/reference/cookbook/adding-a-package.md +120 -0
  105. package/kb/site/en/reference/cookbook/adding-a-settings-card.md +102 -0
  106. package/kb/site/en/reference/cookbook/adding-a-tool.md +96 -0
  107. package/kb/site/en/reference/cookbook/adding-an-llm-adapter.md +45 -0
  108. package/kb/site/en/reference/cookbook/extension-cookbook.md +131 -0
  109. package/kb/site/en/reference/cordis-api/context.md +368 -0
  110. package/kb/site/en/reference/cordis-api/events.md +211 -0
  111. package/kb/site/en/reference/cordis-api/fiber.md +379 -0
  112. package/kb/site/en/reference/cordis-api/inherited.md +43 -0
  113. package/kb/site/en/reference/cordis-api/registry.md +156 -0
  114. package/kb/site/en/reference/cordis-api/service.md +106 -0
  115. package/kb/site/en/reference/cordis-primer.md +46 -0
  116. package/kb/site/en/reference/index.md +131 -0
  117. package/kb/site/en/reference/persistence-catalog.md +949 -0
  118. package/kb/site/en/reference/subsystems/approval.md +173 -0
  119. package/kb/site/en/reference/subsystems/client-modules.md +121 -0
  120. package/kb/site/en/reference/subsystems/code-runtime.md +194 -0
  121. package/kb/site/en/reference/subsystems/commands.md +190 -0
  122. package/kb/site/en/reference/subsystems/compaction.md +241 -0
  123. package/kb/site/en/reference/subsystems/core.md +1073 -0
  124. package/kb/site/en/reference/subsystems/credentials.md +136 -0
  125. package/kb/site/en/reference/subsystems/filesystem.md +498 -0
  126. package/kb/site/en/reference/subsystems/goal.md +280 -0
  127. package/kb/site/en/reference/subsystems/index.md +58 -0
  128. package/kb/site/en/reference/subsystems/invariants.md +91 -0
  129. package/kb/site/en/reference/subsystems/jobs.md +293 -0
  130. package/kb/site/en/reference/subsystems/llm-streaming.md +920 -0
  131. package/kb/site/en/reference/subsystems/lsp.md +205 -0
  132. package/kb/site/en/reference/subsystems/permission-presets.md +134 -0
  133. package/kb/site/en/reference/subsystems/persistence.md +388 -0
  134. package/kb/site/en/reference/subsystems/plan.md +90 -0
  135. package/kb/site/en/reference/subsystems/sandbox.md +221 -0
  136. package/kb/site/en/reference/subsystems/schedule.md +189 -0
  137. package/kb/site/en/reference/subsystems/scope.md +62 -0
  138. package/kb/site/en/reference/subsystems/session-projection.md +265 -0
  139. package/kb/site/en/reference/subsystems/session-query.md +498 -0
  140. package/kb/site/en/reference/subsystems/session-reference.md +111 -0
  141. package/kb/site/en/reference/subsystems/session-telemetry.md +197 -0
  142. package/kb/site/en/reference/subsystems/session-title.md +207 -0
  143. package/kb/site/en/reference/subsystems/session.md +852 -0
  144. package/kb/site/en/reference/subsystems/settings.md +313 -0
  145. package/kb/site/en/reference/subsystems/shell.md +306 -0
  146. package/kb/site/en/reference/subsystems/skills.md +334 -0
  147. package/kb/site/en/reference/subsystems/spill.md +120 -0
  148. package/kb/site/en/reference/subsystems/storage.md +232 -0
  149. package/kb/site/en/reference/subsystems/subagent.md +737 -0
  150. package/kb/site/en/reference/subsystems/subprocess.md +327 -0
  151. package/kb/site/en/reference/subsystems/system-prompt.md +210 -0
  152. package/kb/site/en/reference/subsystems/terminal.md +187 -0
  153. package/kb/site/en/reference/subsystems/token-meter.md +93 -0
  154. package/kb/site/en/reference/subsystems/tools.md +723 -0
  155. package/kb/site/en/reference/subsystems/typert.md +339 -0
  156. package/kb/site/en/reference/subsystems/user-questions.md +181 -0
  157. package/kb/site/en/reference/subsystems/web-server.md +111 -0
  158. package/kb/site/en/reference/subsystems/web.md +202 -0
  159. package/kb/site/en/reference/subsystems/workflow.md +281 -0
  160. package/kb/site/en/reference/subsystems/workspace.md +231 -0
  161. package/kb/site/en/reference/tool-catalog.md +1877 -0
  162. package/kb/site/en/reference/tool-execution-pipeline.md +66 -0
  163. package/kb/site/guide/providers-custom-form.zh.png +0 -0
  164. package/kb/site/guide/providers-models-page.zh.png +0 -0
  165. package/kb/site/guide/providers.md +100 -0
  166. package/kb/site/guide/python-sdk.md +106 -0
  167. package/kb/site/guide/quickstart.md +32 -0
  168. package/kb/site/index.md +8 -0
  169. package/kb/site/reference/agent-lifecycle.md +86 -0
  170. package/kb/site/reference/capability-seams.md +475 -0
  171. package/kb/site/reference/config-catalog.md +3154 -0
  172. package/kb/site/reference/cookbook/adding-a-conversation-node.md +235 -0
  173. package/kb/site/reference/cookbook/adding-a-package.md +120 -0
  174. package/kb/site/reference/cookbook/adding-a-settings-card.md +102 -0
  175. package/kb/site/reference/cookbook/adding-a-tool.md +98 -0
  176. package/kb/site/reference/cookbook/adding-an-llm-adapter.md +45 -0
  177. package/kb/site/reference/cookbook/extension-cookbook.md +133 -0
  178. package/kb/site/reference/cordis-api/context.md +368 -0
  179. package/kb/site/reference/cordis-api/events.md +211 -0
  180. package/kb/site/reference/cordis-api/fiber.md +379 -0
  181. package/kb/site/reference/cordis-api/inherited.md +43 -0
  182. package/kb/site/reference/cordis-api/registry.md +156 -0
  183. package/kb/site/reference/cordis-api/service.md +106 -0
  184. package/kb/site/reference/cordis-primer.md +52 -0
  185. package/kb/site/reference/index.md +135 -0
  186. package/kb/site/reference/persistence-catalog.md +949 -0
  187. package/kb/site/reference/subsystems/approval.md +173 -0
  188. package/kb/site/reference/subsystems/client-modules.md +121 -0
  189. package/kb/site/reference/subsystems/code-runtime.md +194 -0
  190. package/kb/site/reference/subsystems/commands.md +190 -0
  191. package/kb/site/reference/subsystems/compaction.md +241 -0
  192. package/kb/site/reference/subsystems/core.md +1081 -0
  193. package/kb/site/reference/subsystems/credentials.md +136 -0
  194. package/kb/site/reference/subsystems/filesystem.md +498 -0
  195. package/kb/site/reference/subsystems/goal.md +280 -0
  196. package/kb/site/reference/subsystems/index.md +58 -0
  197. package/kb/site/reference/subsystems/invariants.md +91 -0
  198. package/kb/site/reference/subsystems/jobs.md +293 -0
  199. package/kb/site/reference/subsystems/llm-streaming.md +926 -0
  200. package/kb/site/reference/subsystems/lsp.md +205 -0
  201. package/kb/site/reference/subsystems/permission-presets.md +134 -0
  202. package/kb/site/reference/subsystems/persistence.md +388 -0
  203. package/kb/site/reference/subsystems/plan.md +90 -0
  204. package/kb/site/reference/subsystems/sandbox.md +221 -0
  205. package/kb/site/reference/subsystems/schedule.md +189 -0
  206. package/kb/site/reference/subsystems/scope.md +62 -0
  207. package/kb/site/reference/subsystems/session-projection.md +265 -0
  208. package/kb/site/reference/subsystems/session-query.md +498 -0
  209. package/kb/site/reference/subsystems/session-reference.md +111 -0
  210. package/kb/site/reference/subsystems/session-telemetry.md +197 -0
  211. package/kb/site/reference/subsystems/session-title.md +207 -0
  212. package/kb/site/reference/subsystems/session.md +854 -0
  213. package/kb/site/reference/subsystems/settings.md +313 -0
  214. package/kb/site/reference/subsystems/shell.md +306 -0
  215. package/kb/site/reference/subsystems/skills.md +334 -0
  216. package/kb/site/reference/subsystems/spill.md +120 -0
  217. package/kb/site/reference/subsystems/storage.md +232 -0
  218. package/kb/site/reference/subsystems/subagent.md +739 -0
  219. package/kb/site/reference/subsystems/subprocess.md +327 -0
  220. package/kb/site/reference/subsystems/system-prompt.md +210 -0
  221. package/kb/site/reference/subsystems/terminal.md +187 -0
  222. package/kb/site/reference/subsystems/token-meter.md +93 -0
  223. package/kb/site/reference/subsystems/tools.md +723 -0
  224. package/kb/site/reference/subsystems/typert.md +339 -0
  225. package/kb/site/reference/subsystems/user-questions.md +181 -0
  226. package/kb/site/reference/subsystems/web-server.md +111 -0
  227. package/kb/site/reference/subsystems/web.md +202 -0
  228. package/kb/site/reference/subsystems/workflow.md +281 -0
  229. package/kb/site/reference/subsystems/workspace.md +231 -0
  230. package/kb/site/reference/tool-catalog.md +1880 -0
  231. package/kb/site/reference/tool-execution-pipeline.md +66 -0
  232. package/package.json +40 -0
  233. package/scripts/rebuild-index.mjs +88 -0
  234. package/skills/dsh-plugin-dev-kb.md +66 -0
@@ -0,0 +1,131 @@
1
+ ---
2
+ editSource: "docs/cookbook/extension-cookbook.md"
3
+ ---
4
+
5
+ # Cookbook: extension plugin shapes
6
+
7
+ Reference patterns for harness extensions. The snippets omit imports and helper implementations and are not copy-paste-complete. For concrete authoring paths, see the [package checklist](./adding-a-package.md), [first-tool tutorial](../../develop/basic/tool.md), [tool reference](./adding-a-tool.md), and [LLM adapter guide](./adding-an-llm-adapter.md); the [architecture](../index.md) owns the system and extension-point map.
8
+
9
+ ## A tool plugin
10
+
11
+ A tool registers on `ctx.tools`. The annotated `defineTool` example (typed `execute` arguments, result construction, the `run_in_background` pattern) lives in [adding-a-tool.md](./adding-a-tool.md) — that guide is the source of truth for tool definitions. Raw JSON-Schema `ToolDefinition`s are also accepted by `ctx.tools.register()` directly (that is how MCP-sourced tools arrive); `defineTool` is the typed helper for first-party tools.
12
+
13
+ ## A hook plugin (permission-gate example)
14
+
15
+ This permission gate is one example of a hook plugin. It returns a typed decision from the `tools/pre-execute` gate to allow or deny a call; sandbox, permission, and plan-mode plugins can use this extension point. Hook plugins can intercept other extension points and are not inherently permission gates. A "native hook" is an ordinary Cordis plugin on an interception point; it needs no external protocol.
16
+
17
+ ```ts
18
+ import type { Context } from '@deepseek-ai/cordis'
19
+ import type { PreToolDecision, ToolExecution } from '@deepseek-ai/dsh-tools'
20
+
21
+ declare function isAllowed(exec: ToolExecution): Promise<boolean>
22
+
23
+ export const name = 'permission-gate'
24
+
25
+ export function apply(ctx: Context) {
26
+ ctx.on('tools/pre-execute', async (exec, next): Promise<PreToolDecision> => {
27
+ if (!(await isAllowed(exec))) {
28
+ return { kind: 'deny', reason: 'Denied by policy.' }
29
+ }
30
+ return next()
31
+ })
32
+ }
33
+ ```
34
+
35
+ This waterfall is the reorderable policy layer. Use `ctx.tools.guard()` when an invariant needs a monotonic final denial, `tools/execute` when a plugin must wrap the actual dispatch lifetime (timeouts/retries/metrics; only `exec.signal` is replaceable), `tools/post-execute` for explicit result transformation, and `tools/result` for contained observation of the immutable final outcome. The [adding-a-tool guide](./adding-a-tool.md#execution-policy-and-observation) gives the selection rule.
36
+
37
+ ## A UI plugin
38
+
39
+ A UI plugin renders from the `session/event` feed (the assistant token stream as `assistant/chunk`, plus turn/step boundaries and tool activity), and drives input back in via `agent.followup()` / `agent.steer()`. A browser plugin contributing a business row to the built-in Web Client instead registers a `ConversationNodeDefinition` and keyed Chat renderer; follow the [Conversation Node guide](./adding-a-conversation-node.md).
40
+
41
+ ```ts
42
+ import type { Context } from '@deepseek-ai/cordis'
43
+ import { createUserMessage } from '@deepseek-ai/dsh-llm'
44
+ import { SessionId } from '@deepseek-ai/dsh-session'
45
+
46
+ declare function render(text: string): void
47
+ declare function onUserInput(handler: (text: string) => void): void
48
+
49
+ export const name = 'my-ui'
50
+ export const inject = ['agents']
51
+
52
+ export function apply(ctx: Context) {
53
+ ctx.on('session/event', (_session, event) => {
54
+ if (event.type === 'assistant/chunk' && event.data.chunk.type === 'text-delta') {
55
+ render(event.data.chunk.text)
56
+ }
57
+ })
58
+ onUserInput(text => ctx.agents.get(SessionId('client-session'))?.followup(createUserMessage({
59
+ content: [{ type: 'text', text }],
60
+ source: { kind: 'user' },
61
+ })))
62
+ }
63
+ ```
64
+
65
+ ## An external protocol driver
66
+
67
+ A *protocol driver* adapts a wire peer to `ctx.agents`; it may serve a UI or an automation client. A stdio driver owns stdout, creates or resumes agents through the factory, and maps protocol requests to `followup()` or `cancel()`. A low-level prompt request returns its durable enqueue receipt; it does not acquire a result by correlating `MessageId` with `turn/end`. Publish whole-agent status separately. An automation method may wait from its receipt through the next idle and summarize that explicitly owned interval, while a UI normally keeps observing the open-ended event stream. Tear agents down with `AgentHandle.dispose()` so disposal reaches quiescence.
68
+
69
+ [`packages/acp/acp`](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/acp/acp) is the automation-only worked example: it exposes fresh text sessions over Agent Client Protocol JSON-RPC stdio, emits committed assistant text, and registers a one-shot machine permission answerer for agents it owns. Its [README](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/acp/acp/README.md) defines the exact methods, event order, and lifecycle contract.
70
+
71
+ ```ts
72
+ import type { Context } from '@deepseek-ai/cordis'
73
+
74
+ export const name = 'my-protocol-bridge'
75
+ export const inject = ['agents', 'sessions', 'sessionPersistence']
76
+
77
+ export function apply(ctx: Context) {
78
+ // Stream every logged assistant text/reasoning delta out to the client.
79
+ ctx.on('session/event', (_session, event) => {
80
+ if (event.type === 'assistant/chunk') {
81
+ const chunk = event.data.chunk
82
+ if (chunk.type === 'text-delta') {
83
+ // sendToClient({ kind: 'message_chunk', text: chunk.text })
84
+ }
85
+ }
86
+ })
87
+ // Inbound "prompt": create/resume an agent, feed it, and return its enqueue receipt.
88
+ // Whole-agent status is a separate notification; no turn end belongs to this prompt.
89
+ // Teardown reaches quiescence via AgentHandle.dispose() (stop + await exit).
90
+ }
91
+ ```
92
+
93
+ ## Runnable wirings
94
+
95
+ Runnable leaves load their plugin trees from `examples/*/cordis.yml`; the root `demo:*` scripts and those leaf directories are the authoritative inventory. The product `dsh` launcher owns Web and one-shot headless execution, ACP leaves use [`@deepseek-ai/dsh-acp-demo`](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/examples/acp-demo), and JSON-RPC leaves use [`@deepseek-ai/dsh-sdk-jsonrpc-demo`](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/examples/jsonrpc-demo). The headless snapshot leaf mounts [`@deepseek-ai/dsh-agent-spine-demo`](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/examples/agent-spine-demo) and JSONL persistence explicitly, then drives them through an example-owned test fixture rather than a shipped app package.
96
+
97
+ ## The feature → mechanism map
98
+
99
+ Every product feature maps to a listener on a documented extension point — the microkernel claim made checkable ([microkernel Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/architecture/2026-06-11-microkernel-event-taxonomy.md)). No row modifies the loop.
100
+
101
+ `system-prompt/assemble` is an expert cooperative whole-assembly transform: its returned assembly is authoritative, so listener authors own preserving active Code Mode and structured-output protocol contributions. Prefer `ctx.tools.restrict()` for tool filtering that must stay aligned across presentation, lookup, and execution.
102
+
103
+ | Product feature | Plugin mechanism |
104
+ |---|---|
105
+ | Hook system (user + project level) | listeners on `agent/session-start`, `agent/pre-step`, `agent/request`, `tools/pre-execute`, `tools/post-execute`, and `agent/turn-stopping`; the waterfalls return typed decisions, while `agent/turn-stopping` may steer another step; the `dsh-hooks-claude-code` / `dsh-hooks-codex` bridges map hook config files onto these extension points |
106
+ | `/goal` | `ctx.goals` owns durable state, `dsh-goal-round-driver` schedules same-session rounds through the public `Agent`, and separate command/tool producers expose human/model control |
107
+ | `/loop` | on the `turn/end` session event, `followup()` the next iteration; or force-continue |
108
+ | Dynamic workflow | `ctx.workflowEngine` + the worker-thread engine + the `workflow` tool; structured in-process children enforce output with scoped prompt/tool registrations, a monotonic tool guard, final `tools/result` commit (including enclosing `run_code`), and the structured-output execution's monotonic `concludeTurn()` marker |
109
+ | Queued + steering messages | core `Agent.followup()` / `Agent.steer()` |
110
+ | Context compaction (auto + manual) | the `ctx.compaction` seam + `dsh-compaction-basic`; automatic pressure runs on serial `agent/pre-step`, canonical overflow recovery runs on `agent/request-error`, and manual callers use the same compact service ([compaction Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md)) |
111
+ | System prompt configurability | `ctx.systemPrompt.section()` with ordering and scope-local shadowing |
112
+ | AGENTS.md (root) | a section provider reading the file |
113
+ | AGENTS.md (subdir, on-touch) + file-change notices | `agent.inject()` from a watcher / tool-result listener |
114
+ | Built-in tools | `ctx.tools.register()`; schemas flow into the assembly automatically — the `dsh-tool-*` families (bash, fs, web, subagent, todo) are the shipped examples |
115
+ | ToolSearch / progressive disclosure | replace a scoped `ctx.tools.restrict()` registration as the visible set changes; the registry keeps presentation, lookup, and execution aligned |
116
+ | Tool deadline / retry / metrics | wrap core dispatch with `tools/execute`; a wrapper may replace `exec.signal`, delegate, and inspect the normalized result in one lexical lifetime |
117
+ | Final tool-result metrics / audit / capture | observe immutable authoritative outcomes with `tools/result`; use `tools/post-execute` instead only when the plugin must transform the result or attach context |
118
+ | Monotonic terminal turn policy | call `ToolExecution.concludeTurn()` from the successful terminal tool; later tool calls in the same response remain guardable, and the loop stops after the step |
119
+ | Subprocess sandbox (landlock / sandbox-exec) | use a `ctx.sandbox` backend through `dsh-bash-sandbox`; use `tools/pre-execute` for capability-level denial |
120
+ | Permission system / AskUserQuestion | return `ask` from `tools/pre-execute` and answer through `ctx.approval`; register a separate model-facing ask tool for ordinary user questions |
121
+ | Plan mode | [`@deepseek-ai/dsh-plan-mode`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/plan/plan-mode/README.md) — logged `plan/mode` state, the `plan:policy` guidance section, `/plan [message]` entry, `/plan off` direct exit, and the user-reviewed `exit_plan_mode` exit; enforcement stays on the independent sandbox/approval axes |
122
+ | Sub-agent delegation | the `ctx.subagents` provider registry (`dsh-subagent-spawn-in-process`/`-fork`/`-acp`/`-codex`/`-claude-code`/`-dsh-sdk`) + `dsh-tool-subagent` exposing one configured provider to the model |
123
+ | MCP | one plugin per server: discover tools → `ctx.tools.register()` |
124
+ | Skills | section + tool registration; `inject()` skill content on invocation |
125
+ | Memory | section provider + tool |
126
+ | Scheduled tasks (cron) | a plugin registers model-callable scheduling tools; timer fires → `followup(…, {source: {kind: 'cron', …}})` when idle / `inject()` notification when busy |
127
+ | UI (GUI; CLI emits JSONL) | listen `session/event` (assistant chunks, boundaries, tool activity); input → `followup()` |
128
+ | Web Client Chat business node | register a `ConversationNodeDefinition` and `conversation.chat.node` keyed renderer |
129
+ | SessionTelemetryBackend / replayable trace | `session/event` → JSONL; replay = `sessions.create(id, { seed })` |
130
+ | Model adapters | `LlmAdapter` subclass via `registerAdapter` (`dsh-llm-deepseek`, `dsh-llm-pi-ai`) |
131
+ | Plugin hot-reload | every registration is a `ctx.effect` → vendored HMR just works |
@@ -0,0 +1,368 @@
1
+ ---
2
+ editSource: "docs/cordis-api/context.md"
3
+ ---
4
+
5
+ <!-- Generated by scripts/gen-cordis-catalog.ts — do not edit by hand.
6
+ Run `pnpm run gen-cordis-catalog` to regenerate. -->
7
+
8
+ # Context
9
+
10
+ The context is the core Cordis object: every service, event, and lifecycle API is reached through `ctx`. Event methods are documented on [Events](./events.md), effects and the current fiber on [Fiber](./fiber.md), and plugin loading on [Registry](./registry.md).
11
+
12
+ Root and child dependency containers for Cordis plugins.
13
+
14
+ A context is a proxy: normal property reads go through the service resolver, while `extend()`, `isolate()`, and `intercept()` create scoped child contexts without mutating their parent.
15
+
16
+ [Source](https://github.com/deepseek-ai/deepseek-harness/blob/master/vendor/cordis/src/context.ts#L42)
17
+
18
+ ### ctx.extend(meta?)
19
+
20
+ ```ts cordis-catalog
21
+ /**
22
+ * Create a child context with extra metadata on top of the current scope.
23
+ *
24
+ * The child prototypally inherits every property of this context; own
25
+ * properties of `meta` shadow the inherited ones. The parent is not mutated.
26
+ *
27
+ * @param meta — own properties (including symbol keys) to define on the child.
28
+ * @returns a child context inheriting from this one.
29
+ */
30
+ extend(meta = {}): this
31
+ ```
32
+
33
+ Create a child context with extra metadata on top of the current scope.
34
+
35
+ The child prototypally inherits every property of this context; own properties of `meta` shadow the inherited ones. The parent is not mutated.
36
+
37
+ - `meta` — own properties (including symbol keys) to define on the child.
38
+
39
+ **Returns** a child context inheriting from this one.
40
+
41
+ [Source](https://github.com/deepseek-ai/deepseek-harness/blob/master/vendor/cordis/src/context.ts#L99)
42
+
43
+ ### ctx.isolate(name, label?)
44
+
45
+ ```ts cordis-catalog
46
+ /**
47
+ * Create a child context with an independent service scope for `name`.
48
+ *
49
+ * Below the returned context, reads and writes of the service `name`
50
+ * resolve against the new label instead of the parent's, so a different
51
+ * implementation can be provided without affecting the parent scope.
52
+ * Passing the same `label` to two `isolate()` calls joins their scopes.
53
+ *
54
+ * @param name — the service name to isolate.
55
+ * @param label — scope label to join; defaults to a fresh unique symbol.
56
+ * @returns a child context whose `name` service resolves in the new scope.
57
+ */
58
+ isolate(name: string, label?: symbol)
59
+ ```
60
+
61
+ Create a child context with an independent service scope for `name`.
62
+
63
+ Below the returned context, reads and writes of the service `name` resolve against the new label instead of the parent's, so a different implementation can be provided without affecting the parent scope. Passing the same `label` to two `isolate()` calls joins their scopes.
64
+
65
+ - `name` — the service name to isolate.
66
+ - `label` — scope label to join; defaults to a fresh unique symbol.
67
+
68
+ **Returns** a child context whose `name` service resolves in the new scope.
69
+
70
+ [Source](https://github.com/deepseek-ai/deepseek-harness/blob/master/vendor/cordis/src/context.ts#L121)
71
+
72
+ ### ctx.intercept(name, config)
73
+
74
+ ```ts cordis-catalog
75
+ /**
76
+ * Add service-specific intercept config for plugins started below this
77
+ * context.
78
+ *
79
+ * Plugins loaded under the returned context see `config` merged into the
80
+ * service's resolved config (ancestor entries first; see
81
+ * `Service[symbols.resolveConfig]`). The parent context is not affected.
82
+ *
83
+ * @param name — the service name whose config to intercept.
84
+ * @param config — the intercept config to merge for that service.
85
+ * @returns a child context carrying the additional intercept entry.
86
+ */
87
+ intercept<K extends InjectKey>(name: K, config: Context[K] extends { [symbols.config]: infer T } ? T : never): this
88
+ intercept(name: string, config: any): this
89
+ ```
90
+
91
+ Add service-specific intercept config for plugins started below this context.
92
+
93
+ Plugins loaded under the returned context see `config` merged into the service's resolved config (ancestor entries first; see `Service[symbols.resolveConfig]`). The parent context is not affected.
94
+
95
+ - `name` — the service name whose config to intercept.
96
+ - `config` — the intercept config to merge for that service.
97
+
98
+ **Returns** a child context carrying the additional intercept entry.
99
+
100
+ [Source](https://github.com/deepseek-ai/deepseek-harness/blob/master/vendor/cordis/src/context.ts#L139)
101
+
102
+ ### ctx.root
103
+
104
+ ```ts cordis-catalog
105
+ /** The root context of the application (every child context shares it). @experimental */
106
+ root: this
107
+ ```
108
+
109
+ The root context of the application (every child context shares it). @experimental
110
+
111
+ [Source](https://github.com/deepseek-ai/deepseek-harness/blob/master/vendor/cordis/src/context.ts#L22)
112
+
113
+ ### ctx.baseUrl
114
+
115
+ ```ts cordis-catalog
116
+ /** Base URL used to resolve relative plugin/module specifiers, if the runtime sets one. */
117
+ baseUrl?: string
118
+ ```
119
+
120
+ Base URL used to resolve relative plugin/module specifiers, if the runtime sets one.
121
+
122
+ [Source](https://github.com/deepseek-ai/deepseek-harness/blob/master/vendor/cordis/src/context.ts#L24)
123
+
124
+ ### ctx.events
125
+
126
+ ```ts cordis-catalog
127
+ /** The event bus. Its methods are also mixed onto `ctx` (`ctx.on`, `ctx.emit`, ...). */
128
+ events: EventsService
129
+ ```
130
+
131
+ The event bus. Its methods are also mixed onto `ctx` (`ctx.on`, `ctx.emit`, ...).
132
+
133
+ [Source](https://github.com/deepseek-ai/deepseek-harness/blob/master/vendor/cordis/src/context.ts#L26)
134
+
135
+ ### ctx.logger
136
+
137
+ ```ts cordis-catalog
138
+ /** The logging service. Call `ctx.logger(name)` for a named logger. */
139
+ logger: LoggerService
140
+ ```
141
+
142
+ The logging service. Call `ctx.logger(name)` for a named logger.
143
+
144
+ [Source](https://github.com/deepseek-ai/deepseek-harness/blob/master/vendor/cordis/src/context.ts#L28)
145
+
146
+ ### ctx.reflect
147
+
148
+ ```ts cordis-catalog
149
+ /** The reflection layer backing the context proxy (`ctx.get`, `ctx.provide`, ...). */
150
+ reflect: ReflectService
151
+ ```
152
+
153
+ The reflection layer backing the context proxy (`ctx.get`, `ctx.provide`, ...).
154
+
155
+ [Source](https://github.com/deepseek-ai/deepseek-harness/blob/master/vendor/cordis/src/context.ts#L30)
156
+
157
+ ### ctx.registry
158
+
159
+ ```ts cordis-catalog
160
+ /** The plugin registry. Its methods are mixed onto `ctx` (`ctx.plugin`, `ctx.inject`). */
161
+ registry: RegistryService
162
+ ```
163
+
164
+ The plugin registry. Its methods are mixed onto `ctx` (`ctx.plugin`, `ctx.inject`).
165
+
166
+ [Source](https://github.com/deepseek-ai/deepseek-harness/blob/master/vendor/cordis/src/context.ts#L32)
167
+
168
+ ## Static members
169
+
170
+ ### Context.effect
171
+
172
+ ```ts cordis-catalog
173
+ /** Symbol key under which a disposer exposes its {@link EffectMeta} diagnostics tree. */
174
+ static readonly effect: unique symbol
175
+ ```
176
+
177
+ Symbol key under which a disposer exposes its EffectMeta diagnostics tree.
178
+
179
+ [Source](https://github.com/deepseek-ai/deepseek-harness/blob/master/vendor/cordis/src/context.ts#L44)
180
+
181
+ ### Context.filter
182
+
183
+ ```ts cordis-catalog
184
+ /** Symbol key for a context's listener filter, consulted on every event dispatch. */
185
+ static readonly filter: unique symbol
186
+ ```
187
+
188
+ Symbol key for a context's listener filter, consulted on every event dispatch.
189
+
190
+ [Source](https://github.com/deepseek-ai/deepseek-harness/blob/master/vendor/cordis/src/context.ts#L46)
191
+
192
+ ### Context.isolate
193
+
194
+ ```ts cordis-catalog
195
+ /** Symbol key of the isolation map (see the `Context[symbols.isolate]` property). */
196
+ static readonly isolate: unique symbol
197
+ ```
198
+
199
+ Symbol key of the isolation map (see the `Context[symbols.isolate]` property).
200
+
201
+ [Source](https://github.com/deepseek-ai/deepseek-harness/blob/master/vendor/cordis/src/context.ts#L48)
202
+
203
+ ### Context.intercept
204
+
205
+ ```ts cordis-catalog
206
+ /** Symbol key of the intercept map (see the `Context[symbols.intercept]` property). */
207
+ static readonly intercept: unique symbol
208
+ ```
209
+
210
+ Symbol key of the intercept map (see the `Context[symbols.intercept]` property).
211
+
212
+ [Source](https://github.com/deepseek-ai/deepseek-harness/blob/master/vendor/cordis/src/context.ts#L50)
213
+
214
+ ### Context.is(value)
215
+
216
+ ```ts cordis-catalog
217
+ /**
218
+ * Returns true for Cordis context proxies and context prototypes.
219
+ *
220
+ * Works across realms and across multiple copies of cordis, because the
221
+ * brand is keyed by a global symbol rather than by `instanceof`.
222
+ *
223
+ * @param value — the value to test.
224
+ * @returns `true` if `value` is a Cordis context, narrowing its type.
225
+ */
226
+ static is(value: any): value is Context
227
+ ```
228
+
229
+ Returns true for Cordis context proxies and context prototypes.
230
+
231
+ Works across realms and across multiple copies of cordis, because the brand is keyed by a global symbol rather than by `instanceof`.
232
+
233
+ - `value` — the value to test.
234
+
235
+ **Returns** `true` if `value` is a Cordis context, narrowing its type.
236
+
237
+ [Source](https://github.com/deepseek-ai/deepseek-harness/blob/master/vendor/cordis/src/context.ts#L61)
238
+
239
+ ## Service store and mixins
240
+
241
+ ### ctx.get(name, strict?)
242
+
243
+ ```ts cordis-catalog
244
+ /**
245
+ * Read a service from the store without the inject requirement.
246
+ *
247
+ * @param name — the service name.
248
+ * @param strict — when `true` (default), only return implementations
249
+ * whose providing fiber is currently active.
250
+ * @returns the service value, or `undefined` when not (yet) provided.
251
+ */
252
+ get<K extends string & keyof this>(name: K, strict?: boolean): undefined | this[K]
253
+ get(name: string, strict?: boolean): any
254
+ ```
255
+
256
+ Read a service from the store without the inject requirement.
257
+
258
+ - `name` — the service name.
259
+ - `strict` — when `true` (default), only return implementations whose providing fiber is currently active.
260
+
261
+ **Returns** the service value, or `undefined` when not (yet) provided.
262
+
263
+ [Source](https://github.com/deepseek-ai/deepseek-harness/blob/master/vendor/cordis/src/reflect.ts#L17)
264
+
265
+ ### ctx.set(name, value)
266
+
267
+ ```ts cordis-catalog
268
+ /**
269
+ * Overwrite a provided service's value.
270
+ *
271
+ * Only the fiber that provided the service may set it; setting an
272
+ * unprovided name throws.
273
+ *
274
+ * @param name — the service name.
275
+ * @param value — the new service value.
276
+ */
277
+ set<K extends string & keyof this>(name: K, value: undefined | this[K]): void
278
+ set(name: string, value: any): void
279
+ ```
280
+
281
+ Overwrite a provided service's value.
282
+
283
+ Only the fiber that provided the service may set it; setting an unprovided name throws.
284
+
285
+ - `name` — the service name.
286
+ - `value` — the new service value.
287
+
288
+ [Source](https://github.com/deepseek-ai/deepseek-harness/blob/master/vendor/cordis/src/reflect.ts#L29)
289
+
290
+ ### ctx.provide(name, value)
291
+
292
+ ```ts cordis-catalog
293
+ /**
294
+ * Register a service implementation owned by the current fiber.
295
+ *
296
+ * The service becomes visible to dependents in the same isolation scope
297
+ * once the fiber is active; it is unregistered (waking dependents) when
298
+ * the returned disposer runs or the fiber unloads. Throws if the name is
299
+ * already provided in this scope or declared as an accessor.
300
+ *
301
+ * @param name — the service name.
302
+ * @param value — the service value.
303
+ * @returns a disposer that unregisters the service.
304
+ */
305
+ provide<K extends string & keyof this>(name: K, value: undefined | this[K]): () => void
306
+ provide(name: string, value?: any): () => void
307
+ ```
308
+
309
+ Register a service implementation owned by the current fiber.
310
+
311
+ The service becomes visible to dependents in the same isolation scope once the fiber is active; it is unregistered (waking dependents) when the returned disposer runs or the fiber unloads. Throws if the name is already provided in this scope or declared as an accessor.
312
+
313
+ - `name` — the service name.
314
+ - `value` — the service value.
315
+
316
+ **Returns** a disposer that unregisters the service.
317
+
318
+ [Source](https://github.com/deepseek-ai/deepseek-harness/blob/master/vendor/cordis/src/reflect.ts#L44)
319
+
320
+ ### ctx.accessor(name, options)
321
+
322
+ ```ts cordis-catalog
323
+ /**
324
+ * Define a computed context property backed by get/set hooks.
325
+ *
326
+ * The accessor is removed when the current fiber unloads. Throws if the
327
+ * name is already declared.
328
+ *
329
+ * @param name — the context property name.
330
+ * @param options — the `get` hook and optional `set` hook.
331
+ */
332
+ accessor(name: string, options: Omit<Property.Accessor, 'type'>): void
333
+ ```
334
+
335
+ Define a computed context property backed by get/set hooks.
336
+
337
+ The accessor is removed when the current fiber unloads. Throws if the name is already declared.
338
+
339
+ - `name` — the context property name.
340
+ - `options` — the `get` hook and optional `set` hook.
341
+
342
+ [Source](https://github.com/deepseek-ai/deepseek-harness/blob/master/vendor/cordis/src/reflect.ts#L56)
343
+
344
+ ### ctx.mixin(name, mixins)
345
+
346
+ ```ts cordis-catalog
347
+ /**
348
+ * Expose selected members of a service directly on `ctx`.
349
+ *
350
+ * Each mixed-in key becomes an accessor that forwards to the service
351
+ * (binding methods to it), so e.g. `ctx.on` forwards to `ctx.events.on`.
352
+ * Mixins are removed when the current fiber unloads.
353
+ *
354
+ * @param name — the context property holding the source service.
355
+ * @param mixins — keys to forward, or a source-key → ctx-key map.
356
+ */
357
+ mixin<K extends string & keyof this>(name: K, mixins: (keyof this & keyof this[K])[] | Dict<string>): void
358
+ mixin<T extends {}>(source: T, mixins: (keyof this & keyof T)[] | Dict<string>): void
359
+ ```
360
+
361
+ Expose selected members of a service directly on `ctx`.
362
+
363
+ Each mixed-in key becomes an accessor that forwards to the service (binding methods to it), so e.g. `ctx.on` forwards to `ctx.events.on`. Mixins are removed when the current fiber unloads.
364
+
365
+ - `name` — the context property holding the source service.
366
+ - `mixins` — keys to forward, or a source-key → ctx-key map.
367
+
368
+ [Source](https://github.com/deepseek-ai/deepseek-harness/blob/master/vendor/cordis/src/reflect.ts#L67)