@opensumi/ide-ai-native 3.7.2-next-1739859371.0 → 3.7.2-next-1739945875.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,49 @@
1
+ import { z } from 'zod';
2
+ import { zodToJsonSchema } from 'zod-to-json-schema';
3
+
4
+ import { Autowired, Injectable } from '@opensumi/di';
5
+ import { Domain } from '@opensumi/ide-core-common';
6
+ import { WorkbenchEditorService } from '@opensumi/ide-editor';
7
+
8
+ import { IMCPServerRegistry, MCPLogger, MCPServerContribution, MCPToolDefinition } from '../../types';
9
+
10
+ const inputSchema = z.object({});
11
+
12
+ @Domain(MCPServerContribution)
13
+ export class GetCurrentFilePathTool implements MCPServerContribution {
14
+ @Autowired(WorkbenchEditorService)
15
+ private readonly editorService: WorkbenchEditorService;
16
+
17
+ registerMCPServer(registry: IMCPServerRegistry): void {
18
+ registry.registerMCPTool(this.getToolDefinition());
19
+ }
20
+
21
+ getToolDefinition(): MCPToolDefinition {
22
+ return {
23
+ name: 'get_open_in_editor_file_path',
24
+ description:
25
+ 'Retrieves the absolute path of the currently active file in the VS Code editor. ' +
26
+ 'Use this tool to get the file location for tasks requiring file path information. ' +
27
+ 'Returns an empty string if no file is currently open.',
28
+ inputSchema: zodToJsonSchema(inputSchema),
29
+ handler: this.handler.bind(this),
30
+ };
31
+ }
32
+
33
+ private async handler(args: z.infer<typeof inputSchema>, logger: MCPLogger) {
34
+ const editor = this.editorService.currentEditor;
35
+ if (!editor || !editor.currentUri) {
36
+ logger.appendLine('Error: No active text editor found');
37
+ return {
38
+ content: [{ type: 'text', text: '' }],
39
+ };
40
+ }
41
+
42
+ const path = editor.currentUri.toString();
43
+ logger.appendLine(`Current file path: ${path}`);
44
+
45
+ return {
46
+ content: [{ type: 'text', text: path }],
47
+ };
48
+ }
49
+ }
@@ -0,0 +1,123 @@
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 { IWorkspaceService } from '@opensumi/ide-workspace';
9
+ import { URI as MonacoURI } from '@opensumi/monaco-editor-core/esm/vs/base/common/uri';
10
+ import { IMarkerService, MarkerSeverity } from '@opensumi/monaco-editor-core/esm/vs/platform/markers/common/markers';
11
+
12
+ import { IMCPServerRegistry, MCPLogger, MCPServerContribution, MCPToolDefinition } from '../../types';
13
+
14
+ const inputSchema = z.object({
15
+ filePathInProject: z.string().describe('The relative path to the file to get diagnostics for'),
16
+ });
17
+
18
+ @Domain(MCPServerContribution)
19
+ export class GetDiagnosticsByPathTool implements MCPServerContribution {
20
+ @Autowired(IWorkspaceService)
21
+ private readonly workspaceService: IWorkspaceService;
22
+
23
+ @Autowired(IMarkerService)
24
+ private readonly markerService: IMarkerService;
25
+
26
+ registerMCPServer(registry: IMCPServerRegistry): void {
27
+ registry.registerMCPTool(this.getToolDefinition());
28
+ }
29
+
30
+ getToolDefinition(): MCPToolDefinition {
31
+ return {
32
+ name: 'get_diagnostics_by_path',
33
+ description:
34
+ 'Retrieves diagnostic information (errors, warnings, etc.) from a specific file in the project. ' +
35
+ 'Use this tool to get information about problems in any project file. ' +
36
+ 'IMPORTANT: This tool should be called after any code generation or modification operations to verify and fix potential issues. ' +
37
+ 'Requires a filePathInProject parameter specifying the target file path relative to project root. ' +
38
+ 'Returns a JSON-formatted list of diagnostics, where each entry contains: ' +
39
+ '- path: The file path where the diagnostic was found ' +
40
+ '- line: The line number (1-based) of the diagnostic ' +
41
+ '- severity: The severity level ("error", "warning", "information", or "hint") ' +
42
+ '- message: The diagnostic message ' +
43
+ "Returns an empty list ([]) if no diagnostics are found or the file doesn't exist. " +
44
+ 'Best Practice: Always check diagnostics after code generation to ensure code quality and fix any issues immediately. ' +
45
+ 'Use this tool in combination with get_open_in_editor_file_diagnostics to verify all affected files after code changes. ' +
46
+ 'Diagnostic Severity Handling Guidelines: ' +
47
+ '- "error": Must be fixed immediately as they indicate critical issues that will prevent code from working correctly. ' +
48
+ '- "warning": For user code, preserve unless the warning indicates a clear improvement opportunity. For generated code, optimize to remove warnings. ' +
49
+ '- "information"/"hint": For user code, preserve as they might reflect intentional patterns. For generated code, optimize if it improves code quality without changing functionality.',
50
+ inputSchema: zodToJsonSchema(inputSchema),
51
+ handler: this.handler.bind(this),
52
+ };
53
+ }
54
+
55
+ private async handler(args: z.infer<typeof inputSchema>, logger: MCPLogger) {
56
+ try {
57
+ // 获取工作区根目录
58
+ const workspaceRoots = this.workspaceService.tryGetRoots();
59
+ if (!workspaceRoots || workspaceRoots.length === 0) {
60
+ logger.appendLine('Error: Cannot determine project directory');
61
+ return {
62
+ content: [{ type: 'text', text: '[]' }],
63
+ isError: true,
64
+ };
65
+ }
66
+
67
+ // 构建完整的文件路径
68
+ const rootUri = URI.parse(workspaceRoots[0].uri);
69
+ const fullPath = path.join(rootUri.codeUri.fsPath, args.filePathInProject);
70
+ const uri = MonacoURI.file(fullPath);
71
+
72
+ // 检查文件是否在项目目录内
73
+ const relativePath = path.relative(rootUri.codeUri.fsPath, fullPath);
74
+ if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {
75
+ logger.appendLine('Error: File is outside of project scope');
76
+ return {
77
+ content: [{ type: 'text', text: '[]' }],
78
+ isError: true,
79
+ };
80
+ }
81
+
82
+ // 获取文件的诊断信息
83
+ const markers = this.markerService.read({ resource: uri });
84
+
85
+ // 转换诊断信息
86
+ const diagnosticInfos = markers.map((marker) => ({
87
+ path: args.filePathInProject,
88
+ line: marker.startLineNumber,
89
+ severity: this.getSeverityString(marker.severity),
90
+ message: marker.message,
91
+ }));
92
+
93
+ // 将结果转换为 JSON 字符串
94
+ const resultJson = JSON.stringify(diagnosticInfos, null, 2);
95
+ logger.appendLine(`Found ${diagnosticInfos.length} diagnostics in ${args.filePathInProject}`);
96
+
97
+ return {
98
+ content: [{ type: 'text', text: resultJson }],
99
+ };
100
+ } catch (error) {
101
+ logger.appendLine(`Error getting diagnostics: ${error}`);
102
+ return {
103
+ content: [{ type: 'text', text: '[]' }],
104
+ isError: true,
105
+ };
106
+ }
107
+ }
108
+
109
+ private getSeverityString(severity: MarkerSeverity): string {
110
+ switch (severity) {
111
+ case MarkerSeverity.Error:
112
+ return 'error';
113
+ case MarkerSeverity.Warning:
114
+ return 'warning';
115
+ case MarkerSeverity.Info:
116
+ return 'information';
117
+ case MarkerSeverity.Hint:
118
+ return 'hint';
119
+ default:
120
+ return 'unknown';
121
+ }
122
+ }
123
+ }
@@ -0,0 +1,97 @@
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 { IFileServiceClient } from '@opensumi/ide-file-service';
9
+ import { IWorkspaceService } from '@opensumi/ide-workspace';
10
+
11
+ import { IMCPServerRegistry, MCPLogger, MCPServerContribution, MCPToolDefinition } from '../../types';
12
+
13
+ const inputSchema = z.object({
14
+ pathInProject: z.string().describe('The file location relative to project root'),
15
+ });
16
+
17
+ @Domain(MCPServerContribution)
18
+ export class GetFileTextByPathTool implements MCPServerContribution {
19
+ @Autowired(IWorkspaceService)
20
+ private readonly workspaceService: IWorkspaceService;
21
+
22
+ @Autowired(IFileServiceClient)
23
+ private readonly fileService: IFileServiceClient;
24
+
25
+ registerMCPServer(registry: IMCPServerRegistry): void {
26
+ registry.registerMCPTool(this.getToolDefinition());
27
+ }
28
+
29
+ getToolDefinition(): MCPToolDefinition {
30
+ return {
31
+ name: 'get_file_text_by_path',
32
+ description:
33
+ 'Retrieves the text content of a file using its path relative to project root. ' +
34
+ "Use this tool to read file contents when you have the file's project-relative path. " +
35
+ 'Requires a pathInProject parameter specifying the file location from project root. ' +
36
+ 'Returns one of these responses: ' +
37
+ "- The file's content if the file exists and belongs to the project " +
38
+ '- error "project dir not found" if project directory cannot be determined ' +
39
+ '- error "file not found" if the file doesn\'t exist or is outside project scope ' +
40
+ 'Note: Automatically refreshes the file system before reading',
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: 'project dir not found' }],
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 relativePath = path.relative(rootUri.codeUri.fsPath, fullPath);
65
+ if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {
66
+ logger.appendLine('Error: File is outside of project scope');
67
+ return {
68
+ content: [{ type: 'text', text: 'file not found' }],
69
+ isError: true,
70
+ };
71
+ }
72
+
73
+ // 检查文件是否存在并读取内容
74
+ try {
75
+ const result = await this.fileService.readFile(fileUri.toString());
76
+ const content = result.content.toString();
77
+ logger.appendLine(`Successfully read file: ${args.pathInProject}`);
78
+
79
+ return {
80
+ content: [{ type: 'text', text: content }],
81
+ };
82
+ } catch (error) {
83
+ logger.appendLine('Error: File does not exist');
84
+ return {
85
+ content: [{ type: 'text', text: 'file not found' }],
86
+ isError: true,
87
+ };
88
+ }
89
+ } catch (error) {
90
+ logger.appendLine(`Error reading file: ${error}`);
91
+ return {
92
+ content: [{ type: 'text', text: 'file not found' }],
93
+ isError: true,
94
+ };
95
+ }
96
+ }
97
+ }
@@ -0,0 +1,121 @@
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 { WorkbenchEditorService } from '@opensumi/ide-editor';
9
+ import { IWorkspaceService } from '@opensumi/ide-workspace';
10
+ import { URI as MonacoURI } from '@opensumi/monaco-editor-core/esm/vs/base/common/uri';
11
+ import { IMarkerService, MarkerSeverity } from '@opensumi/monaco-editor-core/esm/vs/platform/markers/common/markers';
12
+
13
+ import { IMCPServerRegistry, MCPLogger, MCPServerContribution, MCPToolDefinition } from '../../types';
14
+
15
+ const inputSchema = z.object({});
16
+
17
+ @Domain(MCPServerContribution)
18
+ export class GetOpenEditorFileDiagnosticsTool implements MCPServerContribution {
19
+ @Autowired(WorkbenchEditorService)
20
+ private readonly editorService: WorkbenchEditorService;
21
+
22
+ @Autowired(IWorkspaceService)
23
+ private readonly workspaceService: IWorkspaceService;
24
+
25
+ @Autowired(IMarkerService)
26
+ private readonly markerService: IMarkerService;
27
+
28
+ registerMCPServer(registry: IMCPServerRegistry): void {
29
+ registry.registerMCPTool(this.getToolDefinition());
30
+ }
31
+
32
+ getToolDefinition(): MCPToolDefinition {
33
+ return {
34
+ name: 'get_open_in_editor_file_diagnostics',
35
+ description:
36
+ 'Retrieves diagnostic information (errors, warnings, etc.) from the currently active file in VS Code editor. ' +
37
+ 'Use this tool to get information about problems in your current file. ' +
38
+ 'IMPORTANT: This tool should be called after any code generation or modification operations to verify and fix potential issues. ' +
39
+ 'Returns a JSON-formatted list of diagnostics, where each entry contains: ' +
40
+ '- path: The file path where the diagnostic was found ' +
41
+ '- line: The line number (1-based) of the diagnostic ' +
42
+ '- severity: The severity level ("error", "warning", "information", or "hint") ' +
43
+ '- message: The diagnostic message ' +
44
+ 'Returns an empty list ([]) if no diagnostics are found or no file is open. ' +
45
+ 'Best Practice: Always check diagnostics after code generation to ensure code quality and fix any issues immediately. ' +
46
+ 'Diagnostic Severity Handling Guidelines: ' +
47
+ '- "error": Must be fixed immediately as they indicate critical issues that will prevent code from working correctly. ' +
48
+ '- "warning": For user code, preserve unless the warning indicates a clear improvement opportunity. For generated code, optimize to remove warnings. ' +
49
+ '- "information"/"hint": For user code, preserve as they might reflect intentional patterns. For generated code, optimize if it improves code quality without changing functionality.',
50
+ inputSchema: zodToJsonSchema(inputSchema),
51
+ handler: this.handler.bind(this),
52
+ };
53
+ }
54
+
55
+ private async handler(args: z.infer<typeof inputSchema>, logger: MCPLogger) {
56
+ try {
57
+ // 获取当前活动的编辑器
58
+ const editor = this.editorService.currentEditor;
59
+ if (!editor || !editor.currentUri) {
60
+ logger.appendLine('Error: No active text editor found');
61
+ return {
62
+ content: [{ type: 'text', text: '[]' }],
63
+ isError: true,
64
+ };
65
+ }
66
+
67
+ // 获取工作区根目录
68
+ const workspaceRoots = this.workspaceService.tryGetRoots();
69
+ if (!workspaceRoots || workspaceRoots.length === 0) {
70
+ logger.appendLine('Error: Cannot determine project directory');
71
+ return {
72
+ content: [{ type: 'text', text: '[]' }],
73
+ isError: true,
74
+ };
75
+ }
76
+
77
+ // 获取当前文件的诊断信息
78
+ const monacoUri = MonacoURI.parse(editor.currentUri.toString());
79
+ const markers = this.markerService.read({ resource: monacoUri });
80
+ const rootUri = URI.parse(workspaceRoots[0].uri);
81
+ const relativePath = path.relative(rootUri.codeUri.fsPath, editor.currentUri.codeUri.fsPath);
82
+
83
+ // 转换诊断信息
84
+ const diagnosticInfos = markers.map((marker) => ({
85
+ path: relativePath,
86
+ line: marker.startLineNumber,
87
+ severity: this.getSeverityString(marker.severity),
88
+ message: marker.message,
89
+ }));
90
+
91
+ // 将结果转换为 JSON 字符串
92
+ const resultJson = JSON.stringify(diagnosticInfos, null, 2);
93
+ logger.appendLine(`Found ${diagnosticInfos.length} diagnostics in current file`);
94
+
95
+ return {
96
+ content: [{ type: 'text', text: resultJson }],
97
+ };
98
+ } catch (error) {
99
+ logger.appendLine(`Error getting diagnostics: ${error}`);
100
+ return {
101
+ content: [{ type: 'text', text: '[]' }],
102
+ isError: true,
103
+ };
104
+ }
105
+ }
106
+
107
+ private getSeverityString(severity: MarkerSeverity): string {
108
+ switch (severity) {
109
+ case MarkerSeverity.Error:
110
+ return 'error';
111
+ case MarkerSeverity.Warning:
112
+ return 'warning';
113
+ case MarkerSeverity.Info:
114
+ return 'information';
115
+ case MarkerSeverity.Hint:
116
+ return 'hint';
117
+ default:
118
+ return 'unknown';
119
+ }
120
+ }
121
+ }
@@ -0,0 +1,50 @@
1
+ import { z } from 'zod';
2
+ import { zodToJsonSchema } from 'zod-to-json-schema';
3
+
4
+ import { Autowired, Injectable } from '@opensumi/di';
5
+ import { Domain } from '@opensumi/ide-core-common';
6
+ import { WorkbenchEditorService } from '@opensumi/ide-editor';
7
+
8
+ import { IMCPServerRegistry, MCPLogger, MCPServerContribution, MCPToolDefinition } from '../../types';
9
+
10
+ const inputSchema = z.object({});
11
+
12
+ @Domain(MCPServerContribution)
13
+ export class GetOpenEditorFileTextTool implements MCPServerContribution {
14
+ @Autowired(WorkbenchEditorService)
15
+ private readonly editorService: WorkbenchEditorService;
16
+
17
+ registerMCPServer(registry: IMCPServerRegistry): void {
18
+ registry.registerMCPTool(this.getToolDefinition());
19
+ }
20
+
21
+ getToolDefinition(): MCPToolDefinition {
22
+ return {
23
+ name: 'get_open_in_editor_file_text',
24
+ description:
25
+ 'Retrieves the complete text content of the currently active file in the IDE editor. ' +
26
+ "Use this tool to access and analyze the file's contents for tasks such as code review, content inspection, or text processing. " +
27
+ 'Returns empty string if no file is currently open.',
28
+ inputSchema: zodToJsonSchema(inputSchema),
29
+ handler: this.handler.bind(this),
30
+ };
31
+ }
32
+
33
+ private async handler(args: z.infer<typeof inputSchema>, logger: MCPLogger) {
34
+ const editor = this.editorService.currentEditor;
35
+ if (!editor || !editor.currentDocumentModel) {
36
+ logger.appendLine('Error: No active text editor found');
37
+ return {
38
+ content: [{ type: 'text', text: '' }],
39
+ };
40
+ }
41
+
42
+ const document = editor.currentDocumentModel;
43
+ logger.appendLine(`Reading content from: ${document.uri.toString()}`);
44
+ const content = document.getText();
45
+
46
+ return {
47
+ content: [{ type: 'text', text: content }],
48
+ };
49
+ }
50
+ }
@@ -0,0 +1,57 @@
1
+ import { z } from 'zod';
2
+ import { zodToJsonSchema } from 'zod-to-json-schema';
3
+
4
+ import { Autowired, Injectable } from '@opensumi/di';
5
+ import { Domain } from '@opensumi/ide-core-common';
6
+ import { WorkbenchEditorService } from '@opensumi/ide-editor';
7
+
8
+ import { IMCPServerRegistry, MCPLogger, MCPServerContribution, MCPToolDefinition } from '../../types';
9
+
10
+ const inputSchema = z.object({});
11
+
12
+ @Domain(MCPServerContribution)
13
+ export class GetSelectedTextTool implements MCPServerContribution {
14
+ @Autowired(WorkbenchEditorService)
15
+ private readonly editorService: WorkbenchEditorService;
16
+
17
+ registerMCPServer(registry: IMCPServerRegistry): void {
18
+ registry.registerMCPTool(this.getToolDefinition());
19
+ }
20
+
21
+ getToolDefinition(): MCPToolDefinition {
22
+ return {
23
+ name: 'get_selected_in_editor_text',
24
+ description:
25
+ 'Retrieves the currently selected text from the active editor in VS Code. ' +
26
+ 'Use this tool when you need to access and analyze text that has been highlighted/selected by the user. ' +
27
+ 'Returns an empty string if no text is selected or no editor is open.',
28
+ inputSchema: zodToJsonSchema(inputSchema),
29
+ handler: this.handler.bind(this),
30
+ };
31
+ }
32
+
33
+ private async handler(args: z.infer<typeof inputSchema>, logger: MCPLogger) {
34
+ const editor = this.editorService.currentEditor;
35
+ if (!editor || !editor.monacoEditor) {
36
+ logger.appendLine('Error: No active text editor found');
37
+ return {
38
+ content: [{ type: 'text', text: '' }],
39
+ };
40
+ }
41
+
42
+ const selection = editor.monacoEditor.getSelection();
43
+ if (!selection) {
44
+ logger.appendLine('No text is currently selected');
45
+ return {
46
+ content: [{ type: 'text', text: '' }],
47
+ };
48
+ }
49
+
50
+ const selectedText = editor.monacoEditor.getModel()?.getValueInRange(selection) || '';
51
+ logger.appendLine(`Retrieved selected text of length: ${selectedText.length}`);
52
+
53
+ return {
54
+ content: [{ type: 'text', text: selectedText }],
55
+ };
56
+ }
57
+ }
@@ -0,0 +1,117 @@
1
+ import { Autowired, Injectable } from '@opensumi/di';
2
+ import { AppConfig, Throttler, URI } from '@opensumi/ide-core-browser';
3
+ import { IFileServiceClient } from '@opensumi/ide-file-service';
4
+
5
+ /**
6
+ * 并发限制器
7
+ */
8
+ class ConcurrencyLimiter {
9
+ private maxConcurrent: number;
10
+ private currentCount: number;
11
+ private pendingQueue: (() => void)[];
12
+ /**
13
+ * @param {number} maxConcurrent - 最大并发数
14
+ */
15
+ constructor(maxConcurrent) {
16
+ this.maxConcurrent = maxConcurrent; // 最大并发数
17
+ this.currentCount = 0; // 当前执行的任务数
18
+ this.pendingQueue = []; // 等待执行的任务队列
19
+ }
20
+
21
+ /**
22
+ * 执行异步任务
23
+ * @param {Function} fn - 要执行的异步函数
24
+ * @returns {Promise} 任务执行的结果
25
+ */
26
+ async execute(fn) {
27
+ // 如果当前执行的任务数达到最大并发数,则加入等待队列
28
+ if (this.currentCount >= this.maxConcurrent) {
29
+ await new Promise<void>((resolve) => this.pendingQueue.push(resolve));
30
+ }
31
+
32
+ this.currentCount++;
33
+
34
+ try {
35
+ // 执行任务
36
+ const result = await fn();
37
+ return result;
38
+ } finally {
39
+ this.currentCount--;
40
+ // 如果等待队列中有任务,则允许执行下一个任务
41
+ if (this.pendingQueue.length > 0) {
42
+ const next = this.pendingQueue.shift();
43
+ next?.();
44
+ }
45
+ }
46
+ }
47
+ }
48
+
49
+ @Injectable()
50
+ export class ListDirHandler {
51
+ private readonly MAX_FILE_SIZE = 1024 * 1024; // 1MB
52
+ private readonly MAX_INDEXED_FILES = 50;
53
+ @Autowired(AppConfig)
54
+ private readonly appConfig: AppConfig;
55
+
56
+ @Autowired(IFileServiceClient)
57
+ private readonly fileSystemService: IFileServiceClient;
58
+
59
+ async handler(args: { relativeWorkspacePath: string }) {
60
+ const { relativeWorkspacePath } = args;
61
+ if (!relativeWorkspacePath) {
62
+ throw new Error('No list dir parameters provided. Need to give at least the path.');
63
+ }
64
+
65
+ // 解析相对路径
66
+ const absolutePath = `${this.appConfig.workspaceDir}/${relativeWorkspacePath}`;
67
+ const fileStat = await this.fileSystemService.getFileStat(absolutePath, true);
68
+ // 验证路径有效性
69
+ if (!fileStat || !fileStat.isDirectory) {
70
+ throw new Error(`Could not find file ${relativeWorkspacePath} in the workspace.`);
71
+ }
72
+ // 过滤符合大小限制的文件
73
+ const filesWithinSizeLimit =
74
+ fileStat.children
75
+ ?.filter((file) => !file.isDirectory && file.size !== void 0 && file.size <= this.MAX_FILE_SIZE)
76
+ .slice(0, this.MAX_INDEXED_FILES) || [];
77
+
78
+ // 记录需要分析的文件名
79
+ const filesToAnalyze = new Set(filesWithinSizeLimit.map((file) => new URI(file.uri).displayName));
80
+
81
+ // 创建并发限制器
82
+ const concurrencyLimiter = new ConcurrencyLimiter(4);
83
+ // 处理所有文件信息
84
+ const fileInfos = await Promise.all(
85
+ fileStat.children
86
+ ?.sort((a, b) => b.lastModification - a.lastModification)
87
+ .map(async (file) => {
88
+ const uri = new URI(file.uri);
89
+ const filePath = `${absolutePath}/${uri.displayName}`;
90
+ let lineCount: number | undefined;
91
+
92
+ // 如果文件需要分析,则计算行数
93
+ if (filesToAnalyze.has(uri.displayName)) {
94
+ lineCount = await concurrencyLimiter.execute(async () => this.countFileLines(filePath));
95
+ }
96
+ return {
97
+ name: uri.displayName,
98
+ isDirectory: file.isDirectory,
99
+ size: file.size,
100
+ lastModified: file.lastModification,
101
+ numChildren: file.children?.length,
102
+ numLines: lineCount,
103
+ };
104
+ }) || [],
105
+ );
106
+ // TODO: 过滤忽略文件
107
+ return {
108
+ files: fileInfos,
109
+ directoryRelativeWorkspacePath: relativeWorkspacePath,
110
+ };
111
+ }
112
+
113
+ async countFileLines(filePath: string) {
114
+ const file = await this.fileSystemService.readFile(URI.file(filePath).toString());
115
+ return file.toString().split('\n').length;
116
+ }
117
+ }