240 lines
6.0 KiB
TypeScript

import { useMessageBridge } from '@/api/message-bridge';
import { reactive } from 'vue';
import { pinkLog } from '../setting/util';
import { ElMessage } from 'element-plus';
export const connectionMethods = reactive({
current: 'STDIO',
data: [
{
value: 'STDIO',
label: 'STDIO'
},
{
value: 'SSE',
label: 'SSE'
}
]
});
export const connectionArgs = reactive({
commandString: '',
urlString: ''
});
export interface EnvItem {
key: string
value: string
}
export interface IConnectionEnv {
data: EnvItem[]
newKey: string
newValue: string
}
export const connectionEnv = reactive<IConnectionEnv>({
data: [],
newKey: '',
newValue: ''
});
// 定义连接类型
type ConnectionType = 'STDIO' | 'SSE';
// 定义命令行参数接口
export interface MCPOptions {
connectionType: ConnectionType;
// STDIO 特定选项
command?: string;
args?: string[];
// SSE 特定选项
url?: string;
// 通用客户端选项
clientName?: string;
clientVersion?: string;
}
export function doConnect() {
let connectOption: MCPOptions;
const bridge = useMessageBridge();
return new Promise((resolve, reject) => {
// 监听 connect
bridge.addCommandListener('connect', async data => {
const { code, msg } = data;
connectionResult.success = (code === 200);
connectionResult.logString = msg;
if (code === 200) {
const res = await getServerVersion() as { name: string, version: string };
connectionResult.serverInfo.name = res.name || '';
connectionResult.serverInfo.version = res.version || '';
} else {
ElMessage({
type: 'error',
message: msg
});
}
resolve(void 0);
}, { once: true });
// TODO: 增加判断,获取 cwd
if (connectionMethods.current === 'STDIO') {
if (connectionArgs.commandString.length === 0) {
return;
}
const commandComponents = connectionArgs.commandString.split(/\s+/g);
const command = commandComponents[0];
commandComponents.shift();
connectOption = {
connectionType: 'STDIO',
command: command,
args: commandComponents,
clientName: 'openmcp.connect.stdio.' + command,
clientVersion: '0.0.1'
}
} else {
const url = connectionArgs.urlString;
if (url.length === 0) {
return;
}
connectOption = {
connectionType: 'SSE',
url: url,
clientName: 'openmcp.connect.sse',
clientVersion: '0.0.1'
}
}
bridge.postMessage({
command: 'connect',
data: connectOption
});
});
}
/**
* @description vscode 中初始化启动
*/
export async function launchConnect(option: { updateCommandString?: boolean } = {}) {
// 本地开发只用 IPC 进行启动
// 后续需要考虑到不同的连接方式
const {
updateCommandString = true
} = option;
connectionMethods.current = 'STDIO';
const bridge = useMessageBridge();
pinkLog('请求启动参数');
const { commandString, cwd } = await getLaunchCommand();
if (updateCommandString) {
connectionArgs.commandString = commandString;
if (connectionArgs.commandString.length === 0) {
return;
}
}
return new Promise<void>((resolve, reject) => {
// 监听 connect
bridge.addCommandListener('connect', async data => {
const { code, msg } = data;
connectionResult.success = (code === 200);
connectionResult.logString = msg;
if (code === 200) {
const res = await getServerVersion() as { name: string, version: string };
connectionResult.serverInfo.name = res.name || '';
connectionResult.serverInfo.version = res.version || '';
} else {
ElMessage({
type: 'error',
message: msg
});
}
resolve(void 0);
}, { once: true });
const commandComponents = connectionArgs.commandString.split(/\s+/g);
const command = commandComponents[0];
commandComponents.shift();
const connectOption = {
connectionType: 'STDIO',
command: command,
args: commandComponents,
cwd: cwd,
clientName: 'openmcp.connect.stdio.' + command,
clientVersion: '0.0.1'
};
bridge.postMessage({
command: 'connect',
data: connectOption
});
});
}
function getLaunchCommand() {
return new Promise<any>((resolve, reject) => {
// 与 vscode 进行同步
const bridge = useMessageBridge();
bridge.addCommandListener('vscode/launch-command', data => {
pinkLog('收到启动参数');
resolve(data.msg);
}, { once: true });
bridge.postMessage({
command: 'vscode/launch-command',
data: {}
});
})
}
export function doReconnect() {
// TODO: finish this
console.log();
}
export const connectionResult = reactive({
success: false,
logString: '',
serverInfo: {
name: '',
version: ''
}
});
export function getServerVersion() {
return new Promise((resolve, reject) => {
const bridge = useMessageBridge();
bridge.addCommandListener('server/version', data => {
if (data.code === 200) {
resolve(data.msg);
} else {
reject(data.msg);
}
}, { once: true });
bridge.postMessage({
command: 'server/version',
});
});
}