diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cdfc7f2c96..429de870f97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ Docs: https://docs.openclaw.ai - Skills: require explicit `skills.entries.coding-agent.enabled` before exposing the bundled coding-agent skill, so installs with Codex on PATH but no OpenAI auth do not silently offer Codex delegation. Fixes #73358. Thanks @LaFleurAdvertising and @Sanjays2402. - Plugins/startup: precompute bundled runtime mirror fingerprints before taking the mirror lock, including dist-runtime canonical roots, so Docker Desktop/WSL cold starts no longer hold `.openclaw-runtime-mirror.lock` while scanning slow persisted volumes. Fixes #73339. Thanks @1yihui. - Channels/LINE: persist inbound image, video, audio, and file downloads in `~/.openclaw/media/inbound/` instead of temporary files so agents can still read LINE media after `/tmp` cleanup. Fixes #73370. Thanks @hijirii and @wenxu007. +- CLI/plugins: keep bundled plugin installs out of `plugins.load.paths` while preserving install records, so install/inspect/doctor loops no longer warn about the current bundled plugin directory. Thanks @vincentkoc. - Control UI/WebChat: keep large attachment payloads out of Lit state and optimistic chat messages, using object URL previews plus send-time payload serialization so PDF/image uploads no longer trigger `RangeError: Maximum call stack size exceeded`. Fixes #73360; refs #54378 and #63432. Thanks @hejunhui-73, @Ansub, and @christianhernandez3-afk. - Agents/Anthropic: cancel stalled Anthropic Messages SSE body reads when abort signals fire, so active-memory timeouts release transport resources instead of leaving hidden recall runs parked on `reader.read()`. Refs #72965 and #73120. Thanks @wdeveloper16. - Agents/models: keep per-agent primary models strict when `fallbacks` is omitted, so probe-only custom providers are not tried as hidden fallback candidates unless the agent explicitly opts in. Fixes #73332. Thanks @haumanto. diff --git a/scripts/e2e/bundled-plugin-install-uninstall-docker.sh b/scripts/e2e/bundled-plugin-install-uninstall-docker.sh index b15a4297179..a5abd92d349 100755 --- a/scripts/e2e/bundled-plugin-install-uninstall-docker.sh +++ b/scripts/e2e/bundled-plugin-install-uninstall-docker.sh @@ -138,8 +138,8 @@ if (record.installPath !== record.sourcePath) { throw new Error(`bundled install path should equal source path for ${pluginId}`); } const paths = config.plugins?.load?.paths || []; -if (!paths.includes(record.sourcePath)) { - throw new Error(`config load paths do not include bundled install path for ${pluginId}`); +if (paths.some((entry) => String(entry).includes(`/dist/extensions/${pluginDir}`))) { + throw new Error(`config load paths should not include bundled install path for ${pluginId}`); } if (requiresConfig && config.plugins?.entries?.[pluginId]?.enabled === true) { throw new Error(`plugin requiring config should not be enabled immediately after install for ${pluginId}`); diff --git a/src/cli/plugins-cli.install.test.ts b/src/cli/plugins-cli.install.test.ts index b715519dacc..d6188fd3cd9 100644 --- a/src/cli/plugins-cli.install.test.ts +++ b/src/cli/plugins-cli.install.test.ts @@ -502,9 +502,7 @@ describe("plugins cli install", () => { const writtenConfig = writeConfigFile.mock.calls.at(-1)?.[0] as OpenClawConfig; expect(writtenConfig.plugins?.entries?.["memory-lancedb"]).toBeUndefined(); - expect(writtenConfig.plugins?.load?.paths).toEqual( - expect.arrayContaining(["/existing/plugin", expect.stringContaining("memory-lancedb")]), - ); + expect(writtenConfig.plugins?.load?.paths).toEqual(["/existing/plugin"]); expect(writePersistedInstalledPluginIndexInstallRecords).toHaveBeenCalledWith({ "memory-lancedb": expect.objectContaining({ source: "path", diff --git a/src/cli/plugins-install-command.ts b/src/cli/plugins-install-command.ts index bf86eefc450..18946c19ef5 100644 --- a/src/cli/plugins-install-command.ts +++ b/src/cli/plugins-install-command.ts @@ -110,8 +110,6 @@ async function installBundledPluginSource(params: { bundledSource: BundledPluginSource; warning: string; }) { - const existing = params.snapshot.config.plugins?.load?.paths ?? []; - const mergedPaths = Array.from(new Set([...existing, params.bundledSource.localPath])); const existingEntry = params.snapshot.config.plugins?.entries?.[params.bundledSource.pluginId]; const shouldEnable = hasValidBundledPluginConfig({ bundledSource: params.bundledSource, @@ -125,16 +123,7 @@ async function installBundledPluginSource(params: { : `Installed bundled plugin "${params.bundledSource.pluginId}" without enabling it because it requires configuration first. Configure it, then run \`openclaw plugins enable ${params.bundledSource.pluginId}\`.`; await persistPluginInstall({ snapshot: { - config: { - ...configBase, - plugins: { - ...configBase.plugins, - load: { - ...configBase.plugins?.load, - paths: mergedPaths, - }, - }, - }, + config: configBase, baseHash: params.snapshot.baseHash, }, pluginId: params.bundledSource.pluginId,