Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/chatSessions/copilotcli/vscode-node/test/chatSessionInitializer.spec.ts
13406 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import type { SweCustomAgent } from '@github/copilot/sdk';
7
import { beforeEach, describe, expect, it, vi } from 'vitest';
8
import type * as vscode from 'vscode';
9
import { IConfigurationService } from '../../../../../platform/configuration/common/configurationService';
10
import { ILogService } from '../../../../../platform/log/common/logService';
11
import { IPromptsService } from '../../../../../platform/promptFiles/common/promptsService';
12
import { IWorkspaceService, NullWorkspaceService } from '../../../../../platform/workspace/common/workspaceService';
13
import { mock } from '../../../../../util/common/test/simpleMock';
14
import { CancellationToken } from '../../../../../util/vs/base/common/cancellation';
15
import { DisposableStore, IReference } from '../../../../../util/vs/base/common/lifecycle';
16
import { URI } from '../../../../../util/vs/base/common/uri';
17
import { IChatSessionMetadataStore } from '../../../common/chatSessionMetadataStore';
18
import { IChatSessionWorkspaceFolderService } from '../../../common/chatSessionWorkspaceFolderService';
19
import { IChatSessionWorktreeService } from '../../../common/chatSessionWorktreeService';
20
import { FolderRepositoryInfo, IFolderRepositoryManager, IsolationMode } from '../../../common/folderRepositoryManager';
21
import { IWorkspaceInfo } from '../../../common/workspaceInfo';
22
import { ICopilotCLIAgents, ICopilotCLIModels } from '../../../copilotcli/node/copilotCli';
23
import { ICopilotCLISession } from '../../../copilotcli/node/copilotcliSession';
24
import { ICopilotCLISessionService } from '../../../copilotcli/node/copilotcliSessionService';
25
import { CopilotCLIChatSessionInitializer } from '../copilotCLIChatSessionInitializer';
26
27
// ─── Test Helpers ────────────────────────────────────────────────
28
29
class TestSessionService extends mock<ICopilotCLISessionService>() {
30
declare readonly _serviceBrand: undefined;
31
override isNewSessionId = vi.fn(() => true);
32
override createSession = vi.fn(async (): Promise<IReference<ICopilotCLISession>> => ({
33
object: makeSessionObject(),
34
dispose: vi.fn(),
35
}));
36
override getSession = vi.fn(async (): Promise<IReference<ICopilotCLISession> | undefined> => ({
37
object: makeSessionObject(),
38
dispose: vi.fn(),
39
}));
40
}
41
42
class TestFolderRepositoryManager extends mock<IFolderRepositoryManager>() {
43
declare readonly _serviceBrand: undefined;
44
override initializeFolderRepository = vi.fn(async (): Promise<FolderRepositoryInfo> => ({
45
folder: URI.file('/workspace') as unknown as vscode.Uri,
46
repository: undefined,
47
repositoryProperties: undefined,
48
worktree: undefined,
49
worktreeProperties: undefined,
50
trusted: true,
51
}));
52
override getFolderRepository = vi.fn(async (): Promise<FolderRepositoryInfo> => ({
53
folder: URI.file('/workspace') as unknown as vscode.Uri,
54
repository: undefined,
55
repositoryProperties: undefined,
56
worktree: undefined,
57
worktreeProperties: undefined,
58
trusted: true,
59
}));
60
}
61
62
class TestWorktreeService extends mock<IChatSessionWorktreeService>() {
63
declare readonly _serviceBrand: undefined;
64
override setWorktreeProperties = vi.fn(async () => { });
65
}
66
67
class TestWorkspaceFolderService extends mock<IChatSessionWorkspaceFolderService>() {
68
declare readonly _serviceBrand: undefined;
69
override trackSessionWorkspaceFolder = vi.fn(async () => { });
70
}
71
72
class TestModels extends mock<ICopilotCLIModels>() {
73
declare readonly _serviceBrand: undefined;
74
override resolveModel = vi.fn(async (id: string) => id === 'known-model' ? 'resolved-model' : undefined);
75
override getDefaultModel = vi.fn(async () => 'default-model');
76
}
77
78
class TestAgents extends mock<ICopilotCLIAgents>() {
79
declare readonly _serviceBrand: undefined;
80
override resolveAgent = vi.fn(async (): Promise<SweCustomAgent | undefined> => undefined);
81
}
82
83
class TestPromptsService extends mock<IPromptsService>() {
84
declare readonly _serviceBrand: undefined;
85
override parseFile = vi.fn(async () => ({ uri: URI.file('/test.prompt'), header: undefined, body: undefined }));
86
}
87
88
class TestMetadataStore extends mock<IChatSessionMetadataStore>() {
89
declare readonly _serviceBrand: undefined;
90
override updateRequestDetails = vi.fn(async () => { });
91
}
92
93
class TestConfigurationService extends mock<IConfigurationService>() {
94
declare readonly _serviceBrand: undefined;
95
override getConfig = vi.fn(() => undefined as any);
96
}
97
98
class TestLogService extends mock<ILogService>() {
99
declare readonly _serviceBrand: undefined;
100
override trace = vi.fn();
101
override debug = vi.fn();
102
override info = vi.fn();
103
override error = vi.fn();
104
}
105
106
function makeSessionObject(overrides?: Partial<ICopilotCLISession>): ICopilotCLISession {
107
return {
108
sessionId: 'test-session-id',
109
workspace: {
110
folder: URI.file('/workspace') as unknown as vscode.Uri,
111
repository: undefined,
112
repositoryProperties: undefined,
113
worktree: undefined,
114
worktreeProperties: undefined,
115
},
116
attachStream: vi.fn(() => ({ dispose: vi.fn() })),
117
setPermissionLevel: vi.fn(),
118
dispose: vi.fn(),
119
...overrides,
120
} as unknown as ICopilotCLISession;
121
}
122
123
function makeRequest(overrides?: Partial<vscode.ChatRequest>): vscode.ChatRequest {
124
return {
125
id: 'request-1',
126
prompt: 'hello',
127
model: { id: 'known-model' },
128
references: [],
129
tools: [],
130
toolInvocationToken: {} as vscode.ChatParticipantToolToken,
131
permissionLevel: 'full',
132
modeInstructions2: undefined,
133
...overrides,
134
} as unknown as vscode.ChatRequest;
135
}
136
137
function makeStream(): vscode.ChatResponseStream {
138
return {
139
warning: vi.fn(),
140
markdown: vi.fn(),
141
} as unknown as vscode.ChatResponseStream;
142
}
143
144
function makeChatResource(sessionId: string = 'untitled:new-session'): vscode.Uri {
145
return URI.from({ scheme: 'copilotcli', path: `/${sessionId}` }) as unknown as vscode.Uri;
146
}
147
148
function createInitializer(overrides?: {
149
sessionService?: TestSessionService;
150
folderRepoManager?: TestFolderRepositoryManager;
151
worktreeService?: TestWorktreeService;
152
workspaceFolderService?: TestWorkspaceFolderService;
153
workspaceService?: IWorkspaceService;
154
models?: TestModels;
155
agents?: TestAgents;
156
promptsService?: TestPromptsService;
157
metadataStore?: TestMetadataStore;
158
logService?: TestLogService;
159
configurationService?: TestConfigurationService;
160
}) {
161
const sessionService = overrides?.sessionService ?? new TestSessionService();
162
const folderRepoManager = overrides?.folderRepoManager ?? new TestFolderRepositoryManager();
163
const worktreeService = overrides?.worktreeService ?? new TestWorktreeService();
164
const workspaceFolderService = overrides?.workspaceFolderService ?? new TestWorkspaceFolderService();
165
const workspaceService = overrides?.workspaceService ?? new NullWorkspaceService([URI.file('/workspace')]);
166
const models = overrides?.models ?? new TestModels();
167
const agents = overrides?.agents ?? new TestAgents();
168
const promptsService = overrides?.promptsService ?? new TestPromptsService();
169
const metadataStore = overrides?.metadataStore ?? new TestMetadataStore();
170
const logService = overrides?.logService ?? new TestLogService();
171
const configurationService = overrides?.configurationService ?? new TestConfigurationService();
172
173
const initializer = new CopilotCLIChatSessionInitializer(
174
sessionService,
175
folderRepoManager,
176
workspaceService,
177
models,
178
agents,
179
promptsService,
180
logService,
181
configurationService,
182
);
183
184
return { initializer, sessionService, folderRepoManager, worktreeService, workspaceFolderService, models, agents, promptsService, metadataStore, logService, configurationService };
185
}
186
187
// ─── Tests ───────────────────────────────────────────────────────
188
189
describe('ChatSessionInitializer', () => {
190
beforeEach(() => {
191
vi.restoreAllMocks();
192
});
193
194
describe('resolveModelId', () => {
195
it('returns resolved model from request.model.id', async () => {
196
const { initializer } = createInitializer();
197
const request = makeRequest({ model: { id: 'known-model' } } as Partial<vscode.ChatRequest>);
198
const result = await initializer.resolveModel(request, CancellationToken.None);
199
expect(result).toEqual(expect.objectContaining({ model: 'resolved-model' }));
200
});
201
202
it('falls back to default model when request model is not resolvable', async () => {
203
const { initializer } = createInitializer();
204
const request = makeRequest({ model: { id: 'unknown-model' } } as Partial<vscode.ChatRequest>);
205
const result = await initializer.resolveModel(request, CancellationToken.None);
206
expect(result).toEqual(expect.objectContaining({ model: 'default-model' }));
207
});
208
209
it('returns default model when request is undefined', async () => {
210
const { initializer } = createInitializer();
211
const result = await initializer.resolveModel(undefined, CancellationToken.None);
212
expect(result).toEqual(expect.objectContaining({ model: 'default-model' }));
213
});
214
215
it('returns default model when request has no model', async () => {
216
const { initializer } = createInitializer();
217
const request = makeRequest({ model: undefined } as Partial<vscode.ChatRequest>);
218
const result = await initializer.resolveModel(request, CancellationToken.None);
219
expect(result).toEqual(expect.objectContaining({ model: 'default-model' }));
220
});
221
});
222
223
describe('resolveAgent', () => {
224
it('returns undefined when request has no modeInstructions2', async () => {
225
const { initializer } = createInitializer();
226
const request = makeRequest({ modeInstructions2: undefined } as Partial<vscode.ChatRequest>);
227
const result = await initializer.resolveAgent(request, CancellationToken.None);
228
expect(result).toBeUndefined();
229
});
230
231
it('returns undefined when request is undefined', async () => {
232
const { initializer } = createInitializer();
233
const result = await initializer.resolveAgent(undefined, CancellationToken.None);
234
expect(result).toBeUndefined();
235
});
236
237
it('resolves agent by URI when modeInstructions2 has uri', async () => {
238
const agents = new TestAgents();
239
const fakeAgent = { name: 'test-agent' } as SweCustomAgent;
240
agents.resolveAgent.mockResolvedValue(fakeAgent);
241
const { initializer } = createInitializer({ agents });
242
243
const request = makeRequest({
244
modeInstructions2: {
245
uri: URI.file('/agent.md') as unknown as vscode.Uri,
246
name: 'test-agent',
247
content: '',
248
toolReferences: [],
249
},
250
} as Partial<vscode.ChatRequest>);
251
252
const result = await initializer.resolveAgent(request, CancellationToken.None);
253
expect(result).toBe(fakeAgent);
254
expect(agents.resolveAgent).toHaveBeenCalledWith(URI.file('/agent.md').toString());
255
});
256
257
it('resolves agent by name when modeInstructions2 has no uri', async () => {
258
const agents = new TestAgents();
259
const fakeAgent = { name: 'test-agent' } as SweCustomAgent;
260
agents.resolveAgent.mockResolvedValue(fakeAgent);
261
const { initializer } = createInitializer({ agents });
262
263
const request = makeRequest({
264
modeInstructions2: {
265
uri: undefined,
266
name: 'test-agent',
267
content: '',
268
toolReferences: [],
269
},
270
} as Partial<vscode.ChatRequest>);
271
272
const result = await initializer.resolveAgent(request, CancellationToken.None);
273
expect(result).toBe(fakeAgent);
274
expect(agents.resolveAgent).toHaveBeenCalledWith('test-agent');
275
});
276
277
it('overrides agent tools when modeInstructions2 provides toolReferences', async () => {
278
const agents = new TestAgents();
279
const fakeAgent = { name: 'test-agent', tools: [] } as unknown as SweCustomAgent;
280
agents.resolveAgent.mockResolvedValue(fakeAgent);
281
const { initializer } = createInitializer({ agents });
282
283
const request = makeRequest({
284
modeInstructions2: {
285
uri: undefined,
286
name: 'test-agent',
287
content: '',
288
toolReferences: [{ name: 'tool-a' }, { name: 'tool-b' }],
289
},
290
} as Partial<vscode.ChatRequest>);
291
292
const result = await initializer.resolveAgent(request, CancellationToken.None);
293
expect(result!.tools).toEqual(['tool-a', 'tool-b']);
294
});
295
296
it('returns undefined when agent cannot be resolved', async () => {
297
const agents = new TestAgents();
298
agents.resolveAgent.mockResolvedValue(undefined);
299
const { initializer } = createInitializer({ agents });
300
301
const request = makeRequest({
302
modeInstructions2: {
303
uri: undefined,
304
name: 'unknown-agent',
305
content: '',
306
toolReferences: [],
307
},
308
} as Partial<vscode.ChatRequest>);
309
310
const result = await initializer.resolveAgent(request, CancellationToken.None);
311
expect(result).toBeUndefined();
312
});
313
});
314
315
describe('initializeWorkingDirectory', () => {
316
it('initializes folder for new session with chat session context', async () => {
317
const sessionService = new TestSessionService();
318
sessionService.isNewSessionId.mockReturnValue(true);
319
const { initializer, folderRepoManager } = createInitializer({ sessionService });
320
321
const result = await initializer.initializeWorkingDirectory(
322
makeChatResource('untitled:new'), { stream: makeStream() },
323
{} as vscode.ChatParticipantToolToken, CancellationToken.None
324
);
325
326
expect(result.cancelled).toBe(false);
327
expect(result.trusted).toBe(true);
328
expect(result.workspaceInfo.folder).toBeDefined();
329
expect(folderRepoManager.initializeFolderRepository).toHaveBeenCalled();
330
});
331
332
it('gets existing folder for non-new session', async () => {
333
const sessionService = new TestSessionService();
334
sessionService.isNewSessionId.mockReturnValue(false);
335
const { initializer, folderRepoManager } = createInitializer({ sessionService });
336
337
const result = await initializer.initializeWorkingDirectory(
338
makeChatResource('existing-session'), { stream: makeStream() },
339
{} as vscode.ChatParticipantToolToken, CancellationToken.None
340
);
341
342
expect(result.cancelled).toBe(false);
343
expect(folderRepoManager.getFolderRepository).toHaveBeenCalled();
344
});
345
346
it('initializes with active repository when no chat session context', async () => {
347
const { initializer, folderRepoManager } = createInitializer();
348
349
const result = await initializer.initializeWorkingDirectory(
350
undefined, { stream: makeStream() },
351
{} as vscode.ChatParticipantToolToken, CancellationToken.None
352
);
353
354
expect(result.cancelled).toBe(false);
355
expect(folderRepoManager.initializeFolderRepository).toHaveBeenCalledWith(
356
undefined, expect.anything(), expect.anything()
357
);
358
});
359
360
it('returns cancelled when trust is denied', async () => {
361
const folderRepoManager = new TestFolderRepositoryManager();
362
folderRepoManager.initializeFolderRepository.mockResolvedValue({
363
folder: URI.file('/workspace') as unknown as vscode.Uri,
364
repository: undefined,
365
repositoryProperties: undefined,
366
worktree: undefined,
367
worktreeProperties: undefined,
368
trusted: false,
369
});
370
const { initializer } = createInitializer({ folderRepoManager });
371
372
const result = await initializer.initializeWorkingDirectory(
373
undefined, { stream: makeStream() },
374
{} as vscode.ChatParticipantToolToken, CancellationToken.None
375
);
376
377
expect(result.cancelled).toBe(true);
378
expect(result.trusted).toBe(false);
379
});
380
381
it('returns cancelled when user cancels', async () => {
382
const folderRepoManager = new TestFolderRepositoryManager();
383
folderRepoManager.initializeFolderRepository.mockResolvedValue({
384
folder: undefined,
385
repository: undefined,
386
repositoryProperties: undefined,
387
worktree: undefined,
388
worktreeProperties: undefined,
389
trusted: true,
390
cancelled: true,
391
});
392
const { initializer } = createInitializer({ folderRepoManager });
393
394
const result = await initializer.initializeWorkingDirectory(
395
undefined, { stream: makeStream() },
396
{} as vscode.ChatParticipantToolToken, CancellationToken.None
397
);
398
399
expect(result.cancelled).toBe(true);
400
expect(result.trusted).toBe(true);
401
});
402
403
it('parses session options from chat session context', async () => {
404
const sessionService = new TestSessionService();
405
sessionService.isNewSessionId.mockReturnValue(true);
406
const { initializer, folderRepoManager } = createInitializer({ sessionService });
407
408
await initializer.initializeWorkingDirectory(
409
makeChatResource('untitled:new'),
410
{
411
folder: URI.file('/selected-repo') as unknown as vscode.Uri,
412
branch: 'feature-branch',
413
isolation: IsolationMode.Worktree,
414
stream: makeStream(),
415
},
416
{} as vscode.ChatParticipantToolToken, CancellationToken.None
417
);
418
419
expect(folderRepoManager.initializeFolderRepository).toHaveBeenCalledWith(
420
expect.any(String),
421
expect.objectContaining({
422
branch: 'feature-branch',
423
isolation: IsolationMode.Worktree,
424
}),
425
expect.anything()
426
);
427
});
428
});
429
430
describe('getOrCreateSession', () => {
431
it('creates new session and attaches stream', async () => {
432
const { initializer, sessionService } = createInitializer();
433
sessionService.isNewSessionId.mockReturnValue(true);
434
const disposables = new DisposableStore();
435
const stream = makeStream();
436
437
const result = await initializer.getOrCreateSession(
438
makeRequest(), makeChatResource(), { stream },
439
disposables, CancellationToken.None
440
);
441
442
expect(result.session).toBeDefined();
443
expect(result.isNewSession).toBe(true);
444
expect(result.model).toEqual(expect.objectContaining({ model: 'resolved-model' }));
445
expect(result.trusted).toBe(true);
446
expect(sessionService.createSession).toHaveBeenCalled();
447
expect(result.session!.object.attachStream).toHaveBeenCalledWith(stream);
448
expect(result.session!.object.setPermissionLevel).toHaveBeenCalled();
449
disposables.dispose();
450
});
451
452
it('gets existing session for non-new session ID', async () => {
453
const { initializer, sessionService } = createInitializer();
454
sessionService.isNewSessionId.mockReturnValue(false);
455
const disposables = new DisposableStore();
456
457
const result = await initializer.getOrCreateSession(
458
makeRequest(), makeChatResource('existing-session'), { stream: makeStream() },
459
disposables, CancellationToken.None
460
);
461
462
expect(result.session).toBeDefined();
463
expect(result.isNewSession).toBe(false);
464
expect(sessionService.getSession).toHaveBeenCalled();
465
expect(sessionService.createSession).not.toHaveBeenCalled();
466
disposables.dispose();
467
});
468
469
it('returns undefined session when working directory init is cancelled', async () => {
470
const folderRepoManager = new TestFolderRepositoryManager();
471
folderRepoManager.initializeFolderRepository.mockResolvedValue({
472
folder: undefined, repository: undefined, repositoryProperties: undefined,
473
worktree: undefined, worktreeProperties: undefined,
474
trusted: false,
475
});
476
const { initializer } = createInitializer({ folderRepoManager });
477
const disposables = new DisposableStore();
478
479
const result = await initializer.getOrCreateSession(
480
makeRequest(), makeChatResource(), { stream: makeStream() },
481
disposables, CancellationToken.None
482
);
483
484
expect(result.session).toBeUndefined();
485
expect(result.trusted).toBe(false);
486
disposables.dispose();
487
});
488
489
it('returns undefined session when session service returns undefined', async () => {
490
const sessionService = new TestSessionService();
491
sessionService.isNewSessionId.mockReturnValue(false);
492
sessionService.getSession.mockResolvedValue(undefined);
493
const { initializer } = createInitializer({ sessionService });
494
const disposables = new DisposableStore();
495
const stream = makeStream();
496
497
const result = await initializer.getOrCreateSession(
498
makeRequest(), makeChatResource('missing'), { stream },
499
disposables, CancellationToken.None
500
);
501
502
expect(result.session).toBeUndefined();
503
expect(stream.warning).toHaveBeenCalled();
504
disposables.dispose();
505
});
506
507
it('does not set worktree properties (moved to startRequest)', async () => {
508
const sessionService = new TestSessionService();
509
sessionService.isNewSessionId.mockReturnValue(true);
510
const folderRepoManager = new TestFolderRepositoryManager();
511
folderRepoManager.initializeFolderRepository.mockResolvedValue({
512
folder: URI.file('/workspace') as unknown as vscode.Uri,
513
repository: URI.file('/repo') as unknown as vscode.Uri,
514
repositoryProperties: undefined,
515
worktree: URI.file('/worktree') as unknown as vscode.Uri,
516
worktreeProperties: {
517
version: 2,
518
baseCommit: 'abc',
519
baseBranchName: 'main',
520
branchName: 'copilot/test',
521
repositoryPath: '/repo',
522
worktreePath: '/worktree',
523
},
524
trusted: true,
525
});
526
const { initializer, worktreeService } = createInitializer({ sessionService, folderRepoManager });
527
const disposables = new DisposableStore();
528
529
await initializer.getOrCreateSession(
530
makeRequest(), makeChatResource(), { stream: makeStream() },
531
disposables, CancellationToken.None
532
);
533
534
expect(worktreeService.setWorktreeProperties).not.toHaveBeenCalled();
535
disposables.dispose();
536
});
537
538
it('does not track workspace folder (moved to startRequest)', async () => {
539
const sessionService = new TestSessionService();
540
sessionService.isNewSessionId.mockReturnValue(true);
541
const { initializer, workspaceFolderService } = createInitializer({ sessionService });
542
const disposables = new DisposableStore();
543
544
await initializer.getOrCreateSession(
545
makeRequest(), makeChatResource(), { stream: makeStream() },
546
disposables, CancellationToken.None
547
);
548
549
expect(workspaceFolderService.trackSessionWorkspaceFolder).not.toHaveBeenCalled();
550
disposables.dispose();
551
});
552
553
it('does not record request metadata (moved to startRequest)', async () => {
554
const { initializer, metadataStore } = createInitializer();
555
const disposables = new DisposableStore();
556
557
await initializer.getOrCreateSession(
558
makeRequest(), makeChatResource(), { stream: makeStream() },
559
disposables, CancellationToken.None
560
);
561
562
expect(metadataStore.updateRequestDetails).not.toHaveBeenCalled();
563
disposables.dispose();
564
});
565
});
566
567
describe('createDelegatedSession', () => {
568
it('creates session and resolves model', async () => {
569
const { initializer, sessionService } = createInitializer();
570
const workspace: IWorkspaceInfo = {
571
folder: URI.file('/workspace') as unknown as vscode.Uri,
572
repository: undefined,
573
repositoryProperties: undefined,
574
worktree: undefined,
575
worktreeProperties: undefined,
576
};
577
578
const session = await initializer.createDelegatedSession(
579
makeRequest(), workspace, { mcpServerMappings: new Map() },
580
CancellationToken.None
581
);
582
583
expect(session).toBeDefined();
584
expect(sessionService.createSession).toHaveBeenCalled();
585
});
586
587
it('does not set worktree properties or track workspace folder (moved to startRequest)', async () => {
588
const { initializer, worktreeService, workspaceFolderService, metadataStore } = createInitializer();
589
const workspace: IWorkspaceInfo = {
590
folder: URI.file('/workspace') as unknown as vscode.Uri,
591
repository: URI.file('/repo') as unknown as vscode.Uri,
592
repositoryProperties: undefined,
593
worktree: URI.file('/worktree') as unknown as vscode.Uri,
594
worktreeProperties: {
595
version: 2,
596
baseCommit: 'abc',
597
baseBranchName: 'main',
598
branchName: 'copilot/test',
599
repositoryPath: '/repo',
600
worktreePath: '/worktree',
601
},
602
};
603
604
await initializer.createDelegatedSession(
605
makeRequest(), workspace, { mcpServerMappings: new Map() },
606
CancellationToken.None
607
);
608
609
expect(worktreeService.setWorktreeProperties).not.toHaveBeenCalled();
610
expect(workspaceFolderService.trackSessionWorkspaceFolder).not.toHaveBeenCalled();
611
expect(metadataStore.updateRequestDetails).not.toHaveBeenCalled();
612
});
613
});
614
});
615
616