@opensumi/ide-ai-native 3.4.4 → 3.4.5-next-1729482152.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 (128) hide show
  1. package/lib/browser/ai-core.contribution.d.ts.map +1 -1
  2. package/lib/browser/ai-core.contribution.js +18 -17
  3. package/lib/browser/ai-core.contribution.js.map +1 -1
  4. package/lib/browser/components/utils.d.ts +2 -2
  5. package/lib/browser/contrib/inline-completions/inline-completions.controller.d.ts +18 -0
  6. package/lib/browser/contrib/inline-completions/inline-completions.controller.d.ts.map +1 -0
  7. package/lib/browser/contrib/{intelligent-completions/intelligent-completions.source.js → inline-completions/inline-completions.controller.js} +48 -38
  8. package/lib/browser/contrib/inline-completions/inline-completions.controller.js.map +1 -0
  9. package/lib/browser/contrib/inline-completions/model/competionModel.d.ts +1 -1
  10. package/lib/browser/contrib/inline-completions/model/competionModel.d.ts.map +1 -1
  11. package/lib/browser/contrib/inline-completions/model/inlineCompletionRequestTask.js +4 -4
  12. package/lib/browser/contrib/inline-completions/model/inlineCompletionRequestTask.js.map +1 -1
  13. package/lib/browser/contrib/inline-completions/prompt/prompt.d.ts +3 -3
  14. package/lib/browser/contrib/inline-completions/prompt/prompt.d.ts.map +1 -1
  15. package/lib/browser/contrib/inline-completions/prompt/prompt.js.map +1 -1
  16. package/lib/browser/contrib/inline-completions/prompt/tokenizer.d.ts +1 -1
  17. package/lib/browser/contrib/inline-completions/prompt/tokenizer.d.ts.map +1 -1
  18. package/lib/browser/contrib/inline-completions/prompt/tokenizer.js +2 -3
  19. package/lib/browser/contrib/inline-completions/prompt/tokenizer.js.map +1 -1
  20. package/lib/browser/contrib/inline-completions/promptCache.d.ts +1 -1
  21. package/lib/browser/contrib/inline-completions/promptCache.d.ts.map +1 -1
  22. package/lib/browser/contrib/inline-completions/service/ai-completions.service.d.ts +1 -1
  23. package/lib/browser/contrib/inline-completions/service/ai-completions.service.d.ts.map +1 -1
  24. package/lib/browser/contrib/intelligent-completions/{additions-deletions.decoration.d.ts → decoration/additions-deletions.decoration.d.ts} +1 -1
  25. package/lib/browser/contrib/intelligent-completions/decoration/additions-deletions.decoration.d.ts.map +1 -0
  26. package/lib/browser/contrib/intelligent-completions/{additions-deletions.decoration.js → decoration/additions-deletions.decoration.js} +3 -3
  27. package/lib/browser/contrib/intelligent-completions/decoration/additions-deletions.decoration.js.map +1 -0
  28. package/lib/browser/contrib/intelligent-completions/{multi-line.decoration.d.ts → decoration/multi-line.decoration.d.ts} +1 -1
  29. package/lib/browser/contrib/intelligent-completions/decoration/multi-line.decoration.d.ts.map +1 -0
  30. package/lib/browser/contrib/intelligent-completions/{multi-line.decoration.js → decoration/multi-line.decoration.js} +1 -1
  31. package/lib/browser/contrib/intelligent-completions/decoration/multi-line.decoration.js.map +1 -0
  32. package/lib/browser/contrib/intelligent-completions/index.d.ts +30 -0
  33. package/lib/browser/contrib/intelligent-completions/index.d.ts.map +1 -0
  34. package/lib/browser/contrib/intelligent-completions/index.js +8 -0
  35. package/lib/browser/contrib/intelligent-completions/index.js.map +1 -0
  36. package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.d.ts +3 -4
  37. package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.d.ts.map +1 -1
  38. package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.js +26 -25
  39. package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.js.map +1 -1
  40. package/lib/browser/contrib/intelligent-completions/intelligent-completions.feature.registry.d.ts +7 -3
  41. package/lib/browser/contrib/intelligent-completions/intelligent-completions.feature.registry.d.ts.map +1 -1
  42. package/lib/browser/contrib/intelligent-completions/intelligent-completions.feature.registry.js +12 -3
  43. package/lib/browser/contrib/intelligent-completions/intelligent-completions.feature.registry.js.map +1 -1
  44. package/lib/browser/contrib/intelligent-completions/lint-error.source.d.ts +29 -0
  45. package/lib/browser/contrib/intelligent-completions/lint-error.source.d.ts.map +1 -0
  46. package/lib/browser/contrib/intelligent-completions/lint-error.source.js +99 -0
  47. package/lib/browser/contrib/intelligent-completions/lint-error.source.js.map +1 -0
  48. package/lib/browser/contrib/terminal/decoration/terminal-decoration.d.ts +1 -1
  49. package/lib/browser/contrib/terminal/decoration/terminal-decoration.d.ts.map +1 -1
  50. package/lib/browser/contrib/terminal/decoration/terminal-decoration.js.map +1 -1
  51. package/lib/browser/contrib/terminal/ps1-terminal.service.js.map +1 -1
  52. package/lib/browser/index.d.ts.map +1 -1
  53. package/lib/browser/index.js +5 -0
  54. package/lib/browser/index.js.map +1 -1
  55. package/lib/browser/types.d.ts +13 -3
  56. package/lib/browser/types.d.ts.map +1 -1
  57. package/lib/browser/types.js.map +1 -1
  58. package/lib/browser/widget/inline-diff/index.d.ts +1 -0
  59. package/lib/browser/widget/inline-diff/index.d.ts.map +1 -1
  60. package/lib/browser/widget/inline-diff/index.js +1 -0
  61. package/lib/browser/widget/inline-diff/index.js.map +1 -1
  62. package/lib/browser/widget/inline-diff/inline-diff-previewer.d.ts +4 -1
  63. package/lib/browser/widget/inline-diff/inline-diff-previewer.d.ts.map +1 -1
  64. package/lib/browser/widget/inline-diff/inline-diff-previewer.js +0 -4
  65. package/lib/browser/widget/inline-diff/inline-diff-previewer.js.map +1 -1
  66. package/lib/browser/widget/inline-diff/inline-diff.controller.d.ts +0 -3
  67. package/lib/browser/widget/inline-diff/inline-diff.controller.d.ts.map +1 -1
  68. package/lib/browser/widget/inline-diff/inline-diff.controller.js +0 -7
  69. package/lib/browser/widget/inline-diff/inline-diff.controller.js.map +1 -1
  70. package/lib/browser/widget/inline-diff/inline-diff.service.d.ts +10 -0
  71. package/lib/browser/widget/inline-diff/inline-diff.service.d.ts.map +1 -0
  72. package/lib/browser/widget/inline-diff/inline-diff.service.js +23 -0
  73. package/lib/browser/widget/inline-diff/inline-diff.service.js.map +1 -0
  74. package/lib/browser/widget/inline-stream-diff/inline-stream-diff.handler.d.ts +0 -1
  75. package/lib/browser/widget/inline-stream-diff/inline-stream-diff.handler.d.ts.map +1 -1
  76. package/lib/browser/widget/inline-stream-diff/inline-stream-diff.handler.js +5 -3
  77. package/lib/browser/widget/inline-stream-diff/inline-stream-diff.handler.js.map +1 -1
  78. package/lib/browser/widget/inline-stream-diff/live-preview.component.d.ts +9 -0
  79. package/lib/browser/widget/inline-stream-diff/live-preview.component.d.ts.map +1 -1
  80. package/lib/browser/widget/inline-stream-diff/live-preview.component.js +10 -3
  81. package/lib/browser/widget/inline-stream-diff/live-preview.component.js.map +1 -1
  82. package/lib/browser/widget/inline-stream-diff/live-preview.decoration.d.ts +8 -3
  83. package/lib/browser/widget/inline-stream-diff/live-preview.decoration.d.ts.map +1 -1
  84. package/lib/browser/widget/inline-stream-diff/live-preview.decoration.js +54 -24
  85. package/lib/browser/widget/inline-stream-diff/live-preview.decoration.js.map +1 -1
  86. package/lib/browser/widget/rewrite/rewrite-widget.d.ts.map +1 -1
  87. package/lib/browser/widget/rewrite/rewrite-widget.js +2 -1
  88. package/lib/browser/widget/rewrite/rewrite-widget.js.map +1 -1
  89. package/package.json +24 -24
  90. package/src/browser/ai-core.contribution.ts +23 -17
  91. package/src/browser/contrib/{intelligent-completions/intelligent-completions.source.ts → inline-completions/inline-completions.controller.ts} +51 -23
  92. package/src/browser/contrib/inline-completions/model/competionModel.ts +1 -1
  93. package/src/browser/contrib/inline-completions/model/inlineCompletionRequestTask.ts +5 -5
  94. package/src/browser/contrib/inline-completions/prompt/prompt.ts +9 -5
  95. package/src/browser/contrib/inline-completions/prompt/tokenizer.ts +2 -3
  96. package/src/browser/contrib/inline-completions/promptCache.ts +1 -1
  97. package/src/browser/contrib/inline-completions/service/ai-completions.service.ts +1 -1
  98. package/src/browser/contrib/intelligent-completions/{additions-deletions.decoration.ts → decoration/additions-deletions.decoration.ts} +4 -5
  99. package/src/browser/contrib/intelligent-completions/{multi-line.decoration.ts → decoration/multi-line.decoration.ts} +2 -3
  100. package/src/browser/contrib/intelligent-completions/index.ts +34 -0
  101. package/src/browser/contrib/intelligent-completions/intelligent-completions.controller.ts +31 -44
  102. package/src/browser/contrib/intelligent-completions/intelligent-completions.feature.registry.ts +18 -5
  103. package/src/browser/contrib/intelligent-completions/lint-error.source.ts +130 -0
  104. package/src/browser/contrib/terminal/ai-terminal.service.ts +1 -1
  105. package/src/browser/contrib/terminal/decoration/terminal-decoration.tsx +1 -1
  106. package/src/browser/contrib/terminal/ps1-terminal.service.tsx +1 -1
  107. package/src/browser/index.ts +5 -0
  108. package/src/browser/types.ts +24 -3
  109. package/src/browser/widget/inline-diff/index.ts +1 -0
  110. package/src/browser/widget/inline-diff/inline-diff-previewer.ts +5 -3
  111. package/src/browser/widget/inline-diff/inline-diff.controller.ts +0 -12
  112. package/src/browser/widget/inline-diff/inline-diff.service.ts +17 -0
  113. package/src/browser/widget/inline-stream-diff/inline-stream-diff.handler.tsx +6 -4
  114. package/src/browser/widget/inline-stream-diff/live-preview.component.tsx +15 -0
  115. package/src/browser/widget/inline-stream-diff/live-preview.decoration.tsx +72 -26
  116. package/src/browser/widget/rewrite/rewrite-widget.tsx +2 -1
  117. package/lib/browser/contrib/intelligent-completions/additions-deletions.decoration.d.ts.map +0 -1
  118. package/lib/browser/contrib/intelligent-completions/additions-deletions.decoration.js.map +0 -1
  119. package/lib/browser/contrib/intelligent-completions/intelligent-completions.d.ts +0 -15
  120. package/lib/browser/contrib/intelligent-completions/intelligent-completions.d.ts.map +0 -1
  121. package/lib/browser/contrib/intelligent-completions/intelligent-completions.js +0 -3
  122. package/lib/browser/contrib/intelligent-completions/intelligent-completions.js.map +0 -1
  123. package/lib/browser/contrib/intelligent-completions/intelligent-completions.source.d.ts +0 -15
  124. package/lib/browser/contrib/intelligent-completions/intelligent-completions.source.d.ts.map +0 -1
  125. package/lib/browser/contrib/intelligent-completions/intelligent-completions.source.js.map +0 -1
  126. package/lib/browser/contrib/intelligent-completions/multi-line.decoration.d.ts.map +0 -1
  127. package/lib/browser/contrib/intelligent-completions/multi-line.decoration.js.map +0 -1
  128. package/src/browser/contrib/intelligent-completions/intelligent-completions.ts +0 -15
@@ -1,13 +1,13 @@
1
1
  import debounce from 'lodash/debounce';
2
2
 
3
- import { Autowired, INJECTOR_TOKEN, Injectable, Injector, Optional } from '@opensumi/di';
4
3
  import { AI_INLINE_COMPLETION_VISIBLE } from '@opensumi/ide-core-browser/lib/ai-native/command';
5
4
  import {
6
5
  CommandService,
7
6
  CommandServiceImpl,
8
- Disposable,
7
+ IAICompletionOption,
9
8
  IDisposable,
10
9
  IEventBus,
10
+ IntelligentCompletionsRegistryToken,
11
11
  Sequencer,
12
12
  runWhenIdle,
13
13
  } from '@opensumi/ide-core-common';
@@ -18,28 +18,40 @@ import { empty } from '@opensumi/ide-utils/lib/strings';
18
18
  import { InlineCompletionContextKeys } from '@opensumi/monaco-editor-core/esm/vs/editor/contrib/inlineCompletions/browser/inlineCompletionContextKeys';
19
19
 
20
20
  import { IAIInlineCompletionsProvider } from '../../../common';
21
+ import { AINativeContextKey } from '../../contextkey/ai-native.contextkey.service';
22
+ import { BaseAIMonacoEditorController } from '../base';
23
+ import { IIntelligentCompletionsResult } from '../intelligent-completions';
24
+ import { IntelligentCompletionsRegistry } from '../intelligent-completions/intelligent-completions.feature.registry';
21
25
 
22
- import { IIntelligentCompletionsResult } from './intelligent-completions';
26
+ export class InlineCompletionsController extends BaseAIMonacoEditorController {
27
+ public static readonly ID = 'editor.contrib.ai.inline.completions';
23
28
 
24
- @Injectable({ multiple: true })
25
- export class InlineCompletionsSource extends Disposable {
26
- @Autowired(INJECTOR_TOKEN)
27
- protected readonly injector: Injector;
29
+ public static get(editor: ICodeEditor): InlineCompletionsController | null {
30
+ return editor.getContribution<InlineCompletionsController>(InlineCompletionsController.ID);
31
+ }
32
+
33
+ private get eventBus(): IEventBus {
34
+ return this.injector.get(IEventBus);
35
+ }
28
36
 
29
- @Autowired(IEventBus)
30
- private eventBus: IEventBus;
37
+ private get commandService(): CommandServiceImpl {
38
+ return this.injector.get(CommandService);
39
+ }
31
40
 
32
- @Autowired(CommandService)
33
- private commandService: CommandServiceImpl;
41
+ private get aiInlineCompletionsProvider(): IAIInlineCompletionsProvider {
42
+ return this.injector.get(IAIInlineCompletionsProvider);
43
+ }
34
44
 
35
- @Autowired(IAIInlineCompletionsProvider)
36
- private readonly aiInlineCompletionsProvider: IAIInlineCompletionsProvider;
45
+ private get intelligentCompletionsRegistry(): IntelligentCompletionsRegistry {
46
+ return this.injector.get(IntelligentCompletionsRegistryToken);
47
+ }
37
48
 
49
+ private aiNativeContextKey: AINativeContextKey;
38
50
  private sequencer = new Sequencer();
39
51
  private preDidShowItems: InlineCompletions | undefined;
40
52
 
41
- constructor(@Optional() private readonly monacoEditor: ICodeEditor) {
42
- super();
53
+ public mount(): IDisposable {
54
+ this.aiNativeContextKey = this.injector.get(AINativeContextKey, [this.monacoEditor.contextKeyService]);
43
55
 
44
56
  // 判断用户是否选择了一块区域或者移动光标 取消掉请补全请求
45
57
  const selectionChange = () => {
@@ -62,7 +74,7 @@ export class InlineCompletionsSource extends Disposable {
62
74
  });
63
75
 
64
76
  const inlineVisibleKey = new Set([InlineCompletionContextKeys.inlineSuggestionVisible.key]);
65
- this.addDispose(
77
+ this.featureDisposable.addDispose(
66
78
  this.monacoEditor.contextKeyService.onDidChangeContext((e) => {
67
79
  // inline completion 真正消失时
68
80
  if (e.affectsSome(inlineVisibleKey)) {
@@ -79,7 +91,7 @@ export class InlineCompletionsSource extends Disposable {
79
91
  }),
80
92
  );
81
93
 
82
- this.addDispose(
94
+ this.featureDisposable.addDispose(
83
95
  this.eventBus.on(EditorSelectionChangeEvent, (e) => {
84
96
  if (e.payload.source === 'mouse') {
85
97
  debouncedSelectionChange();
@@ -90,7 +102,7 @@ export class InlineCompletionsSource extends Disposable {
90
102
  }),
91
103
  );
92
104
 
93
- this.addDispose(
105
+ this.featureDisposable.addDispose(
94
106
  this.monacoEditor.onDidChangeModelContent((e) => {
95
107
  const changes = e.changes;
96
108
  for (const change of changes) {
@@ -104,17 +116,15 @@ export class InlineCompletionsSource extends Disposable {
104
116
  }),
105
117
  );
106
118
 
107
- this.addDispose(
119
+ this.featureDisposable.addDispose(
108
120
  this.monacoEditor.onDidBlurEditorText(() => {
109
121
  this.commandService.executeCommand(AI_INLINE_COMPLETION_VISIBLE.id, false);
110
122
  }),
111
123
  );
112
- }
113
124
 
114
- public fetch(): IDisposable {
115
125
  let prePosition: Position | undefined;
116
126
 
117
- this.addDispose(
127
+ this.featureDisposable.addDispose(
118
128
  monacoApi.languages.registerInlineCompletionsProvider('*', {
119
129
  groupId: 'ai-native-intelligent-completions',
120
130
  provideInlineCompletions: async (model, position, context, token) => {
@@ -150,6 +160,24 @@ export class InlineCompletionsSource extends Disposable {
150
160
  }),
151
161
  );
152
162
 
153
- return this;
163
+ return this.featureDisposable;
164
+ }
165
+
166
+ public async fetchProvider(bean: IAICompletionOption): Promise<IIntelligentCompletionsResult | undefined> {
167
+ const provider = this.intelligentCompletionsRegistry.getInlineCompletionsProvider();
168
+ if (!provider) {
169
+ return;
170
+ }
171
+
172
+ // 如果上一次补全结果还在,则不重复请求
173
+ const isVisible = this.aiNativeContextKey.multiLineEditsIsVisible.get();
174
+ if (isVisible) {
175
+ return;
176
+ }
177
+
178
+ const position = this.monacoEditor.getPosition()!;
179
+ const inlineCompletionModel = await provider(this.monacoEditor, position, bean, this.token);
180
+
181
+ return inlineCompletionModel;
154
182
  }
155
183
  }
@@ -1,6 +1,6 @@
1
1
  import * as monaco from '@opensumi/ide-monaco';
2
2
 
3
- import { IIntelligentCompletionsResult } from '../../intelligent-completions/intelligent-completions';
3
+ import { IIntelligentCompletionsResult } from '../../intelligent-completions';
4
4
 
5
5
  /**
6
6
  * 缓存的结果
@@ -16,9 +16,9 @@ import { WorkbenchEditorService } from '@opensumi/ide-editor';
16
16
  import { WorkbenchEditorServiceImpl } from '@opensumi/ide-editor/lib/browser/workbench-editor.service';
17
17
  import * as monaco from '@opensumi/ide-monaco';
18
18
 
19
- import { IIntelligentCompletionsResult } from '../../intelligent-completions/intelligent-completions';
20
- import { IntelligentCompletionsController } from '../../intelligent-completions/intelligent-completions.controller';
19
+ import { IIntelligentCompletionsResult } from '../../intelligent-completions';
21
20
  import { IntelligentCompletionsRegistry } from '../../intelligent-completions/intelligent-completions.feature.registry';
21
+ import { InlineCompletionsController } from '../inline-completions.controller';
22
22
  import { InlineCompletionItem } from '../model/competionModel';
23
23
  import { PromptCache } from '../promptCache';
24
24
  import { lineBasedPromptProcessor } from '../provider';
@@ -174,14 +174,14 @@ export class InlineCompletionRequestTask extends Disposable {
174
174
  } else {
175
175
  try {
176
176
  this.aiCompletionsService.updateStatusBarItem('running', true);
177
- const provider = this.intelligentCompletionsRegistry.getProvider();
177
+ const provider = this.intelligentCompletionsRegistry.getInlineCompletionsProvider();
178
178
  if (provider) {
179
179
  const editor = this.workbenchEditorService.currentCodeEditor;
180
180
  if (!editor) {
181
181
  return [];
182
182
  }
183
- const intelligentCompletionsHandler = IntelligentCompletionsController.get(editor.monacoEditor);
184
- completeResult = await intelligentCompletionsHandler?.fetchProvider(requestBean);
183
+ const inlineCompletionsHandler = InlineCompletionsController.get(editor.monacoEditor);
184
+ completeResult = await inlineCompletionsHandler?.fetchProvider(requestBean);
185
185
  } else {
186
186
  completeResult = await this.aiCompletionsService.complete(requestBean);
187
187
  }
@@ -1,5 +1,4 @@
1
- // @ts-ignore
2
- import { Tiktoken } from 'js-tiktoken';
1
+ import { Tiktoken } from 'tiktoken/lite';
3
2
 
4
3
  import { Injector } from '@opensumi/di';
5
4
 
@@ -59,7 +58,12 @@ export const getMarkerForSnippets = (text: string, language: string) => {
59
58
  return lines.map((line) => getMarkerByLanguage(line, language)).join('\n');
60
59
  };
61
60
 
62
- export const getCroppedTextByLine = (text: string, maxTokenSize: number, textTokens: number[][], reverse = false) => {
61
+ export const getCroppedTextByLine = (
62
+ text: string,
63
+ maxTokenSize: number,
64
+ textTokens: Uint32Array[],
65
+ reverse = false,
66
+ ) => {
63
67
  const currentTokenSize = textTokens.reduce((prev, cur) => prev + cur.length, 0);
64
68
  if (currentTokenSize < maxTokenSize) {
65
69
  return text;
@@ -110,7 +114,7 @@ export const getCroppedTextByLine = (text: string, maxTokenSize: number, textTok
110
114
  export const getCroppedText = async (
111
115
  text: string,
112
116
  maxTokenSize: number,
113
- textTokens: number[][],
117
+ textTokens: Uint32Array[],
114
118
  strategy = StrategyType.InterceptBasedOnLine,
115
119
  tokenizer: Tiktoken,
116
120
  parser?: LanguageParser,
@@ -118,7 +122,7 @@ export const getCroppedText = async (
118
122
  reverse = false,
119
123
  token?: monaco.CancellationToken,
120
124
  ): Promise<string> => {
121
- let tokens: number[];
125
+ let tokens: Uint32Array;
122
126
  if (strategy === StrategyType.InterceptBasedOnLine) {
123
127
  // 按行进行裁剪
124
128
  text = getCroppedTextByLine(text, maxTokenSize, textTokens, reverse);
@@ -1,5 +1,4 @@
1
- // @ts-ignore
2
- import { Tiktoken, getEncoding } from 'js-tiktoken';
1
+ import { Tiktoken, get_encoding } from 'tiktoken';
3
2
 
4
3
  import { TokenizerName } from '../types';
5
4
 
@@ -10,7 +9,7 @@ export const getTokenizer = (tokenizerName = TokenizerName.cl100k_base) => {
10
9
  if (tokenizer) {
11
10
  return tokenizer;
12
11
  }
13
- tokenizer = getEncoding('cl100k_base');
12
+ tokenizer = get_encoding('cl100k_base');
14
13
  TOKENIZER_CACHE.set(tokenizerName, tokenizer);
15
14
  return tokenizer;
16
15
  };
@@ -9,7 +9,7 @@ import {
9
9
  } from '@opensumi/ide-core-browser';
10
10
  import { IHashCalculateService } from '@opensumi/ide-core-common/lib/hash-calculate/hash-calculate';
11
11
 
12
- import { IIntelligentCompletionsResult } from '../intelligent-completions/intelligent-completions';
12
+ import { IIntelligentCompletionsResult } from '../intelligent-completions';
13
13
 
14
14
  /**
15
15
  * 缓存服务
@@ -15,7 +15,7 @@ import {
15
15
  } from '@opensumi/ide-core-common';
16
16
  import { CompletionRT, IAIReporter } from '@opensumi/ide-core-common/lib/types/ai-native/reporter';
17
17
 
18
- import { IIntelligentCompletionsResult } from '../../intelligent-completions/intelligent-completions';
18
+ import { IIntelligentCompletionsResult } from '../../intelligent-completions';
19
19
 
20
20
  @Injectable()
21
21
  export class AICompletionsService extends Disposable {
@@ -1,10 +1,9 @@
1
1
  import { ICodeEditor, IModelDeltaDecoration, IRange, TrackedRangeStickiness } from '@opensumi/ide-monaco';
2
2
 
3
- import { EnhanceDecorationsCollection } from '../../model/enhanceDecorationsCollection';
4
- import { REWRITE_DECORATION_INLINE_ADD } from '../../widget/rewrite/rewrite-widget';
5
-
6
- import { IMultiLineDiffChangeResult } from './diff-computer';
7
- import styles from './intelligent-completions.module.less';
3
+ import { EnhanceDecorationsCollection } from '../../../model/enhanceDecorationsCollection';
4
+ import { REWRITE_DECORATION_INLINE_ADD } from '../../../widget/rewrite/rewrite-widget';
5
+ import { IMultiLineDiffChangeResult } from '../diff-computer';
6
+ import styles from '../intelligent-completions.module.less';
8
7
 
9
8
  export class AdditionsDeletionsDecorationModel {
10
9
  private deletionsDecorations: EnhanceDecorationsCollection;
@@ -4,9 +4,8 @@ import { empty } from '@opensumi/ide-utils/lib/strings';
4
4
  import { EditOperation } from '@opensumi/monaco-editor-core/esm/vs/editor/common/core/editOperation';
5
5
  import { LineDecoration } from '@opensumi/monaco-editor-core/esm/vs/editor/common/viewLayout/lineDecorations';
6
6
 
7
- import { EnhanceDecorationsCollection } from '../../model/enhanceDecorationsCollection';
8
-
9
- import { IMultiLineDiffChangeResult } from './diff-computer';
7
+ import { EnhanceDecorationsCollection } from '../../../model/enhanceDecorationsCollection';
8
+ import { IMultiLineDiffChangeResult } from '../diff-computer';
10
9
 
11
10
  export interface IModificationsInline {
12
11
  newValue: string;
@@ -0,0 +1,34 @@
1
+ import { IRange, InlineCompletion } from '@opensumi/ide-monaco';
2
+
3
+ import type { ILinterErrorData } from './lint-error.source';
4
+
5
+ export interface IIntelligentCompletionsResult<T = any> {
6
+ readonly items: InlineCompletion[];
7
+ /**
8
+ * 定义的额外信息
9
+ */
10
+ extra?: T;
11
+ }
12
+
13
+ export enum ECodeEditsSource {
14
+ LinterErrors = 'lint_errors',
15
+ }
16
+
17
+ export interface ICodeEditsContextBean {
18
+ typing: ECodeEditsSource.LinterErrors;
19
+ data: ILinterErrorData;
20
+ }
21
+
22
+ export interface ICodeEdit {
23
+ /**
24
+ * 插入的文本
25
+ */
26
+ readonly insertText: string;
27
+ /**
28
+ * 替换的文本范围
29
+ */
30
+ readonly range: IRange;
31
+ }
32
+ export interface ICodeEditsResult {
33
+ readonly items: ICodeEdit[];
34
+ }
@@ -1,14 +1,6 @@
1
1
  import { Key, KeybindingRegistry, KeybindingScope, PreferenceService } from '@opensumi/ide-core-browser';
2
2
  import { MultiLineEditsIsVisible } from '@opensumi/ide-core-browser/lib/contextkey/ai-native';
3
- import {
4
- AINativeSettingSectionsId,
5
- Disposable,
6
- Event,
7
- IAICompletionOption,
8
- IDisposable,
9
- IntelligentCompletionsRegistryToken,
10
- runWhenIdle,
11
- } from '@opensumi/ide-core-common';
3
+ import { AINativeSettingSectionsId, Disposable, Event, IDisposable, runWhenIdle } from '@opensumi/ide-core-common';
12
4
  import { ICodeEditor, ICursorPositionChangedEvent, IRange, ITextModel, Range } from '@opensumi/ide-monaco';
13
5
  import { empty } from '@opensumi/ide-utils/lib/strings';
14
6
  import { autorun, transaction } from '@opensumi/monaco-editor-core/esm/vs/base/common/observable';
@@ -21,23 +13,24 @@ import {
21
13
  SuggestItemInfo,
22
14
  SuggestWidgetAdaptor,
23
15
  } from '@opensumi/monaco-editor-core/esm/vs/editor/contrib/inlineCompletions/browser/suggestWidgetInlineCompletionProvider';
16
+ import { SuggestController } from '@opensumi/monaco-editor-core/esm/vs/editor/contrib/suggest/browser/suggestController';
24
17
  import { ContextKeyExpr } from '@opensumi/monaco-editor-core/esm/vs/platform/contextkey/common/contextkey';
25
18
 
26
19
  import { AINativeContextKey } from '../../contextkey/ai-native.contextkey.service';
27
20
  import { REWRITE_DECORATION_INLINE_ADD, RewriteWidget } from '../../widget/rewrite/rewrite-widget';
28
21
  import { BaseAIMonacoEditorController } from '../base';
29
22
 
30
- import { AdditionsDeletionsDecorationModel } from './additions-deletions.decoration';
23
+ import { AdditionsDeletionsDecorationModel } from './decoration/additions-deletions.decoration';
24
+ import { MultiLineDecorationModel } from './decoration/multi-line.decoration';
31
25
  import {
32
26
  IMultiLineDiffChangeResult,
33
27
  computeMultiLineDiffChanges,
34
28
  mergeMultiLineDiffChanges,
35
29
  wordChangesToLineChangesMap,
36
30
  } from './diff-computer';
37
- import { IIntelligentCompletionsResult } from './intelligent-completions';
38
- import { IntelligentCompletionsRegistry } from './intelligent-completions.feature.registry';
39
- import { InlineCompletionsSource } from './intelligent-completions.source';
40
- import { MultiLineDecorationModel } from './multi-line.decoration';
31
+ import { LintErrorCodeEditsSource } from './lint-error.source';
32
+
33
+ import { ICodeEditsResult } from '.';
41
34
 
42
35
  export class IntelligentCompletionsController extends BaseAIMonacoEditorController {
43
36
  public static readonly ID = 'editor.contrib.ai.intelligent.completions';
@@ -46,10 +39,6 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
46
39
  return editor.getContribution<IntelligentCompletionsController>(IntelligentCompletionsController.ID);
47
40
  }
48
41
 
49
- private get intelligentCompletionsRegistry(): IntelligentCompletionsRegistry {
50
- return this.injector.get(IntelligentCompletionsRegistryToken);
51
- }
52
-
53
42
  private get model(): ITextModel {
54
43
  return this.monacoEditor.getModel()!;
55
44
  }
@@ -129,6 +118,19 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
129
118
  }
130
119
  }),
131
120
  );
121
+
122
+ observableDisposable.addDispose(
123
+ autorun((reader) => {
124
+ const state = inlineCompletionsController.model.read(reader)?.state.read(reader);
125
+ const suggestController = SuggestController.get(this.monacoEditor);
126
+ // 当阴影字符超出一行的时候,强制让 suggest 面板向上展示,避免遮挡补全内容
127
+ if (state && state.primaryGhostText?.lineCount >= 2) {
128
+ suggestController?.forceRenderingAbove();
129
+ } else {
130
+ suggestController?.stopForceRenderingAbove();
131
+ }
132
+ }),
133
+ );
132
134
  }
133
135
  };
134
136
 
@@ -169,45 +171,30 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
169
171
  }
170
172
  }
171
173
 
172
- public async fetchProvider(bean: IAICompletionOption): Promise<IIntelligentCompletionsResult | undefined> {
173
- const provider = this.intelligentCompletionsRegistry.getProvider();
174
- if (!provider) {
175
- return;
176
- }
177
-
174
+ public async fetchProvider(editsResult: ICodeEditsResult): Promise<void> {
178
175
  // 如果上一次补全结果还在,则不重复请求
179
176
  const isVisible = this.aiNativeContextKey.multiLineEditsIsVisible.get();
180
177
  if (isVisible) {
181
178
  return;
182
179
  }
183
180
 
184
- const position = this.monacoEditor.getPosition()!;
185
- const intelligentCompletionModel = await provider(this.monacoEditor, position, bean, this.token);
186
-
187
- if (
188
- intelligentCompletionModel &&
189
- intelligentCompletionModel.enableMultiLine &&
190
- intelligentCompletionModel.items.length > 0
191
- ) {
192
- return this.applyInlineDecorations(intelligentCompletionModel);
181
+ if (editsResult && editsResult.items.length > 0) {
182
+ this.applyInlineDecorations(editsResult);
193
183
  }
194
-
195
- return intelligentCompletionModel;
196
184
  }
197
185
 
198
- private applyInlineDecorations(completionModel: IIntelligentCompletionsResult) {
186
+ private applyInlineDecorations(completionModel: ICodeEditsResult) {
199
187
  const { items } = completionModel;
200
-
201
- const position = this.monacoEditor.getPosition()!;
202
- const model = this.monacoEditor.getModel();
203
188
  const { range, insertText } = items[0];
204
- const insertTextString = insertText.toString();
205
189
 
206
- // 如果只是开启了 enableMultiLine 而没有传递 range ,则不显示 multi line
190
+ // code edits 必须提供 range
207
191
  if (!range) {
208
- return completionModel;
192
+ return;
209
193
  }
210
194
 
195
+ const position = this.monacoEditor.getPosition()!;
196
+ const model = this.monacoEditor.getModel();
197
+ const insertTextString = insertText.toString();
211
198
  const originalContent = model?.getValueInRange(range);
212
199
  const eol = this.model.getEOL();
213
200
 
@@ -390,7 +377,7 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
390
377
  }),
391
378
  );
392
379
 
393
- const inlineCompletionsSource = this.injector.get(InlineCompletionsSource, [this.monacoEditor]);
394
- this.featureDisposable.addDispose(inlineCompletionsSource.fetch());
380
+ const lintErrorCodeEditsSource = this.injector.get(LintErrorCodeEditsSource, [this.monacoEditor, this.token]);
381
+ this.featureDisposable.addDispose(lintErrorCodeEditsSource.mount());
395
382
  }
396
383
  }
@@ -1,17 +1,30 @@
1
1
  import { Injectable } from '@opensumi/di';
2
2
  import { Disposable } from '@opensumi/ide-core-common';
3
3
 
4
- import { IIntelligentCompletionProvider, IIntelligentCompletionsRegistry } from '../../types';
4
+ import { ICodeEditsProvider, IIntelligentCompletionProvider, IIntelligentCompletionsRegistry } from '../../types';
5
5
 
6
6
  @Injectable()
7
7
  export class IntelligentCompletionsRegistry extends Disposable implements IIntelligentCompletionsRegistry {
8
- private provider: IIntelligentCompletionProvider | undefined;
8
+ private inlineCompletionsProvider: IIntelligentCompletionProvider | undefined;
9
+ private codeEditsProvider: ICodeEditsProvider | undefined;
9
10
 
10
11
  registerIntelligentCompletionProvider(provider: IIntelligentCompletionProvider): void {
11
- this.provider = provider;
12
+ this.inlineCompletionsProvider = provider;
12
13
  }
13
14
 
14
- getProvider(): IIntelligentCompletionProvider | undefined {
15
- return this.provider;
15
+ registerInlineCompletionsProvider(provider: IIntelligentCompletionProvider): void {
16
+ this.inlineCompletionsProvider = provider;
17
+ }
18
+
19
+ registerCodeEditsProvider(provider: ICodeEditsProvider): void {
20
+ this.codeEditsProvider = provider;
21
+ }
22
+
23
+ getInlineCompletionsProvider(): IIntelligentCompletionProvider | undefined {
24
+ return this.inlineCompletionsProvider;
25
+ }
26
+
27
+ getCodeEditsProvider(): ICodeEditsProvider | undefined {
28
+ return this.codeEditsProvider;
16
29
  }
17
30
  }
@@ -0,0 +1,130 @@
1
+ import { Autowired, Injectable, Optional } from '@opensumi/di';
2
+ import {
3
+ CancellationToken,
4
+ Disposable,
5
+ IDisposable,
6
+ IntelligentCompletionsRegistryToken,
7
+ } from '@opensumi/ide-core-common';
8
+ import { ICodeEditor, ICursorPositionChangedEvent, IPosition, Position } from '@opensumi/ide-monaco';
9
+ import { URI } from '@opensumi/ide-monaco/lib/browser/monaco-api';
10
+ import { IWorkspaceService } from '@opensumi/ide-workspace';
11
+ import { StandaloneServices } from '@opensumi/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneServices';
12
+ import {
13
+ IMarker,
14
+ IMarkerService,
15
+ IRelatedInformation,
16
+ MarkerSeverity,
17
+ } from '@opensumi/monaco-editor-core/esm/vs/platform/markers/common/markers';
18
+
19
+ import { IntelligentCompletionsController } from './intelligent-completions.controller';
20
+ import { IntelligentCompletionsRegistry } from './intelligent-completions.feature.registry';
21
+
22
+ import { ECodeEditsSource } from '.';
23
+
24
+ export interface ILinterErrorData {
25
+ relativeWorkspacePath: string;
26
+ errors: Array<IMarkerErrorData>;
27
+ }
28
+
29
+ export interface IMarkerErrorData {
30
+ message: string;
31
+ range: {
32
+ startPosition: IPosition;
33
+ endPosition: IPosition;
34
+ };
35
+ source: URI;
36
+ severity: string;
37
+ relatedInformation?: IRelatedInformation[];
38
+ }
39
+
40
+ namespace MarkerErrorData {
41
+ export function toData(marker: IMarker): IMarkerErrorData {
42
+ return {
43
+ message: marker.message,
44
+ range: {
45
+ startPosition: {
46
+ lineNumber: marker.startLineNumber,
47
+ column: marker.startColumn,
48
+ },
49
+ endPosition: {
50
+ lineNumber: marker.endLineNumber,
51
+ column: marker.endColumn,
52
+ },
53
+ },
54
+ source: marker.resource,
55
+ relatedInformation: marker.relatedInformation,
56
+ severity: MarkerSeverity.toString(marker.severity),
57
+ };
58
+ }
59
+ }
60
+
61
+ @Injectable({ multiple: true })
62
+ export class LintErrorCodeEditsSource extends Disposable {
63
+ @Autowired(IntelligentCompletionsRegistryToken)
64
+ private readonly intelligentCompletionsRegistry: IntelligentCompletionsRegistry;
65
+
66
+ @Autowired(IWorkspaceService)
67
+ private readonly workspaceService: IWorkspaceService;
68
+
69
+ private get model() {
70
+ return this.monacoEditor.getModel();
71
+ }
72
+
73
+ constructor(
74
+ @Optional() private readonly monacoEditor: ICodeEditor,
75
+ @Optional() private readonly token: CancellationToken,
76
+ ) {
77
+ super();
78
+ }
79
+
80
+ public mount(): IDisposable {
81
+ let prePosition = this.monacoEditor.getPosition();
82
+
83
+ this.addDispose(
84
+ // 仅在光标的行号发生变化时,才触发
85
+ this.monacoEditor.onDidChangeCursorPosition((event: ICursorPositionChangedEvent) => {
86
+ const currentPosition = event.position;
87
+ if (prePosition && prePosition.lineNumber !== currentPosition.lineNumber) {
88
+ this.doTrigger(currentPosition);
89
+ }
90
+ prePosition = currentPosition;
91
+ }),
92
+ );
93
+ return this;
94
+ }
95
+
96
+ private async doTrigger(position: Position) {
97
+ if (!this.model) {
98
+ return;
99
+ }
100
+
101
+ const markerService = StandaloneServices.get(IMarkerService);
102
+ const resource = this.model.uri;
103
+
104
+ let markers = markerService.read({ resource, severities: MarkerSeverity.Error });
105
+ markers = markers.filter((marker) => Math.abs(marker.startLineNumber - position.lineNumber) <= 1);
106
+
107
+ if (markers.length) {
108
+ const provider = this.intelligentCompletionsRegistry.getCodeEditsProvider();
109
+ if (provider) {
110
+ const relativeWorkspacePath = await this.workspaceService.asRelativePath(resource.path);
111
+ const result = await provider(
112
+ this.monacoEditor,
113
+ position,
114
+ {
115
+ typing: ECodeEditsSource.LinterErrors,
116
+ data: {
117
+ relativeWorkspacePath: relativeWorkspacePath?.path ?? resource.path,
118
+ errors: markers.map((marker) => MarkerErrorData.toData(marker)),
119
+ },
120
+ },
121
+ this.token,
122
+ );
123
+
124
+ if (result) {
125
+ IntelligentCompletionsController.get(this.monacoEditor)?.fetchProvider(result);
126
+ }
127
+ }
128
+ }
129
+ }
130
+ }
@@ -1,4 +1,4 @@
1
- import { IMarker } from 'xterm';
1
+ import { IMarker } from '@xterm/xterm';
2
2
 
3
3
  import { Autowired, Injectable } from '@opensumi/di';
4
4
  import { AIActionItem } from '@opensumi/ide-core-browser/lib/components/ai-native';
@@ -1,6 +1,6 @@
1
+ import { IDecoration, IMarker, Terminal } from '@xterm/xterm';
1
2
  import React from 'react';
2
3
  import { Root, createRoot } from 'react-dom/client';
3
- import { IDecoration, IMarker, Terminal } from 'xterm';
4
4
 
5
5
  import { Autowired, Injectable } from '@opensumi/di';
6
6
  import { AIActionItem } from '@opensumi/ide-core-browser/lib/components/ai-native';
@@ -1,7 +1,7 @@
1
+ import { IDecoration, IDisposable, IMarker, Terminal } from '@xterm/xterm';
1
2
  import domAlign from 'dom-align';
2
3
  import React from 'react';
3
4
  import { Root, createRoot } from 'react-dom/client';
4
- import { IDecoration, IDisposable, IMarker, Terminal } from 'xterm';
5
5
 
6
6
  import { Autowired, Injectable } from '@opensumi/di';
7
7
  import { localize } from '@opensumi/ide-core-browser';