Path: blob/main/src/vs/platform/agentHost/test/node/copilotShellTools.test.ts
13399 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import assert from 'assert';6import { URI } from '../../../../base/common/uri.js';7import { Disposable, DisposableStore, type IDisposable } from '../../../../base/common/lifecycle.js';8import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../base/test/common/utils.js';9import { IInstantiationService } from '../../../instantiation/common/instantiation.js';10import { InstantiationService } from '../../../instantiation/common/instantiationService.js';11import { ServiceCollection } from '../../../instantiation/common/serviceCollection.js';12import { ILogService, NullLogService } from '../../../log/common/log.js';13import type { CreateTerminalParams } from '../../common/state/protocol/commands.js';14import type { TerminalClaim, TerminalInfo } from '../../common/state/protocol/state.js';15import { IAgentHostTerminalManager } from '../../node/agentHostTerminalManager.js';16import { ShellManager, prefixForHistorySuppression } from '../../node/copilot/copilotShellTools.js';1718class TestAgentHostTerminalManager implements IAgentHostTerminalManager {19declare readonly _serviceBrand: undefined;2021readonly created: { params: CreateTerminalParams; options?: { shell?: string; preventShellHistory?: boolean; nonInteractive?: boolean } }[] = [];2223async createTerminal(params: CreateTerminalParams, options?: { shell?: string; preventShellHistory?: boolean; nonInteractive?: boolean }): Promise<void> {24this.created.push({ params, options });25}26writeInput(): void { }27onData(): IDisposable { return Disposable.None; }28onExit(): IDisposable { return Disposable.None; }29onClaimChanged(): IDisposable { return Disposable.None; }30onCommandFinished(): IDisposable { return Disposable.None; }31getContent(): string | undefined { return undefined; }32getClaim(): TerminalClaim | undefined { return undefined; }33hasTerminal(): boolean { return false; }34getExitCode(): number | undefined { return undefined; }35supportsCommandDetection(): boolean { return false; }36disposeTerminal(): void { }37getTerminalInfos(): TerminalInfo[] { return []; }38getTerminalState(): undefined { return undefined; }39}4041suite('CopilotShellTools', () => {4243const disposables = new DisposableStore();4445teardown(() => disposables.clear());46ensureNoDisposablesAreLeakedInTestSuite();4748test('uses session working directory for created shells', async () => {49const terminalManager = new TestAgentHostTerminalManager();50const services = new ServiceCollection();51services.set(ILogService, new NullLogService());52services.set(IAgentHostTerminalManager, terminalManager);53const instantiationService: IInstantiationService = disposables.add(new InstantiationService(services));54services.set(IInstantiationService, instantiationService);55const worktreePath = URI.file('/workspace/worktree').fsPath;56const explicitCwd = URI.file('/explicit/cwd').fsPath;57const shellManager = disposables.add(instantiationService.createInstance(ShellManager, URI.parse('copilot:/session-1'), URI.file(worktreePath)));5859await shellManager.getOrCreateShell('bash', 'turn-1', 'tool-1');60await shellManager.getOrCreateShell('bash', 'turn-2', 'tool-2', explicitCwd);6162assert.deepStrictEqual(terminalManager.created.map(c => c.params.cwd), [63worktreePath,64explicitCwd,65]);66});6768test('opts every managed shell into shell-history suppression and non-interactive mode', async () => {69const terminalManager = new TestAgentHostTerminalManager();70const services = new ServiceCollection();71services.set(ILogService, new NullLogService());72services.set(IAgentHostTerminalManager, terminalManager);73const instantiationService: IInstantiationService = disposables.add(new InstantiationService(services));74services.set(IInstantiationService, instantiationService);75const shellManager = disposables.add(instantiationService.createInstance(ShellManager, URI.parse('copilot:/session-1'), undefined));7677await shellManager.getOrCreateShell('bash', 'turn-1', 'tool-1');7879assert.strictEqual(terminalManager.created.length, 1);80assert.strictEqual(terminalManager.created[0].options?.preventShellHistory, true);81assert.strictEqual(terminalManager.created[0].options?.nonInteractive, true);82});8384test('prefixForHistorySuppression prepends a space for POSIX shells, no-op for PowerShell', () => {85assert.strictEqual(prefixForHistorySuppression('bash'), ' ');86assert.strictEqual(prefixForHistorySuppression('powershell'), '');87});88});899091