Files
ttstd-infinite-canvas/docs/content/docs/plugins/plugin-system.mdx
2026-09-14 01:11:56 +08:00

343 lines
16 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: 插件系统设计
description: 影策统一插件系统的扩展边界、Manifest 合同与 Eagle 外部素材来源方案
---
# 插件系统设计
> 状态:已实现首版(Eagle 外部素材来源 + AI 提示词优化器)
>
> 当前版本已经包含 Eagle 专属素材管理页面、后端本地桥接、原始文件树浏览、文件读取和写入,以及内置 `prompt-optimizer` AI 能力插件。第三方包统一使用 `.yingce-plugin`;远程 Web 入口仍必须经过沙箱运行时和宿主 RPC。
## 1. 背景与范围
当前项目包含 Codex App 的 MCP 包和影策网页插件贡献。它们可以使用不同的运行时,但安装、权限、版本和能力发现都遵循同一个影策插件 Manifest;MCP 连接本身仍受独立 Agent 安全边界约束。
网页插件的第一目标不是开放所有页面代码,而是提供稳定、可审计、可逐步扩展的宿主 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、提示词优化器、肖像排查 | 管理员作为硬上限 | 每个用户独立 | 按插件为用户级或无配置 |
| 自定义插件 | 管理员上传的 `.yingce-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. 插件包与清单
插件以一个统一的 `.yingce-plugin` 包作为入口。包内固定包含 `manifest.json`,也可以包含受沙箱约束的 Web 入口和静态资源。Manifest 负责描述插件能力、权限和运行时;包文件负责承载对应版本的实现,不能再把“协议 JSON”和“UI 插件源码”拆成两套安装系统。
建议的最小包结构:
```text
eagle-asset-connector.yingce-plugin
├── manifest.json
├── web/entry.js # 有 UI/功能代码时声明
└── web/assets/... # 可选静态资源
```
`manifest.json` 建议从以下最小清单开始:
```json
{
"apiVersion": "yingce.plugin/v1",
"id": "eagle-asset-connector",
"name": "Eagle 素材库",
"version": "0.3.0",
"author": "影策社区",
"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"`。上传入口只接受 `.yingce-plugin`,服务端会校验 ZIP 路径、大小、重复文件、Manifest 和入口文件,不执行包内 JavaScript;当前版本先完成包校验、存储和入口合同,未授权的 Web 代码不会自动进入主页面。Provider 仍由后端声明式运行时执行;UI/功能代码通过隔离运行时和权限化宿主 API 接入。
字段约束:
- `id`:全局唯一,使用小写 kebab-case;安装后不能随意变更。
- `version`:遵循 SemVer,用于更新和回滚判断。
- `apiVersion`:固定为 `yingce.plugin/v1`,不接受旧版本或平行 Manifest。
- `contributes`:声明 provider、workflow、canvasNodes、transforms、assetSources、agents 等能力。
- `permissions`:最小权限集合,宿主在安装和首次使用时展示。
- `dependencies`:插件依赖的其他插件或宿主能力。
- `integrity`:用于校验远程产物是否被替换。
## 6. 宿主 API 边界
插件不得直接导入页面组件、store 或内部 API 文件。宿主通过版本化 SDK 提供能力。
建议第一版 SDK 包含以下能力:
```ts
export interface CanvasPluginManifest {
apiVersion: "yingce.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. 生命周期
```text
发现 → 查看清单 → 安装 → 校验兼容性和权限 → 启用 → 使用
↓ ↓
拒绝 / 失败 停用 → 卸载
↑ ↓
更新 / 回滚 ← 版本检查 ← 清理
```
生命周期要求:
1. 发现阶段只读取清单,不执行插件代码。
2. 安装阶段下载入口和依赖,校验 HTTPS、版本、完整性和权限。
3. 启用阶段先申请权限,再执行 `setup`。
4. 停用阶段禁止新请求进入,等待可取消任务结束后调用清理函数。
5. 卸载阶段清理插件存储、事件订阅、注册命令和可选的插件节点数据。
6. 更新失败时保留旧版本,不能留下半启用状态。
平台状态与用户状态分开保存:`effectiveEnabled = platformAvailable && userEnabled`。协议和自定义插件只有平台状态。用户停用工作流插件后禁止新任务进入,但已经接收的任务和 Bridge 结果回传继续完成;管理员停用属于平台硬上限,同样不强行破坏已进入执行阶段的任务。
## 8. Eagle 外部素材来源方案
Eagle 插件的主分类是“素材与数据连接器”,可以附带一个 `EagleAsset` 画布节点。
### 8.1 连接器职责
- 使用 Eagle 本地 API(默认 `http://127.0.0.1:41595`)检查服务并读取当前素材库。
- 在影策素材页进入 Eagle 专属素材管理页面,按 Eagle 的父子文件树浏览和搜索文件。
- Eagle 文件仍由 Eagle 管理,影策只通过外部素材来源读取、下载和使用,不要求逐个选择或复制成本地素材。
- 在当前 Eagle 文件夹中新建文件夹,并把本地图片、视频和音频直接写入 Eagle。
- 返回 Eagle 素材 ID、文件夹 ID、完整文件夹路径和来源信息,供影策项目保存外部引用。
- 通过影策后端本地桥接读取 Eagle 文件,避免浏览器直接打开 Eagle 的本机文件路径。
### 8.2 画布节点
`EagleAsset` 节点只保存可迁移的引用信息和展示 metadata,不把 Eagle 的完整文件内容塞进画布 JSON:
```ts
type EagleAssetMetadata = {
assetId: string;
libraryId?: string;
folderId?: string;
title: string;
tags: string[];
sourceUrl?: string;
syncedAt?: string;
};
```
节点可以提供:
- 预览缩略图。
- 标签、尺寸和来源展示。
- 导入本地资源副本。
- 在 Eagle 中打开。
- 更新节点中的 Eagle metadata。
- 将当前生成结果上传到 Eagle。
### 8.3 Eagle 权限
第一版建议只申请:
```text
asset.read
asset.search
asset.upload
external.open
```
删除 Eagle 资源、批量覆盖和修改原始文件属于高风险权限,应单独申请并逐次确认,不能包含在普通 `asset.write` 中。
### 8.4 推荐交互
首版提供外部素材库浏览和双向写入:
```text
Eagle 文件树 / 搜索 → 打开素材 → 在影策中使用外部引用
影策上传图片、视频或音频 → 选择 Eagle 目标文件夹 → 写入 Eagle
影策生成图片、视频或音频 → 插件自动归档到 Eagle 目标文件夹
```
### 8.5 当前实现边界
- 素材页的“Eagle 素材库”进入插件专属页面,不使用抽屉,也不要求选择素材。
- 左侧文件树直接继承 Eagle 的父子层级;影策保存外部引用时保留 Eagle 素材 ID、文件夹 ID 和路径信息。
- 图片、视频、音频和模型可以从 Eagle 直接浏览、搜索和读取;当前不把文本类内容转换成影策文本素材。
- 当前支持将本地图片、视频和音频写入 Eagle 当前文件夹;生成结果可以在插件设置中开启自动归档并指定 Eagle 文件夹。影策仍保留本地素材记录,外部写入成功或失败会记录到素材 metadata。实际可写入格式由本机 Eagle 版本/API 决定;如果 Eagle 拒绝某种媒体,影策保留本地结果并记录失败状态。删除、批量覆盖和冲突解决仍需后续权限设计。
- Eagle 地址只允许本机默认端口,后端会校验本机地址和文件路径,避免把连接器变成任意内网访问代理。
- Eagle 文件夹不会复制成影策项目中的独立资产文件夹;页面以 Eagle 原始文件树作为外部来源视图。自动归档默认使用 Eagle 根目录,用户可以在插件设置中关闭或改用具体文件夹。
## 9. 安全边界
当前远程 JavaScript 插件如果直接在页面上下文执行,可能接触页面可见数据和本地配置。因此正式开放第三方插件前必须完成以下事项:
- 插件默认无权限,按能力逐项授权。
- API Key、登录 Cookie 和后端会话不得通过通用插件 API 暴露。
- 外部请求优先经过宿主服务或明确的连接器 API。
- 远程产物支持完整性校验、版本锁定和撤销。
- 插件错误不能吞掉,必须记录插件 ID、版本和可读错误。
- 公开市场只允许可信来源;组织内部插件可使用私有注册表。
- 高风险写入、上传、删除和外部同步必须有用户确认。
长期方向是将不可信插件放入 iframe、Worker 或 Capability 沙箱,避免插件默认拥有宿主页面权限。
## 10. 开发者接入流程
后续应提供一个独立 SDK 和模板,使开发者可以:
1. 创建插件模板。
2. 安装 SDK 和类型定义。
3. 在本地启动 watch 构建。
4. 使用宿主提供的模拟画布和测试数据验证插件。
5. 生成插件清单和构建产物。
6. 发布到静态地址或组织注册表。
7. 在影策的插件管理器中通过 URL 安装。
推荐目录:
```text
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。
- 插件错误和权限拒绝能够显示给用户。