feat(providers): an OpenAI-compatible preset for any vLLM, LM Studio or gateway URL

Step 8 of the provider refactor plan, a new provider made of one record.
'custom' runs on @ai-sdk/openai-compatible with <think> extraction, merges
system messages (open-source chat templates reject several), has no default
URL (so a key alone does not count as connected, and the chat endpoint is
shown under the URL field) and lists models from its /models. Server side:
CUSTOM_API_KEY and CUSTOM_BASE_URL, ADMIN_CUSTOM_* in the admin panel.
env.example and the three provider docs gained a section; the picker count
in the e2e test is 25 and a new e2e test walks through the preset. The
behavior snapshot gained the new provider's 146 rows; its two 'No AI provider
configured' rows list CUSTOM_API_KEY now.
This commit is contained in:
dayuan.jiang
2026-10-12 21:17:51 +09:00
parent 717f7e9445
commit b2cadfa5bf
9 changed files with 246 additions and 9 deletions
+21
View File
@@ -516,6 +516,27 @@ const defs = {
"zh-Hant": "填服務位址",
},
},
// Any OpenAI-compatible API: vLLM, LM Studio, LiteLLM, a gateway. The
// user enters the URL; a server that ignores keys takes any non-empty
// one (a custom URL always needs a key, see getAIModel's guard)
custom: {
label: "OpenAI-compatible",
sdk: "openai-compatible",
credential: "apiKey",
group: "selfHosted",
envPrefix: "CUSTOM",
modelList: "openai",
icon: "server",
optionsOpen: true,
// Open-source chat templates reject several system messages
singleSystem: true,
note: {
en: "Any OpenAI-compatible URL and key",
zh: "任何 OpenAI 兼容地址和 key",
ja: "OpenAI 互換の URL とキー",
"zh-Hant": "任何 OpenAI 相容位址和 key",
},
},
} satisfies Record<string, ProviderDef>
export type ProviderName = keyof typeof defs