@codingame/monaco-vscode-chat-service-override 3.2.2 → 4.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.
@@ -1,14 +1,25 @@
1
1
  import { __decorate, __param } from '../../../../../../../../external/tslib/tslib.es6.js';
2
- import { raceCancellation } from 'vscode/vscode/vs/base/common/async';
2
+ import { MarkdownString } from 'vscode/vscode/vs/base/common/htmlContent';
3
3
  import { Disposable, MutableDisposable } from 'vscode/vscode/vs/base/common/lifecycle';
4
4
  import { ICodeEditorService } from 'vscode/vscode/vs/editor/browser/services/codeEditorService';
5
5
  import { Range } from 'vscode/vscode/vs/editor/common/core/range';
6
6
  import { getWordAtText } from 'vscode/vscode/vs/editor/common/core/wordHelper';
7
7
  import { ILanguageFeaturesService } from 'vscode/vscode/vs/editor/common/services/languageFeatures';
8
8
  import { localizeWithPath } from 'vscode/vscode/vs/nls';
9
+ import { Action2, registerAction2 } from 'vscode/vscode/vs/platform/actions/common/actions';
9
10
  import { IInstantiationService } from 'vscode/vscode/vs/platform/instantiation/common/instantiation';
10
11
  import { Registry } from 'vscode/vscode/vs/platform/registry/common/platform';
11
- import { inputPlaceholderForeground } from 'vscode/vscode/vs/platform/theme/common/colorRegistry';
12
+ import 'vscode/vscode/vs/platform/theme/common/colorUtils';
13
+ import 'vscode/vscode/vs/platform/theme/common/colors/baseColors';
14
+ import 'vscode/vscode/vs/platform/theme/common/colors/chartsColors';
15
+ import 'vscode/vscode/vs/platform/theme/common/colors/editorColors';
16
+ import { inputPlaceholderForeground } from 'vscode/vscode/vs/platform/theme/common/colors/inputColors';
17
+ import 'vscode/vscode/vs/platform/theme/common/colors/listColors';
18
+ import 'vscode/vscode/vs/platform/theme/common/colors/menuColors';
19
+ import 'vscode/vscode/vs/platform/theme/common/colors/minimapColors';
20
+ import 'vscode/vscode/vs/platform/theme/common/colors/miscColors';
21
+ import 'vscode/vscode/vs/platform/theme/common/colors/quickpickColors';
22
+ import 'vscode/vscode/vs/platform/theme/common/colors/searchColors';
12
23
  import { IThemeService } from 'vscode/vscode/vs/platform/theme/common/themeService';
13
24
  import { Extensions } from 'vscode/vscode/vs/workbench/common/contributions';
14
25
  import { SubmitAction } from 'vscode/vscode/vs/workbench/contrib/chat/browser/actions/chatExecuteActions';
@@ -16,9 +27,8 @@ import { IChatWidgetService } from 'vscode/vscode/vs/workbench/contrib/chat/brow
16
27
  import { ChatInputPart } from 'vscode/vscode/vs/workbench/contrib/chat/browser/chatInputPart';
17
28
  import { ChatWidget } from 'vscode/vscode/vs/workbench/contrib/chat/browser/chatWidget';
18
29
  import { SelectAndInsertFileAction, dynamicVariableDecorationType } from 'vscode/vscode/vs/workbench/contrib/chat/browser/contrib/chatDynamicVariables';
19
- import { IChatAgentService } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatAgents';
20
- import { chatSlashCommandForeground, chatSlashCommandBackground } from '../../common/chatColors.js';
21
- import { getHistoryEntriesFromModel } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatModel';
30
+ import { ChatAgentLocation, IChatAgentService } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatAgents';
31
+ import { chatSlashCommandForeground, chatSlashCommandBackground } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatColors';
22
32
  import { chatVariableLeader, ChatRequestVariablePart, ChatRequestAgentPart, ChatRequestAgentSubcommandPart, ChatRequestSlashCommandPart, ChatRequestTextPart, chatAgentLeader, chatSubcommandLeader } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatParserTypes';
23
33
  import { ChatRequestParser } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatRequestParser';
24
34
  import { IChatSlashCommandService } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatSlashCommands';
@@ -30,7 +40,7 @@ const placeholderDecorationType = 'chat-session-detail';
30
40
  const slashCommandTextDecorationType = 'chat-session-text';
31
41
  const variableTextDecorationType = 'chat-variable-text';
32
42
  function agentAndCommandToKey(agent, subcommand) {
33
- return subcommand ? `${agent}__${subcommand}` : agent;
43
+ return subcommand ? `${agent.id}__${subcommand}` : agent.id;
34
44
  }
35
45
  let InputEditorDecorations = class InputEditorDecorations extends Disposable {
36
46
  constructor(widget, codeEditorService, themeService, chatAgentService) {
@@ -47,13 +57,14 @@ let InputEditorDecorations = class InputEditorDecorations extends Disposable {
47
57
  this.updateRegisteredDecorationTypes();
48
58
  this.updateInputEditorDecorations();
49
59
  this._register(this.widget.inputEditor.onDidChangeModelContent(() => this.updateInputEditorDecorations()));
60
+ this._register(this.widget.onDidChangeParsedInput(() => this.updateInputEditorDecorations()));
50
61
  this._register(this.widget.onDidChangeViewModel(() => {
51
62
  this.registerViewModelListeners();
52
63
  this.previouslyUsedAgents.clear();
53
64
  this.updateInputEditorDecorations();
54
65
  }));
55
66
  this._register(this.widget.onDidSubmitAgent((e) => {
56
- this.previouslyUsedAgents.add(agentAndCommandToKey(e.agent.id, e.slashCommand?.name));
67
+ this.previouslyUsedAgents.add(agentAndCommandToKey(e.agent, e.slashCommand?.name));
57
68
  }));
58
69
  this._register(this.chatAgentService.onDidChangeAgents(() => this.updateInputEditorDecorations()));
59
70
  this.registerViewModelListeners();
@@ -99,8 +110,7 @@ let InputEditorDecorations = class InputEditorDecorations extends Disposable {
99
110
  return;
100
111
  }
101
112
  if (!inputValue) {
102
- const viewModelPlaceholder = this.widget.viewModel?.inputPlaceholder;
103
- const placeholder = viewModelPlaceholder ?? '';
113
+ const defaultAgent = this.chatAgentService.getDefaultAgent(this.widget.location);
104
114
  const decoration = [
105
115
  {
106
116
  range: {
@@ -111,7 +121,7 @@ let InputEditorDecorations = class InputEditorDecorations extends Disposable {
111
121
  },
112
122
  renderOptions: {
113
123
  after: {
114
- contentText: placeholder,
124
+ contentText: viewModel.inputPlaceholder ?? defaultAgent?.description ?? '',
115
125
  color: this.getPlaceholderColor()
116
126
  }
117
127
  }
@@ -141,14 +151,14 @@ let InputEditorDecorations = class InputEditorDecorations extends Disposable {
141
151
  });
142
152
  const onlyAgentAndWhitespace = agentPart && parsedRequest.every(p => p instanceof ChatRequestTextPart && !p.text.trim().length || p instanceof ChatRequestAgentPart);
143
153
  if (onlyAgentAndWhitespace) {
144
- const isFollowupSlashCommand = ( this.previouslyUsedAgents.has(agentAndCommandToKey(agentPart.agent.id, undefined)));
154
+ const isFollowupSlashCommand = ( this.previouslyUsedAgents.has(agentAndCommandToKey(agentPart.agent, undefined)));
145
155
  const shouldRenderFollowupPlaceholder = isFollowupSlashCommand && agentPart.agent.metadata.followupPlaceholder;
146
- if (agentPart.agent.metadata.description && exactlyOneSpaceAfterPart(agentPart)) {
156
+ if (agentPart.agent.description && exactlyOneSpaceAfterPart(agentPart)) {
147
157
  placeholderDecoration = [{
148
158
  range: getRangeForPlaceholder(agentPart),
149
159
  renderOptions: {
150
160
  after: {
151
- contentText: shouldRenderFollowupPlaceholder ? agentPart.agent.metadata.followupPlaceholder : agentPart.agent.metadata.description,
161
+ contentText: shouldRenderFollowupPlaceholder ? agentPart.agent.metadata.followupPlaceholder : agentPart.agent.description,
152
162
  color: this.getPlaceholderColor(),
153
163
  }
154
164
  }
@@ -157,7 +167,7 @@ let InputEditorDecorations = class InputEditorDecorations extends Disposable {
157
167
  }
158
168
  const onlyAgentCommandAndWhitespace = agentPart && agentSubcommandPart && parsedRequest.every(p => p instanceof ChatRequestTextPart && !p.text.trim().length || p instanceof ChatRequestAgentPart || p instanceof ChatRequestAgentSubcommandPart);
159
169
  if (onlyAgentCommandAndWhitespace) {
160
- const isFollowupSlashCommand = ( this.previouslyUsedAgents.has(agentAndCommandToKey(agentPart.agent.id, agentSubcommandPart.command.name)));
170
+ const isFollowupSlashCommand = ( this.previouslyUsedAgents.has(agentAndCommandToKey(agentPart.agent, agentSubcommandPart.command.name)));
161
171
  const shouldRenderFollowupPlaceholder = isFollowupSlashCommand && agentSubcommandPart.command.followupPlaceholder;
162
172
  if (agentSubcommandPart?.command.description && exactlyOneSpaceAfterPart(agentSubcommandPart)) {
163
173
  placeholderDecoration = [{
@@ -174,9 +184,12 @@ let InputEditorDecorations = class InputEditorDecorations extends Disposable {
174
184
  this.widget.inputEditor.setDecorationsByType(decorationDescription, placeholderDecorationType, placeholderDecoration ?? []);
175
185
  const textDecorations = [];
176
186
  if (agentPart) {
177
- textDecorations.push({ range: agentPart.editorRange });
187
+ const isDupe = !!this.chatAgentService.getAgents().find(other => other.name === agentPart.agent.name && other.id !== agentPart.agent.id);
188
+ const id = isDupe ? `(${agentPart.agent.id}) ` : '';
189
+ const agentHover = `${id}${agentPart.agent.description}`;
190
+ textDecorations.push({ range: agentPart.editorRange, hoverMessage: ( new MarkdownString(agentHover)) });
178
191
  if (agentSubcommandPart) {
179
- textDecorations.push({ range: agentSubcommandPart.editorRange });
192
+ textDecorations.push({ range: agentSubcommandPart.editorRange, hoverMessage: ( new MarkdownString(agentSubcommandPart.command.description)) });
180
193
  }
181
194
  }
182
195
  if (slashCommandPart) {
@@ -208,10 +221,10 @@ class InputEditorSlashCommandMode extends Disposable {
208
221
  async repopulateAgentCommand(agent, slashCommand) {
209
222
  let value;
210
223
  if (slashCommand && slashCommand.isSticky) {
211
- value = `${chatAgentLeader}${agent.id} ${chatSubcommandLeader}${slashCommand.name} `;
224
+ value = `${chatAgentLeader}${agent.name} ${chatSubcommandLeader}${slashCommand.name} `;
212
225
  }
213
226
  else if (agent.metadata.isSticky) {
214
- value = `${chatAgentLeader}${agent.id} `;
227
+ value = `${chatAgentLeader}${agent.name} `;
215
228
  }
216
229
  if (value) {
217
230
  this.widget.inputEditor.setValue(value);
@@ -231,7 +244,7 @@ let SlashCommandCompletions = class SlashCommandCompletions extends Disposable {
231
244
  triggerCharacters: ['/'],
232
245
  provideCompletionItems: async (model, position, _context, _token) => {
233
246
  const widget = this.chatWidgetService.getWidgetByInputUri(model.uri);
234
- if (!widget || !widget.viewModel) {
247
+ if (!widget || !widget.viewModel || widget.location !== ChatAgentLocation.Panel ) {
235
248
  return null;
236
249
  }
237
250
  const range = computeCompletionRanges(model, position, /\/\w*/g);
@@ -282,7 +295,7 @@ let AgentCompletions = class AgentCompletions extends Disposable {
282
295
  triggerCharacters: ['@'],
283
296
  provideCompletionItems: async (model, position, _context, _token) => {
284
297
  const widget = this.chatWidgetService.getWidgetByInputUri(model.uri);
285
- if (!widget || !widget.viewModel) {
298
+ if (!widget || !widget.viewModel || widget.location !== ChatAgentLocation.Panel ) {
286
299
  return null;
287
300
  }
288
301
  const parsedRequest = widget.parsedInput.parts;
@@ -295,15 +308,20 @@ let AgentCompletions = class AgentCompletions extends Disposable {
295
308
  return null;
296
309
  }
297
310
  const agents = this.chatAgentService.getAgents()
298
- .filter(a => !a.metadata.isDefault);
311
+ .filter(a => !a.isDefault)
312
+ .filter(a => a.locations.includes(widget.location));
299
313
  return {
300
- suggestions: ( agents.map((c, i) => {
301
- const withAt = `@${c.id}`;
314
+ suggestions: ( agents.map((a, i) => {
315
+ const withAt = `@${a.name}`;
316
+ const isDupe = !!agents.find(other => other.name === a.name && other.id !== a.id);
302
317
  return {
303
- label: withAt,
318
+ label: isDupe ?
319
+ { label: withAt, description: a.description, detail: ` (${a.id})` } :
320
+ withAt,
304
321
  insertText: `${withAt} `,
305
- detail: c.metadata.description,
322
+ detail: a.description,
306
323
  range: ( new Range(1, 1, 1, 1)),
324
+ command: { id: AssignSelectedAgentAction.ID, title: AssignSelectedAgentAction.ID, arguments: [{ agent: a, widget }] },
307
325
  kind: 18 ,
308
326
  };
309
327
  }))
@@ -315,7 +333,7 @@ let AgentCompletions = class AgentCompletions extends Disposable {
315
333
  triggerCharacters: ['/'],
316
334
  provideCompletionItems: async (model, position, _context, token) => {
317
335
  const widget = this.chatWidgetService.getWidgetByInputUri(model.uri);
318
- if (!widget || !widget.viewModel) {
336
+ if (!widget || !widget.viewModel || widget.location !== ChatAgentLocation.Panel ) {
319
337
  return;
320
338
  }
321
339
  const range = computeCompletionRanges(model, position, /\/\w*/g);
@@ -337,9 +355,8 @@ let AgentCompletions = class AgentCompletions extends Disposable {
337
355
  }
338
356
  }
339
357
  const usedAgent = parsedRequest[usedAgentIdx];
340
- const commands = await usedAgent.agent.provideSlashCommands(widget.viewModel.model, getHistoryEntriesFromModel(widget.viewModel.model), token);
341
358
  return {
342
- suggestions: ( commands.map((c, i) => {
359
+ suggestions: ( usedAgent.agent.slashCommands.map((c, i) => {
343
360
  const withSlash = `/${c.name}`;
344
361
  return {
345
362
  label: withSlash,
@@ -358,47 +375,48 @@ let AgentCompletions = class AgentCompletions extends Disposable {
358
375
  provideCompletionItems: async (model, position, _context, token) => {
359
376
  const widget = this.chatWidgetService.getWidgetByInputUri(model.uri);
360
377
  const viewModel = widget?.viewModel;
361
- if (!widget || !viewModel) {
378
+ if (!widget || !viewModel || widget.location !== ChatAgentLocation.Panel ) {
362
379
  return;
363
380
  }
364
381
  const range = computeCompletionRanges(model, position, /\/\w*/g);
365
382
  if (!range) {
366
383
  return null;
367
384
  }
368
- const agents = this.chatAgentService.getAgents();
369
- const all = ( agents.map(
370
- agent => agent.provideSlashCommands(viewModel.model, getHistoryEntriesFromModel(viewModel.model), token)
371
- ));
372
- const commands = await raceCancellation(Promise.all(all), token);
373
- if (!commands) {
374
- return;
375
- }
385
+ const agents = this.chatAgentService.getAgents()
386
+ .filter(a => a.locations.includes(widget.location));
376
387
  const justAgents = ( agents
377
- .filter(a => !a.metadata.isDefault)
388
+ .filter(a => !a.isDefault)
378
389
  .map(agent => {
379
- const agentLabel = `${chatAgentLeader}${agent.id}`;
390
+ const isDupe = !!agents.find(other => other.name === agent.name && other.id !== agent.id);
391
+ const detail = agent.description;
392
+ const agentLabel = `${chatAgentLeader}${agent.name}`;
380
393
  return {
381
- label: { label: agentLabel, description: agent.metadata.description },
382
- filterText: `${chatSubcommandLeader}${agent.id}`,
394
+ label: isDupe ?
395
+ { label: agentLabel, description: agent.description, detail: ` (${agent.id})` } :
396
+ agentLabel,
397
+ detail,
398
+ filterText: `${chatSubcommandLeader}${agent.name}`,
383
399
  insertText: `${agentLabel} `,
384
400
  range: ( new Range(1, 1, 1, 1)),
385
401
  kind: 18 ,
386
402
  sortText: `${chatSubcommandLeader}${agent.id}`,
403
+ command: { id: AssignSelectedAgentAction.ID, title: AssignSelectedAgentAction.ID, arguments: [{ agent, widget }] },
387
404
  };
388
405
  }));
389
406
  return {
390
- suggestions: justAgents.concat(agents.flatMap((agent, i) => ( commands[i].map((c, i) => {
391
- const agentLabel = `${chatAgentLeader}${agent.id}`;
407
+ suggestions: justAgents.concat(agents.flatMap(agent => ( agent.slashCommands.map((c, i) => {
408
+ const agentLabel = `${chatAgentLeader}${agent.name}`;
392
409
  const withSlash = `${chatSubcommandLeader}${c.name}`;
393
410
  return {
394
411
  label: { label: withSlash, description: agentLabel },
395
- filterText: `${chatSubcommandLeader}${agent.id}${c.name}`,
412
+ filterText: `${chatSubcommandLeader}${agent.name}${c.name}`,
396
413
  commitCharacters: [' '],
397
414
  insertText: `${agentLabel} ${withSlash} `,
398
- detail: `(${agentLabel}) ${c.description}`,
415
+ detail: `(${agentLabel}) ${c.description ?? ''}`,
399
416
  range: ( new Range(1, 1, 1, 1)),
400
417
  kind: 18 ,
401
418
  sortText: `${chatSubcommandLeader}${agent.id}${c.name}`,
419
+ command: { id: AssignSelectedAgentAction.ID, title: AssignSelectedAgentAction.ID, arguments: [{ agent, widget }] },
402
420
  };
403
421
  }))))
404
422
  };
@@ -412,6 +430,23 @@ AgentCompletions = ( __decorate([
412
430
  ( __param(2, IChatAgentService))
413
431
  ], AgentCompletions));
414
432
  ( Registry.as(Extensions.Workbench)).registerWorkbenchContribution(AgentCompletions, 4 );
433
+ class AssignSelectedAgentAction extends Action2 {
434
+ static { this.ID = 'workbench.action.chat.assignSelectedAgent'; }
435
+ constructor() {
436
+ super({
437
+ id: AssignSelectedAgentAction.ID,
438
+ title: ''
439
+ });
440
+ }
441
+ async run(accessor, ...args) {
442
+ const arg = args[0];
443
+ if (!arg || !arg.widget || !arg.agent) {
444
+ return;
445
+ }
446
+ arg.widget.lastSelectedAgent = arg.agent;
447
+ }
448
+ }
449
+ registerAction2(AssignSelectedAgentAction);
415
450
  let BuiltinDynamicCompletions = class BuiltinDynamicCompletions extends Disposable {
416
451
  static { BuiltinDynamicCompletions_1 = this; }
417
452
  static { this.VariableNameDef = ( new RegExp(`${chatVariableLeader}\\w*`, 'g')); }
@@ -424,7 +459,7 @@ let BuiltinDynamicCompletions = class BuiltinDynamicCompletions extends Disposab
424
459
  triggerCharacters: [chatVariableLeader],
425
460
  provideCompletionItems: async (model, position, _context, _token) => {
426
461
  const widget = this.chatWidgetService.getWidgetByInputUri(model.uri);
427
- if (!widget || !widget.supportsFileReferences) {
462
+ if (!widget || !widget.supportsFileReferences || widget.location !== ChatAgentLocation.Panel ) {
428
463
  return null;
429
464
  }
430
465
  const range = computeCompletionRanges(model, position, BuiltinDynamicCompletions_1.VariableNameDef);
@@ -502,7 +537,7 @@ let VariableCompletions = class VariableCompletions extends Disposable {
502
537
  triggerCharacters: [chatVariableLeader],
503
538
  provideCompletionItems: async (model, position, _context, _token) => {
504
539
  const widget = this.chatWidgetService.getWidgetByInputUri(model.uri);
505
- if (!widget) {
540
+ if (!widget || widget.location !== ChatAgentLocation.Panel ) {
506
541
  return null;
507
542
  }
508
543
  const range = computeCompletionRanges(model, position, VariableCompletions_1.VariableNameDef);
@@ -545,13 +580,15 @@ let ChatTokenDeleter = class ChatTokenDeleter extends Disposable {
545
580
  const parser = this.instantiationService.createInstance(ChatRequestParser);
546
581
  const inputValue = this.widget.inputEditor.getValue();
547
582
  let previousInputValue;
548
- this.widget.inputEditor.onDidChangeModelContent(e => {
583
+ let previousSelectedAgent;
584
+ this._register(this.widget.inputEditor.onDidChangeModelContent(e => {
549
585
  if (!previousInputValue) {
550
586
  previousInputValue = inputValue;
587
+ previousSelectedAgent = this.widget.lastSelectedAgent;
551
588
  }
552
589
  const change = e.changes[0];
553
590
  if (!change.text && this.widget.viewModel) {
554
- const previousParsedValue = parser.parseChatRequest(this.widget.viewModel.sessionId, previousInputValue);
591
+ const previousParsedValue = parser.parseChatRequest(this.widget.viewModel.sessionId, previousInputValue, ChatAgentLocation.Panel, { selectedAgent: previousSelectedAgent });
555
592
  const deletableTokens = previousParsedValue.parts.filter(p => p instanceof ChatRequestAgentPart || p instanceof ChatRequestAgentSubcommandPart || p instanceof ChatRequestSlashCommandPart || p instanceof ChatRequestVariablePart);
556
593
  deletableTokens.forEach(token => {
557
594
  const deletedRangeOfToken = Range.intersectRanges(token.editorRange, change.range);
@@ -571,7 +608,8 @@ let ChatTokenDeleter = class ChatTokenDeleter extends Disposable {
571
608
  });
572
609
  }
573
610
  previousInputValue = this.widget.inputEditor.getValue();
574
- });
611
+ previousSelectedAgent = this.widget.lastSelectedAgent;
612
+ }));
575
613
  }
576
614
  };
577
615
  ChatTokenDeleter = ( __decorate([
@@ -1,7 +1,8 @@
1
1
  import { __decorate, __param } from '../../../../../../../external/tslib/tslib.es6.js';
2
2
  import { Action } from 'vscode/vscode/vs/base/common/actions';
3
3
  import { CancellationToken, CancellationTokenSource } from 'vscode/vscode/vs/base/common/cancellation';
4
- import { Emitter, Event } from 'vscode/vscode/vs/base/common/event';
4
+ import { ErrorNoTelemetry } from 'vscode/vscode/vs/base/common/errors';
5
+ import { Emitter } from 'vscode/vscode/vs/base/common/event';
5
6
  import { MarkdownString } from 'vscode/vscode/vs/base/common/htmlContent';
6
7
  import { Iterable } from 'vscode/vscode/vs/base/common/iterator';
7
8
  import { Disposable, DisposableMap, toDisposable } from 'vscode/vscode/vs/base/common/lifecycle';
@@ -18,7 +19,7 @@ import { Progress } from 'vscode/vscode/vs/platform/progress/common/progress';
18
19
  import { IStorageService } from 'vscode/vscode/vs/platform/storage/common/storage';
19
20
  import { ITelemetryService } from 'vscode/vscode/vs/platform/telemetry/common/telemetry';
20
21
  import { IWorkspaceContextService } from 'vscode/vscode/vs/platform/workspace/common/workspace';
21
- import { IChatAgentService } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatAgents';
22
+ import { ChatAgentLocation, IChatAgentService } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatAgents';
22
23
  import { CONTEXT_PROVIDER_EXISTS } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatContextKeys';
23
24
  import { ChatModel, ChatWelcomeMessageModel, ChatModelInitState, getHistoryEntriesFromModel, updateRanges } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatModel';
24
25
  import { ChatRequestAgentPart, ChatRequestAgentSubcommandPart, ChatRequestSlashCommandPart, getPromptText } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatParserTypes';
@@ -82,11 +83,6 @@ let ChatService = class ChatService extends Disposable {
82
83
  this._transferredSessionData = { sessionId: transferredChat.sessionId, inputValue: transferredData.inputValue };
83
84
  }
84
85
  this._register(storageService.onWillSaveState(() => this.saveState()));
85
- this._register(Event.debounce(this.chatAgentService.onDidChangeAgents, () => { }, 500)(() => {
86
- for (const model of ( this._sessionModels.values())) {
87
- this.warmSlashCommandCache(model);
88
- }
89
- }));
90
86
  }
91
87
  saveState() {
92
88
  let allSessions = Array.from(( this._sessionModels.values()))
@@ -227,19 +223,14 @@ let ChatService = class ChatService extends Disposable {
227
223
  this.trace('reinitializeModel', `Start reinit`);
228
224
  this.initializeSession(model, CancellationToken.None);
229
225
  }
230
- warmSlashCommandCache(model, agent) {
231
- const agents = agent ? [agent] : this.chatAgentService.getAgents();
232
- agents.forEach(agent => agent.provideSlashCommands(model, [], CancellationToken.None));
233
- }
234
226
  async initializeSession(model, token) {
235
227
  try {
236
228
  this.trace('initializeSession', `Initialize session ${model.sessionId}`);
237
- this.warmSlashCommandCache(model);
238
229
  model.startInitialize();
239
230
  await this.extensionService.activateByEvent(`onInteractiveSession:${model.providerId}`);
240
231
  const provider = this._providers.get(model.providerId);
241
232
  if (!provider) {
242
- throw new Error(`Unknown provider: ${model.providerId}`);
233
+ throw new ErrorNoTelemetry(`Unknown provider: ${model.providerId}`);
243
234
  }
244
235
  let session;
245
236
  try {
@@ -252,7 +243,7 @@ let ChatService = class ChatService extends Disposable {
252
243
  throw new Error('Provider returned no session');
253
244
  }
254
245
  this.trace('startSession', `Provider returned session`);
255
- const defaultAgent = this.chatAgentService.getDefaultAgent();
246
+ const defaultAgent = this.chatAgentService.getDefaultAgent(ChatAgentLocation.Panel);
256
247
  if (!defaultAgent) {
257
248
  this.notificationService.notify({
258
249
  severity: Severity.Error,
@@ -273,10 +264,10 @@ let ChatService = class ChatService extends Disposable {
273
264
  ]
274
265
  }
275
266
  });
276
- throw new Error('No default agent');
267
+ throw new ErrorNoTelemetry('No default agent');
277
268
  }
278
269
  const welcomeMessage = model.welcomeMessage ? undefined : (await defaultAgent.provideWelcomeMessage?.(token)) ?? undefined;
279
- const welcomeModel = welcomeMessage && ( new ChatWelcomeMessageModel(model, ( welcomeMessage.map(item => typeof item === 'string' ? ( new MarkdownString(item)) : item)), (await defaultAgent.provideSampleQuestions?.(token)) ?? []));
270
+ const welcomeModel = welcomeMessage && this.instantiationService.createInstance(ChatWelcomeMessageModel, ( welcomeMessage.map(item => typeof item === 'string' ? ( new MarkdownString(item)) : item)), (await defaultAgent.provideSampleQuestions?.(token)) ?? []);
280
271
  model.initialize(session, welcomeModel);
281
272
  }
282
273
  catch (err) {
@@ -310,7 +301,7 @@ let ChatService = class ChatService extends Disposable {
310
301
  loadSessionFromContent(data) {
311
302
  return this._startSession(data.providerId, data, CancellationToken.None);
312
303
  }
313
- async sendRequest(sessionId, request) {
304
+ async sendRequest(sessionId, request, implicitVariablesEnabled, location = ChatAgentLocation.Panel, parserContext) {
314
305
  this.trace('sendRequest', `sessionId: ${sessionId}, message: ${request.substring(0, 20)}${request.length > 20 ? '[...]' : ''}}`);
315
306
  if (!request.trim()) {
316
307
  this.trace('sendRequest', 'Rejected empty message');
@@ -329,11 +320,12 @@ let ChatService = class ChatService extends Disposable {
329
320
  this.trace('sendRequest', `Session ${sessionId} already has a pending request`);
330
321
  return;
331
322
  }
332
- const parsedRequest = this.instantiationService.createInstance(ChatRequestParser).parseChatRequest(sessionId, request);
333
- const agent = parsedRequest.parts.find((r) => r instanceof ChatRequestAgentPart)?.agent ?? this.chatAgentService.getDefaultAgent();
323
+ const defaultAgent = this.chatAgentService.getDefaultAgent(location);
324
+ const parsedRequest = this.instantiationService.createInstance(ChatRequestParser).parseChatRequest(sessionId, request, location, parserContext);
325
+ const agent = parsedRequest.parts.find((r) => r instanceof ChatRequestAgentPart)?.agent ?? defaultAgent;
334
326
  const agentSlashCommandPart = parsedRequest.parts.find((r) => r instanceof ChatRequestAgentSubcommandPart);
335
327
  return {
336
- responseCompletePromise: this._sendRequestAsync(model, sessionId, provider, parsedRequest),
328
+ responseCompletePromise: this._sendRequestAsync(model, sessionId, provider, parsedRequest, implicitVariablesEnabled ?? false, defaultAgent, location),
337
329
  agent,
338
330
  slashCommand: agentSlashCommandPart?.command,
339
331
  };
@@ -344,7 +336,7 @@ let ChatService = class ChatService extends Disposable {
344
336
  this._sessionFollowupCancelTokens.set(sessionId, newTokenSource);
345
337
  return newTokenSource.token;
346
338
  }
347
- async _sendRequestAsync(model, sessionId, provider, parsedRequest) {
339
+ async _sendRequestAsync(model, sessionId, provider, parsedRequest, implicitVariablesEnabled, defaultAgent, location) {
348
340
  const followupsCancelToken = this.refreshFollowupsCancellationToken(sessionId);
349
341
  let request;
350
342
  const agentPart = 'kind' in parsedRequest ? undefined : parsedRequest.parts.find((r) => r instanceof ChatRequestAgentPart);
@@ -386,26 +378,37 @@ let ChatService = class ChatService extends Disposable {
386
378
  try {
387
379
  let rawResult;
388
380
  let agentOrCommandFollowups = undefined;
389
- const defaultAgent = this.chatAgentService.getDefaultAgent();
390
381
  if (agentPart || (defaultAgent && !commandPart)) {
391
382
  const agent = (agentPart?.agent ?? defaultAgent);
383
+ await this.extensionService.activateByEvent(`onChatParticipant:${agent.id}`);
392
384
  const history = getHistoryEntriesFromModel(model);
393
385
  const initVariableData = { variables: [] };
394
386
  request = model.addRequest(parsedRequest, initVariableData, agent, agentSlashCommandPart?.command);
395
387
  const variableData = await this.chatVariablesService.resolveVariables(parsedRequest, model, progressCallback, token);
396
388
  request.variableData = variableData;
397
389
  const promptTextResult = getPromptText(request.message);
390
+ const updatedVariableData = updateRanges(variableData, promptTextResult.diff);
391
+ if (implicitVariablesEnabled) {
392
+ const implicitVariables = agent.defaultImplicitVariables;
393
+ if (implicitVariables) {
394
+ const resolvedImplicitVariables = await Promise.all(( implicitVariables.map(
395
+ async (v) => ({ name: v, values: await this.chatVariablesService.resolveVariable(v, parsedRequest.text, model, progressCallback, token) })
396
+ )));
397
+ updatedVariableData.variables.push(...resolvedImplicitVariables);
398
+ }
399
+ }
398
400
  const requestProps = {
399
401
  sessionId,
400
402
  requestId: request.id,
401
403
  agentId: agent.id,
402
404
  message: promptTextResult.message,
403
405
  command: agentSlashCommandPart?.command.name,
404
- variables: updateRanges(variableData, promptTextResult.diff)
406
+ variables: updatedVariableData,
407
+ location
405
408
  };
406
409
  const agentResult = await this.chatAgentService.invokeAgent(agent.id, requestProps, progressCallback, history, token);
407
410
  rawResult = agentResult;
408
- agentOrCommandFollowups = this.chatAgentService.getFollowups(agent.id, requestProps, agentResult, followupsCancelToken);
411
+ agentOrCommandFollowups = this.chatAgentService.getFollowups(agent.id, requestProps, agentResult, history, followupsCancelToken);
409
412
  }
410
413
  else if (commandPart && this.chatSlashCommandService.hasCommand(commandPart.slashCommand.command)) {
411
414
  request = model.addRequest(parsedRequest, { variables: [] });
@@ -486,10 +489,6 @@ let ChatService = class ChatService extends Disposable {
486
489
  }
487
490
  model.removeRequest(requestId);
488
491
  }
489
- async sendRequestToProvider(sessionId, message) {
490
- this.trace('sendRequestToProvider', `sessionId: ${sessionId}`);
491
- return await this.sendRequest(sessionId, message.message);
492
- }
493
492
  getProviders() {
494
493
  return Array.from(( this._providers.keys()));
495
494
  }
@@ -0,0 +1,141 @@
1
+ import { __decorate, __param } from '../../../../../../../external/tslib/tslib.es6.js';
2
+ import { Emitter } from 'vscode/vscode/vs/base/common/event';
3
+ import { Disposable, DisposableStore } from 'vscode/vscode/vs/base/common/lifecycle';
4
+ import { rtrim } from 'vscode/vscode/vs/base/common/strings';
5
+ import 'vscode/vscode/vs/platform/instantiation/common/instantiation';
6
+ import { IChatAgentService } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatAgents';
7
+ import { chatAgentLeader, chatSubcommandLeader } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatParserTypes';
8
+ import { SpeechToTextStatus, ISpeechService } from 'vscode/vscode/vs/workbench/contrib/speech/common/speechService';
9
+
10
+ var VoiceChatService_1;
11
+ var PhraseTextType;
12
+ ( (function(PhraseTextType) {
13
+ PhraseTextType[PhraseTextType["AGENT"] = 1] = "AGENT";
14
+ PhraseTextType[PhraseTextType["COMMAND"] = 2] = "COMMAND";
15
+ PhraseTextType[PhraseTextType["AGENT_AND_COMMAND"] = 3] = "AGENT_AND_COMMAND";
16
+ })(PhraseTextType || (PhraseTextType = {})));
17
+ let VoiceChatService = class VoiceChatService extends Disposable {
18
+ static { VoiceChatService_1 = this; }
19
+ static { this.AGENT_PREFIX = chatAgentLeader; }
20
+ static { this.COMMAND_PREFIX = chatSubcommandLeader; }
21
+ static { this.PHRASES_LOWER = {
22
+ [VoiceChatService_1.AGENT_PREFIX]: 'at',
23
+ [VoiceChatService_1.COMMAND_PREFIX]: 'slash'
24
+ }; }
25
+ static { this.PHRASES_UPPER = {
26
+ [VoiceChatService_1.AGENT_PREFIX]: 'At',
27
+ [VoiceChatService_1.COMMAND_PREFIX]: 'Slash'
28
+ }; }
29
+ static { this.CHAT_AGENT_ALIAS = ( new Map([['vscode', 'code']])); }
30
+ constructor(speechService, chatAgentService) {
31
+ super();
32
+ this.speechService = speechService;
33
+ this.chatAgentService = chatAgentService;
34
+ }
35
+ createPhrases(model) {
36
+ const phrases = ( new Map());
37
+ for (const agent of this.chatAgentService.getActivatedAgents()) {
38
+ const agentPhrase = `${VoiceChatService_1.PHRASES_LOWER[VoiceChatService_1.AGENT_PREFIX]} ${VoiceChatService_1.CHAT_AGENT_ALIAS.get(agent.id) ?? agent.id}`.toLowerCase();
39
+ phrases.set(agentPhrase, { agent: agent.id });
40
+ for (const slashCommand of agent.slashCommands) {
41
+ const slashCommandPhrase = `${VoiceChatService_1.PHRASES_LOWER[VoiceChatService_1.COMMAND_PREFIX]} ${slashCommand.name}`.toLowerCase();
42
+ phrases.set(slashCommandPhrase, { agent: agent.id, command: slashCommand.name });
43
+ const agentSlashCommandPhrase = `${agentPhrase} ${slashCommandPhrase}`.toLowerCase();
44
+ phrases.set(agentSlashCommandPhrase, { agent: agent.id, command: slashCommand.name });
45
+ }
46
+ }
47
+ return phrases;
48
+ }
49
+ toText(value, type) {
50
+ switch (type) {
51
+ case PhraseTextType.AGENT:
52
+ return `${VoiceChatService_1.AGENT_PREFIX}${value.agent}`;
53
+ case PhraseTextType.COMMAND:
54
+ return `${VoiceChatService_1.COMMAND_PREFIX}${value.command}`;
55
+ case PhraseTextType.AGENT_AND_COMMAND:
56
+ return `${VoiceChatService_1.AGENT_PREFIX}${value.agent} ${VoiceChatService_1.COMMAND_PREFIX}${value.command}`;
57
+ }
58
+ }
59
+ async createVoiceChatSession(token, options) {
60
+ const disposables = ( new DisposableStore());
61
+ disposables.add(token.onCancellationRequested(() => disposables.dispose()));
62
+ let detectedAgent = false;
63
+ let detectedSlashCommand = false;
64
+ const emitter = disposables.add(( new Emitter()));
65
+ const session = await this.speechService.createSpeechToTextSession(token, 'chat');
66
+ const phrases = this.createPhrases(options.model);
67
+ disposables.add(session.onDidChange(e => {
68
+ switch (e.status) {
69
+ case SpeechToTextStatus.Recognizing:
70
+ case SpeechToTextStatus.Recognized:
71
+ if (e.text) {
72
+ const startsWithAgent = e.text.startsWith(VoiceChatService_1.PHRASES_UPPER[VoiceChatService_1.AGENT_PREFIX]) || e.text.startsWith(VoiceChatService_1.PHRASES_LOWER[VoiceChatService_1.AGENT_PREFIX]);
73
+ const startsWithSlashCommand = e.text.startsWith(VoiceChatService_1.PHRASES_UPPER[VoiceChatService_1.COMMAND_PREFIX]) || e.text.startsWith(VoiceChatService_1.PHRASES_LOWER[VoiceChatService_1.COMMAND_PREFIX]);
74
+ if (startsWithAgent || startsWithSlashCommand) {
75
+ const originalWords = e.text.split(' ');
76
+ let transformedWords;
77
+ let waitingForInput = false;
78
+ if (options.usesAgents && startsWithAgent && !detectedAgent && !detectedSlashCommand && originalWords.length >= 4) {
79
+ const phrase = phrases.get(( originalWords.slice(0, 4).map(word => this.normalizeWord(word))).join(' '));
80
+ if (phrase) {
81
+ transformedWords = [this.toText(phrase, PhraseTextType.AGENT_AND_COMMAND), ...originalWords.slice(4)];
82
+ waitingForInput = originalWords.length === 4;
83
+ if (e.status === SpeechToTextStatus.Recognized) {
84
+ detectedAgent = true;
85
+ detectedSlashCommand = true;
86
+ }
87
+ }
88
+ }
89
+ if (options.usesAgents && startsWithAgent && !detectedAgent && !transformedWords && originalWords.length >= 2) {
90
+ const phrase = phrases.get(( originalWords.slice(0, 2).map(word => this.normalizeWord(word))).join(' '));
91
+ if (phrase) {
92
+ transformedWords = [this.toText(phrase, PhraseTextType.AGENT), ...originalWords.slice(2)];
93
+ waitingForInput = originalWords.length === 2;
94
+ if (e.status === SpeechToTextStatus.Recognized) {
95
+ detectedAgent = true;
96
+ }
97
+ }
98
+ }
99
+ if (startsWithSlashCommand && !detectedSlashCommand && !transformedWords && originalWords.length >= 2) {
100
+ const phrase = phrases.get(( originalWords.slice(0, 2).map(word => this.normalizeWord(word))).join(' '));
101
+ if (phrase) {
102
+ transformedWords = [this.toText(phrase, options.usesAgents && !detectedAgent ?
103
+ PhraseTextType.AGENT_AND_COMMAND :
104
+ PhraseTextType.COMMAND
105
+ ), ...originalWords.slice(2)];
106
+ waitingForInput = originalWords.length === 2;
107
+ if (e.status === SpeechToTextStatus.Recognized) {
108
+ detectedSlashCommand = true;
109
+ }
110
+ }
111
+ }
112
+ emitter.fire({
113
+ status: e.status,
114
+ text: (transformedWords ?? originalWords).join(' '),
115
+ waitingForInput
116
+ });
117
+ break;
118
+ }
119
+ }
120
+ default:
121
+ emitter.fire(e);
122
+ break;
123
+ }
124
+ }));
125
+ return {
126
+ onDidChange: emitter.event
127
+ };
128
+ }
129
+ normalizeWord(word) {
130
+ word = rtrim(word, '.');
131
+ word = rtrim(word, ',');
132
+ word = rtrim(word, '?');
133
+ return word.toLowerCase();
134
+ }
135
+ };
136
+ VoiceChatService = VoiceChatService_1 = ( __decorate([
137
+ ( __param(0, ISpeechService)),
138
+ ( __param(1, IChatAgentService))
139
+ ], VoiceChatService));
140
+
141
+ export { VoiceChatService };