Skip to content

feat(plugins): 模型服务 - 插件接入的服务可以自己列出模型 - #408

Merged
enderzcx merged 6 commits into
mainfrom
feat/plugin-provider-models
Nov 6, 2026
Merged

enderzcx merged 6 commits into
mainfrom
feat/plugin-provider-models

Conversation

@enderzcx

@enderzcx enderzcx commented Nov 5, 2026

Copy link
Copy Markdown
Collaborator

接在 #407 后面(base 是 refactor/plugin-manifest-one-way)。

为什么

插件可以用 JS 接入生成服务(#405),但用户在「模型服务」里添加它时,「读取模型」只会去请求 OpenAI 格式的 /models。ComfyUI、RunningHub 这类服务没有这个接口,用户只能自己去查、手动填模型 ID。而且添加服务时,列表里也看不到插件带来的服务,得选「第三方模型服务」,再在模型上一个个改协议。

改了什么

插件可以列出模型

  • 插件的 JS 生成接口可以多导出一个 models(ctx),返回 [{ id, displayName, capability }]。只接一种能力的服务可以不写 capability。
  • POST /api/ai/models 新增 protocol 参数。它指向插件 JS 接口时,后端改由插件列模型:不请求 /models,也不要求 API Key。
  • 插件没写 models 时返回 catalog_unsupported,界面照旧提示手动添加模型。

插件服务出现在「选择服务商」里

  • 插件目录多返回 module 标记。「模型服务 → 选择服务商」里,每个插件 JS 服务单独列一项,下面写「插件提供」。
  • 选中后,渠道的默认接口就是这个插件。读到的模型会自动用它生成,不用再逐个选协议。
  • 选中插件服务时,隐藏「模型目录地址」和「目录接口格式」,这两项只对 /models 有意义。
  • 服务声明 auth.type: none(比如本机 ComfyUI)时,还没选模型也能直接读取模型,密钥栏提示「这个服务不用密钥,可以留空」。

其它

  • 插件宿主的超时表里,原来有 cancel 的 30 秒,但这个方法从来不会被调用;换成 models 的 25 秒,和读取 /models 的时限一致。
  • SDK 类型(ProviderModule.models、ProviderModel)、插件开发文档第 5 节、HTTP 接口文档都已补上。

没做的:插件设置存后端

原计划这一步还要「插件设置改由后端保存」。查下来不需要:

  • 生成类插件的地址和 Key 填在模型服务(渠道)里。渠道配置本来就由后端加密保存,插件 JS 生成接口也已经从渠道拿到这两项。
  • 再加一份插件设置存储,生成类插件就会出现两处设置,反而是想解决的问题。

等 ComfyUI 或 RunningHub 插件真的需要渠道以外的设置时,再按实际需要补。

验证

  • 后端:go test ./internal/generation/ ./internal/plugins/ ./internal/pluginhost/ ./internal/protocol/ ./internal/handler/ ./internal/workspace/ 全部通过;./internal/app/ 里模型目录相关的 45 个测试(-run 'Catalog|ChannelModel')通过。
  • 新增后端测试,用真实的插件宿主进程跑插件 JS:
    • 插件渠道读取模型只问插件,不请求 /models;
    • 空 ID 和重复 ID 会被去掉;
    • 没写 capability 时用服务唯一的能力;
    • 插件报错时返回 catalog_upstream_failed,并带上插件的原话;
    • 插件没写 models 时返回 catalog_unsupported。
  • 新增前端测试:
    • 插件服务只列一次,停用的不列;
    • 选中后渠道带上插件接口;
    • 不要密钥的服务不填 Key 也能读取模型,提示文案正确;
    • 要密钥的服务仍然要求填 Key;
    • 读到的模型自动用插件接口。
  • web:bun run build、bun run lint、tsc --noEmit 通过。前端全量测试在后一个 PR 的分支上跑过(包含本 PR 的改动),结果写在那个 PR 里。
  • 清单里只写 "auth": { "type": "none" } 的 module provider 可以正常加载(实际加载验证过)。

还没验证:没有在浏览器里实际点过「选择服务商」里的插件项。界面改动只做了构建、类型检查和单元测试。ComfyUI 插件 PR 会在浏览器里用真实的本机 ComfyUI 走一遍。

合并前

改了「模型服务」弹窗的界面和文案,需要交叉 review。

🤖 Generated with Claude Code

Sunny and others added 6 commits November 5, 2026 11:41
插件清单里声明过、但没有任何代码执行的字段一并删除:
- 运行方式 rpc、wasm、host:(后端只校验、从不执行)与 runtime.backendEntry
- .beeftv-plugin 包的 entry 网页入口、runtime.web 的 sandbox/worker,以及包内 web/、backend/ 目录
- 贡献点 transforms、commands、assetSources、usageObservers、aiCapabilities、agents、importExport(只用于插件页标签)

前端插件注册不再重复检查"至少声明一种贡献能力",安装来的插件由后端统一校验;
内置的 Eagle、提示词优化、媒体转换不再为过这条检查而声明空贡献点,插件卡片上对应的标签随之不显示。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
插件的生成接口除了声明式 JSON,现在可以在 provider 里写 module,指向包内的 JS 文件,
由插件自己发请求。做法照 Magpie 的插件宿主:后端用自带 Node 起一个后台子进程
(agent-host/plugin-host.mjs),按行收发 JSON,按 id 配对,取消时发 abort;
同一插件换了版本时新调用进新进程,旧进程处理完手上的调用后退出。

后端规则不变:
- 恢复的任务只调用 query,不再调用 submit
- submit 抛错时按"提交结果不明"处理,不自动重试
- 每次插件调用像上游请求一样记入调用日志,任务号沿用同一条回执规则记下
- 结果地址由后端下载入库

只有 npm、本地目录或 .tgz 安装的插件能带 JS;.beeftv-plugin 归档里的 module 接口标为不可用。
开发文档补充了 module 的写法与约定。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 上传插件弹窗原来写"Web 入口只能进入声明的隔离运行时,不会获得主页面权限"。
  实际插件界面代码直接加载进主页面,没有隔离;改成和安装确认框一致的说法,图标改为警示。
- 插件开发和插件体系文档的清单示例把画布节点写在 beeftv.canvasNodes,
  前后端只读 beeftv.contributes.canvasNodes,照抄这部分不生效;改到 contributes 下。
- 示例去掉代码不读或会自动从 package.json 取的字段(id、version、schemaVersion 等)。
- 去掉"可安装 @beeftv/plugin-sdk":这个包还没发布到 npm,照做会安装失败。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- npm 插件的 beeftv 只认 name、client、surfaces、permissions、configuration、
  contributes;ID、版本、说明、作者取自 package.json。写了旧键或放错位置的键时,
  安装和更新会拒绝并逐项说明怎么改。已装好的插件不在启动时重查。
- 设置项字段只认 name / default / values,key、defaultValue、options 会被指出。
- 6 个自带 npm 插件改成新写法并升补丁版本。
- 从本地目录安装的插件,更新按钮显示为「重新加载」。重新复制目录后,安装包指纹
  进入浏览器端入口地址和插件宿主进程的键,同一版本号也会换上新代码;
  清单不合格时保留原来装好的版本。
- SDK 类型和说明改成同一种写法,补上 JS 生成接口 submit / query 的类型;
  示例改成 JSDoc,因为插件文件由 BeefTV 直接加载,不能 import 包名。
- 文档删掉不会被调用的 cancel,说明取消任务时不会通知服务商。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
handler 的安装和技能同步测试还用旧的 beeftv.id、displayName、节点 type 等写法,
新检查会拒绝安装。改成包名即插件 ID、节点写 id/label/defaultTitle/defaultSize。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 插件 JS 生成接口可以多导出 models(ctx)。渠道默认接口是插件 JS 接口时,
  「读取模型」由后端交给插件,不再请求 /models,也不要求 API Key;
  插件没写 models 时返回 catalog_unsupported,用户照旧手动添加模型。
- 插件目录标出 module 接口;「模型服务 → 选择服务商」把它们各列一项(插件提供),
  选中后渠道默认接口就是这个插件,读到的模型自动用它生成。
- 不要密钥的插件服务(auth.type 为 none)还没选模型时也能直接读取模型,
  密钥栏提示改成「可以留空」。
- 插件宿主去掉从不调用的 cancel 超时,换成 models 的 25 秒。
- SDK 类型、插件开发文档和 HTTP 接口文档补上 models。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant