Download scripts/check-browser-smoke.mjs from SaylorTwift/pi: direct link, hf CLI and curl.
- Browser
- Download file 4.27 kB
-
https://huggingface.co/SaylorTwift/pi/resolve/main/scripts/check-browser-smoke.mjs
- Command line
-
hf download hf://SaylorTwift/pi/scripts/check-browser-smoke.mjs
-
curl -L -o check-browser-smoke.mjs https://huggingface.co/SaylorTwift/pi/resolve/main/scripts/check-browser-smoke.mjs
4.27 kB
| 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 agentTreeshakeOutputPath = join(tmpdir(), "pi-agent-treeshake-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 model data is hydrated. | |
| 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", | |
| })); | |
| }, | |
| }; | |
| function normalizePath(path) { | |
| return path.replaceAll("\\", "/"); | |
| } | |
| function findInput(inputs, suffix) { | |
| return Object.keys(inputs).find((input) => { | |
| const normalized = normalizePath(input); | |
| return normalized === suffix || normalized.endsWith(`/${suffix}`); | |
| }); | |
| } | |
| function includesNodePackage(inputs, packageName) { | |
| const marker = `node_modules/${packageName}/`; | |
| return Object.keys(inputs).some((input) => normalizePath(input).includes(marker)); | |
| } | |
| try { | |
| await build({ | |
| entryPoints: ["scripts/browser-smoke-entry.ts"], | |
| bundle: true, | |
| platform: "browser", | |
| format: "esm", | |
| logLevel: "silent", | |
| outfile: outputPath, | |
| plugins: [generatedCatalogDataPlugin], | |
| }); | |
| const agentTreeshakeBuild = await build({ | |
| entryPoints: ["scripts/agent-treeshake-smoke-entry.ts"], | |
| bundle: true, | |
| platform: "browser", | |
| format: "esm", | |
| logLevel: "silent", | |
| metafile: true, | |
| outfile: agentTreeshakeOutputPath, | |
| plugins: [generatedCatalogDataPlugin], | |
| write: false, | |
| }); | |
| const inputs = agentTreeshakeBuild.metafile.inputs; | |
| for (const forbiddenInput of [ | |
| "packages/ai/src/compat.ts", | |
| "packages/ai/src/models.generated.ts", | |
| "packages/ai/src/providers/all.ts", | |
| ]) { | |
| const includedInput = findInput(inputs, forbiddenInput); | |
| if (includedInput) { | |
| throw new Error(`Agent selective-provider bundle unexpectedly includes ${includedInput}`); | |
| } | |
| } | |
| const contributingInputs = new Set( | |
| Object.values(agentTreeshakeBuild.metafile.outputs).flatMap((output) => | |
| Object.entries(output.inputs) | |
| .filter(([, contribution]) => contribution.bytesInOutput > 0) | |
| .map(([input]) => input), | |
| ), | |
| ); | |
| const catalogInputs = Array.from(contributingInputs).filter((input) => | |
| normalizePath(input).includes("packages/ai/src/providers/data/"), | |
| ); | |
| if (catalogInputs.length !== 1 || !normalizePath(catalogInputs[0]).endsWith("/anthropic.json")) { | |
| throw new Error( | |
| `Agent selective-provider bundle catalogs: expected only anthropic.json, found ${catalogInputs.join(", ") || "none"}`, | |
| ); | |
| } | |
| const aiSdkPackages = [ | |
| "@anthropic-ai/sdk", | |
| "@aws-sdk/client-bedrock-runtime", | |
| "@google/genai", | |
| "@mistralai/mistralai", | |
| "openai", | |
| ]; | |
| const includedAiSdkPackages = aiSdkPackages.filter((packageName) => includesNodePackage(inputs, packageName)); | |
| if ( | |
| includedAiSdkPackages.length !== 1 || | |
| includedAiSdkPackages[0] !== "@anthropic-ai/sdk" | |
| ) { | |
| throw new Error( | |
| `Agent selective-provider bundle SDKs: expected only @anthropic-ai/sdk, found ${includedAiSdkPackages.join(", ") || "none"}`, | |
| ); | |
| } | |
| 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); | |
| } | |