#!/usr/bin/env node /** * Vendor the original webview verbatim into ./original. * * Source: the extracted ChatGPT.app/Contents/Resources/app.asar, i.e. * /webview * * Nothing is rewritten. The copy is byte-for-byte identical, which is what makes * the UI 100% the original rather than an approximation. * * Usage: * node host/vendor-original.mjs --from /tmp/codex-asar/webview * node host/vendor-original.mjs --from /path/to/webview --clean */ import fs from "node:fs"; import path from "node:path"; import crypto from "node:crypto"; import { fileURLToPath } from "node:url"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const projectRoot = path.resolve(__dirname, ".."); const args = process.argv.slice(2); const getArg = (name, fallback) => { const i = args.indexOf(name); return i >= 0 && args[i + 1] ? args[i + 1] : fallback; }; const from = path.resolve(getArg("--from", "/tmp/codex-asar/webview")); const to = path.resolve(projectRoot, getArg("--to", "original")); const clean = args.includes("--clean"); if (!fs.existsSync(path.join(from, "index.html"))) { console.error(`[vendor] not a webview directory: ${from}`); process.exit(1); } if (clean && fs.existsSync(to)) { console.log(`[vendor] removing ${to}`); fs.rmSync(to, { recursive: true, force: true }); } fs.mkdirSync(to, { recursive: true }); console.log(`[vendor] copying ${from} -> ${to}`); fs.cpSync(from, to, { recursive: true, force: true }); // Manifest (written outside ./original so the vendored tree stays untouched). function sha256(file) { return crypto.createHash("sha256").update(fs.readFileSync(file)).digest("hex"); } function countFiles(dir) { let n = 0; for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { n += entry.isDirectory() ? countFiles(path.join(dir, entry.name)) : 1; } return n; } const manifest = { source: from, vendoredAt: new Date().toISOString(), fileCount: countFiles(to), indexHtmlSha256: sha256(path.join(to, "index.html")), }; fs.writeFileSync( path.join(projectRoot, "host", "vendor-manifest.json"), JSON.stringify(manifest, null, 2), ); console.log(`[vendor] done — ${manifest.fileCount} files`); console.log(`[vendor] index.html sha256 ${manifest.indexHtmlSha256}`);