77 lines
2.4 KiB
JavaScript
77 lines
2.4 KiB
JavaScript
#!/usr/bin/env node
|
|
import fs from 'node:fs'
|
|
import path from 'node:path'
|
|
|
|
import { DEFAULTS, USAGE, loadConfig } from '../src/config.mjs'
|
|
import { Orchestrator } from '../src/orchestrator.mjs'
|
|
import { startServer, runsBaseDir } from '../src/server.mjs'
|
|
import { installTerminalControls } from '../src/terminal.mjs'
|
|
import { printLog } from '../src/console.mjs'
|
|
import { loadRun } from '../src/state.mjs'
|
|
|
|
async function main() {
|
|
let config
|
|
try {
|
|
config = loadConfig(process.argv.slice(2))
|
|
} catch (err) {
|
|
process.stderr.write(`\n Error: ${err.message}\n\n${USAGE}\n`)
|
|
process.exit(2)
|
|
}
|
|
if (config.help) {
|
|
process.stdout.write(USAGE + '\n')
|
|
process.exit(0)
|
|
}
|
|
|
|
if (config.promptExtra && fs.existsSync(config.promptExtra)) {
|
|
config.promptExtra = fs.readFileSync(config.promptExtra, 'utf8')
|
|
}
|
|
|
|
const orchestrator = new Orchestrator(config)
|
|
orchestrator.state.on('log', (entry) => printLog(entry, { quiet: config.quiet }))
|
|
|
|
// --resume: reuse the previous run's session and stage progress.
|
|
if (config.resume) {
|
|
try {
|
|
const prev = loadRun(runsBaseDir(config), config.resume)
|
|
if (prev.sessionID) orchestrator.state.update({ sessionID: prev.sessionID })
|
|
const done = (prev.iterations || []).filter((it) => it.stageStatus === 'done' && it.stageId)
|
|
for (const it of done) orchestrator.completedStages.add(it.stageId)
|
|
const last = (prev.iterations || []).slice(-1)[0]
|
|
if (last?.percent != null) orchestrator.lastPercent = last.percent
|
|
orchestrator.log('system', `Resumed run ${config.resume} (session ${prev.sessionID || '—'}, last ${orchestrator.lastPercent}%).`)
|
|
} catch {
|
|
process.stderr.write(` Warning: could not load run "${config.resume}" — starting fresh.\n`)
|
|
}
|
|
}
|
|
|
|
const dashboard = await startServer(config, orchestrator)
|
|
const controls = installTerminalControls(orchestrator)
|
|
|
|
let exitCode = 0
|
|
const shutdown = async (code) => {
|
|
controls.dispose()
|
|
await dashboard.close().catch(() => {})
|
|
process.exit(code)
|
|
}
|
|
|
|
process.on('SIGINT', () => {
|
|
orchestrator.requestStop()
|
|
})
|
|
|
|
try {
|
|
const final = await orchestrator.run()
|
|
if (final.status === 'done-with-errors') exitCode = 1
|
|
} catch (err) {
|
|
process.stderr.write(`\n Fatal: ${err?.stack || err}\n`)
|
|
exitCode = 1
|
|
}
|
|
|
|
if (config.keepOpen) {
|
|
process.stdout.write(`\n Dashboard still open at ${dashboard.url} (Ctrl+C to exit)\n`)
|
|
return
|
|
}
|
|
await shutdown(exitCode)
|
|
}
|
|
|
|
main()
|