Skip to content

refactor(server): move the Claude transcript parser into its own module - #1760

Merged
devswha merged 1 commit into
mainfrom
refactor/claude-transcript-module
Oct 23, 2026
Merged

devswha merged 1 commit into
mainfrom
refactor/claude-transcript-module

Conversation

@devswha

@devswha devswha commented Oct 23, 2026

Copy link
Copy Markdown
Owner

Wave C1 of the per-agent module split. The plan is .omo/plans/agent-modules-split.md in the maintainer's workspace, and plan-reviewer approved it. It follows P1a (#1755).

This wave moves the Claude transcript parser out of server/conversation.ts into a new leaf module, server/claude-transcript.ts. conversation.ts keeps:

  • every cache and both forget* functions;
  • the paging core and the transcript resolvers;
  • the three functions tests spy on (paneTranscript, readCommandTranscript, paneProcessRoots).

It re-exports the parser's public names, so no importer changes.

What changes

  • Moved verbatim, with their doc comments: about 420 lines. That covers isCommandEntry through parseClaudeTranscript:
    • the local-command and notice helpers, stripTerminalControls and unwrapPastes;
    • TranscriptEntry, claudeResultText, IMAGE_TYPES;
    • the parser state, createClaudeTranscriptParser, claudeTranscriptParser and parseClaudeTranscript.
  • New export keywords: four names gain one, because conversation.ts still uses them: isCommandEntry, claudeResultText, IMAGE_TYPES and the type TranscriptEntry.
  • Re-exports: conversation.ts re-exports parseClaudeTranscript, createClaudeTranscriptParser and unwrapPastes. Its other imports narrow to what it still uses.
  • Not moved: the parser holds no module state (its state lives in closures), so no cache changes owner.

Checks

  • --color-moved: git diff --color-moved=plain --color-moved-ws=allow-indentation-change origin/main...HEAD -- server shows 831 lines as moved. The other 19 lines are the new module's imports, conversation.ts's narrowed imports, the re-export, and the four export keywords.

  • No import cycle: bun <plan>/no-path.ts server/claude-transcript.ts server/conversation.ts server/prompt.ts exits 0. It follows value imports through every file, and the new module never reaches conversation.ts or prompt.ts.

  • Spied names stay put: paneTranscript, readCommandTranscript and paneProcessRoots are still declared in conversation.ts.

  • No new herdr call: server/claude-transcript.ts has no herdrRpc call (server/conventions.test.ts forbids new ones).

  • Typecheck: bun run typecheck passes.

  • Unit tests: 212 pass, 0 fail, from:

    HERDR_TEST_MODE=unit bun test server/chat-history.test.ts server/claude-incremental.test.ts server/claude-turn-boundaries.test.ts server/skill-activity.test.ts server/conversation.test.ts server/native-incremental.test.ts server/large-history-agents.test.ts server/outcome-transcript*.test.ts

  • bun run check fast: passes (unit 6251 pass, 0 fail, 13 skip in 443 files, 8 at a time, 73.4s)

  • Integration lane: CI runs claude-session.contract and conversation-push.contract.

Outside PRs that touch the same files

No other maintainer PR touches these files. Three outside contributors' PRs touch server/conversation.ts. I checked each against this branch with git merge-tree:

Move-only: moved declarations plus imports, re-exports and four export keywords. No changelog fragment: users see no change.

Moves the Claude transcript parser verbatim into server/claude-transcript.ts,
a leaf module that imports nothing back from conversation.ts or prompt.ts.
conversation.ts imports the four names it still uses and re-exports
parseClaudeTranscript, createClaudeTranscriptParser and unwrapPastes, so
every importer keeps its path. Plan: .omo/plans/agent-modules-split.md C1.
@coderabbitai

coderabbitai Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
📥 Commits

Reviewing files that changed from the base of the PR and between e590552 and 3ac1999.

📒 Files selected for processing: 2
  • server/claude-transcript.ts
  • server/conversation.ts

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 0 remain after this review.

📝 Summary

Summary by CodeRabbit

  • New Features
    • Claude conversation transcripts now support both live updates and complete transcript reads.
    • Conversation history includes prompts, responses, tool activity, images, and notifications, while filtering command and bookkeeping entries.
    • Invalid transcript lines are skipped, and complete reads can be limited to the most recent turns.

The pull request moves Claude transcript parsing from server/conversation.ts into server/claude-transcript.ts. The parser folds transcript entries into conversation turns, supports incremental snapshots and one-shot parsing, and is re-exported from the existing module.

Changes: Claude transcript parsing

Layer / File(s) Summary
Transcript entry normalization
server/claude-transcript.ts
Defines transcript data and parser options. Filters command entries, unwraps pasted content, and processes terminal output and notices.
Turn state and event folding
server/claude-transcript.ts
Tracks parser state and folds task notifications, peer notices, context clears, prompts, and informational notices into turns.
User and assistant event handling
server/claude-transcript.ts
Folds user content, tool results, supported images, assistant text, thinking, and tool calls into turns.
Incremental parsing and module integration
server/claude-transcript.ts, server/conversation.ts
Adds JSONL writing, snapshots, and one-shot parsing. Replaces the local implementation with imports and re-exports from the new module.

Priority: ⬇️ Low

Estimated code review effort: 4 (Complex) | ~40 minutes

Change: Refactor

Suggested reviewers: yoonwoo-ha

Merge Risk: ⚪ Minimal · up to 3ac19

This is a behavior-preserving refactor that moves the Claude transcript parser into its own module while keeping the existing import paths. No concrete risk was found, and it looks safe to merge after normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 69.23% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 13 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title "refactor(server): move the Claude transcript parser into its own module" matches the main change. The PR moves the parser from server/conversation.ts into the new server/claude-transcript.t…
Description check Passed The description follows the repository template. It has a Change section that explains the move, the re-exports, the four new export keywords, and the reason no behavior changes. It has a Validation s…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title "refactor(server): move the Claude transcript parser into its own module" matches the main change. The PR moves the parser from server/conversation.ts into the new server/claude-transcript.ts, and the objectives confirm this. The title is specific and uses the conventional refactor prefix.

Full details: Description check

Explanation

The description follows the repository template. It has a Change section that explains the move, the re-exports, the four new export keywords, and the reason no behavior changes. It has a Validation section that lists typecheck, unit tests, the fast check lane, the no-import-cycle check, and the CI contract lanes. The template asks for contract-test coverage on HTTP/WS changes. This PR makes no HTTP/WS change, and the author lists the contract lanes that CI runs. The description also cites the changelog rule and explains why no changelog fragment is included.

✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@devswha

devswha commented Oct 23, 2026

Copy link
Copy Markdown
Owner Author

Merge pass: this is a move-only PR (per-agent split, wave C1). As AGENTS.md allows, it is merged on its checks without waiting for a CodeRabbit review.

All required checks are green and no review thread is open.

@devswha
devswha merged commit a0e32ae into main Oct 23, 2026
17 checks passed
@devswha
devswha deleted the refactor/claude-transcript-module branch October 23, 2026 12:49
devswha added a commit that referenced this pull request Oct 23, 2026
…s/live.ts (#1761)

Wave P1b of the per-agent module split. The plan is
`.omo/plans/agent-modules-split.md` in the maintainer's workspace, and
plan-reviewer approved it. It follows P1a (#1755) and C1 (#1760).

This wave moves the live-screen tail checks out of `server/prompt.ts`
into a new leaf module, `server/dialogs/live.ts`. These are the
per-agent checks that say whether a dialog parsed from the screen is
still drawn at its bottom. `prompt.ts` keeps every per-pane map, the
queue drivers and every route.

## What changes

- **Moved verbatim, with their doc comments:**
- the omo task and spinner patterns (`OMO_TASK_ROW_RE` through
`OMO_EMPTY_BOX_RE`);
- `CLAUDE_SUBMIT_TAIL_RE`, `omoFooterIsActive` and `promptTailIsActive`;
- the pi and Command Code footer helpers (`PI_MENU_HINT_AT_END_RE`,
`PI_INPUT_HINT_AT_END_RE`, `CMD_HINT_RE`, `CMD_FOOTER_WORDS`,
`cmdFooterEnds`, `PI_MODEL_HINT_AT_END_RE`, `PI_FOOTER_LINES`);
  - `hintAtEnd`, `parsePrompt` and `liveScreen`.
- **New `export` keywords:** `parsePrompt`, `promptTailIsActive` and
`liveScreen`. `prompt.ts` imports these three back.
- **No re-exports:** nothing else imported these names from `prompt.ts`.
- **Imports:** `prompt.ts`'s imports from `./dialogs/*` narrow to what
it still uses. `live.ts` imports the same names from the same dialogs
modules, plus `paneRead` from `../herdr/client.ts`.
- **State:** none. Nothing that moves holds module state, and no
`herdrRpc` call moves (`liveScreen` uses the typed `paneRead` wrapper).

`server/prompt.ts` goes from 1,530 to 1,334 lines.

## Checks

- **`--color-moved`:** `git diff --color-moved=plain
--color-moved-ws=allow-indentation-change origin/main...HEAD` shows 382
lines as moved. The other 30 lines are:
  - `live.ts`'s eleven import lines;
  - `prompt.ts`'s narrowed and new import lines;
- the three declarations whose only change is the added `export`, each
shown as removed and added.
- **No import cycle:** `bun <plan>/no-path.ts server/dialogs/live.ts
server/prompt.ts server/conversation.ts` prints "no path to
server/prompt.ts, server/conversation.ts". The new module never reaches
either file through value imports.
- **Typecheck:** `bun run typecheck` passes.
- **Unit tests:** **589 pass, 0 fail across 20 files**, from:

`HERDR_TEST_MODE=unit bun test server/prompt.test.ts server/dialogs/
server/hermes-prompt.test.ts server/cmd.test.ts server/core/`

  Every `parseInteractivePrompt` path runs through `parsePrompt`.
- `bun run check fast`: passes (unit 6253 pass, 0 fail, 13 skip in 443
files, 8 at a time, 73.5s)
- **Integration lane:** CI runs pending-input, prompt, opencode-prompt
and claude-session contracts.

## Outside PRs that touch the same files

No other maintainer PR touches these files. Three outside contributors'
PRs touch `server/prompt.ts`. Each has a small change inside a function
that now lives in `server/dialogs/live.ts`, so its rebase carries that
change into the new file. I checked each with `git merge-tree`:
- **#1670** merges cleanly with main, and conflicts with this branch in
`server/prompt.ts`.
- **#1714** already conflicts with main in `server/prompt.ts`, and needs
a rebase either way.
- **#1669** already conflicts with main in `server/prompt.ts`, and needs
a rebase either way.

Move-only: moved declarations plus imports and three `export` keywords.
No changelog fragment: users see no change.
devswha added a commit that referenced this pull request Oct 23, 2026
…ersation-shared.ts (#1763)

Wave C2 of the per-agent module split. The plan is
`.omo/plans/agent-modules-split.md` in the maintainer's workspace, and
plan-reviewer approved it. It follows C1 (#1760) and P1b (#1761).

This wave moves the conversation types and constants that agent modules
share out of `server/conversation.ts` into a new leaf module,
`server/conversation-shared.ts`. Later waves (Devin's session lookup,
then the Claude and omp sessions) can then throw
`ConversationUnavailable` without importing `conversation.ts`.

## What changes

- **Moved verbatim, with their doc comments:**
  - `TRANSCRIPT_WINDOW_BYTES`;
- the error classes `ConversationUnavailable`, `ConversationNotStarted`
and `HistoryChanged`;
- the types `RecognizedConversation`, `StreamSource` and
`ConversationPage`;
  - `PROCESS_VERSION` and `answerVersion`.
- **State:** `PROCESS_VERSION` holds one `randomUUID()`, set once and
never changed. It moves with its only user, `answerVersion`, so it still
has a single owner.
- **New `export`:** only `StreamSource` gains one, because
`conversation.ts` imports it back.
- **Re-exports:** `conversation.ts` re-exports every name that was
exported before, so no other importer changes.
- **One import path changes on purpose:** `server/hermes.ts` now imports
the same names from `./conversation-shared.ts` instead of
`./conversation.ts`. That removes the runtime import cycle between
`hermes.ts` and `conversation.ts`.

## Checks

- **`--color-moved`:** `git diff --color-moved=plain
--color-moved-ws=allow-indentation-change origin/main...HEAD` shows 138
lines as moved. The other 8 lines are:
  - the new file's two import lines;
  - `StreamSource` with its added `export`, shown as removed and added;
  - `conversation.ts`'s import and re-export lines;
  - `hermes.ts`'s changed module path.
- **No cycles:** checked with `bun <plan>/no-path.ts`.
- With `server/conversation-shared.ts server/conversation.ts
server/prompt.ts`, it prints "no path to server/conversation.ts,
server/prompt.ts".
- With `server/hermes.ts server/conversation.ts`, it prints "no path to
server/conversation.ts". The cycle is gone.
- **Typecheck:** `bun run typecheck` passes.
- **Unit tests:** `HERDR_TEST_MODE=unit bun test server/hermes.test.ts
server/conversation.test.ts server/chat-history.test.ts`: 177 pass, 0
fail.
- `bun run check fast`: passes (unit 6253 pass, 0 fail, 13 skip in 443
files, 8 at a time, 66.5s)
- **Integration lane:** CI runs the gjc, api, opencode and hermes
contracts.

## Outside PRs that touch the same files

No other maintainer PR touches these files. Three outside contributors'
PRs touch `server/conversation.ts`. Each adds a member to
`RecognizedConversation`'s `source` union, which now lives in
`server/conversation-shared.ts`, so a rebase carries that one line into
the new file. I checked each with `git merge-tree`:
- **#1706** merges cleanly with main, and conflicts with this branch in
`server/conversation.ts`.
- **#1652** already conflicts with main in `server/conversation.ts`, and
needs a rebase either way.
- **#1442** already conflicts with main in `server/conversation.ts`, and
needs a rebase either way.

Move-only: moved declarations plus imports, one re-export line, one
added `export`, and the `hermes.ts` module path. No changelog fragment:
users see no change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant