import type { IncomingMessage, ServerResponse } from 'http'; import { PORTS } from '../../utils/config'; import { getSetting } from '../../utils/store'; import type { HostApiContext } from '../context'; import { parseJsonBody, sendJson } from '../route-utils'; export async function handleGatewayRoutes( req: IncomingMessage, res: ServerResponse, url: URL, ctx: HostApiContext, ): Promise { if (url.pathname === '/api/app/gateway-info' && req.method === 'GET') { const status = ctx.gatewayManager.getStatus(); const token = await getSetting('gatewayToken'); const port = status.port || PORTS.OPENCLAW_GATEWAY; sendJson(res, 200, { wsUrl: `ws://127.0.0.1:${port}/ws`, token, port, }); return true; } if (url.pathname === '/api/gateway/status' && req.method === 'GET') { sendJson(res, 200, ctx.gatewayManager.getStatus()); return true; } if (url.pathname === '/api/gateway/health' && req.method === 'GET') { const health = await ctx.gatewayManager.checkHealth(); sendJson(res, 200, health); return true; } if (url.pathname === '/api/gateway/start' && req.method === 'POST') { try { await ctx.gatewayManager.start(); sendJson(res, 200, { success: true }); } catch (error) { sendJson(res, 500, { success: false, error: String(error) }); } return true; } if (url.pathname === '/api/gateway/stop' && req.method === 'POST') { try { await ctx.gatewayManager.stop(); sendJson(res, 200, { success: true }); } catch (error) { sendJson(res, 500, { success: false, error: String(error) }); } return true; } if (url.pathname === '/api/gateway/restart' && req.method === 'POST') { try { await ctx.gatewayManager.restart(); sendJson(res, 200, { success: true }); } catch (error) { sendJson(res, 500, { success: false, error: String(error) }); } return true; } if (url.pathname === '/api/gateway/control-ui' && req.method === 'GET') { try { const status = ctx.gatewayManager.getStatus(); const token = await getSetting('gatewayToken'); const port = status.port || PORTS.OPENCLAW_GATEWAY; const urlValue = `http://127.0.0.1:${port}/?token=${encodeURIComponent(token)}`; sendJson(res, 200, { success: true, url: urlValue, token, port }); } catch (error) { sendJson(res, 500, { success: false, error: String(error) }); } return true; } if (url.pathname === '/api/chat/send-with-media' && req.method === 'POST') { try { const body = await parseJsonBody<{ sessionKey: string; message: string; deliver?: boolean; idempotencyKey: string; media?: Array<{ filePath: string; mimeType: string; fileName: string }>; }>(req); const VISION_MIME_TYPES = new Set([ 'image/png', 'image/jpeg', 'image/bmp', 'image/webp', ]); const imageAttachments: Array<{ content: string; mimeType: string; fileName: string }> = []; const fileReferences: string[] = []; if (body.media && body.media.length > 0) { const fsP = await import('node:fs/promises'); for (const m of body.media) { fileReferences.push(`[media attached: ${m.filePath} (${m.mimeType}) | ${m.filePath}]`); if (VISION_MIME_TYPES.has(m.mimeType)) { const fileBuffer = await fsP.readFile(m.filePath); imageAttachments.push({ content: fileBuffer.toString('base64'), mimeType: m.mimeType, fileName: m.fileName, }); } } } const message = fileReferences.length > 0 ? [body.message, ...fileReferences].filter(Boolean).join('\n') : body.message; const rpcParams: Record = { sessionKey: body.sessionKey, message, deliver: body.deliver ?? false, idempotencyKey: body.idempotencyKey, }; if (imageAttachments.length > 0) { rpcParams.attachments = imageAttachments; } const result = await ctx.gatewayManager.rpc('chat.send', rpcParams, 120000); sendJson(res, 200, { success: true, result }); } catch (error) { sendJson(res, 500, { success: false, error: String(error) }); } return true; } return false; }