From 881e35c5586028575b34ea95592a475e28872e8d Mon Sep 17 00:00:00 2001 From: Runway28R Date: Sun, 27 Sep 2026 00:07:19 -0700 Subject: [PATCH] Preserve multiple summaries --- src/ctxlens/parsers/claude_code.py | 7 ++++++- tests/test_parsers.py | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/ctxlens/parsers/claude_code.py b/src/ctxlens/parsers/claude_code.py index a47dff3..c282a6b 100644 --- a/src/ctxlens/parsers/claude_code.py +++ b/src/ctxlens/parsers/claude_code.py @@ -70,7 +70,12 @@ def parse(self, raw: str, path: Path | None = None) -> Session: etype = entry.get("type") if etype == "summary": - meta.setdefault("summary", entry.get("summary")) + summary = entry.get("summary") + if summary: + existing = meta.get("summary") + meta["summary"] = ( + f"{existing}\n{summary}" if existing else str(summary) + ) continue if etype == "system" and "message" not in entry: text = entry.get("content") or entry.get("text") or "" diff --git a/tests/test_parsers.py b/tests/test_parsers.py index e732364..bc95a45 100644 --- a/tests/test_parsers.py +++ b/tests/test_parsers.py @@ -53,6 +53,33 @@ def test_parse_claude_segments_and_turns(claude_jsonl): assert len(s.turns) == 4 +def test_parse_claude_multiple_summaries_preserved(): + raw = "\n".join( + [ + json.dumps( + { + "type": "summary", + "summary": "First summary", + } + ), + json.dumps( + { + "type": "summary", + "summary": "Second summary", + } + ), + json.dumps( + { + "type": "user", + "message": {"role": "user", "content": "Hello"}, + } + ), + ] + ) + session = parse_text(raw, fmt="claude-code-jsonl") + assert session.meta["summary"] == "First summary\nSecond summary" + + def test_parse_claude_tool_ref_present(claude_jsonl): s = parse_file(claude_jsonl) calls = [m for m in s.messages if m.segment == Segment.TOOL_CALL]