UNPKG

@vibe-kit/grok-cli

Version:

An open-source AI agent that brings the power of Grok directly into your terminal.

136 lines 5.21 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SseTransport = void 0; const transport_interface_1 = require("./transport-interface"); class SseTransport extends transport_interface_1.McpTransport { constructor(options) { super(options); this.eventSource = null; this.pendingRequests = new Map(); this.url = options.url; } async connect() { return new Promise((resolve, reject) => { try { // Import EventSource at runtime let EventSource; try { // The eventsource package exports the constructor directly EventSource = require('eventsource'); } catch (error) { return reject(new Error('EventSource package not found. Install "eventsource" package for Node.js support.')); } const headers = { 'Accept': 'text/event-stream', 'Cache-Control': 'no-cache', ...this.options.headers }; this.eventSource = new EventSource(this.url, { headers }); let connected = false; const timeout = setTimeout(() => { if (!connected) { this.eventSource?.close(); reject(new Error('Connection timeout')); } }, this.options.timeout || 30000); this.eventSource.onopen = () => { clearTimeout(timeout); connected = true; this.connected = true; this.emit('connect'); resolve(); }; this.eventSource.onmessage = (event) => { try { const message = JSON.parse(event.data); this.handleMessage(message); } catch (error) { console.warn('Failed to parse SSE message:', event.data, error); } }; this.eventSource.onerror = (error) => { clearTimeout(timeout); this.connected = false; this.emit('error', error); if (!connected) { reject(new Error('Failed to connect to SSE endpoint')); } }; } catch (error) { reject(error); } }); } handleMessage(message) { if (message.id !== undefined) { // Response const pending = this.pendingRequests.get(message.id); if (pending) { this.pendingRequests.delete(message.id); if (message.error) { pending.reject(new Error(`${message.error.message} (${message.error.code})`)); } else { pending.resolve(message.result); } } } else { // Notification this.emit('message', message); } } async send(message) { if (!this.connected || !this.eventSource) { throw new Error('SSE transport not connected'); } // For SSE, we typically send requests via HTTP POST to a companion endpoint // The SSE stream is for receiving responses/notifications const postUrl = this.url.replace('/sse', '/request'); try { const response = await fetch(postUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', ...this.options.headers }, body: JSON.stringify(message) }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } // If this is a request (has ID), wait for response via SSE if (message.id !== undefined) { return new Promise((resolve, reject) => { this.pendingRequests.set(message.id, { resolve, reject }); // Timeout handling setTimeout(() => { if (this.pendingRequests.has(message.id)) { this.pendingRequests.delete(message.id); reject(new Error(`Request timeout for method: ${message.method}`)); } }, this.options.timeout || 30000); }); } } catch (error) { throw new Error(`Failed to send SSE request: ${error}`); } } async disconnect() { if (this.eventSource) { this.eventSource.close(); this.eventSource = null; } this.connected = false; this.pendingRequests.clear(); this.emit('disconnect'); } } exports.SseTransport = SseTransport; //# sourceMappingURL=sse-transport.js.map