@theia/ai-chat-ui 1.59.0-next.62 → 1.59.0-next.72

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 (40) hide show
  1. package/lib/browser/ai-chat-ui-frontend-module.d.ts +1 -1
  2. package/lib/browser/ai-chat-ui-frontend-module.d.ts.map +1 -1
  3. package/lib/browser/ai-chat-ui-frontend-module.js +12 -11
  4. package/lib/browser/ai-chat-ui-frontend-module.js.map +1 -1
  5. package/lib/browser/change-set-actions/change-set-accept-action.d.ts +10 -0
  6. package/lib/browser/change-set-actions/change-set-accept-action.d.ts.map +1 -0
  7. package/lib/browser/change-set-actions/change-set-accept-action.js +47 -0
  8. package/lib/browser/change-set-actions/change-set-accept-action.js.map +1 -0
  9. package/lib/browser/change-set-actions/change-set-action-service.d.ts +31 -0
  10. package/lib/browser/change-set-actions/change-set-action-service.d.ts.map +1 -0
  11. package/lib/browser/change-set-actions/change-set-action-service.js +57 -0
  12. package/lib/browser/change-set-actions/change-set-action-service.js.map +1 -0
  13. package/lib/browser/chat-input-widget.d.ts +6 -4
  14. package/lib/browser/chat-input-widget.d.ts.map +1 -1
  15. package/lib/browser/chat-input-widget.js +56 -43
  16. package/lib/browser/chat-input-widget.js.map +1 -1
  17. package/lib/browser/chat-response-renderer/ai-selection-resolver.d.ts +23 -0
  18. package/lib/browser/chat-response-renderer/ai-selection-resolver.d.ts.map +1 -0
  19. package/lib/browser/chat-response-renderer/{ai-editor-manager.js → ai-selection-resolver.js} +2 -38
  20. package/lib/browser/chat-response-renderer/ai-selection-resolver.js.map +1 -0
  21. package/lib/browser/chat-response-renderer/index.d.ts +1 -1
  22. package/lib/browser/chat-response-renderer/index.d.ts.map +1 -1
  23. package/lib/browser/chat-response-renderer/index.js +1 -1
  24. package/lib/browser/chat-response-renderer/index.js.map +1 -1
  25. package/lib/browser/chat-view-widget.d.ts +1 -1
  26. package/lib/browser/chat-view-widget.d.ts.map +1 -1
  27. package/lib/browser/chat-view-widget.js +2 -3
  28. package/lib/browser/chat-view-widget.js.map +1 -1
  29. package/package.json +10 -10
  30. package/src/browser/ai-chat-ui-frontend-module.ts +12 -14
  31. package/src/browser/change-set-actions/change-set-accept-action.tsx +52 -0
  32. package/src/browser/change-set-actions/change-set-action-service.ts +65 -0
  33. package/src/browser/chat-input-widget.tsx +87 -61
  34. package/src/browser/chat-response-renderer/{ai-editor-manager.ts → ai-selection-resolver.ts} +6 -45
  35. package/src/browser/chat-response-renderer/index.ts +1 -1
  36. package/src/browser/chat-view-widget.tsx +2 -3
  37. package/src/browser/style/index.css +15 -3
  38. package/lib/browser/chat-response-renderer/ai-editor-manager.d.ts +0 -36
  39. package/lib/browser/chat-response-renderer/ai-editor-manager.d.ts.map +0 -1
  40. package/lib/browser/chat-response-renderer/ai-editor-manager.js.map +0 -1
@@ -13,8 +13,8 @@
13
13
  //
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
- import { ChangeSet, ChangeSetElement, ChatAgent, ChatChangeEvent, ChatModel, ChatRequestModel } from '@theia/ai-chat';
17
- import { Disposable, InMemoryResources, URI, nls } from '@theia/core';
16
+ import { ChangeSet, ChatAgent, ChatChangeEvent, ChatModel, ChatRequestModel } from '@theia/ai-chat';
17
+ import { Disposable, DisposableCollection, InMemoryResources, URI, nls } from '@theia/core';
18
18
  import { ContextMenuRenderer, LabelProvider, Message, ReactWidget } from '@theia/core/lib/browser';
19
19
  import { Deferred } from '@theia/core/lib/common/promise-util';
20
20
  import { inject, injectable, optional, postConstruct } from '@theia/core/shared/inversify';
@@ -26,8 +26,9 @@ import { CHAT_VIEW_LANGUAGE_EXTENSION } from './chat-view-language-contribution'
26
26
  import { AIVariableResolutionRequest } from '@theia/ai-core';
27
27
  import { FrontendVariableService } from '@theia/ai-core/lib/browser';
28
28
  import { ContextVariablePicker } from './context-variable-picker';
29
+ import { ChangeSetActionRenderer, ChangeSetActionService } from './change-set-actions/change-set-action-service';
29
30
 
30
- type Query = (query: string, context?: AIVariableResolutionRequest[]) => Promise<void>;
31
+ type Query = (query: string) => Promise<void>;
31
32
  type Unpin = () => void;
32
33
  type Cancel = (requestModel: ChatRequestModel) => void;
33
34
  type DeleteChangeSet = (requestModel: ChatRequestModel) => void;
@@ -65,13 +66,14 @@ export class AIChatInputWidget extends ReactWidget {
65
66
  @inject(ContextVariablePicker)
66
67
  protected readonly contextVariablePicker: ContextVariablePicker;
67
68
 
69
+ @inject(ChangeSetActionService)
70
+ protected readonly changeSetActionService: ChangeSetActionService;
71
+
68
72
  protected editorRef: MonacoEditor | undefined = undefined;
69
73
  private editorReady = new Deferred<void>();
70
74
 
71
75
  protected isEnabled = false;
72
76
 
73
- protected context: AIVariableResolutionRequest[] = [];
74
-
75
77
  private _onQuery: Query;
76
78
  set onQuery(query: Query) {
77
79
  this._onQuery = query;
@@ -93,8 +95,16 @@ export class AIChatInputWidget extends ReactWidget {
93
95
  this._onDeleteChangeSetElement = deleteChangeSetElement;
94
96
  }
95
97
 
98
+ protected onDisposeForChatModel = new DisposableCollection();
96
99
  private _chatModel: ChatModel;
97
100
  set chatModel(chatModel: ChatModel) {
101
+ this.onDisposeForChatModel.dispose();
102
+ this.onDisposeForChatModel = new DisposableCollection();
103
+ this.onDisposeForChatModel.push(chatModel.onDidChange(event => {
104
+ if (event.kind === 'addVariable' || event.kind === 'removeVariable') {
105
+ this.update();
106
+ }
107
+ }));
98
108
  this._chatModel = chatModel;
99
109
  this.update();
100
110
  }
@@ -132,7 +142,7 @@ export class AIChatInputWidget extends ReactWidget {
132
142
  onDeleteChangeSetElement={this._onDeleteChangeSetElement.bind(this)}
133
143
  onAddContextElement={this.addContextElement.bind(this)}
134
144
  onDeleteContextElement={this.deleteContextElement.bind(this)}
135
- context={this.context}
145
+ context={this._chatModel.context.getVariables()}
136
146
  chatModel={this._chatModel}
137
147
  pinnedAgent={this._pinnedAgent}
138
148
  editorProvider={this.editorProvider}
@@ -146,6 +156,7 @@ export class AIChatInputWidget extends ReactWidget {
146
156
  showContext={this.configuration?.showContext}
147
157
  showPinnedAgent={this.configuration?.showPinnedAgent}
148
158
  labelProvider={this.labelProvider}
159
+ actionService={this.changeSetActionService}
149
160
  />
150
161
  );
151
162
  }
@@ -192,14 +203,13 @@ export class AIChatInputWidget extends ReactWidget {
192
203
  protected addContextElement(): void {
193
204
  this.contextVariablePicker.pickContextVariable().then(contextElement => {
194
205
  if (contextElement) {
195
- this.addContext(contextElement);
206
+ this._chatModel.context.addVariables(contextElement);
196
207
  }
197
208
  });
198
209
  }
199
210
 
200
211
  protected deleteContextElement(index: number): void {
201
- this.context.splice(index, 1);
202
- this.update();
212
+ this._chatModel.context.deleteVariables(index);
203
213
  }
204
214
 
205
215
  protected handleContextMenu(event: IMouseEvent): void {
@@ -210,18 +220,14 @@ export class AIChatInputWidget extends ReactWidget {
210
220
  event.preventDefault();
211
221
  }
212
222
 
213
- addContext(variableRequest: AIVariableResolutionRequest): void {
214
- if (this.context.some(existing => existing.variable.id === variableRequest.variable.id && existing.arg === variableRequest.arg)) {
215
- return;
216
- }
217
- this.context.push(variableRequest);
218
- this.update();
223
+ addContext(variable: AIVariableResolutionRequest): void {
224
+ this._chatModel.context.addVariables(variable);
219
225
  }
220
226
  }
221
227
 
222
228
  interface ChatInputProperties {
223
229
  onCancel: (requestModel: ChatRequestModel) => void;
224
- onQuery: (query: string, context?: AIVariableResolutionRequest[]) => void;
230
+ onQuery: (query: string) => void;
225
231
  onUnpin: () => void;
226
232
  onDragOver: (event: React.DragEvent) => void;
227
233
  onDrop: (event: React.DragEvent) => void;
@@ -229,7 +235,7 @@ interface ChatInputProperties {
229
235
  onDeleteChangeSetElement: (sessionId: string, index: number) => void;
230
236
  onAddContextElement: () => void;
231
237
  onDeleteContextElement: (index: number) => void;
232
- context?: AIVariableResolutionRequest[];
238
+ context?: readonly AIVariableResolutionRequest[];
233
239
  isEnabled?: boolean;
234
240
  chatModel: ChatModel;
235
241
  pinnedAgent?: ChatAgent;
@@ -240,6 +246,7 @@ interface ChatInputProperties {
240
246
  showContext?: boolean;
241
247
  showPinnedAgent?: boolean;
242
248
  labelProvider: LabelProvider;
249
+ actionService: ChangeSetActionService;
243
250
  }
244
251
 
245
252
  const ChatInput: React.FunctionComponent<ChatInputProperties> = (props: ChatInputProperties) => {
@@ -249,7 +256,15 @@ const ChatInput: React.FunctionComponent<ChatInputProperties> = (props: ChatInpu
249
256
  const [inProgress, setInProgress] = React.useState(false);
250
257
  const [isInputEmpty, setIsInputEmpty] = React.useState(true);
251
258
  const [changeSetUI, setChangeSetUI] = React.useState(
252
- () => props.chatModel.changeSet ? buildChangeSetUI(props.chatModel.changeSet, props.labelProvider, onDeleteChangeSet, onDeleteChangeSetElement) : undefined
259
+ () => props.chatModel.changeSet
260
+ ? buildChangeSetUI(
261
+ props.chatModel.changeSet,
262
+ props.labelProvider,
263
+ props.actionService.getActionsForChangeset(props.chatModel.changeSet),
264
+ onDeleteChangeSet,
265
+ onDeleteChangeSetElement
266
+ )
267
+ : undefined
253
268
  );
254
269
 
255
270
  // eslint-disable-next-line no-null/no-null
@@ -353,14 +368,28 @@ const ChatInput: React.FunctionComponent<ChatInputProperties> = (props: ChatInpu
353
368
  setInProgress(ChatRequestModel.isInProgress(event.request))
354
369
  );
355
370
  } else if (ChatChangeEvent.isChangeSetEvent(event)) {
356
- if (event.changeSet) {
357
- setChangeSetUI(buildChangeSetUI(event.changeSet, props.labelProvider, onDeleteChangeSet, onDeleteChangeSetElement));
358
- } else {
371
+ if (event.kind === 'removeChangeSet') {
359
372
  setChangeSetUI(undefined);
373
+ } else if (event.kind === 'setChangeSet' || 'updateChangeSet') {
374
+ setChangeSetUI(buildChangeSetUI(
375
+ event.changeSet,
376
+ props.labelProvider,
377
+ props.actionService.getActionsForChangeset(event.changeSet),
378
+ onDeleteChangeSet,
379
+ onDeleteChangeSetElement
380
+ ));
360
381
  }
361
382
  }
362
383
  });
363
- setChangeSetUI(props.chatModel.changeSet ? buildChangeSetUI(props.chatModel.changeSet, props.labelProvider, onDeleteChangeSet, onDeleteChangeSetElement) : undefined);
384
+ setChangeSetUI(props.chatModel.changeSet
385
+ ? buildChangeSetUI(
386
+ props.chatModel.changeSet,
387
+ props.labelProvider,
388
+ props.actionService.getActionsForChangeset(props.chatModel.changeSet),
389
+ onDeleteChangeSet,
390
+ onDeleteChangeSetElement
391
+ )
392
+ : undefined);
364
393
  return () => {
365
394
  listener?.dispose();
366
395
  responseListenerRef.current?.dispose();
@@ -368,16 +397,25 @@ const ChatInput: React.FunctionComponent<ChatInputProperties> = (props: ChatInpu
368
397
  };
369
398
  }, [props.chatModel]);
370
399
 
371
- function submit(value: string): void {
400
+ React.useEffect(() => {
401
+ const disposable = props.actionService.onDidChange(() => {
402
+ if (!props.chatModel.changeSet) { return; }
403
+ const newActions = props.actionService.getActionsForChangeset(props.chatModel.changeSet);
404
+ setChangeSetUI(current => !current ? current : { ...current, actions: newActions });
405
+ });
406
+ return () => disposable.dispose();
407
+ });
408
+
409
+ const submit = React.useCallback(function submit(value: string): void {
372
410
  if (!value || value.trim().length === 0) {
373
411
  return;
374
412
  }
375
413
  setInProgress(true);
376
- props.onQuery(value, props.context);
414
+ props.onQuery(value);
377
415
  if (editorRef.current) {
378
416
  editorRef.current.document.textEditorModel.setValue('');
379
417
  }
380
- }
418
+ }, [props.context, props.onQuery, editorRef]);
381
419
 
382
420
  const onKeyDown = React.useCallback((event: React.KeyboardEvent) => {
383
421
  if (!props.isEnabled) {
@@ -387,7 +425,7 @@ const ChatInput: React.FunctionComponent<ChatInputProperties> = (props: ChatInpu
387
425
  event.preventDefault();
388
426
  submit(editorRef.current?.document.textEditorModel.getValue() || '');
389
427
  }
390
- }, [props.isEnabled]);
428
+ }, [props.isEnabled, submit]);
391
429
 
392
430
  const handleInputFocus = () => {
393
431
  hidePlaceholderIfEditorFilled();
@@ -498,13 +536,18 @@ const noPropagation = (handler: () => void) => (e: React.MouseEvent) => {
498
536
  e.stopPropagation();
499
537
  };
500
538
 
501
- const buildChangeSetUI = (changeSet: ChangeSet, labelProvider: LabelProvider, onDeleteChangeSet: () => void, onDeleteChangeSetElement: (index: number) => void): ChangeSetUI => ({
539
+ const buildChangeSetUI = (
540
+ changeSet: ChangeSet,
541
+ labelProvider: LabelProvider,
542
+ actions: ChangeSetActionRenderer[],
543
+ onDeleteChangeSet: () => void,
544
+ onDeleteChangeSetElement: (index: number) => void
545
+ ): ChangeSetUI => ({
502
546
  title: changeSet.title,
503
- disabled: !hasPendingElementsToAccept(changeSet),
504
- applyAllPendingElements: () => applyAllPendingElements(changeSet),
505
- delete: () => onDeleteChangeSet(),
547
+ changeSet,
548
+ deleteChangeSet: onDeleteChangeSet,
506
549
  elements: changeSet.getElements().map(element => ({
507
- open: element?.open?.bind(element),
550
+ open: element.open?.bind(element),
508
551
  iconClass: element.icon ?? labelProvider.getIcon(element.uri) ?? labelProvider.fileIcon,
509
552
  nameClass: `${element.type} ${element.state}`,
510
553
  name: element.name ?? labelProvider.getName(element.uri),
@@ -513,7 +556,8 @@ const buildChangeSetUI = (changeSet: ChangeSet, labelProvider: LabelProvider, on
513
556
  apply: element.state !== 'applied' ? element?.apply?.bind(element) : undefined,
514
557
  revert: element.state === 'applied' || element.state === 'stale' ? element?.revert?.bind(element) : undefined,
515
558
  delete: () => onDeleteChangeSetElement(changeSet.getElements().indexOf(element))
516
- }))
559
+ })),
560
+ actions
517
561
  });
518
562
 
519
563
  interface ChangeSetUIElement {
@@ -529,32 +573,26 @@ interface ChangeSetUIElement {
529
573
  }
530
574
 
531
575
  interface ChangeSetUI {
576
+ changeSet: ChangeSet;
532
577
  title: string;
533
- disabled: boolean;
534
- applyAllPendingElements: () => void;
535
- delete: () => void;
578
+ deleteChangeSet: () => void;
536
579
  elements: ChangeSetUIElement[];
580
+ actions: ChangeSetActionRenderer[];
537
581
  }
538
582
 
539
- const ChangeSetBox: React.FunctionComponent<{ changeSet: ChangeSetUI }> = ({ changeSet }) => (
583
+ /** Memo because the parent element rerenders on every key press in the chat widget. */
584
+ const ChangeSetBox: React.FunctionComponent<{ changeSet: ChangeSetUI }> = React.memo(({ changeSet: { changeSet, title, deleteChangeSet, elements, actions } }) => (
540
585
  <div className='theia-ChatInput-ChangeSet-Box'>
541
586
  <div className='theia-ChatInput-ChangeSet-Header'>
542
- <h3>{changeSet.title}</h3>
587
+ <h3>{title}</h3>
543
588
  <div className='theia-ChatInput-ChangeSet-Header-Actions'>
544
- <button
545
- className='theia-button'
546
- disabled={changeSet.disabled}
547
- title={nls.localize('theia/ai/chat-ui/applyAllTitle', 'Apply all pending suggestions')}
548
- onClick={() => changeSet.applyAllPendingElements()}
549
- >
550
- {nls.localize('theia/ai/chat-ui/acceptAll', 'Apply All')}
551
- </button>
552
- <span className='codicon codicon-close action' title={nls.localize('theia/ai/chat-ui/deleteChangeSet', 'Delete Change Set')} onClick={() => changeSet.delete()} />
589
+ {actions.map(action => <div key={action.id} className='theia-changeSet-Action'>{action.render(changeSet)}</div>)}
590
+ <span className='codicon codicon-close action' title={nls.localize('theia/ai/chat-ui/deleteChangeSet', 'Delete Change Set')} onClick={() => deleteChangeSet()} />
553
591
  </div>
554
592
  </div>
555
593
  <div className='theia-ChatInput-ChangeSet-List'>
556
594
  <ul>
557
- {changeSet.elements.map((element, index) => (
595
+ {elements.map((element, index) => (
558
596
  <li key={index} title={nls.localize('theia/ai/chat-ui/openDiff', 'Open Diff')} onClick={() => element.openChange?.()}>
559
597
  <div className={`theia-ChatInput-ChangeSet-Icon ${element.iconClass}`} />
560
598
  <span className='theia-ChatInput-ChangeSet-labelParts'>
@@ -591,7 +629,7 @@ const ChangeSetBox: React.FunctionComponent<{ changeSet: ChangeSetUI }> = ({ cha
591
629
  </ul>
592
630
  </div>
593
631
  </div>
594
- );
632
+ ));
595
633
 
596
634
  interface ChatInputOptionsProps {
597
635
  leftOptions: Option[];
@@ -640,24 +678,12 @@ const ChatInputOptions: React.FunctionComponent<ChatInputOptionsProps> = ({ left
640
678
  </div>
641
679
  );
642
680
 
643
- function applyAllPendingElements(changeSet: ChangeSet): void {
644
- getPendingElements(changeSet).forEach(e => e.apply!());
645
- }
646
-
647
- function hasPendingElementsToAccept(changeSet: ChangeSet): boolean | undefined {
648
- return getPendingElements(changeSet).length > 0;
649
- }
650
-
651
- function getPendingElements(changeSet: ChangeSet): ChangeSetElement[] {
652
- return changeSet.getElements().filter(e => e.apply && (e.state === undefined || e.state === 'pending'));
653
- }
654
-
655
681
  function getLatestRequest(chatModel: ChatModel): ChatRequestModel | undefined {
656
682
  const requests = chatModel.getRequests();
657
683
  return requests.length > 0 ? requests[requests.length - 1] : undefined;
658
684
  }
659
685
 
660
- function buildContextUI(context: AIVariableResolutionRequest[] | undefined, labelProvider: LabelProvider, onDeleteContextElement: (index: number) => void): ChatContextUI {
686
+ function buildContextUI(context: readonly AIVariableResolutionRequest[] | undefined, labelProvider: LabelProvider, onDeleteContextElement: (index: number) => void): ChatContextUI {
661
687
  if (!context) {
662
688
  return { context: [] };
663
689
  }
@@ -14,11 +14,11 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import { CancellationToken, ContributionProvider, Prioritizeable, RecursivePartial, URI } from '@theia/core';
18
- import { inject, injectable, named } from '@theia/core/shared/inversify';
17
+ import { CancellationToken, RecursivePartial, URI } from '@theia/core';
18
+ import { inject, injectable } from '@theia/core/shared/inversify';
19
19
  import { EditorOpenerOptions, EditorWidget, Range } from '@theia/editor/lib/browser';
20
20
 
21
- import { EditorPreviewManager } from '@theia/editor-preview/lib/browser/editor-preview-manager';
21
+ import { EditorSelectionResolver } from '@theia/editor/lib/browser/editor-manager';
22
22
  import { DocumentSymbol } from '@theia/monaco-editor-core/esm/vs/editor/common/languages';
23
23
  import { TextModel } from '@theia/monaco-editor-core/esm/vs/editor/common/model/textModel';
24
24
  import { ILanguageFeaturesService } from '@theia/monaco-editor-core/esm/vs/editor/common/services/languageFeatures';
@@ -29,17 +29,8 @@ import { MonacoToProtocolConverter } from '@theia/monaco/lib/browser/monaco-to-p
29
29
  /** Regex to match GitHub-style position and range declaration with line (L) and column (C) */
30
30
  export const LOCATION_REGEX = /#L(\d+)?(?:C(\d+))?(?:-L(\d+)?(?:C(\d+))?)?$/;
31
31
 
32
- export const AIEditorSelectionResolver = Symbol('AIEditorSelectionResolver');
33
- export interface AIEditorSelectionResolver {
34
- /**
35
- * The priority of the resolver. A higher value resolver will be called before others.
36
- */
37
- priority?: number;
38
- resolveSelection(widget: EditorWidget, options: EditorOpenerOptions, uri?: URI): Promise<RecursivePartial<Range> | undefined>
39
- }
40
-
41
32
  @injectable()
42
- export class GitHubSelectionResolver implements AIEditorSelectionResolver {
33
+ export class GitHubSelectionResolver implements EditorSelectionResolver {
43
34
  priority = 100;
44
35
 
45
36
  async resolveSelection(widget: EditorWidget, options: EditorOpenerOptions, uri?: URI): Promise<RecursivePartial<Range> | undefined> {
@@ -67,7 +58,7 @@ export class GitHubSelectionResolver implements AIEditorSelectionResolver {
67
58
  }
68
59
 
69
60
  @injectable()
70
- export class TypeDocSymbolSelectionResolver implements AIEditorSelectionResolver {
61
+ export class TypeDocSymbolSelectionResolver implements EditorSelectionResolver {
71
62
  priority = 50;
72
63
 
73
64
  @inject(MonacoToProtocolConverter) protected readonly m2p: MonacoToProtocolConverter;
@@ -123,7 +114,7 @@ export class TypeDocSymbolSelectionResolver implements AIEditorSelectionResolver
123
114
  }
124
115
 
125
116
  @injectable()
126
- export class TextFragmentSelectionResolver implements AIEditorSelectionResolver {
117
+ export class TextFragmentSelectionResolver implements EditorSelectionResolver {
127
118
  async resolveSelection(widget: EditorWidget, options: EditorOpenerOptions, uri?: URI): Promise<RecursivePartial<Range> | undefined> {
128
119
  if (!uri) {
129
120
  return;
@@ -151,33 +142,3 @@ export class TextFragmentSelectionResolver implements AIEditorSelectionResolver
151
142
  return uri.fragment;
152
143
  }
153
144
  }
154
-
155
- @injectable()
156
- export class AIEditorManager extends EditorPreviewManager {
157
- @inject(ContributionProvider) @named(AIEditorSelectionResolver)
158
- protected readonly resolvers: ContributionProvider<AIEditorSelectionResolver>;
159
-
160
- protected override async revealSelection(widget: EditorWidget, options: EditorOpenerOptions = {}, uri?: URI): Promise<void> {
161
- if (!options.selection) {
162
- options.selection = await this.resolveSelection(options, widget, uri);
163
- }
164
- super.revealSelection(widget, options, uri);
165
- }
166
-
167
- protected async resolveSelection(options: EditorOpenerOptions, widget: EditorWidget, uri: URI | undefined): Promise<RecursivePartial<Range> | undefined> {
168
- if (!options.selection) {
169
- const orderedResolvers = Prioritizeable.prioritizeAllSync(this.resolvers.getContributions(), resolver => resolver.priority ?? 1);
170
- for (const linkResolver of orderedResolvers) {
171
- try {
172
- const selection = await linkResolver.value.resolveSelection(widget, options, uri);
173
- if (selection) {
174
- return selection;
175
- }
176
- } catch (error) {
177
- console.error(error);
178
- }
179
- }
180
- }
181
- return undefined;
182
- }
183
- }
@@ -13,7 +13,7 @@
13
13
  //
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
- export * from './ai-editor-manager';
16
+ export * from './ai-selection-resolver';
17
17
  export * from './code-part-renderer';
18
18
  export * from './command-part-renderer';
19
19
  export * from './error-part-renderer';
@@ -161,12 +161,11 @@ export class ChatViewWidget extends BaseWidget implements ExtractableWidget, Sta
161
161
  return this.onStateChangedEmitter.event;
162
162
  }
163
163
 
164
- protected async onQuery(query: string, contextVariableRequests?: AIVariableResolutionRequest[]): Promise<void> {
164
+ protected async onQuery(query: string): Promise<void> {
165
165
  if (query.length === 0) { return; }
166
166
 
167
167
  const chatRequest: ChatRequest = { text: query };
168
- const context = { variableRequests: contextVariableRequests ?? [] };
169
- const requestProgress = await this.chatService.sendRequest(this.chatSession.id, chatRequest, context);
168
+ const requestProgress = await this.chatService.sendRequest(this.chatSession.id, chatRequest);
170
169
  requestProgress?.responseCompleted.then(responseModel => {
171
170
  if (responseModel.isError) {
172
171
  this.messageService.error(responseModel.errorObject?.message ??
@@ -248,14 +248,15 @@ div:last-child > .theia-ChatNode {
248
248
  color: var(--theia-disabledForeground);
249
249
  padding-top: 0;
250
250
  margin: 0;
251
- display: flex;
252
251
  }
253
252
 
254
- .theia-ChatInput-ChangeSet-Header-Actions button {
253
+ .theia-ChatInput-ChangeSet-Header-Actions .theia-button {
254
+ height: 100%;
255
+ box-sizing: border-box;
255
256
  font-size: 12px;
256
257
  padding: 2px 4px;
257
258
  min-width: 40px;
258
- margin-left: 6px;
259
+ margin: 0;
259
260
  }
260
261
 
261
262
  .theia-ChatInput-ChangeSet-List ul {
@@ -339,6 +340,17 @@ div:last-child > .theia-ChatNode {
339
340
  text-overflow: ellipsis;
340
341
  }
341
342
 
343
+ .theia-ChatInput-ChangeSet-Header-Actions {
344
+ display: flex;
345
+ flex: none;
346
+ flex-flow: row nowrap;
347
+ gap: var(--theia-ui-padding);
348
+ }
349
+
350
+ .theia-changeSet-Action {
351
+ flex: none;
352
+ }
353
+
342
354
  .theia-ChatInput-ChangeSet-Header-Actions,
343
355
  .theia-ChatInput-ChangeSet-Box h3,
344
356
  .theia-ChatInput-ChangeSet-additionalInfo {
@@ -1,36 +0,0 @@
1
- import { ContributionProvider, RecursivePartial, URI } from '@theia/core';
2
- import { EditorOpenerOptions, EditorWidget, Range } from '@theia/editor/lib/browser';
3
- import { EditorPreviewManager } from '@theia/editor-preview/lib/browser/editor-preview-manager';
4
- import { DocumentSymbol } from '@theia/monaco-editor-core/esm/vs/editor/common/languages';
5
- import { MonacoToProtocolConverter } from '@theia/monaco/lib/browser/monaco-to-protocol-converter';
6
- /** Regex to match GitHub-style position and range declaration with line (L) and column (C) */
7
- export declare const LOCATION_REGEX: RegExp;
8
- export declare const AIEditorSelectionResolver: unique symbol;
9
- export interface AIEditorSelectionResolver {
10
- /**
11
- * The priority of the resolver. A higher value resolver will be called before others.
12
- */
13
- priority?: number;
14
- resolveSelection(widget: EditorWidget, options: EditorOpenerOptions, uri?: URI): Promise<RecursivePartial<Range> | undefined>;
15
- }
16
- export declare class GitHubSelectionResolver implements AIEditorSelectionResolver {
17
- priority: number;
18
- resolveSelection(widget: EditorWidget, options: EditorOpenerOptions, uri?: URI): Promise<RecursivePartial<Range> | undefined>;
19
- }
20
- export declare class TypeDocSymbolSelectionResolver implements AIEditorSelectionResolver {
21
- priority: number;
22
- protected readonly m2p: MonacoToProtocolConverter;
23
- resolveSelection(widget: EditorWidget, options: EditorOpenerOptions, uri?: URI): Promise<RecursivePartial<Range> | undefined>;
24
- protected findSymbolPath(uri: URI): string[] | undefined;
25
- protected findSymbolByPath(symbols: DocumentSymbol[], symbolPath: string[]): DocumentSymbol | undefined;
26
- }
27
- export declare class TextFragmentSelectionResolver implements AIEditorSelectionResolver {
28
- resolveSelection(widget: EditorWidget, options: EditorOpenerOptions, uri?: URI): Promise<RecursivePartial<Range> | undefined>;
29
- protected findFragment(uri: URI): string | undefined;
30
- }
31
- export declare class AIEditorManager extends EditorPreviewManager {
32
- protected readonly resolvers: ContributionProvider<AIEditorSelectionResolver>;
33
- protected revealSelection(widget: EditorWidget, options?: EditorOpenerOptions, uri?: URI): Promise<void>;
34
- protected resolveSelection(options: EditorOpenerOptions, widget: EditorWidget, uri: URI | undefined): Promise<RecursivePartial<Range> | undefined>;
35
- }
36
- //# sourceMappingURL=ai-editor-manager.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ai-editor-manager.d.ts","sourceRoot":"","sources":["../../../src/browser/chat-response-renderer/ai-editor-manager.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAqB,oBAAoB,EAAkB,gBAAgB,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAE7G,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAErF,OAAO,EAAE,oBAAoB,EAAE,MAAM,0DAA0D,CAAC;AAChG,OAAO,EAAE,cAAc,EAAE,MAAM,0DAA0D,CAAC;AAK1F,OAAO,EAAE,yBAAyB,EAAE,MAAM,wDAAwD,CAAC;AAEnG,8FAA8F;AAC9F,eAAO,MAAM,cAAc,QAAiD,CAAC;AAE7E,eAAO,MAAM,yBAAyB,eAAsC,CAAC;AAC7E,MAAM,WAAW,yBAAyB;IACtC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,mBAAmB,EAAE,GAAG,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC,CAAA;CAChI;AAED,qBACa,uBAAwB,YAAW,yBAAyB;IACrE,QAAQ,SAAO;IAET,gBAAgB,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,mBAAmB,EAAE,GAAG,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC;CAsBtI;AAED,qBACa,8BAA+B,YAAW,yBAAyB;IAC5E,QAAQ,SAAM;IAEqB,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,yBAAyB,CAAC;IAE/E,gBAAgB,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,mBAAmB,EAAE,GAAG,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC;IA6BnI,SAAS,CAAC,cAAc,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,EAAE,GAAG,SAAS;IAIxD,SAAS,CAAC,gBAAgB,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,cAAc,GAAG,SAAS;CAe1G;AAED,qBACa,6BAA8B,YAAW,yBAAyB;IACrE,gBAAgB,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,mBAAmB,EAAE,GAAG,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC;IAuBnI,SAAS,CAAC,YAAY,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,GAAG,SAAS;CAGvD;AAED,qBACa,eAAgB,SAAQ,oBAAoB;IAErD,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,oBAAoB,CAAC,yBAAyB,CAAC,CAAC;cAErD,eAAe,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,GAAE,mBAAwB,EAAE,GAAG,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;cAO3G,gBAAgB,CAAC,OAAO,EAAE,mBAAmB,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG,GAAG,SAAS,GAAG,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC;CAgB3J"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ai-editor-manager.js","sourceRoot":"","sources":["../../../src/browser/chat-response-renderer/ai-editor-manager.ts"],"names":[],"mappings":"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"}