limit turning off message suppression to the current turn only

This commit is contained in:
Jarrod Whelan
2026-04-07 13:43:20 -07:00
parent 75adad8018
commit 957f5639ba
2 changed files with 85 additions and 2 deletions
@@ -882,6 +882,82 @@ describe('MainContent', () => {
expect(output).toContain('Here is your answer.');
unmount();
});
it('bypasses suppression for the current turn during confirmation, but keeps old turns suppressed', async () => {
const { useConfirmingTool } = await import(
'../hooks/useConfirmingTool.js'
);
vi.mocked(useConfirmingTool).mockReturnValue({
tool: {
callId: 'call-1',
name: 'some_tool',
status: CoreToolCallStatus.AwaitingApproval,
confirmationDetails: {
type: 'confirm_shell_command' as const,
command: 'echo "hello"',
},
},
index: 0,
total: 1,
} as unknown as ConfirmingToolState);
mockUseSettings.mockReturnValue(settingsWithNarration);
const uiState = {
...defaultMockUiState,
history: [
// Previous turn: should remain suppressed
{ id: 10, type: 'user' as const, text: 'Old Turn' },
{ id: 11, type: 'gemini' as const, text: 'Old narration' },
{
id: 12,
type: 'tool_group' as const,
tools: [
{
callId: 'old',
name: 'ls',
status: CoreToolCallStatus.Success,
description: '',
resultDisplay: '',
confirmationDetails: undefined,
} as IndividualToolCallDisplay,
],
},
// Current turn: should be bypassed (shown)
{ id: 20, type: 'user' as const, text: 'Current Turn' },
{ id: 21, type: 'gemini' as const, text: 'Current narration' },
],
pendingHistoryItems: [
{
type: 'tool_group' as const,
tools: [
{
callId: 'call-1',
name: 'some_tool',
status: CoreToolCallStatus.AwaitingApproval,
description: '',
resultDisplay: '',
confirmationDetails: undefined,
} as IndividualToolCallDisplay,
],
},
],
};
const { lastFrame, unmount } = await renderWithProviders(
<MainContent />,
{
uiState: uiState as Partial<UIState>,
settings: settingsWithNarration,
},
);
const output = lastFrame();
// Old narration should STILL be suppressed
expect(output).not.toContain('Old narration');
// Current narration should be VISIBLE because of the bypass
expect(output).toContain('Current narration');
unmount();
});
});
it('renders multiple thinking messages sequentially correctly', async () => {
@@ -123,13 +123,19 @@ export const MainContent = () => {
// Rule 2: Suppress text in intermediate turns (turns containing non-topic
// tools) to hide mechanical narration.
if (turnIsIntermediate && !showConfirmationQueue) {
const isCurrentTurn = i > lastUserPromptIndex;
// Scoping the bypass to the current turn prevents old narration from reappearing.
// This logic affects the rendered height of the history list by conditionally hiding turns.
const bypassSuppression = isCurrentTurn && showConfirmationQueue;
if (turnIsIntermediate && !bypassSuppression) {
flags[i] = true;
}
// Rule 3: Suppress text that precedes a topic tool in the same turn,
// as the topic tool "replaces" it.
if (hasTopicToolInTurn && !showConfirmationQueue) {
if (hasTopicToolInTurn && !bypassSuppression) {
flags[i] = true;
}
}
@@ -141,6 +147,7 @@ export const MainContent = () => {
pendingHistoryItems,
topicUpdateNarrationEnabled,
showConfirmationQueue,
lastUserPromptIndex,
]);
const augmentedHistory = useMemo(