99from typing import Any , cast , get_args
1010
1111from models .record_data import RecordDataUnion
12- from models .session import MessageDict , RoleLiteral , SessionDict , ToolUseDict
12+ from models .session import MessageDict , RoleLiteral , SessionDict , SessionMetadataDict , ToolUseDict
1313from models .tool_results import ToolResultUnion , is_tool_result_dict
1414from utils .jsonl_helpers import (
1515 entry_message as _entry_message ,
@@ -70,6 +70,41 @@ def _safe_int(val: Any) -> int:
7070 return 0
7171
7272
73+ def _finalize_session_metadata (raw : dict [str , Any ]) -> SessionMetadataDict :
74+ """Convert the mutable parse-time metadata builder into a SessionMetadataDict."""
75+ return {
76+ "session_id" : raw ["session_id" ],
77+ "models_used" : sorted (raw ["models_used" ]),
78+ "first_timestamp" : raw ["first_timestamp" ],
79+ "last_timestamp" : raw ["last_timestamp" ],
80+ "total_input_tokens" : raw ["total_input_tokens" ],
81+ "total_output_tokens" : raw ["total_output_tokens" ],
82+ "total_cache_read_tokens" : raw ["total_cache_read_tokens" ],
83+ "total_cache_creation_tokens" : raw ["total_cache_creation_tokens" ],
84+ "total_tool_calls" : raw ["total_tool_calls" ],
85+ "tool_call_counts" : raw ["tool_call_counts" ],
86+ "version" : raw ["version" ],
87+ "cwd" : raw ["cwd" ],
88+ "git_branch" : raw ["git_branch" ],
89+ "permission_mode" : raw ["permission_mode" ],
90+ "compactions" : raw ["compactions" ],
91+ "total_ephemeral_5m_tokens" : raw ["total_ephemeral_5m_tokens" ],
92+ "total_ephemeral_1h_tokens" : raw ["total_ephemeral_1h_tokens" ],
93+ "service_tiers" : sorted (raw ["service_tiers" ]),
94+ "session_wall_time_seconds" : raw ["session_wall_time_seconds" ],
95+ "compact_boundaries" : raw ["compact_boundaries" ],
96+ "api_errors" : raw ["api_errors" ],
97+ "files_read" : sorted (raw ["files_read" ]),
98+ "files_written" : sorted (raw ["files_written" ]),
99+ "files_created" : sorted (raw ["files_created" ]),
100+ "bash_commands" : raw ["bash_commands" ],
101+ "web_fetches" : raw ["web_fetches" ],
102+ "sidechain_messages" : raw ["sidechain_messages" ],
103+ "stop_reasons" : raw ["stop_reasons" ],
104+ "entry_counts" : raw ["entry_counts" ],
105+ }
106+
107+
73108def parse_session (filepath : str ) -> SessionDict :
74109 """Main entry point. Reads every line from a .jsonl file and builds up
75110 a session dict with messages, metadata (tokens, models, tool counts),
@@ -165,12 +200,6 @@ def parse_session(filepath: str) -> SessionDict:
165200 if type_str not in _SKIP_ENTRY_TYPES :
166201 messages .append (_fallback_message (entry , _coerce_role (type_str )))
167202
168- metadata ["models_used" ] = sorted (metadata ["models_used" ])
169- metadata ["service_tiers" ] = sorted (metadata ["service_tiers" ])
170- metadata ["files_read" ] = sorted (metadata ["files_read" ])
171- metadata ["files_written" ] = sorted (metadata ["files_written" ])
172- metadata ["files_created" ] = sorted (metadata ["files_created" ])
173-
174203 # Compute wall clock time
175204 first_ts = metadata ["first_timestamp" ]
176205 last_ts = metadata ["last_timestamp" ]
@@ -189,7 +218,7 @@ def parse_session(filepath: str) -> SessionDict:
189218 "session_id" : session_id ,
190219 "title" : title ,
191220 "messages" : messages ,
192- "metadata" : metadata ,
221+ "metadata" : _finalize_session_metadata ( metadata ) ,
193222 }
194223 )
195224
0 commit comments