@openclaw/slack 2026.9.1-beta.1 → 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 (65) hide show
  1. package/dist/{account-inspect-CN2hBsim.js → account-inspect-C3sePHWa.js} +3 -3
  2. package/dist/account-inspect-api.js +1 -1
  3. package/dist/{action-runtime-BoSeX09X.js → action-runtime-DND4Pyp2.js} +84 -66
  4. package/dist/action-runtime.runtime-CEhbmS-Z.js +2 -0
  5. package/dist/{actions-XdQyjG_p.js → actions-fh66A6lc.js} +198 -54
  6. package/dist/api.js +14 -14
  7. package/dist/{approval-handler.runtime-DxXfGX_Z.js → approval-handler.runtime-D7d8sKM0.js} +18 -12
  8. package/dist/{channel-C_vnTgxo.js → channel-4m8IAdMD.js} +70 -128
  9. package/dist/channel-config-api.js +1 -1
  10. package/dist/channel-plugin-api.js +1 -1
  11. package/dist/{channel-type-j-2lalcC.js → channel-type-3-SqEMVc.js} +2 -2
  12. package/dist/{channel.setup-aal8tokM.js → channel.setup-t_ghLGb_.js} +23 -22
  13. package/dist/{config-schema-CN3XZRX5.js → config-schema-bP3eV2ra.js} +25 -16
  14. package/dist/{conversation-binding-route-DFVLUdYF.js → conversation-binding-route-Vee8Dgbf.js} +2 -2
  15. package/dist/{cursor-pages-eX7p8Wwt.js → cursor-pages-ByFwo-Py.js} +7 -1
  16. package/dist/{directory-config-DqfQ42OV.js → directory-config-Bmw4ykSy.js} +4 -3
  17. package/dist/directory-contract-api.js +1 -1
  18. package/dist/{directory-live-lC6X_Ru-.js → directory-live-q32AW7N1.js} +3 -8
  19. package/dist/{doctor-contract-BAy7-EUQ.js → doctor-contract-BNjw9bxb.js} +5 -4
  20. package/dist/doctor-contract-api.js +1 -1
  21. package/dist/{group-policy-CU1tEGpS.js → group-policy-BKjMqT-8.js} +161 -260
  22. package/dist/{message-tool-api-CWosHSi5.js → message-tool-api-uNEfQYGY.js} +19 -2
  23. package/dist/message-tool-api.js +1 -1
  24. package/dist/{monitor-DrNCGneD.js → monitor-Chwu_SiZ.js} +3 -3
  25. package/dist/{outbound-adapter-DkT2vUE9.js → outbound-adapter-BB8wAjm5.js} +95 -91
  26. package/dist/{pipeline.runtime-CRRng_Nw.js → pipeline.runtime-BklS_NEj.js} +347 -505
  27. package/dist/{policy-BoP6t88v.js → policy-D7PKkiet.js} +7 -4
  28. package/dist/{probe-4_aHtVT3.js → probe-gj5yQgN2.js} +210 -3
  29. package/dist/{provider-D4nDgxCh.js → provider-Do50wMWn.js} +168 -153
  30. package/dist/{relay-source-CEmze11m.js → relay-source-DWuduiJ2.js} +6 -4
  31. package/dist/{replies-D9XMM_S0.js → replies-Dc6WVh_Q.js} +20 -16
  32. package/dist/{resolve-channels-DSamDgVs.js → resolve-channels-CU7Bg5Ka.js} +6 -10
  33. package/dist/{resolve-users-CIzwbaJR.js → resolve-users-DrhttvRQ.js} +5 -4
  34. package/dist/runtime-api.js +10 -10
  35. package/dist/{scopes-BBrUzpBH.js → scopes-B9HRguDe.js} +1 -1
  36. package/dist/{send-DtjEnlLh.js → send-Djswy6lf.js} +24 -16
  37. package/dist/send-results-eeOu_HYm.js +23 -0
  38. package/dist/{send.runtime-DQeNKa2J.js → send.runtime-__WVTWLQ.js} +1 -1
  39. package/dist/setup-plugin-api.js +1 -1
  40. package/dist/{setup-surface-CsBCM4rP.js → setup-surface-DO0e-MMS.js} +5 -5
  41. package/dist/{shared-D9GeeR9K.js → shared-DEQBEKBL.js} +7 -5
  42. package/dist/{slash-dispatch.runtime-Chr3YHnT.js → slash-dispatch.runtime-C3B4h5ZM.js} +2 -2
  43. package/dist/{target-parsing-BnMD2ZqZ.js → target-parsing-PbxGDbr9.js} +11 -6
  44. package/dist/{targets-Cx5W_n3W.js → targets-7FexXJ62.js} +1 -1
  45. package/dist/{thread-ts-DUGhaYKq.js → thread-ts-CukseRVL.js} +5 -1
  46. package/node_modules/@slack/bolt/node_modules/negotiator/lib/accept.js +54 -0
  47. package/node_modules/@slack/bolt/node_modules/negotiator/lib/charset.js +10 -34
  48. package/node_modules/@slack/bolt/node_modules/negotiator/lib/encoding.js +9 -30
  49. package/node_modules/@slack/bolt/node_modules/negotiator/lib/language.js +15 -36
  50. package/node_modules/@slack/bolt/node_modules/negotiator/lib/mediaType.js +16 -134
  51. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/LICENSE +22 -0
  52. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/README.md +71 -0
  53. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.d.ts +46 -0
  54. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.js +176 -0
  55. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.js.map +1 -0
  56. package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/package.json +52 -0
  57. package/node_modules/@slack/bolt/node_modules/negotiator/package.json +16 -10
  58. package/node_modules/typebox/build/format/email.mjs +1 -1
  59. package/node_modules/typebox/build/format/idna/idn-hostname.mjs +19 -1
  60. package/node_modules/typebox/package.json +1 -1
  61. package/openclaw.plugin.json +15 -7
  62. package/package.json +5 -5
  63. package/dist/action-runtime.runtime-Dpa16J87.js +0 -2
  64. package/dist/slack-client-kind-hSfjXyUM.js +0 -94
  65. package/node_modules/@slack/bolt/node_modules/negotiator/HISTORY.md +0 -114
@@ -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
- import { a as parseSlackTarget, n as formatSlackTarget } from "./target-parsing-BnMD2ZqZ.js";
4
- import { $ as isSlackCallbackActionId, B as SLACK_TEXT_LIMIT, G as truncateSlackText, Nt as isSlackExecApprovalAuthorizedSender, Q as isSlackApprovalActionId, _t as isSlackAnyNativeApprovalClientEnabled, a as qualifySlackConversationId, c as allowListMatches, ct as escapeSlackMrkdwn, d as normalizeSlackAllowOwnerEntry, et as isSlackQuestionActionId, f as normalizeSlackSlug, jt as isSlackApprovalAuthorizedSender, kt as registerSlackInstallationState, l as normalizeAllowList, m as resolveSlackUserAllowListForTeam, nt as decodeSlackQuestionAction, o as qualifySlackRoutePeerId, p as resolveSlackAllowListMatch, rt as resolveSlackQuestionAction, s as resolveSlackEnterpriseMainDmSessionKey, t as buildSlackChannelIdCandidates, u as normalizeAllowListLower, ut as decodeSlackApprovalAction } from "./group-policy-CU1tEGpS.js";
5
- import { c as createSlackWebClient, g as resolveSlackWebClientOptions, h as resolveSlackProxyDispatcher, m as resolveSlackLookupClientOptions, o as createSlackStartupAuthClient, r as formatSlackError, u as getSlackListenerUploadCompletionClient } from "./probe-4_aHtVT3.js";
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-BKjMqT-8.js";
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 { i as hasSlackMessageTableBlock, r as saveRemoteMedia, t as isGovSlackClient } from "./slack-client-kind-hSfjXyUM.js";
8
- import { i as setSlackDefaultSendIdentity, p as requireSlackPostMessageTimestamp } from "./send-DtjEnlLh.js";
9
- import { t as collectSlackCursorPages } from "./cursor-pages-eX7p8Wwt.js";
10
- import { t as resolveSlackChannelAllowlist } from "./resolve-channels-DSamDgVs.js";
11
- import { t as resolveSlackUserAllowlist } from "./resolve-users-CIzwbaJR.js";
12
- import { n as resolveSlackChannelConfig, r as resolveSlackChannelLabel, t as isSlackChannelAllowedByPolicy } from "./policy-BoP6t88v.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";
@@ -20,12 +20,13 @@ import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
20
20
  import { computeBackoff, createNonExitingRuntime, createSubsystemLogger, danger, getChildLogger, logVerbose, shouldLogVerbose, sleepWithAbort, warn } from "openclaw/plugin-sdk/runtime-env";
21
21
  import { chunkItems } from "openclaw/plugin-sdk/text-chunking";
22
22
  import { CHANNEL_APPROVAL_NATIVE_RUNTIME_CONTEXT_CAPABILITY } from "openclaw/plugin-sdk/approval-handler-adapter-runtime";
23
+ import { addAllowlistUserEntriesFromConfigEntry, buildAllowlistResolutionSummary, formatAllowlistMatchMeta, mergeAllowlist, patchAllowlistUsersInConfigEntries, summarizeMapping } from "openclaw/plugin-sdk/allow-from";
23
24
  import { parseExecApprovalCommandText } from "openclaw/plugin-sdk/approval-reply-runtime";
24
25
  import { withTimeout } from "openclaw/plugin-sdk/text-utility-runtime";
25
26
  import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
26
27
  import { WebAPIHTTPError, WebAPIPlatformError, WebAPIRateLimitedError, WebAPIRequestError, WebClient } from "@slack/web-api";
27
- import { addAllowlistUserEntriesFromConfigEntry, buildAllowlistResolutionSummary, formatAllowlistMatchMeta, mergeAllowlist, patchAllowlistUsersInConfigEntries, summarizeMapping } from "openclaw/plugin-sdk/allow-from";
28
28
  import { buildPluginBindingResolvedText, parsePluginBindingApprovalCustomId, resolveConversationLabel as resolveConversationLabel$1, resolvePluginConversationBindingApproval, resolveRuntimeConversationBindingRoute, upsertChannelPairingRequest } from "openclaw/plugin-sdk/conversation-runtime";
29
+ import { createChannelIngressResolver, readChannelIngressStoreAllowFromForDmPolicy } from "openclaw/plugin-sdk/channel-ingress-runtime";
29
30
  import { collectErrorGraphCandidates, extractErrorCode, formatErrorMessage, isApprovalNotFoundError, readErrorName, toErrorObject } from "openclaw/plugin-sdk/error-runtime";
30
31
  import { resolveTextChunkLimit } from "openclaw/plugin-sdk/reply-chunking";
31
32
  import { buildChannelMetadata } from "openclaw/plugin-sdk/security-runtime";
@@ -44,12 +45,12 @@ import { resolveDefaultGroupPolicy, resolveOpenProviderRuntimeGroupPolicy as res
44
45
  import { resolveChannelConfigWrites } from "openclaw/plugin-sdk/channel-config-writes";
45
46
  import { mutateConfigFile, readConfigFileSnapshotForWrite } from "openclaw/plugin-sdk/config-mutation";
46
47
  import { enqueueRoutedSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
47
- import { createChannelIngressResolver, defineStableChannelIngressIdentity, readChannelIngressStoreAllowFromForDmPolicy } from "openclaw/plugin-sdk/channel-ingress-runtime";
48
48
  import { asDateTimestampMs, parseFiniteNumber, parseStrictFiniteNumber, resolveExpiresAtMsFromDurationMs, timestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
49
49
  import { resolveApprovalOverGateway } from "openclaw/plugin-sdk/approval-gateway-runtime";
50
50
  import { formatCommandArgMenuTitle, resolveCommandAuthorization, resolveEffectiveAgentRuntime, resolveNativeCommandSessionTargets, resolveStoredModelOverride } from "openclaw/plugin-sdk/command-auth-native";
51
51
  import { requestHeartbeat } from "openclaw/plugin-sdk/heartbeat-runtime";
52
52
  import { createChannelInteractiveDispatcher } from "openclaw/plugin-sdk/plugin-runtime";
53
+ import { reportChannelRoomJoin } from "openclaw/plugin-sdk/channel-join-intro-runtime";
53
54
  import { createChannelInboundDebouncer, shouldDebounceTextInbound } from "openclaw/plugin-sdk/channel-inbound";
54
55
  import { createChannelReplayGuard, runClaimableDedupeClaimLoop } from "openclaw/plugin-sdk/persistent-dedupe";
55
56
  import { channelBlockedPatch, channelReadyPatch } from "openclaw/plugin-sdk/gateway-runtime";
@@ -160,10 +161,7 @@ function createSlackAgentViewState(params) {
160
161
  if (enabled) return true;
161
162
  if (loaded) return false;
162
163
  const stateKey = workspaceStateKey();
163
- if (!stateKey) {
164
- loaded = true;
165
- return false;
166
- }
164
+ if (!stateKey) return false;
167
165
  const openedStore = openWorkspaceStore();
168
166
  if (!openedStore) return false;
169
167
  try {
@@ -236,8 +234,8 @@ function createSlackAgentViewState(params) {
236
234
  //#endregion
237
235
  //#region extensions/slack/src/monitor/assistant-thread-context.ts
238
236
  const SLACK_ASSISTANT_THREAD_CONTEXT_METADATA_EVENT = "assistant_thread_context";
239
- const SLACK_ASSISTANT_CONTEXT_TTL_MS = 1440 * 60 * 1e3;
240
- const SLACK_ASSISTANT_CONTEXT_CLEANUP_INTERVAL_MS = 600 * 1e3;
237
+ const SLACK_ASSISTANT_CONTEXT_TTL_MS = 864e5;
238
+ const SLACK_ASSISTANT_CONTEXT_CLEANUP_INTERVAL_MS = 6e5;
241
239
  function buildSlackAssistantThreadMetadata(context) {
242
240
  const eventPayload = {};
243
241
  if (context.channelId) eventPayload.channel_id = context.channelId;
@@ -356,11 +354,14 @@ const DEFAULT_SLACK_SUGGESTED_PROMPTS = [
356
354
  }
357
355
  ];
358
356
  async function updateSlackSuggestedPrompts(params) {
359
- const prompts = params.prompts.map((prompt) => ({
360
- title: prompt.title.trim(),
361
- message: prompt.message.trim()
357
+ const prompts = params.prompts.map(({ title, message }) => ({
358
+ title: title.trim(),
359
+ message: message.trim()
362
360
  })).filter((prompt) => prompt.title && prompt.message).slice(0, 4);
363
- 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
+ }
364
365
  try {
365
366
  await params.client.assistant.threads.setSuggestedPrompts({
366
367
  token: params.botToken,
@@ -369,10 +370,12 @@ async function updateSlackSuggestedPrompts(params) {
369
370
  ...params.title?.trim() ? { title: params.title.trim() } : {},
370
371
  prompts
371
372
  });
372
- return true;
373
+ return "accepted";
373
374
  } catch (error) {
374
- logVerbose(`slack suggested prompts update failed for channel ${params.channelId}: ${formatSlackError(error)}`);
375
- 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;
376
379
  }
377
380
  }
378
381
  //#endregion
@@ -476,12 +479,12 @@ function resolveSlackSystemEventRoute(params) {
476
479
  const SLACK_CHANNEL_CACHE_MAX_ENTRIES = 1024;
477
480
  const SLACK_USER_CACHE_MAX_ENTRIES = 2048;
478
481
  const SLACK_AVATAR_CACHE_MAX_ENTRIES = 128;
479
- const SLACK_AVATAR_MAX_BYTES = 256 * 1024;
482
+ const SLACK_AVATAR_MAX_BYTES = 262144;
480
483
  const SLACK_AVATAR_SSRF_POLICY = {
481
484
  allowedHostnames: ["avatars.slack-edge.com", "*.slack-edge.com"],
482
485
  hostnameAllowlist: ["avatars.slack-edge.com", "*.slack-edge.com"]
483
486
  };
484
- const SLACK_CHANNEL_DENIAL_WARNING_TTL_MS = 5 * 6e4;
487
+ const SLACK_CHANNEL_DENIAL_WARNING_TTL_MS = 3e5;
485
488
  const SLACK_CHANNEL_DENIAL_WARNING_MAX_ENTRIES = 1024;
486
489
  function createSlackMonitorContext(params) {
487
490
  const channelHistories = /* @__PURE__ */ new Map();
@@ -586,7 +589,8 @@ function createSlackMonitorContext(params) {
586
589
  }
587
590
  };
588
591
  const resolveUserAvatar = (userId, eventScope) => {
589
- if (isGovSlackClient(eventScope?.client ?? params.app.client)) return;
592
+ const client = eventScope?.client ?? params.app.client;
593
+ if (isGovSlackClient(client)) return;
590
594
  const imageUrl = readLruMapEntry(userCache, scopedKey(userId, eventScope))?.imageUrl;
591
595
  if (!imageUrl) return;
592
596
  const cacheKey = scopedKey(`${userId}\0${imageUrl}`, eventScope);
@@ -888,9 +892,9 @@ function resolveSlackInstallationIdentity(params) {
888
892
  const isEnterpriseInstall = auth.is_enterprise_install === true;
889
893
  const apiAppId = normalizeOptionalString(auth.app_id);
890
894
  const enterpriseId = normalizeOptionalString(auth.enterprise_id);
895
+ const transportApiAppId = normalizeOptionalString(params.transportApiAppId);
891
896
  if (isEnterpriseInstall) {
892
897
  if (!enterpriseId) throw new Error("Slack org-wide auth.test returned no enterprise_id");
893
- const transportApiAppId = normalizeOptionalString(params.transportApiAppId);
894
898
  if (apiAppId && transportApiAppId && apiAppId !== transportApiAppId) throw new Error(`Slack token mismatch: bot token app_id=${apiAppId} but transport app_id=${transportApiAppId}`);
895
899
  const effectiveApiAppId = apiAppId ?? transportApiAppId;
896
900
  return {
@@ -902,11 +906,12 @@ function resolveSlackInstallationIdentity(params) {
902
906
  const teamId = normalizeOptionalString(auth.team_id);
903
907
  if (!teamId) throw new Error("Slack workspace auth.test returned no team_id");
904
908
  const teamName = normalizeOptionalString(auth.team);
909
+ const workspaceApiAppId = apiAppId ?? transportApiAppId;
905
910
  return {
906
911
  kind: "workspace",
907
912
  teamId,
908
913
  ...teamName ? { teamName } : {},
909
- ...apiAppId ? { apiAppId } : {},
914
+ ...workspaceApiAppId ? { apiAppId: workspaceApiAppId } : {},
910
915
  ...enterpriseId ? { enterpriseId } : {}
911
916
  };
912
917
  }
@@ -1388,7 +1393,8 @@ function createSlackDurableIngress(options) {
1388
1393
  }
1389
1394
  };
1390
1395
  try {
1391
- if (asOptionalRecord(raw.kind === "events-api" ? asOptionalRecord(raw.body)?.event : void 0)?.type === "channel_id_changed") {
1396
+ const event = raw.kind === "events-api" ? asOptionalRecord(raw.body)?.event : void 0;
1397
+ if (asOptionalRecord(event)?.type === "channel_id_changed") {
1392
1398
  const channelTurns = activeChannelTurns.get(laneKey);
1393
1399
  if (channelTurns && channelTurns.size > 0) {
1394
1400
  adoptOnCompletion = true;
@@ -1500,7 +1506,8 @@ async function resolveThreadTsFromHistory(params) {
1500
1506
  inclusive: true,
1501
1507
  limit: 1
1502
1508
  });
1503
- return normalizeOptionalString((response.messages?.find((entry) => entry.ts === params.messageTs) ?? response.messages?.[0])?.thread_ts);
1509
+ const message = response.messages?.find((entry) => entry.ts === params.messageTs) ?? response.messages?.[0];
1510
+ return normalizeOptionalString(message?.thread_ts);
1504
1511
  }
1505
1512
  function createSlackThreadTsResolver(params) {
1506
1513
  const ttlMs = Math.max(0, parseFiniteNumber(params.cacheTtlMs) ?? DEFAULT_THREAD_TS_CACHE_TTL_MS);
@@ -1586,88 +1593,7 @@ const slackChannelMembersCache = /* @__PURE__ */ new WeakMap();
1586
1593
  const DEFAULT_CHANNEL_MEMBERS_CACHE_TTL_MS = 6e4;
1587
1594
  const CHANNEL_MEMBERS_CACHE_MAX = 512;
1588
1595
  const SLACK_CHANNEL_ID = "slack";
1589
- const SLACK_USER_NAME_KIND = "plugin:slack-user-name";
1590
- const SLACK_WORKSPACE_USER_ID_KIND = "plugin:slack-workspace-user-id";
1591
1596
  var SlackSystemEventAuthRetryError = class extends Error {};
1592
- function normalizeSlackUserId(raw) {
1593
- const value = (raw ?? "").trim().toLowerCase();
1594
- if (!value) return "";
1595
- const mention = value.match(/^<@([a-z0-9_]+)>$/i);
1596
- if (mention?.[1]) return mention[1];
1597
- return value.replace(/^(slack:|user:)/, "");
1598
- }
1599
- function isSlackStableUserId(value) {
1600
- return /^[ubw][a-z0-9_]+$/i.test(value);
1601
- }
1602
- function normalizeSlackWorkspaceUserEntry(entry) {
1603
- const normalized = entry.trim().toLowerCase();
1604
- if (!normalized) return null;
1605
- try {
1606
- const target = parseSlackTarget(normalized);
1607
- if (target?.kind === "user" && target.teamId) return target.normalized;
1608
- } catch {
1609
- return null;
1610
- }
1611
- return null;
1612
- }
1613
- function normalizeSlackBareUserEntry(entry) {
1614
- const normalized = entry.trim().toLowerCase();
1615
- if (!normalized || normalizeSlackWorkspaceUserEntry(normalized)) return null;
1616
- const userId = normalizeSlackUserId(normalized);
1617
- return isSlackStableUserId(userId) ? userId : null;
1618
- }
1619
- function normalizeSlackStableEntry(entry) {
1620
- return normalizeSlackBareUserEntry(entry) ?? normalizeSlackWorkspaceUserEntry(entry);
1621
- }
1622
- function normalizeSlackNameEntry(entry) {
1623
- const normalized = entry.trim().toLowerCase();
1624
- if (!normalized || normalizeSlackStableEntry(normalized)) return null;
1625
- return normalized.replace(/^slack:/, "") || null;
1626
- }
1627
- function normalizeSlackNameSubject(value) {
1628
- return value.trim().toLowerCase() || null;
1629
- }
1630
- function normalizeSlackNameSlugEntry(entry) {
1631
- const name = normalizeSlackNameEntry(entry);
1632
- if (!name) return null;
1633
- const slug = normalizeSlackSlug(name);
1634
- return slug && slug !== name ? slug : null;
1635
- }
1636
- const slackIngressIdentity = defineStableChannelIngressIdentity({
1637
- key: "senderId",
1638
- kind: "stable-id",
1639
- normalizeEntry: normalizeSlackBareUserEntry,
1640
- normalizeSubject: normalizeSlackUserId,
1641
- sensitivity: "pii",
1642
- aliases: [{
1643
- key: "workspaceSenderId",
1644
- kind: SLACK_WORKSPACE_USER_ID_KIND,
1645
- normalizeEntry: normalizeSlackWorkspaceUserEntry,
1646
- normalizeSubject: normalizeSlackWorkspaceUserEntry,
1647
- sensitivity: "pii"
1648
- }, ...[["senderName", normalizeSlackNameEntry], ["senderNameSlug", normalizeSlackNameSlugEntry]].map(([key, normalizeEntry]) => ({
1649
- key,
1650
- kind: SLACK_USER_NAME_KIND,
1651
- normalizeEntry,
1652
- normalizeSubject: normalizeSlackNameSubject,
1653
- dangerous: true,
1654
- sensitivity: "pii"
1655
- }))]
1656
- });
1657
- function createSlackIngressSubject(params) {
1658
- const senderId = normalizeSlackUserId(params.senderId);
1659
- const teamId = normalizeOptionalLowercaseString(params.teamId);
1660
- const senderName = params.senderName?.trim().toLowerCase();
1661
- const senderNameSlug = senderName ? normalizeSlackSlug(senderName) : void 0;
1662
- return {
1663
- stableId: senderId,
1664
- aliases: {
1665
- workspaceSenderId: teamId && senderId ? `team:${teamId}:user:${senderId}` : void 0,
1666
- senderName,
1667
- senderNameSlug
1668
- }
1669
- };
1670
- }
1671
1597
  function createSlackIngressResolver(ctx) {
1672
1598
  return createChannelIngressResolver({
1673
1599
  channelId: SLACK_CHANNEL_ID,
@@ -1909,7 +1835,7 @@ async function decideSlackSystemIngress(params) {
1909
1835
  } : void 0
1910
1836
  };
1911
1837
  const result = await resolver.message(input);
1912
- if (result.ingress.decision !== "allow" && params.retryNameLookup && result.state.allowlists[isDirectMessage ? "dm" : "group"].normalizedEntries.some((entry) => entry.kind === SLACK_USER_NAME_KIND)) {
1838
+ if (result.ingress.decision !== "allow" && params.retryNameLookup && result.state.allowlists[isDirectMessage ? "dm" : "group"].normalizedEntries.some((entry) => entry.kind === "plugin:slack-user-name")) {
1913
1839
  const lookup = await params.ctx.resolveUserName(params.senderId, params.eventScope);
1914
1840
  if (lookup.error && isTransientSlackThreadLookupError(lookup.error)) throw new SlackSystemEventAuthRetryError(formatErrorMessage(lookup.error));
1915
1841
  if (lookup.name) return (await resolver.message({
@@ -2037,7 +1963,8 @@ function resolveSlackEventScope(params) {
2037
1963
  ok: false,
2038
1964
  reason: "enterprise_event_for_workspace_account"
2039
1965
  } : { ok: true };
2040
- const apiAppId = normalizeOptionalString((params.body && typeof params.body === "object" ? params.body : {}).api_app_id);
1966
+ const body = params.body && typeof params.body === "object" ? params.body : {};
1967
+ const apiAppId = normalizeOptionalString(body.api_app_id);
2041
1968
  if (apiAppId && params.identity.apiAppId && apiAppId !== params.identity.apiAppId) return {
2042
1969
  ok: false,
2043
1970
  reason: "wrong_app"
@@ -2200,9 +2127,10 @@ function registerSlackChannelIdChangedEvent(params) {
2200
2127
  const oldChannelId = payload.old_channel_id;
2201
2128
  const newChannelId = payload.new_channel_id;
2202
2129
  if (!oldChannelId || !newChannelId) return;
2130
+ const channelInfo = await ctx.resolveChannelName(newChannelId);
2203
2131
  const label = resolveSlackChannelLabel({
2204
2132
  channelId: newChannelId,
2205
- channelName: (await ctx.resolveChannelName(newChannelId))?.name
2133
+ channelName: channelInfo?.name
2206
2134
  });
2207
2135
  ctx.runtime.log?.(warn(`[slack] Channel ID changed: ${oldChannelId} → ${newChannelId} (${label})`));
2208
2136
  if (!resolveChannelConfigWrites({
@@ -2287,11 +2215,12 @@ function registerSlackHomeEvents(params) {
2287
2215
  if (!payload.user) return;
2288
2216
  if (payload.tab === "messages") {
2289
2217
  if (!payload.channel) return;
2290
- if (await ctx.setSlackSuggestedPrompts({
2218
+ const outcome = await ctx.setSlackSuggestedPrompts({
2291
2219
  channelId: payload.channel,
2292
2220
  title: "Try asking",
2293
2221
  prompts: DEFAULT_SLACK_SUGGESTED_PROMPTS
2294
- })) await ctx.recordSlackAgentView();
2222
+ });
2223
+ if (outcome === "accepted" || outcome === "internal_error") await ctx.recordSlackAgentView();
2295
2224
  return;
2296
2225
  }
2297
2226
  await ctx.app.client.views.publish({
@@ -2455,7 +2384,8 @@ function isSlackReplyActionId(actionId) {
2455
2384
  return actionId === "openclaw:reply_button" || actionId === "openclaw:reply_select" || actionId.startsWith(`openclaw:reply_button:`) || actionId.startsWith(`openclaw:reply_select:`);
2456
2385
  }
2457
2386
  function readSlackApprovalAction(parsed) {
2458
- return decodeSlackApprovalAction(normalizeOptionalString(parsed.actionSummary.value) ?? parsed.actionSummary.selectedValues?.map((entry) => normalizeOptionalString(entry)).find((entry) => Boolean(entry)));
2387
+ const value = normalizeOptionalString(parsed.actionSummary.value) ?? parsed.actionSummary.selectedValues?.map((entry) => normalizeOptionalString(entry)).find((entry) => Boolean(entry));
2388
+ return decodeSlackApprovalAction(value);
2459
2389
  }
2460
2390
  function isSlackReplyLinkAction(parsed) {
2461
2391
  if (parsed.actionId === "openclaw:session_link") return true;
@@ -2580,11 +2510,19 @@ async function handleSlackPluginBindingApproval(params) {
2580
2510
  await respondEphemeral(params.respond, buildPluginBindingResolvedText(resolved));
2581
2511
  return true;
2582
2512
  }
2513
+ function formatSlackPluginApprovalSenderId(userId, eventScope) {
2514
+ return formatSlackTarget({
2515
+ kind: "user",
2516
+ id: userId,
2517
+ teamId: eventScope?.teamId
2518
+ });
2519
+ }
2583
2520
  async function handleSlackApprovalInteraction(params) {
2521
+ const pluginSenderId = formatSlackPluginApprovalSenderId(params.parsed.userId, params.eventScope);
2584
2522
  const pluginApprovalAuthorizedSender = isSlackApprovalAuthorizedSender({
2585
2523
  cfg: params.ctx.cfg,
2586
2524
  accountId: params.ctx.accountId,
2587
- senderId: params.parsed.userId
2525
+ senderId: pluginSenderId
2588
2526
  });
2589
2527
  const execApprovalAuthorizedSender = isSlackExecApprovalAuthorizedSender({
2590
2528
  cfg: params.ctx.cfg,
@@ -2604,7 +2542,7 @@ async function handleSlackApprovalInteraction(params) {
2604
2542
  decision: params.approval.decision,
2605
2543
  channel: "slack",
2606
2544
  accountId: params.ctx.accountId,
2607
- senderId: params.parsed.userId
2545
+ senderId: params.approval.approvalKind === "plugin" ? pluginSenderId : params.parsed.userId
2608
2546
  });
2609
2547
  const terminalLabel = resolveSlackApprovalTerminalLabel(result.approval);
2610
2548
  const prefix = result.applied ? "Resolved" : "Already resolved";
@@ -2640,10 +2578,11 @@ async function handleSlackApprovalInteraction(params) {
2640
2578
  async function handleSlackLegacyApprovalInteraction(params) {
2641
2579
  const parsedApproval = parseExecApprovalCommandText(params.pluginInteractionData);
2642
2580
  if (!parsedApproval) return false;
2581
+ const pluginSenderId = formatSlackPluginApprovalSenderId(params.parsed.userId, params.eventScope);
2643
2582
  const pluginAuthorized = isSlackApprovalAuthorizedSender({
2644
2583
  cfg: params.ctx.cfg,
2645
2584
  accountId: params.ctx.accountId,
2646
- senderId: params.parsed.userId
2585
+ senderId: pluginSenderId
2647
2586
  });
2648
2587
  const execAuthorized = isSlackExecApprovalAuthorizedSender({
2649
2588
  cfg: params.ctx.cfg,
@@ -2665,7 +2604,7 @@ async function handleSlackLegacyApprovalInteraction(params) {
2665
2604
  decision: parsedApproval.decision,
2666
2605
  channel: "slack",
2667
2606
  accountId: params.ctx.accountId,
2668
- senderId: params.parsed.userId,
2607
+ senderId: resolveMethod === "plugin" ? pluginSenderId : params.parsed.userId,
2669
2608
  resolveMethod
2670
2609
  });
2671
2610
  try {
@@ -3651,6 +3590,55 @@ function registerSlackMemberEvents(params) {
3651
3590
  const channelId = payload.channel;
3652
3591
  const channelInfo = channelId ? await ctx.resolveChannelName(channelId, eventScope) : {};
3653
3592
  const channelType = payload.channel_type ?? channelInfo?.type;
3593
+ if (paramsLocal.verb === "joined" && payload.user === ctx.botUserId && channelId) {
3594
+ const roomType = normalizeSlackChannelType(channelType, channelId);
3595
+ if (roomType === "channel" || roomType === "group") {
3596
+ const roomAllowed = ctx.isChannelAllowed({
3597
+ teamId: eventScope?.teamId ?? ctx.teamId,
3598
+ channelId,
3599
+ channelName: channelInfo.name,
3600
+ channelType: roomType
3601
+ });
3602
+ const inviterLabel = roomAllowed && payload.inviter ? (await ctx.resolveUserName(payload.inviter, eventScope)).name ?? payload.inviter : void 0;
3603
+ await reportChannelRoomJoin({
3604
+ cfg: ctx.cfg,
3605
+ channel: "slack",
3606
+ accountId: ctx.accountId,
3607
+ conversationId: channelId,
3608
+ deliverTo: `channel:${channelId}`,
3609
+ route: ctx.resolveSlackSystemEventRoute({
3610
+ channelId,
3611
+ channelType: roomType,
3612
+ eventScope
3613
+ }),
3614
+ inviterLabel,
3615
+ roomAllowed,
3616
+ resolveRoomContext: async ({ messageLimit }) => {
3617
+ const purpose = [channelInfo.purpose, channelInfo.topic].filter((value) => Boolean(value?.trim())).join("\n");
3618
+ const roomContext = {
3619
+ title: channelInfo.name ? `#${channelInfo.name}` : void 0,
3620
+ purpose: purpose || void 0
3621
+ };
3622
+ try {
3623
+ const { messages } = await readSlackMessages(channelId, {
3624
+ limit: messageLimit,
3625
+ client: eventScope?.client ?? ctx.app.client
3626
+ });
3627
+ return {
3628
+ ...roomContext,
3629
+ recentMessages: messages.toReversed().flatMap(({ user, text }) => text?.trim() ? [{
3630
+ sender: user,
3631
+ text
3632
+ }] : [])
3633
+ };
3634
+ } catch {
3635
+ return roomContext;
3636
+ }
3637
+ }
3638
+ });
3639
+ return;
3640
+ }
3641
+ }
3654
3642
  const ingressContext = await authorizeAndResolveSlackSystemEventContext({
3655
3643
  ctx,
3656
3644
  senderId: payload.user,
@@ -3660,7 +3648,8 @@ function registerSlackMemberEvents(params) {
3660
3648
  eventScope
3661
3649
  });
3662
3650
  if (!ingressContext) return;
3663
- enqueueRoutedSystemEvent(`Slack: ${(payload.user ? await ctx.resolveUserName(payload.user, eventScope) : {})?.name ?? payload.user ?? "someone"} ${paramsLocal.verb} ${ingressContext.channelLabel}.`, ingressContext.route, { contextKey: `slack:member:${eventScope ? `${eventScope.teamId}:` : ""}${paramsLocal.verb}:${channelId ?? "unknown"}:${payload.user ?? "unknown"}:${paramsLocal.eventId}` });
3651
+ const userLabel = (payload.user ? await ctx.resolveUserName(payload.user, eventScope) : {})?.name ?? payload.user ?? "someone";
3652
+ enqueueRoutedSystemEvent(`Slack: ${userLabel} ${paramsLocal.verb} ${ingressContext.channelLabel}.`, ingressContext.route, { contextKey: `slack:member:${eventScope ? `${eventScope.teamId}:` : ""}${paramsLocal.verb}:${channelId ?? "unknown"}:${payload.user ?? "unknown"}:${paramsLocal.eventId}` });
3664
3653
  } catch (err) {
3665
3654
  ctx.runtime.error?.(danger(`slack ${paramsLocal.verb} handler failed: ${formatErrorMessage(err)}`));
3666
3655
  if (err instanceof SlackSystemEventAuthRetryError) throw err;
@@ -3850,7 +3839,8 @@ function addUserCandidate(candidates, value, botUserId) {
3850
3839
  candidates.add(id);
3851
3840
  }
3852
3841
  function collectMetadataUserCandidates(candidates, value, botUserId) {
3853
- const payload = asOptionalRecord(asOptionalRecord(value)?.event_payload);
3842
+ const metadata = asOptionalRecord(value);
3843
+ const payload = asOptionalRecord(metadata?.event_payload);
3854
3844
  if (!payload) return;
3855
3845
  for (const key of [
3856
3846
  "user",
@@ -4150,7 +4140,8 @@ function registerSlackReactionEvents(params) {
4150
4140
  const emojiLabel = event.reaction ?? "emoji";
4151
4141
  const authorLabel = authorInfo?.name ?? event.item_user;
4152
4142
  const baseText = `Slack reaction ${action}: :${emojiLabel}: by ${actorLabel} in ${ingressContext.channelLabel} msg ${item.ts}`;
4153
- enqueueRoutedSystemEvent(authorLabel ? `${baseText} from ${authorLabel}` : baseText, ingressContext.route, { contextKey: `slack:reaction:${eventScope ? `${eventScope.teamId}:` : ""}${action}:${item.channel}:${item.ts}:${event.user}:${emojiLabel}:${eventId}` });
4143
+ const text = authorLabel ? `${baseText} from ${authorLabel}` : baseText;
4144
+ enqueueRoutedSystemEvent(text, ingressContext.route, { contextKey: `slack:reaction:${eventScope ? `${eventScope.teamId}:` : ""}${action}:${item.channel}:${item.ts}:${event.user}:${emojiLabel}:${eventId}` });
4154
4145
  } catch (err) {
4155
4146
  ctx.runtime.error?.(danger(`slack reaction handler failed: ${formatErrorMessage(err)}`));
4156
4147
  }
@@ -4229,7 +4220,7 @@ function registerSlackWorkspaceEvents(params) {
4229
4220
  }
4230
4221
  //#endregion
4231
4222
  //#region extensions/slack/src/monitor/message-dispatch-dedupe.ts
4232
- const SLACK_MESSAGE_DISPATCH_DEDUPE_TTL_MS = 1440 * 60 * 1e3;
4223
+ const SLACK_MESSAGE_DISPATCH_DEDUPE_TTL_MS = 864e5;
4233
4224
  const SLACK_MESSAGE_DISPATCH_DEDUPE_MEMORY_MAX_ENTRIES = 2e4;
4234
4225
  const SLACK_MESSAGE_DISPATCH_DEDUPE_STATE_MAX_ENTRIES = 2e4;
4235
4226
  const SLACK_MESSAGE_DISPATCH_DEDUPE_NAMESPACE = "global";
@@ -4296,7 +4287,7 @@ function buildSlackDebounceKey(message, accountId, teamId) {
4296
4287
  }
4297
4288
  //#endregion
4298
4289
  //#region extensions/slack/src/monitor/message-handler.ts
4299
- const loadSlackMessagePipeline = createLazyRuntimeModule(() => import("./pipeline.runtime-CRRng_Nw.js"));
4290
+ const loadSlackMessagePipeline = createLazyRuntimeModule(() => import("./pipeline.runtime-BklS_NEj.js"));
4300
4291
  const RETRYABLE_FLUSH_MAX_ATTEMPTS = 3;
4301
4292
  const RETRYABLE_FLUSH_RETRY_DELAY_MS = 1e3;
4302
4293
  const REPLY_SESSION_INIT_CONFLICT_MESSAGE_RE = /reply session initialization conflicted for \S+/u;
@@ -4304,8 +4295,9 @@ function isRetryableSlackInboundError(error) {
4304
4295
  return collectErrorGraphCandidates(error, (current) => [current.cause, current.error]).some((candidate) => REPLY_SESSION_INIT_CONFLICT_MESSAGE_RE.test(formatErrorMessage(candidate)));
4305
4296
  }
4306
4297
  function shouldDebounceSlackMessage(message, cfg) {
4298
+ const textForCommandDetection = stripSlackMentionsForCommandDetection(message.text ?? "");
4307
4299
  return shouldDebounceTextInbound({
4308
- text: stripSlackMentionsForCommandDetection(message.text ?? ""),
4300
+ text: textForCommandDetection,
4309
4301
  cfg,
4310
4302
  hasMedia: Boolean(message.files && message.files.length > 0) || hasSlackMessageTableBlock(message)
4311
4303
  });
@@ -4477,6 +4469,10 @@ function createSlackMessageHandler(params) {
4477
4469
  if (admissionLifecycle.onDeferred() === false) return false;
4478
4470
  settlementHandedOff = true;
4479
4471
  },
4472
+ onDeferredHeartbeat: () => {
4473
+ turnAdoptionLifecycle?.onDeferredHeartbeat?.();
4474
+ admissionLifecycle.onDeferredHeartbeat?.();
4475
+ },
4480
4476
  onAbandoned: () => {
4481
4477
  settlementHandedOff = true;
4482
4478
  releaseClaims();
@@ -4512,14 +4508,20 @@ function createSlackMessageHandler(params) {
4512
4508
  ctx.runtime.error?.(`slack inbound debounce flush failed: ${formatErrorMessage(err)}`);
4513
4509
  }
4514
4510
  });
4515
- const threadTsResolver = createSlackThreadTsResolver({ client: ctx.app.client });
4511
+ const threadTsResolvers = /* @__PURE__ */ new WeakMap();
4516
4512
  const pendingTopLevelDebounceKeys = /* @__PURE__ */ new Map();
4517
4513
  async function enqueueSlackMessage(message, opts) {
4518
4514
  if (opts.source === "message" && message.type !== "message") return;
4519
4515
  if (opts.source === "message" && message.subtype && message.subtype !== "file_share" && message.subtype !== "bot_message" && message.subtype !== "thread_broadcast") return;
4520
4516
  ctx.rememberSlackChannelType(message.channel, message.channel_type, opts.eventScope);
4521
4517
  trackEvent?.();
4522
- 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({
4523
4525
  message,
4524
4526
  source: opts.source,
4525
4527
  ...opts.turnAdoptionLifecycle ? { turnAdoptionLifecycle: opts.turnAdoptionLifecycle } : {}
@@ -4559,11 +4561,11 @@ function createSlackMessageHandler(params) {
4559
4561
  }
4560
4562
  //#endregion
4561
4563
  //#region extensions/slack/src/monitor/presence-monitor.ts
4562
- const SLACK_PRESENCE_GREETING_COOLDOWN_MS = 480 * 60 * 1e3;
4564
+ const SLACK_PRESENCE_GREETING_COOLDOWN_MS = 288e5;
4563
4565
  const SLACK_PRESENCE_REQUEST_TIMEOUT_MS = 3e4;
4564
4566
  const SLACK_PRESENCE_POLL_INTERVAL_MS = 6e4;
4565
4567
  const SLACK_PRESENCE_AUTO_MAX_PARTICIPANTS = 8;
4566
- const SLACK_PRESENCE_TARGET_TTL_MS = 1440 * 60 * 1e3;
4568
+ const SLACK_PRESENCE_TARGET_TTL_MS = 864e5;
4567
4569
  const SLACK_PRESENCE_MAX_POLLS_PER_INTERVAL = 45;
4568
4570
  const SLACK_PRESENCE_MAX_TARGETS = 2e3;
4569
4571
  const DEFAULT_SLACK_PRESENCE_EVENT_PROMPT = ["Before greeting, retrieve relevant memory and wiki context for this immutable user_id, including a known timezone when available. Use their local time; if their timezone is unknown, do not guess.", "Send at most one short, natural greeting in this Slack conversation. Do not reveal private memory. If no greeting is appropriate, stay silent."];
@@ -5015,7 +5017,10 @@ function createSlackBoltApp(params) {
5015
5017
  ...appReceiver ? { receiver: appReceiver } : {}
5016
5018
  });
5017
5019
  app.use(async (args) => {
5018
- await params.onContextIdentity?.(args.context ?? {});
5020
+ await params.onContextIdentity?.({
5021
+ ...args.context,
5022
+ apiAppId: normalizeOptionalString(asOptionalRecord(args.body)?.api_app_id)
5023
+ });
5019
5024
  if (shouldSkipOpenClawSlackSelfEvent(args)) return;
5020
5025
  await args.next();
5021
5026
  });
@@ -5171,8 +5176,8 @@ async function authorizeSlackDirectMessage(params) {
5171
5176
  //#endregion
5172
5177
  //#region extensions/slack/src/monitor/external-arg-menu-store.ts
5173
5178
  const SLACK_EXTERNAL_ARG_MENU_TOKEN_BYTES = 18;
5174
- const SLACK_EXTERNAL_ARG_MENU_TOKEN_PATTERN = new RegExp(`^[A-Za-z0-9_-]{${Math.ceil(SLACK_EXTERNAL_ARG_MENU_TOKEN_BYTES * 8 / 6)}}$`);
5175
- const SLACK_EXTERNAL_ARG_MENU_TTL_MS = 600 * 1e3;
5179
+ const SLACK_EXTERNAL_ARG_MENU_TOKEN_PATTERN = new RegExp(`^[A-Za-z0-9_-]{${Math.ceil(24)}}$`);
5180
+ const SLACK_EXTERNAL_ARG_MENU_TTL_MS = 6e5;
5176
5181
  const SLACK_EXTERNAL_ARG_MENU_PREFIX = "openclaw_cmdarg_ext:";
5177
5182
  function pruneSlackExternalArgMenuStore(store, rawNow) {
5178
5183
  const now = asDateTimestampMs(rawNow);
@@ -5264,7 +5269,7 @@ const SLACK_COMMAND_ARG_CONFIRM_TEXT_MAX = 300;
5264
5269
  const SLACK_HEADER_TEXT_MAX = 150;
5265
5270
  const SLACK_COMMAND_ARG_ACTION_BLOCKS_MAX = 47;
5266
5271
  const loadSlashCommandsRuntime = createLazyRuntimeModule(() => import("./slash-commands.runtime-BTTMlmwy.js"));
5267
- const loadSlashDispatchRuntime = createLazyRuntimeModule(() => import("./slash-dispatch.runtime-Chr3YHnT.js"));
5272
+ const loadSlashDispatchRuntime = createLazyRuntimeModule(() => import("./slash-dispatch.runtime-C3B4h5ZM.js"));
5268
5273
  const loadSlashSkillCommandsRuntime = createLazyRuntimeModule(() => import("./slash-skill-commands.runtime-CD1J2ODY.js"));
5269
5274
  const loadPluginCommandRuntime = createLazyRuntimeModule(() => import("openclaw/plugin-sdk/plugin-command-runtime"));
5270
5275
  function resolveSlackCommandMenuModelContext(params) {
@@ -5315,6 +5320,8 @@ function resolveSlackCommandMenuModelContext(params) {
5315
5320
  }
5316
5321
  const slackExternalArgMenuStore = createSlackExternalArgMenuStore();
5317
5322
  function buildSlackArgMenuConfirm(params) {
5323
+ const command = escapeSlackMrkdwn(params.command);
5324
+ const arg = escapeSlackMrkdwn(params.arg);
5318
5325
  return {
5319
5326
  title: {
5320
5327
  type: "plain_text",
@@ -5322,7 +5329,7 @@ function buildSlackArgMenuConfirm(params) {
5322
5329
  },
5323
5330
  text: {
5324
5331
  type: "mrkdwn",
5325
- text: truncateSlackText(`Run */${escapeSlackMrkdwn(params.command)}* with *${escapeSlackMrkdwn(params.arg)}* set to this value?`, SLACK_COMMAND_ARG_CONFIRM_TEXT_MAX)
5332
+ text: truncateSlackText(`Run */${command}* with *${arg}* set to this value?`, SLACK_COMMAND_ARG_CONFIRM_TEXT_MAX)
5326
5333
  },
5327
5334
  confirm: {
5328
5335
  type: "plain_text",
@@ -6123,12 +6130,13 @@ async function deliverSlackSlashResponseWithWebApi(params) {
6123
6130
  const mrkdwn = "mrkdwn" in payload && typeof payload.mrkdwn === "boolean" ? payload.mrkdwn : void 0;
6124
6131
  if (payload.response_type === "in_channel") {
6125
6132
  const postSlackMessage = params.client.chat.postMessage;
6126
- requireSlackPostMessageTimestamp(await postSlackMessage({
6133
+ const response = await postSlackMessage({
6127
6134
  channel: params.command.channel_id,
6128
6135
  text,
6129
6136
  ...blocks ? { blocks } : {},
6130
6137
  ...mrkdwn !== void 0 ? { mrkdwn } : {}
6131
- }));
6138
+ });
6139
+ requireSlackPostMessageTimestamp(response);
6132
6140
  } else await params.client.chat.postEphemeral({
6133
6141
  channel: params.command.channel_id,
6134
6142
  user: params.command.user_id,
@@ -6160,8 +6168,8 @@ async function getSlackBoltInterop() {
6160
6168
  }
6161
6169
  return slackBoltInterop;
6162
6170
  }
6163
- const loadSlackRelaySource = createLazyRuntimeModule(() => import("./relay-source-CEmze11m.js"));
6164
- const SLACK_WEBHOOK_MAX_BODY_BYTES = 1024 * 1024;
6171
+ const loadSlackRelaySource = createLazyRuntimeModule(() => import("./relay-source-DWuduiJ2.js"));
6172
+ const SLACK_WEBHOOK_MAX_BODY_BYTES = 1048576;
6165
6173
  const SLACK_WEBHOOK_BODY_TIMEOUT_MS = 3e4;
6166
6174
  function resolveSlackRuntimeIdentity(params) {
6167
6175
  const botUserId = normalizeOptionalString(params.botUserId);
@@ -6262,10 +6270,10 @@ async function monitorSlackProvider(opts = {}) {
6262
6270
  const mainKey = normalizeMainKey(sessionCfg?.mainKey);
6263
6271
  const slackMode = opts.mode ?? account.config.mode ?? "socket";
6264
6272
  const slackWebhookPath = normalizeSlackWebhookPath(account.config.webhookPath);
6265
- const signingSecret = normalizeResolvedSecretInputString({
6273
+ const signingSecret = slackMode === "http" ? normalizeResolvedSecretInputString({
6266
6274
  value: account.config.signingSecret,
6267
6275
  path: `channels.slack.accounts.${account.accountId}.signingSecret`
6268
- });
6276
+ }) : void 0;
6269
6277
  const botToken = resolveSlackBotToken(opts.botToken ?? account.botToken);
6270
6278
  const userToken = account.userToken;
6271
6279
  const appToken = resolveSlackAppToken(opts.appToken ?? account.appToken);
@@ -6302,8 +6310,9 @@ async function monitorSlackProvider(opts = {}) {
6302
6310
  const groupDmChannels = dmConfig?.groupChannels;
6303
6311
  let channelsConfig = slackCfg.channels;
6304
6312
  const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
6313
+ const providerConfigPresent = cfg.channels?.slack !== void 0;
6305
6314
  const { groupPolicy, providerMissingFallbackApplied } = resolveOpenProviderRuntimeGroupPolicy$1({
6306
- providerConfigPresent: cfg.channels?.slack !== void 0,
6315
+ providerConfigPresent,
6307
6316
  groupPolicy: slackCfg.groupPolicy,
6308
6317
  defaultGroupPolicy
6309
6318
  });
@@ -6339,7 +6348,7 @@ async function monitorSlackProvider(opts = {}) {
6339
6348
  slackMode,
6340
6349
  token,
6341
6350
  appToken: slackMode === "socket" ? appToken ?? void 0 : void 0,
6342
- signingSecret: slackMode === "http" ? signingSecret ?? void 0 : void 0,
6351
+ signingSecret: signingSecret ?? void 0,
6343
6352
  slackWebhookPath,
6344
6353
  clientOptions,
6345
6354
  dispatcher: slackDispatcher,
@@ -6366,6 +6375,13 @@ async function monitorSlackProvider(opts = {}) {
6366
6375
  installationState.update(contextInstallationIdentity.kind);
6367
6376
  await installSlackRuntimeForIdentity(contextInstallationIdentity);
6368
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
+ }
6369
6385
  if (recovered || adopted) publishSlackConnectedStatus(opts.setStatus, current.identityHealth);
6370
6386
  }
6371
6387
  });
@@ -6604,10 +6620,11 @@ async function monitorSlackProvider(opts = {}) {
6604
6620
  summarizeMapping("slack users", mapping, [], runtime);
6605
6621
  }
6606
6622
  if (allowNameMatching) try {
6607
- const { mapping, unresolved, additions } = buildAllowlistResolutionSummary(await resolveSlackUserAllowlist({
6623
+ const resolvedUsers = await resolveSlackUserAllowlist({
6608
6624
  token: resolveToken,
6609
6625
  entries: allowEntries
6610
- }), { formatResolved: formatSlackUserResolved });
6626
+ });
6627
+ const { mapping, unresolved, additions } = buildAllowlistResolutionSummary(resolvedUsers, { formatResolved: formatSlackUserResolved });
6611
6628
  allowFrom = mergeAllowlist({
6612
6629
  existing: allowFrom,
6613
6630
  additions
@@ -6634,10 +6651,11 @@ async function monitorSlackProvider(opts = {}) {
6634
6651
  summarizeMapping("slack channel users", mapping, [], runtime);
6635
6652
  }
6636
6653
  if (allowNameMatching) try {
6637
- const { resolvedMap, mapping, unresolved } = buildAllowlistResolutionSummary(await resolveSlackUserAllowlist({
6654
+ const resolvedUsers = await resolveSlackUserAllowlist({
6638
6655
  token: resolveToken,
6639
6656
  entries: Array.from(userEntries)
6640
- }), { formatResolved: formatSlackUserResolved });
6657
+ });
6658
+ const { resolvedMap, mapping, unresolved } = buildAllowlistResolutionSummary(resolvedUsers, { formatResolved: formatSlackUserResolved });
6641
6659
  const nextChannels = patchAllowlistUsersInConfigEntries({
6642
6660
  entries: channelsConfig,
6643
6661
  resolvedMap
@@ -6686,10 +6704,7 @@ async function monitorSlackProvider(opts = {}) {
6686
6704
  app,
6687
6705
  config: slackCfg.execApprovals ?? {},
6688
6706
  resolveClient,
6689
- ...identity.kind === "enterprise" ? { enterprise: {
6690
- apiAppId: identity.apiAppId,
6691
- enterpriseId: identity.enterpriseId
6692
- } } : {}
6707
+ ...identity.kind === "enterprise" ? { enterprise: { enterpriseId: identity.enterpriseId } } : {}
6693
6708
  },
6694
6709
  abortSignal: opts.abortSignal
6695
6710
  });