Skip to content

Commit d7ada25

Browse files
authored
Merge pull request microsoft#273112 from microsoft/tyriar/264565
Handle terminal exit while terminal tool is in progress
2 parents f2529aa + b537b64 commit d7ada25

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/executeStrategy/basicExecuteStrategy.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,19 @@ export class BasicExecuteStrategy implements ITerminalExecuteStrategy {
6666
this._log('onDone 1 of 2 via end event, waiting for short idle prompt');
6767
return idlePromptPromise.then(() => {
6868
this._log('onDone 2 of 2 via short idle prompt');
69-
return e;
69+
return {
70+
'type': 'success',
71+
command: e
72+
} as const;
7073
});
7174
}),
7275
Event.toPromise(token.onCancellationRequested as Event<undefined>, store).then(() => {
7376
this._log('onDone via cancellation');
7477
}),
78+
Event.toPromise(this._instance.onDisposed, store).then(() => {
79+
this._log('onDone via terminal disposal');
80+
return { type: 'disposal' } as const;
81+
}),
7582
// A longer idle prompt event is used here as a catch all for unexpected cases where
7683
// the end event doesn't fire for some reason.
7784
trackIdleOnPrompt(this._instance, 3000, store).then(() => {
@@ -115,7 +122,12 @@ export class BasicExecuteStrategy implements ITerminalExecuteStrategy {
115122

116123
// Wait for the next end execution event - note that this may not correspond to the actual
117124
// execution requested
118-
const finishedCommand = await onDone;
125+
this._log('Waiting for done event');
126+
const onDoneResult = await onDone;
127+
if (onDoneResult && onDoneResult.type === 'disposal') {
128+
throw new Error('The terminal was closed');
129+
}
130+
const finishedCommand = onDoneResult && onDoneResult.type === 'success' ? onDoneResult.command : undefined;
119131

120132
// Wait for the terminal to idle
121133
this._log('Waiting for idle');

src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/executeStrategy/richExecuteStrategy.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { CancellationError } from '../../../../../../base/common/errors.js';
88
import { Emitter, Event } from '../../../../../../base/common/event.js';
99
import { DisposableStore, MutableDisposable } from '../../../../../../base/common/lifecycle.js';
1010
import { isNumber } from '../../../../../../base/common/types.js';
11-
import type { ICommandDetectionCapability, ITerminalCommand } from '../../../../../../platform/terminal/common/capabilities/capabilities.js';
11+
import type { ICommandDetectionCapability } from '../../../../../../platform/terminal/common/capabilities/capabilities.js';
1212
import { ITerminalLogService } from '../../../../../../platform/terminal/common/terminal.js';
1313
import type { ITerminalInstance } from '../../../../terminal/browser/terminal.js';
1414
import { trackIdleOnPrompt, type ITerminalExecuteStrategy, type ITerminalExecuteStrategyResult } from './executeStrategy.js';
@@ -46,14 +46,21 @@ export class RichExecuteStrategy implements ITerminalExecuteStrategy {
4646
throw new Error('Xterm is not available');
4747
}
4848

49-
const onDone: Promise<ITerminalCommand | void> = Promise.race([
49+
const onDone = Promise.race([
5050
Event.toPromise(this._commandDetection.onCommandFinished, store).then(e => {
5151
this._log('onDone via end event');
52-
return e;
52+
return {
53+
'type': 'success',
54+
command: e
55+
} as const;
5356
}),
5457
Event.toPromise(token.onCancellationRequested as Event<undefined>, store).then(() => {
5558
this._log('onDone via cancellation');
5659
}),
60+
Event.toPromise(this._instance.onDisposed, store).then(() => {
61+
this._log('onDone via terminal disposal');
62+
return { type: 'disposal' } as const;
63+
}),
5764
trackIdleOnPrompt(this._instance, 1000, store).then(() => {
5865
this._log('onDone via idle prompt');
5966
}),
@@ -73,7 +80,12 @@ export class RichExecuteStrategy implements ITerminalExecuteStrategy {
7380

7481
// Wait for the terminal to idle
7582
this._log('Waiting for done event');
76-
const finishedCommand = await onDone;
83+
const onDoneResult = await onDone;
84+
if (onDoneResult && onDoneResult.type === 'disposal') {
85+
throw new Error('The terminal was closed');
86+
}
87+
const finishedCommand = onDoneResult && onDoneResult.type === 'success' ? onDoneResult.command : undefined;
88+
7789
if (token.isCancellationRequested) {
7890
throw new CancellationError();
7991
}

0 commit comments

Comments
 (0)