@opensumi/ide-ai-native 3.7.1-next-1739774311.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
@@ -27,7 +27,6 @@ import {
27
27
  } from '@opensumi/ide-core-browser';
28
28
  import {
29
29
  AI_CHAT_VISIBLE,
30
- AI_INLINE_CHAT_INTERACTIVE_INPUT_CANCEL,
31
30
  AI_INLINE_CHAT_INTERACTIVE_INPUT_VISIBLE,
32
31
  AI_INLINE_CHAT_VISIBLE,
33
32
  AI_INLINE_COMPLETION_REPORTER,
@@ -38,7 +37,6 @@ import {
38
37
  InlineChatIsVisible,
39
38
  InlineDiffPartialEditsIsVisible,
40
39
  InlineHintWidgetIsVisible,
41
- InlineInputWidgetIsStreaming,
42
40
  InlineInputWidgetIsVisible,
43
41
  } from '@opensumi/ide-core-browser/lib/contextkey/ai-native';
44
42
  import { DesignLayoutConfig } from '@opensumi/ide-core-browser/lib/layout/constants';
@@ -58,9 +56,8 @@ import {
58
56
  runWhenIdle,
59
57
  } from '@opensumi/ide-core-common';
60
58
  import { DESIGN_MENU_BAR_RIGHT } from '@opensumi/ide-design';
61
- import { IEditor, WorkbenchEditorService } from '@opensumi/ide-editor';
59
+ import { IEditor } from '@opensumi/ide-editor';
62
60
  import { BrowserEditorContribution, IEditorFeatureRegistry } from '@opensumi/ide-editor/lib/browser';
63
- import { WorkbenchEditorServiceImpl } from '@opensumi/ide-editor/lib/browser/workbench-editor.service';
64
61
  import { IMainLayoutService } from '@opensumi/ide-main-layout';
65
62
  import { ISettingRegistry, SettingContribution } from '@opensumi/ide-preferences';
66
63
  import { EditorContributionInstantiation } from '@opensumi/monaco-editor-core/esm/vs/editor/browser/editorExtensions';
@@ -104,11 +101,11 @@ import {
104
101
  } from './types';
105
102
  import { InlineChatEditorController } from './widget/inline-chat/inline-chat-editor.controller';
106
103
  import { InlineChatFeatureRegistry } from './widget/inline-chat/inline-chat.feature.registry';
107
- import { InlineChatService } from './widget/inline-chat/inline-chat.service';
104
+ import { AIInlineChatService } from './widget/inline-chat/inline-chat.service';
108
105
  import { InlineDiffController } from './widget/inline-diff/inline-diff.controller';
109
106
  import { InlineHintController } from './widget/inline-hint/inline-hint.controller';
110
107
  import { InlineInputController } from './widget/inline-input/inline-input.controller';
111
- import { InlineInputService } from './widget/inline-input/inline-input.service';
108
+ import { InlineInputChatService } from './widget/inline-input/inline-input.service';
112
109
  import { InlineStreamDiffService } from './widget/inline-stream-diff/inline-stream-diff.service';
113
110
  import { SumiLightBulbWidget } from './widget/light-bulb';
114
111
 
@@ -194,10 +191,10 @@ export class AINativeBrowserContribution
194
191
  private readonly chatProxyService: ChatProxyService;
195
192
 
196
193
  @Autowired(IAIInlineChatService)
197
- private readonly aiInlineChatService: InlineChatService;
194
+ private readonly aiInlineChatService: AIInlineChatService;
198
195
 
199
- @Autowired(InlineInputService)
200
- private readonly inlineInputService: InlineInputService;
196
+ @Autowired(InlineInputChatService)
197
+ private readonly inlineInputChatService: InlineInputChatService;
201
198
 
202
199
  @Autowired(InlineStreamDiffService)
203
200
  private readonly inlineStreamDiffService: InlineStreamDiffService;
@@ -208,9 +205,6 @@ export class AINativeBrowserContribution
208
205
  @Autowired(CodeActionSingleHandler)
209
206
  private readonly codeActionSingleHandler: CodeActionSingleHandler;
210
207
 
211
- @Autowired(WorkbenchEditorService)
212
- private readonly workbenchEditorService: WorkbenchEditorServiceImpl;
213
-
214
208
  constructor() {
215
209
  this.registerFeature();
216
210
  }
@@ -243,7 +237,7 @@ export class AINativeBrowserContribution
243
237
  EditorContributionInstantiation.BeforeFirstInteraction,
244
238
  );
245
239
 
246
- if (this.inlineInputService.getInteractiveInputHandler()) {
240
+ if (this.inlineChatFeatureRegistry.getInteractiveInputHandler()) {
247
241
  register(
248
242
  InlineHintController.ID,
249
243
  new SyncDescriptor(InlineHintController, [this.injector]),
@@ -260,7 +254,7 @@ export class AINativeBrowserContribution
260
254
  register(
261
255
  IntelligentCompletionsController.ID,
262
256
  new SyncDescriptor(IntelligentCompletionsController, [this.injector]),
263
- EditorContributionInstantiation.Eager,
257
+ EditorContributionInstantiation.AfterFirstRender,
264
258
  );
265
259
  register(
266
260
  InlineCompletionsController.ID,
@@ -371,10 +365,6 @@ export class AINativeBrowserContribution
371
365
  id: AINativeSettingSectionsId.CodeEditsLineChange,
372
366
  localized: 'preference.ai.native.codeEdits.lineChange',
373
367
  },
374
- {
375
- id: AINativeSettingSectionsId.CodeEditsTyping,
376
- localized: 'preference.ai.native.codeEdits.typing',
377
- },
378
368
  ],
379
369
  });
380
370
  }
@@ -424,48 +414,14 @@ export class AINativeBrowserContribution
424
414
  });
425
415
 
426
416
  commands.registerCommand(AI_INLINE_CHAT_INTERACTIVE_INPUT_VISIBLE, {
427
- execute: async (isVisible: boolean) => {
428
- if (!isVisible) {
429
- this.inlineInputService.hide();
430
- return;
417
+ execute: (isVisible: boolean) => {
418
+ if (isVisible) {
419
+ this.inlineInputChatService.visible();
420
+ } else {
421
+ this.inlineInputChatService.hide();
431
422
  }
432
423
 
433
- // 每次在展示 inline input 的时候,先隐藏 inline chat
434
- this.commandService.executeCommand(AI_INLINE_CHAT_VISIBLE.id, false);
435
-
436
- const editor = this.workbenchEditorService.currentCodeEditor;
437
- if (!editor) {
438
- return;
439
- }
440
-
441
- const position = editor.monacoEditor.getPosition();
442
- if (!position) {
443
- return;
444
- }
445
-
446
- const selection = editor.monacoEditor.getSelection();
447
- const isEmptyLine = position ? editor.monacoEditor.getModel()?.getLineLength(position.lineNumber) === 0 : false;
448
-
449
- if (isEmptyLine) {
450
- this.inlineInputService.visibleByPosition(position);
451
- return;
452
- }
453
-
454
- if (selection && !selection.isEmpty()) {
455
- this.inlineInputService.visibleBySelection(selection);
456
- return;
457
- }
458
-
459
- this.inlineInputService.visibleByNearestCodeBlock(position, editor.monacoEditor);
460
- },
461
- });
462
-
463
- commands.registerCommand(AI_INLINE_CHAT_INTERACTIVE_INPUT_CANCEL, {
464
- execute: () => {
465
- const editor = this.workbenchEditorService.currentCodeEditor;
466
- if (editor) {
467
- InlineInputController.get(editor.monacoEditor)?.cancelToken();
468
- }
424
+ this.aiInlineChatService._onInteractiveInputVisible.fire(isVisible);
469
425
  },
470
426
  });
471
427
 
@@ -556,12 +512,12 @@ export class AINativeBrowserContribution
556
512
  when: `editorFocus && ${InlineChatIsVisible.raw}`,
557
513
  });
558
514
 
559
- if (this.inlineInputService.getInteractiveInputHandler()) {
515
+ if (this.inlineChatFeatureRegistry.getInteractiveInputHandler()) {
560
516
  // 当 Inline Chat (浮动组件)展示时,通过 CMD K 唤起 Inline Input
561
517
  keybindings.registerKeybinding(
562
518
  {
563
519
  command: AI_INLINE_CHAT_INTERACTIVE_INPUT_VISIBLE.id,
564
- keybinding: this.aiNativeConfigService.inlineChat.inputKeybinding,
520
+ keybinding: 'ctrlcmd+k',
565
521
  args: true,
566
522
  priority: 0,
567
523
  when: `editorFocus && (${InlineChatIsVisible.raw} || inlineSuggestionVisible)`,
@@ -576,18 +532,11 @@ export class AINativeBrowserContribution
576
532
  priority: 0,
577
533
  when: `editorFocus && ${InlineInputWidgetIsVisible.raw}`,
578
534
  });
579
- // 当 Inline Input 流式编辑时,通过 ESC 退出
580
- keybindings.registerKeybinding({
581
- command: AI_INLINE_CHAT_INTERACTIVE_INPUT_CANCEL.id,
582
- keybinding: 'esc',
583
- priority: 1,
584
- when: `editorFocus && ${InlineInputWidgetIsStreaming.raw}`,
585
- });
586
535
  // 当出现 CMD K 展示信息时,通过快捷键快速唤起 Inline Input
587
536
  keybindings.registerKeybinding(
588
537
  {
589
538
  command: AI_INLINE_CHAT_INTERACTIVE_INPUT_VISIBLE.id,
590
- keybinding: this.aiNativeConfigService.inlineChat.inputKeybinding,
539
+ keybinding: 'ctrlcmd+k',
591
540
  args: true,
592
541
  priority: 0,
593
542
  when: `editorFocus && ${InlineHintWidgetIsVisible.raw} && ${InlineChatIsVisible.not}`,
@@ -1,5 +1,5 @@
1
1
  import cls from 'classnames';
2
- import React, { useEffect, useRef, useState } from 'react';
2
+ import React, { ReactNode, useEffect, useRef, useState } from 'react';
3
3
 
4
4
  import { MarkdownReactParser, MarkdownReactRenderer } from '@opensumi/ide-components/lib/markdown-react';
5
5
  import { IMarkedOptions, marked } from '@opensumi/ide-components/lib/utils';
@@ -14,7 +14,7 @@ import {
14
14
  import { isMarkdownString } from '@opensumi/monaco-editor-core/esm/vs/base/common/htmlContent';
15
15
 
16
16
  import 'react-chat-elements/dist/main.css';
17
- import { IChatAgentService, ISampleQuestions } from '../../common';
17
+ import { IChatAgentService, IChatReplyFollowup, ISampleQuestions } from '../../common';
18
18
  import { ChatService } from '../chat/chat.api.service';
19
19
  import { ChatFeatureRegistry } from '../chat/chat.feature.registry';
20
20
  import { ChatRenderRegistry } from '../chat/chat.render.registry';
@@ -1,15 +1,9 @@
1
1
  import { Disposable, ECodeEditsSourceTyping } from '@opensumi/ide-core-common';
2
- import { IModelContentChangedEvent, IPosition, IRange, InlineCompletion } from '@opensumi/ide-monaco';
2
+ import { IPosition, IRange, InlineCompletion } from '@opensumi/ide-monaco';
3
3
 
4
4
  import type { ILineChangeData } from './source/line-change.source';
5
5
  import type { ILinterErrorData } from './source/lint-error.source';
6
6
 
7
- /**
8
- * 有效弃用时间(毫秒)
9
- * 在可见的情况下超过 750ms 弃用才算有效数据,否则视为无效数据
10
- */
11
- export const VALID_TIME = 750;
12
-
13
7
  export interface IIntelligentCompletionsResult<T = any> {
14
8
  readonly items: InlineCompletion[];
15
9
  /**
@@ -18,15 +12,9 @@ export interface IIntelligentCompletionsResult<T = any> {
18
12
  extra?: T;
19
13
  }
20
14
 
21
- export interface ICodeEditsContextBean {
22
- typing: ECodeEditsSourceTyping;
23
- position: IPosition;
24
- data: {
25
- [ECodeEditsSourceTyping.LinterErrors]?: ILinterErrorData;
26
- [ECodeEditsSourceTyping.LineChange]?: ILineChangeData;
27
- [ECodeEditsSourceTyping.Typing]?: IModelContentChangedEvent;
28
- };
29
- }
15
+ export type ICodeEditsContextBean =
16
+ | { typing: ECodeEditsSourceTyping.LinterErrors; position: IPosition; data: ILinterErrorData }
17
+ | { typing: ECodeEditsSourceTyping.LineChange; position: IPosition; data: ILineChangeData };
30
18
 
31
19
  export interface ICodeEdit {
32
20
  /**
@@ -1,18 +1,19 @@
1
1
  import { Autowired } from '@opensumi/di';
2
2
  import {
3
- AINativeConfigService,
4
3
  ClientAppContribution,
5
4
  Key,
6
5
  KeybindingContribution,
7
6
  KeybindingRegistry,
8
7
  KeybindingScope,
9
8
  } from '@opensumi/ide-core-browser';
10
- import { AI_CODE_EDITS_COMMANDS } from '@opensumi/ide-core-browser/lib/ai-native/command';
9
+ import {
10
+ AI_MULTI_LINE_COMPLETION_ACCEPT,
11
+ AI_MULTI_LINE_COMPLETION_DISCARD,
12
+ } from '@opensumi/ide-core-browser/lib/ai-native/command';
11
13
  import { MultiLineEditsIsVisible } from '@opensumi/ide-core-browser/lib/contextkey/ai-native';
12
14
  import { CommandContribution, CommandRegistry, Domain } from '@opensumi/ide-core-common';
13
15
  import { WorkbenchEditorService } from '@opensumi/ide-editor';
14
16
  import { WorkbenchEditorServiceImpl } from '@opensumi/ide-editor/lib/browser/workbench-editor.service';
15
- import { transaction } from '@opensumi/ide-monaco/lib/common/observable';
16
17
 
17
18
  import { IntelligentCompletionsController } from './intelligent-completions.controller';
18
19
 
@@ -21,11 +22,8 @@ export class IntelligentCompletionsContribution implements KeybindingContributio
21
22
  @Autowired(WorkbenchEditorService)
22
23
  private readonly workbenchEditorService: WorkbenchEditorServiceImpl;
23
24
 
24
- @Autowired(AINativeConfigService)
25
- private readonly aiNativeConfigService: AINativeConfigService;
26
-
27
25
  registerCommands(commands: CommandRegistry): void {
28
- commands.registerCommand(AI_CODE_EDITS_COMMANDS.DISCARD, {
26
+ commands.registerCommand(AI_MULTI_LINE_COMPLETION_DISCARD, {
29
27
  execute: () => {
30
28
  const editor = this.workbenchEditorService.currentCodeEditor;
31
29
  if (editor) {
@@ -34,7 +32,7 @@ export class IntelligentCompletionsContribution implements KeybindingContributio
34
32
  },
35
33
  });
36
34
 
37
- commands.registerCommand(AI_CODE_EDITS_COMMANDS.ACCEPT, {
35
+ commands.registerCommand(AI_MULTI_LINE_COMPLETION_ACCEPT, {
38
36
  execute: () => {
39
37
  const editor = this.workbenchEditorService.currentCodeEditor;
40
38
  if (editor) {
@@ -42,24 +40,11 @@ export class IntelligentCompletionsContribution implements KeybindingContributio
42
40
  }
43
41
  },
44
42
  });
45
-
46
- commands.registerCommand(AI_CODE_EDITS_COMMANDS.TRIGGER, {
47
- execute: () => {
48
- const editor = this.workbenchEditorService.currentCodeEditor;
49
- if (editor) {
50
- transaction((tx) => {
51
- IntelligentCompletionsController.get(editor.monacoEditor)?.trigger(tx);
52
- });
53
- }
54
- },
55
- });
56
43
  }
57
44
 
58
45
  registerKeybindings(keybindings: KeybindingRegistry): void {
59
- const { codeEdits } = this.aiNativeConfigService;
60
-
61
46
  keybindings.registerKeybinding({
62
- command: AI_CODE_EDITS_COMMANDS.DISCARD.id,
47
+ command: AI_MULTI_LINE_COMPLETION_DISCARD.id,
63
48
  keybinding: Key.ESCAPE.code,
64
49
  when: MultiLineEditsIsVisible.raw,
65
50
  priority: 100,
@@ -67,17 +52,11 @@ export class IntelligentCompletionsContribution implements KeybindingContributio
67
52
 
68
53
  keybindings.registerKeybinding(
69
54
  {
70
- command: AI_CODE_EDITS_COMMANDS.ACCEPT.id,
55
+ command: AI_MULTI_LINE_COMPLETION_ACCEPT.id,
71
56
  keybinding: Key.TAB.code,
72
57
  when: MultiLineEditsIsVisible.raw,
73
58
  },
74
59
  KeybindingScope.USER,
75
60
  );
76
-
77
- keybindings.registerKeybinding({
78
- command: AI_CODE_EDITS_COMMANDS.TRIGGER.id,
79
- keybinding: codeEdits.triggerKeybinding,
80
- when: 'editorFocus',
81
- });
82
61
  }
83
62
  }
@@ -1,10 +1,4 @@
1
- import {
2
- ContextKeyChangeEvent,
3
- Key,
4
- KeybindingRegistry,
5
- KeybindingScope,
6
- PreferenceService,
7
- } from '@opensumi/ide-core-browser';
1
+ import { Key, KeybindingRegistry, KeybindingScope, PreferenceService } from '@opensumi/ide-core-browser';
8
2
  import { MultiLineEditsIsVisible } from '@opensumi/ide-core-browser/lib/contextkey/ai-native';
9
3
  import {
10
4
  AINativeSettingSectionsId,
@@ -19,16 +13,10 @@ import {
19
13
  import { Emitter, ICodeEditor, ICursorPositionChangedEvent, IRange, ITextModel, Range } from '@opensumi/ide-monaco';
20
14
  import {
21
15
  IObservable,
22
- IObservableSignal,
23
16
  ISettableObservable,
24
- ITransaction,
25
17
  autorun,
26
18
  autorunWithStoreHandleChanges,
27
19
  derived,
28
- derivedHandleChanges,
29
- derivedOpts,
30
- observableFromEvent,
31
- observableSignal,
32
20
  observableValue,
33
21
  transaction,
34
22
  } from '@opensumi/ide-monaco/lib/common/observable';
@@ -59,9 +47,8 @@ import { IntelligentCompletionsRegistry } from './intelligent-completions.featur
59
47
  import { CodeEditsSourceCollection } from './source/base';
60
48
  import { LineChangeCodeEditsSource } from './source/line-change.source';
61
49
  import { LintErrorCodeEditsSource } from './source/lint-error.source';
62
- import { TypingCodeEditsSource } from './source/typing.source';
63
50
 
64
- import { CodeEditsResultValue, VALID_TIME } from './index';
51
+ import { CodeEditsResultValue } from './index';
65
52
 
66
53
  export class IntelligentCompletionsController extends BaseAIMonacoEditorController {
67
54
  public static readonly ID = 'editor.contrib.ai.intelligent.completions';
@@ -96,32 +83,22 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
96
83
  private codeEditsSourceCollection: CodeEditsSourceCollection;
97
84
  private aiNativeContextKey: AINativeContextKey;
98
85
  private rewriteWidget: RewriteWidget | null;
99
- private codeEditsTriggerSignal: IObservableSignal<void>;
100
- private multiLineEditsIsVisibleObs: IObservable<boolean>;
86
+ private whenMultiLineEditsVisibleDisposable: Disposable;
101
87
 
102
88
  public mount(): IDisposable {
103
89
  this.handlerAlwaysVisiblePreference();
104
90
 
105
91
  this.codeEditsResult = observableValue<CodeEditsResultValue | undefined>(this, undefined);
106
- this.codeEditsTriggerSignal = observableSignal(this);
107
92
 
93
+ this.whenMultiLineEditsVisibleDisposable = new Disposable();
108
94
  this.multiLineDecorationModel = new MultiLineDecorationModel(this.monacoEditor);
109
95
  this.additionsDeletionsDecorationModel = new AdditionsDeletionsDecorationModel(this.monacoEditor);
110
96
  this.aiNativeContextKey = this.injector.get(AINativeContextKey, [this.monacoEditor.contextKeyService]);
111
97
  this.codeEditsSourceCollection = this.injector.get(CodeEditsSourceCollection, [
112
- [LintErrorCodeEditsSource, LineChangeCodeEditsSource, TypingCodeEditsSource],
98
+ [LintErrorCodeEditsSource, LineChangeCodeEditsSource],
113
99
  this.monacoEditor,
114
100
  ]);
115
101
 
116
- const multiLineEditsIsVisibleKey = new Set([MultiLineEditsIsVisible.raw]);
117
- this.multiLineEditsIsVisibleObs = observableFromEvent(
118
- this,
119
- Event.filter(this.aiNativeContextKey.contextKeyService!.onDidChangeContext, (e: ContextKeyChangeEvent) =>
120
- e.payload.affectsSome(multiLineEditsIsVisibleKey),
121
- ),
122
- () => !!this.aiNativeContextKey.multiLineEditsIsVisible.get(),
123
- );
124
-
125
102
  this.registerFeature(this.monacoEditor);
126
103
  return this.featureDisposable;
127
104
  }
@@ -276,6 +253,26 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
276
253
  this.additionsDeletionsDecorationModel.updateDeletionsDecoration(wordChanges, range, eol);
277
254
  this.renderRewriteWidget(wordChanges, model, range, insertTextString);
278
255
  }
256
+
257
+ if (this.whenMultiLineEditsVisibleDisposable.disposed) {
258
+ this.whenMultiLineEditsVisibleDisposable = new Disposable();
259
+ }
260
+ // 监听当前光标位置的变化,如果超出 range 区域则表示弃用
261
+ this.whenMultiLineEditsVisibleDisposable.addDispose(
262
+ this.monacoEditor.onDidChangeCursorPosition((event: ICursorPositionChangedEvent) => {
263
+ const isVisible = this.aiNativeContextKey.multiLineEditsIsVisible.get();
264
+ if (isVisible) {
265
+ const position = event.position;
266
+ if (position.lineNumber < range.startLineNumber || position.lineNumber > range.endLineNumber) {
267
+ runWhenIdle(() => {
268
+ this.discard.get();
269
+ });
270
+ }
271
+ } else {
272
+ this.whenMultiLineEditsVisibleDisposable.dispose();
273
+ }
274
+ }),
275
+ );
279
276
  }
280
277
 
281
278
  private async renderRewriteWidget(
@@ -338,52 +335,36 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
338
335
  const { range, insertText } = codeEditsResult.items[0];
339
336
  const newCode = insertText;
340
337
  const originCode = this.model.getValueInRange(range);
341
- return (type: keyof Pick<CodeEditsRT, 'isReceive' | 'isDrop' | 'isValid'>, defaultValue: boolean = true) => {
342
- const data = {
343
- [type]: defaultValue,
338
+ return (type: keyof Pick<CodeEditsRT, 'isReceive' | 'isDrop' | 'isValid'>) => {
339
+ contextBean.reporterEnd({
340
+ [type]: true,
344
341
  code: newCode,
345
342
  originCode,
346
- };
347
-
348
- contextBean.reporterEnd(data);
343
+ });
349
344
  };
350
345
  }
351
346
  });
352
347
 
353
- public discard = derivedHandleChanges(
354
- {
355
- owner: this,
356
- createEmptyChangeSummary: () => ({ lastVisibleTime: Date.now() }),
357
- handleChange: (context, changeSummary) => {
358
- if (context.didChange(this.multiLineEditsIsVisibleObs)) {
359
- changeSummary.lastVisibleTime = Date.now();
360
- return this.multiLineEditsIsVisibleObs.get();
361
- }
362
- return false;
363
- },
364
- equalityComparer: () => false,
365
- },
366
- (reader, changeSummary) => {
367
- this.multiLineEditsIsVisibleObs.read(reader);
368
-
369
- const lastVisibleTime = changeSummary.lastVisibleTime;
370
- const report = this.reportData.read(reader);
371
- let isValid = false;
372
-
373
- if (lastVisibleTime && Date.now() - lastVisibleTime > VALID_TIME) {
374
- isValid = true;
375
- report?.('isDrop');
376
- } else {
377
- isValid = false;
378
- report?.('isValid', false);
379
- }
348
+ private lastVisibleTime = derived(this, (reader) => {
349
+ const isVisible = this.aiNativeContextKey.multiLineEditsIsVisible.get();
350
+ return isVisible ? Date.now() : undefined;
351
+ });
352
+
353
+ public discard = derived(this, (reader) => {
354
+ const lastVisibleTime = this.lastVisibleTime.read(reader);
355
+ const report = this.reportData.read(reader);
356
+
357
+ // 在可见的情况下超过 750ms 弃用才算有效数据,否则视为取消
358
+ if (lastVisibleTime && Date.now() - lastVisibleTime > 750) {
359
+ report?.('isDrop');
360
+ } else {
361
+ report?.('isValid');
362
+ }
380
363
 
381
- this.hide();
382
- return isValid;
383
- },
384
- );
364
+ this.hide();
365
+ });
385
366
 
386
- public accept = derivedOpts({ owner: this, equalsFn: () => false }, (reader) => {
367
+ public accept = derived(this, (reader) => {
387
368
  const report = this.reportData.read(reader);
388
369
  report?.('isReceive');
389
370
 
@@ -411,10 +392,6 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
411
392
  this.hide();
412
393
  });
413
394
 
414
- public trigger(tx: ITransaction): void {
415
- this.codeEditsTriggerSignal.trigger(tx);
416
- }
417
-
418
395
  private registerFeature(monacoEditor: ICodeEditor): void {
419
396
  this.featureDisposable.addDispose(
420
397
  Event.any<any>(
@@ -426,19 +403,14 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
426
403
  }),
427
404
  );
428
405
 
429
- // 监听当前光标位置的变化,如果超出 range 区域则表示弃用
406
+ const multiLineEditsIsVisibleKey = new Set([MultiLineEditsIsVisible.raw]);
407
+ this.featureDisposable.addDispose(this.whenMultiLineEditsVisibleDisposable);
430
408
  this.featureDisposable.addDispose(
431
- this.monacoEditor.onDidChangeCursorPosition((event: ICursorPositionChangedEvent) => {
432
- const isVisible = this.multiLineEditsIsVisibleObs.get();
433
- const completionModel = this.codeEditsResult.get();
434
-
435
- if (isVisible && completionModel) {
436
- const position = event.position;
437
- const range = completionModel.items[0].range;
438
- if (position.lineNumber < range.startLineNumber || position.lineNumber > range.endLineNumber) {
439
- runWhenIdle(() => {
440
- this.discard.get();
441
- });
409
+ this.aiNativeContextKey.contextKeyService!.onDidChangeContext((e) => {
410
+ if (e.payload.affectsSome(multiLineEditsIsVisibleKey)) {
411
+ const isVisible = this.aiNativeContextKey.multiLineEditsIsVisible.get();
412
+ if (!isVisible) {
413
+ this.whenMultiLineEditsVisibleDisposable.dispose();
442
414
  }
443
415
  }
444
416
  }),
@@ -459,19 +431,16 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
459
431
  autorunWithStoreHandleChanges(
460
432
  {
461
433
  createEmptyChangeSummary: () => ({}),
462
- handleChange: (context) => {
434
+ handleChange: (context, changeSummary) => {
463
435
  if (context.didChange(this.codeEditsSourceCollection.codeEditsContextBean)) {
464
436
  // 如果上一次补全结果还在,则不重复请求
465
437
  const isVisible = this.aiNativeContextKey.multiLineEditsIsVisible.get();
466
438
  return !isVisible;
467
- } else if (context.didChange(this.codeEditsTriggerSignal)) {
468
- return true;
469
439
  }
470
440
  return false;
471
441
  },
472
442
  },
473
443
  async (reader, _, store) => {
474
- this.codeEditsTriggerSignal.read(reader);
475
444
  const context = this.codeEditsSourceCollection.codeEditsContextBean.read(reader);
476
445
 
477
446
  const provider = this.intelligentCompletionsRegistry.getCodeEditsProvider();
@@ -7,6 +7,7 @@ import {
7
7
  Disposable,
8
8
  IAIReporter,
9
9
  IDisposable,
10
+ MaybePromise,
10
11
  uuid,
11
12
  } from '@opensumi/ide-core-common';
12
13
  import { CancellationTokenSource, ICodeEditor } from '@opensumi/ide-monaco';
@@ -36,26 +37,14 @@ export class CodeEditsContextBean extends Disposable {
36
37
  return this.raw;
37
38
  }
38
39
 
39
- public get typing() {
40
- return this.raw.typing;
41
- }
42
-
43
40
  public get position() {
44
41
  return this.raw.position;
45
42
  }
46
43
 
47
- public get data() {
48
- return this.raw.data;
49
- }
50
-
51
44
  public get token() {
52
45
  return this.source.token;
53
46
  }
54
47
 
55
- public joinData(data: ICodeEditsContextBean['data']) {
56
- this.raw.data = { ...this.data, ...data };
57
- }
58
-
59
48
  public reporterStart() {
60
49
  return this.source.reporterStart();
61
50
  }
@@ -80,6 +69,8 @@ export abstract class BaseCodeEditsSource extends Disposable {
80
69
  private cancellationTokenSource = new CancellationTokenSource();
81
70
  private readonly relationID = observableValue<string | undefined>(this, undefined);
82
71
 
72
+ protected abstract doTrigger(...args: any[]): MaybePromise<void>;
73
+
83
74
  public readonly codeEditsContextBean = disposableObservableValue<CodeEditsContextBean | undefined>(this, undefined);
84
75
  public abstract priority: number;
85
76
  public abstract mount(): IDisposable;
@@ -109,9 +100,9 @@ export abstract class BaseCodeEditsSource extends Disposable {
109
100
  });
110
101
  }
111
102
 
112
- protected setBean(bean: Omit<ICodeEditsContextBean, 'position'>) {
103
+ protected setBean(bean: ICodeEditsContextBean) {
113
104
  transaction((tx) => {
114
- const context = new CodeEditsContextBean({ ...bean, position: this.monacoEditor.getPosition()! }, this);
105
+ const context = new CodeEditsContextBean(bean, this);
115
106
  this.codeEditsContextBean.set(context, tx);
116
107
  });
117
108
  }
@@ -121,7 +112,7 @@ export abstract class BaseCodeEditsSource extends Disposable {
121
112
  if (context) {
122
113
  const relationID = this.aiReporter.start(AIServiceType.CodeEdits, {
123
114
  type: AIServiceType.CodeEdits,
124
- actionSource: context?.typing,
115
+ actionSource: context?.bean.typing,
125
116
  });
126
117
 
127
118
  transaction((tx) => {
@@ -177,23 +168,11 @@ export class CodeEditsSourceCollection extends Disposable {
177
168
 
178
169
  for (const source of lastSources) {
179
170
  const value = source.codeEditsContextBean.get();
180
- if (!value) {
181
- return;
182
- }
183
-
184
- if (!contextBean) {
185
- contextBean = value;
186
- }
187
171
 
188
- if (value.priority >= highestPriority) {
172
+ if (value && value.priority >= highestPriority) {
189
173
  highestPriority = value.priority;
190
-
191
- value.joinData(contextBean.data);
192
174
  contextBean = value;
193
175
  }
194
-
195
- // 将多个 source 的 data 合并到一起
196
- contextBean.joinData(value.data);
197
176
  }
198
177
 
199
178
  transaction((tx) => {