@@ -10,9 +10,9 @@ export function isRecord(v: unknown): v is Record<string, unknown> {
1010// ---------------------------------------------------------------------------
1111
1212type TextBlock = { type : "text" ; text : string } ;
13- type ToolUseBlock = { type : "tool_use" ; name : string } ;
13+ type ToolUseBlock = { type : "tool_use" ; name : string ; input ?: Record < string , unknown > } ;
1414type ThinkingBlock = { type : "thinking" } ;
15- type ToolResultBlock = { type : "tool_result" ; is_error ?: boolean } ;
15+ type ToolResultBlock = { type : "tool_result" ; is_error ?: boolean ; content ?: string | unknown [ ] } ;
1616
1717type ContentBlock = TextBlock | ToolUseBlock | ThinkingBlock | ToolResultBlock ;
1818
@@ -54,6 +54,28 @@ function redactSensitive(input: string): string {
5454 . replace ( / - - - - - B E G I N [ A - Z ] + K E Y - - - - - / g, "[REDACTED]" ) ;
5555}
5656
57+ function summarizeToolInput ( name : string , input : Record < string , unknown > ) : string {
58+ const filePath = input . file_path ?? input . path ;
59+ if ( typeof filePath === "string" ) return `Tool: ${ name } (${ truncate ( filePath , 80 ) } )` ;
60+ if ( typeof input . command === "string" ) return `Tool: ${ name } (${ truncate ( input . command , 80 ) } )` ;
61+ if ( typeof input . pattern === "string" ) return `Tool: ${ name } (${ truncate ( input . pattern , 80 ) } )` ;
62+ return `Tool: ${ name } ` ;
63+ }
64+
65+ function summarizeToolResult ( block : ToolResultBlock ) : string {
66+ if ( block . is_error === true ) return "Tool error" ;
67+ const content = block . content ;
68+ if ( typeof content === "string" && content . length > 0 ) return `Tool result: ${ truncate ( content , 120 ) } ` ;
69+ if ( Array . isArray ( content ) ) {
70+ for ( const part of content ) {
71+ if ( isRecord ( part ) && part . type === "text" && typeof part . text === "string" ) {
72+ return `Tool result: ${ truncate ( part . text , 120 ) } ` ;
73+ }
74+ }
75+ }
76+ return "Tool result" ;
77+ }
78+
5779/** Accepts a parsed JSONL record (untrusted) and returns a display summary, or null to skip. */
5880export function summarizeJsonlRecord ( record : Record < string , unknown > ) : string | null {
5981 const typed = record as JsonlRecord ;
@@ -67,14 +89,17 @@ export function summarizeJsonlRecord(record: Record<string, unknown>): string |
6789 for ( const block of content ) {
6890 if ( ! isRecord ( block ) ) continue ;
6991 switch ( block . type ) {
70- case "tool_use" :
71- return redactSensitive ( `Tool: ${ String ( ( block as ToolUseBlock ) . name ?? "unknown" ) } ` ) ;
92+ case "tool_use" : {
93+ const b = block as ToolUseBlock ;
94+ const input = isRecord ( b . input ) ? b . input : { } ;
95+ return redactSensitive ( summarizeToolInput ( String ( b . name ?? "unknown" ) , input ) ) ;
96+ }
7297 case "text" :
7398 return redactSensitive ( truncate ( String ( ( block as TextBlock ) . text ?? "" ) , 200 ) ) ;
7499 case "thinking" :
75100 return redactSensitive ( "Thinking..." ) ;
76101 case "tool_result" :
77- return redactSensitive ( ( block as ToolResultBlock ) . is_error === true ? "Tool error" : "Tool result" ) ;
102+ return redactSensitive ( summarizeToolResult ( block as ToolResultBlock ) ) ;
78103 }
79104 }
80105 return null ;
0 commit comments