VibecapeDocs

开发自定义插件

使用当前 SDK 和 CLI 创建、验证、安装并发布 Vibecape 自定义插件。

Vibecape 扩展可以添加文档操作、Dialog、完整 Main View、设置面板、自定义文档类型,以及需要宿主权限的 Main Action。开发时应以当前安装的 @vibecape/extension-kit@vibecape/cli 为唯一权威来源。

准备环境

  • Node.js 18 或更高版本
  • pnpm
  • 本地安装的 Vibecape,用于安装验证

使用旧示例前,先检查当前 CLI 和类型契约:

pnpm exec vibecape extension --help

同时查看 manifest.schema.json@vibecape/extension-kit 导出的类型声明。不要导入 Vibecape App 的私有模块。

初始化项目

pnpm dlx @vibecape/cli extension init ./my-extension \
  --id com.example.my-extension \
  --name "My Extension"
cd my-extension
pnpm install

生成的扩展采用下面的目录结构:

my-extension/
  manifest.json
  package.json
  README.md
  tsconfig.json
  assets/
    icon.svg
  main/
    index.ts
  renderer/
    index.tsx

不要手写 dist 文件。Main、Renderer、序列化 UI、发布压缩包和 vibecape-extension.json 都由 CLI 生成。

定义 Manifest

从描述扩展所需的最小 Manifest 开始:

{
  "$schema": "./node_modules/@vibecape/extension-kit/manifest.schema.json",
  "id": "com.example.my-extension",
  "name": "My Extension",
  "description": "用一句具体的话描述用户最终得到什么。",
  "icon": "./assets/icon.svg",
  "main": "./dist/main/index.js",
  "renderer": "./dist/renderer/index.js",
  "activationEvents": ["onStartup"],
  "extensionApiVersion": 1
}

package.json.version 是唯一的发布版本。所有路径必须位于扩展包内部;只有测试过真实的最低宿主版本后才添加 engines.vibecape;只有确实提供自定义格式时才声明 contributes.documentTypes

注册 Main Action

需要宿主权限的操作放在 ExtensionMain Action 中。调用会跨越进程边界,因此必须验证所有输入。

import { ExtensionMain } from "@vibecape/extension-kit";

export default class MyExtension extends ExtensionMain {
  readonly id = "com.example.my-extension";

  activate(): void {
    this.extension.action({
      id: "example.readDocument",
      title: "Read current document",
      run: async (input) => {
        const record = input && typeof input === "object" ? input : {};
        const directId = "docId" in record ? record.docId : undefined;
        const doc =
          "doc" in record && record.doc && typeof record.doc === "object"
            ? record.doc
            : {};
        const contextId = "id" in doc ? doc.id : undefined;
        const docId =
          typeof directId === "string"
            ? directId
            : typeof contextId === "string"
              ? contextId
              : "";

        if (!docId) throw new Error("docId is required");

        const file = await this.app.files.read({ id: docId });
        this.logger.info("Read document", { docId });
        return { id: file.id, name: file.name, content: file.content };
      },
    });
  }
}

Action ID 应稳定且带命名空间,输入与返回值必须可以 JSON 序列化。密钥、登录、网络请求、文件系统操作和高开销任务都应留在 Main Runtime。

结构化 App Bridge 提供工作区、文件、资源、外部链接、Finder 和剪贴板等能力。具体签名以当前安装的类型声明为准。

注册 Renderer UI

默认导出 defineRenderer,并导出贡献项引用的每个组件:

import { defineRenderer } from "@vibecape/extension-kit/react";

export function HomePage() {
  return <div>Extension main view</div>;
}

export function ExportDialog() {
  return <div>Export workflow</div>;
}

export function ConfigPanel() {
  return <div>Extension settings</div>;
}

export default defineRenderer(({ ui }) => {
  ui.extension.mainview({
    id: "home",
    title: "My Extension",
    component: HomePage,
  });

  ui.customize.mainview({
    id: "home-entry",
    title: "My Extension",
    page: "home",
  });

  ui.doc.menu.root({ id: "open", title: "Open", order: 10 }).mainview("home");
  ui.doc.menu.export({ id: "export", title: "Export", order: 20 }).dialog(ExportDialog);
  ui.doc.menu.root({ id: "read", title: "Read", order: 30 }).run("example.readDocument");
  ui.config.panel({ id: "settings", title: "My Extension", component: ConfigPanel });
});

每个 .run(actionId) 都必须有对应的 Main Action;每个 .mainview(pageId) 都必须引用已声明的 Extension Main View。文档入口会收到当前文档上下文;Customize 入口可能在没有当前文档时打开,因此必须处理 doc 缺失的情况。

验证与本地安装

运行生成项目提供的脚本:

pnpm run validate
pnpm run typecheck
pnpm run build
pnpm run test

完成前检查:

  1. Manifest 通过当前 CLI 校验;
  2. 声明的 Main 和 Renderer Bundle 已生成;
  3. 每个序列化组件都有对应导出;
  4. 每个序列化 Action 都有 Main 注册;
  5. 发布描述文件中的版本、大小和 SHA-256 与压缩包一致;
  6. 可以通过 Extensions → More → Install from folder 安装;
  7. 相关入口在有、无当前文档时均符合预期;
  8. 停止和重新启动扩展时,贡献项能够正确移除与恢复。

使用 GitHub Releases 发布

第三方扩展通过公开 GitHub 仓库分发:

  1. 按语义化版本更新 package.json.version
  2. 重新执行校验、测试和构建;
  3. 创建 v1.2.0 形式的稳定 Tag;
  4. 上传生成的压缩包和 vibecape-extension.json,不要重命名。

第三方扩展没有 vibecape extension publish 命令。Vibecape 会根据仓库 URL 读取最新的稳定 GitHub Release。

本页内容