# Dsh Plugin Dev

> 开发 DeepSeek Harness (DSH) 插件与 agent preset 的完整规范与避坑指南。当需要为 DSH 编写新插件、新增 agent preset、给 DSH 增加工具/命令/子代理/设置项/WebUI 组件，或排查 DSH 插件导致崩溃或加载失败的问题时使用。涵盖 Cordis 插件契约（name/inject/apply）、host 与 agent 双平面、client 打包格式（window.__ModuleLoader__）、settings 白名单、cordis.patch.yml 的 insert 格式、dsh.client.inject、UI 原语、部署流程等易崩溃陷阱。

- **Type:** Skill
- **Install:** `agentstack add skill-abab996-dsh-plugin-dev-dsh-plugin-dev`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [abab996](https://agentstack.voostack.com/s/abab996)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [abab996](https://github.com/abab996)
- **Source:** https://github.com/abab996/dsh-plugin-dev

## Install

```sh
agentstack add skill-abab996-dsh-plugin-dev-dsh-plugin-dev
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# DSH 插件开发规范

DeepSeek Harness 是插件化的：几乎所有能力都是 npm 包插件，遵循 Cordis 契约。新增功能 = 新增插件包（+ agent preset + 配置），不改 DSH 核心源码。

## 三个核心事实

1. 插件契约：每个插件包导出 { name, inject, apply }；inject 声明依赖的 Cordis 服务名，apply(ctx) 里注册能力。伴生 invariant 用 ctx.invariants.register(PACKAGE_NAME, install) 声明包所有权。
2. 双平面：
   - HOST 平面（三个 bundle 包 dsh-base / dsh-web-app / dsh-headless 各自的 cordis.patch.yml，经 package.json 的 dsh.bundle.patch 声明，再加 profile 的 cordis.patch.yml / $DSH_HOME/cordis.patch.yml / --patch）：注册表、沙箱、审批、持久化、模型路由、客户端 shell——跨会话共享。注意：没有名为 base.cordis.yml / web.cordis.yml 的文件，那是 shipped preset 注释里的概念指代。
   - AGENT PRESET 平面（agent.cordis.yml）：某个会话专属的工具、人设、提示词段、子代理工具——按会话挂载。
3. 新增「模式」= 新增 agent preset 目录（/agent.cordis.yml + /preset.yml），放在 ~/.dsh/.agent-presets//；preset 列表自动发现它。

## 崩溃陷阱（违反必崩，逐条遵守）

### 1. client 插件必须打成 window.__ModuleLoader__ 手接格式
浏览器端插件不是裸 ESM。必须用 rolldown 打成：

    window.__ModuleLoader__.load({ id: "pkg", factory: (require) => { /* ... */ return module.exports } })

把 react 与所有 @deepseek-ai/* 设为 external（交给 loader 的 require）。直接用 tsdown 打出的 .mjs 会让 web 端崩溃。用 scripts/build-client.mjs（已含正确 external + handoff 包装）。

### 2. 新 settings namespace 必须加入白名单
DSH rc.6 的 dsh-host-apiproxy 只对 WEB_SETTINGS_NAMESPACES 白名单里的 namespace 开放给客户端；否则客户端 settingsScope.bind({namespace}) 返回 settings-not-exposed（设置页读不到）。把 namespace 名追加进 node_modules/@deepseek-ai/dsh-host-apiproxy/lib/index.js 的 WEB_SETTINGS_NAMESPACES（见 scripts/deploy.ps1 里的 patch 步骤）。

### 3. cordis.patch.yml 新增插件行用 - insert: 格式

    - insert:
        - id: omd
          name: dsh-omd
        - id: omd-client
          name: dsh-omd-client

不是裸的顶层 - id: ... / name: ... 行。

### 4. dsh.client.inject 必须列全 apply 用到的服务提供包
客户端 apply(ctx) 里用到的每个服务（如 ctx.settingsScope、ctx.slots、UI 原语）都要把它的提供包写进 dsh.client.inject，否则加载顺序错、服务未就绪即崩。例如用了 settings 就加 @deepseek-ai/dsh-client-ui-settings，用了 UI 就加 @deepseek-ai/dsh-client-ui-primitives。

### 5. WebUI 用 DSH 原语，不要手搓 div/input
一律从 @deepseek-ai/dsh-client-ui-primitives 引入 Menu / Button / Input / DisclosureRow / Pill 等（走 --dsw-* token，自动匹配主题）。权限选择器（Read Only / Workspace Write / Full access）用的就是 Menu + Button，做同类下拉直接复用这两个。手写  会与 DSH UI 格格不入。

### 6. 类型与值导入必须分开
用 import type { X } 导类型、import { y } 导值。tsdown/rolldown 对「把类型当值导入」报 MISSING_EXPORT。tsconfig 开 verbatimModuleSyntax: true 让 tsc 先抓住。

### 7. 注册必须唯一（重复即抛错）
同作用域层里 systemPrompt.section 的 name、settings.register 的 namespace、commands.register 的 name 都必须唯一。host 插件与 agent 插件不要注册同名 section。

### 8. 部署用本地 file: 依赖（junction），重建即生效，无需卸载
npm install  在 profile 里生成 junction（软链）指向源码目录；改代码后只需重新构建（软链自动读到新产物），不需要 uninstall/reinstall。

## 开发流程（每步都要做）

1. 先镜像现有插件：写之前必读 node_modules/@deepseek-ai//lib/types/*.d.ts（编译后的类型即权威 API）+ 其 agent.cordis.yml / package.json。绝不凭空猜 API。
2. 写代码：遵守上面的陷阱规则。
3. 类型检查：npx tsc --noEmit -p tsconfig.check.json（strict + verbatimModuleSyntax）。
4. 编译：host/agent 包 npx tsdown；client 包 npm run build（= tsdown + node build-client.mjs）。
5. 冒烟测试：用 mock ctx 调 apply(mockCtx)，断言注册了正确的 settings/section/command/service/slot，且不抛错。
6. 部署：见 references/deployment.md。
7. 重启 host 端到端验证（重启会中断当前会话，需用户执行）。

## 参考
- 架构、服务 API、preset 格式、slot 名：references/architecture.md
- 部署步骤、patch/白名单/junction 细节：references/deployment.md
- 高级注意事项（子代理 capability、isolate 规则、inject/ctx.get、session projection、complete 段、--dump-config）：references/gotchas.md
- **对照源码的事实纠偏与增量（必读）**：references/spec-supplement.md —— Cordis 精确 Context API（无 ctx.scope/name/parent/dispose/baseDir，有 isolate/effect/fiber/baseUrl）、inject vs ctx.get、ctx.effect 生命周期、事件 dispatch 模式、单文件工具插件模式（apply(ctx, config) + Config + defineTool）、完整 slot 清单（single/list/keyed/chain + root/session/session-maybe）、host 组合物理结构、settings/schemastery 完整 API、agent presets roster（copy/standingKeyFor）、动态插件（cordis_* 工具集）、Client→Host RPC（harness.handle/host.call）。
- 完整规范（极致详细版，含 omd/vision-read 逐文件解读与端到端验收）：工作区根 `DSH插件开发规范.md`
- 可复用脚本：scripts/build-client.mjs（client 手接打包）、scripts/deploy.ps1（构建+装包+patch+白名单+preset）

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [abab996](https://github.com/abab996)
- **Source:** [abab996/dsh-plugin-dev](https://github.com/abab996/dsh-plugin-dev)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-abab996-dsh-plugin-dev-dsh-plugin-dev
- Seller: https://agentstack.voostack.com/s/abab996
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
