fix(discord): add messageId to debounce key to prevent duplicate processing#1
Open
fix(discord): add messageId to debounce key to prevent duplicate processing#1
Conversation
…gement (openclaw#22201) * feat(context-engine): add ContextEngine interface and registry Introduce the pluggable ContextEngine abstraction that allows external plugins to register custom context management strategies. - ContextEngine interface with lifecycle methods: bootstrap, ingest, ingestBatch, afterTurn, assemble, compact, prepareSubagentSpawn, onSubagentEnded, dispose - Module-level singleton registry with registerContextEngine() and resolveContextEngine() (config-driven slot selection) - LegacyContextEngine: pass-through implementation wrapping existing compaction behavior for 100% backward compatibility - ensureContextEnginesInitialized() guard for safe one-time registration - 19 tests covering contract, registry, resolution, and legacy parity * feat(plugins): add context-engine slot and registerContextEngine API Wire the ContextEngine abstraction into the plugin system so external plugins can register context engines via the standard plugin API. - Add 'context-engine' to PluginKind union type - Add 'contextEngine' slot to PluginSlotsConfig (default: 'legacy') - Wire registerContextEngine() through OpenClawPluginApi - Export ContextEngine types from plugin-sdk for external consumers - Restore proper slot-based resolution in registry * feat(context-engine): wire ContextEngine into agent run lifecycle Integrate the ContextEngine abstraction into the core agent run path: - Resolve context engine once per run (reused across retries) - Bootstrap: hydrate canonical store from session file on first run - Assemble: route context assembly through pluggable engine - Auto-compaction guard: disable built-in auto-compaction when the engine declares ownsCompaction (prevents double-compaction) - AfterTurn: post-turn lifecycle hook for ingest + background compaction decisions - Overflow compaction: route through contextEngine.compact() - Dispose: clean up engine resources in finally block - Notify context engine on subagent lifecycle events Legacy engine: all lifecycle methods are pass-through/no-op, preserving 100% backward compatibility for users without a context engine plugin. * feat(plugins): add scoped subagent methods and gateway request scope Expose runtime.subagent.{run, waitForRun, getSession, deleteSession} so external plugins can spawn sub-agent sessions without raw gateway dispatch access. Uses AsyncLocalStorage request-scope bridge to dispatch internally via handleGatewayRequest with a synthetic operator client. Methods are only available during gateway request handling. - Symbol.for-backed global singleton for cross-module-reload safety - Fallback gateway context for non-WS dispatch paths (Telegram/WhatsApp) - Set gateway request scope for all handlers, not just plugin handlers - 3 staleness tests for fallback context hardening * feat(context-engine): route /compact and sessions.get through context engine Wire the /compact command and sessions.get handler through the pluggable ContextEngine interface. - Thread tokenBudget and force parameters to context engine compact - Route /compact through contextEngine.compact() when registered - Wire sessions.get as runtime alias for plugin subagent dispatch - Add .pebbles/ to .gitignore * style: format with oxfmt 0.33.0 Fix duplicate import (ControlUiRootState in server.impl.ts) and import ordering across all changed files. * fix: update extension test mocks for context-engine types Add missing subagent property to bluebubbles PluginRuntime mock. Add missing registerContextEngine to lobster OpenClawPluginApi mock. * fix(subagents): keep deferred delete cleanup retryable * style: format run attempt for CI * fix(rebase): remove duplicate embedded-run imports * test: add missing gateway context mock export * fix: pass resolved auth profile into afterTurn compaction Ensure the embedded runner forwards resolved auth profile context into legacy context-engine compaction params on the normal afterTurn path, matching overflow compaction behavior. This allows downstream LCM summarization to use the intended provider auth/profile consistently. Also fix strict TS typing in external-link token dedupe and align an attempt unit test reasoningLevel value with the current ReasoningLevel enum. Regeneration-Prompt: | We were debugging context-engine compaction where downstream summary calls were missing the right auth/profile context in normal afterTurn flow, while overflow compaction already propagated it. Preserve current behavior and keep changes additive: thread the resolved authProfileId through run -> attempt -> legacy compaction param builder without broad refactors. Add tests that prove the auth profile is included in afterTurn legacy params and that overflow compaction still passes it through run attempts. Keep existing APIs stable, and only adjust small type issues needed for strict compilation. * fix: remove duplicate imports from rebase * feat: add context-engine system prompt additions * fix(rebase): dedupe attempt import declarations * test: fix fetch mock typing in ollama autodiscovery * fix(test): add registerContextEngine to diffs extension mock APIs * test(windows): use path.delimiter in ios-team-id fixture PATH * test(cron): add model formatting and precedence edge case tests Covers: - Provider/model string splitting (whitespace, nested paths, empty segments) - Provider normalization (casing, aliases like bedrock→amazon-bedrock) - Anthropic model alias normalization (opus-4.5→claude-opus-4-5) - Precedence: job payload > session override > config default - Sequential runs with different providers (CI flake regression pattern) - forceNew session preserving stored model overrides - Whitespace/empty model string edge cases - Config model as string vs object format * test(cron): fix model formatting test config types * test(phone-control): add registerContextEngine to mock API * fix: re-export ChannelKind from config-reload-plan * fix: add subagent mock to plugin-runtime-mock test util * docs: add changelog fragment for context engine PR openclaw#22201
…aw#37867) * fix(session): require strict direct key routing shapes * test(session): cover direct route poisoning cases
…ge.py (openclaw#18706) The MEDIA: output token must appear at line start with no space after the colon for OpenClaw's splitMediaFromOutput parser to extract the file path and auto-attach media on outbound chat channels (Discord, Telegram, WhatsApp, etc.). The script was printing 'MEDIA: /path' (with space), which while tolerated by the regex, does not match the canonical 'MEDIA:/path' format used by all other skills (e.g. openai-image-gen) and tested in the codebase (pi-embedded-subscribe.tools.media.test.ts, media/parse.test.ts). Also updated the comment to clarify the format constraint.
…penclaw#36880) * nano-banana-pro: respect explicit --resolution when editing images * Changelog: note nano banana resolution fix * Update CHANGELOG.md --------- Co-authored-by: Vincent Koc <[email protected]>
* Telegram: default media cap to 100MB * Telegram: honor outbound mediaMaxMb * Discord: add shared media upload cap * Discord: pass mediaMaxMb to outbound sends * Telegram: cover outbound media cap sends * Discord: cover media upload cap config * Docs: update Telegram media cap guide * Docs: update Telegram config reference * Changelog: note media upload cap fix * Docs: note Discord upload cap behavior
…#36762) * openai-image-gen: validate --background and --style inputs * Skills/openai-image-gen: warn on ignored background and style flags * Skills/openai-image-gen: cover empty and warning cases * Changelog: note openai image flag validation * Skills/openai-image-gen: fix Python import order --------- Co-authored-by: Vincent Koc <[email protected]>
* WhatsApp: add media cap helper * WhatsApp: cap outbound media loads * WhatsApp: align auto-reply media caps * WhatsApp: add outbound media cap test * WhatsApp: update auto-reply cap tests * Docs: update WhatsApp media caps * Changelog: note WhatsApp media cap fix
…38117) * Infra: tighten npm registry spec parsing * Infra: block implicit prerelease npm installs * Plugins: cover prerelease install policy * Infra: add npm registry spec tests * Hooks: cover prerelease install policy * Docs: clarify plugin guide version policy * Docs: clarify plugin install version policy * Docs: clarify hooks install version policy * Docs: clarify hook pack version policy
) * openai-image-gen: validate and normalize output format * Skills/openai-image-gen: cover output-format edge cases * Changelog: note openai image output format validation --------- Co-authored-by: Vincent Koc <[email protected]>
* Media: normalize HEIC input images * Gateway: accept HEIC image input schema * Media: add HEIC input normalization tests * Gateway: cover HEIC input schema parity * Docs: document HEIC input image support * Changelog: note HEIC input image fix
* Media: scope HEIC MIME sniffing * Media: hermeticize HEIC input tests * Gateway: fix HEIC image budget accounting * Gateway: add HEIC image budget regression test * Changelog: note HEIC follow-up fix
openclaw#38199) * fix(gateway): keep probe routes reachable with root-mounted control ui * Changelog: add root-mounted probe precedence fix entry * Update CHANGELOG.md
* Changelog: add channel-backed readiness probe entry * Gateway: add channel-backed readiness probes * Docs: describe readiness probe behavior * Gateway: add readiness probe regression tests * Changelog: dedupe gateway probe entries * Docs: fix readiness startup grace description * Changelog: remove stale readiness entry * Gateway: cover readiness hardening * Gateway: harden readiness probes
The dashboard screenshot uses a relative path `src="whatsapp-openclaw.jpg"` which resolves correctly on the English root page but produces 404 on zh-CN and ja-JP pages because Mintlify prepends the language subdirectory to the CDN path. Change to absolute path `/whatsapp-openclaw.jpg` in all three index files, consistent with other images on the same page that already use absolute paths (e.g. `/assets/openclaw-logo-text-dark.png`).
…penclaw#38267) The `timeout` property is not part of the Lark SDK method signatures, causing TS2353 errors. The client-level `httpTimeoutMs` already applies the timeout to all requests. Co-authored-by: Claude Opus 4.6 <[email protected]>
…create auto-grant (openclaw#32915) Merged via squash. Prepared head SHA: efb2293 Co-authored-by: cszhouwei <[email protected]> Co-authored-by: jalehman <[email protected]> Reviewed-by: @jalehman
* fix(agents): skip auth-profile failure on overload * fix(agents): note overload auth-profile fallback fix * fix(agents): classify overloaded failures separately * fix(agents): back off before overload failover * fix(agents): tighten overload probe and backoff state * fix(agents): persist overloaded cooldown across runs * fix(agents): tighten overloaded status handling * test(agents): add overload regression coverage * fix(agents): restore runner imports after rebase * test(agents): add overload fallback integration coverage * fix(agents): harden overloaded failover abort handling * test(agents): tighten overload classifier coverage * test(agents): cover all-overloaded fallback exhaustion * fix(cron): retry overloaded fallback summaries * fix(cron): treat HTTP 529 as overloaded retry
* Dead code: remove unused provider runtime policy helper * Dead code: remove unused shared env writer * Dead code: remove unused auth store path collector
…penclaw#34556) Merged via squash. Prepared head SHA: 491bb28 Co-authored-by: efe-arv <[email protected]> Co-authored-by: jalehman <[email protected]> Reviewed-by: @jalehman
…aw#36280) (openclaw#36316) * fix: strip skill-injected env vars from ACP harness spawn env Skill apiKey entries (e.g., openai-image-gen with primaryEnv=OPENAI_API_KEY) are set on process.env during agent runs and only reverted after the run completes. ACP harnesses like Codex CLI inherit these vars, causing them to silently use API billing instead of their own auth (e.g., OAuth). The fix tracks which env vars are actively injected by skill overrides in a module-level Set (activeSkillEnvKeys) and strips them in resolveAcpClientSpawnEnv() before spawning ACP child processes. Fixes openclaw#36280 * ACP: type spawn env for stripped keys * Skills: cover active env key lifecycle * Changelog: note ACP skill env isolation * ACP: preserve shell marker after env stripping --------- Co-authored-by: Vincent Koc <[email protected]>
…ools (openclaw#26331) Merged via squash. Prepared head SHA: 1fbe1c7 Co-authored-by: widingmarcus-cyber <[email protected]> Co-authored-by: jalehman <[email protected]> Reviewed-by: @jalehman
openclaw#34977) Merged via squash. Prepared head SHA: 1c14094 Co-authored-by: sp-hk2ldn <[email protected]> Co-authored-by: jalehman <[email protected]> Reviewed-by: @jalehman
* Config: add supportsTools compat flag * Agents: add model tool support helper * Venice: sync discovery and fallback metadata * Agents: skip tools for unsupported models * Changelog: note Venice provider hardening * Update CHANGELOG.md * Venice: cap degraded discovery metadata * Apply suggestion from @greptile-apps[bot] Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * Venice: tolerate partial discovery capabilities * Venice: tolerate missing discovery specs --------- Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
…mplifying NO_REPLY into queue overflow (openclaw#33295) * fix(imessage): prevent echo loop from leaking internal metadata and amplifying NO_REPLY into queue overflow - Add outbound sanitization at channel boundary (sanitize-outbound.ts): strips thinking/reasoning tags, relevant-memories tags, model-specific separators (+#+#), and assistant role markers before iMessage delivery - Add inbound reflection guard (reflection-guard.ts): detects and drops messages containing assistant-internal markers that indicate a reflected outbound message, preventing recursive echo amplification - Harden echo cache: increase text TTL from 5s to 30s to catch delayed reflections that previously expired before the echo could be detected - Add loop rate limiter (loop-rate-limiter.ts): per-conversation rapid-fire detection that suppresses conversations exceeding threshold within a time window, acting as a safety net against amplification Closes openclaw#33281 * fix(imessage): address review — stricter reflection regex, loop-aware rate limiter - Reflection guard: require closing > bracket on thinking/final/memory tag patterns to prevent false-positives on user phrases like '<final answer>' or '<thought experiment>' (openclaw#33295 review) - Rate limiter: only record echo/reflection/from-me drops instead of all dispatches, so the limiter acts as a loop-specific escalation mechanism rather than a general throttle on normal conversation velocity (openclaw#33295 review) * Changelog: add iMessage echo-loop hardening entry * iMessage: restore short echo-text TTL * iMessage: ignore reflection markers in code --------- Co-authored-by: Vincent Koc <[email protected]>
* Docs: refresh Venice default model guidance * Venice: switch default model to Kimi K2.5 * Changelog: credit Venice default refresh
…essing Fixes openclaw#37844 The debounce key was missing messageId, causing duplicate message processing when Discord Gateway reconnects or retries delivery. Key now includes messageId: discord:{accountId}:{channelId}:{authorId}:{messageId}
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.
Summary
Fixes openclaw#37844
The debounce key was missing messageId, causing duplicate message processing when Discord Gateway reconnects or retries message delivery.
Changes
discord:{accountId}:{channelId}:{authorId}:{messageId}Testing
🤖 AI-assisted PR