Skip to content

perf(web): bound DOM growth in long sessions#1900

Open
liujunGH wants to merge 3 commits into
MoonshotAI:mainfrom
liujunGH:perf/bound-dom-growth
Open

perf(web): bound DOM growth in long sessions#1900
liujunGH wants to merge 3 commits into
MoonshotAI:mainfrom
liujunGH:perf/bound-dom-growth

Conversation

@liujunGH

Copy link
Copy Markdown

Problem

In long sessions (hundreds of turns with large tool outputs) the conversation DOM grows without bound and the tab climbs past 1GB, making scrolling and streaming janky. Four compounding causes:

  1. No output truncation — every line of every tool output becomes a DOM node, thousands of divs for large logs.
  2. Collapsed bodies stay mountedToolRow / ToolGroup bodies render all their content even when visually collapsed (grid 0fr + inert), and ToolGroup defaults to open.
  3. scrollKey joins all outputs — the follow watcher re-joins every tool output of the last turn on each change just to measure growth.
  4. characterData MutationObserver — per-token text updates during streaming fire follow/hit-test work at delta rate.

Changes

  • ToolOutputBlock: outputs beyond 80 lines render tail-biased (the last 80 lines, where errors/results live) behind an expand-to-full button (i18n keys added for en/zh).
  • ToolRow / ToolGroup: collapsible bodies unmount when closed; ToolGroup defaults to collapsed and auto-opens while any tool in it is still running, so live execution stays visible.
  • scrollKey: track growth via output line count + tail-line length instead of output.join('').
  • MutationObserver: observe childList only; the scroll follow is driven by the reactive scrollKey watcher regardless.

Result

Fresh-load footprint of a very long session drops dramatically (in local testing ~1.4GB → ~0.4GB range depending on history composition), and streaming no longer re-renders/fires observers at delta rate.

@changeset-bot

changeset-bot Bot commented Jul 19, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 27b6834

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

Here are some automated review suggestions for this pull request.

Reviewed commit: 7c9156e66c

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// kimi-ui: groups default to collapsed (they used to default open, mounting
// every tool call body of every past turn). A group with tools still running
// opens itself so live execution stays visible.
const open = ref(aggregateStatus.value === 'running');

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 Ensure tool groups reopen when tools start running

When an existing tool stack is initially collapsed (for example after refreshing a long session with completed tools) and a later running tool is appended to the same assistant turn, aggregateStatus updates to running but open keeps the one-time initial value from mount. Because the group body is now v-if="open", the live tool rows stay unmounted behind a collapsed header even though the new behavior intends running groups to open automatically; add a watcher/effect that sets open when the aggregate status becomes running.

Useful? React with 👍 / 👎.

liujunGH added 3 commits July 19, 2026 14:23
- ToolOutputBlock: outputs beyond 80 lines render tail-biased behind an
  expand-to-full button (i18n) instead of thousands of divs
- ToolRow/ToolGroup: unmount collapsible bodies when closed (they stayed
  mounted under grid 0fr); ToolGroup defaults to collapsed and auto-opens
  while tools are running
- scrollKey: track output growth via line count + tail-line length
  instead of joining every tool output per change
- drop characterData from the pane MutationObserver so per-token text
  updates no longer fire follow/hit-test work at delta rate
Address Codex review: open was initialized once at mount, so a stack that
mounted completed (collapsed) and later gained a running tool kept the
live rows unmounted. Watch aggregateStatus and reopen on transitions to
running.
@liujunGH
liujunGH force-pushed the perf/bound-dom-growth branch from f243c08 to 27b6834 Compare July 19, 2026 06:23
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