fix(memory-openviking): share pending clientPromise across dual-context registrations#681
Merged
qin-ctx merged 1 commit intovolcengine:mainfrom Mar 17, 2026
Conversation
…xt registrations OpenClaw loads the plugin in two separate contexts ([gateway] and [plugins]), each calling register() and creating its own pending clientPromise. However, start() only runs in one context, leaving the other context's promise permanently pending — causing the before_agent_start hook to hang forever on await getClient(). Fix by introducing a module-level localClientPendingPromises map in client.ts. All registrations share the same pending promise via this map. The first start() call to run claims the entry (deletes it from the map) and spawns the process, resolving the shared promise for all registrations. Subsequent start() calls fall through to await getClient() which waits for the spawner to resolve. The stop() service clears the map entry to prevent stale promises across hot-reloads. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Wiehan Boshoff seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. You have signed the CLA already but the status is still pending? Let us recheck it. |
qin-ctx
approved these changes
Mar 17, 2026
This was referenced Mar 17, 2026
Closed
Closed
19 tasks
qin-ctx
added a commit
that referenced
this pull request
Mar 19, 2026
PR #662 renamed the plugin directory and rewrote index.ts from a stale branch base, silently dropping two merged bug fixes: - #681: share pending clientPromise across dual-context registrations to prevent before_agent_start hook from hanging forever - #688: wrap auto-recall search in withTimeout(5s) to prevent indefinite agent hang when OpenViking search API is slow or unresponsive
19 tasks
chenjw
pushed a commit
that referenced
this pull request
Mar 19, 2026
…rge (#779) PR #662 renamed the plugin directory and rewrote index.ts from a stale branch base, silently dropping two merged bug fixes: - #681: share pending clientPromise across dual-context registrations to prevent before_agent_start hook from hanging forever - #688: wrap auto-recall search in withTimeout(5s) to prevent indefinite agent hang when OpenViking search API is slow or unresponsive
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
OpenClaw loads the
memory-openvikingplugin in two separate contexts ([gateway]and[plugins]), each callingregister()independently. Each call creates its own localclientPromise. However,start()only runs in one context — leaving the other context's promise permanently pending.This causes the
before_agent_starthook to hang forever onawait getClient()wheneverhookAgentIdis set (i.e. always in a standard gateway deployment), because the hook runs in the context whoseclientPromisewas never resolved.Symptoms:
running before_agent_start (1 handlers, sequential)with nothing afterautoRecallandautoCaptureappear completely brokenFix
Introduce a module-level
localClientPendingPromisesmap inclient.ts:register()checks the map first. If an entry exists, it shares that promise instead of creating a new pending one.start()atomically claims the entry (deletes it from the map) — only the firststart()call spawns the process and resolves the shared promise. Subsequentstart()calls fall through toawait getClient()which waits for the spawner.stop()clears the map entry to prevent stale promises persisting across hot-reloads.Test plan
autoRecall: true— confirmautoRecall doneappears in logs within ~2 secondsbefore_agent_starthook no longer hangs indefinitely🤖 Generated with Claude Code