@openclaw/slack 2026.5.14-beta.2 → 2026.5.16-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/{action-runtime-CyE2jfW-.js → action-runtime-p39JLqwf.js} +1 -1
- package/dist/action-runtime.runtime-BzrPV3EA.js +2 -0
- package/dist/{actions-BibhOXpJ.js → actions-BCRbHv1Q.js} +3 -2
- package/dist/{actions.runtime-B9XQG6X4.js → actions.runtime-CpywQR3D.js} +1 -1
- package/dist/api.js +5 -5
- package/dist/{approval-handler.runtime-BjzVRaXN.js → approval-handler.runtime-DXrdRbkT.js} +1 -1
- package/dist/{channel-Dh07mU_K.js → channel-CVSopl66.js} +9 -9
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.setup-CmG37S2W.js → channel.setup-DknBgufI.js} +2 -2
- package/dist/inbound-contract-test-api.js +1 -1
- package/dist/{monitor-DDE5AI2O.js → monitor-CdVxsuHi.js} +2 -2
- package/dist/{outbound-adapter-BluPNDNi.js → outbound-adapter-CHm6e-0Q.js} +1 -1
- package/dist/outbound-payload-test-api.js +1 -1
- package/dist/{outbound-payload.test-harness-BNxnP6MC.js → outbound-payload.test-harness-C0CW7_CE.js} +1 -1
- package/dist/{pipeline.runtime-Dft2-QU4.js → pipeline.runtime-CakcaQh9.js} +113 -136
- package/dist/{prepare-D0tMg4dt.js → prepare-DSRUr44d.js} +220 -81
- package/dist/{provider-C6WxaFFf.js → provider-bKg1hkf5.js} +139 -7
- package/dist/{replies-D0QXXSPP.js → replies-Fg1T3ZzU.js} +2 -2
- package/dist/runtime-api.js +5 -5
- package/dist/{send-Dg9zcyYT.js → send-CxXFbqN1.js} +1 -1
- package/dist/send.runtime-BHCPpSj_.js +2 -0
- package/dist/send.runtime-CDG5AgU3.js +2 -0
- package/dist/{setup-core-WWQl-cE9.js → setup-core-B7pou7oe.js} +23 -22
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-BLoTgna4.js → setup-surface-D6LLzeRz.js} +14 -13
- package/dist/{shared-GoB-OuUq.js → shared-7Vi9j4aV.js} +1 -1
- package/dist/{slash-dispatch.runtime-Bz_OkRcR.js → slash-dispatch.runtime-Cg7uU92H.js} +1 -1
- package/dist/test-api.js +5 -5
- package/package.json +4 -4
- package/dist/action-runtime.runtime-DLhfKw4B.js +0 -2
- package/dist/send.runtime-CjjQ9StM.js +0 -2
- package/dist/send.runtime-E47jGN-2.js +0 -2
|
@@ -2,25 +2,26 @@ import { l as resolveSlackReplyToMode } from "./accounts-yk5K3wQU.js";
|
|
|
2
2
|
import { r as parseSlackTarget } from "./target-parsing-CQmv-iSm.js";
|
|
3
3
|
import "./targets-B1tYCAr6.js";
|
|
4
4
|
import { i as normalizeSlackAllowOwnerEntry, o as resolveSlackAllowListMatch, r as normalizeAllowListLower } from "./allow-list-nwXs_eCP.js";
|
|
5
|
-
import { i as hasSlackThreadParticipationWithPersistence, t as sendMessageSlack } from "./send-
|
|
6
|
-
import { _ as resolveSlackThreadStarter, g as resolveSlackThreadHistory, l as reactSlackMessage, y as formatSlackFileReference } from "./actions-
|
|
5
|
+
import { i as hasSlackThreadParticipationWithPersistence, t as sendMessageSlack } from "./send-CxXFbqN1.js";
|
|
6
|
+
import { _ as resolveSlackThreadStarter, g as resolveSlackThreadHistory, l as reactSlackMessage, y as formatSlackFileReference } from "./actions-BCRbHv1Q.js";
|
|
7
7
|
import { t as formatSlackError } from "./errors-C_sW0Zgl.js";
|
|
8
8
|
import { b as readSessionUpdatedAt, c as authorizeSlackBotRoomMessage, d as resolveSlackEffectiveAllowFrom, g as resolveSlackChannelConfig, h as resolveSlackChatType, k as stripSlackMentionsForCommandDetection, m as normalizeSlackChannelType, n as authorizeSlackDirectMessage, o as resolveConversationLabel$1, t as resolveSlackRoomContextHints, u as resolveSlackCommandIngress, w as resolveStorePath, x as resolveChannelContextVisibilityMode } from "./room-context-Cd8jFpS-.js";
|
|
9
|
-
import "./send.runtime-
|
|
9
|
+
import "./send.runtime-BHCPpSj_.js";
|
|
10
10
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
11
11
|
import { resolveAgentRoute, resolveInboundLastRouteSessionKey, resolveThreadSessionKeys } from "openclaw/plugin-sdk/routing";
|
|
12
12
|
import { resolveChannelMessageSourceReplyDeliveryMode } from "openclaw/plugin-sdk/channel-message";
|
|
13
13
|
import { logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
|
|
14
14
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
15
15
|
import { ensureConfiguredBindingRouteReady, resolveConfiguredBindingRoute, resolveRuntimeConversationBindingRoute } from "openclaw/plugin-sdk/conversation-runtime";
|
|
16
|
-
import {
|
|
16
|
+
import { createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
|
|
17
17
|
import { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
|
|
18
|
-
import { buildMentionRegexes, formatInboundEnvelope, implicitMentionKindWhen, logInboundDrop, matchesMentionWithExplicit, resolveEnvelopeFormatOptions } from "openclaw/plugin-sdk/channel-inbound";
|
|
18
|
+
import { buildChannelTurnContext, buildMentionRegexes, formatInboundEnvelope, implicitMentionKindWhen, logInboundDrop, matchesMentionWithExplicit, resolveEnvelopeFormatOptions, toInboundMediaFacts } from "openclaw/plugin-sdk/channel-inbound";
|
|
19
19
|
import { filterSupplementalContextItems, resolvePinnedMainDmOwnerFromAllowlist, shouldIncludeSupplementalContext } from "openclaw/plugin-sdk/security-runtime";
|
|
20
20
|
import { resolveAckReaction, shouldAckReaction } from "openclaw/plugin-sdk/channel-feedback";
|
|
21
21
|
import { hasControlCommand } from "openclaw/plugin-sdk/command-detection";
|
|
22
22
|
import { shouldHandleTextCommands } from "openclaw/plugin-sdk/command-surface";
|
|
23
|
-
import {
|
|
23
|
+
import { recordDroppedChannelTurnHistory } from "openclaw/plugin-sdk/inbound-reply-dispatch";
|
|
24
|
+
import { mimeTypeFromFilePath } from "openclaw/plugin-sdk/media-mime";
|
|
24
25
|
import { runTasksWithConcurrency } from "openclaw/plugin-sdk/concurrency-runtime";
|
|
25
26
|
//#region extensions/slack/src/monitor/message-handler/prepare-content.ts
|
|
26
27
|
const SLACK_MENTION_RESOLUTION_CONCURRENCY = 4;
|
|
@@ -28,7 +29,7 @@ const SLACK_MENTION_RESOLUTION_MAX_LOOKUPS_PER_MESSAGE = 20;
|
|
|
28
29
|
const SLACK_USER_MENTION_RE$1 = /<@([A-Z0-9]+)(?:\|[^>]+)?>/gi;
|
|
29
30
|
let slackMediaModulePromise$1;
|
|
30
31
|
function loadSlackMediaModule$1() {
|
|
31
|
-
slackMediaModulePromise$1 ??= import("./actions-
|
|
32
|
+
slackMediaModulePromise$1 ??= import("./actions-BCRbHv1Q.js").then((n) => n.h);
|
|
32
33
|
return slackMediaModulePromise$1;
|
|
33
34
|
}
|
|
34
35
|
function collectUniqueSlackMentionIds$1(texts) {
|
|
@@ -190,13 +191,19 @@ async function resolveSlackMessageContent(params) {
|
|
|
190
191
|
files: ownFiles,
|
|
191
192
|
client: params.client,
|
|
192
193
|
token: params.botToken,
|
|
193
|
-
maxBytes: params.mediaMaxBytes
|
|
194
|
+
maxBytes: params.mediaMaxBytes,
|
|
195
|
+
readIdleTimeoutMs: params.mediaReadIdleTimeoutMs,
|
|
196
|
+
totalTimeoutMs: params.mediaTotalTimeoutMs,
|
|
197
|
+
abortSignal: params.abortSignal
|
|
194
198
|
})) : Promise.resolve(null);
|
|
195
199
|
const attachmentContentPromise = params.message.attachments && params.message.attachments.length > 0 ? loadSlackMediaModule$1().then(({ resolveSlackAttachmentContent }) => resolveSlackAttachmentContent({
|
|
196
200
|
attachments: params.message.attachments,
|
|
197
201
|
client: params.client,
|
|
198
202
|
token: params.botToken,
|
|
199
|
-
maxBytes: params.mediaMaxBytes
|
|
203
|
+
maxBytes: params.mediaMaxBytes,
|
|
204
|
+
readIdleTimeoutMs: params.mediaReadIdleTimeoutMs,
|
|
205
|
+
totalTimeoutMs: params.mediaTotalTimeoutMs,
|
|
206
|
+
abortSignal: params.abortSignal
|
|
200
207
|
})) : Promise.resolve(null);
|
|
201
208
|
const [media, attachmentContent] = await Promise.all([mediaPromise, attachmentContentPromise]);
|
|
202
209
|
const mergedMedia = [...media ?? [], ...attachmentContent?.media ?? []];
|
|
@@ -569,7 +576,7 @@ function formatSlackBotStarterThreadLabel(params) {
|
|
|
569
576
|
//#region extensions/slack/src/monitor/message-handler/prepare-thread-context.ts
|
|
570
577
|
let slackMediaModulePromise;
|
|
571
578
|
function loadSlackMediaModule() {
|
|
572
|
-
slackMediaModulePromise ??= import("./actions-
|
|
579
|
+
slackMediaModulePromise ??= import("./actions-BCRbHv1Q.js").then((n) => n.h);
|
|
573
580
|
return slackMediaModulePromise;
|
|
574
581
|
}
|
|
575
582
|
const SLACK_THREAD_CONTEXT_USER_LOOKUP_CONCURRENCY = 4;
|
|
@@ -837,6 +844,10 @@ const SLACK_ANY_MENTION_RE = /<@[^>]+>|<!subteam\^[^>]+>/;
|
|
|
837
844
|
const SLACK_USER_MENTION_RE = /<@([^>|]+)(?:\|[^>]+)?>/g;
|
|
838
845
|
const SLACK_SUBTEAM_MENTION_RE = /<!subteam\^([^>|]+)(?:\|[^>]+)?>/g;
|
|
839
846
|
const SLACK_SUBTEAM_MENTION_MARKER = "<!subteam^";
|
|
847
|
+
const SLACK_HISTORY_MEDIA_MAX_ATTACHMENTS = 4;
|
|
848
|
+
const SLACK_HISTORY_MEDIA_MAX_BYTES = 10 * 1024 * 1024;
|
|
849
|
+
const SLACK_HISTORY_MEDIA_IDLE_TIMEOUT_MS = 1e3;
|
|
850
|
+
const SLACK_HISTORY_MEDIA_TOTAL_TIMEOUT_MS = 3e3;
|
|
840
851
|
function resolveCachedMentionRegexes(ctx, agentId) {
|
|
841
852
|
const key = normalizeOptionalString(agentId) ?? "__default__";
|
|
842
853
|
let byAgent = mentionRegexCache.get(ctx);
|
|
@@ -850,6 +861,60 @@ function resolveCachedMentionRegexes(ctx, agentId) {
|
|
|
850
861
|
byAgent.set(key, built);
|
|
851
862
|
return built;
|
|
852
863
|
}
|
|
864
|
+
function isSlackImageFileCandidate(file) {
|
|
865
|
+
if ((file.mimetype?.split(";")[0]?.trim().toLowerCase())?.startsWith("image/")) return true;
|
|
866
|
+
return Boolean(mimeTypeFromFilePath(file.name)?.startsWith("image/"));
|
|
867
|
+
}
|
|
868
|
+
function sliceSlackImageFileCandidates(files, limit) {
|
|
869
|
+
if (limit <= 0 || !files?.length) return [];
|
|
870
|
+
return files.filter(isSlackImageFileCandidate).slice(0, limit);
|
|
871
|
+
}
|
|
872
|
+
function sliceSlackHistoryAttachmentCandidates(attachments, limit) {
|
|
873
|
+
if (limit <= 0 || !attachments?.length) return [];
|
|
874
|
+
const out = [];
|
|
875
|
+
let remaining = limit;
|
|
876
|
+
for (const attachment of attachments) {
|
|
877
|
+
if (attachment.is_share !== true) continue;
|
|
878
|
+
const hasImageUrl = Boolean(normalizeOptionalString(attachment.image_url));
|
|
879
|
+
const files = sliceSlackImageFileCandidates(attachment.files, remaining - (hasImageUrl ? 1 : 0));
|
|
880
|
+
if (!hasImageUrl && files.length === 0) continue;
|
|
881
|
+
out.push({
|
|
882
|
+
...attachment,
|
|
883
|
+
files
|
|
884
|
+
});
|
|
885
|
+
remaining -= (hasImageUrl ? 1 : 0) + files.length;
|
|
886
|
+
if (remaining <= 0) break;
|
|
887
|
+
}
|
|
888
|
+
return out;
|
|
889
|
+
}
|
|
890
|
+
function buildSlackHistoryMediaCandidateMessage(message) {
|
|
891
|
+
const files = sliceSlackImageFileCandidates(message.files, SLACK_HISTORY_MEDIA_MAX_ATTACHMENTS);
|
|
892
|
+
const attachments = sliceSlackHistoryAttachmentCandidates(message.attachments, Math.max(0, SLACK_HISTORY_MEDIA_MAX_ATTACHMENTS - files.length));
|
|
893
|
+
if (files.length === 0 && attachments.length === 0) return null;
|
|
894
|
+
return {
|
|
895
|
+
...message,
|
|
896
|
+
files,
|
|
897
|
+
attachments
|
|
898
|
+
};
|
|
899
|
+
}
|
|
900
|
+
async function resolveSlackHistoryMediaForPendingRecord(params) {
|
|
901
|
+
const mediaMessage = buildSlackHistoryMediaCandidateMessage(params.message);
|
|
902
|
+
if (!mediaMessage) return [];
|
|
903
|
+
return toInboundMediaFacts((await resolveSlackMessageContent({
|
|
904
|
+
message: mediaMessage,
|
|
905
|
+
isThreadReply: params.isThreadReply,
|
|
906
|
+
threadStarter: params.threadStarter,
|
|
907
|
+
isBotMessage: params.isBotMessage,
|
|
908
|
+
client: params.ctx.app.client,
|
|
909
|
+
botToken: params.ctx.botToken,
|
|
910
|
+
mediaMaxBytes: Math.min(params.ctx.mediaMaxBytes, SLACK_HISTORY_MEDIA_MAX_BYTES),
|
|
911
|
+
mediaReadIdleTimeoutMs: SLACK_HISTORY_MEDIA_IDLE_TIMEOUT_MS,
|
|
912
|
+
mediaTotalTimeoutMs: SLACK_HISTORY_MEDIA_TOTAL_TIMEOUT_MS
|
|
913
|
+
}))?.effectiveDirectMedia, {
|
|
914
|
+
kind: "image",
|
|
915
|
+
messageId: params.message.ts
|
|
916
|
+
});
|
|
917
|
+
}
|
|
853
918
|
function collectUniqueSlackMentionIds(text, regex) {
|
|
854
919
|
const ids = [];
|
|
855
920
|
regex.lastIndex = 0;
|
|
@@ -1198,18 +1263,52 @@ async function prepareSlackMessage(params) {
|
|
|
1198
1263
|
reason: "no-mention"
|
|
1199
1264
|
}, "skipping channel message");
|
|
1200
1265
|
const pendingText = (message.text ?? "").trim();
|
|
1266
|
+
const historyMediaCandidate = buildSlackHistoryMediaCandidateMessage(message);
|
|
1201
1267
|
const fallbackFile = message.files?.length ? `[Slack file: ${formatSlackFileReference(message.files[0])}]` : "";
|
|
1202
|
-
const pendingBody = pendingText || fallbackFile;
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1268
|
+
const pendingBody = pendingText || fallbackFile || (!fallbackFile && historyMediaCandidate ? "[Slack media attachment]" : "");
|
|
1269
|
+
const skippedThreadStarter = historyMediaCandidate && isThreadReply && threadTs ? await resolveSlackThreadStarter({
|
|
1270
|
+
channelId: message.channel,
|
|
1271
|
+
threadTs,
|
|
1272
|
+
client: ctx.app.client
|
|
1273
|
+
}) : null;
|
|
1274
|
+
const timestamp = message.ts ? Math.round(Number(message.ts) * 1e3) : void 0;
|
|
1275
|
+
const senderName = pendingBody ? await resolveSenderName() : void 0;
|
|
1276
|
+
await recordDroppedChannelTurnHistory({
|
|
1277
|
+
input: {
|
|
1278
|
+
id: message.ts ?? `${message.channel}:${Date.now()}`,
|
|
1279
|
+
timestamp,
|
|
1280
|
+
rawText: pendingBody,
|
|
1281
|
+
textForAgent: pendingBody,
|
|
1282
|
+
raw: message
|
|
1283
|
+
},
|
|
1284
|
+
admission: {
|
|
1285
|
+
kind: "drop",
|
|
1286
|
+
reason: "slack-no-mention",
|
|
1287
|
+
recordHistory: true
|
|
1288
|
+
},
|
|
1289
|
+
preflight: {
|
|
1290
|
+
message: pendingBody ? {
|
|
1291
|
+
rawBody: pendingBody,
|
|
1292
|
+
body: pendingBody,
|
|
1293
|
+
bodyForAgent: pendingBody,
|
|
1294
|
+
senderLabel: senderName,
|
|
1295
|
+
envelopeFrom: senderName
|
|
1296
|
+
} : void 0,
|
|
1297
|
+
history: {
|
|
1298
|
+
key: historyKey,
|
|
1299
|
+
historyMap: ctx.channelHistories,
|
|
1300
|
+
limit: ctx.historyLimit,
|
|
1301
|
+
recordOnDrop: true,
|
|
1302
|
+
mediaLimit: SLACK_HISTORY_MEDIA_MAX_ATTACHMENTS
|
|
1303
|
+
},
|
|
1304
|
+
media: () => resolveSlackHistoryMediaForPendingRecord({
|
|
1305
|
+
ctx,
|
|
1306
|
+
message,
|
|
1307
|
+
isThreadReply,
|
|
1308
|
+
threadStarter: skippedThreadStarter,
|
|
1309
|
+
isBotMessage
|
|
1310
|
+
})
|
|
1311
|
+
}
|
|
1213
1312
|
});
|
|
1214
1313
|
return null;
|
|
1215
1314
|
}
|
|
@@ -1270,6 +1369,7 @@ async function prepareSlackMessage(params) {
|
|
|
1270
1369
|
enqueueSystemEvent(`${inboundLabel}: ${preview}`, {
|
|
1271
1370
|
sessionKey,
|
|
1272
1371
|
contextKey: `slack:message:${message.channel}:${message.ts ?? "unknown"}`,
|
|
1372
|
+
forceSenderIsOwnerFalse: true,
|
|
1273
1373
|
trusted: false
|
|
1274
1374
|
});
|
|
1275
1375
|
const envelopeFrom = resolveConversationLabel$1({
|
|
@@ -1286,6 +1386,7 @@ async function prepareSlackMessage(params) {
|
|
|
1286
1386
|
storePath,
|
|
1287
1387
|
sessionKey
|
|
1288
1388
|
});
|
|
1389
|
+
const channelHistory = createChannelHistoryWindow({ historyMap: ctx.channelHistories });
|
|
1289
1390
|
const dmHistoryLimit = isDirectMessage ? resolveSlackDmHistoryLimit({
|
|
1290
1391
|
account,
|
|
1291
1392
|
userId: message.user,
|
|
@@ -1315,8 +1416,7 @@ async function prepareSlackMessage(params) {
|
|
|
1315
1416
|
inboundHistory: void 0
|
|
1316
1417
|
};
|
|
1317
1418
|
if (dmHistoryContext.body) combinedBody = `${dmHistoryContext.body}\n\n${combinedBody}`;
|
|
1318
|
-
if (isRoomish && ctx.historyLimit > 0) combinedBody =
|
|
1319
|
-
historyMap: ctx.channelHistories,
|
|
1419
|
+
if (isRoomish && ctx.historyLimit > 0) combinedBody = channelHistory.buildPendingContext({
|
|
1320
1420
|
historyKey,
|
|
1321
1421
|
limit: ctx.historyLimit,
|
|
1322
1422
|
currentMessage: combinedBody,
|
|
@@ -1353,65 +1453,98 @@ async function prepareSlackMessage(params) {
|
|
|
1353
1453
|
effectiveDirectMedia
|
|
1354
1454
|
});
|
|
1355
1455
|
const effectiveMedia = effectiveDirectMedia ?? threadStarterMedia;
|
|
1356
|
-
const
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
timestamp: entry.timestamp
|
|
1361
|
-
})) : dmHistoryContext.inboundHistory;
|
|
1456
|
+
const inboundHistory = isRoomish && ctx.historyLimit > 0 ? channelHistory.buildInboundHistory({
|
|
1457
|
+
historyKey,
|
|
1458
|
+
limit: ctx.historyLimit
|
|
1459
|
+
}) : dmHistoryContext.inboundHistory;
|
|
1362
1460
|
const commandBody = textForCommandDetection.trim();
|
|
1363
|
-
const ctxPayload =
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1461
|
+
const ctxPayload = buildChannelTurnContext({
|
|
1462
|
+
channel: "slack",
|
|
1463
|
+
provider: "slack",
|
|
1464
|
+
surface: "slack",
|
|
1465
|
+
accountId: route.accountId,
|
|
1466
|
+
messageId: message.ts,
|
|
1467
|
+
timestamp: message.ts ? Math.round(Number(message.ts) * 1e3) : void 0,
|
|
1468
|
+
from: slackFrom,
|
|
1469
|
+
sender: {
|
|
1470
|
+
id: senderId,
|
|
1471
|
+
name: senderName,
|
|
1472
|
+
displayLabel: senderName
|
|
1473
|
+
},
|
|
1474
|
+
conversation: {
|
|
1475
|
+
kind: chatType,
|
|
1476
|
+
id: message.channel,
|
|
1477
|
+
label: envelopeFrom,
|
|
1478
|
+
spaceId: ctx.teamId || void 0,
|
|
1479
|
+
threadId: threadContext.messageThreadId,
|
|
1480
|
+
nativeChannelId: message.channel,
|
|
1481
|
+
routePeer: {
|
|
1482
|
+
kind: chatType,
|
|
1483
|
+
id: message.channel
|
|
1484
|
+
}
|
|
1485
|
+
},
|
|
1486
|
+
route: {
|
|
1487
|
+
agentId: route.agentId,
|
|
1488
|
+
accountId: route.accountId,
|
|
1489
|
+
routeSessionKey: sessionKey,
|
|
1490
|
+
parentSessionKey: threadKeys.parentSessionKey
|
|
1491
|
+
},
|
|
1492
|
+
reply: {
|
|
1493
|
+
to: slackTo,
|
|
1494
|
+
originatingTo: slackTo,
|
|
1495
|
+
replyToId: threadContext.replyToId,
|
|
1496
|
+
messageThreadId: threadContext.messageThreadId,
|
|
1497
|
+
nativeChannelId: message.channel
|
|
1498
|
+
},
|
|
1499
|
+
message: {
|
|
1500
|
+
body: combinedBody,
|
|
1501
|
+
bodyForAgent: rawBody,
|
|
1502
|
+
rawBody,
|
|
1503
|
+
commandBody,
|
|
1504
|
+
envelopeFrom,
|
|
1505
|
+
inboundHistory
|
|
1506
|
+
},
|
|
1507
|
+
access: {
|
|
1508
|
+
mentions: {
|
|
1509
|
+
canDetectMention: isRoomish,
|
|
1510
|
+
wasMentioned: effectiveWasMentioned,
|
|
1511
|
+
hasAnyMention: explicitlyMentioned || mentionedSubteamIds.length > 0,
|
|
1512
|
+
implicitMentionKinds: matchedImplicitMentionKinds,
|
|
1513
|
+
requireMention: shouldRequireMention,
|
|
1514
|
+
effectiveWasMentioned
|
|
1515
|
+
},
|
|
1516
|
+
commands: {
|
|
1517
|
+
authorized: commandAuthorized,
|
|
1518
|
+
allowTextCommands,
|
|
1519
|
+
useAccessGroups: false,
|
|
1520
|
+
authorizers: []
|
|
1521
|
+
}
|
|
1522
|
+
},
|
|
1523
|
+
media: toInboundMediaFacts(effectiveMedia),
|
|
1524
|
+
supplemental: {
|
|
1525
|
+
thread: {
|
|
1526
|
+
starterBody: !threadSessionPreviousTimestamp ? threadStarterBody : void 0,
|
|
1527
|
+
historyBody: threadHistoryBody,
|
|
1528
|
+
label: threadLabel
|
|
1529
|
+
},
|
|
1530
|
+
groupSystemPrompt
|
|
1531
|
+
},
|
|
1532
|
+
extra: {
|
|
1533
|
+
GroupSubject: isRoomish ? roomLabel : void 0,
|
|
1534
|
+
UntrustedContext: untrustedChannelMetadata ? [untrustedChannelMetadata] : void 0,
|
|
1535
|
+
IsFirstThreadTurn: isThreadReply && threadTs && !threadSessionPreviousTimestamp ? true : void 0,
|
|
1536
|
+
...buildSlackMentionContextPayload({
|
|
1537
|
+
isRoomish,
|
|
1538
|
+
effectiveWasMentioned,
|
|
1539
|
+
explicitlyMentioned,
|
|
1540
|
+
mentionedUserIds,
|
|
1541
|
+
mentionedSubteamIds,
|
|
1542
|
+
matchedImplicitMentionKinds,
|
|
1543
|
+
mentionSource
|
|
1544
|
+
})
|
|
1545
|
+
}
|
|
1412
1546
|
});
|
|
1413
|
-
if (isRoomish && !shouldRequireMention)
|
|
1414
|
-
historyMap: ctx.channelHistories,
|
|
1547
|
+
if (isRoomish && !shouldRequireMention) channelHistory.record({
|
|
1415
1548
|
historyKey,
|
|
1416
1549
|
limit: ctx.historyLimit,
|
|
1417
1550
|
entry: {
|
|
@@ -1464,7 +1597,13 @@ async function prepareSlackMessage(params) {
|
|
|
1464
1597
|
sessionKey
|
|
1465
1598
|
}, "failed updating session meta");
|
|
1466
1599
|
}
|
|
1467
|
-
}
|
|
1600
|
+
},
|
|
1601
|
+
history: isRoomish && shouldRequireMention ? {
|
|
1602
|
+
isGroup: true,
|
|
1603
|
+
historyKey,
|
|
1604
|
+
historyMap: ctx.channelHistories,
|
|
1605
|
+
limit: ctx.historyLimit
|
|
1606
|
+
} : void 0
|
|
1468
1607
|
},
|
|
1469
1608
|
replyToMode,
|
|
1470
1609
|
requireMention: shouldRequireMention,
|
|
@@ -121,6 +121,7 @@ function registerSlackChannelEvents(params) {
|
|
|
121
121
|
enqueueSystemEvent(`Slack channel ${params.kind}: ${label}.`, {
|
|
122
122
|
sessionKey,
|
|
123
123
|
contextKey: `slack:channel:${params.kind}:${params.channelId ?? params.channelName ?? "unknown"}`,
|
|
124
|
+
forceSenderIsOwnerFalse: true,
|
|
124
125
|
trusted: false
|
|
125
126
|
});
|
|
126
127
|
};
|
|
@@ -700,6 +701,7 @@ function enqueueSlackBlockActionEvent(params) {
|
|
|
700
701
|
accountId: params.ctx.accountId,
|
|
701
702
|
threadId: params.parsed.threadTs
|
|
702
703
|
},
|
|
704
|
+
forceSenderIsOwnerFalse: true,
|
|
703
705
|
trusted: false
|
|
704
706
|
})) requestHeartbeat({
|
|
705
707
|
source: "hook",
|
|
@@ -845,7 +847,8 @@ function parseSlackModalPrivateMetadata(raw) {
|
|
|
845
847
|
sessionKey: normalizeOptionalString(parsed.sessionKey),
|
|
846
848
|
channelId: normalizeOptionalString(parsed.channelId),
|
|
847
849
|
channelType: normalizeOptionalString(parsed.channelType),
|
|
848
|
-
userId: normalizeOptionalString(parsed.userId)
|
|
850
|
+
userId: normalizeOptionalString(parsed.userId),
|
|
851
|
+
pluginInteractiveData: normalizeOptionalString(parsed.pluginInteractiveData)
|
|
849
852
|
};
|
|
850
853
|
} catch {
|
|
851
854
|
return {};
|
|
@@ -853,6 +856,35 @@ function parseSlackModalPrivateMetadata(raw) {
|
|
|
853
856
|
}
|
|
854
857
|
//#endregion
|
|
855
858
|
//#region extensions/slack/src/monitor/events/interactions.modal.ts
|
|
859
|
+
const OPENCLAW_MODAL_CALLBACK_PREFIX = "openclaw:";
|
|
860
|
+
function resolveSlackModalPluginInteractiveData(params) {
|
|
861
|
+
const metadataData = params.metadata.pluginInteractiveData?.trim();
|
|
862
|
+
if (metadataData) return metadataData;
|
|
863
|
+
if (!params.callbackId.startsWith(OPENCLAW_MODAL_CALLBACK_PREFIX)) return;
|
|
864
|
+
return params.callbackId.slice(9).trim() || void 0;
|
|
865
|
+
}
|
|
866
|
+
function shouldHandleSlackModalLifecycleBody(body) {
|
|
867
|
+
const typed = body;
|
|
868
|
+
if ((typed.view?.callback_id ?? "").startsWith(OPENCLAW_MODAL_CALLBACK_PREFIX)) return true;
|
|
869
|
+
const metadata = parseSlackModalPrivateMetadata(typed.view?.private_metadata);
|
|
870
|
+
return Boolean(metadata.pluginInteractiveData?.trim());
|
|
871
|
+
}
|
|
872
|
+
function resolveSlackModalPluginNamespace(data) {
|
|
873
|
+
if (!data) return;
|
|
874
|
+
const separatorIndex = data.indexOf(":");
|
|
875
|
+
return separatorIndex >= 0 ? data.slice(0, separatorIndex) : data;
|
|
876
|
+
}
|
|
877
|
+
function resolveSlackPluginSystemEventPayload(result) {
|
|
878
|
+
if (!result || typeof result !== "object") return;
|
|
879
|
+
const systemEvent = result.systemEvent;
|
|
880
|
+
if (!systemEvent || typeof systemEvent !== "object") return;
|
|
881
|
+
const typed = systemEvent;
|
|
882
|
+
const output = {};
|
|
883
|
+
if (typeof typed.summary === "string" && typed.summary.trim()) output.summary = typed.summary;
|
|
884
|
+
if (typeof typed.reference === "string" && typed.reference.trim()) output.reference = typed.reference;
|
|
885
|
+
if (typed.data && typeof typed.data === "object" && !Array.isArray(typed.data)) output.data = typed.data;
|
|
886
|
+
return Object.keys(output).length > 0 ? output : void 0;
|
|
887
|
+
}
|
|
856
888
|
function resolveModalSessionRouting(params) {
|
|
857
889
|
const metadata = params.metadata;
|
|
858
890
|
if (metadata.sessionKey) return {
|
|
@@ -899,6 +931,7 @@ function resolveSlackModalEventBase(params) {
|
|
|
899
931
|
expectedUserId: metadata.userId,
|
|
900
932
|
viewId,
|
|
901
933
|
sessionRouting,
|
|
934
|
+
stateValues: params.body.view?.state?.values,
|
|
902
935
|
payload: {
|
|
903
936
|
actionId: `view:${callbackId}`,
|
|
904
937
|
callbackId,
|
|
@@ -918,12 +951,68 @@ function resolveSlackModalEventBase(params) {
|
|
|
918
951
|
}
|
|
919
952
|
};
|
|
920
953
|
}
|
|
954
|
+
async function dispatchSlackModalPluginInteractiveHandler(params) {
|
|
955
|
+
if (!params.data) return {
|
|
956
|
+
matched: false,
|
|
957
|
+
handled: false,
|
|
958
|
+
duplicate: false
|
|
959
|
+
};
|
|
960
|
+
const isViewClosed = params.interactionType === "view_closed";
|
|
961
|
+
const interactionId = [
|
|
962
|
+
params.interactionType,
|
|
963
|
+
params.payload.callbackId,
|
|
964
|
+
params.payload.viewId,
|
|
965
|
+
params.payload.userId
|
|
966
|
+
].filter(Boolean).join(":");
|
|
967
|
+
const result = await dispatchSlackPluginInteractiveHandler({
|
|
968
|
+
data: params.data,
|
|
969
|
+
interactionId,
|
|
970
|
+
ctx: {
|
|
971
|
+
accountId: params.ctx.accountId,
|
|
972
|
+
interactionId,
|
|
973
|
+
conversationId: params.sessionRouting.channelId ?? "",
|
|
974
|
+
parentConversationId: void 0,
|
|
975
|
+
threadId: void 0,
|
|
976
|
+
senderId: params.payload.userId,
|
|
977
|
+
senderUsername: void 0,
|
|
978
|
+
auth: params.auth,
|
|
979
|
+
interaction: {
|
|
980
|
+
kind: params.interactionType,
|
|
981
|
+
callbackId: params.payload.callbackId,
|
|
982
|
+
viewId: params.payload.viewId,
|
|
983
|
+
rootViewId: params.payload.rootViewId,
|
|
984
|
+
previousViewId: params.payload.previousViewId,
|
|
985
|
+
externalId: params.payload.externalId,
|
|
986
|
+
isStackedView: params.payload.isStackedView,
|
|
987
|
+
isCleared: isViewClosed ? params.body.is_cleared === true : void 0,
|
|
988
|
+
inputs: params.payload.inputs,
|
|
989
|
+
stateValues: params.stateValues,
|
|
990
|
+
triggerId: params.body.trigger_id
|
|
991
|
+
}
|
|
992
|
+
},
|
|
993
|
+
respond: {
|
|
994
|
+
acknowledge: async () => {},
|
|
995
|
+
reply: async () => {},
|
|
996
|
+
followUp: async () => {},
|
|
997
|
+
editMessage: async () => {}
|
|
998
|
+
}
|
|
999
|
+
});
|
|
1000
|
+
return {
|
|
1001
|
+
...result,
|
|
1002
|
+
namespace: result.matched ? resolveSlackModalPluginNamespace(params.data) : void 0,
|
|
1003
|
+
systemEvent: result.matched ? resolveSlackPluginSystemEventPayload(result.result) : void 0
|
|
1004
|
+
};
|
|
1005
|
+
}
|
|
921
1006
|
async function emitSlackModalLifecycleEvent(params) {
|
|
922
|
-
const { callbackId, userId, expectedUserId, viewId, sessionRouting, payload } = resolveSlackModalEventBase({
|
|
1007
|
+
const { callbackId, userId, expectedUserId, viewId, sessionRouting, stateValues, payload } = resolveSlackModalEventBase({
|
|
923
1008
|
ctx: params.ctx,
|
|
924
1009
|
body: params.body,
|
|
925
1010
|
summarizeViewState: params.summarizeViewState
|
|
926
1011
|
});
|
|
1012
|
+
const pluginInteractiveData = resolveSlackModalPluginInteractiveData({
|
|
1013
|
+
callbackId,
|
|
1014
|
+
metadata: parseSlackModalPrivateMetadata(params.body.view?.private_metadata)
|
|
1015
|
+
});
|
|
927
1016
|
const isViewClosed = params.interactionType === "view_closed";
|
|
928
1017
|
const isCleared = params.body.is_cleared === true;
|
|
929
1018
|
const eventPayload = isViewClosed ? {
|
|
@@ -937,6 +1026,20 @@ async function emitSlackModalLifecycleEvent(params) {
|
|
|
937
1026
|
if (isViewClosed) params.ctx.runtime.log?.(`slack:interaction view_closed callback=${callbackId} user=${userId} cleared=${isCleared}`);
|
|
938
1027
|
else params.ctx.runtime.log?.(`slack:interaction view_submission callback=${callbackId} user=${userId} inputs=${payload.inputs.length}`);
|
|
939
1028
|
if (!expectedUserId) {
|
|
1029
|
+
if (pluginInteractiveData) try {
|
|
1030
|
+
await dispatchSlackModalPluginInteractiveHandler({
|
|
1031
|
+
ctx: params.ctx,
|
|
1032
|
+
body: params.body,
|
|
1033
|
+
interactionType: params.interactionType,
|
|
1034
|
+
data: pluginInteractiveData,
|
|
1035
|
+
auth: { isAuthorizedSender: false },
|
|
1036
|
+
payload,
|
|
1037
|
+
stateValues,
|
|
1038
|
+
sessionRouting
|
|
1039
|
+
});
|
|
1040
|
+
} catch (error) {
|
|
1041
|
+
params.ctx.runtime.log?.(`slack:interaction modal plugin dispatch failed callback=${callbackId} error=${error instanceof Error ? error.message : String(error)}`);
|
|
1042
|
+
}
|
|
940
1043
|
params.ctx.runtime.log?.(`slack:interaction drop modal callback=${callbackId} user=${userId} reason=missing-expected-user`);
|
|
941
1044
|
return;
|
|
942
1045
|
}
|
|
@@ -952,7 +1055,31 @@ async function emitSlackModalLifecycleEvent(params) {
|
|
|
952
1055
|
params.ctx.runtime.log?.(`slack:interaction drop modal callback=${callbackId} user=${userId} reason=${auth.reason ?? "unauthorized"}`);
|
|
953
1056
|
return;
|
|
954
1057
|
}
|
|
955
|
-
|
|
1058
|
+
let pluginDispatch;
|
|
1059
|
+
try {
|
|
1060
|
+
pluginDispatch = await dispatchSlackModalPluginInteractiveHandler({
|
|
1061
|
+
ctx: params.ctx,
|
|
1062
|
+
body: params.body,
|
|
1063
|
+
interactionType: params.interactionType,
|
|
1064
|
+
data: pluginInteractiveData,
|
|
1065
|
+
auth: { isAuthorizedSender: auth.allowed },
|
|
1066
|
+
payload,
|
|
1067
|
+
stateValues,
|
|
1068
|
+
sessionRouting
|
|
1069
|
+
});
|
|
1070
|
+
} catch (error) {
|
|
1071
|
+
params.ctx.runtime.log?.(`slack:interaction modal plugin dispatch failed callback=${callbackId} error=${error instanceof Error ? error.message : String(error)}`);
|
|
1072
|
+
}
|
|
1073
|
+
const pluginEventFields = pluginDispatch?.matched === true ? {
|
|
1074
|
+
pluginHandled: pluginDispatch.handled,
|
|
1075
|
+
pluginNamespace: pluginDispatch.namespace,
|
|
1076
|
+
pluginDuplicate: pluginDispatch.duplicate || void 0,
|
|
1077
|
+
pluginSystemEvent: pluginDispatch.systemEvent
|
|
1078
|
+
} : {};
|
|
1079
|
+
enqueueSystemEvent(params.formatSystemEvent({
|
|
1080
|
+
...eventPayload,
|
|
1081
|
+
...pluginEventFields
|
|
1082
|
+
}), {
|
|
956
1083
|
sessionKey: sessionRouting.sessionKey,
|
|
957
1084
|
contextKey: [
|
|
958
1085
|
params.contextPrefix,
|
|
@@ -964,6 +1091,7 @@ async function emitSlackModalLifecycleEvent(params) {
|
|
|
964
1091
|
}
|
|
965
1092
|
function registerModalLifecycleHandler(params) {
|
|
966
1093
|
params.register(params.matcher, async ({ ack, body }) => {
|
|
1094
|
+
if (!shouldHandleSlackModalLifecycleBody(body)) return;
|
|
967
1095
|
await ack();
|
|
968
1096
|
if (params.ctx.shouldDropMismatchedSlackEvent?.(body)) {
|
|
969
1097
|
params.ctx.runtime.log?.(`slack:interaction drop ${params.interactionType} payload (mismatched app/team)`);
|
|
@@ -982,7 +1110,6 @@ function registerModalLifecycleHandler(params) {
|
|
|
982
1110
|
}
|
|
983
1111
|
//#endregion
|
|
984
1112
|
//#region extensions/slack/src/monitor/events/interactions.ts
|
|
985
|
-
const OPENCLAW_ACTION_PREFIX = "openclaw:";
|
|
986
1113
|
const SLACK_INTERACTION_EVENT_PREFIX = "Slack interaction: ";
|
|
987
1114
|
const REDACTED_INTERACTION_VALUE = "[redacted]";
|
|
988
1115
|
const SLACK_INTERACTION_EVENT_MAX_CHARS = 2400;
|
|
@@ -1058,6 +1185,10 @@ function buildCompactSlackInteractionPayload(payload) {
|
|
|
1058
1185
|
selectedDateTime: payload.selectedDateTime,
|
|
1059
1186
|
workflowId: payload.workflowId,
|
|
1060
1187
|
routedChannelType: payload.routedChannelType,
|
|
1188
|
+
pluginHandled: payload.pluginHandled,
|
|
1189
|
+
pluginNamespace: payload.pluginNamespace,
|
|
1190
|
+
pluginDuplicate: payload.pluginDuplicate,
|
|
1191
|
+
pluginSystemEvent: payload.pluginSystemEvent,
|
|
1061
1192
|
inputs: compactInputs.length > 0 ? compactInputs : void 0,
|
|
1062
1193
|
inputsOmitted: rawInputs.length > SLACK_INTERACTION_COMPACT_INPUTS_MAX_ITEMS ? rawInputs.length - SLACK_INTERACTION_COMPACT_INPUTS_MAX_ITEMS : void 0,
|
|
1063
1194
|
payloadTruncated: true
|
|
@@ -1103,7 +1234,7 @@ function registerSlackInteractionEvents(params) {
|
|
|
1103
1234
|
formatSystemEvent: formatSlackInteractionSystemEvent
|
|
1104
1235
|
});
|
|
1105
1236
|
if (typeof ctx.app.view !== "function") return;
|
|
1106
|
-
const modalMatcher =
|
|
1237
|
+
const modalMatcher = /.*/;
|
|
1107
1238
|
registerModalLifecycleHandler({
|
|
1108
1239
|
register: (matcher, handler) => ctx.app.view(matcher, handler),
|
|
1109
1240
|
matcher: modalMatcher,
|
|
@@ -1464,6 +1595,7 @@ function registerSlackReactionEvents(params) {
|
|
|
1464
1595
|
enqueueSystemEvent(authorLabel ? `${baseText} from ${authorLabel}` : baseText, {
|
|
1465
1596
|
sessionKey: ingressContext.sessionKey,
|
|
1466
1597
|
contextKey: `slack:reaction:${action}:${item.channel}:${item.ts}:${event.user}:${emojiLabel}`,
|
|
1598
|
+
forceSenderIsOwnerFalse: true,
|
|
1467
1599
|
trusted: false
|
|
1468
1600
|
});
|
|
1469
1601
|
} catch (err) {
|
|
@@ -1629,7 +1761,7 @@ function createSlackThreadTsResolver(params) {
|
|
|
1629
1761
|
//#region extensions/slack/src/monitor/message-handler.ts
|
|
1630
1762
|
let slackMessagePipelinePromise;
|
|
1631
1763
|
function loadSlackMessagePipeline() {
|
|
1632
|
-
slackMessagePipelinePromise ??= import("./pipeline.runtime-
|
|
1764
|
+
slackMessagePipelinePromise ??= import("./pipeline.runtime-CakcaQh9.js");
|
|
1633
1765
|
return slackMessagePipelinePromise;
|
|
1634
1766
|
}
|
|
1635
1767
|
const APP_MENTION_RETRY_TTL_MS = 6e4;
|
|
@@ -2171,7 +2303,7 @@ function loadSlashCommandsRuntime() {
|
|
|
2171
2303
|
return slashCommandsRuntimePromise;
|
|
2172
2304
|
}
|
|
2173
2305
|
function loadSlashDispatchRuntime() {
|
|
2174
|
-
slashDispatchRuntimePromise ??= import("./slash-dispatch.runtime-
|
|
2306
|
+
slashDispatchRuntimePromise ??= import("./slash-dispatch.runtime-Cg7uU92H.js");
|
|
2175
2307
|
return slashDispatchRuntimePromise;
|
|
2176
2308
|
}
|
|
2177
2309
|
function loadSlackPluginCommandsRuntime() {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as resolveSlackReplyBlocks } from "./reply-blocks-BFaJ_ejG.js";
|
|
2
2
|
import { o as SLACK_TEXT_LIMIT } from "./thread-ts-As_dcNbD.js";
|
|
3
|
-
import { o as markdownToSlackMrkdwnChunks, t as sendMessageSlack } from "./send-
|
|
4
|
-
import "./send.runtime-
|
|
3
|
+
import { o as markdownToSlackMrkdwnChunks, t as sendMessageSlack } from "./send-CxXFbqN1.js";
|
|
4
|
+
import "./send.runtime-BHCPpSj_.js";
|
|
5
5
|
import { createReplyReferencePlanner } from "openclaw/plugin-sdk/reply-reference";
|
|
6
6
|
import { SILENT_REPLY_TOKEN, chunkMarkdownTextWithMode, isSilentReplyText } from "openclaw/plugin-sdk/reply-chunking";
|
|
7
7
|
import { deliverTextOrMediaReply, resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
|