feat: improve the Markdown conversation export; shrink the component test module graph - #576
Merged
Merged
Conversation
Copy as Markdown is how a conversation reaches another agent when native forking is unavailable, so prose-shaped content has to outrank everything produced around it. Thinking was dropped one level before tool calls were touched, and the floor spent up to 120 characters per call on bold, mid-word-truncated command strings whose results were already gone. - Thinking degrades by capping (`thinkingCap`) instead of being dropped, so the receiving conversation always inherits some of the reasoning. - Tool calls collapse one level earlier, into one counted per-turn summary. - Prose headings shift below the turn heading outside fenced blocks; agent bodies routinely emit `#` headings that destroyed the outline. - Turns carry a round number, local time, and the recorded model and working time; a rule opens each round; the trim notice moved to the header. - The budget rises to 150k characters / 60k tokens. Model: claude-opus-5[1m] Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Vitest isolates each of the suite's 446 files and re-evaluates every file's whole import graph, so accidental graph weight is paid per file. Tracing `DEBUG=vite-node:*` showed one menu test pulling 991 modules, only 11 of them from `node_modules`. - Delete the unused `Calendar` re-export and `react-day-picker`, which dragged `date-fns`, `date-fns-jalali` and `@date-fns/tz` into every `@/ui` consumer. - Deep-import `date-fns/locale/<tag>` instead of the 96-locale barrel. - Move the icon-asset `new URL` glob, which eagerly pulls 324 SVGs, into its own module so the test config can alias just that one to a stub. - Drop `vite-plugin-top-level-await` and `vite-tsconfig-paths` from the test config only; `vite.config.ts` keeps both for the product bundle. That test now loads 667 modules. Wall-clock improvement is NOT established: host variance exceeded the effect, and a 20s suite needs `isolate: false`, which currently fails past six files on leaked pending async work. Model: claude-opus-5[1m] Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…kdown-export # Conflicts: # .agents/docs/sessions-surface.md # packages/components/src/components/sessions/AGENTS.md # packages/components/src/components/sessions/session-chat-interface.tsx
The fork-menu copy from #558 appended "the last response was still generating" after the transcript, while the trim notice had moved to the header block. Two warnings about the same thing — whether this copy is complete — in two places, one of them after the content it qualifies, defeats the reason the notice moved: the reader is often another agent, which needs to know before it reads. The warning is now a caller-localized `incompleteFinalResponse` option rendered in the header blockquote beside the trim notice, so both fork-menu and session- header copies produce one consistent document. Model: claude-opus-5[1m] Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related issue
Same-repository branch; no intake Issue.
Problem / pressure
Two independent pressures, both surfaced while reviewing what Copy as Markdown
actually produces.
The export loses the reasoning it exists to carry. Copy as Markdown is the
fallback when native forking is unavailable — the user's goal is to move a
conversation's context to another agent, machine, or workspace. The
degradation ladder was ordered as if it were producing a transcript: thinking
was dropped one level before tool calls were touched, and the most aggressive
level spent up to 120 characters per tool call on bold, mid-word-truncated
command strings whose results were already gone. Message bodies routinely
contain
#/##headings, which outranked the## User/## Assistantturnheadings and destroyed the outline of any long paste.
The component suite takes about ten minutes, and almost none of it is
assertions. A
--shard=1/4run spends its time in Vitest'scollectphase —importing a test file and evaluating its transitive graph — which isolation
repeats for every one of 446 files.
DEBUG=vite-node:*on one menu test showed991 modules loaded, only 11 of them from
node_modules.Summary
Commit 1 —
feat(shared): Markdown export format.LevelConfig.includeThinking: booleanbecomesthinkingCap: number. Thinkingdegrades through the same
clampMiddleas tool results, so head andconclusion survive; it is never dropped whole.
<details>per turn with counts bytoolName.demoteMarkdownHeadingsshifts ATX headings in message bodies down two levels,capped at h6, skipping fenced blocks.
MM-DD HH:mm, and for assistantturns the recorded model and effective working time; a rule opens each round.
and the trim notice, which moved from the footer.
distinct
userId; the caller supplies theuserId → namemap.Commit 2 —
perf(components): test module graph.src/ui/calendar.tsxand thereact-day-pickerdependency. TheCalendarcomponent had no callers anywhere; its re-export fromsrc/ui/index.tsdraggeddate-fns,date-fns-jalaliand@date-fns/tzinto every
@/uiconsumer. Also removes 3.6 MB from the product bundle.date-fns/locale/en-US/zh-CNinstead of thedate-fns/localebarrel, which natively loads all 96 locales.new URL(\./files/${name}.svg`, import.meta.url)calls — which make Vite eagerly glob 324 SVGs into everyFileIconconsumer — move tofile-icons/asset-url.ts`, so the test config can alias only that module to astub. Production behaviour is unchanged.
vitest.config.tsdropsvite-plugin-top-level-awaitand replacesvite-tsconfig-pathswith explicit aliases.vite.config.tskeeps both.Visual explanation
Degradation ladder, before and after. The reordering is the change: prose-shaped
content is now everything above the dashed line, and nothing below it can be
lost before everything above it has degraded.
flowchart LR subgraph BEFORE["Before (6 levels)"] direction TB B0["0 · uncapped"] --> B1["1 · tool 4000 / term 2048"] B1 --> B2["2 · tool 1000 / term 512"] B2 --> B3["3 · terminal dropped, tool 300"] B3 --> B4["4 · THINKING DROPPED"] B4 --> B5["5 · one bold line per tool call"] end subgraph AFTER["After (7 levels)"] direction TB A0["0 · uncapped"] --> A1["1 · tool 4000 / term 2048"] A1 --> A2["2 · tool 1000 / term 512"] A2 --> A3["3 · terminal dropped, tool 300"] A3 --> A4["4 · tool calls → one counted summary"] A4 --> A5["5 · thinking capped 2000"] A5 --> A6["6 · thinking capped 500"] end B4:::lost A5:::kept A6:::kept classDef lost fill:#fdd,stroke:#c00 classDef kept fill:#dfd,stroke:#0a0Rendered output, same conversation:
2 · User · Leon · 09-08 15:10