Skip to content

fix(kimi-code): keep the previous turn's answer visible when a task-notification turn ends - #3799

Open
kimi-agent-bot wants to merge 3 commits into
MoonshotAI:mainfrom
kimi-agent-bot:fix/task-notification-fold-boundary
Open

kimi-agent-bot wants to merge 3 commits into
MoonshotAI:mainfrom
kimi-agent-bot:fix/task-notification-fold-boundary

Conversation

@kimi-agent-bot

Copy link
Copy Markdown
Collaborator

Related Issue

Follow-up to #3154 (same root-cause family; no separate issue filed).

Problem

The TUI folds completed-turn assistant messages beyond a keep cap into a step summary, grouped by "fold segments" delimited by turn-boundary components. A turn started by a background task completion notification (detached subagent / background bash / process task injecting an origin: { kind: 'task' } user message while the agent is idle) mounts no boundary component: the injected message is never rendered, and for kind: 'agent' tasks not even a terminal status card is mounted (the termination handler only updates the original tool card in place). When such a notification turn ends, its output shares the previous user turn's fold segment, so the fold cap folds the previous turn's final answer into the step summary — the answer disappears from the transcript and cannot be expanded.

This is the same root cause as #3154 (cron-fired turns), which fixed the cron variant by treating the cron card as a fold-segment boundary.

What changed

Minimal, precedent-following fix (a turnId-ownership-based boundary rework is intentionally left for a future, unified discussion):

  • tui/kimi-tui.tsisFoldSegmentBoundaryComponent now also accepts a BackgroundAgentStatusComponent whose phase is terminal (completed / failed). started-phase cards are excluded so merely starting a background task does not fragment the active turn's fold segment. Live view and replay both mount these cards for task notifications, so the boundary exists on both paths.
  • tui/controllers/session-event-handler.ts — on background.task.terminated, mount the terminal status card for agent-kind tasks too (previously only process / question got one). This closes the tower/worker path, where no card was mounted at all, and matches what replay already renders for agent-task notifications.
  • tui/components/messages/background-agent-status.ts — expose the card's phase for the boundary check.
  • One pre-existing replay test asserted the old no-card behavior for agent-kind termination; updated to assert exactly one terminal card is mounted and a later aborted subagent.failed does not add a contradictory one.

Trade-off, same as #3154 accepted for mid-turn cron fires: a task that terminates while a turn is still running inserts a segment boundary mid-turn, so that turn's earlier steps may stay expanded instead of being folded. Correctness (never folding away an answer) takes precedence over compactness.

Known limitation: a notification whose terminal event this TUI session never saw (e.g. restored after an engine restart) still mounts no card and gets no boundary; replay of such history is covered because replay mounts the card from the notification record itself.

Tests

New regression tests (all fail before the fix, pass after):

  • test/tui/kimi-tui-message-flow.test.ts — "keeps the previous turn's final answer mounted when a task-notification turn completes" (background bash) and "...when a background-agent notification turn completes" (tower/worker path).
  • test/tui/message-replay.test.ts — "keeps the previous turn's final answer visible when a task-notification turn follows in replay".

Full test/tui suite green (one pre-existing, environment-dependent failure in test/tui/commands/registry.test.ts — it reads $HOME and fails identically on a clean checkout). tsc --noEmit clean; oxlint --type-aware 0 errors.

Checklist

@changeset-bot

changeset-bot Bot commented Sep 15, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: e6bd3d7

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Patch

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

@pkg-pr-new

pkg-pr-new Bot commented Sep 15, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@e6bd3d7
npx https://pkg.pr.new/@moonshot-ai/kimi-code@e6bd3d7

commit: e6bd3d7

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@kimi-agent-bot

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c116ccc52e

ℹ️ 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".

Comment thread apps/kimi-code/src/tui/kimi-tui.ts
A terminal background-task card mounts when the task terminates, which is
decoupled from turn boundaries: a task that finishes mid-turn lands its
card inside the live turn's output. When the notification for that card
later missed the turn drain and opened its own turn, that turn had no
boundary of its own, so its end-of-turn fold segment started at the
stray card and the completed-turn assistant cap folded the previous
notification turn's final answer into the step summary.

Give every task-notification turn (turn.started with a task origin) its
own boundary at turn start: re-anchor the task's mounted terminal card
to the turn, or mount one when none is mounted. Terminal cards stay in
the fold-segment boundary whitelist as a fallback for cards that never
get a notification turn (resumed sessions, replay).
@kimi-agent-bot

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e6bd3d73c0

ℹ️ 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".

Comment on lines +1308 to +1312
const mounted = this.backgroundTaskTerminalEntries.get(taskId);
if (mounted !== undefined && this.host.moveTranscriptEntryToEnd(mounted)) return;
const task = this.backgroundTasks.get(taskId);
if (task === undefined) return;
const entry = this.appendBackgroundTaskEntry({ ...task, status });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reuse the terminal card emitted by the subagent handler

When a detached agent completes, SubAgentEventHandler.handleSubagentCompleted can append its terminal card first and mark backgroundTaskTranscriptedTerminal; the later background.task.terminated event then skips its append, so backgroundTaskTerminalEntries is never populated. When the task-notification turn starts, this fallback appends a second terminal card even though the first remains mounted. Record the entry created through the subagent path, or locate/reuse that existing entry, to avoid duplicate completion cards for normal background-agent notifications.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant