@openclaw/slack 2026.10.10 → 2026.11.5-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/.setup/{account-inspect-Bc7TVU8F.mjs → account-inspect-DgQgj0wk.mjs} +11 -8
- package/dist/.setup/{accounts-CEgdyqoW.mjs → accounts-EaPP0fFY.mjs} +10 -1
- package/dist/.setup/{action-runtime-DPoxYao5.mjs → action-runtime-CK9QZgQl.mjs} +38 -45
- package/dist/.setup/action-runtime.runtime-CpZktret.mjs +1 -0
- package/dist/.setup/{actions-PF2cP6to.mjs → actions-s3CcFO45.mjs} +89 -76
- package/dist/.setup/{approval-handler.runtime-BtRklemy.mjs → approval-handler.runtime-Ch7BecYK.mjs} +26 -30
- package/dist/.setup/{approval-message-updates-CpwbsEj6.mjs → approval-message-updates-CqcRoa28.mjs} +1 -1
- package/dist/.setup/{channel-B6bRmYmX.mjs → channel-CAvo_WNZ.mjs} +566 -338
- package/dist/.setup/{channel-type-Dh4vwh1Y.mjs → channel-type-9Lw6yLf2.mjs} +4 -8
- package/dist/.setup/{channel.setup-BBzT6uKA.mjs → channel.setup-BlgXNuCJ.mjs} +13 -13
- package/dist/.setup/{config-schema-Cz3uId-c.mjs → config-schema-Bx1tCZB0.mjs} +3 -7
- package/dist/.setup/cursor-pages-jVn3Vkfi.mjs +309 -0
- package/dist/.setup/{directory-config-BEPra1E2.mjs → directory-config-CGvKYg9F.mjs} +3 -3
- package/dist/.setup/{directory-live-BkUwPrS0.mjs → directory-live-DNdw97LA.mjs} +4 -4
- package/dist/.setup/{doctor-contract-HK8aedwU.mjs → doctor-contract-BB2KJ9Ni.mjs} +37 -45
- package/dist/.setup/{message-tool-api-DeiQJoRV.mjs → message-tool-api-B38BpEaE.mjs} +4 -3
- package/dist/.setup/{monitor-DsZUQtTM.mjs → monitor-BD86SotB.mjs} +3397 -3672
- package/dist/.setup/{outbound-adapter-C0R5jz6S.mjs → outbound-adapter-BH6iPWBj.mjs} +30 -36
- package/dist/.setup/paths-CQZI_5WY.mjs +7 -0
- package/dist/.setup/{pipeline.runtime-CIFVL0kf.mjs → pipeline.runtime-C4ELxaRU.mjs} +415 -534
- package/dist/.setup/{policy-Bp1FvE6m.mjs → policy-C6_DdlSf.mjs} +1 -2
- package/dist/.setup/{session-status-CHkEn3HM.mjs → probe-B_Ax1vS1.mjs} +985 -622
- package/dist/.setup/question-delivery-D3qAIwuv.mjs +38 -0
- package/dist/.setup/{relay-source-DFBDTA5Z.mjs → relay-source-a8jodKuO.mjs} +11 -4
- package/dist/.setup/{replies-7DRN46EL.mjs → replies-Bq7n0gfM.mjs} +34 -19
- package/dist/.setup/{reply-blocks-DOjiDr44.mjs → reply-blocks-DyYYRrP_.mjs} +200 -205
- package/dist/.setup/{resolve-channels-BNQ1KZXh.mjs → resolve-channels-CF2JME9q.mjs} +4 -7
- package/dist/.setup/{resolve-users-C4dC8Z7D.mjs → resolve-users-DDcCAjH1.mjs} +8 -16
- package/dist/.setup/{scopes-C1aeCBa6.mjs → scopes-CzHC_dwV.mjs} +2 -1
- package/dist/.setup/{secret-contract-D0UY2JWF.mjs → secret-contract-CqVqR7MP.mjs} +4 -2
- package/dist/.setup/{secret-contract-api-BhzGpUb0.mjs → secret-contract-api-DaCXZ47j.mjs} +1 -1
- package/dist/.setup/{send-C5uXkmZV.mjs → send-WJZ73VSf.mjs} +297 -333
- package/dist/.setup/{send-results-D-o6PgtS.mjs → send-results-Bm6V1ekL.mjs} +3 -4
- package/dist/.setup/setup-plugin-api-DJXIB8CF.mjs +2 -0
- package/dist/.setup/{setup-surface-CtM1pm-9.mjs → setup-surface-uIqP2B0Y.mjs} +5 -6
- package/dist/.setup/{slash-dispatch.runtime-Bnn9a5qB.mjs → slash-dispatch.runtime-Cwuwv7FL.mjs} +2 -2
- package/dist/.setup/{target-parsing-0pRZtahO.mjs → target-parsing-DwYAP3ts.mjs} +1 -2
- package/dist/.setup/{targets-BqXz7CpG.mjs → targets-eeOxA_b_.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 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/directory-contract-api.js +1 -1
- package/dist/doctor-contract-api.js +1 -1
- package/dist/index.js +0 -6
- package/dist/message-tool-api.js +1 -1
- package/dist/runtime-api.js +10 -12
- package/dist/secret-contract-api.js +1 -1
- package/dist/setup-entry.js +2 -2
- package/dist/setup-plugin-api.js +1 -1
- package/node_modules/@slack/bolt/node_modules/@types/node/README.md +1 -1
- package/node_modules/@slack/bolt/node_modules/@types/node/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/body-parser/README.md +13 -17
- package/node_modules/@slack/bolt/node_modules/body-parser/lib/read.js +57 -74
- package/node_modules/@slack/bolt/node_modules/body-parser/lib/types/json.js +11 -11
- package/node_modules/@slack/bolt/node_modules/body-parser/lib/types/urlencoded.js +5 -5
- package/node_modules/@slack/bolt/node_modules/body-parser/lib/utils.js +15 -0
- package/node_modules/@slack/bolt/node_modules/body-parser/package.json +12 -7
- 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-DWKWaKgC.mjs +0 -1
- package/dist/.setup/http-GpAVKwSX.mjs +0 -2
- package/dist/.setup/plugin-routes-lXsy_bNV.mjs +0 -21
- package/dist/.setup/probe-C5VWf3sz.mjs +0 -686
- package/dist/.setup/registry-1G0f1zuZ.mjs +0 -34
- package/dist/.setup/setup-plugin-api-D7DoueEh.mjs +0 -2
- package/dist/.setup/shared-CohTHxM1.mjs +0 -255
- package/dist/.source-module-urls/562d694877afe9d9dcbb3b32a8883c16974738f2aa892c48d45572cdc9a62529.json +0 -1
- package/dist/http-routes-api.js +0 -1
- 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-nwUcYXjP.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-C5VWf3sz.mjs";
|
|
2
|
+
import { f as resolveSlackOperationToken, s as resolveSlackAccount } from "./accounts-EaPP0fFY.mjs";
|
|
3
|
+
import { a as parseSlackTarget, t as canonicalizeSlackApiTargetId } from "./target-parsing-DwYAP3ts.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-B_Ax1vS1.mjs";
|
|
6
5
|
import { r as resolveSlackThreadTsValue, t as normalizeSlackThreadTsCandidate } from "./thread-ts-47Au2-Yn.mjs";
|
|
6
|
+
import { c as createSlackWriteClient, d as getOrCreateWeakOwnerMap, i as createSlackReadClient, m as writeLruMapEntry, o as createSlackTokenCacheKey, u as getSlackWriteClient } from "./cursor-pages-jVn3Vkfi.mjs";
|
|
7
7
|
import { t as getOptionalSlackRuntime } from "./runtime-C6HKn7Av.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";
|
|
@@ -111,62 +111,9 @@ function buildSlackMessageIdentityPayload(identity) {
|
|
|
111
111
|
...identity?.iconUrl ? { icon_url: identity.iconUrl } : identity?.iconEmoji ? { icon_emoji: identity.iconEmoji } : {}
|
|
112
112
|
};
|
|
113
113
|
}
|
|
114
|
-
function classifySlackCustomIdentityError(err) {
|
|
115
|
-
const data = getSlackWebApiErrorData(err);
|
|
116
|
-
const code = normalizeLowercaseStringOrEmpty(data?.error);
|
|
117
|
-
if (code === "invalid_arguments" || code === "invalid_arg_name") return "argument";
|
|
118
|
-
if (code !== "missing_scope") return;
|
|
119
|
-
if (normalizeLowercaseStringOrEmpty(data?.needed).includes("chat:write.customize")) return "scope";
|
|
120
|
-
return [...normalizeTrimmedStringList(data?.response_metadata?.scopes), ...normalizeTrimmedStringList(data?.response_metadata?.acceptedScopes)].map((scope) => normalizeLowercaseStringOrEmpty(scope)).includes("chat:write.customize") ? "scope" : void 0;
|
|
121
|
-
}
|
|
122
114
|
function hasSlackMessageIdentity(identity) {
|
|
123
115
|
return Boolean(identity?.username || identity?.iconUrl || identity?.iconEmoji);
|
|
124
116
|
}
|
|
125
|
-
/** Post with the requested identity, degrading only on Slack identity-specific errors. */
|
|
126
|
-
async function postSlackMessageWithIdentityFallback(params) {
|
|
127
|
-
const { basePayload, identity, post } = params;
|
|
128
|
-
try {
|
|
129
|
-
if (!identity) return await post(basePayload);
|
|
130
|
-
return await post({
|
|
131
|
-
...basePayload,
|
|
132
|
-
...buildSlackMessageIdentityPayload(identity)
|
|
133
|
-
}, identity);
|
|
134
|
-
} catch (err) {
|
|
135
|
-
if (!identity || !hasSlackMessageIdentity(identity)) throw err;
|
|
136
|
-
const rejection = classifySlackCustomIdentityError(err);
|
|
137
|
-
if (!rejection) throw err;
|
|
138
|
-
if (rejection === "argument" && identity.username && (identity.iconUrl || identity.iconEmoji)) {
|
|
139
|
-
logVerbose("slack send: custom icon rejected, retrying with username only");
|
|
140
|
-
try {
|
|
141
|
-
return await post({
|
|
142
|
-
...basePayload,
|
|
143
|
-
username: identity.username
|
|
144
|
-
}, { username: identity.username });
|
|
145
|
-
} catch (retryError) {
|
|
146
|
-
if (!classifySlackCustomIdentityError(retryError)) throw retryError;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
logVerbose("slack send: custom identity rejected, retrying without custom identity");
|
|
150
|
-
return post(basePayload);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
// extensions/slack/src/post-message-payload.ts
|
|
154
|
-
function buildSlackPostMessagePayload(params) {
|
|
155
|
-
const threadPayload = params.replyBroadcast && params.threadTs ? {
|
|
156
|
-
thread_ts: params.threadTs,
|
|
157
|
-
reply_broadcast: true
|
|
158
|
-
} : params.threadTs ? { thread_ts: params.threadTs } : {};
|
|
159
|
-
return {
|
|
160
|
-
channel: params.channelId,
|
|
161
|
-
text: params.text,
|
|
162
|
-
...params.blocks?.length ? { blocks: params.blocks } : {},
|
|
163
|
-
...params.metadata ? { metadata: params.metadata } : {},
|
|
164
|
-
...typeof params.mrkdwn === "boolean" ? { mrkdwn: params.mrkdwn } : {},
|
|
165
|
-
...threadPayload,
|
|
166
|
-
unfurl_links: params.unfurl?.unfurlLinks ?? false,
|
|
167
|
-
...typeof params.unfurl?.unfurlMedia === "boolean" ? { unfurl_media: params.unfurl.unfurlMedia } : {}
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
117
|
// extensions/slack/src/client-delivery.ts
|
|
171
118
|
const SLACK_COMMERCIAL_API_HOSTNAME = "slack.com";
|
|
172
119
|
const SLACK_COMMERCIAL_UPLOAD_HOSTNAME = "files.slack.com";
|
|
@@ -288,18 +235,61 @@ function requireSlackPostMessageTimestamp(response) {
|
|
|
288
235
|
if (!timestamp) throw new Error("Slack chat.postMessage returned no message timestamp");
|
|
289
236
|
return timestamp;
|
|
290
237
|
}
|
|
238
|
+
function classifySlackCustomIdentityError(err) {
|
|
239
|
+
const data = getSlackWebApiErrorData(err);
|
|
240
|
+
const code = normalizeLowercaseStringOrEmpty(data?.error);
|
|
241
|
+
if (code === "invalid_arguments" || code === "invalid_arg_name") return "argument";
|
|
242
|
+
if (code !== "missing_scope") return;
|
|
243
|
+
if (normalizeLowercaseStringOrEmpty(data?.needed).includes("chat:write.customize")) return "scope";
|
|
244
|
+
return [...normalizeTrimmedStringList(data?.response_metadata?.scopes), ...normalizeTrimmedStringList(data?.response_metadata?.acceptedScopes)].map((scope) => normalizeLowercaseStringOrEmpty(scope)).includes("chat:write.customize") ? "scope" : void 0;
|
|
245
|
+
}
|
|
291
246
|
async function postSlackMessageBestEffort(params) {
|
|
292
|
-
const
|
|
247
|
+
const threadPayload = params.replyBroadcast && params.threadTs ? {
|
|
248
|
+
thread_ts: params.threadTs,
|
|
249
|
+
reply_broadcast: true
|
|
250
|
+
} : params.threadTs ? { thread_ts: params.threadTs } : {};
|
|
251
|
+
const basePayload = {
|
|
252
|
+
channel: params.channelId,
|
|
253
|
+
text: params.text,
|
|
254
|
+
...params.blocks?.length ? { blocks: params.blocks } : {},
|
|
255
|
+
...params.metadata ? { metadata: params.metadata } : {},
|
|
256
|
+
...params.mrkdwn !== void 0 ? { mrkdwn: params.mrkdwn } : {},
|
|
257
|
+
...threadPayload,
|
|
258
|
+
unfurl_links: params.unfurl?.unfurlLinks ?? false,
|
|
259
|
+
...params.unfurl?.unfurlMedia !== void 0 ? { unfurl_media: params.unfurl.unfurlMedia } : {}
|
|
260
|
+
};
|
|
293
261
|
const postChatMessage = params.client.chat.postMessage.bind(params.client.chat);
|
|
294
262
|
const post = async (payload, identity) => ({
|
|
295
263
|
response: await withSlackDnsRequestRetry("chat.postMessage", () => postChatMessage(payload)).catch(rethrowSlackPermanentOutboundApiRejection),
|
|
296
264
|
identity
|
|
297
265
|
});
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
266
|
+
const identity = params.identity;
|
|
267
|
+
const posted = await (async () => {
|
|
268
|
+
try {
|
|
269
|
+
if (!identity) return await post(basePayload);
|
|
270
|
+
return await post({
|
|
271
|
+
...basePayload,
|
|
272
|
+
...buildSlackMessageIdentityPayload(identity)
|
|
273
|
+
}, identity);
|
|
274
|
+
} catch (err) {
|
|
275
|
+
if (!identity || !hasSlackMessageIdentity(identity)) throw err;
|
|
276
|
+
const rejection = classifySlackCustomIdentityError(err);
|
|
277
|
+
if (!rejection) throw err;
|
|
278
|
+
if (rejection === "argument" && identity.username && (identity.iconUrl || identity.iconEmoji)) {
|
|
279
|
+
logVerbose("slack send: custom icon rejected, retrying with username only");
|
|
280
|
+
try {
|
|
281
|
+
return await post({
|
|
282
|
+
...basePayload,
|
|
283
|
+
username: identity.username
|
|
284
|
+
}, { username: identity.username });
|
|
285
|
+
} catch (retryError) {
|
|
286
|
+
if (!classifySlackCustomIdentityError(retryError)) throw retryError;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
logVerbose("slack send: custom identity rejected, retrying without custom identity");
|
|
290
|
+
return post(basePayload);
|
|
291
|
+
}
|
|
292
|
+
})();
|
|
303
293
|
const timestamp = requireSlackPostMessageTimestamp(posted.response);
|
|
304
294
|
return {
|
|
305
295
|
...posted,
|
|
@@ -458,18 +448,11 @@ const slackDmChannelCaches = /* @__PURE__ */ new WeakMap();
|
|
|
458
448
|
function createSlackDmCacheKey(params) {
|
|
459
449
|
return `${params.accountId ?? "default"}:${createSlackTokenCacheKey(params.token)}:${params.recipientId}`;
|
|
460
450
|
}
|
|
461
|
-
function getSlackDmChannelCache(client) {
|
|
462
|
-
const existing = slackDmChannelCaches.get(client);
|
|
463
|
-
if (existing) return existing;
|
|
464
|
-
const cache = /* @__PURE__ */ new Map();
|
|
465
|
-
slackDmChannelCaches.set(client, cache);
|
|
466
|
-
return cache;
|
|
467
|
-
}
|
|
468
451
|
function readCachedSlackDmChannelId(params) {
|
|
469
|
-
return
|
|
452
|
+
return slackDmChannelCaches.get(params.cacheOwner)?.get(createSlackDmCacheKey(params));
|
|
470
453
|
}
|
|
471
454
|
function cacheSlackDmChannelId(params, channelId) {
|
|
472
|
-
const cache =
|
|
455
|
+
const cache = getOrCreateWeakOwnerMap(slackDmChannelCaches, params.cacheOwner);
|
|
473
456
|
const key = createSlackDmCacheKey(params);
|
|
474
457
|
writeLruMapEntry(cache, key, channelId, SLACK_DM_CHANNEL_CACHE_MAX);
|
|
475
458
|
}
|
|
@@ -536,17 +519,23 @@ function resolvePostedMessageThreadTs(response) {
|
|
|
536
519
|
}
|
|
537
520
|
async function updateMessageSlack(params) {
|
|
538
521
|
const cfg = requireRuntimeConfig(params.cfg, "Slack update");
|
|
539
|
-
const
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
522
|
+
const { client } = resolveSlackDelivery({
|
|
523
|
+
account: resolveSlackAccount({
|
|
524
|
+
cfg,
|
|
525
|
+
accountId: params.accountId
|
|
526
|
+
}),
|
|
527
|
+
eventScope: params.eventScope,
|
|
528
|
+
opts: {
|
|
529
|
+
cfg,
|
|
530
|
+
token: params.token
|
|
531
|
+
},
|
|
532
|
+
recipient: {
|
|
533
|
+
kind: "channel",
|
|
534
|
+
id: params.channelId,
|
|
535
|
+
teamId: params.teamId
|
|
536
|
+
}
|
|
548
537
|
});
|
|
549
|
-
await
|
|
538
|
+
await client.chat.update({
|
|
550
539
|
channel: params.channelId,
|
|
551
540
|
ts: params.messageTs,
|
|
552
541
|
text: truncateSlackTextByUtf8Bytes(params.text, SLACK_EDIT_TEXT_MAX_BYTES),
|
|
@@ -623,19 +612,20 @@ function parseEnterpriseEventRecipient(raw) {
|
|
|
623
612
|
function resolveSlackDelivery(params) {
|
|
624
613
|
if (params.eventScope) {
|
|
625
614
|
if (!params.eventScope.writeClient) throw new Error("missing_enterprise_slack_write_client");
|
|
626
|
-
return
|
|
615
|
+
return {
|
|
627
616
|
client: params.eventScope.writeClient,
|
|
628
617
|
credential: SLACK_ENTERPRISE_LISTENER_QUEUE_CREDENTIAL,
|
|
629
618
|
identity: normalizeSlackSendIdentity(params.opts.identity),
|
|
630
619
|
recipient: params.recipient,
|
|
631
620
|
teamId: params.eventScope.teamId,
|
|
632
621
|
unfurl: { unfurlMedia: params.account.config.unfurlMedia },
|
|
633
|
-
upload:
|
|
622
|
+
upload: {
|
|
634
623
|
client: params.eventScope.client,
|
|
635
624
|
auditContext: "slack-enterprise-immediate-upload"
|
|
636
|
-
}
|
|
637
|
-
}
|
|
625
|
+
}
|
|
626
|
+
};
|
|
638
627
|
}
|
|
628
|
+
assertSlackDetachedTargetAllowed(params.account.accountId, params.recipient.teamId);
|
|
639
629
|
const credential = resolveToken({
|
|
640
630
|
explicit: params.opts.token,
|
|
641
631
|
accountId: params.account.accountId,
|
|
@@ -644,7 +634,7 @@ function resolveSlackDelivery(params) {
|
|
|
644
634
|
});
|
|
645
635
|
const cachedClient = params.recipient.teamId ? getSlackWriteClient(credential, { teamId: params.recipient.teamId }) : params.opts.client ?? getSlackWriteClient(credential);
|
|
646
636
|
const client = params.opts.assertDirectAdapterHandoff ? createSlackWriteClient(credential, { teamId: params.recipient.teamId }, params.opts.assertDirectAdapterHandoff) : cachedClient;
|
|
647
|
-
return
|
|
637
|
+
return {
|
|
648
638
|
client,
|
|
649
639
|
...client !== cachedClient ? { dmCacheOwner: cachedClient } : {},
|
|
650
640
|
credential,
|
|
@@ -655,7 +645,7 @@ function resolveSlackDelivery(params) {
|
|
|
655
645
|
unfurlLinks: params.account.config.unfurlLinks,
|
|
656
646
|
unfurlMedia: params.account.config.unfurlMedia
|
|
657
647
|
}
|
|
658
|
-
}
|
|
648
|
+
};
|
|
659
649
|
}
|
|
660
650
|
async function resolveChannelId(client, recipient, params) {
|
|
661
651
|
if (recipient.kind !== "user") return recipient.id;
|
|
@@ -672,20 +662,6 @@ async function resolveChannelId(client, recipient, params) {
|
|
|
672
662
|
cacheSlackDmChannelId(cacheParams, channelId);
|
|
673
663
|
return channelId;
|
|
674
664
|
}
|
|
675
|
-
function resolveSlackTextChunks(params) {
|
|
676
|
-
const text = params.text;
|
|
677
|
-
const chunkLimit = params.chunkLimit;
|
|
678
|
-
if (params.preservePlainText) return text ? chunkTextForOutbound(text, chunkLimit, { preserveWhitespace: true }) : [];
|
|
679
|
-
if (params.textIsSlackMrkdwn) return resolveTextChunksWithFallback(text, chunkSlackMrkdwnText(text, chunkLimit));
|
|
680
|
-
const tableMode = resolveMarkdownTableMode({
|
|
681
|
-
cfg: params.cfg,
|
|
682
|
-
channel: "slack",
|
|
683
|
-
...params.accountId ? { accountId: params.accountId } : {}
|
|
684
|
-
});
|
|
685
|
-
const chunkMode = resolveChunkMode(params.cfg, "slack", params.accountId);
|
|
686
|
-
const chunks = (chunkMode === "newline" ? chunkMarkdownTextWithMode(text, chunkLimit, chunkMode) : [text]).flatMap((markdown) => markdownToSlackMrkdwnChunks(markdown, chunkLimit, { tableMode }));
|
|
687
|
-
return resolveTextChunksWithFallback(text, chunks);
|
|
688
|
-
}
|
|
689
665
|
async function resolveSlackDmChannelId(params) {
|
|
690
666
|
return await resolveChannelId(params.client, {
|
|
691
667
|
kind: "user",
|
|
@@ -756,37 +732,8 @@ const SLACK_RECONCILIATION_EVIDENCE_RANK = {
|
|
|
756
732
|
conflict: 2,
|
|
757
733
|
complete: 3
|
|
758
734
|
};
|
|
759
|
-
function findSlackConversationDeliveryParts(params) {
|
|
760
|
-
const matches = [];
|
|
761
|
-
for (const message of params.messages) {
|
|
762
|
-
const marker = asOptionalRecord(asOptionalRecord(message.metadata)?.event_payload);
|
|
763
|
-
if (!marker || marker[SLACK_DELIVERY_METADATA_KEY] !== params.deliveryId) continue;
|
|
764
|
-
const partIndex = marker[SLACK_DELIVERY_METADATA_PART_INDEX_KEY];
|
|
765
|
-
const partCount = marker[SLACK_DELIVERY_METADATA_PART_COUNT_KEY];
|
|
766
|
-
if (typeof partIndex !== "number" || !Number.isInteger(partIndex) || typeof partCount !== "number" || !Number.isInteger(partCount) || partIndex < 0 || partCount <= 0 || partIndex >= partCount) continue;
|
|
767
|
-
const expectedSignature = createSlackDeliveryMetadataSignature({
|
|
768
|
-
queueId: params.queueId,
|
|
769
|
-
channelId: params.channelId,
|
|
770
|
-
threadTs: params.threadTs,
|
|
771
|
-
partIndex,
|
|
772
|
-
partCount
|
|
773
|
-
});
|
|
774
|
-
const actualSignature = marker[SLACK_DELIVERY_METADATA_SIGNATURE_KEY];
|
|
775
|
-
if (typeof actualSignature !== "string" || !safeEqualSecret(actualSignature, expectedSignature)) continue;
|
|
776
|
-
const messageId = typeof message.ts === "string" ? normalizeSlackThreadTsCandidate(message.ts) : void 0;
|
|
777
|
-
if (!messageId) continue;
|
|
778
|
-
const threadTs = typeof message.thread_ts === "string" ? normalizeSlackThreadTsCandidate(message.thread_ts) : void 0;
|
|
779
|
-
matches.push({
|
|
780
|
-
messageId,
|
|
781
|
-
partIndex,
|
|
782
|
-
partCount,
|
|
783
|
-
...threadTs ? { threadTs } : {}
|
|
784
|
-
});
|
|
785
|
-
}
|
|
786
|
-
return matches;
|
|
787
|
-
}
|
|
788
735
|
async function scanSlackConversationForDelivery(params) {
|
|
789
|
-
const
|
|
736
|
+
const lookupThreadTs = params.threadTs;
|
|
790
737
|
let cursor;
|
|
791
738
|
let expectedPartCount;
|
|
792
739
|
const deliveryParts = /* @__PURE__ */ new Map();
|
|
@@ -799,17 +746,36 @@ async function scanSlackConversationForDelivery(params) {
|
|
|
799
746
|
limit: SLACK_RECONCILE_LIMIT,
|
|
800
747
|
...cursor ? { cursor } : {}
|
|
801
748
|
};
|
|
802
|
-
const response =
|
|
749
|
+
const response = lookupThreadTs ? await withSlackDnsRequestRetry("conversations.replies", () => params.client.conversations.replies({
|
|
803
750
|
...query,
|
|
804
|
-
ts:
|
|
751
|
+
ts: lookupThreadTs
|
|
805
752
|
})) : await withSlackDnsRequestRetry("conversations.history", () => params.client.conversations.history(query));
|
|
806
|
-
const matches =
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
753
|
+
const matches = [];
|
|
754
|
+
for (const message of asSlackConversationMessages(response)) {
|
|
755
|
+
const marker = asOptionalRecord(asOptionalRecord(message.metadata)?.event_payload);
|
|
756
|
+
if (!marker || marker[SLACK_DELIVERY_METADATA_KEY] !== params.deliveryId) continue;
|
|
757
|
+
const partIndex = marker[SLACK_DELIVERY_METADATA_PART_INDEX_KEY];
|
|
758
|
+
const partCount = marker[SLACK_DELIVERY_METADATA_PART_COUNT_KEY];
|
|
759
|
+
if (typeof partIndex !== "number" || !Number.isInteger(partIndex) || typeof partCount !== "number" || !Number.isInteger(partCount) || partIndex < 0 || partCount <= 0 || partIndex >= partCount) continue;
|
|
760
|
+
const expectedSignature = createSlackDeliveryMetadataSignature({
|
|
761
|
+
queueId: params.queueId,
|
|
762
|
+
channelId: params.channelId,
|
|
763
|
+
threadTs: lookupThreadTs,
|
|
764
|
+
partIndex,
|
|
765
|
+
partCount
|
|
766
|
+
});
|
|
767
|
+
const actualSignature = marker[SLACK_DELIVERY_METADATA_SIGNATURE_KEY];
|
|
768
|
+
if (typeof actualSignature !== "string" || !safeEqualSecret(actualSignature, expectedSignature)) continue;
|
|
769
|
+
const messageId = typeof message.ts === "string" ? normalizeSlackThreadTsCandidate(message.ts) : void 0;
|
|
770
|
+
if (!messageId) continue;
|
|
771
|
+
const threadTs = typeof message.thread_ts === "string" ? normalizeSlackThreadTsCandidate(message.thread_ts) : void 0;
|
|
772
|
+
matches.push({
|
|
773
|
+
messageId,
|
|
774
|
+
partIndex,
|
|
775
|
+
partCount,
|
|
776
|
+
...threadTs ? { threadTs } : {}
|
|
777
|
+
});
|
|
778
|
+
}
|
|
813
779
|
for (const match of matches) {
|
|
814
780
|
expectedPartCount ??= match.partCount;
|
|
815
781
|
const existing = deliveryParts.get(match.partIndex);
|
|
@@ -915,208 +881,206 @@ async function reconcileSlackUnknownSend(ctx) {
|
|
|
915
881
|
return unresolvedSlackDelivery(readSlackRequestErrorMessage(enrichSlackWebApiError(err)), ctx.retryCount < 3);
|
|
916
882
|
}
|
|
917
883
|
}
|
|
918
|
-
async function sendMessageSlack(to, message,
|
|
884
|
+
async function sendMessageSlack(to, message, options) {
|
|
919
885
|
const normalizedMessage = normalizeOptionalString(message) ?? "";
|
|
920
|
-
const trimmedMessage =
|
|
921
|
-
const cfg = requireRuntimeConfig(
|
|
886
|
+
const trimmedMessage = options.textIsSlackPlainText && normalizedMessage ? message : normalizedMessage;
|
|
887
|
+
const cfg = requireRuntimeConfig(options.cfg, "Slack send");
|
|
922
888
|
const account = resolveSlackAccount({
|
|
923
889
|
cfg,
|
|
924
|
-
accountId:
|
|
890
|
+
accountId: options.accountId
|
|
925
891
|
});
|
|
926
|
-
const eventScope =
|
|
892
|
+
const eventScope = options.eventScope;
|
|
927
893
|
if (eventScope && (!/^T[A-Z0-9]+$/i.test(eventScope.teamId) || !eventScope.client)) throw new Error("invalid_enterprise_slack_listener_scope");
|
|
928
|
-
const
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
const queuedOpts = Object.freeze({ ...opts });
|
|
894
|
+
const parsedRecipient = eventScope ? parseEnterpriseEventRecipient(to) : parseRecipient(to);
|
|
895
|
+
const blocks = options.blocks == null ? void 0 : validateSlackBlocksArray(options.blocks);
|
|
896
|
+
if (!normalizedMessage && !options.mediaUrl && !blocks) throw new Error("Slack send requires text, blocks, or media");
|
|
897
|
+
const opts = { ...options };
|
|
933
898
|
const delivery = resolveSlackDelivery({
|
|
934
899
|
account,
|
|
935
900
|
eventScope,
|
|
936
|
-
opts
|
|
937
|
-
recipient
|
|
901
|
+
opts,
|
|
902
|
+
recipient: parsedRecipient
|
|
938
903
|
});
|
|
939
904
|
const workspaceScope = delivery.teamId ? `:${delivery.teamId}` : "";
|
|
940
|
-
const queueKey = `${account.accountId}:${createSlackTokenCacheKey(delivery.credential)}${workspaceScope}:${delivery.recipient.kind}:${delivery.recipient.id}:${
|
|
941
|
-
const
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
}));
|
|
951
|
-
const threadTs = result.threadTs ?? normalizeSlackThreadTsCandidate(queuedOpts.threadTs);
|
|
952
|
-
if (threadTs && result.channelId && account.accountId) recordSlackThreadParticipation(account.accountId, result.channelId, threadTs, { teamId: delivery.teamId });
|
|
953
|
-
return result;
|
|
954
|
-
}
|
|
955
|
-
async function sendMessageSlackQueued(params) {
|
|
956
|
-
const { opts, cfg, account, blocks, trimmedMessage, delivery } = params;
|
|
957
|
-
const { client, identity, recipient, unfurl } = delivery;
|
|
958
|
-
if (opts.replyBroadcast && opts.mediaUrl) throw new Error("Slack replyBroadcast is only supported for text or block thread replies.");
|
|
959
|
-
const directUserPostChannelId = !opts.deliveryQueueId && recipient.kind === "user" && !opts.mediaUrl && !opts.threadTs ? recipient.id : void 0;
|
|
960
|
-
const channelId = directUserPostChannelId ? directUserPostChannelId : await resolveChannelId(client, recipient, {
|
|
961
|
-
accountId: account.accountId,
|
|
962
|
-
token: delivery.credential,
|
|
963
|
-
...delivery.dmCacheOwner ? { dmCacheOwner: delivery.dmCacheOwner } : {}
|
|
964
|
-
});
|
|
965
|
-
const deliveredResults = [];
|
|
966
|
-
const reportDelivery = async (result, deliveredBlocks) => {
|
|
967
|
-
const slackQuestionActionIds = resolveSlackQuestionActionIds(deliveredBlocks);
|
|
968
|
-
const deliveryResult = slackQuestionActionIds.length ? {
|
|
969
|
-
...result,
|
|
970
|
-
meta: {
|
|
971
|
-
...result.meta,
|
|
972
|
-
slackQuestionActionIds,
|
|
973
|
-
[SLACK_QUESTION_FINALIZATION_BLOCKS]: deliveredBlocks.filter((block) => block.type !== "actions")
|
|
974
|
-
}
|
|
975
|
-
} : result;
|
|
976
|
-
deliveredResults.push(deliveryResult);
|
|
977
|
-
await opts.onDeliveryResult?.(deliveryResult);
|
|
978
|
-
return deliveryResult;
|
|
979
|
-
};
|
|
980
|
-
let didDispatch = false;
|
|
981
|
-
const dispatchOnce = async () => {
|
|
982
|
-
if (didDispatch) return;
|
|
983
|
-
didDispatch = true;
|
|
984
|
-
await opts.onPlatformSendDispatch?.();
|
|
985
|
-
};
|
|
986
|
-
const explicitNativeDataFallbackBase = Object.hasOwn(opts, "nativeDataFallbackBaseText") ? opts.nativeDataFallbackBaseText?.trim() ?? "" : void 0;
|
|
987
|
-
const authoredTextPlacement = opts.authoredTextPlacement ?? "outside-blocks";
|
|
988
|
-
const nativeDataFallbackBase = blocks && authoredTextPlacement === "outside-blocks" ? explicitNativeDataFallbackBase ?? trimmedMessage : "";
|
|
989
|
-
const hasNativeData = Boolean(blocks && hasSlackNativeDataBlock(blocks));
|
|
990
|
-
const textChunkLimit = Math.min(opts.textLimit ?? resolveTextChunkLimit(cfg, "slack", account.accountId, { fallbackLimit: 8e3 }), SLACK_TEXT_LIMIT);
|
|
991
|
-
const usesOrderedBlockAccessibility = Boolean(blocks && (hasNativeData || opts.authoredTextPlacement !== void 0));
|
|
992
|
-
const orderedBlockDeliveryPlan = blocks && usesOrderedBlockAccessibility ? buildSlackNativeDataDeliveryPlan({
|
|
993
|
-
baseText: nativeDataFallbackBase,
|
|
994
|
-
blocks,
|
|
995
|
-
textLimit: textChunkLimit
|
|
996
|
-
}) : void 0;
|
|
997
|
-
const completeBlockFallbackText = blocks ? buildSlackCompleteBlocksFallbackText(blocks) : "";
|
|
998
|
-
const rawBlockAccessibilityText = trimmedMessage ? [trimmedMessage, ...completeBlockFallbackText.includes(trimmedMessage) ? [] : [completeBlockFallbackText]].join("\n\n") : completeBlockFallbackText;
|
|
999
|
-
const blockAccessibilityText = blocks ? orderedBlockDeliveryPlan?.accessibilityText ?? rawBlockAccessibilityText : void 0;
|
|
1000
|
-
let pendingBlockFallback = orderedBlockDeliveryPlan?.skipOriginalBlocks ? orderedBlockDeliveryPlan : void 0;
|
|
1001
|
-
let lastMessageId = "";
|
|
1002
|
-
let deliveredChannelId = channelId;
|
|
1003
|
-
let canonicalDeliveredThreadTs;
|
|
1004
|
-
let sendIdentity = identity;
|
|
1005
|
-
const postPart = async (part) => {
|
|
1006
|
-
const posted = await postSlackMessageBestEffort({
|
|
1007
|
-
client,
|
|
1008
|
-
channelId,
|
|
1009
|
-
threadTs: opts.threadTs,
|
|
1010
|
-
identity: sendIdentity,
|
|
1011
|
-
unfurl,
|
|
1012
|
-
...part
|
|
1013
|
-
});
|
|
1014
|
-
const { response } = posted;
|
|
1015
|
-
sendIdentity = posted.identity;
|
|
1016
|
-
lastMessageId = response.ts;
|
|
1017
|
-
deliveredChannelId = (typeof response.channel === "string" ? normalizeOptionalString(response.channel) : null) ?? deliveredChannelId;
|
|
1018
|
-
const responseThreadTs = resolvePostedMessageThreadTs(response);
|
|
1019
|
-
canonicalDeliveredThreadTs ??= responseThreadTs;
|
|
1020
|
-
return await reportDelivery(createSlackSendResult(response.ts, deliveredChannelId, part.blocks ? "card" : "text", responseThreadTs ?? normalizeSlackThreadTsCandidate(opts.threadTs)), part.blocks);
|
|
1021
|
-
};
|
|
1022
|
-
if (blocks && opts.mediaUrl) throw new Error("Slack send does not support blocks with mediaUrl");
|
|
1023
|
-
if (blocks) {
|
|
1024
|
-
if (pendingBlockFallback) logVerbose("slack send: native data accessibility exceeds hard limit, using text fallback");
|
|
1025
|
-
else {
|
|
1026
|
-
const accessibilityText = usesOrderedBlockAccessibility ? blockAccessibilityText ?? "Slack could not render this Block Kit message." : truncateSlackText(blockAccessibilityText ?? "", SLACK_TEXT_LIMIT);
|
|
1027
|
-
const initialBlockMetadata = withSlackDeliveryMetadata(opts.metadata, {
|
|
1028
|
-
queueId: opts.deliveryQueueId,
|
|
1029
|
-
channelId,
|
|
1030
|
-
threadTs: opts.threadTs,
|
|
1031
|
-
partIndex: 0,
|
|
1032
|
-
partCount: 1
|
|
905
|
+
const queueKey = `${account.accountId}:${createSlackTokenCacheKey(delivery.credential)}${workspaceScope}:${delivery.recipient.kind}:${delivery.recipient.id}:${options.threadTs ?? ""}`;
|
|
906
|
+
const sent = await slackSendQueue.enqueue(queueKey, async () => {
|
|
907
|
+
try {
|
|
908
|
+
const { client, identity, recipient, unfurl } = delivery;
|
|
909
|
+
if (opts.replyBroadcast && opts.mediaUrl) throw new Error("Slack replyBroadcast is only supported for text or block thread replies.");
|
|
910
|
+
const directUserPostChannelId = !opts.deliveryQueueId && recipient.kind === "user" && !opts.mediaUrl && !opts.threadTs ? recipient.id : void 0;
|
|
911
|
+
const channelId = directUserPostChannelId ? directUserPostChannelId : await resolveChannelId(client, recipient, {
|
|
912
|
+
accountId: account.accountId,
|
|
913
|
+
token: delivery.credential,
|
|
914
|
+
...delivery.dmCacheOwner ? { dmCacheOwner: delivery.dmCacheOwner } : {}
|
|
1033
915
|
});
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
916
|
+
const deliveredResults = [];
|
|
917
|
+
const reportDelivery = async (result, deliveredBlocks) => {
|
|
918
|
+
const slackQuestionActionIds = resolveSlackQuestionActionIds(deliveredBlocks);
|
|
919
|
+
const deliveryResult = slackQuestionActionIds.length ? {
|
|
920
|
+
...result,
|
|
921
|
+
meta: {
|
|
922
|
+
...result.meta,
|
|
923
|
+
slackQuestionActionIds,
|
|
924
|
+
[SLACK_QUESTION_FINALIZATION_BLOCKS]: deliveredBlocks
|
|
925
|
+
}
|
|
926
|
+
} : result;
|
|
927
|
+
deliveredResults.push(deliveryResult);
|
|
928
|
+
await opts.onDeliveryResult?.(deliveryResult);
|
|
929
|
+
return deliveryResult;
|
|
930
|
+
};
|
|
931
|
+
let didDispatch = false;
|
|
932
|
+
const dispatchOnce = async () => {
|
|
933
|
+
if (didDispatch) return;
|
|
934
|
+
didDispatch = true;
|
|
935
|
+
await opts.onPlatformSendDispatch?.();
|
|
936
|
+
};
|
|
937
|
+
const explicitNativeDataFallbackBase = Object.hasOwn(opts, "nativeDataFallbackBaseText") ? opts.nativeDataFallbackBaseText?.trim() ?? "" : void 0;
|
|
938
|
+
const authoredTextPlacement = opts.authoredTextPlacement ?? "outside-blocks";
|
|
939
|
+
const nativeDataFallbackBase = blocks && authoredTextPlacement === "outside-blocks" ? explicitNativeDataFallbackBase ?? trimmedMessage : "";
|
|
940
|
+
const hasNativeData = Boolean(blocks && hasSlackNativeDataBlock(blocks));
|
|
941
|
+
const textChunkLimit = Math.min(opts.textLimit ?? resolveTextChunkLimit(cfg, "slack", account.accountId, { fallbackLimit: 8e3 }), SLACK_TEXT_LIMIT);
|
|
942
|
+
const usesOrderedBlockAccessibility = Boolean(blocks && (hasNativeData || opts.authoredTextPlacement !== void 0));
|
|
943
|
+
const orderedBlockDeliveryPlan = blocks && usesOrderedBlockAccessibility ? buildSlackNativeDataDeliveryPlan({
|
|
944
|
+
baseText: nativeDataFallbackBase,
|
|
945
|
+
blocks,
|
|
946
|
+
textLimit: textChunkLimit
|
|
947
|
+
}) : void 0;
|
|
948
|
+
let pendingBlockFallback = orderedBlockDeliveryPlan?.skipOriginalBlocks ? orderedBlockDeliveryPlan : void 0;
|
|
949
|
+
let lastMessageId = "";
|
|
950
|
+
let deliveredChannelId = channelId;
|
|
951
|
+
let canonicalDeliveredThreadTs;
|
|
952
|
+
let sendIdentity = identity;
|
|
953
|
+
const postPart = async (part) => {
|
|
954
|
+
const posted = await postSlackMessageBestEffort({
|
|
955
|
+
client,
|
|
956
|
+
channelId,
|
|
957
|
+
threadTs: opts.threadTs,
|
|
958
|
+
identity: sendIdentity,
|
|
959
|
+
unfurl,
|
|
960
|
+
...part
|
|
961
|
+
});
|
|
962
|
+
const { response } = posted;
|
|
963
|
+
sendIdentity = posted.identity;
|
|
964
|
+
lastMessageId = response.ts;
|
|
965
|
+
deliveredChannelId = (typeof response.channel === "string" ? normalizeOptionalString(response.channel) : null) ?? deliveredChannelId;
|
|
966
|
+
const responseThreadTs = resolvePostedMessageThreadTs(response);
|
|
967
|
+
canonicalDeliveredThreadTs ??= responseThreadTs;
|
|
968
|
+
return await reportDelivery(createSlackSendResult(response.ts, deliveredChannelId, part.blocks ? "card" : "text", responseThreadTs ?? normalizeSlackThreadTsCandidate(opts.threadTs)), part.blocks);
|
|
969
|
+
};
|
|
970
|
+
if (blocks && opts.mediaUrl) throw new Error("Slack send does not support blocks with mediaUrl");
|
|
971
|
+
if (blocks) {
|
|
972
|
+
if (pendingBlockFallback) logVerbose("slack send: native data accessibility exceeds hard limit, using text fallback");
|
|
973
|
+
else {
|
|
974
|
+
let accessibilityText = orderedBlockDeliveryPlan?.accessibilityText;
|
|
975
|
+
if (accessibilityText === void 0) {
|
|
976
|
+
const fallback = buildSlackCompleteBlocksFallbackText(blocks);
|
|
977
|
+
accessibilityText = truncateSlackText(trimmedMessage ? [trimmedMessage, ...fallback.includes(trimmedMessage) ? [] : [fallback]].join("\n\n") : fallback, SLACK_TEXT_LIMIT);
|
|
978
|
+
}
|
|
979
|
+
const initialBlockMetadata = withSlackDeliveryMetadata(opts.metadata, {
|
|
980
|
+
queueId: opts.deliveryQueueId,
|
|
981
|
+
channelId,
|
|
982
|
+
threadTs: opts.threadTs,
|
|
983
|
+
partIndex: 0,
|
|
984
|
+
partCount: 1
|
|
985
|
+
});
|
|
986
|
+
await dispatchOnce();
|
|
987
|
+
try {
|
|
988
|
+
return await postPart({
|
|
989
|
+
text: accessibilityText,
|
|
990
|
+
replyBroadcast: opts.replyBroadcast,
|
|
991
|
+
blocks,
|
|
992
|
+
metadata: initialBlockMetadata,
|
|
993
|
+
...usesOrderedBlockAccessibility ? { mrkdwn: false } : {}
|
|
994
|
+
});
|
|
995
|
+
} catch (error) {
|
|
996
|
+
if (!hasNativeData || !isSlackInvalidBlocksError(error)) throw error;
|
|
997
|
+
logVerbose("slack send: native data rejected, delivering complete text fallback");
|
|
998
|
+
pendingBlockFallback = orderedBlockDeliveryPlan;
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
let messages;
|
|
1003
|
+
if (pendingBlockFallback) messages = pendingBlockFallback.fallbackMessages;
|
|
1004
|
+
else {
|
|
1005
|
+
let resolvedChunks;
|
|
1006
|
+
if (opts.textIsSlackPlainText) resolvedChunks = trimmedMessage ? chunkTextForOutbound(trimmedMessage, textChunkLimit, { preserveWhitespace: true }) : [];
|
|
1007
|
+
else if (opts.textIsSlackMrkdwn) resolvedChunks = resolveTextChunksWithFallback(trimmedMessage, chunkSlackMrkdwnText(trimmedMessage, textChunkLimit));
|
|
1008
|
+
else {
|
|
1009
|
+
const tableMode = resolveMarkdownTableMode({
|
|
1010
|
+
cfg,
|
|
1011
|
+
channel: "slack",
|
|
1012
|
+
...account.accountId ? { accountId: account.accountId } : {}
|
|
1013
|
+
});
|
|
1014
|
+
const chunkMode = resolveChunkMode(cfg, "slack", account.accountId);
|
|
1015
|
+
const chunks = (chunkMode === "newline" ? chunkMarkdownTextWithMode(trimmedMessage, textChunkLimit, chunkMode) : [trimmedMessage]).flatMap((markdown) => markdownToSlackMrkdwnChunks(markdown, textChunkLimit, { tableMode }));
|
|
1016
|
+
resolvedChunks = resolveTextChunksWithFallback(trimmedMessage, chunks);
|
|
1017
|
+
}
|
|
1018
|
+
const mediaMaxBytes = opts.mediaMaxBytes ?? (typeof account.config.mediaMaxMb === "number" ? account.config.mediaMaxMb * 1024 * 1024 : void 0);
|
|
1019
|
+
let chunksToPost;
|
|
1020
|
+
if (opts.mediaUrl) {
|
|
1021
|
+
const [firstChunk, ...rest] = resolvedChunks;
|
|
1022
|
+
lastMessageId = await uploadSlackFile({
|
|
1023
|
+
client: delivery.upload?.client ?? client,
|
|
1024
|
+
completionClient: client,
|
|
1025
|
+
channelId,
|
|
1026
|
+
mediaUrl: opts.mediaUrl,
|
|
1027
|
+
mediaAccess: opts.mediaAccess,
|
|
1028
|
+
uploadFileName: opts.uploadFileName,
|
|
1029
|
+
uploadTitle: opts.uploadTitle,
|
|
1030
|
+
mediaLocalRoots: opts.mediaLocalRoots,
|
|
1031
|
+
mediaReadFile: opts.mediaReadFile,
|
|
1032
|
+
caption: firstChunk,
|
|
1033
|
+
threadTs: opts.threadTs,
|
|
1034
|
+
maxBytes: mediaMaxBytes,
|
|
1035
|
+
...opts.forceDocument ? { optimizeImages: false } : {},
|
|
1036
|
+
onPlatformSendDispatch: dispatchOnce,
|
|
1037
|
+
assertDirectAdapterHandoff: opts.assertDirectAdapterHandoff,
|
|
1038
|
+
...delivery.upload ? { auditContext: delivery.upload.auditContext } : {}
|
|
1039
|
+
});
|
|
1040
|
+
await reportDelivery(createSlackSendResult(lastMessageId, channelId, "media", normalizeSlackThreadTsCandidate(opts.threadTs)));
|
|
1041
|
+
chunksToPost = rest;
|
|
1042
|
+
} else chunksToPost = resolvedChunks.length ? resolvedChunks : [""];
|
|
1043
|
+
messages = chunksToPost.map((text) => opts.textIsSlackPlainText ? {
|
|
1044
|
+
text,
|
|
1045
|
+
mrkdwn: false
|
|
1046
|
+
} : { text });
|
|
1047
|
+
}
|
|
1048
|
+
let questionDelivery;
|
|
1049
|
+
for (const [partIndex, part] of messages.entries()) {
|
|
1050
|
+
const carriesPrimaryMessageOptions = partIndex === 0 && !opts.mediaUrl;
|
|
1051
|
+
const baseMetadata = carriesPrimaryMessageOptions ? opts.metadata : void 0;
|
|
1052
|
+
const metadata = opts.mediaUrl ? baseMetadata : withSlackDeliveryMetadata(baseMetadata, {
|
|
1053
|
+
queueId: opts.deliveryQueueId,
|
|
1054
|
+
channelId,
|
|
1055
|
+
threadTs: opts.threadTs,
|
|
1056
|
+
partIndex,
|
|
1057
|
+
partCount: messages.length
|
|
1042
1058
|
});
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1059
|
+
if (partIndex === 0 && !opts.mediaUrl) await dispatchOnce();
|
|
1060
|
+
const partDelivery = await postPart({
|
|
1061
|
+
...part,
|
|
1062
|
+
replyBroadcast: carriesPrimaryMessageOptions ? opts.replyBroadcast : void 0,
|
|
1063
|
+
metadata
|
|
1064
|
+
});
|
|
1065
|
+
if (pendingBlockFallback && partDelivery.meta?.slackQuestionActionIds.length) questionDelivery = partDelivery;
|
|
1047
1066
|
}
|
|
1067
|
+
const deliveredThreadTs = canonicalDeliveredThreadTs ?? normalizeSlackThreadTsCandidate(opts.threadTs);
|
|
1068
|
+
return {
|
|
1069
|
+
messageId: lastMessageId,
|
|
1070
|
+
channelId: deliveredChannelId,
|
|
1071
|
+
threadTs: deliveredThreadTs,
|
|
1072
|
+
...questionDelivery?.meta ? { meta: {
|
|
1073
|
+
...questionDelivery.meta,
|
|
1074
|
+
slackQuestionMessageId: questionDelivery.messageId
|
|
1075
|
+
} } : {},
|
|
1076
|
+
receipt: createSlackSendReceiptFromResults(deliveredResults, deliveredThreadTs)
|
|
1077
|
+
};
|
|
1078
|
+
} catch (err) {
|
|
1079
|
+
throw enrichSlackWebApiError(err);
|
|
1048
1080
|
}
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
|
-
if (
|
|
1052
|
-
|
|
1053
|
-
const resolvedChunks = resolveSlackTextChunks({
|
|
1054
|
-
cfg,
|
|
1055
|
-
accountId: account.accountId,
|
|
1056
|
-
text: trimmedMessage,
|
|
1057
|
-
chunkLimit: textChunkLimit,
|
|
1058
|
-
...opts.textIsSlackMrkdwn ? { textIsSlackMrkdwn: true } : {},
|
|
1059
|
-
...opts.textIsSlackPlainText ? { preservePlainText: true } : {}
|
|
1060
|
-
});
|
|
1061
|
-
const mediaMaxBytes = opts.mediaMaxBytes ?? (typeof account.config.mediaMaxMb === "number" ? account.config.mediaMaxMb * 1024 * 1024 : void 0);
|
|
1062
|
-
let chunksToPost;
|
|
1063
|
-
if (opts.mediaUrl) {
|
|
1064
|
-
const [firstChunk, ...rest] = resolvedChunks;
|
|
1065
|
-
lastMessageId = await uploadSlackFile({
|
|
1066
|
-
client: delivery.upload?.client ?? client,
|
|
1067
|
-
completionClient: client,
|
|
1068
|
-
channelId,
|
|
1069
|
-
mediaUrl: opts.mediaUrl,
|
|
1070
|
-
mediaAccess: opts.mediaAccess,
|
|
1071
|
-
uploadFileName: opts.uploadFileName,
|
|
1072
|
-
uploadTitle: opts.uploadTitle,
|
|
1073
|
-
mediaLocalRoots: opts.mediaLocalRoots,
|
|
1074
|
-
mediaReadFile: opts.mediaReadFile,
|
|
1075
|
-
caption: firstChunk,
|
|
1076
|
-
threadTs: opts.threadTs,
|
|
1077
|
-
maxBytes: mediaMaxBytes,
|
|
1078
|
-
...opts.forceDocument ? { optimizeImages: false } : {},
|
|
1079
|
-
onPlatformSendDispatch: dispatchOnce,
|
|
1080
|
-
assertDirectAdapterHandoff: opts.assertDirectAdapterHandoff,
|
|
1081
|
-
...delivery.upload ? { auditContext: delivery.upload.auditContext } : {}
|
|
1082
|
-
});
|
|
1083
|
-
await reportDelivery(createSlackSendResult(lastMessageId, channelId, "media", normalizeSlackThreadTsCandidate(opts.threadTs)));
|
|
1084
|
-
chunksToPost = rest;
|
|
1085
|
-
} else chunksToPost = resolvedChunks.length ? resolvedChunks : [""];
|
|
1086
|
-
messages = chunksToPost.map((text) => opts.textIsSlackPlainText ? {
|
|
1087
|
-
text,
|
|
1088
|
-
mrkdwn: false
|
|
1089
|
-
} : { text });
|
|
1090
|
-
}
|
|
1091
|
-
let questionDelivery;
|
|
1092
|
-
for (const [partIndex, part] of messages.entries()) {
|
|
1093
|
-
const carriesPrimaryMessageOptions = partIndex === 0 && !opts.mediaUrl;
|
|
1094
|
-
const baseMetadata = carriesPrimaryMessageOptions ? opts.metadata : void 0;
|
|
1095
|
-
const metadata = opts.mediaUrl ? baseMetadata : withSlackDeliveryMetadata(baseMetadata, {
|
|
1096
|
-
queueId: opts.deliveryQueueId,
|
|
1097
|
-
channelId,
|
|
1098
|
-
threadTs: opts.threadTs,
|
|
1099
|
-
partIndex,
|
|
1100
|
-
partCount: messages.length
|
|
1101
|
-
});
|
|
1102
|
-
if (partIndex === 0 && !opts.mediaUrl) await dispatchOnce();
|
|
1103
|
-
const partDelivery = await postPart({
|
|
1104
|
-
...part,
|
|
1105
|
-
replyBroadcast: carriesPrimaryMessageOptions ? opts.replyBroadcast : void 0,
|
|
1106
|
-
metadata
|
|
1107
|
-
});
|
|
1108
|
-
if (pendingBlockFallback && partDelivery.meta?.slackQuestionActionIds.length) questionDelivery = partDelivery;
|
|
1109
|
-
}
|
|
1110
|
-
const deliveredThreadTs = canonicalDeliveredThreadTs ?? normalizeSlackThreadTsCandidate(opts.threadTs);
|
|
1111
|
-
return {
|
|
1112
|
-
messageId: lastMessageId,
|
|
1113
|
-
channelId: deliveredChannelId,
|
|
1114
|
-
threadTs: deliveredThreadTs,
|
|
1115
|
-
...questionDelivery?.meta ? { meta: {
|
|
1116
|
-
...questionDelivery.meta,
|
|
1117
|
-
slackQuestionMessageId: questionDelivery.messageId
|
|
1118
|
-
} } : {},
|
|
1119
|
-
receipt: createSlackSendReceiptFromResults(deliveredResults, deliveredThreadTs)
|
|
1120
|
-
};
|
|
1081
|
+
});
|
|
1082
|
+
const threadTs = sent.threadTs ?? normalizeSlackThreadTsCandidate(opts.threadTs);
|
|
1083
|
+
if (threadTs && sent.channelId && account.accountId) recordSlackThreadParticipation(account.accountId, sent.channelId, threadTs, { teamId: delivery.teamId });
|
|
1084
|
+
return sent;
|
|
1121
1085
|
}
|
|
1122
|
-
export {
|
|
1086
|
+
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 };
|