@openclaw/slack 2026.8.1-beta.2 → 2026.8.1-beta.3
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-Drw2gAiN.js → account-inspect-YJvFBbCR.js} +1 -1
- package/dist/account-inspect-api.js +1 -1
- package/dist/{accounts-CK4AVI2_.js → accounts-BlzxuYle.js} +5 -1
- package/dist/{accounts.runtime-Cb7QwWBz.js → accounts.runtime-CbabBL8x.js} +1 -1
- package/dist/{action-runtime-BkGe7ny_.js → action-runtime-D6jg2CQd.js} +64 -68
- package/dist/action-runtime.runtime-JtoOK9l5.js +2 -0
- package/dist/{actions-BTDXwwE3.js → actions-DFk0ANVB.js} +52 -212
- package/dist/{actions.runtime-DLFyUkvg.js → actions.runtime-CYLsYRai.js} +1 -1
- package/dist/api.js +14 -14
- package/dist/{approval-handler.runtime-CJaNzAq2.js → approval-handler.runtime-BNvAoKdK.js} +4 -2
- package/dist/{channel-D_tovcUL.js → channel-CA5w7qDF.js} +78 -39
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-type-B9MSdoGN.js → channel-type-CZWv55Wu.js} +3 -7
- package/dist/{channel.setup-Bch9dYmA.js → channel.setup-CpyYsEXH.js} +4 -4
- package/dist/{config-schema-xto5jFIx.js → config-schema-CN3XZRX5.js} +23 -7
- package/dist/conversation-binding-route-DFVLUdYF.js +115 -0
- package/dist/{directory-config-CNBz8lJa.js → directory-config-BGYyuzWh.js} +1 -1
- package/dist/directory-contract-api.js +1 -1
- package/dist/{directory-live-CFKUtW9E.js → directory-live-DjUJQLbq.js} +2 -2
- package/dist/{group-policy-c4RP9bjc.js → group-policy-DyfB_ZIE.js} +38 -24
- package/dist/{message-tool-api-BykQB4AU.js → message-tool-api-CqMr5Rmc.js} +2 -2
- package/dist/message-tool-api.js +1 -1
- package/dist/{monitor-1nF1NtqT.js → monitor-Chrecrb9.js} +3 -3
- package/dist/{outbound-adapter-S81tsswN.js → outbound-adapter-DuRqAQXK.js} +18 -8
- package/dist/{pipeline.runtime-BvYsM5JO.js → pipeline.runtime-Bbfd5VFW.js} +376 -324
- package/dist/{policy-TapwbeaT.js → policy-BKXSxrIS.js} +1 -1
- package/dist/{probe-HoEg_WxB.js → probe-BVA65leh.js} +1 -1
- package/dist/{provider-CDNvBXUi.js → provider-CUUiwsg2.js} +65 -44
- package/dist/{relay-source-C9leF11u.js → relay-source-mhpMMRG-.js} +1 -1
- package/dist/{replies-CeOfv82I.js → replies-SnWyXcsL.js} +36 -25
- package/dist/{resolve-channels-CNPrxaXY.js → resolve-channels-BSpqC8jU.js} +1 -1
- package/dist/{resolve-users-Dzomuwnr.js → resolve-users-Dvz9pDe0.js} +1 -1
- package/dist/{runtime-api-Cj9nxBNv.js → runtime-api-DBi7xc_g.js} +2 -2
- package/dist/runtime-api.js +11 -11
- package/dist/{scopes-cYXKkrRD.js → scopes-BSk4GZvZ.js} +1 -1
- package/dist/security-contract-api.js +1 -1
- package/dist/{send-Nor0iBwY.js → send-CtnOxKCc.js} +58 -78
- package/dist/{send.runtime-BmgNe6S9.js → send.runtime-kYctMHSd.js} +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-CbX1-Knh.js → setup-surface-BPFfp6So.js} +6 -6
- package/dist/{shared-zdT5AMp-.js → shared-DJBaslN7.js} +13 -7
- package/dist/{block-text-YtiNkqmx.js → slack-client-kind-BXyOOICI.js} +17 -2
- package/dist/{slash-dispatch.runtime-Bnr9GR1S.js → slash-dispatch.runtime-Cf2FTrnf.js} +2 -2
- package/openclaw.plugin.json +43 -1
- package/package.json +4 -6
- package/dist/account-reply-mode-DrUXogvO.js +0 -14
- package/dist/action-runtime.runtime-D9I6uc0Q.js +0 -2
- package/node_modules/p-map/index.d.ts +0 -155
- package/node_modules/p-map/index.js +0 -285
- package/node_modules/p-map/license +0 -9
- package/node_modules/p-map/package.json +0 -57
- package/node_modules/p-map/readme.md +0 -190
- package/dist/{security-audit-DR097212.js → security-audit-B_yKr7MW.js} +1 -1
|
@@ -1,35 +1,36 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import "./
|
|
4
|
-
import {
|
|
5
|
-
import { r as formatSlackError } from "./probe-HoEg_WxB.js";
|
|
1
|
+
import { n as resolveSlackConversationBindingRoute, r as resolveSlackReplyToMode, t as normalizeSlackRouteBindingConfig } from "./conversation-binding-route-DFVLUdYF.js";
|
|
2
|
+
import { n as formatSlackTarget } from "./target-parsing-BnMD2ZqZ.js";
|
|
3
|
+
import { B as SLACK_EDIT_TEXT_MAX_BYTES, F as normalizeSlackOutboundText, I as buildSlackBlocksFallbackText, J as truncateSlackText, O as hasSlackNativeDataBlock, S as resolveSlackReplyRenderPlan, U as SLACK_TEXT_LIMIT, Y as truncateSlackTextByUtf8Bytes, a as qualifySlackConversationId, ct as escapeSlackMrkdwn, d as normalizeSlackAllowOwnerEntry, et as SLACK_SESSION_LINK_ACTION_ID, o as qualifySlackRoutePeerId, p as resolveSlackAllowListMatch, q as countSlackTextUtf8Bytes, s as resolveSlackEnterpriseMainDmSessionKey, u as normalizeAllowListLower } from "./group-policy-DyfB_ZIE.js";
|
|
4
|
+
import { r as formatSlackError } from "./probe-BVA65leh.js";
|
|
6
5
|
import { n as resolveSlackStreamingMode, t as resolveSlackNativeStreaming } from "./streaming-compat-B-e0mqM0.js";
|
|
7
|
-
import { b as
|
|
8
|
-
import { a as resolveSlackMessageText } from "./
|
|
9
|
-
import { c as hasSlackThreadFailureNotice, d as recordSlackThreadFailureNotice, f as recordSlackThreadParticipation, l as hasSlackThreadParticipation,
|
|
10
|
-
import {
|
|
11
|
-
import { n as resolveSlackChannelConfig } from "./policy-
|
|
12
|
-
import { a as resolveDeliveredSlackReplyThreadTs, i as readSlackReplyBlocks, n as deliverReplies, o as resolveSlackThreadTs, s as emitSlackMessageSentHooks, t as createSlackReplyDeliveryPlan } from "./replies-
|
|
6
|
+
import { b as formatSlackFileReferenceList, i as editSlackRenderedMessage, p as removeSlackReaction, r as editSlackMessage, t as deleteSlackMessage, u as reactSlackMessage, v as logVerbose$1, x as buildSlackEditTextPayload, y as formatSlackFileReference } from "./actions-DFk0ANVB.js";
|
|
7
|
+
import { a as hasSlackTableBlock, c as resolveSlackMessageText$1, o as isSlackUnfurlAttachment, s as resolveSlackBlocksText } from "./slack-client-kind-BXyOOICI.js";
|
|
8
|
+
import { c as hasSlackThreadFailureNotice, d as recordSlackThreadFailureNotice, f as recordSlackThreadParticipation, l as hasSlackThreadParticipation, m as buildSlackNativeDataDeliveryPlan, o as clearSlackThreadFailureNotice, r as sendMessageSlack, u as hasSlackThreadParticipationWithPersistence } from "./send-CtnOxKCc.js";
|
|
9
|
+
import { S as updateLastRoute, _ as parseSlackAssistantThreadMetadata, b as resolveChannelResetConfig, c as resolveConversationLabel$1, d as resolveSlackEffectiveAllowFrom, g as buildSlackAssistantThreadMetadata, h as resolveSlackChatType, l as authorizeSlackBotRoomMessage, m as normalizeSlackChannelType, o as authorizeSlackDirectMessage, r as resolveSlackRoomContextHints, s as trackSlackDraftMessage, u as resolveSlackCommandIngress, v as readSessionUpdatedAt, w as stripSlackMentionsForCommandDetection, x as resolveStorePath, y as resolveChannelContextVisibilityMode } from "./provider-CUUiwsg2.js";
|
|
10
|
+
import { n as resolveSlackChannelConfig } from "./policy-BKXSxrIS.js";
|
|
11
|
+
import { a as resolveDeliveredSlackReplyThreadTs, i as readSlackReplyBlocks, n as deliverReplies, o as resolveSlackThreadTs, s as emitSlackMessageSentHooks, t as createSlackReplyDeliveryPlan } from "./replies-SnWyXcsL.js";
|
|
13
12
|
import { asOptionalRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
14
13
|
import { resolveAgentRoute, resolveInboundLastRouteSessionKey, resolveThreadSessionKeys } from "openclaw/plugin-sdk/routing";
|
|
15
|
-
import { buildChannelProgressDraftLine, buildChannelProgressDraftLineForEntry, createChannelMessageReplyPipeline, createChannelProgressDraftCompositor,
|
|
14
|
+
import { buildChannelProgressDraftLine, buildChannelProgressDraftLineForEntry, createChannelMessageReplyPipeline, createChannelProgressDraftCompositor, createChannelProgressWorkCounter, createFinalizableDraftStreamControlsForState, defineFinalizableLivePreviewAdapter, deliverWithFinalizableLivePreviewAdapter, formatChannelProgressDraftText, formatPlanChecklistLines, isChannelProgressDraftWorkToolName, resolveAgentOutboundIdentity, resolveChannelMessageSourceReplyDeliveryMode, resolveChannelProgressDraftConfig, resolveChannelProgressDraftMaxLineChars, resolveChannelStreamingBlockEnabled, resolveChannelStreamingPreviewToolProgress, resolveChannelStreamingSuppressDefaultToolProgressMessages } from "openclaw/plugin-sdk/channel-outbound";
|
|
16
15
|
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
17
16
|
import { danger, logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
|
|
18
17
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
19
18
|
import { createHash } from "node:crypto";
|
|
19
|
+
import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
|
|
20
|
+
import { ensureConfiguredBindingRouteReady } from "openclaw/plugin-sdk/conversation-runtime";
|
|
20
21
|
import fs from "node:fs/promises";
|
|
22
|
+
import { runTasksWithConcurrency } from "openclaw/plugin-sdk/concurrency-runtime";
|
|
21
23
|
import { formatErrorMessage, toErrorObject } from "openclaw/plugin-sdk/error-runtime";
|
|
22
|
-
import { asDateTimestampMs, asFiniteNumberInRange, parseStrictFiniteNumber, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
|
|
23
24
|
import { buildTtsSupplementMediaPayload, getReplyPayloadTtsSupplement, isReplyPayloadNonTerminalToolErrorWarning, resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
|
|
24
25
|
import { filterSupplementalContextItems, resolvePinnedMainDmOwnerFromAllowlist, shouldIncludeSupplementalContext } from "openclaw/plugin-sdk/security-runtime";
|
|
25
26
|
import { mimeTypeFromFilePath } from "openclaw/plugin-sdk/media-mime";
|
|
26
|
-
import { ensureConfiguredBindingRouteReady, resolveConfiguredBindingRoute, resolveRuntimeConversationBindingRoute } from "openclaw/plugin-sdk/conversation-runtime";
|
|
27
27
|
import { createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
|
|
28
28
|
import { mergePairLoopGuardConfig } from "openclaw/plugin-sdk/pair-loop-guard-runtime";
|
|
29
29
|
import { enqueueRoutedSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
|
|
30
30
|
import { resolveChannelImplicitMentions } from "openclaw/plugin-sdk/channel-ingress-runtime";
|
|
31
|
+
import { asDateTimestampMs, asFiniteNumberInRange, parseStrictFiniteNumber, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
|
|
31
32
|
import { getGlobalHookRunner } from "openclaw/plugin-sdk/plugin-runtime";
|
|
32
|
-
import { buildChannelInboundEventContext, buildMentionRegexes, classifyChannelInboundEvent, dispatchChannelInboundTurn, formatInboundEnvelope, formatInboundMediaUnavailableText, hasVisibleInboundReplyDispatch, implicitMentionKindWhen, logInboundDrop, matchesMentionWithExplicit, readAgentRunTerminalOutcome, recordDroppedChannelInboundHistory, resolveEnvelopeFormatOptions, resolveInboundMentionDecision, resolveInboundSupplementalSenderAllowed, resolveUnmentionedGroupInboundPolicy, toInboundMediaFactsWithMetadata } from "openclaw/plugin-sdk/channel-inbound";
|
|
33
|
+
import { buildChannelInboundEventContext, buildMentionRegexes, classifyChannelInboundEvent, dispatchChannelInboundTurn, formatInboundEnvelope, formatInboundMediaUnavailableText, hasVisibleInboundReplyDispatch, implicitMentionKindWhen, logInboundDrop, matchesMentionWithExplicit, readAgentRunTerminalOutcome, recordDroppedChannelInboundHistory, resolveEnvelopeFormatOptions, resolveInboundMentionDecision, resolveInboundReplyDispatchCounts, resolveInboundSupplementalSenderAllowed, resolveUnmentionedGroupInboundPolicy, toInboundMediaFactsWithMetadata } from "openclaw/plugin-sdk/channel-inbound";
|
|
33
34
|
import { resolveHumanDelayConfig } from "openclaw/plugin-sdk/agent-runtime";
|
|
34
35
|
import { resolveGatewayPublicOrigin } from "openclaw/plugin-sdk/config-contracts";
|
|
35
36
|
import { buildControlUiSessionPath } from "openclaw/plugin-sdk/session-discussion";
|
|
@@ -37,8 +38,7 @@ import { DEFAULT_TIMING, createStatusReactionController, logAckFailure, logTypin
|
|
|
37
38
|
import { hasControlCommand } from "openclaw/plugin-sdk/command-detection";
|
|
38
39
|
import { isAbortRequestText } from "openclaw/plugin-sdk/command-primitives-runtime";
|
|
39
40
|
import { shouldHandleTextCommands } from "openclaw/plugin-sdk/command-surface";
|
|
40
|
-
import { createChannelPreflightAudio } from "openclaw/plugin-sdk/media-understanding-runtime";
|
|
41
|
-
import { runTasksWithConcurrency } from "openclaw/plugin-sdk/concurrency-runtime";
|
|
41
|
+
import { createChannelPreflightAudio, formatAudioTranscriptForAgent } from "openclaw/plugin-sdk/media-understanding-runtime";
|
|
42
42
|
//#region extensions/slack/src/streaming.ts
|
|
43
43
|
/**
|
|
44
44
|
* Thrown when Slack definitively rejects a stream flush/finalize while text
|
|
@@ -267,7 +267,11 @@ function resolveExplicitSlackProgressTitle(entry) {
|
|
|
267
267
|
const trimmed = label.trim();
|
|
268
268
|
return trimmed && trimmed.toLowerCase() !== "auto" ? trimmed : void 0;
|
|
269
269
|
}
|
|
270
|
+
function resolveSlackProgressStyle(entry) {
|
|
271
|
+
return entry?.streaming?.progress?.style === "compact" ? "compact" : "card";
|
|
272
|
+
}
|
|
270
273
|
function resolveSlackNativeProgressTaskCards(entry) {
|
|
274
|
+
if (resolveSlackProgressStyle(entry) === "compact") return false;
|
|
271
275
|
const streaming = entry?.streaming;
|
|
272
276
|
if (!streaming || typeof streaming !== "object" || Array.isArray(streaming)) return true;
|
|
273
277
|
const progressConfig = streaming.progress;
|
|
@@ -567,6 +571,56 @@ function createSlackDraftStream(params) {
|
|
|
567
571
|
};
|
|
568
572
|
}
|
|
569
573
|
//#endregion
|
|
574
|
+
//#region extensions/slack/src/stream-mode.ts
|
|
575
|
+
function resolveSlackStreamingConfig(params) {
|
|
576
|
+
return {
|
|
577
|
+
mode: resolveSlackStreamingMode(params),
|
|
578
|
+
nativeStreaming: resolveSlackNativeStreaming(params)
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
function applyAppendOnlyStreamUpdate(params) {
|
|
582
|
+
const incoming = params.incoming.trimEnd();
|
|
583
|
+
if (!incoming) return {
|
|
584
|
+
rendered: params.rendered,
|
|
585
|
+
source: params.source,
|
|
586
|
+
changed: false
|
|
587
|
+
};
|
|
588
|
+
if (!params.rendered) return {
|
|
589
|
+
rendered: incoming,
|
|
590
|
+
source: incoming,
|
|
591
|
+
changed: true
|
|
592
|
+
};
|
|
593
|
+
if (incoming === params.source) return {
|
|
594
|
+
rendered: params.rendered,
|
|
595
|
+
source: params.source,
|
|
596
|
+
changed: false
|
|
597
|
+
};
|
|
598
|
+
if (incoming.startsWith(params.rendered)) return {
|
|
599
|
+
rendered: incoming,
|
|
600
|
+
source: incoming,
|
|
601
|
+
changed: incoming !== params.rendered
|
|
602
|
+
};
|
|
603
|
+
if (incoming.startsWith(params.source)) {
|
|
604
|
+
const delta = incoming.slice(params.source.length);
|
|
605
|
+
return {
|
|
606
|
+
rendered: `${params.rendered}${delta}`,
|
|
607
|
+
source: incoming,
|
|
608
|
+
changed: delta.length > 0
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
if (params.source.startsWith(incoming)) return {
|
|
612
|
+
rendered: params.rendered,
|
|
613
|
+
source: params.source,
|
|
614
|
+
changed: false
|
|
615
|
+
};
|
|
616
|
+
const separator = params.separator ?? (params.rendered.endsWith("\n") ? "" : "\n");
|
|
617
|
+
return {
|
|
618
|
+
rendered: `${params.rendered}${separator}${incoming}`,
|
|
619
|
+
source: incoming,
|
|
620
|
+
changed: true
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
//#endregion
|
|
570
624
|
//#region extensions/slack/src/progress-blocks.ts
|
|
571
625
|
const SLACK_PROGRESS_FIELD_MAX = 1800;
|
|
572
626
|
const DEFAULT_SLACK_PROGRESS_DETAIL_MAX_CHARS = 120;
|
|
@@ -628,12 +682,14 @@ function lineTaskTitle(line) {
|
|
|
628
682
|
return compactTitle(label);
|
|
629
683
|
}
|
|
630
684
|
function lineTaskDetails(line, maxLineChars) {
|
|
631
|
-
const detail =
|
|
632
|
-
return detail ? compactDetail(detail, maxLineChars) : void 0;
|
|
685
|
+
const detail = line.detail?.replace(SLACK_PROGRESS_LINE_DELTA_RE, "").replace(/\s+·\s*$/u, "").trim();
|
|
686
|
+
return detail && detail !== line.status?.trim() ? compactDetail(detail, maxLineChars) : void 0;
|
|
633
687
|
}
|
|
634
688
|
function lineTaskOutput(line) {
|
|
635
|
-
const match = SLACK_PROGRESS_LINE_DELTA_RE.exec(
|
|
636
|
-
|
|
689
|
+
const match = line.detail ? SLACK_PROGRESS_LINE_DELTA_RE.exec(line.detail) : null;
|
|
690
|
+
if (match) return `+${match[1]} −${match[2]}`;
|
|
691
|
+
const status = line.status?.replace(/\s+/g, " ").trim();
|
|
692
|
+
return status && lineTaskStatus(line) === "error" ? status : void 0;
|
|
637
693
|
}
|
|
638
694
|
function lineTaskStatus(line) {
|
|
639
695
|
const normalized = line.status?.replace(/\s+/g, " ").trim().toLowerCase();
|
|
@@ -738,7 +794,7 @@ function buildSlackProgressStreamChunks(params) {
|
|
|
738
794
|
};
|
|
739
795
|
if (task.details) chunk.details = task.details;
|
|
740
796
|
if (task.output) chunk.output = task.output;
|
|
741
|
-
if (index === finalTaskIndex && diffOutput) chunk.output = diffOutput;
|
|
797
|
+
if (index === finalTaskIndex && diffOutput) chunk.output = [task.output, diffOutput].filter(Boolean).join(" · ");
|
|
742
798
|
if (index === finalTaskIndex && params.sessionUrl) chunk.sources = buildSessionSources(params.sessionUrl);
|
|
743
799
|
return chunk;
|
|
744
800
|
});
|
|
@@ -784,8 +840,7 @@ function buildSlackProgressCardBlocks(params) {
|
|
|
784
840
|
...diffStat ? [diffStat] : [],
|
|
785
841
|
...params.elapsedSeconds && params.elapsedSeconds > 0 ? [`⏱ ${params.elapsedSeconds}s`] : []
|
|
786
842
|
].join(" · ");
|
|
787
|
-
const
|
|
788
|
-
const footer = params.state === "working" ? workingFooter : terminalFooter;
|
|
843
|
+
const footer = params.state === "working" ? workingFooter : diffStat;
|
|
789
844
|
return [
|
|
790
845
|
{
|
|
791
846
|
type: "section",
|
|
@@ -821,35 +876,106 @@ function buildSlackProgressCardBlocks(params) {
|
|
|
821
876
|
}] : []
|
|
822
877
|
].slice(0, 50);
|
|
823
878
|
}
|
|
879
|
+
const EMPTY_SLACK_NATIVE_STREAM_SNAPSHOT = { tasks: /* @__PURE__ */ new Map() };
|
|
880
|
+
const SLACK_TASK_FIELD_SEPARATOR = " · ";
|
|
881
|
+
function resolveTaskFieldDelta(previous, incoming) {
|
|
882
|
+
if (!incoming) return {
|
|
883
|
+
field: previous,
|
|
884
|
+
delta: void 0
|
|
885
|
+
};
|
|
886
|
+
if (previous?.rendered.includes(incoming)) return {
|
|
887
|
+
field: {
|
|
888
|
+
rendered: previous.rendered,
|
|
889
|
+
source: incoming
|
|
890
|
+
},
|
|
891
|
+
delta: void 0
|
|
892
|
+
};
|
|
893
|
+
const next = applyAppendOnlyStreamUpdate({
|
|
894
|
+
incoming,
|
|
895
|
+
rendered: previous?.rendered ?? "",
|
|
896
|
+
source: previous?.source ?? "",
|
|
897
|
+
separator: SLACK_TASK_FIELD_SEPARATOR
|
|
898
|
+
});
|
|
899
|
+
const delta = next.changed ? next.rendered.slice(previous?.rendered.length ?? 0) : void 0;
|
|
900
|
+
return {
|
|
901
|
+
field: {
|
|
902
|
+
rendered: next.rendered,
|
|
903
|
+
source: next.source
|
|
904
|
+
},
|
|
905
|
+
delta
|
|
906
|
+
};
|
|
907
|
+
}
|
|
824
908
|
/**
|
|
825
|
-
*
|
|
826
|
-
*
|
|
827
|
-
*
|
|
828
|
-
*
|
|
909
|
+
* Turns a full task snapshot into the delta Slack must receive. Native streams
|
|
910
|
+
* key rows by persistent id with no removal chunk: unchanged rows are omitted,
|
|
911
|
+
* changed rows carry only their unsent field text, and rows that dropped out
|
|
912
|
+
* (plan shrinks, tool-line <-> plan source switches) get a final complete
|
|
913
|
+
* update or they linger in_progress forever.
|
|
829
914
|
*/
|
|
830
915
|
function reconcileSlackNativeTaskChunks(params) {
|
|
831
916
|
const nextTasks = /* @__PURE__ */ new Map();
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
917
|
+
let planTitle = params.previous.planTitle;
|
|
918
|
+
const emitted = [];
|
|
919
|
+
for (const chunk of params.chunks ?? []) {
|
|
920
|
+
if (chunk.type === "plan_update") {
|
|
921
|
+
if (chunk.title !== planTitle) {
|
|
922
|
+
planTitle = chunk.title;
|
|
923
|
+
emitted.push(chunk);
|
|
924
|
+
}
|
|
925
|
+
continue;
|
|
926
|
+
}
|
|
927
|
+
if (chunk.type !== "task_update") {
|
|
928
|
+
emitted.push(chunk);
|
|
929
|
+
continue;
|
|
930
|
+
}
|
|
931
|
+
const previousRow = params.previous.tasks.get(chunk.id);
|
|
932
|
+
const status = chunk.status;
|
|
933
|
+
const details = resolveTaskFieldDelta(previousRow?.details, chunk.details);
|
|
934
|
+
const output = resolveTaskFieldDelta(previousRow?.output, chunk.output);
|
|
935
|
+
const sourcesChanged = Boolean(chunk.sources) && !previousRow?.sourcesSent;
|
|
936
|
+
const row = {
|
|
937
|
+
title: chunk.title,
|
|
938
|
+
status
|
|
840
939
|
};
|
|
841
|
-
|
|
842
|
-
|
|
940
|
+
if (details.field) row.details = details.field;
|
|
941
|
+
if (output.field) row.output = output.field;
|
|
942
|
+
if (sourcesChanged || previousRow?.sourcesSent) row.sourcesSent = true;
|
|
943
|
+
nextTasks.set(chunk.id, row);
|
|
944
|
+
if (!(!previousRow || previousRow.title !== chunk.title || previousRow.status !== status || Boolean(details.delta) || Boolean(output.delta) || sourcesChanged)) continue;
|
|
945
|
+
const update = {
|
|
946
|
+
type: "task_update",
|
|
947
|
+
id: chunk.id,
|
|
948
|
+
title: chunk.title,
|
|
949
|
+
status
|
|
950
|
+
};
|
|
951
|
+
if (details.delta) update.details = details.delta;
|
|
952
|
+
if (output.delta) update.output = output.delta;
|
|
953
|
+
if (sourcesChanged) update.sources = chunk.sources;
|
|
954
|
+
emitted.push(update);
|
|
955
|
+
}
|
|
956
|
+
for (const [id, row] of params.previous.tasks) {
|
|
957
|
+
if (nextTasks.has(id)) continue;
|
|
958
|
+
if (row.status === "complete" || row.status === "error") {
|
|
959
|
+
nextTasks.set(id, row);
|
|
960
|
+
continue;
|
|
961
|
+
}
|
|
962
|
+
nextTasks.set(id, {
|
|
963
|
+
...row,
|
|
964
|
+
status: "complete"
|
|
965
|
+
});
|
|
966
|
+
emitted.push({
|
|
843
967
|
type: "task_update",
|
|
844
968
|
id,
|
|
845
|
-
title:
|
|
969
|
+
title: row.title,
|
|
846
970
|
status: "complete"
|
|
847
|
-
};
|
|
848
|
-
}
|
|
849
|
-
for (const [id, task] of params.previousTasks) if (!nextTasks.has(id)) nextTasks.set(id, task);
|
|
971
|
+
});
|
|
972
|
+
}
|
|
850
973
|
return {
|
|
851
|
-
chunks:
|
|
852
|
-
|
|
974
|
+
chunks: emitted.length > 0 ? emitted : void 0,
|
|
975
|
+
snapshot: {
|
|
976
|
+
...planTitle ? { planTitle } : {},
|
|
977
|
+
tasks: nextTasks
|
|
978
|
+
}
|
|
853
979
|
};
|
|
854
980
|
}
|
|
855
981
|
function buildSlackProgressStreamCompletionChunks(params) {
|
|
@@ -859,56 +985,6 @@ function buildSlackProgressStreamCompletionChunks(params) {
|
|
|
859
985
|
});
|
|
860
986
|
}
|
|
861
987
|
//#endregion
|
|
862
|
-
//#region extensions/slack/src/stream-mode.ts
|
|
863
|
-
function resolveSlackStreamingConfig(params) {
|
|
864
|
-
return {
|
|
865
|
-
mode: resolveSlackStreamingMode(params),
|
|
866
|
-
nativeStreaming: resolveSlackNativeStreaming(params)
|
|
867
|
-
};
|
|
868
|
-
}
|
|
869
|
-
function applyAppendOnlyStreamUpdate(params) {
|
|
870
|
-
const incoming = params.incoming.trimEnd();
|
|
871
|
-
if (!incoming) return {
|
|
872
|
-
rendered: params.rendered,
|
|
873
|
-
source: params.source,
|
|
874
|
-
changed: false
|
|
875
|
-
};
|
|
876
|
-
if (!params.rendered) return {
|
|
877
|
-
rendered: incoming,
|
|
878
|
-
source: incoming,
|
|
879
|
-
changed: true
|
|
880
|
-
};
|
|
881
|
-
if (incoming === params.source) return {
|
|
882
|
-
rendered: params.rendered,
|
|
883
|
-
source: params.source,
|
|
884
|
-
changed: false
|
|
885
|
-
};
|
|
886
|
-
if (incoming.startsWith(params.rendered)) return {
|
|
887
|
-
rendered: incoming,
|
|
888
|
-
source: incoming,
|
|
889
|
-
changed: incoming !== params.rendered
|
|
890
|
-
};
|
|
891
|
-
if (incoming.startsWith(params.source)) {
|
|
892
|
-
const delta = incoming.slice(params.source.length);
|
|
893
|
-
return {
|
|
894
|
-
rendered: `${params.rendered}${delta}`,
|
|
895
|
-
source: incoming,
|
|
896
|
-
changed: delta.length > 0
|
|
897
|
-
};
|
|
898
|
-
}
|
|
899
|
-
if (params.source.startsWith(incoming)) return {
|
|
900
|
-
rendered: params.rendered,
|
|
901
|
-
source: params.source,
|
|
902
|
-
changed: false
|
|
903
|
-
};
|
|
904
|
-
const separator = params.rendered.endsWith("\n") ? "" : "\n";
|
|
905
|
-
return {
|
|
906
|
-
rendered: `${params.rendered}${separator}${incoming}`,
|
|
907
|
-
source: incoming,
|
|
908
|
-
changed: true
|
|
909
|
-
};
|
|
910
|
-
}
|
|
911
|
-
//#endregion
|
|
912
988
|
//#region extensions/slack/src/monitor/message-handler/dispatch-progress-render.ts
|
|
913
989
|
function resolveStructuredProgressLines(lines) {
|
|
914
990
|
return lines.map((line) => {
|
|
@@ -1098,12 +1174,9 @@ function createSlackDraftProgressCardRuntime(params) {
|
|
|
1098
1174
|
maxLineChars: params.maxLineChars,
|
|
1099
1175
|
diffStat: snapshot.diffStat,
|
|
1100
1176
|
...state === "working" ? {
|
|
1101
|
-
toolCalls: params.
|
|
1102
|
-
elapsedSeconds: params.
|
|
1103
|
-
} : {
|
|
1104
|
-
receiptSummary: params.progressReceipt.buildSummaryLine(),
|
|
1105
|
-
sessionUrl: resolveSessionUrl()
|
|
1106
|
-
}
|
|
1177
|
+
toolCalls: params.progressWorkCounter.toolCalls,
|
|
1178
|
+
elapsedSeconds: params.progressWorkCounter.elapsedSeconds
|
|
1179
|
+
} : { sessionUrl: resolveSessionUrl() }
|
|
1107
1180
|
});
|
|
1108
1181
|
};
|
|
1109
1182
|
const finalize = async (status, snapshot = params.getSnapshot(), fallbackText = resolveText(snapshot)) => {
|
|
@@ -1276,12 +1349,11 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1276
1349
|
previewStreamingEnabled
|
|
1277
1350
|
});
|
|
1278
1351
|
let previewToolProgressSuppressed = false;
|
|
1279
|
-
let
|
|
1352
|
+
let nativeStreamSnapshot = EMPTY_SLACK_NATIVE_STREAM_SNAPSHOT;
|
|
1280
1353
|
let appendRenderedText = "";
|
|
1281
1354
|
let appendSourceText = "";
|
|
1282
1355
|
let nativeProgressCompletionSent = false;
|
|
1283
1356
|
let nativeProgressTerminalStatus = "complete";
|
|
1284
|
-
let nativeProgressChunkKey;
|
|
1285
1357
|
let nativeNarrationRenderedText = "";
|
|
1286
1358
|
let nativeNarrationSourceText = "";
|
|
1287
1359
|
let nativeStreamOrder = Promise.resolve();
|
|
@@ -1290,9 +1362,10 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1290
1362
|
nativeStreamOrder = run.catch(() => void 0);
|
|
1291
1363
|
return run;
|
|
1292
1364
|
};
|
|
1293
|
-
const
|
|
1365
|
+
const progressWorkCounter = createChannelProgressWorkCounter();
|
|
1294
1366
|
const progressSeed = `${account.accountId}:${message.channel}`;
|
|
1295
|
-
const
|
|
1367
|
+
const slackProgressStyle = resolveSlackProgressStyle(account.config);
|
|
1368
|
+
const useDraftProgressCard = Boolean(draftStream) && isProgressMode && slackProgressStyle === "card";
|
|
1296
1369
|
const explicitProgressTitle = resolveExplicitSlackProgressTitle(account.config);
|
|
1297
1370
|
const progressDraftMaxLineChars = resolveChannelProgressDraftMaxLineChars(account.config);
|
|
1298
1371
|
const progressCard = createSlackDraftProgressCardRuntime({
|
|
@@ -1305,7 +1378,7 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1305
1378
|
},
|
|
1306
1379
|
draftStream,
|
|
1307
1380
|
enabled: useDraftProgressCard,
|
|
1308
|
-
|
|
1381
|
+
progressWorkCounter,
|
|
1309
1382
|
progressSeed,
|
|
1310
1383
|
explicitTitle: explicitProgressTitle,
|
|
1311
1384
|
maxLineChars: progressDraftMaxLineChars,
|
|
@@ -1367,16 +1440,14 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1367
1440
|
const snapshot = progressDraft.getSnapshot();
|
|
1368
1441
|
const progressLines = resolveNativeProgressLines(snapshot);
|
|
1369
1442
|
const narrationUpdate = resolveNarrationUpdate(resolveNativeProgressNarration(snapshot));
|
|
1370
|
-
const hasRetirableNativeTasks = [...
|
|
1443
|
+
const hasRetirableNativeTasks = [...nativeStreamSnapshot.tasks.values()].some((task) => task.status !== "complete" && task.status !== "error");
|
|
1371
1444
|
if (!useNativeProgressStreaming || delivery.streamFailed || progressLines.length === 0 && !snapshot.plan?.length && !snapshot.statusHeadline && !explicitProgressTitle && !hasRetirableNativeTasks && !narrationUpdate.delta) return false;
|
|
1372
1445
|
if (!await nativeTransport.waitForStart()) return false;
|
|
1373
1446
|
const reconciled = reconcileSlackNativeTaskChunks({
|
|
1374
|
-
|
|
1447
|
+
previous: nativeStreamSnapshot,
|
|
1375
1448
|
chunks: buildNativeProgressChunks$1(snapshot)
|
|
1376
1449
|
});
|
|
1377
|
-
const
|
|
1378
|
-
const taskChunksChanged = chunkKey !== nativeProgressChunkKey;
|
|
1379
|
-
const chunks = taskChunksChanged ? reconciled.chunks : void 0;
|
|
1450
|
+
const chunks = reconciled.chunks;
|
|
1380
1451
|
if (!chunks?.length && !narrationUpdate.delta) return false;
|
|
1381
1452
|
try {
|
|
1382
1453
|
const hadSession = Boolean(delivery.streamSession);
|
|
@@ -1390,10 +1461,7 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1390
1461
|
nativeNarrationRenderedText = narrationUpdate.next.rendered;
|
|
1391
1462
|
nativeNarrationSourceText = narrationUpdate.next.source;
|
|
1392
1463
|
}
|
|
1393
|
-
if (
|
|
1394
|
-
nativeProgressChunkKey = chunkKey;
|
|
1395
|
-
nativeTaskState = reconciled.tasks;
|
|
1396
|
-
}
|
|
1464
|
+
if (chunks?.length) nativeStreamSnapshot = reconciled.snapshot;
|
|
1397
1465
|
return true;
|
|
1398
1466
|
} catch (err) {
|
|
1399
1467
|
runtime.error?.(danger(`slack-stream: native progress stream failed: ${formatSlackError(err)}, falling back`));
|
|
@@ -1420,7 +1488,7 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1420
1488
|
return true;
|
|
1421
1489
|
};
|
|
1422
1490
|
const resetProgressTurnState = () => {
|
|
1423
|
-
|
|
1491
|
+
progressWorkCounter.reset();
|
|
1424
1492
|
nativeNarrationRenderedText = "";
|
|
1425
1493
|
nativeNarrationSourceText = "";
|
|
1426
1494
|
};
|
|
@@ -1476,10 +1544,10 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1476
1544
|
const snapshot = progressDraft.getSnapshot();
|
|
1477
1545
|
const lines = resolveNativeProgressLines(snapshot);
|
|
1478
1546
|
const sessionUrl = progressCard.resolveSessionUrl();
|
|
1479
|
-
const hasRetirableNativeTasks = [...
|
|
1547
|
+
const hasRetirableNativeTasks = [...nativeStreamSnapshot.tasks.values()].some((task) => task.status !== "complete" && task.status !== "error");
|
|
1480
1548
|
if (lines.length === 0 && !snapshot.plan?.length && !hasRetirableNativeTasks && !snapshot.diffStat && !sessionUrl) return;
|
|
1481
1549
|
return reconcileSlackNativeTaskChunks({
|
|
1482
|
-
|
|
1550
|
+
previous: nativeStreamSnapshot,
|
|
1483
1551
|
chunks: buildSlackProgressStreamCompletionChunks({
|
|
1484
1552
|
title: resolveNativeProgressTitle(snapshot) ?? (lines.length === 0 && !snapshot.plan?.length ? "Working" : void 0),
|
|
1485
1553
|
lines,
|
|
@@ -1514,7 +1582,10 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1514
1582
|
delivery.streamFailed = false;
|
|
1515
1583
|
};
|
|
1516
1584
|
const pushPlanProgress = async (steps, explanation) => {
|
|
1517
|
-
if (isProgressMode)
|
|
1585
|
+
if (isProgressMode) {
|
|
1586
|
+
if (slackProgressStyle === "compact") return false;
|
|
1587
|
+
return await progressDraft.pushPlanProgress(steps, { explanation });
|
|
1588
|
+
}
|
|
1518
1589
|
if (previewToolProgressSuppressed || !draftStream) return false;
|
|
1519
1590
|
const text = formatChannelProgressDraftText({
|
|
1520
1591
|
entry: account.config,
|
|
@@ -1580,7 +1651,6 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1580
1651
|
progressDraft.mergeReasoningProgress(normalized, { snapshot: true });
|
|
1581
1652
|
return visible;
|
|
1582
1653
|
}
|
|
1583
|
-
progressReceipt.noteReasoning();
|
|
1584
1654
|
return await progressDraft.pushReasoningProgress(payload.text, { snapshot: payload.isReasoningSnapshot === true });
|
|
1585
1655
|
};
|
|
1586
1656
|
const resetDraftDeliveryState = () => {
|
|
@@ -1604,10 +1674,9 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1604
1674
|
await dropDetachedProgressCards();
|
|
1605
1675
|
}
|
|
1606
1676
|
resetProgressTurnState();
|
|
1607
|
-
|
|
1677
|
+
nativeStreamSnapshot = EMPTY_SLACK_NATIVE_STREAM_SNAPSHOT;
|
|
1608
1678
|
nativeProgressCompletionSent = false;
|
|
1609
1679
|
nativeProgressTerminalStatus = "complete";
|
|
1610
|
-
nativeProgressChunkKey = void 0;
|
|
1611
1680
|
progressCard.reset();
|
|
1612
1681
|
resetPreviewDeliveryState();
|
|
1613
1682
|
delivery.resetDeliveryTracker();
|
|
@@ -1645,7 +1714,7 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1645
1714
|
suppressDefaultToolProgressMessages,
|
|
1646
1715
|
progressDraft,
|
|
1647
1716
|
commentaryProgressEnabled,
|
|
1648
|
-
|
|
1717
|
+
progressWorkCounter,
|
|
1649
1718
|
get nativeProgressCompletionSent() {
|
|
1650
1719
|
return nativeProgressCompletionSent;
|
|
1651
1720
|
},
|
|
@@ -1980,11 +2049,6 @@ function createSlackStreamingDeliveryRuntime(setup) {
|
|
|
1980
2049
|
observedFinalReplyDelivery: false
|
|
1981
2050
|
};
|
|
1982
2051
|
const streamedDeliveries = [];
|
|
1983
|
-
const streamedFailuresOwnedByDispatcher = {
|
|
1984
|
-
tool: 0,
|
|
1985
|
-
block: 0,
|
|
1986
|
-
final: 0
|
|
1987
|
-
};
|
|
1988
2052
|
const refreshStreamedAcknowledgements = (session) => {
|
|
1989
2053
|
if (session.pendingText.length === 0) for (const delivery of streamedDeliveries) delivery.acknowledged = true;
|
|
1990
2054
|
};
|
|
@@ -2167,10 +2231,7 @@ function createSlackStreamingDeliveryRuntime(setup) {
|
|
|
2167
2231
|
return deliveryReplyThreadTs;
|
|
2168
2232
|
};
|
|
2169
2233
|
const deliverBufferedStreamFallback = async (params) => {
|
|
2170
|
-
if (!await deliverPendingStreamFallback(params.session, params.err))
|
|
2171
|
-
streamedFailuresOwnedByDispatcher[params.kind] += 1;
|
|
2172
|
-
return false;
|
|
2173
|
-
}
|
|
2234
|
+
if (!await deliverPendingStreamFallback(params.session, params.err)) return false;
|
|
2174
2235
|
replyPlan.markSent();
|
|
2175
2236
|
if (params.kind === "final") state.observedFinalReplyDelivery = true;
|
|
2176
2237
|
deliveryTracker.markDelivered({
|
|
@@ -2329,23 +2390,6 @@ function createSlackStreamingDeliveryRuntime(setup) {
|
|
|
2329
2390
|
});
|
|
2330
2391
|
}
|
|
2331
2392
|
};
|
|
2332
|
-
const reconcileCounts = (counts) => {
|
|
2333
|
-
const next = { ...counts };
|
|
2334
|
-
let changed = false;
|
|
2335
|
-
for (const kind of [
|
|
2336
|
-
"tool",
|
|
2337
|
-
"block",
|
|
2338
|
-
"final"
|
|
2339
|
-
]) {
|
|
2340
|
-
const failedStreamedCount = streamedDeliveries.filter((delivery) => delivery.kind === kind && delivery.outcome === "failure").length;
|
|
2341
|
-
const additionalFailedStreamed = Math.max(0, failedStreamedCount - streamedFailuresOwnedByDispatcher[kind]);
|
|
2342
|
-
if (additionalFailedStreamed > 0) {
|
|
2343
|
-
next[kind] = Math.max(0, (next[kind] ?? 0) - additionalFailedStreamed);
|
|
2344
|
-
changed = true;
|
|
2345
|
-
}
|
|
2346
|
-
}
|
|
2347
|
-
return changed ? next : counts;
|
|
2348
|
-
};
|
|
2349
2393
|
return Object.assign(state, {
|
|
2350
2394
|
acknowledgeStoppedStreamedDeliveries,
|
|
2351
2395
|
deliverNormally,
|
|
@@ -2357,7 +2401,6 @@ function createSlackStreamingDeliveryRuntime(setup) {
|
|
|
2357
2401
|
isStreamingEligible,
|
|
2358
2402
|
markPreviewPayloadDelivered,
|
|
2359
2403
|
rememberDeliveredThreadTs,
|
|
2360
|
-
reconcileCounts,
|
|
2361
2404
|
resetDeliveryTracker: () => {
|
|
2362
2405
|
deliveryTracker = createSlackEventDeliveryTracker();
|
|
2363
2406
|
}
|
|
@@ -2463,63 +2506,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2463
2506
|
const previewFinalText = replyRenderPlan.mode === "single" && replyRenderPlan.textIsSlackMrkdwn ? trimmedFinalText : normalizeSlackOutboundText((replySourceText ?? "").trim());
|
|
2464
2507
|
const previewFinalTextFitsEdit = countSlackTextUtf8Bytes(previewFinalText) <= SLACK_EDIT_TEXT_MAX_BYTES;
|
|
2465
2508
|
const shouldRestoreTtsSupplementTextForPreviewFallback = Boolean(ttsSupplement) && ttsSupplement?.visibleTextAlreadyDelivered !== true && Boolean(draftStream) && !draftPreviewCommitted.value && !delivery.observedFinalReplyDelivery && previewStreamingEnabled && !payload.text?.trim();
|
|
2466
|
-
|
|
2467
|
-
await draftStream.flush();
|
|
2468
|
-
const channelId = draftStream.channelId();
|
|
2469
|
-
const messageId = draftStream.messageId();
|
|
2470
|
-
if (channelId && messageId) {
|
|
2471
|
-
const finalThreadTs = delivery.usedReplyThreadTs ?? statusThreadTs;
|
|
2472
|
-
await draftStream.seal();
|
|
2473
|
-
try {
|
|
2474
|
-
if (!await draftStream.finalizeMessage(messageId, async () => {
|
|
2475
|
-
await finalizeSlackPreviewEdit({
|
|
2476
|
-
client: slackClient,
|
|
2477
|
-
token: ctx.botToken,
|
|
2478
|
-
accountId: account.accountId,
|
|
2479
|
-
channelId,
|
|
2480
|
-
messageId,
|
|
2481
|
-
text: previewFinalText,
|
|
2482
|
-
...slackBlocks?.length ? { blocks: slackBlocks } : {},
|
|
2483
|
-
threadTs: finalThreadTs
|
|
2484
|
-
});
|
|
2485
|
-
})) throw new Error("Slack preview moved below a newer conversation message");
|
|
2486
|
-
} catch (err) {
|
|
2487
|
-
logVerbose(`slack: preview final edit failed; falling back to standard send (${formatSlackError(err)})`);
|
|
2488
|
-
await draftStream.discardPending();
|
|
2489
|
-
let delivered = false;
|
|
2490
|
-
try {
|
|
2491
|
-
await delivery.deliverNormally({
|
|
2492
|
-
payload: payload.text?.trim() ? payload : {
|
|
2493
|
-
...payload,
|
|
2494
|
-
text: ttsSupplement.spokenText
|
|
2495
|
-
},
|
|
2496
|
-
kind: info.kind,
|
|
2497
|
-
forcedThreadTs: finalThreadTs
|
|
2498
|
-
});
|
|
2499
|
-
delivered = true;
|
|
2500
|
-
} finally {
|
|
2501
|
-
if (delivered) await draftStream.clear();
|
|
2502
|
-
}
|
|
2503
|
-
return;
|
|
2504
|
-
}
|
|
2505
|
-
draftPreviewCommitted.value = true;
|
|
2506
|
-
delivery.observedFinalReplyDelivery = true;
|
|
2507
|
-
delivery.observedReplyDelivery = true;
|
|
2508
|
-
replyPlan.markSent();
|
|
2509
|
-
await delivery.deliverNormally({
|
|
2510
|
-
payload: buildTtsSupplementMediaPayload(payload),
|
|
2511
|
-
kind: info.kind,
|
|
2512
|
-
forcedThreadTs: finalThreadTs
|
|
2513
|
-
});
|
|
2514
|
-
delivery.markPreviewPayloadDelivered({
|
|
2515
|
-
kind: info.kind,
|
|
2516
|
-
payload,
|
|
2517
|
-
threadTs: finalThreadTs
|
|
2518
|
-
});
|
|
2519
|
-
progress.progressDraft.markFinalReplyDelivered();
|
|
2520
|
-
return;
|
|
2521
|
-
}
|
|
2522
|
-
}
|
|
2509
|
+
let ttsPreviewFinalization;
|
|
2523
2510
|
await deliverWithFinalizableLivePreviewAdapter({
|
|
2524
2511
|
kind: info.kind,
|
|
2525
2512
|
payload,
|
|
@@ -2552,6 +2539,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2552
2539
|
payload,
|
|
2553
2540
|
threadTs: edit.threadTs
|
|
2554
2541
|
})) return;
|
|
2542
|
+
if (ttsSupplement) ttsPreviewFinalization = { threadTs: edit.threadTs };
|
|
2555
2543
|
if (!await draftStream?.finalizeMessage(preview.messageId, async () => {
|
|
2556
2544
|
await finalizeSlackPreviewEdit({
|
|
2557
2545
|
client: slackClient,
|
|
@@ -2607,11 +2595,12 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2607
2595
|
}),
|
|
2608
2596
|
deliverNormally: async () => {
|
|
2609
2597
|
await delivery.deliverNormally({
|
|
2610
|
-
payload: shouldRestoreTtsSupplementTextForPreviewFallback ? {
|
|
2598
|
+
payload: shouldRestoreTtsSupplementTextForPreviewFallback || ttsPreviewFinalization && !payload.text?.trim() ? {
|
|
2611
2599
|
...payload,
|
|
2612
2600
|
text: ttsSupplement?.spokenText
|
|
2613
2601
|
} : payload,
|
|
2614
|
-
kind: info.kind
|
|
2602
|
+
kind: info.kind,
|
|
2603
|
+
...ttsPreviewFinalization?.threadTs ? { forcedThreadTs: ttsPreviewFinalization.threadTs } : {}
|
|
2615
2604
|
});
|
|
2616
2605
|
}
|
|
2617
2606
|
});
|
|
@@ -2619,8 +2608,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2619
2608
|
};
|
|
2620
2609
|
let dispatchError;
|
|
2621
2610
|
let agentRunFailed = false;
|
|
2622
|
-
let
|
|
2623
|
-
let counts = {};
|
|
2611
|
+
let settledDispatchResult;
|
|
2624
2612
|
try {
|
|
2625
2613
|
const turnResult = await dispatchChannelInboundTurn({
|
|
2626
2614
|
cfg,
|
|
@@ -2672,7 +2660,6 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2672
2660
|
return false;
|
|
2673
2661
|
} : void 0,
|
|
2674
2662
|
onReasoningEnd: async () => {
|
|
2675
|
-
progress.progressReceipt.closeReasoning();
|
|
2676
2663
|
await progress.onDraftBoundary?.();
|
|
2677
2664
|
return false;
|
|
2678
2665
|
},
|
|
@@ -2686,18 +2673,14 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2686
2673
|
} : void 0,
|
|
2687
2674
|
onToolStart: async (payload) => {
|
|
2688
2675
|
if (statusReactionsEnabled) await statusReactions.setTool(payload.name);
|
|
2689
|
-
if (payload.phase === "start") progress.
|
|
2676
|
+
if (payload.phase === "start") progress.progressWorkCounter.noteToolCall(payload.name);
|
|
2690
2677
|
return await progress.progressDraft.pushToolEvent(payload);
|
|
2691
2678
|
},
|
|
2692
2679
|
onItemEvent: async (payload) => {
|
|
2693
2680
|
if (progress.isProgressMode && payload.kind === "preamble") {
|
|
2694
2681
|
if (progress.shouldYieldDraftProgress()) return false;
|
|
2695
2682
|
const headlineVisible = await progress.progressDraft.pushPreambleHeadline(payload.progressText, { itemId: payload.itemId });
|
|
2696
|
-
if (progress.commentaryProgressEnabled) {
|
|
2697
|
-
const accepted = await progress.progressDraft.pushCommentaryProgress(payload.progressText, { itemId: payload.itemId });
|
|
2698
|
-
if (accepted) progress.progressReceipt.noteCommentary(payload.itemId, payload.progressText);
|
|
2699
|
-
return accepted || headlineVisible;
|
|
2700
|
-
}
|
|
2683
|
+
if (progress.commentaryProgressEnabled) return await progress.progressDraft.pushCommentaryProgress(payload.progressText, { itemId: payload.itemId }) || headlineVisible;
|
|
2701
2684
|
return headlineVisible;
|
|
2702
2685
|
}
|
|
2703
2686
|
return await progress.progressDraft.pushItemEvent(payload);
|
|
@@ -2719,8 +2702,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2719
2702
|
});
|
|
2720
2703
|
if (turnResult.dispatched) {
|
|
2721
2704
|
const result = turnResult.dispatchResult;
|
|
2722
|
-
|
|
2723
|
-
counts = result.counts;
|
|
2705
|
+
settledDispatchResult = result;
|
|
2724
2706
|
const agentRunOutcome = readAgentRunTerminalOutcome(result);
|
|
2725
2707
|
agentRunFailed = agentRunOutcome === "failed";
|
|
2726
2708
|
if (agentRunOutcome === "completed" && !sawTerminalFailurePayload && prepared.ctxPayload.ChatType === "channel") clearSlackThreadFailureNotice({
|
|
@@ -2759,12 +2741,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2759
2741
|
if (!finalStream.delivered) dispatchError ??= err;
|
|
2760
2742
|
}
|
|
2761
2743
|
}
|
|
2762
|
-
|
|
2763
|
-
queuedFinal = queuedFinal && (counts.final ?? 0) > 0;
|
|
2764
|
-
const anyReplyDelivered = hasVisibleInboundReplyDispatch({
|
|
2765
|
-
queuedFinal,
|
|
2766
|
-
counts
|
|
2767
|
-
}, {
|
|
2744
|
+
const anyReplyDelivered = hasVisibleInboundReplyDispatch(settledDispatchResult, {
|
|
2768
2745
|
observedReplyDelivery: delivery.observedReplyDelivery,
|
|
2769
2746
|
fallbackDelivered: streamFallbackDelivered
|
|
2770
2747
|
});
|
|
@@ -2786,11 +2763,11 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2786
2763
|
if (dispatchError) throw toErrorObject(dispatchError, "Slack dispatch failed");
|
|
2787
2764
|
if (!anyReplyDelivered && !draftPreviewCommitted.value && !(agentRunFailed && progress.useDraftProgressCard)) {
|
|
2788
2765
|
await draftStream?.clear();
|
|
2789
|
-
await
|
|
2766
|
+
await draftStream?.dropDetachedMessages();
|
|
2790
2767
|
return;
|
|
2791
2768
|
}
|
|
2792
2769
|
if (shouldLogVerbose()) {
|
|
2793
|
-
const finalCount =
|
|
2770
|
+
const finalCount = resolveInboundReplyDispatchCounts(settledDispatchResult).final;
|
|
2794
2771
|
logVerbose(`slack: delivered ${finalCount} reply${finalCount === 1 ? "" : "ies"} to ${prepared.replyTarget}`);
|
|
2795
2772
|
}
|
|
2796
2773
|
}
|
|
@@ -2834,6 +2811,153 @@ function normalizeSlackAppContextEntities(value) {
|
|
|
2834
2811
|
});
|
|
2835
2812
|
}
|
|
2836
2813
|
//#endregion
|
|
2814
|
+
//#region extensions/slack/src/monitor/thread.ts
|
|
2815
|
+
const THREAD_STARTER_CACHE = /* @__PURE__ */ new Map();
|
|
2816
|
+
const THREAD_STARTER_CACHE_TTL_MS = 360 * 6e4;
|
|
2817
|
+
const THREAD_STARTER_CACHE_MAX = 2e3;
|
|
2818
|
+
function evictThreadStarterCache() {
|
|
2819
|
+
const now = asDateTimestampMs(Date.now());
|
|
2820
|
+
if (now === void 0) {
|
|
2821
|
+
THREAD_STARTER_CACHE.clear();
|
|
2822
|
+
return;
|
|
2823
|
+
}
|
|
2824
|
+
for (const [cacheKey, entry] of THREAD_STARTER_CACHE.entries()) if (asDateTimestampMs(entry.expiresAt) === void 0 || entry.expiresAt <= now) THREAD_STARTER_CACHE.delete(cacheKey);
|
|
2825
|
+
pruneMapToMaxSize(THREAD_STARTER_CACHE, THREAD_STARTER_CACHE_MAX);
|
|
2826
|
+
}
|
|
2827
|
+
function formatSlackFilePlaceholder(files) {
|
|
2828
|
+
return `[attached: ${formatSlackFileReferenceList(files)}]`;
|
|
2829
|
+
}
|
|
2830
|
+
function pushUniqueText(parts, value, options = {}) {
|
|
2831
|
+
const text = options.preserveWhitespace ? typeof value === "string" && value.trim().length > 0 ? value : void 0 : normalizeOptionalString(value);
|
|
2832
|
+
if (text && !parts.includes(text)) parts.push(text);
|
|
2833
|
+
}
|
|
2834
|
+
function resolveSlackBlocksFallbackText(blocks) {
|
|
2835
|
+
return resolveSlackBlocksText(blocks)?.text;
|
|
2836
|
+
}
|
|
2837
|
+
function resolveSlackAttachmentFallbackText(attachments) {
|
|
2838
|
+
if (!Array.isArray(attachments) || attachments.length === 0) return;
|
|
2839
|
+
const parts = [];
|
|
2840
|
+
for (const attachment of attachments) {
|
|
2841
|
+
const excludeTableBlocks = isSlackUnfurlAttachment(attachment);
|
|
2842
|
+
const fallbackBlocks = (blocks) => excludeTableBlocks ? blocks?.filter((block) => !hasSlackTableBlock([block])) : blocks;
|
|
2843
|
+
pushUniqueText(parts, attachment.pretext);
|
|
2844
|
+
pushUniqueText(parts, attachment.title);
|
|
2845
|
+
pushUniqueText(parts, attachment.text);
|
|
2846
|
+
if (!(hasSlackTableBlock(attachment.blocks) && normalizeOptionalString(attachment.fallback) === "[no preview available]")) pushUniqueText(parts, attachment.fallback);
|
|
2847
|
+
for (const field of attachment.fields ?? []) {
|
|
2848
|
+
pushUniqueText(parts, field.title);
|
|
2849
|
+
pushUniqueText(parts, field.value);
|
|
2850
|
+
}
|
|
2851
|
+
pushUniqueText(parts, resolveSlackBlocksFallbackText(fallbackBlocks(attachment.blocks)), { preserveWhitespace: true });
|
|
2852
|
+
pushUniqueText(parts, resolveSlackBlocksFallbackText(fallbackBlocks(attachment.message_blocks)), { preserveWhitespace: true });
|
|
2853
|
+
}
|
|
2854
|
+
return parts.length > 0 ? parts.join("\n") : void 0;
|
|
2855
|
+
}
|
|
2856
|
+
function resolveSlackMessageText(message) {
|
|
2857
|
+
const messageText = normalizeOptionalString(message.text) ?? resolveSlackAttachmentFallbackText(message.attachments);
|
|
2858
|
+
return resolveSlackMessageText$1({
|
|
2859
|
+
...message,
|
|
2860
|
+
text: messageText
|
|
2861
|
+
}, { preserveMessageTextWhitespace: true });
|
|
2862
|
+
}
|
|
2863
|
+
async function resolveSlackThreadStarter(params) {
|
|
2864
|
+
evictThreadStarterCache();
|
|
2865
|
+
const cacheKey = JSON.stringify([
|
|
2866
|
+
params.workspaceScope.accountId,
|
|
2867
|
+
params.workspaceScope.teamId,
|
|
2868
|
+
params.channelId,
|
|
2869
|
+
params.threadTs
|
|
2870
|
+
]);
|
|
2871
|
+
const cached = THREAD_STARTER_CACHE.get(cacheKey);
|
|
2872
|
+
if (cached) {
|
|
2873
|
+
const now = asDateTimestampMs(Date.now());
|
|
2874
|
+
if (now !== void 0 && cached.expiresAt > now) return cached.value;
|
|
2875
|
+
THREAD_STARTER_CACHE.delete(cacheKey);
|
|
2876
|
+
}
|
|
2877
|
+
try {
|
|
2878
|
+
const message = (await params.client.conversations.replies({
|
|
2879
|
+
channel: params.channelId,
|
|
2880
|
+
ts: params.threadTs,
|
|
2881
|
+
limit: 1,
|
|
2882
|
+
inclusive: true
|
|
2883
|
+
}))?.messages?.[0];
|
|
2884
|
+
const text = message ? resolveSlackMessageText(message) : void 0;
|
|
2885
|
+
const files = message?.files?.length ? message.files : void 0;
|
|
2886
|
+
if (!message || !text && !files) return null;
|
|
2887
|
+
const starter = {
|
|
2888
|
+
text: text || formatSlackFilePlaceholder(files),
|
|
2889
|
+
userId: message.user,
|
|
2890
|
+
botId: message.bot_id,
|
|
2891
|
+
ts: message.ts,
|
|
2892
|
+
files
|
|
2893
|
+
};
|
|
2894
|
+
const expiresAt = resolveExpiresAtMsFromDurationMs(THREAD_STARTER_CACHE_TTL_MS);
|
|
2895
|
+
if (expiresAt !== void 0) {
|
|
2896
|
+
if (THREAD_STARTER_CACHE.has(cacheKey)) THREAD_STARTER_CACHE.delete(cacheKey);
|
|
2897
|
+
THREAD_STARTER_CACHE.set(cacheKey, {
|
|
2898
|
+
value: starter,
|
|
2899
|
+
expiresAt
|
|
2900
|
+
});
|
|
2901
|
+
evictThreadStarterCache();
|
|
2902
|
+
}
|
|
2903
|
+
return starter;
|
|
2904
|
+
} catch (err) {
|
|
2905
|
+
logVerbose$1(`slack thread starter fetch failed channel=${params.channelId} ts=${params.threadTs}: ${formatErrorMessage(err)}`);
|
|
2906
|
+
return null;
|
|
2907
|
+
}
|
|
2908
|
+
}
|
|
2909
|
+
const SLACK_THREAD_HISTORY_MAX_PAGES = 3;
|
|
2910
|
+
/**
|
|
2911
|
+
* Fetches the most recent messages in a Slack thread (excluding the current message).
|
|
2912
|
+
* Used to populate thread context when a new thread session starts.
|
|
2913
|
+
*
|
|
2914
|
+
* Uses cursor pagination and keeps only the latest N retained messages when the full
|
|
2915
|
+
* thread fits in the bounded fetch window.
|
|
2916
|
+
*/
|
|
2917
|
+
async function resolveSlackThreadHistory(params) {
|
|
2918
|
+
const maxMessages = params.limit ?? 20;
|
|
2919
|
+
if (!Number.isFinite(maxMessages) || maxMessages <= 0) return [];
|
|
2920
|
+
const fetchLimit = 200;
|
|
2921
|
+
const retained = [];
|
|
2922
|
+
let cursor;
|
|
2923
|
+
let pagesFetched = 0;
|
|
2924
|
+
try {
|
|
2925
|
+
do {
|
|
2926
|
+
pagesFetched += 1;
|
|
2927
|
+
const response = await params.client.conversations.replies({
|
|
2928
|
+
channel: params.channelId,
|
|
2929
|
+
ts: params.threadTs,
|
|
2930
|
+
limit: fetchLimit,
|
|
2931
|
+
inclusive: true,
|
|
2932
|
+
...cursor ? { cursor } : {}
|
|
2933
|
+
});
|
|
2934
|
+
for (const msg of response.messages ?? []) {
|
|
2935
|
+
const text = resolveSlackMessageText(msg);
|
|
2936
|
+
if (!text && !msg.files?.length) continue;
|
|
2937
|
+
if (params.currentMessageTs && msg.ts === params.currentMessageTs) continue;
|
|
2938
|
+
retained.push([msg, text]);
|
|
2939
|
+
}
|
|
2940
|
+
if (retained.length > maxMessages) retained.splice(0, retained.length - maxMessages);
|
|
2941
|
+
const next = response.response_metadata?.next_cursor;
|
|
2942
|
+
cursor = typeof next === "string" && next.trim().length > 0 ? next.trim() : void 0;
|
|
2943
|
+
} while (cursor && pagesFetched < SLACK_THREAD_HISTORY_MAX_PAGES);
|
|
2944
|
+
if (cursor) {
|
|
2945
|
+
logVerbose$1(`slack thread history capped channel=${params.channelId} ts=${params.threadTs} pages=${SLACK_THREAD_HISTORY_MAX_PAGES}`);
|
|
2946
|
+
return [];
|
|
2947
|
+
}
|
|
2948
|
+
return retained.map(([message, text]) => ({
|
|
2949
|
+
text: text ?? formatSlackFilePlaceholder(message.files),
|
|
2950
|
+
userId: message.user,
|
|
2951
|
+
botId: message.bot_id,
|
|
2952
|
+
ts: message.ts,
|
|
2953
|
+
files: message.files
|
|
2954
|
+
}));
|
|
2955
|
+
} catch (err) {
|
|
2956
|
+
logVerbose$1(`slack thread history fetch failed channel=${params.channelId} ts=${params.threadTs}: ${formatErrorMessage(err)}`);
|
|
2957
|
+
return [];
|
|
2958
|
+
}
|
|
2959
|
+
}
|
|
2960
|
+
//#endregion
|
|
2837
2961
|
//#region extensions/slack/src/monitor/message-handler/preflight-audio.ts
|
|
2838
2962
|
function isSlackAudioFile(file) {
|
|
2839
2963
|
if (file.subtype === "slack_audio") return true;
|
|
@@ -2849,7 +2973,7 @@ function findCaptionlessSlackAudioFile(message) {
|
|
|
2849
2973
|
return message.files?.slice(0, 8).find(isSlackAudioFile);
|
|
2850
2974
|
}
|
|
2851
2975
|
function formatSlackAudioTranscriptForAgent(params) {
|
|
2852
|
-
return [
|
|
2976
|
+
return [formatAudioTranscriptForAgent(params.transcript), params.rawBody].filter(Boolean).join("\n");
|
|
2853
2977
|
}
|
|
2854
2978
|
async function resolveSlackPreflightAudioTranscript(params) {
|
|
2855
2979
|
const mediaIndex = params.media.findIndex((entry) => entry.contentType?.toLowerCase().startsWith("audio/"));
|
|
@@ -2884,7 +3008,7 @@ async function discardSlackPreflightMedia(media) {
|
|
|
2884
3008
|
const SLACK_MENTION_RESOLUTION_CONCURRENCY = 4;
|
|
2885
3009
|
const SLACK_MENTION_RESOLUTION_MAX_LOOKUPS_PER_MESSAGE = 20;
|
|
2886
3010
|
const SLACK_USER_MENTION_RE$1 = /<@([A-Z0-9]+)(?:\|[^>]+)?>/gi;
|
|
2887
|
-
const loadSlackMediaModule$1 = createLazyRuntimeModule(() => import("./actions-
|
|
3011
|
+
const loadSlackMediaModule$1 = createLazyRuntimeModule(() => import("./actions-DFk0ANVB.js").then((n) => n._));
|
|
2888
3012
|
function collectUniqueSlackMentionIds$1(texts) {
|
|
2889
3013
|
const seen = /* @__PURE__ */ new Set();
|
|
2890
3014
|
const mentionIds = [];
|
|
@@ -2965,7 +3089,7 @@ async function resolveSlackMessageContent(params) {
|
|
|
2965
3089
|
botAttachmentText = botAttachmentTextParts.length > 0 ? botAttachmentTextParts.join("\n") : void 0;
|
|
2966
3090
|
}
|
|
2967
3091
|
const textParts = [
|
|
2968
|
-
resolveSlackMessageText(params.message),
|
|
3092
|
+
resolveSlackMessageText$1(params.message),
|
|
2969
3093
|
attachmentContent?.text,
|
|
2970
3094
|
botAttachmentText
|
|
2971
3095
|
];
|
|
@@ -3083,62 +3207,6 @@ async function resolveSlackDmHistoryContext(params) {
|
|
|
3083
3207
|
}
|
|
3084
3208
|
//#endregion
|
|
3085
3209
|
//#region extensions/slack/src/monitor/message-handler/prepare-routing.ts
|
|
3086
|
-
const slackRouteBindingConfigCache = /* @__PURE__ */ new WeakMap();
|
|
3087
|
-
function slackTargetDefaultKindForPeer(kind) {
|
|
3088
|
-
return kind === "direct" ? "user" : "channel";
|
|
3089
|
-
}
|
|
3090
|
-
function slackTargetKindMatchesPeer(peerKind, targetKind) {
|
|
3091
|
-
if (targetKind === "user") return peerKind === "direct";
|
|
3092
|
-
return peerKind === "channel" || peerKind === "group";
|
|
3093
|
-
}
|
|
3094
|
-
function normalizeSlackRouteBindingPeer(peer) {
|
|
3095
|
-
const rawId = peer.id.trim();
|
|
3096
|
-
if (!rawId || rawId === "*") return peer;
|
|
3097
|
-
const target = (() => {
|
|
3098
|
-
try {
|
|
3099
|
-
return parseSlackTarget(rawId, { defaultKind: slackTargetDefaultKindForPeer(peer.kind) });
|
|
3100
|
-
} catch {
|
|
3101
|
-
return;
|
|
3102
|
-
}
|
|
3103
|
-
})();
|
|
3104
|
-
if (!target || !slackTargetKindMatchesPeer(peer.kind, target.kind)) return peer;
|
|
3105
|
-
const normalizedId = target.teamId ? `team:${target.teamId}:${target.kind}:${target.id}` : target.id;
|
|
3106
|
-
return normalizedId === peer.id ? peer : {
|
|
3107
|
-
...peer,
|
|
3108
|
-
id: normalizedId
|
|
3109
|
-
};
|
|
3110
|
-
}
|
|
3111
|
-
function normalizeSlackRouteBindingConfig(cfg) {
|
|
3112
|
-
const bindings = cfg.bindings;
|
|
3113
|
-
const cached = slackRouteBindingConfigCache.get(cfg);
|
|
3114
|
-
if (cached && cached.bindingsRef === bindings) return cached.normalizedCfg;
|
|
3115
|
-
if (!Array.isArray(bindings)) return cfg;
|
|
3116
|
-
let changed = false;
|
|
3117
|
-
const normalizedBindings = bindings.map((binding) => {
|
|
3118
|
-
if (binding.type === "acp" || binding.match.channel.trim().toLowerCase() !== "slack") return binding;
|
|
3119
|
-
const peer = binding.match.peer;
|
|
3120
|
-
if (!peer) return binding;
|
|
3121
|
-
const normalizedPeer = normalizeSlackRouteBindingPeer(peer);
|
|
3122
|
-
if (normalizedPeer === peer) return binding;
|
|
3123
|
-
changed = true;
|
|
3124
|
-
return {
|
|
3125
|
-
...binding,
|
|
3126
|
-
match: {
|
|
3127
|
-
...binding.match,
|
|
3128
|
-
peer: normalizedPeer
|
|
3129
|
-
}
|
|
3130
|
-
};
|
|
3131
|
-
});
|
|
3132
|
-
const normalizedCfg = changed ? {
|
|
3133
|
-
...cfg,
|
|
3134
|
-
bindings: normalizedBindings
|
|
3135
|
-
} : cfg;
|
|
3136
|
-
slackRouteBindingConfigCache.set(cfg, {
|
|
3137
|
-
bindingsRef: bindings,
|
|
3138
|
-
normalizedCfg
|
|
3139
|
-
});
|
|
3140
|
-
return normalizedCfg;
|
|
3141
|
-
}
|
|
3142
3210
|
function resolveSlackBaseConversationId(params) {
|
|
3143
3211
|
return qualifySlackConversationId(params.isDirectMessage ? `user:${params.message.user ?? "unknown"}` : params.message.channel, params.eventScope);
|
|
3144
3212
|
}
|
|
@@ -3197,44 +3265,18 @@ function resolveSlackRoutingContext(params) {
|
|
|
3197
3265
|
eventScope
|
|
3198
3266
|
});
|
|
3199
3267
|
const runtimeBindingThreadId = routedThreadId ?? (isDirectMessage && isThreadReply ? threadTs : void 0);
|
|
3200
|
-
const
|
|
3201
|
-
|
|
3202
|
-
conversation: {
|
|
3203
|
-
channel: "slack",
|
|
3204
|
-
accountId: account.accountId,
|
|
3205
|
-
conversationId: runtimeBindingThreadId,
|
|
3206
|
-
parentConversationId: baseConversationId
|
|
3207
|
-
}
|
|
3208
|
-
}) : null;
|
|
3209
|
-
const runtimeRoute = eventScope ? {
|
|
3210
|
-
route,
|
|
3211
|
-
bindingRecord: null,
|
|
3212
|
-
boundSessionKey: void 0
|
|
3213
|
-
} : boundThreadRoute?.boundSessionKey || boundThreadRoute?.bindingRecord ? boundThreadRoute : resolveRuntimeConversationBindingRoute({
|
|
3268
|
+
const bindingRoute = resolveSlackConversationBindingRoute({
|
|
3269
|
+
cfg: ctx.cfg,
|
|
3214
3270
|
route,
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
}
|
|
3271
|
+
accountId: account.accountId,
|
|
3272
|
+
baseConversationId,
|
|
3273
|
+
runtimeBindingThreadId,
|
|
3274
|
+
bindingsEnabled: !eventScope
|
|
3220
3275
|
});
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
const configuredRoute = resolveConfiguredBindingRoute({
|
|
3226
|
-
cfg: ctx.cfg,
|
|
3227
|
-
route,
|
|
3228
|
-
conversation: {
|
|
3229
|
-
channel: "slack",
|
|
3230
|
-
accountId: account.accountId,
|
|
3231
|
-
conversationId: baseConversationId
|
|
3232
|
-
}
|
|
3233
|
-
});
|
|
3234
|
-
configuredBinding = configuredRoute.bindingResolution;
|
|
3235
|
-
configuredBindingSessionKey = configuredRoute.boundSessionKey ?? "";
|
|
3236
|
-
route = configuredRoute.route;
|
|
3237
|
-
}
|
|
3276
|
+
const runtimeRoute = bindingRoute.runtimeRoute;
|
|
3277
|
+
const configuredBinding = bindingRoute.configuredRoute?.bindingResolution ?? null;
|
|
3278
|
+
const configuredBindingSessionKey = bindingRoute.configuredRoute?.boundSessionKey ?? "";
|
|
3279
|
+
route = bindingRoute.route;
|
|
3238
3280
|
const threadKeys = runtimeRoute.boundSessionKey || configuredBindingSessionKey ? {
|
|
3239
3281
|
sessionKey: route.sessionKey,
|
|
3240
3282
|
parentSessionKey: void 0
|
|
@@ -3317,7 +3359,7 @@ function formatSlackThreadLabelSnippet(text) {
|
|
|
3317
3359
|
}
|
|
3318
3360
|
//#endregion
|
|
3319
3361
|
//#region extensions/slack/src/monitor/message-handler/prepare-thread-context.ts
|
|
3320
|
-
const loadSlackMediaModule = createLazyRuntimeModule(() => import("./actions-
|
|
3362
|
+
const loadSlackMediaModule = createLazyRuntimeModule(() => import("./actions-DFk0ANVB.js").then((n) => n._));
|
|
3321
3363
|
const SLACK_THREAD_CONTEXT_USER_LOOKUP_CONCURRENCY = 4;
|
|
3322
3364
|
function resolveSlackThreadSessionFreshness(params) {
|
|
3323
3365
|
return params.ctx.channelRuntime?.session?.resolveEntryResetFreshness?.({
|
|
@@ -4468,6 +4510,7 @@ async function prepareSlackMessage(params) {
|
|
|
4468
4510
|
workspaceName
|
|
4469
4511
|
}) : void 0;
|
|
4470
4512
|
const senderName = await resolveSenderName();
|
|
4513
|
+
const conversationAvatar = isDirectMessage && message.user ? ctx.resolveUserAvatar(message.user, opts.eventScope) : void 0;
|
|
4471
4514
|
const preview = truncateUtf16Safe(bodyForAgent.replace(/\s+/g, " "), 160);
|
|
4472
4515
|
const inboundLabel = isDirectMessage ? `Slack DM from ${senderName}` : `Slack message in ${roomLabel} from ${senderName}`;
|
|
4473
4516
|
const slackFrom = isDirectMessage ? `slack:${message.user}` : isRoom ? `slack:channel:${message.channel}` : `slack:group:${message.channel}`;
|
|
@@ -4600,10 +4643,19 @@ async function prepareSlackMessage(params) {
|
|
|
4600
4643
|
conversation: {
|
|
4601
4644
|
kind: chatType,
|
|
4602
4645
|
id: message.channel,
|
|
4646
|
+
routePeer: {
|
|
4647
|
+
kind: chatType,
|
|
4648
|
+
id: qualifySlackRoutePeerId({
|
|
4649
|
+
id: isDirectMessage ? message.user ?? "unknown" : message.channel,
|
|
4650
|
+
kind: isDirectMessage ? "user" : "channel",
|
|
4651
|
+
eventScope: opts.eventScope
|
|
4652
|
+
})
|
|
4653
|
+
},
|
|
4603
4654
|
label: envelopeFrom,
|
|
4604
4655
|
spaceId: opts.eventScope?.teamId || ctx.teamId || void 0,
|
|
4605
4656
|
threadId: boundMessageThreadId,
|
|
4606
|
-
nativeChannelId: message.channel
|
|
4657
|
+
nativeChannelId: message.channel,
|
|
4658
|
+
avatar: conversationAvatar
|
|
4607
4659
|
},
|
|
4608
4660
|
route: {
|
|
4609
4661
|
agentId: route.agentId,
|