Mike0021's picture
Enable browser HTTP commands with CORS-aware errors and bounded requests
39371ea verified
Raw
History Blame Contribute Delete
1.89 kB
import { resolve } from 'node:path';
import { readFileSync } from 'node:fs';
import { createHash } from 'node:crypto';
// Adapt host services at build time; never edit installed or vendored Pi code.
// Exact package pin + component checksums make this boundary reviewable.
export function piBrowser() {
const sourceRoot = resolve('vendor/pi-coding-agent');
const provenance = JSON.parse(readFileSync(resolve(sourceRoot, 'provenance.json'), 'utf8'));
for (const [file, expected] of Object.entries(provenance.files)) {
const actual = createHash('sha256').update(readFileSync(resolve(sourceRoot, file))).digest('hex');
if (actual !== expected) throw Error(`Vendored Pi component differs from its upstream checksum: ${file}`);
}
const host = resolve('src/pi/browser-host.mjs');
return {
name: 'pi-browser-host', enforce: 'pre',
resolveId(source, importer = '') {
if (source === '@earendil-works/pi-tui') return resolve('src/pi/entry.mjs');
if (importer.includes('/@earendil-works/pi-tui/')) {
if (source.endsWith('/terminal-image.js')) return resolve('src/pi/capabilities.mjs');
if (source === 'node:perf_hooks') return host;
}
if (importer.includes('/vendor/pi-coding-agent/') && source === '../theme/theme.js') return resolve('src/pi/theme.mjs');
},
transform(code, id) {
if (!id.includes('/@earendil-works/pi-tui/') || !id.split('?')[0].endsWith('.js')) return;
// Browser timer IDs don't have Node's event-loop keepalive methods.
// Scrolling, selection autoscroll and flash timers still run normally.
let adapted = code.replace(/\.unref\(\)/g, '.unref?.()');
if (/\b(?:process|Buffer)\./.test(code)) adapted = `import { browserProcess as process, Buffer } from ${JSON.stringify(host)};\n${adapted}`;
if (adapted !== code) return { code: adapted, map: null };
},
};
}