kilo-loop/bin/kilocode-loop.mjs
2026-09-13 13:46:28 +03:00

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()