singularity-forge/packages/pi-coding-agent/scripts/copy-assets.cjs
Tom Boucher 4c98d3e708 fix: handle Windows non-ASCII paths in cpSync with copyFileSync fallback (#1181)
Node.js's cpSync fails on Windows when the path contains non-ASCII
characters (e.g. C:\Users\Görloff) due to the \\?\ extended-length path
prefix not handling Unicode correctly. This affects both the build
script (copy-assets.cjs) and the runtime resource sync (resource-loader.ts).

Added a try/catch fallback: when cpSync throws, fall back to a manual
recursive copy using copyFileSync which handles non-ASCII paths correctly.

Changed files:
- src/resource-loader.ts: syncResourceDir() catches cpSync failure and
  falls back to copyDirRecursive()
- packages/pi-coding-agent/scripts/copy-assets.cjs: all cpSync calls
  wrapped in safeCpSync() with the same fallback

Fixes #1178
2026-03-18 10:13:37 -06:00

55 lines
1.8 KiB
JavaScript

#!/usr/bin/env node
const { mkdirSync, cpSync, copyFileSync, readdirSync } = require('fs');
const { join } = require('path');
/**
* Recursive directory copy using copyFileSync — workaround for cpSync failures
* on Windows paths containing non-ASCII characters (#1178).
*/
function safeCpSync(src, dest, options) {
try {
cpSync(src, dest, options);
} catch {
if (options && options.recursive) {
copyDirRecursive(src, dest, options && options.filter);
} else {
copyFileSync(src, dest);
}
}
}
function copyDirRecursive(src, dest, filter) {
mkdirSync(dest, { recursive: true });
for (const entry of readdirSync(src, { withFileTypes: true })) {
const srcPath = join(src, entry.name);
const destPath = join(dest, entry.name);
if (filter && !filter(srcPath)) continue;
if (entry.isDirectory()) {
copyDirRecursive(srcPath, destPath, filter);
} else {
copyFileSync(srcPath, destPath);
}
}
}
// Theme assets
mkdirSync('dist/modes/interactive/theme', { recursive: true });
safeCpSync('src/modes/interactive/theme', 'dist/modes/interactive/theme', {
recursive: true,
filter: (s) => !s.endsWith('.ts'),
});
// Export HTML templates and vendor files
mkdirSync('dist/core/export-html/vendor', { recursive: true });
safeCpSync('src/core/export-html/template.html', 'dist/core/export-html/template.html');
safeCpSync('src/core/export-html/template.css', 'dist/core/export-html/template.css');
safeCpSync('src/core/export-html/template.js', 'dist/core/export-html/template.js');
safeCpSync('src/core/export-html/vendor', 'dist/core/export-html/vendor', {
recursive: true,
filter: (s) => !s.endsWith('.ts'),
});
// LSP defaults
mkdirSync('dist/core/lsp', { recursive: true });
safeCpSync('src/core/lsp/defaults.json', 'dist/core/lsp/defaults.json');
safeCpSync('src/core/lsp/lsp.md', 'dist/core/lsp/lsp.md');