diff --git a/packages/web-shell/client/utils/todos.test.ts b/packages/web-shell/client/utils/todos.test.ts index b1b07be573..36f9e2b4ad 100644 --- a/packages/web-shell/client/utils/todos.test.ts +++ b/packages/web-shell/client/utils/todos.test.ts @@ -75,6 +75,10 @@ function userMessage(id: string): Message { return { id, role: 'user', content: 'hello' }; } +function userShellMessage(id: string): Message { + return { id, role: 'user_shell', command: 'npm test', output: '' }; +} + function assistantMessage(id: string): Message { return { id, role: 'assistant', content: 'working on it' }; } @@ -110,12 +114,21 @@ describe('getFloatingTodos', () => { expect(state.sourceCallId).toBeNull(); }); - it('keeps an active list visible across later user messages', () => { + it('clears an active list after the next user message', () => { const state = getFloatingTodos([ todoWriteMessage('m1', [todo('1', 'in_progress')]), userMessage('u1'), ]); - expect(state.todos).toHaveLength(1); + expect(state.todos).toHaveLength(0); + expect(state.allCompleted).toBe(false); + }); + + it('clears an active list after the next user shell message', () => { + const state = getFloatingTodos([ + todoWriteMessage('m1', [todo('1', 'in_progress')]), + userShellMessage('shell-1'), + ]); + expect(state.todos).toHaveLength(0); expect(state.allCompleted).toBe(false); }); @@ -145,6 +158,17 @@ describe('getFloatingTodos', () => { expect(state.sourceMessageId).toBe('m2'); }); + it('shows a new active list started after clearing a stale active one', () => { + const state = getFloatingTodos([ + todoWriteMessage('m1', [todo('1', 'in_progress')]), + userMessage('u1'), + todoWriteMessage('m2', [todo('2', 'pending')]), + ]); + expect(state.todos.map((t) => t.id)).toEqual(['2']); + expect(state.allCompleted).toBe(false); + expect(state.sourceMessageId).toBe('m2'); + }); + it('ignores user messages sent before the todo update', () => { const state = getFloatingTodos([ userMessage('u1'), diff --git a/packages/web-shell/client/utils/todos.ts b/packages/web-shell/client/utils/todos.ts index bbd37e5f2b..8c2c072416 100644 --- a/packages/web-shell/client/utils/todos.ts +++ b/packages/web-shell/client/utils/todos.ts @@ -96,7 +96,7 @@ export function getFloatingTodos( let userMessageAfter = false; for (const message of messages) { - if (message.role === 'user') { + if (message.role === 'user' || message.role === 'user_shell') { userMessageAfter = true; continue; } @@ -122,9 +122,7 @@ export function getFloatingTodos( if (todos.length === 0) return EMPTY_FLOATING_TODOS; const allCompleted = !hasActiveTodos(todos); - // A finished list stays visible (the "all done" moment) only until the - // user sends the next prompt. - if (allCompleted && userMessageAfter) return EMPTY_FLOATING_TODOS; + if (userMessageAfter) return EMPTY_FLOATING_TODOS; return { todos, allCompleted, sourceMessageId, sourceCallId }; }