插件

插件系统设计

BeefTV统一插件系统的扩展边界、Manifest 合同与 Eagle 外部素材来源方案

状态:已实现首版(Eagle 外部素材来源 + AI 提示词优化器)

当前版本已经包含 Eagle 专属素材管理页面、后端本地桥接、原始文件树浏览、文件读取和写入,以及内置 prompt-optimizer AI 能力插件。第三方包统一使用 .beeftv-plugin;远程 Web 入口仍必须经过沙箱运行时和宿主 RPC。

1. 背景与范围

当前项目包含 Codex App 的 MCP 包和BeefTV网页插件贡献。它们可以使用不同的运行时,但安装、权限、版本和能力发现都遵循同一个BeefTV插件 Manifest;MCP 连接本身仍受独立的工具安全边界约束。

网页插件的第一目标不是开放所有页面代码,而是提供稳定、可审计、可逐步扩展的宿主 API,让第三方开发者能够在不修改主应用源码的情况下接入能力。

2. 设计目标

  • 第三方开发者可以独立开发、构建和发布插件。
  • 普通用户可以查看并启用官方应用插件;管理员统一安装、更新、停用和卸载系统协议及自定义插件。
  • 插件不直接依赖页面内部 React 组件和 Zustand store。
  • 宿主可以通过 apiVersion 和权限声明控制兼容性与风险。
  • 插件的错误、超时、权限拒绝和版本不兼容必须可见,不能静默降级。
  • 插件产生的本地数据必须按插件 ID 隔离,并在卸载时可清理。
  • 未来可以加入官方注册表,也可以使用组织内部或本地插件源。

3. 非目标

第一阶段不开放以下能力:

  • 任意修改宿主路由、全局布局和认证流程。
  • 任意访问用户 Cookie、API Key、数据库或后端数据目录。
  • 插件自行注册 Gin 路由、GORM model 或后台 Worker。
  • 插件在没有用户确认的情况下上传、删除或覆盖资源。
  • 用插件机制替代现有 AI 渠道、资源存储和权限服务合同。

需要服务端能力的插件,应通过明确的后端集成接口或独立服务完成,而不是让远程 JavaScript 直接访问敏感数据。

4. 插件分类

插件分类用于权限、市场筛选和能力发现,不直接决定代码目录结构。

4.0 管理分类与权限

插件的管理分类由宿主根据插件 ID 和安装来源计算,不能由上传包自行声明:

分类典型插件平台可用性用户启用状态配置范围
系统插件OpenAI、Gemini、即梦等协议 Provider管理员不适用管理员
官方插件RunningHub、ComfyUI Bridge、Eagle、提示词优化器、肖像排查管理员作为硬上限每个用户独立按插件为用户级或无配置
自定义插件管理员上传的 .beeftv-plugin管理员不适用管理员

/plugins 是用户发现、个人启用和个人配置入口;/admin/plugins 是平台可用性、上传、卸载和启用人数入口。普通用户是否能看到只读的系统/自定义插件由“向普通用户显示系统插件”功能开关控制,但官方应用插件始终保留个人开关。

4.1 画布节点插件

新增自定义节点类型、节点内容渲染、节点详情面板、节点工具栏和节点输入输出资源。

适合:角色卡、场景卡、分镜卡、Markdown、SVG、HTML、提示词、素材引用和分析结果节点。

4.2 工作流插件

在用户确认后创建节点、连接节点、批量处理、触发生成、执行重试或进行结果整理。

适合:剧本 → 角色 → 场景 → 分镜 → 提示词 → 生图 等可复用流程。

4.3 AI 能力插件

提供提示词处理、图片分析、批量生成、结果评分或模型能力适配。涉及真实 API Key 的请求必须经过宿主现有渠道中转合同或受控后端服务。

当前内置的 prompt-optimizer 插件用于在创作页和图片、视频节点的提示词编辑器中优化用户输入。它通过宿主的 ai.text 服务调用已配置的文本模型,不直接读取 API Key;结果先以可编辑内容展示,用户点击“采用”后才回填当前输入框。

4.4 素材与数据连接器

连接外部素材库、提示词库、知识库、云盘或项目管理工具,提供搜索、导入、上传、同步和来源追踪。

Eagle 插件属于此类,具体方案见第 8 节。

4.5 导入导出插件

扩展剧本、分镜、提示词、素材包、JSON、Markdown、PDF 等格式的导入或导出。

4.6 画布工具能力(旧内置 Agent 宿主已退场)

旧内置 Agent 的宿主已从产品运行面退场,因此当前没有运行时读取这些画布工具声明。插件仍然只能通过版本化的宿主贡献点提供技能或能力声明,不能注入本地进程、MCP 连接或浏览器私有状态;替换内核落地时按同一合同接入。

5. 插件包与清单

插件以一个统一的 .beeftv-plugin 包作为入口。包内固定包含 manifest.json,也可以包含受沙箱约束的 Web 入口和静态资源。Manifest 负责描述插件能力、权限和运行时;包文件负责承载对应版本的实现,不能再把“协议 JSON”和“UI 插件源码”拆成两套安装系统。

建议的最小包结构:

eagle-asset-connector.beeftv-plugin
├── manifest.json
├── web/entry.js       # 有 UI/功能代码时声明
└── web/assets/...     # 可选静态资源

manifest.json 建议从以下最小清单开始:

{
  "apiVersion": "beeftv.plugin/v1",
  "id": "eagle-asset-connector",
  "name": "Eagle 素材库",
  "version": "0.3.0",
  "author": "BeefTV Contributors",
  "permissions": ["asset.read", "asset.search", "asset.upload"],
  "configuration": { "fields": [{ "name": "baseUrl", "type": "url", "required": true }] },
  "contributes": { "assetSources": ["eagle"] }
}

带 Web 功能的包增加 entry: "web/entry.js"、runtime.web: "sandbox" 或 "worker"。上传入口只接受 .beeftv-plugin,服务端会校验 ZIP 路径、大小、重复文件、Manifest 和入口文件,不执行包内 JavaScript;当前版本先完成包校验、存储和入口合同,未授权的 Web 代码不会自动进入主页面。Provider 仍由后端声明式运行时执行;UI/功能代码通过隔离运行时和权限化宿主 API 接入。

字段约束:

  • id:全局唯一,使用小写 kebab-case;安装后不能随意变更。
  • version:遵循 SemVer,用于更新和回滚判断。
  • apiVersion:支持 beeftv.plugin/v1、v2 和 v3。v2 增加编辑器插槽;v3 保留 v2 的 UI 结构,并要求宿主支持 provider 变量、默认路径前缀及图片流响应。使用这些新字段必须声明 v3,旧宿主会在加载时拒绝该清单,避免忽略字段后错误提交。已有 v1/v2 插件继续读取。
  • contributes:声明 provider、workflow、canvasNodes、transforms、assetSources、agents 等能力。
  • permissions:最小权限集合,宿主在安装和首次使用时展示。
  • dependencies:插件依赖的其他插件或宿主能力。
  • integrity:用于校验远程产物是否被替换。

Provider 的 v3 请求与图片响应

contributes.providers[] 可在 v3 清单中声明 variables:按数组顺序计算的纯表达式,输入为 request,前面的变量通过 vars.<name> 读取。变量仅在当前请求内存在,不共享状态。重复名称、前向引用,以及请求模板或参数校验中不存在的变量会在加载时拒绝。

{
  "variables": [{ "name": "size", "value": { "$coalesce": [{ "$ref": "request.aspectRatio" }, "2K"] } }],
  "create": {
    "method": "POST",
    "path": "/images/generations",
    "defaultPathPrefix": "/api/v3",
    "body": { "size": { "$ref": "vars.size" } }
  }
}

defaultPathPrefix 是连接地址没有路径时使用的默认前缀;连接地址已有 /v1 等路径时保留该路径。它只接受相对路径,不能包含查询参数、片段或上级目录。

图片响应可声明 response.detectImageMime: true,按实际 PNG、JPEG 或 WebP 字节确定内联图片类型。response.stream 指定事件类型路径、完成事件、错误事件、图片表达式和可选的非负整数索引路径;只有声明了此字段才读取图片 SSE。网关错标 Content-Type 时,仍可识别明确的 data: / event: 流。重复索引以第一张有效图片为准;坏事件不占用索引,部分成功保留已收到的图片,[DONE] 后不再接收。图层的名称、描述、边界框和层次顺序随图片结果保留。

这些字段必须使用 beeftv.plugin/v3;旧宿主拒绝加载该版本,避免忽略字段后发送错误请求。

6. 宿主 API 边界

插件不得直接导入页面组件、store 或内部 API 文件。宿主通过版本化 SDK 提供能力。

建议第一版 SDK 包含以下能力:

export interface CanvasPluginManifest {
  apiVersion: "beeftv.plugin/v1";
  id: string;
  name: string;
  version: string;
  permissions: string[];
  contributes: Record<string, unknown>;
}

export interface PluginSetupApi {
  canvas: CanvasApi;
  commands: CommandRegistry;
  events: PluginEventBus;
  storage: PluginStorage;
  assets: AssetApi;
  permissions: PermissionApi;
}

第一阶段的能力合同:

能力说明
节点注册注册节点类型、标题、图标、默认尺寸和渲染组件
节点面板编辑节点 metadata,展示插件自己的控制项
工具栏命令在节点工具栏、画布工具栏或上下文菜单增加动作
画布读写读取节点和连线;在用户确认后应用结构化操作
资源读写通过资源服务获取、导入和上传媒体,不在插件中拼接资源 URL
事件订阅监听节点、项目、生成任务和插件生命周期事件
插件存储使用带插件命名空间的轻量配置和索引数据
清理函数停用或卸载时移除事件、样式、命令和临时资源

写操作必须通过结构化指令进入宿主,不能直接修改 React 状态。所有写操作都要保留失败原因和用户可见反馈。

6.1 内置 AI 文本服务

声明 ai.text 权限的插件可以使用宿主提供的文本模型服务。请求包含消息、可选的工具定义、工具选择、取消信号和流式增量回调;宿主负责选择当前配置的模型、经过现有渠道中转并返回结构化工具调用结果。插件不得自行创建平行的 HTTP 客户端或把密钥写入请求正文、日志和 URL。

提示词优化器使用 optimize_prompt 工具返回以下结构:优化后的提示词、规避项、变化说明、假设和最多两个备选版本。model-adapt 模式会根据目标生成模型和协议选择适配策略,但不会臆造未确认的模型参数。

7. 生命周期

发现 → 查看清单 → 安装 → 校验兼容性和权限 → 启用 → 使用
                         ↓                       ↓
                 拒绝 / 失败                  停用 → 卸载
                         ↑                       ↓
                  更新 / 回滚 ← 版本检查 ← 清理

生命周期要求:

  1. 发现阶段只读取清单,不执行插件代码。
  2. 安装阶段下载入口和依赖,校验 HTTPS、版本、完整性和权限。
  3. 启用阶段先申请权限,再执行 setup。
  4. 停用阶段禁止新请求进入,等待可取消任务结束后调用清理函数。
  5. 卸载阶段清理插件存储、事件订阅、注册命令和可选的插件节点数据。
  6. 更新失败时保留旧版本,不能留下半启用状态。
  7. 官方协议插件随发行包撤下时不会立即删除:启动先盘点本地模型配置、系统渠道模型和未取回结果的任务,仍有引用就保留执行能力,并在插件中心和协议目录接口里带上“已撤下”标记;没有任何引用时才清理。目前前端还不读这个标记,新建模型时把已撤下的协议过滤掉,要等以后前端接入后才生效。

平台状态与用户状态分开保存:effectiveEnabled = platformAvailable && userEnabled。协议和自定义插件只有平台状态。用户停用工作流插件后禁止新任务进入,但已经接收的任务和 Bridge 结果回传继续完成;管理员停用属于平台硬上限,同样不强行破坏已进入执行阶段的任务。

8. Eagle 外部素材来源方案

Eagle 插件的主分类是“素材与数据连接器”,可以附带一个 EagleAsset 画布节点。

8.1 连接器职责

  • 使用 Eagle 本地 API(默认 http://127.0.0.1:41595)检查服务并读取当前素材库。
  • 在BeefTV素材页进入 Eagle 专属素材管理页面,按 Eagle 的父子文件树浏览和搜索文件。
  • Eagle 文件仍由 Eagle 管理,BeefTV只通过外部素材来源读取、下载和使用,不要求逐个选择或复制成本地素材。
  • 在当前 Eagle 文件夹中新建文件夹,并把本地图片、视频和音频直接写入 Eagle。
  • 返回 Eagle 素材 ID、文件夹 ID、完整文件夹路径和来源信息,供BeefTV项目保存外部引用。
  • 通过BeefTV后端本地桥接读取 Eagle 文件,避免浏览器直接打开 Eagle 的本机文件路径。

8.2 画布节点

EagleAsset 节点只保存可迁移的引用信息和展示 metadata,不把 Eagle 的完整文件内容塞进画布 JSON:

type EagleAssetMetadata = {
  assetId: string;
  libraryId?: string;
  folderId?: string;
  title: string;
  tags: string[];
  sourceUrl?: string;
  syncedAt?: string;
};

节点可以提供:

  • 预览缩略图。
  • 标签、尺寸和来源展示。
  • 导入本地资源副本。
  • 在 Eagle 中打开。
  • 更新节点中的 Eagle metadata。
  • 将当前生成结果上传到 Eagle。

8.3 Eagle 权限

第一版建议只申请:

asset.read
asset.search
asset.upload
external.open

删除 Eagle 资源、批量覆盖和修改原始文件属于高风险权限,应单独申请并逐次确认,不能包含在普通 asset.write 中。

8.4 推荐交互

首版提供外部素材库浏览和双向写入:

Eagle 文件树 / 搜索 → 打开素材 → 在BeefTV中使用外部引用
BeefTV上传图片、视频或音频 → 选择 Eagle 目标文件夹 → 写入 Eagle
BeefTV生成图片、视频或音频 → 插件自动归档到 Eagle 目标文件夹

8.5 当前实现边界

  • 素材页的“Eagle 素材库”进入插件专属页面,不使用抽屉,也不要求选择素材。
  • 左侧文件树直接继承 Eagle 的父子层级;BeefTV保存外部引用时保留 Eagle 素材 ID、文件夹 ID 和路径信息。
  • 图片、视频、音频和模型可以从 Eagle 直接浏览、搜索和读取;当前不把文本类内容转换成BeefTV文本素材。
  • 当前支持将本地图片、视频和音频写入 Eagle 当前文件夹;生成结果可以在插件设置中开启自动归档并指定 Eagle 文件夹。BeefTV仍保留本地素材记录,外部写入成功或失败会记录到素材 metadata。实际可写入格式由本机 Eagle 版本/API 决定;如果 Eagle 拒绝某种媒体,BeefTV保留本地结果并记录失败状态。删除、批量覆盖和冲突解决仍需后续权限设计。
  • Eagle 地址只允许本机默认端口,后端会校验本机地址和文件路径,避免把连接器变成任意内网访问代理。
  • Eagle 文件夹不会复制成BeefTV项目中的独立资产文件夹;页面以 Eagle 原始文件树作为外部来源视图。自动归档默认使用 Eagle 根目录,用户可以在插件设置中关闭或改用具体文件夹。

9. 安全边界

当前远程 JavaScript 插件如果直接在页面上下文执行,可能接触页面可见数据和本地配置。因此正式开放第三方插件前必须完成以下事项:

  • 插件默认无权限,按能力逐项授权。
  • API Key、登录 Cookie 和后端会话不得通过通用插件 API 暴露。
  • 外部请求优先经过宿主服务或明确的连接器 API。
  • 远程产物支持完整性校验、版本锁定和撤销。
  • 插件错误不能吞掉,必须记录插件 ID、版本和可读错误。
  • 公开市场只允许可信来源;组织内部插件可使用私有注册表。
  • 高风险写入、上传、删除和外部同步必须有用户确认。

长期方向是将不可信插件放入 iframe、Worker 或 Capability 沙箱,避免插件默认拥有宿主页面权限。

10. 开发者接入流程

后续应提供一个独立 SDK 和模板,使开发者可以:

  1. 创建插件模板。
  2. 安装 SDK 和类型定义。
  3. 在本地启动 watch 构建。
  4. 使用宿主提供的模拟画布和测试数据验证插件。
  5. 生成插件清单和构建产物。
  6. 发布到静态地址或组织注册表。
  7. 在BeefTV的插件管理器中通过 URL 安装。

推荐目录:

plugins/
  eagle-asset-connector/
    plugin.json
    package.json
    src/
      index.ts
      eagle-client.ts
      eagle-node.tsx
    README.md
    dist/

11. 实施顺序

Phase 1:稳定插件核心

  • 插件清单和 apiVersion。
  • 本地插件发现。
  • 安装、启用、停用、更新和卸载。
  • 节点注册、工具栏命令、事件和插件存储。
  • Eagle 外部素材来源页面、媒体写入和生成结果自动归档。

Phase 2:连接器和工作流

  • 资源连接器合同。
  • 上传回写和标签同步。
  • 批量处理和工作流触发器。
  • 插件配置页面和错误诊断。
  • 插件 SDK、模板和本地测试工具。

Phase 3:生态安全

  • 官方和私有注册表。
  • 完整性校验、签名和版本回滚。
  • 权限审核和风险分级。
  • 不可信插件沙箱。
  • 插件兼容性测试和自动化发布。

12. 第一版验收标准

  • 第三方开发者可以只依赖 SDK 新增一个画布节点。
  • 插件可以通过 URL 安装,不需要修改宿主业务代码。
  • 用户能看到插件名称、版本、来源和权限。
  • 插件停用后不再响应事件,也不残留工具栏命令。
  • 插件更新失败时旧版本仍可用。
  • Eagle 插件可以浏览原始文件树、搜索和读取素材,并将图片、视频和音频写入 Eagle;用户可以配置生成结果是否自动归档及目标文件夹。
  • Eagle Token 不进入画布节点、任务正文、日志或 URL。
  • 插件错误和权限拒绝能够显示给用户。

本页内容