@openclaw/slack 2026.7.2-beta.1 → 2026.7.2-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-configured-DzC407uv.js → account-configured-BwfXBo_F.js} +1 -1
- package/dist/{account-inspect-Di7ditqZ.js → account-inspect-Bvbtu3iH.js} +9 -2
- package/dist/account-inspect-api.js +1 -1
- package/dist/{accounts-BOJJiHSr.js → accounts-DQEbYKh9.js} +9 -0
- package/dist/accounts.runtime-BIKmJdtJ.js +2 -0
- package/dist/{action-runtime-p6M2ULpv.js → action-runtime-DqkRwO3Z.js} +14 -17
- package/dist/action-runtime.runtime-DEWOcFM4.js +2 -0
- package/dist/{actions-DkTcWmpT.js → actions-CF0tUY5q.js} +5 -9
- package/dist/{actions.runtime-BSxpwgUc.js → actions.runtime-hCbx4RXg.js} +1 -1
- package/dist/api.js +13 -14
- package/dist/{approval-handler.runtime-UGbnz9OC.js → approval-handler.runtime-Em8I1-8-.js} +2 -2
- package/dist/{channel-B0_j6C6z.js → channel-4-TRi1D6.js} +75 -41
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-type-BpeTezY4.js → channel-type-Cu1yjNg2.js} +3 -3
- package/dist/{channel.setup-BQFut21T.js → channel.setup-CgkADtZg.js} +6 -4
- package/dist/{config-schema-DYI01PV2.js → config-schema-XjJGfwQC.js} +18 -5
- package/dist/{directory-config-DRkFujwG.js → directory-config-Bv0lcUlH.js} +1 -1
- package/dist/directory-contract-api.js +1 -1
- package/dist/{directory-live-DX7yFsM-.js → directory-live-CzUIB7th.js} +2 -2
- package/dist/{doctor-contract-DddfkMlF.js → doctor-contract-DKpe5VBr.js} +80 -12
- package/dist/doctor-contract-api.js +1 -1
- package/dist/{group-policy-C-b2ZnSl.js → group-policy-Bw-65m3V.js} +94 -135
- package/dist/{interactive-replies-BilWUdcI.js → interactive-replies-Dm_t2R9S.js} +1 -1
- package/dist/interactive-replies-api.js +1 -1
- package/dist/{message-tool-api-CA9jZrCY.js → message-tool-api-C2pcf5du.js} +3 -3
- package/dist/message-tool-api.js +1 -1
- package/dist/{monitor-BN_uuvrQ.js → monitor-CNFeF30h.js} +3 -3
- package/dist/{outbound-adapter-ECl0go7d.js → outbound-adapter-CVi2uok0.js} +49 -5
- package/dist/{pipeline.runtime-f0eJJoJL.js → pipeline.runtime-CTvokbty.js} +485 -251
- package/dist/{policy-f8b0edSi.js → policy-b_dOPDCq.js} +7 -7
- package/dist/probe-Borhn9PQ.js +340 -0
- package/dist/{provider-Ds-y-imP.js → provider-B-HVL5ZE.js} +831 -329
- package/dist/{relay-source-B-6LFUdz.js → relay-source-Ea_P9VcO.js} +6 -11
- package/dist/{replies-BMvf3ihj.js → replies-B4bOdrYb.js} +3 -3
- package/dist/{resolve-channels-DOMgNCWb.js → resolve-channels-KTc568SU.js} +1 -1
- package/dist/{resolve-users-aL6-Ssee.js → resolve-users-DeGJf1yp.js} +1 -1
- package/dist/{runtime-CauEvswP.js → runtime-JSVZSWAj.js} +2 -2
- package/dist/{runtime-api-CVb6CQjX.js → runtime-api-BFfNpzDe.js} +1 -1
- package/dist/runtime-api.js +12 -12
- package/dist/runtime-setter-api.js +1 -1
- package/dist/{scopes-Dw8wbU0j.js → scopes-lx08L56K.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/{send-NEfJ0GvM.js → send-KuTDky7i.js} +29 -12
- package/dist/send.runtime-CXyxws1D.js +2 -0
- package/dist/setup-core-CeiAVwQ3.js +502 -0
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-BN2WeG5c.js → setup-surface-DLA0vHXp.js} +23 -13
- package/dist/{shared-BLnB9R1T.js → shared-C4yVB0Q-.js} +64 -41
- package/dist/{slash-dispatch.runtime-C0Otuf_T.js → slash-dispatch.runtime-BT-mMm-f.js} +1 -1
- package/npm-shrinkwrap.json +3 -3
- package/openclaw.plugin.json +134 -10
- package/package.json +5 -7
- package/dist/accounts.runtime-KvftRRek.js +0 -2
- package/dist/action-runtime.runtime-DQstDkHG.js +0 -2
- package/dist/client-D2F6m8CP.js +0 -152
- package/dist/configured-state.js +0 -11
- package/dist/probe-CfALk0l4.js +0 -48
- package/dist/send.runtime-BkKpitPu.js +0 -2
- package/dist/setup-core-fGd6Gquy.js +0 -343
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import { u as resolveSlackReplyToMode } from "./accounts-
|
|
1
|
+
import { u as resolveSlackReplyToMode } from "./accounts-DQEbYKh9.js";
|
|
2
2
|
import { i as parseSlackTarget } from "./target-parsing-N6lHogYZ.js";
|
|
3
3
|
import "./targets-KmjP2E8s.js";
|
|
4
|
-
import { C as hasSlackNativeDataBlock, F as SLACK_TEXT_LIMIT,
|
|
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-Bw-65m3V.js";
|
|
5
|
+
import { n as isSlackInteractiveRepliesEnabled, t as compileSlackInteractiveReplies } from "./interactive-replies-Dm_t2R9S.js";
|
|
6
|
+
import { r as formatSlackError } from "./probe-Borhn9PQ.js";
|
|
6
7
|
import { n as resolveSlackNativeStreaming, r as resolveSlackStreamingMode, t as mapStreamingModeToSlackLegacyDraftStreamMode } from "./streaming-compat-3_X-21wW.js";
|
|
7
|
-
import {
|
|
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-CF0tUY5q.js";
|
|
9
|
+
import { c as hasSlackThreadParticipationWithPersistence, l as recordSlackThreadParticipation, r as sendMessageSlack, u as buildSlackNativeDataDeliveryPlan } from "./send-KuTDky7i.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-B-HVL5ZE.js";
|
|
11
|
+
import { n as resolveSlackChannelConfig } from "./policy-b_dOPDCq.js";
|
|
12
|
+
import { a as resolveDeliveredSlackReplyThreadTs, i as readSlackReplyBlocks, n as deliverReplies, o as resolveSlackThreadTs, s as emitSlackMessageSentHooks, t as createSlackReplyDeliveryPlan } from "./replies-B4bOdrYb.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
17
|
import { danger, logVerbose, shouldLogVerbose, sleep } from "openclaw/plugin-sdk/runtime-env";
|
|
17
|
-
import { stripReasoningTagsFromText } from "openclaw/plugin-sdk/text-chunking";
|
|
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 {
|
|
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";
|
|
31
32
|
import { DEFAULT_TIMING, createStatusReactionController, logAckFailure, logTypingFailure, removeAckReactionAfterReply, resolveAckReaction, shouldAckReaction } from "openclaw/plugin-sdk/channel-feedback";
|
|
32
|
-
import { dispatchReplyWithBufferedBlockDispatcher } from "openclaw/plugin-sdk/reply-runtime";
|
|
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,17 +216,49 @@ 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
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
status: lineTaskStatus(line)
|
|
239
|
+
if (params.plan) return params.plan.slice(-50).map((entry, index) => ({
|
|
240
|
+
id: `plan_step_${index + 1}`,
|
|
241
|
+
title: compactTitle(entry.step),
|
|
242
|
+
status: entry.status === "completed" ? "complete" : entry.status
|
|
229
243
|
}));
|
|
244
|
+
const maxLineChars = resolveMaxLineChars(params.maxLineChars, DEFAULT_SLACK_PROGRESS_TASK_DETAIL_MAX_CHARS);
|
|
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
|
+
});
|
|
230
262
|
}
|
|
231
263
|
function resolvePlanTitle(params) {
|
|
232
264
|
return compactChunkText(params.title?.trim() || params.label?.trim() || params.tasks.at(-1)?.title || SLACK_PROGRESS_PLAN_FALLBACK_TITLE);
|
|
@@ -234,9 +266,16 @@ function resolvePlanTitle(params) {
|
|
|
234
266
|
function buildSlackProgressStreamChunks(params) {
|
|
235
267
|
const tasks = buildPlanTasks({
|
|
236
268
|
lines: params.lines,
|
|
269
|
+
plan: params.plan,
|
|
237
270
|
maxLineChars: params.maxLineChars
|
|
238
271
|
});
|
|
239
|
-
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
|
+
}
|
|
240
279
|
return [{
|
|
241
280
|
type: "plan_update",
|
|
242
281
|
title: resolvePlanTitle({
|
|
@@ -254,15 +293,63 @@ function buildSlackProgressStreamChunks(params) {
|
|
|
254
293
|
function buildSlackProgressDraftBlocks(params) {
|
|
255
294
|
const label = params.label?.trim() || params.title?.trim();
|
|
256
295
|
const maxLineChars = resolveMaxLineChars(params.maxLineChars, DEFAULT_SLACK_PROGRESS_DETAIL_MAX_CHARS);
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
}
|
|
296
|
+
const planLines = formatPlanChecklistLines(params.plan ?? [], {
|
|
297
|
+
maxLines: 50,
|
|
298
|
+
maxLineChars
|
|
299
|
+
});
|
|
300
|
+
const narration = params.narration?.replace(/\s+/g, " ").trim();
|
|
301
|
+
const headBlocks = [
|
|
302
|
+
...label ? [{
|
|
303
|
+
type: "section",
|
|
304
|
+
text: field(`*${escapeSlackMrkdwn(label)}*`)
|
|
305
|
+
}] : [],
|
|
306
|
+
...narration ? [{
|
|
307
|
+
type: "section",
|
|
308
|
+
text: field(`_${escapeSlackMrkdwn(narration)}_`)
|
|
309
|
+
}] : [],
|
|
310
|
+
...planLines.length > 0 ? [{
|
|
311
|
+
type: "section",
|
|
312
|
+
text: field(planLines.map((line) => escapeSlackMrkdwn(line)).join("\n"))
|
|
313
|
+
}] : []
|
|
314
|
+
].slice(0, 50);
|
|
315
|
+
const lineBudget = Math.max(0, 50 - headBlocks.length);
|
|
316
|
+
const renderedBlocks = [...headBlocks, ...params.lines.slice(-lineBudget).map((line) => ({
|
|
261
317
|
type: "section",
|
|
262
318
|
fields: [field(legacyLineTitle(line)), field(legacyLineDetail(line, maxLineChars))]
|
|
263
|
-
}))]
|
|
319
|
+
}))];
|
|
264
320
|
return renderedBlocks.length ? renderedBlocks : void 0;
|
|
265
321
|
}
|
|
322
|
+
/**
|
|
323
|
+
* Slack native streams key task rows by persistent id with no removal chunk.
|
|
324
|
+
* When the task source switches representation (tool lines <-> typed plan) or
|
|
325
|
+
* a snapshot drops ids, previously emitted non-terminal rows must receive a
|
|
326
|
+
* final update or they linger in_progress forever.
|
|
327
|
+
*/
|
|
328
|
+
function reconcileSlackNativeTaskChunks(params) {
|
|
329
|
+
const nextTasks = /* @__PURE__ */ new Map();
|
|
330
|
+
for (const chunk of params.chunks ?? []) if (chunk.type === "task_update") nextTasks.set(chunk.id, {
|
|
331
|
+
title: chunk.title,
|
|
332
|
+
status: chunk.status
|
|
333
|
+
});
|
|
334
|
+
const terminalized = [...params.previousTasks].filter(([id, task]) => !nextTasks.has(id) && task.status !== "complete" && task.status !== "error").map(([id, task]) => {
|
|
335
|
+
const entry = {
|
|
336
|
+
title: task.title,
|
|
337
|
+
status: "complete"
|
|
338
|
+
};
|
|
339
|
+
nextTasks.set(id, entry);
|
|
340
|
+
return {
|
|
341
|
+
type: "task_update",
|
|
342
|
+
id,
|
|
343
|
+
title: task.title,
|
|
344
|
+
status: "complete"
|
|
345
|
+
};
|
|
346
|
+
});
|
|
347
|
+
for (const [id, task] of params.previousTasks) if (!nextTasks.has(id)) nextTasks.set(id, task);
|
|
348
|
+
return {
|
|
349
|
+
chunks: params.chunks?.length ? [...params.chunks, ...terminalized] : terminalized.length ? terminalized : params.chunks,
|
|
350
|
+
tasks: nextTasks
|
|
351
|
+
};
|
|
352
|
+
}
|
|
266
353
|
function buildSlackProgressStreamStartChunks(params) {
|
|
267
354
|
return buildSlackProgressStreamChunks(params);
|
|
268
355
|
}
|
|
@@ -656,15 +743,6 @@ function resolveSlackTimestampMs(ts) {
|
|
|
656
743
|
}
|
|
657
744
|
//#endregion
|
|
658
745
|
//#region extensions/slack/src/monitor/message-handler/dispatch.ts
|
|
659
|
-
const SLACK_REASONING_TAG_RE = /<\s*(\/?)\s*(?:(?:antml:|mm:)?(?:think(?:ing)?|thought)|antthinking)\b[^<>]*>/gi;
|
|
660
|
-
const SLACK_REASONING_LABEL_PREFIX_RE = /^\s*(?:>\s*)?Reasoning:\s*/iu;
|
|
661
|
-
const SLACK_THINKING_LABEL_PREFIX_RE = /^\s*(?:>\s*)?Thinking\.{0,3}(?=\s*(?:\n|_))/iu;
|
|
662
|
-
const SLACK_THREAD_LOADING_MESSAGES = [
|
|
663
|
-
"Reading the thread...",
|
|
664
|
-
"Checking context...",
|
|
665
|
-
"Working through the request...",
|
|
666
|
-
"Putting it all together..."
|
|
667
|
-
];
|
|
668
746
|
function resolveSlackMessageTimestampMs(message) {
|
|
669
747
|
return resolveSlackTimestampMs(message.event_ts ?? message.ts);
|
|
670
748
|
}
|
|
@@ -766,43 +844,6 @@ function rememberSlackStreamRecipientTeam(params) {
|
|
|
766
844
|
if (oldest) cache.delete(oldest);
|
|
767
845
|
}
|
|
768
846
|
}
|
|
769
|
-
function normalizeSlackReasoningProgressLine(text) {
|
|
770
|
-
return (extractSlackReasoningTagText(text) || stripReasoningTagsFromText(text, {
|
|
771
|
-
mode: "strict",
|
|
772
|
-
trim: "both"
|
|
773
|
-
})).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();
|
|
774
|
-
}
|
|
775
|
-
function extractSlackReasoningTagText(text) {
|
|
776
|
-
if (!text) return "";
|
|
777
|
-
let result = "";
|
|
778
|
-
let lastIndex = 0;
|
|
779
|
-
let inReasoning = false;
|
|
780
|
-
SLACK_REASONING_TAG_RE.lastIndex = 0;
|
|
781
|
-
for (const match of text.matchAll(SLACK_REASONING_TAG_RE)) {
|
|
782
|
-
const index = match.index ?? 0;
|
|
783
|
-
if (inReasoning) result += text.slice(lastIndex, index);
|
|
784
|
-
inReasoning = match[1] !== "/";
|
|
785
|
-
lastIndex = index + match[0].length;
|
|
786
|
-
}
|
|
787
|
-
if (inReasoning) result += text.slice(lastIndex);
|
|
788
|
-
return result.trim();
|
|
789
|
-
}
|
|
790
|
-
function stripSimpleItalicMarkers(line) {
|
|
791
|
-
const trimmed = line.trim();
|
|
792
|
-
if (trimmed.length >= 2 && trimmed.startsWith("_") && trimmed.endsWith("_")) return trimmed.slice(1, -1).trim();
|
|
793
|
-
return trimmed;
|
|
794
|
-
}
|
|
795
|
-
function mergeSlackReasoningProgressText(current, incoming, options) {
|
|
796
|
-
if (!current) return incoming;
|
|
797
|
-
const normalizedCurrent = normalizeSlackReasoningProgressLine(current);
|
|
798
|
-
const normalizedIncoming = normalizeSlackReasoningProgressLine(incoming);
|
|
799
|
-
if (!normalizedIncoming || normalizedIncoming === normalizedCurrent) return current;
|
|
800
|
-
if (options?.snapshot === true || isSlackReasoningSnapshotText(incoming) || normalizedIncoming.startsWith(normalizedCurrent)) return incoming;
|
|
801
|
-
return `${current}${incoming}`;
|
|
802
|
-
}
|
|
803
|
-
function isSlackReasoningSnapshotText(text) {
|
|
804
|
-
return SLACK_REASONING_LABEL_PREFIX_RE.test(text) || SLACK_THINKING_LABEL_PREFIX_RE.test(text);
|
|
805
|
-
}
|
|
806
847
|
function createSlackEventDeliveryTracker() {
|
|
807
848
|
const deliveredKeys = /* @__PURE__ */ new Set();
|
|
808
849
|
return {
|
|
@@ -982,7 +1023,6 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
982
1023
|
channelId: message.channel,
|
|
983
1024
|
threadTs: statusThreadTs,
|
|
984
1025
|
status: "is typing...",
|
|
985
|
-
loadingMessages: SLACK_THREAD_LOADING_MESSAGES,
|
|
986
1026
|
eventScope: prepared.eventScope
|
|
987
1027
|
});
|
|
988
1028
|
if (typingReaction && message.ts) await reactSlackMessage(message.channel, message.ts, typingReaction, {
|
|
@@ -1102,6 +1142,11 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1102
1142
|
delivery.outcome = "success";
|
|
1103
1143
|
}
|
|
1104
1144
|
};
|
|
1145
|
+
const acknowledgeStoppedStreamedDeliveries = (session, messageId) => {
|
|
1146
|
+
refreshStreamedAcknowledgements(session);
|
|
1147
|
+
for (const delivery of streamedDeliveries) delivery.acknowledged = true;
|
|
1148
|
+
emitAcknowledgedStreamedDeliveries(messageId);
|
|
1149
|
+
};
|
|
1105
1150
|
const emitFailedPendingStreamedDeliveries = (error) => {
|
|
1106
1151
|
for (const delivery of streamedDeliveries) {
|
|
1107
1152
|
if (delivery.acknowledged || delivery.outcome) continue;
|
|
@@ -1130,7 +1175,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1130
1175
|
delivery.outcome = "success";
|
|
1131
1176
|
}
|
|
1132
1177
|
};
|
|
1133
|
-
|
|
1178
|
+
let deliveryTracker = createSlackEventDeliveryTracker();
|
|
1134
1179
|
const markPreviewPayloadDelivered = (params) => {
|
|
1135
1180
|
deliveryTracker.markDelivered(params);
|
|
1136
1181
|
const nextThreadTs = replyPlan.peekThreadTs();
|
|
@@ -1155,8 +1200,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1155
1200
|
session,
|
|
1156
1201
|
...slackMessageMetadata ? { metadata: slackMessageMetadata } : {}
|
|
1157
1202
|
});
|
|
1158
|
-
|
|
1159
|
-
emitAcknowledgedStreamedDeliveries(stopResult.messageId);
|
|
1203
|
+
acknowledgeStoppedStreamedDeliveries(session, stopResult.messageId);
|
|
1160
1204
|
observedReplyDelivery = true;
|
|
1161
1205
|
usedReplyThreadTs ??= session.threadTs;
|
|
1162
1206
|
return true;
|
|
@@ -1265,6 +1309,24 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1265
1309
|
rememberDeliveredThreadTs(params.kind, params.session.threadTs);
|
|
1266
1310
|
return true;
|
|
1267
1311
|
};
|
|
1312
|
+
const appendNativeProgressCompletion = async (isError) => {
|
|
1313
|
+
const session = streamSession;
|
|
1314
|
+
if (isError) nativeProgressTerminalStatus = "error";
|
|
1315
|
+
if (!session || nativeProgressCompletionSent) return;
|
|
1316
|
+
const chunks = buildNativeProgressCompletionChunks(isError ? "error" : "complete");
|
|
1317
|
+
if (!chunks?.length) return;
|
|
1318
|
+
try {
|
|
1319
|
+
await appendSlackStream({
|
|
1320
|
+
session,
|
|
1321
|
+
chunks
|
|
1322
|
+
});
|
|
1323
|
+
nativeProgressCompletionSent = true;
|
|
1324
|
+
observedReplyDelivery ||= session.delivered;
|
|
1325
|
+
} catch (err) {
|
|
1326
|
+
streamFailed = true;
|
|
1327
|
+
runtime.error?.(danger(`slack-stream: native progress completion failed: ${formatSlackError(err)}`));
|
|
1328
|
+
}
|
|
1329
|
+
};
|
|
1268
1330
|
const deliverWithStreaming = async (params) => {
|
|
1269
1331
|
if (params.payload.isReasoning === true) return;
|
|
1270
1332
|
const reply = resolveSendableOutboundReplyParts(params.payload);
|
|
@@ -1290,13 +1352,6 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1290
1352
|
});
|
|
1291
1353
|
return;
|
|
1292
1354
|
}
|
|
1293
|
-
if (useNativeProgressStreaming && !streamSession) {
|
|
1294
|
-
await deliverNormally({
|
|
1295
|
-
payload: params.payload,
|
|
1296
|
-
kind: params.kind
|
|
1297
|
-
});
|
|
1298
|
-
return;
|
|
1299
|
-
}
|
|
1300
1355
|
if (!streamSession) {
|
|
1301
1356
|
const streamThreadTs = replyPlan.nextThreadTs();
|
|
1302
1357
|
plannedThreadTs = streamThreadTs;
|
|
@@ -1357,36 +1412,12 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1357
1412
|
logVerbose("slack-stream: suppressed duplicate append payload");
|
|
1358
1413
|
return;
|
|
1359
1414
|
}
|
|
1360
|
-
const completionChunks = useNativeProgressStreaming && !nativeProgressCompletionSent && previewToolProgressLines.length > 0 ? buildSlackProgressStreamCompletionChunks({
|
|
1361
|
-
title: explicitProgressTitle,
|
|
1362
|
-
lines: previewToolProgressLines,
|
|
1363
|
-
maxLineChars: progressDraftMaxLineChars,
|
|
1364
|
-
finalInProgressStatus: params.payload.isError ? "error" : "complete"
|
|
1365
|
-
}) : void 0;
|
|
1366
|
-
if (useNativeProgressStreaming) {
|
|
1367
|
-
if (completionChunks?.length) {
|
|
1368
|
-
await appendSlackStream({
|
|
1369
|
-
session: streamSession,
|
|
1370
|
-
chunks: completionChunks
|
|
1371
|
-
});
|
|
1372
|
-
nativeProgressCompletionSent = true;
|
|
1373
|
-
if (streamSession.delivered) observedReplyDelivery = true;
|
|
1374
|
-
}
|
|
1375
|
-
await deliverNormally({
|
|
1376
|
-
payload: params.payload,
|
|
1377
|
-
kind: params.kind,
|
|
1378
|
-
forcedThreadTs: streamSession.threadTs
|
|
1379
|
-
});
|
|
1380
|
-
return;
|
|
1381
|
-
}
|
|
1382
1415
|
if (text) recordStreamedDelivery(params.kind, text);
|
|
1383
1416
|
await appendSlackStream({
|
|
1384
1417
|
session: streamSession,
|
|
1385
|
-
text: "\n" + text
|
|
1386
|
-
chunks: completionChunks
|
|
1418
|
+
text: "\n" + text
|
|
1387
1419
|
});
|
|
1388
1420
|
refreshStreamedAcknowledgements(streamSession);
|
|
1389
|
-
if (completionChunks?.length) nativeProgressCompletionSent = true;
|
|
1390
1421
|
if (streamSession.delivered) {
|
|
1391
1422
|
observedReplyDelivery = true;
|
|
1392
1423
|
if (params.kind === "final") observedFinalReplyDelivery = true;
|
|
@@ -1433,13 +1464,59 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1433
1464
|
await deliverNormally({
|
|
1434
1465
|
payload: params.payload,
|
|
1435
1466
|
kind: params.kind,
|
|
1436
|
-
forcedThreadTs: streamSession?.threadTs ?? plannedThreadTs
|
|
1467
|
+
forcedThreadTs: streamSession?.threadTs ?? nativeProgressStreamThreadTs ?? plannedThreadTs
|
|
1437
1468
|
});
|
|
1438
1469
|
}
|
|
1439
1470
|
};
|
|
1440
1471
|
let draftPreviewCommitted = false;
|
|
1441
1472
|
const deliverSlackPayload = async (payload, info) => {
|
|
1442
1473
|
if (payload.isReasoning === true) return { visibleReplySent: false };
|
|
1474
|
+
if (info.kind === "final" && slackStreaming.mode === "progress" && streamMode === "status_final") {
|
|
1475
|
+
const hadProgressDraft = progressDraft.hasStarted;
|
|
1476
|
+
progressDraft.markFinalReplyStarted();
|
|
1477
|
+
if (useNativeProgressStreaming) {
|
|
1478
|
+
await waitForNativeProgressStreamStart();
|
|
1479
|
+
const finalThreadTs = streamSession?.threadTs ?? nativeProgressStreamThreadTs;
|
|
1480
|
+
await deliverNormally({
|
|
1481
|
+
payload,
|
|
1482
|
+
kind: info.kind,
|
|
1483
|
+
forcedThreadTs: finalThreadTs
|
|
1484
|
+
});
|
|
1485
|
+
await appendNativeProgressCompletion(payload.isError === true);
|
|
1486
|
+
progressDraft.markFinalReplyDelivered();
|
|
1487
|
+
if (!payload.isError && hadProgressDraft && streamSession) pendingNativeProgressReceipt = progressReceipt.buildSummaryLine();
|
|
1488
|
+
return;
|
|
1489
|
+
}
|
|
1490
|
+
if (hadProgressDraft) try {
|
|
1491
|
+
await draftStream?.flush();
|
|
1492
|
+
} catch (err) {
|
|
1493
|
+
logVerbose(`slack: progress draft flush before final failed (${formatSlackError(err)})`);
|
|
1494
|
+
}
|
|
1495
|
+
const receiptChannelId = hadProgressDraft ? draftStream?.channelId() : void 0;
|
|
1496
|
+
const receiptMessageId = hadProgressDraft ? draftStream?.messageId() : void 0;
|
|
1497
|
+
const draftThreadTs = hadProgressDraft ? usedReplyThreadTs ?? statusThreadTs : void 0;
|
|
1498
|
+
await deliverNormally({
|
|
1499
|
+
payload,
|
|
1500
|
+
kind: info.kind,
|
|
1501
|
+
...draftThreadTs ? { forcedThreadTs: draftThreadTs } : {}
|
|
1502
|
+
});
|
|
1503
|
+
progressDraft.markFinalReplyDelivered();
|
|
1504
|
+
if (!payload.isError && receiptChannelId && receiptMessageId && !progressReceiptCollapsed) await collapseProgressReceipt({
|
|
1505
|
+
channelId: receiptChannelId,
|
|
1506
|
+
messageId: receiptMessageId,
|
|
1507
|
+
text: progressReceipt.buildSummaryLine(),
|
|
1508
|
+
threadTs: usedReplyThreadTs ?? statusThreadTs
|
|
1509
|
+
});
|
|
1510
|
+
return;
|
|
1511
|
+
}
|
|
1512
|
+
if (useNativeProgressStreaming) {
|
|
1513
|
+
await deliverNormally({
|
|
1514
|
+
payload,
|
|
1515
|
+
kind: info.kind,
|
|
1516
|
+
forcedThreadTs: streamSession?.threadTs ?? nativeProgressStreamThreadTs
|
|
1517
|
+
});
|
|
1518
|
+
return;
|
|
1519
|
+
}
|
|
1443
1520
|
if (useStreaming) {
|
|
1444
1521
|
await deliverWithStreaming({
|
|
1445
1522
|
payload,
|
|
@@ -1630,8 +1707,6 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1630
1707
|
const useNativeProgressStreaming = useStreaming && slackStreaming.mode === "progress";
|
|
1631
1708
|
const progressDraftActive = Boolean(draftStream) || useNativeProgressStreaming;
|
|
1632
1709
|
const previewToolProgressEnabled = progressDraftActive && resolveChannelStreamingPreviewToolProgress(account.config);
|
|
1633
|
-
const commentaryProgressEnabled = progressDraftActive && resolveChannelStreamingProgressCommentary(account.config);
|
|
1634
|
-
const commentaryDraftEnabled = progressDraftActive && (slackStreaming.mode === "progress" ? resolveChannelStreamingProgressCommentary(account.config, previewToolProgressEnabled) : previewToolProgressEnabled);
|
|
1635
1710
|
let shouldYieldDraftProgress = () => false;
|
|
1636
1711
|
const suppressDefaultToolProgressMessages = resolveChannelStreamingSuppressDefaultToolProgressMessages(account.config, {
|
|
1637
1712
|
draftStreamActive: Boolean(draftStream) || useNativeProgressStreaming,
|
|
@@ -1639,39 +1714,20 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1639
1714
|
previewStreamingEnabled
|
|
1640
1715
|
});
|
|
1641
1716
|
let previewToolProgressSuppressed = false;
|
|
1642
|
-
let
|
|
1643
|
-
let
|
|
1717
|
+
let legacyPreviewToolProgressLines = [];
|
|
1718
|
+
let nativeTaskState = /* @__PURE__ */ new Map();
|
|
1644
1719
|
let appendRenderedText = "";
|
|
1645
1720
|
let appendSourceText = "";
|
|
1646
|
-
let reasoningProgressRawText = "";
|
|
1647
|
-
let statusUpdateCount = 0;
|
|
1648
1721
|
let nativeProgressCompletionSent = false;
|
|
1722
|
+
let nativeProgressTerminalStatus = "complete";
|
|
1649
1723
|
let nativeProgressChunkKey;
|
|
1724
|
+
const progressReceipt = createChannelProgressReceiptTracker();
|
|
1725
|
+
let progressReceiptCollapsed = false;
|
|
1726
|
+
let pendingNativeProgressReceipt;
|
|
1650
1727
|
const progressSeed = `${account.accountId}:${message.channel}`;
|
|
1651
1728
|
const useRichProgressDraft = streamMode === "status_final" && resolveChannelProgressDraftRender(account.config) === "rich";
|
|
1652
1729
|
const explicitProgressTitle = resolveExplicitSlackProgressTitle(account.config);
|
|
1653
1730
|
const progressDraftMaxLineChars = resolveChannelProgressDraftMaxLineChars(account.config);
|
|
1654
|
-
const renderProgressDraft = () => {
|
|
1655
|
-
if (!draftStream || streamMode !== "status_final") return;
|
|
1656
|
-
const progressLines = previewToolProgressLines.length === 0 ? lastNonEmptyPreviewToolProgressLines : previewToolProgressLines;
|
|
1657
|
-
const previewText = formatChannelProgressDraftText({
|
|
1658
|
-
entry: account.config,
|
|
1659
|
-
lines: progressLines,
|
|
1660
|
-
seed: progressSeed,
|
|
1661
|
-
formatLine: escapeSlackMrkdwn
|
|
1662
|
-
});
|
|
1663
|
-
if (!previewText) return;
|
|
1664
|
-
const richProgressBlocks = useRichProgressDraft ? buildSlackProgressDraftBlocks({
|
|
1665
|
-
title: explicitProgressTitle,
|
|
1666
|
-
lines: progressLines,
|
|
1667
|
-
maxLineChars: resolveChannelProgressDraftMaxLineChars(account.config)
|
|
1668
|
-
}) : void 0;
|
|
1669
|
-
draftStream.update(useRichProgressDraft && richProgressBlocks ? {
|
|
1670
|
-
text: previewText,
|
|
1671
|
-
blocks: richProgressBlocks
|
|
1672
|
-
} : previewText);
|
|
1673
|
-
hasStreamedMessage = true;
|
|
1674
|
-
};
|
|
1675
1731
|
const waitForNativeProgressStreamStart = async () => {
|
|
1676
1732
|
if (streamSession || !nativeProgressStreamStartPromise) return true;
|
|
1677
1733
|
try {
|
|
@@ -1682,13 +1738,40 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1682
1738
|
}
|
|
1683
1739
|
return !streamFailed;
|
|
1684
1740
|
};
|
|
1685
|
-
const
|
|
1686
|
-
|
|
1687
|
-
|
|
1741
|
+
const resolveStructuredProgressLines = (lines) => lines.map((line) => {
|
|
1742
|
+
if (typeof line !== "string") return line;
|
|
1743
|
+
const reasoning = line.startsWith("🧠 ");
|
|
1744
|
+
const text = line.replace(/^(?:🧠|💬)\s+/u, "").replace(/^_(.*)_$/su, "$1").trim();
|
|
1745
|
+
return {
|
|
1746
|
+
...reasoning ? { id: "reasoning" } : {},
|
|
1747
|
+
kind: "item",
|
|
1748
|
+
text,
|
|
1749
|
+
label: reasoning ? "Reasoning" : "Update",
|
|
1750
|
+
prefix: false
|
|
1751
|
+
};
|
|
1752
|
+
});
|
|
1753
|
+
const resolveNativeProgressPlan = (snapshot) => snapshot.plan?.length ? snapshot.plan : void 0;
|
|
1754
|
+
const resolveNativeProgressLines = (snapshot) => {
|
|
1755
|
+
const lines = resolveStructuredProgressLines(snapshot.lines);
|
|
1756
|
+
if (snapshot.plan?.length || !snapshot.planExplanation) return lines;
|
|
1757
|
+
const explanationLine = buildChannelProgressDraftLine({
|
|
1758
|
+
event: "plan",
|
|
1759
|
+
phase: "update",
|
|
1760
|
+
explanation: snapshot.planExplanation
|
|
1761
|
+
});
|
|
1762
|
+
return explanationLine ? [...lines, explanationLine] : lines;
|
|
1763
|
+
};
|
|
1764
|
+
const combineProgressHeadlineAndExplanation = (headline, explanation) => headline && explanation && headline !== explanation ? `${headline} — ${explanation}` : headline ?? explanation;
|
|
1765
|
+
const resolveNativeProgressTitle = (snapshot) => combineProgressHeadlineAndExplanation(explicitProgressTitle ?? snapshot.statusHeadline, snapshot.planExplanation);
|
|
1766
|
+
const buildNativeProgressChunks = (snapshot) => streamSession ? buildSlackProgressStreamUpdateChunks({
|
|
1767
|
+
title: resolveNativeProgressTitle(snapshot),
|
|
1768
|
+
lines: resolveNativeProgressLines(snapshot),
|
|
1769
|
+
plan: resolveNativeProgressPlan(snapshot),
|
|
1688
1770
|
maxLineChars: progressDraftMaxLineChars
|
|
1689
1771
|
}) : buildSlackProgressStreamStartChunks({
|
|
1690
|
-
title:
|
|
1691
|
-
lines:
|
|
1772
|
+
title: resolveNativeProgressTitle(snapshot),
|
|
1773
|
+
lines: resolveNativeProgressLines(snapshot),
|
|
1774
|
+
plan: resolveNativeProgressPlan(snapshot),
|
|
1692
1775
|
maxLineChars: progressDraftMaxLineChars
|
|
1693
1776
|
});
|
|
1694
1777
|
const markNativeProgressDelivered = (session, threadTs) => {
|
|
@@ -1746,78 +1829,176 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1746
1829
|
nativeProgressChunkKey = chunkKey;
|
|
1747
1830
|
};
|
|
1748
1831
|
const updateNativeProgressStream = async () => {
|
|
1749
|
-
|
|
1832
|
+
const snapshot = progressDraft.getSnapshot();
|
|
1833
|
+
const progressLines = resolveNativeProgressLines(snapshot);
|
|
1834
|
+
const hasRetirableNativeTasks = [...nativeTaskState.values()].some((task) => task.status !== "complete" && task.status !== "error");
|
|
1835
|
+
if (!useNativeProgressStreaming || streamFailed || progressLines.length === 0 && !snapshot.plan?.length && !snapshot.statusHeadline && !explicitProgressTitle && !hasRetirableNativeTasks) return;
|
|
1750
1836
|
if (!await waitForNativeProgressStreamStart()) return;
|
|
1751
|
-
const
|
|
1837
|
+
const reconciled = reconcileSlackNativeTaskChunks({
|
|
1838
|
+
previousTasks: nativeTaskState,
|
|
1839
|
+
chunks: buildNativeProgressChunks(snapshot)
|
|
1840
|
+
});
|
|
1841
|
+
const chunks = reconciled.chunks;
|
|
1752
1842
|
if (!chunks?.length) return;
|
|
1753
1843
|
const chunkKey = JSON.stringify(chunks);
|
|
1754
1844
|
if (chunkKey === nativeProgressChunkKey) return;
|
|
1755
1845
|
try {
|
|
1756
|
-
if (!streamSession)
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
}
|
|
1760
|
-
await appendNativeProgressStream(chunks, chunkKey);
|
|
1846
|
+
if (!streamSession) await startNativeProgressStream(chunks, chunkKey);
|
|
1847
|
+
else await appendNativeProgressStream(chunks, chunkKey);
|
|
1848
|
+
nativeTaskState = reconciled.tasks;
|
|
1761
1849
|
} catch (err) {
|
|
1762
1850
|
runtime.error?.(danger(`slack-stream: native progress stream failed: ${formatSlackError(err)}, falling back`));
|
|
1763
1851
|
streamFailed = true;
|
|
1764
1852
|
}
|
|
1765
1853
|
};
|
|
1766
|
-
const
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1854
|
+
const resetProgressTurnState = () => {
|
|
1855
|
+
progressReceipt.reset();
|
|
1856
|
+
progressReceiptCollapsed = false;
|
|
1857
|
+
pendingNativeProgressReceipt = void 0;
|
|
1770
1858
|
};
|
|
1771
|
-
const
|
|
1772
|
-
const
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
return;
|
|
1859
|
+
const collapseProgressReceipt = async (params) => {
|
|
1860
|
+
const { botToken: token } = ctx;
|
|
1861
|
+
try {
|
|
1862
|
+
await finalizeSlackPreviewEdit({
|
|
1863
|
+
client: slackClient,
|
|
1864
|
+
token,
|
|
1865
|
+
accountId: account.accountId,
|
|
1866
|
+
...params
|
|
1867
|
+
});
|
|
1868
|
+
progressReceiptCollapsed = true;
|
|
1869
|
+
} catch (err) {
|
|
1870
|
+
logVerbose(`slack: progress receipt edit failed (${formatSlackError(err)})`);
|
|
1784
1871
|
}
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1872
|
+
};
|
|
1873
|
+
const progressDraft = createChannelProgressDraftCompositor({
|
|
1874
|
+
entry: account.config,
|
|
1875
|
+
mode: slackStreaming.mode,
|
|
1876
|
+
active: progressDraftActive && streamMode === "status_final",
|
|
1877
|
+
seed: progressSeed,
|
|
1878
|
+
formatLine: escapeSlackMrkdwn,
|
|
1879
|
+
reasoningLinePrefix: "🧠 ",
|
|
1880
|
+
commentaryLinePrefix: "💬 ",
|
|
1881
|
+
reasoningGate: previewToolProgressEnabled,
|
|
1882
|
+
commentaryItalics: false,
|
|
1883
|
+
updateOnLineChange: useNativeProgressStreaming || useRichProgressDraft,
|
|
1884
|
+
update: async (previewText, options) => {
|
|
1885
|
+
if (useNativeProgressStreaming) {
|
|
1886
|
+
await updateNativeProgressStream();
|
|
1887
|
+
return;
|
|
1888
|
+
}
|
|
1889
|
+
if (!draftStream) return;
|
|
1890
|
+
const snapshot = progressDraft.getSnapshot();
|
|
1891
|
+
const structuredLines = resolveStructuredProgressLines(options?.lines ?? snapshot.lines);
|
|
1892
|
+
const richNarration = combineProgressHeadlineAndExplanation(snapshot.statusHeadline, snapshot.planExplanation);
|
|
1893
|
+
const richProgressBlocks = useRichProgressDraft ? buildSlackProgressDraftBlocks({
|
|
1894
|
+
title: explicitProgressTitle,
|
|
1895
|
+
lines: structuredLines,
|
|
1896
|
+
plan: snapshot.plan,
|
|
1897
|
+
narration: richNarration,
|
|
1898
|
+
maxLineChars: progressDraftMaxLineChars
|
|
1899
|
+
}) : void 0;
|
|
1900
|
+
draftStream.update(useRichProgressDraft && richProgressBlocks ? {
|
|
1901
|
+
text: previewText,
|
|
1902
|
+
blocks: richProgressBlocks
|
|
1903
|
+
} : previewText);
|
|
1796
1904
|
hasStreamedMessage = true;
|
|
1905
|
+
if (options?.flush) await draftStream.flush();
|
|
1906
|
+
}
|
|
1907
|
+
});
|
|
1908
|
+
const commentaryProgressEnabled = progressDraft.commentaryProgressEnabled;
|
|
1909
|
+
const buildNativeProgressCompletionChunks = (finalInProgressStatus) => {
|
|
1910
|
+
const snapshot = progressDraft.getSnapshot();
|
|
1911
|
+
const lines = resolveNativeProgressLines(snapshot);
|
|
1912
|
+
const hasRetirableNativeTasks = [...nativeTaskState.values()].some((task) => task.status !== "complete" && task.status !== "error");
|
|
1913
|
+
if (lines.length === 0 && !snapshot.plan?.length && !hasRetirableNativeTasks) return;
|
|
1914
|
+
return reconcileSlackNativeTaskChunks({
|
|
1915
|
+
previousTasks: nativeTaskState,
|
|
1916
|
+
chunks: buildSlackProgressStreamCompletionChunks({
|
|
1917
|
+
title: resolveNativeProgressTitle(snapshot),
|
|
1918
|
+
lines,
|
|
1919
|
+
plan: resolveNativeProgressPlan(snapshot),
|
|
1920
|
+
maxLineChars: progressDraftMaxLineChars,
|
|
1921
|
+
finalInProgressStatus
|
|
1922
|
+
})
|
|
1923
|
+
}).chunks;
|
|
1924
|
+
};
|
|
1925
|
+
const finishNativeProgressTurn = async (completionChunks) => {
|
|
1926
|
+
if (nativeProgressStreamStartPromise) await nativeProgressStreamStartPromise.catch(() => null);
|
|
1927
|
+
const session = streamSession;
|
|
1928
|
+
if (session && !session.stopped) try {
|
|
1929
|
+
if (completionChunks?.length) nativeProgressCompletionSent = true;
|
|
1930
|
+
const stopResult = await stopSlackStream({
|
|
1931
|
+
session,
|
|
1932
|
+
...completionChunks?.length ? { chunks: completionChunks } : {},
|
|
1933
|
+
...slackMessageMetadata ? { metadata: slackMessageMetadata } : {}
|
|
1934
|
+
});
|
|
1935
|
+
acknowledgeStoppedStreamedDeliveries(session, stopResult?.messageId);
|
|
1936
|
+
if (pendingNativeProgressReceipt && stopResult?.messageId) await collapseProgressReceipt({
|
|
1937
|
+
channelId: session.channel,
|
|
1938
|
+
messageId: stopResult.messageId,
|
|
1939
|
+
text: pendingNativeProgressReceipt,
|
|
1940
|
+
threadTs: session.threadTs
|
|
1941
|
+
});
|
|
1942
|
+
} catch (err) {
|
|
1943
|
+
const error = formatSlackError(err);
|
|
1944
|
+
emitAcknowledgedStreamedDeliveries();
|
|
1945
|
+
emitFailedPendingStreamedDeliveries(error);
|
|
1946
|
+
logVerbose(`slack-stream: failed to rotate native progress stream (${error})`);
|
|
1947
|
+
}
|
|
1948
|
+
streamSession = null;
|
|
1949
|
+
nativeProgressStreamStartPromise = null;
|
|
1950
|
+
nativeProgressStreamThreadTs = void 0;
|
|
1951
|
+
streamFailed = false;
|
|
1952
|
+
};
|
|
1953
|
+
const pushPlanProgress = async (steps, explanation) => {
|
|
1954
|
+
if (streamMode === "status_final") {
|
|
1955
|
+
await progressDraft.pushPlanProgress(steps, { explanation });
|
|
1797
1956
|
return;
|
|
1798
1957
|
}
|
|
1799
|
-
if (
|
|
1800
|
-
|
|
1801
|
-
|
|
1958
|
+
if (previewToolProgressSuppressed || !draftStream) return;
|
|
1959
|
+
const text = formatChannelProgressDraftText({
|
|
1960
|
+
entry: account.config,
|
|
1961
|
+
lines: legacyPreviewToolProgressLines,
|
|
1962
|
+
seed: progressSeed,
|
|
1963
|
+
formatLine: escapeSlackMrkdwn,
|
|
1964
|
+
narration: explanation,
|
|
1965
|
+
plan: steps
|
|
1966
|
+
});
|
|
1967
|
+
if (text) {
|
|
1968
|
+
draftStream.update(text);
|
|
1969
|
+
hasStreamedMessage = true;
|
|
1802
1970
|
}
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1971
|
+
};
|
|
1972
|
+
const pushPreviewProgress = async (line, options) => {
|
|
1973
|
+
if (!draftStream && !useNativeProgressStreaming) return;
|
|
1974
|
+
if (options?.toolName !== void 0 && !isChannelProgressDraftWorkToolName(options.toolName)) return;
|
|
1975
|
+
const normalized = line?.text.replace(/\s+/g, " ").trim();
|
|
1976
|
+
if (streamMode === "status_final") {
|
|
1977
|
+
if (!line || !normalized) {
|
|
1978
|
+
await progressDraft.noteActivity();
|
|
1979
|
+
return;
|
|
1808
1980
|
}
|
|
1981
|
+
await progressDraft.pushToolProgress(line, options);
|
|
1809
1982
|
return;
|
|
1810
1983
|
}
|
|
1811
|
-
|
|
1812
|
-
const
|
|
1813
|
-
if (
|
|
1984
|
+
if (!line || !normalized || !draftStream || !previewToolProgressEnabled || previewToolProgressSuppressed) return;
|
|
1985
|
+
const nextLines = mergeChannelProgressDraftLine(legacyPreviewToolProgressLines, line, { maxLines: resolveChannelProgressDraftMaxLines(account.config) });
|
|
1986
|
+
if (nextLines === legacyPreviewToolProgressLines) return;
|
|
1987
|
+
legacyPreviewToolProgressLines = nextLines;
|
|
1988
|
+
draftStream.update(formatChannelProgressDraftText({
|
|
1989
|
+
entry: account.config,
|
|
1990
|
+
lines: legacyPreviewToolProgressLines,
|
|
1991
|
+
seed: progressSeed,
|
|
1992
|
+
formatLine: escapeSlackMrkdwn
|
|
1993
|
+
}));
|
|
1994
|
+
hasStreamedMessage = true;
|
|
1814
1995
|
};
|
|
1815
1996
|
const updateDraftFromPartial = (text) => {
|
|
1816
1997
|
const trimmed = text?.trimEnd();
|
|
1817
1998
|
if (!trimmed) return;
|
|
1818
1999
|
if (streamMode === "append") {
|
|
1819
2000
|
previewToolProgressSuppressed = true;
|
|
1820
|
-
|
|
2001
|
+
legacyPreviewToolProgressLines = [];
|
|
1821
2002
|
const next = applyAppendOnlyStreamUpdate({
|
|
1822
2003
|
incoming: trimmed,
|
|
1823
2004
|
rendered: appendRenderedText,
|
|
@@ -1830,56 +2011,86 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1830
2011
|
hasStreamedMessage = true;
|
|
1831
2012
|
return;
|
|
1832
2013
|
}
|
|
1833
|
-
if (streamMode === "status_final")
|
|
1834
|
-
if (!progressDraftGate.hasStarted) return;
|
|
1835
|
-
statusUpdateCount += 1;
|
|
1836
|
-
if (statusUpdateCount > 1 && statusUpdateCount % 4 !== 0) return;
|
|
1837
|
-
renderProgressDraft();
|
|
1838
|
-
return;
|
|
1839
|
-
}
|
|
2014
|
+
if (streamMode === "status_final") return;
|
|
1840
2015
|
previewToolProgressSuppressed = true;
|
|
1841
|
-
|
|
2016
|
+
legacyPreviewToolProgressLines = [];
|
|
1842
2017
|
draftStream?.update(trimmed);
|
|
1843
2018
|
hasStreamedMessage = true;
|
|
1844
2019
|
};
|
|
1845
2020
|
const pushReasoningProgress = async (payload) => {
|
|
1846
2021
|
if (!payload?.text) return;
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
const onDraftBoundary = !shouldUseDraftStream ? void 0 : async () => {
|
|
1858
|
-
if (hasStreamedMessage && streamMode !== "status_final") {
|
|
1859
|
-
draftStream?.forceNewMessage();
|
|
1860
|
-
hasStreamedMessage = false;
|
|
1861
|
-
appendRenderedText = "";
|
|
1862
|
-
appendSourceText = "";
|
|
1863
|
-
statusUpdateCount = 0;
|
|
2022
|
+
if (streamMode !== "status_final") {
|
|
2023
|
+
const normalized = progressDraft.mergeReasoningProgress(payload.text, { snapshot: payload.isReasoningSnapshot === true }).replace(/^_(.*)_$/su, "$1").trim();
|
|
2024
|
+
if (!normalized) return;
|
|
2025
|
+
await pushPreviewProgress({
|
|
2026
|
+
id: "reasoning",
|
|
2027
|
+
kind: "item",
|
|
2028
|
+
text: normalized,
|
|
2029
|
+
label: "Reasoning"
|
|
2030
|
+
});
|
|
2031
|
+
return;
|
|
1864
2032
|
}
|
|
1865
|
-
|
|
2033
|
+
progressReceipt.noteReasoning();
|
|
2034
|
+
await progressDraft.pushReasoningProgress(payload.text, { snapshot: payload.isReasoningSnapshot === true });
|
|
2035
|
+
};
|
|
2036
|
+
const resetDraftDeliveryState = () => {
|
|
2037
|
+
hasStreamedMessage = false;
|
|
2038
|
+
appendRenderedText = "";
|
|
2039
|
+
appendSourceText = "";
|
|
2040
|
+
};
|
|
2041
|
+
const resetDraftProgressState = () => {
|
|
2042
|
+
progressDraft.resetReasoningProgress();
|
|
1866
2043
|
previewToolProgressSuppressed = false;
|
|
1867
|
-
|
|
2044
|
+
legacyPreviewToolProgressLines = [];
|
|
2045
|
+
};
|
|
2046
|
+
const beginNewProgressTurn = async (options) => {
|
|
2047
|
+
const completionChunks = useNativeProgressStreaming && !nativeProgressCompletionSent ? buildNativeProgressCompletionChunks(nativeProgressTerminalStatus) : void 0;
|
|
2048
|
+
if (!progressDraft.beginNewTurn(options)) return false;
|
|
2049
|
+
if (useNativeProgressStreaming) await finishNativeProgressTurn(completionChunks);
|
|
2050
|
+
else draftStream?.forceNewMessage();
|
|
2051
|
+
resetProgressTurnState();
|
|
2052
|
+
nativeTaskState = /* @__PURE__ */ new Map();
|
|
2053
|
+
nativeProgressCompletionSent = false;
|
|
2054
|
+
nativeProgressTerminalStatus = "complete";
|
|
2055
|
+
nativeProgressChunkKey = void 0;
|
|
2056
|
+
draftPreviewCommitted = false;
|
|
2057
|
+
observedFinalReplyDelivery = false;
|
|
2058
|
+
deliveryTracker = createSlackEventDeliveryTracker();
|
|
2059
|
+
progressReceiptCollapsed = false;
|
|
2060
|
+
return true;
|
|
2061
|
+
};
|
|
2062
|
+
const onDraftBoundary = !shouldUseDraftStream && !useNativeProgressStreaming ? void 0 : async () => {
|
|
2063
|
+
if (streamMode === "status_final") {
|
|
2064
|
+
await beginNewProgressTurn();
|
|
2065
|
+
return;
|
|
2066
|
+
}
|
|
2067
|
+
if (hasStreamedMessage) draftStream?.forceNewMessage();
|
|
2068
|
+
resetDraftDeliveryState();
|
|
2069
|
+
resetDraftProgressState();
|
|
2070
|
+
};
|
|
2071
|
+
const onQueuedFollowupAdmitted = !shouldUseDraftStream && !useNativeProgressStreaming ? void 0 : async () => {
|
|
2072
|
+
await draftStream?.flush();
|
|
2073
|
+
draftPreviewCommitted = false;
|
|
2074
|
+
observedFinalReplyDelivery = false;
|
|
2075
|
+
if (streamMode === "status_final") await beginNewProgressTurn({ force: true });
|
|
2076
|
+
else draftStream?.forceNewMessage();
|
|
2077
|
+
deliveryTracker = createSlackEventDeliveryTracker();
|
|
2078
|
+
resetDraftDeliveryState();
|
|
2079
|
+
resetDraftProgressState();
|
|
1868
2080
|
};
|
|
1869
2081
|
let dispatchError;
|
|
1870
2082
|
let queuedFinal = false;
|
|
1871
2083
|
let counts = {};
|
|
1872
2084
|
try {
|
|
1873
|
-
const turnResult = await
|
|
2085
|
+
const turnResult = await dispatchChannelInboundTurn({
|
|
1874
2086
|
cfg,
|
|
1875
2087
|
channel: "slack",
|
|
1876
2088
|
accountId: route.accountId,
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
2089
|
+
route: {
|
|
2090
|
+
agentId: route.agentId,
|
|
2091
|
+
sessionKey: route.sessionKey
|
|
2092
|
+
},
|
|
1880
2093
|
ctxPayload: prepared.ctxPayload,
|
|
1881
|
-
recordInboundSession,
|
|
1882
|
-
dispatchReplyWithBufferedBlockDispatcher,
|
|
1883
2094
|
dispatcherOptions: {
|
|
1884
2095
|
...replyPipeline,
|
|
1885
2096
|
humanDelay: resolveHumanDelayConfig(cfg, route.agentId)
|
|
@@ -1892,6 +2103,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1892
2103
|
history: prepared.turn.history,
|
|
1893
2104
|
botLoopProtection: resolveSlackBotLoopProtection(prepared),
|
|
1894
2105
|
replyOptions: {
|
|
2106
|
+
...prepared.turnAdoptionLifecycle ? { turnAdoptionLifecycle: prepared.turnAdoptionLifecycle } : {},
|
|
1895
2107
|
skillFilter: prepared.channelConfig?.skills,
|
|
1896
2108
|
sourceReplyDeliveryMode,
|
|
1897
2109
|
suppressTyping: suppressRoomEventTyping ? true : void 0,
|
|
@@ -1900,6 +2112,8 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1900
2112
|
onModelSelected,
|
|
1901
2113
|
suppressDefaultToolProgressMessages: suppressDefaultToolProgressMessages ? true : void 0,
|
|
1902
2114
|
commentaryProgressEnabled: commentaryProgressEnabled ? true : void 0,
|
|
2115
|
+
progressPreambleEnabled: progressDraftActive && slackStreaming.mode === "progress" ? true : void 0,
|
|
2116
|
+
commentaryPayloadsEnabled: commentaryProgressEnabled ? true : void 0,
|
|
1903
2117
|
onVerboseProgressVisibility: commentaryProgressEnabled ? (isActive) => {
|
|
1904
2118
|
shouldYieldDraftProgress = isActive;
|
|
1905
2119
|
} : void 0,
|
|
@@ -1909,7 +2123,11 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1909
2123
|
updateDraftFromPartial(payload.text);
|
|
1910
2124
|
},
|
|
1911
2125
|
onAssistantMessageStart: onDraftBoundary,
|
|
1912
|
-
onReasoningEnd:
|
|
2126
|
+
onReasoningEnd: async () => {
|
|
2127
|
+
progressReceipt.closeReasoning();
|
|
2128
|
+
await onDraftBoundary?.();
|
|
2129
|
+
},
|
|
2130
|
+
onQueuedFollowupAdmitted,
|
|
1913
2131
|
onReasoningStream: statusReactionsEnabled || previewToolProgressEnabled ? async (payload) => {
|
|
1914
2132
|
await pushReasoningProgress(payload);
|
|
1915
2133
|
if (!statusReactionsEnabled) return;
|
|
@@ -1917,6 +2135,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1917
2135
|
} : void 0,
|
|
1918
2136
|
onToolStart: async (payload) => {
|
|
1919
2137
|
if (statusReactionsEnabled) await statusReactions.setTool(payload.name);
|
|
2138
|
+
if (payload.phase === "start") progressReceipt.noteToolCall(payload.name);
|
|
1920
2139
|
await pushPreviewProgress(buildChannelProgressDraftLineForEntry(account.config, {
|
|
1921
2140
|
event: "tool",
|
|
1922
2141
|
itemId: payload.itemId,
|
|
@@ -1927,6 +2146,14 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1927
2146
|
}, payload.detailMode ? { detailMode: payload.detailMode } : void 0), { toolName: payload.name });
|
|
1928
2147
|
},
|
|
1929
2148
|
onItemEvent: async (payload) => {
|
|
2149
|
+
if (streamMode === "status_final" && payload.kind === "preamble") {
|
|
2150
|
+
if (shouldYieldDraftProgress()) return;
|
|
2151
|
+
await progressDraft.pushPreambleHeadline(payload.progressText, { itemId: payload.itemId });
|
|
2152
|
+
if (commentaryProgressEnabled) {
|
|
2153
|
+
if (await progressDraft.pushCommentaryProgress(payload.progressText, { itemId: payload.itemId })) progressReceipt.noteCommentary(payload.itemId, payload.progressText);
|
|
2154
|
+
}
|
|
2155
|
+
return;
|
|
2156
|
+
}
|
|
1930
2157
|
await pushPreviewProgress(buildChannelProgressDraftLineForEntry(account.config, {
|
|
1931
2158
|
event: "item",
|
|
1932
2159
|
itemId: payload.itemId,
|
|
@@ -1939,17 +2166,11 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
1939
2166
|
summary: payload.summary,
|
|
1940
2167
|
progressText: payload.progressText,
|
|
1941
2168
|
meta: payload.meta
|
|
1942
|
-
})
|
|
2169
|
+
}));
|
|
1943
2170
|
},
|
|
1944
2171
|
onPlanUpdate: async (payload) => {
|
|
1945
2172
|
if (payload.phase !== "update") return;
|
|
1946
|
-
await
|
|
1947
|
-
event: "plan",
|
|
1948
|
-
phase: payload.phase,
|
|
1949
|
-
title: payload.title,
|
|
1950
|
-
explanation: payload.explanation,
|
|
1951
|
-
steps: payload.steps
|
|
1952
|
-
}));
|
|
2173
|
+
await pushPlanProgress(payload.steps, payload.explanation);
|
|
1953
2174
|
},
|
|
1954
2175
|
onApprovalEvent: async (payload) => {
|
|
1955
2176
|
if (payload.phase !== "requested") return;
|
|
@@ -2000,26 +2221,26 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2000
2221
|
} catch (err) {
|
|
2001
2222
|
dispatchError = err;
|
|
2002
2223
|
} finally {
|
|
2003
|
-
|
|
2224
|
+
progressDraft.cancel();
|
|
2004
2225
|
await draftStream?.discardPending();
|
|
2005
2226
|
}
|
|
2006
2227
|
let streamFallbackDelivered = false;
|
|
2007
2228
|
const finalStream = streamSession;
|
|
2008
2229
|
if (finalStream && !finalStream.stopped) try {
|
|
2009
|
-
const completionChunks = useNativeProgressStreaming && !nativeProgressCompletionSent
|
|
2010
|
-
title: explicitProgressTitle,
|
|
2011
|
-
lines: previewToolProgressLines,
|
|
2012
|
-
maxLineChars: progressDraftMaxLineChars,
|
|
2013
|
-
finalInProgressStatus: dispatchError ? "error" : "complete"
|
|
2014
|
-
}) : void 0;
|
|
2230
|
+
const completionChunks = useNativeProgressStreaming && !nativeProgressCompletionSent ? buildNativeProgressCompletionChunks(dispatchError ? "error" : nativeProgressTerminalStatus) : void 0;
|
|
2015
2231
|
if (completionChunks?.length) nativeProgressCompletionSent = true;
|
|
2016
2232
|
const stopResult = await stopSlackStream({
|
|
2017
2233
|
session: finalStream,
|
|
2018
2234
|
...completionChunks?.length ? { chunks: completionChunks } : {},
|
|
2019
2235
|
...slackMessageMetadata ? { metadata: slackMessageMetadata } : {}
|
|
2020
2236
|
});
|
|
2021
|
-
|
|
2022
|
-
|
|
2237
|
+
acknowledgeStoppedStreamedDeliveries(finalStream, stopResult?.messageId);
|
|
2238
|
+
if (pendingNativeProgressReceipt && stopResult?.messageId && !progressReceiptCollapsed) await collapseProgressReceipt({
|
|
2239
|
+
channelId: finalStream.channel,
|
|
2240
|
+
messageId: stopResult.messageId,
|
|
2241
|
+
text: pendingNativeProgressReceipt,
|
|
2242
|
+
threadTs: finalStream.threadTs
|
|
2243
|
+
});
|
|
2023
2244
|
} catch (err) {
|
|
2024
2245
|
if (err instanceof SlackStreamNotDeliveredError) {
|
|
2025
2246
|
streamFallbackDelivered = await deliverPendingStreamFallback(finalStream, err);
|
|
@@ -2199,7 +2420,7 @@ async function discardSlackPreflightMedia(media) {
|
|
|
2199
2420
|
const SLACK_MENTION_RESOLUTION_CONCURRENCY = 4;
|
|
2200
2421
|
const SLACK_MENTION_RESOLUTION_MAX_LOOKUPS_PER_MESSAGE = 20;
|
|
2201
2422
|
const SLACK_USER_MENTION_RE$1 = /<@([A-Z0-9]+)(?:\|[^>]+)?>/gi;
|
|
2202
|
-
const loadSlackMediaModule$1 = createLazyRuntimeModule(() => import("./actions-
|
|
2423
|
+
const loadSlackMediaModule$1 = createLazyRuntimeModule(() => import("./actions-CF0tUY5q.js").then((n) => n.g));
|
|
2203
2424
|
function collectUniqueSlackMentionIds$1(texts) {
|
|
2204
2425
|
const seen = /* @__PURE__ */ new Set();
|
|
2205
2426
|
const mentionIds = [];
|
|
@@ -2621,7 +2842,7 @@ function formatSlackThreadLabelSnippet(text) {
|
|
|
2621
2842
|
}
|
|
2622
2843
|
//#endregion
|
|
2623
2844
|
//#region extensions/slack/src/monitor/message-handler/prepare-thread-context.ts
|
|
2624
|
-
const loadSlackMediaModule = createLazyRuntimeModule(() => import("./actions-
|
|
2845
|
+
const loadSlackMediaModule = createLazyRuntimeModule(() => import("./actions-CF0tUY5q.js").then((n) => n.g));
|
|
2625
2846
|
const SLACK_THREAD_CONTEXT_USER_LOOKUP_CONCURRENCY = 4;
|
|
2626
2847
|
function resolveSlackThreadSessionFreshness(params) {
|
|
2627
2848
|
return params.ctx.channelRuntime?.session?.resolveEntryResetFreshness?.({
|
|
@@ -2636,14 +2857,21 @@ function resolveSlackThreadSessionFreshness(params) {
|
|
|
2636
2857
|
});
|
|
2637
2858
|
}
|
|
2638
2859
|
function isSlackThreadContextSenderAllowed(params) {
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2860
|
+
return resolveInboundSupplementalSenderAllowed({
|
|
2861
|
+
isGroup: true,
|
|
2862
|
+
groupPolicy: params.allowFromLower.length === 0 ? "open" : "allowlist",
|
|
2863
|
+
allowFrom: params.allowFromLower,
|
|
2864
|
+
isSenderAllowed: (allowFrom) => {
|
|
2865
|
+
if (params.botId) return true;
|
|
2866
|
+
if (!params.userId) return false;
|
|
2867
|
+
return resolveSlackAllowListMatch({
|
|
2868
|
+
allowList: allowFrom,
|
|
2869
|
+
id: params.userId,
|
|
2870
|
+
name: params.userName,
|
|
2871
|
+
allowNameMatching: params.allowNameMatching
|
|
2872
|
+
}).allowed;
|
|
2873
|
+
}
|
|
2874
|
+
});
|
|
2647
2875
|
}
|
|
2648
2876
|
async function resolveSlackThreadUserMap(params) {
|
|
2649
2877
|
const uniqueUserIds = [];
|
|
@@ -3336,7 +3564,7 @@ async function prepareSlackMessage(params) {
|
|
|
3336
3564
|
name: void 0
|
|
3337
3565
|
});
|
|
3338
3566
|
let implicitMentionKinds = [];
|
|
3339
|
-
if (!isDirectMessage && ctx.botUserId && message.thread_ts && !
|
|
3567
|
+
if (!isDirectMessage && ctx.botUserId && message.thread_ts && !wasMentioned) {
|
|
3340
3568
|
const replyToBotKinds = implicitMentionKindWhen("reply_to_bot", message.parent_user_id === ctx.botUserId);
|
|
3341
3569
|
implicitMentionKinds = replyToBotKinds.length > 0 ? replyToBotKinds : implicitMentionKindWhen("bot_thread_participant", await hasSlackThreadParticipationWithPersistence({
|
|
3342
3570
|
accountId: account.accountId,
|
|
@@ -3432,6 +3660,11 @@ async function prepareSlackMessage(params) {
|
|
|
3432
3660
|
surface: "slack"
|
|
3433
3661
|
});
|
|
3434
3662
|
const shouldRequireMention = isRoom ? channelConfig?.requireMention ?? ctx.defaultRequireMention : false;
|
|
3663
|
+
const implicitMentions = resolveChannelImplicitMentions({
|
|
3664
|
+
cfg,
|
|
3665
|
+
channel: "slack",
|
|
3666
|
+
accountId: account.accountId
|
|
3667
|
+
});
|
|
3435
3668
|
if (message["_ambiguousThreadReply"]) {
|
|
3436
3669
|
ctx.logger.info({
|
|
3437
3670
|
channel: message.channel,
|
|
@@ -3464,7 +3697,7 @@ async function prepareSlackMessage(params) {
|
|
|
3464
3697
|
activation: {
|
|
3465
3698
|
requireMention: shouldRequireMention,
|
|
3466
3699
|
allowTextCommands,
|
|
3467
|
-
|
|
3700
|
+
implicitMentions
|
|
3468
3701
|
}
|
|
3469
3702
|
});
|
|
3470
3703
|
const senderGate = messageIngress.senderAccess.gate;
|
|
@@ -3576,7 +3809,7 @@ async function prepareSlackMessage(params) {
|
|
|
3576
3809
|
allowTextCommands,
|
|
3577
3810
|
hasControlCommand: hasControlCommandInMessage,
|
|
3578
3811
|
commandAuthorized,
|
|
3579
|
-
|
|
3812
|
+
implicitMentions
|
|
3580
3813
|
}
|
|
3581
3814
|
});
|
|
3582
3815
|
const effectiveWasMentioned = mentionDecision.effectiveWasMentioned;
|
|
@@ -3804,6 +4037,7 @@ async function prepareSlackMessage(params) {
|
|
|
3804
4037
|
},
|
|
3805
4038
|
route: {
|
|
3806
4039
|
agentId: route.agentId,
|
|
4040
|
+
dmScope: route.dmScope,
|
|
3807
4041
|
accountId: route.accountId,
|
|
3808
4042
|
routeSessionKey: sessionKey,
|
|
3809
4043
|
parentSessionKey: threadKeys.parentSessionKey
|