Files
Kilo-Org_kilo/packages/kilo-vscode/scripts/prepare-cli-binary.mjs
T
Mark IJbema 845fc2a28a Update packages/kilo-vscode/scripts/prepare-cli-binary.mjs
Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com>
2026-02-10 12:42:38 +01:00

134 lines
3.9 KiB
JavaScript

import { existsSync, mkdirSync, readdirSync, statSync, copyFileSync, chmodSync } from "node:fs"
import path from "node:path"
import { fileURLToPath } from "node:url"
import { execSync } from "node:child_process"
/**
* Ensures the VS Code extension has a CLI binary at `packages/kilo-vscode/bin/kilo`.
*
* Strategy:
* 1) If `bin/kilo` already exists -> ok.
* 2) Else try to locate a prebuilt binary produced by `packages/opencode` build.
* 3) Else try to build it via `bun run build --single` in `packages/opencode`.
* 4) Copy the resulting binary into `packages/kilo-vscode/bin/kilo` and chmod +x.
*
* This script is intended to be run from `packages/kilo-vscode` as part of build/package.
*/
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const kiloVscodeDir = path.resolve(__dirname, "..")
const repoRootDir = path.resolve(kiloVscodeDir, "..")
const opencodeDir = path.resolve(repoRootDir, "opencode")
const targetBinDir = path.resolve(kiloVscodeDir, "bin")
const targetBinPath = path.resolve(targetBinDir, "kilo")
function log(msg) {
// Keep logs machine-grep friendly in CI
console.log(`[prepare-cli-binary] ${msg}`)
}
function findKiloBinaryInOpencodeDist() {
const distDir = path.resolve(opencodeDir, "dist")
if (!existsSync(distDir)) return null
// Expected: packages/opencode/dist/@kilocode/cli-<platform>/bin/kilo
// But keep it flexible: find any dist/**/bin/kilo
/** @type {string[]} */
const queue = [distDir]
while (queue.length) {
const dir = queue.pop()
if (!dir) continue
let entries
try {
entries = readdirSync(dir, { withFileTypes: true })
} catch {
continue
}
for (const e of entries) {
const p = path.join(dir, e.name)
if (e.isDirectory()) {
queue.push(p)
continue
}
if (e.isFile() && e.name === "kilo" && path.basename(path.dirname(p)) === "bin") {
return p
}
}
}
return null
}
function ensureBuiltBinary() {
const found = findKiloBinaryInOpencodeDist()
if (found) return found
log(
`No prebuilt binary found under ${path.relative(kiloVscodeDir, path.resolve(opencodeDir, "dist"))} - attempting build via bun.`,
)
try {
execSync("bun --version", { stdio: "ignore" })
} catch {
throw new Error(
`Bun is required to build the CLI binary, but was not found on PATH. ` +
`Install bun, or build the CLI separately in ${opencodeDir} and re-run.`,
)
}
// Ensure dependencies are installed before building.
log("Installing dependencies in opencode package...")
execSync("bun install --frozen-lockfile", {
cwd: opencodeDir,
stdio: "inherit",
env: process.env,
})
// Build using the opencode package script.
execSync("bun run build --single", {
cwd: opencodeDir,
stdio: "inherit",
env: process.env,
})
const built = findKiloBinaryInOpencodeDist()
if (!built) {
throw new Error(
`CLI build completed but no binary was found in ${path.resolve(opencodeDir, "dist")} (expected dist/**/bin/kilo).`,
)
}
return built
}
function main() {
if (existsSync(targetBinPath)) {
const st = statSync(targetBinPath)
log(
`CLI binary already present at ${path.relative(kiloVscodeDir, targetBinPath)} (${Math.round(st.size / 1024 / 1024)}MB).`,
)
return
}
if (!existsSync(opencodeDir)) {
throw new Error(`Expected opencode package at ${opencodeDir}, but it does not exist.`)
}
const sourceBinPath = ensureBuiltBinary()
mkdirSync(targetBinDir, { recursive: true })
copyFileSync(sourceBinPath, targetBinPath)
chmodSync(targetBinPath, 0o755)
log(
`Copied CLI binary from ${path.relative(repoRootDir, sourceBinPath)} -> ${path.relative(kiloVscodeDir, targetBinPath)}`,
)
}
try {
main()
} catch (err) {
console.error(`[prepare-cli-binary] ERROR: ${err instanceof Error ? err.message : String(err)}`)
process.exit(1)
}