扩展阿里云订阅计划支持 - #4571
Conversation
WalkthroughThis PR introduces support for special coding plans from Aliyun/DashScope and other providers with dedicated base URL endpoints. It adds configuration mappings, updates request routing logic to prefer special plan URLs when available, implements a UI unlock flow for custom API endpoint editing, and extends internationalization support across multiple languages. Changes
Sequence DiagramsequenceDiagram
participant User as User (Frontend)
participant Controller as Controller
participant Adaptor as Ali Adaptor
participant Provider as Ali Provider
User->>Controller: Request models for Ali channel
Controller->>Controller: Check ChannelSpecialBases for base URL
alt Has Special Base URL
Controller->>Provider: Fetch from /models with OpenAIBaseURL
else Standard Ali Channel
Controller->>Provider: Fetch from /compatible-mode/v1/models
end
Provider-->>Controller: Model list
User->>User: Send request with special plan
User->>Adaptor: Process request
Adaptor->>Adaptor: Check if base URL is "special"
alt Is Claude Request
Adaptor->>Adaptor: Use ClaudeBaseURL directly
Adaptor->>Provider: Route to {ClaudeBaseURL}/v1/messages
else Is Other Format
Adaptor->>Adaptor: Use OpenAIBaseURL directly
Adaptor->>Provider: Route to {OpenAIBaseURL}/chat/completions
else Fallback
Adaptor->>Provider: Use standard Ali-compatible endpoint
end
Provider-->>Adaptor: Response
Adaptor-->>User: Processed response
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (1)
web/default/src/features/channels/components/drawers/channel-mutate-drawer.tsx (1)
404-405: ⚡ Quick winUse hierarchical i18n keys for the newly added Ali strings
New translation calls use literal English phrases as keys. Please switch these new entries to stable hierarchical keys (e.g.
channels.ali.tokenPlan,channels.ali.unlockToast,channels.ali.selectEndpoint) for consistency and maintainability.As per coding guidelines "Use hierarchical, semantically clear translation keys with consistent naming (e.g.,
dashboard.overview.title)".Also applies to: 1781-1785, 1789-1789
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/default/src/features/channels/components/drawers/channel-mutate-drawer.tsx` around lines 404 - 405, Replace the new literal-English i18n keys in ChannelMutateDrawer with hierarchical keys: locate the t(...) calls around the toast.info call and the other translation uses in this file (the ChannelMutateDrawer component) and change strings like 'Ali custom API address editing unlocked' and the other literal phrases at the noted positions to stable hierarchical keys such as channels.ali.unlockToast, channels.ali.tokenPlan, channels.ali.selectEndpoint; update the corresponding translation JSON entries to match these new keys and ensure the t(...) calls use those hierarchical keys instead of raw English sentences.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@relay/channel/ali/adaptor.go`:
- Around line 95-111: In GetRequestURL, the special-plan OpenAIBaseURL override
is applied before checking info.RelayMode, causing non-Claude requests for plans
like ali-token-plan to always route to /chat/completions; move the
specialPlan.OpenAIBaseURL handling inside the RelayMode switch (the same place
where Claude handling and supportsAliAnthropicMessages are evaluated) so that
for each RelayMode (e.g., RelayModeCompletion, RelayModeEmbedding,
RelayModeResponse, image relay) you return the mode-appropriate
OpenAI-compatible path using specialPlan.OpenAIBaseURL when present, falling
back to baseUrl paths otherwise; update logic around info.RelayFormat and
info.RelayMode in GetRequestURL to perform the OpenAIBaseURL override per mode
rather than unconditionally.
In
`@web/default/src/features/channels/components/drawers/channel-mutate-drawer.tsx`:
- Around line 1759-1762: The FormLabel currently only handles mouse clicks
(onClick={handleAliApiConfigSecretClick}) which is not keyboard-accessible; make
the unlock trigger keyboard-operable by giving the FormLabel a semantics and
keyboard handlers: add a focusable attribute (tabIndex=0), semantic role
(role="button"), an onKeyDown handler that calls handleAliApiConfigSecretClick
when Enter or Space is pressed, and include appropriate ARIA attributes (e.g.,
aria-label describing the action and aria-expanded or aria-pressed as
applicable) so screen readers and keyboard users can operate the hidden-unlock
control.
- Around line 632-638: When switching channel type to Ali (the currentType ===
17 branch in channel-mutate-drawer.tsx) we must normalize base_url instead of
only setting it when empty; update the logic in the currentType === 17 handler
(where form.getValues('base_url') and form.setValue('base_url',
'https://dashscope.aliyuncs.com') are used) to either validate the existing
base_url against an expected Ali pattern and replace it with the default if it
doesn't match, or simply overwrite it with 'https://dashscope.aliyuncs.com'
whenever currentType becomes 17 so incompatible sentinel values from other
channel types cannot persist.
In `@web/default/src/i18n/locales/fr.json`:
- Around line 211-213: The French locale has two values still in English; update
the JSON value strings for the keys "Ali Coding Plan" and "Ali Token Plan" to
their French translations so the UI is consistently localized (e.g., replace
"Ali Coding Plan" value and "Ali Token Plan" value with appropriate French
phrases matching the surrounding style).
In `@web/default/src/i18n/locales/ru.json`:
- Around line 211-213: Replace the two English display values so Russian users
don't see mixed-language options: update the JSON entries for the keys "Ali
Coding Plan" and "Ali Token Plan" to Russian strings (for example, "План
кодирования Ali" for "Ali Coding Plan" and "Токен-план Ali" or "План токенов
Ali" for "Ali Token Plan") and ensure the key "Ali custom API address editing
unlocked" remains correctly localized; edit the values for those keys in ru.json
accordingly and run a quick UI check to confirm the selector shows only Russian
labels.
In `@web/default/src/i18n/locales/vi.json`:
- Around line 211-213: The vi.json entries for the new Ali plan labels use
English values; update the values for the keys "Ali Coding Plan" and "Ali Token
Plan" to Vietnamese so the UI is fully localized (keep the keys unchanged, only
replace the right-hand string values for "Ali Coding Plan" and "Ali Token Plan"
with appropriate Vietnamese translations).
---
Nitpick comments:
In
`@web/default/src/features/channels/components/drawers/channel-mutate-drawer.tsx`:
- Around line 404-405: Replace the new literal-English i18n keys in
ChannelMutateDrawer with hierarchical keys: locate the t(...) calls around the
toast.info call and the other translation uses in this file (the
ChannelMutateDrawer component) and change strings like 'Ali custom API address
editing unlocked' and the other literal phrases at the noted positions to stable
hierarchical keys such as channels.ali.unlockToast, channels.ali.tokenPlan,
channels.ali.selectEndpoint; update the corresponding translation JSON entries
to match these new keys and ensure the t(...) calls use those hierarchical keys
instead of raw English sentences.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: b3eae75b-009a-40f6-89aa-e1171686d899
📒 Files selected for processing (11)
coding-plan.mdconstant/channel.gocontroller/channel_upstream_update.gorelay/channel/ali/adaptor.goweb/default/src/features/channels/components/drawers/channel-mutate-drawer.tsxweb/default/src/i18n/locales/en.jsonweb/default/src/i18n/locales/fr.jsonweb/default/src/i18n/locales/ja.jsonweb/default/src/i18n/locales/ru.jsonweb/default/src/i18n/locales/vi.jsonweb/default/src/i18n/locales/zh.json
| func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) { | ||
| var fullRequestURL string | ||
| baseUrl := info.ChannelBaseUrl | ||
| specialPlan, hasSpecialPlan := channelconstant.ChannelSpecialBases[baseUrl] | ||
|
|
||
| switch info.RelayFormat { | ||
| case types.RelayFormatClaude: | ||
| if hasSpecialPlan && specialPlan.ClaudeBaseURL != "" { | ||
| return fmt.Sprintf("%s/v1/messages", specialPlan.ClaudeBaseURL), nil | ||
| } | ||
| if supportsAliAnthropicMessages(info.UpstreamModelName) { | ||
| fullRequestURL = fmt.Sprintf("%s/apps/anthropic/v1/messages", info.ChannelBaseUrl) | ||
| } else { | ||
| fullRequestURL = fmt.Sprintf("%s/compatible-mode/v1/chat/completions", info.ChannelBaseUrl) | ||
| return fmt.Sprintf("%s/apps/anthropic/v1/messages", baseUrl), nil | ||
| } | ||
| return fmt.Sprintf("%s/compatible-mode/v1/chat/completions", baseUrl), nil | ||
| default: | ||
| if hasSpecialPlan && specialPlan.OpenAIBaseURL != "" { | ||
| return fmt.Sprintf("%s/chat/completions", specialPlan.OpenAIBaseURL), nil | ||
| } |
There was a problem hiding this comment.
Keep special-plan routing mode-aware.
This early return sends every non-Claude special-plan request to /chat/completions, so embeddings, completions, responses, and any image relay that reaches this path will hit the wrong upstream endpoint once ChannelBaseUrl is ali-token-plan or ali-coding-plan. Move the OpenAIBaseURL override inside the RelayMode switch so each mode still maps to its own OpenAI-compatible path.
Suggested direction
default:
- if hasSpecialPlan && specialPlan.OpenAIBaseURL != "" {
- return fmt.Sprintf("%s/chat/completions", specialPlan.OpenAIBaseURL), nil
- }
+ openAIBaseURL := baseUrl
+ if hasSpecialPlan && specialPlan.OpenAIBaseURL != "" {
+ openAIBaseURL = specialPlan.OpenAIBaseURL
+ }
switch info.RelayMode {
case constant.RelayModeEmbeddings:
+ if hasSpecialPlan && specialPlan.OpenAIBaseURL != "" {
+ return fmt.Sprintf("%s/embeddings", openAIBaseURL), nil
+ }
return fmt.Sprintf("%s/compatible-mode/v1/embeddings", baseUrl), nil
case constant.RelayModeRerank:
return fmt.Sprintf("%s/api/v1/services/rerank/text-rerank/text-rerank", baseUrl), nil
case constant.RelayModeResponses:
+ if hasSpecialPlan && specialPlan.OpenAIBaseURL != "" {
+ return fmt.Sprintf("%s/responses", openAIBaseURL), nil
+ }
return fmt.Sprintf("%s/api/v2/apps/protocols/compatible-mode/v1/responses", baseUrl), nil
case constant.RelayModeImagesGenerations:
if isSyncImageModel(info.OriginModelName) {
return fmt.Sprintf("%s/api/v1/services/aigc/multimodal-generation/generation", baseUrl), nil
} else {
return fmt.Sprintf("%s/api/v1/services/aigc/text2image/image-synthesis", baseUrl), nil
}
case constant.RelayModeImagesEdits:
if isOldWanModel(info.OriginModelName) {
return fmt.Sprintf("%s/api/v1/services/aigc/image2image/image-synthesis", baseUrl), nil
} else if isWanModel(info.OriginModelName) {
return fmt.Sprintf("%s/api/v1/services/aigc/image-generation/generation", baseUrl), nil
} else {
return fmt.Sprintf("%s/api/v1/services/aigc/multimodal-generation/generation", baseUrl), nil
}
case constant.RelayModeCompletions:
+ if hasSpecialPlan && specialPlan.OpenAIBaseURL != "" {
+ return fmt.Sprintf("%s/completions", openAIBaseURL), nil
+ }
return fmt.Sprintf("%s/compatible-mode/v1/completions", baseUrl), nil
default:
+ if hasSpecialPlan && specialPlan.OpenAIBaseURL != "" {
+ return fmt.Sprintf("%s/chat/completions", openAIBaseURL), nil
+ }
return fmt.Sprintf("%s/compatible-mode/v1/chat/completions", baseUrl), nil
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@relay/channel/ali/adaptor.go` around lines 95 - 111, In GetRequestURL, the
special-plan OpenAIBaseURL override is applied before checking info.RelayMode,
causing non-Claude requests for plans like ali-token-plan to always route to
/chat/completions; move the specialPlan.OpenAIBaseURL handling inside the
RelayMode switch (the same place where Claude handling and
supportsAliAnthropicMessages are evaluated) so that for each RelayMode (e.g.,
RelayModeCompletion, RelayModeEmbedding, RelayModeResponse, image relay) you
return the mode-appropriate OpenAI-compatible path using
specialPlan.OpenAIBaseURL when present, falling back to baseUrl paths otherwise;
update logic around info.RelayFormat and info.RelayMode in GetRequestURL to
perform the OpenAIBaseURL override per mode rather than unconditionally.
| // Type 17 (Ali) - set default base_url | ||
| if (currentType === 17) { | ||
| const currentBaseUrlValue = form.getValues('base_url') | ||
| if (!currentBaseUrlValue || currentBaseUrlValue === '') { | ||
| form.setValue('base_url', 'https://dashscope.aliyuncs.com') | ||
| } | ||
| } |
There was a problem hiding this comment.
Normalize base_url when switching to Ali type to avoid invalid sentinel carry-over
For type 17, defaulting only on empty values lets incompatible values (e.g. from other channel types like doubao-coding-plan) persist and be submitted. This can break upstream requests.
Suggested fix
+const ALI_DEFAULT_BASE_URL = 'https://dashscope.aliyuncs.com'
+const ALI_PRESET_BASE_URLS = new Set([
+ ALI_DEFAULT_BASE_URL,
+ 'ali-token-plan',
+ 'ali-coding-plan',
+])
// Type 17 (Ali) - set default base_url
if (currentType === 17) {
- const currentBaseUrlValue = form.getValues('base_url')
- if (!currentBaseUrlValue || currentBaseUrlValue === '') {
- form.setValue('base_url', 'https://dashscope.aliyuncs.com')
- }
+ const currentBaseUrlValue = (form.getValues('base_url') || '').trim()
+ if (!currentBaseUrlValue || !ALI_PRESET_BASE_URLS.has(currentBaseUrlValue)) {
+ form.setValue('base_url', ALI_DEFAULT_BASE_URL)
+ }
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Type 17 (Ali) - set default base_url | |
| if (currentType === 17) { | |
| const currentBaseUrlValue = form.getValues('base_url') | |
| if (!currentBaseUrlValue || currentBaseUrlValue === '') { | |
| form.setValue('base_url', 'https://dashscope.aliyuncs.com') | |
| } | |
| } | |
| const ALI_DEFAULT_BASE_URL = 'https://dashscope.aliyuncs.com' | |
| const ALI_PRESET_BASE_URLS = new Set([ | |
| ALI_DEFAULT_BASE_URL, | |
| 'ali-token-plan', | |
| 'ali-coding-plan', | |
| ]) | |
| // Type 17 (Ali) - set default base_url | |
| if (currentType === 17) { | |
| const currentBaseUrlValue = (form.getValues('base_url') || '').trim() | |
| if (!currentBaseUrlValue || !ALI_PRESET_BASE_URLS.has(currentBaseUrlValue)) { | |
| form.setValue('base_url', ALI_DEFAULT_BASE_URL) | |
| } | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@web/default/src/features/channels/components/drawers/channel-mutate-drawer.tsx`
around lines 632 - 638, When switching channel type to Ali (the currentType ===
17 branch in channel-mutate-drawer.tsx) we must normalize base_url instead of
only setting it when empty; update the logic in the currentType === 17 handler
(where form.getValues('base_url') and form.setValue('base_url',
'https://dashscope.aliyuncs.com') are used) to either validate the existing
base_url against an expected Ali pattern and replace it with the default if it
doesn't match, or simply overwrite it with 'https://dashscope.aliyuncs.com'
whenever currentType becomes 17 so incompatible sentinel values from other
channel types cannot persist.
| <FormLabel | ||
| className='cursor-pointer select-none' | ||
| onClick={handleAliApiConfigSecretClick} | ||
| > |
There was a problem hiding this comment.
Make the hidden unlock interaction keyboard-operable
The unlock trigger is click-only on a label; keyboard users cannot perform this interaction.
Suggested fix
<FormLabel
- className='cursor-pointer select-none'
+ className='cursor-pointer select-none'
+ role='button'
+ tabIndex={0}
onClick={handleAliApiConfigSecretClick}
+ onKeyDown={(e) => {
+ if (e.key === 'Enter' || e.key === ' ') {
+ e.preventDefault()
+ handleAliApiConfigSecretClick()
+ }
+ }}
>As per coding guidelines "Ensure keyboard operability and logical focus order; use ARIA attributes (aria-label, aria-expanded, aria-hidden) when necessary".
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <FormLabel | |
| className='cursor-pointer select-none' | |
| onClick={handleAliApiConfigSecretClick} | |
| > | |
| <FormLabel | |
| className='cursor-pointer select-none' | |
| role='button' | |
| tabIndex={0} | |
| onClick={handleAliApiConfigSecretClick} | |
| onKeyDown={(e) => { | |
| if (e.key === 'Enter' || e.key === ' ') { | |
| e.preventDefault() | |
| handleAliApiConfigSecretClick() | |
| } | |
| }} | |
| > |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@web/default/src/features/channels/components/drawers/channel-mutate-drawer.tsx`
around lines 1759 - 1762, The FormLabel currently only handles mouse clicks
(onClick={handleAliApiConfigSecretClick}) which is not keyboard-accessible; make
the unlock trigger keyboard-operable by giving the FormLabel a semantics and
keyboard handlers: add a focusable attribute (tabIndex=0), semantic role
(role="button"), an onKeyDown handler that calls handleAliApiConfigSecretClick
when Enter or Space is pressed, and include appropriate ARIA attributes (e.g.,
aria-label describing the action and aria-expanded or aria-pressed as
applicable) so screen readers and keyboard users can operate the hidden-unlock
control.
| "Ali Coding Plan": "Ali Coding Plan", | ||
| "Ali custom API address editing unlocked": "Édition d'adresse API Ali personnalisée déverrouillée", | ||
| "Ali Token Plan": "Ali Token Plan", |
There was a problem hiding this comment.
Translate the new Ali plan labels in the French locale
Line 211 and Line 213 are still English while related strings are localized, so the selector will look mixed-language in French UI.
Proposed fix
- "Ali Coding Plan": "Ali Coding Plan",
+ "Ali Coding Plan": "Plan Ali Coding",
"Ali custom API address editing unlocked": "Édition d'adresse API Ali personnalisée déverrouillée",
- "Ali Token Plan": "Ali Token Plan",
+ "Ali Token Plan": "Plan Ali Token",🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/default/src/i18n/locales/fr.json` around lines 211 - 213, The French
locale has two values still in English; update the JSON value strings for the
keys "Ali Coding Plan" and "Ali Token Plan" to their French translations so the
UI is consistently localized (e.g., replace "Ali Coding Plan" value and "Ali
Token Plan" value with appropriate French phrases matching the surrounding
style).
| "Ali Coding Plan": "Ali Coding Plan", | ||
| "Ali custom API address editing unlocked": "Редактирование пользовательского адреса API Ali разблокировано", | ||
| "Ali Token Plan": "Ali Token Plan", |
There was a problem hiding this comment.
Localize Ali plan labels to avoid mixed-language UI in Russian
Line 211 and Line 213 keep English values, so Russian users will see mixed-language options in the same selector.
Suggested patch
- "Ali Coding Plan": "Ali Coding Plan",
+ "Ali Coding Plan": "План Ali Coding",
...
- "Ali Token Plan": "Ali Token Plan",
+ "Ali Token Plan": "План Ali Token",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "Ali Coding Plan": "Ali Coding Plan", | |
| "Ali custom API address editing unlocked": "Редактирование пользовательского адреса API Ali разблокировано", | |
| "Ali Token Plan": "Ali Token Plan", | |
| "Ali Coding Plan": "План Ali Coding", | |
| "Ali custom API address editing unlocked": "Редактирование пользовательского адреса API Ali разблокировано", | |
| "Ali Token Plan": "План Ali Token", |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/default/src/i18n/locales/ru.json` around lines 211 - 213, Replace the two
English display values so Russian users don't see mixed-language options: update
the JSON entries for the keys "Ali Coding Plan" and "Ali Token Plan" to Russian
strings (for example, "План кодирования Ali" for "Ali Coding Plan" and
"Токен-план Ali" or "План токенов Ali" for "Ali Token Plan") and ensure the key
"Ali custom API address editing unlocked" remains correctly localized; edit the
values for those keys in ru.json accordingly and run a quick UI check to confirm
the selector shows only Russian labels.
| "Ali Coding Plan": "Ali Coding Plan", | ||
| "Ali custom API address editing unlocked": "Đã mở khóa chỉnh sửa địa chỉ API Ali tùy chỉnh", | ||
| "Ali Token Plan": "Ali Token Plan", |
There was a problem hiding this comment.
Localize the new Ali plan labels for the Vietnamese locale
Line 211 and Line 213 still use English values, which causes mixed-language UI in vi.
💡 Suggested fix
- "Ali Coding Plan": "Ali Coding Plan",
+ "Ali Coding Plan": "Gói Ali Coding",
...
- "Ali Token Plan": "Ali Token Plan",
+ "Ali Token Plan": "Gói Ali Token",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "Ali Coding Plan": "Ali Coding Plan", | |
| "Ali custom API address editing unlocked": "Đã mở khóa chỉnh sửa địa chỉ API Ali tùy chỉnh", | |
| "Ali Token Plan": "Ali Token Plan", | |
| "Ali Coding Plan": "Gói Ali Coding", | |
| "Ali custom API address editing unlocked": "Đã mở khóa chỉnh sửa địa chỉ API Ali tùy chỉnh", | |
| "Ali Token Plan": "Gói Ali Token", |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/default/src/i18n/locales/vi.json` around lines 211 - 213, The vi.json
entries for the new Ali plan labels use English values; update the values for
the keys "Ali Coding Plan" and "Ali Token Plan" to Vietnamese so the UI is fully
localized (keep the keys unchanged, only replace the right-hand string values
for "Ali Coding Plan" and "Ali Token Plan" with appropriate Vietnamese
translations).
|
不考虑Coding Plan相关功能 |
Important
扩展阿里云百炼订阅计划支持,新增 Token Plan(企业版)和 Coding Plan(个人版)两种订阅渠道。
📝 变更描述 / Description
(简述:做了什么?为什么这样改能生效?请基于你对代码逻辑的理解来写,避免粘贴未经整理的内容)
阿里云百炼的订阅计划提供了独立的 API 端点,这些端点原生兼容 OpenAI 和 Anthropic 协议,因此请求无需转换为阿里 DashScope
原生格式,可以直接透传。本次变更复用了已有的 ChannelSpecialBases 机制(此前已用于火山引擎 Coding
Plan),将两种阿里云订阅计划注册为特殊 Base URL:
后端改动:
OpenAI 协议的独立端点
格式转换和专用头(X-DashScope-SSE/X-DashScope-Async),直接透传请求;Claude 格式请求委托给 Claude
适配器处理响应;同时将 GetRequestURL 从变量累加重构为提前返回,逻辑更清晰
而非硬编码的 /compatible-mode/v1/models
前端改动:
Plan
i18n 改动:
🚀 变更类型 / Type of change
🔗 关联任务 / Related Issue
✅ 提交前检查项 / Checklist
Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。📸 运行证明 / Proof of Work
(请在此粘贴截图、关键日志或测试报告,以证明变更生效)


Summary by CodeRabbit
New Features
Documentation
Internationalization