@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.
- package/package.json +2 -2
- package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.js +24 -24
- package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatClearActions.js +2 -2
- package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatCodeblockActions.js +73 -22
- package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatContextActions.js +47 -36
- package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatCopyActions.js +2 -2
- package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatDeveloperActions.js +1 -1
- package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatFileTreeActions.js +2 -2
- package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatImportExport.js +5 -4
- package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatMoveActions.js +5 -4
- package/vscode/src/vs/workbench/contrib/chat/browser/chat.contribution.js +27 -21
- package/vscode/src/vs/workbench/contrib/chat/browser/chatAccessibilityService.js +10 -3
- package/vscode/src/vs/workbench/contrib/chat/browser/chatEditor.js +2 -2
- package/vscode/src/vs/workbench/contrib/chat/browser/chatParticipantContributions.js +179 -35
- package/vscode/src/vs/workbench/contrib/chat/browser/chatQuick.js +1 -1
- package/vscode/src/vs/workbench/contrib/chat/browser/chatResponseAccessibleView.js +2 -9
- package/vscode/src/vs/workbench/contrib/chat/browser/chatVariables.js +14 -4
- package/vscode/src/vs/workbench/contrib/chat/browser/chatViewPane.js +14 -7
- package/vscode/src/vs/workbench/contrib/chat/browser/contrib/chatContextAttachments.js +0 -5
- package/vscode/src/vs/workbench/contrib/chat/browser/contrib/chatInputCompletions.js +37 -9
- package/vscode/src/vs/workbench/contrib/chat/browser/contrib/chatInputEditorContrib.js +6 -2
- package/vscode/src/vs/workbench/contrib/chat/browser/contrib/chatInputEditorHover.js +1 -1
- package/vscode/src/vs/workbench/contrib/chat/common/chatServiceImpl.js +253 -67
- package/vscode/src/vs/workbench/contrib/chat/common/chatServiceTelemetry.js +16 -0
- package/vscode/src/vs/workbench/contrib/chat/common/languageModelStats.js +2 -2
- package/vscode/src/vs/workbench/contrib/chat/common/languageModelToolsService.js +59 -18
- package/vscode/src/vs/workbench/contrib/chat/common/tools/languageModelToolsContribution.js +51 -20
- package/vscode/src/vs/workbench/contrib/chat/common/voiceChatService.js +1 -1
- package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChat.contribution.js +28 -49
- package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatCurrentLine.js +130 -0
- package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatNotebook.js +10 -2
- package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatSavingServiceImpl.js +2 -2
- 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 {
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
.
|
|
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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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.
|
|
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
|
|
162
|
-
.filter(session => session.requests.length > 0)
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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
|
-
|
|
179
|
-
|
|
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
|
|
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,
|
|
369
|
-
const
|
|
370
|
-
|
|
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(
|
|
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:
|
|
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
|
-
|
|
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(
|
|
125
|
-
description: ( localize(
|
|
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
|
},
|