One parentless commit with only the files that the open seed tasks touch and the modules they import. The full squashed import (SPEC 8.6) is a later step: this tree is not the cutoff tree. T2T-StandIn-Source-Commit: 43f95b7333efe73aeaebf806023f17bffea27aba
69 lines
4.0 KiB
JavaScript
69 lines
4.0 KiB
JavaScript
// Elffuss Runtime · SDK de la caché compartida de modelos.
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Embebe un iframe oculto al BROKER (origen compartido de Elffuss) y le pide los
|
|
// modelos por postMessage. Como el broker vive en un subdominio de utopiaia.com
|
|
// —igual que todas las webs de Elffuss (mismo «site»)—, comparte UNA sola OPFS:
|
|
// el modelo se descarga UNA vez y se reutiliza en claw/translator/copilot/code…
|
|
// Si el broker no está disponible, el llamador cae a su OPFS local (model-store).
|
|
export const BROKER_URL = 'https://models.elffuss.utopiaia.com/';
|
|
|
|
let _iframe = null, _ready = null, _seq = 0, _url = BROKER_URL;
|
|
|
|
function ensure(brokerURL) {
|
|
if (_iframe) return _ready;
|
|
_url = brokerURL;
|
|
_iframe = document.createElement('iframe');
|
|
_iframe.src = brokerURL; _iframe.setAttribute('aria-hidden', 'true');
|
|
_iframe.style.cssText = 'position:absolute;width:0;height:0;border:0;left:-9999px;visibility:hidden';
|
|
_ready = new Promise((resolve, reject) => {
|
|
const to = setTimeout(() => reject(new Error('broker timeout')), 8000);
|
|
const h = e => { if (e.source === _iframe.contentWindow && e.data?.kind === 'elffuss-broker-ready') { clearTimeout(to); removeEventListener('message', h); resolve(); } };
|
|
addEventListener('message', h);
|
|
_iframe.addEventListener('error', () => { clearTimeout(to); reject(new Error('broker no cargó')); });
|
|
});
|
|
(document.body || document.documentElement).appendChild(_iframe);
|
|
return _ready;
|
|
}
|
|
const origin = () => new URL(_url).origin;
|
|
|
|
// Modelo como Blob (el navegador lo respalda en disco), desde la caché compartida.
|
|
// Descarga una vez para TODO Elffuss; el resto de webs lo leen sin red.
|
|
export async function getSharedModel(url, onProgress = () => {}, brokerURL = BROKER_URL) {
|
|
await ensure(brokerURL);
|
|
return new Promise((resolve, reject) => {
|
|
const id = ++_seq;
|
|
// Timeout por INACTIVIDAD: sin CUALQUIER mensaje del broker (progreso/file/
|
|
// error) en IDLE ms, la carga está colgada → rechazar para caer a OPFS local.
|
|
// No es un tope total (una descarga real tarda minutos): cada mensaje del
|
|
// broker reinicia el reloj, así que solo salta si el broker enmudece de verdad.
|
|
const IDLE = 30000;
|
|
let timer;
|
|
const arm = () => { clearTimeout(timer); timer = setTimeout(() => { removeEventListener('message', h); reject(new Error('broker sin respuesta (timeout de inactividad)')); }, IDLE); };
|
|
const done = fn => (...a) => { clearTimeout(timer); removeEventListener('message', h); fn(...a); };
|
|
const h = e => {
|
|
if (e.source !== _iframe.contentWindow || e.data?.id !== id) return;
|
|
const m = e.data;
|
|
arm(); // cualquier señal del broker reinicia el reloj
|
|
if (m.kind === 'progress') onProgress(m);
|
|
// El broker devuelve un File respaldado en disco (structured-clone por
|
|
// referencia): no copia los GB a RAM. Se lee con .stream() al subirlo a GPU.
|
|
else if (m.kind === 'file') done(resolve)(m.file);
|
|
else if (m.kind === 'error') done(reject)(new Error(m.message));
|
|
};
|
|
addEventListener('message', h);
|
|
arm();
|
|
_iframe.contentWindow.postMessage({ type: 'elffuss-model-get', id, url }, origin());
|
|
});
|
|
}
|
|
|
|
// ¿ya está en la caché compartida? (para la UI: «cargando desde caché, sin bajar»)
|
|
export async function isSharedCached(url, brokerURL = BROKER_URL) {
|
|
try { await ensure(brokerURL); } catch { return false; }
|
|
return new Promise(resolve => {
|
|
const id = ++_seq; const to = setTimeout(() => { removeEventListener('message', h); resolve(false); }, 4000);
|
|
const h = e => { if (e.source !== _iframe.contentWindow || e.data?.id !== id) return; if (e.data.kind === 'has') { clearTimeout(to); removeEventListener('message', h); resolve(!!e.data.cached); } };
|
|
addEventListener('message', h);
|
|
_iframe.contentWindow.postMessage({ type: 'elffuss-model-has', id, url }, origin());
|
|
});
|
|
}
|