Skip to content

feat(web): copy a thread transcript from the thread menu - #143

Merged
incognitojam merged 4 commits into
mainfrom
t3code/add-copy-transcript
Aug 15, 2026
Merged

feat(web): copy a thread transcript from the thread menu#143
incognitojam merged 4 commits into
mainfrom
t3code/add-copy-transcript

Conversation

@incognitojam

@incognitojam incognitojam commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator

Note

TL;DR: New Copy transcript thread action copies the conversation as markdown (## User / ## Assistant under the thread title) — no tool calls, reasoning, or half-streamed replies — for sharing or pasting into a new chat as context.

There was no way to get a thread's conversation out of T3 Code. This adds copy-transcript to the shared thread action menu (sidebar right-click and chat header), with the serializer in apps/web/src/lib/threadTranscript.ts. User prompts are copied as their visible text, without injected terminal/element/issue context blocks; image attachments become [Attached image: …] placeholders.

Details worth reviewing:

  • The action fetches a full unwindowed snapshot through a new createThreadSnapshotCommands factory in client-runtime. The cached detail atom holds only the last 10 user turns (nothing for never-opened threads), so reading client state would silently truncate.
  • This is the only asynchronous copy action, so clipboard writes follow "last copy wins": every in-app write bumps a shared epoch (the direct navigator.clipboard call sites now route through writeTextToClipboard), and a transcript fetch whose epoch moved drops its result. A late-landing transcript is therefore harmless — it only lands when nothing else was copied since the click. Copies made in other applications during the fetch are unobservable from a web page (window bounded by the 6s fetch timeout).
  • Not wired: LegacySidebar (hand-curated legacy menu) and mobile (the shared factory makes later adoption cheap).

Verified with unit tests (serializer, menu builder, clipboard epoch) and an integrated browser pass against seeded fixtures — including reproducing both clipboard race directions on an 8000-message thread and confirming the guard fixes them.

Before / After

Before After
Thread context menu without Copy transcript Thread context menu with Copy transcript

Transcript copied toast reporting 4 messages


Written by an agent (T3 Code, claude-fable-5).

Adds a Copy transcript action to the thread context menu (sidebar
right-click and chat header). It copies the conversation as markdown
(## User / ## Assistant sections under the thread title), omitting tool
activity, reasoning, and still-streaming replies. User prompts are
copied as their visible text, without the injected terminal/element/
issue context blocks.

Because the detail subscription only holds a turn window on
pagination-capable servers, the action fetches a full unwindowed
snapshot on demand via a new createThreadSnapshotCommands factory in
client-runtime instead of reading cached state.
Copy transcript is the only asynchronous copy action: nothing superseded
an in-flight snapshot fetch, so copying a large thread and then quickly a
small one let the slow fetch land last and silently overwrite the
clipboard with the wrong transcript (confirmed against an 8000-message
fixture). Only the most recent copy request may write the clipboard now;
superseded results are dropped without writing or toasting.
@incognitojam
incognitojam force-pushed the t3code/add-copy-transcript branch from 2c52001 to 28bf1b6 Compare August 15, 2026 15:43
The latest-request guard only ordered transcript copies against each
other; a slow transcript fetch could still land after Copy path, a
message copy button, or Cmd+C and stomp the newer clipboard content
(reproduced: Copy transcript on an 8000-message thread, then Copy
thread ID 130ms later, left the transcript in the clipboard).

Clipboard writes now bump a shared epoch — every write through
writeTextToClipboard plus DOM copy events once tracking is installed —
and a transcript fetch drops its result if the epoch moved while it was
in flight. The four call sites writing through navigator.clipboard
directly now route through writeTextToClipboard so their copies count.
A fetch slower than 400ms also shows a loading toast, so a pending
transcript copy is visible instead of landing silently.

Copies made outside the app remain unobservable from a web page; that
window is bounded by the snapshot fetch timeout.
With the clipboard epoch in place a late-landing transcript is harmless:
it can only land when nothing else was copied since the click, meaning
the user is still waiting for exactly that content. The loading toast
was left covering only slow-connection progress feedback, at the cost of
a timer and toast lifecycle threaded through every exit path of the copy
hook. Remove it and collapse the two fetch-failure branches that showed
the same toast. If remote users miss the feedback, GitActionsControl has
the loading-toast pattern to reintroduce it behind real demand.
@incognitojam
incognitojam merged commit d86de54 into main Aug 15, 2026
9 checks passed
@incognitojam
incognitojam deleted the t3code/add-copy-transcript branch August 15, 2026 16:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant