Skip to content

fix(plugins): restore cold-registry load for path-based plugin tools (#76598)#76609

Closed
hclsys wants to merge 2 commits into
openclaw:mainfrom
hclsys:fix/76598-path-plugin-tools-cold-registry-load
Closed

fix(plugins): restore cold-registry load for path-based plugin tools (#76598)#76609
hclsys wants to merge 2 commits into
openclaw:mainfrom
hclsys:fix/76598-path-plugin-tools-cold-registry-load

Conversation

@hclsys

@hclsys hclsys commented May 3, 2026

Copy link
Copy Markdown

Summary

resolvePluginTools silently returned an empty list when no pre-warmed channel/active runtime registry was available — specifically for path-based plugins loaded via plugins.load.paths (origin "config").

Root cause: PR #76004 ("perf(plugins): reuse startup runtime registry") replaced resolveRuntimePluginRegistry (which did on-demand loading) with getLoadedRuntimePluginRegistry (lookup-only). The on-demand load fallback was restored for memory plugins (#76393) and capability providers (#76536), but not for resolvePluginTools. Result: path-based plugin tool factories register at startup but their tools disappear at agent request time with unknown method: <tool-name>.run.

Fix: When resolvePluginToolRegistry returns null (cold registry), call ensureStandaloneRuntimePluginRegistryLoaded to trigger the load, then retry. If still null after load, return the (possibly partial) cached tool list.

Changes

  • src/plugins/tools.ts: add cold-registry fallback load + retry in resolvePluginTools
  • src/plugins/tools.optional.test.ts: regression test asserting tools resolve without pre-warming the registry
  • CHANGELOG.md: fix entry

Audit

Rule Check Result
A: existing helper? ensureStandaloneRuntimePluginRegistryLoaded already imported in tools.ts reused
B: shared callers ≥3? resolvePluginTools is called from many sites, but the change is internal to its body no contract change
C: rival PR? No open PR mentioning #76598 or touching src/plugins/tools.ts for this path NONE

Test

pnpm test src/plugins/tools.optional.test.ts
# 38/38 pass

Fixes #76598.

@clawsweeper

clawsweeper Bot commented May 3, 2026

Copy link
Copy Markdown
Contributor

Thanks for the context here. I did a careful shell check against current main, and this is already implemented.

Close as implemented on current main: the central cold-registry load for selected plugin tools is already handled in resolvePluginToolRegistry, making this PR's fallback redundant. The fix is present on main but no tag contains it yet.

So I’m closing this as already implemented rather than keeping a duplicate issue open.

Review details

Best possible solution:

Keep the centralized current-main fallback in resolvePluginToolRegistry; if maintainers still want exact config-origin coverage or a dedicated changelog credit, handle that as a separate small cleanup rather than merging the redundant fallback.

Do we have a high-confidence way to reproduce the issue?

Yes. The linked report has a concrete path-based config plugin reproducer, and source inspection shows the relevant resolution path now goes from manifest-selected plugin ids to a scoped standalone runtime load without requiring a pre-warmed registry.

Is this the best way to solve the issue?

Yes. The current-main helper-level fallback is the narrower maintainable fix because every resolvePluginToolRegistry caller benefits from the cold-load behavior, while this PR's additional resolvePluginTools fallback is now mostly redundant.

Security review:

Security review cleared: The PR touches plugin tool resolution, tests, and changelog only; it adds no dependency, CI, publishing, secret-handling, or new supply-chain surface.

What I checked:

  • Current-main implementation: resolvePluginToolRegistry now checks loaded channel and active registries, then calls ensureStandaloneRuntimePluginRegistryLoaded with the selected plugin ids and returns the standalone registry when it contains scoped plugin tools. (src/plugins/tools.ts:648, e0a83c00461c)
  • Config path discovery: Plugins listed through plugins.load.paths are discovered with origin config, so the current scoped runtime load covers the path-based plugin class from the linked report. (src/plugins/discovery.ts:986, e0a83c00461c)
  • Scoped loader behavior: loadOpenClawPlugins normalizes onlyPluginIds, discovers config load paths, filters candidate imports to the requested ids, and uses toolDiscovery registration mode for tool-resolution loads. (src/plugins/loader.ts:1427, e0a83c00461c)
  • Plugin metadata contract: Plugin architecture docs require compatibility checks to include plugin discovery roots such as plugins.load.paths, supporting the source-level conclusion that path plugins belong in this runtime resolution path. Public docs: docs/plugins/architecture.md. (docs/plugins/architecture.md:154, e0a83c00461c)
  • Fix provenance: The implementation appears on main in commit 5e9135f2e23d40914ab3c3ec9f883bcda330fcda with committer timestamp 2026-05-03T12:24:03+01:00. (src/plugins/tools.ts:648, 5e9135f2e23d)
  • Release check: git tag --contains returned no tags for the proof commit, and the latest listed release tag v2026.5.2 dereferences to 8b2a6e57fef6c582ec6d27b85150616f9e3a7ba4, so the fix is only proven on current main. (5e9135f2e23d)

Likely related people:

  • steipete: Authored the current-main commit that centralized the cold fallback for plugin tools and recently maintained the standalone registry/bootstrap path. (role: recent maintainer and proof-commit author; confidence: high; commits: 5e9135f2e23d, 9cb8608dab83, 380085071303; files: src/plugins/tools.ts, src/plugins/runtime/standalone-runtime-registry-loader.ts, src/plugins/loader.ts)
  • DmitryPogodaev: Merged PR perf(plugins): reuse startup runtime registry #76004 changed plugin helper paths to reuse loaded runtime registries, which the linked report identifies as the regression family. (role: introduced related registry reuse behavior; confidence: medium; commits: 8283c5d6cc3f; files: src/plugins/tools.ts, src/plugins/loader.ts)
  • neeravmakwana: Authored the merged memory cold-registry fallback in the same regression family, using the same standalone registry helper pattern. (role: adjacent cold-registry fix owner; confidence: medium; commits: 5de8ffe7bf17; files: src/plugins/memory-runtime.ts, src/commands/doctor-memory-search.test.ts)

Codex review notes: model gpt-5.5, reasoning high; reviewed against e0a83c00461c; fix evidence: commit 5e9135f2e23d, main fix timestamp 2026-05-03T12:24:03+01:00.

@martingarramon

Copy link
Copy Markdown
Contributor

Silent fallback recreates the original symptom. The second-null branch in resolvePluginTools returns the partial tools list with no diagnostic. ensureStandaloneRuntimePluginRegistryLoaded calls loadOpenClawPlugins at standalone-runtime-registry-loader.ts:69 with no surrounding catch, so any throw during the cold-load propagates and the caller sees the same silent-failure shape as the original #76598 symptom. Add a try/catch around the loader call and a diagnostic on the second-null branch.

Test doesn't match repro. The test uses origin: "bundled" (tools.optional.test.ts:502) but the reporter's repro is origin: "config" (per #76598 body). No origin-specific branching exists in the touched code (origins enumerated in plugin-origin.types.ts:1), so both functionally hit the same null-registry condition — but the test should use "config" to mirror the reported case.

The cold-registry fallback approach is correct, and surface: "channel" aligns with the first surface resolvePluginToolRegistry queries (tools.ts:620).

@steipete steipete force-pushed the fix/76598-path-plugin-tools-cold-registry-load branch from 2daef9c to 2910653 Compare May 3, 2026 12:02
HCL and others added 2 commits May 3, 2026 13:03
…penclaw#76598)

`resolvePluginTools` returned an empty tool list when no pre-warmed
channel/active registry was found after startup — the on-demand fallback
removed by PR openclaw#76004 was only added back for memory and capability-provider
surfaces, leaving path-based (origin "config") plugin tool factories silent.

Fix: when `resolvePluginToolRegistry` returns null, trigger a standalone
registry load via `ensureStandaloneRuntimePluginRegistryLoaded`, then retry.
Adds regression test asserting tools are resolved without pre-warming.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@steipete steipete force-pushed the fix/76598-path-plugin-tools-cold-registry-load branch from 2910653 to fccd78d Compare May 3, 2026 12:04
@clawsweeper clawsweeper Bot closed this May 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Path-based plugin tools (origin "config") not exposed after 2026.5.2

3 participants