perf(plugins): reuse startup runtime registry#76004
Conversation
|
Codex review: found issues before merge. Summary Reproducibility: yes. A source-level reproduction is to call Next step before merge Security Review findings
Review detailsBest possible solution: Keep the extra-param cache, but make registry reuse a compatible fast path only and preserve the existing cold-load, auto-enable, and recovery fallbacks for runtime helpers. Do we have a high-confidence way to reproduce the issue? Yes. A source-level reproduction is to call Is this the best way to solve the issue? No. Memoizing prepared extra params per stable config is a narrow maintainable optimization, but replacing resolver fallbacks with loaded-registry-only reads across shared plugin surfaces is not the safest implementation boundary. Full review comments:
Overall correctness: patch is incorrect Security concerns:
Acceptance criteria:
What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against 695960975a60. |
d61869e to
983a94f
Compare
983a94f to
499ccb1
Compare
Co-authored-by: DmitryPogodaev <pogodaev.dm@gmail.com>
499ccb1 to
3800850
Compare
|
Landed in main.
Thanks @DmitryPogodaev! |
…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>
…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>
…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 #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>
…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>
…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>
…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>
…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>
…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>
Summary
Memoize
resolvePreparedExtraParamsperOpenClawConfigobject identity. Profiling on a stable warm gateway shows it synchronously costs ~1.9 sec per embedded turn even when nothing about the agent / model / config has changed.Background
resolvePreparedExtraParamsruns on every embedded turn throughbuildAgentRuntimePlan. It calls two provider plugin hooks (prepareProviderExtraParams,resolveProviderExtraParamsForTransport) which trigger provider runtime plugin resolution. The result is deterministic for stable inputs (provider, modelId, agentId, workspaceDir, agentDir, thinkingLevel, resolvedTransport, extraParamsOverride, resolvedExtraParams) within a given config lifetime, but currently is recomputed on every dispatch.Approach
WeakMapkeyed byOpenClawConfigobject reference. Hot-reload installs a fresh config object viasetRuntimeConfig(...), so the previous config bucket is garbage-collected automatically — no manual invalidation hook needed.Mapkeyed by a deterministic JSON serialization of the call-site inputs that influence the prepared extra-params output.Inputs intentionally excluded from the key
params.model— its identity is captured indirectly viaprovider+modelIdand throughresolvedTransportwhen the transport hook needs it; including the fullProviderRuntimeModelobject would defeat caching for callers that build a fresh model object per turn.params.cfg— already used as the cache bucket identity.Risk note
Provider plugins implementing
prepareExtraParams/resolveProviderExtraParamsForTransportare expected to be deterministic for a given(config, provider, model, thinkingLevel, extraParams)tuple. All bundled providers satisfy this. If a future plugin needs dynamic state (env var, time-of-day, runtime telemetry) within these hooks, caching would mask that within one config lifetime — but that pattern is already incompatible with the surrounding embedded-run infrastructure that resolves these hooks exactly once per turn anyway.If maintainers prefer a feature-flagged opt-in or invalidation hooked to plugin registry version changes, happy to adapt.
Measurements
Personal VPS, codex harness, warm gateway, simple ping message:
buildAgentRuntimePlan(sync)Combined with the sibling PR for
resolveTranscriptPolicy, pre-codex setup drops to ~3.7 s.Test plan
extra-params.test.tsshould pass unchanged.prepareProviderExtraParamsre-resolution overhead in profiling.🤖 Patch authored after debugging slow message dispatch on a personal VPS.