diff --git a/README.md b/README.md index 2559c88..b57de77 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,15 @@ - 包含一个简易的用于进行测试的大模型对话 & 执行窗口 - 支持多种大模型 +--- + +## TODO + +- [x] 完成最基本的各类基础设施 +- [ ] 支持同时调试多个 MCP Server +- [ ] 支持通过大模型进行在线验证 + +--- ## Dev diff --git a/app/public/CascadiaCode.woff2 b/app/public/CascadiaCode.woff2 new file mode 100644 index 0000000..ed0335c Binary files /dev/null and b/app/public/CascadiaCode.woff2 differ diff --git a/app/public/mcp.css b/app/public/mcp.css index 8f733f1..a5ff19c 100644 --- a/app/public/mcp.css +++ b/app/public/mcp.css @@ -11,6 +11,8 @@ --toolbar-height: 50px; --toolbar-item-height: 32px; + --code-font-family: "Cascadia code"; + /* css 动画属性 */ --animation-7s: .7s cubic-bezier(0.23,1,0.32,1); --animation-5s: .5s cubic-bezier(0.23,1,0.32,1); diff --git a/app/src/App.vue b/app/src/App.vue index 926f181..c606c9a 100644 --- a/app/src/App.vue +++ b/app/src/App.vue @@ -18,10 +18,12 @@ import { useMessageBridge } from './api/message-bridge'; const bridge = useMessageBridge(); // 监听所有消息 -bridge.onMessage((message) => { - console.log('Received:', message.command, message.data); +bridge.addCommandListener('hello', data => { + pinkLog(`${data.name} 上线`); + pinkLog(`version: ${data.version}`); }); + // 发送消息 const sendPing = () => { bridge.postMessage({ diff --git a/app/src/api/message-bridge.ts b/app/src/api/message-bridge.ts index 29e3e52..91ceef2 100644 --- a/app/src/api/message-bridge.ts +++ b/app/src/api/message-bridge.ts @@ -8,11 +8,13 @@ export interface VSCodeMessage { } export type MessageHandler = (message: VSCodeMessage) => void; +export type CommandHandler = (data: any) => void; + export const acquireVsCodeApi = (window as any)['acquireVsCodeApi']; class MessageBridge { private ws: WebSocket | null = null; - private handlers = new Set(); + private handlers = new Map>(); public isConnected = ref(false); constructor(private wsUrl: string = 'ws://localhost:8080') { @@ -72,17 +74,35 @@ class MessageBridge { }; } + /** + * @description 对 message 发起调度,根据 command 类型获取调取器 + * @param message + */ private dispatchMessage(message: VSCodeMessage) { - this.handlers.forEach(handler => handler(message)); + const command = message.command; + const data = message.data; + + const handlers = this.handlers.get(command) || []; + handlers.forEach(handler => handler(data)); } public postMessage(message: VSCodeMessage) { throw new Error('PostMessage not initialized'); } + + /** + * @description 注册一个命令的执行器 + * @param handler + * @returns + */ + public addCommandListener(command: string, commandHandler: CommandHandler) { + if (!this.handlers.has(command)) { + this.handlers.set(command, new Set()); + } + const commandHandlers = this.handlers.get(command)!; + commandHandlers.add(commandHandler); - public onMessage(handler: MessageHandler) { - this.handlers.add(handler); - return () => this.handlers.delete(handler); + return () => commandHandlers.delete(commandHandler); } public destroy() { @@ -104,7 +124,7 @@ export function useMessageBridge() { return { postMessage: bridge.postMessage.bind(bridge), - onMessage: bridge.onMessage.bind(bridge), + addCommandListener: bridge.addCommandListener.bind(bridge), isConnected: bridge.isConnected }; } \ No newline at end of file diff --git a/app/src/hook/css.ts b/app/src/hook/css.ts index 2f7b68f..1c78c07 100644 --- a/app/src/hook/css.ts +++ b/app/src/hook/css.ts @@ -22,6 +22,8 @@ export function setDefaultCss() { document.body.style.setProperty('--el-color-primary-dark-2', 'var(--main-light-color)'); document.body.style.setProperty('--el-fill-color-dark', 'var(--main-light-color)'); document.body.style.setProperty('--el-fill-color-darker', 'var(--main-light-color)'); + document.body.style.setProperty('--el-color-primary-light-5', 'var(--button-disabled)'); + // document.body.style.setProperty('--el-color-white', 'var(--background)'); // 设置全局宏 diff --git a/app/src/i18n/ar.json b/app/src/i18n/ar.json index 3cbee6b..0fc8c6a 100644 --- a/app/src/i18n/ar.json +++ b/app/src/i18n/ar.json @@ -103,5 +103,6 @@ "api-token": "مفتاح API", "connection-method": "طريقة الاتصال", "command": "أمر", - "env-var": "متغيرات البيئة" + "env-var": "متغيرات البيئة", + "log": "سجلات" } \ No newline at end of file diff --git a/app/src/i18n/de.json b/app/src/i18n/de.json index 6faede9..e22998f 100644 --- a/app/src/i18n/de.json +++ b/app/src/i18n/de.json @@ -103,5 +103,6 @@ "api-token": "API-Schlüssel", "connection-method": "Verbindungsmethode", "command": "Befehl", - "env-var": "Umgebungsvariablen" + "env-var": "Umgebungsvariablen", + "log": "Protokolle" } \ No newline at end of file diff --git a/app/src/i18n/en.json b/app/src/i18n/en.json index 935e6d5..d16bc29 100644 --- a/app/src/i18n/en.json +++ b/app/src/i18n/en.json @@ -103,5 +103,6 @@ "api-token": "API key", "connection-method": "Connection method", "command": "Command", - "env-var": "Environment variables" + "env-var": "Environment variables", + "log": "Logs" } \ No newline at end of file diff --git a/app/src/i18n/fr.json b/app/src/i18n/fr.json index 8d13019..8e5783d 100644 --- a/app/src/i18n/fr.json +++ b/app/src/i18n/fr.json @@ -103,5 +103,6 @@ "api-token": "Clé API", "connection-method": "Méthode de connexion", "command": "Commande", - "env-var": "Variables d'environnement" + "env-var": "Variables d'environnement", + "log": "Journaux" } \ No newline at end of file diff --git a/app/src/i18n/ja.json b/app/src/i18n/ja.json index 2ecc5f0..30a4603 100644 --- a/app/src/i18n/ja.json +++ b/app/src/i18n/ja.json @@ -103,5 +103,6 @@ "api-token": "APIキー", "connection-method": "接続方法", "command": "コマンド", - "env-var": "環境変数" + "env-var": "環境変数", + "log": "ログ" } \ No newline at end of file diff --git a/app/src/i18n/ko.json b/app/src/i18n/ko.json index d90b65c..320778e 100644 --- a/app/src/i18n/ko.json +++ b/app/src/i18n/ko.json @@ -103,5 +103,6 @@ "api-token": "API 키", "connection-method": "연결 방법", "command": "명령", - "env-var": "환경 변수" + "env-var": "환경 변수", + "log": "로그" } \ No newline at end of file diff --git a/app/src/i18n/ru.json b/app/src/i18n/ru.json index 04c8d0a..0da8c4a 100644 --- a/app/src/i18n/ru.json +++ b/app/src/i18n/ru.json @@ -103,5 +103,6 @@ "api-token": "API-ключ", "connection-method": "Способ подключения", "command": "Команда", - "env-var": "Переменные среды" + "env-var": "Переменные среды", + "log": "Логи" } \ No newline at end of file diff --git a/app/src/i18n/zh-cn.json b/app/src/i18n/zh-cn.json index 453f256..f4ad466 100644 --- a/app/src/i18n/zh-cn.json +++ b/app/src/i18n/zh-cn.json @@ -103,5 +103,6 @@ "api-token": "API 密钥", "connection-method": "连接方式", "command": "命令", - "env-var": "环境变量" + "env-var": "环境变量", + "log": "日志" } \ No newline at end of file diff --git a/app/src/i18n/zh-tw.json b/app/src/i18n/zh-tw.json index f953b9b..6b0537d 100644 --- a/app/src/i18n/zh-tw.json +++ b/app/src/i18n/zh-tw.json @@ -103,5 +103,6 @@ "api-token": "API 密鑰", "connection-method": "連接方式", "command": "命令", - "env-var": "環境變數" + "env-var": "環境變數", + "log": "日誌" } \ No newline at end of file diff --git a/app/src/router/index.ts b/app/src/router/index.ts index 7a33c9e..4add9dc 100644 --- a/app/src/router/index.ts +++ b/app/src/router/index.ts @@ -1,6 +1,11 @@ import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router"; const routes: Array = [ + { + name : "default", + path : "/", + redirect : "/debug" + }, { path: "/debug", name: "debug", diff --git a/app/src/views/connect/connection-args.vue b/app/src/views/connect/connection-args.vue index 19753ca..3b90b90 100644 --- a/app/src/views/connect/connection-args.vue +++ b/app/src/views/connect/connection-args.vue @@ -33,13 +33,9 @@ import { connectionArgs, connectionMethods } from './connection'; const { t } = useI18n(); -interface ConnectionMethods { - current: string -} const stdioForm = ref() const urlForm = ref() - // 验证规则 const rules = reactive({ commandString: [ diff --git a/app/src/views/connect/connection-log.vue b/app/src/views/connect/connection-log.vue new file mode 100644 index 0000000..83052d8 --- /dev/null +++ b/app/src/views/connect/connection-log.vue @@ -0,0 +1,42 @@ + + + + + \ No newline at end of file diff --git a/app/src/views/connect/connection-method.vue b/app/src/views/connect/connection-method.vue new file mode 100644 index 0000000..4f56a83 --- /dev/null +++ b/app/src/views/connect/connection-method.vue @@ -0,0 +1,24 @@ + + + + + \ No newline at end of file diff --git a/app/src/views/connect/connection.ts b/app/src/views/connect/connection.ts index 0e47617..1b7fe72 100644 --- a/app/src/views/connect/connection.ts +++ b/app/src/views/connect/connection.ts @@ -37,10 +37,6 @@ export const connectionEnv = reactive({ newValue: '' }); -export function onconnectionmethodchange() { - console.log(); - -} // 定义连接类型 type ConnectionType = 'STDIO' | 'SSE'; @@ -58,12 +54,15 @@ export interface MCPOptions { clientVersion?: string; } - - export function doConnect() { let connectOption: MCPOptions; if (connectionMethods.current === 'STDIO') { + + if (connectionArgs.commandString.length === 0) { + return; + } + const commandComponents = connectionArgs.commandString.split(/\s+/g); const command = commandComponents[0]; commandComponents.shift(); @@ -79,6 +78,10 @@ export function doConnect() { } else { const url = connectionArgs.urlString; + if (url.length === 0) { + return; + } + connectOption = { connectionType: 'SSE', url: url, @@ -92,4 +95,14 @@ export function doConnect() { command: 'connect', data: connectOption }); -} \ No newline at end of file +} + +export function doReconnect() { + // TODO: finish this + console.log(); +} + +export const connectionResult = reactive({ + success: false, + logString: '' +}); \ No newline at end of file diff --git a/app/src/views/connect/env-var.vue b/app/src/views/connect/env-var.vue new file mode 100644 index 0000000..8cb7048 --- /dev/null +++ b/app/src/views/connect/env-var.vue @@ -0,0 +1,83 @@ + + + + + + \ No newline at end of file diff --git a/app/src/views/connect/index.vue b/app/src/views/connect/index.vue index 61332dc..f68cd64 100644 --- a/app/src/views/connect/index.vue +++ b/app/src/views/connect/index.vue @@ -1,124 +1,74 @@