@codingame/monaco-vscode-chat-cloud-service-override 0.0.0-stage → 38.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/common.d.ts +2 -0
  2. package/common.js +29 -0
  3. package/index.d.ts +3 -0
  4. package/index.js +9 -0
  5. package/package.json +52 -3
  6. package/session.d.ts +3 -0
  7. package/session.js +11 -0
  8. package/vscode/src/vs/sessions/contrib/chat/browser/newSession.d.ts +9 -0
  9. package/vscode/src/vs/sessions/contrib/providers/copilotChatSessions/browser/cloudAutomationStore.d.ts +67 -0
  10. package/vscode/src/vs/sessions/contrib/providers/copilotChatSessions/browser/cloudAutomationStore.js +695 -0
  11. package/vscode/src/vs/sessions/contrib/providers/copilotChatSessions/browser/cloudSandboxSessionConfig.d.ts +4 -0
  12. package/vscode/src/vs/sessions/contrib/providers/copilotChatSessions/browser/cloudSandboxSessionConfig.js +39 -0
  13. package/vscode/src/vs/sessions/contrib/providers/copilotChatSessions/browser/copilotChatSessions.contribution.d.ts +1 -0
  14. package/vscode/src/vs/sessions/contrib/providers/copilotChatSessions/browser/copilotChatSessions.contribution.js +59 -0
  15. package/vscode/src/vs/sessions/contrib/providers/copilotChatSessions/browser/copilotChatSessionsActions.d.ts +1 -0
  16. package/vscode/src/vs/sessions/contrib/providers/copilotChatSessions/browser/copilotChatSessionsActions.js +83 -0
  17. package/vscode/src/vs/sessions/contrib/providers/copilotChatSessions/browser/copilotChatSessionsChangesets.d.ts +87 -0
  18. package/vscode/src/vs/sessions/contrib/providers/copilotChatSessions/browser/copilotChatSessionsChangesets.js +176 -0
  19. package/vscode/src/vs/sessions/contrib/providers/copilotChatSessions/browser/copilotChatSessionsProvider.d.ts +422 -0
  20. package/vscode/src/vs/sessions/contrib/providers/copilotChatSessions/browser/copilotChatSessionsProvider.js +2444 -0
  21. package/vscode/src/vs/sessions/contrib/providers/copilotChatSessions/browser/githubCloudAutomationStore.d.ts +91 -0
  22. package/vscode/src/vs/sessions/contrib/providers/copilotChatSessions/browser/githubCloudAutomationStore.js +620 -0
  23. package/vscode/src/vs/sessions/contrib/providers/remoteAgentHost/browser/cloudSandboxAgentHost.contribution.d.ts +1 -0
  24. package/vscode/src/vs/sessions/contrib/providers/remoteAgentHost/browser/cloudSandboxAgentHost.contribution.js +5 -0
  25. package/vscode/src/vs/sessions/contrib/providers/remoteAgentHost/browser/cloudSandboxAgentHostContribution.d.ts +46 -0
  26. package/vscode/src/vs/sessions/contrib/providers/remoteAgentHost/browser/cloudSandboxAgentHostContribution.js +321 -0
  27. package/vscode/src/vs/sessions/contrib/providers/remoteAgentHost/browser/cloudSandboxSessionsProvider.d.ts +104 -0
  28. package/vscode/src/vs/sessions/contrib/providers/remoteAgentHost/browser/cloudSandboxSessionsProvider.js +345 -0
  29. package/README.md +0 -3
@@ -0,0 +1,2444 @@
1
+
2
+ import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
3
+ import { Emitter, Event } from '@codingame/monaco-vscode-api/vscode/vs/base/common/event';
4
+ import { raceCancellationError, raceTimeout } from '@codingame/monaco-vscode-api/vscode/vs/base/common/async';
5
+ import { Codicon } from '@codingame/monaco-vscode-api/vscode/vs/base/common/codicons';
6
+ import { CancellationError, isCancellationError } from '@codingame/monaco-vscode-api/vscode/vs/base/common/errors';
7
+ import { markdownStringEqual, MarkdownString } from '@codingame/monaco-vscode-api/vscode/vs/base/common/htmlContent';
8
+ import { Disposable, MutableDisposable, toDisposable, DisposableMap, DisposableStore } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
9
+ import { Schemas } from '@codingame/monaco-vscode-api/vscode/vs/base/common/network';
10
+ import { deepClone } from '@codingame/monaco-vscode-api/vscode/vs/base/common/objects';
11
+ import { isWeb } from '@codingame/monaco-vscode-api/vscode/vs/base/common/platform';
12
+ import '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/index';
13
+ import { URI } from '@codingame/monaco-vscode-api/vscode/vs/base/common/uri';
14
+ import { ICommandService } from '@codingame/monaco-vscode-api/vscode/vs/platform/commands/common/commands.service';
15
+ import { IInstantiationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/instantiation';
16
+ import { AgentSession } from '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/agent';
17
+ import { parseGitHubIssueUrl, getGitHubRepositoryId } from '@codingame/monaco-vscode-api/vscode/vs/platform/github/common/githubUrls';
18
+ import { getAgentSessionPullRequestUri } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/browser/agentSessions/agentSessionsModel';
19
+ import { getRepositoryName } from '@codingame/monaco-vscode-katex-common/vscode/vs/workbench/contrib/chat/browser/agentSessions/agentSessionsViewer';
20
+ import { IAgentSessionsService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/browser/agentSessions/agentSessionsService.service';
21
+ import { AgentSessionProviders } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/browser/agentSessions/agentSessions';
22
+ import { IChatService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/common/chatService/chatService.service';
23
+ import { ChatSessionStatus, SessionType } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/common/chatSessionsService';
24
+ import { IChatSessionsService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/common/chatSessionsService.service';
25
+ import { assertAutomationSessionTemplate } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/common/automations/automation';
26
+ import { AutomationModelConfiguration } from '@codingame/monaco-vscode-api/vscode/vs/sessions/contrib/automations/browser/automationModelConfiguration';
27
+ import { SessionTypeAuthRequirement, ChatInteractivity, SessionStatus, sessionFileChangesEqual, toSessionId, GITHUB_REMOTE_FILE_SCHEME, sessionWorkspaceEqual, gitHubInfoEqual, SessionArtifactKind, SESSION_WORKSPACE_GROUP_GITHUB, SESSION_WORKSPACE_GROUP_LOCAL, ChatModelSource } from '@codingame/monaco-vscode-api/vscode/vs/sessions/services/sessions/common/session';
28
+ import { linkKey } from '@codingame/monaco-vscode-api/vscode/vs/sessions/common/sessionLinks';
29
+ import { getSessionApplication } from '@codingame/monaco-vscode-api/vscode/vs/sessions/common/sessionApplication';
30
+ import { ChatConfiguration, isChatPermissionLevel, ChatPermissionLevel, ChatModeKind, ChatAgentLocation } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/common/constants';
31
+ import { isEqual, basename, dirname } from '@codingame/monaco-vscode-api/vscode/vs/base/common/resources';
32
+ import { UNIFIED_WORKSPACE_PICKER_SETTING } from '@codingame/monaco-vscode-api/vscode/vs/sessions/contrib/chat/common/constants';
33
+ import { cancelOnDispose, CancellationTokenSource, CancellationToken } from '@codingame/monaco-vscode-api/vscode/vs/base/common/cancellation';
34
+ import { generateUuid } from '@codingame/monaco-vscode-api/vscode/vs/base/common/uuid';
35
+ import { COPILOT_VENDOR_ID } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/common/languageModels';
36
+ import { ILanguageModelsService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/common/languageModels.service';
37
+ import { resolveModelIdentifier, getRegisteredLanguageModels, resolveModelIdentifierFromLanguageModels } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/common/modelSelection';
38
+ import { ContextKeyExpr } from '@codingame/monaco-vscode-api/vscode/vs/platform/contextkey/common/contextkey';
39
+ import { IContextKeyService } from '@codingame/monaco-vscode-api/vscode/vs/platform/contextkey/common/contextkey.service';
40
+ import { ExtensionIdentifier } from '@codingame/monaco-vscode-api/vscode/vs/platform/extensions/common/extensions';
41
+ import { localize } from '@codingame/monaco-vscode-api/vscode/vs/nls';
42
+ import { IConfigurationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/configuration/common/configuration.service';
43
+ import { ILabelService } from '@codingame/monaco-vscode-api/vscode/vs/platform/label/common/label.service';
44
+ import { ILogService } from '@codingame/monaco-vscode-api/vscode/vs/platform/log/common/log.service';
45
+ import { INotificationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/notification/common/notification.service';
46
+ import { SessionConfigKey } from '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/sessionConfigKeys';
47
+ import { SESSION_META_WORKSPACELESS_KEY } from '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/sessionState';
48
+ import { StorageScope, StorageTarget } from '@codingame/monaco-vscode-api/vscode/vs/platform/storage/common/storage';
49
+ import { IStorageService } from '@codingame/monaco-vscode-api/vscode/vs/platform/storage/common/storage.service';
50
+ import { IGitHubService } from '@codingame/monaco-vscode-api/vscode/vs/sessions/contrib/github/browser/githubService.service';
51
+ import { GitHubPullRequestState } from '@codingame/monaco-vscode-api/vscode/vs/sessions/contrib/github/common/types';
52
+ import { computePullRequestRefPresentation } from '@codingame/monaco-vscode-api/vscode/vs/sessions/contrib/github/browser/pullRequestIconStatus';
53
+ import { IPullRequestIconCache } from '@codingame/monaco-vscode-api/vscode/vs/sessions/contrib/github/browser/pullRequestIconCache.service';
54
+ import { arrayEquals, structuralEquals } from '@codingame/monaco-vscode-api/vscode/vs/base/common/equals';
55
+ import { createChangesets } from './copilotChatSessionsChangesets.js';
56
+ import { IUriIdentityService } from '@codingame/monaco-vscode-api/vscode/vs/platform/uriIdentity/common/uriIdentity.service';
57
+ import { isCloudSandboxEnabled, CloudSandboxEnabledSettingId } from '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/cloudSandboxAgentHost';
58
+ import { RemoteAgentHostsEnabledSettingId } from '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/remoteAgentHostService';
59
+ import { getWorkbenchContribution } from '@codingame/monaco-vscode-api/vscode/vs/workbench/common/contributions';
60
+ import { CLOUD_SANDBOX_CREATION_PROVIDER_ID, CloudSandboxAgentHostContribution } from '../../remoteAgentHost/browser/cloudSandboxAgentHostContribution.js';
61
+ import { IFileService } from '@codingame/monaco-vscode-api/vscode/vs/platform/files/common/files.service';
62
+ import { resolveGitRepositoryFromGitConfig } from '@codingame/monaco-vscode-api/vscode/vs/sessions/services/sessions/browser/gitHubRepositoryResolver';
63
+ import '@codingame/monaco-vscode-api/vscode/vs/workbench/services/path/common/pathService';
64
+ import { RepositoryPicker } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/browser/agentSessions/repositoryPicker';
65
+ import { ChatAIDisabledSettingId } from '@codingame/monaco-vscode-api/vscode/vs/platform/chat/common/chatSettings';
66
+ import { CloudSandboxModels } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/browser/remoteAgentHost/cloudSandboxModels';
67
+ import { validateSessionConfigWrite } from '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/sessionConfigProperties';
68
+ import { createCloudSandboxSessionConfig } from './cloudSandboxSessionConfig.js';
69
+ import { CloudAutomationStore } from './cloudAutomationStore.js';
70
+ import { observableValue } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/observableValue';
71
+ import { constObservable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/constObservable';
72
+ import { transaction } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/transaction';
73
+ import { IPathService } from '@codingame/monaco-vscode-api/vscode/vs/platform/path/common/pathService.service';
74
+ import { observableValueOpts } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/observableValueOpts';
75
+ import { derived } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/observables/derived';
76
+ import { computePullRequestIcon } from '@codingame/monaco-vscode-api/vscode/vs/workbench/common/chatPullRequest';
77
+ import { observableFromPromise } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/utils/utils';
78
+
79
+ var CopilotChatSessionsProvider_1;
80
+ const CopilotCloudSessionType = {
81
+ id: "copilot-cloud-agent",
82
+ label: ( localize(5066, "Cloud")),
83
+ icon: Codicon.cloud,
84
+ authRequirement: SessionTypeAuthRequirement.GitHub
85
+ };
86
+ const CopilotSandboxSessionType = {
87
+ id: "copilot-cloud-sandbox",
88
+ label: ( localize(5067, "Copilot")),
89
+ icon: Codicon.copilot,
90
+ authRequirement: SessionTypeAuthRequirement.GitHub
91
+ };
92
+ const STORAGE_KEY_CREATED_BY_SESSIONS = "sessions.copilotChat.createdBySessions";
93
+ const OPEN_REPO_COMMAND = "github.copilot.chat.cloudSessions.openRepository";
94
+ const OPEN_ISSUE_COMMAND = "github.copilot.chat.cloudSessions.openIssue";
95
+ const OPEN_PULL_REQUEST_COMMAND = "github.copilot.chat.cloudSessions.openPullRequest";
96
+ const COPILOT_PROVIDER_ID = "default-copilot";
97
+ function isChangesSummary(changes) {
98
+ return !!changes && !Array.isArray(changes);
99
+ }
100
+ function buildChatFromSession(chat) {
101
+ return {
102
+ resource: chat.resource,
103
+ createdAt: chat.createdAt,
104
+ workspace: chat.workspace,
105
+ title: chat.title,
106
+ updatedAt: chat.updatedAt,
107
+ status: chat.status,
108
+ changes: chat.changes,
109
+ changesets: constObservable(undefined),
110
+ checkpoints: chat.checkpoints,
111
+ modelId: chat.modelId,
112
+ modelSource: chat.modelSource,
113
+ mode: chat.mode,
114
+ isArchived: chat.isArchived,
115
+ isRead: chat.isRead,
116
+ interactivity: constObservable(ChatInteractivity.Full),
117
+ description: chat.description,
118
+ lastTurnEnd: chat.lastTurnEnd
119
+ };
120
+ }
121
+ function setIfChanged(observable, value, tx, equals = Object.is) {
122
+ if (equals(observable.get(), value)) {
123
+ return false;
124
+ }
125
+ observable.set(value, tx, undefined);
126
+ return true;
127
+ }
128
+ function dateEquals(a, b) {
129
+ return a?.getTime() === b?.getTime();
130
+ }
131
+ function markdownStringEquals(a, b) {
132
+ return a === b || !!a && !!b && markdownStringEqual(a, b);
133
+ }
134
+ function sessionArtifactsEqual(a, b) {
135
+ return arrayEquals(
136
+ a,
137
+ b,
138
+ (left, right) => left.id === right.id && left.kind === right.kind && left.label === right.label && left.isArtifact === right.isArtifact && isEqual(left.link, right.link) && isEqual(left.uri, right.uri) && left.commitHash === right.commitHash && left.isGitHub === right.isGitHub
139
+ );
140
+ }
141
+ function isModelOptionGroup(group) {
142
+ if (group.id === "models") {
143
+ return true;
144
+ }
145
+ const nameLower = group.name.toLowerCase();
146
+ return nameLower === "model" || nameLower === "models";
147
+ }
148
+ function isRepositoriesOptionGroup(group) {
149
+ return group.id === "repositories";
150
+ }
151
+ let RemoteNewSession = class RemoteNewSession extends Disposable {
152
+ get project() {
153
+ return this._project;
154
+ }
155
+ get selectedModelId() {
156
+ return this._modelId;
157
+ }
158
+ get repoNwo() {
159
+ return this._repoUri ? githubRemoteRepoLabel(this._repoUri) : undefined;
160
+ }
161
+ get query() {
162
+ return this._query;
163
+ }
164
+ get attachedContext() {
165
+ return this._attachedContext;
166
+ }
167
+ setCreatedBySession(reference) {
168
+ this.createdBySession.set(reference, undefined);
169
+ }
170
+ get disabled() {
171
+ return !this.isQuickChat.get() && !this._repoUri && !( this.selectedOptions.has("repositories"));
172
+ }
173
+ constructor(
174
+ resource,
175
+ sessionWorkspace,
176
+ target,
177
+ providerId,
178
+ initialAutomationSessionConfiguration,
179
+ isAutomationDraft,
180
+ chatSessionsService,
181
+ contextKeyService,
182
+ languageModelsService
183
+ ) {
184
+ super();
185
+ this.resource = resource;
186
+ this.sessionWorkspace = sessionWorkspace;
187
+ this.target = target;
188
+ this.initialAutomationSessionConfiguration = initialAutomationSessionConfiguration;
189
+ this.isAutomationDraft = isAutomationDraft;
190
+ this.chatSessionsService = chatSessionsService;
191
+ this.contextKeyService = contextKeyService;
192
+ this.application = constObservable(getSessionApplication("vscode"));
193
+ this.lifetimeToken = cancelOnDispose(this._store);
194
+ this._title = observableValue(this, "");
195
+ this.title = this._title;
196
+ this._updatedAt = observableValue(this, ( new Date()));
197
+ this.updatedAt = this._updatedAt;
198
+ this._status = observableValue(this, SessionStatus.Untitled);
199
+ this.status = this._status;
200
+ this._workspaceData = observableValue(this, undefined);
201
+ this.workspace = this._workspaceData;
202
+ this.changes = observableValueOpts({
203
+ owner: this,
204
+ equalsFn: sessionFileChangesEqual
205
+ }, []);
206
+ this.checkpoints = constObservable(undefined);
207
+ this._modelIdObservable = observableValue(this, undefined);
208
+ this.modelId = this._modelIdObservable;
209
+ this._modelSourceObservable = observableValue(this, undefined);
210
+ this.modelSource = this._modelSourceObservable;
211
+ this.mode = observableValue(this, undefined);
212
+ this.loading = observableValue(this, false);
213
+ this.preparationProgress = observableValue(this, undefined);
214
+ this.isNewSessionRequestInProgress = this.preparationProgress.map(progress => !!progress);
215
+ this._preparationCts = this._register(( new MutableDisposable()));
216
+ this._preparationActivities = 0;
217
+ this._isArchived = observableValue(this, false);
218
+ this.isArchived = this._isArchived;
219
+ this.isRead = observableValue(this, true);
220
+ this.description = constObservable(undefined);
221
+ this.lastTurnEnd = constObservable(undefined);
222
+ this.gitHubInfo = constObservable(undefined);
223
+ this._onDidChangeOptionGroups = this._register(( new Emitter()));
224
+ this.onDidChangeOptionGroups = this._onDidChangeOptionGroups.event;
225
+ this.selectedOptions = ( new Map());
226
+ this.createdBySession = observableValue(this, undefined);
227
+ this._whenClauseKeys = ( new Set());
228
+ this.modelConfiguration = this._register(( new AutomationModelConfiguration(
229
+ languageModelsService,
230
+ initialAutomationSessionConfiguration?.sessionTemplate
231
+ )));
232
+ this.sessionId = toSessionId(providerId, resource);
233
+ this.providerId = providerId;
234
+ this.sessionType = target;
235
+ this.isQuickChat = constObservable(sessionWorkspace === undefined);
236
+ this.icon = target === CopilotSandboxSessionType.id ? CopilotSandboxSessionType.icon : CopilotCloudSessionType.icon;
237
+ this.createdAt = ( new Date());
238
+ this._updateWhenClauseKeys();
239
+ this._register(this.chatSessionsService.onDidChangeOptionGroups(() => {
240
+ this._updateWhenClauseKeys();
241
+ this._onDidChangeOptionGroups.fire();
242
+ }));
243
+ this._register(this.contextKeyService.onDidChangeContext(e => {
244
+ if (this._whenClauseKeys.size > 0 && e.affectsSome(this._whenClauseKeys)) {
245
+ this._onDidChangeOptionGroups.fire();
246
+ }
247
+ }));
248
+ this._workspaceData.set(sessionWorkspace, undefined);
249
+ this._repoUri = sessionWorkspace?.folders[0]?.root;
250
+ if (this._repoUri) {
251
+ const id = this._repoUri.path.substring(1);
252
+ this.setOption("repositories", {
253
+ id,
254
+ name: id
255
+ });
256
+ }
257
+ this.mainChat = observableValue(this, buildChatFromSession(this));
258
+ }
259
+ setModelId(modelId, source) {
260
+ this._modelId = modelId;
261
+ transaction(tx => {
262
+ this._modelSourceObservable.set(modelId ? source : undefined, tx);
263
+ this._modelIdObservable.set(modelId, tx);
264
+ });
265
+ }
266
+ setTitle(title) {
267
+ this._title.set(title, undefined);
268
+ }
269
+ setStatus(status) {
270
+ this._status.set(status, undefined);
271
+ }
272
+ startPreparation() {
273
+ if (!this._preparationCts.value) {
274
+ this._preparationCts.value = ( new CancellationTokenSource(this.lifetimeToken));
275
+ this.reportPreparationProgress(( localize(5068, "Setting up cloud container")));
276
+ }
277
+ this._preparationActivities++;
278
+ const token = this._preparationCts.value.token;
279
+ const activity = toDisposable(() => {
280
+ if (--this._preparationActivities === 0) {
281
+ this.clearPreparation();
282
+ }
283
+ });
284
+ return {
285
+ object: token,
286
+ dispose: () => activity.dispose()
287
+ };
288
+ }
289
+ reportPreparationProgress(message) {
290
+ const source = this._preparationCts.value;
291
+ if (source && !source.token.isCancellationRequested && this.preparationProgress.get()?.message !== message) {
292
+ this.preparationProgress.set({
293
+ message,
294
+ cancel: () => source.cancel()
295
+ }, undefined);
296
+ }
297
+ }
298
+ clearPreparation() {
299
+ this.preparationProgress.set(undefined, undefined);
300
+ this._preparationCts.clear();
301
+ }
302
+ setArchived(archived) {
303
+ this._isArchived.set(archived, undefined);
304
+ }
305
+ setOption(optionId, value) {
306
+ if (typeof value !== "string") {
307
+ this.selectedOptions.set(optionId, value);
308
+ }
309
+ this.chatSessionsService.setSessionOption(this.resource, optionId, value);
310
+ }
311
+ getModelOptionsSnapshot() {
312
+ const groups = this._getOptionGroups();
313
+ if (!groups) {
314
+ return {
315
+ modelOption: undefined,
316
+ isResolved: false
317
+ };
318
+ }
319
+ const group = groups.find(g => isModelOptionGroup(g));
320
+ if (!group) {
321
+ return {
322
+ modelOption: undefined,
323
+ isResolved: true
324
+ };
325
+ }
326
+ return {
327
+ modelOption: {
328
+ group,
329
+ value: this._getValueForGroup(group)
330
+ },
331
+ isResolved: true
332
+ };
333
+ }
334
+ getOtherOptionGroups() {
335
+ const groups = this._getOptionGroups();
336
+ if (!groups) {
337
+ return [];
338
+ }
339
+ return groups.filter(
340
+ g => !isModelOptionGroup(g) && !isRepositoriesOptionGroup(g) && this._isOptionGroupVisible(g)
341
+ ).map(g => ({
342
+ group: g,
343
+ value: this._getValueForGroup(g)
344
+ }));
345
+ }
346
+ getOptionValue(groupId) {
347
+ return this.selectedOptions.get(groupId);
348
+ }
349
+ setOptionValue(groupId, value) {
350
+ this.setOption(groupId, value);
351
+ }
352
+ _getOptionGroups() {
353
+ return this.chatSessionsService.getOptionGroupsForSessionType(this.target);
354
+ }
355
+ _isOptionGroupVisible(group) {
356
+ if (!group.when) {
357
+ return true;
358
+ }
359
+ const expr = ContextKeyExpr.deserialize(group.when);
360
+ return !expr || this.contextKeyService.contextMatchesRules(expr);
361
+ }
362
+ _updateWhenClauseKeys() {
363
+ this._whenClauseKeys.clear();
364
+ const groups = this._getOptionGroups();
365
+ if (!groups) {
366
+ return;
367
+ }
368
+ for (const group of groups) {
369
+ if (group.when) {
370
+ const expr = ContextKeyExpr.deserialize(group.when);
371
+ if (expr) {
372
+ for (const key of ( expr.keys())) {
373
+ this._whenClauseKeys.add(key);
374
+ }
375
+ }
376
+ }
377
+ }
378
+ }
379
+ _getValueForGroup(group) {
380
+ const selected = this.selectedOptions.get(group.id);
381
+ if (selected) {
382
+ return selected;
383
+ }
384
+ const sessionOption = this.chatSessionsService.getSessionOption(this.resource, group.id);
385
+ if (sessionOption && typeof sessionOption !== "string") {
386
+ return sessionOption;
387
+ }
388
+ if (typeof sessionOption === "string") {
389
+ const item = group.items.find(i => i.id === sessionOption.trim());
390
+ if (item) {
391
+ return item;
392
+ }
393
+ }
394
+ return group.items.find(i => i.default === true) ?? group.items[0];
395
+ }
396
+ update(_session) {}
397
+ };
398
+ RemoteNewSession = ( __decorate([( __param(6, IChatSessionsService)), ( __param(7, IContextKeyService)), ( __param(8, ILanguageModelsService))], RemoteNewSession));
399
+ function toSessionStatus(status) {
400
+ switch (status) {
401
+ case ChatSessionStatus.InProgress:
402
+ return SessionStatus.InProgress;
403
+ case ChatSessionStatus.NeedsInput:
404
+ return SessionStatus.NeedsInput;
405
+ case ChatSessionStatus.Completed:
406
+ return SessionStatus.Completed;
407
+ case ChatSessionStatus.Failed:
408
+ return SessionStatus.Error;
409
+ }
410
+ }
411
+ function githubRemoteRepoLabel(uri) {
412
+ if (uri.scheme !== GITHUB_REMOTE_FILE_SCHEME) {
413
+ return undefined;
414
+ }
415
+ const parts = uri.path.replace(/^\//, "").split("/");
416
+ return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : undefined;
417
+ }
418
+ function resolveGitHubRepositoryId(folder) {
419
+ const gitHubInfo = folder.gitRepository?.gitHubInfo.get();
420
+ if (gitHubInfo) {
421
+ return `${gitHubInfo.owner}/${gitHubInfo.repo}`;
422
+ }
423
+ return githubRemoteRepoLabel(folder.root);
424
+ }
425
+ class AgentSessionAdapter {
426
+ constructor(session, providerId, _gitHubService, _pullRequestIconCache, _logService) {
427
+ this._gitHubService = _gitHubService;
428
+ this._pullRequestIconCache = _pullRequestIconCache;
429
+ this._logService = _logService;
430
+ this._modelSource = observableValue("agentSessionModelSource", undefined);
431
+ this.modelSource = this._modelSource;
432
+ this._pullRequestNumberCache = ( new Map());
433
+ this.sessionId = toSessionId(providerId, session.resource);
434
+ this.resource = session.resource;
435
+ this.providerId = providerId;
436
+ this.sessionType = session.providerType;
437
+ this.application = observableValueOpts({
438
+ owner: this,
439
+ equalsFn: structuralEquals
440
+ }, getSessionApplication(
441
+ typeof session.metadata?.event_type === "string" && session.metadata.event_type ? session.metadata.event_type : this._extractIsExternal(session) ? "github/autopilot" : "vscode"
442
+ ));
443
+ this.icon = CopilotCloudSessionType.icon;
444
+ this.createdAt = ( new Date(session.timing.created));
445
+ const artifacts = this._extractIssueArtifacts(session);
446
+ this._artifacts = observableValueOpts({
447
+ owner: this,
448
+ equalsFn: sessionArtifactsEqual
449
+ }, artifacts);
450
+ this.artifacts = this._artifacts;
451
+ this._baseGitHubInfo = observableValue(this, this._extractGitHubInfo(session, artifacts));
452
+ this._pullRequestBranch = observableValue(this, this._extractPullRequestBranch(session));
453
+ this._pullRequestNumberFromBranch = derived(this, reader => {
454
+ const base = this._baseGitHubInfo.read(reader);
455
+ const branch = this._pullRequestBranch.read(reader);
456
+ if (base?.pullRequest || !base || !branch) {
457
+ return undefined;
458
+ }
459
+ return this._pullRequestNumberForBranch(base.owner, base.repo, branch);
460
+ });
461
+ this.gitHubInfo = derived(this, reader => {
462
+ let info = this._baseGitHubInfo.read(reader);
463
+ if (!info) {
464
+ return undefined;
465
+ }
466
+ if (!info.pullRequest) {
467
+ const pullRequestNumber = this._pullRequestNumberFromBranch.read(reader)?.read(reader).value;
468
+ if (pullRequestNumber === undefined) {
469
+ return info;
470
+ }
471
+ info = {
472
+ ...info,
473
+ pullRequest: {
474
+ number: pullRequestNumber,
475
+ uri: ( URI.parse(`https://github.com/${info.owner}/${info.repo}/pull/${pullRequestNumber}`))
476
+ }
477
+ };
478
+ }
479
+ const pullRequest = info.pullRequest;
480
+ if (!pullRequest) {
481
+ return info;
482
+ }
483
+ if (pullRequest.uri.authority.toLowerCase() !== "github.com") {
484
+ return info;
485
+ }
486
+ const presentation = computePullRequestRefPresentation(reader, this._gitHubService, this._pullRequestIconCache, {
487
+ owner: info.owner,
488
+ repo: info.repo,
489
+ number: pullRequest.number,
490
+ uri: pullRequest.uri,
491
+ icon: pullRequest.icon,
492
+ title: pullRequest.title
493
+ }, computePullRequestIcon(GitHubPullRequestState.Open));
494
+ return {
495
+ ...info,
496
+ pullRequest: {
497
+ ...pullRequest,
498
+ ...presentation
499
+ }
500
+ };
501
+ });
502
+ this._workspace = observableValue(this, this._buildWorkspace(session));
503
+ this.workspace = this._workspace;
504
+ this._title = observableValue(this, session.label);
505
+ this.title = this._title;
506
+ const updatedTime = session.timing.lastRequestEnded ?? session.timing.lastRequestStarted ?? session.timing.created;
507
+ this._updatedAt = observableValue(this, ( new Date(updatedTime)));
508
+ this.updatedAt = this._updatedAt;
509
+ this._status = observableValue(this, toSessionStatus(session.status));
510
+ this.status = this._status;
511
+ this._changes = observableValueOpts({
512
+ owner: this,
513
+ equalsFn: sessionFileChangesEqual
514
+ }, this._extractChanges(session));
515
+ this.changes = this._changes;
516
+ this._changesSummary = observableValueOpts({
517
+ owner: this,
518
+ equalsFn: structuralEquals
519
+ }, this._extractChangesSummary(session));
520
+ this.changesSummary = this._changesSummary;
521
+ this._checkpoints = observableValueOpts({
522
+ owner: this,
523
+ equalsFn: structuralEquals
524
+ }, this._extractCheckpoints(session));
525
+ this.checkpoints = this._checkpoints;
526
+ this._modelId = observableValue(this, undefined);
527
+ this.modelId = this._modelId;
528
+ this.mode = observableValue(this, undefined);
529
+ this.loading = observableValue(this, false);
530
+ this._isArchived = observableValue(this, session.isArchived());
531
+ this.isArchived = this._isArchived;
532
+ this._isRead = observableValue(this, session.isRead());
533
+ this.isRead = this._isRead;
534
+ this._isExternal = observableValue(this, this._extractIsExternal(session));
535
+ this.isExternal = this._isExternal;
536
+ this._description = observableValue(this, this._extractDescription(session));
537
+ this.description = this._description;
538
+ this._lastTurnEnd = observableValue(this, session.timing.lastRequestEnded ? ( new Date(session.timing.lastRequestEnded)) : undefined);
539
+ this.lastTurnEnd = this._lastTurnEnd;
540
+ this.mainChat = observableValue(this, buildChatFromSession(this));
541
+ }
542
+ setModelId(modelId, source) {
543
+ transaction(tx => {
544
+ this._modelSource.set(modelId ? source : undefined, tx);
545
+ this._modelId.set(modelId, tx);
546
+ });
547
+ }
548
+ update(session) {
549
+ let changed = false;
550
+ transaction(tx => {
551
+ const artifacts = this._extractIssueArtifacts(session);
552
+ const gitHubInfo = this._extractGitHubInfo(session, artifacts);
553
+ const pullRequestBranch = this._extractPullRequestBranch(session);
554
+ changed = setIfChanged(this._title, session.label, tx) || changed;
555
+ changed = setIfChanged(this._workspace, this._buildWorkspace(session), tx, sessionWorkspaceEqual) || changed;
556
+ const updatedTime = session.timing.lastRequestEnded ?? session.timing.lastRequestStarted ?? session.timing.created;
557
+ changed = setIfChanged(this._updatedAt, ( new Date(updatedTime)), tx, dateEquals) || changed;
558
+ changed = setIfChanged(this._status, toSessionStatus(session.status), tx) || changed;
559
+ changed = setIfChanged(this._changes, this._extractChanges(session), tx, sessionFileChangesEqual) || changed;
560
+ changed = setIfChanged(
561
+ this._changesSummary,
562
+ this._extractChangesSummary(session),
563
+ tx,
564
+ structuralEquals
565
+ ) || changed;
566
+ changed = setIfChanged(this._checkpoints, this._extractCheckpoints(session), tx, structuralEquals) || changed;
567
+ changed = setIfChanged(this._isArchived, session.isArchived(), tx) || changed;
568
+ changed = setIfChanged(this._isRead, session.isRead(), tx) || changed;
569
+ changed = setIfChanged(this._isExternal, this._extractIsExternal(session), tx) || changed;
570
+ if (typeof session.metadata?.event_type === "string" && session.metadata.event_type) {
571
+ changed = setIfChanged(
572
+ this.application,
573
+ getSessionApplication(session.metadata.event_type),
574
+ tx,
575
+ structuralEquals
576
+ ) || changed;
577
+ }
578
+ changed = setIfChanged(
579
+ this._description,
580
+ this._extractDescription(session),
581
+ tx,
582
+ markdownStringEquals
583
+ ) || changed;
584
+ changed = setIfChanged(this._lastTurnEnd, session.timing.lastRequestEnded ? ( new Date(session.timing.lastRequestEnded)) : undefined, tx, dateEquals) || changed;
585
+ changed = setIfChanged(this._baseGitHubInfo, gitHubInfo, tx, gitHubInfoEqual) || changed;
586
+ changed = setIfChanged(this._artifacts, artifacts, tx, sessionArtifactsEqual) || changed;
587
+ changed = setIfChanged(this._pullRequestBranch, pullRequestBranch, tx) || changed;
588
+ });
589
+ return changed;
590
+ }
591
+ _pullRequestNumberForBranch(owner, repo, branch) {
592
+ const key = `${owner}/${repo}@${branch}`;
593
+ const cached = this._pullRequestNumberCache.get(key);
594
+ if (cached) {
595
+ return cached;
596
+ }
597
+ const lookup = this._gitHubService.findPullRequestNumberByHeadBranch(owner, repo, branch);
598
+ const observable = observableFromPromise(lookup);
599
+ this._pullRequestNumberCache.set(key, observable);
600
+ lookup.then(pullRequestNumber => {
601
+ if (pullRequestNumber === undefined && this._pullRequestNumberCache.get(key) === observable) {
602
+ this._pullRequestNumberCache.delete(key);
603
+ }
604
+ });
605
+ return observable;
606
+ }
607
+ _extractDescription(session) {
608
+ if (!session.description) {
609
+ return undefined;
610
+ }
611
+ return typeof session.description === "string" ? ( new MarkdownString(session.description)) : session.description;
612
+ }
613
+ _extractIsExternal(session) {
614
+ return session.providerType === AgentSessionProviders.Cloud && session.metadata?.external === true;
615
+ }
616
+ _extractIssueArtifacts(session) {
617
+ const linkedIssues = session.metadata?.linkedIssues;
618
+ if (linkedIssues === undefined) {
619
+ return [];
620
+ }
621
+ if (!Array.isArray(linkedIssues)) {
622
+ this._logService.warn("Ignoring invalid linked issues metadata for a cloud session.");
623
+ return [];
624
+ }
625
+ const artifacts = [];
626
+ const seen = ( new Set());
627
+ const issues = linkedIssues;
628
+ for (const issue of issues) {
629
+ if (!issue || typeof issue !== "object" || typeof issue.url !== "string" || typeof issue.title !== "string") {
630
+ this._logService.warn("Ignoring invalid linked issue metadata for a cloud session.");
631
+ continue;
632
+ }
633
+ let link;
634
+ try {
635
+ link = ( URI.parse(issue.url, true));
636
+ } catch (error) {
637
+ this._logService.warn("Ignoring an invalid linked issue URL for a cloud session.", error);
638
+ continue;
639
+ }
640
+ if (link.scheme !== Schemas.https || !link.authority || !/^\/[\w.-]+\/[\w.-]+\/issues\/[1-9]\d*\/?$/.test(link.path)) {
641
+ this._logService.warn("Ignoring an invalid linked issue URL for a cloud session.");
642
+ continue;
643
+ }
644
+ const key = linkKey(issue.url);
645
+ if (( seen.has(key))) {
646
+ continue;
647
+ }
648
+ seen.add(key);
649
+ artifacts.push({
650
+ id: `linked-issue:${key}`,
651
+ kind: SessionArtifactKind.Issue,
652
+ label: issue.title || issue.url,
653
+ isArtifact: true,
654
+ link,
655
+ isGitHub: true
656
+ });
657
+ }
658
+ return artifacts;
659
+ }
660
+ _extractGitHubInfo(session, artifacts) {
661
+ const metadata = session.metadata;
662
+ if (!metadata) {
663
+ return undefined;
664
+ }
665
+ const pullRequestUri = this._extractPullRequestUri(session);
666
+ const pullRequestIdentity = pullRequestUri ? this._extractPullRequestIdentity(pullRequestUri) : undefined;
667
+ const {
668
+ owner,
669
+ repo
670
+ } = pullRequestIdentity ?? this._extractOwnerRepo(session);
671
+ if (!owner || !repo) {
672
+ return undefined;
673
+ }
674
+ const issues = [];
675
+ for (const artifact of artifacts) {
676
+ const issue = artifact.link && parseGitHubIssueUrl(( artifact.link.toString(true)));
677
+ if (issue && artifact.link) {
678
+ issues.push({
679
+ ...issue,
680
+ uri: artifact.link,
681
+ title: artifact.label
682
+ });
683
+ }
684
+ }
685
+ const issueInfo = issues.length ? {
686
+ issues
687
+ } : {};
688
+ if (!pullRequestUri || !pullRequestIdentity) {
689
+ return {
690
+ owner,
691
+ repo,
692
+ ...issueInfo
693
+ };
694
+ }
695
+ const icon = this._extractPullRequestStateIcon(session);
696
+ const baseRefOid = typeof metadata.baseRefOid === "string" ? metadata.baseRefOid : undefined;
697
+ const headRefOid = typeof metadata.headRefOid === "string" ? metadata.headRefOid : undefined;
698
+ return {
699
+ owner,
700
+ repo,
701
+ ...issueInfo,
702
+ pullRequest: {
703
+ number: pullRequestIdentity.number,
704
+ uri: pullRequestUri,
705
+ icon,
706
+ baseRefOid,
707
+ headRefOid
708
+ }
709
+ };
710
+ }
711
+ _extractPullRequestBranch(session) {
712
+ if (typeof session.metadata?.host === "string" && session.metadata.host.toLowerCase() !== "github.com") {
713
+ return undefined;
714
+ }
715
+ return typeof session.metadata?.branch === "string" ? session.metadata.branch : undefined;
716
+ }
717
+ _extractPullRequestIdentity(pullRequestUri) {
718
+ const match = /^\/(?<owner>[^/]+)\/(?<repo>[^/]+)\/pull\/(?<number>\d+)\/?$/.exec(pullRequestUri.path);
719
+ if (!match?.groups) {
720
+ return undefined;
721
+ }
722
+ return {
723
+ owner: decodeURIComponent(match.groups.owner),
724
+ repo: decodeURIComponent(match.groups.repo),
725
+ number: parseInt(match.groups.number, 10)
726
+ };
727
+ }
728
+ _extractOwnerRepo(session) {
729
+ const metadata = session.metadata;
730
+ if (!metadata) {
731
+ return {
732
+ owner: undefined,
733
+ repo: undefined
734
+ };
735
+ }
736
+ if (typeof metadata.owner === "string" && typeof metadata.name === "string") {
737
+ return {
738
+ owner: metadata.owner,
739
+ repo: metadata.name
740
+ };
741
+ }
742
+ if (typeof metadata.repositoryNwo === "string") {
743
+ const parts = metadata.repositoryNwo.split("/");
744
+ if (parts.length === 2) {
745
+ return {
746
+ owner: parts[0],
747
+ repo: parts[1]
748
+ };
749
+ }
750
+ }
751
+ return {
752
+ owner: undefined,
753
+ repo: undefined
754
+ };
755
+ }
756
+ _extractPullRequestStateIcon(session) {
757
+ const metadata = session.metadata;
758
+ const state = metadata?.pullRequestState;
759
+ if (typeof state === "string") {
760
+ return computePullRequestIcon(state);
761
+ }
762
+ return undefined;
763
+ }
764
+ _extractPullRequestUri(session) {
765
+ return getAgentSessionPullRequestUri(session);
766
+ }
767
+ _extractChanges(session) {
768
+ return session.changes && !isChangesSummary(session.changes) ? session.changes : [];
769
+ }
770
+ _extractChangesSummary(session) {
771
+ if (!isChangesSummary(session.changes)) {
772
+ return undefined;
773
+ }
774
+ return {
775
+ files: session.changes.files,
776
+ additions: session.changes.insertions,
777
+ deletions: session.changes.deletions
778
+ };
779
+ }
780
+ _extractCheckpoints(session) {
781
+ const metadata = session.metadata;
782
+ if (typeof metadata?.firstCheckpointRef !== "string" || typeof metadata?.lastCheckpointRef !== "string") {
783
+ return undefined;
784
+ }
785
+ return {
786
+ firstCheckpointRef: metadata.firstCheckpointRef,
787
+ lastCheckpointRef: metadata.lastCheckpointRef
788
+ };
789
+ }
790
+ _buildWorkspace(session) {
791
+ const repoUri = this._extractRepositoryUri(session);
792
+ const repoUriResolved = repoUri ?? ( URI.parse("unknown:///"));
793
+ const gitRepository = {
794
+ uri: repoUriResolved,
795
+ workTreeUri: undefined,
796
+ isRepository: constObservable(repoUri !== undefined),
797
+ baseBranchName: undefined,
798
+ gitHubInfo: this.gitHubInfo
799
+ };
800
+ const folder = {
801
+ root: repoUriResolved,
802
+ workingDirectory: repoUriResolved,
803
+ name: basename(repoUriResolved),
804
+ description: undefined,
805
+ gitRepository
806
+ };
807
+ return {
808
+ uri: repoUriResolved,
809
+ label: githubRemoteRepoLabel(repoUriResolved) ?? getRepositoryName(session) ?? basename(repoUriResolved),
810
+ icon: repoUri ? Codicon.repo : Codicon.folder,
811
+ group: repoUri ? SESSION_WORKSPACE_GROUP_GITHUB : SESSION_WORKSPACE_GROUP_LOCAL,
812
+ folders: [folder],
813
+ requiresWorkspaceTrust: false,
814
+ isVirtualWorkspace: true
815
+ };
816
+ }
817
+ _extractRepositoryUri(session) {
818
+ const metadata = session.metadata;
819
+ if (typeof metadata?.owner !== "string" || typeof metadata.name !== "string") {
820
+ return undefined;
821
+ }
822
+ const branch = typeof metadata.branch === "string" ? metadata.branch : "HEAD";
823
+ return ( URI.from({
824
+ scheme: GITHUB_REMOTE_FILE_SCHEME,
825
+ authority: "github",
826
+ path: `/${metadata.owner}/${metadata.name}/${encodeURIComponent(branch)}`
827
+ }));
828
+ }
829
+ }
830
+ let CopilotChatSessionsProvider = class CopilotChatSessionsProvider extends Disposable {
831
+ static {
832
+ CopilotChatSessionsProvider_1 = this;
833
+ }
834
+ static {
835
+ this.SANDBOX_MODEL_WAIT_MS = 30_000;
836
+ }
837
+ get id() {
838
+ return this.providerMode === "sandbox" ? CLOUD_SANDBOX_CREATION_PROVIDER_ID : COPILOT_PROVIDER_ID;
839
+ }
840
+ get label() {
841
+ return this.providerMode === "sandbox" ? ( localize(5069, "GitHub Sandboxes")) : ( localize(5070, "Copilot Chat"));
842
+ }
843
+ get sessionTypes() {
844
+ return this.providerMode === "sandbox" ? [CopilotSandboxSessionType] : [CopilotCloudSessionType];
845
+ }
846
+ get supportsLocalWorkspaces() {
847
+ return this.providerMode !== "sandbox";
848
+ }
849
+ get supportsAutomationSessionConfiguration() {
850
+ return this.providerMode === "default" && this.automations?.enabled.get() === true;
851
+ }
852
+ get supportsQuickChats() {
853
+ return isCloudSandboxEnabled(this.configurationService) && !this.configurationService.getValue(ChatAIDisabledSettingId);
854
+ }
855
+ constructor(
856
+ providerMode,
857
+ agentSessionsService,
858
+ chatService,
859
+ chatSessionsService,
860
+ commandService,
861
+ instantiationService,
862
+ languageModelsService,
863
+ configurationService,
864
+ logService,
865
+ notificationService,
866
+ gitHubService,
867
+ pullRequestIconCache,
868
+ labelService,
869
+ uriIdentityService,
870
+ fileService,
871
+ pathService,
872
+ storageService
873
+ ) {
874
+ super();
875
+ this.providerMode = providerMode;
876
+ this.agentSessionsService = agentSessionsService;
877
+ this.chatService = chatService;
878
+ this.chatSessionsService = chatSessionsService;
879
+ this.commandService = commandService;
880
+ this.instantiationService = instantiationService;
881
+ this.languageModelsService = languageModelsService;
882
+ this.configurationService = configurationService;
883
+ this.logService = logService;
884
+ this.notificationService = notificationService;
885
+ this.gitHubService = gitHubService;
886
+ this.pullRequestIconCache = pullRequestIconCache;
887
+ this.labelService = labelService;
888
+ this.uriIdentityService = uriIdentityService;
889
+ this.fileService = fileService;
890
+ this.pathService = pathService;
891
+ this.storageService = storageService;
892
+ this.environment = {
893
+ id: "cloud",
894
+ label: ( localize(5071, "Cloud"))
895
+ };
896
+ this.icon = Codicon.copilot;
897
+ this.order = 0;
898
+ this._onDidChangeSessionTypes = this._register(( new Emitter()));
899
+ this.onDidChangeSessionTypes = this._onDidChangeSessionTypes.event;
900
+ this._onDidChangeCapabilities = this._register(( new Emitter()));
901
+ this.onDidChangeCapabilities = this._onDidChangeCapabilities.event;
902
+ this._onDidChangeSessions = this._register(( new Emitter()));
903
+ this.onDidChangeSessions = this._onDidChangeSessions.event;
904
+ this._onDidReplaceSession = this._register(( new Emitter()));
905
+ this.onDidReplaceSession = this._onDidReplaceSession.event;
906
+ this._sessionCache = ( new Map());
907
+ this._inFlightCommits = ( new Set());
908
+ this._sandboxSends = ( new Set());
909
+ this._repositoryPicker = this._register(( new MutableDisposable()));
910
+ this._sandboxCatalog = this._register(( new MutableDisposable()));
911
+ this._onDidChangeSandboxModels = this._register(( new Emitter()));
912
+ this._sandboxConfigs = ( new Map());
913
+ this._onDidChangeSessionConfig = this._register(( new Emitter()));
914
+ this.onDidChangeSessionConfig = this._onDidChangeSessionConfig.event;
915
+ this.sessionConfig = this;
916
+ this._sessionWrapperCache = ( new Map());
917
+ this._localGitRepositoryState = ( new Map());
918
+ this._localGitRepositoryResolutionStarted = ( new Set());
919
+ this._newSessions = this._register(( new DisposableMap()));
920
+ this._createdBySessions = ( new Map());
921
+ this._storedCreatedBySessions = ( new Map());
922
+ this._loadCreatedBySessions();
923
+ if (providerMode === "default") {
924
+ this.automations = this._register(
925
+ this.instantiationService.createInstance(CloudAutomationStore, this.id, CopilotCloudSessionType.id, async uri => {
926
+ if (uri.scheme === GITHUB_REMOTE_FILE_SCHEME) {
927
+ return uri;
928
+ }
929
+ if (uri.scheme !== Schemas.file) {
930
+ return undefined;
931
+ }
932
+ const repository = await resolveGitRepositoryFromGitConfig(this.fileService, uri, ["github.com"]);
933
+ return repository?.gitHub ? ( URI.from({
934
+ scheme: GITHUB_REMOTE_FILE_SCHEME,
935
+ authority: "github",
936
+ path: `/${repository.gitHub.owner}/${repository.gitHub.repo}/HEAD`
937
+ })) : undefined;
938
+ })
939
+ );
940
+ }
941
+ this._register(Event.filter(
942
+ this.configurationService.onDidChangeConfiguration,
943
+ event => event.affectsConfiguration(UNIFIED_WORKSPACE_PICKER_SETTING)
944
+ )(() => this._onDidChangeSessionTypes.fire()));
945
+ this._register(this.configurationService.onDidChangeConfiguration(event => {
946
+ const sandboxChanged = event.affectsConfiguration(CloudSandboxEnabledSettingId) || event.affectsConfiguration(RemoteAgentHostsEnabledSettingId);
947
+ if (sandboxChanged || event.affectsConfiguration(ChatAIDisabledSettingId)) {
948
+ this._onDidChangeSessionTypes.fire();
949
+ this._onDidChangeCapabilities.fire();
950
+ }
951
+ if (sandboxChanged) {
952
+ if (this._newSessions.size > 0 && this._usesSandbox()) {
953
+ this._getSandboxCatalog().load();
954
+ }
955
+ for (const sessionId of ( this._newSessions.keys())) {
956
+ this._onDidChangeSessionConfig.fire(sessionId);
957
+ }
958
+ this._onDidChangeSandboxModels.fire();
959
+ }
960
+ if (event.affectsConfiguration(ChatConfiguration.DefaultConfiguration) || event.affectsConfiguration(ChatConfiguration.GlobalAutoApprove)) {
961
+ for (const [sessionId, config] of this._sandboxConfigs) {
962
+ const refreshed = createCloudSandboxSessionConfig(this.configurationService);
963
+ for (const [key, value] of Object.entries(config.values)) {
964
+ if (refreshed.schema.properties[key]?.enum?.some(candidate => candidate === value)) {
965
+ refreshed.values[key] = value;
966
+ }
967
+ }
968
+ this._sandboxConfigs.set(sessionId, refreshed);
969
+ this._onDidChangeSessionConfig.fire(sessionId);
970
+ }
971
+ }
972
+ }));
973
+ this._register(this.agentSessionsService.model.onDidChangeSessions(() => {
974
+ this._refreshSessionCache();
975
+ }));
976
+ this._ensureSessionCache();
977
+ }
978
+ get browseActions() {
979
+ const useConsolidatedRemoteWorkspaces = this.configurationService.getValue(UNIFIED_WORKSPACE_PICKER_SETTING);
980
+ const isSandbox = this.providerMode === "sandbox";
981
+ const repositoryAction = {
982
+ label: isSandbox ? ( localize(5072, "Choose Repository...")) : useConsolidatedRemoteWorkspaces ? ( localize(5073, "Work in Repository...")) : ( localize(5074, "Repository...")),
983
+ group: SESSION_WORKSPACE_GROUP_GITHUB,
984
+ icon: isSandbox || useConsolidatedRemoteWorkspaces ? Codicon.github : Codicon.library,
985
+ providerId: this.id,
986
+ attachesContext: false,
987
+ supportsContextAttachment: !isSandbox,
988
+ run: () => this._browseForRepository()
989
+ };
990
+ if (isSandbox) {
991
+ return [repositoryAction];
992
+ }
993
+ return [repositoryAction, {
994
+ label: ( localize(5075, "Issue...")),
995
+ group: SESSION_WORKSPACE_GROUP_GITHUB,
996
+ icon: Codicon.issues,
997
+ providerId: this.id,
998
+ attachesContext: true,
999
+ run: workspace => this._browseForGitHubContext(OPEN_ISSUE_COMMAND, Codicon.issues, workspace)
1000
+ }, {
1001
+ label: ( localize(5076, "Pull Request...")),
1002
+ group: SESSION_WORKSPACE_GROUP_GITHUB,
1003
+ icon: useConsolidatedRemoteWorkspaces ? Codicon.github : Codicon.gitPullRequest,
1004
+ providerId: this.id,
1005
+ attachesContext: true,
1006
+ run: workspace => this._browseForGitHubContext(
1007
+ OPEN_PULL_REQUEST_COMMAND,
1008
+ useConsolidatedRemoteWorkspaces ? Codicon.github : Codicon.gitPullRequest,
1009
+ workspace
1010
+ )
1011
+ }];
1012
+ }
1013
+ getSessionTypes(workspaceUri) {
1014
+ if (this.providerMode === "sandbox") {
1015
+ return this.resolveWorkspace(workspaceUri) ? [CopilotSandboxSessionType] : [];
1016
+ }
1017
+ if (workspaceUri.scheme === GITHUB_REMOTE_FILE_SCHEME || workspaceUri.scheme === SessionType.CopilotCloud) {
1018
+ return [CopilotCloudSessionType];
1019
+ }
1020
+ if (this.configurationService.getValue(UNIFIED_WORKSPACE_PICKER_SETTING) && workspaceUri.scheme === Schemas.file) {
1021
+ const gitRepository = this._getLocalGitRepository(workspaceUri);
1022
+ gitRepository.resolveGitHubInfo?.();
1023
+ if (gitRepository.gitHubInfo.get()) {
1024
+ return [CopilotCloudSessionType];
1025
+ }
1026
+ }
1027
+ return [];
1028
+ }
1029
+ getSessions() {
1030
+ this._ensureSessionCache();
1031
+ return Array.from(( this._sessionCache.values()), chat => this._chatToSession(chat));
1032
+ }
1033
+ _createdBySession(resource) {
1034
+ const key = ( resource.toString());
1035
+ let createdBySession = this._createdBySessions.get(key);
1036
+ if (!createdBySession) {
1037
+ createdBySession = observableValue(this, this._storedCreatedBySessions.get(key));
1038
+ this._createdBySessions.set(key, createdBySession);
1039
+ }
1040
+ return createdBySession;
1041
+ }
1042
+ _setCreatedBySession(resource, reference) {
1043
+ const key = ( resource.toString());
1044
+ this._createdBySession(resource).set(reference, undefined);
1045
+ this._storedCreatedBySessions.set(key, reference);
1046
+ this._saveCreatedBySessions();
1047
+ }
1048
+ _deleteCreatedBySession(resource) {
1049
+ const key = ( resource.toString());
1050
+ this._createdBySessions.delete(key);
1051
+ if (this._storedCreatedBySessions.delete(key)) {
1052
+ this._saveCreatedBySessions();
1053
+ }
1054
+ }
1055
+ _loadCreatedBySessions() {
1056
+ const raw = this.storageService.get(STORAGE_KEY_CREATED_BY_SESSIONS, StorageScope.PROFILE);
1057
+ if (!raw) {
1058
+ return;
1059
+ }
1060
+ try {
1061
+ const stored = JSON.parse(raw);
1062
+ for (const [resource, reference] of Object.entries(stored)) {
1063
+ this._storedCreatedBySessions.set(resource, {
1064
+ session: ( URI.parse(reference.session)),
1065
+ chat: reference.chat ? ( URI.parse(reference.chat)) : undefined,
1066
+ turnId: reference.turnId
1067
+ });
1068
+ }
1069
+ } catch (error) {
1070
+ this.logService.error(
1071
+ "[CopilotChatSessionsProvider] Failed to restore session creation references.",
1072
+ error
1073
+ );
1074
+ }
1075
+ }
1076
+ _saveCreatedBySessions() {
1077
+ const stored = {};
1078
+ for (const [resource, reference] of this._storedCreatedBySessions) {
1079
+ stored[resource] = {
1080
+ session: ( reference.session.toString()),
1081
+ chat: reference.chat?.toString(),
1082
+ turnId: reference.turnId
1083
+ };
1084
+ }
1085
+ this.storageService.store(
1086
+ STORAGE_KEY_CREATED_BY_SESSIONS,
1087
+ JSON.stringify(stored),
1088
+ StorageScope.PROFILE,
1089
+ StorageTarget.MACHINE
1090
+ );
1091
+ }
1092
+ _clearCurrentNewSessionIfMatch(session, leak) {
1093
+ if (this._newSessions.get(session.sessionId) === session) {
1094
+ this._sandboxConfigs.delete(session.sessionId);
1095
+ if (leak) {
1096
+ this._newSessions.deleteAndLeak(session.sessionId);
1097
+ } else {
1098
+ this._newSessions.deleteAndDispose(session.sessionId);
1099
+ }
1100
+ }
1101
+ }
1102
+ deleteNewSession(sessionId) {
1103
+ this._sandboxConfigs.delete(sessionId);
1104
+ if (( this._newSessions.has(sessionId))) {
1105
+ this._newSessions.deleteAndDispose(sessionId);
1106
+ this._sessionWrapperCache.delete(sessionId);
1107
+ }
1108
+ }
1109
+ getSession(sessionId) {
1110
+ const newSession = this._newSessions.get(sessionId);
1111
+ if (newSession) {
1112
+ return newSession;
1113
+ }
1114
+ return this._findChatSession(sessionId);
1115
+ }
1116
+ createNewSession(workspaceUri, sessionTypeId, options) {
1117
+ return this._createDraftSession(workspaceUri, sessionTypeId, options);
1118
+ }
1119
+ _createDraftSession(workspaceUri, sessionTypeId, options) {
1120
+ if (this.providerMode === "sandbox") {
1121
+ if (!isCloudSandboxEnabled(this.configurationService) || this.configurationService.getValue(ChatAIDisabledSettingId)) {
1122
+ throw ( new Error(( localize(5077, "GitHub sandbox sessions are not enabled."))));
1123
+ }
1124
+ if (sessionTypeId !== CopilotSandboxSessionType.id || options?.automationConfiguration || options?.isAutomationDraft) {
1125
+ throw ( new Error(( localize(
1126
+ 5078,
1127
+ "This configuration is not supported for a new GitHub sandbox session."
1128
+ ))));
1129
+ }
1130
+ }
1131
+ const workspace = workspaceUri ? this.resolveWorkspace(workspaceUri) : undefined;
1132
+ if (workspaceUri && !workspace) {
1133
+ throw ( new Error(`Cannot resolve workspace for URI: ${( workspaceUri.toString())}`));
1134
+ }
1135
+ const automationConfiguration = options?.automationConfiguration;
1136
+ assertAutomationSessionTemplate(automationConfiguration?.sessionTemplate);
1137
+ if (this.providerMode !== "sandbox" && sessionTypeId !== CopilotCloudSessionType.id) {
1138
+ throw ( new Error(`Unsupported session type '${sessionTypeId}'`));
1139
+ }
1140
+ const cloudWorkspace = !workspace || workspaceUri?.scheme === GITHUB_REMOTE_FILE_SCHEME ? workspace : this._getCloudWorkspaceForLocalRepository(workspace);
1141
+ if (workspace && !cloudWorkspace) {
1142
+ throw ( new Error("Copilot Cloud sessions require a local workspace with a GitHub remote"));
1143
+ }
1144
+ const target = this.providerMode === "sandbox" ? CopilotSandboxSessionType.id : AgentSessionProviders.Cloud;
1145
+ const resource = ( URI.from({
1146
+ scheme: target,
1147
+ path: `/untitled-${generateUuid()}`
1148
+ }));
1149
+ const session = this.instantiationService.createInstance(
1150
+ RemoteNewSession,
1151
+ resource,
1152
+ cloudWorkspace,
1153
+ target,
1154
+ this.id,
1155
+ automationConfiguration,
1156
+ options?.isAutomationDraft === true
1157
+ );
1158
+ session.setCreatedBySession(options?.createdBySession);
1159
+ this._newSessions.set(session.sessionId, session);
1160
+ if (this._usesSandbox(session)) {
1161
+ this._getSandboxCatalog().load();
1162
+ }
1163
+ this._onDidChangeSessionConfig.fire(session.sessionId);
1164
+ this._onDidChangeSandboxModels.fire();
1165
+ try {
1166
+ this._applyAutomationSessionConfiguration(session, automationConfiguration);
1167
+ return this._chatToSession(session);
1168
+ } catch (error) {
1169
+ this._newSessions.deleteAndDispose(session.sessionId);
1170
+ throw error;
1171
+ }
1172
+ }
1173
+ _getCloudWorkspaceForLocalRepository(workspace) {
1174
+ const gitHubInfo = workspace.folders.map(folder => folder.gitRepository?.gitHubInfo.get()).find(info => info !== undefined);
1175
+ if (!gitHubInfo) {
1176
+ return undefined;
1177
+ }
1178
+ const root = ( URI.from({
1179
+ scheme: GITHUB_REMOTE_FILE_SCHEME,
1180
+ authority: "github",
1181
+ path: `/${gitHubInfo.owner}/${gitHubInfo.repo}/HEAD`
1182
+ }));
1183
+ return this.resolveWorkspace(root);
1184
+ }
1185
+ getAutomationModelConfiguration(sessionId) {
1186
+ return this._newSessions.get(sessionId)?.modelConfiguration;
1187
+ }
1188
+ async getAutomationSessionConfiguration(sessionId) {
1189
+ const session = this._newSessions.get(sessionId);
1190
+ if (!session) {
1191
+ return undefined;
1192
+ }
1193
+ const modelId = session.modelId.get();
1194
+ const modelConfiguration = session.modelConfiguration.captureModelConfiguration(modelId);
1195
+ const initialConfiguration = session.initialAutomationSessionConfiguration;
1196
+ const initialTemplate = initialConfiguration?.sessionTemplate;
1197
+ if (this.automations?.enabled.get()) {
1198
+ if (modelConfiguration !== undefined || initialConfiguration?.mode !== undefined || initialConfiguration?.permissionLevel !== undefined) {
1199
+ throw ( new Error(( localize(
1200
+ 5079,
1201
+ "Cloud automations do not support local mode, approval, or model-specific settings. Remove those settings before saving."
1202
+ ))));
1203
+ }
1204
+ return {
1205
+ sessionTemplate: {
1206
+ ...(modelId !== undefined ? {
1207
+ modelId
1208
+ } : {}),
1209
+ ...(initialTemplate?.config !== undefined ? {
1210
+ config: initialTemplate.config
1211
+ } : {})
1212
+ }
1213
+ };
1214
+ }
1215
+ const initialMode = initialConfiguration?.mode ?? initialTemplate?.config?.[SessionConfigKey.Mode];
1216
+ const mode = typeof initialMode === "string" ? initialMode : undefined;
1217
+ const initialPermissionLevel = initialConfiguration?.permissionLevel ?? initialTemplate?.config?.[SessionConfigKey.AutoApprove];
1218
+ const permissionLevel = isChatPermissionLevel(initialPermissionLevel) ? initialPermissionLevel : ChatPermissionLevel.Default;
1219
+ const config = {
1220
+ ...initialTemplate?.config
1221
+ };
1222
+ if (mode) {
1223
+ config[SessionConfigKey.Mode] = mode;
1224
+ } else {
1225
+ delete config[SessionConfigKey.Mode];
1226
+ }
1227
+ config[SessionConfigKey.AutoApprove] = permissionLevel;
1228
+ const sessionTemplate = {
1229
+ ...(modelId ? {
1230
+ modelId
1231
+ } : {}),
1232
+ ...(modelConfiguration !== undefined ? {
1233
+ modelConfiguration
1234
+ } : {}),
1235
+ ...(( Object.keys(config)).length > 0 ? {
1236
+ config
1237
+ } : {})
1238
+ };
1239
+ return {
1240
+ sessionTemplate,
1241
+ modelId,
1242
+ mode,
1243
+ permissionLevel
1244
+ };
1245
+ }
1246
+ createQuickChat(sessionTypeId, options) {
1247
+ if (!this.supportsQuickChats) {
1248
+ throw ( new Error(( localize(5077, "GitHub sandbox sessions are not enabled."))));
1249
+ }
1250
+ return this._createDraftSession(undefined, sessionTypeId, options);
1251
+ }
1252
+ _applyAutomationSessionConfiguration(session, configuration) {
1253
+ if (!configuration) {
1254
+ return;
1255
+ }
1256
+ const template = configuration.sessionTemplate;
1257
+ if (template?.agent) {
1258
+ throw ( new Error(( localize(
1259
+ 5080,
1260
+ "This provider does not support custom agents in Automation session templates."
1261
+ ))));
1262
+ }
1263
+ const modelId = template?.modelId ?? configuration.modelId;
1264
+ if (modelId) {
1265
+ session.setModelId(modelId, ChatModelSource.Chosen);
1266
+ }
1267
+ }
1268
+ get onDidChangeModels() {
1269
+ return Event.signal(Event.any(
1270
+ this._onDidChangeSandboxModels.event,
1271
+ this.languageModelsService.onDidChangeLanguageModels,
1272
+ this.chatSessionsService.onDidChangeOptionGroups
1273
+ ));
1274
+ }
1275
+ getModelsSnapshot(sessionId, desiredModelId) {
1276
+ const draft = this._newSessions.get(sessionId);
1277
+ if (draft && this._usesSandbox(draft)) {
1278
+ return this._sandboxModelsSnapshot(desiredModelId);
1279
+ }
1280
+ const session = this.getSession(sessionId);
1281
+ if (session instanceof RemoteNewSession) {
1282
+ const {
1283
+ modelOption,
1284
+ isResolved
1285
+ } = session.getModelOptionsSnapshot();
1286
+ const models = modelOption?.group.items.map(item => this._toSyntheticModel(item)) ?? [];
1287
+ return {
1288
+ models,
1289
+ desiredModelResolution: resolveModelIdentifier(models, desiredModelId, isResolved),
1290
+ modelTarget: session.sessionType
1291
+ };
1292
+ }
1293
+ const sessionType = session?.sessionType;
1294
+ if (!sessionType) {
1295
+ return {
1296
+ models: [],
1297
+ desiredModelResolution: resolveModelIdentifier([], desiredModelId, false),
1298
+ modelTarget: undefined
1299
+ };
1300
+ }
1301
+ const allModels = getRegisteredLanguageModels(this.languageModelsService);
1302
+ const models = allModels.filter(model => model.metadata.targetChatSessionType === sessionType);
1303
+ return {
1304
+ models,
1305
+ desiredModelResolution: resolveModelIdentifierFromLanguageModels(models, desiredModelId, this.languageModelsService, allModels),
1306
+ modelTarget: sessionType
1307
+ };
1308
+ }
1309
+ getModelsSnapshotForCreation(_workspaceUri, sessionTypeId, desiredModelId) {
1310
+ if (this.providerMode !== "sandbox" && sessionTypeId !== CopilotCloudSessionType.id) {
1311
+ return {
1312
+ models: [],
1313
+ desiredModelResolution: resolveModelIdentifier([], desiredModelId, true),
1314
+ modelTarget: undefined
1315
+ };
1316
+ }
1317
+ if (this._usesSandbox()) {
1318
+ return this._sandboxModelsSnapshot(desiredModelId);
1319
+ }
1320
+ const group = this.chatSessionsService.getOptionGroupsForSessionType(AgentSessionProviders.Cloud)?.find(candidate => isModelOptionGroup(candidate));
1321
+ const models = group?.items.map(item => this._toSyntheticModel(item)) ?? [];
1322
+ return {
1323
+ models,
1324
+ desiredModelResolution: resolveModelIdentifier(models, desiredModelId, group !== undefined),
1325
+ modelTarget: AgentSessionProviders.Cloud
1326
+ };
1327
+ }
1328
+ getModelPickerOptions(sessionId) {
1329
+ const draft = this._newSessions.get(sessionId);
1330
+ if (draft && this._usesSandbox(draft)) {
1331
+ return {
1332
+ showUnavailableFeatured: false,
1333
+ showManageModelsAction: false,
1334
+ showAutoModel: false
1335
+ };
1336
+ }
1337
+ const sessionType = this.getSession(sessionId)?.sessionType;
1338
+ const showAutoModel = !sessionType || this.chatSessionsService.supportsAutoModelForSessionType(sessionType);
1339
+ return {
1340
+ showUnavailableFeatured: false,
1341
+ showManageModelsAction: false,
1342
+ showAutoModel
1343
+ };
1344
+ }
1345
+ _usesSandbox(session) {
1346
+ return !session?.isAutomationDraft && (session?.isQuickChat.get() === true || this.providerMode === "sandbox" || isCloudSandboxEnabled(this.configurationService));
1347
+ }
1348
+ _getSandboxCatalog() {
1349
+ if (!this._sandboxCatalog.value) {
1350
+ const catalog = this.instantiationService.createInstance(
1351
+ CloudSandboxModels,
1352
+ CopilotSandboxSessionType.id,
1353
+ `${this.id}-sandbox-models`,
1354
+ undefined
1355
+ );
1356
+ this._sandboxCatalog.value = catalog;
1357
+ this._register(catalog.onDidChange(() => this._onDidChangeSandboxModels.fire()));
1358
+ }
1359
+ return this._sandboxCatalog.value;
1360
+ }
1361
+ _sandboxModelsSnapshot(desiredModelId) {
1362
+ const catalog = this._getSandboxCatalog();
1363
+ catalog.load();
1364
+ return {
1365
+ models: catalog.models,
1366
+ desiredModelResolution: resolveModelIdentifier(catalog.models, desiredModelId, catalog.ready),
1367
+ modelTarget: CopilotSandboxSessionType.id
1368
+ };
1369
+ }
1370
+ getSessionConfig(sessionId) {
1371
+ const session = this._newSessions.get(sessionId);
1372
+ if (!session || !this._usesSandbox(session)) {
1373
+ return undefined;
1374
+ }
1375
+ let config = this._sandboxConfigs.get(sessionId);
1376
+ if (!config) {
1377
+ config = createCloudSandboxSessionConfig(this.configurationService);
1378
+ this._sandboxConfigs.set(sessionId, config);
1379
+ }
1380
+ return config;
1381
+ }
1382
+ getCreateSessionConfig(sessionId) {
1383
+ return this.getSessionConfig(sessionId)?.values;
1384
+ }
1385
+ isSessionConfigResolving(_sessionId) {
1386
+ return constObservable(false);
1387
+ }
1388
+ async setSessionConfigValue(sessionId, property, value) {
1389
+ const config = this.getSessionConfig(sessionId);
1390
+ if (!config) {
1391
+ throw ( new Error("Cloud sandbox draft configuration is unavailable."));
1392
+ }
1393
+ validateSessionConfigWrite(config.schema, config.values, property, value, true);
1394
+ this._sandboxConfigs.set(sessionId, {
1395
+ ...config,
1396
+ values: {
1397
+ ...config.values,
1398
+ [property]: value
1399
+ }
1400
+ });
1401
+ this._onDidChangeSessionConfig.fire(sessionId);
1402
+ }
1403
+ _toSyntheticModel(item) {
1404
+ const modelMetadata = item.modelMetadata;
1405
+ return {
1406
+ identifier: item.id,
1407
+ metadata: {
1408
+ extension: ( new ExtensionIdentifier("")),
1409
+ name: modelMetadata?.name ?? item.name,
1410
+ id: modelMetadata?.id ?? item.id,
1411
+ vendor: COPILOT_VENDOR_ID,
1412
+ version: modelMetadata?.version ?? "",
1413
+ family: modelMetadata?.family ?? "",
1414
+ tooltip: modelMetadata?.tooltip ?? item.tooltip,
1415
+ pricing: modelMetadata?.pricing,
1416
+ multiplierNumeric: modelMetadata?.multiplierNumeric,
1417
+ inputCost: modelMetadata?.inputCost,
1418
+ outputCost: modelMetadata?.outputCost,
1419
+ cacheCost: modelMetadata?.cacheCost,
1420
+ cacheWriteCost: modelMetadata?.cacheWriteCost,
1421
+ longContextInputCost: modelMetadata?.longContextInputCost,
1422
+ longContextOutputCost: modelMetadata?.longContextOutputCost,
1423
+ longContextCacheCost: modelMetadata?.longContextCacheCost,
1424
+ longContextCacheWriteCost: modelMetadata?.longContextCacheWriteCost,
1425
+ priceCategory: modelMetadata?.priceCategory,
1426
+ promo: modelMetadata?.promo,
1427
+ maxInputTokens: modelMetadata?.maxInputTokens ?? 0,
1428
+ maxOutputTokens: modelMetadata?.maxOutputTokens ?? 0,
1429
+ maxContextWindowTokens: modelMetadata?.maxContextWindowTokens,
1430
+ capabilities: modelMetadata?.capabilities ? {
1431
+ vision: modelMetadata.capabilities.vision,
1432
+ toolCalling: modelMetadata.capabilities.toolCalling
1433
+ } : undefined,
1434
+ isUserSelectable: true,
1435
+ isDefaultForLocation: {}
1436
+ }
1437
+ };
1438
+ }
1439
+ setModel(sessionId, chatResource, modelId, source) {
1440
+ const newSession = this._newSessions.get(sessionId);
1441
+ if (newSession) {
1442
+ const previousModelId = newSession.modelId.get();
1443
+ if (previousModelId && previousModelId !== modelId) {
1444
+ const resolution = this.getModelsSnapshot(sessionId, previousModelId).desiredModelResolution;
1445
+ if (resolution.kind === "available" && resolution.model.identifier === modelId) {
1446
+ newSession.modelConfiguration.rebindModelConfiguration(previousModelId, modelId);
1447
+ }
1448
+ }
1449
+ newSession.setModelId(modelId, source);
1450
+ const {
1451
+ modelOption
1452
+ } = newSession.getModelOptionsSnapshot();
1453
+ const item = modelOption?.group.items.find(i => i.id === modelId);
1454
+ if (item) {
1455
+ newSession.setOptionValue(modelOption.group.id, item);
1456
+ }
1457
+ return;
1458
+ }
1459
+ this._ensureSessionCache();
1460
+ const chatSession = this._sessionCache.get(( chatResource.toString())) ?? this._findChatSession(sessionId);
1461
+ chatSession?.setModelId(modelId, source);
1462
+ }
1463
+ async getNewSessionConfig(sessionId) {
1464
+ const session = this._newSessions.get(sessionId);
1465
+ if (!session) {
1466
+ return undefined;
1467
+ }
1468
+ return {
1469
+ providerConfig: deepClone(
1470
+ Object.fromEntries([...session.selectedOptions].map(([key, value]) => [key, value.id]))
1471
+ )
1472
+ };
1473
+ }
1474
+ async archiveSession(sessionId) {
1475
+ const chatSession = this._findChatSession(sessionId);
1476
+ if (chatSession instanceof RemoteNewSession) {
1477
+ chatSession.setArchived(true);
1478
+ this._onDidChangeSessions.fire({
1479
+ added: [],
1480
+ removed: [],
1481
+ changed: [this._chatToSession(chatSession)]
1482
+ });
1483
+ return;
1484
+ }
1485
+ const agentSession = this._findAgentSession(sessionId);
1486
+ if (agentSession) {
1487
+ agentSession.setArchived(true);
1488
+ }
1489
+ }
1490
+ async unarchiveSession(sessionId) {
1491
+ const chatSession = this._findChatSession(sessionId);
1492
+ if (chatSession instanceof RemoteNewSession) {
1493
+ chatSession.setArchived(false);
1494
+ this._onDidChangeSessions.fire({
1495
+ added: [],
1496
+ removed: [],
1497
+ changed: [this._chatToSession(chatSession)]
1498
+ });
1499
+ return;
1500
+ }
1501
+ const agentSession = this._findAgentSession(sessionId);
1502
+ if (agentSession) {
1503
+ agentSession.setArchived(false);
1504
+ }
1505
+ }
1506
+ async setSessionReadState(sessionId, isRead) {
1507
+ const agentSession = this._findAgentSession(sessionId);
1508
+ if (agentSession && agentSession.isRead() !== isRead) {
1509
+ agentSession.setRead(isRead);
1510
+ }
1511
+ }
1512
+ async deleteSession(sessionId) {
1513
+ const agentSession = this._findAgentSession(sessionId);
1514
+ if (!agentSession) {
1515
+ this._cleanupTempSession(sessionId);
1516
+ return;
1517
+ }
1518
+ await this.chatService.removeHistoryEntry(agentSession.resource);
1519
+ this._deleteCreatedBySession(agentSession.resource);
1520
+ this._sessionWrapperCache.delete(sessionId);
1521
+ this._refreshSessionCache();
1522
+ }
1523
+ async deleteSessions(sessionIds) {
1524
+ for (const sessionId of sessionIds) {
1525
+ await this.deleteSession(sessionId);
1526
+ }
1527
+ }
1528
+ async renameChat(_sessionId, _chatUri, _title) {
1529
+ throw ( new Error("Renaming is not supported for Copilot Cloud sessions"));
1530
+ }
1531
+ async renameSession(_sessionId, _title) {
1532
+ throw ( new Error("Renaming is not supported for Copilot Cloud sessions"));
1533
+ }
1534
+ async deleteChat(_sessionId, _chatUri, _options) {
1535
+ throw ( new Error("Deleting individual chats is not supported for Copilot Cloud sessions"));
1536
+ }
1537
+ async forkChat(sessionId, _sourceChat, _turnId) {
1538
+ throw ( new Error(`Session '${sessionId}' does not support forking into a chat`));
1539
+ }
1540
+ async createSideChat(sessionId, _sourceChat, _turnId, _selection) {
1541
+ throw ( new Error(`Session '${sessionId}' does not support side chats`));
1542
+ }
1543
+ startNewSessionRequest(sessionId) {
1544
+ const session = this._newSessions.get(sessionId);
1545
+ if (!session || !this._usesSandbox(session)) {
1546
+ return undefined;
1547
+ }
1548
+ return session.startPreparation();
1549
+ }
1550
+ async createNewChat(sessionId, _prompt) {
1551
+ const session = this._newSessions.get(sessionId);
1552
+ if (!session) {
1553
+ throw ( new Error(
1554
+ `[CopilotChatSessionsProvider] Session '${sessionId}' does not support multiple chats`
1555
+ ));
1556
+ }
1557
+ if (!this._usesSandbox(session)) {
1558
+ (await this._createChatSession(session.resource, session)).dispose();
1559
+ }
1560
+ const newChat = this._withChangesets(buildChatFromSession(session), session.workspace);
1561
+ session.mainChat.set(newChat, undefined);
1562
+ return newChat;
1563
+ }
1564
+ _getCloudSandboxContribution() {
1565
+ return getWorkbenchContribution(CloudSandboxAgentHostContribution.ID);
1566
+ }
1567
+ get _sandboxModelWaitMs() {
1568
+ return CopilotChatSessionsProvider_1.SANDBOX_MODEL_WAIT_MS;
1569
+ }
1570
+ async _sendFirstChatToSandbox(session, repoNwo, options) {
1571
+ this._sandboxSends.add(session.sessionId);
1572
+ const preparation = session.startPreparation();
1573
+ const token = preparation.object;
1574
+ session.setTitle(
1575
+ (options.title || options.query.split("\n")[0]).trim().substring(0, 100) || ( localize(5081, "New Session"))
1576
+ );
1577
+ session.setStatus(SessionStatus.InProgress);
1578
+ this._sessionCache.set(( session.resource.toString()), session);
1579
+ const placeholder = this._chatToSession(session);
1580
+ this._onDidChangeSessions.fire({
1581
+ added: [placeholder],
1582
+ removed: [],
1583
+ changed: []
1584
+ });
1585
+ let provisioned;
1586
+ const selectedModel = this._selectedCloudModel(session);
1587
+ const config = this.getCreateSessionConfig(session.sessionId);
1588
+ const store = ( new DisposableStore());
1589
+ store.add(preparation);
1590
+ store.add(token.onCancellationRequested(() => store.dispose()));
1591
+ const progress = {
1592
+ report: message => {
1593
+ if (!store.isDisposed) {
1594
+ session.reportPreparationProgress(message);
1595
+ }
1596
+ }
1597
+ };
1598
+ try {
1599
+ const contribution = this._getCloudSandboxContribution();
1600
+ provisioned = await raceCancellationError(contribution.provisionSession({
1601
+ ...(repoNwo ? {
1602
+ repoNwo
1603
+ } : {}),
1604
+ prompt: options.query
1605
+ }, token, progress), token);
1606
+ if (token.isCancellationRequested) {
1607
+ throw ( new CancellationError());
1608
+ }
1609
+ if (repoNwo) {
1610
+ store.add(
1611
+ contribution.trackSessionCreationProgress(provisioned.environmentId, repoNwo, progress)
1612
+ );
1613
+ await raceCancellationError(
1614
+ contribution.prepareSession(provisioned.environmentId, repoNwo, token),
1615
+ token
1616
+ );
1617
+ }
1618
+ progress.report(( localize(5082, "Starting Copilot agent")));
1619
+ const chat = provisioned.session.mainChat.get();
1620
+ if (session.isQuickChat.get()) {
1621
+ const canResolve = await raceCancellationError(
1622
+ this.chatSessionsService.canResolveChatSession(chat.resource.scheme),
1623
+ token
1624
+ );
1625
+ if (!canResolve || !this.chatSessionsService.updateChatSessionMetadata(chat.resource, {
1626
+ [SESSION_META_WORKSPACELESS_KEY]: true
1627
+ })) {
1628
+ throw ( new Error(( localize(
1629
+ 5083,
1630
+ "The sandbox could not start a chat without a workspace. Your prompt was not sent."
1631
+ ))));
1632
+ }
1633
+ }
1634
+ const sessionConfig = config ? await provisioned.provider.resolveInitialSessionConfig(provisioned.session.sessionId, config, token) : undefined;
1635
+ await raceCancellationError(
1636
+ this._carryModelToSandbox(provisioned, chat.resource, selectedModel),
1637
+ token
1638
+ );
1639
+ await raceCancellationError(
1640
+ provisioned.provider.setInitialSessionTitle(provisioned.session.sessionId, session.title.get()),
1641
+ token
1642
+ );
1643
+ const committed = await provisioned.provider.sendRequest(provisioned.session.sessionId, chat.resource, {
1644
+ ...options,
1645
+ sessionConfig
1646
+ });
1647
+ this._publishSandboxSession(provisioned, {
1648
+ announce: false
1649
+ });
1650
+ this._retirePlaceholder(session, placeholder, committed);
1651
+ return committed;
1652
+ } catch (error) {
1653
+ this.logService.error(
1654
+ `[CopilotChatSessionsProvider] Failed to start cloud sandbox session ${session.sessionId}:`,
1655
+ error
1656
+ );
1657
+ if (provisioned) {
1658
+ this._publishSandboxSession(provisioned);
1659
+ }
1660
+ this._sessionCache.delete(( session.resource.toString()));
1661
+ this._sessionWrapperCache.delete(session.sessionId);
1662
+ this._clearCurrentNewSessionIfMatch(session, true);
1663
+ this._onDidChangeSessions.fire({
1664
+ added: [],
1665
+ removed: [placeholder],
1666
+ changed: []
1667
+ });
1668
+ session.dispose();
1669
+ throw error;
1670
+ } finally {
1671
+ store.dispose();
1672
+ this._sandboxSends.delete(session.sessionId);
1673
+ }
1674
+ }
1675
+ _publishSandboxSession(provisioned, options) {
1676
+ provisioned.provider.publishWithheldSession(AgentSession.id(provisioned.session.resource), options);
1677
+ }
1678
+ _selectedCloudModel(session) {
1679
+ const selectedModelId = session.selectedModelId;
1680
+ if (!selectedModelId) {
1681
+ return undefined;
1682
+ }
1683
+ const sandboxModel = this._sandboxCatalog.value?.models.find(model => model.identifier === selectedModelId);
1684
+ if (sandboxModel) {
1685
+ return {
1686
+ rawModelId: sandboxModel.metadata.id,
1687
+ label: sandboxModel.metadata.name,
1688
+ config: session.modelConfiguration.captureModelConfiguration(selectedModelId),
1689
+ fromCloudCatalog: true
1690
+ };
1691
+ }
1692
+ const {
1693
+ modelOption
1694
+ } = session.getModelOptionsSnapshot();
1695
+ const item = modelOption?.group.items.find(i => i.id === selectedModelId);
1696
+ const rawModelId = item?.modelMetadata?.id ?? item?.id ?? selectedModelId;
1697
+ return {
1698
+ rawModelId,
1699
+ label: item?.modelMetadata?.name ?? item?.name ?? rawModelId
1700
+ };
1701
+ }
1702
+ async _carryModelToSandbox(provisioned, chatResource, selected) {
1703
+ if (!selected) {
1704
+ return;
1705
+ }
1706
+ const {
1707
+ rawModelId,
1708
+ label
1709
+ } = selected;
1710
+ const sessionId = provisioned.session.sessionId;
1711
+ const provider = provisioned.provider;
1712
+ const modelTarget = provider.getModelsSnapshot(sessionId).modelTarget;
1713
+ if (!modelTarget) {
1714
+ this.logService.info(
1715
+ `[CopilotChatSessionsProvider] Sandbox session ${sessionId} reported no model target; letting the agent host choose.`
1716
+ );
1717
+ this._notifySandboxModelNotApplied(label);
1718
+ return;
1719
+ }
1720
+ const desiredModelId = `${modelTarget}:${rawModelId}`;
1721
+ const store = ( new DisposableStore());
1722
+ try {
1723
+ const deadline = Date.now() + this._sandboxModelWaitMs;
1724
+ for (; ; ) {
1725
+ const resolution = provider.getModelsSnapshot(sessionId, desiredModelId).desiredModelResolution;
1726
+ if (resolution.kind === "available") {
1727
+ if (selected.config && ( Object.keys(selected.config)).length) {
1728
+ const schema = resolution.model.metadata.configurationSchema;
1729
+ for (const [key, value] of Object.entries(selected.config)) {
1730
+ const property = schema?.properties?.[key];
1731
+ if (!property || property.readOnly || (property.enum && !property.enum.includes(value))) {
1732
+ throw ( new Error(( localize(5084, "The sandbox does not support the selected {0} for {1}.", key, label))));
1733
+ }
1734
+ }
1735
+ const configuration = provider.getAutomationModelConfiguration(sessionId);
1736
+ if (!configuration) {
1737
+ throw ( new Error("The sandbox model configuration is unavailable."));
1738
+ }
1739
+ await configuration.setModelConfiguration(resolution.model.identifier, selected.config);
1740
+ }
1741
+ provider.setModel(
1742
+ sessionId,
1743
+ chatResource,
1744
+ resolution.model.identifier,
1745
+ ChatModelSource.CarriedOver
1746
+ );
1747
+ return;
1748
+ }
1749
+ if (resolution.kind !== "pending" && !selected.fromCloudCatalog) {
1750
+ this.logService.info(
1751
+ `[CopilotChatSessionsProvider] Sandbox session ${sessionId} does not advertise model '${rawModelId}'; letting the agent host choose.`
1752
+ );
1753
+ this._notifySandboxModelNotApplied(label);
1754
+ return;
1755
+ }
1756
+ const remaining = deadline - Date.now();
1757
+ const published = remaining > 0 ? await raceTimeout(
1758
+ Event.toPromise(provider.onDidChangeModels, store).then(() => true),
1759
+ remaining
1760
+ ) : undefined;
1761
+ if (!published) {
1762
+ this.logService.warn(
1763
+ `[CopilotChatSessionsProvider] Sandbox session ${sessionId} had not published model '${rawModelId}' in time; letting the agent host choose.`
1764
+ );
1765
+ this._notifySandboxModelNotApplied(label);
1766
+ return;
1767
+ }
1768
+ }
1769
+ } finally {
1770
+ store.dispose();
1771
+ }
1772
+ }
1773
+ _notifySandboxModelNotApplied(label) {
1774
+ this.notificationService.warn(( localize(
1775
+ 5085,
1776
+ "Couldn't use {0} for this session. The agent's default model will be used instead.",
1777
+ label
1778
+ )));
1779
+ }
1780
+ _retirePlaceholder(session, placeholder, committed) {
1781
+ this._sessionCache.delete(( session.resource.toString()));
1782
+ this._sessionWrapperCache.delete(session.sessionId);
1783
+ this._clearCurrentNewSessionIfMatch(session);
1784
+ this._onDidReplaceSession.fire({
1785
+ from: placeholder,
1786
+ to: committed
1787
+ });
1788
+ }
1789
+ async sendRequest(sessionId, chatResource, options) {
1790
+ if (( this._sandboxSends.has(sessionId))) {
1791
+ throw ( new Error(( localize(
1792
+ 5086,
1793
+ "A GitHub sandbox session is already being started. Wait for it to finish before sending another message."
1794
+ ))));
1795
+ }
1796
+ const newSession = this._newSessions.get(sessionId);
1797
+ if (newSession) {
1798
+ if (!this.uriIdentityService.extUri.isEqual(newSession.mainChat.get().resource, chatResource)) {
1799
+ throw ( new Error("Chat resource does not match the main chat of the current new session"));
1800
+ }
1801
+ if (this._usesSandbox(newSession)) {
1802
+ if (!this.supportsQuickChats) {
1803
+ throw ( new Error(( localize(
1804
+ 5087,
1805
+ "GitHub sandbox creation is no longer available. Enable the feature to try again."
1806
+ ))));
1807
+ }
1808
+ if (!newSession.isQuickChat.get() && !newSession.repoNwo) {
1809
+ throw ( new Error(( localize(
1810
+ 5088,
1811
+ "GitHub sandbox creation requires a repository for this session. Please choose a repository to try again."
1812
+ ))));
1813
+ }
1814
+ return this._sendFirstChatToSandbox(newSession, newSession.repoNwo, options);
1815
+ }
1816
+ return this._sendFirstChat(newSession, chatResource, options);
1817
+ }
1818
+ if (!this._findChatSession(sessionId)) {
1819
+ throw ( new Error(`Session '${sessionId}' not found`));
1820
+ }
1821
+ throw ( new Error("Multiple chats per session is not supported"));
1822
+ }
1823
+ async _sendFirstChat(session, chatResource, options) {
1824
+ const {
1825
+ query,
1826
+ attachedContext
1827
+ } = options;
1828
+ session.setTitle(
1829
+ (options.title || query.split("\n")[0]).substring(0, 100) || ( localize(5081, "New Session"))
1830
+ );
1831
+ session.setStatus(SessionStatus.InProgress);
1832
+ this._sessionCache.set(( session.resource.toString()), session);
1833
+ const newSession = this._chatToSession(session);
1834
+ this._onDidChangeSessions.fire({
1835
+ added: [newSession],
1836
+ removed: [],
1837
+ changed: []
1838
+ });
1839
+ const contribution = this.chatSessionsService.getChatSessionContribution(session.target);
1840
+ const permissionLevel = ChatPermissionLevel.Default;
1841
+ const sendOptions = {
1842
+ location: ChatAgentLocation.Chat,
1843
+ userSelectedModelId: session.selectedModelId,
1844
+ userSelectedModelConfiguration: session.modelConfiguration.getModelConfigurationForRequest(session.selectedModelId),
1845
+ modeInfo: {
1846
+ kind: ChatModeKind.Agent,
1847
+ isBuiltin: true,
1848
+ modeInstructions: undefined,
1849
+ telemetryModeId: ChatModeKind.Agent,
1850
+ applyCodeBlockSuggestionId: undefined,
1851
+ permissionLevel
1852
+ },
1853
+ agentIdSilent: contribution?.type,
1854
+ attachedContext,
1855
+ hideFromTranscript: options.hideFromTranscript,
1856
+ onDidCreateResponse: options.onDidCreateResponse
1857
+ };
1858
+ const ref = await this._updateChatSessionState(chatResource, session, permissionLevel);
1859
+ this.logService.debug(
1860
+ `[CopilotChatSessionsProvider] Sending first chat for session ${session.sessionId} with options:`,
1861
+ {
1862
+ userSelectedModelId: sendOptions.userSelectedModelId
1863
+ }
1864
+ );
1865
+ try {
1866
+ const result = await this.chatService.sendRequest(chatResource, query, sendOptions);
1867
+ if (result.kind === "rejected") {
1868
+ this._sessionCache.delete(( session.resource.toString()));
1869
+ this._sessionWrapperCache.delete(session.sessionId);
1870
+ this._clearCurrentNewSessionIfMatch(session, true);
1871
+ this._onDidChangeSessions.fire({
1872
+ added: [],
1873
+ removed: [newSession],
1874
+ changed: []
1875
+ });
1876
+ session.dispose();
1877
+ throw ( new Error(`[DefaultCopilotProvider] sendRequest rejected: ${result.reason}`));
1878
+ }
1879
+ const cts = ( new CancellationTokenSource());
1880
+ const responseCreatedPromise = result.kind === "sent" ? result.data.responseCreatedPromise : undefined;
1881
+ responseCreatedPromise?.then(r => {
1882
+ if (r?.isCanceled) {
1883
+ cts.cancel();
1884
+ }
1885
+ });
1886
+ try {
1887
+ const committedResource = await this._waitForCommittedSession(session.resource, responseCreatedPromise);
1888
+ this._inFlightCommits.add(( committedResource.toString()));
1889
+ try {
1890
+ const createdBySession = session.createdBySession.get();
1891
+ if (createdBySession) {
1892
+ this._setCreatedBySession(committedResource, createdBySession);
1893
+ }
1894
+ const committedChat = await this._waitForSessionInCache(committedResource, cts.token);
1895
+ this._sessionCache.delete(( session.resource.toString()));
1896
+ this._clearCurrentNewSessionIfMatch(session);
1897
+ const committedSession = this._chatToSession(committedChat);
1898
+ this._sessionWrapperCache.delete(session.sessionId);
1899
+ this._onDidReplaceSession.fire({
1900
+ from: newSession,
1901
+ to: committedSession
1902
+ });
1903
+ return committedSession;
1904
+ } finally {
1905
+ this._inFlightCommits.delete(( committedResource.toString()));
1906
+ }
1907
+ } catch (error) {
1908
+ this._clearCurrentNewSessionIfMatch(session, true);
1909
+ if (error instanceof CancellationError) {
1910
+ session.setStatus(SessionStatus.Completed);
1911
+ this._onDidChangeSessions.fire({
1912
+ added: [],
1913
+ removed: [],
1914
+ changed: [newSession]
1915
+ });
1916
+ return newSession;
1917
+ }
1918
+ this._sessionCache.delete(( session.resource.toString()));
1919
+ this._sessionWrapperCache.delete(session.sessionId);
1920
+ this._onDidChangeSessions.fire({
1921
+ added: [],
1922
+ removed: [this._chatToSession(session)],
1923
+ changed: []
1924
+ });
1925
+ session.dispose();
1926
+ throw error;
1927
+ } finally {
1928
+ cts.dispose();
1929
+ }
1930
+ } catch (error) {
1931
+ this.logService.error(
1932
+ `[CopilotChatSessionsProvider] Failed to send first chat for session ${session.sessionId}:`,
1933
+ error
1934
+ );
1935
+ throw error;
1936
+ } finally {
1937
+ ref?.dispose();
1938
+ }
1939
+ }
1940
+ async _createChatSession(resource, session) {
1941
+ await this.chatSessionsService.getOrCreateChatSession(resource, CancellationToken.None);
1942
+ return this._updateChatSessionState(resource, session);
1943
+ }
1944
+ async _updateChatSessionState(resource, session, permissionLevel) {
1945
+ const modelRef = await this.chatService.acquireOrLoadSession(resource, ChatAgentLocation.Chat, CancellationToken.None);
1946
+ if (!modelRef) {
1947
+ return Disposable.None;
1948
+ }
1949
+ const model = modelRef.object;
1950
+ if (session.selectedModelId) {
1951
+ const languageModel = this.languageModelsService.lookupLanguageModel(session.selectedModelId);
1952
+ if (languageModel) {
1953
+ model.inputModel.setState({
1954
+ selectedModel: {
1955
+ identifier: session.selectedModelId,
1956
+ metadata: languageModel
1957
+ }
1958
+ });
1959
+ }
1960
+ }
1961
+ if (session.selectedOptions.size > 0) {
1962
+ this.chatSessionsService.updateSessionOptions(resource, session.selectedOptions);
1963
+ }
1964
+ if (permissionLevel) {
1965
+ model.inputModel.setState({
1966
+ permissionLevel
1967
+ });
1968
+ }
1969
+ return modelRef;
1970
+ }
1971
+ async _waitForCommittedSession(untitledResource, responseCreatedPromise) {
1972
+ const timeoutMs = 5 * 60_000;
1973
+ const disposables = ( new DisposableStore());
1974
+ try {
1975
+ const commitPromise = ( new Promise(resolve => {
1976
+ disposables.add(this.chatSessionsService.onDidCommitSession(e => {
1977
+ if (isEqual(e.original, untitledResource)) {
1978
+ resolve(e.committed);
1979
+ }
1980
+ }));
1981
+ }));
1982
+ const candidates = [raceTimeout(commitPromise, timeoutMs).then(uri => uri ? {
1983
+ kind: "commit",
1984
+ uri
1985
+ } : {
1986
+ kind: "timeout"
1987
+ })];
1988
+ if (responseCreatedPromise) {
1989
+ candidates.push(responseCreatedPromise.then(r => r?.isCanceled ? {
1990
+ kind: "cancelled"
1991
+ } : ( new Promise(() => {}))));
1992
+ }
1993
+ const outcome = await Promise.race(candidates);
1994
+ if (outcome.kind === "commit") {
1995
+ return outcome.uri;
1996
+ }
1997
+ if (outcome.kind === "cancelled") {
1998
+ throw ( new CancellationError());
1999
+ }
2000
+ const response = responseCreatedPromise ? await responseCreatedPromise : undefined;
2001
+ if (response?.isCanceled) {
2002
+ throw ( new CancellationError());
2003
+ }
2004
+ throw ( new Error("Timed out waiting for session commit"));
2005
+ } finally {
2006
+ disposables.dispose();
2007
+ }
2008
+ }
2009
+ async _waitForSessionInCache(resource, token) {
2010
+ const key = ( resource.toString());
2011
+ const existing = this._sessionCache.get(key);
2012
+ if (existing instanceof AgentSessionAdapter) {
2013
+ return existing;
2014
+ }
2015
+ const disposables = ( new DisposableStore());
2016
+ try {
2017
+ const sessionPromise = ( new Promise(resolve => {
2018
+ disposables.add(this.onDidChangeSessions(e => {
2019
+ const cached = this._sessionCache.get(key);
2020
+ if (cached instanceof AgentSessionAdapter) {
2021
+ resolve(cached);
2022
+ }
2023
+ }));
2024
+ }));
2025
+ const result = await raceTimeout(
2026
+ token ? raceCancellationError(sessionPromise, token) : sessionPromise,
2027
+ 30_000
2028
+ );
2029
+ if (!result) {
2030
+ throw ( new Error("Timed out waiting for committed session in cache"));
2031
+ }
2032
+ return result;
2033
+ } finally {
2034
+ disposables.dispose();
2035
+ }
2036
+ }
2037
+ async _pickRepository(allowRepositoryUrl = false) {
2038
+ if (isWeb) {
2039
+ const store = ( new DisposableStore());
2040
+ this._repositoryPicker.value = store;
2041
+ const token = cancelOnDispose(store);
2042
+ const checkHost = () => {
2043
+ if (this.gitHubService.enterpriseHost !== undefined) {
2044
+ throw ( new Error(( localize(
2045
+ 5089,
2046
+ "This picker supports github.com repositories only. Switch to a github.com account, then try again."
2047
+ ))));
2048
+ }
2049
+ };
2050
+ try {
2051
+ checkHost();
2052
+ await raceCancellationError(this.gitHubService.authenticateForRepositoryAccess(token), token);
2053
+ if (token.isCancellationRequested) {
2054
+ return undefined;
2055
+ }
2056
+ checkHost();
2057
+ const picker = store.add(this.instantiationService.createInstance(RepositoryPicker));
2058
+ const selection = await picker.pickRepository(async (query, requestToken) => {
2059
+ checkHost();
2060
+ const repositories = await this.gitHubService.getRepositories(getGitHubRepositoryId(query.trim()) ?? query, requestToken);
2061
+ checkHost();
2062
+ return repositories.map(repository => repository.fullName);
2063
+ }, undefined, token);
2064
+ if (selection) {
2065
+ checkHost();
2066
+ }
2067
+ return selection?.repository;
2068
+ } catch (error) {
2069
+ if (!isCancellationError(error) && !token.isCancellationRequested) {
2070
+ this.notificationService.error(error);
2071
+ }
2072
+ return undefined;
2073
+ } finally {
2074
+ store.dispose();
2075
+ if (this._repositoryPicker.value === store) {
2076
+ this._repositoryPicker.clear();
2077
+ }
2078
+ }
2079
+ }
2080
+ return this.commandService.executeCommand(OPEN_REPO_COMMAND, undefined, {
2081
+ allowRepositoryUrl
2082
+ });
2083
+ }
2084
+ async _browseForRepository() {
2085
+ const allowRepositoryUrl = this._supportsLocalRepositoryActions();
2086
+ const repository = await this._pickRepository(allowRepositoryUrl);
2087
+ if (!repository) {
2088
+ return undefined;
2089
+ }
2090
+ const repoId = getGitHubRepositoryId(repository);
2091
+ if (!repoId) {
2092
+ return allowRepositoryUrl ? this._cloneRepository(repository) : undefined;
2093
+ }
2094
+ const uri = ( URI.from({
2095
+ scheme: GITHUB_REMOTE_FILE_SCHEME,
2096
+ authority: "github",
2097
+ path: `/${repoId}/HEAD`
2098
+ }));
2099
+ const folder = {
2100
+ root: uri,
2101
+ workingDirectory: uri,
2102
+ name: basename(uri),
2103
+ description: undefined,
2104
+ gitRepository: undefined
2105
+ };
2106
+ return {
2107
+ uri: ( URI.parse(`https://github.com/${repoId}`)),
2108
+ label: this._labelFromUri(uri),
2109
+ icon: this._iconFromUri(uri),
2110
+ group: SESSION_WORKSPACE_GROUP_GITHUB,
2111
+ folders: [folder],
2112
+ requiresWorkspaceTrust: false,
2113
+ isVirtualWorkspace: true
2114
+ };
2115
+ }
2116
+ _supportsLocalRepositoryActions() {
2117
+ return this.supportsLocalWorkspaces && !isWeb && (this.pathService.defaultUriScheme === Schemas.file || this.pathService.defaultUriScheme === GITHUB_REMOTE_FILE_SCHEME || this.pathService.defaultUriScheme === SessionType.CopilotCloud);
2118
+ }
2119
+ async _cloneRepository(url) {
2120
+ try {
2121
+ const repositoryPath = await this.commandService.executeCommand("git.clone", url, undefined, {
2122
+ postCloneAction: "none",
2123
+ returnRepositoryPath: true
2124
+ });
2125
+ if (repositoryPath?.endsWith(".code-workspace")) {
2126
+ this.notificationService.error(( localize(
2127
+ 5090,
2128
+ "The selected clone is a workspace file. Choose the repository again to select a repository folder."
2129
+ )));
2130
+ return undefined;
2131
+ }
2132
+ return repositoryPath ? this.resolveWorkspace(URI.file(repositoryPath)) : undefined;
2133
+ } catch (error) {
2134
+ if (!isCancellationError(error)) {
2135
+ this.notificationService.error(error);
2136
+ }
2137
+ return undefined;
2138
+ }
2139
+ }
2140
+ async _browseForGitHubContext(commandId, icon, currentWorkspace) {
2141
+ const repositoryIds = ( new Set());
2142
+ for (const folder of currentWorkspace?.folders ?? []) {
2143
+ const repositoryId = resolveGitHubRepositoryId(folder);
2144
+ if (repositoryId) {
2145
+ repositoryIds.add(repositoryId);
2146
+ }
2147
+ }
2148
+ const repository = repositoryIds.size === 1 ? ( repositoryIds.values()).next().value : currentWorkspace?.folders.length === 1 && currentWorkspace.folders[0].root.scheme === Schemas.file ? currentWorkspace.folders[0].root : await this._pickRepository();
2149
+ if (!repository) {
2150
+ return undefined;
2151
+ }
2152
+ const selection = await this.commandService.executeCommand(commandId, repository);
2153
+ if (!selection) {
2154
+ return undefined;
2155
+ }
2156
+ const root = ( URI.from({
2157
+ scheme: GITHUB_REMOTE_FILE_SCHEME,
2158
+ authority: "github",
2159
+ path: `/${selection.repoId}/HEAD`
2160
+ }));
2161
+ return {
2162
+ uri: ( URI.parse(selection.url)),
2163
+ label: selection.label,
2164
+ icon,
2165
+ group: SESSION_WORKSPACE_GROUP_GITHUB,
2166
+ folders: [{
2167
+ root,
2168
+ workingDirectory: root,
2169
+ name: basename(root),
2170
+ description: undefined,
2171
+ gitRepository: undefined
2172
+ }],
2173
+ requiresWorkspaceTrust: false,
2174
+ isVirtualWorkspace: true
2175
+ };
2176
+ }
2177
+ resolveWorkspace(uri) {
2178
+ if (this.providerMode === "sandbox" && (uri.scheme !== GITHUB_REMOTE_FILE_SCHEME || uri.authority !== "github" || !/^\/[^/]+\/[^/]+\/HEAD$/.test(uri.path) || uri.query || uri.fragment)) {
2179
+ return undefined;
2180
+ }
2181
+ if (uri.scheme !== Schemas.file && uri.scheme !== GITHUB_REMOTE_FILE_SCHEME) {
2182
+ return undefined;
2183
+ }
2184
+ const folder = {
2185
+ root: uri,
2186
+ workingDirectory: uri,
2187
+ name: basename(uri),
2188
+ description: undefined,
2189
+ gitRepository: uri.scheme === Schemas.file ? this._getLocalGitRepository(uri) : undefined
2190
+ };
2191
+ return {
2192
+ uri: uri,
2193
+ label: this._labelFromUri(uri),
2194
+ description: this._descriptionFromUri(uri),
2195
+ group: uri.scheme === GITHUB_REMOTE_FILE_SCHEME ? SESSION_WORKSPACE_GROUP_GITHUB : SESSION_WORKSPACE_GROUP_LOCAL,
2196
+ icon: this._iconFromUri(uri),
2197
+ folders: [folder],
2198
+ requiresWorkspaceTrust: uri.scheme !== GITHUB_REMOTE_FILE_SCHEME,
2199
+ isVirtualWorkspace: uri.scheme === GITHUB_REMOTE_FILE_SCHEME
2200
+ };
2201
+ }
2202
+ _getLocalGitRepository(uri) {
2203
+ const state = this._getLocalGitRepositoryState(uri);
2204
+ const resolveRepository = () => this._resolveLocalGitRepository(uri, state);
2205
+ return {
2206
+ uri,
2207
+ workTreeUri: uri,
2208
+ baseBranchName: undefined,
2209
+ isRepository: state.isRepository,
2210
+ gitHubInfo: state.gitHubInfo,
2211
+ resolveRepository,
2212
+ resolveGitHubInfo: resolveRepository
2213
+ };
2214
+ }
2215
+ _getLocalGitRepositoryState(uri) {
2216
+ const key = this.uriIdentityService.extUri.getComparisonKey(uri);
2217
+ let state = this._localGitRepositoryState.get(key);
2218
+ if (state) {
2219
+ return state;
2220
+ }
2221
+ if (this._localGitRepositoryState.size >= 50) {
2222
+ const oldestKey = ( this._localGitRepositoryState.keys()).next().value;
2223
+ if (oldestKey !== undefined) {
2224
+ this._localGitRepositoryState.delete(oldestKey);
2225
+ this._localGitRepositoryResolutionStarted.delete(oldestKey);
2226
+ }
2227
+ }
2228
+ state = {
2229
+ isRepository: observableValue(this, false),
2230
+ gitHubInfo: observableValue(this, undefined)
2231
+ };
2232
+ this._localGitRepositoryState.set(key, state);
2233
+ return state;
2234
+ }
2235
+ _resolveLocalGitRepository(uri, state) {
2236
+ const key = this.uriIdentityService.extUri.getComparisonKey(uri);
2237
+ if (( this._localGitRepositoryResolutionStarted.has(key))) {
2238
+ return;
2239
+ }
2240
+ this._localGitRepositoryResolutionStarted.add(key);
2241
+ void resolveGitRepositoryFromGitConfig(this.fileService, uri).then(repositoryInfo => {
2242
+ if (this._localGitRepositoryState.get(key) !== state) {
2243
+ this._localGitRepositoryResolutionStarted.delete(key);
2244
+ return;
2245
+ }
2246
+ if (!repositoryInfo) {
2247
+ this._localGitRepositoryResolutionStarted.delete(key);
2248
+ return;
2249
+ }
2250
+ const nextGitHubInfo = repositoryInfo.gitHub ? {
2251
+ owner: repositoryInfo.gitHub.owner,
2252
+ repo: repositoryInfo.gitHub.repo
2253
+ } : undefined;
2254
+ if (!state.isRepository.get() || !gitHubInfoEqual(state.gitHubInfo.get(), nextGitHubInfo)) {
2255
+ transaction(tx => {
2256
+ state.isRepository.set(true, tx);
2257
+ state.gitHubInfo.set(nextGitHubInfo, tx);
2258
+ });
2259
+ this._onDidChangeSessionTypes.fire();
2260
+ }
2261
+ if (!repositoryInfo.gitHub) {
2262
+ this._localGitRepositoryResolutionStarted.delete(key);
2263
+ }
2264
+ }, error => {
2265
+ this._localGitRepositoryResolutionStarted.delete(key);
2266
+ this.logService.warn(`Failed to resolve Git repository metadata for '${( uri.toString())}'.`, error);
2267
+ });
2268
+ }
2269
+ _labelFromUri(uri) {
2270
+ return githubRemoteRepoLabel(uri) ?? basename(uri);
2271
+ }
2272
+ _descriptionFromUri(uri) {
2273
+ if (uri.scheme === GITHUB_REMOTE_FILE_SCHEME) {
2274
+ const parts = uri.path.substring(1).split("/");
2275
+ return parts.length >= 2 ? parts[0] : undefined;
2276
+ }
2277
+ return this.labelService.getUriLabel(dirname(uri), {
2278
+ relative: false
2279
+ });
2280
+ }
2281
+ _iconFromUri(uri) {
2282
+ if (uri.scheme === GITHUB_REMOTE_FILE_SCHEME) {
2283
+ return Codicon.repo;
2284
+ }
2285
+ return Codicon.folder;
2286
+ }
2287
+ _ensureSessionCache() {
2288
+ if (this._sessionCache.size > 0) {
2289
+ return;
2290
+ }
2291
+ this._refreshSessionCache();
2292
+ }
2293
+ _cleanupTempSession(sessionId) {
2294
+ const chatSession = this._findChatSession(sessionId);
2295
+ if (!chatSession) {
2296
+ return;
2297
+ }
2298
+ this._sessionCache.delete(( chatSession.resource.toString()));
2299
+ this._deleteCreatedBySession(chatSession.resource);
2300
+ if (( this._newSessions.has(chatSession.sessionId))) {
2301
+ this._newSessions.deleteAndLeak(chatSession.sessionId);
2302
+ }
2303
+ const removedSession = this._chatToSession(chatSession);
2304
+ this._sessionWrapperCache.delete(chatSession.sessionId);
2305
+ this._onDidChangeSessions.fire({
2306
+ added: [],
2307
+ removed: [removedSession],
2308
+ changed: []
2309
+ });
2310
+ if (chatSession instanceof RemoteNewSession) {
2311
+ chatSession.dispose();
2312
+ }
2313
+ }
2314
+ _refreshSessionCache() {
2315
+ if (this.providerMode === "sandbox") {
2316
+ return;
2317
+ }
2318
+ const currentKeys = ( new Set());
2319
+ const addedData = [];
2320
+ const changedData = [];
2321
+ const sessionsToMarkUnread = [];
2322
+ for (const session of this.agentSessionsService.model.sessions) {
2323
+ if (session.providerType !== AgentSessionProviders.Cloud) {
2324
+ continue;
2325
+ }
2326
+ const key = ( session.resource.toString());
2327
+ currentKeys.add(key);
2328
+ const existing = this._sessionCache.get(key);
2329
+ if (existing) {
2330
+ const previousStatus = existing.status.get();
2331
+ if (existing.update(session)) {
2332
+ changedData.push(existing);
2333
+ }
2334
+ const currentStatus = existing.status.get();
2335
+ if (previousStatus === SessionStatus.InProgress && currentStatus !== SessionStatus.InProgress && currentStatus !== SessionStatus.Untitled && existing.isRead.get()) {
2336
+ sessionsToMarkUnread.push(session);
2337
+ }
2338
+ } else {
2339
+ const adapter = ( new AgentSessionAdapter(
2340
+ session,
2341
+ this.id,
2342
+ this.gitHubService,
2343
+ this.pullRequestIconCache,
2344
+ this.logService
2345
+ ));
2346
+ this._sessionCache.set(key, adapter);
2347
+ addedData.push(adapter);
2348
+ }
2349
+ }
2350
+ const removedData = [];
2351
+ for (const [key, adapter] of this._sessionCache) {
2352
+ if (!( currentKeys.has(key)) && adapter instanceof AgentSessionAdapter && !( this._inFlightCommits.has(key))) {
2353
+ removedData.push(adapter);
2354
+ }
2355
+ }
2356
+ for (const removed of removedData) {
2357
+ this._sessionCache.delete(( removed.resource.toString()));
2358
+ }
2359
+ if (addedData.length > 0 || removedData.length > 0 || changedData.length > 0) {
2360
+ this._onDidChangeSessions.fire({
2361
+ added: addedData.map(d => this._chatToSession(d)),
2362
+ removed: removedData.map(d => {
2363
+ const session = this._chatToSession(d);
2364
+ this._sessionWrapperCache.delete(d.sessionId);
2365
+ return session;
2366
+ }),
2367
+ changed: changedData.map(d => this._chatToSession(d))
2368
+ });
2369
+ }
2370
+ for (const session of sessionsToMarkUnread) {
2371
+ session.setRead(false);
2372
+ }
2373
+ }
2374
+ _findChatSession(sessionId) {
2375
+ return this._sessionCache.get(this._localIdFromSessionId(sessionId));
2376
+ }
2377
+ _findAgentSession(sessionId) {
2378
+ const adapter = this._findChatSession(sessionId);
2379
+ if (!adapter) {
2380
+ return undefined;
2381
+ }
2382
+ return this.agentSessionsService.getSession(adapter.resource);
2383
+ }
2384
+ _localIdFromSessionId(sessionId) {
2385
+ const prefix = `${this.id}:`;
2386
+ return sessionId.startsWith(prefix) ? sessionId.substring(prefix.length) : sessionId;
2387
+ }
2388
+ _chatToSession(chat) {
2389
+ const cached = this._sessionWrapperCache.get(chat.sessionId);
2390
+ if (cached) {
2391
+ return cached;
2392
+ }
2393
+ const mainChat = chat.mainChat.map(mainChat => this._withChangesets(mainChat, chat.workspace));
2394
+ const chatsObs = mainChat.map(c => [c]);
2395
+ const session = {
2396
+ sessionId: chat.sessionId,
2397
+ resource: chat.resource,
2398
+ providerId: chat.providerId,
2399
+ sessionType: chat.sessionType,
2400
+ harness: "copilot",
2401
+ environment: this.environment.id,
2402
+ application: chat.application,
2403
+ icon: chat.icon,
2404
+ createdAt: chat.createdAt,
2405
+ workspace: chat.workspace,
2406
+ isQuickChat: chat.isQuickChat,
2407
+ title: chat.title,
2408
+ updatedAt: chat.updatedAt,
2409
+ status: chat.status,
2410
+ changesSummary: chat.changesSummary,
2411
+ artifacts: chat.artifacts,
2412
+ modelId: chat.modelId,
2413
+ mode: chat.mode,
2414
+ loading: chat.loading,
2415
+ preparationProgress: chat.preparationProgress,
2416
+ isNewSessionRequestInProgress: chat.isNewSessionRequestInProgress,
2417
+ isArchived: chat.isArchived,
2418
+ isRead: chat.isRead,
2419
+ description: chat.description,
2420
+ lastTurnEnd: chat.lastTurnEnd,
2421
+ chats: chatsObs,
2422
+ mainChat,
2423
+ createdBySession: chat.createdBySession ?? this._createdBySession(chat.resource),
2424
+ isExternal: chat.isExternal,
2425
+ capabilities: constObservable({
2426
+ supportsMultipleChats: false,
2427
+ supportsRename: false,
2428
+ supportsDelete: false,
2429
+ runsWorktreeCreatedTasks: chat.sessionType === CopilotCloudSessionType.id
2430
+ })
2431
+ };
2432
+ this._sessionWrapperCache.set(chat.sessionId, session);
2433
+ return session;
2434
+ }
2435
+ _withChangesets(chat, workspace) {
2436
+ return {
2437
+ ...chat,
2438
+ changesets: createChangesets(workspace, constObservable([chat]), this.instantiationService)
2439
+ };
2440
+ }
2441
+ };
2442
+ CopilotChatSessionsProvider = CopilotChatSessionsProvider_1 = ( __decorate([( __param(1, IAgentSessionsService)), ( __param(2, IChatService)), ( __param(3, IChatSessionsService)), ( __param(4, ICommandService)), ( __param(5, IInstantiationService)), ( __param(6, ILanguageModelsService)), ( __param(7, IConfigurationService)), ( __param(8, ILogService)), ( __param(9, INotificationService)), ( __param(10, IGitHubService)), ( __param(11, IPullRequestIconCache)), ( __param(12, ILabelService)), ( __param(13, IUriIdentityService)), ( __param(14, IFileService)), ( __param(15, IPathService)), ( __param(16, IStorageService))], CopilotChatSessionsProvider));
2443
+
2444
+ export { COPILOT_PROVIDER_ID, CopilotChatSessionsProvider, CopilotCloudSessionType, CopilotSandboxSessionType, RemoteNewSession };