Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | import { providerConfigs } from '@api/ai-providers'; import { RealtimeLlmEventParser } from '@api/services/realtime-llm-event-parser'; import type { AppContext } from '@api/types/hono'; import type { InternalProviderAPIConfig } from '@shared/types/ai-providers/config'; import type { RealtimeSessionOptions } from '@shared/types/realtime'; import { addListeners, getOptionsForOutgoingConnection, getURLForOutgoingConnection, } from './websocket-utils'; // Define types for Cloudflare Workers WebSocket environment interface WorkerWebSocket extends WebSocket { accept(): void; } interface WorkerResponse extends Response { webSocket: WorkerWebSocket; } // Cloudflare Workers WebSocketPair constructor declare const WebSocketPair: { new (): [WebSocket, WorkerWebSocket]; }; const getOutgoingWebSocket = async ( url: string, options: RequestInit, ): Promise<WorkerWebSocket> => { let outgoingWebSocket: WorkerWebSocket | null = null; try { const response = (await fetch(url, options)) as WorkerResponse; outgoingWebSocket = response.webSocket; } catch (error) { console.error(error); } if (!outgoingWebSocket) { throw new Error('WebSocket connection failed'); } outgoingWebSocket.accept(); return outgoingWebSocket; }; export async function realTimeHandler(c: AppContext): Promise<Response> { try { const headers = c.req.header(); const saRequestData = c.get('sa_request_data'); const saConfig = c.get('sa_config'); const provider = saConfig.targets[0].configuration.ai_provider; if (!provider) { throw new Error('Provider not found'); } const providerConfig = providerConfigs[provider]; if (!providerConfig) { throw new Error('Provider not found'); } const apiConfig: InternalProviderAPIConfig = providerConfig.api; if (!apiConfig) { throw new Error('API config not found'); } const url = getURLForOutgoingConnection( c, apiConfig, saConfig.targets[0], saRequestData, ); const options = await getOptionsForOutgoingConnection( c, apiConfig, saConfig.targets[0], ); const sessionOptions: RealtimeSessionOptions = { id: crypto.randomUUID(), providerOptions: { ...saConfig.targets[0], requestURL: url, rubeusURL: 'realtime', }, requestHeaders: headers as Record<string, string>, requestParams: {}, }; const webSocketPair = new WebSocketPair(); const client = webSocketPair[0]; const server = webSocketPair[1]; server.accept(); const outgoingWebSocket = await getOutgoingWebSocket(url, options); const eventParser = new RealtimeLlmEventParser(); addListeners(outgoingWebSocket, eventParser, server, c, sessionOptions); return new Response(null, { status: 101, webSocket: client, } as ResponseInit); } catch (err: unknown) { console.error( 'realtimeHandler error', err instanceof Error ? err.message : String(err), ); return new Response( JSON.stringify({ status: 'failure', message: 'Something went wrong', }), { status: 500, headers: { 'content-type': 'application/json', }, }, ); } } |