Add basic thread forking from the sidebar#4390
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Needs human review This PR introduces a new thread forking feature with substantial scope: new database schema, new event/command types, provider API integrations for Codex/Claude/OpenCode, and new UI components in sidebar and chat view. New user-facing capabilities of this magnitude warrant human review. You can customize Macroscope's approvability policy. Learn more. |
29c1ba0 to
bf7ab07
Compare
ac92627 to
eb09585
Compare
2e90fb7 to
3360755
Compare
0ae7550 to
0258dca
Compare
b9b18e0 to
f4474ea
Compare
9ac81ba to
ece3d88
Compare
ece3d88 to
b779c54
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit b779c54. Configure here.
| isRevertingCheckpoint={isRevertingCheckpoint} | ||
| {...(isServerThread && supportsSelectedResponseFork(activeProviderStatus?.driver) | ||
| ? { onForkFromResponse, isForkingResponse } | ||
| : {})} |
There was a problem hiding this comment.
Timeline fork uses composer provider
Medium Severity
Per-message fork actions are gated on activeProviderStatus?.driver, which follows the thread composer’s selected provider instance before the thread’s session or model binding. Sidebar fork uses the thread’s provider instance instead, so the timeline can hide fork on supported threads or show it when native fork will fail.
Reviewed by Cursor Bugbot for commit b779c54. Configure here.
…ted response from the sidebar) # Conflicts: # apps/web/src/components/Sidebar.tsx
…ted response from the sidebar) # Conflicts: # apps/web/src/components/Sidebar.tsx


What Changed
thread.forkorchestration command and persists fork lineageWhy
The basic fork interaction should feel like cloning a thread: right-click it in the sidebar, fork it, and continue in an independent copy. Branching from an older response can be added later, but it should not complicate the first version or introduce a separate side-chat surface.
UI Changes
Right-click a supported thread in the sidebar and select Fork thread. The action is disabled while the latest turn is running or before the thread has a completed assistant response. A successful fork appears as
<original title> (fork)and opens in the normal full-thread route.There is no split view, embedded side chat, or per-response fork button.
Checklist
Note
Add thread forking from the sidebar and assistant message timeline
codex,claudeAgent,opencode).thread.forkcommand andthread.forkedevent in the contracts layer; the decider clones messages up to the specified source turn (excluding streaming messages), rewrites attachment ids, and records fork lineage.sessionFork: "native"), forwarding fork context to their respective SDKs.forked_from_thread_id,forked_from_turn_id) via migration 035, inherits messages from the source thread, and physically copies attachment files into fork-owned paths post-transaction.MAX_THREAD_MESSAGEScap, so threads now retain an unbounded message history.Macroscope summarized b779c54.
Note
High Risk
Touches orchestration, durable projections, attachment lifecycle, and provider session start/fork paths; unbounded message retention may increase memory and storage for long threads.
Overview
Adds end-to-end thread forking: a
thread.forkcommand emitsthread.forkedwith inherited history through a chosen completed turn, fork lineage on threads, and fork-owned message/attachment ids (createForkedAttachmentId). The SQL projection copies attachment files on fork, keeps inherited:fork:messages across revert, and migration 035 storesforked_from_*columns.Provider integration — Codex, Claude, and OpenCode declare
sessionFork: "native"and receiveforkFrom(turn index/id + source resume cursor) when a forked thread starts;ProviderCommandReactorwalks nested fork lineage to the provider-owning ancestor.getCommandReadModelnow loads full per-thread message history (not capped like shell snapshots).Client —
@t3tools/client-runtime/thread-forkinggates fork UI; sidebar Fork thread and chat Fork from this response calluseForkThread/threadEnvironment.fork. In-memory projection drops the 2,000-message cap so command/read models can retain complete history.Reviewed by Cursor Bugbot for commit b779c54. Bugbot is set up for automated code reviews on this repo. Configure here.