@@ -25,7 +25,7 @@ import type {
2525import apiService from '../../services/api'
2626
2727const SETTING_STORAGE_KEY = 'tiny-engine-robot-settings'
28- const SETTING_VERSION = 2 // 新版本号
28+ const SETTING_VERSION = 3 // 新版本号
2929
3030const robotSettingState = reactive < RobotSettings > ( {
3131 version : SETTING_VERSION ,
@@ -37,6 +37,10 @@ const robotSettingState = reactive<RobotSettings>({
3737 serviceId : '' ,
3838 modelName : ''
3939 } ,
40+ completionModel : {
41+ serviceId : '' ,
42+ modelName : ''
43+ } ,
4044 services : [ ] ,
4145 chatMode : ChatMode . Agent ,
4246 enableThinking : false
@@ -50,6 +54,23 @@ const getAIModelOptions = () => {
5054 return mergeAIModelOptions ( DEFAULT_LLM_MODELS , customAIModels ) // eslint-disable-line
5155}
5256
57+ const QWEN_FIM_MODEL_PATTERNS = [ / ^ q w e n - c o d e r - t u r b o (?: - l a t e s t | - 0 9 1 9 ) ? $ / , / ^ q w e n 2 \. 5 - c o d e r - ( 7 | 1 4 | 3 2 ) b - i n s t r u c t $ / ]
58+ const DEEPSEEK_FIM_MODELS = new Set ( [ 'deepseek-chat' ] )
59+
60+ const matchesCompletionModel = ( modelName = '' , patterns : RegExp [ ] = [ ] , exactModels : Set < string > = new Set ( ) ) => {
61+ const normalizedModelName = modelName . toLowerCase ( )
62+
63+ if ( ! normalizedModelName ) {
64+ return false
65+ }
66+
67+ if ( exactModels . has ( normalizedModelName ) ) {
68+ return true
69+ }
70+
71+ return patterns . some ( ( pattern ) => pattern . test ( normalizedModelName ) )
72+ }
73+
5374const inferCompletionProtocol = ( {
5475 provider = '' ,
5576 baseUrl = '' ,
@@ -65,34 +86,65 @@ const inferCompletionProtocol = ({
6586 return capabilities . completionProtocol
6687 }
6788
68- const normalizedProvider = provider . toLowerCase ( )
69- if ( normalizedProvider === 'bailian' ) {
89+ if ( matchesCompletionModel ( modelName , QWEN_FIM_MODEL_PATTERNS ) ) {
7090 return 'qwen'
7191 }
72- if ( normalizedProvider === 'deepseek' ) {
92+
93+ if ( matchesCompletionModel ( modelName , [ ] , DEEPSEEK_FIM_MODELS ) ) {
7394 return 'deepseek'
7495 }
7596
97+ const normalizedProvider = provider . toLowerCase ( )
7698 const normalizedBaseUrl = baseUrl . toLowerCase ( )
77- if ( normalizedBaseUrl . includes ( 'dashscope.aliyuncs.com' ) ) {
78- return 'qwen'
79- }
80- if ( normalizedBaseUrl . includes ( 'deepseek.com' ) ) {
99+ if (
100+ normalizedProvider === 'deepseek' &&
101+ normalizedBaseUrl . includes ( 'deepseek.com' ) &&
102+ matchesCompletionModel ( modelName , [ ] , DEEPSEEK_FIM_MODELS )
103+ ) {
81104 return 'deepseek'
82105 }
83106
84- const normalizedModelName = modelName . toLowerCase ( )
85- if ( normalizedModelName . includes ( 'qwen' ) ) {
86- return 'qwen'
107+ return null
108+ }
109+
110+ // 初始化内置服务
111+ const isCompletionCapableModel = ( service : ModelService | undefined , model : ModelConfig | undefined ) => {
112+ if ( ! service || ! model ) {
113+ return false
87114 }
88- if ( normalizedModelName . includes ( 'deepseek' ) ) {
89- return 'deepseek'
115+
116+ return (
117+ inferCompletionProtocol ( {
118+ provider : service . provider ,
119+ baseUrl : service . baseUrl ,
120+ modelName : model . name ,
121+ capabilities : model . capabilities
122+ } ) !== null
123+ )
124+ }
125+
126+ const getFallbackCompletionModel = ( services : ModelService [ ] , preferredServiceId = '' ) => {
127+ const preferredService = services . find ( ( service ) => service . id === preferredServiceId )
128+ const orderedServices = preferredService
129+ ? [ preferredService , ...services . filter ( ( service ) => service . id !== preferredServiceId ) ]
130+ : services
131+
132+ for ( const service of orderedServices ) {
133+ const supportedModel = service . models . find ( ( model ) => isCompletionCapableModel ( service , model ) )
134+ if ( supportedModel ) {
135+ return {
136+ serviceId : service . id ,
137+ modelName : supportedModel . name
138+ }
139+ }
90140 }
91141
92- return null
142+ return {
143+ serviceId : '' ,
144+ modelName : ''
145+ }
93146}
94147
95- // 初始化内置服务
96148const initBuiltInServices = ( ) : ModelService [ ] => {
97149 return getAIModelOptions ( ) . map ( ( service : any ) => ( {
98150 id : service . provider ,
@@ -122,6 +174,7 @@ const initDefaultSettings = (): RobotSettings => {
122174 serviceId : '' ,
123175 modelName : ''
124176 } ,
177+ completionModel : getFallbackCompletionModel ( builtInServices ) ,
125178 services : builtInServices ,
126179 chatMode : ChatMode . Agent ,
127180 enableThinking : false
@@ -181,16 +234,23 @@ const migrateOldSettings = (oldSettings: any): RobotSettings | null => {
181234 const defaultServiceId =
182235 activeName === 'existingModels' ? services . find ( ( s ) => s . baseUrl === selectedModel ?. baseUrl ) ?. id : ''
183236
237+ const quickModel = {
238+ serviceId : defaultServiceId || '' ,
239+ modelName : selectedModel ?. completeModel || ''
240+ }
241+ const completionModel =
242+ quickModel . modelName && quickModel . serviceId
243+ ? getFallbackCompletionModel ( services , quickModel . serviceId )
244+ : getFallbackCompletionModel ( services , defaultServiceId || services [ 0 ] ?. id || '' )
245+
184246 return {
185247 version : SETTING_VERSION ,
186248 defaultModel : {
187249 serviceId : defaultServiceId || services [ 0 ] ?. id || '' ,
188250 modelName : selectedModel ?. model || services [ 0 ] ?. models [ 0 ] ?. name || ''
189251 } ,
190- quickModel : {
191- serviceId : defaultServiceId || '' ,
192- modelName : selectedModel ?. completeModel || ''
193- } ,
252+ quickModel,
253+ completionModel,
194254 services,
195255 chatMode : chatMode || ChatMode . Agent ,
196256 enableThinking : enableThinking || false
@@ -373,6 +433,22 @@ const getCompactModels = () => {
373433 return getAllAvailableModels ( ) . filter ( ( model ) => model . capabilities ?. compact )
374434}
375435
436+ const getCompletionModels = ( ) => {
437+ return robotSettingState . services . flatMap ( ( service ) =>
438+ service . models
439+ . filter ( ( model ) => isCompletionCapableModel ( service , model ) )
440+ . map ( ( model ) => ( {
441+ serviceId : service . id ,
442+ serviceName : service . label ,
443+ modelName : model . name ,
444+ modelLabel : model . label ,
445+ capabilities : model . capabilities || { } ,
446+ displayLabel : `${ service . label } - ${ model . label } ` ,
447+ value : `${ service . id } ::${ model . name } `
448+ } ) )
449+ )
450+ }
451+
376452const updateThinkingState = ( value : boolean ) => {
377453 robotSettingState . enableThinking = value
378454 saveRobotSettingState ( { enableThinking : robotSettingState . enableThinking } )
@@ -498,6 +574,35 @@ const getSelectedQuickModelInfo = (): SelectedModelInfo => {
498574 }
499575}
500576
577+ const getSelectedCompletionModelInfo = ( ) : SelectedModelInfo => {
578+ const currentService : ModelService | undefined = getServiceById ( robotSettingState . completionModel . serviceId )
579+ const currentModel : ModelConfig | undefined = currentService ?. models . find (
580+ ( m ) => m . name === robotSettingState . completionModel . modelName
581+ )
582+ const { name = '' , label = '' , capabilities = { } } = currentModel || { }
583+ const completionProtocol =
584+ inferCompletionProtocol ( {
585+ provider : currentService ?. provider ,
586+ baseUrl : currentService ?. baseUrl ,
587+ modelName : name ,
588+ capabilities
589+ } ) || null
590+
591+ const { models, ...service } = currentService ?? ( { } as Partial < ModelService > )
592+
593+ return {
594+ name,
595+ label,
596+ capabilities,
597+ service : ( currentService ? service : null ) as ModelService | null ,
598+ model : robotSettingState . completionModel . modelName ,
599+ completeModel : robotSettingState . completionModel . modelName || '' ,
600+ completionProtocol,
601+ baseUrl : currentService ?. baseUrl || '' ,
602+ apiKey : currentService ?. apiKey || ''
603+ }
604+ }
605+
501606export default ( ) => {
502607 return {
503608 // 配置状态
@@ -514,8 +619,10 @@ export default () => {
514619 getModelCapabilities,
515620 getAllAvailableModels,
516621 getCompactModels,
622+ getCompletionModels,
517623 getSelectedModelInfo, // 对话模型信息
518624 getSelectedQuickModelInfo, // 快速模型信息
625+ getSelectedCompletionModelInfo, // 代码补全模型信息
519626
520627 // 服务管理
521628 addCustomService,
0 commit comments