MCPcopy Index your code
hub / github.com/garrytan/gstack / parseTranscriptJsonl

Function parseTranscriptJsonl

bin/gstack-memory-ingest.ts:544–644  ·  view source on GitHub ↗
(path: string)

Source from the content-addressed store, hash-verified

542}
543
544function parseTranscriptJsonl(path: string): ParsedSession | null {
545 // Best-effort tolerant parser. Handles truncated last lines (D10 partial-flag).
546 let raw: string;
547 try {
548 raw = readFileSync(path, "utf-8");
549 } catch {
550 return null;
551 }
552 const lines = raw.split("\n").filter((l) => l.trim().length > 0);
553 if (lines.length === 0) return null;
554
555 // Detect partial: if the last line doesn't end with `}` or doesn't parse, mark partial.
556 let partial = false;
557 let parsedLines: any[] = [];
558 for (let i = 0; i < lines.length; i++) {
559 try {
560 parsedLines.push(JSON.parse(lines[i]));
561 } catch {
562 // Last-line truncation is the common case (D10).
563 if (i === lines.length - 1) partial = true;
564 else continue;
565 }
566 }
567 if (parsedLines.length === 0) return null;
568
569 // Detect format: Codex `session_meta` or Claude Code `type: user|assistant|tool`
570 const first = parsedLines[0];
571 const isCodex = first?.type === "session_meta" || first?.payload?.id != null;
572 const agent: "claude-code" | "codex" = isCodex ? "codex" : "claude-code";
573
574 let session_id = "";
575 let cwd = "";
576 let start_time: string | undefined;
577 let end_time: string | undefined;
578
579 if (isCodex) {
580 session_id = first.payload?.id || first.id || basename(path, ".jsonl");
581 cwd = first.payload?.cwd || first.cwd || "";
582 start_time = first.timestamp || first.payload?.timestamp;
583 } else {
584 // Claude Code: look for cwd in first non-queue record
585 for (const r of parsedLines) {
586 if (r?.cwd) {
587 cwd = r.cwd;
588 break;
589 }
590 }
591 session_id = basename(path, ".jsonl");
592 start_time = parsedLines.find((r) => r?.timestamp)?.timestamp;
593 const last = parsedLines[parsedLines.length - 1];
594 end_time = last?.timestamp;
595 }
596
597 // Render body — collapsed conversation
598 let messageCount = 0;
599 let toolCalls = 0;
600 const bodyParts: string[] = [];
601 for (const rec of parsedLines) {

Callers 1

preparePagesFunction · 0.85

Calls 2

extractContentTextFunction · 0.85
pushMethod · 0.45

Tested by

no test coverage detected