@opensumi/ide-ai-native 3.7.1-next-1739781685.0 → 3.7.1

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 (162) hide show
  1. package/lib/browser/ai-core.contextkeys.d.ts +0 -1
  2. package/lib/browser/ai-core.contextkeys.d.ts.map +1 -1
  3. package/lib/browser/ai-core.contextkeys.js +0 -1
  4. package/lib/browser/ai-core.contextkeys.js.map +1 -1
  5. package/lib/browser/ai-core.contribution.d.ts +1 -2
  6. package/lib/browser/ai-core.contribution.d.ts.map +1 -1
  7. package/lib/browser/ai-core.contribution.js +15 -60
  8. package/lib/browser/ai-core.contribution.js.map +1 -1
  9. package/lib/browser/components/ChatMarkdown.d.ts.map +1 -1
  10. package/lib/browser/components/ChatMarkdown.js.map +1 -1
  11. package/lib/browser/components/WelcomeMsg.js.map +1 -1
  12. package/lib/browser/components/utils.d.ts +2 -2
  13. package/lib/browser/contrib/intelligent-completions/index.d.ts +9 -14
  14. package/lib/browser/contrib/intelligent-completions/index.d.ts.map +1 -1
  15. package/lib/browser/contrib/intelligent-completions/index.js +1 -6
  16. package/lib/browser/contrib/intelligent-completions/index.js.map +1 -1
  17. package/lib/browser/contrib/intelligent-completions/intelligent-completions.contribution.d.ts +0 -1
  18. package/lib/browser/contrib/intelligent-completions/intelligent-completions.contribution.d.ts.map +1 -1
  19. package/lib/browser/contrib/intelligent-completions/intelligent-completions.contribution.js +4 -26
  20. package/lib/browser/contrib/intelligent-completions/intelligent-completions.contribution.js.map +1 -1
  21. package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.d.ts +4 -5
  22. package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.d.ts.map +1 -1
  23. package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.js +42 -50
  24. package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.js.map +1 -1
  25. package/lib/browser/contrib/intelligent-completions/source/base.d.ts +3 -9
  26. package/lib/browser/contrib/intelligent-completions/source/base.d.ts.map +1 -1
  27. package/lib/browser/contrib/intelligent-completions/source/base.js +3 -21
  28. package/lib/browser/contrib/intelligent-completions/source/base.js.map +1 -1
  29. package/lib/browser/contrib/intelligent-completions/source/line-change.source.d.ts +3 -10
  30. package/lib/browser/contrib/intelligent-completions/source/line-change.source.d.ts.map +1 -1
  31. package/lib/browser/contrib/intelligent-completions/source/line-change.source.js +22 -95
  32. package/lib/browser/contrib/intelligent-completions/source/line-change.source.js.map +1 -1
  33. package/lib/browser/contrib/intelligent-completions/source/lint-error.source.d.ts +3 -1
  34. package/lib/browser/contrib/intelligent-completions/source/lint-error.source.d.ts.map +1 -1
  35. package/lib/browser/contrib/intelligent-completions/source/lint-error.source.js +20 -13
  36. package/lib/browser/contrib/intelligent-completions/source/lint-error.source.js.map +1 -1
  37. package/lib/browser/contrib/terminal/component/terminal-command-suggest-controller.js +2 -2
  38. package/lib/browser/contrib/terminal/component/terminal-command-suggest-controller.js.map +1 -1
  39. package/lib/browser/index.js +1 -1
  40. package/lib/browser/index.js.map +1 -1
  41. package/lib/browser/languages/tree-sitter/wasm-manager.d.ts.map +1 -1
  42. package/lib/browser/languages/tree-sitter/wasm-manager.js +2 -14
  43. package/lib/browser/languages/tree-sitter/wasm-manager.js.map +1 -1
  44. package/lib/browser/layout/ai-layout.d.ts.map +1 -1
  45. package/lib/browser/layout/ai-layout.js +2 -2
  46. package/lib/browser/layout/ai-layout.js.map +1 -1
  47. package/lib/browser/layout/layout.module.less +9 -9
  48. package/lib/browser/layout/tabbar.view.d.ts.map +1 -1
  49. package/lib/browser/layout/tabbar.view.js +6 -5
  50. package/lib/browser/layout/tabbar.view.js.map +1 -1
  51. package/lib/browser/model/enhanceDecorationsCollection.d.ts +10 -14
  52. package/lib/browser/model/enhanceDecorationsCollection.d.ts.map +1 -1
  53. package/lib/browser/model/enhanceDecorationsCollection.js +53 -42
  54. package/lib/browser/model/enhanceDecorationsCollection.js.map +1 -1
  55. package/lib/browser/model/styles.module.less +7 -0
  56. package/lib/browser/preferences/schema.d.ts.map +1 -1
  57. package/lib/browser/preferences/schema.js +0 -4
  58. package/lib/browser/preferences/schema.js.map +1 -1
  59. package/lib/browser/types.d.ts +2 -7
  60. package/lib/browser/types.d.ts.map +1 -1
  61. package/lib/browser/types.js.map +1 -1
  62. package/lib/browser/widget/inline-chat/inline-chat-editor.controller.d.ts +1 -2
  63. package/lib/browser/widget/inline-chat/inline-chat-editor.controller.d.ts.map +1 -1
  64. package/lib/browser/widget/inline-chat/inline-chat-editor.controller.js +48 -20
  65. package/lib/browser/widget/inline-chat/inline-chat-editor.controller.js.map +1 -1
  66. package/lib/browser/widget/inline-chat/inline-chat.feature.registry.d.ts +13 -3
  67. package/lib/browser/widget/inline-chat/inline-chat.feature.registry.d.ts.map +1 -1
  68. package/lib/browser/widget/inline-chat/inline-chat.feature.registry.js +72 -24
  69. package/lib/browser/widget/inline-chat/inline-chat.feature.registry.js.map +1 -1
  70. package/lib/browser/widget/inline-chat/inline-chat.service.d.ts +6 -1
  71. package/lib/browser/widget/inline-chat/inline-chat.service.d.ts.map +1 -1
  72. package/lib/browser/widget/inline-chat/inline-chat.service.js +17 -5
  73. package/lib/browser/widget/inline-chat/inline-chat.service.js.map +1 -1
  74. package/lib/browser/widget/inline-chat/inline-content-widget.d.ts +5 -2
  75. package/lib/browser/widget/inline-chat/inline-content-widget.d.ts.map +1 -1
  76. package/lib/browser/widget/inline-chat/inline-content-widget.js +42 -17
  77. package/lib/browser/widget/inline-chat/inline-content-widget.js.map +1 -1
  78. package/lib/browser/widget/inline-diff/inline-diff-previewer.d.ts +5 -22
  79. package/lib/browser/widget/inline-diff/inline-diff-previewer.d.ts.map +1 -1
  80. package/lib/browser/widget/inline-diff/inline-diff-previewer.js +30 -61
  81. package/lib/browser/widget/inline-diff/inline-diff-previewer.js.map +1 -1
  82. package/lib/browser/widget/inline-diff/inline-diff.controller.d.ts +12 -8
  83. package/lib/browser/widget/inline-diff/inline-diff.controller.d.ts.map +1 -1
  84. package/lib/browser/widget/inline-diff/inline-diff.controller.js +96 -68
  85. package/lib/browser/widget/inline-diff/inline-diff.controller.js.map +1 -1
  86. package/lib/browser/widget/inline-hint/inline-hint.controller.d.ts +1 -0
  87. package/lib/browser/widget/inline-hint/inline-hint.controller.d.ts.map +1 -1
  88. package/lib/browser/widget/inline-hint/inline-hint.controller.js +5 -0
  89. package/lib/browser/widget/inline-hint/inline-hint.controller.js.map +1 -1
  90. package/lib/browser/widget/inline-input/inline-input-widget.d.ts +2 -12
  91. package/lib/browser/widget/inline-input/inline-input-widget.d.ts.map +1 -1
  92. package/lib/browser/widget/inline-input/inline-input-widget.js +18 -26
  93. package/lib/browser/widget/inline-input/inline-input-widget.js.map +1 -1
  94. package/lib/browser/widget/inline-input/inline-input.controller.d.ts +5 -14
  95. package/lib/browser/widget/inline-input/inline-input.controller.d.ts.map +1 -1
  96. package/lib/browser/widget/inline-input/inline-input.controller.js +165 -321
  97. package/lib/browser/widget/inline-input/inline-input.controller.js.map +1 -1
  98. package/lib/browser/widget/inline-input/inline-input.module.less +0 -4
  99. package/lib/browser/widget/inline-input/inline-input.service.d.ts +7 -19
  100. package/lib/browser/widget/inline-input/inline-input.service.d.ts.map +1 -1
  101. package/lib/browser/widget/inline-input/inline-input.service.js +12 -72
  102. package/lib/browser/widget/inline-input/inline-input.service.js.map +1 -1
  103. package/lib/browser/widget/inline-stream-diff/inline-stream-diff.handler.d.ts +19 -8
  104. package/lib/browser/widget/inline-stream-diff/inline-stream-diff.handler.d.ts.map +1 -1
  105. package/lib/browser/widget/inline-stream-diff/inline-stream-diff.handler.js +39 -44
  106. package/lib/browser/widget/inline-stream-diff/inline-stream-diff.handler.js.map +1 -1
  107. package/lib/browser/widget/inline-stream-diff/live-preview.component.d.ts +4 -17
  108. package/lib/browser/widget/inline-stream-diff/live-preview.component.d.ts.map +1 -1
  109. package/lib/browser/widget/inline-stream-diff/live-preview.component.js +5 -37
  110. package/lib/browser/widget/inline-stream-diff/live-preview.component.js.map +1 -1
  111. package/lib/browser/widget/inline-stream-diff/live-preview.decoration.d.ts +11 -7
  112. package/lib/browser/widget/inline-stream-diff/live-preview.decoration.d.ts.map +1 -1
  113. package/lib/browser/widget/inline-stream-diff/live-preview.decoration.js +77 -33
  114. package/lib/browser/widget/inline-stream-diff/live-preview.decoration.js.map +1 -1
  115. package/lib/common/utils.js +2 -2
  116. package/lib/common/utils.js.map +1 -1
  117. package/package.json +21 -21
  118. package/src/browser/ai-core.contextkeys.ts +0 -3
  119. package/src/browser/ai-core.contribution.ts +17 -68
  120. package/src/browser/components/ChatMarkdown.tsx +1 -1
  121. package/src/browser/components/WelcomeMsg.tsx +1 -1
  122. package/src/browser/contrib/intelligent-completions/index.ts +4 -16
  123. package/src/browser/contrib/intelligent-completions/intelligent-completions.contribution.ts +8 -29
  124. package/src/browser/contrib/intelligent-completions/intelligent-completions.controller.ts +55 -86
  125. package/src/browser/contrib/intelligent-completions/source/base.ts +7 -28
  126. package/src/browser/contrib/intelligent-completions/source/line-change.source.ts +22 -129
  127. package/src/browser/contrib/intelligent-completions/source/lint-error.source.ts +31 -19
  128. package/src/browser/contrib/terminal/component/terminal-command-suggest-controller.tsx +1 -1
  129. package/src/browser/index.ts +2 -2
  130. package/src/browser/languages/tree-sitter/wasm-manager.ts +2 -12
  131. package/src/browser/layout/ai-layout.tsx +2 -5
  132. package/src/browser/layout/layout.module.less +9 -9
  133. package/src/browser/layout/tabbar.view.tsx +8 -10
  134. package/src/browser/model/enhanceDecorationsCollection.ts +77 -62
  135. package/src/browser/model/styles.module.less +7 -0
  136. package/src/browser/preferences/schema.ts +0 -4
  137. package/src/browser/types.ts +3 -5
  138. package/src/browser/widget/inline-chat/inline-chat-editor.controller.ts +64 -29
  139. package/src/browser/widget/inline-chat/inline-chat.feature.registry.ts +90 -23
  140. package/src/browser/widget/inline-chat/inline-chat.service.ts +17 -2
  141. package/src/browser/widget/inline-chat/inline-content-widget.tsx +69 -14
  142. package/src/browser/widget/inline-diff/inline-diff-previewer.ts +32 -87
  143. package/src/browser/widget/inline-diff/inline-diff.controller.ts +114 -90
  144. package/src/browser/widget/inline-hint/inline-hint.controller.ts +7 -1
  145. package/src/browser/widget/inline-input/inline-input-widget.tsx +12 -34
  146. package/src/browser/widget/inline-input/inline-input.controller.ts +242 -454
  147. package/src/browser/widget/inline-input/inline-input.module.less +0 -4
  148. package/src/browser/widget/inline-input/inline-input.service.ts +13 -92
  149. package/src/browser/widget/inline-stream-diff/inline-stream-diff.handler.tsx +67 -54
  150. package/src/browser/widget/inline-stream-diff/live-preview.component.tsx +6 -45
  151. package/src/browser/widget/inline-stream-diff/live-preview.decoration.tsx +112 -40
  152. package/src/common/utils.ts +2 -2
  153. package/lib/browser/contrib/intelligent-completions/source/typing.source.d.ts +0 -9
  154. package/lib/browser/contrib/intelligent-completions/source/typing.source.d.ts.map +0 -1
  155. package/lib/browser/contrib/intelligent-completions/source/typing.source.js +0 -36
  156. package/lib/browser/contrib/intelligent-completions/source/typing.source.js.map +0 -1
  157. package/lib/browser/widget/inline-input/model.d.ts +0 -34
  158. package/lib/browser/widget/inline-input/model.d.ts.map +0 -1
  159. package/lib/browser/widget/inline-input/model.js +0 -63
  160. package/lib/browser/widget/inline-input/model.js.map +0 -1
  161. package/src/browser/contrib/intelligent-completions/source/typing.source.ts +0 -34
  162. package/src/browser/widget/inline-input/model.ts +0 -74
@@ -3,7 +3,6 @@ import { Disposable, ErrorResponse, IDisposable, ReplyResponse } from '@opensumi
3
3
  import { EOL, ICodeEditor, IPosition, ITextModel, Position, Selection } from '@opensumi/ide-monaco';
4
4
  import { ContentWidgetPositionPreference } from '@opensumi/ide-monaco/lib/browser/monaco-exports/editor';
5
5
  import { empty, getLeadingWhitespace } from '@opensumi/ide-utils/lib/strings';
6
- import { LineRange } from '@opensumi/monaco-editor-core/esm/vs/editor/common/core/lineRange';
7
6
  import { DefaultEndOfLine } from '@opensumi/monaco-editor-core/esm/vs/editor/common/model';
8
7
  import { createTextBuffer } from '@opensumi/monaco-editor-core/esm/vs/editor/common/model/textModel';
9
8
  import { ModelService } from '@opensumi/monaco-editor-core/esm/vs/editor/common/services/modelService';
@@ -44,13 +43,10 @@ export abstract class BaseInlineDiffPreviewer<N extends IInlineDiffPreviewerNode
44
43
  protected inlineContentWidget: AIInlineContentWidget | null = null;
45
44
  protected selection: Selection;
46
45
  protected model: ITextModel;
47
- public modelId: string;
48
46
 
49
47
  constructor(protected readonly monacoEditor: ICodeEditor) {
50
48
  super();
51
49
  this.model = this.monacoEditor.getModel()!;
52
- this.modelId = this.model.id;
53
-
54
50
  this.addDispose(
55
51
  Disposable.create(() => {
56
52
  if (this.inlineContentWidget) {
@@ -110,7 +106,11 @@ export abstract class BaseInlineDiffPreviewer<N extends IInlineDiffPreviewerNode
110
106
  return this.node;
111
107
  }
112
108
 
113
- public mountWidget(contentWidget: AIInlineContentWidget): void {
109
+ public createNodeSnapshot(): N | undefined {
110
+ return this.node;
111
+ }
112
+
113
+ public mount(contentWidget: AIInlineContentWidget): void {
114
114
  this.inlineContentWidget = contentWidget;
115
115
  }
116
116
 
@@ -156,25 +156,20 @@ export abstract class BaseInlineDiffPreviewer<N extends IInlineDiffPreviewerNode
156
156
  setValue(content: string): void {
157
157
  // do nothing
158
158
  }
159
-
160
159
  getValue(): string {
161
160
  // do nothing
162
161
  return '';
163
162
  }
164
-
165
163
  getOriginValue(): string {
166
164
  // do nothing
167
165
  return '';
168
166
  }
169
-
170
167
  onError(error: ErrorResponse): void {
171
168
  // do nothing
172
169
  }
173
-
174
170
  onAbort(): void {
175
171
  // do nothing
176
172
  }
177
-
178
173
  onEnd(): void {
179
174
  // do nothing
180
175
  }
@@ -183,30 +178,6 @@ export abstract class BaseInlineDiffPreviewer<N extends IInlineDiffPreviewerNode
183
178
  // do nothing
184
179
  }
185
180
 
186
- /**
187
- * 会新建一个渲染层的实例
188
- * 或重新赋值渲染层的数据
189
- * 适用于首次渲染
190
- */
191
- render(): void {
192
- // do nothing
193
- }
194
-
195
- /**
196
- * 仅隐藏渲染层,而不销毁实例
197
- */
198
- hide(): void {
199
- // do nothing
200
- }
201
-
202
- /**
203
- * 恢复渲染层
204
- * 适用于非首次渲染
205
- */
206
- resume(): void {
207
- // do nothing
208
- }
209
-
210
181
  isModel(uri: string): boolean {
211
182
  return this.model.uri.toString() === uri;
212
183
  }
@@ -228,37 +199,30 @@ export class SideBySideInlineDiffWidget extends BaseInlineDiffPreviewer<InlineDi
228
199
  this.addDispose(widget);
229
200
  return widget;
230
201
  }
231
-
232
- mountWidget(contentWidget: AIInlineContentWidget): void {
233
- super.mountWidget(contentWidget);
202
+ mount(contentWidget: AIInlineContentWidget): void {
203
+ super.mount(contentWidget);
234
204
  contentWidget.addDispose(this);
235
205
  }
236
-
237
206
  getPosition(): IPosition {
238
207
  return Position.lift({ lineNumber: this.selection.endLineNumber + 1, column: 1 });
239
208
  }
240
-
241
209
  layout(): void {
242
210
  this.inlineContentWidget?.setPositionPreference([ContentWidgetPositionPreference.BELOW]);
243
211
  super.layout();
244
212
  }
245
-
246
213
  onReady(exec: () => void): IDisposable {
247
214
  if (this.node) {
248
215
  return this.node!.onReady(exec.bind(this));
249
216
  }
250
217
  return Disposable.NULL;
251
218
  }
252
-
253
219
  show(line: number, heightInLines: number): void {
254
220
  this.node?.showByLine(line, heightInLines);
255
221
  }
256
-
257
222
  setValue(content: string): void {
258
223
  const modifiedModel = this.node?.getModifiedModel();
259
224
  modifiedModel?.setValue(this.formatIndentation(content));
260
225
  }
261
-
262
226
  getValue(): string {
263
227
  const model = this.node?.getModifiedModel();
264
228
  return model!.getValue();
@@ -276,12 +240,10 @@ export class SideBySideInlineDiffWidget extends BaseInlineDiffPreviewer<InlineDi
276
240
  this.model.pushStackElement();
277
241
  }
278
242
  }
279
-
280
243
  onLineCount(event: (count: number) => void): Disposable {
281
244
  this.node?.onMaxLineCount(event.bind(this));
282
245
  return this;
283
246
  }
284
-
285
247
  onData(data: ReplyResponse): void {
286
248
  const { message } = data;
287
249
 
@@ -296,15 +258,12 @@ export class SideBySideInlineDiffWidget extends BaseInlineDiffPreviewer<InlineDi
296
258
  disposable.dispose();
297
259
  this.node?.layout();
298
260
  }
299
-
300
261
  onError(error: ErrorResponse): void {
301
262
  this.node?.layout();
302
263
  }
303
-
304
264
  onAbort(): void {
305
265
  this.node?.layout();
306
266
  }
307
-
308
267
  onEnd(): void {
309
268
  this.node?.layout();
310
269
  }
@@ -337,6 +296,30 @@ export class LiveInlineDiffPreviewer extends BaseInlineDiffPreviewer<InlineStrea
337
296
  this.listenNode(node);
338
297
  return node;
339
298
  }
299
+ attachNode(node: InlineStreamDiffHandler): void {
300
+ this.node?.dispose();
301
+ this.node = node;
302
+
303
+ if (node) {
304
+ const snapshot = node.currentSnapshotStore;
305
+ if (snapshot) {
306
+ this.node.restoreDecorationSnapshot(snapshot.decorationSnapshotData);
307
+ this.listenNode(node);
308
+ }
309
+ }
310
+ }
311
+ public createNodeSnapshot(): InlineStreamDiffHandler | undefined {
312
+ if (!this.node) {
313
+ return this.createNode();
314
+ }
315
+
316
+ // 拿前一个 node 的快照信息
317
+ const snapshot = this.node.createSnapshot();
318
+ // 创建新的实例
319
+ const node = this.injector.get(InlineStreamDiffHandler, [this.monacoEditor]);
320
+ node.restoreSnapshot(snapshot);
321
+ return node;
322
+ }
340
323
 
341
324
  getPosition(): IPosition {
342
325
  const zone = this.node?.getZone();
@@ -345,7 +328,6 @@ export class LiveInlineDiffPreviewer extends BaseInlineDiffPreviewer<InlineStrea
345
328
  }
346
329
  return Position.lift({ lineNumber: 1, column: 1 });
347
330
  }
348
-
349
331
  handleAction(action: EResultKind): void {
350
332
  switch (action) {
351
333
  case EResultKind.ACCEPT:
@@ -361,11 +343,9 @@ export class LiveInlineDiffPreviewer extends BaseInlineDiffPreviewer<InlineStrea
361
343
  break;
362
344
  }
363
345
  }
364
-
365
346
  onLineCount() {
366
347
  return Disposable.NULL;
367
348
  }
368
-
369
349
  layout(): void {
370
350
  this.inlineContentWidget?.setPositionPreference([
371
351
  ContentWidgetPositionPreference.ABOVE,
@@ -385,52 +365,17 @@ export class LiveInlineDiffPreviewer extends BaseInlineDiffPreviewer<InlineStrea
385
365
  const firstRemovedWidgetLineNumber = firstRemovedWidget.getLastPosition()?.lineNumber;
386
366
  if (firstRemovedWidgetLineNumber <= lineNumber) {
387
367
  const lineHeight = this.inlineContentWidget.getLineHeight();
388
- const len = firstRemovedWidget.height + 1;
368
+ const len = firstRemovedWidget.height;
389
369
  this.inlineContentWidget.setOffsetTop(-lineHeight * len - 4);
390
- } else {
391
- this.inlineContentWidget.setOffsetTop(0);
392
370
  }
393
371
  }
394
- } else {
395
- this.inlineContentWidget.setOffsetTop(0);
396
372
  }
397
373
  }
398
374
  }
399
-
400
- render(): void {
401
- this.inlineContentWidget?.show();
402
- this.node?.rateRenderEditController();
403
- }
404
-
405
- hide(): void {
406
- this.inlineContentWidget?.hide();
407
- this.node?.hide();
408
- }
409
-
410
- resume(): void {
411
- this.inlineContentWidget?.show();
412
- this.node?.resume();
413
- }
414
-
415
375
  onData(data: ReplyResponse): void {
416
376
  const { message } = data;
417
377
  this.node?.addLinesToDiff(this.formatIndentation(message));
418
378
  }
419
-
420
- onAbort(): void {
421
- const diffModel = this.node?.recompute(EComputerMode.default);
422
- if (diffModel) {
423
- /**
424
- * abort 的时候,需要保留当前已经输出的内容
425
- * 同时需要去掉流式过程中的 pending 区域和 activeLine
426
- */
427
- diffModel.activeLine = 0;
428
- diffModel.pendingRange = new LineRange(0, 0);
429
-
430
- this.node?.finallyRender(diffModel);
431
- }
432
- }
433
-
434
379
  onEnd(): void {
435
380
  const diffModel = this.node?.recompute(EComputerMode.legacy);
436
381
  if (diffModel) {
@@ -6,18 +6,12 @@ import {
6
6
  Emitter,
7
7
  Event,
8
8
  IDisposable,
9
+ IEventBus,
9
10
  ReplyResponse,
10
11
  } from '@opensumi/ide-core-common';
12
+ import { EditorGroupCloseEvent } from '@opensumi/ide-editor/lib/browser';
11
13
  import * as monaco from '@opensumi/ide-monaco';
12
14
  import { ICodeEditor } from '@opensumi/ide-monaco';
13
- import {
14
- IObservable,
15
- ISettableObservable,
16
- autorun,
17
- observableFromEvent,
18
- observableValue,
19
- transaction,
20
- } from '@opensumi/ide-monaco/lib/common/observable';
21
15
 
22
16
  import { BaseAIMonacoEditorController } from '../../contrib/base';
23
17
  import { EInlineDiffPreviewMode } from '../../preferences/schema';
@@ -33,8 +27,6 @@ import {
33
27
  } from './inline-diff-previewer';
34
28
  import { InlineDiffWidget } from './inline-diff-widget';
35
29
 
36
- type IInlineDiffPreviewer = BaseInlineDiffPreviewer<InlineDiffWidget | InlineStreamDiffHandler>;
37
-
38
30
  export class InlineDiffController extends BaseAIMonacoEditorController {
39
31
  public static readonly ID = 'editor.contrib.ai.inline.diff';
40
32
 
@@ -46,68 +38,106 @@ export class InlineDiffController extends BaseAIMonacoEditorController {
46
38
  return this.injector.get(PreferenceService);
47
39
  }
48
40
 
41
+ private get eventBus(): IEventBus {
42
+ return this.injector.get(IEventBus);
43
+ }
44
+
49
45
  private readonly _onMaxLineCount = new Emitter<number>();
50
46
  public readonly onMaxLineCount: Event<number> = this._onMaxLineCount.event;
51
47
 
52
- private previewerStore: Map<string, IInlineDiffPreviewer>;
53
- private currentPreviewer: ISettableObservable<IInlineDiffPreviewer | undefined>;
54
- private modelChangeObs: IObservable<monaco.editor.ITextModel, unknown>;
48
+ private previewer: BaseInlineDiffPreviewer<InlineDiffWidget | InlineStreamDiffHandler> | undefined;
49
+ private _previewerNodeStore = new Map<string, InlineStreamDiffHandler | null>();
55
50
 
56
51
  mount(): IDisposable {
57
- this.previewerStore = new Map();
58
- this.currentPreviewer = observableValue(this, undefined);
59
- this.modelChangeObs = observableFromEvent<monaco.editor.ITextModel>(
60
- this,
61
- this.monacoEditor.onDidChangeModel,
62
- () => this.monacoEditor.getModel()!,
63
- );
64
-
65
52
  this.featureDisposable.addDispose(
66
- autorun((reader) => {
67
- const model = this.modelChangeObs.read(reader);
68
- if (!model) {
69
- return;
70
- }
53
+ this.eventBus.on(EditorGroupCloseEvent, (e: EditorGroupCloseEvent) => {
54
+ const uriString = e.payload.resource.uri.toString();
55
+ const node = this.getStoredState(uriString);
71
56
 
72
- /**
73
- * 切换到其他 model 且 previewer 未卸载时
74
- * 保留 previewer 的实例,仅卸载 previewer 的渲染层
75
- */
76
- const id = model.id;
77
- const previewer = this.currentPreviewer.get();
78
- if (previewer && previewer.modelId !== id && !previewer.disposed) {
79
- previewer.hide();
57
+ if (node && node.previewerOptions.disposeWhenEditorClosed) {
58
+ this.destroyPreviewer(uriString);
80
59
  }
81
-
82
- const storedPreview = this.previewerStore.get(model.id);
83
- transaction((tx) => {
84
- if (storedPreview && storedPreview.modelId === id) {
85
- this.currentPreviewer.set(storedPreview, tx);
86
- storedPreview.resume();
87
- } else {
88
- this.currentPreviewer.set(undefined, tx);
89
- }
90
- });
91
60
  }),
92
61
  );
93
62
 
63
+ this.registerInlineDiffFeature(this.monacoEditor);
64
+
94
65
  return this.featureDisposable;
95
66
  }
96
67
 
97
- getPreviewer(): IInlineDiffPreviewer | undefined {
98
- return this.currentPreviewer.get();
68
+ storeState(key: string) {
69
+ if (!this.previewer) {
70
+ return;
71
+ }
72
+
73
+ // 存储的是快照
74
+ const node = this.previewer.createNodeSnapshot();
75
+ if (node) {
76
+ this._previewerNodeStore.set(key, node as InlineStreamDiffHandler);
77
+ }
99
78
  }
100
79
 
101
- private renderDiff(previewer: IInlineDiffPreviewer, data: ReplyResponse) {
102
- if (!previewer) {
80
+ tryRestoreState(monacoEditor: monaco.ICodeEditor, key: string) {
81
+ const node = this.getStoredState(key);
82
+ if (!node) {
103
83
  return;
104
84
  }
105
85
 
106
- previewer.onData(data);
86
+ if (node.disposed) {
87
+ this.destroyPreviewer(key);
88
+ return;
89
+ }
90
+
91
+ return this.restoreState(monacoEditor, node);
92
+ }
93
+
94
+ restoreState(monacoEditor: monaco.ICodeEditor, node: InlineStreamDiffHandler) {
95
+ const uri = monacoEditor.getModel()?.uri;
96
+
97
+ if (uri) {
98
+ this.previewer = this.injector.get(LiveInlineDiffPreviewer, [monacoEditor]);
99
+ this.previewer.attachNode(node);
100
+ this.listenPreviewer(this.previewer);
101
+
102
+ const dispose = this.previewer.onDispose(() => {
103
+ this.destroyPreviewer();
104
+ dispose.dispose();
105
+ });
106
+ }
107
+ }
108
+
109
+ registerInlineDiffFeature(monacoEditor: monaco.ICodeEditor): void {
110
+ const model = monacoEditor.getModel();
111
+
112
+ this.featureDisposable.addDispose(
113
+ monacoEditor.onWillChangeModel((e) => {
114
+ if (!e.oldModelUrl) {
115
+ return;
116
+ }
117
+
118
+ const urlString = e.oldModelUrl.toString();
119
+ this.storeState(urlString);
120
+
121
+ this.destroyPreviewer();
122
+ }),
123
+ );
124
+
125
+ this.featureDisposable.addDispose(
126
+ monacoEditor.onDidChangeModel((e) => {
127
+ if (!e.newModelUrl) {
128
+ return;
129
+ }
130
+ this.tryRestoreState(monacoEditor, e.newModelUrl.toString());
131
+ }),
132
+ );
107
133
 
108
- // 仅在当前 model 中进行流式渲染
109
- if (this.modelChangeObs.get()?.id === previewer.modelId) {
110
- previewer.render();
134
+ if (model) {
135
+ this.featureDisposable.addDispose(
136
+ model.onWillDispose(() => {
137
+ const uriString = model.uri.toString();
138
+ this.destroyPreviewer(uriString);
139
+ }),
140
+ );
111
141
  }
112
142
  }
113
143
 
@@ -124,10 +154,6 @@ export class InlineDiffController extends BaseAIMonacoEditorController {
124
154
  const disposable = new Disposable();
125
155
 
126
156
  const previewer = this.createDiffPreviewer(monacoEditor, crossSelection, options.previewerOptions);
127
- transaction((tx) => {
128
- this.currentPreviewer.set(previewer, tx);
129
- this.previewerStore.set(previewer.modelId, previewer);
130
- });
131
157
 
132
158
  const onFinish = () => {
133
159
  previewer.layout();
@@ -142,7 +168,7 @@ export class InlineDiffController extends BaseAIMonacoEditorController {
142
168
  disposable.addDispose([
143
169
  controller.onData((data) => {
144
170
  if (ReplyResponse.is(data)) {
145
- this.renderDiff(previewer, data);
171
+ previewer.onData(data);
146
172
  }
147
173
  }),
148
174
  controller.onError((error) => {
@@ -177,61 +203,59 @@ export class InlineDiffController extends BaseAIMonacoEditorController {
177
203
  EInlineDiffPreviewMode.inlineLive,
178
204
  );
179
205
 
180
- let previewer: IInlineDiffPreviewer;
206
+ this.destroyPreviewer();
181
207
 
182
208
  if (inlineDiffMode === EInlineDiffPreviewMode.sideBySide) {
183
- previewer = this.injector.get(SideBySideInlineDiffWidget, [monacoEditor]);
209
+ this.previewer = this.injector.get(SideBySideInlineDiffWidget, [monacoEditor]);
184
210
  } else {
185
- previewer = this.injector.get(LiveInlineDiffPreviewer, [monacoEditor]);
211
+ this.previewer = this.injector.get(LiveInlineDiffPreviewer, [monacoEditor]);
186
212
  }
187
213
 
188
- previewer.create(selection, options);
189
- previewer.show(selection.startLineNumber - 1, selection.endLineNumber - selection.startLineNumber + 2);
214
+ this.previewer.create(selection, options);
215
+ this.previewer.show(selection.startLineNumber - 1, selection.endLineNumber - selection.startLineNumber + 2);
190
216
 
191
- previewer.addDispose(previewer.onLineCount((lineCount) => this._onMaxLineCount.fire(lineCount)));
217
+ this.listenPreviewer(this.previewer);
192
218
 
193
- previewer.addDispose(
194
- Disposable.create(() => {
195
- this.previewerStore.delete(previewer.modelId);
196
- }),
197
- );
198
-
199
- return previewer;
219
+ return this.previewer;
200
220
  }
201
221
 
202
- handleAction(action: EResultKind): void {
203
- const previewer = this.getPreviewer();
222
+ private listenPreviewer(previewer: BaseInlineDiffPreviewer<InlineDiffWidget | InlineStreamDiffHandler> | undefined) {
204
223
  if (!previewer) {
205
224
  return;
206
225
  }
207
226
 
208
- previewer.handleAction(action);
227
+ previewer.addDispose(previewer.onLineCount((lineCount) => this._onMaxLineCount.fire(lineCount)));
209
228
  }
210
229
 
211
- getModifyContent() {
212
- const previewer = this.getPreviewer();
213
- if (!previewer) {
214
- return;
215
- }
230
+ getPreviewer(): BaseInlineDiffPreviewer<InlineDiffWidget | InlineStreamDiffHandler> | undefined {
231
+ return this.previewer;
232
+ }
216
233
 
217
- return previewer.getValue();
234
+ getStoredState(uri: string) {
235
+ return this._previewerNodeStore.get(uri);
218
236
  }
219
237
 
220
- getOriginContent() {
221
- const previewer = this.getPreviewer();
222
- if (!previewer) {
223
- return;
224
- }
238
+ handleAction(action: EResultKind): void {
239
+ this.previewer?.handleAction(action);
240
+ }
241
+
242
+ getModifyContent() {
243
+ return this.previewer?.getValue();
244
+ }
225
245
 
226
- return previewer.getOriginValue();
246
+ getOriginContent() {
247
+ return this.previewer?.getOriginValue();
227
248
  }
228
249
 
229
- revealFirstDiff() {
230
- const previewer = this.getPreviewer();
231
- if (!previewer) {
232
- return;
250
+ destroyPreviewer(uriString?: string) {
251
+ this.previewer?.dispose();
252
+ this.previewer = undefined;
253
+ if (uriString) {
254
+ this._previewerNodeStore.delete(uriString);
233
255
  }
256
+ }
234
257
 
235
- previewer.revealFirstDiff();
258
+ revealFirstDiff() {
259
+ this.previewer?.revealFirstDiff();
236
260
  }
237
261
  }
@@ -1,12 +1,13 @@
1
1
  import throttle from 'lodash/throttle';
2
2
 
3
3
  import { Disposable, IDisposable } from '@opensumi/ide-core-common';
4
- import * as monaco from '@opensumi/ide-monaco';
5
4
  import { ICodeEditor } from '@opensumi/ide-monaco';
5
+ import * as monaco from '@opensumi/ide-monaco';
6
6
 
7
7
  import { AINativeContextKey } from '../../ai-core.contextkeys';
8
8
  import { BaseAIMonacoEditorController } from '../../contrib/base';
9
9
  import { AICompletionsService } from '../../contrib/inline-completions/service/ai-completions.service';
10
+ import { InlineInputChatService } from '../inline-input/inline-input.service';
10
11
  import { InlineInputPreviewDecorationID } from '../internal.type';
11
12
 
12
13
  import { InlineHintLineDecoration } from './inline-hint-line-widget';
@@ -22,6 +23,10 @@ export class InlineHintController extends BaseAIMonacoEditorController {
22
23
  return this.injector.get(AICompletionsService);
23
24
  }
24
25
 
26
+ private get inlineInputChatService(): InlineInputChatService {
27
+ return this.injector.get(InlineInputChatService);
28
+ }
29
+
25
30
  mount(): IDisposable {
26
31
  return this.registerHintLineFeature(this.monacoEditor);
27
32
  }
@@ -54,6 +59,7 @@ export class InlineHintController extends BaseAIMonacoEditorController {
54
59
  if (!lineContent?.trim()) {
55
60
  inlineHintLineDecoration.show(position);
56
61
  }
62
+ this.inlineInputChatService.setCurrentVisiblePosition(position);
57
63
 
58
64
  aiNativeContextKey.inlineHintWidgetIsVisible.set(true);
59
65
 
@@ -1,9 +1,8 @@
1
1
  import React, { ReactNode, useCallback, useEffect, useMemo, useState } from 'react';
2
2
 
3
- import { Injectable } from '@opensumi/di';
4
- import { AINativeConfigService, useInjectable } from '@opensumi/ide-core-browser';
3
+ import { Autowired, Injectable } from '@opensumi/di';
5
4
  import { AIAction, InteractiveInput } from '@opensumi/ide-core-browser/lib/components/ai-native/index';
6
- import { AIInlineInputChatContentWidgetId, Disposable, Emitter, Event, localize } from '@opensumi/ide-core-common';
5
+ import { AIInlineInputChatContentWidgetId, Disposable, Event, localize } from '@opensumi/ide-core-common';
7
6
  import { ContentWidgetPositionPreference } from '@opensumi/ide-monaco/lib/browser/monaco-exports/editor';
8
7
 
9
8
  import { InlineResultAction } from '../inline-actions/result-items/index';
@@ -11,24 +10,19 @@ import { EInlineChatStatus, EResultKind } from '../inline-chat/inline-chat.servi
11
10
  import { AIInlineContentWidget } from '../inline-chat/inline-content-widget';
12
11
 
13
12
  import styles from './inline-input.module.less';
14
-
15
- import type { ICodeEditor as IMonacoCodeEditor } from '@opensumi/ide-monaco';
13
+ import { InlineInputChatService } from './inline-input.service';
16
14
 
17
15
  interface IInlineInputWidgetRenderProps {
18
- defaultValue?: string;
19
16
  onLayoutChange: (height: number) => void;
20
17
  onClose?: () => void;
21
18
  onInteractiveInputSend?: (value: string) => void;
22
19
  onChatStatus: Event<EInlineChatStatus>;
23
20
  onResultClick: (k: EResultKind) => void;
24
- onValueChange?: (value: string) => void;
25
21
  }
26
22
 
27
23
  const InlineInputWidgetRender = (props: IInlineInputWidgetRenderProps) => {
28
- const { defaultValue, onClose, onInteractiveInputSend, onLayoutChange, onChatStatus, onResultClick, onValueChange } =
29
- props;
24
+ const { onClose, onInteractiveInputSend, onLayoutChange, onChatStatus, onResultClick } = props;
30
25
  const [status, setStatus] = useState<EInlineChatStatus>(EInlineChatStatus.READY);
31
- const aiNativeConfigService = useInjectable<AINativeConfigService>(AINativeConfigService);
32
26
 
33
27
  useEffect(() => {
34
28
  const dis = new Disposable();
@@ -70,12 +64,10 @@ const InlineInputWidgetRender = (props: IInlineInputWidgetRenderProps) => {
70
64
  customOperationRender={
71
65
  <InteractiveInput
72
66
  autoFocus
73
- defaultValue={defaultValue}
74
- onValueChange={onValueChange}
75
67
  onHeightChange={(height) => onLayoutChange(height)}
76
68
  size='small'
77
69
  placeholder={localize('aiNative.inline.chat.input.placeholder.default')}
78
- width={aiNativeConfigService.inlineChat.inputWidth}
70
+ width={320}
79
71
  disabled={isLoading}
80
72
  onSend={handleInteractiveInputSend}
81
73
  />
@@ -85,26 +77,16 @@ const InlineInputWidgetRender = (props: IInlineInputWidgetRenderProps) => {
85
77
  };
86
78
 
87
79
  @Injectable({ multiple: true })
88
- export class InlineInputWidget extends AIInlineContentWidget {
80
+ export class InlineInputChatWidget extends AIInlineContentWidget {
81
+ @Autowired(InlineInputChatService)
82
+ private inlineInputChatService: InlineInputChatService;
83
+
89
84
  allowEditorOverflow = true;
90
85
  positionPreference = [ContentWidgetPositionPreference.ABOVE];
91
86
 
92
- protected readonly _onSend = new Emitter<string>();
93
- public readonly onSend = this._onSend.event;
94
-
95
- protected readonly _onClose = new Emitter<void>();
96
- public readonly onClose = this._onClose.event;
97
-
98
- protected readonly _onValueChange = new Emitter<string>();
99
- public readonly onValueChange = this._onValueChange.event;
100
-
101
- constructor(protected readonly editor: IMonacoCodeEditor, protected readonly defaultValue?: string) {
102
- super(editor);
103
- }
104
-
105
87
  override dispose(): void {
106
88
  super.dispose();
107
- this.inlineInputService.hide();
89
+ this.inlineInputChatService.hide();
108
90
  }
109
91
 
110
92
  override id(): string {
@@ -115,18 +97,14 @@ export class InlineInputWidget extends AIInlineContentWidget {
115
97
  return (
116
98
  <div className={styles.input_wrapper}>
117
99
  <InlineInputWidgetRender
118
- defaultValue={this.defaultValue}
119
- onClose={() => this._onClose.fire()}
100
+ onClose={() => this.dispose()}
120
101
  onChatStatus={this.onStatusChange.bind(this)}
121
102
  onLayoutChange={() => {
122
103
  this.editor.layoutContentWidget(this);
123
104
  }}
124
- onValueChange={(value) => {
125
- this._onValueChange.fire(value);
126
- }}
127
105
  onInteractiveInputSend={(value) => {
128
106
  this.launchChatStatus(EInlineChatStatus.THINKING);
129
- this._onSend.fire(value);
107
+ this._onInteractiveInputValue.fire(value);
130
108
  }}
131
109
  onResultClick={(k: EResultKind) => {
132
110
  this._onResultClick.fire(k);