#!/usr/bin/env bun import { $ } from "bun" import { join } from "node:path" import { existsSync, mkdirSync, rmSync, chmodSync } from "node:fs" import { copyKiloSandboxWorker, copySandboxResources, copyTreeSitterResources, } from "../src/services/cli-backend/cli-resources" import { ensureFfmpegForTarget } from "./ffmpeg-helper" const packageJsonPath = join(import.meta.dir, "..", "package.json") const packageJson = await Bun.file(packageJsonPath).json() const version = process.env.KILO_VERSION ? process.env.KILO_VERSION : packageJson.version const prerelease = process.env.KILO_PRE_RELEASE === "true" console.log(`Building VSCode extension version: ${version}${prerelease ? " (pre-release)" : ""}`) if (packageJson.version !== version) { console.log(`Updating package.json version from ${packageJson.version} to ${version}`) packageJson.version = version await Bun.write(packageJsonPath, JSON.stringify(packageJson, null, 2) + "\n") } const cliDistDir = process.env.CLI_DIST_DIR || join(import.meta.dir, "..", "..", "opencode", "dist") console.log(`Using CLI dist directory: ${cliDistDir}`) if (!existsSync(cliDistDir)) { throw new Error(`CLI dist directory not found: ${cliDistDir}`) } const targets = [ { target: "linux-x64", cliDir: "@kilocode/cli-linux-x64", binary: "kilo" }, { target: "linux-arm64", cliDir: "@kilocode/cli-linux-arm64", binary: "kilo" }, { target: "alpine-x64", cliDir: "@kilocode/cli-linux-x64-musl", binary: "kilo" }, { target: "alpine-arm64", cliDir: "@kilocode/cli-linux-arm64-musl", binary: "kilo" }, { target: "darwin-x64", cliDir: "@kilocode/cli-darwin-x64", binary: "kilo" }, { target: "darwin-arm64", cliDir: "@kilocode/cli-darwin-arm64", binary: "kilo" }, { target: "win32-x64", cliDir: "@kilocode/cli-windows-x64", binary: "kilo.exe" }, { target: "win32-arm64", cliDir: "@kilocode/cli-windows-arm64", binary: "kilo.exe" }, ] const binDir = join(import.meta.dir, "..", "bin") const distDir = join(import.meta.dir, "..", "dist") const outDir = join(import.meta.dir, "..", "out") console.log("\n๐Ÿงน Cleaning up directories...") for (const dir of [binDir, distDir, outDir]) { if (existsSync(dir)) { rmSync(dir, { recursive: true, force: true }) console.log(` โœ“ Cleaned ${dir}`) } } mkdirSync(outDir, { recursive: true }) mkdirSync(distDir, { recursive: true }) console.log("\n๐Ÿ”„ Rebuilding SDK types (ensures dist/ is in sync with server API)...") await $`bun run --cwd ${join(import.meta.dir, "..", "..", "sdk", "js")} build` console.log("\n๐Ÿ“ฆ Compiling extension...") await $`bun run check-types` await $`bun run lint` await $`node ${join(import.meta.dir, "..", "esbuild.js")} --production` for (const config of targets) { console.log(`\n๐ŸŽฏ Processing target: ${config.target}`) if (existsSync(binDir)) { rmSync(binDir, { recursive: true, force: true }) } mkdirSync(binDir, { recursive: true }) const sourceBinary = join(cliDistDir, config.cliDir, "bin", config.binary) const targetBinary = join(binDir, config.binary) if (!existsSync(sourceBinary)) { throw new Error(`CLI binary not found at ${sourceBinary}`) } console.log(` ๐Ÿ“ฅ Copying binary from ${config.cliDir}/bin/${config.binary}...`) await $`cp ${sourceBinary} ${targetBinary}` await copyTreeSitterResources(sourceBinary, targetBinary) await copySandboxResources(sourceBinary, targetBinary) await copyKiloSandboxWorker(sourceBinary, targetBinary) if (config.binary !== "kilo.exe") { chmodSync(targetBinary, 0o755) } console.log(` โœ… Binary ready at ${targetBinary}`) console.log("Adding bundled FFmpeg helper...") await ensureFfmpegForTarget(config.target, binDir) console.log(` ๐Ÿ“ฆ Packaging .vsix for ${config.target}${prerelease ? " (pre-release)" : ""}...`) const vsixPath = join(outDir, `kilo-vscode-${config.target}.vsix`) const args = ["--no-dependencies", "--skip-license", "--target", config.target, "-o", vsixPath] if (prerelease) args.push("--pre-release") await $`vsce package ${args}`.env({ ...process.env, npm_config_ignore_scripts: "true", }) console.log(` โœ… Created ${vsixPath}`) } console.log("\nโœจ All VSIX packages built successfully!")