@opensumi/ide-ai-native 3.7.2-next-1740107209.0 → 3.7.2-next-1740365741.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 (180) hide show
  1. package/lib/browser/ai-core.contribution.d.ts +3 -1
  2. package/lib/browser/ai-core.contribution.d.ts.map +1 -1
  3. package/lib/browser/ai-core.contribution.js +13 -1
  4. package/lib/browser/ai-core.contribution.js.map +1 -1
  5. package/lib/browser/chat/chat-manager.service.d.ts +30 -2
  6. package/lib/browser/chat/chat-manager.service.d.ts.map +1 -1
  7. package/lib/browser/chat/chat-manager.service.js +45 -1
  8. package/lib/browser/chat/chat-manager.service.js.map +1 -1
  9. package/lib/browser/chat/chat-model.d.ts +33 -6
  10. package/lib/browser/chat/chat-model.d.ts.map +1 -1
  11. package/lib/browser/chat/chat-model.js +50 -29
  12. package/lib/browser/chat/chat-model.js.map +1 -1
  13. package/lib/browser/chat/chat-proxy.service.d.ts +1 -1
  14. package/lib/browser/chat/chat-proxy.service.d.ts.map +1 -1
  15. package/lib/browser/chat/chat-proxy.service.js +1 -1
  16. package/lib/browser/chat/chat-proxy.service.js.map +1 -1
  17. package/lib/browser/chat/chat.internal.service.d.ts +4 -2
  18. package/lib/browser/chat/chat.internal.service.d.ts.map +1 -1
  19. package/lib/browser/chat/chat.internal.service.js +31 -12
  20. package/lib/browser/chat/chat.internal.service.js.map +1 -1
  21. package/lib/browser/chat/chat.module.less +8 -42
  22. package/lib/browser/chat/chat.view.d.ts.map +1 -1
  23. package/lib/browser/chat/chat.view.js +85 -31
  24. package/lib/browser/chat/chat.view.js.map +1 -1
  25. package/lib/browser/components/ChatContext/index.d.ts.map +1 -1
  26. package/lib/browser/components/ChatContext/index.js +18 -2
  27. package/lib/browser/components/ChatContext/index.js.map +1 -1
  28. package/lib/browser/components/ChatContext/style.module.less +12 -0
  29. package/lib/browser/components/ChatHistory.d.ts +21 -0
  30. package/lib/browser/components/ChatHistory.d.ts.map +1 -0
  31. package/lib/browser/components/ChatHistory.js +148 -0
  32. package/lib/browser/components/ChatHistory.js.map +1 -0
  33. package/lib/browser/components/ChatReply.d.ts.map +1 -1
  34. package/lib/browser/components/ChatReply.js +3 -1
  35. package/lib/browser/components/ChatReply.js.map +1 -1
  36. package/lib/browser/components/ChatThinking.js +1 -1
  37. package/lib/browser/components/ChatThinking.js.map +1 -1
  38. package/lib/browser/components/ChatToolRender.d.ts +1 -1
  39. package/lib/browser/components/ChatToolRender.d.ts.map +1 -1
  40. package/lib/browser/components/ChatToolRender.js +15 -18
  41. package/lib/browser/components/ChatToolRender.js.map +1 -1
  42. package/lib/browser/components/chat-history.css +139 -0
  43. package/lib/browser/components/components.module.less +2 -2
  44. package/lib/browser/components/utils.d.ts +2 -2
  45. package/lib/browser/context/llm-context.service.d.ts +1 -0
  46. package/lib/browser/context/llm-context.service.d.ts.map +1 -1
  47. package/lib/browser/context/llm-context.service.js +24 -18
  48. package/lib/browser/context/llm-context.service.js.map +1 -1
  49. package/lib/browser/index.d.ts.map +1 -1
  50. package/lib/browser/index.js +5 -13
  51. package/lib/browser/index.js.map +1 -1
  52. package/lib/browser/layout/layout.module.less +1 -1
  53. package/lib/browser/mcp/mcp-server.feature.registry.d.ts.map +1 -1
  54. package/lib/browser/mcp/mcp-server.feature.registry.js +2 -1
  55. package/lib/browser/mcp/mcp-server.feature.registry.js.map +1 -1
  56. package/lib/browser/mcp/tools/components/SearchResult.d.ts +11 -0
  57. package/lib/browser/mcp/tools/components/SearchResult.d.ts.map +1 -0
  58. package/lib/browser/mcp/tools/components/SearchResult.js +60 -0
  59. package/lib/browser/mcp/tools/components/SearchResult.js.map +1 -0
  60. package/lib/browser/mcp/tools/components/Terminal.d.ts +4 -0
  61. package/lib/browser/mcp/tools/components/Terminal.d.ts.map +1 -0
  62. package/lib/browser/mcp/tools/components/Terminal.js +64 -0
  63. package/lib/browser/mcp/tools/components/Terminal.js.map +1 -0
  64. package/lib/browser/mcp/tools/components/index.module.less +101 -0
  65. package/lib/browser/mcp/tools/{findFilesByNameSubstring.d.ts → fileSearch.d.ts} +3 -2
  66. package/lib/browser/mcp/tools/fileSearch.d.ts.map +1 -0
  67. package/lib/browser/mcp/tools/fileSearch.js +94 -0
  68. package/lib/browser/mcp/tools/fileSearch.js.map +1 -0
  69. package/lib/browser/mcp/tools/{getFileTextByPath.d.ts → grepSearch.d.ts} +4 -3
  70. package/lib/browser/mcp/tools/grepSearch.d.ts.map +1 -0
  71. package/lib/browser/mcp/tools/grepSearch.js +118 -0
  72. package/lib/browser/mcp/tools/grepSearch.js.map +1 -0
  73. package/lib/browser/mcp/tools/handlers/RunCommand.d.ts +43 -0
  74. package/lib/browser/mcp/tools/handlers/RunCommand.d.ts.map +1 -0
  75. package/lib/browser/mcp/tools/handlers/RunCommand.js +104 -0
  76. package/lib/browser/mcp/tools/handlers/RunCommand.js.map +1 -0
  77. package/lib/browser/mcp/tools/listDir.d.ts.map +1 -1
  78. package/lib/browser/mcp/tools/listDir.js +1 -0
  79. package/lib/browser/mcp/tools/listDir.js.map +1 -1
  80. package/lib/browser/mcp/tools/readFile.d.ts.map +1 -1
  81. package/lib/browser/mcp/tools/readFile.js +1 -0
  82. package/lib/browser/mcp/tools/readFile.js.map +1 -1
  83. package/lib/browser/mcp/tools/runTerminalCmd.d.ts +1 -6
  84. package/lib/browser/mcp/tools/runTerminalCmd.d.ts.map +1 -1
  85. package/lib/browser/mcp/tools/runTerminalCmd.js +9 -55
  86. package/lib/browser/mcp/tools/runTerminalCmd.js.map +1 -1
  87. package/lib/browser/model/msg-history-manager.d.ts +15 -0
  88. package/lib/browser/model/msg-history-manager.d.ts.map +1 -1
  89. package/lib/browser/model/msg-history-manager.js +28 -9
  90. package/lib/browser/model/msg-history-manager.js.map +1 -1
  91. package/lib/common/mcp-server-manager.d.ts +1 -1
  92. package/lib/common/mcp-server-manager.d.ts.map +1 -1
  93. package/lib/common/mcp-server-manager.js.map +1 -1
  94. package/lib/common/tool-invocation-registry.d.ts +2 -1
  95. package/lib/common/tool-invocation-registry.d.ts.map +1 -1
  96. package/lib/common/tool-invocation-registry.js.map +1 -1
  97. package/lib/node/base-language-model.d.ts.map +1 -1
  98. package/lib/node/base-language-model.js +1 -1
  99. package/lib/node/base-language-model.js.map +1 -1
  100. package/lib/node/mcp/sumi-mcp-server.d.ts +1 -1
  101. package/lib/node/mcp/sumi-mcp-server.d.ts.map +1 -1
  102. package/lib/node/mcp/sumi-mcp-server.js +5 -2
  103. package/lib/node/mcp/sumi-mcp-server.js.map +1 -1
  104. package/lib/node/mcp-server-manager-impl.d.ts +1 -1
  105. package/lib/node/mcp-server-manager-impl.d.ts.map +1 -1
  106. package/lib/node/mcp-server-manager-impl.js +4 -4
  107. package/lib/node/mcp-server-manager-impl.js.map +1 -1
  108. package/lib/node/mcp-server.d.ts +2 -2
  109. package/lib/node/mcp-server.d.ts.map +1 -1
  110. package/lib/node/mcp-server.js +2 -1
  111. package/lib/node/mcp-server.js.map +1 -1
  112. package/package.json +23 -22
  113. package/src/browser/ai-core.contribution.ts +13 -1
  114. package/src/browser/chat/chat-manager.service.ts +83 -7
  115. package/src/browser/chat/chat-model.ts +62 -12
  116. package/src/browser/chat/chat-proxy.service.ts +1 -1
  117. package/src/browser/chat/chat.internal.service.ts +23 -5
  118. package/src/browser/chat/chat.module.less +8 -42
  119. package/src/browser/chat/chat.view.tsx +143 -60
  120. package/src/browser/components/ChatContext/index.tsx +19 -3
  121. package/src/browser/components/ChatContext/style.module.less +12 -0
  122. package/src/browser/components/ChatHistory.tsx +292 -0
  123. package/src/browser/components/ChatReply.tsx +5 -1
  124. package/src/browser/components/ChatThinking.tsx +1 -1
  125. package/src/browser/components/ChatToolRender.tsx +13 -15
  126. package/src/browser/components/chat-history.css +139 -0
  127. package/src/browser/components/components.module.less +2 -2
  128. package/src/browser/context/llm-context.service.ts +30 -18
  129. package/src/browser/index.ts +5 -13
  130. package/src/browser/layout/layout.module.less +1 -1
  131. package/src/browser/mcp/mcp-server.feature.registry.ts +2 -1
  132. package/src/browser/mcp/tools/components/SearchResult.tsx +92 -0
  133. package/src/browser/mcp/tools/components/Terminal.tsx +97 -0
  134. package/src/browser/mcp/tools/components/index.module.less +101 -0
  135. package/src/browser/mcp/tools/fileSearch.ts +99 -0
  136. package/src/browser/mcp/tools/grepSearch.ts +121 -0
  137. package/src/browser/mcp/tools/handlers/RunCommand.ts +115 -0
  138. package/src/browser/mcp/tools/listDir.ts +1 -0
  139. package/src/browser/mcp/tools/readFile.ts +1 -0
  140. package/src/browser/mcp/tools/runTerminalCmd.ts +7 -68
  141. package/src/browser/model/msg-history-manager.ts +34 -1
  142. package/src/common/mcp-server-manager.ts +18 -13
  143. package/src/common/tool-invocation-registry.ts +122 -124
  144. package/src/node/base-language-model.ts +3 -2
  145. package/src/node/mcp/sumi-mcp-server.ts +5 -2
  146. package/src/node/mcp-server-manager-impl.ts +11 -4
  147. package/src/node/mcp-server.ts +3 -2
  148. package/lib/browser/mcp/tools/findFilesByNameSubstring.d.ts.map +0 -1
  149. package/lib/browser/mcp/tools/findFilesByNameSubstring.js +0 -91
  150. package/lib/browser/mcp/tools/findFilesByNameSubstring.js.map +0 -1
  151. package/lib/browser/mcp/tools/getCurrentFilePath.d.ts +0 -8
  152. package/lib/browser/mcp/tools/getCurrentFilePath.d.ts.map +0 -1
  153. package/lib/browser/mcp/tools/getCurrentFilePath.js +0 -48
  154. package/lib/browser/mcp/tools/getCurrentFilePath.js.map +0 -1
  155. package/lib/browser/mcp/tools/getFileTextByPath.d.ts.map +0 -1
  156. package/lib/browser/mcp/tools/getFileTextByPath.js +0 -96
  157. package/lib/browser/mcp/tools/getFileTextByPath.js.map +0 -1
  158. package/lib/browser/mcp/tools/getOpenEditorFileText.d.ts +0 -8
  159. package/lib/browser/mcp/tools/getOpenEditorFileText.d.ts.map +0 -1
  160. package/lib/browser/mcp/tools/getOpenEditorFileText.js +0 -49
  161. package/lib/browser/mcp/tools/getOpenEditorFileText.js.map +0 -1
  162. package/lib/browser/mcp/tools/getSelectedText.d.ts +0 -8
  163. package/lib/browser/mcp/tools/getSelectedText.d.ts.map +0 -1
  164. package/lib/browser/mcp/tools/getSelectedText.js +0 -56
  165. package/lib/browser/mcp/tools/getSelectedText.js.map +0 -1
  166. package/lib/browser/mcp/tools/replaceOpenEditorFile.d.ts +0 -8
  167. package/lib/browser/mcp/tools/replaceOpenEditorFile.d.ts.map +0 -1
  168. package/lib/browser/mcp/tools/replaceOpenEditorFile.js +0 -80
  169. package/lib/browser/mcp/tools/replaceOpenEditorFile.js.map +0 -1
  170. package/lib/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.d.ts +0 -8
  171. package/lib/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.d.ts.map +0 -1
  172. package/lib/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.js +0 -83
  173. package/lib/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.js.map +0 -1
  174. package/src/browser/mcp/tools/findFilesByNameSubstring.ts +0 -92
  175. package/src/browser/mcp/tools/getCurrentFilePath.ts +0 -48
  176. package/src/browser/mcp/tools/getFileTextByPath.ts +0 -96
  177. package/src/browser/mcp/tools/getOpenEditorFileText.ts +0 -49
  178. package/src/browser/mcp/tools/getSelectedText.ts +0 -56
  179. package/src/browser/mcp/tools/replaceOpenEditorFile.ts +0 -81
  180. package/src/browser/mcp/tools/replaceOpenEditorFileByDiffPreviewer.ts +0 -90
@@ -7,23 +7,8 @@ import { ITerminalController, ITerminalGroupViewService } from '@opensumi/ide-te
7
7
 
8
8
  import { IMCPServerRegistry, MCPLogger, MCPServerContribution, MCPToolDefinition } from '../../types';
9
9
 
10
- const color = {
11
- italic: '\x1b[3m',
12
- reset: '\x1b[0m',
13
- };
14
-
15
- const inputSchema = z.object({
16
- command: z.string().describe('The terminal command to execute'),
17
- is_background: z.boolean().describe('Whether the command should be run in the background'),
18
- explanation: z
19
- .string()
20
- .describe('One sentence explanation as to why this command needs to be run and how it contributes to the goal.'),
21
- require_user_approval: z
22
- .boolean()
23
- .describe(
24
- "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.",
25
- ),
26
- });
10
+ import { TerminalToolComponent } from './components/Terminal';
11
+ import { RunCommandHandler, inputSchema } from './handlers/RunCommand';
27
12
 
28
13
  @Domain(MCPServerContribution)
29
14
  export class RunTerminalCommandTool implements MCPServerContribution {
@@ -36,10 +21,12 @@ export class RunTerminalCommandTool implements MCPServerContribution {
36
21
  @Autowired(ITerminalGroupViewService)
37
22
  protected readonly terminalView: ITerminalGroupViewService;
38
23
 
39
- private terminalId = 0;
24
+ @Autowired(RunCommandHandler)
25
+ private readonly runCommandHandler: RunCommandHandler;
40
26
 
41
27
  registerMCPServer(registry: IMCPServerRegistry): void {
42
28
  registry.registerMCPTool(this.getToolDefinition());
29
+ registry.registerToolComponent('run_terminal_cmd', TerminalToolComponent);
43
30
  }
44
31
 
45
32
  getToolDefinition(): MCPToolDefinition {
@@ -52,55 +39,7 @@ export class RunTerminalCommandTool implements MCPServerContribution {
52
39
  };
53
40
  }
54
41
 
55
- getShellLaunchConfig(command: string) {
56
- return {
57
- name: `MCP:Terminal_${this.terminalId++}`,
58
- cwd: this.appConfig.workspaceDir,
59
- args: ['-c', command],
60
- };
61
- }
62
-
63
- private async handler(args: z.infer<typeof inputSchema>, logger: MCPLogger) {
64
- if (args.require_user_approval) {
65
- // FIXME: support approval
66
- }
67
-
68
- const terminalClient = await this.terminalController.createTerminalWithWidget({
69
- config: this.getShellLaunchConfig(args.command),
70
- closeWhenExited: false,
71
- });
72
-
73
- this.terminalController.showTerminalPanel();
74
-
75
- const result: { type: string; text: string }[] = [];
76
- const def = new Deferred<{ isError?: boolean; content: { type: string; text: string }[] }>();
77
-
78
- terminalClient.onOutput((e) => {
79
- result.push({
80
- type: 'output',
81
- text: e.data.toString(),
82
- });
83
- });
84
-
85
- terminalClient.onExit((e) => {
86
- const isError = e.code !== 0;
87
- def.resolve({
88
- isError,
89
- content: result,
90
- });
91
-
92
- terminalClient.term.writeln(
93
- `\n${color.italic}> Command ${args.command} executed successfully. Terminal will close in ${
94
- 3000 / 1000
95
- } seconds.${color.reset}\n`,
96
- );
97
-
98
- setTimeout(() => {
99
- terminalClient.dispose();
100
- this.terminalView.removeWidget(terminalClient.id);
101
- }, 3000);
102
- });
103
-
104
- return def.promise;
42
+ private async handler(args: z.infer<typeof inputSchema> & { toolCallId: string }, logger: MCPLogger) {
43
+ return this.runCommandHandler.handler(args, logger);
105
44
  }
106
45
  }
@@ -5,13 +5,24 @@ import { IHistoryChatMessage } from '@opensumi/ide-core-common/lib/types/ai-nati
5
5
 
6
6
  type IExcludeMessage = Omit<IHistoryChatMessage, 'id' | 'order'>;
7
7
 
8
- @Injectable({ multiple: false })
9
8
  export class MsgHistoryManager extends Disposable {
10
9
  private messageMap: Map<string, IHistoryChatMessage> = new Map();
10
+ private messageAdditionalMap: Map<string, Record<string, any>> = new Map();
11
11
 
12
12
  private readonly _onMessageChange = new Emitter<IHistoryChatMessage[]>();
13
13
  public readonly onMessageChange: Event<IHistoryChatMessage[]> = this._onMessageChange.event;
14
14
 
15
+ private readonly _onMessageAdditionalChange = new Emitter<Record<string, any>>();
16
+ public readonly onMessageAdditionalChange: Event<Record<string, any>> = this._onMessageAdditionalChange.event;
17
+
18
+ constructor(data?: { additional: Record<string, any>; messages: IHistoryChatMessage[] }) {
19
+ super();
20
+ if (data) {
21
+ this.messageMap = new Map(data.messages.map((item) => [item.id, item]));
22
+ this.messageAdditionalMap = new Map(Object.entries(data.additional));
23
+ }
24
+ }
25
+
15
26
  override dispose(): void {
16
27
  this.clearMessages();
17
28
  super.dispose();
@@ -19,6 +30,7 @@ export class MsgHistoryManager extends Disposable {
19
30
 
20
31
  public clearMessages() {
21
32
  this.messageMap.clear();
33
+ this.messageAdditionalMap.clear();
22
34
  }
23
35
 
24
36
  private doAddMessage(message: IExcludeMessage): string {
@@ -70,4 +82,25 @@ export class MsgHistoryManager extends Disposable {
70
82
  content: message.content,
71
83
  });
72
84
  }
85
+
86
+ public setMessageAdditional(id: string, additional: Record<string, any>) {
87
+ if (!this.messageMap.has(id)) {
88
+ return;
89
+ }
90
+
91
+ this.messageAdditionalMap.set(id, additional);
92
+
93
+ this._onMessageAdditionalChange.fire(additional);
94
+ }
95
+
96
+ public getMessageAdditional(id: string): Record<string, any> {
97
+ return this.messageAdditionalMap.get(id) || {};
98
+ }
99
+
100
+ toJSON() {
101
+ return {
102
+ messages: this.getMessages(),
103
+ additional: Object.fromEntries(this.messageAdditionalMap.entries()),
104
+ };
105
+ }
73
106
  }
@@ -1,19 +1,24 @@
1
1
  import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
2
 
3
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;
4
+ callTool(
5
+ serverName: string,
6
+ toolName: string,
7
+ toolCallId: string,
8
+ arg_string: string,
9
+ ): ReturnType<Client['callTool']>;
10
+ removeServer(name: string): void;
11
+ addOrUpdateServer(description: MCPServerDescription): void;
12
+ // invoke in node.js only
13
+ addOrUpdateServerDirectly(server: any): void;
14
+ initBuiltinServer(builtinMCPServer: any): void;
15
+ getTools(serverName: string): ReturnType<Client['listTools']>;
16
+ getServerNames(): Promise<string[]>;
17
+ startServer(serverName: string): Promise<void>;
18
+ stopServer(serverName: string): Promise<void>;
19
+ getStartedServers(): Promise<string[]>;
20
+ registerTools(serverName: string): Promise<void>;
21
+ addExternalMCPServers(servers: MCPServerDescription[]): void;
17
22
  }
18
23
 
19
24
  export type MCPTool = Awaited<ReturnType<MCPServerManager['getTools']>>['tools'][number];
@@ -1,33 +1,32 @@
1
+ import { ToolExecutionOptions } from 'ai';
1
2
  import { z } from 'zod';
2
3
 
3
4
  import { Injectable } from '@opensumi/di';
4
5
 
5
- import { MCPToolParameter } from './mcp-server-manager';
6
-
7
6
  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(),
7
+ type: z.enum(['string', 'number', 'boolean', 'object', 'array']),
8
+ description: z.string().optional(),
9
+ enum: z.array(z.any()).optional(),
10
+ items: z.lazy(() => ToolParameterSchema).optional(),
11
+ properties: z.record(z.lazy(() => ToolParameterSchema)).optional(),
12
+ required: z.array(z.string()).optional(),
14
13
  });
15
14
 
16
15
  export type ToolParameter = z.infer<typeof ToolParameterSchema>;
17
16
 
18
17
  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;
18
+ id: string;
19
+ name: string;
20
+ parameters?: any;
21
+ description?: string;
22
+ handler: (arg_string: string, options?: ToolExecutionOptions) => Promise<any>;
23
+ providerName?: string;
25
24
  }
26
25
 
27
26
  export namespace ToolRequest {
28
- export function isToolParameter(obj: unknown): obj is ToolParameter {
29
- return ToolParameterSchema.safeParse(obj).success;
30
- }
27
+ export function isToolParameter(obj: unknown): obj is ToolParameter {
28
+ return ToolParameterSchema.safeParse(obj).success;
29
+ }
31
30
  }
32
31
 
33
32
  export const ToolInvocationRegistry = Symbol('ToolInvocationRegistry');
@@ -36,135 +35,134 @@ export const ToolInvocationRegistry = Symbol('ToolInvocationRegistry');
36
35
  * 为 Agent 提供的所有可用函数调用的注册表
37
36
  */
38
37
  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;
38
+ /**
39
+ * 在注册表中注册一个工具
40
+ *
41
+ * @param tool - 要注册的 `ToolRequest` 对象
42
+ */
43
+ registerTool(tool: ToolRequest): void;
44
+
45
+ /**
46
+ * 从注册表中获取特定的 `ToolRequest`
47
+ *
48
+ * @param toolId - 要获取的工具的唯一标识符
49
+ * @returns 对应提供的工具 ID 的 `ToolRequest` 对象,
50
+ * 如果在注册表中找不到该工具,则返回 `undefined`
51
+ */
52
+ getFunction(toolId: string): ToolRequest | undefined;
53
+
54
+ /**
55
+ * 从注册表中获取多个 `ToolRequest`
56
+ *
57
+ * @param toolIds - 要获取的工具 ID 列表
58
+ * @returns 指定工具 ID 的 `ToolRequest` 对象数组
59
+ * 如果找不到某个工具 ID,将在返回的数组中跳过该工具
60
+ */
61
+ getFunctions(...toolIds: string[]): ToolRequest[];
62
+
63
+ /**
64
+ * 获取当前注册表中的所有 `ToolRequest`
65
+ *
66
+ * @returns 注册表中所有 `ToolRequest` 对象的数组
67
+ */
68
+ getAllFunctions(): ToolRequest[];
69
+
70
+ /**
71
+ * 注销特定工具提供者的所有工具
72
+ *
73
+ * @param providerName - 要移除其工具的工具提供者名称(在 `ToolRequest` 中指定)
74
+ */
75
+ unregisterAllTools(providerName: string): void;
77
76
  }
78
77
 
79
78
  export const ToolProvider = Symbol('ToolProvider');
80
79
  export interface ToolProvider {
81
- getTool(): ToolRequest;
80
+ getTool(): ToolRequest;
82
81
  }
83
82
 
84
83
  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());
84
+ private tools: Map<string, ToolRequest> = new Map<string, ToolRequest>();
85
+
86
+ unregisterAllTools(providerName: string): void {
87
+ const toolsToRemove: string[] = [];
88
+ for (const [id, tool] of this.tools.entries()) {
89
+ if (tool.providerName === providerName) {
90
+ toolsToRemove.push(id);
91
+ }
99
92
  }
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;
93
+ toolsToRemove.forEach((id) => this.tools.delete(id));
94
+ }
95
+
96
+ getAllFunctions(): ToolRequest[] {
97
+ return Array.from(this.tools.values());
98
+ }
99
+
100
+ registerTool(tool: ToolRequest): void {
101
+ if (this.tools.has(tool.id)) {
102
+ // TODO: 使用适当的日志机制
103
+ this.tools.set(tool.id, tool);
104
+ } else {
105
+ this.tools.set(tool.id, tool);
124
106
  }
107
+ }
108
+
109
+ getFunction(toolId: string): ToolRequest | undefined {
110
+ return this.tools.get(toolId);
111
+ }
112
+
113
+ getFunctions(...toolIds: string[]): ToolRequest[] {
114
+ const tools: ToolRequest[] = toolIds.map((toolId) => {
115
+ const tool = this.tools.get(toolId);
116
+ if (tool) {
117
+ return tool;
118
+ } else {
119
+ throw new Error(`找不到 ID 为 ${toolId} 的函数`);
120
+ }
121
+ });
122
+ return tools;
123
+ }
125
124
  }
126
125
 
127
126
  /**
128
127
  * 管理多个 ToolInvocationRegistry 实例的管理器,每个实例与一个 clientId 关联
129
128
  */
130
129
  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;
130
+ /**
131
+ * 获取或创建特定 clientId 的 ToolInvocationRegistry
132
+ */
133
+ getRegistry(clientId: string): ToolInvocationRegistry;
134
+
135
+ /**
136
+ * 移除特定 clientId 的 ToolInvocationRegistry
137
+ */
138
+ removeRegistry(clientId: string): void;
139
+
140
+ /**
141
+ * 检查特定 clientId 是否存在对应的注册表
142
+ */
143
+ hasRegistry(clientId: string): boolean;
145
144
  }
146
145
 
147
146
  export const ToolInvocationRegistryManager = Symbol('ToolInvocationRegistryManager');
148
147
 
149
148
  @Injectable()
150
149
  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
- }
150
+ private registries: Map<string, ToolInvocationRegistry> = new Map();
161
151
 
162
- removeRegistry(clientId: string): void {
163
- this.registries.delete(clientId);
152
+ getRegistry(clientId: string): ToolInvocationRegistry {
153
+ let registry = this.registries.get(clientId);
154
+ if (!registry) {
155
+ registry = new ToolInvocationRegistryImpl();
156
+ this.registries.set(clientId, registry);
164
157
  }
158
+ return registry;
159
+ }
165
160
 
166
- hasRegistry(clientId: string): boolean {
167
- return this.registries.has(clientId);
168
- }
169
- }
161
+ removeRegistry(clientId: string): void {
162
+ this.registries.delete(clientId);
163
+ }
170
164
 
165
+ hasRegistry(clientId: string): boolean {
166
+ return this.registries.has(clientId);
167
+ }
168
+ }
@@ -1,4 +1,4 @@
1
- import { CoreMessage, jsonSchema, streamText, tool } from 'ai';
1
+ import { CoreMessage, ToolExecutionOptions, jsonSchema, streamText, tool } from 'ai';
2
2
 
3
3
  import { Autowired, Injectable } from '@opensumi/di';
4
4
  import { ChatMessageRole, IAIBackServiceOption, IChatMessage } from '@opensumi/ide-core-common';
@@ -66,7 +66,8 @@ export abstract class BaseLanguageModel {
66
66
  description: toolRequest.description || '',
67
67
  // TODO 这里应该是 z.object 而不是 JSON Schema
68
68
  parameters: jsonSchema(toolRequest.parameters),
69
- execute: async (args: any) => await toolRequest.handler(JSON.stringify(args)),
69
+ execute: async (args: any, options: ToolExecutionOptions) =>
70
+ await toolRequest.handler(JSON.stringify(args), options),
70
71
  });
71
72
  }
72
73
 
@@ -156,7 +156,7 @@ export class BuiltinMCPServer implements IMCPServer {
156
156
  this.started = true;
157
157
  }
158
158
 
159
- async callTool(toolName: string, arg_string: string): Promise<any> {
159
+ async callTool(toolName: string, toolCallId: string, arg_string: string): Promise<any> {
160
160
  if (!this.started) {
161
161
  throw new Error('MCP Server not started');
162
162
  }
@@ -171,7 +171,10 @@ export class BuiltinMCPServer implements IMCPServer {
171
171
  );
172
172
  throw error;
173
173
  }
174
- return this.sumiMCPServer.callMCPTool(toolName, args);
174
+ return this.sumiMCPServer.callMCPTool(toolName, {
175
+ ...args,
176
+ toolCallId,
177
+ });
175
178
  }
176
179
 
177
180
  async getTools(): ReturnType<Client['listTools']> {
@@ -1,3 +1,5 @@
1
+ import { ToolExecutionOptions } from 'ai';
2
+
1
3
  import { ILogger } from '@opensumi/ide-core-common';
2
4
 
3
5
  import { MCPServerDescription, MCPServerManager, MCPTool } from '../common/mcp-server-manager';
@@ -42,12 +44,17 @@ export class MCPServerManagerImpl implements MCPServerManager {
42
44
  return startedServers;
43
45
  }
44
46
 
45
- callTool(serverName: string, toolName: string, arg_string: string): ReturnType<IMCPServer['callTool']> {
47
+ callTool(
48
+ serverName: string,
49
+ toolName: string,
50
+ toolCallId: string,
51
+ arg_string: string,
52
+ ): ReturnType<IMCPServer['callTool']> {
46
53
  const server = this.servers.get(serverName);
47
54
  if (!server) {
48
55
  throw new Error(`MCP server "${toolName}" not found.`);
49
56
  }
50
- return server.callTool(toolName, arg_string);
57
+ return server.callTool(toolName, toolCallId, arg_string);
51
58
  }
52
59
 
53
60
  async startServer(serverName: string): Promise<void> {
@@ -71,9 +78,9 @@ export class MCPServerManagerImpl implements MCPServerManager {
71
78
  providerName: serverName,
72
79
  parameters: tool.inputSchema,
73
80
  description: tool.description,
74
- handler: async (arg_string: string) => {
81
+ handler: async (arg_string: string, options?: ToolExecutionOptions) => {
75
82
  try {
76
- const res = await this.callTool(serverName, tool.name, arg_string);
83
+ const res = await this.callTool(serverName, tool.name, options?.toolCallId || '', arg_string);
77
84
  this.logger.debug(`[MCP: ${serverName}] ${tool.name} called with ${arg_string}`);
78
85
  this.logger.debug('Tool execution result:', res);
79
86
  return JSON.stringify(res);
@@ -8,7 +8,7 @@ export interface IMCPServer {
8
8
  isStarted(): boolean;
9
9
  start(): Promise<void>;
10
10
  getServerName(): string;
11
- callTool(toolName: string, arg_string: string): ReturnType<Client['callTool']>;
11
+ callTool(toolName: string, toolCallId: string, arg_string: string): ReturnType<Client['callTool']>;
12
12
  getTools(): ReturnType<Client['listTools']>;
13
13
  update(command: string, args?: string[], env?: { [key: string]: string }): void;
14
14
  stop(): void;
@@ -87,7 +87,7 @@ export class MCPServerImpl implements IMCPServer {
87
87
  this.started = true;
88
88
  }
89
89
 
90
- async callTool(toolName: string, arg_string: string) {
90
+ async callTool(toolName: string, toolCallId: string, arg_string: string) {
91
91
  let args;
92
92
  try {
93
93
  args = JSON.parse(arg_string);
@@ -101,6 +101,7 @@ export class MCPServerImpl implements IMCPServer {
101
101
  const params = {
102
102
  name: toolName,
103
103
  arguments: args,
104
+ toolCallId,
104
105
  };
105
106
  return this.client.callTool(params);
106
107
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"findFilesByNameSubstring.d.ts","sourceRoot":"","sources":["../../../../src/browser/mcp/tools/findFilesByNameSubstring.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,kBAAkB,EAAa,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAMtG,qBACa,4BAA6B,YAAW,qBAAqB;IAExE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAoB;IAGrD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAqB;IAEvD,iBAAiB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI;IAIrD,iBAAiB,IAAI,iBAAiB;YAiBxB,OAAO;CA+CtB"}