Skip to content

refactor(tui): unify resume replay rendering - #88

Merged
liruifengv merged 4 commits into
mainfrom
liruifeng/fix-plan-review-rendering
May 27, 2026
Merged

refactor(tui): unify resume replay rendering#88
liruifengv merged 4 commits into
mainfrom
liruifeng/fix-plan-review-rendering

Conversation

@liruifengv

Copy link
Copy Markdown
Collaborator

Related Issue

No linked issue. This addresses TUI resume replay drift where replayed history used a separate rendering path from live session events.

Problem

Resume replay rendering had diverged from the normal live rendering flow. The replay code carried its own callback-based projection path, which made Agent and Read grouping behavior harder to keep consistent and caused background task notifications to render with the wrong task wording after resume.

What changed

Refactored TUI resume replay so replay orchestration lives in the KimiTUI session replay flow and drives the same live rendering hooks used by normal session events. Extracted stateless replay helpers for parsing, turn limiting, hook result formatting, background state projection, and snapshot hydration. Replaced the old replay action module and consolidated replay coverage into message replay tests, including plan review replay and bash background task notification wording.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

Validation

  • pnpm exec vitest run apps/kimi-code/test/tui/message-replay.test.ts apps/kimi-code/test/tui/kimi-tui-startup.test.ts apps/kimi-code/test/tui/kimi-tui-message-flow.test.ts apps/kimi-code/test/tui/create-tui-state.test.ts
  • pnpm --filter @moonshot-ai/kimi-code run typecheck
  • git diff --check

@changeset-bot

changeset-bot Bot commented May 26, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 1a67963

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

@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

if (outcome.kind === 'rejected' && outcome.feedback !== undefined) {
const trimmed = outcome.feedback.trim();
if (trimmed.length > 0) {
const labelTone = chalk.hex(this.colors.warning).bold;
this.addChild(new Text(labelTone('↪ Suggestion'), 2, 0));

P2 Badge Preserve rejection visibility without plan payload

This replay/display path swallows recognized ExitPlanMode outputs unless parsed feedback text exists, and the header path no longer shows a rejected chip for error outcomes. When args.plan is absent and getPlan() cannot supply a preview, a rejection like "Plan rejected by user. Plan mode remains active." renders as a neutral card with no rejection signal, so users lose the actual decision context.

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

replayEntry(
context,
'status',
mode === 'manual' ? 'YOLO mode: OFF' : `Permission mode: ${mode}`,

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 Report manual permission mode accurately during replay

The replay notice path currently maps every permission_updated event with mode === 'manual' to "YOLO mode: OFF", which is only correct when the previous mode was actually yolo. For sessions that switch auto -> manual (or emit a manual update without ever enabling YOLO), the transcript becomes misleading and loses the real mode transition. Please preserve prior replay permission state (as the old projection logic did) so manual is shown as "Permission mode: manual" unless it is explicitly a YOLO-off transition.

Useful? React with 👍 / 👎.

Comment on lines +97 to +100
backgroundAgents.add(info.taskId);
backgroundAgentMetadata.set(info.taskId, {
agentId: info.taskId,
parentToolCallId: info.taskId,

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 Track replayed background agents by subagent id

Replay hydration seeds backgroundAgents/backgroundAgentMetadata with taskId (agent-*) instead of the subagent identifier (info.agentId), but live completion/failure handlers look these maps up by event.subagentId. For resumed sessions with in-flight background subagents, the later subagent.completed/subagent.failed events miss the background metadata path, so completion cards are skipped and stale background-agent bookkeeping can persist.

Useful? React with 👍 / 👎.

@liruifengv
liruifengv merged commit ce420bf into main May 27, 2026
4 checks passed
@liruifengv
liruifengv deleted the liruifeng/fix-plan-review-rendering branch May 27, 2026 04:44
@github-actions github-actions Bot mentioned this pull request May 27, 2026

@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: 1a679639b6

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

return `${label}${chalk.hex(colors.success)(` · ${chipText}`)}`;
}
return `${label}${chalk.hex(colors.error)(' · Rejected')}`;
return label;

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 Preserve rejection status when no plan box renders

When an ExitPlanMode rejection has no inline/current plan to show (for example plan-file mode if getPlan() returns null/fails, or a replayed/reconstructed card without args.plan), buildPlanPreview() renders no plan box, and buildContent() suppresses the Plan rejected by user... result body. Since this branch now returns only Current plan, the user loses the only visible rejected indicator; keep a header/status fallback for rejected outcomes when no plan box can carry the chip.

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