Add progress tracking fields to shared types and session parser

Introduce ProgressSubtype union ("hook" | "bash" | "mcp" | "agent") and
three new fields on ParsedMessage: toolUseId, parentToolUseId, and
progressSubtype. These enable linking hook_progress events to the
tool_call that spawned them and classifying progress by source.

Session parser changes:
- Extract `id` from tool_use content blocks into toolUseId
- Extract `tool_use_id` from tool_result blocks into toolUseId (was
  previously misassigned to toolName)
- Read `parentToolUseID` from raw progress lines
- Derive progressSubtype from the `data.type` field using a new
  deriveProgressSubtype() helper
- Add `toolProgress` map to SessionDetailResponse for grouped progress

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-30 23:03:00 -05:00
parent 150cd0c686
commit b168e6ffd7
2 changed files with 22 additions and 2 deletions

View File

@@ -1,5 +1,5 @@
import fs from "fs/promises"; import fs from "fs/promises";
import type { ParsedMessage } from "../../shared/types.js"; import type { ParsedMessage, ProgressSubtype } from "../../shared/types.js";
/** /**
* Real Claude Code JSONL format (verified from actual session files): * Real Claude Code JSONL format (verified from actual session files):
@@ -19,6 +19,7 @@ import type { ParsedMessage } from "../../shared/types.js";
interface ContentBlock { interface ContentBlock {
type: string; type: string;
id?: string;
text?: string; text?: string;
thinking?: string; thinking?: string;
name?: string; name?: string;
@@ -31,6 +32,7 @@ interface RawLine {
type?: string; type?: string;
uuid?: string; uuid?: string;
timestamp?: string; timestamp?: string;
parentToolUseID?: string;
message?: { message?: {
role?: string; role?: string;
content?: string | ContentBlock[]; content?: string | ContentBlock[];
@@ -85,12 +87,16 @@ function extractMessages(raw: RawLine, rawIndex: number): ParsedMessage[] {
const progressText = data const progressText = data
? formatProgressData(data) ? formatProgressData(data)
: "Progress event"; : "Progress event";
const dataType = typeof data?.type === "string" ? data.type : "";
const progressSubtype = deriveProgressSubtype(dataType);
messages.push({ messages.push({
uuid, uuid,
category: "hook_progress", category: "hook_progress",
content: progressText, content: progressText,
timestamp, timestamp,
rawIndex, rawIndex,
parentToolUseId: raw.parentToolUseID,
progressSubtype,
}); });
return messages; return messages;
} }
@@ -155,7 +161,7 @@ function extractMessages(raw: RawLine, rawIndex: number): ParsedMessage[] {
uuid: `${uuid}-tr-${block.tool_use_id || rawIndex}`, uuid: `${uuid}-tr-${block.tool_use_id || rawIndex}`,
category: "tool_result", category: "tool_result",
content: resultText, content: resultText,
toolName: block.tool_use_id, toolUseId: block.tool_use_id,
timestamp, timestamp,
rawIndex, rawIndex,
}); });
@@ -215,6 +221,7 @@ function extractMessages(raw: RawLine, rawIndex: number): ParsedMessage[] {
toolInput: JSON.stringify(block.input, null, 2), toolInput: JSON.stringify(block.input, null, 2),
timestamp, timestamp,
rawIndex, rawIndex,
toolUseId: block.id,
}); });
} }
} }
@@ -239,3 +246,10 @@ function formatProgressData(data: Record<string, unknown>): string {
function detectSystemReminder(text: string): boolean { function detectSystemReminder(text: string): boolean {
return text.includes("<system-reminder>") || text.includes("</system-reminder>"); return text.includes("<system-reminder>") || text.includes("</system-reminder>");
} }
function deriveProgressSubtype(dataType: string): ProgressSubtype {
if (dataType === "bash_progress") return "bash";
if (dataType === "mcp_progress") return "mcp";
if (dataType === "agent_progress") return "agent";
return "hook";
}

View File

@@ -9,6 +9,8 @@ export type MessageCategory =
| "file_snapshot" | "file_snapshot"
| "summary"; | "summary";
export type ProgressSubtype = "hook" | "bash" | "mcp" | "agent";
export interface ParsedMessage { export interface ParsedMessage {
uuid: string; uuid: string;
category: MessageCategory; category: MessageCategory;
@@ -17,6 +19,9 @@ export interface ParsedMessage {
toolInput?: string; toolInput?: string;
timestamp?: string; timestamp?: string;
rawIndex: number; rawIndex: number;
toolUseId?: string;
parentToolUseId?: string;
progressSubtype?: ProgressSubtype;
} }
export interface SessionEntry { export interface SessionEntry {
@@ -39,6 +44,7 @@ export interface SessionDetailResponse {
id: string; id: string;
project: string; project: string;
messages: ParsedMessage[]; messages: ParsedMessage[];
toolProgress?: Record<string, ParsedMessage[]>;
} }
export interface ExportRequest { export interface ExportRequest {