UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

107 lines • 5.1 kB
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. ========= // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ========= Copyright 2026 @ Strukto.AI All Rights Reserved. ========= var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) { if (typeof path === "string" && /^\.\.?\//.test(path)) { return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) { return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js"); }); } return path; }; import { resolveHome } from "../../config.js"; import { PyodideUnavailableError } from "./errors.js"; import { sealNetwork } from "./network.js"; const noopIo = () => undefined; const PYODIDE_CDN_VERSION = '314.0.5'; const PYODIDE_CDN_URL = `https://cdn.jsdelivr.net/pyodide/v${PYODIDE_CDN_VERSION}/full/`; const PYODIDE_HOME_ENV = 'MIRAGE_PYODIDE_HOME'; /** Whether this runs under Node, where pyodide loads from the installed package. */ export function isNode() { const proc = globalThis.process; return typeof proc?.versions?.node === 'string'; } async function resolveNodeIndexURL() { if (!isNode()) return null; try { const nodeModule = await import('node:module'); const nodePath = await import('node:path'); const require = nodeModule.createRequire(import.meta.url); const entry = require.resolve('pyodide'); const dir = nodePath.dirname(entry); return `${dir}/`; } catch { return null; } } export async function loadPyodideRuntime( /** Distribution knobs a deployment can point at its own prebuilt assets. */ options = {}) { const home = resolveHome(options, PYODIDE_HOME_ENV) ?? (await resolveNodeIndexURL()) ?? (isNode() ? null : PYODIDE_CDN_URL); // A browser worker starts from a blob (worker/client.ts), where neither // a bare specifier nor a relative path resolves, so it loads pyodide's // loader and every other asset from the distribution's absolute URL, a // path read from the page's origin. The page loads from the same URL, so // the two always run one release and the page needs no pyodide package. const origin = isNode() ? undefined : globalThis.location?.origin; const resolved = home === null || origin === undefined ? home : new URL(home, `${origin}/`).href; const indexURL = resolved === null || resolved.endsWith('/') ? resolved : `${resolved}/`; const distribution = origin === undefined ? null : indexURL; let mod; try { mod = (await (distribution === null ? import('pyodide') : import(__rewriteRelativeImportExtension(/* @vite-ignore */ `${distribution}pyodide.mjs`)))); } catch (err) { throw new PyodideUnavailableError(distribution === null ? 'python3 requires the optional `pyodide` peer dependency. Install it with `npm i pyodide`.' : `cannot load pyodide from ${distribution}: ${err instanceof Error ? err.message : String(err)}`, { cause: err }); } // A null-prototype jsglobals empties the guest's `js` module: `import // js` still resolves, but js.process, js.fetch and the rest of the host // globalThis are not attributes of it. pyodide's own internals capture // the globals they need at load time, not through this object. const opts = { stdout: noopIo, stderr: noopIo, jsglobals: Object.create(null), }; if (options.packageBaseUrl !== undefined) opts.packageBaseUrl = options.packageBaseUrl; if (options.lockFileURL !== undefined) opts.lockFileURL = options.lockFileURL; if (options.packages !== undefined && options.packages.length > 0) { opts.packages = [...options.packages]; } if (indexURL !== null) opts.indexURL = indexURL; try { const runtime = (await mod.loadPyodide(opts)); // Emscripten's SOCKFS would carry a guest socket over a WebSocket to // the host; sealNetwork makes it refuse instead. A build it cannot // seal reports pyodide unavailable, like any failed initialization. sealNetwork(runtime._module ?? {}, runtime.FS, runtime.ERRNO_CODES); return runtime; } catch (err) { throw new PyodideUnavailableError(`python3: failed to initialize pyodide runtime: ${err instanceof Error ? err.message : String(err)}`, { cause: err }); } } //# sourceMappingURL=loader.js.map