Skip to content

清单 ​

manifest.json 是插件的唯一事实来源。宿主在安装时解析它,以获知插件的身份、如何启动其 worker、挂载什么 UI、允许它做什么,以及它暴露哪些 AI 工具。它位于 .fyp 归档的根目录。

Schema 参考 ​

字段类型必填默认值说明
schemaVersionnumber是—清单 schema 版本。当前为 2。
idstring是—反向 DNS 的插件 id,例如 fan.summer.excel。在已安装插件中必须唯一。
namestring是—人类可读的显示名。
descriptionstring是—在市场与插件列表中展示的一行描述。
versionstring是—SemVer 风格的版本字符串,例如 4.0.0。
authorstring是—作者或组织名。
iconstring是—图标标识符(一个 Vuetify/Material 设计图标名,例如 file-excel)。
categorystring是—合法 category 取值之一。
uiobject是—UI 子记录。见 ui。
backendobject否—Worker 子记录。见 backend。可选——纯 UI 插件可省略它。
enginesobject否—宿主兼容性。engines.fengyu 使用如 >=4.0.0-beta.4 <5.0.0 的 SemVer 范围;不兼容包在解压前被拒绝。
rpcobject否—RPC 方法表。见 rpc.methods。声明每个方法的 inputSchema/outputSchema(JSON-Schema 对象)。
permissionsstring[]否[]声明的权限。驱动文件 I/O 授权。
homepagestring否—指向插件主页或源码仓库的 URL。
officialboolean否false由 OfficialPluginSeeder 预置的插件设为 true;将描述符的 source 设为 OFFICIAL。
aiToolsobject[]否[]声明的 AI 工具。空数组表示 supportsAi = false。
i18nobject否—manifest 与 AI 工具显示文案的 locale 覆盖。
flowNodesobject[]否[]一等流程画布节点描述符。

ui ​

字段类型必填说明
entrystring是相对于归档根的入口 HTML 路径,通常为 ui/index.html。通过 /plugin-runtime/{id}/<entry> 提供。

backend ​

字段类型必填说明
runtimestring否java(默认)、python 或 go。可执行文件及制品约定由宿主持有,绝不接受任意命令。
protocolVersioninteger否新插件设为 1,启用保留的启动握手;仅遗留 Java 包可省略。
callTimeoutSecondsinteger否插件级的默认每次调用超时(秒)。会被钳制到 [1, 600]。省略时宿主使用 60。aiTools[].timeoutSeconds 会针对单个工具覆盖此值。
resources.memoryMbinteger否Worker 进程树常驻内存上限,64–8192 MiB;Linux/macOS 由宿主监控,Windows 由 Job Object 内核限制强制。
resources.maxProcessesinteger否Worker 进程树总进程数上限(含 worker),1–64。

约定制品分别是 Java 的 backend/worker.jar、Python 的 backend/worker.py、Go 的 backend/worker(Windows 为 worker.exe)。三种 runtime 都通过 stdio 上换行分隔的 JSON-RPC 2.0 通信,不再在清单中声明启动命令。设置 protocolVersion: 1 后,宿主先调用保留的 $/fengyu/initialize,校验返回的协议与 runtime,再把插件标为健康。

rpc.methods ​

插件暴露的 JSON-RPC 方法表,以方法名为键。每个方法自带其参数与输出的 JSON Schema——是真正的 JSON-Schema 对象,而非转义字符串。Java Worker SDK 与 TypeScript UI 客户端均从该表生成类型化绑定。

字段类型必填说明
descriptionstring否方法的简短描述。
inputSchemaobject是描述方法参数的 JSON Schema 对象。
outputSchemaobject否描述 Worker 结果信封的 JSON Schema 对象。

aiTools[].method 必须在此表中存在;fengyu CLI 在 check/build 时会校验二者一致。

aiTools[] ​

每一项声明一个 AI 可调用的工具,宿主会把它们聚合成其 Spring AI 的 ToolCallback[]。参数与输出 Schema 不再内联——它们声明在 rpc.methods 中;aiTools[] 只携带工具的面向模型的元数据与副作用分类。

字段类型必填说明
namestring是暴露给模型的工具名。
descriptionstring是给模型的自然语言描述。
methodstring是当模型调用此工具时要调用的 worker JSON-RPC 方法(必须在 rpc.methods 中存在)。
effectstring是审批分类:read、write 或 external。
idempotentboolean否仅当重复完全相同的写入/外部调用不会产生重复副作用时设为 true,从而允许工作流重试;只读工具自动可安全重试。默认 false。
timeoutSecondsinteger否针对此工具的调用超时(秒),钳制到 [1, 600]。覆盖 backend.callTimeoutSeconds。默认 60。可能超过其声明超时的工具必须拆分为 *_start / *_status / *_cancel 的 job 方法——参见 Worker → 长任务(job 模式)。

端到端流程见 AI 工具。

flowNodes[] ​

面向 Flows 流程构建器的显式画布节点声明。带 flowNodes 声明的工具在画布上呈现为 一等节点——类型化端口、示例值、帮助文案、自定义控件;未声明的工具仍会出现在调色板 「显示全部工具」开关之后,作为按 Schema 推导的降级节点。

字段类型必填说明
toolstring是该节点渲染并执行的 aiTools[].name。
labelstring否卡片标签(缺省为工具名的人性化形式)。
kindstring否action(默认)/ control / start —— 画布结构节点的保留字。
helpstring否节点级帮助,展示在检查器的帮助区。
docsUrlstring否外部文档链接。
colorstring否卡片十六进制颜色。
iconstring否徽章的 MDI 图标名。
inputs[]array否声明的输入,见下。
outputs[]array否命名输出端口,见下。

可执行输入契约由所引用 RPC 的 inputSchema 唯一拥有:每个 Schema 属性都会出现在检查器中, 无需重复填写类型、必填或默认值。可选的输入 UI 增量以 name 开头,可增加 widget (text / number / switch / select / textarea / json / analyze / rows)、 title、description、help、placeholder、examples[]、 advanced(折叠进高级设置)、options[](select 用——纯字符串或 {value, label} 对以支持本地化标签)、source(从插件列表 RPC 加载选项)、context (分析式编辑期数据集)与 fields[](rows 控件的每行字段)。没有增量时,UI 会从 Schema 推断普通控件。fengyu check 会把每个增量名称及控件与 RPC Schema 交叉校验,并拒绝增量 中的 type、required、default;这些可执行字段只能存在于 RPC JSON Schema 中。

每个输出 UI 增量携带 name,并可增加 title、description / help、examples[]。 对象或数组输出还可递归增加只负责显示的 properties / items,用于标注 confirmation.confirmationId、files[0] 等路径;字段是否存在及其类型仍来自 outputSchema。

locale 条目还可包含按工具名索引的紧凑 flowNodes 对象;其中 inputs/outputs 再按规范 端口名索引,只覆盖标题、帮助、选项、示例、嵌套 fields 和输出 properties 等显示字段, 不会重复或改变 RPC 类型。fengyu check 与宿主安装都会拒绝不存在的工具、端口或属性键。

完整词表定义在 toolchain/spec/manifest.schema.json (flowNode、flowNodeInput、flowNodeOutput、flowOutputProperty 定义);宿主的 flow-nodes/builtin.json 以 flow-node.schema.json 校验。

合法 category 取值 ​

category 是一个自由格式的提示性字符串,UI 用它来对插件分组——宿主不会校验它是否属于某个固定集合(它只会把你写的值转为大写,为空时默认为 OTHER)。为保持一致,请使用以下约定取值之一:

取值用途
dev开发者工具
text文本编辑/渲染(例如 fan.summer.markdown)
image图像处理
net网络相关
network网络相关(例如 fan.summer.email)
file文件处理(例如 fan.summer.excel)
ai以 AI 为中心的插件
other上述未涵盖的任何类型(脚手架的默认值)

合法权限 ​

permissions 是一个数组,包含零个或多个以下规范集合中的值,由 CLI 与宿主共同强制执行:

取值授权
files.readPOST /api/plugin-runtime/{id}/files/upload、upload-directory、native(读访问)
files.writePOST .../files/native(写访问)、POST .../files/output、GET .../files/export/{ref}
network来自 worker 的通用出站网络访问。
network.emailworker 可以建立 SMTP/IMAP 连接(fan.summer.email 使用)。
clipboard.read读取宿主剪贴板。
clipboard.write写入宿主剪贴板。
notifications声明性:插件可发出通知。notify 桥不再读取该 token——所有插件的 notify 一律走统一宿主管线(保留接受以兼容既有 manifest)。
database宿主向 worker 环境注入数据库连接坐标(FENGYU_DB_* —— type/driver/url/username/password —— 以及一个私有数据目录),以隔离 DB 用户/schema 形式 provision;由 worker 自行建立连接。参见插件数据库规范。
screen.capture桌面插件 UI 可以调用 getDisplayMedia。只有声明该权限时,宿主才会给 iframe 授予 display-capture;Electron 的独立处理器只暴露整屏源,不暴露摄像头、麦克风或单个窗口。macOS 另外要求宿主应用拥有系统“屏幕录制”权限。

fengyu dev 模拟器应用同一 manifest 闸门,因此插件可以在打包前验证屏幕捕获链路。

任何其他取值在 validate 与 install 时都会被当作未知权限拒绝。在缺少对应权限的情况下尝试文件操作会被以 403 拒绝。参见 文件 I/O。

强制力度并不一致(P1-9)。 不要假设每个被接受的权限都被同等强制执行:

  • 由宿主/OS 沙箱强制: files.read、files.write(FileRef 授权闸门)、network(OS 网络命名空间)、screen.capture(桌面 iframe Permissions Policy + 仅屏幕的 Electron display-media 处理器)。
  • 在网络层按全量出站放行(advisory): network.email、database 目前授予宽泛的出站网络——宿主尚未代理 SMTP/IMAP,也未限制 DB 只连特定主机。真正的邮件/DB 代理是一项已立项的后续工作。
  • 声明性(不强制): notifications。所有插件的 notify 调用一律走统一宿主管线 (应用内 toast + 原生桌面通知 + 持久化通知中心)——此前的门控会把未声明权限的插件 路由到 iframe 内部兜底,而其 snackbar 用户实际看不到。token 仍被接受以兼容既有 manifest,仅作为意图声明。
  • 仅声明(尚无宿主强制): clipboard.read、clipboard.write 只是为未来到桌面外壳的 capability 桥接声明意图,运行时当前不读取。

在任何汇总插件权限的 UI 中都要如实呈现——不要对 network.email/database 暗示比 OS 实际强制更细的网络隔离。

示例 ​

Markdown 插件 ​

fan.summer.markdown 的清单——一个无权限、无 AI 工具的文本插件:

json
{
  "schemaVersion": 2,
  "id": "fan.summer.markdown",
  "name": "Markdown Editor",
  "description": "Split-pane Markdown editor with isolated server-side rendering",
  "version": "4.0.0",
  "author": "FengYu",
  "icon": "language-markdown",
  "category": "text",
  "ui": { "entry": "ui/index.html" },
  "backend": { "callTimeoutSeconds": 30 },
  "permissions": [],
  "homepage": "https://github.com/MuskStark/FengYu",
  "official": true,
  "rpc": {
    "methods": {
      "render": {
        "description": "Render Markdown source to sanitized HTML via commonmark.",
        "inputSchema": {
          "type": "object",
          "properties": {
            "markdown": { "type": "string", "description": "The Markdown source to render." }
          },
          "required": ["markdown"]
        },
        "outputSchema": {
          "type": "object",
          "properties": {
            "success": { "type": "boolean", "description": "true when the render completed." },
            "summary": { "type": "string", "description": "Short localized result summary." },
            "html": { "type": "string", "nullable": true, "description": "The rendered, sanitized HTML." }
          },
          "required": ["success", "summary"]
        }
      }
    }
  }
}

Excel 插件(含 aiTools) ​

fan.summer.excel 的清单——一个带读写权限和 AI 工具的文件插件。这里完整展示两个方法:excel_analyze(短时同步调用),以及 excel_execute_start(长时拆分 job 模式对的启动半边)。参数与输出 Schema 是 rpc.methods 里的 JSON-Schema 对象;aiTools[] 只引用方法名并声明副作用:

json
{
  "schemaVersion": 2,
  "id": "fan.summer.excel",
  "name": "Excel Splitter",
  "description": "Split Excel workbooks by sheet, column value, or complex rules",
  "version": "4.0.0",
  "author": "FengYu",
  "icon": "file-excel",
  "category": "file",
  "ui": { "entry": "ui/index.html" },
  "backend": { "callTimeoutSeconds": 60 },
  "permissions": ["files.read", "files.write"],
  "homepage": "https://github.com/MuskStark/FengYu",
  "official": true,
  "rpc": {
    "methods": {
      "excel_analyze": {
        "description": "Analyze the granted Excel workbook; returns sheet names.",
        "inputSchema": {
          "type": "object",
          "properties": {
            "filePath": { "type": "string", "description": "Resolved absolute path of a readable FengYu FileRef." }
          },
          "required": ["filePath"]
        },
        "outputSchema": {
          "type": "object",
          "properties": {
            "success": { "type": "boolean" },
            "summary": { "type": "string" },
            "sheets": { "type": "array", "items": { "type": "string" } }
          },
          "required": ["success", "summary"]
        }
      },
      "excel_execute_start": {
        "description": "Launch the configured split as a background job and return a jobId immediately. Poll excel_execute_status with a cursor to drain progress logs.",
        "inputSchema": {
          "type": "object",
          "properties": {
            "outputDir": { "type": "string", "description": "Resolved absolute path of a writable FengYu DirectoryRef." },
            "filePrefix": { "type": "string" }
          },
          "required": ["outputDir"]
        },
        "outputSchema": {
          "type": "object",
          "properties": {
            "success": { "type": "boolean" },
            "summary": { "type": "string" },
            "jobId": { "type": "string" }
          },
          "required": ["success", "summary"]
        }
      }
    }
  },
  "aiTools": [
    { "name": "excel_analyze", "method": "excel_analyze", "effect": "read", "description": "Analyze the granted Excel workbook; returns sheet names.", "timeoutSeconds": 30 },
    { "name": "excel_execute_start", "method": "excel_execute_start", "effect": "write", "description": "Launch the configured split as a background job and return its job ID.", "timeoutSeconds": 30 }
  ]
}

inputSchema/outputSchema 是真正的 JSON-Schema 对象(不再是转义字符串)。aiTools[] 只携带 name/method/effect/idempotent/description/timeoutSeconds——参数与输出 Schema 统一声明在 rpc.methods 中,宿主据此构建 Spring AI 的 ToolDefinition。

代码优先清单(manifest.base.json) ​

插件可以从 Java、Python 或 Go 源码声明 RPC 契约,而不必手写 rpc.methods/aiTools JSON。 新建的 Worker 脚手架默认采用代码优先,并用以下文件替代 manifest.json:

text
manifest.base.json        身份、ui、backend、权限…(不允许 rpc/aiTools/flowNodes/i18n)
manifest/flow-nodes.json  Flow overlay(只允许 flowNodes)
manifest/i18n/<locale>.json
worker/... 契约源码       Java 注解、Python dataclass 或 Go struct

Java 由 DevKit 注解处理器(fengyu-plugin-devkit,以 proc:only 绑定到 generate-resources)提取;Python 以 dataclass + Annotated[..., Field(...)] 配合 Contract.rpc(...) 声明;Go 以带标签的 struct 配合 NewContract(...).RPC(...) 声明。 各语言的小型生成器写出相同 IR。CLI 将 base + IR + overlay + i18n 合并为 .fyp 内唯一一份完整的根 manifest.json(安装契约不变)。 两种编写模式不得共存——fengyu check/build 在 manifest.json 与 manifest.base.json 同时存在时直接失败。同一份源码连续编译产生字节级一致的结果。

主要注解:@FengYuContract(接口)、@FengYuRpc(方法名、描述、超时)、 @FengYuAiTool(AI 暴露 + effect)、@FengYuField(描述/必填/可空/默认值/主机文件 format+fileAccess 等)、@FengYuSensitive(禁止记录与透传)。不支持裸 Map、未界定泛型、 递归或多态 DTO——直接编译失败,绝不静默退化为无约束 object。三种运行时都用 fengyu generate 完成各自的提取、合并与类型化客户端/方法常量再生成。

引用上游节点的实际输入 ​

Flow 步骤直接暴露模板解析后的实际调用参数,无需声明合成输出。下游参数可这样引用:

json
{ "attachmentDirectory": "{{steps.0.input.outputDirectory}}" }

画布表单生成等价的编写期语法 {{node.<id>.input.outputDirectory}},保存时编译为步骤索引形式。 .input 与 .result 都支持点分路径和 [N] 数组下标。敏感参数名及 Schema 标记字段会从 实际输入快照中过滤,无法解析;缺失路径会明确报错,不会静默变成空字符串。

下一步 ​

Released under the GPL-3.0 License.