@opensumi/ide-ai-native 3.7.2-next-1739848467.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 (227) 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/index.d.ts +11 -3
  46. package/lib/browser/index.d.ts.map +1 -1
  47. package/lib/browser/index.js +56 -3
  48. package/lib/browser/index.js.map +1 -1
  49. package/lib/browser/mcp/mcp-server-proxy.service.d.ts +25 -0
  50. package/lib/browser/mcp/mcp-server-proxy.service.d.ts.map +1 -0
  51. package/lib/browser/mcp/mcp-server-proxy.service.js +56 -0
  52. package/lib/browser/mcp/mcp-server-proxy.service.js.map +1 -0
  53. package/lib/browser/mcp/mcp-server.feature.registry.d.ts +16 -0
  54. package/lib/browser/mcp/mcp-server.feature.registry.d.ts.map +1 -0
  55. package/lib/browser/mcp/mcp-server.feature.registry.js +53 -0
  56. package/lib/browser/mcp/mcp-server.feature.registry.js.map +1 -0
  57. package/lib/browser/mcp/mcp-tools-dialog.module.less +44 -0
  58. package/lib/browser/mcp/mcp-tools-dialog.view.d.ts +8 -0
  59. package/lib/browser/mcp/mcp-tools-dialog.view.d.ts.map +1 -0
  60. package/lib/browser/mcp/mcp-tools-dialog.view.js +16 -0
  61. package/lib/browser/mcp/mcp-tools-dialog.view.js.map +1 -0
  62. package/lib/browser/mcp/tools/createNewFileWithText.d.ts +9 -0
  63. package/lib/browser/mcp/tools/createNewFileWithText.d.ts.map +1 -0
  64. package/lib/browser/mcp/tools/createNewFileWithText.js +83 -0
  65. package/lib/browser/mcp/tools/createNewFileWithText.js.map +1 -0
  66. package/lib/browser/mcp/tools/findFilesByNameSubstring.d.ts +9 -0
  67. package/lib/browser/mcp/tools/findFilesByNameSubstring.d.ts.map +1 -0
  68. package/lib/browser/mcp/tools/findFilesByNameSubstring.js +92 -0
  69. package/lib/browser/mcp/tools/findFilesByNameSubstring.js.map +1 -0
  70. package/lib/browser/mcp/tools/getCurrentFilePath.d.ts +8 -0
  71. package/lib/browser/mcp/tools/getCurrentFilePath.d.ts.map +1 -0
  72. package/lib/browser/mcp/tools/getCurrentFilePath.js +49 -0
  73. package/lib/browser/mcp/tools/getCurrentFilePath.js.map +1 -0
  74. package/lib/browser/mcp/tools/getDiagnosticsByPath.d.ts +10 -0
  75. package/lib/browser/mcp/tools/getDiagnosticsByPath.d.ts.map +1 -0
  76. package/lib/browser/mcp/tools/getDiagnosticsByPath.js +119 -0
  77. package/lib/browser/mcp/tools/getDiagnosticsByPath.js.map +1 -0
  78. package/lib/browser/mcp/tools/getFileTextByPath.d.ts +9 -0
  79. package/lib/browser/mcp/tools/getFileTextByPath.d.ts.map +1 -0
  80. package/lib/browser/mcp/tools/getFileTextByPath.js +97 -0
  81. package/lib/browser/mcp/tools/getFileTextByPath.js.map +1 -0
  82. package/lib/browser/mcp/tools/getOpenEditorFileDiagnostics.d.ts +11 -0
  83. package/lib/browser/mcp/tools/getOpenEditorFileDiagnostics.d.ts.map +1 -0
  84. package/lib/browser/mcp/tools/getOpenEditorFileDiagnostics.js +119 -0
  85. package/lib/browser/mcp/tools/getOpenEditorFileDiagnostics.js.map +1 -0
  86. package/lib/browser/mcp/tools/getOpenEditorFileText.d.ts +8 -0
  87. package/lib/browser/mcp/tools/getOpenEditorFileText.d.ts.map +1 -0
  88. package/lib/browser/mcp/tools/getOpenEditorFileText.js +50 -0
  89. package/lib/browser/mcp/tools/getOpenEditorFileText.js.map +1 -0
  90. package/lib/browser/mcp/tools/getSelectedText.d.ts +8 -0
  91. package/lib/browser/mcp/tools/getSelectedText.d.ts.map +1 -0
  92. package/lib/browser/mcp/tools/getSelectedText.js +57 -0
  93. package/lib/browser/mcp/tools/getSelectedText.js.map +1 -0
  94. package/lib/browser/mcp/tools/handlers/ListDir.d.ts +21 -0
  95. package/lib/browser/mcp/tools/handlers/ListDir.d.ts.map +1 -0
  96. package/lib/browser/mcp/tools/handlers/ListDir.js +112 -0
  97. package/lib/browser/mcp/tools/handlers/ListDir.js.map +1 -0
  98. package/lib/browser/mcp/tools/handlers/ReadFile.d.ts +47 -0
  99. package/lib/browser/mcp/tools/handlers/ReadFile.d.ts.map +1 -0
  100. package/lib/browser/mcp/tools/handlers/ReadFile.js +147 -0
  101. package/lib/browser/mcp/tools/handlers/ReadFile.js.map +1 -0
  102. package/lib/browser/mcp/tools/listDir.d.ts +8 -0
  103. package/lib/browser/mcp/tools/listDir.d.ts.map +1 -0
  104. package/lib/browser/mcp/tools/listDir.js +65 -0
  105. package/lib/browser/mcp/tools/listDir.js.map +1 -0
  106. package/lib/browser/mcp/tools/readFile.d.ts +8 -0
  107. package/lib/browser/mcp/tools/readFile.d.ts.map +1 -0
  108. package/lib/browser/mcp/tools/readFile.js +82 -0
  109. package/lib/browser/mcp/tools/readFile.js.map +1 -0
  110. package/lib/browser/mcp/tools/replaceOpenEditorFile.d.ts +8 -0
  111. package/lib/browser/mcp/tools/replaceOpenEditorFile.d.ts.map +1 -0
  112. package/lib/browser/mcp/tools/replaceOpenEditorFile.js +79 -0
  113. package/lib/browser/mcp/tools/replaceOpenEditorFile.js.map +1 -0
  114. package/lib/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.d.ts +8 -0
  115. package/lib/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.d.ts.map +1 -0
  116. package/lib/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.js +84 -0
  117. package/lib/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.js.map +1 -0
  118. package/lib/browser/mcp/tools/runTerminalCmd.d.ts +18 -0
  119. package/lib/browser/mcp/tools/runTerminalCmd.d.ts.map +1 -0
  120. package/lib/browser/mcp/tools/runTerminalCmd.js +96 -0
  121. package/lib/browser/mcp/tools/runTerminalCmd.js.map +1 -0
  122. package/lib/browser/preferences/schema.d.ts.map +1 -1
  123. package/lib/browser/preferences/schema.js +60 -0
  124. package/lib/browser/preferences/schema.js.map +1 -1
  125. package/lib/browser/types.d.ts +45 -0
  126. package/lib/browser/types.d.ts.map +1 -1
  127. package/lib/browser/types.js +5 -1
  128. package/lib/browser/types.js.map +1 -1
  129. package/lib/common/index.d.ts +9 -0
  130. package/lib/common/index.d.ts.map +1 -1
  131. package/lib/common/index.js +4 -1
  132. package/lib/common/index.js.map +1 -1
  133. package/lib/common/llm-context.d.ts +37 -0
  134. package/lib/common/llm-context.d.ts.map +1 -0
  135. package/lib/common/llm-context.js +5 -0
  136. package/lib/common/llm-context.js.map +1 -0
  137. package/lib/common/mcp-server-manager.d.ts +40 -0
  138. package/lib/common/mcp-server-manager.d.ts.map +1 -0
  139. package/lib/common/mcp-server-manager.js +6 -0
  140. package/lib/common/mcp-server-manager.js.map +1 -0
  141. package/lib/common/tool-invocation-registry.d.ts +91 -0
  142. package/lib/common/tool-invocation-registry.d.ts.map +1 -0
  143. package/lib/common/tool-invocation-registry.js +90 -0
  144. package/lib/common/tool-invocation-registry.js.map +1 -0
  145. package/lib/common/types.d.ts +17 -0
  146. package/lib/common/types.d.ts.map +1 -1
  147. package/lib/node/anthropic/anthropic-language-model.d.ts +9 -0
  148. package/lib/node/anthropic/anthropic-language-model.d.ts.map +1 -0
  149. package/lib/node/anthropic/anthropic-language-model.js +26 -0
  150. package/lib/node/anthropic/anthropic-language-model.js.map +1 -0
  151. package/lib/node/base-language-model.d.ts +14 -0
  152. package/lib/node/base-language-model.d.ts.map +1 -0
  153. package/lib/node/base-language-model.js +136 -0
  154. package/lib/node/base-language-model.js.map +1 -0
  155. package/lib/node/deepseek/deepseek-language-model.d.ts +9 -0
  156. package/lib/node/deepseek/deepseek-language-model.d.ts.map +1 -0
  157. package/lib/node/deepseek/deepseek-language-model.js +26 -0
  158. package/lib/node/deepseek/deepseek-language-model.js.map +1 -0
  159. package/lib/node/index.d.ts.map +1 -1
  160. package/lib/node/index.js +19 -0
  161. package/lib/node/index.js.map +1 -1
  162. package/lib/node/mcp/sumi-mcp-server.d.ts +91 -0
  163. package/lib/node/mcp/sumi-mcp-server.d.ts.map +1 -0
  164. package/lib/node/mcp/sumi-mcp-server.js +172 -0
  165. package/lib/node/mcp/sumi-mcp-server.js.map +1 -0
  166. package/lib/node/mcp-server-manager-impl.d.ts +27 -0
  167. package/lib/node/mcp-server-manager-impl.d.ts.map +1 -0
  168. package/lib/node/mcp-server-manager-impl.js +127 -0
  169. package/lib/node/mcp-server-manager-impl.js.map +1 -0
  170. package/lib/node/mcp-server.d.ts +207 -0
  171. package/lib/node/mcp-server.d.ts.map +1 -0
  172. package/lib/node/mcp-server.js +91 -0
  173. package/lib/node/mcp-server.js.map +1 -0
  174. package/lib/node/openai/openai-language-model.d.ts +9 -0
  175. package/lib/node/openai/openai-language-model.d.ts.map +1 -0
  176. package/lib/node/openai/openai-language-model.js +29 -0
  177. package/lib/node/openai/openai-language-model.js.map +1 -0
  178. package/package.json +34 -22
  179. package/src/browser/ai-core.contribution.ts +77 -1
  180. package/src/browser/chat/chat-model.ts +24 -6
  181. package/src/browser/chat/chat-proxy.service.ts +42 -0
  182. package/src/browser/chat/chat.view.tsx +59 -6
  183. package/src/browser/components/ChatContext/ContextSelector.tsx +177 -0
  184. package/src/browser/components/ChatContext/index.tsx +135 -0
  185. package/src/browser/components/ChatContext/style.module.less +189 -0
  186. package/src/browser/components/ChatInput.tsx +1 -0
  187. package/src/browser/components/ChatReply.tsx +32 -0
  188. package/src/browser/components/ChatToolRender.module.less +86 -0
  189. package/src/browser/components/ChatToolRender.tsx +77 -0
  190. package/src/browser/components/components.module.less +32 -31
  191. package/src/browser/context/llm-context.contribution.ts +14 -0
  192. package/src/browser/context/llm-context.service.ts +156 -0
  193. package/src/browser/index.ts +68 -4
  194. package/src/browser/mcp/mcp-server-proxy.service.ts +53 -0
  195. package/src/browser/mcp/mcp-server.feature.registry.ts +54 -0
  196. package/src/browser/mcp/mcp-tools-dialog.module.less +44 -0
  197. package/src/browser/mcp/mcp-tools-dialog.view.tsx +24 -0
  198. package/src/browser/mcp/tools/createNewFileWithText.ts +83 -0
  199. package/src/browser/mcp/tools/findFilesByNameSubstring.ts +93 -0
  200. package/src/browser/mcp/tools/getCurrentFilePath.ts +49 -0
  201. package/src/browser/mcp/tools/getDiagnosticsByPath.ts +123 -0
  202. package/src/browser/mcp/tools/getFileTextByPath.ts +97 -0
  203. package/src/browser/mcp/tools/getOpenEditorFileDiagnostics.ts +121 -0
  204. package/src/browser/mcp/tools/getOpenEditorFileText.ts +50 -0
  205. package/src/browser/mcp/tools/getSelectedText.ts +57 -0
  206. package/src/browser/mcp/tools/handlers/ListDir.ts +117 -0
  207. package/src/browser/mcp/tools/handlers/ReadFile.ts +174 -0
  208. package/src/browser/mcp/tools/listDir.ts +66 -0
  209. package/src/browser/mcp/tools/readFile.ts +82 -0
  210. package/src/browser/mcp/tools/replaceOpenEditorFile.ts +80 -0
  211. package/src/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.ts +91 -0
  212. package/src/browser/mcp/tools/runTerminalCmd.ts +107 -0
  213. package/src/browser/preferences/schema.ts +60 -0
  214. package/src/browser/types.ts +56 -0
  215. package/src/common/index.ts +14 -0
  216. package/src/common/llm-context.ts +41 -0
  217. package/src/common/mcp-server-manager.ts +46 -0
  218. package/src/common/tool-invocation-registry.ts +170 -0
  219. package/src/common/types.ts +22 -0
  220. package/src/node/anthropic/anthropic-language-model.ts +25 -0
  221. package/src/node/base-language-model.ts +163 -0
  222. package/src/node/deepseek/deepseek-language-model.ts +25 -0
  223. package/src/node/index.ts +21 -0
  224. package/src/node/mcp/sumi-mcp-server.ts +197 -0
  225. package/src/node/mcp-server-manager-impl.ts +148 -0
  226. package/src/node/mcp-server.ts +126 -0
  227. package/src/node/openai/openai-language-model.ts +25 -0
@@ -0,0 +1,91 @@
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
+ import { Selection, SelectionDirection } from '@opensumi/monaco-editor-core/esm/vs/editor/common/core/selection';
8
+
9
+ import { IMCPServerRegistry, MCPLogger, MCPServerContribution, MCPToolDefinition } from '../../types';
10
+ import { LiveInlineDiffPreviewer } from '../../widget/inline-diff/inline-diff-previewer';
11
+ import { InlineDiffController } from '../../widget/inline-diff/inline-diff.controller';
12
+
13
+ const inputSchema = z.object({
14
+ text: z.string().describe('The new content to replace the entire file with'),
15
+ });
16
+
17
+ @Domain(MCPServerContribution)
18
+ export class ReplaceOpenEditorFileByDiffPreviewerTool implements MCPServerContribution {
19
+ @Autowired(WorkbenchEditorService)
20
+ private readonly editorService: WorkbenchEditorService;
21
+
22
+ registerMCPServer(registry: IMCPServerRegistry): void {
23
+ registry.registerMCPTool(this.getToolDefinition());
24
+ }
25
+
26
+ getToolDefinition(): MCPToolDefinition {
27
+ return {
28
+ name: 'replace_open_in_editor_file_text',
29
+ description:
30
+ 'Replaces the entire content of the currently active file in the IDE editor with specified new text using diff previewer. ' +
31
+ "Use this tool when you need to completely overwrite the current file's content with diff preview. " +
32
+ 'Requires a text parameter containing the new content. ' +
33
+ 'Returns one of three possible responses: ' +
34
+ '"ok" if the file content was successfully replaced, ' +
35
+ '"no file open" if no editor is active, ' +
36
+ '"unknown error" if the operation fails.',
37
+ inputSchema: zodToJsonSchema(inputSchema),
38
+ handler: this.handler.bind(this),
39
+ };
40
+ }
41
+
42
+ private async handler(args: z.infer<typeof inputSchema>, logger: MCPLogger) {
43
+ try {
44
+ const editor = this.editorService.currentEditor;
45
+ if (!editor || !editor.monacoEditor) {
46
+ logger.appendLine('Error: No active text editor found');
47
+ return {
48
+ content: [{ type: 'text', text: 'no file open' }],
49
+ isError: true,
50
+ };
51
+ }
52
+
53
+ // Get the model and its full range
54
+ const model = editor.monacoEditor.getModel();
55
+ if (!model) {
56
+ logger.appendLine('Error: No model found for current editor');
57
+ return {
58
+ content: [{ type: 'text', text: 'unknown error' }],
59
+ isError: true,
60
+ };
61
+ }
62
+
63
+ const fullRange = model.getFullModelRange();
64
+ const inlineDiffHandler = InlineDiffController.get(editor.monacoEditor)!;
65
+
66
+ // Create diff previewer
67
+ const previewer = inlineDiffHandler.createDiffPreviewer(
68
+ editor.monacoEditor,
69
+ Selection.fromRange(fullRange, SelectionDirection.LTR),
70
+ {
71
+ disposeWhenEditorClosed: false,
72
+ renderRemovedWidgetImmediately: true,
73
+ },
74
+ ) as LiveInlineDiffPreviewer;
75
+
76
+ // Set the new content
77
+ previewer.setValue(args.text);
78
+
79
+ logger.appendLine('Successfully created diff preview with new content');
80
+ return {
81
+ content: [{ type: 'text', text: 'ok' }],
82
+ };
83
+ } catch (error) {
84
+ logger.appendLine(`Error during file content replacement: ${error}`);
85
+ return {
86
+ content: [{ type: 'text', text: 'unknown error' }],
87
+ isError: true,
88
+ };
89
+ }
90
+ }
91
+ }
@@ -0,0 +1,107 @@
1
+ import { z } from 'zod';
2
+ import { zodToJsonSchema } from 'zod-to-json-schema';
3
+
4
+ import { Autowired } from '@opensumi/di';
5
+ import { AppConfig } from '@opensumi/ide-core-browser';
6
+ import { Deferred, Domain } from '@opensumi/ide-core-common';
7
+ import { ITerminalController, ITerminalGroupViewService } from '@opensumi/ide-terminal-next/lib/common/controller';
8
+
9
+ import { IMCPServerRegistry, MCPLogger, MCPServerContribution, MCPToolDefinition } from '../../types';
10
+
11
+ const color = {
12
+ italic: '\x1b[3m',
13
+ reset: '\x1b[0m',
14
+ };
15
+
16
+ const inputSchema = z.object({
17
+ command: z.string().describe('The terminal command to execute'),
18
+ is_background: z.boolean().describe('Whether the command should be run in the background'),
19
+ explanation: z
20
+ .string()
21
+ .describe('One sentence explanation as to why this command needs to be run and how it contributes to the goal.'),
22
+ require_user_approval: z
23
+ .boolean()
24
+ .describe(
25
+ "Whether the user must approve the command before it is executed. Only set this to false if the command is safe and if it matches the user's requirements for commands that should be executed automatically.",
26
+ ),
27
+ });
28
+
29
+ @Domain(MCPServerContribution)
30
+ export class RunTerminalCommandTool implements MCPServerContribution {
31
+ @Autowired(ITerminalController)
32
+ protected readonly terminalController: ITerminalController;
33
+
34
+ @Autowired(AppConfig)
35
+ protected readonly appConfig: AppConfig;
36
+
37
+ @Autowired(ITerminalGroupViewService)
38
+ protected readonly terminalView: ITerminalGroupViewService;
39
+
40
+ private terminalId = 0;
41
+
42
+ registerMCPServer(registry: IMCPServerRegistry): void {
43
+ registry.registerMCPTool(this.getToolDefinition());
44
+ }
45
+
46
+ getToolDefinition(): MCPToolDefinition {
47
+ return {
48
+ name: 'run_terminal_cmd',
49
+ description:
50
+ "PROPOSE a command to run on behalf of the user.\nIf you have this tool, note that you DO have the ability to run commands directly on the USER's system.\n\nAdhere to these rules:\n1. Based on the contents of the conversation, you will be told if you are in the same shell as a previous step or a new shell.\n2. If in a new shell, you should `cd` to the right directory and do necessary setup in addition to running the command.\n3. If in the same shell, the state will persist, no need to do things like `cd` to the same directory.\n4. For ANY commands that would use a pager, you should append ` | cat` to the command (or whatever is appropriate). You MUST do this for: git, less, head, tail, more, etc.\n5. For commands that are long running/expected to run indefinitely until interruption, please run them in the background. To run jobs in the background, set `is_background` to true rather than changing the details of the command.\n6. Dont include any newlines in the command.",
51
+ inputSchema: zodToJsonSchema(inputSchema),
52
+ handler: this.handler.bind(this),
53
+ };
54
+ }
55
+
56
+ getShellLaunchConfig(command: string) {
57
+ return {
58
+ name: `MCP:Terminal_${this.terminalId++}`,
59
+ cwd: this.appConfig.workspaceDir,
60
+ args: ['-c', command],
61
+ };
62
+ }
63
+
64
+ private async handler(args: z.infer<typeof inputSchema>, logger: MCPLogger) {
65
+ if (args.require_user_approval) {
66
+ // FIXME: support approval
67
+ }
68
+
69
+ const terminalClient = await this.terminalController.createTerminalWithWidget({
70
+ config: this.getShellLaunchConfig(args.command),
71
+ closeWhenExited: false,
72
+ });
73
+
74
+ this.terminalController.showTerminalPanel();
75
+
76
+ const result: { type: string; text: string }[] = [];
77
+ const def = new Deferred<{ isError?: boolean; content: { type: string; text: string }[] }>();
78
+
79
+ terminalClient.onOutput((e) => {
80
+ result.push({
81
+ type: 'output',
82
+ text: e.data.toString(),
83
+ });
84
+ });
85
+
86
+ terminalClient.onExit((e) => {
87
+ const isError = e.code !== 0;
88
+ def.resolve({
89
+ isError,
90
+ content: result,
91
+ });
92
+
93
+ terminalClient.term.writeln(
94
+ `\n${color.italic}> Command ${args.command} executed successfully. Terminal will close in ${
95
+ 3000 / 1000
96
+ } seconds.${color.reset}\n`,
97
+ );
98
+
99
+ setTimeout(() => {
100
+ terminalClient.dispose();
101
+ this.terminalView.removeWidget(terminalClient.id);
102
+ }, 3000);
103
+ });
104
+
105
+ return def.promise;
106
+ }
107
+ }
@@ -58,6 +58,66 @@ export const aiNativePreferenceSchema: PreferenceSchema = {
58
58
  type: 'boolean',
59
59
  default: false,
60
60
  },
61
+ [AINativeSettingSectionsId.LLMModelSelection]: {
62
+ type: 'string',
63
+ default: 'deepseek',
64
+ enum: ['deepseek', 'anthropic', 'openai'],
65
+ description: localize('preference.ai.native.llm.model.selection.description'),
66
+ },
67
+ [AINativeSettingSectionsId.DeepseekApiKey]: {
68
+ type: 'string',
69
+ default: '',
70
+ description: localize('preference.ai.native.deepseek.apiKey.description'),
71
+ },
72
+ [AINativeSettingSectionsId.AnthropicApiKey]: {
73
+ type: 'string',
74
+ default: '',
75
+ description: localize('preference.ai.native.anthropic.apiKey.description'),
76
+ },
77
+ [AINativeSettingSectionsId.OpenaiApiKey]: {
78
+ type: 'string',
79
+ default: '',
80
+ description: localize('preference.ai.native.openai.apiKey.description'),
81
+ },
82
+ [AINativeSettingSectionsId.OpenaiBaseURL]: {
83
+ type: 'string',
84
+ default: '',
85
+ description: localize('preference.ai.native.openai.baseURL.description'),
86
+ },
87
+ [AINativeSettingSectionsId.MCPServers]: {
88
+ type: 'array',
89
+ default: [],
90
+ description: localize('preference.ai.native.mcp.servers.description'),
91
+ items: {
92
+ type: 'object',
93
+ required: ['name', 'command', 'args'],
94
+ properties: {
95
+ name: {
96
+ type: 'string',
97
+ description: localize('preference.ai.native.mcp.servers.name.description'),
98
+ },
99
+ command: {
100
+ type: 'string',
101
+ description: localize('preference.ai.native.mcp.servers.command.description'),
102
+ },
103
+ args: {
104
+ type: 'array',
105
+ items: {
106
+ type: 'string',
107
+ },
108
+ description: localize('preference.ai.native.mcp.servers.args.description'),
109
+ },
110
+ env: {
111
+ type: 'object',
112
+ additionalProperties: {
113
+ type: 'string',
114
+ },
115
+ description: localize('preference.ai.native.mcp.servers.env.description'),
116
+ default: {},
117
+ },
118
+ },
119
+ },
120
+ },
61
121
  [AINativeSettingSectionsId.CodeEditsTyping]: {
62
122
  type: 'boolean',
63
123
  default: false,
@@ -26,6 +26,7 @@ import { SumiReadableStream } from '@opensumi/ide-utils/lib/stream';
26
26
  import { IMarker } from '@opensumi/monaco-editor-core/esm/vs/platform/markers/common/markers';
27
27
 
28
28
  import { IChatWelcomeMessageContent, ISampleQuestions, ITerminalCommandSuggestionDesc } from '../common';
29
+ import { SerializedContext } from '../common/llm-context';
29
30
 
30
31
  import {
31
32
  ICodeEditsContextBean,
@@ -325,6 +326,51 @@ export interface AINativeCoreContribution {
325
326
  * proposed api
326
327
  */
327
328
  registerIntelligentCompletionFeature?(registry: IIntelligentCompletionsRegistry): void;
329
+
330
+ /**
331
+ * 注册 Agent 模式下的 chat prompt provider
332
+ * @param provider
333
+ */
334
+ registerChatAgentPromptProvider?(): void;
335
+ }
336
+
337
+ // MCP Server 的 贡献点
338
+ export const MCPServerContribution = Symbol('MCPServerContribution');
339
+
340
+ export const TokenMCPServerRegistry = Symbol('TokenMCPServerRegistry');
341
+
342
+ export interface MCPServerContribution {
343
+ registerMCPServer(registry: IMCPServerRegistry): void;
344
+ }
345
+
346
+ export interface MCPLogger {
347
+ appendLine(message: string): void;
348
+ }
349
+
350
+ export interface MCPToolDefinition {
351
+ name: string;
352
+ description: string;
353
+ inputSchema: any; // JSON Schema
354
+ handler: (
355
+ args: any,
356
+ logger: MCPLogger,
357
+ ) => Promise<{
358
+ content: { type: string; text: string }[];
359
+ isError?: boolean;
360
+ }>;
361
+ }
362
+
363
+ export interface IMCPServerRegistry {
364
+ registerMCPTool(tool: MCPToolDefinition): void;
365
+ getMCPTools(): MCPToolDefinition[];
366
+ callMCPTool(
367
+ name: string,
368
+ args: any,
369
+ ): Promise<{
370
+ content: { type: string; text: string }[];
371
+ isError?: boolean;
372
+ }>;
373
+ // 后续支持其他 MCP 功能
328
374
  }
329
375
 
330
376
  export interface IChatComponentConfig {
@@ -359,3 +405,13 @@ export interface IAIMiddleware {
359
405
  provideInlineCompletions?: IProvideInlineCompletionsSignature;
360
406
  };
361
407
  }
408
+
409
+ export const ChatAgentPromptProvider = Symbol('ChatAgentPromptProvider');
410
+
411
+ export interface ChatAgentPromptProvider {
412
+ /**
413
+ * 提供上下文提示
414
+ * @param context 上下文
415
+ */
416
+ provideContextPrompt(context: SerializedContext, userMessage: string): MaybePromise<string>;
417
+ }
@@ -16,6 +16,9 @@ import { IChatMessage } from '@opensumi/ide-core-common/lib/types/ai-native';
16
16
  import { DESIGN_MENUBAR_CONTAINER_VIEW_ID } from '@opensumi/ide-design/lib/common/constants';
17
17
  import { IPosition, ITextModel, InlineCompletionContext } from '@opensumi/ide-monaco/lib/common';
18
18
 
19
+ import { MCPServerDescription } from './mcp-server-manager';
20
+ import { MCPTool } from './types';
21
+
19
22
  export const IAINativeService = Symbol('IAINativeService');
20
23
 
21
24
  /**
@@ -116,6 +119,17 @@ export const IChatAgentService = Symbol('IChatAgentService');
116
119
 
117
120
  export const ChatProxyServiceToken = Symbol('ChatProxyServiceToken');
118
121
 
122
+ // 暴露给 Node.js 层,使其可以感知 Opensumi 注册的 MCP 能力
123
+ export const TokenMCPServerProxyService = Symbol('TokenMCPServerProxyService');
124
+
125
+ export interface ISumiMCPServerBackend {
126
+ initBuiltinMCPServer(): void;
127
+ initExternalMCPServers(servers: MCPServerDescription[]): void;
128
+ getAllMCPTools(): Promise<MCPTool[]>;
129
+ }
130
+
131
+ export const SumiMCPServerProxyServicePath = 'SumiMCPServerProxyServicePath';
132
+
119
133
  export interface IChatAgentService {
120
134
  readonly onDidChangeAgents: Event<void>;
121
135
  readonly onDidSendMessage: Event<IChatProgress>;
@@ -0,0 +1,41 @@
1
+ import { Event, URI } from '@opensumi/ide-core-common/lib/utils';
2
+
3
+ export interface LLMContextService {
4
+ startAutoCollection(): void;
5
+
6
+ stopAutoCollection(): void;
7
+
8
+ /**
9
+ * 添加文件到 context 中
10
+ */
11
+ addFileToContext(uri: URI, selection?: [number, number], isManual?: boolean): void;
12
+
13
+ /**
14
+ * 清除上下文
15
+ */
16
+ cleanFileContext(): void;
17
+
18
+ onDidContextFilesChangeEvent: Event<FileContext[]>;
19
+
20
+ /**
21
+ * 从 context 中移除文件
22
+ * @param uri URI
23
+ */
24
+ removeFileFromContext(uri: URI): void;
25
+
26
+ /** 导出为可序列化格式 */
27
+ serialize(): SerializedContext;
28
+ }
29
+
30
+ export interface FileContext {
31
+ uri: URI;
32
+ selection?: [number, number];
33
+ isManual: boolean;
34
+ }
35
+
36
+ export const LLMContextServiceToken = Symbol('LLMContextService');
37
+
38
+ export interface SerializedContext {
39
+ recentlyViewFiles: string[];
40
+ attachedFiles: Array<{ content: string; lineErrors: string[]; path: string; language: string }>;
41
+ }
@@ -0,0 +1,46 @@
1
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
+
3
+ export interface MCPServerManager {
4
+ callTool(serverName: string, toolName: string, arg_string: string): ReturnType<Client['callTool']>;
5
+ removeServer(name: string): void;
6
+ addOrUpdateServer(description: MCPServerDescription): void;
7
+ // invoke in node.js only
8
+ addOrUpdateServerDirectly(server: any): void;
9
+ initBuiltinServer(builtinMCPServer: any): void;
10
+ getTools(serverName: string): ReturnType<Client['listTools']>;
11
+ getServerNames(): Promise<string[]>;
12
+ startServer(serverName: string): Promise<void>;
13
+ stopServer(serverName: string): Promise<void>;
14
+ getStartedServers(): Promise<string[]>;
15
+ registerTools(serverName: string): Promise<void>;
16
+ addExternalMCPServers(servers: MCPServerDescription[]): void;
17
+ }
18
+
19
+ export type MCPTool = Awaited<ReturnType<MCPServerManager['getTools']>>['tools'][number];
20
+
21
+ export type MCPToolParameter = Awaited<ReturnType<MCPServerManager['getTools']>>['tools'][number]['inputSchema'];
22
+
23
+ export interface MCPServerDescription {
24
+ /**
25
+ * The unique name of the MCP server.
26
+ */
27
+ name: string;
28
+
29
+ /**
30
+ * The command to execute the MCP server.
31
+ */
32
+ command: string;
33
+
34
+ /**
35
+ * An array of arguments to pass to the command.
36
+ */
37
+ args?: string[];
38
+
39
+ /**
40
+ * Optional environment variables to set when starting the server.
41
+ */
42
+ env?: { [key: string]: string };
43
+ }
44
+
45
+ export const MCPServerManager = Symbol('MCPServerManager');
46
+ export const MCPServerManagerPath = 'ServicesMCPServerManager';
@@ -0,0 +1,170 @@
1
+ import { z } from 'zod';
2
+
3
+ import { Injectable } from '@opensumi/di';
4
+
5
+ import { MCPToolParameter } from './mcp-server-manager';
6
+
7
+ export const ToolParameterSchema = z.object({
8
+ type: z.enum(['string', 'number', 'boolean', 'object', 'array']),
9
+ description: z.string().optional(),
10
+ enum: z.array(z.any()).optional(),
11
+ items: z.lazy(() => ToolParameterSchema).optional(),
12
+ properties: z.record(z.lazy(() => ToolParameterSchema)).optional(),
13
+ required: z.array(z.string()).optional(),
14
+ });
15
+
16
+ export type ToolParameter = z.infer<typeof ToolParameterSchema>;
17
+
18
+ export interface ToolRequest {
19
+ id: string;
20
+ name: string;
21
+ parameters?: any;
22
+ description?: string;
23
+ handler: (arg_string: string) => Promise<any>;
24
+ providerName?: string;
25
+ }
26
+
27
+ export namespace ToolRequest {
28
+ export function isToolParameter(obj: unknown): obj is ToolParameter {
29
+ return ToolParameterSchema.safeParse(obj).success;
30
+ }
31
+ }
32
+
33
+ export const ToolInvocationRegistry = Symbol('ToolInvocationRegistry');
34
+
35
+ /**
36
+ * 为 Agent 提供的所有可用函数调用的注册表
37
+ */
38
+ export interface ToolInvocationRegistry {
39
+ /**
40
+ * 在注册表中注册一个工具
41
+ *
42
+ * @param tool - 要注册的 `ToolRequest` 对象
43
+ */
44
+ registerTool(tool: ToolRequest): void;
45
+
46
+ /**
47
+ * 从注册表中获取特定的 `ToolRequest`
48
+ *
49
+ * @param toolId - 要获取的工具的唯一标识符
50
+ * @returns 对应提供的工具 ID 的 `ToolRequest` 对象,
51
+ * 如果在注册表中找不到该工具,则返回 `undefined`
52
+ */
53
+ getFunction(toolId: string): ToolRequest | undefined;
54
+
55
+ /**
56
+ * 从注册表中获取多个 `ToolRequest`
57
+ *
58
+ * @param toolIds - 要获取的工具 ID 列表
59
+ * @returns 指定工具 ID 的 `ToolRequest` 对象数组
60
+ * 如果找不到某个工具 ID,将在返回的数组中跳过该工具
61
+ */
62
+ getFunctions(...toolIds: string[]): ToolRequest[];
63
+
64
+ /**
65
+ * 获取当前注册表中的所有 `ToolRequest`
66
+ *
67
+ * @returns 注册表中所有 `ToolRequest` 对象的数组
68
+ */
69
+ getAllFunctions(): ToolRequest[];
70
+
71
+ /**
72
+ * 注销特定工具提供者的所有工具
73
+ *
74
+ * @param providerName - 要移除其工具的工具提供者名称(在 `ToolRequest` 中指定)
75
+ */
76
+ unregisterAllTools(providerName: string): void;
77
+ }
78
+
79
+ export const ToolProvider = Symbol('ToolProvider');
80
+ export interface ToolProvider {
81
+ getTool(): ToolRequest;
82
+ }
83
+
84
+ export class ToolInvocationRegistryImpl implements ToolInvocationRegistry {
85
+ private tools: Map<string, ToolRequest> = new Map<string, ToolRequest>();
86
+
87
+ unregisterAllTools(providerName: string): void {
88
+ const toolsToRemove: string[] = [];
89
+ for (const [id, tool] of this.tools.entries()) {
90
+ if (tool.providerName === providerName) {
91
+ toolsToRemove.push(id);
92
+ }
93
+ }
94
+ toolsToRemove.forEach((id) => this.tools.delete(id));
95
+ }
96
+
97
+ getAllFunctions(): ToolRequest[] {
98
+ return Array.from(this.tools.values());
99
+ }
100
+
101
+ registerTool(tool: ToolRequest): void {
102
+ if (this.tools.has(tool.id)) {
103
+ // TODO: 使用适当的日志机制
104
+ this.tools.set(tool.id, tool);
105
+ } else {
106
+ this.tools.set(tool.id, tool);
107
+ }
108
+ }
109
+
110
+ getFunction(toolId: string): ToolRequest | undefined {
111
+ return this.tools.get(toolId);
112
+ }
113
+
114
+ getFunctions(...toolIds: string[]): ToolRequest[] {
115
+ const tools: ToolRequest[] = toolIds.map((toolId) => {
116
+ const tool = this.tools.get(toolId);
117
+ if (tool) {
118
+ return tool;
119
+ } else {
120
+ throw new Error(`找不到 ID 为 ${toolId} 的函数`);
121
+ }
122
+ });
123
+ return tools;
124
+ }
125
+ }
126
+
127
+ /**
128
+ * 管理多个 ToolInvocationRegistry 实例的管理器,每个实例与一个 clientId 关联
129
+ */
130
+ export interface IToolInvocationRegistryManager {
131
+ /**
132
+ * 获取或创建特定 clientId 的 ToolInvocationRegistry
133
+ */
134
+ getRegistry(clientId: string): ToolInvocationRegistry;
135
+
136
+ /**
137
+ * 移除特定 clientId 的 ToolInvocationRegistry
138
+ */
139
+ removeRegistry(clientId: string): void;
140
+
141
+ /**
142
+ * 检查特定 clientId 是否存在对应的注册表
143
+ */
144
+ hasRegistry(clientId: string): boolean;
145
+ }
146
+
147
+ export const ToolInvocationRegistryManager = Symbol('ToolInvocationRegistryManager');
148
+
149
+ @Injectable()
150
+ export class ToolInvocationRegistryManagerImpl implements IToolInvocationRegistryManager {
151
+ private registries: Map<string, ToolInvocationRegistry> = new Map();
152
+
153
+ getRegistry(clientId: string): ToolInvocationRegistry {
154
+ let registry = this.registries.get(clientId);
155
+ if (!registry) {
156
+ registry = new ToolInvocationRegistryImpl();
157
+ this.registries.set(clientId, registry);
158
+ }
159
+ return registry;
160
+ }
161
+
162
+ removeRegistry(clientId: string): void {
163
+ this.registries.delete(clientId);
164
+ }
165
+
166
+ hasRegistry(clientId: string): boolean {
167
+ return this.registries.has(clientId);
168
+ }
169
+ }
170
+
@@ -18,3 +18,25 @@ export interface INearestCodeBlock {
18
18
  offset: number;
19
19
  type?: NearestCodeBlockType;
20
20
  }
21
+
22
+ // SUMI MCP Server 网页部分暴露给 Node.js 部分的能力
23
+ export interface IMCPServerProxyService {
24
+ $callMCPTool(
25
+ name: string,
26
+ args: any,
27
+ ): Promise<{
28
+ content: { type: string; text: string }[];
29
+ isError?: boolean;
30
+ }>;
31
+ // 获取 browser 层注册的 MCP 工具列表 (Browser tab 维度)
32
+ $getMCPTools(): Promise<MCPTool[]>;
33
+ // 通知前端 MCP 服务注册表发生了变化
34
+ $updateMCPServers(): Promise<void>;
35
+ }
36
+
37
+ export interface MCPTool {
38
+ name: string;
39
+ description: string;
40
+ inputSchema: any;
41
+ providerName: string;
42
+ }
@@ -0,0 +1,25 @@
1
+ import { AnthropicProvider, createAnthropic } from '@ai-sdk/anthropic';
2
+
3
+ import { Injectable } from '@opensumi/di';
4
+ import { IAIBackServiceOption } from '@opensumi/ide-core-common';
5
+ import { AINativeSettingSectionsId } from '@opensumi/ide-core-common/lib/settings/ai-native';
6
+
7
+ import { BaseLanguageModel } from '../base-language-model';
8
+
9
+ export const AnthropicModelIdentifier = Symbol('AnthropicModelIdentifier');
10
+
11
+ @Injectable()
12
+ export class AnthropicModel extends BaseLanguageModel {
13
+ protected initializeProvider(options: IAIBackServiceOption): AnthropicProvider {
14
+ const apiKey = options.apiKey;
15
+ if (!apiKey) {
16
+ throw new Error(`Please provide Anthropic API Key in preferences (${AINativeSettingSectionsId.AnthropicApiKey})`);
17
+ }
18
+
19
+ return createAnthropic({ apiKey });
20
+ }
21
+
22
+ protected getModelIdentifier(provider: AnthropicProvider) {
23
+ return provider('claude-3-5-sonnet-20241022');
24
+ }
25
+ }