import { fetchEventSource } from "@microsoft/fetch-event-source"; import type { CredentialGetter } from "@/api/AxiosClient"; import { getRuntimeApiKey, runsApiBaseUrl } from "@/util/env"; export type SseJsonPayload = Record; type SseClient = { post: (path: string, body: unknown) => Promise; }; export async function fetchJsonSse( input: RequestInfo | URL, init: RequestInit, ): Promise { const controller = new AbortController(); try { const parsedPayload = await new Promise((resolve, reject) => { fetchEventSource(input instanceof URL ? input.toString() : input, { method: init.method, headers: init.headers as Record, body: init.body, signal: controller.signal, onmessage: (event) => { if (!event.data || !event.data.trim()) { return; } try { const payload = JSON.parse(event.data) as T; resolve(payload); } catch (error) { reject(error); } }, onerror: (error) => { reject(error); }, onopen: async (response) => { if (!response.ok) { const errorText = await response.text(); reject(new Error(errorText || "Failed to send request.")); } }, }).catch(reject); }); return parsedPayload; } finally { controller.abort(); } } export async function getSseClient( credentialGetter: CredentialGetter | null, ): Promise { const requestHeaders: Record = { Accept: "text/event-stream", "Content-Type": "application/json", "x-user-agent": "skyvern-ui", }; let authToken: string | null = null; if (credentialGetter) { authToken = await credentialGetter(); } if (authToken) { requestHeaders.Authorization = `Bearer ${authToken}`; } else { const apiKey = getRuntimeApiKey(); if (apiKey) { requestHeaders["X-API-Key"] = apiKey; } } return { post: (path: string, body: unknown) => { return fetchJsonSse( `${runsApiBaseUrl.replace(/\/$/, "")}/${path.replace(/^\//, "")}`, { method: "POST", headers: requestHeaders, body: JSON.stringify(body), }, ); }, }; }