@@ -60,10 +60,10 @@ async function extractSummaryTitle(
6060 * @returns The event hook function
6161 *
6262 * @remarks
63- * Handles two types of events:
64- *
65- * 1. **message.part.updated** - Tracks token usage from step-finish parts
66- * 2. **session.idle** - Finalizes and exports the session
63+ * Handles two types of events:
64+ *
65+ * 1. **message.part.updated** - Tracks token usage from step-finish parts
66+ * 2. **session.idle** - Finalizes and exports the session
6767 *
6868 * @example
6969 * ```typescript
@@ -77,6 +77,9 @@ export function createEventHook(
7777 csvWriter : CsvWriter ,
7878 client : OpencodeClient
7979) {
80+ // Track sessions that are currently being processed to prevent duplicates
81+ const processingSessions = new Set < string > ( )
82+
8083 return async ( { event } : { event : Event } ) : Promise < void > => {
8184 // Track token usage from step-finish events
8285 if ( event . type === "message.part.updated" ) {
@@ -105,13 +108,33 @@ export function createEventHook(
105108 return
106109 }
107110
111+ // Debug: Log all session.idle events
112+ console . log ( `[TimeTracking] ${ new Date ( ) . toISOString ( ) } Received session.idle for session ${ sessionID } , processingSessions size before: ${ processingSessions . size } ` )
113+
114+ // Prevent duplicate processing if this session is already being handled
115+ if ( processingSessions . has ( sessionID ) ) {
116+ console . log ( `[TimeTracking] ${ new Date ( ) . toISOString ( ) } Skipping duplicate session.idle for session ${ sessionID } ` )
117+ return
118+ }
119+
120+ // Mark this session as being processed
121+ processingSessions . add ( sessionID )
122+ console . log ( `[TimeTracking] ${ new Date ( ) . toISOString ( ) } Added session ${ sessionID } to processingSessions, size now: ${ processingSessions . size } ` )
123+
108124 const session = sessionManager . get ( sessionID )
109125
110126 if ( ! session || session . activities . length === 0 ) {
111127 sessionManager . delete ( sessionID )
128+ processingSessions . delete ( sessionID )
112129 return
113130 }
114131
132+ // Delete session immediately to prevent duplicate processing
133+ sessionManager . delete ( sessionID )
134+
135+ // Debug: Log if we're processing this session
136+ console . log ( `[TimeTracking] ${ new Date ( ) . toISOString ( ) } Processing session.idle for session ${ sessionID } , activities: ${ session . activities . length } , processingSessions: [${ Array . from ( processingSessions ) . join ( ', ' ) } ]` )
137+
115138 const endTime = Date . now ( )
116139 const durationSeconds = Math . round ( ( endTime - session . startTime ) / 1000 )
117140
@@ -155,9 +178,10 @@ export function createEventHook(
155178 variant : "error" ,
156179 } ,
157180 } )
158- }
181+ }
159182
160- sessionManager . delete ( sessionID )
161- }
183+ // Remove from processing set when done
184+ processingSessions . delete ( sessionID )
185+ }
162186 }
163187}
0 commit comments