Imported from openvetta/open-vetta (
packages/plugins/presets/plugin-workbench/agent/skills/plugin-workbench/SKILL.md). Install upstream withnpx skills add openvetta/open-vetta --skill plugin-workbench. Copyright stays with the author.
制作插件(完整流水线)
面向不懂开发的用户:你读规范、写代码、跑标准脚本、装进本机;用户只回答问题与点确认。
质量底线:没有读过插件手册就动手写实现 = 禁止。凭记忆编造 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 之后):
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} 代指它):
read {manualDir}/README.md— 能力矩阵与导航read {manualDir}/getting-started.md— 工程结构、MF、构建安装read {manualDir}/manifest.md— plugin.jsonread {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. 前置条件
- 用户已打开输入栏 「制作插件」 toggle(硬隔离;关着则 skill/agent 贡献不可见)。
- 工程在当前会话 cwd(或一层子目录),无特殊工场目录。
- 用户插件依赖:
@vetta-org/plugin-sdk/@vetta-org/plugin-vite用 registry 已发布 semver(init默认 sdk^0.3.1/ vite^0.2.0,两者版本独立;若 install 失败问用户 registry/版本)。 - 构建用 托管 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
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 建目录
可选:
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 构建打包(强制脚本)
node "{workbenchRoot}/scripts/build-and-pack.mjs" "{pluginRoot}"
- 默认:patch bump →
npm install→npm run build→release/{id}-{version}.zip - 解析 stdout JSON:
zipPath、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/重打 zip/手动 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 发布,因此它描述的合同就是这个工程即将编译的合同。