@opensumi/ide-ai-native 2.26.9-next-1695201123.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 (194) hide show
  1. package/LICENSE +21 -0
  2. package/lib/browser/ai-chat.contribution.d.ts +26 -0
  3. package/lib/browser/ai-chat.contribution.d.ts.map +1 -0
  4. package/lib/browser/ai-chat.contribution.js +228 -0
  5. package/lib/browser/ai-chat.contribution.js.map +1 -0
  6. package/lib/browser/ai-chat.module.less +174 -0
  7. package/lib/browser/ai-chat.service.d.ts +30 -0
  8. package/lib/browser/ai-chat.service.d.ts.map +1 -0
  9. package/lib/browser/ai-chat.service.js +129 -0
  10. package/lib/browser/ai-chat.service.js.map +1 -0
  11. package/lib/browser/ai-chat.view.d.ts +4 -0
  12. package/lib/browser/ai-chat.view.d.ts.map +1 -0
  13. package/lib/browser/ai-chat.view.js +292 -0
  14. package/lib/browser/ai-chat.view.js.map +1 -0
  15. package/lib/browser/ai-editor.contribution.d.ts +26 -0
  16. package/lib/browser/ai-editor.contribution.d.ts.map +1 -0
  17. package/lib/browser/ai-editor.contribution.js +430 -0
  18. package/lib/browser/ai-editor.contribution.js.map +1 -0
  19. package/lib/browser/ai-project/generate.service.d.ts +34 -0
  20. package/lib/browser/ai-project/generate.service.d.ts.map +1 -0
  21. package/lib/browser/ai-project/generate.service.js +460 -0
  22. package/lib/browser/ai-project/generate.service.js.map +1 -0
  23. package/lib/browser/ai-sumi/sumi.service.d.ts +11 -0
  24. package/lib/browser/ai-sumi/sumi.service.d.ts.map +1 -0
  25. package/lib/browser/ai-sumi/sumi.service.js +64 -0
  26. package/lib/browser/ai-sumi/sumi.service.js.map +1 -0
  27. package/lib/browser/code-widget/ai-code-document.provider.d.ts +10 -0
  28. package/lib/browser/code-widget/ai-code-document.provider.d.ts.map +1 -0
  29. package/lib/browser/code-widget/ai-code-document.provider.js +26 -0
  30. package/lib/browser/code-widget/ai-code-document.provider.js.map +1 -0
  31. package/lib/browser/code-widget/ai-code-widget.d.ts +20 -0
  32. package/lib/browser/code-widget/ai-code-widget.d.ts.map +1 -0
  33. package/lib/browser/code-widget/ai-code-widget.js +164 -0
  34. package/lib/browser/code-widget/ai-code-widget.js.map +1 -0
  35. package/lib/browser/components/AIImprove.d.ts +9 -0
  36. package/lib/browser/components/AIImprove.d.ts.map +1 -0
  37. package/lib/browser/components/AIImprove.js +34 -0
  38. package/lib/browser/components/AIImprove.js.map +1 -0
  39. package/lib/browser/components/AIInput.d.ts +5 -0
  40. package/lib/browser/components/AIInput.d.ts.map +1 -0
  41. package/lib/browser/components/AIInput.js +22 -0
  42. package/lib/browser/components/AIInput.js.map +1 -0
  43. package/lib/browser/components/ChatEditor.d.ts +5 -0
  44. package/lib/browser/components/ChatEditor.d.ts.map +1 -0
  45. package/lib/browser/components/ChatEditor.js +85 -0
  46. package/lib/browser/components/ChatEditor.js.map +1 -0
  47. package/lib/browser/components/ChatInput.d.ts +6 -0
  48. package/lib/browser/components/ChatInput.d.ts.map +1 -0
  49. package/lib/browser/components/ChatInput.js +126 -0
  50. package/lib/browser/components/ChatInput.js.map +1 -0
  51. package/lib/browser/components/ChatMoreActions.d.ts +5 -0
  52. package/lib/browser/components/ChatMoreActions.d.ts.map +1 -0
  53. package/lib/browser/components/ChatMoreActions.js +26 -0
  54. package/lib/browser/components/ChatMoreActions.js.map +1 -0
  55. package/lib/browser/components/Thinking.d.ts +3 -0
  56. package/lib/browser/components/Thinking.d.ts.map +1 -0
  57. package/lib/browser/components/Thinking.js +19 -0
  58. package/lib/browser/components/Thinking.js.map +1 -0
  59. package/lib/browser/components/components.module.less +261 -0
  60. package/lib/browser/components/lineVertical.d.ts +4 -0
  61. package/lib/browser/components/lineVertical.d.ts.map +1 -0
  62. package/lib/browser/components/lineVertical.js +22 -0
  63. package/lib/browser/components/lineVertical.js.map +1 -0
  64. package/lib/browser/content-widget/ai-content-widget.d.ts +38 -0
  65. package/lib/browser/content-widget/ai-content-widget.d.ts.map +1 -0
  66. package/lib/browser/content-widget/ai-content-widget.js +97 -0
  67. package/lib/browser/content-widget/ai-content-widget.js.map +1 -0
  68. package/lib/browser/content-widget/ai-inline-chat-panel.d.ts +6 -0
  69. package/lib/browser/content-widget/ai-inline-chat-panel.d.ts.map +1 -0
  70. package/lib/browser/content-widget/ai-inline-chat-panel.js +108 -0
  71. package/lib/browser/content-widget/ai-inline-chat-panel.js.map +1 -0
  72. package/lib/browser/content-widget/ai-inline-chat.module.less +81 -0
  73. package/lib/browser/content-widget/ai-inline-chat.service.d.ts +23 -0
  74. package/lib/browser/content-widget/ai-inline-chat.service.d.ts.map +1 -0
  75. package/lib/browser/content-widget/ai-inline-chat.service.js +47 -0
  76. package/lib/browser/content-widget/ai-inline-chat.service.js.map +1 -0
  77. package/lib/browser/diff-widget/ai-diff-document.provider.d.ts +10 -0
  78. package/lib/browser/diff-widget/ai-diff-document.provider.d.ts.map +1 -0
  79. package/lib/browser/diff-widget/ai-diff-document.provider.js +26 -0
  80. package/lib/browser/diff-widget/ai-diff-document.provider.js.map +1 -0
  81. package/lib/browser/diff-widget/ai-diff-widget.d.ts +20 -0
  82. package/lib/browser/diff-widget/ai-diff-widget.d.ts.map +1 -0
  83. package/lib/browser/diff-widget/ai-diff-widget.js +158 -0
  84. package/lib/browser/diff-widget/ai-diff-widget.js.map +1 -0
  85. package/lib/browser/index.d.ts +11 -0
  86. package/lib/browser/index.d.ts.map +1 -0
  87. package/lib/browser/index.js +82 -0
  88. package/lib/browser/index.js.map +1 -0
  89. package/lib/browser/inline-completions/constants.d.ts +62 -0
  90. package/lib/browser/inline-completions/constants.d.ts.map +1 -0
  91. package/lib/browser/inline-completions/constants.js +69 -0
  92. package/lib/browser/inline-completions/constants.js.map +1 -0
  93. package/lib/browser/inline-completions/provider.d.ts +27 -0
  94. package/lib/browser/inline-completions/provider.d.ts.map +1 -0
  95. package/lib/browser/inline-completions/provider.js +63 -0
  96. package/lib/browser/inline-completions/provider.js.map +1 -0
  97. package/lib/browser/override/ai-editor-tab.service.d.ts +6 -0
  98. package/lib/browser/override/ai-editor-tab.service.d.ts.map +1 -0
  99. package/lib/browser/override/ai-editor-tab.service.js +22 -0
  100. package/lib/browser/override/ai-editor-tab.service.js.map +1 -0
  101. package/lib/browser/override/ai-marker.service.d.ts +11 -0
  102. package/lib/browser/override/ai-marker.service.d.ts.map +1 -0
  103. package/lib/browser/override/ai-marker.service.js +56 -0
  104. package/lib/browser/override/ai-marker.service.js.map +1 -0
  105. package/lib/browser/override/layout/layout-config.d.ts +11 -0
  106. package/lib/browser/override/layout/layout-config.d.ts.map +1 -0
  107. package/lib/browser/override/layout/layout-config.js +17 -0
  108. package/lib/browser/override/layout/layout-config.js.map +1 -0
  109. package/lib/browser/override/layout/layout.module.less +261 -0
  110. package/lib/browser/override/layout/main-slot-renderer.d.ts +4 -0
  111. package/lib/browser/override/layout/main-slot-renderer.d.ts.map +1 -0
  112. package/lib/browser/override/layout/main-slot-renderer.js +23 -0
  113. package/lib/browser/override/layout/main-slot-renderer.js.map +1 -0
  114. package/lib/browser/override/layout/menu-bar/menu-bar.contribution.d.ts +8 -0
  115. package/lib/browser/override/layout/menu-bar/menu-bar.contribution.d.ts.map +1 -0
  116. package/lib/browser/override/layout/menu-bar/menu-bar.contribution.js +32 -0
  117. package/lib/browser/override/layout/menu-bar/menu-bar.contribution.js.map +1 -0
  118. package/lib/browser/override/layout/menu-bar/menu-bar.module.less +41 -0
  119. package/lib/browser/override/layout/menu-bar/menu-bar.view.d.ts +3 -0
  120. package/lib/browser/override/layout/menu-bar/menu-bar.view.d.ts.map +1 -0
  121. package/lib/browser/override/layout/menu-bar/menu-bar.view.js +62 -0
  122. package/lib/browser/override/layout/menu-bar/menu-bar.view.js.map +1 -0
  123. package/lib/browser/override/layout/tabbar.view.d.ts +19 -0
  124. package/lib/browser/override/layout/tabbar.view.d.ts.map +1 -0
  125. package/lib/browser/override/layout/tabbar.view.js +38 -0
  126. package/lib/browser/override/layout/tabbar.view.js.map +1 -0
  127. package/lib/browser/override/override.module.less +32 -0
  128. package/lib/browser/override/theme/default-theme.d.ts +315 -0
  129. package/lib/browser/override/theme/default-theme.d.ts.map +1 -0
  130. package/lib/browser/override/theme/default-theme.js +821 -0
  131. package/lib/browser/override/theme/default-theme.js.map +1 -0
  132. package/lib/browser/run/run.service.d.ts +52 -0
  133. package/lib/browser/run/run.service.d.ts.map +1 -0
  134. package/lib/browser/run/run.service.js +176 -0
  135. package/lib/browser/run/run.service.js.map +1 -0
  136. package/lib/common/command.d.ts +17 -0
  137. package/lib/common/command.d.ts.map +1 -0
  138. package/lib/common/command.js +21 -0
  139. package/lib/common/command.js.map +1 -0
  140. package/lib/common/index.d.ts +47 -0
  141. package/lib/common/index.d.ts.map +1 -0
  142. package/lib/common/index.js +33 -0
  143. package/lib/common/index.js.map +1 -0
  144. package/lib/index.d.ts +2 -0
  145. package/lib/index.d.ts.map +1 -0
  146. package/lib/index.js +5 -0
  147. package/lib/index.js.map +1 -0
  148. package/lib/node/index.d.ts +10 -0
  149. package/lib/node/index.d.ts.map +1 -0
  150. package/lib/node/index.js +32 -0
  151. package/lib/node/index.js.map +1 -0
  152. package/package.json +38 -0
  153. package/src/browser/ai-chat.contribution.ts +300 -0
  154. package/src/browser/ai-chat.module.less +174 -0
  155. package/src/browser/ai-chat.service.ts +146 -0
  156. package/src/browser/ai-chat.view.tsx +410 -0
  157. package/src/browser/ai-editor.contribution.ts +564 -0
  158. package/src/browser/ai-project/generate.service.ts +515 -0
  159. package/src/browser/ai-sumi/sumi.service.ts +65 -0
  160. package/src/browser/code-widget/ai-code-document.provider.ts +22 -0
  161. package/src/browser/code-widget/ai-code-widget.tsx +202 -0
  162. package/src/browser/components/AIImprove.tsx +45 -0
  163. package/src/browser/components/AIInput.tsx +30 -0
  164. package/src/browser/components/ChatEditor.tsx +129 -0
  165. package/src/browser/components/ChatInput.tsx +199 -0
  166. package/src/browser/components/ChatMoreActions.tsx +33 -0
  167. package/src/browser/components/Thinking.tsx +23 -0
  168. package/src/browser/components/components.module.less +261 -0
  169. package/src/browser/components/lineVertical.tsx +19 -0
  170. package/src/browser/content-widget/ai-content-widget.tsx +132 -0
  171. package/src/browser/content-widget/ai-inline-chat-panel.tsx +163 -0
  172. package/src/browser/content-widget/ai-inline-chat.module.less +81 -0
  173. package/src/browser/content-widget/ai-inline-chat.service.ts +46 -0
  174. package/src/browser/diff-widget/ai-diff-document.provider.ts +22 -0
  175. package/src/browser/diff-widget/ai-diff-widget.tsx +196 -0
  176. package/src/browser/index.ts +89 -0
  177. package/src/browser/inline-completions/constants.ts +108 -0
  178. package/src/browser/inline-completions/provider.ts +55 -0
  179. package/src/browser/override/ai-editor-tab.service.tsx +22 -0
  180. package/src/browser/override/ai-marker.service.tsx +61 -0
  181. package/src/browser/override/layout/layout-config.ts +17 -0
  182. package/src/browser/override/layout/layout.module.less +261 -0
  183. package/src/browser/override/layout/main-slot-renderer.tsx +63 -0
  184. package/src/browser/override/layout/menu-bar/menu-bar.contribution.tsx +28 -0
  185. package/src/browser/override/layout/menu-bar/menu-bar.module.less +41 -0
  186. package/src/browser/override/layout/menu-bar/menu-bar.view.tsx +92 -0
  187. package/src/browser/override/layout/tabbar.view.tsx +91 -0
  188. package/src/browser/override/override.module.less +32 -0
  189. package/src/browser/override/theme/default-theme.ts +818 -0
  190. package/src/browser/run/run.service.ts +186 -0
  191. package/src/common/command.ts +21 -0
  192. package/src/common/index.ts +50 -0
  193. package/src/index.ts +1 -0
  194. package/src/node/index.ts +24 -0
@@ -0,0 +1,564 @@
1
+ import { Injectable, Autowired, INJECTOR_TOKEN, Injector } from '@opensumi/di';
2
+ import { AbstractMenuService } from '@opensumi/ide-core-browser/lib/menu/next';
3
+ import {
4
+ IDisposable,
5
+ URI,
6
+ MaybePromise,
7
+ Disposable,
8
+ Event,
9
+ uuid,
10
+ CommandService,
11
+ ILoggerManagerClient,
12
+ SupportLogNamespace,
13
+ ILogServiceClient,
14
+ } from '@opensumi/ide-core-common';
15
+ import { IEditor, IEditorFeatureContribution } from '@opensumi/ide-editor/lib/browser';
16
+ import { DocumentSymbolStore } from '@opensumi/ide-editor/lib/browser/breadcrumb/document-symbol';
17
+ import { IFileTreeAPI } from '@opensumi/ide-file-tree-next';
18
+ import { Position } from '@opensumi/ide-monaco';
19
+ import { editor as MonacoEditor } from '@opensumi/monaco-editor-core';
20
+ import { InlineCompletion, InlineCompletions } from '@opensumi/monaco-editor-core/esm/vs/editor/common/languages';
21
+ import * as monaco from '@opensumi/monaco-editor-core/esm/vs/editor/editor.api';
22
+
23
+ import { AiGPTBackSerivcePath, InstructionEnum } from '../common/index';
24
+
25
+ import { AiChatService } from './ai-chat.service';
26
+ import { AiCodeWidget } from './code-widget/ai-code-widget';
27
+ import { AiContentWidget } from './content-widget/ai-content-widget';
28
+ import { AiInlineChatService, EChatStatus } from './content-widget/ai-inline-chat.service';
29
+ import { AiDiffWidget } from './diff-widget/ai-diff-widget';
30
+ import { prePromptHandler, preSuffixHandler, ReqStack } from './inline-completions/provider';
31
+
32
+ @Injectable()
33
+ export class AiEditorContribution extends Disposable implements IEditorFeatureContribution {
34
+ @Autowired(INJECTOR_TOKEN)
35
+ private readonly injector: Injector;
36
+
37
+ @Autowired(AiGPTBackSerivcePath)
38
+ private readonly aiGPTBackService: any;
39
+
40
+ @Autowired(AiInlineChatService)
41
+ private readonly aiInlineChatService: AiInlineChatService;
42
+
43
+ @Autowired(DocumentSymbolStore)
44
+ private documentSymbolStore: DocumentSymbolStore;
45
+
46
+ @Autowired(CommandService)
47
+ private readonly commandService: CommandService;
48
+
49
+ @Autowired(AiChatService)
50
+ private readonly aiChatService: AiChatService;
51
+
52
+ @Autowired(IFileTreeAPI)
53
+ private readonly fileTreeAPI: IFileTreeAPI;
54
+
55
+ @Autowired(ILoggerManagerClient)
56
+ private readonly loggerManagerClient: ILoggerManagerClient;
57
+
58
+ private logger: ILogServiceClient;
59
+
60
+ constructor() {
61
+ super();
62
+
63
+ this.logger = this.loggerManagerClient.getLogger(SupportLogNamespace.Browser);
64
+ }
65
+
66
+ contribute(editor: IEditor): IDisposable {
67
+ if (!editor) {
68
+ return this;
69
+ }
70
+
71
+ this.registerSuggestJavaDoc(editor);
72
+ this.registerCompletion(editor);
73
+
74
+ const { monacoEditor, currentUri } = editor;
75
+ if (currentUri && currentUri.codeUri.scheme !== 'file') {
76
+ return this;
77
+ }
78
+
79
+ let aiDiffWidget: AiDiffWidget | undefined;
80
+ let aiCodeWidget: AiCodeWidget | undefined;
81
+ let aiContentWidget: AiContentWidget | undefined;
82
+ const aiInlineChatDisposed = new Disposable();
83
+
84
+ const disposeAllWidget = () => {
85
+ if (aiDiffWidget) {
86
+ aiDiffWidget.dispose();
87
+ }
88
+ if (aiCodeWidget) {
89
+ aiCodeWidget.dispose();
90
+ }
91
+ if (aiContentWidget) {
92
+ aiContentWidget.dispose();
93
+ }
94
+ if (aiInlineChatDisposed) {
95
+ aiInlineChatDisposed.dispose();
96
+ }
97
+ };
98
+
99
+ this.disposables.push(
100
+ monacoEditor.onDidChangeModel(() => {
101
+ disposeAllWidget();
102
+ }),
103
+ );
104
+
105
+ Event.debounce(
106
+ Event.any(monacoEditor.onDidChangeCursorSelection),
107
+ (_, e) => e,
108
+ 100,
109
+ )((e) => {
110
+ disposeAllWidget();
111
+
112
+ const { monacoEditor, currentUri } = editor;
113
+
114
+ if (!currentUri) {
115
+ return;
116
+ }
117
+
118
+ if (currentUri && currentUri.codeUri.scheme !== 'file') {
119
+ return;
120
+ }
121
+
122
+ const selection = monacoEditor.getSelection();
123
+
124
+ if (!selection) {
125
+ disposeAllWidget();
126
+ return;
127
+ }
128
+
129
+ const { startLineNumber, endLineNumber } = selection;
130
+ // 获取指定范围内的文本内容
131
+ const text = monacoEditor.getModel()?.getValueInRange(selection);
132
+
133
+ if (!text) {
134
+ return;
135
+ }
136
+
137
+ disposeAllWidget();
138
+
139
+ this.logger.log('monacoEditor.onMouseUp: >>> text', text);
140
+
141
+ this.aiInlineChatService.launchChatMessage(EChatStatus.READY);
142
+
143
+ aiContentWidget = this.injector.get(AiContentWidget, [monacoEditor]);
144
+
145
+ aiContentWidget.show({
146
+ selection,
147
+ });
148
+
149
+ this.disposables.push(
150
+ aiContentWidget.onSelectChange(async (value) => {
151
+ if (aiDiffWidget) {
152
+ aiDiffWidget.dispose();
153
+ }
154
+
155
+ const model = monacoEditor.getModel();
156
+ if (!model) {
157
+ return;
158
+ }
159
+
160
+ if (value === '解释代码') {
161
+ this.aiChatService.launchChatMessage({
162
+ message: InstructionEnum.aiExplainKey,
163
+ prompt: this.aiChatService.explainCodePrompt(),
164
+ });
165
+ return;
166
+ }
167
+
168
+ if (value === '生成测试用例') {
169
+ this.aiInlineChatService.launchChatMessage(EChatStatus.THINKING);
170
+
171
+ // @ts-ignore
172
+ const symbols = this.documentSymbolStore.getDocumentSymbol(model.uri!);
173
+
174
+ const findRange = (range: { startLineNumber: number; endLineNumber: number }) => {
175
+ if (!symbols) {
176
+ return;
177
+ }
178
+
179
+ return symbols
180
+ .map((obj) =>
181
+ // (range.startLineNumber >= obj.range.startLineNumber && range.endLineNumber <= obj.range.endLineNumber ? obj : null)
182
+ (obj.children || []).find(
183
+ (child) =>
184
+ range.startLineNumber >= child.range.startLineNumber &&
185
+ range.endLineNumber <= child.range.endLineNumber,
186
+ ),
187
+ )
188
+ .filter(Boolean)[0];
189
+ };
190
+
191
+ const fullCode = monacoEditor.getValue();
192
+
193
+ const currentFunc = findRange(selection);
194
+
195
+ if (!currentFunc) {
196
+ return;
197
+ }
198
+
199
+ const prompt = `这是我的完整代码。\`\`\`${fullCode}\`\`\`。请帮我生成 ${currentFunc.name} 方法的 junit 单元测试用例,不需要解释,只需要返回代码结果`;
200
+ this.logger.log('生成测试用例 prompt:>>> ', prompt);
201
+ const result = await this.aiGPTBackService.aiGPTcompletionRequest(
202
+ `这是我的完整代码。\`\`\`${fullCode}\`\`\`。请帮我生成 ${currentFunc.name} 方法的 junit 单元测试用例,不需要解释,只需要返回代码结果`,
203
+ );
204
+
205
+ // 说明接口有异常
206
+ if (result.errorCode !== 0) {
207
+ this.aiInlineChatService.launchChatMessage(EChatStatus.ERROR);
208
+ } else {
209
+ this.aiInlineChatService.launchChatMessage(EChatStatus.DONE);
210
+ }
211
+
212
+ let answer = result && result.data;
213
+
214
+ // 提取代码内容
215
+ const regex = /```\w*\s*([\s\S]+?)\s*```/;
216
+ const regExec = regex.exec(answer);
217
+ answer = (regExec && regExec[1]) || answer;
218
+
219
+ this.logger.log('生成测试用例 answer:>>> ', result);
220
+
221
+ if (answer) {
222
+ // 文件后缀名
223
+ const ext = URI.from(model.uri).path.ext;
224
+ const testUri = model.uri.with({
225
+ path: model.uri.path.replace(ext, `.test${ext}`),
226
+ });
227
+
228
+ this.logger.log(testUri);
229
+ aiCodeWidget = this.injector.get(AiCodeWidget, [monacoEditor!, answer, testUri]);
230
+ aiCodeWidget.create();
231
+ aiCodeWidget.showByLine(endLineNumber, selection.endLineNumber - selection.startLineNumber + 2);
232
+
233
+ // 调整 aiContentWidget 位置
234
+ aiContentWidget?.setOptions({
235
+ position: {
236
+ lineNumber: endLineNumber + 1,
237
+ column: selection.startColumn,
238
+ },
239
+ });
240
+ aiContentWidget?.layoutContentWidget();
241
+
242
+ aiInlineChatDisposed.addDispose(
243
+ this.aiInlineChatService.onAccept(async (value) => {
244
+ // 采纳后在同级目录下新建测试文件
245
+ if (testUri) {
246
+ await this.fileTreeAPI.createFile(URI.parse(testUri.path), answer);
247
+ }
248
+
249
+ setTimeout(() => {
250
+ disposeAllWidget();
251
+ }, 110);
252
+ }),
253
+ );
254
+
255
+ aiInlineChatDisposed.addDispose(
256
+ this.aiInlineChatService.onDiscard((value) => {
257
+ setTimeout(() => {
258
+ disposeAllWidget();
259
+ }, 110);
260
+ }),
261
+ );
262
+ }
263
+
264
+ return;
265
+ }
266
+
267
+ if (value) {
268
+ this.aiInlineChatService.launchChatMessage(EChatStatus.THINKING);
269
+ const result = await this.aiGPTBackService.aiGPTcompletionRequest(
270
+ `${value}, 要求只回答代码内容,并保留代码的缩进。不需要给我解释。代码内容是: \n` + text,
271
+ );
272
+
273
+ // 说明接口有异常
274
+ if (result.errorCode !== 0) {
275
+ this.aiInlineChatService.launchChatMessage(EChatStatus.ERROR);
276
+ } else {
277
+ this.aiInlineChatService.launchChatMessage(EChatStatus.DONE);
278
+ }
279
+
280
+ this.logger.log('aiGPTcompletionRequest:>>> ', result);
281
+
282
+ let answer = result && result.data;
283
+
284
+ // 提取代码内容
285
+ const regex = /```\w*\s*([\s\S]+?)\s*```/;
286
+ const regExec = regex.exec(answer);
287
+ answer = (regExec && regExec[1]) || answer;
288
+
289
+ this.logger.log('aiGPTcompletionRequest:>>> refresh answer', answer);
290
+ if (answer) {
291
+ // 控制缩进
292
+ const indents = ' '.repeat(4);
293
+ const spcode = answer.split('\n');
294
+ answer = spcode.map((s, i) => (i === 0 ? s : indents + s)).join('\n');
295
+
296
+ aiDiffWidget = this.injector.get(AiDiffWidget, [monacoEditor!, text, answer]);
297
+ aiDiffWidget.create();
298
+ aiDiffWidget.showByLine(endLineNumber, selection.endLineNumber - selection.startLineNumber + 2);
299
+
300
+ // 调整 aiContentWidget 位置
301
+ aiContentWidget?.setOptions({
302
+ position: {
303
+ lineNumber: endLineNumber + 1,
304
+ column: selection.startColumn,
305
+ },
306
+ });
307
+ aiContentWidget?.layoutContentWidget();
308
+
309
+ aiInlineChatDisposed.addDispose(
310
+ this.aiInlineChatService.onAccept((value) => {
311
+ // monacoEditor.getModel()?.pushStackElement();
312
+ monacoEditor.getModel()?.pushEditOperations(
313
+ null,
314
+ [
315
+ {
316
+ range: selection,
317
+ text: answer,
318
+ },
319
+ ],
320
+ () => null,
321
+ );
322
+ // monacoEditor.getModel()?.pushStackElement();
323
+
324
+ setTimeout(() => {
325
+ disposeAllWidget();
326
+ }, 110);
327
+ }),
328
+ );
329
+
330
+ aiInlineChatDisposed.addDispose(
331
+ this.aiInlineChatService.onDiscard((value) => {
332
+ setTimeout(() => {
333
+ disposeAllWidget();
334
+ }, 110);
335
+ }),
336
+ );
337
+ }
338
+ }
339
+ }),
340
+ );
341
+ });
342
+
343
+ this.logger.log('AiEditorContribution:>>>', editor, monacoEditor);
344
+
345
+ return this;
346
+ }
347
+ provideEditorOptionsForUri?(uri: URI): MaybePromise<Partial<MonacoEditor.IEditorOptions>> {
348
+ throw new Error('Method not implemented.');
349
+ }
350
+
351
+ /**
352
+ * java doc
353
+ */
354
+ private async registerSuggestJavaDoc(editor: IEditor): Promise<void> {
355
+ const { monacoEditor, currentUri, currentDocumentModel } = editor;
356
+
357
+ if (currentUri && currentUri.codeUri.scheme !== 'file') {
358
+ return;
359
+ }
360
+
361
+ let inlayHintDispose: IDisposable | undefined;
362
+
363
+ this.disposables.push(
364
+ monacoEditor.onDidChangeModelContent((event) => {
365
+ const model = monacoEditor.getModel();
366
+ if (!model) {
367
+ return;
368
+ }
369
+
370
+ if (inlayHintDispose) {
371
+ inlayHintDispose.dispose();
372
+ }
373
+
374
+ const content = model.getValue();
375
+
376
+ // 使用正则表达式匹配所有 "/**" 的位置
377
+ const matches = content.matchAll(/\/\*\*/g);
378
+
379
+ // 存在 /** 的 position 集合
380
+ const hasKeyPosition: Position[] = [];
381
+
382
+ // 遍历匹配结果并输出位置信息
383
+ for (const match of matches) {
384
+ // const startPosition = model.getPositionAt(match.index!);
385
+ const endPosition = model.getPositionAt(match.index! + match[0].length);
386
+ hasKeyPosition.push(endPosition);
387
+ }
388
+
389
+ // @ts-ignore
390
+ const symbols = this.documentSymbolStore.getDocumentSymbol(model.uri!);
391
+
392
+ this.logger.log('documentSymbolStore: symbols>>> ', symbols);
393
+ const findRange = (range: Position) => {
394
+ if (!symbols) {
395
+ return { range: null };
396
+ }
397
+ return symbols
398
+ .map(
399
+ (obj) =>
400
+ (obj.range.startLineNumber === range.lineNumber ? obj : null) ||
401
+ (obj.children || []).find((child) => child.range.startLineNumber === range.lineNumber),
402
+ )
403
+ .filter(Boolean)[0];
404
+ };
405
+
406
+ if (hasKeyPosition.length > 0) {
407
+ // inlayHintDispose = monaco.languages.registerInlayHintsProvider(model.getLanguageId(), {
408
+ inlayHintDispose = monaco.languages.registerInlayHintsProvider(
409
+ {
410
+ language: model.getLanguageId(),
411
+ scheme: 'file',
412
+ },
413
+ {
414
+ provideInlayHints(model, range, token) {
415
+ return {
416
+ hints: hasKeyPosition.map((position) => ({
417
+ kind: monaco.languages.InlayHintKind.Parameter,
418
+ position: { column: position.column, lineNumber: position.lineNumber },
419
+ label: [
420
+ {
421
+ label: '✨ Suggest documentation',
422
+ command: {
423
+ id: 'ai.suggest.documentation',
424
+ title: '',
425
+ arguments: [findRange(position)?.range],
426
+ },
427
+ },
428
+ ],
429
+ paddingLeft: true,
430
+ })),
431
+ dispose: () => {},
432
+ };
433
+ },
434
+ },
435
+ );
436
+
437
+ this.disposables.push(inlayHintDispose);
438
+ }
439
+ }),
440
+ );
441
+ }
442
+
443
+ /**
444
+ * 代码补全
445
+ */
446
+ private async registerCompletion(editor: IEditor): Promise<void> {
447
+ const { monacoEditor, currentUri, currentDocumentModel } = editor;
448
+
449
+ if (currentUri && currentUri.codeUri.scheme !== 'file') {
450
+ return;
451
+ }
452
+
453
+ let dispose: IDisposable | undefined;
454
+
455
+ const cancelRequest = () => {
456
+ if (reqStack) {
457
+ reqStack.cancleRqe();
458
+ }
459
+ if (timer) {
460
+ clearTimeout(timer);
461
+ }
462
+ };
463
+
464
+ this.disposables.push(
465
+ monacoEditor.onDidChangeModel(() => {
466
+ if (dispose) {
467
+ dispose.dispose();
468
+ }
469
+ }),
470
+ );
471
+
472
+ const reqStack = new ReqStack();
473
+ let timer: any;
474
+
475
+ let isCancelFlag = false;
476
+
477
+ this.disposables.push(
478
+ Event.debounce(
479
+ monacoEditor.onDidChangeModelContent,
480
+ (_, e) => e,
481
+ 300,
482
+ )(async (event) => {
483
+ if (dispose) {
484
+ dispose.dispose();
485
+ }
486
+
487
+ const model = monacoEditor.getModel();
488
+ if (!model) {
489
+ return;
490
+ }
491
+
492
+ // 取光标的当前位置
493
+ const position = monacoEditor.getPosition();
494
+ if (!position) {
495
+ return;
496
+ }
497
+
498
+ cancelRequest();
499
+ dispose = monaco.languages.registerInlineCompletionsProvider(model.getLanguageId(), {
500
+ provideInlineCompletions: async (model, position, context, token) => {
501
+ // 补全上文
502
+ const startRange = new monaco.Range(0, 0, position.lineNumber, position.column);
503
+ let prompt = model.getValueInRange(startRange);
504
+
505
+ // 补全下文
506
+ const endRange = new monaco.Range(
507
+ position.lineNumber,
508
+ position.column,
509
+ model.getLineCount(),
510
+ Number.MAX_SAFE_INTEGER,
511
+ );
512
+ let suffix = model.getValueInRange(endRange);
513
+
514
+ prompt = prePromptHandler(prompt);
515
+ suffix = preSuffixHandler(suffix);
516
+
517
+ const uid = uuid();
518
+
519
+ const language = model.getLanguageId();
520
+
521
+ reqStack.addReq({
522
+ sendRequest: async () => {
523
+ isCancelFlag = false;
524
+ const completionResult = await this.aiGPTBackService.aiCompletionRequest({
525
+ prompt,
526
+ suffix,
527
+ sessionId: uid,
528
+ language,
529
+ fileUrl: model.uri.toString().split('/').pop(),
530
+ });
531
+
532
+ const items = completionResult.data.codeModelList;
533
+ this.logger.log('onDidChangeModelContent:>>> ai 补全返回结果', completionResult);
534
+ return {
535
+ items: items.map((data) => ({
536
+ insertText: data.content,
537
+ })),
538
+ };
539
+ },
540
+ cancelRequest: () => {
541
+ isCancelFlag = true;
542
+ },
543
+ });
544
+
545
+ await new Promise((f) => {
546
+ timer = setTimeout(f, 300);
547
+ });
548
+
549
+ this.logger.log('onDidChangeModelContent:>>> 参数', {
550
+ prompt,
551
+ suffix,
552
+ uid,
553
+ language,
554
+ });
555
+
556
+ return reqStack.runReq() || [];
557
+ },
558
+ freeInlineCompletions(completions: InlineCompletions<InlineCompletion>) {},
559
+ });
560
+ this.disposables.push(dispose);
561
+ }),
562
+ );
563
+ }
564
+ }