diff --git a/CHANGELOG.md b/CHANGELOG.md index bab85ad73..747d3c794 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ Docs: https://docs.openclaw.ai - Plugins/SDK subpath parity: add channel-specific plugin SDK subpaths for Discord, Slack, Signal, iMessage, WhatsApp, and LINE; migrate bundled plugin entrypoints to scoped subpaths/core with CI guardrails; and keep `openclaw/plugin-sdk` root import compatibility for existing external plugins. (#33737) thanks @gumadeiras. - Routing/session duplicate suppression synthesis: align shared session delivery-context inheritance, channel-paired route-field merges, and reply-surface target matching so dmScope=main turns avoid cross-surface duplicate replies while thread-aware forwarding keeps intended routing semantics. (from #33629, #26889, #17337, #33250) Thanks @Yuandiaodiaodiao, @kevinwildenradt, @Glucksberg, and @bmendonca3. - Routing/legacy session route inheritance: preserve external route metadata inheritance for legacy channel session keys (`agent:::` and `...:thread:`) so `chat.send` does not incorrectly fall back to webchat when valid delivery context exists. Follow-up to #33786. +- Routing/legacy route guard tightening: require legacy session-key channel hints to match the saved delivery channel before inheriting external routing metadata, preventing custom namespaced keys like `agent::work:` from inheriting stale non-webchat routes. - Security/auth labels: remove token and API-key snippets from user-facing auth status labels so `/status` and `/models` do not expose credential fragments. (#33262) thanks @cu1ch3n. - Auth/credential semantics: align profile eligibility + probe diagnostics with SecretRef/expiry rules and harden browser download atomic writes. (#33733) thanks @joshavant. - Security/audit denyCommands guidance: suggest likely exact node command IDs for unknown `gateway.nodes.denyCommands` entries so ineffective denylist entries are easier to correct. (#29713) thanks @liquidhorizon88-bot. diff --git a/src/gateway/server-methods/chat.directive-tags.test.ts b/src/gateway/server-methods/chat.directive-tags.test.ts index b6f6fce38..0ea0e0181 100644 --- a/src/gateway/server-methods/chat.directive-tags.test.ts +++ b/src/gateway/server-methods/chat.directive-tags.test.ts @@ -570,7 +570,9 @@ describe("chat directive tag stripping for non-streaming final payloads", () => context, respond, idempotencyKey: "idem-custom-no-cross-route", - sessionKey: "agent:main:work", + // Keep a second custom scope token so legacy-shape detection is exercised. + // "agent:main:work" only yields one rest token and does not hit that path. + sessionKey: "agent:main:work:ticket-123", expectBroadcast: false, }); diff --git a/src/gateway/server-methods/chat.ts b/src/gateway/server-methods/chat.ts index 7c8db7344..db78d7966 100644 --- a/src/gateway/server-methods/chat.ts +++ b/src/gateway/server-methods/chat.ts @@ -876,7 +876,9 @@ export const chatHandlers: GatewayRequestHandlers = { CHANNEL_SCOPED_SESSION_SHAPES.has(part), ); const hasLegacyChannelPeerShape = - !isChannelScopedSession && typeof sessionScopeParts[1] === "string"; + !isChannelScopedSession && + typeof sessionScopeParts[1] === "string" && + sessionChannelHint === routeChannelCandidate; // Only inherit prior external route metadata for channel-scoped sessions. // Channel-agnostic sessions (main, direct:, etc.) can otherwise // leak stale routes across surfaces.