diff --git a/bin/oh-my-opencode.js b/bin/oh-my-opencode.js index 75b5794ce..0e644afc2 100755 --- a/bin/oh-my-opencode.js +++ b/bin/oh-my-opencode.js @@ -5,7 +5,12 @@ import { spawnSync } from "node:child_process"; import { readFileSync } from "node:fs"; import { createRequire } from "node:module"; -import { getPlatformPackageCandidates, getBinaryPath } from "./platform.js"; +import { basename } from "node:path"; +import { + getPlatformPackageCandidates, + getBinaryPath, + resolvePlatformPackageBaseName, +} from "./platform.js"; const require = createRequire(import.meta.url); @@ -74,12 +79,29 @@ function getSignalExitCode(signal) { function getPackageBaseName() { try { const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")); - return packageJson.name || "oh-my-opencode"; + return resolvePlatformPackageBaseName(packageJson.name || "oh-my-opencode"); } catch { return "oh-my-opencode"; } } +/** + * Determine which bin name the user invoked us with (oh-my-opencode, oh-my-openagent, omo, lazycodex). + * Propagated to the compiled CLI binary via OMO_INVOCATION_NAME so it can route accordingly + * (e.g. `lazycodex` defaults to the Codex install flow). + * @returns {string} + */ +function getInvocationName() { + if (process.env.OMO_INVOCATION_NAME) { + return process.env.OMO_INVOCATION_NAME; + } + const argv1 = process.argv[1] ?? ""; + if (!argv1) { + return "oh-my-opencode"; + } + return basename(argv1, ".js").replace(/\.exe$/, ""); +} + function main() { const { platform, arch } = process; const libcFamily = getLibcFamily(); @@ -119,11 +141,18 @@ function main() { process.exit(1); } + const invocationName = getInvocationName(); + const childEnv = { + ...process.env, + OMO_INVOCATION_NAME: invocationName, + }; + for (let index = 0; index < resolvedBinaries.length; index += 1) { const currentBinary = resolvedBinaries[index]; const hasFallback = index < resolvedBinaries.length - 1; const result = spawnSync(currentBinary.binPath, process.argv.slice(2), { stdio: "inherit", + env: childEnv, }); if (result.error) { diff --git a/bin/platform.d.ts b/bin/platform.d.ts index ed3987957..f9375b7c1 100644 --- a/bin/platform.d.ts +++ b/bin/platform.d.ts @@ -2,6 +2,7 @@ export declare function getPlatformPackage(options: { platform: string; arch: string; libcFamily?: string | null; + packageBaseName?: string; }): string; export declare function getPlatformPackageCandidates(options: { @@ -9,6 +10,9 @@ export declare function getPlatformPackageCandidates(options: { arch: string; libcFamily?: string | null; preferBaseline?: boolean; + packageBaseName?: string; }): string[]; export declare function getBinaryPath(pkg: string, platform: string): string; + +export declare function resolvePlatformPackageBaseName(wrapperPackageName: string): string; diff --git a/bin/platform.js b/bin/platform.js index 5790cf3dc..0ed616615 100644 --- a/bin/platform.js +++ b/bin/platform.js @@ -1,6 +1,20 @@ // bin/platform.js // Shared platform detection module - used by wrapper and postinstall +const PLATFORM_PACKAGE_BASE_BY_WRAPPER_NAME = { + lazycodex: "oh-my-opencode", +}; + +/** + * Resolve platform package base from a wrapper package name. + * Wrapper aliases can intentionally reuse an existing platform package family. + * @param {string} wrapperPackageName + * @returns {string} + */ +export function resolvePlatformPackageBaseName(wrapperPackageName) { + return PLATFORM_PACKAGE_BASE_BY_WRAPPER_NAME[wrapperPackageName] ?? wrapperPackageName; +} + /** * Get the platform-specific package name * @param {{ platform: string, arch: string, libcFamily?: string | null, packageBaseName?: string }} options diff --git a/bin/platform.test.ts b/bin/platform.test.ts index 0d21f3dd4..49eba4d5d 100644 --- a/bin/platform.test.ts +++ b/bin/platform.test.ts @@ -1,6 +1,46 @@ // bin/platform.test.ts import { describe, expect, test } from "bun:test"; -import { getBinaryPath, getPlatformPackage, getPlatformPackageCandidates } from "./platform.js"; +import { + getBinaryPath, + getPlatformPackage, + getPlatformPackageCandidates, + resolvePlatformPackageBaseName, +} from "./platform.js"; + +describe("resolvePlatformPackageBaseName", () => { + test("maps lazycodex wrapper to oh-my-opencode platform package family", () => { + // #given + const wrapperPackageName = "lazycodex"; + + // #when + const resolvedPlatformBase = resolvePlatformPackageBaseName(wrapperPackageName); + + // #then + expect(resolvedPlatformBase).toBe("oh-my-opencode"); + }); + + test("keeps oh-my-opencode wrapper mapped to oh-my-opencode platform package family", () => { + // #given + const wrapperPackageName = "oh-my-opencode"; + + // #when + const resolvedPlatformBase = resolvePlatformPackageBaseName(wrapperPackageName); + + // #then + expect(resolvedPlatformBase).toBe("oh-my-opencode"); + }); + + test("keeps oh-my-openagent wrapper mapped to oh-my-openagent platform package family", () => { + // #given + const wrapperPackageName = "oh-my-openagent"; + + // #when + const resolvedPlatformBase = resolvePlatformPackageBaseName(wrapperPackageName); + + // #then + expect(resolvedPlatformBase).toBe("oh-my-openagent"); + }); +}); describe("getPlatformPackage", () => { // #region Darwin platforms