Status: Complete (Phase 1–5) Scope: Provider system unification — resolve "主聊天能用、旁路功能失效" structural issue
ApiProvidermixes protocol/vendor/auth/model-mapping into one flat structureclaude-clientandtext-generatorare two independent provider resolution chains- GLM/Kimi/MiniMax/Volcengine/Bailian are Anthropic-compatible but built as
custom(OpenAI-compatible in text-generator) - Model listing relies on hardcoded base_url → model label mapping
- Bridge/chat/onboarding/checkin/plan have divergent provider resolution
- No contract tests
src/lib/provider-catalog.ts— vendor presets, default model catalogs, protocol definitionssrc/lib/provider-resolver.ts— unified provider/model resolution for all consumers
- Add
protocol,headers_json,env_overrides_json,role_models_jsontoapi_providers - Create
provider_modelstable - Migrate existing data (provider_type → protocol, extra_env → env_overrides_json)
claude-client.ts→ use resolver'stoClaudeCodeEnv()text-generator.ts→ use resolver'stoAiSdkConfig()route.ts,conversation-engine.ts,onboarding,checkin,plan→ use shared resolver
ProviderManager.tsxpresets → reference catalogProviderForm.tsx→ protocol selector instead of provider_type/api/providers/models→ read from catalog + provider_models
- Provider resolver contract tests
- Entry point consistency tests
- Preset protocol validation
- Regression tests (env cleanup, bind semantics)
| Date | Decision | Rationale |
|---|---|---|
| 2026-03-09 | Add fields to existing table, not new system | Minimize migration risk, preserve existing data |
| 2026-03-09 | Protocol-based dispatch instead of brand-name | Matches actual API behavior, extensible |
| 2026-03-09 | Merge custom-anthropic into anthropic-thirdparty | Remove user confusion between two nearly identical presets |
| 2026-03-09 | Auth env keys protected from envOverrides deletion | Legacy extra_env placeholders ({"ANTHROPIC_AUTH_TOKEN":""}) were deleting freshly-injected credentials |
| 2026-03-09 | Env var names use _MODEL suffix |
Claude Code SDK expects ANTHROPIC_DEFAULT_SONNET_MODEL, not ANTHROPIC_DEFAULT_SONNET |
- aiberm (no model mapping): ✅ responded "OK claude-sonnet-4-6"
- pipellm (with sonnet/opus/haiku mapping): ✅ responded "OK claude-sonnet-4-6"
- Unit tests: 229/229 passed