開發 DSH 插件標準
本技能是開發 DeepSeek Harness(DSH)插件的唯一標準:它把 DSH 官方文檔中分散在教程、參考手冊與生成目錄裡的約定,收斂為可執行的工作流、硬規則與檢查清單。DSH 的一切都是插件——模型適配器、工具註冊表、會話日誌乃至 agent loop 本身——因此按本技能行事,就是在按 DSH 自己的架構方式擴展它。
適用範圍
- 倉庫內、文件式的 DSH 插件開發:編寫插件包、註冊 cordis.yml 行、patch overlay、開發工具、接模型、打包安裝。
- DSH monorepo 內的 workspace 包開發(packages//)也屬本技能(references/workspace-package.md)。
- 本技能不覆蓋:會話內動態插件(cordis_define/cordis_run 流)與 agent preset 組合編輯——這兩類由各部署的專項技能或官方工具覆蓋。
硬規則(任何場景都必須遵守)
- 介面以生成參考為準。 服務名、公開方法、事件簽名、ctx 鍵均以倉庫自動生成的子系統頁面與 TypeScript 介面為準;不要憑服務名、範例或舊程式碼推斷完整 API,也不要維護另一份靜態清單。
- 所有貢獻都是副作用。 透過 ctx 做的一切註冊(事件監聽、工具、適配器、ctx.effect)在插件卸載時自動撤銷;不要在模組作用域建立程序級/頁面級副作用;不返回 disposer 的第三方訂閱要主動查清清理機制。
- waterfall 監聽器必須呼叫 next()。 不呼叫 next() 即有意短路下游(用於攔截/閘道),不是可選項。
- 失敗要響亮。 apply 拋異常則程序終止;配置驗證失敗則明確報錯;schema 應表達自身完備的約束,不要在執行時悄悄吞掉錯誤。
- 必需依賴用 inject 宣告,可選依賴用 ctx.get() 判空。 不要用 inject 規避 undefined 檢查;也不要直接存取未宣告注入的 ctx.xxx——未宣告的服務經服務解析器求值可能得到 undefined。
- 配置一律 Schemastery。 匯出 interface Config 與同名 Schema,預設值寫在 schema 裡;不匯出普通物件充當 Config;凡不同部署可能改值的參數都必須進配置。
- 工具 execute 返回規範 JSON 值,不返回內容塊。 面向人類的文字放 output.render;部署策略/鉤子不要內建進工具體。
- 模型可見即已記錄。 新增任何模型可見輸入,都要落在會話日誌可重建的機制裡(新增持久事件或經 agent.inject()),並有執行時不變式斷言。
- npm 設定面板優先
ctx.connection.rpc。 瀏覽器半設定面板調主程序方法,優先走 Connection RPC(ctx.connection.rpc.handle+ctx.connection.rpc.call),樣板見 references/connection-rpc.md。禁止裸@Remote、手寫 typert manifest、createRequire掛 harness 原始碼。完整 Typert generator 產出並經package.json匯出./typert+./remote、由ctx.remote.$mount()消費的路徑仍然合法。
標準工作流
場景 A:新建一個插件
- 確定插件要貢獻什麼(服務?工具?監聽?),用 references/seams.md 的「新行為的歸屬位置」表選擇機制。
- 建立 src/.ts,匯出 name、inject(可選)、apply(ctx, config?)。先寫函數型態;要對外提供服務時再換 Service 類別型態。
- 本地開發迴路(原始碼 checkout):
mkdir -p scratch-plugin/src
# scratch-plugin/cordis.yml —— patch overlay;插件路徑必須是絕對路徑
- insert:
- id: hello
name: '/absolute/path/to/deepseek-harness/scratch-plugin/src/my-plugin.ts'
pnpm dsh web --patch ./scratch-plugin/cordis.yml # 打開 http://127.0.0.1:3080
- 驗證載入與卸載:啟動日誌出現、停用時資源確實清理(references/plugin-anatomy.md)。
場景 B:給模型加一個工具
- inject: ['tools'],用 defineTool 定義(name/description/parameters/output/execute)。
- 按 references/tools.md 的 execute 約定實現:schema DSL 宣告參數與輸出、execute 返回規範值、遵守 exec.signal、可選 presentationMeta/UI 卡片。
- 需要策略時掛 tools/* 事件(pre-execute/guard/execute/post-execute/result),不要把策略寫死在工具體裡(權限門禁範例見 references/plugin-forms.md)。
- 重啟後讓模型實際呼叫驗證。
場景 C:可替換能力(多種提供方)
- 按 references/three-roles.md 拆 Definition / Provider / Consumer 三個包(按需合併角色,不要預防性拆分)。
- Definition 擁有 Request/Result 型別與抽象 Service;Provider 實現;Consumer 暴露為工具或服務消費方。
- 在 cordis.yml 只列 Provider 與 Consumer 行;換提供方只換一行。
場景 D:接入新的模型提供方
- 繼承 LlmAdapter 實現 stream(),按 StreamChunk 協定輸出分片;錯誤用帶穩定 code 的 LlmError(或在帶內以 finish { kind: 'error' | 'aborted' } 結束);每個 HTTP 請求合併 attributionHeaders() 並傳遞 signal。
- ctx.llm.registerAdapter([''], adapter);可選覆寫 resolveModel()/listModels()。
- 在組合中配置 agent-loop 的 provider/model 驗證。詳見 references/llm-adapter.md(含 7 條協定義務)。
場景 E:打包與安裝交付
- 建組合包:package.json 宣告 dsh.bundle(指向 cordis.patch.yml),patch 行按包名引用插件;僅供 import 的庫包不宣告 dsh.bundle。
- 安裝:dsh plugin --profile add ;先 dsh --profile --dump-config 驗證層,再啟動。
- 記住層順序與整行替換語義(references/packaging.md)。
場景 F:在 DSH monorepo 內新建包
按 references/workspace-package.md 的逐檔案清單執行:建立包(package.json 不變式/tsconfig/src/README)→ 根配置註冊 → 包拓撲與命名(角色詞表)→ README Model Experience 結構 → 驗證命令。
決策速查
| 我要…… | 機制 | 詳情 |
|---|---|---|
| 向其他插件公開能力 | Service(類別型態) | references/services.md |
| 消費已有能力 | inject 或 ctx.get() | references/services.md |
| 插件間通信 / 擴充點 | ctx.on / ctx.emit 等事件(五種分發模式) | references/events.md |
| 讓使用者可配置 | Config + Schemastery | references/config.md |
| 給模型加能力 | defineTool → ctx.tools.register(或原始 JSON Schema) | references/tools.md |
| 接新模型提供方 | LlmAdapter + ctx.llm.registerAdapter | references/llm-adapter.md |
| 拆可替換能力 | 三種角色(Definition/Provider/Consumer) | references/three-roles.md |
| 分發插件 | 組合包 + profile | references/packaging.md |
| 查內建服務 / 歸屬位置 | seam 目錄、架構映射 | references/seams.md |
| 作用域/服務儲存/Fiber API | ctx.extend/isolate/provide/mixin、fiber.* | references/context-api.md |
| 鉤子 / UI / 面板 / 協定橋插件 | 五種擴充型態 + 功能→機制映射 | references/plugin-forms.md |
| 瀏覽器半面板調主程序服務 | ctx.connection.rpc.handle/call,endpoint + 信封 | references/connection-rpc.md |
| 在倉庫內新建包 / 命名 | workspace 包清單 + 角色詞表 | references/workspace-package.md |
完成前檢查清單
- 介面查過生成參考(服務/事件/ctx 鍵均以生成為準),沒有憑名字猜 API。
- 所有註冊走 ctx(事件/工具/適配器/effect),卸載可清理;順序敏感的清理放在同一個 ctx.effect 裡。
- 必需依賴注入宣告正確;可選依賴有 undefined 處理。
- 有配置的插件:Config 用 Schemastery,預設值進 schema,無效配置在載入時響亮失敗。
- 有工具:execute 返回規範 JSON 值;render 負責人類可讀;策略走 tools/* 事件;遵守 exec.signal;並發安全宣告了 isConcurrencySafe(未宣告 → exclusive)。
- 有 waterfall 監聽:呼叫並返回 next()(除非有意短路)。
- 有 LLM 適配器:StreamChunk 協定完整(塊配對、index 按首次出現、usage 在 finish 前、arguments 全程原始 JSON 字串);錯誤走兩條合法路徑之一;不支援的欄位拋 UNSUPPORTED;需要原生回放時發 finish.replayState;傳了 attributionHeaders 與 signal。
- 組合行與層序正確;新增行在 --dump-config 中可見;HMR/重啟後無殘留註冊。
- 若模型可見內容變化:落在日誌可重建的機制內。
- 瀏覽器半設定面板:優先
ctx.connection.rpc.handle/call;禁止裸@Remote、手寫 typert manifest、createRequire掛 harness 原始碼;完整 Typert generator +./typert+./remote產物仍合法。 - 新建 workspace 包:package.json 不變式、恰一個 aggregate、命名符合角色詞表、README 有 Model Experience 結構,且 constraints/typecheck/lint/build/hygiene 全綠。
參考文件(按需載入,不要一次全讀)
完整索引與「何時讀」對照表見 references/README.md。
- references/plugin-anatomy.md —— 寫/改插件、處理生命週期或 HMR 時讀
- references/services.md —— 定義或消費服務、注入依賴時讀
- references/events.md —— 用事件通信、監聽擴充點時讀
- references/config.md —— 讓插件可配置時讀
- references/context-api.md —— 用作用域、服務儲存或 Fiber API 時讀
- references/three-roles.md —— 拆分可替換能力時讀
- references/tools.md —— 開發模型工具時讀
- references/llm-adapter.md —— 接入新模型提供方時讀
- references/plugin-forms.md —— 寫鉤子/UI/協定橋插件時讀
- references/connection-rpc.md —— npm 設定面板要調主程序方法時讀;遇到裸
@Remote/ 手寫 manifest /createRequire原始碼橋時也讀 - references/packaging.md —— 打包安裝、交付 plugin 時讀
- references/workspace-package.md —— 在 monorepo 內新建包時讀
- references/seams.md —— 查內建服務、歸屬位置或架構映射時讀
驗證
- 格式自檢:name 為 kebab-case 且與目錄名一致;description 非空且簡潔(本技能控制在 500 字符內);正文用標準 Markdown;所有引用的 references 檔案真實存在。
- 目錄命名:本技能名(name)為 dsh-plugin-dev,與託管倉庫名 dsh-plugin-dev-skills 不同——克隆/解壓後必須把資料夾命名為 dsh-plugin-dev(與 name 一致),否則按目錄名尋址的載入器可能發現不了本技能。
- 有 skills-ref CLI 的環境可執行:skills-ref validate ./dsh-plugin-dev
- 觸發迴歸:修改 description 後執行 evals/trigger-queries.json 評測集(方法見倉庫 evals/README.md)。
- 行為驗證:按場景 A 走通一個最小插件(載入日誌 + 卸載清理),再按場景 B 走通一個 greet 工具。