@openclaw/slack 2026.8.2 → 2026.9.1

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 (36) hide show
  1. package/dist/{action-runtime-B0kRJ69h.js → action-runtime-DND4Pyp2.js} +4 -4
  2. package/dist/action-runtime.runtime-CEhbmS-Z.js +2 -0
  3. package/dist/{actions-BOxiu2Vy.js → actions-fh66A6lc.js} +2 -2
  4. package/dist/api.js +8 -8
  5. package/dist/{approval-handler.runtime-l5_2JLqi.js → approval-handler.runtime-D7d8sKM0.js} +13 -8
  6. package/dist/{channel-BguxhhNG.js → channel-4m8IAdMD.js} +28 -23
  7. package/dist/channel-config-api.js +1 -1
  8. package/dist/channel-plugin-api.js +1 -1
  9. package/dist/{channel-type-ChkODKBW.js → channel-type-3-SqEMVc.js} +1 -1
  10. package/dist/{channel.setup-BJohRJha.js → channel.setup-t_ghLGb_.js} +2 -2
  11. package/dist/{config-schema-B9GwoRlE.js → config-schema-bP3eV2ra.js} +1 -1
  12. package/dist/{cursor-pages-eX7p8Wwt.js → cursor-pages-ByFwo-Py.js} +7 -1
  13. package/dist/{directory-live-BOILcXPo.js → directory-live-q32AW7N1.js} +2 -7
  14. package/dist/{group-policy-BYH74y50.js → group-policy-BKjMqT-8.js} +46 -87
  15. package/dist/{message-tool-api-BsZbsulu.js → message-tool-api-uNEfQYGY.js} +1 -1
  16. package/dist/message-tool-api.js +1 -1
  17. package/dist/{monitor-B72wWXWg.js → monitor-Chwu_SiZ.js} +3 -3
  18. package/dist/{outbound-adapter-CPgYQ-BM.js → outbound-adapter-BB8wAjm5.js} +3 -3
  19. package/dist/{pipeline.runtime-CcdujV99.js → pipeline.runtime-BklS_NEj.js} +61 -95
  20. package/dist/{policy-CUpBeOt9.js → policy-D7PKkiet.js} +1 -1
  21. package/dist/{provider-DW9YC_no.js → provider-Do50wMWn.js} +52 -35
  22. package/dist/{relay-source-BLMdBrAw.js → relay-source-DWuduiJ2.js} +1 -1
  23. package/dist/{replies-DLjQ8RYU.js → replies-Dc6WVh_Q.js} +9 -10
  24. package/dist/{resolve-channels-Bv6IiGZ4.js → resolve-channels-CU7Bg5Ka.js} +2 -7
  25. package/dist/{resolve-users-BXw2pA7y.js → resolve-users-DrhttvRQ.js} +1 -1
  26. package/dist/runtime-api.js +9 -9
  27. package/dist/{send-GUz4_v2E.js → send-Djswy6lf.js} +2 -2
  28. package/dist/{send.runtime-rScD-UJi.js → send.runtime-__WVTWLQ.js} +1 -1
  29. package/dist/setup-plugin-api.js +1 -1
  30. package/dist/{setup-surface-Cc3P-z35.js → setup-surface-DO0e-MMS.js} +4 -4
  31. package/dist/{shared-CQGVZ_8a.js → shared-DEQBEKBL.js} +1 -1
  32. package/dist/{slash-dispatch.runtime-C2015r6s.js → slash-dispatch.runtime-C3B4h5ZM.js} +1 -1
  33. package/dist/{thread-ts-DUGhaYKq.js → thread-ts-CukseRVL.js} +5 -1
  34. package/openclaw.plugin.json +1 -1
  35. package/package.json +4 -4
  36. package/dist/action-runtime.runtime-IuA14rev.js +0 -2
@@ -1,13 +1,14 @@
1
1
  import { n as resolveSlackConversationBindingRoute, r as resolveSlackReplyToMode, t as normalizeSlackRouteBindingConfig } from "./conversation-binding-route-Vee8Dgbf.js";
2
2
  import { n as formatSlackTarget } from "./target-parsing-PbxGDbr9.js";
3
- import { I as countSlackTextUtf8Bytes, L as truncateSlackText, M as SLACK_TEXT_LIMIT, Q as normalizeSlackOutboundText, R as truncateSlackTextByUtf8Bytes, T as buildSlackBlocksFallbackText, U as SLACK_SESSION_LINK_ACTION_ID, a as qualifySlackConversationId, b as hasSlackNativeDataBlock, et as escapeSlackMrkdwn, k as SLACK_EDIT_TEXT_MAX_BYTES, m as resolveSlackReplyRenderPlan, o as qualifySlackRoutePeerId, s as resolveSlackEnterpriseMainDmSessionKey } from "./group-policy-BYH74y50.js";
3
+ import { I as countSlackTextUtf8Bytes, L as truncateSlackText, M as SLACK_TEXT_LIMIT, Q as normalizeSlackOutboundText, R as truncateSlackTextByUtf8Bytes, T as buildSlackBlocksFallbackText, U as SLACK_SESSION_LINK_ACTION_ID, a as qualifySlackConversationId, b as hasSlackNativeDataBlock, et as escapeSlackMrkdwn, k as SLACK_EDIT_TEXT_MAX_BYTES, m as resolveSlackReplyRenderPlan, o as qualifySlackRoutePeerId, s as resolveSlackEnterpriseMainDmSessionKey } from "./group-policy-BKjMqT-8.js";
4
4
  import { C as normalizeAllowListLower, E as resolveSlackAllowListMatch, o as formatSlackError, w as normalizeSlackAllowOwnerEntry } from "./probe-gj5yQgN2.js";
5
+ import { n as resolveSlackReplyThreadTs } from "./thread-ts-CukseRVL.js";
5
6
  import { n as resolveSlackStreamingMode, t as resolveSlackNativeStreaming } from "./streaming-compat-B-e0mqM0.js";
6
- import { D as resolveSlackMessageText$1, E as resolveSlackBlocksText, O as buildSlackEditTextPayload, S as formatSlackFileReferenceList, T as isSlackUnfurlAttachment, a as editSlackRenderedMessage, d as reactSlackMessage, i as editSlackMessage, m as removeSlackReaction, n as deleteSlackMessage, v as logVerbose$1, w as hasSlackTableBlock, x as formatSlackFileReference } from "./actions-BOxiu2Vy.js";
7
- import { c as hasSlackThreadFailureNotice, d as recordSlackThreadFailureNotice, f as recordSlackThreadParticipation, l as hasSlackThreadParticipation, m as buildSlackNativeDataDeliveryPlan, o as clearSlackThreadFailureNotice, r as sendMessageSlack, u as hasSlackThreadParticipationWithPersistence } from "./send-GUz4_v2E.js";
8
- import { C as resolveStorePath, E as stripSlackMentionsForCommandDetection, S as resolveChannelResetConfig, _ as resolveSlackChatType, b as readSessionUpdatedAt, c as resolveSlackThreadTargets, d as authorizeSlackBotRoomMessage, f as resolveSlackCommandIngress, g as normalizeSlackChannelType, l as trackSlackDraftMessage, o as authorizeSlackDirectMessage, p as resolveSlackEffectiveAllowFrom, r as resolveSlackRoomContextHints, s as resolveSlackThreadContext, u as resolveConversationLabel$1, v as buildSlackAssistantThreadMetadata, w as updateLastRoute, x as resolveChannelContextVisibilityMode, y as parseSlackAssistantThreadMetadata } from "./provider-DW9YC_no.js";
9
- import { n as resolveSlackChannelConfig } from "./policy-CUpBeOt9.js";
10
- import { a as resolveDeliveredSlackReplyThreadTs, c as emitSlackMessageSentHooks, i as readSlackReplyBlocks, n as deliverReplies, o as resolveSlackThreadTs, s as sanitizeSlackMonitorReplyPayload, t as createSlackReplyDeliveryPlan } from "./replies-DLjQ8RYU.js";
7
+ import { D as resolveSlackMessageText$1, E as resolveSlackBlocksText, O as buildSlackEditTextPayload, S as formatSlackFileReferenceList, T as isSlackUnfurlAttachment, a as editSlackRenderedMessage, d as reactSlackMessage, i as editSlackMessage, m as removeSlackReaction, n as deleteSlackMessage, v as logVerbose$1, w as hasSlackTableBlock, x as formatSlackFileReference } from "./actions-fh66A6lc.js";
8
+ import { c as hasSlackThreadFailureNotice, d as recordSlackThreadFailureNotice, f as recordSlackThreadParticipation, l as hasSlackThreadParticipation, m as buildSlackNativeDataDeliveryPlan, o as clearSlackThreadFailureNotice, r as sendMessageSlack, u as hasSlackThreadParticipationWithPersistence } from "./send-Djswy6lf.js";
9
+ import { C as resolveStorePath, E as stripSlackMentionsForCommandDetection, S as resolveChannelResetConfig, _ as resolveSlackChatType, b as readSessionUpdatedAt, c as resolveSlackThreadTargets, d as authorizeSlackBotRoomMessage, f as resolveSlackCommandIngress, g as normalizeSlackChannelType, l as trackSlackDraftMessage, o as authorizeSlackDirectMessage, p as resolveSlackEffectiveAllowFrom, r as resolveSlackRoomContextHints, s as resolveSlackThreadContext, u as resolveConversationLabel$1, v as buildSlackAssistantThreadMetadata, w as updateLastRoute, x as resolveChannelContextVisibilityMode, y as parseSlackAssistantThreadMetadata } from "./provider-Do50wMWn.js";
10
+ import { n as resolveSlackChannelConfig } from "./policy-D7PKkiet.js";
11
+ import { a as resolveSlackThreadTs, i as readSlackReplyBlocks, n as deliverReplies, o as sanitizeSlackMonitorReplyPayload, s as emitSlackMessageSentHooks, t as createSlackReplyDeliveryPlan } from "./replies-Dc6WVh_Q.js";
11
12
  import { asOptionalRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
12
13
  import { resolveAgentRoute, resolveInboundLastRouteSessionKey, resolveThreadSessionKeys } from "openclaw/plugin-sdk/routing";
13
14
  import { createChannelMessageReplyPipeline, createChannelProgressDraftCompositor, createDraftStreamLoop, createFinalizableDraftStreamControlsForState, defineFinalizableLivePreviewAdapter, deliverWithFinalizableLivePreviewAdapter, formatChannelProgressDraftText, isChannelProgressDraftWorkToolName, resolveAgentOutboundIdentity, resolveChannelMessageSourceReplyDeliveryMode, resolveChannelProgressDraftConfig, resolveChannelProgressDraftMaxLineChars, resolveChannelStreamingBlockEnabled, resolveChannelStreamingPreviewToolProgress, resolveChannelStreamingSuppressDefaultToolProgressMessages } from "openclaw/plugin-sdk/channel-outbound";
@@ -30,7 +31,7 @@ import { mergePairLoopGuardConfig } from "openclaw/plugin-sdk/pair-loop-guard-ru
30
31
  import { enqueueRoutedSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
31
32
  import { asDateTimestampMs, asFiniteNumberInRange, parseStrictFiniteNumber, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
32
33
  import { getGlobalHookRunner } from "openclaw/plugin-sdk/plugin-runtime";
33
- import { buildChannelInboundEventContext, buildMentionRegexes, classifyChannelInboundEvent, dispatchChannelInboundTurn, formatInboundEnvelope, formatInboundMediaUnavailableText, hasVisibleInboundReplyDispatch, implicitMentionKindWhen, logInboundDrop, matchesMentionWithExplicit, readAgentRunTerminalOutcome, recordDroppedChannelInboundHistory, resolveEnvelopeFormatOptions, resolveInboundMentionDecision, resolveInboundReplyDispatchCounts, resolveInboundSupplementalSenderAllowed, resolveUnmentionedGroupInboundPolicy, toInboundMediaFactsWithMetadata } from "openclaw/plugin-sdk/channel-inbound";
34
+ import { buildChannelInboundEventContext, buildMentionRegexes, classifyChannelInboundEvent, dispatchChannelInboundTurn, formatInboundEnvelope, formatInboundMediaUnavailableText, hasVisibleInboundReplyDispatch, implicitMentionKindWhen, matchesMentionWithExplicit, readAgentRunTerminalOutcome, recordDroppedChannelInboundHistory, resolveEnvelopeFormatOptions, resolveInboundMentionDecision, resolveInboundReplyDispatchCounts, resolveInboundSupplementalSenderAllowed, resolveUnmentionedGroupInboundPolicy, toInboundMediaFactsWithMetadata } from "openclaw/plugin-sdk/channel-inbound";
34
35
  import { resolveHumanDelayConfig } from "openclaw/plugin-sdk/agent-runtime";
35
36
  import { resolveGatewayPublicOrigin } from "openclaw/plugin-sdk/config-contracts";
36
37
  import { buildControlUiSessionPath } from "openclaw/plugin-sdk/session-discussion";
@@ -92,7 +93,7 @@ async function startSlackStream(params) {
92
93
  try {
93
94
  const result = await streamer.append({
94
95
  ...text ? { markdown_text: text } : {},
95
- ...chunks?.length ? { chunks } : {}
96
+ ...chunks ? { chunks } : {}
96
97
  });
97
98
  if (result) {
98
99
  session.delivered = true;
@@ -120,7 +121,7 @@ async function appendSlackStream(params) {
120
121
  try {
121
122
  const result = await session.streamer.append({
122
123
  ...text ? { markdown_text: text } : {},
123
- ...chunks?.length ? { chunks } : {}
124
+ ...chunks ? { chunks } : {}
124
125
  });
125
126
  if (result) {
126
127
  session.delivered = true;
@@ -268,7 +269,8 @@ function resolveExplicitSlackProgressTitle(entry) {
268
269
  return trimmed && trimmed.toLowerCase() !== "auto" ? trimmed : void 0;
269
270
  }
270
271
  function resolveSlackProgressStyle(entry) {
271
- return entry?.streaming?.progress?.style === "compact" ? "compact" : "card";
272
+ const progress = entry?.streaming?.progress;
273
+ return progress?.style ?? (progress?.toolProgress === false ? "compact" : "card");
272
274
  }
273
275
  function resolveSlackNativeProgressTaskCards(entry) {
274
276
  if (resolveSlackProgressStyle(entry) === "compact") return false;
@@ -1309,7 +1311,7 @@ function createSlackProgressRuntime(runtimeParams) {
1309
1311
  nativeNarrationSourceText = "";
1310
1312
  };
1311
1313
  const progressDraft = createChannelProgressDraftCompositor({
1312
- presentation: isProgressMode ? "summary" : void 0,
1314
+ presentation: isProgressMode && slackProgressStyle === "card" ? "summary" : void 0,
1313
1315
  entry: account.config,
1314
1316
  mode: slackStreaming.mode,
1315
1317
  active: progressDraftActive,
@@ -1409,6 +1411,7 @@ function createSlackProgressRuntime(runtimeParams) {
1409
1411
  delivery.streamFailed = false;
1410
1412
  };
1411
1413
  const pushPlanProgress = async (steps, explanation) => {
1414
+ if (!previewToolProgressEnabled) return false;
1412
1415
  if (isProgressMode) {
1413
1416
  if (slackProgressStyle === "compact") return false;
1414
1417
  return await progressDraft.pushPlanProgress(steps, { explanation });
@@ -2010,10 +2013,11 @@ function createSlackStreamingDeliveryRuntime(setup) {
2010
2013
  });
2011
2014
  state.observedReplyDelivery = true;
2012
2015
  if (params.kind === "final") state.observedFinalReplyDelivery = true;
2013
- const deliveredThreadTs = resolveDeliveredSlackReplyThreadTs({
2016
+ const deliveredThreadTs = resolveSlackReplyThreadTs({
2014
2017
  replyToMode: replyDeliveryMode,
2015
- payloadReplyToId: params.payload.replyToId,
2016
- replyThreadTs: deliveryReplyThreadTs
2018
+ replyToId: params.payload.replyToId,
2019
+ threadId: deliveryReplyThreadTs,
2020
+ replyToCurrent: params.payload.replyToCurrent
2017
2021
  });
2018
2022
  rememberDeliveredThreadTs(params.kind, deliveredThreadTs);
2019
2023
  replyPlan.markSent();
@@ -2055,6 +2059,7 @@ function createSlackStreamingDeliveryRuntime(setup) {
2055
2059
  }
2056
2060
  const text = params.streamText ?? reply.trimmedText;
2057
2061
  const hookContent = reply.trimmedText;
2062
+ const chunks = params.kind === "final" ? [] : void 0;
2058
2063
  let plannedThreadTs;
2059
2064
  try {
2060
2065
  if (!state.streamSession && state.nativeProgressStreamStartPromise) await state.nativeProgressStreamStartPromise;
@@ -2092,6 +2097,7 @@ function createSlackStreamingDeliveryRuntime(setup) {
2092
2097
  channel: message.channel,
2093
2098
  threadTs: streamThreadTs,
2094
2099
  text,
2100
+ chunks,
2095
2101
  ...params.taskDisplayMode ? { taskDisplayMode: params.taskDisplayMode } : {},
2096
2102
  ...slackIdentity ? { identity: slackIdentity } : {},
2097
2103
  teamId: await resolveSlackStreamRecipientTeamId({
@@ -2130,7 +2136,8 @@ function createSlackStreamingDeliveryRuntime(setup) {
2130
2136
  if (hookContent) recordStreamedDelivery(params.kind, hookContent);
2131
2137
  await appendSlackStream({
2132
2138
  session: state.streamSession,
2133
- text: `${params.appendSeparator === false ? "" : "\n"}${text}`
2139
+ text: `${params.appendSeparator === false ? "" : "\n"}${text}`,
2140
+ chunks
2134
2141
  });
2135
2142
  refreshStreamedAcknowledgements(state.streamSession);
2136
2143
  if (state.streamSession.delivered && state.streamSession.pendingText.length === 0) {
@@ -2473,6 +2480,7 @@ async function dispatchPreparedSlackMessage(prepared) {
2473
2480
  return await progress.progressDraft.pushToolEvent(payload);
2474
2481
  },
2475
2482
  onItemEvent: async (payload) => {
2483
+ if (payload.kind === "preamble" && (payload.phase === "start" || payload.phase === "update") && !draftStream?.messageId() && !delivery.streamSession?.delivered) return false;
2476
2484
  if (progress.isProgressMode && payload.kind === "preamble") {
2477
2485
  if (progress.shouldYieldDraftProgress()) return false;
2478
2486
  const headlineVisible = await progress.progressDraft.pushPreambleHeadline(payload.progressText, { itemId: payload.itemId });
@@ -2807,7 +2815,7 @@ const SLACK_MENTION_RESOLUTION_CONCURRENCY = 4;
2807
2815
  const SLACK_MENTION_RESOLUTION_MAX_LOOKUPS_PER_MESSAGE = 20;
2808
2816
  const SLACK_USER_MENTION_RE$1 = /<@([A-Z0-9]+)(?:\|[^>]+)?>/gi;
2809
2817
  const MAX_SLACK_UNAVAILABLE_FILE_TEXT_CHARS = 2e3;
2810
- const loadSlackMediaModule$1 = createLazyRuntimeModule(() => import("./actions-BOxiu2Vy.js").then((n) => n._));
2818
+ const loadSlackMediaModule$1 = createLazyRuntimeModule(() => import("./actions-fh66A6lc.js").then((n) => n._));
2811
2819
  function formatSlackUnavailableMedia(params) {
2812
2820
  let fileReferences = params.files?.map((file) => `${formatSlackFileReference(file)} unavailable (${file.reason})`).join(", ");
2813
2821
  if (fileReferences && fileReferences.length > MAX_SLACK_UNAVAILABLE_FILE_TEXT_CHARS) fileReferences = `${truncateUtf16Safe(fileReferences, MAX_SLACK_UNAVAILABLE_FILE_TEXT_CHARS)}; … (file references truncated)`;
@@ -3153,7 +3161,7 @@ function formatSlackThreadLabelSnippet(text) {
3153
3161
  }
3154
3162
  //#endregion
3155
3163
  //#region extensions/slack/src/monitor/message-handler/prepare-thread-context.ts
3156
- const loadSlackMediaModule = createLazyRuntimeModule(() => import("./actions-BOxiu2Vy.js").then((n) => n._));
3164
+ const loadSlackMediaModule = createLazyRuntimeModule(() => import("./actions-fh66A6lc.js").then((n) => n._));
3157
3165
  const SLACK_THREAD_CONTEXT_USER_LOOKUP_CONCURRENCY = 4;
3158
3166
  function resolveSlackThreadSessionFreshness(params) {
3159
3167
  return params.ctx.channelRuntime?.session?.resolveEntryResetFreshness?.({
@@ -3713,24 +3721,15 @@ async function resolveSlackConversationContext(params) {
3713
3721
  };
3714
3722
  }
3715
3723
  async function authorizeSlackInboundMessage(params) {
3716
- const { ctx, account, message, conversation } = params;
3724
+ const { ctx, account, message, conversation, drop } = params;
3717
3725
  const { isDirectMessage, channelName, resolvedChannelType, isBotMessage, allowBotsMode } = conversation;
3718
3726
  if (isBotMessage) {
3719
3727
  if (message.user && ctx.botUserId && message.user === ctx.botUserId) return null;
3720
- if (allowBotsMode === "off") {
3721
- logVerbose(`slack: drop bot message ${message.bot_id ?? "unknown"} (allowBots=false)`);
3722
- return null;
3723
- }
3724
- }
3725
- if (isDirectMessage && !message.user) {
3726
- logVerbose("slack: drop dm message (missing user id)");
3727
- return null;
3728
+ if (allowBotsMode === "off") return drop("bot-disabled");
3728
3729
  }
3730
+ if (isDirectMessage && !message.user) return drop("missing-user");
3729
3731
  const senderId = message.user ?? (isBotMessage ? message.bot_id : void 0);
3730
- if (!senderId) {
3731
- logVerbose("slack: drop message (missing sender id)");
3732
- return null;
3733
- }
3732
+ if (!senderId) return drop("missing-sender");
3734
3733
  if (!ctx.isChannelAllowed({
3735
3734
  teamId: params.eventScope?.teamId ?? ctx.teamId,
3736
3735
  channelId: message.channel,
@@ -3758,8 +3757,7 @@ async function authorizeSlackInboundMessage(params) {
3758
3757
  ctx.runtime.error?.(`slack allowlist denial notice failed for channel ${message.channel}: ${formatSlackError(error)}`);
3759
3758
  }
3760
3759
  }
3761
- logVerbose("slack: drop message (channel not allowed)");
3762
- return null;
3760
+ return drop("channel-not-allowed");
3763
3761
  }
3764
3762
  const allowFromLower = await resolveSlackEffectiveAllowFrom(ctx, {
3765
3763
  includePairingStore: isDirectMessage,
@@ -3767,10 +3765,8 @@ async function authorizeSlackInboundMessage(params) {
3767
3765
  });
3768
3766
  if (isDirectMessage) {
3769
3767
  const directUserId = message.user;
3770
- if (!directUserId) {
3771
- logVerbose("slack: drop dm message (missing user id)");
3772
- return null;
3773
- }
3768
+ if (!directUserId) return drop("missing-user");
3769
+ let dropReason = "dm-unauthorized";
3774
3770
  if (!await authorizeSlackDirectMessage({
3775
3771
  ctx,
3776
3772
  accountId: account.accountId,
@@ -3788,13 +3784,13 @@ async function authorizeSlackInboundMessage(params) {
3788
3784
  });
3789
3785
  },
3790
3786
  onDisabled: () => {
3791
- logVerbose("slack: drop dm (dms disabled)");
3787
+ dropReason = "dm-disabled";
3792
3788
  },
3793
3789
  onUnauthorized: ({ allowMatchMeta }) => {
3794
3790
  logVerbose(`Blocked unauthorized slack sender ${message.user} (dmPolicy=${ctx.dmPolicy}, ${allowMatchMeta})`);
3795
3791
  },
3796
3792
  log: logVerbose
3797
- })) return null;
3793
+ })) return drop(dropReason);
3798
3794
  }
3799
3795
  return {
3800
3796
  senderId,
@@ -3803,6 +3799,19 @@ async function authorizeSlackInboundMessage(params) {
3803
3799
  }
3804
3800
  async function prepareSlackMessage(params) {
3805
3801
  const { ctx, account, message, opts } = params;
3802
+ const drop = (reason, parentUserId) => {
3803
+ ctx.logger.info({
3804
+ provider: "slack",
3805
+ accountId: account.accountId,
3806
+ teamId: opts.eventScope?.teamId ?? ctx.teamId,
3807
+ channelId: message.channel,
3808
+ messageTs: message.ts,
3809
+ source: opts.source,
3810
+ reason,
3811
+ ...parentUserId ? { parentUserId } : {}
3812
+ }, "Slack inbound event rejected during preparation");
3813
+ return null;
3814
+ };
3806
3815
  const slackClient = opts.eventScope?.client ?? ctx.app.client;
3807
3816
  const threadStarterWorkspaceScope = {
3808
3817
  accountId: account.accountId,
@@ -3826,7 +3835,8 @@ async function prepareSlackMessage(params) {
3826
3835
  conversation,
3827
3836
  explicitBotMention: opts.source === "app_mention" || Boolean(normalizedBotUserId && mentionMetadata.mentionedUserIds.includes(normalizedBotUserId)),
3828
3837
  eventScope: opts.eventScope,
3829
- onVisibleDrop: opts.onVisibleDrop
3838
+ onVisibleDrop: opts.onVisibleDrop,
3839
+ drop
3830
3840
  });
3831
3841
  if (!authorization) return null;
3832
3842
  const { senderId, allowFromLower } = authorization;
@@ -3931,13 +3941,7 @@ async function prepareSlackMessage(params) {
3931
3941
  if (shouldLogVerbose()) logVerbose(`slack: using configured ACP binding for ${configuredBinding.record.conversation.conversationId} -> ${configuredBindingSessionKey}`);
3932
3942
  } else {
3933
3943
  if (shouldLogVerbose()) logVerbose(`slack: configured ACP binding unavailable for ${configuredBinding.record.conversation.conversationId}: ${ensured.error}`);
3934
- logInboundDrop({
3935
- log: logVerbose,
3936
- channel: "slack",
3937
- reason: "configured ACP binding unavailable",
3938
- target: configuredBinding.record.conversation.conversationId
3939
- });
3940
- return null;
3944
+ return drop("configured-binding-unavailable");
3941
3945
  }
3942
3946
  }
3943
3947
  const senderNameForAuthPromise = ctx.allowNameMatching ? resolveSenderName().then((name) => ({
@@ -4052,14 +4056,7 @@ async function prepareSlackMessage(params) {
4052
4056
  channel: "slack",
4053
4057
  accountId: account.accountId
4054
4058
  });
4055
- if (message["_ambiguousThreadReply"]) {
4056
- ctx.logger.info({
4057
- channel: message.channel,
4058
- ts: message.ts,
4059
- parentUserId: message.parent_user_id
4060
- }, "skipping ambiguous slack thread reply");
4061
- return null;
4062
- }
4059
+ if (message["_ambiguousThreadReply"]) return drop("ambiguous-thread", message.parent_user_id);
4063
4060
  let canDetectMention = Boolean(ctx.botUserId) || mentionRegexes.length > 0;
4064
4061
  const textForCommandDetection = stripSlackMentionsForCommandDetection(message.text ?? "");
4065
4062
  const hasControlCommandInMessage = hasControlCommand(textForCommandDetection, cfg);
@@ -4092,10 +4089,7 @@ async function prepareSlackMessage(params) {
4092
4089
  });
4093
4090
  let messageIngress = await resolveMessageIngress();
4094
4091
  const senderGate = messageIngress.senderAccess.gate;
4095
- if (isRoomish && senderGate?.allowed === false) {
4096
- logVerbose(`Blocked unauthorized slack sender ${senderId} (not in sender allowlist)`);
4097
- return null;
4098
- }
4092
+ if (isRoomish && senderGate?.allowed === false) return drop("unauthorized-sender");
4099
4093
  if (isRoom && isBotMessage && allowBotsMode !== "off" && !await authorizeSlackBotRoomMessage({
4100
4094
  ctx,
4101
4095
  channelId: message.channel,
@@ -4104,7 +4098,7 @@ async function prepareSlackMessage(params) {
4104
4098
  channelUsers: channelConfig?.users,
4105
4099
  allowFromLower,
4106
4100
  eventScope: opts.eventScope
4107
- })) return null;
4101
+ })) return drop("unauthorized-bot");
4108
4102
  const threadContextAllowFromLower = isRoom ? channelUsersAllowlistConfigured ? normalizeAllowListLower(channelConfig?.users) : [] : isDirectMessage ? allowFromLower : [];
4109
4103
  const contextVisibilityMode = resolveChannelContextVisibilityMode({
4110
4104
  cfg: ctx.cfg,
@@ -4124,15 +4118,7 @@ async function prepareSlackMessage(params) {
4124
4118
  explicitKind: true
4125
4119
  });
4126
4120
  const commandAuthorized = messageIngress.commandAccess.authorized;
4127
- if (isRoomish && messageIngress.commandAccess.shouldBlockControlCommand) {
4128
- logInboundDrop({
4129
- log: logVerbose,
4130
- channel: "slack",
4131
- reason: "control command (unauthorized)",
4132
- target: senderId
4133
- });
4134
- return null;
4135
- }
4121
+ if (isRoomish && messageIngress.commandAccess.shouldBlockControlCommand) return drop("control-command-unauthorized");
4136
4122
  const canSeedMentionedRoomThread = !seedTopLevelRoomThreadBySource && isRoom && !routing.isThreadReply && !hasBoundSession;
4137
4123
  let seededMentionRouting;
4138
4124
  const getSeededMentionRouting = () => {
@@ -4227,37 +4213,20 @@ async function prepareSlackMessage(params) {
4227
4213
  wasMentioned
4228
4214
  });
4229
4215
  if (isBotMessage && allowBotsMode === "mentions") {
4230
- if (!(isDirectMessage || effectiveWasMentioned || shouldBypassMention)) {
4231
- logVerbose("slack: drop bot message (allowBots=mentions, missing mention)");
4232
- return null;
4233
- }
4216
+ if (!(isDirectMessage || effectiveWasMentioned || shouldBypassMention)) return drop("bot-missing-mention");
4234
4217
  }
4235
4218
  if (isRoom && shouldRequireMention && !canDetectMention && !effectiveWasMentioned) {
4236
- ctx.logger.info({
4237
- channel: message.channel,
4238
- reason: "mention-detection-unavailable"
4239
- }, "skipping channel message");
4240
4219
  await recordDroppedHistory("slack-mention-detection-unavailable");
4241
- return null;
4220
+ return drop("mention-detection-unavailable");
4242
4221
  }
4243
4222
  const ignoreOtherMentions = channelConfig?.ignoreOtherMentions ?? false;
4244
4223
  if (isRoom && ignoreOtherMentions && Boolean(ctx.botUserId) && hasAnyMention && !wasMentioned) {
4245
- logInboundDrop({
4246
- log: logVerbose,
4247
- channel: "slack",
4248
- reason: "other-mention",
4249
- target: senderId
4250
- });
4251
4224
  await recordDroppedHistory("slack-other-mention");
4252
- return null;
4225
+ return drop("other-mention");
4253
4226
  }
4254
4227
  if (isRoom && shouldRequireMention && mentionDecision.shouldSkip) {
4255
- ctx.logger.info({
4256
- channel: message.channel,
4257
- reason: "no-mention"
4258
- }, "skipping channel message");
4259
4228
  await recordDroppedHistory("slack-no-mention");
4260
- return null;
4229
+ return drop("missing-mention");
4261
4230
  }
4262
4231
  const chatType = resolveSlackChatType(conversation.resolvedChannelType);
4263
4232
  const inboundEventKind = classifyChannelInboundEvent({
@@ -4272,7 +4241,7 @@ async function prepareSlackMessage(params) {
4272
4241
  });
4273
4242
  const threadStarter = await getThreadStarter();
4274
4243
  const resolvedMessageContent = await getMessageContent();
4275
- if (!resolvedMessageContent) return null;
4244
+ if (!resolvedMessageContent) return drop("empty-content");
4276
4245
  const { rawBody, effectiveDirectMedia } = resolvedMessageContent;
4277
4246
  const bodyForAgent = preflightAudioTranscript ? formatSlackAudioTranscriptForAgent({
4278
4247
  transcript: preflightAudioTranscript,
@@ -4435,10 +4404,7 @@ async function prepareSlackMessage(params) {
4435
4404
  messageId: threadContext.messageTs,
4436
4405
  inboundEventKind
4437
4406
  }, boundMessageThreadId);
4438
- if (messageIngress.ingress.admission !== "dispatch") {
4439
- logVerbose(`Blocked slack sender ${senderId} after final route binding`);
4440
- return null;
4441
- }
4407
+ if (messageIngress.ingress.admission !== "dispatch") return drop("final-route-denied");
4442
4408
  const agentContextEntities = isAgentViewMessage ? normalizeSlackAppContextEntities(message.app_context) : [];
4443
4409
  const ctxPayload = (ctx.buildContext ?? buildChannelInboundEventContext)({
4444
4410
  channelIngress: messageIngress,
@@ -4523,6 +4489,7 @@ async function prepareSlackMessage(params) {
4523
4489
  payload: { entities: agentContextEntities }
4524
4490
  }] : void 0,
4525
4491
  TransportThreadId: directThreadRoutedToDmSession ? threadContext.messageThreadId : void 0,
4492
+ ReplyThreading: isThreadReply ? { implicitCurrentMessage: "deny" } : void 0,
4526
4493
  SlackAssistantThread: assistantThreadContext ? true : void 0,
4527
4494
  SlackAgentThread: agentViewThreadTs ? true : void 0,
4528
4495
  SlackAssistantThreadContextChannelId: assistantThreadContext?.channelId,
@@ -4558,7 +4525,6 @@ async function prepareSlackMessage(params) {
4558
4525
  normalizeEntry: normalizeSlackAllowOwnerEntry
4559
4526
  }) : null;
4560
4527
  const replyTarget = `channel:${message.channel}`;
4561
- if (!replyTarget) return null;
4562
4528
  if (preflightAudioTranscript) await sendSlackPreflightAudioTranscriptEcho({
4563
4529
  transcript: preflightAudioTranscript,
4564
4530
  cfg,
@@ -1,4 +1,4 @@
1
- import { n as buildSlackChannelPolicyScope, t as buildSlackChannelIdCandidates } from "./group-policy-BYH74y50.js";
1
+ import { n as buildSlackChannelPolicyScope, t as buildSlackChannelIdCandidates } from "./group-policy-BKjMqT-8.js";
2
2
  import { D as resolveSlackUserAllowListForTeam, T as normalizeSlackSlug } from "./probe-gj5yQgN2.js";
3
3
  import { applyChannelMatchMeta, buildChannelKeyCandidates } from "openclaw/plugin-sdk/channel-targets";
4
4
  import { mergePairLoopGuardConfig } from "openclaw/plugin-sdk/pair-loop-guard-runtime";
@@ -1,15 +1,15 @@
1
1
  import { n as registerSlackHttpHandler, r as normalizeSlackWebhookPath } from "./registry-bbjH7IHX.js";
2
2
  import { a as resolveSlackAccount, d as resolveSlackAppToken, f as resolveSlackBotToken, i as resolveDefaultSlackAccountId, o as resolveSlackAccountAllowFrom, s as resolveSlackAccountDmPolicy, u as formatSlackBotTokenIdentityWarning } from "./accounts-Dm_H77gH.js";
3
3
  import { a as parseSlackTarget, n as formatSlackTarget } from "./target-parsing-PbxGDbr9.js";
4
- import { Ct as isSlackApprovalAuthorizedSender, G as isSlackCallbackActionId, J as decodeSlackQuestionAction, K as isSlackQuestionActionId, L as truncateSlackText, M as SLACK_TEXT_LIMIT, Tt as isSlackExecApprovalAuthorizedSender, W as isSlackApprovalActionId, Y as resolveSlackQuestionAction, a as qualifySlackConversationId, et as escapeSlackMrkdwn, lt as isSlackAnyNativeApprovalClientEnabled, nt as decodeSlackApprovalAction, o as qualifySlackRoutePeerId, s as resolveSlackEnterpriseMainDmSessionKey, t as buildSlackChannelIdCandidates, xt as registerSlackInstallationState } from "./group-policy-BYH74y50.js";
4
+ import { Ct as isSlackApprovalAuthorizedSender, G as isSlackCallbackActionId, J as decodeSlackQuestionAction, K as isSlackQuestionActionId, L as truncateSlackText, M as SLACK_TEXT_LIMIT, Tt as isSlackExecApprovalAuthorizedSender, W as isSlackApprovalActionId, Y as resolveSlackQuestionAction, a as qualifySlackConversationId, et as escapeSlackMrkdwn, lt as isSlackAnyNativeApprovalClientEnabled, nt as decodeSlackApprovalAction, o as qualifySlackRoutePeerId, s as resolveSlackEnterpriseMainDmSessionKey, t as buildSlackChannelIdCandidates, xt as registerSlackInstallationState } from "./group-policy-BKjMqT-8.js";
5
5
  import { C as normalizeAllowListLower, D as resolveSlackUserAllowListForTeam, E as resolveSlackAllowListMatch, S as normalizeAllowList, T as normalizeSlackSlug, _ as resolveSlackLookupClientOptions, a as slackIngressIdentity, d as createSlackWebClient, i as createSlackIngressSubject, l as createSlackStartupAuthClient, o as formatSlackError, p as getSlackListenerUploadCompletionClient, v as resolveSlackProxyDispatcher, w as normalizeSlackAllowOwnerEntry, x as allowListMatches, y as resolveSlackWebClientOptions } from "./probe-gj5yQgN2.js";
6
6
  import { n as getSlackRuntime, t as getOptionalSlackRuntime } from "./runtime-JSVZSWAj.js";
7
- import { C as hasSlackMessageTableBlock, b as saveRemoteMedia, f as readSlackMessages, y as isGovSlackClient } from "./actions-BOxiu2Vy.js";
8
- import { i as setSlackDefaultSendIdentity, p as requireSlackPostMessageTimestamp } from "./send-GUz4_v2E.js";
9
- import { t as collectSlackCursorPages } from "./cursor-pages-eX7p8Wwt.js";
10
- import { t as resolveSlackChannelAllowlist } from "./resolve-channels-Bv6IiGZ4.js";
11
- import { t as resolveSlackUserAllowlist } from "./resolve-users-BXw2pA7y.js";
12
- import { n as resolveSlackChannelConfig, r as resolveSlackChannelLabel, t as isSlackChannelAllowedByPolicy } from "./policy-CUpBeOt9.js";
7
+ import { C as hasSlackMessageTableBlock, b as saveRemoteMedia, f as readSlackMessages, y as isGovSlackClient } from "./actions-fh66A6lc.js";
8
+ import { i as setSlackDefaultSendIdentity, p as requireSlackPostMessageTimestamp } from "./send-Djswy6lf.js";
9
+ import { t as collectSlackCursorPages } from "./cursor-pages-ByFwo-Py.js";
10
+ import { t as resolveSlackChannelAllowlist } from "./resolve-channels-CU7Bg5Ka.js";
11
+ import { t as resolveSlackUserAllowlist } from "./resolve-users-DrhttvRQ.js";
12
+ import { n as resolveSlackChannelConfig, r as resolveSlackChannelLabel, t as isSlackChannelAllowedByPolicy } from "./policy-D7PKkiet.js";
13
13
  import { normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
14
14
  import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
15
15
  import { asNonArrayRecord, asOptionalRecord, isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries, normalizeUniqueTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
@@ -161,10 +161,7 @@ function createSlackAgentViewState(params) {
161
161
  if (enabled) return true;
162
162
  if (loaded) return false;
163
163
  const stateKey = workspaceStateKey();
164
- if (!stateKey) {
165
- loaded = true;
166
- return false;
167
- }
164
+ if (!stateKey) return false;
168
165
  const openedStore = openWorkspaceStore();
169
166
  if (!openedStore) return false;
170
167
  try {
@@ -357,11 +354,14 @@ const DEFAULT_SLACK_SUGGESTED_PROMPTS = [
357
354
  }
358
355
  ];
359
356
  async function updateSlackSuggestedPrompts(params) {
360
- const prompts = params.prompts.map((prompt) => ({
361
- title: prompt.title.trim(),
362
- message: prompt.message.trim()
357
+ const prompts = params.prompts.map(({ title, message }) => ({
358
+ title: title.trim(),
359
+ message: message.trim()
363
360
  })).filter((prompt) => prompt.title && prompt.message).slice(0, 4);
364
- if (prompts.length === 0) return false;
361
+ if (prompts.length === 0) {
362
+ logVerbose(`slack suggested prompts update failed for channel ${params.channelId}: failed (no prompts)`);
363
+ return "failed";
364
+ }
365
365
  try {
366
366
  await params.client.assistant.threads.setSuggestedPrompts({
367
367
  token: params.botToken,
@@ -370,10 +370,12 @@ async function updateSlackSuggestedPrompts(params) {
370
370
  ...params.title?.trim() ? { title: params.title.trim() } : {},
371
371
  prompts
372
372
  });
373
- return true;
373
+ return "accepted";
374
374
  } catch (error) {
375
- logVerbose(`slack suggested prompts update failed for channel ${params.channelId}: ${formatSlackError(error)}`);
376
- return false;
375
+ const code = error instanceof WebAPIPlatformError ? error.data.error : void 0;
376
+ const outcome = code === "not_agent_app" || code === "missing_scope" ? "rejected" : code === "internal_error" ? "internal_error" : "failed";
377
+ logVerbose(`slack suggested prompts update failed for channel ${params.channelId}: ${outcome}: ${formatSlackError(error)}`);
378
+ return outcome;
377
379
  }
378
380
  }
379
381
  //#endregion
@@ -890,9 +892,9 @@ function resolveSlackInstallationIdentity(params) {
890
892
  const isEnterpriseInstall = auth.is_enterprise_install === true;
891
893
  const apiAppId = normalizeOptionalString(auth.app_id);
892
894
  const enterpriseId = normalizeOptionalString(auth.enterprise_id);
895
+ const transportApiAppId = normalizeOptionalString(params.transportApiAppId);
893
896
  if (isEnterpriseInstall) {
894
897
  if (!enterpriseId) throw new Error("Slack org-wide auth.test returned no enterprise_id");
895
- const transportApiAppId = normalizeOptionalString(params.transportApiAppId);
896
898
  if (apiAppId && transportApiAppId && apiAppId !== transportApiAppId) throw new Error(`Slack token mismatch: bot token app_id=${apiAppId} but transport app_id=${transportApiAppId}`);
897
899
  const effectiveApiAppId = apiAppId ?? transportApiAppId;
898
900
  return {
@@ -904,11 +906,12 @@ function resolveSlackInstallationIdentity(params) {
904
906
  const teamId = normalizeOptionalString(auth.team_id);
905
907
  if (!teamId) throw new Error("Slack workspace auth.test returned no team_id");
906
908
  const teamName = normalizeOptionalString(auth.team);
909
+ const workspaceApiAppId = apiAppId ?? transportApiAppId;
907
910
  return {
908
911
  kind: "workspace",
909
912
  teamId,
910
913
  ...teamName ? { teamName } : {},
911
- ...apiAppId ? { apiAppId } : {},
914
+ ...workspaceApiAppId ? { apiAppId: workspaceApiAppId } : {},
912
915
  ...enterpriseId ? { enterpriseId } : {}
913
916
  };
914
917
  }
@@ -2212,11 +2215,12 @@ function registerSlackHomeEvents(params) {
2212
2215
  if (!payload.user) return;
2213
2216
  if (payload.tab === "messages") {
2214
2217
  if (!payload.channel) return;
2215
- if (await ctx.setSlackSuggestedPrompts({
2218
+ const outcome = await ctx.setSlackSuggestedPrompts({
2216
2219
  channelId: payload.channel,
2217
2220
  title: "Try asking",
2218
2221
  prompts: DEFAULT_SLACK_SUGGESTED_PROMPTS
2219
- })) await ctx.recordSlackAgentView();
2222
+ });
2223
+ if (outcome === "accepted" || outcome === "internal_error") await ctx.recordSlackAgentView();
2220
2224
  return;
2221
2225
  }
2222
2226
  await ctx.app.client.views.publish({
@@ -4283,7 +4287,7 @@ function buildSlackDebounceKey(message, accountId, teamId) {
4283
4287
  }
4284
4288
  //#endregion
4285
4289
  //#region extensions/slack/src/monitor/message-handler.ts
4286
- const loadSlackMessagePipeline = createLazyRuntimeModule(() => import("./pipeline.runtime-CcdujV99.js"));
4290
+ const loadSlackMessagePipeline = createLazyRuntimeModule(() => import("./pipeline.runtime-BklS_NEj.js"));
4287
4291
  const RETRYABLE_FLUSH_MAX_ATTEMPTS = 3;
4288
4292
  const RETRYABLE_FLUSH_RETRY_DELAY_MS = 1e3;
4289
4293
  const REPLY_SESSION_INIT_CONFLICT_MESSAGE_RE = /reply session initialization conflicted for \S+/u;
@@ -4504,14 +4508,20 @@ function createSlackMessageHandler(params) {
4504
4508
  ctx.runtime.error?.(`slack inbound debounce flush failed: ${formatErrorMessage(err)}`);
4505
4509
  }
4506
4510
  });
4507
- const threadTsResolver = createSlackThreadTsResolver({ client: ctx.app.client });
4511
+ const threadTsResolvers = /* @__PURE__ */ new WeakMap();
4508
4512
  const pendingTopLevelDebounceKeys = /* @__PURE__ */ new Map();
4509
4513
  async function enqueueSlackMessage(message, opts) {
4510
4514
  if (opts.source === "message" && message.type !== "message") return;
4511
4515
  if (opts.source === "message" && message.subtype && message.subtype !== "file_share" && message.subtype !== "bot_message" && message.subtype !== "thread_broadcast") return;
4512
4516
  ctx.rememberSlackChannelType(message.channel, message.channel_type, opts.eventScope);
4513
4517
  trackEvent?.();
4514
- const resolvedMessage = await (opts.eventScope ? createSlackThreadTsResolver({ client: opts.eventScope.client }) : threadTsResolver).resolve({
4518
+ const client = opts.eventScope?.client ?? ctx.app.client;
4519
+ let threadTsResolver = threadTsResolvers.get(client);
4520
+ if (!threadTsResolver) {
4521
+ threadTsResolver = createSlackThreadTsResolver({ client });
4522
+ threadTsResolvers.set(client, threadTsResolver);
4523
+ }
4524
+ const resolvedMessage = await threadTsResolver.resolve({
4515
4525
  message,
4516
4526
  source: opts.source,
4517
4527
  ...opts.turnAdoptionLifecycle ? { turnAdoptionLifecycle: opts.turnAdoptionLifecycle } : {}
@@ -5007,7 +5017,10 @@ function createSlackBoltApp(params) {
5007
5017
  ...appReceiver ? { receiver: appReceiver } : {}
5008
5018
  });
5009
5019
  app.use(async (args) => {
5010
- await params.onContextIdentity?.(args.context ?? {});
5020
+ await params.onContextIdentity?.({
5021
+ ...args.context,
5022
+ apiAppId: normalizeOptionalString(asOptionalRecord(args.body)?.api_app_id)
5023
+ });
5011
5024
  if (shouldSkipOpenClawSlackSelfEvent(args)) return;
5012
5025
  await args.next();
5013
5026
  });
@@ -5256,7 +5269,7 @@ const SLACK_COMMAND_ARG_CONFIRM_TEXT_MAX = 300;
5256
5269
  const SLACK_HEADER_TEXT_MAX = 150;
5257
5270
  const SLACK_COMMAND_ARG_ACTION_BLOCKS_MAX = 47;
5258
5271
  const loadSlashCommandsRuntime = createLazyRuntimeModule(() => import("./slash-commands.runtime-BTTMlmwy.js"));
5259
- const loadSlashDispatchRuntime = createLazyRuntimeModule(() => import("./slash-dispatch.runtime-C2015r6s.js"));
5272
+ const loadSlashDispatchRuntime = createLazyRuntimeModule(() => import("./slash-dispatch.runtime-C3B4h5ZM.js"));
5260
5273
  const loadSlashSkillCommandsRuntime = createLazyRuntimeModule(() => import("./slash-skill-commands.runtime-CD1J2ODY.js"));
5261
5274
  const loadPluginCommandRuntime = createLazyRuntimeModule(() => import("openclaw/plugin-sdk/plugin-command-runtime"));
5262
5275
  function resolveSlackCommandMenuModelContext(params) {
@@ -6155,7 +6168,7 @@ async function getSlackBoltInterop() {
6155
6168
  }
6156
6169
  return slackBoltInterop;
6157
6170
  }
6158
- const loadSlackRelaySource = createLazyRuntimeModule(() => import("./relay-source-BLMdBrAw.js"));
6171
+ const loadSlackRelaySource = createLazyRuntimeModule(() => import("./relay-source-DWuduiJ2.js"));
6159
6172
  const SLACK_WEBHOOK_MAX_BODY_BYTES = 1048576;
6160
6173
  const SLACK_WEBHOOK_BODY_TIMEOUT_MS = 3e4;
6161
6174
  function resolveSlackRuntimeIdentity(params) {
@@ -6257,10 +6270,10 @@ async function monitorSlackProvider(opts = {}) {
6257
6270
  const mainKey = normalizeMainKey(sessionCfg?.mainKey);
6258
6271
  const slackMode = opts.mode ?? account.config.mode ?? "socket";
6259
6272
  const slackWebhookPath = normalizeSlackWebhookPath(account.config.webhookPath);
6260
- const signingSecret = normalizeResolvedSecretInputString({
6273
+ const signingSecret = slackMode === "http" ? normalizeResolvedSecretInputString({
6261
6274
  value: account.config.signingSecret,
6262
6275
  path: `channels.slack.accounts.${account.accountId}.signingSecret`
6263
- });
6276
+ }) : void 0;
6264
6277
  const botToken = resolveSlackBotToken(opts.botToken ?? account.botToken);
6265
6278
  const userToken = account.userToken;
6266
6279
  const appToken = resolveSlackAppToken(opts.appToken ?? account.appToken);
@@ -6335,7 +6348,7 @@ async function monitorSlackProvider(opts = {}) {
6335
6348
  slackMode,
6336
6349
  token,
6337
6350
  appToken: slackMode === "socket" ? appToken ?? void 0 : void 0,
6338
- signingSecret: slackMode === "http" ? signingSecret ?? void 0 : void 0,
6351
+ signingSecret: signingSecret ?? void 0,
6339
6352
  slackWebhookPath,
6340
6353
  clientOptions,
6341
6354
  dispatcher: slackDispatcher,
@@ -6362,6 +6375,13 @@ async function monitorSlackProvider(opts = {}) {
6362
6375
  installationState.update(contextInstallationIdentity.kind);
6363
6376
  await installSlackRuntimeForIdentity(contextInstallationIdentity);
6364
6377
  }
6378
+ if (!current.apiAppId && identity.apiAppId && current.installationIdentity.kind !== "degraded") {
6379
+ applySlackInstallationIdentity(current, {
6380
+ ...current.installationIdentity,
6381
+ apiAppId: identity.apiAppId
6382
+ });
6383
+ runtime.log?.(`[${account.accountId}] slack app id ${identity.apiAppId} learned from signed event`);
6384
+ }
6365
6385
  if (recovered || adopted) publishSlackConnectedStatus(opts.setStatus, current.identityHealth);
6366
6386
  }
6367
6387
  });
@@ -6684,10 +6704,7 @@ async function monitorSlackProvider(opts = {}) {
6684
6704
  app,
6685
6705
  config: slackCfg.execApprovals ?? {},
6686
6706
  resolveClient,
6687
- ...identity.kind === "enterprise" ? { enterprise: {
6688
- apiAppId: identity.apiAppId,
6689
- enterpriseId: identity.enterpriseId
6690
- } } : {}
6707
+ ...identity.kind === "enterprise" ? { enterprise: { enterpriseId: identity.enterpriseId } } : {}
6691
6708
  },
6692
6709
  abortSignal: opts.abortSignal
6693
6710
  });
@@ -1,4 +1,4 @@
1
- import { h as formatUnknownError, m as SLACK_SOCKET_RECONNECT_POLICY } from "./provider-DW9YC_no.js";
1
+ import { h as formatUnknownError, m as SLACK_SOCKET_RECONNECT_POLICY } from "./provider-Do50wMWn.js";
2
2
  import { asOptionalRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  import { computeBackoff, sleepWithAbort, warn } from "openclaw/plugin-sdk/runtime-env";
4
4
  import { isIP } from "node:net";