@openclaw/slack 2026.7.2-beta.7 → 2026.8.1-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/{account-inspect-DEKpg9Ip.js → account-inspect-Drw2gAiN.js} +1 -1
- package/dist/account-inspect-api.js +1 -1
- package/dist/{accounts-CHAeNZOX.js → accounts-CK4AVI2_.js} +2 -2
- package/dist/{accounts.runtime-BHD4Ma2R.js → accounts.runtime-Cb7QwWBz.js} +1 -1
- package/dist/{action-runtime-DfuYoMjG.js → action-runtime-BkGe7ny_.js} +148 -76
- package/dist/action-runtime.runtime-D9I6uc0Q.js +2 -0
- package/dist/{actions-D3NuJvva.js → actions-BTDXwwE3.js} +85 -44
- package/dist/actions.runtime-DLFyUkvg.js +2 -0
- package/dist/api.js +15 -15
- package/dist/{approval-handler.runtime-BA05P0QT.js → approval-handler.runtime-CJaNzAq2.js} +51 -14
- package/dist/{block-text-DkHaoGem.js → block-text-YtiNkqmx.js} +1 -1
- package/dist/{channel-B9fVdW3s.js → channel-D_tovcUL.js} +151 -91
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-type-DXyos1d2.js → channel-type-B9MSdoGN.js} +9 -8
- package/dist/{config-adapter-CxBQH8fq.js → channel.setup-Bch9dYmA.js} +83 -25
- package/dist/{config-schema-SgZT6nXV.js → config-schema-xto5jFIx.js} +5 -11
- package/dist/{directory-config-CnCIAktf.js → directory-config-CNBz8lJa.js} +3 -3
- package/dist/directory-contract-api.js +1 -1
- package/dist/{directory-live-DKunWh3A.js → directory-live-CFKUtW9E.js} +13 -22
- package/dist/{doctor-contract-CsGH1Dfc.js → doctor-contract-BAy7-EUQ.js} +30 -3
- package/dist/doctor-contract-api.js +1 -1
- package/dist/{group-policy-NQZti9t-.js → group-policy-c4RP9bjc.js} +248 -163
- package/dist/index.js +4 -1
- package/dist/{message-tool-api-DkhFpMoy.js → message-tool-api-BykQB4AU.js} +14 -3
- package/dist/message-tool-api.js +1 -1
- package/dist/{monitor-CmKz0wtI.js → monitor-1nF1NtqT.js} +3 -3
- package/dist/{outbound-adapter-BkuMp2Vs.js → outbound-adapter-S81tsswN.js} +19 -17
- package/dist/{pipeline.runtime-DgtmuYCP.js → pipeline.runtime-BvYsM5JO.js} +1087 -682
- package/dist/{policy-PRysPn23.js → policy-TapwbeaT.js} +18 -14
- package/dist/{probe-CgDsSops.js → probe-HoEg_WxB.js} +38 -18
- package/dist/{provider-DmRizMZt.js → provider-CDNvBXUi.js} +3422 -2590
- package/dist/{relay-source-Blxj8xb4.js → relay-source-C9leF11u.js} +11 -21
- package/dist/{replies-4s_Vq_z9.js → replies-CeOfv82I.js} +52 -6
- package/dist/{resolve-channels-yEqmM-3I.js → resolve-channels-CNPrxaXY.js} +39 -12
- package/dist/{resolve-users-BOrt5K-5.js → resolve-users-Dzomuwnr.js} +28 -5
- package/dist/{runtime-api-QMb-Q5Ko.js → runtime-api-Cj9nxBNv.js} +3 -3
- package/dist/runtime-api.js +11 -11
- package/dist/{scopes-BJSrkAp6.js → scopes-cYXKkrRD.js} +1 -1
- package/dist/{send-DsLeZpST.js → send-Nor0iBwY.js} +211 -105
- package/dist/{send.runtime-gUdK6V3h.js → send.runtime-BmgNe6S9.js} +1 -1
- package/dist/setup-entry.js +1 -4
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-BeNzrMrJ.js → setup-surface-CbX1-Knh.js} +6 -6
- package/dist/{shared-DgIN3Dcr.js → shared-zdT5AMp-.js} +36 -42
- package/dist/{slash-dispatch.runtime-zPkyl7dB.js → slash-dispatch.runtime-Bnr9GR1S.js} +1 -1
- package/dist/{streaming-compat-3_X-21wW.js → streaming-compat-B-e0mqM0.js} +3 -8
- package/dist/{target-parsing-N6lHogYZ.js → target-parsing-BnMD2ZqZ.js} +40 -2
- package/dist/{targets-KmjP2E8s.js → targets-Cx5W_n3W.js} +1 -1
- package/node_modules/@slack/bolt/node_modules/@types/node/README.md +1 -1
- package/node_modules/@slack/bolt/node_modules/@types/node/crypto.d.ts +1 -1
- package/node_modules/@slack/bolt/node_modules/@types/node/package.json +2 -2
- package/node_modules/@slack/socket-mode/node_modules/@types/node/README.md +1 -1
- package/node_modules/@slack/socket-mode/node_modules/@types/node/crypto.d.ts +1 -1
- package/node_modules/@slack/socket-mode/node_modules/@types/node/package.json +2 -2
- package/node_modules/@slack/web-api/node_modules/@types/node/README.md +1 -1
- package/node_modules/@slack/web-api/node_modules/@types/node/crypto.d.ts +1 -1
- package/node_modules/@slack/web-api/node_modules/@types/node/package.json +2 -2
- package/node_modules/undici/lib/cache/memory-cache-store.js +54 -9
- package/node_modules/undici/lib/cache/sqlite-cache-store.js +7 -1
- package/node_modules/undici/lib/core/request.js +12 -1
- package/node_modules/undici/lib/dispatcher/client-h1.js +11 -2
- package/node_modules/undici/lib/handler/cache-handler.js +246 -64
- package/node_modules/undici/lib/handler/cache-revalidation-handler.js +3 -3
- package/node_modules/undici/lib/handler/retry-handler.js +24 -0
- package/node_modules/undici/lib/interceptor/cache.js +159 -52
- package/node_modules/undici/lib/util/cache.js +324 -62
- package/node_modules/undici/lib/util/date.js +23 -6
- package/node_modules/undici/lib/web/cookies/util.js +79 -9
- package/node_modules/undici/package.json +1 -1
- package/openclaw.plugin.json +239 -34
- package/package.json +9 -9
- package/skills/slack/SKILL.md +10 -68
- package/dist/action-runtime.runtime-DQErZYpz.js +0 -2
- package/dist/actions.runtime-BIRU_G4M.js +0 -2
- package/dist/channel.setup-CLP5oTvh.js +0 -56
- package/dist/preflight-audio.runtime-D5Bgags0.js +0 -3
- package/dist/slash-plugin-commands.runtime-Dosfcx3X.js +0 -2
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { a as resolveSlackAccount, l as resolveSlackOperationToken } from "./accounts-
|
|
2
|
-
import {
|
|
3
|
-
import { C as
|
|
1
|
+
import { a as resolveSlackAccount, l as resolveSlackOperationToken } from "./accounts-CK4AVI2_.js";
|
|
2
|
+
import { a as parseSlackTarget, t as canonicalizeSlackApiTargetId } from "./target-parsing-BnMD2ZqZ.js";
|
|
3
|
+
import { A as chunkSlackMrkdwnText, B as SLACK_TEXT_LIMIT, C as buildSlackNativeDataAccessibilityText, E as isSlackInvalidBlocksError, F as renderSlackBlockFallbackText, G as truncateSlackText, K as truncateSlackTextByUtf8Bytes, L as SLACK_EDIT_TEXT_MAX_BYTES, P as buildSlackCompleteBlocksFallbackText, R as SLACK_MESSAGE_TEXT_HARD_LIMIT, S as appendSlackNativeDataPlainTextFallback, T as hasSlackNativeDataBlock, j as markdownToSlackMrkdwnChunks, k as stripSlackNativeDataBlocks, p as assertSlackDetachedTargetAllowed, q as SLACK_QUESTION_FINALIZATION_BLOCKS, tt as resolveSlackQuestionActionIds, ut as validateSlackBlocksArray, w as createSlackNativeDataBaseTextConsumer, z as SLACK_MESSAGE_TEXT_RECOMMENDED_LIMIT } from "./group-policy-c4RP9bjc.js";
|
|
4
4
|
import { n as resolveSlackThreadTsValue, t as normalizeSlackThreadTsCandidate } from "./thread-ts-DUGhaYKq.js";
|
|
5
|
-
import {
|
|
5
|
+
import { a as createSlackReadClient, d as getSlackWriteClient, r as formatSlackError, s as createSlackTokenCacheKey } from "./probe-HoEg_WxB.js";
|
|
6
6
|
import { t as getOptionalSlackRuntime } from "./runtime-JSVZSWAj.js";
|
|
7
|
-
import { i as loadOutboundMediaFromUrl } from "./runtime-api-
|
|
7
|
+
import { i as loadOutboundMediaFromUrl } from "./runtime-api-Cj9nxBNv.js";
|
|
8
8
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
9
9
|
import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
|
|
10
10
|
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
|
11
|
+
import { resolveGlobalSingleton } from "openclaw/plugin-sdk/global-singleton";
|
|
11
12
|
import { sliceUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
12
13
|
import { createHash, createHmac } from "node:crypto";
|
|
13
14
|
import { withTrustedEnvProxyGuardedFetchMode } from "openclaw/plugin-sdk/fetch-runtime";
|
|
@@ -19,25 +20,34 @@ import { chunkMarkdownTextWithMode, isSilentReplyText, resolveChunkMode, resolve
|
|
|
19
20
|
import { resolveTextChunksWithFallback } from "openclaw/plugin-sdk/reply-payload";
|
|
20
21
|
import { safeEqualSecret } from "openclaw/plugin-sdk/security-runtime";
|
|
21
22
|
import { buildTimeoutAbortSignal } from "openclaw/plugin-sdk/extension-shared";
|
|
23
|
+
import { extensionForMime } from "openclaw/plugin-sdk/media-mime";
|
|
22
24
|
import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
23
25
|
import { createPersistentDedupeCache } from "openclaw/plugin-sdk/dedupe-runtime";
|
|
26
|
+
import { createPluginStateErrorReporter } from "openclaw/plugin-sdk/plugin-state-runtime";
|
|
24
27
|
//#region extensions/slack/src/native-data-fallback.ts
|
|
25
28
|
const SLACK_SECTION_PLAIN_TEXT_MAX = 3e3;
|
|
26
29
|
const SLACK_EMPTY_BLOCK_FALLBACK = "Shared a Block Kit message";
|
|
30
|
+
function sliceSlackTextChunk(text, start, limit) {
|
|
31
|
+
return sliceUtf16Safe(text, start, Math.min(text.length, start + limit)) || Array.from(text.slice(start))[0] || "";
|
|
32
|
+
}
|
|
27
33
|
function chunkSlackTextAtHardLimit(text, limit = SLACK_MESSAGE_TEXT_HARD_LIMIT) {
|
|
28
|
-
const effectiveLimit = Math.max(
|
|
34
|
+
const effectiveLimit = Math.max(1, Math.floor(limit));
|
|
29
35
|
const chunks = [];
|
|
30
36
|
let offset = 0;
|
|
31
37
|
while (offset < text.length) {
|
|
32
|
-
const chunk =
|
|
38
|
+
const chunk = sliceSlackTextChunk(text, offset, effectiveLimit);
|
|
33
39
|
if (!chunk) throw new Error("Slack plain-text fallback chunking made no progress.");
|
|
34
40
|
chunks.push(chunk);
|
|
35
41
|
offset += chunk.length;
|
|
36
42
|
}
|
|
37
43
|
return chunks;
|
|
38
44
|
}
|
|
39
|
-
function
|
|
40
|
-
|
|
45
|
+
function fitsSlackTextLimit(text, limit) {
|
|
46
|
+
if (text.length <= limit) return true;
|
|
47
|
+
return sliceSlackTextChunk(text, 0, limit).length === text.length;
|
|
48
|
+
}
|
|
49
|
+
function buildPlainTextBlocks(text, textLimit) {
|
|
50
|
+
return chunkSlackTextAtHardLimit(text, Math.min(textLimit, SLACK_SECTION_PLAIN_TEXT_MAX)).map((chunk, index) => {
|
|
41
51
|
const fallbackBlock = {
|
|
42
52
|
block: {
|
|
43
53
|
type: "section",
|
|
@@ -58,11 +68,11 @@ function renderNativeDataPlainText(block) {
|
|
|
58
68
|
function buildOrderedFallbackBlocks(params) {
|
|
59
69
|
const entries = [];
|
|
60
70
|
const consumeFromBase = createSlackNativeDataBaseTextConsumer(params.baseText);
|
|
61
|
-
if (params.baseText) entries.push(...buildPlainTextBlocks(params.baseText));
|
|
71
|
+
if (params.baseText) entries.push(...buildPlainTextBlocks(params.baseText, params.textLimit));
|
|
62
72
|
for (const block of params.blocks) {
|
|
63
73
|
if (hasSlackNativeDataBlock([block])) {
|
|
64
74
|
const nativeText = renderNativeDataPlainText(block);
|
|
65
|
-
if (!consumeFromBase(nativeText)) entries.push(...buildPlainTextBlocks(nativeText));
|
|
75
|
+
if (!consumeFromBase(nativeText)) entries.push(...buildPlainTextBlocks(nativeText, params.textLimit));
|
|
66
76
|
continue;
|
|
67
77
|
}
|
|
68
78
|
const text = renderSlackBlockFallbackText(block, { nativeDataFormat: "plain" });
|
|
@@ -73,7 +83,7 @@ function buildOrderedFallbackBlocks(params) {
|
|
|
73
83
|
}
|
|
74
84
|
return entries;
|
|
75
85
|
}
|
|
76
|
-
function buildOrderedBlockMessages(entries) {
|
|
86
|
+
function buildOrderedBlockMessages(entries, textLimit) {
|
|
77
87
|
const messages = [];
|
|
78
88
|
let blocks = [];
|
|
79
89
|
let text = "";
|
|
@@ -90,10 +100,10 @@ function buildOrderedBlockMessages(entries) {
|
|
|
90
100
|
for (const entry of entries) {
|
|
91
101
|
const separator = text && entry.text && !entry.continuesText ? "\n\n" : "";
|
|
92
102
|
const nextText = entry.text ? `${text}${separator}${entry.text}` : text;
|
|
93
|
-
if (blocks.length >= 50 || nextText
|
|
103
|
+
if (blocks.length >= 50 || !fitsSlackTextLimit(nextText, textLimit)) flush();
|
|
94
104
|
const freshSeparator = text && entry.text && !entry.continuesText ? "\n\n" : "";
|
|
95
105
|
const freshText = entry.text ? `${text}${freshSeparator}${entry.text}` : text;
|
|
96
|
-
if (freshText
|
|
106
|
+
if (!fitsSlackTextLimit(freshText, textLimit)) throw new Error("One Slack fallback block exceeds the resolved message text limit.");
|
|
97
107
|
blocks.push(entry.block);
|
|
98
108
|
text = freshText;
|
|
99
109
|
}
|
|
@@ -103,17 +113,19 @@ function buildOrderedBlockMessages(entries) {
|
|
|
103
113
|
/** Build one complete, ordered retry plan after Slack rejects native data blocks. */
|
|
104
114
|
function buildSlackNativeDataDeliveryPlan(params) {
|
|
105
115
|
const baseText = params.baseText?.trim() ?? "";
|
|
116
|
+
const textLimit = Math.min(SLACK_MESSAGE_TEXT_RECOMMENDED_LIMIT, SLACK_MESSAGE_TEXT_HARD_LIMIT, Math.max(1, Math.floor(params.textLimit ?? 4e4)));
|
|
106
117
|
const hasNativeData = hasSlackNativeDataBlock(params.blocks);
|
|
107
118
|
const accessibilityText = buildSlackNativeDataAccessibilityText(baseText, params.blocks) || (hasNativeData ? "Slack could not render this chart or table data." : SLACK_EMPTY_BLOCK_FALLBACK);
|
|
108
119
|
return {
|
|
109
120
|
accessibilityText,
|
|
110
|
-
fallbackMessages: stripSlackNativeDataBlocks(params.blocks).length === 0 ? chunkSlackTextAtHardLimit(accessibilityText).map((text) => ({
|
|
121
|
+
fallbackMessages: stripSlackNativeDataBlocks(params.blocks).length === 0 ? chunkSlackTextAtHardLimit(accessibilityText, textLimit).map((text) => ({
|
|
111
122
|
text,
|
|
112
123
|
mrkdwn: false
|
|
113
124
|
})) : buildOrderedBlockMessages(buildOrderedFallbackBlocks({
|
|
114
125
|
baseText,
|
|
115
|
-
blocks: params.blocks
|
|
116
|
-
|
|
126
|
+
blocks: params.blocks,
|
|
127
|
+
textLimit
|
|
128
|
+
}), textLimit),
|
|
117
129
|
skipOriginalBlocks: accessibilityText.length > SLACK_MESSAGE_TEXT_HARD_LIMIT
|
|
118
130
|
};
|
|
119
131
|
}
|
|
@@ -355,9 +367,10 @@ async function uploadSlackFile(params) {
|
|
|
355
367
|
maxBytes: params.maxBytes,
|
|
356
368
|
mediaAccess: params.mediaAccess,
|
|
357
369
|
mediaLocalRoots: params.mediaLocalRoots,
|
|
358
|
-
mediaReadFile: params.mediaReadFile
|
|
370
|
+
mediaReadFile: params.mediaReadFile,
|
|
371
|
+
...params.optimizeImages !== void 0 ? { optimizeImages: params.optimizeImages } : {}
|
|
359
372
|
});
|
|
360
|
-
const uploadFileName = params.uploadFileName ?? fileName ??
|
|
373
|
+
const uploadFileName = params.uploadFileName ?? fileName ?? `upload${extensionForMime(contentType) ?? ""}`;
|
|
361
374
|
const uploadTitle = params.uploadTitle ?? uploadFileName;
|
|
362
375
|
const uploadUrlResp = await withSlackDnsRequestRetry("files.getUploadURLExternal", () => params.client.files.getUploadURLExternal({
|
|
363
376
|
filename: uploadFileName,
|
|
@@ -416,24 +429,32 @@ async function uploadSlackFile(params) {
|
|
|
416
429
|
}
|
|
417
430
|
//#endregion
|
|
418
431
|
//#region extensions/slack/src/sent-thread-cache.ts
|
|
432
|
+
/**
|
|
433
|
+
* Cache of Slack threads the bot has participated in.
|
|
434
|
+
* Used to auto-respond in threads without requiring @mention after the first reply.
|
|
435
|
+
*/
|
|
436
|
+
const MAX_ENTRIES = 5e3;
|
|
437
|
+
const PERSISTENT_MAX_ENTRIES = 1e3;
|
|
438
|
+
const MAX_FAILURE_NOTICES = 1e3;
|
|
439
|
+
const PERSISTENT_NAMESPACE = "slack.thread-participation";
|
|
440
|
+
/**
|
|
441
|
+
* Keep Slack thread participation shared across bundled chunks so thread
|
|
442
|
+
* auto-reply gating does not diverge between prepare/dispatch call paths.
|
|
443
|
+
*/
|
|
444
|
+
const SLACK_THREAD_PARTICIPATION_KEY = Symbol.for("openclaw.slackThreadParticipation");
|
|
445
|
+
const SLACK_THREAD_FAILURE_NOTICES_KEY = Symbol.for("openclaw.slackThreadFailureNotices");
|
|
419
446
|
const threadParticipation = createPersistentDedupeCache({
|
|
420
|
-
globalKey:
|
|
421
|
-
ttlMs:
|
|
422
|
-
maxSize:
|
|
447
|
+
globalKey: SLACK_THREAD_PARTICIPATION_KEY,
|
|
448
|
+
ttlMs: 0,
|
|
449
|
+
maxSize: MAX_ENTRIES,
|
|
423
450
|
persistent: {
|
|
424
|
-
namespace:
|
|
425
|
-
maxEntries:
|
|
451
|
+
namespace: PERSISTENT_NAMESPACE,
|
|
452
|
+
maxEntries: PERSISTENT_MAX_ENTRIES,
|
|
426
453
|
openStore: (options) => getOptionalSlackRuntime()?.state.openKeyedStore(options),
|
|
427
|
-
logError: (
|
|
428
|
-
try {
|
|
429
|
-
getOptionalSlackRuntime()?.logging.getChildLogger({
|
|
430
|
-
plugin: "slack",
|
|
431
|
-
feature: "thread-participation-state"
|
|
432
|
-
}).warn("Slack persistent thread participation state failed", { error: String(error) });
|
|
433
|
-
} catch {}
|
|
434
|
-
}
|
|
454
|
+
logError: createPluginStateErrorReporter(getOptionalSlackRuntime, "slack", "thread-participation-state", "Slack persistent thread participation state failed")
|
|
435
455
|
}
|
|
436
456
|
});
|
|
457
|
+
const threadFailureNotices = resolveGlobalSingleton(SLACK_THREAD_FAILURE_NOTICES_KEY, () => /* @__PURE__ */ new Map(), (notices) => notices.clear());
|
|
437
458
|
function makeKey(accountId, channelId, threadTs, teamId) {
|
|
438
459
|
return `${accountId}:${teamId ? `${teamId}:` : ""}${channelId}:${threadTs}`;
|
|
439
460
|
}
|
|
@@ -452,8 +473,41 @@ async function hasSlackThreadParticipationWithPersistence(params) {
|
|
|
452
473
|
if (!params.accountId || !params.channelId || !params.threadTs) return false;
|
|
453
474
|
return await threadParticipation.lookup(makeKey(params.accountId, params.channelId, params.threadTs, params.teamId));
|
|
454
475
|
}
|
|
476
|
+
function makeFailureNoticeKey(params) {
|
|
477
|
+
const scope = params.threadTs ? `thread:${params.threadTs}` : "channel";
|
|
478
|
+
return makeKey(params.accountId, params.channelId, scope, params.teamId);
|
|
479
|
+
}
|
|
480
|
+
/** Returns whether this failure was already delivered in the thread or channel. */
|
|
481
|
+
function hasSlackThreadFailureNotice(params) {
|
|
482
|
+
const { accountId, channelId, failureText } = params;
|
|
483
|
+
const fingerprint = failureText.trim().replace(/\s+/gu, " ");
|
|
484
|
+
if (!accountId || !channelId || !fingerprint) return false;
|
|
485
|
+
return threadFailureNotices.get(makeFailureNoticeKey(params)) === fingerprint;
|
|
486
|
+
}
|
|
487
|
+
/** Records a failure after it was delivered in the thread or channel. */
|
|
488
|
+
function recordSlackThreadFailureNotice(params) {
|
|
489
|
+
const { accountId, channelId, failureText } = params;
|
|
490
|
+
const fingerprint = failureText.trim().replace(/\s+/gu, " ");
|
|
491
|
+
if (!accountId || !channelId || !fingerprint) return false;
|
|
492
|
+
const key = makeFailureNoticeKey(params);
|
|
493
|
+
if (threadFailureNotices.get(key) === fingerprint) return false;
|
|
494
|
+
threadFailureNotices.delete(key);
|
|
495
|
+
threadFailureNotices.set(key, fingerprint);
|
|
496
|
+
if (threadFailureNotices.size > MAX_FAILURE_NOTICES) {
|
|
497
|
+
const oldestKey = threadFailureNotices.keys().next().value;
|
|
498
|
+
if (oldestKey !== void 0) threadFailureNotices.delete(oldestKey);
|
|
499
|
+
}
|
|
500
|
+
return true;
|
|
501
|
+
}
|
|
502
|
+
/** Clears a thread or channel outage notice after a healthy model turn completes. */
|
|
503
|
+
function clearSlackThreadFailureNotice(params) {
|
|
504
|
+
const { accountId, channelId } = params;
|
|
505
|
+
if (!accountId || !channelId) return;
|
|
506
|
+
threadFailureNotices.delete(makeFailureNoticeKey(params));
|
|
507
|
+
}
|
|
455
508
|
function clearSlackThreadParticipationCache() {
|
|
456
509
|
threadParticipation.clearForTest();
|
|
510
|
+
threadFailureNotices.clear();
|
|
457
511
|
}
|
|
458
512
|
//#endregion
|
|
459
513
|
//#region extensions/slack/src/send.ts
|
|
@@ -537,11 +591,12 @@ async function updateMessageSlack(params) {
|
|
|
537
591
|
cfg: requireRuntimeConfig(params.cfg, "Slack update"),
|
|
538
592
|
accountId: params.accountId
|
|
539
593
|
});
|
|
594
|
+
assertSlackDetachedTargetAllowed(account.accountId, params.teamId);
|
|
540
595
|
await getSlackWriteClient(resolveToken({
|
|
541
596
|
accountId: account.accountId,
|
|
542
597
|
fallbackToken: account.botToken,
|
|
543
598
|
fallbackSource: account.botTokenSource
|
|
544
|
-
})).chat.update({
|
|
599
|
+
}), { teamId: params.teamId }).chat.update({
|
|
545
600
|
channel: params.channelId,
|
|
546
601
|
ts: params.messageTs,
|
|
547
602
|
text: truncateSlackTextByUtf8Bytes(params.text, SLACK_EDIT_TEXT_MAX_BYTES),
|
|
@@ -577,7 +632,8 @@ function parseRecipient(raw) {
|
|
|
577
632
|
if (!target) throw new Error("Recipient is required for Slack sends");
|
|
578
633
|
return {
|
|
579
634
|
kind: target.kind,
|
|
580
|
-
id: canonicalizeSlackApiTargetId(target.kind, target.id, raw)
|
|
635
|
+
id: canonicalizeSlackApiTargetId(target.kind, target.id, raw),
|
|
636
|
+
teamId: target.teamId
|
|
581
637
|
};
|
|
582
638
|
}
|
|
583
639
|
function parseEnterpriseEventRecipient(raw) {
|
|
@@ -588,20 +644,62 @@ function parseEnterpriseEventRecipient(raw) {
|
|
|
588
644
|
id: canonicalizeSlackApiTargetId("channel", match[1])
|
|
589
645
|
};
|
|
590
646
|
}
|
|
591
|
-
function
|
|
592
|
-
const scope = params.opts.
|
|
593
|
-
if (!scope)
|
|
594
|
-
|
|
595
|
-
return;
|
|
596
|
-
}
|
|
597
|
-
if (params.account.config.enterpriseOrgInstall !== true) throw new Error("unexpected_enterprise_slack_listener_scope");
|
|
598
|
-
if (!scope.isEnterpriseInstall || !normalizeOptionalString(scope.apiAppId) || !normalizeOptionalString(scope.enterpriseId) || !/^T[A-Z0-9]+$/i.test(scope.teamId) || !scope.client || params.opts.client !== scope.client) throw new Error("invalid_enterprise_slack_listener_scope");
|
|
647
|
+
function resolveSlackSendEventScope(params) {
|
|
648
|
+
const scope = params.opts.eventScope;
|
|
649
|
+
if (!scope) return;
|
|
650
|
+
if (!/^T[A-Z0-9]+$/i.test(scope.teamId) || !scope.client) throw new Error("invalid_enterprise_slack_listener_scope");
|
|
599
651
|
return scope;
|
|
600
652
|
}
|
|
653
|
+
function resolveSlackDelivery(params) {
|
|
654
|
+
if (params.eventScope) {
|
|
655
|
+
if (params.opts.mediaUrl && !params.eventScope.uploadCompletionClient) throw new Error("missing_enterprise_slack_upload_completion_client");
|
|
656
|
+
return Object.freeze({
|
|
657
|
+
client: params.eventScope.client,
|
|
658
|
+
credential: SLACK_ENTERPRISE_LISTENER_QUEUE_CREDENTIAL,
|
|
659
|
+
identity: normalizeSlackSendIdentity(params.opts.identity),
|
|
660
|
+
recipient: params.recipient,
|
|
661
|
+
requireMessageTimestamp: true,
|
|
662
|
+
teamId: params.eventScope.teamId,
|
|
663
|
+
unfurl: { unfurlMedia: params.account.config.unfurlMedia },
|
|
664
|
+
...params.eventScope.uploadCompletionClient ? { upload: Object.freeze({
|
|
665
|
+
completionClient: params.eventScope.uploadCompletionClient,
|
|
666
|
+
auditContext: "slack-enterprise-immediate-upload"
|
|
667
|
+
}) } : {}
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
const credential = resolveToken({
|
|
671
|
+
explicit: params.opts.token,
|
|
672
|
+
accountId: params.account.accountId,
|
|
673
|
+
fallbackToken: resolveSlackOperationToken(params.account, "write"),
|
|
674
|
+
fallbackSource: params.account.identity === "user" ? params.account.userTokenSource : params.account.botTokenSource
|
|
675
|
+
});
|
|
676
|
+
return Object.freeze({
|
|
677
|
+
client: params.recipient.teamId ? getSlackWriteClient(credential, { teamId: params.recipient.teamId }) : params.opts.client ?? getSlackWriteClient(credential),
|
|
678
|
+
credential,
|
|
679
|
+
identity: resolveSlackSendIdentity({
|
|
680
|
+
accountId: params.account.accountId,
|
|
681
|
+
explicit: params.opts.identity
|
|
682
|
+
}),
|
|
683
|
+
recipient: params.recipient,
|
|
684
|
+
requireMessageTimestamp: false,
|
|
685
|
+
teamId: params.recipient.teamId,
|
|
686
|
+
unfurl: params.recipient.teamId ? { unfurlMedia: params.account.config.unfurlMedia } : {
|
|
687
|
+
unfurlLinks: params.account.config.unfurlLinks,
|
|
688
|
+
unfurlMedia: params.account.config.unfurlMedia
|
|
689
|
+
}
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
function assertSlackPostMessageResponse(response, required) {
|
|
693
|
+
if (!required || response.ok && response.ts) return;
|
|
694
|
+
throw new Error(response.ok ? "Slack chat.postMessage returned no message timestamp" : `Slack chat.postMessage failed: ${formatSlackError(response.error, "unknown error")}`);
|
|
695
|
+
}
|
|
696
|
+
function resolveSlackTextChunkLimit(params) {
|
|
697
|
+
const configuredLimit = params.textLimit ?? resolveTextChunkLimit(params.cfg, "slack", params.accountId, { fallbackLimit: 8e3 });
|
|
698
|
+
return Math.min(configuredLimit, SLACK_TEXT_LIMIT);
|
|
699
|
+
}
|
|
601
700
|
function resolveSlackTextChunks(params) {
|
|
602
701
|
const text = params.preservePlainText ? params.text : params.text.trim();
|
|
603
|
-
const
|
|
604
|
-
const chunkLimit = Math.min(configuredLimit, SLACK_TEXT_LIMIT);
|
|
702
|
+
const chunkLimit = resolveSlackTextChunkLimit(params);
|
|
605
703
|
if (params.preservePlainText) {
|
|
606
704
|
const chunks = [];
|
|
607
705
|
let remaining = text;
|
|
@@ -867,7 +965,7 @@ async function scanSlackConversationForDelivery(params) {
|
|
|
867
965
|
evidence: deliveryParts.size > 0 ? "partial" : "none"
|
|
868
966
|
};
|
|
869
967
|
}
|
|
870
|
-
async function reconcileSlackUnknownSend(ctx
|
|
968
|
+
async function reconcileSlackUnknownSend(ctx) {
|
|
871
969
|
const account = resolveSlackAccount({
|
|
872
970
|
cfg: requireRuntimeConfig(ctx.cfg, "Slack delivery reconciliation"),
|
|
873
971
|
accountId: ctx.accountId ?? void 0
|
|
@@ -878,13 +976,22 @@ async function reconcileSlackUnknownSend(ctx, opts) {
|
|
|
878
976
|
error: "Slack unknown-send reconciliation requires a durable delivery id",
|
|
879
977
|
retryable: false
|
|
880
978
|
};
|
|
979
|
+
const recipient = parseRecipient(ctx.to);
|
|
980
|
+
try {
|
|
981
|
+
assertSlackDetachedTargetAllowed(account.accountId, recipient.teamId);
|
|
982
|
+
} catch (error) {
|
|
983
|
+
return {
|
|
984
|
+
status: "unresolved",
|
|
985
|
+
error: error instanceof Error ? error.message : String(error),
|
|
986
|
+
retryable: false
|
|
987
|
+
};
|
|
988
|
+
}
|
|
881
989
|
const readToken = resolveSlackOperationToken(account, "read");
|
|
882
990
|
if (!readToken) return {
|
|
883
991
|
status: "unresolved",
|
|
884
992
|
error: `Slack read token missing for account "${account.accountId}"`,
|
|
885
993
|
retryable: false
|
|
886
994
|
};
|
|
887
|
-
const recipient = parseRecipient(ctx.to);
|
|
888
995
|
const userRecipient = isSlackUserRecipient(recipient);
|
|
889
996
|
const writeToken = resolveSlackOperationToken(account, "write");
|
|
890
997
|
if (userRecipient && !writeToken) return {
|
|
@@ -892,8 +999,8 @@ async function reconcileSlackUnknownSend(ctx, opts) {
|
|
|
892
999
|
error: `Slack write token missing for direct-message reconciliation on account "${account.accountId}"`,
|
|
893
1000
|
retryable: false
|
|
894
1001
|
};
|
|
895
|
-
const readClient =
|
|
896
|
-
const writeClient =
|
|
1002
|
+
const readClient = createSlackReadClient(readToken, { teamId: recipient.teamId });
|
|
1003
|
+
const writeClient = writeToken ? getSlackWriteClient(writeToken, { teamId: recipient.teamId }) : void 0;
|
|
897
1004
|
const payloadReplyToId = ctx.payloads[0]?.replyToId;
|
|
898
1005
|
const threadTs = resolveSlackThreadTsValue({
|
|
899
1006
|
replyToId: Object.hasOwn(ctx, "effectiveReplyToId") ? normalizeOptionalString(ctx.effectiveReplyToId) : payloadReplyToId != null ? normalizeOptionalString(payloadReplyToId) : ctx.replyToMode === "off" ? void 0 : normalizeOptionalString(ctx.replyToId),
|
|
@@ -910,7 +1017,7 @@ async function reconcileSlackUnknownSend(ctx, opts) {
|
|
|
910
1017
|
accountId: account.accountId,
|
|
911
1018
|
token: channelToken
|
|
912
1019
|
});
|
|
913
|
-
const lookupClients =
|
|
1020
|
+
const lookupClients = [readClient, ...writeClient && writeClient !== readClient && writeToken !== readToken ? [writeClient] : []];
|
|
914
1021
|
let lookupError;
|
|
915
1022
|
let bestUnresolvedScan;
|
|
916
1023
|
for (const lookupClient of lookupClients) try {
|
|
@@ -947,15 +1054,9 @@ async function sendMessageSlack(to, message, opts) {
|
|
|
947
1054
|
cfg,
|
|
948
1055
|
accountId: opts.accountId
|
|
949
1056
|
});
|
|
950
|
-
const
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
});
|
|
954
|
-
const enterpriseDelivery = enterpriseEventScope ? Object.freeze({
|
|
955
|
-
client: enterpriseEventScope.client,
|
|
956
|
-
teamId: enterpriseEventScope.teamId,
|
|
957
|
-
...enterpriseEventScope.uploadCompletionClient ? { uploadCompletionClient: enterpriseEventScope.uploadCompletionClient } : {}
|
|
958
|
-
}) : void 0;
|
|
1057
|
+
const eventScope = resolveSlackSendEventScope({ opts });
|
|
1058
|
+
const recipient = eventScope ? parseEnterpriseEventRecipient(to) : parseRecipient(to);
|
|
1059
|
+
if (!eventScope) assertSlackDetachedTargetAllowed(account.accountId, recipient.teamId);
|
|
959
1060
|
if (isSilentReplyText(normalizedMessage) && !opts.mediaUrl && !opts.blocks) {
|
|
960
1061
|
logVerbose("slack send: suppressed NO_REPLY token before API call");
|
|
961
1062
|
return {
|
|
@@ -969,37 +1070,29 @@ async function sendMessageSlack(to, message, opts) {
|
|
|
969
1070
|
}
|
|
970
1071
|
const blocks = opts.blocks == null ? void 0 : validateSlackBlocksArray(opts.blocks);
|
|
971
1072
|
if (!normalizedMessage && !opts.mediaUrl && !blocks) throw new Error("Slack send requires text, blocks, or media");
|
|
972
|
-
const
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
1073
|
+
const queuedOpts = Object.freeze({ ...opts });
|
|
1074
|
+
const delivery = resolveSlackDelivery({
|
|
1075
|
+
account,
|
|
1076
|
+
eventScope,
|
|
1077
|
+
opts: queuedOpts,
|
|
1078
|
+
recipient
|
|
977
1079
|
});
|
|
978
|
-
const
|
|
979
|
-
const queueKey = createSlackSendQueueKey({
|
|
1080
|
+
const result = await runQueuedSlackSend(createSlackSendQueueKey({
|
|
980
1081
|
accountId: account.accountId,
|
|
981
|
-
token,
|
|
982
|
-
recipient,
|
|
1082
|
+
token: delivery.credential,
|
|
1083
|
+
recipient: delivery.recipient,
|
|
983
1084
|
threadTs: opts.threadTs,
|
|
984
|
-
|
|
985
|
-
})
|
|
986
|
-
const queuedOpts = enterpriseDelivery ? Object.freeze({
|
|
987
|
-
...opts,
|
|
988
|
-
client: enterpriseDelivery.client
|
|
989
|
-
}) : opts;
|
|
990
|
-
const result = await runQueuedSlackSend(queueKey, () => sendMessageSlackQueued({
|
|
1085
|
+
teamId: delivery.teamId
|
|
1086
|
+
}), () => sendMessageSlackQueued({
|
|
991
1087
|
trimmedMessage,
|
|
992
1088
|
opts: queuedOpts,
|
|
993
1089
|
cfg,
|
|
994
1090
|
account,
|
|
995
|
-
token,
|
|
996
|
-
recipient,
|
|
997
1091
|
blocks,
|
|
998
|
-
|
|
1092
|
+
delivery
|
|
999
1093
|
}));
|
|
1000
1094
|
const threadTs = result.threadTs ?? normalizeSlackThreadTsCandidate(queuedOpts.threadTs);
|
|
1001
|
-
if (threadTs && result.channelId && account.accountId)
|
|
1002
|
-
else recordSlackThreadParticipation(account.accountId, result.channelId, threadTs);
|
|
1095
|
+
if (threadTs && result.channelId && account.accountId) recordSlackThreadParticipation(account.accountId, result.channelId, threadTs, { teamId: delivery.teamId });
|
|
1003
1096
|
return result;
|
|
1004
1097
|
}
|
|
1005
1098
|
async function sendMessageSlackQueued(params) {
|
|
@@ -1010,17 +1103,9 @@ async function sendMessageSlackQueued(params) {
|
|
|
1010
1103
|
}
|
|
1011
1104
|
}
|
|
1012
1105
|
async function sendMessageSlackQueuedInner(params) {
|
|
1013
|
-
const { opts, cfg, account,
|
|
1014
|
-
const client
|
|
1015
|
-
const identity = enterpriseDelivery ? normalizeSlackSendIdentity(opts.identity) : resolveSlackSendIdentity({
|
|
1016
|
-
accountId: account.accountId,
|
|
1017
|
-
explicit: opts.identity
|
|
1018
|
-
});
|
|
1106
|
+
const { opts, cfg, account, blocks, trimmedMessage, delivery } = params;
|
|
1107
|
+
const { client, identity, recipient, unfurl } = delivery;
|
|
1019
1108
|
if (opts.replyBroadcast && opts.mediaUrl) throw new Error("Slack replyBroadcast is only supported for text or block thread replies.");
|
|
1020
|
-
const unfurl = enterpriseDelivery ? { unfurlMedia: account.config.unfurlMedia } : {
|
|
1021
|
-
unfurlLinks: account.config.unfurlLinks,
|
|
1022
|
-
unfurlMedia: account.config.unfurlMedia
|
|
1023
|
-
};
|
|
1024
1109
|
const directUserPostChannelId = opts.deliveryQueueId ? void 0 : resolveDirectUserPostChannelId({
|
|
1025
1110
|
recipient,
|
|
1026
1111
|
hasMedia: Boolean(opts.mediaUrl),
|
|
@@ -1028,11 +1113,20 @@ async function sendMessageSlackQueuedInner(params) {
|
|
|
1028
1113
|
});
|
|
1029
1114
|
const { channelId } = directUserPostChannelId ? { channelId: directUserPostChannelId } : await resolveChannelId(client, recipient, {
|
|
1030
1115
|
accountId: account.accountId,
|
|
1031
|
-
token
|
|
1116
|
+
token: delivery.credential
|
|
1032
1117
|
});
|
|
1033
|
-
const reportDelivery = async (result) => {
|
|
1034
|
-
|
|
1035
|
-
|
|
1118
|
+
const reportDelivery = async (result, deliveredBlocks) => {
|
|
1119
|
+
const slackQuestionActionIds = resolveSlackQuestionActionIds(deliveredBlocks);
|
|
1120
|
+
const deliveryResult = slackQuestionActionIds.length ? {
|
|
1121
|
+
...result,
|
|
1122
|
+
meta: {
|
|
1123
|
+
...result.meta,
|
|
1124
|
+
slackQuestionActionIds,
|
|
1125
|
+
[SLACK_QUESTION_FINALIZATION_BLOCKS]: deliveredBlocks.filter((block) => block.type !== "actions")
|
|
1126
|
+
}
|
|
1127
|
+
} : result;
|
|
1128
|
+
await opts.onDeliveryResult?.(deliveryResult);
|
|
1129
|
+
return deliveryResult;
|
|
1036
1130
|
};
|
|
1037
1131
|
let didDispatch = false;
|
|
1038
1132
|
const dispatchOnce = async () => {
|
|
@@ -1044,10 +1138,16 @@ async function sendMessageSlackQueuedInner(params) {
|
|
|
1044
1138
|
const authoredTextPlacement = opts.authoredTextPlacement ?? "outside-blocks";
|
|
1045
1139
|
const nativeDataFallbackBase = blocks && authoredTextPlacement === "outside-blocks" ? explicitNativeDataFallbackBase ?? trimmedMessage : "";
|
|
1046
1140
|
const hasNativeData = Boolean(blocks && hasSlackNativeDataBlock(blocks));
|
|
1141
|
+
const textChunkLimit = resolveSlackTextChunkLimit({
|
|
1142
|
+
cfg,
|
|
1143
|
+
accountId: account.accountId,
|
|
1144
|
+
...opts.textLimit !== void 0 ? { textLimit: opts.textLimit } : {}
|
|
1145
|
+
});
|
|
1047
1146
|
const usesOrderedBlockAccessibility = Boolean(blocks && (hasNativeData || opts.authoredTextPlacement !== void 0));
|
|
1048
1147
|
const orderedBlockDeliveryPlan = blocks && usesOrderedBlockAccessibility ? buildSlackNativeDataDeliveryPlan({
|
|
1049
1148
|
baseText: nativeDataFallbackBase,
|
|
1050
|
-
blocks
|
|
1149
|
+
blocks,
|
|
1150
|
+
textLimit: textChunkLimit
|
|
1051
1151
|
}) : void 0;
|
|
1052
1152
|
const orderedBlockAccessibilityText = blocks && usesOrderedBlockAccessibility ? orderedBlockDeliveryPlan?.accessibilityText ?? (buildSlackNativeDataAccessibilityText(nativeDataFallbackBase, blocks) || "Slack could not render this Block Kit message.") : void 0;
|
|
1053
1153
|
const completeBlockFallbackText = blocks ? buildSlackCompleteBlocksFallbackText(blocks) : "";
|
|
@@ -1085,7 +1185,7 @@ async function sendMessageSlackQueuedInner(params) {
|
|
|
1085
1185
|
...usesOrderedBlockAccessibility ? { mrkdwn: false } : {},
|
|
1086
1186
|
unfurl
|
|
1087
1187
|
});
|
|
1088
|
-
|
|
1188
|
+
assertSlackPostMessageResponse(response, delivery.requireMessageTimestamp);
|
|
1089
1189
|
const messageId = response.ts ?? "unknown";
|
|
1090
1190
|
deliveredChannelId = resolvePostedMessageChannelId(response, channelId);
|
|
1091
1191
|
const deliveredThreadTs = resolvePostedMessageThreadTs(response) ?? normalizeSlackThreadTsCandidate(opts.threadTs);
|
|
@@ -1099,7 +1199,7 @@ async function sendMessageSlackQueuedInner(params) {
|
|
|
1099
1199
|
kind: "card",
|
|
1100
1200
|
threadTs: deliveredThreadTs
|
|
1101
1201
|
})
|
|
1102
|
-
});
|
|
1202
|
+
}, blocks);
|
|
1103
1203
|
} catch (error) {
|
|
1104
1204
|
if (!hasNativeData || !isSlackInvalidBlocksError(error)) throw error;
|
|
1105
1205
|
logVerbose("slack send: native data rejected, delivering complete text fallback");
|
|
@@ -1108,6 +1208,7 @@ async function sendMessageSlackQueuedInner(params) {
|
|
|
1108
1208
|
}
|
|
1109
1209
|
if (pendingBlockFallback) {
|
|
1110
1210
|
const fallbackMessages = pendingBlockFallback.fallbackMessages;
|
|
1211
|
+
let questionDelivery;
|
|
1111
1212
|
for (const [partIndex, fallback] of fallbackMessages.entries()) {
|
|
1112
1213
|
const metadata = withSlackDeliveryMetadata(partIndex === 0 ? opts.metadata : void 0, {
|
|
1113
1214
|
queueId: opts.deliveryQueueId,
|
|
@@ -1130,7 +1231,7 @@ async function sendMessageSlackQueuedInner(params) {
|
|
|
1130
1231
|
unfurl
|
|
1131
1232
|
});
|
|
1132
1233
|
const response = posted.response;
|
|
1133
|
-
|
|
1234
|
+
assertSlackPostMessageResponse(response, delivery.requireMessageTimestamp);
|
|
1134
1235
|
sendIdentity = posted.identity;
|
|
1135
1236
|
lastMessageId = response.ts ?? lastMessageId;
|
|
1136
1237
|
deliveredChannelId = resolvePostedMessageChannelId(response, deliveredChannelId);
|
|
@@ -1138,7 +1239,7 @@ async function sendMessageSlackQueuedInner(params) {
|
|
|
1138
1239
|
if (!response.ts) continue;
|
|
1139
1240
|
sentMessageIds.push(response.ts);
|
|
1140
1241
|
const deliveredThreadTs = resolvePostedMessageThreadTs(response) ?? normalizeSlackThreadTsCandidate(opts.threadTs);
|
|
1141
|
-
await reportDelivery({
|
|
1242
|
+
const fallbackDelivery = await reportDelivery({
|
|
1142
1243
|
messageId: response.ts,
|
|
1143
1244
|
channelId: deliveredChannelId,
|
|
1144
1245
|
threadTs: deliveredThreadTs,
|
|
@@ -1148,7 +1249,8 @@ async function sendMessageSlackQueuedInner(params) {
|
|
|
1148
1249
|
kind: fallback.blocks ? "card" : "text",
|
|
1149
1250
|
threadTs: deliveredThreadTs
|
|
1150
1251
|
})
|
|
1151
|
-
});
|
|
1252
|
+
}, fallback.blocks);
|
|
1253
|
+
if (fallbackDelivery.meta?.slackQuestionActionIds.length) questionDelivery = fallbackDelivery;
|
|
1152
1254
|
}
|
|
1153
1255
|
const messageId = lastMessageId || "unknown";
|
|
1154
1256
|
const deliveredThreadTs = canonicalDeliveredThreadTs ?? normalizeSlackThreadTsCandidate(opts.threadTs);
|
|
@@ -1156,6 +1258,10 @@ async function sendMessageSlackQueuedInner(params) {
|
|
|
1156
1258
|
messageId,
|
|
1157
1259
|
channelId: deliveredChannelId,
|
|
1158
1260
|
threadTs: deliveredThreadTs,
|
|
1261
|
+
...questionDelivery?.meta ? { meta: {
|
|
1262
|
+
...questionDelivery.meta,
|
|
1263
|
+
slackQuestionMessageId: questionDelivery.messageId
|
|
1264
|
+
} } : {},
|
|
1159
1265
|
receipt: createSlackSendReceipt({
|
|
1160
1266
|
platformMessageIds: sentMessageIds.length ? sentMessageIds : [messageId],
|
|
1161
1267
|
channelId: deliveredChannelId,
|
|
@@ -1169,18 +1275,17 @@ async function sendMessageSlackQueuedInner(params) {
|
|
|
1169
1275
|
cfg,
|
|
1170
1276
|
accountId: account.accountId,
|
|
1171
1277
|
text: trimmedMessage,
|
|
1172
|
-
|
|
1278
|
+
textLimit: textChunkLimit,
|
|
1173
1279
|
...opts.textIsSlackMrkdwn ? { textIsSlackMrkdwn: true } : {},
|
|
1174
1280
|
...opts.textIsSlackPlainText ? { preservePlainText: true } : {}
|
|
1175
1281
|
});
|
|
1176
1282
|
const mediaMaxBytes = opts.mediaMaxBytes ?? (typeof account.config.mediaMaxMb === "number" ? account.config.mediaMaxMb * 1024 * 1024 : void 0);
|
|
1177
1283
|
let chunksToPost;
|
|
1178
1284
|
if (opts.mediaUrl) {
|
|
1179
|
-
if (enterpriseDelivery && !enterpriseDelivery.uploadCompletionClient) throw new Error("missing_enterprise_slack_upload_completion_client");
|
|
1180
1285
|
const [firstChunk, ...rest] = resolvedChunks;
|
|
1181
1286
|
lastMessageId = await uploadSlackFile({
|
|
1182
1287
|
client,
|
|
1183
|
-
...
|
|
1288
|
+
...delivery.upload ? { completionClient: delivery.upload.completionClient } : {},
|
|
1184
1289
|
channelId,
|
|
1185
1290
|
mediaUrl: opts.mediaUrl,
|
|
1186
1291
|
mediaAccess: opts.mediaAccess,
|
|
@@ -1191,8 +1296,9 @@ async function sendMessageSlackQueuedInner(params) {
|
|
|
1191
1296
|
caption: firstChunk,
|
|
1192
1297
|
threadTs: opts.threadTs,
|
|
1193
1298
|
maxBytes: mediaMaxBytes,
|
|
1299
|
+
...opts.forceDocument ? { optimizeImages: false } : {},
|
|
1194
1300
|
onPlatformSendDispatch: dispatchOnce,
|
|
1195
|
-
...
|
|
1301
|
+
...delivery.upload ? { auditContext: delivery.upload.auditContext } : {}
|
|
1196
1302
|
});
|
|
1197
1303
|
sentMessageIds.push(lastMessageId);
|
|
1198
1304
|
await reportDelivery({
|
|
@@ -1231,7 +1337,7 @@ async function sendMessageSlackQueuedInner(params) {
|
|
|
1231
1337
|
unfurl
|
|
1232
1338
|
});
|
|
1233
1339
|
const response = posted.response;
|
|
1234
|
-
|
|
1340
|
+
assertSlackPostMessageResponse(response, delivery.requireMessageTimestamp);
|
|
1235
1341
|
sendIdentity = posted.identity;
|
|
1236
1342
|
lastMessageId = response.ts ?? lastMessageId;
|
|
1237
1343
|
deliveredChannelId = resolvePostedMessageChannelId(response, deliveredChannelId);
|
|
@@ -1266,4 +1372,4 @@ async function sendMessageSlackQueuedInner(params) {
|
|
|
1266
1372
|
};
|
|
1267
1373
|
}
|
|
1268
1374
|
//#endregion
|
|
1269
|
-
export { updateMessageSlack as a,
|
|
1375
|
+
export { updateMessageSlack as a, hasSlackThreadFailureNotice as c, recordSlackThreadFailureNotice as d, recordSlackThreadParticipation as f, setSlackDefaultSendIdentity as i, hasSlackThreadParticipation as l, chunkSlackTextAtHardLimit as m, resolveSlackDmChannelId as n, clearSlackThreadFailureNotice as o, buildSlackNativeDataDeliveryPlan as p, sendMessageSlack as r, clearSlackThreadParticipationCache as s, reconcileSlackUnknownSend as t, hasSlackThreadParticipationWithPersistence as u };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as updateMessageSlack, n as resolveSlackDmChannelId, r as sendMessageSlack, t as reconcileSlackUnknownSend } from "./send-
|
|
1
|
+
import { a as updateMessageSlack, n as resolveSlackDmChannelId, r as sendMessageSlack, t as reconcileSlackUnknownSend } from "./send-Nor0iBwY.js";
|
|
2
2
|
export { reconcileSlackUnknownSend, resolveSlackDmChannelId, sendMessageSlack, updateMessageSlack };
|
package/dist/setup-entry.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { t as registerSlackPluginHttpRoutes } from "./plugin-routes-CLp4obpN.js";
|
|
2
|
-
import "./http-routes-api.js";
|
|
3
1
|
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
|
4
2
|
//#region extensions/slack/setup-entry.ts
|
|
5
3
|
var setup_entry_default = defineBundledChannelSetupEntry({
|
|
@@ -15,8 +13,7 @@ var setup_entry_default = defineBundledChannelSetupEntry({
|
|
|
15
13
|
runtime: {
|
|
16
14
|
specifier: "./runtime-setter-api.js",
|
|
17
15
|
exportName: "setSlackRuntime"
|
|
18
|
-
}
|
|
19
|
-
registerSetupRuntime: registerSlackPluginHttpRoutes
|
|
16
|
+
}
|
|
20
17
|
});
|
|
21
18
|
//#endregion
|
|
22
19
|
export { setup_entry_default as default };
|
package/dist/setup-plugin-api.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as slackSetupPlugin } from "./channel.setup-
|
|
1
|
+
import { t as slackSetupPlugin } from "./channel.setup-Bch9dYmA.js";
|
|
2
2
|
export { slackSetupPlugin };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { i as resolveDefaultSlackAccountId, o as resolveSlackAccountAllowFrom } from "./accounts-
|
|
2
|
-
import { t as inspectSlackAccount } from "./account-inspect-
|
|
3
|
-
import "./shared-
|
|
4
|
-
import {
|
|
5
|
-
import { t as resolveSlackChannelAllowlist } from "./resolve-channels-
|
|
6
|
-
import { t as resolveSlackUserAllowlist } from "./resolve-users-
|
|
1
|
+
import { i as resolveDefaultSlackAccountId, o as resolveSlackAccountAllowFrom } from "./accounts-CK4AVI2_.js";
|
|
2
|
+
import { t as inspectSlackAccount } from "./account-inspect-Drw2gAiN.js";
|
|
3
|
+
import "./shared-zdT5AMp-.js";
|
|
4
|
+
import { o as SLACK_CHANNEL, r as createSlackSetupWizardBase } from "./channel.setup-Bch9dYmA.js";
|
|
5
|
+
import { t as resolveSlackChannelAllowlist } from "./resolve-channels-CNPrxaXY.js";
|
|
6
|
+
import { t as resolveSlackUserAllowlist } from "./resolve-users-Dzomuwnr.js";
|
|
7
7
|
import { normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
8
8
|
import { resolveBasicAllowFromEntries } from "openclaw/plugin-sdk/allow-from";
|
|
9
9
|
import { createSetupTranslator, noteChannelLookupFailure, noteChannelLookupSummary, parseMentionOrPrefixedId, patchChannelConfigForAccount, promptResolvedAllowFrom, resolveEntriesWithOptionalToken, resolveSetupAccountId, splitSetupEntries } from "openclaw/plugin-sdk/setup-runtime";
|