moving
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled

This commit is contained in:
Oleg Maslov
2026-09-02 10:10:29 +02:00
commit 0c3e2ead3b
3841 changed files with 970576 additions and 0 deletions

View File

@@ -0,0 +1,98 @@
#!/usr/bin/env node
/**
* P4/D12 preflight — fail a Tauri build LOUDLY when the arch-parameterized
* sidecar resources are missing.
*
* The tauri.conf.json beforeBuildCommand regenerates ONLY the sidecar JS
* bundle (build-sidecar.mjs — arch-independent, safe to run arch-blind). The
* Node runtime and native modules are arch-PARAMETERIZED (TARGET_ARCH) and
* must be staged by the explicit npm scripts / CI steps that set it — the
* hook must never regenerate them (an arch-blind re-run on a cross-arch
* matrix leg clobbers the staged artifacts; P4 review HIGH). But the bundle
* resources glob (`resources/*`) silently tolerates ABSENT files — a raw
* `npx tauri build` on a fresh clone would package a binary with no Node
* runtime at all. This check turns that silent miss into a hard stop.
*/
import fs from 'node:fs';
import path from 'node:path';
import { execFileSync } from 'node:child_process';
import { fileURLToPath } from 'node:url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const root = path.resolve(__dirname, '..');
const resourcesDir = path.join(root, 'app', 'src-tauri', 'resources');
const missing = [];
const nodeBinary = process.platform === 'win32' ? 'node.exe' : 'node';
const nodePath = path.join(resourcesDir, nodeBinary);
if (!fs.existsSync(nodePath)) {
missing.push(`resources/${nodeBinary} (run: node scripts/bundle-node.mjs)`);
} else {
try {
const bundledAbi = execFileSync(nodePath, ['-p', 'process.versions.modules'], {
encoding: 'utf-8',
stdio: ['ignore', 'pipe', 'pipe'],
}).trim();
const currentAbi = process.versions.modules;
if (bundledAbi !== currentAbi) {
missing.push(
`resources/${nodeBinary} ABI ${bundledAbi} does not match current Node ABI ${currentAbi} ` +
'(run: node scripts/bundle-node.mjs with the same Node used for npm install/stage-sidecar-deps)',
);
}
} catch (err) {
missing.push(`resources/${nodeBinary} is not executable (${err.message})`);
}
}
const nativeDir = path.join(resourcesDir, 'native');
const nativeEntries = fs.existsSync(nativeDir)
? fs.readdirSync(nativeDir).filter((e) => e !== '.gitkeep' && e !== 'onnxruntime')
: [];
if (nativeEntries.length === 0) {
missing.push('resources/native/* (run: node scripts/bundle-native-deps.mjs)');
}
// Staged production node_modules for the esbuild-externalized packages
// (better-sqlite3, @fastify/static, mammoth, …). The bundled service.js
// `require()`s these by bare name and resolves them via NODE_PATH=resources/
// node_modules (service.rs). Like the native deps above, staging is done by the
// npm scripts / CI (stage-sidecar-deps.mjs), NOT the arch-blind beforeBuildCommand
// hook — so a raw `npx tauri build` that skips those would package a sidecar that
// dies with MODULE_NOT_FOUND on first boot. Probe a canonical external.
const stagedDepsDir = path.join(resourcesDir, 'node_modules');
if (!fs.existsSync(path.join(stagedDepsDir, 'better-sqlite3', 'package.json'))) {
missing.push('resources/node_modules/* (run: node scripts/stage-sidecar-deps.mjs)');
}
// External agents and hook management run directly from this staged payload;
// none of these packages are available from npm in a packaged installation.
const hookRuntimeEntries = [
'@waggle/hive-mind-cli/dist/index.js',
'@waggle/hive-mind-hooks-claude-code/dist/bin/claude-code-hooks-cli.js',
'@waggle/hive-mind-hooks-claude-desktop/dist/bin/claude-desktop-hooks.js',
'@waggle/hive-mind-hooks-codex/dist/bin/codex-hooks.js',
'@waggle/hive-mind-hooks-codex-desktop/dist/bin/codex-desktop-hooks.js',
'@waggle/hive-mind-hooks-cursor/dist/bin/cursor-hooks.js',
'@waggle/hive-mind-hooks-hermes/dist/bin/hermes-hooks.js',
'@waggle/hive-mind-hooks-openclaw/dist/bin/openclaw-hooks.js',
];
for (const entry of hookRuntimeEntries) {
if (!fs.existsSync(path.join(stagedDepsDir, ...entry.split('/')))) {
missing.push(`resources/node_modules/${entry} (run: node scripts/stage-sidecar-deps.mjs)`);
}
}
if (missing.length > 0) {
console.error('[check-sidecar-resources] FATAL — sidecar runtime artifacts missing:');
for (const m of missing) console.error(` - ${m}`);
console.error(
'[check-sidecar-resources] Stage them with the bundle scripts (set TARGET_ARCH for\n' +
'cross-arch builds) or use the npm tauri:build* scripts / CI, which run them for you.',
);
process.exit(1);
}
console.log('[check-sidecar-resources] OK — Node runtime + native deps + staged node_modules present');