agent-ecosystem/scripts/dev-with-runtime.mjs

84 lines
2.5 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')
runOrExit('pnpm', ['run', 'dev:ui'], {
cwd: uiRepoRoot,
env: {
...process.env,
CLAUDE_CLI_PATH: runtimeCliPath,
},
})