@opensumi/ide-ai-native 3.7.2-next-1739859371.0 → 3.7.2-next-1740013940.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 (243) hide show
  1. package/lib/browser/ai-core.contribution.d.ts +3 -0
  2. package/lib/browser/ai-core.contribution.d.ts.map +1 -1
  3. package/lib/browser/ai-core.contribution.js +68 -2
  4. package/lib/browser/ai-core.contribution.js.map +1 -1
  5. package/lib/browser/chat/chat-model.d.ts +2 -2
  6. package/lib/browser/chat/chat-model.d.ts.map +1 -1
  7. package/lib/browser/chat/chat-model.js +16 -5
  8. package/lib/browser/chat/chat-model.js.map +1 -1
  9. package/lib/browser/chat/chat-proxy.service.d.ts +4 -0
  10. package/lib/browser/chat/chat-proxy.service.d.ts.map +1 -1
  11. package/lib/browser/chat/chat-proxy.service.js +43 -0
  12. package/lib/browser/chat/chat-proxy.service.js.map +1 -1
  13. package/lib/browser/chat/chat.view.d.ts.map +1 -1
  14. package/lib/browser/chat/chat.view.js +29 -2
  15. package/lib/browser/chat/chat.view.js.map +1 -1
  16. package/lib/browser/components/ChatContext/ContextSelector.d.ts +12 -0
  17. package/lib/browser/components/ChatContext/ContextSelector.d.ts.map +1 -0
  18. package/lib/browser/components/ChatContext/ContextSelector.js +113 -0
  19. package/lib/browser/components/ChatContext/ContextSelector.js.map +1 -0
  20. package/lib/browser/components/ChatContext/index.d.ts +4 -0
  21. package/lib/browser/components/ChatContext/index.d.ts.map +1 -0
  22. package/lib/browser/components/ChatContext/index.js +84 -0
  23. package/lib/browser/components/ChatContext/index.js.map +1 -0
  24. package/lib/browser/components/ChatContext/style.module.less +189 -0
  25. package/lib/browser/components/ChatInput.d.ts.map +1 -1
  26. package/lib/browser/components/ChatInput.js.map +1 -1
  27. package/lib/browser/components/ChatReply.d.ts.map +1 -1
  28. package/lib/browser/components/ChatReply.js +25 -0
  29. package/lib/browser/components/ChatReply.js.map +1 -1
  30. package/lib/browser/components/ChatToolRender.d.ts +6 -0
  31. package/lib/browser/components/ChatToolRender.d.ts.map +1 -0
  32. package/lib/browser/components/ChatToolRender.js +53 -0
  33. package/lib/browser/components/ChatToolRender.js.map +1 -0
  34. package/lib/browser/components/ChatToolRender.module.less +86 -0
  35. package/lib/browser/components/components.module.less +32 -31
  36. package/lib/browser/components/utils.d.ts +2 -2
  37. package/lib/browser/context/llm-context.contribution.d.ts +7 -0
  38. package/lib/browser/context/llm-context.contribution.d.ts.map +1 -0
  39. package/lib/browser/context/llm-context.contribution.js +21 -0
  40. package/lib/browser/context/llm-context.contribution.js.map +1 -0
  41. package/lib/browser/context/llm-context.service.d.ts +24 -0
  42. package/lib/browser/context/llm-context.service.d.ts.map +1 -0
  43. package/lib/browser/context/llm-context.service.js +136 -0
  44. package/lib/browser/context/llm-context.service.js.map +1 -0
  45. package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.d.ts +2 -2
  46. package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.d.ts.map +1 -1
  47. package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.js.map +1 -1
  48. package/lib/browser/contrib/intelligent-completions/intelligent-completions.feature.registry.d.ts +4 -0
  49. package/lib/browser/contrib/intelligent-completions/intelligent-completions.feature.registry.d.ts.map +1 -1
  50. package/lib/browser/contrib/intelligent-completions/intelligent-completions.feature.registry.js +7 -0
  51. package/lib/browser/contrib/intelligent-completions/intelligent-completions.feature.registry.js.map +1 -1
  52. package/lib/browser/index.d.ts +11 -3
  53. package/lib/browser/index.d.ts.map +1 -1
  54. package/lib/browser/index.js +56 -3
  55. package/lib/browser/index.js.map +1 -1
  56. package/lib/browser/mcp/mcp-server-proxy.service.d.ts +25 -0
  57. package/lib/browser/mcp/mcp-server-proxy.service.d.ts.map +1 -0
  58. package/lib/browser/mcp/mcp-server-proxy.service.js +56 -0
  59. package/lib/browser/mcp/mcp-server-proxy.service.js.map +1 -0
  60. package/lib/browser/mcp/mcp-server.feature.registry.d.ts +16 -0
  61. package/lib/browser/mcp/mcp-server.feature.registry.d.ts.map +1 -0
  62. package/lib/browser/mcp/mcp-server.feature.registry.js +53 -0
  63. package/lib/browser/mcp/mcp-server.feature.registry.js.map +1 -0
  64. package/lib/browser/mcp/mcp-tools-dialog.module.less +44 -0
  65. package/lib/browser/mcp/mcp-tools-dialog.view.d.ts +8 -0
  66. package/lib/browser/mcp/mcp-tools-dialog.view.d.ts.map +1 -0
  67. package/lib/browser/mcp/mcp-tools-dialog.view.js +16 -0
  68. package/lib/browser/mcp/mcp-tools-dialog.view.js.map +1 -0
  69. package/lib/browser/mcp/tools/createNewFileWithText.d.ts +9 -0
  70. package/lib/browser/mcp/tools/createNewFileWithText.d.ts.map +1 -0
  71. package/lib/browser/mcp/tools/createNewFileWithText.js +83 -0
  72. package/lib/browser/mcp/tools/createNewFileWithText.js.map +1 -0
  73. package/lib/browser/mcp/tools/findFilesByNameSubstring.d.ts +9 -0
  74. package/lib/browser/mcp/tools/findFilesByNameSubstring.d.ts.map +1 -0
  75. package/lib/browser/mcp/tools/findFilesByNameSubstring.js +92 -0
  76. package/lib/browser/mcp/tools/findFilesByNameSubstring.js.map +1 -0
  77. package/lib/browser/mcp/tools/getCurrentFilePath.d.ts +8 -0
  78. package/lib/browser/mcp/tools/getCurrentFilePath.d.ts.map +1 -0
  79. package/lib/browser/mcp/tools/getCurrentFilePath.js +49 -0
  80. package/lib/browser/mcp/tools/getCurrentFilePath.js.map +1 -0
  81. package/lib/browser/mcp/tools/getDiagnosticsByPath.d.ts +10 -0
  82. package/lib/browser/mcp/tools/getDiagnosticsByPath.d.ts.map +1 -0
  83. package/lib/browser/mcp/tools/getDiagnosticsByPath.js +119 -0
  84. package/lib/browser/mcp/tools/getDiagnosticsByPath.js.map +1 -0
  85. package/lib/browser/mcp/tools/getFileTextByPath.d.ts +9 -0
  86. package/lib/browser/mcp/tools/getFileTextByPath.d.ts.map +1 -0
  87. package/lib/browser/mcp/tools/getFileTextByPath.js +97 -0
  88. package/lib/browser/mcp/tools/getFileTextByPath.js.map +1 -0
  89. package/lib/browser/mcp/tools/getOpenEditorFileDiagnostics.d.ts +11 -0
  90. package/lib/browser/mcp/tools/getOpenEditorFileDiagnostics.d.ts.map +1 -0
  91. package/lib/browser/mcp/tools/getOpenEditorFileDiagnostics.js +119 -0
  92. package/lib/browser/mcp/tools/getOpenEditorFileDiagnostics.js.map +1 -0
  93. package/lib/browser/mcp/tools/getOpenEditorFileText.d.ts +8 -0
  94. package/lib/browser/mcp/tools/getOpenEditorFileText.d.ts.map +1 -0
  95. package/lib/browser/mcp/tools/getOpenEditorFileText.js +50 -0
  96. package/lib/browser/mcp/tools/getOpenEditorFileText.js.map +1 -0
  97. package/lib/browser/mcp/tools/getSelectedText.d.ts +8 -0
  98. package/lib/browser/mcp/tools/getSelectedText.d.ts.map +1 -0
  99. package/lib/browser/mcp/tools/getSelectedText.js +57 -0
  100. package/lib/browser/mcp/tools/getSelectedText.js.map +1 -0
  101. package/lib/browser/mcp/tools/handlers/ListDir.d.ts +21 -0
  102. package/lib/browser/mcp/tools/handlers/ListDir.d.ts.map +1 -0
  103. package/lib/browser/mcp/tools/handlers/ListDir.js +112 -0
  104. package/lib/browser/mcp/tools/handlers/ListDir.js.map +1 -0
  105. package/lib/browser/mcp/tools/handlers/ReadFile.d.ts +47 -0
  106. package/lib/browser/mcp/tools/handlers/ReadFile.d.ts.map +1 -0
  107. package/lib/browser/mcp/tools/handlers/ReadFile.js +147 -0
  108. package/lib/browser/mcp/tools/handlers/ReadFile.js.map +1 -0
  109. package/lib/browser/mcp/tools/listDir.d.ts +8 -0
  110. package/lib/browser/mcp/tools/listDir.d.ts.map +1 -0
  111. package/lib/browser/mcp/tools/listDir.js +65 -0
  112. package/lib/browser/mcp/tools/listDir.js.map +1 -0
  113. package/lib/browser/mcp/tools/readFile.d.ts +8 -0
  114. package/lib/browser/mcp/tools/readFile.d.ts.map +1 -0
  115. package/lib/browser/mcp/tools/readFile.js +82 -0
  116. package/lib/browser/mcp/tools/readFile.js.map +1 -0
  117. package/lib/browser/mcp/tools/replaceOpenEditorFile.d.ts +8 -0
  118. package/lib/browser/mcp/tools/replaceOpenEditorFile.d.ts.map +1 -0
  119. package/lib/browser/mcp/tools/replaceOpenEditorFile.js +79 -0
  120. package/lib/browser/mcp/tools/replaceOpenEditorFile.js.map +1 -0
  121. package/lib/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.d.ts +8 -0
  122. package/lib/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.d.ts.map +1 -0
  123. package/lib/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.js +84 -0
  124. package/lib/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.js.map +1 -0
  125. package/lib/browser/mcp/tools/runTerminalCmd.d.ts +18 -0
  126. package/lib/browser/mcp/tools/runTerminalCmd.d.ts.map +1 -0
  127. package/lib/browser/mcp/tools/runTerminalCmd.js +96 -0
  128. package/lib/browser/mcp/tools/runTerminalCmd.js.map +1 -0
  129. package/lib/browser/preferences/schema.d.ts.map +1 -1
  130. package/lib/browser/preferences/schema.js +60 -0
  131. package/lib/browser/preferences/schema.js.map +1 -1
  132. package/lib/browser/types.d.ts +64 -3
  133. package/lib/browser/types.d.ts.map +1 -1
  134. package/lib/browser/types.js +5 -1
  135. package/lib/browser/types.js.map +1 -1
  136. package/lib/browser/widget/inline-chat/inline-chat-editor.controller.js +1 -1
  137. package/lib/browser/widget/inline-chat/inline-chat-editor.controller.js.map +1 -1
  138. package/lib/browser/widget/inline-diff/inline-diff.controller.d.ts.map +1 -1
  139. package/lib/browser/widget/inline-input/inline-input.controller.d.ts.map +1 -1
  140. package/lib/common/index.d.ts +9 -0
  141. package/lib/common/index.d.ts.map +1 -1
  142. package/lib/common/index.js +4 -1
  143. package/lib/common/index.js.map +1 -1
  144. package/lib/common/llm-context.d.ts +37 -0
  145. package/lib/common/llm-context.d.ts.map +1 -0
  146. package/lib/common/llm-context.js +5 -0
  147. package/lib/common/llm-context.js.map +1 -0
  148. package/lib/common/mcp-server-manager.d.ts +40 -0
  149. package/lib/common/mcp-server-manager.d.ts.map +1 -0
  150. package/lib/common/mcp-server-manager.js +6 -0
  151. package/lib/common/mcp-server-manager.js.map +1 -0
  152. package/lib/common/tool-invocation-registry.d.ts +91 -0
  153. package/lib/common/tool-invocation-registry.d.ts.map +1 -0
  154. package/lib/common/tool-invocation-registry.js +90 -0
  155. package/lib/common/tool-invocation-registry.js.map +1 -0
  156. package/lib/common/types.d.ts +17 -0
  157. package/lib/common/types.d.ts.map +1 -1
  158. package/lib/node/anthropic/anthropic-language-model.d.ts +9 -0
  159. package/lib/node/anthropic/anthropic-language-model.d.ts.map +1 -0
  160. package/lib/node/anthropic/anthropic-language-model.js +26 -0
  161. package/lib/node/anthropic/anthropic-language-model.js.map +1 -0
  162. package/lib/node/base-language-model.d.ts +14 -0
  163. package/lib/node/base-language-model.d.ts.map +1 -0
  164. package/lib/node/base-language-model.js +136 -0
  165. package/lib/node/base-language-model.js.map +1 -0
  166. package/lib/node/deepseek/deepseek-language-model.d.ts +9 -0
  167. package/lib/node/deepseek/deepseek-language-model.d.ts.map +1 -0
  168. package/lib/node/deepseek/deepseek-language-model.js +26 -0
  169. package/lib/node/deepseek/deepseek-language-model.js.map +1 -0
  170. package/lib/node/index.d.ts.map +1 -1
  171. package/lib/node/index.js +19 -0
  172. package/lib/node/index.js.map +1 -1
  173. package/lib/node/mcp/sumi-mcp-server.d.ts +91 -0
  174. package/lib/node/mcp/sumi-mcp-server.d.ts.map +1 -0
  175. package/lib/node/mcp/sumi-mcp-server.js +172 -0
  176. package/lib/node/mcp/sumi-mcp-server.js.map +1 -0
  177. package/lib/node/mcp-server-manager-impl.d.ts +27 -0
  178. package/lib/node/mcp-server-manager-impl.d.ts.map +1 -0
  179. package/lib/node/mcp-server-manager-impl.js +127 -0
  180. package/lib/node/mcp-server-manager-impl.js.map +1 -0
  181. package/lib/node/mcp-server.d.ts +207 -0
  182. package/lib/node/mcp-server.d.ts.map +1 -0
  183. package/lib/node/mcp-server.js +91 -0
  184. package/lib/node/mcp-server.js.map +1 -0
  185. package/lib/node/openai/openai-language-model.d.ts +9 -0
  186. package/lib/node/openai/openai-language-model.d.ts.map +1 -0
  187. package/lib/node/openai/openai-language-model.js +29 -0
  188. package/lib/node/openai/openai-language-model.js.map +1 -0
  189. package/package.json +34 -22
  190. package/src/browser/ai-core.contribution.ts +77 -1
  191. package/src/browser/chat/chat-model.ts +24 -6
  192. package/src/browser/chat/chat-proxy.service.ts +42 -0
  193. package/src/browser/chat/chat.view.tsx +59 -6
  194. package/src/browser/components/ChatContext/ContextSelector.tsx +177 -0
  195. package/src/browser/components/ChatContext/index.tsx +135 -0
  196. package/src/browser/components/ChatContext/style.module.less +189 -0
  197. package/src/browser/components/ChatInput.tsx +1 -0
  198. package/src/browser/components/ChatReply.tsx +32 -0
  199. package/src/browser/components/ChatToolRender.module.less +86 -0
  200. package/src/browser/components/ChatToolRender.tsx +77 -0
  201. package/src/browser/components/components.module.less +32 -31
  202. package/src/browser/context/llm-context.contribution.ts +14 -0
  203. package/src/browser/context/llm-context.service.ts +156 -0
  204. package/src/browser/contrib/intelligent-completions/intelligent-completions.controller.ts +2 -3
  205. package/src/browser/contrib/intelligent-completions/intelligent-completions.feature.registry.ts +11 -0
  206. package/src/browser/index.ts +68 -4
  207. package/src/browser/mcp/mcp-server-proxy.service.ts +53 -0
  208. package/src/browser/mcp/mcp-server.feature.registry.ts +54 -0
  209. package/src/browser/mcp/mcp-tools-dialog.module.less +44 -0
  210. package/src/browser/mcp/mcp-tools-dialog.view.tsx +24 -0
  211. package/src/browser/mcp/tools/createNewFileWithText.ts +83 -0
  212. package/src/browser/mcp/tools/findFilesByNameSubstring.ts +93 -0
  213. package/src/browser/mcp/tools/getCurrentFilePath.ts +49 -0
  214. package/src/browser/mcp/tools/getDiagnosticsByPath.ts +123 -0
  215. package/src/browser/mcp/tools/getFileTextByPath.ts +97 -0
  216. package/src/browser/mcp/tools/getOpenEditorFileDiagnostics.ts +121 -0
  217. package/src/browser/mcp/tools/getOpenEditorFileText.ts +50 -0
  218. package/src/browser/mcp/tools/getSelectedText.ts +57 -0
  219. package/src/browser/mcp/tools/handlers/ListDir.ts +117 -0
  220. package/src/browser/mcp/tools/handlers/ReadFile.ts +174 -0
  221. package/src/browser/mcp/tools/listDir.ts +66 -0
  222. package/src/browser/mcp/tools/readFile.ts +82 -0
  223. package/src/browser/mcp/tools/replaceOpenEditorFile.ts +80 -0
  224. package/src/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.ts +91 -0
  225. package/src/browser/mcp/tools/runTerminalCmd.ts +107 -0
  226. package/src/browser/preferences/schema.ts +60 -0
  227. package/src/browser/types.ts +92 -3
  228. package/src/browser/widget/inline-chat/inline-chat-editor.controller.ts +1 -1
  229. package/src/browser/widget/inline-diff/inline-diff.controller.ts +1 -1
  230. package/src/browser/widget/inline-input/inline-input.controller.ts +1 -1
  231. package/src/common/index.ts +14 -0
  232. package/src/common/llm-context.ts +41 -0
  233. package/src/common/mcp-server-manager.ts +46 -0
  234. package/src/common/tool-invocation-registry.ts +170 -0
  235. package/src/common/types.ts +22 -0
  236. package/src/node/anthropic/anthropic-language-model.ts +25 -0
  237. package/src/node/base-language-model.ts +163 -0
  238. package/src/node/deepseek/deepseek-language-model.ts +25 -0
  239. package/src/node/index.ts +21 -0
  240. package/src/node/mcp/sumi-mcp-server.ts +197 -0
  241. package/src/node/mcp-server-manager-impl.ts +148 -0
  242. package/src/node/mcp-server.ts +126 -0
  243. package/src/node/openai/openai-language-model.ts +25 -0
@@ -0,0 +1,156 @@
1
+ import { Autowired, Injectable } from '@opensumi/di';
2
+ import { AppConfig } from '@opensumi/ide-core-browser/lib/react-providers/config-provider';
3
+ import { WithEventBus } from '@opensumi/ide-core-common/lib/event-bus/event-decorator';
4
+ import { MarkerSeverity } from '@opensumi/ide-core-common/lib/types/markers/markers';
5
+ import { Emitter, URI } from '@opensumi/ide-core-common/lib/utils';
6
+ import {
7
+ EditorDocumentModelCreationEvent,
8
+ EditorDocumentModelRemovalEvent,
9
+ EditorDocumentModelSavedEvent,
10
+ IEditorDocumentModelService,
11
+ } from '@opensumi/ide-editor/lib/browser/doc-model/types';
12
+ import { EditorSelectionChangeEvent } from '@opensumi/ide-editor/lib/browser/types';
13
+ import { IMarkerService } from '@opensumi/ide-markers/lib/common/types';
14
+
15
+ import { FileContext, LLMContextService, SerializedContext } from '../../common/llm-context';
16
+
17
+ @Injectable()
18
+ export class LLMContextServiceImpl extends WithEventBus implements LLMContextService {
19
+ @Autowired(AppConfig)
20
+ protected readonly appConfig: AppConfig;
21
+
22
+ @Autowired(IEditorDocumentModelService)
23
+ protected readonly docModelManager: IEditorDocumentModelService;
24
+
25
+ @Autowired(IMarkerService)
26
+ protected readonly markerService: IMarkerService;
27
+
28
+ private isAutoCollecting = false;
29
+
30
+ private contextFiles: Map<string, FileContext> = new Map();
31
+
32
+ private onDidContextFilesChangeEmitter = new Emitter<FileContext[]>();
33
+ onDidContextFilesChangeEvent = this.onDidContextFilesChangeEmitter.event;
34
+
35
+ addFileToContext(uri: URI, selection?: [number, number], isManual = true): void {
36
+ this.contextFiles.set(uri.toString(), {
37
+ uri,
38
+ selection,
39
+ isManual,
40
+ });
41
+ this.onDidContextFilesChangeEmitter.fire(this.getAllContextFiles());
42
+ }
43
+
44
+ cleanFileContext() {
45
+ this.contextFiles.clear();
46
+ this.onDidContextFilesChangeEmitter.fire(this.getAllContextFiles());
47
+ }
48
+
49
+ private getAllContextFiles() {
50
+ return Array.from(this.contextFiles.values());
51
+ }
52
+
53
+ removeFileFromContext(uri: URI): void {
54
+ this.contextFiles.delete(uri.toString());
55
+ this.onDidContextFilesChangeEmitter.fire(this.getAllContextFiles());
56
+ }
57
+
58
+ startAutoCollection(): void {
59
+ if (this.isAutoCollecting) {
60
+ return;
61
+ }
62
+ this.isAutoCollecting = true;
63
+
64
+ this.startAutoCollectionInternal();
65
+ }
66
+
67
+ private startAutoCollectionInternal(): void {
68
+ // 文件打开
69
+ this.disposables.push(
70
+ this.eventBus.on(EditorDocumentModelCreationEvent, (event) => {
71
+ if (event.payload.uri.scheme !== 'file') {
72
+ return;
73
+ }
74
+ // TODO: 是否自动添加文件到上下文?
75
+ // this.addFileToContext(event.payload.uri);
76
+ }),
77
+ );
78
+
79
+ // 删除
80
+ this.disposables.push(
81
+ this.eventBus.on(EditorDocumentModelRemovalEvent, (event) => {
82
+ if (event.payload.scheme !== 'file') {
83
+ return;
84
+ }
85
+ }),
86
+ );
87
+
88
+ // 保存
89
+ this.disposables.push(
90
+ this.eventBus.on(EditorDocumentModelSavedEvent, (event) => {
91
+ if (event.payload.scheme !== 'file') {
92
+ return;
93
+ }
94
+ }),
95
+ );
96
+
97
+ // 光标选中
98
+ this.disposables.push(
99
+ this.eventBus.on(EditorSelectionChangeEvent, (event) => {
100
+ if (event.payload.selections.length > 0) {
101
+ const selection = [
102
+ event.payload.selections[0].selectionStartLineNumber,
103
+ event.payload.selections[0].positionLineNumber,
104
+ ].sort() as [number, number];
105
+ if (selection[0] === selection[1]) {
106
+ // TODO: 是否自动添加文件到上下文?
107
+ // this.addFileToContext(event.payload.editorUri, undefined);
108
+ } else {
109
+ this.addFileToContext(
110
+ event.payload.editorUri,
111
+ selection.sort((a, b) => a - b),
112
+ );
113
+ }
114
+ }
115
+ }),
116
+ );
117
+ }
118
+
119
+ stopAutoCollection(): void {
120
+ this.dispose();
121
+ }
122
+
123
+ serialize(): SerializedContext {
124
+ const files = this.getAllContextFiles();
125
+ const recentlyViewFiles = files
126
+ .filter((v) => !v.selection)
127
+ .map((file) => URI.file(this.appConfig.workspaceDir).relative(file.uri)!.toString())
128
+ .filter(Boolean);
129
+ const attachedFiles = files
130
+ .filter((v) => v.selection)
131
+ .map((file) => {
132
+ const ref = this.docModelManager.getModelReference(file.uri);
133
+ const content = ref!.instance.getText();
134
+ const lineErrors = this.markerService
135
+ .getManager()
136
+ .getMarkers({
137
+ resource: file.uri.toString(),
138
+ severities: MarkerSeverity.Error,
139
+ })
140
+ .map((marker) => marker.message);
141
+
142
+ return {
143
+ content,
144
+ lineErrors,
145
+ path: URI.file(this.appConfig.workspaceDir).relative(file.uri)!.toString(),
146
+ language: ref?.instance.languageId!,
147
+ };
148
+ })
149
+ .filter(Boolean);
150
+
151
+ return {
152
+ recentlyViewFiles,
153
+ attachedFiles,
154
+ };
155
+ }
156
+ }
@@ -40,7 +40,7 @@ import { InlineCompletionsController } from '@opensumi/monaco-editor-core/esm/vs
40
40
  import {
41
41
  SuggestItemInfo,
42
42
  SuggestWidgetAdaptor,
43
- } from '@opensumi/monaco-editor-core/esm/vs/editor/contrib/inlineCompletions/browser/model/suggestWidgetAdaptor';
43
+ } from '@opensumi/monaco-editor-core/esm/vs/editor/contrib/inlineCompletions/browser/model/suggestWidgetAdapter';
44
44
  import { ContextKeyExpr } from '@opensumi/monaco-editor-core/esm/vs/platform/contextkey/common/contextkey';
45
45
 
46
46
  import { AINativeContextKey } from '../../ai-core.contextkeys';
@@ -166,8 +166,7 @@ export class IntelligentCompletionsController extends BaseAIMonacoEditorControll
166
166
  model?.inlineCompletionState.read(reader);
167
167
 
168
168
  const suggestWidgetSelectedItem = inlineCompletionsController['_suggestWidgetSelectedItem'] as IObservable<
169
- SuggestItemInfo | undefined,
170
- unknown
169
+ SuggestItemInfo | undefined
171
170
  >;
172
171
  const selectedItem = suggestWidgetSelectedItem.get();
173
172
  if (selectedItem) {
@@ -1,5 +1,6 @@
1
1
  import { Injectable } from '@opensumi/di';
2
2
  import { Disposable } from '@opensumi/ide-core-common';
3
+ import { InlineEditProvider } from '@opensumi/ide-monaco';
3
4
 
4
5
  import { ICodeEditsProvider, IIntelligentCompletionProvider, IIntelligentCompletionsRegistry } from '../../types';
5
6
 
@@ -7,6 +8,7 @@ import { ICodeEditsProvider, IIntelligentCompletionProvider, IIntelligentComplet
7
8
  export class IntelligentCompletionsRegistry extends Disposable implements IIntelligentCompletionsRegistry {
8
9
  private inlineCompletionsProvider: IIntelligentCompletionProvider | undefined;
9
10
  private codeEditsProvider: ICodeEditsProvider | undefined;
11
+ private inlineEditProvider: InlineEditProvider | undefined;
10
12
 
11
13
  registerIntelligentCompletionProvider(provider: IIntelligentCompletionProvider): void {
12
14
  this.inlineCompletionsProvider = provider;
@@ -16,6 +18,10 @@ export class IntelligentCompletionsRegistry extends Disposable implements IIntel
16
18
  this.inlineCompletionsProvider = provider;
17
19
  }
18
20
 
21
+ registerInlineEditProvider(provider: InlineEditProvider): void {
22
+ this.inlineEditProvider = provider;
23
+ }
24
+
19
25
  registerCodeEditsProvider(provider: ICodeEditsProvider): void {
20
26
  this.codeEditsProvider = provider;
21
27
  }
@@ -27,4 +33,9 @@ export class IntelligentCompletionsRegistry extends Disposable implements IIntel
27
33
  getCodeEditsProvider(): ICodeEditsProvider | undefined {
28
34
  return this.codeEditsProvider;
29
35
  }
36
+
37
+ getInlineEditProvider(): InlineEditProvider | undefined {
38
+ // TODO: 支持模块内调用
39
+ return this.inlineEditProvider;
40
+ }
30
41
  }
@@ -19,8 +19,17 @@ import {
19
19
  TerminalRegistryToken,
20
20
  } from '@opensumi/ide-core-common';
21
21
 
22
- import { ChatProxyServiceToken, IChatAgentService, IChatInternalService, IChatManagerService } from '../common';
23
- import { IAIInlineCompletionsProvider } from '../common';
22
+ import {
23
+ ChatProxyServiceToken,
24
+ IAIInlineCompletionsProvider,
25
+ IChatAgentService,
26
+ IChatInternalService,
27
+ IChatManagerService,
28
+ SumiMCPServerProxyServicePath,
29
+ TokenMCPServerProxyService,
30
+ } from '../common';
31
+ import { LLMContextServiceToken } from '../common/llm-context';
32
+ import { MCPServerManager, MCPServerManagerPath } from '../common/mcp-server-manager';
24
33
 
25
34
  import { AINativeBrowserContribution } from './ai-core.contribution';
26
35
  import { ChatAgentService } from './chat/chat-agent.service';
@@ -31,6 +40,8 @@ import { ChatService } from './chat/chat.api.service';
31
40
  import { ChatFeatureRegistry } from './chat/chat.feature.registry';
32
41
  import { ChatInternalService } from './chat/chat.internal.service';
33
42
  import { ChatRenderRegistry } from './chat/chat.render.registry';
43
+ import { LlmContextContribution } from './context/llm-context.contribution';
44
+ import { LLMContextServiceImpl } from './context/llm-context.service';
34
45
  import { AICodeActionContribution } from './contrib/code-action/code-action.contribution';
35
46
  import { AIInlineCompletionsProvider } from './contrib/inline-completions/completeProvider';
36
47
  import { IntelligentCompletionsContribution } from './contrib/intelligent-completions/intelligent-completions.contribution';
@@ -43,8 +54,22 @@ import { RenameCandidatesProviderRegistry } from './contrib/rename/rename.featur
43
54
  import { TerminalAIContribution } from './contrib/terminal/terminal-ai.contributon';
44
55
  import { TerminalFeatureRegistry } from './contrib/terminal/terminal.feature.registry';
45
56
  import { LanguageParserService } from './languages/service';
57
+ import { MCPServerProxyService } from './mcp/mcp-server-proxy.service';
58
+ import { MCPServerRegistry } from './mcp/mcp-server.feature.registry';
59
+ import { CreateNewFileWithTextTool } from './mcp/tools/createNewFileWithText';
60
+ import { FindFilesByNameSubstringTool } from './mcp/tools/findFilesByNameSubstring';
61
+ import { GetCurrentFilePathTool } from './mcp/tools/getCurrentFilePath';
62
+ import { GetDiagnosticsByPathTool } from './mcp/tools/getDiagnosticsByPath';
63
+ import { GetFileTextByPathTool } from './mcp/tools/getFileTextByPath';
64
+ import { GetOpenEditorFileDiagnosticsTool } from './mcp/tools/getOpenEditorFileDiagnostics';
65
+ import { GetOpenEditorFileTextTool } from './mcp/tools/getOpenEditorFileText';
66
+ import { GetSelectedTextTool } from './mcp/tools/getSelectedText';
67
+ import { ListDirTool } from './mcp/tools/listDir';
68
+ import { ReadFileTool } from './mcp/tools/readFile';
69
+ import { ReplaceOpenEditorFileByDiffPreviewerTool } from './mcp/tools/replaceOpenEditorFileByDiffPreviewer';
70
+ import { RunTerminalCommandTool } from './mcp/tools/runTerminalCmd';
46
71
  import { AINativePreferencesContribution } from './preferences';
47
- import { AINativeCoreContribution } from './types';
72
+ import { AINativeCoreContribution, MCPServerContribution, TokenMCPServerRegistry } from './types';
48
73
  import { InlineChatFeatureRegistry } from './widget/inline-chat/inline-chat.feature.registry';
49
74
  import { InlineChatService } from './widget/inline-chat/inline-chat.service';
50
75
  import { InlineDiffService } from './widget/inline-diff';
@@ -59,7 +84,7 @@ export class AINativeModule extends BrowserModule {
59
84
  this.aiNativeConfig.setAINativeModuleLoaded(true);
60
85
  }
61
86
 
62
- contributionProvider = AINativeCoreContribution;
87
+ contributionProvider = [AINativeCoreContribution, MCPServerContribution];
63
88
  providers: Provider[] = [
64
89
  AINativeBrowserContribution,
65
90
  InterfaceNavigationContribution,
@@ -68,6 +93,37 @@ export class AINativeModule extends BrowserModule {
68
93
  AICodeActionContribution,
69
94
  AINativePreferencesContribution,
70
95
  IntelligentCompletionsContribution,
96
+
97
+ // MCP Server Contributions START
98
+ ListDirTool,
99
+ ReadFileTool,
100
+ CreateNewFileWithTextTool,
101
+ GetSelectedTextTool,
102
+ GetOpenEditorFileDiagnosticsTool,
103
+ GetOpenEditorFileTextTool,
104
+ GetFileTextByPathTool,
105
+ GetCurrentFilePathTool,
106
+ FindFilesByNameSubstringTool,
107
+ GetDiagnosticsByPathTool,
108
+ RunTerminalCommandTool,
109
+ ReplaceOpenEditorFileByDiffPreviewerTool,
110
+ // MCP Server Contributions END
111
+
112
+ // Context Service
113
+ LlmContextContribution,
114
+ {
115
+ token: LLMContextServiceToken,
116
+ useClass: LLMContextServiceImpl,
117
+ },
118
+
119
+ {
120
+ token: TokenMCPServerRegistry,
121
+ useClass: MCPServerRegistry,
122
+ },
123
+ {
124
+ token: TokenMCPServerProxyService,
125
+ useClass: MCPServerProxyService,
126
+ },
71
127
  {
72
128
  token: InlineChatFeatureRegistryToken,
73
129
  useClass: InlineChatFeatureRegistry,
@@ -148,5 +204,13 @@ export class AINativeModule extends BrowserModule {
148
204
  token: AIBackSerivceToken,
149
205
  clientToken: ChatProxyServiceToken,
150
206
  },
207
+ {
208
+ servicePath: MCPServerManagerPath,
209
+ token: MCPServerManager,
210
+ },
211
+ {
212
+ clientToken: TokenMCPServerProxyService,
213
+ servicePath: SumiMCPServerProxyServicePath,
214
+ },
151
215
  ];
152
216
  }
@@ -0,0 +1,53 @@
1
+ import { Autowired, Injectable } from '@opensumi/di';
2
+ import { ILogger } from '@opensumi/ide-core-browser';
3
+ import { Emitter, Event } from '@opensumi/ide-core-common';
4
+
5
+ import { ISumiMCPServerBackend, SumiMCPServerProxyServicePath } from '../../common';
6
+ import { IMCPServerProxyService } from '../../common/types';
7
+ import { IMCPServerRegistry, TokenMCPServerRegistry } from '../types';
8
+
9
+ @Injectable()
10
+ export class MCPServerProxyService implements IMCPServerProxyService {
11
+ @Autowired(TokenMCPServerRegistry)
12
+ private readonly mcpServerRegistry: IMCPServerRegistry;
13
+
14
+ @Autowired(ILogger)
15
+ private readonly logger: ILogger;
16
+
17
+ @Autowired(SumiMCPServerProxyServicePath)
18
+ private readonly sumiMCPServerProxyService: ISumiMCPServerBackend;
19
+
20
+ private readonly _onChangeMCPServers = new Emitter<any>();
21
+ public readonly onChangeMCPServers: Event<any> = this._onChangeMCPServers.event;
22
+
23
+ // 调用 OpenSumi 内部注册的 MCP 工具
24
+ $callMCPTool(name: string, args: any) {
25
+ return this.mcpServerRegistry.callMCPTool(name, args);
26
+ }
27
+
28
+ // 获取 OpenSumi 内部注册的 MCP tools
29
+ async $getMCPTools() {
30
+ const tools = await this.mcpServerRegistry.getMCPTools().map((tool) =>
31
+ // 不要传递 handler
32
+ ({
33
+ name: tool.name,
34
+ description: tool.description,
35
+ inputSchema: tool.inputSchema,
36
+ providerName: 'sumi-builtin',
37
+ }),
38
+ );
39
+
40
+ this.logger.log('SUMI MCP tools', tools);
41
+
42
+ return tools;
43
+ }
44
+
45
+ // 通知前端 MCP 服务注册表发生了变化
46
+ async $updateMCPServers() {
47
+ this._onChangeMCPServers.fire('update');
48
+ }
49
+
50
+ async getAllMCPTools() {
51
+ return this.sumiMCPServerProxyService.getAllMCPTools();
52
+ }
53
+ }
@@ -0,0 +1,54 @@
1
+ // OpenSumi as MCP Server 前端的代理服务
2
+ import { Autowired, Injectable } from '@opensumi/di';
3
+ import { IAIBackService, ILogger } from '@opensumi/ide-core-common';
4
+
5
+ import { IMCPServerRegistry, MCPLogger, MCPToolDefinition } from '../types';
6
+
7
+ class LoggerAdapter implements MCPLogger {
8
+ constructor(private readonly logger: ILogger) { }
9
+
10
+ appendLine(message: string): void {
11
+ this.logger.log(message);
12
+ }
13
+ }
14
+
15
+ @Injectable()
16
+ export class MCPServerRegistry implements IMCPServerRegistry {
17
+ private tools: MCPToolDefinition[] = [];
18
+
19
+ @Autowired(ILogger)
20
+ private readonly baseLogger: ILogger;
21
+
22
+ private get logger(): MCPLogger {
23
+ return new LoggerAdapter(this.baseLogger);
24
+ }
25
+
26
+ registerMCPTool(tool: MCPToolDefinition): void {
27
+ this.tools.push(tool);
28
+ }
29
+
30
+ getMCPTools(): MCPToolDefinition[] {
31
+ return this.tools;
32
+ }
33
+
34
+ async callMCPTool(
35
+ name: string,
36
+ args: any,
37
+ ): Promise<{
38
+ content: { type: string; text: string }[];
39
+ isError?: boolean;
40
+ }> {
41
+ try {
42
+ const tool = this.tools.find((tool) => tool.name === name);
43
+ if (!tool) {
44
+ throw new Error(`MCP tool ${name} not found`);
45
+ }
46
+ return await tool.handler(args, this.logger);
47
+ } catch (error) {
48
+ return {
49
+ content: [{ type: 'text', text: `The tool ${name} failed to execute. Error: ${error}` }],
50
+ isError: true,
51
+ };
52
+ }
53
+ }
54
+ }
@@ -0,0 +1,44 @@
1
+ .mcp_tools_dialog {
2
+ .dialog_title {
3
+ font-size: 16px;
4
+ font-weight: 600;
5
+ color: var(--foreground);
6
+ padding-bottom: 16px;
7
+ padding-top: 8px;
8
+ border-bottom: 1px solid var(--menu-separatorBackground);
9
+ }
10
+
11
+ .tools_list {
12
+ max-height: calc(60vh - 53px); // 减去标题高度
13
+ overflow: auto;
14
+
15
+ .tool_item {
16
+ padding-top: 12px;
17
+ padding-bottom: 12px;
18
+ border-radius: 6px;
19
+
20
+ &:hover {
21
+ background-color: var(--list-hoverBackground);
22
+ }
23
+
24
+ .tool_name {
25
+ font-weight: 600;
26
+ color: var(--foreground);
27
+ margin-bottom: 8px;
28
+ }
29
+
30
+ .tool_description {
31
+ font-size: 12px;
32
+ line-height: 1.5;
33
+ color: var(--descriptionForeground);
34
+ margin-bottom: 4px;
35
+ }
36
+
37
+ .tool_provider {
38
+ font-size: 12px;
39
+ color: var(--descriptionForeground);
40
+ font-style: italic;
41
+ }
42
+ }
43
+ }
44
+ }
@@ -0,0 +1,24 @@
1
+ import * as React from 'react';
2
+
3
+ import { MCPTool } from '../../common/types';
4
+
5
+ import styles from './mcp-tools-dialog.module.less';
6
+
7
+ interface MCPToolsDialogProps {
8
+ tools: MCPTool[];
9
+ }
10
+
11
+ export const MCPToolsDialog: React.FC<MCPToolsDialogProps> = ({ tools }) => (
12
+ <div className={styles.mcp_tools_dialog}>
13
+ <div className={styles.dialog_title}>MCP Tools</div>
14
+ <div className={styles.tools_list}>
15
+ {tools.map((tool) => (
16
+ <div key={tool.name} className={styles.tool_item}>
17
+ <div className={styles.tool_name}>{tool.name}</div>
18
+ <div className={styles.tool_description}>{tool.description}</div>
19
+ {tool.providerName && <div className={styles.tool_provider}>Provider: {tool.providerName}</div>}
20
+ </div>
21
+ ))}
22
+ </div>
23
+ </div>
24
+ );
@@ -0,0 +1,83 @@
1
+ import { z } from 'zod';
2
+ import { zodToJsonSchema } from 'zod-to-json-schema';
3
+
4
+ import { Autowired } from '@opensumi/di';
5
+ import { Domain, URI, path } from '@opensumi/ide-core-common';
6
+ import { IFileServiceClient } from '@opensumi/ide-file-service';
7
+ import { IWorkspaceService } from '@opensumi/ide-workspace';
8
+
9
+ import { IMCPServerRegistry, MCPLogger, MCPServerContribution, MCPToolDefinition } from '../../types';
10
+
11
+ const inputSchema = z.object({
12
+ pathInProject: z.string().describe('The relative path where the file should be created'),
13
+ text: z.string().describe('The content to write into the new file'),
14
+ });
15
+
16
+ @Domain(MCPServerContribution)
17
+ export class CreateNewFileWithTextTool implements MCPServerContribution {
18
+ @Autowired(IWorkspaceService)
19
+ private readonly workspaceService: IWorkspaceService;
20
+
21
+ @Autowired(IFileServiceClient)
22
+ private readonly fileService: IFileServiceClient;
23
+
24
+ registerMCPServer(registry: IMCPServerRegistry): void {
25
+ registry.registerMCPTool(this.getToolDefinition());
26
+ }
27
+
28
+ getToolDefinition(): MCPToolDefinition {
29
+ return {
30
+ name: 'create_new_file_with_text',
31
+ description:
32
+ 'Creates a new file at the specified path within the project directory and populates it with the provided text. ' +
33
+ 'Use this tool to generate new files in your project structure. ' +
34
+ 'Requires two parameters: ' +
35
+ '- pathInProject: The relative path where the file should be created ' +
36
+ '- text: The content to write into the new file ' +
37
+ 'Returns one of two possible responses: ' +
38
+ '"ok" if the file was successfully created and populated, ' +
39
+ '"can\'t find project dir" if the project directory cannot be determined. ' +
40
+ 'Note: Creates any necessary parent directories automatically.',
41
+ inputSchema: zodToJsonSchema(inputSchema),
42
+ handler: this.handler.bind(this),
43
+ };
44
+ }
45
+
46
+ private async handler(args: z.infer<typeof inputSchema>, logger: MCPLogger) {
47
+ try {
48
+ // 获取工作区根目录
49
+ const workspaceRoots = this.workspaceService.tryGetRoots();
50
+ if (!workspaceRoots || workspaceRoots.length === 0) {
51
+ logger.appendLine('Error: Cannot determine project directory');
52
+ return {
53
+ content: [{ type: 'text', text: "can't find project dir" }],
54
+ isError: true,
55
+ };
56
+ }
57
+
58
+ // 构建完整的文件路径
59
+ const rootUri = URI.parse(workspaceRoots[0].uri);
60
+ const fullPath = path.join(rootUri.codeUri.fsPath, args.pathInProject);
61
+ const fileUri = URI.file(fullPath);
62
+
63
+ // 创建父目录
64
+ const parentDir = path.dirname(fullPath);
65
+ const parentUri = URI.file(parentDir);
66
+ await this.fileService.createFolder(parentUri.toString());
67
+
68
+ // 写入文件内容
69
+ await this.fileService.createFile(fileUri.toString(), { content: args.text });
70
+
71
+ logger.appendLine(`Successfully created file at: ${args.pathInProject}`);
72
+ return {
73
+ content: [{ type: 'text', text: 'ok' }],
74
+ };
75
+ } catch (error) {
76
+ logger.appendLine(`Error during file creation: ${error}`);
77
+ return {
78
+ content: [{ type: 'text', text: 'unknown error' }],
79
+ isError: true,
80
+ };
81
+ }
82
+ }
83
+ }
@@ -0,0 +1,93 @@
1
+ import * as path from 'path';
2
+
3
+ import { z } from 'zod';
4
+ import { zodToJsonSchema } from 'zod-to-json-schema';
5
+
6
+ import { Autowired, Injectable } from '@opensumi/di';
7
+ import { Domain, URI } from '@opensumi/ide-core-common';
8
+ import { IFileSearchService } from '@opensumi/ide-file-search/lib/common';
9
+ import { IWorkspaceService } from '@opensumi/ide-workspace';
10
+
11
+ import { IMCPServerRegistry, MCPLogger, MCPServerContribution, MCPToolDefinition } from '../../types';
12
+
13
+ const inputSchema = z.object({
14
+ nameSubstring: z.string().describe('The substring to search for in file names'),
15
+ });
16
+
17
+ @Domain(MCPServerContribution)
18
+ export class FindFilesByNameSubstringTool implements MCPServerContribution {
19
+ @Autowired(IWorkspaceService)
20
+ private readonly workspaceService: IWorkspaceService;
21
+
22
+ @Autowired(IFileSearchService)
23
+ private readonly fileSearchService: IFileSearchService;
24
+
25
+ registerMCPServer(registry: IMCPServerRegistry): void {
26
+ registry.registerMCPTool(this.getToolDefinition());
27
+ }
28
+
29
+ getToolDefinition(): MCPToolDefinition {
30
+ return {
31
+ name: 'find_files_by_name_substring',
32
+ description:
33
+ 'Searches for all files in the project whose names contain the specified substring (case-insensitive). ' +
34
+ 'Use this tool to locate files when you know part of the filename. ' +
35
+ 'Requires a nameSubstring parameter for the search term. ' +
36
+ 'Returns a JSON array of objects containing file information: ' +
37
+ '- path: Path relative to project root ' +
38
+ '- name: File name ' +
39
+ 'Returns an empty array ([]) if no matching files are found. ' +
40
+ 'Note: Only searches through files within the project directory, excluding libraries and external dependencies.',
41
+ inputSchema: zodToJsonSchema(inputSchema),
42
+ handler: this.handler.bind(this),
43
+ };
44
+ }
45
+
46
+ private async handler(args: z.infer<typeof inputSchema>, logger: MCPLogger) {
47
+ try {
48
+ // 获取工作区根目录
49
+ const workspaceRoots = this.workspaceService.tryGetRoots();
50
+ if (!workspaceRoots || workspaceRoots.length === 0) {
51
+ logger.appendLine('Error: Cannot determine project directory');
52
+ return {
53
+ content: [{ type: 'text', text: '[]' }],
54
+ isError: true,
55
+ };
56
+ }
57
+
58
+ // 使用 OpenSumi 的文件搜索 API
59
+ const searchPattern = `**/*${args.nameSubstring}*`;
60
+ const searchResults = await this.fileSearchService.find(searchPattern, {
61
+ rootUris: [workspaceRoots[0].uri],
62
+ excludePatterns: ['**/node_modules/**'],
63
+ limit: 1000,
64
+ });
65
+
66
+ // 转换结果为所需的格式
67
+ const results = searchResults.map((file) => {
68
+ const uri = URI.parse(file);
69
+ const rootUri = URI.parse(workspaceRoots[0].uri);
70
+ const relativePath = path.relative(rootUri.codeUri.fsPath, uri.codeUri.fsPath);
71
+ const fileName = path.basename(uri.codeUri.fsPath);
72
+ return {
73
+ path: relativePath,
74
+ name: fileName,
75
+ };
76
+ });
77
+
78
+ // 将结果转换为 JSON 字符串
79
+ const resultJson = JSON.stringify(results, null, 2);
80
+ logger.appendLine(`Found ${results.length} files matching "${args.nameSubstring}"`);
81
+
82
+ return {
83
+ content: [{ type: 'text', text: resultJson }],
84
+ };
85
+ } catch (error) {
86
+ logger.appendLine(`Error during file search: ${error}`);
87
+ return {
88
+ content: [{ type: 'text', text: '[]' }],
89
+ isError: true,
90
+ };
91
+ }
92
+ }
93
+ }