1+ // @index JSONL session parsing and extraction helpers for benchmark analysis.
12package benchmark
23
34import (
1516)
1617
1718// SessionMessage represents one line from a Claude Code session JSONL file.
19+ // @intent model the subset of Claude session JSONL needed to reconstruct benchmark runs.
1820type SessionMessage struct {
1921 Type string `json:"type"`
2022 Message * MessagePayload `json:"message,omitempty"`
@@ -23,13 +25,15 @@ type SessionMessage struct {
2325}
2426
2527// MessagePayload is the nested message object inside a SessionMessage.
28+ // @intent expose assistant role, content blocks, and usage data from session lines.
2629type MessagePayload struct {
2730 Role string `json:"role"`
2831 Content []ContentBlock `json:"content"`
2932 Usage * UsageInfo `json:"usage,omitempty"`
3033}
3134
3235// ContentBlock is a single content item (text, tool_use, etc.).
36+ // @intent represent individual Claude message blocks so benchmark analyzers can inspect tool calls and text.
3337type ContentBlock struct {
3438 Type string `json:"type"`
3539 Text string `json:"text,omitempty"`
@@ -39,19 +43,22 @@ type ContentBlock struct {
3943}
4044
4145// UsageInfo holds token usage from Claude's response.
46+ // @intent capture token accounting for one Claude message so benchmark runs can aggregate usage.
4247type UsageInfo struct {
4348 InputTokens int `json:"input_tokens"`
4449 OutputTokens int `json:"output_tokens"`
4550}
4651
4752// QuerySegment groups the messages belonging to a single benchmark query.
53+ // @intent isolate the portion of a session that belongs to one marked benchmark query.
4854type QuerySegment struct {
4955 QueryID string
5056 Messages []SessionMessage
5157}
5258
5359// ParseJSONL reads a Claude Code session JSONL file and returns all parsed lines.
5460// Lines that are not valid JSON are silently skipped.
61+ // @intent ingest recorded Claude sessions even when they contain partial or non-JSON noise lines.
5562func ParseJSONL (path string ) ([]SessionMessage , error ) {
5663 f , err := os .Open (path )
5764 if err != nil {
@@ -83,6 +90,7 @@ const (
8390
8491// extractMarker checks if a SessionMessage contains a benchmark marker.
8592// Returns (queryID, isStart, found). Uses strict regex to prevent injection via crafted IDs.
93+ // @intent locate benchmark query boundaries inside session transcripts safely.
8694func extractMarker (m SessionMessage ) (queryID string , isStart bool , found bool ) {
8795 var text string
8896 if m .Type == "tool_result" {
@@ -107,6 +115,7 @@ func extractMarker(m SessionMessage) (queryID string, isStart bool, found bool)
107115
108116// ExtractQuerySegments splits a session's messages into per-query segments using markers.
109117// An unclosed segment (START without END) is included, spanning to the last message.
118+ // @intent reconstruct per-query transcript slices from a whole benchmark session log.
110119func ExtractQuerySegments (msgs []SessionMessage ) ([]QuerySegment , error ) {
111120 var segs []QuerySegment
112121 var current * QuerySegment
@@ -134,6 +143,7 @@ func ExtractQuerySegments(msgs []SessionMessage) ([]QuerySegment, error) {
134143}
135144
136145// ExtractToolCalls collects all tool_use blocks from a segment's messages.
146+ // @intent recover structured tool invocation history for one benchmark query.
137147func ExtractToolCalls (seg QuerySegment ) []ToolCall {
138148 var calls []ToolCall
139149 for _ , m := range seg .Messages {
@@ -154,6 +164,7 @@ func ExtractToolCalls(seg QuerySegment) []ToolCall {
154164}
155165
156166// ExtractFilesRead returns deduplicated file paths from Read tool calls in the segment.
167+ // @intent estimate file-inspection behavior from tool-use records without double-counting reads.
157168func ExtractFilesRead (seg QuerySegment ) []string {
158169 var files []string
159170 seen := make (map [string ]bool )
@@ -178,6 +189,7 @@ func ExtractFilesRead(seg QuerySegment) []string {
178189}
179190
180191// ExtractTokens sums input and output token counts across all messages in a segment.
192+ // @intent aggregate token usage for the full lifecycle of one benchmark query.
181193func ExtractTokens (seg QuerySegment ) (inputTokens , outputTokens int ) {
182194 for _ , m := range seg .Messages {
183195 if m .Message != nil && m .Message .Usage != nil {
@@ -189,6 +201,7 @@ func ExtractTokens(seg QuerySegment) (inputTokens, outputTokens int) {
189201}
190202
191203// ExtractAnswer returns the text of the last assistant text block in the segment.
204+ // @intent capture the final assistant answer that should be evaluated for symbol hits.
192205func ExtractAnswer (seg QuerySegment ) string {
193206 var last string
194207 for _ , m := range seg .Messages {
@@ -205,6 +218,7 @@ func ExtractAnswer(seg QuerySegment) string {
205218}
206219
207220// ExtractRunResult builds a RunResult from a query segment.
221+ // @intent convert an extracted query segment into the canonical benchmark run result shape.
208222func ExtractRunResult (queryID string , seg QuerySegment ) RunResult {
209223 in , out := ExtractTokens (seg )
210224 return RunResult {
0 commit comments