@openclaw/slack 2026.7.2-beta.1 → 2026.7.2-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 (61) hide show
  1. package/dist/{account-configured-DzC407uv.js → account-configured-BwfXBo_F.js} +1 -1
  2. package/dist/{account-inspect-Di7ditqZ.js → account-inspect-Bvbtu3iH.js} +9 -2
  3. package/dist/account-inspect-api.js +1 -1
  4. package/dist/{accounts-BOJJiHSr.js → accounts-DQEbYKh9.js} +9 -0
  5. package/dist/accounts.runtime-BIKmJdtJ.js +2 -0
  6. package/dist/{action-runtime-p6M2ULpv.js → action-runtime-DqkRwO3Z.js} +14 -17
  7. package/dist/action-runtime.runtime-DEWOcFM4.js +2 -0
  8. package/dist/{actions-DkTcWmpT.js → actions-CF0tUY5q.js} +5 -9
  9. package/dist/{actions.runtime-BSxpwgUc.js → actions.runtime-hCbx4RXg.js} +1 -1
  10. package/dist/api.js +13 -14
  11. package/dist/{approval-handler.runtime-UGbnz9OC.js → approval-handler.runtime-Em8I1-8-.js} +2 -2
  12. package/dist/{channel-B0_j6C6z.js → channel-4-TRi1D6.js} +75 -41
  13. package/dist/channel-config-api.js +1 -1
  14. package/dist/channel-plugin-api.js +1 -1
  15. package/dist/{channel-type-BpeTezY4.js → channel-type-Cu1yjNg2.js} +3 -3
  16. package/dist/{channel.setup-BQFut21T.js → channel.setup-CgkADtZg.js} +6 -4
  17. package/dist/{config-schema-DYI01PV2.js → config-schema-XjJGfwQC.js} +18 -5
  18. package/dist/{directory-config-DRkFujwG.js → directory-config-Bv0lcUlH.js} +1 -1
  19. package/dist/directory-contract-api.js +1 -1
  20. package/dist/{directory-live-DX7yFsM-.js → directory-live-CzUIB7th.js} +2 -2
  21. package/dist/{doctor-contract-DddfkMlF.js → doctor-contract-DKpe5VBr.js} +80 -12
  22. package/dist/doctor-contract-api.js +1 -1
  23. package/dist/{group-policy-C-b2ZnSl.js → group-policy-Bw-65m3V.js} +94 -135
  24. package/dist/{interactive-replies-BilWUdcI.js → interactive-replies-Dm_t2R9S.js} +1 -1
  25. package/dist/interactive-replies-api.js +1 -1
  26. package/dist/{message-tool-api-CA9jZrCY.js → message-tool-api-C2pcf5du.js} +3 -3
  27. package/dist/message-tool-api.js +1 -1
  28. package/dist/{monitor-BN_uuvrQ.js → monitor-CNFeF30h.js} +3 -3
  29. package/dist/{outbound-adapter-ECl0go7d.js → outbound-adapter-CVi2uok0.js} +49 -5
  30. package/dist/{pipeline.runtime-f0eJJoJL.js → pipeline.runtime-CTvokbty.js} +485 -251
  31. package/dist/{policy-f8b0edSi.js → policy-b_dOPDCq.js} +7 -7
  32. package/dist/probe-Borhn9PQ.js +340 -0
  33. package/dist/{provider-Ds-y-imP.js → provider-B-HVL5ZE.js} +831 -329
  34. package/dist/{relay-source-B-6LFUdz.js → relay-source-Ea_P9VcO.js} +6 -11
  35. package/dist/{replies-BMvf3ihj.js → replies-B4bOdrYb.js} +3 -3
  36. package/dist/{resolve-channels-DOMgNCWb.js → resolve-channels-KTc568SU.js} +1 -1
  37. package/dist/{resolve-users-aL6-Ssee.js → resolve-users-DeGJf1yp.js} +1 -1
  38. package/dist/{runtime-CauEvswP.js → runtime-JSVZSWAj.js} +2 -2
  39. package/dist/{runtime-api-CVb6CQjX.js → runtime-api-BFfNpzDe.js} +1 -1
  40. package/dist/runtime-api.js +12 -12
  41. package/dist/runtime-setter-api.js +1 -1
  42. package/dist/{scopes-Dw8wbU0j.js → scopes-lx08L56K.js} +1 -2
  43. package/dist/{secret-contract-CMohXFWS.js → secret-contract-DxmvbxBF.js} +1 -0
  44. package/dist/secret-contract-api.js +1 -1
  45. package/dist/{send-NEfJ0GvM.js → send-KuTDky7i.js} +29 -12
  46. package/dist/send.runtime-CXyxws1D.js +2 -0
  47. package/dist/setup-core-CeiAVwQ3.js +502 -0
  48. package/dist/setup-plugin-api.js +1 -1
  49. package/dist/{setup-surface-BN2WeG5c.js → setup-surface-DLA0vHXp.js} +23 -13
  50. package/dist/{shared-BLnB9R1T.js → shared-C4yVB0Q-.js} +64 -41
  51. package/dist/{slash-dispatch.runtime-C0Otuf_T.js → slash-dispatch.runtime-BT-mMm-f.js} +1 -1
  52. package/npm-shrinkwrap.json +3 -3
  53. package/openclaw.plugin.json +134 -10
  54. package/package.json +5 -7
  55. package/dist/accounts.runtime-KvftRRek.js +0 -2
  56. package/dist/action-runtime.runtime-DQstDkHG.js +0 -2
  57. package/dist/client-D2F6m8CP.js +0 -152
  58. package/dist/configured-state.js +0 -11
  59. package/dist/probe-CfALk0l4.js +0 -48
  60. package/dist/send.runtime-BkKpitPu.js +0 -2
  61. package/dist/setup-core-fGd6Gquy.js +0 -343
@@ -1,16 +1,16 @@
1
- import { a as resolveSlackAccount, c as resolveSlackConfigAccessorAccount, i as resolveDefaultSlackAccountId, n as listSlackAccountIds, o as resolveSlackAccountAllowFrom, r as mergeSlackAccountConfig, s as resolveSlackAccountDmPolicy } from "./accounts-BOJJiHSr.js";
2
- import { t as inspectSlackAccount } from "./account-inspect-Di7ditqZ.js";
3
- import { t as isSlackPluginAccountConfigured } from "./account-configured-DzC407uv.js";
4
- import { n as isSlackInteractiveRepliesEnabled } from "./interactive-replies-BilWUdcI.js";
5
- import { m as getChatChannelMeta } from "./client-D2F6m8CP.js";
6
- import { i as SLACK_CHANNEL } from "./setup-core-fGd6Gquy.js";
7
- import { t as SlackChannelConfigSchema } from "./config-schema-DYI01PV2.js";
8
- import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-DddfkMlF.js";
9
- import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-CMohXFWS.js";
1
+ import { a as resolveSlackAccount, c as resolveSlackConfigAccessorAccount, i as resolveDefaultSlackAccountId, n as listSlackAccountIds, o as resolveSlackAccountAllowFrom, r as mergeSlackAccountConfig, s as resolveSlackAccountDmPolicy } from "./accounts-DQEbYKh9.js";
2
+ import { t as inspectSlackAccount } from "./account-inspect-Bvbtu3iH.js";
3
+ import { t as isSlackPluginAccountConfigured } from "./account-configured-BwfXBo_F.js";
4
+ import { n as isSlackInteractiveRepliesEnabled } from "./interactive-replies-Dm_t2R9S.js";
5
+ import { t as probeSlack, v as getChatChannelMeta } from "./probe-Borhn9PQ.js";
6
+ import { i as SLACK_CHANNEL } from "./setup-core-CeiAVwQ3.js";
7
+ import { t as SlackChannelConfigSchema } from "./config-schema-XjJGfwQC.js";
8
+ import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-DKpe5VBr.js";
9
+ import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-DxmvbxBF.js";
10
10
  import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter, createScopedDmSecurityResolver } from "openclaw/plugin-sdk/channel-config-helpers";
11
11
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
12
12
  import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
13
- import { createDangerousNameMatchingMutableAllowlistWarningCollector, createOpenProviderConfiguredRouteWarningCollector } from "openclaw/plugin-sdk/channel-policy";
13
+ import { buildMutableAllowEntryDetector, collectStandardAllowlistLists, createDangerousNameMatchingMutableAllowlistWarningCollector, createOpenProviderConfiguredRouteWarningCollector } from "openclaw/plugin-sdk/channel-policy";
14
14
  import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
15
15
  //#region extensions/slack/src/security.ts
16
16
  const resolveSlackDmPolicy = createScopedDmSecurityResolver({
@@ -57,16 +57,7 @@ const slackSecurityAdapter = {
57
57
  };
58
58
  //#endregion
59
59
  //#region extensions/slack/src/security-doctor.ts
60
- function isSlackMutableAllowEntry(raw) {
61
- const text = raw.trim();
62
- if (!text || text === "*") return false;
63
- const mentionMatch = text.match(/^<@([A-Z0-9]+)>$/i);
64
- if (mentionMatch && /^[A-Z0-9]{8,}$/i.test(mentionMatch[1] ?? "")) return false;
65
- const withoutPrefix = text.replace(/^(slack|user):/i, "").trim();
66
- if (/^[UWBCGDT][A-Z0-9]{2,}$/.test(withoutPrefix)) return false;
67
- if (/^[A-Z0-9]{8,}$/i.test(withoutPrefix)) return false;
68
- return true;
69
- }
60
+ const isSlackMutableAllowEntry = buildMutableAllowEntryDetector({ stableIdPattern: /^(?:(?:(?:[sS][lL][aA][cC][kK]|[uU][sS][eE][rR]):)?(?:[UWBCGDT][A-Z0-9]{2,}|[A-Za-z0-9]{8,})|<@[A-Za-z0-9]{8,}>)$/ });
70
61
  //#endregion
71
62
  //#region extensions/slack/src/doctor.ts
72
63
  function asObjectRecord(value) {
@@ -75,27 +66,13 @@ function asObjectRecord(value) {
75
66
  const collectSlackMutableAllowlistWarnings = createDangerousNameMatchingMutableAllowlistWarningCollector({
76
67
  channel: "slack",
77
68
  detector: isSlackMutableAllowEntry,
78
- collectLists: (scope) => {
79
- const lists = [{
80
- pathLabel: `${scope.prefix}.allowFrom`,
81
- list: scope.account.allowFrom
82
- }];
83
- const dm = asObjectRecord(scope.account.dm);
84
- if (dm) lists.push({
85
- pathLabel: `${scope.prefix}.dm.allowFrom`,
86
- list: dm.allowFrom
87
- });
88
- const channels = asObjectRecord(scope.account.channels);
89
- if (channels) for (const [channelKey, channelRaw] of Object.entries(channels)) {
90
- const channel = asObjectRecord(channelRaw);
91
- if (!channel) continue;
92
- lists.push({
93
- pathLabel: `${scope.prefix}.channels.${channelKey}.users`,
94
- list: channel.users
95
- });
96
- }
97
- return lists;
98
- }
69
+ collectLists: (scope) => collectStandardAllowlistLists(scope, {
70
+ includeGroupAllowFrom: false,
71
+ includeDm: true,
72
+ includeGroups: true,
73
+ groupsKey: "channels",
74
+ groupField: "users"
75
+ })
99
76
  });
100
77
  const SLACK_CANONICAL_CHANNEL_ID_RE = /^[CG][A-Z0-9]{8,}$/;
101
78
  const SLACK_LOWERCASE_CHANNEL_ID_RE = /^[cg][0-9][a-z0-9]{7,}$/;
@@ -158,6 +135,46 @@ function collectSlackNameKeyedChannelWarnings({ cfg }) {
158
135
  }
159
136
  return [...warnings];
160
137
  }
138
+ function slackAccountConfigPath(accountId) {
139
+ return accountId === "default" ? "channels.slack" : `channels.slack.accounts.${accountId}`;
140
+ }
141
+ async function collectSlackUserIdentityWarnings(params) {
142
+ const warnings = [];
143
+ for (const accountId of listSlackAccountIds(params.cfg)) {
144
+ const account = inspectSlackAccount({
145
+ cfg: params.cfg,
146
+ accountId,
147
+ envBotToken: params.env?.SLACK_BOT_TOKEN,
148
+ envAppToken: params.env?.SLACK_APP_TOKEN,
149
+ envUserToken: params.env?.SLACK_USER_TOKEN
150
+ });
151
+ if (!account.enabled || account.identity !== "user") continue;
152
+ const path = slackAccountConfigPath(accountId);
153
+ const mode = account.mode ?? "socket";
154
+ if (mode === "socket" && account.appTokenStatus === "missing") warnings.push(`- ${path}: identity "user" in Socket Mode requires appToken for companion-app events.`);
155
+ else if (mode === "http" && account.signingSecretStatus === "missing") warnings.push(`- ${path}: identity "user" in HTTP mode requires signingSecret for companion-app events.`);
156
+ if (!account.userToken) {
157
+ warnings.push(account.userTokenStatus === "configured_unavailable" ? `- ${path}: userToken is configured but unavailable; Slack auth.test validation was skipped.` : `- ${path}: identity "user" requires userToken for the authorizing human.`);
158
+ continue;
159
+ }
160
+ const probe = await probeSlack(account.userToken, 2500, {
161
+ accountId,
162
+ identity: "user"
163
+ });
164
+ if (!probe.ok) {
165
+ warnings.push(`- ${path}: userToken auth.test failed: ${probe.error ?? "unknown error"}.`);
166
+ continue;
167
+ }
168
+ const userId = probe.user?.id?.trim();
169
+ const userName = probe.user?.name?.trim();
170
+ if (!userId) {
171
+ warnings.push(`- ${path}: userToken auth.test succeeded but returned no human user_id.`);
172
+ continue;
173
+ }
174
+ warnings.push(`- ${path}: user identity authenticated as ${userName ? `@${userName} ` : ""}(${userId}).`);
175
+ }
176
+ return warnings;
177
+ }
161
178
  const slackDoctor = {
162
179
  dmAllowFromMode: "topOnly",
163
180
  groupModel: "route",
@@ -165,6 +182,10 @@ const slackDoctor = {
165
182
  warnOnEmptyGroupSenderAllowlist: false,
166
183
  legacyConfigRules,
167
184
  normalizeCompatibilityConfig,
185
+ collectPreviewWarnings: async ({ cfg, env }) => await collectSlackUserIdentityWarnings({
186
+ cfg,
187
+ env
188
+ }),
168
189
  collectMutableAllowlistWarnings: ({ cfg }) => [...collectSlackMutableAllowlistWarnings({ cfg }), ...collectSlackNameKeyedChannelWarnings({ cfg })]
169
190
  };
170
191
  //#endregion
@@ -179,6 +200,8 @@ const slackConfigAdapter = createScopedChannelConfigAdapter({
179
200
  clearBaseFields: [
180
201
  "botToken",
181
202
  "appToken",
203
+ "userToken",
204
+ "signingSecret",
182
205
  "name"
183
206
  ],
184
207
  resolveAllowFrom: (account) => account.allowFrom,
@@ -1,4 +1,4 @@
1
- import { r as deliverSlackSlashReplies$1 } from "./replies-BMvf3ihj.js";
1
+ import { r as deliverSlackSlashReplies$1 } from "./replies-B4bOdrYb.js";
2
2
  import { resolveAgentRoute as resolveAgentRoute$1 } from "openclaw/plugin-sdk/routing";
3
3
  import { resolveMarkdownTableMode as resolveMarkdownTableMode$1 } from "openclaw/plugin-sdk/markdown-table-runtime";
4
4
  import { recordInboundSessionMetaSafe as recordInboundSessionMetaSafe$1, resolveConversationLabel as resolveConversationLabel$1 } from "openclaw/plugin-sdk/conversation-runtime";
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@openclaw/slack",
3
- "version": "2026.7.2-beta.1",
3
+ "version": "2026.7.2-beta.3",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/slack",
9
- "version": "2026.7.2-beta.1",
9
+ "version": "2026.7.2-beta.3",
10
10
  "dependencies": {
11
11
  "@slack/bolt": "4.7.3",
12
12
  "@slack/types": "2.21.1",
@@ -17,7 +17,7 @@
17
17
  "zod": "4.4.3"
18
18
  },
19
19
  "peerDependencies": {
20
- "openclaw": ">=2026.7.2-beta.1"
20
+ "openclaw": ">=2026.7.2-beta.3"
21
21
  },
22
22
  "peerDependenciesMeta": {
23
23
  "openclaw": {
@@ -20,6 +20,14 @@
20
20
  "name": {
21
21
  "type": "string"
22
22
  },
23
+ "identity": {
24
+ "default": "bot",
25
+ "type": "string",
26
+ "enum": [
27
+ "bot",
28
+ "user"
29
+ ]
30
+ },
23
31
  "mode": {
24
32
  "default": "socket",
25
33
  "type": "string",
@@ -620,6 +628,21 @@
620
628
  "requireMention": {
621
629
  "type": "boolean"
622
630
  },
631
+ "implicitMentions": {
632
+ "type": "object",
633
+ "properties": {
634
+ "replyToBot": {
635
+ "type": "boolean"
636
+ },
637
+ "quotedBot": {
638
+ "type": "boolean"
639
+ },
640
+ "threadParticipation": {
641
+ "type": "boolean"
642
+ }
643
+ },
644
+ "additionalProperties": false
645
+ },
623
646
  "groupPolicy": {
624
647
  "default": "allowlist",
625
648
  "type": "string",
@@ -996,9 +1019,20 @@
996
1019
  "type": "integer",
997
1020
  "minimum": 0,
998
1021
  "maximum": 9007199254740991
999
- },
1000
- "requireExplicitMention": {
1001
- "type": "boolean"
1022
+ }
1023
+ },
1024
+ "additionalProperties": false
1025
+ },
1026
+ "presenceEvents": {
1027
+ "type": "object",
1028
+ "properties": {
1029
+ "mode": {
1030
+ "type": "string",
1031
+ "enum": [
1032
+ "off",
1033
+ "auto",
1034
+ "on"
1035
+ ]
1002
1036
  }
1003
1037
  },
1004
1038
  "additionalProperties": false
@@ -1290,6 +1324,20 @@
1290
1324
  },
1291
1325
  "systemPrompt": {
1292
1326
  "type": "string"
1327
+ },
1328
+ "presenceEvents": {
1329
+ "type": "object",
1330
+ "properties": {
1331
+ "mode": {
1332
+ "type": "string",
1333
+ "enum": [
1334
+ "off",
1335
+ "auto",
1336
+ "on"
1337
+ ]
1338
+ }
1339
+ },
1340
+ "additionalProperties": false
1293
1341
  }
1294
1342
  },
1295
1343
  "additionalProperties": false
@@ -1339,6 +1387,13 @@
1339
1387
  "name": {
1340
1388
  "type": "string"
1341
1389
  },
1390
+ "identity": {
1391
+ "type": "string",
1392
+ "enum": [
1393
+ "bot",
1394
+ "user"
1395
+ ]
1396
+ },
1342
1397
  "mode": {
1343
1398
  "type": "string",
1344
1399
  "enum": [
@@ -1937,6 +1992,21 @@
1937
1992
  "requireMention": {
1938
1993
  "type": "boolean"
1939
1994
  },
1995
+ "implicitMentions": {
1996
+ "type": "object",
1997
+ "properties": {
1998
+ "replyToBot": {
1999
+ "type": "boolean"
2000
+ },
2001
+ "quotedBot": {
2002
+ "type": "boolean"
2003
+ },
2004
+ "threadParticipation": {
2005
+ "type": "boolean"
2006
+ }
2007
+ },
2008
+ "additionalProperties": false
2009
+ },
1940
2010
  "groupPolicy": {
1941
2011
  "type": "string",
1942
2012
  "enum": [
@@ -2312,9 +2382,20 @@
2312
2382
  "type": "integer",
2313
2383
  "minimum": 0,
2314
2384
  "maximum": 9007199254740991
2315
- },
2316
- "requireExplicitMention": {
2317
- "type": "boolean"
2385
+ }
2386
+ },
2387
+ "additionalProperties": false
2388
+ },
2389
+ "presenceEvents": {
2390
+ "type": "object",
2391
+ "properties": {
2392
+ "mode": {
2393
+ "type": "string",
2394
+ "enum": [
2395
+ "off",
2396
+ "auto",
2397
+ "on"
2398
+ ]
2318
2399
  }
2319
2400
  },
2320
2401
  "additionalProperties": false
@@ -2606,6 +2687,20 @@
2606
2687
  },
2607
2688
  "systemPrompt": {
2608
2689
  "type": "string"
2690
+ },
2691
+ "presenceEvents": {
2692
+ "type": "object",
2693
+ "properties": {
2694
+ "mode": {
2695
+ "type": "string",
2696
+ "enum": [
2697
+ "off",
2698
+ "auto",
2699
+ "on"
2700
+ ]
2701
+ }
2702
+ },
2703
+ "additionalProperties": false
2609
2704
  }
2610
2705
  },
2611
2706
  "additionalProperties": false
@@ -2656,6 +2751,7 @@
2656
2751
  }
2657
2752
  },
2658
2753
  "required": [
2754
+ "identity",
2659
2755
  "mode",
2660
2756
  "webhookPath",
2661
2757
  "userTokenReadOnly",
@@ -2674,6 +2770,10 @@
2674
2770
  "label": "Slack Enterprise Grid Org Install",
2675
2771
  "help": "Enable only for an Enterprise Grid org-wide bot installation. OpenClaw verifies the token with Slack auth.test at startup; DMs must be disabled or use dmPolicy=\"open\" with allowFrom=[\"*\"]."
2676
2772
  },
2773
+ "identity": {
2774
+ "label": "Slack Identity",
2775
+ "help": "Select \"bot\" (default) for the classic Slack app/bot identity or \"user\" to post as the authorizing human through a user token while the app carries event transport."
2776
+ },
2677
2777
  "dm.policy": {
2678
2778
  "label": "Slack DM Policy",
2679
2779
  "help": "Direct message access control (\"pairing\" recommended). \"open\" requires channels.slack.allowFrom=[\"*\"] (legacy: channels.slack.dm.allowFrom)."
@@ -2710,6 +2810,22 @@
2710
2810
  "label": "Slack Native Skill Commands",
2711
2811
  "help": "Override native skill commands for Slack (bool or \"auto\")."
2712
2812
  },
2813
+ "implicitMentions": {
2814
+ "label": "Slack Implicit Mentions",
2815
+ "help": "Control which Slack reply, quote, and thread-participation signals count as mentions. Unset flags preserve the channel defaults."
2816
+ },
2817
+ "implicitMentions.replyToBot": {
2818
+ "label": "Slack Replies to Bot",
2819
+ "help": "Treat replies to the bot's own messages as implicit mentions when the channel reports that signal."
2820
+ },
2821
+ "implicitMentions.quotedBot": {
2822
+ "label": "Slack Quoted Bot Messages",
2823
+ "help": "Treat messages quoting the bot as implicit mentions when the channel reports that signal."
2824
+ },
2825
+ "implicitMentions.threadParticipation": {
2826
+ "label": "Slack Thread Participation",
2827
+ "help": "Treat follow-ups in threads where the bot participated as implicit mentions when the channel reports that signal."
2828
+ },
2713
2829
  "allowBots": {
2714
2830
  "label": "Slack Allow Bot Messages",
2715
2831
  "help": "Allow bot-authored messages to trigger Slack replies (default: false)."
@@ -2790,6 +2906,18 @@
2790
2906
  "label": "Slack Exec Approvals",
2791
2907
  "help": "Slack-native exec approval routing and approver authorization. When unset, OpenClaw auto-enables DM-first native approvals if approvers can be resolved for this workspace account."
2792
2908
  },
2909
+ "presenceEvents": {
2910
+ "label": "Slack Presence Events",
2911
+ "help": "Poll observed human participants and wake the routed agent on away-to-active transitions. Default: \"off\"."
2912
+ },
2913
+ "presenceEvents.mode": {
2914
+ "label": "Slack Presence Event Mode",
2915
+ "help": "\"off\" disables polling; \"auto\" covers DMs, MPIMs, and recent threads with up to 8 observed people; \"on\" also covers larger threads and top-level channels."
2916
+ },
2917
+ "channels.*.presenceEvents.mode": {
2918
+ "label": "Slack Channel Presence Event Mode",
2919
+ "help": "Override presence events for one Slack channel. Use \"on\" to include large threads or top-level channel sessions."
2920
+ },
2793
2921
  "execApprovals.enabled": {
2794
2922
  "label": "Slack Exec Approvals Enabled",
2795
2923
  "help": "Controls Slack native exec approvals for this account: unset or \"auto\" enables DM-first native approvals when approvers can be resolved, true forces native approvals on, and false disables them."
@@ -2885,10 +3013,6 @@
2885
3013
  "thread.initialHistoryLimit": {
2886
3014
  "label": "Slack Thread Initial History Limit",
2887
3015
  "help": "Maximum number of existing Slack thread messages to fetch when starting a new thread session (default: 20, set to 0 to disable)."
2888
- },
2889
- "thread.requireExplicitMention": {
2890
- "label": "Slack Thread Require Explicit Mention",
2891
- "help": "If true, require an explicit @mention even inside threads where the bot has participated. Suppresses implicit thread mention behavior so the bot only responds to explicit @bot mentions in threads (default: false)."
2892
3016
  }
2893
3017
  }
2894
3018
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/slack",
3
- "version": "2026.7.2-beta.1",
3
+ "version": "2026.7.2-beta.3",
4
4
  "description": "OpenClaw Slack channel plugin for channels, DMs, commands, and app events.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -17,7 +17,7 @@
17
17
  "zod": "4.4.3"
18
18
  },
19
19
  "peerDependencies": {
20
- "openclaw": ">=2026.7.2-beta.1"
20
+ "openclaw": ">=2026.7.2-beta.3"
21
21
  },
22
22
  "peerDependenciesMeta": {
23
23
  "openclaw": {
@@ -50,9 +50,7 @@
50
50
  "SLACK_BOT_TOKEN",
51
51
  "SLACK_USER_TOKEN"
52
52
  ]
53
- },
54
- "specifier": "./configured-state",
55
- "exportName": "hasSlackConfiguredState"
53
+ }
56
54
  }
57
55
  },
58
56
  "install": {
@@ -62,13 +60,13 @@
62
60
  "allowInvalidConfigRecovery": true
63
61
  },
64
62
  "compat": {
65
- "pluginApi": ">=2026.7.2-beta.1"
63
+ "pluginApi": ">=2026.7.2-beta.3"
66
64
  },
67
65
  "startup": {
68
66
  "deferConfiguredChannelFullLoadUntilAfterListen": true
69
67
  },
70
68
  "build": {
71
- "openclawVersion": "2026.7.2-beta.1",
69
+ "openclawVersion": "2026.7.2-beta.3",
72
70
  "bundledDist": false
73
71
  },
74
72
  "release": {
@@ -1,2 +0,0 @@
1
- import { a as resolveSlackAccount, o as resolveSlackAccountAllowFrom } from "./accounts-BOJJiHSr.js";
2
- export { resolveSlackAccount, resolveSlackAccountAllowFrom };
@@ -1,2 +0,0 @@
1
- import { t as handleSlackAction } from "./action-runtime-p6M2ULpv.js";
2
- export { handleSlackAction };
@@ -1,152 +0,0 @@
1
- import "./target-parsing-N6lHogYZ.js";
2
- import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1 } from "openclaw/plugin-sdk/account-id";
3
- import { PAIRING_APPROVED_MESSAGE, projectCredentialSnapshotFields, resolveConfiguredFromRequiredCredentialStatuses } from "openclaw/plugin-sdk/channel-status";
4
- import { createHash } from "node:crypto";
5
- import { WebClient } from "@slack/web-api";
6
- import { createNodeProxyAgent } from "openclaw/plugin-sdk/fetch-runtime";
7
- //#region extensions/slack/src/channel-api.ts
8
- const SLACK_CHANNEL_META = {
9
- id: "slack",
10
- label: "Slack",
11
- selectionLabel: "Slack",
12
- docsPath: "/channels/slack",
13
- docsLabel: "slack",
14
- blurb: "supports bot + app tokens, channels, threads, and interactive replies.",
15
- systemImage: "number.square",
16
- markdownCapable: true
17
- };
18
- function getChatChannelMeta(id) {
19
- if (id !== SLACK_CHANNEL_META.id) throw new Error(`Unsupported Slack channel meta lookup: ${id}`);
20
- return SLACK_CHANNEL_META;
21
- }
22
- //#endregion
23
- //#region extensions/slack/src/client-options.ts
24
- const SLACK_DEFAULT_RETRY_OPTIONS = {
25
- retries: 2,
26
- factor: 2,
27
- minTimeout: 500,
28
- maxTimeout: 3e3,
29
- randomize: true
30
- };
31
- const SLACK_WRITE_RETRY_OPTIONS = { retries: 0 };
32
- const SLACK_LOOKUP_TIMEOUT_MS = 3e4;
33
- const SLACK_LOOKUP_RETRY_OPTIONS = { retries: 0 };
34
- /**
35
- * Build an HTTPS proxy agent from env vars (HTTPS_PROXY, HTTP_PROXY, etc.)
36
- * for use as the `agent` option in Slack WebClient and Socket Mode connections.
37
- *
38
- * When set, this agent is forwarded through @slack/bolt -> @slack/socket-mode ->
39
- * SlackWebSocket as the `httpAgent`, which the `ws` library uses to tunnel the
40
- * WebSocket upgrade request through the proxy. This fixes Socket Mode in
41
- * environments where outbound traffic must go through an HTTP CONNECT proxy.
42
- *
43
- * Respects `NO_PROXY` / `no_proxy`; if `*.slack.com` (or a matching pattern)
44
- * appears in the exclusion list, returns `undefined` so the connection is direct.
45
- *
46
- * Returns `undefined` when no proxy env var is configured or when Slack hosts
47
- * are excluded by `NO_PROXY`.
48
- */
49
- function resolveSlackProxyAgent(targetUrl) {
50
- try {
51
- return createNodeProxyAgent({
52
- mode: "env",
53
- targetUrl
54
- });
55
- } catch {
56
- return;
57
- }
58
- }
59
- function resolveSlackApiUrlFromEnv() {
60
- return process.env.SLACK_API_URL?.trim() || void 0;
61
- }
62
- function applySlackApiUrlAndProxyOptions(options) {
63
- const slackApiUrl = options.slackApiUrl ?? resolveSlackApiUrlFromEnv();
64
- options.agent ??= resolveSlackProxyAgent(slackApiUrl ?? "https://slack.com/");
65
- if (slackApiUrl !== void 0) options.slackApiUrl = slackApiUrl;
66
- else delete options.slackApiUrl;
67
- }
68
- function resolveSlackWebClientOptions(options = {}) {
69
- const resolved = Object.assign({}, options);
70
- applySlackApiUrlAndProxyOptions(resolved);
71
- resolved.retryConfig ??= SLACK_DEFAULT_RETRY_OPTIONS;
72
- return resolved;
73
- }
74
- function resolveSlackWriteClientOptions(options = {}) {
75
- const resolved = Object.assign({}, options);
76
- applySlackApiUrlAndProxyOptions(resolved);
77
- resolved.retryConfig ??= SLACK_WRITE_RETRY_OPTIONS;
78
- return resolved;
79
- }
80
- function resolveSlackLookupClientOptions(options = {}) {
81
- const resolved = Object.assign({}, options);
82
- applySlackApiUrlAndProxyOptions(resolved);
83
- resolved.rejectRateLimitedCalls = true;
84
- resolved.retryConfig = SLACK_LOOKUP_RETRY_OPTIONS;
85
- resolved.timeout ??= SLACK_LOOKUP_TIMEOUT_MS;
86
- return resolved;
87
- }
88
- //#endregion
89
- //#region extensions/slack/src/client.ts
90
- const SLACK_WRITE_CLIENT_CACHE_MAX = 32;
91
- const slackWriteClientCache = /* @__PURE__ */ new Map();
92
- let slackListenerUploadCompletionClientCache = /* @__PURE__ */ new WeakMap();
93
- function createSlackWebClient(token, options = {}) {
94
- return new WebClient(token, resolveSlackWebClientOptions(options));
95
- }
96
- function createSlackLookupClient(token, options = {}) {
97
- return new WebClient(token, resolveSlackLookupClientOptions(options));
98
- }
99
- function createSlackWriteClient(token, options = {}) {
100
- return new WebClient(token, resolveSlackWriteClientOptions(options));
101
- }
102
- function createSlackTokenCacheKey(token) {
103
- return `sha256:${createHash("sha256").update(token).digest("base64url")}`;
104
- }
105
- function slackWriteClientCacheKey(token, options) {
106
- const tokenKey = createSlackTokenCacheKey(token);
107
- return options.slackApiUrl ? `${tokenKey}:api:${options.slackApiUrl}` : tokenKey;
108
- }
109
- function getSlackWriteClient(token, options = {}) {
110
- const resolvedOptions = resolveSlackWriteClientOptions(options);
111
- const tokenKey = slackWriteClientCacheKey(token, resolvedOptions);
112
- const cached = slackWriteClientCache.get(tokenKey);
113
- if (cached) {
114
- slackWriteClientCache.delete(tokenKey);
115
- slackWriteClientCache.set(tokenKey, cached);
116
- return cached;
117
- }
118
- const client = new WebClient(token, resolvedOptions);
119
- if (slackWriteClientCache.size >= SLACK_WRITE_CLIENT_CACHE_MAX) {
120
- const oldestTokenKey = slackWriteClientCache.keys().next().value;
121
- if (oldestTokenKey) slackWriteClientCache.delete(oldestTokenKey);
122
- }
123
- slackWriteClientCache.set(tokenKey, client);
124
- return client;
125
- }
126
- function getSlackListenerUploadCompletionClient(params) {
127
- const token = params.listenerClient.token?.trim();
128
- const teamId = params.teamId.trim().toUpperCase();
129
- if (!token || !teamId) return;
130
- const cached = slackListenerUploadCompletionClientCache.get(params.listenerClient);
131
- if (cached) return cached.teamId === teamId ? cached.client : void 0;
132
- const headers = Object.fromEntries(Object.entries(params.clientOptions?.headers ?? {}).filter(([name]) => name.toLowerCase() !== "authorization"));
133
- const client = new WebClient(token, resolveSlackWriteClientOptions({
134
- ...params.clientOptions,
135
- headers,
136
- slackApiUrl: params.listenerClient.slackApiUrl,
137
- teamId,
138
- retryConfig: SLACK_WRITE_RETRY_OPTIONS,
139
- timeout: 0
140
- }));
141
- slackListenerUploadCompletionClientCache.set(params.listenerClient, {
142
- teamId,
143
- client
144
- });
145
- return client;
146
- }
147
- function clearSlackWriteClientCacheForTest() {
148
- slackWriteClientCache.clear();
149
- slackListenerUploadCompletionClientCache = /* @__PURE__ */ new WeakMap();
150
- }
151
- //#endregion
152
- export { createSlackWriteClient as a, SLACK_DEFAULT_RETRY_OPTIONS as c, resolveSlackWriteClientOptions as d, DEFAULT_ACCOUNT_ID$1 as f, resolveConfiguredFromRequiredCredentialStatuses as g, projectCredentialSnapshotFields as h, createSlackWebClient as i, SLACK_WRITE_RETRY_OPTIONS as l, getChatChannelMeta as m, createSlackLookupClient as n, getSlackListenerUploadCompletionClient as o, PAIRING_APPROVED_MESSAGE as p, createSlackTokenCacheKey as r, getSlackWriteClient as s, clearSlackWriteClientCacheForTest as t, resolveSlackWebClientOptions as u };
@@ -1,11 +0,0 @@
1
- //#region extensions/slack/configured-state.ts
2
- const SLACK_CONFIGURED_ENV_KEYS = [
3
- "SLACK_APP_TOKEN",
4
- "SLACK_BOT_TOKEN",
5
- "SLACK_USER_TOKEN"
6
- ];
7
- function hasSlackConfiguredState(params) {
8
- return SLACK_CONFIGURED_ENV_KEYS.some((key) => typeof params.env?.[key] === "string" && params.env[key]?.trim().length > 0);
9
- }
10
- //#endregion
11
- export { hasSlackConfiguredState };
@@ -1,48 +0,0 @@
1
- import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
- import { d as formatSlackBotTokenIdentityWarning } from "./accounts-BOJJiHSr.js";
3
- import { r as formatSlackError } from "./group-policy-C-b2ZnSl.js";
4
- import { i as createSlackWebClient } from "./client-D2F6m8CP.js";
5
- import { withTimeout } from "openclaw/plugin-sdk/text-utility-runtime";
6
- //#region extensions/slack/src/probe.ts
7
- var probe_exports = /* @__PURE__ */ __exportAll({ probeSlack: () => probeSlack });
8
- async function probeSlack(token, timeoutMs = 2500, opts) {
9
- const client = createSlackWebClient(token);
10
- const start = Date.now();
11
- try {
12
- const result = await withTimeout(client.auth.test(), timeoutMs);
13
- if (!result.ok) return {
14
- ok: false,
15
- status: 200,
16
- error: result.error ?? "unknown",
17
- elapsedMs: Date.now() - start
18
- };
19
- const warning = formatSlackBotTokenIdentityWarning({
20
- auth: result,
21
- accountId: opts?.accountId
22
- });
23
- return {
24
- ok: true,
25
- status: 200,
26
- elapsedMs: Date.now() - start,
27
- bot: {
28
- id: result.user_id,
29
- name: result.user
30
- },
31
- team: {
32
- id: result.team_id,
33
- name: result.team
34
- },
35
- ...warning ? { warning } : {}
36
- };
37
- } catch (err) {
38
- const message = formatSlackError(err);
39
- return {
40
- ok: false,
41
- status: typeof err.statusCode === "number" ? err.statusCode : null,
42
- error: message,
43
- elapsedMs: Date.now() - start
44
- };
45
- }
46
- }
47
- //#endregion
48
- export { probe_exports as n, probeSlack as t };