@codingame/monaco-vscode-chat-service-override 10.1.3 → 11.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 (50) hide show
  1. package/chat.js +6 -3
  2. package/package.json +6 -2
  3. package/vscode/src/vs/editor/common/diff/documentDiffProvider.js +8 -0
  4. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.js +84 -38
  5. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatClearActions.js +265 -20
  6. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatCodeblockActions.js +20 -39
  7. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatContextActions.js +373 -216
  8. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatCopyActions.js +4 -5
  9. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatDeveloperActions.js +1 -1
  10. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatFileTreeActions.js +4 -5
  11. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatGettingStarted.js +54 -0
  12. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatImportExport.js +6 -7
  13. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatMoveActions.js +12 -11
  14. package/vscode/src/vs/workbench/contrib/chat/browser/actions/codeBlockOperations.js +14 -42
  15. package/vscode/src/vs/workbench/contrib/chat/browser/chat.contribution.js +82 -50
  16. package/vscode/src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingModifiedFileEntry.js +326 -0
  17. package/vscode/src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingService.js +448 -0
  18. package/vscode/src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingSession.js +507 -0
  19. package/vscode/src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingTextModelContentProviders.js +76 -0
  20. package/vscode/src/vs/workbench/contrib/chat/browser/chatEditor.js +4 -4
  21. package/vscode/src/vs/workbench/contrib/chat/browser/chatEditorActions.js +109 -0
  22. package/vscode/src/vs/workbench/contrib/chat/browser/chatEditorController.js +284 -0
  23. package/vscode/src/vs/workbench/contrib/chat/browser/chatParticipantContributions.js +116 -77
  24. package/vscode/src/vs/workbench/contrib/chat/browser/chatPasteProviders.js +100 -9
  25. package/vscode/src/vs/workbench/contrib/chat/browser/chatQuick.js +3 -3
  26. package/vscode/src/vs/workbench/contrib/chat/browser/chatResponseAccessibleView.js +1 -1
  27. package/vscode/src/vs/workbench/contrib/chat/browser/chatVariables.js +7 -9
  28. package/vscode/src/vs/workbench/contrib/chat/browser/chatViewPane.js +61 -42
  29. package/vscode/src/vs/workbench/contrib/chat/browser/contrib/chatInputEditorContrib.js +5 -5
  30. package/vscode/src/vs/workbench/contrib/chat/browser/contrib/chatInputEditorHover.js +3 -3
  31. package/vscode/src/vs/workbench/contrib/chat/{common → browser}/languageModelToolsService.js +28 -31
  32. package/vscode/src/vs/workbench/contrib/chat/browser/viewsWelcome/chatViewsWelcomeContributions.js +75 -0
  33. package/vscode/src/vs/workbench/contrib/chat/common/chatCodeMapperService.js +120 -1
  34. package/vscode/src/vs/workbench/contrib/chat/common/chatProgressTypes/chatToolInvocation.js +10 -8
  35. package/vscode/src/vs/workbench/contrib/chat/common/chatServiceImpl.js +33 -18
  36. package/vscode/src/vs/workbench/contrib/chat/common/chatWidgetHistoryService.js +1 -1
  37. package/vscode/src/vs/workbench/contrib/chat/common/ignoredFiles.js +21 -0
  38. package/vscode/src/vs/workbench/contrib/chat/common/languageModelStats.js +2 -2
  39. package/vscode/src/vs/workbench/contrib/chat/common/languageModels.js +6 -6
  40. package/vscode/src/vs/workbench/contrib/chat/common/tools/languageModelToolsContribution.js +68 -47
  41. package/vscode/src/vs/workbench/contrib/chat/common/tools/languageModelToolsParametersSchema.js +250 -0
  42. package/vscode/src/vs/workbench/contrib/chat/common/voiceChatService.js +2 -2
  43. package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChat.contribution.js +7 -8
  44. package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatAccessibilityHelp.js +1 -1
  45. package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatAccessibleView.js +1 -1
  46. package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatCurrentLine.js +3 -3
  47. package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatNotebook.js +2 -2
  48. package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatSavingServiceImpl.js +65 -128
  49. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatQuickInputActions.js +0 -170
  50. package/vscode/src/vs/workbench/contrib/chat/browser/chatGettingStarted.js +0 -131
@@ -1,6 +1,7 @@
1
1
  import { CancellationToken } from 'vscode/vscode/vs/base/common/cancellation';
2
2
  import { Codicon } from 'vscode/vscode/vs/base/common/codicons';
3
3
  import { Schemas } from 'vscode/vscode/vs/base/common/network';
4
+ import { isElectron } from 'vscode/vscode/vs/base/common/platform';
4
5
  import { compare } from 'vscode/vscode/vs/base/common/strings';
5
6
  import { ThemeIcon } from 'vscode/vscode/vs/base/common/themables';
6
7
  import { URI } from 'vscode/vscode/vs/base/common/uri';
@@ -8,44 +9,84 @@ import { EditorType } from 'vscode/vscode/vs/editor/common/editorCommon';
8
9
  import { AbstractGotoSymbolQuickAccessProvider } from 'vscode/vscode/vs/editor/contrib/quickAccess/browser/gotoSymbolQuickAccess';
9
10
  import { localize2, localize } from 'vscode/vscode/vs/nls';
10
11
  import { registerAction2, Action2, MenuId } from 'vscode/vscode/vs/platform/actions/common/actions';
12
+ import { IClipboardService } from 'vscode/vscode/vs/platform/clipboard/common/clipboardService.service';
11
13
  import { ICommandService } from 'vscode/vscode/vs/platform/commands/common/commands.service';
12
14
  import { ContextKeyExpr } from 'vscode/vscode/vs/platform/contextkey/common/contextkey';
15
+ import { IContextKeyService } from 'vscode/vscode/vs/platform/contextkey/common/contextkey.service';
16
+ import { ILabelService } from 'vscode/vscode/vs/platform/label/common/label.service';
13
17
  import { IQuickInputService } from 'vscode/vscode/vs/platform/quickinput/common/quickInput.service';
14
- import 'vscode/vscode/vs/workbench/contrib/chat/browser/actions/chatActions';
15
- import { showChatView } from 'vscode/vscode/vs/workbench/contrib/chat/browser/chat';
16
- import { IChatWidgetService, IQuickChatService } from 'vscode/vscode/vs/workbench/contrib/chat/browser/chat.service';
17
- import { isQuickChat } from 'vscode/vscode/vs/workbench/contrib/chat/browser/chatWidget';
18
- import { ChatContextAttachments } from 'vscode/vscode/vs/workbench/contrib/chat/browser/contrib/chatContextAttachments';
18
+ import { ActiveEditorContext } from 'vscode/vscode/vs/workbench/common/contextkeys';
19
+ import { DiffEditorInput } from 'vscode/vscode/vs/workbench/common/editor/diffEditorInput';
20
+ import { IEditorService } from 'vscode/vscode/vs/workbench/services/editor/common/editorService.service';
21
+ import { isProposedApiEnabled } from 'vscode/vscode/vs/workbench/services/extensions/common/extensions';
22
+ import { IExtensionService } from 'vscode/vscode/vs/workbench/services/extensions/common/extensions.service';
23
+ import { IHostService } from 'vscode/vscode/vs/workbench/services/host/browser/host.service';
24
+ import { VIEW_ID } from 'vscode/vscode/vs/workbench/services/search/common/search';
25
+ import { UntitledTextEditorInput } from 'vscode/vscode/vs/workbench/services/untitled/common/untitledTextEditorInput';
26
+ import { IViewsService } from 'vscode/vscode/vs/workbench/services/views/common/viewsService.service';
27
+ import { FileEditorInput } from 'vscode/vscode/vs/workbench/contrib/files/browser/editors/fileEditorInput';
28
+ import { AnythingQuickAccessProvider } from 'vscode/vscode/vs/workbench/contrib/search/browser/anythingQuickAccess';
29
+ import { SymbolsQuickAccessProvider } from 'vscode/vscode/vs/workbench/contrib/search/browser/symbolsQuickAccess';
30
+ import { SearchContext } from 'vscode/vscode/vs/workbench/contrib/search/common/constants';
19
31
  import { ChatAgentLocation } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatAgents';
20
32
  import { IChatAgentService } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatAgents.service';
21
- import { CONTEXT_CHAT_LOCATION, CONTEXT_IN_CHAT_INPUT } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatContextKeys';
22
- import { ChatRequestAgentPart } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatParserTypes';
33
+ import { CONTEXT_CHAT_ENABLED, CONTEXT_CHAT_LOCATION, CONTEXT_IN_CHAT_INPUT } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatContextKeys';
34
+ import { IChatEditingService } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatEditingService.service';
35
+ import { ChatRequestAgentPart } from '@codingame/monaco-vscode-chat-extensions-interactive-notebook-quickaccess-search-terminal-common/vscode/vs/workbench/contrib/chat/common/chatParserTypes';
23
36
  import { IChatVariablesService } from 'vscode/vscode/vs/workbench/contrib/chat/common/chatVariables.service';
24
37
  import { ILanguageModelToolsService } from 'vscode/vscode/vs/workbench/contrib/chat/common/languageModelToolsService.service';
25
- import { AnythingQuickAccessProvider } from 'vscode/vscode/vs/workbench/contrib/search/browser/anythingQuickAccess';
26
- import { SymbolsQuickAccessProvider } from 'vscode/vscode/vs/workbench/contrib/search/browser/symbolsQuickAccess';
27
- import { IEditorService } from 'vscode/vscode/vs/workbench/services/editor/common/editorService.service';
28
- import { IClipboardService } from 'vscode/vscode/vs/platform/clipboard/common/clipboardService.service';
29
- import { imageToHash, isImage } from 'vscode/vscode/vs/workbench/contrib/chat/browser/chatImagePaste';
30
- import { IConfigurationService } from 'vscode/vscode/vs/platform/configuration/common/configuration.service';
31
- import { ActiveEditorContext } from 'vscode/vscode/vs/workbench/common/contextkeys';
32
- import { IViewsService } from 'vscode/vscode/vs/workbench/services/views/common/viewsService.service';
33
- import { CHAT_CATEGORY } from 'vscode/vscode/vs/workbench/contrib/chat/browser/actions/chatConstants';
38
+ import { showChatView } from '@codingame/monaco-vscode-chat-extensions-interactive-notebook-quickaccess-search-terminal-common/vscode/vs/workbench/contrib/chat/browser/chat';
39
+ import { IChatWidgetService, IQuickChatService } from 'vscode/vscode/vs/workbench/contrib/chat/browser/chat.service';
40
+ import { imageToHash, isImage } from '../chatPasteProviders.js';
41
+ import { isQuickChat } from '@codingame/monaco-vscode-chat-extensions-notebook-common/vscode/vs/workbench/contrib/chat/browser/chatWidget';
42
+ import { convertBufferToScreenshotVariable, ScreenshotVariableId } from '@codingame/monaco-vscode-chat-extensions-interactive-notebook-quickaccess-search-terminal-common/vscode/vs/workbench/contrib/chat/browser/contrib/screenshot';
43
+ import { CHAT_CATEGORY } from '@codingame/monaco-vscode-chat-extensions-interactive-notebook-quickaccess-search-terminal-common/vscode/vs/workbench/contrib/chat/browser/actions/chatActions';
34
44
 
35
45
  function registerChatContextActions() {
36
46
  registerAction2(AttachContextAction);
37
47
  registerAction2(AttachFileAction);
38
48
  registerAction2(AttachSelectionAction);
39
49
  }
50
+ function isIGotoSymbolQuickPickItem(obj) {
51
+ return (typeof obj === 'object'
52
+ && typeof obj.symbolName === 'string'
53
+ && !!obj.uri
54
+ && !!obj.range);
55
+ }
56
+ function isISymbolQuickPickItem(obj) {
57
+ return (typeof obj === 'object'
58
+ && typeof obj.symbol === 'object'
59
+ && !!obj.symbol);
60
+ }
61
+ function isIQuickPickItemWithResource(obj) {
62
+ return (typeof obj === 'object'
63
+ && typeof obj.resource === 'object'
64
+ && URI.isUri(obj.resource));
65
+ }
66
+ function isIOpenEditorsQuickPickItem(obj) {
67
+ return (typeof obj === 'object'
68
+ && obj.id === 'open-editors');
69
+ }
70
+ function isISearchResultsQuickPickItem(obj) {
71
+ return (typeof obj === 'object'
72
+ && obj.kind === 'search-results');
73
+ }
74
+ function isScreenshotQuickPickItem(obj) {
75
+ return (typeof obj === 'object'
76
+ && obj.kind === 'screenshot');
77
+ }
40
78
  class AttachFileAction extends Action2 {
41
79
  static { this.ID = 'workbench.action.chat.attachFile'; }
42
80
  constructor() {
43
81
  super({
44
82
  id: AttachFileAction.ID,
45
- title: ( localize2(7312, "Add File to Chat")),
83
+ title: ( localize2(7532, "Add File to Chat")),
46
84
  category: CHAT_CATEGORY,
47
85
  f1: false,
48
- precondition: ( (ActiveEditorContext.isEqualTo('workbench.editors.files.textFileEditor'))),
86
+ precondition: ( (ContextKeyExpr.and(
87
+ CONTEXT_CHAT_ENABLED,
88
+ (ActiveEditorContext.isEqualTo('workbench.editors.files.textFileEditor'))
89
+ ))),
49
90
  menu: {
50
91
  id: MenuId.ChatCommandCenter,
51
92
  group: 'a_chat',
@@ -68,10 +109,13 @@ class AttachSelectionAction extends Action2 {
68
109
  constructor() {
69
110
  super({
70
111
  id: AttachSelectionAction.ID,
71
- title: ( localize2(7313, "Add Selection to Chat")),
112
+ title: ( localize2(7533, "Add Selection to Chat")),
72
113
  category: CHAT_CATEGORY,
73
114
  f1: false,
74
- precondition: ( (ActiveEditorContext.isEqualTo('workbench.editors.files.textFileEditor'))),
115
+ precondition: ( (ContextKeyExpr.and(
116
+ CONTEXT_CHAT_ENABLED,
117
+ (ActiveEditorContext.isEqualTo('workbench.editors.files.textFileEditor'))
118
+ ))),
75
119
  menu: {
76
120
  id: MenuId.ChatCommandCenter,
77
121
  group: 'a_chat',
@@ -97,52 +141,51 @@ class AttachContextAction extends Action2 {
97
141
  static { this.ID = 'workbench.action.chat.attachContext'; }
98
142
  static { this._cdt = ( (ContextKeyExpr.or(
99
143
  (ContextKeyExpr.and( (CONTEXT_CHAT_LOCATION.isEqualTo(ChatAgentLocation.Panel)))),
144
+ (ContextKeyExpr.and( (CONTEXT_CHAT_LOCATION.isEqualTo(ChatAgentLocation.Editor)))),
100
145
  (ContextKeyExpr.and(
101
- (CONTEXT_CHAT_LOCATION.isEqualTo(ChatAgentLocation.Editor)),
102
- (ContextKeyExpr.equals('config.chat.experimental.variables.editor', true))
146
+ (CONTEXT_CHAT_LOCATION.isEqualTo(ChatAgentLocation.Notebook))
103
147
  )),
104
148
  (ContextKeyExpr.and(
105
- (CONTEXT_CHAT_LOCATION.isEqualTo(ChatAgentLocation.Notebook)),
106
- (ContextKeyExpr.equals('config.chat.experimental.variables.notebook', true))
107
- )),
108
- (ContextKeyExpr.and(
109
- (CONTEXT_CHAT_LOCATION.isEqualTo(ChatAgentLocation.Terminal)),
110
- (ContextKeyExpr.equals('config.chat.experimental.variables.terminal', true))
149
+ (CONTEXT_CHAT_LOCATION.isEqualTo(ChatAgentLocation.Terminal))
111
150
  ))
112
151
  ))); }
113
- constructor() {
114
- super({
115
- id: AttachContextAction.ID,
116
- title: ( localize2(7314, "Attach Context")),
117
- icon: Codicon.attach,
118
- category: CHAT_CATEGORY,
119
- precondition: AttachContextAction._cdt,
120
- keybinding: {
121
- when: CONTEXT_IN_CHAT_INPUT,
122
- primary: 2048 | 90 ,
123
- weight: 100
152
+ constructor(desc = {
153
+ id: AttachContextAction.ID,
154
+ title: ( localize2(7534, "Attach Context")),
155
+ icon: Codicon.attach,
156
+ category: CHAT_CATEGORY,
157
+ precondition: ( (ContextKeyExpr.or(AttachContextAction._cdt, (ContextKeyExpr.and(
158
+ (CONTEXT_CHAT_LOCATION.isEqualTo(ChatAgentLocation.EditingSession))
159
+ ))))),
160
+ keybinding: {
161
+ when: CONTEXT_IN_CHAT_INPUT,
162
+ primary: 2048 | 90 ,
163
+ weight: 100
164
+ },
165
+ menu: [
166
+ {
167
+ when: ( (ContextKeyExpr.or( (ContextKeyExpr.and(
168
+ (CONTEXT_CHAT_LOCATION.isEqualTo(ChatAgentLocation.EditingSession))
169
+ )), (ContextKeyExpr.and( (ContextKeyExpr.or(
170
+ (CONTEXT_CHAT_LOCATION.isEqualTo(ChatAgentLocation.Panel)),
171
+ (CONTEXT_CHAT_LOCATION.isEqualTo(ChatAgentLocation.EditingSession))
172
+ )), AttachContextAction._cdt))))),
173
+ id: MenuId.ChatInput,
174
+ group: 'navigation',
175
+ order: 2
124
176
  },
125
- menu: [
126
- {
127
- when: ( (ContextKeyExpr.and(
128
- (CONTEXT_CHAT_LOCATION.isEqualTo(ChatAgentLocation.Panel)),
129
- AttachContextAction._cdt
130
- ))),
131
- id: MenuId.ChatInput,
132
- group: 'navigation',
133
- order: 2
134
- },
135
- {
136
- when: ( (ContextKeyExpr.and(
137
- (( (CONTEXT_CHAT_LOCATION.isEqualTo(ChatAgentLocation.Panel))).negate()),
138
- AttachContextAction._cdt
139
- ))),
140
- id: MenuId.ChatExecute,
141
- group: 'navigation',
142
- order: 1
143
- },
144
- ]
145
- });
177
+ {
178
+ when: ( (ContextKeyExpr.and(
179
+ (( (CONTEXT_CHAT_LOCATION.isEqualTo(ChatAgentLocation.Panel))).negate()),
180
+ AttachContextAction._cdt
181
+ ))),
182
+ id: MenuId.ChatExecute,
183
+ group: 'navigation',
184
+ order: 1
185
+ },
186
+ ]
187
+ }) {
188
+ super(desc);
146
189
  }
147
190
  _getFileContextId(item) {
148
191
  if ('resource' in item) {
@@ -154,25 +197,11 @@ class AttachContextAction extends Action2 {
154
197
  `:${item.range.startLineNumber}-${item.range.endLineNumber}` :
155
198
  `:${item.range.startLineNumber}`);
156
199
  }
157
- async _attachContext(widget, commandService, clipboardService, ...picks) {
200
+ async _attachContext(widget, commandService, clipboardService, editorService, labelService, viewsService, chatEditingService, hostService, isInBackground, ...picks) {
158
201
  const toAttach = [];
159
202
  for (const pick of picks) {
160
- if (pick && typeof pick === 'object' && 'command' in pick && pick.command) {
161
- const selection = await commandService.executeCommand(pick.command.id, ...(pick.command.arguments ?? []));
162
- if (!selection) {
163
- continue;
164
- }
203
+ if (isISymbolQuickPickItem(pick) && pick.symbol) {
165
204
  toAttach.push({
166
- ...pick,
167
- isDynamic: pick.isDynamic,
168
- value: pick.value,
169
- name: `${typeof pick.value === 'string' && pick.value.startsWith('#') ? pick.value.slice(1) : ''}${selection}`,
170
- fullName: selection
171
- });
172
- }
173
- else if ('symbol' in pick && pick.symbol) {
174
- toAttach.push({
175
- ...pick,
176
205
  id: this._getFileContextId(pick.symbol.location),
177
206
  value: pick.symbol.location,
178
207
  fullName: pick.label,
@@ -180,7 +209,7 @@ class AttachContextAction extends Action2 {
180
209
  isDynamic: true
181
210
  });
182
211
  }
183
- else if (pick && typeof pick === 'object' && 'resource' in pick && pick.resource) {
212
+ else if (isIQuickPickItemWithResource(pick) && pick.resource) {
184
213
  if (/\.(png|jpg|jpeg|bmp|gif|tiff)$/i.test(pick.resource.path)) {
185
214
  toAttach.push({
186
215
  id: ( (pick.resource.toString())),
@@ -192,19 +221,22 @@ class AttachContextAction extends Action2 {
192
221
  });
193
222
  }
194
223
  else {
195
- toAttach.push({
196
- ...pick,
197
- id: this._getFileContextId({ resource: pick.resource }),
198
- value: pick.resource,
199
- name: pick.label,
200
- isFile: true,
201
- isDynamic: true
202
- });
224
+ if (chatEditingService) {
225
+ chatEditingService.currentEditingSessionObs.get()?.addFileToWorkingSet(pick.resource);
226
+ }
227
+ else {
228
+ toAttach.push({
229
+ id: this._getFileContextId({ resource: pick.resource }),
230
+ value: pick.resource,
231
+ name: pick.label,
232
+ isFile: true,
233
+ isDynamic: true,
234
+ });
235
+ }
203
236
  }
204
237
  }
205
- else if ('symbolName' in pick && pick.uri && pick.range) {
238
+ else if (isIGotoSymbolQuickPickItem(pick) && pick.uri && pick.range) {
206
239
  toAttach.push({
207
- ...pick,
208
240
  range: undefined,
209
241
  id: this._getFileContextId({ uri: pick.uri, range: pick.range.decoration }),
210
242
  value: { uri: pick.uri, range: pick.range.decoration },
@@ -213,40 +245,100 @@ class AttachContextAction extends Action2 {
213
245
  isDynamic: true
214
246
  });
215
247
  }
216
- else if ('kind' in pick && pick.kind === 'tool') {
217
- toAttach.push({
218
- id: pick.id,
219
- name: pick.label,
220
- fullName: pick.label,
221
- value: undefined,
222
- icon: pick.icon,
223
- isTool: true
224
- });
248
+ else if (isIOpenEditorsQuickPickItem(pick)) {
249
+ for (const editor of editorService.editors.filter(e => e instanceof FileEditorInput || e instanceof DiffEditorInput || e instanceof UntitledTextEditorInput)) {
250
+ const uri = editor instanceof DiffEditorInput ? editor.modified.resource : editor.resource;
251
+ if (uri) {
252
+ if (chatEditingService) {
253
+ chatEditingService.currentEditingSessionObs.get()?.addFileToWorkingSet(uri);
254
+ }
255
+ else {
256
+ toAttach.push({
257
+ id: this._getFileContextId({ resource: uri }),
258
+ value: uri,
259
+ name: labelService.getUriBasenameLabel(uri),
260
+ isFile: true,
261
+ isDynamic: true
262
+ });
263
+ }
264
+ }
265
+ }
225
266
  }
226
- else if ('kind' in pick && pick.kind === 'image') {
227
- const fileBuffer = await clipboardService.readImage();
228
- toAttach.push({
229
- id: await imageToHash(fileBuffer),
230
- name: ( localize(7315, 'Pasted Image')),
231
- fullName: ( localize(7315, 'Pasted Image')),
232
- value: fileBuffer,
233
- isDynamic: true,
234
- isImage: true
235
- });
267
+ else if (isISearchResultsQuickPickItem(pick)) {
268
+ const searchView = viewsService.getViewWithId(VIEW_ID);
269
+ for (const result of searchView.model.searchResult.matches()) {
270
+ if (chatEditingService) {
271
+ chatEditingService.currentEditingSessionObs.get()?.addFileToWorkingSet(result.resource);
272
+ }
273
+ else {
274
+ toAttach.push({
275
+ id: this._getFileContextId({ resource: result.resource }),
276
+ value: result.resource,
277
+ name: labelService.getUriBasenameLabel(result.resource),
278
+ isFile: true,
279
+ isDynamic: true
280
+ });
281
+ }
282
+ }
283
+ }
284
+ else if (isScreenshotQuickPickItem(pick)) {
285
+ const blob = await hostService.getScreenshot();
286
+ if (blob) {
287
+ toAttach.push(convertBufferToScreenshotVariable(blob));
288
+ }
236
289
  }
237
290
  else {
238
- toAttach.push({
239
- ...pick,
240
- range: undefined,
241
- id: pick.id ?? '',
242
- value: 'value' in pick ? pick.value : undefined,
243
- fullName: pick.label,
244
- name: 'name' in pick && typeof pick.name === 'string' ? pick.name : pick.label,
245
- icon: 'icon' in pick && ThemeIcon.isThemeIcon(pick.icon) ? pick.icon : undefined
246
- });
291
+ const attachmentPick = pick;
292
+ if (attachmentPick.kind === 'command') {
293
+ const selection = await commandService.executeCommand(attachmentPick.command.id, ...(attachmentPick.command.arguments ?? []));
294
+ if (!selection) {
295
+ continue;
296
+ }
297
+ toAttach.push({
298
+ ...attachmentPick,
299
+ isDynamic: attachmentPick.isDynamic,
300
+ value: attachmentPick.value,
301
+ name: `${typeof attachmentPick.value === 'string' && attachmentPick.value.startsWith('#') ? attachmentPick.value.slice(1) : ''}${selection}`,
302
+ fullName: selection
303
+ });
304
+ }
305
+ else if (attachmentPick.kind === 'tool') {
306
+ toAttach.push({
307
+ id: attachmentPick.id,
308
+ name: attachmentPick.label,
309
+ fullName: attachmentPick.label,
310
+ value: undefined,
311
+ icon: attachmentPick.icon,
312
+ isTool: true
313
+ });
314
+ }
315
+ else if (attachmentPick.kind === 'image') {
316
+ const fileBuffer = await clipboardService.readImage();
317
+ toAttach.push({
318
+ id: await imageToHash(fileBuffer),
319
+ name: ( localize(7535, 'Pasted Image')),
320
+ fullName: ( localize(7535, 'Pasted Image')),
321
+ value: fileBuffer,
322
+ isDynamic: true,
323
+ isImage: true
324
+ });
325
+ }
326
+ else if (attachmentPick.kind === 'variable') {
327
+ toAttach.push({
328
+ range: undefined,
329
+ id: pick.id ?? '',
330
+ value: undefined,
331
+ fullName: pick.label,
332
+ name: attachmentPick.variable.name,
333
+ icon: attachmentPick.variable.icon
334
+ });
335
+ }
247
336
  }
248
337
  }
249
- widget.getContrib(ChatContextAttachments.ID)?.setContext(false, ...toAttach);
338
+ widget.attachmentModel.addContext(...toAttach);
339
+ if (!isInBackground) {
340
+ widget.focusInput();
341
+ }
250
342
  }
251
343
  async run(accessor, ...args) {
252
344
  const quickInputService = accessor.get(IQuickInputService);
@@ -257,63 +349,79 @@ class AttachContextAction extends Action2 {
257
349
  const languageModelToolsService = accessor.get(ILanguageModelToolsService);
258
350
  const quickChatService = accessor.get(IQuickChatService);
259
351
  const clipboardService = accessor.get(IClipboardService);
260
- const configurationService = accessor.get(IConfigurationService);
352
+ const editorService = accessor.get(IEditorService);
353
+ const labelService = accessor.get(ILabelService);
354
+ const contextKeyService = accessor.get(IContextKeyService);
355
+ const viewsService = accessor.get(IViewsService);
356
+ const hostService = accessor.get(IHostService);
357
+ const extensionService = accessor.get(IExtensionService);
261
358
  const context = args[0];
262
359
  const widget = context?.widget ?? widgetService.lastFocusedWidget;
263
360
  if (!widget) {
264
361
  return;
265
362
  }
363
+ const chatEditingService = widget.location === ChatAgentLocation.EditingSession ? accessor.get(IChatEditingService) : undefined;
266
364
  const usedAgent = widget.parsedInput.parts.find(p => p instanceof ChatRequestAgentPart);
267
365
  const slowSupported = usedAgent ? usedAgent.agent.metadata.supportsSlowVariables : true;
268
366
  const quickPickItems = [];
269
- for (const variable of chatVariablesService.getVariables(widget.location)) {
270
- if (variable.fullName && (!variable.isSlow || slowSupported)) {
271
- quickPickItems.push({
272
- label: variable.fullName,
273
- name: variable.name,
274
- id: variable.id,
275
- iconClass: variable.icon ? ThemeIcon.asClassName(variable.icon) : undefined,
276
- icon: variable.icon
277
- });
367
+ if (!context || !context.showFilesOnly) {
368
+ for (const variable of chatVariablesService.getVariables(widget.location)) {
369
+ if (variable.fullName && (!variable.isSlow || slowSupported)) {
370
+ quickPickItems.push({
371
+ kind: 'variable',
372
+ variable,
373
+ label: variable.fullName,
374
+ id: variable.id,
375
+ iconClass: variable.icon ? ThemeIcon.asClassName(variable.icon) : undefined,
376
+ });
377
+ }
278
378
  }
279
- }
280
- if (configurationService.getValue('chat.experimental.imageAttachments')) {
281
- const imageData = await clipboardService.readImage();
282
- if (isImage(imageData)) {
379
+ if (( (extensionService.extensions.some(ext => isProposedApiEnabled(ext, 'chatReferenceBinaryData'))))) {
380
+ const imageData = await clipboardService.readImage();
381
+ if (isImage(imageData)) {
382
+ quickPickItems.push({
383
+ kind: 'image',
384
+ id: await imageToHash(imageData),
385
+ label: ( localize(7536, 'Image from Clipboard')),
386
+ iconClass: ThemeIcon.asClassName(Codicon.fileMedia),
387
+ });
388
+ }
283
389
  quickPickItems.push({
284
- id: await imageToHash(imageData),
285
- kind: 'image',
286
- label: ( localize(7316, 'Image from Clipboard')),
287
- iconClass: ThemeIcon.asClassName(Codicon.fileMedia),
390
+ kind: 'screenshot',
391
+ id: ScreenshotVariableId,
392
+ icon: ThemeIcon.fromId(Codicon.deviceCamera.id),
393
+ iconClass: ThemeIcon.asClassName(Codicon.deviceCamera),
394
+ label: (isElectron
395
+ ? ( localize(7537, 'Screenshot Window'))
396
+ : ( localize(7538, 'Screenshot'))),
288
397
  });
289
398
  }
290
- }
291
- if (widget.viewModel?.sessionId) {
292
- const agentPart = widget.parsedInput.parts.find((part) => part instanceof ChatRequestAgentPart);
293
- if (agentPart) {
294
- const completions = await chatAgentService.getAgentCompletionItems(agentPart.agent.id, '', CancellationToken.None);
295
- for (const variable of completions) {
296
- if (variable.fullName) {
297
- quickPickItems.push({
298
- label: variable.fullName,
299
- id: variable.id,
300
- command: variable.command,
301
- icon: variable.icon,
302
- iconClass: variable.icon ? ThemeIcon.asClassName(variable.icon) : undefined,
303
- value: variable.value,
304
- isDynamic: true,
305
- name: variable.name
306
- });
399
+ if (widget.viewModel?.sessionId) {
400
+ const agentPart = widget.parsedInput.parts.find((part) => part instanceof ChatRequestAgentPart);
401
+ if (agentPart) {
402
+ const completions = await chatAgentService.getAgentCompletionItems(agentPart.agent.id, '', CancellationToken.None);
403
+ for (const variable of completions) {
404
+ if (variable.fullName && variable.command) {
405
+ quickPickItems.push({
406
+ kind: 'command',
407
+ label: variable.fullName,
408
+ id: variable.id,
409
+ command: variable.command,
410
+ icon: variable.icon,
411
+ iconClass: variable.icon ? ThemeIcon.asClassName(variable.icon) : undefined,
412
+ value: variable.value,
413
+ isDynamic: true,
414
+ name: variable.name
415
+ });
416
+ }
307
417
  }
308
418
  }
309
419
  }
310
- }
311
- if (!usedAgent || usedAgent.agent.supportsToolReferences) {
312
420
  for (const tool of languageModelToolsService.getTools()) {
313
- if (tool.canBeInvokedManually) {
421
+ if (tool.canBeReferencedInPrompt) {
314
422
  const item = {
315
423
  kind: 'tool',
316
- label: tool.displayName ?? tool.name ?? '',
424
+ label: tool.displayName ?? '',
317
425
  id: tool.id,
318
426
  icon: ThemeIcon.isThemeIcon(tool.icon) ? tool.icon : undefined
319
427
  };
@@ -326,28 +434,47 @@ class AttachContextAction extends Action2 {
326
434
  quickPickItems.push(item);
327
435
  }
328
436
  }
329
- }
330
- quickPickItems.push({
331
- label: ( localize(7317, 'Symbol...')),
332
- icon: ThemeIcon.fromId(Codicon.symbolField.id),
333
- iconClass: ThemeIcon.asClassName(Codicon.symbolField),
334
- prefix: SymbolsQuickAccessProvider.PREFIX
335
- });
336
- if (widget.location === ChatAgentLocation.Notebook) {
337
437
  quickPickItems.push({
338
- kind: 'dynamic',
339
- id: 'chatContext.notebook.kernelVariable',
340
- isDynamic: true,
341
- icon: ThemeIcon.fromId(Codicon.serverEnvironment.id),
342
- iconClass: ThemeIcon.asClassName(Codicon.serverEnvironment),
343
- value: 'kernelVariable',
344
- label: ( localize(7318, 'Kernel Variable...')),
345
- command: {
346
- id: 'notebook.chat.selectAndInsertKernelVariable',
347
- title: ( localize(7319, 'Select and Insert Kernel Variable')),
348
- arguments: [{ widget, range: undefined }]
349
- }
438
+ kind: 'quickaccess',
439
+ label: ( localize(7539, 'Symbol...')),
440
+ iconClass: ThemeIcon.asClassName(Codicon.symbolField),
441
+ prefix: SymbolsQuickAccessProvider.PREFIX,
442
+ id: 'symbol'
350
443
  });
444
+ if (widget.location === ChatAgentLocation.Notebook) {
445
+ quickPickItems.push({
446
+ kind: 'command',
447
+ id: 'chatContext.notebook.kernelVariable',
448
+ isDynamic: true,
449
+ icon: ThemeIcon.fromId(Codicon.serverEnvironment.id),
450
+ iconClass: ThemeIcon.asClassName(Codicon.serverEnvironment),
451
+ value: 'kernelVariable',
452
+ label: ( localize(7540, 'Kernel Variable...')),
453
+ command: {
454
+ id: 'notebook.chat.selectAndInsertKernelVariable',
455
+ title: ( localize(7541, 'Select and Insert Kernel Variable')),
456
+ arguments: [{ widget, range: undefined }]
457
+ }
458
+ });
459
+ }
460
+ }
461
+ else if (context.showFilesOnly) {
462
+ if (editorService.editors.filter(e => e instanceof FileEditorInput || e instanceof DiffEditorInput || e instanceof UntitledTextEditorInput).length > 0) {
463
+ quickPickItems.push({
464
+ kind: 'open-editors',
465
+ id: 'open-editors',
466
+ label: ( localize(7542, 'Open Editors')),
467
+ iconClass: ThemeIcon.asClassName(Codicon.files),
468
+ });
469
+ }
470
+ if (SearchContext.HasSearchResults.getValue(contextKeyService)) {
471
+ quickPickItems.push({
472
+ kind: 'search-results',
473
+ id: 'search-results',
474
+ label: ( localize(7543, 'Search Results')),
475
+ iconClass: ThemeIcon.asClassName(Codicon.search),
476
+ });
477
+ }
351
478
  }
352
479
  function extractTextFromIconLabel(label) {
353
480
  if (!label) {
@@ -360,55 +487,85 @@ class AttachContextAction extends Action2 {
360
487
  const first = extractTextFromIconLabel(a.label).toUpperCase();
361
488
  const second = extractTextFromIconLabel(b.label).toUpperCase();
362
489
  return compare(first, second);
363
- }), clipboardService, '');
490
+ }), clipboardService, editorService, labelService, viewsService, chatEditingService, hostService, '', context?.placeholder);
364
491
  }
365
- _show(quickInputService, commandService, widget, quickChatService, quickPickItems, clipboardService, query = '') {
366
- quickInputService.quickAccess.show(query, {
367
- enabledProviderPrefixes: [
368
- AnythingQuickAccessProvider.PREFIX,
369
- SymbolsQuickAccessProvider.PREFIX,
370
- AbstractGotoSymbolQuickAccessProvider.PREFIX
371
- ],
372
- placeholder: ( localize(7320, 'Search attachments')),
373
- providerOptions: {
374
- handleAccept: (item) => {
375
- if ('prefix' in item) {
376
- this._show(quickInputService, commandService, widget, quickChatService, quickPickItems, clipboardService, item.prefix);
377
- }
378
- else {
379
- if (!clipboardService) {
380
- return;
381
- }
382
- this._attachContext(widget, commandService, clipboardService, item);
383
- if (isQuickChat(widget)) {
384
- quickChatService.open();
385
- }
386
- }
387
- },
388
- additionPicks: quickPickItems,
389
- filter: (item) => {
390
- const attachedContext = widget.getContrib(ChatContextAttachments.ID)?.getContext() ?? ( (new Set()));
391
- if ('kind' in item && item.kind === 'image') {
392
- return !( (attachedContext.has(item.id)));
393
- }
394
- if ('symbol' in item && item.symbol) {
395
- return !( (attachedContext.has(this._getFileContextId(item.symbol.location))));
492
+ _show(quickInputService, commandService, widget, quickChatService, quickPickItems, clipboardService, editorService, labelService, viewsService, chatEditingService, hostService, query = '', placeholder) {
493
+ const providerOptions = {
494
+ handleAccept: (item, isBackgroundAccept) => {
495
+ if ('prefix' in item) {
496
+ this._show(quickInputService, commandService, widget, quickChatService, quickPickItems, clipboardService, editorService, labelService, viewsService, chatEditingService, hostService, item.prefix, placeholder);
497
+ }
498
+ else {
499
+ if (!clipboardService) {
500
+ return;
396
501
  }
397
- if (item && typeof item === 'object' && 'resource' in item && URI.isUri(item.resource)) {
398
- return [Schemas.file, Schemas.vscodeRemote].includes(item.resource.scheme)
399
- && !( (attachedContext.has(this._getFileContextId({ resource: item.resource }))));
502
+ this._attachContext(widget, commandService, clipboardService, editorService, labelService, viewsService, chatEditingService, hostService, isBackgroundAccept, item);
503
+ if (isQuickChat(widget)) {
504
+ quickChatService.open();
400
505
  }
401
- if (item && typeof item === 'object' && 'uri' in item && item.uri && item.range) {
402
- return !( (attachedContext.has(this._getFileContextId({ uri: item.uri, range: item.range.decoration }))));
506
+ }
507
+ },
508
+ additionPicks: quickPickItems,
509
+ filter: (item) => {
510
+ const attachedContext = widget.attachmentModel.getAttachmentIDs();
511
+ if (chatEditingService) {
512
+ for (const file of chatEditingService.currentEditingSessionObs.get()?.workingSet.keys() ?? []) {
513
+ attachedContext.add(this._getFileContextId({ resource: file }));
403
514
  }
404
- if (!('command' in item) && item.id) {
405
- return !( (attachedContext.has(item.id)));
515
+ }
516
+ if (isIOpenEditorsQuickPickItem(item)) {
517
+ for (const editor of editorService.editors.filter(e => e instanceof FileEditorInput || e instanceof DiffEditorInput || e instanceof UntitledTextEditorInput)) {
518
+ if (editor.resource && !( (attachedContext.has(this._getFileContextId({ resource: editor.resource }))))) {
519
+ return true;
520
+ }
406
521
  }
407
- return true;
522
+ return false;
523
+ }
524
+ if ('kind' in item && item.kind === 'image') {
525
+ return !( (attachedContext.has(item.id)));
526
+ }
527
+ if ('symbol' in item && item.symbol) {
528
+ return !( (attachedContext.has(this._getFileContextId(item.symbol.location))));
529
+ }
530
+ if (item && typeof item === 'object' && 'resource' in item && URI.isUri(item.resource)) {
531
+ return [Schemas.file, Schemas.vscodeRemote].includes(item.resource.scheme)
532
+ && !( (attachedContext.has(this._getFileContextId({ resource: item.resource }))));
408
533
  }
534
+ if (item && typeof item === 'object' && 'uri' in item && item.uri && item.range) {
535
+ return !( (attachedContext.has(this._getFileContextId({ uri: item.uri, range: item.range.decoration }))));
536
+ }
537
+ if (!('command' in item) && item.id) {
538
+ return !( (attachedContext.has(item.id)));
539
+ }
540
+ return true;
409
541
  }
542
+ };
543
+ quickInputService.quickAccess.show(query, {
544
+ enabledProviderPrefixes: [
545
+ AnythingQuickAccessProvider.PREFIX,
546
+ SymbolsQuickAccessProvider.PREFIX,
547
+ AbstractGotoSymbolQuickAccessProvider.PREFIX
548
+ ],
549
+ placeholder: placeholder ?? ( localize(7544, 'Search attachments')),
550
+ providerOptions,
410
551
  });
411
552
  }
412
553
  }
554
+ registerAction2(class AttachFilesAction extends AttachContextAction {
555
+ constructor() {
556
+ super({
557
+ id: 'workbench.action.chat.editing.attachFiles',
558
+ title: ( localize2(7545, "Add Files to Working Set")),
559
+ f1: false,
560
+ category: CHAT_CATEGORY,
561
+ precondition: ( (CONTEXT_CHAT_LOCATION.isEqualTo(ChatAgentLocation.EditingSession)))
562
+ });
563
+ }
564
+ async run(accessor, ...args) {
565
+ const context = args[0];
566
+ const attachFilesContext = { ...context, showFilesOnly: true, placeholder: ( localize(7546, 'Search for files to add to your working set')) };
567
+ return super.run(accessor, attachFilesContext);
568
+ }
569
+ });
413
570
 
414
- export { registerChatContextActions };
571
+ export { AttachContextAction, registerChatContextActions };