完成兼容
This commit is contained in:
parent
355b25b9b7
commit
c218dcba03
@ -3,6 +3,8 @@
|
||||
## [main] 0.1.0
|
||||
- 新特性:支持同时连入多个 mcp server
|
||||
- 新特性:更新协议内容,支持 streamable http 协议,未来将逐步取代 SSE 的连接方式
|
||||
- 对于 uv 创建的 py 项目进行特殊支持:自动初始化项目,并将 mcp 定向到 .venv/bin/mcp 中,不再需要用户全局安装 mcp
|
||||
- 对于 npm 创建的 js/ts 项目进行特殊支持:自动初始化项目
|
||||
|
||||
## [main] 0.0.9
|
||||
- 修复 0.0.8 引入的bug:system prompt 返回的是索引而非真实内容
|
||||
|
@ -48,11 +48,11 @@ onMounted(async () => {
|
||||
pinkLog('OpenMCP Client 启动');
|
||||
|
||||
// 跳转到首页
|
||||
if (route.name !== 'debug') {
|
||||
const targetRoute = import.meta.env.BASE_URL + 'debug';
|
||||
console.log('go to ' + targetRoute);
|
||||
router.push(targetRoute);
|
||||
}
|
||||
// if (route.name !== 'debug') {
|
||||
// const targetRoute = import.meta.env.BASE_URL + 'debug';
|
||||
// console.log('go to ' + targetRoute);
|
||||
// router.push(targetRoute);
|
||||
// }
|
||||
|
||||
// 进行桥接
|
||||
await bridge.awaitForWebsocket();
|
||||
|
@ -58,7 +58,7 @@
|
||||
</el-tour-step>
|
||||
|
||||
<el-tour-step
|
||||
:target="client.connectionSettingRef.value"
|
||||
:target="client.connectionSettingRef"
|
||||
:prev-button-props="{ children: '上一步' }"
|
||||
:next-button-props="{ children: '下一步' }"
|
||||
:show-close="false"
|
||||
@ -78,7 +78,7 @@
|
||||
</el-tour-step>
|
||||
|
||||
<el-tour-step
|
||||
:target="client.connectionLogRef.value"
|
||||
:target="client.connectionLogRef"
|
||||
:prev-button-props="{ children: '上一步' }"
|
||||
:next-button-props="{ children: '下一步' }"
|
||||
:show-close="false"
|
||||
|
@ -2,7 +2,7 @@
|
||||
<el-scrollbar>
|
||||
<div class="connection-container">
|
||||
<div class="connect-panel-container"
|
||||
:ref="el => client.connectionSettingRef.value = el"
|
||||
:ref="el => client.connectionSettingRef = el"
|
||||
>
|
||||
<ConnectionMethod :index="props.index" />
|
||||
<ConnectionArgs :index="props.index" />
|
||||
@ -18,7 +18,7 @@
|
||||
</div>
|
||||
|
||||
<div class="connect-panel-container"
|
||||
:ref="el => client.connectionLogRef.value = el"
|
||||
:ref="el => client.connectionLogRef = el"
|
||||
>
|
||||
<ConnectionLog :index="props.index" />
|
||||
</div>
|
||||
@ -51,6 +51,8 @@ const props = defineProps({
|
||||
const client = mcpClientAdapter.clients[props.index];
|
||||
|
||||
console.log(client);
|
||||
console.log(client.connectionSettingRef);
|
||||
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
@ -59,8 +61,9 @@ const isLoading = ref(false);
|
||||
async function connect() {
|
||||
isLoading.value = true;
|
||||
|
||||
const plaform = getPlatform();
|
||||
const ok = await client.connect(plaform);
|
||||
const platform = getPlatform();
|
||||
const ok = await client.connect();
|
||||
|
||||
if (ok) {
|
||||
mcpClientAdapter.saveLaunchSignature();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useMessageBridge } from "@/api/message-bridge";
|
||||
import { reactive, ref, type Reactive, type Ref } from "vue";
|
||||
import { reactive } from "vue";
|
||||
import type { IConnectionResult, ConnectionTypeOptionItem, IConnectionArgs, IConnectionEnvironment, McpOptions } from "./type";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { loadPanels } from "@/hook/panel";
|
||||
@ -23,49 +23,49 @@ export const connectionSelectDataViewOption: ConnectionTypeOptionItem[] = [
|
||||
|
||||
export class McpClient {
|
||||
// 连接入参
|
||||
public connectionArgs: Reactive<IConnectionArgs>;
|
||||
public connectionArgs: IConnectionArgs;
|
||||
// 连接出参
|
||||
public connectionResult: Reactive<IConnectionResult>;
|
||||
public connectionResult: IConnectionResult;
|
||||
|
||||
// 预设环境变量,初始化的时候会去获取它们
|
||||
public presetsEnvironment: string[] = ['HOME', 'LOGNAME', 'PATH', 'SHELL', 'TERM', 'USER'];
|
||||
// 环境变量
|
||||
public connectionEnvironment: Reactive<IConnectionEnvironment>;
|
||||
public connectionEnvironment: IConnectionEnvironment;
|
||||
|
||||
// logger 面板的 ref
|
||||
public connectionLogRef = ref<any>(null);
|
||||
public connectionLogRef: any = null;
|
||||
// setting 面板的 ref
|
||||
public connectionSettingRef = ref<any>(null);
|
||||
public connectionSettingRef: any = null;
|
||||
|
||||
constructor(
|
||||
public clientVersion: string = '0.0.1',
|
||||
public clientNamePrefix: string = 'openmcp.connect'
|
||||
) {
|
||||
// 连接入参
|
||||
this.connectionArgs = reactive({
|
||||
this.connectionArgs = {
|
||||
type: 'STDIO',
|
||||
commandString: '',
|
||||
cwd: '',
|
||||
url: '',
|
||||
oauth: ''
|
||||
});
|
||||
};
|
||||
|
||||
// 连接出参
|
||||
this.connectionResult = reactive({
|
||||
this.connectionResult = {
|
||||
success: false,
|
||||
status: 'disconnected',
|
||||
clientId: '',
|
||||
name: '',
|
||||
version: '',
|
||||
logString: []
|
||||
});
|
||||
};
|
||||
|
||||
// 环境变量
|
||||
this.connectionEnvironment = reactive({
|
||||
this.connectionEnvironment = {
|
||||
data: [],
|
||||
newKey: '',
|
||||
newValue: ''
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
async acquireConnectionSignature(args: IConnectionArgs) {
|
||||
@ -121,6 +121,7 @@ export class McpClient {
|
||||
const { command, args } = this.commandAndArgs;
|
||||
const env = this.env;
|
||||
const url = this.connectionArgs.url;
|
||||
const cwd = this.connectionArgs.cwd;
|
||||
const oauth = this.connectionArgs.oauth;
|
||||
const connectionType = this.connectionArgs.type;
|
||||
|
||||
@ -132,6 +133,7 @@ export class McpClient {
|
||||
command,
|
||||
args,
|
||||
url,
|
||||
cwd,
|
||||
oauth,
|
||||
clientName,
|
||||
clientVersion,
|
||||
@ -145,7 +147,7 @@ export class McpClient {
|
||||
return option;
|
||||
}
|
||||
|
||||
public async connect(platform: string) {
|
||||
public async connect() {
|
||||
const bridge = useMessageBridge();
|
||||
const { code, msg } = await bridge.commandRequest<IConnectionResult>('connect', this.connectOption);
|
||||
|
||||
@ -160,6 +162,11 @@ export class McpClient {
|
||||
|
||||
ElMessage.error(message);
|
||||
return false;
|
||||
} else {
|
||||
this.connectionResult.logString.push({
|
||||
type: 'info',
|
||||
message: msg.info || ''
|
||||
})
|
||||
}
|
||||
|
||||
this.connectionResult.status = msg.status;
|
||||
@ -284,9 +291,13 @@ class McpClientAdapter {
|
||||
|
||||
public async launch() {
|
||||
const launchSignature = await this.getLaunchSignature();
|
||||
console.log('launchSignature', launchSignature);
|
||||
|
||||
let allOk = true;
|
||||
|
||||
for (const item of launchSignature) {
|
||||
|
||||
// 创建一个新的客户端
|
||||
const client = new McpClient();
|
||||
|
||||
// 同步连接参数
|
||||
|
@ -3,9 +3,15 @@
|
||||
<div class="server-list">
|
||||
<div v-for="(client, index) in mcpClientAdapter.clients" :key="index" class="server-item"
|
||||
:class="{ 'active': mcpClientAdapter.currentClientIndex === index }" @click="selectServer(index)">
|
||||
<span class="server-name">Server {{ index + 1 }}</span>
|
||||
<span class="server-status" :class="client.connectionResult.status">
|
||||
{{ client.connectionResult.status }}
|
||||
<span class="connect-status">
|
||||
<span v-if="client.connectionResult.success">
|
||||
<span class="iconfont icon-connect"></span>
|
||||
<span class="iconfont icon-dui"></span>
|
||||
</span>
|
||||
<span v-else>
|
||||
<span class="iconfont icon-connect"></span>
|
||||
<span class="server-name"> Unconnected </span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="add-server" @click="addServer">
|
||||
@ -21,7 +27,7 @@
|
||||
<script setup lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import ConnectionPanel from './connection-panel.vue';
|
||||
import { mcpClientAdapter } from './core';
|
||||
import { McpClient, mcpClientAdapter } from './core';
|
||||
import { ElMessage } from 'element-plus';
|
||||
|
||||
defineComponent({ name: 'connection' });
|
||||
@ -32,9 +38,8 @@ function selectServer(index: number) {
|
||||
|
||||
function addServer() {
|
||||
ElMessage.info('Add server is not implemented yet');
|
||||
|
||||
// mcpClientAdapter.clients.push(new McpClient());
|
||||
// mcpClientAdapter.currentClientIndex = mcpClientAdapter.clients.length - 1;
|
||||
mcpClientAdapter.clients.push(new McpClient());
|
||||
mcpClientAdapter.currentClientIndex = mcpClientAdapter.clients.length - 1;
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -45,11 +50,15 @@ function addServer() {
|
||||
}
|
||||
|
||||
.server-list {
|
||||
width: 200px;
|
||||
width: 150px;
|
||||
border-right: 1px solid var(--border-color);
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.server-name {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.server-item {
|
||||
padding: 10px;
|
||||
margin-bottom: 5px;
|
||||
|
@ -16,6 +16,7 @@ export interface IConnectionArgs {
|
||||
|
||||
|
||||
export interface IConnectionResult {
|
||||
info?: string;
|
||||
success: boolean;
|
||||
status: string
|
||||
clientId: string
|
||||
|
0
service/src/hook/util.ts
Normal file
0
service/src/hook/util.ts
Normal file
@ -42,19 +42,20 @@ interface ISSELaunchSignature {
|
||||
export type ILaunchSigature = IStdioLaunchSignature | ISSELaunchSignature;
|
||||
|
||||
function refreshConnectionOption(envPath: string) {
|
||||
const serverPath = path.join(__dirname, '..', '..', 'servers');
|
||||
|
||||
const defaultOption = {
|
||||
type:'STDIO',
|
||||
command: 'mcp',
|
||||
args: ['run', 'main.py'],
|
||||
cwd: '../server'
|
||||
commandString: 'mcp run main.py',
|
||||
cwd: serverPath
|
||||
};
|
||||
|
||||
fs.writeFileSync(envPath, JSON.stringify(defaultOption, null, 4));
|
||||
|
||||
return defaultOption;
|
||||
return { data: [ defaultOption ] };
|
||||
}
|
||||
|
||||
function getInitConnectionOption() {
|
||||
function acquireConnectionOption() {
|
||||
const envPath = path.join(__dirname, '..', '.env');
|
||||
|
||||
if (!fs.existsSync(envPath)) {
|
||||
@ -63,6 +64,15 @@ function getInitConnectionOption() {
|
||||
|
||||
try {
|
||||
const option = JSON.parse(fs.readFileSync(envPath, 'utf-8'));
|
||||
|
||||
if (!option.data) {
|
||||
return refreshConnectionOption(envPath);
|
||||
}
|
||||
|
||||
if (option.data && option.data.length === 0) {
|
||||
return refreshConnectionOption(envPath);
|
||||
}
|
||||
|
||||
return option;
|
||||
|
||||
} catch (error) {
|
||||
@ -73,27 +83,11 @@ function getInitConnectionOption() {
|
||||
|
||||
function updateConnectionOption(data: any) {
|
||||
const envPath = path.join(__dirname, '..', '.env');
|
||||
|
||||
if (data.connectionType === 'STDIO') {
|
||||
const connectionItem = {
|
||||
type: 'STDIO',
|
||||
command: data.command,
|
||||
args: data.args,
|
||||
cwd: data.cwd.replace(/\\/g, '/')
|
||||
};
|
||||
|
||||
fs.writeFileSync(envPath, JSON.stringify(connectionItem, null, 4));
|
||||
} else {
|
||||
const connectionItem = {
|
||||
type: 'SSE',
|
||||
url: data.url,
|
||||
oauth: data.oauth
|
||||
};
|
||||
|
||||
fs.writeFileSync(envPath, JSON.stringify(connectionItem, null, 4));
|
||||
}
|
||||
const connection = { data };
|
||||
fs.writeFileSync(envPath, JSON.stringify(connection, null, 4));
|
||||
}
|
||||
|
||||
|
||||
const devHome = path.join(__dirname, '..', '..');
|
||||
setRunningCWD(devHome);
|
||||
|
||||
@ -115,7 +109,7 @@ wss.on('connection', (ws: any) => {
|
||||
}
|
||||
});
|
||||
|
||||
const option = getInitConnectionOption();
|
||||
const option = acquireConnectionOption();
|
||||
|
||||
// 注册消息接受的管线
|
||||
webview.onDidReceiveMessage(message => {
|
||||
@ -124,21 +118,9 @@ wss.on('connection', (ws: any) => {
|
||||
|
||||
switch (command) {
|
||||
case 'web/launch-signature':
|
||||
const launchResultMessage: ILaunchSigature = option.type === 'STDIO' ?
|
||||
{
|
||||
type: 'STDIO',
|
||||
commandString: option.command + ' ' + option.args.join(' '),
|
||||
cwd: option.cwd || ''
|
||||
} :
|
||||
{
|
||||
type: 'SSE',
|
||||
url: option.url,
|
||||
oauth: option.oauth || ''
|
||||
};
|
||||
|
||||
const launchResult = {
|
||||
code: 200,
|
||||
msg: launchResultMessage
|
||||
msg: option.data
|
||||
};
|
||||
|
||||
webview.postMessage({
|
||||
|
@ -1,9 +1,11 @@
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { execSync, spawnSync } from 'node:child_process';
|
||||
import { RequestClientType } from '../common';
|
||||
import { connect } from './client.service';
|
||||
import { RestfulResponse } from '../common/index.dto';
|
||||
import { McpOptions } from './client.dto';
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs';
|
||||
|
||||
export const clientMap: Map<string, RequestClientType> = new Map();
|
||||
export function getClient(clientId?: string): RequestClientType | undefined {
|
||||
@ -15,30 +17,39 @@ export function tryGetRunCommandError(command: string, args: string[] = [], cwd?
|
||||
console.log('current command', command);
|
||||
console.log('current args', args);
|
||||
|
||||
const result = spawnSync(command, args, {
|
||||
cwd: cwd || process.cwd(),
|
||||
STDIO: 'pipe',
|
||||
encoding: 'utf-8'
|
||||
});
|
||||
const commandString = [command, ...args].join(' ');
|
||||
|
||||
if (result.error) {
|
||||
return result.error.message;
|
||||
}
|
||||
if (result.status !== 0) {
|
||||
return result.stderr || `Command failed with code ${result.status}`;
|
||||
}
|
||||
return null;
|
||||
const result = execSync(commandString, {
|
||||
cwd: cwd || process.cwd()
|
||||
}).toString('utf-8');
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
return error instanceof Error ? error.message : String(error);
|
||||
}
|
||||
}
|
||||
|
||||
export async function connectService(
|
||||
option: McpOptions
|
||||
): Promise<RestfulResponse> {
|
||||
try {
|
||||
console.log('ready to connect', option);
|
||||
function getCWD(option: McpOptions) {
|
||||
if (option.cwd) {
|
||||
return option.cwd;
|
||||
}
|
||||
const file = option.args?.at(-1);
|
||||
if (file) {
|
||||
return path.dirname(file);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getCommandFileExt(option: McpOptions) {
|
||||
const file = option.args?.at(-1);
|
||||
if (file) {
|
||||
return path.extname(file);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
function preprocessCommand(option: McpOptions): [McpOptions, string] {
|
||||
// 对于特殊表示的路径,进行特殊的支持
|
||||
if (option.args) {
|
||||
option.args = option.args.map(arg => {
|
||||
@ -49,6 +60,98 @@ export async function connectService(
|
||||
});
|
||||
}
|
||||
|
||||
if (option.connectionType === 'SSE' || option.connectionType === 'STREAMABLE_HTTP') {
|
||||
return [option, ''];
|
||||
}
|
||||
|
||||
const cwd = getCWD(option);
|
||||
if (!cwd) {
|
||||
return [option, ''];
|
||||
}
|
||||
|
||||
const ext = getCommandFileExt(option);
|
||||
if (!ext) {
|
||||
return [option, ''];
|
||||
}
|
||||
|
||||
// STDIO 模式下,对不同类型的项目进行额外支持
|
||||
// uv:如果没有初始化,则进行 uv sync,将 mcp 设置为虚拟环境的
|
||||
// npm:如果没有初始化,则进行 npm init,将 mcp 设置为虚拟环境
|
||||
// go:如果没有初始化,则进行 go mod init
|
||||
|
||||
let info: string = '';
|
||||
|
||||
switch (ext) {
|
||||
case '.py':
|
||||
info = initUv(cwd);
|
||||
break;
|
||||
case '.js':
|
||||
case '.ts':
|
||||
info = initNpm(cwd);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return [option, info];
|
||||
}
|
||||
|
||||
function initUv(cwd: string) {
|
||||
let projectDir = cwd;
|
||||
|
||||
while (projectDir!== path.dirname(projectDir)) {
|
||||
if (fs.readFileSync(projectDir).includes('pyproject.toml')) {
|
||||
break;
|
||||
}
|
||||
projectDir = path.dirname(projectDir);
|
||||
}
|
||||
|
||||
console.log(projectDir);
|
||||
|
||||
|
||||
const venv = path.join(projectDir, '.venv');
|
||||
const mcpCli = path.join(venv, 'bin', 'mcp');
|
||||
if (fs.existsSync(mcpCli)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
let info = '';
|
||||
info += execSync('uv sync', { cwd: projectDir }).toString('utf-8') + '\n';
|
||||
info += execSync('uv add mcp "mcp[cli]"', { cwd: projectDir }).toString('utf-8') + '\n';
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
function initNpm(cwd: string) {
|
||||
let projectDir = cwd;
|
||||
|
||||
while (projectDir !== path.dirname(projectDir)) {
|
||||
if (fs.readFileSync(projectDir).includes('package.json')) {
|
||||
break;
|
||||
}
|
||||
projectDir = path.dirname(projectDir);
|
||||
}
|
||||
|
||||
const nodeModulesPath = path.join(projectDir, 'node_modules');
|
||||
if (fs.existsSync(nodeModulesPath)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return execSync('npm i', { cwd: projectDir }).toString('utf-8') + '\n';
|
||||
}
|
||||
|
||||
|
||||
export async function connectService(
|
||||
option: McpOptions
|
||||
): Promise<RestfulResponse> {
|
||||
try {
|
||||
console.log('ready to connect', option);
|
||||
|
||||
const info = preprocessCommand(option);
|
||||
|
||||
const client = await connect(option);
|
||||
const uuid = randomUUID();
|
||||
clientMap.set(uuid, client);
|
||||
@ -61,7 +164,8 @@ export async function connectService(
|
||||
status: 'success',
|
||||
clientId: uuid,
|
||||
name: versionInfo?.name,
|
||||
version: versionInfo?.version
|
||||
version: versionInfo?.version,
|
||||
info
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -43,19 +43,20 @@ interface ISSELaunchSignature {
|
||||
export type ILaunchSigature = IStdioLaunchSignature | ISSELaunchSignature;
|
||||
|
||||
function refreshConnectionOption(envPath: string) {
|
||||
const serverPath = path.join(__dirname, '..', '..', 'servers');
|
||||
|
||||
const defaultOption = {
|
||||
type: 'STDIO',
|
||||
command: 'mcp',
|
||||
args: ['run', 'main.py'],
|
||||
cwd: '../server'
|
||||
type:'STDIO',
|
||||
commandString: 'mcp run main.py',
|
||||
cwd: serverPath
|
||||
};
|
||||
|
||||
fs.writeFileSync(envPath, JSON.stringify(defaultOption, null, 4));
|
||||
|
||||
return defaultOption;
|
||||
return { data: [ defaultOption ] };
|
||||
}
|
||||
|
||||
function getInitConnectionOption() {
|
||||
function acquireConnectionOption() {
|
||||
const envPath = path.join(__dirname, '..', '.env');
|
||||
|
||||
if (!fs.existsSync(envPath)) {
|
||||
@ -64,6 +65,15 @@ function getInitConnectionOption() {
|
||||
|
||||
try {
|
||||
const option = JSON.parse(fs.readFileSync(envPath, 'utf-8'));
|
||||
|
||||
if (!option.data) {
|
||||
return refreshConnectionOption(envPath);
|
||||
}
|
||||
|
||||
if (option.data && option.data.length === 0) {
|
||||
return refreshConnectionOption(envPath);
|
||||
}
|
||||
|
||||
return option;
|
||||
|
||||
} catch (error) {
|
||||
@ -81,25 +91,8 @@ const authPassword = JSON.parse(fs.readFileSync(path.join(__dirname, '..', '.env
|
||||
|
||||
function updateConnectionOption(data: any) {
|
||||
const envPath = path.join(__dirname, '..', '.env');
|
||||
|
||||
if (data.connectionType === 'STDIO') {
|
||||
const connectionItem = {
|
||||
type: 'STDIO',
|
||||
command: data.command,
|
||||
args: data.args,
|
||||
cwd: data.cwd.replace(/\\/g, '/')
|
||||
};
|
||||
|
||||
fs.writeFileSync(envPath, JSON.stringify(connectionItem, null, 4));
|
||||
} else {
|
||||
const connectionItem = {
|
||||
type: 'SSE',
|
||||
url: data.url,
|
||||
oauth: data.oauth
|
||||
};
|
||||
|
||||
fs.writeFileSync(envPath, JSON.stringify(connectionItem, null, 4));
|
||||
}
|
||||
const connection = { data };
|
||||
fs.writeFileSync(envPath, JSON.stringify(connection, null, 4));
|
||||
}
|
||||
|
||||
const devHome = path.join(__dirname, '..', '..');
|
||||
@ -146,7 +139,7 @@ wss.on('connection', (ws: any) => {
|
||||
}
|
||||
});
|
||||
|
||||
const option = getInitConnectionOption();
|
||||
const option = acquireConnectionOption();
|
||||
|
||||
// 注册消息接受的管线
|
||||
webview.onDidReceiveMessage(message => {
|
||||
@ -155,21 +148,9 @@ wss.on('connection', (ws: any) => {
|
||||
|
||||
switch (command) {
|
||||
case 'web/launch-signature':
|
||||
const launchResultMessage: ILaunchSigature = option.type === 'STDIO' ?
|
||||
{
|
||||
type: 'STDIO',
|
||||
commandString: option.command + ' ' + option.args.join(' '),
|
||||
cwd: option.cwd || ''
|
||||
} :
|
||||
{
|
||||
type: 'SSE',
|
||||
url: option.url,
|
||||
oauth: option.oauth || ''
|
||||
};
|
||||
|
||||
const launchResult = {
|
||||
code: 200,
|
||||
msg: launchResultMessage
|
||||
msg: option.data
|
||||
};
|
||||
|
||||
webview.postMessage({
|
||||
|
Loading…
x
Reference in New Issue
Block a user