@openclaw/slack 2026.10.2 → 2026.10.5-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.
- package/dist/.setup/account-configured-zcR9TJJN.mjs +35 -0
- package/dist/.setup/{account-inspect-Cs-7DXXW.mjs → account-inspect-D58VVDjk.mjs} +15 -35
- package/dist/.setup/{accounts-CDgkV7Cm.mjs → accounts-BMg9YLIv.mjs} +44 -53
- package/dist/.setup/{action-runtime-DJ1daRAZ.mjs → action-runtime-BiRZNsIG.mjs} +20 -22
- package/dist/.setup/action-runtime.runtime-C5xceJoS.mjs +2 -0
- package/dist/.setup/{actions-DDoAJnrH.mjs → actions-KGKwTAKO.mjs} +34 -43
- package/dist/.setup/{approval-handler.runtime-BcE_shWc.mjs → approval-handler.runtime-DYrsG2Ox.mjs} +44 -70
- package/dist/.setup/{approval-message-updates-EgKGmFXx.mjs → approval-message-updates-CwdDew9i.mjs} +1 -1
- package/dist/.setup/{channel-DgKSu8Iv.mjs → channel-C7MY-Hhg.mjs} +138 -97
- package/dist/.setup/{channel-type-B9zYYzBU.mjs → channel-type-NjX2SwvS.mjs} +3 -3
- package/dist/.setup/{channel.setup-BYIlwbQ7.mjs → channel.setup-BFpQowO3.mjs} +7 -14
- package/dist/.setup/{directory-config-B_by7zrc.mjs → directory-config-BEDZPfDn.mjs} +1 -1
- package/dist/.setup/{directory-live-C48wazJt.mjs → directory-live-FipfeCwt.mjs} +33 -36
- package/dist/.setup/{message-tool-api-CcjLPN3v.mjs → message-tool-api-C7im5ETh.mjs} +2 -2
- package/dist/.setup/{monitor-BuYBDmm7.mjs → monitor-BnN2px0N.mjs} +609 -801
- package/dist/.setup/{outbound-adapter-BZFkK-mw.mjs → outbound-adapter-4HdGq-8r.mjs} +4 -4
- package/dist/.setup/{pipeline.runtime-CIepKmZt.mjs → pipeline.runtime-ByPbC6MN.mjs} +287 -365
- package/dist/.setup/{policy-KKTqEiDv.mjs → policy-BaY9_eh1.mjs} +2 -2
- package/dist/.setup/{probe-BVlJ3dp0.mjs → probe-CyX52GtD.mjs} +54 -61
- package/dist/.setup/{relay-source-CC3h6M7y.mjs → relay-source-CVfH-fBO.mjs} +28 -45
- package/dist/.setup/{replies-DHbuthIR.mjs → replies-WmfwvQxc.mjs} +38 -49
- package/dist/.setup/{reply-blocks-CKnO4BSG.mjs → reply-blocks-rqHQ_3pr.mjs} +87 -138
- package/dist/.setup/{resolve-channels-HR0TgArR.mjs → resolve-channels-B96cgprw.mjs} +17 -41
- package/dist/.setup/{resolve-users-BNYBhF0q.mjs → resolve-users-Xz9aPdns.mjs} +22 -58
- package/dist/.setup/{scopes-DrDbyUH2.mjs → scopes-aMcMHhXk.mjs} +1 -1
- package/dist/.setup/{send-CgPI3Zj8.mjs → send-CLmsR42r.mjs} +157 -284
- package/dist/.setup/{session-status-D46GHwOV.mjs → session-status-CcXe10zN.mjs} +181 -238
- package/dist/.setup/{setup-plugin-api-ZrHs0N4U.mjs → setup-plugin-api-D92P5p51.mjs} +1 -1
- package/dist/.setup/{setup-surface-83lxvE2y.mjs → setup-surface-368jx6Uc.mjs} +6 -6
- package/dist/.setup/{shared-VtmYNj-v.mjs → shared-CtprVh_G.mjs} +5 -5
- package/dist/.setup/{slash-dispatch.runtime-gBj_uaLM.mjs → slash-dispatch.runtime-Dzwj6TPI.mjs} +1 -1
- package/dist/account-inspect-api.js +1 -1
- package/dist/api.js +12 -12
- package/dist/channel-plugin-api.js +1 -1
- package/dist/configured-state.js +6 -13
- package/dist/directory-contract-api.js +1 -1
- package/dist/message-tool-api.js +1 -1
- package/dist/runtime-api.js +10 -10
- package/dist/setup-entry.js +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/node_modules/@slack/bolt/node_modules/@slack/socket-mode/dist/package.json +4 -4
- package/node_modules/@slack/bolt/node_modules/@slack/socket-mode/dist/src/SlackWebSocket.d.ts.map +1 -1
- package/node_modules/@slack/bolt/node_modules/@slack/socket-mode/dist/src/SlackWebSocket.js +9 -17
- package/node_modules/@slack/bolt/node_modules/@slack/socket-mode/dist/src/SlackWebSocket.js.map +1 -1
- package/node_modules/@slack/bolt/node_modules/@slack/socket-mode/package.json +4 -4
- package/node_modules/@slack/bolt/node_modules/@types/node/README.md +2 -2
- package/node_modules/@slack/bolt/node_modules/@types/node/crypto.d.ts +2 -2
- package/node_modules/@slack/bolt/node_modules/@types/node/dgram.d.ts +1 -1
- package/node_modules/@slack/bolt/node_modules/@types/node/package.json +2 -17
- package/node_modules/@slack/bolt/node_modules/@types/node/zlib.d.ts +6 -0
- package/node_modules/@slack/types/dist/block-kit/block-elements.d.ts +1 -1
- package/node_modules/@slack/types/dist/block-kit/block-elements.d.ts.map +1 -1
- package/node_modules/@slack/types/dist/block-kit/blocks.d.ts +79 -4
- package/node_modules/@slack/types/dist/block-kit/blocks.d.ts.map +1 -1
- package/node_modules/@slack/types/dist/block-kit/composition-objects.d.ts +17 -0
- package/node_modules/@slack/types/dist/block-kit/composition-objects.d.ts.map +1 -1
- package/node_modules/@slack/types/package.json +1 -1
- package/node_modules/@slack/web-api/dist/methods.d.ts +49 -2
- package/node_modules/@slack/web-api/dist/methods.d.ts.map +1 -1
- package/node_modules/@slack/web-api/dist/methods.js +47 -0
- package/node_modules/@slack/web-api/dist/methods.js.map +1 -1
- package/node_modules/@slack/web-api/dist/types/request/agents.d.ts +186 -0
- package/node_modules/@slack/web-api/dist/types/request/agents.d.ts.map +1 -1
- package/node_modules/@slack/web-api/dist/types/request/index.d.ts +1 -1
- package/node_modules/@slack/web-api/dist/types/request/index.d.ts.map +1 -1
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsArchiveResponse.d.ts +9 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsArchiveResponse.d.ts.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsArchiveResponse.js +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsArchiveResponse.js.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsCreateResponse.d.ts +10 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsCreateResponse.d.ts.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsCreateResponse.js +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsCreateResponse.js.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsGetCanvasResponse.d.ts +29 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsGetCanvasResponse.d.ts.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsGetCanvasResponse.js +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsGetCanvasResponse.js.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsListViewsResponse.d.ts +18 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsListViewsResponse.d.ts.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsListViewsResponse.js +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsListViewsResponse.js.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsRemoveViewResponse.d.ts +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsRemoveViewResponse.d.ts.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsRemoveViewResponse.js +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsRemoveViewResponse.js.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCanvasContentResponse.d.ts +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCanvasContentResponse.d.ts.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCanvasContentResponse.js +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCanvasContentResponse.js.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCommandsResponse.d.ts +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCommandsResponse.d.ts.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCommandsResponse.js +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCommandsResponse.js.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetPropertiesResponse.d.ts +10 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetPropertiesResponse.d.ts.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetPropertiesResponse.js +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetPropertiesResponse.js.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetViewResponse.d.ts +15 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetViewResponse.d.ts.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetViewResponse.js +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetViewResponse.js.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/ConversationsInfoResponse.d.ts +31 -0
- package/node_modules/@slack/web-api/dist/types/response/ConversationsInfoResponse.d.ts.map +1 -1
- package/node_modules/@slack/web-api/dist/types/response/index.d.ts +9 -0
- package/node_modules/@slack/web-api/dist/types/response/index.d.ts.map +1 -1
- package/node_modules/@slack/web-api/node_modules/@types/node/README.md +2 -2
- package/node_modules/@slack/web-api/node_modules/@types/node/crypto.d.ts +2 -2
- package/node_modules/@slack/web-api/node_modules/@types/node/dgram.d.ts +1 -1
- package/node_modules/@slack/web-api/node_modules/@types/node/package.json +2 -17
- package/node_modules/@slack/web-api/node_modules/@types/node/zlib.d.ts +6 -0
- package/node_modules/@slack/web-api/package.json +2 -2
- package/openclaw.plugin.json +0 -3
- package/package.json +6 -14
- package/dist/.setup/account-configured-sUohAxZr.mjs +0 -33
- package/dist/.setup/action-runtime.runtime-CdWL2mLC.mjs +0 -2
- package/dist/control-ui/2f4b1e827be6b68ced2ea0d8b7da8529a4eafbe72be27ee37e1064bdd530ec10/index.js +0 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as mergeSlackAccountConfig, c as resolveSlackAccountAllowFrom, i as listSlackAccountIds, o as resolveDefaultSlackAccountId, s as resolveSlackAccount } from "./accounts-
|
|
1
|
+
import { r as isSlackPluginAccountConfigured } from "./account-configured-zcR9TJJN.mjs";
|
|
2
|
+
import { a as mergeSlackAccountConfig, c as resolveSlackAccountAllowFrom, i as listSlackAccountIds, o as resolveDefaultSlackAccountId, s as resolveSlackAccount } from "./accounts-BMg9YLIv.mjs";
|
|
3
3
|
import { a as parseSlackTarget, n as formatSlackTarget, t as canonicalizeSlackApiTargetId } from "./target-parsing-FFE26kOV.mjs";
|
|
4
4
|
import { t as slackContextTargetsMatch } from "./targets-C6LZQL1Q.mjs";
|
|
5
|
-
import { A as
|
|
5
|
+
import { A as resolveSlackAllowListMatch, j as resolveSlackUserAllowListForTeam, o as formatSlackError } from "./probe-CyX52GtD.mjs";
|
|
6
6
|
import { normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
|
|
7
7
|
import { asOptionalRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeStringifiedOptionalString, readNonBlankString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
8
|
-
import { normalizeMessageChannel } from "openclaw/plugin-sdk/routing";
|
|
8
|
+
import { normalizeMessageChannel, resolveAgentRoute } from "openclaw/plugin-sdk/routing";
|
|
9
9
|
import { defaultRuntime, logVerbose, warn } from "openclaw/plugin-sdk/runtime-env";
|
|
10
10
|
import { FormatCapabilityProfile, chunkTextForOutbound, markdownToIR, renderMarkdownIRChunksWithinLimit, renderMarkdownWithMarkers } from "openclaw/plugin-sdk/text-chunking";
|
|
11
11
|
import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
@@ -83,34 +83,24 @@ function normalizeSlackApproverId(value) {
|
|
|
83
83
|
const target = normalizeSlackApproverTarget(value);
|
|
84
84
|
return target?.startsWith("team:") ? void 0 : target;
|
|
85
85
|
}
|
|
86
|
-
function resolveSlackOwnerApprovers(cfg) {
|
|
87
|
-
const ownerAllowFrom = cfg.commands?.ownerAllowFrom;
|
|
88
|
-
if (!Array.isArray(ownerAllowFrom) || ownerAllowFrom.length === 0) return [];
|
|
89
|
-
return resolveApprovalApprovers({
|
|
90
|
-
explicit: ownerAllowFrom,
|
|
91
|
-
normalizeApprover: normalizeSlackApproverId
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
86
|
function getSlackExecApprovalApprovers(params) {
|
|
95
87
|
const account = resolveSlackAccount(params).config;
|
|
88
|
+
const ownerAllowFrom = params.cfg.commands?.ownerAllowFrom;
|
|
96
89
|
return resolveApprovalApprovers({
|
|
97
|
-
explicit: account.execApprovals?.approvers ??
|
|
90
|
+
explicit: account.execApprovals?.approvers ?? (Array.isArray(ownerAllowFrom) ? ownerAllowFrom : []),
|
|
98
91
|
normalizeApprover: normalizeSlackApproverId
|
|
99
92
|
});
|
|
100
93
|
}
|
|
101
|
-
function isSlackExecApprovalTargetRecipient(params) {
|
|
102
|
-
return isChannelExecApprovalTargetRecipient({
|
|
103
|
-
...params,
|
|
104
|
-
channel: "slack",
|
|
105
|
-
normalizeSenderId: normalizeSlackApproverId,
|
|
106
|
-
matchTarget: ({ target, normalizedSenderId }) => normalizeSlackApproverId(target.to) === normalizedSenderId
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
94
|
const slackExecApprovalProfile = createChannelExecApprovalProfile({
|
|
110
95
|
resolveConfig: (params) => resolveSlackAccount(params).config.execApprovals,
|
|
111
96
|
resolveApprovers: getSlackExecApprovalApprovers,
|
|
112
97
|
normalizeSenderId: normalizeSlackApproverId,
|
|
113
|
-
isTargetRecipient:
|
|
98
|
+
isTargetRecipient: (params) => isChannelExecApprovalTargetRecipient({
|
|
99
|
+
...params,
|
|
100
|
+
channel: "slack",
|
|
101
|
+
normalizeSenderId: normalizeSlackApproverId,
|
|
102
|
+
matchTarget: ({ target, normalizedSenderId }) => normalizeSlackApproverId(target.to) === normalizedSenderId
|
|
103
|
+
})
|
|
114
104
|
});
|
|
115
105
|
const isSlackExecApprovalClientEnabled = slackExecApprovalProfile.isClientEnabled;
|
|
116
106
|
const isSlackExecApprovalAuthorizedSender = slackExecApprovalProfile.isAuthorizedSender;
|
|
@@ -250,25 +240,15 @@ function isSlackApprovalTransportEnabled(params) {
|
|
|
250
240
|
function normalizeSlackThreadMatchKey(threadId) {
|
|
251
241
|
return threadId == null ? "" : String(threadId).trim();
|
|
252
242
|
}
|
|
253
|
-
function
|
|
254
|
-
if (
|
|
255
|
-
|
|
256
|
-
const kind = normalizeLowercaseStringOrEmpty(match?.[1]);
|
|
257
|
-
return kind ? kind : null;
|
|
258
|
-
}
|
|
259
|
-
function resolveSlackTurnSourceDefaultKind(params) {
|
|
260
|
-
if (SLACK_DM_CHANNEL_ID_RE.test(params.turnSourceTo)) return "channel";
|
|
261
|
-
return params.sessionKind === "direct" ? "user" : "channel";
|
|
243
|
+
function resolveSlackTurnSourceDefaultKind(turnSourceTo, sessionKey) {
|
|
244
|
+
if (SLACK_DM_CHANNEL_ID_RE.test(turnSourceTo)) return "channel";
|
|
245
|
+
return sessionKey?.match(/slack:(direct|channel|group):/i)?.[1]?.toLowerCase() === "direct" ? "user" : "channel";
|
|
262
246
|
}
|
|
263
247
|
function resolveTurnSourceSlackOriginTarget(request) {
|
|
264
248
|
const turnSourceChannel = normalizeLowercaseStringOrEmpty(request.request.turnSourceChannel);
|
|
265
249
|
const turnSourceTo = normalizeOptionalString(request.request.turnSourceTo) ?? "";
|
|
266
250
|
if (turnSourceChannel !== "slack" || !turnSourceTo) return null;
|
|
267
|
-
const
|
|
268
|
-
const parsed = parseSlackTarget(turnSourceTo, { defaultKind: resolveSlackTurnSourceDefaultKind({
|
|
269
|
-
turnSourceTo,
|
|
270
|
-
sessionKind
|
|
271
|
-
}) });
|
|
251
|
+
const parsed = parseSlackTarget(turnSourceTo, { defaultKind: resolveSlackTurnSourceDefaultKind(turnSourceTo, request.request.sessionKey) });
|
|
272
252
|
if (!parsed) return null;
|
|
273
253
|
return {
|
|
274
254
|
to: formatSlackTarget({
|
|
@@ -538,33 +518,25 @@ function escapeSlackMrkdwn(value) {
|
|
|
538
518
|
//#endregion
|
|
539
519
|
//#region extensions/slack/src/presentation-fallback.ts
|
|
540
520
|
const SLACK_UNCOPYABLE_COMMAND_WARNING = "not copyable: contains backtick";
|
|
541
|
-
function resolveSlackCommandFallback(command) {
|
|
542
|
-
if (!command.includes("`")) return { command };
|
|
543
|
-
return {
|
|
544
|
-
command: command.replaceAll("`", "[backtick]"),
|
|
545
|
-
warning: SLACK_UNCOPYABLE_COMMAND_WARNING
|
|
546
|
-
};
|
|
547
|
-
}
|
|
548
521
|
function escapeSlackPresentationChartBlock(block) {
|
|
549
|
-
|
|
522
|
+
const escaped = {
|
|
550
523
|
...block,
|
|
551
|
-
title: escapeSlackMrkdwn(block.title)
|
|
552
|
-
segments: block.segments.map((segment) => ({
|
|
553
|
-
...segment,
|
|
554
|
-
label: escapeSlackMrkdwn(segment.label)
|
|
555
|
-
}))
|
|
524
|
+
title: escapeSlackMrkdwn(block.title)
|
|
556
525
|
};
|
|
557
|
-
|
|
558
|
-
...
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
526
|
+
if (escaped.chartType === "pie") escaped.segments = escaped.segments.map((segment) => ({
|
|
527
|
+
...segment,
|
|
528
|
+
label: escapeSlackMrkdwn(segment.label)
|
|
529
|
+
}));
|
|
530
|
+
else {
|
|
531
|
+
escaped.categories = escaped.categories.map(escapeSlackMrkdwn);
|
|
532
|
+
escaped.series = escaped.series.map((series) => ({
|
|
562
533
|
...series,
|
|
563
534
|
name: escapeSlackMrkdwn(series.name)
|
|
564
|
-
}))
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
}
|
|
535
|
+
}));
|
|
536
|
+
if (escaped.xLabel) escaped.xLabel = escapeSlackMrkdwn(escaped.xLabel);
|
|
537
|
+
if (escaped.yLabel) escaped.yLabel = escapeSlackMrkdwn(escaped.yLabel);
|
|
538
|
+
}
|
|
539
|
+
return escaped;
|
|
568
540
|
}
|
|
569
541
|
function escapeSlackPresentationTableBlock(block) {
|
|
570
542
|
return {
|
|
@@ -580,8 +552,8 @@ function escapeSlackPresentationFallbackBlock(block) {
|
|
|
580
552
|
if (block.type === "buttons") return {
|
|
581
553
|
...block,
|
|
582
554
|
buttons: block.buttons.map((button) => {
|
|
583
|
-
const
|
|
584
|
-
const label =
|
|
555
|
+
const commandAction = button.action?.type === "command" ? button.action : void 0;
|
|
556
|
+
const label = commandAction?.command.includes("`") ? `${button.label} [${SLACK_UNCOPYABLE_COMMAND_WARNING}]` : button.label;
|
|
585
557
|
return {
|
|
586
558
|
...button,
|
|
587
559
|
label: escapeSlackMrkdwn(label),
|
|
@@ -589,9 +561,9 @@ function escapeSlackPresentationFallbackBlock(block) {
|
|
|
589
561
|
...button.url ? { url: escapeSlackMrkdwn(button.url) } : {},
|
|
590
562
|
...button.webApp ? { webApp: { url: escapeSlackMrkdwn(button.webApp.url) } } : {},
|
|
591
563
|
...button.web_app ? { web_app: { url: escapeSlackMrkdwn(button.web_app.url) } } : {},
|
|
592
|
-
...
|
|
593
|
-
...
|
|
594
|
-
command:
|
|
564
|
+
...commandAction ? { action: {
|
|
565
|
+
...commandAction,
|
|
566
|
+
command: commandAction.command.replaceAll("`", "[backtick]")
|
|
595
567
|
} } : {}
|
|
596
568
|
};
|
|
597
569
|
})
|
|
@@ -646,13 +618,12 @@ function renderSlackRichText(value, mode, separator = "") {
|
|
|
646
618
|
const element = asOptionalRecord(rawElement);
|
|
647
619
|
if (!element) return "";
|
|
648
620
|
if (Array.isArray(element.elements) && (table || RICH_TEXT_CONTAINER_TYPES.has(element.type))) return renderSlackRichText(element.elements, mode, element.type === "rich_text_list" ? "\n" : "");
|
|
621
|
+
if (element.type === "text" && typeof element.text === "string") return literal(element.text);
|
|
649
622
|
if (table) {
|
|
650
|
-
if (element.type === "text" && typeof element.text === "string") return element.text;
|
|
651
623
|
const text = readNonBlankString(element.text);
|
|
652
624
|
if (text) return text;
|
|
653
625
|
}
|
|
654
626
|
switch (element.type) {
|
|
655
|
-
case "text": return typeof element.text === "string" ? literal(element.text) : "";
|
|
656
627
|
case "link": return literal(read(element.text) ?? read(element.url) ?? "");
|
|
657
628
|
case "user": return formatReference(element.user_id, "<@", ">");
|
|
658
629
|
case "channel": return formatReference(element.channel_id, "<#", ">");
|
|
@@ -675,16 +646,18 @@ const SLACK_DATA_TABLE_AGGREGATE_CELL_CHARACTERS_MAX = 1e4;
|
|
|
675
646
|
function countCharacters(value) {
|
|
676
647
|
return Array.from(value).length;
|
|
677
648
|
}
|
|
678
|
-
function
|
|
649
|
+
function readSlackTableCell(value, mode) {
|
|
679
650
|
const cell = asOptionalRecord(value);
|
|
680
|
-
if (!cell) return
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
651
|
+
if (!cell) return;
|
|
652
|
+
const basic = mode === "basic";
|
|
653
|
+
let text;
|
|
654
|
+
if (cell.type === "raw_text") text = cell.text;
|
|
655
|
+
else if (cell.type === "raw_number") {
|
|
656
|
+
if (basic && typeof cell.text === "string" && cell.text.length > 0) return cell.text;
|
|
657
|
+
if (typeof cell.value === "number" && Number.isFinite(cell.value)) text = basic ? String(cell.value) : cell.text;
|
|
658
|
+
else if (basic && typeof cell.value === "string") text = cell.value;
|
|
659
|
+
} else if (cell.type === "rich_text" && mode !== "native-header") text = renderSlackRichText(cell.elements, "table", basic ? "\n" : "");
|
|
660
|
+
return basic ? typeof text === "string" ? text : void 0 : readNonBlankString(text);
|
|
688
661
|
}
|
|
689
662
|
function parseSlackBasicTableRows(value) {
|
|
690
663
|
const block = asOptionalRecord(value);
|
|
@@ -694,20 +667,13 @@ function parseSlackBasicTableRows(value) {
|
|
|
694
667
|
const rows = [];
|
|
695
668
|
for (const rawRow of block.rows) {
|
|
696
669
|
if (!Array.isArray(rawRow) || rawRow.length < 1 || rawRow.length > SLACK_DATA_TABLE_COLUMNS_MAX) return;
|
|
697
|
-
const row = rawRow.map(
|
|
670
|
+
const row = rawRow.map((cell) => readSlackTableCell(cell, "basic") ?? "");
|
|
698
671
|
characterCount += row.reduce((total, cell) => total + countCharacters(cell), 0);
|
|
699
672
|
if (characterCount > 1e4) return;
|
|
700
673
|
rows.push(row);
|
|
701
674
|
}
|
|
702
675
|
return rows.some((row) => row.some((cell) => cell.length > 0)) ? rows : void 0;
|
|
703
676
|
}
|
|
704
|
-
function readSlackDataTableCell(value, allowRichText) {
|
|
705
|
-
const cell = asOptionalRecord(value);
|
|
706
|
-
if (!cell) return;
|
|
707
|
-
if (cell.type === "raw_text") return readNonBlankString(cell.text);
|
|
708
|
-
if (cell.type === "raw_number") return typeof cell.value === "number" && Number.isFinite(cell.value) ? readNonBlankString(cell.text) : void 0;
|
|
709
|
-
if (allowRichText && cell.type === "rich_text") return readNonBlankString(renderSlackRichText(cell.elements, "table"));
|
|
710
|
-
}
|
|
711
677
|
function parseSlackDataTable(value) {
|
|
712
678
|
const block = asOptionalRecord(value);
|
|
713
679
|
const caption = readNonBlankString(block?.caption);
|
|
@@ -715,11 +681,11 @@ function parseSlackDataTable(value) {
|
|
|
715
681
|
if (block.rows.length < 2) return;
|
|
716
682
|
const rawHeader = block.rows[0];
|
|
717
683
|
if (!Array.isArray(rawHeader) || rawHeader.length < 1) return;
|
|
718
|
-
const headers = Array.from(rawHeader, (cell) =>
|
|
684
|
+
const headers = Array.from(rawHeader, (cell) => readSlackTableCell(cell, "native-header"));
|
|
719
685
|
if (!headers.every((header) => Boolean(header))) return;
|
|
720
686
|
const rows = block.rows.slice(1).map((rawRow) => {
|
|
721
687
|
if (!Array.isArray(rawRow) || rawRow.length !== headers.length) return;
|
|
722
|
-
const cells = rawRow.map((cell) =>
|
|
688
|
+
const cells = rawRow.map((cell) => readSlackTableCell(cell, "native-cell"));
|
|
723
689
|
return cells.every((cell) => Boolean(cell)) ? cells : void 0;
|
|
724
690
|
});
|
|
725
691
|
if (!rows.every((row) => Boolean(row))) return;
|
|
@@ -729,70 +695,56 @@ function parseSlackDataTable(value) {
|
|
|
729
695
|
rows
|
|
730
696
|
};
|
|
731
697
|
}
|
|
732
|
-
/** Detect current native table blocks without depending on unreleased Slack SDK types. */
|
|
733
|
-
function hasSlackDataTableBlock(blocks) {
|
|
734
|
-
return blocks?.some((block) => asOptionalRecord(block)?.type === "data_table") ?? false;
|
|
735
|
-
}
|
|
736
698
|
function countSlackDataTableCellCharacters(value) {
|
|
737
699
|
const parsed = parseSlackDataTable(value);
|
|
738
700
|
if (!parsed || parsed.rows.length > SLACK_DATA_TABLE_ROWS_MAX || parsed.headers.length > SLACK_DATA_TABLE_COLUMNS_MAX) return;
|
|
739
701
|
const cellCharacterCount = [...parsed.headers, ...parsed.rows.flat()].reduce((total, cell) => total + countCharacters(cell), 0);
|
|
740
702
|
return cellCharacterCount > 1e4 ? void 0 : cellCharacterCount;
|
|
741
703
|
}
|
|
742
|
-
/** Count the aggregate native-table cell characters already present in a message. */
|
|
743
704
|
function countSlackDataTableBlocksCellCharacters(blocks) {
|
|
744
705
|
let total = 0;
|
|
745
706
|
for (const block of blocks ?? []) {
|
|
746
|
-
if (
|
|
707
|
+
if (asOptionalRecord(block)?.type !== "data_table") continue;
|
|
747
708
|
const cellCharacterCount = countSlackDataTableCellCharacters(block);
|
|
748
709
|
if (cellCharacterCount === void 0) return;
|
|
749
710
|
total += cellCharacterCount;
|
|
750
711
|
}
|
|
751
712
|
return total;
|
|
752
713
|
}
|
|
753
|
-
function
|
|
714
|
+
function buildSlackDataTableBlock(block, options = {}) {
|
|
715
|
+
const cellCharacterCountOffset = options.cellCharacterCountOffset ?? 0;
|
|
716
|
+
if (!Number.isSafeInteger(cellCharacterCountOffset) || cellCharacterCountOffset < 0) return;
|
|
754
717
|
if (typeof block.caption !== "string" || block.caption.trim().length === 0 || !Array.isArray(block.headers) || block.headers.length < 1 || block.headers.length > SLACK_DATA_TABLE_COLUMNS_MAX || !Array.isArray(block.rows) || block.rows.length < 1 || block.rows.length > SLACK_DATA_TABLE_ROWS_MAX || new Set(block.headers).size !== block.headers.length || !block.headers.every((header) => typeof header === "string" && header.trim().length > 0) || block.rowHeaderColumnIndex !== void 0 && (!Number.isInteger(block.rowHeaderColumnIndex) || block.rowHeaderColumnIndex < 0 || block.rowHeaderColumnIndex >= block.headers.length)) return;
|
|
755
|
-
const
|
|
718
|
+
const rows = [Array.from(block.headers, (text) => ({
|
|
719
|
+
type: "raw_text",
|
|
720
|
+
text
|
|
721
|
+
}))];
|
|
756
722
|
for (const row of block.rows) {
|
|
757
723
|
if (!Array.isArray(row) || row.length !== block.headers.length) return;
|
|
724
|
+
const cells = [];
|
|
758
725
|
for (const cell of row) {
|
|
759
726
|
if (typeof cell === "number") {
|
|
760
727
|
if (!Number.isFinite(cell)) return;
|
|
761
|
-
|
|
728
|
+
cells.push({
|
|
729
|
+
type: "raw_number",
|
|
730
|
+
value: cell,
|
|
731
|
+
text: String(cell)
|
|
732
|
+
});
|
|
762
733
|
continue;
|
|
763
734
|
}
|
|
764
735
|
if (typeof cell !== "string" || cell.trim().length === 0) return;
|
|
765
|
-
|
|
736
|
+
cells.push({
|
|
737
|
+
type: "raw_text",
|
|
738
|
+
text: cell
|
|
739
|
+
});
|
|
766
740
|
}
|
|
741
|
+
rows.push(cells);
|
|
767
742
|
}
|
|
768
|
-
|
|
769
|
-
}
|
|
770
|
-
/** Count portable table cells when the table fits Slack's native message budget. */
|
|
771
|
-
function resolveSlackDataTableCellCharacterCount(block, options = {}) {
|
|
772
|
-
const cellCharacterCountOffset = options.cellCharacterCountOffset ?? 0;
|
|
773
|
-
if (!Number.isSafeInteger(cellCharacterCountOffset) || cellCharacterCountOffset < 0) return;
|
|
774
|
-
const cellCharacterCount = resolvePortableTableCellCharacterCount(block);
|
|
775
|
-
return cellCharacterCount !== void 0 && cellCharacterCountOffset + cellCharacterCount <= 1e4 ? cellCharacterCount : void 0;
|
|
776
|
-
}
|
|
777
|
-
/** Map a validated portable table to Slack's current app-facing Block Kit shape. */
|
|
778
|
-
function buildSlackDataTableBlock(block, options = {}) {
|
|
779
|
-
if (resolveSlackDataTableCellCharacterCount(block, options) === void 0) return;
|
|
780
|
-
const header = block.headers.map((text) => ({
|
|
781
|
-
type: "raw_text",
|
|
782
|
-
text
|
|
783
|
-
}));
|
|
784
|
-
const rows = block.rows.map((row) => row.map((cell) => typeof cell === "number" ? {
|
|
785
|
-
type: "raw_number",
|
|
786
|
-
value: cell,
|
|
787
|
-
text: String(cell)
|
|
788
|
-
} : {
|
|
789
|
-
type: "raw_text",
|
|
790
|
-
text: cell
|
|
791
|
-
}));
|
|
743
|
+
if (cellCharacterCountOffset + rows.flat().reduce((total, cell) => total + countCharacters(cell.text), 0) > 1e4) return;
|
|
792
744
|
return {
|
|
793
745
|
type: "data_table",
|
|
794
746
|
caption: block.caption,
|
|
795
|
-
rows
|
|
747
|
+
rows,
|
|
796
748
|
...block.rowHeaderColumnIndex !== void 0 ? { row_header_column_index: block.rowHeaderColumnIndex } : {}
|
|
797
749
|
};
|
|
798
750
|
}
|
|
@@ -809,7 +761,6 @@ function renderSlackDataTable(value, render, mrkdwnSafe = false) {
|
|
|
809
761
|
const caption = readNonBlankString(block.caption)?.trim();
|
|
810
762
|
return caption && mrkdwnSafe ? escapeSlackMrkdwn(caption) : caption;
|
|
811
763
|
}
|
|
812
|
-
/** Extract a deterministic accessible summary from a native Slack table block. */
|
|
813
764
|
function renderSlackDataTableFallbackText(value, mrkdwnSafe = false) {
|
|
814
765
|
return renderSlackDataTable(value, mrkdwnSafe ? renderSlackMessagePresentationTableFallbackText : renderMessagePresentationTableFallbackText, mrkdwnSafe);
|
|
815
766
|
}
|
|
@@ -845,24 +796,20 @@ function isStringWithin(value, maxLength) {
|
|
|
845
796
|
function hasUniqueStrings(values) {
|
|
846
797
|
return new Set(values).size === values.length;
|
|
847
798
|
}
|
|
848
|
-
/** True when a portable chart satisfies Slack's complete native-block contract. */
|
|
849
|
-
function canRenderSlackDataVisualization(block) {
|
|
850
|
-
if (!isStringWithin(block.title, SLACK_CHART_TITLE_MAX)) return false;
|
|
851
|
-
if (block.chartType === "pie") return block.segments.length >= 1 && block.segments.length <= SLACK_CHART_SERIES_MAX && block.segments.every((segment) => isStringWithin(segment.label, SLACK_CHART_LABEL_MAX) && Number.isFinite(segment.value) && segment.value > 0);
|
|
852
|
-
if (block.categories.length < 1 || block.categories.length > SLACK_CHART_DATA_POINTS_MAX || !block.categories.every((category) => isStringWithin(category, SLACK_CHART_LABEL_MAX)) || !hasUniqueStrings(block.categories) || block.series.length < 1 || block.series.length > SLACK_CHART_SERIES_MAX || !hasUniqueStrings(block.series.map((series) => series.name)) || block.xLabel !== void 0 && !isStringWithin(block.xLabel, SLACK_CHART_AXIS_LABEL_MAX) || block.yLabel !== void 0 && !isStringWithin(block.yLabel, SLACK_CHART_AXIS_LABEL_MAX)) return false;
|
|
853
|
-
return block.series.every((series) => isStringWithin(series.name, SLACK_CHART_LABEL_MAX) && series.values.length === block.categories.length && series.values.every((value) => Number.isFinite(value)));
|
|
854
|
-
}
|
|
855
|
-
/** Map a validated portable chart to Slack's app-facing Block Kit shape. */
|
|
856
799
|
function buildSlackDataVisualizationBlock(block) {
|
|
857
|
-
if (!
|
|
858
|
-
if (block.chartType === "pie")
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
800
|
+
if (!isStringWithin(block.title, SLACK_CHART_TITLE_MAX)) return;
|
|
801
|
+
if (block.chartType === "pie") {
|
|
802
|
+
if (block.segments.length < 1 || block.segments.length > SLACK_CHART_SERIES_MAX || !block.segments.every((segment) => isStringWithin(segment.label, SLACK_CHART_LABEL_MAX) && Number.isFinite(segment.value) && segment.value > 0)) return;
|
|
803
|
+
return {
|
|
804
|
+
type: "data_visualization",
|
|
805
|
+
title: block.title,
|
|
806
|
+
chart: {
|
|
807
|
+
type: "pie",
|
|
808
|
+
segments: block.segments.map((segment) => ({ ...segment }))
|
|
809
|
+
}
|
|
810
|
+
};
|
|
811
|
+
}
|
|
812
|
+
if (block.categories.length < 1 || block.categories.length > SLACK_CHART_DATA_POINTS_MAX || !block.categories.every((category) => isStringWithin(category, SLACK_CHART_LABEL_MAX)) || !hasUniqueStrings(block.categories) || block.series.length < 1 || block.series.length > SLACK_CHART_SERIES_MAX || !hasUniqueStrings(block.series.map((series) => series.name)) || block.xLabel !== void 0 && !isStringWithin(block.xLabel, SLACK_CHART_AXIS_LABEL_MAX) || block.yLabel !== void 0 && !isStringWithin(block.yLabel, SLACK_CHART_AXIS_LABEL_MAX) || !block.series.every((series) => isStringWithin(series.name, SLACK_CHART_LABEL_MAX) && series.values.length === block.categories.length && series.values.every((value) => Number.isFinite(value)))) return;
|
|
866
813
|
return {
|
|
867
814
|
type: "data_visualization",
|
|
868
815
|
title: block.title,
|
|
@@ -892,22 +839,20 @@ function readSlackChartDatum(value) {
|
|
|
892
839
|
value: datumValue
|
|
893
840
|
} : void 0;
|
|
894
841
|
}
|
|
895
|
-
function parseSlackDataVisualizationBlock(
|
|
896
|
-
const
|
|
897
|
-
const
|
|
898
|
-
|
|
899
|
-
if (block?.type !== "data_visualization" || typeof title !== "string" || !chart) return;
|
|
842
|
+
function parseSlackDataVisualizationBlock(block) {
|
|
843
|
+
const title = block.title;
|
|
844
|
+
const chart = asOptionalRecord(block.chart);
|
|
845
|
+
if (typeof title !== "string" || !chart) return;
|
|
900
846
|
if (chart.type === "pie") {
|
|
901
847
|
if (!Array.isArray(chart.segments)) return;
|
|
902
848
|
const segments = chart.segments.map(readSlackChartDatum);
|
|
903
849
|
if (segments.some((segment) => !segment)) return;
|
|
904
|
-
|
|
850
|
+
return {
|
|
905
851
|
type: "chart",
|
|
906
852
|
chartType: "pie",
|
|
907
853
|
title,
|
|
908
854
|
segments
|
|
909
|
-
}
|
|
910
|
-
return normalizedBlock?.type === "chart" ? normalizedBlock : void 0;
|
|
855
|
+
};
|
|
911
856
|
}
|
|
912
857
|
if (chart.type !== "bar" && chart.type !== "area" && chart.type !== "line") return;
|
|
913
858
|
const axisConfig = asOptionalRecord(chart.axis_config);
|
|
@@ -927,7 +872,7 @@ function parseSlackDataVisualizationBlock(value) {
|
|
|
927
872
|
};
|
|
928
873
|
});
|
|
929
874
|
if (series.some((entry) => !entry)) return;
|
|
930
|
-
|
|
875
|
+
return {
|
|
931
876
|
type: "chart",
|
|
932
877
|
chartType: chart.type,
|
|
933
878
|
title,
|
|
@@ -935,15 +880,14 @@ function parseSlackDataVisualizationBlock(value) {
|
|
|
935
880
|
series,
|
|
936
881
|
xLabel: axisConfig?.x_label,
|
|
937
882
|
yLabel: axisConfig?.y_label
|
|
938
|
-
}
|
|
939
|
-
return normalizedBlock?.type === "chart" ? normalizedBlock : void 0;
|
|
883
|
+
};
|
|
940
884
|
}
|
|
941
885
|
/** Extract an accessible summary, escaping mrkdwn control tokens when requested. */
|
|
942
886
|
function renderSlackDataVisualizationFallbackText(value, mrkdwnSafe = false) {
|
|
943
887
|
const block = asOptionalRecord(value);
|
|
944
888
|
if (block?.type !== "data_visualization") return;
|
|
945
|
-
const parsed = parseSlackDataVisualizationBlock(block);
|
|
946
|
-
if (parsed) return mrkdwnSafe ? renderSlackMessagePresentationChartFallbackText(parsed) : renderMessagePresentationChartFallbackText(parsed);
|
|
889
|
+
const parsed = normalizeMessagePresentation({ blocks: [parseSlackDataVisualizationBlock(block)] })?.blocks[0];
|
|
890
|
+
if (parsed?.type === "chart") return mrkdwnSafe ? renderSlackMessagePresentationChartFallbackText(parsed) : renderMessagePresentationChartFallbackText(parsed);
|
|
947
891
|
const title = typeof block.title === "string" ? block.title.trim() : "";
|
|
948
892
|
return title ? mrkdwnSafe ? escapeSlackMrkdwn(title) : title : void 0;
|
|
949
893
|
}
|
|
@@ -1052,7 +996,7 @@ const SLACK_FORMAT_PROFILE = FormatCapabilityProfile.define({
|
|
|
1052
996
|
}
|
|
1053
997
|
});
|
|
1054
998
|
const SLACK_ASSISTANT_TRANSCRIPT_PREFIX = "`Assistant:` ";
|
|
1055
|
-
function tokenizeSlackMrkdwn(text) {
|
|
999
|
+
function tokenizeSlackMrkdwn(text, graphemes) {
|
|
1056
1000
|
const tokens = [];
|
|
1057
1001
|
for (let index = 0; index < text.length;) {
|
|
1058
1002
|
if (text.startsWith("```", index)) {
|
|
@@ -1081,15 +1025,15 @@ function tokenizeSlackMrkdwn(text) {
|
|
|
1081
1025
|
}
|
|
1082
1026
|
const codePoint = text.codePointAt(index);
|
|
1083
1027
|
if (codePoint === void 0) break;
|
|
1084
|
-
const
|
|
1028
|
+
const grapheme = graphemes?.containing(index + (codePoint > 65535 ? 1 : 0));
|
|
1029
|
+
const character = grapheme && text.slice(index, grapheme.index + grapheme.segment.length).match(/^[^`*_~<>&]+/u)?.[0] || String.fromCodePoint(codePoint);
|
|
1085
1030
|
index += character.length;
|
|
1086
1031
|
tokens.push(character);
|
|
1087
1032
|
}
|
|
1088
1033
|
return tokens;
|
|
1089
1034
|
}
|
|
1090
1035
|
function resolveSlackCodeMarkerTransition(active, token) {
|
|
1091
|
-
if (token === "```" && active
|
|
1092
|
-
if (token === "`" && active !== "```") return active === "`" ? void 0 : "`";
|
|
1036
|
+
if ((token === "`" || token === "```") && (active === void 0 || active === token)) return active === token ? void 0 : token;
|
|
1093
1037
|
return null;
|
|
1094
1038
|
}
|
|
1095
1039
|
function maskSlackExcludedText(text) {
|
|
@@ -1128,9 +1072,8 @@ function projectSlackAngleToken(token, dateDisplay) {
|
|
|
1128
1072
|
}
|
|
1129
1073
|
const labelSeparator = inner.indexOf("|");
|
|
1130
1074
|
if (labelSeparator >= 0) return decodeSlackMrkdwnEntities(inner.slice(labelSeparator + 1));
|
|
1131
|
-
|
|
1132
|
-
if (
|
|
1133
|
-
if (inner.startsWith("!")) return "!";
|
|
1075
|
+
const prefix = inner.charAt(0);
|
|
1076
|
+
if (prefix === "@" || prefix === "#" || prefix === "!") return prefix;
|
|
1134
1077
|
return decodeSlackMrkdwnEntities(inner);
|
|
1135
1078
|
}
|
|
1136
1079
|
function appendSlackVisibleProjection(projection, visible, excluded) {
|
|
@@ -1235,7 +1178,7 @@ function chunkSlackMrkdwnText(text, limit) {
|
|
|
1235
1178
|
if (content && content !== marker) chunks.push(marker ? `${content}${marker}` : content);
|
|
1236
1179
|
content = "";
|
|
1237
1180
|
};
|
|
1238
|
-
for (const token of tokenizeSlackMrkdwn(text)) {
|
|
1181
|
+
for (const token of tokenizeSlackMrkdwn(text, new Intl.Segmenter(void 0, { granularity: "grapheme" }).segment(text))) {
|
|
1239
1182
|
const transition = resolveSlackCodeMarkerTransition(activeMarker, token);
|
|
1240
1183
|
const nextMarker = transition === null ? activeMarker : transition;
|
|
1241
1184
|
const sourceMarker = token === "`" || token === "```" ? token : void 0;
|
|
@@ -1251,9 +1194,9 @@ function chunkSlackMrkdwnText(text, limit) {
|
|
|
1251
1194
|
if (token.length > contentLimit) {
|
|
1252
1195
|
flush();
|
|
1253
1196
|
const marker = wrapper(activeMarker);
|
|
1254
|
-
if (activeMarker
|
|
1255
|
-
|
|
1256
|
-
|
|
1197
|
+
if (activeMarker) {
|
|
1198
|
+
const fragments = chunkTextForOutbound(marker ? token : escapeSlackMrkdwn(token), Math.max(1, Math.floor(marker ? contentLimit : limit)), { preserveWhitespace: true });
|
|
1199
|
+
chunks.push(...marker ? fragments.map((fragment) => `${marker}${fragment}${marker}`) : fragments);
|
|
1257
1200
|
continue;
|
|
1258
1201
|
}
|
|
1259
1202
|
chunks.push(...token.length <= limit ? [token] : chunkTextForOutbound(token, limit));
|
|
@@ -1316,27 +1259,25 @@ const SLACK_REPLY_BUTTON_ACTION_ID = "openclaw:reply_button";
|
|
|
1316
1259
|
const SLACK_REPLY_LINK_ACTION_ID = "openclaw:reply_link";
|
|
1317
1260
|
const SLACK_SESSION_LINK_ACTION_ID = "openclaw:session_link";
|
|
1318
1261
|
const SLACK_REPLY_SELECT_ACTION_ID = "openclaw:reply_select";
|
|
1319
|
-
const SLACK_CALLBACK_BUTTON_ACTION_ID = "openclaw:callback_button";
|
|
1320
|
-
const SLACK_CALLBACK_SELECT_ACTION_ID = "openclaw:callback_select";
|
|
1321
|
-
const SLACK_APPROVAL_BUTTON_ACTION_ID = "openclaw:approval_button";
|
|
1322
|
-
const SLACK_APPROVAL_SELECT_ACTION_ID = "openclaw:approval_select";
|
|
1323
|
-
const SLACK_QUESTION_BUTTON_ACTION_ID = "openclaw:question_button";
|
|
1324
1262
|
const SLACK_BUTTON_ACTION_IDS = {
|
|
1325
|
-
approval:
|
|
1326
|
-
callback:
|
|
1263
|
+
approval: "openclaw:approval_button",
|
|
1264
|
+
callback: "openclaw:callback_button",
|
|
1327
1265
|
link: SLACK_REPLY_LINK_ACTION_ID,
|
|
1328
|
-
question:
|
|
1266
|
+
question: "openclaw:question_button",
|
|
1329
1267
|
reply: SLACK_REPLY_BUTTON_ACTION_ID
|
|
1330
1268
|
};
|
|
1331
1269
|
const SLACK_SELECT_ACTION_IDS = {
|
|
1332
|
-
approval:
|
|
1333
|
-
callback:
|
|
1270
|
+
approval: "openclaw:approval_select",
|
|
1271
|
+
callback: "openclaw:callback_select",
|
|
1334
1272
|
reply: SLACK_REPLY_SELECT_ACTION_ID
|
|
1335
1273
|
};
|
|
1336
1274
|
const SLACK_QUESTION_FINALIZATION_BLOCKS = Symbol("slackQuestionFinalizationBlocks");
|
|
1337
|
-
function
|
|
1338
|
-
return actionId ===
|
|
1275
|
+
function createSlackActionIdMatcher(...prefixes) {
|
|
1276
|
+
return (actionId) => prefixes.some((prefix) => actionId === prefix || actionId.startsWith(`${prefix}:`));
|
|
1339
1277
|
}
|
|
1278
|
+
const isSlackQuestionActionId = createSlackActionIdMatcher(SLACK_BUTTON_ACTION_IDS.question);
|
|
1279
|
+
const isSlackApprovalActionId = createSlackActionIdMatcher(SLACK_BUTTON_ACTION_IDS.approval, SLACK_SELECT_ACTION_IDS.approval);
|
|
1280
|
+
const isSlackCallbackActionId = createSlackActionIdMatcher(SLACK_BUTTON_ACTION_IDS.callback, SLACK_SELECT_ACTION_IDS.callback);
|
|
1340
1281
|
/** Read only question control identities from the blocks actually sent to Slack. */
|
|
1341
1282
|
function resolveSlackQuestionActionIds(blocks) {
|
|
1342
1283
|
return (blocks ?? []).flatMap((block) => {
|
|
@@ -1344,19 +1285,13 @@ function resolveSlackQuestionActionIds(blocks) {
|
|
|
1344
1285
|
return (block.elements ?? []).flatMap(({ action_id }) => action_id && isSlackQuestionActionId(action_id) ? [action_id] : []);
|
|
1345
1286
|
});
|
|
1346
1287
|
}
|
|
1347
|
-
function isSlackApprovalActionId(actionId) {
|
|
1348
|
-
return actionId === SLACK_APPROVAL_BUTTON_ACTION_ID || actionId === SLACK_APPROVAL_SELECT_ACTION_ID || actionId.startsWith(`${SLACK_APPROVAL_BUTTON_ACTION_ID}:`) || actionId.startsWith(`${SLACK_APPROVAL_SELECT_ACTION_ID}:`);
|
|
1349
|
-
}
|
|
1350
|
-
function isSlackCallbackActionId(actionId) {
|
|
1351
|
-
return actionId === SLACK_CALLBACK_BUTTON_ACTION_ID || actionId === SLACK_CALLBACK_SELECT_ACTION_ID || actionId.startsWith(`${SLACK_CALLBACK_BUTTON_ACTION_ID}:`) || actionId.startsWith(`${SLACK_CALLBACK_SELECT_ACTION_ID}:`);
|
|
1352
|
-
}
|
|
1353
1288
|
//#endregion
|
|
1354
1289
|
//#region extensions/slack/src/truncate.ts
|
|
1355
|
-
function truncateSlackText(value, max) {
|
|
1356
|
-
const
|
|
1357
|
-
if (
|
|
1358
|
-
if (max <= 1) return sliceUtf16Safe(
|
|
1359
|
-
return `${sliceUtf16Safe(
|
|
1290
|
+
function truncateSlackText(value, max, whitespace = "trim") {
|
|
1291
|
+
const text = whitespace === "preserve" ? value : value.trim();
|
|
1292
|
+
if (text.length <= max) return text;
|
|
1293
|
+
if (max <= 1) return sliceUtf16Safe(text, 0, max);
|
|
1294
|
+
return `${sliceUtf16Safe(text, 0, max - 1)}…`;
|
|
1360
1295
|
}
|
|
1361
1296
|
function countSlackTextUtf8Bytes(value) {
|
|
1362
1297
|
return Buffer.byteLength(value, "utf8");
|
|
@@ -1409,14 +1344,6 @@ function readAltText(value) {
|
|
|
1409
1344
|
const text = normalizeOptionalString(value);
|
|
1410
1345
|
return text ? escapeSlackMrkdwn(text) : void 0;
|
|
1411
1346
|
}
|
|
1412
|
-
function readContextText(block, options = {}) {
|
|
1413
|
-
if (!Array.isArray(block.elements)) return;
|
|
1414
|
-
const parts = block.elements.map((element) => {
|
|
1415
|
-
const record = asOptionalRecord(element);
|
|
1416
|
-
return readTextObject(record, options) ?? readAltText(record?.alt_text);
|
|
1417
|
-
}).filter((part) => Boolean(part));
|
|
1418
|
-
return parts.length > 0 ? parts.join(" ") : void 0;
|
|
1419
|
-
}
|
|
1420
1347
|
function readControlElementText(value, options = {}) {
|
|
1421
1348
|
const element = asOptionalRecord(value);
|
|
1422
1349
|
const type = normalizeOptionalString(element?.type);
|
|
@@ -1431,12 +1358,16 @@ function readControlElementsText(values, options = {}) {
|
|
|
1431
1358
|
const labels = values.map((value) => readControlElementText(value, options)).filter(Boolean);
|
|
1432
1359
|
return [...new Set(labels)].join("\n") || void 0;
|
|
1433
1360
|
}
|
|
1434
|
-
function
|
|
1435
|
-
const
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1361
|
+
function readTextLayout(block, options = {}) {
|
|
1362
|
+
const context = block.type === "context";
|
|
1363
|
+
return (context ? (Array.isArray(block.elements) ? block.elements : []).map((element) => {
|
|
1364
|
+
const record = asOptionalRecord(element);
|
|
1365
|
+
return readTextObject(record, options) ?? readAltText(record?.alt_text);
|
|
1366
|
+
}) : [
|
|
1367
|
+
readTextObject(block.text, options),
|
|
1368
|
+
...Array.isArray(block.fields) ? block.fields.map((field) => readTextObject(field, options)) : [],
|
|
1369
|
+
readControlElementText(block.accessory, options)
|
|
1370
|
+
]).filter(Boolean).join(context ? " " : "\n") || void 0;
|
|
1440
1371
|
}
|
|
1441
1372
|
/** Read only user-visible text from one Slack block. */
|
|
1442
1373
|
function renderSlackBlockFallbackText(raw, options = {}) {
|
|
@@ -1445,11 +1376,11 @@ function renderSlackBlockFallbackText(raw, options = {}) {
|
|
|
1445
1376
|
switch (block.type) {
|
|
1446
1377
|
case "rich_text": return normalizeOptionalString(renderSlackRichText(block.elements, options.nativeReferenceFormat === "plain" ? "native-reference" : "escaped", "\n"));
|
|
1447
1378
|
case "header": return readTextObject(block.text, options);
|
|
1448
|
-
case "section":
|
|
1379
|
+
case "section":
|
|
1380
|
+
case "context": return readTextLayout(block, options);
|
|
1449
1381
|
case "image": return readAltText(block.alt_text) ?? readTextObject(block.title) ?? "Shared an image";
|
|
1450
1382
|
case "video": return readTextObject(block.title, options) ?? readAltText(block.alt_text) ?? "Shared a video";
|
|
1451
1383
|
case "file": return "Shared a file";
|
|
1452
|
-
case "context": return readContextText(block, options);
|
|
1453
1384
|
case "actions": return Array.isArray(block.elements) ? readControlElementsText(block.elements, options) : void 0;
|
|
1454
1385
|
case "data_visualization": return renderSlackDataVisualizationFallbackText(block, options.nativeDataFormat !== "plain");
|
|
1455
1386
|
case "data_table": return renderSlackDataTableFallbackText(block, options.nativeDataFormat !== "plain");
|
|
@@ -1472,16 +1403,16 @@ function buildSlackCompleteBlocksFallbackText(blocks, options = {}) {
|
|
|
1472
1403
|
const SLACK_MALFORMED_NATIVE_DATA_FALLBACK = "Slack could not render this chart or table data.";
|
|
1473
1404
|
const SLACK_RESPONSE_URL_BODY_LIMIT_BYTES = 16384;
|
|
1474
1405
|
const SLACK_RESPONSE_URL_BODY_TIMEOUT_MS = 3e4;
|
|
1475
|
-
|
|
1406
|
+
function isSlackNativeDataBlock(block) {
|
|
1407
|
+
const type = asOptionalRecord(block)?.type;
|
|
1408
|
+
return type === "data_table" || type === "data_visualization";
|
|
1409
|
+
}
|
|
1476
1410
|
function hasSlackNativeDataBlock(blocks) {
|
|
1477
|
-
return
|
|
1411
|
+
return blocks?.some(isSlackNativeDataBlock) ?? false;
|
|
1478
1412
|
}
|
|
1479
1413
|
/** Keep every sibling block while removing Slack's native data blocks. */
|
|
1480
1414
|
function stripSlackNativeDataBlocks(blocks) {
|
|
1481
|
-
return (blocks ?? []).filter((block) =>
|
|
1482
|
-
const type = asOptionalRecord(block)?.type;
|
|
1483
|
-
return type !== "data_table" && type !== "data_visualization";
|
|
1484
|
-
});
|
|
1415
|
+
return (blocks ?? []).filter((block) => !isSlackNativeDataBlock(block));
|
|
1485
1416
|
}
|
|
1486
1417
|
/** Match Slack's Web API and response_url `invalid_blocks` error shapes. */
|
|
1487
1418
|
function isSlackInvalidBlocksError(error) {
|
|
@@ -1540,17 +1471,16 @@ function createSlackNativeDataBaseTextConsumer(baseText) {
|
|
|
1540
1471
|
return true;
|
|
1541
1472
|
};
|
|
1542
1473
|
}
|
|
1543
|
-
function
|
|
1544
|
-
const
|
|
1545
|
-
const
|
|
1546
|
-
const dataTexts = [];
|
|
1474
|
+
function appendSlackBlockFallback(text, blocks, render) {
|
|
1475
|
+
const consumeFromBase = createSlackNativeDataBaseTextConsumer(text);
|
|
1476
|
+
const parts = [text];
|
|
1547
1477
|
for (const block of blocks ?? []) {
|
|
1548
1478
|
const dataText = render(block);
|
|
1549
1479
|
if (!dataText) continue;
|
|
1550
|
-
if (
|
|
1551
|
-
|
|
1480
|
+
if (isSlackNativeDataBlock(block) && consumeFromBase(dataText)) continue;
|
|
1481
|
+
parts.push(dataText);
|
|
1552
1482
|
}
|
|
1553
|
-
return
|
|
1483
|
+
return parts.filter((part) => part.trim()).join("\n\n");
|
|
1554
1484
|
}
|
|
1555
1485
|
function renderSlackNativeDataPlainTextBlock(value) {
|
|
1556
1486
|
const type = asOptionalRecord(value)?.type;
|
|
@@ -1559,30 +1489,18 @@ function renderSlackNativeDataPlainTextBlock(value) {
|
|
|
1559
1489
|
}
|
|
1560
1490
|
/** Build formatting-disabled accessibility text from actual Slack block order. */
|
|
1561
1491
|
function buildSlackNativeDataAccessibilityText(text, blocks) {
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
};
|
|
1567
|
-
append(text);
|
|
1568
|
-
for (const block of blocks ?? []) {
|
|
1569
|
-
const isNativeData = hasSlackNativeDataBlock([block]);
|
|
1570
|
-
const rendered = renderSlackNativeDataPlainTextBlock(block) ?? renderSlackBlockFallbackText(block, {
|
|
1571
|
-
nativeDataFormat: "plain",
|
|
1572
|
-
includeSelectOptions: true
|
|
1573
|
-
}) ?? (isNativeData ? "Slack could not render this chart or table data." : void 0);
|
|
1574
|
-
if (!rendered || isNativeData && consumeFromBase(rendered)) continue;
|
|
1575
|
-
append(rendered);
|
|
1576
|
-
}
|
|
1577
|
-
return parts.join("\n\n");
|
|
1492
|
+
return appendSlackBlockFallback(text, blocks, (block) => renderSlackNativeDataPlainTextBlock(block) ?? renderSlackBlockFallbackText(block, {
|
|
1493
|
+
nativeDataFormat: "plain",
|
|
1494
|
+
includeSelectOptions: true
|
|
1495
|
+
}) ?? (isSlackNativeDataBlock(block) ? "Slack could not render this chart or table data." : void 0));
|
|
1578
1496
|
}
|
|
1579
1497
|
/** Preserve every native data block's content once when Slack requires a text-only retry. */
|
|
1580
1498
|
function appendSlackNativeDataFallbackText(text, blocks) {
|
|
1581
|
-
return
|
|
1499
|
+
return appendSlackBlockFallback(text.trim(), blocks, (block) => isSlackNativeDataBlock(block) ? renderSlackBlockFallbackText(block) : void 0);
|
|
1582
1500
|
}
|
|
1583
1501
|
/** Build a bounded plain-text retry without activating control tokens. */
|
|
1584
1502
|
function appendSlackNativeDataPlainTextFallback(text, blocks) {
|
|
1585
|
-
return
|
|
1503
|
+
return appendSlackBlockFallback(text.trim(), blocks, renderSlackNativeDataPlainTextBlock);
|
|
1586
1504
|
}
|
|
1587
1505
|
//#endregion
|
|
1588
1506
|
//#region extensions/slack/src/detached-target-admission.ts
|
|
@@ -1641,8 +1559,12 @@ function normalizeSlackRouteBindingConfig(cfg) {
|
|
|
1641
1559
|
}
|
|
1642
1560
|
function resolveSlackConversationBindingRoute(params) {
|
|
1643
1561
|
const { resolveRoute } = params;
|
|
1562
|
+
const resolveRuntime = (input, role) => params.inspections ? inspectRuntimeConversationBindingRoute({
|
|
1563
|
+
...input,
|
|
1564
|
+
inspection: params.inspections[role]
|
|
1565
|
+
}) : resolveRuntimeConversationBindingRoute(input);
|
|
1644
1566
|
let baseRuntimeRoute;
|
|
1645
|
-
const resolveBaseRoute = (threadInspection) => baseRuntimeRoute ??=
|
|
1567
|
+
const resolveBaseRoute = (threadInspection) => baseRuntimeRoute ??= resolveRuntime({
|
|
1646
1568
|
resolveRoute: threadInspection ? (selection) => inspectRuntimeConversationBindingRoute({
|
|
1647
1569
|
route: resolveRoute(selection),
|
|
1648
1570
|
inspection: threadInspection
|
|
@@ -1653,8 +1575,8 @@ function resolveSlackConversationBindingRoute(params) {
|
|
|
1653
1575
|
accountId: params.accountId,
|
|
1654
1576
|
conversationId: params.baseConversationId
|
|
1655
1577
|
}
|
|
1656
|
-
});
|
|
1657
|
-
const boundThreadRoute = params.bindingsEnabled && params.runtimeBindingThreadId ?
|
|
1578
|
+
}, "base");
|
|
1579
|
+
const boundThreadRoute = params.bindingsEnabled && params.runtimeBindingThreadId ? resolveRuntime({
|
|
1658
1580
|
resolveRoute: (selection) => selection.bindingRecord || !selection.bindingOwnerAvailable ? resolveRoute(selection) : resolveBaseRoute(selection.inspection).route,
|
|
1659
1581
|
touchBinding: params.touchBinding,
|
|
1660
1582
|
conversation: {
|
|
@@ -1663,7 +1585,7 @@ function resolveSlackConversationBindingRoute(params) {
|
|
|
1663
1585
|
conversationId: params.runtimeBindingThreadId,
|
|
1664
1586
|
parentConversationId: params.baseConversationId
|
|
1665
1587
|
}
|
|
1666
|
-
}) : null;
|
|
1588
|
+
}, "thread") : null;
|
|
1667
1589
|
const runtimeRoute = !params.bindingsEnabled ? {
|
|
1668
1590
|
bindingOwnerAvailable: true,
|
|
1669
1591
|
route: resolveRoute({
|
|
@@ -1694,10 +1616,31 @@ function resolveSlackConversationBindingRoute(params) {
|
|
|
1694
1616
|
}
|
|
1695
1617
|
//#endregion
|
|
1696
1618
|
//#region extensions/slack/src/monitor/workspace-routing.ts
|
|
1697
|
-
function
|
|
1619
|
+
function resolveSlackAgentRoute(params) {
|
|
1620
|
+
const route = resolveAgentRoute({
|
|
1621
|
+
cfg: params.cfg,
|
|
1622
|
+
defaultAgentId: params.defaultAgentId,
|
|
1623
|
+
channel: "slack",
|
|
1624
|
+
accountId: params.accountId,
|
|
1625
|
+
teamId: params.teamId,
|
|
1626
|
+
peer: {
|
|
1627
|
+
kind: params.peer.kind,
|
|
1628
|
+
id: qualifySlackRoutePeerId({
|
|
1629
|
+
id: params.peer.id,
|
|
1630
|
+
kind: params.peer.kind === "direct" ? "user" : "channel",
|
|
1631
|
+
eventScope: params.eventScope
|
|
1632
|
+
})
|
|
1633
|
+
}
|
|
1634
|
+
});
|
|
1635
|
+
if (!params.eventScope || params.peer.kind !== "direct" || route.dmScope !== "main") return route;
|
|
1698
1636
|
const accountId = encodeURIComponent(params.accountId).toLowerCase();
|
|
1699
1637
|
const teamId = encodeURIComponent(params.eventScope.teamId).toLowerCase();
|
|
1700
|
-
|
|
1638
|
+
const sessionKey = `${route.sessionKey}:account:${accountId}:team:${teamId}`;
|
|
1639
|
+
return {
|
|
1640
|
+
...route,
|
|
1641
|
+
sessionKey,
|
|
1642
|
+
mainSessionKey: sessionKey
|
|
1643
|
+
};
|
|
1701
1644
|
}
|
|
1702
1645
|
function qualifySlackRoutePeerId(params) {
|
|
1703
1646
|
if (!params.eventScope) return params.id;
|
|
@@ -1801,4 +1744,4 @@ async function renameSlackSession(params) {
|
|
|
1801
1744
|
}
|
|
1802
1745
|
}
|
|
1803
1746
|
//#endregion
|
|
1804
|
-
export { SLACK_DATA_TABLE_AGGREGATE_CELL_CHARACTERS_MAX as $,
|
|
1747
|
+
export { SLACK_DATA_TABLE_AGGREGATE_CELL_CHARACTERS_MAX as $, SLACK_TEXT_LIMIT as A, isSlackWorkspaceInstallation as At, SLACK_SESSION_LINK_ACTION_ID as B, resolveSlackAutoThreadId as Bt, stripSlackNativeDataBlocks as C, shouldHandleSlackNativeApprovalRequest as Ct, SLACK_EDIT_TEXT_MAX_BYTES as D, isSlackPluginApprovalAuthorizedSender as Dt, renderSlackBlockFallbackText as E, getSlackApprovalApproversForTeam as Et, SLACK_QUESTION_FINALIZATION_BLOCKS as F, normalizeSlackApproverId as Ft, decodeSlackQuestionAction as G, isSlackCallbackActionId as H, SLACK_REPLY_BUTTON_ACTION_ID as I, resolveSlackExecApprovalTarget as It, chunkSlackMrkdwnText as J, encodeSlackQuestionAction as K, SLACK_REPLY_LINK_ACTION_ID as L, shouldSuppressLocalSlackExecApprovalPrompt as Lt, truncateSlackText as M, getSlackExecApprovalApprovers as Mt, truncateSlackTextByUtf8Bytes as N, isSlackExecApprovalAuthorizedSender as Nt, SLACK_MESSAGE_TEXT_HARD_LIMIT as O, resolveSlackApprovalTeamId as Ot, SLACK_BUTTON_ACTION_IDS as P, isSlackExecApprovalClientEnabled as Pt, hasSlackDataVisualizationBlock as Q, SLACK_REPLY_SELECT_ACTION_ID as R, resolvePluginApprovalSlackApprovers as Rt, renderSlackNativeDataPlainTextBlock as S, resolveTurnSourceSlackOriginTarget as St, buildSlackCompleteBlocksFallbackText as T, slackTargetsMatch as Tt, isSlackQuestionActionId as U, isSlackApprovalActionId as V, resolveSlackQuestionActionIds as W, normalizeSlackOutboundText as X, markdownToSlackMrkdwnChunks as Y, buildSlackDataVisualizationBlock as Z, createSlackNativeDataBaseTextConsumer as _, normalizeSlackForwardTarget as _t, resolveSlackGroupRequireMention as a, escapeSlackMrkdwn as at, isSlackInvalidBlocksResponse as b, resolveSlackApproverDmTargets as bt, qualifySlackRoutePeerId as c, encodeSlackApprovalAction as ct, resolveSlackConversationBindingRoute as d, SLACK_SECTION_TEXT_MAX as dt, buildSlackDataTableBlock as et, assertSlackDetachedTargetAllowed as f, SLACK_MAX_BLOCKS as ft, buildSlackNativeDataAccessibilityText as g, isSlackPluginApprovalRequest as gt, appendSlackNativeDataPlainTextFallback as h, isSlackAnyNativeApprovalClientEnabled as ht, buildSlackChannelPolicyScope as i, renderSlackMessagePresentationFallbackText as it, countSlackTextUtf8Bytes as j, registerSlackInstallationState as jt, SLACK_MESSAGE_TEXT_RECOMMENDED_LIMIT as k, getSlackInstallationKind as kt, resolveSlackAgentRoute as l, SLACK_BUTTON_VALUE_MAX as lt, appendSlackNativeDataFallbackText as m, validateSlackBlocksArray as mt, setSlackSessionStatus as n, countSlackDataTableCellCharacters as nt, resolveSlackGroupToolPolicy as o, SLACK_APPROVAL_HEADER_BLOCK_ID as ot, SLACK_MALFORMED_NATIVE_DATA_FALLBACK as p, parseSlackBlocksInput as pt, resolveSlackQuestionAction as q, buildSlackChannelIdCandidates as r, renderSlackMessagePresentationChartFallbackText as rt, qualifySlackConversationId as s, decodeSlackApprovalAction as st, renameSlackSession as t, countSlackDataTableBlocksCellCharacters as tt, normalizeSlackRouteBindingConfig as u, SLACK_PRESENTATION_CAPABILITIES as ut, hasSlackNativeDataBlock as v, normalizeSlackOriginTarget as vt, buildSlackBlocksFallbackText as w, shouldHandleSlackPluginViaForwardingSession as wt, isSlackNativeResponseUrlRejection as x, resolveSlackFallbackOriginTarget as xt, isSlackInvalidBlocksError as y, resolveSessionSlackOriginTarget as yt, SLACK_SELECT_ACTION_IDS as z, SLACK_PRIVATE_ACTION_DELIVERY_RESULT as zt };
|