// Pithos for Theseus. The add-on runs the same control server as the web // console and desktop app, in Theseus's main process, and opens its UI in a // normal tab at a random loopback port. The first URL carries a one-time // secret that the server swaps for an HttpOnly cookie. // // Loaded with require() by the add-on host; core/ is ESM, hence import(). const path = require("node:path"); const { pathToFileURL } = require("node:url"); let pithos = null; let starting = null; module.exports = { activate(api) { // The pinned s3d release lands in the per-add-on data folder, never in the // add-on folder itself (that one is replaced on update). const dataDir = path.join(api.dataDir || path.join(api.folder, "..", "..", "extensions-data"), "pithos"); async function ensureServer() { if (pithos) return pithos; if (!starting) { starting = (async () => { const { createPithos } = await import(pathToFileURL(path.join(__dirname, "core", "server.js")).href); pithos = await createPithos({ host: "127.0.0.1", port: 0, hostName: "theseus", binDir: path.join(dataDir, "bin"), openExternal: (url) => api.openTab(url), }); api.log(`control server on ${pithos.url}`); return pithos; })().finally(() => { starting = null; }); } return starting; } api.onMessage("menu-select", async (payload) => { const id = payload && payload.id; if (id === "open") { const p = await ensureServer(); api.openTab(p.authUrl); } else if (id === "stop") { if (pithos) await pithos.daemon.stop(); } }); // The host has no quit hook for add-ons; without this an s3d we started // would outlive Theseus. process.on("exit", () => { try { pithos && pithos.daemon.child && pithos.daemon.child.kill(); } catch {} }); }, async deactivate() { if (pithos) { const p = pithos; pithos = null; await p.close(); } }, };