// OrbitCosmo offscreen document — runs the local sentence-embedding model.
// Everything here is bundled in the extension; no network, no remote code.
// The model weights live in vendor/models/, the ONNX/WASM runtime in vendor/.

import { pipeline, env } from "../vendor/transformers.min.js";

// Force fully-local operation.
env.allowRemoteModels = false;
env.allowLocalModels = true;
// The model files are bundled and served from chrome-extension://, a scheme the
// browser Cache API rejects. Caching them buys nothing (they're already on disk
// in the extension), so disable it to avoid the noisy "scheme unsupported" warning.
env.useBrowserCache = false;
env.localModelPath = chrome.runtime.getURL("vendor/models/");
env.backends.onnx.wasm.wasmPaths = chrome.runtime.getURL("vendor/");
// Offscreen documents aren't cross-origin isolated, so SharedArrayBuffer
// (multi-threaded WASM) isn't available — run single-threaded.
env.backends.onnx.wasm.numThreads = 1;

let extractorPromise = null;
function getExtractor() {
  if (!extractorPromise) {
    extractorPromise = pipeline(
      "feature-extraction",
      "Xenova/all-MiniLM-L6-v2",
      { dtype: "q8" }
    );
  }
  return extractorPromise;
}

chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  if (msg?.type !== "orbit:embed" || msg.target !== "offscreen") return false;
  (async () => {
    try {
      const extractor = await getExtractor();
      const output = await extractor(msg.text, {
        pooling: "mean",
        normalize: true,
      });
      // 384-dim normalized vector.
      sendResponse({ ok: true, embedding: Array.from(output.data) });
    } catch (e) {
      sendResponse({ ok: false, error: String((e && e.message) || e) });
    }
  })();
  return true; // async response
});
