@openclaw/slack 2026.8.1-beta.2 → 2026.8.1-beta.3

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 (54) hide show
  1. package/dist/{account-inspect-Drw2gAiN.js → account-inspect-YJvFBbCR.js} +1 -1
  2. package/dist/account-inspect-api.js +1 -1
  3. package/dist/{accounts-CK4AVI2_.js → accounts-BlzxuYle.js} +5 -1
  4. package/dist/{accounts.runtime-Cb7QwWBz.js → accounts.runtime-CbabBL8x.js} +1 -1
  5. package/dist/{action-runtime-BkGe7ny_.js → action-runtime-D6jg2CQd.js} +64 -68
  6. package/dist/action-runtime.runtime-JtoOK9l5.js +2 -0
  7. package/dist/{actions-BTDXwwE3.js → actions-DFk0ANVB.js} +52 -212
  8. package/dist/{actions.runtime-DLFyUkvg.js → actions.runtime-CYLsYRai.js} +1 -1
  9. package/dist/api.js +14 -14
  10. package/dist/{approval-handler.runtime-CJaNzAq2.js → approval-handler.runtime-BNvAoKdK.js} +4 -2
  11. package/dist/{channel-D_tovcUL.js → channel-CA5w7qDF.js} +78 -39
  12. package/dist/channel-config-api.js +1 -1
  13. package/dist/channel-plugin-api.js +1 -1
  14. package/dist/{channel-type-B9MSdoGN.js → channel-type-CZWv55Wu.js} +3 -7
  15. package/dist/{channel.setup-Bch9dYmA.js → channel.setup-CpyYsEXH.js} +4 -4
  16. package/dist/{config-schema-xto5jFIx.js → config-schema-CN3XZRX5.js} +23 -7
  17. package/dist/conversation-binding-route-DFVLUdYF.js +115 -0
  18. package/dist/{directory-config-CNBz8lJa.js → directory-config-BGYyuzWh.js} +1 -1
  19. package/dist/directory-contract-api.js +1 -1
  20. package/dist/{directory-live-CFKUtW9E.js → directory-live-DjUJQLbq.js} +2 -2
  21. package/dist/{group-policy-c4RP9bjc.js → group-policy-DyfB_ZIE.js} +38 -24
  22. package/dist/{message-tool-api-BykQB4AU.js → message-tool-api-CqMr5Rmc.js} +2 -2
  23. package/dist/message-tool-api.js +1 -1
  24. package/dist/{monitor-1nF1NtqT.js → monitor-Chrecrb9.js} +3 -3
  25. package/dist/{outbound-adapter-S81tsswN.js → outbound-adapter-DuRqAQXK.js} +18 -8
  26. package/dist/{pipeline.runtime-BvYsM5JO.js → pipeline.runtime-Bbfd5VFW.js} +376 -324
  27. package/dist/{policy-TapwbeaT.js → policy-BKXSxrIS.js} +1 -1
  28. package/dist/{probe-HoEg_WxB.js → probe-BVA65leh.js} +1 -1
  29. package/dist/{provider-CDNvBXUi.js → provider-CUUiwsg2.js} +65 -44
  30. package/dist/{relay-source-C9leF11u.js → relay-source-mhpMMRG-.js} +1 -1
  31. package/dist/{replies-CeOfv82I.js → replies-SnWyXcsL.js} +36 -25
  32. package/dist/{resolve-channels-CNPrxaXY.js → resolve-channels-BSpqC8jU.js} +1 -1
  33. package/dist/{resolve-users-Dzomuwnr.js → resolve-users-Dvz9pDe0.js} +1 -1
  34. package/dist/{runtime-api-Cj9nxBNv.js → runtime-api-DBi7xc_g.js} +2 -2
  35. package/dist/runtime-api.js +11 -11
  36. package/dist/{scopes-cYXKkrRD.js → scopes-BSk4GZvZ.js} +1 -1
  37. package/dist/security-contract-api.js +1 -1
  38. package/dist/{send-Nor0iBwY.js → send-CtnOxKCc.js} +58 -78
  39. package/dist/{send.runtime-BmgNe6S9.js → send.runtime-kYctMHSd.js} +1 -1
  40. package/dist/setup-plugin-api.js +1 -1
  41. package/dist/{setup-surface-CbX1-Knh.js → setup-surface-BPFfp6So.js} +6 -6
  42. package/dist/{shared-zdT5AMp-.js → shared-DJBaslN7.js} +13 -7
  43. package/dist/{block-text-YtiNkqmx.js → slack-client-kind-BXyOOICI.js} +17 -2
  44. package/dist/{slash-dispatch.runtime-Bnr9GR1S.js → slash-dispatch.runtime-Cf2FTrnf.js} +2 -2
  45. package/openclaw.plugin.json +43 -1
  46. package/package.json +4 -6
  47. package/dist/account-reply-mode-DrUXogvO.js +0 -14
  48. package/dist/action-runtime.runtime-D9I6uc0Q.js +0 -2
  49. package/node_modules/p-map/index.d.ts +0 -155
  50. package/node_modules/p-map/index.js +0 -285
  51. package/node_modules/p-map/license +0 -9
  52. package/node_modules/p-map/package.json +0 -57
  53. package/node_modules/p-map/readme.md +0 -190
  54. package/dist/{security-audit-DR097212.js → security-audit-B_yKr7MW.js} +1 -1
@@ -1,4 +1,4 @@
1
- import { d as resolveSlackUserAllowListForTeam, l as normalizeSlackSlug, n as buildSlackChannelPolicyScope, t as buildSlackChannelIdCandidates } from "./group-policy-c4RP9bjc.js";
1
+ import { f as normalizeSlackSlug, m as resolveSlackUserAllowListForTeam, n as buildSlackChannelPolicyScope, t as buildSlackChannelIdCandidates } from "./group-policy-DyfB_ZIE.js";
2
2
  import { applyChannelMatchMeta, buildChannelKeyCandidates } from "openclaw/plugin-sdk/channel-targets";
3
3
  import { mergePairLoopGuardConfig } from "openclaw/plugin-sdk/pair-loop-guard-runtime";
4
4
  //#region extensions/slack/src/monitor/channel-config.ts
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
- import { u as formatSlackBotTokenIdentityWarning } from "./accounts-CK4AVI2_.js";
2
+ import { u as formatSlackBotTokenIdentityWarning } from "./accounts-BlzxuYle.js";
3
3
  import "./target-parsing-BnMD2ZqZ.js";
4
4
  import { createRequire } from "node:module";
5
5
  import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1 } from "openclaw/plugin-sdk/account-id";
@@ -1,15 +1,15 @@
1
1
  import { n as registerSlackHttpHandler, r as normalizeSlackWebhookPath } from "./registry-bbjH7IHX.js";
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-CK4AVI2_.js";
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-BlzxuYle.js";
3
3
  import { a as parseSlackTarget, n as formatSlackTarget } from "./target-parsing-BnMD2ZqZ.js";
4
- import { $ as isSlackCallbackActionId, B as SLACK_TEXT_LIMIT, Et as isSlackApprovalAuthorizedSender, G as truncateSlackText, Ot as isSlackExecApprovalAuthorizedSender, Q as isSlackApprovalActionId, a as allowListMatches, at as escapeSlackMrkdwn, c as normalizeSlackAllowOwnerEntry, d as resolveSlackUserAllowListForTeam, et as isSlackQuestionActionId, ft as isSlackAnyNativeApprovalClientEnabled, l as normalizeSlackSlug, nt as decodeSlackQuestionAction, o as normalizeAllowList, ot as decodeSlackApprovalAction, rt as resolveSlackQuestionAction, s as normalizeAllowListLower, t as buildSlackChannelIdCandidates, u as resolveSlackAllowListMatch, wt as registerSlackInstallationState } from "./group-policy-c4RP9bjc.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-HoEg_WxB.js";
4
+ import { At as isSlackApprovalAuthorizedSender, J as truncateSlackText, Mt as isSlackExecApprovalAuthorizedSender, Ot as registerSlackInstallationState, U as SLACK_TEXT_LIMIT, a as qualifySlackConversationId, at as decodeSlackQuestionAction, c as allowListMatches, ct as escapeSlackMrkdwn, d as normalizeSlackAllowOwnerEntry, f as normalizeSlackSlug, gt as isSlackAnyNativeApprovalClientEnabled, l as normalizeAllowList, m as resolveSlackUserAllowListForTeam, nt as isSlackCallbackActionId, o as qualifySlackRoutePeerId, ot as resolveSlackQuestionAction, p as resolveSlackAllowListMatch, rt as isSlackQuestionActionId, s as resolveSlackEnterpriseMainDmSessionKey, t as buildSlackChannelIdCandidates, tt as isSlackApprovalActionId, u as normalizeAllowListLower, ut as decodeSlackApprovalAction } from "./group-policy-DyfB_ZIE.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-BVA65leh.js";
6
6
  import { n as getSlackRuntime, t as getOptionalSlackRuntime } from "./runtime-JSVZSWAj.js";
7
- import { t as hasSlackMessageTableBlock } from "./block-text-YtiNkqmx.js";
8
- import { i as setSlackDefaultSendIdentity } from "./send-Nor0iBwY.js";
7
+ import { i as hasSlackMessageTableBlock, r as saveRemoteMedia, t as isGovSlackClient } from "./slack-client-kind-BXyOOICI.js";
8
+ import { i as setSlackDefaultSendIdentity, p as requireSlackPostMessageTimestamp } from "./send-CtnOxKCc.js";
9
9
  import { t as collectSlackCursorPages } from "./cursor-pages-eX7p8Wwt.js";
10
- import { t as resolveSlackChannelAllowlist } from "./resolve-channels-CNPrxaXY.js";
11
- import { t as resolveSlackUserAllowlist } from "./resolve-users-Dzomuwnr.js";
12
- import { n as resolveSlackChannelConfig, r as resolveSlackChannelLabel, t as isSlackChannelAllowedByPolicy } from "./policy-TapwbeaT.js";
10
+ import { t as resolveSlackChannelAllowlist } from "./resolve-channels-BSpqC8jU.js";
11
+ import { t as resolveSlackUserAllowlist } from "./resolve-users-Dvz9pDe0.js";
12
+ import { n as resolveSlackChannelConfig, r as resolveSlackChannelLabel, t as isSlackChannelAllowedByPolicy } from "./policy-BKXSxrIS.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";
@@ -25,13 +25,13 @@ import { withTimeout } from "openclaw/plugin-sdk/text-utility-runtime";
25
25
  import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
26
26
  import { WebAPIHTTPError, WebAPIPlatformError, WebAPIRateLimitedError, WebAPIRequestError, WebClient } from "@slack/web-api";
27
27
  import { addAllowlistUserEntriesFromConfigEntry, buildAllowlistResolutionSummary, formatAllowlistMatchMeta, mergeAllowlist, patchAllowlistUsersInConfigEntries, summarizeMapping } from "openclaw/plugin-sdk/allow-from";
28
+ import { buildPluginBindingResolvedText, parsePluginBindingApprovalCustomId, resolveConversationLabel as resolveConversationLabel$1, resolvePluginConversationBindingApproval, resolveRuntimeConversationBindingRoute, upsertChannelPairingRequest } from "openclaw/plugin-sdk/conversation-runtime";
28
29
  import { collectErrorGraphCandidates, extractErrorCode, formatErrorMessage, isApprovalNotFoundError, readErrorName, toErrorObject } from "openclaw/plugin-sdk/error-runtime";
29
- import { asDateTimestampMs, parseFiniteNumber, parseStrictFiniteNumber, resolveExpiresAtMsFromDurationMs, timestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
30
30
  import { resolveTextChunkLimit } from "openclaw/plugin-sdk/reply-chunking";
31
31
  import { buildChannelMetadata } from "openclaw/plugin-sdk/security-runtime";
32
32
  import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
33
+ import { classifyTransientNetworkErrorCode } from "openclaw/plugin-sdk/retry-runtime";
33
34
  import { createDedupeCache } from "openclaw/plugin-sdk/dedupe-runtime";
34
- import { buildPluginBindingResolvedText, parsePluginBindingApprovalCustomId, resolveConversationLabel as resolveConversationLabel$1, resolvePluginConversationBindingApproval, resolveRuntimeConversationBindingRoute, upsertChannelPairingRequest } from "openclaw/plugin-sdk/conversation-runtime";
35
35
  import { resolveNativeCommandsEnabled, resolveNativeSkillsEnabled } from "openclaw/plugin-sdk/native-command-config-runtime";
36
36
  import { registerChannelRuntimeContext } from "openclaw/plugin-sdk/channel-runtime-context";
37
37
  import { DEFAULT_GROUP_HISTORY_LIMIT } from "openclaw/plugin-sdk/reply-history";
@@ -45,7 +45,7 @@ import { resolveChannelConfigWrites } from "openclaw/plugin-sdk/channel-config-w
45
45
  import { mutateConfigFile, readConfigFileSnapshotForWrite } from "openclaw/plugin-sdk/config-mutation";
46
46
  import { enqueueRoutedSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
47
47
  import { createChannelIngressResolver, defineStableChannelIngressIdentity, readChannelIngressStoreAllowFromForDmPolicy } from "openclaw/plugin-sdk/channel-ingress-runtime";
48
- import { classifyTransientNetworkErrorCode } from "openclaw/plugin-sdk/retry-runtime";
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";
@@ -376,20 +376,6 @@ async function updateSlackSuggestedPrompts(params) {
376
376
  }
377
377
  }
378
378
  //#endregion
379
- //#region extensions/slack/src/monitor/workspace-routing.ts
380
- function resolveSlackEnterpriseMainDmSessionKey(params) {
381
- const accountId = encodeURIComponent(params.accountId).toLowerCase();
382
- const teamId = encodeURIComponent(params.eventScope.teamId).toLowerCase();
383
- return `${params.baseSessionKey}:account:${accountId}:team:${teamId}`;
384
- }
385
- function qualifySlackRoutePeerId(params) {
386
- if (!params.eventScope) return params.id;
387
- return `team:${encodeURIComponent(params.eventScope.teamId)}:${params.kind}:${encodeURIComponent(params.id)}`;
388
- }
389
- function qualifySlackConversationId(conversationId, eventScope) {
390
- return eventScope ? `team:${encodeURIComponent(eventScope.teamId)}:${conversationId}` : conversationId;
391
- }
392
- //#endregion
393
379
  //#region extensions/slack/src/monitor/system-event-session.ts
394
380
  function createSlackSystemEventRouteResolver(params) {
395
381
  return (event) => {
@@ -489,6 +475,12 @@ function resolveSlackSystemEventRoute(params) {
489
475
  //#region extensions/slack/src/monitor/context.ts
490
476
  const SLACK_CHANNEL_CACHE_MAX_ENTRIES = 1024;
491
477
  const SLACK_USER_CACHE_MAX_ENTRIES = 2048;
478
+ const SLACK_AVATAR_CACHE_MAX_ENTRIES = 128;
479
+ const SLACK_AVATAR_MAX_BYTES = 256 * 1024;
480
+ const SLACK_AVATAR_SSRF_POLICY = {
481
+ allowedHostnames: ["avatars.slack-edge.com", "*.slack-edge.com"],
482
+ hostnameAllowlist: ["avatars.slack-edge.com", "*.slack-edge.com"]
483
+ };
492
484
  const SLACK_CHANNEL_DENIAL_WARNING_TTL_MS = 5 * 6e4;
493
485
  const SLACK_CHANNEL_DENIAL_WARNING_MAX_ENTRIES = 1024;
494
486
  function createSlackMonitorContext(params) {
@@ -496,6 +488,8 @@ function createSlackMonitorContext(params) {
496
488
  const logger = getChildLogger({ module: "slack-auto-reply" });
497
489
  const channelCache = /* @__PURE__ */ new Map();
498
490
  const userCache = /* @__PURE__ */ new Map();
491
+ const avatarCache = /* @__PURE__ */ new Map();
492
+ const pendingAvatars = /* @__PURE__ */ new Set();
499
493
  const channelDenialWarnings = createDedupeCache({
500
494
  ttlMs: SLACK_CHANNEL_DENIAL_WARNING_TTL_MS,
501
495
  maxSize: SLACK_CHANNEL_DENIAL_WARNING_MAX_ENTRIES
@@ -581,13 +575,41 @@ function createSlackMonitorContext(params) {
581
575
  user: userId
582
576
  });
583
577
  const profile = info.user?.profile;
584
- const entry = { name: profile?.display_name || profile?.real_name || info.user?.name || void 0 };
578
+ const entry = {
579
+ name: profile?.display_name || profile?.real_name || info.user?.name || void 0,
580
+ imageUrl: normalizeOptionalString(profile?.image_192) ?? normalizeOptionalString(profile?.image_512) ?? normalizeOptionalString(profile?.image_72)
581
+ };
585
582
  writeLruMapEntry(userCache, cacheKey, entry, SLACK_USER_CACHE_MAX_ENTRIES);
586
583
  return entry;
587
584
  } catch (error) {
588
585
  return { error };
589
586
  }
590
587
  };
588
+ const resolveUserAvatar = (userId, eventScope) => {
589
+ if (isGovSlackClient(eventScope?.client ?? params.app.client)) return;
590
+ const imageUrl = readLruMapEntry(userCache, scopedKey(userId, eventScope))?.imageUrl;
591
+ if (!imageUrl) return;
592
+ const cacheKey = scopedKey(`${userId}\0${imageUrl}`, eventScope);
593
+ const cached = readLruMapEntry(avatarCache, cacheKey);
594
+ if (cached) return cached;
595
+ if (pendingAvatars.has(cacheKey) || pendingAvatars.size >= SLACK_AVATAR_CACHE_MAX_ENTRIES) return;
596
+ pendingAvatars.add(cacheKey);
597
+ saveRemoteMedia({
598
+ url: imageUrl,
599
+ filePathHint: "conversation-avatar.png",
600
+ maxBytes: SLACK_AVATAR_MAX_BYTES,
601
+ ssrfPolicy: SLACK_AVATAR_SSRF_POLICY
602
+ }).then((media) => {
603
+ writeLruMapEntry(avatarCache, cacheKey, media.path, SLACK_AVATAR_CACHE_MAX_ENTRIES);
604
+ }).catch((error) => {
605
+ logger.debug({
606
+ error: formatSlackError(error),
607
+ userId
608
+ }, "Slack conversation avatar download failed");
609
+ }).finally(() => {
610
+ pendingAvatars.delete(cacheKey);
611
+ });
612
+ };
591
613
  const setSlackThreadStatus = async (p) => {
592
614
  if (!p.threadTs) return;
593
615
  try {
@@ -734,6 +756,7 @@ function createSlackMonitorContext(params) {
734
756
  rememberSlackChannelType,
735
757
  recallSlackChannelType,
736
758
  resolveUserName,
759
+ resolveUserAvatar,
737
760
  setSlackThreadStatus,
738
761
  getSlackAssistantThreadContext: assistantThreadContextStore.get,
739
762
  saveSlackAssistantThreadContext: assistantThreadContextStore.save,
@@ -2421,8 +2444,8 @@ function removeSlackApprovalControls(blocks) {
2421
2444
  }
2422
2445
  function buildSlackApprovalTerminalBlocks(params) {
2423
2446
  const blocks = removeSlackApprovalControls(params.blocks ?? []).filter((block) => {
2424
- const text = block.text?.text;
2425
- return !(block.type === "section" && typeof text === "string" && /^\*(?:Exec|Plugin) approval required\*/u.test(text));
2447
+ const blockId = block.block_id;
2448
+ return !(block.type === "section" && blockId === "openclaw_approval_header");
2426
2449
  });
2427
2450
  return [{
2428
2451
  type: "section",
@@ -3783,14 +3806,6 @@ function registerSlackMessageEvents(params) {
3783
3806
  if (ctx.shouldDropMismatchedSlackEvent(body)) return;
3784
3807
  const message = event;
3785
3808
  ctx.rememberSlackChannelType(message.channel, message.channel_type, eventScope);
3786
- if (eventScope && isBotAuthoredEnterpriseEvent(message)) {
3787
- logVerbose("slack: drop enterprise bot-authored message");
3788
- return;
3789
- }
3790
- if (eventScope && message.subtype && message.subtype !== "file_share") {
3791
- logVerbose(`slack: drop enterprise message subtype=${message.subtype}`);
3792
- return;
3793
- }
3794
3809
  const assistantChangedInbound = resolveAssistantMessageChangedInbound({
3795
3810
  event: message,
3796
3811
  ctx
@@ -4149,7 +4164,7 @@ function buildSlackDebounceKey(message, accountId, teamId) {
4149
4164
  }
4150
4165
  //#endregion
4151
4166
  //#region extensions/slack/src/monitor/message-handler.ts
4152
- const loadSlackMessagePipeline = createLazyRuntimeModule(() => import("./pipeline.runtime-BvYsM5JO.js"));
4167
+ const loadSlackMessagePipeline = createLazyRuntimeModule(() => import("./pipeline.runtime-Bbfd5VFW.js"));
4153
4168
  function createSlackDispatchCompletion() {
4154
4169
  let resolve;
4155
4170
  let reject;
@@ -4427,9 +4442,13 @@ const SLACK_PRESENCE_AUTO_MAX_PARTICIPANTS = 8;
4427
4442
  const SLACK_PRESENCE_TARGET_TTL_MS = 1440 * 60 * 1e3;
4428
4443
  const SLACK_PRESENCE_MAX_POLLS_PER_INTERVAL = 45;
4429
4444
  const SLACK_PRESENCE_MAX_TARGETS = 2e3;
4445
+ 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."];
4430
4446
  function resolveMode(channelConfig, accountConfig) {
4431
4447
  return channelConfig?.mode ?? accountConfig?.mode ?? "off";
4432
4448
  }
4449
+ function resolvePrompt(channelConfig, accountConfig) {
4450
+ return channelConfig?.prompt ?? accountConfig?.prompt;
4451
+ }
4433
4452
  function hasSlackPresenceEventsEnabled(params) {
4434
4453
  if (resolveMode(void 0, params.account) !== "off") return true;
4435
4454
  return Object.values(params.channels ?? {}).some((entry) => resolveMode(entry?.presenceEvents, void 0) !== "off");
@@ -4442,12 +4461,12 @@ function isTargetEligible(target) {
4442
4461
  function formatSlackPresenceEvent(target, userId, awayObservation) {
4443
4462
  const { observedAwayAtMs, observedActiveAtMs } = awayObservation;
4444
4463
  const observedAwayDurationMs = Math.max(0, observedActiveAtMs - observedAwayAtMs);
4464
+ const promptLines = target.prompt === void 0 ? DEFAULT_SLACK_PRESENCE_EVENT_PROMPT : target.prompt.length > 0 ? [target.prompt] : [];
4445
4465
  return [
4446
4466
  "Slack presence event:",
4447
4467
  `A human participant became active on Slack after being observed away: user_id=${JSON.stringify(userId)}${target.teamId ? ` team_id=${JSON.stringify(target.teamId)}` : ""} channel_id=${JSON.stringify(target.channelId)}${target.threadId ? ` thread_ts=${JSON.stringify(target.threadId)}` : ""}.`,
4448
4468
  `observed_away_at_ms=${observedAwayAtMs} observed_active_at_ms=${observedActiveAtMs} observed_away_duration_ms=${observedAwayDurationMs}`,
4449
- "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.",
4450
- "Send at most one short, natural greeting in this Slack conversation. Do not reveal private memory. If no greeting is appropriate, stay silent."
4469
+ ...promptLines
4451
4470
  ].join("\n");
4452
4471
  }
4453
4472
  function resolveObservedTarget(params) {
@@ -4470,6 +4489,7 @@ function resolveObservedTarget(params) {
4470
4489
  key: `${teamId ? `team:${teamId}:` : ""}${channelId}${targetSuffix}`,
4471
4490
  ...teamId ? { teamId } : {},
4472
4491
  mode,
4492
+ prompt: resolvePrompt(prepared.channelConfig?.presenceEvents, params.accountConfig),
4473
4493
  channelId,
4474
4494
  threadId,
4475
4495
  to: formatSlackTarget({
@@ -4523,6 +4543,7 @@ function createSlackPresenceMonitor(params) {
4523
4543
  const current = targets.get(observed.key);
4524
4544
  if (current) {
4525
4545
  current.mode = observed.mode;
4546
+ current.prompt = observed.prompt;
4526
4547
  current.sessionKey = observed.sessionKey;
4527
4548
  current.agentId = observed.agentId;
4528
4549
  current.to = observed.to;
@@ -5119,7 +5140,7 @@ const SLACK_COMMAND_ARG_CONFIRM_TEXT_MAX = 300;
5119
5140
  const SLACK_HEADER_TEXT_MAX = 150;
5120
5141
  const SLACK_COMMAND_ARG_ACTION_BLOCKS_MAX = 47;
5121
5142
  const loadSlashCommandsRuntime = createLazyRuntimeModule(() => import("./slash-commands.runtime-BTTMlmwy.js"));
5122
- const loadSlashDispatchRuntime = createLazyRuntimeModule(() => import("./slash-dispatch.runtime-Bnr9GR1S.js"));
5143
+ const loadSlashDispatchRuntime = createLazyRuntimeModule(() => import("./slash-dispatch.runtime-Cf2FTrnf.js"));
5123
5144
  const loadSlashSkillCommandsRuntime = createLazyRuntimeModule(() => import("./slash-skill-commands.runtime-CD1J2ODY.js"));
5124
5145
  const loadPluginCommandRuntime = createLazyRuntimeModule(() => import("openclaw/plugin-sdk/plugin-command-runtime"));
5125
5146
  function resolveSlackCommandMenuModelContext(params) {
@@ -5978,12 +5999,12 @@ async function deliverSlackSlashResponseWithWebApi(params) {
5978
5999
  const mrkdwn = "mrkdwn" in payload && typeof payload.mrkdwn === "boolean" ? payload.mrkdwn : void 0;
5979
6000
  if (payload.response_type === "in_channel") {
5980
6001
  const postSlackMessage = params.client.chat.postMessage;
5981
- await postSlackMessage({
6002
+ requireSlackPostMessageTimestamp(await postSlackMessage({
5982
6003
  channel: params.command.channel_id,
5983
6004
  text,
5984
6005
  ...blocks ? { blocks } : {},
5985
6006
  ...mrkdwn !== void 0 ? { mrkdwn } : {}
5986
- });
6007
+ }));
5987
6008
  } else await params.client.chat.postEphemeral({
5988
6009
  channel: params.command.channel_id,
5989
6010
  user: params.command.user_id,
@@ -6015,7 +6036,7 @@ async function getSlackBoltInterop() {
6015
6036
  }
6016
6037
  return slackBoltInterop;
6017
6038
  }
6018
- const loadSlackRelaySource = createLazyRuntimeModule(() => import("./relay-source-C9leF11u.js"));
6039
+ const loadSlackRelaySource = createLazyRuntimeModule(() => import("./relay-source-mhpMMRG-.js"));
6019
6040
  const SLACK_WEBHOOK_MAX_BODY_BYTES = 1024 * 1024;
6020
6041
  const SLACK_WEBHOOK_BODY_TIMEOUT_MS = 3e4;
6021
6042
  function resolveSlackRuntimeIdentity(params) {
@@ -6729,4 +6750,4 @@ function createSlackWorkspaceClientResolver(params) {
6729
6750
  }
6730
6751
  const resolveSlackRuntimeGroupPolicy = resolveOpenProviderRuntimeGroupPolicy$1;
6731
6752
  //#endregion
6732
- export { resolveChannelResetConfig as C, stripSlackMentionsForCommandDetection as D, buildSlackSlashCommandMatcher as E, resolveChannelContextVisibilityMode as S, updateLastRoute as T, normalizeSlackChannelType as _, createSlackResponseUrlBudget as a, parseSlackAssistantThreadMetadata as b, resolveConversationLabel$1 as c, resolveSlackEffectiveAllowFrom as d, SLACK_SOCKET_RECONNECT_POLICY as f, resolveSlackEnterpriseMainDmSessionKey as g, qualifySlackRoutePeerId as h, SlackResponseAlreadyReportedError as i, authorizeSlackBotRoomMessage as l, qualifySlackConversationId as m, resolveSlackRuntimeGroupPolicy as n, authorizeSlackDirectMessage as o, formatUnknownError as p, resolveSlackRoomContextHints as r, trackSlackDraftMessage as s, monitorSlackProvider as t, resolveSlackCommandIngress as u, resolveSlackChatType as v, resolveStorePath$1 as w, readSessionUpdatedAt as x, buildSlackAssistantThreadMetadata as y };
6753
+ export { buildSlackSlashCommandMatcher as C, updateLastRoute as S, parseSlackAssistantThreadMetadata as _, createSlackResponseUrlBudget as a, resolveChannelResetConfig as b, resolveConversationLabel$1 as c, resolveSlackEffectiveAllowFrom as d, SLACK_SOCKET_RECONNECT_POLICY as f, buildSlackAssistantThreadMetadata as g, resolveSlackChatType as h, SlackResponseAlreadyReportedError as i, authorizeSlackBotRoomMessage as l, normalizeSlackChannelType as m, resolveSlackRuntimeGroupPolicy as n, authorizeSlackDirectMessage as o, formatUnknownError as p, resolveSlackRoomContextHints as r, trackSlackDraftMessage as s, monitorSlackProvider as t, resolveSlackCommandIngress as u, readSessionUpdatedAt as v, stripSlackMentionsForCommandDetection as w, resolveStorePath$1 as x, resolveChannelContextVisibilityMode as y };
@@ -1,4 +1,4 @@
1
- import { f as SLACK_SOCKET_RECONNECT_POLICY, p as formatUnknownError } from "./provider-CDNvBXUi.js";
1
+ import { f as SLACK_SOCKET_RECONNECT_POLICY, p as formatUnknownError } from "./provider-CUUiwsg2.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";
@@ -1,6 +1,7 @@
1
- import { B as SLACK_TEXT_LIMIT, C as buildSlackNativeDataAccessibilityText, D as isSlackInvalidBlocksResponse, N as buildSlackBlocksFallbackText, O as isSlackNativeResponseUrlRejection, T as hasSlackNativeDataBlock, _ as resolveSlackReplyBlocks, g as resolveSlackReplyBlockResolution, j as markdownToSlackMrkdwnChunks, m as hasSlackReplyStructuredContent } from "./group-policy-c4RP9bjc.js";
2
- import { m as chunkSlackTextAtHardLimit, p as buildSlackNativeDataDeliveryPlan, r as sendMessageSlack } from "./send-Nor0iBwY.js";
3
- import { a as createSlackResponseUrlBudget, i as SlackResponseAlreadyReportedError } from "./provider-CDNvBXUi.js";
1
+ import { A as isSlackInvalidBlocksResponse, E as buildSlackNativeDataAccessibilityText, I as buildSlackBlocksFallbackText, O as hasSlackNativeDataBlock, P as markdownToSlackMrkdwnChunks, U as SLACK_TEXT_LIMIT, _ as hasSlackReplyStructuredContent, b as resolveSlackReplyBlocks, j as isSlackNativeResponseUrlRejection, y as resolveSlackReplyBlockResolution } from "./group-policy-DyfB_ZIE.js";
2
+ import { h as chunkSlackTextAtHardLimit, m as buildSlackNativeDataDeliveryPlan, r as sendMessageSlack } from "./send-CtnOxKCc.js";
3
+ import { a as createSlackResponseUrlBudget, i as SlackResponseAlreadyReportedError } from "./provider-CUUiwsg2.js";
4
+ import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
4
5
  import { createReplyReferencePlanner } from "openclaw/plugin-sdk/reply-reference";
5
6
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
6
7
  import { SILENT_REPLY_TOKEN, chunkMarkdownTextWithMode, isSilentReplyText } from "openclaw/plugin-sdk/reply-chunking";
@@ -121,27 +122,6 @@ function resolveDeliveredSlackReplyThreadTs(params) {
121
122
  }
122
123
  async function deliverReplies(params) {
123
124
  let latestResult;
124
- const sendReply = async (input) => {
125
- return await sendMessageSlack(params.target, input.text, {
126
- cfg: params.cfg,
127
- token: params.token,
128
- threadTs: input.threadTs,
129
- accountId: params.accountId,
130
- ...input.mediaUrl ? { mediaUrl: input.mediaUrl } : {},
131
- ...input.blocks ? { blocks: input.blocks } : {},
132
- ...input.authoredTextPlacement ? { authoredTextPlacement: input.authoredTextPlacement } : {},
133
- ...Object.hasOwn(input, "nativeDataFallbackBaseText") ? { nativeDataFallbackBaseText: input.nativeDataFallbackBaseText } : {},
134
- ...input.textIsSlackMrkdwn ? { textIsSlackMrkdwn: true } : {},
135
- ...input.textIsSlackPlainText ? { textIsSlackPlainText: true } : {},
136
- ...params.eventScope ? {
137
- eventScope: params.eventScope,
138
- textLimit: params.textLimit,
139
- ...params.mediaMaxBytes !== void 0 ? { mediaMaxBytes: params.mediaMaxBytes } : {}
140
- } : {},
141
- ...params.identity ? { identity: params.identity } : {},
142
- ...params.metadata ? { metadata: params.metadata } : {}
143
- });
144
- };
145
125
  for (const payload of params.replies) {
146
126
  if (payload.isReasoning === true) continue;
147
127
  const threadTs = resolveDeliveredSlackReplyThreadTs({
@@ -153,6 +133,31 @@ async function deliverReplies(params) {
153
133
  const textRaw = reply.hasText && !isSilentReplyText(reply.trimmedText, SILENT_REPLY_TOKEN) ? reply.trimmedText : void 0;
154
134
  const { authoredTextPlacement, segments } = resolveSlackReplyBlockResolution(payload, { materializeAuthoredText: !reply.hasMedia && hasSlackReplyStructuredContent(payload) });
155
135
  if (!textRaw && !reply.hasMedia && segments.length === 0) continue;
136
+ const acceptedResults = [];
137
+ const sendReply = async (input) => {
138
+ return await sendMessageSlack(params.target, input.text, {
139
+ cfg: params.cfg,
140
+ token: params.token,
141
+ threadTs: input.threadTs,
142
+ accountId: params.accountId,
143
+ onDeliveryResult: (result) => {
144
+ acceptedResults.push(result);
145
+ },
146
+ ...input.mediaUrl ? { mediaUrl: input.mediaUrl } : {},
147
+ ...input.blocks ? { blocks: input.blocks } : {},
148
+ ...input.authoredTextPlacement ? { authoredTextPlacement: input.authoredTextPlacement } : {},
149
+ ...Object.hasOwn(input, "nativeDataFallbackBaseText") ? { nativeDataFallbackBaseText: input.nativeDataFallbackBaseText } : {},
150
+ ...input.textIsSlackMrkdwn ? { textIsSlackMrkdwn: true } : {},
151
+ ...input.textIsSlackPlainText ? { textIsSlackPlainText: true } : {},
152
+ ...params.eventScope ? {
153
+ eventScope: params.eventScope,
154
+ textLimit: params.textLimit,
155
+ ...params.mediaMaxBytes !== void 0 ? { mediaMaxBytes: params.mediaMaxBytes } : {}
156
+ } : {},
157
+ ...params.identity ? { identity: params.identity } : {},
158
+ ...params.metadata ? { metadata: params.metadata } : {}
159
+ });
160
+ };
156
161
  const emitSent = (content, result) => {
157
162
  if (params.deferMessageSentHooks) return;
158
163
  emitSlackMessageSentHooks({
@@ -250,7 +255,13 @@ async function deliverReplies(params) {
250
255
  }
251
256
  } catch (error) {
252
257
  emitFailed(hookParts.join("\n\n") || textRaw || spokenText || "", error);
253
- throw error;
258
+ if (acceptedResults.length === 0) throw error;
259
+ const receipt = createMessageReceiptFromOutboundResults({ results: acceptedResults });
260
+ throw createChannelPartialDeliveryError(error, {
261
+ messageIds: receipt.platformMessageIds,
262
+ receipt,
263
+ visibleReplySent: true
264
+ });
254
265
  }
255
266
  if (delivered) {
256
267
  emitSent(hookParts.join("\n\n") || textRaw || spokenText || "", reply.hasMedia ? void 0 : lastResult);
@@ -1,6 +1,6 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
2
  import { a as parseSlackTarget, n as formatSlackTarget } from "./target-parsing-BnMD2ZqZ.js";
3
- import { i as createSlackLookupClient } from "./probe-HoEg_WxB.js";
3
+ import { i as createSlackLookupClient } from "./probe-BVA65leh.js";
4
4
  import { t as collectSlackCursorPages } from "./cursor-pages-eX7p8Wwt.js";
5
5
  import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
6
6
  import { resolveDirectoryAllowlistEntries } from "openclaw/plugin-sdk/directory-runtime";
@@ -1,6 +1,6 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
2
  import { a as parseSlackTarget, n as formatSlackTarget } from "./target-parsing-BnMD2ZqZ.js";
3
- import { i as createSlackLookupClient } from "./probe-HoEg_WxB.js";
3
+ import { i as createSlackLookupClient } from "./probe-BVA65leh.js";
4
4
  import { t as collectSlackCursorPages } from "./cursor-pages-eX7p8Wwt.js";
5
5
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
6
6
  import { resolveDirectoryAllowlistEntries } from "openclaw/plugin-sdk/directory-runtime";
@@ -1,6 +1,6 @@
1
1
  import "./target-parsing-BnMD2ZqZ.js";
2
- import "./probe-HoEg_WxB.js";
3
- import "./config-schema-xto5jFIx.js";
2
+ import "./probe-BVA65leh.js";
3
+ import "./config-schema-CN3XZRX5.js";
4
4
  import "openclaw/plugin-sdk/account-id";
5
5
  import { createActionGate as createActionGate$1, imageResultFromFile, jsonResult, readPositiveIntegerParam, readReactionParams, readStringParam, withNormalizedTimestamp } from "openclaw/plugin-sdk/channel-actions";
6
6
  import "openclaw/plugin-sdk/channel-status";
@@ -1,14 +1,14 @@
1
1
  import { t as registerSlackPluginHttpRoutes } from "./plugin-routes-CLp4obpN.js";
2
- import { a as resolveSlackAccount, d as resolveSlackAppToken, f as resolveSlackBotToken, i as resolveDefaultSlackAccountId, n as listSlackAccountIds, t as listEnabledSlackAccounts } from "./accounts-CK4AVI2_.js";
3
- import { i as resolveSlackGroupToolPolicy, r as resolveSlackGroupRequireMention } from "./group-policy-c4RP9bjc.js";
4
- import { t as probeSlack } from "./probe-HoEg_WxB.js";
2
+ import { a as resolveSlackAccount, d as resolveSlackAppToken, f as resolveSlackBotToken, i as resolveDefaultSlackAccountId, n as listSlackAccountIds, t as listEnabledSlackAccounts } from "./accounts-BlzxuYle.js";
3
+ import { i as resolveSlackGroupToolPolicy, r as resolveSlackGroupRequireMention } from "./group-policy-DyfB_ZIE.js";
4
+ import { t as probeSlack } from "./probe-BVA65leh.js";
5
5
  import { r as setSlackRuntime } from "./runtime-JSVZSWAj.js";
6
- import { a as getSlackMemberInfo, c as listSlackReactions, d as readSlackMessages, f as removeOwnSlackReactions, g as unpinSlackMessage, h as sendSlackMessage, l as pinSlackMessage, o as listSlackEmojis, p as removeSlackReaction, r as editSlackMessage, s as listSlackPins, t as deleteSlackMessage, u as reactSlackMessage } from "./actions-BTDXwwE3.js";
7
- import { r as sendMessageSlack } from "./send-Nor0iBwY.js";
8
- import { t as resolveSlackChannelAllowlist } from "./resolve-channels-CNPrxaXY.js";
9
- import { t as resolveSlackUserAllowlist } from "./resolve-users-Dzomuwnr.js";
10
- import { t as monitorSlackProvider } from "./provider-CDNvBXUi.js";
11
- import { n as slackActionRuntime, t as handleSlackAction } from "./action-runtime-BkGe7ny_.js";
12
- import { n as listSlackDirectoryGroupsLive, r as listSlackDirectoryPeersLive } from "./directory-live-CFKUtW9E.js";
13
- import "./monitor-1nF1NtqT.js";
6
+ import { a as getSlackMemberInfo, c as listSlackReactions, d as readSlackMessages, f as removeOwnSlackReactions, g as unpinSlackMessage, h as sendSlackMessage, l as pinSlackMessage, o as listSlackEmojis, p as removeSlackReaction, r as editSlackMessage, s as listSlackPins, t as deleteSlackMessage, u as reactSlackMessage } from "./actions-DFk0ANVB.js";
7
+ import { r as sendMessageSlack } from "./send-CtnOxKCc.js";
8
+ import { t as resolveSlackChannelAllowlist } from "./resolve-channels-BSpqC8jU.js";
9
+ import { t as resolveSlackUserAllowlist } from "./resolve-users-Dvz9pDe0.js";
10
+ import { t as monitorSlackProvider } from "./provider-CUUiwsg2.js";
11
+ import { n as slackActionRuntime, t as handleSlackAction } from "./action-runtime-D6jg2CQd.js";
12
+ import { n as listSlackDirectoryGroupsLive, r as listSlackDirectoryPeersLive } from "./directory-live-DjUJQLbq.js";
13
+ import "./monitor-Chrecrb9.js";
14
14
  export { deleteSlackMessage, editSlackMessage, getSlackMemberInfo, handleSlackAction, listEnabledSlackAccounts, listSlackAccountIds, listSlackDirectoryGroupsLive, listSlackDirectoryPeersLive, listSlackEmojis, listSlackPins, listSlackReactions, monitorSlackProvider, pinSlackMessage, probeSlack, reactSlackMessage, readSlackMessages, registerSlackPluginHttpRoutes, removeOwnSlackReactions, removeSlackReaction, resolveDefaultSlackAccountId, resolveSlackAccount, resolveSlackAppToken, resolveSlackBotToken, resolveSlackChannelAllowlist, resolveSlackGroupRequireMention, resolveSlackGroupToolPolicy, resolveSlackUserAllowlist, sendMessageSlack, sendSlackMessage, setSlackRuntime, slackActionRuntime, unpinSlackMessage };
@@ -1,4 +1,4 @@
1
- import { a as createSlackReadClient, r as formatSlackError } from "./probe-HoEg_WxB.js";
1
+ import { a as createSlackReadClient, r as formatSlackError } from "./probe-BVA65leh.js";
2
2
  import { isRecord, normalizeOptionalString, normalizeStringEntries, sortUniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  //#region extensions/slack/src/scopes.ts
4
4
  function collectScopes(value, into) {
@@ -1,2 +1,2 @@
1
- import { t as collectSlackSecurityAuditFindings } from "./security-audit-DR097212.js";
1
+ import { t as collectSlackSecurityAuditFindings } from "./security-audit-B_yKr7MW.js";
2
2
  export { collectSlackSecurityAuditFindings };