Draft: two-way teleport with native CLI sessions - #7136
Conversation
Contracts, orchestration, and the teleport service land first. Native CLI formats register later, so list/import/export stay empty until a provider adapter is added. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
The UI can list, import, and export native sessions. Until a format adapter is registered, the picker stays empty and export fails closed. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Codex jsonl adapter so T3 can list, import, and export rollouts the CLI can resume. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the OpenCode adapter so T3 can list, import, and export text turns from opencode.db or JSON storage without treating the live db as a foreign lock. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Claude jsonl adapter so T3 can list, import, and export sessions from the Claude projects folder. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Register the Grok session-directory adapter so T3 can list, import, and export native Grok Build chats. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Stop marked the turn interrupted but left the session running, so the thread stayed Working after abort hung or only emitted turn.aborted. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
A projected running OpenCode thread stayed Working after Stop if the in-memory provider session was already gone. Interrupt no longer recovers a session just to abort it, and Stop settles the projection when there is nothing live to interrupt. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep personal project directories out of the public diff. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep live-session titles and personal directories out of the public diff. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
|
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:
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 |
There was a problem hiding this comment.
Two small consistency findings in the new teleport UI. Everything else in the changed web files (command palette views, composer disabled/placeholder handling, ChatView toast) follows the existing primitives and layout conventions.
Posted via Macroscope — UI Consistency
There was a problem hiding this comment.
Effect service conventions review of the new TeleportService (plus its contract errors). Four convention violations found; details inline.
Posted via Macroscope — Effect Service Conventions
The import CTA lacked cursor-pointer, and the header export control used the text xs size instead of the square icon-xs used by neighboring actions. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Reject unsafe session ids on native reads/writes, fail closed when lock checks cannot run, keep Codex whitespace, preserve in-place provider instances, and clear stale history/approvals when replacing a thread. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
There was a problem hiding this comment.
One finding: the new header control's disabled state suppresses the tooltip that explains why it is unavailable.
Posted via Macroscope — UI Consistency
Effect 4 does not provide zipRight on Effect. Complete the sendTurn abort latch from a generator finalizer instead. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Claim the in-flight abort through an atomic gate so a second interrupt waits instead of emitting another turn.aborted or calling session.abort again. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Export writes the native session cwd from the thread worktree, which lives outside the project root. Listing and import treated only the workspace root as in-project, so Teleport Out was a one-way door. Discover extra cwds from the project's thread worktrees, match subdirectory sessions, and stop accepting ancestor cwds such as / or $HOME. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Export set presence to native with a teleport-pending path before writing the CLI file, then only reverted on write tapError. Interruptions, defects, and later directory or teleport.set failures left the thread stuck: the UI only offered Import, which rejected the fake path. Wrap the pending presence in acquireUseRelease so any unsuccessful exit reverts to T3, or persists the real native path if the file was written. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Release-path persist of a written native session can still raise a filesystem error. Catch that so a failed bind cannot mask the export failure or skip reverting pending presence. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
There was a problem hiding this comment.
Two error-modeling convention issues in the new teleport code: message stored as data when it is a fixed template over existing attributes, and a helper whose only behavior is constructing that error.
Posted via Macroscope — Effect Service Conventions
Lock, schema, identity, and file-locked errors now derive `message` from their fields, so the lockProbeError helper can go. A failed new-thread import deletes the orphan thread instead of leaving it unbound. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
There was a problem hiding this comment.
Reviewed the new teleport service against the Effect service conventions. Service shape (Context.Service with inline interface, exported make/layer), dependency acquisition via yield*, and Effect.catchTags usage all look right now. Three remaining error-modelling issues below.
Posted via Macroscope — Effect Service Conventions
Store a write stage instead of a free-form message on TeleportNativeWriteError, derive TeleportUnsupportedProviderError from the provider, and remap schema verification with catchTags. On Windows, replace native files by moving the destination aside so a failed rename can restore the previous session. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Persist teleport ownership first so a failed history replace cannot leave an unbound thread with overwritten messages. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep the teleported-out composer disable path and use main's disconnected placeholder constant. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
There was a problem hiding this comment.
One finding: the new chat-header teleport button loses the themed toolbar control styling because the tooltip wrapper overwrites data-slot="button". See the inline comment for the one-attribute fix.
Posted via Macroscope — UI Consistency
TooltipTrigger replaces data-slot=button, so custom themes skipped this icon. Opt in with data-toolbar-control the same way ProjectScriptsControl does. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Send-disabled only grayed the editor. Type-to-focus, mention drops, and file drops could still queue hidden draft content. Reject those paths too. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
In-place native session import persisted directory binding, teleport presence, unarchive, history, and title as separate durable mutations. A later failure left T3 ownership and history out of sync, and a concurrent turn could run against that intermediate state. Commit ownership, history, and unarchive in one orchestration command. Fence thread.turn.start with importing presence, recover leftover importing state on startup, and keep title plus directory finalize best-effort. Import stays atomic per session, not all-or-nothing for the batch. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
tapError only saw typed failures, so a cancelled or defective pre-commit import step could leave presence "importing" until process restart. onError reverts for fail, die, and interrupt, and keeps revert running. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep ChatView's teleport send-disabled import. Main moved the collapsed sidebar titlebar inset into WorkspacePageHeader, so that import is gone. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Keep ChatComposer's teleport lock on the prompt editor after main moved send/stop into the footer. Native and importing presence still disable the editor and show the send-disabled reason. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
Paste/drop could start before teleport lock, then attach compressed images after compression finished. Stash restore and stash-current could also write into a native/importing draft. Recheck send-disabled after awaits and reject those stash mutations while teleport-locked. Co-authored-by: aanishbhirud <aanishbhirud@gmail.com>
|
closing because this is explicitly marked |
What Changed
T3 Code can list, import, and export native CLI sessions for Codex, and Claude.
Native files stay native. Import copies a CLI session onto a T3 thread. Export writes the thread back. Presence (
t3vsnative) swaps Import/Export so both sides are not writers at once.Codex export writes
session_metathe CLI can resume. OpenCode imports text turns only, does not treat liveopencode.dbas a foreign lock, and does not match parent cwds into siblingcodex/claude/grokfolders. Stop settles Working when the turn is aborted, when there is no live session, or when interrupt fails.UI
Import lives on the new-thread / sessions view. Export lives in the chat header. Composer send is disabled while the thread is in the native CLI.
New UI
Hover
Composer disabled after Teleport Out
Recordings
Codex

Claude

Why
Two-way teleport needs a shared engine, UI, and one adapter per CLI. This PR is that whole stack in one diff because stacked bases have to exist on
pingdotgg/t3code.UI Changes
Import lives on the new-thread / sessions view. Export lives in the chat header. Composer send is disabled while the thread is in the native CLI.
Checklist
Relates to #207, #5146, #5741, and #6590.
Note
Add two-way teleport between app threads and native CLI sessions
thread.history.replaceandthread.teleport.setorchestration commands.TeleportServicewith list/import/export session RPCs (teleport.listSessions,teleport.importSessions,teleport.exportSession) wired into the WS layer with scope-based authorization.TeleportOutButtonin the chat header, and composer/send disabling when a thread is teleported-out.teleport_jsontoprojection_threadswith backfill from existing runtime telemetry.thread.turn.startnow fails withOrchestrationCommandInvariantErrorif the thread's teleport presence isnative, blocking turn creation on teleported-out threads.📊 Macroscope summarized 18ed3c0. 52 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted
🗂️ Filtered Issues
No issues evaluated.