@openclaw/slack 2026.7.2-beta.2 → 2026.7.2-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/{account-configured-DzC407uv.js → account-configured-BwfXBo_F.js} +1 -1
- package/dist/account-inspect-api.js +1 -1
- package/dist/{account-inspect-Di7ditqZ.js → account-inspect-jn1xLaVi.js} +9 -2
- package/dist/account-reply-mode-DrUXogvO.js +14 -0
- package/dist/{accounts-BOJJiHSr.js → accounts-BSr252c_.js} +13 -25
- package/dist/accounts.runtime-CjULMLTa.js +2 -0
- package/dist/{action-runtime-Cee2ih0s.js → action-runtime-CFU52n4W.js} +11 -17
- package/dist/action-runtime.runtime-9-17zvKH.js +2 -0
- package/dist/{actions-BZiuSTIq.js → actions-D51foiwR.js} +5 -5
- package/dist/{actions.runtime-DoD0-gxw.js → actions.runtime-BMJwtf5C.js} +1 -1
- package/dist/api.js +15 -15
- package/dist/{approval-handler.runtime-CUPtIM4k.js → approval-handler.runtime-3b4-wxMl.js} +2 -2
- package/dist/{channel-DaIiGUOp.js → channel-Ds8NKvfr.js} +75 -41
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-type-Cfm6_6n1.js → channel-type-DXkUajFP.js} +3 -3
- package/dist/{channel.setup-C-mLz50O.js → channel.setup-DOSTEDfA.js} +8 -5
- package/dist/{config-schema-xPSnK2VK.js → config-schema-B4j4tCOI.js} +236 -30
- package/dist/{directory-config-DRkFujwG.js → directory-config-B08pm5ZT.js} +1 -1
- package/dist/directory-contract-api.js +1 -1
- package/dist/{directory-live-D_yZhjgp.js → directory-live-DpPKzPrn.js} +2 -2
- package/dist/doctor-contract-U6oVntbM.js +173 -0
- package/dist/doctor-contract-api.js +1 -1
- package/dist/{group-policy-85UWiriS.js → group-policy-CdnQzQBI.js} +98 -125
- package/dist/{interactive-replies-BilWUdcI.js → interactive-replies-C3ffk6oN.js} +1 -1
- package/dist/interactive-replies-api.js +1 -1
- package/dist/{message-tool-api-CA9jZrCY.js → message-tool-api-ByVyIVOh.js} +3 -3
- package/dist/message-tool-api.js +1 -1
- package/dist/{monitor-CalGciTs.js → monitor-CnB_WKvF.js} +3 -3
- package/dist/{outbound-adapter-BiLKcnyH.js → outbound-adapter-DuPz2HHt.js} +49 -5
- package/dist/{pipeline.runtime-DofAvTtb.js → pipeline.runtime-5rRYZuX5.js} +490 -345
- package/dist/{policy-BVs4LiSa.js → policy-C31RYSuT.js} +1 -1
- package/dist/probe-CVRuArHA.js +340 -0
- package/dist/{provider-CmeoUiIM.js → provider-htuIJGFD.js} +791 -359
- package/dist/{relay-source-DMmgtvg4.js → relay-source-Df9EaiTF.js} +6 -11
- package/dist/{replies-CJJCp6qz.js → replies-Cgr2Gli4.js} +3 -3
- package/dist/{resolve-channels-Rfts6POK.js → resolve-channels-DodP2TFx.js} +1 -1
- package/dist/{resolve-users-y6wAxR8E.js → resolve-users-M9eF8891.js} +1 -1
- package/dist/{runtime-api-BGDyOt1D.js → runtime-api-D5XYMMsf.js} +3 -2
- package/dist/runtime-api.js +11 -11
- package/dist/{scopes-CuxNQZ6v.js → scopes-CJRpHkDC.js} +1 -2
- package/dist/{secret-contract-CMohXFWS.js → secret-contract-DxmvbxBF.js} +1 -0
- package/dist/secret-contract-api.js +1 -1
- package/dist/{security-audit-CikQhBUY.js → security-audit-Cz6erklv.js} +0 -10
- package/dist/security-contract-api.js +1 -1
- package/dist/{send-DYp8ca-l.js → send-BZ1tPv7-.js} +28 -11
- package/dist/send.runtime-a2pilFor.js +2 -0
- package/dist/setup-core-tPxMuFez.js +600 -0
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-oSd3NX9J.js → setup-surface-wV-S1dE_.js} +58 -32
- package/dist/{shared-D9yz5Otg.js → shared-BfMskaMx.js} +57 -10
- package/dist/{slash-dispatch.runtime-CSja9VuD.js → slash-dispatch.runtime-lfeIsXTX.js} +1 -1
- package/node_modules/@types/node/README.md +1 -1
- package/node_modules/@types/node/fs/promises.d.ts +16 -6
- package/node_modules/@types/node/package.json +2 -2
- package/node_modules/agent-base/README.md +145 -0
- package/node_modules/agent-base/dist/src/index.d.ts +78 -0
- package/node_modules/agent-base/dist/src/index.js +203 -0
- package/node_modules/agent-base/dist/src/index.js.map +1 -0
- package/node_modules/agent-base/dist/src/promisify.d.ts +4 -0
- package/node_modules/agent-base/dist/src/promisify.js +18 -0
- package/node_modules/agent-base/dist/src/promisify.js.map +1 -0
- package/node_modules/agent-base/package.json +64 -0
- package/node_modules/agent-base/src/index.ts +345 -0
- package/node_modules/agent-base/src/promisify.ts +33 -0
- package/node_modules/axios/CHANGELOG.md +197 -1
- package/node_modules/axios/README.md +424 -256
- package/node_modules/axios/dist/axios.js +589 -204
- package/node_modules/axios/dist/axios.min.js +3 -3
- package/node_modules/axios/dist/axios.min.js.map +1 -1
- package/node_modules/axios/dist/browser/axios.cjs +630 -185
- package/node_modules/axios/dist/esm/axios.js +630 -185
- package/node_modules/axios/dist/esm/axios.min.js +2 -2
- package/node_modules/axios/dist/esm/axios.min.js.map +1 -1
- package/node_modules/axios/dist/node/axios.cjs +949 -301
- package/node_modules/axios/index.d.cts +28 -5
- package/node_modules/axios/index.d.ts +24 -3
- package/node_modules/axios/lib/adapters/adapters.js +1 -1
- package/node_modules/axios/lib/adapters/fetch.js +223 -49
- package/node_modules/axios/lib/adapters/http.js +408 -193
- package/node_modules/axios/lib/adapters/xhr.js +3 -1
- package/node_modules/axios/lib/core/Axios.js +4 -2
- package/node_modules/axios/lib/core/AxiosError.js +13 -1
- package/node_modules/axios/lib/core/AxiosHeaders.js +13 -42
- package/node_modules/axios/lib/core/buildFullPath.js +29 -1
- package/node_modules/axios/lib/core/mergeConfig.js +35 -0
- package/node_modules/axios/lib/defaults/transitional.js +2 -0
- package/node_modules/axios/lib/env/data.js +1 -1
- package/node_modules/axios/lib/helpers/AxiosURLSearchParams.js +1 -3
- package/node_modules/axios/lib/helpers/Http2Sessions.js +119 -0
- package/node_modules/axios/lib/helpers/buildURL.js +7 -4
- package/node_modules/axios/lib/helpers/composeSignals.js +48 -47
- package/node_modules/axios/lib/helpers/cookies.js +5 -1
- package/node_modules/axios/lib/helpers/estimateDataURLDecodedBytes.js +16 -11
- package/node_modules/axios/lib/helpers/formDataToJSON.js +26 -4
- package/node_modules/axios/lib/helpers/formDataToStream.js +2 -2
- package/node_modules/axios/lib/helpers/fromDataURI.js +20 -5
- package/node_modules/axios/lib/helpers/progressEventReducer.js +3 -0
- package/node_modules/axios/lib/helpers/resolveConfig.js +26 -13
- package/node_modules/axios/lib/helpers/sanitizeHeaderValue.js +60 -0
- package/node_modules/axios/lib/helpers/shouldBypassProxy.js +33 -1
- package/node_modules/axios/lib/helpers/toFormData.js +48 -12
- package/node_modules/axios/lib/helpers/validator.js +1 -1
- package/node_modules/axios/lib/utils.js +105 -19
- package/node_modules/axios/package.json +31 -13
- package/node_modules/https-proxy-agent/README.md +137 -0
- package/node_modules/https-proxy-agent/dist/agent.d.ts +30 -0
- package/node_modules/https-proxy-agent/dist/agent.js +177 -0
- package/node_modules/https-proxy-agent/dist/agent.js.map +1 -0
- package/node_modules/https-proxy-agent/dist/index.d.ts +23 -0
- package/node_modules/https-proxy-agent/dist/index.js +14 -0
- package/node_modules/https-proxy-agent/dist/index.js.map +1 -0
- package/node_modules/https-proxy-agent/dist/parse-proxy-response.d.ts +7 -0
- package/node_modules/https-proxy-agent/dist/parse-proxy-response.js +66 -0
- package/node_modules/https-proxy-agent/dist/parse-proxy-response.js.map +1 -0
- package/node_modules/https-proxy-agent/package.json +56 -0
- package/node_modules/iconv-lite/encodings/sbcs-data.js +2 -0
- package/node_modules/iconv-lite/encodings/utf32.js +10 -3
- package/node_modules/iconv-lite/package.json +2 -2
- package/node_modules/iconv-lite/types/encodings.d.ts +2 -0
- package/node_modules/path-to-regexp/Readme.md +3 -3
- package/node_modules/path-to-regexp/dist/index.js +135 -158
- package/node_modules/path-to-regexp/dist/index.js.map +1 -1
- package/node_modules/path-to-regexp/package.json +2 -2
- package/node_modules/qs/CHANGELOG.md +11 -0
- package/node_modules/qs/dist/qs.js +17 -17
- package/node_modules/qs/lib/parse.js +19 -8
- package/node_modules/qs/lib/utils.js +47 -8
- package/node_modules/qs/package.json +6 -5
- package/node_modules/qs/test/parse.js +230 -0
- package/node_modules/qs/test/utils.js +194 -0
- package/node_modules/typebox/build/compile/validator.d.mts +1 -4
- package/node_modules/typebox/build/guard/guard.d.mts +1 -1
- package/node_modules/typebox/build/guard/guard.mjs +5 -2
- package/node_modules/typebox/build/guard/string.mjs +16 -4
- package/node_modules/typebox/build/schema/engine/_functions.mjs +34 -15
- package/node_modules/typebox/build/type/action/readonly_object.d.mts +5 -0
- package/node_modules/typebox/build/type/action/readonly_object.mjs +8 -0
- package/node_modules/typebox/build/typebox.d.mts +1 -1
- package/node_modules/typebox/build/typebox.mjs +1 -1
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/typebox/readme.md +29 -32
- package/node_modules/ws/lib/receiver.js +15 -32
- package/node_modules/ws/lib/websocket-server.js +4 -4
- package/node_modules/ws/lib/websocket.js +4 -4
- package/node_modules/ws/package.json +5 -1
- package/npm-shrinkwrap.json +54 -27
- package/openclaw.plugin.json +1331 -1424
- package/package.json +92 -14
- package/dist/accounts.runtime-KvftRRek.js +0 -2
- package/dist/action-runtime.runtime-DZfd7IFr.js +0 -2
- package/dist/client-WIPAS3Yr.js +0 -160
- package/dist/config-api-Df9a1B8C.js +0 -3
- package/dist/doctor-contract-DddfkMlF.js +0 -134
- package/dist/probe-CN0ssfLN.js +0 -48
- package/dist/send.runtime-CJLxAt26.js +0 -2
- package/dist/setup-core-CkwVLzFO.js +0 -337
- package/node_modules/axios/dist/axios.js.map +0 -1
- package/node_modules/axios/dist/browser/axios.cjs.map +0 -1
- package/node_modules/axios/dist/esm/axios.js.map +0 -1
- package/node_modules/axios/dist/node/axios.cjs.map +0 -1
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { t as resolveSlackReplyToMode } from "./account-reply-mode-DrUXogvO.js";
|
|
2
2
|
import { i as parseSlackTarget } from "./target-parsing-N6lHogYZ.js";
|
|
3
3
|
import "./targets-KmjP2E8s.js";
|
|
4
|
-
import {
|
|
5
|
-
import { n as isSlackInteractiveRepliesEnabled, t as compileSlackInteractiveReplies } from "./interactive-replies-
|
|
4
|
+
import { C as hasSlackNativeDataBlock, F as SLACK_TEXT_LIMIT, N as SLACK_EDIT_TEXT_LIMIT, O as normalizeSlackOutboundText, Y as escapeSlackMrkdwn, _ as resolveSlackReplyRenderPlan, c as normalizeSlackAllowOwnerEntry, k as buildSlackBlocksFallbackText, s as normalizeAllowListLower, u as resolveSlackAllowListMatch, z as truncateSlackText } from "./group-policy-CdnQzQBI.js";
|
|
5
|
+
import { n as isSlackInteractiveRepliesEnabled, t as compileSlackInteractiveReplies } from "./interactive-replies-C3ffk6oN.js";
|
|
6
|
+
import { r as formatSlackError } from "./probe-CVRuArHA.js";
|
|
6
7
|
import { n as resolveSlackNativeStreaming, r as resolveSlackStreamingMode, t as mapStreamingModeToSlackLegacyDraftStreamMode } from "./streaming-compat-3_X-21wW.js";
|
|
7
|
-
import { S as buildSlackEditTextPayload, _ as resolveSlackThreadHistory, b as resolveSlackBlocksText, f as removeSlackReaction, l as reactSlackMessage, r as editSlackMessage, t as deleteSlackMessage, v as resolveSlackThreadStarter, x as formatSlackFileReference, y as chooseSlackPrimaryText } from "./actions-
|
|
8
|
-
import { c as
|
|
9
|
-
import {
|
|
10
|
-
import { n as resolveSlackChannelConfig } from "./policy-
|
|
11
|
-
import { a as resolveDeliveredSlackReplyThreadTs, i as readSlackReplyBlocks, n as deliverReplies, o as resolveSlackThreadTs, s as emitSlackMessageSentHooks, t as createSlackReplyDeliveryPlan } from "./replies-
|
|
8
|
+
import { S as buildSlackEditTextPayload, _ as resolveSlackThreadHistory, b as resolveSlackBlocksText, f as removeSlackReaction, l as reactSlackMessage, r as editSlackMessage, t as deleteSlackMessage, v as resolveSlackThreadStarter, x as formatSlackFileReference, y as chooseSlackPrimaryText } from "./actions-D51foiwR.js";
|
|
9
|
+
import { c as hasSlackThreadParticipationWithPersistence, l as recordSlackThreadParticipation, r as sendMessageSlack, u as buildSlackNativeDataDeliveryPlan } from "./send-BZ1tPv7-.js";
|
|
10
|
+
import { C as stripSlackMentionsForCommandDetection, _ as readSessionUpdatedAt, b as resolveStorePath, d as resolveSlackCommandIngress, f as resolveSlackEffectiveAllowFrom, g as resolveSlackChatType, h as normalizeSlackChannelType, l as resolveConversationLabel$1, m as parseSlackAssistantThreadMetadata, o as authorizeSlackDirectMessage, p as buildSlackAssistantThreadMetadata, r as resolveSlackRoomContextHints, u as authorizeSlackBotRoomMessage, v as resolveChannelContextVisibilityMode, x as updateLastRoute, y as resolveChannelResetConfig } from "./provider-htuIJGFD.js";
|
|
11
|
+
import { n as resolveSlackChannelConfig } from "./policy-C31RYSuT.js";
|
|
12
|
+
import { a as resolveDeliveredSlackReplyThreadTs, i as readSlackReplyBlocks, n as deliverReplies, o as resolveSlackThreadTs, s as emitSlackMessageSentHooks, t as createSlackReplyDeliveryPlan } from "./replies-Cgr2Gli4.js";
|
|
12
13
|
import { asOptionalRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
13
14
|
import { resolveAgentRoute, resolveInboundLastRouteSessionKey, resolveThreadSessionKeys } from "openclaw/plugin-sdk/routing";
|
|
14
|
-
import { buildChannelProgressDraftLine, buildChannelProgressDraftLineForEntry, createChannelMessageReplyPipeline,
|
|
15
|
+
import { buildChannelProgressDraftLine, buildChannelProgressDraftLineForEntry, createChannelMessageReplyPipeline, createChannelProgressDraftCompositor, createChannelProgressReceiptTracker, createDraftStreamLoop, defineFinalizableLivePreviewAdapter, deliverWithFinalizableLivePreviewAdapter, formatChannelProgressDraftText, formatPlanChecklistLines, isChannelProgressDraftWorkToolName, mergeChannelProgressDraftLine, resolveAgentOutboundIdentity, resolveChannelMessageSourceReplyDeliveryMode, resolveChannelProgressDraftConfig, resolveChannelProgressDraftMaxLineChars, resolveChannelProgressDraftMaxLines, resolveChannelProgressDraftRender, resolveChannelStreamingBlockEnabled, resolveChannelStreamingNativeTransport, resolveChannelStreamingPreviewToolProgress, resolveChannelStreamingSuppressDefaultToolProgressMessages } from "openclaw/plugin-sdk/channel-outbound";
|
|
15
16
|
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
16
|
-
import { danger, logVerbose, shouldLogVerbose
|
|
17
|
-
import { stripReasoningTagsFromText } from "openclaw/plugin-sdk/text-chunking";
|
|
17
|
+
import { danger, logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
|
|
18
18
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
19
19
|
import { createHash } from "node:crypto";
|
|
20
20
|
import fs from "node:fs/promises";
|
|
@@ -27,9 +27,9 @@ import { createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
|
|
|
27
27
|
import { resolveHumanDelayConfig } from "openclaw/plugin-sdk/agent-runtime";
|
|
28
28
|
import { mergePairLoopGuardConfig } from "openclaw/plugin-sdk/pair-loop-guard-runtime";
|
|
29
29
|
import { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
30
|
+
import { resolveChannelImplicitMentions } from "openclaw/plugin-sdk/channel-ingress-runtime";
|
|
31
|
+
import { buildChannelInboundEventContext, buildMentionRegexes, classifyChannelInboundEvent, dispatchChannelInboundTurn, formatInboundEnvelope, hasVisibleInboundReplyDispatch, implicitMentionKindWhen, logInboundDrop, matchesMentionWithExplicit, recordDroppedChannelInboundHistory, resolveEnvelopeFormatOptions, resolveInboundMentionDecision, resolveInboundSupplementalSenderAllowed, resolveUnmentionedGroupInboundPolicy, toInboundMediaFacts } from "openclaw/plugin-sdk/channel-inbound";
|
|
32
|
+
import { DEFAULT_TIMING, createStatusReactionController, logAckFailure, logTypingFailure, resolveAckReaction, shouldAckReaction } from "openclaw/plugin-sdk/channel-feedback";
|
|
33
33
|
import { hasControlCommand } from "openclaw/plugin-sdk/command-detection";
|
|
34
34
|
import { isAbortRequestText } from "openclaw/plugin-sdk/command-primitives-runtime";
|
|
35
35
|
import { shouldHandleTextCommands } from "openclaw/plugin-sdk/command-surface";
|
|
@@ -216,9 +216,24 @@ function lineTaskStatus(line) {
|
|
|
216
216
|
function slugTaskIdPart(value) {
|
|
217
217
|
return value?.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "") || "task";
|
|
218
218
|
}
|
|
219
|
-
function stableTaskIdPart(value) {
|
|
219
|
+
function stableTaskIdPart(value, slugValue = value) {
|
|
220
220
|
const suffix = createHash("sha256").update(value).digest("hex").slice(0, 8);
|
|
221
|
-
return `${slugTaskIdPart(
|
|
221
|
+
return `${slugTaskIdPart(slugValue).slice(0, 48)}_${suffix}`;
|
|
222
|
+
}
|
|
223
|
+
function resolveLineTaskIdentity(line) {
|
|
224
|
+
if (line.id?.trim()) return {
|
|
225
|
+
id: stableTaskIdPart(line.id),
|
|
226
|
+
contentDerived: false
|
|
227
|
+
};
|
|
228
|
+
return {
|
|
229
|
+
id: stableTaskIdPart([
|
|
230
|
+
line.kind,
|
|
231
|
+
line.toolName,
|
|
232
|
+
line.label,
|
|
233
|
+
line.text
|
|
234
|
+
].join("\0"), line.toolName ?? line.kind ?? line.label),
|
|
235
|
+
contentDerived: true
|
|
236
|
+
};
|
|
222
237
|
}
|
|
223
238
|
function buildPlanTasks(params) {
|
|
224
239
|
if (params.plan) return params.plan.slice(-50).map((entry, index) => ({
|
|
@@ -227,11 +242,23 @@ function buildPlanTasks(params) {
|
|
|
227
242
|
status: entry.status === "completed" ? "complete" : entry.status
|
|
228
243
|
}));
|
|
229
244
|
const maxLineChars = resolveMaxLineChars(params.maxLineChars, DEFAULT_SLACK_PROGRESS_TASK_DETAIL_MAX_CHARS);
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
245
|
+
const lines = params.lines.slice(-50);
|
|
246
|
+
const identities = lines.map(resolveLineTaskIdentity);
|
|
247
|
+
const contentIdOccurrences = /* @__PURE__ */ new Map();
|
|
248
|
+
return lines.map((line, index) => {
|
|
249
|
+
const identity = identities[index];
|
|
250
|
+
let id = identity.id;
|
|
251
|
+
if (identity.contentDerived) {
|
|
252
|
+
const occurrence = (contentIdOccurrences.get(id) ?? 0) + 1;
|
|
253
|
+
contentIdOccurrences.set(id, occurrence);
|
|
254
|
+
id = `${id}_${occurrence}`;
|
|
255
|
+
}
|
|
256
|
+
return {
|
|
257
|
+
id,
|
|
258
|
+
title: lineTaskTitle(line, maxLineChars),
|
|
259
|
+
status: lineTaskStatus(line)
|
|
260
|
+
};
|
|
261
|
+
});
|
|
235
262
|
}
|
|
236
263
|
function resolvePlanTitle(params) {
|
|
237
264
|
return compactChunkText(params.title?.trim() || params.label?.trim() || params.tasks.at(-1)?.title || SLACK_PROGRESS_PLAN_FALLBACK_TITLE);
|
|
@@ -242,7 +269,13 @@ function buildSlackProgressStreamChunks(params) {
|
|
|
242
269
|
plan: params.plan,
|
|
243
270
|
maxLineChars: params.maxLineChars
|
|
244
271
|
});
|
|
245
|
-
if (tasks.length === 0)
|
|
272
|
+
if (tasks.length === 0) {
|
|
273
|
+
const title = params.title?.trim() || params.label?.trim();
|
|
274
|
+
return title ? [{
|
|
275
|
+
type: "plan_update",
|
|
276
|
+
title: compactChunkText(title)
|
|
277
|
+
}] : void 0;
|
|
278
|
+
}
|
|
246
279
|
return [{
|
|
247
280
|
type: "plan_update",
|
|
248
281
|
title: resolvePlanTitle({
|
|
@@ -710,15 +743,6 @@ function resolveSlackTimestampMs(ts) {
|
|
|
710
743
|
}
|
|
711
744
|
//#endregion
|
|
712
745
|
//#region extensions/slack/src/monitor/message-handler/dispatch.ts
|
|
713
|
-
const SLACK_REASONING_TAG_RE = /<\s*(\/?)\s*(?:(?:antml:|mm:)?(?:think(?:ing)?|thought)|antthinking)\b[^<>]*>/gi;
|
|
714
|
-
const SLACK_REASONING_LABEL_PREFIX_RE = /^\s*(?:>\s*)?Reasoning:\s*/iu;
|
|
715
|
-
const SLACK_THINKING_LABEL_PREFIX_RE = /^\s*(?:>\s*)?Thinking\.{0,3}(?=\s*(?:\n|_))/iu;
|
|
716
|
-
const SLACK_THREAD_LOADING_MESSAGES = [
|
|
717
|
-
"Reading the thread...",
|
|
718
|
-
"Checking context...",
|
|
719
|
-
"Working through the request...",
|
|
720
|
-
"Putting it all together..."
|
|
721
|
-
];
|
|
722
746
|
function resolveSlackMessageTimestampMs(message) {
|
|
723
747
|
return resolveSlackTimestampMs(message.event_ts ?? message.ts);
|
|
724
748
|
}
|
|
@@ -820,43 +844,6 @@ function rememberSlackStreamRecipientTeam(params) {
|
|
|
820
844
|
if (oldest) cache.delete(oldest);
|
|
821
845
|
}
|
|
822
846
|
}
|
|
823
|
-
function normalizeSlackReasoningProgressLine(text) {
|
|
824
|
-
return (extractSlackReasoningTagText(text) || stripReasoningTagsFromText(text, {
|
|
825
|
-
mode: "strict",
|
|
826
|
-
trim: "both"
|
|
827
|
-
})).replace(SLACK_REASONING_LABEL_PREFIX_RE, "").replace(SLACK_THINKING_LABEL_PREFIX_RE, "").split(/\r?\n/u).map((line) => stripSimpleItalicMarkers(line)).filter(Boolean).join(" ").replace(/\s+/g, " ").trim();
|
|
828
|
-
}
|
|
829
|
-
function extractSlackReasoningTagText(text) {
|
|
830
|
-
if (!text) return "";
|
|
831
|
-
let result = "";
|
|
832
|
-
let lastIndex = 0;
|
|
833
|
-
let inReasoning = false;
|
|
834
|
-
SLACK_REASONING_TAG_RE.lastIndex = 0;
|
|
835
|
-
for (const match of text.matchAll(SLACK_REASONING_TAG_RE)) {
|
|
836
|
-
const index = match.index ?? 0;
|
|
837
|
-
if (inReasoning) result += text.slice(lastIndex, index);
|
|
838
|
-
inReasoning = match[1] !== "/";
|
|
839
|
-
lastIndex = index + match[0].length;
|
|
840
|
-
}
|
|
841
|
-
if (inReasoning) result += text.slice(lastIndex);
|
|
842
|
-
return result.trim();
|
|
843
|
-
}
|
|
844
|
-
function stripSimpleItalicMarkers(line) {
|
|
845
|
-
const trimmed = line.trim();
|
|
846
|
-
if (trimmed.length >= 2 && trimmed.startsWith("_") && trimmed.endsWith("_")) return trimmed.slice(1, -1).trim();
|
|
847
|
-
return trimmed;
|
|
848
|
-
}
|
|
849
|
-
function mergeSlackReasoningProgressText(current, incoming, options) {
|
|
850
|
-
if (!current) return incoming;
|
|
851
|
-
const normalizedCurrent = normalizeSlackReasoningProgressLine(current);
|
|
852
|
-
const normalizedIncoming = normalizeSlackReasoningProgressLine(incoming);
|
|
853
|
-
if (!normalizedIncoming || normalizedIncoming === normalizedCurrent) return current;
|
|
854
|
-
if (options?.snapshot === true || isSlackReasoningSnapshotText(incoming) || normalizedIncoming.startsWith(normalizedCurrent)) return incoming;
|
|
855
|
-
return `${current}${incoming}`;
|
|
856
|
-
}
|
|
857
|
-
function isSlackReasoningSnapshotText(text) {
|
|
858
|
-
return SLACK_REASONING_LABEL_PREFIX_RE.test(text) || SLACK_THINKING_LABEL_PREFIX_RE.test(text);
|
|
859
|
-
}
|
|
860
847
|
function createSlackEventDeliveryTracker() {
|
|
861
848
|
const deliveredKeys = /* @__PURE__ */ new Set();
|
|
862
849
|
return {
|
|
@@ -967,36 +954,31 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
967
954
|
const incomingThreadTs = message.thread_ts;
|
|
968
955
|
let didSetStatus = false;
|
|
969
956
|
const statusReactionsEnabled = prepared.ctxPayload.InboundEventKind !== "room_event" && Boolean(prepared.ackReactionPromise) && Boolean(reactionMessageTs) && cfg.messages?.statusReactions?.enabled === true;
|
|
970
|
-
const slackStatusAdapter = {
|
|
971
|
-
setReaction: async (emoji) => {
|
|
972
|
-
await reactSlackMessage(message.channel, reactionMessageTs ?? "", emoji, {
|
|
973
|
-
token: ctx.botToken,
|
|
974
|
-
client: slackClient
|
|
975
|
-
}).catch((err) => {
|
|
976
|
-
if (formatErrorMessage(err).includes("already_reacted")) return;
|
|
977
|
-
throw err;
|
|
978
|
-
});
|
|
979
|
-
},
|
|
980
|
-
removeReaction: async (emoji) => {
|
|
981
|
-
await removeSlackReaction(message.channel, reactionMessageTs ?? "", emoji, {
|
|
982
|
-
token: ctx.botToken,
|
|
983
|
-
client: slackClient
|
|
984
|
-
}).catch((err) => {
|
|
985
|
-
if (formatErrorMessage(err).includes("no_reaction")) return;
|
|
986
|
-
throw err;
|
|
987
|
-
});
|
|
988
|
-
}
|
|
989
|
-
};
|
|
990
|
-
const statusReactionTiming = {
|
|
991
|
-
...DEFAULT_TIMING,
|
|
992
|
-
...cfg.messages?.statusReactions?.timing
|
|
993
|
-
};
|
|
994
957
|
const statusReactions = createStatusReactionController({
|
|
995
958
|
enabled: statusReactionsEnabled,
|
|
996
|
-
adapter:
|
|
959
|
+
adapter: {
|
|
960
|
+
setReaction: async (emoji) => {
|
|
961
|
+
await reactSlackMessage(message.channel, reactionMessageTs ?? "", emoji, {
|
|
962
|
+
token: ctx.botToken,
|
|
963
|
+
client: slackClient
|
|
964
|
+
}).catch((err) => {
|
|
965
|
+
if (formatErrorMessage(err).includes("already_reacted")) return;
|
|
966
|
+
throw err;
|
|
967
|
+
});
|
|
968
|
+
},
|
|
969
|
+
removeReaction: async (emoji) => {
|
|
970
|
+
await removeSlackReaction(message.channel, reactionMessageTs ?? "", emoji, {
|
|
971
|
+
token: ctx.botToken,
|
|
972
|
+
client: slackClient
|
|
973
|
+
}).catch((err) => {
|
|
974
|
+
if (formatErrorMessage(err).includes("no_reaction")) return;
|
|
975
|
+
throw err;
|
|
976
|
+
});
|
|
977
|
+
}
|
|
978
|
+
},
|
|
997
979
|
initialEmoji: prepared.ackReactionValue || "eyes",
|
|
998
|
-
emojis:
|
|
999
|
-
timing:
|
|
980
|
+
emojis: void 0,
|
|
981
|
+
timing: DEFAULT_TIMING,
|
|
1000
982
|
onError: (err) => {
|
|
1001
983
|
logAckFailure({
|
|
1002
984
|
log: logVerbose,
|
|
@@ -1036,7 +1018,6 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1036
1018
|
channelId: message.channel,
|
|
1037
1019
|
threadTs: statusThreadTs,
|
|
1038
1020
|
status: "is typing...",
|
|
1039
|
-
loadingMessages: SLACK_THREAD_LOADING_MESSAGES,
|
|
1040
1021
|
eventScope: prepared.eventScope
|
|
1041
1022
|
});
|
|
1042
1023
|
if (typingReaction && message.ts) await reactSlackMessage(message.channel, message.ts, typingReaction, {
|
|
@@ -1156,6 +1137,11 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1156
1137
|
delivery.outcome = "success";
|
|
1157
1138
|
}
|
|
1158
1139
|
};
|
|
1140
|
+
const acknowledgeStoppedStreamedDeliveries = (session, messageId) => {
|
|
1141
|
+
refreshStreamedAcknowledgements(session);
|
|
1142
|
+
for (const delivery of streamedDeliveries) delivery.acknowledged = true;
|
|
1143
|
+
emitAcknowledgedStreamedDeliveries(messageId);
|
|
1144
|
+
};
|
|
1159
1145
|
const emitFailedPendingStreamedDeliveries = (error) => {
|
|
1160
1146
|
for (const delivery of streamedDeliveries) {
|
|
1161
1147
|
if (delivery.acknowledged || delivery.outcome) continue;
|
|
@@ -1209,8 +1195,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1209
1195
|
session,
|
|
1210
1196
|
...slackMessageMetadata ? { metadata: slackMessageMetadata } : {}
|
|
1211
1197
|
});
|
|
1212
|
-
|
|
1213
|
-
emitAcknowledgedStreamedDeliveries(stopResult.messageId);
|
|
1198
|
+
acknowledgeStoppedStreamedDeliveries(session, stopResult.messageId);
|
|
1214
1199
|
observedReplyDelivery = true;
|
|
1215
1200
|
usedReplyThreadTs ??= session.threadTs;
|
|
1216
1201
|
return true;
|
|
@@ -1319,6 +1304,24 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1319
1304
|
rememberDeliveredThreadTs(params.kind, params.session.threadTs);
|
|
1320
1305
|
return true;
|
|
1321
1306
|
};
|
|
1307
|
+
const appendNativeProgressCompletion = async (isError) => {
|
|
1308
|
+
const session = streamSession;
|
|
1309
|
+
if (isError) nativeProgressTerminalStatus = "error";
|
|
1310
|
+
if (!session || nativeProgressCompletionSent) return;
|
|
1311
|
+
const chunks = buildNativeProgressCompletionChunks(isError ? "error" : "complete");
|
|
1312
|
+
if (!chunks?.length) return;
|
|
1313
|
+
try {
|
|
1314
|
+
await appendSlackStream({
|
|
1315
|
+
session,
|
|
1316
|
+
chunks
|
|
1317
|
+
});
|
|
1318
|
+
nativeProgressCompletionSent = true;
|
|
1319
|
+
observedReplyDelivery ||= session.delivered;
|
|
1320
|
+
} catch (err) {
|
|
1321
|
+
streamFailed = true;
|
|
1322
|
+
runtime.error?.(danger(`slack-stream: native progress completion failed: ${formatSlackError(err)}`));
|
|
1323
|
+
}
|
|
1324
|
+
};
|
|
1322
1325
|
const deliverWithStreaming = async (params) => {
|
|
1323
1326
|
if (params.payload.isReasoning === true) return;
|
|
1324
1327
|
const reply = resolveSendableOutboundReplyParts(params.payload);
|
|
@@ -1344,13 +1347,6 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1344
1347
|
});
|
|
1345
1348
|
return;
|
|
1346
1349
|
}
|
|
1347
|
-
if (useNativeProgressStreaming && !streamSession) {
|
|
1348
|
-
await deliverNormally({
|
|
1349
|
-
payload: params.payload,
|
|
1350
|
-
kind: params.kind
|
|
1351
|
-
});
|
|
1352
|
-
return;
|
|
1353
|
-
}
|
|
1354
1350
|
if (!streamSession) {
|
|
1355
1351
|
const streamThreadTs = replyPlan.nextThreadTs();
|
|
1356
1352
|
plannedThreadTs = streamThreadTs;
|
|
@@ -1411,40 +1407,12 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1411
1407
|
logVerbose("slack-stream: suppressed duplicate append payload");
|
|
1412
1408
|
return;
|
|
1413
1409
|
}
|
|
1414
|
-
const completionChunks = useNativeProgressStreaming && !nativeProgressCompletionSent && (previewToolProgressLines.length > 0 || Boolean(latestPlan?.length) || Boolean(latestPlanExplanation) || [...nativeTaskState.values()].some((task) => task.status !== "complete" && task.status !== "error")) ? reconcileSlackNativeTaskChunks({
|
|
1415
|
-
previousTasks: nativeTaskState,
|
|
1416
|
-
chunks: buildSlackProgressStreamCompletionChunks({
|
|
1417
|
-
title: resolveNativeProgressTitle(),
|
|
1418
|
-
lines: resolveNativeProgressLines(),
|
|
1419
|
-
plan: resolveNativeProgressPlan(),
|
|
1420
|
-
maxLineChars: progressDraftMaxLineChars,
|
|
1421
|
-
finalInProgressStatus: params.payload.isError ? "error" : "complete"
|
|
1422
|
-
})
|
|
1423
|
-
}).chunks : void 0;
|
|
1424
|
-
if (useNativeProgressStreaming) {
|
|
1425
|
-
if (completionChunks?.length) {
|
|
1426
|
-
await appendSlackStream({
|
|
1427
|
-
session: streamSession,
|
|
1428
|
-
chunks: completionChunks
|
|
1429
|
-
});
|
|
1430
|
-
nativeProgressCompletionSent = true;
|
|
1431
|
-
if (streamSession.delivered) observedReplyDelivery = true;
|
|
1432
|
-
}
|
|
1433
|
-
await deliverNormally({
|
|
1434
|
-
payload: params.payload,
|
|
1435
|
-
kind: params.kind,
|
|
1436
|
-
forcedThreadTs: streamSession.threadTs
|
|
1437
|
-
});
|
|
1438
|
-
return;
|
|
1439
|
-
}
|
|
1440
1410
|
if (text) recordStreamedDelivery(params.kind, text);
|
|
1441
1411
|
await appendSlackStream({
|
|
1442
1412
|
session: streamSession,
|
|
1443
|
-
text: "\n" + text
|
|
1444
|
-
chunks: completionChunks
|
|
1413
|
+
text: "\n" + text
|
|
1445
1414
|
});
|
|
1446
1415
|
refreshStreamedAcknowledgements(streamSession);
|
|
1447
|
-
if (completionChunks?.length) nativeProgressCompletionSent = true;
|
|
1448
1416
|
if (streamSession.delivered) {
|
|
1449
1417
|
observedReplyDelivery = true;
|
|
1450
1418
|
if (params.kind === "final") observedFinalReplyDelivery = true;
|
|
@@ -1491,13 +1459,59 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1491
1459
|
await deliverNormally({
|
|
1492
1460
|
payload: params.payload,
|
|
1493
1461
|
kind: params.kind,
|
|
1494
|
-
forcedThreadTs: streamSession?.threadTs ?? plannedThreadTs
|
|
1462
|
+
forcedThreadTs: streamSession?.threadTs ?? nativeProgressStreamThreadTs ?? plannedThreadTs
|
|
1495
1463
|
});
|
|
1496
1464
|
}
|
|
1497
1465
|
};
|
|
1498
1466
|
let draftPreviewCommitted = false;
|
|
1499
1467
|
const deliverSlackPayload = async (payload, info) => {
|
|
1500
1468
|
if (payload.isReasoning === true) return { visibleReplySent: false };
|
|
1469
|
+
if (info.kind === "final" && slackStreaming.mode === "progress" && streamMode === "status_final") {
|
|
1470
|
+
const hadProgressDraft = progressDraft.hasStarted;
|
|
1471
|
+
progressDraft.markFinalReplyStarted();
|
|
1472
|
+
if (useNativeProgressStreaming) {
|
|
1473
|
+
await waitForNativeProgressStreamStart();
|
|
1474
|
+
const finalThreadTs = streamSession?.threadTs ?? nativeProgressStreamThreadTs;
|
|
1475
|
+
await deliverNormally({
|
|
1476
|
+
payload,
|
|
1477
|
+
kind: info.kind,
|
|
1478
|
+
forcedThreadTs: finalThreadTs
|
|
1479
|
+
});
|
|
1480
|
+
await appendNativeProgressCompletion(payload.isError === true);
|
|
1481
|
+
progressDraft.markFinalReplyDelivered();
|
|
1482
|
+
if (!payload.isError && hadProgressDraft && streamSession) pendingNativeProgressReceipt = progressReceipt.buildSummaryLine();
|
|
1483
|
+
return;
|
|
1484
|
+
}
|
|
1485
|
+
if (hadProgressDraft) try {
|
|
1486
|
+
await draftStream?.flush();
|
|
1487
|
+
} catch (err) {
|
|
1488
|
+
logVerbose(`slack: progress draft flush before final failed (${formatSlackError(err)})`);
|
|
1489
|
+
}
|
|
1490
|
+
const receiptChannelId = hadProgressDraft ? draftStream?.channelId() : void 0;
|
|
1491
|
+
const receiptMessageId = hadProgressDraft ? draftStream?.messageId() : void 0;
|
|
1492
|
+
const draftThreadTs = hadProgressDraft ? usedReplyThreadTs ?? statusThreadTs : void 0;
|
|
1493
|
+
await deliverNormally({
|
|
1494
|
+
payload,
|
|
1495
|
+
kind: info.kind,
|
|
1496
|
+
...draftThreadTs ? { forcedThreadTs: draftThreadTs } : {}
|
|
1497
|
+
});
|
|
1498
|
+
progressDraft.markFinalReplyDelivered();
|
|
1499
|
+
if (!payload.isError && receiptChannelId && receiptMessageId && !progressReceiptCollapsed) await collapseProgressReceipt({
|
|
1500
|
+
channelId: receiptChannelId,
|
|
1501
|
+
messageId: receiptMessageId,
|
|
1502
|
+
text: progressReceipt.buildSummaryLine(),
|
|
1503
|
+
threadTs: usedReplyThreadTs ?? statusThreadTs
|
|
1504
|
+
});
|
|
1505
|
+
return;
|
|
1506
|
+
}
|
|
1507
|
+
if (useNativeProgressStreaming) {
|
|
1508
|
+
await deliverNormally({
|
|
1509
|
+
payload,
|
|
1510
|
+
kind: info.kind,
|
|
1511
|
+
forcedThreadTs: streamSession?.threadTs ?? nativeProgressStreamThreadTs
|
|
1512
|
+
});
|
|
1513
|
+
return;
|
|
1514
|
+
}
|
|
1501
1515
|
if (useStreaming) {
|
|
1502
1516
|
await deliverWithStreaming({
|
|
1503
1517
|
payload,
|
|
@@ -1688,8 +1702,6 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1688
1702
|
const useNativeProgressStreaming = useStreaming && slackStreaming.mode === "progress";
|
|
1689
1703
|
const progressDraftActive = Boolean(draftStream) || useNativeProgressStreaming;
|
|
1690
1704
|
const previewToolProgressEnabled = progressDraftActive && resolveChannelStreamingPreviewToolProgress(account.config);
|
|
1691
|
-
const commentaryProgressEnabled = progressDraftActive && resolveChannelStreamingProgressCommentary(account.config);
|
|
1692
|
-
const commentaryDraftEnabled = progressDraftActive && (slackStreaming.mode === "progress" ? resolveChannelStreamingProgressCommentary(account.config, previewToolProgressEnabled) : previewToolProgressEnabled);
|
|
1693
1705
|
let shouldYieldDraftProgress = () => false;
|
|
1694
1706
|
const suppressDefaultToolProgressMessages = resolveChannelStreamingSuppressDefaultToolProgressMessages(account.config, {
|
|
1695
1707
|
draftStreamActive: Boolean(draftStream) || useNativeProgressStreaming,
|
|
@@ -1697,46 +1709,20 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1697
1709
|
previewStreamingEnabled
|
|
1698
1710
|
});
|
|
1699
1711
|
let previewToolProgressSuppressed = false;
|
|
1700
|
-
let
|
|
1701
|
-
let lastNonEmptyPreviewToolProgressLines = [];
|
|
1702
|
-
let latestPlan;
|
|
1703
|
-
let latestPlanExplanation;
|
|
1712
|
+
let legacyPreviewToolProgressLines = [];
|
|
1704
1713
|
let nativeTaskState = /* @__PURE__ */ new Map();
|
|
1705
1714
|
let appendRenderedText = "";
|
|
1706
1715
|
let appendSourceText = "";
|
|
1707
|
-
let reasoningProgressRawText = "";
|
|
1708
|
-
let statusUpdateCount = 0;
|
|
1709
1716
|
let nativeProgressCompletionSent = false;
|
|
1717
|
+
let nativeProgressTerminalStatus = "complete";
|
|
1710
1718
|
let nativeProgressChunkKey;
|
|
1719
|
+
const progressReceipt = createChannelProgressReceiptTracker();
|
|
1720
|
+
let progressReceiptCollapsed = false;
|
|
1721
|
+
let pendingNativeProgressReceipt;
|
|
1711
1722
|
const progressSeed = `${account.accountId}:${message.channel}`;
|
|
1712
1723
|
const useRichProgressDraft = streamMode === "status_final" && resolveChannelProgressDraftRender(account.config) === "rich";
|
|
1713
1724
|
const explicitProgressTitle = resolveExplicitSlackProgressTitle(account.config);
|
|
1714
1725
|
const progressDraftMaxLineChars = resolveChannelProgressDraftMaxLineChars(account.config);
|
|
1715
|
-
const renderProgressDraft = () => {
|
|
1716
|
-
if (!draftStream || streamMode !== "status_final") return;
|
|
1717
|
-
const progressLines = previewToolProgressLines.length === 0 ? lastNonEmptyPreviewToolProgressLines : previewToolProgressLines;
|
|
1718
|
-
const previewText = formatChannelProgressDraftText({
|
|
1719
|
-
entry: account.config,
|
|
1720
|
-
lines: progressLines,
|
|
1721
|
-
seed: progressSeed,
|
|
1722
|
-
formatLine: escapeSlackMrkdwn,
|
|
1723
|
-
narration: latestPlanExplanation,
|
|
1724
|
-
plan: latestPlan
|
|
1725
|
-
});
|
|
1726
|
-
if (!previewText) return;
|
|
1727
|
-
const richProgressBlocks = useRichProgressDraft ? buildSlackProgressDraftBlocks({
|
|
1728
|
-
title: explicitProgressTitle,
|
|
1729
|
-
lines: progressLines,
|
|
1730
|
-
plan: latestPlan,
|
|
1731
|
-
narration: latestPlanExplanation,
|
|
1732
|
-
maxLineChars: resolveChannelProgressDraftMaxLineChars(account.config)
|
|
1733
|
-
}) : void 0;
|
|
1734
|
-
draftStream.update(useRichProgressDraft && richProgressBlocks ? {
|
|
1735
|
-
text: previewText,
|
|
1736
|
-
blocks: richProgressBlocks
|
|
1737
|
-
} : previewText);
|
|
1738
|
-
hasStreamedMessage = true;
|
|
1739
|
-
};
|
|
1740
1726
|
const waitForNativeProgressStreamStart = async () => {
|
|
1741
1727
|
if (streamSession || !nativeProgressStreamStartPromise) return true;
|
|
1742
1728
|
try {
|
|
@@ -1747,26 +1733,40 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1747
1733
|
}
|
|
1748
1734
|
return !streamFailed;
|
|
1749
1735
|
};
|
|
1750
|
-
const
|
|
1751
|
-
|
|
1752
|
-
|
|
1736
|
+
const resolveStructuredProgressLines = (lines) => lines.map((line) => {
|
|
1737
|
+
if (typeof line !== "string") return line;
|
|
1738
|
+
const reasoning = line.startsWith("🧠 ");
|
|
1739
|
+
const text = line.replace(/^(?:🧠|💬)\s+/u, "").replace(/^_(.*)_$/su, "$1").trim();
|
|
1740
|
+
return {
|
|
1741
|
+
...reasoning ? { id: "reasoning" } : {},
|
|
1742
|
+
kind: "item",
|
|
1743
|
+
text,
|
|
1744
|
+
label: reasoning ? "Reasoning" : "Update",
|
|
1745
|
+
prefix: false
|
|
1746
|
+
};
|
|
1747
|
+
});
|
|
1748
|
+
const resolveNativeProgressPlan = (snapshot) => snapshot.plan?.length ? snapshot.plan : void 0;
|
|
1749
|
+
const resolveNativeProgressLines = (snapshot) => {
|
|
1750
|
+
const lines = resolveStructuredProgressLines(snapshot.lines);
|
|
1751
|
+
if (snapshot.plan?.length || !snapshot.planExplanation) return lines;
|
|
1753
1752
|
const explanationLine = buildChannelProgressDraftLine({
|
|
1754
1753
|
event: "plan",
|
|
1755
1754
|
phase: "update",
|
|
1756
|
-
explanation:
|
|
1755
|
+
explanation: snapshot.planExplanation
|
|
1757
1756
|
});
|
|
1758
|
-
return explanationLine ? [...
|
|
1757
|
+
return explanationLine ? [...lines, explanationLine] : lines;
|
|
1759
1758
|
};
|
|
1760
|
-
const
|
|
1761
|
-
const
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1759
|
+
const combineProgressHeadlineAndExplanation = (headline, explanation) => headline && explanation && headline !== explanation ? `${headline} — ${explanation}` : headline ?? explanation;
|
|
1760
|
+
const resolveNativeProgressTitle = (snapshot) => combineProgressHeadlineAndExplanation(explicitProgressTitle ?? snapshot.statusHeadline, snapshot.planExplanation);
|
|
1761
|
+
const buildNativeProgressChunks = (snapshot) => streamSession ? buildSlackProgressStreamUpdateChunks({
|
|
1762
|
+
title: resolveNativeProgressTitle(snapshot),
|
|
1763
|
+
lines: resolveNativeProgressLines(snapshot),
|
|
1764
|
+
plan: resolveNativeProgressPlan(snapshot),
|
|
1765
1765
|
maxLineChars: progressDraftMaxLineChars
|
|
1766
1766
|
}) : buildSlackProgressStreamStartChunks({
|
|
1767
|
-
title: resolveNativeProgressTitle(),
|
|
1768
|
-
lines: resolveNativeProgressLines(),
|
|
1769
|
-
plan: resolveNativeProgressPlan(),
|
|
1767
|
+
title: resolveNativeProgressTitle(snapshot),
|
|
1768
|
+
lines: resolveNativeProgressLines(snapshot),
|
|
1769
|
+
plan: resolveNativeProgressPlan(snapshot),
|
|
1770
1770
|
maxLineChars: progressDraftMaxLineChars
|
|
1771
1771
|
});
|
|
1772
1772
|
const markNativeProgressDelivered = (session, threadTs) => {
|
|
@@ -1824,12 +1824,14 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1824
1824
|
nativeProgressChunkKey = chunkKey;
|
|
1825
1825
|
};
|
|
1826
1826
|
const updateNativeProgressStream = async () => {
|
|
1827
|
+
const snapshot = progressDraft.getSnapshot();
|
|
1828
|
+
const progressLines = resolveNativeProgressLines(snapshot);
|
|
1827
1829
|
const hasRetirableNativeTasks = [...nativeTaskState.values()].some((task) => task.status !== "complete" && task.status !== "error");
|
|
1828
|
-
if (!useNativeProgressStreaming || streamFailed ||
|
|
1830
|
+
if (!useNativeProgressStreaming || streamFailed || progressLines.length === 0 && !snapshot.plan?.length && !snapshot.statusHeadline && !explicitProgressTitle && !hasRetirableNativeTasks) return;
|
|
1829
1831
|
if (!await waitForNativeProgressStreamStart()) return;
|
|
1830
1832
|
const reconciled = reconcileSlackNativeTaskChunks({
|
|
1831
1833
|
previousTasks: nativeTaskState,
|
|
1832
|
-
chunks: buildNativeProgressChunks()
|
|
1834
|
+
chunks: buildNativeProgressChunks(snapshot)
|
|
1833
1835
|
});
|
|
1834
1836
|
const chunks = reconciled.chunks;
|
|
1835
1837
|
if (!chunks?.length) return;
|
|
@@ -1844,85 +1846,154 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1844
1846
|
streamFailed = true;
|
|
1845
1847
|
}
|
|
1846
1848
|
};
|
|
1847
|
-
const
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
plan: latestPlan
|
|
1849
|
+
const resetProgressTurnState = () => {
|
|
1850
|
+
progressReceipt.reset();
|
|
1851
|
+
progressReceiptCollapsed = false;
|
|
1852
|
+
pendingNativeProgressReceipt = void 0;
|
|
1853
|
+
};
|
|
1854
|
+
const collapseProgressReceipt = async (params) => {
|
|
1855
|
+
const { botToken: token } = ctx;
|
|
1856
|
+
try {
|
|
1857
|
+
await finalizeSlackPreviewEdit({
|
|
1858
|
+
client: slackClient,
|
|
1859
|
+
token,
|
|
1860
|
+
accountId: account.accountId,
|
|
1861
|
+
...params
|
|
1861
1862
|
});
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1863
|
+
progressReceiptCollapsed = true;
|
|
1864
|
+
} catch (err) {
|
|
1865
|
+
logVerbose(`slack: progress receipt edit failed (${formatSlackError(err)})`);
|
|
1866
|
+
}
|
|
1867
|
+
};
|
|
1868
|
+
const progressDraft = createChannelProgressDraftCompositor({
|
|
1869
|
+
entry: account.config,
|
|
1870
|
+
mode: slackStreaming.mode,
|
|
1871
|
+
active: progressDraftActive && streamMode === "status_final",
|
|
1872
|
+
seed: progressSeed,
|
|
1873
|
+
formatLine: escapeSlackMrkdwn,
|
|
1874
|
+
reasoningLinePrefix: "🧠 ",
|
|
1875
|
+
commentaryLinePrefix: "💬 ",
|
|
1876
|
+
reasoningGate: previewToolProgressEnabled,
|
|
1877
|
+
commentaryItalics: false,
|
|
1878
|
+
updateOnLineChange: useNativeProgressStreaming || useRichProgressDraft,
|
|
1879
|
+
update: async (previewText, options) => {
|
|
1880
|
+
if (useNativeProgressStreaming) {
|
|
1881
|
+
await updateNativeProgressStream();
|
|
1882
|
+
return;
|
|
1865
1883
|
}
|
|
1866
|
-
return;
|
|
1884
|
+
if (!draftStream) return;
|
|
1885
|
+
const snapshot = progressDraft.getSnapshot();
|
|
1886
|
+
const structuredLines = resolveStructuredProgressLines(options?.lines ?? snapshot.lines);
|
|
1887
|
+
const richNarration = combineProgressHeadlineAndExplanation(snapshot.statusHeadline, snapshot.planExplanation);
|
|
1888
|
+
const richProgressBlocks = useRichProgressDraft ? buildSlackProgressDraftBlocks({
|
|
1889
|
+
title: explicitProgressTitle,
|
|
1890
|
+
lines: structuredLines,
|
|
1891
|
+
plan: snapshot.plan,
|
|
1892
|
+
narration: richNarration,
|
|
1893
|
+
maxLineChars: progressDraftMaxLineChars
|
|
1894
|
+
}) : void 0;
|
|
1895
|
+
draftStream.update(useRichProgressDraft && richProgressBlocks ? {
|
|
1896
|
+
text: previewText,
|
|
1897
|
+
blocks: richProgressBlocks
|
|
1898
|
+
} : previewText);
|
|
1899
|
+
hasStreamedMessage = true;
|
|
1900
|
+
if (options?.flush) await draftStream.flush();
|
|
1867
1901
|
}
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1902
|
+
});
|
|
1903
|
+
const commentaryProgressEnabled = progressDraft.commentaryProgressEnabled;
|
|
1904
|
+
const buildNativeProgressCompletionChunks = (finalInProgressStatus) => {
|
|
1905
|
+
const snapshot = progressDraft.getSnapshot();
|
|
1906
|
+
const lines = resolveNativeProgressLines(snapshot);
|
|
1907
|
+
const hasRetirableNativeTasks = [...nativeTaskState.values()].some((task) => task.status !== "complete" && task.status !== "error");
|
|
1908
|
+
if (lines.length === 0 && !snapshot.plan?.length && !hasRetirableNativeTasks) return;
|
|
1909
|
+
return reconcileSlackNativeTaskChunks({
|
|
1910
|
+
previousTasks: nativeTaskState,
|
|
1911
|
+
chunks: buildSlackProgressStreamCompletionChunks({
|
|
1912
|
+
title: resolveNativeProgressTitle(snapshot),
|
|
1913
|
+
lines,
|
|
1914
|
+
plan: resolveNativeProgressPlan(snapshot),
|
|
1915
|
+
maxLineChars: progressDraftMaxLineChars,
|
|
1916
|
+
finalInProgressStatus
|
|
1917
|
+
})
|
|
1918
|
+
}).chunks;
|
|
1871
1919
|
};
|
|
1872
|
-
const
|
|
1873
|
-
if (
|
|
1874
|
-
|
|
1920
|
+
const finishNativeProgressTurn = async (completionChunks) => {
|
|
1921
|
+
if (nativeProgressStreamStartPromise) await nativeProgressStreamStartPromise.catch(() => null);
|
|
1922
|
+
const session = streamSession;
|
|
1923
|
+
if (session && !session.stopped) try {
|
|
1924
|
+
if (completionChunks?.length) nativeProgressCompletionSent = true;
|
|
1925
|
+
const stopResult = await stopSlackStream({
|
|
1926
|
+
session,
|
|
1927
|
+
...completionChunks?.length ? { chunks: completionChunks } : {},
|
|
1928
|
+
...slackMessageMetadata ? { metadata: slackMessageMetadata } : {}
|
|
1929
|
+
});
|
|
1930
|
+
acknowledgeStoppedStreamedDeliveries(session, stopResult?.messageId);
|
|
1931
|
+
if (pendingNativeProgressReceipt && stopResult?.messageId) await collapseProgressReceipt({
|
|
1932
|
+
channelId: session.channel,
|
|
1933
|
+
messageId: stopResult.messageId,
|
|
1934
|
+
text: pendingNativeProgressReceipt,
|
|
1935
|
+
threadTs: session.threadTs
|
|
1936
|
+
});
|
|
1937
|
+
} catch (err) {
|
|
1938
|
+
const error = formatSlackError(err);
|
|
1939
|
+
emitAcknowledgedStreamedDeliveries();
|
|
1940
|
+
emitFailedPendingStreamedDeliveries(error);
|
|
1941
|
+
logVerbose(`slack-stream: failed to rotate native progress stream (${error})`);
|
|
1942
|
+
}
|
|
1943
|
+
streamSession = null;
|
|
1944
|
+
nativeProgressStreamStartPromise = null;
|
|
1945
|
+
nativeProgressStreamThreadTs = void 0;
|
|
1946
|
+
streamFailed = false;
|
|
1875
1947
|
};
|
|
1876
|
-
const
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
if (!draftStream && !useNativeProgressStreaming) return;
|
|
1880
|
-
if (lane === "commentary" && commentaryProgressEnabled && shouldYieldDraftProgress()) return;
|
|
1881
|
-
if (options?.toolName !== void 0 && !isChannelProgressDraftWorkToolName(options.toolName)) return;
|
|
1882
|
-
const normalized = line?.text.replace(/\s+/g, " ").trim();
|
|
1883
|
-
if (!line || !normalized) {
|
|
1884
|
-
if (streamMode !== "status_final") return;
|
|
1885
|
-
const alreadyStarted = progressDraftGate.hasStarted;
|
|
1886
|
-
const progressActive = await progressDraftGate.noteWork();
|
|
1887
|
-
if ((alreadyStarted || progressActive) && progressDraftGate.hasStarted) await refreshStartedProgressDraft();
|
|
1948
|
+
const pushPlanProgress = async (steps, explanation) => {
|
|
1949
|
+
if (streamMode === "status_final") {
|
|
1950
|
+
await progressDraft.pushPlanProgress(steps, { explanation });
|
|
1888
1951
|
return;
|
|
1889
1952
|
}
|
|
1890
|
-
if (
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1953
|
+
if (previewToolProgressSuppressed || !draftStream) return;
|
|
1954
|
+
const text = formatChannelProgressDraftText({
|
|
1955
|
+
entry: account.config,
|
|
1956
|
+
lines: legacyPreviewToolProgressLines,
|
|
1957
|
+
seed: progressSeed,
|
|
1958
|
+
formatLine: escapeSlackMrkdwn,
|
|
1959
|
+
narration: explanation,
|
|
1960
|
+
plan: steps
|
|
1961
|
+
});
|
|
1962
|
+
if (text) {
|
|
1963
|
+
draftStream.update(text);
|
|
1901
1964
|
hasStreamedMessage = true;
|
|
1902
|
-
return;
|
|
1903
|
-
}
|
|
1904
|
-
if (progressEnabled && !previewToolProgressSuppressed) {
|
|
1905
|
-
previewToolProgressLines = mergeChannelProgressDraftLine(previewToolProgressLines, line, { maxLines: resolveChannelProgressDraftMaxLines(account.config) });
|
|
1906
|
-
if (previewToolProgressLines.length > 0) lastNonEmptyPreviewToolProgressLines = previewToolProgressLines;
|
|
1907
1965
|
}
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1966
|
+
};
|
|
1967
|
+
const pushPreviewProgress = async (line, options) => {
|
|
1968
|
+
if (!draftStream && !useNativeProgressStreaming) return;
|
|
1969
|
+
if (options?.toolName !== void 0 && !isChannelProgressDraftWorkToolName(options.toolName)) return;
|
|
1970
|
+
const normalized = line?.text.replace(/\s+/g, " ").trim();
|
|
1971
|
+
if (streamMode === "status_final") {
|
|
1972
|
+
if (!line || !normalized) {
|
|
1973
|
+
await progressDraft.noteActivity();
|
|
1974
|
+
return;
|
|
1913
1975
|
}
|
|
1976
|
+
await progressDraft.pushToolProgress(line, options);
|
|
1914
1977
|
return;
|
|
1915
1978
|
}
|
|
1916
|
-
|
|
1917
|
-
const
|
|
1918
|
-
if (
|
|
1979
|
+
if (!line || !normalized || !draftStream || !previewToolProgressEnabled || previewToolProgressSuppressed) return;
|
|
1980
|
+
const nextLines = mergeChannelProgressDraftLine(legacyPreviewToolProgressLines, line, { maxLines: resolveChannelProgressDraftMaxLines(account.config) });
|
|
1981
|
+
if (nextLines === legacyPreviewToolProgressLines) return;
|
|
1982
|
+
legacyPreviewToolProgressLines = nextLines;
|
|
1983
|
+
draftStream.update(formatChannelProgressDraftText({
|
|
1984
|
+
entry: account.config,
|
|
1985
|
+
lines: legacyPreviewToolProgressLines,
|
|
1986
|
+
seed: progressSeed,
|
|
1987
|
+
formatLine: escapeSlackMrkdwn
|
|
1988
|
+
}));
|
|
1989
|
+
hasStreamedMessage = true;
|
|
1919
1990
|
};
|
|
1920
1991
|
const updateDraftFromPartial = (text) => {
|
|
1921
1992
|
const trimmed = text?.trimEnd();
|
|
1922
1993
|
if (!trimmed) return;
|
|
1923
1994
|
if (streamMode === "append") {
|
|
1924
1995
|
previewToolProgressSuppressed = true;
|
|
1925
|
-
|
|
1996
|
+
legacyPreviewToolProgressLines = [];
|
|
1926
1997
|
const next = applyAppendOnlyStreamUpdate({
|
|
1927
1998
|
incoming: trimmed,
|
|
1928
1999
|
rendered: appendRenderedText,
|
|
@@ -1935,74 +2006,86 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1935
2006
|
hasStreamedMessage = true;
|
|
1936
2007
|
return;
|
|
1937
2008
|
}
|
|
1938
|
-
if (streamMode === "status_final")
|
|
1939
|
-
if (!progressDraftGate.hasStarted) return;
|
|
1940
|
-
statusUpdateCount += 1;
|
|
1941
|
-
if (statusUpdateCount > 1 && statusUpdateCount % 4 !== 0) return;
|
|
1942
|
-
renderProgressDraft();
|
|
1943
|
-
return;
|
|
1944
|
-
}
|
|
2009
|
+
if (streamMode === "status_final") return;
|
|
1945
2010
|
previewToolProgressSuppressed = true;
|
|
1946
|
-
|
|
2011
|
+
legacyPreviewToolProgressLines = [];
|
|
1947
2012
|
draftStream?.update(trimmed);
|
|
1948
2013
|
hasStreamedMessage = true;
|
|
1949
2014
|
};
|
|
1950
2015
|
const pushReasoningProgress = async (payload) => {
|
|
1951
2016
|
if (!payload?.text) return;
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
2017
|
+
if (streamMode !== "status_final") {
|
|
2018
|
+
const normalized = progressDraft.mergeReasoningProgress(payload.text, { snapshot: payload.isReasoningSnapshot === true }).replace(/^_(.*)_$/su, "$1").trim();
|
|
2019
|
+
if (!normalized) return;
|
|
2020
|
+
await pushPreviewProgress({
|
|
2021
|
+
id: "reasoning",
|
|
2022
|
+
kind: "item",
|
|
2023
|
+
text: normalized,
|
|
2024
|
+
label: "Reasoning"
|
|
2025
|
+
});
|
|
2026
|
+
return;
|
|
2027
|
+
}
|
|
2028
|
+
progressReceipt.noteReasoning();
|
|
2029
|
+
await progressDraft.pushReasoningProgress(payload.text, { snapshot: payload.isReasoningSnapshot === true });
|
|
1961
2030
|
};
|
|
1962
2031
|
const resetDraftDeliveryState = () => {
|
|
1963
2032
|
hasStreamedMessage = false;
|
|
1964
2033
|
appendRenderedText = "";
|
|
1965
2034
|
appendSourceText = "";
|
|
1966
|
-
statusUpdateCount = 0;
|
|
1967
2035
|
};
|
|
1968
2036
|
const resetDraftProgressState = () => {
|
|
1969
|
-
|
|
2037
|
+
progressDraft.resetReasoningProgress();
|
|
1970
2038
|
previewToolProgressSuppressed = false;
|
|
1971
|
-
|
|
2039
|
+
legacyPreviewToolProgressLines = [];
|
|
2040
|
+
};
|
|
2041
|
+
const beginNewProgressTurn = async (options) => {
|
|
2042
|
+
const completionChunks = useNativeProgressStreaming && !nativeProgressCompletionSent ? buildNativeProgressCompletionChunks(nativeProgressTerminalStatus) : void 0;
|
|
2043
|
+
if (!progressDraft.beginNewTurn(options)) return false;
|
|
2044
|
+
if (useNativeProgressStreaming) await finishNativeProgressTurn(completionChunks);
|
|
2045
|
+
else draftStream?.forceNewMessage();
|
|
2046
|
+
resetProgressTurnState();
|
|
2047
|
+
nativeTaskState = /* @__PURE__ */ new Map();
|
|
2048
|
+
nativeProgressCompletionSent = false;
|
|
2049
|
+
nativeProgressTerminalStatus = "complete";
|
|
2050
|
+
nativeProgressChunkKey = void 0;
|
|
2051
|
+
draftPreviewCommitted = false;
|
|
2052
|
+
observedFinalReplyDelivery = false;
|
|
2053
|
+
deliveryTracker = createSlackEventDeliveryTracker();
|
|
2054
|
+
progressReceiptCollapsed = false;
|
|
2055
|
+
return true;
|
|
1972
2056
|
};
|
|
1973
|
-
const onDraftBoundary = !shouldUseDraftStream ? void 0 : async () => {
|
|
1974
|
-
if (
|
|
1975
|
-
|
|
1976
|
-
|
|
2057
|
+
const onDraftBoundary = !shouldUseDraftStream && !useNativeProgressStreaming ? void 0 : async () => {
|
|
2058
|
+
if (streamMode === "status_final") {
|
|
2059
|
+
await beginNewProgressTurn();
|
|
2060
|
+
return;
|
|
1977
2061
|
}
|
|
2062
|
+
if (hasStreamedMessage) draftStream?.forceNewMessage();
|
|
2063
|
+
resetDraftDeliveryState();
|
|
1978
2064
|
resetDraftProgressState();
|
|
1979
2065
|
};
|
|
1980
|
-
const onQueuedFollowupAdmitted = !shouldUseDraftStream ? void 0 : async () => {
|
|
2066
|
+
const onQueuedFollowupAdmitted = !shouldUseDraftStream && !useNativeProgressStreaming ? void 0 : async () => {
|
|
1981
2067
|
await draftStream?.flush();
|
|
1982
|
-
draftStream?.forceNewMessage();
|
|
1983
2068
|
draftPreviewCommitted = false;
|
|
1984
2069
|
observedFinalReplyDelivery = false;
|
|
2070
|
+
if (streamMode === "status_final") await beginNewProgressTurn({ force: true });
|
|
2071
|
+
else draftStream?.forceNewMessage();
|
|
1985
2072
|
deliveryTracker = createSlackEventDeliveryTracker();
|
|
1986
2073
|
resetDraftDeliveryState();
|
|
1987
2074
|
resetDraftProgressState();
|
|
1988
|
-
latestPlan = void 0;
|
|
1989
|
-
latestPlanExplanation = void 0;
|
|
1990
|
-
nativeTaskState = /* @__PURE__ */ new Map();
|
|
1991
2075
|
};
|
|
1992
2076
|
let dispatchError;
|
|
1993
2077
|
let queuedFinal = false;
|
|
1994
2078
|
let counts = {};
|
|
1995
2079
|
try {
|
|
1996
|
-
const turnResult = await
|
|
2080
|
+
const turnResult = await dispatchChannelInboundTurn({
|
|
1997
2081
|
cfg,
|
|
1998
2082
|
channel: "slack",
|
|
1999
2083
|
accountId: route.accountId,
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2084
|
+
route: {
|
|
2085
|
+
agentId: route.agentId,
|
|
2086
|
+
sessionKey: route.sessionKey
|
|
2087
|
+
},
|
|
2003
2088
|
ctxPayload: prepared.ctxPayload,
|
|
2004
|
-
recordInboundSession,
|
|
2005
|
-
dispatchReplyWithBufferedBlockDispatcher,
|
|
2006
2089
|
dispatcherOptions: {
|
|
2007
2090
|
...replyPipeline,
|
|
2008
2091
|
humanDelay: resolveHumanDelayConfig(cfg, route.agentId)
|
|
@@ -2015,6 +2098,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2015
2098
|
history: prepared.turn.history,
|
|
2016
2099
|
botLoopProtection: resolveSlackBotLoopProtection(prepared),
|
|
2017
2100
|
replyOptions: {
|
|
2101
|
+
...prepared.turnAdoptionLifecycle ? { turnAdoptionLifecycle: prepared.turnAdoptionLifecycle } : {},
|
|
2018
2102
|
skillFilter: prepared.channelConfig?.skills,
|
|
2019
2103
|
sourceReplyDeliveryMode,
|
|
2020
2104
|
suppressTyping: suppressRoomEventTyping ? true : void 0,
|
|
@@ -2023,6 +2107,8 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2023
2107
|
onModelSelected,
|
|
2024
2108
|
suppressDefaultToolProgressMessages: suppressDefaultToolProgressMessages ? true : void 0,
|
|
2025
2109
|
commentaryProgressEnabled: commentaryProgressEnabled ? true : void 0,
|
|
2110
|
+
progressPreambleEnabled: progressDraftActive && slackStreaming.mode === "progress" ? true : void 0,
|
|
2111
|
+
commentaryPayloadsEnabled: commentaryProgressEnabled ? true : void 0,
|
|
2026
2112
|
onVerboseProgressVisibility: commentaryProgressEnabled ? (isActive) => {
|
|
2027
2113
|
shouldYieldDraftProgress = isActive;
|
|
2028
2114
|
} : void 0,
|
|
@@ -2032,7 +2118,10 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2032
2118
|
updateDraftFromPartial(payload.text);
|
|
2033
2119
|
},
|
|
2034
2120
|
onAssistantMessageStart: onDraftBoundary,
|
|
2035
|
-
onReasoningEnd:
|
|
2121
|
+
onReasoningEnd: async () => {
|
|
2122
|
+
progressReceipt.closeReasoning();
|
|
2123
|
+
await onDraftBoundary?.();
|
|
2124
|
+
},
|
|
2036
2125
|
onQueuedFollowupAdmitted,
|
|
2037
2126
|
onReasoningStream: statusReactionsEnabled || previewToolProgressEnabled ? async (payload) => {
|
|
2038
2127
|
await pushReasoningProgress(payload);
|
|
@@ -2041,6 +2130,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2041
2130
|
} : void 0,
|
|
2042
2131
|
onToolStart: async (payload) => {
|
|
2043
2132
|
if (statusReactionsEnabled) await statusReactions.setTool(payload.name);
|
|
2133
|
+
if (payload.phase === "start") progressReceipt.noteToolCall(payload.name);
|
|
2044
2134
|
await pushPreviewProgress(buildChannelProgressDraftLineForEntry(account.config, {
|
|
2045
2135
|
event: "tool",
|
|
2046
2136
|
itemId: payload.itemId,
|
|
@@ -2051,6 +2141,14 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2051
2141
|
}, payload.detailMode ? { detailMode: payload.detailMode } : void 0), { toolName: payload.name });
|
|
2052
2142
|
},
|
|
2053
2143
|
onItemEvent: async (payload) => {
|
|
2144
|
+
if (streamMode === "status_final" && payload.kind === "preamble") {
|
|
2145
|
+
if (shouldYieldDraftProgress()) return;
|
|
2146
|
+
await progressDraft.pushPreambleHeadline(payload.progressText, { itemId: payload.itemId });
|
|
2147
|
+
if (commentaryProgressEnabled) {
|
|
2148
|
+
if (await progressDraft.pushCommentaryProgress(payload.progressText, { itemId: payload.itemId })) progressReceipt.noteCommentary(payload.itemId, payload.progressText);
|
|
2149
|
+
}
|
|
2150
|
+
return;
|
|
2151
|
+
}
|
|
2054
2152
|
await pushPreviewProgress(buildChannelProgressDraftLineForEntry(account.config, {
|
|
2055
2153
|
event: "item",
|
|
2056
2154
|
itemId: payload.itemId,
|
|
@@ -2063,11 +2161,11 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2063
2161
|
summary: payload.summary,
|
|
2064
2162
|
progressText: payload.progressText,
|
|
2065
2163
|
meta: payload.meta
|
|
2066
|
-
})
|
|
2164
|
+
}));
|
|
2067
2165
|
},
|
|
2068
2166
|
onPlanUpdate: async (payload) => {
|
|
2069
2167
|
if (payload.phase !== "update") return;
|
|
2070
|
-
await pushPlanProgress(payload.
|
|
2168
|
+
await pushPlanProgress(payload.steps, payload.explanation);
|
|
2071
2169
|
},
|
|
2072
2170
|
onApprovalEvent: async (payload) => {
|
|
2073
2171
|
if (payload.phase !== "requested") return;
|
|
@@ -2118,30 +2216,26 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2118
2216
|
} catch (err) {
|
|
2119
2217
|
dispatchError = err;
|
|
2120
2218
|
} finally {
|
|
2121
|
-
|
|
2219
|
+
progressDraft.cancel();
|
|
2122
2220
|
await draftStream?.discardPending();
|
|
2123
2221
|
}
|
|
2124
2222
|
let streamFallbackDelivered = false;
|
|
2125
2223
|
const finalStream = streamSession;
|
|
2126
2224
|
if (finalStream && !finalStream.stopped) try {
|
|
2127
|
-
const completionChunks = useNativeProgressStreaming && !nativeProgressCompletionSent
|
|
2128
|
-
previousTasks: nativeTaskState,
|
|
2129
|
-
chunks: buildSlackProgressStreamCompletionChunks({
|
|
2130
|
-
title: resolveNativeProgressTitle(),
|
|
2131
|
-
lines: resolveNativeProgressLines(),
|
|
2132
|
-
plan: resolveNativeProgressPlan(),
|
|
2133
|
-
maxLineChars: progressDraftMaxLineChars,
|
|
2134
|
-
finalInProgressStatus: dispatchError ? "error" : "complete"
|
|
2135
|
-
})
|
|
2136
|
-
}).chunks : void 0;
|
|
2225
|
+
const completionChunks = useNativeProgressStreaming && !nativeProgressCompletionSent ? buildNativeProgressCompletionChunks(dispatchError ? "error" : nativeProgressTerminalStatus) : void 0;
|
|
2137
2226
|
if (completionChunks?.length) nativeProgressCompletionSent = true;
|
|
2138
2227
|
const stopResult = await stopSlackStream({
|
|
2139
2228
|
session: finalStream,
|
|
2140
2229
|
...completionChunks?.length ? { chunks: completionChunks } : {},
|
|
2141
2230
|
...slackMessageMetadata ? { metadata: slackMessageMetadata } : {}
|
|
2142
2231
|
});
|
|
2143
|
-
|
|
2144
|
-
|
|
2232
|
+
acknowledgeStoppedStreamedDeliveries(finalStream, stopResult?.messageId);
|
|
2233
|
+
if (pendingNativeProgressReceipt && stopResult?.messageId && !progressReceiptCollapsed) await collapseProgressReceipt({
|
|
2234
|
+
channelId: finalStream.channel,
|
|
2235
|
+
messageId: stopResult.messageId,
|
|
2236
|
+
text: pendingNativeProgressReceipt,
|
|
2237
|
+
threadTs: finalStream.threadTs
|
|
2238
|
+
});
|
|
2145
2239
|
} catch (err) {
|
|
2146
2240
|
if (err instanceof SlackStreamNotDeliveredError) {
|
|
2147
2241
|
streamFallbackDelivered = await deliverPendingStreamFallback(finalStream, err);
|
|
@@ -2174,19 +2268,10 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2174
2268
|
observedReplyDelivery,
|
|
2175
2269
|
fallbackDelivered: streamFallbackDelivered
|
|
2176
2270
|
});
|
|
2177
|
-
if (statusReactionsEnabled) if (dispatchError)
|
|
2178
|
-
|
|
2179
|
-
if (ctx.removeAckAfterReply) (async () => {
|
|
2180
|
-
await sleep(statusReactionTiming.errorHoldMs);
|
|
2181
|
-
if (anyReplyDelivered) await statusReactions.clear();
|
|
2182
|
-
})();
|
|
2183
|
-
} else if (anyReplyDelivered) {
|
|
2271
|
+
if (statusReactionsEnabled) if (dispatchError) await statusReactions.setError();
|
|
2272
|
+
else if (anyReplyDelivered) {
|
|
2184
2273
|
await statusReactions.setDone();
|
|
2185
|
-
|
|
2186
|
-
await sleep(statusReactionTiming.doneHoldMs);
|
|
2187
|
-
await statusReactions.clear();
|
|
2188
|
-
})();
|
|
2189
|
-
else statusReactions.restoreInitial();
|
|
2274
|
+
statusReactions.restoreInitial();
|
|
2190
2275
|
} else await statusReactions.restoreInitial();
|
|
2191
2276
|
const participationThreadTs = usedReplyThreadTs ?? statusThreadTs;
|
|
2192
2277
|
if (anyReplyDelivered && participationThreadTs) recordSlackThreadParticipation(account.accountId, message.channel, participationThreadTs, {
|
|
@@ -2202,23 +2287,6 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2202
2287
|
const finalCount = counts.final;
|
|
2203
2288
|
logVerbose(`slack: delivered ${finalCount} reply${finalCount === 1 ? "" : "ies"} to ${prepared.replyTarget}`);
|
|
2204
2289
|
}
|
|
2205
|
-
if (!statusReactionsEnabled) removeAckReactionAfterReply({
|
|
2206
|
-
removeAfterReply: ctx.removeAckAfterReply && anyReplyDelivered,
|
|
2207
|
-
ackReactionPromise: prepared.ackReactionPromise,
|
|
2208
|
-
ackReactionValue: prepared.ackReactionValue,
|
|
2209
|
-
remove: () => removeSlackReaction(message.channel, prepared.ackReactionMessageTs ?? "", prepared.ackReactionValue, {
|
|
2210
|
-
token: ctx.botToken,
|
|
2211
|
-
client: slackClient
|
|
2212
|
-
}),
|
|
2213
|
-
onError: (err) => {
|
|
2214
|
-
logAckFailure({
|
|
2215
|
-
log: logVerbose,
|
|
2216
|
-
channel: "slack",
|
|
2217
|
-
target: `${message.channel}/${message.ts}`,
|
|
2218
|
-
error: err
|
|
2219
|
-
});
|
|
2220
|
-
}
|
|
2221
|
-
});
|
|
2222
2290
|
}
|
|
2223
2291
|
function toLintErrorObject(value, fallbackMessage) {
|
|
2224
2292
|
if (value instanceof Error) return value;
|
|
@@ -2228,6 +2296,51 @@ function toLintErrorObject(value, fallbackMessage) {
|
|
|
2228
2296
|
return error;
|
|
2229
2297
|
}
|
|
2230
2298
|
//#endregion
|
|
2299
|
+
//#region extensions/slack/src/agent-context.ts
|
|
2300
|
+
function asRecord(value) {
|
|
2301
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
2302
|
+
}
|
|
2303
|
+
function trimmedString(value) {
|
|
2304
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
2305
|
+
}
|
|
2306
|
+
function normalizeEntity(value) {
|
|
2307
|
+
const entity = asRecord(value);
|
|
2308
|
+
const type = trimmedString(entity?.type);
|
|
2309
|
+
if (!entity || !type) return;
|
|
2310
|
+
const teamId = trimmedString(entity.team_id);
|
|
2311
|
+
if (type === "slack#/types/channel_id" || type === "slack#/types/canvas_id" || type === "slack#/types/list_id") {
|
|
2312
|
+
const entityValue = trimmedString(entity.value);
|
|
2313
|
+
return entityValue ? {
|
|
2314
|
+
type,
|
|
2315
|
+
value: entityValue,
|
|
2316
|
+
...teamId ? { team_id: teamId } : {}
|
|
2317
|
+
} : void 0;
|
|
2318
|
+
}
|
|
2319
|
+
if (type !== "slack#/types/message_context") return;
|
|
2320
|
+
const message = asRecord(entity.value);
|
|
2321
|
+
const channelId = trimmedString(message?.channel_id);
|
|
2322
|
+
const messageTs = trimmedString(message?.message_ts);
|
|
2323
|
+
return channelId && messageTs ? {
|
|
2324
|
+
type,
|
|
2325
|
+
value: {
|
|
2326
|
+
channel_id: channelId,
|
|
2327
|
+
message_ts: messageTs
|
|
2328
|
+
},
|
|
2329
|
+
...teamId ? { team_id: teamId } : {}
|
|
2330
|
+
} : void 0;
|
|
2331
|
+
}
|
|
2332
|
+
function isSlackAppContext(value) {
|
|
2333
|
+
return Boolean(asRecord(value));
|
|
2334
|
+
}
|
|
2335
|
+
function normalizeSlackAppContextEntities(value) {
|
|
2336
|
+
const context = asRecord(value);
|
|
2337
|
+
if (!Array.isArray(context?.entities)) return [];
|
|
2338
|
+
return context.entities.flatMap((entity) => {
|
|
2339
|
+
const normalized = normalizeEntity(entity);
|
|
2340
|
+
return normalized ? [normalized] : [];
|
|
2341
|
+
});
|
|
2342
|
+
}
|
|
2343
|
+
//#endregion
|
|
2231
2344
|
//#region extensions/slack/src/monitor/message-handler/preflight-audio.ts
|
|
2232
2345
|
const SLACK_DEFAULT_ECHO_TRANSCRIPT_FORMAT = "📝 \"{transcript}\"";
|
|
2233
2346
|
const loadSlackPreflightAudioRuntime = createLazyRuntimeModule(() => import("./preflight-audio.runtime-D5Bgags0.js"));
|
|
@@ -2267,8 +2380,7 @@ async function resolveSlackPreflightAudioTranscript(params) {
|
|
|
2267
2380
|
const { transcribeFirstAudio } = await loadSlackPreflightAudioRuntime();
|
|
2268
2381
|
const transcript = await transcribeFirstAudio({
|
|
2269
2382
|
ctx: {
|
|
2270
|
-
|
|
2271
|
-
MediaTypes: params.media.map((entry) => entry.contentType ?? ""),
|
|
2383
|
+
media: [...params.media],
|
|
2272
2384
|
Provider: "slack",
|
|
2273
2385
|
Surface: "slack",
|
|
2274
2386
|
OriginatingChannel: "slack",
|
|
@@ -2321,7 +2433,7 @@ async function discardSlackPreflightMedia(media) {
|
|
|
2321
2433
|
const SLACK_MENTION_RESOLUTION_CONCURRENCY = 4;
|
|
2322
2434
|
const SLACK_MENTION_RESOLUTION_MAX_LOOKUPS_PER_MESSAGE = 20;
|
|
2323
2435
|
const SLACK_USER_MENTION_RE$1 = /<@([A-Z0-9]+)(?:\|[^>]+)?>/gi;
|
|
2324
|
-
const loadSlackMediaModule$1 = createLazyRuntimeModule(() => import("./actions-
|
|
2436
|
+
const loadSlackMediaModule$1 = createLazyRuntimeModule(() => import("./actions-D51foiwR.js").then((n) => n.g));
|
|
2325
2437
|
function collectUniqueSlackMentionIds$1(texts) {
|
|
2326
2438
|
const seen = /* @__PURE__ */ new Set();
|
|
2327
2439
|
const mentionIds = [];
|
|
@@ -2600,7 +2712,7 @@ function resolveSlackInitialAgentRoute(params) {
|
|
|
2600
2712
|
};
|
|
2601
2713
|
}
|
|
2602
2714
|
function resolveSlackRoutingContext(params) {
|
|
2603
|
-
const { ctx, account, message, isDirectMessage, isGroupDm, isRoom, isRoomish, channelConfig, seedTopLevelRoomThread, assistantThreadTs, eventScope } = params;
|
|
2715
|
+
const { ctx, account, message, isDirectMessage, isGroupDm, isRoom, isRoomish, channelConfig, seedTopLevelRoomThread, assistantThreadTs, agentViewThreadTs, eventScope } = params;
|
|
2604
2716
|
let route = resolveSlackInitialAgentRoute({
|
|
2605
2717
|
ctx,
|
|
2606
2718
|
account,
|
|
@@ -2620,7 +2732,7 @@ function resolveSlackRoutingContext(params) {
|
|
|
2620
2732
|
const isThreadReply = threadContext.isThreadReply;
|
|
2621
2733
|
const autoThreadId = !isThreadReply && replyToMode === "all" && threadContext.messageTs ? threadContext.messageTs : void 0;
|
|
2622
2734
|
const seedCandidateThreadId = threadContext.incomingThreadTs ?? threadContext.messageTs;
|
|
2623
|
-
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);
|
|
2735
|
+
const routedThreadId = (isDirectMessage ? assistantThreadTs ?? agentViewThreadTs : isRoomish ? isThreadReply && threadTs ? threadTs : void 0 : isThreadReply ? threadTs : autoThreadId) ?? (isRoomish ? !isThreadReply && isRoom && seedTopLevelRoomThread && replyToMode !== "off" && seedCandidateThreadId ? seedCandidateThreadId : void 0 : void 0);
|
|
2624
2736
|
const baseConversationId = resolveSlackBaseConversationId({
|
|
2625
2737
|
message,
|
|
2626
2738
|
isDirectMessage,
|
|
@@ -2743,7 +2855,7 @@ function formatSlackThreadLabelSnippet(text) {
|
|
|
2743
2855
|
}
|
|
2744
2856
|
//#endregion
|
|
2745
2857
|
//#region extensions/slack/src/monitor/message-handler/prepare-thread-context.ts
|
|
2746
|
-
const loadSlackMediaModule = createLazyRuntimeModule(() => import("./actions-
|
|
2858
|
+
const loadSlackMediaModule = createLazyRuntimeModule(() => import("./actions-D51foiwR.js").then((n) => n.g));
|
|
2747
2859
|
const SLACK_THREAD_CONTEXT_USER_LOOKUP_CONCURRENCY = 4;
|
|
2748
2860
|
function resolveSlackThreadSessionFreshness(params) {
|
|
2749
2861
|
return params.ctx.channelRuntime?.session?.resolveEntryResetFreshness?.({
|
|
@@ -2758,14 +2870,21 @@ function resolveSlackThreadSessionFreshness(params) {
|
|
|
2758
2870
|
});
|
|
2759
2871
|
}
|
|
2760
2872
|
function isSlackThreadContextSenderAllowed(params) {
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2873
|
+
return resolveInboundSupplementalSenderAllowed({
|
|
2874
|
+
isGroup: true,
|
|
2875
|
+
groupPolicy: params.allowFromLower.length === 0 ? "open" : "allowlist",
|
|
2876
|
+
allowFrom: params.allowFromLower,
|
|
2877
|
+
isSenderAllowed: (allowFrom) => {
|
|
2878
|
+
if (params.botId) return true;
|
|
2879
|
+
if (!params.userId) return false;
|
|
2880
|
+
return resolveSlackAllowListMatch({
|
|
2881
|
+
allowList: allowFrom,
|
|
2882
|
+
id: params.userId,
|
|
2883
|
+
name: params.userName,
|
|
2884
|
+
allowNameMatching: params.allowNameMatching
|
|
2885
|
+
}).allowed;
|
|
2886
|
+
}
|
|
2887
|
+
});
|
|
2769
2888
|
}
|
|
2770
2889
|
async function resolveSlackThreadUserMap(params) {
|
|
2771
2890
|
const uniqueUserIds = [];
|
|
@@ -3389,6 +3508,14 @@ async function prepareSlackMessage(params) {
|
|
|
3389
3508
|
const assistantThreadContext = mergeSlackAssistantThreadContext(messageAssistantThreadContext, cachedAssistantThreadContext ?? restoredAssistantThreadContext);
|
|
3390
3509
|
const assistantThreadContextToCache = messageAssistantThreadContext || restoredAssistantThreadContext ? assistantThreadContext : void 0;
|
|
3391
3510
|
if (assistantThreadContextToCache) ctx.saveSlackAssistantThreadContext(assistantThreadContextToCache, opts.eventScope);
|
|
3511
|
+
const hasAgentViewMessageSignal = isDirectMessage && !opts.eventScope && !assistantThreadContext && isSlackAppContext(message.app_context);
|
|
3512
|
+
if (hasAgentViewMessageSignal) await ctx.recordSlackAgentView();
|
|
3513
|
+
const managedViewThreadTs = message.thread_ts;
|
|
3514
|
+
const isManagedViewRoot = isDirectMessage && !opts.eventScope && !assistantThreadContext && !message.parent_user_id && Boolean(managedViewThreadTs && message.ts && managedViewThreadTs === message.ts);
|
|
3515
|
+
if (isManagedViewRoot && managedViewThreadTs) await ctx.recordSlackManagedViewThread(message.channel, managedViewThreadTs);
|
|
3516
|
+
const hasManagedViewThread = isDirectMessage && !opts.eventScope && !assistantThreadContext && Boolean(managedViewThreadTs && await ctx.isSlackManagedViewThread(message.channel, managedViewThreadTs));
|
|
3517
|
+
const isAgentViewMessage = isDirectMessage && !opts.eventScope && !assistantThreadContext && (hasAgentViewMessageSignal || isManagedViewRoot || hasManagedViewThread || await ctx.isSlackAgentView());
|
|
3518
|
+
const agentViewThreadTs = isAgentViewMessage ? message.thread_ts ?? message.ts : void 0;
|
|
3392
3519
|
const channelReplyToMode = channelConfig?.replyToMode ?? resolveSlackReplyToMode(account, channelChatType);
|
|
3393
3520
|
const willImplicitlyThreadReply = isRoom && !channelRequireMention && channelReplyToMode !== "off";
|
|
3394
3521
|
const seedTopLevelRoomThreadBySource = opts.source === "app_mention" || opts.wasMentioned === true || explicitlyMentioned || willImplicitlyThreadReply;
|
|
@@ -3403,6 +3530,7 @@ async function prepareSlackMessage(params) {
|
|
|
3403
3530
|
channelConfig,
|
|
3404
3531
|
seedTopLevelRoomThread: seedTopLevelRoomThreadBySource,
|
|
3405
3532
|
assistantThreadTs: assistantThreadContext?.threadTs,
|
|
3533
|
+
agentViewThreadTs,
|
|
3406
3534
|
eventScope: opts.eventScope
|
|
3407
3535
|
});
|
|
3408
3536
|
let mentionCheckTranscript;
|
|
@@ -3428,6 +3556,7 @@ async function prepareSlackMessage(params) {
|
|
|
3428
3556
|
const { configuredBinding, configuredBindingSessionKey } = routing;
|
|
3429
3557
|
const isAssistantThreadMessage = Boolean(isDirectMessage && messageAssistantThreadContext);
|
|
3430
3558
|
const forcedAssistantReplyThreadTs = Boolean(assistantThreadContext?.threadTs && (isThreadReply || isAssistantThreadMessage || replyToMode !== "off")) ? assistantThreadContext?.threadTs : void 0;
|
|
3559
|
+
const forcedReplyThreadTs = agentViewThreadTs ?? forcedAssistantReplyThreadTs;
|
|
3431
3560
|
if (runtimeBinding && shouldLogVerbose()) logVerbose(`slack: routed via bound conversation ${runtimeBinding.conversation.conversationId} -> ${runtimeBinding.targetSessionKey}`);
|
|
3432
3561
|
if (configuredBinding) {
|
|
3433
3562
|
const ensured = await ensureConfiguredBindingRouteReady({
|
|
@@ -3458,7 +3587,7 @@ async function prepareSlackMessage(params) {
|
|
|
3458
3587
|
name: void 0
|
|
3459
3588
|
});
|
|
3460
3589
|
let implicitMentionKinds = [];
|
|
3461
|
-
if (!isDirectMessage && ctx.botUserId && message.thread_ts && !
|
|
3590
|
+
if (!isDirectMessage && ctx.botUserId && message.thread_ts && !wasMentioned) {
|
|
3462
3591
|
const replyToBotKinds = implicitMentionKindWhen("reply_to_bot", message.parent_user_id === ctx.botUserId);
|
|
3463
3592
|
implicitMentionKinds = replyToBotKinds.length > 0 ? replyToBotKinds : implicitMentionKindWhen("bot_thread_participant", await hasSlackThreadParticipationWithPersistence({
|
|
3464
3593
|
accountId: account.accountId,
|
|
@@ -3554,6 +3683,11 @@ async function prepareSlackMessage(params) {
|
|
|
3554
3683
|
surface: "slack"
|
|
3555
3684
|
});
|
|
3556
3685
|
const shouldRequireMention = isRoom ? channelConfig?.requireMention ?? ctx.defaultRequireMention : false;
|
|
3686
|
+
const implicitMentions = resolveChannelImplicitMentions({
|
|
3687
|
+
cfg,
|
|
3688
|
+
channel: "slack",
|
|
3689
|
+
accountId: account.accountId
|
|
3690
|
+
});
|
|
3557
3691
|
if (message["_ambiguousThreadReply"]) {
|
|
3558
3692
|
ctx.logger.info({
|
|
3559
3693
|
channel: message.channel,
|
|
@@ -3586,7 +3720,7 @@ async function prepareSlackMessage(params) {
|
|
|
3586
3720
|
activation: {
|
|
3587
3721
|
requireMention: shouldRequireMention,
|
|
3588
3722
|
allowTextCommands,
|
|
3589
|
-
|
|
3723
|
+
implicitMentions
|
|
3590
3724
|
}
|
|
3591
3725
|
});
|
|
3592
3726
|
const senderGate = messageIngress.senderAccess.gate;
|
|
@@ -3633,6 +3767,7 @@ async function prepareSlackMessage(params) {
|
|
|
3633
3767
|
channelConfig,
|
|
3634
3768
|
seedTopLevelRoomThread: true,
|
|
3635
3769
|
assistantThreadTs: assistantThreadContext?.threadTs,
|
|
3770
|
+
agentViewThreadTs,
|
|
3636
3771
|
eventScope: opts.eventScope
|
|
3637
3772
|
});
|
|
3638
3773
|
return seededMentionRouting;
|
|
@@ -3684,7 +3819,7 @@ async function prepareSlackMessage(params) {
|
|
|
3684
3819
|
preflightAudioTranscript = void 0;
|
|
3685
3820
|
preflightAudioMedia = void 0;
|
|
3686
3821
|
}
|
|
3687
|
-
const directThreadRoutedToDmSession = !assistantThreadContext && isDirectMessage && isThreadReply && threadTs && runtimeBinding?.conversation.conversationId !== threadTs;
|
|
3822
|
+
const directThreadRoutedToDmSession = !assistantThreadContext && !agentViewThreadTs && isDirectMessage && isThreadReply && threadTs && runtimeBinding?.conversation.conversationId !== threadTs;
|
|
3688
3823
|
const mentionDecision = resolveInboundMentionDecision({
|
|
3689
3824
|
facts: {
|
|
3690
3825
|
canDetectMention,
|
|
@@ -3698,7 +3833,7 @@ async function prepareSlackMessage(params) {
|
|
|
3698
3833
|
allowTextCommands,
|
|
3699
3834
|
hasControlCommand: hasControlCommandInMessage,
|
|
3700
3835
|
commandAuthorized,
|
|
3701
|
-
|
|
3836
|
+
implicitMentions
|
|
3702
3837
|
}
|
|
3703
3838
|
});
|
|
3704
3839
|
const effectiveWasMentioned = mentionDecision.effectiveWasMentioned;
|
|
@@ -3845,7 +3980,7 @@ async function prepareSlackMessage(params) {
|
|
|
3845
3980
|
previousTimestamp,
|
|
3846
3981
|
envelope: envelopeOptions
|
|
3847
3982
|
});
|
|
3848
|
-
const dmHistoryContext = isDirectMessage && !isThreadReply && dmHistoryLimit > 0 && !previousTimestamp ? await resolveSlackDmHistoryContext({
|
|
3983
|
+
const dmHistoryContext = isDirectMessage && !assistantThreadContext && !agentViewThreadTs && !isThreadReply && dmHistoryLimit > 0 && !previousTimestamp ? await resolveSlackDmHistoryContext({
|
|
3849
3984
|
ctx,
|
|
3850
3985
|
channelId: message.channel,
|
|
3851
3986
|
currentMessageTs: message.ts,
|
|
@@ -3903,7 +4038,8 @@ async function prepareSlackMessage(params) {
|
|
|
3903
4038
|
}) : dmHistoryContext.inboundHistory;
|
|
3904
4039
|
const commandBody = textForCommandDetection.trim();
|
|
3905
4040
|
const supplementalThreadHistoryBody = directThreadRoutedToDmSession && !threadHistoryBody ? threadStarterBody : threadHistoryBody;
|
|
3906
|
-
const effectiveMessageThreadId = assistantThreadContext?.threadTs ?? threadContext.messageThreadId;
|
|
4041
|
+
const effectiveMessageThreadId = assistantThreadContext?.threadTs ?? agentViewThreadTs ?? threadContext.messageThreadId;
|
|
4042
|
+
const agentContextEntities = isAgentViewMessage ? normalizeSlackAppContextEntities(message.app_context) : [];
|
|
3907
4043
|
const ctxPayload = buildChannelInboundEventContext({
|
|
3908
4044
|
channel: "slack",
|
|
3909
4045
|
accountId: route.accountId,
|
|
@@ -3926,6 +4062,7 @@ async function prepareSlackMessage(params) {
|
|
|
3926
4062
|
},
|
|
3927
4063
|
route: {
|
|
3928
4064
|
agentId: route.agentId,
|
|
4065
|
+
dmScope: route.dmScope,
|
|
3929
4066
|
accountId: route.accountId,
|
|
3930
4067
|
routeSessionKey: sessionKey,
|
|
3931
4068
|
parentSessionKey: threadKeys.parentSessionKey
|
|
@@ -3944,6 +4081,7 @@ async function prepareSlackMessage(params) {
|
|
|
3944
4081
|
commandBody,
|
|
3945
4082
|
inboundHistory
|
|
3946
4083
|
},
|
|
4084
|
+
sessionTranscript: { historyLimit: isRoomish ? ctx.historyLimit : dmHistoryLimit },
|
|
3947
4085
|
access: {
|
|
3948
4086
|
mentions: {
|
|
3949
4087
|
canDetectMention: isRoomish,
|
|
@@ -3967,8 +4105,15 @@ async function prepareSlackMessage(params) {
|
|
|
3967
4105
|
extra: {
|
|
3968
4106
|
GroupSubject: isRoomish ? roomLabel : void 0,
|
|
3969
4107
|
UntrustedContext: untrustedChannelMetadata ? [untrustedChannelMetadata] : void 0,
|
|
4108
|
+
UntrustedStructuredContext: agentContextEntities.length > 0 ? [{
|
|
4109
|
+
label: "Slack active context",
|
|
4110
|
+
source: "slack",
|
|
4111
|
+
type: "active_view",
|
|
4112
|
+
payload: { entities: agentContextEntities }
|
|
4113
|
+
}] : void 0,
|
|
3970
4114
|
TransportThreadId: directThreadRoutedToDmSession ? threadContext.messageThreadId : void 0,
|
|
3971
4115
|
SlackAssistantThread: assistantThreadContext ? true : void 0,
|
|
4116
|
+
SlackAgentThread: agentViewThreadTs ? true : void 0,
|
|
3972
4117
|
SlackAssistantThreadContextChannelId: assistantThreadContext?.channelId,
|
|
3973
4118
|
SlackAssistantThreadContextTeamId: assistantThreadContext?.teamId,
|
|
3974
4119
|
SlackAssistantThreadContextEnterpriseId: assistantThreadContext?.enterpriseId ?? void 0,
|
|
@@ -4058,7 +4203,7 @@ async function prepareSlackMessage(params) {
|
|
|
4058
4203
|
} : void 0
|
|
4059
4204
|
},
|
|
4060
4205
|
replyToMode,
|
|
4061
|
-
...
|
|
4206
|
+
...forcedReplyThreadTs ? { forcedReplyThreadTs } : {},
|
|
4062
4207
|
...assistantThreadContext ? { slackMessageMetadata: buildSlackAssistantThreadMetadata(assistantThreadContext) } : {},
|
|
4063
4208
|
requireMention: shouldRequireMention,
|
|
4064
4209
|
isDirectMessage,
|