[Bug] 自定义(custom) LLM 提供方未实现 /models 接口时,Studio 后台拒绝保存
What happened?
在 Studio 后台配置 custom 类型 (OpenAI 兼容) 的 LLM 提供方时,即便已正确填写 baseUrl、apiKey 和默认模型 ID,点击「验证/保存」仍被拒绝,无法保存。 测试使用火山方舟 Agent Plan (volcengine agent plan) 火山方舟提供的兼容 OpenAI 接口协议工具(已支持Responses API)为 https://ark.cn-beijing.volces.com/api/plan/v3
根因:Studio 在保存前会无条件向 baseUrl + "/models" 发起探测 (inkos-core/dist/llm/providers/probe.js 的 probeModelsFromUpstream),而许多自建/聚合 API 并不实现该可选端点。探测失败后,inkos-studio/dist/api/server.js:3076 直接 return 400 拒绝保存。矛盾点在于:custom 提供方在 inkos-core/dist/llm/providers/endpoints/custom.js 中定义为 models: []、checkModel: undefined(即设计上本就不掌握模型清单),验证环节却强制要求 /models 探测通过。同一份配置在 CLI 下不调 verifyService、不探测,可直接推理,仅在 Studio 后台卡死。
Steps to reproduce
- 启动 Studio (
inkos studio),打开 Web 后台 → 设置 → LLM 提供方 → 新增 custom 类型 - 填写:
baseUrl:一个 OpenAI 兼容但不提供/models端点的上游地址(例如火山方舟AgentPlan仅暴露/v3/chat/completions,可以正常调用)apiKey:有效密钥- 默认模型 ID:例如
deepseek-v4-pro(该 ID 在chat/completions中实际可用,为火山方舟AgentPlan提供的标准模型ID)
- 打开浏览器开发者工具 → Network 面板,准备观察验证请求
- 点击「测试连接」或「保存」
- 随即页面显示红色字样「无法自动确定模型,请先填写可用模型或提供支持 /models 的服务端点。」
Expected behavior
只要 chat/completions 可正常调用、且用户已手动指定可用模型 ID,服务就应当保存成功。/models 是 OpenAI 兼容协议的可选端点,缺失不应阻断保存。/models 仅可用于自动获取API提供的模型列表,不应当用于校验API上游的chat/completions 对话端点是否可用。运营商的models端点请求后返回的列表不一定准确,因为模型提供商可能滞后更新该列表,应当以用户指定的模型ID为高优先级。
InkOS version
1.8.0
Operating system
Windows (native)
LLM provider / model
deepseek-v4-pro
Relevant logs
安装方式:
- npm 全局 `@actalk/inkos`
- 操作系统:Windows
- 提供方类型:custom(上游未实现 `/models` 接口)
**根据源码推断的返回结构(server.js:3076 拦截分支):**
HTTP/1.1 400 Bad Request
{
"ok": false,
"error": "<probe.error 或 connectionFailed 文案>",
"probe": { "ok": false, "error": "..." }
}
**关键源码(v1.8.0):**
- `inkos-studio/dist/api/server.js:3076` — 硬性拦截:
if (!probe.ok) {
return c.json({ ok: false, error: probe.error ?? connectionFailed, ... }, 400);
}
- `inkos-core/dist/llm/providers/probe.js` — `probeModelsFromUpstream()` 无条件请求 `baseUrl + "/models"`
- `inkos-core/dist/llm/providers/endpoints/custom.js`:
export const CUSTOM = {
id: "custom",
api: "openai-completions",
baseUrl: "",
models: [], // 空,不预置模型清单
checkModel: undefined, // 无模型校验
};
---
## 补充:建议修复与临时绕过方案
**建议修复**(对 custom 放宽门槛,不影响其他 provider):
- 方案 A(最小改动):在 `server.js:3076`,对 `custom` 类型,若已填模型 ID 且 `chat/completions` 可达,则 `/models` 探测失败也放行保存。同时全面排查类似校验方式,彻底改正该验证步骤。
- 方案 B(更彻底):在 `probe.js` 中,对 `custom` 缺失 `/models` 时直接返回 `ok: true`,依赖核心库已有的 `UNKNOWN_MODEL_FALLBACK_MAX_TOKENS` 兜底。
**临时绕过方式(目前可用,但不修复该bug仍有可能导致其他功能出现错误):**
1. 反代/中转层补一个 `/models` 端点返回 `{"data":[{"id":"你的模型ID"}]}`;
2. 或改用 CLI 直连:`inkos config set-global --provider openai --base-url <URL> --api-key <KEY> --model <模型ID>`。Source: Narcooo/inkos