@openclaw/slack 2026.9.1-beta.1 → 2026.9.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-CN2hBsim.js → account-inspect-C3sePHWa.js} +3 -3
- package/dist/account-inspect-api.js +1 -1
- package/dist/{action-runtime-BoSeX09X.js → action-runtime-DftQWpI4.js} +84 -66
- package/dist/action-runtime.runtime-rHI3UAh4.js +2 -0
- package/dist/{actions-XdQyjG_p.js → actions-CFkvEv1d.js} +198 -54
- package/dist/api.js +14 -14
- package/dist/{approval-handler.runtime-DxXfGX_Z.js → approval-handler.runtime-BeILKdw4.js} +47 -25
- package/dist/{channel-C_vnTgxo.js → channel-CmOuxbOD.js} +76 -133
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-type-j-2lalcC.js → channel-type-BWt2CRaI.js} +2 -2
- package/dist/{channel.setup-aal8tokM.js → channel.setup-D5z1ReaT.js} +29 -23
- package/dist/{config-schema-CN3XZRX5.js → config-schema-JDx_f9Zb.js} +26 -17
- package/dist/{cursor-pages-eX7p8Wwt.js → cursor-pages-ByFwo-Py.js} +7 -1
- package/dist/{directory-config-DqfQ42OV.js → directory-config-Bmw4ykSy.js} +4 -3
- package/dist/directory-contract-api.js +1 -1
- package/dist/{directory-live-lC6X_Ru-.js → directory-live-BuBPHmju.js} +3 -8
- package/dist/{doctor-contract-BAy7-EUQ.js → doctor-contract-BNjw9bxb.js} +5 -4
- package/dist/doctor-contract-api.js +1 -1
- package/dist/{message-tool-api-CWosHSi5.js → message-tool-api-uNEfQYGY.js} +19 -2
- package/dist/message-tool-api.js +1 -1
- package/dist/{monitor-DrNCGneD.js → monitor-DI07pfJl.js} +3 -3
- package/dist/{outbound-adapter-DkT2vUE9.js → outbound-adapter-B5QyTRpJ.js} +96 -91
- package/dist/{pipeline.runtime-CRRng_Nw.js → pipeline.runtime-BdIwZgm4.js} +596 -920
- package/dist/{policy-BoP6t88v.js → policy-Bh5TOqII.js} +7 -4
- package/dist/{probe-4_aHtVT3.js → probe-Biy--yhL.js} +251 -12
- package/dist/{provider-D4nDgxCh.js → provider-DoaUvAM4.js} +5621 -4944
- package/dist/{relay-source-CEmze11m.js → relay-source-D4uecp68.js} +6 -4
- package/dist/{replies-D9XMM_S0.js → replies-DENuTcPO.js} +21 -16
- package/dist/reply-blocks-PRkhyAN7.js +790 -0
- package/dist/{resolve-channels-DSamDgVs.js → resolve-channels-DQGV2VrE.js} +6 -10
- package/dist/{resolve-users-CIzwbaJR.js → resolve-users-DRGt_Q4I.js} +5 -4
- package/dist/runtime-api.js +10 -10
- package/dist/{scopes-BBrUzpBH.js → scopes-CZzeGdWV.js} +1 -1
- package/dist/{send-DtjEnlLh.js → send-DElUcgIs.js} +32 -24
- package/dist/send-results-eeOu_HYm.js +23 -0
- package/dist/{send.runtime-DQeNKa2J.js → send.runtime-C8D6cKGm.js} +1 -1
- package/dist/{group-policy-CU1tEGpS.js → session-status-BynwcZSO.js} +284 -1013
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-CsBCM4rP.js → setup-surface-B1_gpGBl.js} +5 -5
- package/dist/{shared-D9GeeR9K.js → shared-CNQsWJT7.js} +7 -5
- package/dist/{slash-dispatch.runtime-Chr3YHnT.js → slash-dispatch.runtime-DhsXavSY.js} +2 -2
- package/dist/{target-parsing-BnMD2ZqZ.js → target-parsing-PbxGDbr9.js} +11 -6
- package/dist/{targets-Cx5W_n3W.js → targets-7FexXJ62.js} +1 -1
- package/dist/{thread-ts-DUGhaYKq.js → thread-ts-CukseRVL.js} +5 -1
- package/node_modules/@slack/bolt/node_modules/negotiator/lib/accept.js +54 -0
- package/node_modules/@slack/bolt/node_modules/negotiator/lib/charset.js +10 -34
- package/node_modules/@slack/bolt/node_modules/negotiator/lib/encoding.js +9 -30
- package/node_modules/@slack/bolt/node_modules/negotiator/lib/language.js +15 -36
- package/node_modules/@slack/bolt/node_modules/negotiator/lib/mediaType.js +16 -134
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/LICENSE +22 -0
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/README.md +71 -0
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.d.ts +46 -0
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.js +176 -0
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.js.map +1 -0
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/package.json +52 -0
- package/node_modules/@slack/bolt/node_modules/negotiator/package.json +16 -10
- package/node_modules/typebox/build/format/email.mjs +1 -1
- package/node_modules/typebox/build/format/idna/idn-hostname.mjs +19 -1
- package/node_modules/typebox/build/format/json_pointer.d.mts +2 -2
- package/node_modules/typebox/build/format/json_pointer.mjs +2 -2
- package/node_modules/typebox/build/format/json_pointer_uri_fragment.d.mts +2 -2
- package/node_modules/typebox/build/format/json_pointer_uri_fragment.mjs +2 -2
- 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/system/memory/assign.mjs +2 -1
- package/node_modules/typebox/build/system/memory/create.mjs +3 -4
- package/node_modules/typebox/build/system/memory/discard.mjs +2 -2
- package/node_modules/typebox/build/system/memory/freeze.d.mts +4 -0
- package/node_modules/typebox/build/system/memory/freeze.mjs +6 -0
- package/node_modules/typebox/build/system/memory/update.mjs +3 -2
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/undici/lib/dispatcher/balanced-pool.js +4 -2
- package/node_modules/undici/lib/dispatcher/client-h1.js +12 -4
- package/node_modules/undici/lib/dispatcher/client-h2.js +70 -14
- package/node_modules/undici/lib/dispatcher/client.js +6 -2
- package/node_modules/undici/lib/handler/cache-handler.js +21 -5
- package/node_modules/undici/lib/handler/retry-handler.js +42 -7
- package/node_modules/undici/lib/interceptor/cache.js +20 -1
- package/node_modules/undici/lib/interceptor/decompress.js +146 -14
- package/node_modules/undici/lib/interceptor/dump.js +10 -23
- package/node_modules/undici/lib/web/eventsource/eventsource-stream.js +245 -150
- package/node_modules/undici/lib/web/websocket/connection.js +1 -1
- package/node_modules/undici/lib/web/websocket/permessage-deflate.js +5 -0
- package/node_modules/undici/lib/web/websocket/stream/websocketstream.js +8 -10
- package/node_modules/undici/package.json +1 -1
- package/node_modules/undici/types/interceptors.d.ts +2 -0
- package/openclaw.plugin.json +17 -9
- package/package.json +6 -6
- package/skills/_vendor/slack-skills-plugin.LICENSE +21 -0
- package/skills/_vendor/slack-skills-plugin.json +31 -0
- package/skills/block-kit/SKILL.md +37 -0
- package/skills/block-kit/references/official-block-kit.md +257 -0
- package/skills/block-kit/references/official-common-patterns.md +385 -0
- package/skills/slack/SKILL.md +1 -1
- package/dist/action-runtime.runtime-Dpa16J87.js +0 -2
- package/dist/conversation-binding-route-DFVLUdYF.js +0 -115
- package/dist/slack-client-kind-hSfjXyUM.js +0 -94
- package/node_modules/@slack/bolt/node_modules/negotiator/HISTORY.md +0 -114
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
|
|
2
|
-
import { a as resolveSlackAccount, f as resolveSlackBotToken } from "./accounts-Dm_H77gH.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { m as buildSlackNativeDataDeliveryPlan, r as sendMessageSlack } from "./send-
|
|
2
|
+
import { a as resolveSlackAccount, f as resolveSlackBotToken, i as resolveDefaultSlackAccountId } from "./accounts-Dm_H77gH.js";
|
|
3
|
+
import { A as countSlackTextUtf8Bytes, C as buildSlackBlocksFallbackText, E as SLACK_EDIT_TEXT_MAX_BYTES, M as truncateSlackTextByUtf8Bytes, S as stripSlackNativeDataBlocks, T as renderSlackBlockFallbackText, Y as normalizeSlackOutboundText, at as escapeSlackMrkdwn, ct as validateSlackBlocksArray, f as assertSlackDetachedTargetAllowed, h as appendSlackNativeDataPlainTextFallback, jt as SLACK_PRIVATE_ACTION_DELIVERY_RESULT, m as appendSlackNativeDataFallbackText, v as hasSlackNativeDataBlock, w as buildSlackCompleteBlocksFallbackText, y as isSlackInvalidBlocksError } from "./session-status-BynwcZSO.js";
|
|
4
|
+
import { n as formatSlackTarget } from "./target-parsing-PbxGDbr9.js";
|
|
5
|
+
import { m as getSlackWriteClient, s as createSlackLookupClient } from "./probe-Biy--yhL.js";
|
|
6
|
+
import { m as buildSlackNativeDataDeliveryPlan, r as sendMessageSlack } from "./send-DElUcgIs.js";
|
|
7
7
|
import { normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
|
|
8
8
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
9
|
-
import { logVerbose, logVerbose as logVerbose$1 } from "openclaw/plugin-sdk/runtime-env";
|
|
9
|
+
import { createSubsystemLogger, logVerbose, logVerbose as logVerbose$1 } from "openclaw/plugin-sdk/runtime-env";
|
|
10
|
+
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
11
|
+
import { redactToolPayloadText } from "openclaw/plugin-sdk/logging-core";
|
|
10
12
|
import { z } from "zod";
|
|
11
13
|
import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
12
14
|
import fs from "node:fs/promises";
|
|
@@ -14,6 +16,31 @@ import { runTasksWithConcurrency } from "openclaw/plugin-sdk/concurrency-runtime
|
|
|
14
16
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
15
17
|
import { normalizeHostname } from "openclaw/plugin-sdk/host-runtime";
|
|
16
18
|
import { resolveRequestUrl } from "openclaw/plugin-sdk/request-url";
|
|
19
|
+
import { fetchWithRuntimeDispatcher } from "openclaw/plugin-sdk/runtime-fetch";
|
|
20
|
+
import { saveRemoteMedia } from "openclaw/plugin-sdk/media-runtime";
|
|
21
|
+
//#region extensions/slack/src/conversation-open.ts
|
|
22
|
+
function parseSlackConversationOpenInput(userIds, teamId) {
|
|
23
|
+
const users = z.array(z.string().trim().regex(/^[UW][A-Z0-9]+$/)).min(1).max(8).parse(userIds);
|
|
24
|
+
if (new Set(users).size !== users.length) throw new Error("Slack conversation-open requires distinct userIds.");
|
|
25
|
+
return {
|
|
26
|
+
users,
|
|
27
|
+
teamId: teamId === void 0 ? void 0 : z.string().trim().regex(/^T[A-Z0-9]+$/i).parse(teamId)
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
async function openSlackConversationWithClient(client, input) {
|
|
31
|
+
const channelId = (await client.conversations.open({ users: input.users.join(",") })).channel?.id?.trim();
|
|
32
|
+
if (!channelId || !/^[CDG][A-Z0-9]+$/i.test(channelId)) throw new Error("Slack conversations.open did not return a valid conversation ID.");
|
|
33
|
+
return {
|
|
34
|
+
channelId,
|
|
35
|
+
target: formatSlackTarget({
|
|
36
|
+
teamId: input.teamId,
|
|
37
|
+
kind: "channel",
|
|
38
|
+
id: channelId,
|
|
39
|
+
explicitKind: true
|
|
40
|
+
})
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
17
44
|
//#region extensions/slack/src/edit-text.ts
|
|
18
45
|
function buildSlackEditTextPayload(content, blocks) {
|
|
19
46
|
const trimmedContent = content.trim();
|
|
@@ -21,12 +48,92 @@ function buildSlackEditTextPayload(content, blocks) {
|
|
|
21
48
|
if (trimmedContent && !blockText) return trimmedContent;
|
|
22
49
|
if (trimmedContent) {
|
|
23
50
|
const nativePlainText = blocks?.length ? appendSlackNativeDataPlainTextFallback("", blocks).trim() : "";
|
|
24
|
-
|
|
51
|
+
const fallbackText = Boolean(blockText && trimmedContent.includes(blockText)) || Boolean(nativePlainText && trimmedContent.includes(nativePlainText)) ? trimmedContent : blockText && !blockText.includes(trimmedContent) ? `${trimmedContent}\n\n${blockText}` : blockText || trimmedContent;
|
|
52
|
+
return truncateSlackTextByUtf8Bytes(fallbackText, SLACK_EDIT_TEXT_MAX_BYTES);
|
|
25
53
|
}
|
|
26
54
|
if (blockText) return truncateSlackTextByUtf8Bytes(blockText, SLACK_EDIT_TEXT_MAX_BYTES);
|
|
27
55
|
return " ";
|
|
28
56
|
}
|
|
29
57
|
//#endregion
|
|
58
|
+
//#region extensions/slack/src/monitor/block-text.ts
|
|
59
|
+
function readSlackBlockType(block) {
|
|
60
|
+
return block && typeof block === "object" && !Array.isArray(block) ? block.type : void 0;
|
|
61
|
+
}
|
|
62
|
+
function hasSlackTableBlock(blocks) {
|
|
63
|
+
return blocks?.some((block) => readSlackBlockType(block) === "table") ?? false;
|
|
64
|
+
}
|
|
65
|
+
function hasSlackMessageTableBlock(message) {
|
|
66
|
+
return hasSlackTableBlock(message.blocks) || message.attachments?.some((attachment) => !isSlackUnfurlAttachment(attachment) && hasSlackTableBlock(attachment.blocks)) === true;
|
|
67
|
+
}
|
|
68
|
+
function isSlackUnfurlAttachment(attachment) {
|
|
69
|
+
return attachment.is_msg_unfurl === true || attachment.is_app_unfurl === true || typeof attachment.app_unfurl_url === "string" && attachment.app_unfurl_url.trim().length > 0;
|
|
70
|
+
}
|
|
71
|
+
function resolveSlackBlocksText(blocks) {
|
|
72
|
+
if (!blocks?.length) return;
|
|
73
|
+
const parts = [];
|
|
74
|
+
let hasRichText = false;
|
|
75
|
+
let hasNativeData = false;
|
|
76
|
+
for (const block of blocks) {
|
|
77
|
+
const blockType = readSlackBlockType(block);
|
|
78
|
+
hasRichText ||= blockType === "rich_text";
|
|
79
|
+
hasNativeData ||= blockType === "data_visualization" || blockType === "data_table" || blockType === "table";
|
|
80
|
+
const text = renderSlackBlockFallbackText(block, {
|
|
81
|
+
nativeDataFormat: "plain",
|
|
82
|
+
nativeReferenceFormat: "plain"
|
|
83
|
+
});
|
|
84
|
+
if (text) parts.push(text);
|
|
85
|
+
}
|
|
86
|
+
return parts.length > 0 ? {
|
|
87
|
+
text: parts.join("\n"),
|
|
88
|
+
hasRichText,
|
|
89
|
+
hasNativeData
|
|
90
|
+
} : void 0;
|
|
91
|
+
}
|
|
92
|
+
function appendDistinctSlackText(base, addition) {
|
|
93
|
+
if (!base) return addition;
|
|
94
|
+
const comparableBase = `\n${base.replace(/\r\n?/g, "\n")}\n`;
|
|
95
|
+
const comparableAddition = `\n${addition.replace(/\r\n?/g, "\n")}\n`;
|
|
96
|
+
if (comparableBase.includes(comparableAddition)) return base;
|
|
97
|
+
return `${base}\n${addition}`;
|
|
98
|
+
}
|
|
99
|
+
function resolveSlackAttachmentTableTexts(attachments) {
|
|
100
|
+
const seen = /* @__PURE__ */ new Set();
|
|
101
|
+
const texts = [];
|
|
102
|
+
for (const attachment of attachments ?? []) {
|
|
103
|
+
if (isSlackUnfurlAttachment(attachment)) continue;
|
|
104
|
+
for (const block of attachment.blocks ?? []) {
|
|
105
|
+
if (readSlackBlockType(block) !== "table") continue;
|
|
106
|
+
const text = renderSlackBlockFallbackText(block, { nativeDataFormat: "plain" });
|
|
107
|
+
if (!text || seen.has(text)) continue;
|
|
108
|
+
seen.add(text);
|
|
109
|
+
texts.push(text);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return texts;
|
|
113
|
+
}
|
|
114
|
+
/** Resolve agent-visible Slack text while admitting only native tables from attachments. */
|
|
115
|
+
function resolveSlackMessageText(message, options = {}) {
|
|
116
|
+
let resolved = chooseSlackPrimaryText({
|
|
117
|
+
messageText: options.preserveMessageTextWhitespace ? typeof message.text === "string" && message.text.trim().length > 0 ? message.text : void 0 : normalizeOptionalString(message.text),
|
|
118
|
+
blocksText: resolveSlackBlocksText(message.blocks)
|
|
119
|
+
});
|
|
120
|
+
for (const tableText of resolveSlackAttachmentTableTexts(message.attachments)) resolved = appendDistinctSlackText(resolved, tableText);
|
|
121
|
+
return resolved;
|
|
122
|
+
}
|
|
123
|
+
function chooseSlackPrimaryText(params) {
|
|
124
|
+
const { messageText, blocksText } = params;
|
|
125
|
+
if (!blocksText) return messageText;
|
|
126
|
+
if (!messageText) return blocksText.text;
|
|
127
|
+
if (blocksText.hasNativeData) {
|
|
128
|
+
const comparableMessageText = messageText.replace(/\s+/g, " ").trim();
|
|
129
|
+
const comparableBlocksText = blocksText.text.replace(/\s+/g, " ").trim();
|
|
130
|
+
if (comparableMessageText.includes(comparableBlocksText)) return messageText;
|
|
131
|
+
return comparableBlocksText.startsWith(comparableMessageText) ? blocksText.text : `${messageText}\n${blocksText.text}`;
|
|
132
|
+
}
|
|
133
|
+
if (blocksText.hasRichText && blocksText.text.length > messageText.length) return blocksText.text;
|
|
134
|
+
return blocksText.text.length > messageText.length && blocksText.text.startsWith(messageText) ? blocksText.text : messageText;
|
|
135
|
+
}
|
|
136
|
+
//#endregion
|
|
30
137
|
//#region extensions/slack/src/file-reference.ts
|
|
31
138
|
function formatSlackFileReference(file) {
|
|
32
139
|
const name = normalizeOptionalString(file?.name) ?? "file";
|
|
@@ -45,6 +152,21 @@ function formatSlackFileReferenceList(files) {
|
|
|
45
152
|
return files.map((file) => formatSlackFileReference(file)).join(", ");
|
|
46
153
|
}
|
|
47
154
|
//#endregion
|
|
155
|
+
//#region extensions/slack/src/monitor/media.runtime.ts
|
|
156
|
+
const slackMediaLog = createSubsystemLogger("gateway/channels/slack").child("media");
|
|
157
|
+
//#endregion
|
|
158
|
+
//#region extensions/slack/src/monitor/slack-client-kind.ts
|
|
159
|
+
/** Detects the isolated GovSlack API plane without consulting mutable config. */
|
|
160
|
+
function isGovSlackClient(client) {
|
|
161
|
+
if (!client?.slackApiUrl) return false;
|
|
162
|
+
try {
|
|
163
|
+
const apiUrl = new URL(client.slackApiUrl);
|
|
164
|
+
return apiUrl.protocol === "https:" && !apiUrl.port && normalizeHostname(apiUrl.hostname) === "slack-gov.com";
|
|
165
|
+
} catch {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
//#endregion
|
|
48
170
|
//#region extensions/slack/src/monitor/media.ts
|
|
49
171
|
var media_exports = /* @__PURE__ */ __exportAll({
|
|
50
172
|
SLACK_MEDIA_READ_IDLE_TIMEOUT_MS: () => SLACK_MEDIA_READ_IDLE_TIMEOUT_MS,
|
|
@@ -180,6 +302,10 @@ async function looksLikeHtmlFile(filePath) {
|
|
|
180
302
|
}
|
|
181
303
|
const MAX_SLACK_MEDIA_CONCURRENCY = 3;
|
|
182
304
|
const MAX_SLACK_FORWARDED_ATTACHMENTS = 8;
|
|
305
|
+
const SLACK_MEDIA_LIMIT_REASON = `omitted: 8-file limit`;
|
|
306
|
+
function formatSlackMediaFailure(error) {
|
|
307
|
+
return redactToolPayloadText(formatErrorMessage(error)).replace(/\s+/g, " ").slice(0, 200);
|
|
308
|
+
}
|
|
183
309
|
async function fetchFreshSlackFileUrl(params) {
|
|
184
310
|
if (!params.file.id || !params.client) return null;
|
|
185
311
|
try {
|
|
@@ -221,7 +347,7 @@ async function downloadSlackMediaFile(params) {
|
|
|
221
347
|
if (!(fileMime === "text/html" || fileName.endsWith(".html") || fileName.endsWith(".htm"))) {
|
|
222
348
|
if (normalizeOptionalLowercaseString(saved.contentType?.split(";")[0]) === "text/html" || await looksLikeHtmlFile(saved.path)) {
|
|
223
349
|
await fs.rm(saved.path, { force: true }).catch(() => void 0);
|
|
224
|
-
|
|
350
|
+
throw new Error("blocked: unexpected HTML content");
|
|
225
351
|
}
|
|
226
352
|
}
|
|
227
353
|
const effectiveMime = resolveSlackMediaMimetype(params.file, saved.contentType);
|
|
@@ -259,6 +385,7 @@ async function resolveSlackMedia(params) {
|
|
|
259
385
|
const govSlack = isGovSlackClient(params.client);
|
|
260
386
|
const files = params.files ?? [];
|
|
261
387
|
const limitedFiles = files.length > 8 ? files.slice(0, 8) : files;
|
|
388
|
+
for (const file of files.slice(8)) params.unavailableFiles?.set(file, SLACK_MEDIA_LIMIT_REASON);
|
|
262
389
|
const refreshFileUrl = (file) => fetchFreshSlackFileUrl({
|
|
263
390
|
file,
|
|
264
391
|
client: params.client,
|
|
@@ -269,40 +396,30 @@ async function resolveSlackMedia(params) {
|
|
|
269
396
|
const preloaded = params.preloadedMedia?.get(file);
|
|
270
397
|
if (preloaded) return preloaded;
|
|
271
398
|
const eventUrl = file.url_private_download ?? file.url_private;
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
token: params.token,
|
|
291
|
-
maxBytes: params.maxBytes,
|
|
292
|
-
readIdleTimeoutMs: params.readIdleTimeoutMs,
|
|
293
|
-
totalTimeoutMs: params.totalTimeoutMs,
|
|
294
|
-
abortSignal: params.abortSignal,
|
|
295
|
-
govSlack
|
|
296
|
-
}).catch(() => null);
|
|
399
|
+
let url = eventUrl ?? await refreshFileUrl(file);
|
|
400
|
+
let reason = "no private download URL";
|
|
401
|
+
for (let attempt = 0; url && attempt < 2; attempt += 1) {
|
|
402
|
+
try {
|
|
403
|
+
return await downloadSlackMediaFile({
|
|
404
|
+
...params,
|
|
405
|
+
file,
|
|
406
|
+
url,
|
|
407
|
+
govSlack
|
|
408
|
+
});
|
|
409
|
+
} catch (error) {
|
|
410
|
+
reason = formatSlackMediaFailure(error);
|
|
411
|
+
}
|
|
412
|
+
url = attempt === 0 && eventUrl ? await refreshFileUrl(file) : null;
|
|
413
|
+
}
|
|
414
|
+
params.unavailableFiles?.set(file, reason);
|
|
415
|
+
slackMediaLog.warn(`slack: file ${formatSlackFileReference(file)} unavailable (${reason})`);
|
|
416
|
+
return null;
|
|
297
417
|
}),
|
|
298
418
|
limit: MAX_SLACK_MEDIA_CONCURRENCY,
|
|
299
419
|
errorMode: "stop",
|
|
300
420
|
throwOnError: true
|
|
301
421
|
});
|
|
302
|
-
const resolved = results.filter((result
|
|
303
|
-
if (result) params.resolvedFiles?.add(limitedFiles[index]);
|
|
304
|
-
return result !== null;
|
|
305
|
-
});
|
|
422
|
+
const resolved = results.filter((result) => result !== null);
|
|
306
423
|
return resolved.length > 0 ? resolved : null;
|
|
307
424
|
}
|
|
308
425
|
/** Extracts text and media from forwarded-message attachments. Returns null when empty. */
|
|
@@ -317,7 +434,8 @@ async function resolveSlackAttachmentContent(params) {
|
|
|
317
434
|
if (fileIds.has(fileId)) return false;
|
|
318
435
|
fileIds.add(fileId);
|
|
319
436
|
return true;
|
|
320
|
-
}).
|
|
437
|
+
}).map((file, index) => {
|
|
438
|
+
if (index >= 8) return file;
|
|
321
439
|
const fileId = normalizeOptionalString(file.id);
|
|
322
440
|
const preloaded = fileId && candidates.find((candidate) => normalizeOptionalString(candidate.id) === fileId && params.preloadedMedia?.has(candidate));
|
|
323
441
|
if (preloaded) return preloaded;
|
|
@@ -325,11 +443,11 @@ async function resolveSlackAttachmentContent(params) {
|
|
|
325
443
|
const downloadable = candidates.find((candidate) => normalizeOptionalString(candidate.id) === fileId && (candidate.url_private_download || candidate.url_private));
|
|
326
444
|
return downloadable ? Object.assign({}, file, downloadable) : file;
|
|
327
445
|
});
|
|
328
|
-
const pendingFiles = new Map(allFiles.map((file) => [normalizeOptionalString(file.id) ?? file, file]));
|
|
329
|
-
const
|
|
446
|
+
const pendingFiles = new Map(allFiles.slice(0, 8).map((file) => [normalizeOptionalString(file.id) ?? file, file]));
|
|
447
|
+
const unavailableFileReasons = /* @__PURE__ */ new Map();
|
|
330
448
|
const resolveFiles = (files) => resolveSlackMedia({
|
|
331
449
|
...params,
|
|
332
|
-
|
|
450
|
+
unavailableFiles: unavailableFileReasons,
|
|
333
451
|
files: files?.flatMap((file) => {
|
|
334
452
|
const key = normalizeOptionalString(file.id) ?? file;
|
|
335
453
|
const selected = pendingFiles.get(key);
|
|
@@ -340,7 +458,7 @@ async function resolveSlackAttachmentContent(params) {
|
|
|
340
458
|
const directMediaPromise = resolveFiles(params.files);
|
|
341
459
|
const textBlocks = [];
|
|
342
460
|
const attachmentMedia = [];
|
|
343
|
-
let
|
|
461
|
+
let unavailableMediaCount = 0;
|
|
344
462
|
const govSlack = isGovSlackClient(params.client);
|
|
345
463
|
for (const att of forwardedAttachments) {
|
|
346
464
|
const text = att.text?.trim() || att.fallback?.trim();
|
|
@@ -371,19 +489,27 @@ async function resolveSlackAttachmentContent(params) {
|
|
|
371
489
|
...saved.fileName ? { fileName: saved.fileName } : {},
|
|
372
490
|
placeholder: `[Forwarded image: ${label}]`
|
|
373
491
|
});
|
|
374
|
-
} catch {
|
|
375
|
-
|
|
492
|
+
} catch (error) {
|
|
493
|
+
unavailableMediaCount += 1;
|
|
494
|
+
slackMediaLog.warn(`slack: forwarded image unavailable (${formatSlackMediaFailure(error)})`);
|
|
376
495
|
}
|
|
377
496
|
attachmentMedia.push(...await resolveFiles(att.files) ?? []);
|
|
378
497
|
}
|
|
379
498
|
const allMedia = [...await directMediaPromise ?? [], ...attachmentMedia];
|
|
380
|
-
const unavailableFiles = allFiles.
|
|
499
|
+
const unavailableFiles = allFiles.flatMap((file, index) => {
|
|
500
|
+
const reason = index >= 8 ? SLACK_MEDIA_LIMIT_REASON : unavailableFileReasons.get(file);
|
|
501
|
+
return reason ? [{
|
|
502
|
+
...file,
|
|
503
|
+
reason
|
|
504
|
+
}] : [];
|
|
505
|
+
});
|
|
506
|
+
unavailableMediaCount += unavailableFiles.length;
|
|
381
507
|
const combinedText = textBlocks.join("\n\n");
|
|
382
|
-
if (!combinedText && allMedia.length === 0 && allFiles.length === 0 &&
|
|
508
|
+
if (!combinedText && allMedia.length === 0 && allFiles.length === 0 && unavailableMediaCount === 0) return null;
|
|
383
509
|
return {
|
|
384
510
|
text: combinedText,
|
|
385
511
|
media: allMedia,
|
|
386
|
-
|
|
512
|
+
unavailableMediaCount,
|
|
387
513
|
...unavailableFiles.length > 0 ? { files: unavailableFiles } : {}
|
|
388
514
|
};
|
|
389
515
|
}
|
|
@@ -398,6 +524,7 @@ var actions_exports = /* @__PURE__ */ __exportAll({
|
|
|
398
524
|
listSlackEmojis: () => listSlackEmojis,
|
|
399
525
|
listSlackPins: () => listSlackPins,
|
|
400
526
|
listSlackReactions: () => listSlackReactions,
|
|
527
|
+
openSlackConversation: () => openSlackConversation,
|
|
401
528
|
pinSlackMessage: () => pinSlackMessage,
|
|
402
529
|
reactSlackMessage: () => reactSlackMessage,
|
|
403
530
|
readSlackMessages: () => readSlackMessages,
|
|
@@ -421,8 +548,9 @@ function resolveToken(explicit, accountId, cfg) {
|
|
|
421
548
|
if (token) return token;
|
|
422
549
|
}
|
|
423
550
|
if (!cfg) throw new Error("Slack actions requires a resolved runtime config. Load and resolve config at the command or gateway boundary, then pass cfg through the runtime path.");
|
|
551
|
+
const resolvedCfg = requireRuntimeConfig(cfg, "Slack actions");
|
|
424
552
|
const account = resolveSlackAccount({
|
|
425
|
-
cfg:
|
|
553
|
+
cfg: resolvedCfg,
|
|
426
554
|
accountId
|
|
427
555
|
});
|
|
428
556
|
const token = resolveSlackBotToken(account.botToken ?? void 0);
|
|
@@ -509,10 +637,11 @@ function hasSlackPlatformError(err, code) {
|
|
|
509
637
|
}
|
|
510
638
|
async function getClient(opts = {}, mode = "read") {
|
|
511
639
|
if (opts.client) return opts.client;
|
|
512
|
-
|
|
640
|
+
const accountId = opts.cfg ? resolveSlackAccount({
|
|
513
641
|
cfg: requireRuntimeConfig(opts.cfg, "Slack actions"),
|
|
514
642
|
accountId: opts.accountId
|
|
515
|
-
}).accountId : normalizeAccountId(opts.accountId)
|
|
643
|
+
}).accountId : normalizeAccountId(opts.accountId);
|
|
644
|
+
assertSlackDetachedTargetAllowed(accountId, opts.teamId);
|
|
516
645
|
const token = resolveToken(opts.token, opts.accountId, opts.cfg);
|
|
517
646
|
if (mode === "write") return getSlackWriteClient(token, { teamId: opts.teamId });
|
|
518
647
|
return createSlackLookupClient(token, { teamId: opts.teamId });
|
|
@@ -597,7 +726,13 @@ async function sendSlackMessage(to, content, opts) {
|
|
|
597
726
|
});
|
|
598
727
|
}
|
|
599
728
|
async function editSlackMessage(channelId, messageId, content, opts = {}) {
|
|
600
|
-
|
|
729
|
+
const accountId = opts.accountId ?? (opts.cfg ? resolveDefaultSlackAccountId(opts.cfg) : void 0);
|
|
730
|
+
const tableMode = resolveMarkdownTableMode({
|
|
731
|
+
cfg: opts.cfg,
|
|
732
|
+
channel: "slack",
|
|
733
|
+
accountId
|
|
734
|
+
});
|
|
735
|
+
await editSlackRenderedMessage(channelId, messageId, normalizeSlackOutboundText(content, { tableMode }), opts);
|
|
601
736
|
}
|
|
602
737
|
async function editSlackRenderedMessage(channelId, messageId, content, opts = {}) {
|
|
603
738
|
const client = await getClient(opts, "write");
|
|
@@ -617,10 +752,12 @@ async function editSlackRenderedMessage(channelId, messageId, content, opts = {}
|
|
|
617
752
|
} catch (error) {
|
|
618
753
|
if (!hasSlackNativeDataBlock(blocks) || !isSlackInvalidBlocksError(error)) throw error;
|
|
619
754
|
logVerbose("slack edit: native data block rejected, retrying with text fallback");
|
|
620
|
-
const
|
|
755
|
+
const survivorBlocks = stripSlackNativeDataBlocks(blocks);
|
|
756
|
+
const survivorText = buildSlackBlocksFallbackText(survivorBlocks) ?? "";
|
|
621
757
|
const authoredEditText = content.trim();
|
|
758
|
+
const baseText = authoredEditText && !survivorText.includes(authoredEditText) ? authoredEditText : "";
|
|
622
759
|
const fallbackPlan = buildSlackNativeDataDeliveryPlan({
|
|
623
|
-
baseText
|
|
760
|
+
baseText,
|
|
624
761
|
blocks: blocks ?? []
|
|
625
762
|
});
|
|
626
763
|
if (fallbackPlan.fallbackMessages.length !== 1) throw new Error("Slack native chart or table edit fallback requires multiple messages. Send a new message instead.", { cause: error });
|
|
@@ -642,6 +779,13 @@ async function deleteSlackMessage(channelId, messageId, opts = {}) {
|
|
|
642
779
|
ts: messageId
|
|
643
780
|
});
|
|
644
781
|
}
|
|
782
|
+
async function openSlackConversation(userIds, opts = {}) {
|
|
783
|
+
const input = parseSlackConversationOpenInput(userIds, opts.teamId);
|
|
784
|
+
return await openSlackConversationWithClient(await getClient({
|
|
785
|
+
...opts,
|
|
786
|
+
teamId: input.teamId
|
|
787
|
+
}, "write"), input);
|
|
788
|
+
}
|
|
645
789
|
async function resolveSlackConversationName(channelId, opts = {}) {
|
|
646
790
|
return (await (await getClient(opts, "read")).conversations.info({ channel: channelId })).channel?.name?.trim() || void 0;
|
|
647
791
|
}
|
|
@@ -786,4 +930,4 @@ async function downloadSlackFile(fileId, opts) {
|
|
|
786
930
|
}))?.[0] ?? null;
|
|
787
931
|
}
|
|
788
932
|
//#endregion
|
|
789
|
-
export { media_exports as _, editSlackRenderedMessage as a,
|
|
933
|
+
export { hasSlackMessageTableBlock as C, resolveSlackMessageText as D, resolveSlackBlocksText as E, buildSlackEditTextPayload as O, formatSlackFileReferenceList as S, isSlackUnfurlAttachment as T, media_exports as _, editSlackRenderedMessage as a, saveRemoteMedia as b, listSlackPins as c, reactSlackMessage as d, readSlackMessages as f, unpinSlackMessage as g, sendSlackMessage as h, editSlackMessage as i, listSlackReactions as l, removeSlackReaction as m, deleteSlackMessage as n, getSlackMemberInfo as o, removeOwnSlackReactions as p, downloadSlackFile as r, listSlackEmojis as s, actions_exports as t, pinSlackMessage as u, logVerbose$1 as v, hasSlackTableBlock as w, formatSlackFileReference as x, isGovSlackClient as y };
|
package/dist/api.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { n as registerSlackHttpHandler, r as normalizeSlackWebhookPath, t as handleSlackHttpRequest } from "./registry-bbjH7IHX.js";
|
|
2
2
|
import { a as resolveSlackAccount, i as resolveDefaultSlackAccountId, n as listSlackAccountIds, r as mergeSlackAccountConfig, t as listEnabledSlackAccounts } from "./accounts-Dm_H77gH.js";
|
|
3
|
-
import {
|
|
4
|
-
import { t as inspectSlackAccount } from "./account-inspect-
|
|
5
|
-
import { a as parseSlackTarget, i as normalizeSlackMessagingTarget, o as resolveSlackChannelId, r as looksLikeSlackTargetId } from "./target-parsing-
|
|
6
|
-
import "./targets-
|
|
7
|
-
import {
|
|
8
|
-
import { n as buildSlackThreadingToolContext, t as slackPlugin } from "./channel-
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { n as resolveSlackChannelType } from "./channel-type-
|
|
12
|
-
import { t as slackSetupPlugin } from "./channel.setup-
|
|
13
|
-
import { c as listSlackPins, d as reactSlackMessage, f as readSlackMessages, g as unpinSlackMessage, h as sendSlackMessage, i as editSlackMessage, l as listSlackReactions, m as removeSlackReaction, n as deleteSlackMessage, o as getSlackMemberInfo, p as removeOwnSlackReactions, r as downloadSlackFile, s as listSlackEmojis, u as pinSlackMessage } from "./actions-
|
|
14
|
-
import { f as recordSlackThreadParticipation, l as hasSlackThreadParticipation, s as clearSlackThreadParticipationCache } from "./send-
|
|
15
|
-
import { n as listSlackDirectoryGroupsFromConfig, r as listSlackDirectoryPeersFromConfig } from "./directory-config-
|
|
3
|
+
import { Mt as resolveSlackAutoThreadId, Nt as resolveSlackReplyToMode, a as resolveSlackGroupRequireMention, ct as validateSlackBlocksArray, o as resolveSlackGroupToolPolicy, ot as SLACK_MAX_BLOCKS, st as parseSlackBlocksInput } from "./session-status-BynwcZSO.js";
|
|
4
|
+
import { t as inspectSlackAccount } from "./account-inspect-C3sePHWa.js";
|
|
5
|
+
import { a as parseSlackTarget, i as normalizeSlackMessagingTarget, o as resolveSlackChannelId, r as looksLikeSlackTargetId } from "./target-parsing-PbxGDbr9.js";
|
|
6
|
+
import "./targets-7FexXJ62.js";
|
|
7
|
+
import { C as normalizeAllowListLower, E as resolveSlackAllowListMatch, O as resolveSlackUserAllowed, S as normalizeAllowList, T as normalizeSlackSlug, b as resolveSlackWriteClientOptions, d as createSlackWebClient, f as createSlackWriteClient, g as SLACK_WRITE_RETRY_OPTIONS, h as SLACK_DEFAULT_RETRY_OPTIONS, m as getSlackWriteClient, t as probeSlack, u as createSlackTokenCacheKey, w as normalizeSlackAllowOwnerEntry, x as allowListMatches, y as resolveSlackWebClientOptions } from "./probe-Biy--yhL.js";
|
|
8
|
+
import { n as buildSlackThreadingToolContext, t as slackPlugin } from "./channel-CmOuxbOD.js";
|
|
9
|
+
import { c as buildSlackInteractiveBlocks, l as buildSlackPresentationBlocks } from "./reply-blocks-PRkhyAN7.js";
|
|
10
|
+
import { n as extractSlackToolSend, r as listSlackMessageActions } from "./message-tool-api-uNEfQYGY.js";
|
|
11
|
+
import { n as resolveSlackChannelType } from "./channel-type-BWt2CRaI.js";
|
|
12
|
+
import { t as slackSetupPlugin } from "./channel.setup-D5z1ReaT.js";
|
|
13
|
+
import { c as listSlackPins, d as reactSlackMessage, f as readSlackMessages, g as unpinSlackMessage, h as sendSlackMessage, i as editSlackMessage, l as listSlackReactions, m as removeSlackReaction, n as deleteSlackMessage, o as getSlackMemberInfo, p as removeOwnSlackReactions, r as downloadSlackFile, s as listSlackEmojis, u as pinSlackMessage } from "./actions-CFkvEv1d.js";
|
|
14
|
+
import { f as recordSlackThreadParticipation, l as hasSlackThreadParticipation, s as clearSlackThreadParticipationCache } from "./send-DElUcgIs.js";
|
|
15
|
+
import { n as listSlackDirectoryGroupsFromConfig, r as listSlackDirectoryPeersFromConfig } from "./directory-config-Bmw4ykSy.js";
|
|
16
16
|
import { t as collectSlackSecurityAuditFindings } from "./security-audit-B_yKr7MW.js";
|
|
17
|
-
import { n as resolveSlackRuntimeGroupPolicy } from "./provider-
|
|
17
|
+
import { n as resolveSlackRuntimeGroupPolicy } from "./provider-DoaUvAM4.js";
|
|
18
18
|
export { SLACK_DEFAULT_RETRY_OPTIONS, SLACK_MAX_BLOCKS, SLACK_WRITE_RETRY_OPTIONS, allowListMatches, buildSlackInteractiveBlocks, buildSlackPresentationBlocks, buildSlackThreadingToolContext, clearSlackThreadParticipationCache, collectSlackSecurityAuditFindings, createSlackTokenCacheKey, createSlackWebClient, createSlackWriteClient, deleteSlackMessage, downloadSlackFile, editSlackMessage, extractSlackToolSend, getSlackMemberInfo, getSlackWriteClient, handleSlackHttpRequest, hasSlackThreadParticipation, inspectSlackAccount, listEnabledSlackAccounts, listSlackAccountIds, listSlackDirectoryGroupsFromConfig, listSlackDirectoryPeersFromConfig, listSlackEmojis, listSlackMessageActions, listSlackPins, listSlackReactions, looksLikeSlackTargetId, mergeSlackAccountConfig, normalizeAllowList, normalizeAllowListLower, normalizeSlackAllowOwnerEntry, normalizeSlackMessagingTarget, normalizeSlackSlug, normalizeSlackWebhookPath, parseSlackBlocksInput, parseSlackTarget, pinSlackMessage, probeSlack, reactSlackMessage, readSlackMessages, recordSlackThreadParticipation, registerSlackHttpHandler, removeOwnSlackReactions, removeSlackReaction, resolveDefaultSlackAccountId, resolveSlackAccount, resolveSlackAllowListMatch, resolveSlackAutoThreadId, resolveSlackChannelId, resolveSlackChannelType, resolveSlackGroupRequireMention, resolveSlackGroupToolPolicy, resolveSlackReplyToMode, resolveSlackRuntimeGroupPolicy, resolveSlackUserAllowed, resolveSlackWebClientOptions, resolveSlackWriteClientOptions, sendSlackMessage, slackPlugin, slackSetupPlugin, unpinSlackMessage, validateSlackBlocksArray };
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { E as SLACK_EDIT_TEXT_MAX_BYTES, M as truncateSlackTextByUtf8Bytes, Ot as normalizeSlackApproverId, _t as shouldHandleSlackNativeApprovalRequest, n as setSlackSessionStatus, ut as isSlackAnyNativeApprovalClientEnabled } from "./session-status-BynwcZSO.js";
|
|
2
|
+
import { a as parseSlackTarget } from "./target-parsing-PbxGDbr9.js";
|
|
3
|
+
import { p as getSlackListenerWriteClient } from "./probe-Biy--yhL.js";
|
|
4
|
+
import { i as resolveSlackReplyBlocks, p as SLACK_APPROVAL_HEADER_BLOCK_ID } from "./reply-blocks-PRkhyAN7.js";
|
|
5
|
+
import { r as sendMessageSlack } from "./send-DElUcgIs.js";
|
|
4
6
|
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
5
7
|
import { buildChannelApprovalNativeTargetKey } from "openclaw/plugin-sdk/approval-native-runtime";
|
|
6
8
|
import { buildApprovalPresentationFromActionDescriptors } from "openclaw/plugin-sdk/approval-reply-runtime";
|
|
@@ -46,7 +48,7 @@ function buildSlackMetadataLines(metadata) {
|
|
|
46
48
|
}
|
|
47
49
|
function buildSlackMetadataContextElements(metadata) {
|
|
48
50
|
const lines = buildSlackMetadataLines(metadata);
|
|
49
|
-
const visibleLineCount = lines.length > SLACK_CONTEXT_ELEMENTS_MAX ?
|
|
51
|
+
const visibleLineCount = lines.length > SLACK_CONTEXT_ELEMENTS_MAX ? 9 : lines.length;
|
|
50
52
|
const elements = [];
|
|
51
53
|
for (let index = 0; index < visibleLineCount; index += 1) {
|
|
52
54
|
const line = lines[index];
|
|
@@ -93,14 +95,15 @@ function buildSlackPluginRequestBlocks(view) {
|
|
|
93
95
|
function buildSlackApprovalPayload(input) {
|
|
94
96
|
const { phase, view } = input;
|
|
95
97
|
const isPlugin = view.approvalKind === "plugin";
|
|
96
|
-
const
|
|
98
|
+
const isSystemAgent = view.approvalKind === "system-agent";
|
|
99
|
+
const approvalName = isPlugin ? "Plugin" : isSystemAgent ? "OpenClaw change" : "Exec";
|
|
97
100
|
let heading;
|
|
98
101
|
let description;
|
|
99
102
|
if (phase === "pending") {
|
|
100
103
|
heading = `*${approvalName} approval required*`;
|
|
101
|
-
description = view.approvalKind === "plugin" ? resolveSlackPluginDescription(view) : "A command needs your approval.";
|
|
104
|
+
description = view.approvalKind === "plugin" ? resolveSlackPluginDescription(view) : isSystemAgent ? "An OpenClaw change needs your approval." : "A command needs your approval.";
|
|
102
105
|
} else if (phase === "resolved") {
|
|
103
|
-
heading = `*${approvalName} approval: ${resolveSlackApprovalDecisionLabel(view.decision)}*`;
|
|
106
|
+
heading = `*${approvalName} approval: ${isSystemAgent && view.terminalStatus === "cancelled" ? "Cancelled" : isSystemAgent && view.applicationStatus === "applied" ? "Applied" : isSystemAgent && view.applicationStatus === "not-applied" ? "Not applied" : resolveSlackApprovalDecisionLabel(view.decision)}*`;
|
|
104
107
|
const resolvedBy = formatSlackApprover(view.resolvedBy);
|
|
105
108
|
description = resolvedBy ? `Resolved by ${resolvedBy}.` : "Resolved.";
|
|
106
109
|
} else {
|
|
@@ -108,7 +111,7 @@ function buildSlackApprovalPayload(input) {
|
|
|
108
111
|
description = "This approval request expired before it was resolved.";
|
|
109
112
|
}
|
|
110
113
|
const metadata = isPlugin ? buildSlackPluginMetadata(view) : view.metadata;
|
|
111
|
-
const bodyLabel = isPlugin ? "*Request*" : "*Command*";
|
|
114
|
+
const bodyLabel = isPlugin ? "*Request*" : isSystemAgent ? "*Change*" : "*Command*";
|
|
112
115
|
const bodyText = isPlugin ? view.title : buildSlackCodeBlock(view.commandText);
|
|
113
116
|
const text = [
|
|
114
117
|
heading,
|
|
@@ -130,7 +133,7 @@ function buildSlackApprovalPayload(input) {
|
|
|
130
133
|
type: "section",
|
|
131
134
|
text: {
|
|
132
135
|
type: "mrkdwn",
|
|
133
|
-
text:
|
|
136
|
+
text: `${bodyLabel}\n${buildSlackCodeBlock(truncateSlackMrkdwn(view.commandText, 2600))}`
|
|
134
137
|
}
|
|
135
138
|
}, ...phase === "pending" ? buildSlackMetadataContextBlocks(view.metadata) : []]];
|
|
136
139
|
if (phase === "pending") blocks.push(...resolveSlackReplyBlocks({
|
|
@@ -155,7 +158,11 @@ async function updateMessage(params) {
|
|
|
155
158
|
}
|
|
156
159
|
}
|
|
157
160
|
const slackApprovalNativeRuntime = createChannelApprovalNativeRuntimeAdapter({
|
|
158
|
-
eventKinds: [
|
|
161
|
+
eventKinds: [
|
|
162
|
+
"exec",
|
|
163
|
+
"plugin",
|
|
164
|
+
"system-agent"
|
|
165
|
+
],
|
|
159
166
|
availability: {
|
|
160
167
|
isConfigured: (params) => {
|
|
161
168
|
const resolved = resolveHandlerContext(params);
|
|
@@ -217,7 +224,15 @@ const slackApprovalNativeRuntime = createChannelApprovalNativeRuntimeAdapter({
|
|
|
217
224
|
if (!resolved) return null;
|
|
218
225
|
const client = resolveApprovalClient(resolved.context, preparedTarget.teamId);
|
|
219
226
|
const to = await resolveApprovalChannel(client, preparedTarget.to, preparedTarget.teamId);
|
|
220
|
-
const eventScope =
|
|
227
|
+
const eventScope = preparedTarget.teamId ? {
|
|
228
|
+
teamId: preparedTarget.teamId,
|
|
229
|
+
client,
|
|
230
|
+
writeClient: getSlackListenerWriteClient({
|
|
231
|
+
listenerClient: client,
|
|
232
|
+
teamId: preparedTarget.teamId,
|
|
233
|
+
clientOptions: resolved.context.app.webClientOptions
|
|
234
|
+
})
|
|
235
|
+
} : void 0;
|
|
221
236
|
const message = await sendMessageSlack(to, pendingPayload.text, {
|
|
222
237
|
cfg,
|
|
223
238
|
accountId: resolved.accountId,
|
|
@@ -226,26 +241,39 @@ const slackApprovalNativeRuntime = createChannelApprovalNativeRuntimeAdapter({
|
|
|
226
241
|
client,
|
|
227
242
|
eventScope
|
|
228
243
|
});
|
|
244
|
+
await setSlackSessionStatus({
|
|
245
|
+
client,
|
|
246
|
+
channelId: message.channelId,
|
|
247
|
+
threadTs: preparedTarget.threadTs,
|
|
248
|
+
status: "suspended"
|
|
249
|
+
});
|
|
229
250
|
return {
|
|
230
251
|
channelId: message.channelId,
|
|
231
252
|
messageTs: message.messageId,
|
|
253
|
+
threadTs: preparedTarget.threadTs,
|
|
232
254
|
teamId: preparedTarget.teamId
|
|
233
255
|
};
|
|
234
256
|
},
|
|
235
|
-
updateEntry: async ({ cfg, accountId, context, entry, payload }) => {
|
|
257
|
+
updateEntry: async ({ cfg, accountId, context, entry, payload, phase }) => {
|
|
236
258
|
const resolved = resolveHandlerContext({
|
|
237
259
|
cfg,
|
|
238
260
|
accountId,
|
|
239
261
|
context
|
|
240
262
|
});
|
|
241
263
|
if (!resolved) return;
|
|
242
|
-
const
|
|
264
|
+
const client = resolveApprovalClient(resolved.context, entry.teamId);
|
|
243
265
|
await updateMessage({
|
|
244
|
-
client
|
|
266
|
+
client,
|
|
245
267
|
channelId: entry.channelId,
|
|
246
268
|
messageTs: entry.messageTs,
|
|
247
|
-
text:
|
|
248
|
-
blocks:
|
|
269
|
+
text: payload.text,
|
|
270
|
+
blocks: payload.blocks
|
|
271
|
+
});
|
|
272
|
+
await setSlackSessionStatus({
|
|
273
|
+
client,
|
|
274
|
+
channelId: entry.channelId,
|
|
275
|
+
threadTs: entry.threadTs,
|
|
276
|
+
status: phase === "resolved" ? "processing" : "active"
|
|
249
277
|
});
|
|
250
278
|
}
|
|
251
279
|
},
|
|
@@ -260,22 +288,16 @@ function resolveApprovalClient(context, teamId) {
|
|
|
260
288
|
if (!client) throw new Error("Slack Enterprise Grid approval client is unavailable");
|
|
261
289
|
return client;
|
|
262
290
|
}
|
|
263
|
-
function resolveApprovalEventScope(client, teamId) {
|
|
264
|
-
if (!teamId) return;
|
|
265
|
-
return {
|
|
266
|
-
teamId,
|
|
267
|
-
client
|
|
268
|
-
};
|
|
269
|
-
}
|
|
270
291
|
async function resolveApprovalChannel(client, target, teamId) {
|
|
271
292
|
if (!teamId) return target;
|
|
272
293
|
const parsed = parseSlackTarget(target, { defaultKind: "channel" });
|
|
273
294
|
if (!parsed) throw new Error("Slack approval delivery target is missing");
|
|
274
295
|
if (parsed.kind === "channel") return `channel:${parsed.id}`;
|
|
275
|
-
const
|
|
296
|
+
const opened = await client.conversations.open({
|
|
276
297
|
users: parsed.id,
|
|
277
298
|
return_im: true
|
|
278
|
-
})
|
|
299
|
+
});
|
|
300
|
+
const channelId = normalizeOptionalString(opened.channel?.id);
|
|
279
301
|
if (!channelId) throw new Error("Slack Enterprise Grid approval DM did not return a channel id");
|
|
280
302
|
return `channel:${channelId}`;
|
|
281
303
|
}
|