feat(web): auto-reconcile external agent sessions on project open - #1
Open
lewismarshall wants to merge 3 commits into
Open
feat(web): auto-reconcile external agent sessions on project open#1lewismarshall wants to merge 3 commits into
lewismarshall wants to merge 3 commits into
Conversation
When environment shells bootstrap, automatically import external Claude Code and Codex sessions for every known project. This surfaces agent work already on disk in the thread list without requiring a manual "Import agent sessions…" action. The new useAgentSessionAutoReconcile hook reuses the existing idempotent agentSessions.import RPC. Each project is reconciled once per mount cycle; failures are silently ignored since a missing agent home is not actionable for the user. Refs: pingdotgg#6994, pingdotgg#6680 Co-authored-by: Lewis Marshall <lewismarshall@users.noreply.github.com>
The original hook swallowed all import failures silently (.catch(() => {})),
making E2E debugging impossible when the server doesn't support the
agentSessions.import RPC (e.g. t3@0.0.38 predates PR pingdotgg#5362).
Changes:
- Add classifyImportFailure() that distinguishes four failure kinds:
unsupported-server (RpcClientError), interrupted, expected domain
errors, and unexpected defects.
- Log unsupported-server with a one-time console.warn naming the
required server version and PR pingdotgg#5362. Skip further import attempts
for that environment.
- Log expected errors (project not found, workspace mismatch, scan
error, auth) with console.warn including project context.
- Log unexpected errors with console.error for debugging.
- Log successful imports with console.info when importedCount > 0.
- Add 10 new unit tests for classifyImportFailure covering all
error classifications.
Co-authored-by: Lewis Marshall <lewismarshall@users.noreply.github.com>
selectUnreconciledProjects no longer eagerly adds keys to the reconciled set. The hook marks a project reconciled only after: - A successful import (importedCount + skippedCount returned). - A definitive domain error (project not found, workspace mismatch, scan error, auth error) — these won't resolve without user action. Transient failures (unsupported-server, unexpected defect, interrupted) leave the project eligible for retry on the next render cycle. This fixes the scenario where imports fail against an old server (pre-pingdotgg#5362) and the project is permanently marked done, preventing retry after a server upgrade without a full client remount. Also: console.info now logs for every successful import (even when importedCount is 0) with projectId, workspaceRoot, and skippedCount for E2E observability. Co-authored-by: Lewis Marshall <lewismarshall@users.noreply.github.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.
What Changed
Added always-on automatic reconciliation of external agent sessions (Claude Code, Codex) when projects become available on a connected environment.
A new
useAgentSessionAutoReconcilehook is mounted in the chat layout route. When environment shells bootstrap, it calls the existing idempotentagentSessions.importRPC for every known project, surfacing agent work already on disk in the thread list — without requiring a manual "Import agent sessions…" action.Related Ideas discussions:
Why
When connecting to a remote environment via T3 Connect, agent sessions already on disk (e.g. Claude CLI history under
~/.claude) do not appear in the project thread list unless the user manually triggers an import. The existingAgentSessionScanner+AgentSessionImporterinfrastructure (pingdotgg#5362) handles the heavy lifting, but is only wired into the first-run Welcome Wizard. Post-onboarding, there is no continuous visibility path.This PR adds the minimal client-side trigger to close that gap. It reuses the existing server-side import RPC, which is fully idempotent (thread IDs are prefixed with
import:, and per-source file-identity watermarks prevent re-reading unchanged transcripts).Server version requirement
Auto-reconcile requires a server build that includes PR pingdotgg#5362 (the
agentSessions.scan/agentSessions.importRPCs). Servers older than this (e.g.t3@0.0.38) do not expose these methods.The hook detects unsupported servers via
RpcClientErrorclassification and logs a one-timeconsole.warnexplaining the minimum version requirement. It skips further import attempts for that environment but does not mark projects as reconciled, so a server upgrade without full client remount will retry automatically.workspaceRoot matching
The import passes
expectedWorkspaceRootfrom the project'sworkspaceRootto the server. If the T3 project root differs from the directory Claude/Codex sessions ran in (e.g./home/box/Evosimvs/workspace/charlie-evosim/Evosim), the server returnsAgentSessionImportProjectChangedErrorand the hook logs a diagnostic warning. Sessions are only imported when paths match.What shipped
useAgentSessionAutoReconcilehook: watches the project list, triggersagentSessions.importonce per project per mount cycleselectUnreconciledProjectspure function: identifies projects not yet reconciled without eagerly marking them — the hook marks reconciled only after a definitive outcomeclassifyImportFailurepure function: classifies import failures into four categories (unsupported-server, interrupted, expected domain error, unexpected defect)isDefinitiveOutcomehelper: onlyexpecteddomain errors and successes are definitive; transient failures (unsupported-server, unexpected, interrupted) allow retryChatRouteLayout(_chat.tsx)isDefinitiveOutcome— 1 test per outcome kind + success omission since success returns"expected"but is handled before classification in the hook)Reconcile-marking semantics
importedCount/skippedCountreturned)Error handling behavior
RpcClientErrorconsole.warnwith upgrade instructions; skip environmentCause.hasInterruptsOnly_tagmatchconsole.warnwith project contextconsole.errorwith project contextresult._tag === "Success"console.infowith importedCount + skippedCount (always, even when 0)Out of scope
claude --remote-controlChecklist
Maintainer manual QA checklist
Prerequisites: Server must include PR pingdotgg#5362 (
agentSessions.importRPC).t3@0.0.38is insufficient — use a build frommainafter 2026-09-05. The project'sworkspaceRootmust match thecwdrecorded in Claude/Codex session transcripts.Success signal: Imported threads have IDs prefixed with
import:(visible in devtools/network/DB asimport:claudeAgent:<session-uuid>). The visible sidebar title is the human-readable title from the transcript (e.g. "Evosim open issues survey"), NOT the stringimport:.workspaceRootmatches agent sessioncwdon disk[auto-reconcile] project "..." (...): imported N, skipped Minfo lineimport:threads (idempotent by design)historyImport: true, no session is started)expectedWorkspaceRootlogs a diagnostic warning to the console and skips safelyTest commands and results
This change was authored by Cursor (Claude Opus 4.6) via T3 Code Cloud Agent.