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