fix(kimi-code): revert the todo panel to its pre-turn state on undo - #3016
Conversation
🦋 Changeset detectedLatest commit: fd30311 The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4021c597fa
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| const session = host.session; | ||
| if (session === undefined) return; | ||
| try { | ||
| host.streamingUI.setTodoList(await session.getTodos()); |
There was a problem hiding this comment.
Preserve the hidden state for completed todo lists
When the state before the undone turn contains only completed todos, the panel was empty because both turn-end handling and session replay deliberately hide all-done lists; this direct refresh instead remounts those completed items. For example, undoing a turn that changed an all-done list back to pending will restore the engine data but not the actual pre-turn panel state. Route the refreshed data through the same todo-display normalization used by replay/turn-end rather than setting the panel directly.
AGENTS.md reference: apps/kimi-code/AGENTS.md:L39-L40
Useful? React with 👍 / 👎.
| */ | ||
| override async getTodos(input: SessionIdRpcInput): Promise<readonly SessionTodoItem[]> { | ||
| const session = this.requireLiveSession(input.sessionId); | ||
| return session.accessor.get(ISessionTodoService).getTodos(); |
There was a problem hiding this comment.
Return a detached copy of the todo state
SDKRpcClientV2 is in-process, and ISessionTodoService.getTodos() returns the same array and item objects stored by IAgentStateService; therefore a JavaScript SDK consumer can mutate the result of session.getTodos() and silently alter live engine state without a durable event, change notification, or undo checkpoint. The TypeScript readonly annotations provide no runtime protection, so this method should clone the array and its items before exposing them.
Useful? React with 👍 / 👎.
Related Issue
No linked issue — the problem is explained below.
Problem
When the model updates the todo list during a turn and the user then runs
/undoon that turn, the todo panel keeps showing the undone turn's items instead of reverting to the pre-turn state.The engine already rolls the todo state back correctly (it is an undoable replayable state), but the TUI panel is a local copy fed only by
TodoListtool-result events. Undo produces no new tool events, and the SDK exposed no way to read the rolled-back todo state, so the stale copy lingered on screen.What changed
getTodos()session read that returns the engine's current todo state. On the v2 engine it reads the live session todo state; the v1 client answersnot_implementedsince the legacy engine has no todo read path./undohandler re-pulls the todo state after a successful undo and refreshes the panel, mirroring how resume hydrates it. If the read is unavailable or fails (e.g. the v1 engine), the panel is left untouched and the undo command still succeeds.Checklist
gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update.