From b5eceaf51e426eed16625cc65d66e914a59ca018 Mon Sep 17 00:00:00 2001 From: zerob13 Date: Sat, 21 Mar 2026 15:15:12 +0800 Subject: [PATCH 1/4] fix(deepchat): support interleaved thinking --- .../configPresenter/providerDbLoader.ts | 4 + .../deepchatAgentPresenter/contextBuilder.ts | 40 ++++- .../deepchatAgentPresenter/dispatch.ts | 41 +++-- .../presenter/deepchatAgentPresenter/index.ts | 145 +++++++++++++++++- .../deepchatAgentPresenter/process.ts | 2 + .../presenter/deepchatAgentPresenter/types.ts | 16 ++ .../tables/deepchatSessions.ts | 34 +++- .../src/components/chat/ChatStatusBar.vue | 48 +++++- src/renderer/src/i18n/da-DK/chat.json | 2 + src/renderer/src/i18n/en-US/chat.json | 2 + src/renderer/src/i18n/fa-IR/chat.json | 2 + src/renderer/src/i18n/fr-FR/chat.json | 2 + src/renderer/src/i18n/he-IL/chat.json | 2 + src/renderer/src/i18n/ja-JP/chat.json | 2 + src/renderer/src/i18n/ko-KR/chat.json | 2 + src/renderer/src/i18n/pt-BR/chat.json | 2 + src/renderer/src/i18n/ru-RU/chat.json | 2 + src/renderer/src/i18n/zh-CN/chat.json | 2 + src/renderer/src/i18n/zh-HK/chat.json | 2 + src/renderer/src/i18n/zh-TW/chat.json | 2 + src/renderer/src/stores/ui/draft.ts | 9 ++ src/shared/types/agent-interface.d.ts | 1 + .../contextBuilder.test.ts | 91 +++++++++++ .../deepchatAgentPresenter.test.ts | 89 ++++++++++- .../deepchatAgentPresenter/dispatch.test.ts | 124 ++++++++++++++- test/main/presenter/sqlitePresenter.test.ts | 7 +- 26 files changed, 631 insertions(+), 44 deletions(-) diff --git a/src/main/presenter/configPresenter/providerDbLoader.ts b/src/main/presenter/configPresenter/providerDbLoader.ts index 0fc3ed170..bf4b98b8a 100644 --- a/src/main/presenter/configPresenter/providerDbLoader.ts +++ b/src/main/presenter/configPresenter/providerDbLoader.ts @@ -77,6 +77,10 @@ export class ProviderDbLoader { return provider.models.find((m) => m.id === modelId) } + getSourceUrl(): string { + return this.readMeta()?.sourceUrl?.trim() || this.getProviderDbUrl() + } + private loadFromCache(): ProviderAggregate | null { try { if (!fs.existsSync(this.cacheFilePath)) return null diff --git a/src/main/presenter/deepchatAgentPresenter/contextBuilder.ts b/src/main/presenter/deepchatAgentPresenter/contextBuilder.ts index e5ffce3f0..32c331a36 100644 --- a/src/main/presenter/deepchatAgentPresenter/contextBuilder.ts +++ b/src/main/presenter/deepchatAgentPresenter/contextBuilder.ts @@ -15,6 +15,7 @@ export type ContextBuildOptions = { summaryCursorOrderSeq?: number historyRecords?: ChatMessageRecord[] fallbackProtectedTurnCount?: number + preserveInterleavedReasoning?: boolean } type TokenizedTurn = { @@ -216,7 +217,8 @@ export function estimateMessagesTokens(messages: ChatMessage[]): number { */ export function recordToChatMessages( record: ChatMessageRecord, - supportsVision: boolean + supportsVision: boolean, + preserveInterleavedReasoning: boolean = false ): ChatMessage[] { if (isCompactionRecord(record)) { return [] @@ -228,10 +230,18 @@ export function recordToChatMessages( } const blocks = JSON.parse(record.content) as AssistantMessageBlock[] - const text = blocks + const combinedText = blocks .filter((block) => block.type === 'content' || block.type === 'reasoning_content') .map((block) => block.content) .join('') + const text = blocks + .filter((block) => block.type === 'content') + .map((block) => block.content) + .join('') + const reasoning = blocks + .filter((block) => block.type === 'reasoning_content') + .map((block) => block.content) + .join('') const toolCallBlocks = blocks.filter( (block) => @@ -244,7 +254,7 @@ export function recordToChatMessages( ) if (toolCallBlocks.length === 0) { - return [{ role: 'assistant', content: text }] + return [{ role: 'assistant', content: combinedText }] } const toolCalls: NonNullable = [] @@ -261,7 +271,7 @@ export function recordToChatMessages( } if (toolCalls.length === 0) { - return [{ role: 'assistant', content: text }] + return [{ role: 'assistant', content: combinedText }] } const assistantMessage: ChatMessage = { @@ -269,6 +279,9 @@ export function recordToChatMessages( content: text, tool_calls: toolCalls } + if (preserveInterleavedReasoning && reasoning) { + assistantMessage.reasoning_content = reasoning + } const result: ChatMessage[] = [assistantMessage] for (const block of toolCallBlocks) { @@ -284,7 +297,8 @@ export function recordToChatMessages( export function buildHistoryTurns( records: ChatMessageRecord[], - supportsVision: boolean + supportsVision: boolean, + preserveInterleavedReasoning: boolean = false ): HistoryTurn[] { const sortedRecords = [...records].sort((a, b) => a.orderSeq - b.orderSeq) const turns: ChatMessageRecord[][] = [] @@ -310,7 +324,9 @@ export function buildHistoryTurns( } return turns.map((turnRecords) => { - const messages = turnRecords.flatMap((record) => recordToChatMessages(record, supportsVision)) + const messages = turnRecords.flatMap((record) => + recordToChatMessages(record, supportsVision, preserveInterleavedReasoning) + ) return { records: turnRecords, messages, @@ -440,7 +456,11 @@ export function buildContext( options.historyRecords ?? messageStore.getMessages(sessionId).filter((message) => message.status === 'sent') const historyRecords = filterRecordsFromCursor(sentRecords, options.summaryCursorOrderSeq ?? 1) - const historyTurns = buildHistoryTurns(historyRecords, supportsVision) + const historyTurns = buildHistoryTurns( + historyRecords, + supportsVision, + options.preserveInterleavedReasoning ?? false + ) const newUserMessage = createUserChatMessage(newUserContent, supportsVision) const systemPromptTokens = systemPrompt ? approximateTokenSize(systemPrompt) : 0 @@ -530,7 +550,11 @@ export function buildResumeContext( return message.orderSeq >= cursor }) - const historyTurns = buildHistoryTurns(historyRecords, supportsVision) + const historyTurns = buildHistoryTurns( + historyRecords, + supportsVision, + options.preserveInterleavedReasoning ?? false + ) const systemPromptTokens = systemPrompt ? approximateTokenSize(systemPrompt) : 0 const available = contextLength - systemPromptTokens - reserveTokens const selectedHistory = selectTurnHistory( diff --git a/src/main/presenter/deepchatAgentPresenter/dispatch.ts b/src/main/presenter/deepchatAgentPresenter/dispatch.ts index 047129900..d9ad2ef05 100644 --- a/src/main/presenter/deepchatAgentPresenter/dispatch.ts +++ b/src/main/presenter/deepchatAgentPresenter/dispatch.ts @@ -7,7 +7,13 @@ import type { SearchResult } from '@shared/types/core/search' import type { IToolPresenter } from '@shared/types/presenters/tool.presenter' import type { AssistantMessageBlock, PermissionMode } from '@shared/types/agent-interface' import { parseQuestionToolArgs, QUESTION_TOOL_NAME } from '../../lib/agentRuntime/questionTool' -import type { IoParams, PendingToolInteraction, ProcessHooks, StreamState } from './types' +import type { + InterleavedReasoningConfig, + IoParams, + PendingToolInteraction, + ProcessHooks, + StreamState +} from './types' import type { ChatMessage } from '@shared/types/core/chat-message' import { nanoid } from 'nanoid' import type { ToolOutputGuard } from './toolOutputGuard' @@ -48,15 +54,6 @@ function extractReasoningFromBlocks(blocks: AssistantMessageBlock[]): string { .join('') } -function requiresReasoningField(modelId: string): boolean { - const lower = modelId.toLowerCase() - return ( - lower.includes('deepseek-reasoner') || - lower.includes('kimi-k2-thinking') || - lower.includes('glm-4.7') - ) -} - function toolResponseToText(content: string | MCPContentItem[]): string { if (typeof content === 'string') return content return content @@ -391,6 +388,7 @@ export async function executeTools( tools: MCPToolDefinition[], toolPresenter: IToolPresenter, modelId: string, + interleavedReasoning: InterleavedReasoningConfig, io: IoParams, permissionMode: PermissionMode, toolOutputGuard: ToolOutputGuard, @@ -425,10 +423,25 @@ export async function executeTools( })) } - if (requiresReasoningField(modelId)) { - const reasoning = extractReasoningFromBlocks(iterationBlocks) - if (reasoning) { - assistantMessage.reasoning_content = reasoning + const reasoning = extractReasoningFromBlocks(iterationBlocks) + if (interleavedReasoning.preserveReasoningContent && reasoning) { + assistantMessage.reasoning_content = reasoning + } else if ( + reasoning && + interleavedReasoning.reasoningSupported && + !interleavedReasoning.forcedBySessionSetting && + !interleavedReasoning.portraitInterleaved + ) { + const gapPayload = { + providerId: providerId?.trim() || 'unknown-provider', + modelId, + providerDbSourceUrl: interleavedReasoning.providerDbSourceUrl, + reasoningContentLength: reasoning.length, + toolCallCount: state.completedToolCalls.length + } + hooks?.onInterleavedReasoningGap?.(gapPayload) + if (!hooks?.onInterleavedReasoningGap) { + console.warn('[DeepChatDispatch] Missing interleaved reasoning portrait:', gapPayload) } } diff --git a/src/main/presenter/deepchatAgentPresenter/index.ts b/src/main/presenter/deepchatAgentPresenter/index.ts index 21e1fd233..e0a7506f8 100644 --- a/src/main/presenter/deepchatAgentPresenter/index.ts +++ b/src/main/presenter/deepchatAgentPresenter/index.ts @@ -47,10 +47,11 @@ import { PendingInputCoordinator } from './pendingInputCoordinator' import { DeepChatPendingInputStore } from './pendingInputStore' import { processStream } from './process' import { DeepChatSessionStore, type SessionSummaryState } from './sessionStore' -import type { PendingToolInteraction, ProcessResult } from './types' +import type { InterleavedReasoningConfig, PendingToolInteraction, ProcessResult } from './types' import { ToolOutputGuard } from './toolOutputGuard' import type { ProviderRequestTracePayload } from '../llmProviderPresenter/requestTrace' import type { NewSessionHooksBridge } from '../hooksNotifications/newSessionBridge' +import { providerDbLoader } from '../configPresenter/providerDbLoader' type PendingInteractionEntry = { interaction: PendingToolInteraction @@ -85,6 +86,7 @@ type PersistedSessionGenerationRow = { thinking_budget: number | null reasoning_effort: SessionGenerationSettings['reasoningEffort'] | null verbosity: SessionGenerationSettings['verbosity'] | null + force_interleaved_thinking_compat: number | null } type SystemPromptCacheEntry = { @@ -346,6 +348,11 @@ export class DeepChatAgentPresenter implements IAgentImplementation { try { const generationSettings = await this.getEffectiveSessionGenerationSettings(sessionId) + const interleavedReasoning = this.resolveInterleavedReasoningConfig( + state.providerId, + state.modelId, + generationSettings + ) const maxTokens = generationSettings.maxTokens const tools = await this.loadToolDefinitionsForSession(sessionId, projectDir) const baseSystemPrompt = await this.buildSystemPromptWithSkills( @@ -428,7 +435,8 @@ export class DeepChatAgentPresenter implements IAgentImplementation { supportsVision, { summaryCursorOrderSeq: summaryState.summaryCursorOrderSeq, - historyRecords + historyRecords, + preserveInterleavedReasoning: interleavedReasoning.preserveReasoningContent } ) @@ -453,7 +461,8 @@ export class DeepChatAgentPresenter implements IAgentImplementation { messages, projectDir, promptPreview: normalizedInput.text, - tools + tools, + interleavedReasoning }) this.applyProcessResultStatus(sessionId, result) if (result?.status === 'completed') { @@ -759,7 +768,10 @@ export class DeepChatAgentPresenter implements IAgentImplementation { } this.sessionStore.updateSessionModel(sessionId, nextProviderId, nextModelId) - this.sessionStore.updateGenerationSettings(sessionId, sanitized) + this.sessionStore.updateGenerationSettings( + sessionId, + this.buildPersistedGenerationSettingsReplacement(sanitized) + ) this.sessionGenerationSettings.set(sessionId, sanitized) this.invalidateSystemPromptCache(sessionId) } @@ -801,7 +813,10 @@ export class DeepChatAgentPresenter implements IAgentImplementation { const current = await this.getEffectiveSessionGenerationSettings(sessionId) const sanitized = await this.sanitizeGenerationSettings(providerId, modelId, settings, current) this.sessionGenerationSettings.set(sessionId, sanitized) - this.sessionStore.updateGenerationSettings(sessionId, sanitized) + this.sessionStore.updateGenerationSettings( + sessionId, + this.buildPersistedGenerationSettingsPatch(settings, sanitized) + ) if (Object.prototype.hasOwnProperty.call(settings, 'systemPrompt')) { this.invalidateSystemPromptCache(sessionId) } @@ -1122,6 +1137,7 @@ export class DeepChatAgentPresenter implements IAgentImplementation { tools?: MCPToolDefinition[] initialBlocks?: AssistantMessageBlock[] promptPreview?: string + interleavedReasoning?: InterleavedReasoningConfig }): Promise { const { sessionId, @@ -1130,7 +1146,8 @@ export class DeepChatAgentPresenter implements IAgentImplementation { projectDir, tools: providedTools, initialBlocks, - promptPreview + promptPreview, + interleavedReasoning: providedInterleavedReasoning } = args const state = this.runtimeState.get(sessionId) if (!state) { @@ -1153,6 +1170,9 @@ export class DeepChatAgentPresenter implements IAgentImplementation { ).getProviderInstance(state.providerId) const generationSettings = await this.getEffectiveSessionGenerationSettings(sessionId) + const interleavedReasoning = + providedInterleavedReasoning ?? + this.resolveInterleavedReasoningConfig(state.providerId, state.modelId, generationSettings) const baseModelConfig = this.configPresenter.getModelConfig(state.modelId, state.providerId) const modelConfig: ModelConfig = { ...baseModelConfig, @@ -1262,6 +1282,7 @@ export class DeepChatAgentPresenter implements IAgentImplementation { modelConfig, temperature, maxTokens, + interleavedReasoning, permissionMode: state.permissionMode, toolOutputGuard: this.toolOutputGuard, initialBlocks, @@ -1306,6 +1327,25 @@ export class DeepChatAgentPresenter implements IAgentImplementation { permission, tool }) + }, + onInterleavedReasoningGap: (gap) => { + console.warn( + `[DeepChatAgent] Interleaved reasoning gap detected for ${gap.providerId}/${gap.modelId}. Update provider DB metadata at ${gap.providerDbSourceUrl}.` + ) + if (!traceEnabled) { + return + } + persistMessageTrace({ + sessionId, + messageId, + providerId: state.providerId, + modelId: state.modelId, + payload: { + endpoint: 'deepchat://interleaved-reasoning-gap', + headers: {}, + body: gap + } + }) } }, io: { @@ -1460,6 +1500,11 @@ export class DeepChatAgentPresenter implements IAgentImplementation { this.setSessionStatus(sessionId, 'generating') const generationSettings = await this.getEffectiveSessionGenerationSettings(sessionId) + const interleavedReasoning = this.resolveInterleavedReasoningConfig( + state.providerId, + state.modelId, + generationSettings + ) const maxTokens = generationSettings.maxTokens const projectDir = this.resolveProjectDir(sessionId) const tools = await this.loadToolDefinitionsForSession(sessionId, projectDir) @@ -1489,7 +1534,8 @@ export class DeepChatAgentPresenter implements IAgentImplementation { this.supportsVision(state.providerId, state.modelId), { summaryCursorOrderSeq: summaryState.summaryCursorOrderSeq, - fallbackProtectedTurnCount: 1 + fallbackProtectedTurnCount: 1, + preserveInterleavedReasoning: interleavedReasoning.preserveReasoningContent } ) if (budgetToolCall?.id && budgetToolCall.name) { @@ -1534,7 +1580,8 @@ export class DeepChatAgentPresenter implements IAgentImplementation { messages: resumeContext, projectDir, tools, - initialBlocks + initialBlocks, + interleavedReasoning }) this.applyProcessResultStatus(sessionId, result) if (result?.status === 'completed') { @@ -1903,10 +1950,62 @@ export class DeepChatAgentPresenter implements IAgentImplementation { if (sessionRow.verbosity !== null) { patch.verbosity = sessionRow.verbosity } + if (typeof sessionRow.force_interleaved_thinking_compat === 'number') { + patch.forceInterleavedThinkingCompat = sessionRow.force_interleaved_thinking_compat === 1 + } return patch } + private buildPersistedGenerationSettingsPatch( + requestedPatch: Partial, + sanitized: SessionGenerationSettings + ): Partial { + const patch: Partial = {} + + if (Object.prototype.hasOwnProperty.call(requestedPatch, 'systemPrompt')) { + patch.systemPrompt = sanitized.systemPrompt + } + if (Object.prototype.hasOwnProperty.call(requestedPatch, 'temperature')) { + patch.temperature = sanitized.temperature + } + if (Object.prototype.hasOwnProperty.call(requestedPatch, 'contextLength')) { + patch.contextLength = sanitized.contextLength + } + if (Object.prototype.hasOwnProperty.call(requestedPatch, 'maxTokens')) { + patch.maxTokens = sanitized.maxTokens + } + if (Object.prototype.hasOwnProperty.call(requestedPatch, 'thinkingBudget')) { + patch.thinkingBudget = sanitized.thinkingBudget + } + if (Object.prototype.hasOwnProperty.call(requestedPatch, 'reasoningEffort')) { + patch.reasoningEffort = sanitized.reasoningEffort + } + if (Object.prototype.hasOwnProperty.call(requestedPatch, 'verbosity')) { + patch.verbosity = sanitized.verbosity + } + if (Object.prototype.hasOwnProperty.call(requestedPatch, 'forceInterleavedThinkingCompat')) { + patch.forceInterleavedThinkingCompat = sanitized.forceInterleavedThinkingCompat + } + + return patch + } + + private buildPersistedGenerationSettingsReplacement( + settings: SessionGenerationSettings + ): Partial { + return { + systemPrompt: settings.systemPrompt, + temperature: settings.temperature, + contextLength: settings.contextLength, + maxTokens: settings.maxTokens, + thinkingBudget: settings.thinkingBudget, + reasoningEffort: settings.reasoningEffort, + verbosity: settings.verbosity, + forceInterleavedThinkingCompat: settings.forceInterleavedThinkingCompat + } + } + private async buildDefaultGenerationSettings( providerId: string, modelId: string @@ -2077,9 +2176,39 @@ export class DeepChatAgentPresenter implements IAgentImplementation { delete next.verbosity } + if (Object.prototype.hasOwnProperty.call(patch, 'forceInterleavedThinkingCompat')) { + if (patch.forceInterleavedThinkingCompat === true) { + next.forceInterleavedThinkingCompat = true + } else { + delete next.forceInterleavedThinkingCompat + } + } else if (base.forceInterleavedThinkingCompat !== true) { + delete next.forceInterleavedThinkingCompat + } + return next } + private resolveInterleavedReasoningConfig( + providerId: string, + modelId: string, + generationSettings: SessionGenerationSettings + ): InterleavedReasoningConfig { + const portrait = this.getReasoningPortrait(providerId, modelId) + const forcedBySessionSetting = generationSettings.forceInterleavedThinkingCompat === true + const portraitInterleaved = portrait?.interleaved === true + const reasoningSupported = + this.configPresenter.supportsReasoningCapability?.(providerId, modelId) === true + + return { + preserveReasoningContent: forcedBySessionSetting || portraitInterleaved, + forcedBySessionSetting, + portraitInterleaved, + reasoningSupported, + providerDbSourceUrl: providerDbLoader.getSourceUrl() + } + } + private normalizeReasoningEffort( providerId: string, modelId: string | undefined, diff --git a/src/main/presenter/deepchatAgentPresenter/process.ts b/src/main/presenter/deepchatAgentPresenter/process.ts index 540afe442..ccdaebe0e 100644 --- a/src/main/presenter/deepchatAgentPresenter/process.ts +++ b/src/main/presenter/deepchatAgentPresenter/process.ts @@ -54,6 +54,7 @@ export async function processStream(params: ProcessParams): Promise void + onInterleavedReasoningGap?: (gap: { + providerId: string + modelId: string + providerDbSourceUrl: string + reasoningContentLength: number + toolCallCount: number + }) => void } export interface PendingToolInteraction { @@ -126,6 +141,7 @@ export interface ProcessParams { modelConfig: ModelConfig temperature: number maxTokens: number + interleavedReasoning: InterleavedReasoningConfig permissionMode: PermissionMode toolOutputGuard: ToolOutputGuard initialBlocks?: AssistantMessageBlock[] diff --git a/src/main/presenter/sqlitePresenter/tables/deepchatSessions.ts b/src/main/presenter/sqlitePresenter/tables/deepchatSessions.ts index 8ec3b583c..3e58cf3ec 100644 --- a/src/main/presenter/sqlitePresenter/tables/deepchatSessions.ts +++ b/src/main/presenter/sqlitePresenter/tables/deepchatSessions.ts @@ -11,6 +11,7 @@ type DeepChatSessionGenerationSettings = Pick< | 'thinkingBudget' | 'reasoningEffort' | 'verbosity' + | 'forceInterleavedThinkingCompat' > export interface DeepChatSessionRow { @@ -25,6 +26,7 @@ export interface DeepChatSessionRow { thinking_budget: number | null reasoning_effort: 'minimal' | 'low' | 'medium' | 'high' | null verbosity: 'low' | 'medium' | 'high' | null + force_interleaved_thinking_compat: number | null summary_text: string | null summary_cursor_order_seq: number | null summary_updated_at: number | null @@ -81,6 +83,10 @@ export class DeepChatSessionsTable extends BaseTable { ) } + if (version >= 17) { + columns.push('force_interleaved_thinking_compat INTEGER') + } + return ` CREATE TABLE IF NOT EXISTS deepchat_sessions ( ${columns.join(',\n ')} @@ -107,11 +113,16 @@ export class DeepChatSessionsTable extends BaseTable { ALTER TABLE deepchat_sessions ADD COLUMN summary_updated_at INTEGER; ` } + if (version === 17) { + return ` + ALTER TABLE deepchat_sessions ADD COLUMN force_interleaved_thinking_compat INTEGER; + ` + } return null } getLatestVersion(): number { - return 14 + return 17 } create( @@ -135,11 +146,12 @@ export class DeepChatSessionsTable extends BaseTable { thinking_budget, reasoning_effort, verbosity, + force_interleaved_thinking_compat, summary_text, summary_cursor_order_seq, summary_updated_at ) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` ) .run( id, @@ -153,6 +165,11 @@ export class DeepChatSessionsTable extends BaseTable { generationSettings?.thinkingBudget ?? null, generationSettings?.reasoningEffort ?? null, generationSettings?.verbosity ?? null, + generationSettings?.forceInterleavedThinkingCompat === undefined + ? null + : generationSettings.forceInterleavedThinkingCompat + ? 1 + : 0, null, 1, null @@ -194,6 +211,9 @@ export class DeepChatSessionsTable extends BaseTable { if (row.verbosity !== null) { settings.verbosity = row.verbosity } + if (typeof row.force_interleaved_thinking_compat === 'number') { + settings.forceInterleavedThinkingCompat = row.force_interleaved_thinking_compat === 1 + } return settings } @@ -240,6 +260,16 @@ export class DeepChatSessionsTable extends BaseTable { updates.push('verbosity = ?') params.push(settings.verbosity ?? null) } + if (Object.prototype.hasOwnProperty.call(settings, 'forceInterleavedThinkingCompat')) { + updates.push('force_interleaved_thinking_compat = ?') + params.push( + settings.forceInterleavedThinkingCompat === undefined + ? null + : settings.forceInterleavedThinkingCompat + ? 1 + : 0 + ) + } if (updates.length === 0) { return diff --git a/src/renderer/src/components/chat/ChatStatusBar.vue b/src/renderer/src/components/chat/ChatStatusBar.vue index 6a30b2f37..9ed23d6bd 100644 --- a/src/renderer/src/components/chat/ChatStatusBar.vue +++ b/src/renderer/src/components/chat/ChatStatusBar.vue @@ -540,6 +540,33 @@ {{ getNumericInputErrorMessage('thinkingBudget') }}
+ {{ + t('chat.advancedSettings.forceInterleavedThinkingCompatDescription') + }} +
+ {{ t('settings.model.modelConfig.interleavedThinking.description') }} +