@openclaw/slack 2026.8.1-beta.3 → 2026.9.1-beta.1
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-configured-sUohAxZr.js +33 -0
- package/dist/account-inspect-CN2hBsim.js +87 -0
- package/dist/account-inspect-api.js +1 -1
- package/dist/{accounts-BlzxuYle.js → accounts-Dm_H77gH.js} +7 -10
- package/dist/{accounts.runtime-CbabBL8x.js → accounts.runtime-DRuEK6mL.js} +1 -1
- package/dist/{action-runtime-D6jg2CQd.js → action-runtime-BoSeX09X.js} +18 -21
- package/dist/action-runtime.runtime-Dpa16J87.js +2 -0
- package/dist/{actions-DFk0ANVB.js → actions-XdQyjG_p.js} +98 -66
- package/dist/api.js +12 -12
- package/dist/{approval-handler.runtime-BNvAoKdK.js → approval-handler.runtime-DxXfGX_Z.js} +53 -176
- package/dist/{channel-CA5w7qDF.js → channel-C_vnTgxo.js} +60 -54
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-type-CZWv55Wu.js → channel-type-j-2lalcC.js} +3 -3
- package/dist/{channel.setup-CpyYsEXH.js → channel.setup-aal8tokM.js} +33 -48
- package/dist/configured-state.js +34 -0
- package/dist/{directory-config-BGYyuzWh.js → directory-config-DqfQ42OV.js} +1 -1
- package/dist/directory-contract-api.js +1 -1
- package/dist/{directory-live-DjUJQLbq.js → directory-live-lC6X_Ru-.js} +2 -2
- package/dist/{group-policy-DyfB_ZIE.js → group-policy-CU1tEGpS.js} +536 -609
- package/dist/{message-tool-api-CqMr5Rmc.js → message-tool-api-CWosHSi5.js} +6 -5
- package/dist/message-tool-api.js +1 -1
- package/dist/{monitor-Chrecrb9.js → monitor-DrNCGneD.js} +3 -3
- package/dist/{outbound-adapter-DuRqAQXK.js → outbound-adapter-DkT2vUE9.js} +34 -13
- package/dist/{pipeline.runtime-Bbfd5VFW.js → pipeline.runtime-CRRng_Nw.js} +74 -137
- package/dist/{policy-BKXSxrIS.js → policy-BoP6t88v.js} +1 -1
- package/dist/{probe-BVA65leh.js → probe-4_aHtVT3.js} +2 -21
- package/dist/{provider-CUUiwsg2.js → provider-D4nDgxCh.js} +187 -63
- package/dist/{relay-source-mhpMMRG-.js → relay-source-CEmze11m.js} +1 -1
- package/dist/{replies-SnWyXcsL.js → replies-D9XMM_S0.js} +14 -4
- package/dist/{resolve-channels-BSpqC8jU.js → resolve-channels-DSamDgVs.js} +1 -1
- package/dist/{resolve-users-Dvz9pDe0.js → resolve-users-CIzwbaJR.js} +1 -1
- package/dist/runtime-api.js +11 -11
- package/dist/{scopes-BSk4GZvZ.js → scopes-BBrUzpBH.js} +1 -1
- package/dist/{send-CtnOxKCc.js → send-DtjEnlLh.js} +37 -29
- package/dist/{send.runtime-kYctMHSd.js → send.runtime-DQeNKa2J.js} +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-BPFfp6So.js → setup-surface-CsBCM4rP.js} +6 -6
- package/dist/{shared-DJBaslN7.js → shared-D9GeeR9K.js} +24 -6
- package/dist/{slack-client-kind-BXyOOICI.js → slack-client-kind-hSfjXyUM.js} +1 -1
- package/dist/{slash-dispatch.runtime-Cf2FTrnf.js → slash-dispatch.runtime-Chr3YHnT.js} +2 -2
- package/node_modules/@slack/bolt/node_modules/@types/node/README.md +1 -1
- package/node_modules/@slack/bolt/node_modules/@types/node/child_process.d.ts +0 -1
- package/node_modules/@slack/bolt/node_modules/@types/node/crypto.d.ts +6 -6
- package/node_modules/@slack/bolt/node_modules/@types/node/dns/promises.d.ts +5 -5
- package/node_modules/@slack/bolt/node_modules/@types/node/dns.d.ts +5 -5
- package/node_modules/@slack/bolt/node_modules/@types/node/fs.d.ts +7 -0
- package/node_modules/@slack/bolt/node_modules/@types/node/http.d.ts +30 -0
- package/node_modules/@slack/bolt/node_modules/@types/node/http2.d.ts +4 -4
- package/node_modules/@slack/bolt/node_modules/@types/node/os.d.ts +30 -30
- package/node_modules/@slack/bolt/node_modules/@types/node/package.json +2 -2
- package/node_modules/@slack/bolt/node_modules/@types/node/perf_hooks.d.ts +2 -1
- package/node_modules/@slack/bolt/node_modules/@types/node/process.d.ts +42 -43
- package/node_modules/@slack/bolt/node_modules/@types/node/quic.d.ts +1049 -84
- package/node_modules/@slack/bolt/node_modules/@types/node/sqlite.d.ts +14 -1
- package/node_modules/@slack/bolt/node_modules/@types/node/stream/iter.d.ts +3 -2
- package/node_modules/@slack/bolt/node_modules/@types/node/test.d.ts +61 -0
- package/node_modules/@slack/bolt/node_modules/@types/node/v8.d.ts +20 -23
- package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/README.md +2 -0
- package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/dist/index.d.ts +20 -0
- package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/dist/index.js +20 -14
- package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/dist/index.js.map +1 -1
- package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/package.json +1 -1
- package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/README.md +2 -0
- package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.d.ts +20 -0
- package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.js +20 -14
- package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.js.map +1 -1
- package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/package.json +1 -1
- package/node_modules/@slack/socket-mode/node_modules/@types/node/README.md +1 -1
- package/node_modules/@slack/socket-mode/node_modules/@types/node/child_process.d.ts +0 -1
- package/node_modules/@slack/socket-mode/node_modules/@types/node/crypto.d.ts +6 -6
- package/node_modules/@slack/socket-mode/node_modules/@types/node/dns/promises.d.ts +5 -5
- package/node_modules/@slack/socket-mode/node_modules/@types/node/dns.d.ts +5 -5
- package/node_modules/@slack/socket-mode/node_modules/@types/node/fs.d.ts +7 -0
- package/node_modules/@slack/socket-mode/node_modules/@types/node/http.d.ts +30 -0
- package/node_modules/@slack/socket-mode/node_modules/@types/node/http2.d.ts +4 -4
- package/node_modules/@slack/socket-mode/node_modules/@types/node/os.d.ts +30 -30
- package/node_modules/@slack/socket-mode/node_modules/@types/node/package.json +2 -2
- package/node_modules/@slack/socket-mode/node_modules/@types/node/perf_hooks.d.ts +2 -1
- package/node_modules/@slack/socket-mode/node_modules/@types/node/process.d.ts +42 -43
- package/node_modules/@slack/socket-mode/node_modules/@types/node/quic.d.ts +1049 -84
- package/node_modules/@slack/socket-mode/node_modules/@types/node/sqlite.d.ts +14 -1
- package/node_modules/@slack/socket-mode/node_modules/@types/node/stream/iter.d.ts +3 -2
- package/node_modules/@slack/socket-mode/node_modules/@types/node/test.d.ts +61 -0
- package/node_modules/@slack/socket-mode/node_modules/@types/node/v8.d.ts +20 -23
- package/node_modules/@slack/web-api/node_modules/@types/node/README.md +1 -1
- package/node_modules/@slack/web-api/node_modules/@types/node/child_process.d.ts +0 -1
- package/node_modules/@slack/web-api/node_modules/@types/node/crypto.d.ts +6 -6
- package/node_modules/@slack/web-api/node_modules/@types/node/dns/promises.d.ts +5 -5
- package/node_modules/@slack/web-api/node_modules/@types/node/dns.d.ts +5 -5
- package/node_modules/@slack/web-api/node_modules/@types/node/fs.d.ts +7 -0
- package/node_modules/@slack/web-api/node_modules/@types/node/http.d.ts +30 -0
- package/node_modules/@slack/web-api/node_modules/@types/node/http2.d.ts +4 -4
- package/node_modules/@slack/web-api/node_modules/@types/node/os.d.ts +30 -30
- package/node_modules/@slack/web-api/node_modules/@types/node/package.json +2 -2
- package/node_modules/@slack/web-api/node_modules/@types/node/perf_hooks.d.ts +2 -1
- package/node_modules/@slack/web-api/node_modules/@types/node/process.d.ts +42 -43
- package/node_modules/@slack/web-api/node_modules/@types/node/quic.d.ts +1049 -84
- package/node_modules/@slack/web-api/node_modules/@types/node/sqlite.d.ts +14 -1
- package/node_modules/@slack/web-api/node_modules/@types/node/stream/iter.d.ts +3 -2
- package/node_modules/@slack/web-api/node_modules/@types/node/test.d.ts +61 -0
- package/node_modules/@slack/web-api/node_modules/@types/node/v8.d.ts +20 -23
- package/node_modules/typebox/build/format/date.d.mts +1 -1
- package/node_modules/typebox/build/format/date.mjs +1 -1
- package/node_modules/typebox/build/format/date_time.d.mts +2 -2
- package/node_modules/typebox/build/format/date_time.mjs +3 -3
- package/node_modules/typebox/build/format/email.d.mts +1 -1
- package/node_modules/typebox/build/format/email.mjs +2 -2
- package/node_modules/typebox/build/format/hostname.mjs +2 -10
- package/node_modules/typebox/build/format/idn_email.d.mts +1 -1
- package/node_modules/typebox/build/format/idn_email.mjs +3 -3
- package/node_modules/typebox/build/format/idn_hostname.d.mts +1 -0
- package/node_modules/typebox/build/format/idn_hostname.mjs +3 -11
- package/node_modules/typebox/build/format/idna/format/bidi.d.mts +3 -0
- package/node_modules/typebox/build/format/idna/format/bidi.mjs +98 -0
- package/node_modules/typebox/build/format/idna/format/puny.d.mts +3 -0
- package/node_modules/typebox/build/format/idna/format/puny.mjs +144 -0
- package/node_modules/typebox/build/format/idna/hostname.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/hostname.mjs +16 -0
- package/node_modules/typebox/build/format/idna/idn-hostname.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/idn-hostname.mjs +23 -0
- package/node_modules/typebox/build/format/idna/index.d.mts +2 -0
- package/node_modules/typebox/build/format/idna/index.mjs +2 -0
- package/node_modules/typebox/build/format/idna/label/ascii.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/label/ascii.mjs +9 -0
- package/node_modules/typebox/build/format/idna/label/puny.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/label/puny.mjs +28 -0
- package/node_modules/typebox/build/format/idna/label/unicode.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/label/unicode.mjs +106 -0
- package/node_modules/typebox/build/format/idna/pattern/pattern.d.mts +30 -0
- package/node_modules/typebox/build/format/idna/pattern/pattern.mjs +70 -0
- package/node_modules/typebox/build/format/ipv4.d.mts +0 -1
- package/node_modules/typebox/build/format/ipv4.mjs +2 -32
- package/node_modules/typebox/build/format/ipv6.mjs +2 -61
- package/node_modules/typebox/build/format/iri.d.mts +2 -2
- package/node_modules/typebox/build/format/iri.mjs +26 -8
- package/node_modules/typebox/build/format/iri_reference.d.mts +2 -2
- package/node_modules/typebox/build/format/iri_reference.mjs +9 -55
- package/node_modules/typebox/build/format/regex.d.mts +1 -2
- package/node_modules/typebox/build/format/regex.mjs +2 -6
- package/node_modules/typebox/build/format/time.d.mts +2 -2
- package/node_modules/typebox/build/format/time.mjs +19 -14
- package/node_modules/typebox/build/format/uri.d.mts +1 -1
- package/node_modules/typebox/build/format/uri.mjs +3 -130
- package/node_modules/typebox/build/format/uri_reference.d.mts +1 -1
- package/node_modules/typebox/build/format/uri_reference.mjs +2 -3
- package/node_modules/typebox/build/format/uri_template.d.mts +2 -3
- package/node_modules/typebox/build/format/uri_template.mjs +4 -5
- package/node_modules/typebox/build/format/url.d.mts +3 -3
- package/node_modules/typebox/build/format/url.mjs +4 -5
- package/node_modules/typebox/build/guard/emit.d.mts +3 -1
- package/node_modules/typebox/build/guard/emit.mjs +12 -5
- package/node_modules/typebox/build/guard/guard.d.mts +8 -2
- package/node_modules/typebox/build/guard/guard.mjs +25 -4
- package/node_modules/typebox/build/guard/string.d.mts +2 -2
- package/node_modules/typebox/build/guard/string.mjs +7 -7
- package/node_modules/typebox/build/schema/engine/_context.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/_functions.mjs +1 -2
- package/node_modules/typebox/build/schema/engine/_regexp.d.mts +2 -0
- package/node_modules/typebox/build/schema/engine/_regexp.mjs +4 -0
- package/node_modules/typebox/build/schema/engine/_stack.mjs +12 -13
- package/node_modules/typebox/build/schema/engine/additionalItems.mjs +17 -7
- package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +4 -3
- package/node_modules/typebox/build/schema/engine/contains.mjs +18 -6
- package/node_modules/typebox/build/schema/engine/enum.mjs +1 -1
- package/node_modules/typebox/build/schema/engine/items.mjs +26 -6
- package/node_modules/typebox/build/schema/engine/maxContains.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/minContains.mjs +14 -4
- package/node_modules/typebox/build/schema/engine/not.mjs +4 -2
- package/node_modules/typebox/build/schema/engine/oneOf.mjs +7 -6
- package/node_modules/typebox/build/schema/engine/pattern.mjs +3 -2
- package/node_modules/typebox/build/schema/engine/patternProperties.mjs +4 -3
- package/node_modules/typebox/build/schema/engine/ref.mjs +1 -7
- package/node_modules/typebox/build/schema/engine/schema.mjs +13 -4
- package/node_modules/typebox/build/schema/engine/type.mjs +1 -1
- package/node_modules/typebox/build/schema/resolve/resolve.d.mts +4 -1
- package/node_modules/typebox/build/schema/resolve/resolve.mjs +202 -1
- package/node_modules/typebox/build/schema/static/propertyNames.d.mts +5 -0
- package/node_modules/typebox/build/schema/static/propertyNames.mjs +3 -0
- package/node_modules/typebox/build/schema/static/schema.d.mts +3 -0
- package/node_modules/typebox/build/schema/types/index.d.mts +0 -2
- package/node_modules/typebox/build/schema/types/index.mjs +0 -2
- package/node_modules/typebox/build/system/memory/clone.mjs +14 -11
- package/node_modules/typebox/build/system/memory/discard.mjs +6 -5
- package/node_modules/typebox/build/system/settings/settings.d.mts +9 -0
- package/node_modules/typebox/build/system/settings/settings.mjs +2 -0
- package/node_modules/typebox/build/type/engine/call/distribute_arguments.d.mts +6 -1
- package/node_modules/typebox/build/type/engine/call/distribute_arguments.mjs +16 -3
- package/node_modules/typebox/build/type/engine/call/instantiate.mjs +34 -4
- package/node_modules/typebox/build/type/engine/evaluate/broaden.d.mts +5 -5
- package/node_modules/typebox/build/type/engine/evaluate/broaden.mjs +20 -26
- package/node_modules/typebox/build/type/engine/evaluate/compare.d.mts +6 -10
- package/node_modules/typebox/build/type/engine/evaluate/compare.mjs +9 -13
- package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +7 -4
- package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +12 -19
- package/node_modules/typebox/build/type/engine/evaluate/distribute.d.mts +4 -20
- package/node_modules/typebox/build/type/engine/evaluate/distribute.mjs +8 -20
- package/node_modules/typebox/build/type/engine/evaluate/evaluate.d.mts +4 -4
- package/node_modules/typebox/build/type/engine/evaluate/evaluate.mjs +11 -8
- package/node_modules/typebox/build/type/engine/evaluate/flatten.d.mts +1 -1
- package/node_modules/typebox/build/type/engine/evaluate/flatten.mjs +3 -4
- package/node_modules/typebox/build/type/engine/evaluate/narrow.d.mts +17 -2
- package/node_modules/typebox/build/type/engine/evaluate/narrow.mjs +26 -6
- package/node_modules/typebox/build/type/engine/exclude/operation.mjs +3 -4
- package/node_modules/typebox/build/type/engine/extract/operation.d.mts +1 -1
- package/node_modules/typebox/build/type/engine/extract/operation.mjs +3 -4
- package/node_modules/typebox/build/type/engine/priority/priority.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/priority/priority.mjs +3 -4
- package/node_modules/typebox/build/type/script/mapping.d.mts +32 -29
- package/node_modules/typebox/build/type/script/mapping.mjs +18 -25
- package/node_modules/typebox/build/type/script/parser.d.mts +19 -25
- package/node_modules/typebox/build/type/script/parser.mjs +27 -23
- package/node_modules/typebox/build/value/errors/errors.d.mts +2 -2
- package/node_modules/typebox/build/value/errors/errors.mjs +1 -1
- package/node_modules/typebox/package.json +27 -27
- package/node_modules/typebox/readme.md +79 -82
- package/node_modules/ws/lib/permessage-deflate.js +3 -1
- package/node_modules/ws/package.json +1 -1
- package/package.json +9 -7
- package/dist/account-configured-BwfXBo_F.js +0 -14
- package/dist/account-inspect-YJvFBbCR.js +0 -89
- package/dist/action-runtime.runtime-JtoOK9l5.js +0 -2
- package/dist/actions.runtime-CYLsYRai.js +0 -2
- package/dist/runtime-api-DBi7xc_g.js +0 -10
- package/node_modules/typebox/build/format/_idna.d.mts +0 -2
- package/node_modules/typebox/build/format/_idna.mjs +0 -246
- package/node_modules/typebox/build/format/_puny.d.mts +0 -1
- package/node_modules/typebox/build/format/_puny.mjs +0 -77
- package/node_modules/typebox/build/schema/resolve/ref.d.mts +0 -3
- package/node_modules/typebox/build/schema/resolve/ref.mjs +0 -146
- package/node_modules/typebox/build/schema/types/contentEncoding.d.mts +0 -9
- package/node_modules/typebox/build/schema/types/contentEncoding.mjs +0 -13
- package/node_modules/typebox/build/schema/types/contentMediaType.d.mts +0 -9
- package/node_modules/typebox/build/schema/types/contentMediaType.mjs +0 -13
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as isSlackPluginAccountConfigured } from "./account-configured-sUohAxZr.js";
|
|
2
|
+
import { a as resolveSlackAccount, i as resolveDefaultSlackAccountId, n as listSlackAccountIds, o as resolveSlackAccountAllowFrom, r as mergeSlackAccountConfig } from "./accounts-Dm_H77gH.js";
|
|
2
3
|
import { a as parseSlackTarget, n as formatSlackTarget, t as canonicalizeSlackApiTargetId } from "./target-parsing-BnMD2ZqZ.js";
|
|
3
4
|
import { t as slackContextTargetsMatch } from "./targets-Cx5W_n3W.js";
|
|
4
|
-
import { t as isSlackPluginAccountConfigured } from "./account-configured-BwfXBo_F.js";
|
|
5
5
|
import { normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
|
|
6
6
|
import { asOptionalRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringifiedOptionalString, readNonBlankString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
7
7
|
import { normalizeMessageChannel } from "openclaw/plugin-sdk/routing";
|
|
@@ -13,12 +13,12 @@ import { createChannelApprovalAuth, resolveApprovalApprovers } from "openclaw/pl
|
|
|
13
13
|
import { createChannelExecApprovalProfile, isChannelExecApprovalClientEnabledFromConfig, isChannelExecApprovalTargetRecipient, matchesApprovalRequestFilters } from "openclaw/plugin-sdk/approval-client-runtime";
|
|
14
14
|
import { channelRouteTargetsMatchExact, stringifyRouteThreadId } from "openclaw/plugin-sdk/channel-route";
|
|
15
15
|
import { resolveGlobalMap } from "openclaw/plugin-sdk/global-singleton";
|
|
16
|
-
import {
|
|
16
|
+
import { legacyInteractiveReplyToPresentation, normalizeMessagePresentation, renderMessagePresentationChartFallbackText, renderMessagePresentationFallbackText, renderMessagePresentationTableFallbackText, resolveMessagePresentationButtonAction, resolveMessagePresentationOptionAction } from "openclaw/plugin-sdk/interactive-runtime";
|
|
17
17
|
import { parseExecApprovalCommandText } from "openclaw/plugin-sdk/approval-reply-runtime";
|
|
18
18
|
import { buildApprovalResolutionRef } from "openclaw/plugin-sdk/approval-reference-runtime";
|
|
19
|
+
import { eastAsianWidthType } from "get-east-asian-width";
|
|
19
20
|
import { questionGatewayRuntime } from "openclaw/plugin-sdk/question-gateway-runtime";
|
|
20
21
|
import { sliceUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
21
|
-
import { eastAsianWidthType } from "get-east-asian-width";
|
|
22
22
|
import { readResponseTextLimited } from "openclaw/plugin-sdk/provider-http";
|
|
23
23
|
import { compileAllowlist, resolveCompiledAllowlistMatch } from "openclaw/plugin-sdk/allow-from";
|
|
24
24
|
import { normalizeHyphenSlug, normalizeStringEntries as normalizeStringEntries$1, normalizeStringEntriesLower } from "openclaw/plugin-sdk/string-normalization-runtime";
|
|
@@ -924,109 +924,460 @@ function renderSlackDataVisualizationMrkdwnFallbackText(value) {
|
|
|
924
924
|
return typeof block.title === "string" && block.title.trim() ? escapeSlackMrkdwn(block.title.trim()) : void 0;
|
|
925
925
|
}
|
|
926
926
|
//#endregion
|
|
927
|
-
//#region extensions/slack/src/
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
function encodeSlackQuestionAction(action) {
|
|
931
|
-
if (!QUESTION_RECORD_ID_PATTERN.test(action.questionId) || !Number.isInteger(action.optionIndex) || action.optionIndex < 0 || action.optionIndex > 3) return;
|
|
932
|
-
const value = `${SLACK_QUESTION_VALUE_PREFIX}${action.questionId}:${action.optionIndex}`;
|
|
933
|
-
return value.length <= 2e3 ? value : void 0;
|
|
927
|
+
//#region extensions/slack/src/format.ts
|
|
928
|
+
function escapeSlackMrkdwnSegment(text) {
|
|
929
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
934
930
|
}
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
optionIndex: Number(match[2])
|
|
941
|
-
} : null;
|
|
931
|
+
const SLACK_ANGLE_TOKEN_RE = /<[^>\n]+>/g;
|
|
932
|
+
function isAllowedSlackAngleToken(token) {
|
|
933
|
+
if (!token.startsWith("<") || !token.endsWith(">")) return false;
|
|
934
|
+
const inner = token.slice(1, -1);
|
|
935
|
+
return inner.startsWith("@") || inner.startsWith("#") || inner.startsWith("!") || inner.startsWith("mailto:") || inner.startsWith("tel:") || inner.startsWith("http://") || inner.startsWith("https://") || inner.startsWith("slack://");
|
|
942
936
|
}
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
return;
|
|
937
|
+
function escapeSlackMrkdwnContent(text) {
|
|
938
|
+
if (!text) return "";
|
|
939
|
+
if (!text.includes("&") && !text.includes("<") && !text.includes(">")) return text;
|
|
940
|
+
SLACK_ANGLE_TOKEN_RE.lastIndex = 0;
|
|
941
|
+
const out = [];
|
|
942
|
+
let lastIndex = 0;
|
|
943
|
+
for (let match = SLACK_ANGLE_TOKEN_RE.exec(text); match; match = SLACK_ANGLE_TOKEN_RE.exec(text)) {
|
|
944
|
+
const matchIndex = match.index ?? 0;
|
|
945
|
+
out.push(escapeSlackMrkdwnSegment(text.slice(lastIndex, matchIndex)));
|
|
946
|
+
const token = match[0] ?? "";
|
|
947
|
+
out.push(isAllowedSlackAngleToken(token) ? token : escapeSlackMrkdwnSegment(token));
|
|
948
|
+
lastIndex = matchIndex + token.length;
|
|
956
949
|
}
|
|
957
|
-
|
|
950
|
+
out.push(escapeSlackMrkdwnSegment(text.slice(lastIndex)));
|
|
951
|
+
return out.join("");
|
|
958
952
|
}
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
const SLACK_CALLBACK_SELECT_ACTION_ID = "openclaw:callback_select";
|
|
967
|
-
const SLACK_APPROVAL_BUTTON_ACTION_ID = "openclaw:approval_button";
|
|
968
|
-
const SLACK_APPROVAL_SELECT_ACTION_ID = "openclaw:approval_select";
|
|
969
|
-
const SLACK_QUESTION_BUTTON_ACTION_ID = "openclaw:question_button";
|
|
970
|
-
const SLACK_QUESTION_FINALIZATION_BLOCKS = Symbol("slackQuestionFinalizationBlocks");
|
|
971
|
-
function isSlackQuestionActionId(actionId) {
|
|
972
|
-
return actionId === "openclaw:question_button" || actionId.startsWith(`openclaw:question_button:`);
|
|
953
|
+
function escapeSlackMrkdwnText(text) {
|
|
954
|
+
if (!text) return "";
|
|
955
|
+
if (!text.includes("&") && !text.includes("<") && !text.includes(">")) return text;
|
|
956
|
+
return text.split("\n").map((line) => {
|
|
957
|
+
if (line.startsWith("> ")) return `> ${escapeSlackMrkdwnContent(line.slice(2))}`;
|
|
958
|
+
return escapeSlackMrkdwnContent(line);
|
|
959
|
+
}).join("\n");
|
|
973
960
|
}
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
961
|
+
function buildSlackLink(link, text) {
|
|
962
|
+
const href = link.href.trim();
|
|
963
|
+
if (!href) return null;
|
|
964
|
+
const trimmedLabel = text.slice(link.start, link.end).trim();
|
|
965
|
+
const comparableHref = href.startsWith("mailto:") ? href.slice(7) : href;
|
|
966
|
+
if (!(trimmedLabel.length > 0 && trimmedLabel !== href && trimmedLabel !== comparableHref)) return null;
|
|
967
|
+
const safeHref = escapeSlackMrkdwnSegment(href);
|
|
968
|
+
return {
|
|
969
|
+
start: link.start,
|
|
970
|
+
end: link.end,
|
|
971
|
+
open: `<${safeHref}|`,
|
|
972
|
+
close: ">"
|
|
973
|
+
};
|
|
980
974
|
}
|
|
981
|
-
|
|
982
|
-
|
|
975
|
+
const SLACK_MRKDWN_WORD_CHARACTER_RE = /[\p{L}\p{M}\p{N}_]/u;
|
|
976
|
+
const SLACK_MRKDWN_PUNCTUATION_RE = /\p{P}/u;
|
|
977
|
+
const SLACK_MRKDWN_SYMBOL_RE = /\p{S}/u;
|
|
978
|
+
const SLACK_MRKDWN_CJK_SCRIPT_RE = /[\p{Script_Extensions=Han}\p{Script_Extensions=Hiragana}\p{Script_Extensions=Katakana}\p{Script_Extensions=Hangul}]/u;
|
|
979
|
+
const SLACK_MRKDWN_EMOJI_PRESENTATION_RE = /\p{Emoji_Presentation}/u;
|
|
980
|
+
function getCodePointBefore(text, index) {
|
|
981
|
+
if (index <= 0) return "";
|
|
982
|
+
const lastCodeUnit = text.charCodeAt(index - 1);
|
|
983
|
+
if (lastCodeUnit >= 56320 && lastCodeUnit <= 57343 && index > 1) {
|
|
984
|
+
const previousCodeUnit = text.charCodeAt(index - 2);
|
|
985
|
+
if (previousCodeUnit >= 55296 && previousCodeUnit <= 56319) return text.slice(index - 2, index);
|
|
986
|
+
}
|
|
987
|
+
return text[index - 1] ?? "";
|
|
983
988
|
}
|
|
984
|
-
function
|
|
985
|
-
|
|
989
|
+
function getCodePointAt(text, index) {
|
|
990
|
+
const codePoint = text.codePointAt(index);
|
|
991
|
+
return codePoint === void 0 ? "" : String.fromCodePoint(codePoint);
|
|
986
992
|
}
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
const
|
|
991
|
-
if (
|
|
992
|
-
|
|
993
|
-
return
|
|
993
|
+
function isSlackCjkPunctuation(character) {
|
|
994
|
+
if (!SLACK_MRKDWN_PUNCTUATION_RE.test(character)) return false;
|
|
995
|
+
if (SLACK_MRKDWN_CJK_SCRIPT_RE.test(character)) return true;
|
|
996
|
+
const codePoint = character.codePointAt(0);
|
|
997
|
+
if (codePoint === void 0) return false;
|
|
998
|
+
const width = eastAsianWidthType(codePoint);
|
|
999
|
+
return width === "fullwidth" || width === "halfwidth" || width === "wide" && !SLACK_MRKDWN_EMOJI_PRESENTATION_RE.test(character);
|
|
994
1000
|
}
|
|
995
|
-
function
|
|
996
|
-
|
|
1001
|
+
function isUnsafeSlackEmphasisBoundary(character) {
|
|
1002
|
+
if (SLACK_MRKDWN_WORD_CHARACTER_RE.test(character)) return true;
|
|
1003
|
+
const codePoint = character.codePointAt(0);
|
|
1004
|
+
if (codePoint === void 0 || codePoint <= 127) return false;
|
|
1005
|
+
return SLACK_MRKDWN_SYMBOL_RE.test(character) || isSlackCjkPunctuation(character);
|
|
997
1006
|
}
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1007
|
+
function makeSlackEmphasisStylesSafe(ir) {
|
|
1008
|
+
const styles = ir.styles.filter((span) => {
|
|
1009
|
+
if (span.style !== "italic" && span.style !== "bold") return true;
|
|
1010
|
+
return !isUnsafeSlackEmphasisBoundary(getCodePointBefore(ir.text, span.start)) && !isUnsafeSlackEmphasisBoundary(getCodePointAt(ir.text, span.end));
|
|
1011
|
+
});
|
|
1012
|
+
return styles.length === ir.styles.length ? ir : {
|
|
1013
|
+
...ir,
|
|
1014
|
+
styles
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
const SLACK_FORMAT_PROFILE = FormatCapabilityProfile.define({
|
|
1018
|
+
mechanism: "markdown",
|
|
1019
|
+
constructs: {
|
|
1020
|
+
underline: "strip",
|
|
1021
|
+
spoiler: "fallback",
|
|
1022
|
+
codeLanguage: "fallback",
|
|
1023
|
+
heading: "fallback",
|
|
1024
|
+
bulletList: "fallback",
|
|
1025
|
+
orderedList: "fallback",
|
|
1026
|
+
taskList: "fallback",
|
|
1027
|
+
table: "fallback",
|
|
1028
|
+
image: "fallback"
|
|
1029
|
+
},
|
|
1030
|
+
chunk: {
|
|
1031
|
+
limit: 4e3,
|
|
1032
|
+
unit: "chars",
|
|
1033
|
+
hardCap: 4e4
|
|
1013
1034
|
}
|
|
1014
|
-
|
|
1035
|
+
});
|
|
1036
|
+
const SLACK_ASSISTANT_TRANSCRIPT_PREFIX = "`Assistant:` ";
|
|
1037
|
+
function tokenizeSlackMrkdwn(text) {
|
|
1038
|
+
const tokens = [];
|
|
1039
|
+
for (let index = 0; index < text.length;) {
|
|
1040
|
+
if (text.startsWith("```", index)) {
|
|
1041
|
+
tokens.push("```");
|
|
1042
|
+
index += 3;
|
|
1043
|
+
continue;
|
|
1044
|
+
}
|
|
1045
|
+
const entity = [
|
|
1046
|
+
"&",
|
|
1047
|
+
"<",
|
|
1048
|
+
">"
|
|
1049
|
+
].find((candidate) => text.startsWith(candidate, index));
|
|
1050
|
+
if (entity) {
|
|
1051
|
+
tokens.push(entity);
|
|
1052
|
+
index += entity.length;
|
|
1053
|
+
continue;
|
|
1054
|
+
}
|
|
1055
|
+
if (text[index] === "<") {
|
|
1056
|
+
const end = text.indexOf(">", index + 1);
|
|
1057
|
+
const angleToken = end >= 0 ? text.slice(index, end + 1) : void 0;
|
|
1058
|
+
if (angleToken && !angleToken.includes("\n") && isAllowedSlackAngleToken(angleToken)) {
|
|
1059
|
+
tokens.push(angleToken);
|
|
1060
|
+
index += angleToken.length;
|
|
1061
|
+
continue;
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
const codePoint = text.codePointAt(index);
|
|
1065
|
+
if (codePoint === void 0) break;
|
|
1066
|
+
const character = String.fromCodePoint(codePoint);
|
|
1067
|
+
index += character.length;
|
|
1068
|
+
if (character === "\\" && index < text.length) {
|
|
1069
|
+
const escapedCodePoint = text.codePointAt(index);
|
|
1070
|
+
if (escapedCodePoint !== void 0) {
|
|
1071
|
+
const escapedCharacter = String.fromCodePoint(escapedCodePoint);
|
|
1072
|
+
tokens.push(character + escapedCharacter);
|
|
1073
|
+
index += escapedCharacter.length;
|
|
1074
|
+
continue;
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
tokens.push(character);
|
|
1078
|
+
}
|
|
1079
|
+
return tokens;
|
|
1015
1080
|
}
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
return `${SLACK_REPLY_BUTTON_ACTION_ID}:${String(buttonIndex)}:${String(choiceIndex + 1)}`;
|
|
1081
|
+
function resolveSlackCodeMarkerTransition(active, token) {
|
|
1082
|
+
if (token === "```" && active !== "`") return active === "```" ? void 0 : "```";
|
|
1083
|
+
if (token === "`" && active !== "```") return active === "`" ? void 0 : "`";
|
|
1084
|
+
return null;
|
|
1021
1085
|
}
|
|
1022
|
-
function
|
|
1023
|
-
return
|
|
1086
|
+
function maskSlackExcludedText(text) {
|
|
1087
|
+
return text.split("\n").map((line) => line.trim() ? `x${" ".repeat(Math.max(0, line.length - 1))}` : " ".repeat(line.length)).join("\n");
|
|
1024
1088
|
}
|
|
1025
|
-
function
|
|
1026
|
-
|
|
1089
|
+
function maskSlackExcludedRanges(projection) {
|
|
1090
|
+
let masked = "";
|
|
1091
|
+
let cursor = 0;
|
|
1092
|
+
for (const range of projection.excludedRanges) {
|
|
1093
|
+
masked += projection.text.slice(cursor, range.start);
|
|
1094
|
+
masked += maskSlackExcludedText(projection.text.slice(range.start, range.end));
|
|
1095
|
+
cursor = range.end;
|
|
1096
|
+
}
|
|
1097
|
+
return masked + projection.text.slice(cursor);
|
|
1027
1098
|
}
|
|
1028
|
-
function
|
|
1029
|
-
return
|
|
1099
|
+
function slackProjectionHasRoleHeader(projection) {
|
|
1100
|
+
return Boolean(markdownToIR(maskSlackExcludedRanges(projection), {
|
|
1101
|
+
assistantTranscriptRoleHeaders: true,
|
|
1102
|
+
autolink: false,
|
|
1103
|
+
blockquotePrefix: "",
|
|
1104
|
+
headingStyle: "none",
|
|
1105
|
+
linkify: false,
|
|
1106
|
+
tableMode: "off"
|
|
1107
|
+
}).annotations?.some((annotation) => annotation.type === "assistant_transcript_role"));
|
|
1108
|
+
}
|
|
1109
|
+
function decodeSlackMrkdwnEntities(text) {
|
|
1110
|
+
return text.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
1111
|
+
}
|
|
1112
|
+
function projectSlackAngleToken(token, dateDisplay) {
|
|
1113
|
+
const inner = token.slice(1, -1);
|
|
1114
|
+
if (inner.startsWith("!date^")) {
|
|
1115
|
+
const fallbackSeparator = inner.indexOf("|");
|
|
1116
|
+
const tokenString = (fallbackSeparator === -1 ? inner : inner.slice(0, fallbackSeparator)).split("^")[2] ?? "";
|
|
1117
|
+
const fallback = fallbackSeparator === -1 ? "" : inner.slice(fallbackSeparator + 1);
|
|
1118
|
+
return decodeSlackMrkdwnEntities(dateDisplay === "fallback" ? fallback || tokenString : tokenString || fallback);
|
|
1119
|
+
}
|
|
1120
|
+
const labelSeparator = inner.indexOf("|");
|
|
1121
|
+
if (labelSeparator >= 0) return decodeSlackMrkdwnEntities(inner.slice(labelSeparator + 1));
|
|
1122
|
+
if (inner.startsWith("@")) return "@";
|
|
1123
|
+
if (inner.startsWith("#")) return "#";
|
|
1124
|
+
if (inner.startsWith("!")) return "!";
|
|
1125
|
+
return decodeSlackMrkdwnEntities(inner);
|
|
1126
|
+
}
|
|
1127
|
+
function appendSlackVisibleProjection(projection, visible, excluded) {
|
|
1128
|
+
if (!visible) return;
|
|
1129
|
+
const start = projection.text.length;
|
|
1130
|
+
projection.text += visible;
|
|
1131
|
+
if (!excluded) return;
|
|
1132
|
+
const previous = projection.excludedRanges.at(-1);
|
|
1133
|
+
if (previous?.end === start) previous.end = projection.text.length;
|
|
1134
|
+
else projection.excludedRanges.push({
|
|
1135
|
+
start,
|
|
1136
|
+
end: projection.text.length
|
|
1137
|
+
});
|
|
1138
|
+
}
|
|
1139
|
+
function projectSlackMrkdwnVisibleText(text, dateDisplay) {
|
|
1140
|
+
const projection = {
|
|
1141
|
+
text: "",
|
|
1142
|
+
excludedRanges: []
|
|
1143
|
+
};
|
|
1144
|
+
let activeMarker;
|
|
1145
|
+
let lineHasVisibleContent = false;
|
|
1146
|
+
for (const token of tokenizeSlackMrkdwn(text)) {
|
|
1147
|
+
const transition = resolveSlackCodeMarkerTransition(activeMarker, token);
|
|
1148
|
+
if (transition !== null) {
|
|
1149
|
+
activeMarker = transition;
|
|
1150
|
+
continue;
|
|
1151
|
+
}
|
|
1152
|
+
let visible = token;
|
|
1153
|
+
if (isAllowedSlackAngleToken(token)) visible = activeMarker ? token : projectSlackAngleToken(token, dateDisplay);
|
|
1154
|
+
else if (token === "&" || token === "<" || token === ">") visible = decodeSlackMrkdwnEntities(token);
|
|
1155
|
+
else if (!activeMarker && (token === "*" || token === "_" || token === "~")) visible = "";
|
|
1156
|
+
else if (!activeMarker && token === ">" && !lineHasVisibleContent) visible = "";
|
|
1157
|
+
else if (token.startsWith("\\") && token.length > 1) visible = token.slice(1);
|
|
1158
|
+
appendSlackVisibleProjection(projection, visible, activeMarker !== void 0);
|
|
1159
|
+
for (const character of visible) if (character === "\n") lineHasVisibleContent = false;
|
|
1160
|
+
else if (character !== " " && character !== " " && character !== "\r") lineHasVisibleContent = true;
|
|
1161
|
+
}
|
|
1162
|
+
return projection;
|
|
1163
|
+
}
|
|
1164
|
+
function protectSlackAssistantTranscriptRoleHeaders(text) {
|
|
1165
|
+
if (text.startsWith(SLACK_ASSISTANT_TRANSCRIPT_PREFIX)) return text;
|
|
1166
|
+
const tokenProjection = projectSlackMrkdwnVisibleText(text, "token");
|
|
1167
|
+
const fallbackProjection = projectSlackMrkdwnVisibleText(text, "fallback");
|
|
1168
|
+
if (!slackProjectionHasRoleHeader(tokenProjection) && !slackProjectionHasRoleHeader(fallbackProjection)) return text;
|
|
1169
|
+
return `${SLACK_ASSISTANT_TRANSCRIPT_PREFIX}${text}`;
|
|
1170
|
+
}
|
|
1171
|
+
function buildSlackRenderOptions() {
|
|
1172
|
+
return {
|
|
1173
|
+
annotationMarkers: { assistant_transcript_role: {
|
|
1174
|
+
open: "`",
|
|
1175
|
+
close: "`",
|
|
1176
|
+
suppressNestedFormatting: true
|
|
1177
|
+
} },
|
|
1178
|
+
styleMarkers: {
|
|
1179
|
+
bold: {
|
|
1180
|
+
open: "*",
|
|
1181
|
+
close: "*"
|
|
1182
|
+
},
|
|
1183
|
+
italic: {
|
|
1184
|
+
open: "_",
|
|
1185
|
+
close: "_"
|
|
1186
|
+
},
|
|
1187
|
+
strikethrough: {
|
|
1188
|
+
open: "~",
|
|
1189
|
+
close: "~"
|
|
1190
|
+
},
|
|
1191
|
+
code: {
|
|
1192
|
+
open: "`",
|
|
1193
|
+
close: "`"
|
|
1194
|
+
},
|
|
1195
|
+
code_block: {
|
|
1196
|
+
open: "```\n",
|
|
1197
|
+
close: "```"
|
|
1198
|
+
}
|
|
1199
|
+
},
|
|
1200
|
+
escapeText: escapeSlackMrkdwnText,
|
|
1201
|
+
buildLink: buildSlackLink
|
|
1202
|
+
};
|
|
1203
|
+
}
|
|
1204
|
+
function markdownToSlackMrkdwn(markdown, options = {}) {
|
|
1205
|
+
return renderMarkdownWithMarkers(makeSlackEmphasisStylesSafe(markdownToIR(markdown ?? "", {
|
|
1206
|
+
assistantTranscriptRoleHeaders: true,
|
|
1207
|
+
linkify: false,
|
|
1208
|
+
autolink: false,
|
|
1209
|
+
headingStyle: "rich",
|
|
1210
|
+
blockquotePrefix: "> ",
|
|
1211
|
+
tableMode: options.tableMode
|
|
1212
|
+
})), buildSlackRenderOptions(), SLACK_FORMAT_PROFILE);
|
|
1213
|
+
}
|
|
1214
|
+
function normalizeSlackOutboundText(markdown) {
|
|
1215
|
+
return protectSlackAssistantTranscriptRoleHeaders(markdownToSlackMrkdwn(markdown ?? ""));
|
|
1216
|
+
}
|
|
1217
|
+
/** Chunk already-rendered Slack mrkdwn without splitting entities or code markers. */
|
|
1218
|
+
function chunkSlackMrkdwnText(text, limit) {
|
|
1219
|
+
if (text.length <= limit) return [text];
|
|
1220
|
+
if (!(text.includes("`") || text.includes("&") || text.includes("<") || text.includes(">") || (text.match(/<[^>\n]+>/gu)?.some(isAllowedSlackAngleToken) ?? false) || /\\[\s\S]/u.test(text))) return chunkTextForOutbound(text, limit, { preserveWhitespace: true });
|
|
1221
|
+
const chunks = [];
|
|
1222
|
+
let activeMarker;
|
|
1223
|
+
let content = "";
|
|
1224
|
+
const wrapper = (marker) => marker && limit > marker.length * 2 ? marker : void 0;
|
|
1225
|
+
const capacity = (marker) => limit - (wrapper(marker)?.length ?? 0);
|
|
1226
|
+
const flush = () => {
|
|
1227
|
+
const marker = wrapper(activeMarker);
|
|
1228
|
+
if (content && content !== marker) chunks.push(marker ? `${content}${marker}` : content);
|
|
1229
|
+
content = "";
|
|
1230
|
+
};
|
|
1231
|
+
for (const token of tokenizeSlackMrkdwn(text)) {
|
|
1232
|
+
const transition = resolveSlackCodeMarkerTransition(activeMarker, token);
|
|
1233
|
+
const nextMarker = transition === null ? activeMarker : transition;
|
|
1234
|
+
const sourceMarker = token === "`" || token === "```" ? token : void 0;
|
|
1235
|
+
if (transition !== null && sourceMarker && !wrapper(sourceMarker)) {
|
|
1236
|
+
activeMarker = nextMarker;
|
|
1237
|
+
continue;
|
|
1238
|
+
}
|
|
1239
|
+
if (content && content.length + token.length > capacity(nextMarker)) flush();
|
|
1240
|
+
activeMarker = nextMarker;
|
|
1241
|
+
if (!content && transition === void 0) continue;
|
|
1242
|
+
content ||= transition === null ? wrapper(activeMarker) ?? "" : "";
|
|
1243
|
+
const contentLimit = capacity(activeMarker) - (wrapper(activeMarker)?.length ?? 0);
|
|
1244
|
+
if (token.length > contentLimit) {
|
|
1245
|
+
flush();
|
|
1246
|
+
const marker = wrapper(activeMarker);
|
|
1247
|
+
if (activeMarker && isAllowedSlackAngleToken(token)) {
|
|
1248
|
+
if (marker) chunks.push(...chunkTextForOutbound(token, Math.max(1, Math.floor(contentLimit)), { preserveWhitespace: true }).map((fragment) => `${marker}${fragment}${marker}`));
|
|
1249
|
+
else chunks.push(...chunkTextForOutbound(escapeSlackMrkdwnSegment(token), Math.max(1, Math.floor(limit)), { preserveWhitespace: true }));
|
|
1250
|
+
continue;
|
|
1251
|
+
}
|
|
1252
|
+
chunks.push(...token.length <= limit ? [token] : chunkTextForOutbound(token, limit));
|
|
1253
|
+
continue;
|
|
1254
|
+
}
|
|
1255
|
+
content += token;
|
|
1256
|
+
}
|
|
1257
|
+
flush();
|
|
1258
|
+
return chunks;
|
|
1259
|
+
}
|
|
1260
|
+
function markdownToSlackMrkdwnChunks(markdown, limit, options = {}) {
|
|
1261
|
+
const ir = makeSlackEmphasisStylesSafe(markdownToIR(markdown ?? "", {
|
|
1262
|
+
assistantTranscriptRoleHeaders: true,
|
|
1263
|
+
linkify: false,
|
|
1264
|
+
autolink: false,
|
|
1265
|
+
headingStyle: "rich",
|
|
1266
|
+
blockquotePrefix: "> ",
|
|
1267
|
+
tableMode: options.tableMode
|
|
1268
|
+
}));
|
|
1269
|
+
const renderOptions = buildSlackRenderOptions();
|
|
1270
|
+
return renderMarkdownIRChunksWithinLimit({
|
|
1271
|
+
ir,
|
|
1272
|
+
limit,
|
|
1273
|
+
renderChunk: (chunk) => protectSlackAssistantTranscriptRoleHeaders(renderMarkdownWithMarkers(chunk, renderOptions, SLACK_FORMAT_PROFILE)),
|
|
1274
|
+
measureRendered: (rendered) => rendered.length
|
|
1275
|
+
}).map(({ rendered }) => rendered);
|
|
1276
|
+
}
|
|
1277
|
+
//#endregion
|
|
1278
|
+
//#region extensions/slack/src/question-actions.ts
|
|
1279
|
+
const SLACK_QUESTION_VALUE_PREFIX = "slq1:";
|
|
1280
|
+
const QUESTION_RECORD_ID_PATTERN = /^ask_[a-f0-9]{32}$/u;
|
|
1281
|
+
function encodeSlackQuestionAction(action) {
|
|
1282
|
+
if (!QUESTION_RECORD_ID_PATTERN.test(action.questionId) || !Number.isInteger(action.optionIndex) || action.optionIndex < 0 || action.optionIndex > 3) return;
|
|
1283
|
+
const value = `${SLACK_QUESTION_VALUE_PREFIX}${action.questionId}:${action.optionIndex}`;
|
|
1284
|
+
return value.length <= 2e3 ? value : void 0;
|
|
1285
|
+
}
|
|
1286
|
+
function decodeSlackQuestionAction(value) {
|
|
1287
|
+
if (typeof value !== "string" || value.length > 2e3) return null;
|
|
1288
|
+
const match = /^slq1:(ask_[a-f0-9]{32}):([0-3])$/u.exec(value);
|
|
1289
|
+
return match?.[1] && match[2] ? {
|
|
1290
|
+
questionId: match[1],
|
|
1291
|
+
optionIndex: Number(match[2])
|
|
1292
|
+
} : null;
|
|
1293
|
+
}
|
|
1294
|
+
async function resolveSlackQuestionAction(params) {
|
|
1295
|
+
let result;
|
|
1296
|
+
try {
|
|
1297
|
+
result = await (params.resolveQuestion ?? questionGatewayRuntime.resolveOption)({
|
|
1298
|
+
cfg: params.cfg,
|
|
1299
|
+
questionId: params.action.questionId,
|
|
1300
|
+
optionIndex: params.action.optionIndex,
|
|
1301
|
+
senderId: params.userId,
|
|
1302
|
+
clientDisplayName: `Slack question (${params.accountId})`
|
|
1303
|
+
});
|
|
1304
|
+
} catch {
|
|
1305
|
+
await params.respond("Could not submit this answer.").catch(() => {});
|
|
1306
|
+
return;
|
|
1307
|
+
}
|
|
1308
|
+
await params.respond(result.status === "answered" ? "Answer submitted." : "This question was already answered.").catch(() => {});
|
|
1309
|
+
}
|
|
1310
|
+
//#endregion
|
|
1311
|
+
//#region extensions/slack/src/reply-action-ids.ts
|
|
1312
|
+
const SLACK_REPLY_BUTTON_ACTION_ID = "openclaw:reply_button";
|
|
1313
|
+
const SLACK_REPLY_LINK_ACTION_ID = "openclaw:reply_link";
|
|
1314
|
+
const SLACK_SESSION_LINK_ACTION_ID = "openclaw:session_link";
|
|
1315
|
+
const SLACK_REPLY_SELECT_ACTION_ID = "openclaw:reply_select";
|
|
1316
|
+
const SLACK_CALLBACK_BUTTON_ACTION_ID = "openclaw:callback_button";
|
|
1317
|
+
const SLACK_CALLBACK_SELECT_ACTION_ID = "openclaw:callback_select";
|
|
1318
|
+
const SLACK_APPROVAL_BUTTON_ACTION_ID = "openclaw:approval_button";
|
|
1319
|
+
const SLACK_APPROVAL_SELECT_ACTION_ID = "openclaw:approval_select";
|
|
1320
|
+
const SLACK_QUESTION_BUTTON_ACTION_ID = "openclaw:question_button";
|
|
1321
|
+
const SLACK_QUESTION_FINALIZATION_BLOCKS = Symbol("slackQuestionFinalizationBlocks");
|
|
1322
|
+
function isSlackQuestionActionId(actionId) {
|
|
1323
|
+
return actionId === "openclaw:question_button" || actionId.startsWith(`openclaw:question_button:`);
|
|
1324
|
+
}
|
|
1325
|
+
/** Read only question control identities from the blocks actually sent to Slack. */
|
|
1326
|
+
function resolveSlackQuestionActionIds(blocks) {
|
|
1327
|
+
return (blocks ?? []).flatMap((block) => {
|
|
1328
|
+
if (block.type !== "actions") return [];
|
|
1329
|
+
return (block.elements ?? []).flatMap(({ action_id }) => action_id && isSlackQuestionActionId(action_id) ? [action_id] : []);
|
|
1330
|
+
});
|
|
1331
|
+
}
|
|
1332
|
+
function isSlackApprovalActionId(actionId) {
|
|
1333
|
+
return actionId === "openclaw:approval_button" || actionId === "openclaw:approval_select" || actionId.startsWith(`openclaw:approval_button:`) || actionId.startsWith(`openclaw:approval_select:`);
|
|
1334
|
+
}
|
|
1335
|
+
function isSlackCallbackActionId(actionId) {
|
|
1336
|
+
return actionId === "openclaw:callback_button" || actionId === "openclaw:callback_select" || actionId.startsWith(`openclaw:callback_button:`) || actionId.startsWith(`openclaw:callback_select:`);
|
|
1337
|
+
}
|
|
1338
|
+
//#endregion
|
|
1339
|
+
//#region extensions/slack/src/truncate.ts
|
|
1340
|
+
function truncateSlackText(value, max) {
|
|
1341
|
+
const trimmed = value.trim();
|
|
1342
|
+
if (trimmed.length <= max) return trimmed;
|
|
1343
|
+
if (max <= 1) return sliceUtf16Safe(trimmed, 0, max);
|
|
1344
|
+
return `${sliceUtf16Safe(trimmed, 0, max - 1)}…`;
|
|
1345
|
+
}
|
|
1346
|
+
function countSlackTextUtf8Bytes(value) {
|
|
1347
|
+
return Buffer.byteLength(value, "utf8");
|
|
1348
|
+
}
|
|
1349
|
+
/** Truncate Slack text without splitting a code point or exceeding a UTF-8 byte limit. */
|
|
1350
|
+
function truncateSlackTextByUtf8Bytes(value, maxBytes) {
|
|
1351
|
+
const trimmed = value.trim();
|
|
1352
|
+
if (maxBytes <= 0) return "";
|
|
1353
|
+
if (countSlackTextUtf8Bytes(trimmed) <= maxBytes) return trimmed;
|
|
1354
|
+
const suffix = "…";
|
|
1355
|
+
const suffixBytes = countSlackTextUtf8Bytes(suffix);
|
|
1356
|
+
const prefixBudget = maxBytes >= suffixBytes ? maxBytes - suffixBytes : maxBytes;
|
|
1357
|
+
let prefix = "";
|
|
1358
|
+
let prefixBytes = 0;
|
|
1359
|
+
for (const character of trimmed) {
|
|
1360
|
+
const characterBytes = countSlackTextUtf8Bytes(character);
|
|
1361
|
+
if (prefixBytes + characterBytes > prefixBudget) break;
|
|
1362
|
+
prefix += character;
|
|
1363
|
+
prefixBytes += characterBytes;
|
|
1364
|
+
}
|
|
1365
|
+
return maxBytes >= suffixBytes ? `${prefix}${suffix}` : prefix;
|
|
1366
|
+
}
|
|
1367
|
+
//#endregion
|
|
1368
|
+
//#region extensions/slack/src/blocks-render.ts
|
|
1369
|
+
const SLACK_BUTTON_URL_MAX = 3e3;
|
|
1370
|
+
function buildSlackReplyButtonActionId(buttonIndex, choiceIndex) {
|
|
1371
|
+
return `${SLACK_REPLY_BUTTON_ACTION_ID}:${String(buttonIndex)}:${String(choiceIndex + 1)}`;
|
|
1372
|
+
}
|
|
1373
|
+
function buildSlackReplyLinkActionId(buttonIndex, choiceIndex) {
|
|
1374
|
+
return `${SLACK_REPLY_LINK_ACTION_ID}:${String(buttonIndex)}:${String(choiceIndex + 1)}`;
|
|
1375
|
+
}
|
|
1376
|
+
function buildSlackReplySelectActionId(selectIndex) {
|
|
1377
|
+
return `${SLACK_REPLY_SELECT_ACTION_ID}:${String(selectIndex)}`;
|
|
1378
|
+
}
|
|
1379
|
+
function buildSlackApprovalButtonActionId(buttonIndex, choiceIndex) {
|
|
1380
|
+
return `${SLACK_APPROVAL_BUTTON_ACTION_ID}:${String(buttonIndex)}:${String(choiceIndex + 1)}`;
|
|
1030
1381
|
}
|
|
1031
1382
|
function buildSlackApprovalSelectActionId(selectIndex) {
|
|
1032
1383
|
return `${SLACK_APPROVAL_SELECT_ACTION_ID}:${String(selectIndex)}`;
|
|
@@ -1150,81 +1501,8 @@ function resolveSlackBlockOffsets(blocks) {
|
|
|
1150
1501
|
/**
|
|
1151
1502
|
* @deprecated Use buildSlackPresentationBlocks with MessagePresentation.
|
|
1152
1503
|
*/
|
|
1153
|
-
function buildSlackInteractiveBlocks(interactive, options = {}) {
|
|
1154
|
-
return
|
|
1155
|
-
blocks: [],
|
|
1156
|
-
buttonIndex: options.buttonIndexOffset ?? 0,
|
|
1157
|
-
selectIndex: options.selectIndexOffset ?? 0
|
|
1158
|
-
}, (state, block) => {
|
|
1159
|
-
if (block.type === "text") {
|
|
1160
|
-
const trimmed = block.text.trim();
|
|
1161
|
-
if (!trimmed) return state;
|
|
1162
|
-
state.blocks.push({
|
|
1163
|
-
type: "section",
|
|
1164
|
-
text: {
|
|
1165
|
-
type: "mrkdwn",
|
|
1166
|
-
text: truncateSlackText(trimmed, SLACK_SECTION_TEXT_MAX)
|
|
1167
|
-
}
|
|
1168
|
-
});
|
|
1169
|
-
return state;
|
|
1170
|
-
}
|
|
1171
|
-
if (block.type === "buttons") {
|
|
1172
|
-
const elements = block.buttons.flatMap((button, choiceIndex) => {
|
|
1173
|
-
const target = resolveSlackButtonTarget(button, choiceIndex);
|
|
1174
|
-
if (!target || (target.kind === "link" ? !isWithinSlackLimit(target.url, SLACK_BUTTON_URL_MAX) : !isWithinSlackLimit(target.value, 2e3))) return [];
|
|
1175
|
-
const style = resolveSlackButtonStyle(button.style);
|
|
1176
|
-
return [{
|
|
1177
|
-
type: "button",
|
|
1178
|
-
action_id: target.kind === "link" ? buildSlackReplyLinkActionId(state.buttonIndex + 1, choiceIndex) : target.kind === "approval" ? buildSlackApprovalButtonActionId(state.buttonIndex + 1, choiceIndex) : target.kind === "callback" ? buildSlackCallbackButtonActionId(state.buttonIndex + 1, choiceIndex) : target.kind === "question" ? buildSlackQuestionButtonActionId(state.buttonIndex + 1, choiceIndex) : buildSlackReplyButtonActionId(state.buttonIndex + 1, choiceIndex),
|
|
1179
|
-
text: {
|
|
1180
|
-
type: "plain_text",
|
|
1181
|
-
text: truncateSlackText(button.label, 75),
|
|
1182
|
-
emoji: true
|
|
1183
|
-
},
|
|
1184
|
-
...target.kind === "link" ? { url: target.url } : { value: target.value },
|
|
1185
|
-
...style ? { style } : {}
|
|
1186
|
-
}];
|
|
1187
|
-
}).slice(0, 25);
|
|
1188
|
-
if (elements.length === 0) return state;
|
|
1189
|
-
state.blocks.push({
|
|
1190
|
-
type: "actions",
|
|
1191
|
-
block_id: `openclaw_reply_buttons_${++state.buttonIndex}`,
|
|
1192
|
-
elements
|
|
1193
|
-
});
|
|
1194
|
-
return state;
|
|
1195
|
-
}
|
|
1196
|
-
const optionsLocal = block.options.flatMap((option) => {
|
|
1197
|
-
const target = resolveSlackOptionTarget(option);
|
|
1198
|
-
return target ? [{
|
|
1199
|
-
label: option.label,
|
|
1200
|
-
...target
|
|
1201
|
-
}] : [];
|
|
1202
|
-
}).filter(isRenderableSlackOption).slice(0, 100);
|
|
1203
|
-
const optionKinds = new Set(optionsLocal.map((option) => option.kind));
|
|
1204
|
-
if (optionsLocal.length === 0 || optionKinds.size !== 1) return state;
|
|
1205
|
-
state.blocks.push({
|
|
1206
|
-
type: "actions",
|
|
1207
|
-
block_id: `openclaw_reply_select_${++state.selectIndex}`,
|
|
1208
|
-
elements: [{
|
|
1209
|
-
type: "static_select",
|
|
1210
|
-
action_id: optionsLocal[0]?.kind === "approval" ? buildSlackApprovalSelectActionId(state.selectIndex) : optionsLocal[0]?.kind === "callback" ? buildSlackCallbackSelectActionId(state.selectIndex) : buildSlackReplySelectActionId(state.selectIndex),
|
|
1211
|
-
placeholder: {
|
|
1212
|
-
type: "plain_text",
|
|
1213
|
-
text: truncateSlackText(normalizeOptionalString(block.placeholder) ?? "Choose an option", 75),
|
|
1214
|
-
emoji: true
|
|
1215
|
-
},
|
|
1216
|
-
options: optionsLocal.map((option, _choiceIndex) => ({
|
|
1217
|
-
text: {
|
|
1218
|
-
type: "plain_text",
|
|
1219
|
-
text: truncateSlackText(option.label, 75),
|
|
1220
|
-
emoji: true
|
|
1221
|
-
},
|
|
1222
|
-
value: option.value
|
|
1223
|
-
}))
|
|
1224
|
-
}]
|
|
1225
|
-
});
|
|
1226
|
-
return state;
|
|
1227
|
-
}).blocks;
|
|
1504
|
+
function buildSlackInteractiveBlocks(interactive, options = {}) {
|
|
1505
|
+
return buildSlackPresentationBlocks(interactive ? legacyInteractiveReplyToPresentation(interactive) : void 0, options);
|
|
1228
1506
|
}
|
|
1229
1507
|
/** Render portable presentation blocks as Slack Block Kit blocks. */
|
|
1230
1508
|
function buildSlackPresentationBlocks(presentation, options = {}) {
|
|
@@ -1247,19 +1525,18 @@ function buildSlackPresentationBlocks(presentation, options = {}) {
|
|
|
1247
1525
|
if (block.type === "text" || block.type === "context") {
|
|
1248
1526
|
const text = block.text.trim();
|
|
1249
1527
|
if (!text) continue;
|
|
1250
|
-
|
|
1528
|
+
for (const chunk of chunkSlackMrkdwnText(text, SLACK_SECTION_TEXT_MAX)) blocks.push(block.type === "context" ? {
|
|
1251
1529
|
type: "context",
|
|
1252
1530
|
elements: [{
|
|
1253
1531
|
type: "mrkdwn",
|
|
1254
|
-
text:
|
|
1532
|
+
text: chunk,
|
|
1255
1533
|
verbatim: true
|
|
1256
1534
|
}]
|
|
1257
|
-
}
|
|
1258
|
-
else blocks.push({
|
|
1535
|
+
} : {
|
|
1259
1536
|
type: "section",
|
|
1260
1537
|
text: {
|
|
1261
1538
|
type: "mrkdwn",
|
|
1262
|
-
text:
|
|
1539
|
+
text: chunk
|
|
1263
1540
|
}
|
|
1264
1541
|
});
|
|
1265
1542
|
continue;
|
|
@@ -1356,10 +1633,7 @@ function canRenderSlackPresentation(presentation, options = {}) {
|
|
|
1356
1633
|
if (!canRenderSlackPresentationTables(presentation, options)) return false;
|
|
1357
1634
|
let dataVisualizationCount = options.dataVisualizationCountOffset ?? 0;
|
|
1358
1635
|
for (const block of presentation.blocks) {
|
|
1359
|
-
if (block.type === "text" || block.type === "context")
|
|
1360
|
-
if (!isWithinSlackLimit(block.text.trim(), 3e3)) return false;
|
|
1361
|
-
continue;
|
|
1362
|
-
}
|
|
1636
|
+
if (block.type === "text" || block.type === "context") continue;
|
|
1363
1637
|
if (block.type === "buttons") {
|
|
1364
1638
|
if (!(block.buttons.length <= 25 && block.buttons.every((button, choiceIndex) => {
|
|
1365
1639
|
if (!isWithinSlackLimit(button.label, 75)) return false;
|
|
@@ -1492,453 +1766,105 @@ function renderSlackRichTextLeaf(element) {
|
|
|
1492
1766
|
const usergroupId = normalizeOptionalString(element.usergroup_id);
|
|
1493
1767
|
return usergroupId ? escapeSlackMrkdwn(`<!subteam^${usergroupId}>`) : "";
|
|
1494
1768
|
}
|
|
1495
|
-
case "broadcast": {
|
|
1496
|
-
const range = normalizeOptionalString(element.range);
|
|
1497
|
-
return range ? escapeSlackMrkdwn(`<!${range}>`) : "";
|
|
1498
|
-
}
|
|
1499
|
-
case "emoji": {
|
|
1500
|
-
const name = normalizeOptionalString(element.name);
|
|
1501
|
-
return name ? `:${name}:` : "";
|
|
1502
|
-
}
|
|
1503
|
-
case "date": return escapeSlackMrkdwn(normalizeOptionalString(element.fallback) ?? "");
|
|
1504
|
-
default: return "";
|
|
1505
|
-
}
|
|
1506
|
-
}
|
|
1507
|
-
function renderSlackRichTextElement(value) {
|
|
1508
|
-
const element = asOptionalRecord(value);
|
|
1509
|
-
if (!element) return "";
|
|
1510
|
-
switch (element.type) {
|
|
1511
|
-
case "rich_text_section":
|
|
1512
|
-
case "rich_text_preformatted":
|
|
1513
|
-
case "rich_text_quote": return renderSlackRichTextElements(element.elements, "");
|
|
1514
|
-
case "rich_text_list": return renderSlackRichTextElements(element.elements, "\n");
|
|
1515
|
-
default: return renderSlackRichTextLeaf(element);
|
|
1516
|
-
}
|
|
1517
|
-
}
|
|
1518
|
-
function renderSlackRichTextElements(value, separator) {
|
|
1519
|
-
if (!Array.isArray(value)) return "";
|
|
1520
|
-
return value.map(renderSlackRichTextElement).filter(Boolean).join(separator);
|
|
1521
|
-
}
|
|
1522
|
-
function readImageText(block) {
|
|
1523
|
-
const altText = normalizeOptionalString(block.alt_text);
|
|
1524
|
-
return (altText ? escapeSlackMrkdwn(altText) : void 0) ?? readTextObject(block.title);
|
|
1525
|
-
}
|
|
1526
|
-
function readVideoText(block, options = {}) {
|
|
1527
|
-
const altText = normalizeOptionalString(block.alt_text);
|
|
1528
|
-
return readTextObject(block.title, options) ?? (altText ? escapeSlackMrkdwn(altText) : void 0);
|
|
1529
|
-
}
|
|
1530
|
-
function readContextText(block, options = {}) {
|
|
1531
|
-
if (!Array.isArray(block.elements)) return;
|
|
1532
|
-
const parts = block.elements.map((element) => {
|
|
1533
|
-
const record = asOptionalRecord(element);
|
|
1534
|
-
const altText = normalizeOptionalString(record?.alt_text);
|
|
1535
|
-
return readTextObject(record, options) ?? (altText ? escapeSlackMrkdwn(altText) : void 0);
|
|
1536
|
-
}).filter((part) => Boolean(part));
|
|
1537
|
-
return parts.length > 0 ? parts.join(" ") : void 0;
|
|
1538
|
-
}
|
|
1539
|
-
function readControlElementText(value, options = {}) {
|
|
1540
|
-
const element = asOptionalRecord(value);
|
|
1541
|
-
const type = normalizeOptionalString(element?.type);
|
|
1542
|
-
if (type === "button" || type === "workflow_button") return readTextValue(element?.text, options);
|
|
1543
|
-
if (type && SLACK_SELECT_ELEMENT_TYPES.has(type)) return readTextObject(element?.placeholder, options);
|
|
1544
|
-
}
|
|
1545
|
-
function readControlElementsText(values, options = {}) {
|
|
1546
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1547
|
-
const labels = [];
|
|
1548
|
-
for (const value of values) {
|
|
1549
|
-
const candidate = readControlElementText(value, options);
|
|
1550
|
-
if (!candidate || seen.has(candidate)) continue;
|
|
1551
|
-
seen.add(candidate);
|
|
1552
|
-
labels.push(candidate);
|
|
1553
|
-
}
|
|
1554
|
-
return labels.length > 0 ? labels.join("\n") : void 0;
|
|
1555
|
-
}
|
|
1556
|
-
function readSectionText(block, options = {}) {
|
|
1557
|
-
const parts = [readTextObject(block.text, options)];
|
|
1558
|
-
if (Array.isArray(block.fields)) parts.push(...block.fields.map((field) => readTextObject(field, options)));
|
|
1559
|
-
parts.push(readControlElementText(block.accessory, options));
|
|
1560
|
-
const visibleParts = parts.filter((part) => Boolean(part));
|
|
1561
|
-
return visibleParts.length > 0 ? visibleParts.join("\n") : void 0;
|
|
1562
|
-
}
|
|
1563
|
-
function readActionsText(block, options = {}) {
|
|
1564
|
-
return Array.isArray(block.elements) ? readControlElementsText(block.elements, options) : void 0;
|
|
1565
|
-
}
|
|
1566
|
-
/** Read only user-visible text from one Slack block. */
|
|
1567
|
-
function renderSlackBlockFallbackText(raw, options = {}) {
|
|
1568
|
-
const block = asOptionalRecord(raw);
|
|
1569
|
-
if (!block) return;
|
|
1570
|
-
switch (block.type) {
|
|
1571
|
-
case "rich_text": return normalizeOptionalString(renderSlackRichTextElements(block.elements, "\n"));
|
|
1572
|
-
case "header": return readTextObject(block.text, options);
|
|
1573
|
-
case "section": return readSectionText(block, options);
|
|
1574
|
-
case "image": return readImageText(block) ?? "Shared an image";
|
|
1575
|
-
case "video": return readVideoText(block, options) ?? "Shared a video";
|
|
1576
|
-
case "file": return "Shared a file";
|
|
1577
|
-
case "context": return readContextText(block, options);
|
|
1578
|
-
case "actions": return readActionsText(block, options);
|
|
1579
|
-
case "data_visualization": return options.nativeDataFormat === "plain" ? renderSlackDataVisualizationFallbackText(block) : renderSlackDataVisualizationMrkdwnFallbackText(block);
|
|
1580
|
-
case "data_table": return options.nativeDataFormat === "plain" ? renderSlackDataTableFallbackText(block) : renderSlackDataTableMrkdwnFallbackText(block);
|
|
1581
|
-
case "table": return options.nativeDataFormat === "plain" ? renderSlackTableFallbackText(block) : renderSlackTableMrkdwnFallbackText(block);
|
|
1582
|
-
default: return;
|
|
1583
|
-
}
|
|
1584
|
-
}
|
|
1585
|
-
function buildSlackBlocksFallbackText(blocks) {
|
|
1586
|
-
for (const block of blocks) {
|
|
1587
|
-
const text = renderSlackBlockFallbackText(block);
|
|
1588
|
-
if (text) return text;
|
|
1589
|
-
}
|
|
1590
|
-
return "Shared a Block Kit message";
|
|
1591
|
-
}
|
|
1592
|
-
function buildSlackCompleteBlocksFallbackText(blocks) {
|
|
1593
|
-
return blocks.map((block) => renderSlackBlockFallbackText(block)).filter(Boolean).join("\n\n").trim() || buildSlackBlocksFallbackText(blocks);
|
|
1594
|
-
}
|
|
1595
|
-
//#endregion
|
|
1596
|
-
//#region extensions/slack/src/format.ts
|
|
1597
|
-
function escapeSlackMrkdwnSegment(text) {
|
|
1598
|
-
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
1599
|
-
}
|
|
1600
|
-
const SLACK_ANGLE_TOKEN_RE = /<[^>\n]+>/g;
|
|
1601
|
-
function isAllowedSlackAngleToken(token) {
|
|
1602
|
-
if (!token.startsWith("<") || !token.endsWith(">")) return false;
|
|
1603
|
-
const inner = token.slice(1, -1);
|
|
1604
|
-
return inner.startsWith("@") || inner.startsWith("#") || inner.startsWith("!") || inner.startsWith("mailto:") || inner.startsWith("tel:") || inner.startsWith("http://") || inner.startsWith("https://") || inner.startsWith("slack://");
|
|
1605
|
-
}
|
|
1606
|
-
function escapeSlackMrkdwnContent(text) {
|
|
1607
|
-
if (!text) return "";
|
|
1608
|
-
if (!text.includes("&") && !text.includes("<") && !text.includes(">")) return text;
|
|
1609
|
-
SLACK_ANGLE_TOKEN_RE.lastIndex = 0;
|
|
1610
|
-
const out = [];
|
|
1611
|
-
let lastIndex = 0;
|
|
1612
|
-
for (let match = SLACK_ANGLE_TOKEN_RE.exec(text); match; match = SLACK_ANGLE_TOKEN_RE.exec(text)) {
|
|
1613
|
-
const matchIndex = match.index ?? 0;
|
|
1614
|
-
out.push(escapeSlackMrkdwnSegment(text.slice(lastIndex, matchIndex)));
|
|
1615
|
-
const token = match[0] ?? "";
|
|
1616
|
-
out.push(isAllowedSlackAngleToken(token) ? token : escapeSlackMrkdwnSegment(token));
|
|
1617
|
-
lastIndex = matchIndex + token.length;
|
|
1618
|
-
}
|
|
1619
|
-
out.push(escapeSlackMrkdwnSegment(text.slice(lastIndex)));
|
|
1620
|
-
return out.join("");
|
|
1621
|
-
}
|
|
1622
|
-
function escapeSlackMrkdwnText(text) {
|
|
1623
|
-
if (!text) return "";
|
|
1624
|
-
if (!text.includes("&") && !text.includes("<") && !text.includes(">")) return text;
|
|
1625
|
-
return text.split("\n").map((line) => {
|
|
1626
|
-
if (line.startsWith("> ")) return `> ${escapeSlackMrkdwnContent(line.slice(2))}`;
|
|
1627
|
-
return escapeSlackMrkdwnContent(line);
|
|
1628
|
-
}).join("\n");
|
|
1629
|
-
}
|
|
1630
|
-
function buildSlackLink(link, text) {
|
|
1631
|
-
const href = link.href.trim();
|
|
1632
|
-
if (!href) return null;
|
|
1633
|
-
const trimmedLabel = text.slice(link.start, link.end).trim();
|
|
1634
|
-
const comparableHref = href.startsWith("mailto:") ? href.slice(7) : href;
|
|
1635
|
-
if (!(trimmedLabel.length > 0 && trimmedLabel !== href && trimmedLabel !== comparableHref)) return null;
|
|
1636
|
-
const safeHref = escapeSlackMrkdwnSegment(href);
|
|
1637
|
-
return {
|
|
1638
|
-
start: link.start,
|
|
1639
|
-
end: link.end,
|
|
1640
|
-
open: `<${safeHref}|`,
|
|
1641
|
-
close: ">"
|
|
1642
|
-
};
|
|
1643
|
-
}
|
|
1644
|
-
const SLACK_MRKDWN_WORD_CHARACTER_RE = /[\p{L}\p{M}\p{N}_]/u;
|
|
1645
|
-
const SLACK_MRKDWN_PUNCTUATION_RE = /\p{P}/u;
|
|
1646
|
-
const SLACK_MRKDWN_SYMBOL_RE = /\p{S}/u;
|
|
1647
|
-
const SLACK_MRKDWN_CJK_SCRIPT_RE = /[\p{Script_Extensions=Han}\p{Script_Extensions=Hiragana}\p{Script_Extensions=Katakana}\p{Script_Extensions=Hangul}]/u;
|
|
1648
|
-
const SLACK_MRKDWN_EMOJI_PRESENTATION_RE = /\p{Emoji_Presentation}/u;
|
|
1649
|
-
function getCodePointBefore(text, index) {
|
|
1650
|
-
if (index <= 0) return "";
|
|
1651
|
-
const lastCodeUnit = text.charCodeAt(index - 1);
|
|
1652
|
-
if (lastCodeUnit >= 56320 && lastCodeUnit <= 57343 && index > 1) {
|
|
1653
|
-
const previousCodeUnit = text.charCodeAt(index - 2);
|
|
1654
|
-
if (previousCodeUnit >= 55296 && previousCodeUnit <= 56319) return text.slice(index - 2, index);
|
|
1655
|
-
}
|
|
1656
|
-
return text[index - 1] ?? "";
|
|
1657
|
-
}
|
|
1658
|
-
function getCodePointAt(text, index) {
|
|
1659
|
-
const codePoint = text.codePointAt(index);
|
|
1660
|
-
return codePoint === void 0 ? "" : String.fromCodePoint(codePoint);
|
|
1661
|
-
}
|
|
1662
|
-
function isSlackCjkPunctuation(character) {
|
|
1663
|
-
if (!SLACK_MRKDWN_PUNCTUATION_RE.test(character)) return false;
|
|
1664
|
-
if (SLACK_MRKDWN_CJK_SCRIPT_RE.test(character)) return true;
|
|
1665
|
-
const codePoint = character.codePointAt(0);
|
|
1666
|
-
if (codePoint === void 0) return false;
|
|
1667
|
-
const width = eastAsianWidthType(codePoint);
|
|
1668
|
-
return width === "fullwidth" || width === "halfwidth" || width === "wide" && !SLACK_MRKDWN_EMOJI_PRESENTATION_RE.test(character);
|
|
1669
|
-
}
|
|
1670
|
-
function isUnsafeSlackEmphasisBoundary(character) {
|
|
1671
|
-
if (SLACK_MRKDWN_WORD_CHARACTER_RE.test(character)) return true;
|
|
1672
|
-
const codePoint = character.codePointAt(0);
|
|
1673
|
-
if (codePoint === void 0 || codePoint <= 127) return false;
|
|
1674
|
-
return SLACK_MRKDWN_SYMBOL_RE.test(character) || isSlackCjkPunctuation(character);
|
|
1675
|
-
}
|
|
1676
|
-
function makeSlackEmphasisStylesSafe(ir) {
|
|
1677
|
-
const styles = ir.styles.filter((span) => {
|
|
1678
|
-
if (span.style !== "italic" && span.style !== "bold") return true;
|
|
1679
|
-
return !isUnsafeSlackEmphasisBoundary(getCodePointBefore(ir.text, span.start)) && !isUnsafeSlackEmphasisBoundary(getCodePointAt(ir.text, span.end));
|
|
1680
|
-
});
|
|
1681
|
-
return styles.length === ir.styles.length ? ir : {
|
|
1682
|
-
...ir,
|
|
1683
|
-
styles
|
|
1684
|
-
};
|
|
1685
|
-
}
|
|
1686
|
-
const SLACK_FORMAT_PROFILE = FormatCapabilityProfile.define({
|
|
1687
|
-
mechanism: "markdown",
|
|
1688
|
-
constructs: {
|
|
1689
|
-
underline: "strip",
|
|
1690
|
-
spoiler: "fallback",
|
|
1691
|
-
codeLanguage: "fallback",
|
|
1692
|
-
heading: "fallback",
|
|
1693
|
-
bulletList: "fallback",
|
|
1694
|
-
orderedList: "fallback",
|
|
1695
|
-
taskList: "fallback",
|
|
1696
|
-
table: "fallback",
|
|
1697
|
-
image: "fallback"
|
|
1698
|
-
},
|
|
1699
|
-
chunk: {
|
|
1700
|
-
limit: 4e3,
|
|
1701
|
-
unit: "chars",
|
|
1702
|
-
hardCap: 4e4
|
|
1703
|
-
}
|
|
1704
|
-
});
|
|
1705
|
-
const SLACK_ASSISTANT_TRANSCRIPT_PREFIX = "`Assistant:` ";
|
|
1706
|
-
function tokenizeSlackMrkdwn(text) {
|
|
1707
|
-
const tokens = [];
|
|
1708
|
-
for (let index = 0; index < text.length;) {
|
|
1709
|
-
if (text.startsWith("```", index)) {
|
|
1710
|
-
tokens.push("```");
|
|
1711
|
-
index += 3;
|
|
1712
|
-
continue;
|
|
1713
|
-
}
|
|
1714
|
-
const entity = [
|
|
1715
|
-
"&",
|
|
1716
|
-
"<",
|
|
1717
|
-
">"
|
|
1718
|
-
].find((candidate) => text.startsWith(candidate, index));
|
|
1719
|
-
if (entity) {
|
|
1720
|
-
tokens.push(entity);
|
|
1721
|
-
index += entity.length;
|
|
1722
|
-
continue;
|
|
1723
|
-
}
|
|
1724
|
-
if (text[index] === "<") {
|
|
1725
|
-
const end = text.indexOf(">", index + 1);
|
|
1726
|
-
const angleToken = end >= 0 ? text.slice(index, end + 1) : void 0;
|
|
1727
|
-
if (angleToken && !angleToken.includes("\n") && isAllowedSlackAngleToken(angleToken)) {
|
|
1728
|
-
tokens.push(angleToken);
|
|
1729
|
-
index += angleToken.length;
|
|
1730
|
-
continue;
|
|
1731
|
-
}
|
|
1732
|
-
}
|
|
1733
|
-
const codePoint = text.codePointAt(index);
|
|
1734
|
-
if (codePoint === void 0) break;
|
|
1735
|
-
const character = String.fromCodePoint(codePoint);
|
|
1736
|
-
index += character.length;
|
|
1737
|
-
if (character === "\\" && index < text.length) {
|
|
1738
|
-
const escapedCodePoint = text.codePointAt(index);
|
|
1739
|
-
if (escapedCodePoint !== void 0) {
|
|
1740
|
-
const escapedCharacter = String.fromCodePoint(escapedCodePoint);
|
|
1741
|
-
tokens.push(character + escapedCharacter);
|
|
1742
|
-
index += escapedCharacter.length;
|
|
1743
|
-
continue;
|
|
1744
|
-
}
|
|
1745
|
-
}
|
|
1746
|
-
tokens.push(character);
|
|
1769
|
+
case "broadcast": {
|
|
1770
|
+
const range = normalizeOptionalString(element.range);
|
|
1771
|
+
return range ? escapeSlackMrkdwn(`<!${range}>`) : "";
|
|
1772
|
+
}
|
|
1773
|
+
case "emoji": {
|
|
1774
|
+
const name = normalizeOptionalString(element.name);
|
|
1775
|
+
return name ? `:${name}:` : "";
|
|
1776
|
+
}
|
|
1777
|
+
case "date": return escapeSlackMrkdwn(normalizeOptionalString(element.fallback) ?? "");
|
|
1778
|
+
default: return "";
|
|
1747
1779
|
}
|
|
1748
|
-
return tokens;
|
|
1749
|
-
}
|
|
1750
|
-
function resolveSlackCodeMarkerTransition(active, token) {
|
|
1751
|
-
if (token === "```" && active !== "`") return active === "```" ? void 0 : "```";
|
|
1752
|
-
if (token === "`" && active !== "```") return active === "`" ? void 0 : "`";
|
|
1753
|
-
return null;
|
|
1754
|
-
}
|
|
1755
|
-
function maskSlackExcludedText(text) {
|
|
1756
|
-
return text.split("\n").map((line) => line.trim() ? `x${" ".repeat(Math.max(0, line.length - 1))}` : " ".repeat(line.length)).join("\n");
|
|
1757
1780
|
}
|
|
1758
|
-
function
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1781
|
+
function renderSlackRichTextElement(value) {
|
|
1782
|
+
const element = asOptionalRecord(value);
|
|
1783
|
+
if (!element) return "";
|
|
1784
|
+
switch (element.type) {
|
|
1785
|
+
case "rich_text_section":
|
|
1786
|
+
case "rich_text_preformatted":
|
|
1787
|
+
case "rich_text_quote": return renderSlackRichTextElements(element.elements, "");
|
|
1788
|
+
case "rich_text_list": return renderSlackRichTextElements(element.elements, "\n");
|
|
1789
|
+
default: return renderSlackRichTextLeaf(element);
|
|
1765
1790
|
}
|
|
1766
|
-
return masked + projection.text.slice(cursor);
|
|
1767
1791
|
}
|
|
1768
|
-
function
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
autolink: false,
|
|
1772
|
-
blockquotePrefix: "",
|
|
1773
|
-
headingStyle: "none",
|
|
1774
|
-
linkify: false,
|
|
1775
|
-
tableMode: "off"
|
|
1776
|
-
}).annotations?.some((annotation) => annotation.type === "assistant_transcript_role"));
|
|
1792
|
+
function renderSlackRichTextElements(value, separator) {
|
|
1793
|
+
if (!Array.isArray(value)) return "";
|
|
1794
|
+
return value.map(renderSlackRichTextElement).filter(Boolean).join(separator);
|
|
1777
1795
|
}
|
|
1778
|
-
function
|
|
1779
|
-
|
|
1796
|
+
function readImageText(block) {
|
|
1797
|
+
const altText = normalizeOptionalString(block.alt_text);
|
|
1798
|
+
return (altText ? escapeSlackMrkdwn(altText) : void 0) ?? readTextObject(block.title);
|
|
1780
1799
|
}
|
|
1781
|
-
function
|
|
1782
|
-
const
|
|
1783
|
-
|
|
1784
|
-
const fallbackSeparator = inner.indexOf("|");
|
|
1785
|
-
const tokenString = (fallbackSeparator === -1 ? inner : inner.slice(0, fallbackSeparator)).split("^")[2] ?? "";
|
|
1786
|
-
const fallback = fallbackSeparator === -1 ? "" : inner.slice(fallbackSeparator + 1);
|
|
1787
|
-
return decodeSlackMrkdwnEntities(dateDisplay === "fallback" ? fallback || tokenString : tokenString || fallback);
|
|
1788
|
-
}
|
|
1789
|
-
const labelSeparator = inner.indexOf("|");
|
|
1790
|
-
if (labelSeparator >= 0) return decodeSlackMrkdwnEntities(inner.slice(labelSeparator + 1));
|
|
1791
|
-
if (inner.startsWith("@")) return "@";
|
|
1792
|
-
if (inner.startsWith("#")) return "#";
|
|
1793
|
-
if (inner.startsWith("!")) return "!";
|
|
1794
|
-
return decodeSlackMrkdwnEntities(inner);
|
|
1800
|
+
function readVideoText(block, options = {}) {
|
|
1801
|
+
const altText = normalizeOptionalString(block.alt_text);
|
|
1802
|
+
return readTextObject(block.title, options) ?? (altText ? escapeSlackMrkdwn(altText) : void 0);
|
|
1795
1803
|
}
|
|
1796
|
-
function
|
|
1797
|
-
if (!
|
|
1798
|
-
const
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
start,
|
|
1805
|
-
end: projection.text.length
|
|
1806
|
-
});
|
|
1804
|
+
function readContextText(block, options = {}) {
|
|
1805
|
+
if (!Array.isArray(block.elements)) return;
|
|
1806
|
+
const parts = block.elements.map((element) => {
|
|
1807
|
+
const record = asOptionalRecord(element);
|
|
1808
|
+
const altText = normalizeOptionalString(record?.alt_text);
|
|
1809
|
+
return readTextObject(record, options) ?? (altText ? escapeSlackMrkdwn(altText) : void 0);
|
|
1810
|
+
}).filter((part) => Boolean(part));
|
|
1811
|
+
return parts.length > 0 ? parts.join(" ") : void 0;
|
|
1807
1812
|
}
|
|
1808
|
-
function
|
|
1809
|
-
const
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
let activeMarker;
|
|
1814
|
-
let lineHasVisibleContent = false;
|
|
1815
|
-
for (const token of tokenizeSlackMrkdwn(text)) {
|
|
1816
|
-
const transition = resolveSlackCodeMarkerTransition(activeMarker, token);
|
|
1817
|
-
if (transition !== null) {
|
|
1818
|
-
activeMarker = transition;
|
|
1819
|
-
continue;
|
|
1820
|
-
}
|
|
1821
|
-
let visible = token;
|
|
1822
|
-
if (isAllowedSlackAngleToken(token)) visible = activeMarker ? token : projectSlackAngleToken(token, dateDisplay);
|
|
1823
|
-
else if (token === "&" || token === "<" || token === ">") visible = decodeSlackMrkdwnEntities(token);
|
|
1824
|
-
else if (!activeMarker && (token === "*" || token === "_" || token === "~")) visible = "";
|
|
1825
|
-
else if (!activeMarker && token === ">" && !lineHasVisibleContent) visible = "";
|
|
1826
|
-
else if (token.startsWith("\\") && token.length > 1) visible = token.slice(1);
|
|
1827
|
-
appendSlackVisibleProjection(projection, visible, activeMarker !== void 0);
|
|
1828
|
-
for (const character of visible) if (character === "\n") lineHasVisibleContent = false;
|
|
1829
|
-
else if (character !== " " && character !== " " && character !== "\r") lineHasVisibleContent = true;
|
|
1830
|
-
}
|
|
1831
|
-
return projection;
|
|
1813
|
+
function readControlElementText(value, options = {}) {
|
|
1814
|
+
const element = asOptionalRecord(value);
|
|
1815
|
+
const type = normalizeOptionalString(element?.type);
|
|
1816
|
+
if (type === "button" || type === "workflow_button") return readTextValue(element?.text, options);
|
|
1817
|
+
if (type && SLACK_SELECT_ELEMENT_TYPES.has(type)) return readTextObject(element?.placeholder, options);
|
|
1832
1818
|
}
|
|
1833
|
-
function
|
|
1834
|
-
|
|
1835
|
-
const
|
|
1836
|
-
const
|
|
1837
|
-
|
|
1838
|
-
|
|
1819
|
+
function readControlElementsText(values, options = {}) {
|
|
1820
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1821
|
+
const labels = [];
|
|
1822
|
+
for (const value of values) {
|
|
1823
|
+
const candidate = readControlElementText(value, options);
|
|
1824
|
+
if (!candidate || seen.has(candidate)) continue;
|
|
1825
|
+
seen.add(candidate);
|
|
1826
|
+
labels.push(candidate);
|
|
1827
|
+
}
|
|
1828
|
+
return labels.length > 0 ? labels.join("\n") : void 0;
|
|
1839
1829
|
}
|
|
1840
|
-
function
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
} },
|
|
1847
|
-
styleMarkers: {
|
|
1848
|
-
bold: {
|
|
1849
|
-
open: "*",
|
|
1850
|
-
close: "*"
|
|
1851
|
-
},
|
|
1852
|
-
italic: {
|
|
1853
|
-
open: "_",
|
|
1854
|
-
close: "_"
|
|
1855
|
-
},
|
|
1856
|
-
strikethrough: {
|
|
1857
|
-
open: "~",
|
|
1858
|
-
close: "~"
|
|
1859
|
-
},
|
|
1860
|
-
code: {
|
|
1861
|
-
open: "`",
|
|
1862
|
-
close: "`"
|
|
1863
|
-
},
|
|
1864
|
-
code_block: {
|
|
1865
|
-
open: "```\n",
|
|
1866
|
-
close: "```"
|
|
1867
|
-
}
|
|
1868
|
-
},
|
|
1869
|
-
escapeText: escapeSlackMrkdwnText,
|
|
1870
|
-
buildLink: buildSlackLink
|
|
1871
|
-
};
|
|
1830
|
+
function readSectionText(block, options = {}) {
|
|
1831
|
+
const parts = [readTextObject(block.text, options)];
|
|
1832
|
+
if (Array.isArray(block.fields)) parts.push(...block.fields.map((field) => readTextObject(field, options)));
|
|
1833
|
+
parts.push(readControlElementText(block.accessory, options));
|
|
1834
|
+
const visibleParts = parts.filter((part) => Boolean(part));
|
|
1835
|
+
return visibleParts.length > 0 ? visibleParts.join("\n") : void 0;
|
|
1872
1836
|
}
|
|
1873
|
-
function
|
|
1874
|
-
return
|
|
1875
|
-
assistantTranscriptRoleHeaders: true,
|
|
1876
|
-
linkify: false,
|
|
1877
|
-
autolink: false,
|
|
1878
|
-
headingStyle: "rich",
|
|
1879
|
-
blockquotePrefix: "> ",
|
|
1880
|
-
tableMode: options.tableMode
|
|
1881
|
-
})), buildSlackRenderOptions(), SLACK_FORMAT_PROFILE);
|
|
1837
|
+
function readActionsText(block, options = {}) {
|
|
1838
|
+
return Array.isArray(block.elements) ? readControlElementsText(block.elements, options) : void 0;
|
|
1882
1839
|
}
|
|
1883
|
-
|
|
1884
|
-
|
|
1840
|
+
/** Read only user-visible text from one Slack block. */
|
|
1841
|
+
function renderSlackBlockFallbackText(raw, options = {}) {
|
|
1842
|
+
const block = asOptionalRecord(raw);
|
|
1843
|
+
if (!block) return;
|
|
1844
|
+
switch (block.type) {
|
|
1845
|
+
case "rich_text": return normalizeOptionalString(renderSlackRichTextElements(block.elements, "\n"));
|
|
1846
|
+
case "header": return readTextObject(block.text, options);
|
|
1847
|
+
case "section": return readSectionText(block, options);
|
|
1848
|
+
case "image": return readImageText(block) ?? "Shared an image";
|
|
1849
|
+
case "video": return readVideoText(block, options) ?? "Shared a video";
|
|
1850
|
+
case "file": return "Shared a file";
|
|
1851
|
+
case "context": return readContextText(block, options);
|
|
1852
|
+
case "actions": return readActionsText(block, options);
|
|
1853
|
+
case "data_visualization": return options.nativeDataFormat === "plain" ? renderSlackDataVisualizationFallbackText(block) : renderSlackDataVisualizationMrkdwnFallbackText(block);
|
|
1854
|
+
case "data_table": return options.nativeDataFormat === "plain" ? renderSlackDataTableFallbackText(block) : renderSlackDataTableMrkdwnFallbackText(block);
|
|
1855
|
+
case "table": return options.nativeDataFormat === "plain" ? renderSlackTableFallbackText(block) : renderSlackTableMrkdwnFallbackText(block);
|
|
1856
|
+
default: return;
|
|
1857
|
+
}
|
|
1885
1858
|
}
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
const chunks = [];
|
|
1891
|
-
let activeMarker;
|
|
1892
|
-
let content = "";
|
|
1893
|
-
const wrapper = () => activeMarker && limit > activeMarker.length * 2 ? activeMarker : void 0;
|
|
1894
|
-
const capacity = () => limit - (wrapper()?.length ?? 0) * 2;
|
|
1895
|
-
const flush = () => {
|
|
1896
|
-
if (!content) return;
|
|
1897
|
-
const marker = wrapper();
|
|
1898
|
-
chunks.push(marker ? `${marker}${content}${marker}` : content);
|
|
1899
|
-
content = "";
|
|
1900
|
-
};
|
|
1901
|
-
for (const token of tokenizeSlackMrkdwn(text)) {
|
|
1902
|
-
const transition = resolveSlackCodeMarkerTransition(activeMarker, token);
|
|
1903
|
-
if (transition !== null) {
|
|
1904
|
-
flush();
|
|
1905
|
-
activeMarker = transition;
|
|
1906
|
-
continue;
|
|
1907
|
-
}
|
|
1908
|
-
const contentLimit = capacity();
|
|
1909
|
-
if (token.length > contentLimit) {
|
|
1910
|
-
flush();
|
|
1911
|
-
const marker = wrapper();
|
|
1912
|
-
if (activeMarker && isAllowedSlackAngleToken(token)) {
|
|
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 }));
|
|
1915
|
-
continue;
|
|
1916
|
-
}
|
|
1917
|
-
chunks.push(...token.length <= limit ? [token] : chunkTextForOutbound(token, limit));
|
|
1918
|
-
continue;
|
|
1919
|
-
}
|
|
1920
|
-
if (content && content.length + token.length > contentLimit) flush();
|
|
1921
|
-
content += token;
|
|
1859
|
+
function buildSlackBlocksFallbackText(blocks) {
|
|
1860
|
+
for (const block of blocks) {
|
|
1861
|
+
const text = renderSlackBlockFallbackText(block);
|
|
1862
|
+
if (text) return text;
|
|
1922
1863
|
}
|
|
1923
|
-
|
|
1924
|
-
return chunks;
|
|
1864
|
+
return "Shared a Block Kit message";
|
|
1925
1865
|
}
|
|
1926
|
-
function
|
|
1927
|
-
|
|
1928
|
-
assistantTranscriptRoleHeaders: true,
|
|
1929
|
-
linkify: false,
|
|
1930
|
-
autolink: false,
|
|
1931
|
-
headingStyle: "rich",
|
|
1932
|
-
blockquotePrefix: "> ",
|
|
1933
|
-
tableMode: options.tableMode
|
|
1934
|
-
}));
|
|
1935
|
-
const renderOptions = buildSlackRenderOptions();
|
|
1936
|
-
return renderMarkdownIRChunksWithinLimit({
|
|
1937
|
-
ir,
|
|
1938
|
-
limit,
|
|
1939
|
-
renderChunk: (chunk) => protectSlackAssistantTranscriptRoleHeaders(renderMarkdownWithMarkers(chunk, renderOptions, SLACK_FORMAT_PROFILE)),
|
|
1940
|
-
measureRendered: (rendered) => rendered.length
|
|
1941
|
-
}).map(({ rendered }) => rendered);
|
|
1866
|
+
function buildSlackCompleteBlocksFallbackText(blocks) {
|
|
1867
|
+
return blocks.map((block) => renderSlackBlockFallbackText(block)).filter(Boolean).join("\n\n").trim() || buildSlackBlocksFallbackText(blocks);
|
|
1942
1868
|
}
|
|
1943
1869
|
//#endregion
|
|
1944
1870
|
//#region extensions/slack/src/native-data-blocks.ts
|
|
@@ -2264,6 +2190,7 @@ function appendPresentationPart(segments, presentation) {
|
|
|
2264
2190
|
const SLACK_BUTTON_CONTROL_ACTION_IDS = [
|
|
2265
2191
|
SLACK_APPROVAL_BUTTON_ACTION_ID,
|
|
2266
2192
|
SLACK_CALLBACK_BUTTON_ACTION_ID,
|
|
2193
|
+
SLACK_QUESTION_BUTTON_ACTION_ID,
|
|
2267
2194
|
SLACK_REPLY_BUTTON_ACTION_ID,
|
|
2268
2195
|
SLACK_REPLY_LINK_ACTION_ID
|
|
2269
2196
|
];
|
|
@@ -2538,4 +2465,4 @@ function resolveSlackGroupToolPolicy(params) {
|
|
|
2538
2465
|
});
|
|
2539
2466
|
}
|
|
2540
2467
|
//#endregion
|
|
2541
|
-
export {
|
|
2468
|
+
export { isSlackCallbackActionId as $, isSlackInvalidBlocksResponse as A, getSlackApprovalApprovers as At, SLACK_TEXT_LIMIT as B, SLACK_MALFORMED_NATIVE_DATA_FALLBACK as C, resolveTurnSourceSlackOriginTarget as Ct, createSlackNativeDataBaseTextConsumer as D, getSlackInstallationKind as Dt, buildSlackNativeDataAccessibilityText as E, slackTargetsMatch as Et, renderSlackBlockFallbackText as F, normalizeSlackApproverId as Ft, truncateSlackText as G, buildSlackPresentationBlocks as H, resolveSlackAuthoredTextPlacement as I, resolveSlackExecApprovalTarget as It, SLACK_REPLY_BUTTON_ACTION_ID as J, truncateSlackTextByUtf8Bytes as K, SLACK_EDIT_TEXT_MAX_BYTES as L, shouldSuppressLocalSlackExecApprovalPrompt as Lt, stripSlackNativeDataBlocks as M, getSlackExecApprovalApprovers as Mt, buildSlackBlocksFallbackText as N, isSlackExecApprovalAuthorizedSender as Nt, hasSlackNativeDataBlock as O, isSlackWorkspaceInstallation as Ot, buildSlackCompleteBlocksFallbackText as P, isSlackExecApprovalClientEnabled as Pt, isSlackApprovalActionId as Q, SLACK_MESSAGE_TEXT_HARD_LIMIT as R, SLACK_PRIVATE_ACTION_DELIVERY_RESULT as Rt, resolveSlackReplyRenderPlan as S, resolveSlackFallbackOriginTarget as St, appendSlackNativeDataPlainTextFallback as T, shouldHandleSlackPluginViaForwardingSession as Tt, canRenderSlackPresentation as U, buildSlackInteractiveBlocks as V, countSlackTextUtf8Bytes as W, SLACK_REPLY_SELECT_ACTION_ID as X, SLACK_REPLY_LINK_ACTION_ID as Y, SLACK_SESSION_LINK_ACTION_ID as Z, hasSlackReplyStructuredContent as _, isSlackAnyNativeApprovalClientEnabled as _t, qualifySlackConversationId as a, markdownToSlackMrkdwnChunks as at, resolveSlackReplyBlocks as b, resolveEnterpriseApprovalTeamId as bt, allowListMatches as c, escapeSlackMrkdwn as ct, normalizeSlackAllowOwnerEntry as d, SLACK_PRESENTATION_CAPABILITIES as dt, isSlackQuestionActionId as et, normalizeSlackSlug as f, SLACK_SECTION_TEXT_MAX as ft, assertSlackDetachedTargetAllowed as g, hasSlackPluginApprovers as gt, resolveSlackUserAllowed as h, validateSlackBlocksArray as ht, resolveSlackGroupToolPolicy as i, chunkSlackMrkdwnText as it, isSlackNativeResponseUrlRejection as j, isSlackApprovalAuthorizedSender as jt, isSlackInvalidBlocksError as k, registerSlackInstallationState as kt, normalizeAllowList as l, SLACK_APPROVAL_HEADER_BLOCK_ID as lt, resolveSlackUserAllowListForTeam as m, parseSlackBlocksInput as mt, buildSlackChannelPolicyScope as n, decodeSlackQuestionAction as nt, qualifySlackRoutePeerId as o, normalizeSlackOutboundText as ot, resolveSlackAllowListMatch as p, SLACK_MAX_BLOCKS as pt, SLACK_QUESTION_FINALIZATION_BLOCKS as q, resolveSlackGroupRequireMention as r, resolveSlackQuestionAction as rt, resolveSlackEnterpriseMainDmSessionKey as s, renderSlackMessagePresentationFallbackText as st, buildSlackChannelIdCandidates as t, resolveSlackQuestionActionIds as tt, normalizeAllowListLower as u, decodeSlackApprovalAction as ut, parseSlackReplyBlockSegments as v, normalizeSlackForwardTarget as vt, appendSlackNativeDataFallbackText as w, shouldHandleSlackNativeApprovalRequest as wt, resolveSlackReplyDeliveryMessages as x, resolveSessionSlackOriginTarget as xt, resolveSlackReplyBlockResolution as y, normalizeSlackOriginTarget as yt, SLACK_MESSAGE_TEXT_RECOMMENDED_LIMIT as z, resolveSlackAutoThreadId as zt };
|