feat(config): tolerate /v1 base-url convention in endpoint connectivity probe - #23
Merged
Conversation
…tivity probe OpenAI and Anthropic SDKs take `baseURL` differently — OpenAI's includes the `/v1` segment, Anthropic's does not (the SDK appends `/v1/...` itself). Users routinely paste the wrong shape (most often a bare `host:port` for an openai gateway that needs `/v1`), and the probe / wire then 404s or hits the gateway's HTML web UI. The endpoint connectivity probe now resolves the base-url tolerantly: it tries the value AS-GIVEN first (so a non-standard gateway path still works), then the convention-corrected alternative (openai: +`/v1` when missing; anthropic: strip a trailing `/v1`), and keeps whichever actually lists models. The base-url that responded is persisted and shown on the result card, so the stored endpoint matches the verified wire path — no blind rewrite, no extra hint text. - list-models.ts: `apiKeyBaseUrlCandidates` + `listApiKeyModelsResolvingBaseUrl` (prefers a candidate that lists models, else first reachable, else first error). - config.ts / admin.ts: probe returns `resolvedBaseUrl`; endpoint add/set (both /config and /admin) persist it instead of the raw typed value. Tests: candidate-generation + tolerant-lister unit tests (openai-missing-/v1 resolves to +/v1, anthropic-wrong-/v1 strips, all-unreachable returns first error); config persist test asserts the resolved base-url lands in config.json (fails on old code). Full suite 2616/2616, typecheck clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR updates the endpoint connectivity probe to tolerate differing /v1 base-url conventions between OpenAI-style and Anthropic-style apiKey endpoints by probing multiple base-url candidates and persisting the base-url that actually responded.
Changes:
- Add base-url candidate generation and a tolerant model-lister that resolves a working base-url (
/v1add/remove) while probing. - Thread
resolvedBaseUrlthrough the/configand/adminendpoint probe paths and persist the resolved base-url on add/set. - Add unit tests covering candidate generation, tolerant probing behavior, and config persistence of the resolved base-url.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/provider/list-models.ts | Adds base-url candidate generation and a tolerant model listing function that returns resolvedBaseUrl. |
| src/provider/list-models.test.ts | Adds unit tests for candidate generation and base-url-resolving probe behavior. |
| src/commands/config.ts | Uses the resolving lister in endpoint probing and persists resolvedBaseUrl for /config endpoint add/set. |
| src/commands/config.test.ts | Adds a regression test asserting resolved base-url persistence in user config. |
| src/commands/admin.ts | Persists resolvedBaseUrl for /admin endpoint add/set as well. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+124
to
+126
| if (baseUrl === undefined) return [undefined] | ||
| const trimmed = baseUrl.trim().replace(/\/+$/, '') | ||
| if (!trimmed) return [undefined] |
Comment on lines
+540
to
+544
| // the add confirmation. `resolvedBaseUrl` is the base-url that actually | ||
| // responded — set when the probe normalized the `/v1` convention (apiKey | ||
| // endpoints only); the caller persists / displays it so the stored endpoint | ||
| // matches the verified wire path. Undefined when no base-url was probed | ||
| // (codex / default base) or the as-given value worked unchanged. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
背景
OpenAI / Anthropic 两个 SDK 的
baseURL约定不同:OpenAI 的带/v1(https://api.openai.com/v1),Anthropic 的不带(SDK 自己补/v1/...)。用户配 endpoint 时经常填错形式——最常见是给 openai 网关填了不带/v1的host:port——导致探针/wire 打到 404 或网关的 HTML 网页。改动
endpoint 连通性探针现在容忍
/v1约定:先试用户填的原值(非标网关路径仍能命中),再试约定修正后的候选(openai 缺/v1就补、anthropic 多/v1就去),哪个真能列出 model 就用哪个。探针实际打通的那个 base-url 被持久化并显示在结果卡上——不是盲改,没有额外提示文案,存的就是验证过的 wire 路径。list-models.ts:apiKeyBaseUrlCandidates+listApiKeyModelsResolvingBaseUrl(优先选能列 model 的候选,否则首个可达,否则首个错误)。config.ts/admin.ts:探针返回resolvedBaseUrl;endpoint add/set(/config和/admin两面)持久化它而非用户原值。测试
候选生成 + 容忍 lister 单测(openai 缺 /v1 → 解析成 +/v1、anthropic 错带 /v1 → 去掉、全不可达 → 返回首个错误);config 持久化测试断言 resolved base-url 落进 config.json(旧码上 fail)。全量 2616/2616、typecheck 干净。
🤖 Generated with Claude Code