news 2026/9/20 21:00:05

OpenDesign 插件测试夹具解析:sample-plugin 的双文件清单结构与 Phase 1 安装闭环

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OpenDesign 插件测试夹具解析:sample-plugin 的双文件清单结构与 Phase 1 安装闭环
  • AI 应用
  • 人工智能
  • AI 技能
  • 设计系统
  • 媒体生成

【免费下载链接】open-design

🎨 Best DeepSeek Harness Design Plugin. The open-source Claude Design alternative. 🖥️ Local-first desktop app. 🖼️ Your coding agent becomes the design engine: prototypes, landing pages, dashboards, slides, images & video — real files, HTML/PDF/PPTX/MP4 export. 🤖 Claude Code / Codex / Cursor / DeepSeek Harness / OpenCode & 20+ CLIs via BYOK.

项目地址:https://gitcode.com/gh_mirrors/opend/open-design
点击查看免费下载

OpenDesign 的插件系统以SKILL.md为可执行契约、以open-design.json为增强型 sidecar,而 apps/daemon/tests/fixtures/plugin-fixtures/README.md 正是这套机制的"最小可运行标本":一个自包含的声明式插件夹具,被 Phase 1 插件系统测试作为端到端闭环(e2e-1)的输入。阅读本文后,你将掌握open-design.json清单的每个核心字段的语义、sidecar 与 SKILL.md 的合并优先级、以及"安装 → 列出 → 应用 → 快照 → 诊断"整条闭环是如何在仓库测试中落地验证的——这套知识可直接复用于编写你自己的 OpenDesign 插件。

一、plugin-fixtures 是什么:Phase 1 测试的"声明式插件标本"

插件夹具目录 apps/daemon/tests/fixtures/plugin-fixtures/ 是插件系统测试专用的固定输入。README 中明确了两条定位:

  1. 服务对象:Phase 1 插件系统测试(对应 docs/plans/plugins-implementation.md 中记录的 e2e-1 闭环验收);
  2. 组织方式:每个子文件夹都是一个"自包含的 OpenDesign 插件",按 docs/plugins-spec.md §5 的约定组织,随时可以交给od plugin install --source <path>安装。

当前夹具只含一个子目录sample-plugin/,内部是两个文件:

  • open-design.json—— 规范清单(canonical manifest);
  • SKILL.md—— 伴随的技能文件(companion)。

README 特别强调了这套双文件设计的意图:sidecar 拥有主优先级(primary precedence);而SKILL.md之所以存在,是为了在删除open-design.json之后,让 daemon 的兼容适配器(compat adapter)可以被隔离测试。也就是说,一个夹具同时覆盖了插件系统的两条解析路径——完整清单路径与纯 SKILL 降级路径。

二、解剖 sample-plugin:open-design.json 清单逐字段解析

sample-plugin的清单是 spec v1 中最精简的合法形态,适合逐字段拆解。完整内容见 apps/daemon/tests/fixtures/plugin-fixtures/sample-plugin/open-design.json,逐段含义如下:

顶层:标识与元数据

{ "$schema": "https://open-design.ai/schemas/plugin.v1.json", "specVersion": "1.0.0", "name": "sample-plugin", "title": "Sample Plugin", "version": "1.0.0", "description": "Phase 1 e2e fixture used by od plugin install/apply walkthroughs.", "license": "MIT", "tags": ["sample", "phase1"] }
  • $schema:清单所遵循的 JSON Schema(docs/schemas/open-design.plugin.v1.json的对外地址),供编辑器补全与校验;
  • specVersion插件规范版本,与插件自身的version是两回事。spec §5.1 指出它会冻结进 apply 快照用于回放(replay)一致性;
  • name:插件唯一 id,安装后installed_plugins表即以此为主键;
  • version:插件包版本,任何行为、元数据、pipeline、inputs 或内置资源变更都应升版;
  • licensetags:分发元数据,spec 中tags用于 marketplace 筛选。

od 命名空间:可执行行为声明

"od": { "kind": "skill", "taskKind": "new-generation", "useCase": { "query": "Generate a {{topic}} brief for {{audience}}." }, "context": { "skills": [{ "ref": "open-design-landing" }], "atoms": ["todo-write", "discovery-question-form"] }, "inputs": [ { "name": "topic", "type": "string", "required": true, "label": "Topic" }, { "name": "audience", "type": "select", "options": ["VC pitch", "general"], "default": "general" } ], "capabilities": ["prompt:inject"] }

对照 spec §5.1 的字段参考,各字段语义如下:

字段语义sample-plugin 中的用法
od.kind注册表分类:skill/scenario/atom/bundleskill,即作为普通技能被注册
od.taskKind四大产品场景之一:new-generation/code-migration/figma-migration/tune-collabnew-generation,驱动 marketplace 过滤与默认输入模板
od.useCase.query点击"使用"时填入 brief 框的确切文本;{{var}}占位符绑定到od.inputs{{topic}}{{audience}}两个占位符模板化查询
od.context.skills类型化上下文条目,编译为ContextItem(spec §5.2)引用open-design-landing技能,注入提示栈
od.context.atoms无序集:声明插件需要的 atom;daemon 按默认顺序使用todo-write(规划)、discovery-question-form(澄清)
od.inputs详情页表单字段,其值回填useCase.querytopic(必填字符串)、audience(下拉单选,默认general
od.capabilities声明式能力列表;restricted插件缺省时为['prompt:inject']显式声明prompt:inject(提示注入总是被允许)

值得注意的细节:context.skillsrefopen-design-landing——这与仓库中的 design-templates/open-design-landing/ 模板命名一致,说明夹具刻意引用了仓库内真实存在的技能资产,从而让od plugin doctor的"上下文引用检查"(resolved-context ref check)在闭环测试中有真实可解析的目标。

三、SKILL.md 半边:兼容适配器的隔离测试场

sample-plugin 的 SKILL.md 不是摆设。它带有od:frontmatter:

--- name: sample-plugin description: Phase 1 sample plugin synthesizing a SKILL.md frontmatter for backwards-compat tests. od: kind: skill taskKind: new-generation preview: type: deck ---

正文则描述了一个三步工作流:先经 discovery question form atom 确认用户 brief,再用 TodoWrite 规划,最后以 deck 产物形式输出 brief。

这份SKILL.md的存在意义在 README 中说得非常直白:当一次安装缺少显式 sidecar 时(只需删掉open-design.json),纯 SKILL 兼容层级(legacy compat tier)必须保持诚实可测。这正是 spec §5.4 描述的机制:当插件没有open-design.json,但SKILL.md已含od:frontmatter 时,packages/plugin-runtime 的adapters/agent-skill.ts会从 frontmatter **合成(synthesize)**一个最小PluginManifest,且映射必须稳定,避免遗留技能协议与新插件 schema 产生语义漂移。

由此形成三种消费形态:

  • SKILL.md单独存在 → 任何按 SKILL 协议消费的 agent(Claude Code、Cursor、Codex 等)都能直接运行;
  • 加上open-design.json→ 解锁 OD 的 marketplace 卡片、预览、一键使用、类型化上下文条;
  • 只有open-design.json→ 按 spec §5 属于metadata-only 预设,不可直接触发 agent 运行,od plugin doctor会提示作者补上SKILL.md.claude-plugin/plugin.json

四、sidecar 合并优先级:open-design.json wins

README 强调的"sidecar 有主优先级",在 spec 与实现计划中有三重印证:

  1. 合并规则:spec §5.4 明确"如果open-design.jsonSKILL.mdfrontmatter 同时存在,open-design.json胜出(wins),但加载器必须保留适配器告警"。packages/plugin-runtime/src/merge.ts正是负责"sidecar + 适配器合并"的模块。
  2. 不变量 I1:实现计划 docs/plans/plugins-implementation.md 的第 1 条不变量规定:"SKILL.md是底线(floor),open-design.json是 sidecar,二者永不双向耦合",并明确"打包的 e2e fixture 同时携带两个半边,由apps/daemon/tests/plugins-e2e-fixture.test.ts演练合并器"。
  3. 合成与缓存installed_plugins表的manifest_json列缓存的就是"open-design.json(或合成的结果)",即注册表在安装时已完成合并落盘。

这意味着插件作者可以增量迁移:先让旧 SKILL 原样可运行,再逐步补充 OD marketplace 元数据,两个消费通道互不破坏。

五、Phase 1 闭环:install → list → apply → snapshot → doctor

夹具的价值最终体现在它驱动了 e2e-1 闭环测试:apps/daemon/tests/plugins-e2e-fixture.test.ts。该测试刻意只走 daemon 内部模块、不起 HTTP 服务,从而在 CI 上无头运行。测试步骤与对应模块如下:

步骤调用断言要点
1. 安装installFromLocalFolder(db, { source: FIXTURE_DIR, roots: { userPluginsRoot } })事件流中出现success
2. 列出listInstalledPlugins(db)恰好 1 条记录,id === 'sample-plugin'title === 'Sample Plugin'
3. 应用applyPlugin({ plugin, inputs: { topic: 'AI design tools' }, registry })返回AppliedPluginSnapshotpluginId === 'sample-plugin'manifestSourceDigest匹配^[0-9a-f]{64}$(sha256 hex)
4. 快照createSnapshot(db, {...})getSnapshot(db, snapId)snapshotId 为 UUID;重取后manifestSourceDigestinputs.topic原样保留
5. 诊断doctorPlugin(plugin, {...})report.ok === true

其中两个细节尤其值得关注:

  • 纯函数边界applyPlugin本身不写数据库、不动文件系统——快照由snapshots.tscreateSnapshot单独持久化。这印证了实现计划中的不变量 I2("Apply 是纯函数,副作用只在POST /api/projects/POST /api/runs之后发生"),也对应定义完成标准中的 e2e-8(100 次 apply 只增长 100 条快照行、项目目录字节数不变)。
  • 输入模板绑定inputs: { topic: 'AI design tools' }会在 apply 时把{{topic}}占位符解析为实际文本,最终快照里inputs.topic被持久化,证明useCase.query模板化机制在闭环中真实生效。

六、如何复现这条路径:命令行走查

夹具的设计目标之一就是可直接交给 CLI 消费。在已启动 daemon 的环境中可以这样走:

od plugin install --source apps/daemon/tests/fixtures/plugin-fixtures/sample-plugin od plugin list # 应看到 sample-plugin / Sample Plugin od plugin info sample-plugin od plugin apply sample-plugin --input topic="AI design tools" --input audience="general" od plugin doctor sample-plugin # 输出 ok: true

若想验证兼容适配器路径,把sample-plugin目录下的open-design.json临时移走后再次安装/apply,daemon 将走SKILL.mdfrontmatter 合成清单的降级路径。安装器本身带有路径穿越防护、50 MiB 大小上限与符号链接拒绝等守卫(见实现计划 Phase 1 对installer.ts的描述);od plugin install还支持github:owner/repohttps://…/plugin.tar.gz与裸插件名(经 marketplace 解析)等多种 source 形态,具体语法见 docs/plugins-spec.md。

七、从夹具到正式插件:你能从中复用什么

把 sample-plugin 当作模板,向正式插件演进时遵循 spec §5 的升级阶梯:

  1. 保持SKILL.md可运行——这是跨目录(Claude Code / Cursor / Codex / 各类 catalog)的通用契约;
  2. 补充open-design.jsonsidecar——从本夹具的 11 个顶层/od 字段起步,逐步加入title_i18npreviewpipeline.stagesgenui.surfacesconnectors等高级声明;
  3. od plugin doctor持续校验——它覆盖 schema 校验、SKILL.md 解析、atom id 存在性、上下文引用检查、digest 漂移检测(spec §5.3 能力词汇表与 §12 退出码可作验收依据);
  4. 注意context.atomspipeline的关系——两者并存时pipeline优先,context.atoms只作为上下文条元数据(spec §5.1)。

八、延伸阅读

  • 插件规范正文:docs/plugins-spec.md(含 §5open-design.jsonschema、§5.2ContextItem联合类型、§5.3 能力词汇表)
  • 实现计划与不变量:docs/plans/plugins-implementation.md
  • 技能协议(SKILL.md 与od:frontmatter 语义):docs/skills-protocol.md
  • 运行时适配器与合并逻辑:packages/plugin-runtime
  • 契约类型(PluginManifestAppliedPluginSnapshot等):packages/contracts/src/plugins/

一句话总结:plugin-fixtures/sample-plugin是 OpenDesign 插件系统最小的"完整真理源"——它用一个双文件夹具同时锁定了 sidecar 合并优先级、SKILL 兼容降级与安装→应用→快照→诊断闭环三条核心不变量,是理解整个插件架构的最佳切入点。

  • AI 应用
  • 人工智能
  • AI 技能
  • 设计系统
  • 媒体生成

【免费下载链接】open-design

🎨 Best DeepSeek Harness Design Plugin. The open-source Claude Design alternative. 🖥️ Local-first desktop app. 🖼️ Your coding agent becomes the design engine: prototypes, landing pages, dashboards, slides, images & video — real files, HTML/PDF/PPTX/MP4 export. 🤖 Claude Code / Codex / Cursor / DeepSeek Harness / OpenCode & 20+ CLIs via BYOK.

项目地址:https://gitcode.com/gh_mirrors/opend/open-design
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 20:54:59

C语言Socket编程实战:手写TCP双端即时通讯完整教程

简介&#xff1a;这是一份以C语言实现双端即时通讯的教学演示项目&#xff0c;面向具备基础C语法、希望进阶网络编程的学习者&#xff0c;也适合高校网络编程课程作为实验参考。项目完整呈现了客户端与服务器从创建套接字、绑定地址、监听连接到收发消息、多线程处理请求的整个…

作者头像 李华
网站建设 2026/9/20 20:54:37

T265+PX4视觉定位保姆级教程:从驱动安装到EKF2融合与MAVROS桥接

我第一次把 T265 接到 Pixhawk 上时&#xff0c;无人机在地面站里显示的位置跟实际位置永远差着 90 度&#xff0c;差点把满屋子设备撞翻。后来排查下来才发现&#xff0c;问题不在硬件&#xff0c;而在整个数据链路里有一层没人明说的坐标系转换。这篇文章想把这套链路完完整整…

作者头像 李华
网站建设 2026/9/20 20:53:36

AnySearch 的 MCP 接进 Cursor,模型 Base URL 填 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 20:49:54

Claude Code vs Codex:同一把 TaoToken Key 跑 pytest 夹具重构

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 20:48:26

ICESAT-1/2激光测高数据可视化与去噪Python实践

简介&#xff1a;面向ICESAT系列卫星数据的科研与工程人员&#xff0c;这份Python程序包实现了光子计数与波形数据的加载、去噪和可视化&#xff0c;适用于冰川高度变化分析、全球气候变化研究等场景。资源压缩包共三十五个文件&#xff0c;整体约七百一十七兆&#xff0c;主要…

作者头像 李华