@openclaw/slack 2026.8.1 → 2026.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{account-inspect-CN2hBsim.js → account-inspect-C3sePHWa.js} +3 -3
- package/dist/account-inspect-api.js +1 -1
- package/dist/{action-runtime-044ldvNL.js → action-runtime-B0kRJ69h.js} +50 -40
- package/dist/action-runtime.runtime-IuA14rev.js +2 -0
- package/dist/{actions-BI7JkfVm.js → actions-BOxiu2Vy.js} +18 -12
- package/dist/api.js +14 -14
- package/dist/{approval-handler.runtime-DYv0UIZS.js → approval-handler.runtime-l5_2JLqi.js} +7 -6
- package/dist/{channel-1vIJOzPx.js → channel-BguxhhNG.js} +39 -31
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-type-DlFSKeIZ.js → channel-type-ChkODKBW.js} +2 -2
- package/dist/{channel.setup-ofDi3_Pu.js → channel.setup-BJohRJha.js} +23 -22
- package/dist/{config-schema-BVIMyiDN.js → config-schema-B9GwoRlE.js} +5 -3
- package/dist/{conversation-binding-route-DFVLUdYF.js → conversation-binding-route-Vee8Dgbf.js} +2 -2
- package/dist/{directory-config-DqfQ42OV.js → directory-config-Bmw4ykSy.js} +4 -3
- package/dist/directory-contract-api.js +1 -1
- package/dist/{directory-live-BPaNHjmP.js → directory-live-BOILcXPo.js} +1 -1
- package/dist/{doctor-contract-BAy7-EUQ.js → doctor-contract-BNjw9bxb.js} +5 -4
- package/dist/doctor-contract-api.js +1 -1
- package/dist/{group-policy-BdwszjYn.js → group-policy-BYH74y50.js} +70 -39
- package/dist/{message-tool-api-CJ0kjcg5.js → message-tool-api-BsZbsulu.js} +1 -1
- package/dist/message-tool-api.js +1 -1
- package/dist/{monitor-Dq5Cmrvp.js → monitor-B72wWXWg.js} +3 -3
- package/dist/{outbound-adapter-DYaI8ThX.js → outbound-adapter-CPgYQ-BM.js} +3 -3
- package/dist/{pipeline.runtime-Bd22U0ga.js → pipeline.runtime-CcdujV99.js} +238 -393
- package/dist/{policy-CtQVbde1.js → policy-CUpBeOt9.js} +7 -5
- package/dist/{probe-0usmAb0i.js → probe-gj5yQgN2.js} +113 -112
- package/dist/{provider-CN_8hFv2.js → provider-DW9YC_no.js} +69 -44
- package/dist/{relay-source-BNGpsdwV.js → relay-source-BLMdBrAw.js} +6 -4
- package/dist/{replies-BSiRQOJ1.js → replies-DLjQ8RYU.js} +13 -8
- package/dist/{resolve-channels-Czheznc8.js → resolve-channels-Bv6IiGZ4.js} +4 -3
- package/dist/{resolve-users-BAOlNimr.js → resolve-users-BXw2pA7y.js} +4 -3
- package/dist/runtime-api.js +10 -10
- package/dist/{scopes-COSlmhnH.js → scopes-B9HRguDe.js} +1 -1
- package/dist/{send-DS9ICrBI.js → send-GUz4_v2E.js} +21 -13
- package/dist/{send.runtime-D_Bb6IuH.js → send.runtime-rScD-UJi.js} +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-BGnd2pSe.js → setup-surface-Cc3P-z35.js} +5 -5
- package/dist/{shared-D5B-5hBg.js → shared-CQGVZ_8a.js} +5 -5
- package/dist/{slash-dispatch.runtime-CilDmI0c.js → slash-dispatch.runtime-C2015r6s.js} +1 -1
- package/dist/{target-parsing-BnMD2ZqZ.js → target-parsing-PbxGDbr9.js} +11 -6
- package/dist/{targets-Cx5W_n3W.js → targets-7FexXJ62.js} +1 -1
- package/node_modules/@slack/bolt/node_modules/negotiator/lib/accept.js +54 -0
- package/node_modules/@slack/bolt/node_modules/negotiator/lib/charset.js +10 -34
- package/node_modules/@slack/bolt/node_modules/negotiator/lib/encoding.js +9 -30
- package/node_modules/@slack/bolt/node_modules/negotiator/lib/language.js +15 -36
- package/node_modules/@slack/bolt/node_modules/negotiator/lib/mediaType.js +16 -134
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/LICENSE +22 -0
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/README.md +71 -0
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.d.ts +46 -0
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.js +176 -0
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.js.map +1 -0
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/package.json +52 -0
- package/node_modules/@slack/bolt/node_modules/negotiator/package.json +16 -10
- package/node_modules/typebox/build/format/email.mjs +1 -1
- package/node_modules/typebox/build/format/idna/idn-hostname.mjs +19 -1
- package/node_modules/typebox/package.json +1 -1
- package/package.json +5 -5
- package/dist/action-runtime.runtime-BL3KzX13.js +0 -2
- package/node_modules/@slack/bolt/node_modules/negotiator/HISTORY.md +0 -114
|
@@ -1,23 +1,22 @@
|
|
|
1
|
-
import { n as resolveSlackConversationBindingRoute, r as resolveSlackReplyToMode, t as normalizeSlackRouteBindingConfig } from "./conversation-binding-route-
|
|
2
|
-
import { n as formatSlackTarget } from "./target-parsing-
|
|
3
|
-
import { I as countSlackTextUtf8Bytes, L as truncateSlackText, M as SLACK_TEXT_LIMIT, Q as normalizeSlackOutboundText, R as truncateSlackTextByUtf8Bytes, T as buildSlackBlocksFallbackText, U as SLACK_SESSION_LINK_ACTION_ID, a as qualifySlackConversationId, b as hasSlackNativeDataBlock, et as escapeSlackMrkdwn, k as SLACK_EDIT_TEXT_MAX_BYTES, m as resolveSlackReplyRenderPlan, o as qualifySlackRoutePeerId, s as resolveSlackEnterpriseMainDmSessionKey } from "./group-policy-
|
|
4
|
-
import {
|
|
1
|
+
import { n as resolveSlackConversationBindingRoute, r as resolveSlackReplyToMode, t as normalizeSlackRouteBindingConfig } from "./conversation-binding-route-Vee8Dgbf.js";
|
|
2
|
+
import { n as formatSlackTarget } from "./target-parsing-PbxGDbr9.js";
|
|
3
|
+
import { I as countSlackTextUtf8Bytes, L as truncateSlackText, M as SLACK_TEXT_LIMIT, Q as normalizeSlackOutboundText, R as truncateSlackTextByUtf8Bytes, T as buildSlackBlocksFallbackText, U as SLACK_SESSION_LINK_ACTION_ID, a as qualifySlackConversationId, b as hasSlackNativeDataBlock, et as escapeSlackMrkdwn, k as SLACK_EDIT_TEXT_MAX_BYTES, m as resolveSlackReplyRenderPlan, o as qualifySlackRoutePeerId, s as resolveSlackEnterpriseMainDmSessionKey } from "./group-policy-BYH74y50.js";
|
|
4
|
+
import { C as normalizeAllowListLower, E as resolveSlackAllowListMatch, o as formatSlackError, w as normalizeSlackAllowOwnerEntry } from "./probe-gj5yQgN2.js";
|
|
5
5
|
import { n as resolveSlackStreamingMode, t as resolveSlackNativeStreaming } from "./streaming-compat-B-e0mqM0.js";
|
|
6
|
-
import { D as resolveSlackMessageText$1, E as resolveSlackBlocksText, O as buildSlackEditTextPayload, S as formatSlackFileReferenceList, T as isSlackUnfurlAttachment, a as editSlackRenderedMessage, d as reactSlackMessage, i as editSlackMessage, m as removeSlackReaction, n as deleteSlackMessage, v as logVerbose$1, w as hasSlackTableBlock, x as formatSlackFileReference } from "./actions-
|
|
7
|
-
import { c as hasSlackThreadFailureNotice, d as recordSlackThreadFailureNotice, f as recordSlackThreadParticipation, l as hasSlackThreadParticipation, m as buildSlackNativeDataDeliveryPlan, o as clearSlackThreadFailureNotice, r as sendMessageSlack, u as hasSlackThreadParticipationWithPersistence } from "./send-
|
|
8
|
-
import { C as resolveStorePath, E as stripSlackMentionsForCommandDetection, S as resolveChannelResetConfig, _ as resolveSlackChatType, b as readSessionUpdatedAt, c as resolveSlackThreadTargets, d as authorizeSlackBotRoomMessage, f as resolveSlackCommandIngress, g as normalizeSlackChannelType, l as trackSlackDraftMessage, o as authorizeSlackDirectMessage, p as resolveSlackEffectiveAllowFrom, r as resolveSlackRoomContextHints, s as resolveSlackThreadContext, u as resolveConversationLabel$1, v as buildSlackAssistantThreadMetadata, w as updateLastRoute, x as resolveChannelContextVisibilityMode, y as parseSlackAssistantThreadMetadata } from "./provider-
|
|
9
|
-
import { n as resolveSlackChannelConfig } from "./policy-
|
|
10
|
-
import { a as resolveDeliveredSlackReplyThreadTs, c as emitSlackMessageSentHooks, i as readSlackReplyBlocks, n as deliverReplies, o as resolveSlackThreadTs, s as sanitizeSlackMonitorReplyPayload, t as createSlackReplyDeliveryPlan } from "./replies-
|
|
6
|
+
import { D as resolveSlackMessageText$1, E as resolveSlackBlocksText, O as buildSlackEditTextPayload, S as formatSlackFileReferenceList, T as isSlackUnfurlAttachment, a as editSlackRenderedMessage, d as reactSlackMessage, i as editSlackMessage, m as removeSlackReaction, n as deleteSlackMessage, v as logVerbose$1, w as hasSlackTableBlock, x as formatSlackFileReference } from "./actions-BOxiu2Vy.js";
|
|
7
|
+
import { c as hasSlackThreadFailureNotice, d as recordSlackThreadFailureNotice, f as recordSlackThreadParticipation, l as hasSlackThreadParticipation, m as buildSlackNativeDataDeliveryPlan, o as clearSlackThreadFailureNotice, r as sendMessageSlack, u as hasSlackThreadParticipationWithPersistence } from "./send-GUz4_v2E.js";
|
|
8
|
+
import { C as resolveStorePath, E as stripSlackMentionsForCommandDetection, S as resolveChannelResetConfig, _ as resolveSlackChatType, b as readSessionUpdatedAt, c as resolveSlackThreadTargets, d as authorizeSlackBotRoomMessage, f as resolveSlackCommandIngress, g as normalizeSlackChannelType, l as trackSlackDraftMessage, o as authorizeSlackDirectMessage, p as resolveSlackEffectiveAllowFrom, r as resolveSlackRoomContextHints, s as resolveSlackThreadContext, u as resolveConversationLabel$1, v as buildSlackAssistantThreadMetadata, w as updateLastRoute, x as resolveChannelContextVisibilityMode, y as parseSlackAssistantThreadMetadata } from "./provider-DW9YC_no.js";
|
|
9
|
+
import { n as resolveSlackChannelConfig } from "./policy-CUpBeOt9.js";
|
|
10
|
+
import { a as resolveDeliveredSlackReplyThreadTs, c as emitSlackMessageSentHooks, i as readSlackReplyBlocks, n as deliverReplies, o as resolveSlackThreadTs, s as sanitizeSlackMonitorReplyPayload, t as createSlackReplyDeliveryPlan } from "./replies-DLjQ8RYU.js";
|
|
11
11
|
import { asOptionalRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
12
12
|
import { resolveAgentRoute, resolveInboundLastRouteSessionKey, resolveThreadSessionKeys } from "openclaw/plugin-sdk/routing";
|
|
13
|
-
import {
|
|
13
|
+
import { createChannelMessageReplyPipeline, createChannelProgressDraftCompositor, createDraftStreamLoop, createFinalizableDraftStreamControlsForState, defineFinalizableLivePreviewAdapter, deliverWithFinalizableLivePreviewAdapter, formatChannelProgressDraftText, isChannelProgressDraftWorkToolName, resolveAgentOutboundIdentity, resolveChannelMessageSourceReplyDeliveryMode, resolveChannelProgressDraftConfig, resolveChannelProgressDraftMaxLineChars, resolveChannelStreamingBlockEnabled, resolveChannelStreamingPreviewToolProgress, resolveChannelStreamingSuppressDefaultToolProgressMessages } from "openclaw/plugin-sdk/channel-outbound";
|
|
14
14
|
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
15
15
|
import { danger, logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
|
|
16
16
|
import { sanitizeAssistantVisibleText } from "openclaw/plugin-sdk/text-chunking";
|
|
17
17
|
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
18
18
|
import { buildTtsSupplementMediaPayload, getReplyPayloadTtsSupplement, isReplyPayloadNonTerminalToolErrorWarning, resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
|
|
19
19
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
20
|
-
import { createHash } from "node:crypto";
|
|
21
20
|
import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
|
|
22
21
|
import { ensureConfiguredBindingRouteReady } from "openclaw/plugin-sdk/conversation-runtime";
|
|
23
22
|
import { resolveChannelImplicitMentions } from "openclaw/plugin-sdk/channel-ingress-runtime";
|
|
@@ -35,7 +34,7 @@ import { buildChannelInboundEventContext, buildMentionRegexes, classifyChannelIn
|
|
|
35
34
|
import { resolveHumanDelayConfig } from "openclaw/plugin-sdk/agent-runtime";
|
|
36
35
|
import { resolveGatewayPublicOrigin } from "openclaw/plugin-sdk/config-contracts";
|
|
37
36
|
import { buildControlUiSessionPath } from "openclaw/plugin-sdk/session-discussion";
|
|
38
|
-
import {
|
|
37
|
+
import { createStatusReactionController, logAckFailure, logTypingFailure, resolveAckReaction, shouldAckReaction } from "openclaw/plugin-sdk/channel-feedback";
|
|
39
38
|
import { hasControlCommand } from "openclaw/plugin-sdk/command-detection";
|
|
40
39
|
import { isAbortRequestText } from "openclaw/plugin-sdk/command-primitives-runtime";
|
|
41
40
|
import { shouldHandleTextCommands } from "openclaw/plugin-sdk/command-surface";
|
|
@@ -479,6 +478,7 @@ function createSlackDraftStream(params) {
|
|
|
479
478
|
};
|
|
480
479
|
const { loop, update, discardPending, seal } = createFinalizableDraftStreamControlsForState({
|
|
481
480
|
throttleMs,
|
|
481
|
+
coalesceInFlight: true,
|
|
482
482
|
state: streamState,
|
|
483
483
|
sendOrEditStreamMessage,
|
|
484
484
|
emptyValue: "",
|
|
@@ -572,64 +572,11 @@ function createSlackDraftStream(params) {
|
|
|
572
572
|
};
|
|
573
573
|
}
|
|
574
574
|
//#endregion
|
|
575
|
-
//#region extensions/slack/src/stream-mode.ts
|
|
576
|
-
function resolveSlackStreamingConfig(params) {
|
|
577
|
-
return {
|
|
578
|
-
mode: resolveSlackStreamingMode(params),
|
|
579
|
-
nativeStreaming: resolveSlackNativeStreaming(params)
|
|
580
|
-
};
|
|
581
|
-
}
|
|
582
|
-
function applyAppendOnlyStreamUpdate(params) {
|
|
583
|
-
const incoming = params.incoming.trimEnd();
|
|
584
|
-
if (!incoming) return {
|
|
585
|
-
rendered: params.rendered,
|
|
586
|
-
source: params.source,
|
|
587
|
-
changed: false
|
|
588
|
-
};
|
|
589
|
-
if (!params.rendered) return {
|
|
590
|
-
rendered: incoming,
|
|
591
|
-
source: incoming,
|
|
592
|
-
changed: true
|
|
593
|
-
};
|
|
594
|
-
if (incoming === params.source) return {
|
|
595
|
-
rendered: params.rendered,
|
|
596
|
-
source: params.source,
|
|
597
|
-
changed: false
|
|
598
|
-
};
|
|
599
|
-
if (incoming.startsWith(params.rendered)) return {
|
|
600
|
-
rendered: incoming,
|
|
601
|
-
source: incoming,
|
|
602
|
-
changed: incoming !== params.rendered
|
|
603
|
-
};
|
|
604
|
-
if (incoming.startsWith(params.source)) {
|
|
605
|
-
const delta = incoming.slice(params.source.length);
|
|
606
|
-
return {
|
|
607
|
-
rendered: `${params.rendered}${delta}`,
|
|
608
|
-
source: incoming,
|
|
609
|
-
changed: delta.length > 0
|
|
610
|
-
};
|
|
611
|
-
}
|
|
612
|
-
if (params.source.startsWith(incoming)) return {
|
|
613
|
-
rendered: params.rendered,
|
|
614
|
-
source: params.source,
|
|
615
|
-
changed: false
|
|
616
|
-
};
|
|
617
|
-
const separator = params.separator ?? (params.rendered.endsWith("\n") ? "" : "\n");
|
|
618
|
-
return {
|
|
619
|
-
rendered: `${params.rendered}${separator}${incoming}`,
|
|
620
|
-
source: incoming,
|
|
621
|
-
changed: true
|
|
622
|
-
};
|
|
623
|
-
}
|
|
624
|
-
//#endregion
|
|
625
575
|
//#region extensions/slack/src/progress-blocks.ts
|
|
626
576
|
const SLACK_PROGRESS_FIELD_MAX = 1800;
|
|
627
577
|
const DEFAULT_SLACK_PROGRESS_DETAIL_MAX_CHARS = 120;
|
|
628
|
-
const DEFAULT_SLACK_PROGRESS_TASK_DETAIL_MAX_CHARS = 48;
|
|
629
578
|
const SLACK_PROGRESS_CHUNK_TEXT_MAX = 256;
|
|
630
579
|
const SLACK_PROGRESS_TASK_TITLE_MAX = 120;
|
|
631
|
-
const SLACK_PROGRESS_PLAN_FALLBACK_TITLE = "Thinking";
|
|
632
|
-
const SLACK_PROGRESS_LINE_DELTA_RE = /(?:^|\s)\+(\d+)\s+[−-](\d+)(?=\s|$)/u;
|
|
633
580
|
function buildSessionSources(url) {
|
|
634
581
|
return [{
|
|
635
582
|
type: "url_source",
|
|
@@ -637,12 +584,6 @@ function buildSessionSources(url) {
|
|
|
637
584
|
text: "Open in OpenClaw"
|
|
638
585
|
}];
|
|
639
586
|
}
|
|
640
|
-
function field(text) {
|
|
641
|
-
return {
|
|
642
|
-
type: "mrkdwn",
|
|
643
|
-
text: truncateSlackText(text, SLACK_PROGRESS_FIELD_MAX)
|
|
644
|
-
};
|
|
645
|
-
}
|
|
646
587
|
function resolveMaxLineChars(value, fallback) {
|
|
647
588
|
return value && value > 0 ? Math.floor(value) : fallback;
|
|
648
589
|
}
|
|
@@ -661,141 +602,58 @@ function compactTitle(value) {
|
|
|
661
602
|
function compactChunkText(value) {
|
|
662
603
|
return truncateSlackText(value.replace(/\s+/g, " ").trim(), SLACK_PROGRESS_CHUNK_TEXT_MAX);
|
|
663
604
|
}
|
|
664
|
-
function lineDetailParts(line) {
|
|
665
|
-
return [line.detail, line.status && line.status !== "completed" && !line.detail?.includes(line.status) ? line.status : void 0].map((part) => part?.trim()).filter((part) => Boolean(part));
|
|
666
|
-
}
|
|
667
|
-
function legacyLineTitle(line) {
|
|
668
|
-
return `${line.icon ?? "•"} *${escapeSlackMrkdwn(line.label)}*`;
|
|
669
|
-
}
|
|
670
605
|
function isAuthoredProgressLine(line) {
|
|
671
606
|
return line.id === "reasoning" || line.id?.startsWith("commentary:") === true;
|
|
672
607
|
}
|
|
673
|
-
function
|
|
674
|
-
const
|
|
675
|
-
if (
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
function lineTaskTitle(line) {
|
|
680
|
-
const label = (line.kind === "command-output" ? line.toolName : void 0) || line.label.replace(/\s+/g, " ").trim() || line.toolName || line.kind || "Update";
|
|
681
|
-
const fallback = line.text.replace(/\s+/g, " ").trim();
|
|
682
|
-
if (fallback && fallback !== label) return compactTitle(lineDetailParts(line).length > 0 || line.status ? label : fallback);
|
|
683
|
-
return compactTitle(label);
|
|
684
|
-
}
|
|
685
|
-
function lineTaskDetails(line, maxLineChars) {
|
|
686
|
-
const detail = line.detail?.replace(SLACK_PROGRESS_LINE_DELTA_RE, "").replace(/\s+·\s*$/u, "").trim();
|
|
687
|
-
return detail && detail !== line.status?.trim() ? compactDetail(detail, maxLineChars) : void 0;
|
|
688
|
-
}
|
|
689
|
-
function lineTaskOutput(line) {
|
|
690
|
-
const match = line.detail ? SLACK_PROGRESS_LINE_DELTA_RE.exec(line.detail) : null;
|
|
691
|
-
if (match) return `+${match[1]} −${match[2]}`;
|
|
692
|
-
const status = line.status?.replace(/\s+/g, " ").trim();
|
|
693
|
-
return status && lineTaskStatus(line) === "error" ? status : void 0;
|
|
694
|
-
}
|
|
695
|
-
function lineTaskStatus(line) {
|
|
696
|
-
const normalized = line.status?.replace(/\s+/g, " ").trim().toLowerCase();
|
|
697
|
-
if (!normalized) return "in_progress";
|
|
698
|
-
if (normalized === "complete" || normalized === "completed" || normalized === "done" || normalized === "ok" || normalized === "success" || normalized === "succeeded" || normalized === "successful" || normalized === "exit 0") return "complete";
|
|
699
|
-
if (normalized === "error" || normalized === "failed" || normalized === "failure" || normalized.startsWith("exit ")) return normalized === "exit 0" ? "complete" : "error";
|
|
700
|
-
return "in_progress";
|
|
701
|
-
}
|
|
702
|
-
function slugTaskIdPart(value) {
|
|
703
|
-
return value?.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "") || "task";
|
|
704
|
-
}
|
|
705
|
-
function stableTaskIdPart(value, slugValue = value) {
|
|
706
|
-
const suffix = createHash("sha256").update(value).digest("hex").slice(0, 8);
|
|
707
|
-
return `${slugTaskIdPart(slugValue).slice(0, 48)}_${suffix}`;
|
|
708
|
-
}
|
|
709
|
-
function resolveLineTaskIdentity(line) {
|
|
710
|
-
if (line.id?.trim()) return {
|
|
711
|
-
id: stableTaskIdPart(line.id),
|
|
712
|
-
contentDerived: false
|
|
608
|
+
function resolveProgressAttention(lines) {
|
|
609
|
+
const approval = lines.findLast((line) => line.kind === "approval" && line.status === "requested");
|
|
610
|
+
if (approval) return {
|
|
611
|
+
id: "openclaw_attention",
|
|
612
|
+
title: compactTitle(`Approval required: ${approval.detail || approval.label}`),
|
|
613
|
+
status: "pending"
|
|
713
614
|
};
|
|
615
|
+
const failure = lines.findLast((line) => {
|
|
616
|
+
const status = line.status?.trim().toLowerCase();
|
|
617
|
+
return status === "error" || status === "failed" || status === "failure" || status?.startsWith("exit ") && status !== "exit 0";
|
|
618
|
+
});
|
|
619
|
+
if (!failure) return;
|
|
714
620
|
return {
|
|
715
|
-
id:
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
].join("
|
|
721
|
-
|
|
621
|
+
id: "openclaw_attention",
|
|
622
|
+
title: compactTitle([...new Set([
|
|
623
|
+
failure.label,
|
|
624
|
+
failure.detail,
|
|
625
|
+
failure.status
|
|
626
|
+
].filter(Boolean))].join(" — ")),
|
|
627
|
+
status: "error"
|
|
722
628
|
};
|
|
723
629
|
}
|
|
724
|
-
function
|
|
725
|
-
|
|
630
|
+
function buildSlackProgressStreamChunks(params) {
|
|
631
|
+
const title = compactChunkText(params.title?.trim() || params.label?.trim() || "Working");
|
|
632
|
+
if (!params.title && !params.label && !params.lines.length && !params.plan?.length && !params.sessionUrl) return;
|
|
633
|
+
const tasks = params.plan?.length ? params.plan.slice(-50).map((entry, index) => ({
|
|
726
634
|
id: `plan_step_${index + 1}`,
|
|
727
635
|
title: compactTitle(entry.step),
|
|
728
636
|
status: entry.status === "completed" ? "complete" : entry.status
|
|
729
|
-
}))
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
}
|
|
742
|
-
const details = lineTaskDetails(line, maxLineChars);
|
|
743
|
-
const output = lineTaskOutput(line);
|
|
744
|
-
const task = {
|
|
745
|
-
id,
|
|
746
|
-
title: lineTaskTitle(line),
|
|
747
|
-
status: lineTaskStatus(line)
|
|
748
|
-
};
|
|
749
|
-
if (details) task.details = details;
|
|
750
|
-
if (output) task.output = output;
|
|
751
|
-
return task;
|
|
752
|
-
});
|
|
753
|
-
}
|
|
754
|
-
function resolvePlanTitle(params) {
|
|
755
|
-
return compactChunkText(params.title?.trim() || params.label?.trim() || (params.tasks.at(-1)?.details ? `${params.tasks.at(-1)?.title} — ${params.tasks.at(-1)?.details}` : params.tasks.at(-1)?.title) || SLACK_PROGRESS_PLAN_FALLBACK_TITLE);
|
|
756
|
-
}
|
|
757
|
-
function buildSlackProgressStreamChunks(params) {
|
|
758
|
-
const tasks = buildPlanTasks({
|
|
759
|
-
lines: params.lines,
|
|
760
|
-
plan: params.plan,
|
|
761
|
-
maxLineChars: params.maxLineChars
|
|
762
|
-
});
|
|
763
|
-
if (tasks.length === 0) {
|
|
764
|
-
const title = params.title?.trim() || params.label?.trim();
|
|
765
|
-
if (!title) return;
|
|
766
|
-
if (!params.sessionUrl && !params.diffStat) return [{
|
|
767
|
-
type: "plan_update",
|
|
768
|
-
title: compactChunkText(title)
|
|
769
|
-
}];
|
|
770
|
-
return [{
|
|
771
|
-
type: "plan_update",
|
|
772
|
-
title: compactChunkText(title)
|
|
773
|
-
}, {
|
|
774
|
-
type: "task_update",
|
|
775
|
-
id: "openclaw_summary",
|
|
776
|
-
title: "Completed",
|
|
777
|
-
status: "complete",
|
|
778
|
-
...formatTaskDiffOutput(params.diffStat) ? { output: formatTaskDiffOutput(params.diffStat) } : {},
|
|
779
|
-
...params.sessionUrl ? { sources: buildSessionSources(params.sessionUrl) } : {}
|
|
780
|
-
}];
|
|
781
|
-
}
|
|
782
|
-
const title = resolvePlanTitle({
|
|
783
|
-
label: params.label,
|
|
784
|
-
title: params.title,
|
|
785
|
-
tasks
|
|
786
|
-
});
|
|
637
|
+
})) : [{
|
|
638
|
+
id: "openclaw_summary",
|
|
639
|
+
title: compactTitle(title),
|
|
640
|
+
status: "in_progress"
|
|
641
|
+
}];
|
|
642
|
+
let attention = resolveProgressAttention(params.lines);
|
|
643
|
+
if (params.finalInProgressStatus === "error" && !tasks.some((task) => task.status === "in_progress")) attention = {
|
|
644
|
+
id: "openclaw_attention",
|
|
645
|
+
title: attention?.status === "error" ? attention.title : "Failed",
|
|
646
|
+
status: "error"
|
|
647
|
+
};
|
|
648
|
+
if (attention && !(params.finalInProgressStatus && attention.status === "pending")) tasks.push(attention);
|
|
787
649
|
const finalTaskIndex = tasks.length - 1;
|
|
788
|
-
const diffOutput = formatTaskDiffOutput(params.diffStat);
|
|
789
650
|
const taskChunks = tasks.map((task, index) => {
|
|
790
651
|
const chunk = {
|
|
791
652
|
type: "task_update",
|
|
792
653
|
id: task.id,
|
|
793
654
|
title: task.title,
|
|
794
|
-
status: task.status === "in_progress" ? params.finalInProgressStatus ??
|
|
655
|
+
status: task.status === "in_progress" ? params.finalInProgressStatus ?? task.status : task.status
|
|
795
656
|
};
|
|
796
|
-
if (task.details) chunk.details = task.details;
|
|
797
|
-
if (task.output) chunk.output = task.output;
|
|
798
|
-
if (index === finalTaskIndex && diffOutput) chunk.output = [task.output, diffOutput].filter(Boolean).join(" · ");
|
|
799
657
|
if (index === finalTaskIndex && params.sessionUrl) chunk.sources = buildSessionSources(params.sessionUrl);
|
|
800
658
|
return chunk;
|
|
801
659
|
});
|
|
@@ -804,113 +662,50 @@ function buildSlackProgressStreamChunks(params) {
|
|
|
804
662
|
title
|
|
805
663
|
}, ...taskChunks];
|
|
806
664
|
}
|
|
807
|
-
function formatDiffStat(diffStat) {
|
|
808
|
-
if (!diffStat || diffStat.files === 0 && diffStat.added === 0 && diffStat.removed === 0) return;
|
|
809
|
-
return [
|
|
810
|
-
`📝 ${diffStat.files} files`,
|
|
811
|
-
...diffStat.added > 0 ? [`+${diffStat.added}`] : [],
|
|
812
|
-
...diffStat.removed > 0 ? [`−${diffStat.removed}`] : []
|
|
813
|
-
].join(" ");
|
|
814
|
-
}
|
|
815
|
-
function formatTaskDiffOutput(diffStat) {
|
|
816
|
-
return diffStat && (diffStat.added > 0 || diffStat.removed > 0) ? `+${diffStat.added} −${diffStat.removed}` : void 0;
|
|
817
|
-
}
|
|
818
|
-
function buildActivityText(lines, maxLineChars) {
|
|
819
|
-
const rendered = [];
|
|
820
|
-
let length = 0;
|
|
821
|
-
for (const line of lines.slice(-50).toReversed()) {
|
|
822
|
-
const row = `${legacyLineTitle(line)} — ${legacyLineDetail(line, maxLineChars)}`;
|
|
823
|
-
const nextLength = length + row.length + (rendered.length > 0 ? 1 : 0);
|
|
824
|
-
if (nextLength > SLACK_PROGRESS_FIELD_MAX) break;
|
|
825
|
-
rendered.push(row);
|
|
826
|
-
length = nextLength;
|
|
827
|
-
}
|
|
828
|
-
return rendered.toReversed().join("\n");
|
|
829
|
-
}
|
|
830
665
|
function buildSlackProgressCardBlocks(params) {
|
|
831
666
|
const maxLineChars = resolveMaxLineChars(params.maxLineChars, DEFAULT_SLACK_PROGRESS_DETAIL_MAX_CHARS);
|
|
832
|
-
const
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
const narration = params.narration?.replace(/\s+/g, " ").trim();
|
|
837
|
-
const activityText = buildActivityText(params.lines, maxLineChars);
|
|
838
|
-
const diffStat = formatDiffStat(params.diffStat);
|
|
839
|
-
const workingFooter = [
|
|
840
|
-
...params.toolCalls && params.toolCalls > 0 ? [`🛠️ ${params.toolCalls} tools`] : [],
|
|
841
|
-
...diffStat ? [diffStat] : [],
|
|
842
|
-
...params.elapsedSeconds && params.elapsedSeconds > 0 ? [`⏱ ${params.elapsedSeconds}s`] : []
|
|
843
|
-
].join(" · ");
|
|
844
|
-
const footer = params.state === "working" ? workingFooter : diffStat;
|
|
845
|
-
return [
|
|
846
|
-
{
|
|
847
|
-
type: "section",
|
|
848
|
-
text: field(`${params.state === "working" ? "🔄" : params.state === "success" ? "✅" : "❌"} *${escapeSlackMrkdwn(params.title.trim() || "Working")}*`)
|
|
849
|
-
},
|
|
850
|
-
...narration ? [{
|
|
851
|
-
type: "section",
|
|
852
|
-
text: field(`_${escapeSlackMrkdwn(narration)}_`)
|
|
853
|
-
}] : [],
|
|
854
|
-
...planLines.length > 0 ? [{
|
|
855
|
-
type: "section",
|
|
856
|
-
text: field(planLines.map((line) => escapeSlackMrkdwn(line)).join("\n"))
|
|
857
|
-
}] : [],
|
|
858
|
-
...activityText ? [{
|
|
859
|
-
type: "section",
|
|
860
|
-
text: field(activityText)
|
|
861
|
-
}] : [],
|
|
862
|
-
...footer ? [{
|
|
863
|
-
type: "context",
|
|
864
|
-
elements: [field(footer)]
|
|
865
|
-
}] : [],
|
|
866
|
-
...params.state !== "working" && params.sessionUrl ? [{
|
|
867
|
-
type: "actions",
|
|
868
|
-
elements: [{
|
|
869
|
-
type: "button",
|
|
870
|
-
action_id: SLACK_SESSION_LINK_ACTION_ID,
|
|
871
|
-
text: {
|
|
872
|
-
type: "plain_text",
|
|
873
|
-
text: "Open in OpenClaw"
|
|
874
|
-
},
|
|
875
|
-
url: params.sessionUrl
|
|
876
|
-
}]
|
|
877
|
-
}] : []
|
|
878
|
-
].slice(0, 50);
|
|
879
|
-
}
|
|
880
|
-
const EMPTY_SLACK_NATIVE_STREAM_SNAPSHOT = { tasks: /* @__PURE__ */ new Map() };
|
|
881
|
-
const SLACK_TASK_FIELD_SEPARATOR = " · ";
|
|
882
|
-
function resolveTaskFieldDelta(previous, incoming) {
|
|
883
|
-
if (!incoming) return {
|
|
884
|
-
field: previous,
|
|
885
|
-
delta: void 0
|
|
667
|
+
const statusLabels = {
|
|
668
|
+
completed: "Completed",
|
|
669
|
+
in_progress: "In progress",
|
|
670
|
+
pending: "Pending"
|
|
886
671
|
};
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
672
|
+
const planLines = (params.plan ?? []).slice(-50).map((entry) => `${statusLabels[entry.status]}: ${compactDetail(entry.step, maxLineChars)}`);
|
|
673
|
+
const narration = params.narration?.replace(/\s+/g, " ").trim();
|
|
674
|
+
const authoredText = params.lines.filter(isAuthoredProgressLine).map((line) => line.text.trim()).filter((text, index, values) => text && text !== narration && values.indexOf(text) === index).map((text) => normalizeSlackOutboundText(compactDetail(text, maxLineChars))).join("\n");
|
|
675
|
+
const attention = resolveProgressAttention(params.lines);
|
|
676
|
+
const blocks = [
|
|
677
|
+
`${params.state === "success" ? "Completed: " : params.state === "error" ? "Failed: " : ""}*${escapeSlackMrkdwn(params.title.trim() || "Working")}*`,
|
|
678
|
+
narration ? `_${escapeSlackMrkdwn(narration)}_` : "",
|
|
679
|
+
planLines.map((line) => escapeSlackMrkdwn(line)).join("\n"),
|
|
680
|
+
authoredText,
|
|
681
|
+
attention && !(params.state !== "working" && attention.status === "pending") ? escapeSlackMrkdwn(attention.title) : ""
|
|
682
|
+
].filter(Boolean).map((text) => ({
|
|
683
|
+
type: "section",
|
|
684
|
+
text: {
|
|
685
|
+
type: "mrkdwn",
|
|
686
|
+
text: truncateSlackText(text, SLACK_PROGRESS_FIELD_MAX)
|
|
687
|
+
}
|
|
688
|
+
}));
|
|
689
|
+
if (params.state !== "working" && params.sessionUrl) blocks.push({
|
|
690
|
+
type: "actions",
|
|
691
|
+
elements: [{
|
|
692
|
+
type: "button",
|
|
693
|
+
action_id: SLACK_SESSION_LINK_ACTION_ID,
|
|
694
|
+
text: {
|
|
695
|
+
type: "plain_text",
|
|
696
|
+
text: "Open in OpenClaw"
|
|
697
|
+
},
|
|
698
|
+
url: params.sessionUrl
|
|
699
|
+
}]
|
|
899
700
|
});
|
|
900
|
-
|
|
901
|
-
return {
|
|
902
|
-
field: {
|
|
903
|
-
rendered: next.rendered,
|
|
904
|
-
source: next.source
|
|
905
|
-
},
|
|
906
|
-
delta
|
|
907
|
-
};
|
|
701
|
+
return blocks.slice(0, 50);
|
|
908
702
|
}
|
|
703
|
+
const EMPTY_SLACK_NATIVE_STREAM_SNAPSHOT = { tasks: /* @__PURE__ */ new Map() };
|
|
909
704
|
/**
|
|
910
705
|
* Turns a full task snapshot into the delta Slack must receive. Native streams
|
|
911
706
|
* key rows by persistent id with no removal chunk: unchanged rows are omitted,
|
|
912
|
-
* changed
|
|
913
|
-
* (plan shrinks,
|
|
707
|
+
* changed titles/statuses replace in place, and rows that dropped out
|
|
708
|
+
* (plan shrinks, summary <-> plan source switches) get a final complete
|
|
914
709
|
* update or they linger in_progress forever.
|
|
915
710
|
*/
|
|
916
711
|
function reconcileSlackNativeTaskChunks(params) {
|
|
@@ -931,26 +726,20 @@ function reconcileSlackNativeTaskChunks(params) {
|
|
|
931
726
|
}
|
|
932
727
|
const previousRow = params.previous.tasks.get(chunk.id);
|
|
933
728
|
const status = chunk.status;
|
|
934
|
-
const details = resolveTaskFieldDelta(previousRow?.details, chunk.details);
|
|
935
|
-
const output = resolveTaskFieldDelta(previousRow?.output, chunk.output);
|
|
936
729
|
const sourcesChanged = Boolean(chunk.sources) && !previousRow?.sourcesSent;
|
|
937
730
|
const row = {
|
|
938
731
|
title: chunk.title,
|
|
939
732
|
status
|
|
940
733
|
};
|
|
941
|
-
if (details.field) row.details = details.field;
|
|
942
|
-
if (output.field) row.output = output.field;
|
|
943
734
|
if (sourcesChanged || previousRow?.sourcesSent) row.sourcesSent = true;
|
|
944
735
|
nextTasks.set(chunk.id, row);
|
|
945
|
-
if (!(!previousRow || previousRow.title !== chunk.title || previousRow.status !== status ||
|
|
736
|
+
if (!(!previousRow || previousRow.title !== chunk.title || previousRow.status !== status || sourcesChanged)) continue;
|
|
946
737
|
const update = {
|
|
947
738
|
type: "task_update",
|
|
948
739
|
id: chunk.id,
|
|
949
740
|
title: chunk.title,
|
|
950
741
|
status
|
|
951
742
|
};
|
|
952
|
-
if (details.delta) update.details = details.delta;
|
|
953
|
-
if (output.delta) update.output = output.delta;
|
|
954
743
|
if (sourcesChanged) update.sources = chunk.sources;
|
|
955
744
|
emitted.push(update);
|
|
956
745
|
}
|
|
@@ -979,40 +768,63 @@ function reconcileSlackNativeTaskChunks(params) {
|
|
|
979
768
|
}
|
|
980
769
|
};
|
|
981
770
|
}
|
|
982
|
-
function buildSlackProgressStreamCompletionChunks(params) {
|
|
983
|
-
return buildSlackProgressStreamChunks({
|
|
984
|
-
...params,
|
|
985
|
-
completeInProgress: true
|
|
986
|
-
});
|
|
987
|
-
}
|
|
988
771
|
//#endregion
|
|
989
|
-
//#region extensions/slack/src/
|
|
990
|
-
function
|
|
991
|
-
return
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
772
|
+
//#region extensions/slack/src/stream-mode.ts
|
|
773
|
+
function resolveSlackStreamingConfig(params) {
|
|
774
|
+
return {
|
|
775
|
+
mode: resolveSlackStreamingMode(params),
|
|
776
|
+
nativeStreaming: resolveSlackNativeStreaming(params)
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
function applyAppendOnlyStreamUpdate(params) {
|
|
780
|
+
const incoming = params.incoming.trimEnd();
|
|
781
|
+
if (!incoming) return {
|
|
782
|
+
rendered: params.rendered,
|
|
783
|
+
source: params.source,
|
|
784
|
+
changed: false
|
|
785
|
+
};
|
|
786
|
+
if (!params.rendered) return {
|
|
787
|
+
rendered: incoming,
|
|
788
|
+
source: incoming,
|
|
789
|
+
changed: true
|
|
790
|
+
};
|
|
791
|
+
if (incoming === params.source) return {
|
|
792
|
+
rendered: params.rendered,
|
|
793
|
+
source: params.source,
|
|
794
|
+
changed: false
|
|
795
|
+
};
|
|
796
|
+
if (incoming.startsWith(params.rendered)) return {
|
|
797
|
+
rendered: incoming,
|
|
798
|
+
source: incoming,
|
|
799
|
+
changed: incoming !== params.rendered
|
|
800
|
+
};
|
|
801
|
+
if (incoming.startsWith(params.source)) {
|
|
802
|
+
const delta = incoming.slice(params.source.length);
|
|
995
803
|
return {
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
label: reasoning ? "Reasoning" : "Update",
|
|
1000
|
-
prefix: false
|
|
804
|
+
rendered: `${params.rendered}${delta}`,
|
|
805
|
+
source: incoming,
|
|
806
|
+
changed: delta.length > 0
|
|
1001
807
|
};
|
|
1002
|
-
}
|
|
808
|
+
}
|
|
809
|
+
if (params.source.startsWith(incoming)) return {
|
|
810
|
+
rendered: params.rendered,
|
|
811
|
+
source: params.source,
|
|
812
|
+
changed: false
|
|
813
|
+
};
|
|
814
|
+
const separator = params.separator ?? (params.rendered.endsWith("\n") ? "" : "\n");
|
|
815
|
+
return {
|
|
816
|
+
rendered: `${params.rendered}${separator}${incoming}`,
|
|
817
|
+
source: incoming,
|
|
818
|
+
changed: true
|
|
819
|
+
};
|
|
1003
820
|
}
|
|
1004
|
-
|
|
1005
|
-
|
|
821
|
+
//#endregion
|
|
822
|
+
//#region extensions/slack/src/monitor/message-handler/dispatch-progress-render.ts
|
|
823
|
+
function resolveStructuredProgressLines(lines) {
|
|
824
|
+
return lines.filter((line) => typeof line !== "string");
|
|
1006
825
|
}
|
|
1007
826
|
function resolveNativeProgressLines(snapshot) {
|
|
1008
|
-
|
|
1009
|
-
if (snapshot.plan?.length || !snapshot.planExplanation) return lines;
|
|
1010
|
-
const explanationLine = buildChannelProgressDraftLine({
|
|
1011
|
-
event: "plan",
|
|
1012
|
-
phase: "update",
|
|
1013
|
-
explanation: snapshot.planExplanation
|
|
1014
|
-
});
|
|
1015
|
-
return explanationLine ? [...lines, explanationLine] : lines;
|
|
827
|
+
return resolveStructuredProgressLines(snapshot.lines).filter((line) => line.id !== "reasoning" && line.id?.startsWith("commentary:") !== true);
|
|
1016
828
|
}
|
|
1017
829
|
function resolveNativeProgressNarration(snapshot) {
|
|
1018
830
|
const paragraphs = resolveStructuredProgressLines(snapshot.lines).filter((line) => line.id === "reasoning" || line.id?.startsWith("commentary:") === true).map((line) => line.text.trim()).filter((text, index, values) => Boolean(text) && values.indexOf(text) === index);
|
|
@@ -1021,14 +833,6 @@ function resolveNativeProgressNarration(snapshot) {
|
|
|
1021
833
|
function combineProgressHeadlineAndExplanation(headline, explanation) {
|
|
1022
834
|
return headline && explanation && headline !== explanation ? `${headline} — ${explanation}` : headline ?? explanation;
|
|
1023
835
|
}
|
|
1024
|
-
function buildNativeProgressChunks(params) {
|
|
1025
|
-
return buildSlackProgressStreamChunks({
|
|
1026
|
-
title: params.title,
|
|
1027
|
-
lines: resolveNativeProgressLines(params.snapshot),
|
|
1028
|
-
plan: resolveNativeProgressPlan(params.snapshot),
|
|
1029
|
-
maxLineChars: params.maxLineChars
|
|
1030
|
-
});
|
|
1031
|
-
}
|
|
1032
836
|
//#endregion
|
|
1033
837
|
//#region extensions/slack/src/monitor/message-handler/preview-finalize.ts
|
|
1034
838
|
function buildExpectedSlackEditText(params) {
|
|
@@ -1066,7 +870,8 @@ function blocksMatch(expected, actual) {
|
|
|
1066
870
|
const fallbackBlocks = fallbackPlan.fallbackMessages.flatMap((message) => message.blocks ?? []);
|
|
1067
871
|
if (JSON.stringify(fallbackBlocks) === JSON.stringify(actual)) return true;
|
|
1068
872
|
const fallbackText = fallbackPlan.fallbackMessages.map((message) => message.text).filter(Boolean).join("\n\n");
|
|
1069
|
-
|
|
873
|
+
const actualText = buildSlackBlocksFallbackText(actual);
|
|
874
|
+
return normalizeSlackOutboundText(actualText) === normalizeSlackOutboundText(fallbackText);
|
|
1070
875
|
} catch {
|
|
1071
876
|
return false;
|
|
1072
877
|
}
|
|
@@ -1157,6 +962,7 @@ function createSlackDraftProgressCardRuntime(params) {
|
|
|
1157
962
|
return url.toString();
|
|
1158
963
|
};
|
|
1159
964
|
const resolveText = (snapshot) => latestFallbackText || formatChannelProgressDraftText({
|
|
965
|
+
presentation: "summary",
|
|
1160
966
|
entry: account.config,
|
|
1161
967
|
lines: [...snapshot.lines],
|
|
1162
968
|
seed: params.progressSeed,
|
|
@@ -1173,11 +979,7 @@ function createSlackDraftProgressCardRuntime(params) {
|
|
|
1173
979
|
plan: snapshot.plan,
|
|
1174
980
|
lines: resolveStructuredProgressLines(snapshot.lines),
|
|
1175
981
|
maxLineChars: params.maxLineChars,
|
|
1176
|
-
|
|
1177
|
-
...state === "working" ? {
|
|
1178
|
-
toolCalls: params.progressWorkCounter.toolCalls,
|
|
1179
|
-
elapsedSeconds: params.progressWorkCounter.elapsedSeconds
|
|
1180
|
-
} : { sessionUrl: resolveSessionUrl() }
|
|
982
|
+
...state !== "working" ? { sessionUrl: resolveSessionUrl() } : {}
|
|
1181
983
|
});
|
|
1182
984
|
};
|
|
1183
985
|
const finalize = async (status, snapshot = params.getSnapshot(), fallbackText = resolveText(snapshot)) => {
|
|
@@ -1363,7 +1165,6 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1363
1165
|
nativeStreamOrder = run.catch(() => void 0);
|
|
1364
1166
|
return run;
|
|
1365
1167
|
};
|
|
1366
|
-
const progressWorkCounter = createChannelProgressWorkCounter();
|
|
1367
1168
|
const progressSeed = `${account.accountId}:${message.channel}`;
|
|
1368
1169
|
const slackProgressStyle = resolveSlackProgressStyle(account.config);
|
|
1369
1170
|
const useDraftProgressCard = Boolean(draftStream) && isProgressMode && slackProgressStyle === "card";
|
|
@@ -1379,7 +1180,6 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1379
1180
|
},
|
|
1380
1181
|
draftStream,
|
|
1381
1182
|
enabled: useDraftProgressCard,
|
|
1382
|
-
progressWorkCounter,
|
|
1383
1183
|
progressSeed,
|
|
1384
1184
|
explicitTitle: explicitProgressTitle,
|
|
1385
1185
|
maxLineChars: progressDraftMaxLineChars,
|
|
@@ -1399,12 +1199,17 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1399
1199
|
if (isError) nativeProgressTerminalStatus = "error";
|
|
1400
1200
|
if (!session || nativeProgressCompletionSent) return;
|
|
1401
1201
|
const chunks = buildNativeProgressCompletionChunks(isError ? "error" : "complete");
|
|
1402
|
-
|
|
1202
|
+
const narrationUpdate = resolveNarrationUpdate(resolveNativeProgressNarration(progressDraft.getSnapshot()));
|
|
1203
|
+
if (!chunks?.length && !narrationUpdate.delta) return;
|
|
1403
1204
|
try {
|
|
1404
1205
|
await appendSlackStream({
|
|
1405
1206
|
session,
|
|
1406
1207
|
chunks
|
|
1407
1208
|
});
|
|
1209
|
+
if (narrationUpdate.next.changed) {
|
|
1210
|
+
nativeNarrationRenderedText = narrationUpdate.next.rendered;
|
|
1211
|
+
nativeNarrationSourceText = narrationUpdate.next.source;
|
|
1212
|
+
}
|
|
1408
1213
|
nativeProgressCompletionSent = true;
|
|
1409
1214
|
delivery.observedReplyDelivery ||= session.delivered;
|
|
1410
1215
|
} catch (err) {
|
|
@@ -1413,11 +1218,6 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1413
1218
|
}
|
|
1414
1219
|
};
|
|
1415
1220
|
const resolveNativeProgressTitle = (snapshot) => combineProgressHeadlineAndExplanation(explicitProgressTitle ?? snapshot.statusHeadline, snapshot.planExplanation);
|
|
1416
|
-
const buildNativeProgressChunks$1 = (snapshot) => buildNativeProgressChunks({
|
|
1417
|
-
snapshot,
|
|
1418
|
-
title: resolveNativeProgressTitle(snapshot),
|
|
1419
|
-
maxLineChars: progressDraftMaxLineChars
|
|
1420
|
-
});
|
|
1421
1221
|
const normalizeProgressText = (text) => text?.replace(/\s+/gu, " ").trim() ?? "";
|
|
1422
1222
|
const isRenderedAsProgressTitle = (text) => {
|
|
1423
1223
|
const candidate = normalizeProgressText(text);
|
|
@@ -1436,17 +1236,18 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1436
1236
|
delta: next.changed ? next.rendered.slice(nativeNarrationRenderedText.length) : ""
|
|
1437
1237
|
};
|
|
1438
1238
|
};
|
|
1439
|
-
const updateNativeProgressStream = () => withNativeStreamOrder(updateNativeProgressStreamNow);
|
|
1440
1239
|
const updateNativeProgressStreamNow = async () => {
|
|
1441
1240
|
const snapshot = progressDraft.getSnapshot();
|
|
1442
|
-
const progressLines = resolveNativeProgressLines(snapshot);
|
|
1443
1241
|
const narrationUpdate = resolveNarrationUpdate(resolveNativeProgressNarration(snapshot));
|
|
1444
|
-
|
|
1445
|
-
if (!useNativeProgressStreaming || delivery.streamFailed || progressLines.length === 0 && !snapshot.plan?.length && !snapshot.statusHeadline && !explicitProgressTitle && !hasRetirableNativeTasks && !narrationUpdate.delta) return false;
|
|
1242
|
+
if (!useNativeProgressStreaming || delivery.streamFailed || nativeUpdatesStopped) return false;
|
|
1446
1243
|
if (!await nativeTransport.waitForStart()) return false;
|
|
1447
1244
|
const reconciled = reconcileSlackNativeTaskChunks({
|
|
1448
1245
|
previous: nativeStreamSnapshot,
|
|
1449
|
-
chunks:
|
|
1246
|
+
chunks: buildSlackProgressStreamChunks({
|
|
1247
|
+
title: resolveNativeProgressTitle(snapshot) ?? "Working",
|
|
1248
|
+
lines: resolveNativeProgressLines(snapshot),
|
|
1249
|
+
plan: snapshot.plan
|
|
1250
|
+
})
|
|
1450
1251
|
});
|
|
1451
1252
|
const chunks = reconciled.chunks;
|
|
1452
1253
|
if (!chunks?.length && !narrationUpdate.delta) return false;
|
|
@@ -1470,6 +1271,21 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1470
1271
|
return false;
|
|
1471
1272
|
}
|
|
1472
1273
|
};
|
|
1274
|
+
let nativeUpdatesStopped = false;
|
|
1275
|
+
const nativeUpdates = createDraftStreamLoop({
|
|
1276
|
+
throttleMs: 1e3,
|
|
1277
|
+
coalesceInFlight: true,
|
|
1278
|
+
emptyValue: false,
|
|
1279
|
+
isEmpty: (pending) => !pending,
|
|
1280
|
+
isStopped: () => nativeUpdatesStopped,
|
|
1281
|
+
sendOrEditStreamMessage: () => withNativeStreamOrder(updateNativeProgressStreamNow),
|
|
1282
|
+
onBackgroundFlushError: (err) => runtime.error?.(danger(`slack-stream: progress update failed: ${formatSlackError(err)}`))
|
|
1283
|
+
});
|
|
1284
|
+
const cancelNativeUpdates = async () => {
|
|
1285
|
+
nativeUpdatesStopped = true;
|
|
1286
|
+
nativeUpdates.stop();
|
|
1287
|
+
await nativeUpdates.waitForInFlight();
|
|
1288
|
+
};
|
|
1473
1289
|
const appendNativeNarration = (payload, kind) => withNativeStreamOrder(() => appendNativeNarrationNow(payload, kind));
|
|
1474
1290
|
const appendNativeNarrationNow = async (payload, kind) => {
|
|
1475
1291
|
if (isRenderedAsProgressTitle(payload.text)) return false;
|
|
@@ -1489,24 +1305,28 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1489
1305
|
return true;
|
|
1490
1306
|
};
|
|
1491
1307
|
const resetProgressTurnState = () => {
|
|
1492
|
-
progressWorkCounter.reset();
|
|
1493
1308
|
nativeNarrationRenderedText = "";
|
|
1494
1309
|
nativeNarrationSourceText = "";
|
|
1495
1310
|
};
|
|
1496
1311
|
const progressDraft = createChannelProgressDraftCompositor({
|
|
1312
|
+
presentation: isProgressMode ? "summary" : void 0,
|
|
1497
1313
|
entry: account.config,
|
|
1498
1314
|
mode: slackStreaming.mode,
|
|
1499
1315
|
active: progressDraftActive,
|
|
1500
1316
|
seed: progressSeed,
|
|
1501
1317
|
formatLine: formatSlackProgressDraftLine,
|
|
1502
1318
|
reasoningLinePrefix: "🧠 ",
|
|
1503
|
-
commentaryLinePrefix: "",
|
|
1504
1319
|
reasoningGate: previewToolProgressEnabled,
|
|
1505
|
-
commentaryItalics: true,
|
|
1506
|
-
buildProgressEventLine: (input, options) => input.event === "tool" || input.event === "item" || input.event === "command-output" ? buildChannelProgressDraftLineForEntry(account.config, input, options) : buildChannelProgressDraftLine(input, options),
|
|
1507
1320
|
updateOnLineChange: useNativeProgressStreaming || useDraftProgressCard,
|
|
1508
1321
|
update: async (previewText, options) => {
|
|
1509
|
-
if (useNativeProgressStreaming)
|
|
1322
|
+
if (useNativeProgressStreaming) {
|
|
1323
|
+
const priorSnapshot = nativeStreamSnapshot;
|
|
1324
|
+
const priorNarration = nativeNarrationRenderedText;
|
|
1325
|
+
nativeUpdates.update(true);
|
|
1326
|
+
if (options?.flush) await nativeUpdates.flush();
|
|
1327
|
+
else await nativeUpdates.waitForInFlight();
|
|
1328
|
+
return priorSnapshot !== nativeStreamSnapshot || priorNarration !== nativeNarrationRenderedText;
|
|
1329
|
+
}
|
|
1510
1330
|
if (!draftStream) return false;
|
|
1511
1331
|
const snapshot = progressDraft.getSnapshot();
|
|
1512
1332
|
progressCard.setFallbackText(previewText);
|
|
@@ -1519,7 +1339,11 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1519
1339
|
}
|
|
1520
1340
|
});
|
|
1521
1341
|
const commentaryProgressEnabled = progressDraft.commentaryProgressEnabled;
|
|
1522
|
-
const deliverNativeFinal = (payload, kind) =>
|
|
1342
|
+
const deliverNativeFinal = async (payload, kind) => {
|
|
1343
|
+
progressDraft.markFinalReplyStarted();
|
|
1344
|
+
await cancelNativeUpdates();
|
|
1345
|
+
await withNativeStreamOrder(() => deliverNativeFinalNow(payload, kind));
|
|
1346
|
+
};
|
|
1523
1347
|
const deliverNativeFinalNow = async (payload, kind) => {
|
|
1524
1348
|
progressDraft.markFinalReplyStarted();
|
|
1525
1349
|
const streamReady = await nativeTransport.waitForStart();
|
|
@@ -1544,20 +1368,23 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1544
1368
|
const snapshot = progressDraft.getSnapshot();
|
|
1545
1369
|
const lines = resolveNativeProgressLines(snapshot);
|
|
1546
1370
|
const sessionUrl = progressCard.resolveSessionUrl();
|
|
1371
|
+
const narrationUpdate = resolveNarrationUpdate(resolveNativeProgressNarration(snapshot));
|
|
1547
1372
|
const hasRetirableNativeTasks = [...nativeStreamSnapshot.tasks.values()].some((task) => task.status !== "complete" && task.status !== "error");
|
|
1548
|
-
if (lines.length === 0 && !snapshot.plan?.length && !hasRetirableNativeTasks && !
|
|
1549
|
-
|
|
1373
|
+
if (lines.length === 0 && !snapshot.plan?.length && !hasRetirableNativeTasks && !narrationUpdate.delta && !sessionUrl) return;
|
|
1374
|
+
const completion = reconcileSlackNativeTaskChunks({
|
|
1550
1375
|
previous: nativeStreamSnapshot,
|
|
1551
|
-
chunks:
|
|
1376
|
+
chunks: buildSlackProgressStreamChunks({
|
|
1552
1377
|
title: resolveNativeProgressTitle(snapshot) ?? (lines.length === 0 && !snapshot.plan?.length ? "Working" : void 0),
|
|
1553
1378
|
lines,
|
|
1554
|
-
plan:
|
|
1555
|
-
maxLineChars: progressDraftMaxLineChars,
|
|
1379
|
+
plan: snapshot.plan,
|
|
1556
1380
|
finalInProgressStatus,
|
|
1557
|
-
diffStat: snapshot.diffStat,
|
|
1558
1381
|
sessionUrl
|
|
1559
1382
|
})
|
|
1560
1383
|
}).chunks;
|
|
1384
|
+
return narrationUpdate.delta ? [{
|
|
1385
|
+
type: "markdown_text",
|
|
1386
|
+
text: narrationUpdate.delta
|
|
1387
|
+
}, ...completion ?? []] : completion;
|
|
1561
1388
|
};
|
|
1562
1389
|
const finishNativeProgressTurn = async (completionChunks) => {
|
|
1563
1390
|
if (delivery.nativeProgressStreamStartPromise) await delivery.nativeProgressStreamStartPromise.catch(() => null);
|
|
@@ -1660,6 +1487,10 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1660
1487
|
progressDraft.reset();
|
|
1661
1488
|
};
|
|
1662
1489
|
const beginNewProgressTurn = async (options) => {
|
|
1490
|
+
if (useNativeProgressStreaming) {
|
|
1491
|
+
if (!nativeUpdatesStopped && options?.force !== true) return false;
|
|
1492
|
+
await cancelNativeUpdates();
|
|
1493
|
+
}
|
|
1663
1494
|
const priorSnapshot = progressDraft.getSnapshot();
|
|
1664
1495
|
const priorFallbackText = progressCard.resolveText(priorSnapshot);
|
|
1665
1496
|
const completionChunks = useNativeProgressStreaming && !nativeProgressCompletionSent ? buildNativeProgressCompletionChunks(nativeProgressTerminalStatus) : void 0;
|
|
@@ -1674,6 +1505,8 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1674
1505
|
nativeStreamSnapshot = EMPTY_SLACK_NATIVE_STREAM_SNAPSHOT;
|
|
1675
1506
|
nativeProgressCompletionSent = false;
|
|
1676
1507
|
nativeProgressTerminalStatus = "complete";
|
|
1508
|
+
nativeUpdatesStopped = false;
|
|
1509
|
+
nativeUpdates.resetThrottleWindow();
|
|
1677
1510
|
progressCard.reset();
|
|
1678
1511
|
resetPreviewDeliveryState();
|
|
1679
1512
|
delivery.resetDeliveryTracker();
|
|
@@ -1697,7 +1530,14 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1697
1530
|
resetDraftDeliveryState();
|
|
1698
1531
|
resetDraftProgressState();
|
|
1699
1532
|
};
|
|
1700
|
-
const onQueuedFollowupSettled = !useDraftProgressCard ? void 0 : async () => {
|
|
1533
|
+
const onQueuedFollowupSettled = !useDraftProgressCard && !useNativeProgressStreaming ? void 0 : async () => {
|
|
1534
|
+
if (useNativeProgressStreaming) {
|
|
1535
|
+
progressDraft.markFinalReplyStarted();
|
|
1536
|
+
await cancelNativeUpdates();
|
|
1537
|
+
await finishNativeProgressTurn(nativeProgressCompletionSent ? void 0 : buildNativeProgressCompletionChunks(nativeProgressTerminalStatus));
|
|
1538
|
+
progressDraft.markFinalReplyDelivered();
|
|
1539
|
+
return;
|
|
1540
|
+
}
|
|
1701
1541
|
if (!progressCard.hasTerminalized) await draftStream?.clear();
|
|
1702
1542
|
await dropDetachedProgressCards();
|
|
1703
1543
|
};
|
|
@@ -1711,7 +1551,10 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1711
1551
|
suppressDefaultToolProgressMessages,
|
|
1712
1552
|
progressDraft,
|
|
1713
1553
|
commentaryProgressEnabled,
|
|
1714
|
-
|
|
1554
|
+
async cancel() {
|
|
1555
|
+
progressDraft.cancel();
|
|
1556
|
+
await cancelNativeUpdates();
|
|
1557
|
+
},
|
|
1715
1558
|
get nativeProgressCompletionSent() {
|
|
1716
1559
|
return nativeProgressCompletionSent;
|
|
1717
1560
|
},
|
|
@@ -1816,24 +1659,17 @@ async function createSlackDispatchSetup(prepared) {
|
|
|
1816
1659
|
await reactSlackMessage(message.channel, reactionMessageTs ?? "", emoji, {
|
|
1817
1660
|
token: ctx.botToken,
|
|
1818
1661
|
client: slackClient
|
|
1819
|
-
}).catch((err) => {
|
|
1820
|
-
if (formatErrorMessage(err).includes("already_reacted")) return;
|
|
1821
|
-
throw err;
|
|
1822
1662
|
});
|
|
1823
1663
|
},
|
|
1824
1664
|
removeReaction: async (emoji) => {
|
|
1825
1665
|
await removeSlackReaction(message.channel, reactionMessageTs ?? "", emoji, {
|
|
1826
1666
|
token: ctx.botToken,
|
|
1827
1667
|
client: slackClient
|
|
1828
|
-
}).catch((err) => {
|
|
1829
|
-
if (formatErrorMessage(err).includes("no_reaction")) return;
|
|
1830
|
-
throw err;
|
|
1831
1668
|
});
|
|
1832
1669
|
}
|
|
1833
1670
|
},
|
|
1834
1671
|
initialEmoji: prepared.ackReactionValue || "eyes",
|
|
1835
|
-
|
|
1836
|
-
timing: DEFAULT_TIMING,
|
|
1672
|
+
presentation: "acknowledgement",
|
|
1837
1673
|
onError: (err) => {
|
|
1838
1674
|
logAckFailure({
|
|
1839
1675
|
log: logVerbose,
|
|
@@ -2634,7 +2470,6 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2634
2470
|
} : void 0,
|
|
2635
2471
|
onToolStart: async (payload) => {
|
|
2636
2472
|
if (statusReactionsEnabled) await statusReactions.setTool(payload.name);
|
|
2637
|
-
if (payload.phase === "start") progress.progressWorkCounter.noteToolCall(payload.name);
|
|
2638
2473
|
return await progress.progressDraft.pushToolEvent(payload);
|
|
2639
2474
|
},
|
|
2640
2475
|
onItemEvent: async (payload) => {
|
|
@@ -2676,7 +2511,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2676
2511
|
} catch (err) {
|
|
2677
2512
|
dispatchError = err;
|
|
2678
2513
|
} finally {
|
|
2679
|
-
progress.
|
|
2514
|
+
await progress.cancel();
|
|
2680
2515
|
if (!progress.useDraftProgressCard) await draftStream?.discardPending();
|
|
2681
2516
|
}
|
|
2682
2517
|
let streamFallbackDelivered = false;
|
|
@@ -2709,13 +2544,15 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2709
2544
|
if (pendingFailureNotice && anyReplyDelivered) recordSlackThreadFailureNotice(pendingFailureNotice);
|
|
2710
2545
|
if (dispatchError || agentRunFailed) await progress.finalizeDraftProgressCard("error");
|
|
2711
2546
|
await progress.dropDetachedProgressCards();
|
|
2712
|
-
if (statusReactionsEnabled)
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2547
|
+
if (statusReactionsEnabled) {
|
|
2548
|
+
if (dispatchError || agentRunFailed) {
|
|
2549
|
+
await statusReactions.setError();
|
|
2550
|
+
statusReactions.restoreInitial();
|
|
2551
|
+
} else if (anyReplyDelivered) {
|
|
2552
|
+
await statusReactions.setDone();
|
|
2553
|
+
statusReactions.restoreInitial();
|
|
2554
|
+
} else await statusReactions.restoreInitial();
|
|
2555
|
+
}
|
|
2719
2556
|
const participationThreadTs = delivery.usedReplyThreadTs ?? statusThreadTs;
|
|
2720
2557
|
if (anyReplyDelivered && participationThreadTs) recordSlackThreadParticipation(account.accountId, message.channel, participationThreadTs, {
|
|
2721
2558
|
agentId: route.agentId,
|
|
@@ -2774,7 +2611,7 @@ function normalizeSlackAppContextEntities(value) {
|
|
|
2774
2611
|
//#endregion
|
|
2775
2612
|
//#region extensions/slack/src/monitor/thread.ts
|
|
2776
2613
|
const THREAD_STARTER_CACHE = /* @__PURE__ */ new Map();
|
|
2777
|
-
const THREAD_STARTER_CACHE_TTL_MS =
|
|
2614
|
+
const THREAD_STARTER_CACHE_TTL_MS = 216e5;
|
|
2778
2615
|
const THREAD_STARTER_CACHE_MAX = 2e3;
|
|
2779
2616
|
function evictThreadStarterCache() {
|
|
2780
2617
|
const now = asDateTimestampMs(Date.now());
|
|
@@ -2970,7 +2807,7 @@ const SLACK_MENTION_RESOLUTION_CONCURRENCY = 4;
|
|
|
2970
2807
|
const SLACK_MENTION_RESOLUTION_MAX_LOOKUPS_PER_MESSAGE = 20;
|
|
2971
2808
|
const SLACK_USER_MENTION_RE$1 = /<@([A-Z0-9]+)(?:\|[^>]+)?>/gi;
|
|
2972
2809
|
const MAX_SLACK_UNAVAILABLE_FILE_TEXT_CHARS = 2e3;
|
|
2973
|
-
const loadSlackMediaModule$1 = createLazyRuntimeModule(() => import("./actions-
|
|
2810
|
+
const loadSlackMediaModule$1 = createLazyRuntimeModule(() => import("./actions-BOxiu2Vy.js").then((n) => n._));
|
|
2974
2811
|
function formatSlackUnavailableMedia(params) {
|
|
2975
2812
|
let fileReferences = params.files?.map((file) => `${formatSlackFileReference(file)} unavailable (${file.reason})`).join(", ");
|
|
2976
2813
|
if (fileReferences && fileReferences.length > MAX_SLACK_UNAVAILABLE_FILE_TEXT_CHARS) fileReferences = `${truncateUtf16Safe(fileReferences, MAX_SLACK_UNAVAILABLE_FILE_TEXT_CHARS)}; … (file references truncated)`;
|
|
@@ -3060,7 +2897,8 @@ async function resolveSlackMessageContent(params) {
|
|
|
3060
2897
|
if (skippedLookups > 0) logVerbose(`slack: skipping ${skippedLookups} mention lookup(s) beyond per-message cap (${SLACK_MENTION_RESOLUTION_MAX_LOOKUPS_PER_MESSAGE})`);
|
|
3061
2898
|
const { results } = await runTasksWithConcurrency({
|
|
3062
2899
|
tasks: lookupIds.map((userId) => async () => {
|
|
3063
|
-
const
|
|
2900
|
+
const user = await resolveUserName(userId);
|
|
2901
|
+
const renderedName = normalizeOptionalString(user?.name);
|
|
3064
2902
|
return {
|
|
3065
2903
|
userId,
|
|
3066
2904
|
rendered: renderedName ? `<@${userId}> (${renderedName})` : null
|
|
@@ -3163,7 +3001,8 @@ async function resolveSlackDmHistoryContext(params) {
|
|
|
3163
3001
|
//#endregion
|
|
3164
3002
|
//#region extensions/slack/src/monitor/message-handler/prepare-routing.ts
|
|
3165
3003
|
function resolveSlackBaseConversationId(params) {
|
|
3166
|
-
|
|
3004
|
+
const raw = params.isDirectMessage ? `user:${params.message.user ?? "unknown"}` : params.message.channel;
|
|
3005
|
+
return qualifySlackConversationId(raw, params.eventScope);
|
|
3167
3006
|
}
|
|
3168
3007
|
function resolveSlackInitialAgentRoute(params) {
|
|
3169
3008
|
const route = resolveAgentRoute({
|
|
@@ -3314,7 +3153,7 @@ function formatSlackThreadLabelSnippet(text) {
|
|
|
3314
3153
|
}
|
|
3315
3154
|
//#endregion
|
|
3316
3155
|
//#region extensions/slack/src/monitor/message-handler/prepare-thread-context.ts
|
|
3317
|
-
const loadSlackMediaModule = createLazyRuntimeModule(() => import("./actions-
|
|
3156
|
+
const loadSlackMediaModule = createLazyRuntimeModule(() => import("./actions-BOxiu2Vy.js").then((n) => n._));
|
|
3318
3157
|
const SLACK_THREAD_CONTEXT_USER_LOOKUP_CONCURRENCY = 4;
|
|
3319
3158
|
function resolveSlackThreadSessionFreshness(params) {
|
|
3320
3159
|
return params.ctx.channelRuntime?.session?.resolveEntryResetFreshness?.({
|
|
@@ -3440,7 +3279,10 @@ async function resolveSlackThreadContextData(params) {
|
|
|
3440
3279
|
unavailableMediaCount: attachmentContent.unavailableMediaCount,
|
|
3441
3280
|
prependUnavailable: true
|
|
3442
3281
|
});
|
|
3443
|
-
if (threadStarterMedia)
|
|
3282
|
+
if (threadStarterMedia) {
|
|
3283
|
+
const starterPlaceholders = threadStarterMedia.map((item) => item.placeholder).join(", ");
|
|
3284
|
+
logVerbose(`slack: hydrated thread starter file ${starterPlaceholders} from root message`);
|
|
3285
|
+
}
|
|
3444
3286
|
}
|
|
3445
3287
|
} else threadLabel = `Slack thread ${params.roomLabel}`;
|
|
3446
3288
|
const includeBotStarterAsRootContext = shouldIncludeBotThreadStarterContext({
|
|
@@ -3559,7 +3401,7 @@ async function resolveSlackThreadContextData(params) {
|
|
|
3559
3401
|
//#endregion
|
|
3560
3402
|
//#region extensions/slack/src/monitor/message-handler/subteam-mentions.ts
|
|
3561
3403
|
const SUBTEAM_MENTION_RE = /<!subteam\^([A-Z0-9]+)(?:\|[^>]*)?>/gi;
|
|
3562
|
-
const SUBTEAM_MEMBER_CACHE_TTL_MS =
|
|
3404
|
+
const SUBTEAM_MEMBER_CACHE_TTL_MS = 3e5;
|
|
3563
3405
|
const subteamMemberCache = /* @__PURE__ */ new WeakMap();
|
|
3564
3406
|
function normalizeSlackId(value) {
|
|
3565
3407
|
return typeof value === "string" && value.trim() ? value.trim().toUpperCase() : void 0;
|
|
@@ -3630,7 +3472,7 @@ const SLACK_USER_MENTION_RE = /<@([^>|]+)(?:\|[^>]+)?>/g;
|
|
|
3630
3472
|
const SLACK_SUBTEAM_MENTION_RE = /<!subteam\^([^>|]+)(?:\|[^>]+)?>/g;
|
|
3631
3473
|
const SLACK_SUBTEAM_MENTION_MARKER = "<!subteam^";
|
|
3632
3474
|
const SLACK_HISTORY_MEDIA_MAX_ATTACHMENTS = 4;
|
|
3633
|
-
const SLACK_HISTORY_MEDIA_MAX_BYTES =
|
|
3475
|
+
const SLACK_HISTORY_MEDIA_MAX_BYTES = 10485760;
|
|
3634
3476
|
const SLACK_HISTORY_MEDIA_IDLE_TIMEOUT_MS = 1e3;
|
|
3635
3477
|
const SLACK_HISTORY_MEDIA_TOTAL_TIMEOUT_MS = 3e3;
|
|
3636
3478
|
const SLACK_CHANNEL_ACCESS_DOCS_URL = "https://docs.openclaw.ai/channels/slack#access-control-and-routing";
|
|
@@ -3764,7 +3606,7 @@ function buildSlackHistoryMediaCandidateMessage(message) {
|
|
|
3764
3606
|
async function resolveSlackHistoryMediaForPendingRecord(params) {
|
|
3765
3607
|
const mediaMessage = buildSlackHistoryMediaCandidateMessage(params.message);
|
|
3766
3608
|
if (!mediaMessage) return [];
|
|
3767
|
-
|
|
3609
|
+
const content = await resolveSlackMessageContent({
|
|
3768
3610
|
message: mediaMessage,
|
|
3769
3611
|
isThreadReply: params.isThreadReply,
|
|
3770
3612
|
threadStarter: params.threadStarter,
|
|
@@ -3774,7 +3616,8 @@ async function resolveSlackHistoryMediaForPendingRecord(params) {
|
|
|
3774
3616
|
mediaMaxBytes: Math.min(params.ctx.mediaMaxBytes, SLACK_HISTORY_MEDIA_MAX_BYTES),
|
|
3775
3617
|
mediaReadIdleTimeoutMs: SLACK_HISTORY_MEDIA_IDLE_TIMEOUT_MS,
|
|
3776
3618
|
mediaTotalTimeoutMs: SLACK_HISTORY_MEDIA_TOTAL_TIMEOUT_MS
|
|
3777
|
-
})
|
|
3619
|
+
});
|
|
3620
|
+
return await toInboundMediaFactsWithMetadata(content?.effectiveDirectMedia, {
|
|
3778
3621
|
kind: "image",
|
|
3779
3622
|
messageId: params.message.ts
|
|
3780
3623
|
});
|
|
@@ -3897,7 +3740,8 @@ async function authorizeSlackInboundMessage(params) {
|
|
|
3897
3740
|
if (conversation.isRoom && ctx.groupPolicy === "allowlist" && params.explicitBotMention && !isBotMessage && message.user) {
|
|
3898
3741
|
let subject = "This OpenClaw bot";
|
|
3899
3742
|
if (ctx.botUserId) try {
|
|
3900
|
-
const
|
|
3743
|
+
const botIdentity = await ctx.resolveUserName(ctx.botUserId, params.eventScope);
|
|
3744
|
+
const botName = normalizeOptionalString(botIdentity?.name);
|
|
3901
3745
|
if (botName) subject = escapeSlackMrkdwn(botName);
|
|
3902
3746
|
} catch (error) {
|
|
3903
3747
|
logVerbose(`slack allowlist denial bot-name lookup failed: ${formatSlackError(error)}`);
|
|
@@ -3990,7 +3834,8 @@ async function prepareSlackMessage(params) {
|
|
|
3990
3834
|
const resolveSenderName = async () => {
|
|
3991
3835
|
if (resolvedSenderName) return resolvedSenderName;
|
|
3992
3836
|
if (message.user) {
|
|
3993
|
-
const
|
|
3837
|
+
const sender = await ctx.resolveUserName(message.user, opts.eventScope);
|
|
3838
|
+
const normalized = normalizeOptionalString(sender?.name);
|
|
3994
3839
|
if (normalized) {
|
|
3995
3840
|
resolvedSenderName = normalized;
|
|
3996
3841
|
return resolvedSenderName;
|