( filePath: string, )
| 2452 | * @throws Error if file doesn't exist or contains invalid data |
| 2453 | */ |
| 2454 | export async function loadTranscriptFromFile( |
| 2455 | filePath: string, |
| 2456 | ): Promise<LogOption> { |
| 2457 | if (filePath.endsWith('.jsonl')) { |
| 2458 | const { |
| 2459 | messages, |
| 2460 | summaries, |
| 2461 | customTitles, |
| 2462 | tags, |
| 2463 | fileHistorySnapshots, |
| 2464 | attributionSnapshots, |
| 2465 | contextCollapseCommits, |
| 2466 | contextCollapseSnapshot, |
| 2467 | leafUuids, |
| 2468 | contentReplacements, |
| 2469 | worktreeStates, |
| 2470 | } = await loadTranscriptFile(filePath) |
| 2471 | |
| 2472 | if (messages.size === 0) { |
| 2473 | throw new Error('No messages found in JSONL file') |
| 2474 | } |
| 2475 | |
| 2476 | // Find the most recent leaf message using pre-computed leaf UUIDs |
| 2477 | const leafMessage = findLatestMessage(messages.values(), msg => |
| 2478 | leafUuids.has(msg.uuid), |
| 2479 | ) |
| 2480 | |
| 2481 | if (!leafMessage) { |
| 2482 | throw new Error('No valid conversation chain found in JSONL file') |
| 2483 | } |
| 2484 | |
| 2485 | // Build the conversation chain backwards from leaf to root |
| 2486 | const transcript = buildConversationChain(messages, leafMessage, { |
| 2487 | includeLogicalParents: true, |
| 2488 | }) |
| 2489 | |
| 2490 | const summary = summaries.get(leafMessage.uuid) |
| 2491 | const customTitle = customTitles.get(leafMessage.sessionId as UUID) |
| 2492 | const tag = tags.get(leafMessage.sessionId as UUID) |
| 2493 | const sessionId = leafMessage.sessionId as UUID |
| 2494 | return { |
| 2495 | ...convertToLogOption( |
| 2496 | transcript, |
| 2497 | 0, |
| 2498 | summary, |
| 2499 | customTitle, |
| 2500 | buildFileHistorySnapshotChain(fileHistorySnapshots, transcript), |
| 2501 | tag, |
| 2502 | filePath, |
| 2503 | buildAttributionSnapshotChain(attributionSnapshots, transcript), |
| 2504 | undefined, |
| 2505 | contentReplacements.get(sessionId) ?? [], |
| 2506 | ), |
| 2507 | contextCollapseCommits: contextCollapseCommits.filter( |
| 2508 | e => e.sessionId === sessionId, |
| 2509 | ), |
| 2510 | contextCollapseSnapshot: |
| 2511 | contextCollapseSnapshot?.sessionId === sessionId |
no test coverage detected