@openclaw/slack 2026.5.16-beta.3 → 2026.5.16-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/{action-runtime-p39JLqwf.js → action-runtime-0RLkDKyA.js} +1 -1
  2. package/dist/action-runtime.runtime-DpzOXqtk.js +2 -0
  3. package/dist/{actions-BCRbHv1Q.js → actions-Chs6DbrP.js} +1 -1
  4. package/dist/{actions.runtime-CpywQR3D.js → actions.runtime-BsbIDsmT.js} +1 -1
  5. package/dist/api.js +5 -5
  6. package/dist/{approval-handler.runtime-DXrdRbkT.js → approval-handler.runtime-BmCbRrbT.js} +1 -1
  7. package/dist/{channel-DoFtZGpw.js → channel-DUS8ZO45.js} +9 -9
  8. package/dist/channel-plugin-api.js +1 -1
  9. package/dist/{channel.setup-BDL4qn9U.js → channel.setup-qGOC05UK.js} +2 -2
  10. package/dist/inbound-contract-test-api.js +2 -2
  11. package/dist/{monitor-Djnd8pGL.js → monitor-BhEzWuv0.js} +3 -3
  12. package/dist/{outbound-adapter-CHm6e-0Q.js → outbound-adapter-BoDXPksS.js} +1 -1
  13. package/dist/outbound-payload-test-api.js +1 -1
  14. package/dist/{outbound-payload.test-harness-C0CW7_CE.js → outbound-payload.test-harness-C7Izm95Q.js} +1 -1
  15. package/dist/{pipeline.runtime-DJcwOZky.js → pipeline.runtime-Bq754VH8.js} +40 -25
  16. package/dist/{prepare-Or_6_XXl.js → prepare-BcznR9ok.js} +125 -18
  17. package/dist/{prepare.test-helpers-CU1qB54Q.js → prepare.test-helpers-D807wdul.js} +1 -1
  18. package/dist/{provider-3Y7c15_J.js → provider-BFnE2bgI.js} +114 -3
  19. package/dist/{replies-Fg1T3ZzU.js → replies-2ve_YcHy.js} +8 -5
  20. package/dist/{room-context-Cd8jFpS-.js → room-context-BI26wVBb.js} +83 -2
  21. package/dist/runtime-api.js +5 -5
  22. package/dist/{send-CxXFbqN1.js → send-C5PzphgC.js} +5 -0
  23. package/dist/send.runtime-Bgf0P22e.js +2 -0
  24. package/dist/send.runtime-DsEXD6MR.js +2 -0
  25. package/dist/{setup-core-B7pou7oe.js → setup-core-az0LCrNr.js} +21 -2
  26. package/dist/setup-plugin-api.js +1 -1
  27. package/dist/{setup-surface-CJS-L7PA.js → setup-surface-Cdq_mfjx.js} +2 -2
  28. package/dist/{shared-BEabCPK3.js → shared-BuNoOmas.js} +1 -1
  29. package/dist/{slash-dispatch.runtime-Cg7uU92H.js → slash-dispatch.runtime-CcbE1HtP.js} +1 -1
  30. package/dist/test-api.js +6 -6
  31. package/package.json +4 -4
  32. package/dist/action-runtime.runtime-BzrPV3EA.js +0 -2
  33. package/dist/send.runtime-BHCPpSj_.js +0 -2
  34. package/dist/send.runtime-CDG5AgU3.js +0 -2
@@ -28,7 +28,7 @@ function sameSlackChannelTarget(targetChannel, currentChannelId) {
28
28
  let slackActionsRuntimePromise;
29
29
  let slackAccountsRuntimePromise;
30
30
  function loadSlackActionsRuntime() {
31
- slackActionsRuntimePromise ??= import("./actions.runtime-CpywQR3D.js");
31
+ slackActionsRuntimePromise ??= import("./actions.runtime-BsbIDsmT.js");
32
32
  return slackActionsRuntimePromise;
33
33
  }
34
34
  function loadSlackAccountsRuntime() {
@@ -0,0 +1,2 @@
1
+ import { t as handleSlackAction } from "./action-runtime-0RLkDKyA.js";
2
+ export { handleSlackAction };
@@ -2,7 +2,7 @@ import { t as __exportAll } from "./rolldown-runtime-CiIaOW0V.js";
2
2
  import { a as resolveSlackAccount, d as resolveSlackBotToken } from "./accounts-yk5K3wQU.js";
3
3
  import { a as validateSlackBlocksArray, o as SLACK_TEXT_LIMIT, s as truncateSlackText } from "./thread-ts-As_dcNbD.js";
4
4
  import { a as getSlackWriteClient, r as createSlackWebClient } from "./client-C_IaJbi5.js";
5
- import { c as buildSlackBlocksFallbackText, t as sendMessageSlack } from "./send-CxXFbqN1.js";
5
+ import { c as buildSlackBlocksFallbackText, t as sendMessageSlack } from "./send-C5PzphgC.js";
6
6
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
7
7
  import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
8
8
  import { logVerbose, logVerbose as logVerbose$1 } from "openclaw/plugin-sdk/runtime-env";
@@ -1,2 +1,2 @@
1
- import { a as listSlackEmojis, c as pinSlackMessage, d as removeOwnSlackReactions, f as removeSlackReaction, i as getSlackMemberInfo, l as reactSlackMessage, m as unpinSlackMessage, n as downloadSlackFile, o as listSlackPins, p as sendSlackMessage, r as editSlackMessage, s as listSlackReactions, t as deleteSlackMessage, u as readSlackMessages } from "./actions-BCRbHv1Q.js";
1
+ import { a as listSlackEmojis, c as pinSlackMessage, d as removeOwnSlackReactions, f as removeSlackReaction, i as getSlackMemberInfo, l as reactSlackMessage, m as unpinSlackMessage, n as downloadSlackFile, o as listSlackPins, p as sendSlackMessage, r as editSlackMessage, s as listSlackReactions, t as deleteSlackMessage, u as readSlackMessages } from "./actions-Chs6DbrP.js";
2
2
  export { deleteSlackMessage, downloadSlackFile, editSlackMessage, getSlackMemberInfo, listSlackEmojis, listSlackPins, listSlackReactions, pinSlackMessage, reactSlackMessage, readSlackMessages, removeOwnSlackReactions, removeSlackReaction, sendSlackMessage, unpinSlackMessage };
package/dist/api.js CHANGED
@@ -2,7 +2,7 @@ import { a as resolveSlackAccount, i as resolveDefaultSlackAccountId, l as resol
2
2
  import { t as inspectSlackAccount } from "./account-inspect-BJyQLSkN.js";
3
3
  import { i as resolveSlackChannelId, n as normalizeSlackMessagingTarget, r as parseSlackTarget, t as looksLikeSlackTargetId } from "./target-parsing-CQmv-iSm.js";
4
4
  import "./targets-B1tYCAr6.js";
5
- import { i as resolveSlackChannelType, n as buildSlackThreadingToolContext, o as resolveSlackAutoThreadId, r as __resetSlackChannelTypeCacheForTest, t as slackPlugin } from "./channel-DoFtZGpw.js";
5
+ import { i as resolveSlackChannelType, n as buildSlackThreadingToolContext, o as resolveSlackAutoThreadId, r as __resetSlackChannelTypeCacheForTest, t as slackPlugin } from "./channel-DUS8ZO45.js";
6
6
  import { n as resolveSlackGroupRequireMention, r as resolveSlackGroupToolPolicy } from "./reply-blocks-BFaJ_ejG.js";
7
7
  import { n as buildSlackPresentationBlocks, t as buildSlackInteractiveBlocks } from "./blocks-render-BAVfd6r0.js";
8
8
  import { a as validateSlackBlocksArray, i as parseSlackBlocksInput, r as SLACK_MAX_BLOCKS } from "./thread-ts-As_dcNbD.js";
@@ -10,12 +10,12 @@ import { n as extractSlackToolSend, r as listSlackMessageActions } from "./messa
10
10
  import { n as isSlackInteractiveRepliesEnabled, r as parseSlackOptionsLine, t as compileSlackInteractiveReplies } from "./interactive-replies-BSg5hXhj.js";
11
11
  import { a as getSlackWriteClient, c as resolveSlackWebClientOptions, i as createSlackWriteClient, l as resolveSlackWriteClientOptions, n as createSlackTokenCacheKey, o as SLACK_DEFAULT_RETRY_OPTIONS, r as createSlackWebClient, s as SLACK_WRITE_RETRY_OPTIONS, t as clearSlackWriteClientCacheForTest } from "./client-C_IaJbi5.js";
12
12
  import { a as normalizeSlackSlug, i as normalizeSlackAllowOwnerEntry, n as normalizeAllowList, o as resolveSlackAllowListMatch, r as normalizeAllowListLower, s as resolveSlackUserAllowed, t as allowListMatches } from "./allow-list-nwXs_eCP.js";
13
- import { t as slackSetupPlugin } from "./channel.setup-BDL4qn9U.js";
14
- import { a as recordSlackThreadParticipation, n as clearSlackThreadParticipationCache, r as hasSlackThreadParticipation } from "./send-CxXFbqN1.js";
15
- import { a as listSlackEmojis, c as pinSlackMessage, d as removeOwnSlackReactions, f as removeSlackReaction, i as getSlackMemberInfo, l as reactSlackMessage, m as unpinSlackMessage, n as downloadSlackFile, o as listSlackPins, p as sendSlackMessage, r as editSlackMessage, s as listSlackReactions, t as deleteSlackMessage, u as readSlackMessages } from "./actions-BCRbHv1Q.js";
13
+ import { t as slackSetupPlugin } from "./channel.setup-qGOC05UK.js";
14
+ import { a as recordSlackThreadParticipation, n as clearSlackThreadParticipationCache, r as hasSlackThreadParticipation } from "./send-C5PzphgC.js";
15
+ import { a as listSlackEmojis, c as pinSlackMessage, d as removeOwnSlackReactions, f as removeSlackReaction, i as getSlackMemberInfo, l as reactSlackMessage, m as unpinSlackMessage, n as downloadSlackFile, o as listSlackPins, p as sendSlackMessage, r as editSlackMessage, s as listSlackReactions, t as deleteSlackMessage, u as readSlackMessages } from "./actions-Chs6DbrP.js";
16
16
  import { n as listSlackDirectoryGroupsFromConfig, r as listSlackDirectoryPeersFromConfig } from "./directory-config-CMvFiswf.js";
17
17
  import { n as registerSlackHttpHandler, r as normalizeSlackWebhookPath, t as handleSlackHttpRequest } from "./registry-D2cWOLZV.js";
18
18
  import { t as probeSlack } from "./probe-FL4sUJsH.js";
19
19
  import { t as collectSlackSecurityAuditFindings } from "./security-audit-BJzADAw3.js";
20
- import { n as resolveSlackRuntimeGroupPolicy } from "./provider-3Y7c15_J.js";
20
+ import { n as resolveSlackRuntimeGroupPolicy } from "./provider-BFnE2bgI.js";
21
21
  export { SLACK_DEFAULT_RETRY_OPTIONS, SLACK_MAX_BLOCKS, SLACK_WRITE_RETRY_OPTIONS, __resetSlackChannelTypeCacheForTest, allowListMatches, buildSlackInteractiveBlocks, buildSlackPresentationBlocks, buildSlackThreadingToolContext, clearSlackThreadParticipationCache, clearSlackWriteClientCacheForTest, collectSlackSecurityAuditFindings, compileSlackInteractiveReplies, createSlackTokenCacheKey, createSlackWebClient, createSlackWriteClient, deleteSlackMessage, downloadSlackFile, editSlackMessage, extractSlackToolSend, getSlackMemberInfo, getSlackWriteClient, handleSlackHttpRequest, hasSlackThreadParticipation, inspectSlackAccount, isSlackInteractiveRepliesEnabled, listEnabledSlackAccounts, listSlackAccountIds, listSlackDirectoryGroupsFromConfig, listSlackDirectoryPeersFromConfig, listSlackEmojis, listSlackMessageActions, listSlackPins, listSlackReactions, looksLikeSlackTargetId, mergeSlackAccountConfig, normalizeAllowList, normalizeAllowListLower, normalizeSlackAllowOwnerEntry, normalizeSlackMessagingTarget, normalizeSlackSlug, normalizeSlackWebhookPath, parseSlackBlocksInput, parseSlackOptionsLine, parseSlackTarget, pinSlackMessage, probeSlack, reactSlackMessage, readSlackMessages, recordSlackThreadParticipation, registerSlackHttpHandler, removeOwnSlackReactions, removeSlackReaction, resolveDefaultSlackAccountId, resolveSlackAccount, resolveSlackAllowListMatch, resolveSlackAutoThreadId, resolveSlackChannelId, resolveSlackChannelType, resolveSlackGroupRequireMention, resolveSlackGroupToolPolicy, resolveSlackReplyToMode, resolveSlackRuntimeGroupPolicy, resolveSlackUserAllowed, resolveSlackWebClientOptions, resolveSlackWriteClientOptions, sendSlackMessage, slackPlugin, slackSetupPlugin, unpinSlackMessage, validateSlackBlocksArray };
@@ -1,6 +1,6 @@
1
1
  import { c as normalizeSlackApproverId, s as isSlackExecApprovalClientEnabled, t as resolveSlackReplyBlocks, u as shouldHandleSlackExecApprovalRequest } from "./reply-blocks-BFaJ_ejG.js";
2
2
  import { s as truncateSlackText } from "./thread-ts-As_dcNbD.js";
3
- import { t as sendMessageSlack } from "./send-CxXFbqN1.js";
3
+ import { t as sendMessageSlack } from "./send-C5PzphgC.js";
4
4
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
5
5
  import { buildChannelApprovalNativeTargetKey } from "openclaw/plugin-sdk/approval-native-runtime";
6
6
  import { logError } from "openclaw/plugin-sdk/logging-core";
@@ -9,8 +9,8 @@ import { n as isSlackInteractiveRepliesEnabled, t as compileSlackInteractiveRepl
9
9
  import { d as PAIRING_APPROVED_MESSAGE, m as resolveConfiguredFromRequiredCredentialStatuses, p as projectCredentialSnapshotFields, r as createSlackWebClient, u as DEFAULT_ACCOUNT_ID } from "./client-C_IaJbi5.js";
10
10
  import { r as normalizeAllowListLower } from "./allow-list-nwXs_eCP.js";
11
11
  import { t as getOptionalSlackRuntime } from "./runtime-DQxkf7k2.js";
12
- import { i as slackSecurityAdapter, n as isSlackPluginAccountConfigured, r as slackConfigAdapter, t as createSlackPluginBase } from "./shared-BEabCPK3.js";
13
- import { i as SLACK_CHANNEL, n as createSlackSetupWizardProxy, r as slackSetupAdapter } from "./setup-core-B7pou7oe.js";
12
+ import { i as slackSecurityAdapter, n as isSlackPluginAccountConfigured, r as slackConfigAdapter, t as createSlackPluginBase } from "./shared-BuNoOmas.js";
13
+ import { i as SLACK_CHANNEL, n as createSlackSetupWizardProxy, r as slackSetupAdapter } from "./setup-core-az0LCrNr.js";
14
14
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
15
15
  import { adaptScopedAccountAccessor } from "openclaw/plugin-sdk/channel-config-helpers";
16
16
  import { buildOutboundBaseSessionKey } from "openclaw/plugin-sdk/routing";
@@ -173,7 +173,7 @@ const slackApprovalCapability = createApproverRestrictedNativeApprovalCapability
173
173
  accountId,
174
174
  request
175
175
  }),
176
- load: async () => (await import("./approval-handler.runtime-DXrdRbkT.js")).slackApprovalNativeRuntime
176
+ load: async () => (await import("./approval-handler.runtime-BmCbRrbT.js")).slackApprovalNativeRuntime
177
177
  })
178
178
  });
179
179
  splitChannelApprovalCapability(slackApprovalCapability);
@@ -340,7 +340,7 @@ async function handleSlackMessageAction(params) {
340
340
  //#region extensions/slack/src/channel-actions.ts
341
341
  let slackActionRuntimePromise$1;
342
342
  async function loadSlackActionRuntime$1() {
343
- slackActionRuntimePromise$1 ??= import("./action-runtime.runtime-BzrPV3EA.js");
343
+ slackActionRuntimePromise$1 ??= import("./action-runtime.runtime-DpzOXqtk.js");
344
344
  return await slackActionRuntimePromise$1;
345
345
  }
346
346
  function resolveSlackActionContext(params) {
@@ -468,9 +468,9 @@ const EXTENSION_SHARED_MODULE_ID = "openclaw/plugin-sdk/extension-shared";
468
468
  const TARGET_RESOLVER_RUNTIME_MODULE_ID = "openclaw/plugin-sdk/target-resolver-runtime";
469
469
  const loadExtensionSharedSdk = createLazyRuntimeModule(() => import(EXTENSION_SHARED_MODULE_ID));
470
470
  const loadTargetResolverRuntimeSdk = createLazyRuntimeModule(() => import(TARGET_RESOLVER_RUNTIME_MODULE_ID));
471
- const loadSlackSetupSurfaceModule = createLazyRuntimeModule(() => import("./setup-surface-CJS-L7PA.js"));
471
+ const loadSlackSetupSurfaceModule = createLazyRuntimeModule(() => import("./setup-surface-Cdq_mfjx.js"));
472
472
  const loadSlackScopesModule = createLazyRuntimeModule(() => import("./scopes-Bvg_ZzqZ.js"));
473
- const loadSlackOutboundAdapterModule = createLazyRuntimeModule(() => import("./outbound-adapter-CHm6e-0Q.js").then((n) => n.t));
473
+ const loadSlackOutboundAdapterModule = createLazyRuntimeModule(() => import("./outbound-adapter-BoDXPksS.js").then((n) => n.t));
474
474
  async function resolveSlackHandleAction() {
475
475
  return getOptionalSlackRuntime()?.channel?.slack?.handleSlackAction ?? (await loadSlackActionRuntime()).handleSlackAction;
476
476
  }
@@ -494,11 +494,11 @@ const loadSlackDirectoryConfigModule = createLazyRuntimeModule(() => import("./d
494
494
  const loadSlackResolveChannelsModule = createLazyRuntimeModule(() => import("./resolve-channels-B_eKaOkE.js").then((n) => n.n));
495
495
  const loadSlackResolveUsersModule = createLazyRuntimeModule(() => import("./resolve-users-BzBAJwvq.js").then((n) => n.n));
496
496
  async function loadSlackActionRuntime() {
497
- slackActionRuntimePromise ??= import("./action-runtime.runtime-BzrPV3EA.js");
497
+ slackActionRuntimePromise ??= import("./action-runtime.runtime-DpzOXqtk.js");
498
498
  return await slackActionRuntimePromise;
499
499
  }
500
500
  async function loadSlackSendRuntime() {
501
- slackSendRuntimePromise ??= import("./send.runtime-CDG5AgU3.js");
501
+ slackSendRuntimePromise ??= import("./send.runtime-Bgf0P22e.js");
502
502
  return await slackSendRuntimePromise;
503
503
  }
504
504
  async function loadSlackProbeModule() {
@@ -506,7 +506,7 @@ async function loadSlackProbeModule() {
506
506
  return await slackProbeModulePromise;
507
507
  }
508
508
  async function loadSlackMonitorModule() {
509
- slackMonitorModulePromise ??= import("./monitor-Djnd8pGL.js").then((n) => n.t);
509
+ slackMonitorModulePromise ??= import("./monitor-BhEzWuv0.js").then((n) => n.t);
510
510
  return await slackMonitorModulePromise;
511
511
  }
512
512
  async function loadSlackDirectoryLiveModule() {
@@ -1,2 +1,2 @@
1
- import { t as slackPlugin } from "./channel-DoFtZGpw.js";
1
+ import { t as slackPlugin } from "./channel-DUS8ZO45.js";
2
2
  export { slackPlugin };
@@ -1,10 +1,10 @@
1
1
  import { a as resolveSlackAccount, c as resolveSlackConfigAccessorAccount, i as resolveDefaultSlackAccountId, n as listSlackAccountIds } from "./accounts-yk5K3wQU.js";
2
- import { a as describeSlackSetupAccount, i as SLACK_CHANNEL, n as createSlackSetupWizardProxy, o as isSlackSetupAccountConfigured, r as slackSetupAdapter } from "./setup-core-B7pou7oe.js";
2
+ import { a as describeSlackSetupAccount, i as SLACK_CHANNEL, n as createSlackSetupWizardProxy, o as isSlackSetupAccountConfigured, r as slackSetupAdapter } from "./setup-core-az0LCrNr.js";
3
3
  import { t as SlackChannelConfigSchema } from "./config-schema-CNRousxw.js";
4
4
  import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
5
5
  import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
6
6
  //#region extensions/slack/src/channel.setup.ts
7
- const slackSetupWizard = createSlackSetupWizardProxy(async () => ({ slackSetupWizard: (await import("./setup-surface-CJS-L7PA.js")).slackSetupWizard }));
7
+ const slackSetupWizard = createSlackSetupWizardProxy(async () => ({ slackSetupWizard: (await import("./setup-surface-Cdq_mfjx.js")).slackSetupWizard }));
8
8
  const slackSetupConfigAdapter = createScopedChannelConfigAdapter({
9
9
  sectionKey: SLACK_CHANNEL,
10
10
  listAccountIds: listSlackAccountIds,
@@ -1,3 +1,3 @@
1
- import { t as prepareSlackMessage } from "./prepare-Or_6_XXl.js";
2
- import { t as createInboundSlackTestContext } from "./prepare.test-helpers-CU1qB54Q.js";
1
+ import { t as prepareSlackMessage } from "./prepare-BcznR9ok.js";
2
+ import { t as createInboundSlackTestContext } from "./prepare.test-helpers-D807wdul.js";
3
3
  export { createInboundSlackTestContext, prepareSlackMessage };
@@ -1,7 +1,7 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-CiIaOW0V.js";
2
- import { D as buildSlackSlashCommandMatcher, p as isSlackChannelAllowedByPolicy } from "./room-context-Cd8jFpS-.js";
3
- import { t as monitorSlackProvider } from "./provider-3Y7c15_J.js";
4
- import { o as resolveSlackThreadTs } from "./replies-Fg1T3ZzU.js";
2
+ import { h as isSlackChannelAllowedByPolicy, k as buildSlackSlashCommandMatcher } from "./room-context-BI26wVBb.js";
3
+ import { t as monitorSlackProvider } from "./provider-BFnE2bgI.js";
4
+ import { o as resolveSlackThreadTs } from "./replies-2ve_YcHy.js";
5
5
  //#region extensions/slack/src/monitor.ts
6
6
  var monitor_exports = /* @__PURE__ */ __exportAll({
7
7
  buildSlackSlashCommandMatcher: () => buildSlackSlashCommandMatcher,
@@ -12,7 +12,7 @@ var outbound_adapter_exports = /* @__PURE__ */ __exportAll({ slackOutbound: () =
12
12
  const SLACK_MAX_BLOCKS = 50;
13
13
  let slackSendRuntimePromise;
14
14
  async function loadSlackSendRuntime() {
15
- slackSendRuntimePromise ??= import("./send.runtime-CDG5AgU3.js");
15
+ slackSendRuntimePromise ??= import("./send.runtime-Bgf0P22e.js");
16
16
  return await slackSendRuntimePromise;
17
17
  }
18
18
  function resolveRenderedInteractiveBlocks(interactive, previousBlocks) {
@@ -1,2 +1,2 @@
1
- import { t as createSlackOutboundPayloadHarness } from "./outbound-payload.test-harness-C0CW7_CE.js";
1
+ import { t as createSlackOutboundPayloadHarness } from "./outbound-payload.test-harness-C7Izm95Q.js";
2
2
  export { createSlackOutboundPayloadHarness };
@@ -1,4 +1,4 @@
1
- import { n as slackOutbound } from "./outbound-adapter-CHm6e-0Q.js";
1
+ import { n as slackOutbound } from "./outbound-adapter-BoDXPksS.js";
2
2
  import { primeChannelOutboundSendMock } from "openclaw/plugin-sdk/channel-contract-testing";
3
3
  //#region node_modules/tinyrainbow/dist/index.js
4
4
  var b = {
@@ -2,13 +2,13 @@ import { o as SLACK_TEXT_LIMIT, s as truncateSlackText } from "./thread-ts-As_dc
2
2
  import { n as isSlackInteractiveRepliesEnabled, t as compileSlackInteractiveReplies } from "./interactive-replies-BSg5hXhj.js";
3
3
  import { i as normalizeSlackAllowOwnerEntry } from "./allow-list-nwXs_eCP.js";
4
4
  import { n as resolveSlackNativeStreaming, r as resolveSlackStreamingMode, t as mapStreamingModeToSlackLegacyDraftStreamMode } from "./streaming-compat-eu5Rj5gj.js";
5
- import { a as recordSlackThreadParticipation, s as normalizeSlackOutboundText, t as sendMessageSlack } from "./send-CxXFbqN1.js";
6
- import { b as buildSlackEditTextPayload, f as removeSlackReaction, l as reactSlackMessage, r as editSlackMessage, t as deleteSlackMessage } from "./actions-BCRbHv1Q.js";
5
+ import { a as recordSlackThreadParticipation, s as normalizeSlackOutboundText, t as sendMessageSlack } from "./send-C5PzphgC.js";
6
+ import { b as buildSlackEditTextPayload, f as removeSlackReaction, l as reactSlackMessage, r as editSlackMessage, t as deleteSlackMessage } from "./actions-Chs6DbrP.js";
7
7
  import { t as formatSlackError } from "./errors-C_sW0Zgl.js";
8
- import { T as updateLastRoute, a as recordInboundSession, w as resolveStorePath } from "./room-context-Cd8jFpS-.js";
9
- import { r as escapeSlackMrkdwn } from "./provider-3Y7c15_J.js";
10
- import { n as resolveSlackThreadTargets, t as prepareSlackMessage } from "./prepare-Or_6_XXl.js";
11
- import { a as resolveDeliveredSlackReplyThreadTs, i as readSlackReplyBlocks, n as deliverReplies, o as resolveSlackThreadTs, t as createSlackReplyDeliveryPlan } from "./replies-Fg1T3ZzU.js";
8
+ import { D as updateLastRoute, E as resolveStorePath, a as recordInboundSession } from "./room-context-BI26wVBb.js";
9
+ import { r as escapeSlackMrkdwn } from "./provider-BFnE2bgI.js";
10
+ import { n as resolveSlackThreadTargets, t as prepareSlackMessage } from "./prepare-BcznR9ok.js";
11
+ import { a as resolveDeliveredSlackReplyThreadTs, i as readSlackReplyBlocks, n as deliverReplies, o as resolveSlackThreadTs, t as createSlackReplyDeliveryPlan } from "./replies-2ve_YcHy.js";
12
12
  import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/string-coerce-runtime";
13
13
  import { resolveInboundLastRouteSessionKey } from "openclaw/plugin-sdk/routing";
14
14
  import { createChannelMessageReplyPipeline, defineFinalizableLivePreviewAdapter, deliverWithFinalizableLivePreviewAdapter, resolveChannelMessageSourceReplyDeliveryMode } from "openclaw/plugin-sdk/channel-message";
@@ -68,6 +68,7 @@ function createSlackDraftStream(params) {
68
68
  accountId: params.accountId,
69
69
  threadTs: params.resolveThreadTs?.(),
70
70
  identity: params.identity,
71
+ ...params.metadata ? { metadata: params.metadata } : {},
71
72
  ...blocks ? { blocks } : {}
72
73
  });
73
74
  streamChannelId = sent.channelId || streamChannelId;
@@ -317,7 +318,7 @@ async function appendSlackStream(params) {
317
318
  * All other errors propagate unchanged.
318
319
  */
319
320
  async function stopSlackStream(params) {
320
- const { session, text } = params;
321
+ const { session, text, metadata } = params;
321
322
  if (session.stopped) {
322
323
  logVerbose("slack-stream: stream already stopped, ignoring duplicate stop");
323
324
  return;
@@ -326,7 +327,10 @@ async function stopSlackStream(params) {
326
327
  if (text) session.pendingText += text;
327
328
  logVerbose(`slack-stream: stopping stream in ${session.channel} thread=${session.threadTs}${text ? ` (final text: ${text.length} chars)` : ""}`);
328
329
  try {
329
- await session.streamer.stop(text ? { markdown_text: text } : void 0);
330
+ await session.streamer.stop({
331
+ ...text ? { markdown_text: text } : {},
332
+ ...metadata ? { metadata } : {}
333
+ });
330
334
  session.delivered = true;
331
335
  session.pendingText = "";
332
336
  } catch (err) {
@@ -523,7 +527,7 @@ function resolveSlackStreamingThreadHint(params) {
523
527
  }
524
528
  const SLACK_STREAM_RECIPIENT_TEAM_CACHE_MAX = 2e3;
525
529
  const slackStreamRecipientTeamCache = /* @__PURE__ */ new Map();
526
- function buildSlackTurnDeliveryKey(params) {
530
+ function buildSlackEventDeliveryKey(params) {
527
531
  const reply = resolveSendableOutboundReplyParts(params.payload, { text: params.textOverride });
528
532
  const slackBlocks = readSlackReplyBlocks(params.payload);
529
533
  if (!reply.hasContent && !slackBlocks?.length) return null;
@@ -555,15 +559,15 @@ function rememberSlackStreamRecipientTeam(params) {
555
559
  if (oldest) slackStreamRecipientTeamCache.delete(oldest);
556
560
  }
557
561
  }
558
- function createSlackTurnDeliveryTracker() {
562
+ function createSlackEventDeliveryTracker() {
559
563
  const deliveredKeys = /* @__PURE__ */ new Set();
560
564
  return {
561
565
  hasDelivered(params) {
562
- const key = buildSlackTurnDeliveryKey(params);
566
+ const key = buildSlackEventDeliveryKey(params);
563
567
  return key ? deliveredKeys.has(key) : false;
564
568
  },
565
569
  markDelivered(params) {
566
- const key = buildSlackTurnDeliveryKey(params);
570
+ const key = buildSlackEventDeliveryKey(params);
567
571
  if (key) deliveredKeys.add(key);
568
572
  }
569
573
  };
@@ -632,10 +636,15 @@ async function dispatchPreparedSlackMessage(prepared) {
632
636
  ctx: prepared.ctxPayload
633
637
  });
634
638
  }
635
- const { statusThreadTs, isThreadReply } = resolveSlackThreadTargets({
639
+ const threadTargets = resolveSlackThreadTargets({
636
640
  message,
637
641
  replyToMode: prepared.replyToMode
638
642
  });
643
+ const forcedReplyThreadTs = prepared.forcedReplyThreadTs;
644
+ const slackMessageMetadata = prepared.slackMessageMetadata;
645
+ const statusThreadTs = forcedReplyThreadTs ?? threadTargets.statusThreadTs;
646
+ const isThreadReply = threadTargets.isThreadReply;
647
+ const replyDeliveryMode = forcedReplyThreadTs ? "off" : prepared.replyToMode;
639
648
  const sourceReplyDeliveryMode = resolveChannelMessageSourceReplyDeliveryMode({
640
649
  cfg,
641
650
  ctx: prepared.ctxPayload
@@ -688,11 +697,11 @@ async function dispatchPreparedSlackMessage(prepared) {
688
697
  if (statusReactionsEnabled) statusReactions.setQueued();
689
698
  const hasRepliedRef = { value: false };
690
699
  const replyPlan = createSlackReplyDeliveryPlan({
691
- replyToMode: prepared.replyToMode,
692
- incomingThreadTs,
700
+ replyToMode: replyDeliveryMode,
701
+ incomingThreadTs: forcedReplyThreadTs ?? incomingThreadTs,
693
702
  messageTs,
694
703
  hasRepliedRef,
695
- isThreadReply
704
+ isThreadReply: Boolean(forcedReplyThreadTs) || isThreadReply
696
705
  });
697
706
  const typingTarget = statusThreadTs ? `${message.channel}/${statusThreadTs}` : message.channel;
698
707
  const typingReaction = ctx.typingReaction;
@@ -755,8 +764,8 @@ async function dispatchPreparedSlackMessage(prepared) {
755
764
  streaming: account.config.streaming,
756
765
  nativeStreaming: resolveChannelStreamingNativeTransport(account.config)
757
766
  });
758
- const streamThreadHint = resolveSlackStreamingThreadHint({
759
- replyToMode: prepared.replyToMode,
767
+ const streamThreadHint = forcedReplyThreadTs ?? resolveSlackStreamingThreadHint({
768
+ replyToMode: replyDeliveryMode,
760
769
  incomingThreadTs,
761
770
  messageTs,
762
771
  isThreadReply
@@ -784,7 +793,7 @@ async function dispatchPreparedSlackMessage(prepared) {
784
793
  let usedReplyThreadTs;
785
794
  let usedBlockReplyThreadTs;
786
795
  let observedReplyDelivery = false;
787
- const deliveryTracker = createSlackTurnDeliveryTracker();
796
+ const deliveryTracker = createSlackEventDeliveryTracker();
788
797
  const resolveDeliveryThreadTs = (params) => {
789
798
  const plannedThreadTs = params.forcedThreadTs ? void 0 : replyPlan.nextThreadTs();
790
799
  return params.forcedThreadTs ?? plannedThreadTs ?? (params.kind === "block" ? usedBlockReplyThreadTs : void 0);
@@ -807,8 +816,9 @@ async function dispatchPreparedSlackMessage(prepared) {
807
816
  runtime,
808
817
  textLimit: ctx.textLimit,
809
818
  replyThreadTs: session.threadTs,
810
- replyToMode: prepared.replyToMode,
811
- ...slackIdentity ? { identity: slackIdentity } : {}
819
+ replyToMode: replyDeliveryMode,
820
+ ...slackIdentity ? { identity: slackIdentity } : {},
821
+ ...slackMessageMetadata ? { metadata: slackMessageMetadata } : {}
812
822
  });
813
823
  markSlackStreamFallbackDelivered(session);
814
824
  observedReplyDelivery = true;
@@ -839,12 +849,13 @@ async function dispatchPreparedSlackMessage(prepared) {
839
849
  runtime,
840
850
  textLimit: ctx.textLimit,
841
851
  replyThreadTs,
842
- replyToMode: prepared.replyToMode,
843
- ...slackIdentity ? { identity: slackIdentity } : {}
852
+ replyToMode: replyDeliveryMode,
853
+ ...slackIdentity ? { identity: slackIdentity } : {},
854
+ ...slackMessageMetadata ? { metadata: slackMessageMetadata } : {}
844
855
  });
845
856
  observedReplyDelivery = true;
846
857
  const deliveredThreadTs = resolveDeliveredSlackReplyThreadTs({
847
- replyToMode: prepared.replyToMode,
858
+ replyToMode: replyDeliveryMode,
848
859
  payloadReplyToId: params.payload.replyToId,
849
860
  replyThreadTs
850
861
  });
@@ -1078,6 +1089,7 @@ async function dispatchPreparedSlackMessage(prepared) {
1078
1089
  token: ctx.botToken,
1079
1090
  accountId: account.accountId,
1080
1091
  identity: slackIdentity,
1092
+ ...slackMessageMetadata ? { metadata: slackMessageMetadata } : {},
1081
1093
  maxChars: Math.min(ctx.textLimit, SLACK_TEXT_LIMIT),
1082
1094
  resolveThreadTs: () => {
1083
1095
  const ts = replyPlan.peekThreadTs();
@@ -1323,7 +1335,10 @@ async function dispatchPreparedSlackMessage(prepared) {
1323
1335
  let streamFallbackDelivered = false;
1324
1336
  const finalStream = streamSession;
1325
1337
  if (finalStream && !finalStream.stopped) try {
1326
- await stopSlackStream({ session: finalStream });
1338
+ await stopSlackStream({
1339
+ session: finalStream,
1340
+ ...slackMessageMetadata ? { metadata: slackMessageMetadata } : {}
1341
+ });
1327
1342
  } catch (err) {
1328
1343
  if (err instanceof SlackStreamNotDeliveredError) streamFallbackDelivered = await deliverPendingStreamFallback(finalStream, err);
1329
1344
  else runtime.error?.(danger(`slack-stream: failed to stop stream: ${formatSlackError(err)}`));
@@ -2,11 +2,11 @@ import { l as resolveSlackReplyToMode } from "./accounts-yk5K3wQU.js";
2
2
  import { r as parseSlackTarget } from "./target-parsing-CQmv-iSm.js";
3
3
  import "./targets-B1tYCAr6.js";
4
4
  import { i as normalizeSlackAllowOwnerEntry, o as resolveSlackAllowListMatch, r as normalizeAllowListLower } from "./allow-list-nwXs_eCP.js";
5
- import { i as hasSlackThreadParticipationWithPersistence, t as sendMessageSlack } from "./send-CxXFbqN1.js";
6
- import { _ as resolveSlackThreadStarter, g as resolveSlackThreadHistory, l as reactSlackMessage, y as formatSlackFileReference } from "./actions-BCRbHv1Q.js";
5
+ import { i as hasSlackThreadParticipationWithPersistence, t as sendMessageSlack } from "./send-C5PzphgC.js";
6
+ import { _ as resolveSlackThreadStarter, g as resolveSlackThreadHistory, l as reactSlackMessage, y as formatSlackFileReference } from "./actions-Chs6DbrP.js";
7
7
  import { t as formatSlackError } from "./errors-C_sW0Zgl.js";
8
- import { b as readSessionUpdatedAt, c as authorizeSlackBotRoomMessage, d as resolveSlackEffectiveAllowFrom, g as resolveSlackChannelConfig, h as resolveSlackChatType, k as stripSlackMentionsForCommandDetection, m as normalizeSlackChannelType, n as authorizeSlackDirectMessage, o as resolveConversationLabel$1, t as resolveSlackRoomContextHints, u as resolveSlackCommandIngress, w as resolveStorePath, x as resolveChannelContextVisibilityMode } from "./room-context-Cd8jFpS-.js";
9
- import "./send.runtime-BHCPpSj_.js";
8
+ import { C as resolveChannelContextVisibilityMode, E as resolveStorePath, S as readSessionUpdatedAt, _ as resolveSlackChatType, c as authorizeSlackBotRoomMessage, d as resolveSlackEffectiveAllowFrom, f as buildSlackAssistantThreadMetadata, g as normalizeSlackChannelType, j as stripSlackMentionsForCommandDetection, m as parseSlackAssistantThreadMetadata, n as authorizeSlackDirectMessage, o as resolveConversationLabel$1, t as resolveSlackRoomContextHints, u as resolveSlackCommandIngress, v as resolveSlackChannelConfig } from "./room-context-BI26wVBb.js";
9
+ import "./send.runtime-DsEXD6MR.js";
10
10
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
11
11
  import { resolveAgentRoute, resolveInboundLastRouteSessionKey, resolveThreadSessionKeys } from "openclaw/plugin-sdk/routing";
12
12
  import { resolveChannelMessageSourceReplyDeliveryMode } from "openclaw/plugin-sdk/channel-message";
@@ -15,10 +15,11 @@ import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
15
15
  import { ensureConfiguredBindingRouteReady, resolveConfiguredBindingRoute, resolveRuntimeConversationBindingRoute } from "openclaw/plugin-sdk/conversation-runtime";
16
16
  import { createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
17
17
  import { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
18
- import { buildChannelTurnContext, buildMentionRegexes, formatInboundEnvelope, implicitMentionKindWhen, logInboundDrop, matchesMentionWithExplicit, resolveEnvelopeFormatOptions, toInboundMediaFacts } from "openclaw/plugin-sdk/channel-inbound";
18
+ import { buildChannelInboundEventContext, buildMentionRegexes, classifyChannelInboundEvent, formatInboundEnvelope, implicitMentionKindWhen, logInboundDrop, matchesMentionWithExplicit, resolveEnvelopeFormatOptions, resolveUnmentionedGroupInboundPolicy, toInboundMediaFacts } from "openclaw/plugin-sdk/channel-inbound";
19
19
  import { filterSupplementalContextItems, resolvePinnedMainDmOwnerFromAllowlist, shouldIncludeSupplementalContext } from "openclaw/plugin-sdk/security-runtime";
20
20
  import { resolveAckReaction, shouldAckReaction } from "openclaw/plugin-sdk/channel-feedback";
21
21
  import { hasControlCommand } from "openclaw/plugin-sdk/command-detection";
22
+ import { isAbortRequestText } from "openclaw/plugin-sdk/command-primitives-runtime";
22
23
  import { shouldHandleTextCommands } from "openclaw/plugin-sdk/command-surface";
23
24
  import { recordDroppedChannelTurnHistory } from "openclaw/plugin-sdk/inbound-reply-dispatch";
24
25
  import { mimeTypeFromFilePath } from "openclaw/plugin-sdk/media-mime";
@@ -29,7 +30,7 @@ const SLACK_MENTION_RESOLUTION_MAX_LOOKUPS_PER_MESSAGE = 20;
29
30
  const SLACK_USER_MENTION_RE$1 = /<@([A-Z0-9]+)(?:\|[^>]+)?>/gi;
30
31
  let slackMediaModulePromise$1;
31
32
  function loadSlackMediaModule$1() {
32
- slackMediaModulePromise$1 ??= import("./actions-BCRbHv1Q.js").then((n) => n.h);
33
+ slackMediaModulePromise$1 ??= import("./actions-Chs6DbrP.js").then((n) => n.h);
33
34
  return slackMediaModulePromise$1;
34
35
  }
35
36
  function collectUniqueSlackMentionIds$1(texts) {
@@ -442,7 +443,7 @@ function resolveSlackInitialAgentRoute(params) {
442
443
  });
443
444
  }
444
445
  function resolveSlackRoutingContext(params) {
445
- const { ctx, account, message, isDirectMessage, isGroupDm, isRoom, isRoomish, seedTopLevelRoomThread } = params;
446
+ const { ctx, account, message, isDirectMessage, isGroupDm, isRoom, isRoomish, seedTopLevelRoomThread, assistantThreadTs } = params;
446
447
  let route = resolveSlackInitialAgentRoute({
447
448
  ctx,
448
449
  account,
@@ -460,7 +461,7 @@ function resolveSlackRoutingContext(params) {
460
461
  const isThreadReply = threadContext.isThreadReply;
461
462
  const autoThreadId = !isThreadReply && replyToMode === "all" && threadContext.messageTs ? threadContext.messageTs : void 0;
462
463
  const seedCandidateThreadId = threadContext.incomingThreadTs ?? threadContext.messageTs;
463
- const routedThreadId = (isDirectMessage ? void 0 : isRoomish ? isThreadReply && threadTs ? threadTs : void 0 : isThreadReply ? threadTs : autoThreadId) ?? (isRoomish ? !isThreadReply && isRoom && seedTopLevelRoomThread && replyToMode !== "off" && seedCandidateThreadId ? seedCandidateThreadId : void 0 : void 0);
464
+ const routedThreadId = (isDirectMessage ? assistantThreadTs : isRoomish ? isThreadReply && threadTs ? threadTs : void 0 : isThreadReply ? threadTs : autoThreadId) ?? (isRoomish ? !isThreadReply && isRoom && seedTopLevelRoomThread && replyToMode !== "off" && seedCandidateThreadId ? seedCandidateThreadId : void 0 : void 0);
464
465
  const baseConversationId = resolveSlackBaseConversationId({
465
466
  message,
466
467
  isDirectMessage
@@ -577,7 +578,7 @@ function formatSlackBotStarterThreadLabel(params) {
577
578
  //#region extensions/slack/src/monitor/message-handler/prepare-thread-context.ts
578
579
  let slackMediaModulePromise;
579
580
  function loadSlackMediaModule() {
580
- slackMediaModulePromise ??= import("./actions-BCRbHv1Q.js").then((n) => n.h);
581
+ slackMediaModulePromise ??= import("./actions-Chs6DbrP.js").then((n) => n.h);
581
582
  return slackMediaModulePromise;
582
583
  }
583
584
  const SLACK_THREAD_CONTEXT_USER_LOOKUP_CONCURRENCY = 4;
@@ -849,6 +850,76 @@ const SLACK_HISTORY_MEDIA_MAX_ATTACHMENTS = 4;
849
850
  const SLACK_HISTORY_MEDIA_MAX_BYTES = 10 * 1024 * 1024;
850
851
  const SLACK_HISTORY_MEDIA_IDLE_TIMEOUT_MS = 1e3;
851
852
  const SLACK_HISTORY_MEDIA_TOTAL_TIMEOUT_MS = 3e3;
853
+ function asRecord(value) {
854
+ return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
855
+ }
856
+ function recordString(record, key) {
857
+ return normalizeOptionalString(record?.[key]);
858
+ }
859
+ function recordNullableString(record, key) {
860
+ if (!record || !(key in record)) return;
861
+ if (record[key] === null) return null;
862
+ return normalizeOptionalString(record[key]);
863
+ }
864
+ function mergeSlackAssistantThreadContext(primary, fallback) {
865
+ if (!primary) return fallback;
866
+ if (!fallback) return primary;
867
+ return {
868
+ assistantChannelId: primary.assistantChannelId || fallback.assistantChannelId,
869
+ threadTs: primary.threadTs || fallback.threadTs,
870
+ userId: primary.userId ?? fallback.userId,
871
+ channelId: primary.channelId ?? fallback.channelId,
872
+ teamId: primary.teamId ?? fallback.teamId,
873
+ enterpriseId: primary.enterpriseId !== void 0 ? primary.enterpriseId : fallback.enterpriseId
874
+ };
875
+ }
876
+ function hasSlackAssistantThreadMetadata(context) {
877
+ return Boolean(context?.channelId || context?.teamId || context?.enterpriseId !== void 0);
878
+ }
879
+ function resolveSlackMessageAssistantThreadContext(message) {
880
+ const thread = asRecord(message.assistant_thread);
881
+ if (!thread) return;
882
+ const context = asRecord(thread.context);
883
+ const assistantChannelId = recordString(thread, "channel_id") ?? message.channel;
884
+ const threadTs = recordString(thread, "thread_ts") ?? message.thread_ts ?? message.ts;
885
+ if (!assistantChannelId || !threadTs) return;
886
+ return {
887
+ assistantChannelId,
888
+ threadTs,
889
+ userId: recordString(thread, "user_id") ?? message.user,
890
+ channelId: recordString(context, "channel_id"),
891
+ teamId: recordString(context, "team_id"),
892
+ enterpriseId: recordNullableString(context, "enterprise_id")
893
+ };
894
+ }
895
+ async function restoreSlackAssistantThreadContextFromMetadata(params) {
896
+ const threadTs = params.message.thread_ts;
897
+ const parentUserId = params.message.parent_user_id?.trim();
898
+ if (!params.message.channel || !threadTs || !parentUserId || parentUserId !== params.ctx.botUserId && parentUserId !== params.ctx.botId) return;
899
+ try {
900
+ const response = await params.ctx.app.client.conversations.replies({
901
+ channel: params.message.channel,
902
+ ts: threadTs,
903
+ oldest: threadTs,
904
+ include_all_metadata: true,
905
+ limit: 4
906
+ });
907
+ for (const message of response.messages ?? []) {
908
+ const context = parseSlackAssistantThreadMetadata(message.metadata);
909
+ if (!context) continue;
910
+ return {
911
+ assistantChannelId: params.message.channel,
912
+ threadTs,
913
+ userId: params.message.user,
914
+ channelId: context.channelId,
915
+ teamId: context.teamId,
916
+ enterpriseId: context.enterpriseId
917
+ };
918
+ }
919
+ } catch (err) {
920
+ logVerbose(`slack assistant context restore failed channel=${params.message.channel} ts=${threadTs}: ${formatErrorMessage(err)}`);
921
+ }
922
+ }
852
923
  function resolveCachedMentionRegexes(ctx, agentId) {
853
924
  const key = normalizeOptionalString(agentId) ?? "__default__";
854
925
  let byAgent = mentionRegexCache.get(ctx);
@@ -1093,7 +1164,19 @@ async function prepareSlackMessage(params) {
1093
1164
  source: opts.source
1094
1165
  });
1095
1166
  const channelRequireMention = channelConfig?.requireMention ?? ctx.defaultRequireMention ?? true;
1096
- const willImplicitlyThreadReply = isRoom && !channelRequireMention && resolveSlackReplyToMode(account, isDirectMessage ? "direct" : isGroupDm ? "group" : "channel") !== "off";
1167
+ const channelChatType = isDirectMessage ? "direct" : isGroupDm ? "group" : "channel";
1168
+ const messageAssistantThreadContext = resolveSlackMessageAssistantThreadContext(message);
1169
+ const assistantContextLookupChannelId = messageAssistantThreadContext?.assistantChannelId ?? message.channel;
1170
+ const assistantContextLookupThreadTs = messageAssistantThreadContext?.threadTs ?? message.thread_ts ?? message.ts;
1171
+ const cachedAssistantThreadContext = isDirectMessage ? ctx.getSlackAssistantThreadContext(assistantContextLookupChannelId, assistantContextLookupThreadTs) : void 0;
1172
+ const restoredAssistantThreadContext = isDirectMessage && !cachedAssistantThreadContext && !hasSlackAssistantThreadMetadata(messageAssistantThreadContext) ? await restoreSlackAssistantThreadContextFromMetadata({
1173
+ ctx,
1174
+ message
1175
+ }) : void 0;
1176
+ const assistantThreadContext = mergeSlackAssistantThreadContext(messageAssistantThreadContext, cachedAssistantThreadContext ?? restoredAssistantThreadContext);
1177
+ const assistantThreadContextToCache = messageAssistantThreadContext || restoredAssistantThreadContext ? assistantThreadContext : void 0;
1178
+ if (assistantThreadContextToCache) ctx.saveSlackAssistantThreadContext(assistantThreadContextToCache);
1179
+ const willImplicitlyThreadReply = isRoom && !channelRequireMention && resolveSlackReplyToMode(account, channelChatType) !== "off";
1097
1180
  const seedTopLevelRoomThreadBySource = opts.source === "app_mention" || opts.wasMentioned === true || explicitlyMentioned || willImplicitlyThreadReply;
1098
1181
  let routing = resolveSlackRoutingContext({
1099
1182
  ctx,
@@ -1103,7 +1186,8 @@ async function prepareSlackMessage(params) {
1103
1186
  isGroupDm,
1104
1187
  isRoom,
1105
1188
  isRoomish,
1106
- seedTopLevelRoomThread: seedTopLevelRoomThreadBySource
1189
+ seedTopLevelRoomThread: seedTopLevelRoomThreadBySource,
1190
+ assistantThreadTs: assistantThreadContext?.threadTs
1107
1191
  });
1108
1192
  const resolveWasMentioned = (mentionRegexes) => opts.wasMentioned ?? (!isDirectMessage && matchesMentionWithExplicit({
1109
1193
  text: messageText,
@@ -1126,7 +1210,8 @@ async function prepareSlackMessage(params) {
1126
1210
  isGroupDm,
1127
1211
  isRoom,
1128
1212
  isRoomish,
1129
- seedTopLevelRoomThread: true
1213
+ seedTopLevelRoomThread: true,
1214
+ assistantThreadTs: assistantThreadContext?.threadTs
1130
1215
  });
1131
1216
  mentionRegexes = resolveCachedMentionRegexes(ctx, routing.route.agentId);
1132
1217
  wasMentioned = resolveWasMentioned(mentionRegexes);
@@ -1151,7 +1236,7 @@ async function prepareSlackMessage(params) {
1151
1236
  return null;
1152
1237
  }
1153
1238
  }
1154
- const directThreadRoutedToDmSession = isDirectMessage && isThreadReply && threadTs && runtimeBinding?.conversation.conversationId !== threadTs;
1239
+ const directThreadRoutedToDmSession = !assistantThreadContext && isDirectMessage && isThreadReply && threadTs && runtimeBinding?.conversation.conversationId !== threadTs;
1155
1240
  let implicitMentionKinds = [];
1156
1241
  if (!isDirectMessage && ctx.botUserId && message.thread_ts && !ctx.threadRequireExplicitMention && !wasMentioned) {
1157
1242
  const replyToBotKinds = implicitMentionKindWhen("reply_to_bot", message.parent_user_id === ctx.botUserId);
@@ -1191,6 +1276,7 @@ async function prepareSlackMessage(params) {
1191
1276
  const canDetectMention = Boolean(ctx.botUserId) || mentionRegexes.length > 0;
1192
1277
  const textForCommandDetection = stripSlackMentionsForCommandDetection(message.text ?? "");
1193
1278
  const hasControlCommandInMessage = hasControlCommand(textForCommandDetection, cfg);
1279
+ const hasAbortRequest = isAbortRequestText(textForCommandDetection);
1194
1280
  const channelUsersAllowlistConfigured = isRoom && Array.isArray(channelConfig?.users) && channelConfig.users.length > 0;
1195
1281
  const messageIngress = await resolveSlackCommandIngress({
1196
1282
  ctx,
@@ -1332,6 +1418,16 @@ async function prepareSlackMessage(params) {
1332
1418
  if (!resolvedMessageContent) return null;
1333
1419
  const { rawBody, effectiveDirectMedia } = resolvedMessageContent;
1334
1420
  const chatType = resolveSlackChatType(conversation.resolvedChannelType);
1421
+ const inboundEventKind = classifyChannelInboundEvent({
1422
+ conversation: { kind: chatType },
1423
+ unmentionedGroupPolicy: resolveUnmentionedGroupInboundPolicy({
1424
+ cfg,
1425
+ agentId: route.agentId
1426
+ }),
1427
+ wasMentioned: effectiveWasMentioned,
1428
+ hasControlCommand: hasControlCommandInMessage,
1429
+ hasAbortRequest
1430
+ });
1335
1431
  const ackReaction = resolveAckReaction(cfg, route.agentId, {
1336
1432
  channel: "slack",
1337
1433
  accountId: account.accountId
@@ -1339,7 +1435,10 @@ async function prepareSlackMessage(params) {
1339
1435
  const ackReactionValue = ackReaction ?? "";
1340
1436
  const sourceRepliesAreToolOnly = resolveChannelMessageSourceReplyDeliveryMode({
1341
1437
  cfg,
1342
- ctx: { ChatType: chatType }
1438
+ ctx: {
1439
+ ChatType: chatType,
1440
+ InboundEventKind: inboundEventKind
1441
+ }
1343
1442
  }) === "message_tool_only";
1344
1443
  const statusReactionsExplicitlyEnabled = cfg.messages?.statusReactions?.enabled === true;
1345
1444
  const shouldAckReaction$1 = () => Boolean(ackReaction && shouldAckReaction({
@@ -1462,7 +1561,8 @@ async function prepareSlackMessage(params) {
1462
1561
  }) : dmHistoryContext.inboundHistory;
1463
1562
  const commandBody = textForCommandDetection.trim();
1464
1563
  const supplementalThreadHistoryBody = directThreadRoutedToDmSession && !threadHistoryBody ? threadStarterBody : threadHistoryBody;
1465
- const ctxPayload = buildChannelTurnContext({
1564
+ const effectiveMessageThreadId = assistantThreadContext?.threadTs ?? threadContext.messageThreadId;
1565
+ const ctxPayload = buildChannelInboundEventContext({
1466
1566
  channel: "slack",
1467
1567
  provider: "slack",
1468
1568
  surface: "slack",
@@ -1480,7 +1580,7 @@ async function prepareSlackMessage(params) {
1480
1580
  id: message.channel,
1481
1581
  label: envelopeFrom,
1482
1582
  spaceId: ctx.teamId || void 0,
1483
- threadId: directThreadRoutedToDmSession ? void 0 : threadContext.messageThreadId,
1583
+ threadId: directThreadRoutedToDmSession ? void 0 : effectiveMessageThreadId,
1484
1584
  nativeChannelId: message.channel,
1485
1585
  routePeer: {
1486
1586
  kind: chatType,
@@ -1497,10 +1597,11 @@ async function prepareSlackMessage(params) {
1497
1597
  to: slackTo,
1498
1598
  originatingTo: slackTo,
1499
1599
  replyToId: threadContext.replyToId,
1500
- messageThreadId: directThreadRoutedToDmSession ? void 0 : threadContext.messageThreadId,
1600
+ messageThreadId: directThreadRoutedToDmSession ? void 0 : effectiveMessageThreadId,
1501
1601
  nativeChannelId: message.channel
1502
1602
  },
1503
1603
  message: {
1604
+ inboundEventKind,
1504
1605
  body: combinedBody,
1505
1606
  bodyForAgent: rawBody,
1506
1607
  rawBody,
@@ -1537,6 +1638,10 @@ async function prepareSlackMessage(params) {
1537
1638
  GroupSubject: isRoomish ? roomLabel : void 0,
1538
1639
  UntrustedContext: untrustedChannelMetadata ? [untrustedChannelMetadata] : void 0,
1539
1640
  TransportThreadId: directThreadRoutedToDmSession ? threadContext.messageThreadId : void 0,
1641
+ SlackAssistantThread: assistantThreadContext ? true : void 0,
1642
+ SlackAssistantThreadContextChannelId: assistantThreadContext?.channelId,
1643
+ SlackAssistantThreadContextTeamId: assistantThreadContext?.teamId,
1644
+ SlackAssistantThreadContextEnterpriseId: assistantThreadContext?.enterpriseId ?? void 0,
1540
1645
  IsFirstThreadTurn: isThreadReply && threadTs && !directThreadRoutedToDmSession && !threadSessionPreviousTimestamp ? true : void 0,
1541
1646
  ...buildSlackMentionContextPayload({
1542
1647
  isRoomish,
@@ -1586,7 +1691,7 @@ async function prepareSlackMessage(params) {
1586
1691
  channel: "slack",
1587
1692
  to: `user:${message.user}`,
1588
1693
  accountId: route.accountId,
1589
- threadId: threadContext.messageThreadId,
1694
+ threadId: effectiveMessageThreadId,
1590
1695
  mainDmOwnerPin: pinnedMainDmOwner && message.user ? {
1591
1696
  ownerRecipient: pinnedMainDmOwner,
1592
1697
  senderRecipient: normalizeLowercaseStringOrEmpty(message.user),
@@ -1611,6 +1716,8 @@ async function prepareSlackMessage(params) {
1611
1716
  } : void 0
1612
1717
  },
1613
1718
  replyToMode,
1719
+ ...assistantThreadContext?.threadTs ? { forcedReplyThreadTs: assistantThreadContext.threadTs } : {},
1720
+ ...assistantThreadContext ? { slackMessageMetadata: buildSlackAssistantThreadMetadata(assistantThreadContext) } : {},
1614
1721
  requireMention: shouldRequireMention,
1615
1722
  isDirectMessage,
1616
1723
  isRoomish,
@@ -1,4 +1,4 @@
1
- import { f as createSlackMonitorContext } from "./room-context-Cd8jFpS-.js";
1
+ import { p as createSlackMonitorContext } from "./room-context-BI26wVBb.js";
2
2
  import "openclaw/plugin-sdk/temp-path";
3
3
  //#region extensions/slack/src/monitor/message-handler/prepare.test-helpers.ts
4
4
  function createInboundSlackTestContext(params) {
@@ -8,7 +8,7 @@ import { n as registerSlackHttpHandler, r as normalizeSlackWebhookPath } from ".
8
8
  import { t as formatSlackError } from "./errors-C_sW0Zgl.js";
9
9
  import { t as resolveSlackChannelAllowlist } from "./resolve-channels-B_eKaOkE.js";
10
10
  import { t as resolveSlackUserAllowlist } from "./resolve-users-BzBAJwvq.js";
11
- import { C as resolveOpenProviderRuntimeGroupPolicy, D as buildSlackSlashCommandMatcher, E as warnMissingProviderGroupPolicyFallbackOnce, O as resolveSlackSlashCommandConfig, S as resolveDefaultGroupPolicy, _ as resolveSlackChannelLabel, d as resolveSlackEffectiveAllowFrom, f as createSlackMonitorContext, g as resolveSlackChannelConfig, h as resolveSlackChatType, i as parsePluginBindingApprovalCustomId, k as stripSlackMentionsForCommandDetection, l as authorizeSlackSystemEventSender, m as normalizeSlackChannelType, n as authorizeSlackDirectMessage, p as isSlackChannelAllowedByPolicy, r as buildPluginBindingResolvedText, s as resolvePluginConversationBindingApproval, t as resolveSlackRoomContextHints, u as resolveSlackCommandIngress, v as getRuntimeConfig$1, y as isDangerousNameMatchingEnabled } from "./room-context-Cd8jFpS-.js";
11
+ import { A as resolveSlackSlashCommandConfig, O as warnMissingProviderGroupPolicyFallbackOnce, T as resolveOpenProviderRuntimeGroupPolicy, _ as resolveSlackChatType, b as getRuntimeConfig$1, d as resolveSlackEffectiveAllowFrom, f as buildSlackAssistantThreadMetadata, g as normalizeSlackChannelType, h as isSlackChannelAllowedByPolicy, i as parsePluginBindingApprovalCustomId, j as stripSlackMentionsForCommandDetection, k as buildSlackSlashCommandMatcher, l as authorizeSlackSystemEventSender, n as authorizeSlackDirectMessage, p as createSlackMonitorContext, r as buildPluginBindingResolvedText, s as resolvePluginConversationBindingApproval, t as resolveSlackRoomContextHints, u as resolveSlackCommandIngress, v as resolveSlackChannelConfig, w as resolveDefaultGroupPolicy, x as isDangerousNameMatchingEnabled, y as resolveSlackChannelLabel } from "./room-context-BI26wVBb.js";
12
12
  import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
13
13
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
14
14
  import { normalizeAccountId, normalizeMainKey } from "openclaw/plugin-sdk/routing";
@@ -37,6 +37,112 @@ import { requestHeartbeat } from "openclaw/plugin-sdk/heartbeat-runtime";
37
37
  import { createInteractiveConversationBindingHelpers, dispatchPluginInteractiveHandler } from "openclaw/plugin-sdk/plugin-runtime";
38
38
  import { createChannelInboundDebouncer, shouldDebounceTextInbound } from "openclaw/plugin-sdk/channel-inbound";
39
39
  import { generateSecureToken } from "openclaw/plugin-sdk/secure-random-runtime";
40
+ //#region extensions/slack/src/monitor/events/assistant.ts
41
+ const DEFAULT_ASSISTANT_PROMPTS = [
42
+ {
43
+ title: "What can you do?",
44
+ message: "What can you help me with?"
45
+ },
46
+ {
47
+ title: "Summarize this channel",
48
+ message: "Summarize the recent activity in this channel."
49
+ },
50
+ {
51
+ title: "Draft a reply",
52
+ message: "Help me draft a reply."
53
+ }
54
+ ];
55
+ function normalizeAssistantThread(event, getPrevious) {
56
+ const thread = event.assistant_thread;
57
+ if (!thread) return null;
58
+ const channelId = thread.channel_id?.trim();
59
+ const threadTs = thread.thread_ts?.trim();
60
+ if (!channelId || !threadTs) return null;
61
+ const previous = getPrevious?.(channelId, threadTs);
62
+ const threadContext = thread.context;
63
+ const eventContext = event.context;
64
+ const resolveContextString = (key, previousValue) => threadContext?.[key]?.trim() || eventContext?.[key]?.trim() || previousValue;
65
+ const enterpriseId = (() => {
66
+ if (threadContext && "enterprise_id" in threadContext) return threadContext.enterprise_id === null ? null : threadContext.enterprise_id?.trim() || previous?.enterpriseId;
67
+ if (eventContext && "enterprise_id" in eventContext) return eventContext.enterprise_id === null ? null : eventContext.enterprise_id?.trim() || previous?.enterpriseId;
68
+ return previous?.enterpriseId;
69
+ })();
70
+ return {
71
+ assistantChannelId: channelId,
72
+ threadTs,
73
+ userId: thread.user_id?.trim() || previous?.userId,
74
+ channelId: resolveContextString("channel_id", previous?.channelId),
75
+ teamId: resolveContextString("team_id", previous?.teamId),
76
+ enterpriseId
77
+ };
78
+ }
79
+ async function persistAssistantThreadMetadata(params) {
80
+ const { ctx, assistantThread } = params;
81
+ try {
82
+ const initialMessage = ((await ctx.app.client.conversations.replies({
83
+ token: ctx.botToken,
84
+ channel: assistantThread.assistantChannelId,
85
+ ts: assistantThread.threadTs,
86
+ oldest: assistantThread.threadTs,
87
+ include_all_metadata: true,
88
+ limit: 4
89
+ })).messages ?? []).find((message) => !message.subtype && message.user === ctx.botUserId && message.ts);
90
+ if (!initialMessage?.ts) return;
91
+ await ctx.app.client.chat.update({
92
+ token: ctx.botToken,
93
+ channel: assistantThread.assistantChannelId,
94
+ ts: initialMessage.ts,
95
+ text: initialMessage.text ?? "",
96
+ blocks: Array.isArray(initialMessage.blocks) ? initialMessage.blocks : [],
97
+ metadata: buildSlackAssistantThreadMetadata(assistantThread)
98
+ });
99
+ } catch (err) {
100
+ logVerbose(`slack assistant thread metadata persist failed for channel ${assistantThread.assistantChannelId}: ${formatErrorMessage(err)}`);
101
+ }
102
+ }
103
+ function registerSlackAssistantEvents(params) {
104
+ const { ctx, trackEvent } = params;
105
+ const slackApp = ctx.app;
106
+ slackApp.event("assistant_thread_started", async ({ event, body }) => {
107
+ try {
108
+ if (ctx.shouldDropMismatchedSlackEvent(body)) return;
109
+ trackEvent?.();
110
+ const assistantThread = normalizeAssistantThread(event, ctx.getSlackAssistantThreadContext);
111
+ if (!assistantThread) {
112
+ logVerbose("slack assistant_thread_started dropped: missing assistant thread channel/thread");
113
+ return;
114
+ }
115
+ ctx.saveSlackAssistantThreadContext(assistantThread);
116
+ await ctx.setSlackAssistantSuggestedPrompts({
117
+ channelId: assistantThread.assistantChannelId,
118
+ threadTs: assistantThread.threadTs,
119
+ title: "Try asking",
120
+ prompts: DEFAULT_ASSISTANT_PROMPTS
121
+ });
122
+ } catch (err) {
123
+ ctx.runtime.error?.(danger(`slack assistant_thread_started handler failed: ${formatErrorMessage(err)}`));
124
+ }
125
+ });
126
+ slackApp.event("assistant_thread_context_changed", async ({ event, body }) => {
127
+ try {
128
+ if (ctx.shouldDropMismatchedSlackEvent(body)) return;
129
+ trackEvent?.();
130
+ const assistantThread = normalizeAssistantThread(event, ctx.getSlackAssistantThreadContext);
131
+ if (!assistantThread) {
132
+ logVerbose("slack assistant_thread_context_changed dropped: missing assistant thread channel/thread");
133
+ return;
134
+ }
135
+ ctx.saveSlackAssistantThreadContext(assistantThread);
136
+ await persistAssistantThreadMetadata({
137
+ ctx,
138
+ assistantThread
139
+ });
140
+ } catch (err) {
141
+ ctx.runtime.error?.(danger(`slack assistant_thread_context_changed handler failed: ${formatErrorMessage(err)}`));
142
+ }
143
+ });
144
+ }
145
+ //#endregion
40
146
  //#region extensions/slack/src/channel-migration.ts
41
147
  function resolveAccountChannels(cfg, accountId) {
42
148
  if (!accountId) return {};
@@ -1431,6 +1537,7 @@ function resolveAssistantMessageChangedInbound(params) {
1431
1537
  ts: asString(message.ts) ?? asString(changed.event_ts),
1432
1538
  thread_ts: asString(message.thread_ts),
1433
1539
  event_ts: changed.event_ts,
1540
+ assistant_thread: asRecord$1(message.assistant_thread) ?? asRecord$1(changed.assistant_thread),
1434
1541
  files: Array.isArray(message.files) ? message.files : void 0,
1435
1542
  attachments: Array.isArray(message.attachments) ? message.attachments : void 0
1436
1543
  };
@@ -1645,6 +1752,10 @@ function registerSlackMonitorEvents(params) {
1645
1752
  ctx: params.ctx,
1646
1753
  trackEvent: params.trackEvent
1647
1754
  });
1755
+ registerSlackAssistantEvents({
1756
+ ctx: params.ctx,
1757
+ trackEvent: params.trackEvent
1758
+ });
1648
1759
  }
1649
1760
  //#endregion
1650
1761
  //#region extensions/slack/src/monitor/message-handler/debounce-key.ts
@@ -1764,7 +1875,7 @@ function createSlackThreadTsResolver(params) {
1764
1875
  //#region extensions/slack/src/monitor/message-handler.ts
1765
1876
  let slackMessagePipelinePromise;
1766
1877
  function loadSlackMessagePipeline() {
1767
- slackMessagePipelinePromise ??= import("./pipeline.runtime-DJcwOZky.js");
1878
+ slackMessagePipelinePromise ??= import("./pipeline.runtime-Bq754VH8.js");
1768
1879
  return slackMessagePipelinePromise;
1769
1880
  }
1770
1881
  const APP_MENTION_RETRY_TTL_MS = 6e4;
@@ -2306,7 +2417,7 @@ function loadSlashCommandsRuntime() {
2306
2417
  return slashCommandsRuntimePromise;
2307
2418
  }
2308
2419
  function loadSlashDispatchRuntime() {
2309
- slashDispatchRuntimePromise ??= import("./slash-dispatch.runtime-Cg7uU92H.js");
2420
+ slashDispatchRuntimePromise ??= import("./slash-dispatch.runtime-CcbE1HtP.js");
2310
2421
  return slashDispatchRuntimePromise;
2311
2422
  }
2312
2423
  function loadSlackPluginCommandsRuntime() {
@@ -1,7 +1,7 @@
1
1
  import { t as resolveSlackReplyBlocks } from "./reply-blocks-BFaJ_ejG.js";
2
2
  import { o as SLACK_TEXT_LIMIT } from "./thread-ts-As_dcNbD.js";
3
- import { o as markdownToSlackMrkdwnChunks, t as sendMessageSlack } from "./send-CxXFbqN1.js";
4
- import "./send.runtime-BHCPpSj_.js";
3
+ import { o as markdownToSlackMrkdwnChunks, t as sendMessageSlack } from "./send-C5PzphgC.js";
4
+ import "./send.runtime-DsEXD6MR.js";
5
5
  import { createReplyReferencePlanner } from "openclaw/plugin-sdk/reply-reference";
6
6
  import { SILENT_REPLY_TOKEN, chunkMarkdownTextWithMode, isSilentReplyText } from "openclaw/plugin-sdk/reply-chunking";
7
7
  import { deliverTextOrMediaReply, resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
@@ -32,7 +32,8 @@ async function deliverReplies(params) {
32
32
  threadTs,
33
33
  accountId: params.accountId,
34
34
  ...slackBlocks?.length ? { blocks: slackBlocks } : {},
35
- ...params.identity ? { identity: params.identity } : {}
35
+ ...params.identity ? { identity: params.identity } : {},
36
+ ...params.metadata ? { metadata: params.metadata } : {}
36
37
  });
37
38
  params.runtime.log?.(`delivered reply to ${params.target}`);
38
39
  continue;
@@ -51,7 +52,8 @@ async function deliverReplies(params) {
51
52
  token: params.token,
52
53
  threadTs,
53
54
  accountId: params.accountId,
54
- ...params.identity ? { identity: params.identity } : {}
55
+ ...params.identity ? { identity: params.identity } : {},
56
+ ...params.metadata ? { metadata: params.metadata } : {}
55
57
  });
56
58
  },
57
59
  sendMedia: async ({ mediaUrl, caption }) => {
@@ -61,7 +63,8 @@ async function deliverReplies(params) {
61
63
  mediaUrl,
62
64
  threadTs,
63
65
  accountId: params.accountId,
64
- ...params.identity ? { identity: params.identity } : {}
66
+ ...params.identity ? { identity: params.identity } : {},
67
+ ...params.metadata ? { metadata: params.metadata } : {}
65
68
  });
66
69
  }
67
70
  }) !== "empty") params.runtime.log?.(`delivered reply to ${params.target}`);
@@ -121,6 +121,36 @@ function isSlackChannelAllowedByPolicy(params) {
121
121
  }
122
122
  //#endregion
123
123
  //#region extensions/slack/src/monitor/context.ts
124
+ const SLACK_ASSISTANT_THREAD_CONTEXT_METADATA_EVENT = "assistant_thread_context";
125
+ function buildSlackAssistantThreadMetadata(context) {
126
+ const eventPayload = {};
127
+ if (context.channelId) eventPayload.channel_id = context.channelId;
128
+ if (context.teamId) eventPayload.team_id = context.teamId;
129
+ if (context.enterpriseId) eventPayload.enterprise_id = context.enterpriseId;
130
+ return {
131
+ event_type: SLACK_ASSISTANT_THREAD_CONTEXT_METADATA_EVENT,
132
+ event_payload: eventPayload
133
+ };
134
+ }
135
+ function parseSlackAssistantThreadMetadata(value) {
136
+ if (!value || typeof value !== "object" || Array.isArray(value)) return;
137
+ const metadata = value;
138
+ if (metadata.event_type !== "assistant_thread_context") return;
139
+ const payload = metadata.event_payload;
140
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) return;
141
+ const record = payload;
142
+ const stringField = (key) => {
143
+ const raw = record[key];
144
+ return typeof raw === "string" && raw.trim() ? raw.trim() : void 0;
145
+ };
146
+ return {
147
+ channelId: stringField("channel_id"),
148
+ teamId: stringField("team_id"),
149
+ enterpriseId: stringField("enterprise_id")
150
+ };
151
+ }
152
+ const SLACK_ASSISTANT_CONTEXT_TTL_MS = 1440 * 60 * 1e3;
153
+ const SLACK_ASSISTANT_CONTEXT_CLEANUP_INTERVAL_MS = 600 * 1e3;
124
154
  function createSlackMonitorContext(params) {
125
155
  const channelHistories = /* @__PURE__ */ new Map();
126
156
  const logger = getChildLogger({ module: "slack-auto-reply" });
@@ -130,6 +160,8 @@ function createSlackMonitorContext(params) {
130
160
  ttlMs: 6e4,
131
161
  maxSize: 500
132
162
  });
163
+ const assistantThreadContexts = /* @__PURE__ */ new Map();
164
+ let lastAssistantContextCleanupAt = Date.now();
133
165
  const allowFrom = normalizeAllowList(params.allowFrom);
134
166
  const groupDmChannels = normalizeAllowList(params.groupDmChannels);
135
167
  const groupDmChannelsLower = normalizeAllowListLower(groupDmChannels);
@@ -144,6 +176,32 @@ function createSlackMonitorContext(params) {
144
176
  if (!channelId || !ts) return;
145
177
  seenMessages.delete(`${channelId}:${ts}`);
146
178
  };
179
+ const assistantContextKey = (channelId, threadTs) => `${channelId}:${threadTs}`;
180
+ const cleanupAssistantThreadContexts = () => {
181
+ const now = Date.now();
182
+ if (now - lastAssistantContextCleanupAt < SLACK_ASSISTANT_CONTEXT_CLEANUP_INTERVAL_MS) return;
183
+ lastAssistantContextCleanupAt = now;
184
+ const cutoff = now - SLACK_ASSISTANT_CONTEXT_TTL_MS;
185
+ for (const [key, entry] of assistantThreadContexts) if (entry.updatedAt < cutoff) assistantThreadContexts.delete(key);
186
+ };
187
+ const getSlackAssistantThreadContext = (channelId, threadTs) => {
188
+ if (!channelId || !threadTs) return;
189
+ const key = assistantContextKey(channelId, threadTs);
190
+ const entry = assistantThreadContexts.get(key);
191
+ if (!entry) return;
192
+ if (Date.now() - entry.updatedAt > SLACK_ASSISTANT_CONTEXT_TTL_MS) {
193
+ assistantThreadContexts.delete(key);
194
+ return;
195
+ }
196
+ return entry;
197
+ };
198
+ const saveSlackAssistantThreadContext = (context) => {
199
+ cleanupAssistantThreadContexts();
200
+ assistantThreadContexts.set(assistantContextKey(context.assistantChannelId, context.threadTs), {
201
+ ...context,
202
+ updatedAt: Date.now()
203
+ });
204
+ };
147
205
  const resolveSlackSystemEventSessionKey = (p) => {
148
206
  const channelId = normalizeOptionalString(p.channelId) ?? "";
149
207
  if (!channelId) return params.mainKey;
@@ -256,6 +314,26 @@ function createSlackMonitorContext(params) {
256
314
  logVerbose(`slack status update failed for channel ${p.channelId}: ${formatSlackError(err)}`);
257
315
  }
258
316
  };
317
+ const setSlackAssistantSuggestedPrompts = async (p) => {
318
+ const prompts = p.prompts.map((prompt) => ({
319
+ title: prompt.title.trim(),
320
+ message: prompt.message.trim()
321
+ })).filter((prompt) => prompt.title && prompt.message).slice(0, 4);
322
+ if (prompts.length === 0) return false;
323
+ try {
324
+ await params.app.client.assistant.threads.setSuggestedPrompts({
325
+ token: params.botToken,
326
+ channel_id: p.channelId,
327
+ thread_ts: p.threadTs,
328
+ ...p.title?.trim() ? { title: p.title.trim() } : {},
329
+ prompts
330
+ });
331
+ return true;
332
+ } catch (err) {
333
+ logVerbose(`slack suggested prompts update failed for channel ${p.channelId}: ${formatSlackError(err)}`);
334
+ return false;
335
+ }
336
+ };
259
337
  const isChannelAllowed = (p) => {
260
338
  const channelType = normalizeSlackChannelType(p.channelType, p.channelId);
261
339
  const isDirectMessage = channelType === "im";
@@ -362,7 +440,10 @@ function createSlackMonitorContext(params) {
362
440
  isChannelAllowed,
363
441
  resolveChannelName,
364
442
  resolveUserName,
365
- setSlackThreadStatus
443
+ setSlackThreadStatus,
444
+ getSlackAssistantThreadContext,
445
+ saveSlackAssistantThreadContext,
446
+ setSlackAssistantSuggestedPrompts
366
447
  };
367
448
  }
368
449
  //#endregion
@@ -786,4 +867,4 @@ function resolveSlackRoomContextHints(params) {
786
867
  };
787
868
  }
788
869
  //#endregion
789
- export { resolveOpenProviderRuntimeGroupPolicy as C, buildSlackSlashCommandMatcher as D, warnMissingProviderGroupPolicyFallbackOnce as E, resolveSlackSlashCommandConfig as O, resolveDefaultGroupPolicy as S, updateLastRoute as T, resolveSlackChannelLabel as _, recordInboundSession as a, readSessionUpdatedAt as b, authorizeSlackBotRoomMessage as c, resolveSlackEffectiveAllowFrom as d, createSlackMonitorContext as f, resolveSlackChannelConfig as g, resolveSlackChatType as h, parsePluginBindingApprovalCustomId as i, stripSlackMentionsForCommandDetection as k, authorizeSlackSystemEventSender as l, normalizeSlackChannelType as m, authorizeSlackDirectMessage as n, resolveConversationLabel$1 as o, isSlackChannelAllowedByPolicy as p, buildPluginBindingResolvedText as r, resolvePluginConversationBindingApproval as s, resolveSlackRoomContextHints as t, resolveSlackCommandIngress as u, getRuntimeConfig$1 as v, resolveStorePath$1 as w, resolveChannelContextVisibilityMode as x, isDangerousNameMatchingEnabled as y };
870
+ export { resolveSlackSlashCommandConfig as A, resolveChannelContextVisibilityMode as C, updateLastRoute as D, resolveStorePath$1 as E, warnMissingProviderGroupPolicyFallbackOnce as O, readSessionUpdatedAt as S, resolveOpenProviderRuntimeGroupPolicy as T, resolveSlackChatType as _, recordInboundSession as a, getRuntimeConfig$1 as b, authorizeSlackBotRoomMessage as c, resolveSlackEffectiveAllowFrom as d, buildSlackAssistantThreadMetadata as f, normalizeSlackChannelType as g, isSlackChannelAllowedByPolicy as h, parsePluginBindingApprovalCustomId as i, stripSlackMentionsForCommandDetection as j, buildSlackSlashCommandMatcher as k, authorizeSlackSystemEventSender as l, parseSlackAssistantThreadMetadata as m, authorizeSlackDirectMessage as n, resolveConversationLabel$1 as o, createSlackMonitorContext as p, buildPluginBindingResolvedText as r, resolvePluginConversationBindingApproval as s, resolveSlackRoomContextHints as t, resolveSlackCommandIngress as u, resolveSlackChannelConfig as v, resolveDefaultGroupPolicy as w, isDangerousNameMatchingEnabled as x, resolveSlackChannelLabel as y };
@@ -1,14 +1,14 @@
1
1
  import { a as resolveSlackAccount, d as resolveSlackBotToken, i as resolveDefaultSlackAccountId, n as listSlackAccountIds, t as listEnabledSlackAccounts, u as resolveSlackAppToken } from "./accounts-yk5K3wQU.js";
2
2
  import { n as resolveSlackGroupRequireMention, r as resolveSlackGroupToolPolicy } from "./reply-blocks-BFaJ_ejG.js";
3
3
  import { n as setSlackRuntime } from "./runtime-DQxkf7k2.js";
4
- import { t as sendMessageSlack } from "./send-CxXFbqN1.js";
5
- import { a as listSlackEmojis, c as pinSlackMessage, d as removeOwnSlackReactions, f as removeSlackReaction, i as getSlackMemberInfo, l as reactSlackMessage, m as unpinSlackMessage, o as listSlackPins, p as sendSlackMessage, r as editSlackMessage, s as listSlackReactions, t as deleteSlackMessage, u as readSlackMessages } from "./actions-BCRbHv1Q.js";
4
+ import { t as sendMessageSlack } from "./send-C5PzphgC.js";
5
+ import { a as listSlackEmojis, c as pinSlackMessage, d as removeOwnSlackReactions, f as removeSlackReaction, i as getSlackMemberInfo, l as reactSlackMessage, m as unpinSlackMessage, o as listSlackPins, p as sendSlackMessage, r as editSlackMessage, s as listSlackReactions, t as deleteSlackMessage, u as readSlackMessages } from "./actions-Chs6DbrP.js";
6
6
  import { t as probeSlack } from "./probe-FL4sUJsH.js";
7
7
  import { t as resolveSlackChannelAllowlist } from "./resolve-channels-B_eKaOkE.js";
8
8
  import { t as resolveSlackUserAllowlist } from "./resolve-users-BzBAJwvq.js";
9
- import { t as monitorSlackProvider } from "./provider-3Y7c15_J.js";
9
+ import { t as monitorSlackProvider } from "./provider-BFnE2bgI.js";
10
10
  import { t as registerSlackPluginHttpRoutes } from "./plugin-routes-CRnfsTTX.js";
11
- import { n as slackActionRuntime, t as handleSlackAction } from "./action-runtime-p39JLqwf.js";
11
+ import { n as slackActionRuntime, t as handleSlackAction } from "./action-runtime-0RLkDKyA.js";
12
12
  import { n as listSlackDirectoryGroupsLive, r as listSlackDirectoryPeersLive } from "./directory-live-CZPzpQZF.js";
13
- import "./monitor-Djnd8pGL.js";
13
+ import "./monitor-BhEzWuv0.js";
14
14
  export { deleteSlackMessage, editSlackMessage, getSlackMemberInfo, handleSlackAction, listEnabledSlackAccounts, listSlackAccountIds, listSlackDirectoryGroupsLive, listSlackDirectoryPeersLive, listSlackEmojis, listSlackPins, listSlackReactions, monitorSlackProvider, pinSlackMessage, probeSlack, reactSlackMessage, readSlackMessages, registerSlackPluginHttpRoutes, removeOwnSlackReactions, removeSlackReaction, resolveDefaultSlackAccountId, resolveSlackAccount, resolveSlackAppToken, resolveSlackBotToken, resolveSlackChannelAllowlist, resolveSlackGroupRequireMention, resolveSlackGroupToolPolicy, resolveSlackUserAllowlist, sendMessageSlack, sendSlackMessage, setSlackRuntime, slackActionRuntime, unpinSlackMessage };
@@ -312,12 +312,14 @@ function buildSlackPostMessagePayload(params) {
312
312
  channel: params.channelId,
313
313
  text: params.text,
314
314
  blocks: params.blocks,
315
+ ...params.metadata ? { metadata: params.metadata } : {},
315
316
  ...threadPayload,
316
317
  ...unfurlPayload
317
318
  };
318
319
  return {
319
320
  channel: params.channelId,
320
321
  text: params.text,
322
+ ...params.metadata ? { metadata: params.metadata } : {},
321
323
  ...threadPayload,
322
324
  ...unfurlPayload
323
325
  };
@@ -637,6 +639,7 @@ async function sendMessageSlackQueuedInner(params) {
637
639
  replyBroadcast: opts.replyBroadcast,
638
640
  identity: opts.identity,
639
641
  blocks,
642
+ metadata: opts.metadata,
640
643
  unfurl
641
644
  })).ts ?? "unknown";
642
645
  return {
@@ -686,6 +689,7 @@ async function sendMessageSlackQueuedInner(params) {
686
689
  threadTs: opts.threadTs,
687
690
  replyBroadcast: sentMessageIds.length === 0 ? opts.replyBroadcast : void 0,
688
691
  identity: opts.identity,
692
+ metadata: sentMessageIds.length === 0 ? opts.metadata : void 0,
689
693
  unfurl
690
694
  });
691
695
  lastMessageId = response.ts ?? lastMessageId;
@@ -699,6 +703,7 @@ async function sendMessageSlackQueuedInner(params) {
699
703
  threadTs: opts.threadTs,
700
704
  replyBroadcast: sentMessageIds.length === 0 ? opts.replyBroadcast : void 0,
701
705
  identity: opts.identity,
706
+ metadata: sentMessageIds.length === 0 ? opts.metadata : void 0,
702
707
  unfurl
703
708
  });
704
709
  lastMessageId = response.ts ?? lastMessageId;
@@ -0,0 +1,2 @@
1
+ import { t as sendMessageSlack } from "./send-C5PzphgC.js";
2
+ export { sendMessageSlack };
@@ -0,0 +1,2 @@
1
+ import "./send-C5PzphgC.js";
2
+ export {};
@@ -24,6 +24,23 @@ function buildSlackManifest(botName = "OpenClaw") {
24
24
  messages_tab_enabled: true,
25
25
  messages_tab_read_only_enabled: false
26
26
  },
27
+ assistant_view: {
28
+ assistant_description: `${safeName} connects Slack assistant threads to OpenClaw agents.`,
29
+ suggested_prompts: [
30
+ {
31
+ title: "What can you do?",
32
+ message: "What can you help me with?"
33
+ },
34
+ {
35
+ title: "Summarize this channel",
36
+ message: "Summarize the recent activity in this channel."
37
+ },
38
+ {
39
+ title: "Draft a reply",
40
+ message: "Help me draft a reply."
41
+ }
42
+ ]
43
+ },
27
44
  slash_commands: [{
28
45
  command: "/openclaw",
29
46
  description: "Send a message to OpenClaw",
@@ -60,6 +77,8 @@ function buildSlackManifest(botName = "OpenClaw") {
60
77
  event_subscriptions: { bot_events: [
61
78
  "app_home_opened",
62
79
  "app_mention",
80
+ "assistant_thread_context_changed",
81
+ "assistant_thread_started",
63
82
  "channel_rename",
64
83
  "member_joined_channel",
65
84
  "member_left_channel",
@@ -81,8 +100,8 @@ function buildSlackSetupLines() {
81
100
  "1) Slack API -> Create App -> From scratch or From manifest (with the JSON below)",
82
101
  "2) Add Socket Mode + enable it to get the app-level token (xapp-...)",
83
102
  "3) Install App to workspace to get the xoxb- bot token",
84
- "4) Enable Event Subscriptions (socket) for message and App Home events",
85
- "5) App Home -> enable the Home tab and Messages tab for DMs",
103
+ "4) Enable Event Subscriptions (socket) for message, App Home, and assistant events",
104
+ "5) App Home -> enable the Home tab, Messages tab for DMs, and AI assistant view",
86
105
  "Manifest JSON follows as plain text for copy/paste.",
87
106
  "Tip: set SLACK_BOT_TOKEN + SLACK_APP_TOKEN in your env.",
88
107
  `Docs: ${formatDocsLink("/slack", "slack")}`
@@ -1,2 +1,2 @@
1
- import { t as slackSetupPlugin } from "./channel.setup-BDL4qn9U.js";
1
+ import { t as slackSetupPlugin } from "./channel.setup-qGOC05UK.js";
2
2
  export { slackSetupPlugin };
@@ -1,6 +1,6 @@
1
1
  import { a as resolveSlackAccount, i as resolveDefaultSlackAccountId, o as resolveSlackAccountAllowFrom } from "./accounts-yk5K3wQU.js";
2
- import "./shared-BEabCPK3.js";
3
- import { i as SLACK_CHANNEL, t as createSlackSetupWizardBase } from "./setup-core-B7pou7oe.js";
2
+ import "./shared-BuNoOmas.js";
3
+ import { i as SLACK_CHANNEL, t as createSlackSetupWizardBase } from "./setup-core-az0LCrNr.js";
4
4
  import { t as resolveSlackChannelAllowlist } from "./resolve-channels-B_eKaOkE.js";
5
5
  import { t as resolveSlackUserAllowlist } from "./resolve-users-BzBAJwvq.js";
6
6
  import { adaptScopedAccountAccessor } from "openclaw/plugin-sdk/channel-config-helpers";
@@ -2,7 +2,7 @@ import { a as resolveSlackAccount, c as resolveSlackConfigAccessorAccount, i as
2
2
  import { t as inspectSlackAccount } from "./account-inspect-BJyQLSkN.js";
3
3
  import { n as isSlackInteractiveRepliesEnabled } from "./interactive-replies-BSg5hXhj.js";
4
4
  import { f as getChatChannelMeta } from "./client-C_IaJbi5.js";
5
- import { i as SLACK_CHANNEL } from "./setup-core-B7pou7oe.js";
5
+ import { i as SLACK_CHANNEL } from "./setup-core-az0LCrNr.js";
6
6
  import { t as SlackChannelConfigSchema } from "./config-schema-CNRousxw.js";
7
7
  import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-B8QIWMs1.js";
8
8
  import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-0TL3L5Kb.js";
@@ -1,4 +1,4 @@
1
- import { r as deliverSlackSlashReplies$1 } from "./replies-Fg1T3ZzU.js";
1
+ import { r as deliverSlackSlashReplies$1 } from "./replies-2ve_YcHy.js";
2
2
  import { resolveAgentRoute as resolveAgentRoute$1 } from "openclaw/plugin-sdk/routing";
3
3
  import { resolveMarkdownTableMode as resolveMarkdownTableMode$1 } from "openclaw/plugin-sdk/markdown-table-runtime";
4
4
  import { recordInboundSessionMetaSafe as recordInboundSessionMetaSafe$1, resolveConversationLabel as resolveConversationLabel$1 } from "openclaw/plugin-sdk/conversation-runtime";
package/dist/test-api.js CHANGED
@@ -1,8 +1,8 @@
1
- import { a as createSlackActions, t as slackPlugin } from "./channel-DoFtZGpw.js";
1
+ import { a as createSlackActions, t as slackPlugin } from "./channel-DUS8ZO45.js";
2
2
  import { n as setSlackRuntime } from "./runtime-DQxkf7k2.js";
3
- import { t as sendMessageSlack } from "./send-CxXFbqN1.js";
4
- import { t as prepareSlackMessage } from "./prepare-Or_6_XXl.js";
5
- import { t as createInboundSlackTestContext } from "./prepare.test-helpers-CU1qB54Q.js";
6
- import { t as createSlackOutboundPayloadHarness } from "./outbound-payload.test-harness-C0CW7_CE.js";
7
- import { n as slackOutbound } from "./outbound-adapter-CHm6e-0Q.js";
3
+ import { t as sendMessageSlack } from "./send-C5PzphgC.js";
4
+ import { t as prepareSlackMessage } from "./prepare-BcznR9ok.js";
5
+ import { t as createInboundSlackTestContext } from "./prepare.test-helpers-D807wdul.js";
6
+ import { t as createSlackOutboundPayloadHarness } from "./outbound-payload.test-harness-C7Izm95Q.js";
7
+ import { n as slackOutbound } from "./outbound-adapter-BoDXPksS.js";
8
8
  export { createInboundSlackTestContext, createSlackActions, createSlackOutboundPayloadHarness, prepareSlackMessage, sendMessageSlack, setSlackRuntime, slackOutbound, slackPlugin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/slack",
3
- "version": "2026.5.16-beta.3",
3
+ "version": "2026.5.16-beta.4",
4
4
  "description": "OpenClaw Slack channel plugin",
5
5
  "repository": {
6
6
  "type": "git",
@@ -20,7 +20,7 @@
20
20
  "openclaw": "workspace:*"
21
21
  },
22
22
  "peerDependencies": {
23
- "openclaw": ">=2026.5.16-beta.3"
23
+ "openclaw": ">=2026.5.16-beta.4"
24
24
  },
25
25
  "peerDependenciesMeta": {
26
26
  "openclaw": {
@@ -65,10 +65,10 @@
65
65
  "allowInvalidConfigRecovery": true
66
66
  },
67
67
  "compat": {
68
- "pluginApi": ">=2026.5.16-beta.3"
68
+ "pluginApi": ">=2026.5.16-beta.4"
69
69
  },
70
70
  "build": {
71
- "openclawVersion": "2026.5.16-beta.3",
71
+ "openclawVersion": "2026.5.16-beta.4",
72
72
  "bundledDist": false
73
73
  },
74
74
  "release": {
@@ -1,2 +0,0 @@
1
- import { t as handleSlackAction } from "./action-runtime-p39JLqwf.js";
2
- export { handleSlackAction };
@@ -1,2 +0,0 @@
1
- import "./send-CxXFbqN1.js";
2
- export {};
@@ -1,2 +0,0 @@
1
- import { t as sendMessageSlack } from "./send-CxXFbqN1.js";
2
- export { sendMessageSlack };