feat: Add model routing configuration support#1980
feat: Add model routing configuration support#1980papperrollinggery wants to merge 1 commit intofarion1231:mainfrom
Conversation
- Support routing different Claude models to different backends - Add ModelRoutingConfig data structures to provider.rs - Implement get_claude_api_format_with_model() and get_routed_base_url() - Add ModelRoutingConfigPanel UI component (426 lines) - Add useModelRoutingConfig state management hook (90 lines) - Integrate routing logic in forwarder.rs - Update zh.json and en.json translations Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 78b08fa38e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if let Some(route) = routing_config.routes.iter().find(|r| { | ||
| r.source_model.eq_ignore_ascii_case(model) | ||
| }) { | ||
| return Box::leak(route.target.api_format.clone().into_boxed_str()); |
There was a problem hiding this comment.
Stop leaking strings when selecting routed API format
get_claude_api_format_with_model now allocates and leaks memory on every matched route by returning Box::leak(...into_boxed_str()). Because this path runs per request, a busy long-lived proxy process will accumulate unreclaimed heap memory over time. This should return a non-leaking owned value (or map to known static literals) instead of manufacturing 'static strings at runtime.
Useful? React with 👍 / 👎.
| base_url = crate::proxy::providers::get_routed_base_url( | ||
| provider, | ||
| original_model, | ||
| &base_url, | ||
| ); |
There was a problem hiding this comment.
Rewrite request model when a routing rule matches
The routing integration in forward only replaces base_url (and separately API format), but it never updates the outgoing request model to RouteTarget.model_name. As a result, routes intended to map Claude model IDs to different backend model IDs still send the original Claude model upstream, which can cause wrong-model execution or upstream rejection for non-Claude backends. The matched route’s target model needs to be applied to the request body before sending.
Useful? React with 👍 / 👎.
Summary / 概述
This PR adds Model Routing feature to cc-switch, allowing a single Provider to route different Claude models to different backends based on the requested model name.
本 PR 为 cc-switch 添加了模型路由功能,允许单个 Provider 根据请求的模型名称自动路由到不同的后端服务。
Problem / 问题
apiFormatper ProviderExample / 示例:
Related Issue / 关联 Issue
Fixes #
Technical Details / 技术细节
Architecture / 架构
Routing Flow / 路由流程
modelfield from request body (case-insensitive)sourceModelinmodelRoutingConfig.routesbase_url,api_format, andmodel_namebased on target configFiles Changed / 修改的文件
Backend (Rust) - 后端:
src-tauri/src/provider.rs- AddedModelRoutingConfig,ModelRoute,RouteTarget,RouteFallbackstructssrc-tauri/src/proxy/providers/claude.rs- Addedget_claude_api_format_with_model(),get_routed_base_url()src-tauri/src/proxy/forwarder.rs- Integrated routing in 3 locations (lines 764, 870, 1383)src-tauri/src/proxy/providers/mod.rs- Exported new functionsFrontend (TypeScript) - 前端:
src/components/providers/forms/ModelRoutingConfigPanel.tsx- NEW - UI panel component (426 lines)src/components/providers/forms/hooks/useModelRoutingConfig.ts- NEW - State management hook (90 lines)src/components/providers/forms/ProviderAdvancedConfig.tsx- Integrated ModelRoutingConfigPanelsrc/components/providers/forms/ProviderForm.tsx- State and persistence managementi18n Files / 国际化
src/i18n/locales/zh.json- 中文翻译 (+18 lines)src/i18n/locales/en.json- English translation (+18 lines)Testing / 测试
Build Verification / 构建验证
pnpm typecheckpnpm format:checkcargo checkcargo clippypnpm tauri buildManual Testing / 手动测试
http://localhost:3000)Claude Opus→ Target:gemini-2.5-pro(OpenAI Chat)Claude Sonnet→ Target:gemini-2.5-flash(OpenAI Chat)Claude Haiku→ Target:MiniMax-Text-01(Anthropic)Edge Cases / 边界情况
fallback.apiFormatif configuredapiFormatBreaking Changes / 破坏性变更
None / 无 - This feature is additive and backward-compatible.
Existing Providers without
modelRoutingConfigwork unchanged. The feature only activates whenmodelRoutingConfig.enabled = true.Checklist / 检查清单
pnpm typecheckpassespnpm format:checkpassescargo clippypassesCommit / 提交
Notes / 备注
API Key Management: This implementation assumes NewAPI handles API key injection. Direct routing to external APIs requires additional key management.
Claude Adapter Only: Current implementation is for Claude adapter only. Other adapters (Gemini, MiniMax, etc.) can be extended similarly.
Security: All routing happens on the client side. Ensure the NewAPI endpoint is trusted and properly secured.