3
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
4
*--------------------------------------------------------------------------------------------*/
5
5
6
- import { timeout } from '../../../../../base/common/async.js' ;
7
6
import { CancellationToken } from '../../../../../base/common/cancellation.js' ;
8
7
import { Emitter , Event } from '../../../../../base/common/event.js' ;
9
8
import { Disposable } from '../../../../../base/common/lifecycle.js' ;
10
9
import { ILanguageModelsService } from '../../../chat/common/languageModels.js' ;
11
10
import { IChatService } from '../../../chat/common/chatService.js' ;
12
- import { assessOutputForErrors , PollingConsts , racePollingOrPrompt , promptForMorePolling } from './bufferOutputPolling.js' ;
13
-
14
- export const enum OutputMonitorAction {
15
- PollingStarted = 'polling_started' ,
16
- OutputReceived = 'output_received' ,
17
- IdleDetected = 'idle_detected' ,
18
- TimeoutReached = 'timeout_reached' ,
19
- CancellationRequested = 'cancellation_requested' ,
20
- ExtendedPollingStarted = 'extended_polling_started' ,
21
- AssessmentCompleted = 'assessment_completed'
22
- }
11
+ import { racePollingOrPrompt , promptForMorePolling , pollForOutputAndIdle } from './bufferOutputPolling.js' ;
23
12
24
13
export interface IOutputMonitor extends Disposable {
25
- readonly actions : OutputMonitorAction [ ] ;
26
14
readonly isIdle : boolean ;
27
15
28
16
readonly onDidFinishCommand : Event < void > ;
@@ -38,7 +26,6 @@ export interface IOutputMonitor extends Disposable {
38
26
}
39
27
40
28
export class OutputMonitor extends Disposable implements IOutputMonitor {
41
- private readonly _actions : OutputMonitorAction [ ] = [ ] ;
42
29
private _isIdle = false ;
43
30
44
31
private readonly _onDidFinishCommand = this . _register ( new Emitter < void > ( ) ) ;
@@ -48,17 +35,13 @@ export class OutputMonitor extends Disposable implements IOutputMonitor {
48
35
private readonly _onDidTimeout = this . _register ( new Emitter < void > ( ) ) ;
49
36
readonly onDidTimeout = this . _onDidTimeout . event ;
50
37
51
- get actions ( ) : OutputMonitorAction [ ] {
52
- return [ ...this . _actions ] ;
53
- }
54
-
55
38
get isIdle ( ) : boolean {
56
39
return this . _isIdle ;
57
40
}
58
41
59
42
constructor (
60
43
private readonly _execution : { getOutput : ( ) => string ; isActive ?: ( ) => Promise < boolean > } ,
61
- private readonly _languageModelsService : ILanguageModelsService
44
+ @ ILanguageModelsService private readonly _languageModelsService : ILanguageModelsService
62
45
) {
63
46
super ( ) ;
64
47
}
@@ -69,11 +52,11 @@ export class OutputMonitor extends Disposable implements IOutputMonitor {
69
52
invocationContext : any ,
70
53
token : CancellationToken
71
54
) : Promise < { terminalExecutionIdleBeforeTimeout : boolean ; output : string ; pollDurationMs ?: number ; modelOutputEvalResponse ?: string } > {
72
- let result = await this . _startMonitoring ( false , token ) ;
55
+ let result = await pollForOutputAndIdle ( this . _execution , false , token , this . _languageModelsService ) ;
73
56
74
57
if ( ! result . terminalExecutionIdleBeforeTimeout ) {
75
58
result = await racePollingOrPrompt (
76
- ( ) => this . _startMonitoring ( true , token ) ,
59
+ ( ) => pollForOutputAndIdle ( this . _execution , true , token , this . _languageModelsService ) ,
77
60
( ) => promptForMorePolling ( command , token , invocationContext , chatService ) ,
78
61
result ,
79
62
token ,
@@ -84,89 +67,4 @@ export class OutputMonitor extends Disposable implements IOutputMonitor {
84
67
85
68
return result ;
86
69
}
87
-
88
- protected async _startMonitoring ( extendedPolling : boolean , token : CancellationToken ) : Promise < { terminalExecutionIdleBeforeTimeout : boolean ; output : string ; pollDurationMs ?: number ; modelOutputEvalResponse ?: string } > {
89
- this . _addAction ( OutputMonitorAction . PollingStarted ) ;
90
- if ( extendedPolling ) {
91
- this . _addAction ( OutputMonitorAction . ExtendedPollingStarted ) ;
92
- }
93
-
94
- const maxWaitMs = extendedPolling ? PollingConsts . ExtendedPollingMaxDuration : PollingConsts . FirstPollingMaxDuration ;
95
- const maxInterval = PollingConsts . MaxPollingIntervalDuration ;
96
- let currentInterval = PollingConsts . MinPollingDuration ;
97
- const pollStartTime = Date . now ( ) ;
98
-
99
- let lastBufferLength = 0 ;
100
- let noNewDataCount = 0 ;
101
- let buffer = '' ;
102
- let terminalExecutionIdleBeforeTimeout = false ;
103
-
104
- while ( true ) {
105
- if ( token . isCancellationRequested ) {
106
- this . _addAction ( OutputMonitorAction . CancellationRequested ) ;
107
- break ;
108
- }
109
- const now = Date . now ( ) ;
110
- const elapsed = now - pollStartTime ;
111
- const timeLeft = maxWaitMs - elapsed ;
112
-
113
- if ( timeLeft <= 0 ) {
114
- this . _addAction ( OutputMonitorAction . TimeoutReached ) ;
115
- this . _onDidTimeout . fire ( ) ;
116
- break ;
117
- }
118
-
119
- // Cap the wait so we never overshoot timeLeft
120
- const waitTime = Math . min ( currentInterval , timeLeft ) ;
121
- await timeout ( waitTime ) ;
122
-
123
- // Check again immediately after waking
124
- if ( Date . now ( ) - pollStartTime >= maxWaitMs ) {
125
- this . _addAction ( OutputMonitorAction . TimeoutReached ) ;
126
- this . _onDidTimeout . fire ( ) ;
127
- break ;
128
- }
129
-
130
- currentInterval = Math . min ( currentInterval * 2 , maxInterval ) ;
131
-
132
- buffer = this . _execution . getOutput ( ) ;
133
- const currentBufferLength = buffer . length ;
134
-
135
- if ( currentBufferLength !== lastBufferLength ) {
136
- this . _addAction ( OutputMonitorAction . OutputReceived ) ;
137
- }
138
-
139
- if ( currentBufferLength === lastBufferLength ) {
140
- noNewDataCount ++ ;
141
- } else {
142
- noNewDataCount = 0 ;
143
- lastBufferLength = currentBufferLength ;
144
- }
145
-
146
- if ( noNewDataCount >= PollingConsts . MinNoDataEvents ) {
147
- if ( this . _execution . isActive && ( ( await this . _execution . isActive ( ) ) === true ) ) {
148
- noNewDataCount = 0 ;
149
- lastBufferLength = currentBufferLength ;
150
- continue ;
151
- }
152
- this . _addAction ( OutputMonitorAction . IdleDetected ) ;
153
- this . _isIdle = true ;
154
- this . _onDidIdle . fire ( ) ;
155
- terminalExecutionIdleBeforeTimeout = true ;
156
-
157
- this . _addAction ( OutputMonitorAction . AssessmentCompleted ) ;
158
- const modelOutputEvalResponse = await assessOutputForErrors ( buffer , token , this . _languageModelsService ) ;
159
-
160
- this . _onDidFinishCommand . fire ( ) ;
161
- return { modelOutputEvalResponse, terminalExecutionIdleBeforeTimeout, output : buffer , pollDurationMs : Date . now ( ) - pollStartTime + ( extendedPolling ? PollingConsts . FirstPollingMaxDuration : 0 ) } ;
162
- }
163
- }
164
-
165
- this . _onDidFinishCommand . fire ( ) ;
166
- return { terminalExecutionIdleBeforeTimeout : false , output : buffer , pollDurationMs : Date . now ( ) - pollStartTime + ( extendedPolling ? PollingConsts . FirstPollingMaxDuration : 0 ) } ;
167
- }
168
-
169
- private _addAction ( action : OutputMonitorAction ) : void {
170
- this . _actions . push ( action ) ;
171
- }
172
70
}
0 commit comments