@openclaw/slack 2026.11.3 → 2026.11.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-inspect-CmkKiSb9.mjs → account-inspect-BLVha-ov.mjs} +11 -8
- package/dist/.setup/{accounts-msihSF3-.mjs → accounts-CGJScKtk.mjs} +10 -1
- package/dist/.setup/{action-runtime-ChRfnnBu.mjs → action-runtime-D01wBhx5.mjs} +38 -45
- package/dist/.setup/action-runtime.runtime-VQGaR6g8.mjs +1 -0
- package/dist/.setup/{actions-By7tvpvv.mjs → actions-D5S6D_BU.mjs} +89 -76
- package/dist/.setup/{approval-handler.runtime-D8ArtDQt.mjs → approval-handler.runtime-Buw5jh2Y.mjs} +26 -30
- package/dist/.setup/{approval-message-updates-DT7XBPbV.mjs → approval-message-updates-pmXcve5E.mjs} +1 -1
- package/dist/.setup/{channel-DLFiMJm2.mjs → channel-C_R98Nbv.mjs} +569 -339
- package/dist/.setup/{channel-type-BEFP2ORi.mjs → channel-type-B5P3w9eA.mjs} +4 -8
- package/dist/.setup/{channel.setup-CzFw73mU.mjs → channel.setup-Lq2OxKkF.mjs} +13 -13
- package/dist/.setup/{config-schema-DNnh6bWU.mjs → config-schema-BWAaa5au.mjs} +3 -7
- package/dist/.setup/cursor-pages-CATAzbTT.mjs +313 -0
- package/dist/.setup/{directory-config-Cjj0N8R0.mjs → directory-config-D-hf9KGQ.mjs} +3 -3
- package/dist/.setup/{directory-live-BIKD-5B_.mjs → directory-live-onKAFI1E.mjs} +4 -4
- package/dist/.setup/{doctor-contract-Cd4-VzIM.mjs → doctor-contract-9-QJRCXk.mjs} +37 -45
- package/dist/.setup/{message-tool-api-BS5ekEA_.mjs → message-tool-api-LGIgVXJf.mjs} +4 -3
- package/dist/.setup/{monitor-CV6Z6FKP.mjs → monitor-Cm1TuqxN.mjs} +3424 -3703
- package/dist/.setup/{outbound-adapter-9dbnYtL1.mjs → outbound-adapter-C-95EWl2.mjs} +30 -36
- package/dist/.setup/paths-B1u59oLK.mjs +8 -0
- package/dist/.setup/{pipeline.runtime-DLIQf1Bo.mjs → pipeline.runtime-DGnV6akc.mjs} +416 -534
- package/dist/.setup/{policy-yhn48xf5.mjs → policy-DxhGRvc2.mjs} +1 -2
- package/dist/.setup/{session-status-Dv8wNBEt.mjs → probe-DANukR3O.mjs} +1206 -839
- package/dist/.setup/question-delivery-CWC7sRhH.mjs +39 -0
- package/dist/.setup/{relay-source-CxDcrn16.mjs → relay-source-DoyOlTbK.mjs} +5 -3
- package/dist/.setup/{replies-MRkrg3rC.mjs → replies-BcmUKord.mjs} +34 -19
- package/dist/.setup/{reply-blocks-Ca-raz2z.mjs → reply-blocks-BzsXUUUL.mjs} +201 -206
- package/dist/.setup/{resolve-channels-DRRhElwz.mjs → resolve-channels-XDPgnesf.mjs} +4 -7
- package/dist/.setup/{resolve-users-Cz8e17ky.mjs → resolve-users-aDAv24U2.mjs} +8 -16
- package/dist/.setup/runtime-setter-api-Cx_PV-xu.mjs +2 -0
- package/dist/.setup/{scopes-DfQVi8Jw.mjs → scopes-BocHwImV.mjs} +2 -1
- package/dist/.setup/secret-contract-api-BlLz88mj.mjs +2 -0
- package/dist/.setup/{secret-contract-vVRMoE1D.mjs → secret-contract-uiQtoNlu.mjs} +2 -2
- package/dist/.setup/{send-results-eeOu_HYm.mjs → send-results-BGxlroJ-.mjs} +3 -4
- package/dist/.setup/{send-C-8wY0lK.mjs → send-yK6_-px6.mjs} +297 -334
- package/dist/.setup/setup-plugin-api-Cfz58xoh.mjs +2 -0
- package/dist/.setup/{setup-surface--n8VsDvV.mjs → setup-surface-C0KRtyqa.mjs} +5 -6
- package/dist/.setup/{slash-dispatch.runtime-D3Wq45ER.mjs → slash-dispatch.runtime-CyVC3bYx.mjs} +2 -2
- package/dist/.setup/{target-parsing-FFE26kOV.mjs → target-parsing-Bx2UZniD.mjs} +1 -2
- package/dist/.setup/{targets-C6LZQL1Q.mjs → targets-D-ASeWHy.mjs} +1 -1
- package/dist/.source-module-urls/c5ffd0957b234c7c12090e7de4eca2482ef339b8561e078da55b734211b0ba58.json +1 -0
- package/dist/account-inspect-api.js +1 -1
- package/dist/api.js +16 -17
- package/dist/channel-config-api.js +1 -2
- package/dist/channel-plugin-api.js +1 -2
- package/dist/directory-contract-api.js +1 -2
- package/dist/doctor-contract-api.js +1 -2
- package/dist/index.js +0 -6
- package/dist/message-tool-api.js +1 -2
- package/dist/runtime-api.js +10 -12
- package/dist/runtime-setter-api.js +1 -2
- package/dist/secret-contract-api.js +1 -2
- package/dist/security-contract-api.js +1 -2
- package/dist/setup-entry.js +3 -3
- package/dist/setup-plugin-api.js +1 -2
- package/node_modules/@slack/bolt/node_modules/@types/node/README.md +1 -1
- package/node_modules/@slack/bolt/node_modules/@types/node/package.json +2 -2
- package/node_modules/@slack/bolt/node_modules/@types/node/util.d.ts +6 -3
- package/node_modules/@slack/bolt/node_modules/content-disposition/README.md +105 -35
- package/node_modules/@slack/bolt/node_modules/content-disposition/dist/index.d.ts +72 -0
- package/node_modules/@slack/bolt/node_modules/content-disposition/dist/index.js +388 -0
- package/node_modules/@slack/bolt/node_modules/content-disposition/dist/index.js.map +1 -0
- package/node_modules/@slack/bolt/node_modules/content-disposition/package.json +31 -19
- package/node_modules/@slack/bolt/node_modules/content-type/README.md +34 -57
- package/node_modules/@slack/bolt/node_modules/content-type/package.json +35 -25
- package/node_modules/@slack/bolt/node_modules/express/Readme.md +15 -9
- package/node_modules/@slack/bolt/node_modules/express/lib/application.js +2 -2
- package/node_modules/@slack/bolt/node_modules/express/lib/request.js +32 -19
- package/node_modules/@slack/bolt/node_modules/express/lib/response.js +27 -30
- package/node_modules/@slack/bolt/node_modules/express/package.json +10 -10
- package/node_modules/@slack/bolt/node_modules/qs/.github/THREAT_MODEL.md +4 -2
- package/node_modules/@slack/bolt/node_modules/qs/CHANGELOG.md +38 -14
- package/node_modules/@slack/bolt/node_modules/qs/README.md +31 -3
- package/node_modules/@slack/bolt/node_modules/qs/dist/qs.js +20 -20
- package/node_modules/@slack/bolt/node_modules/qs/lib/parse.js +94 -4
- package/node_modules/@slack/bolt/node_modules/qs/lib/stringify.js +4 -4
- package/node_modules/@slack/bolt/node_modules/qs/lib/utils.js +130 -6
- package/node_modules/@slack/bolt/node_modules/qs/package.json +4 -4
- package/node_modules/@slack/bolt/node_modules/qs/test/parse.js +174 -0
- package/node_modules/@slack/bolt/node_modules/qs/test/stringify.js +263 -33
- package/node_modules/@slack/bolt/node_modules/qs/test/utils.js +184 -0
- package/node_modules/@slack/web-api/node_modules/@types/node/README.md +1 -1
- package/node_modules/@slack/web-api/node_modules/@types/node/package.json +2 -2
- package/node_modules/@slack/web-api/node_modules/@types/node/util.d.ts +6 -3
- package/node_modules/typebox/build/format/duration.d.mts +2 -2
- package/node_modules/typebox/build/format/duration.mjs +2 -2
- package/node_modules/typebox/build/format/idn_email.d.mts +1 -0
- package/node_modules/typebox/build/format/idn_email.mjs +1 -0
- package/node_modules/typebox/build/format/idn_hostname.d.mts +1 -1
- package/node_modules/typebox/build/format/idn_hostname.mjs +1 -1
- package/node_modules/typebox/build/format/ipv4.d.mts +2 -2
- package/node_modules/typebox/build/format/ipv4.mjs +2 -2
- package/node_modules/typebox/build/format/ipv6.d.mts +1 -1
- package/node_modules/typebox/build/format/ipv6.mjs +1 -1
- package/node_modules/typebox/build/format/relative_json_pointer.d.mts +2 -2
- package/node_modules/typebox/build/format/relative_json_pointer.mjs +2 -2
- package/node_modules/typebox/build/schema/build.mjs +1 -0
- package/node_modules/typebox/build/schema/engine/_unique.d.mts +4 -2
- package/node_modules/typebox/build/schema/engine/_unique.mjs +7 -3
- package/node_modules/typebox/build/schema/engine/additionalItems.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/additionalProperties.d.mts +0 -3
- package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +15 -17
- package/node_modules/typebox/build/schema/engine/contains.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/index.d.mts +1 -0
- package/node_modules/typebox/build/schema/engine/index.mjs +1 -0
- package/node_modules/typebox/build/schema/engine/items.mjs +7 -4
- package/node_modules/typebox/build/schema/engine/maxContains.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/minContains.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/oneOf.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/patternProperties.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/unevaluatedItems.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/unevaluatedProperties.mjs +2 -2
- package/node_modules/typebox/build/system/hashing/hash.mjs +63 -34
- package/node_modules/typebox/build/system/locale/en_US.mjs +2 -1
- package/node_modules/typebox/build/system/memory/assign.d.mts +2 -8
- package/node_modules/typebox/build/system/memory/assign.mjs +13 -6
- package/node_modules/typebox/build/system/memory/clone.d.mts +4 -5
- package/node_modules/typebox/build/system/memory/clone.mjs +8 -96
- package/node_modules/typebox/build/system/memory/create.d.mts +1 -5
- package/node_modules/typebox/build/system/memory/create.mjs +18 -13
- package/node_modules/typebox/build/system/memory/deep.d.mts +2 -0
- package/node_modules/typebox/build/system/memory/deep.mjs +108 -0
- package/node_modules/typebox/build/system/memory/discard.d.mts +1 -1
- package/node_modules/typebox/build/system/memory/discard.mjs +9 -8
- package/node_modules/typebox/build/system/memory/finalize.d.mts +4 -0
- package/node_modules/typebox/build/system/memory/finalize.mjs +30 -0
- package/node_modules/typebox/build/system/memory/keys.d.mts +2 -0
- package/node_modules/typebox/build/system/memory/keys.mjs +8 -0
- package/node_modules/typebox/build/system/memory/update.d.mts +1 -4
- package/node_modules/typebox/build/system/memory/update.mjs +43 -16
- package/node_modules/typebox/build/type/engine/call/index.d.mts +1 -0
- package/node_modules/typebox/build/type/engine/call/index.mjs +1 -0
- package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +2 -24
- package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +2 -29
- package/node_modules/typebox/build/type/engine/evaluate/index.d.mts +1 -0
- package/node_modules/typebox/build/type/engine/evaluate/index.mjs +1 -0
- package/node_modules/typebox/build/type/engine/evaluate/narrow.d.mts +5 -1
- package/node_modules/typebox/build/type/engine/evaluate/narrow.mjs +6 -1
- package/node_modules/typebox/build/type/engine/evaluate/property.d.mts +30 -0
- package/node_modules/typebox/build/type/engine/evaluate/property.mjs +29 -0
- package/node_modules/typebox/build/type/engine/immutable/instantiate_add.d.mts +1 -3
- package/node_modules/typebox/build/type/engine/immutable/instantiate_add.mjs +1 -4
- package/node_modules/typebox/build/type/engine/object/from_intersect.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/object/from_intersect.mjs +2 -2
- package/node_modules/typebox/build/type/engine/object/from_union.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/object/from_union.mjs +2 -2
- package/node_modules/typebox/build/type/engine/optional/instantiate_add.d.mts +1 -3
- package/node_modules/typebox/build/type/engine/optional/instantiate_add.mjs +1 -4
- package/node_modules/typebox/build/type/engine/readonly/instantiate_add.d.mts +1 -3
- package/node_modules/typebox/build/type/engine/readonly/instantiate_add.mjs +1 -4
- package/node_modules/typebox/build/type/engine/this/index.d.mts +1 -0
- package/node_modules/typebox/build/type/engine/this/index.mjs +1 -0
- package/node_modules/typebox/build/value/clone/clone.d.mts +4 -3
- package/node_modules/typebox/build/value/clone/clone.mjs +5 -7
- package/node_modules/typebox/build/value/repair/from_cyclic.d.mts +2 -0
- package/node_modules/typebox/build/value/repair/from_cyclic.mjs +6 -0
- package/node_modules/typebox/build/value/shared/union_priority_sort.mjs +25 -14
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/typebox/readme.md +1 -1
- package/node_modules/undici/docs/docs/api/Interceptors.md +15 -2
- package/node_modules/undici/lib/dispatcher/client-h2.js +78 -3
- package/node_modules/undici/lib/dispatcher/pool-base.js +20 -3
- package/node_modules/undici/package.json +3 -3
- package/node_modules/undici/types/api.d.ts +1 -1
- package/node_modules/undici/types/utility.d.ts +4 -4
- package/node_modules/zod/package.json +1 -1
- package/node_modules/zod/src/v4/classic/tests/array.test.ts +27 -0
- package/node_modules/zod/src/v4/classic/tests/map.test.ts +7 -0
- package/node_modules/zod/src/v4/classic/tests/set.test.ts +6 -0
- package/node_modules/zod/src/v4/core/compile.ts +9 -0
- package/node_modules/zod/src/v4/core/schemas.ts +35 -1
- package/node_modules/zod/src/v4/core/util.ts +13 -0
- package/node_modules/zod/src/v4/core/versions.ts +1 -1
- package/node_modules/zod/v4/core/compile.cjs +8 -0
- package/node_modules/zod/v4/core/compile.js +8 -0
- package/node_modules/zod/v4/core/schemas.cjs +30 -0
- package/node_modules/zod/v4/core/schemas.d.cts +3 -1
- package/node_modules/zod/v4/core/schemas.d.ts +3 -1
- package/node_modules/zod/v4/core/schemas.js +30 -0
- package/node_modules/zod/v4/core/util.cjs +15 -0
- package/node_modules/zod/v4/core/util.d.cts +2 -0
- package/node_modules/zod/v4/core/util.d.ts +2 -0
- package/node_modules/zod/v4/core/util.js +14 -0
- package/node_modules/zod/v4/core/versions.cjs +1 -1
- package/node_modules/zod/v4/core/versions.js +1 -1
- package/openclaw.plugin.json +6 -30
- package/package.json +7 -7
- package/dist/.setup/action-runtime.runtime-vLxx_7s2.mjs +0 -2
- package/dist/.setup/http-C9sM-FXe.mjs +0 -2
- package/dist/.setup/plugin-routes-D4qozHVn.mjs +0 -22
- package/dist/.setup/probe-IiHogLQN.mjs +0 -694
- package/dist/.setup/registry-DizWcnNp.mjs +0 -36
- package/dist/.setup/runtime-setter-api-CMFvhrAr.mjs +0 -3
- package/dist/.setup/secret-contract-api-DK9gZldc.mjs +0 -3
- package/dist/.setup/setup-plugin-api-BGD1TYnK.mjs +0 -3
- package/dist/.setup/shared-BhJHIZs1.mjs +0 -259
- package/dist/http-routes-api.js +0 -2
- package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/LICENSE +0 -22
- package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/README.md +0 -71
- package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/package.json +0 -52
- package/node_modules/@slack/bolt/node_modules/content-disposition/index.js +0 -536
- package/node_modules/@slack/bolt/node_modules/content-type/HISTORY.md +0 -29
- package/node_modules/@slack/bolt/node_modules/content-type/index.js +0 -225
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/LICENSE +0 -22
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/README.md +0 -71
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.d.ts +0 -46
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.js +0 -176
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.js.map +0 -1
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/package.json +0 -52
- package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/LICENSE +0 -22
- package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/README.md +0 -71
- package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.d.ts +0 -46
- package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.js +0 -176
- package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.js.map +0 -1
- package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/package.json +0 -52
- package/node_modules/typebox/build/system/memory/freeze.d.mts +0 -4
- package/node_modules/typebox/build/system/memory/freeze.mjs +0 -6
- /package/node_modules/@slack/bolt/node_modules/{body-parser/node_modules/content-type → content-type}/dist/index.d.ts +0 -0
- /package/node_modules/@slack/bolt/node_modules/{body-parser/node_modules/content-type → content-type}/dist/index.js +0 -0
- /package/node_modules/@slack/bolt/node_modules/{body-parser/node_modules/content-type → content-type}/dist/index.js.map +0 -0
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { a as parseSlackTarget, t as canonicalizeSlackApiTargetId } from "./target-parsing-
|
|
4
|
-
import {
|
|
5
|
-
import { _ as getSlackWriteClient, b as writeLruMapEntry, d as createSlackReadClient, h as createSlackWriteClient, o as formatSlackError, p as createSlackTokenCacheKey, s as getSlackWebApiErrorData } from "./probe-IiHogLQN.mjs";
|
|
2
|
+
import { f as resolveSlackOperationToken, s as resolveSlackAccount } from "./accounts-CGJScKtk.mjs";
|
|
3
|
+
import { a as parseSlackTarget, t as canonicalizeSlackApiTargetId } from "./target-parsing-Bx2UZniD.mjs";
|
|
4
|
+
import { Ct as markdownToSlackMrkdwnChunks, D as createSlackNativeDataBaseTextConsumer, E as buildSlackNativeDataAccessibilityText, F as truncateSlackText, I as truncateSlackTextByUtf8Bytes, J as resolveSlackQuestionActionIds, M as renderSlackNativeDataPlainTextBlock, N as stripSlackNativeDataBlocks, O as hasSlackNativeDataBlock, R as SLACK_QUESTION_FINALIZATION_BLOCKS, S as assertSlackDetachedTargetAllowed, St as chunkSlackMrkdwnText, at as buildSlackCompleteBlocksFallbackText, bt as SLACK_MESSAGE_TEXT_RECOMMENDED_LIMIT, h as getSlackWebApiErrorData, k as isSlackInvalidBlocksError, m as formatSlackError, ot as renderSlackBlockFallbackText, rt as validateSlackBlocksArray, vt as SLACK_EDIT_TEXT_MAX_BYTES, xt as SLACK_TEXT_LIMIT, yt as SLACK_MESSAGE_TEXT_HARD_LIMIT } from "./probe-DANukR3O.mjs";
|
|
6
5
|
import { r as resolveSlackThreadTsValue, t as normalizeSlackThreadTsCandidate } from "./thread-ts-Cvt7WD6B.mjs";
|
|
6
|
+
import { c as createSlackWriteClient, d as getOrCreateWeakOwnerMap, i as createSlackReadClient, m as writeLruMapEntry, o as createSlackTokenCacheKey, u as getSlackWriteClient } from "./cursor-pages-CATAzbTT.mjs";
|
|
7
7
|
import { t as getOptionalSlackRuntime } from "./runtime-JSVZSWAj.mjs";
|
|
8
|
-
import { resolveGlobalSingleton } from "openclaw/plugin-sdk/global-singleton";
|
|
9
8
|
import { asOptionalObjectRecord, asOptionalRecord, isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
9
|
+
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
10
10
|
import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
|
|
11
11
|
import { logVerbose, sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
|
|
12
12
|
import { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking";
|
|
13
|
-
import {
|
|
13
|
+
import { resolveGlobalSingleton } from "openclaw/plugin-sdk/global-singleton";
|
|
14
14
|
import { resolveTextChunksWithFallback } from "openclaw/plugin-sdk/reply-payload";
|
|
15
15
|
import { createHash, createHmac } from "node:crypto";
|
|
16
16
|
import { withTrustedEnvProxyGuardedFetchMode } from "openclaw/plugin-sdk/fetch-runtime";
|
|
@@ -112,63 +112,9 @@ function buildSlackMessageIdentityPayload(identity) {
|
|
|
112
112
|
...identity?.iconUrl ? { icon_url: identity.iconUrl } : identity?.iconEmoji ? { icon_emoji: identity.iconEmoji } : {}
|
|
113
113
|
};
|
|
114
114
|
}
|
|
115
|
-
function classifySlackCustomIdentityError(err) {
|
|
116
|
-
const data = getSlackWebApiErrorData(err);
|
|
117
|
-
const code = normalizeLowercaseStringOrEmpty(data?.error);
|
|
118
|
-
if (code === "invalid_arguments" || code === "invalid_arg_name") return "argument";
|
|
119
|
-
if (code !== "missing_scope") return;
|
|
120
|
-
if (normalizeLowercaseStringOrEmpty(data?.needed).includes("chat:write.customize")) return "scope";
|
|
121
|
-
return [...normalizeTrimmedStringList(data?.response_metadata?.scopes), ...normalizeTrimmedStringList(data?.response_metadata?.acceptedScopes)].map((scope) => normalizeLowercaseStringOrEmpty(scope)).includes("chat:write.customize") ? "scope" : void 0;
|
|
122
|
-
}
|
|
123
115
|
function hasSlackMessageIdentity(identity) {
|
|
124
116
|
return Boolean(identity?.username || identity?.iconUrl || identity?.iconEmoji);
|
|
125
117
|
}
|
|
126
|
-
/** Post with the requested identity, degrading only on Slack identity-specific errors. */
|
|
127
|
-
async function postSlackMessageWithIdentityFallback(params) {
|
|
128
|
-
const { basePayload, identity, post } = params;
|
|
129
|
-
try {
|
|
130
|
-
if (!identity) return await post(basePayload);
|
|
131
|
-
return await post({
|
|
132
|
-
...basePayload,
|
|
133
|
-
...buildSlackMessageIdentityPayload(identity)
|
|
134
|
-
}, identity);
|
|
135
|
-
} catch (err) {
|
|
136
|
-
if (!identity || !hasSlackMessageIdentity(identity)) throw err;
|
|
137
|
-
const rejection = classifySlackCustomIdentityError(err);
|
|
138
|
-
if (!rejection) throw err;
|
|
139
|
-
if (rejection === "argument" && identity.username && (identity.iconUrl || identity.iconEmoji)) {
|
|
140
|
-
logVerbose("slack send: custom icon rejected, retrying with username only");
|
|
141
|
-
try {
|
|
142
|
-
return await post({
|
|
143
|
-
...basePayload,
|
|
144
|
-
username: identity.username
|
|
145
|
-
}, { username: identity.username });
|
|
146
|
-
} catch (retryError) {
|
|
147
|
-
if (!classifySlackCustomIdentityError(retryError)) throw retryError;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
logVerbose("slack send: custom identity rejected, retrying without custom identity");
|
|
151
|
-
return post(basePayload);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
//#endregion
|
|
155
|
-
//#region extensions/slack/src/post-message-payload.ts
|
|
156
|
-
function buildSlackPostMessagePayload(params) {
|
|
157
|
-
const threadPayload = params.replyBroadcast && params.threadTs ? {
|
|
158
|
-
thread_ts: params.threadTs,
|
|
159
|
-
reply_broadcast: true
|
|
160
|
-
} : params.threadTs ? { thread_ts: params.threadTs } : {};
|
|
161
|
-
return {
|
|
162
|
-
channel: params.channelId,
|
|
163
|
-
text: params.text,
|
|
164
|
-
...params.blocks?.length ? { blocks: params.blocks } : {},
|
|
165
|
-
...params.metadata ? { metadata: params.metadata } : {},
|
|
166
|
-
...typeof params.mrkdwn === "boolean" ? { mrkdwn: params.mrkdwn } : {},
|
|
167
|
-
...threadPayload,
|
|
168
|
-
unfurl_links: params.unfurl?.unfurlLinks ?? false,
|
|
169
|
-
...typeof params.unfurl?.unfurlMedia === "boolean" ? { unfurl_media: params.unfurl.unfurlMedia } : {}
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
118
|
//#endregion
|
|
173
119
|
//#region extensions/slack/src/client-delivery.ts
|
|
174
120
|
const SLACK_COMMERCIAL_API_HOSTNAME = "slack.com";
|
|
@@ -291,18 +237,61 @@ function requireSlackPostMessageTimestamp(response) {
|
|
|
291
237
|
if (!timestamp) throw new Error("Slack chat.postMessage returned no message timestamp");
|
|
292
238
|
return timestamp;
|
|
293
239
|
}
|
|
240
|
+
function classifySlackCustomIdentityError(err) {
|
|
241
|
+
const data = getSlackWebApiErrorData(err);
|
|
242
|
+
const code = normalizeLowercaseStringOrEmpty(data?.error);
|
|
243
|
+
if (code === "invalid_arguments" || code === "invalid_arg_name") return "argument";
|
|
244
|
+
if (code !== "missing_scope") return;
|
|
245
|
+
if (normalizeLowercaseStringOrEmpty(data?.needed).includes("chat:write.customize")) return "scope";
|
|
246
|
+
return [...normalizeTrimmedStringList(data?.response_metadata?.scopes), ...normalizeTrimmedStringList(data?.response_metadata?.acceptedScopes)].map((scope) => normalizeLowercaseStringOrEmpty(scope)).includes("chat:write.customize") ? "scope" : void 0;
|
|
247
|
+
}
|
|
294
248
|
async function postSlackMessageBestEffort(params) {
|
|
295
|
-
const
|
|
249
|
+
const threadPayload = params.replyBroadcast && params.threadTs ? {
|
|
250
|
+
thread_ts: params.threadTs,
|
|
251
|
+
reply_broadcast: true
|
|
252
|
+
} : params.threadTs ? { thread_ts: params.threadTs } : {};
|
|
253
|
+
const basePayload = {
|
|
254
|
+
channel: params.channelId,
|
|
255
|
+
text: params.text,
|
|
256
|
+
...params.blocks?.length ? { blocks: params.blocks } : {},
|
|
257
|
+
...params.metadata ? { metadata: params.metadata } : {},
|
|
258
|
+
...params.mrkdwn !== void 0 ? { mrkdwn: params.mrkdwn } : {},
|
|
259
|
+
...threadPayload,
|
|
260
|
+
unfurl_links: params.unfurl?.unfurlLinks ?? false,
|
|
261
|
+
...params.unfurl?.unfurlMedia !== void 0 ? { unfurl_media: params.unfurl.unfurlMedia } : {}
|
|
262
|
+
};
|
|
296
263
|
const postChatMessage = params.client.chat.postMessage.bind(params.client.chat);
|
|
297
264
|
const post = async (payload, identity) => ({
|
|
298
265
|
response: await withSlackDnsRequestRetry("chat.postMessage", () => postChatMessage(payload)).catch(rethrowSlackPermanentOutboundApiRejection),
|
|
299
266
|
identity
|
|
300
267
|
});
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
268
|
+
const identity = params.identity;
|
|
269
|
+
const posted = await (async () => {
|
|
270
|
+
try {
|
|
271
|
+
if (!identity) return await post(basePayload);
|
|
272
|
+
return await post({
|
|
273
|
+
...basePayload,
|
|
274
|
+
...buildSlackMessageIdentityPayload(identity)
|
|
275
|
+
}, identity);
|
|
276
|
+
} catch (err) {
|
|
277
|
+
if (!identity || !hasSlackMessageIdentity(identity)) throw err;
|
|
278
|
+
const rejection = classifySlackCustomIdentityError(err);
|
|
279
|
+
if (!rejection) throw err;
|
|
280
|
+
if (rejection === "argument" && identity.username && (identity.iconUrl || identity.iconEmoji)) {
|
|
281
|
+
logVerbose("slack send: custom icon rejected, retrying with username only");
|
|
282
|
+
try {
|
|
283
|
+
return await post({
|
|
284
|
+
...basePayload,
|
|
285
|
+
username: identity.username
|
|
286
|
+
}, { username: identity.username });
|
|
287
|
+
} catch (retryError) {
|
|
288
|
+
if (!classifySlackCustomIdentityError(retryError)) throw retryError;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
logVerbose("slack send: custom identity rejected, retrying without custom identity");
|
|
292
|
+
return post(basePayload);
|
|
293
|
+
}
|
|
294
|
+
})();
|
|
306
295
|
const timestamp = requireSlackPostMessageTimestamp(posted.response);
|
|
307
296
|
return {
|
|
308
297
|
...posted,
|
|
@@ -463,18 +452,11 @@ const slackDmChannelCaches = /* @__PURE__ */ new WeakMap();
|
|
|
463
452
|
function createSlackDmCacheKey(params) {
|
|
464
453
|
return `${params.accountId ?? "default"}:${createSlackTokenCacheKey(params.token)}:${params.recipientId}`;
|
|
465
454
|
}
|
|
466
|
-
function getSlackDmChannelCache(client) {
|
|
467
|
-
const existing = slackDmChannelCaches.get(client);
|
|
468
|
-
if (existing) return existing;
|
|
469
|
-
const cache = /* @__PURE__ */ new Map();
|
|
470
|
-
slackDmChannelCaches.set(client, cache);
|
|
471
|
-
return cache;
|
|
472
|
-
}
|
|
473
455
|
function readCachedSlackDmChannelId(params) {
|
|
474
|
-
return
|
|
456
|
+
return slackDmChannelCaches.get(params.cacheOwner)?.get(createSlackDmCacheKey(params));
|
|
475
457
|
}
|
|
476
458
|
function cacheSlackDmChannelId(params, channelId) {
|
|
477
|
-
const cache =
|
|
459
|
+
const cache = getOrCreateWeakOwnerMap(slackDmChannelCaches, params.cacheOwner);
|
|
478
460
|
const key = createSlackDmCacheKey(params);
|
|
479
461
|
writeLruMapEntry(cache, key, channelId, SLACK_DM_CHANNEL_CACHE_MAX);
|
|
480
462
|
}
|
|
@@ -542,17 +524,23 @@ function resolvePostedMessageThreadTs(response) {
|
|
|
542
524
|
}
|
|
543
525
|
async function updateMessageSlack(params) {
|
|
544
526
|
const cfg = requireRuntimeConfig(params.cfg, "Slack update");
|
|
545
|
-
const
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
527
|
+
const { client } = resolveSlackDelivery({
|
|
528
|
+
account: resolveSlackAccount({
|
|
529
|
+
cfg,
|
|
530
|
+
accountId: params.accountId
|
|
531
|
+
}),
|
|
532
|
+
eventScope: params.eventScope,
|
|
533
|
+
opts: {
|
|
534
|
+
cfg,
|
|
535
|
+
token: params.token
|
|
536
|
+
},
|
|
537
|
+
recipient: {
|
|
538
|
+
kind: "channel",
|
|
539
|
+
id: params.channelId,
|
|
540
|
+
teamId: params.teamId
|
|
541
|
+
}
|
|
554
542
|
});
|
|
555
|
-
await
|
|
543
|
+
await client.chat.update({
|
|
556
544
|
channel: params.channelId,
|
|
557
545
|
ts: params.messageTs,
|
|
558
546
|
text: truncateSlackTextByUtf8Bytes(params.text, SLACK_EDIT_TEXT_MAX_BYTES),
|
|
@@ -629,19 +617,20 @@ function parseEnterpriseEventRecipient(raw) {
|
|
|
629
617
|
function resolveSlackDelivery(params) {
|
|
630
618
|
if (params.eventScope) {
|
|
631
619
|
if (!params.eventScope.writeClient) throw new Error("missing_enterprise_slack_write_client");
|
|
632
|
-
return
|
|
620
|
+
return {
|
|
633
621
|
client: params.eventScope.writeClient,
|
|
634
622
|
credential: SLACK_ENTERPRISE_LISTENER_QUEUE_CREDENTIAL,
|
|
635
623
|
identity: normalizeSlackSendIdentity(params.opts.identity),
|
|
636
624
|
recipient: params.recipient,
|
|
637
625
|
teamId: params.eventScope.teamId,
|
|
638
626
|
unfurl: { unfurlMedia: params.account.config.unfurlMedia },
|
|
639
|
-
upload:
|
|
627
|
+
upload: {
|
|
640
628
|
client: params.eventScope.client,
|
|
641
629
|
auditContext: "slack-enterprise-immediate-upload"
|
|
642
|
-
}
|
|
643
|
-
}
|
|
630
|
+
}
|
|
631
|
+
};
|
|
644
632
|
}
|
|
633
|
+
assertSlackDetachedTargetAllowed(params.account.accountId, params.recipient.teamId);
|
|
645
634
|
const credential = resolveToken({
|
|
646
635
|
explicit: params.opts.token,
|
|
647
636
|
accountId: params.account.accountId,
|
|
@@ -650,7 +639,7 @@ function resolveSlackDelivery(params) {
|
|
|
650
639
|
});
|
|
651
640
|
const cachedClient = params.recipient.teamId ? getSlackWriteClient(credential, { teamId: params.recipient.teamId }) : params.opts.client ?? getSlackWriteClient(credential);
|
|
652
641
|
const client = params.opts.assertDirectAdapterHandoff ? createSlackWriteClient(credential, { teamId: params.recipient.teamId }, params.opts.assertDirectAdapterHandoff) : cachedClient;
|
|
653
|
-
return
|
|
642
|
+
return {
|
|
654
643
|
client,
|
|
655
644
|
...client !== cachedClient ? { dmCacheOwner: cachedClient } : {},
|
|
656
645
|
credential,
|
|
@@ -661,7 +650,7 @@ function resolveSlackDelivery(params) {
|
|
|
661
650
|
unfurlLinks: params.account.config.unfurlLinks,
|
|
662
651
|
unfurlMedia: params.account.config.unfurlMedia
|
|
663
652
|
}
|
|
664
|
-
}
|
|
653
|
+
};
|
|
665
654
|
}
|
|
666
655
|
async function resolveChannelId(client, recipient, params) {
|
|
667
656
|
if (recipient.kind !== "user") return recipient.id;
|
|
@@ -678,20 +667,6 @@ async function resolveChannelId(client, recipient, params) {
|
|
|
678
667
|
cacheSlackDmChannelId(cacheParams, channelId);
|
|
679
668
|
return channelId;
|
|
680
669
|
}
|
|
681
|
-
function resolveSlackTextChunks(params) {
|
|
682
|
-
const text = params.text;
|
|
683
|
-
const chunkLimit = params.chunkLimit;
|
|
684
|
-
if (params.preservePlainText) return text ? chunkTextForOutbound(text, chunkLimit, { preserveWhitespace: true }) : [];
|
|
685
|
-
if (params.textIsSlackMrkdwn) return resolveTextChunksWithFallback(text, chunkSlackMrkdwnText(text, chunkLimit));
|
|
686
|
-
const tableMode = resolveMarkdownTableMode({
|
|
687
|
-
cfg: params.cfg,
|
|
688
|
-
channel: "slack",
|
|
689
|
-
...params.accountId ? { accountId: params.accountId } : {}
|
|
690
|
-
});
|
|
691
|
-
const chunkMode = resolveChunkMode(params.cfg, "slack", params.accountId);
|
|
692
|
-
const chunks = (chunkMode === "newline" ? chunkMarkdownTextWithMode(text, chunkLimit, chunkMode) : [text]).flatMap((markdown) => markdownToSlackMrkdwnChunks(markdown, chunkLimit, { tableMode }));
|
|
693
|
-
return resolveTextChunksWithFallback(text, chunks);
|
|
694
|
-
}
|
|
695
670
|
async function resolveSlackDmChannelId(params) {
|
|
696
671
|
return await resolveChannelId(params.client, {
|
|
697
672
|
kind: "user",
|
|
@@ -762,37 +737,8 @@ const SLACK_RECONCILIATION_EVIDENCE_RANK = {
|
|
|
762
737
|
conflict: 2,
|
|
763
738
|
complete: 3
|
|
764
739
|
};
|
|
765
|
-
function findSlackConversationDeliveryParts(params) {
|
|
766
|
-
const matches = [];
|
|
767
|
-
for (const message of params.messages) {
|
|
768
|
-
const marker = asOptionalRecord(asOptionalRecord(message.metadata)?.event_payload);
|
|
769
|
-
if (!marker || marker[SLACK_DELIVERY_METADATA_KEY] !== params.deliveryId) continue;
|
|
770
|
-
const partIndex = marker[SLACK_DELIVERY_METADATA_PART_INDEX_KEY];
|
|
771
|
-
const partCount = marker[SLACK_DELIVERY_METADATA_PART_COUNT_KEY];
|
|
772
|
-
if (typeof partIndex !== "number" || !Number.isInteger(partIndex) || typeof partCount !== "number" || !Number.isInteger(partCount) || partIndex < 0 || partCount <= 0 || partIndex >= partCount) continue;
|
|
773
|
-
const expectedSignature = createSlackDeliveryMetadataSignature({
|
|
774
|
-
queueId: params.queueId,
|
|
775
|
-
channelId: params.channelId,
|
|
776
|
-
threadTs: params.threadTs,
|
|
777
|
-
partIndex,
|
|
778
|
-
partCount
|
|
779
|
-
});
|
|
780
|
-
const actualSignature = marker[SLACK_DELIVERY_METADATA_SIGNATURE_KEY];
|
|
781
|
-
if (typeof actualSignature !== "string" || !safeEqualSecret(actualSignature, expectedSignature)) continue;
|
|
782
|
-
const messageId = typeof message.ts === "string" ? normalizeSlackThreadTsCandidate(message.ts) : void 0;
|
|
783
|
-
if (!messageId) continue;
|
|
784
|
-
const threadTs = typeof message.thread_ts === "string" ? normalizeSlackThreadTsCandidate(message.thread_ts) : void 0;
|
|
785
|
-
matches.push({
|
|
786
|
-
messageId,
|
|
787
|
-
partIndex,
|
|
788
|
-
partCount,
|
|
789
|
-
...threadTs ? { threadTs } : {}
|
|
790
|
-
});
|
|
791
|
-
}
|
|
792
|
-
return matches;
|
|
793
|
-
}
|
|
794
740
|
async function scanSlackConversationForDelivery(params) {
|
|
795
|
-
const
|
|
741
|
+
const lookupThreadTs = params.threadTs;
|
|
796
742
|
let cursor;
|
|
797
743
|
let expectedPartCount;
|
|
798
744
|
const deliveryParts = /* @__PURE__ */ new Map();
|
|
@@ -805,17 +751,36 @@ async function scanSlackConversationForDelivery(params) {
|
|
|
805
751
|
limit: SLACK_RECONCILE_LIMIT,
|
|
806
752
|
...cursor ? { cursor } : {}
|
|
807
753
|
};
|
|
808
|
-
const response =
|
|
754
|
+
const response = lookupThreadTs ? await withSlackDnsRequestRetry("conversations.replies", () => params.client.conversations.replies({
|
|
809
755
|
...query,
|
|
810
|
-
ts:
|
|
756
|
+
ts: lookupThreadTs
|
|
811
757
|
})) : await withSlackDnsRequestRetry("conversations.history", () => params.client.conversations.history(query));
|
|
812
|
-
const matches =
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
758
|
+
const matches = [];
|
|
759
|
+
for (const message of asSlackConversationMessages(response)) {
|
|
760
|
+
const marker = asOptionalRecord(asOptionalRecord(message.metadata)?.event_payload);
|
|
761
|
+
if (!marker || marker[SLACK_DELIVERY_METADATA_KEY] !== params.deliveryId) continue;
|
|
762
|
+
const partIndex = marker[SLACK_DELIVERY_METADATA_PART_INDEX_KEY];
|
|
763
|
+
const partCount = marker[SLACK_DELIVERY_METADATA_PART_COUNT_KEY];
|
|
764
|
+
if (typeof partIndex !== "number" || !Number.isInteger(partIndex) || typeof partCount !== "number" || !Number.isInteger(partCount) || partIndex < 0 || partCount <= 0 || partIndex >= partCount) continue;
|
|
765
|
+
const expectedSignature = createSlackDeliveryMetadataSignature({
|
|
766
|
+
queueId: params.queueId,
|
|
767
|
+
channelId: params.channelId,
|
|
768
|
+
threadTs: lookupThreadTs,
|
|
769
|
+
partIndex,
|
|
770
|
+
partCount
|
|
771
|
+
});
|
|
772
|
+
const actualSignature = marker[SLACK_DELIVERY_METADATA_SIGNATURE_KEY];
|
|
773
|
+
if (typeof actualSignature !== "string" || !safeEqualSecret(actualSignature, expectedSignature)) continue;
|
|
774
|
+
const messageId = typeof message.ts === "string" ? normalizeSlackThreadTsCandidate(message.ts) : void 0;
|
|
775
|
+
if (!messageId) continue;
|
|
776
|
+
const threadTs = typeof message.thread_ts === "string" ? normalizeSlackThreadTsCandidate(message.thread_ts) : void 0;
|
|
777
|
+
matches.push({
|
|
778
|
+
messageId,
|
|
779
|
+
partIndex,
|
|
780
|
+
partCount,
|
|
781
|
+
...threadTs ? { threadTs } : {}
|
|
782
|
+
});
|
|
783
|
+
}
|
|
819
784
|
for (const match of matches) {
|
|
820
785
|
expectedPartCount ??= match.partCount;
|
|
821
786
|
const existing = deliveryParts.get(match.partIndex);
|
|
@@ -921,209 +886,207 @@ async function reconcileSlackUnknownSend(ctx) {
|
|
|
921
886
|
return unresolvedSlackDelivery(readSlackRequestErrorMessage(enrichSlackWebApiError(err)), ctx.retryCount < 3);
|
|
922
887
|
}
|
|
923
888
|
}
|
|
924
|
-
async function sendMessageSlack(to, message,
|
|
889
|
+
async function sendMessageSlack(to, message, options) {
|
|
925
890
|
const normalizedMessage = normalizeOptionalString(message) ?? "";
|
|
926
|
-
const trimmedMessage =
|
|
927
|
-
const cfg = requireRuntimeConfig(
|
|
891
|
+
const trimmedMessage = options.textIsSlackPlainText && normalizedMessage ? message : normalizedMessage;
|
|
892
|
+
const cfg = requireRuntimeConfig(options.cfg, "Slack send");
|
|
928
893
|
const account = resolveSlackAccount({
|
|
929
894
|
cfg,
|
|
930
|
-
accountId:
|
|
895
|
+
accountId: options.accountId
|
|
931
896
|
});
|
|
932
|
-
const eventScope =
|
|
897
|
+
const eventScope = options.eventScope;
|
|
933
898
|
if (eventScope && (!/^T[A-Z0-9]+$/i.test(eventScope.teamId) || !eventScope.client)) throw new Error("invalid_enterprise_slack_listener_scope");
|
|
934
|
-
const
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
const queuedOpts = Object.freeze({ ...opts });
|
|
899
|
+
const parsedRecipient = eventScope ? parseEnterpriseEventRecipient(to) : parseRecipient(to);
|
|
900
|
+
const blocks = options.blocks == null ? void 0 : validateSlackBlocksArray(options.blocks);
|
|
901
|
+
if (!normalizedMessage && !options.mediaUrl && !blocks) throw new Error("Slack send requires text, blocks, or media");
|
|
902
|
+
const opts = { ...options };
|
|
939
903
|
const delivery = resolveSlackDelivery({
|
|
940
904
|
account,
|
|
941
905
|
eventScope,
|
|
942
|
-
opts
|
|
943
|
-
recipient
|
|
906
|
+
opts,
|
|
907
|
+
recipient: parsedRecipient
|
|
944
908
|
});
|
|
945
909
|
const workspaceScope = delivery.teamId ? `:${delivery.teamId}` : "";
|
|
946
|
-
const queueKey = `${account.accountId}:${createSlackTokenCacheKey(delivery.credential)}${workspaceScope}:${delivery.recipient.kind}:${delivery.recipient.id}:${
|
|
947
|
-
const
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
}));
|
|
957
|
-
const threadTs = result.threadTs ?? normalizeSlackThreadTsCandidate(queuedOpts.threadTs);
|
|
958
|
-
if (threadTs && result.channelId && account.accountId) recordSlackThreadParticipation(account.accountId, result.channelId, threadTs, { teamId: delivery.teamId });
|
|
959
|
-
return result;
|
|
960
|
-
}
|
|
961
|
-
async function sendMessageSlackQueued(params) {
|
|
962
|
-
const { opts, cfg, account, blocks, trimmedMessage, delivery } = params;
|
|
963
|
-
const { client, identity, recipient, unfurl } = delivery;
|
|
964
|
-
if (opts.replyBroadcast && opts.mediaUrl) throw new Error("Slack replyBroadcast is only supported for text or block thread replies.");
|
|
965
|
-
const directUserPostChannelId = !opts.deliveryQueueId && recipient.kind === "user" && !opts.mediaUrl && !opts.threadTs ? recipient.id : void 0;
|
|
966
|
-
const channelId = directUserPostChannelId ? directUserPostChannelId : await resolveChannelId(client, recipient, {
|
|
967
|
-
accountId: account.accountId,
|
|
968
|
-
token: delivery.credential,
|
|
969
|
-
...delivery.dmCacheOwner ? { dmCacheOwner: delivery.dmCacheOwner } : {}
|
|
970
|
-
});
|
|
971
|
-
const deliveredResults = [];
|
|
972
|
-
const reportDelivery = async (result, deliveredBlocks) => {
|
|
973
|
-
const slackQuestionActionIds = resolveSlackQuestionActionIds(deliveredBlocks);
|
|
974
|
-
const deliveryResult = slackQuestionActionIds.length ? {
|
|
975
|
-
...result,
|
|
976
|
-
meta: {
|
|
977
|
-
...result.meta,
|
|
978
|
-
slackQuestionActionIds,
|
|
979
|
-
[SLACK_QUESTION_FINALIZATION_BLOCKS]: deliveredBlocks.filter((block) => block.type !== "actions")
|
|
980
|
-
}
|
|
981
|
-
} : result;
|
|
982
|
-
deliveredResults.push(deliveryResult);
|
|
983
|
-
await opts.onDeliveryResult?.(deliveryResult);
|
|
984
|
-
return deliveryResult;
|
|
985
|
-
};
|
|
986
|
-
let didDispatch = false;
|
|
987
|
-
const dispatchOnce = async () => {
|
|
988
|
-
if (didDispatch) return;
|
|
989
|
-
didDispatch = true;
|
|
990
|
-
await opts.onPlatformSendDispatch?.();
|
|
991
|
-
};
|
|
992
|
-
const explicitNativeDataFallbackBase = Object.hasOwn(opts, "nativeDataFallbackBaseText") ? opts.nativeDataFallbackBaseText?.trim() ?? "" : void 0;
|
|
993
|
-
const authoredTextPlacement = opts.authoredTextPlacement ?? "outside-blocks";
|
|
994
|
-
const nativeDataFallbackBase = blocks && authoredTextPlacement === "outside-blocks" ? explicitNativeDataFallbackBase ?? trimmedMessage : "";
|
|
995
|
-
const hasNativeData = Boolean(blocks && hasSlackNativeDataBlock(blocks));
|
|
996
|
-
const textChunkLimit = Math.min(opts.textLimit ?? resolveTextChunkLimit(cfg, "slack", account.accountId, { fallbackLimit: 8e3 }), SLACK_TEXT_LIMIT);
|
|
997
|
-
const usesOrderedBlockAccessibility = Boolean(blocks && (hasNativeData || opts.authoredTextPlacement !== void 0));
|
|
998
|
-
const orderedBlockDeliveryPlan = blocks && usesOrderedBlockAccessibility ? buildSlackNativeDataDeliveryPlan({
|
|
999
|
-
baseText: nativeDataFallbackBase,
|
|
1000
|
-
blocks,
|
|
1001
|
-
textLimit: textChunkLimit
|
|
1002
|
-
}) : void 0;
|
|
1003
|
-
const completeBlockFallbackText = blocks ? buildSlackCompleteBlocksFallbackText(blocks) : "";
|
|
1004
|
-
const rawBlockAccessibilityText = trimmedMessage ? [trimmedMessage, ...completeBlockFallbackText.includes(trimmedMessage) ? [] : [completeBlockFallbackText]].join("\n\n") : completeBlockFallbackText;
|
|
1005
|
-
const blockAccessibilityText = blocks ? orderedBlockDeliveryPlan?.accessibilityText ?? rawBlockAccessibilityText : void 0;
|
|
1006
|
-
let pendingBlockFallback = orderedBlockDeliveryPlan?.skipOriginalBlocks ? orderedBlockDeliveryPlan : void 0;
|
|
1007
|
-
let lastMessageId = "";
|
|
1008
|
-
let deliveredChannelId = channelId;
|
|
1009
|
-
let canonicalDeliveredThreadTs;
|
|
1010
|
-
let sendIdentity = identity;
|
|
1011
|
-
const postPart = async (part) => {
|
|
1012
|
-
const posted = await postSlackMessageBestEffort({
|
|
1013
|
-
client,
|
|
1014
|
-
channelId,
|
|
1015
|
-
threadTs: opts.threadTs,
|
|
1016
|
-
identity: sendIdentity,
|
|
1017
|
-
unfurl,
|
|
1018
|
-
...part
|
|
1019
|
-
});
|
|
1020
|
-
const { response } = posted;
|
|
1021
|
-
sendIdentity = posted.identity;
|
|
1022
|
-
lastMessageId = response.ts;
|
|
1023
|
-
deliveredChannelId = (typeof response.channel === "string" ? normalizeOptionalString(response.channel) : null) ?? deliveredChannelId;
|
|
1024
|
-
const responseThreadTs = resolvePostedMessageThreadTs(response);
|
|
1025
|
-
canonicalDeliveredThreadTs ??= responseThreadTs;
|
|
1026
|
-
return await reportDelivery(createSlackSendResult(response.ts, deliveredChannelId, part.blocks ? "card" : "text", responseThreadTs ?? normalizeSlackThreadTsCandidate(opts.threadTs)), part.blocks);
|
|
1027
|
-
};
|
|
1028
|
-
if (blocks && opts.mediaUrl) throw new Error("Slack send does not support blocks with mediaUrl");
|
|
1029
|
-
if (blocks) {
|
|
1030
|
-
if (pendingBlockFallback) logVerbose("slack send: native data accessibility exceeds hard limit, using text fallback");
|
|
1031
|
-
else {
|
|
1032
|
-
const accessibilityText = usesOrderedBlockAccessibility ? blockAccessibilityText ?? "Slack could not render this Block Kit message." : truncateSlackText(blockAccessibilityText ?? "", SLACK_TEXT_LIMIT);
|
|
1033
|
-
const initialBlockMetadata = withSlackDeliveryMetadata(opts.metadata, {
|
|
1034
|
-
queueId: opts.deliveryQueueId,
|
|
1035
|
-
channelId,
|
|
1036
|
-
threadTs: opts.threadTs,
|
|
1037
|
-
partIndex: 0,
|
|
1038
|
-
partCount: 1
|
|
910
|
+
const queueKey = `${account.accountId}:${createSlackTokenCacheKey(delivery.credential)}${workspaceScope}:${delivery.recipient.kind}:${delivery.recipient.id}:${options.threadTs ?? ""}`;
|
|
911
|
+
const sent = await slackSendQueue.enqueue(queueKey, async () => {
|
|
912
|
+
try {
|
|
913
|
+
const { client, identity, recipient, unfurl } = delivery;
|
|
914
|
+
if (opts.replyBroadcast && opts.mediaUrl) throw new Error("Slack replyBroadcast is only supported for text or block thread replies.");
|
|
915
|
+
const directUserPostChannelId = !opts.deliveryQueueId && recipient.kind === "user" && !opts.mediaUrl && !opts.threadTs ? recipient.id : void 0;
|
|
916
|
+
const channelId = directUserPostChannelId ? directUserPostChannelId : await resolveChannelId(client, recipient, {
|
|
917
|
+
accountId: account.accountId,
|
|
918
|
+
token: delivery.credential,
|
|
919
|
+
...delivery.dmCacheOwner ? { dmCacheOwner: delivery.dmCacheOwner } : {}
|
|
1039
920
|
});
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
921
|
+
const deliveredResults = [];
|
|
922
|
+
const reportDelivery = async (result, deliveredBlocks) => {
|
|
923
|
+
const slackQuestionActionIds = resolveSlackQuestionActionIds(deliveredBlocks);
|
|
924
|
+
const deliveryResult = slackQuestionActionIds.length ? {
|
|
925
|
+
...result,
|
|
926
|
+
meta: {
|
|
927
|
+
...result.meta,
|
|
928
|
+
slackQuestionActionIds,
|
|
929
|
+
[SLACK_QUESTION_FINALIZATION_BLOCKS]: deliveredBlocks
|
|
930
|
+
}
|
|
931
|
+
} : result;
|
|
932
|
+
deliveredResults.push(deliveryResult);
|
|
933
|
+
await opts.onDeliveryResult?.(deliveryResult);
|
|
934
|
+
return deliveryResult;
|
|
935
|
+
};
|
|
936
|
+
let didDispatch = false;
|
|
937
|
+
const dispatchOnce = async () => {
|
|
938
|
+
if (didDispatch) return;
|
|
939
|
+
didDispatch = true;
|
|
940
|
+
await opts.onPlatformSendDispatch?.();
|
|
941
|
+
};
|
|
942
|
+
const explicitNativeDataFallbackBase = Object.hasOwn(opts, "nativeDataFallbackBaseText") ? opts.nativeDataFallbackBaseText?.trim() ?? "" : void 0;
|
|
943
|
+
const authoredTextPlacement = opts.authoredTextPlacement ?? "outside-blocks";
|
|
944
|
+
const nativeDataFallbackBase = blocks && authoredTextPlacement === "outside-blocks" ? explicitNativeDataFallbackBase ?? trimmedMessage : "";
|
|
945
|
+
const hasNativeData = Boolean(blocks && hasSlackNativeDataBlock(blocks));
|
|
946
|
+
const textChunkLimit = Math.min(opts.textLimit ?? resolveTextChunkLimit(cfg, "slack", account.accountId, { fallbackLimit: 8e3 }), SLACK_TEXT_LIMIT);
|
|
947
|
+
const usesOrderedBlockAccessibility = Boolean(blocks && (hasNativeData || opts.authoredTextPlacement !== void 0));
|
|
948
|
+
const orderedBlockDeliveryPlan = blocks && usesOrderedBlockAccessibility ? buildSlackNativeDataDeliveryPlan({
|
|
949
|
+
baseText: nativeDataFallbackBase,
|
|
950
|
+
blocks,
|
|
951
|
+
textLimit: textChunkLimit
|
|
952
|
+
}) : void 0;
|
|
953
|
+
let pendingBlockFallback = orderedBlockDeliveryPlan?.skipOriginalBlocks ? orderedBlockDeliveryPlan : void 0;
|
|
954
|
+
let lastMessageId = "";
|
|
955
|
+
let deliveredChannelId = channelId;
|
|
956
|
+
let canonicalDeliveredThreadTs;
|
|
957
|
+
let sendIdentity = identity;
|
|
958
|
+
const postPart = async (part) => {
|
|
959
|
+
const posted = await postSlackMessageBestEffort({
|
|
960
|
+
client,
|
|
961
|
+
channelId,
|
|
962
|
+
threadTs: opts.threadTs,
|
|
963
|
+
identity: sendIdentity,
|
|
964
|
+
unfurl,
|
|
965
|
+
...part
|
|
966
|
+
});
|
|
967
|
+
const { response } = posted;
|
|
968
|
+
sendIdentity = posted.identity;
|
|
969
|
+
lastMessageId = response.ts;
|
|
970
|
+
deliveredChannelId = (typeof response.channel === "string" ? normalizeOptionalString(response.channel) : null) ?? deliveredChannelId;
|
|
971
|
+
const responseThreadTs = resolvePostedMessageThreadTs(response);
|
|
972
|
+
canonicalDeliveredThreadTs ??= responseThreadTs;
|
|
973
|
+
return await reportDelivery(createSlackSendResult(response.ts, deliveredChannelId, part.blocks ? "card" : "text", responseThreadTs ?? normalizeSlackThreadTsCandidate(opts.threadTs)), part.blocks);
|
|
974
|
+
};
|
|
975
|
+
if (blocks && opts.mediaUrl) throw new Error("Slack send does not support blocks with mediaUrl");
|
|
976
|
+
if (blocks) {
|
|
977
|
+
if (pendingBlockFallback) logVerbose("slack send: native data accessibility exceeds hard limit, using text fallback");
|
|
978
|
+
else {
|
|
979
|
+
let accessibilityText = orderedBlockDeliveryPlan?.accessibilityText;
|
|
980
|
+
if (accessibilityText === void 0) {
|
|
981
|
+
const fallback = buildSlackCompleteBlocksFallbackText(blocks);
|
|
982
|
+
accessibilityText = truncateSlackText(trimmedMessage ? [trimmedMessage, ...fallback.includes(trimmedMessage) ? [] : [fallback]].join("\n\n") : fallback, SLACK_TEXT_LIMIT);
|
|
983
|
+
}
|
|
984
|
+
const initialBlockMetadata = withSlackDeliveryMetadata(opts.metadata, {
|
|
985
|
+
queueId: opts.deliveryQueueId,
|
|
986
|
+
channelId,
|
|
987
|
+
threadTs: opts.threadTs,
|
|
988
|
+
partIndex: 0,
|
|
989
|
+
partCount: 1
|
|
990
|
+
});
|
|
991
|
+
await dispatchOnce();
|
|
992
|
+
try {
|
|
993
|
+
return await postPart({
|
|
994
|
+
text: accessibilityText,
|
|
995
|
+
replyBroadcast: opts.replyBroadcast,
|
|
996
|
+
blocks,
|
|
997
|
+
metadata: initialBlockMetadata,
|
|
998
|
+
...usesOrderedBlockAccessibility ? { mrkdwn: false } : {}
|
|
999
|
+
});
|
|
1000
|
+
} catch (error) {
|
|
1001
|
+
if (!hasNativeData || !isSlackInvalidBlocksError(error)) throw error;
|
|
1002
|
+
logVerbose("slack send: native data rejected, delivering complete text fallback");
|
|
1003
|
+
pendingBlockFallback = orderedBlockDeliveryPlan;
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
let messages;
|
|
1008
|
+
if (pendingBlockFallback) messages = pendingBlockFallback.fallbackMessages;
|
|
1009
|
+
else {
|
|
1010
|
+
let resolvedChunks;
|
|
1011
|
+
if (opts.textIsSlackPlainText) resolvedChunks = trimmedMessage ? chunkTextForOutbound(trimmedMessage, textChunkLimit, { preserveWhitespace: true }) : [];
|
|
1012
|
+
else if (opts.textIsSlackMrkdwn) resolvedChunks = resolveTextChunksWithFallback(trimmedMessage, chunkSlackMrkdwnText(trimmedMessage, textChunkLimit));
|
|
1013
|
+
else {
|
|
1014
|
+
const tableMode = resolveMarkdownTableMode({
|
|
1015
|
+
cfg,
|
|
1016
|
+
channel: "slack",
|
|
1017
|
+
...account.accountId ? { accountId: account.accountId } : {}
|
|
1018
|
+
});
|
|
1019
|
+
const chunkMode = resolveChunkMode(cfg, "slack", account.accountId);
|
|
1020
|
+
const chunks = (chunkMode === "newline" ? chunkMarkdownTextWithMode(trimmedMessage, textChunkLimit, chunkMode) : [trimmedMessage]).flatMap((markdown) => markdownToSlackMrkdwnChunks(markdown, textChunkLimit, { tableMode }));
|
|
1021
|
+
resolvedChunks = resolveTextChunksWithFallback(trimmedMessage, chunks);
|
|
1022
|
+
}
|
|
1023
|
+
const mediaMaxBytes = opts.mediaMaxBytes ?? (typeof account.config.mediaMaxMb === "number" ? account.config.mediaMaxMb * 1024 * 1024 : void 0);
|
|
1024
|
+
let chunksToPost;
|
|
1025
|
+
if (opts.mediaUrl) {
|
|
1026
|
+
const [firstChunk, ...rest] = resolvedChunks;
|
|
1027
|
+
lastMessageId = await uploadSlackFile({
|
|
1028
|
+
client: delivery.upload?.client ?? client,
|
|
1029
|
+
completionClient: client,
|
|
1030
|
+
channelId,
|
|
1031
|
+
mediaUrl: opts.mediaUrl,
|
|
1032
|
+
mediaAccess: opts.mediaAccess,
|
|
1033
|
+
uploadFileName: opts.uploadFileName,
|
|
1034
|
+
uploadTitle: opts.uploadTitle,
|
|
1035
|
+
mediaLocalRoots: opts.mediaLocalRoots,
|
|
1036
|
+
mediaReadFile: opts.mediaReadFile,
|
|
1037
|
+
caption: firstChunk,
|
|
1038
|
+
threadTs: opts.threadTs,
|
|
1039
|
+
maxBytes: mediaMaxBytes,
|
|
1040
|
+
...opts.forceDocument ? { optimizeImages: false } : {},
|
|
1041
|
+
onPlatformSendDispatch: dispatchOnce,
|
|
1042
|
+
assertDirectAdapterHandoff: opts.assertDirectAdapterHandoff,
|
|
1043
|
+
...delivery.upload ? { auditContext: delivery.upload.auditContext } : {}
|
|
1044
|
+
});
|
|
1045
|
+
await reportDelivery(createSlackSendResult(lastMessageId, channelId, "media", normalizeSlackThreadTsCandidate(opts.threadTs)));
|
|
1046
|
+
chunksToPost = rest;
|
|
1047
|
+
} else chunksToPost = resolvedChunks.length ? resolvedChunks : [""];
|
|
1048
|
+
messages = chunksToPost.map((text) => opts.textIsSlackPlainText ? {
|
|
1049
|
+
text,
|
|
1050
|
+
mrkdwn: false
|
|
1051
|
+
} : { text });
|
|
1052
|
+
}
|
|
1053
|
+
let questionDelivery;
|
|
1054
|
+
for (const [partIndex, part] of messages.entries()) {
|
|
1055
|
+
const carriesPrimaryMessageOptions = partIndex === 0 && !opts.mediaUrl;
|
|
1056
|
+
const baseMetadata = carriesPrimaryMessageOptions ? opts.metadata : void 0;
|
|
1057
|
+
const metadata = opts.mediaUrl ? baseMetadata : withSlackDeliveryMetadata(baseMetadata, {
|
|
1058
|
+
queueId: opts.deliveryQueueId,
|
|
1059
|
+
channelId,
|
|
1060
|
+
threadTs: opts.threadTs,
|
|
1061
|
+
partIndex,
|
|
1062
|
+
partCount: messages.length
|
|
1048
1063
|
});
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1064
|
+
if (partIndex === 0 && !opts.mediaUrl) await dispatchOnce();
|
|
1065
|
+
const partDelivery = await postPart({
|
|
1066
|
+
...part,
|
|
1067
|
+
replyBroadcast: carriesPrimaryMessageOptions ? opts.replyBroadcast : void 0,
|
|
1068
|
+
metadata
|
|
1069
|
+
});
|
|
1070
|
+
if (pendingBlockFallback && partDelivery.meta?.slackQuestionActionIds.length) questionDelivery = partDelivery;
|
|
1053
1071
|
}
|
|
1072
|
+
const deliveredThreadTs = canonicalDeliveredThreadTs ?? normalizeSlackThreadTsCandidate(opts.threadTs);
|
|
1073
|
+
return {
|
|
1074
|
+
messageId: lastMessageId,
|
|
1075
|
+
channelId: deliveredChannelId,
|
|
1076
|
+
threadTs: deliveredThreadTs,
|
|
1077
|
+
...questionDelivery?.meta ? { meta: {
|
|
1078
|
+
...questionDelivery.meta,
|
|
1079
|
+
slackQuestionMessageId: questionDelivery.messageId
|
|
1080
|
+
} } : {},
|
|
1081
|
+
receipt: createSlackSendReceiptFromResults(deliveredResults, deliveredThreadTs)
|
|
1082
|
+
};
|
|
1083
|
+
} catch (err) {
|
|
1084
|
+
throw enrichSlackWebApiError(err);
|
|
1054
1085
|
}
|
|
1055
|
-
}
|
|
1056
|
-
|
|
1057
|
-
if (
|
|
1058
|
-
|
|
1059
|
-
const resolvedChunks = resolveSlackTextChunks({
|
|
1060
|
-
cfg,
|
|
1061
|
-
accountId: account.accountId,
|
|
1062
|
-
text: trimmedMessage,
|
|
1063
|
-
chunkLimit: textChunkLimit,
|
|
1064
|
-
...opts.textIsSlackMrkdwn ? { textIsSlackMrkdwn: true } : {},
|
|
1065
|
-
...opts.textIsSlackPlainText ? { preservePlainText: true } : {}
|
|
1066
|
-
});
|
|
1067
|
-
const mediaMaxBytes = opts.mediaMaxBytes ?? (typeof account.config.mediaMaxMb === "number" ? account.config.mediaMaxMb * 1024 * 1024 : void 0);
|
|
1068
|
-
let chunksToPost;
|
|
1069
|
-
if (opts.mediaUrl) {
|
|
1070
|
-
const [firstChunk, ...rest] = resolvedChunks;
|
|
1071
|
-
lastMessageId = await uploadSlackFile({
|
|
1072
|
-
client: delivery.upload?.client ?? client,
|
|
1073
|
-
completionClient: client,
|
|
1074
|
-
channelId,
|
|
1075
|
-
mediaUrl: opts.mediaUrl,
|
|
1076
|
-
mediaAccess: opts.mediaAccess,
|
|
1077
|
-
uploadFileName: opts.uploadFileName,
|
|
1078
|
-
uploadTitle: opts.uploadTitle,
|
|
1079
|
-
mediaLocalRoots: opts.mediaLocalRoots,
|
|
1080
|
-
mediaReadFile: opts.mediaReadFile,
|
|
1081
|
-
caption: firstChunk,
|
|
1082
|
-
threadTs: opts.threadTs,
|
|
1083
|
-
maxBytes: mediaMaxBytes,
|
|
1084
|
-
...opts.forceDocument ? { optimizeImages: false } : {},
|
|
1085
|
-
onPlatformSendDispatch: dispatchOnce,
|
|
1086
|
-
assertDirectAdapterHandoff: opts.assertDirectAdapterHandoff,
|
|
1087
|
-
...delivery.upload ? { auditContext: delivery.upload.auditContext } : {}
|
|
1088
|
-
});
|
|
1089
|
-
await reportDelivery(createSlackSendResult(lastMessageId, channelId, "media", normalizeSlackThreadTsCandidate(opts.threadTs)));
|
|
1090
|
-
chunksToPost = rest;
|
|
1091
|
-
} else chunksToPost = resolvedChunks.length ? resolvedChunks : [""];
|
|
1092
|
-
messages = chunksToPost.map((text) => opts.textIsSlackPlainText ? {
|
|
1093
|
-
text,
|
|
1094
|
-
mrkdwn: false
|
|
1095
|
-
} : { text });
|
|
1096
|
-
}
|
|
1097
|
-
let questionDelivery;
|
|
1098
|
-
for (const [partIndex, part] of messages.entries()) {
|
|
1099
|
-
const carriesPrimaryMessageOptions = partIndex === 0 && !opts.mediaUrl;
|
|
1100
|
-
const baseMetadata = carriesPrimaryMessageOptions ? opts.metadata : void 0;
|
|
1101
|
-
const metadata = opts.mediaUrl ? baseMetadata : withSlackDeliveryMetadata(baseMetadata, {
|
|
1102
|
-
queueId: opts.deliveryQueueId,
|
|
1103
|
-
channelId,
|
|
1104
|
-
threadTs: opts.threadTs,
|
|
1105
|
-
partIndex,
|
|
1106
|
-
partCount: messages.length
|
|
1107
|
-
});
|
|
1108
|
-
if (partIndex === 0 && !opts.mediaUrl) await dispatchOnce();
|
|
1109
|
-
const partDelivery = await postPart({
|
|
1110
|
-
...part,
|
|
1111
|
-
replyBroadcast: carriesPrimaryMessageOptions ? opts.replyBroadcast : void 0,
|
|
1112
|
-
metadata
|
|
1113
|
-
});
|
|
1114
|
-
if (pendingBlockFallback && partDelivery.meta?.slackQuestionActionIds.length) questionDelivery = partDelivery;
|
|
1115
|
-
}
|
|
1116
|
-
const deliveredThreadTs = canonicalDeliveredThreadTs ?? normalizeSlackThreadTsCandidate(opts.threadTs);
|
|
1117
|
-
return {
|
|
1118
|
-
messageId: lastMessageId,
|
|
1119
|
-
channelId: deliveredChannelId,
|
|
1120
|
-
threadTs: deliveredThreadTs,
|
|
1121
|
-
...questionDelivery?.meta ? { meta: {
|
|
1122
|
-
...questionDelivery.meta,
|
|
1123
|
-
slackQuestionMessageId: questionDelivery.messageId
|
|
1124
|
-
} } : {},
|
|
1125
|
-
receipt: createSlackSendReceiptFromResults(deliveredResults, deliveredThreadTs)
|
|
1126
|
-
};
|
|
1086
|
+
});
|
|
1087
|
+
const threadTs = sent.threadTs ?? normalizeSlackThreadTsCandidate(opts.threadTs);
|
|
1088
|
+
if (threadTs && sent.channelId && account.accountId) recordSlackThreadParticipation(account.accountId, sent.channelId, threadTs, { teamId: delivery.teamId });
|
|
1089
|
+
return sent;
|
|
1127
1090
|
}
|
|
1128
1091
|
//#endregion
|
|
1129
|
-
export {
|
|
1092
|
+
export { clearSlackThreadFailureNotice as a, hasSlackThreadParticipation as c, recordSlackThreadParticipation as d, requireSlackPostMessageTimestamp as f, chunkSlackTextAtHardLimit as g, buildSlackNativeDataDeliveryPlan as h, updateMessageSlack as i, hasSlackThreadParticipationWithPersistence as l, hasSlackMessageIdentity as m, send_exports as n, clearSlackThreadParticipationCache as o, buildSlackMessageIdentityPayload as p, setSlackDefaultSendIdentity as r, hasSlackThreadFailureNotice as s, sendMessageSlack as t, recordSlackThreadFailureNotice as u };
|