Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion skills/make-dsh-plugin/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,14 @@ make-skill)见 `references/entry-contract.md` 对应小节——不要发明
运行时的职责(`@deepseek-ai/*`、`cordis`——profile pnpm 闭包注入,勿声明)。
在 `ctx.effect()`/`ctx.on()` 内注册,disable 时清理。

**检查点**:entry 可解析;工具已注册;inject 声明完整。
**工具的 `output` 必须声明 `{ schema, render }`**(`presentationMeta` 可选)——
缺 `render` 在 boot 挂载时抛 `tool ... must declare output { schema, render, presentationMeta? }`
并导致整棵插件树加载失败(web 起不来)。写法:
`output: { schema: {...}, render: (_args, value) => [{ type: 'text', text: JSON.stringify(value, null, 2) }] }`。
`defineTool` 来自 `@deepseek-ai/dsh-tools`(公共 npm 不存在、仅运行时闭包可解析)——本地独立验证
用原生 ToolDefinition 对象更稳(`ctx.tools.register` 原生接受,参照 `dsh-chatdata-plugin`)。

**检查点**:entry 可解析;工具已注册且 `output` 含 `schema + render`;inject 声明完整。

## Step 4:Client half(可选)——自渲染

Expand Down
15 changes: 13 additions & 2 deletions skills/make-dsh-plugin/references/entry-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,24 @@ export function apply(ctx) {
name: 'my_tool',
description: 'What it does.',
parameters: { type: 'object', properties: {} },
output: { schema: { type: 'string' } },
execute: async () => 'result',
output: {
schema: { type: 'object' },
render: (_args, value) => [{ type: 'text', text: JSON.stringify(value, null, 2) }],
},
execute: async () => ({ ok: true }),
}))
}
```

- 能力上限是完整 Cordis——事件(`ctx.on`)、服务(`ctx.provide`)、命令、system prompt、TUI,无需声明。
- **`output` 必须声明 `{ schema, render }`(`presentationMeta` 可选)**:运行时 `ctx.tools.register`
强制校验,缺 `render` 在 boot 挂载时抛 `tool "<name>" must declare output { schema, render, presentationMeta? }`
并导致整棵插件树加载失败(`plugin tree failed to load`,web 起不来)。`schema` 须通过官方
`assertSupportedJsonSchema`(纯 JSON Schema 可用);`render(args, value)` 返回渲染块数组
(`[{ type: 'text', text: ... }]`)。此坑曾因示例漏写 `render` 真实踩到(见 gotchas §6)。
- **`defineTool` 仅运行时闭包可解析**:`@deepseek-ai/dsh-tools` 不在公共 npm,本地独立 `import` 失败——
本地验证时直接注册原生 ToolDefinition 对象(`ctx.tools.register` 原生接受),参照 `dsh-chatdata-plugin`;
正式分发仍由运行时经闭包注入解析。
- **依赖解析**:entry 可 import 官方包(`@deepseek-ai/*`、`cordis`),官方运行时经 profile pnpm 闭包注入(`$DSH_HOME/profiles/node_modules` flat fallback);**不要声明这些依赖**(声明了公共 npm 解析不到反而失败)。
- **注册是 effect**:`ctx.tools.register` 返回 disposer,用 `ctx.effect()`/`ctx.on()` 持有生命周期,disable 时清理。

Expand Down
19 changes: 19 additions & 0 deletions skills/make-dsh-plugin/references/gotchas.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,22 @@ bundle 插件的**启停覆盖写 profile 层**,不要写进 bundle 包内层
- **client 经 `__ModuleLoader__.load` 注册**:0811 client-modules 只扫描声明 `dsh.client` 的包,client bundle 必须 `__ModuleLoader__.load({id, factory})`——否则报 `loaded without registering`。
- **严格注入**:`ctx.get` 未在 `inject` 声明的服务 → `cannot get property without inject`,apply 开头即抛、整个 effect 不注册(路由全 fallback 成 SPA 主页)。
- **工具 schema DSL 违规在挂载时暴露**:CLI enable 只校验名称,`defineTool` value-schema 违规在 web boot/面板 enable(reconcile)时暴露——发现后重启 web 确认日志。

## 6. 工具 `output` 缺 `render` → boot 硬失败(实测 2026-08-31)

ToolDefinition 的 `output` 只写 `schema` 不写 `render`(`presentationMeta` 可选)时,boot 挂载即抛:

```
TypeError: tool "<name>" must declare output { schema, render, presentationMeta? }
```

→ `plugin tree failed to load` → **web 启动失败**。要点:

- **CLI enable 查不出、mock ctx 独立验证也查不出**(假 ctx 不跑运行时校验)——只有真实挂载
冒烟(装 → 挂载 → boot log 干净)能抓到;本地快速自证可用官方
`assertSupportedJsonSchema`(从已安装 dsh 的 `@deepseek-ai/dsh-tools` import)+ 按
`register()` 源码复刻 output 条件校验。
- 正确写法:`output: { schema: {...}, render: (_args, value) => [{ type: 'text', text: JSON.stringify(value, null, 2) }] }`
(对照本部署 `dsh-chatdata-plugin`)。
- 环境事实:`entry-contract.md` 的示例曾漏写 `render`(已修)——照旧示例原样抄会复现此坑;
这也是「挂载失败排查顺序」(§3)之外的另一个 boot 失败入口。