Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/chatSessions/vscode-node/chatSessions.ts
13399 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 * as l10n from '@vscode/l10n';
7
import * as vscode from 'vscode';
8
import { ConfigKey, IConfigurationService } from '../../../platform/configuration/common/configurationService';
9
import { IEnvService, INativeEnvService } from '../../../platform/env/common/envService';
10
import { IFileSystemService } from '../../../platform/filesystem/common/fileSystemService';
11
import { IGitExtensionService } from '../../../platform/git/common/gitExtensionService';
12
import { IGitService } from '../../../platform/git/common/gitService';
13
import { IOctoKitService } from '../../../platform/github/common/githubService';
14
import { OctoKitService } from '../../../platform/github/common/octoKitServiceImpl';
15
import { ILogService } from '../../../platform/log/common/logService';
16
import { Disposable, DisposableStore } from '../../../util/vs/base/common/lifecycle';
17
import { SyncDescriptor } from '../../../util/vs/platform/instantiation/common/descriptors';
18
import { IInstantiationService } from '../../../util/vs/platform/instantiation/common/instantiation';
19
import { ServiceCollection } from '../../../util/vs/platform/instantiation/common/serviceCollection';
20
import { ILanguageModelServer, LanguageModelServer } from '../../agents/node/langModelServer';
21
import { IExtensionContribution } from '../../common/contributions';
22
import { prExtensionInstalledContextKey } from '../../contextKeys/vscode-node/contextKeys.contribution';
23
import { GitBranchNameGenerator } from '../../prompt/node/gitBranch';
24
import { ChatSummarizerProvider } from '../../prompt/node/summarizer';
25
import { IToolsService } from '../../tools/common/toolsService';
26
import { IClaudeRuntimeDataService } from '../claude/common/claudeRuntimeDataService';
27
import { ClaudeSessionUri } from '../claude/common/claudeSessionUri';
28
import { ClaudeToolPermissionService, IClaudeToolPermissionService } from '../claude/common/claudeToolPermissionService';
29
import { ClaudeCodeFolderMruService } from '../claude/node/claudeCodeFolderMru';
30
import { ClaudeAgentManager } from '../claude/node/claudeCodeAgent';
31
import { ClaudeCodeModels, IClaudeCodeModels } from '../claude/node/claudeCodeModels';
32
import { ClaudeCodeSdkService, IClaudeCodeSdkService } from '../claude/node/claudeCodeSdkService';
33
import { ClaudeRuntimeDataService } from '../claude/node/claudeRuntimeDataService';
34
import { ClaudePluginService, IClaudePluginService } from '../claude/node/claudeSkills';
35
import { IClaudeSessionStateService } from '../claude/common/claudeSessionStateService';
36
import { ClaudeSessionStateService } from '../claude/node/claudeSessionStateService';
37
import { ClaudeCodeSessionService, IClaudeCodeSessionService } from '../claude/node/sessionParser/claudeCodeSessionService';
38
import { ClaudeSlashCommandService, IClaudeSlashCommandService } from '../claude/vscode-node/claudeSlashCommandService';
39
import { IAgentSessionsWorkspace } from '../common/agentSessionsWorkspace';
40
import { IChatSessionMetadataStore } from '../common/chatSessionMetadataStore';
41
import { IChatSessionWorkspaceFolderService } from '../common/chatSessionWorkspaceFolderService';
42
import { IClaudeWorkspaceFolderService } from '../common/claudeWorkspaceFolderService';
43
import { IChatSessionWorktreeCheckpointService } from '../common/chatSessionWorktreeCheckpointService';
44
import { IChatSessionWorktreeService } from '../common/chatSessionWorktreeService';
45
import { IChatFolderMruService, IFolderRepositoryManager } from '../common/folderRepositoryManager';
46
import { ICustomSessionTitleService } from '../copilotcli/common/customSessionTitleService';
47
import { ChatDelegationSummaryService, IChatDelegationSummaryService } from '../copilotcli/common/delegationSummaryService';
48
import { SessionIdForCLI } from '../copilotcli/common/utils';
49
import { CopilotCLIAgents, CopilotCLIModels, CopilotCLISDK, ICopilotCLIAgents, ICopilotCLIModels, ICopilotCLISDK } from '../copilotcli/node/copilotCli';
50
import { CopilotCLIImageSupport, ICopilotCLIImageSupport } from '../copilotcli/node/copilotCLIImageSupport';
51
import { CopilotCLIPromptResolver } from '../copilotcli/node/copilotcliPromptResolver';
52
import { CopilotCLISessionService, ICopilotCLISessionService } from '../copilotcli/node/copilotcliSessionService';
53
import { CopilotCLISkills, ICopilotCLISkills } from '../copilotcli/node/copilotCLISkills';
54
import { CopilotCLIMCPHandler, ICopilotCLIMCPHandler } from '../copilotcli/node/mcpHandler';
55
import { IUserQuestionHandler } from '../copilotcli/node/userInputHelpers';
56
import { CopilotCLIContrib, getServices } from '../copilotcli/vscode-node/contribution';
57
import { CopilotCLIFolderMruService } from '../copilotcli/vscode-node/copilotCLIFolderMru';
58
import { ICopilotCLISessionTracker } from '../copilotcli/vscode-node/copilotCLISessionTracker';
59
import { CustomSessionTitleService } from '../copilotcli/vscode-node/customSessionTitleServiceImpl';
60
import { GHPR_EXTENSION_ID } from '../vscode/chatSessionsUriHandler';
61
import { AgentSessionsWorkspace } from './agentSessionsWorkspace';
62
import { UserQuestionHandler } from '../copilotcli/vscode-node/askUserQuestionHandler';
63
import { ChatSessionMetadataStore } from '../copilotcli/vscode-node/chatSessionMetadataStoreImpl';
64
import { ChatSessionRepositoryTracker } from './chatSessionRepositoryTracker';
65
import { ChatSessionWorkspaceFolderService } from './chatSessionWorkspaceFolderServiceImpl';
66
import { ClaudeWorkspaceFolderService } from './claudeWorkspaceFolderServiceImpl';
67
import { ChatSessionWorktreeCheckpointService } from './chatSessionWorktreeCheckpointServiceImpl';
68
import { ChatSessionWorktreeService } from './chatSessionWorktreeServiceImpl';
69
import { ClaudeChatSessionContentProvider } from './claudeChatSessionContentProvider';
70
import { ClaudeCustomizationProvider } from './claudeCustomizationProvider';
71
import { CopilotCLIChatSessionInitializer, ICopilotCLIChatSessionInitializer } from '../copilotcli/vscode-node/copilotCLIChatSessionInitializer';
72
import { CopilotCLIChatSessionContentProvider, CopilotCLIChatSessionParticipant, registerCLIChatCommands } from './copilotCLIChatSessions';
73
import { CopilotCLIChatSessionContentProvider as CopilotCLIChatSessionContentProviderV1, CopilotCLIChatSessionItemProvider as CopilotCLIChatSessionItemProviderV1, CopilotCLIChatSessionParticipant as CopilotCLIChatSessionParticipantV1, registerCLIChatCommands as registerCLIChatCommandsV1 } from './copilotCLIChatSessionsContribution';
74
import { CopilotCLICustomizationProvider } from '../copilotcli/vscode-node/copilotCLICustomizationProvider';
75
import { CopilotCLITerminalIntegration, ICopilotCLITerminalIntegration } from './copilotCLITerminalIntegration';
76
import { CopilotCloudSessionsProvider } from './copilotCloudSessionsProvider';
77
import { ClaudeFolderRepositoryManager, CopilotCLIFolderRepositoryManager } from './folderRepositoryManagerImpl';
78
import { PRContentProvider } from './prContentProvider';
79
import { IPullRequestDetectionService, PullRequestDetectionService } from './pullRequestDetectionService';
80
import { IPullRequestFileChangesService, PullRequestFileChangesService } from './pullRequestFileChangesService';
81
import { ISessionOptionGroupBuilder, SessionOptionGroupBuilder } from './sessionOptionGroupBuilder';
82
import { ISessionRequestLifecycle, SessionRequestLifecycle } from './sessionRequestLifecycle';
83
84
85
// https://github.com/microsoft/vscode-pull-request-github/blob/8a5c9a145cd80ee364a3bed9cf616b2bd8ac74c2/src/github/copilotApi.ts#L56-L71
86
export interface CrossChatSessionWithPR {
87
pullRequestDetails: {
88
number: number;
89
repository: {
90
owner: {
91
login: string;
92
};
93
name: string;
94
};
95
};
96
}
97
98
const CLOSE_SESSION_PR_CMD = 'github.copilot.cloud.sessions.proxy.closeChatSessionPullRequest';
99
export class ChatSessionsContrib extends Disposable implements IExtensionContribution {
100
readonly id = 'chatSessions';
101
readonly copilotcliSessionType = 'copilotcli';
102
103
private copilotCloudRegistrations: DisposableStore | undefined;
104
private copilotAgentInstaService: IInstantiationService | undefined;
105
106
constructor(
107
@IInstantiationService instantiationService: IInstantiationService,
108
@ILogService private readonly logService: ILogService,
109
@IOctoKitService private readonly octoKitService: IOctoKitService,
110
@IEnvService private readonly envService: IEnvService,
111
) {
112
super();
113
// Copilot Cloud Agent - conditionally register based on configuration
114
const summarizer = instantiationService.createInstance(ChatSummarizerProvider);
115
const delegationSummary = instantiationService.createInstance(ChatDelegationSummaryService, summarizer);
116
this._register(vscode.workspace.registerTextDocumentContentProvider(delegationSummary.scheme, {
117
provideTextDocumentContent: (uri: vscode.Uri): string | undefined => delegationSummary.provideTextDocumentContent(uri)
118
}));
119
this.copilotAgentInstaService = instantiationService.createChild(new ServiceCollection(
120
[IOctoKitService, new SyncDescriptor(OctoKitService)],
121
[IChatDelegationSummaryService, delegationSummary],
122
[IPullRequestFileChangesService, new SyncDescriptor(PullRequestFileChangesService)],
123
));
124
125
const configKey = vscode.workspace.isAgentSessionsWorkspace
126
? ConfigKey.Advanced.CLISessionControllerForSessionsApp
127
: ConfigKey.Advanced.CLISessionController;
128
const useController = instantiationService.invokeFunction(accessor =>
129
accessor.get(IConfigurationService).getConfig(configKey)
130
);
131
const { sessionMetadata } = useController ? this.registerCopilotCLIServices(instantiationService, delegationSummary, logService) : this.registerCopilotCLIServicesV1(instantiationService, delegationSummary, logService);
132
133
// #region Claude Code Chat Sessions
134
const claudeAgentInstaService = instantiationService.createChild(
135
new ServiceCollection(
136
[IAgentSessionsWorkspace, new SyncDescriptor(AgentSessionsWorkspace)],
137
[IClaudeCodeSessionService, new SyncDescriptor(ClaudeCodeSessionService)],
138
[IClaudeCodeSdkService, new SyncDescriptor(ClaudeCodeSdkService)],
139
[IClaudeCodeModels, new SyncDescriptor(ClaudeCodeModels)],
140
[ILanguageModelServer, new SyncDescriptor(LanguageModelServer)],
141
[IClaudeToolPermissionService, new SyncDescriptor(ClaudeToolPermissionService)],
142
[IClaudeSessionStateService, new SyncDescriptor(ClaudeSessionStateService)],
143
[IClaudeSlashCommandService, new SyncDescriptor(ClaudeSlashCommandService)],
144
[IChatSessionMetadataStore, sessionMetadata],
145
[IChatSessionWorktreeService, new SyncDescriptor(ChatSessionWorktreeService)],
146
[IChatSessionWorktreeCheckpointService, new SyncDescriptor(ChatSessionWorktreeCheckpointService)],
147
[IChatSessionWorkspaceFolderService, new SyncDescriptor(ChatSessionWorkspaceFolderService)],
148
[IClaudeWorkspaceFolderService, new SyncDescriptor(ClaudeWorkspaceFolderService)],
149
[IFolderRepositoryManager, new SyncDescriptor(ClaudeFolderRepositoryManager)],
150
[IChatFolderMruService, new SyncDescriptor(ClaudeCodeFolderMruService)],
151
[IClaudeRuntimeDataService, new SyncDescriptor(ClaudeRuntimeDataService)],
152
[IClaudePluginService, new SyncDescriptor(ClaudePluginService)],
153
));
154
const claudeAgentManager = this._register(claudeAgentInstaService.createInstance(ClaudeAgentManager));
155
const claudeModels = claudeAgentInstaService.invokeFunction(accessor => accessor.get(IClaudeCodeModels));
156
claudeModels.registerLanguageModelChatProvider(vscode.lm);
157
const chatSessionContentProvider = this._register(claudeAgentInstaService.createInstance(ClaudeChatSessionContentProvider, claudeAgentManager));
158
const chatParticipant = vscode.chat.createChatParticipant(ClaudeSessionUri.scheme, chatSessionContentProvider.createHandler());
159
chatParticipant.iconPath = new vscode.ThemeIcon('claude');
160
this._register(vscode.chat.registerChatSessionContentProvider(ClaudeSessionUri.scheme, chatSessionContentProvider, chatParticipant));
161
const claudeCustomizationProvider = this._register(claudeAgentInstaService.createInstance(ClaudeCustomizationProvider));
162
this._register(vscode.chat.registerChatSessionCustomizationProvider(ClaudeSessionUri.scheme, ClaudeCustomizationProvider.metadata, claudeCustomizationProvider));
163
164
// #endregion
165
166
// #endregion
167
168
}
169
170
private registerCopilotCLIServices(instantiationService: IInstantiationService, delegationSummary: IChatDelegationSummaryService, logService: ILogService) {
171
const cloudSessionProvider = this.registerCopilotCloudAgent();
172
const copilotcliAgentInstaService = instantiationService.createChild(
173
new ServiceCollection(
174
[IAgentSessionsWorkspace, new SyncDescriptor(AgentSessionsWorkspace)],
175
[ICopilotCLIImageSupport, new SyncDescriptor(CopilotCLIImageSupport)],
176
[ICopilotCLISessionService, new SyncDescriptor(CopilotCLISessionService)],
177
[IChatDelegationSummaryService, delegationSummary],
178
[ICopilotCLIModels, new SyncDescriptor(CopilotCLIModels)],
179
[ICopilotCLISDK, new SyncDescriptor(CopilotCLISDK)],
180
[ICopilotCLIAgents, new SyncDescriptor(CopilotCLIAgents)],
181
[ILanguageModelServer, new SyncDescriptor(LanguageModelServer)],
182
[ICopilotCLITerminalIntegration, new SyncDescriptor(CopilotCLITerminalIntegration)],
183
[IChatSessionWorktreeService, new SyncDescriptor(ChatSessionWorktreeService)],
184
[IChatSessionWorktreeCheckpointService, new SyncDescriptor(ChatSessionWorktreeCheckpointService)],
185
[IChatSessionWorkspaceFolderService, new SyncDescriptor(ChatSessionWorkspaceFolderService)],
186
[ICopilotCLIMCPHandler, new SyncDescriptor(CopilotCLIMCPHandler)],
187
[IFolderRepositoryManager, new SyncDescriptor(CopilotCLIFolderRepositoryManager)],
188
[IUserQuestionHandler, new SyncDescriptor(UserQuestionHandler)],
189
[ICustomSessionTitleService, new SyncDescriptor(CustomSessionTitleService)],
190
[ICopilotCLISkills, new SyncDescriptor(CopilotCLISkills)],
191
[IChatSessionMetadataStore, new SyncDescriptor(ChatSessionMetadataStore)],
192
[IChatFolderMruService, new SyncDescriptor(CopilotCLIFolderMruService)],
193
[IPullRequestDetectionService, new SyncDescriptor(PullRequestDetectionService)],
194
[ISessionOptionGroupBuilder, new SyncDescriptor(SessionOptionGroupBuilder)],
195
[ISessionRequestLifecycle, new SyncDescriptor(SessionRequestLifecycle)],
196
[ICopilotCLIChatSessionInitializer, new SyncDescriptor(CopilotCLIChatSessionInitializer)],
197
...getServices()
198
));
199
200
const copilotcliChatSessionContentProvider = copilotcliAgentInstaService.createInstance(CopilotCLIChatSessionContentProvider);
201
this._register(copilotcliAgentInstaService.createInstance(ChatSessionRepositoryTracker, undefined));
202
const promptResolver = copilotcliAgentInstaService.createInstance(CopilotCLIPromptResolver);
203
const gitService = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(IGitService));
204
const sessionTracker = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(ICopilotCLISessionTracker));
205
const terminalIntegration = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(ICopilotCLITerminalIntegration));
206
const aiGeneratedBranchNames = instantiationService.invokeFunction(accessor =>
207
accessor.get(IConfigurationService).getConfig(ConfigKey.Advanced.CLIAIGenerateBranchNames)
208
);
209
const branchNameGenerator = aiGeneratedBranchNames ? copilotcliAgentInstaService.createInstance(GitBranchNameGenerator) : undefined;
210
211
const copilotcliChatSessionParticipant = this._register(copilotcliAgentInstaService.createInstance(
212
CopilotCLIChatSessionParticipant,
213
copilotcliChatSessionContentProvider,
214
promptResolver,
215
cloudSessionProvider,
216
branchNameGenerator,
217
));
218
const copilotCLISessionService = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(ICopilotCLISessionService));
219
const copilotCLIWorktreeManagerService = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(IChatSessionWorktreeService));
220
const copilotCLIWorkspaceFolderSessions = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(IChatSessionWorkspaceFolderService));
221
const folderRepositoryManager = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(IFolderRepositoryManager));
222
const nativeEnvService = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(INativeEnvService));
223
const fileSystemService = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(IFileSystemService));
224
const copilotModels = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(ICopilotCLIModels));
225
const copilotCLIFolderMruService = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(IChatFolderMruService));
226
227
this._register(copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(ICopilotCLISessionTracker)));
228
this._register(copilotcliAgentInstaService.createInstance(CopilotCLIContrib));
229
230
copilotModels.registerLanguageModelChatProvider(vscode.lm);
231
232
const copilotcliParticipant = vscode.chat.createChatParticipant(this.copilotcliSessionType, copilotcliChatSessionParticipant.createHandler());
233
this._register(vscode.chat.registerChatSessionContentProvider(this.copilotcliSessionType, copilotcliChatSessionContentProvider, copilotcliParticipant));
234
const copilotcliCustomizationProvider = this._register(copilotcliAgentInstaService.createInstance(CopilotCLICustomizationProvider));
235
this._register(vscode.chat.registerChatSessionCustomizationProvider(this.copilotcliSessionType, CopilotCLICustomizationProvider.metadata, copilotcliCustomizationProvider));
236
this._register(registerCLIChatCommands(copilotCLISessionService, copilotCLIWorktreeManagerService, gitService, copilotCLIWorkspaceFolderSessions, copilotcliChatSessionContentProvider, folderRepositoryManager, copilotCLIFolderMruService, nativeEnvService, fileSystemService, sessionTracker, terminalIntegration, logService));
237
// #endregion
238
239
const sessionMetadata = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(IChatSessionMetadataStore));
240
return { sessionMetadata };
241
}
242
243
private registerCopilotCLIServicesV1(instantiationService: IInstantiationService, delegationSummary: IChatDelegationSummaryService, logService: ILogService) {
244
const cloudSessionProvider = this.registerCopilotCloudAgent();
245
const copilotcliAgentInstaService = instantiationService.createChild(
246
new ServiceCollection(
247
[IAgentSessionsWorkspace, new SyncDescriptor(AgentSessionsWorkspace)],
248
[ICopilotCLIImageSupport, new SyncDescriptor(CopilotCLIImageSupport)],
249
[ICopilotCLISessionService, new SyncDescriptor(CopilotCLISessionService)],
250
[IChatDelegationSummaryService, delegationSummary],
251
[ICopilotCLIModels, new SyncDescriptor(CopilotCLIModels)],
252
[ICopilotCLISDK, new SyncDescriptor(CopilotCLISDK)],
253
[ICopilotCLIAgents, new SyncDescriptor(CopilotCLIAgents)],
254
[ILanguageModelServer, new SyncDescriptor(LanguageModelServer)],
255
[ICopilotCLITerminalIntegration, new SyncDescriptor(CopilotCLITerminalIntegration)],
256
[IChatSessionWorktreeService, new SyncDescriptor(ChatSessionWorktreeService)],
257
[IChatSessionWorktreeCheckpointService, new SyncDescriptor(ChatSessionWorktreeCheckpointService)],
258
[IChatSessionWorkspaceFolderService, new SyncDescriptor(ChatSessionWorkspaceFolderService)],
259
[ICopilotCLIMCPHandler, new SyncDescriptor(CopilotCLIMCPHandler)],
260
[IFolderRepositoryManager, new SyncDescriptor(CopilotCLIFolderRepositoryManager)],
261
[IUserQuestionHandler, new SyncDescriptor(UserQuestionHandler)],
262
[ICustomSessionTitleService, new SyncDescriptor(CustomSessionTitleService)],
263
[ICopilotCLISkills, new SyncDescriptor(CopilotCLISkills)],
264
[IChatSessionMetadataStore, new SyncDescriptor(ChatSessionMetadataStore)],
265
[IChatFolderMruService, new SyncDescriptor(CopilotCLIFolderMruService)],
266
...getServices()
267
));
268
269
const copilotcliSessionItemProvider = this._register(copilotcliAgentInstaService.createInstance(CopilotCLIChatSessionItemProviderV1));
270
const providerRegistration = vscode.chat.registerChatSessionItemProvider(this.copilotcliSessionType, copilotcliSessionItemProvider);
271
this._register(providerRegistration);
272
this._register(copilotcliAgentInstaService.createInstance(ChatSessionRepositoryTracker, copilotcliSessionItemProvider));
273
const copilotcliChatSessionContentProvider = copilotcliAgentInstaService.createInstance(CopilotCLIChatSessionContentProviderV1, copilotcliSessionItemProvider);
274
const promptResolver = copilotcliAgentInstaService.createInstance(CopilotCLIPromptResolver);
275
const gitService = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(IGitService));
276
const gitExtensionService = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(IGitExtensionService));
277
const toolsService = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(IToolsService));
278
const aiGeneratedBranchNamesV1 = instantiationService.invokeFunction(accessor =>
279
accessor.get(IConfigurationService).getConfig(ConfigKey.Advanced.CLIAIGenerateBranchNames)
280
);
281
const branchNameGeneratorV1 = aiGeneratedBranchNamesV1 ? copilotcliAgentInstaService.createInstance(GitBranchNameGenerator) : undefined;
282
283
const copilotcliChatSessionParticipant = this._register(copilotcliAgentInstaService.createInstance(
284
CopilotCLIChatSessionParticipantV1,
285
copilotcliChatSessionContentProvider,
286
promptResolver,
287
copilotcliSessionItemProvider,
288
cloudSessionProvider,
289
branchNameGeneratorV1,
290
));
291
const copilotCLISessionService = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(ICopilotCLISessionService));
292
const copilotCLIWorktreeManagerService = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(IChatSessionWorktreeService));
293
294
// Handle worktree cleanup/recreation when archive state changes
295
const onDidChangeChatSessionItemState = (providerRegistration as { onDidChangeChatSessionItemState?: vscode.Event<vscode.ChatSessionItem> }).onDidChangeChatSessionItemState;
296
if (onDidChangeChatSessionItemState) {
297
this._register(onDidChangeChatSessionItemState(async (item) => {
298
const sessionId = SessionIdForCLI.parse(item.resource);
299
if (item.archived) {
300
try {
301
const result = await copilotCLIWorktreeManagerService.cleanupWorktreeOnArchive(sessionId);
302
logService.trace(`[CopilotCLI] Worktree cleanup for session ${sessionId}: ${result.cleaned ? 'cleaned' : result.reason}`);
303
} catch (error) {
304
logService.error(`[CopilotCLI] Failed to cleanup worktree for archived session ${sessionId}:`, error);
305
}
306
} else {
307
try {
308
const result = await copilotCLIWorktreeManagerService.recreateWorktreeOnUnarchive(sessionId);
309
logService.trace(`[CopilotCLI] Worktree recreation for session ${sessionId}: ${result.recreated ? 'recreated' : result.reason}`);
310
if (result.recreated) {
311
copilotcliSessionItemProvider.refreshSession({ reason: 'update', sessionId });
312
}
313
} catch (error) {
314
logService.error(`[CopilotCLI] Failed to recreate worktree for unarchived session ${sessionId}:`, error);
315
}
316
}
317
}));
318
}
319
320
const copilotCLIWorkspaceFolderSessions = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(IChatSessionWorkspaceFolderService));
321
const folderRepositoryManager = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(IFolderRepositoryManager));
322
const nativeEnvService = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(INativeEnvService));
323
const fileSystemService = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(IFileSystemService));
324
const copilotModels = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(ICopilotCLIModels));
325
const copilotFolderMruService = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(IChatFolderMruService));
326
327
this._register(copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(ICopilotCLISessionTracker)));
328
this._register(copilotcliAgentInstaService.createInstance(CopilotCLIContrib));
329
330
copilotModels.registerLanguageModelChatProvider(vscode.lm);
331
332
const copilotcliParticipant = vscode.chat.createChatParticipant(this.copilotcliSessionType, copilotcliChatSessionParticipant.createHandler());
333
this._register(vscode.chat.registerChatSessionContentProvider(this.copilotcliSessionType, copilotcliChatSessionContentProvider, copilotcliParticipant));
334
const copilotcliCustomizationProvider = this._register(copilotcliAgentInstaService.createInstance(CopilotCLICustomizationProvider));
335
this._register(vscode.chat.registerChatSessionCustomizationProvider(this.copilotcliSessionType, CopilotCLICustomizationProvider.metadata, copilotcliCustomizationProvider));
336
this._register(registerCLIChatCommandsV1(copilotcliSessionItemProvider, copilotCLISessionService, copilotCLIWorktreeManagerService, gitService, gitExtensionService, toolsService, copilotCLIWorkspaceFolderSessions, copilotcliChatSessionContentProvider, folderRepositoryManager, copilotFolderMruService, nativeEnvService, fileSystemService, logService));
337
// #endregion
338
339
const sessionMetadata = copilotcliAgentInstaService.invokeFunction(accessor => accessor.get(IChatSessionMetadataStore));
340
return { sessionMetadata };
341
}
342
343
private registerCopilotCloudAgent() {
344
if (!this.copilotAgentInstaService) {
345
return;
346
}
347
if (this.copilotCloudRegistrations) {
348
this.copilotCloudRegistrations.dispose();
349
this.copilotCloudRegistrations = undefined;
350
}
351
this.copilotCloudRegistrations = new DisposableStore();
352
this.copilotCloudRegistrations.add(
353
this.copilotAgentInstaService.createInstance(PRContentProvider)
354
);
355
const cloudSessionsProvider = this.copilotCloudRegistrations.add(
356
this.copilotAgentInstaService.createInstance(CopilotCloudSessionsProvider)
357
);
358
this.copilotCloudRegistrations.add(
359
vscode.chat.registerChatSessionItemProvider(CopilotCloudSessionsProvider.TYPE, cloudSessionsProvider)
360
);
361
this.copilotCloudRegistrations.add(
362
vscode.chat.registerChatSessionContentProvider(
363
CopilotCloudSessionsProvider.TYPE,
364
cloudSessionsProvider,
365
cloudSessionsProvider.chatParticipant,
366
{ supportsInterruptions: true }
367
)
368
);
369
this.copilotCloudRegistrations.add(
370
vscode.commands.registerCommand('github.copilot.cloud.resetWorkspaceConfirmations', () => {
371
cloudSessionsProvider.resetWorkspaceContext();
372
})
373
);
374
this.copilotCloudRegistrations.add(
375
vscode.commands.registerCommand('github.copilot.cloud.sessions.openInBrowser', async (chatSessionItem: vscode.ChatSessionItem) => {
376
cloudSessionsProvider.openSessionInBrowser(chatSessionItem);
377
})
378
);
379
this.copilotCloudRegistrations.add(
380
vscode.commands.registerCommand(CLOSE_SESSION_PR_CMD, async (ctx: CrossChatSessionWithPR) => {
381
try {
382
const success = await this.octoKitService.closePullRequest(
383
ctx.pullRequestDetails.repository.owner.login,
384
ctx.pullRequestDetails.repository.name,
385
ctx.pullRequestDetails.number,
386
{ createIfNone: { detail: l10n.t('Sign in to GitHub to access Copilot cloud sessions.') } });
387
if (!success) {
388
this.logService.error(`${CLOSE_SESSION_PR_CMD}: Failed to close PR #${ctx.pullRequestDetails.number}`);
389
}
390
cloudSessionsProvider.refresh();
391
} catch (e) {
392
this.logService.error(`${CLOSE_SESSION_PR_CMD}: Exception ${e}`);
393
}
394
})
395
);
396
this.copilotCloudRegistrations.add(
397
vscode.commands.registerCommand('github.copilot.cloud.sessions.installPRExtension', async () => {
398
await this.installPullRequestExtension();
399
})
400
);
401
return cloudSessionsProvider;
402
}
403
404
private isPullRequestExtensionInstalled(): boolean {
405
return vscode.extensions.getExtension(GHPR_EXTENSION_ID) !== undefined;
406
}
407
408
private async installPullRequestExtension(): Promise<void> {
409
if (this.isPullRequestExtensionInstalled()) {
410
return;
411
}
412
try {
413
const isInsiders = this.envService.getEditorInfo().version.includes('insider');
414
const installOptions = { enable: true, installPreReleaseVersion: isInsiders, justification: vscode.l10n.t('Enable additional pull request features, such as checking out and applying changes.') };
415
await vscode.commands.executeCommand('workbench.extensions.installExtension', GHPR_EXTENSION_ID, installOptions);
416
const maxWaitTime = 10_000; // 10 seconds
417
const pollInterval = 100; // 100ms
418
let elapsed = 0;
419
while (elapsed < maxWaitTime) {
420
if (this.isPullRequestExtensionInstalled()) {
421
vscode.window.showInformationMessage(vscode.l10n.t('GitHub Pull Request extension installed successfully.'));
422
break;
423
}
424
await new Promise(resolve => setTimeout(resolve, pollInterval));
425
elapsed += pollInterval;
426
}
427
if (!this.isPullRequestExtensionInstalled()) {
428
vscode.window.showWarningMessage(vscode.l10n.t('GitHub Pull Request extension is taking longer than expected to install.'));
429
}
430
await vscode.commands.executeCommand('setContext', prExtensionInstalledContextKey, true);
431
} catch (error) {
432
vscode.window.showErrorMessage(vscode.l10n.t('Failed to install GitHub Pull Request extension: {0}', error instanceof Error ? error.message : String(error)));
433
}
434
}
435
}
436
437