@opensumi/ide-ai-native 3.7.2-next-1740323956.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 (73) 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/ChatHistory.d.ts +21 -0
  26. package/lib/browser/components/ChatHistory.d.ts.map +1 -0
  27. package/lib/browser/components/ChatHistory.js +148 -0
  28. package/lib/browser/components/ChatHistory.js.map +1 -0
  29. package/lib/browser/components/ChatReply.d.ts.map +1 -1
  30. package/lib/browser/components/ChatReply.js +3 -1
  31. package/lib/browser/components/ChatReply.js.map +1 -1
  32. package/lib/browser/components/ChatThinking.js +1 -1
  33. package/lib/browser/components/ChatThinking.js.map +1 -1
  34. package/lib/browser/components/chat-history.css +139 -0
  35. package/lib/browser/components/components.module.less +2 -2
  36. package/lib/browser/components/utils.d.ts +2 -2
  37. package/lib/browser/layout/layout.module.less +1 -1
  38. package/lib/browser/mcp/tools/components/Terminal.d.ts +4 -0
  39. package/lib/browser/mcp/tools/components/Terminal.d.ts.map +1 -0
  40. package/lib/browser/mcp/tools/components/Terminal.js +64 -0
  41. package/lib/browser/mcp/tools/components/Terminal.js.map +1 -0
  42. package/lib/browser/mcp/tools/components/index.module.less +36 -0
  43. package/lib/browser/mcp/tools/handlers/RunCommand.d.ts +43 -0
  44. package/lib/browser/mcp/tools/handlers/RunCommand.d.ts.map +1 -0
  45. package/lib/browser/mcp/tools/handlers/RunCommand.js +104 -0
  46. package/lib/browser/mcp/tools/handlers/RunCommand.js.map +1 -0
  47. package/lib/browser/mcp/tools/runTerminalCmd.d.ts +1 -6
  48. package/lib/browser/mcp/tools/runTerminalCmd.d.ts.map +1 -1
  49. package/lib/browser/mcp/tools/runTerminalCmd.js +9 -55
  50. package/lib/browser/mcp/tools/runTerminalCmd.js.map +1 -1
  51. package/lib/browser/model/msg-history-manager.d.ts +10 -0
  52. package/lib/browser/model/msg-history-manager.d.ts.map +1 -1
  53. package/lib/browser/model/msg-history-manager.js +14 -9
  54. package/lib/browser/model/msg-history-manager.js.map +1 -1
  55. package/package.json +23 -23
  56. package/src/browser/ai-core.contribution.ts +13 -1
  57. package/src/browser/chat/chat-manager.service.ts +83 -7
  58. package/src/browser/chat/chat-model.ts +62 -12
  59. package/src/browser/chat/chat-proxy.service.ts +1 -1
  60. package/src/browser/chat/chat.internal.service.ts +23 -5
  61. package/src/browser/chat/chat.module.less +8 -42
  62. package/src/browser/chat/chat.view.tsx +143 -60
  63. package/src/browser/components/ChatHistory.tsx +292 -0
  64. package/src/browser/components/ChatReply.tsx +5 -1
  65. package/src/browser/components/ChatThinking.tsx +1 -1
  66. package/src/browser/components/chat-history.css +139 -0
  67. package/src/browser/components/components.module.less +2 -2
  68. package/src/browser/layout/layout.module.less +1 -1
  69. package/src/browser/mcp/tools/components/Terminal.tsx +97 -0
  70. package/src/browser/mcp/tools/components/index.module.less +36 -0
  71. package/src/browser/mcp/tools/handlers/RunCommand.ts +115 -0
  72. package/src/browser/mcp/tools/runTerminalCmd.ts +7 -68
  73. package/src/browser/model/msg-history-manager.ts +15 -1
@@ -0,0 +1,115 @@
1
+ import z from 'zod';
2
+
3
+ import { Autowired, Injectable } from '@opensumi/di';
4
+ import { AppConfig } from '@opensumi/ide-core-browser';
5
+ import { ITerminalController, ITerminalGroupViewService } from '@opensumi/ide-terminal-next';
6
+ import { Deferred } from '@opensumi/ide-utils/lib/promises';
7
+
8
+ import { MCPLogger } from '../../../types';
9
+
10
+ const color = {
11
+ italic: '\x1b[3m',
12
+ reset: '\x1b[0m',
13
+ };
14
+
15
+ export 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
+ });
27
+
28
+ @Injectable()
29
+ export class RunCommandHandler {
30
+ @Autowired(ITerminalController)
31
+ protected readonly terminalController: ITerminalController;
32
+
33
+ @Autowired(AppConfig)
34
+ protected readonly appConfig: AppConfig;
35
+
36
+ @Autowired(ITerminalGroupViewService)
37
+ protected readonly terminalView: ITerminalGroupViewService;
38
+
39
+ private approvalDeferredMap = new Map<string, Deferred<boolean>>();
40
+
41
+ private terminalId = 0;
42
+
43
+ getShellLaunchConfig(command: string) {
44
+ return {
45
+ name: `MCP:Terminal_${this.terminalId++}`,
46
+ cwd: this.appConfig.workspaceDir,
47
+ args: ['-c', command],
48
+ };
49
+ }
50
+
51
+ async handler(args: z.infer<typeof inputSchema> & { toolCallId: string }, logger: MCPLogger) {
52
+ if (args.require_user_approval) {
53
+ const def = new Deferred<boolean>();
54
+ this.approvalDeferredMap.set(args.toolCallId, def);
55
+ const approval = await def.promise;
56
+ if (!approval) {
57
+ return {
58
+ isError: false,
59
+ content: [
60
+ {
61
+ type: 'text',
62
+ text: 'User rejection',
63
+ },
64
+ ],
65
+ };
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: 'text',
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;
105
+ }
106
+
107
+ handleApproval(callId: string, approval: boolean) {
108
+ if (!this.approvalDeferredMap.has(callId)) {
109
+ return;
110
+ }
111
+
112
+ const def = this.approvalDeferredMap.get(callId);
113
+ def?.resolve(approval);
114
+ }
115
+ }
@@ -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,7 +5,6 @@ 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();
11
10
  private messageAdditionalMap: Map<string, Record<string, any>> = new Map();
@@ -16,6 +15,14 @@ export class MsgHistoryManager extends Disposable {
16
15
  private readonly _onMessageAdditionalChange = new Emitter<Record<string, any>>();
17
16
  public readonly onMessageAdditionalChange: Event<Record<string, any>> = this._onMessageAdditionalChange.event;
18
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
+
19
26
  override dispose(): void {
20
27
  this.clearMessages();
21
28
  super.dispose();
@@ -89,4 +96,11 @@ export class MsgHistoryManager extends Disposable {
89
96
  public getMessageAdditional(id: string): Record<string, any> {
90
97
  return this.messageAdditionalMap.get(id) || {};
91
98
  }
99
+
100
+ toJSON() {
101
+ return {
102
+ messages: this.getMessages(),
103
+ additional: Object.fromEntries(this.messageAdditionalMap.entries()),
104
+ };
105
+ }
92
106
  }