UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

139 lines (138 loc) • 4.97 kB
import { i as asOptionalObjectRecord } from "./record-coerce-TIsquoVR.mjs"; import "./string-coerce-runtime-B1b8UNzb.mjs"; import { n as rawDataToString } from "./ws-BdD3UP1C.mjs"; import "./realtime-voice-provider-D_Fp61Jy.mjs"; import { r as isOpenAIGptLiveApiModel } from "./realtime-quicksilver-0VQEPDSP.mjs"; import { t as parseOpenAIQuicksilverEvent } from "./realtime-quicksilver-events-BptwDZ_Q.mjs"; //#region extensions/openai/realtime-quicksilver-protocol.ts function buildOpenAIQuicksilverAudioAppend(model, audio) { return { type: isOpenAIGptLiveApiModel(model) ? "session.input_audio.append" : "input_audio.append", audio }; } function buildOpenAIQuicksilverContextAppend(params) { if (isOpenAIGptLiveApiModel(params.model)) return { type: params.channel === "speakable" ? "session.commentary.append" : "session.thinking.append", delegation_id: params.delegationId ?? null, content: params.text }; return { type: params.delegationId ? "delegation.context.append" : "session.context.append", ...params.delegationId ? { delegation_item_id: params.delegationId } : {}, ...params.channel ? { channel: params.channel } : {}, content: [{ type: "input_text", text: params.text }] }; } function openAIQuicksilverToolResultText(result) { if (typeof result === "string") return result; const record = asOptionalObjectRecord(result); if (record) for (const key of [ "text", "result", "output", "error" ]) { const value = record[key]; if (typeof value === "string" && value.trim()) return value; } try { return JSON.stringify(result) ?? String(result); } catch { return String(result); } } async function closeOpenAILiveSocket(socket) { let outcome; try { outcome = { reason: await new Promise((resolve, reject) => { const finish = (result) => { clearTimeout(timeout); socket.off("message", onMessage); socket.off("close", onClose); socket.off("error", onClose); if (result instanceof Error) reject(result); else resolve(result); }; const onMessage = (data, isBinary) => { if (!isBinary) { const event = parseOpenAIQuicksilverEvent(rawDataToString(data), "gpt-live-1"); if (event?.kind === "session-closed") finish(event.reason); } }; const onClose = () => finish(/* @__PURE__ */ new Error("GPT-Live connection ended before session.closed; finalization is unconfirmed")); const timeout = setTimeout(() => finish(/* @__PURE__ */ new Error("GPT-Live session.closed timed out; finalization is unconfirmed")), 15e3); timeout.unref?.(); socket.on("message", onMessage); socket.on("close", onClose); socket.on("error", onClose); if (socket.readyState !== 1) { onClose(); return; } try { socket.send(JSON.stringify({ type: "session.close" })); } catch { onClose(); } }) }; } catch (error) { outcome = { error }; } try { socket.close(1e3, "session closed"); } catch { if (!("error" in outcome)) outcome = { error: /* @__PURE__ */ new Error("GPT-Live transport could not be closed") }; } if ("error" in outcome) throw outcome.error; return outcome.reason; } function retireOpenAIQuicksilverSessionWire(params) { const publicApi = isOpenAIGptLiveApiModel(params.model); const finish = (error) => { try { if (publicApi) params.delegations.detach(); else params.delegations.stop(/* @__PURE__ */ new Error("GPT-Live delegation stopped")); } finally { params.controller.abort(/* @__PURE__ */ new Error("GPT-Live session closed")); if (!publicApi && params.socket.readyState === 1) try { params.socket.send(JSON.stringify({ type: "session.close" })); } catch {} try { params.socket.close(1e3, "session closed"); } catch {} params.reportTerminal(error); } }; if (!publicApi) { finish(params.error); return; } params.delegations.beginTranscriptDrain("abort"); if (params.error || params.isFinalized() || params.socket.readyState !== 1) { finish(params.error); return; } return closeOpenAILiveSocket(params.socket).then((reason) => finish(reason === "content" || reason === "connection_lost" ? /* @__PURE__ */ new Error("GPT-Live session ended with a provider or connection failure") : void 0), (error) => { finish(/* @__PURE__ */ new Error("GPT-Live session finalization was not confirmed")); throw error; }); } /** Transport diagnostics retain activity only, never routes, IDs, or frame content. */ function captureOpenAIQuicksilverTransportEvent(runtime, direction, kind) { runtime.captureWsEventAsync?.({ url: "wss://realtime.invalid/private", direction, kind, flowId: "private-realtime", meta: { provider: "openai", capability: "gpt-live-voice" } }).catch(() => {}); } //#endregion export { openAIQuicksilverToolResultText as a, closeOpenAILiveSocket as i, buildOpenAIQuicksilverContextAppend as n, retireOpenAIQuicksilverSessionWire as o, captureOpenAIQuicksilverTransportEvent as r, buildOpenAIQuicksilverAudioAppend as t };