Skip to content

fix: reset stale state on plugin re-load to handle double-load by OpenClaw Gateway#1214

Open
r266-tech wants to merge 2 commits intovolcengine:mainfrom
r266-tech:fix/plugin-double-load-registration
Open

fix: reset stale state on plugin re-load to handle double-load by OpenClaw Gateway#1214
r266-tech wants to merge 2 commits intovolcengine:mainfrom
r266-tech:fix/plugin-double-load-registration

Conversation

@r266-tech
Copy link
Copy Markdown
Contributor

Closes #1210

Problem

When OpenClaw Gateway starts, the openviking plugin is loaded twice with different cacheKey (first with preferSetupRuntimeForChannelPlugins: true, then without). Because the plugin's module-level Maps (localClientCache, localClientPendingPromises) persist across re-imports, the second register() call sees stale state from the first load — causing tool/service/context-engine registration to operate on incorrect cached entries.

Root Cause

The plugin's register() function assumes it's called exactly once per plugin lifecycle. Module-level state is never cleared, so a second registration (triggered by OpenClaw's dual-load startup sequence) inherits stale references.

Fix

Add an idempotency guard at the beginning of register() that detects when the plugin has already been registered. On the second registration call:

  1. Log a diagnostic message
  2. Clear localClientCache and localClientPendingPromises Maps
  3. Proceed with a clean registration

This ensures tools, service startup, and context-engine are registered correctly even when OpenClaw loads the plugin twice.

Verification

Related

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 3, 2026

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🏅 Score: 85
🧪 No relevant tests
🔒 No security concerns identified
✅ No TODO sections
🔀 No multiple PR themes
⚡ Recommended focus areas for review

Missing Client Parameters

Defensive re-spawn path creates OpenVikingClient without tenantAccount, tenantUser, and routingDebugLog parameters, which may cause inconsistent behavior compared to the main spawn path.

const client = new OpenVikingClient(baseUrl, cfg.apiKey, cfg.agentId, cfg.timeoutMs);

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 3, 2026

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Add missing client parameters in re-spawn

Pass all required parameters (tenantAccount, tenantUser, routingDebugLog) when
creating the OpenVikingClient in the defensive re-spawn path, matching the initial
client construction.

examples/openclaw-plugin/index.ts [1231]

-const client = new OpenVikingClient(baseUrl, cfg.apiKey, cfg.agentId, cfg.timeoutMs);
+const client = new OpenVikingClient(
+  baseUrl,
+  cfg.apiKey,
+  cfg.agentId,
+  cfg.timeoutMs,
+  tenantAccount,
+  tenantUser,
+  routingDebugLog,
+);
Suggestion importance[1-10]: 7

__

Why: Fixes incomplete OpenVikingClient initialization in the defensive re-spawn path by adding missing parameters (tenantAccount, tenantUser, routingDebugLog) to match the initial client construction.

Medium
General
Optimize unique memory filtering to linear time

Replace the O(n²) unique memory filter with a linear-time approach using a Set to
track seen URIs. This improves performance when merging memory results from multiple
sources.

examples/openclaw-plugin/index.ts [484-487]

 const allMemories = [...(userResult.memories ?? []), ...(agentResult.memories ?? [])];
-const uniqueMemories = allMemories.filter((memory, index, self) =>
-  index === self.findIndex((m) => m.uri === memory.uri)
-);
+const seenUris = new Set<string>();
+const uniqueMemories = allMemories.filter((memory) => {
+  if (seenUris.has(memory.uri)) return false;
+  seenUris.add(memory.uri);
+  return true;
+});
Suggestion importance[1-10]: 5

__

Why: Replaces O(n²) duplicate filtering with a linear-time Set-based approach, improving performance for memory result merging.

Low
Optimize before_prompt_build unique filtering

Replace the second instance of O(n²) unique memory filtering with a linear-time
Set-based approach in the before_prompt_build hook.

examples/openclaw-plugin/index.ts [940-943]

 const allMemories = [...(userResult.memories ?? []), ...(agentResult.memories ?? [])];
-const uniqueMemories = allMemories.filter((memory, index, self) =>
-  index === self.findIndex((m) => m.uri === memory.uri)
-);
+const seenUris = new Set<string>();
+const uniqueMemories = allMemories.filter((memory) => {
+  if (seenUris.has(memory.uri)) return false;
+  seenUris.add(memory.uri);
+  return true;
+});
Suggestion importance[1-10]: 5

__

Why: Replaces another O(n²) duplicate filter with a linear-time Set-based approach in the before_prompt_build hook, improving performance for auto-recall memory merging.

Low

…nClaw Gateway

Closes volcengine#1210

When OpenClaw Gateway starts, the openviking plugin is loaded twice
with different cacheKey. Module-level Maps (localClientCache,
localClientPendingPromises) persist across re-imports, causing the
second register() call to see stale state.

This patch adds the plugin file with an idempotency guard that
detects duplicate registration and clears cached state before
proceeding.
@r266-tech r266-tech force-pushed the fix/plugin-double-load-registration branch from 97f0f27 to 680450b Compare April 4, 2026 01:01
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 4, 2026

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ r266-tech
❌ wzrrrrrrr
You have signed the CLA already but the status is still pending? Let us recheck it.

The defensive re-spawn path was creating OpenVikingClient without
tenantAccount, tenantUser, and routingDebugLog parameters.
This mismatch could cause incorrect agent routing.
@r266-tech
Copy link
Copy Markdown
Contributor Author

Fixed: added missing tenantAccount, tenantUser, routingDebugLog parameters to the defensive re-spawn path OpenVikingClient constructor, matching the initial construction. Thanks for catching this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

Plugin tools not registered when loaded twice by OpenClaw Gateway

3 participants