@opensumi/ide-ai-native 3.7.1-next-1738899837.0 → 3.7.1-next-1738922480.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 (26) hide show
  1. package/lib/browser/layout/layout.module.less +9 -9
  2. package/lib/browser/layout/tabbar.view.d.ts.map +1 -1
  3. package/lib/browser/layout/tabbar.view.js +6 -5
  4. package/lib/browser/layout/tabbar.view.js.map +1 -1
  5. package/lib/browser/widget/inline-chat/inline-content-widget.d.ts.map +1 -1
  6. package/lib/browser/widget/inline-chat/inline-content-widget.js +0 -5
  7. package/lib/browser/widget/inline-chat/inline-content-widget.js.map +1 -1
  8. package/lib/browser/widget/inline-input/inline-input-widget.d.ts +5 -3
  9. package/lib/browser/widget/inline-input/inline-input-widget.d.ts.map +1 -1
  10. package/lib/browser/widget/inline-input/inline-input-widget.js +14 -10
  11. package/lib/browser/widget/inline-input/inline-input-widget.js.map +1 -1
  12. package/lib/browser/widget/inline-input/inline-input.controller.d.ts +3 -0
  13. package/lib/browser/widget/inline-input/inline-input.controller.d.ts.map +1 -1
  14. package/lib/browser/widget/inline-input/inline-input.controller.js +80 -36
  15. package/lib/browser/widget/inline-input/inline-input.controller.js.map +1 -1
  16. package/lib/browser/widget/inline-input/model.d.ts +19 -1
  17. package/lib/browser/widget/inline-input/model.d.ts.map +1 -1
  18. package/lib/browser/widget/inline-input/model.js +39 -1
  19. package/lib/browser/widget/inline-input/model.js.map +1 -1
  20. package/package.json +21 -21
  21. package/src/browser/layout/layout.module.less +9 -9
  22. package/src/browser/layout/tabbar.view.tsx +8 -10
  23. package/src/browser/widget/inline-chat/inline-content-widget.tsx +0 -7
  24. package/src/browser/widget/inline-input/inline-input-widget.tsx +14 -5
  25. package/src/browser/widget/inline-input/inline-input.controller.ts +110 -42
  26. package/src/browser/widget/inline-input/model.ts +41 -1
@@ -15,6 +15,13 @@ import {
15
15
  import { EditorGroupCloseEvent } from '@opensumi/ide-editor/lib/browser';
16
16
  import * as monaco from '@opensumi/ide-monaco';
17
17
  import { ICodeEditor } from '@opensumi/ide-monaco';
18
+ import {
19
+ IObservable,
20
+ ISettableObservable,
21
+ autorun,
22
+ observableFromEvent,
23
+ observableValue,
24
+ } from '@opensumi/ide-monaco/lib/common/observable';
18
25
  import { MessageService } from '@opensumi/ide-overlay/lib/browser/message.service';
19
26
  import { EditOperation } from '@opensumi/monaco-editor-core/esm/vs/editor/common/core/editOperation';
20
27
  import { LineRange } from '@opensumi/monaco-editor-core/esm/vs/editor/common/core/lineRange';
@@ -28,10 +35,10 @@ import { EInlineChatStatus, EResultKind } from '../inline-chat/inline-chat.servi
28
35
  import { InlineDiffController } from '../inline-diff';
29
36
  import { InlineInputPreviewDecorationID } from '../internal.type';
30
37
 
31
- import { InlineInputChatWidget } from './inline-input-widget';
38
+ import { InlineInputWidget } from './inline-input-widget';
32
39
  import styles from './inline-input.module.less';
33
40
  import { InlineInputService } from './inline-input.service';
34
-
41
+ import { InlineInputWidgetStoreInEmptyLine, InlineInputWidgetStoreInSelection } from './model';
35
42
  @Injectable()
36
43
  export class InlineInputController extends BaseAIMonacoEditorController {
37
44
  public static readonly ID = 'editor.contrib.ai.inline.input';
@@ -60,11 +67,25 @@ export class InlineInputController extends BaseAIMonacoEditorController {
60
67
  private inputDisposable: Disposable;
61
68
  private aiNativeContextKey: AINativeContextKey;
62
69
 
70
+ private inputValue: ISettableObservable<string>;
71
+ private modelChangeObs: IObservable<monaco.editor.ITextModel, unknown>;
72
+ private inlineInputWidgetStore = new Map<
73
+ string,
74
+ InlineInputWidgetStoreInEmptyLine | InlineInputWidgetStoreInSelection | null
75
+ >();
76
+
63
77
  mount(): IDisposable {
64
78
  this.inputDisposable = new Disposable();
65
79
  this.aiNativeContextKey = this.injector.get(AINativeContextKey, [this.monacoEditor.contextKeyService]);
66
80
  this.inlineDiffController = InlineDiffController.get(this.monacoEditor)!;
67
81
 
82
+ this.inputValue = observableValue(this, '');
83
+ this.modelChangeObs = observableFromEvent<monaco.editor.ITextModel>(
84
+ this,
85
+ this.monacoEditor.onDidChangeModel,
86
+ () => this.monacoEditor.getModel()!,
87
+ );
88
+
68
89
  this.featureDisposable.addDispose(
69
90
  /**
70
91
  * 如果在流式过程中,直接关闭了当前文件,则需要销毁 diff previewer 并隐藏 input,恢复原始代码
@@ -91,10 +112,7 @@ export class InlineInputController extends BaseAIMonacoEditorController {
91
112
  );
92
113
 
93
114
  this.featureDisposable.addDispose(
94
- Event.any<any>(
95
- this.inlineInputService.onHidden,
96
- this.monacoEditor.onWillChangeModel,
97
- )(() => {
115
+ this.inlineInputService.onHidden(() => {
98
116
  this.hideInput();
99
117
  }),
100
118
  );
@@ -119,6 +137,27 @@ export class InlineInputController extends BaseAIMonacoEditorController {
119
137
  }),
120
138
  );
121
139
 
140
+ this.featureDisposable.addDispose(
141
+ autorun((reader) => {
142
+ const model = this.modelChangeObs.read(reader);
143
+ if (!model) {
144
+ return;
145
+ }
146
+
147
+ const storeData = this.inlineInputWidgetStore.get(model.id);
148
+ if (!storeData) {
149
+ this.hideInput();
150
+ return;
151
+ }
152
+
153
+ if (storeData instanceof InlineInputWidgetStoreInEmptyLine) {
154
+ this.showInputInEmptyLine(storeData.getPosition(), this.monacoEditor, storeData.getValue());
155
+ } else if (storeData instanceof InlineInputWidgetStoreInSelection) {
156
+ this.showInputInSelection(storeData.getSelection(), this.monacoEditor, storeData.getValue());
157
+ }
158
+ }),
159
+ );
160
+
122
161
  this.featureDisposable.addDispose(this.inputDisposable);
123
162
 
124
163
  return this.featureDisposable;
@@ -130,6 +169,7 @@ export class InlineInputController extends BaseAIMonacoEditorController {
130
169
  }
131
170
 
132
171
  private hideInput() {
172
+ this.inlineInputWidgetStore.delete(this.monacoEditor.getModel()!.id);
133
173
  this.inputDisposable.dispose();
134
174
  }
135
175
 
@@ -145,15 +185,16 @@ export class InlineInputController extends BaseAIMonacoEditorController {
145
185
  return;
146
186
  }
147
187
 
188
+ this.inputValue.set(defaultValue || '', undefined);
189
+ this.inlineInputWidgetStore.set(model.id, new InlineInputWidgetStoreInEmptyLine(position, defaultValue));
190
+
148
191
  if (this.inputDisposable) {
149
192
  this.inputDisposable.dispose();
150
193
  this.inputDisposable = new Disposable();
151
194
  }
152
195
 
153
196
  const collection = monacoEditor.createDecorationsCollection();
154
- const inlineInputChatWidget = this.injector.get(InlineInputChatWidget, [monacoEditor, defaultValue]);
155
-
156
- let inputValue = defaultValue;
197
+ const inlineInputWidget = this.injector.get(InlineInputWidget, [monacoEditor, this.inputValue.get()]);
157
198
 
158
199
  // 仅在空行情况下增加装饰逻辑
159
200
  collection.append([
@@ -172,12 +213,12 @@ export class InlineInputController extends BaseAIMonacoEditorController {
172
213
  let preLineRange: LineRange;
173
214
  if (decorationRange) {
174
215
  preLineRange = LineRange.fromRange(decorationRange);
175
- inlineInputChatWidget.show({ position: decorationRange.getStartPosition() });
216
+ inlineInputWidget.show({ position: decorationRange.getStartPosition() });
176
217
  this.aiNativeContextKey.inlineInputWidgetIsVisible.set(true);
177
218
  }
178
219
 
179
220
  this.inputDisposable.addDispose(
180
- inlineInputChatWidget.onDispose(() => {
221
+ inlineInputWidget.onDispose(() => {
181
222
  this.cancelToken();
182
223
  collection.clear();
183
224
  this.aiNativeContextKey.inlineInputWidgetIsVisible.set(false);
@@ -185,7 +226,18 @@ export class InlineInputController extends BaseAIMonacoEditorController {
185
226
  );
186
227
 
187
228
  this.inputDisposable.addDispose(
188
- inlineInputChatWidget.onResultClick(async (kind: EResultKind) => {
229
+ inlineInputWidget.onValueChange((value) => {
230
+ this.inputValue.set(value, undefined);
231
+
232
+ const storeData = this.inlineInputWidgetStore.get(model.id);
233
+ if (storeData instanceof InlineInputWidgetStoreInEmptyLine) {
234
+ storeData.setValue(value);
235
+ }
236
+ }),
237
+ );
238
+
239
+ this.inputDisposable.addDispose(
240
+ inlineInputWidget.onResultClick(async (kind: EResultKind) => {
189
241
  const clear = () => {
190
242
  const curPosi = collection.getRange(0)!;
191
243
 
@@ -210,7 +262,7 @@ export class InlineInputController extends BaseAIMonacoEditorController {
210
262
  */
211
263
  const curPosi = collection.getRange(0)!;
212
264
  const curPosition = curPosi.getStartPosition();
213
- this.showInputInEmptyLine(curPosition, monacoEditor, inputValue);
265
+ this.showInputInEmptyLine(curPosition, monacoEditor, this.inputValue.get());
214
266
  });
215
267
  break;
216
268
 
@@ -233,18 +285,18 @@ export class InlineInputController extends BaseAIMonacoEditorController {
233
285
  const range = collection.getRange(0)!;
234
286
  const curLineRange = LineRange.fromRange(range);
235
287
  if (!preLineRange.equals(curLineRange)) {
236
- inlineInputChatWidget.setOptions({
288
+ inlineInputWidget.setOptions({
237
289
  position: range.getStartPosition(),
238
290
  });
239
291
 
240
- inlineInputChatWidget.layoutContentWidget();
292
+ inlineInputWidget.layoutContentWidget();
241
293
  }
242
294
  preLineRange = curLineRange;
243
295
  }),
244
296
  );
245
297
 
246
298
  this.inputDisposable.addDispose(
247
- inlineInputChatWidget.onClose(() => {
299
+ inlineInputWidget.onClose(() => {
248
300
  const isStreaming = this.aiNativeContextKey.inlineInputWidgetIsStreaming.get();
249
301
  if (isStreaming) {
250
302
  this.cancelToken();
@@ -255,8 +307,7 @@ export class InlineInputController extends BaseAIMonacoEditorController {
255
307
  );
256
308
 
257
309
  this.inputDisposable.addDispose(
258
- inlineInputChatWidget.onInteractiveInputValue(async (value) => {
259
- inputValue = value;
310
+ inlineInputWidget.onSend(async (value) => {
260
311
  monacoEditor.focus();
261
312
 
262
313
  const handler = this.inlineInputService.getInteractiveInputHandler();
@@ -266,13 +317,13 @@ export class InlineInputController extends BaseAIMonacoEditorController {
266
317
  return;
267
318
  }
268
319
 
269
- inlineInputChatWidget.launchChatStatus(EInlineChatStatus.THINKING);
320
+ inlineInputWidget.launchChatStatus(EInlineChatStatus.THINKING);
270
321
 
271
322
  const strategy = await this.inlineInputService.getInteractiveInputStrategyHandler()(monacoEditor, value);
272
323
 
273
324
  if (strategy === ERunStrategy.EXECUTE && handler.execute) {
274
325
  handler.execute(monacoEditor, value, this.token);
275
- inlineInputChatWidget.launchChatStatus(EInlineChatStatus.DONE);
326
+ inlineInputWidget.launchChatStatus(EInlineChatStatus.DONE);
276
327
  this.hideInput();
277
328
  return;
278
329
  }
@@ -281,7 +332,7 @@ export class InlineInputController extends BaseAIMonacoEditorController {
281
332
  const previewResponse = await handler.providePreviewStrategy(monacoEditor, value, this.token);
282
333
 
283
334
  if (CancelResponse.is(previewResponse)) {
284
- inlineInputChatWidget.launchChatStatus(EInlineChatStatus.READY);
335
+ inlineInputWidget.launchChatStatus(EInlineChatStatus.READY);
285
336
  this.hideInput();
286
337
  return;
287
338
  }
@@ -314,17 +365,17 @@ export class InlineInputController extends BaseAIMonacoEditorController {
314
365
  }),
315
366
  controller.onError((error) => {
316
367
  this.aiNativeContextKey.inlineInputWidgetIsStreaming.set(false);
317
- inlineInputChatWidget.launchChatStatus(EInlineChatStatus.ERROR);
368
+ inlineInputWidget.launchChatStatus(EInlineChatStatus.ERROR);
318
369
  }),
319
370
  controller.onAbort(() => {
320
371
  this.aiNativeContextKey.inlineInputWidgetIsStreaming.set(false);
321
372
  model.pushStackElement();
322
- inlineInputChatWidget.launchChatStatus(EInlineChatStatus.DONE);
373
+ inlineInputWidget.launchChatStatus(EInlineChatStatus.DONE);
323
374
  }),
324
375
  controller.onEnd(() => {
325
376
  this.aiNativeContextKey.inlineInputWidgetIsStreaming.set(false);
326
377
  model.pushStackElement();
327
- inlineInputChatWidget.launchChatStatus(EInlineChatStatus.DONE);
378
+ inlineInputWidget.launchChatStatus(EInlineChatStatus.DONE);
328
379
  }),
329
380
  ]);
330
381
 
@@ -334,7 +385,7 @@ export class InlineInputController extends BaseAIMonacoEditorController {
334
385
  }),
335
386
  );
336
387
 
337
- this.inputDisposable.addDispose(inlineInputChatWidget);
388
+ this.inputDisposable.addDispose(inlineInputWidget);
338
389
  }
339
390
 
340
391
  private async showInputInSelection(selection: monaco.Selection, monacoEditor: ICodeEditor, defaultValue?: string) {
@@ -343,6 +394,14 @@ export class InlineInputController extends BaseAIMonacoEditorController {
343
394
  this.inputDisposable = new Disposable();
344
395
  }
345
396
 
397
+ const model = monacoEditor.getModel();
398
+ if (!model) {
399
+ return;
400
+ }
401
+
402
+ this.inputValue.set(defaultValue || '', undefined);
403
+ this.inlineInputWidgetStore.set(model.id, new InlineInputWidgetStoreInSelection(selection, defaultValue));
404
+
346
405
  const decorationsCollection = monacoEditor.createDecorationsCollection();
347
406
  decorationsCollection.set([
348
407
  {
@@ -361,15 +420,14 @@ export class InlineInputController extends BaseAIMonacoEditorController {
361
420
  },
362
421
  ]);
363
422
 
364
- const inlineInputChatWidget = this.injector.get(InlineInputChatWidget, [monacoEditor, defaultValue]);
365
- inlineInputChatWidget.show({ selection });
423
+ const inlineInputWidget = this.injector.get(InlineInputWidget, [monacoEditor, this.inputValue.get()]);
424
+ inlineInputWidget.show({ selection });
366
425
 
367
426
  this.aiNativeContextKey.inlineInputWidgetIsVisible.set(true);
368
427
  this.inlineDiffController.destroyPreviewer(monacoEditor.getModel()?.uri.toString());
369
- let inputValue = defaultValue;
370
428
 
371
429
  this.inputDisposable.addDispose(
372
- inlineInputChatWidget.onDispose(() => {
430
+ inlineInputWidget.onDispose(() => {
373
431
  this.cancelToken();
374
432
  decorationsCollection.clear();
375
433
  this.aiNativeContextKey.inlineInputWidgetIsVisible.set(false);
@@ -377,7 +435,18 @@ export class InlineInputController extends BaseAIMonacoEditorController {
377
435
  );
378
436
 
379
437
  this.inputDisposable.addDispose(
380
- inlineInputChatWidget.onClose(() => {
438
+ inlineInputWidget.onValueChange((value) => {
439
+ this.inputValue.set(value, undefined);
440
+
441
+ const storeData = this.inlineInputWidgetStore.get(model.id);
442
+ if (storeData instanceof InlineInputWidgetStoreInSelection) {
443
+ storeData.setValue(value);
444
+ }
445
+ }),
446
+ );
447
+
448
+ this.inputDisposable.addDispose(
449
+ inlineInputWidget.onClose(() => {
381
450
  const isStreaming = this.aiNativeContextKey.inlineInputWidgetIsStreaming.get();
382
451
  if (isStreaming) {
383
452
  this.cancelToken();
@@ -388,8 +457,7 @@ export class InlineInputController extends BaseAIMonacoEditorController {
388
457
  );
389
458
 
390
459
  this.inputDisposable.addDispose(
391
- inlineInputChatWidget.onInteractiveInputValue(async (value) => {
392
- inputValue = value;
460
+ inlineInputWidget.onSend(async (value) => {
393
461
  monacoEditor.focus();
394
462
  decorationsCollection.clear();
395
463
 
@@ -399,7 +467,7 @@ export class InlineInputController extends BaseAIMonacoEditorController {
399
467
  return;
400
468
  }
401
469
 
402
- inlineInputChatWidget.launchChatStatus(EInlineChatStatus.THINKING);
470
+ inlineInputWidget.launchChatStatus(EInlineChatStatus.THINKING);
403
471
 
404
472
  const strategy = await this.inlineInputService.getInteractiveInputStrategyHandler()(monacoEditor, value);
405
473
 
@@ -411,7 +479,7 @@ export class InlineInputController extends BaseAIMonacoEditorController {
411
479
  const previewResponse = await handler.providePreviewStrategy(monacoEditor, value, this.token);
412
480
 
413
481
  if (CancelResponse.is(previewResponse)) {
414
- inlineInputChatWidget.launchChatStatus(EInlineChatStatus.READY);
482
+ inlineInputWidget.launchChatStatus(EInlineChatStatus.READY);
415
483
  this.hideInput();
416
484
  return;
417
485
  }
@@ -427,15 +495,15 @@ export class InlineInputController extends BaseAIMonacoEditorController {
427
495
  }),
428
496
  chatResponse.onError((error) => {
429
497
  this.aiNativeContextKey.inlineInputWidgetIsStreaming.set(false);
430
- inlineInputChatWidget.launchChatStatus(EInlineChatStatus.ERROR);
498
+ inlineInputWidget.launchChatStatus(EInlineChatStatus.ERROR);
431
499
  }),
432
500
  chatResponse.onAbort(() => {
433
501
  this.aiNativeContextKey.inlineInputWidgetIsStreaming.set(false);
434
- inlineInputChatWidget.launchChatStatus(EInlineChatStatus.DONE);
502
+ inlineInputWidget.launchChatStatus(EInlineChatStatus.DONE);
435
503
  }),
436
504
  chatResponse.onEnd(() => {
437
505
  this.aiNativeContextKey.inlineInputWidgetIsStreaming.set(false);
438
- inlineInputChatWidget.launchChatStatus(EInlineChatStatus.DONE);
506
+ inlineInputWidget.launchChatStatus(EInlineChatStatus.DONE);
439
507
  }),
440
508
  ]);
441
509
 
@@ -445,28 +513,28 @@ export class InlineInputController extends BaseAIMonacoEditorController {
445
513
  crossSelection,
446
514
  chatResponse,
447
515
  });
448
- diffPreviewer.mount(inlineInputChatWidget);
516
+ diffPreviewer.mount(inlineInputWidget);
449
517
  }
450
518
  } else {
451
- inlineInputChatWidget.launchChatStatus(EInlineChatStatus.READY);
519
+ inlineInputWidget.launchChatStatus(EInlineChatStatus.READY);
452
520
  this.hideInput();
453
521
  }
454
522
  }),
455
523
  );
456
524
 
457
525
  this.inputDisposable.addDispose(
458
- inlineInputChatWidget.onResultClick((kind: EResultKind) => {
526
+ inlineInputWidget.onResultClick((kind: EResultKind) => {
459
527
  this.inlineDiffController.handleAction(kind);
460
528
  this.hideInput();
461
529
 
462
530
  if (kind === EResultKind.REGENERATE) {
463
531
  requestAnimationFrame(() => {
464
- this.showInputInSelection(selection, monacoEditor, inputValue);
532
+ this.showInputInSelection(selection, monacoEditor, this.inputValue.get());
465
533
  });
466
534
  }
467
535
  }),
468
536
  );
469
537
 
470
- this.inputDisposable.addDispose(inlineInputChatWidget);
538
+ this.inputDisposable.addDispose(inlineInputWidget);
471
539
  }
472
540
  }
@@ -1,6 +1,6 @@
1
1
  import { InteractiveInput } from '@opensumi/ide-core-browser/lib/components/ai-native';
2
2
  import { MaybePromise, uuid } from '@opensumi/ide-core-common';
3
- import { ICodeEditor } from '@opensumi/ide-monaco';
3
+ import { ICodeEditor, IPosition, Selection } from '@opensumi/ide-monaco';
4
4
 
5
5
  import { ERunStrategy, IInteractiveInputHandler } from '../../types';
6
6
 
@@ -32,3 +32,43 @@ export class InteractiveInputModel {
32
32
  this._handler = undefined;
33
33
  }
34
34
  }
35
+
36
+ export class InlineInputWidgetStoreInEmptyLine {
37
+ constructor(private position: IPosition, private value?: string) {}
38
+
39
+ public getPosition(): IPosition {
40
+ return this.position;
41
+ }
42
+
43
+ public setPosition(position: IPosition): void {
44
+ this.position = position;
45
+ }
46
+
47
+ public getValue(): string | undefined {
48
+ return this.value;
49
+ }
50
+
51
+ public setValue(value: string): void {
52
+ this.value = value;
53
+ }
54
+ }
55
+
56
+ export class InlineInputWidgetStoreInSelection {
57
+ constructor(private selection: Selection, private value?: string) {}
58
+
59
+ public getSelection(): Selection {
60
+ return this.selection;
61
+ }
62
+
63
+ public setSelection(selection: Selection): void {
64
+ this.selection = selection;
65
+ }
66
+
67
+ public getValue(): string | undefined {
68
+ return this.value;
69
+ }
70
+
71
+ public setValue(value: string): void {
72
+ this.value = value;
73
+ }
74
+ }