91 lines
3 KiB
JavaScript
91 lines
3 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import { spawnSync } from 'node:child_process';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
function runOrExit(cmd, args, options = {}) {
|
|
const result = spawnSync(cmd, args, {
|
|
stdio: 'inherit',
|
|
...options,
|
|
});
|
|
|
|
if (result.error) {
|
|
console.error(`Failed to run ${cmd}: ${result.error.message}`);
|
|
process.exit(1);
|
|
}
|
|
|
|
if (result.status !== 0) {
|
|
process.exit(result.status ?? 1);
|
|
}
|
|
}
|
|
|
|
function readPackageManagerCommand(repoRoot) {
|
|
const packageJsonPath = path.join(repoRoot, 'package.json');
|
|
const rawPackageJson = fs.readFileSync(packageJsonPath, 'utf8');
|
|
const packageJson = JSON.parse(rawPackageJson);
|
|
const rawPackageManager = packageJson.packageManager;
|
|
|
|
if (typeof rawPackageManager !== 'string' || rawPackageManager.trim().length === 0) {
|
|
return 'pnpm';
|
|
}
|
|
|
|
const [packageManagerName] = rawPackageManager.trim().split('@', 1);
|
|
if (!packageManagerName) {
|
|
return 'pnpm';
|
|
}
|
|
|
|
return packageManagerName;
|
|
}
|
|
|
|
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
const uiRepoRoot = path.resolve(scriptDir, '..');
|
|
// Keep the dev runtime target explicit. This workspace can contain multiple
|
|
// sibling repos with the same package name, so auto-discovery is ambiguous and
|
|
// can silently point the UI at the wrong runtime after branch switches.
|
|
const runtimeRepoRoot = process.env.CLAUDE_DEV_RUNTIME_ROOT?.trim();
|
|
|
|
if (!runtimeRepoRoot) {
|
|
console.error(
|
|
'CLAUDE_DEV_RUNTIME_ROOT is required for pnpm dev. ' +
|
|
'Point it at the runtime repo root you want the UI to use in dev.'
|
|
);
|
|
process.exit(1);
|
|
}
|
|
|
|
const runtimePackageJsonPath = path.join(runtimeRepoRoot, 'package.json');
|
|
if (!fs.existsSync(runtimePackageJsonPath)) {
|
|
console.error(`CLAUDE_DEV_RUNTIME_ROOT does not look like a repo root: ${runtimeRepoRoot}`);
|
|
process.exit(1);
|
|
}
|
|
|
|
const runtimePackageManager = readPackageManagerCommand(runtimeRepoRoot);
|
|
|
|
if (process.argv.includes('--print-runtime-path')) {
|
|
process.stdout.write(`${runtimeRepoRoot}\n`);
|
|
process.exit(0);
|
|
}
|
|
|
|
// Respect the runtime repo's own package manager. The UI repo uses pnpm, but
|
|
// the runtime may legitimately be a Bun workspace, and forcing pnpm there can
|
|
// fail before the build even starts.
|
|
runOrExit(runtimePackageManager, ['run', 'build:dev'], { cwd: runtimeRepoRoot });
|
|
|
|
const runtimeCliPath = path.join(runtimeRepoRoot, 'cli-dev');
|
|
const uiEnv = {
|
|
...process.env,
|
|
// Dev-only agent_teams_orchestrator runtime override. Keep it separate from
|
|
// the generic CLAUDE_CLI_PATH override so switching the app into Claude CLI
|
|
// mode still resolves the real official binary instead of this local
|
|
// cli-dev shim.
|
|
CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH: runtimeCliPath,
|
|
};
|
|
// If the parent shell exported a stale generic override, do not let it leak
|
|
// into the Electron main process. Claude mode must resolve the real binary.
|
|
delete uiEnv.CLAUDE_CLI_PATH;
|
|
|
|
runOrExit('pnpm', ['run', 'dev:ui'], {
|
|
cwd: uiRepoRoot,
|
|
env: uiEnv,
|
|
});
|