From e306388f146bfc544b15081494f98a9c08b34ab8 Mon Sep 17 00:00:00 2001 From: Kirigaya <1193466151@qq.com> Date: Sun, 13 Apr 2025 15:19:13 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20vscode/trae=20=E4=B8=8B=20?= =?UTF-8?q?tab=20=E6=81=A2=E5=A4=8D=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- renderer/src/hook/panel.ts | 12 +++-- service/src/controller/connect.ts | 12 ++++- service/src/controller/panel.ts | 6 ++- service/src/index.ts | 2 +- service/src/util.ts | 41 ++++++++++------- service/tabs.untitle.json | 4 ++ service/tabs.锦恢的 MCP Server.json | 70 +++++++++++++++++++++++++++++ src/extension.ts | 15 ++++--- 8 files changed, 131 insertions(+), 31 deletions(-) create mode 100644 service/tabs.untitle.json create mode 100644 service/tabs.锦恢的 MCP Server.json diff --git a/renderer/src/hook/panel.ts b/renderer/src/hook/panel.ts index 11cb996..772a5de 100644 --- a/renderer/src/hook/panel.ts +++ b/renderer/src/hook/panel.ts @@ -1,9 +1,7 @@ import { useMessageBridge } from "@/api/message-bridge"; -import { llmManager, llms } from "@/views/setting/llm"; import { pinkLog } from "@/views/setting/util"; -import I18n from '@/i18n/index'; import { debugModes, tabs } from "@/components/main-panel/panel"; -import { markRaw, ref } from "vue"; +import { markRaw, ref, nextTick } from "vue"; interface SaveTabItem { name: string; @@ -53,6 +51,9 @@ export function loadPanels() { } tabs.activeIndex = persistTab.currentIndex; + nextTick(() => { + tabs.activeIndex = persistTab.currentIndex; + }); } panelLoaded.value = true; @@ -73,6 +74,11 @@ export function safeSavePanels() { } export function savePanels(saveHandler?: () => void) { + // 没有完成 panel 加载就不保存 + if (!panelLoaded.value) { + return; + } + const bridge = useMessageBridge(); const saveTabs: SaveTab = { diff --git a/service/src/controller/connect.ts b/service/src/controller/connect.ts index 5e2f316..8b0e494 100644 --- a/service/src/controller/connect.ts +++ b/service/src/controller/connect.ts @@ -2,11 +2,13 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js"; import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js"; +import { Implementation } from "@modelcontextprotocol/sdk/types"; // 定义连接类型 type ConnectionType = 'STDIO' | 'SSE'; type McpTransport = StdioClientTransport | SSEClientTransport; +export type IServerVersion = Implementation | undefined; // 定义命令行参数接口 export interface MCPOptions { @@ -27,9 +29,11 @@ export class MCPClient { private client: Client; private transport?: McpTransport; private options: MCPOptions; + private serverVersion: IServerVersion; constructor(options: MCPOptions) { this.options = options; + this.serverVersion = undefined; this.client = new Client( { @@ -73,7 +77,13 @@ export class MCPClient { } public getServerVersion() { - return this.client.getServerVersion(); + if (this.serverVersion) { + return this.serverVersion; + } + + const version = this.client.getServerVersion(); + this.serverVersion = version; + return version; } // 断开连接 diff --git a/service/src/controller/panel.ts b/service/src/controller/panel.ts index ad006ca..9e636fc 100644 --- a/service/src/controller/panel.ts +++ b/service/src/controller/panel.ts @@ -5,7 +5,8 @@ import { MCPClient } from './connect'; export async function panelSaveHandler(client: MCPClient | undefined, data: any, webview: PostMessageble) { try { // 保存配置 - saveTabSaveConfig(data); + const serverInfo = client?.getServerVersion(); + saveTabSaveConfig(serverInfo, data); webview.postMessage({ command: 'panel/save', @@ -28,7 +29,8 @@ export async function panelSaveHandler(client: MCPClient | undefined, data: any, export async function panelLoadHandler(client: MCPClient | undefined, webview: PostMessageble) { try { // 加载配置 - const config = loadTabSaveConfig(); + const serverInfo = client?.getServerVersion(); + const config = loadTabSaveConfig(serverInfo); webview.postMessage({ command: 'panel/load', diff --git a/service/src/index.ts b/service/src/index.ts index 2899a1b..3c29ddc 100644 --- a/service/src/index.ts +++ b/service/src/index.ts @@ -1,3 +1,3 @@ export { messageController } from './controller'; export { VSCodeWebViewLike } from './adapter'; -export type { VSCodeMessage, MessageHandler } from './main'; \ No newline at end of file +export { setVscodeWorkspace } from './util'; \ No newline at end of file diff --git a/service/src/util.ts b/service/src/util.ts index 4edce7d..d2b2546 100644 --- a/service/src/util.ts +++ b/service/src/util.ts @@ -2,10 +2,17 @@ import * as fs from 'fs'; import * as path from 'path'; import * as os from 'os'; import { llms } from './llm'; +import { IServerVersion } from './controller/connect'; + +export let VSCODE_WORKSPACE = ''; + +export function setVscodeWorkspace(workspace: string) { + VSCODE_WORKSPACE = workspace; +} function getConfigurationPath() { // 如果是 vscode 插件下,则修改为 ~/.openmcp/config.json - if (process.env.VSCODE_PID) { + if (VSCODE_WORKSPACE) { // 在 VSCode 插件环境下 const homeDir = os.homedir(); const configDir = path.join(homeDir, '.openmcp'); @@ -17,18 +24,20 @@ function getConfigurationPath() { return 'config.json'; } -function getTabSavePath() { +function getTabSavePath(serverInfo: IServerVersion) { + const { name = 'untitle', version = '0.0.0' } = serverInfo || {}; + const tabSaveName = `tabs.${name}.json`; + // 如果是 vscode 插件下,则修改为 ~/.vscode/openmcp.json - if (process.env.VSCODE_PID) { + if (VSCODE_WORKSPACE) { // 在 VSCode 插件环境下 - const homeDir = os.homedir(); - const configDir = path.join(homeDir, '.openmcp'); + const configDir = path.join(VSCODE_WORKSPACE, '.vscode'); if (!fs.existsSync(configDir)) { fs.mkdirSync(configDir, { recursive: true }); } - return path.join(configDir, 'tabs.json'); + return path.join(configDir, tabSaveName); } - return 'tabs.json'; + return tabSaveName; } function getDefaultLanguage() { @@ -82,8 +91,8 @@ function createConfig(): IConfig { return DEFAULT_CONFIG; } -function createSaveTabConfig(): SaveTab { - const configPath = getTabSavePath(); +function createSaveTabConfig(serverInfo: IServerVersion): SaveTab { + const configPath = getTabSavePath(serverInfo); const configDir = path.dirname(configPath); // 确保配置目录存在 @@ -114,8 +123,6 @@ export function loadConfig(): IConfig { export function saveConfig(config: Partial): void { const configPath = getConfigurationPath(); - let currentConfig: IConfig = DEFAULT_CONFIG; - console.log('save to ' + configPath); try { @@ -126,11 +133,11 @@ export function saveConfig(config: Partial): void { } } -export function loadTabSaveConfig(): SaveTab { - const tabSavePath = getTabSavePath(); +export function loadTabSaveConfig(serverInfo: IServerVersion): SaveTab { + const tabSavePath = getTabSavePath(serverInfo); if (!fs.existsSync(tabSavePath)) { - return createSaveTabConfig(); + return createSaveTabConfig(serverInfo); } try { @@ -138,12 +145,12 @@ export function loadTabSaveConfig(): SaveTab { return JSON.parse(configData) as SaveTab; } catch (error) { console.error('Error loading config file, creating new one:', error); - return createSaveTabConfig(); + return createSaveTabConfig(serverInfo); } } -export function saveTabSaveConfig(config: Partial): void { - const tabSavePath = getTabSavePath(); +export function saveTabSaveConfig(serverInfo: IServerVersion, config: Partial): void { + const tabSavePath = getTabSavePath(serverInfo); try { fs.writeFileSync(tabSavePath, JSON.stringify(config, null, 2), 'utf-8'); diff --git a/service/tabs.untitle.json b/service/tabs.untitle.json new file mode 100644 index 0000000..497bc1e --- /dev/null +++ b/service/tabs.untitle.json @@ -0,0 +1,4 @@ +{ + "tabs": [], + "currentIndex": -1 +} \ No newline at end of file diff --git a/service/tabs.锦恢的 MCP Server.json b/service/tabs.锦恢的 MCP Server.json new file mode 100644 index 0000000..a235a34 --- /dev/null +++ b/service/tabs.锦恢的 MCP Server.json @@ -0,0 +1,70 @@ +{ + "currentIndex": 0, + "tabs": [ + { + "name": "资源", + "icon": "icon-file", + "type": "blank", + "componentIndex": 0, + "storage": { + "currentResourceName": "greeting", + "lastResourceReadResponse": { + "contents": [ + { + "uri": "greeting://12312", + "mimeType": "text/plain", + "text": "Hello, 12312!" + } + ] + } + } + }, + { + "name": "交互测试", + "icon": "icon-robot", + "type": "blank", + "componentIndex": 3, + "storage": { + "messages": [], + "settings": { + "modelIndex": 0, + "enableTools": [ + { + "name": "add", + "description": "对两个数字进行实数域的加法", + "enabled": true + }, + { + "name": "multiply", + "description": "对两个数字进行实数域的乘法运算", + "enabled": true + }, + { + "name": "is_even", + "description": "判断一个整数是否为偶数", + "enabled": true + }, + { + "name": "capitalize", + "description": "将字符串首字母大写", + "enabled": true + } + ], + "enableWebSearch": false, + "temperature": 0.7, + "contextLength": 10, + "systemPrompt": "" + } + } + }, + { + "name": "提词", + "icon": "icon-chat", + "type": "blank", + "componentIndex": 1, + "storage": { + "currentPromptName": "translate" + } + } + ] +} \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index 1ca81b6..1979cf7 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -27,6 +27,12 @@ function getLaunchCWD(context: vscode.ExtensionContext, uri: vscode.Uri) { export function activate(context: vscode.ExtensionContext) { console.log('activate openmcp'); + // 初始化 OpenMCPService + // 获取当前打开的项目的路径 + const workspaceFolder = vscode.workspace.workspaceFolders?.[0]; + const workspace = workspaceFolder?.uri.fsPath || ''; + OpenMCPService.setVscodeWorkspace(workspace); + // 注册 showOpenMCP 命令 context.subscriptions.push( vscode.commands.registerCommand('openmcp.showOpenMCP', async (uri: vscode.Uri) => { @@ -51,7 +57,8 @@ export function activate(context: vscode.ExtensionContext) { // 设置HTML内容 const html = getWebviewContent(context, panel); - panel.webview.html = html || ''; + panel.webview.html = html || ''; + panel.iconPath = vscode.Uri.file(fspath.join(context.extensionPath, 'resources', 'renderer', 'images', 'openmcp.png')); // 处理来自webview的消息 panel.webview.onDidReceiveMessage(message => { @@ -89,12 +96,6 @@ export function activate(context: vscode.ExtensionContext) { }); }) ); - - // const provider = new WebviewViewProvider(context); - - // context.subscriptions.push( - // vscode.window.registerWebviewViewProvider('webview-sidebar.view', provider) - // ); }