快速开始

适用版本:StablEdge 桌面端 0.4.4,插件清单协议 v3

本页从零写一个最小的工作区插件:一个可以保存草稿、并能被 Agent 读取的页面。整个过程不需要 Worker,也不需要网络权限。

先选最小架构

只为当前需求申请能力,不为“以后可能用到”预留:

需求采用
面板、表单、看板、可视化工作区界面(Workspace)
插件私有的解析、转换、后台计算插件 Worker
多个插件共享、版本独立的重型能力全局 Worker 服务
Agent 读取或修改插件状态Workspace 加包内技能(Skill)
少量设置和索引storage.kv
文档、图片、音视频和大块状态storage.blob
外部 HTTP API界面侧 net.fetch 或 Worker 侧 host.net.fetch

推荐的演进顺序是:Workspace → 插件 Worker → 全局 Worker 服务。纯展示的插件不要创建占位 Worker。

目录结构

<插件目录>/
├── plugin.json
└── payload/
    ├── ui/
    │   ├── index.html
    │   ├── app.js
    │   └── styles.css
    ├── i18n/
    │   ├── zh-CN.json
    │   └── en-US.json
    ├── resources/
    │   └── icon.png        # 必需:200×200 PNG,≤ 500 KiB
    └── agent/
        └── SKILL.md

所有入口和运行资源都必须放在 payload/ 下,并出现在最终 plugin.json 的 files 里。不要把 node_modules、构建缓存、测试数据、密钥或本机绝对路径放进包。

编写 plugin.json

{
  "schema_version": 3,
  "plugin_id": "com.example.my-notes",
  "name": "My Notes",
  "version": "0.1.0",
  "minimum_app_version": "0.4.5",
  "icon": { "resource_id": "icon" },
  "contributions": {
    "resources": [
      { "id": "icon", "path": "payload/resources/icon.png", "media_type": "image/png" }
    ],
    "workspaces": [
      {
        "id": "main",
        "title": "My Notes",
        "entrypoint": "payload/ui/index.html",
        "bridge_version": "1.0",
        "allowed_placements": ["replace_files", "replace_editor", "replace_both"],
        "default_placement": "replace_editor"
      }
    ],
    "skills": [{ "id": "agent", "entrypoint": "payload/agent/SKILL.md" }]
  },
  "workers": [],
  "requested_permissions": [
    { "permission": "agent.context", "worker": "host", "optional": false },
    { "permission": "agent.events", "worker": "host", "optional": false },
    { "permission": "storage.kv", "worker": "host", "optional": true }
  ],
  "required_services": [],
  "platforms": ["windows-x86_64", "macos-aarch64", "macos-x86_64"],
  "files": {},
  "publisher": "Example Inc."
}
  • plugin_id 一经发布不可更改,建议用反向域名。
  • agent.context、agent.events、storage.kv 都是 Workspace 作用域权限,按 workspace 授权,可以直接写 "worker": "host",不需要为此建 Worker。
  • 有 workspace 时,skills 和 agent.context 必须成对出现。skills 只接受 1 项。
  • files 在开发时可以先留空,打包工具会计算每个文件的 SHA-256 后写入。
清单里不要写 signature 和 publisher_key_id,这两个字段由打包器写入,见签名。

编写界面

界面必须先等待 stabledgePlugin.ready(),再调用其他方法。首次 context.publish 成功后,宿主才把这个 Workspace 标记为可以绑定 Agent。

async function initialize() {
  const host = await window.stabledgePlugin.ready();
  const draft = (await window.stabledgePlugin.storage.get("draft")) ?? "";
  render(draft);
  await window.stabledgePlugin.context.publish({
    version: 1,
    draft,
    available_actions: [{ name: "draft.set", payload: { text: "string" } }],
  });
}

if (window.stabledgePlugin) void initialize();
else window.addEventListener("stabledge:ready", initialize, { once: true });

window.stabledgePlugin.events.on("agent.custom", async ({ event, payload }) => {
  if (event !== "draft.set" || typeof payload?.text !== "string") {
    showError("不支持的操作");
    return;
  }
  await window.stabledgePlugin.storage.set("draft", payload.text);
  render(payload.text);
});
遇到无法处理的 Agent 动作时,在界面里给出明确提示即可,不要直接 throw。未捕获的异常只会让页面停在半初始化状态,用户看不到原因。

编写技能说明

payload/agent/SKILL.md 告诉 Agent 这个插件发布了哪些上下文、接受哪些动作(例如 draft.set 及其参数)。说明要和界面里 available_actions 的定义保持一致。

打包与安装

  1. 在桌面端打开「插件创建模式」,选择 <插件目录>。
  2. 点击「校验项目」,修复清单、图标、文件集和权限方面的报错。
  3. 点击「打包项目」生成 .seplugin;也可以直接「安装到预览环境」进行调试。
  4. 双击 .seplugin 会打开安装预览,确认权限后安装。新安装的插件默认停用,需要在插件列表里手动启用。

未经官方签名的包按「开发者」来源安装,需要先在「设置 → 插件 → 安装与签名」中打开「允许安装未签名插件」。详见 打包、签名与发布。

完成检查

  • 每项能力都有对应的清单声明和用户授权路径。
  • 界面不直接访问系统路径、裸网络或桌面端内部接口。
  • 持久化、外部数据和 Agent 交互都考虑了失败、撤权和重新打开后的恢复。
  • 没有为了挂权限而存在、却声称可调用业务方法的空 Worker。
本页目录