2026-01-15 10:33:07 -05:00
|
|
|
// postinstall.mjs
|
|
|
|
|
// Runs after npm install to verify platform binary is available
|
|
|
|
|
|
2026-03-28 15:24:18 +09:00
|
|
|
import { readFileSync } from "node:fs";
|
2026-01-15 10:33:07 -05:00
|
|
|
import { createRequire } from "node:module";
|
2026-05-30 19:12:15 +09:00
|
|
|
import {
|
|
|
|
|
getPlatformPackageCandidates,
|
|
|
|
|
getBinaryPath,
|
|
|
|
|
resolvePlatformPackageBaseName,
|
|
|
|
|
} from "./bin/platform.js";
|
2026-01-15 10:33:07 -05:00
|
|
|
|
|
|
|
|
const require = createRequire(import.meta.url);
|
|
|
|
|
|
2026-04-08 13:13:03 +09:00
|
|
|
const MIN_OPENCODE_VERSION = "1.4.0";
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Parse version string into numeric parts
|
|
|
|
|
* @param {string} version
|
|
|
|
|
* @returns {number[]}
|
|
|
|
|
*/
|
|
|
|
|
function parseVersion(version) {
|
|
|
|
|
return version
|
|
|
|
|
.replace(/^v/, "")
|
|
|
|
|
.split("-")[0]
|
|
|
|
|
.split(".")
|
|
|
|
|
.map((part) => Number.parseInt(part, 10) || 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Compare two version strings
|
|
|
|
|
* @param {string} current
|
|
|
|
|
* @param {string} minimum
|
|
|
|
|
* @returns {boolean} true if current >= minimum
|
|
|
|
|
*/
|
|
|
|
|
function compareVersions(current, minimum) {
|
|
|
|
|
const currentParts = parseVersion(current);
|
|
|
|
|
const minimumParts = parseVersion(minimum);
|
|
|
|
|
const length = Math.max(currentParts.length, minimumParts.length);
|
|
|
|
|
|
|
|
|
|
for (let index = 0; index < length; index++) {
|
|
|
|
|
const currentPart = currentParts[index] ?? 0;
|
|
|
|
|
const minimumPart = minimumParts[index] ?? 0;
|
|
|
|
|
if (currentPart > minimumPart) return true;
|
|
|
|
|
if (currentPart < minimumPart) return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Check if opencode version meets minimum requirement
|
|
|
|
|
* @returns {{ok: boolean, version: string | null}}
|
|
|
|
|
*/
|
|
|
|
|
function checkOpenCodeVersion() {
|
|
|
|
|
try {
|
|
|
|
|
const result = require("child_process").execSync("opencode --version", {
|
|
|
|
|
encoding: "utf-8",
|
|
|
|
|
stdio: ["pipe", "pipe", "ignore"],
|
|
|
|
|
});
|
|
|
|
|
const version = result.trim();
|
|
|
|
|
const ok = compareVersions(version, MIN_OPENCODE_VERSION);
|
|
|
|
|
return { ok, version };
|
|
|
|
|
} catch {
|
|
|
|
|
return { ok: true, version: null };
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-15 10:33:07 -05:00
|
|
|
/**
|
|
|
|
|
* Detect libc family on Linux
|
|
|
|
|
*/
|
|
|
|
|
function getLibcFamily() {
|
|
|
|
|
if (process.platform !== "linux") {
|
|
|
|
|
return undefined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const detectLibc = require("detect-libc");
|
|
|
|
|
return detectLibc.familySync();
|
|
|
|
|
} catch {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-27 18:29:36 +09:00
|
|
|
function getPackageBaseName() {
|
|
|
|
|
try {
|
2026-03-28 15:24:18 +09:00
|
|
|
const packageJson = JSON.parse(readFileSync(new URL("./package.json", import.meta.url), "utf8"));
|
2026-05-30 19:12:15 +09:00
|
|
|
return resolvePlatformPackageBaseName(packageJson.name || "oh-my-opencode");
|
2026-03-27 18:29:36 +09:00
|
|
|
} catch {
|
|
|
|
|
return "oh-my-opencode";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-15 10:33:07 -05:00
|
|
|
function main() {
|
|
|
|
|
const { platform, arch } = process;
|
|
|
|
|
const libcFamily = getLibcFamily();
|
2026-03-27 18:29:36 +09:00
|
|
|
const packageBaseName = getPackageBaseName();
|
2026-04-08 13:13:03 +09:00
|
|
|
|
|
|
|
|
// Check opencode version requirement
|
|
|
|
|
const versionCheck = checkOpenCodeVersion();
|
|
|
|
|
if (versionCheck.version && !versionCheck.ok) {
|
|
|
|
|
console.warn(`⚠ oh-my-opencode requires OpenCode >= ${MIN_OPENCODE_VERSION}`);
|
|
|
|
|
console.warn(` Detected: ${versionCheck.version}`);
|
|
|
|
|
console.warn(` Please update OpenCode to avoid compatibility issues.`);
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-15 10:33:07 -05:00
|
|
|
try {
|
2026-02-26 21:00:31 +09:00
|
|
|
const packageCandidates = getPlatformPackageCandidates({
|
|
|
|
|
platform,
|
|
|
|
|
arch,
|
|
|
|
|
libcFamily,
|
2026-03-27 18:29:36 +09:00
|
|
|
packageBaseName,
|
2026-02-26 21:00:31 +09:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const resolvedPackage = packageCandidates.find((pkg) => {
|
|
|
|
|
try {
|
|
|
|
|
require.resolve(getBinaryPath(pkg, platform));
|
|
|
|
|
return true;
|
|
|
|
|
} catch {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!resolvedPackage) {
|
|
|
|
|
throw new Error(
|
|
|
|
|
`No platform binary package installed. Tried: ${packageCandidates.join(", ")}`
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log(`✓ oh-my-opencode binary installed for ${platform}-${arch} (${resolvedPackage})`);
|
2026-01-15 10:33:07 -05:00
|
|
|
} catch (error) {
|
|
|
|
|
console.warn(`⚠ oh-my-opencode: ${error.message}`);
|
|
|
|
|
console.warn(` The CLI may not work on this platform.`);
|
|
|
|
|
// Don't fail installation - let user try anyway
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
main();
|