diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d92a86d20c..3bdc8110fe3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ Docs: https://docs.openclaw.ai - Discord/voice: include a bounded one-line STT transcript preview in verbose voice logs so live voice debugging shows what speakers said before the agent reply. - Codex app-server: pin the managed Codex harness and Codex CLI smoke package to `@openai/codex@0.129.0`, defer OpenClaw integration dynamic tools behind Codex tool search by default, and accept current Codex service-tier values so legacy `fast` settings survive the stable harness upgrade as `priority`. - Codex app-server: default implicit local stdio app-server permissions to guardian when Codex system requirements disallow the YOLO approval, reviewer, or sandbox value, including hostname-scoped remote sandbox entries, avoiding turn-start failures on managed hosts that permit only reviewed approval or narrower sandboxes. +- Plugins/install: run managed npm-root install, uninstall, prune, and repair commands from the managed root without a redundant `--prefix .`, avoiding npm 10.9.3 Arborist crashes on native Windows WhatsApp plugin installs. Fixes #78514. (#78902) Thanks @melihselamett-stack. - Discord/voice: stream ElevenLabs TTS directly into Discord playback and send ElevenLabs latency optimization as the documented query parameter so spoken replies can start sooner. - Discord/voice: keep TTS playback running when another user starts speaking, ignore new capture during playback to avoid feedback loops, and downgrade expected receive-stream aborts to verbose diagnostics. - iMessage: expose native private-API message actions through `imsg rpc` for reactions, edits, unsends, replies, rich sends, attachments, and group management when `imsg status --json` reports the required bridge capabilities. diff --git a/docs/plugins/dependency-resolution.md b/docs/plugins/dependency-resolution.md index 68a10b2b393..6017eb21093 100644 --- a/docs/plugins/dependency-resolution.md +++ b/docs/plugins/dependency-resolution.md @@ -41,7 +41,8 @@ OpenClaw uses stable per-source roots: npm installs run in the npm root with: ```bash -npm install --prefix ~/.openclaw/npm --omit=dev --omit=peer --legacy-peer-deps --ignore-scripts --no-audit --no-fund +cd ~/.openclaw/npm +npm install --omit=dev --omit=peer --legacy-peer-deps --ignore-scripts --no-audit --no-fund ``` `openclaw plugins install npm-pack:` uses that same managed npm root diff --git a/src/infra/npm-managed-root.test.ts b/src/infra/npm-managed-root.test.ts index 5fca5b1c8b7..81c422babe8 100644 --- a/src/infra/npm-managed-root.test.ts +++ b/src/infra/npm-managed-root.test.ts @@ -398,8 +398,6 @@ describe("managed npm root", () => { "--ignore-scripts", "--no-audit", "--no-fund", - "--prefix", - ".", "openclaw", ], expect.objectContaining({ diff --git a/src/infra/npm-managed-root.ts b/src/infra/npm-managed-root.ts index fac2eaad8ee..dbc93ce7f37 100644 --- a/src/infra/npm-managed-root.ts +++ b/src/infra/npm-managed-root.ts @@ -245,8 +245,6 @@ export async function repairManagedNpmRootOpenClawPeer(params: { "--ignore-scripts", "--no-audit", "--no-fund", - "--prefix", - ".", "openclaw", ] : [ @@ -257,8 +255,6 @@ export async function repairManagedNpmRootOpenClawPeer(params: { "--ignore-scripts", "--no-audit", "--no-fund", - "--prefix", - ".", ]; try { const result = await command(npmArgs, { diff --git a/src/plugins/install.npm-spec.test.ts b/src/plugins/install.npm-spec.test.ts index eff92925f69..7bccb2d1d1a 100644 --- a/src/plugins/install.npm-spec.test.ts +++ b/src/plugins/install.npm-spec.test.ts @@ -69,8 +69,6 @@ function expectNpmInstallIntoRoot(params: { calls: unknown[][]; npmRoot: string "--ignore-scripts", "--no-audit", "--no-fund", - "--prefix", - ".", ]); } @@ -290,9 +288,7 @@ function mockNpmViewAndInstallMany(packages: MockNpmPackage[]) { ); } if (argv[0] === "npm" && argv[1] === "install") { - const prefixIndex = argv.indexOf("--prefix"); - const prefixValue = prefixIndex >= 0 ? argv[prefixIndex + 1] : undefined; - const npmRoot = prefixValue === "." ? options?.cwd : prefixValue; + const npmRoot = options?.cwd; if (!npmRoot) { throw new Error(`unexpected npm install command: ${argv.join(" ")}`); } @@ -345,9 +341,7 @@ function mockNpmViewAndInstallMany(packages: MockNpmPackage[]) { if (argv[0] === "npm" && argv[1] === "uninstall") { const packageName = argv.at(-1); if (packageName === "openclaw") { - const prefixIndex = argv.indexOf("--prefix"); - const prefixValue = prefixIndex >= 0 ? argv[prefixIndex + 1] : undefined; - const npmRoot = prefixValue === "." ? options?.cwd : prefixValue; + const npmRoot = options?.cwd; if (!npmRoot) { throw new Error(`unexpected npm uninstall command: ${argv.join(" ")}`); } diff --git a/src/plugins/install.ts b/src/plugins/install.ts index c067d8ac75c..df04989bcf0 100644 --- a/src/plugins/install.ts +++ b/src/plugins/install.ts @@ -328,8 +328,6 @@ async function rollbackManagedNpmPluginInstall(params: { "--ignore-scripts", "--no-audit", "--no-fund", - "--prefix", - ".", params.packageName, ], { @@ -499,8 +497,6 @@ async function installPluginFromManagedNpmRoot( noAudit: true, noFund: true, }), - "--prefix", - ".", ], { cwd: npmRoot, diff --git a/src/plugins/uninstall.test.ts b/src/plugins/uninstall.test.ts index 5981192abb7..53ccf585042 100644 --- a/src/plugins/uninstall.test.ts +++ b/src/plugins/uninstall.test.ts @@ -992,8 +992,6 @@ describe("uninstallPlugin", () => { "--ignore-scripts", "--no-audit", "--no-fund", - "--prefix", - ".", "@openclaw/kitchen-sink", ], expect.objectContaining({ @@ -1128,8 +1126,6 @@ describe("uninstallPlugin", () => { "--ignore-scripts", "--no-audit", "--no-fund", - "--prefix", - ".", "missing-plugin", ], expect.objectContaining({ diff --git a/src/plugins/uninstall.ts b/src/plugins/uninstall.ts index bdfe8ea22aa..02e98ab8cfb 100644 --- a/src/plugins/uninstall.ts +++ b/src/plugins/uninstall.ts @@ -611,8 +611,6 @@ export async function applyPluginUninstallDirectoryRemoval( "--ignore-scripts", "--no-audit", "--no-fund", - "--prefix", - ".", removal.cleanup.packageName, ], {