@openclaw/slack 2026.7.2-beta.7 → 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.
- package/dist/{account-inspect-DEKpg9Ip.js → account-inspect-YJvFBbCR.js} +1 -1
- package/dist/account-inspect-api.js +1 -1
- package/dist/{accounts-CHAeNZOX.js → accounts-BlzxuYle.js} +7 -3
- package/dist/{accounts.runtime-BHD4Ma2R.js → accounts.runtime-CbabBL8x.js} +1 -1
- package/dist/{action-runtime-DfuYoMjG.js → action-runtime-D6jg2CQd.js} +193 -125
- package/dist/action-runtime.runtime-JtoOK9l5.js +2 -0
- package/dist/{actions-D3NuJvva.js → actions-DFk0ANVB.js} +116 -235
- package/dist/actions.runtime-CYLsYRai.js +2 -0
- package/dist/api.js +17 -17
- package/dist/{approval-handler.runtime-BA05P0QT.js → approval-handler.runtime-BNvAoKdK.js} +53 -14
- package/dist/{channel-B9fVdW3s.js → channel-CA5w7qDF.js} +209 -110
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-type-DXyos1d2.js → channel-type-CZWv55Wu.js} +9 -12
- package/dist/{config-adapter-CxBQH8fq.js → channel.setup-CpyYsEXH.js} +83 -25
- package/dist/{config-schema-SgZT6nXV.js → config-schema-CN3XZRX5.js} +27 -17
- package/dist/conversation-binding-route-DFVLUdYF.js +115 -0
- package/dist/{directory-config-CnCIAktf.js → directory-config-BGYyuzWh.js} +3 -3
- package/dist/directory-contract-api.js +1 -1
- package/dist/{directory-live-DKunWh3A.js → directory-live-DjUJQLbq.js} +13 -22
- package/dist/{doctor-contract-CsGH1Dfc.js → doctor-contract-BAy7-EUQ.js} +30 -3
- package/dist/doctor-contract-api.js +1 -1
- package/dist/{group-policy-NQZti9t-.js → group-policy-DyfB_ZIE.js} +282 -183
- package/dist/index.js +4 -1
- package/dist/{message-tool-api-DkhFpMoy.js → message-tool-api-CqMr5Rmc.js} +14 -3
- package/dist/message-tool-api.js +1 -1
- package/dist/{monitor-CmKz0wtI.js → monitor-Chrecrb9.js} +3 -3
- package/dist/{outbound-adapter-BkuMp2Vs.js → outbound-adapter-DuRqAQXK.js} +35 -23
- package/dist/{pipeline.runtime-DgtmuYCP.js → pipeline.runtime-Bbfd5VFW.js} +1386 -929
- package/dist/{policy-PRysPn23.js → policy-BKXSxrIS.js} +18 -14
- package/dist/{probe-CgDsSops.js → probe-BVA65leh.js} +38 -18
- package/dist/{provider-DmRizMZt.js → provider-CUUiwsg2.js} +3454 -2601
- package/dist/{relay-source-Blxj8xb4.js → relay-source-mhpMMRG-.js} +11 -21
- package/dist/{replies-4s_Vq_z9.js → replies-SnWyXcsL.js} +84 -27
- package/dist/{resolve-channels-yEqmM-3I.js → resolve-channels-BSpqC8jU.js} +39 -12
- package/dist/{resolve-users-BOrt5K-5.js → resolve-users-Dvz9pDe0.js} +28 -5
- package/dist/{runtime-api-QMb-Q5Ko.js → runtime-api-DBi7xc_g.js} +3 -3
- package/dist/runtime-api.js +11 -11
- package/dist/{scopes-BJSrkAp6.js → scopes-BSk4GZvZ.js} +1 -1
- package/dist/security-contract-api.js +1 -1
- package/dist/{send-DsLeZpST.js → send-CtnOxKCc.js} +249 -163
- package/dist/{send.runtime-gUdK6V3h.js → send.runtime-kYctMHSd.js} +1 -1
- package/dist/setup-entry.js +1 -4
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-BeNzrMrJ.js → setup-surface-BPFfp6So.js} +6 -6
- package/dist/{shared-DgIN3Dcr.js → shared-DJBaslN7.js} +45 -45
- package/dist/{block-text-DkHaoGem.js → slack-client-kind-BXyOOICI.js} +17 -2
- package/dist/{slash-dispatch.runtime-zPkyl7dB.js → slash-dispatch.runtime-Cf2FTrnf.js} +2 -2
- package/dist/{streaming-compat-3_X-21wW.js → streaming-compat-B-e0mqM0.js} +3 -8
- package/dist/{target-parsing-N6lHogYZ.js → target-parsing-BnMD2ZqZ.js} +40 -2
- package/dist/{targets-KmjP2E8s.js → targets-Cx5W_n3W.js} +1 -1
- package/node_modules/@slack/bolt/node_modules/@types/node/README.md +1 -1
- package/node_modules/@slack/bolt/node_modules/@types/node/crypto.d.ts +1 -1
- package/node_modules/@slack/bolt/node_modules/@types/node/package.json +2 -2
- package/node_modules/@slack/socket-mode/node_modules/@types/node/README.md +1 -1
- package/node_modules/@slack/socket-mode/node_modules/@types/node/crypto.d.ts +1 -1
- package/node_modules/@slack/socket-mode/node_modules/@types/node/package.json +2 -2
- package/node_modules/@slack/web-api/node_modules/@types/node/README.md +1 -1
- package/node_modules/@slack/web-api/node_modules/@types/node/crypto.d.ts +1 -1
- package/node_modules/@slack/web-api/node_modules/@types/node/package.json +2 -2
- package/node_modules/undici/lib/cache/memory-cache-store.js +54 -9
- package/node_modules/undici/lib/cache/sqlite-cache-store.js +7 -1
- package/node_modules/undici/lib/core/request.js +12 -1
- package/node_modules/undici/lib/dispatcher/client-h1.js +11 -2
- package/node_modules/undici/lib/handler/cache-handler.js +246 -64
- package/node_modules/undici/lib/handler/cache-revalidation-handler.js +3 -3
- package/node_modules/undici/lib/handler/retry-handler.js +24 -0
- package/node_modules/undici/lib/interceptor/cache.js +159 -52
- package/node_modules/undici/lib/util/cache.js +324 -62
- package/node_modules/undici/lib/util/date.js +23 -6
- package/node_modules/undici/lib/web/cookies/util.js +79 -9
- package/node_modules/undici/package.json +1 -1
- package/openclaw.plugin.json +280 -33
- package/package.json +9 -11
- package/skills/slack/SKILL.md +10 -68
- package/dist/account-reply-mode-DrUXogvO.js +0 -14
- package/dist/action-runtime.runtime-DQErZYpz.js +0 -2
- package/dist/actions.runtime-BIRU_G4M.js +0 -2
- package/dist/channel.setup-CLP5oTvh.js +0 -56
- package/dist/preflight-audio.runtime-D5Bgags0.js +0 -3
- package/dist/slash-plugin-commands.runtime-Dosfcx3X.js +0 -2
- package/node_modules/p-map/index.d.ts +0 -155
- package/node_modules/p-map/index.js +0 -285
- package/node_modules/p-map/license +0 -9
- package/node_modules/p-map/package.json +0 -57
- package/node_modules/p-map/readme.md +0 -190
- package/dist/{security-audit-DR097212.js → security-audit-B_yKr7MW.js} +1 -1
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
import { a as resolveSlackAccount, i as resolveDefaultSlackAccountId, n as listSlackAccountIds, o as resolveSlackAccountAllowFrom, r as mergeSlackAccountConfig } from "./accounts-
|
|
2
|
-
import {
|
|
1
|
+
import { a as resolveSlackAccount, i as resolveDefaultSlackAccountId, n as listSlackAccountIds, o as resolveSlackAccountAllowFrom, r as mergeSlackAccountConfig } from "./accounts-BlzxuYle.js";
|
|
2
|
+
import { a as parseSlackTarget, n as formatSlackTarget, t as canonicalizeSlackApiTargetId } from "./target-parsing-BnMD2ZqZ.js";
|
|
3
|
+
import { t as slackContextTargetsMatch } from "./targets-Cx5W_n3W.js";
|
|
3
4
|
import { t as isSlackPluginAccountConfigured } from "./account-configured-BwfXBo_F.js";
|
|
4
5
|
import { normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
|
|
5
|
-
import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringifiedOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
6
|
+
import { asOptionalRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringifiedOptionalString, readNonBlankString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
6
7
|
import { normalizeMessageChannel } from "openclaw/plugin-sdk/routing";
|
|
7
8
|
import { FormatCapabilityProfile, chunkTextForOutbound, markdownToIR, renderMarkdownIRChunksWithinLimit, renderMarkdownWithMarkers } from "openclaw/plugin-sdk/text-chunking";
|
|
8
|
-
import {
|
|
9
|
+
import { isSingleUseReplyToMode } from "openclaw/plugin-sdk/reply-reference";
|
|
10
|
+
import { buildChannelKeyCandidates } from "openclaw/plugin-sdk/channel-targets";
|
|
11
|
+
import { createNativeApprovalChannelRouteGates, doesApprovalRequestSelectChannelAccount, resolveApprovalKind, resolveApprovalRequestSessionConversation } from "openclaw/plugin-sdk/approval-native-runtime";
|
|
9
12
|
import { createChannelApprovalAuth, resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";
|
|
10
13
|
import { createChannelExecApprovalProfile, isChannelExecApprovalClientEnabledFromConfig, isChannelExecApprovalTargetRecipient, matchesApprovalRequestFilters } from "openclaw/plugin-sdk/approval-client-runtime";
|
|
11
14
|
import { channelRouteTargetsMatchExact, stringifyRouteThreadId } from "openclaw/plugin-sdk/channel-route";
|
|
15
|
+
import { resolveGlobalMap } from "openclaw/plugin-sdk/global-singleton";
|
|
12
16
|
import { normalizeMessagePresentation, reduceLegacyInteractiveReply, renderMessagePresentationChartFallbackText, renderMessagePresentationFallbackText, renderMessagePresentationTableFallbackText, resolveMessagePresentationButtonAction, resolveMessagePresentationOptionAction } from "openclaw/plugin-sdk/interactive-runtime";
|
|
13
17
|
import { parseExecApprovalCommandText } from "openclaw/plugin-sdk/approval-reply-runtime";
|
|
14
18
|
import { buildApprovalResolutionRef } from "openclaw/plugin-sdk/approval-reference-runtime";
|
|
@@ -17,8 +21,23 @@ import { sliceUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
|
17
21
|
import { eastAsianWidthType } from "get-east-asian-width";
|
|
18
22
|
import { readResponseTextLimited } from "openclaw/plugin-sdk/provider-http";
|
|
19
23
|
import { compileAllowlist, resolveCompiledAllowlistMatch } from "openclaw/plugin-sdk/allow-from";
|
|
20
|
-
import { normalizeHyphenSlug, normalizeStringEntries as normalizeStringEntries$1, normalizeStringEntriesLower
|
|
24
|
+
import { normalizeHyphenSlug, normalizeStringEntries as normalizeStringEntries$1, normalizeStringEntriesLower } from "openclaw/plugin-sdk/string-normalization-runtime";
|
|
21
25
|
import { resolveScopeRequireMention, resolveScopeToolsPolicy } from "openclaw/plugin-sdk/channel-policy";
|
|
26
|
+
//#region extensions/slack/src/action-threading.ts
|
|
27
|
+
const SLACK_PRIVATE_ACTION_DELIVERY_RESULT = Symbol("slack.action.delivery-result");
|
|
28
|
+
function resolveSlackAutoThreadId(params) {
|
|
29
|
+
const context = params.toolContext;
|
|
30
|
+
if (!context?.currentChannelId && !context?.currentMessagingTarget) return;
|
|
31
|
+
if (!slackContextTargetsMatch(params.to, context)) return;
|
|
32
|
+
if (!context.currentThreadTs) {
|
|
33
|
+
if (context.sameChannelThreadRequired) throw new Error("Slack thread context is required for same-channel replies from a threaded Slack turn. Set topLevel=true or threadId=null to post at the channel root.");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (context.replyToMode !== "all" && !isSingleUseReplyToMode(context.replyToMode ?? "off")) return;
|
|
37
|
+
if (isSingleUseReplyToMode(context.replyToMode ?? "off") && context.hasRepliedRef?.value) return;
|
|
38
|
+
return context.currentThreadTs;
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
22
41
|
//#region extensions/slack/src/exec-approvals.ts
|
|
23
42
|
function normalizeSlackUserLikeId(value) {
|
|
24
43
|
const upper = value.toUpperCase();
|
|
@@ -60,13 +79,7 @@ const slackExecApprovalProfile = createChannelExecApprovalProfile({
|
|
|
60
79
|
resolveConfig: (params) => resolveSlackAccount(params).config.execApprovals,
|
|
61
80
|
resolveApprovers: getSlackExecApprovalApprovers,
|
|
62
81
|
normalizeSenderId: normalizeSlackApproverId,
|
|
63
|
-
isTargetRecipient: isSlackExecApprovalTargetRecipient
|
|
64
|
-
matchesRequestAccount: (params) => doesApprovalRequestMatchChannelAccount({
|
|
65
|
-
cfg: params.cfg,
|
|
66
|
-
request: params.request,
|
|
67
|
-
channel: "slack",
|
|
68
|
-
accountId: params.accountId
|
|
69
|
-
})
|
|
82
|
+
isTargetRecipient: isSlackExecApprovalTargetRecipient
|
|
70
83
|
});
|
|
71
84
|
const isSlackExecApprovalClientEnabled = slackExecApprovalProfile.isClientEnabled;
|
|
72
85
|
const isSlackExecApprovalAuthorizedSender = slackExecApprovalProfile.isAuthorizedSender;
|
|
@@ -96,18 +109,40 @@ const slackApproval = createChannelApprovalAuth({
|
|
|
96
109
|
const getSlackApprovalApprovers = slackApproval.resolveApprovers;
|
|
97
110
|
const isSlackApprovalAuthorizedSender = slackApproval.isAuthorizedSender;
|
|
98
111
|
//#endregion
|
|
112
|
+
//#region extensions/slack/src/installation-identity-state.ts
|
|
113
|
+
const slackInstallationStates = resolveGlobalMap(Symbol.for("openclaw.slack.installation-identities"), "close-and-restart");
|
|
114
|
+
function registerSlackInstallationState(accountId, kind) {
|
|
115
|
+
const normalizedAccountId = normalizeAccountId(accountId);
|
|
116
|
+
const owner = Symbol(`slack-installation:${normalizedAccountId}`);
|
|
117
|
+
slackInstallationStates.set(normalizedAccountId, {
|
|
118
|
+
kind,
|
|
119
|
+
owner
|
|
120
|
+
});
|
|
121
|
+
return {
|
|
122
|
+
update: (nextKind) => {
|
|
123
|
+
if (slackInstallationStates.get(normalizedAccountId)?.owner === owner) slackInstallationStates.set(normalizedAccountId, {
|
|
124
|
+
kind: nextKind,
|
|
125
|
+
owner
|
|
126
|
+
});
|
|
127
|
+
},
|
|
128
|
+
release: () => {
|
|
129
|
+
if (slackInstallationStates.get(normalizedAccountId)?.owner === owner) slackInstallationStates.delete(normalizedAccountId);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function getSlackInstallationKind(accountId) {
|
|
134
|
+
return slackInstallationStates.get(normalizeAccountId(accountId))?.kind;
|
|
135
|
+
}
|
|
136
|
+
function isSlackWorkspaceInstallation(accountId) {
|
|
137
|
+
return getSlackInstallationKind(accountId) === "workspace";
|
|
138
|
+
}
|
|
139
|
+
//#endregion
|
|
99
140
|
//#region extensions/slack/src/approval-native-gates.ts
|
|
100
141
|
const DEFAULT_APPROVAL_FORWARDING_MODE = "session";
|
|
101
142
|
const SLACK_DM_CHANNEL_ID_RE = /^D[A-Z0-9]{8,}$/i;
|
|
102
143
|
const SLACK_USER_ID_RE = /^[UW][A-Z0-9]{8,}$/i;
|
|
103
|
-
function resolveSlackApprovalKind(request) {
|
|
104
|
-
const isExec = "command" in request.request;
|
|
105
|
-
if (isExec === ("title" in request.request && "description" in request.request)) throw new Error("Slack approval request payload does not identify exactly one owner");
|
|
106
|
-
return isExec ? "exec" : "plugin";
|
|
107
|
-
}
|
|
108
144
|
function isSlackApprovalTransportEnabled(params) {
|
|
109
|
-
|
|
110
|
-
return account.config.enterpriseOrgInstall !== true && isSlackPluginAccountConfigured(account);
|
|
145
|
+
return isSlackPluginAccountConfigured(resolveSlackAccount(params));
|
|
111
146
|
}
|
|
112
147
|
function resolveSlackNativeApprovalConfig(params) {
|
|
113
148
|
return resolveSlackAccount(params).config.execApprovals;
|
|
@@ -140,7 +175,10 @@ function resolveTurnSourceSlackOriginTarget(request) {
|
|
|
140
175
|
}) });
|
|
141
176
|
if (!parsed) return null;
|
|
142
177
|
return {
|
|
143
|
-
to:
|
|
178
|
+
to: formatSlackTarget({
|
|
179
|
+
...parsed,
|
|
180
|
+
explicitKind: true
|
|
181
|
+
}),
|
|
144
182
|
threadId: stringifyRouteThreadId(request.request.turnSourceThreadId)
|
|
145
183
|
};
|
|
146
184
|
}
|
|
@@ -160,7 +198,11 @@ function resolveSlackFallbackOriginTarget(request) {
|
|
|
160
198
|
const parsed = parseSlackTarget(sessionTarget.id, { defaultKind: "channel" });
|
|
161
199
|
if (!parsed) return null;
|
|
162
200
|
return {
|
|
163
|
-
to:
|
|
201
|
+
to: formatSlackTarget({
|
|
202
|
+
...parsed,
|
|
203
|
+
id: canonicalizeSlackApiTargetId(parsed.kind, parsed.id),
|
|
204
|
+
explicitKind: true
|
|
205
|
+
}),
|
|
164
206
|
threadId: sessionTarget.threadId
|
|
165
207
|
};
|
|
166
208
|
}
|
|
@@ -177,6 +219,7 @@ function isSlackDmChannelToUserRoutePair(a, b) {
|
|
|
177
219
|
const left = parseComparableSlackTarget(a);
|
|
178
220
|
const right = parseComparableSlackTarget(b);
|
|
179
221
|
if (!left || !right) return false;
|
|
222
|
+
if (left.teamId?.toLowerCase() !== right.teamId?.toLowerCase()) return false;
|
|
180
223
|
return left.kind === "channel" && SLACK_DM_CHANNEL_ID_RE.test(left.id) && right.kind === "user" || right.kind === "channel" && SLACK_DM_CHANNEL_ID_RE.test(right.id) && left.kind === "user";
|
|
181
224
|
}
|
|
182
225
|
function slackTargetsMatch(a, b) {
|
|
@@ -201,7 +244,10 @@ function normalizeSlackForwardTarget(target) {
|
|
|
201
244
|
const parsed = parseSlackTarget(to, { defaultKind: SLACK_USER_ID_RE.test(to) ? "user" : "channel" });
|
|
202
245
|
if (!parsed) return null;
|
|
203
246
|
return {
|
|
204
|
-
to:
|
|
247
|
+
to: formatSlackTarget({
|
|
248
|
+
...parsed,
|
|
249
|
+
explicitKind: true
|
|
250
|
+
}),
|
|
205
251
|
accountId: normalizeOptionalString(target.accountId),
|
|
206
252
|
threadId: stringifyRouteThreadId(target.threadId)
|
|
207
253
|
};
|
|
@@ -235,21 +281,18 @@ function isSlackPluginNativeApprovalClientEnabled(params) {
|
|
|
235
281
|
return isSlackPluginNativeApprovalClientConfigEnabled(params) || isSlackPluginForwardingRoutePotentiallyEnabled(params);
|
|
236
282
|
}
|
|
237
283
|
function shouldHandleSlackPluginViaNativeClientConfig(params) {
|
|
238
|
-
if (!
|
|
239
|
-
|
|
240
|
-
request: params.request,
|
|
284
|
+
if (!doesApprovalRequestSelectChannelAccount({
|
|
285
|
+
...params,
|
|
241
286
|
channel: "slack",
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
approverCount: getSlackApprovalApprovers(params).length
|
|
287
|
+
defaultAccountId: resolveDefaultSlackAccountId(params.cfg),
|
|
288
|
+
eligibleAccountIds: listSlackNativeApprovalEligibleAccountIds({
|
|
289
|
+
...params,
|
|
290
|
+
approvalKind: "plugin"
|
|
291
|
+
})
|
|
248
292
|
})) return false;
|
|
249
|
-
return
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
sessionFilter: config?.sessionFilter
|
|
293
|
+
return isSlackNativeApprovalAccountEligible({
|
|
294
|
+
...params,
|
|
295
|
+
approvalKind: "plugin"
|
|
253
296
|
});
|
|
254
297
|
}
|
|
255
298
|
function matchesSlackNativeApprovalFilters(params) {
|
|
@@ -259,6 +302,25 @@ function matchesSlackNativeApprovalFilters(params) {
|
|
|
259
302
|
sessionFilter: params.sessionFilter
|
|
260
303
|
});
|
|
261
304
|
}
|
|
305
|
+
function isSlackNativeApprovalAccountEligible(params) {
|
|
306
|
+
const config = resolveSlackNativeApprovalConfig(params);
|
|
307
|
+
const approverCount = params.approvalKind === "exec" ? getSlackExecApprovalApprovers(params).length : getSlackApprovalApprovers(params).length;
|
|
308
|
+
return isSlackApprovalTransportEnabled(params) && isChannelExecApprovalClientEnabledFromConfig({
|
|
309
|
+
enabled: config?.enabled,
|
|
310
|
+
approverCount
|
|
311
|
+
}) && matchesSlackNativeApprovalFilters({
|
|
312
|
+
request: params.request,
|
|
313
|
+
agentFilter: config?.agentFilter,
|
|
314
|
+
sessionFilter: config?.sessionFilter
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
function listSlackNativeApprovalEligibleAccountIds(params) {
|
|
318
|
+
const accountId = params.accountId ?? resolveDefaultSlackAccountId(params.cfg);
|
|
319
|
+
return isSlackNativeApprovalAccountEligible({
|
|
320
|
+
...params,
|
|
321
|
+
accountId
|
|
322
|
+
}) ? [accountId] : [];
|
|
323
|
+
}
|
|
262
324
|
function isAnyForwardedSlackExplicitTargetEligible(params) {
|
|
263
325
|
return (resolvePluginApprovalForwardingConfig(params.cfg)?.targets ?? []).some((target) => isForwardedSlackExplicitTargetEligible({
|
|
264
326
|
...params,
|
|
@@ -292,24 +354,32 @@ function isSlackAnyNativeApprovalClientEnabled(params) {
|
|
|
292
354
|
});
|
|
293
355
|
}
|
|
294
356
|
function shouldHandleSlackNativeApprovalRequest(params) {
|
|
295
|
-
if ((
|
|
296
|
-
if (
|
|
297
|
-
|
|
298
|
-
|
|
357
|
+
if (getSlackInstallationKind(resolveSlackAccount(params).accountId) === "enterprise" && !resolveEnterpriseApprovalTeamId(params.request)) return false;
|
|
358
|
+
if (resolveApprovalKind(params.request, params.approvalKind) === "plugin") return shouldHandleSlackPluginViaNativeClientConfig(params) || shouldHandleSlackPluginViaForwarding(params);
|
|
359
|
+
const turnSourceChannel = normalizeMessageChannel(params.request.request.turnSourceChannel);
|
|
360
|
+
if (turnSourceChannel && turnSourceChannel !== "slack") return false;
|
|
361
|
+
if (!doesApprovalRequestSelectChannelAccount({
|
|
362
|
+
...params,
|
|
299
363
|
channel: "slack",
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
approverCount: getSlackExecApprovalApprovers(params).length
|
|
364
|
+
defaultAccountId: resolveDefaultSlackAccountId(params.cfg),
|
|
365
|
+
eligibleAccountIds: listSlackNativeApprovalEligibleAccountIds({
|
|
366
|
+
...params,
|
|
367
|
+
approvalKind: "exec"
|
|
368
|
+
})
|
|
306
369
|
})) return false;
|
|
307
|
-
return
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
sessionFilter: config?.sessionFilter
|
|
370
|
+
return isSlackNativeApprovalAccountEligible({
|
|
371
|
+
...params,
|
|
372
|
+
approvalKind: "exec"
|
|
311
373
|
});
|
|
312
374
|
}
|
|
375
|
+
function resolveEnterpriseApprovalTeamId(request) {
|
|
376
|
+
try {
|
|
377
|
+
const target = resolveTurnSourceSlackOriginTarget(request);
|
|
378
|
+
return target ? parseSlackTarget(target.to)?.teamId : void 0;
|
|
379
|
+
} catch {
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
313
383
|
//#endregion
|
|
314
384
|
//#region extensions/slack/src/blocks-input.ts
|
|
315
385
|
const SLACK_MAX_BLOCKS = 50;
|
|
@@ -368,6 +438,7 @@ const SLACK_PRESENTATION_CAPABILITIES = {
|
|
|
368
438
|
//#endregion
|
|
369
439
|
//#region extensions/slack/src/approval-actions.ts
|
|
370
440
|
const SLACK_APPROVAL_VALUE_PREFIX = "openclaw:approval:v1:";
|
|
441
|
+
const SLACK_APPROVAL_HEADER_BLOCK_ID = "openclaw_approval_header";
|
|
371
442
|
function isApprovalDecision(value) {
|
|
372
443
|
return value === "allow-once" || value === "allow-always" || value === "deny";
|
|
373
444
|
}
|
|
@@ -500,42 +571,36 @@ function renderSlackMessagePresentationFallbackText(params) {
|
|
|
500
571
|
//#region extensions/slack/src/data-table.ts
|
|
501
572
|
const SLACK_DATA_TABLE_COLUMNS_MAX = 20;
|
|
502
573
|
const SLACK_DATA_TABLE_ROWS_MAX = 100;
|
|
503
|
-
function asRecord$3(value) {
|
|
504
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
505
|
-
}
|
|
506
|
-
function readNonEmptyString$1(value) {
|
|
507
|
-
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
508
|
-
}
|
|
509
574
|
function countCharacters(value) {
|
|
510
575
|
return Array.from(value).length;
|
|
511
576
|
}
|
|
512
577
|
function readRichTextLeaf(record) {
|
|
513
578
|
if (record.type === "text" && typeof record.text === "string") return record.text;
|
|
514
|
-
const text =
|
|
579
|
+
const text = readNonBlankString(record.text);
|
|
515
580
|
if (text) return text;
|
|
516
581
|
switch (record.type) {
|
|
517
|
-
case "link": return
|
|
582
|
+
case "link": return readNonBlankString(record.url) ?? "";
|
|
518
583
|
case "user": {
|
|
519
|
-
const userId =
|
|
584
|
+
const userId = readNonBlankString(record.user_id);
|
|
520
585
|
return userId ? `<@${userId}>` : "";
|
|
521
586
|
}
|
|
522
587
|
case "channel": {
|
|
523
|
-
const channelId =
|
|
588
|
+
const channelId = readNonBlankString(record.channel_id);
|
|
524
589
|
return channelId ? `<#${channelId}>` : "";
|
|
525
590
|
}
|
|
526
591
|
case "usergroup": {
|
|
527
|
-
const usergroupId =
|
|
592
|
+
const usergroupId = readNonBlankString(record.usergroup_id);
|
|
528
593
|
return usergroupId ? `<!subteam^${usergroupId}>` : "";
|
|
529
594
|
}
|
|
530
595
|
case "broadcast": {
|
|
531
|
-
const range =
|
|
596
|
+
const range = readNonBlankString(record.range);
|
|
532
597
|
return range ? `<!${range}>` : "";
|
|
533
598
|
}
|
|
534
599
|
case "emoji": {
|
|
535
|
-
const name =
|
|
600
|
+
const name = readNonBlankString(record.name);
|
|
536
601
|
return name ? `:${name}:` : "";
|
|
537
602
|
}
|
|
538
|
-
case "date": return
|
|
603
|
+
case "date": return readNonBlankString(record.fallback) ?? "";
|
|
539
604
|
default: return "";
|
|
540
605
|
}
|
|
541
606
|
}
|
|
@@ -543,7 +608,7 @@ function readRichTextElements(value, separator = "") {
|
|
|
543
608
|
if (!Array.isArray(value)) return "";
|
|
544
609
|
const parts = [];
|
|
545
610
|
for (const rawElement of value) {
|
|
546
|
-
const element =
|
|
611
|
+
const element = asOptionalRecord(rawElement);
|
|
547
612
|
if (!element) continue;
|
|
548
613
|
if (Array.isArray(element.elements)) {
|
|
549
614
|
const rendered = readRichTextElements(element.elements, element.type === "rich_text_list" ? "\n" : "");
|
|
@@ -556,7 +621,7 @@ function readRichTextElements(value, separator = "") {
|
|
|
556
621
|
return parts.join(separator);
|
|
557
622
|
}
|
|
558
623
|
function readSlackBasicTableCell(value) {
|
|
559
|
-
const cell =
|
|
624
|
+
const cell = asOptionalRecord(value);
|
|
560
625
|
if (!cell) return "";
|
|
561
626
|
if (cell.type === "raw_text") return typeof cell.text === "string" ? cell.text : "";
|
|
562
627
|
if (cell.type === "raw_number") {
|
|
@@ -567,7 +632,7 @@ function readSlackBasicTableCell(value) {
|
|
|
567
632
|
return cell.type === "rich_text" ? readRichTextElements(cell.elements, "\n") : "";
|
|
568
633
|
}
|
|
569
634
|
function parseSlackBasicTableRows(value) {
|
|
570
|
-
const block =
|
|
635
|
+
const block = asOptionalRecord(value);
|
|
571
636
|
if (block?.type !== "table" || !Array.isArray(block.rows)) return;
|
|
572
637
|
if (block.rows.length < 1 || block.rows.length > SLACK_DATA_TABLE_ROWS_MAX) return;
|
|
573
638
|
let characterCount = 0;
|
|
@@ -582,15 +647,15 @@ function parseSlackBasicTableRows(value) {
|
|
|
582
647
|
return rows.some((row) => row.some((cell) => cell.length > 0)) ? rows : void 0;
|
|
583
648
|
}
|
|
584
649
|
function readSlackDataTableCell(value, allowRichText) {
|
|
585
|
-
const cell =
|
|
650
|
+
const cell = asOptionalRecord(value);
|
|
586
651
|
if (!cell) return;
|
|
587
|
-
if (cell.type === "raw_text") return
|
|
588
|
-
if (cell.type === "raw_number") return typeof cell.value === "number" && Number.isFinite(cell.value) ?
|
|
589
|
-
if (allowRichText && cell.type === "rich_text") return
|
|
652
|
+
if (cell.type === "raw_text") return readNonBlankString(cell.text);
|
|
653
|
+
if (cell.type === "raw_number") return typeof cell.value === "number" && Number.isFinite(cell.value) ? readNonBlankString(cell.text) : void 0;
|
|
654
|
+
if (allowRichText && cell.type === "rich_text") return readNonBlankString(readRichTextElements(cell.elements));
|
|
590
655
|
}
|
|
591
656
|
function parseSlackDataTable(value, options = {}) {
|
|
592
|
-
const block =
|
|
593
|
-
const caption =
|
|
657
|
+
const block = asOptionalRecord(value);
|
|
658
|
+
const caption = readNonBlankString(block?.caption);
|
|
594
659
|
if (block?.type !== "data_table" || !caption || !Array.isArray(block.rows)) return;
|
|
595
660
|
if (block.rows.length < 2) return;
|
|
596
661
|
const rawHeader = block.rows[0];
|
|
@@ -614,7 +679,7 @@ function parseSlackDataTable(value, options = {}) {
|
|
|
614
679
|
}
|
|
615
680
|
/** Detect current native table blocks without depending on unreleased Slack SDK types. */
|
|
616
681
|
function hasSlackDataTableBlock(blocks) {
|
|
617
|
-
return blocks?.some((block) =>
|
|
682
|
+
return blocks?.some((block) => asOptionalRecord(block)?.type === "data_table") ?? false;
|
|
618
683
|
}
|
|
619
684
|
function countSlackDataTableCellCharacters(value) {
|
|
620
685
|
return parseSlackDataTable(value, { enforceNativeLimits: true })?.cellCharacterCount;
|
|
@@ -678,7 +743,7 @@ function buildSlackDataTableBlock(block, options = {}) {
|
|
|
678
743
|
}
|
|
679
744
|
/** Extract a deterministic accessible summary from a native Slack table block. */
|
|
680
745
|
function renderSlackDataTableFallbackText(value) {
|
|
681
|
-
const block =
|
|
746
|
+
const block = asOptionalRecord(value);
|
|
682
747
|
if (block?.type !== "data_table") return;
|
|
683
748
|
const parsed = parseSlackDataTable(block);
|
|
684
749
|
if (parsed) return renderMessagePresentationTableFallbackText({
|
|
@@ -687,7 +752,7 @@ function renderSlackDataTableFallbackText(value) {
|
|
|
687
752
|
headers: parsed.headers,
|
|
688
753
|
rows: parsed.rows
|
|
689
754
|
});
|
|
690
|
-
return
|
|
755
|
+
return readNonBlankString(block.caption)?.trim();
|
|
691
756
|
}
|
|
692
757
|
function escapeCompactFallbackCell(value) {
|
|
693
758
|
return value.replaceAll("\\", "\\\\").replaceAll(" ", "\\t").replaceAll("\r", "\\r").replaceAll("\n", "\\n");
|
|
@@ -708,10 +773,10 @@ function renderSlackTableMrkdwnFallbackText(value) {
|
|
|
708
773
|
}
|
|
709
774
|
/** Render each native table cell once for bounded, formatting-disabled delivery. */
|
|
710
775
|
function renderSlackDataTableCompactPlainTextFallback(value) {
|
|
711
|
-
const block =
|
|
776
|
+
const block = asOptionalRecord(value);
|
|
712
777
|
if (block?.type !== "data_table") return;
|
|
713
778
|
const parsed = parseSlackDataTable(block);
|
|
714
|
-
if (!parsed) return
|
|
779
|
+
if (!parsed) return readNonBlankString(block.caption)?.trim();
|
|
715
780
|
return [
|
|
716
781
|
`${escapeCompactFallbackCell(parsed.caption)} (table)`,
|
|
717
782
|
parsed.headers.map(escapeCompactFallbackCell).join(" "),
|
|
@@ -720,7 +785,7 @@ function renderSlackDataTableCompactPlainTextFallback(value) {
|
|
|
720
785
|
}
|
|
721
786
|
/** Render a native table as mrkdwn without activating raw cell control tokens. */
|
|
722
787
|
function renderSlackDataTableMrkdwnFallbackText(value) {
|
|
723
|
-
const block =
|
|
788
|
+
const block = asOptionalRecord(value);
|
|
724
789
|
if (block?.type !== "data_table") return;
|
|
725
790
|
const parsed = parseSlackDataTable(block);
|
|
726
791
|
if (parsed) return renderSlackMessagePresentationTableFallbackText({
|
|
@@ -729,7 +794,7 @@ function renderSlackDataTableMrkdwnFallbackText(value) {
|
|
|
729
794
|
headers: parsed.headers,
|
|
730
795
|
rows: parsed.rows
|
|
731
796
|
});
|
|
732
|
-
const caption =
|
|
797
|
+
const caption = readNonBlankString(block.caption)?.trim();
|
|
733
798
|
return caption ? escapeSlackMrkdwn(caption) : void 0;
|
|
734
799
|
}
|
|
735
800
|
//#endregion
|
|
@@ -739,12 +804,9 @@ const SLACK_CHART_LABEL_MAX = 20;
|
|
|
739
804
|
const SLACK_CHART_AXIS_LABEL_MAX = 50;
|
|
740
805
|
const SLACK_CHART_SERIES_MAX = 12;
|
|
741
806
|
const SLACK_CHART_DATA_POINTS_MAX = 20;
|
|
742
|
-
function asRecord$2(value) {
|
|
743
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
744
|
-
}
|
|
745
807
|
/** Detect native chart blocks without depending on unreleased Slack SDK types. */
|
|
746
808
|
function hasSlackDataVisualizationBlock(blocks) {
|
|
747
|
-
return blocks?.some((block) =>
|
|
809
|
+
return blocks?.some((block) => asOptionalRecord(block)?.type === "data_visualization") ?? false;
|
|
748
810
|
}
|
|
749
811
|
function isStringWithin(value, maxLength) {
|
|
750
812
|
return typeof value === "string" && value.trim().length > 0 && Array.from(value).length <= maxLength;
|
|
@@ -791,7 +853,7 @@ function buildSlackDataVisualizationBlock(block) {
|
|
|
791
853
|
};
|
|
792
854
|
}
|
|
793
855
|
function readSlackChartDatum(value) {
|
|
794
|
-
const record =
|
|
856
|
+
const record = asOptionalRecord(value);
|
|
795
857
|
const label = record?.label;
|
|
796
858
|
const datumValue = record?.value;
|
|
797
859
|
return typeof label === "string" && typeof datumValue === "number" ? {
|
|
@@ -800,9 +862,9 @@ function readSlackChartDatum(value) {
|
|
|
800
862
|
} : void 0;
|
|
801
863
|
}
|
|
802
864
|
function parseSlackDataVisualizationBlock(value) {
|
|
803
|
-
const block =
|
|
865
|
+
const block = asOptionalRecord(value);
|
|
804
866
|
const title = block?.title;
|
|
805
|
-
const chart =
|
|
867
|
+
const chart = asOptionalRecord(block?.chart);
|
|
806
868
|
if (block?.type !== "data_visualization" || typeof title !== "string" || !chart) return;
|
|
807
869
|
if (chart.type === "pie") {
|
|
808
870
|
if (!Array.isArray(chart.segments)) return;
|
|
@@ -817,12 +879,12 @@ function parseSlackDataVisualizationBlock(value) {
|
|
|
817
879
|
return normalizedBlock?.type === "chart" ? normalizedBlock : void 0;
|
|
818
880
|
}
|
|
819
881
|
if (chart.type !== "bar" && chart.type !== "area" && chart.type !== "line") return;
|
|
820
|
-
const axisConfig =
|
|
882
|
+
const axisConfig = asOptionalRecord(chart.axis_config);
|
|
821
883
|
const categories = axisConfig?.categories;
|
|
822
884
|
if (!Array.isArray(categories) || !categories.every((category) => typeof category === "string")) return;
|
|
823
885
|
if (!Array.isArray(chart.series)) return;
|
|
824
886
|
const series = chart.series.map((rawSeries) => {
|
|
825
|
-
const seriesRecord =
|
|
887
|
+
const seriesRecord = asOptionalRecord(rawSeries);
|
|
826
888
|
if (typeof seriesRecord?.name !== "string" || !Array.isArray(seriesRecord.data)) return;
|
|
827
889
|
const data = seriesRecord.data.map(readSlackChartDatum);
|
|
828
890
|
if (data.some((datum) => !datum) || data.length !== categories.length) return;
|
|
@@ -847,7 +909,7 @@ function parseSlackDataVisualizationBlock(value) {
|
|
|
847
909
|
}
|
|
848
910
|
/** Extract a deterministic accessible summary from a native Slack chart block. */
|
|
849
911
|
function renderSlackDataVisualizationFallbackText(value) {
|
|
850
|
-
const block =
|
|
912
|
+
const block = asOptionalRecord(value);
|
|
851
913
|
if (block?.type !== "data_visualization") return;
|
|
852
914
|
const parsed = parseSlackDataVisualizationBlock(block);
|
|
853
915
|
if (parsed) return renderMessagePresentationChartFallbackText(parsed);
|
|
@@ -855,7 +917,7 @@ function renderSlackDataVisualizationFallbackText(value) {
|
|
|
855
917
|
}
|
|
856
918
|
/** Render a native chart as mrkdwn without activating raw data control tokens. */
|
|
857
919
|
function renderSlackDataVisualizationMrkdwnFallbackText(value) {
|
|
858
|
-
const block =
|
|
920
|
+
const block = asOptionalRecord(value);
|
|
859
921
|
if (block?.type !== "data_visualization") return;
|
|
860
922
|
const parsed = parseSlackDataVisualizationBlock(block);
|
|
861
923
|
if (parsed) return renderSlackMessagePresentationChartFallbackText(parsed);
|
|
@@ -898,15 +960,24 @@ async function resolveSlackQuestionAction(params) {
|
|
|
898
960
|
//#region extensions/slack/src/reply-action-ids.ts
|
|
899
961
|
const SLACK_REPLY_BUTTON_ACTION_ID = "openclaw:reply_button";
|
|
900
962
|
const SLACK_REPLY_LINK_ACTION_ID = "openclaw:reply_link";
|
|
963
|
+
const SLACK_SESSION_LINK_ACTION_ID = "openclaw:session_link";
|
|
901
964
|
const SLACK_REPLY_SELECT_ACTION_ID = "openclaw:reply_select";
|
|
902
965
|
const SLACK_CALLBACK_BUTTON_ACTION_ID = "openclaw:callback_button";
|
|
903
966
|
const SLACK_CALLBACK_SELECT_ACTION_ID = "openclaw:callback_select";
|
|
904
967
|
const SLACK_APPROVAL_BUTTON_ACTION_ID = "openclaw:approval_button";
|
|
905
968
|
const SLACK_APPROVAL_SELECT_ACTION_ID = "openclaw:approval_select";
|
|
906
969
|
const SLACK_QUESTION_BUTTON_ACTION_ID = "openclaw:question_button";
|
|
970
|
+
const SLACK_QUESTION_FINALIZATION_BLOCKS = Symbol("slackQuestionFinalizationBlocks");
|
|
907
971
|
function isSlackQuestionActionId(actionId) {
|
|
908
972
|
return actionId === "openclaw:question_button" || actionId.startsWith(`openclaw:question_button:`);
|
|
909
973
|
}
|
|
974
|
+
/** Read only question control identities from the blocks actually sent to Slack. */
|
|
975
|
+
function resolveSlackQuestionActionIds(blocks) {
|
|
976
|
+
return (blocks ?? []).flatMap((block) => {
|
|
977
|
+
if (block.type !== "actions") return [];
|
|
978
|
+
return (block.elements ?? []).flatMap(({ action_id }) => action_id && isSlackQuestionActionId(action_id) ? [action_id] : []);
|
|
979
|
+
});
|
|
980
|
+
}
|
|
910
981
|
function isSlackApprovalActionId(actionId) {
|
|
911
982
|
return actionId === "openclaw:approval_button" || actionId === "openclaw:approval_select" || actionId.startsWith(`openclaw:approval_button:`) || actionId.startsWith(`openclaw:approval_select:`);
|
|
912
983
|
}
|
|
@@ -1351,6 +1422,7 @@ function buildSlackPresentationSelectBlock(block, selectIndex) {
|
|
|
1351
1422
|
//#endregion
|
|
1352
1423
|
//#region extensions/slack/src/limits.ts
|
|
1353
1424
|
const SLACK_TEXT_LIMIT = 8e3;
|
|
1425
|
+
const SLACK_MESSAGE_TEXT_RECOMMENDED_LIMIT = 4e3;
|
|
1354
1426
|
const SLACK_EDIT_TEXT_MAX_BYTES = 4e3;
|
|
1355
1427
|
const SLACK_MESSAGE_TEXT_HARD_LIMIT = 4e4;
|
|
1356
1428
|
//#endregion
|
|
@@ -1394,54 +1466,46 @@ const SLACK_SELECT_ELEMENT_TYPES = /* @__PURE__ */ new Set([
|
|
|
1394
1466
|
"channels_select",
|
|
1395
1467
|
"multi_channels_select"
|
|
1396
1468
|
]);
|
|
1397
|
-
function asRecord$1(value) {
|
|
1398
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
1399
|
-
}
|
|
1400
|
-
function readNonEmptyString(value) {
|
|
1401
|
-
if (typeof value !== "string") return;
|
|
1402
|
-
const trimmed = value.trim();
|
|
1403
|
-
return trimmed.length > 0 ? trimmed : void 0;
|
|
1404
|
-
}
|
|
1405
1469
|
function readTextObject(value, options = {}) {
|
|
1406
|
-
const record =
|
|
1470
|
+
const record = asOptionalRecord(value);
|
|
1407
1471
|
if (!record) return;
|
|
1408
|
-
const text =
|
|
1472
|
+
const text = normalizeOptionalString(record?.text);
|
|
1409
1473
|
if (!text) return;
|
|
1410
1474
|
return record.type === "plain_text" && options.nativeDataFormat !== "plain" ? escapeSlackMrkdwn(text) : text;
|
|
1411
1475
|
}
|
|
1412
1476
|
function readTextValue(value, options = {}) {
|
|
1413
|
-
return
|
|
1477
|
+
return normalizeOptionalString(value) ?? readTextObject(value, options);
|
|
1414
1478
|
}
|
|
1415
1479
|
function renderSlackRichTextLeaf(element) {
|
|
1416
1480
|
switch (element.type) {
|
|
1417
1481
|
case "text": return typeof element.text === "string" ? escapeSlackMrkdwn(element.text) : "";
|
|
1418
|
-
case "link": return escapeSlackMrkdwn(
|
|
1482
|
+
case "link": return escapeSlackMrkdwn(normalizeOptionalString(element.text) ?? normalizeOptionalString(element.url) ?? "");
|
|
1419
1483
|
case "user": {
|
|
1420
|
-
const userId =
|
|
1484
|
+
const userId = normalizeOptionalString(element.user_id);
|
|
1421
1485
|
return userId ? escapeSlackMrkdwn(`<@${userId}>`) : "";
|
|
1422
1486
|
}
|
|
1423
1487
|
case "channel": {
|
|
1424
|
-
const channelId =
|
|
1488
|
+
const channelId = normalizeOptionalString(element.channel_id);
|
|
1425
1489
|
return channelId ? escapeSlackMrkdwn(`<#${channelId}>`) : "";
|
|
1426
1490
|
}
|
|
1427
1491
|
case "usergroup": {
|
|
1428
|
-
const usergroupId =
|
|
1492
|
+
const usergroupId = normalizeOptionalString(element.usergroup_id);
|
|
1429
1493
|
return usergroupId ? escapeSlackMrkdwn(`<!subteam^${usergroupId}>`) : "";
|
|
1430
1494
|
}
|
|
1431
1495
|
case "broadcast": {
|
|
1432
|
-
const range =
|
|
1496
|
+
const range = normalizeOptionalString(element.range);
|
|
1433
1497
|
return range ? escapeSlackMrkdwn(`<!${range}>`) : "";
|
|
1434
1498
|
}
|
|
1435
1499
|
case "emoji": {
|
|
1436
|
-
const name =
|
|
1500
|
+
const name = normalizeOptionalString(element.name);
|
|
1437
1501
|
return name ? `:${name}:` : "";
|
|
1438
1502
|
}
|
|
1439
|
-
case "date": return escapeSlackMrkdwn(
|
|
1503
|
+
case "date": return escapeSlackMrkdwn(normalizeOptionalString(element.fallback) ?? "");
|
|
1440
1504
|
default: return "";
|
|
1441
1505
|
}
|
|
1442
1506
|
}
|
|
1443
1507
|
function renderSlackRichTextElement(value) {
|
|
1444
|
-
const element =
|
|
1508
|
+
const element = asOptionalRecord(value);
|
|
1445
1509
|
if (!element) return "";
|
|
1446
1510
|
switch (element.type) {
|
|
1447
1511
|
case "rich_text_section":
|
|
@@ -1456,25 +1520,25 @@ function renderSlackRichTextElements(value, separator) {
|
|
|
1456
1520
|
return value.map(renderSlackRichTextElement).filter(Boolean).join(separator);
|
|
1457
1521
|
}
|
|
1458
1522
|
function readImageText(block) {
|
|
1459
|
-
const altText =
|
|
1523
|
+
const altText = normalizeOptionalString(block.alt_text);
|
|
1460
1524
|
return (altText ? escapeSlackMrkdwn(altText) : void 0) ?? readTextObject(block.title);
|
|
1461
1525
|
}
|
|
1462
1526
|
function readVideoText(block, options = {}) {
|
|
1463
|
-
const altText =
|
|
1527
|
+
const altText = normalizeOptionalString(block.alt_text);
|
|
1464
1528
|
return readTextObject(block.title, options) ?? (altText ? escapeSlackMrkdwn(altText) : void 0);
|
|
1465
1529
|
}
|
|
1466
1530
|
function readContextText(block, options = {}) {
|
|
1467
1531
|
if (!Array.isArray(block.elements)) return;
|
|
1468
1532
|
const parts = block.elements.map((element) => {
|
|
1469
|
-
const record =
|
|
1470
|
-
const altText =
|
|
1533
|
+
const record = asOptionalRecord(element);
|
|
1534
|
+
const altText = normalizeOptionalString(record?.alt_text);
|
|
1471
1535
|
return readTextObject(record, options) ?? (altText ? escapeSlackMrkdwn(altText) : void 0);
|
|
1472
1536
|
}).filter((part) => Boolean(part));
|
|
1473
1537
|
return parts.length > 0 ? parts.join(" ") : void 0;
|
|
1474
1538
|
}
|
|
1475
1539
|
function readControlElementText(value, options = {}) {
|
|
1476
|
-
const element =
|
|
1477
|
-
const type =
|
|
1540
|
+
const element = asOptionalRecord(value);
|
|
1541
|
+
const type = normalizeOptionalString(element?.type);
|
|
1478
1542
|
if (type === "button" || type === "workflow_button") return readTextValue(element?.text, options);
|
|
1479
1543
|
if (type && SLACK_SELECT_ELEMENT_TYPES.has(type)) return readTextObject(element?.placeholder, options);
|
|
1480
1544
|
}
|
|
@@ -1501,10 +1565,10 @@ function readActionsText(block, options = {}) {
|
|
|
1501
1565
|
}
|
|
1502
1566
|
/** Read only user-visible text from one Slack block. */
|
|
1503
1567
|
function renderSlackBlockFallbackText(raw, options = {}) {
|
|
1504
|
-
const block =
|
|
1568
|
+
const block = asOptionalRecord(raw);
|
|
1505
1569
|
if (!block) return;
|
|
1506
1570
|
switch (block.type) {
|
|
1507
|
-
case "rich_text": return
|
|
1571
|
+
case "rich_text": return normalizeOptionalString(renderSlackRichTextElements(block.elements, "\n"));
|
|
1508
1572
|
case "header": return readTextObject(block.text, options);
|
|
1509
1573
|
case "section": return readSectionText(block, options);
|
|
1510
1574
|
case "image": return readImageText(block) ?? "Shared an image";
|
|
@@ -1773,19 +1837,6 @@ function protectSlackAssistantTranscriptRoleHeaders(text) {
|
|
|
1773
1837
|
if (!slackProjectionHasRoleHeader(tokenProjection) && !slackProjectionHasRoleHeader(fallbackProjection)) return text;
|
|
1774
1838
|
return `${SLACK_ASSISTANT_TRANSCRIPT_PREFIX}${text}`;
|
|
1775
1839
|
}
|
|
1776
|
-
function hardSliceSlackToken(token, limit) {
|
|
1777
|
-
const chunks = [];
|
|
1778
|
-
let chunk = "";
|
|
1779
|
-
for (const character of token) {
|
|
1780
|
-
if (chunk && chunk.length + character.length > limit) {
|
|
1781
|
-
chunks.push(chunk);
|
|
1782
|
-
chunk = "";
|
|
1783
|
-
}
|
|
1784
|
-
chunk += character;
|
|
1785
|
-
}
|
|
1786
|
-
if (chunk) chunks.push(chunk);
|
|
1787
|
-
return chunks;
|
|
1788
|
-
}
|
|
1789
1840
|
function buildSlackRenderOptions() {
|
|
1790
1841
|
return {
|
|
1791
1842
|
annotationMarkers: { assistant_transcript_role: {
|
|
@@ -1859,8 +1910,8 @@ function chunkSlackMrkdwnText(text, limit) {
|
|
|
1859
1910
|
flush();
|
|
1860
1911
|
const marker = wrapper();
|
|
1861
1912
|
if (activeMarker && isAllowedSlackAngleToken(token)) {
|
|
1862
|
-
if (marker) chunks.push(...
|
|
1863
|
-
else chunks.push(...
|
|
1913
|
+
if (marker) chunks.push(...chunkTextForOutbound(token, Math.max(1, Math.floor(contentLimit)), { preserveWhitespace: true }).map((fragment) => `${marker}${fragment}${marker}`));
|
|
1914
|
+
else chunks.push(...chunkTextForOutbound(escapeSlackMrkdwnSegment(token), Math.max(1, Math.floor(limit)), { preserveWhitespace: true }));
|
|
1864
1915
|
continue;
|
|
1865
1916
|
}
|
|
1866
1917
|
chunks.push(...token.length <= limit ? [token] : chunkTextForOutbound(token, limit));
|
|
@@ -1894,9 +1945,6 @@ function markdownToSlackMrkdwnChunks(markdown, limit, options = {}) {
|
|
|
1894
1945
|
const SLACK_MALFORMED_NATIVE_DATA_FALLBACK = "Slack could not render this chart or table data.";
|
|
1895
1946
|
const SLACK_RESPONSE_URL_BODY_LIMIT_BYTES = 16 * 1024;
|
|
1896
1947
|
const SLACK_RESPONSE_URL_BODY_TIMEOUT_MS = 3e4;
|
|
1897
|
-
function asRecord(value) {
|
|
1898
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
1899
|
-
}
|
|
1900
1948
|
/** Detect a native Slack chart or table block. */
|
|
1901
1949
|
function hasSlackNativeDataBlock(blocks) {
|
|
1902
1950
|
return hasSlackDataVisualizationBlock(blocks) || hasSlackDataTableBlock(blocks);
|
|
@@ -1904,23 +1952,23 @@ function hasSlackNativeDataBlock(blocks) {
|
|
|
1904
1952
|
/** Keep every sibling block while removing Slack's native data blocks. */
|
|
1905
1953
|
function stripSlackNativeDataBlocks(blocks) {
|
|
1906
1954
|
return (blocks ?? []).filter((block) => {
|
|
1907
|
-
const type =
|
|
1955
|
+
const type = asOptionalRecord(block)?.type;
|
|
1908
1956
|
return type !== "data_table" && type !== "data_visualization";
|
|
1909
1957
|
});
|
|
1910
1958
|
}
|
|
1911
1959
|
/** Match Slack's Web API and response_url `invalid_blocks` error shapes. */
|
|
1912
1960
|
function isSlackInvalidBlocksError(error) {
|
|
1913
|
-
const record =
|
|
1961
|
+
const record = asOptionalRecord(error);
|
|
1914
1962
|
const rawData = record?.data;
|
|
1915
|
-
const data =
|
|
1916
|
-
const rawResponseData =
|
|
1917
|
-
const responseData =
|
|
1963
|
+
const data = asOptionalRecord(rawData);
|
|
1964
|
+
const rawResponseData = asOptionalRecord(record?.response)?.data;
|
|
1965
|
+
const responseData = asOptionalRecord(rawResponseData);
|
|
1918
1966
|
const code = data?.error ?? (typeof rawData === "string" ? rawData : void 0) ?? responseData?.error ?? (typeof rawResponseData === "string" ? rawResponseData : void 0) ?? record?.error;
|
|
1919
1967
|
return typeof code === "string" && code.trim().toLowerCase() === "invalid_blocks";
|
|
1920
1968
|
}
|
|
1921
1969
|
function isSlackResponseLike(value) {
|
|
1922
|
-
const record =
|
|
1923
|
-
const body =
|
|
1970
|
+
const record = asOptionalRecord(value);
|
|
1971
|
+
const body = asOptionalRecord(record?.body);
|
|
1924
1972
|
return typeof record?.status === "number" && (typeof record.arrayBuffer === "function" || typeof body?.getReader === "function");
|
|
1925
1973
|
}
|
|
1926
1974
|
/** Consume Bolt 5's native response_url body under strict time and byte bounds. */
|
|
@@ -1937,12 +1985,12 @@ async function isSlackInvalidBlocksResponse(response) {
|
|
|
1937
1985
|
/** Bolt 5 omits the response body from RespondError; 400 is contextual here. */
|
|
1938
1986
|
function isSlackNativeResponseUrlRejection(error) {
|
|
1939
1987
|
if (isSlackInvalidBlocksError(error)) return true;
|
|
1940
|
-
const record =
|
|
1988
|
+
const record = asOptionalRecord(error);
|
|
1941
1989
|
return record?.code === "slack_bolt_respond_error" && record.statusCode === 400;
|
|
1942
1990
|
}
|
|
1943
1991
|
/** Extract a complete accessible summary from a supported native data block. */
|
|
1944
1992
|
function renderSlackNativeDataFallbackText(value) {
|
|
1945
|
-
const type =
|
|
1993
|
+
const type = asOptionalRecord(value)?.type;
|
|
1946
1994
|
if (type === "data_visualization") return renderSlackDataVisualizationMrkdwnFallbackText(value);
|
|
1947
1995
|
if (type === "data_table") return renderSlackDataTableMrkdwnFallbackText(value);
|
|
1948
1996
|
}
|
|
@@ -1984,7 +2032,7 @@ function appendSlackNativeDataFallback(text, blocks, render) {
|
|
|
1984
2032
|
return [base, ...dataTexts].filter(Boolean).join("\n\n");
|
|
1985
2033
|
}
|
|
1986
2034
|
function renderSlackNativeDataPlainTextBlock(value) {
|
|
1987
|
-
const type =
|
|
2035
|
+
const type = asOptionalRecord(value)?.type;
|
|
1988
2036
|
if (type === "data_table") return renderSlackDataTableCompactPlainTextFallback(value);
|
|
1989
2037
|
if (type === "data_visualization") return renderSlackDataVisualizationFallbackText(value);
|
|
1990
2038
|
}
|
|
@@ -2312,8 +2360,15 @@ function resolveSlackReplyBlocks(payload) {
|
|
|
2312
2360
|
return segments.length === 1 && segments[0]?.kind === "blocks" ? segments[0].blocks : void 0;
|
|
2313
2361
|
}
|
|
2314
2362
|
//#endregion
|
|
2363
|
+
//#region extensions/slack/src/detached-target-admission.ts
|
|
2364
|
+
function assertSlackDetachedTargetAllowed(accountId, teamId) {
|
|
2365
|
+
const installationKind = getSlackInstallationKind(accountId);
|
|
2366
|
+
if (installationKind && installationKind !== "workspace" && !teamId) throw new Error("unsupported_enterprise_slack_delivery: detached Slack operations require team:<team-id>:channel:<channel-id> or team:<team-id>:user:<user-id> until a workspace install is authenticated");
|
|
2367
|
+
}
|
|
2368
|
+
//#endregion
|
|
2315
2369
|
//#region extensions/slack/src/monitor/allow-list.ts
|
|
2316
2370
|
const SLACK_SLUG_CACHE_MAX = 512;
|
|
2371
|
+
const SLACK_STABLE_USER_ID_RE = /^[ubw][a-z0-9]+$/;
|
|
2317
2372
|
const slackSlugCache = /* @__PURE__ */ new Map();
|
|
2318
2373
|
function normalizeSlackSlug(raw) {
|
|
2319
2374
|
const key = raw ?? "";
|
|
@@ -2331,49 +2386,61 @@ function normalizeAllowList(list) {
|
|
|
2331
2386
|
return normalizeStringEntries$1(list);
|
|
2332
2387
|
}
|
|
2333
2388
|
function normalizeAllowListLower(list) {
|
|
2334
|
-
return normalizeStringEntriesLower
|
|
2389
|
+
return normalizeStringEntriesLower(list);
|
|
2335
2390
|
}
|
|
2336
2391
|
function normalizeSlackAllowOwnerEntry(entry) {
|
|
2337
2392
|
const trimmed = normalizeOptionalLowercaseString(entry);
|
|
2338
2393
|
if (!trimmed || trimmed === "*") return;
|
|
2394
|
+
try {
|
|
2395
|
+
const target = parseSlackTarget(trimmed);
|
|
2396
|
+
if (target?.kind === "user" && target.teamId) return target.id.toLowerCase();
|
|
2397
|
+
} catch {
|
|
2398
|
+
return;
|
|
2399
|
+
}
|
|
2339
2400
|
const withoutPrefix = trimmed.replace(/^(slack:|user:)/, "");
|
|
2340
|
-
return
|
|
2401
|
+
return SLACK_STABLE_USER_ID_RE.test(withoutPrefix) ? withoutPrefix : void 0;
|
|
2341
2402
|
}
|
|
2342
2403
|
function resolveSlackAllowListMatch(params) {
|
|
2343
2404
|
const compiledAllowList = compileAllowlist(params.allowList);
|
|
2405
|
+
const teamId = normalizeOptionalLowercaseString(params.teamId);
|
|
2344
2406
|
const id = normalizeOptionalLowercaseString(params.id);
|
|
2345
2407
|
const name = normalizeOptionalLowercaseString(params.name);
|
|
2346
2408
|
const slug = normalizeSlackSlug(name);
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2409
|
+
const scopedCandidates = [{
|
|
2410
|
+
value: teamId && id ? `team:${teamId}:user:${id}` : void 0,
|
|
2411
|
+
source: "workspace-id"
|
|
2412
|
+
}];
|
|
2413
|
+
const unscopedCandidates = [
|
|
2414
|
+
{
|
|
2415
|
+
value: id,
|
|
2416
|
+
source: "id"
|
|
2417
|
+
},
|
|
2418
|
+
{
|
|
2419
|
+
value: id ? `slack:${id}` : void 0,
|
|
2420
|
+
source: "prefixed-id"
|
|
2421
|
+
},
|
|
2422
|
+
{
|
|
2423
|
+
value: id ? `user:${id}` : void 0,
|
|
2424
|
+
source: "prefixed-user"
|
|
2425
|
+
},
|
|
2426
|
+
...params.allowNameMatching === true ? [
|
|
2350
2427
|
{
|
|
2351
|
-
value:
|
|
2352
|
-
source: "
|
|
2428
|
+
value: name,
|
|
2429
|
+
source: "name"
|
|
2353
2430
|
},
|
|
2354
2431
|
{
|
|
2355
|
-
value:
|
|
2356
|
-
source: "prefixed-
|
|
2432
|
+
value: name ? `slack:${name}` : void 0,
|
|
2433
|
+
source: "prefixed-name"
|
|
2357
2434
|
},
|
|
2358
2435
|
{
|
|
2359
|
-
value:
|
|
2360
|
-
source: "
|
|
2361
|
-
}
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
{
|
|
2368
|
-
value: name ? `slack:${name}` : void 0,
|
|
2369
|
-
source: "prefixed-name"
|
|
2370
|
-
},
|
|
2371
|
-
{
|
|
2372
|
-
value: slug,
|
|
2373
|
-
source: "slug"
|
|
2374
|
-
}
|
|
2375
|
-
] : []
|
|
2376
|
-
]
|
|
2436
|
+
value: slug,
|
|
2437
|
+
source: "slug"
|
|
2438
|
+
}
|
|
2439
|
+
] : []
|
|
2440
|
+
];
|
|
2441
|
+
return resolveCompiledAllowlistMatch({
|
|
2442
|
+
compiledAllowlist: compiledAllowList,
|
|
2443
|
+
candidates: [...scopedCandidates, ...unscopedCandidates]
|
|
2377
2444
|
});
|
|
2378
2445
|
}
|
|
2379
2446
|
function allowListMatches(params) {
|
|
@@ -2384,18 +2451,55 @@ function resolveSlackUserAllowed(params) {
|
|
|
2384
2451
|
if (allowList.length === 0) return true;
|
|
2385
2452
|
return allowListMatches({
|
|
2386
2453
|
allowList,
|
|
2454
|
+
teamId: params.teamId,
|
|
2387
2455
|
id: params.userId,
|
|
2388
2456
|
name: params.userName,
|
|
2389
2457
|
allowNameMatching: params.allowNameMatching
|
|
2390
2458
|
});
|
|
2391
2459
|
}
|
|
2460
|
+
function resolveSlackUserAllowListForTeam(params) {
|
|
2461
|
+
const allowList = normalizeAllowListLower(params.allowList);
|
|
2462
|
+
const teamId = normalizeOptionalLowercaseString(params.teamId);
|
|
2463
|
+
return allowList.flatMap((entry) => {
|
|
2464
|
+
if (entry === "*") return [entry];
|
|
2465
|
+
if (!entry.startsWith("team:")) return [entry];
|
|
2466
|
+
try {
|
|
2467
|
+
const target = parseSlackTarget(entry);
|
|
2468
|
+
if (target?.kind === "user" && target.teamId?.toLowerCase() === teamId) return [entry];
|
|
2469
|
+
return params.preserveUnmatchedScopedEntries ? [entry] : [];
|
|
2470
|
+
} catch {
|
|
2471
|
+
return params.preserveUnmatchedScopedEntries ? [entry] : [];
|
|
2472
|
+
}
|
|
2473
|
+
});
|
|
2474
|
+
}
|
|
2392
2475
|
//#endregion
|
|
2393
|
-
//#region extensions/slack/src/
|
|
2394
|
-
function
|
|
2395
|
-
|
|
2476
|
+
//#region extensions/slack/src/monitor/workspace-routing.ts
|
|
2477
|
+
function resolveSlackEnterpriseMainDmSessionKey(params) {
|
|
2478
|
+
const accountId = encodeURIComponent(params.accountId).toLowerCase();
|
|
2479
|
+
const teamId = encodeURIComponent(params.eventScope.teamId).toLowerCase();
|
|
2480
|
+
return `${params.baseSessionKey}:account:${accountId}:team:${teamId}`;
|
|
2481
|
+
}
|
|
2482
|
+
function qualifySlackRoutePeerId(params) {
|
|
2483
|
+
if (!params.eventScope) return params.id;
|
|
2484
|
+
return `team:${encodeURIComponent(params.eventScope.teamId)}:${params.kind}:${encodeURIComponent(params.id)}`;
|
|
2485
|
+
}
|
|
2486
|
+
function qualifySlackConversationId(conversationId, eventScope) {
|
|
2487
|
+
return eventScope ? `team:${encodeURIComponent(eventScope.teamId)}:${conversationId}` : conversationId;
|
|
2396
2488
|
}
|
|
2397
2489
|
//#endregion
|
|
2398
2490
|
//#region extensions/slack/src/group-policy.ts
|
|
2491
|
+
function buildSlackChannelIdCandidates(channelId, teamId, options) {
|
|
2492
|
+
const trimmedId = channelId?.trim();
|
|
2493
|
+
if (!trimmedId) return [];
|
|
2494
|
+
const lowercaseId = trimmedId.toLowerCase();
|
|
2495
|
+
const uppercaseId = trimmedId.toUpperCase();
|
|
2496
|
+
const exactTeamId = teamId || void 0;
|
|
2497
|
+
const lowercaseTeamId = exactTeamId?.toLowerCase();
|
|
2498
|
+
const uppercaseTeamId = exactTeamId?.toUpperCase();
|
|
2499
|
+
const scopedCandidates = buildChannelKeyCandidates(exactTeamId ? `team:${exactTeamId}:channel:${trimmedId}` : void 0, lowercaseTeamId ? `team:${lowercaseTeamId}:channel:${lowercaseId}` : void 0, uppercaseTeamId ? `team:${uppercaseTeamId}:channel:${uppercaseId}` : void 0);
|
|
2500
|
+
if (exactTeamId && options?.allowUnscoped !== true) return scopedCandidates;
|
|
2501
|
+
return buildChannelKeyCandidates(...scopedCandidates, trimmedId, lowercaseId, uppercaseId, `channel:${trimmedId}`, `channel:${lowercaseId}`, `channel:${uppercaseId}`);
|
|
2502
|
+
}
|
|
2399
2503
|
function buildSlackChannelPolicyScope(params) {
|
|
2400
2504
|
const channels = params.channels ?? {};
|
|
2401
2505
|
const tree = { scopes: channels };
|
|
@@ -2413,16 +2517,11 @@ function buildSlackChannelPolicyScope(params) {
|
|
|
2413
2517
|
function resolveSlackGroupPolicyScope(params) {
|
|
2414
2518
|
const accountId = normalizeAccountId(params.accountId ?? resolveDefaultSlackAccountId(params.cfg));
|
|
2415
2519
|
const channels = mergeSlackAccountConfig(params.cfg, accountId).channels;
|
|
2416
|
-
const channelId = params.groupId?.trim();
|
|
2417
2520
|
const channelName = params.groupChannel?.replace(/^#/, "");
|
|
2521
|
+
const allowUnscoped = getSlackInstallationKind(accountId) !== "enterprise";
|
|
2418
2522
|
return buildSlackChannelPolicyScope({
|
|
2419
2523
|
channels,
|
|
2420
|
-
candidates:
|
|
2421
|
-
channelId,
|
|
2422
|
-
channelName ? `#${channelName}` : void 0,
|
|
2423
|
-
channelName,
|
|
2424
|
-
normalizeHyphenSlug(channelName)
|
|
2425
|
-
].filter((candidate) => Boolean(candidate))
|
|
2524
|
+
candidates: buildChannelKeyCandidates(...buildSlackChannelIdCandidates(params.groupId, params.groupSpace, { allowUnscoped }), channelName ? `#${channelName}` : void 0, channelName, normalizeHyphenSlug(channelName))
|
|
2426
2525
|
});
|
|
2427
2526
|
}
|
|
2428
2527
|
function resolveSlackGroupRequireMention(params) {
|
|
@@ -2439,4 +2538,4 @@ function resolveSlackGroupToolPolicy(params) {
|
|
|
2439
2538
|
});
|
|
2440
2539
|
}
|
|
2441
2540
|
//#endregion
|
|
2442
|
-
export {
|
|
2541
|
+
export { SLACK_REPLY_SELECT_ACTION_ID as $, isSlackInvalidBlocksResponse as A, isSlackApprovalAuthorizedSender as At, SLACK_EDIT_TEXT_MAX_BYTES as B, SLACK_MALFORMED_NATIVE_DATA_FALLBACK as C, shouldHandleSlackNativeApprovalRequest as Ct, createSlackNativeDataBaseTextConsumer as D, isSlackWorkspaceInstallation as Dt, buildSlackNativeDataAccessibilityText as E, getSlackInstallationKind as Et, normalizeSlackOutboundText as F, resolveSlackExecApprovalTarget as Ft, buildSlackPresentationBlocks as G, SLACK_MESSAGE_TEXT_RECOMMENDED_LIMIT as H, buildSlackBlocksFallbackText as I, shouldSuppressLocalSlackExecApprovalPrompt as It, truncateSlackText as J, canRenderSlackPresentation as K, buildSlackCompleteBlocksFallbackText as L, SLACK_PRIVATE_ACTION_DELIVERY_RESULT as Lt, stripSlackNativeDataBlocks as M, isSlackExecApprovalAuthorizedSender as Mt, chunkSlackMrkdwnText as N, isSlackExecApprovalClientEnabled as Nt, hasSlackNativeDataBlock as O, registerSlackInstallationState as Ot, markdownToSlackMrkdwnChunks as P, normalizeSlackApproverId as Pt, SLACK_REPLY_LINK_ACTION_ID as Q, renderSlackBlockFallbackText as R, resolveSlackAutoThreadId as Rt, resolveSlackReplyRenderPlan as S, resolveTurnSourceSlackOriginTarget as St, appendSlackNativeDataPlainTextFallback as T, slackTargetsMatch as Tt, SLACK_TEXT_LIMIT as U, SLACK_MESSAGE_TEXT_HARD_LIMIT as V, buildSlackInteractiveBlocks as W, SLACK_QUESTION_FINALIZATION_BLOCKS as X, truncateSlackTextByUtf8Bytes as Y, SLACK_REPLY_BUTTON_ACTION_ID as Z, hasSlackReplyStructuredContent as _, normalizeSlackForwardTarget as _t, qualifySlackConversationId as a, decodeSlackQuestionAction as at, resolveSlackReplyBlocks as b, resolveSessionSlackOriginTarget as bt, allowListMatches as c, escapeSlackMrkdwn as ct, normalizeSlackAllowOwnerEntry as d, SLACK_PRESENTATION_CAPABILITIES as dt, SLACK_SESSION_LINK_ACTION_ID as et, normalizeSlackSlug as f, SLACK_MAX_BLOCKS as ft, assertSlackDetachedTargetAllowed as g, isSlackAnyNativeApprovalClientEnabled as gt, resolveSlackUserAllowed as h, hasSlackPluginApprovers as ht, resolveSlackGroupToolPolicy as i, resolveSlackQuestionActionIds as it, isSlackNativeResponseUrlRejection as j, getSlackExecApprovalApprovers as jt, isSlackInvalidBlocksError as k, getSlackApprovalApprovers as kt, normalizeAllowList as l, SLACK_APPROVAL_HEADER_BLOCK_ID as lt, resolveSlackUserAllowListForTeam as m, validateSlackBlocksArray as mt, buildSlackChannelPolicyScope as n, isSlackCallbackActionId as nt, qualifySlackRoutePeerId as o, resolveSlackQuestionAction as ot, resolveSlackAllowListMatch as p, parseSlackBlocksInput as pt, countSlackTextUtf8Bytes as q, resolveSlackGroupRequireMention as r, isSlackQuestionActionId as rt, resolveSlackEnterpriseMainDmSessionKey as s, renderSlackMessagePresentationFallbackText as st, buildSlackChannelIdCandidates as t, isSlackApprovalActionId as tt, normalizeAllowListLower as u, decodeSlackApprovalAction as ut, parseSlackReplyBlockSegments as v, normalizeSlackOriginTarget as vt, appendSlackNativeDataFallbackText as w, shouldHandleSlackPluginViaForwardingSession as wt, resolveSlackReplyDeliveryMessages as x, resolveSlackFallbackOriginTarget as xt, resolveSlackReplyBlockResolution as y, resolveEnterpriseApprovalTeamId as yt, resolveSlackAuthoredTextPlacement as z };
|