1
1
import * as vscode from 'vscode' ;
2
2
3
- import { COMMAND_DASHBOARD , LogLevel } from '../constants' ;
3
+ import { AI_RECENT_PASTES_TIME_MS , COMMAND_DASHBOARD , LogLevel } from '../constants' ;
4
4
5
5
import { Logger } from './logger' ;
6
6
import { Memento } from 'vscode' ;
@@ -26,9 +26,14 @@ export class WakaTime {
26
26
private lastHeartbeat : number = 0 ;
27
27
private lastDebug : boolean = false ;
28
28
private lastCompile : boolean = false ;
29
+ private lastAICodeGenerating : boolean = false ;
29
30
private dedupe : FileSelectionMap = { } ;
30
31
private debounceTimeoutId : any = null ;
31
32
private debounceMs = 50 ;
33
+ private AIDebounceTimeoutId : any = null ;
34
+ private AIdebounceMs = 1000 ;
35
+ private AIdebounceCount = 0 ;
36
+ private AIrecentPastes : number [ ] = [ ] ;
32
37
private logger : Logger ;
33
38
private config : Memento ;
34
39
private fetchTodayInterval : number = 60000 ;
@@ -40,6 +45,7 @@ export class WakaTime {
40
45
private disabled : boolean = true ;
41
46
private isCompiling : boolean = false ;
42
47
private isDebugging : boolean = false ;
48
+ private isAICodeGenerating : boolean = false ;
43
49
private currentlyFocusedFile : string ;
44
50
private teamDevsForFileCache = { } ;
45
51
private lastApiKeyPrompted : number = 0 ;
@@ -329,9 +335,13 @@ export class WakaTime {
329
335
// subscribe to selection change and editor activation events
330
336
let subscriptions : vscode . Disposable [ ] = [ ] ;
331
337
vscode . window . onDidChangeTextEditorSelection ( this . onChangeSelection , this , subscriptions ) ;
338
+ vscode . workspace . onDidChangeTextDocument ( this . onChangeTextDocument , this , subscriptions ) ;
332
339
vscode . window . onDidChangeActiveTextEditor ( this . onChangeTab , this , subscriptions ) ;
333
340
vscode . workspace . onDidSaveTextDocument ( this . onSave , this , subscriptions ) ;
334
341
342
+ vscode . workspace . onDidChangeNotebookDocument ( this . onChangeNotebook , this , subscriptions ) ;
343
+ vscode . workspace . onDidSaveNotebookDocument ( this . onSaveNotebook , this , subscriptions ) ;
344
+
335
345
vscode . tasks . onDidStartTask ( this . onDidStartTask , this , subscriptions ) ;
336
346
vscode . tasks . onDidEndTask ( this . onDidEndTask , this , subscriptions ) ;
337
347
@@ -375,6 +385,36 @@ export class WakaTime {
375
385
this . onEvent ( false ) ;
376
386
}
377
387
388
+ private onChangeTextDocument ( e : vscode . TextDocumentChangeEvent ) : void {
389
+ if ( Utils . isAIChatSidebar ( e . document ?. uri ) ) {
390
+ this . isAICodeGenerating = true ;
391
+ this . AIdebounceCount = 0 ;
392
+ } else if ( Utils . isPossibleAICodeInsert ( e ) ) {
393
+ const now = Date . now ( ) ;
394
+ if ( this . recentlyAIPasted ( now ) ) {
395
+ this . isAICodeGenerating = true ;
396
+ this . AIdebounceCount = 0 ;
397
+ }
398
+ this . AIrecentPastes . push ( now ) ;
399
+ } else if ( Utils . isPossibleHumanCodeInsert ( e ) ) {
400
+ this . AIrecentPastes = [ ] ;
401
+ if ( this . isAICodeGenerating ) {
402
+ this . AIdebounceCount ++ ;
403
+ clearTimeout ( this . AIDebounceTimeoutId ) ;
404
+ this . AIDebounceTimeoutId = setTimeout ( ( ) => {
405
+ if ( this . AIdebounceCount > 1 ) {
406
+ this . isAICodeGenerating = false ;
407
+ }
408
+ } , this . AIdebounceMs ) ;
409
+ }
410
+ } else if ( this . isAICodeGenerating ) {
411
+ this . AIdebounceCount = 0 ;
412
+ clearTimeout ( this . AIDebounceTimeoutId ) ;
413
+ }
414
+ if ( ! this . isAICodeGenerating ) return ;
415
+ this . onEvent ( false ) ;
416
+ }
417
+
378
418
private onChangeTab ( _e : vscode . TextEditor | undefined ) : void {
379
419
this . onEvent ( false ) ;
380
420
}
@@ -383,6 +423,14 @@ export class WakaTime {
383
423
this . onEvent ( true ) ;
384
424
}
385
425
426
+ private onChangeNotebook ( _e : vscode . NotebookDocumentChangeEvent ) : void {
427
+ this . onEvent ( false ) ;
428
+ }
429
+
430
+ private onSaveNotebook ( _e : vscode . NotebookDocument | undefined ) : void {
431
+ this . onEvent ( true ) ;
432
+ }
433
+
386
434
private onEvent ( isWrite : boolean ) : void {
387
435
clearTimeout ( this . debounceTimeoutId ) ;
388
436
this . debounceTimeoutId = setTimeout ( ( ) => {
@@ -402,10 +450,11 @@ export class WakaTime {
402
450
let time : number = Date . now ( ) ;
403
451
if (
404
452
isWrite ||
405
- this . enoughTimePassed ( time ) ||
453
+ Utils . enoughTimePassed ( this . lastHeartbeat , time ) ||
406
454
this . lastFile !== file ||
407
455
this . lastDebug !== this . isDebugging ||
408
- this . lastCompile !== this . isCompiling
456
+ this . lastCompile !== this . isCompiling ||
457
+ this . lastAICodeGenerating !== this . isAICodeGenerating
409
458
) {
410
459
this . sendHeartbeat (
411
460
doc ,
@@ -414,11 +463,13 @@ export class WakaTime {
414
463
isWrite ,
415
464
this . isCompiling ,
416
465
this . isDebugging ,
466
+ this . isAICodeGenerating ,
417
467
) ;
418
468
this . lastFile = file ;
419
469
this . lastHeartbeat = time ;
420
470
this . lastDebug = this . isDebugging ;
421
471
this . lastCompile = this . isCompiling ;
472
+ this . lastAICodeGenerating = this . isAICodeGenerating ;
422
473
}
423
474
}
424
475
}
@@ -433,10 +484,11 @@ export class WakaTime {
433
484
isWrite : boolean ,
434
485
isCompiling : boolean ,
435
486
isDebugging : boolean ,
487
+ isAICoding : boolean ,
436
488
) : void {
437
489
this . hasApiKey ( ( hasApiKey ) => {
438
490
if ( hasApiKey ) {
439
- this . _sendHeartbeat ( doc , time , selection , isWrite , isCompiling , isDebugging ) ;
491
+ this . _sendHeartbeat ( doc , time , selection , isWrite , isCompiling , isDebugging , isAICoding ) ;
440
492
} else {
441
493
this . promptForApiKey ( ) ;
442
494
}
@@ -450,6 +502,7 @@ export class WakaTime {
450
502
isWrite : boolean ,
451
503
isCompiling : boolean ,
452
504
isDebugging : boolean ,
505
+ isAICoding : boolean ,
453
506
) {
454
507
let file = doc . fileName ;
455
508
if ( Utils . isRemoteUri ( doc . uri ) ) {
@@ -487,6 +540,8 @@ export class WakaTime {
487
540
payload [ 'category' ] = 'debugging' ;
488
541
} else if ( isCompiling ) {
489
542
payload [ 'category' ] = 'building' ;
543
+ } else if ( isAICoding ) {
544
+ payload [ 'category' ] = 'ai coding' ;
490
545
} else if ( Utils . isPullRequest ( doc . uri ) ) {
491
546
payload [ 'category' ] = 'code reviewing' ;
492
547
}
@@ -741,8 +796,9 @@ export class WakaTime {
741
796
}
742
797
}
743
798
744
- private enoughTimePassed ( time : number ) : boolean {
745
- return this . lastHeartbeat + 120000 < time ;
799
+ private recentlyAIPasted ( time : number ) : boolean {
800
+ this . AIrecentPastes = this . AIrecentPastes . filter ( ( x ) => x + AI_RECENT_PASTES_TIME_MS >= time ) ;
801
+ return this . AIrecentPastes . length > 3 ;
746
802
}
747
803
748
804
private isDuplicateHeartbeat ( file : string , time : number , selection : vscode . Position ) : boolean {
0 commit comments