diff --git a/packages/coding-agent/src/config.ts b/packages/coding-agent/src/config.ts index 76e2429d..603e6d84 100644 --- a/packages/coding-agent/src/config.ts +++ b/packages/coding-agent/src/config.ts @@ -20,6 +20,65 @@ export const isBunBinary = /** Detect if Bun is the runtime (compiled binary or bun run) */ export const isBunRuntime = !!process.versions.bun; +// ============================================================================= +// Install Method Detection +// ============================================================================= + +export type InstallMethod = "bun-binary" | "npm" | "pnpm" | "yarn" | "bun" | "unknown"; + +let _cachedInstallMethod: InstallMethod | undefined; + +export function detectInstallMethod(): InstallMethod { + if (_cachedInstallMethod) return _cachedInstallMethod; + + if (isBunBinary) { + _cachedInstallMethod = "bun-binary"; + return _cachedInstallMethod; + } + + const resolvedPath = `${__dirname}\0${process.execPath || ""}`.toLowerCase(); + + if (resolvedPath.includes("/pnpm/") || resolvedPath.includes("/.pnpm/") || resolvedPath.includes("\\pnpm\\")) { + _cachedInstallMethod = "pnpm"; + } else if ( + resolvedPath.includes("/yarn/") || + resolvedPath.includes("/.yarn/") || + resolvedPath.includes("\\yarn\\") + ) { + _cachedInstallMethod = "yarn"; + } else if (isBunRuntime) { + _cachedInstallMethod = "bun"; + } else if ( + resolvedPath.includes("/npm/") || + resolvedPath.includes("/node_modules/") || + resolvedPath.includes("\\npm\\") + ) { + _cachedInstallMethod = "npm"; + } else { + _cachedInstallMethod = "unknown"; + } + + return _cachedInstallMethod; +} + +export function getUpdateInstruction(packageName: string): string { + const method = detectInstallMethod(); + switch (method) { + case "bun-binary": + return `Download from: https://github.com/badlogic/pi-mono/releases/latest`; + case "pnpm": + return `Run: pnpm install -g ${packageName}`; + case "yarn": + return `Run: yarn global add ${packageName}`; + case "bun": + return `Run: bun install -g ${packageName}`; + case "npm": + return `Run: npm install -g ${packageName}`; + default: + return `Run: npm install -g ${packageName}`; + } +} + // ============================================================================= // Package Asset Paths (shipped with executable) // ============================================================================= diff --git a/packages/coding-agent/src/modes/interactive/interactive-mode.ts b/packages/coding-agent/src/modes/interactive/interactive-mode.ts index 300a7516..705f9ba9 100644 --- a/packages/coding-agent/src/modes/interactive/interactive-mode.ts +++ b/packages/coding-agent/src/modes/interactive/interactive-mode.ts @@ -48,8 +48,7 @@ import { getAuthPath, getDebugLogPath, getShareViewerUrl, - isBunBinary, - isBunRuntime, + getUpdateInstruction, VERSION, } from "../../config.js"; import { type AgentSession, type AgentSessionEvent, parseSkillBlock } from "../../core/agent-session.js"; @@ -2754,9 +2753,7 @@ export class InteractiveMode { } showNewVersionNotification(newVersion: string): void { - const action = isBunBinary - ? `Download from: ${theme.fg("accent", "https://github.com/badlogic/pi-mono/releases/latest")}` - : `Run: ${theme.fg("accent", `${isBunRuntime ? "bun" : "npm"} install -g @mariozechner/pi-coding-agent`)}`; + const action = theme.fg("accent", getUpdateInstruction("@mariozechner/pi-coding-agent")); const updateInstruction = theme.fg("muted", `New version ${newVersion} is available. `) + action; const changelogUrl = theme.fg( "accent",