diff --git a/src/extension/agents/copilotcli/node/copilotCli.ts b/src/extension/agents/copilotcli/node/copilotCli.ts index 50ee8a9195..e854b2c9c6 100644 --- a/src/extension/agents/copilotcli/node/copilotCli.ts +++ b/src/extension/agents/copilotcli/node/copilotCli.ts @@ -23,6 +23,7 @@ const DEFAULT_CLI_MODEL = 'claude-sonnet-4'; export interface CopilotCLISessionOptions { addPermissionHandler(handler: SessionOptions['requestPermission']): IDisposable; toSessionOptions(): SessionOptions; + isolationEnabled: boolean; } export interface ICopilotCLIModels { @@ -171,7 +172,8 @@ export class CopilotCLISessionOptionsService implements ICopilotCLISessionOption } }); }, - toSessionOptions: () => allOptions + toSessionOptions: () => allOptions, + isolationEnabled: false } satisfies CopilotCLISessionOptions; } private async getWorkspaceFolderPath() { diff --git a/src/extension/agents/copilotcli/node/copilotcliSession.ts b/src/extension/agents/copilotcli/node/copilotcliSession.ts index 944d73a4e2..3df8b8936a 100644 --- a/src/extension/agents/copilotcli/node/copilotcliSession.ts +++ b/src/extension/agents/copilotcli/node/copilotcliSession.ts @@ -5,6 +5,7 @@ import type { Attachment, Session } from '@github/copilot/sdk'; import type * as vscode from 'vscode'; +import { IGitService } from '../../../../platform/git/common/gitService'; import { ILogService } from '../../../../platform/log/common/logService'; import { IWorkspaceService } from '../../../../platform/workspace/common/workspaceService'; import { CancellationToken } from '../../../../util/vs/base/common/cancellation'; @@ -67,6 +68,7 @@ export class CopilotCLISession extends DisposableStore implements ICopilotCLISes constructor( private readonly _options: CopilotCLISessionOptions, private readonly _sdkSession: Session, + @IGitService private readonly gitService: IGitService, @ILogService private readonly logService: ILogService, @IWorkspaceService private readonly workspaceService: IWorkspaceService, @ICopilotCLISessionOptionsService private readonly cliSessionOptions: ICopilotCLISessionOptionsService, @@ -199,6 +201,16 @@ export class CopilotCLISession extends DisposableStore implements ICopilotCLISes await this._sdkSession.send({ prompt, attachments, abortController }); this.logService.trace(`[CopilotCLISession] Invoking session (completed) ${this.sessionId}`); + if (this._options.isolationEnabled) { + // When isolation is enabled and we are using a git workspace, stage + // all changes in the working directory when the session is completed + const workingDirectory = this._options.toSessionOptions().workingDirectory; + if (workingDirectory) { + await this.gitService.add(Uri.file(workingDirectory), []); + this.logService.trace(`[CopilotCLISession] Staged all changes in working directory ${workingDirectory}`); + } + } + this._status = ChatSessionStatus.Completed; this._statusChange.fire(this._status); } catch (error) { diff --git a/src/extension/agents/copilotcli/node/copilotcliSessionService.ts b/src/extension/agents/copilotcli/node/copilotcliSessionService.ts index 893336e0a6..3d412727c6 100644 --- a/src/extension/agents/copilotcli/node/copilotcliSessionService.ts +++ b/src/extension/agents/copilotcli/node/copilotcliSessionService.ts @@ -46,7 +46,7 @@ export interface ICopilotCLISessionService { // Session wrapper tracking getSession(sessionId: string, model: string | undefined, workingDirectory: string | undefined, readonly: boolean, token: CancellationToken): Promise; - createSession(prompt: string, model: string | undefined, workingDirectory: string | undefined, token: CancellationToken): Promise; + createSession(prompt: string, model: string | undefined, workingDirectory: string | undefined, isolationEnabled: boolean | undefined, token: CancellationToken): Promise; } export const ICopilotCLISessionService = createServiceIdentifier('ICopilotCLISessionService'); @@ -183,13 +183,14 @@ export class CopilotCLISessionService extends Disposable implements ICopilotCLIS return { session, dispose: () => Promise.resolve() }; } - public async createSession(prompt: string, model: string | undefined, workingDirectory: string | undefined, token: CancellationToken): Promise { + public async createSession(prompt: string, model: string | undefined, workingDirectory: string | undefined, isolationEnabled: boolean | undefined, token: CancellationToken): Promise { const sessionDisposables = this._register(new DisposableStore()); try { const options = await raceCancellationError(this.optionsService.createOptions({ model: model as unknown as ModelMetadata['model'], workingDirectory }), token); + options.isolationEnabled = isolationEnabled === true; const sessionManager = await raceCancellationError(this.getSessionManager(), token); const sdkSession = await sessionManager.createSession(options.toSessionOptions()); const chatMessages = await sdkSession.getChatContextMessages(); diff --git a/src/extension/agents/copilotcli/node/test/copilotCliSessionService.spec.ts b/src/extension/agents/copilotcli/node/test/copilotCliSessionService.spec.ts index 1f18414372..85014b158d 100644 --- a/src/extension/agents/copilotcli/node/test/copilotCliSessionService.spec.ts +++ b/src/extension/agents/copilotcli/node/test/copilotCliSessionService.spec.ts @@ -12,7 +12,7 @@ import { DisposableStore, IDisposable } from '../../../../../util/vs/base/common import { IInstantiationService } from '../../../../../util/vs/platform/instantiation/common/instantiation'; import { CancellationTokenSource, ChatSessionStatus, EventEmitter } from '../../../../../vscodeTypes'; import { createExtensionUnitTestingServices } from '../../../../test/node/services'; -import { ICopilotCLISDK, ICopilotCLISessionOptionsService } from '../copilotCli'; +import { CopilotCLISessionOptions, ICopilotCLISDK, ICopilotCLISessionOptionsService } from '../copilotCli'; import { ICopilotCLISession } from '../copilotcliSession'; import { CopilotCLISessionService } from '../copilotcliSessionService'; @@ -84,8 +84,9 @@ describe('CopilotCLISessionService', () => { createOptions: vi.fn(async (opts: any) => { return { addPermissionHandler: () => ({ dispose() { /* noop */ } }), - toSessionOptions: () => ({ ...opts, requestPermission: async () => ({ kind: 'denied-interactively-by-user' }) }) - }; + toSessionOptions: () => ({ ...opts, requestPermission: async () => ({ kind: 'denied-interactively-by-user' }) }), + isolationEnabled: false + } satisfies CopilotCLISessionOptions; }), }; const sdk = { @@ -137,7 +138,7 @@ describe('CopilotCLISessionService', () => { describe('CopilotCLISessionService.createSession', () => { it('get session will return the same session created using createSession', async () => { - const session = await service.createSession(' ', 'gpt-test', '/tmp', createToken().token); + const session = await service.createSession(' ', 'gpt-test', '/tmp', false, createToken().token); expect(optionsService.createOptions).toHaveBeenCalledWith({ model: 'gpt-test', workingDirectory: '/tmp' }); const existingSession = await service.getSession(session.sessionId, undefined, undefined, false, createToken().token); @@ -145,7 +146,7 @@ describe('CopilotCLISessionService', () => { expect(existingSession).toBe(session); }); it('get session will return new once previous session is disposed', async () => { - const session = await service.createSession(' ', 'gpt-test', '/tmp', createToken().token); + const session = await service.createSession(' ', 'gpt-test', '/tmp', false, createToken().token); expect(optionsService.createOptions).toHaveBeenCalledWith({ model: 'gpt-test', workingDirectory: '/tmp' }); session.dispose(); @@ -166,7 +167,7 @@ describe('CopilotCLISessionService', () => { describe('CopilotCLISessionService.getAllSessions', () => { it('will not list created sessions', async () => { - await service.createSession(' ', 'gpt-test', '/tmp', createToken().token); + await service.createSession(' ', 'gpt-test', '/tmp', false, createToken().token); const s1 = new FakeSdkSession('s1', new Date(0)); s1.messages.push({ role: 'user', content: 'a'.repeat(100) }); @@ -186,7 +187,7 @@ describe('CopilotCLISessionService', () => { describe('CopilotCLISessionService.deleteSession', () => { it('disposes active wrapper, removes from manager and fires change event', async () => { - const session = await service.createSession('to delete', undefined, undefined, createToken().token); + const session = await service.createSession('to delete', undefined, undefined, undefined, createToken().token); const id = session!.sessionId; let fired = false; disposables.add(service.onDidChangeSessions(() => { fired = true; })); @@ -214,7 +215,7 @@ describe('CopilotCLISessionService', () => { describe('CopilotCLISessionService.auto disposal timeout', () => { it.skip('disposes session after completion timeout and aborts underlying sdk session', async () => { vi.useFakeTimers(); - const session = await service.createSession('will timeout', undefined, undefined, createToken().token); + const session = await service.createSession('will timeout', undefined, undefined, undefined, createToken().token); vi.advanceTimersByTime(31000); await Promise.resolve(); // allow any pending promises to run diff --git a/src/extension/agents/copilotcli/node/test/copilotcliSession.spec.ts b/src/extension/agents/copilotcli/node/test/copilotcliSession.spec.ts index e27bd354cf..0f0f9c9b8f 100644 --- a/src/extension/agents/copilotcli/node/test/copilotcliSession.spec.ts +++ b/src/extension/agents/copilotcli/node/test/copilotcliSession.spec.ts @@ -19,6 +19,7 @@ import { CopilotCLISessionOptions, ICopilotCLISessionOptionsService } from '../c import { CopilotCLISession } from '../copilotcliSession'; import { CopilotCLIToolNames } from '../copilotcliToolInvocationFormatter'; import { PermissionRequest } from '../permissionHelpers'; +import { IGitService } from '../../../../../platform/git/common/gitService'; // Minimal shapes for types coming from the Copilot SDK we interact with interface MockSdkEventHandler { (payload: unknown): void } @@ -77,7 +78,8 @@ function createSessionOptionsService() { permissionHandler = h; return { dispose: () => { permissionHandler = undefined; } }; }, - toSessionOptions: () => allOptions + toSessionOptions: () => allOptions, + isolationEnabled: false } satisfies CopilotCLISessionOptions; } }; @@ -104,6 +106,7 @@ describe('CopilotCLISession', () => { let sdkSession: MockSdkSession; let workspaceService: IWorkspaceService; let logger: ILogService; + let gitService: IGitService; let sessionOptionsService: ICopilotCLISessionOptionsService; let sessionOptions: CopilotCLISessionOptions; @@ -111,6 +114,7 @@ describe('CopilotCLISession', () => { const services = disposables.add(createExtensionUnitTestingServices()); const accessor = services.createTestingAccessor(); logger = accessor.get(ILogService); + gitService = accessor.get(IGitService); sdkSession = new MockSdkSession(); sessionOptionsService = createSessionOptionsService(); @@ -128,6 +132,7 @@ describe('CopilotCLISession', () => { return disposables.add(new CopilotCLISession( sessionOptions, sdkSession as unknown as Session, + gitService, logger, workspaceService, sessionOptionsService, diff --git a/src/extension/chatSessions/vscode-node/copilotCLIChatSessionsContribution.ts b/src/extension/chatSessions/vscode-node/copilotCLIChatSessionsContribution.ts index 3fca203bda..3eff63e5cf 100644 --- a/src/extension/chatSessions/vscode-node/copilotCLIChatSessionsContribution.ts +++ b/src/extension/chatSessions/vscode-node/copilotCLIChatSessionsContribution.ts @@ -135,6 +135,7 @@ export class CopilotCLIChatSessionItemProvider extends Disposable implements vsc private readonly worktreeManager: CopilotCLIWorktreeManager, @ICopilotCLISessionService private readonly copilotcliSessionService: ICopilotCLISessionService, @ICopilotCLITerminalIntegration private readonly terminalIntegration: ICopilotCLITerminalIntegration, + @IGitService private readonly gitService: IGitService, @IRunCommandExecutionService private readonly commandExecutionService: IRunCommandExecutionService ) { super(); @@ -154,7 +155,7 @@ export class CopilotCLIChatSessionItemProvider extends Disposable implements vsc public async provideChatSessionItems(token: vscode.CancellationToken): Promise { const sessions = await this.copilotcliSessionService.getAllSessions(token); - const diskSessions = sessions.map(session => this._toChatSessionItem(session)); + const diskSessions = await Promise.all(sessions.map(session => this._toChatSessionItem(session))); const count = diskSessions.length; this.commandExecutionService.executeCommand('setContext', 'github.copilot.chat.cliSessionsEmpty', count === 0); @@ -162,28 +163,39 @@ export class CopilotCLIChatSessionItemProvider extends Disposable implements vsc return diskSessions; } - private _toChatSessionItem(session: { id: string; label: string; timestamp: Date; status?: vscode.ChatSessionStatus }): vscode.ChatSessionItem { + private async _toChatSessionItem(session: { id: string; label: string; timestamp: Date; status?: vscode.ChatSessionStatus }): Promise { const resource = SessionIdForCLI.getResource(session.id); - const label = session.label || 'Copilot CLI'; - const worktreePath = this.worktreeManager.getWorktreeRelativePath(session.id); + const worktreePath = this.worktreeManager.getWorktreePath(session.id); + const worktreeRelativePath = this.worktreeManager.getWorktreeRelativePath(session.id); + + const label = session.label ?? 'Copilot CLI'; + const tooltipLines = [`Copilot CLI session: ${label}`]; let description: vscode.MarkdownString | undefined; - if (worktreePath) { - description = new vscode.MarkdownString(`$(git-merge) ${worktreePath}`); + let statistics: { files: number; insertions: number; deletions: number } | undefined; + + if (worktreePath && worktreeRelativePath) { + // Description + description = new vscode.MarkdownString(`$(list-tree) ${worktreeRelativePath}`); description.supportThemeIcons = true; + + // Tooltip + tooltipLines.push(`Worktree: ${worktreeRelativePath}`); + + // Statistics + statistics = await this.gitService.diffIndexWithHEADShortStats(Uri.file(worktreePath)); } - const tooltipLines = [`Copilot CLI session: ${label}`]; - if (worktreePath) { - tooltipLines.push(`Worktree: ${worktreePath}`); - } + const status = session.status ?? vscode.ChatSessionStatus.Completed; + return { resource, label, description, tooltip: tooltipLines.join('\n'), timing: { startTime: session.timestamp.getTime() }, + statistics, status - }; + } satisfies vscode.ChatSessionItem; } public async createCopilotCLITerminal(): Promise { @@ -380,8 +392,10 @@ export class CopilotCLIChatSessionParticipant { (this.worktreeManager.getIsolationPreference(id) ? await this.worktreeManager.createWorktree(stream) : undefined) : this.worktreeManager.getWorktreePath(id); + const isolationEnabled = this.worktreeManager.getIsolationPreference(id); + const session = chatSessionContext.isUntitled ? - await this.sessionService.createSession(prompt, modelId, workingDirectory, token) : + await this.sessionService.createSession(prompt, modelId, workingDirectory, isolationEnabled, token) : await this.sessionService.getSession(id, undefined, workingDirectory, false, token); if (!session) { @@ -478,7 +492,7 @@ export class CopilotCLIChatSessionParticipant { const history = context.chatSummary?.history ?? await this.summarizer.provideChatSummary(context, token); const requestPrompt = history ? `${prompt}\n**Summary**\n${history}` : prompt; - const session = await this.sessionService.createSession(requestPrompt, undefined, undefined, token); + const session = await this.sessionService.createSession(requestPrompt, undefined, undefined, undefined, token); await this.commandExecutionService.executeCommand('vscode.open', SessionIdForCLI.getResource(session.sessionId)); await this.commandExecutionService.executeCommand('workbench.action.chat.submit', { inputValue: requestPrompt }); diff --git a/src/extension/chatSessions/vscode-node/test/copilotCLIChatSessionParticipant.spec.ts b/src/extension/chatSessions/vscode-node/test/copilotCLIChatSessionParticipant.spec.ts index 8dda4ea4c6..d8013206c6 100644 --- a/src/extension/chatSessions/vscode-node/test/copilotCLIChatSessionParticipant.spec.ts +++ b/src/extension/chatSessions/vscode-node/test/copilotCLIChatSessionParticipant.spec.ts @@ -60,10 +60,10 @@ class FakeWorktreeManager extends mock() { override createWorktree = vi.fn(async () => undefined); override storeWorktreePath = vi.fn(async () => { }); override getWorktreePath = vi.fn((_id: string) => undefined); - override getIsolationPreference = vi.fn(() => true); + override getIsolationPreference = vi.fn(() => false); } -interface CreateSessionArgs { prompt: string | undefined; modelId: string | undefined; workingDirectory: string | undefined } +interface CreateSessionArgs { prompt: string | undefined; modelId: string | undefined; workingDirectory: string | undefined; isolationEnabled: boolean | undefined } class FakeCopilotCLISession implements ICopilotCLISession { public sessionId: string; @@ -88,8 +88,8 @@ class FakeCopilotCLISession implements ICopilotCLISession { class FakeSessionService extends DisposableStore implements ICopilotCLISessionService { _serviceBrand: undefined; public createdArgs: CreateSessionArgs | undefined; - public createSession = vi.fn(async (prompt: string | undefined, modelId: string | undefined, workingDirectory: string | undefined) => { - this.createdArgs = { prompt, modelId, workingDirectory }; + public createSession = vi.fn(async (prompt: string | undefined, modelId: string | undefined, workingDirectory: string | undefined, isolationEnabled: boolean | undefined) => { + this.createdArgs = { prompt, modelId, workingDirectory, isolationEnabled }; const s = new FakeCopilotCLISession('new-session-id'); return s as unknown as ICopilotCLISession; }); @@ -285,7 +285,7 @@ describe('CopilotCLIChatSessionParticipant.handleRequest', () => { await participant.createHandler()(request, context, stream, token); const expectedPrompt = 'Push this\n**Summary**\nsummary text'; - expect(sessionService.createSession).toHaveBeenCalledWith(expectedPrompt, undefined, undefined, token); + expect(sessionService.createSession).toHaveBeenCalledWith(expectedPrompt, undefined, undefined, undefined, token); expect(summarySpy).toHaveBeenCalledTimes(1); expect(execSpy).toHaveBeenCalledTimes(2); expect(execSpy.mock.calls[0]).toEqual(['vscode.open', expect.any(Object)]); @@ -304,7 +304,7 @@ describe('CopilotCLIChatSessionParticipant.handleRequest', () => { await participant.createHandler()(request, context, stream, token); const expectedPrompt = 'Push that\n**Summary**\nprecomputed history'; - expect(sessionService.createSession).toHaveBeenCalledWith(expectedPrompt, undefined, undefined, token); + expect(sessionService.createSession).toHaveBeenCalledWith(expectedPrompt, undefined, undefined, undefined, token); expect(summarySpy).not.toHaveBeenCalled(); expect(execSpy).toHaveBeenCalledTimes(2); expect(execSpy.mock.calls[0].at(0)).toBe('vscode.open'); diff --git a/src/extension/prompt/node/test/repoInfoTelemetry.spec.ts b/src/extension/prompt/node/test/repoInfoTelemetry.spec.ts index 1387117900..5ac3a22d78 100644 --- a/src/extension/prompt/node/test/repoInfoTelemetry.spec.ts +++ b/src/extension/prompt/node/test/repoInfoTelemetry.spec.ts @@ -82,8 +82,10 @@ suite('RepoInfoTelemetry', () => { log: vi.fn(), diffBetween: vi.fn(), diffWith: vi.fn(), + diffIndexWithHEADShortStats: vi.fn(), fetch: vi.fn(), getMergeBase: vi.fn(), + add: vi.fn(), dispose: vi.fn() }; services.define(IGitService, mockGitService); diff --git a/src/platform/git/common/gitService.ts b/src/platform/git/common/gitService.ts index b106aa5210..8b8413b66e 100644 --- a/src/platform/git/common/gitService.ts +++ b/src/platform/git/common/gitService.ts @@ -9,7 +9,7 @@ import { Event } from '../../../util/vs/base/common/event'; import { IObservable } from '../../../util/vs/base/common/observableInternal'; import { equalsIgnoreCase } from '../../../util/vs/base/common/strings'; import { URI } from '../../../util/vs/base/common/uri'; -import { Change, Commit, LogOptions } from '../vscode/git'; +import { Change, Commit, CommitShortStat, LogOptions } from '../vscode/git'; export interface RepoContext { readonly rootUri: URI; @@ -52,9 +52,11 @@ export interface IGitService extends IDisposable { getRepository(uri: URI): Promise; getRepositoryFetchUrls(uri: URI): Promise | undefined>; initialize(): Promise; + add(uri: URI, paths: string[]): Promise; log(uri: URI, options?: LogOptions): Promise; diffBetween(uri: URI, ref1: string, ref2: string): Promise; diffWith(uri: URI, ref: string): Promise; + diffIndexWithHEADShortStats(uri: URI): Promise; fetch(uri: URI, remote?: string, ref?: string, depth?: number): Promise; getMergeBase(uri: URI, ref1: string, ref2: string): Promise; } diff --git a/src/platform/git/vscode/git.d.ts b/src/platform/git/vscode/git.d.ts index 5c8f4f6c8a..a14173e3b0 100644 --- a/src/platform/git/vscode/git.d.ts +++ b/src/platform/git/vscode/git.d.ts @@ -233,10 +233,12 @@ export interface Repository { diff(cached?: boolean): Promise; diffWithHEAD(): Promise; diffWithHEAD(path: string): Promise; + diffWithHEADShortStats(path?: string): Promise; diffWith(ref: string): Promise; diffWith(ref: string, path: string): Promise; diffIndexWithHEAD(): Promise; diffIndexWithHEAD(path: string): Promise; + diffIndexWithHEADShortStats(path?: string): Promise; diffIndexWith(ref: string): Promise; diffIndexWith(ref: string, path: string): Promise; diffBlobs(object1: string, object2: string): Promise; diff --git a/src/platform/git/vscode/gitServiceImpl.ts b/src/platform/git/vscode/gitServiceImpl.ts index 3ea547d571..ecfa0bbb28 100644 --- a/src/platform/git/vscode/gitServiceImpl.ts +++ b/src/platform/git/vscode/gitServiceImpl.ts @@ -19,7 +19,7 @@ import { ILogService } from '../../log/common/logService'; import { IGitExtensionService } from '../common/gitExtensionService'; import { IGitService, RepoContext } from '../common/gitService'; import { parseGitRemotes } from '../common/utils'; -import { API, APIState, Change, Commit, LogOptions, Repository } from './git'; +import { API, APIState, Change, Commit, CommitShortStat, LogOptions, Repository } from './git'; export class GitServiceImpl extends Disposable implements IGitService { @@ -178,6 +178,12 @@ export class GitServiceImpl extends Disposable implements IGitService { } } + async add(uri: URI, paths: string[]): Promise { + const gitAPI = this.gitExtensionService.getExtensionApi(); + const repository = gitAPI?.getRepository(uri); + await repository?.add(paths); + } + async log(uri: vscode.Uri, options?: LogOptions): Promise { const gitAPI = this.gitExtensionService.getExtensionApi(); if (!gitAPI) { @@ -202,6 +208,12 @@ export class GitServiceImpl extends Disposable implements IGitService { return repository?.diffWith(ref); } + async diffIndexWithHEADShortStats(uri: URI): Promise { + const gitAPI = this.gitExtensionService.getExtensionApi(); + const repository = gitAPI?.getRepository(uri); + return await repository?.diffIndexWithHEADShortStats(); + } + async fetch(uri: vscode.Uri, remote?: string, ref?: string, depth?: number): Promise { const gitAPI = this.gitExtensionService.getExtensionApi(); const repository = gitAPI?.getRepository(uri); diff --git a/src/platform/test/node/simulationWorkspaceServices.ts b/src/platform/test/node/simulationWorkspaceServices.ts index 0423c2528c..be423964d2 100644 --- a/src/platform/test/node/simulationWorkspaceServices.ts +++ b/src/platform/test/node/simulationWorkspaceServices.ts @@ -28,7 +28,7 @@ import { IFileSystemService } from '../../filesystem/common/fileSystemService'; import { FileType, RelativePattern } from '../../filesystem/common/fileTypes'; import { NodeFileSystemService } from '../../filesystem/node/fileSystemServiceImpl'; import { IGitService, RepoContext } from '../../git/common/gitService'; -import { Change } from '../../git/vscode/git'; +import { Change, CommitShortStat } from '../../git/vscode/git'; import { AbstractLanguageDiagnosticsService } from '../../languages/common/languageDiagnosticsService'; import { ILanguageFeaturesService } from '../../languages/common/languageFeaturesService'; import { ILogService } from '../../log/common/logService'; @@ -741,6 +741,10 @@ export class TestingGitService implements IGitService { return undefined; } + async diffIndexWithHEADShortStats(uri: URI): Promise { + return undefined; + } + async fetch(uri: URI, remote?: string, ref?: string, depth?: number): Promise { return; } @@ -748,6 +752,10 @@ export class TestingGitService implements IGitService { async getMergeBase(uri: URI, ref1: string, ref2: string): Promise { return undefined; } + + async add(uri: URI, paths: string[]): Promise { + return; + } } export class TestingTerminalService extends Disposable implements ITerminalService { diff --git a/test/e2e/cli.stest.ts b/test/e2e/cli.stest.ts index 938e06e93f..85f2507052 100644 --- a/test/e2e/cli.stest.ts +++ b/test/e2e/cli.stest.ts @@ -67,7 +67,7 @@ const scenariosPath = path.join(__dirname, '..', 'test/scenarios/test-cli'); ssuite.skip({ title: '@cli', location: 'external' }, async (_) => { stest({ description: 'can start a session' }, testRunner(async ({ sessionService }, stream, disposables) => { - const session = await sessionService.createSession('What is 1+8?', undefined, undefined, CancellationToken.None); + const session = await sessionService.createSession('What is 1+8?', undefined, undefined, undefined, CancellationToken.None); disposables.add(session); disposables.add(session.attachStream(stream)); @@ -90,7 +90,7 @@ ssuite.skip({ title: '@cli', location: 'external' }, async (_) => { testRunner(async ({ sessionService }, stream, disposables) => { let sessionId = ''; { - const session = await sessionService.createSession('What is 1+8?', undefined, undefined, CancellationToken.None); + const session = await sessionService.createSession('What is 1+8?', undefined, undefined, undefined, CancellationToken.None); sessionId = session.sessionId; disposables.add(session); @@ -126,7 +126,7 @@ ssuite.skip({ title: '@cli', location: 'external' }, async (_) => { const workingDirectory = path.join(scenariosPath, 'wkspc1'); const file = path.join(workingDirectory, 'sample.js'); const prompt = `Explain the contents of the file '${path.basename(file)}'. There is no need to check for contents in the directory. This file exists on disc.`; - const session = await sessionService.createSession(prompt, undefined, workingDirectory, CancellationToken.None); + const session = await sessionService.createSession(prompt, undefined, workingDirectory, undefined, CancellationToken.None); disposables.add(session); disposables.add(session.attachStream(stream)); @@ -141,7 +141,7 @@ ssuite.skip({ title: '@cli', location: 'external' }, async (_) => { const workingDirectory = path.join(scenariosPath, 'wkspc1'); const externalFile = path.join(scenariosPath, 'wkspc2', 'foobar.js'); const prompt = `Explain the contents of the file '${path.basename(externalFile)}'. This file exists on disc but not in the current working directory.`; - const session = await sessionService.createSession(prompt, undefined, workingDirectory, CancellationToken.None); + const session = await sessionService.createSession(prompt, undefined, workingDirectory, undefined, CancellationToken.None); disposables.add(session); disposables.add(session.attachStream(stream)); let permissionRequested = false; @@ -174,7 +174,7 @@ ssuite.skip({ title: '@cli', location: 'external' }, async (_) => { promptResolver ); - const session = await sessionService.createSession(prompt, undefined, workingDirectory, CancellationToken.None); + const session = await sessionService.createSession(prompt, undefined, workingDirectory, undefined, CancellationToken.None); disposables.add(session); disposables.add(session.attachStream(stream));