@codingame/monaco-vscode-chat-service-override 8.0.4 → 9.0.0

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 (33) hide show
  1. package/package.json +2 -2
  2. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.js +24 -24
  3. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatClearActions.js +2 -2
  4. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatCodeblockActions.js +73 -22
  5. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatContextActions.js +47 -36
  6. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatCopyActions.js +2 -2
  7. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatDeveloperActions.js +1 -1
  8. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatFileTreeActions.js +2 -2
  9. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatImportExport.js +5 -4
  10. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatMoveActions.js +5 -4
  11. package/vscode/src/vs/workbench/contrib/chat/browser/chat.contribution.js +27 -21
  12. package/vscode/src/vs/workbench/contrib/chat/browser/chatAccessibilityService.js +10 -3
  13. package/vscode/src/vs/workbench/contrib/chat/browser/chatEditor.js +2 -2
  14. package/vscode/src/vs/workbench/contrib/chat/browser/chatParticipantContributions.js +179 -35
  15. package/vscode/src/vs/workbench/contrib/chat/browser/chatQuick.js +1 -1
  16. package/vscode/src/vs/workbench/contrib/chat/browser/chatResponseAccessibleView.js +2 -9
  17. package/vscode/src/vs/workbench/contrib/chat/browser/chatVariables.js +14 -4
  18. package/vscode/src/vs/workbench/contrib/chat/browser/chatViewPane.js +14 -7
  19. package/vscode/src/vs/workbench/contrib/chat/browser/contrib/chatContextAttachments.js +0 -5
  20. package/vscode/src/vs/workbench/contrib/chat/browser/contrib/chatInputCompletions.js +37 -9
  21. package/vscode/src/vs/workbench/contrib/chat/browser/contrib/chatInputEditorContrib.js +6 -2
  22. package/vscode/src/vs/workbench/contrib/chat/browser/contrib/chatInputEditorHover.js +1 -1
  23. package/vscode/src/vs/workbench/contrib/chat/common/chatServiceImpl.js +253 -67
  24. package/vscode/src/vs/workbench/contrib/chat/common/chatServiceTelemetry.js +16 -0
  25. package/vscode/src/vs/workbench/contrib/chat/common/languageModelStats.js +2 -2
  26. package/vscode/src/vs/workbench/contrib/chat/common/languageModelToolsService.js +59 -18
  27. package/vscode/src/vs/workbench/contrib/chat/common/tools/languageModelToolsContribution.js +51 -20
  28. package/vscode/src/vs/workbench/contrib/chat/common/voiceChatService.js +1 -1
  29. package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChat.contribution.js +28 -49
  30. package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatCurrentLine.js +130 -0
  31. package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatNotebook.js +10 -2
  32. package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatSavingServiceImpl.js +2 -2
  33. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatTitleActions.js +0 -258
@@ -11,6 +11,8 @@ import { revive } from 'vscode/vscode/vs/base/common/marshalling';
11
11
  import { StopWatch } from 'vscode/vscode/vs/base/common/stopwatch';
12
12
  import { URI } from 'vscode/vscode/vs/base/common/uri';
13
13
  import { localize } from 'vscode/vscode/vs/nls';
14
+ import { IConfigurationService } from 'vscode/vscode/vs/platform/configuration/common/configuration.service';
15
+ import { IContextKeyService } from 'vscode/vscode/vs/platform/contextkey/common/contextkey.service';
14
16
  import { IInstantiationService } from 'vscode/vscode/vs/platform/instantiation/common/instantiation';
15
17
  import { ILogService } from 'vscode/vscode/vs/platform/log/common/log.service';
16
18
  import { Progress } from 'vscode/vscode/vs/platform/progress/common/progress';
@@ -20,24 +22,38 @@ import { ITelemetryService } from 'vscode/vscode/vs/platform/telemetry/common/te
20
22
  import { IWorkspaceContextService } from 'vscode/vscode/vs/platform/workspace/common/workspace.service';
21
23
  import { ChatAgentLocation } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatAgents';
22
24
  import { IChatAgentService } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatAgents.service';
23
- import { ChatModel, ChatWelcomeMessageModel, ChatRequestRemovalReason, getHistoryEntriesFromModel, updateRanges, ChatRequestModel } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatModel';
25
+ import { CONTEXT_VOTE_UP_ENABLED } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatContextKeys';
26
+ import { normalizeSerializableChatData, ChatModel, ChatWelcomeMessageModel, ChatRequestRemovalReason, updateRanges, ChatRequestModel } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatModel';
24
27
  import { ChatRequestAgentPart, ChatRequestAgentSubcommandPart, chatSubcommandLeader, chatAgentLeader, ChatRequestSlashCommandPart, getPromptText } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatParserTypes';
25
28
  import { ChatRequestParser } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatRequestParser';
26
29
  import { ChatServiceTelemetry } from './chatServiceTelemetry.js';
27
30
  import { IChatSlashCommandService } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatSlashCommands.service';
28
31
  import { IChatVariablesService } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatVariables.service';
29
32
  import { ChatMessageRole } from 'vscode/vscode/vs/workbench/contrib/chat/common/languageModels';
33
+ import { IWorkbenchAssignmentService } from 'vscode/vscode/vs/workbench/services/assignment/common/assignmentService.service';
30
34
  import { IExtensionService } from 'vscode/vscode/vs/workbench/services/extensions/common/extensions.service';
31
35
 
32
36
  const serializedChatKey = 'interactive.sessions';
33
37
  const globalChatKey = 'chat.workspaceTransfer';
34
38
  const SESSION_TRANSFER_EXPIRATION_IN_MILLISECONDS = 1000 * 60;
35
39
  const maxPersistedSessions = 25;
40
+ class CancellableRequest {
41
+ constructor(cancellationTokenSource, requestId) {
42
+ this.cancellationTokenSource = cancellationTokenSource;
43
+ this.requestId = requestId;
44
+ }
45
+ dispose() {
46
+ this.cancellationTokenSource.dispose();
47
+ }
48
+ cancel() {
49
+ this.cancellationTokenSource.cancel();
50
+ }
51
+ }
36
52
  let ChatService = class ChatService extends Disposable {
37
53
  get transferredSessionData() {
38
54
  return this._transferredSessionData;
39
55
  }
40
- constructor(storageService, logService, extensionService, instantiationService, telemetryService, workspaceContextService, chatSlashCommandService, chatVariablesService, chatAgentService) {
56
+ constructor(storageService, logService, extensionService, instantiationService, telemetryService, workspaceContextService, chatSlashCommandService, chatVariablesService, chatAgentService, workbenchAssignmentService, contextKeyService, configurationService) {
41
57
  super();
42
58
  this.storageService = storageService;
43
59
  this.logService = logService;
@@ -48,15 +64,18 @@ let ChatService = class ChatService extends Disposable {
48
64
  this.chatSlashCommandService = chatSlashCommandService;
49
65
  this.chatVariablesService = chatVariablesService;
50
66
  this.chatAgentService = chatAgentService;
67
+ this.configurationService = configurationService;
51
68
  this._sessionModels = this._register(( (new DisposableMap())));
52
69
  this._pendingRequests = this._register(( (new DisposableMap())));
70
+ this._deletedChatIds = ( (new Set()));
53
71
  this._onDidPerformUserAction = this._register(( (new Emitter())));
54
72
  this.onDidPerformUserAction = this._onDidPerformUserAction.event;
55
73
  this._onDidDisposeSession = this._register(( (new Emitter())));
56
74
  this.onDidDisposeSession = this._onDidDisposeSession.event;
57
75
  this._sessionFollowupCancelTokens = this._register(( (new DisposableMap())));
58
76
  this._chatServiceTelemetry = this.instantiationService.createInstance(ChatServiceTelemetry);
59
- const sessionData = storageService.get(serializedChatKey, StorageScope.WORKSPACE, '');
77
+ const isEmptyWindow = !workspaceContextService.getWorkspace().folders.length;
78
+ const sessionData = storageService.get(serializedChatKey, isEmptyWindow ? StorageScope.APPLICATION : StorageScope.WORKSPACE, '');
60
79
  if (sessionData) {
61
80
  this._persistedSessions = this.deserializeChats(sessionData);
62
81
  const countsForLog = ( (Object.keys(this._persistedSessions))).length;
@@ -75,32 +94,90 @@ let ChatService = class ChatService extends Disposable {
75
94
  this._transferredSessionData = { sessionId: transferredChat.sessionId, inputValue: transferredData.inputValue };
76
95
  }
77
96
  this._register(storageService.onWillSaveState(() => this.saveState()));
97
+ const voteUpEnabled = CONTEXT_VOTE_UP_ENABLED.bindTo(contextKeyService);
98
+ workbenchAssignmentService.getTreatment('chatVoteUpEnabled')
99
+ .then(value => voteUpEnabled.set(!!value));
78
100
  }
79
101
  isEnabled(location) {
80
102
  return this.chatAgentService.getContributedDefaultAgent(location) !== undefined;
81
103
  }
82
104
  saveState() {
83
- let allSessions = Array.from(( (this._sessionModels.values())))
105
+ const liveChats = Array.from(( (this._sessionModels.values())))
84
106
  .filter(session => session.initialLocation === ChatAgentLocation.Panel)
85
107
  .filter(session => session.getRequests().length > 0);
86
- allSessions = allSessions.concat(( (Object.values(this._persistedSessions)))
87
- .filter(session => !( (this._sessionModels.has(session.sessionId))))
88
- .filter(session => session.requests.length));
89
- allSessions.sort((a, b) => (b.creationDate ?? 0) - (a.creationDate ?? 0));
90
- allSessions = allSessions.slice(0, maxPersistedSessions);
91
- if (allSessions.length) {
92
- this.trace('onWillSaveState', `Persisting ${allSessions.length} sessions`);
108
+ const isEmptyWindow = !this.workspaceContextService.getWorkspace().folders.length;
109
+ if (isEmptyWindow) {
110
+ this.syncEmptyWindowChats(liveChats);
93
111
  }
94
- const serialized = JSON.stringify(allSessions);
95
- if (allSessions.length) {
96
- this.trace('onWillSaveState', `Persisting ${serialized.length} chars`);
112
+ else {
113
+ let allSessions = liveChats;
114
+ allSessions = allSessions.concat(( (Object.values(this._persistedSessions)))
115
+ .filter(session => !( (this._sessionModels.has(session.sessionId))))
116
+ .filter(session => session.requests.length));
117
+ allSessions.sort((a, b) => (b.creationDate ?? 0) - (a.creationDate ?? 0));
118
+ allSessions = allSessions.slice(0, maxPersistedSessions);
119
+ if (allSessions.length) {
120
+ this.trace('onWillSaveState', `Persisting ${allSessions.length} sessions`);
121
+ }
122
+ const serialized = JSON.stringify(allSessions);
123
+ if (allSessions.length) {
124
+ this.trace('onWillSaveState', `Persisting ${serialized.length} chars`);
125
+ }
126
+ this.storageService.store(serializedChatKey, serialized, StorageScope.WORKSPACE, StorageTarget.MACHINE);
97
127
  }
98
- this.storageService.store(serializedChatKey, serialized, StorageScope.WORKSPACE, StorageTarget.MACHINE);
128
+ this._deletedChatIds.clear();
129
+ }
130
+ syncEmptyWindowChats(thisWindowChats) {
131
+ const sessionData = this.storageService.get(serializedChatKey, StorageScope.APPLICATION, '');
132
+ const originalPersistedSessions = this._persistedSessions;
133
+ let persistedSessions;
134
+ if (sessionData) {
135
+ persistedSessions = this.deserializeChats(sessionData);
136
+ const countsForLog = ( (Object.keys(persistedSessions))).length;
137
+ if (countsForLog > 0) {
138
+ this.trace('constructor', `Restored ${countsForLog} persisted sessions`);
139
+ }
140
+ }
141
+ else {
142
+ persistedSessions = {};
143
+ }
144
+ this._deletedChatIds.forEach(id => delete persistedSessions[id]);
145
+ ( (Object.values(originalPersistedSessions))).forEach(session => {
146
+ const persistedSession = persistedSessions[session.sessionId];
147
+ if (persistedSession && session.requests.length > persistedSession.requests.length) {
148
+ persistedSessions[session.sessionId] = session;
149
+ }
150
+ else if (!persistedSession && session.isNew) {
151
+ session.isNew = false;
152
+ persistedSessions[session.sessionId] = session;
153
+ }
154
+ });
155
+ this._persistedSessions = persistedSessions;
156
+ const allSessions = { ...this._persistedSessions };
157
+ for (const chat of thisWindowChats) {
158
+ allSessions[chat.sessionId] = chat;
159
+ }
160
+ let sessionsList = ( (Object.values(allSessions)));
161
+ sessionsList.sort((a, b) => (b.creationDate ?? 0) - (a.creationDate ?? 0));
162
+ sessionsList = sessionsList.slice(0, maxPersistedSessions);
163
+ const data = JSON.stringify(sessionsList);
164
+ this.storageService.store(serializedChatKey, data, StorageScope.APPLICATION, StorageTarget.MACHINE);
99
165
  }
100
166
  notifyUserAction(action) {
101
167
  this._chatServiceTelemetry.notifyUserAction(action);
102
168
  this._onDidPerformUserAction.fire(action);
103
169
  }
170
+ setChatSessionTitle(sessionId, title) {
171
+ const model = this._sessionModels.get(sessionId);
172
+ if (model) {
173
+ model.setCustomTitle(title);
174
+ return;
175
+ }
176
+ const session = this._persistedSessions[sessionId];
177
+ if (session) {
178
+ session.customTitle = title;
179
+ }
180
+ }
104
181
  trace(method, message) {
105
182
  if (message) {
106
183
  this.logService.trace(`ChatService#${method}: ${message}`);
@@ -134,7 +211,7 @@ let ChatService = class ChatService extends Disposable {
134
211
  request.response = [( (new MarkdownString(request.response)))];
135
212
  }
136
213
  }
137
- acc[session.sessionId] = session;
214
+ acc[session.sessionId] = normalizeSerializableChatData(session);
138
215
  return acc;
139
216
  }, {});
140
217
  return sessions;
@@ -158,27 +235,42 @@ let ChatService = class ChatService extends Disposable {
158
235
  return transferred;
159
236
  }
160
237
  getHistory() {
161
- const sessions = ( (Object.values(this._persistedSessions)))
162
- .filter(session => session.requests.length > 0);
163
- sessions.sort((a, b) => (b.creationDate ?? 0) - (a.creationDate ?? 0));
164
- return (
165
- (sessions
166
- .filter(session => !( (this._sessionModels.has(session.sessionId))))
167
- .filter(session => !session.isImported)
168
- .map(item => {
169
- const title = ChatModel.getDefaultTitle(item.requests);
170
- return {
171
- sessionId: item.sessionId,
172
- title
173
- };
174
- }))
175
- );
238
+ const persistedSessions = ( (Object.values(this._persistedSessions)))
239
+ .filter(session => session.requests.length > 0)
240
+ .filter(session => !( (this._sessionModels.has(session.sessionId))));
241
+ const persistedSessionItems = ( (persistedSessions
242
+ .filter(session => !session.isImported)
243
+ .map(session => {
244
+ const title = session.customTitle ?? ChatModel.getDefaultTitle(session.requests);
245
+ return {
246
+ sessionId: session.sessionId,
247
+ title,
248
+ lastMessageDate: session.lastMessageDate,
249
+ isActive: false,
250
+ };
251
+ })));
252
+ const liveSessionItems = ( (Array.from(( (this._sessionModels.values())))
253
+ .filter(session => !session.isImported)
254
+ .map(session => {
255
+ const title = session.title || ( localize(2568, "New Chat"));
256
+ return {
257
+ sessionId: session.sessionId,
258
+ title,
259
+ lastMessageDate: session.lastMessageDate,
260
+ isActive: true,
261
+ };
262
+ })));
263
+ return [...liveSessionItems, ...persistedSessionItems];
176
264
  }
177
265
  removeHistoryEntry(sessionId) {
178
- delete this._persistedSessions[sessionId];
179
- this.saveState();
266
+ if (this._persistedSessions[sessionId]) {
267
+ this._deletedChatIds.add(sessionId);
268
+ delete this._persistedSessions[sessionId];
269
+ this.saveState();
270
+ }
180
271
  }
181
272
  clearAllHistoryEntries() {
273
+ ( (Object.values(this._persistedSessions))).forEach(session => this._deletedChatIds.add(session.sessionId));
182
274
  this._persistedSessions = {};
183
275
  this.saveState();
184
276
  }
@@ -258,13 +350,14 @@ let ChatService = class ChatService extends Disposable {
258
350
  model.removeRequest(request.id, ChatRequestRemovalReason.Resend);
259
351
  const resendOptions = {
260
352
  ...options,
261
- locationData: request.locationData
353
+ locationData: request.locationData,
354
+ attachedContext: request.attachedContext,
262
355
  };
263
356
  await this._sendRequestAsync(model, model.sessionId, request.message, attempt, enableCommandDetection, defaultAgent, location, resendOptions).responseCompletePromise;
264
357
  }
265
358
  async sendRequest(sessionId, request, options) {
266
359
  this.trace('sendRequest', `sessionId: ${sessionId}, message: ${request.substring(0, 20)}${request.length > 20 ? '[...]' : ''}}`);
267
- if (!request.trim()) {
360
+ if (!request.trim() && !options?.slashCommand && !options?.agentId) {
268
361
  this.trace('sendRequest', 'Rejected empty message');
269
362
  return;
270
363
  }
@@ -315,6 +408,7 @@ let ChatService = class ChatService extends Disposable {
315
408
  const agentPart = 'kind' in parsedRequest ? undefined : parsedRequest.parts.find((r) => r instanceof ChatRequestAgentPart);
316
409
  const agentSlashCommandPart = 'kind' in parsedRequest ? undefined : parsedRequest.parts.find((r) => r instanceof ChatRequestAgentSubcommandPart);
317
410
  const commandPart = 'kind' in parsedRequest ? undefined : parsedRequest.parts.find((r) => r instanceof ChatRequestSlashCommandPart);
411
+ const requests = [...model.getRequests()];
318
412
  let gotProgress = false;
319
413
  const requestType = commandPart ? 'slashCommand' : 'string';
320
414
  const responseCreated = ( (new DeferredPromise()));
@@ -342,6 +436,8 @@ let ChatService = class ChatService extends Disposable {
342
436
  model.acceptResponseProgress(request, progress);
343
437
  completeResponseCreated();
344
438
  };
439
+ let detectedAgent;
440
+ let detectedCommand;
345
441
  const stopWatch = ( (new StopWatch(false)));
346
442
  const listener = token.onCancellationRequested(() => {
347
443
  this.trace('sendRequest', `Request for session ${model.sessionId} was cancelled`);
@@ -355,41 +451,64 @@ let ChatService = class ChatService extends Disposable {
355
451
  slashCommand: agentSlashCommandPart ? agentSlashCommandPart.command.name : commandPart?.slashCommand.command,
356
452
  chatSessionId: model.sessionId,
357
453
  location,
358
- citations: request?.response?.codeCitations.length ?? 0
454
+ citations: request?.response?.codeCitations.length ?? 0,
455
+ numCodeBlocks: getCodeBlocks(request.response?.response.toString() ?? '').length,
456
+ isParticipantDetected: !!detectedAgent
359
457
  });
360
458
  model.cancelRequest(request);
361
459
  });
362
460
  try {
363
461
  let rawResult;
364
462
  let agentOrCommandFollowups = undefined;
463
+ let chatTitlePromise;
365
464
  if (agentPart || (defaultAgent && !commandPart)) {
366
- const agent = (agentPart?.agent ?? defaultAgent);
465
+ const prepareChatAgentRequest = async (agent, command, enableCommandDetection, chatRequest, isParticipantDetected) => {
466
+ const initVariableData = { variables: [] };
467
+ request = chatRequest ?? model.addRequest(parsedRequest, initVariableData, attempt, agent, command, options?.confirmation, options?.locationData, options?.attachedContext);
468
+ const variableData = await this.chatVariablesService.resolveVariables(parsedRequest, request.attachedContext, model, progressCallback, token);
469
+ model.updateRequest(request, variableData);
470
+ const promptTextResult = getPromptText(request.message);
471
+ const updatedVariableData = updateRanges(variableData, promptTextResult.diff);
472
+ return {
473
+ sessionId,
474
+ requestId: request.id,
475
+ agentId: agent.id,
476
+ message: promptTextResult.message,
477
+ command: command?.name,
478
+ variables: updatedVariableData,
479
+ enableCommandDetection,
480
+ isParticipantDetected,
481
+ attempt,
482
+ location,
483
+ locationData: request.locationData,
484
+ acceptedConfirmationData: options?.acceptedConfirmationData,
485
+ rejectedConfirmationData: options?.rejectedConfirmationData,
486
+ };
487
+ };
488
+ if (this.configurationService.getValue('chat.experimental.detectParticipant.enabled') !== false && this.chatAgentService.hasChatParticipantDetectionProviders() && !agentPart && !commandPart && enableCommandDetection) {
489
+ const defaultAgentHistory = this.getHistoryEntriesFromModel(requests, model.sessionId, location, defaultAgent.id);
490
+ const chatAgentRequest = await prepareChatAgentRequest(defaultAgent, agentSlashCommandPart?.command, enableCommandDetection, undefined, false);
491
+ const result = await this.chatAgentService.detectAgentOrCommand(chatAgentRequest, defaultAgentHistory, { location }, token);
492
+ if (result && this.chatAgentService.getAgent(result.agent.id)?.locations?.includes(location)) {
493
+ request.response?.setAgent(result.agent, result.command);
494
+ detectedAgent = result.agent;
495
+ detectedCommand = result.command;
496
+ }
497
+ }
498
+ const agent = (detectedAgent ?? agentPart?.agent ?? defaultAgent);
499
+ const command = detectedCommand ?? agentSlashCommandPart?.command;
367
500
  await this.extensionService.activateByEvent(`onChatParticipant:${agent.id}`);
368
- const history = getHistoryEntriesFromModel(model, agentPart?.agent.id);
369
- const initVariableData = { variables: [] };
370
- request = model.addRequest(parsedRequest, initVariableData, attempt, agent, agentSlashCommandPart?.command, options?.locationData);
501
+ const history = this.getHistoryEntriesFromModel(requests, model.sessionId, location, agent.id);
502
+ const requestProps = await prepareChatAgentRequest(agent, command, enableCommandDetection, request , !!detectedAgent);
503
+ const pendingRequest = this._pendingRequests.get(sessionId);
504
+ if (pendingRequest && !pendingRequest.requestId) {
505
+ pendingRequest.requestId = requestProps.requestId;
506
+ }
371
507
  completeResponseCreated();
372
- const variableData = await this.chatVariablesService.resolveVariables(parsedRequest, options?.attachedContext, model, progressCallback, token);
373
- model.updateRequest(request, variableData);
374
- const promptTextResult = getPromptText(request.message);
375
- const updatedVariableData = updateRanges(variableData, promptTextResult.diff);
376
- const requestProps = {
377
- sessionId,
378
- requestId: request.id,
379
- agentId: agent.id,
380
- message: promptTextResult.message,
381
- command: agentSlashCommandPart?.command.name,
382
- variables: updatedVariableData,
383
- enableCommandDetection,
384
- attempt,
385
- location,
386
- locationData: request.locationData,
387
- acceptedConfirmationData: options?.acceptedConfirmationData,
388
- rejectedConfirmationData: options?.rejectedConfirmationData,
389
- };
390
508
  const agentResult = await this.chatAgentService.invokeAgent(agent.id, requestProps, progressCallback, history, token);
391
509
  rawResult = agentResult;
392
510
  agentOrCommandFollowups = this.chatAgentService.getFollowups(agent.id, requestProps, agentResult, history, followupsCancelToken);
511
+ chatTitlePromise = model.getRequests().length === 1 && !model.customTitle ? this.chatAgentService.getChatTitle(defaultAgent.id, this.getHistoryEntriesFromModel(model.getRequests(), model.sessionId, location, agent.id), CancellationToken.None) : undefined;
393
512
  }
394
513
  else if (commandPart && this.chatSlashCommandService.hasCommand(commandPart.slashCommand.command)) {
395
514
  request = model.addRequest(parsedRequest, { variables: [] }, attempt);
@@ -399,8 +518,8 @@ let ChatService = class ChatService extends Disposable {
399
518
  if (!request.response) {
400
519
  continue;
401
520
  }
402
- history.push({ role: ChatMessageRole.User, content: { type: 'text', value: request.message.text } });
403
- history.push({ role: ChatMessageRole.Assistant, content: { type: 'text', value: ( (request.response.response.toString())) } });
521
+ history.push({ role: ChatMessageRole.User, content: [{ type: 'text', value: request.message.text }] });
522
+ history.push({ role: ChatMessageRole.Assistant, content: [{ type: 'text', value: ( (request.response.response.toString())) }] });
404
523
  }
405
524
  const message = parsedRequest.text;
406
525
  const commandResult = await this.chatSlashCommandService.executeCommand(commandPart.slashCommand.command, message.substring(commandPart.slashCommand.command.length + 1).trimStart(), ( (new Progress(p => {
@@ -418,12 +537,13 @@ let ChatService = class ChatService extends Disposable {
418
537
  else {
419
538
  if (!rawResult) {
420
539
  this.trace('sendRequest', `Provider returned no response for session ${model.sessionId}`);
421
- rawResult = { errorDetails: { message: ( localize(3048, "Provider returned null response")) } };
540
+ rawResult = { errorDetails: { message: ( localize(2569, "Provider returned null response")) } };
422
541
  }
423
542
  const result = rawResult.errorDetails?.responseIsFiltered ? 'filtered' :
424
543
  rawResult.errorDetails && gotProgress ? 'errorWithOutput' :
425
544
  rawResult.errorDetails ? 'error' :
426
545
  'success';
546
+ const commandForTelemetry = agentSlashCommandPart ? agentSlashCommandPart.command.name : commandPart?.slashCommand.command;
427
547
  this.telemetryService.publicLog2('interactiveSessionProviderInvoked', {
428
548
  timeToFirstProgress: rawResult.timings?.firstProgress,
429
549
  totalTime: rawResult.timings?.totalElapsed,
@@ -431,10 +551,12 @@ let ChatService = class ChatService extends Disposable {
431
551
  requestType,
432
552
  agent: agentPart?.agent.id ?? '',
433
553
  agentExtensionId: agentPart?.agent.extensionId.value ?? '',
434
- slashCommand: agentSlashCommandPart ? agentSlashCommandPart.command.name : commandPart?.slashCommand.command,
554
+ slashCommand: commandForTelemetry,
435
555
  chatSessionId: model.sessionId,
556
+ isParticipantDetected: !!detectedAgent,
436
557
  location,
437
- citations: request.response?.codeCitations.length ?? 0
558
+ citations: request.response?.codeCitations.length ?? 0,
559
+ numCodeBlocks: getCodeBlocks(request.response?.response.toString() ?? '').length
438
560
  });
439
561
  model.setResponse(request, rawResult);
440
562
  completeResponseCreated();
@@ -443,8 +565,14 @@ let ChatService = class ChatService extends Disposable {
443
565
  if (agentOrCommandFollowups) {
444
566
  agentOrCommandFollowups.then(followups => {
445
567
  model.setFollowups(request, followups);
568
+ this._chatServiceTelemetry.retrievedFollowups(agentPart?.agent.id ?? '', commandForTelemetry, followups?.length ?? 0);
446
569
  });
447
570
  }
571
+ chatTitlePromise?.then(title => {
572
+ if (title) {
573
+ model.setCustomTitle(title);
574
+ }
575
+ });
448
576
  }
449
577
  }
450
578
  catch (err) {
@@ -459,7 +587,9 @@ let ChatService = class ChatService extends Disposable {
459
587
  slashCommand: agentSlashCommandPart ? agentSlashCommandPart.command.name : commandPart?.slashCommand.command,
460
588
  chatSessionId: model.sessionId,
461
589
  location,
462
- citations: 0
590
+ citations: 0,
591
+ numCodeBlocks: 0,
592
+ isParticipantDetected: !!detectedAgent
463
593
  });
464
594
  this.logService.error(`Error while handling chat request: ${toErrorMessage(err, true)}`);
465
595
  if (request) {
@@ -474,7 +604,7 @@ let ChatService = class ChatService extends Disposable {
474
604
  }
475
605
  };
476
606
  const rawResponsePromise = sendRequestInternal();
477
- this._pendingRequests.set(model.sessionId, source);
607
+ this._pendingRequests.set(model.sessionId, ( (new CancellableRequest(source))));
478
608
  rawResponsePromise.finally(() => {
479
609
  this._pendingRequests.deleteAndDispose(model.sessionId);
480
610
  });
@@ -483,12 +613,41 @@ let ChatService = class ChatService extends Disposable {
483
613
  responseCompletePromise: rawResponsePromise,
484
614
  };
485
615
  }
616
+ getHistoryEntriesFromModel(requests, sessionId, location, forAgentId) {
617
+ const history = [];
618
+ for (const request of requests) {
619
+ if (!request.response) {
620
+ continue;
621
+ }
622
+ const defaultAgentId = this.chatAgentService.getDefaultAgent(location)?.id;
623
+ if (forAgentId !== request.response.agent?.id && forAgentId !== defaultAgentId) {
624
+ continue;
625
+ }
626
+ const promptTextResult = getPromptText(request.message);
627
+ const historyRequest = {
628
+ sessionId: sessionId,
629
+ requestId: request.id,
630
+ agentId: request.response.agent?.id ?? '',
631
+ message: promptTextResult.message,
632
+ command: request.response.slashCommand?.name,
633
+ variables: updateRanges(request.variableData, promptTextResult.diff),
634
+ location: ChatAgentLocation.Panel
635
+ };
636
+ history.push({ request: historyRequest, response: request.response.response.value, result: request.response.result ?? {} });
637
+ }
638
+ return history;
639
+ }
486
640
  async removeRequest(sessionId, requestId) {
487
641
  const model = this._sessionModels.get(sessionId);
488
642
  if (!model) {
489
643
  throw ( (new Error(`Unknown session: ${sessionId}`)));
490
644
  }
491
645
  await model.waitForInitialization();
646
+ const pendingRequest = this._pendingRequests.get(sessionId);
647
+ if (pendingRequest?.requestId === requestId) {
648
+ pendingRequest.cancel();
649
+ this._pendingRequests.deleteAndDispose(sessionId);
650
+ }
492
651
  model.removeRequest(requestId);
493
652
  }
494
653
  async adoptRequest(sessionId, request) {
@@ -505,6 +664,7 @@ let ChatService = class ChatService extends Disposable {
505
664
  if (request.response && !request.response.isComplete) {
506
665
  const cts = this._pendingRequests.deleteAndLeak(oldOwner.sessionId);
507
666
  if (cts) {
667
+ cts.requestId = request.id;
508
668
  this._pendingRequests.set(target.sessionId, cts);
509
669
  }
510
670
  }
@@ -546,7 +706,9 @@ let ChatService = class ChatService extends Disposable {
546
706
  throw ( (new Error(`Unknown session: ${sessionId}`)));
547
707
  }
548
708
  if (model.initialLocation === ChatAgentLocation.Panel) {
549
- this._persistedSessions[sessionId] = JSON.parse(JSON.stringify(model));
709
+ const sessionData = JSON.parse(JSON.stringify(model));
710
+ sessionData.isNew = true;
711
+ this._persistedSessions[sessionId] = sessionData;
550
712
  }
551
713
  this._sessionModels.deleteAndDispose(sessionId);
552
714
  this._pendingRequests.get(sessionId)?.cancel();
@@ -583,7 +745,31 @@ ChatService = ( (__decorate([
583
745
  ( (__param(5, IWorkspaceContextService))),
584
746
  ( (__param(6, IChatSlashCommandService))),
585
747
  ( (__param(7, IChatVariablesService))),
586
- ( (__param(8, IChatAgentService)))
748
+ ( (__param(8, IChatAgentService))),
749
+ ( (__param(9, IWorkbenchAssignmentService))),
750
+ ( (__param(10, IContextKeyService))),
751
+ ( (__param(11, IConfigurationService)))
587
752
  ], ChatService)));
753
+ function getCodeBlocks(text) {
754
+ const lines = text.split('\n');
755
+ const codeBlockLanguages = [];
756
+ let codeBlockState;
757
+ for (let i = 0; i < lines.length; i++) {
758
+ const line = lines[i];
759
+ if (codeBlockState) {
760
+ if (( (new RegExp(`^\\s*${codeBlockState.delimiter}\\s*$`))).test(line)) {
761
+ codeBlockLanguages.push(codeBlockState.languageId);
762
+ codeBlockState = undefined;
763
+ }
764
+ }
765
+ else {
766
+ const match = line.match(/^(\s*)(`{3,}|~{3,})(\w*)/);
767
+ if (match) {
768
+ codeBlockState = { delimiter: match[2], languageId: match[3] };
769
+ }
770
+ }
771
+ }
772
+ return codeBlockLanguages;
773
+ }
588
774
 
589
775
  export { ChatService };
@@ -13,6 +13,7 @@ let ChatServiceTelemetry = class ChatServiceTelemetry {
13
13
  direction: action.action.direction === ChatAgentVoteDirection.Up ? 'up' : 'down',
14
14
  agentId: action.agentId ?? '',
15
15
  command: action.command,
16
+ reason: action.action.reason,
16
17
  });
17
18
  }
18
19
  else if (action.action.kind === 'copy') {
@@ -25,6 +26,8 @@ let ChatServiceTelemetry = class ChatServiceTelemetry {
25
26
  else if (action.action.kind === 'insert') {
26
27
  this.telemetryService.publicLog2('interactiveSessionInsert', {
27
28
  newFile: !!action.action.newFile,
29
+ userAction: action.action.userAction,
30
+ codeMapper: action.action.codeMapper,
28
31
  agentId: action.agentId ?? '',
29
32
  command: action.command,
30
33
  });
@@ -45,6 +48,19 @@ let ChatServiceTelemetry = class ChatServiceTelemetry {
45
48
  command: action.command,
46
49
  });
47
50
  }
51
+ else if (action.action.kind === 'followUp') {
52
+ this.telemetryService.publicLog2('chatFollowupClicked', {
53
+ agentId: action.agentId ?? '',
54
+ command: action.command,
55
+ });
56
+ }
57
+ }
58
+ retrievedFollowups(agentId, command, numFollowups) {
59
+ this.telemetryService.publicLog2('chatFollowupsRetrieved', {
60
+ agentId,
61
+ command,
62
+ numFollowups,
63
+ });
48
64
  }
49
65
  };
50
66
  ChatServiceTelemetry = ( __decorate([
@@ -121,8 +121,8 @@ LanguageModelStatsService = LanguageModelStatsService_1 = ( (__decorate([
121
121
  ], LanguageModelStatsService)));
122
122
  ( (Registry.as(Extensions.ExtensionFeaturesRegistry))).registerExtensionFeature({
123
123
  id: 'languageModels',
124
- label: ( localize(3057, "Language Models")),
125
- description: ( localize(3058, "Language models usage statistics of this extension.")),
124
+ label: ( localize(2578, "Language Models")),
125
+ description: ( localize(2579, "Language models usage statistics of this extension.")),
126
126
  access: {
127
127
  canToggle: false
128
128
  },