openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
158 lines (157 loc) • 5.8 kB
JavaScript
import { u as toErrorObject } from "./error-coercion-1P2One0X.mjs";
import { c as sleepWithAbort } from "./src-DqaLEvc_.mjs";
import "./realtime-voice-provider-D_Fp61Jy.mjs";
import { f as openAIQuicksilverAuthHeaders } from "./realtime-quicksilver-wire-DVntsqk5.mjs";
//#region extensions/openai/realtime-quicksilver-sideband.ts
const SIDEBAND_CONNECT_TIMEOUT_MS = 15e3;
const SIDEBAND_CONNECT_ATTEMPTS = 5;
const SIDEBAND_RETRY_BASE_MS = 200;
const EARLY_FRAME_MAX = 32;
const EARLY_FRAME_MAX_BYTES = 1048576;
const SIDEBAND_MAX_PAYLOAD_BYTES = 16777216;
function rawDataByteLength(data) {
if (Array.isArray(data)) return data.reduce((total, chunk) => total + chunk.byteLength, 0);
return data.byteLength;
}
function waitForSocketOpen(params) {
return new Promise((resolve, reject) => {
let settled = false;
let opened = false;
let terminalEvent;
const detachTerminalListeners = () => {
params.socket.off("error", onError);
params.socket.off("close", onClose);
return terminalEvent;
};
const finish = (error) => {
if (settled) return;
settled = true;
clearTimeout(timeout);
params.signal.removeEventListener("abort", onAbort);
params.socket.off("open", onOpen);
if (error) {
detachTerminalListeners();
reject(error);
} else resolve({ detachTerminalListeners });
};
const onOpen = () => {
opened = true;
finish();
};
const onError = (error) => {
if (opened) {
terminalEvent ??= {
kind: "error",
error
};
return;
}
finish(error);
};
const onClose = (code, reason) => {
if (opened) {
terminalEvent ??= {
kind: "close",
code: code ?? 1006,
reason: reason?.toString("utf8") ?? ""
};
return;
}
finish(/* @__PURE__ */ new Error("GPT-Live sideband closed during startup"));
};
const onAbort = () => finish(params.signal.reason instanceof Error ? params.signal.reason : /* @__PURE__ */ new Error("GPT-Live session stopped during startup"));
const timeout = setTimeout(() => finish(/* @__PURE__ */ new Error("GPT-Live sideband connection timed out")), SIDEBAND_CONNECT_TIMEOUT_MS);
timeout.unref?.();
params.socket.once("open", onOpen);
params.socket.on("error", onError);
params.socket.on("close", onClose);
params.signal.addEventListener("abort", onAbort, { once: true });
if (params.signal.aborted) onAbort();
});
}
async function connectOpenAIQuicksilverSideband(params, runtime) {
let lastError = /* @__PURE__ */ new Error("GPT-Live sideband connection failed");
for (let attempt = 0; attempt < SIDEBAND_CONNECT_ATTEMPTS; attempt += 1) {
if (params.signal.aborted) throw params.signal.reason;
const socket = params.createSocket(params.url, {
headers: openAIQuicksilverAuthHeaders(params.auth, params.requestIds, runtime, params.url),
maxPayload: SIDEBAND_MAX_PAYLOAD_BYTES
});
const bufferedFrames = [];
let bufferedBytes = 0;
const bufferFrame = (data, isBinary) => {
const frameBytes = rawDataByteLength(data);
if (bufferedFrames.length >= EARLY_FRAME_MAX || bufferedBytes + frameBytes > EARLY_FRAME_MAX_BYTES) {
socket.off("message", bufferFrame);
socket.close(1009, "sideband startup buffer exceeded");
return;
}
bufferedBytes += frameBytes;
bufferedFrames.push({
data,
isBinary
});
};
socket.on("message", bufferFrame);
try {
const openHandoff = await waitForSocketOpen({
socket,
signal: params.signal
});
if (params.signal.aborted) {
socket.off("message", bufferFrame);
openHandoff.detachTerminalListeners();
socket.on("error", () => {});
socket.close(1e3, "sideband startup stopped");
throw params.signal.reason;
}
return {
socket,
bufferedFrames,
detachBuffer: () => {
socket.off("message", bufferFrame);
return openHandoff.detachTerminalListeners();
}
};
} catch (error) {
lastError = error;
socket.off("message", bufferFrame);
socket.on("error", () => {});
try {
socket.close(1e3, "retrying sideband");
} catch {}
if (params.signal.aborted) throw params.signal.reason;
if (attempt + 1 < SIDEBAND_CONNECT_ATTEMPTS) await sleepWithAbort(SIDEBAND_RETRY_BASE_MS * 2 ** attempt, params.signal, { ref: false }).catch(() => {
const reason = params.signal.reason;
throw reason instanceof Error ? reason : new Error(reason === void 0 ? "GPT-Live session stopped" : String(reason), { cause: reason });
});
}
}
throw lastError;
}
/** Default transport loading belongs to live connection admission, not cold catalogs. */
async function loadOpenAIQuicksilverMediaSocketFactory(signal) {
return (await waitForOpenAIQuicksilverConnectStep(import("./extensions/openai/realtime-quicksilver-socket.js"), signal)).OpenAIQuicksilverWorkerSocket.create;
}
function openAIQuicksilverConnectAbortError(signal) {
return signal.reason instanceof Error ? signal.reason : new Error("GPT-Live gateway relay startup stopped", { cause: signal.reason });
}
function waitForOpenAIQuicksilverConnectStep(promise, signal) {
if (signal.aborted) return Promise.reject(openAIQuicksilverConnectAbortError(signal));
return new Promise((resolve, reject) => {
const onAbort = () => {
signal.removeEventListener("abort", onAbort);
reject(openAIQuicksilverConnectAbortError(signal));
};
signal.addEventListener("abort", onAbort, { once: true });
promise.then((value) => {
signal.removeEventListener("abort", onAbort);
resolve(value);
}, (error) => {
signal.removeEventListener("abort", onAbort);
reject(toErrorObject(error, "OpenAI GPT-Live gateway relay failed"));
});
});
}
//#endregion
export { waitForOpenAIQuicksilverConnectStep as i, loadOpenAIQuicksilverMediaSocketFactory as n, openAIQuicksilverConnectAbortError as r, connectOpenAIQuicksilverSideband as t };