@@ -19,6 +19,7 @@ import {
1919 type PermissionConfig ,
2020 PermissionMode ,
2121} from '../config/index.js' ;
22+ import type { ModelConfig } from '../config/types.js' ;
2223import { CompactionService } from '../context/CompactionService.js' ;
2324import { ContextManager } from '../context/ContextManager.js' ;
2425import { HookManager } from '../hooks/HookManager.js' ;
@@ -49,6 +50,7 @@ function toJsonValue(value: string | object): JsonValue {
4950 }
5051}
5152
53+
5254import { discoverSkills , injectSkillsMetadata } from '../skills/index.js' ;
5355import { SpecManager } from '../spec/SpecManager.js' ;
5456import {
@@ -59,6 +61,7 @@ import {
5961 getConfig ,
6062 getCurrentModel ,
6163 getMcpServers ,
64+ getModelById ,
6265 getThinkingModeEnabled ,
6366} from '../store/vanilla.js' ;
6467import { getBuiltinTools } from '../tools/builtin/index.js' ;
@@ -111,6 +114,7 @@ export class Agent {
111114
112115 // 当前模型的上下文窗口大小(用于 tokenUsage 上报)
113116 private currentModelMaxContextTokens ! : number ;
117+ private currentModelId ?: string ;
114118
115119 constructor (
116120 config : BladeConfig ,
@@ -144,6 +148,57 @@ export class Agent {
144148 } ) ;
145149 }
146150
151+ private resolveModelConfig ( requestedModelId ?: string ) : ModelConfig {
152+ const modelId = requestedModelId && requestedModelId !== 'inherit' ? requestedModelId : undefined ;
153+ const modelConfig = modelId ? getModelById ( modelId ) : getCurrentModel ( ) ;
154+ if ( ! modelConfig ) {
155+ throw new Error ( `❌ 模型配置未找到: ${ modelId ?? 'current' } ` ) ;
156+ }
157+ return modelConfig ;
158+ }
159+
160+ private async applyModelConfig ( modelConfig : ModelConfig , label : string ) : Promise < void > {
161+ this . log ( `${ label } ${ modelConfig . name } (${ modelConfig . model } )` ) ;
162+
163+ const modelSupportsThinking = isThinkingModel ( modelConfig ) ;
164+ const thinkingModeEnabled = getThinkingModeEnabled ( ) ;
165+ const supportsThinking = modelSupportsThinking && thinkingModeEnabled ;
166+ if ( modelSupportsThinking && ! thinkingModeEnabled ) {
167+ this . log ( `🧠 模型支持 Thinking,但用户未开启(按 Tab 开启)` ) ;
168+ } else if ( supportsThinking ) {
169+ this . log ( `🧠 Thinking 模式已启用,启用 reasoning_content 支持` ) ;
170+ }
171+
172+ this . currentModelMaxContextTokens =
173+ modelConfig . maxContextTokens ?? this . config . maxContextTokens ;
174+
175+ this . chatService = await createChatServiceAsync ( {
176+ provider : modelConfig . provider ,
177+ apiKey : modelConfig . apiKey ,
178+ model : modelConfig . model ,
179+ baseUrl : modelConfig . baseUrl ,
180+ temperature : modelConfig . temperature ?? this . config . temperature ,
181+ maxContextTokens : this . currentModelMaxContextTokens ,
182+ maxOutputTokens : modelConfig . maxOutputTokens ?? this . config . maxOutputTokens ,
183+ timeout : this . config . timeout ,
184+ supportsThinking,
185+ } ) ;
186+
187+ const contextManager = this . executionEngine ?. getContextManager ( ) ;
188+ this . executionEngine = new ExecutionEngine ( this . chatService , contextManager ) ;
189+ this . currentModelId = modelConfig . id ;
190+ }
191+
192+ private async switchModelIfNeeded ( modelId : string ) : Promise < void > {
193+ if ( ! modelId || modelId === this . currentModelId ) return ;
194+ const modelConfig = getModelById ( modelId ) ;
195+ if ( ! modelConfig ) {
196+ this . log ( `⚠️ 模型配置未找到: ${ modelId } ` ) ;
197+ return ;
198+ }
199+ await this . applyModelConfig ( modelConfig , '🔁 切换模型' ) ;
200+ }
201+
147202 /**
148203 * 快速创建并初始化 Agent 实例(静态工厂方法)
149204 * 使用 Store 获取配置
@@ -211,43 +266,8 @@ export class Agent {
211266 await this . discoverSkills ( ) ;
212267
213268 // 5. 初始化核心组件
214- // 获取当前模型配置(从 Store)
215- const modelConfig = getCurrentModel ( ) ;
216- if ( ! modelConfig ) {
217- throw new Error ( '❌ 当前模型配置未找到' ) ;
218- }
219-
220- this . log ( `🚀 使用模型: ${ modelConfig . name } (${ modelConfig . model } )` ) ;
221-
222- // 检测模型是否支持 thinking 模式,且用户已开启 thinking 模式
223- const modelSupportsThinking = isThinkingModel ( modelConfig ) ;
224- const thinkingModeEnabled = getThinkingModeEnabled ( ) ;
225- const supportsThinking = modelSupportsThinking && thinkingModeEnabled ;
226- if ( modelSupportsThinking && ! thinkingModeEnabled ) {
227- this . log ( `🧠 模型支持 Thinking,但用户未开启(按 Tab 开启)` ) ;
228- } else if ( supportsThinking ) {
229- this . log ( `🧠 Thinking 模式已启用,启用 reasoning_content 支持` ) ;
230- }
231-
232- // 保存当前模型的上下文窗口大小(用于 tokenUsage 上报)
233- this . currentModelMaxContextTokens =
234- modelConfig . maxContextTokens ?? this . config . maxContextTokens ;
235-
236- // 使用工厂函数创建 ChatService(根据 provider 选择实现)
237- this . chatService = await createChatServiceAsync ( {
238- provider : modelConfig . provider ,
239- apiKey : modelConfig . apiKey ,
240- model : modelConfig . model ,
241- baseUrl : modelConfig . baseUrl ,
242- temperature : modelConfig . temperature ?? this . config . temperature ,
243- maxContextTokens : this . currentModelMaxContextTokens , // 上下文窗口(压缩判断)
244- maxOutputTokens : modelConfig . maxOutputTokens ?? this . config . maxOutputTokens , // 输出限制(API max_tokens)
245- timeout : this . config . timeout ,
246- supportsThinking, // 传递 thinking 模式支持标志
247- } ) ;
248-
249- // 4. 初始化执行引擎
250- this . executionEngine = new ExecutionEngine ( this . chatService ) ;
269+ const modelConfig = this . resolveModelConfig ( this . runtimeOptions . modelId ) ;
270+ await this . applyModelConfig ( modelConfig , '🚀 使用模型:' ) ;
251271
252272 // 5. 初始化附件收集器(@ 文件提及)
253273 this . attachmentCollector = new AttachmentCollector ( {
@@ -814,7 +834,6 @@ IMPORTANT: Execute according to the approved plan above. Follow the steps exactl
814834 // 3. 调用 ChatService(流式或非流式)
815835 // 默认启用流式,除非显式设置 stream: false
816836 const isStreamEnabled = options ?. stream !== false ;
817-
818837 const turnResult = isStreamEnabled
819838 ? await this . processStreamResponse ( messages , tools , options )
820839 : await this . chatService . chat ( messages , tools , options ?. signal ) ;
@@ -1335,6 +1354,14 @@ IMPORTANT: Execute according to the approved plan above. Follow the steps exactl
13351354 }
13361355 }
13371356
1357+ const modelId =
1358+ result . metadata ?. modelId ?. trim ( ) ||
1359+ result . metadata ?. model ?. trim ( ) ||
1360+ undefined ;
1361+ if ( modelId ) {
1362+ await this . switchModelIfNeeded ( modelId ) ;
1363+ }
1364+
13381365 // 添加工具执行结果到消息历史
13391366 let toolResultContent = result . success
13401367 ? result . llmContent || result . displayContent || ''
0 commit comments