fix: keep slack off-mode top-level turns in one session (#32193) (thanks @bmendonca3)

This commit is contained in:
Peter Steinberger
2026-03-02 22:05:09 +00:00
parent 29342c37b5
commit 2c39731846
2 changed files with 18 additions and 0 deletions

View File

@@ -106,6 +106,7 @@ Docs: https://docs.openclaw.ai
- Telegram/models picker callbacks: keep long model buttons selectable by falling back to compact callback payloads and resolving provider ids on selection (with provider re-prompt on ambiguity), avoiding Telegram 64-byte callback truncation failures. (#31857) Thanks @bmendonca3.
- WhatsApp/inbound self-message context: propagate inbound `fromMe` through the web inbox pipeline and annotate direct self messages as `(self)` in envelopes so agents can distinguish owner-authored turns from contact turns. (#32167) Thanks @scoootscooob.
- Slack/thread context payloads: only inject thread starter/history text on first thread turn for new sessions while preserving thread metadata, reducing repeated context-token bloat on long-lived thread sessions. (#32133) Thanks @sourman.
- Slack/session routing: keep top-level channel messages in one shared session when `replyToMode=off`, while preserving thread-scoped keys for true thread replies and non-off modes. (#32193) Thanks @bmendonca3.
- Slack/inbound debounce routing: isolate top-level non-DM message debounce keys by message timestamp to avoid cross-thread collisions, preserve DM batching, and flush pending top-level buffers before immediate non-debounce follow-ups to keep ordering stable. (#31951) Thanks @scoootscooob.
- OpenRouter/x-ai compatibility: skip `reasoning.effort` injection for `x-ai/*` models (for example Grok) so OpenRouter requests no longer fail with invalid-arguments errors on unsupported reasoning params. (#32054) Thanks @scoootscooob.
- Mentions/Slack formatting hardening: add null-safe guards for runtime text normalization paths so malformed/undefined text payloads do not crash mention stripping or mrkdwn conversion. (#31865) Thanks @stone-jin.

View File

@@ -100,6 +100,23 @@ describe("thread-level session keys", () => {
expect(sessionKey).toContain(":thread:1770408530.000000");
});
it("keeps top-level channel turns thread-scoped when replyToMode=first", async () => {
const ctx = buildCtx({ replyToMode: "first" });
ctx.resolveUserName = async () => ({ name: "Dora" });
const account = createSlackTestAccount({ replyToMode: "first" });
const prepared = await prepareSlackMessage({
ctx,
account,
message: buildChannelMessage({ ts: "1770408531.000000" }),
opts: { source: "message" },
});
expect(prepared).toBeTruthy();
const sessionKey = prepared!.ctxPayload.SessionKey as string;
expect(sessionKey).toContain(":thread:1770408531.000000");
});
it("does not add thread suffix for DMs when replyToMode=off", async () => {
const ctx = buildCtx({ replyToMode: "off" });
ctx.resolveUserName = async () => ({ name: "Carol" });