// Agent-turn requests are held open by the backend for the whole turn // (POST /messages returns only after the agent finishes), and production p99 // is ~17 minutes. base44-mobile's Wix engine swizzles RCTNetworking and // replaces a request timeout of 0 (what React Native's fetch always sends) // with a hard 30s cap, so most sends died with WixFetchError. An explicit // non-zero XMLHttpRequest timeout is preserved by the engine, which is why // this transport exists instead of fetch. export const SUPERAGENT_REQUEST_TIMEOUT_MS = 30 * 60 * 1000; export interface XhrResponse { ok: boolean; status: number; json(): Promise; } export interface XhrFetchInit { method: string; headers?: Record; body?: string; timeoutMs?: number; } export function xhrFetch(url: string, init: XhrFetchInit): Promise { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open(init.method, url); xhr.timeout = init.timeoutMs ?? SUPERAGENT_REQUEST_TIMEOUT_MS; for (const [name, value] of Object.entries(init.headers ?? {})) { xhr.setRequestHeader(name, value); } xhr.onload = () => { resolve({ ok: xhr.status >= 200 && xhr.status < 300, status: xhr.status, json: () => Promise.resolve(JSON.parse(xhr.responseText)), }); }; xhr.onerror = (error) => { console.error('Superagent request failed', error); reject(error); }; xhr.ontimeout = () => reject(new Error('The request timed out. The agent may still be working — check the conversation again in a moment.')); xhr.send(init.body); }); }