---
name: plugin-workbench
description: >
  Create, implement, build, pack, install, reload, and manage Vetta desktop plugins
  for non-developers. Use whenever the user wants a Vetta plugin, plugin scaffolding,
  apply a `.vettapkg` package to Vetta, edit plugin.json name/guidingWords, or debug plugin load/install.
  Requires the Plugin Workbench input-bar toggle (hard isolation). The plugin handbook ships
  inside the project's own @vetta-org/plugin-sdk; locate it with the bundled CLI's docs command.
---

# 制作插件（完整流水线）

面向**不懂开发的用户**：你读规范、写代码、跑标准脚本、装进本机；用户只回答问题与点确认。

**质量底线**：没有读过插件手册就动手写实现 = 禁止。凭记忆编造 SDK API 很容易装上不能用。

---

## 0. 解析工作台根目录（先做）

```
workbenchRoot = listPlugins() 中 id === "plugin-workbench" 的 rootPath
```

若拿不到：用宿主 `plugins.query` list，或面板/会话上下文；失败则 AskUserQuestion 请用户确认 App 已启用系统插件「制作插件」。

| 资源 | 绝对路径 |
| --- | --- |
| **插件 CLI（内置）** | `{workbenchRoot}/agent/cli/vetta-plugin-cli.js` |
| 文档索引（本 skill 附件） | 本 skill 目录 `references/doc-index.md` |
| 实现模板摘要 | 本 skill 目录 `references/templates.md` |
| 标准脚本 | `{workbenchRoot}/scripts/*.mjs` |

**手册不在工作台里**，它随 `@vetta-org/plugin-sdk` 装进**被编辑工程自己的** `node_modules`。
这是刻意的：那份手册与该工程实际编译的 SDK 版本一致，而随 App 发版的内嵌副本做不到。用内置
CLI 解析它的位置（工程 `npm install` 之后）：

```bash
node "{workbenchRoot}/agent/cli/vetta-plugin-cli.js" docs --json
```

返回 `manualDir`（手册目录绝对路径）、`entry`（README.md）、`sdkVersion`，以及当前命中的插件工程。
**不要硬编码 node_modules 路径**：工作区可能把依赖提升到上层，一仓多插件时各插件还可能钉不同版本。

---

## 1. 强制读文档（不可跳过）

用 **read 工具**打开文件（绝对路径），不要只 skim 本 skill。

### 1.1 每次创建或大改插件

先用上面的 `docs --json` 拿到 `manualDir`，然后（`{manualDir}` 代指它）：

1. `read {manualDir}/README.md` — 能力矩阵与导航  
2. `read {manualDir}/getting-started.md` — 工程结构、MF、构建安装  
3. `read {manualDir}/manifest.md` — plugin.json  
4. `read {manualDir}/permissions.md` — 权限清单  

工程若还没 `npm install`，`docs` 会明确告诉你先装 SDK——那一步本来也绕不过去，构建需要它。

### 1.2 按用户目标追加（实现前）

| 用户意图 | 必读 |
| --- | --- |
| 侧栏面板 / 活动 Tab | `ui-slots.md`（activity-tab） |
| 整页工作区视图 / 接管宿主页头 | `ui-slots.md`（workspace-view + setWorkspaceViewHeader） |
| 视图要随宿主侧边栏收缩自适应 | `ui-slots.md`（useSidebarState；沉浸式页头尤其需要） |
| 输入栏按钮 | `ui-slots.md`（input-action） |
| 新会话页摆素材 / 选完智能体的第一屏 | `ui-slots.md`（new-session-context） |
| 插件自带人设 / 团队 | `manifest.md`（贡献智能体与团队） |
| 文件预览 | `ui-slots.md`（file-preview + **notify 错误上报**）+ `styling-and-pitfalls.md`（**面板布局边界**） |
| 全局弹层 | `ui-slots.md`（global） |
| 任何可能失败的 IO/解析 | `ui-slots.md`（**notify**）+ `styling-and-pitfalls.md`（错误必须上报） |
| Agent 工具 / 读写文件 / 对话 | `conversation-and-agent.md` |
| 消息下方卡片 | `message-cards.md` |
| 插件自带 MCP | `mcp.md` |
| 样式 / 布局逃逸 / 不生效 / 缓存 | `styling-and-pitfalls.md`（含**面板类 slot 禁止 viewport fixed**） |
| 引导词 / 设置项 | `manifest.md` 对应章节 |

### 1.3 实现时

- API 名、权限、scope_use fail-closed、返回值形状 **以手册为准**。  
- 模板摘要见 `references/templates.md`，但细节冲突时以 `{manualDir}/*` 为准。  
- 不确定就再 read 对应章节，或 AskUserQuestion。

---

## 2. 前置条件

1. 用户已打开输入栏 **「制作插件」** toggle（硬隔离；关着则 skill/agent 贡献不可见）。  
2. 工程在**当前会话 cwd**（或一层子目录），无特殊工场目录。  
3. 用户插件依赖：`@vetta-org/plugin-sdk` / `@vetta-org/plugin-vite` 用 **registry 已发布 semver**（`init` 默认 sdk `^0.3.1` / vite `^0.2.0`，两者版本独立；若 install 失败问用户 registry/版本）。
4. 构建用 **托管 Node + npm**；标准脚本封装，禁止随意手搓另一套 pack（除非用户明确要求且你已读 getting-started 的打包约定）。

---

## 3. 禁止臆测（必须 AskUserQuestion 或等价确认）

| 项 | 原因 |
| --- | --- |
| 插件 `id` | 全局唯一，装后难改 |
| 展示名 `name` | 用户可见品牌 |
| `permissions` 列表 | 安全；对照 permissions.md 向用户解释再写入 |
| 要解决的问题 / MVP 范围 | 避免一次做全家桶 |
| 是否立即安装到本机 | 构建后是否引导用户在面板点「应用到 Vetta」 |
| 扩展点类型（用户没说时） | activity-tab / 工具 / 引导词 / 预览 / … |

---

## 4. 端到端流水线

### 4.1 澄清

AskUserQuestion 收齐 §3；对照 README 能力矩阵选定扩展点 → 列出要读的文档章节 → **先 read 再写代码**。

### 4.2 Scaffold

```bash
node "{workbenchRoot}/agent/cli/vetta-plugin-cli.js" init --id {id} --name "{name}" "{cwd}/{plugin-id}"
cd "{cwd}/{plugin-id}" && npm install
```

脚手架同时落一份 `AGENTS.md`（该读哪些手册、不可违反的几条）。**先读它**，它与本 skill 同源。

然后按文档改：

- `plugin.json`：permissions、guidingWords、agent、styles、moduleFederation…（`agent_mode` 已废弃，不要写，见 manifest.md）  
- `src/index.tsx`：register* / registerTool 等（遵守 styling 顶层 JSX 规则）  
- 需要 skill/prompt 时按 manifest 建目录  

可选：

```bash
node "{workbenchRoot}/scripts/check-manifest.mjs" "{pluginRoot}"
```

### 4.3 实现质量检查（自检清单）

对照已读文档确认：

- [ ] 每个用到的 API 都在 `permissions` 里声明  
- [ ] 会话页 UI / 工具都写了合理的 `scope_use`（fail-closed）  
- [ ] 工具 description 写清何时调用  
- [ ] 无 MF 顶层 JSX 陷阱  
- [ ] **样式：只用 Tailwind className；未手写业务 .css / 未用全局选择器**（`style.css` 仅 theme+utilities 入口，见 styling-and-pitfalls）  
- [ ] **面板布局：file-preview / activity-tab 内无 `fixed` 贴视口、无超高 z-index、无 portal 到 `document.body`**；面板内浮层用 `relative`+`absolute`；全局浮层用 `registerGlobalSlot`，Toast 用 `notify`（见 styling-and-pitfalls → 面板类 slot 布局边界）  
- [ ] 用户工程无 `workspace:*`  
- [ ] i18n：若要宿主渲染中文 label，按手册用 catalog / `%key%`（desktop 用户文案规范）  
- [ ] **错误可排查：所有可能失败的路径（读文件/解析/网络/外部库）在 catch 里调用 `ctx.ui.notify({ message, error })`**，禁止只写死「失败」文案、丢掉原始 error；`notify` 无需权限，有 `error` 时宿主 Toast 可一键复制堆栈（见 `ui-slots.md` → notify）  


### 4.3.5 热更新感知（改已装插件前必查）

改一个**已安装**的插件前，先 `plugins.query` → `get {id}` 看返回项有没有 `devWatch` 字段：

- **`devWatch` 存在（热更新已开启）**：改完工程源码或 `plugin.json` 即结束——vite watch 构建成功后自动重载；dev 会话内新增 permissions/commands 也会自动放行。**禁止**再走 4.4/4.5 或 reload。若 `devWatch.status === "error"`，提示用户看面板错误或拨一下热更新开关。仅当用户明确要**持久**写入注册表（关热更新/重启后仍生效）时，才用 `workbench_offer_reinstall` 让用户点卡片「重新安装」。
- **`devWatch` 不存在**：走 4.4→4.5 常规流程（构建打包后引导用户在面板点「应用到 Vetta」）。

### 4.4 构建打包（强制脚本）

```bash
node "{workbenchRoot}/scripts/build-and-pack.mjs" "{pluginRoot}"
```

- 默认：patch bump → `npm install` → `npm run build` → `release/{id}-{version}.vettapkg`
- 解析 stdout JSON：`packagePath`、`id`、`version`
- 失败：读 stderr，按 getting-started / styling 修；缺依赖或 registry 问题 → AskUserQuestion

### 4.5 安装到本机 Vetta（引导用户在面板点击，不要弹确认）

打包完成后**不要调用** `plugins.manage` 的 `install-from-path`（会弹确认 sheet，工作台流程已废弃此路径）。改为告知用户：

> 打开右侧活动面板「制作插件」→ 对应工程卡片 → 点 **「应用到 Vetta」**（面板安装一次完成授权 + 启用，无确认弹窗）。

- 应用成功后面板会**默认开启「热更新」**：之后你改源码即自动构建+重载（§4.3.5），无需再次应用。用户可手动关掉。  
- 再次应用（热更新被关掉时）：build-and-pack 后再请用户点「应用到 Vetta」（应用后会重新默认开启热更新）。  
- 不可覆盖系统插件 id。

### 4.6 改 name / guidingWords

只改 **工程源码** `plugin.json`，再 4.4 → 4.5。禁止改 `~/.vetta/plugins/...` 已装目录当真相源。

### 4.7 卸载 / 重载 / 重新安装

- `plugins.manage`：`uninstall` / `reload`（系统插件不可卸）。
- **重新安装**（权限/命令等安装态变更）：工具 `workbench_offer_reinstall` 出消息卡，或面板「重新安装」——**不要** `install-from-path`。

---

## 5. 运维面板

Activity Tab「制作插件」（同样受 toggle 硬隔离）：扫描 cwd、构建、应用、卸载、重载、改 name/引导词。与对话同一规则与同一脚本。

每张工程卡片有 **「热更新」开关（已安装后默认开）**：宿主把插件 dev 链接到工程目录并常驻 `vetta-plugin dev`；React / CSS 走 HMR，其余资源定向重载（无需 bump/重打包/手动 reload）。适合迭代调试。

已安装时还有 **「重新安装」**（与消息卡按钮同路径）：强制 build-and-pack → 把权限/命令**持久写入注册表** → **刷新整个 Vetta 窗口**。日常改代码 / 改 plugin.json 靠热更新即可（dev 会话内权限声明自动放行）；重新安装用于落盘授权或热更新异常时兜底。首次安装仍用「应用到 Vetta」。

---

## 6. 排错

| 现象 | 处理 |
| --- | --- |
| Skill/工具不可见 | 是否打开工作台 toggle；系统插件是否启用 |
| npm install 失败 | registry、网络、sdk 版本；AskUserQuestion |
| 构建失败 | 读完整错误；对照 getting-started / 依赖版本 |
| 装上无效果 | permissions 是否授予；scope_use；插件 enabled；reload + version |
| 反复改 UI 调试 | 已安装工程默认开热更新：保存即自动构建+重载（见 §5）；若被关掉可再打开 |
| UI 不出现 | ui-slots 权限与 scope_use；activity tab 是否 attach |
| 样式/缓存怪 | styling-and-pitfalls；bump version |
| 运行时「失败」但不知原因 | 插件是否 `notify({ message, error })`？让用户右下角 Toast 点「复制堆栈」贴给你；没有则补 notify 后热更新再复现 |
| 只显示红字无堆栈 | 实现遗漏：catch 必须把原始 `error` 传给 `ctx.ui.notify`（见 §4.3 与 ui-slots notify） |

---

## 7. 边界

- 不发布插件市场、不拖拽式 no-code 搭建  
- 不保证任意原生/C++ 依赖在托管 Node 下可构建  
- 细粒度权限仍可在设置页调整  
- 用户自建插件默认 **不要** 开 hardIsolation（除非用户明确要求模式开关）

---

## 8. 附件

- `references/doc-index.md` — 手册路径与阅读表  
- `references/templates.md` — 常见扩展点代码起点  

**再次强调**：实现前先 `docs --json` 拿到 `manualDir`，再 `read` 其中对应的章节。手册随工程自己的
`@vetta-org/plugin-sdk` 发布，因此它描述的合同就是这个工程即将编译的合同。
