@@ -79,8 +79,6 @@ interface CompileMetrics {
7979 outputTokens : number ;
8080 reasoningTokens : number ;
8181 toolCalls : number ;
82- filesWritten : Set < string > ;
83- filesDeleted : Set < string > ;
8482 lastAssistantMessage : string ;
8583 errors : string [ ] ;
8684}
@@ -417,14 +415,34 @@ function formatDuration(ms: number): string {
417415}
418416
419417/** Count LOC across files the agent actually wrote (ignores node_modules etc.) */
420- function countAgentOutput ( filesWritten : Set < string > ) : { files : number ; lines : number } {
421- let lines = 0 ;
418+ const SCAN_IGNORE = new Set ( [
419+ "node_modules" , ".git" , "__pycache__" , ".mypy_cache" , ".pytest_cache" ,
420+ "target" , "vendor" , ".build" , "build" , "DerivedData" , ".gradle" ,
421+ ".dart_tool" , ".packages" , "Pods" ,
422+ ] ) ;
423+
424+ function countOutputDir ( dir : string ) : { files : number ; lines : number } {
422425 let files = 0 ;
423- for ( const fp of filesWritten ) {
424- if ( ! existsSync ( fp ) ) continue ;
425- files ++ ;
426- lines += readFileSync ( fp , "utf-8" ) . split ( "\n" ) . length ;
427- }
426+ let lines = 0 ;
427+ if ( ! existsSync ( dir ) ) return { files, lines } ;
428+
429+ const walk = ( d : string ) => {
430+ for ( const entry of readdirSync ( d , { withFileTypes : true } ) ) {
431+ if ( entry . name . startsWith ( "." ) || SCAN_IGNORE . has ( entry . name ) ) continue ;
432+ const full = join ( d , entry . name ) ;
433+ if ( entry . isDirectory ( ) ) {
434+ walk ( full ) ;
435+ } else if ( entry . isFile ( ) ) {
436+ files ++ ;
437+ try {
438+ lines += readFileSync ( full , "utf-8" ) . split ( "\n" ) . length ;
439+ } catch {
440+ /* binary or unreadable — skip */
441+ }
442+ }
443+ }
444+ } ;
445+ walk ( dir ) ;
428446 return { files, lines } ;
429447}
430448
@@ -627,20 +645,18 @@ function printSummary(
627645 passNumber = 1 ,
628646) : void {
629647 const elapsed = Date . now ( ) - metrics . startTime ;
630- const { files, lines } = countAgentOutput ( metrics . filesWritten ) ;
631- const deleted = metrics . filesDeleted . size ;
648+ const { files, lines } = countOutputDir ( outDir ) ;
632649 const totalTokens = metrics . inputTokens + metrics . outputTokens ;
633650
634651 const tokenDetail =
635652 `(${ metrics . inputTokens . toLocaleString ( ) } in / ${ metrics . outputTokens . toLocaleString ( ) } out` +
636653 `${ metrics . reasoningTokens ? ` / ${ metrics . reasoningTokens . toLocaleString ( ) } reasoning` : "" } )` ;
637654
638655 const passLabel = passNumber > 1 ? ` (pass ${ passNumber } )` : "" ;
639- const filesLine = deleted > 0 ? `${ files } written, ${ deleted } deleted` : `${ files } written` ;
640656 const body = [
641657 `Model: ${ config . model } ${ config . effort ? ` (${ config . effort } effort)` : "" } ` ,
642658 `Time: ${ formatDuration ( elapsed ) } ` ,
643- `Files: ${ filesLine } ` ,
659+ `Files: ${ files } ` ,
644660 `LOC: ~${ lines . toLocaleString ( ) } lines` ,
645661 `Tokens: ~${ totalTokens . toLocaleString ( ) } total ${ tokenDetail } ` ,
646662 `Tools: ${ metrics . toolCalls } calls` ,
@@ -719,8 +735,6 @@ async function cmdBuild(
719735 outputTokens : 0 ,
720736 reasoningTokens : 0 ,
721737 toolCalls : 0 ,
722- filesWritten : new Set ( ) ,
723- filesDeleted : new Set ( ) ,
724738 lastAssistantMessage : "" ,
725739 errors : [ ] ,
726740 } ;
@@ -894,34 +908,8 @@ your final message like this:
894908 metrics . reasoningTokens += event . data . reasoningTokens ?? 0 ;
895909 } ) ;
896910
897- session . on ( "tool.execution_start" , ( event ) => {
911+ session . on ( "tool.execution_start" , ( ) => {
898912 metrics . toolCalls ++ ;
899- const { toolName } = event . data ;
900- const args = event . data . arguments as Record < string , unknown > | undefined ;
901- if ( args ) {
902- const filePath = ( args . path ?? args . file_path ?? args . filePath ?? args . file ) as string | undefined ;
903- const isWrite =
904- toolName === "edit_file" ||
905- toolName === "create_file" ||
906- toolName === "write_file" ||
907- toolName === "create" ||
908- toolName === "edit" ||
909- toolName === "write" ||
910- toolName === "write_to_file" ||
911- toolName === "str_replace_editor" ||
912- toolName === "insert_edit_into_file" ||
913- toolName . includes ( "edit" ) ||
914- toolName . includes ( "create" ) ||
915- toolName . includes ( "write" ) ;
916- const isDelete = toolName === "delete_file" || toolName === "delete" || toolName . includes ( "delete" ) ;
917-
918- if ( isDelete && filePath ) {
919- metrics . filesDeleted . add ( filePath ) ;
920- metrics . filesWritten . delete ( filePath ) ;
921- } else if ( isWrite && filePath ) {
922- metrics . filesWritten . add ( filePath ) ;
923- }
924- }
925913 } ) ;
926914
927915 session . on ( "session.error" , ( event ) => {
0 commit comments