Files
Kilo-Org_kilo/packages/kilo-vscode/scripts/prepare-cli-binary.mjs
T

121 lines
3.7 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.`
);
}
// 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);
}