@@ -37,6 +37,7 @@ import { ProviderForm } from "./ProviderForm";
3737import type { ProviderFormData } from "./ProviderForm" ;
3838import type { ApiProvider } from "@/types" ;
3939import { useTranslation } from "@/hooks/useTranslation" ;
40+ import type { TranslationKey } from "@/i18n" ;
4041import Anthropic from "@lobehub/icons/es/Anthropic" ;
4142import OpenRouter from "@lobehub/icons/es/OpenRouter" ;
4243import Zhipu from "@lobehub/icons/es/Zhipu" ;
@@ -46,6 +47,8 @@ import Minimax from "@lobehub/icons/es/Minimax";
4647import Aws from "@lobehub/icons/es/Aws" ;
4748import Bedrock from "@lobehub/icons/es/Bedrock" ;
4849import Google from "@lobehub/icons/es/Google" ;
50+ import Volcengine from "@lobehub/icons/es/Volcengine" ;
51+ import Bailian from "@lobehub/icons/es/Bailian" ;
4952
5053// ---------------------------------------------------------------------------
5154// Brand icon resolver
@@ -62,6 +65,10 @@ function getProviderIcon(name: string, baseUrl: string): ReactNode {
6265 if ( url . includes ( "kimi.com" ) || lower . includes ( "kimi" ) ) return < Kimi size = { 18 } /> ;
6366 if ( url . includes ( "moonshot" ) || lower . includes ( "moonshot" ) ) return < Moonshot size = { 18 } /> ;
6467 if ( url . includes ( "minimax" ) || lower . includes ( "minimax" ) ) return < Minimax size = { 18 } /> ;
68+ if ( url . includes ( "volces.com" ) || url . includes ( "volcengine" ) || lower . includes ( "volcengine" ) || lower . includes ( "火山" ) || lower . includes ( "doubao" ) || lower . includes ( "豆包" ) )
69+ return < Volcengine size = { 18 } /> ;
70+ if ( url . includes ( "dashscope" ) || lower . includes ( "bailian" ) || lower . includes ( "百炼" ) || lower . includes ( "aliyun" ) )
71+ return < Bailian size = { 18 } /> ;
6572 if ( lower . includes ( "bedrock" ) ) return < Bedrock size = { 18 } /> ;
6673 if ( lower . includes ( "vertex" ) || lower . includes ( "google" ) ) return < Google size = { 18 } /> ;
6774 if ( lower . includes ( "aws" ) ) return < Aws size = { 18 } /> ;
@@ -118,7 +125,7 @@ const QUICK_PRESETS: QuickPreset[] = [
118125 description : "Anthropic-compatible API — provide URL and Key" ,
119126 descriptionZh : "Anthropic 兼容第三方 API — 填写地址和密钥" ,
120127 icon : < Anthropic size = { 18 } /> ,
121- provider_type : "custom " ,
128+ provider_type : "anthropic " ,
122129 base_url : "" ,
123130 extra_env : '{"ANTHROPIC_API_KEY":""}' ,
124131 fields : [ "name" , "api_key" , "base_url" , "model_names" ] ,
@@ -211,6 +218,28 @@ const QUICK_PRESETS: QuickPreset[] = [
211218 extra_env : '{"API_TIMEOUT_MS":"3000000","CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC":"1","ANTHROPIC_API_KEY":""}' ,
212219 fields : [ "api_key" ] ,
213220 } ,
221+ {
222+ key : "volcengine" ,
223+ name : "Volcengine Ark" ,
224+ description : "Volcengine Ark Coding Plan — Doubao, GLM, DeepSeek, Kimi" ,
225+ descriptionZh : "字节火山方舟 Coding Plan — 豆包、GLM、DeepSeek、Kimi" ,
226+ icon : < Volcengine size = { 18 } /> ,
227+ provider_type : "custom" ,
228+ base_url : "https://ark.cn-beijing.volces.com/api/coding" ,
229+ extra_env : '{"ANTHROPIC_AUTH_TOKEN":""}' ,
230+ fields : [ "api_key" , "model_names" ] ,
231+ } ,
232+ {
233+ key : "bailian" ,
234+ name : "Aliyun Bailian" ,
235+ description : "Aliyun Bailian Coding Plan — Qwen, GLM, Kimi, MiniMax" ,
236+ descriptionZh : "阿里云百炼 Coding Plan — 通义千问、GLM、Kimi、MiniMax" ,
237+ icon : < Bailian size = { 18 } /> ,
238+ provider_type : "custom" ,
239+ base_url : "https://coding.dashscope.aliyuncs.com/apps/anthropic" ,
240+ extra_env : '{"ANTHROPIC_AUTH_TOKEN":""}' ,
241+ fields : [ "api_key" ] ,
242+ } ,
214243 {
215244 key : "bedrock" ,
216245 name : "AWS Bedrock" ,
@@ -294,6 +323,7 @@ function PresetConnectDialog({
294323 const [ baseUrl , setBaseUrl ] = useState ( "" ) ;
295324 const [ name , setName ] = useState ( "" ) ;
296325 const [ extraEnv , setExtraEnv ] = useState ( "{}" ) ;
326+ const [ modelName , setModelName ] = useState ( "" ) ;
297327 const [ showAdvanced , setShowAdvanced ] = useState ( false ) ;
298328 const [ error , setError ] = useState < string | null > ( null ) ;
299329 const [ saving , setSaving ] = useState ( false ) ;
@@ -307,6 +337,7 @@ function PresetConnectDialog({
307337 setBaseUrl ( preset . base_url ) ;
308338 setName ( preset . name ) ;
309339 setExtraEnv ( preset . extra_env ) ;
340+ setModelName ( "" ) ;
310341 setError ( null ) ;
311342 setSaving ( false ) ;
312343 setShowAdvanced ( false ) ;
@@ -329,6 +360,15 @@ function PresetConnectDialog({
329360 } catch { /* use as-is */ }
330361 }
331362
363+ // Inject model name into extra_env if model_names field is used
364+ if ( preset . fields . includes ( "model_names" ) && modelName . trim ( ) ) {
365+ try {
366+ const envObj = JSON . parse ( finalExtraEnv ) ;
367+ envObj [ "ANTHROPIC_MODEL" ] = modelName . trim ( ) ;
368+ finalExtraEnv = JSON . stringify ( envObj ) ;
369+ } catch { /* use as-is */ }
370+ }
371+
332372 // Validate extra_env JSON
333373 try {
334374 JSON . parse ( finalExtraEnv ) ;
@@ -410,6 +450,24 @@ function PresetConnectDialog({
410450 </ div >
411451 ) }
412452
453+ { /* Model name — for providers that need user-specified model */ }
454+ { preset . fields . includes ( "model_names" ) && (
455+ < div className = "space-y-2" >
456+ < Label className = "text-xs text-muted-foreground" > { t ( 'provider.modelName' as TranslationKey ) } </ Label >
457+ < Input
458+ value = { modelName }
459+ onChange = { ( e ) => setModelName ( e . target . value ) }
460+ placeholder = "ark-code-latest"
461+ className = "text-sm font-mono"
462+ />
463+ < p className = "text-[11px] text-muted-foreground" >
464+ { isZh
465+ ? '在服务商控制台配置的模型名称,如 ark-code-latest、doubao-seed-2.0-code'
466+ : 'Model name configured in provider console, e.g. ark-code-latest' }
467+ </ p >
468+ </ div >
469+ ) }
470+
413471 { /* Extra env — bedrock/vertex/custom always shown */ }
414472 { preset . fields . includes ( "extra_env" ) && (
415473 < div className = "space-y-2" >
0 commit comments