import { readdir, readFile, mkdir, writeFile } from 'node:fs/promises'; import path from 'node:path'; // Include dependency notices with the static distributable, without fetching // anything at build time. Some upstream Pi packages omit a LICENSE file; // their repository license is included in public/licenses/pi-LICENSE. export async function collectLicenses() { const notices = []; async function scan(root) { for (const entry of await readdir(root, { withFileTypes: true })) { if (!entry.isDirectory() || entry.name.startsWith('.')) continue; const directory = path.join(root, entry.name); if (entry.name.startsWith('@')) { await scan(directory); continue; } let pkg; try { pkg = JSON.parse(await readFile(path.join(directory, 'package.json'), 'utf8')); } catch { continue; } const texts = []; for (const file of await readdir(directory, { withFileTypes: true })) { if (file.isFile() && /^(licen[cs]e|copying|notice|thirdpartynotices)/i.test(file.name)) texts.push(await readFile(path.join(directory, file.name), 'utf8')); } notices.push(`${pkg.name}@${pkg.version} (${pkg.license ?? 'see upstream'})\n${texts.join('\n')}\n`); } } await scan('node_modules'); await mkdir('dist/licenses', { recursive: true }); await writeFile('dist/licenses/dependencies.txt', notices.sort().join('\n----------------------------------------\n\n')); await writeFile('dist/licenses/pi-components.json', await readFile('vendor/pi-coding-agent/provenance.json')); }