fix: [ENG-2897] route all OpenAI-compatible providers to 'openai' registry type#701
Conversation
…istry type resolveRegistryProvider only listed 6 of the 17 user-facing provider IDs that talk OpenAI-compatible APIs. The other 11 (deepseek, glm, glm-coding-plan, moonshot, cerebras, cohere, deepinfra, togetherai, vercel, minimax, perplexity) fell through to the 'gemini' default, breaking acceptsAnyModel bypass, context-length lookups, and tokenizer selection — surfaced by openai-compatible users in #691 but latent for the other ten. Cross-checks the resolver's hardcoded list against PROVIDER_MODULES so any future OpenAI-compatible provider added in infra fails the test unless the resolver is updated in sync.
|
Claude finished @cuongdo-byterover's task in 3m 39s —— View job Claude PR Review
SummaryOverall: 4.5 / 5 — targeted, correct fix with a thoughtful regression guard. Two minor nits (one wording, one latent gap on the gemini side) and one optional test-coverage suggestion; none are blockers. Correctness
Issues
Test design
Security / Performance
VerdictLGTM. The latent |
… all-bucket cross-check Reviewer flagged that `byterover` (declared providerType: 'gemini') resolved correctly only via the terminal `return 'gemini'` fallback — by accident, not by design. A future refactor of the default branch would silently regress it on the same path that bit openai-compatible. - Map `byterover` explicitly in the gemini branch alongside `google` / `google-vertex`, so resolution is intent-driven rather than fallback- driven. - Generalise the regression test to iterate every provider module and assert it resolves to its declared `providerType`. Now covers all three buckets (claude / gemini / openai = 24 cases vs 22 before), so drift on the claude/gemini side fails loudly instead of slipping through the same gap. - Pin `google-vertex` separately (no infra module, only in PROVIDER_REGISTRY) so it stays covered by an explicit test. - Tighten the registry comment: "at build time" -> "at test time" to match the actual mocha-runtime check.
|
Claude finished @cuongdo-byterover's task in 2m 19s —— View job Claude PR Review (synchronize on
|
| Bucket | Modules declaring this providerType |
Resolver-mapped IDs | Match? |
|---|---|---|---|
claude |
anthropic |
anthropic |
✅ |
gemini |
google, byterover |
google, byterover (+ google-vertex defensive) |
✅ |
openai |
17 modules (cerebras, cohere, deepinfra, deepseek, glm, glm-coding-plan, groq, minimax, mistral, moonshot, openai, openai-compatible, openrouter, perplexity, togetherai, vercel, xai) |
identical 17 IDs | ✅ |
No misroutes. The terminal-fallback return 'gemini' is no longer load-bearing for any real provider — byterover was the only one that needed it.
Issues / nits
- nit (documentation only, posted inline): The new test's block comment at lines 48–51 says
google-vertexis "exposed in PROVIDER_REGISTRY (user-facing)". Verified bygrep -rn "google-vertex" src/: it only appears insideregistry.tsitself — no entry insrc/server/core/domain/entities/provider-registry.ts, and no caller passes it asexplicitProvider. The mapping is future-proofing for Vertex support, not a current user-facing path. Suggested rewording inline; cosmetic only.
Security / performance
- No change since the prior review. Closed hardcoded set, not user-controlled. Trivial
Array.includescost.
Verdict
LGTM. Ship it. The remaining nit is documentation-only.
• Branch: fix/ENG-2897
|
Claude finished @bao-byterover's task in 1m 54s —— View job Claude PR Review (synchronize on
|
| Bucket | Modules in infra | Resolver-mapped IDs | Match? |
|---|---|---|---|
claude |
anthropic |
anthropic |
✅ |
gemini |
google, byterover |
google, byterover (+ google-vertex defensive) |
✅ |
openai |
17 modules (cerebras, cohere, deepinfra, deepseek, glm, glm-coding-plan, groq, minimax, mistral, moonshot, openai, openai-compatible, openrouter, perplexity, togetherai, vercel, xai) |
identical 17 IDs | ✅ |
No drift. Regression test still asserts all three buckets (registry.ts:707-711, resolve-registry-provider.test.ts:34-45).
Outstanding (carried over, optional)
- nit (doc-only, from prior review, still unaddressed):
resolve-registry-provider.test.ts:49still saysgoogle-vertexis "exposed in PROVIDER_REGISTRY (user-facing)". Verified again bygrep -rn "google-vertex" src/— onlyregistry.tsreferences it; it is not insrc/server/core/domain/entities/provider-registry.tsand no caller passes it asexplicitProvider. Cosmetic only; the resolver mapping itself is correct as forward-looking pinning. Not a blocker.
Verdict
LGTM — ship it. The synchronize introduces no risk to the fix; the merge is clean and the regression-guard test is intact. Only carry-over is the documentation-accuracy nit on the google-vertex block comment, which is optional.
• Branch: fix/ENG-2897
Summary
brv providers connect openai-compatible --model <custom>no longer fires the registry-whitelist rejection; the gate now correctly bypasses for the user-facing provider ID.deepseek,glm,glm-coding-plan,moonshot,cerebras,cohere,deepinfra,togetherai,vercel,minimax,perplexity) that were silently misrouted to the Gemini registry.PROVIDER_MODULESin infra, so adding a new OpenAI-compatible provider without updating the resolver fails the test.Root cause
resolveRegistryProviderinsrc/agent/core/domain/llm/registry.tsexplicitly mapped 6 user-facing provider IDs (openai,openai-compatible,openrouter,xai,groq,mistral) to the registry-internal'openai'type. The other 11 OpenAI-compatible passthrough providers fell through to the'gemini'default branch. Downstream effects of the wrong resolution:acceptsAnyModel('gemini')returnsfalse→ the schema validator fires"Model X is not supported for provider 'gemini'"for any model not in the Gemini registry.getEffectiveMaxInputTokens('gemini', ...)clamps to a Gemini model's window instead of honouring the user'smaxInputTokenscap.agent-llm-service.tspicks Gemini's, which is architecturally wrong for an OpenAI-compatible endpoint (works today becauseAiSdkContentGeneratordoes its own message conversion, but the mismatch is latent risk).Issue #691 surfaced through
openai-compatiblebecause it was the most-used affected provider; the other 10 were broken in the same way without an open ticket.Fix
Expand the explicit OpenAI-mapped list to all 17 user-facing IDs that declare
providerType: 'openai'in their provider module. One file changed, plus a regression test.Test plan
test/unit/agent/core/domain/llm/resolve-registry-provider.test.ts— 22 cases, including a cross-check that importsPROVIDER_MODULESfrom infra and asserts every module withproviderType: 'openai'resolves to'openai'. New OpenAI-compatible providers added in infra without updating the resolver fail this test.Model 'deepseek-v4-flash' is not supported for provider 'openai-compatible'. Supported: gpt-4.1, gpt-4.1-mini, ...Post-fix: validation passes; any error originates from the downstream LLM call (endpoint unreachable, model not found at endpoint), never from the registry whitelist.
Closes #691.