Skip to content

Commit 51b78b5

Browse files
authored
Merge pull request microsoft#257844 from microsoft/tyriar/257822__share
Share logic between fg/bg terminals
2 parents b5eca89 + a917218 commit 51b78b5

File tree

1 file changed

+48
-59
lines changed

1 file changed

+48
-59
lines changed

src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/runInTerminalTool.ts

Lines changed: 48 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -274,40 +274,35 @@ export class RunInTerminalTool extends Disposable implements IToolImpl {
274274
}
275275

276276
let error: string | undefined;
277+
const isNewSession = !args.isBackground && !this._sessionTerminalAssociations.has(chatSessionId);
277278

278279
const timingStart = Date.now();
279280
const termId = generateUuid();
280281

281-
if (args.isBackground) {
282-
const store = new DisposableStore();
283-
let outputAndIdle: { terminalExecutionIdleBeforeTimeout: boolean; output: string; pollDurationMs?: number; modelOutputEvalResponse?: string } | undefined = undefined;
282+
const store = new DisposableStore();
284283

285-
this._logService.debug(`RunInTerminalTool: Creating background terminal with ID=${termId}`);
286-
const toolTerminal = await this._instantiationService.createInstance(ToolTerminalCreator).createTerminal(token);
287-
this._sessionTerminalAssociations.set(chatSessionId, toolTerminal);
288-
if (token.isCancellationRequested) {
289-
toolTerminal.instance.dispose();
290-
throw new CancellationError();
291-
}
292-
await this._setupTerminalAssociation(toolTerminal, chatSessionId, termId, args.isBackground);
284+
this._logService.debug(`RunInTerminalTool: Creating ${args.isBackground ? 'background' : 'foreground'} terminal. termId=${termId}, chatSessionId=${chatSessionId}`);
285+
const toolTerminal = await (args.isBackground ? this._initBackgroundTerminal : this._initForegroundTerminal)(chatSessionId, termId, token);
293286

294-
this._terminalService.setActiveInstance(toolTerminal.instance);
295-
const timingConnectMs = Date.now() - timingStart;
287+
this._terminalService.setActiveInstance(toolTerminal.instance);
288+
const timingConnectMs = Date.now() - timingStart;
296289

297-
const xterm = await toolTerminal.instance.xtermReadyPromise;
298-
if (!xterm) {
299-
throw new Error('Instance was disposed before xterm.js was ready');
300-
}
290+
const xterm = await toolTerminal.instance.xtermReadyPromise;
291+
if (!xterm) {
292+
throw new Error('Instance was disposed before xterm.js was ready');
293+
}
301294

302-
let inputUserChars = 0;
303-
let inputUserSigint = false;
304-
store.add(xterm.raw.onData(data => {
305-
if (!telemetryIgnoredSequences.includes(data)) {
306-
inputUserChars += data.length;
307-
}
308-
inputUserSigint ||= data === '\x03';
309-
}));
295+
let inputUserChars = 0;
296+
let inputUserSigint = false;
297+
store.add(xterm.raw.onData(data => {
298+
if (!telemetryIgnoredSequences.includes(data)) {
299+
inputUserChars += data.length;
300+
}
301+
inputUserSigint ||= data === '\x03';
302+
}));
310303

304+
if (args.isBackground) {
305+
let outputAndIdle: { terminalExecutionIdleBeforeTimeout: boolean; output: string; pollDurationMs?: number; modelOutputEvalResponse?: string } | undefined = undefined;
311306
try {
312307
this._logService.debug(`RunInTerminalTool: Starting background execution \`${command}\``);
313308

@@ -372,40 +367,6 @@ export class RunInTerminalTool extends Disposable implements IToolImpl {
372367
});
373368
}
374369
} else {
375-
const store = new DisposableStore();
376-
let toolTerminal: IToolTerminal | undefined = this._sessionTerminalAssociations.get(chatSessionId);
377-
const isNewSession = !toolTerminal;
378-
if (toolTerminal) {
379-
this._logService.debug(`RunInTerminalTool: Using existing terminal with session ID \`${chatSessionId}\``);
380-
} else {
381-
this._logService.debug(`RunInTerminalTool: Creating terminal with session ID \`${chatSessionId}\``);
382-
toolTerminal = await this._instantiationService.createInstance(ToolTerminalCreator).createTerminal(token);
383-
this._sessionTerminalAssociations.set(chatSessionId, toolTerminal);
384-
if (token.isCancellationRequested) {
385-
toolTerminal.instance.dispose();
386-
throw new CancellationError();
387-
}
388-
await this._setupTerminalAssociation(toolTerminal, chatSessionId, termId, args.isBackground);
389-
}
390-
391-
this._terminalService.setActiveInstance(toolTerminal.instance);
392-
393-
const timingConnectMs = Date.now() - timingStart;
394-
395-
const xterm = await toolTerminal.instance.xtermReadyPromise;
396-
if (!xterm) {
397-
throw new Error('Instance was disposed before xterm.js was ready');
398-
}
399-
400-
let inputUserChars = 0;
401-
let inputUserSigint = false;
402-
store.add(xterm.raw.onData(data => {
403-
if (!telemetryIgnoredSequences.includes(data)) {
404-
inputUserChars += data.length;
405-
}
406-
inputUserSigint ||= data === '\x03';
407-
}));
408-
409370
let terminalResult = '';
410371

411372
let outputLineCount = -1;
@@ -484,6 +445,34 @@ export class RunInTerminalTool extends Disposable implements IToolImpl {
484445
}
485446
}
486447

448+
private async _initBackgroundTerminal(chatSessionId: string, termId: string, token: CancellationToken): Promise<IToolTerminal> {
449+
this._logService.debug(`RunInTerminalTool: Creating background terminal with ID=${termId}`);
450+
const toolTerminal = await this._instantiationService.createInstance(ToolTerminalCreator).createTerminal(token);
451+
this._sessionTerminalAssociations.set(chatSessionId, toolTerminal);
452+
if (token.isCancellationRequested) {
453+
toolTerminal.instance.dispose();
454+
throw new CancellationError();
455+
}
456+
await this._setupTerminalAssociation(toolTerminal, chatSessionId, termId, true);
457+
return toolTerminal;
458+
}
459+
460+
private async _initForegroundTerminal(chatSessionId: string, termId: string, token: CancellationToken): Promise<IToolTerminal> {
461+
const cachedTerminal = this._sessionTerminalAssociations.get(chatSessionId);
462+
if (cachedTerminal) {
463+
this._logService.debug(`RunInTerminalTool: Using cached foreground terminal with session ID \`${chatSessionId}\``);
464+
return cachedTerminal;
465+
}
466+
const toolTerminal = await this._instantiationService.createInstance(ToolTerminalCreator).createTerminal(token);
467+
this._sessionTerminalAssociations.set(chatSessionId, toolTerminal);
468+
if (token.isCancellationRequested) {
469+
toolTerminal.instance.dispose();
470+
throw new CancellationError();
471+
}
472+
await this._setupTerminalAssociation(toolTerminal, chatSessionId, termId, false);
473+
return toolTerminal;
474+
}
475+
487476
protected async _rewriteCommandIfNeeded(args: IRunInTerminalInputParams, instance: Pick<ITerminalInstance, 'getCwdResource'> | undefined, shell: string): Promise<string> {
488477
const commandLine = args.command;
489478
const os = await this._osBackend;

0 commit comments

Comments
 (0)