11const axios = require ( 'axios' ) ;
2+ const config = require ( './config.json' ) ;
23
34/**
45 * ActivityWatch Integration
@@ -96,9 +97,9 @@ class ActivityWatchIntegration {
9697 }
9798 } ;
9899
99- // Retry mechanism for network issues
100+ // Enhanced retry mechanism for network issues
100101 let response ;
101- const maxRetries = 3 ;
102+ const maxRetries = 5 ;
102103 let lastError ;
103104
104105 for ( let attempt = 1 ; attempt <= maxRetries ; attempt ++ ) {
@@ -108,7 +109,9 @@ class ActivityWatchIntegration {
108109 [ event ] ,
109110 {
110111 headers : { 'Content-Type' : 'application/json' } ,
111- timeout : 5000
112+ timeout : 10000 , // Increased timeout
113+ // Add connection keep-alive
114+ httpAgent : new ( require ( 'http' ) . Agent ) ( { keepAlive : true } ) ,
112115 }
113116 ) ;
114117 break ; // Success, exit retry loop
@@ -120,13 +123,16 @@ class ActivityWatchIntegration {
120123 attemptError . code === 'ECONNRESET' ||
121124 attemptError . code === 'ENOTFOUND' ||
122125 attemptError . code === 'ETIMEDOUT' ||
126+ attemptError . code === 'ECONNREFUSED' ||
123127 attemptError . message . includes ( 'socket hang up' ) ||
124- attemptError . message . includes ( 'timeout' )
128+ attemptError . message . includes ( 'timeout' ) ||
129+ attemptError . message . includes ( 'ECONNRESET' )
125130 ) ;
126131
127132 if ( isRetryable && attempt < maxRetries ) {
128- console . warn ( `[ActivityWatch] Recording attempt ${ attempt } failed (${ attemptError . message } ), retrying...` ) ;
129- await new Promise ( resolve => setTimeout ( resolve , 1000 * attempt ) ) ; // Exponential backoff
133+ const backoffDelay = Math . min ( 1000 * Math . pow ( 2 , attempt - 1 ) , 5000 ) ; // Exponential backoff, max 5s
134+ console . warn ( `[ActivityWatch] Main recording attempt ${ attempt } failed (${ attemptError . message } ), retrying in ${ backoffDelay } ms...` ) ;
135+ await new Promise ( resolve => setTimeout ( resolve , backoffDelay ) ) ;
130136 continue ;
131137 } else {
132138 // Not retryable or max retries exceeded
@@ -166,53 +172,76 @@ class ActivityWatchIntegration {
166172 try {
167173 const windowBucket = `aw-watcher-window_${ this . hostname } ` ;
168174
169- // Create fake window event that looks like a real application
175+ // Create fake window event with configured app name for work categorization
176+ // Using more generic IT/development-related app names
170177 const windowEvent = {
171178 timestamp : timestamp ,
172179 duration : durationSeconds ,
173180 data : {
174- app : ` ${ projectName . toLowerCase ( ) } -ai-assistant` ,
175- title : `${ projectName } AI Assistant - Session ${ sessionId ?. slice ( - 8 ) || 'work' } `
181+ app : config . activityWatch . integration . fakeAppName ,
182+ title : `${ config . activityWatch . integration . sessionTitleTemplate } - ${ projectName } AI Assistant Session ${ sessionId ?. slice ( - 8 ) || 'work' } `
176183 }
177184 } ;
178185
179- // Try to record to window bucket
180- try {
181- await axios . post (
182- `${ this . baseUrl } /buckets/${ windowBucket } /events` ,
183- [ windowEvent ] ,
184- {
185- headers : { 'Content-Type' : 'application/json' } ,
186- timeout : 5000
187- }
188- ) ;
189- console . log ( `[ActivityWatch] Window event recorded: ${ windowEvent . data . app } | ${ durationSeconds . toFixed ( 1 ) } s` ) ;
190- } catch ( error ) {
191- // If window bucket doesn't exist, try to create it first
192- if ( error . response ?. status === 404 ) {
193- console . log ( `[ActivityWatch] Creating window bucket: ${ windowBucket } ` ) ;
194- await axios . post ( `${ this . baseUrl } /buckets/${ windowBucket } ` , {
195- type : 'currentwindow' ,
196- client : 'aw-watcher-window' ,
197- hostname : this . hostname
198- } ) ;
199-
200- // Retry recording after creating bucket
186+ // Enhanced retry mechanism for socket issues
187+ const maxRetries = 5 ;
188+ let lastError ;
189+
190+ for ( let attempt = 1 ; attempt <= maxRetries ; attempt ++ ) {
191+ try {
201192 await axios . post (
202193 `${ this . baseUrl } /buckets/${ windowBucket } /events` ,
203194 [ windowEvent ] ,
204195 {
205196 headers : { 'Content-Type' : 'application/json' } ,
206- timeout : 5000
197+ timeout : 10000 , // Increased timeout
198+ // Add connection keep-alive
199+ httpAgent : new ( require ( 'http' ) . Agent ) ( { keepAlive : true } ) ,
207200 }
208201 ) ;
209- console . log ( `[ActivityWatch] Window event recorded after bucket creation: ${ windowEvent . data . app } ` ) ;
210- } else {
211- throw error ;
202+ console . log ( `[ActivityWatch] Window event recorded: ${ windowEvent . data . app } | ${ durationSeconds . toFixed ( 1 ) } s | attempt ${ attempt } ` ) ;
203+ return ; // Success, exit function
204+ } catch ( error ) {
205+ lastError = error ;
206+
207+ // Handle bucket creation first
208+ if ( error . response ?. status === 404 && attempt === 1 ) {
209+ console . log ( `[ActivityWatch] Creating window bucket: ${ windowBucket } ` ) ;
210+ try {
211+ await axios . post ( `${ this . baseUrl } /buckets/${ windowBucket } ` , {
212+ type : 'currentwindow' ,
213+ client : 'aw-watcher-window' ,
214+ hostname : this . hostname
215+ } , { timeout : 10000 } ) ;
216+ continue ; // Retry recording after creating bucket
217+ } catch ( bucketError ) {
218+ console . warn ( `[ActivityWatch] Could not create window bucket: ${ bucketError . message } ` ) ;
219+ }
220+ }
221+
222+ // Handle retryable errors
223+ const isRetryable = (
224+ error . code === 'ECONNRESET' ||
225+ error . code === 'ENOTFOUND' ||
226+ error . code === 'ETIMEDOUT' ||
227+ error . code === 'ECONNREFUSED' ||
228+ error . message . includes ( 'socket hang up' ) ||
229+ error . message . includes ( 'timeout' ) ||
230+ error . message . includes ( 'ECONNRESET' )
231+ ) ;
232+
233+ if ( isRetryable && attempt < maxRetries ) {
234+ const backoffDelay = Math . min ( 1000 * Math . pow ( 2 , attempt - 1 ) , 5000 ) ; // Exponential backoff, max 5s
235+ console . warn ( `[ActivityWatch] Window event attempt ${ attempt } failed (${ error . message } ), retrying in ${ backoffDelay } ms...` ) ;
236+ await new Promise ( resolve => setTimeout ( resolve , backoffDelay ) ) ;
237+ continue ;
238+ } else {
239+ throw error ;
240+ }
212241 }
213242 }
214243 } catch ( error ) {
215- console . warn ( `[ActivityWatch] Could not record window event: ${ error . message } ` ) ;
244+ console . warn ( `[ActivityWatch] Could not record window event after ${ maxRetries } attempts : ${ error . message } ` ) ;
216245 }
217246 }
218247
0 commit comments