refactor(experimental)!: classify optional packages and move prototypes

This commit is contained in:
Tianyi Cui committed 2026-10-06 16:41:04 +08:00
1 parent 8666a77482
commit b48384223a
259 files changed
+2366 -1512

No files matched your search

@@ -12,8 +12,8 @@
en: 5656c117648160c8
zh: 7f7c3de8e2ea6d9a
/agent-note-persistent-pty-sessions/decision/package-topology:
en: 0187ac573d06a360
zh: 13e08f4f22bacfff
en: 98d7a77fa6cb717e
zh: b2364ffe4827ac11
/agent-note-persistent-pty-sessions/decision/agent-ownership-and-identity:
en: 9bf79081f102eb51
zh: 34855888f0614b47
@@ -21,8 +21,8 @@
en: 882bbfd3f0dc6e09
zh: a547d6ff5e6ef7a1
/agent-note-persistent-pty-sessions/decision/six-model-facing-tools:
en: b92715f36550c728
zh: e18d7e0e2363347a
en: e124f17351795dba
zh: 9f91f729ca384bb2
/agent-note-persistent-pty-sessions/decision/local-readiness-detection:
en: 8f36f06869bd5367
zh: f3560477a8965cbe
@@ -33,8 +33,8 @@
en: e96a972845bc3513
zh: d76d7dfb80985e9d
/agent-note-persistent-pty-sessions/decision/composition-and-rollout:
en: db49b6dff73d8772
zh: 1f2182fd2c7dc3af
en: 9473f6670c12c8e7
zh: 882f8302007e6026
/agent-note-persistent-pty-sessions/decision/deferred-work:
en: c0ae6d86dd5c0635
zh: 737bd3fda903d5e3
@@ -24,7 +24,7 @@ The implementation supports interactive shells and line-oriented REPLs on Linux
|---|---|---|
| `dsh-terminal` | `TerminalSessionService`, branded `TerminalSessionId`, backend registry, owner-scoped session contract, and result types | `ctx.terminals` |
| `dsh-terminal-bash` | Persistent-shell backend over `ctx.subprocess.spawnTerminal()`: readiness, bounded terminal buffers, sandbox resolution, and owner-aware session lifecycle | registers a backend on `ctx.terminals` |
| `dsh-tool-terminal` | Six model-facing tools, task-runtime integration for background sends, guidance, and UI render intents | registers on `ctx.tools` |
| `dsh-experimental-tool-terminal` | Six model-facing tools, task-runtime integration for background sends, guidance, and UI render intents | registers on `ctx.tools` |
Readiness remains PTY-backend behavior, not a second public contract. The terminal-process provider supplies only substrate facts such as the foreground process group and whether it can prove that group is waiting on input; `dsh-terminal-bash` combines those facts with prompt and silence evidence into the common send result.
@@ -62,9 +62,9 @@ The UI render contract is exact and location-free. `terminal_send` uses terminal
`terminal_send({ sessionId, text, submit?, run_in_background? })` treats `text` as UTF-8 bytes and resolves `submit` to `true` in the tool implementation. When `submit` is true it writes the platform Enter sequence after the text; when false it writes only the text, allowing control characters and REPL fragments without hidden content heuristics. Cancellation marks queued input before signaling the real foreground group, so input cannot execute if an asynchronous pre-write inspection settles afterward. The canceled send retains its reservation until asynchronous foreground signalling settles, so a successor cannot become that signal's target. `enableRunInBackground` defaults to true; false removes `run_in_background` from the schema and rejects the same undeclared argument if a caller forces it through execution.
Foreground sends return a bounded rendered delta and two independent facts: `waitReason` (`stdin_read | inferred_idle | timeout | session_exit`) and `sessionStatus` (`running` or `exited` with exit code or signal). `session_exit` refers to the PTY's top-level shell process, not an arbitrary foreground command whose status the shell consumes. A timeout never implies process exit. `dsh-tool-terminal.maxResultBytes` defaults to 262144, rejects values below 64 so creation acknowledgements retain registry-issued ids, and caps each single-text UTF-8 result after normalized tool or pipeline errors, wait, session, pagination, truncation, generic task-status wrappers, policy denials or short-circuits, and post-execute replacements or blocks; the terminal definitions' last-mile `finalizeContent` callback leaves deliberately structured multi-block policy content unchanged. The renderer reserves suffix space and preserves code-point boundaries instead of treating the backend payload cap as the final model bound.
Foreground sends return a bounded rendered delta and two independent facts: `waitReason` (`stdin_read | inferred_idle | timeout | session_exit`) and `sessionStatus` (`running` or `exited` with exit code or signal). `session_exit` refers to the PTY's top-level shell process, not an arbitrary foreground command whose status the shell consumes. A timeout never implies process exit. `dsh-experimental-tool-terminal.maxResultBytes` defaults to 262144, rejects values below 64 so creation acknowledgements retain registry-issued ids, and caps each single-text UTF-8 result after normalized tool or pipeline errors, wait, session, pagination, truncation, generic task-status wrappers, policy denials or short-circuits, and post-execute replacements or blocks; the terminal definitions' last-mile `finalizeContent` callback leaves deliberately structured multi-block policy content unchanged. The renderer reserves suffix space and preserves code-point boundaries instead of treating the backend payload cap as the final model bound.
With `run_in_background: true`, `dsh-tool-terminal` registers the in-flight send on `ctx.jobs` and returns immediately with `jobId`. The producer places `maxResultBytes` on the task snapshot so `job_output`, terminal kill status, and completion notices enforce the same complete-result cap after generic metadata. `job_output(wait: true)` waits, reads incremental output, and records the final result; `job_kill` resolves the current foreground PGID and delivers a real `SIGINT`, including when the application has disabled terminal `ISIG`, and escalates only through the PTY backend's owned teardown path. If the task surface is absent, background mode fails before writing input. No PTY-specific `sleep` tool or general wake-up API is added.
With `run_in_background: true`, `dsh-experimental-tool-terminal` registers the in-flight send on `ctx.jobs` and returns immediately with `jobId`. The producer places `maxResultBytes` on the task snapshot so `job_output`, terminal kill status, and completion notices enforce the same complete-result cap after generic metadata. `job_output(wait: true)` waits, reads incremental output, and records the final result; `job_kill` resolves the current foreground PGID and delivers a real `SIGINT`, including when the application has disabled terminal `ISIG`, and escalates only through the PTY backend's owned teardown path. If the task surface is absent, background mode fails before writing input. No PTY-specific `sleep` tool or general wake-up API is added.
`terminal_read` pages backward from the newest retained line. The backend enforces both line and UTF-8 byte caps on retained scrollback and the returned page payload, so one oversized line cannot bypass the backend bound; the tool then caps the fully rendered page including pagination and truncation metadata. `truncated` distinguishes retention loss from an ordinary viewport delta.
@@ -122,13 +122,13 @@ plugins:
handoffGraceMs: 500
timeoutMs: 30000
disposeGraceMs: 3000
'@deepseek-ai/dsh-tool-terminal':
'@deepseek-ai/dsh-experimental-tool-terminal':
config:
enableRunInBackground: true
maxResultBytes: 262144
```
The package ships concise tool guidance explaining persistent state, owner isolation, uncertain idle results, cleanup, and the preference for existing one-shot tools when interaction is unnecessary. It does not mount PTY in the base shipped examples: PTY is opt-in through the dedicated composition, while ACP and headless snapshot overlays exercise it. Within an enabled `dsh-tool-terminal` instance, the six tools and `run_in_background` are enabled by default; deployments may disable only the background argument with config.
The package ships concise tool guidance explaining persistent state, owner isolation, uncertain idle results, cleanup, and the preference for existing one-shot tools when interaction is unnecessary. It does not mount PTY in the base shipped examples: PTY is opt-in through the dedicated composition, while ACP and headless snapshot overlays exercise it. Within an enabled `dsh-experimental-tool-terminal` instance, the six tools and `run_in_background` are enabled by default; deployments may disable only the background argument with config.
### Deferred work
@@ -24,7 +24,7 @@ harness 可以运行前台与后台命令、编辑文件和委派工作,但无
|---|---|---|
| `dsh-terminal` | `TerminalSessionService`、branded `TerminalSessionId`、后端注册表、按 owner 隔离的会话约定和结果类型 | `ctx.terminals` |
| `dsh-terminal-bash` | 基于 `ctx.subprocess.spawnTerminal()` 的持久 shell 后端:就绪状态、有界终端缓冲、沙箱解析和感知 owner 的会话生命周期 | 在 `ctx.terminals` 上注册后端 |
| `dsh-tool-terminal` | 6 个面向模型的工具、后台发送的 task 运行时集成、使用指引和 UI 渲染意图 | 注册到 `ctx.tools` |
| `dsh-experimental-tool-terminal` | 6 个面向模型的工具、后台发送的 task 运行时集成、使用指引和 UI 渲染意图 | 注册到 `ctx.tools` |
就绪判定仍属于 PTY 后端行为,不是第二条公共约定。终端进程提供方只提供基底事实,例如前台进程组,以及能否证明该组正在等待输入;`dsh-terminal-bash` 将这些事实与提示符和静默证据组合成统一的发送结果。
@@ -62,9 +62,9 @@ UI 渲染约定精确且不携带位置信息。`terminal_send` 只为前台发
`terminal_send({ sessionId, text, submit?, run_in_background? })` 将 `text` 视为 UTF-8 字节,并由工具实现在解析阶段把 `submit` 默认成 `true`。`submit` 为 true 时先写入文本,再写入平台 Enter 序列;为 false 时只写文本,使控制字符和 REPL 片段无需隐藏的内容启发式即可发送。取消会在向真实前台进程组发送信号前将排队输入标记为已取消,因此即使异步的写入前检查随后才结算,该输入也无法执行。被取消的发送会保留其预留,直至异步前台信号发送结算,因此后续发送不会成为该信号的目标。`enableRunInBackground` 默认为 true;设为 false 时,schema 中会移除 `run_in_background`,调用方即使强行把这个未声明参数传入执行流程,也会被拒绝。
前台发送返回有界的渲染增量和两个独立事实:`waitReason`(`stdin_read | inferred_idle | timeout | session_exit`)与 `sessionStatus`(`running`,或携带退出码或信号的 `exited`)。`session_exit` 指 PTY 顶层 shell 进程退出,不指由 shell 消费状态的任意前台命令。timeout 从不意味着进程已经退出。`dsh-tool-terminal.maxResultBytes` 默认为 262144;低于 64 的值会被拒绝,以确保创建确认保留注册表签发的 id;每个单文本 UTF-8 结果在加入规范化的工具或流水线错误、等待、会话、分页、截断、通用 task 状态包装、策略拒绝或短路以及 post-execute 替换或阻断后,仍受该值限制;终端定义自有的末端 `finalizeContent` callback 会原样保留策略刻意返回的结构化多块内容。渲染器会为后缀预留空间并保持代码点边界,而不会把后端载荷上限当作面向模型结果的最终上限。
前台发送返回有界的渲染增量和两个独立事实:`waitReason`(`stdin_read | inferred_idle | timeout | session_exit`)与 `sessionStatus`(`running`,或携带退出码或信号的 `exited`)。`session_exit` 指 PTY 顶层 shell 进程退出,不指由 shell 消费状态的任意前台命令。timeout 从不意味着进程已经退出。`dsh-experimental-tool-terminal.maxResultBytes` 默认为 262144;低于 64 的值会被拒绝,以确保创建确认保留注册表签发的 id;每个单文本 UTF-8 结果在加入规范化的工具或流水线错误、等待、会话、分页、截断、通用 task 状态包装、策略拒绝或短路以及 post-execute 替换或阻断后,仍受该值限制;终端定义自有的末端 `finalizeContent` callback 会原样保留策略刻意返回的结构化多块内容。渲染器会为后缀预留空间并保持代码点边界,而不会把后端载荷上限当作面向模型结果的最终上限。
当 `run_in_background: true` 时,`dsh-tool-terminal` 在 `ctx.jobs` 上注册进行中的发送,并立即返回 `jobId`。生产方把 `maxResultBytes` 写入 task 快照,使 `job_output`、kill 返回的终态状态和完成通知在加上通用元数据后,仍对完整结果执行同一上限。`job_output(wait: true)` 负责等待、读取增量输出并记录最终结果;`job_kill` 会解析当前前台 PGID 并发送真正的 `SIGINT`,即使应用已禁用终端 `ISIG` 也同样如此,且后续升级仍只通过 PTY 后端拥有的 teardown 路径进行。若 task 对外接口不存在,后台模式必须在写入输入前失败。设计不新增 PTY 专用的 `sleep` 工具或通用唤醒 API。
当 `run_in_background: true` 时,`dsh-experimental-tool-terminal` 在 `ctx.jobs` 上注册进行中的发送,并立即返回 `jobId`。生产方把 `maxResultBytes` 写入 task 快照,使 `job_output`、kill 返回的终态状态和完成通知在加上通用元数据后,仍对完整结果执行同一上限。`job_output(wait: true)` 负责等待、读取增量输出并记录最终结果;`job_kill` 会解析当前前台 PGID 并发送真正的 `SIGINT`,即使应用已禁用终端 `ISIG` 也同样如此,且后续升级仍只通过 PTY 后端拥有的 teardown 路径进行。若 task 对外接口不存在,后台模式必须在写入输入前失败。设计不新增 PTY 专用的 `sleep` 工具或通用唤醒 API。
`terminal_read` 从最新保留行向后分页。后端同时对保留的 scrollback 和返回页载荷执行行数与 UTF-8 字节上限,因此单个超长行无法绕过后端上限;工具随后再限制包含分页与截断元数据的完整渲染页。`truncated` 用于区分保留数据丢失与普通 viewport 增量。
@@ -122,13 +122,13 @@ plugins:
handoffGraceMs: 500
timeoutMs: 30000
disposeGraceMs: 3000
'@deepseek-ai/dsh-tool-terminal':
'@deepseek-ai/dsh-experimental-tool-terminal':
config:
enableRunInBackground: true
maxResultBytes: 262144
```
包提供简洁的工具指引,说明持久状态、owner 隔离、不确定的 idle 结果、清理,以及无需交互时优先使用现有一次性工具。已发布的基础示例不挂载 PTY:PTY 仅通过专用组合 opt-in,而 ACP(Agent Client Protocol)与 headless 快照 overlay 会对其进行验证。`dsh-tool-terminal` 实例一旦启用,6 个工具和 `run_in_background` 就会默认启用;部署可通过配置仅禁用后台参数。
包提供简洁的工具指引,说明持久状态、owner 隔离、不确定的 idle 结果、清理,以及无需交互时优先使用现有一次性工具。已发布的基础示例不挂载 PTY:PTY 仅通过专用组合 opt-in,而 ACP(Agent Client Protocol)与 headless 快照 overlay 会对其进行验证。`dsh-experimental-tool-terminal` 实例一旦启用,6 个工具和 `run_in_background` 就会默认启用;部署可通过配置仅禁用后台参数。
### 推迟的工作
@@ -0,0 +1,19 @@
# Bilingual-pair consistency record for 2026-10-05-product-package-classification.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-10-05-product-package-classification.md
/agent-note-require-product-use-or-an-explicit-package-classification:
en: 8caa2edff065f7db
zh: 163ee0f31c7adc6a
/agent-note-require-product-use-or-an-explicit-package-classification/problem:
en: 748eb2bf5f645911
zh: b123aec22395193a
/agent-note-require-product-use-or-an-explicit-package-classification/decision:
en: 8678a01d48195e8f
zh: 9052cc7f64ed452f
/agent-note-require-product-use-or-an-explicit-package-classification/alternatives-considered:
en: 67177e349ecb70de
zh: e8263b9445f46ded
/agent-note-require-product-use-or-an-explicit-package-classification/consequences:
en: 449278a2bccea70e
zh: 5eb28c22783ac6cf
@@ -0,0 +1,29 @@
# Agent Note: Require product use or an explicit package classification
Status: implemented
English | [中文](2026-10-05-product-package-classification.zh.md)
## Problem
An installation dependency can remain dormant indefinitely. Its presence in the dependency graph does not establish that a shipped profile, runtime import, or optional capability uses it. Conversely, an embedding SDK or a deployment-configured provider can have a maintained product role without appearing in the default GUI.
## Decision
Nonexperimental packages have effective product use or an explicit entry in the [package policy](../../../../scripts/product-package-policy.ts). The policy distinguishes optional integrations, SDKs, build tools, test tools, Web distribution packages, and declaration-only infrastructure. Each exception records its maintained role. [Experimental status](../../../../packages/experimental/README.md#status) describes maturity and support, independently of installation, optional selection, and Official discovery.
The [product-use check](../../../../scripts/verify-product-use.ts) follows effective shipped profiles, preset children, runtime source imports, and explicit dynamic mounts. It preserves disabled state through groups and Includes and applies patches before counting use. Manifest dependencies and type-only references do not create runtime use. Optional-bundle reachability remains separate from default reachability. Unknown packages and invalid or stale policy entries fail static CI and package hygiene.
The [default-product isolation rule](2026-09-12-default-product-experimental-isolation.md) remains independent: its conservative installation and declaration traversal rejects unintended experimental dependencies even when they are disabled. That traversal cannot establish active product use.
## Alternatives considered
**Treat every installed package as used.** A redundant dependency would satisfy its own classification requirement and conceal dormant code.
**Classify every nondefault capability as experimental.** Deployment prerequisites and installation cost do not establish immaturity; supported optional providers and SDKs need separate categories.
**Count every declared patch row.** A disabled Include, missing target, or later replacement can prevent that row from mounting. Only the effective composition establishes use.
## Consequences
Adding a nonexperimental package requires a product consumer or a reviewed classification. Renames and reduced in-box availability require upgrade instructions, while recorded events and released data keep their existing obligations. Regression fixtures reject manifest-only dependencies, disabled subtrees, ineffective patches, and stale classifications. SDK, test, build, and declaration packages remain independently installable without acquiring a runtime mount requirement.
@@ -0,0 +1,29 @@
# Agent Note: Require product use or an explicit package classification
Status: implemented
[English](2026-10-05-product-package-classification.md) | 中文
## 问题
安装依赖可能长期处于休眠状态。出现在依赖图中,并不表明随附 profile、运行时导入或可选能力使用了它。反过来,嵌入式 SDK 或需要部署配置的提供方即使不出现在默认 GUI 中,也可以承担维护中的产品职责。
## 决策
非实验包必须具有有效产品用途,或在[包策略](../../../../scripts/product-package-policy.ts)中显式列出。策略区分可选集成、SDK、构建工具、测试工具、Web 分发包和纯声明基础设施,每个例外记录其维护职责。[实验性状态](../../../../packages/experimental/README.zh.md#status)描述成熟度与支持承诺,独立于安装、可选启用与官方发现。
[产品用途检查](../../../../scripts/verify-product-use.ts)跟踪有效的随附 profile、预设子行、运行时源码导入与显式动态挂载。检查在组与 Include 中保留禁用状态,并先应用 patch 再统计用途。Manifest 依赖和纯类型引用不产生运行时用途。可选组合包的可达关系与默认可达关系分别计算。未知包及无效或过时的策略条目会使静态 CI 和包卫生检查失败。
[默认产品隔离规则](2026-09-12-default-product-experimental-isolation.zh.md)保持独立:其保守的安装与声明遍历即使对已禁用行,也会拒绝意外实验依赖。该遍历不能证明活动产品用途。
## 考虑过的替代方案
**将所有已安装包视为已使用。** 冗余依赖本身就能满足分类要求,从而掩盖休眠代码。
**将所有非默认能力归为实验性。** 部署前提与安装成本不能证明不成熟;受支持的可选提供方与 SDK 需要独立分类。
**统计所有声明的 patch 行。** 禁用的 Include、缺失目标或后续替换都可能阻止该行挂载。只有有效组合才能证明用途。
## 影响
新增非实验包需要产品消费者或经过审查的分类。改名和减少随附可用性需要升级说明,已记录事件和已发布数据继续遵守既有义务。回归 fixture 拒绝只有 manifest 依赖、禁用子树、无效 patch 和过时分类的情况。SDK、测试、构建与声明包仍可独立安装,无需新增运行时挂载。
@@ -6,8 +6,8 @@
en: cd9f68956ba34672
zh: 1fc649c5eb0d3cf4
/agent-note-pi-extensions-bridge/problem:
en: 9bfc5f0c9ff223a6
zh: 7c5f026c94677dd8
en: eb4d3f10c3feedb4
zh: a1a1a75a724c9a8b
/agent-note-pi-extensions-bridge/proposal:
en: 56b36193ca6f829d
zh: a31e226794c1ca90
@@ -8,7 +8,7 @@ English | [中文](2026-10-03-pi-extensions-bridge.zh.md)
Pi 1.0.0 extensions are in-process TypeScript factories `(pi: ExtensionAPI) => void`. A factory subscribes to about forty lifecycle, context, tool, and provider events, registers model tools, slash commands, model providers, and MCP servers, and talks to the user through `ctx.ui` ([extensions guide](https://github.com/earendil-works/pi/blob/v1.0.0/packages/coding-agent/docs/extensions.md), [API types](https://github.com/earendil-works/pi/blob/v1.0.0/packages/coding-agent/src/core/extensions/types.ts)). The API is published and widely used: about 11,000 npm packages carried the `pi-package` keyword in October 2026.
DSH has bridges for two other ecosystems: shell hooks written for Claude Code and Codex ([hooks group](../../../../packages/hooks/README.md)) and Claude Code mods ([compatibility page](../../../../docs/subsystems/claude-code-mods.md)). Pi's extension API is broader than either. It lets one in-process module rewrite the messages of a single request, edit tool arguments, append its own durable records, and continue a finished run. Serving that API from DSH extension points answers two questions: how much of an extension written for another harness runs unchanged, and which DSH core mechanisms are narrower than Pi's.
DSH has bridges for two other ecosystems: shell hooks written for Claude Code and Codex ([hooks group](../../../../packages/experimental/README.md)) and Claude Code mods ([compatibility page](../../../../docs/subsystems/claude-code-mods.md)). Pi's extension API is broader than either. It lets one in-process module rewrite the messages of a single request, edit tool arguments, append its own durable records, and continue a finished run. Serving that API from DSH extension points answers two questions: how much of an extension written for another harness runs unchanged, and which DSH core mechanisms are narrower than Pi's.
## Proposal
@@ -8,7 +8,7 @@ Status: proposed
Pi 1.0.0 的扩展是进程内的 TypeScript 工厂函数 `(pi: ExtensionAPI) => void`。工厂函数订阅约四十个生命周期、上下文、工具与提供方事件,注册模型工具、斜杠命令、模型提供商与 MCP server,并通过 `ctx.ui` 与用户交互([扩展指南](https://github.com/earendil-works/pi/blob/v1.0.0/packages/coding-agent/docs/extensions.md)、[API 类型](https://github.com/earendil-works/pi/blob/v1.0.0/packages/coding-agent/src/core/extensions/types.ts))。该 API 已发布并被广泛使用:截至 2026 年 10 月,npm 上约有 11,000 个包带有 `pi-package` 关键字。
DSH 已为另外两个生态提供桥接:为 Claude Code 与 Codex 编写的 shell 钩子([hooks 组](../../../../packages/hooks/README.zh.md)),以及 Claude Code mods([兼容性页面](../../../../docs/subsystems/claude-code-mods.zh.md))。Pi 的扩展 API 比两者都宽。它允许一个进程内模块改写单次请求的消息、编辑工具参数、追加自己的持久记录,并让已经结束的运行继续。用 DSH 扩展点提供这套 API 可以回答两个问题:为另一个 harness 编写的扩展有多少能原样运行,以及 DSH 的哪些核心机制比 Pi 窄。
DSH 已为另外两个生态提供桥接:为 Claude Code 与 Codex 编写的 shell 钩子([hooks 组](../../../../packages/experimental/README.zh.md)),以及 Claude Code mods([兼容性页面](../../../../docs/subsystems/claude-code-mods.zh.md))。Pi 的扩展 API 比两者都宽。它允许一个进程内模块改写单次请求的消息、编辑工具参数、追加自己的持久记录,并让已经结束的运行继续。用 DSH 扩展点提供这套 API 可以回答两个问题:为另一个 harness 编写的扩展有多少能原样运行,以及 DSH 的哪些核心机制比 Pi 窄。
## 提案
+1 -1
View File
@@ -700,7 +700,7 @@ jobs:
--testTimeout 90000
packages/shell/tool-pwsh/tests/loader.spec.ts
packages/workflow/workflow-ptc/tests/workflow-ptc.spec.ts
packages/workflow/tool-ralph/tests/integration.spec.ts
packages/experimental/tool-ralph/tests/integration.spec.ts
packages/subprocess/subprocess-local/tests/process-exit.spec.ts
# Single stable required check for branch protection: require "all checks
+2 -4
View File
@@ -40,7 +40,6 @@ packages/ @deepseek-ai/dsh-<pkg> workspaces at packages/<group>/<pkg>/
jobs/ background jobs
bundle/ profile bundles
workflow/ workflow execution
webhook/ webhook ingress
todo/ todo_write tool
plan/ logged planning
goal/ session goals
@@ -48,7 +47,6 @@ packages/ @deepseek-ai/dsh-<pkg> workspaces at packages/<group>/<pkg>/
preset/ agent composition
guard/ loop/tool guards
extensions/ runtime self-modification
hooks/ Claude Code/Codex bridges
session/ durable sessions
session-query/ browsing/search/export
attachment/ binary attachments
@@ -66,7 +64,7 @@ packages/ @deepseek-ai/dsh-<pkg> workspaces at packages/<group>/<pkg>/
host/ GUI host
client/ GUI client
mcp/ external tools
experimental/ pre-stable prototypes; public by default with explicit private exceptions
experimental/ evaluated capabilities without a product-support commitment
test-support/ test infrastructure
util/ zero-dependency utilities
python/ Python SDK/runtime (python/README.md)
@@ -78,7 +76,7 @@ scripts/ gates and generators
website/ VitePress documentation projection
```
Package groups: [packages/README.md](packages/README.md).
Package groups: [packages/README.md](packages/README.md). [Experimental status](packages/experimental/README.md#status) is independent of optional delivery; nonexperimental packages need product use or an explicit [classification](scripts/product-package-policy.ts).
## Commands
-6
View File
@@ -116,8 +116,6 @@ flowchart LR
cfg --> plugin_dsh_base_skill
plugin_dsh_base_skill_filesystem["skill-filesystem<br/>@deepseek-ai/dsh-skill-filesystem"]
cfg --> plugin_dsh_base_skill_filesystem
plugin_dsh_base_skill_badge["skill-badge<br/>@deepseek-ai/dsh-skill-badge"]
cfg --> plugin_dsh_base_skill_badge
plugin_dsh_base_tool_skill["tool-skill<br/>@deepseek-ai/dsh-tool-skill"]
cfg --> plugin_dsh_base_tool_skill
plugin_dsh_base_commands["commands<br/>@deepseek-ai/dsh-commands"]
@@ -174,8 +172,6 @@ flowchart LR
cfg --> plugin_dsh_base_tool_todo
plugin_dsh_base_tool_goal["tool-goal<br/>@deepseek-ai/dsh-tool-goal"]
cfg --> plugin_dsh_base_tool_goal
plugin_dsh_base_tool_ralph["tool-ralph<br/>@deepseek-ai/dsh-tool-ralph"]
cfg --> plugin_dsh_base_tool_ralph
plugin_dsh_base_repeat_tool_reminder["repeat-tool-reminder<br/>@deepseek-ai/dsh-repeat-tool-reminder"]
cfg --> plugin_dsh_base_repeat_tool_reminder
plugin_dsh_base_web["web<br/>@deepseek-ai/dsh-web"]
@@ -258,7 +254,6 @@ flowchart LR
| `agent-instructions` | `@deepseek-ai/dsh-agent-instructions` |
| `skill` | `@deepseek-ai/dsh-skill` |
| `skill-filesystem` | `@deepseek-ai/dsh-skill-filesystem` |
| `skill-badge` | `@deepseek-ai/dsh-skill-badge` |
| `tool-skill` | `@deepseek-ai/dsh-tool-skill` |
| `commands` | `@deepseek-ai/dsh-commands` |
| `command-feedback` | `@deepseek-ai/dsh-command-feedback` |
@@ -287,7 +282,6 @@ flowchart LR
| `image-offload` | `@deepseek-ai/dsh-compaction-image-offload` |
| `tool-todo` | `@deepseek-ai/dsh-tool-todo` |
| `tool-goal` | `@deepseek-ai/dsh-tool-goal` |
| `tool-ralph` | `@deepseek-ai/dsh-tool-ralph` |
| `repeat-tool-reminder` | `@deepseek-ai/dsh-repeat-tool-reminder` |
| `web` | `@deepseek-ai/dsh-web` |
| `web-search-deepseek` | `@deepseek-ai/dsh-web-search-deepseek` |
+6 -5
View File
@@ -45,8 +45,6 @@
"@deepseek-ai/dsh-goal-round-driver": "workspace:*",
"@deepseek-ai/dsh-headless": "workspace:*",
"@deepseek-ai/dsh-home-paths": "workspace:*",
"@deepseek-ai/dsh-hooks-claude-code": "workspace:*",
"@deepseek-ai/dsh-hooks-codex": "workspace:*",
"@deepseek-ai/dsh-jobs-local": "workspace:*",
"@deepseek-ai/dsh-launch-environment": "workspace:*",
"@deepseek-ai/dsh-mcp-client": "workspace:*",
@@ -79,7 +77,6 @@
"@deepseek-ai/dsh-tool-jobs": "workspace:*",
"@deepseek-ai/dsh-tool-pwsh": "workspace:*",
"@deepseek-ai/dsh-tool-pwsh-persistent": "workspace:*",
"@deepseek-ai/dsh-tool-ralph": "workspace:*",
"@deepseek-ai/dsh-tool-schedule": "workspace:*",
"@deepseek-ai/dsh-tool-skill": "workspace:*",
"@deepseek-ai/dsh-tool-str-replace-editor": "workspace:*",
@@ -89,8 +86,6 @@
"@deepseek-ai/dsh-tool-web": "workspace:*",
"@deepseek-ai/dsh-tool-workflow": "workspace:*",
"@deepseek-ai/dsh-web-app": "workspace:*",
"@deepseek-ai/dsh-webhook": "workspace:*",
"@deepseek-ai/dsh-webhook-github": "workspace:*",
"@deepseek-ai/dsh-workflow-ptc": "workspace:*",
"@deepseek-ai/schemastery": "workspace:~",
"commander": "^15.0.0",
@@ -107,6 +102,12 @@
"@deepseek-ai/dsh-experimental-tool-worktree": "workspace:*"
},
"devDependencies": {
"@deepseek-ai/dsh-experimental-skill-badge": "workspace:*",
"@deepseek-ai/dsh-experimental-webhook-github": "workspace:*",
"@deepseek-ai/dsh-experimental-webhook": "workspace:*",
"@deepseek-ai/dsh-experimental-tool-ralph": "workspace:*",
"@deepseek-ai/dsh-experimental-hooks-codex": "workspace:*",
"@deepseek-ai/dsh-experimental-hooks-claude-code": "workspace:*",
"@agentclientprotocol/sdk": "1.4.0",
"@deepseek-ai/dsh-acp": "workspace:*",
"@deepseek-ai/dsh-agent": "workspace:*",
+1 -1
View File
@@ -5,7 +5,7 @@ const binScript = fileURLToPath(new URL('./fixtures/dsh-badge/snapshot.ts', impo
const configPath = fileURLToPath(new URL('./fixtures/dsh-badge/cordis.yml', import.meta.url))
const defaultConfigPath = fileURLToPath(new URL('./fixtures/dsh-badge/default.cordis.yml', import.meta.url))
const tsconfigPath = fileURLToPath(new URL('../../../tsconfig.json', import.meta.url))
const badgeAssetsPath = fileURLToPath(new URL('../../../packages/skill/skill-badge/assets/', import.meta.url))
const badgeAssetsPath = fileURLToPath(new URL('../../../packages/experimental/skill-badge/assets/', import.meta.url))
describe('dsh badge assembled snapshot', () => {
it('advertises and loads the opt-in bundled skill through the shipped app', async () => {
+3 -2
View File
@@ -1,5 +1,6 @@
- id: skill-badge
disabled: false
- insert:
- id: skill-badge
name: '@deepseek-ai/dsh-experimental-skill-badge'
- id: skill-filesystem
config:
+8 -1
View File
@@ -11,9 +11,16 @@ const overlayPath = process.argv[2]
if (overlayPath === undefined) throw new Error('dsh-badge snapshot requires an overlay path')
const rootConfigPath = fileURLToPath(new URL('../../../../../packages/bundle/base/tests/fixtures/root.cordis.yml', import.meta.url))
const basePatchPath = fileURLToPath(new URL('../../../../../packages/bundle/base/cordis.patch.yml', import.meta.url))
// The fixture owns the optional provider; the base bundle has no dependency on it.
const overlays = loadOverlayPatches('dsh-badge-snapshot', overlayPath).map(patch => patch.insert === undefined ? patch : {
...patch,
insert: patch.insert.map(row => row.name === '@deepseek-ai/dsh-experimental-skill-badge'
? { ...row, name: import.meta.resolve('@deepseek-ai/dsh-experimental-skill-badge') }
: row),
})
const ctx = await boot('dsh-badge-snapshot', rootConfigPath, [
...loadOverlayPatches('dsh-badge-snapshot', basePatchPath),
...loadOverlayPatches('dsh-badge-snapshot', overlayPath),
...overlays,
])
try {
+2 -2
View File
@@ -3,7 +3,7 @@
- insert:
- id: webhook-runtime
name: '@deepseek-ai/dsh-webhook'
name: '@deepseek-ai/dsh-experimental-webhook'
- id: github-webhook-real-e2e-rule
name: './github-webhook-rule.mjs'
@@ -28,7 +28,7 @@
port: !!js Number(process.env.DSH_GITHUB_WEBHOOK_PORT)
- id: github-webhook-real-e2e-adapter
name: '@deepseek-ai/dsh-webhook-github'
name: '@deepseek-ai/dsh-experimental-webhook-github'
config:
source: github-real-e2e
path: /github
@@ -1,5 +1,5 @@
import z from '@deepseek-ai/schemastery'
import { WebhookRuleId } from '@deepseek-ai/dsh-webhook'
import { WebhookRuleId } from '@deepseek-ai/dsh-experimental-webhook'
export const name = 'github-webhook-real-e2e-rule'
export const inject = ['webhookRuntime']
@@ -0,0 +1,253 @@
/** Exercise the published webhook example from an isolated installed Web profile. */
import { createHmac } from 'node:crypto'
import { createRequire } from 'node:module'
import { existsSync, globSync } from 'node:fs'
import { lstat, mkdir, mkdtemp, readFile, readdir, readlink, realpath, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { dirname, join, relative, sep } from 'node:path'
import { fileURLToPath } from 'node:url'
import { execa } from 'execa'
import yaml from 'js-yaml'
import { expect, it, onTestFinished } from 'vitest'
import { pnpmCommand } from '../../../../scripts/release/process.ts'
import { packedWorkspaceClosure, type WorkspacePackage } from '../../../../packages/sandbox/sandbox-local/tests/packed-workspace-closure.ts'
const root = fileURLToPath(new URL('../../../..', import.meta.url))
const adapter = '@deepseek-ai/dsh-experimental-webhook-github'
const runtime = '@deepseek-ai/dsh-experimental-webhook'
const built = existsSync(join(root, 'apps/cli/lib/bin.js'))
&& existsSync(join(root, 'packages/experimental/webhook-github/lib/index.js'))
const secret = 'packed-webhook-test-secret'
/** Capture workspace dependency links without following their targets. */
async function workspaceLinks(directories: string[]): Promise<Record<string, string>> {
const links: Record<string, string> = {}
for (const directory of directories) {
const modules = join(directory, 'node_modules')
links[modules] = existsSync(modules) ? 'directory' : 'absent'
if (!existsSync(modules)) continue
for (const entry of await readdir(modules, { withFileTypes: true })) {
const path = join(modules, entry.name)
const paths = entry.name.startsWith('@') && entry.isDirectory()
? (await readdir(path)).map(name => join(path, name)) : [path]
for (const dependency of paths) {
const stat = await lstat(dependency)
links[dependency] = stat.isSymbolicLink() ? await readlink(dependency) : stat.isDirectory() ? 'directory' : 'file'
}
}
}
return links
}
/** Reject workspace links throughout the installed dependency tree. */
async function assertInstalledTree(directory: string): Promise<void> {
const installedRoot = await realpath(directory)
const visited = new Set<string>()
const visit = async (path: string): Promise<void> => {
const resolved = await realpath(path)
expect(resolved === installedRoot || resolved.startsWith(installedRoot + sep), `${path} escapes its installation`).toBe(true)
if (visited.has(resolved)) return
visited.add(resolved)
for (const entry of await readdir(path, { withFileTypes: true })) {
const child = join(path, entry.name)
if (entry.isSymbolicLink()) {
const target = await realpath(child)
expect(target.startsWith(installedRoot + sep), `${child} escapes its installation`).toBe(true)
} else if (entry.isDirectory()) await visit(child)
}
}
await visit(directory)
}
it.skipIf(!built)('loads the packed GitHub example with its explicitly installed runtime peer', {
// Packing and installing the complete product closure owns this budget; no model request runs.
timeout: 360_000,
retry: 0,
}, async () => {
const temporary = await realpath(await mkdtemp(join(tmpdir(), 'dsh-webhook-packed-')))
onTestFinished(() => rm(temporary, { recursive: true, force: true }))
const installation = join(temporary, 'installation')
const home = join(temporary, 'home')
const profile = join(home, 'profiles', 'web')
const archives = join(temporary, 'archives')
await mkdir(profile, { recursive: true })
await mkdir(archives)
const environment: NodeJS.ProcessEnv = Object.fromEntries(Object.entries(process.env).filter(([key]) => (
!/KEY|SECRET|TOKEN|PASSWORD/.test(key) && key !== 'NODE_OPTIONS' && key !== 'NODE_PATH'
)))
Object.assign(environment, {
DSH_HOME: home,
DSH_AGENTS_HOME: join(temporary, 'agents'),
DSH_TELEMETRY_DISABLED: '1',
DSH_GITHUB_WEBHOOK_SECRET: secret,
DSH_GITHUB_WEBHOOK_PORT: '0',
CI: 'true',
})
const [pnpm, ...prefix] = pnpmCommand()
const packageCommand = async (args: string[], cwd: string) => {
const result = await execa(pnpm, [...prefix, ...args], {
cwd, env: environment, extendEnv: false, timeout: 180_000, reject: false,
})
expect(result.timedOut, `${result.stdout}\n${result.stderr}`).toBe(false)
expect(result.signal, result.stderr).toBeUndefined()
expect(result.exitCode, `${result.stdout}\n${result.stderr}`).toBe(0)
return result
}
const packages = new Map<string, WorkspacePackage>()
for (const path of globSync([
'apps/*/package.json', 'packages/*/*/package.json', 'vendor/*/package.json', 'native/system/packages/*/package.json',
], { cwd: root })) {
const manifest = JSON.parse(await readFile(join(root, path), 'utf8')) as Record<string, unknown>
if (typeof manifest.name !== 'string') throw new Error(`${path} has no package name`)
packages.set(manifest.name, { name: manifest.name, manifest, directory: dirname(join(root, path)) })
}
const sourceDirectories = [root, ...[...packages.values()].map(member => member.directory)]
const initialLinks = await workspaceLinks(sourceDirectories)
onTestFinished(async () => { expect(await workspaceLinks(sourceDirectories)).toEqual(initialLinks) })
const closure = packedWorkspaceClosure('@deepseek-ai/dsh', packages)
const runtimeMembers = closure.filter(member => (
(!Array.isArray(member.manifest.os) || member.manifest.os.includes(process.platform))
&& (!Array.isArray(member.manifest.cpu) || member.manifest.cpu.includes(process.arch))
))
const members = new Map(runtimeMembers.map(member => [member.name, member]))
for (const name of [runtime, adapter]) {
const member = packages.get(name)
if (member === undefined) throw new Error(`missing workspace package ${name}`)
members.set(name, member)
}
// Packing reads package-owned files; installation never runs in the workspace.
await packageCommand([
'pack', '--recursive', '--workspace-concurrency=4',
...[...members.keys()].map(name => `--filter=${name}`), '--pack-destination', archives,
], root)
const tarballs = new Map([...members.values()].map((member) => {
if (typeof member.manifest.version !== 'string') throw new Error(`${member.name} has no version`)
const name = member.name.replaceAll('/', '-').replace('@', '')
const archive = join(archives, `${name}-${member.manifest.version}.tgz`)
expect(existsSync(archive), `missing packed payload for ${member.name}`).toBe(true)
return [member.name, archive]
}))
const workspaceSettings = yaml.load(await readFile(join(root, 'pnpm-workspace.yaml'), 'utf8')) as {
allowBuilds: Record<string, boolean>
patchedDependencies: Record<string, string>
minimumReleaseAgeExclude: string[]
overrides: Record<string, string>
}
const externalVersions: Record<string, string> = {}
for (const member of members.values()) {
const require = createRequire(join(member.directory, 'package.json'))
for (const section of ['dependencies', 'optionalDependencies', 'peerDependencies']) {
const dependencies = member.manifest[section] as Record<string, string> | undefined
for (const [name, range] of Object.entries(dependencies ?? {})) {
if (range.startsWith('workspace:')) continue
const manifest = require.resolve.paths(name)?.map(path => join(path, name, 'package.json')).find(path => existsSync(path))
if (manifest === undefined) continue
const installed = JSON.parse(await readFile(manifest, 'utf8')) as { version: string }
externalVersions[`${name}@${range}`] = installed.version
}
}
}
await mkdir(installation)
for (const path of Object.values(workspaceSettings.patchedDependencies)) {
await mkdir(dirname(join(installation, path)), { recursive: true })
await writeFile(join(installation, path), await readFile(join(root, path)))
}
await writeFile(join(installation, 'package.json'), JSON.stringify({
name: 'packed-webhook-installation', private: true,
dependencies: Object.fromEntries(runtimeMembers.map(member => [member.name, `file:${tarballs.get(member.name)!}`])),
}))
await writeFile(join(installation, 'pnpm-workspace.yaml'), yaml.dump({
packages: ['.'], nodeLinker: 'hoisted', autoInstallPeers: false, allowUnusedPatches: true,
ignoredOptionalDependencies: closure.filter(member => !members.has(member.name)).map(member => member.name),
allowBuilds: {
...workspaceSettings.allowBuilds,
[`@deepseek-ai/dsh-subprocess-local@file:${relative(installation, tarballs.get('@deepseek-ai/dsh-subprocess-local')!).split(sep).join('/')}`]: true,
},
patchedDependencies: workspaceSettings.patchedDependencies,
minimumReleaseAgeExclude: workspaceSettings.minimumReleaseAgeExclude,
overrides: {
...workspaceSettings.overrides,
...externalVersions,
...Object.fromEntries(runtimeMembers.map(member => [member.name, `file:${tarballs.get(member.name)!}`])),
},
}))
await packageCommand(['install', '--offline', '--no-frozen-lockfile'], installation)
await assertInstalledTree(installation)
expect(existsSync(join(installation, 'node_modules', runtime))).toBe(false)
expect(existsSync(join(installation, 'node_modules', adapter))).toBe(false)
await writeFile(join(profile, 'package.json'), JSON.stringify({
name: 'packed-webhook-profile', private: true, dependencies: {},
dsh: { profile: { bundles: ['@deepseek-ai/dsh-base', '@deepseek-ai/dsh-web-app'] } },
}))
const profileDependencies = new Set([runtime, adapter])
for (const name of profileDependencies) {
const member = members.get(name)
if (member === undefined) throw new Error(`missing packed dependency ${name}`)
for (const [dependency, range] of Object.entries(member.manifest.dependencies as Record<string, string> | undefined ?? {})) {
if (range.startsWith('workspace:')) profileDependencies.add(dependency)
}
}
await writeFile(join(profile, 'pnpm-workspace.yaml'), yaml.dump({
packages: ['.'], nodeLinker: 'hoisted', autoInstallPeers: false,
overrides: {
...externalVersions,
...Object.fromEntries([...profileDependencies].map(name => [name, `file:${tarballs.get(name)!}`])),
},
}))
const adapterArchive = tarballs.get(adapter)
const runtimeArchive = tarballs.get(runtime)
if (adapterArchive === undefined || runtimeArchive === undefined) throw new Error('webhook tarballs were not packed')
await packageCommand(['add', runtimeArchive, adapterArchive, '--offline', '--ignore-scripts'], profile)
const manifest = JSON.parse(await readFile(join(profile, 'package.json'), 'utf8')) as { dependencies: Record<string, string> }
expect(Object.keys(manifest.dependencies).sort()).toEqual([runtime, adapter].sort())
await assertInstalledTree(profile)
const example = join(profile, 'node_modules', adapter, 'examples/github-review/cordis.yml')
expect(existsSync(example)).toBe(true)
expect(existsSync(join(dirname(example), 'github-ready-review-rule.mjs'))).toBe(true)
const observer = join(temporary, 'observe-ingress.mjs')
await writeFile(observer, `export const name = 'observe-packed-ingress'
export const inject = ['webServer', 'webhookRuntime']
export function apply(ctx) {
process.stdout.write('PACKED_WEBHOOK_READY=http://127.0.0.1:' + ctx.webServer.port + '\\n')
}
`)
const patch = join(temporary, 'test.patch.yml')
await writeFile(patch, yaml.dump([
{ id: 'session-telemetry-otel', disabled: true },
{ id: 'github-webhook-ingress', insert: [{ id: 'observe-packed-ingress', name: observer }] },
]))
const child = execa(process.execPath, [
join(installation, 'node_modules/@deepseek-ai/dsh/lib/bin.js'), 'web', '--patch', example, '--patch', patch, '--no-open', '--port', '0',
], { cwd: temporary, env: environment, extendEnv: false, reject: false, timeout: 90_000 })
try {
const ready = new Promise<string>((resolveReady, rejectReady) => {
let output = ''
child.stdout?.on('data', (chunk: Buffer) => {
output += chunk.toString()
const origin = /PACKED_WEBHOOK_READY=(http:\/\/127\.0\.0\.1:\d+)/.exec(output)?.[1]
if (origin !== undefined && output.includes('dsh web: ')) resolveReady(origin)
})
void child.then((result) => {
rejectReady(new Error(`Web profile exited before readiness:\n${result.stdout}\n${result.stderr}`))
})
})
const origin = await ready
expect((await fetch(`${origin}/api`, { signal: AbortSignal.timeout(10_000) })).status).toBe(404)
const body = JSON.stringify({ zen: 'A signed ping does not start an Agent.' })
const response = await fetch(`${origin}/github`, {
method: 'POST', body, signal: AbortSignal.timeout(10_000),
headers: {
'content-type': 'application/json', 'x-github-event': 'ping', 'x-github-delivery': 'packed-ping',
'x-hub-signature-256': `sha256=${createHmac('sha256', secret).update(body).digest('hex')}`,
},
})
expect(response.status, await response.text()).toBe(202)
} finally {
child.kill('SIGTERM')
const result = await child
expect(result.timedOut, `${result.stdout}\n${result.stderr}`).toBe(false)
expect(result.exitCode === 0 || result.signal === 'SIGTERM', result.stderr).toBe(true)
}
expect(globSync('sessions/**/*.jsonl*', { cwd: home })).toEqual([])
})
+1 -1
View File
@@ -93,7 +93,7 @@ async function bootWeb(
// A deployment-level skill on the host registry's GLOBAL layer — the same
// registration shape a repository plugin's skill root uses. The layered
// skills test below proves it reaches preset-composed agents.
{ id: 'skill-badge', disabled: false },
{ insert: [{ id: 'skill-badge', name: '@deepseek-ai/dsh-experimental-skill-badge' }] },
{ id: 'modules', disabled: true },
// The physical Connection row owns the disabled HTTP server. bootWeb
// supplies only its in-process registries so Host services still prove
+2 -2
View File
@@ -9,7 +9,7 @@ import { chromium } from 'playwright'
import { afterAll, beforeAll, describe, expect, it, onTestFailed, onTestFinished, vi } from 'vitest'
import type { GenerateOptions, StreamChunk } from '@deepseek-ai/dsh-llm'
import { LlmAdapter } from '@deepseek-ai/dsh-llm'
import type {} from '@deepseek-ai/dsh-webhook'
import type {} from '@deepseek-ai/dsh-experimental-webhook'
import {
captureExpandedTurnProcessAria,
captureStableAria,
@@ -22,7 +22,7 @@ import {
import { saveFailureShot } from './support.ts'
const MODE = webSnapshotMode()
const OVERLAY = fileURLToPath(new URL('../../cli/config/examples/github-review/cordis.yml', import.meta.url))
const OVERLAY = fileURLToPath(new URL('../../../packages/experimental/webhook-github/examples/github-review/cordis.yml', import.meta.url))
const EXPECTED = fileURLToPath(new URL('./expected/github-ready-review/conversation.expected.md', import.meta.url))
const EXPANDED_EXPECTED = fileURLToPath(
new URL('./expected/github-ready-review/conversation-expanded.expected.md', import.meta.url),
+4 -4
View File
@@ -18,8 +18,8 @@
en: b9eeb18645121a8b
zh: 70d87a12c43e042a
/deepseek-harness-architecture/core-packages:
en: 651ad3fefe270b64
zh: 85b82b5d327dcbca
en: 20ef882e44b06a10
zh: c10c3934ed5570e9
/deepseek-harness-architecture/events:
en: 214c3c81c21df6f9
zh: 75d2cdc3c9fc9930
@@ -33,5 +33,5 @@
en: 93d1dc2eeda4aec2
zh: ee7a9da89151ea17
/deepseek-harness-architecture/where-new-behavior-goes:
en: 9b2eb0539a9cd0d6
zh: 4f575277b91d4e5c
en: 3cbf3d7d6094fa44
zh: 015a848652d90f54
+1 -2
View File
@@ -63,7 +63,6 @@ Electron starts the private Desktop Host in Electron Node mode. The Host invokes
| [`core/agent-loop`](subsystems/core.md) | The default driver implementing that interface | `ctx.agentLoop` |
| [`core/scope`](subsystems/scope.md) | The per-agent scoped-registration primitive | library, no key |
| [`llm/llm`](subsystems/llm-streaming.md) | Message and stream vocabulary plus the adapter seam | `ctx.llm` |
| [`webhook/webhook`](subsystems/webhook.md) | Authenticated-delivery dispatch and Workspace Session creation | `ctx.webhookRuntime` |
## Events
@@ -146,7 +145,7 @@ New behavior attaches to a documented extension point. Changing the loop itself
| Add a model-facing capability | register on `ctx.tools`; its schema joins prompt assembly |
| Give one session a different capability set | compose an agent preset; a service row there needs an `isolate` realm |
| Add shell execution | register a `ctx.shell` backend; the local one spawns through `ctx.subprocess` |
| Add persistent terminal execution | register a `ctx.terminals` backend plus `dsh-tool-terminal` |
| Add persistent terminal execution | register a `ctx.terminals` backend plus `dsh-experimental-tool-terminal` |
| Add a human command | register on `ctx.commands`; it dispatches without a model turn |
| Manage background jobs | register on `ctx.jobs`; `job_*` tools read or stop jobs |
| Start a Session from an external webhook | register a trusted rule on `ctx.webhookRuntime` and mount a provider adapter |
+1 -2
View File
@@ -63,7 +63,6 @@ Electron 使用 Electron Node 模式启动私有 Desktop Host。Host 调用共
| [`core/agent-loop`](subsystems/core.zh.md) | 实现该接口的默认驱动器 | `ctx.agentLoop` |
| [`core/scope`](subsystems/scope.zh.md) | 按 agent 划分作用域的注册原语 | 库,无 ctx 键 |
| [`llm/llm`](subsystems/llm-streaming.zh.md) | 消息与流式词汇表,以及适配器 seam | `ctx.llm` |
| [`webhook/webhook`](subsystems/webhook.zh.md) | 已认证 delivery 的分派和 Workspace Session 创建 | `ctx.webhookRuntime` |
<a id="events"></a>
@@ -150,7 +149,7 @@ seam 正是替换一个提供方就能改变整个产品的原因。文件系统
| 添加面向模型的能力 | 在 `ctx.tools` 上注册;其 schema 加入提示词组装 |
| 让某个会话拥有不同的能力集合 | 组装一个 agent preset;其中的服务行需要 `isolate` realm |
| 添加 shell 执行 | 注册 `ctx.shell` 后端;本地后端通过 `ctx.subprocess` spawn 进程 |
| 添加持久化终端执行 | 注册 `ctx.terminals` 后端和 `dsh-tool-terminal` |
| 添加持久化终端执行 | 注册 `ctx.terminals` 后端和 `dsh-experimental-tool-terminal` |
| 添加用户命令 | 在 `ctx.commands` 上注册;它无需模型轮次即可分派 |
| 管理后台任务 | 在 `ctx.jobs` 上注册;`job_*` 工具读取或停止任务 |
| 从外部 webhook 启动 Session | 在 `ctx.webhookRuntime` 上注册可信规则,并挂载提供方适配器 |
+2 -2
View File
@@ -21,5 +21,5 @@
en: f0a28d07c0bb4d1b
zh: 840962f512cb4031
/cookbook-extension-plugin-shapes/the-feature-mechanism-map:
en: fa917d46c071fad2
zh: 4062805237e2c847
en: abe512b526ffbefd
zh: 6bae5440248441f3
+1 -1
View File
@@ -103,7 +103,7 @@ Every product feature maps to a listener on a documented extension point — the
| Product feature | Plugin mechanism |
|---|---|
| Hook system (user + project level) | listeners on `agent/created`, `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 |
| Hook system (user + project level) | listeners on `agent/created`, `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-experimental-hooks-claude-code` / `dsh-experimental-hooks-codex` bridges map hook config files onto these extension points |
| `/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 |
| `/loop` | on the `turn/end` session event, `followup()` the next iteration; or force-continue |
| Dynamic workflow | `ctx.workflowEngine` + the PTC workflow 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 |
+1 -1
View File
@@ -107,7 +107,7 @@ export function apply(ctx: Context) {
| 产品功能 | 插件机制 |
|---|---|
| 钩子系统(用户级 + 项目级) | `agent/created`、`agent/pre-step`、`agent/request`、`tools/pre-execute`、`tools/post-execute` 和 `agent/turn-stopping` 上的监听器;waterfall 返回类型化决策,`agent/turn-stopping` 则可通过 steering(中途引导)触发下一步;`dsh-hooks-claude-code` / `dsh-hooks-codex` 桥接器将钩子配置文件映射到这些扩展点上 |
| 钩子系统(用户级 + 项目级) | `agent/created`、`agent/pre-step`、`agent/request`、`tools/pre-execute`、`tools/post-execute` 和 `agent/turn-stopping` 上的监听器;waterfall 返回类型化决策,`agent/turn-stopping` 则可通过 steering(中途引导)触发下一步;`dsh-experimental-hooks-claude-code` / `dsh-experimental-hooks-codex` 桥接器将钩子配置文件映射到这些扩展点上 |
| `/goal` | `ctx.goals` 管理持久状态,`dsh-goal-round-driver` 通过公共 `Agent` 调度同会话 Round,独立的命令/工具生产方分别提供人类/模型控制 |
| `/loop` | 在 `turn/end` 会话事件上 `followup()` 下一次迭代;或强制继续 |
| 动态工作流 | `ctx.workflowEngine` + PTC 工作流引擎 + `workflow` 工具;结构化的进程内子任务通过作用域化的提示词/工具注册、单调工具守卫、最终 `tools/result` 提交(包括外层 `run_code`)和结构化输出执行的单调 `concludeTurn()` 标记来强制输出 |
@@ -57,12 +57,12 @@ Save the input as `.artifacts/persistence-change.prose.json`, creating the ignor
"en": {
"summary": "Makes the persisted hook audit decision optional.",
"compatibility": "Existing records remain valid. Hook execution consumes HookOutput instead of replaying this audit field. Producers still write decisions, and absence does not imply pass.",
"verification": "pnpm exec vitest run packages/hooks/hook-protocol/tests/events.spec.ts: 10 tests passed."
"verification": "pnpm exec vitest run packages/experimental/hook-protocol/tests/events.spec.ts: 10 tests passed."
},
"zh": {
"summary": "将持久化的钩子审计决策改为可选。",
"compatibility": "已有记录仍然有效。钩子执行消费 HookOutput,不回放此审计字段。写入方仍然记录决策,缺失不代表 pass。",
"verification": "pnpm exec vitest run packages/hooks/hook-protocol/tests/events.spec.ts:10 个测试通过。"
"verification": "pnpm exec vitest run packages/experimental/hook-protocol/tests/events.spec.ts:10 个测试通过。"
}
}
```
@@ -57,12 +57,12 @@ pnpm --silent run persistence-review --before .artifacts/base.schema.json --afte
"en": {
"summary": "Makes the persisted hook audit decision optional.",
"compatibility": "Existing records remain valid. Hook execution consumes HookOutput instead of replaying this audit field. Producers still write decisions, and absence does not imply pass.",
"verification": "pnpm exec vitest run packages/hooks/hook-protocol/tests/events.spec.ts: 10 tests passed."
"verification": "pnpm exec vitest run packages/experimental/hook-protocol/tests/events.spec.ts: 10 tests passed."
},
"zh": {
"summary": "将持久化的钩子审计决策改为可选。",
"compatibility": "已有记录仍然有效。钩子执行消费 HookOutput,不回放此审计字段。写入方仍然记录决策,缺失不代表 pass。",
"verification": "pnpm exec vitest run packages/hooks/hook-protocol/tests/events.spec.ts:10 个测试通过。"
"verification": "pnpm exec vitest run packages/experimental/hook-protocol/tests/events.spec.ts:10 个测试通过。"
}
}
```
+18 -18
View File
@@ -108,11 +108,11 @@
en: 8d6fa78d450a0e56
zh: 8d6fa78d450a0e56
/session-persistence-event-catalog/events/hook/hook-invoked-log-only:
en: 7e87780c1e9328b7
zh: 79b535ed8a26bc4f
en: 705ffb04951178a1
zh: 6031b9e7b48f5549
/session-persistence-event-catalog/events/hook/hook-result-log-only:
en: 5479d86486adbc40
zh: b9df61258535c7da
en: b84c2cbfca534935
zh: ee1d71fad6dfb896
/session-persistence-event-catalog/events/image:
en: 4378f94cd30a2ba8
zh: 4378f94cd30a2ba8
@@ -1020,11 +1020,11 @@
en: d13de5c951afd4e5
zh: 44069b6d0f3b8303
/session-persistence-event-catalog/resolved-persistence-types/headerline:
en: 0228dc7dcff3ff5a
zh: bfab168767453f00
en: d0e4b453af58af7f
zh: 8209d2206840b137
/session-persistence-event-catalog/resolved-persistence-types/hookdialect:
en: c8420c48f6167ad9
zh: a6dc3dc1ee50ea81
en: c5418d1e906e9114
zh: 0bc528427386d8a4
/session-persistence-event-catalog/resolved-persistence-types/imageattachmentref:
en: 76ee1e266cd651da
zh: 55c7c95a223ccbed
@@ -1296,11 +1296,11 @@
en: 5e7d82a493a1d4d8
zh: d2d785891dd766fc
/session-persistence-event-catalog/resolved-persistence-types/number~2:
en: 38211d71372021e4
zh: c0305af81a67e285
en: 386989934d1bb62e
zh: 69b8bc182a5acbd3
/session-persistence-event-catalog/resolved-persistence-types/string:
en: 052f9ce1988e44f2
zh: 5adaad6c9bca43e2
en: 21a0bfa3d2e4d775
zh: e1d212b7cbc37c35
/session-persistence-event-catalog/resolved-persistence-types/string~2:
en: 0089620bf4638263
zh: 1922bef1713094bb
@@ -1413,8 +1413,8 @@
en: 1bc55be85a68f0a3
zh: 9e84a55ed11bba5d
/session-persistence-event-catalog/resolved-persistence-types/decision-durationms-exitcode-handlerid:
en: ed8ca43bb7622393
zh: 697e1ccbe9439aa9
en: a99ac57bbec0370f
zh: 9073329e324a66e0
/session-persistence-event-catalog/resolved-persistence-types/delayms-failure-maxretries-mode:
en: 27987dc154def5d8
zh: 7dd493f04daa654f
@@ -1428,8 +1428,8 @@
en: a07969828eed2e6f
zh: e06893743af544b5
/session-persistence-event-catalog/resolved-persistence-types/dialect-handlerid-matcher-point:
en: afb33a900f77ddf6
zh: 90edc32643550430
en: eeba88520aacd126
zh: 8e2ca4e2bd2c1e3a
/session-persistence-event-catalog/resolved-persistence-types/end-start:
en: 4b7a8793663d3fef
zh: 249459c825d330c3
@@ -1809,8 +1809,8 @@
en: 77a8fc6a2f3a9319
zh: 4dc1de1358b51a8d
/session-persistence-event-catalog/resolved-persistence-types/kind-webhook-form-notice:
en: ebced4ba6c43c34b
zh: 627c660edbf5030c
en: 0b74295f7c5c8f11
zh: 5f1213cec87f6be0
/session-persistence-event-catalog/resolved-persistence-types/kind-working-directory:
en: 9848d783b7b5af16
zh: f161eaf1a841cd55
+14 -14
View File
@@ -583,7 +583,7 @@ Source: [`packages/goal/goal/src/domain.ts:66`](../packages/goal/goal/src/domain
}
```
Source: [`packages/hooks/hook-protocol/src/types.ts:19`](../packages/hooks/hook-protocol/src/types.ts)
Source: [`packages/experimental/hook-protocol/src/types.ts:19`](../packages/experimental/hook-protocol/src/types.ts)
<a id="hookresult--log-only"></a>
@@ -606,7 +606,7 @@ Source: [`packages/hooks/hook-protocol/src/types.ts:19`](../packages/hooks/hook-
}
```
Source: [`packages/hooks/hook-protocol/src/types.ts:31`](../packages/hooks/hook-protocol/src/types.ts)
Source: [`packages/experimental/hook-protocol/src/types.ts:31`](../packages/experimental/hook-protocol/src/types.ts)
### `image/*`
@@ -3582,13 +3582,13 @@ Sources: [`packages/session/session-persistence-jsonl/src/format.ts:83`](../pack
<a id="persistence-type-hookdialect"></a>
<a id="persistence-type-packageshookshook-protocolsrctypestshookdialect"></a>
<a id="persistence-type-packagesexperimentalhook-protocolsrctypestshookdialect"></a>
### `HookDialect`
SHA-256: `a6b41f5bede8094d7bf635be5d69b1bd7a25e006ca9cf9415bceb9322f1a7feb`
Sources: [`packages/hooks/hook-protocol/src/types.ts:48`](../packages/hooks/hook-protocol/src/types.ts)
Sources: [`packages/experimental/hook-protocol/src/types.ts:48`](../packages/experimental/hook-protocol/src/types.ts)
One of:
@@ -5315,6 +5315,12 @@ Array of `number`.
<a id="persistence-type-packagesexperimentalagent-teamsrctypeststeamtaskid"></a>
<a id="persistence-type-packagesexperimentalwebhooksrcbrandtswebhookdeliveryid"></a>
<a id="persistence-type-packagesexperimentalwebhooksrcbrandtswebhookruleid"></a>
<a id="persistence-type-packagesexperimentalwebhooksrcbrandtswebhooksourceid"></a>
<a id="persistence-type-packagesfeedbackmessage-feedbacksrctypestsmessagefeedbackversion"></a>
<a id="persistence-type-packagesgoalgoalsrctypestsgoalid"></a>
@@ -5339,12 +5345,6 @@ Array of `number`.
<a id="persistence-type-packagessessionsession-titlesrctypestssessiontitleproviderid"></a>
<a id="persistence-type-packageswebhookwebhooksrcbrandtswebhookdeliveryid"></a>
<a id="persistence-type-packageswebhookwebhooksrcbrandtswebhookruleid"></a>
<a id="persistence-type-packageswebhookwebhooksrcbrandtswebhooksourceid"></a>
<a id="persistence-type-packagesworkflowworkflowsrctypestsworkflowrunid"></a>
<a id="persistence-type-providerrequestid"></a>
@@ -5381,7 +5381,7 @@ Array of `number`.
SHA-256: `4cd48f3e5108bd6ebedf7301c3638839b8b2b9db8dbd493974177fbdeb91a01b`
Sources: [`packages/api/session-controller/src/types.ts:398`](../packages/api/session-controller/src/types.ts) · [`packages/attachment/attachment/src/brand.ts:6`](../packages/attachment/attachment/src/brand.ts) · [`packages/compaction/compaction/src/brand.ts:4`](../packages/compaction/compaction/src/brand.ts) · [`packages/core/session/src/types.ts:20`](../packages/core/session/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:20`](../packages/experimental/agent-team/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:32`](../packages/experimental/agent-team/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:8`](../packages/experimental/agent-team/src/types.ts) · [`packages/feedback/message-feedback/src/types.ts:14`](../packages/feedback/message-feedback/src/types.ts) · [`packages/goal/goal/src/types.ts:17`](../packages/goal/goal/src/types.ts) · [`packages/interaction/commands/src/brand.ts:31`](../packages/interaction/commands/src/brand.ts) · [`packages/interaction/user-approval/src/types.ts:17`](../packages/interaction/user-approval/src/types.ts) · [`packages/llm/llm-retry/src/brand.ts:4`](../packages/llm/llm-retry/src/brand.ts) · [`packages/llm/llm/src/brand.ts:16`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:31`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:43`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:67`](../packages/llm/llm/src/brand.ts) · [`packages/schedule/schedule/src/types.ts:14`](../packages/schedule/schedule/src/types.ts) · [`packages/session/session-title/src/index.ts:42`](../packages/session/session-title/src/index.ts) · [`packages/session/session-title/src/types.ts:17`](../packages/session/session-title/src/types.ts) · [`packages/webhook/webhook/src/brand.ts:12`](../packages/webhook/webhook/src/brand.ts) · [`packages/webhook/webhook/src/brand.ts:6`](../packages/webhook/webhook/src/brand.ts) · [`packages/webhook/webhook/src/brand.ts:9`](../packages/webhook/webhook/src/brand.ts) · [`packages/workflow/workflow/src/types.ts:13`](../packages/workflow/workflow/src/types.ts)
Sources: [`packages/api/session-controller/src/types.ts:398`](../packages/api/session-controller/src/types.ts) · [`packages/attachment/attachment/src/brand.ts:6`](../packages/attachment/attachment/src/brand.ts) · [`packages/compaction/compaction/src/brand.ts:4`](../packages/compaction/compaction/src/brand.ts) · [`packages/core/session/src/types.ts:20`](../packages/core/session/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:20`](../packages/experimental/agent-team/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:32`](../packages/experimental/agent-team/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:8`](../packages/experimental/agent-team/src/types.ts) · [`packages/experimental/webhook/src/brand.ts:12`](../packages/experimental/webhook/src/brand.ts) · [`packages/experimental/webhook/src/brand.ts:6`](../packages/experimental/webhook/src/brand.ts) · [`packages/experimental/webhook/src/brand.ts:9`](../packages/experimental/webhook/src/brand.ts) · [`packages/feedback/message-feedback/src/types.ts:14`](../packages/feedback/message-feedback/src/types.ts) · [`packages/goal/goal/src/types.ts:17`](../packages/goal/goal/src/types.ts) · [`packages/interaction/commands/src/brand.ts:31`](../packages/interaction/commands/src/brand.ts) · [`packages/interaction/user-approval/src/types.ts:17`](../packages/interaction/user-approval/src/types.ts) · [`packages/llm/llm-retry/src/brand.ts:4`](../packages/llm/llm-retry/src/brand.ts) · [`packages/llm/llm/src/brand.ts:16`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:31`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:43`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:67`](../packages/llm/llm/src/brand.ts) · [`packages/schedule/schedule/src/types.ts:14`](../packages/schedule/schedule/src/types.ts) · [`packages/session/session-title/src/index.ts:42`](../packages/session/session-title/src/index.ts) · [`packages/session/session-title/src/types.ts:17`](../packages/session/session-title/src/types.ts) · [`packages/workflow/workflow/src/types.ts:13`](../packages/workflow/workflow/src/types.ts)
`string`
@@ -5876,7 +5876,7 @@ Sources: [`packages/session/working-directory/src/index.ts:36`](../packages/sess
SHA-256: `8ad45ad053b4d89f8865c17cc9ff3b8748e86045f3f0fb816269a34af2619141`
Sources: [`packages/hooks/hook-protocol/src/types.ts:31`](../packages/hooks/hook-protocol/src/types.ts)
Sources: [`packages/experimental/hook-protocol/src/types.ts:31`](../packages/experimental/hook-protocol/src/types.ts)
| Property | Presence | Type |
|---|---|---|
@@ -5956,7 +5956,7 @@ Array of [`{ description, name }`](#persistence-type-sha256-83079c8a3f733ac3fa60
SHA-256: `119abe2b9c0b2f46ecb31d82b9acba4d4b30e049f655e2475e8b4ae12d5a9e25`
Sources: [`packages/hooks/hook-protocol/src/types.ts:19`](../packages/hooks/hook-protocol/src/types.ts)
Sources: [`packages/experimental/hook-protocol/src/types.ts:19`](../packages/experimental/hook-protocol/src/types.ts)
| Property | Presence | Type |
|---|---|---|
@@ -7446,7 +7446,7 @@ Sources: [`packages/interaction/user-questions/src/types.ts:117`](../packages/in
SHA-256: `9edc162949abf93bd5ff049191b345454ba104f583937ce5580fb50f067d2b94`
Sources: [`packages/webhook/webhook/src/types.ts:74`](../packages/webhook/webhook/src/types.ts)
Sources: [`packages/experimental/webhook/src/types.ts:74`](../packages/experimental/webhook/src/types.ts)
| Property | Presence | Type |
|---|---|---|
+14 -14
View File
@@ -585,7 +585,7 @@ export type SessionEvent<T extends SessionEventType = SessionEventType> = {
}
```
来源:[`packages/hooks/hook-protocol/src/types.ts:19`](../packages/hooks/hook-protocol/src/types.ts)
来源:[`packages/experimental/hook-protocol/src/types.ts:19`](../packages/experimental/hook-protocol/src/types.ts)
<a id="hookresult--log-only"></a>
@@ -608,7 +608,7 @@ export type SessionEvent<T extends SessionEventType = SessionEventType> = {
}
```
来源:[`packages/hooks/hook-protocol/src/types.ts:31`](../packages/hooks/hook-protocol/src/types.ts)
来源:[`packages/experimental/hook-protocol/src/types.ts:31`](../packages/experimental/hook-protocol/src/types.ts)
### `image/*`
@@ -3584,13 +3584,13 @@ SHA-256: `18ee62b8900a4c3d046700f05d7a4d49d6cab2a660a020c87481d1603dd8bd4f`
<a id="persistence-type-hookdialect"></a>
<a id="persistence-type-packageshookshook-protocolsrctypestshookdialect"></a>
<a id="persistence-type-packagesexperimentalhook-protocolsrctypestshookdialect"></a>
### `HookDialect`
SHA-256: `a6b41f5bede8094d7bf635be5d69b1bd7a25e006ca9cf9415bceb9322f1a7feb`
来源:[`packages/hooks/hook-protocol/src/types.ts:48`](../packages/hooks/hook-protocol/src/types.ts)
来源:[`packages/experimental/hook-protocol/src/types.ts:48`](../packages/experimental/hook-protocol/src/types.ts)
以下类型之一:
@@ -5317,6 +5317,12 @@ SHA-256: `5d03ba38734809bcbd2a55221bd938b3b3fc34b49bb686c6113e9e4931e3aa78`
<a id="persistence-type-packagesexperimentalagent-teamsrctypeststeamtaskid"></a>
<a id="persistence-type-packagesexperimentalwebhooksrcbrandtswebhookdeliveryid"></a>
<a id="persistence-type-packagesexperimentalwebhooksrcbrandtswebhookruleid"></a>
<a id="persistence-type-packagesexperimentalwebhooksrcbrandtswebhooksourceid"></a>
<a id="persistence-type-packagesfeedbackmessage-feedbacksrctypestsmessagefeedbackversion"></a>
<a id="persistence-type-packagesgoalgoalsrctypestsgoalid"></a>
@@ -5341,12 +5347,6 @@ SHA-256: `5d03ba38734809bcbd2a55221bd938b3b3fc34b49bb686c6113e9e4931e3aa78`
<a id="persistence-type-packagessessionsession-titlesrctypestssessiontitleproviderid"></a>
<a id="persistence-type-packageswebhookwebhooksrcbrandtswebhookdeliveryid"></a>
<a id="persistence-type-packageswebhookwebhooksrcbrandtswebhookruleid"></a>
<a id="persistence-type-packageswebhookwebhooksrcbrandtswebhooksourceid"></a>
<a id="persistence-type-packagesworkflowworkflowsrctypestsworkflowrunid"></a>
<a id="persistence-type-providerrequestid"></a>
@@ -5383,7 +5383,7 @@ SHA-256: `5d03ba38734809bcbd2a55221bd938b3b3fc34b49bb686c6113e9e4931e3aa78`
SHA-256: `4cd48f3e5108bd6ebedf7301c3638839b8b2b9db8dbd493974177fbdeb91a01b`
来源:[`packages/api/session-controller/src/types.ts:398`](../packages/api/session-controller/src/types.ts) · [`packages/attachment/attachment/src/brand.ts:6`](../packages/attachment/attachment/src/brand.ts) · [`packages/compaction/compaction/src/brand.ts:4`](../packages/compaction/compaction/src/brand.ts) · [`packages/core/session/src/types.ts:20`](../packages/core/session/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:20`](../packages/experimental/agent-team/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:32`](../packages/experimental/agent-team/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:8`](../packages/experimental/agent-team/src/types.ts) · [`packages/feedback/message-feedback/src/types.ts:14`](../packages/feedback/message-feedback/src/types.ts) · [`packages/goal/goal/src/types.ts:17`](../packages/goal/goal/src/types.ts) · [`packages/interaction/commands/src/brand.ts:31`](../packages/interaction/commands/src/brand.ts) · [`packages/interaction/user-approval/src/types.ts:17`](../packages/interaction/user-approval/src/types.ts) · [`packages/llm/llm-retry/src/brand.ts:4`](../packages/llm/llm-retry/src/brand.ts) · [`packages/llm/llm/src/brand.ts:16`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:31`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:43`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:67`](../packages/llm/llm/src/brand.ts) · [`packages/schedule/schedule/src/types.ts:14`](../packages/schedule/schedule/src/types.ts) · [`packages/session/session-title/src/index.ts:42`](../packages/session/session-title/src/index.ts) · [`packages/session/session-title/src/types.ts:17`](../packages/session/session-title/src/types.ts) · [`packages/webhook/webhook/src/brand.ts:12`](../packages/webhook/webhook/src/brand.ts) · [`packages/webhook/webhook/src/brand.ts:6`](../packages/webhook/webhook/src/brand.ts) · [`packages/webhook/webhook/src/brand.ts:9`](../packages/webhook/webhook/src/brand.ts) · [`packages/workflow/workflow/src/types.ts:13`](../packages/workflow/workflow/src/types.ts)
来源:[`packages/api/session-controller/src/types.ts:398`](../packages/api/session-controller/src/types.ts) · [`packages/attachment/attachment/src/brand.ts:6`](../packages/attachment/attachment/src/brand.ts) · [`packages/compaction/compaction/src/brand.ts:4`](../packages/compaction/compaction/src/brand.ts) · [`packages/core/session/src/types.ts:20`](../packages/core/session/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:20`](../packages/experimental/agent-team/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:32`](../packages/experimental/agent-team/src/types.ts) · [`packages/experimental/agent-team/src/types.ts:8`](../packages/experimental/agent-team/src/types.ts) · [`packages/experimental/webhook/src/brand.ts:12`](../packages/experimental/webhook/src/brand.ts) · [`packages/experimental/webhook/src/brand.ts:6`](../packages/experimental/webhook/src/brand.ts) · [`packages/experimental/webhook/src/brand.ts:9`](../packages/experimental/webhook/src/brand.ts) · [`packages/feedback/message-feedback/src/types.ts:14`](../packages/feedback/message-feedback/src/types.ts) · [`packages/goal/goal/src/types.ts:17`](../packages/goal/goal/src/types.ts) · [`packages/interaction/commands/src/brand.ts:31`](../packages/interaction/commands/src/brand.ts) · [`packages/interaction/user-approval/src/types.ts:17`](../packages/interaction/user-approval/src/types.ts) · [`packages/llm/llm-retry/src/brand.ts:4`](../packages/llm/llm-retry/src/brand.ts) · [`packages/llm/llm/src/brand.ts:16`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:31`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:43`](../packages/llm/llm/src/brand.ts) · [`packages/llm/llm/src/brand.ts:67`](../packages/llm/llm/src/brand.ts) · [`packages/schedule/schedule/src/types.ts:14`](../packages/schedule/schedule/src/types.ts) · [`packages/session/session-title/src/index.ts:42`](../packages/session/session-title/src/index.ts) · [`packages/session/session-title/src/types.ts:17`](../packages/session/session-title/src/types.ts) · [`packages/workflow/workflow/src/types.ts:13`](../packages/workflow/workflow/src/types.ts)
`string`
@@ -5878,7 +5878,7 @@ SHA-256: `da60ed58a8fa23d7aa4920ab5c1f4e3d28109cb0797ef9e5c8b125721b847582`
SHA-256: `8ad45ad053b4d89f8865c17cc9ff3b8748e86045f3f0fb816269a34af2619141`
来源:[`packages/hooks/hook-protocol/src/types.ts:31`](../packages/hooks/hook-protocol/src/types.ts)
来源:[`packages/experimental/hook-protocol/src/types.ts:31`](../packages/experimental/hook-protocol/src/types.ts)
| 属性 | 存在性 | 类型 |
|---|---|---|
@@ -5958,7 +5958,7 @@ SHA-256: `aba175fb20ffc71112c55efe70458ff5d7dbfb83501892b4ba8d077f0ea5d7ba`
SHA-256: `119abe2b9c0b2f46ecb31d82b9acba4d4b30e049f655e2475e8b4ae12d5a9e25`
来源:[`packages/hooks/hook-protocol/src/types.ts:19`](../packages/hooks/hook-protocol/src/types.ts)
来源:[`packages/experimental/hook-protocol/src/types.ts:19`](../packages/experimental/hook-protocol/src/types.ts)
| 属性 | 存在性 | 类型 |
|---|---|---|
@@ -7448,7 +7448,7 @@ SHA-256: `c55827fba7018198772c50e37cb7d3f60a3d8bb6e94b07de72dee0d9f8968005`
SHA-256: `9edc162949abf93bd5ff049191b345454ba104f583937ce5580fb50f067d2b94`
来源:[`packages/webhook/webhook/src/types.ts:74`](../packages/webhook/webhook/src/types.ts)
来源:[`packages/experimental/webhook/src/types.ts:74`](../packages/experimental/webhook/src/types.ts)
| 属性 | 存在性 | 类型 |
|---|---|---|
+11 -11
View File
@@ -22223,7 +22223,7 @@
"digest": "119abe2b9c0b2f46ecb31d82b9acba4d4b30e049f655e2475e8b4ae12d5a9e25",
"names": [],
"sources": [
"packages/hooks/hook-protocol/src/types.ts:19"
"packages/experimental/hook-protocol/src/types.ts:19"
]
},
{
@@ -23110,6 +23110,9 @@
"packages/experimental/agent-team/src/types.ts#TeamId",
"packages/experimental/agent-team/src/types.ts#TeamMessageId",
"packages/experimental/agent-team/src/types.ts#TeamTaskId",
"packages/experimental/webhook/src/brand.ts#WebhookDeliveryId",
"packages/experimental/webhook/src/brand.ts#WebhookRuleId",
"packages/experimental/webhook/src/brand.ts#WebhookSourceId",
"packages/feedback/message-feedback/src/types.ts#MessageFeedbackVersion",
"packages/goal/goal/src/types.ts#GoalId",
"packages/interaction/commands/src/brand.ts#CommandId",
@@ -23122,9 +23125,6 @@
"packages/schedule/schedule/src/types.ts#ScheduleId",
"packages/session/session-title/src/index.ts#SessionTitleProviderId",
"packages/session/session-title/src/types.ts#SessionTitleProviderId",
"packages/webhook/webhook/src/brand.ts#WebhookDeliveryId",
"packages/webhook/webhook/src/brand.ts#WebhookRuleId",
"packages/webhook/webhook/src/brand.ts#WebhookSourceId",
"packages/workflow/workflow/src/types.ts#WorkflowRunId"
],
"sources": [
@@ -23135,6 +23135,9 @@
"packages/experimental/agent-team/src/types.ts:20",
"packages/experimental/agent-team/src/types.ts:32",
"packages/experimental/agent-team/src/types.ts:8",
"packages/experimental/webhook/src/brand.ts:12",
"packages/experimental/webhook/src/brand.ts:6",
"packages/experimental/webhook/src/brand.ts:9",
"packages/feedback/message-feedback/src/types.ts:14",
"packages/goal/goal/src/types.ts:17",
"packages/interaction/commands/src/brand.ts:31",
@@ -23147,9 +23150,6 @@
"packages/schedule/schedule/src/types.ts:14",
"packages/session/session-title/src/index.ts:42",
"packages/session/session-title/src/types.ts:17",
"packages/webhook/webhook/src/brand.ts:12",
"packages/webhook/webhook/src/brand.ts:6",
"packages/webhook/webhook/src/brand.ts:9",
"packages/workflow/workflow/src/types.ts:13"
]
},
@@ -24068,7 +24068,7 @@
"digest": "8ad45ad053b4d89f8865c17cc9ff3b8748e86045f3f0fb816269a34af2619141",
"names": [],
"sources": [
"packages/hooks/hook-protocol/src/types.ts:31"
"packages/experimental/hook-protocol/src/types.ts:31"
]
},
{
@@ -24333,7 +24333,7 @@
"digest": "9edc162949abf93bd5ff049191b345454ba104f583937ce5580fb50f067d2b94",
"names": [],
"sources": [
"packages/webhook/webhook/src/types.ts:74"
"packages/experimental/webhook/src/types.ts:74"
]
},
{
@@ -24428,10 +24428,10 @@
{
"digest": "a6b41f5bede8094d7bf635be5d69b1bd7a25e006ca9cf9415bceb9322f1a7feb",
"names": [
"packages/hooks/hook-protocol/src/types.ts#HookDialect"
"packages/experimental/hook-protocol/src/types.ts#HookDialect"
],
"sources": [
"packages/hooks/hook-protocol/src/types.ts:48"
"packages/experimental/hook-protocol/src/types.ts:48"
]
},
{
+2 -2
View File
@@ -6,8 +6,8 @@
en: e520df3bf44e1160
zh: 557956eaf6faf4a7
/claude-code-mods-compatibility/packaging-and-loading:
en: 75cf021ce8babaab
zh: caa20540f8bce11a
en: 169ef86a77b15f0a
zh: a3425924fc771856
/claude-code-mods-compatibility/events:
en: cea776ec0063c311
zh: 6b8c8b32f2f7ede9
+1 -1
View File
@@ -15,7 +15,7 @@ Every way a mod behaves differently through this bridge than under Claude Code,
| A hooks module may be TypeScript | A `.ts` hooks module loads only where the launcher transpiles (the source launch does; a built install does not) | DSH ships plain Node |
| Mods run in-process with `$` as their only access to the host | The hooks module runs in-process with Node's globals, no access rule, and the process's full authority: `$.env` reads and writes the harness environment, `$.http.fetch` reaches any URL, `$.fs` and `$.tool.call` act as the session | No sandbox is applied to mods; mount only mods you would run as a plugin |
| `import type { … } from 'claude-code'`, `declare module 'claude-code' { interface PluginState }` | The `claude-code` module name resolves only inside this repository's test setup, to the bridge's types; a mod outside it imports `@deepseek-ai/dsh-experimental-claude-code-mods` | The type names are the bridge's own |
| `settings hooks` in `hooks.json` run beside mod hooks | Not run; mount `@deepseek-ai/dsh-hooks-claude-code` for them | Different bridge |
| `settings hooks` in `hooks.json` run beside mod hooks | Not run; mount `@deepseek-ai/dsh-experimental-hooks-claude-code` for them | Different bridge |
## Events
+1 -1
View File
@@ -15,7 +15,7 @@
| 钩子模块可以是 TypeScript | `.ts` 钩子模块只在启动器转译时可加载(源码启动可以;构建后的安装不行) | DSH 交付的是纯 Node |
| 模组在进程内运行,`$` 是其访问宿主的唯一途径 | 钩子模块以 Node 全局对象在进程内运行,没有访问规则,并拥有进程的全部权限:`$.env` 读写 harness 环境变量,`$.http.fetch` 可访问任意 URL,`$.fs` 与 `$.tool.call` 以会话的身份行动 | 不对模组施加沙箱;只挂载你愿意作为插件运行的模组 |
| `import type { … } from 'claude-code'`、`declare module 'claude-code' { interface PluginState }` | `claude-code` 模块名只在本仓库的测试设置中解析到桥接的类型;仓库外的模组导入 `@deepseek-ai/dsh-experimental-claude-code-mods` | 类型名是桥接自己的 |
| `hooks.json` 中的设置钩子与模组钩子并行运行 | 不运行;为它们挂载 `@deepseek-ai/dsh-hooks-claude-code` | 不同的桥接 |
| `hooks.json` 中的设置钩子与模组钩子并行运行 | 不运行;为它们挂载 `@deepseek-ai/dsh-experimental-hooks-claude-code` | 不同的桥接 |
## 事件
+4 -4
View File
@@ -6,8 +6,8 @@
en: 28fb7eb8f758fdf0
zh: a36d6f03e331ad86
/sessions/sessioneventmap-the-event-vocabulary:
en: 541354f6468e117d
zh: 2d7a665bad828a02
en: e1d52db578c6cb8a
zh: ddc12916f6e60b81
/sessions/sessioneventmap-the-event-vocabulary/the-request-header-event-request-header:
en: 6eb931fcb2f4ab8d
zh: d822a83384cc1fee
@@ -57,8 +57,8 @@
en: 63b4059793255ca3
zh: 6bc7891c320249f4
/sessions/plugin-contributed-log-only-events:
en: 0a014a755b75449f
zh: 9d59d74490a1bcb2
en: a176d23454f6f6e3
zh: 1b6af3e8fd8e9d6e
/sessions/plugin-contributed-log-only-events/plugin-records:
en: 15102fd0b937fbf3
zh: 37ebf1d715db097c
+2 -2
View File
@@ -8,7 +8,7 @@ Source: [`packages/core/session/src/types.ts`](../../packages/core/session/src/t
## `SessionEventMap` — the event vocabulary
The append-only event types. Merge-extensible: a plugin declares extra event types via declaration merging — e.g. the [compaction seam](compaction.md) adds `compaction/start` / `compaction/summary` / `compaction/end`, and `@deepseek-ai/dsh-hook-protocol` adds log-only `hook/invoked` / `hook/result` records for a hook bridge. Like `compaction/*`, these are NOT `SurfaceEventType`s (no `surfaceOp`). The generated [persistence log event catalog](../persistence-catalog.md) enumerates every member — core and merged — with its payload, surface badge, and declaration site.
The append-only event types. Merge-extensible: a plugin declares extra event types via declaration merging — e.g. the [compaction seam](compaction.md) adds `compaction/start` / `compaction/summary` / `compaction/end`, and `@deepseek-ai/dsh-experimental-hook-protocol` adds log-only `hook/invoked` / `hook/result` records for a hook bridge. Like `compaction/*`, these are NOT `SurfaceEventType`s (no `surfaceOp`). The generated [persistence log event catalog](../persistence-catalog.md) enumerates every member — core and merged — with its payload, surface badge, and declaration site.
```ts type-equiv
/** A user-role specialization of the shared message representation. */
@@ -750,7 +750,7 @@ A plugin may declaration-merge extra `SessionEventMap` types. These are **log-on
When several events in one plugin-owned family assemble into one Web Client Conversation Node, every start, update, result, resource, or interruption event in that family carries or independently derives the same stable business id. This requirement applies to correlated Node families, not to every Session event; it lets the client group each event without guessing from adjacency or scanning history. See the [Conversation subsystem](conversation.md).
The hook bridges' `hook/invoked` / `hook/result` pairs (from `@deepseek-ai/dsh-hook-protocol`) correlate by `handlerId`. `UserPromptSubmit`, `PreToolUse`, `PostToolUse`, and `Stop` fire inside the loop's open turn, so their `hook/*` records are turn-enclosed by construction. `SessionStart` gets no `hook/*` record because it runs before turn 1; its context remains pending in the inbox until a waking delivery opens a turn.
The hook bridges' `hook/invoked` / `hook/result` pairs (from `@deepseek-ai/dsh-experimental-hook-protocol`) correlate by `handlerId`. `UserPromptSubmit`, `PreToolUse`, `PostToolUse`, and `Stop` fire inside the loop's open turn, so their `hook/*` records are turn-enclosed by construction. `SessionStart` gets no `hook/*` record because it runs before turn 1; its context remains pending in the inbox until a waking delivery opens a turn.
### Plugin records
+2 -2
View File
@@ -8,7 +8,7 @@
## `SessionEventMap`:事件词汇
仅追加的事件类型。可通过声明合并扩展:插件通过 declaration merging 声明额外的事件类型。例如[压缩(compaction) seam](compaction.zh.md) 添加了 `compaction/start` / `compaction/summary` / `compaction/end`,`@deepseek-ai/dsh-hook-protocol` 为钩子桥接添加了仅记录日志的 `hook/invoked` / `hook/result` 记录。与 `compaction/*` 一样,这些都不是 `SurfaceEventType`(没有 `surfaceOp`)。生成的[持久化日志事件目录](../persistence-catalog.zh.md)列举了所有成员(核心与合并扩展的),包含其 payload、surface 标记与声明位置。
仅追加的事件类型。可通过声明合并扩展:插件通过 declaration merging 声明额外的事件类型。例如[压缩(compaction) seam](compaction.zh.md) 添加了 `compaction/start` / `compaction/summary` / `compaction/end`,`@deepseek-ai/dsh-experimental-hook-protocol` 为钩子桥接添加了仅记录日志的 `hook/invoked` / `hook/result` 记录。与 `compaction/*` 一样,这些都不是 `SurfaceEventType`(没有 `surfaceOp`)。生成的[持久化日志事件目录](../persistence-catalog.zh.md)列举了所有成员(核心与合并扩展的),包含其 payload、surface 标记与声明位置。
```ts type-equiv
/** A user-role specialization of the shared message representation. */
@@ -754,7 +754,7 @@ interface TurnEndReasonMap {
如果同一个插件事件族中的多条事件要组装成一个 Web Client Conversation Node,该事件族中的每条 start、update、result、resource 或 interruption 事件都必须携带或独立推导出同一个稳定业务 id。此要求只约束需要关联的 Node 事件族,并不要求每条 Session 事件都有业务 id;Client 因此无须根据相邻关系猜测归属,也无须扫描历史。参见 [Conversation 子系统](conversation.zh.md)。
钩子桥接层的 `hook/invoked` / `hook/result` 对(来自 `@deepseek-ai/dsh-hook-protocol`)通过 `handlerId` 关联。`UserPromptSubmit`、`PreToolUse`、`PostToolUse` 与 `Stop` 在 loop 已打开的轮次内触发,因此其 `hook/*` 记录天然位于轮次之内。`SessionStart` 不生成 `hook/*` 记录,因为它在轮次 1 之前运行;其上下文会在 inbox 中保持待处理,直到唤醒交付打开一个轮次。
钩子桥接层的 `hook/invoked` / `hook/result` 对(来自 `@deepseek-ai/dsh-experimental-hook-protocol`)通过 `handlerId` 关联。`UserPromptSubmit`、`PreToolUse`、`PostToolUse` 与 `Stop` 在 loop 已打开的轮次内触发,因此其 `hook/*` 记录天然位于轮次之内。`SessionStart` 不生成 `hook/*` 记录,因为它在轮次 1 之前运行;其上下文会在 inbox 中保持待处理,直到唤醒交付打开一个轮次。
### 插件记录
+4 -4
View File
@@ -3,14 +3,14 @@
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/subsystems/skills.md
/skills:
en: 047c73a023dcdcd1
zh: 052f42fbfd202f32
en: 8e9b47984ad1b59e
zh: 2dbe82fe2ef13618
/skills/provider-registry:
en: abe338b6c6d1ebd1
zh: c604db2de10a23c4
/skills/local-discovery-priority:
en: accf8ad4c73c41ad
zh: 141294fe8dab8ecf
en: 13233cb0f2d37f66
zh: d13b16ae7a444649
/skills/skill-identity:
en: 61295a9cf1c51588
zh: 1c4c1582688d2310
+3 -3
View File
@@ -2,9 +2,9 @@
English | [中文](skills.zh.md)
The [skill capability family](../../packages/skill) includes the Service Definition ([dsh-skill](../../packages/skill/skill), `ctx.skills`), the local Service Provider ([dsh-skill-filesystem](../../packages/skill/skill-filesystem)), optional packaged providers ([dsh-skill-badge](../../packages/skill/skill-badge), [dsh-skill-office](../../packages/skill/skill-office), and the Windows ACL diagnosis provider in [dsh-sandbox-windows-acl](../../packages/sandbox/sandbox-windows-acl)), and the Consumer ([dsh-tool-skill](../../packages/skill/tool-skill)). The registry merges provider catalogs across its host and per-scope layers; providers contribute local or packaged skills; the Consumer owns the initial and replacement catalogs plus the model-facing `skill` tool. Skills are optional instructions, not session events, so their vocabulary lives here rather than in [core.md](core.md).
The [skill capability family](../../packages/skill) includes the Service Definition ([dsh-skill](../../packages/skill/skill), `ctx.skills`), the local Service Provider ([dsh-skill-filesystem](../../packages/skill/skill-filesystem)), optional packaged providers ([dsh-experimental-skill-badge](../../packages/experimental/skill-badge), [dsh-skill-office](../../packages/skill/skill-office), and the Windows ACL diagnosis provider in [dsh-sandbox-windows-acl](../../packages/sandbox/sandbox-windows-acl)), and the Consumer ([dsh-tool-skill](../../packages/skill/tool-skill)). The registry merges provider catalogs across its host and per-scope layers; providers contribute local or packaged skills; the Consumer owns the initial and replacement catalogs plus the model-facing `skill` tool. Skills are optional instructions, not session events, so their vocabulary lives here rather than in [core.md](core.md).
Source: [`packages/skill/skill/src/index.ts`](../../packages/skill/skill/src/index.ts), [`packages/skill/skill-filesystem/src/index.ts`](../../packages/skill/skill-filesystem/src/index.ts), [`packages/skill/skill-badge/src/index.ts`](../../packages/skill/skill-badge/src/index.ts), [`packages/skill/skill-office/src/index.ts`](../../packages/skill/skill-office/src/index.ts), [`packages/sandbox/sandbox-windows-acl/src/acl-skill.ts`](../../packages/sandbox/sandbox-windows-acl/src/acl-skill.ts), and [`packages/skill/tool-skill/src/index.ts`](../../packages/skill/tool-skill/src/index.ts).
Source: [`packages/skill/skill/src/index.ts`](../../packages/skill/skill/src/index.ts), [`packages/skill/skill-filesystem/src/index.ts`](../../packages/skill/skill-filesystem/src/index.ts), [`packages/experimental/skill-badge/src/index.ts`](../../packages/experimental/skill-badge/src/index.ts), [`packages/skill/skill-office/src/index.ts`](../../packages/skill/skill-office/src/index.ts), [`packages/sandbox/sandbox-windows-acl/src/acl-skill.ts`](../../packages/sandbox/sandbox-windows-acl/src/acl-skill.ts), and [`packages/skill/tool-skill/src/index.ts`](../../packages/skill/tool-skill/src/index.ts).
## Provider registry
@@ -76,7 +76,7 @@ The shipped local provider scans roots in rank order:
The project root is the nearest ancestor containing `.git`; without one, the current cwd is used. When `ctx.fs` is available, the git-root walk probes `.git` through the filesystem service so remote or sandboxed workspaces do not fall back to the host filesystem boundary. The user DSH root skips its `.system` child. The local provider does not synthesize built-in system skills; deployments supply packaged skills through configured bundled roots or dedicated providers.
`dsh-skill-badge` registers one immutable `bundled` candidate at `BUNDLED_SKILL_RANK` and exposes its packaged asset directory through `resourceBase`. The shipped CLI declares the plugin disabled, so enabling its composition row is an explicit opt-in.
`dsh-experimental-skill-badge` registers one immutable `bundled` candidate at `BUNDLED_SKILL_RANK` and exposes its packaged asset directory through `resourceBase`. The shipped CLI declares the plugin disabled, so enabling its composition row is an explicit opt-in.
Chokidar watches existing roots for direct bundle/flat-entry additions and removals plus direct skill-entry changes. A missing root is followed one absent path segment at a time from its nearest existing ancestor until Chokidar can attach. Resource files below a bundle are not catalog changes. Model-facing `write` and `edit` observations synchronously invalidate the provider when their target is catalog-relevant, while the host watcher covers IDE, Git, shell, and external-process mutations. Watcher failures make the current observation incomplete without hiding readable candidates from direct loads; project-scoped watchers use a configured bounded LRU.
+3 -3
View File
@@ -2,9 +2,9 @@
[English](skills.md) | 中文
[skill(技能)能力族](../../packages/skill) 包含 Service Definition([dsh-skill](../../packages/skill/skill),`ctx.skills`)、本地 Service Provider([dsh-skill-filesystem](../../packages/skill/skill-filesystem))、可选的随包提供方([dsh-skill-badge](../../packages/skill/skill-badge)、[dsh-skill-office](../../packages/skill/skill-office) 及 [dsh-sandbox-windows-acl](../../packages/sandbox/sandbox-windows-acl) 中的 Windows ACL 诊断提供方)和 Consumer([dsh-tool-skill](../../packages/skill/tool-skill))。注册表在其宿主层与各 scope 层之间合并各提供方的目录;提供方贡献本地或随包 skill;Consumer 拥有初始目录和替换目录,以及面向模型的 `skill` 工具。skill 是可选的指令而非会话事件,因此其词汇定义在此处而非 [core.md](core.zh.md)。
[skill(技能)能力族](../../packages/skill) 包含 Service Definition([dsh-skill](../../packages/skill/skill),`ctx.skills`)、本地 Service Provider([dsh-skill-filesystem](../../packages/skill/skill-filesystem))、可选的随包提供方([dsh-experimental-skill-badge](../../packages/experimental/skill-badge)、[dsh-skill-office](../../packages/skill/skill-office) 及 [dsh-sandbox-windows-acl](../../packages/sandbox/sandbox-windows-acl) 中的 Windows ACL 诊断提供方)和 Consumer([dsh-tool-skill](../../packages/skill/tool-skill))。注册表在其宿主层与各 scope 层之间合并各提供方的目录;提供方贡献本地或随包 skill;Consumer 拥有初始目录和替换目录,以及面向模型的 `skill` 工具。skill 是可选的指令而非会话事件,因此其词汇定义在此处而非 [core.md](core.zh.md)。
源码:[`packages/skill/skill/src/index.ts`](../../packages/skill/skill/src/index.ts)、[`packages/skill/skill-filesystem/src/index.ts`](../../packages/skill/skill-filesystem/src/index.ts)、[`packages/skill/skill-badge/src/index.ts`](../../packages/skill/skill-badge/src/index.ts)、[`packages/skill/skill-office/src/index.ts`](../../packages/skill/skill-office/src/index.ts)、[`packages/sandbox/sandbox-windows-acl/src/acl-skill.ts`](../../packages/sandbox/sandbox-windows-acl/src/acl-skill.ts) 与 [`packages/skill/tool-skill/src/index.ts`](../../packages/skill/tool-skill/src/index.ts)。
源码:[`packages/skill/skill/src/index.ts`](../../packages/skill/skill/src/index.ts)、[`packages/skill/skill-filesystem/src/index.ts`](../../packages/skill/skill-filesystem/src/index.ts)、[`packages/experimental/skill-badge/src/index.ts`](../../packages/experimental/skill-badge/src/index.ts)、[`packages/skill/skill-office/src/index.ts`](../../packages/skill/skill-office/src/index.ts)、[`packages/sandbox/sandbox-windows-acl/src/acl-skill.ts`](../../packages/sandbox/sandbox-windows-acl/src/acl-skill.ts) 与 [`packages/skill/tool-skill/src/index.ts`](../../packages/skill/tool-skill/src/index.ts)。
## 提供方注册表
@@ -76,7 +76,7 @@ interface SkillProviderControl {
项目根目录为包含 `.git` 的最近祖先目录;找不到时使用当前 cwd。当 `ctx.fs` 可用时,git-root 向上查找通过文件系统服务探测 `.git`,使远程或沙箱工作区不会回退到宿主文件系统边界。用户 DSH 根目录会跳过其 `.system` 子目录。本地提供方不会合成内置系统 skill;部署方通过已配置的 bundled 根目录或专用提供方提供随包 skill。
`dsh-skill-badge` 在 `BUNDLED_SKILL_RANK` 注册一个不可变的 `bundled` 候选项,并通过 `resourceBase` 公开其随包资产目录。交付的 CLI(命令行界面)将该插件声明为禁用,因此启用其组合配置行即为显式选择加入。
`dsh-experimental-skill-badge` 在 `BUNDLED_SKILL_RANK` 注册一个不可变的 `bundled` 候选项,并通过 `resourceBase` 公开其随包资产目录。交付的 CLI(命令行界面)将该插件声明为禁用,因此启用其组合配置行即为显式选择加入。
Chokidar 会监视现有根目录中直属 bundle 和平铺条目的添加与移除,以及直属 skill 条目的变更。缺失的根目录会从最近的现有祖先开始,逐个跟踪缺失路径段,直至 Chokidar 可以附加。bundle 下的资源文件变更不属于目录变更。面向模型的 `write` 和 `edit` 观测会在目标路径与目录相关时同步使提供方目录失效,而宿主 watcher 覆盖 IDE、Git、shell 和外部进程产生的变更。watcher 失败会使当前观测不完整,但不会在直接加载时隐藏可读候选项;项目作用域 watcher 使用按配置设限的 LRU。
+2 -2
View File
@@ -15,5 +15,5 @@
en: 2ccdbc45140f9c41
zh: af509a7fb0f84e18
/webhook-runtime/github-adapter:
en: ddb0522ef321a8c5
zh: 6f08a99848facaf3
en: 4f99db873df49da3
zh: 7bb93fd67b1e6e2d
+2 -2
View File
@@ -32,7 +32,7 @@ Failed attachment disposes the new Agent before a prompt exists. A failure betwe
## GitHub adapter
`@deepseek-ai/dsh-webhook-github` registers an exact route on an injected WebServer, resolves its credential reference for each request, verifies the untouched `application/json` body before parsing, and returns `202` immediately after in-memory dispatch. Its normalized event guarantees a signed lossless-JSON object; rules validate the event-specific fields they consume.
`@deepseek-ai/dsh-experimental-webhook-github` registers an exact route on an injected WebServer, resolves its credential reference for each request, verifies the untouched `application/json` body before parsing, and returns `202` immediately after in-memory dispatch. Its normalized event guarantees a signed lossless-JSON object; rules validate the event-specific fields they consume.
The [GitHub review guide](../user/guide/github-review.md) mounts this route on an isolated second WebServer so exposing webhook ingress does not expose the browser API.
@@ -66,5 +66,5 @@ register<K extends string>(rule: WebhookRule<K>): () => Promise<void>
dispatch<K extends string>(delivery: VerifiedWebhookDelivery<K>): void
```
Source: [`packages/webhook/webhook/src/index.ts`](../../packages/webhook/webhook/src/index.ts)
Source: [`packages/experimental/webhook/src/index.ts`](../../packages/experimental/webhook/src/index.ts)
<!-- END GENERATED cordis-surface -->
+2 -2
View File
@@ -32,7 +32,7 @@ follow-up 是普通持久 user-role 消息,使用 `source.kind: "webhook"`,
## GitHub 适配器
`@deepseek-ai/dsh-webhook-github` 在注入的 WebServer 上注册精确路由,为每次请求解析凭据引用,在解析前验证未改动的 `application/json` body,并在内存分发后立即返回 `202`。它的规范化事件保证为已签名的无损 JSON 对象;规则负责验证自己消费的事件特定字段。
`@deepseek-ai/dsh-experimental-webhook-github` 在注入的 WebServer 上注册精确路由,为每次请求解析凭据引用,在解析前验证未改动的 `application/json` body,并在内存分发后立即返回 `202`。它的规范化事件保证为已签名的无损 JSON 对象;规则负责验证自己消费的事件特定字段。
[GitHub 评审指南](../user/guide/github-review.zh.md)把该路由挂载在隔离的第二个 WebServer 上,因此暴露 webhook 入口不会暴露浏览器 API。
@@ -66,5 +66,5 @@ register<K extends string>(rule: WebhookRule<K>): () => Promise<void>
dispatch<K extends string>(delivery: VerifiedWebhookDelivery<K>): void
```
Source: [`packages/webhook/webhook/src/index.ts`](../../packages/webhook/webhook/src/index.ts)
Source: [`packages/experimental/webhook/src/index.ts`](../../packages/experimental/webhook/src/index.ts)
<!-- END GENERATED cordis-surface -->
+2 -2
View File
@@ -3,8 +3,8 @@
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/subsystems/workflow.md
/workflow:
en: eaf02eb7b85ec696
zh: 648807dce7860e2d
en: 5b0844dea8f31ba6
zh: 7422bb6b5d87bad7
/workflow/the-start-request:
en: 6c8755833293a36c
zh: a0f061387fe0d3a6
+1 -1
View File
@@ -4,7 +4,7 @@ English | [中文](workflow.zh.md)
The workflow seam lets an agent run a model-written orchestration SCRIPT that starts subagents. Like [subagent](subagent.md) it is **one optional capability**, not part of the agent loop, so its types and operations live here rather than in [core.md](core.md). Like bash, it permits ONE engine implementation per context to provide `ctx.workflowEngine`; there is no named-provider registry (a second engine replaces the first through plugin configuration rather than running beside it).
Service Definition: [dsh-workflow](../../packages/workflow/workflow) (`ctx.workflowEngine` and the vocabulary below). [dsh-workflow-ptc](../../packages/workflow/workflow-ptc) executes the VM and helpers through the shared Node PTC process runtime under the calling Session's file policy. The consumers are [dsh-tool-workflow](../../packages/workflow/tool-workflow) and the opt-in [dsh-tool-ralph](../../packages/workflow/tool-ralph). [Workflow sandbox reuse](../../.agents/notes/implemented/architecture/2026-09-13-workflow-ptc-sandbox-reuse.md) owns execution choices; the [dynamic-workflows reference](../../packages/workflow/workflow/README.md) owns script semantics.
Service Definition: [dsh-workflow](../../packages/workflow/workflow) (`ctx.workflowEngine` and the vocabulary below). [dsh-workflow-ptc](../../packages/workflow/workflow-ptc) executes the VM and helpers through the shared Node PTC process runtime under the calling Session's file policy. The consumers are [dsh-tool-workflow](../../packages/workflow/tool-workflow) and the opt-in [dsh-experimental-tool-ralph](../../packages/experimental/tool-ralph). [Workflow sandbox reuse](../../.agents/notes/implemented/architecture/2026-09-13-workflow-ptc-sandbox-reuse.md) owns execution choices; the [dynamic-workflows reference](../../packages/workflow/workflow/README.md) owns script semantics.
Sources: browser-safe vocabulary in [`packages/workflow/workflow/src/types.ts`](../../packages/workflow/workflow/src/types.ts), Host request and live-run handles in [`runtime-types.ts`](../../packages/workflow/workflow/src/runtime-types.ts).
+1 -1
View File
@@ -4,7 +4,7 @@
工作流 seam 允许 agent(智能体)运行由模型编写、会启动 subagent 的编排脚本。与 [subagent](subagent.zh.md) 一样,它是**一项可选能力**,不属于 agent loop,因此其类型和操作记录在此处,而非 [core.md](core.zh.md)。与 bash 一样,每个上下文只允许一个引擎实现提供 `ctx.workflowEngine`;没有命名提供方注册表(第二个引擎通过插件配置替换第一个,而不与它同时运行)。
Service Definition:[dsh-workflow](../../packages/workflow/workflow)(`ctx.workflowEngine` 和下文词汇)。[dsh-workflow-ptc](../../packages/workflow/workflow-ptc)通过共享 Node PTC 进程运行时按调用 Session 的文件策略执行 VM 与辅助函数。消费方为 [dsh-tool-workflow](../../packages/workflow/tool-workflow) 和需显式启用的 [dsh-tool-ralph](../../packages/workflow/tool-ralph)。[工作流沙箱复用](../../.agents/notes/implemented/architecture/2026-09-13-workflow-ptc-sandbox-reuse.zh.md)负责执行选择;[动态工作流参考](../../packages/workflow/workflow/README.zh.md)负责脚本语义。
Service Definition:[dsh-workflow](../../packages/workflow/workflow)(`ctx.workflowEngine` 和下文词汇)。[dsh-workflow-ptc](../../packages/workflow/workflow-ptc)通过共享 Node PTC 进程运行时按调用 Session 的文件策略执行 VM 与辅助函数。消费方为 [dsh-tool-workflow](../../packages/workflow/tool-workflow) 和需显式启用的 [dsh-experimental-tool-ralph](../../packages/experimental/tool-ralph)。[工作流沙箱复用](../../.agents/notes/implemented/architecture/2026-09-13-workflow-ptc-sandbox-reuse.zh.md)负责执行选择;[动态工作流参考](../../packages/workflow/workflow/README.zh.md)负责脚本语义。
源码:浏览器安全词汇位于 [`packages/workflow/workflow/src/types.ts`](../../packages/workflow/workflow/src/types.ts),Host 请求与活跃运行句柄位于 [`runtime-types.ts`](../../packages/workflow/workflow/src/runtime-types.ts)。
+13 -13
View File
@@ -30,11 +30,11 @@ This table connects model-visible tool names to the plugin package and service s
| `@deepseek-ai/dsh-tool-str-replace-editor` | `str_replace_editor` | `ctx.tools`, `ctx.fs` | `tool/call`, `fs/observed after view presence/absence, edit absence, or successful mutation`, `tool/result` | - | Standalone view/create/unique literal replace/line insert tool over the filesystem seam; it composes with any shell or terminal API. |
| `@deepseek-ai/dsh-tool-fs` | `edit`, `read`, `read_image`, `write` | `ctx.workingDirectory`, `ctx.tools`, `ctx.fs`, `ctx.systemPrompt`, `ctx.attachments (image-tool registration)`, `ctx.llm + an image-capable route (image-tool execution)` | `tool/call`, `fs/write-intent or fs/edit-intent for mutations`, `fs/observed after read presence/absence or successful file operation`, `durable attachment (read_image)`, `tool/result` | - | The read-before-write/edit policy is added by `@deepseek-ai/dsh-fs-observation-policy` (an `fs/*` event-gate plugin, no schema change); a deployment that loads these tools is expected to also load it. The image tool is not registered without `ctx.attachments`; its schema is route-independent, and execution refuses unless the exact routed model declares image input. |
| `@deepseek-ai/dsh-tool-fs-search` | `glob`, `grep` | `ctx.workingDirectory`, `ctx.tools`, `ctx.subprocess`, `ctx.systemPrompt` | `tool/call`, `tool/result` | - | glob and grep are unconditional discovery tools that spawn the packaged ripgrep binary (`@vscode/ripgrep`) through ctx.subprocess as ordinary foreground calls (never background jobs) — no host `rg` install and no shell layer. The catalog uses `sampleOverCapGlobResults: true`; deployments must choose that behavior explicitly. Capped results save the complete formatted list through the optional ctx.spillStore backend; returned locators are follow-up-readable/searchable when the backend exposes local paths in co-located deployments. |
| `@deepseek-ai/dsh-tool-terminal` | `terminal_close`, `terminal_list`, `terminal_open`, `terminal_read`, `terminal_send`, `terminal_signal` | `ctx.workingDirectory`, `ctx.tools`, `ctx.terminals`, `ctx.systemPrompt`, `ctx.jobs at call time for run_in_background` | `tool/call`, `tool/result` | - | The six terminal tools are opt-in and complement one-shot shell/filesystem tools. `terminal_send(run_in_background: true)` registers with `ctx.jobs`; TUI, named key sequences, BEL, resize, auto-start, and cross-agent sharing are absent from the schema. |
| `@deepseek-ai/dsh-experimental-tool-terminal` | `terminal_close`, `terminal_list`, `terminal_open`, `terminal_read`, `terminal_send`, `terminal_signal` | `ctx.workingDirectory`, `ctx.tools`, `ctx.terminals`, `ctx.systemPrompt`, `ctx.jobs at call time for run_in_background` | `tool/call`, `tool/result` | - | The six terminal tools are opt-in and complement one-shot shell/filesystem tools. `terminal_send(run_in_background: true)` registers with `ctx.jobs`; TUI, named key sequences, BEL, resize, auto-start, and cross-agent sharing are absent from the schema. |
| `@deepseek-ai/dsh-tool-goal` | `create_goal`, `get_goal`, `update_goal` | `ctx.tools`, `ctx.agents`, `ctx.goals`, `ctx.systemPrompt`, `a calling Agent in an authorized open turn` | `tool/call`, `goal/change for mutations`, `tool/result` | - | create, edit, pause, and resume require direct-human root authority; complete and blocked also accept the exact current goal round. The default blocked lower bound is three admitted rounds. |
| `@deepseek-ai/dsh-tool-schedule` | `schedule_create`, `schedule_delete`, `schedule_list`, `schedule_update` | `ctx.tools`, `ctx.schedule` | `tool/call`, `Schedule storage domain create, update, or delete`, `tool/result` | - | A preset or Agent scope mounts this package; the preset decides which agents receive the four management tools. Each call acts on the calling Agent's Session. Accepts after_seconds, explicit absolute at, bounded fixed-rate every_seconds, daily and weekly local times in an explicit IANA zone, and cron as a five-field expression. Management uses the Host storage domain; due messages resume the original Session. |
| `@deepseek-ai/dsh-tool-lsp` | `lsp` | `ctx.workingDirectory`, `ctx.tools`, `ctx.lsp`, `ctx.systemPrompt` | `tool/call`, `tool/result` | - | The lsp tool keeps provider selection and language-server subprocesses behind ctx.lsp, so its model-visible schema stays stable across providers. Requires a registered provider (e.g. `@deepseek-ai/dsh-lsp-stdio`) at runtime; without one, a query returns the structured `LSP_UNAVAILABLE` error rather than changing the schema. |
| `@deepseek-ai/dsh-tool-ralph` | `ralph` | `ctx.tools`, `ctx.workflowEngine`, `ctx.subagents`, `ctx.systemPrompt`, `a calling Agent (exec.agent parents every fresh round)` | `tool/call`, `tool/result`, `workflow and child session events during execution` | - | A fixed foreground workflow starts one fresh structured child per round; the model selects only the immutable objective and an optional round cap. |
| `@deepseek-ai/dsh-experimental-tool-ralph` | `ralph` | `ctx.tools`, `ctx.workflowEngine`, `ctx.subagents`, `ctx.systemPrompt`, `a calling Agent (exec.agent parents every fresh round)` | `tool/call`, `tool/result`, `workflow and child session events during execution` | - | A fixed foreground workflow starts one fresh structured child per round; the model selects only the immutable objective and an optional round cap. |
| `@deepseek-ai/dsh-tool-skill` | `skill` | `ctx.workingDirectory`, `ctx.tools`, `ctx.agents`, `ctx.skills` | `tool/call`, `tool/result`, `user/message replacement catalogs via agent.inject()` | - | - |
| `@deepseek-ai/dsh-tool-session-query` | `session_event_read`, `session_event_search`, `session_event_trace`, `session_search`, `session_trace` | `ctx.tools`, `ctx.systemPrompt`, `ctx.sessionQuery`, `a calling Agent for workspace authority` | `tool/call`, `tool/result` | - | The five read-only tools hide provider cursors and authorize every result from the immutable calling agent session. The package is opt-in; compositions that need enforced deadlines or bounded inline output also mount the generic timeout or spill policies. |
| `@deepseek-ai/dsh-tool-subagent` | `list_subagent_models`, `subagent` | `ctx.tools`, `ctx.subagents`, `ctx.systemPrompt`, `ctx.llm for model discovery and selected-route validation` | `tool/call`, `tool/result`, `child session events through the chosen provider` | `subagent`, `subagent_fork` | The registered delegation name is the load-time `toolName` config (default `subagent`); the default schema above has model selection off, while the discovery schema is shown as the fixed companion available in an enabled Session. Web presets sample the Plugins preference for each new top-level Session and preserve that decision for its child Sessions; `subagent_fork` remains fixed-route. Each instance selects its backend through `provider` and reads model-selection settings through `modelSelectionSettings`. Every delegation returns a child id promptly; local children accept follow-ups, while external backends report their single execution automatically. |
@@ -1120,9 +1120,9 @@ Source: [`packages/fs/tool-fs-search/src/index.ts`](../packages/fs/tool-fs-searc
glob and grep are unconditional discovery tools that spawn the packaged ripgrep binary (`@vscode/ripgrep`) through ctx.subprocess as ordinary foreground calls (never background jobs) — no host `rg` install and no shell layer. The catalog uses `sampleOverCapGlobResults: true`; deployments must choose that behavior explicitly. Capped results save the complete formatted list through the optional ctx.spillStore backend; returned locators are follow-up-readable/searchable when the backend exposes local paths in co-located deployments.
<a id="deepseek-aidsh-tool-terminal"></a>
<a id="deepseek-aidsh-experimental-tool-terminal"></a>
## `@deepseek-ai/dsh-tool-terminal`
## `@deepseek-ai/dsh-experimental-tool-terminal`
### `terminal_close`
@@ -1143,7 +1143,7 @@ Close one persistent terminal and wait until its captured owned process tree is
}
```
Source: [`packages/terminal/tool-terminal/src/index.ts`](../packages/terminal/tool-terminal/src/index.ts)
Source: [`packages/experimental/tool-terminal/src/index.ts`](../packages/experimental/tool-terminal/src/index.ts)
### `terminal_list`
@@ -1156,7 +1156,7 @@ List persistent terminal sessions owned by the current agent.
}
```
Source: [`packages/terminal/tool-terminal/src/index.ts`](../packages/terminal/tool-terminal/src/index.ts)
Source: [`packages/experimental/tool-terminal/src/index.ts`](../packages/experimental/tool-terminal/src/index.ts)
### `terminal_open`
@@ -1185,7 +1185,7 @@ Create a persistent, owner-isolated terminal session from a registered backend t
}
```
Source: [`packages/terminal/tool-terminal/src/index.ts`](../packages/terminal/tool-terminal/src/index.ts)
Source: [`packages/experimental/tool-terminal/src/index.ts`](../packages/experimental/tool-terminal/src/index.ts)
### `terminal_read`
@@ -1214,7 +1214,7 @@ Read a bounded page of retained output from a persistent terminal without sendin
}
```
Source: [`packages/terminal/tool-terminal/src/index.ts`](../packages/terminal/tool-terminal/src/index.ts)
Source: [`packages/experimental/tool-terminal/src/index.ts`](../packages/experimental/tool-terminal/src/index.ts)
### `terminal_send`
@@ -1248,7 +1248,7 @@ Send text to a persistent terminal. By default Enter is submitted and the call w
}
```
Source: [`packages/terminal/tool-terminal/src/index.ts`](../packages/terminal/tool-terminal/src/index.ts)
Source: [`packages/experimental/tool-terminal/src/index.ts`](../packages/experimental/tool-terminal/src/index.ts)
### `terminal_signal`
@@ -1281,7 +1281,7 @@ Send an allowed signal to the current foreground process group of a persistent t
}
```
Source: [`packages/terminal/tool-terminal/src/index.ts`](../packages/terminal/tool-terminal/src/index.ts)
Source: [`packages/experimental/tool-terminal/src/index.ts`](../packages/experimental/tool-terminal/src/index.ts)
The six terminal tools are opt-in and complement one-shot shell/filesystem tools. `terminal_send(run_in_background: true)` registers with `ctx.jobs`; TUI, named key sequences, BEL, resize, auto-start, and cross-agent sharing are absent from the schema.
@@ -1720,9 +1720,9 @@ Source: [`packages/lsp/tool-lsp/src/index.ts`](../packages/lsp/tool-lsp/src/inde
The lsp tool keeps provider selection and language-server subprocesses behind ctx.lsp, so its model-visible schema stays stable across providers. Requires a registered provider (e.g. `@deepseek-ai/dsh-lsp-stdio`) at runtime; without one, a query returns the structured `LSP_UNAVAILABLE` error rather than changing the schema.
<a id="deepseek-aidsh-tool-ralph"></a>
<a id="deepseek-aidsh-experimental-tool-ralph"></a>
## `@deepseek-ai/dsh-tool-ralph`
## `@deepseek-ai/dsh-experimental-tool-ralph`
### `ralph`
@@ -1747,7 +1747,7 @@ Run a foreground fresh-agent Ralph loop toward one immutable objective. Use only
}
```
Source: [`packages/workflow/tool-ralph/src/index.ts`](../packages/workflow/tool-ralph/src/index.ts)
Source: [`packages/experimental/tool-ralph/src/index.ts`](../packages/experimental/tool-ralph/src/index.ts)
A fixed foreground workflow starts one fresh structured child per round; the model selects only the immutable objective and an optional round cap.
+13 -13
View File
@@ -34,11 +34,11 @@
| `@deepseek-ai/dsh-tool-str-replace-editor` | `str_replace_editor` | `ctx.tools`、`ctx.fs` | `tool/call`、`fs/observed after view presence/absence, edit absence, or successful mutation`、`tool/result` | - | 基于文件系统 seam 的独立查看/创建/唯一字面量替换/按行插入工具;可与任何 shell 或终端接口组合。 |
| `@deepseek-ai/dsh-tool-fs` | `edit`、`read`、`read_image`、`write` | `ctx.workingDirectory`、`ctx.tools`、`ctx.fs`、`ctx.systemPrompt`、`ctx.attachments (image-tool registration)`、`ctx.llm + an image-capable route (image-tool execution)` | `tool/call`、`fs/write-intent or fs/edit-intent for mutations`、`fs/observed after read presence/absence or successful file operation`、`durable attachment (read_image)`、`tool/result` | - | 先读后写/编辑策略由 `@deepseek-ai/dsh-fs-observation-policy` 添加;它是一个 `fs/*` 事件门禁插件,不会改变 schema。加载这些工具的部署按预期也应加载该插件。没有 `ctx.attachments` 时图片工具不会注册;其 schema 与路由无关,执行时除非确切路由的模型声明图片输入,否则拒绝。 |
| `@deepseek-ai/dsh-tool-fs-search` | `glob`、`grep` | `ctx.workingDirectory`、`ctx.tools`、`ctx.subprocess`、`ctx.systemPrompt` | `tool/call`、`tool/result` | - | glob 和 grep 是无条件可用的发现工具,通过 ctx.subprocess spawn 随包提供的 ripgrep 二进制文件(`@vscode/ripgrep`),并作为普通前台调用运行,绝不作为后台任务;无需在宿主机安装 `rg`,也不经过 shell 层。本目录使用 `sampleOverCapGlobResults: true`;部署必须显式选择该行为。结果超过上限时,会通过可选的 ctx.spillStore 后端保存完整的格式化列表;在共置部署中,如果后端公开本地路径,返回的定位信息可供后续读取/搜索。 |
| `@deepseek-ai/dsh-tool-terminal` | `terminal_close`、`terminal_list`、`terminal_open`、`terminal_read`、`terminal_send`、`terminal_signal` | `ctx.workingDirectory`、`ctx.tools`、`ctx.terminals`、`ctx.systemPrompt`、`ctx.jobs at call time for run_in_background` | `tool/call`、`tool/result` | - | 这 6 个终端工具需要选择启用,用于补充一次性 bash/文件系统工具。`terminal_send(run_in_background: true)` 会注册到 `ctx.jobs`;schema 不包含 TUI、具名按键序列、BEL、调整尺寸、自动启动和跨 agent 共享。 |
| `@deepseek-ai/dsh-experimental-tool-terminal` | `terminal_close`、`terminal_list`、`terminal_open`、`terminal_read`、`terminal_send`、`terminal_signal` | `ctx.workingDirectory`、`ctx.tools`、`ctx.terminals`、`ctx.systemPrompt`、`ctx.jobs at call time for run_in_background` | `tool/call`、`tool/result` | - | 这 6 个终端工具需要选择启用,用于补充一次性 bash/文件系统工具。`terminal_send(run_in_background: true)` 会注册到 `ctx.jobs`;schema 不包含 TUI、具名按键序列、BEL、调整尺寸、自动启动和跨 agent 共享。 |
| `@deepseek-ai/dsh-tool-goal` | `create_goal`、`get_goal`、`update_goal` | `ctx.tools`、`ctx.agents`、`ctx.goals`、`ctx.systemPrompt`、`a calling Agent in an authorized open turn` | `tool/call`、`goal/change for mutations`、`tool/result` | - | create、edit、pause 和 resume 要求直接来自人类的根权限;complete 和 blocked 也接受确切的当前 Goal Round。blocked 的默认下限是 3 个获准的 Round。 |
| `@deepseek-ai/dsh-tool-schedule` | `schedule_create`、`schedule_delete`、`schedule_list`、`schedule_update` | `ctx.tools`、`ctx.schedule` | `tool/call`、Schedule storage domain 创建、更新或删除、`tool/result` | - | preset 或 Agent scope 挂载本包;由 preset 决定哪些 agent 获得这四个管理工具。每次调用都作用于调用方 Agent 的 Session。接受 after_seconds、显式绝对 at、有界固定速率 every_seconds、带显式 IANA 时区的每日与每周本地时间,以及作为五字段表达式的 cron。管理使用宿主 storage domain;到期消息会恢复原 Session。 |
| `@deepseek-ai/dsh-tool-lsp` | `lsp` | `ctx.workingDirectory`、`ctx.tools`、`ctx.lsp`、`ctx.systemPrompt` | `tool/call`、`tool/result` | - | lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后,因此其模型可见 schema 在更换提供方时保持稳定。运行时要求已注册提供方,例如 `@deepseek-ai/dsh-lsp-stdio`;如果没有提供方,查询会返回结构化 `LSP_UNAVAILABLE` 错误,而不会改变 schema。 |
| `@deepseek-ai/dsh-tool-ralph` | `ralph` | `ctx.tools`、`ctx.workflowEngine`、`ctx.subagents`、`ctx.systemPrompt`、`a calling Agent (exec.agent parents every fresh round)` | `tool/call`、`tool/result`、`workflow and child session events during execution` | - | 固定的前台工作流会在每个 Round 启动一个全新的结构化子级;模型只能选择不可变目标和可选的 Round 上限。 |
| `@deepseek-ai/dsh-experimental-tool-ralph` | `ralph` | `ctx.tools`、`ctx.workflowEngine`、`ctx.subagents`、`ctx.systemPrompt`、`a calling Agent (exec.agent parents every fresh round)` | `tool/call`、`tool/result`、`workflow and child session events during execution` | - | 固定的前台工作流会在每个 Round 启动一个全新的结构化子级;模型只能选择不可变目标和可选的 Round 上限。 |
| `@deepseek-ai/dsh-tool-skill` | `skill` | `ctx.workingDirectory`、`ctx.tools`、`ctx.agents`、`ctx.skills` | `tool/call`、`tool/result`、`user/message replacement catalogs via agent.inject()` | - | - |
| `@deepseek-ai/dsh-tool-session-query` | `session_event_read`、`session_event_search`、`session_event_trace`、`session_search`、`session_trace` | `ctx.tools`、`ctx.systemPrompt`、`ctx.sessionQuery`、`a calling Agent for workspace authority` | `tool/call`、`tool/result` | - | 这 5 个只读工具会隐藏提供方游标,并根据不可变的调用 agent 会话为每个结果授权。该包需要选择启用;需要强制截止时间或限制行内输出的组合还会挂载通用超时或 spill 策略。 |
| `@deepseek-ai/dsh-tool-subagent` | `list_subagent_models`、`subagent` | `ctx.tools`、`ctx.subagents`、`ctx.systemPrompt`、`用于模型发现和所选路由校验的 ctx.llm` | `tool/call`、`tool/result`、`child session events through the chosen provider` | `subagent`、`subagent_fork` | 注册的委派工具名称取决于加载时 `toolName` 配置(默认为 `subagent`);上述默认 schema 关闭模型选择,而发现 schema 则展示为已启用 Session 中可用的固定配套工具。Web preset 会在每个新顶层 Session 创建时读取插件页偏好,并为其子 Session 保留该决定;`subagent_fork` 始终使用固定路由。每个实例通过 `provider` 选择后端,通过 `modelSelectionSettings` 读取模型选择设置。每次委派都会立即返回子代理 id;本地子代理接受后续消息,外部后端自动汇报单次执行结果。 |
@@ -1126,9 +1126,9 @@ pwsh 工具是 Windows 组合中 bash 执行器 seam 的 PowerShell 方言消费
glob 和 grep 是无条件可用的发现工具,通过 ctx.subprocess spawn 随包提供的 ripgrep 二进制文件(`@vscode/ripgrep`),并作为普通前台调用运行,绝不作为后台任务;无需在宿主机安装 `rg`,也不经过 shell 层。本目录使用 `sampleOverCapGlobResults: true`;部署必须显式选择该行为。结果超过上限时,会通过可选的 ctx.spillStore 后端保存完整的格式化列表;在共置部署中,如果后端公开本地路径,返回的定位信息可供后续读取/搜索。
<a id="deepseek-aidsh-tool-terminal"></a>
<a id="deepseek-aidsh-experimental-tool-terminal"></a>
## `@deepseek-ai/dsh-tool-terminal`
## `@deepseek-ai/dsh-experimental-tool-terminal`
### `terminal_close`
@@ -1149,7 +1149,7 @@ glob 和 grep 是无条件可用的发现工具,通过 ctx.subprocess spawn
}
```
来源:[`packages/terminal/tool-terminal/src/index.ts`](../packages/terminal/tool-terminal/src/index.ts)
来源:[`packages/experimental/tool-terminal/src/index.ts`](../packages/experimental/tool-terminal/src/index.ts)
### `terminal_list`
@@ -1162,7 +1162,7 @@ glob 和 grep 是无条件可用的发现工具,通过 ctx.subprocess spawn
}
```
来源:[`packages/terminal/tool-terminal/src/index.ts`](../packages/terminal/tool-terminal/src/index.ts)
来源:[`packages/experimental/tool-terminal/src/index.ts`](../packages/experimental/tool-terminal/src/index.ts)
### `terminal_open`
@@ -1191,7 +1191,7 @@ glob 和 grep 是无条件可用的发现工具,通过 ctx.subprocess spawn
}
```
来源:[`packages/terminal/tool-terminal/src/index.ts`](../packages/terminal/tool-terminal/src/index.ts)
来源:[`packages/experimental/tool-terminal/src/index.ts`](../packages/experimental/tool-terminal/src/index.ts)
### `terminal_read`
@@ -1220,7 +1220,7 @@ glob 和 grep 是无条件可用的发现工具,通过 ctx.subprocess spawn
}
```
来源:[`packages/terminal/tool-terminal/src/index.ts`](../packages/terminal/tool-terminal/src/index.ts)
来源:[`packages/experimental/tool-terminal/src/index.ts`](../packages/experimental/tool-terminal/src/index.ts)
### `terminal_send`
@@ -1254,7 +1254,7 @@ glob 和 grep 是无条件可用的发现工具,通过 ctx.subprocess spawn
}
```
来源:[`packages/terminal/tool-terminal/src/index.ts`](../packages/terminal/tool-terminal/src/index.ts)
来源:[`packages/experimental/tool-terminal/src/index.ts`](../packages/experimental/tool-terminal/src/index.ts)
### `terminal_signal`
@@ -1287,7 +1287,7 @@ glob 和 grep 是无条件可用的发现工具,通过 ctx.subprocess spawn
}
```
来源:[`packages/terminal/tool-terminal/src/index.ts`](../packages/terminal/tool-terminal/src/index.ts)
来源:[`packages/experimental/tool-terminal/src/index.ts`](../packages/experimental/tool-terminal/src/index.ts)
这 6 个终端工具需要选择启用,用于补充一次性 bash/文件系统工具。`terminal_send(run_in_background: true)` 会注册到 `ctx.jobs`;schema 不包含 TUI、具名按键序列、BEL、调整尺寸、自动启动和跨 agent 共享。
@@ -1726,9 +1726,9 @@ preset 或 Agent scope 挂载本包;由 preset 决定哪些 agent 获得这四
lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后,因此其模型可见 schema 在更换提供方时保持稳定。运行时要求已注册提供方,例如 `@deepseek-ai/dsh-lsp-stdio`;如果没有提供方,查询会返回结构化 `LSP_UNAVAILABLE` 错误,而不会改变 schema。
<a id="deepseek-aidsh-tool-ralph"></a>
<a id="deepseek-aidsh-experimental-tool-ralph"></a>
## `@deepseek-ai/dsh-tool-ralph`
## `@deepseek-ai/dsh-experimental-tool-ralph`
### `ralph`
@@ -1753,7 +1753,7 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后,
}
```
来源:[`packages/workflow/tool-ralph/src/index.ts`](../packages/workflow/tool-ralph/src/index.ts)
来源:[`packages/experimental/tool-ralph/src/index.ts`](../packages/experimental/tool-ralph/src/index.ts)
固定的前台工作流会在每个 Round 启动一个全新的结构化子级;模型只能选择不可变目标和可选的 Round 上限。
@@ -0,0 +1,16 @@
# Bilingual-pair consistency record for guide.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/upgrade-guide/v0.2.1-alpha.1/experimental-package-renames/guide.md
/:
en: 222547ce1ccbf1cb
zh: 7890c66934821e45
/experimental-package-names-and-explicit-composition:
en: 1ddb73ece556f6e5
zh: 1f169e6d590f45e2
/experimental-package-names-and-explicit-composition/change:
en: ae31baa97d4514be
zh: 936e1120fc433f1a
/experimental-package-names-and-explicit-composition/migration:
en: 80b390d9ed786f0b
zh: 4606a6e46a67ce2b
@@ -0,0 +1,41 @@
---
kind: upgrade-guide
description: "Nine optional packages use experimental names, and hook, webhook, Ralph, and badge configurations require explicit installation or insertion."
---
# Experimental package names and explicit composition
English | [中文](guide.zh.md)
## Change
The next release replaces these v0.2.1-alpha.1 package names:
| Old name suffix after `@deepseek-ai/dsh-` | New suffix |
|---|---|
| `hook-protocol` | `experimental-hook-protocol` |
| `hooks-claude-code` | `experimental-hooks-claude-code` |
| `hooks-codex` | `experimental-hooks-codex` |
| `webhook` | `experimental-webhook` |
| `webhook-github` | `experimental-webhook-github` |
| `session-title-all-prompts-llm` | `experimental-session-title-all-prompts-llm` |
| `tool-terminal` | `experimental-tool-terminal` |
| `tool-ralph` | `experimental-tool-ralph` |
| `skill-badge` | `experimental-skill-badge` |
The CLI and Python runtime do not install the relocated hook bridges or Ralph. The CLI does not install the webhook pair. Base and the full Web presets omit dormant Ralph rows, and base omits its dormant badge row. Patches that only enable those removed IDs no longer insert a plugin. Default active behavior, plugin registration names, tool names, and recorded Session event names remain unchanged.
## Migration
1. Replace old npm names in dependencies, imports, profile patches, and overlays using the table. Do not rewrite recorded Session events.
2. Install the packages and missing peers into each affected profile. Profiles disable automatic peer installation. For example, run `dsh plugin --profile web add @deepseek-ai/dsh-experimental-hooks-claude-code @deepseek-ai/dsh-experimental-hook-protocol`. The Codex bridge needs the same protocol peer. The GitHub adapter needs `@deepseek-ai/dsh-experimental-webhook` alongside `@deepseek-ai/dsh-experimental-webhook-github`.
3. Replace an override of a removed row with a complete insertion. Add preset-local tools inside that preset's `config.plugins`, including the services they require. A host badge insertion is:
```yaml
- insert:
- id: skill-badge
name: '@deepseek-ai/dsh-experimental-skill-badge'
```
4. For GitHub review, use the example distributed with the adapter instead of the removed CLI example. Follow the [installed-profile instructions](../../../user/guide/github-review.md); keep customized rule modules inside the profile so their imports resolve its installed packages.
5. Start the profile and confirm that its configured plugins activate without missing-package, missing-peer, or missing-row errors. Confirm the expected tool or skill is available in the intended Agent preset.
@@ -0,0 +1,41 @@
---
kind: upgrade-guide
description: "九个可选包使用实验性名称,钩子、webhook、Ralph 和徽章配置需要显式安装或插入。"
---
# 实验性包名称与显式组合
[English](guide.md) | 中文
## 变更
下一个版本替换以下 v0.2.1-alpha.1 包名称:
| `@deepseek-ai/dsh-` 后的旧名称后缀 | 新后缀 |
|---|---|
| `hook-protocol` | `experimental-hook-protocol` |
| `hooks-claude-code` | `experimental-hooks-claude-code` |
| `hooks-codex` | `experimental-hooks-codex` |
| `webhook` | `experimental-webhook` |
| `webhook-github` | `experimental-webhook-github` |
| `session-title-all-prompts-llm` | `experimental-session-title-all-prompts-llm` |
| `tool-terminal` | `experimental-tool-terminal` |
| `tool-ralph` | `experimental-tool-ralph` |
| `skill-badge` | `experimental-skill-badge` |
CLI 与 Python 运行时不再安装迁移后的钩子桥接或 Ralph。CLI 不再安装两个 webhook 包。Base 与完整 Web 预设省略休眠的 Ralph 行,base 也省略休眠的徽章行。只启用这些已删除 ID 的 patch 不会插入插件。默认活动行为、插件注册名称、工具名称与已记录的 Session 事件名称保持不变。
## 迁移
1. 按表替换依赖、导入、profile patch 和 overlay 中的旧 npm 名称。不要改写已记录的 Session 事件。
2. 将包与缺失的 peer 安装到每个受影响的 profile。Profile 禁用自动 peer 安装。例如,运行 `dsh plugin --profile web add @deepseek-ai/dsh-experimental-hooks-claude-code @deepseek-ai/dsh-experimental-hook-protocol`。Codex 桥接需要相同的协议 peer。GitHub 适配器需要同时安装 `@deepseek-ai/dsh-experimental-webhook` 与 `@deepseek-ai/dsh-experimental-webhook-github`。
3. 将覆盖已删除行的 patch 替换为完整插入。在预设的 `config.plugins` 中添加预设内工具及其需要的服务。宿主徽章插入示例:
```yaml
- insert:
- id: skill-badge
name: '@deepseek-ai/dsh-experimental-skill-badge'
```
4. GitHub review 使用适配器随附的示例,替代已删除的 CLI 示例。遵循[安装版 profile 说明](../../../user/guide/github-review.zh.md);将定制规则模块保留在 profile 内,使其导入能解析该 profile 安装的包。
5. 启动 profile,确认配置的插件激活时没有缺包、缺 peer 或缺行错误。确认预期工具或技能在目标 Agent 预设中可用。
+2 -2
View File
@@ -9,8 +9,8 @@
en: 6784d85f90231608
zh: 3e62e9cadfdc2c18
/create-review-sessions-from-github-webhooks/start-dsh:
en: 5751931f5c89b1c0
zh: 867950515a152d47
en: 6c2c8394bfaf5d11
zh: a863fa2ad6bc48bb
/create-review-sessions-from-github-webhooks/expose-the-dedicated-endpoint:
en: f18a2969b3082da9
zh: 87d3d0e58d25a62f
+5 -8
View File
@@ -22,20 +22,17 @@ export DSH_GITHUB_WEBHOOK_SECRET="$(openssl rand -hex 32)"
printf '%s\n' "$DSH_GITHUB_WEBHOOK_SECRET"
```
From a development checkout:
Install both experimental packages into the Web profile first. Profiles do not install peers automatically; the GitHub adapter needs the webhook runtime explicitly:
```sh
dsh plugin --profile web add @deepseek-ai/dsh-experimental-webhook @deepseek-ai/dsh-experimental-webhook-github
export DSH_GITHUB_REVIEW_WORKSPACE=/path/to/deepseek-harness
pnpm dsh web --patch apps/cli/config/examples/github-review/cordis.yml
dsh web --patch "${DSH_HOME:-$HOME/.dsh}/profiles/web/node_modules/@deepseek-ai/dsh-experimental-webhook-github/examples/github-review/cordis.yml"
```
An installed DSH uses the same overlay through an absolute path:
The adapter distributes the example, which loads from the profile's installation directory so its rule module can resolve profile-installed peers. Do not run the rule from an arbitrary directory outside the profile. To customize it, copy both example files to `$DSH_HOME/profiles/web/github-review/`, edit the configuration, and point `--patch` at that copy of `cordis.yml`; use `~/.dsh` when `DSH_HOME` is unset.
```sh
dsh web --patch /absolute/path/to/github-review/cordis.yml
```
For a permanent profile, place `github-ready-review-rule.mjs` beside `$DSH_HOME/profiles/web/cordis.patch.yml`, append the rows from `cordis.yml` to that patch, and start with `dsh web`. The shipped CLI already contains both webhook packages; the overlay alone activates them.
The repository example lives under `packages/experimental/webhook-github/examples/github-review/`. The CLI does not install webhook packages or list them as Official plugins; installing the packages and supplying the overlay are separate steps.
## Expose the dedicated endpoint
+5 -8
View File
@@ -22,20 +22,17 @@ export DSH_GITHUB_WEBHOOK_SECRET="$(openssl rand -hex 32)"
printf '%s\n' "$DSH_GITHUB_WEBHOOK_SECRET"
```
在开发 checkout 中运行:
先把两个实验包安装到 Web profile。Profile 不会自动安装 peer;GitHub 适配器需要显式安装 webhook 运行时:
```sh
dsh plugin --profile web add @deepseek-ai/dsh-experimental-webhook @deepseek-ai/dsh-experimental-webhook-github
export DSH_GITHUB_REVIEW_WORKSPACE=/path/to/deepseek-harness
pnpm dsh web --patch apps/cli/config/examples/github-review/cordis.yml
dsh web --patch "${DSH_HOME:-$HOME/.dsh}/profiles/web/node_modules/@deepseek-ai/dsh-experimental-webhook-github/examples/github-review/cordis.yml"
```
安装版 DSH 通过绝对路径使用同一 overlay:
示例随 GitHub 适配器发布,并从 profile 的安装目录加载,因此规则模块能解析该 profile 安装的 peer。不要把规则单独放到 profile 之外的任意目录运行。需要定制时,将示例的两个文件复制到 `$DSH_HOME/profiles/web/github-review/`,修改其配置并把 `--patch` 指向复制后的 `cordis.yml`;未设置 `DSH_HOME` 时使用 `~/.dsh`。
```sh
dsh web --patch /absolute/path/to/github-review/cordis.yml
```
对于永久 profile,把 `github-ready-review-rule.mjs` 放在 `$DSH_HOME/profiles/web/cordis.patch.yml` 旁边,把 `cordis.yml` 中的行追加到该 patch,然后运行 `dsh web`。随附 CLI 已经包含两个 webhook 包;只需 overlay 即可激活它们。
仓库中的示例位于 `packages/experimental/webhook-github/examples/github-review/`。Webhook 包不随 CLI 安装,也不出现在官方插件列表中;安装包与提供 overlay 是两个独立步骤。
## 暴露专用端点
+6 -1
View File
@@ -204,9 +204,14 @@
"mock:llm": "node --import tsx packages/test-support/llm-mock-server/src/bin.ts",
"start:web": "node --import tsx/esm apps/cli/src/bin.ts web",
"dev:web": "tsx scripts/dev-web.ts --poll",
"postinstall": "node scripts/install-lefthook.mjs"
"postinstall": "node scripts/install-lefthook.mjs",
"verify-product-use": "tsx scripts/verify-product-use.ts"
},
"devDependencies": {
"@deepseek-ai/dsh-experimental-hooks-claude-code": "workspace:*",
"@deepseek-ai/dsh-experimental-hooks-codex": "workspace:*",
"@deepseek-ai/dsh-experimental-tool-ralph": "workspace:*",
"@deepseek-ai/dsh-experimental-tool-terminal": "workspace:*",
"@deepseek-ai/dsh-agent": "workspace:*",
"@deepseek-ai/dsh-browser-use": "workspace:*",
"@deepseek-ai/dsh-experimental-browser-use-runtime": "workspace:*",
+4 -4
View File
@@ -15,11 +15,11 @@
en: ffc55792d6e922e1
zh: 83bd759638857e2d
/packages/package-groups:
en: 989c5a7131853dc6
zh: 259d15e2bceb0bb5
en: 52d0ed3ab9643687
zh: 79954308b188080b
/packages/release-expectations:
en: 7a152a53e2b1f2e5
zh: 3c154c20db49713d
en: 236081c1659b25ab
zh: 809110adf003802e
/packages/dependencies:
en: 9576e7c486bf123f
zh: fedd18da3e27ad00
+1 -3
View File
@@ -55,7 +55,6 @@ Every package lives in exactly one group; new packages join existing groups, and
| [`jobs/`](jobs/README.md) | Generic background-job runtime and model-facing job control tools |
| [`experimental/`](experimental/README.md) | Pre-stable prototypes with explicit private exceptions |
| [`workflow/`](workflow/README.md) | Workflow seam, PTC process engine, and model-facing `workflow`/`ralph` tools |
| [`webhook/`](webhook/README.md) | Verified external events, trusted rules, and fire-and-forget Workspace Sessions |
| [`web/`](web/README.md) | Web capability family: seam, search/fetch providers, model-facing web tools |
| [`document/`](document/README.md) | Shared Host Office-to-PDF conversion |
| [`attachment/`](attachment/README.md) | Durable attachment identity, validation, local content-addressed storage |
@@ -67,7 +66,6 @@ Every package lives in exactly one group; new packages join existing groups, and
| [`bundle/`](bundle/README.md) | Installable `dsh --profile` patch layers |
| [`extensions/`](extensions/README.md) | Agent runtime self-modification: live plugin/service inspection and model-written mount/unmount |
| [`mcp/`](mcp/README.md) | External Model Context Protocol servers exposed as native tools |
| [`hooks/`](hooks/README.md) | Hook bridges + the shared Claude Code / Codex wire-protocol library |
| [`session/`](session/README.md) | Durable session data plane: persistence seam + backends, projection seam, log-backed titles, session reporting |
| [`session-query/`](session-query/README.md) | Session retrieval family: logical corpus, bounded reads, lineage, semantic filtering, SQLite full-text search |
| [`settings/`](settings/README.md) | User-settings seam + file-backed provider |
@@ -88,7 +86,7 @@ Every package lives in exactly one group; new packages join existing groups, and
<a id="release-expectations"></a>
## Release expectations
Most groups are product — stable API. The exceptions: `experimental/` publishes without stability or support promises, and `test-support/` and `util/` are support with lower compatibility expectations.
Product groups have maintained product roles, while their public APIs remain pre-stable. [Experimental status](experimental/README.md#status) is independent of publication, installation, and optional delivery. Nonexperimental runtime packages must have product use or an explicit [package classification](../scripts/product-package-policy.ts); SDK, build, test, and declaration infrastructure have separate classifications.
-----
+1 -3
View File
@@ -55,7 +55,6 @@ harness 由 `packages/` 下的 npm 包组装而成,按能力系列分组:会
| [`jobs/`](jobs/README.zh.md) | 通用后台任务运行时和面向模型的作业控制工具 |
| [`experimental/`](experimental/README.zh.md) | 预稳定原型,包含显式私有例外 |
| [`workflow/`](workflow/README.zh.md) | 工作流 seam、PTC 进程引擎、面向模型的 `workflow`/`ralph` 工具 |
| [`webhook/`](webhook/README.zh.md) | 已验证外部事件、受信规则与即发即弃 Workspace 会话 |
| [`web/`](web/README.zh.md) | Web 能力系列:seam、搜索/获取提供方、面向模型的 Web 工具 |
| [`document/`](document/README.zh.md) | 共享宿主 Office 到 PDF 转换 |
| [`attachment/`](attachment/README.zh.md) | 持久附件标识、校验、本地内容寻址存储 |
@@ -67,7 +66,6 @@ harness 由 `packages/` 下的 npm 包组装而成,按能力系列分组:会
| [`bundle/`](bundle/README.zh.md) | 可安装的 `dsh --profile` 补丁层 |
| [`extensions/`](extensions/README.zh.md) | agent 运行时自修改:实时插件/服务检查与模型所写挂载/卸载 |
| [`mcp/`](mcp/README.zh.md) | 将外部 Model Context Protocol 服务器的工具接入为原生工具 |
| [`hooks/`](hooks/README.zh.md) | 钩子桥接 + 共享的 Claude Code/Codex 线协议库 |
| [`session/`](session/README.zh.md) | 持久会话数据平面:持久化 seam + 后端、投影 seam、基于日志的标题、会话上报 |
| [`session-query/`](session-query/README.zh.md) | 会话检索系列:逻辑语料库、有界读取、血缘、语义过滤、SQLite 全文搜索 |
| [`settings/`](settings/README.zh.md) | 用户设置 seam + 基于文件的提供方 |
@@ -88,7 +86,7 @@ harness 由 `packages/` 下的 npm 包组装而成,按能力系列分组:会
<a id="release-expectations"></a>
## 发布预期
大多数组属于产品组,提供稳定 API。例外:`experimental/` 发布时不提供稳定性或支持承诺,`test-support/` 与 `util/` 是兼容性预期较低的支持组。
产品组承担维护职责,但其公开 API 仍处于预稳定阶段。[实验性状态](experimental/README.zh.md#status)独立于发布、安装和可选交付。非实验运行时包必须被产品使用或在[包分类策略](../scripts/product-package-policy.ts)中明确列出;SDK、构建、测试与声明基础设施分别分类。
-----
-18
View File
@@ -303,10 +303,6 @@
- id: skill-filesystem
name: '@deepseek-ai/dsh-skill-filesystem'
- id: skill-badge
name: '@deepseek-ai/dsh-skill-badge'
disabled: true
- id: tool-skill
name: '@deepseek-ai/dsh-tool-skill'
@@ -440,20 +436,6 @@
- id: tool-goal
name: '@deepseek-ai/dsh-tool-goal'
# Fresh-agent Ralph iteration over a build-time-fixed script. Off by
# default: the tool description restricts `ralph` to runs the human
# explicitly asked for, and completion is a worker self-report, not an
# independent evaluation. An overlay row restores it for a base-backed
# profile (`$DSH_HOME/cordis.patch.yml`, or a `--patch <file>`):
# - id: tool-ralph
# disabled: false
- id: tool-ralph
name: '@deepseek-ai/dsh-tool-ralph'
disabled: true
config:
subagentProvider: spawn
maxRounds: 64
# Consecutive-repeat reminders on the tool chain.
- id: repeat-tool-reminder
name: '@deepseek-ai/dsh-repeat-tool-reminder'
-2
View File
@@ -81,7 +81,6 @@
"@deepseek-ai/dsh-session-title": "workspace:*",
"@deepseek-ai/dsh-session-title-first-prompt-llm": "workspace:*",
"@deepseek-ai/dsh-skill": "workspace:*",
"@deepseek-ai/dsh-skill-badge": "workspace:*",
"@deepseek-ai/dsh-skill-filesystem": "workspace:*",
"@deepseek-ai/dsh-spill-local": "workspace:*",
"@deepseek-ai/dsh-spill-policy": "workspace:*",
@@ -102,7 +101,6 @@
"@deepseek-ai/dsh-tool-fs-search": "workspace:*",
"@deepseek-ai/dsh-tool-goal": "workspace:*",
"@deepseek-ai/dsh-tool-pwsh": "workspace:*",
"@deepseek-ai/dsh-tool-ralph": "workspace:*",
"@deepseek-ai/dsh-tool-skill": "workspace:*",
"@deepseek-ai/dsh-tool-subagent": "workspace:*",
"@deepseek-ai/dsh-tool-subagent-control": "workspace:*",
-6
View File
@@ -557,12 +557,6 @@
- id: tool-workflow
disabled: true
# `base` ships this row disabled; the preset-plane gate reads declared row ids
# without regard to `disabled`, so this row must stay to keep `tool-ralph` off
# the host plane and out of collision with every preset's row.
- id: tool-ralph
disabled: true
- id: agent-instructions
disabled: true
-1
View File
@@ -160,7 +160,6 @@
"@deepseek-ai/dsh-tool-present": "workspace:*",
"@deepseek-ai/dsh-tool-pwsh": "workspace:*",
"@deepseek-ai/dsh-tool-pwsh-persistent": "workspace:*",
"@deepseek-ai/dsh-tool-ralph": "workspace:*",
"@deepseek-ai/dsh-tool-schedule": "workspace:*",
"@deepseek-ai/dsh-tool-skill": "workspace:*",
"@deepseek-ai/dsh-tool-subagent": "workspace:*",
@@ -132,12 +132,6 @@
provider: spawn
- id: tool-workflow
name: '@deepseek-ai/dsh-tool-workflow'
- id: tool-ralph
name: '@deepseek-ai/dsh-tool-ralph'
disabled: true
config:
subagentProvider: spawn
maxRounds: 64
- id: tool-ask-user
name: '@deepseek-ai/dsh-tool-ask-user'
- id: tool-todo
@@ -135,12 +135,6 @@
- id: tool-workflow
name: '@deepseek-ai/dsh-tool-workflow'
disabled: true
- id: tool-ralph
name: '@deepseek-ai/dsh-tool-ralph'
disabled: true
config:
subagentProvider: spawn
maxRounds: 64
- id: tool-ask-user
name: '@deepseek-ai/dsh-tool-ask-user'
- id: tool-todo
@@ -133,12 +133,6 @@
provider: spawn
- id: tool-workflow
name: '@deepseek-ai/dsh-tool-workflow'
- id: tool-ralph
name: '@deepseek-ai/dsh-tool-ralph'
disabled: true
config:
subagentProvider: spawn
maxRounds: 64
- id: tool-ask-user
name: '@deepseek-ai/dsh-tool-ask-user'
- id: tool-todo
+1 -1
View File
@@ -53,7 +53,7 @@
"@deepseek-ai/dsh-tools": "workspace:*",
"@deepseek-ai/dsh-tool-jobs": "workspace:*",
"@deepseek-ai/dsh-tool-session-query": "workspace:*",
"@deepseek-ai/dsh-tool-terminal": "workspace:*",
"@deepseek-ai/dsh-experimental-tool-terminal": "workspace:*",
"@deepseek-ai/dsh-spill": "workspace:*",
"@deepseek-ai/cordis": "workspace:~",
"@deepseek-ai/dsh-api-remotes": "workspace:*",
@@ -8,7 +8,7 @@ import { en as commonEn } from '@deepseek-ai/dsh-client-locale/src/locales/en.ts
import { zh as commonZh } from '@deepseek-ai/dsh-client-locale/src/locales/zh.ts'
import { statusLine } from '@deepseek-ai/dsh-tool-jobs/src/render.ts'
import { presentation } from '@deepseek-ai/dsh-tool-session-query/src/presentation.ts'
import { renderList, renderRead, renderSpawn } from '@deepseek-ai/dsh-tool-terminal/src/render.ts'
import { renderList, renderRead, renderSpawn } from '@deepseek-ai/dsh-experimental-tool-terminal/src/render.ts'
import { formatSpillNotice } from '@deepseek-ai/dsh-spill-policy/notice'
import { detailBadge, detailJson, detailList, detailRecord, inspectionItems, nonempty } from '../src/client/tool/models/detail-model-shared.ts'
import { detailsCardModel } from '../src/client/tool/models/details-card-model.ts'
@@ -730,7 +730,7 @@ describe('tools/pre-execute gate (native-plugin permission pattern, end-to-end t
})
describe('worked example: a native hook plugin is just a cordis plugin on the seams', () => {
// The whole point of the interception taxonomy: a "native hook" needs no dsh-hook-protocol,
// The whole point of the interception taxonomy: a "native hook" needs no dsh-experimental-hook-protocol,
// no external command, no hook/* log — it is an ordinary cordis plugin subscribing to the
// canonical events and returning typed decisions.
const NativeGuard = {
+1 -1
View File
@@ -1,6 +1,6 @@
# AGENTS.md — Experimental packages
These rules supplement the [package rules](../AGENTS.md). The [experimental publication reference](README.md) owns the publication policy; the rules below define dependency isolation and promotion.
These rules supplement the [package rules](../AGENTS.md). The [experimental reference](README.md#status) defines experimental, optional, and Official status; the rules below define dependency isolation and promotion.
- A package belongs here only when its complete public contract is experimental or internal-only. An experimental option inside a release package stays with its owning product role.
- Every package here uses the `@deepseek-ai/dsh-experimental-*` npm prefix and joins the dsh release family by default: omit `private` and set `publishConfig.access: public`. Only directories in `PRIVATE_EXPERIMENTAL_PACKAGE_DIRECTORIES` in [the publication policy](../../scripts/experimental-package-policy.ts) stay private: set `private: true` and omit `publishConfig`.
+9 -6
View File
@@ -9,14 +9,17 @@
en: 18bc48bb66b3e516
zh: 51f2340a5c921f36
/packages-experimental/summary:
en: b069b2b8ef04abd7
zh: 330095b8c3f9aa7c
en: b268bb4e0a1f2013
zh: bc4abacc015b44dc
/packages-experimental/table-of-contents:
en: 1eb35b015a6c423f
zh: a8a3dceee2c9e943
en: cd24cc2ef2ec742e
zh: 7db21f509a8620a5
/packages-experimental/experimental-optional-and-official:
en: 5d86d3390fe062a0
zh: 582d77571ba08f65
/packages-experimental/packages:
en: dc594ae77b05499c
zh: 06090a11e2144b47
en: 8dbff5ff0843dd44
zh: 5d8947f8a309f8b0
/packages-experimental/related-documentation:
en: 1cb9d3448d44e48d
zh: cd326d70a746b896
+22 -1
View File
@@ -9,21 +9,42 @@ English | [中文](README.zh.md)
## Summary
Experimental prototypes may change their contracts and carry no support promise. New packages publish by default; private packages must also appear in the [private-exception list](../../scripts/experimental-package-policy.ts). All current packages publish under their `@deepseek-ai/dsh-experimental-*` names, including the opt-in Agent Teams composition, Auto review, Cua Driver providers, browser-use backends, cross-realm Inspector, CPython PTC backend, and browser-worker preview libraries. Released products outside this group must not depend on experimental packages. The dsh installation ships its optional bundles switched off; the GUI plugin manager offers them in the Official group ([decision](../../.agents/notes/implemented/architecture/2026-09-21-experimental-capabilities-as-optional-bundles.md)); the other packages are libraries or explicit compositions.
Install and compose experimental capabilities explicitly, without a product-support commitment. Packages publish under `@deepseek-ai/dsh-experimental-*`; private packages require an entry in the [publication policy](../../scripts/experimental-package-policy.ts). The [optional-bundle rule](../../.agents/notes/implemented/architecture/2026-09-21-experimental-capabilities-as-optional-bundles.md) determines which capabilities ship switched off with the installation for explicit selection in the GUI plugin manager’s Official group.
## Table of Contents
- [Experimental, optional, and Official](#status)
- [Packages](#packages)
- [Related documentation](#related-documentation)
- [Dev Note](#dev-note)
-----
<a id="status"></a>
## Experimental, optional, and Official
**Experimental** means the complete public capability remains under evaluation and is not a product-support commitment. Its behavior or API may change, and the capability may be withdrawn; engineering, security, documentation, testing, and released-data obligations still apply. A package belongs here only when its entire public contract is experimental or internal-only; an experimental option inside a product package stays with that product role.
**Optional** means a user explicitly selects the capability. **Official** means the project maintains and lists the package in the Plugins page. Neither describes maturity; publication, default installation, and GUI visibility do not determine maturity either. Product packages outside this group have maintained product roles, while their public APIs still follow the repository's pre-stable policy.
Promotion requires a named product role, documented public behavior and limitations, current consumers, release contents, and test evidence. Move the package to its product group, remove `experimental-` from its npm name, and update every consumer together. The [subtree rules](AGENTS.md) govern dependency isolation and publication.
-----
<a id="packages"></a>
## Packages
| Package | Role | ctx key |
|---|---|---|
| [`hook-protocol`](hook-protocol/README.md) | Hook bridge wire types and durable events | — |
| [`hooks-claude-code`](hooks-claude-code/README.md) | Claude Code hook bridge | — |
| [`hooks-codex`](hooks-codex/README.md) | Codex hook bridge | — |
| [`webhook`](webhook/README.md) | Authenticated delivery dispatch and Workspace Session creation | `ctx.webhookRuntime` |
| [`webhook-github`](webhook-github/README.md) | Signed GitHub webhook ingress | — |
| [`session-title-all-prompts-llm`](session-title-all-prompts-llm/README.md) | Session titles from all human prompts | — |
| [`tool-terminal`](tool-terminal/README.md) | Persistent terminal tools | — |
| [`tool-ralph`](tool-ralph/README.md) | Bounded repeated delegated tasks | — |
| [`skill-badge`](skill-badge/README.md) | The powered-by-dsh badge skill | — |
| [`translator`](translator/README.md) | Anonymous Google and Bing text translation | `ctx.translator` |
| [`client-ui-cot-translation`](client-ui-cot-translation/README.md) | Expanded reasoning translation and original-text controls | `ctx.cotTranslation` |
| [`cot-translation-bundle`](cot-translation-bundle/README.md) | Default-disabled reasoning translation composition | — |
+22 -1
View File
@@ -9,21 +9,42 @@ kind: "package-group"
## 概述
实验性原型的约定可能变更,且不提供支持承诺。新包默认发布;私有包还必须列入[私有例外列表](../../scripts/experimental-package-policy.ts)。所有当前包都以 `@deepseek-ai/dsh-experimental-*` 名称发布,包括显式启用的 Agent Teams 组合、Auto review、Cua Driver 提供方、浏览器操作后端、跨 realm Inspector、CPython PTC 后端与浏览器 worker 预览库。组外已发布产品不得依赖实验性包。dsh 安装随附默认关闭的可选 bundle,GUI 插件管理器在官方分组提供它们([决策](../../.agents/notes/implemented/architecture/2026-09-21-experimental-capabilities-as-optional-bundles.zh.md));其余包是库或显式组合。
实验性能力可按需安装和组合,但不提供产品支持承诺。各包以 `@deepseek-ai/dsh-experimental-*` 名称发布;私有包必须列入[发布策略](../../scripts/experimental-package-policy.ts)。[可选组合规则](../../.agents/notes/implemented/architecture/2026-09-21-experimental-capabilities-as-optional-bundles.zh.md)决定哪些能力以默认关闭状态随安装提供,并在 GUI 插件管理器的官方分组显式启用。
## 目录
- [实验性、可选与官方](#status)
- [包](#packages)
- [相关文档](#related-documentation)
- [开发备注](#dev-note)
-----
<a id="status"></a>
## 实验性、可选与官方
**实验性**表示整个公开能力仍在评估中,不属于产品支持承诺。其行为或 API 可能变更,能力也可能被撤回;工程、安全、文档、测试和已发布数据的义务仍然适用。只有其完整公开约定均为实验性或仅限内部使用的包才属于本组;产品包中的实验选项仍归原产品职责所有。
**可选**表示用户显式选择该能力。**官方**表示项目维护并在插件页列出该包。两者均不表示成熟度;发布、默认安装和界面可见性也不决定成熟度。组外产品包承担维护职责,其公开 API 仍遵循仓库的预稳定政策。
晋升需要明确的产品职责、公开行为与限制、当前消费者、发布内容以及测试证据。晋升时将包移入对应产品组,去掉 npm 名称中的 `experimental-`,并同时更新所有消费者。[子树规则](AGENTS.md)规定依赖隔离和发布要求。
-----
<a id="packages"></a>
## 包
| 包 | 职责 | ctx 键 |
|---|---|---|
| [`hook-protocol`](hook-protocol/README.zh.md) | 钩子桥接的通信类型与持久事件 | — |
| [`hooks-claude-code`](hooks-claude-code/README.zh.md) | Claude Code 钩子桥接 | — |
| [`hooks-codex`](hooks-codex/README.zh.md) | Codex 钩子桥接 | — |
| [`webhook`](webhook/README.zh.md) | 已认证投递分发与 Workspace Session 创建 | `ctx.webhookRuntime` |
| [`webhook-github`](webhook-github/README.zh.md) | 带签名的 GitHub webhook 入口 | — |
| [`session-title-all-prompts-llm`](session-title-all-prompts-llm/README.zh.md) | 根据所有人类提示生成会话标题 | — |
| [`tool-terminal`](tool-terminal/README.zh.md) | 持久终端工具 | — |
| [`tool-ralph`](tool-ralph/README.zh.md) | 有界重复委派任务 | — |
| [`skill-badge`](skill-badge/README.zh.md) | powered-by-dsh 徽章技能 | — |
| [`translator`](translator/README.zh.md) | 免登录 Google 与 Bing 文本翻译 | `ctx.translator` |
| [`client-ui-cot-translation`](client-ui-cot-translation/README.zh.md) | 展开的思考内容翻译与原文控件 | `ctx.cotTranslation` |
| [`cot-translation-bundle`](cot-translation-bundle/README.zh.md) | 默认禁用的思考内容翻译组合 | — |
@@ -45,8 +45,8 @@
en: a141066b146cef7c
zh: fe91851f05c008c4
/deepseek-ai-dsh-experimental-claude-code-mods/further-exploration:
en: 43c558ca826febdd
zh: 3dfd87ca60c6548d
en: 66d98f72199cbb41
zh: 0409978863af3b1e
/deepseek-ai-dsh-experimental-claude-code-mods/model-experience:
en: 215e7ba838619b7b
zh: a311da3843709f90
@@ -78,8 +78,8 @@
en: ca31263f47f654d9
zh: 17d55e6641705627
/deepseek-ai-dsh-experimental-claude-code-mods/known-limitations-and-deferred-work:
en: 99aaa73c8ef9c609
zh: 46fab480bd2b1706
en: c4e5cc431b15c7e5
zh: a964d0a9a1f13b0f
/deepseek-ai-dsh-experimental-claude-code-mods/known-limitations-and-deferred-work/dev-note:
en: 4d1e26f4cc9c3c1c
zh: d80209b56c56b11c
@@ -148,7 +148,7 @@ A call whose service is not composed rejects with the missing service's package
- [Claude Code mods reference](https://code.claude.com/docs/en/plugins/mods/reference) — the events, methods, and limits this bridge mirrors.
- [The Web band](../client-ui-claude-code-mods/README.md) — the Client package that draws `ui.render` trees in the input dock.
- [Experimental packages](../README.md) — publication policy and dependency isolation.
- [Hooks group](../../hooks/README.md) — the settings-hook bridges; a plugin's `hooks.json` settings hooks need `dsh-hooks-claude-code`.
- [Hooks group](../README.md) — the settings-hook bridges; a plugin's `hooks.json` settings hooks need `dsh-experimental-hooks-claude-code`.
- [Tool execution pipeline](../../../docs/tool-execution-pipeline.md) — the waterfalls `tool.call` runs around.
- [Human commands](../../interaction/commands/README.md) — the registry `$.command.register` lands on.
@@ -207,7 +207,7 @@ These limits describe where a Claude Code mod behaves differently through this b
- **No sandbox, no static analysis, no hot reload** — the hooks module runs in-process with Node's globals and the process's full authority (its environment, network, filesystem, and tools); the `$`-only access rule, `claude plugin validate`, type generation, `--plugin-dir` watching, and the in-session mod authoring flow are not implemented. Mount only mods you would run as a plugin. Mounting a mod again re-runs `register` on the same evaluated module, so module-level variables keep their values.
- **`turn.complete` text** — the `{ text }` a hook returns reaches the host log, not a line under the answer; `durationMs` counts from the turn's `turn/start`.
- **`$.session.usage`** — `window` is `0` and `percent` absent until the route's context window and a provider usage report are known through the token meter; `rateLimits` is always empty. `$.fs.stat` reports `mtimeMs: 0`.
- **`plugin.json` and `hooks.json`** — not read; `defineMod` carries the identity, and a plugin's settings hooks need `@deepseek-ai/dsh-hooks-claude-code`.
- **`plugin.json` and `hooks.json`** — not read; `defineMod` carries the identity, and a plugin's settings hooks need `@deepseek-ai/dsh-experimental-hooks-claude-code`.
<a id="dev-note"></a>
### Dev Note
@@ -148,7 +148,7 @@ Blast Radius 的 DSH 包装使用当前运行的可执行文件提供 Node 计
- [Claude Code 模组参考](https://code.claude.com/docs/en/plugins/mods/reference) — 本桥接镜像的事件、方法与限制。
- [Web 横幅](../client-ui-claude-code-mods/README.zh.md) — 在输入停靠区绘制 `ui.render` 树的 Client 包。
- [实验性包](../README.zh.md) — 发布策略与依赖隔离。
- [Hooks 组](../../hooks/README.zh.md) — 设置钩子桥接;插件 `hooks.json` 中的设置钩子需要 `dsh-hooks-claude-code`。
- [Hooks 组](../README.zh.md) — 设置钩子桥接;插件 `hooks.json` 中的设置钩子需要 `dsh-experimental-hooks-claude-code`。
- [工具执行流水线](../../../docs/tool-execution-pipeline.zh.md) — `tool.call` 所包裹的瀑布流。
- [人类命令](../../interaction/commands/README.zh.md) — `$.command.register` 落到的注册表。
@@ -207,7 +207,7 @@ Message from the "<plugin>" mod:
- **无沙箱、无静态分析、无热重载** — 钩子模块以 Node 全局对象在进程内运行,拥有本进程的全部权限(环境变量、网络、文件系统与工具);仅 `$` 访问规则、`claude plugin validate`、类型生成、`--plugin-dir` 监视与会话内模组编写流程均未实现。只挂载你愿意作为插件运行的模组。再次挂载模组会在同一已求值模块上重新运行 `register`,模块级变量保留其值。
- **`turn.complete` 文本** — 钩子返回的 `{ text }` 到达宿主日志,而非答案下方的一行;`durationMs` 从该轮的 `turn/start` 起算。
- **`$.session.usage`** — 在 token 计量器得知路由的上下文窗口与提供商用量报告之前,`window` 为 `0` 且无 `percent`;`rateLimits` 始终为空。`$.fs.stat` 报告 `mtimeMs: 0`。
- **`plugin.json` 与 `hooks.json`** — 不读取;`defineMod` 承载身份,插件的设置钩子需要 `@deepseek-ai/dsh-hooks-claude-code`。
- **`plugin.json` 与 `hooks.json`** — 不读取;`defineMod` 承载身份,插件的设置钩子需要 `@deepseek-ai/dsh-experimental-hooks-claude-code`。
<a id="dev-note"></a>
### 开发备注
@@ -0,0 +1,61 @@
# Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/experimental/hook-protocol/README.md
/:
en: 7cfe3761eedff848
zh: 80b0bed5743d0924
/deepseek-ai-dsh-experimental-hook-protocol:
en: 59c4379ae58d7ca3
zh: 6d015de6ce018358
/deepseek-ai-dsh-experimental-hook-protocol/summary:
en: 2831db16082fcbed
zh: 38c1eb54c1dd56dc
/deepseek-ai-dsh-experimental-hook-protocol/table-of-contents:
en: d152484eb41ac6b4
zh: 09388d293f9be9cb
/deepseek-ai-dsh-experimental-hook-protocol/use-this-package:
en: 84b3719a71cc14a9
zh: 8f500851d2f02784
/deepseek-ai-dsh-experimental-hook-protocol/use-this-package/when-to-choose-it:
en: b1a1a4e9652ab792
zh: 08f819dd3b0b98d4
/deepseek-ai-dsh-experimental-hook-protocol/use-this-package/what-a-hook-can-do:
en: 043f54b3a5b518a7
zh: a4115083a9b1cef1
/deepseek-ai-dsh-experimental-hook-protocol/use-this-package/what-you-see-when-hooks-run:
en: ba2d6ed1db063f53
zh: ab1b8d72dccd2ff1
/deepseek-ai-dsh-experimental-hook-protocol/understand-the-implementation:
en: 08b3960150e9c5e2
zh: 6bb2f236d697de01
/deepseek-ai-dsh-experimental-hook-protocol/understand-the-implementation/processing-pipeline:
en: b25d80f19b551f1a
zh: 9c6602f008d89bce
/deepseek-ai-dsh-experimental-hook-protocol/understand-the-implementation/hook-session-events:
en: f01ab4ab98f052b3
zh: 1da25fa50378bd19
/deepseek-ai-dsh-experimental-hook-protocol/understand-the-implementation/design-philosophy:
en: 7f9239eaea5a945c
zh: 9ba6a2ea955d4934
/deepseek-ai-dsh-experimental-hook-protocol/understand-the-implementation/source-map:
en: aa4983adf89ea45c
zh: cc83b0ede5ff156c
/deepseek-ai-dsh-experimental-hook-protocol/further-exploration:
en: 8b585ce73c2be2cc
zh: c0270fd001e1352b
/deepseek-ai-dsh-experimental-hook-protocol/model-experience:
en: 99188699e4c6e334
zh: bba689b1e0f33d97
/deepseek-ai-dsh-experimental-hook-protocol/model-experience/kv-cache-effect:
en: e290ccc9b3c92c08
zh: cb3c8823f41e7afe
/deepseek-ai-dsh-experimental-hook-protocol/known-limitations-and-deferred-work:
en: 1ca6146a077a7d2d
zh: 369741569178fc79
/deepseek-ai-dsh-experimental-hook-protocol/known-limitations-and-deferred-work/dev-note:
en: ac1d08360a93382b
zh: 6c58749bae9a6e65
/deepseek-ai-dsh-experimental-hook-protocol/known-limitations-and-deferred-work/dev-note/future-run-level-halt:
en: bfb3db50de22c1d0
zh: 2a979359b0edbbe7
@@ -3,13 +3,13 @@ description: "The shared hook rules behind the Claude Code and Codex bridges —
kind: "package-library"
---
# @deepseek-ai/dsh-hook-protocol
# @deepseek-ai/dsh-experimental-hook-protocol
English | [中文](README.zh.md)
## Summary
`dsh-hook-protocol` makes both bridges handle your hooks identically: it defines what a hook can do and what happens when it runs. You never install or configure it yourself — choose `dsh-hooks-claude-code` or `dsh-hooks-codex`, point it at your existing `hooks.json`, and these rules apply to your hooks. Through either bridge, a hook can block a prompt or tool call with a message the model sees, attach extra context to the conversation, or ask the run to stop. Only command hooks run; `http`, `mcp_tool`, `prompt`, and `agent` handlers are skipped with a warning.
`dsh-experimental-hook-protocol` makes both bridges handle your hooks identically: it defines what a hook can do and what happens when it runs. You never install or configure it yourself — choose `dsh-experimental-hooks-claude-code` or `dsh-experimental-hooks-codex`, point it at your existing `hooks.json`, and these rules apply to your hooks. Through either bridge, a hook can block a prompt or tool call with a message the model sees, attach extra context to the conversation, or ask the run to stop. Only command hooks run; `http`, `mcp_tool`, `prompt`, and `agent` handlers are skipped with a warning.
## Table of Contents
@@ -25,11 +25,11 @@ English | [中文](README.zh.md)
<a id="use-this-package"></a>
## Use this package
You don't install or configure this package directly — mounting `dsh-hooks-claude-code` or `dsh-hooks-codex` applies these rules to your existing `hooks.json` hooks. Use this page to learn what a hook can do and what happens when it runs; the two bridge pages list which events each dialect supports.
You don't install or configure this package directly — mounting `dsh-experimental-hooks-claude-code` or `dsh-experimental-hooks-codex` applies these rules to your existing `hooks.json` hooks. Use this page to learn what a hook can do and what happens when it runs; the two bridge pages list which events each dialect supports.
### When to choose it
Choose `dsh-hooks-claude-code` or `dsh-hooks-codex` when you have existing Claude Code or Codex hooks and want them to keep working during agent runs. You never choose this package directly. Avoid the whole group for bespoke behavior with no reference-tool equivalent: a native Cordis plugin has the full harness API with no hook protocol in between.
Choose `dsh-experimental-hooks-claude-code` or `dsh-experimental-hooks-codex` when you have existing Claude Code or Codex hooks and want them to keep working during agent runs. You never choose this package directly. Avoid the whole group for bespoke behavior with no reference-tool equivalent: a native Cordis plugin has the full harness API with no hook protocol in between.
### What a hook can do
@@ -112,7 +112,7 @@ Read these pages when the package-level contract is not enough. They move from t
<a id="model-experience"></a>
## Model Experience
Indirectly, through `dsh-hooks-claude-code` and `dsh-hooks-codex`, which are the only consumers that render decoded hook output into model context.
Indirectly, through `dsh-experimental-hooks-claude-code` and `dsh-experimental-hooks-codex`, which are the only consumers that render decoded hook output into model context.
#### KV Cache effect
@@ -3,13 +3,13 @@ description: "Claude Code 与 Codex 桥接背后的共享钩子规则——钩
kind: "package-library"
---
# @deepseek-ai/dsh-hook-protocol
# @deepseek-ai/dsh-experimental-hook-protocol
[English](README.md) | 中文
## 概述
`dsh-hook-protocol` 让两个桥接以相同方式处理你的钩子:它定义钩子能做什么、运行时会发生什么。你无需自行安装或配置它——选择 `dsh-hooks-claude-code` 或 `dsh-hooks-codex`,把它指向你现有的 `hooks.json`,这些规则就会作用于你的钩子。通过任一桥接,钩子都可以带一条模型可见的消息阻塞提示词或工具调用、向对话附加额外上下文,或请求运行停止。只有 command 钩子会运行;`http`、`mcp_tool`、`prompt` 与 `agent` handler 会被跳过并给出警告。
`dsh-experimental-hook-protocol` 让两个桥接以相同方式处理你的钩子:它定义钩子能做什么、运行时会发生什么。你无需自行安装或配置它——选择 `dsh-experimental-hooks-claude-code` 或 `dsh-experimental-hooks-codex`,把它指向你现有的 `hooks.json`,这些规则就会作用于你的钩子。通过任一桥接,钩子都可以带一条模型可见的消息阻塞提示词或工具调用、向对话附加额外上下文,或请求运行停止。只有 command 钩子会运行;`http`、`mcp_tool`、`prompt` 与 `agent` handler 会被跳过并给出警告。
## 目录
@@ -25,11 +25,11 @@ kind: "package-library"
<a id="use-this-package"></a>
## 使用本包
你无需直接安装或配置本包——挂载 `dsh-hooks-claude-code` 或 `dsh-hooks-codex` 就会把这些规则应用到你的 `hooks.json` 钩子上。用本页了解钩子能做什么、运行时会发生什么;两个桥接页面列出各方言支持的事件。
你无需直接安装或配置本包——挂载 `dsh-experimental-hooks-claude-code` 或 `dsh-experimental-hooks-codex` 就会把这些规则应用到你的 `hooks.json` 钩子上。用本页了解钩子能做什么、运行时会发生什么;两个桥接页面列出各方言支持的事件。
### 何时选择
当你持有现有的 Claude Code 或 Codex 钩子、希望它们在 agent(智能体)运行期间继续工作时,选择 `dsh-hooks-claude-code` 或 `dsh-hooks-codex`。你永远不会直接选择本包。没有参考工具对应物的定制行为请避开整个组:原生 Cordis 插件拥有完整的 harness API,无需中间的钩子协议。
当你持有现有的 Claude Code 或 Codex 钩子、希望它们在 agent(智能体)运行期间继续工作时,选择 `dsh-experimental-hooks-claude-code` 或 `dsh-experimental-hooks-codex`。你永远不会直接选择本包。没有参考工具对应物的定制行为请避开整个组:原生 Cordis 插件拥有完整的 harness API,无需中间的钩子协议。
### 钩子能做什么
@@ -112,7 +112,7 @@ kind: "package-library"
<a id="model-experience"></a>
## 模型体验
通过 `dsh-hooks-claude-code` 与 `dsh-hooks-codex` 间接影响;它们是将解码后的 hook 输出渲染为模型上下文的唯一消费方。
通过 `dsh-experimental-hooks-claude-code` 与 `dsh-experimental-hooks-codex` 间接影响;它们是将解码后的 hook 输出渲染为模型上下文的唯一消费方。
#### KV Cache 影响
@@ -1,5 +1,5 @@
{
"name": "@deepseek-ai/dsh-hook-protocol",
"name": "@deepseek-ai/dsh-experimental-hook-protocol",
"description": "Shared Claude Code / Codex hook wire protocol: matcher engine, stdin/exit-code/stdout codec, multi-hook merge, and hook/* session events",
"version": "0.2.1-alpha.1",
"publishConfig": {
@@ -8,7 +8,7 @@
"repository": {
"type": "git",
"url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
"directory": "packages/hooks/hook-protocol"
"directory": "packages/experimental/hook-protocol"
},
"type": "module",
"main": "lib/index.js",
@@ -2,7 +2,7 @@
* Decode hook process outcomes for both dialects. Exit 0 may carry structured
* JSON or plain stdout; exit 2 blocks with stderr as the reason; every other
* exit is a non-blocking error. Bridges decide which recognized fields apply.
* @module @deepseek-ai/dsh-hook-protocol/codec
* @module @deepseek-ai/dsh-experimental-hook-protocol/codec
*/
import type { HookOutput } from './types.ts'
@@ -2,7 +2,7 @@
* Quiescence tracking for emit-shaped hook runs that no extension point awaits. Bridges
* track the run plus its continuation, pass the tracker signal into execution,
* and drain on disposal so no process or late callback outlives the fiber.
* @module @deepseek-ai/dsh-hook-protocol/detached
* @module @deepseek-ai/dsh-experimental-hook-protocol/detached
*/
/** In-flight registry for one bridge's detached hook runs; see the module doc for the wiring contract. */
@@ -3,7 +3,7 @@
* intent and must remain turn-enclosed and invoked/result paired. Mid-turn hook
* points satisfy that boundary; SessionStart records injected context instead
* and does not append `hook/*` outside a turn.
* @module @deepseek-ai/dsh-hook-protocol/events
* @module @deepseek-ai/dsh-experimental-hook-protocol/events
*/
import type { Session } from '@deepseek-ai/dsh-session'
@@ -3,7 +3,7 @@
* decoding, restrictive outcome merging, durable event helpers, and detached
* run quiescence. Claude Code and Codex bridges own their distinct payloads,
* environment rules, matcher mode, and typed extension-point mappings.
* @module @deepseek-ai/dsh-hook-protocol
* @module @deepseek-ai/dsh-experimental-hook-protocol
*/
export type {
@@ -4,7 +4,7 @@
* treats every non-empty pattern as an unanchored regex. Missing, empty, and
* `*` match all. Runtime matching contains invalid regexes as non-matches;
* config parsers use {@link matcherDiagnostic} to reject them with a diagnostic.
* @module @deepseek-ai/dsh-hook-protocol/matcher
* @module @deepseek-ai/dsh-experimental-hook-protocol/matcher
*/
import type { MatcherGroup, MatcherMode } from './types.ts'
@@ -3,7 +3,7 @@
* is `deny > ask > allow`; the first `continue:false` stop is sticky; reasons
* for the winning rank are joined; and context and system messages accumulate
* in hook order.
* @module @deepseek-ai/dsh-hook-protocol/merge
* @module @deepseek-ai/dsh-experimental-hook-protocol/merge
*/
import type { HookOutput } from './types.ts'
@@ -3,7 +3,7 @@
* process-group cancellation, and timeout machinery. The bridge supplies the
* trusted stdin payload and dialect environment, then this module decodes the
* captured outcome.
* @module @deepseek-ai/dsh-hook-protocol/runner
* @module @deepseek-ai/dsh-experimental-hook-protocol/runner
*/
import type { ShellExecutor } from '@deepseek-ai/dsh-shell'
@@ -2,7 +2,7 @@
* Dialect-neutral vocabulary and log-only events shared by the Claude Code and
* Codex hook bridges. Payload construction, matching differences, environment,
* and extension-point-specific decision mapping remain owned by each bridge.
* @module @deepseek-ai/dsh-hook-protocol/types
* @module @deepseek-ai/dsh-experimental-hook-protocol/types
*/
declare module '@deepseek-ai/dsh-session/types' {
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest'
import { parseHookOutput } from '@deepseek-ai/dsh-hook-protocol'
import { parseHookOutput } from '@deepseek-ai/dsh-experimental-hook-protocol'
describe('parseHookOutput — exit code semantics', () => {
it('exit 0 with no stdout is a neutral success', () => {
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest'
import { createDetachedRuns } from '@deepseek-ai/dsh-hook-protocol'
import { createDetachedRuns } from '@deepseek-ai/dsh-experimental-hook-protocol'
/** A promise settled from outside, so a test controls exactly when a tracked run finishes. */
function deferred(): { promise: Promise<void>; resolve: () => void; reject: (error: Error) => void } {
@@ -1,6 +1,6 @@
import { describe, expect, it } from 'vitest'
import { Session, SessionId } from '@deepseek-ai/dsh-session'
import { appendHookInvoked, appendHookResult, summarizeStderr, type HookOutput } from '@deepseek-ai/dsh-hook-protocol'
import { appendHookInvoked, appendHookResult, summarizeStderr, type HookOutput } from '@deepseek-ai/dsh-experimental-hook-protocol'
/** A {@link HookOutput} with the required stream fields defaulted. */
function output(over: Partial<HookOutput> = {}): HookOutput {
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest'
import { matcherDiagnostic, matchesMatcher, selectHookGroups, type MatcherGroup } from '@deepseek-ai/dsh-hook-protocol'
import { matcherDiagnostic, matchesMatcher, selectHookGroups, type MatcherGroup } from '@deepseek-ai/dsh-experimental-hook-protocol'
describe('matchesMatcher — match-all sentinels (both dialects)', () => {
for (const mode of ['claude-code', 'codex'] as const) {
@@ -1,6 +1,6 @@
import { describe, expect, it } from 'vitest'
import { mergeHookOutputs } from '@deepseek-ai/dsh-hook-protocol'
import type { HookOutput } from '@deepseek-ai/dsh-hook-protocol'
import { mergeHookOutputs } from '@deepseek-ai/dsh-experimental-hook-protocol'
import type { HookOutput } from '@deepseek-ai/dsh-experimental-hook-protocol'
function out(over: Partial<HookOutput> = {}): HookOutput {
return { exitCode: 0, stderr: '', stdout: '', ...over }
@@ -1,7 +1,7 @@
import { describe, expect, expectTypeOf, it } from 'vitest'
import type { ShellExecRequest, ShellExecSpec, ShellExecution, ShellExecutor, ShellRunResult } from '@deepseek-ai/dsh-shell'
import { DEFAULT_HOOK_TIMEOUT_MS, runHook } from '@deepseek-ai/dsh-hook-protocol'
import type { RunHookOptions } from '@deepseek-ai/dsh-hook-protocol'
import { DEFAULT_HOOK_TIMEOUT_MS, runHook } from '@deepseek-ai/dsh-experimental-hook-protocol'
import type { RunHookOptions } from '@deepseek-ai/dsh-experimental-hook-protocol'
/**
* A minimal stand-in for the bits of {@link ShellExecutor} that {@link runHook}
@@ -0,0 +1,88 @@
# Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/experimental/hooks-claude-code/README.md
/:
en: 3570440302708236
zh: 6e4217f2856879a1
/deepseek-ai-dsh-experimental-hooks-claude-code:
en: 77dc8c195263a10d
zh: 51f3ab9fa13d950e
/deepseek-ai-dsh-experimental-hooks-claude-code/summary:
en: 6aaa917b54b3af85
zh: 7054c24382ab6083
/deepseek-ai-dsh-experimental-hooks-claude-code/table-of-contents:
en: d152484eb41ac6b4
zh: 09388d293f9be9cb
/deepseek-ai-dsh-experimental-hooks-claude-code/use-this-package:
en: af7c3b8bcce24e7f
zh: 6b5225e34cbd1c85
/deepseek-ai-dsh-experimental-hooks-claude-code/use-this-package/when-to-choose-it:
en: 5fdf4ff17e6d9a2e
zh: 82979c137758005d
/deepseek-ai-dsh-experimental-hooks-claude-code/use-this-package/smallest-working-setup:
en: 2c493d787543e82b
zh: fc2f7c595a5542f6
/deepseek-ai-dsh-experimental-hooks-claude-code/use-this-package/what-your-hooks-can-do:
en: 6c3b126e6607c311
zh: 33199f443edb2824
/deepseek-ai-dsh-experimental-hooks-claude-code/use-this-package/how-hooks-run-and-fail:
en: 98d13f2e7207e3f3
zh: 4e0336b32c2775e9
/deepseek-ai-dsh-experimental-hooks-claude-code/understand-the-implementation:
en: d33ddd080880b3f5
zh: 64328f5239c26752
/deepseek-ai-dsh-experimental-hooks-claude-code/understand-the-implementation/hook-point-mapping:
en: d315f54ec60f8860
zh: 53b7a6531d9f4bbb
/deepseek-ai-dsh-experimental-hooks-claude-code/understand-the-implementation/payloads-and-environment:
en: 0389b516653c7f45
zh: 15ec2182113a9aa4
/deepseek-ai-dsh-experimental-hooks-claude-code/understand-the-implementation/matcher-subjects-and-serial-execution:
en: 0f30690502687688
zh: 19d4ec653c19f00e
/deepseek-ai-dsh-experimental-hooks-claude-code/understand-the-implementation/detached-runs-and-disposal:
en: aa09842e9c40ad82
zh: f7b65a3f2604003c
/deepseek-ai-dsh-experimental-hooks-claude-code/understand-the-implementation/design-philosophy:
en: e9dc2e482e9a7b50
zh: 5fa4e92b75884f93
/deepseek-ai-dsh-experimental-hooks-claude-code/understand-the-implementation/source-map:
en: 0289ee9e374d3606
zh: b88841c10ad5c10f
/deepseek-ai-dsh-experimental-hooks-claude-code/further-exploration:
en: 6f34fec52fcf5fd3
zh: 15dde7f0ec896efc
/deepseek-ai-dsh-experimental-hooks-claude-code/model-experience:
en: 215e7ba838619b7b
zh: a311da3843709f90
/deepseek-ai-dsh-experimental-hooks-claude-code/model-experience/hook-provided-context:
en: 7b2f5028dacd7146
zh: e4d226735f7abfc2
/deepseek-ai-dsh-experimental-hooks-claude-code/model-experience/hook-provided-context/what-the-model-sees:
en: 7b6edde085633c5f
zh: caadcfe8b9364c6d
/deepseek-ai-dsh-experimental-hooks-claude-code/model-experience/hook-provided-context/token-effect:
en: b70e3524b160cd63
zh: e1011ee18d1bf12b
/deepseek-ai-dsh-experimental-hooks-claude-code/model-experience/hook-provided-context/kv-cache-effect:
en: f5d5f97a153f7c70
zh: f681f89596f500f5
/deepseek-ai-dsh-experimental-hooks-claude-code/model-experience/blocked-prompt-or-tool-outcome:
en: 82be8d95921ef639
zh: 11c185068ec18932
/deepseek-ai-dsh-experimental-hooks-claude-code/model-experience/blocked-prompt-or-tool-outcome/what-the-model-sees:
en: 1313b662532a2bda
zh: 4002d38540286a94
/deepseek-ai-dsh-experimental-hooks-claude-code/model-experience/blocked-prompt-or-tool-outcome/token-effect:
en: 7c13e10d2a0e3151
zh: 54ffd88bca4fce3a
/deepseek-ai-dsh-experimental-hooks-claude-code/model-experience/blocked-prompt-or-tool-outcome/kv-cache-effect:
en: f84fa6c0511cd113
zh: f6ce9cdd47a72684
/deepseek-ai-dsh-experimental-hooks-claude-code/known-limitations-and-deferred-work:
en: 23ab8cf19542ea03
zh: e56f896b4393c1c5
/deepseek-ai-dsh-experimental-hooks-claude-code/known-limitations-and-deferred-work/dev-note:
en: b1e9a373ae8b7bb0
zh: 30446fe59d5ec8be
@@ -3,13 +3,13 @@ description: "Run your existing Claude Code hooks.json or settings hook config d
kind: "package-reference"
---
# @deepseek-ai/dsh-hooks-claude-code
# @deepseek-ai/dsh-experimental-hooks-claude-code
English | [中文](README.zh.md)
## Summary
`dsh-hooks-claude-code` runs command hooks from your existing Claude Code `hooks.json` or settings file during agent runs, without requiring a rewrite. Supported hooks can run when sessions, prompts, tools, stops, or subagents reach matching moments. They can block prompts or tool calls with model-visible reasons, add conversation context, or force another model turn. Choose this package to reuse Claude Code command hooks in the harness; use a native plugin for behavior that has no Claude Code equivalent.
`dsh-experimental-hooks-claude-code` runs command hooks from your existing Claude Code `hooks.json` or settings file during agent runs, without requiring a rewrite. Supported hooks can run when sessions, prompts, tools, stops, or subagents reach matching moments. They can block prompts or tool calls with model-visible reasons, add conversation context, or force another model turn. Choose this package to reuse Claude Code command hooks in the harness; use a native plugin for behavior that has no Claude Code equivalent.
## Table of Contents
@@ -36,7 +36,7 @@ Use it when you own a Claude Code `hooks.json` (or a settings file whose `hooks`
### Smallest working setup
```yaml
- name: '@deepseek-ai/dsh-hooks-claude-code'
- name: '@deepseek-ai/dsh-experimental-hooks-claude-code'
config:
configPath: ./.claude/hooks.json
pluginRoot: ./.claude/plugins/my-plugin
@@ -51,7 +51,7 @@ Use it when you own a Claude Code `hooks.json` (or a settings file whose `hooks`
| `defaultTimeoutMs` | `600,000` | Per-hook timeout when a hook sets none (the Claude Code default) |
| `stderrSummaryMaxChars` | `500` | Character cap on the persisted `hook/result` stderr summary |
The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-hooks-claude-code) is the exhaustive source for every accepted field.
The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-experimental-hooks-claude-code) is the exhaustive source for every accepted field.
### What your hooks can do
@@ -98,7 +98,7 @@ The matcher subject is the tool name (`PreToolUse` / `PostToolUse`), the session
### Detached runs and disposal
The three emit points (`SessionStart`, `SubagentStart`, `SubagentStop`) run detached — no extension point awaits them. Each run chain is tracked, and disposing the bridge aborts still-running hook processes, then drains the continuations before the dispose resolves (`createDetachedRuns` in `dsh-hook-protocol`).
The three emit points (`SessionStart`, `SubagentStart`, `SubagentStop`) run detached — no extension point awaits them. Each run chain is tracked, and disposing the bridge aborts still-running hook processes, then drains the continuations before the dispose resolves (`createDetachedRuns` in `dsh-experimental-hook-protocol`).
### Design philosophy
@@ -130,7 +130,7 @@ Read these pages when the package-level contract is not enough. They move from t
- [Hook protocol library](../hook-protocol/README.md) — the shared hook rules this bridge applies.
- [Hook bridges Agent Note](../../../.agents/notes/archived/feature/2026-06-30-hook-bridges.md) — the bridge design, decision mapping, and deferred gaps.
- [Interception extension-points reference](../../../docs/tool-execution-pipeline.md) — the typed-Decision surface the bridge maps onto.
- [Generated configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-hooks-claude-code) — every accepted config field and its source declaration.
- [Generated configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-experimental-hooks-claude-code) — every accepted config field and its source declaration.
-----
@@ -3,13 +3,13 @@ description: "在 agent 运行期间使用你现有的 Claude Code hooks.json
kind: "package-reference"
---
# @deepseek-ai/dsh-hooks-claude-code
# @deepseek-ai/dsh-experimental-hooks-claude-code
[English](README.md) | 中文
## 概述
`dsh-hooks-claude-code` 在 agent(智能体)运行期间执行你现有 Claude Code `hooks.json` 或 settings 文件中的 command 钩子,无需重写。受支持的钩子会在会话、提示词、工具、停止或 subagent 到达对应时刻时运行。它们可以带模型可见的原因阻塞提示词或工具调用、添加对话上下文,或强制模型再执行一个轮次。需要在 harness 中复用 Claude Code command 钩子时选择本包;没有 Claude Code 对应物的行为应使用原生插件。
`dsh-experimental-hooks-claude-code` 在 agent(智能体)运行期间执行你现有 Claude Code `hooks.json` 或 settings 文件中的 command 钩子,无需重写。受支持的钩子会在会话、提示词、工具、停止或 subagent 到达对应时刻时运行。它们可以带模型可见的原因阻塞提示词或工具调用、添加对话上下文,或强制模型再执行一个轮次。需要在 harness 中复用 Claude Code command 钩子时选择本包;没有 Claude Code 对应物的行为应使用原生插件。
## 目录
@@ -36,7 +36,7 @@ kind: "package-reference"
### 最小配置
```yaml
- name: '@deepseek-ai/dsh-hooks-claude-code'
- name: '@deepseek-ai/dsh-experimental-hooks-claude-code'
config:
configPath: ./.claude/hooks.json
pluginRoot: ./.claude/plugins/my-plugin
@@ -51,7 +51,7 @@ kind: "package-reference"
| `defaultTimeoutMs` | `600,000` | hook 未设置时的每 hook 超时(即 Claude Code 默认值) |
| `stderrSummaryMaxChars` | `500` | 持久化 `hook/result` stderr 摘要的字符上限 |
生成的[配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-hooks-claude-code)是每个受支持字段的穷尽式真源。
生成的[配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-experimental-hooks-claude-code)是每个受支持字段的穷尽式真源。
### 你的钩子能做什么
@@ -98,7 +98,7 @@ matcher subject 是工具名称(`PreToolUse`/`PostToolUse`)、会话源(
### 脱离运行与释放
三个 emit 点(`SessionStart`、`SubagentStart`、`SubagentStop`)以脱离方式运行——没有扩展点等待它们。每条运行链都会被跟踪,对桥接执行 dispose(资源释放)时会中止仍在运行的 hook 进程,并在 dispose 完成前排空 continuation(`createDetachedRuns`,位于 `dsh-hook-protocol`)。
三个 emit 点(`SessionStart`、`SubagentStart`、`SubagentStop`)以脱离方式运行——没有扩展点等待它们。每条运行链都会被跟踪,对桥接执行 dispose(资源释放)时会中止仍在运行的 hook 进程,并在 dispose 完成前排空 continuation(`createDetachedRuns`,位于 `dsh-experimental-hook-protocol`)。
### 设计理念
@@ -130,7 +130,7 @@ matcher subject 是工具名称(`PreToolUse`/`PostToolUse`)、会话源(
- [hook 协议库](../hook-protocol/README.zh.md)——本桥接应用的共享钩子规则。
- [钩子桥接 Agent Note](../../../.agents/notes/archived/feature/2026-06-30-hook-bridges.md)——桥接设计、决策映射与延期缺口。
- [拦截扩展点 参考](../../../docs/tool-execution-pipeline.zh.md)——桥接所映射的类型化 Decision 接口面。
- [生成的配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-hooks-claude-code)——每个受支持配置字段及其源声明。
- [生成的配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-experimental-hooks-claude-code)——每个受支持配置字段及其源声明。
-----
@@ -1,5 +1,5 @@
{
"name": "@deepseek-ai/dsh-hooks-claude-code",
"name": "@deepseek-ai/dsh-experimental-hooks-claude-code",
"description": "Bridge plugin: run a Claude Code hooks.json / settings hook config on the DeepSeek Harness interception seams",
"version": "0.2.1-alpha.1",
"publishConfig": {
@@ -8,7 +8,7 @@
"repository": {
"type": "git",
"url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
"directory": "packages/hooks/hooks-claude-code"
"directory": "packages/experimental/hooks-claude-code"
},
"type": "module",
"main": "lib/index.js",
@@ -31,7 +31,7 @@
},
"peerDependencies": {
"@deepseek-ai/dsh-agent": "workspace:*",
"@deepseek-ai/dsh-hook-protocol": "workspace:*",
"@deepseek-ai/dsh-experimental-hook-protocol": "workspace:*",
"@deepseek-ai/dsh-llm": "workspace:*",
"@deepseek-ai/dsh-session": "workspace:*",
"@deepseek-ai/dsh-subagent": "workspace:*",
@@ -47,7 +47,7 @@
"@deepseek-ai/dsh-shell": "workspace:*",
"@deepseek-ai/dsh-bash-local": "workspace:*",
"@deepseek-ai/dsh-subprocess-local": "workspace:*",
"@deepseek-ai/dsh-hook-protocol": "workspace:*",
"@deepseek-ai/dsh-experimental-hook-protocol": "workspace:*",
"@deepseek-ai/dsh-llm": "workspace:*",
"@deepseek-ai/dsh-session": "workspace:*",
"@deepseek-ai/dsh-session-persistence-jsonl": "workspace:*",
Loaded 100 of 259 files, more files were not shown because too many files have changed in this diff. Show more