@openclaw/slack 2026.5.27 → 2026.5.28-beta.2

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 (94) hide show
  1. package/dist/{account-inspect-vVg3pT03.js → account-inspect-CdGk6R7l.js} +1 -1
  2. package/dist/account-inspect-api.js +1 -1
  3. package/dist/{accounts-BnLQ3fe2.js → accounts-f6Xcv9Vi.js} +42 -1
  4. package/dist/accounts.runtime-BJt1IxOS.js +2 -0
  5. package/dist/{action-runtime-JVb7KyQs.js → action-runtime-BOEgcnv6.js} +7 -8
  6. package/dist/action-runtime.runtime-BXQYV0yA.js +2 -0
  7. package/dist/{actions-1o9nMIY8.js → actions-zfVWcIY6.js} +4 -4
  8. package/dist/{actions.runtime-qQtdNww-.js → actions.runtime-CoijPN8g.js} +1 -1
  9. package/dist/api.js +14 -17
  10. package/dist/{approval-handler.runtime-Ba8nwnYi.js → approval-handler.runtime-CWz3XLfN.js} +12 -69
  11. package/dist/{channel-Bd7eept6.js → channel-D8p_1twn.js} +25 -28
  12. package/dist/channel-config-api.js +1 -1
  13. package/dist/channel-plugin-api.js +1 -1
  14. package/dist/{channel.setup-WNNVmCm0.js → channel.setup-oGp4gSTP.js} +4 -4
  15. package/dist/{client-Dc2Ji2YN.js → client-DowBk5k0.js} +6 -24
  16. package/dist/{config-schema-CUiDK8HV.js → config-schema-C0RewpJQ.js} +4 -0
  17. package/dist/contract-api.js +1 -1
  18. package/dist/{directory-config-9_djLTOK.js → directory-config-8UPAEyNg.js} +1 -1
  19. package/dist/directory-contract-api.js +1 -1
  20. package/dist/{directory-live-Cl83cGLZ.js → directory-live-BFB1pSax.js} +2 -2
  21. package/dist/http-routes-api.js +1 -1
  22. package/dist/index.js +3 -7
  23. package/dist/{interactive-replies-DtYu4Sf5.js → interactive-replies-DrBq4Mld.js} +1 -1
  24. package/dist/interactive-replies-api.js +1 -1
  25. package/dist/{message-tool-api-BieXX5lk.js → message-tool-api-B9M0zzlQ.js} +2 -2
  26. package/dist/message-tool-api.js +1 -1
  27. package/dist/{monitor-Cn7LUDFL.js → monitor-D7jGKmQk.js} +3 -4
  28. package/dist/{outbound-adapter-ChuR4_0v.js → outbound-adapter-BHZMgblN.js} +4 -7
  29. package/dist/pipeline.runtime-xM6ppqQZ.js +3492 -0
  30. package/dist/plugin-routes-B9PvcDQJ.js +22 -0
  31. package/dist/{policy-pu8tsF8_.js → policy-BBDU-PQK.js} +1 -1
  32. package/dist/{probe-cBVPhCKZ.js → probe-Djes9Fy6.js} +1 -1
  33. package/dist/{provider-Bccng2Wp.js → provider-CxMP_s2o.js} +828 -28
  34. package/dist/{replies-jiEDV6lH.js → replies-DkmWK7JW.js} +2 -4
  35. package/dist/{resolve-channels-CT4oiz_9.js → resolve-channels-zXt5f47h.js} +1 -1
  36. package/dist/{resolve-users-o5S-Ijks.js → resolve-users-BLfGAz1v.js} +1 -1
  37. package/dist/{runtime-api-CyPE-EvY.js → runtime-api-DvpUD2hw.js} +2 -2
  38. package/dist/runtime-api.js +12 -12
  39. package/dist/{scopes-CnyhLIPT.js → scopes-DiiHsqh1.js} +1 -1
  40. package/dist/{send-DvfE8LVm.js → send-BURYyCXI.js} +4 -4
  41. package/dist/send.runtime-CKaMG3s-.js +2 -0
  42. package/dist/{setup-core-DKe7Ug3V.js → setup-core-POfI_bgP.js} +2 -2
  43. package/dist/setup-entry.js +8 -1
  44. package/dist/setup-plugin-api.js +1 -1
  45. package/dist/{setup-surface-gjRthuZA.js → setup-surface-DJTHAguz.js} +5 -5
  46. package/dist/{shared-D8A7iVVH.js → shared-D9WMYymo.js} +5 -5
  47. package/dist/{slash-dispatch.runtime-BBhdJHb8.js → slash-dispatch.runtime-lsyTm_q5.js} +1 -1
  48. package/dist/thread-ts-NSVqWybn.js +646 -0
  49. package/node_modules/semver/classes/range.js +7 -0
  50. package/node_modules/semver/package.json +1 -1
  51. package/node_modules/semver/ranges/subset.js +2 -2
  52. package/npm-shrinkwrap.json +6 -29
  53. package/openclaw.plugin.json +10 -0
  54. package/package.json +8 -7
  55. package/dist/accounts.runtime-BVdtQeuq.js +0 -2
  56. package/dist/action-runtime.runtime-BZa5VDjs.js +0 -2
  57. package/dist/allow-list-B1lkGjwl.js +0 -82
  58. package/dist/blocks-render-CNC4vQnd.js +0 -232
  59. package/dist/inbound-contract-test-api.js +0 -3
  60. package/dist/magic-string.es-BPXBBMwL.js +0 -1011
  61. package/dist/outbound-payload-test-api.js +0 -2
  62. package/dist/outbound-payload.test-harness-8MnHFgR1.js +0 -13551
  63. package/dist/pipeline.runtime-BVK8yXw_.js +0 -1473
  64. package/dist/plugin-routes-DRR3ijKM.js +0 -20
  65. package/dist/prepare-Bl5WcC3f.js +0 -1713
  66. package/dist/prepare.test-helpers-BcAo4KMw.js +0 -49
  67. package/dist/reply-blocks-BlOURkUm.js +0 -290
  68. package/dist/room-context-BmNTBiw5.js +0 -816
  69. package/dist/send.runtime-Dv6ajTGK.js +0 -2
  70. package/dist/send.runtime-v3TSw9xY.js +0 -2
  71. package/dist/test-api.js +0 -8
  72. package/dist/thread-ts-ks-O8cEG.js +0 -52
  73. package/node_modules/agent-base/LICENSE +0 -22
  74. package/node_modules/agent-base/README.md +0 -69
  75. package/node_modules/agent-base/dist/helpers.d.ts +0 -10
  76. package/node_modules/agent-base/dist/helpers.d.ts.map +0 -1
  77. package/node_modules/agent-base/dist/helpers.js +0 -37
  78. package/node_modules/agent-base/dist/helpers.js.map +0 -1
  79. package/node_modules/agent-base/dist/index.d.ts +0 -37
  80. package/node_modules/agent-base/dist/index.d.ts.map +0 -1
  81. package/node_modules/agent-base/dist/index.js +0 -146
  82. package/node_modules/agent-base/dist/index.js.map +0 -1
  83. package/node_modules/agent-base/package.json +0 -46
  84. package/node_modules/https-proxy-agent/LICENSE +0 -22
  85. package/node_modules/https-proxy-agent/README.md +0 -70
  86. package/node_modules/https-proxy-agent/dist/index.d.ts +0 -43
  87. package/node_modules/https-proxy-agent/dist/index.d.ts.map +0 -1
  88. package/node_modules/https-proxy-agent/dist/index.js +0 -150
  89. package/node_modules/https-proxy-agent/dist/index.js.map +0 -1
  90. package/node_modules/https-proxy-agent/dist/parse-proxy-response.d.ts +0 -12
  91. package/node_modules/https-proxy-agent/dist/parse-proxy-response.d.ts.map +0 -1
  92. package/node_modules/https-proxy-agent/dist/parse-proxy-response.js +0 -94
  93. package/node_modules/https-proxy-agent/dist/parse-proxy-response.js.map +0 -1
  94. package/node_modules/https-proxy-agent/package.json +0 -50
@@ -0,0 +1,646 @@
1
+ import { a as resolveSlackAccount, i as resolveDefaultSlackAccountId, o as resolveSlackAccountAllowFrom, r as mergeSlackAccountConfig } from "./accounts-f6Xcv9Vi.js";
2
+ import { normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
3
+ import { normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringifiedOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
4
+ import { normalizeMessageChannel } from "openclaw/plugin-sdk/routing";
5
+ import { doesApprovalRequestMatchChannelAccount, resolveApprovalRequestSessionConversation } from "openclaw/plugin-sdk/approval-native-runtime";
6
+ import { createResolvedApproverActionAuthAdapter, resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";
7
+ import { createChannelExecApprovalProfile, isChannelExecApprovalClientEnabledFromConfig, isChannelExecApprovalTargetRecipient, matchesApprovalRequestFilters } from "openclaw/plugin-sdk/approval-client-runtime";
8
+ import { reduceInteractiveReply } from "openclaw/plugin-sdk/interactive-runtime";
9
+ import { compileAllowlist, resolveCompiledAllowlistMatch } from "openclaw/plugin-sdk/allow-from";
10
+ import { normalizeHyphenSlug, normalizeStringEntries as normalizeStringEntries$1, normalizeStringEntriesLower as normalizeStringEntriesLower$1 } from "openclaw/plugin-sdk/string-normalization-runtime";
11
+ import { resolveToolsBySender } from "openclaw/plugin-sdk/channel-policy";
12
+ //#region extensions/slack/src/exec-approvals.ts
13
+ function normalizeSlackUserLikeId(value) {
14
+ const upper = value.toUpperCase();
15
+ return /^[UW][A-Z0-9]+$/.test(upper) ? upper : void 0;
16
+ }
17
+ function normalizeSlackApproverId(value) {
18
+ const trimmed = normalizeStringifiedOptionalString(value);
19
+ if (!trimmed) return;
20
+ const prefixed = trimmed.match(/^(?:slack|user):([A-Z0-9]+)$/i);
21
+ if (prefixed?.[1]) return normalizeSlackUserLikeId(prefixed[1]);
22
+ const mention = trimmed.match(/^<@([A-Z0-9]+)>$/i);
23
+ if (mention?.[1]) return normalizeSlackUserLikeId(mention[1]);
24
+ return normalizeSlackUserLikeId(trimmed);
25
+ }
26
+ function resolveSlackOwnerApprovers(cfg) {
27
+ const ownerAllowFrom = cfg.commands?.ownerAllowFrom;
28
+ if (!Array.isArray(ownerAllowFrom) || ownerAllowFrom.length === 0) return [];
29
+ return resolveApprovalApprovers({
30
+ explicit: ownerAllowFrom,
31
+ normalizeApprover: normalizeSlackApproverId
32
+ });
33
+ }
34
+ function getSlackExecApprovalApprovers(params) {
35
+ const account = resolveSlackAccount(params).config;
36
+ return resolveApprovalApprovers({
37
+ explicit: account.execApprovals?.approvers ?? resolveSlackOwnerApprovers(params.cfg),
38
+ normalizeApprover: normalizeSlackApproverId
39
+ });
40
+ }
41
+ function isSlackExecApprovalTargetRecipient(params) {
42
+ return isChannelExecApprovalTargetRecipient({
43
+ ...params,
44
+ channel: "slack",
45
+ normalizeSenderId: normalizeSlackApproverId,
46
+ matchTarget: ({ target, normalizedSenderId }) => normalizeSlackApproverId(target.to) === normalizedSenderId
47
+ });
48
+ }
49
+ const slackExecApprovalProfile = createChannelExecApprovalProfile({
50
+ resolveConfig: (params) => resolveSlackAccount(params).config.execApprovals,
51
+ resolveApprovers: getSlackExecApprovalApprovers,
52
+ normalizeSenderId: normalizeSlackApproverId,
53
+ isTargetRecipient: isSlackExecApprovalTargetRecipient,
54
+ matchesRequestAccount: (params) => doesApprovalRequestMatchChannelAccount({
55
+ cfg: params.cfg,
56
+ request: params.request,
57
+ channel: "slack",
58
+ accountId: params.accountId
59
+ })
60
+ });
61
+ const isSlackExecApprovalClientEnabled = slackExecApprovalProfile.isClientEnabled;
62
+ slackExecApprovalProfile.isApprover;
63
+ const isSlackExecApprovalAuthorizedSender = slackExecApprovalProfile.isAuthorizedSender;
64
+ const resolveSlackExecApprovalTarget = slackExecApprovalProfile.resolveTarget;
65
+ slackExecApprovalProfile.shouldHandleRequest;
66
+ const shouldSuppressLocalSlackExecApprovalPrompt = slackExecApprovalProfile.shouldSuppressLocalPrompt;
67
+ //#endregion
68
+ //#region extensions/slack/src/approval-auth.ts
69
+ function getSlackApprovalApprovers(params) {
70
+ const account = resolveSlackAccount(params).config;
71
+ return resolveApprovalApprovers({
72
+ allowFrom: resolveSlackAccountAllowFrom(params),
73
+ defaultTo: account.defaultTo,
74
+ normalizeApprover: normalizeSlackApproverId,
75
+ normalizeDefaultTo: normalizeSlackApproverId
76
+ });
77
+ }
78
+ function isSlackApprovalAuthorizedSender(params) {
79
+ const senderId = params.senderId ? normalizeSlackApproverId(params.senderId) : void 0;
80
+ if (!senderId) return false;
81
+ return getSlackApprovalApprovers(params).includes(senderId);
82
+ }
83
+ createResolvedApproverActionAuthAdapter({
84
+ channelLabel: "Slack",
85
+ resolveApprovers: ({ cfg, accountId }) => getSlackApprovalApprovers({
86
+ cfg,
87
+ accountId
88
+ }),
89
+ normalizeSenderId: (value) => normalizeSlackApproverId(value)
90
+ });
91
+ //#endregion
92
+ //#region extensions/slack/src/approval-native-gates.ts
93
+ function resolveSlackApprovalKind(request) {
94
+ return request.id.startsWith("plugin:") ? "plugin" : "exec";
95
+ }
96
+ function resolveSlackNativeApprovalConfig(params) {
97
+ return resolveSlackAccount(params).config.execApprovals;
98
+ }
99
+ function resolvePluginApprovalForwardingConfig(cfg) {
100
+ return cfg.approvals?.plugin;
101
+ }
102
+ function getSlackNativeApprovalApprovers(params) {
103
+ return params.approvalKind === "plugin" ? getSlackApprovalApprovers(params) : getSlackExecApprovalApprovers(params);
104
+ }
105
+ function normalizeAccountId$2(value) {
106
+ return normalizeOptionalString(value)?.toLowerCase();
107
+ }
108
+ function matchesSlackAccount(params) {
109
+ const expected = normalizeAccountId$2(params.expectedAccountId);
110
+ const actual = normalizeAccountId$2(params.actualAccountId);
111
+ return !expected || !actual || expected === actual;
112
+ }
113
+ function modeIncludesSession(mode) {
114
+ return mode === void 0 || mode === "session" || mode === "both";
115
+ }
116
+ function modeIncludesTargets(mode) {
117
+ return mode === "targets" || mode === "both";
118
+ }
119
+ function hasSlackPluginForwardingTarget(params) {
120
+ return (resolvePluginApprovalForwardingConfig(params.cfg)?.targets ?? []).some((target) => {
121
+ return (normalizeMessageChannel(target.channel) ?? target.channel) === "slack" && matchesSlackAccount({
122
+ expectedAccountId: params.accountId,
123
+ actualAccountId: target.accountId
124
+ });
125
+ });
126
+ }
127
+ function requestHasSlackOriginOrSession(params) {
128
+ const request = params.request.request;
129
+ const turnSourceChannel = normalizeMessageChannel(request.turnSourceChannel);
130
+ if (turnSourceChannel) return turnSourceChannel === "slack" && matchesSlackAccount({
131
+ expectedAccountId: params.accountId,
132
+ actualAccountId: request.turnSourceAccountId
133
+ });
134
+ return resolveApprovalRequestSessionConversation({
135
+ request: params.request,
136
+ channel: "slack",
137
+ bundledFallback: false
138
+ }) !== null && doesApprovalRequestMatchChannelAccount({
139
+ cfg: params.cfg,
140
+ request: params.request,
141
+ channel: "slack",
142
+ accountId: params.accountId
143
+ });
144
+ }
145
+ function isPluginForwardingEnabledForRequest(params) {
146
+ const config = resolvePluginApprovalForwardingConfig(params.cfg);
147
+ if (!config?.enabled) return false;
148
+ return matchesApprovalRequestFilters({
149
+ request: params.request.request,
150
+ agentFilter: config.agentFilter,
151
+ sessionFilter: config.sessionFilter
152
+ });
153
+ }
154
+ function canPluginForwardingRouteToSlack(params) {
155
+ const mode = resolvePluginApprovalForwardingConfig(params.cfg)?.mode;
156
+ if (modeIncludesSession(mode) && requestHasSlackOriginOrSession({
157
+ cfg: params.cfg,
158
+ request: params.request,
159
+ accountId: params.accountId
160
+ })) return true;
161
+ return modeIncludesTargets(mode) && hasSlackPluginForwardingTarget(params);
162
+ }
163
+ function isSlackPluginNativeApprovalClientEnabled(params) {
164
+ if (isChannelExecApprovalClientEnabledFromConfig({
165
+ enabled: resolveSlackNativeApprovalConfig(params)?.enabled,
166
+ approverCount: getSlackApprovalApprovers(params).length
167
+ })) return true;
168
+ const config = resolvePluginApprovalForwardingConfig(params.cfg);
169
+ if (!config?.enabled || getSlackApprovalApprovers(params).length <= 0) return false;
170
+ const mode = config.mode;
171
+ return modeIncludesSession(mode) || modeIncludesTargets(mode) && hasSlackPluginForwardingTarget(params);
172
+ }
173
+ function shouldHandleSlackPluginViaNativeClientConfig(params) {
174
+ if (!doesApprovalRequestMatchChannelAccount({
175
+ cfg: params.cfg,
176
+ request: params.request,
177
+ channel: "slack",
178
+ accountId: params.accountId
179
+ })) return false;
180
+ const config = resolveSlackNativeApprovalConfig(params);
181
+ if (!isChannelExecApprovalClientEnabledFromConfig({
182
+ enabled: config?.enabled,
183
+ approverCount: getSlackApprovalApprovers(params).length
184
+ })) return false;
185
+ return matchesApprovalRequestFilters({
186
+ request: params.request.request,
187
+ agentFilter: config?.agentFilter,
188
+ sessionFilter: config?.sessionFilter
189
+ });
190
+ }
191
+ function shouldHandleSlackPluginNativeApprovalRequest(params) {
192
+ if (getSlackApprovalApprovers(params).length <= 0) return false;
193
+ if (shouldHandleSlackPluginViaNativeClientConfig(params)) return true;
194
+ if (!isPluginForwardingEnabledForRequest(params)) return false;
195
+ return canPluginForwardingRouteToSlack(params);
196
+ }
197
+ function isSlackNativeApprovalClientEnabled(params) {
198
+ if (params.approvalKind === "exec") return isSlackExecApprovalClientEnabled(params);
199
+ return isSlackPluginNativeApprovalClientEnabled(params);
200
+ }
201
+ function isSlackAnyNativeApprovalClientEnabled(params) {
202
+ return isSlackNativeApprovalClientEnabled({
203
+ ...params,
204
+ approvalKind: "exec"
205
+ }) || isSlackNativeApprovalClientEnabled({
206
+ ...params,
207
+ approvalKind: "plugin"
208
+ });
209
+ }
210
+ function shouldHandleSlackNativeApprovalRequest(params) {
211
+ const approvalKind = params.approvalKind ?? resolveSlackApprovalKind(params.request);
212
+ if (approvalKind === "plugin") return shouldHandleSlackPluginNativeApprovalRequest({
213
+ cfg: params.cfg,
214
+ accountId: params.accountId,
215
+ request: params.request
216
+ });
217
+ if (!doesApprovalRequestMatchChannelAccount({
218
+ cfg: params.cfg,
219
+ request: params.request,
220
+ channel: "slack",
221
+ accountId: params.accountId
222
+ })) return false;
223
+ const config = resolveSlackNativeApprovalConfig(params);
224
+ if (!isChannelExecApprovalClientEnabledFromConfig({
225
+ enabled: config?.enabled,
226
+ approverCount: getSlackNativeApprovalApprovers({
227
+ ...params,
228
+ approvalKind
229
+ }).length
230
+ })) return false;
231
+ return matchesApprovalRequestFilters({
232
+ request: params.request.request,
233
+ agentFilter: config?.agentFilter,
234
+ sessionFilter: config?.sessionFilter
235
+ });
236
+ }
237
+ //#endregion
238
+ //#region extensions/slack/src/reply-action-ids.ts
239
+ const SLACK_REPLY_BUTTON_ACTION_ID = "openclaw:reply_button";
240
+ const SLACK_REPLY_SELECT_ACTION_ID = "openclaw:reply_select";
241
+ //#endregion
242
+ //#region extensions/slack/src/truncate.ts
243
+ function truncateSlackText(value, max) {
244
+ const trimmed = value.trim();
245
+ if (trimmed.length <= max) return trimmed;
246
+ if (max <= 1) return trimmed.slice(0, max);
247
+ return `${trimmed.slice(0, max - 1)}…`;
248
+ }
249
+ //#endregion
250
+ //#region extensions/slack/src/blocks-render.ts
251
+ const SLACK_SECTION_TEXT_MAX = 3e3;
252
+ const SLACK_PLAIN_TEXT_MAX = 75;
253
+ const SLACK_OPTION_VALUE_MAX = 150;
254
+ const SLACK_BUTTON_VALUE_MAX = 2e3;
255
+ const SLACK_BUTTON_URL_MAX = 3e3;
256
+ const SLACK_STATIC_SELECT_OPTIONS_MAX = 100;
257
+ const SLACK_ACTION_BLOCK_ELEMENTS_MAX = 25;
258
+ function buildSlackReplyButtonActionId(buttonIndex, choiceIndex) {
259
+ return `${SLACK_REPLY_BUTTON_ACTION_ID}:${String(buttonIndex)}:${String(choiceIndex + 1)}`;
260
+ }
261
+ function buildSlackReplySelectActionId(selectIndex) {
262
+ return `${SLACK_REPLY_SELECT_ACTION_ID}:${String(selectIndex)}`;
263
+ }
264
+ function resolveSlackButtonStyle(style) {
265
+ if (style === "primary" || style === "danger") return style;
266
+ if (style === "success") return "primary";
267
+ }
268
+ function isWithinSlackLimit(value, maxLength) {
269
+ return value.length <= maxLength;
270
+ }
271
+ function readSlackBlockId(block) {
272
+ const value = block.block_id;
273
+ return typeof value === "string" ? value : void 0;
274
+ }
275
+ function readSlackOpenClawBlockIndex(blockId, prefix) {
276
+ if (!blockId.startsWith(prefix)) return;
277
+ const value = Number.parseInt(blockId.slice(prefix.length), 10);
278
+ return Number.isSafeInteger(value) && value > 0 ? value : void 0;
279
+ }
280
+ /** Resolve existing OpenClaw Block Kit indexes so appended controls keep stable unique IDs. */
281
+ function resolveSlackInteractiveBlockOffsets(blocks) {
282
+ let buttonIndexOffset = 0;
283
+ let selectIndexOffset = 0;
284
+ for (const block of blocks ?? []) {
285
+ const blockId = readSlackBlockId(block);
286
+ if (!blockId) continue;
287
+ buttonIndexOffset = Math.max(buttonIndexOffset, readSlackOpenClawBlockIndex(blockId, "openclaw_reply_buttons_") ?? 0);
288
+ selectIndexOffset = Math.max(selectIndexOffset, readSlackOpenClawBlockIndex(blockId, "openclaw_reply_select_") ?? 0);
289
+ }
290
+ return {
291
+ buttonIndexOffset,
292
+ selectIndexOffset
293
+ };
294
+ }
295
+ /**
296
+ * @deprecated Use buildSlackPresentationBlocks with MessagePresentation.
297
+ */
298
+ function buildSlackInteractiveBlocks(interactive, options = {}) {
299
+ return reduceInteractiveReply(interactive, {
300
+ blocks: [],
301
+ buttonIndex: options.buttonIndexOffset ?? 0,
302
+ selectIndex: options.selectIndexOffset ?? 0
303
+ }, (state, block) => {
304
+ if (block.type === "text") {
305
+ const trimmed = block.text.trim();
306
+ if (!trimmed) return state;
307
+ state.blocks.push({
308
+ type: "section",
309
+ text: {
310
+ type: "mrkdwn",
311
+ text: truncateSlackText(trimmed, SLACK_SECTION_TEXT_MAX)
312
+ }
313
+ });
314
+ return state;
315
+ }
316
+ if (block.type === "buttons") {
317
+ const elements = block.buttons.flatMap((button, choiceIndex) => {
318
+ const value = button.value && isWithinSlackLimit(button.value, SLACK_BUTTON_VALUE_MAX) ? button.value : void 0;
319
+ const url = button.url && isWithinSlackLimit(button.url, SLACK_BUTTON_URL_MAX) ? button.url : void 0;
320
+ if (!value && !url) return [];
321
+ const style = resolveSlackButtonStyle(button.style);
322
+ return [{
323
+ type: "button",
324
+ action_id: buildSlackReplyButtonActionId(state.buttonIndex + 1, choiceIndex),
325
+ text: {
326
+ type: "plain_text",
327
+ text: truncateSlackText(button.label, SLACK_PLAIN_TEXT_MAX),
328
+ emoji: true
329
+ },
330
+ ...value ? { value } : {},
331
+ ...url ? { url } : {},
332
+ ...style ? { style } : {}
333
+ }];
334
+ }).slice(0, SLACK_ACTION_BLOCK_ELEMENTS_MAX);
335
+ if (elements.length === 0) return state;
336
+ state.blocks.push({
337
+ type: "actions",
338
+ block_id: `openclaw_reply_buttons_${++state.buttonIndex}`,
339
+ elements
340
+ });
341
+ return state;
342
+ }
343
+ const options = block.options.filter((option) => isWithinSlackLimit(option.value, SLACK_OPTION_VALUE_MAX)).slice(0, SLACK_STATIC_SELECT_OPTIONS_MAX);
344
+ if (options.length === 0) return state;
345
+ state.blocks.push({
346
+ type: "actions",
347
+ block_id: `openclaw_reply_select_${++state.selectIndex}`,
348
+ elements: [{
349
+ type: "static_select",
350
+ action_id: buildSlackReplySelectActionId(state.selectIndex),
351
+ placeholder: {
352
+ type: "plain_text",
353
+ text: truncateSlackText(normalizeOptionalString(block.placeholder) ?? "Choose an option", SLACK_PLAIN_TEXT_MAX),
354
+ emoji: true
355
+ },
356
+ options: options.map((option, _choiceIndex) => ({
357
+ text: {
358
+ type: "plain_text",
359
+ text: truncateSlackText(option.label, SLACK_PLAIN_TEXT_MAX),
360
+ emoji: true
361
+ },
362
+ value: option.value
363
+ }))
364
+ }]
365
+ });
366
+ return state;
367
+ }).blocks;
368
+ }
369
+ /** Render portable presentation blocks as Slack Block Kit blocks. */
370
+ function buildSlackPresentationBlocks(presentation, options = {}) {
371
+ if (!presentation) return [];
372
+ const blocks = [];
373
+ if (presentation.title) blocks.push({
374
+ type: "header",
375
+ text: {
376
+ type: "plain_text",
377
+ text: truncateSlackText(presentation.title, 150),
378
+ emoji: true
379
+ }
380
+ });
381
+ for (const block of presentation.blocks) {
382
+ if (block.type === "text" || block.type === "context") {
383
+ const text = block.text.trim();
384
+ if (!text) continue;
385
+ if (block.type === "context") blocks.push({
386
+ type: "context",
387
+ elements: [{
388
+ type: "mrkdwn",
389
+ text: truncateSlackText(text, SLACK_SECTION_TEXT_MAX)
390
+ }]
391
+ });
392
+ else blocks.push({
393
+ type: "section",
394
+ text: {
395
+ type: "mrkdwn",
396
+ text: truncateSlackText(text, SLACK_SECTION_TEXT_MAX)
397
+ }
398
+ });
399
+ continue;
400
+ }
401
+ if (block.type === "divider") blocks.push({ type: "divider" });
402
+ }
403
+ let buttonIndex = options.buttonIndexOffset ?? 0;
404
+ let selectIndex = options.selectIndexOffset ?? 0;
405
+ for (const block of presentation.blocks) {
406
+ if (block.type === "buttons") {
407
+ const rendered = buildSlackPresentationButtonBlock(block, buttonIndex + 1);
408
+ if (rendered) {
409
+ buttonIndex += 1;
410
+ blocks.push(rendered);
411
+ }
412
+ continue;
413
+ }
414
+ if (block.type === "select") {
415
+ const rendered = buildSlackPresentationSelectBlock(block, selectIndex + 1);
416
+ if (rendered) {
417
+ selectIndex += 1;
418
+ blocks.push(rendered);
419
+ }
420
+ }
421
+ }
422
+ return blocks;
423
+ }
424
+ function buildSlackPresentationButtonBlock(block, buttonIndex) {
425
+ const elements = block.buttons.flatMap((button, choiceIndex) => {
426
+ const value = button.value && isWithinSlackLimit(button.value, SLACK_BUTTON_VALUE_MAX) ? button.value : void 0;
427
+ const url = button.url && isWithinSlackLimit(button.url, SLACK_BUTTON_URL_MAX) ? button.url : void 0;
428
+ if (!value && !url) return [];
429
+ const style = resolveSlackButtonStyle(button.style);
430
+ return [{
431
+ type: "button",
432
+ action_id: buildSlackReplyButtonActionId(buttonIndex, choiceIndex),
433
+ text: {
434
+ type: "plain_text",
435
+ text: truncateSlackText(button.label, SLACK_PLAIN_TEXT_MAX),
436
+ emoji: true
437
+ },
438
+ ...value ? { value } : {},
439
+ ...url ? { url } : {},
440
+ ...style ? { style } : {}
441
+ }];
442
+ }).slice(0, SLACK_ACTION_BLOCK_ELEMENTS_MAX);
443
+ return elements.length > 0 ? {
444
+ type: "actions",
445
+ block_id: `openclaw_reply_buttons_${buttonIndex}`,
446
+ elements
447
+ } : void 0;
448
+ }
449
+ function buildSlackPresentationSelectBlock(block, selectIndex) {
450
+ const options = block.options.filter((option) => isWithinSlackLimit(option.value, SLACK_OPTION_VALUE_MAX)).slice(0, SLACK_STATIC_SELECT_OPTIONS_MAX);
451
+ return options.length > 0 ? {
452
+ type: "actions",
453
+ block_id: `openclaw_reply_select_${selectIndex}`,
454
+ elements: [{
455
+ type: "static_select",
456
+ action_id: buildSlackReplySelectActionId(selectIndex),
457
+ placeholder: {
458
+ type: "plain_text",
459
+ text: truncateSlackText(normalizeOptionalString(block.placeholder) ?? "Choose an option", SLACK_PLAIN_TEXT_MAX),
460
+ emoji: true
461
+ },
462
+ options: options.map((option) => ({
463
+ text: {
464
+ type: "plain_text",
465
+ text: truncateSlackText(option.label, SLACK_PLAIN_TEXT_MAX),
466
+ emoji: true
467
+ },
468
+ value: option.value
469
+ }))
470
+ }]
471
+ } : void 0;
472
+ }
473
+ //#endregion
474
+ //#region extensions/slack/src/monitor/allow-list.ts
475
+ const SLACK_SLUG_CACHE_MAX = 512;
476
+ const slackSlugCache = /* @__PURE__ */ new Map();
477
+ function normalizeSlackSlug(raw) {
478
+ const key = raw ?? "";
479
+ const cached = slackSlugCache.get(key);
480
+ if (cached !== void 0) return cached;
481
+ const normalized = normalizeHyphenSlug(raw);
482
+ slackSlugCache.set(key, normalized);
483
+ if (slackSlugCache.size > SLACK_SLUG_CACHE_MAX) {
484
+ const oldest = slackSlugCache.keys().next();
485
+ if (!oldest.done) slackSlugCache.delete(oldest.value);
486
+ }
487
+ return normalized;
488
+ }
489
+ function normalizeAllowList(list) {
490
+ return normalizeStringEntries$1(list);
491
+ }
492
+ function normalizeAllowListLower(list) {
493
+ return normalizeStringEntriesLower$1(list);
494
+ }
495
+ function normalizeSlackAllowOwnerEntry(entry) {
496
+ const trimmed = normalizeOptionalLowercaseString(entry);
497
+ if (!trimmed || trimmed === "*") return;
498
+ const withoutPrefix = trimmed.replace(/^(slack:|user:)/, "");
499
+ return /^u[a-z0-9]+$/.test(withoutPrefix) ? withoutPrefix : void 0;
500
+ }
501
+ function resolveSlackAllowListMatch(params) {
502
+ const compiledAllowList = compileAllowlist(params.allowList);
503
+ const id = normalizeOptionalLowercaseString(params.id);
504
+ const name = normalizeOptionalLowercaseString(params.name);
505
+ const slug = normalizeSlackSlug(name);
506
+ return resolveCompiledAllowlistMatch({
507
+ compiledAllowlist: compiledAllowList,
508
+ candidates: [
509
+ {
510
+ value: id,
511
+ source: "id"
512
+ },
513
+ {
514
+ value: id ? `slack:${id}` : void 0,
515
+ source: "prefixed-id"
516
+ },
517
+ {
518
+ value: id ? `user:${id}` : void 0,
519
+ source: "prefixed-user"
520
+ },
521
+ ...params.allowNameMatching === true ? [
522
+ {
523
+ value: name,
524
+ source: "name"
525
+ },
526
+ {
527
+ value: name ? `slack:${name}` : void 0,
528
+ source: "prefixed-name"
529
+ },
530
+ {
531
+ value: slug,
532
+ source: "slug"
533
+ }
534
+ ] : []
535
+ ]
536
+ });
537
+ }
538
+ function allowListMatches(params) {
539
+ return resolveSlackAllowListMatch(params).allowed;
540
+ }
541
+ function resolveSlackUserAllowed(params) {
542
+ const allowList = normalizeAllowListLower(params.allowList);
543
+ if (allowList.length === 0) return true;
544
+ return allowListMatches({
545
+ allowList,
546
+ id: params.userId,
547
+ name: params.userName,
548
+ allowNameMatching: params.allowNameMatching
549
+ });
550
+ }
551
+ //#endregion
552
+ //#region extensions/slack/src/group-policy.ts
553
+ function resolveSlackChannelPolicyEntry(params) {
554
+ const accountId = normalizeAccountId(params.accountId ?? resolveDefaultSlackAccountId(params.cfg));
555
+ const channelMap = mergeSlackAccountConfig(params.cfg, accountId).channels ?? {};
556
+ if (Object.keys(channelMap).length === 0) return;
557
+ const channelId = params.groupId?.trim();
558
+ const channelName = params.groupChannel?.replace(/^#/, "");
559
+ const normalizedName = normalizeHyphenSlug(channelName);
560
+ const candidates = [
561
+ channelId ?? "",
562
+ channelName ? `#${channelName}` : "",
563
+ channelName ?? "",
564
+ normalizedName
565
+ ].filter(Boolean);
566
+ for (const candidate of candidates) if (candidate && channelMap[candidate]) return channelMap[candidate];
567
+ return channelMap["*"];
568
+ }
569
+ function resolveSenderToolsEntry(entry, params) {
570
+ if (!entry) return;
571
+ return resolveToolsBySender({
572
+ toolsBySender: entry.toolsBySender,
573
+ senderId: params.senderId,
574
+ senderName: params.senderName,
575
+ senderUsername: params.senderUsername,
576
+ senderE164: params.senderE164
577
+ }) ?? entry.tools;
578
+ }
579
+ function resolveSlackGroupRequireMention(params) {
580
+ const resolved = resolveSlackChannelPolicyEntry(params);
581
+ if (typeof resolved?.requireMention === "boolean") return resolved.requireMention;
582
+ return true;
583
+ }
584
+ function resolveSlackGroupToolPolicy(params) {
585
+ return resolveSenderToolsEntry(resolveSlackChannelPolicyEntry(params), params);
586
+ }
587
+ //#endregion
588
+ //#region extensions/slack/src/limits.ts
589
+ const SLACK_TEXT_LIMIT = 8e3;
590
+ //#endregion
591
+ //#region extensions/slack/src/blocks-input.ts
592
+ const SLACK_MAX_BLOCKS = 50;
593
+ function parseBlocksJson(raw) {
594
+ try {
595
+ return JSON.parse(raw);
596
+ } catch {
597
+ throw new Error("blocks must be valid JSON");
598
+ }
599
+ }
600
+ function assertBlocksArray(raw) {
601
+ if (!Array.isArray(raw)) throw new Error("blocks must be an array");
602
+ if (raw.length === 0) throw new Error("blocks must contain at least one block");
603
+ if (raw.length > 50) throw new Error(`blocks cannot exceed 50 items`);
604
+ for (const block of raw) {
605
+ if (!block || typeof block !== "object" || Array.isArray(block)) throw new Error("each block must be an object");
606
+ const type = block.type;
607
+ if (typeof type !== "string" || type.trim().length === 0) throw new Error("each block must include a non-empty string type");
608
+ }
609
+ }
610
+ function validateSlackBlocksArray(raw) {
611
+ assertBlocksArray(raw);
612
+ return raw;
613
+ }
614
+ function parseSlackBlocksInput(raw) {
615
+ if (raw == null) return;
616
+ return validateSlackBlocksArray(typeof raw === "string" ? parseBlocksJson(raw) : raw);
617
+ }
618
+ //#endregion
619
+ //#region extensions/slack/src/reply-blocks.ts
620
+ function resolveSlackReplyBlocks(payload) {
621
+ const slackData = payload.channelData?.slack;
622
+ let channelBlocks = [];
623
+ if (slackData && typeof slackData === "object" && !Array.isArray(slackData)) channelBlocks = parseSlackBlocksInput(slackData.blocks) ?? [];
624
+ const presentationBlocks = buildSlackPresentationBlocks(payload.presentation, resolveSlackInteractiveBlockOffsets(channelBlocks));
625
+ const interactiveBlocks = buildSlackInteractiveBlocks(payload.interactive, resolveSlackInteractiveBlockOffsets([...channelBlocks, ...presentationBlocks]));
626
+ const blocks = [
627
+ ...channelBlocks,
628
+ ...presentationBlocks,
629
+ ...interactiveBlocks
630
+ ];
631
+ if (blocks.length > 50) throw new Error(`Slack blocks cannot exceed 50 items after interactive render`);
632
+ return blocks.length > 0 ? blocks : void 0;
633
+ }
634
+ //#endregion
635
+ //#region extensions/slack/src/thread-ts.ts
636
+ const SLACK_THREAD_TS_PATTERN = /^\d+\.\d+$/;
637
+ function normalizeSlackThreadTsCandidate(value) {
638
+ if (typeof value !== "string") return;
639
+ const normalized = normalizeOptionalString(value);
640
+ return normalized && SLACK_THREAD_TS_PATTERN.test(normalized) ? normalized : void 0;
641
+ }
642
+ function resolveSlackThreadTsValue(params) {
643
+ return normalizeSlackThreadTsCandidate(params.replyToId) ?? normalizeSlackThreadTsCandidate(params.threadId);
644
+ }
645
+ //#endregion
646
+ export { isSlackExecApprovalClientEnabled as A, isSlackAnyNativeApprovalClientEnabled as C, isSlackApprovalAuthorizedSender as D, getSlackApprovalApprovers as E, resolveSlackExecApprovalTarget as M, shouldSuppressLocalSlackExecApprovalPrompt as N, getSlackExecApprovalApprovers as O, SLACK_REPLY_SELECT_ACTION_ID as S, shouldHandleSlackNativeApprovalRequest as T, buildSlackInteractiveBlocks as _, parseSlackBlocksInput as a, truncateSlackText as b, resolveSlackGroupRequireMention as c, normalizeAllowList as d, normalizeAllowListLower as f, resolveSlackUserAllowed as g, resolveSlackAllowListMatch as h, SLACK_MAX_BLOCKS as i, normalizeSlackApproverId as j, isSlackExecApprovalAuthorizedSender as k, resolveSlackGroupToolPolicy as l, normalizeSlackSlug as m, resolveSlackThreadTsValue as n, validateSlackBlocksArray as o, normalizeSlackAllowOwnerEntry as p, resolveSlackReplyBlocks as r, SLACK_TEXT_LIMIT as s, normalizeSlackThreadTsCandidate as t, allowListMatches as u, buildSlackPresentationBlocks as v, resolveSlackApprovalKind as w, SLACK_REPLY_BUTTON_ACTION_ID as x, resolveSlackInteractiveBlockOffsets as y };
@@ -98,6 +98,9 @@ class Range {
98
98
  }
99
99
 
100
100
  parseRange (range) {
101
+ // strip build metadata so it can't bleed into the version
102
+ range = range.replace(BUILDSTRIPRE, '')
103
+
101
104
  // memoize range parsing for performance.
102
105
  // this is a very hot path, and fully deterministic.
103
106
  const memoOpts =
@@ -223,6 +226,7 @@ const debug = require('../internal/debug')
223
226
  const SemVer = require('./semver')
224
227
  const {
225
228
  safeRe: re,
229
+ src,
226
230
  t,
227
231
  comparatorTrimReplace,
228
232
  tildeTrimReplace,
@@ -230,6 +234,9 @@ const {
230
234
  } = require('../internal/re')
231
235
  const { FLAG_INCLUDE_PRERELEASE, FLAG_LOOSE } = require('../internal/constants')
232
236
 
237
+ // unbounded global build-metadata stripper used by parseRange
238
+ const BUILDSTRIPRE = new RegExp(src[t.BUILD], 'g')
239
+
233
240
  const isNullSet = c => c.value === '<0.0.0-0'
234
241
  const isAny = c => c.value === ''
235
242
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "semver",
3
- "version": "7.8.0",
3
+ "version": "7.8.1",
4
4
  "description": "The semantic version parser used by npm.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -174,7 +174,7 @@ const simpleSubset = (sub, dom, options) => {
174
174
  if (higher === c && higher !== gt) {
175
175
  return false
176
176
  }
177
- } else if (gt.operator === '>=' && !satisfies(gt.semver, String(c), options)) {
177
+ } else if (gt.operator === '>=' && !c.test(gt.semver)) {
178
178
  return false
179
179
  }
180
180
  }
@@ -192,7 +192,7 @@ const simpleSubset = (sub, dom, options) => {
192
192
  if (lower === c && lower !== lt) {
193
193
  return false
194
194
  }
195
- } else if (lt.operator === '<=' && !satisfies(lt.semver, String(c), options)) {
195
+ } else if (lt.operator === '<=' && !c.test(lt.semver)) {
196
196
  return false
197
197
  }
198
198
  }