openmcp-client/app/src/api/message-bridge.ts
2025-03-27 21:01:12 +08:00

110 lines
2.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { pinkLog } from '@/views/setting/util';
import { onUnmounted, ref } from 'vue';
export interface VSCodeMessage {
command: string;
payload?: unknown;
callbackId?: string;
}
export type MessageHandler = (message: VSCodeMessage) => void;
export const acquireVsCodeApi = (window as any)['acquireVsCodeApi'];
class MessageBridge {
private ws: WebSocket | null = null;
private handlers = new Set<MessageHandler>();
public isConnected = ref(false);
constructor(private wsUrl: string = 'ws://localhost:8080') {
this.init();
}
private init() {
// 环境检测优先级:
// 1. VS Code WebView 环境
// 2. 浏览器 WebSocket 环境
if (typeof acquireVsCodeApi !== 'undefined') {
this.setupVSCodeListener();
pinkLog('当前模式release');
} else {
this.setupWebSocket();
pinkLog('当前模式debug');
}
}
// VS Code 环境监听
private setupVSCodeListener() {
const vscode = acquireVsCodeApi();
window.addEventListener('message', (event: MessageEvent<VSCodeMessage>) => {
this.dispatchMessage(event.data);
});
this.postMessage = (message) => vscode.postMessage(message);
this.isConnected.value = true;
}
// WebSocket 环境连接
private setupWebSocket() {
this.ws = new WebSocket(this.wsUrl);
this.ws.onopen = () => {
this.isConnected.value = true;
};
this.ws.onmessage = (event) => {
try {
const message = JSON.parse(event.data) as VSCodeMessage;
this.dispatchMessage(message);
} catch (err) {
console.error('Message parse error:', err);
}
};
this.ws.onclose = () => {
this.isConnected.value = false;
};
this.postMessage = (message) => {
if (this.ws?.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(message));
}
};
}
private dispatchMessage(message: VSCodeMessage) {
this.handlers.forEach(handler => handler(message));
}
public postMessage(message: VSCodeMessage) {
throw new Error('PostMessage not initialized');
}
public onMessage(handler: MessageHandler) {
this.handlers.add(handler);
return () => this.handlers.delete(handler);
}
public destroy() {
this.ws?.close();
this.handlers.clear();
}
}
// 单例实例
const messageBridge = new MessageBridge();
// 向外暴露一个独立函数,保证 MessageBridge 是单例的
export function useMessageBridge() {
const bridge = messageBridge;
onUnmounted(() => {
bridge.destroy();
});
return {
postMessage: bridge.postMessage.bind(bridge),
onMessage: bridge.onMessage.bind(bridge),
isConnected: bridge.isConnected
};
}