From e4c01e7ca24fad23d7db616f0e0084fd7a0531ec Mon Sep 17 00:00:00 2001 From: kumarabhirup Date: Sun, 22 Feb 2026 00:38:25 -0800 Subject: [PATCH] update: always install canonical ironclaw package name --- src/cli/nodes-camera.test.ts | 13 ++++++++++--- src/cli/update-cli/shared.ts | 13 ++++++------- src/cli/update-cli/update-command.ts | 8 +++----- src/infra/update-runner.test.ts | 12 ++++++------ src/infra/update-runner.ts | 7 ++++--- 5 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/cli/nodes-camera.test.ts b/src/cli/nodes-camera.test.ts index b553244d6b2..5cb0219faa8 100644 --- a/src/cli/nodes-camera.test.ts +++ b/src/cli/nodes-camera.test.ts @@ -1,7 +1,7 @@ import * as fs from "node:fs/promises"; import * as os from "node:os"; import * as path from "node:path"; -import { afterEach, describe, expect, it, vi } from "vitest"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { cameraTempPath, parseCameraClipPayload, @@ -26,6 +26,12 @@ async function withCameraTempDir(run: (dir: string) => Promise): Promise { + const originalArgv = [...process.argv]; + + beforeEach(() => { + process.argv = ["node", "ironclaw"]; + }); + function stubFetchResponse(response: Response) { vi.stubGlobal( "fetch", @@ -96,7 +102,7 @@ describe("nodes camera helpers", () => { tmpDir: dir, id: "clip1", }); - expect(out).toBe(path.join(dir, "openclaw-camera-clip-front-clip1.mp4")); + expect(out).toBe(path.join(dir, "ironclaw-camera-clip-front-clip1.mp4")); await expect(fs.readFile(out, "utf8")).resolves.toBe("hi"); }); }); @@ -115,7 +121,7 @@ describe("nodes camera helpers", () => { tmpDir: dir, id: "clip2", }); - expect(out).toBe(path.join(dir, "openclaw-camera-clip-back-clip2.mp4")); + expect(out).toBe(path.join(dir, "ironclaw-camera-clip-back-clip2.mp4")); await expect(fs.readFile(out, "utf8")).resolves.toBe("url-clip"); }); }); @@ -129,6 +135,7 @@ describe("nodes camera helpers", () => { }); afterEach(() => { + process.argv = [...originalArgv]; vi.unstubAllGlobals(); }); diff --git a/src/cli/update-cli/shared.ts b/src/cli/update-cli/shared.ts index 2cf53e201f9..e5b046519da 100644 --- a/src/cli/update-cli/shared.ts +++ b/src/cli/update-cli/shared.ts @@ -53,8 +53,8 @@ export function parseTimeoutMsOrExit(timeout?: string): number | undefined | nul const OPENCLAW_REPO_URL = "https://github.com/openclaw/openclaw.git"; const MAX_LOG_CHARS = 8000; -export const DEFAULT_PACKAGE_NAME = "openclaw"; -const CORE_PACKAGE_NAMES = new Set([DEFAULT_PACKAGE_NAME]); +export const DEFAULT_PACKAGE_NAME = "ironclaw"; +const CORE_PACKAGE_NAMES = new Set([DEFAULT_PACKAGE_NAME, "openclaw"]); export function normalizeTag(value?: string | null): string | null { if (!value) { @@ -64,11 +64,10 @@ export function normalizeTag(value?: string | null): string | null { if (!trimmed) { return null; } - if (trimmed.startsWith("openclaw@")) { - return trimmed.slice("openclaw@".length); - } - if (trimmed.startsWith(`${DEFAULT_PACKAGE_NAME}@`)) { - return trimmed.slice(`${DEFAULT_PACKAGE_NAME}@`.length); + for (const prefix of ["ironclaw@", "openclaw@"]) { + if (trimmed.startsWith(prefix)) { + return trimmed.slice(prefix.length); + } } return trimmed; } diff --git a/src/cli/update-cli/update-command.ts b/src/cli/update-cli/update-command.ts index 58536704df3..92a277e4541 100644 --- a/src/cli/update-cli/update-command.ts +++ b/src/cli/update-cli/update-command.ts @@ -51,7 +51,6 @@ import { ensureGitCheckout, normalizeTag, parseTimeoutMsOrExit, - readPackageName, readPackageVersion, resolveGitInstallDir, resolveGlobalManager, @@ -212,9 +211,8 @@ async function runPackageInstallUpdate(params: { const runCommand = createGlobalCommandRunner(); const pkgRoot = await resolveGlobalPackageRoot(manager, runCommand, params.timeoutMs); - const packageName = - (pkgRoot ? await readPackageName(pkgRoot) : await readPackageName(params.root)) ?? - DEFAULT_PACKAGE_NAME; + // Always install the canonical package name regardless of what's on disk + const packageName = DEFAULT_PACKAGE_NAME; const beforeVersion = pkgRoot ? await readPackageVersion(pkgRoot) : null; if (pkgRoot) { @@ -747,7 +745,7 @@ export async function updateCommand(opts: UpdateCommandOptions): Promise { ); defaultRuntime.log( theme.muted( - `Examples: \`${replaceCliName("npm i -g openclaw@latest", CLI_NAME)}\` or \`${replaceCliName("pnpm add -g openclaw@latest", CLI_NAME)}\``, + `Examples: \`npm i -g ${DEFAULT_PACKAGE_NAME}@latest\` or \`pnpm add -g ${DEFAULT_PACKAGE_NAME}@latest\``, ), ); } diff --git a/src/infra/update-runner.test.ts b/src/infra/update-runner.test.ts index bb301c563ca..648785e232d 100644 --- a/src/infra/update-runner.test.ts +++ b/src/infra/update-runner.test.ts @@ -362,16 +362,16 @@ describe("runGatewayUpdate", () => { it.each([ { title: "updates global npm installs when detected", - expectedInstallCommand: "npm i -g openclaw@latest --no-fund --no-audit --loglevel=error", + expectedInstallCommand: "npm i -g ironclaw@latest --no-fund --no-audit --loglevel=error", }, { title: "uses update channel for global npm installs when tag is omitted", - expectedInstallCommand: "npm i -g openclaw@beta --no-fund --no-audit --loglevel=error", + expectedInstallCommand: "npm i -g ironclaw@beta --no-fund --no-audit --loglevel=error", channel: "beta" as const, }, { title: "updates global npm installs with tag override", - expectedInstallCommand: "npm i -g openclaw@beta --no-fund --no-audit --loglevel=error", + expectedInstallCommand: "npm i -g ironclaw@beta --no-fund --no-audit --loglevel=error", tag: "beta", }, ])("$title", async ({ expectedInstallCommand, channel, tag }) => { @@ -407,7 +407,7 @@ describe("runGatewayUpdate", () => { if (key === "pnpm root -g") { return { stdout: "", stderr: "", code: 1 }; } - if (key === "npm i -g openclaw@latest --no-fund --no-audit --loglevel=error") { + if (key === "npm i -g ironclaw@latest --no-fund --no-audit --loglevel=error") { stalePresentAtInstall = await pathExists(staleDir); return { stdout: "ok", stderr: "", code: 0 }; } @@ -430,7 +430,7 @@ describe("runGatewayUpdate", () => { const { calls, runCommand } = createGlobalInstallHarness({ pkgRoot, - installCommand: "bun add -g openclaw@latest", + installCommand: "bun add -g ironclaw@latest", onInstall: async () => { await fs.writeFile( path.join(pkgRoot, "package.json"), @@ -446,7 +446,7 @@ describe("runGatewayUpdate", () => { expect(result.mode).toBe("bun"); expect(result.before?.version).toBe("1.0.0"); expect(result.after?.version).toBe("2.0.0"); - expect(calls.some((call) => call === "bun add -g openclaw@latest")).toBe(true); + expect(calls.some((call) => call === "bun add -g ironclaw@latest")).toBe(true); }); }); diff --git a/src/infra/update-runner.ts b/src/infra/update-runner.ts index a46a51e28e9..2599d9783b7 100644 --- a/src/infra/update-runner.ts +++ b/src/infra/update-runner.ts @@ -866,14 +866,15 @@ export async function runGatewayUpdate(opts: UpdateRunnerOptions = {}): Promise< const beforeVersion = await readPackageVersion(pkgRoot); const globalManager = await detectGlobalInstallManagerForRoot(runCommand, pkgRoot, timeoutMs); if (globalManager) { - const packageName = (await readPackageName(pkgRoot)) ?? DEFAULT_PACKAGE_NAME; + // Always install the canonical package name regardless of what's on disk + const installedName = (await readPackageName(pkgRoot)) ?? DEFAULT_PACKAGE_NAME; await cleanupGlobalRenameDirs({ globalRoot: path.dirname(pkgRoot), - packageName, + packageName: installedName, }); const channel = opts.channel ?? DEFAULT_PACKAGE_CHANNEL; const tag = normalizeTag(opts.tag ?? channelToNpmTag(channel)); - const spec = `${packageName}@${tag}`; + const spec = `${DEFAULT_PACKAGE_NAME}@${tag}`; const updateStep = await runStep({ runCommand, name: "global update",