fix: hide completed todos on resume (#57)

This commit is contained in:
liruifengv 2026-05-26 16:18:19 +08:00 committed by GitHub
parent 8ddfc0433e
commit 8fb61f9a3e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 72 additions and 0 deletions

View file

@ -0,0 +1,5 @@
---
"@moonshot-ai/kimi-code": patch
---
Hide the todo panel on resume when all todos are already completed.

View file

@ -139,6 +139,10 @@ function hydrateTodoPanelFromResume(
const todos = rawTodos
.filter((todo): todo is TodoItem => isTodoItemShape(todo))
.map((todo) => ({ title: todo.title, status: todo.status }));
if (todos.length > 0 && todos.every((t) => t.status === 'done')) {
hooks.setTodoList([]);
return;
}
hooks.setTodoList(todos);
}

View file

@ -350,3 +350,66 @@ describe('hydrateProjectedEntries', () => {
expect(out).toContain('✗ Failed');
});
});
describe('hydrateTodoPanelFromResume', () => {
function makeHooks(state: TUIState) {
return {
setAppState: vi.fn(),
appendEntry: vi.fn(),
setTodoList: (todos: Parameters<typeof setTodoList>[1]) => setTodoList(state, todos),
emitError: vi.fn(),
};
}
it('clears the panel when all resumed todos are done', async () => {
const state = makeTuiState();
const session = sessionWithToolStore({
todo: [
{ title: 'A', status: 'done' },
{ title: 'B', status: 'done' },
],
});
await hydrateTranscriptFromReplay(state, makeHooks(state), session);
expect(state.todoPanel.isEmpty()).toBe(true);
expect(state.todoPanelContainer.children.length).toBe(0);
});
it('restores pending and in-progress todos', async () => {
const state = makeTuiState();
const session = sessionWithToolStore({
todo: [
{ title: 'A', status: 'done' },
{ title: 'B', status: 'in_progress' },
],
});
await hydrateTranscriptFromReplay(state, makeHooks(state), session);
expect(state.todoPanel.getTodos()).toEqual([
{ title: 'A', status: 'done' },
{ title: 'B', status: 'in_progress' },
]);
expect(state.todoPanelContainer.children.length).toBe(1);
});
it('clears the panel when the tool store has no todo key', async () => {
const state = makeTuiState();
const session = sessionWithToolStore({});
await hydrateTranscriptFromReplay(state, makeHooks(state), session);
expect(state.todoPanel.isEmpty()).toBe(true);
expect(state.todoPanelContainer.children.length).toBe(0);
});
it('filters out malformed todo items', async () => {
const state = makeTuiState();
const session = sessionWithToolStore({
todo: [
{ title: 'Valid', status: 'pending' },
{ title: '', status: 'done' },
{ status: 'in_progress' },
'not-an-object',
],
});
await hydrateTranscriptFromReplay(state, makeHooks(state), session);
expect(state.todoPanel.getTodos()).toEqual([{ title: 'Valid', status: 'pending' }]);
expect(state.todoPanelContainer.children.length).toBe(1);
});
});