import { existsSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { dirname, join, resolve } from "node:path"; import { build } from "esbuild"; const outputPath = join(tmpdir(), "pi-browser-smoke.js"); const errorLogPath = join(tmpdir(), "pi-browser-smoke-errors.log"); const generatedCatalogDataDir = join(process.cwd(), "packages/ai/src/providers/data"); // Fresh checkouts do not materialize provider JSON until npm run build. const generatedCatalogDataPlugin = { name: "generated-model-catalog", setup(build) { build.onResolve({ filter: /^\.\/data\/[^/]+\.json$/ }, (args) => { const path = resolve(dirname(args.importer), args.path); if (dirname(path) !== generatedCatalogDataDir || existsSync(path)) return; return { path, namespace: "empty-generated-model-catalog" }; }); build.onLoad({ filter: /.*/, namespace: "empty-generated-model-catalog" }, () => ({ contents: "{}", loader: "json", })); }, }; try { await build({ entryPoints: ["scripts/browser-smoke-entry.ts"], bundle: true, platform: "browser", format: "esm", logLevel: "silent", outfile: outputPath, plugins: [generatedCatalogDataPlugin], }); process.exit(0); } catch (error) { let detailedErrors = ""; if (error && typeof error === "object" && "errors" in error && Array.isArray(error.errors)) { detailedErrors = error.errors .map((entry) => { const location = entry.location ? `${entry.location.file}:${entry.location.line}:${entry.location.column}` : ""; return [location, entry.text].filter(Boolean).join(" "); }) .join("\n"); } const baseError = error instanceof Error ? (error.stack ?? error.message) : String(error); writeFileSync(errorLogPath, [detailedErrors, baseError].filter(Boolean).join("\n\n"), "utf-8"); console.error(`Browser smoke check failed. See ${errorLogPath}`); process.exit(1); }