Commit Graph
237 Commits
Author SHA1 Message Date
Peter Steinberger 0e4f3ccbdf refactor: dedupe media and request-body test scaffolding 2026-02-22 18:37:25 +00:00
89a1e99815 fix(slack): finalize replyToMode off threading behavior (#23799)
* fix: make replyToMode 'off' actually prevent threading in Slack

Three independent bugs caused Slack replies to always create threads
even when replyToMode was set to 'off':

1. Typing indicator created threads via statusThreadTs fallback (#16868)
   - resolveSlackThreadTargets fell back to messageTs for statusThreadTs
   - 'is typing...' was posted as thread reply, creating a thread
   - Fix: remove messageTs fallback, let statusThreadTs be undefined

2. [[reply_to_current]] tags bypassed replyToMode entirely (#16080)
   - Slack dock had allowExplicitReplyTagsWhenOff: true
   - Reply tags from system prompt always threaded regardless of config
   - Fix: set allowExplicitReplyTagsWhenOff to false for Slack

3. Contradictory replyToMode defaults in codebase (#20827)
   - monitor/provider.ts defaulted to 'all'
   - accounts.ts defaulted to 'off' (matching docs)
   - Fix: align provider.ts default to 'off' per documentation

Fixes: openclaw/openclaw#16868, openclaw/openclaw#16080, openclaw/openclaw#20827

* fix(slack): respect replyToMode in DMs even with typing indicator thread

When replyToMode is 'off' in DMs, replies should stay in the main
conversation even when the typing indicator creates a thread context.

Previously, when incomingThreadTs was set (from the typing indicator's
thread), replyToMode was forced to 'all', causing all replies to go
into the thread.

Now, for direct messages, the user's configured replyToMode is always
respected. For channels/groups, the existing behavior is preserved
(stay in thread if already in one).

This fix:
- Keeps the typing indicator working (statusThreadTs fallback preserved)
- Prevents DM replies from being forced into threads
- Maintains channel thread continuity

Fixes #16868

* refactor(slack): eliminate redundant resolveSlackThreadContext call

- Add isThreadReply to resolveSlackThreadTargets return value
- Remove duplicate call in dispatch.ts
- Addresses greptile review feedback with cleaner DRY approach

* docs(slack): add JSDoc to resolveSlackThreadTargets

Document return values including isThreadReply distinction between
genuine user thread replies vs bot status message thread context.

* docs(changelog): record Slack replyToMode off threading fixes

---------

Co-authored-by: James <[email protected]>
Co-authored-by: theoseo <[email protected]>
2026-02-22 13:27:50 -05:00
Vincent KocandRobClawd cd7b2814af fix(slack): preserve string thread context in queue + DM route (#23804)
* fix(slack): preserve thread_ts in queue drain and deliveryContext

Two related fixes for Slack thread reply routing:

1. Queue drain drops string thread_ts (#11195)
   - `typeof threadId === "number"` in drain.ts only matches Telegram numeric
     topic IDs. Slack thread_ts is a string like "1770474140.187459" which
     fails the check, causing threadKey to become empty.
   - Changed to `threadId != null && threadId !== ""` to accept both number
     and string thread IDs.
   - Applies to all 3 occurrences in drain.ts: cross-channel detection,
     thread key building, and collected originatingThreadId extraction.

2. DM deliveryContext missing thread_ts (#10837)
   - updateLastRoute calls for Slack DMs in both prepare.ts and dispatch.ts
     built deliveryContext without threadId, so the session's delivery context
     never included thread_ts for DM threads.
   - Added threadId from threadContext.messageThreadId / ctxPayload.MessageThreadId
     to both updateLastRoute call sites.

Tests: 3 new cases in queue.collect-routing.test.ts
- Collects messages with matching string thread_ts (same Slack thread)
- Separates messages with different string thread_ts (different threads)
- Treats empty string threadId same as absent

Closes #10837, closes #11195

* fix(slack): preserve string thread context in queue + DM route updates

---------

Co-authored-by: RobClawd <[email protected]>
2026-02-22 13:26:31 -05:00
Peter Steinberger 296b19e413 test: dedupe gateway browser discord and channel coverage 2026-02-22 17:11:54 +00:00
Peter Steinberger d116bcfb14 refactor(runtime): consolidate followup, gateway, and provider dedupe paths 2026-02-22 14:08:51 +00:00
Peter Steinberger 6dd36a6b77 refactor(channels): reuse runtime group policy helpers 2026-02-22 12:44:23 +01:00
Peter Steinberger 85e5ed3f78 refactor(channels): centralize runtime group policy handling 2026-02-22 12:35:41 +01:00
Peter Steinberger 777817392d fix: fail closed missing provider group policy across message channels (#23367) (thanks @bmendonca3) 2026-02-22 12:21:04 +01:00
Brian Mendonca 3700151ec0 Channels: fail closed when Slack/Discord config is missing 2026-02-22 12:18:43 +01:00
Peter Steinberger 6c2e999776 refactor(security): unify secure id paths and guard weak patterns 2026-02-22 10:16:19 +01:00
Peter Steinberger ae8d4a8eec fix(security): harden channel token and id generation 2026-02-22 10:16:02 +01:00
Peter Steinberger 089a78c061 test(slack): avoid redundant reset in slash metadata wait case 2026-02-22 08:14:16 +00:00
Peter Steinberger 6f3fed0470 test(slack): use lightweight clear in interactions modal-close case 2026-02-22 08:13:42 +00:00
Peter Steinberger 7cf280805c test: dedupe cron and slack monitor test harness setup 2026-02-22 07:52:12 +00:00
Peter Steinberger 75c1bfbae8 refactor(channels): dedupe message routing and telegram helpers 2026-02-22 07:44:57 +00:00
Peter Steinberger 474ba45a2f refactor(slack): dedupe modal lifecycle interaction handlers 2026-02-22 07:44:56 +00:00
Peter Steinberger a3936264ea test(slack): use lightweight clears for interaction event mock 2026-02-22 07:35:54 +00:00
Robin Waslander daf036a4f6 fix(slash): persist channel metadata from slash command sessions (#23065)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 29fa20c7d773b2aac62dea912e00e438ce8ba9f6
Co-authored-by: hydro13 <[email protected]>
Co-authored-by: obviyus <[email protected]>
Reviewed-by: @obviyus
2026-02-22 10:29:06 +05:30
Vignesh Natarajan c51c2a2dca Slack: preserve slash options receiver binding 2026-02-21 20:01:39 -08:00
Peter Steinberger 0bd9f0d4ac fix: enforce strict allowlist across pairing stores (#23017) 2026-02-22 00:00:23 +01:00
Peter Steinberger 2c14b0cf4c refactor(config): unify streaming config across channels 2026-02-21 19:53:42 +01:00
bbcb3ac6e0 fix(slack): pass recipient_team_id to streaming API calls (#20988)
* fix(slack): pass recipient_team_id and recipient_user_id to streaming API calls

The Slack Agents & AI Apps streaming API (chat.startStream / chat.stopStream)
requires recipient_team_id and recipient_user_id parameters. Without them,
stopStream fails with 'missing_recipient_team_id' (all contexts) or
'missing_recipient_user_id' (DM contexts), causing streamed messages to
disappear after generation completes.

This passes:
- team_id (from auth.test at provider startup, stored in monitor context)
- user_id (from the incoming message sender, for DM recipient identification)

through to the ChatStreamer via recipient_team_id and recipient_user_id options.

Fixes #19839, #20847, #20299, #19791, #20337

AI-assisted: Written with Claude (Opus 4.6) via OpenClaw. Lightly tested
(unit tests pass, live workspace verification in progress).

* fix(slack): disable block streaming when native streaming is active

When Slack native streaming (`chat.startStream`/`stopStream`) is enabled,
`disableBlockStreaming` was set to `false`, which activated the app-level
block streaming pipeline. This pipeline intercepted agent output, sent it
via block replies, then dropped the final payloads that would have flowed
through `deliverWithStreaming` to the Slack streaming API — resulting in
zero replies delivered.

Set `disableBlockStreaming: true` when native streaming is active so the
final reply flows through the Slack streaming API path as intended.

Co-Authored-By: Claude Opus 4.6 <[email protected]>

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>
2026-02-19 14:44:34 -08:00
Peter Steinberger 672b1c5084 refactor: dedupe slack monitor mrkdwn and modal event base 2026-02-19 14:27:36 +00:00
Peter Steinberger 41e68c31db test(channels): dedupe slack arg-menu and discord reply chunk assertions 2026-02-18 13:39:40 +00:00
Peter Steinberger a69e7682c1 refactor(test): dedupe channel and monitor action suites 2026-02-18 04:49:22 +00:00
Peter Steinberger 05b7bd2c22 refactor: dedupe command dispatch and process poll tests 2026-02-18 04:04:14 +00:00
Peter Steinberger 91e9684e8c test: add normalization coverage for shared and slack allow-list 2026-02-18 03:17:54 +00:00
Peter Steinberger 8407eeb33c refactor: extract shared string normalization helpers 2026-02-18 03:17:54 +00:00
Peter Steinberger b8b43175c5 style: align formatting with oxfmt 0.33 2026-02-18 01:34:35 +00:00
Peter Steinberger 31f9be126c style: run oxfmt and fix gate failures 2026-02-18 01:29:02 +00:00
Peter Steinberger 6dcc052bb4 fix: stabilize model catalog and pi discovery auth storage compatibility 2026-02-18 02:09:40 +01:00
Peter Steinberger 1d23934c09 fix: follow-up slack streaming routing/tests (#9972) (thanks @natedenh) 2026-02-18 00:50:22 +01:00
Peter Steinberger bb9a539d1d Merge remote-tracking branch 'prhead/feat/slack-text-streaming'
# Conflicts:
#	docs/channels/slack.md
#	src/config/types.slack.ts
#	src/slack/monitor/message-handler/dispatch.ts
2026-02-18 00:49:30 +01:00
Seb Slight f44e3b2a34 revert: fix models set catalog validation (#19194)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7e3b2ff7afe052097c4414fc64d7e66191e8fcc3
Co-authored-by: sebslight <[email protected]>
Co-authored-by: sebslight <[email protected]>
Reviewed-by: @sebslight
2026-02-17 09:43:41 -05:00
Sebastian cc359d338e test: add fetch mock helper and reaction coverage 2026-02-17 09:02:39 -05:00
cpojer 2a4ca7671e chore: Fix types in tests 35/N. 2026-02-17 15:50:07 +09:00
cpojer 97c8f4999e chore: Fix types in tests 27/N. 2026-02-17 14:31:55 +09:00
cpojer d0cb8c19b2 chore: wtf. 2026-02-17 13:36:48 +09:00
Sebastian ed11e93cf2 chore(format) 2026-02-16 23:20:16 -05:00
cpojer a76a9c375f chore: Fix types in tests 15/N. 2026-02-17 12:00:29 +09:00
cpojer a78839e60c chore: Fix Slack test. 2026-02-17 11:15:15 +09:00
cpojer 01ea808876 chore: Format files. 2026-02-17 10:57:31 +09:00
Peter Steinberger d6226355e6 fix(slack): validate interaction payloads and handle malformed actions 2026-02-17 02:51:00 +01:00
Sebastian 67250f059a fix(slack): scope attachment extraction to forwarded shares 2026-02-16 20:37:08 -05:00
cpojer 90ef2d6bdf chore: Update formatting. 2026-02-17 09:18:40 +09:00
Peter Steinberger 4088c0b89d refactor(core): dedupe schema and command parsing helpers 2026-02-16 23:48:43 +00:00
Tom Peri b57d29d833 fix(slack): extract text and media from forwarded message attachments 2026-02-16 23:55:34 +01:00
Colin 1faf8e8e9d Slack: add external select flow for large arg menus 2026-02-16 23:51:44 +01:00
Colin 7a4efbb030 Slack: capture workflow button interaction metadata 2026-02-16 23:51:44 +01:00
Colin bd20c1e24d Slack: include stacked modal lifecycle context 2026-02-16 23:51:44 +01:00