@openclaw/slack 2026.5.16-beta.2 → 2026.5.16-beta.4
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-p39JLqwf.js → action-runtime-0RLkDKyA.js} +1 -1
- package/dist/action-runtime.runtime-DpzOXqtk.js +2 -0
- package/dist/{actions-BCRbHv1Q.js → actions-Chs6DbrP.js} +1 -1
- package/dist/{actions.runtime-CpywQR3D.js → actions.runtime-BsbIDsmT.js} +1 -1
- package/dist/api.js +5 -5
- package/dist/{approval-handler.runtime-DXrdRbkT.js → approval-handler.runtime-BmCbRrbT.js} +1 -1
- package/dist/{channel-CVSopl66.js → channel-DUS8ZO45.js} +16 -12
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.setup-DknBgufI.js → channel.setup-qGOC05UK.js} +2 -2
- package/dist/inbound-contract-test-api.js +2 -2
- package/dist/{monitor-CdVxsuHi.js → monitor-BhEzWuv0.js} +3 -3
- package/dist/{outbound-adapter-CHm6e-0Q.js → outbound-adapter-BoDXPksS.js} +1 -1
- package/dist/outbound-payload-test-api.js +1 -1
- package/dist/{outbound-payload.test-harness-C0CW7_CE.js → outbound-payload.test-harness-C7Izm95Q.js} +1 -1
- package/dist/{pipeline.runtime-CakcaQh9.js → pipeline.runtime-Bq754VH8.js} +41 -26
- package/dist/{prepare-DSRUr44d.js → prepare-BcznR9ok.js} +136 -24
- package/dist/{prepare.test-helpers-CU1qB54Q.js → prepare.test-helpers-D807wdul.js} +1 -1
- package/dist/{provider-bKg1hkf5.js → provider-BFnE2bgI.js} +118 -4
- package/dist/{replies-Fg1T3ZzU.js → replies-2ve_YcHy.js} +8 -5
- package/dist/{room-context-Cd8jFpS-.js → room-context-BI26wVBb.js} +83 -2
- package/dist/runtime-api.js +5 -5
- package/dist/{send-CxXFbqN1.js → send-C5PzphgC.js} +5 -0
- package/dist/send.runtime-Bgf0P22e.js +2 -0
- package/dist/send.runtime-DsEXD6MR.js +2 -0
- package/dist/{setup-core-B7pou7oe.js → setup-core-az0LCrNr.js} +21 -2
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-D6LLzeRz.js → setup-surface-Cdq_mfjx.js} +2 -2
- package/dist/{shared-7Vi9j4aV.js → shared-BuNoOmas.js} +6 -2
- package/dist/{slash-dispatch.runtime-Cg7uU92H.js → slash-dispatch.runtime-CcbE1HtP.js} +1 -1
- package/dist/test-api.js +6 -6
- package/package.json +4 -4
- package/dist/action-runtime.runtime-BzrPV3EA.js +0 -2
- package/dist/send.runtime-BHCPpSj_.js +0 -2
- package/dist/send.runtime-CDG5AgU3.js +0 -2
|
@@ -2,11 +2,11 @@ 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-C5PzphgC.js";
|
|
6
|
+
import { _ as resolveSlackThreadStarter, g as resolveSlackThreadHistory, l as reactSlackMessage, y as formatSlackFileReference } from "./actions-Chs6DbrP.js";
|
|
7
7
|
import { t as formatSlackError } from "./errors-C_sW0Zgl.js";
|
|
8
|
-
import {
|
|
9
|
-
import "./send.runtime-
|
|
8
|
+
import { C as resolveChannelContextVisibilityMode, E as resolveStorePath, S as readSessionUpdatedAt, _ as resolveSlackChatType, c as authorizeSlackBotRoomMessage, d as resolveSlackEffectiveAllowFrom, f as buildSlackAssistantThreadMetadata, g as normalizeSlackChannelType, j as stripSlackMentionsForCommandDetection, m as parseSlackAssistantThreadMetadata, n as authorizeSlackDirectMessage, o as resolveConversationLabel$1, t as resolveSlackRoomContextHints, u as resolveSlackCommandIngress, v as resolveSlackChannelConfig } from "./room-context-BI26wVBb.js";
|
|
9
|
+
import "./send.runtime-DsEXD6MR.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";
|
|
@@ -15,10 +15,11 @@ import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
|
15
15
|
import { ensureConfiguredBindingRouteReady, resolveConfiguredBindingRoute, resolveRuntimeConversationBindingRoute } from "openclaw/plugin-sdk/conversation-runtime";
|
|
16
16
|
import { createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
|
|
17
17
|
import { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
|
|
18
|
-
import {
|
|
18
|
+
import { buildChannelInboundEventContext, buildMentionRegexes, classifyChannelInboundEvent, formatInboundEnvelope, implicitMentionKindWhen, logInboundDrop, matchesMentionWithExplicit, resolveEnvelopeFormatOptions, resolveUnmentionedGroupInboundPolicy, 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
|
+
import { isAbortRequestText } from "openclaw/plugin-sdk/command-primitives-runtime";
|
|
22
23
|
import { shouldHandleTextCommands } from "openclaw/plugin-sdk/command-surface";
|
|
23
24
|
import { recordDroppedChannelTurnHistory } from "openclaw/plugin-sdk/inbound-reply-dispatch";
|
|
24
25
|
import { mimeTypeFromFilePath } from "openclaw/plugin-sdk/media-mime";
|
|
@@ -29,7 +30,7 @@ const SLACK_MENTION_RESOLUTION_MAX_LOOKUPS_PER_MESSAGE = 20;
|
|
|
29
30
|
const SLACK_USER_MENTION_RE$1 = /<@([A-Z0-9]+)(?:\|[^>]+)?>/gi;
|
|
30
31
|
let slackMediaModulePromise$1;
|
|
31
32
|
function loadSlackMediaModule$1() {
|
|
32
|
-
slackMediaModulePromise$1 ??= import("./actions-
|
|
33
|
+
slackMediaModulePromise$1 ??= import("./actions-Chs6DbrP.js").then((n) => n.h);
|
|
33
34
|
return slackMediaModulePromise$1;
|
|
34
35
|
}
|
|
35
36
|
function collectUniqueSlackMentionIds$1(texts) {
|
|
@@ -442,7 +443,7 @@ function resolveSlackInitialAgentRoute(params) {
|
|
|
442
443
|
});
|
|
443
444
|
}
|
|
444
445
|
function resolveSlackRoutingContext(params) {
|
|
445
|
-
const { ctx, account, message, isDirectMessage, isGroupDm, isRoom, isRoomish, seedTopLevelRoomThread } = params;
|
|
446
|
+
const { ctx, account, message, isDirectMessage, isGroupDm, isRoom, isRoomish, seedTopLevelRoomThread, assistantThreadTs } = params;
|
|
446
447
|
let route = resolveSlackInitialAgentRoute({
|
|
447
448
|
ctx,
|
|
448
449
|
account,
|
|
@@ -460,17 +461,18 @@ function resolveSlackRoutingContext(params) {
|
|
|
460
461
|
const isThreadReply = threadContext.isThreadReply;
|
|
461
462
|
const autoThreadId = !isThreadReply && replyToMode === "all" && threadContext.messageTs ? threadContext.messageTs : void 0;
|
|
462
463
|
const seedCandidateThreadId = threadContext.incomingThreadTs ?? threadContext.messageTs;
|
|
463
|
-
const routedThreadId = (isDirectMessage ?
|
|
464
|
+
const routedThreadId = (isDirectMessage ? assistantThreadTs : isRoomish ? isThreadReply && threadTs ? threadTs : void 0 : isThreadReply ? threadTs : autoThreadId) ?? (isRoomish ? !isThreadReply && isRoom && seedTopLevelRoomThread && replyToMode !== "off" && seedCandidateThreadId ? seedCandidateThreadId : void 0 : void 0);
|
|
464
465
|
const baseConversationId = resolveSlackBaseConversationId({
|
|
465
466
|
message,
|
|
466
467
|
isDirectMessage
|
|
467
468
|
});
|
|
468
|
-
const
|
|
469
|
+
const runtimeBindingThreadId = routedThreadId ?? (isDirectMessage && isThreadReply ? threadTs : void 0);
|
|
470
|
+
const boundThreadRoute = runtimeBindingThreadId ? resolveRuntimeConversationBindingRoute({
|
|
469
471
|
route,
|
|
470
472
|
conversation: {
|
|
471
473
|
channel: "slack",
|
|
472
474
|
accountId: account.accountId,
|
|
473
|
-
conversationId:
|
|
475
|
+
conversationId: runtimeBindingThreadId,
|
|
474
476
|
parentConversationId: baseConversationId
|
|
475
477
|
}
|
|
476
478
|
}) : null;
|
|
@@ -576,7 +578,7 @@ function formatSlackBotStarterThreadLabel(params) {
|
|
|
576
578
|
//#region extensions/slack/src/monitor/message-handler/prepare-thread-context.ts
|
|
577
579
|
let slackMediaModulePromise;
|
|
578
580
|
function loadSlackMediaModule() {
|
|
579
|
-
slackMediaModulePromise ??= import("./actions-
|
|
581
|
+
slackMediaModulePromise ??= import("./actions-Chs6DbrP.js").then((n) => n.h);
|
|
580
582
|
return slackMediaModulePromise;
|
|
581
583
|
}
|
|
582
584
|
const SLACK_THREAD_CONTEXT_USER_LOOKUP_CONCURRENCY = 4;
|
|
@@ -686,7 +688,7 @@ async function resolveSlackThreadContextData(params) {
|
|
|
686
688
|
logVerbose("slack: retained current-bot thread starter as assistant root context");
|
|
687
689
|
}
|
|
688
690
|
const threadInitialHistoryLimit = params.account.config?.thread?.initialHistoryLimit ?? 20;
|
|
689
|
-
if (threadInitialHistoryLimit > 0 && !threadSessionPreviousTimestamp) {
|
|
691
|
+
if (threadInitialHistoryLimit > 0 && (!threadSessionPreviousTimestamp || params.forceInitialHistory)) {
|
|
690
692
|
const currentBotRootTs = starter?.ts ?? params.threadTs;
|
|
691
693
|
const threadHistoryWithBotRoot = ensureSlackThreadHistoryHasBotRoot({
|
|
692
694
|
history: await resolveSlackThreadHistory({
|
|
@@ -848,6 +850,76 @@ const SLACK_HISTORY_MEDIA_MAX_ATTACHMENTS = 4;
|
|
|
848
850
|
const SLACK_HISTORY_MEDIA_MAX_BYTES = 10 * 1024 * 1024;
|
|
849
851
|
const SLACK_HISTORY_MEDIA_IDLE_TIMEOUT_MS = 1e3;
|
|
850
852
|
const SLACK_HISTORY_MEDIA_TOTAL_TIMEOUT_MS = 3e3;
|
|
853
|
+
function asRecord(value) {
|
|
854
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
855
|
+
}
|
|
856
|
+
function recordString(record, key) {
|
|
857
|
+
return normalizeOptionalString(record?.[key]);
|
|
858
|
+
}
|
|
859
|
+
function recordNullableString(record, key) {
|
|
860
|
+
if (!record || !(key in record)) return;
|
|
861
|
+
if (record[key] === null) return null;
|
|
862
|
+
return normalizeOptionalString(record[key]);
|
|
863
|
+
}
|
|
864
|
+
function mergeSlackAssistantThreadContext(primary, fallback) {
|
|
865
|
+
if (!primary) return fallback;
|
|
866
|
+
if (!fallback) return primary;
|
|
867
|
+
return {
|
|
868
|
+
assistantChannelId: primary.assistantChannelId || fallback.assistantChannelId,
|
|
869
|
+
threadTs: primary.threadTs || fallback.threadTs,
|
|
870
|
+
userId: primary.userId ?? fallback.userId,
|
|
871
|
+
channelId: primary.channelId ?? fallback.channelId,
|
|
872
|
+
teamId: primary.teamId ?? fallback.teamId,
|
|
873
|
+
enterpriseId: primary.enterpriseId !== void 0 ? primary.enterpriseId : fallback.enterpriseId
|
|
874
|
+
};
|
|
875
|
+
}
|
|
876
|
+
function hasSlackAssistantThreadMetadata(context) {
|
|
877
|
+
return Boolean(context?.channelId || context?.teamId || context?.enterpriseId !== void 0);
|
|
878
|
+
}
|
|
879
|
+
function resolveSlackMessageAssistantThreadContext(message) {
|
|
880
|
+
const thread = asRecord(message.assistant_thread);
|
|
881
|
+
if (!thread) return;
|
|
882
|
+
const context = asRecord(thread.context);
|
|
883
|
+
const assistantChannelId = recordString(thread, "channel_id") ?? message.channel;
|
|
884
|
+
const threadTs = recordString(thread, "thread_ts") ?? message.thread_ts ?? message.ts;
|
|
885
|
+
if (!assistantChannelId || !threadTs) return;
|
|
886
|
+
return {
|
|
887
|
+
assistantChannelId,
|
|
888
|
+
threadTs,
|
|
889
|
+
userId: recordString(thread, "user_id") ?? message.user,
|
|
890
|
+
channelId: recordString(context, "channel_id"),
|
|
891
|
+
teamId: recordString(context, "team_id"),
|
|
892
|
+
enterpriseId: recordNullableString(context, "enterprise_id")
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
async function restoreSlackAssistantThreadContextFromMetadata(params) {
|
|
896
|
+
const threadTs = params.message.thread_ts;
|
|
897
|
+
const parentUserId = params.message.parent_user_id?.trim();
|
|
898
|
+
if (!params.message.channel || !threadTs || !parentUserId || parentUserId !== params.ctx.botUserId && parentUserId !== params.ctx.botId) return;
|
|
899
|
+
try {
|
|
900
|
+
const response = await params.ctx.app.client.conversations.replies({
|
|
901
|
+
channel: params.message.channel,
|
|
902
|
+
ts: threadTs,
|
|
903
|
+
oldest: threadTs,
|
|
904
|
+
include_all_metadata: true,
|
|
905
|
+
limit: 4
|
|
906
|
+
});
|
|
907
|
+
for (const message of response.messages ?? []) {
|
|
908
|
+
const context = parseSlackAssistantThreadMetadata(message.metadata);
|
|
909
|
+
if (!context) continue;
|
|
910
|
+
return {
|
|
911
|
+
assistantChannelId: params.message.channel,
|
|
912
|
+
threadTs,
|
|
913
|
+
userId: params.message.user,
|
|
914
|
+
channelId: context.channelId,
|
|
915
|
+
teamId: context.teamId,
|
|
916
|
+
enterpriseId: context.enterpriseId
|
|
917
|
+
};
|
|
918
|
+
}
|
|
919
|
+
} catch (err) {
|
|
920
|
+
logVerbose(`slack assistant context restore failed channel=${params.message.channel} ts=${threadTs}: ${formatErrorMessage(err)}`);
|
|
921
|
+
}
|
|
922
|
+
}
|
|
851
923
|
function resolveCachedMentionRegexes(ctx, agentId) {
|
|
852
924
|
const key = normalizeOptionalString(agentId) ?? "__default__";
|
|
853
925
|
let byAgent = mentionRegexCache.get(ctx);
|
|
@@ -1092,7 +1164,19 @@ async function prepareSlackMessage(params) {
|
|
|
1092
1164
|
source: opts.source
|
|
1093
1165
|
});
|
|
1094
1166
|
const channelRequireMention = channelConfig?.requireMention ?? ctx.defaultRequireMention ?? true;
|
|
1095
|
-
const
|
|
1167
|
+
const channelChatType = isDirectMessage ? "direct" : isGroupDm ? "group" : "channel";
|
|
1168
|
+
const messageAssistantThreadContext = resolveSlackMessageAssistantThreadContext(message);
|
|
1169
|
+
const assistantContextLookupChannelId = messageAssistantThreadContext?.assistantChannelId ?? message.channel;
|
|
1170
|
+
const assistantContextLookupThreadTs = messageAssistantThreadContext?.threadTs ?? message.thread_ts ?? message.ts;
|
|
1171
|
+
const cachedAssistantThreadContext = isDirectMessage ? ctx.getSlackAssistantThreadContext(assistantContextLookupChannelId, assistantContextLookupThreadTs) : void 0;
|
|
1172
|
+
const restoredAssistantThreadContext = isDirectMessage && !cachedAssistantThreadContext && !hasSlackAssistantThreadMetadata(messageAssistantThreadContext) ? await restoreSlackAssistantThreadContextFromMetadata({
|
|
1173
|
+
ctx,
|
|
1174
|
+
message
|
|
1175
|
+
}) : void 0;
|
|
1176
|
+
const assistantThreadContext = mergeSlackAssistantThreadContext(messageAssistantThreadContext, cachedAssistantThreadContext ?? restoredAssistantThreadContext);
|
|
1177
|
+
const assistantThreadContextToCache = messageAssistantThreadContext || restoredAssistantThreadContext ? assistantThreadContext : void 0;
|
|
1178
|
+
if (assistantThreadContextToCache) ctx.saveSlackAssistantThreadContext(assistantThreadContextToCache);
|
|
1179
|
+
const willImplicitlyThreadReply = isRoom && !channelRequireMention && resolveSlackReplyToMode(account, channelChatType) !== "off";
|
|
1096
1180
|
const seedTopLevelRoomThreadBySource = opts.source === "app_mention" || opts.wasMentioned === true || explicitlyMentioned || willImplicitlyThreadReply;
|
|
1097
1181
|
let routing = resolveSlackRoutingContext({
|
|
1098
1182
|
ctx,
|
|
@@ -1102,7 +1186,8 @@ async function prepareSlackMessage(params) {
|
|
|
1102
1186
|
isGroupDm,
|
|
1103
1187
|
isRoom,
|
|
1104
1188
|
isRoomish,
|
|
1105
|
-
seedTopLevelRoomThread: seedTopLevelRoomThreadBySource
|
|
1189
|
+
seedTopLevelRoomThread: seedTopLevelRoomThreadBySource,
|
|
1190
|
+
assistantThreadTs: assistantThreadContext?.threadTs
|
|
1106
1191
|
});
|
|
1107
1192
|
const resolveWasMentioned = (mentionRegexes) => opts.wasMentioned ?? (!isDirectMessage && matchesMentionWithExplicit({
|
|
1108
1193
|
text: messageText,
|
|
@@ -1125,7 +1210,8 @@ async function prepareSlackMessage(params) {
|
|
|
1125
1210
|
isGroupDm,
|
|
1126
1211
|
isRoom,
|
|
1127
1212
|
isRoomish,
|
|
1128
|
-
seedTopLevelRoomThread: true
|
|
1213
|
+
seedTopLevelRoomThread: true,
|
|
1214
|
+
assistantThreadTs: assistantThreadContext?.threadTs
|
|
1129
1215
|
});
|
|
1130
1216
|
mentionRegexes = resolveCachedMentionRegexes(ctx, routing.route.agentId);
|
|
1131
1217
|
wasMentioned = resolveWasMentioned(mentionRegexes);
|
|
@@ -1150,6 +1236,7 @@ async function prepareSlackMessage(params) {
|
|
|
1150
1236
|
return null;
|
|
1151
1237
|
}
|
|
1152
1238
|
}
|
|
1239
|
+
const directThreadRoutedToDmSession = !assistantThreadContext && isDirectMessage && isThreadReply && threadTs && runtimeBinding?.conversation.conversationId !== threadTs;
|
|
1153
1240
|
let implicitMentionKinds = [];
|
|
1154
1241
|
if (!isDirectMessage && ctx.botUserId && message.thread_ts && !ctx.threadRequireExplicitMention && !wasMentioned) {
|
|
1155
1242
|
const replyToBotKinds = implicitMentionKindWhen("reply_to_bot", message.parent_user_id === ctx.botUserId);
|
|
@@ -1189,6 +1276,7 @@ async function prepareSlackMessage(params) {
|
|
|
1189
1276
|
const canDetectMention = Boolean(ctx.botUserId) || mentionRegexes.length > 0;
|
|
1190
1277
|
const textForCommandDetection = stripSlackMentionsForCommandDetection(message.text ?? "");
|
|
1191
1278
|
const hasControlCommandInMessage = hasControlCommand(textForCommandDetection, cfg);
|
|
1279
|
+
const hasAbortRequest = isAbortRequestText(textForCommandDetection);
|
|
1192
1280
|
const channelUsersAllowlistConfigured = isRoom && Array.isArray(channelConfig?.users) && channelConfig.users.length > 0;
|
|
1193
1281
|
const messageIngress = await resolveSlackCommandIngress({
|
|
1194
1282
|
ctx,
|
|
@@ -1330,6 +1418,16 @@ async function prepareSlackMessage(params) {
|
|
|
1330
1418
|
if (!resolvedMessageContent) return null;
|
|
1331
1419
|
const { rawBody, effectiveDirectMedia } = resolvedMessageContent;
|
|
1332
1420
|
const chatType = resolveSlackChatType(conversation.resolvedChannelType);
|
|
1421
|
+
const inboundEventKind = classifyChannelInboundEvent({
|
|
1422
|
+
conversation: { kind: chatType },
|
|
1423
|
+
unmentionedGroupPolicy: resolveUnmentionedGroupInboundPolicy({
|
|
1424
|
+
cfg,
|
|
1425
|
+
agentId: route.agentId
|
|
1426
|
+
}),
|
|
1427
|
+
wasMentioned: effectiveWasMentioned,
|
|
1428
|
+
hasControlCommand: hasControlCommandInMessage,
|
|
1429
|
+
hasAbortRequest
|
|
1430
|
+
});
|
|
1333
1431
|
const ackReaction = resolveAckReaction(cfg, route.agentId, {
|
|
1334
1432
|
channel: "slack",
|
|
1335
1433
|
accountId: account.accountId
|
|
@@ -1337,7 +1435,10 @@ async function prepareSlackMessage(params) {
|
|
|
1337
1435
|
const ackReactionValue = ackReaction ?? "";
|
|
1338
1436
|
const sourceRepliesAreToolOnly = resolveChannelMessageSourceReplyDeliveryMode({
|
|
1339
1437
|
cfg,
|
|
1340
|
-
ctx: {
|
|
1438
|
+
ctx: {
|
|
1439
|
+
ChatType: chatType,
|
|
1440
|
+
InboundEventKind: inboundEventKind
|
|
1441
|
+
}
|
|
1341
1442
|
}) === "message_tool_only";
|
|
1342
1443
|
const statusReactionsExplicitlyEnabled = cfg.messages?.statusReactions?.enabled === true;
|
|
1343
1444
|
const shouldAckReaction$1 = () => Boolean(ackReaction && shouldAckReaction({
|
|
@@ -1446,6 +1547,7 @@ async function prepareSlackMessage(params) {
|
|
|
1446
1547
|
roomLabel,
|
|
1447
1548
|
storePath,
|
|
1448
1549
|
sessionKey,
|
|
1550
|
+
forceInitialHistory: Boolean(directThreadRoutedToDmSession),
|
|
1449
1551
|
allowFromLower: threadContextAllowFromLower,
|
|
1450
1552
|
allowNameMatching: ctx.allowNameMatching,
|
|
1451
1553
|
contextVisibilityMode,
|
|
@@ -1458,7 +1560,9 @@ async function prepareSlackMessage(params) {
|
|
|
1458
1560
|
limit: ctx.historyLimit
|
|
1459
1561
|
}) : dmHistoryContext.inboundHistory;
|
|
1460
1562
|
const commandBody = textForCommandDetection.trim();
|
|
1461
|
-
const
|
|
1563
|
+
const supplementalThreadHistoryBody = directThreadRoutedToDmSession && !threadHistoryBody ? threadStarterBody : threadHistoryBody;
|
|
1564
|
+
const effectiveMessageThreadId = assistantThreadContext?.threadTs ?? threadContext.messageThreadId;
|
|
1565
|
+
const ctxPayload = buildChannelInboundEventContext({
|
|
1462
1566
|
channel: "slack",
|
|
1463
1567
|
provider: "slack",
|
|
1464
1568
|
surface: "slack",
|
|
@@ -1476,7 +1580,7 @@ async function prepareSlackMessage(params) {
|
|
|
1476
1580
|
id: message.channel,
|
|
1477
1581
|
label: envelopeFrom,
|
|
1478
1582
|
spaceId: ctx.teamId || void 0,
|
|
1479
|
-
threadId:
|
|
1583
|
+
threadId: directThreadRoutedToDmSession ? void 0 : effectiveMessageThreadId,
|
|
1480
1584
|
nativeChannelId: message.channel,
|
|
1481
1585
|
routePeer: {
|
|
1482
1586
|
kind: chatType,
|
|
@@ -1493,10 +1597,11 @@ async function prepareSlackMessage(params) {
|
|
|
1493
1597
|
to: slackTo,
|
|
1494
1598
|
originatingTo: slackTo,
|
|
1495
1599
|
replyToId: threadContext.replyToId,
|
|
1496
|
-
messageThreadId:
|
|
1600
|
+
messageThreadId: directThreadRoutedToDmSession ? void 0 : effectiveMessageThreadId,
|
|
1497
1601
|
nativeChannelId: message.channel
|
|
1498
1602
|
},
|
|
1499
1603
|
message: {
|
|
1604
|
+
inboundEventKind,
|
|
1500
1605
|
body: combinedBody,
|
|
1501
1606
|
bodyForAgent: rawBody,
|
|
1502
1607
|
rawBody,
|
|
@@ -1523,16 +1628,21 @@ async function prepareSlackMessage(params) {
|
|
|
1523
1628
|
media: toInboundMediaFacts(effectiveMedia),
|
|
1524
1629
|
supplemental: {
|
|
1525
1630
|
thread: {
|
|
1526
|
-
starterBody: !threadSessionPreviousTimestamp ? threadStarterBody : void 0,
|
|
1527
|
-
historyBody:
|
|
1528
|
-
label: threadLabel
|
|
1631
|
+
starterBody: !directThreadRoutedToDmSession && !threadSessionPreviousTimestamp ? threadStarterBody : void 0,
|
|
1632
|
+
historyBody: supplementalThreadHistoryBody,
|
|
1633
|
+
label: directThreadRoutedToDmSession ? void 0 : threadLabel
|
|
1529
1634
|
},
|
|
1530
1635
|
groupSystemPrompt
|
|
1531
1636
|
},
|
|
1532
1637
|
extra: {
|
|
1533
1638
|
GroupSubject: isRoomish ? roomLabel : void 0,
|
|
1534
1639
|
UntrustedContext: untrustedChannelMetadata ? [untrustedChannelMetadata] : void 0,
|
|
1535
|
-
|
|
1640
|
+
TransportThreadId: directThreadRoutedToDmSession ? threadContext.messageThreadId : void 0,
|
|
1641
|
+
SlackAssistantThread: assistantThreadContext ? true : void 0,
|
|
1642
|
+
SlackAssistantThreadContextChannelId: assistantThreadContext?.channelId,
|
|
1643
|
+
SlackAssistantThreadContextTeamId: assistantThreadContext?.teamId,
|
|
1644
|
+
SlackAssistantThreadContextEnterpriseId: assistantThreadContext?.enterpriseId ?? void 0,
|
|
1645
|
+
IsFirstThreadTurn: isThreadReply && threadTs && !directThreadRoutedToDmSession && !threadSessionPreviousTimestamp ? true : void 0,
|
|
1536
1646
|
...buildSlackMentionContextPayload({
|
|
1537
1647
|
isRoomish,
|
|
1538
1648
|
effectiveWasMentioned,
|
|
@@ -1581,7 +1691,7 @@ async function prepareSlackMessage(params) {
|
|
|
1581
1691
|
channel: "slack",
|
|
1582
1692
|
to: `user:${message.user}`,
|
|
1583
1693
|
accountId: route.accountId,
|
|
1584
|
-
threadId:
|
|
1694
|
+
threadId: effectiveMessageThreadId,
|
|
1585
1695
|
mainDmOwnerPin: pinnedMainDmOwner && message.user ? {
|
|
1586
1696
|
ownerRecipient: pinnedMainDmOwner,
|
|
1587
1697
|
senderRecipient: normalizeLowercaseStringOrEmpty(message.user),
|
|
@@ -1606,6 +1716,8 @@ async function prepareSlackMessage(params) {
|
|
|
1606
1716
|
} : void 0
|
|
1607
1717
|
},
|
|
1608
1718
|
replyToMode,
|
|
1719
|
+
...assistantThreadContext?.threadTs ? { forcedReplyThreadTs: assistantThreadContext.threadTs } : {},
|
|
1720
|
+
...assistantThreadContext ? { slackMessageMetadata: buildSlackAssistantThreadMetadata(assistantThreadContext) } : {},
|
|
1609
1721
|
requireMention: shouldRequireMention,
|
|
1610
1722
|
isDirectMessage,
|
|
1611
1723
|
isRoomish,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { p as createSlackMonitorContext } from "./room-context-BI26wVBb.js";
|
|
2
2
|
import "openclaw/plugin-sdk/temp-path";
|
|
3
3
|
//#region extensions/slack/src/monitor/message-handler/prepare.test-helpers.ts
|
|
4
4
|
function createInboundSlackTestContext(params) {
|
|
@@ -8,7 +8,7 @@ import { n as registerSlackHttpHandler, r as normalizeSlackWebhookPath } from ".
|
|
|
8
8
|
import { t as formatSlackError } from "./errors-C_sW0Zgl.js";
|
|
9
9
|
import { t as resolveSlackChannelAllowlist } from "./resolve-channels-B_eKaOkE.js";
|
|
10
10
|
import { t as resolveSlackUserAllowlist } from "./resolve-users-BzBAJwvq.js";
|
|
11
|
-
import {
|
|
11
|
+
import { A as resolveSlackSlashCommandConfig, O as warnMissingProviderGroupPolicyFallbackOnce, T as resolveOpenProviderRuntimeGroupPolicy, _ as resolveSlackChatType, b as getRuntimeConfig$1, d as resolveSlackEffectiveAllowFrom, f as buildSlackAssistantThreadMetadata, g as normalizeSlackChannelType, h as isSlackChannelAllowedByPolicy, i as parsePluginBindingApprovalCustomId, j as stripSlackMentionsForCommandDetection, k as buildSlackSlashCommandMatcher, l as authorizeSlackSystemEventSender, n as authorizeSlackDirectMessage, p as createSlackMonitorContext, r as buildPluginBindingResolvedText, s as resolvePluginConversationBindingApproval, t as resolveSlackRoomContextHints, u as resolveSlackCommandIngress, v as resolveSlackChannelConfig, w as resolveDefaultGroupPolicy, x as isDangerousNameMatchingEnabled, y as resolveSlackChannelLabel } from "./room-context-BI26wVBb.js";
|
|
12
12
|
import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
|
|
13
13
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
14
14
|
import { normalizeAccountId, normalizeMainKey } from "openclaw/plugin-sdk/routing";
|
|
@@ -37,6 +37,112 @@ import { requestHeartbeat } from "openclaw/plugin-sdk/heartbeat-runtime";
|
|
|
37
37
|
import { createInteractiveConversationBindingHelpers, dispatchPluginInteractiveHandler } from "openclaw/plugin-sdk/plugin-runtime";
|
|
38
38
|
import { createChannelInboundDebouncer, shouldDebounceTextInbound } from "openclaw/plugin-sdk/channel-inbound";
|
|
39
39
|
import { generateSecureToken } from "openclaw/plugin-sdk/secure-random-runtime";
|
|
40
|
+
//#region extensions/slack/src/monitor/events/assistant.ts
|
|
41
|
+
const DEFAULT_ASSISTANT_PROMPTS = [
|
|
42
|
+
{
|
|
43
|
+
title: "What can you do?",
|
|
44
|
+
message: "What can you help me with?"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
title: "Summarize this channel",
|
|
48
|
+
message: "Summarize the recent activity in this channel."
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
title: "Draft a reply",
|
|
52
|
+
message: "Help me draft a reply."
|
|
53
|
+
}
|
|
54
|
+
];
|
|
55
|
+
function normalizeAssistantThread(event, getPrevious) {
|
|
56
|
+
const thread = event.assistant_thread;
|
|
57
|
+
if (!thread) return null;
|
|
58
|
+
const channelId = thread.channel_id?.trim();
|
|
59
|
+
const threadTs = thread.thread_ts?.trim();
|
|
60
|
+
if (!channelId || !threadTs) return null;
|
|
61
|
+
const previous = getPrevious?.(channelId, threadTs);
|
|
62
|
+
const threadContext = thread.context;
|
|
63
|
+
const eventContext = event.context;
|
|
64
|
+
const resolveContextString = (key, previousValue) => threadContext?.[key]?.trim() || eventContext?.[key]?.trim() || previousValue;
|
|
65
|
+
const enterpriseId = (() => {
|
|
66
|
+
if (threadContext && "enterprise_id" in threadContext) return threadContext.enterprise_id === null ? null : threadContext.enterprise_id?.trim() || previous?.enterpriseId;
|
|
67
|
+
if (eventContext && "enterprise_id" in eventContext) return eventContext.enterprise_id === null ? null : eventContext.enterprise_id?.trim() || previous?.enterpriseId;
|
|
68
|
+
return previous?.enterpriseId;
|
|
69
|
+
})();
|
|
70
|
+
return {
|
|
71
|
+
assistantChannelId: channelId,
|
|
72
|
+
threadTs,
|
|
73
|
+
userId: thread.user_id?.trim() || previous?.userId,
|
|
74
|
+
channelId: resolveContextString("channel_id", previous?.channelId),
|
|
75
|
+
teamId: resolveContextString("team_id", previous?.teamId),
|
|
76
|
+
enterpriseId
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
async function persistAssistantThreadMetadata(params) {
|
|
80
|
+
const { ctx, assistantThread } = params;
|
|
81
|
+
try {
|
|
82
|
+
const initialMessage = ((await ctx.app.client.conversations.replies({
|
|
83
|
+
token: ctx.botToken,
|
|
84
|
+
channel: assistantThread.assistantChannelId,
|
|
85
|
+
ts: assistantThread.threadTs,
|
|
86
|
+
oldest: assistantThread.threadTs,
|
|
87
|
+
include_all_metadata: true,
|
|
88
|
+
limit: 4
|
|
89
|
+
})).messages ?? []).find((message) => !message.subtype && message.user === ctx.botUserId && message.ts);
|
|
90
|
+
if (!initialMessage?.ts) return;
|
|
91
|
+
await ctx.app.client.chat.update({
|
|
92
|
+
token: ctx.botToken,
|
|
93
|
+
channel: assistantThread.assistantChannelId,
|
|
94
|
+
ts: initialMessage.ts,
|
|
95
|
+
text: initialMessage.text ?? "",
|
|
96
|
+
blocks: Array.isArray(initialMessage.blocks) ? initialMessage.blocks : [],
|
|
97
|
+
metadata: buildSlackAssistantThreadMetadata(assistantThread)
|
|
98
|
+
});
|
|
99
|
+
} catch (err) {
|
|
100
|
+
logVerbose(`slack assistant thread metadata persist failed for channel ${assistantThread.assistantChannelId}: ${formatErrorMessage(err)}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function registerSlackAssistantEvents(params) {
|
|
104
|
+
const { ctx, trackEvent } = params;
|
|
105
|
+
const slackApp = ctx.app;
|
|
106
|
+
slackApp.event("assistant_thread_started", async ({ event, body }) => {
|
|
107
|
+
try {
|
|
108
|
+
if (ctx.shouldDropMismatchedSlackEvent(body)) return;
|
|
109
|
+
trackEvent?.();
|
|
110
|
+
const assistantThread = normalizeAssistantThread(event, ctx.getSlackAssistantThreadContext);
|
|
111
|
+
if (!assistantThread) {
|
|
112
|
+
logVerbose("slack assistant_thread_started dropped: missing assistant thread channel/thread");
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
ctx.saveSlackAssistantThreadContext(assistantThread);
|
|
116
|
+
await ctx.setSlackAssistantSuggestedPrompts({
|
|
117
|
+
channelId: assistantThread.assistantChannelId,
|
|
118
|
+
threadTs: assistantThread.threadTs,
|
|
119
|
+
title: "Try asking",
|
|
120
|
+
prompts: DEFAULT_ASSISTANT_PROMPTS
|
|
121
|
+
});
|
|
122
|
+
} catch (err) {
|
|
123
|
+
ctx.runtime.error?.(danger(`slack assistant_thread_started handler failed: ${formatErrorMessage(err)}`));
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
slackApp.event("assistant_thread_context_changed", async ({ event, body }) => {
|
|
127
|
+
try {
|
|
128
|
+
if (ctx.shouldDropMismatchedSlackEvent(body)) return;
|
|
129
|
+
trackEvent?.();
|
|
130
|
+
const assistantThread = normalizeAssistantThread(event, ctx.getSlackAssistantThreadContext);
|
|
131
|
+
if (!assistantThread) {
|
|
132
|
+
logVerbose("slack assistant_thread_context_changed dropped: missing assistant thread channel/thread");
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
ctx.saveSlackAssistantThreadContext(assistantThread);
|
|
136
|
+
await persistAssistantThreadMetadata({
|
|
137
|
+
ctx,
|
|
138
|
+
assistantThread
|
|
139
|
+
});
|
|
140
|
+
} catch (err) {
|
|
141
|
+
ctx.runtime.error?.(danger(`slack assistant_thread_context_changed handler failed: ${formatErrorMessage(err)}`));
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
//#endregion
|
|
40
146
|
//#region extensions/slack/src/channel-migration.ts
|
|
41
147
|
function resolveAccountChannels(cfg, accountId) {
|
|
42
148
|
if (!accountId) return {};
|
|
@@ -1418,7 +1524,10 @@ function resolveAssistantMessageChangedInbound(params) {
|
|
|
1418
1524
|
message,
|
|
1419
1525
|
botUserId: params.ctx.botUserId
|
|
1420
1526
|
});
|
|
1421
|
-
if (!senderId)
|
|
1527
|
+
if (!senderId) {
|
|
1528
|
+
if (shouldLogVerbose()) logVerbose(`slack: assistant_app_thread message_changed in DM channel=${changed.channel} dropped: no sender resolved from metadata`);
|
|
1529
|
+
return;
|
|
1530
|
+
}
|
|
1422
1531
|
return {
|
|
1423
1532
|
type: "message",
|
|
1424
1533
|
channel: changed.channel ?? params.event.channel,
|
|
@@ -1428,6 +1537,7 @@ function resolveAssistantMessageChangedInbound(params) {
|
|
|
1428
1537
|
ts: asString(message.ts) ?? asString(changed.event_ts),
|
|
1429
1538
|
thread_ts: asString(message.thread_ts),
|
|
1430
1539
|
event_ts: changed.event_ts,
|
|
1540
|
+
assistant_thread: asRecord$1(message.assistant_thread) ?? asRecord$1(changed.assistant_thread),
|
|
1431
1541
|
files: Array.isArray(message.files) ? message.files : void 0,
|
|
1432
1542
|
attachments: Array.isArray(message.attachments) ? message.attachments : void 0
|
|
1433
1543
|
};
|
|
@@ -1642,6 +1752,10 @@ function registerSlackMonitorEvents(params) {
|
|
|
1642
1752
|
ctx: params.ctx,
|
|
1643
1753
|
trackEvent: params.trackEvent
|
|
1644
1754
|
});
|
|
1755
|
+
registerSlackAssistantEvents({
|
|
1756
|
+
ctx: params.ctx,
|
|
1757
|
+
trackEvent: params.trackEvent
|
|
1758
|
+
});
|
|
1645
1759
|
}
|
|
1646
1760
|
//#endregion
|
|
1647
1761
|
//#region extensions/slack/src/monitor/message-handler/debounce-key.ts
|
|
@@ -1761,7 +1875,7 @@ function createSlackThreadTsResolver(params) {
|
|
|
1761
1875
|
//#region extensions/slack/src/monitor/message-handler.ts
|
|
1762
1876
|
let slackMessagePipelinePromise;
|
|
1763
1877
|
function loadSlackMessagePipeline() {
|
|
1764
|
-
slackMessagePipelinePromise ??= import("./pipeline.runtime-
|
|
1878
|
+
slackMessagePipelinePromise ??= import("./pipeline.runtime-Bq754VH8.js");
|
|
1765
1879
|
return slackMessagePipelinePromise;
|
|
1766
1880
|
}
|
|
1767
1881
|
const APP_MENTION_RETRY_TTL_MS = 6e4;
|
|
@@ -2303,7 +2417,7 @@ function loadSlashCommandsRuntime() {
|
|
|
2303
2417
|
return slashCommandsRuntimePromise;
|
|
2304
2418
|
}
|
|
2305
2419
|
function loadSlashDispatchRuntime() {
|
|
2306
|
-
slashDispatchRuntimePromise ??= import("./slash-dispatch.runtime-
|
|
2420
|
+
slashDispatchRuntimePromise ??= import("./slash-dispatch.runtime-CcbE1HtP.js");
|
|
2307
2421
|
return slashDispatchRuntimePromise;
|
|
2308
2422
|
}
|
|
2309
2423
|
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-C5PzphgC.js";
|
|
4
|
+
import "./send.runtime-DsEXD6MR.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";
|
|
@@ -32,7 +32,8 @@ async function deliverReplies(params) {
|
|
|
32
32
|
threadTs,
|
|
33
33
|
accountId: params.accountId,
|
|
34
34
|
...slackBlocks?.length ? { blocks: slackBlocks } : {},
|
|
35
|
-
...params.identity ? { identity: params.identity } : {}
|
|
35
|
+
...params.identity ? { identity: params.identity } : {},
|
|
36
|
+
...params.metadata ? { metadata: params.metadata } : {}
|
|
36
37
|
});
|
|
37
38
|
params.runtime.log?.(`delivered reply to ${params.target}`);
|
|
38
39
|
continue;
|
|
@@ -51,7 +52,8 @@ async function deliverReplies(params) {
|
|
|
51
52
|
token: params.token,
|
|
52
53
|
threadTs,
|
|
53
54
|
accountId: params.accountId,
|
|
54
|
-
...params.identity ? { identity: params.identity } : {}
|
|
55
|
+
...params.identity ? { identity: params.identity } : {},
|
|
56
|
+
...params.metadata ? { metadata: params.metadata } : {}
|
|
55
57
|
});
|
|
56
58
|
},
|
|
57
59
|
sendMedia: async ({ mediaUrl, caption }) => {
|
|
@@ -61,7 +63,8 @@ async function deliverReplies(params) {
|
|
|
61
63
|
mediaUrl,
|
|
62
64
|
threadTs,
|
|
63
65
|
accountId: params.accountId,
|
|
64
|
-
...params.identity ? { identity: params.identity } : {}
|
|
66
|
+
...params.identity ? { identity: params.identity } : {},
|
|
67
|
+
...params.metadata ? { metadata: params.metadata } : {}
|
|
65
68
|
});
|
|
66
69
|
}
|
|
67
70
|
}) !== "empty") params.runtime.log?.(`delivered reply to ${params.target}`);
|