diff --git a/tests/test_tui_gateway_server.py b/tests/test_tui_gateway_server.py index dacc55df5b..2e385eec91 100644 --- a/tests/test_tui_gateway_server.py +++ b/tests/test_tui_gateway_server.py @@ -1066,6 +1066,18 @@ def test_config_set_reasoning_updates_live_session_and_agent(tmp_path, monkeypat ) assert resp_show["result"]["value"] == "show" assert server._sessions["sid"]["show_reasoning"] is True + assert server._load_cfg()["display"]["sections"]["thinking"] == "expanded" + + resp_hide = server.handle_request( + { + "id": "3", + "method": "config.set", + "params": {"session_id": "sid", "key": "reasoning", "value": "hide"}, + } + ) + assert resp_hide["result"]["value"] == "hide" + assert server._sessions["sid"]["show_reasoning"] is False + assert server._load_cfg()["display"]["sections"]["thinking"] == "hidden" def test_config_set_verbose_updates_session_mode_and_agent(tmp_path, monkeypatch): diff --git a/tui_gateway/server.py b/tui_gateway/server.py index fee8e9550e..50e6074140 100644 --- a/tui_gateway/server.py +++ b/tui_gateway/server.py @@ -3106,11 +3106,13 @@ def _(rid, params: dict) -> dict: arg = str(value or "").strip().lower() if arg in ("show", "on"): _write_config_key("display.show_reasoning", True) + _write_config_key("display.sections.thinking", "expanded") if session: session["show_reasoning"] = True return _ok(rid, {"key": key, "value": "show"}) if arg in ("hide", "off"): _write_config_key("display.show_reasoning", False) + _write_config_key("display.sections.thinking", "hidden") if session: session["show_reasoning"] = False return _ok(rid, {"key": key, "value": "hide"}) diff --git a/ui-tui/src/__tests__/createSlashHandler.test.ts b/ui-tui/src/__tests__/createSlashHandler.test.ts index 3ec340b8a2..56128e388f 100644 --- a/ui-tui/src/__tests__/createSlashHandler.test.ts +++ b/ui-tui/src/__tests__/createSlashHandler.test.ts @@ -76,6 +76,45 @@ describe('createSlashHandler', () => { }) }) + it('applies /reasoning hide to the thinking section immediately', async () => { + patchUiState({ sections: { thinking: 'expanded' }, showReasoning: true, sid: 'sid-abc' }) + const ctx = buildCtx({ + gateway: { + ...buildGateway(), + rpc: vi.fn(() => Promise.resolve({ value: 'hide' })) + } + }) + + expect(createSlashHandler(ctx)('/reasoning hide')).toBe(true) + + await vi.waitFor(() => { + expect(getUiState().showReasoning).toBe(false) + expect(getUiState().sections.thinking).toBe('hidden') + }) + expect(ctx.gateway.rpc).toHaveBeenCalledWith('config.set', { + key: 'reasoning', + session_id: 'sid-abc', + value: 'hide' + }) + }) + + it('applies /reasoning show to the thinking section immediately', async () => { + patchUiState({ sections: { thinking: 'hidden' }, showReasoning: false, sid: 'sid-abc' }) + const ctx = buildCtx({ + gateway: { + ...buildGateway(), + rpc: vi.fn(() => Promise.resolve({ value: 'show' })) + } + }) + + expect(createSlashHandler(ctx)('/reasoning show')).toBe(true) + + await vi.waitFor(() => { + expect(getUiState().showReasoning).toBe(true) + expect(getUiState().sections.thinking).toBe('expanded') + }) + }) + it('opens the skills hub locally for bare /skills', () => { const ctx = buildCtx() diff --git a/ui-tui/src/app/slash/commands/session.ts b/ui-tui/src/app/slash/commands/session.ts index ecd1b7866f..cfe84f9421 100644 --- a/ui-tui/src/app/slash/commands/session.ts +++ b/ui-tui/src/app/slash/commands/session.ts @@ -332,7 +332,29 @@ export const sessionCommands: SlashCommand[] = [ ctx.gateway .rpc('config.set', { key: 'reasoning', session_id: ctx.sid, value: arg }) - .then(ctx.guarded(r => r.value && ctx.transcript.sys(`reasoning: ${r.value}`))) + .then( + ctx.guarded(r => { + if (!r.value) { + return + } + + if (r.value === 'hide') { + patchUiState(state => ({ + ...state, + sections: { ...state.sections, thinking: 'hidden' }, + showReasoning: false + })) + } else if (r.value === 'show') { + patchUiState(state => ({ + ...state, + sections: { ...state.sections, thinking: 'expanded' }, + showReasoning: true + })) + } + + ctx.transcript.sys(`reasoning: ${r.value}`) + }) + ) } }, diff --git a/ui-tui/src/app/useMainApp.ts b/ui-tui/src/app/useMainApp.ts index 70dc96fec3..7a4633a324 100644 --- a/ui-tui/src/app/useMainApp.ts +++ b/ui-tui/src/app/useMainApp.ts @@ -711,6 +711,7 @@ export function useMainApp(gw: GatewayClient) { const anyPanelVisible = SECTION_NAMES.some( s => sectionMode(s, ui.detailsMode, ui.sections, ui.detailsModeCommandOverride) !== 'hidden' ) + const thinkingPanelVisible = sectionMode('thinking', ui.detailsMode, ui.sections, ui.detailsModeCommandOverride) !== 'hidden' const showProgressArea = useTurnSelector(state => anyPanelVisible @@ -723,7 +724,7 @@ export function useMainApp(gw: GatewayClient) { state.tools.length || state.todos.length || state.turnTrail.length || - hasReasoning || + (thinkingPanelVisible && hasReasoning) || state.activity.length ) : state.activity.some(item => item.tone !== 'info')