Skip to content

fix(models): map legacy provider api_type values to pi's canonical api ids#418

Open
jacoblee-io wants to merge 1 commit into
mainfrom
investigate/no-api-provider
Open

fix(models): map legacy provider api_type values to pi's canonical api ids#418
jacoblee-io wants to merge 1 commit into
mainfrom
investigate/no-api-provider

Conversation

@jacoblee-io

Copy link
Copy Markdown
Collaborator

Problem

Selecting Anthropic as a model provider has never worked. Every chat turn fails immediately with:

No API provider registered for api: anthropic   MODEL_ERROR

Root cause

The Models page stored api_type="anthropic", which flowed verbatim into every model config's api field (adapter → agentbox → pi ModelRegistry, no validation or aliasing anywhere). pi-ai's API-provider registry only registers anthropic-messagesanthropic is a provider slug there, not an api id — so resolveApiProvider() throws on the first prompt. Verified this was broken since the Portal's first commit (pi-ai 0.55.3 already only knew anthropic-messages); it went unnoticed because everyone used OpenAI-compatible endpoints. The bare-API create default "openai" had the same latent problem (openai-completions is the registered id).

Fix

Backend (read-time normalization — existing DB rows keep working, no migration):

  • normalizeProviderApi() in core/model-compat.ts: anthropicanthropic-messages, openaiopenai-completions, everything else passes through.
  • Applied at every boundary that builds a pi model config from model_providers.api_type: the four adapter handlers (agent settings + model-binding, HTTP and WS mirrors), chat-gateway, cli-snapshot-api (TUI snapshot), model-routing-config (fallback routing).
  • TUI Anthropic preset (provider-presets.ts) and the provider-create default now emit canonical ids.

Frontend (canonical values going forward):

  • Models page select options store anthropic-messages / openai-completions; the edit form maps a legacy stored value so it displays and re-saves correctly instead of snapping to the first option.

Deliberately untouched: the default-provider endpoints that return raw rows to sicore, and ai-security-reviewer (raw chat/completions fetch, not pi) — normalizing those could change consumer-side comparisons.

Testing

  • New unit tests: normalizeProviderApi (legacy mapping, passthrough, case/whitespace tolerance, empty fallback) and frontend normalizeApiType.
  • tsc --noEmit clean on backend + portal-web; backend suite green at repo root; portal-web tests pass.

🤖 Generated with Claude Code

…i ids

Selecting "Anthropic" as a model provider has never worked: the option
stored api_type="anthropic", which flowed verbatim into every model
config's `api` field — but pi-ai's API-provider registry only knows
"anthropic-messages" ("anthropic" is a provider slug there, not an
api), so every turn failed with "No API provider registered for api:
anthropic". The bare-API default "openai" had the same latent problem.

Fix on both sides:
- normalizeProviderApi() in core/model-compat maps the legacy values
  (anthropic → anthropic-messages, openai → openai-completions) and
  passes everything else through. Applied at every boundary that builds
  a pi model config from model_providers.api_type: the four adapter
  handlers (agent settings + model-binding, HTTP and WS mirrors),
  chat-gateway, cli-snapshot-api, and model-routing-config. Existing DB
  rows keep working with no migration.
- The TUI Anthropic preset and the provider-create default now emit
  canonical ids.
- Models page: select options store canonical ids; the edit form maps a
  legacy stored value so it displays (and re-saves) correctly.

Deliberately untouched: the default-provider endpoints that return raw
rows to sicore, and ai-security-reviewer (raw chat/completions fetch,
not pi) — normalizing those could change consumer-side comparisons.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants