-
Notifications
You must be signed in to change notification settings - Fork 39.3k
Expand file tree
/
Copy pathcopilotShellTools.test.ts
More file actions
89 lines (75 loc) · 4.68 KB
/
copilotShellTools.test.ts
File metadata and controls
89 lines (75 loc) · 4.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import assert from 'assert';
import { URI } from '../../../../base/common/uri.js';
import { Disposable, DisposableStore, type IDisposable } from '../../../../base/common/lifecycle.js';
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../base/test/common/utils.js';
import { IInstantiationService } from '../../../instantiation/common/instantiation.js';
import { InstantiationService } from '../../../instantiation/common/instantiationService.js';
import { ServiceCollection } from '../../../instantiation/common/serviceCollection.js';
import { ILogService, NullLogService } from '../../../log/common/log.js';
import type { ICreateTerminalParams } from '../../common/state/protocol/commands.js';
import type { ITerminalClaim, ITerminalInfo } from '../../common/state/protocol/state.js';
import { IAgentHostTerminalManager } from '../../node/agentHostTerminalManager.js';
import { ShellManager, prefixForHistorySuppression } from '../../node/copilot/copilotShellTools.js';
class TestAgentHostTerminalManager implements IAgentHostTerminalManager {
declare readonly _serviceBrand: undefined;
readonly created: { params: ICreateTerminalParams; options?: { shell?: string; preventShellHistory?: boolean; nonInteractive?: boolean } }[] = [];
async createTerminal(params: ICreateTerminalParams, options?: { shell?: string; preventShellHistory?: boolean; nonInteractive?: boolean }): Promise<void> {
this.created.push({ params, options });
}
writeInput(): void { }
onData(): IDisposable { return Disposable.None; }
onExit(): IDisposable { return Disposable.None; }
onClaimChanged(): IDisposable { return Disposable.None; }
onCommandFinished(): IDisposable { return Disposable.None; }
getContent(): string | undefined { return undefined; }
getClaim(): ITerminalClaim | undefined { return undefined; }
hasTerminal(): boolean { return false; }
getExitCode(): number | undefined { return undefined; }
supportsCommandDetection(): boolean { return false; }
disposeTerminal(): void { }
getTerminalInfos(): ITerminalInfo[] { return []; }
getTerminalState(): undefined { return undefined; }
}
suite('CopilotShellTools', () => {
const disposables = new DisposableStore();
teardown(() => disposables.clear());
ensureNoDisposablesAreLeakedInTestSuite();
test('uses session working directory for created shells', async () => {
const terminalManager = new TestAgentHostTerminalManager();
const services = new ServiceCollection();
services.set(ILogService, new NullLogService());
services.set(IAgentHostTerminalManager, terminalManager);
const instantiationService: IInstantiationService = disposables.add(new InstantiationService(services));
services.set(IInstantiationService, instantiationService);
const worktreePath = URI.file('/workspace/worktree').fsPath;
const explicitCwd = URI.file('/explicit/cwd').fsPath;
const shellManager = disposables.add(instantiationService.createInstance(ShellManager, URI.parse('copilot:/session-1'), URI.file(worktreePath)));
await shellManager.getOrCreateShell('bash', 'turn-1', 'tool-1');
await shellManager.getOrCreateShell('bash', 'turn-2', 'tool-2', explicitCwd);
assert.deepStrictEqual(terminalManager.created.map(c => c.params.cwd), [
worktreePath,
explicitCwd,
]);
});
test('opts every managed shell into shell-history suppression and non-interactive mode', async () => {
const terminalManager = new TestAgentHostTerminalManager();
const services = new ServiceCollection();
services.set(ILogService, new NullLogService());
services.set(IAgentHostTerminalManager, terminalManager);
const instantiationService: IInstantiationService = disposables.add(new InstantiationService(services));
services.set(IInstantiationService, instantiationService);
const shellManager = disposables.add(instantiationService.createInstance(ShellManager, URI.parse('copilot:/session-1'), undefined));
await shellManager.getOrCreateShell('bash', 'turn-1', 'tool-1');
assert.strictEqual(terminalManager.created.length, 1);
assert.strictEqual(terminalManager.created[0].options?.preventShellHistory, true);
assert.strictEqual(terminalManager.created[0].options?.nonInteractive, true);
});
test('prefixForHistorySuppression prepends a space for POSIX shells, no-op for PowerShell', () => {
assert.strictEqual(prefixForHistorySuppression('bash'), ' ');
assert.strictEqual(prefixForHistorySuppression('powershell'), '');
});
});