Repository navigation
Conversation
On reattach, record which conversation entries the session history holds and send the ones after the last known entry before the scanners start.
This branch has not been deployed
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.
Summary. When a conversation is continued outside happy (plain
claude --resume) and the session is then resumed withhappy resume, the messages added outside never reach the app, although Claude remembers them: on start, happy marks every entry already in Claude's conversation file as sent. This PR adds a reconnect backfill: while skipping the session's existing history on reattach, the CLI records which Claude entries the history holds (claudeUuid), then sends the entries after the last known one before the scanners start. It also keeps the SDK's messageuuidin remote mode instead of generating a random one, soclaudeUuidmatches the conversation file (rewind/fork already treat the file as the source of truth for it). Fixes #1861.Changes
claude/utils/sdkToLogConverter.ts: use the SDK message'suuid(the entry's uuid in Claude's JSONL); fall back to a random one only when it is missing.api/apiSession.ts: on reconnect (skipExistingMessages), decrypt the skipped history and expose what it holds of the conversation (syncedTranscript()).claude/utils/transcriptResync.ts(new): finds the entries after the last one the history knows (app-typed messages that never got a reply are not sent twice) and sends them; sends nothing if the history cannot be read within 10 s or matches none of the entries.claude/runClaude.ts: runs the backfill on reconnect when resuming a Claude session (--resume <id>), next to the existing fork backfill.transcriptResync.test.ts(8),sdkToLogConverter.test.ts(+2),apiSession.test.ts(+1).Proof — local
pnpm env:up:authenticated, same steps onmainand on this branch: starthappy, send a message from the web app, stop the session process, send two messages withclaude --resume <id>, thenhappy resume <session id>.Before:

After:

CLI log on this branch:
CLI test suite: no new failures (
claude_version_utils"falls back to --version…" and the daemon "stress test: spawn / stop" fail onmainas well).