Files
CodePilot/docs/exec-plans/active/provider-resolver-refactor.md
T
7418andClaude Opus 4.6 f76e4747cd feat: unified provider resolver with protocol-based dispatch
Extract provider resolution logic into two new modules:
- provider-catalog.ts: vendor presets, default model catalogs, protocol definitions
- provider-resolver.ts: unified resolution for all consumers (Claude SDK, AI SDK, model listing)

DB migration:
- Add protocol, headers_json, env_overrides_json, role_models_json columns to api_providers
- Create provider_models table for per-provider model catalog

Consumer refactoring:
- claude-client.ts: replace inline env-building with toClaudeCodeEnv()
- text-generator.ts: replace inline config with toAiSdkConfig()
- conversation-engine.ts, onboarding, checkin, plan routes: use shared resolveProvider()
- /api/providers/models: read from catalog + provider_models table

UI improvements:
- Merge confusing "Custom API (Anthropic-compatible)" into "Anthropic Third-party API"
- Add 3-field model name mapping (sonnet/opus/haiku) in advanced options
- ProviderForm.tsx: support new fields (protocol, env_overrides, role_models)

Bug fixes:
- Protect auth credentials from being deleted by legacy extra_env empty-string overrides
- Fix env var names: ANTHROPIC_DEFAULT_SONNET → ANTHROPIC_DEFAULT_SONNET_MODEL (SDK convention)

Tests: 229/229 passed. Verified with aiberm (no mapping) and pipellm (with mapping).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 20:30:35 +08:00

57 lines
2.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Provider Resolver Refactor
**Status:** Complete (Phase 1–5)
**Scope:** Provider system unification — resolve "主聊天能用、旁路功能失效" structural issue
## Problem
- `ApiProvider` mixes protocol/vendor/auth/model-mapping into one flat structure
- `claude-client` and `text-generator` are 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
## Solution
### Phase 1: Core modules
- `src/lib/provider-catalog.ts` — vendor presets, default model catalogs, protocol definitions
- `src/lib/provider-resolver.ts` — unified provider/model resolution for all consumers
### Phase 2: DB migration
- Add `protocol`, `headers_json`, `env_overrides_json`, `role_models_json` to `api_providers`
- Create `provider_models` table
- Migrate existing data (provider_type → protocol, extra_env → env_overrides_json)
### Phase 3: Consumer refactoring
- `claude-client.ts` → use resolver's `toClaudeCodeEnv()`
- `text-generator.ts` → use resolver's `toAiSdkConfig()`
- `route.ts`, `conversation-engine.ts`, `onboarding`, `checkin`, `plan` → use shared resolver
### Phase 4: UI update
- `ProviderManager.tsx` presets → reference catalog
- `ProviderForm.tsx` → protocol selector instead of provider_type
- `/api/providers/models` → read from catalog + provider_models
### Phase 5: Tests
- Provider resolver contract tests
- Entry point consistency tests
- Preset protocol validation
- Regression tests (env cleanup, bind semantics)
## Decision Log
| 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` |
## Verification
- **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