Skip to content

feat(provider): 供应商配置与模型路由重构——预设注册表、四类接口、多 Key / 多源地址、模型目录 - #825

Draft
yovinchen wants to merge 66 commits into
mainfrom
feat/provider-registry-routing
Draft

yovinchen wants to merge 66 commits into
mainfrom
feat/provider-registry-routing

Conversation

@yovinchen

@yovinchen yovinchen commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

Closes #826
Closes #723

把供应商配置从"五个写死的类型"改造成预设注册表 + 四类聊天接口 + 分层模型目录,并补齐多 Key、多源地址、四层故障转移与连通性测试。设计文档见 docs/design/provider-registry-and-model-routing.md(含实施记录与审查修复附录)。

主要变化

接口与路由

  • 聊天接口收敛为四类:Anthropic Messages、OpenAI Chat Completions、OpenAI Responses、Gemini generateContent。xAI 与 DeepSeek 是 Responses 上的厂商实现差异,不是独立协议。
  • 一个供应商可同时挂多个接口端点,各自独立配置地址、厂商实现、鉴权头、凭据、请求头、兼容开关与身份模拟。
  • 模型只显式选一个接口,可选范围按渠道限定:原生渠道取预设声明(Anthropic 固定 Messages、Gemini 固定 v1beta、OpenAI 在两类间切换、xAI 只有 Responses);其它渠道为 OpenAI 两类 + Messages,Gemini 系列再加 v1beta。
  • 端点地址无版本段时自动补 /v1(Gemini 补 /v1beta),以 # 结尾则原样使用。

预设注册表

  • 47 个渠道预设,数据由 models.dev 生成 + 覆盖层维护,新增渠道只加数据不加代码分支。
  • 覆盖原生五家、国内厂商(智谱、MiniMax、Kimi、通义、火山、阶跃、腾讯、百度、小米、美团、商汤、讯飞)、聚合站与本地服务,以及各家 Coding / Token / Step Plan 套餐渠道。

模型元数据目录

  • 唯一来源是随包生成的目录(41 个分区、924 个模型),由 models.dev 与 Codex models.json 派生,CI 每日刷新开 PR。
  • 字段含上下文 / 最大输入 / 最大输出、输入与输出模态、思考档位、工具调用、结构化输出、附件、知识截止、发布与更新日期、状态、原生价格(仅展示,不计费)。
  • 厂商渠道的模型列表直接用目录,探测不再请求 /models;中转与聚合站仍走探测,相同地址去重只发一次。
  • 能力与限额按"用户覆盖 > 目录 > 供应商 > 启发式"分层,每项带来源,可一键还原。

多 Key、多源地址与故障转移

  • 一个供应商可配多把 Key,各带模型范围;路由按范围选 Key。
  • 供应商级源地址列表 + 端点 {origin} 模板:同一渠道的多个入口主机(Key 与接口相同、只有主机不同)不再靠复制实例表达。
  • 故障转移四层:凭据 → 源 → 端点 → 供应商,共用切换预算,按接口家族分组;鉴权失败不换源,熔断键带源主机。

设置界面

  • 三栏:渠道目录 / 供应商详情 / 抽屉。模型列表支持文档、收起、搜索、按能力与接口过滤、分组内拖拽排序、分组一键删除。
  • 每个模型可单独做连通性测试(按解析出的路由发一次最小请求),多 Key 时逐把测并聚合。
  • 编辑模型按属性归一:目录值、有效值、覆盖三列并排。
  • 探测采纳的模型默认关闭,由用户逐个启用。

图像生成

  • 新增模型类型 chat | image:目录输出模态含图片即生图模型,可手动覆盖;生图模型不进入聊天选择器。
  • 生图不走四类聊天接口(pi-ai 的聊天流没有图片输出),做成内置工具 generate_image + 独立调用:OpenAI 兼容渠道走 /images/generations(gpt-image、dall-e,中转普遍支持),Gemini 渠道走 generateContent 带 responseModalities;地址、Key、请求头、源地址展开与版本段规则全部复用现有路由。
  • 桌面走 Rust 命令 provider_generate_image / provider_download_image,WebUI 走网关桥(按凭据补 Key、主机白名单)。图片存进工作区并以图片块返回,聊天里直接可见;可设全局"生图默认模型"。
  • 目录不再跳过纯图片输出模型(新增 gpt-image 系列、grok-imagine 等 16 条);连通性测试对生图模型跳过(生成有成本)。

设计缺口补齐

  • 字段候选与冲突采纳:能力与限额每个字段带候选列表(目录 / 供应商 / 适配器 / 启发式),目录值与供应商声明不一致时显示"冲突"并可一键采纳;供应商声明来自模型列表接口返回的元数据,刷新时更新但不自动覆盖有效值。
  • 模型级请求参数覆盖:temperature、maxTokens 全接口;topP 仅 OpenAI 两类(pi-ai 只对它们透传采样参数);按接口钳制范围,未知键丢弃。
  • promptCaching 能力接到缓存保留判定;parallelTools 因四类接口无任何消费者而移除。

Screenshots / preview

供应商详情:多 Key 列表、四类接口端点、模型列表工具栏与连通性测试

供应商配置总览

编辑模型:目录信息一行摘要,能力与限额按"目录值 / 有效值 / 覆盖"三列归一

编辑模型抽屉

模型目录浏览器:来源、快照日期、搜索与筛选,条目含模态、能力位、限额与价格

模型目录

厂商渠道的"检测并配置":模型列表随应用内置,不请求任何接口

探测并配置

验证

项目 结果
前端全量测试 3283 / 3283
网关 WebUI 测试 718 / 718
Rust settings / gateway_bridge / provider_models / provider_check / image_generation 108 / 26 / 19 / 9 / 8
三包类型检查、lint、UI 边界检查、目录快照校验 通过

桌面端实机核对了探测与采纳、多 Key 列表、模型连通性测试、源地址模式、模型目录浏览与各抽屉布局。

兼容性

旧存档全部可选字段:凭据缺省为单把默认 Key、预设按地址主机归属、默认接口由旧类型回填、没有源地址的实例保持单地址模式。写入时同步维护旧字段,旧版本仍可读。

- 新增 lib/providers/registry:四类接口/家族/方言与请求头档、模型家族表、
  从 models.dev 派生的预设(scripts/generate-provider-presets.mjs)与覆盖层
- 设置类型:端点完整配置(启用/方言/quirks/鉴权/凭据/头/探测观测)、多 Key
  与模型范围、模型级远端 ID/分组/接口列表/方言/凭据/默认档/能力覆盖、
  故障转移按接口家族分组(旧五组合并迁移)
- 路由函数输出协议来源/家族/方言/远端 ID/凭据/合并头/quirks;
  deepseek-responses 改写为 Responses + deepseek 方言
- 探测与自动配置模块(providerProbe.ts)与模型列表拉取的状态码错误
- Gateway 同步与 Web 存储脱敏覆盖多 Key
- 公开快照脱敏扩展到 credentials[] 每把 Key,只保留 apiKeyConfigured;
  save_providers 收到脱敏形状时按供应商 id / 凭据 id 回填已落库 Key,
  首把凭据缺失时退回默认 Key,configured=false 仍视为明确清空
- 备份导出剥离端点 lastProbe 与凭据 lastModels,落库数据不受影响
- Gateway 供应商摘要补 presetId / category / enabled / dialect /
  defaultChatProtocol / modelOrder,endpointConfigs 只带 enabled / dialect /
  quirks / source,凭据列表整体不进摘要
- Cherry Studio 导入回传全部 Key,前端映射 presetId / category /
  defaultChatProtocol / dialect / endpointConfigs / credentials
- ProviderRuntimeConfig 增加 protocol / dialect / family / modelId / wireModelId /
  credentialId / endpointHeaders / quirks / authOverride,由 resolveProviderChatRoute
  一次填充;apiKey 取路由选中的凭据,customHeaders 用供应商级与端点级合并结果;
  模型级 reasoning 覆盖会话档并钳到该模型档位,模型级 nativeWebSearch 覆盖开关
- 请求头改为查表:协议头档(buildProtocolAuthHeaders,端点 auth 可覆盖)→ 方言头档
  (Responses+openai 的 Codex 会话头、anthropic-messages 的 SDK 指纹头)→ 用户头;
  DeepSeek 端点路径规范化只在 (Responses, deepseek) 触发
- 模型工厂按 (protocol, dialect) 构造 Model:Model.provider 填方言 id 让 pi-ai
  detectCompat 生效,quirks 映射到 compat 同名键,Model.id 用 wireModelId、本地 id
  继续用于目录 / 熔断 / 展示;删除与 detectCompat 重复的域名判断(api.z.ai /
  openrouter / groq / chutes 等),旧签名 createModelFromConfig 保留为兼容入口
- payload 中间件、原生搜索注入、缓存形态描述改读 (protocol, dialect),
  adapterProviderId 只作兜底
- 故障转移按路由 family 分组,候选按凭据层 → 端点层 → 供应商层展开并共用一份
  maxSwitches;enabled 只控制供应商层;熔断 key 扩展为
  provider::credential::protocol::model(旧调用保持 provider::model)
- 新增 provider-route-runtime 与三层候选用例;五类旧配置的 Golden 逐字节不变
- 左栏渠道目录由注册表驱动:已配置实例在前,未配置渠道灰显并可直接填 Key
  "检测并启用";同一渠道可有多个实例;"添加渠道"对话框按四类接口填地址,
  即时显示实际请求路径,可从预设填入接口与地址
- 中栏详情:名称/启用/预设与分类;默认 Key 与"管理密钥";默认接口地址、探测
  状态芯片、"检测并配置"与已启用渠道标签;模型按分组折叠,行内能力图标、
  接口/方言/远端 ID/Key 范围标签;更多设置、按接口家族的故障转移、用量查询
- 抽屉:请求配置(每个接口一张卡片:启用、探测、默认、地址、方言、鉴权头、
  凭据、quirks、端点请求头;供应商级请求头与模拟 CLI)、管理密钥(多 Key、
  模型范围、用此 Key 重新拉取)、编辑模型(能力三态、接口多选、方言、凭据、
  限额、目录思考档位与默认档、路由解析结果)
- 探测对话框:候选接口逐个拉模型列表,摘要里渠道可取消、模型按家族勾选,
  采纳后经 buildAutoConfiguration 写入;所有写入统一走 normalizeCustomProvider
- 删除旧 ProviderModal / ProviderModalView,宿主导入扩展的 activeTab 改为可选;
  中英文各新增 207 个 settings.channel* / provider* / model* 文案
- 迁移 portal-layering / provider-edit-deeplink / provider-copy-config /
  provider-deepseek 测试到新结构,新增 provider-settings-model 单测
- 探测只发起一次并把 Promise 放进 ref,效果重跑时只重新挂接结果;探测被拒绝时
  展示错误而不是一直等待
- 未配置渠道详情在窄屏也显示"返回渠道目录"
- 请求配置抽屉去掉未使用的 isGatewayWebui 属性
…与 quirks、供应商页走查缺陷

设置层:隐式端点由主连接物化为唯一真相;故障转移家族按已启用接口计算;主机解析统一到 registry/hosts;预设按 id/主机建索引;路由上下文一次构造;空地址默认端点自动切换。
探测:严格模式;既有端点永不因探测失败被停用或切走默认;候选只从实例自身地址派生;取消也写回观测。
运行时:Model.provider generic→openai;旧工厂签名应用 quirks 推导;家族/协议统一经 wireRoute;删除 endpointHeaders;渲染期路由记忆化;停用供应商不进入聊天/摘要/标题/提交信息模型选择。
网关桥:ProviderModelsRequest 新增 credential_id;WebUI 复用落库 Key 时按凭据选 Key,草稿地址限定已保存主机,回填按命中端点。
界面:再加一个实例预填、停用端点设默认、三层故障转移候选预览、窄屏换行、quirks 仅 OpenAI 家族、{origin} 实时展开、未知原因可见、请求头预览复用运行时合并、来源徽标、密钥差异与刷新竞态、删除确认、非自建必填 Key、非法请求头可见、分组内拖拽排序、模型行记忆化、停用提示条、清理无消费者 i18n 键。
测试:注册表主机归属、隐式端点、故障转移家族与迁移、探测严格模式、网关桥凭据与主机、运行时方言与 quirks、辅助模型选择、WebUI 源码契约改按三栏结构。设计文档新增附录 D。
冲突仅在 modelFactory:保留路由式构造,并吸收 main 对 DeepSeek Flash 家族放开图片输入(inputOverride ?? 按模型 id 推断)。
数据:合并两份生成器为 scripts/generate-model-catalog.mjs,一次拉取写出 catalog.generated.ts(22 分区 / 785 模型,字段补全:上下文/最大输入/最大输出、输入与输出模态、思考档位、工具调用、结构化输出、附件、温度、知识截止、发布/更新日期、状态、开放权重、交错思考)与 presets.generated.ts(仅渠道事实,按 sourceId 引用目录);CI 每日刷新两份文件;新增 Groq 预设。
解析:resolveModelCapabilities / resolveModelCatalogInfo / resolveModelInputModalitiesResolved,用户覆盖 > 目录 > 供应商 > 启发式 > 未知,每项带来源;限额初值带入目录的最大输入。
界面:编辑模型新增只读目录信息面板;能力芯片按有效值与来源显示;输入模态与限额三项各自带来源徽标;模型行显示图片/文件图标;术语统一为接口家族与模型系列。
运行时:模型 tools 能力为不支持时不下发工具定义;目录输入模态优先于内置白名单(用户覆盖最高);原生搜索资格委托共享判定。
文档:6.1 能力默认值来源改为目录,新增 6.6 模型元数据目录维护与获取。
删除 CustomProvider.category、预设 category 与添加渠道对话框的类型选择;API Key 改为可选(本地服务留空);探测的系列方言只对原生渠道生效;网关摘要白名单与文案、文档同步清理。
模型只显式选一个接口(chatProtocol),旧有序 chatProtocols 只取首项迁移;可选范围由渠道决定:原生渠道 = 预设声明的接口(Anthropic 固定 Messages、Gemini 固定 v1beta、OpenAI/xAI 在 Completions 与 Responses 间切换),其它渠道 = OpenAI 两类 + Anthropic Messages,Gemini 系列模型再加 v1beta;未配置地址的接口置灰。端点层故障转移候选改为自动取供应商已启用的同家族其它接口,不再由模型维护列表。
- 新增 ProviderLogos(内联 @lobehub/icons-static-svg 1.95.0,MIT):智谱 / MiniMax /
  Kimi / 通义 / 火山 / 硅基流动 / Groq / OpenRouter / New API / Ollama / LM Studio;
  原生五家沿用 IconSet 品牌图标,自定义与未知预设用中性 Server 图标,不再用首字
- ProviderAvatar 统一容器(rounded-lg 浅底、无边框),列表 28 / 详情 40 / 对话框 56,
  添加渠道对话框、"从预设创建"下拉与探测对话框标题也走同一组件
- ChipTone 收敛为 default / on / ok / warn / bad,删除 purple;芯片统一 22px 高、
  11px 字、rounded-md;去掉 strike,禁用 / 未采纳只降透明度
- 能力芯片改三态形状:支持 = 实心绿点,不支持 = 空心圆 + 虚线边框,未知 = 问号图标;
  用户覆盖只加一圈主色描边;目录信息面板的能力位同一组件,标签列与值列按芯片行高对齐
- SourceTag 统一为中性小字,仅"用户"主色;缺 Key 由 bad 改 warn;思考档位阶梯
  可用 = 描边、当前默认 = 主色、不可用 = 降透明度
每个端点各自选择 Claude Code / Codex / Grok / 不模拟 / 纯协议头,推荐值按该端点的接口与方言给;身份档(UA、静态身份头、该 CLI 的会话头)叠在方言头档之上、用户头之下。供应商级请求头编辑器不再提供"模拟 CLI",检测到旧的供应商级身份头时提示并可一键移除。协议 / 方言 / 身份三层装配移到 lib/providers/requestHeaders.ts,设置页"最终请求头"预览与运行时共用。
新增阶跃星辰(国内 / 国际)、腾讯云 · 混元、百度千帆、小米 MiMo、美团 LongCat、商汤 SenseNova、讯飞星火、魔搭 ModelScope 九个渠道预设及品牌 logo;目录分区增至 25 个(805 个模型)。百度千帆与讯飞星火 models.dev 未收录,地址由覆盖层声明。
按模型当前解析出的路由发一次最小生成请求(Completions / Responses / Messages /
Gemini 各自的路径与请求体),记录状态码、耗时与错误摘要;多把 Key 逐一测并聚合。

- agent-ui lib/providers/modelCheck.ts:URL 拼接(/v1 去重、isFullUrl、Gemini
  models/{id}:generateContent)、四类最小请求体、内置头 + 用户头装配、响应归类
  (401/403 鉴权、404 模型或路径、429 限流、非 JSON)、多 Key 聚合。
- providerUtils:checkProviderModel / checkProviderModelAllKeys / checkProviderModels
  (并发工作池 + AbortSignal);桌面走 provider_check_model,WebUI 走
  gateway_provider_check_model,脱敏态不带鉴权头由桌面端按 credentialId 补 Key。
- Rust services/provider_check.rs:与模型列表同一套 client(系统代理开关、直连
  忽略环境代理),POST + 30s 超时(可传 1–120s),响应体截断 4KB,只接受 http(s),
  出错信息不回显头取值。
- 网关桥 handle_provider_check_model:缺鉴权头时按 protocol 与端点 auth 覆盖生成,
  url 主机必须属于该供应商已保存地址集合;proto 新增 ProviderCheckModelRequest /
  Response(103 / 109),Go 侧加入直通白名单,web 端 adapters / rpc / shim 接线。
- 顺手补上 WebUI 拉模型列表时丢失的 credential_id 透传。
渠道详情页:
- 模型行右侧加“测试”按钮,行内芯片显示检测中 / ✓ 延迟 / ✗ 原因 / 部分 Key 失败,
  title 列每把 Key 的结果;“模型列表”标题加“全部测试”(只测已启用模型,并发 3,
  进行中变“停止”,AbortController 中止)。结果只在组件内存里,切换供应商即清空。
- API 密钥区改为多 Key 列表(ProviderKeyList):每行标签、遮罩输入(沿用 WebUI
  脱敏逻辑)、启用开关、范围芯片(自动 / 全部 / 手动 N,点击打开抽屉并定位到该 Key)、
  上次拉取时间与数量、逐 Key 检测、删除(确认,至少保留一把);底部“添加 Key”
  新增并聚焦。“管理密钥(N)”改名“范围与详情”,可互换 / 各有范围提示保留在标题行。
- providerSettingsModel 新增 addProviderCredential / removeProviderCredential /
  updateProviderCredential 与 refreshCredentialModelList,维持
  apiKey === credentials[0].apiKey 不变量;CredentialsDrawer 复用同一套并支持 focus。
- 添加渠道对话框改为两列栅格分节(基本信息 / API Key / 接口地址 / 从预设创建折叠),
  头像缩至 40px 放标题左侧,四类接口平铺,占位符不带 /v1,校验文案固定在底部按钮左侧
- API Key 支持多把:每行 Key + 标签 + 删除,提交时空行剔除生成 credentials[],
  第一把即主 Key;createProviderFromEndpoints 新增 apiKeys 参数(保留 apiKey 兼容)
- 新增 resolveEndpointRequestBase:OpenAI 家族无版本段补 /v1、Gemini 补 /v1beta、
  Anthropic 不改地址且不重复 /v1;地址以 # 结尾原样使用;完整 URL 原样
- resolveProviderChatRoute 输出规范化后的 baseUrl(存档原值不改)并携带 baseUrlVerbatim;
  模型工厂改按同一口径判断版本段(/api/paas/v4 不再追加 /v1),# 原样不补
- 设置页各处实际请求路径预览(添加渠道、请求配置抽屉、编辑模型路由结果)共用该函数;
  请求配置抽屉地址下补版本段说明;模型列表推导对 # 结尾地址去标记并直接挂 /models
- 补充 endpoint-request-base / 多 Key 创建 / 路由 baseUrl / 模型工厂版本段测试
- 标题行计数芯片后加四个图标按钮:打开模型文档(供应商 docUrl 覆盖预设 doc,
  都没有则禁用并提示去请求配置填写)、一键收起 / 展开全部分组、内联搜索
  (模型 ID / 显示名 / 远端 ID 子串,Escape 或清空关闭)、Popover 多选过滤
  (能力 / 状态 / 接口,生效时高亮并显示计数角标,可一键清除)
- 搜索与过滤取交集:分组计数改为"匹配 / 总数",无匹配分组隐藏,生效期间禁用
  分组内拖拽,"全部测试"只测可见的已启用模型
- CustomProvider 新增可选 docUrl(归一化只保留 http(s) 绝对地址),请求配置
  抽屉顶部加"文档地址"输入
- 全部测试 / 刷新模型列表 / 手动添加抽到 ModelListActions,容器 < 640px 时退化
  为图标(title / aria-label 保留文字)
- 纯函数 filterProviderModels / providerDocUrl 进 providerSettingsModel,补单测
  provider-model-filter.test.mjs;刷新按钮的 WebUI 契约测试跟随新组件位置
同一渠道的多个入口主机(Key 与接口都相同、只有主机不同)不再靠复制实例表达:供应商维护 origins[],接口地址写成 {origin} 模板,解析时按主源或指定源展开,路由输出 originId / originUrl。

故障转移由三层变四层,在凭据层与端点层之间插入源层:同 Key、同接口换下一个启用的源;熔断键带源主机,一个主机挂掉不影响其它源;鉴权类失败整体跳过源层。

探测按"源 × 接口"展开候选,摘要逐源显示状态、模型取并集,观测写回 origins[].lastProbe;网关侧主机白名单纳入各源主机;备份快照剥离源观测值。

界面:API 地址区改为源地址列表(主/备、启用、检测、删除、添加备用地址),接口地址显示模板与展开后的真实地址;旧实例可一键转为源地址模式;添加渠道对话框支持填源地址。
模型厂商自营渠道的模型列表是已知事实,没必要每次探测都去问一遍;只有聚合站、
中转、本地服务与自定义渠道才需要问接口。

- presets.overlay 给全部 47 个预设显式标注 modelListSource:原生五家与厂商渠道
  (含 Coding / Token / Step Plan 变体)为 catalog,聚合站 / 中转 / 本地服务 /
  自定义为 api;presets.ts 对“声明 catalog 但目录分区为空”的渠道(baidu、
  xunfei)退回 api。
- 探测按来源分流:catalog 渠道不发任何请求,端点观测记新增的 catalog 态,模型取
  该渠道的目录分区(limitsSource: catalog、source: auto),端点照常按预设声明
  启用;api 渠道行为不变。
- api 渠道下同一把 Key、同一个源上请求签名(旧类型 + 最终模型列表地址)相同的
  接口只发一次请求,结果复用给共享它的接口,摘要仍按接口逐行显示。
- 探测采纳的模型默认全部关闭:buildAutoConfiguration 的 activeModels 恒为空,
  applyProbeToProvider 只追加模型不改启停,refresh 不会关掉用户已启用的模型。
- 探测对话框显示“内置目录”芯片与目录快照日期,顶部说明按来源分两套文案。
腾讯云 Coding / Token Plan 与小米 MiMo 三个 Token Plan 集群补上 Anthropic 兼容协议端点(OpenAI 侧地址与官方文档一致,未改)。

界面术语调整:"方言(厂商差异)"→"厂商实现","继承"→"自动","实现偏差(quirks)"与"兼容开关(quirks)"统一为"兼容开关";相关说明改写成不含行话的表述。代码标识符 dialect 与设计文档用词不动。

未配置渠道页的"检测并启用"提示按渠道来源区分:目录渠道说明只核对配置、不请求接口。
@StackCairn
StackCairn marked this pull request as draft September 18, 2026 03:21
@github-actions

Copy link
Copy Markdown
Contributor

PR governance checks failed — this PR has been converted to draft.

  • No linked issue: the PR body must contain Closes #123 / Fixes #123 / Resolves #123. This project requires an issue before a PR — see the contribution guidelines.
  • UI change without screenshots: this PR modifies frontend code. Please add before/after screenshots or a recording under "Screenshots / preview" in the PR body.

Fix the items above, then click Ready for review to re-run the checks.

补齐设计文档 §6.1 / §6.2 / §6.3 里写了但没实现的三项。

§6.2 逐字段来源:
- FieldSource 补 "adapter",能力与模态解析结果带 candidates(目录 > 供应商 >
  适配器 > 启发式,不含 user);tools / structuredOutput 的接口层可用性与
  nativeWebSearch 的接口规则改记 adapter 来源,供应商总开关关闭时仍记 provider。
- 探测拉回的 /models 限额与模态(context_length、top_provider.*、
  architecture.input_modalities、supports_image_in,Gemini 的 inputTokenLimit /
  outputTokenLimit)留存到 ProviderModelConfig.providerMeta,作 provider 候选;
  只认上游 snake_case 字段,本地 inputModalities 仍是用户覆盖。
- 目录值与供应商值不同即冲突:编辑模型抽屉显示 warn 芯片与"采纳供应商值"
  (写成用户覆盖),供应商元数据不自动覆盖目录值;"目录值"列加候选数量标记,
  点击在该行下方展开来源与值,列数与列宽不变。

§6.3 模型级参数覆盖:
- ProviderModelConfig.parameters 只收 temperature / maxTokens / topP——前两个是
  pi-ai StreamOptions 的具名字段,topP 经 samplingParams 落 OpenAI 兼容请求体的
  top_p;pi-ai 0.84.2 在这四类接口上没有 stop 序列通路,故不收 stopSequences。
- 归一化做范围校验并丢弃未知键(dev 下 warn);PROTOCOL_PARAMETER_KEYS 按接口
  过滤,temperature 按接口范围钳制,maxTokens 与 maxOutputToken 取小。
- createProviderRuntimeConfig 带上 parameters,agentRunner 与 textOnlyRuntime 在
  payload 中间件链之前应用,抽屉限额表下新增"请求参数"小节。

§6.1 悬空能力位:
- promptCaching 接进 resolveProviderCacheRetention:unsupported 直接返回 none;
  Anthropic Messages 与 OpenAI Responses 在适配器层默认 supported,其余 unknown。
- 删除 parallelTools——四类接口在 pi-ai 0.84.2 上都没有 parallel_tool_calls 可
  透传(写死该字段的 openai-codex-responses 与有映射的 mistral-conversations 本
  应用都不使用),旧存档里的该键归一化时静默丢弃。
- §6.1 去掉 parallelTools,写明 promptCaching 的运行时消费点与删除 parallelTools
  的依据(pi-ai 0.84.2 的四类接口都没有 parallel_tool_calls 通路)。
- §6.2 补适配器来源的结论(四类接口都不发 response_format,结构化输出一律由工具
  模拟)、providerMeta 的字段来源与冲突采纳规则、抽屉的候选展示方式。
- §6.3 加模型级参数覆盖的字段表:逐项标出 pi-ai 的透传路径与可用接口,写明不收
  stopSequences 的原因,以及归一化与请求期钳制的分工。
生成器不再跳过输出模态不含 text 的模型;生图模型在 models.dev 里普遍
limit.context = limit.output = 0(没有上下文语义),这类条目成对写 0,
由消费侧按 contextWindow > 0 的既有门控跳过预算计算。目录新增 16 条:
openai 5、xai 3、alibaba-token-plan 与 -cn 各 4。

新增 lib/models/modelType.ts 的 resolveModelType:用户显式 modelType >
目录 outputModalities 含 image > 模型 id 启发式 > chat。image 类型模型
不进聊天选择器(buildModelOptions / isProviderModelAvailable 都排除),
因为四类聊天接口发不出也收不到它们。

同时加能力位 imageGeneration(目录值来自 outputModalities)与
AppSettings.imageGeneration.defaultModel(归一化时丢弃指向不存在或
非 image 类型模型的配置),同步与备份照常。
新增 lib/providers/imageGeneration.ts:resolveImageGenerationRoute 按
供应商已启用的端点决定走哪条 API——Gemini 系列模型 + 已启用的
google-generative-ai 端点走 generateContent,否则借 OpenAI 家族端点
(Completions 或 Responses 任一)打 /images/generations,都没有则不可用。
地址、Key、请求头、{origin} 展开与版本段规则全部复用
resolveProviderChatRoute + buildBuiltinRequestHeaders。

buildImageGenerationRequest 按 kind 拼体;response_format 只对非
gpt-image-* 发送(gpt-image 系列恒返回 b64,官方对该参数直接回 400)。
parseImageGenerationResponse 覆盖 OpenAI 的 b64_json / url 两种形态与
Gemini 的 inlineData(含中转的 inline_data / mime_type 变体),错误
归类与模型连通测试同一口径。

连通性测试对 image 类型模型直接跳过:最小生成请求在这两条接口上等于
真出一张图,要花钱。ModelCheckResult 增加 skipped,聚合状态加 "skipped"。
新增 services/image_generation.rs 与两个命令:provider_generate_image
(缺省超时 120 秒、上限 300 秒、响应上限 64MB 且不截断——截断会切坏
base64)与 provider_download_image(32MB、只允许 http(s),供 dall-e 那种
只回 url 的结果落地)。响应体原样回传、解析留在 TS 侧,避免图片抽取规则
出现两份实现。

网关桥 handle_provider_generate_image 镜像 handle_provider_check_model:
脱敏态按 credential_id 补 Key、主机白名单与超时钳制全部复用
resolve_stored_provider_check_headers。出图慢,和用量查询一样挪到独立
任务上,不占住 socket。proto / Go 透传与 WebUI shim 按 provider_check_model
那次的做法照搬。

fs_write_text 增加 encoding(""/utf8 保持原语义,base64 解码后按字节写),
让生图工具能复用同一条路径边界、检查点前像与符号链接解析,不另开绕过
工作区边界的写入通路。
新工具按 imageGeneration.ts 拼请求,桌面走 provider_generate_image,
WebUI 走网关桥,再把每张图存为 save_to/<yyyyMMdd-HHmmss>-<n>.<ext>。
路径经 ToolPathResolver(intent: write) 与 Rust 侧 resolve_scoped_fs_path
双重校验,写入用 fs_write_text + encoding=base64,不绕过工作区边界。
url 形式的结果先经 provider_download_image 下载成 base64 再落盘。

选模型优先级:工具参数 model("<providerId>:<modelId>")> 设置里的默认
生图模型 > 第一个启用供应商里第一个启用的 image 类型模型;都没有则报错
并指引用户去供应商页启用生图模型。

category intelligence、非只读、缺省 allow、仅对话场景注册;沙箱离线模式
下与 Browser 一样整个 bundle 不注册。中止信号透传到 invoke。

设计文档新增 §6.7 与附录 D 一行,§2.4 的 modelType 注释同步。
编辑模型的标识区新增"模型类型"(对话 / 生图,缺省按目录输出模态,可覆盖);能力表增加"图像生成"行。模型列表行对生图模型显示"生图"标记与"设为生图默认"切换(写入 settings.imageGeneration.defaultModel),不再显示聊天接口芯片;连通性测试对生图模型显示"跳过 · 生成有成本"。设计文档 §7 抽屉描述同步到当前结构。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant