@opensumi/ide-ai-native 3.8.1-next-1740452912.0 → 3.8.1-next-1740465035.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.
- package/lib/browser/ai-core.contribution.d.ts.map +1 -1
- package/lib/browser/ai-core.contribution.js +10 -3
- package/lib/browser/ai-core.contribution.js.map +1 -1
- package/lib/browser/chat/chat-manager.service.d.ts +5 -0
- package/lib/browser/chat/chat-manager.service.d.ts.map +1 -1
- package/lib/browser/chat/chat-manager.service.js +18 -1
- package/lib/browser/chat/chat-manager.service.js.map +1 -1
- package/lib/browser/chat/chat-model.d.ts +2 -0
- package/lib/browser/chat/chat-model.d.ts.map +1 -1
- package/lib/browser/chat/chat-model.js +8 -2
- package/lib/browser/chat/chat-model.js.map +1 -1
- package/lib/browser/chat/chat.module.less +1 -2
- package/lib/browser/chat/chat.view.d.ts.map +1 -1
- package/lib/browser/chat/chat.view.js +14 -9
- package/lib/browser/chat/chat.view.js.map +1 -1
- package/lib/browser/components/ChatContext/index.js +2 -2
- package/lib/browser/components/ChatContext/index.js.map +1 -1
- package/lib/browser/components/chat-history.css +1 -1
- package/lib/browser/context/llm-context.service.d.ts +16 -5
- package/lib/browser/context/llm-context.service.d.ts.map +1 -1
- package/lib/browser/context/llm-context.service.js +78 -47
- package/lib/browser/context/llm-context.service.js.map +1 -1
- package/lib/browser/index.d.ts.map +1 -1
- package/lib/browser/index.js +4 -0
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/mcp/config/components/mcp-config.module.less +178 -0
- package/lib/browser/mcp/config/components/mcp-config.view.d.ts +3 -0
- package/lib/browser/mcp/config/components/mcp-config.view.d.ts.map +1 -0
- package/lib/browser/mcp/config/components/mcp-config.view.js +150 -0
- package/lib/browser/mcp/config/components/mcp-config.view.js.map +1 -0
- package/lib/browser/mcp/config/components/mcp-server-form.d.ts +16 -0
- package/lib/browser/mcp/config/components/mcp-server-form.d.ts.map +1 -0
- package/lib/browser/mcp/config/components/mcp-server-form.js +84 -0
- package/lib/browser/mcp/config/components/mcp-server-form.js.map +1 -0
- package/lib/browser/mcp/config/components/mcp-server-form.module.less +78 -0
- package/lib/browser/mcp/config/mcp-config.commands.d.ts +10 -0
- package/lib/browser/mcp/config/mcp-config.commands.d.ts.map +1 -0
- package/lib/browser/mcp/config/mcp-config.commands.js +35 -0
- package/lib/browser/mcp/config/mcp-config.commands.js.map +1 -0
- package/lib/browser/mcp/config/mcp-config.contribution.d.ts +16 -0
- package/lib/browser/mcp/config/mcp-config.contribution.d.ts.map +1 -0
- package/lib/browser/mcp/config/mcp-config.contribution.js +62 -0
- package/lib/browser/mcp/config/mcp-config.contribution.js.map +1 -0
- package/lib/browser/mcp/mcp-server-proxy.service.d.ts +6 -0
- package/lib/browser/mcp/mcp-server-proxy.service.d.ts.map +1 -1
- package/lib/browser/mcp/mcp-server-proxy.service.js +10 -1
- package/lib/browser/mcp/mcp-server-proxy.service.js.map +1 -1
- package/lib/browser/mcp/mcp-server.feature.registry.d.ts.map +1 -1
- package/lib/browser/mcp/mcp-server.feature.registry.js +3 -2
- package/lib/browser/mcp/mcp-server.feature.registry.js.map +1 -1
- package/lib/browser/mcp/tools/handlers/RunCommand.d.ts.map +1 -1
- package/lib/browser/mcp/tools/handlers/RunCommand.js +2 -0
- package/lib/browser/mcp/tools/handlers/RunCommand.js.map +1 -1
- package/lib/browser/preferences/schema.d.ts.map +1 -1
- package/lib/browser/preferences/schema.js +16 -0
- package/lib/browser/preferences/schema.js.map +1 -1
- package/lib/common/index.d.ts +8 -1
- package/lib/common/index.d.ts.map +1 -1
- package/lib/common/index.js +3 -1
- package/lib/common/index.js.map +1 -1
- package/lib/common/llm-context.d.ts +12 -9
- package/lib/common/llm-context.d.ts.map +1 -1
- package/lib/common/llm-context.js.map +1 -1
- package/lib/common/mcp-server-manager.d.ts +17 -1
- package/lib/common/mcp-server-manager.d.ts.map +1 -1
- package/lib/common/mcp-server-manager.js.map +1 -1
- package/lib/common/prompts/context-prompt-provider.d.ts +2 -3
- package/lib/common/prompts/context-prompt-provider.d.ts.map +1 -1
- package/lib/common/prompts/context-prompt-provider.js +21 -22
- package/lib/common/prompts/context-prompt-provider.js.map +1 -1
- package/lib/common/tool-invocation-registry.d.ts +2 -2
- package/lib/common/tool-invocation-registry.d.ts.map +1 -1
- package/lib/common/tool-invocation-registry.js +1 -1
- package/lib/common/tool-invocation-registry.js.map +1 -1
- package/lib/common/types.d.ts +6 -0
- package/lib/common/types.d.ts.map +1 -1
- package/lib/common/utils.d.ts.map +1 -1
- package/lib/common/utils.js +2 -1
- package/lib/common/utils.js.map +1 -1
- package/lib/node/mcp/sumi-mcp-server.d.ts +17 -3
- package/lib/node/mcp/sumi-mcp-server.d.ts.map +1 -1
- package/lib/node/mcp/sumi-mcp-server.js +59 -6
- package/lib/node/mcp/sumi-mcp-server.js.map +1 -1
- package/lib/node/mcp-server-manager-impl.d.ts +4 -3
- package/lib/node/mcp-server-manager-impl.d.ts.map +1 -1
- package/lib/node/mcp-server-manager-impl.js +26 -6
- package/lib/node/mcp-server-manager-impl.js.map +1 -1
- package/lib/node/mcp-server.d.ts +5 -16
- package/lib/node/mcp-server.d.ts.map +1 -1
- package/lib/node/mcp-server.js +12 -6
- package/lib/node/mcp-server.js.map +1 -1
- package/lib/node/openai/openai-language-model.d.ts +4 -3
- package/lib/node/openai/openai-language-model.d.ts.map +1 -1
- package/lib/node/openai/openai-language-model.js +3 -2
- package/lib/node/openai/openai-language-model.js.map +1 -1
- package/package.json +27 -27
- package/src/browser/ai-core.contribution.ts +13 -4
- package/src/browser/chat/chat-manager.service.ts +17 -1
- package/src/browser/chat/chat-model.ts +18 -3
- package/src/browser/chat/chat.module.less +1 -2
- package/src/browser/chat/chat.view.tsx +45 -23
- package/src/browser/components/ChatContext/index.tsx +2 -2
- package/src/browser/components/chat-history.css +1 -1
- package/src/browser/context/llm-context.service.ts +90 -54
- package/src/browser/index.ts +4 -0
- package/src/browser/mcp/config/components/mcp-config.module.less +178 -0
- package/src/browser/mcp/config/components/mcp-config.view.tsx +215 -0
- package/src/browser/mcp/config/components/mcp-server-form.module.less +78 -0
- package/src/browser/mcp/config/components/mcp-server-form.tsx +144 -0
- package/src/browser/mcp/config/mcp-config.commands.ts +29 -0
- package/src/browser/mcp/config/mcp-config.contribution.ts +65 -0
- package/src/browser/mcp/mcp-server-proxy.service.ts +14 -2
- package/src/browser/mcp/mcp-server.feature.registry.ts +3 -2
- package/src/browser/mcp/tools/handlers/RunCommand.ts +2 -0
- package/src/browser/preferences/schema.ts +16 -0
- package/src/common/index.ts +7 -1
- package/src/common/llm-context.ts +10 -4
- package/src/common/mcp-server-manager.ts +17 -1
- package/src/common/prompts/context-prompt-provider.ts +26 -28
- package/src/common/tool-invocation-registry.ts +2 -2
- package/src/common/types.ts +6 -0
- package/src/common/utils.ts +3 -1
- package/src/node/mcp/sumi-mcp-server.ts +67 -9
- package/src/node/mcp-server-manager-impl.ts +30 -9
- package/src/node/mcp-server.ts +11 -14
- package/src/node/openai/openai-language-model.ts +7 -4
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { Button } from '@opensumi/ide-components/lib/button';
|
|
4
|
+
import { Modal } from '@opensumi/ide-components/lib/modal';
|
|
5
|
+
|
|
6
|
+
import styles from './mcp-server-form.module.less';
|
|
7
|
+
|
|
8
|
+
export interface MCPServerFormData {
|
|
9
|
+
name: string;
|
|
10
|
+
command: string;
|
|
11
|
+
args: string[];
|
|
12
|
+
env?: Record<string, string>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface Props {
|
|
16
|
+
visible: boolean;
|
|
17
|
+
initialData?: MCPServerFormData;
|
|
18
|
+
onSave: (data: MCPServerFormData) => void;
|
|
19
|
+
onCancel: () => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const MCPServerForm: React.FC<Props> = ({ visible, initialData, onSave, onCancel }) => {
|
|
23
|
+
const [formData, setFormData] = React.useState<MCPServerFormData>(() => ({
|
|
24
|
+
name: '',
|
|
25
|
+
command: '',
|
|
26
|
+
args: [],
|
|
27
|
+
env: {},
|
|
28
|
+
type: 'stdio', // TODO: 支持 SSE
|
|
29
|
+
...initialData,
|
|
30
|
+
}));
|
|
31
|
+
|
|
32
|
+
const [argsText, setArgsText] = React.useState(() => initialData?.args?.join(' ') || '');
|
|
33
|
+
const [envText, setEnvText] = React.useState(() => {
|
|
34
|
+
if (!initialData?.env) {
|
|
35
|
+
return '';
|
|
36
|
+
}
|
|
37
|
+
return Object.entries(initialData.env)
|
|
38
|
+
.map(([key, value]) => `${key}=${value}`)
|
|
39
|
+
.join('\n');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Update form data when initialData changes
|
|
43
|
+
React.useEffect(() => {
|
|
44
|
+
setFormData({
|
|
45
|
+
name: '',
|
|
46
|
+
command: '',
|
|
47
|
+
args: [],
|
|
48
|
+
env: {},
|
|
49
|
+
...initialData,
|
|
50
|
+
});
|
|
51
|
+
setArgsText(initialData?.args?.join(' ') || '');
|
|
52
|
+
setEnvText(
|
|
53
|
+
initialData?.env
|
|
54
|
+
? Object.entries(initialData.env)
|
|
55
|
+
.map(([key, value]) => `${key}=${value}`)
|
|
56
|
+
.join('\n')
|
|
57
|
+
: '',
|
|
58
|
+
);
|
|
59
|
+
}, [initialData]);
|
|
60
|
+
|
|
61
|
+
const handleSubmit = (e: React.FormEvent) => {
|
|
62
|
+
e.preventDefault();
|
|
63
|
+
const args = argsText.split(' ').filter(Boolean);
|
|
64
|
+
const env = envText
|
|
65
|
+
.split('\n')
|
|
66
|
+
.filter(Boolean)
|
|
67
|
+
.reduce((acc, line) => {
|
|
68
|
+
const [key, value] = line.split('=');
|
|
69
|
+
if (key && value) {
|
|
70
|
+
acc[key.trim()] = value.trim();
|
|
71
|
+
}
|
|
72
|
+
return acc;
|
|
73
|
+
}, {} as Record<string, string>);
|
|
74
|
+
|
|
75
|
+
onSave({
|
|
76
|
+
...formData,
|
|
77
|
+
args,
|
|
78
|
+
env,
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<Modal
|
|
84
|
+
title={initialData ? 'Edit MCP Server' : 'Add New MCP Server'}
|
|
85
|
+
visible={visible}
|
|
86
|
+
onCancel={onCancel}
|
|
87
|
+
centered
|
|
88
|
+
width={600}
|
|
89
|
+
footer={null}
|
|
90
|
+
style={{
|
|
91
|
+
background: 'var(--editor-background)',
|
|
92
|
+
}}
|
|
93
|
+
>
|
|
94
|
+
<form className={styles.form} onSubmit={(e) => e.preventDefault()}>
|
|
95
|
+
<div className={styles.formItem}>
|
|
96
|
+
<label>Name:</label>
|
|
97
|
+
<input
|
|
98
|
+
type='text'
|
|
99
|
+
value={formData.name}
|
|
100
|
+
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
|
101
|
+
placeholder='Enter server name'
|
|
102
|
+
required
|
|
103
|
+
/>
|
|
104
|
+
</div>
|
|
105
|
+
<div className={styles.formItem}>
|
|
106
|
+
<label>Command:</label>
|
|
107
|
+
<input
|
|
108
|
+
type='text'
|
|
109
|
+
value={formData.command}
|
|
110
|
+
onChange={(e) => setFormData({ ...formData, command: e.target.value })}
|
|
111
|
+
placeholder='Enter command (e.g., npx)'
|
|
112
|
+
required
|
|
113
|
+
/>
|
|
114
|
+
</div>
|
|
115
|
+
<div className={styles.formItem}>
|
|
116
|
+
<label>Arguments:</label>
|
|
117
|
+
<textarea
|
|
118
|
+
value={argsText}
|
|
119
|
+
onChange={(e) => setArgsText(e.target.value)}
|
|
120
|
+
placeholder='Enter arguments separated by space'
|
|
121
|
+
rows={3}
|
|
122
|
+
/>
|
|
123
|
+
</div>
|
|
124
|
+
<div className={styles.formItem}>
|
|
125
|
+
<label>Environment Variables:</label>
|
|
126
|
+
<textarea
|
|
127
|
+
value={envText}
|
|
128
|
+
onChange={(e) => setEnvText(e.target.value)}
|
|
129
|
+
placeholder='KEY=value (one per line)'
|
|
130
|
+
rows={3}
|
|
131
|
+
/>
|
|
132
|
+
</div>
|
|
133
|
+
<div className={styles.formActions}>
|
|
134
|
+
<Button onClick={onCancel} type='secondary'>
|
|
135
|
+
Cancel
|
|
136
|
+
</Button>
|
|
137
|
+
<Button onClick={handleSubmit} type='primary'>
|
|
138
|
+
Save
|
|
139
|
+
</Button>
|
|
140
|
+
</div>
|
|
141
|
+
</form>
|
|
142
|
+
</Modal>
|
|
143
|
+
);
|
|
144
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Autowired } from '@opensumi/di';
|
|
2
|
+
import { CommandContribution, CommandRegistry, URI } from '@opensumi/ide-core-browser';
|
|
3
|
+
import { Domain } from '@opensumi/ide-core-common';
|
|
4
|
+
import { WorkbenchEditorService } from '@opensumi/ide-editor';
|
|
5
|
+
|
|
6
|
+
import { MCP_CONFIG_COMPONENTS_SCHEME_ID } from './mcp-config.contribution';
|
|
7
|
+
|
|
8
|
+
export const OPEN_MCP_CONFIG_COMMAND = {
|
|
9
|
+
id: 'opensumi-mcp.openConfig',
|
|
10
|
+
label: 'Open MCP Configuration',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
@Domain(CommandContribution)
|
|
14
|
+
export class MCPConfigCommandContribution implements CommandContribution {
|
|
15
|
+
@Autowired(WorkbenchEditorService)
|
|
16
|
+
private readonly editorService: WorkbenchEditorService;
|
|
17
|
+
|
|
18
|
+
registerCommands(registry: CommandRegistry) {
|
|
19
|
+
registry.registerCommand(OPEN_MCP_CONFIG_COMMAND, {
|
|
20
|
+
execute: () => {
|
|
21
|
+
const uri = new URI().withScheme(MCP_CONFIG_COMPONENTS_SCHEME_ID);
|
|
22
|
+
this.editorService.open(uri, {
|
|
23
|
+
preview: false,
|
|
24
|
+
focus: true,
|
|
25
|
+
});
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Autowired } from '@opensumi/di';
|
|
2
|
+
import { LabelService } from '@opensumi/ide-core-browser/lib/services';
|
|
3
|
+
import { Domain, Schemes, URI } from '@opensumi/ide-core-common';
|
|
4
|
+
import {
|
|
5
|
+
BrowserEditorContribution,
|
|
6
|
+
EditorComponentRegistry,
|
|
7
|
+
EditorComponentRenderMode,
|
|
8
|
+
IResource,
|
|
9
|
+
ResourceService,
|
|
10
|
+
} from '@opensumi/ide-editor/lib/browser/types';
|
|
11
|
+
import { IconService } from '@opensumi/ide-theme/lib/browser';
|
|
12
|
+
import { IWorkspaceService } from '@opensumi/ide-workspace/lib/common';
|
|
13
|
+
|
|
14
|
+
import { MCPConfigView } from './components/mcp-config.view';
|
|
15
|
+
|
|
16
|
+
const COMPONENTS_ID = 'opensumi-mcp-config-viewer';
|
|
17
|
+
export const MCP_CONFIG_COMPONENTS_SCHEME_ID = 'mcp-config';
|
|
18
|
+
|
|
19
|
+
export type IMCPConfigResource = IResource<{ configType: string }>;
|
|
20
|
+
|
|
21
|
+
@Domain(BrowserEditorContribution)
|
|
22
|
+
export class MCPConfigContribution implements BrowserEditorContribution {
|
|
23
|
+
@Autowired(IWorkspaceService)
|
|
24
|
+
protected readonly workspaceService: IWorkspaceService;
|
|
25
|
+
|
|
26
|
+
@Autowired(IconService)
|
|
27
|
+
protected readonly iconService: IconService;
|
|
28
|
+
|
|
29
|
+
@Autowired()
|
|
30
|
+
labelService: LabelService;
|
|
31
|
+
|
|
32
|
+
registerEditorComponent(registry: EditorComponentRegistry) {
|
|
33
|
+
registry.registerEditorComponent({
|
|
34
|
+
uid: COMPONENTS_ID,
|
|
35
|
+
scheme: MCP_CONFIG_COMPONENTS_SCHEME_ID,
|
|
36
|
+
component: MCPConfigView,
|
|
37
|
+
renderMode: EditorComponentRenderMode.ONE_PER_WORKBENCH,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
registry.registerEditorComponentResolver(MCP_CONFIG_COMPONENTS_SCHEME_ID, (resource, results) => {
|
|
41
|
+
results.push({
|
|
42
|
+
type: 'component',
|
|
43
|
+
componentId: COMPONENTS_ID,
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
registerResource(service: ResourceService) {
|
|
49
|
+
service.registerResourceProvider({
|
|
50
|
+
scheme: MCP_CONFIG_COMPONENTS_SCHEME_ID,
|
|
51
|
+
provideResource: async (uri: URI): Promise<IMCPConfigResource> => {
|
|
52
|
+
const { configType } = uri.getParsedQuery();
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
uri,
|
|
56
|
+
name: 'MCP Configuration',
|
|
57
|
+
icon: 'settings',
|
|
58
|
+
metadata: {
|
|
59
|
+
configType,
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -4,7 +4,7 @@ import { Autowired, Injectable } from '@opensumi/di';
|
|
|
4
4
|
import { ILogger } from '@opensumi/ide-core-browser';
|
|
5
5
|
import { Emitter, Event } from '@opensumi/ide-core-common';
|
|
6
6
|
|
|
7
|
-
import { ISumiMCPServerBackend, SumiMCPServerProxyServicePath } from '../../common';
|
|
7
|
+
import { BUILTIN_MCP_SERVER_NAME, ISumiMCPServerBackend, SumiMCPServerProxyServicePath } from '../../common';
|
|
8
8
|
import { IMCPServerProxyService } from '../../common/types';
|
|
9
9
|
import { IMCPServerRegistry, TokenMCPServerRegistry } from '../types';
|
|
10
10
|
|
|
@@ -35,7 +35,7 @@ export class MCPServerProxyService implements IMCPServerProxyService {
|
|
|
35
35
|
name: tool.name,
|
|
36
36
|
description: tool.description,
|
|
37
37
|
inputSchema: zodToJsonSchema(tool.inputSchema),
|
|
38
|
-
providerName:
|
|
38
|
+
providerName: BUILTIN_MCP_SERVER_NAME,
|
|
39
39
|
}),
|
|
40
40
|
);
|
|
41
41
|
|
|
@@ -52,4 +52,16 @@ export class MCPServerProxyService implements IMCPServerProxyService {
|
|
|
52
52
|
async getAllMCPTools() {
|
|
53
53
|
return this.sumiMCPServerProxyService.getAllMCPTools();
|
|
54
54
|
}
|
|
55
|
+
|
|
56
|
+
async $getServers() {
|
|
57
|
+
return this.sumiMCPServerProxyService.getServers();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async $startServer(serverName: string) {
|
|
61
|
+
await this.sumiMCPServerProxyService.startServer(serverName);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async $stopServer(serverName: string) {
|
|
65
|
+
await this.sumiMCPServerProxyService.stopServer(serverName);
|
|
66
|
+
}
|
|
55
67
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { Autowired, Injectable } from '@opensumi/di';
|
|
3
3
|
import { ILogger } from '@opensumi/ide-core-common';
|
|
4
4
|
|
|
5
|
+
import { BUILTIN_MCP_SERVER_NAME } from '../../common';
|
|
5
6
|
import { getToolName } from '../../common/utils';
|
|
6
7
|
import { IMCPServerRegistry, IMCPServerToolComponentProps, MCPLogger, MCPToolDefinition } from '../types';
|
|
7
8
|
|
|
@@ -25,7 +26,7 @@ export class MCPServerRegistry implements IMCPServerRegistry {
|
|
|
25
26
|
return new LoggerAdapter(this.baseLogger);
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
getMCPTool(name: string, serverName =
|
|
29
|
+
getMCPTool(name: string, serverName = BUILTIN_MCP_SERVER_NAME): MCPToolDefinition | undefined {
|
|
29
30
|
return this.tools.find((tool) => getToolName(tool.name, serverName) === name);
|
|
30
31
|
}
|
|
31
32
|
|
|
@@ -36,7 +37,7 @@ export class MCPServerRegistry implements IMCPServerRegistry {
|
|
|
36
37
|
registerToolComponent(
|
|
37
38
|
name: string,
|
|
38
39
|
component: React.FC<IMCPServerToolComponentProps>,
|
|
39
|
-
serverName =
|
|
40
|
+
serverName = BUILTIN_MCP_SERVER_NAME,
|
|
40
41
|
): void {
|
|
41
42
|
this.toolComponents[getToolName(name, serverName)] = component;
|
|
42
43
|
}
|
|
@@ -49,6 +49,7 @@ export class RunCommandHandler {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
async handler(args: z.infer<typeof inputSchema> & { toolCallId: string }, logger: MCPLogger) {
|
|
52
|
+
logger.appendLine(`Executing command: ${args.command}`);
|
|
52
53
|
if (args.require_user_approval) {
|
|
53
54
|
const def = new Deferred<boolean>();
|
|
54
55
|
this.approvalDeferredMap.set(args.toolCallId, def);
|
|
@@ -89,6 +90,7 @@ export class RunCommandHandler {
|
|
|
89
90
|
content: result,
|
|
90
91
|
});
|
|
91
92
|
|
|
93
|
+
logger.appendLine(`Command ${args.command} finished with exit code: ${e.code}`);
|
|
92
94
|
terminalClient.term.writeln(
|
|
93
95
|
`\n${color.italic}> Command ${args.command} executed successfully. Terminal will close in ${
|
|
94
96
|
3000 / 1000
|
|
@@ -108,11 +108,27 @@ export const aiNativePreferenceSchema: PreferenceSchema = {
|
|
|
108
108
|
type: 'string',
|
|
109
109
|
description: localize('preference.ai.native.mcp.servers.command.description'),
|
|
110
110
|
},
|
|
111
|
+
type: {
|
|
112
|
+
type: 'string',
|
|
113
|
+
enum: ['stdio', 'sse'],
|
|
114
|
+
enumDescriptions: [
|
|
115
|
+
localize('preference.ai.native.mcp.servers.type.stdio'),
|
|
116
|
+
localize('preference.ai.native.mcp.servers.type.sse'),
|
|
117
|
+
],
|
|
118
|
+
description: localize('preference.ai.native.mcp.servers.type.description'),
|
|
119
|
+
default: 'stdio',
|
|
120
|
+
},
|
|
121
|
+
enabled: {
|
|
122
|
+
type: 'boolean',
|
|
123
|
+
description: localize('preference.ai.native.mcp.servers.enabled.description'),
|
|
124
|
+
default: true,
|
|
125
|
+
},
|
|
111
126
|
args: {
|
|
112
127
|
type: 'array',
|
|
113
128
|
items: {
|
|
114
129
|
type: 'string',
|
|
115
130
|
},
|
|
131
|
+
default: [],
|
|
116
132
|
description: localize('preference.ai.native.mcp.servers.args.description'),
|
|
117
133
|
},
|
|
118
134
|
env: {
|
package/src/common/index.ts
CHANGED
|
@@ -31,6 +31,9 @@ export const AI_CHAT_CONTAINER_ID = 'AI-Chat-Container';
|
|
|
31
31
|
export const AI_CHAT_LOGO_AVATAR_ID = 'AI-Chat-Logo-Avatar';
|
|
32
32
|
export const AI_MENU_BAR_DEBUG_TOOLBAR = 'AI_MENU_BAR_DEBUG_TOOLBAR';
|
|
33
33
|
|
|
34
|
+
// 内置 MCP 服务器名称
|
|
35
|
+
export const BUILTIN_MCP_SERVER_NAME = 'sumi-builtin';
|
|
36
|
+
|
|
34
37
|
/**
|
|
35
38
|
* @deprecated Use {@link DESIGN_MENUBAR_CONTAINER_VIEW_ID} instead
|
|
36
39
|
*/
|
|
@@ -123,9 +126,12 @@ export const ChatProxyServiceToken = Symbol('ChatProxyServiceToken');
|
|
|
123
126
|
export const TokenMCPServerProxyService = Symbol('TokenMCPServerProxyService');
|
|
124
127
|
|
|
125
128
|
export interface ISumiMCPServerBackend {
|
|
126
|
-
initBuiltinMCPServer(): void;
|
|
129
|
+
initBuiltinMCPServer(enabled: boolean): void;
|
|
127
130
|
initExternalMCPServers(servers: MCPServerDescription[]): void;
|
|
128
131
|
getAllMCPTools(): Promise<MCPTool[]>;
|
|
132
|
+
getServers(): Promise<Array<{ name: string; isStarted: boolean }>>;
|
|
133
|
+
startServer(serverName: string): Promise<void>;
|
|
134
|
+
stopServer(serverName: string): Promise<void>;
|
|
129
135
|
}
|
|
130
136
|
|
|
131
137
|
export const SumiMCPServerProxyServicePath = 'SumiMCPServerProxyServicePath';
|
|
@@ -15,13 +15,13 @@ export interface LLMContextService {
|
|
|
15
15
|
*/
|
|
16
16
|
cleanFileContext(): void;
|
|
17
17
|
|
|
18
|
-
onDidContextFilesChangeEvent: Event<FileContext[]>;
|
|
18
|
+
onDidContextFilesChangeEvent: Event<{ viewed: FileContext[]; attached: FileContext[] }>;
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* 从 context 中移除文件
|
|
22
22
|
* @param uri URI
|
|
23
23
|
*/
|
|
24
|
-
removeFileFromContext(uri: URI): void;
|
|
24
|
+
removeFileFromContext(uri: URI, isManual?: boolean): void;
|
|
25
25
|
|
|
26
26
|
/** 导出为可序列化格式 */
|
|
27
27
|
serialize(): SerializedContext;
|
|
@@ -30,12 +30,18 @@ export interface LLMContextService {
|
|
|
30
30
|
export interface FileContext {
|
|
31
31
|
uri: URI;
|
|
32
32
|
selection?: [number, number];
|
|
33
|
-
isManual: boolean;
|
|
34
33
|
}
|
|
35
34
|
|
|
36
35
|
export const LLMContextServiceToken = Symbol('LLMContextService');
|
|
37
36
|
|
|
37
|
+
export interface AttachFileContext {
|
|
38
|
+
content: string;
|
|
39
|
+
lineErrors: string[];
|
|
40
|
+
path: string;
|
|
41
|
+
language: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
38
44
|
export interface SerializedContext {
|
|
39
45
|
recentlyViewFiles: string[];
|
|
40
|
-
attachedFiles: Array<
|
|
46
|
+
attachedFiles: Array<AttachFileContext>;
|
|
41
47
|
}
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
2
2
|
|
|
3
|
+
export interface IMCPServer {
|
|
4
|
+
isStarted(): boolean;
|
|
5
|
+
start(): Promise<void>;
|
|
6
|
+
getServerName(): string;
|
|
7
|
+
callTool(toolName: string, toolCallId: string, arg_string: string): ReturnType<Client['callTool']>;
|
|
8
|
+
getTools(): ReturnType<Client['listTools']>;
|
|
9
|
+
update(command: string, args?: string[], env?: { [key: string]: string }): void;
|
|
10
|
+
stop(): void;
|
|
11
|
+
}
|
|
12
|
+
|
|
3
13
|
export interface MCPServerManager {
|
|
4
14
|
callTool(
|
|
5
15
|
serverName: string,
|
|
@@ -11,7 +21,7 @@ export interface MCPServerManager {
|
|
|
11
21
|
addOrUpdateServer(description: MCPServerDescription): void;
|
|
12
22
|
// invoke in node.js only
|
|
13
23
|
addOrUpdateServerDirectly(server: any): void;
|
|
14
|
-
initBuiltinServer(builtinMCPServer: any): void;
|
|
24
|
+
initBuiltinServer(builtinMCPServer: any, enabled: boolean): void;
|
|
15
25
|
getTools(serverName: string): ReturnType<Client['listTools']>;
|
|
16
26
|
getServerNames(): Promise<string[]>;
|
|
17
27
|
startServer(serverName: string): Promise<void>;
|
|
@@ -19,6 +29,7 @@ export interface MCPServerManager {
|
|
|
19
29
|
getStartedServers(): Promise<string[]>;
|
|
20
30
|
registerTools(serverName: string): Promise<void>;
|
|
21
31
|
addExternalMCPServers(servers: MCPServerDescription[]): void;
|
|
32
|
+
getServers(): Map<string, IMCPServer>;
|
|
22
33
|
}
|
|
23
34
|
|
|
24
35
|
export type MCPTool = Awaited<ReturnType<MCPServerManager['getTools']>>['tools'][number];
|
|
@@ -45,6 +56,11 @@ export interface MCPServerDescription {
|
|
|
45
56
|
* Optional environment variables to set when starting the server.
|
|
46
57
|
*/
|
|
47
58
|
env?: { [key: string]: string };
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Whether to enable the MCP server.
|
|
62
|
+
*/
|
|
63
|
+
enabled?: boolean;
|
|
48
64
|
}
|
|
49
65
|
|
|
50
66
|
export const MCPServerManager = Symbol('MCPServerManager');
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Injectable } from '@opensumi/di';
|
|
2
|
-
import { MaybePromise } from '@opensumi/ide-core-common/lib/utils';
|
|
3
2
|
|
|
4
3
|
import { SerializedContext } from '../llm-context';
|
|
5
4
|
|
|
@@ -10,37 +9,36 @@ export interface ChatAgentPromptProvider {
|
|
|
10
9
|
* 提供上下文提示
|
|
11
10
|
* @param context 上下文
|
|
12
11
|
*/
|
|
13
|
-
provideContextPrompt(context: SerializedContext, userMessage: string):
|
|
12
|
+
provideContextPrompt(context: SerializedContext, userMessage: string): string;
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
@Injectable()
|
|
17
16
|
export class DefaultChatAgentPromptProvider implements ChatAgentPromptProvider {
|
|
18
|
-
provideContextPrompt(context: SerializedContext, userMessage: string):
|
|
17
|
+
provideContextPrompt(context: SerializedContext, userMessage: string): string {
|
|
19
18
|
return `
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
</user_query>`;
|
|
19
|
+
<additional_data>
|
|
20
|
+
Below are some potentially helpful/relevant pieces of information for figuring out to respond
|
|
21
|
+
<recently_viewed_files>
|
|
22
|
+
${context.recentlyViewFiles.map((file, idx) => ` ${idx + 1}: ${file}`).join('\n')}
|
|
23
|
+
</recently_viewed_files>
|
|
24
|
+
<attached_files>
|
|
25
|
+
${context.attachedFiles.map(
|
|
26
|
+
(file) =>
|
|
27
|
+
`
|
|
28
|
+
<file_contents>
|
|
29
|
+
\`\`\`${file.language} ${file.path}
|
|
30
|
+
${file.content}
|
|
31
|
+
\`\`\`
|
|
32
|
+
</file_contents>
|
|
33
|
+
<linter_errors>
|
|
34
|
+
${file.lineErrors.join('\n')}
|
|
35
|
+
</linter_errors>
|
|
36
|
+
`,
|
|
37
|
+
)}
|
|
38
|
+
</attached_files>
|
|
39
|
+
</additional_data>
|
|
40
|
+
<user_query>
|
|
41
|
+
${userMessage}
|
|
42
|
+
</user_query>`;
|
|
45
43
|
}
|
|
46
44
|
}
|
|
@@ -72,7 +72,7 @@ export interface ToolInvocationRegistry {
|
|
|
72
72
|
*
|
|
73
73
|
* @param providerName - 要移除其工具的工具提供者名称(在 `ToolRequest` 中指定)
|
|
74
74
|
*/
|
|
75
|
-
|
|
75
|
+
unregisterProviderTools(providerName: string): void;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
export const ToolProvider = Symbol('ToolProvider');
|
|
@@ -83,7 +83,7 @@ export interface ToolProvider {
|
|
|
83
83
|
export class ToolInvocationRegistryImpl implements ToolInvocationRegistry {
|
|
84
84
|
private tools: Map<string, ToolRequest> = new Map<string, ToolRequest>();
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
unregisterProviderTools(providerName: string): void {
|
|
87
87
|
const toolsToRemove: string[] = [];
|
|
88
88
|
for (const [id, tool] of this.tools.entries()) {
|
|
89
89
|
if (tool.providerName === providerName) {
|
package/src/common/types.ts
CHANGED
|
@@ -32,6 +32,12 @@ export interface IMCPServerProxyService {
|
|
|
32
32
|
$getMCPTools(): Promise<MCPTool[]>;
|
|
33
33
|
// 通知前端 MCP 服务注册表发生了变化
|
|
34
34
|
$updateMCPServers(): Promise<void>;
|
|
35
|
+
// 获取所有 MCP 服务器列表
|
|
36
|
+
$getServers(): Promise<Array<{ name: string; isStarted: boolean }>>;
|
|
37
|
+
// 启动指定的 MCP 服务器
|
|
38
|
+
$startServer(serverName: string): Promise<void>;
|
|
39
|
+
// 停止指定的 MCP 服务器
|
|
40
|
+
$stopServer(serverName: string): Promise<void>;
|
|
35
41
|
}
|
|
36
42
|
|
|
37
43
|
export interface MCPTool {
|
package/src/common/utils.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { IEditorDocumentModel } from '@opensumi/ide-editor';
|
|
2
2
|
|
|
3
|
+
import { BUILTIN_MCP_SERVER_NAME } from './index';
|
|
4
|
+
|
|
3
5
|
const BACK_QUOTE_3_SYMBOL = '```';
|
|
4
6
|
const MIN_PROMPT_CHARS = 10;
|
|
5
7
|
|
|
@@ -49,4 +51,4 @@ export const extractCodeBlocks = (content: string): string => {
|
|
|
49
51
|
return newContents.join('\n');
|
|
50
52
|
};
|
|
51
53
|
|
|
52
|
-
export const getToolName = (toolName: string, serverName =
|
|
54
|
+
export const getToolName = (toolName: string, serverName = BUILTIN_MCP_SERVER_NAME) => `mcp_${serverName}_${toolName}`;
|