From 3367a5fe396cb51e914f424ce3c80e149b03404a Mon Sep 17 00:00:00 2001 From: Contributor Date: Tue, 24 Mar 2026 15:44:25 +0800 Subject: [PATCH 1/2] fix(self-improvement): skip note inject on Discord channel /new to avoid hook interference Skip self-improvement note injection on Discord channel (non-thread) resets. The appendSelfImprovementNote hook was push()ing synchronously into event.messages before the first agent turn ran, which contributed to the post-reset startup race described in openclaw/openclaw#46941. Discord channel resets are guarded by checking Provider=discord && (MessageThreadId == null or empty). Thread resets and non-Discord surfaces are unaffected. Ref: openclaw/openclaw#46941 (root cause: /new re-fires command:new hooks) Ref: openclaw/openclaw#49001 (thread-only post-rotation window) --- index.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/index.ts b/index.ts index 212dede..c30f237 100644 --- a/index.ts +++ b/index.ts @@ -2785,6 +2785,19 @@ const memoryLanceDBProPlugin = { return; } + // Skip self-improvement note on Discord channel (non-thread) resets + // to avoid contributing to the post-reset startup race on Discord channels. + // Discord thread resets are handled separately by the OpenClaw core's + // postRotationStartupUntilMs mechanism (PR #49001). + const provider = typeof contextForLog.Provider === "string" ? contextForLog.Provider : ""; + const messageThreadId = contextForLog.MessageThreadId; + if (provider === "discord" && (messageThreadId == null || messageThreadId === "")) { + api.logger.info( + `self-improvement: command:${action} skipped on Discord channel (non-thread) reset to avoid startup race; use /new in thread or restart gateway if startup is incomplete` + ); + return; + } + const exists = event.messages.some((m: unknown) => typeof m === "string" && m.includes(SELF_IMPROVEMENT_NOTE_PREFIX)); if (exists) { api.logger.info(`self-improvement: command:${action} note already present; skip duplicate inject`); From 8fcdf53fdfa344a1d629d567b8994339923262e8 Mon Sep 17 00:00:00 2001 From: Contributor Date: Wed, 25 Mar 2026 08:33:51 +0800 Subject: [PATCH 2/2] fix(self-improvement): access Provider and threadId via sessionEntry Previously the code accessed contextForLog.Provider and contextForLog.MessageThreadId directly, but these fields are not present in the command:new/command:reset hook event context. Provider lives in sessionEntry.Provider; MessageThreadId is stored as sessionEntry.threadId (populated from ctx.MessageThreadId at session creation time). Access them correctly via the sessionEntry object that is passed to the hook event context. --- index.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/index.ts b/index.ts index c30f237..a355e60 100644 --- a/index.ts +++ b/index.ts @@ -2789,9 +2789,11 @@ const memoryLanceDBProPlugin = { // to avoid contributing to the post-reset startup race on Discord channels. // Discord thread resets are handled separately by the OpenClaw core's // postRotationStartupUntilMs mechanism (PR #49001). - const provider = typeof contextForLog.Provider === "string" ? contextForLog.Provider : ""; - const messageThreadId = contextForLog.MessageThreadId; - if (provider === "discord" && (messageThreadId == null || messageThreadId === "")) { + // Note: Provider lives in sessionEntry.Provider; MessageThreadId lives in + // sessionEntry.threadId (populated from ctx.MessageThreadId at session creation). + const provider = contextForLog.sessionEntry?.Provider ?? ""; + const threadId = contextForLog.sessionEntry?.threadId; + if (provider === "discord" && (threadId == null || threadId === "")) { api.logger.info( `self-improvement: command:${action} skipped on Discord channel (non-thread) reset to avoid startup race; use /new in thread or restart gateway if startup is incomplete` );