diff --git a/packages/desktop/src/renderer/components/agent/AcpModelSelector.tsx b/packages/desktop/src/renderer/components/agent/AcpModelSelector.tsx
index 52b048d355..07143d2470 100644
--- a/packages/desktop/src/renderer/components/agent/AcpModelSelector.tsx
+++ b/packages/desktop/src/renderer/components/agent/AcpModelSelector.tsx
@@ -17,7 +17,9 @@ import RuntimeSelectorPill, { RuntimeSelectorLoadingIndicator } from './RuntimeS
import {
composeRuntimeSelectorLabel,
getCurrentThoughtLevelLabel,
+ isThinkingModeOption,
isConfigSetting,
+ localizeThinkingModeOption,
RUNTIME_SUBMENU_TRIGGER_PROPS,
RuntimeSelectorCheckedItem,
RuntimeSelectorModelList,
@@ -69,6 +71,15 @@ const AcpModelSelector: React.FC<{
});
const defaultModelLabel = t('common.defaultModel');
+ const thinkingMode = isThinkingModeOption(thoughtLevel);
+ const displayThoughtLevel = localizeThinkingModeOption(thoughtLevel, {
+ enabled: t('agent.thinkingMode.enabled'),
+ disabled: t('agent.thinkingMode.disabled'),
+ });
+ const thoughtControlLabel = thinkingMode ? t('agent.thinkingMode.label') : t('agent.thoughtLevel.label');
+ const thoughtSwitchSuccess = thinkingMode
+ ? t('agent.thinkingMode.switchSuccess')
+ : t('agent.thoughtLevel.switchSuccess');
const rawDisplayLabel =
(model_info?.current_model_id &&
model_info.available_models.find((m) => m.id === model_info.current_model_id)?.label) ||
@@ -81,19 +92,19 @@ const AcpModelSelector: React.FC<{
defaultModelLabel,
fallbackLabel: t('conversation.welcome.useCliModel'),
});
- const combinedLabel = composeRuntimeSelectorLabel({ modelLabel: display_label, thoughtLevel });
+ const combinedLabel = composeRuntimeSelectorLabel({ modelLabel: display_label, thoughtLevel: displayThoughtLevel });
const isRuntimeSetting = isConfigSetting(setStatus);
const handleThoughtLevelSelect = useCallback(
async (value: string) => {
if (!thoughtLevel || value === thoughtLevel.currentValue || isRuntimeSetting) return;
try {
await setConfigOption(thoughtLevel.id, value);
- Message.success(t('agent.thoughtLevel.switchSuccess'));
+ Message.success(thoughtSwitchSuccess);
} catch (error) {
Message.error(t(configErrorMessageKey(error)));
}
},
- [isRuntimeSetting, setConfigOption, thoughtLevel, t]
+ [isRuntimeSetting, setConfigOption, thoughtLevel, thoughtSwitchSuccess]
);
const tooltipContent = combinedLabel;
@@ -170,12 +181,12 @@ const AcpModelSelector: React.FC<{
triggerProps={RUNTIME_SUBMENU_TRIGGER_PROPS}
title={
}
>
- {thoughtLevel.options.map((item) => (
+ {displayThoughtLevel?.options.map((item) => (
{
+ if (!option || option.options.length !== 2) return false;
+ const values = new Set(option.options.map((item) => item.value.toLowerCase()));
+ return values.has('enabled') && values.has('disabled');
+};
+
+export const localizeThinkingModeOption = (
+ option: AcpDerivedOption | null | undefined,
+ labels: { enabled: string; disabled: string }
+): AcpDerivedOption | null => {
+ if (!option) return null;
+ if (!isThinkingModeOption(option)) return option;
+ return {
+ ...option,
+ options: option.options.map((item) => ({
+ ...item,
+ label: item.value.toLowerCase() === 'enabled' ? labels.enabled : labels.disabled,
+ })),
+ };
+};
+
export const composeRuntimeSelectorLabel = ({
modelLabel,
thoughtLevel,
diff --git a/packages/desktop/src/renderer/hooks/agent/useAcpConfigOptions.ts b/packages/desktop/src/renderer/hooks/agent/useAcpConfigOptions.ts
index 2131fd9614..261a042c1d 100644
--- a/packages/desktop/src/renderer/hooks/agent/useAcpConfigOptions.ts
+++ b/packages/desktop/src/renderer/hooks/agent/useAcpConfigOptions.ts
@@ -276,7 +276,7 @@ export function useAcpConfigOptions({
setStatus,
mode: deriveSelectOption(configOptions, 'mode', ['mode']),
model: deriveSelectOption(configOptions, 'model', ['model']),
- thoughtLevel: deriveSelectOption(configOptions, 'thought_level', ['thought_level', 'reasoning_effort']),
+ thoughtLevel: deriveSelectOption(configOptions, 'thought_level', ['thought_level', 'reasoning_effort', 'thinking']),
reload,
setConfigOption,
};
diff --git a/packages/desktop/src/renderer/pages/conversation/platforms/acp/AcpSendBox.tsx b/packages/desktop/src/renderer/pages/conversation/platforms/acp/AcpSendBox.tsx
index 21305346fc..227108ad5a 100644
--- a/packages/desktop/src/renderer/pages/conversation/platforms/acp/AcpSendBox.tsx
+++ b/packages/desktop/src/renderer/pages/conversation/platforms/acp/AcpSendBox.tsx
@@ -4,6 +4,7 @@ import { isBackendHttpError } from '@/common/adapter/httpBridge';
import { isSideQuestionSupported } from '@/common/chat/sideQuestion';
import { parseError, uuid } from '@/common/utils';
import AgentModeSelector from '@/renderer/components/agent/AgentModeSelector';
+import { isThinkingModeOption, localizeThinkingModeOption } from '@/renderer/components/agent/runtimeSelectorOptions';
import CommandQueuePanel from '@/renderer/components/chat/CommandQueuePanel';
import MobileActionSheet, {
type MobileActionSheetEntry,
@@ -152,6 +153,15 @@ const AcpSendBox: React.FC<{
});
const runtimeMode = runtimeConfig.mode;
const runtimeThoughtLevel = runtimeConfig.thoughtLevel;
+ const runtimeThinkingMode = isThinkingModeOption(runtimeThoughtLevel);
+ const displayRuntimeThoughtLevel = localizeThinkingModeOption(runtimeThoughtLevel, {
+ enabled: t('agent.thinkingMode.enabled'),
+ disabled: t('agent.thinkingMode.disabled'),
+ });
+ const thoughtControlLabel = runtimeThinkingMode ? t('agent.thinkingMode.label') : t('agent.thoughtLevel.label');
+ const thoughtSwitchSuccess = runtimeThinkingMode
+ ? t('agent.thinkingMode.switchSuccess')
+ : t('agent.thoughtLevel.switchSuccess');
const handleThoughtLevelSetOption = useCallback(
async (optionId: string, value: string) => runtimeConfig.setConfigOption(optionId, value),
[runtimeConfig]
@@ -499,18 +509,18 @@ Please check your local CLI tool authentication status`,
});
}
- if (runtimeThoughtLevel) {
+ if (runtimeThoughtLevel && displayRuntimeThoughtLevel) {
entries.push({
key: 'thought-level',
icon: ,
- label: t('agent.thoughtLevel.label'),
+ label: thoughtControlLabel,
meta:
- runtimeThoughtLevel.options.find((item) => item.value === runtimeThoughtLevel.currentValue)?.label ||
+ displayRuntimeThoughtLevel.options.find((item) => item.value === runtimeThoughtLevel.currentValue)?.label ||
runtimeThoughtLevel.currentValue ||
'',
submenu: {
- title: t('agent.thoughtLevel.label'),
- options: runtimeThoughtLevel.options.map((item) => ({
+ title: thoughtControlLabel,
+ options: displayRuntimeThoughtLevel.options.map((item) => ({
key: item.value,
label: item.label,
description: item.description ?? undefined,
@@ -518,7 +528,7 @@ Please check your local CLI tool authentication status`,
})),
onSelect: (value) => {
void handleThoughtLevelSetOption(runtimeThoughtLevel.id, value)
- .then(() => Message.success(t('agent.thoughtLevel.switchSuccess')))
+ .then(() => Message.success(thoughtSwitchSuccess))
.catch((error) => Message.error(t(configErrorMessageKey(error))));
},
},
@@ -597,6 +607,7 @@ Please check your local CLI tool authentication status`,
attachEntries,
canSwitchModel,
currentMode,
+ displayRuntimeThoughtLevel,
handleSheetModeChange,
handleThoughtLevelSetOption,
isMobile,
@@ -608,6 +619,8 @@ Please check your local CLI tool authentication status`,
selectModel,
setContent,
t,
+ thoughtControlLabel,
+ thoughtSwitchSuccess,
]);
useAddEventListener('acp.selected.file', setAtPath);
diff --git a/packages/desktop/src/renderer/pages/conversation/platforms/aionrs/AionrsModelSelector.tsx b/packages/desktop/src/renderer/pages/conversation/platforms/aionrs/AionrsModelSelector.tsx
index b688ee6234..8726eb6520 100644
--- a/packages/desktop/src/renderer/pages/conversation/platforms/aionrs/AionrsModelSelector.tsx
+++ b/packages/desktop/src/renderer/pages/conversation/platforms/aionrs/AionrsModelSelector.tsx
@@ -9,6 +9,8 @@ import type { AcpConfigSetStatus, AcpDerivedOption } from '@/renderer/hooks/agen
import {
composeRuntimeSelectorLabel,
getCurrentThoughtLevelLabel,
+ isThinkingModeOption,
+ localizeThinkingModeOption,
RUNTIME_SUBMENU_TRIGGER_PROPS,
RuntimeSelectorCheckedItem,
RuntimeSelectorModelList,
@@ -44,6 +46,12 @@ const AionrsModelSelector: React.FC<{
const defaultModelLabel = t('common.defaultModel');
const current_model = selection?.current_model;
+ const thinkingMode = isThinkingModeOption(thoughtLevel);
+ const displayThoughtLevel = localizeThinkingModeOption(thoughtLevel, {
+ enabled: t('agent.thinkingMode.enabled'),
+ disabled: t('agent.thinkingMode.disabled'),
+ });
+ const thoughtControlLabel = thinkingMode ? t('agent.thinkingMode.label') : t('agent.thoughtLevel.label');
const renderLogo = () => ;
@@ -77,7 +85,7 @@ const AionrsModelSelector: React.FC<{
defaultModelLabel,
fallbackLabel: t('conversation.welcome.selectModel'),
});
- const combinedLabel = composeRuntimeSelectorLabel({ modelLabel: label, thoughtLevel });
+ const combinedLabel = composeRuntimeSelectorLabel({ modelLabel: label, thoughtLevel: displayThoughtLevel });
const handleThoughtLevelSelect = (value: string) => {
if (!thoughtLevel || value === thoughtLevel.currentValue || !onSetThoughtLevel) return;
void onSetThoughtLevel(thoughtLevel.id, value);
@@ -134,12 +142,12 @@ const AionrsModelSelector: React.FC<{
triggerProps={RUNTIME_SUBMENU_TRIGGER_PROPS}
title={
}
>
- {thoughtLevel.options.map((item) => (
+ {displayThoughtLevel?.options.map((item) => (
{
if (!runtimeMode?.currentValue) return;
@@ -511,18 +521,18 @@ const AionrsSendBox: React.FC<{
...attachEntries,
];
- if (runtimeThoughtLevel) {
+ if (runtimeThoughtLevel && displayRuntimeThoughtLevel) {
entries.splice(1, 0, {
key: 'thought-level',
icon: ,
- label: t('agent.thoughtLevel.label'),
+ label: thoughtControlLabel,
meta:
- runtimeThoughtLevel.options.find((item) => item.value === runtimeThoughtLevel.currentValue)?.label ||
+ displayRuntimeThoughtLevel.options.find((item) => item.value === runtimeThoughtLevel.currentValue)?.label ||
runtimeThoughtLevel.currentValue ||
'',
submenu: {
- title: t('agent.thoughtLevel.label'),
- options: runtimeThoughtLevel.options.map((item) => ({
+ title: thoughtControlLabel,
+ options: displayRuntimeThoughtLevel.options.map((item) => ({
key: item.value,
label: item.label,
description: item.description ?? undefined,
@@ -531,7 +541,7 @@ const AionrsSendBox: React.FC<{
onSelect: (value) => {
void runtimeConfig
.setConfigOption(runtimeThoughtLevel.id, value)
- .then(() => Message.success(t('agent.thoughtLevel.switchSuccess')))
+ .then(() => Message.success(thoughtSwitchSuccess))
.catch((error) => Message.error(t(configErrorMessageKey(error))));
},
},
@@ -588,6 +598,7 @@ const AionrsSendBox: React.FC<{
}, [
attachEntries,
currentMode,
+ displayRuntimeThoughtLevel,
dynamicModes,
handleSheetModeChange,
handleSheetModelSelect,
@@ -600,6 +611,8 @@ const AionrsSendBox: React.FC<{
runtimeThoughtLevel,
setContent,
t,
+ thoughtControlLabel,
+ thoughtSwitchSuccess,
]);
useAddEventListener('aionrs.selected.file', setAtPath);
diff --git a/packages/desktop/src/renderer/services/i18n/i18n-keys.d.ts b/packages/desktop/src/renderer/services/i18n/i18n-keys.d.ts
index 550d6eb155..5db2492dfd 100644
--- a/packages/desktop/src/renderer/services/i18n/i18n-keys.d.ts
+++ b/packages/desktop/src/renderer/services/i18n/i18n-keys.d.ts
@@ -56,6 +56,10 @@ export type I18nKey =
| 'agent.setup.noAlternatives'
| 'agent.setup.notConfigured'
| 'agent.setup.switching'
+ | 'agent.thinkingMode.disabled'
+ | 'agent.thinkingMode.enabled'
+ | 'agent.thinkingMode.label'
+ | 'agent.thinkingMode.switchSuccess'
| 'agent.thoughtLevel.label'
| 'agent.thoughtLevel.switchFailed'
| 'agent.thoughtLevel.switchSuccess'
diff --git a/packages/desktop/src/renderer/services/i18n/locales/de-DE/agent.json b/packages/desktop/src/renderer/services/i18n/locales/de-DE/agent.json
index a4b6c36d8e..8d8c35193b 100644
--- a/packages/desktop/src/renderer/services/i18n/locales/de-DE/agent.json
+++ b/packages/desktop/src/renderer/services/i18n/locales/de-DE/agent.json
@@ -44,5 +44,11 @@
"label": "Denk-Stufe",
"switchSuccess": "Denk-Stufe gewechselt",
"switchFailed": "Wechsel der Denk-Stufe fehlgeschlagen"
+ },
+ "thinkingMode": {
+ "label": "Denkmodus",
+ "enabled": "Ein",
+ "disabled": "Aus",
+ "switchSuccess": "Denkmodus gewechselt"
}
}
diff --git a/packages/desktop/src/renderer/services/i18n/locales/en-US/agent.json b/packages/desktop/src/renderer/services/i18n/locales/en-US/agent.json
index de20a3e47c..dc90fa0c43 100644
--- a/packages/desktop/src/renderer/services/i18n/locales/en-US/agent.json
+++ b/packages/desktop/src/renderer/services/i18n/locales/en-US/agent.json
@@ -44,5 +44,11 @@
"label": "Thinking Level",
"switchSuccess": "Thinking level switched",
"switchFailed": "Failed to switch thinking level"
+ },
+ "thinkingMode": {
+ "label": "Thinking Mode",
+ "enabled": "On",
+ "disabled": "Off",
+ "switchSuccess": "Thinking mode switched"
}
}
diff --git a/packages/desktop/src/renderer/services/i18n/locales/es-ES/agent.json b/packages/desktop/src/renderer/services/i18n/locales/es-ES/agent.json
index cd062de2d9..bc2ebe8c8a 100644
--- a/packages/desktop/src/renderer/services/i18n/locales/es-ES/agent.json
+++ b/packages/desktop/src/renderer/services/i18n/locales/es-ES/agent.json
@@ -44,5 +44,11 @@
"label": "Nivel de razonamiento",
"switchSuccess": "Nivel de razonamiento cambiado",
"switchFailed": "Error al cambiar el nivel de razonamiento"
+ },
+ "thinkingMode": {
+ "label": "Modo de razonamiento",
+ "enabled": "Activado",
+ "disabled": "Desactivado",
+ "switchSuccess": "Modo de razonamiento cambiado"
}
}
diff --git a/packages/desktop/src/renderer/services/i18n/locales/fa-IR/agent.json b/packages/desktop/src/renderer/services/i18n/locales/fa-IR/agent.json
index 7eb1f18331..4be5aec90f 100644
--- a/packages/desktop/src/renderer/services/i18n/locales/fa-IR/agent.json
+++ b/packages/desktop/src/renderer/services/i18n/locales/fa-IR/agent.json
@@ -44,5 +44,11 @@
"label": "سطح تفکر",
"switchSuccess": "سطح تفکر تغییر کرد",
"switchFailed": "تغییر سطح تفکر ناموفق بود"
+ },
+ "thinkingMode": {
+ "label": "حالت تفکر",
+ "enabled": "فعال",
+ "disabled": "غیرفعال",
+ "switchSuccess": "حالت تفکر تغییر کرد"
}
}
diff --git a/packages/desktop/src/renderer/services/i18n/locales/fr-FR/agent.json b/packages/desktop/src/renderer/services/i18n/locales/fr-FR/agent.json
index 698d94992e..ec2295dda9 100644
--- a/packages/desktop/src/renderer/services/i18n/locales/fr-FR/agent.json
+++ b/packages/desktop/src/renderer/services/i18n/locales/fr-FR/agent.json
@@ -42,5 +42,11 @@
"label": "Niveau de réflexion",
"switchSuccess": "Niveau de réflexion changé",
"switchFailed": "Échec du changement de niveau de réflexion"
+ },
+ "thinkingMode": {
+ "label": "Mode de réflexion",
+ "enabled": "Activé",
+ "disabled": "Désactivé",
+ "switchSuccess": "Mode de réflexion modifié"
}
}
diff --git a/packages/desktop/src/renderer/services/i18n/locales/ja-JP/agent.json b/packages/desktop/src/renderer/services/i18n/locales/ja-JP/agent.json
index b4a116d7e3..127b1b8006 100644
--- a/packages/desktop/src/renderer/services/i18n/locales/ja-JP/agent.json
+++ b/packages/desktop/src/renderer/services/i18n/locales/ja-JP/agent.json
@@ -44,5 +44,11 @@
"label": "思考レベル",
"switchSuccess": "思考レベルを切り替えました",
"switchFailed": "思考レベルの切り替えに失敗しました"
+ },
+ "thinkingMode": {
+ "label": "思考モード",
+ "enabled": "オン",
+ "disabled": "オフ",
+ "switchSuccess": "思考モードを切り替えました"
}
}
diff --git a/packages/desktop/src/renderer/services/i18n/locales/ko-KR/agent.json b/packages/desktop/src/renderer/services/i18n/locales/ko-KR/agent.json
index 456ba82408..c64e54b345 100644
--- a/packages/desktop/src/renderer/services/i18n/locales/ko-KR/agent.json
+++ b/packages/desktop/src/renderer/services/i18n/locales/ko-KR/agent.json
@@ -44,5 +44,11 @@
"label": "사고 강도",
"switchSuccess": "사고 강도가 전환되었습니다",
"switchFailed": "사고 강도 전환에 실패했습니다"
+ },
+ "thinkingMode": {
+ "label": "사고 모드",
+ "enabled": "켜기",
+ "disabled": "끄기",
+ "switchSuccess": "사고 모드가 전환되었습니다"
}
}
diff --git a/packages/desktop/src/renderer/services/i18n/locales/pt-BR/agent.json b/packages/desktop/src/renderer/services/i18n/locales/pt-BR/agent.json
index 4a36eb5dd4..2c62d37724 100644
--- a/packages/desktop/src/renderer/services/i18n/locales/pt-BR/agent.json
+++ b/packages/desktop/src/renderer/services/i18n/locales/pt-BR/agent.json
@@ -44,5 +44,11 @@
"label": "Nível de raciocínio",
"switchSuccess": "Nível de raciocínio alterado",
"switchFailed": "Falha ao alterar o nível de raciocínio"
+ },
+ "thinkingMode": {
+ "label": "Modo de raciocínio",
+ "enabled": "Ativado",
+ "disabled": "Desativado",
+ "switchSuccess": "Modo de raciocínio alterado"
}
}
diff --git a/packages/desktop/src/renderer/services/i18n/locales/ru-RU/agent.json b/packages/desktop/src/renderer/services/i18n/locales/ru-RU/agent.json
index 580ac7f59d..8fcb4eecae 100644
--- a/packages/desktop/src/renderer/services/i18n/locales/ru-RU/agent.json
+++ b/packages/desktop/src/renderer/services/i18n/locales/ru-RU/agent.json
@@ -44,5 +44,11 @@
"label": "Уровень рассуждений",
"switchSuccess": "Уровень рассуждений переключен",
"switchFailed": "Не удалось переключить уровень рассуждений"
+ },
+ "thinkingMode": {
+ "label": "Режим рассуждений",
+ "enabled": "Включён",
+ "disabled": "Выключен",
+ "switchSuccess": "Режим рассуждений переключён"
}
}
diff --git a/packages/desktop/src/renderer/services/i18n/locales/tr-TR/agent.json b/packages/desktop/src/renderer/services/i18n/locales/tr-TR/agent.json
index fa7b1551ae..0cb9149b79 100644
--- a/packages/desktop/src/renderer/services/i18n/locales/tr-TR/agent.json
+++ b/packages/desktop/src/renderer/services/i18n/locales/tr-TR/agent.json
@@ -44,5 +44,11 @@
"label": "Düşünme düzeyi",
"switchSuccess": "Düşünme düzeyi değiştirildi",
"switchFailed": "Düşünme düzeyi değiştirilemedi"
+ },
+ "thinkingMode": {
+ "label": "Düşünme modu",
+ "enabled": "Açık",
+ "disabled": "Kapalı",
+ "switchSuccess": "Düşünme modu değiştirildi"
}
}
diff --git a/packages/desktop/src/renderer/services/i18n/locales/uk-UA/agent.json b/packages/desktop/src/renderer/services/i18n/locales/uk-UA/agent.json
index 7ee89bce2b..dd6ef8d3ef 100644
--- a/packages/desktop/src/renderer/services/i18n/locales/uk-UA/agent.json
+++ b/packages/desktop/src/renderer/services/i18n/locales/uk-UA/agent.json
@@ -44,5 +44,11 @@
"label": "Рівень міркування",
"switchSuccess": "Рівень міркування змінено",
"switchFailed": "Не вдалося змінити рівень міркування"
+ },
+ "thinkingMode": {
+ "label": "Режим міркування",
+ "enabled": "Увімкнено",
+ "disabled": "Вимкнено",
+ "switchSuccess": "Режим міркування перемкнено"
}
}
diff --git a/packages/desktop/src/renderer/services/i18n/locales/zh-CN/agent.json b/packages/desktop/src/renderer/services/i18n/locales/zh-CN/agent.json
index 486d2a1c83..45e38b4d66 100644
--- a/packages/desktop/src/renderer/services/i18n/locales/zh-CN/agent.json
+++ b/packages/desktop/src/renderer/services/i18n/locales/zh-CN/agent.json
@@ -44,5 +44,11 @@
"label": "思考强度",
"switchSuccess": "思考强度切换成功",
"switchFailed": "思考强度切换失败"
+ },
+ "thinkingMode": {
+ "label": "思考模式",
+ "enabled": "开启",
+ "disabled": "关闭",
+ "switchSuccess": "思考模式切换成功"
}
}
diff --git a/packages/desktop/src/renderer/services/i18n/locales/zh-TW/agent.json b/packages/desktop/src/renderer/services/i18n/locales/zh-TW/agent.json
index 8a41af3894..7a24c04da8 100644
--- a/packages/desktop/src/renderer/services/i18n/locales/zh-TW/agent.json
+++ b/packages/desktop/src/renderer/services/i18n/locales/zh-TW/agent.json
@@ -44,5 +44,11 @@
"label": "思考強度",
"switchSuccess": "思考強度切換成功",
"switchFailed": "思考強度切換失敗"
+ },
+ "thinkingMode": {
+ "label": "思考模式",
+ "enabled": "開啟",
+ "disabled": "關閉",
+ "switchSuccess": "思考模式切換成功"
}
}
diff --git a/packages/desktop/src/renderer/utils/model/agentRuntimeCatalog.ts b/packages/desktop/src/renderer/utils/model/agentRuntimeCatalog.ts
index 371bcdc181..7fdb9a34ad 100644
--- a/packages/desktop/src/renderer/utils/model/agentRuntimeCatalog.ts
+++ b/packages/desktop/src/renderer/utils/model/agentRuntimeCatalog.ts
@@ -238,6 +238,7 @@ export function buildAgentRuntimeThoughtLevelOption(
return buildSelectOptionFromConfigOptions(normalizeConfigOptions(agent.config_options), 'thought_level', [
'thought_level',
'reasoning_effort',
+ 'thinking',
]);
}
diff --git a/tests/unit/acpConfigOptions.test.ts b/tests/unit/acpConfigOptions.test.ts
index bcf460e275..cd65059902 100644
--- a/tests/unit/acpConfigOptions.test.ts
+++ b/tests/unit/acpConfigOptions.test.ts
@@ -56,6 +56,30 @@ describe('ACP config option derivation', () => {
expect(thought?.options.map((item) => item.value)).toEqual(['low', 'high']);
});
+ it('recognizes a binary thinking option from a third-party runtime', () => {
+ const backendOptions = [
+ {
+ id: 'thinking',
+ option_type: 'select',
+ current_value: 'enabled',
+ options: [
+ { value: 'enabled', name: 'Enabled' },
+ { value: 'disabled', name: 'Disabled' },
+ ],
+ },
+ ] as AcpConfigOptionDto[];
+
+ const thought = deriveSelectOption(backendOptions, 'thought_level', [
+ 'thought_level',
+ 'reasoning_effort',
+ 'thinking',
+ ]);
+
+ expect(thought?.id).toBe('thinking');
+ expect(thought?.currentValue).toBe('enabled');
+ expect(thought?.options.map((item) => item.value)).toEqual(['enabled', 'disabled']);
+ });
+
it('accepts only observed set responses with matching current_value', () => {
const response: SetConfigOptionResponse = {
confirmation: 'observed',
diff --git a/tests/unit/renderer/AcpModelSelector.dom.test.tsx b/tests/unit/renderer/AcpModelSelector.dom.test.tsx
index 0303227441..44714932ff 100644
--- a/tests/unit/renderer/AcpModelSelector.dom.test.tsx
+++ b/tests/unit/renderer/AcpModelSelector.dom.test.tsx
@@ -47,6 +47,16 @@ const thoughtLevel: AcpDerivedOption = {
],
};
+const thinkingMode: AcpDerivedOption = {
+ id: 'thinking',
+ category: 'thought_level',
+ currentValue: 'enabled',
+ options: [
+ { value: 'enabled', label: 'Enabled' },
+ { value: 'disabled', label: 'Disabled' },
+ ],
+};
+
const makeResult = (overrides: Partial = {}): MockAcpModelInfoResult => ({
model_info: modelInfo,
canSwitch: true,
@@ -96,6 +106,10 @@ vi.mock('react-i18next', () => ({
t: (key: string, options?: { defaultValue?: string }) => {
if (key === 'agent.thoughtLevel.label') return 'Thinking Level';
if (key === 'agent.thoughtLevel.switchSuccess') return 'agent.thoughtLevel.switchSuccess';
+ if (key === 'agent.thinkingMode.label') return 'Thinking Mode';
+ if (key === 'agent.thinkingMode.enabled') return 'On';
+ if (key === 'agent.thinkingMode.disabled') return 'Off';
+ if (key === 'agent.thinkingMode.switchSuccess') return 'agent.thinkingMode.switchSuccess';
if (key === 'agent.config.commandAck') return 'agent.config.commandAck';
if (key === 'common.model') return 'Model';
if (key === 'common.defaultModel') return 'Default';
@@ -360,6 +374,22 @@ describe('AcpModelSelector runtime options', () => {
expect(messageSuccessMock).toHaveBeenCalledWith('agent.thoughtLevel.switchSuccess');
});
+ it('renders and switches a binary thinking mode exposed by the runtime', async () => {
+ const setConfigOption = vi.fn().mockResolvedValue(undefined);
+ useAcpModelInfoMock.mockReturnValue(makeResult({ thoughtLevel: thinkingMode, setConfigOption }));
+
+ render();
+
+ expect(screen.getByTestId('acp-model-selector')).toHaveTextContent('GPT-5.2 · On');
+ expect(screen.getAllByTestId('submenu-title')[1]).toHaveTextContent('Thinking Mode');
+ fireEvent.click(screen.getByText('Off'));
+
+ await waitFor(() => {
+ expect(setConfigOption).toHaveBeenCalledWith('thinking', 'disabled');
+ });
+ expect(messageSuccessMock).toHaveBeenCalledWith('agent.thinkingMode.switchSuccess');
+ });
+
it('keeps the old thought value and shows an error when config update fails', async () => {
const setConfigOption = vi.fn().mockRejectedValue(new Error('command_ack'));
useAcpModelInfoMock.mockReturnValue(makeResult({ setConfigOption }));
diff --git a/tests/unit/renderer/AionrsModelSelector.dom.test.tsx b/tests/unit/renderer/AionrsModelSelector.dom.test.tsx
index c5aab041fb..1c3af6e0bc 100644
--- a/tests/unit/renderer/AionrsModelSelector.dom.test.tsx
+++ b/tests/unit/renderer/AionrsModelSelector.dom.test.tsx
@@ -30,6 +30,16 @@ const thoughtLevel: AcpDerivedOption = {
],
};
+const thinkingMode: AcpDerivedOption = {
+ id: 'thinking',
+ category: 'thought_level',
+ currentValue: 'enabled',
+ options: [
+ { value: 'enabled', label: 'Enabled' },
+ { value: 'disabled', label: 'Disabled' },
+ ],
+};
+
const makeSelection = (overrides: Partial = {}): AionrsModelSelection => ({
current_model: {
...provider,
@@ -72,6 +82,9 @@ vi.mock('react-i18next', () => ({
useTranslation: () => ({
t: (key: string, options?: { defaultValue?: string }) => {
if (key === 'agent.thoughtLevel.label') return 'Thinking Level';
+ if (key === 'agent.thinkingMode.label') return 'Thinking Mode';
+ if (key === 'agent.thinkingMode.enabled') return 'On';
+ if (key === 'agent.thinkingMode.disabled') return 'Off';
if (key === 'common.model') return 'Model';
if (key === 'conversation.welcome.selectModel') return 'Select model';
if (key === 'conversation.welcome.useCliModel') return 'Use CLI model';
@@ -253,4 +266,25 @@ describe('AionrsModelSelector runtime options', () => {
expect(onSetThoughtLevel).toHaveBeenCalledWith('reasoning_effort', 'low');
});
});
+
+ it('renders and switches GLM-5.2 binary thinking mode', async () => {
+ const onSetThoughtLevel = vi.fn().mockResolvedValue(undefined);
+
+ render(
+
+ );
+
+ expect(screen.getByTestId('aionrs-model-selector')).toHaveTextContent('gpt-5.2 · On');
+ expect(screen.getAllByTestId('submenu-title')[1]).toHaveTextContent('Thinking Mode');
+ fireEvent.click(screen.getByText('Off'));
+
+ await waitFor(() => {
+ expect(onSetThoughtLevel).toHaveBeenCalledWith('thinking', 'disabled');
+ });
+ });
});