@openclaw/slack 2026.8.1-beta.2 → 2026.8.1
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-sUohAxZr.js +33 -0
- package/dist/account-inspect-CN2hBsim.js +87 -0
- package/dist/account-inspect-api.js +1 -1
- package/dist/{accounts-CK4AVI2_.js → accounts-Dm_H77gH.js} +12 -11
- package/dist/{accounts.runtime-Cb7QwWBz.js → accounts.runtime-DRuEK6mL.js} +1 -1
- package/dist/{action-runtime-BkGe7ny_.js → action-runtime-044ldvNL.js} +80 -79
- package/dist/action-runtime.runtime-BL3KzX13.js +2 -0
- package/dist/{actions-BTDXwwE3.js → actions-BI7JkfVm.js} +273 -263
- package/dist/api.js +14 -14
- package/dist/{approval-handler.runtime-CJaNzAq2.js → approval-handler.runtime-DYv0UIZS.js} +53 -174
- package/dist/{channel-D_tovcUL.js → channel-1vIJOzPx.js} +134 -160
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-type-B9MSdoGN.js → channel-type-DlFSKeIZ.js} +3 -7
- package/dist/{channel.setup-Bch9dYmA.js → channel.setup-ofDi3_Pu.js} +34 -49
- package/dist/{config-schema-xto5jFIx.js → config-schema-BVIMyiDN.js} +42 -19
- package/dist/configured-state.js +34 -0
- package/dist/conversation-binding-route-DFVLUdYF.js +115 -0
- package/dist/{directory-config-CNBz8lJa.js → directory-config-DqfQ42OV.js} +1 -1
- package/dist/directory-contract-api.js +1 -1
- package/dist/{directory-live-CFKUtW9E.js → directory-live-BPaNHjmP.js} +2 -2
- package/dist/{group-policy-c4RP9bjc.js → group-policy-BdwszjYn.js} +625 -773
- package/dist/{message-tool-api-BykQB4AU.js → message-tool-api-CJ0kjcg5.js} +23 -5
- package/dist/message-tool-api.js +1 -1
- package/dist/{monitor-1nF1NtqT.js → monitor-Dq5Cmrvp.js} +3 -3
- package/dist/{outbound-adapter-S81tsswN.js → outbound-adapter-DYaI8ThX.js} +101 -66
- package/dist/{pipeline.runtime-BvYsM5JO.js → pipeline.runtime-Bd22U0ga.js} +494 -474
- package/dist/{policy-TapwbeaT.js → policy-CtQVbde1.js} +2 -1
- package/dist/{probe-HoEg_WxB.js → probe-0usmAb0i.js} +209 -22
- package/dist/{provider-CDNvBXUi.js → provider-CN_8hFv2.js} +296 -178
- package/dist/{relay-source-C9leF11u.js → relay-source-BNGpsdwV.js} +1 -1
- package/dist/{replies-CeOfv82I.js → replies-BSiRQOJ1.js} +48 -27
- package/dist/{resolve-channels-CNPrxaXY.js → resolve-channels-Czheznc8.js} +1 -1
- package/dist/{resolve-users-Dzomuwnr.js → resolve-users-BAOlNimr.js} +1 -1
- package/dist/runtime-api.js +11 -11
- package/dist/{scopes-cYXKkrRD.js → scopes-COSlmhnH.js} +1 -1
- package/dist/security-contract-api.js +1 -1
- package/dist/{send-Nor0iBwY.js → send-DS9ICrBI.js} +88 -100
- package/dist/send-results-eeOu_HYm.js +23 -0
- package/dist/{send.runtime-BmgNe6S9.js → send.runtime-D_Bb6IuH.js} +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-CbX1-Knh.js → setup-surface-BGnd2pSe.js} +6 -6
- package/dist/{shared-zdT5AMp-.js → shared-D5B-5hBg.js} +35 -9
- package/dist/{slash-dispatch.runtime-Bnr9GR1S.js → slash-dispatch.runtime-CilDmI0c.js} +2 -2
- package/node_modules/@slack/bolt/node_modules/@types/node/README.md +1 -1
- package/node_modules/@slack/bolt/node_modules/@types/node/child_process.d.ts +0 -1
- package/node_modules/@slack/bolt/node_modules/@types/node/crypto.d.ts +6 -6
- package/node_modules/@slack/bolt/node_modules/@types/node/dns/promises.d.ts +5 -5
- package/node_modules/@slack/bolt/node_modules/@types/node/dns.d.ts +5 -5
- package/node_modules/@slack/bolt/node_modules/@types/node/fs.d.ts +7 -0
- package/node_modules/@slack/bolt/node_modules/@types/node/http.d.ts +30 -0
- package/node_modules/@slack/bolt/node_modules/@types/node/http2.d.ts +4 -4
- package/node_modules/@slack/bolt/node_modules/@types/node/os.d.ts +30 -30
- package/node_modules/@slack/bolt/node_modules/@types/node/package.json +2 -2
- package/node_modules/@slack/bolt/node_modules/@types/node/perf_hooks.d.ts +2 -1
- package/node_modules/@slack/bolt/node_modules/@types/node/process.d.ts +42 -43
- package/node_modules/@slack/bolt/node_modules/@types/node/quic.d.ts +1049 -84
- package/node_modules/@slack/bolt/node_modules/@types/node/sqlite.d.ts +14 -1
- package/node_modules/@slack/bolt/node_modules/@types/node/stream/iter.d.ts +3 -2
- package/node_modules/@slack/bolt/node_modules/@types/node/test.d.ts +61 -0
- package/node_modules/@slack/bolt/node_modules/@types/node/v8.d.ts +20 -23
- package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/README.md +2 -0
- package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/dist/index.d.ts +20 -0
- package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/dist/index.js +20 -14
- package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/dist/index.js.map +1 -1
- package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/package.json +1 -1
- package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/README.md +2 -0
- package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.d.ts +20 -0
- package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.js +20 -14
- package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.js.map +1 -1
- package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/package.json +1 -1
- package/node_modules/@slack/socket-mode/node_modules/@types/node/README.md +1 -1
- package/node_modules/@slack/socket-mode/node_modules/@types/node/child_process.d.ts +0 -1
- package/node_modules/@slack/socket-mode/node_modules/@types/node/crypto.d.ts +6 -6
- package/node_modules/@slack/socket-mode/node_modules/@types/node/dns/promises.d.ts +5 -5
- package/node_modules/@slack/socket-mode/node_modules/@types/node/dns.d.ts +5 -5
- package/node_modules/@slack/socket-mode/node_modules/@types/node/fs.d.ts +7 -0
- package/node_modules/@slack/socket-mode/node_modules/@types/node/http.d.ts +30 -0
- package/node_modules/@slack/socket-mode/node_modules/@types/node/http2.d.ts +4 -4
- package/node_modules/@slack/socket-mode/node_modules/@types/node/os.d.ts +30 -30
- package/node_modules/@slack/socket-mode/node_modules/@types/node/package.json +2 -2
- package/node_modules/@slack/socket-mode/node_modules/@types/node/perf_hooks.d.ts +2 -1
- package/node_modules/@slack/socket-mode/node_modules/@types/node/process.d.ts +42 -43
- package/node_modules/@slack/socket-mode/node_modules/@types/node/quic.d.ts +1049 -84
- package/node_modules/@slack/socket-mode/node_modules/@types/node/sqlite.d.ts +14 -1
- package/node_modules/@slack/socket-mode/node_modules/@types/node/stream/iter.d.ts +3 -2
- package/node_modules/@slack/socket-mode/node_modules/@types/node/test.d.ts +61 -0
- package/node_modules/@slack/socket-mode/node_modules/@types/node/v8.d.ts +20 -23
- package/node_modules/@slack/web-api/node_modules/@types/node/README.md +1 -1
- package/node_modules/@slack/web-api/node_modules/@types/node/child_process.d.ts +0 -1
- package/node_modules/@slack/web-api/node_modules/@types/node/crypto.d.ts +6 -6
- package/node_modules/@slack/web-api/node_modules/@types/node/dns/promises.d.ts +5 -5
- package/node_modules/@slack/web-api/node_modules/@types/node/dns.d.ts +5 -5
- package/node_modules/@slack/web-api/node_modules/@types/node/fs.d.ts +7 -0
- package/node_modules/@slack/web-api/node_modules/@types/node/http.d.ts +30 -0
- package/node_modules/@slack/web-api/node_modules/@types/node/http2.d.ts +4 -4
- package/node_modules/@slack/web-api/node_modules/@types/node/os.d.ts +30 -30
- package/node_modules/@slack/web-api/node_modules/@types/node/package.json +2 -2
- package/node_modules/@slack/web-api/node_modules/@types/node/perf_hooks.d.ts +2 -1
- package/node_modules/@slack/web-api/node_modules/@types/node/process.d.ts +42 -43
- package/node_modules/@slack/web-api/node_modules/@types/node/quic.d.ts +1049 -84
- package/node_modules/@slack/web-api/node_modules/@types/node/sqlite.d.ts +14 -1
- package/node_modules/@slack/web-api/node_modules/@types/node/stream/iter.d.ts +3 -2
- package/node_modules/@slack/web-api/node_modules/@types/node/test.d.ts +61 -0
- package/node_modules/@slack/web-api/node_modules/@types/node/v8.d.ts +20 -23
- package/node_modules/typebox/build/format/date.d.mts +1 -1
- package/node_modules/typebox/build/format/date.mjs +1 -1
- package/node_modules/typebox/build/format/date_time.d.mts +2 -2
- package/node_modules/typebox/build/format/date_time.mjs +3 -3
- package/node_modules/typebox/build/format/email.d.mts +1 -1
- package/node_modules/typebox/build/format/email.mjs +2 -2
- package/node_modules/typebox/build/format/hostname.mjs +2 -10
- package/node_modules/typebox/build/format/idn_email.d.mts +1 -1
- package/node_modules/typebox/build/format/idn_email.mjs +3 -3
- package/node_modules/typebox/build/format/idn_hostname.d.mts +1 -0
- package/node_modules/typebox/build/format/idn_hostname.mjs +3 -11
- package/node_modules/typebox/build/format/idna/format/bidi.d.mts +3 -0
- package/node_modules/typebox/build/format/idna/format/bidi.mjs +98 -0
- package/node_modules/typebox/build/format/idna/format/puny.d.mts +3 -0
- package/node_modules/typebox/build/format/idna/format/puny.mjs +144 -0
- package/node_modules/typebox/build/format/idna/hostname.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/hostname.mjs +16 -0
- package/node_modules/typebox/build/format/idna/idn-hostname.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/idn-hostname.mjs +23 -0
- package/node_modules/typebox/build/format/idna/index.d.mts +2 -0
- package/node_modules/typebox/build/format/idna/index.mjs +2 -0
- package/node_modules/typebox/build/format/idna/label/ascii.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/label/ascii.mjs +9 -0
- package/node_modules/typebox/build/format/idna/label/puny.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/label/puny.mjs +28 -0
- package/node_modules/typebox/build/format/idna/label/unicode.d.mts +1 -0
- package/node_modules/typebox/build/format/idna/label/unicode.mjs +106 -0
- package/node_modules/typebox/build/format/idna/pattern/pattern.d.mts +30 -0
- package/node_modules/typebox/build/format/idna/pattern/pattern.mjs +70 -0
- package/node_modules/typebox/build/format/ipv4.d.mts +0 -1
- package/node_modules/typebox/build/format/ipv4.mjs +2 -32
- package/node_modules/typebox/build/format/ipv6.mjs +2 -61
- package/node_modules/typebox/build/format/iri.d.mts +2 -2
- package/node_modules/typebox/build/format/iri.mjs +26 -8
- package/node_modules/typebox/build/format/iri_reference.d.mts +2 -2
- package/node_modules/typebox/build/format/iri_reference.mjs +9 -55
- package/node_modules/typebox/build/format/regex.d.mts +1 -2
- package/node_modules/typebox/build/format/regex.mjs +2 -6
- package/node_modules/typebox/build/format/time.d.mts +2 -2
- package/node_modules/typebox/build/format/time.mjs +19 -14
- package/node_modules/typebox/build/format/uri.d.mts +1 -1
- package/node_modules/typebox/build/format/uri.mjs +3 -130
- package/node_modules/typebox/build/format/uri_reference.d.mts +1 -1
- package/node_modules/typebox/build/format/uri_reference.mjs +2 -3
- package/node_modules/typebox/build/format/uri_template.d.mts +2 -3
- package/node_modules/typebox/build/format/uri_template.mjs +4 -5
- package/node_modules/typebox/build/format/url.d.mts +3 -3
- package/node_modules/typebox/build/format/url.mjs +4 -5
- package/node_modules/typebox/build/guard/emit.d.mts +3 -1
- package/node_modules/typebox/build/guard/emit.mjs +12 -5
- package/node_modules/typebox/build/guard/guard.d.mts +8 -2
- package/node_modules/typebox/build/guard/guard.mjs +25 -4
- package/node_modules/typebox/build/guard/string.d.mts +2 -2
- package/node_modules/typebox/build/guard/string.mjs +7 -7
- package/node_modules/typebox/build/schema/engine/_context.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/_functions.mjs +1 -2
- package/node_modules/typebox/build/schema/engine/_regexp.d.mts +2 -0
- package/node_modules/typebox/build/schema/engine/_regexp.mjs +4 -0
- package/node_modules/typebox/build/schema/engine/_stack.mjs +12 -13
- package/node_modules/typebox/build/schema/engine/additionalItems.mjs +17 -7
- package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +4 -3
- package/node_modules/typebox/build/schema/engine/contains.mjs +18 -6
- package/node_modules/typebox/build/schema/engine/enum.mjs +1 -1
- package/node_modules/typebox/build/schema/engine/items.mjs +26 -6
- package/node_modules/typebox/build/schema/engine/maxContains.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/minContains.mjs +14 -4
- package/node_modules/typebox/build/schema/engine/not.mjs +4 -2
- package/node_modules/typebox/build/schema/engine/oneOf.mjs +7 -6
- package/node_modules/typebox/build/schema/engine/pattern.mjs +3 -2
- package/node_modules/typebox/build/schema/engine/patternProperties.mjs +4 -3
- package/node_modules/typebox/build/schema/engine/ref.mjs +1 -7
- package/node_modules/typebox/build/schema/engine/schema.mjs +13 -4
- package/node_modules/typebox/build/schema/engine/type.mjs +1 -1
- package/node_modules/typebox/build/schema/resolve/resolve.d.mts +4 -1
- package/node_modules/typebox/build/schema/resolve/resolve.mjs +202 -1
- package/node_modules/typebox/build/schema/static/propertyNames.d.mts +5 -0
- package/node_modules/typebox/build/schema/static/propertyNames.mjs +3 -0
- package/node_modules/typebox/build/schema/static/schema.d.mts +3 -0
- package/node_modules/typebox/build/schema/types/index.d.mts +0 -2
- package/node_modules/typebox/build/schema/types/index.mjs +0 -2
- package/node_modules/typebox/build/system/memory/clone.mjs +14 -11
- package/node_modules/typebox/build/system/memory/discard.mjs +6 -5
- package/node_modules/typebox/build/system/settings/settings.d.mts +9 -0
- package/node_modules/typebox/build/system/settings/settings.mjs +2 -0
- package/node_modules/typebox/build/type/engine/call/distribute_arguments.d.mts +6 -1
- package/node_modules/typebox/build/type/engine/call/distribute_arguments.mjs +16 -3
- package/node_modules/typebox/build/type/engine/call/instantiate.mjs +34 -4
- package/node_modules/typebox/build/type/engine/evaluate/broaden.d.mts +5 -5
- package/node_modules/typebox/build/type/engine/evaluate/broaden.mjs +20 -26
- package/node_modules/typebox/build/type/engine/evaluate/compare.d.mts +6 -10
- package/node_modules/typebox/build/type/engine/evaluate/compare.mjs +9 -13
- package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +7 -4
- package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +12 -19
- package/node_modules/typebox/build/type/engine/evaluate/distribute.d.mts +4 -20
- package/node_modules/typebox/build/type/engine/evaluate/distribute.mjs +8 -20
- package/node_modules/typebox/build/type/engine/evaluate/evaluate.d.mts +4 -4
- package/node_modules/typebox/build/type/engine/evaluate/evaluate.mjs +11 -8
- package/node_modules/typebox/build/type/engine/evaluate/flatten.d.mts +1 -1
- package/node_modules/typebox/build/type/engine/evaluate/flatten.mjs +3 -4
- package/node_modules/typebox/build/type/engine/evaluate/narrow.d.mts +17 -2
- package/node_modules/typebox/build/type/engine/evaluate/narrow.mjs +26 -6
- package/node_modules/typebox/build/type/engine/exclude/operation.mjs +3 -4
- package/node_modules/typebox/build/type/engine/extract/operation.d.mts +1 -1
- package/node_modules/typebox/build/type/engine/extract/operation.mjs +3 -4
- package/node_modules/typebox/build/type/engine/priority/priority.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/priority/priority.mjs +3 -4
- package/node_modules/typebox/build/type/script/mapping.d.mts +32 -29
- package/node_modules/typebox/build/type/script/mapping.mjs +18 -25
- package/node_modules/typebox/build/type/script/parser.d.mts +19 -25
- package/node_modules/typebox/build/type/script/parser.mjs +27 -23
- package/node_modules/typebox/build/value/errors/errors.d.mts +2 -2
- package/node_modules/typebox/build/value/errors/errors.mjs +1 -1
- package/node_modules/typebox/package.json +27 -27
- package/node_modules/typebox/readme.md +79 -82
- package/node_modules/ws/lib/permessage-deflate.js +3 -1
- package/node_modules/ws/package.json +1 -1
- package/openclaw.plugin.json +57 -7
- package/package.json +9 -9
- package/dist/account-configured-BwfXBo_F.js +0 -14
- package/dist/account-inspect-Drw2gAiN.js +0 -89
- package/dist/account-reply-mode-DrUXogvO.js +0 -14
- package/dist/action-runtime.runtime-D9I6uc0Q.js +0 -2
- package/dist/actions.runtime-DLFyUkvg.js +0 -2
- package/dist/block-text-YtiNkqmx.js +0 -79
- package/dist/runtime-api-Cj9nxBNv.js +0 -10
- package/node_modules/p-map/index.d.ts +0 -155
- package/node_modules/p-map/index.js +0 -285
- package/node_modules/p-map/license +0 -9
- package/node_modules/p-map/package.json +0 -57
- package/node_modules/p-map/readme.md +0 -190
- package/node_modules/typebox/build/format/_idna.d.mts +0 -2
- package/node_modules/typebox/build/format/_idna.mjs +0 -246
- package/node_modules/typebox/build/format/_puny.d.mts +0 -1
- package/node_modules/typebox/build/format/_puny.mjs +0 -77
- package/node_modules/typebox/build/schema/resolve/ref.d.mts +0 -3
- package/node_modules/typebox/build/schema/resolve/ref.mjs +0 -146
- package/node_modules/typebox/build/schema/types/contentEncoding.d.mts +0 -9
- package/node_modules/typebox/build/schema/types/contentEncoding.mjs +0 -13
- package/node_modules/typebox/build/schema/types/contentMediaType.d.mts +0 -9
- package/node_modules/typebox/build/schema/types/contentMediaType.mjs +0 -13
- package/dist/{security-audit-DR097212.js → security-audit-B_yKr7MW.js} +1 -1
|
@@ -1,35 +1,37 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import "./
|
|
4
|
-
import {
|
|
5
|
-
import { r as formatSlackError } from "./probe-HoEg_WxB.js";
|
|
1
|
+
import { n as resolveSlackConversationBindingRoute, r as resolveSlackReplyToMode, t as normalizeSlackRouteBindingConfig } from "./conversation-binding-route-DFVLUdYF.js";
|
|
2
|
+
import { n as formatSlackTarget } from "./target-parsing-BnMD2ZqZ.js";
|
|
3
|
+
import { 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-BdwszjYn.js";
|
|
4
|
+
import { f as resolveSlackAllowListMatch, l as normalizeAllowListLower, o as formatSlackError, u as normalizeSlackAllowOwnerEntry } from "./probe-0usmAb0i.js";
|
|
6
5
|
import { n as resolveSlackStreamingMode, t as resolveSlackNativeStreaming } from "./streaming-compat-B-e0mqM0.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { c as
|
|
10
|
-
import {
|
|
11
|
-
import { n as
|
|
12
|
-
import { a as resolveDeliveredSlackReplyThreadTs, i as readSlackReplyBlocks, n as deliverReplies, o as resolveSlackThreadTs, s as emitSlackMessageSentHooks, t as createSlackReplyDeliveryPlan } from "./replies-CeOfv82I.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-BI7JkfVm.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-DS9ICrBI.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-CN_8hFv2.js";
|
|
9
|
+
import { n as resolveSlackChannelConfig } from "./policy-CtQVbde1.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-BSiRQOJ1.js";
|
|
13
11
|
import { asOptionalRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
14
12
|
import { resolveAgentRoute, resolveInboundLastRouteSessionKey, resolveThreadSessionKeys } from "openclaw/plugin-sdk/routing";
|
|
15
|
-
import { buildChannelProgressDraftLine, buildChannelProgressDraftLineForEntry, createChannelMessageReplyPipeline, createChannelProgressDraftCompositor,
|
|
13
|
+
import { buildChannelProgressDraftLine, buildChannelProgressDraftLineForEntry, createChannelMessageReplyPipeline, createChannelProgressDraftCompositor, createChannelProgressWorkCounter, createFinalizableDraftStreamControlsForState, defineFinalizableLivePreviewAdapter, deliverWithFinalizableLivePreviewAdapter, formatChannelProgressDraftText, formatPlanChecklistLines, isChannelProgressDraftWorkToolName, resolveAgentOutboundIdentity, resolveChannelMessageSourceReplyDeliveryMode, resolveChannelProgressDraftConfig, resolveChannelProgressDraftMaxLineChars, resolveChannelStreamingBlockEnabled, resolveChannelStreamingPreviewToolProgress, resolveChannelStreamingSuppressDefaultToolProgressMessages } from "openclaw/plugin-sdk/channel-outbound";
|
|
16
14
|
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
17
15
|
import { danger, logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
|
|
16
|
+
import { sanitizeAssistantVisibleText } from "openclaw/plugin-sdk/text-chunking";
|
|
17
|
+
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
18
|
+
import { buildTtsSupplementMediaPayload, getReplyPayloadTtsSupplement, isReplyPayloadNonTerminalToolErrorWarning, resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
|
|
18
19
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
19
20
|
import { createHash } from "node:crypto";
|
|
21
|
+
import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
|
|
22
|
+
import { ensureConfiguredBindingRouteReady } from "openclaw/plugin-sdk/conversation-runtime";
|
|
23
|
+
import { resolveChannelImplicitMentions } from "openclaw/plugin-sdk/channel-ingress-runtime";
|
|
20
24
|
import fs from "node:fs/promises";
|
|
25
|
+
import { runTasksWithConcurrency } from "openclaw/plugin-sdk/concurrency-runtime";
|
|
21
26
|
import { formatErrorMessage, toErrorObject } from "openclaw/plugin-sdk/error-runtime";
|
|
22
|
-
import { asDateTimestampMs, asFiniteNumberInRange, parseStrictFiniteNumber, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
|
|
23
|
-
import { buildTtsSupplementMediaPayload, getReplyPayloadTtsSupplement, isReplyPayloadNonTerminalToolErrorWarning, resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
|
|
24
27
|
import { filterSupplementalContextItems, resolvePinnedMainDmOwnerFromAllowlist, shouldIncludeSupplementalContext } from "openclaw/plugin-sdk/security-runtime";
|
|
25
28
|
import { mimeTypeFromFilePath } from "openclaw/plugin-sdk/media-mime";
|
|
26
|
-
import { ensureConfiguredBindingRouteReady, resolveConfiguredBindingRoute, resolveRuntimeConversationBindingRoute } from "openclaw/plugin-sdk/conversation-runtime";
|
|
27
29
|
import { createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
|
|
28
30
|
import { mergePairLoopGuardConfig } from "openclaw/plugin-sdk/pair-loop-guard-runtime";
|
|
29
31
|
import { enqueueRoutedSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
|
|
30
|
-
import {
|
|
32
|
+
import { asDateTimestampMs, asFiniteNumberInRange, parseStrictFiniteNumber, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
|
|
31
33
|
import { getGlobalHookRunner } from "openclaw/plugin-sdk/plugin-runtime";
|
|
32
|
-
import { buildChannelInboundEventContext, buildMentionRegexes, classifyChannelInboundEvent, dispatchChannelInboundTurn, formatInboundEnvelope, formatInboundMediaUnavailableText, hasVisibleInboundReplyDispatch, implicitMentionKindWhen, logInboundDrop, matchesMentionWithExplicit, readAgentRunTerminalOutcome, recordDroppedChannelInboundHistory, resolveEnvelopeFormatOptions, resolveInboundMentionDecision, resolveInboundSupplementalSenderAllowed, resolveUnmentionedGroupInboundPolicy, toInboundMediaFactsWithMetadata } from "openclaw/plugin-sdk/channel-inbound";
|
|
34
|
+
import { buildChannelInboundEventContext, buildMentionRegexes, classifyChannelInboundEvent, dispatchChannelInboundTurn, formatInboundEnvelope, formatInboundMediaUnavailableText, hasVisibleInboundReplyDispatch, implicitMentionKindWhen, logInboundDrop, matchesMentionWithExplicit, readAgentRunTerminalOutcome, recordDroppedChannelInboundHistory, resolveEnvelopeFormatOptions, resolveInboundMentionDecision, resolveInboundReplyDispatchCounts, resolveInboundSupplementalSenderAllowed, resolveUnmentionedGroupInboundPolicy, toInboundMediaFactsWithMetadata } from "openclaw/plugin-sdk/channel-inbound";
|
|
33
35
|
import { resolveHumanDelayConfig } from "openclaw/plugin-sdk/agent-runtime";
|
|
34
36
|
import { resolveGatewayPublicOrigin } from "openclaw/plugin-sdk/config-contracts";
|
|
35
37
|
import { buildControlUiSessionPath } from "openclaw/plugin-sdk/session-discussion";
|
|
@@ -37,8 +39,7 @@ import { DEFAULT_TIMING, createStatusReactionController, logAckFailure, logTypin
|
|
|
37
39
|
import { hasControlCommand } from "openclaw/plugin-sdk/command-detection";
|
|
38
40
|
import { isAbortRequestText } from "openclaw/plugin-sdk/command-primitives-runtime";
|
|
39
41
|
import { shouldHandleTextCommands } from "openclaw/plugin-sdk/command-surface";
|
|
40
|
-
import { createChannelPreflightAudio } from "openclaw/plugin-sdk/media-understanding-runtime";
|
|
41
|
-
import { runTasksWithConcurrency } from "openclaw/plugin-sdk/concurrency-runtime";
|
|
42
|
+
import { createChannelPreflightAudio, formatAudioTranscriptForAgent } from "openclaw/plugin-sdk/media-understanding-runtime";
|
|
42
43
|
//#region extensions/slack/src/streaming.ts
|
|
43
44
|
/**
|
|
44
45
|
* Thrown when Slack definitively rejects a stream flush/finalize while text
|
|
@@ -267,7 +268,11 @@ function resolveExplicitSlackProgressTitle(entry) {
|
|
|
267
268
|
const trimmed = label.trim();
|
|
268
269
|
return trimmed && trimmed.toLowerCase() !== "auto" ? trimmed : void 0;
|
|
269
270
|
}
|
|
271
|
+
function resolveSlackProgressStyle(entry) {
|
|
272
|
+
return entry?.streaming?.progress?.style === "compact" ? "compact" : "card";
|
|
273
|
+
}
|
|
270
274
|
function resolveSlackNativeProgressTaskCards(entry) {
|
|
275
|
+
if (resolveSlackProgressStyle(entry) === "compact") return false;
|
|
271
276
|
const streaming = entry?.streaming;
|
|
272
277
|
if (!streaming || typeof streaming !== "object" || Array.isArray(streaming)) return true;
|
|
273
278
|
const progressConfig = streaming.progress;
|
|
@@ -380,12 +385,12 @@ function createSlackDraftStream(params) {
|
|
|
380
385
|
const send = params.send ?? sendMessageSlack;
|
|
381
386
|
const edit = params.edit ?? editSlackMessage;
|
|
382
387
|
const remove = params.remove ?? deleteSlackMessage;
|
|
383
|
-
let
|
|
384
|
-
let streamChannelId;
|
|
388
|
+
let streamMessage;
|
|
385
389
|
let untrackConversationBoundary;
|
|
386
390
|
let lastVisibleUpdate;
|
|
387
391
|
let lastSentKey = "";
|
|
388
|
-
const
|
|
392
|
+
const pendingCleanupMessages = [];
|
|
393
|
+
let cleanupTail = Promise.resolve();
|
|
389
394
|
const finalizedMessageIds = /* @__PURE__ */ new Set();
|
|
390
395
|
const streamState = {
|
|
391
396
|
stopped: false,
|
|
@@ -407,8 +412,8 @@ function createSlackDraftStream(params) {
|
|
|
407
412
|
if (sentKey === lastSentKey) return;
|
|
408
413
|
lastSentKey = sentKey;
|
|
409
414
|
try {
|
|
410
|
-
if (
|
|
411
|
-
await edit(
|
|
415
|
+
if (streamMessage) {
|
|
416
|
+
await edit(streamMessage.channelId, streamMessage.messageId, trimmed, {
|
|
412
417
|
cfg: params.cfg,
|
|
413
418
|
token: params.token,
|
|
414
419
|
accountId: params.accountId,
|
|
@@ -440,27 +445,29 @@ function createSlackDraftStream(params) {
|
|
|
440
445
|
...params.metadata ? { metadata: params.metadata } : {},
|
|
441
446
|
...blocks ? { blocks } : {}
|
|
442
447
|
});
|
|
443
|
-
|
|
444
|
-
streamMessageId = sent.messageId || streamMessageId;
|
|
445
|
-
if (!streamChannelId || !streamMessageId) {
|
|
448
|
+
if (!sent.channelId || !sent.messageId) {
|
|
446
449
|
stopTrackingConversationBoundary();
|
|
447
450
|
streamState.stopped = true;
|
|
448
451
|
params.warn?.("slack stream preview stopped (missing identifiers from sendMessage)");
|
|
449
452
|
return;
|
|
450
453
|
}
|
|
454
|
+
streamMessage = {
|
|
455
|
+
channelId: sent.channelId,
|
|
456
|
+
messageId: sent.messageId
|
|
457
|
+
};
|
|
451
458
|
lastVisibleUpdate = {
|
|
452
459
|
text: trimmed,
|
|
453
460
|
...blocks ? { blocks } : {}
|
|
454
461
|
};
|
|
455
|
-
if (pendingBoundary && params.conversationChannelId ===
|
|
462
|
+
if (pendingBoundary && params.conversationChannelId === streamMessage.channelId) pendingBoundary.setMessageTs(streamMessage.messageId);
|
|
456
463
|
else {
|
|
457
464
|
stopTrackingConversationBoundary();
|
|
458
465
|
untrackConversationBoundary = trackSlackDraftMessage({
|
|
459
466
|
accountId: params.accountId,
|
|
460
467
|
teamId: params.eventScope?.teamId,
|
|
461
|
-
channelId:
|
|
468
|
+
channelId: streamMessage.channelId,
|
|
462
469
|
threadTs,
|
|
463
|
-
messageTs:
|
|
470
|
+
messageTs: streamMessage.messageId,
|
|
464
471
|
onInterveningMessage: forceNewMessage
|
|
465
472
|
}).stop;
|
|
466
473
|
}
|
|
@@ -481,60 +488,58 @@ function createSlackDraftStream(params) {
|
|
|
481
488
|
untrackConversationBoundary?.();
|
|
482
489
|
untrackConversationBoundary = void 0;
|
|
483
490
|
};
|
|
484
|
-
const
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
491
|
+
const dropDetachedMessages = () => {
|
|
492
|
+
cleanupTail = cleanupTail.then(async () => {
|
|
493
|
+
for (let index = 0; index < pendingCleanupMessages.length;) {
|
|
494
|
+
const message = pendingCleanupMessages[index];
|
|
495
|
+
if (!message) return;
|
|
496
|
+
try {
|
|
497
|
+
await remove(message.channelId, message.messageId, {
|
|
498
|
+
token: params.token,
|
|
499
|
+
accountId: params.accountId,
|
|
500
|
+
...params.eventScope ? { client: params.eventScope.client } : {}
|
|
501
|
+
});
|
|
502
|
+
pendingCleanupMessages.splice(index, 1);
|
|
503
|
+
} catch (err) {
|
|
504
|
+
params.warn?.(`slack stream preview cleanup failed: ${formatSlackError(err)}`);
|
|
505
|
+
index += 1;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
return cleanupTail;
|
|
494
510
|
};
|
|
495
511
|
const clear = async () => {
|
|
496
512
|
stopTrackingConversationBoundary();
|
|
497
513
|
await discardPending();
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
514
|
+
if (streamMessage) {
|
|
515
|
+
pendingCleanupMessages.push(streamMessage);
|
|
516
|
+
streamMessage = void 0;
|
|
517
|
+
}
|
|
502
518
|
lastVisibleUpdate = void 0;
|
|
503
519
|
lastSentKey = "";
|
|
504
|
-
|
|
505
|
-
await removeMessage(channelId, messageId);
|
|
520
|
+
await dropDetachedMessages();
|
|
506
521
|
};
|
|
507
522
|
const forceNewMessage = () => {
|
|
508
523
|
stopTrackingConversationBoundary();
|
|
509
524
|
streamState.stopped = false;
|
|
510
525
|
streamState.final = false;
|
|
511
|
-
if (
|
|
512
|
-
|
|
513
|
-
messageId: streamMessageId
|
|
514
|
-
});
|
|
515
|
-
streamMessageId = void 0;
|
|
516
|
-
streamChannelId = void 0;
|
|
526
|
+
if (streamMessage && !finalizedMessageIds.has(streamMessage.messageId)) pendingCleanupMessages.push(streamMessage);
|
|
527
|
+
streamMessage = void 0;
|
|
517
528
|
lastVisibleUpdate = void 0;
|
|
518
529
|
lastSentKey = "";
|
|
519
530
|
loop.resetPending();
|
|
520
531
|
};
|
|
521
|
-
const dropDetachedMessages = async () => {
|
|
522
|
-
let message;
|
|
523
|
-
while ((message = detachedMessages.shift()) !== void 0) {
|
|
524
|
-
const { channelId, messageId } = message;
|
|
525
|
-
await removeMessage(channelId, messageId);
|
|
526
|
-
}
|
|
527
|
-
};
|
|
528
532
|
const discardPendingAndStopTracking = async () => {
|
|
529
533
|
stopTrackingConversationBoundary();
|
|
530
534
|
await discardPending();
|
|
531
535
|
};
|
|
532
536
|
const finalizeMessage = async (messageId, editFinal) => {
|
|
533
|
-
const
|
|
537
|
+
const currentMessage = streamMessage;
|
|
534
538
|
const previousUpdate = lastVisibleUpdate;
|
|
535
|
-
if (!
|
|
539
|
+
if (!currentMessage || currentMessage.messageId !== messageId || !previousUpdate) return false;
|
|
540
|
+
const { channelId } = currentMessage;
|
|
536
541
|
await editFinal();
|
|
537
|
-
if (
|
|
542
|
+
if (streamMessage?.channelId === channelId && streamMessage.messageId === messageId) {
|
|
538
543
|
finalizedMessageIds.add(messageId);
|
|
539
544
|
stopTrackingConversationBoundary();
|
|
540
545
|
return true;
|
|
@@ -562,8 +567,58 @@ function createSlackDraftStream(params) {
|
|
|
562
567
|
forceNewMessage,
|
|
563
568
|
dropDetachedMessages,
|
|
564
569
|
finalizeMessage,
|
|
565
|
-
messageId: () =>
|
|
566
|
-
channelId: () =>
|
|
570
|
+
messageId: () => streamMessage?.messageId,
|
|
571
|
+
channelId: () => streamMessage?.channelId
|
|
572
|
+
};
|
|
573
|
+
}
|
|
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
|
|
567
622
|
};
|
|
568
623
|
}
|
|
569
624
|
//#endregion
|
|
@@ -628,12 +683,14 @@ function lineTaskTitle(line) {
|
|
|
628
683
|
return compactTitle(label);
|
|
629
684
|
}
|
|
630
685
|
function lineTaskDetails(line, maxLineChars) {
|
|
631
|
-
const detail =
|
|
632
|
-
return detail ? compactDetail(detail, maxLineChars) : void 0;
|
|
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;
|
|
633
688
|
}
|
|
634
689
|
function lineTaskOutput(line) {
|
|
635
|
-
const match = SLACK_PROGRESS_LINE_DELTA_RE.exec(
|
|
636
|
-
|
|
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;
|
|
637
694
|
}
|
|
638
695
|
function lineTaskStatus(line) {
|
|
639
696
|
const normalized = line.status?.replace(/\s+/g, " ").trim().toLowerCase();
|
|
@@ -738,7 +795,7 @@ function buildSlackProgressStreamChunks(params) {
|
|
|
738
795
|
};
|
|
739
796
|
if (task.details) chunk.details = task.details;
|
|
740
797
|
if (task.output) chunk.output = task.output;
|
|
741
|
-
if (index === finalTaskIndex && diffOutput) chunk.output = diffOutput;
|
|
798
|
+
if (index === finalTaskIndex && diffOutput) chunk.output = [task.output, diffOutput].filter(Boolean).join(" · ");
|
|
742
799
|
if (index === finalTaskIndex && params.sessionUrl) chunk.sources = buildSessionSources(params.sessionUrl);
|
|
743
800
|
return chunk;
|
|
744
801
|
});
|
|
@@ -784,8 +841,7 @@ function buildSlackProgressCardBlocks(params) {
|
|
|
784
841
|
...diffStat ? [diffStat] : [],
|
|
785
842
|
...params.elapsedSeconds && params.elapsedSeconds > 0 ? [`⏱ ${params.elapsedSeconds}s`] : []
|
|
786
843
|
].join(" · ");
|
|
787
|
-
const
|
|
788
|
-
const footer = params.state === "working" ? workingFooter : terminalFooter;
|
|
844
|
+
const footer = params.state === "working" ? workingFooter : diffStat;
|
|
789
845
|
return [
|
|
790
846
|
{
|
|
791
847
|
type: "section",
|
|
@@ -821,35 +877,106 @@ function buildSlackProgressCardBlocks(params) {
|
|
|
821
877
|
}] : []
|
|
822
878
|
].slice(0, 50);
|
|
823
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
|
|
886
|
+
};
|
|
887
|
+
if (previous?.rendered.includes(incoming)) return {
|
|
888
|
+
field: {
|
|
889
|
+
rendered: previous.rendered,
|
|
890
|
+
source: incoming
|
|
891
|
+
},
|
|
892
|
+
delta: void 0
|
|
893
|
+
};
|
|
894
|
+
const next = applyAppendOnlyStreamUpdate({
|
|
895
|
+
incoming,
|
|
896
|
+
rendered: previous?.rendered ?? "",
|
|
897
|
+
source: previous?.source ?? "",
|
|
898
|
+
separator: SLACK_TASK_FIELD_SEPARATOR
|
|
899
|
+
});
|
|
900
|
+
const delta = next.changed ? next.rendered.slice(previous?.rendered.length ?? 0) : void 0;
|
|
901
|
+
return {
|
|
902
|
+
field: {
|
|
903
|
+
rendered: next.rendered,
|
|
904
|
+
source: next.source
|
|
905
|
+
},
|
|
906
|
+
delta
|
|
907
|
+
};
|
|
908
|
+
}
|
|
824
909
|
/**
|
|
825
|
-
*
|
|
826
|
-
*
|
|
827
|
-
*
|
|
828
|
-
*
|
|
910
|
+
* Turns a full task snapshot into the delta Slack must receive. Native streams
|
|
911
|
+
* key rows by persistent id with no removal chunk: unchanged rows are omitted,
|
|
912
|
+
* changed rows carry only their unsent field text, and rows that dropped out
|
|
913
|
+
* (plan shrinks, tool-line <-> plan source switches) get a final complete
|
|
914
|
+
* update or they linger in_progress forever.
|
|
829
915
|
*/
|
|
830
916
|
function reconcileSlackNativeTaskChunks(params) {
|
|
831
917
|
const nextTasks = /* @__PURE__ */ new Map();
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
918
|
+
let planTitle = params.previous.planTitle;
|
|
919
|
+
const emitted = [];
|
|
920
|
+
for (const chunk of params.chunks ?? []) {
|
|
921
|
+
if (chunk.type === "plan_update") {
|
|
922
|
+
if (chunk.title !== planTitle) {
|
|
923
|
+
planTitle = chunk.title;
|
|
924
|
+
emitted.push(chunk);
|
|
925
|
+
}
|
|
926
|
+
continue;
|
|
927
|
+
}
|
|
928
|
+
if (chunk.type !== "task_update") {
|
|
929
|
+
emitted.push(chunk);
|
|
930
|
+
continue;
|
|
931
|
+
}
|
|
932
|
+
const previousRow = params.previous.tasks.get(chunk.id);
|
|
933
|
+
const status = chunk.status;
|
|
934
|
+
const details = resolveTaskFieldDelta(previousRow?.details, chunk.details);
|
|
935
|
+
const output = resolveTaskFieldDelta(previousRow?.output, chunk.output);
|
|
936
|
+
const sourcesChanged = Boolean(chunk.sources) && !previousRow?.sourcesSent;
|
|
937
|
+
const row = {
|
|
938
|
+
title: chunk.title,
|
|
939
|
+
status
|
|
840
940
|
};
|
|
841
|
-
|
|
842
|
-
|
|
941
|
+
if (details.field) row.details = details.field;
|
|
942
|
+
if (output.field) row.output = output.field;
|
|
943
|
+
if (sourcesChanged || previousRow?.sourcesSent) row.sourcesSent = true;
|
|
944
|
+
nextTasks.set(chunk.id, row);
|
|
945
|
+
if (!(!previousRow || previousRow.title !== chunk.title || previousRow.status !== status || Boolean(details.delta) || Boolean(output.delta) || sourcesChanged)) continue;
|
|
946
|
+
const update = {
|
|
947
|
+
type: "task_update",
|
|
948
|
+
id: chunk.id,
|
|
949
|
+
title: chunk.title,
|
|
950
|
+
status
|
|
951
|
+
};
|
|
952
|
+
if (details.delta) update.details = details.delta;
|
|
953
|
+
if (output.delta) update.output = output.delta;
|
|
954
|
+
if (sourcesChanged) update.sources = chunk.sources;
|
|
955
|
+
emitted.push(update);
|
|
956
|
+
}
|
|
957
|
+
for (const [id, row] of params.previous.tasks) {
|
|
958
|
+
if (nextTasks.has(id)) continue;
|
|
959
|
+
if (row.status === "complete" || row.status === "error") {
|
|
960
|
+
nextTasks.set(id, row);
|
|
961
|
+
continue;
|
|
962
|
+
}
|
|
963
|
+
nextTasks.set(id, {
|
|
964
|
+
...row,
|
|
965
|
+
status: "complete"
|
|
966
|
+
});
|
|
967
|
+
emitted.push({
|
|
843
968
|
type: "task_update",
|
|
844
969
|
id,
|
|
845
|
-
title:
|
|
970
|
+
title: row.title,
|
|
846
971
|
status: "complete"
|
|
847
|
-
};
|
|
848
|
-
}
|
|
849
|
-
for (const [id, task] of params.previousTasks) if (!nextTasks.has(id)) nextTasks.set(id, task);
|
|
972
|
+
});
|
|
973
|
+
}
|
|
850
974
|
return {
|
|
851
|
-
chunks:
|
|
852
|
-
|
|
975
|
+
chunks: emitted.length > 0 ? emitted : void 0,
|
|
976
|
+
snapshot: {
|
|
977
|
+
...planTitle ? { planTitle } : {},
|
|
978
|
+
tasks: nextTasks
|
|
979
|
+
}
|
|
853
980
|
};
|
|
854
981
|
}
|
|
855
982
|
function buildSlackProgressStreamCompletionChunks(params) {
|
|
@@ -859,56 +986,6 @@ function buildSlackProgressStreamCompletionChunks(params) {
|
|
|
859
986
|
});
|
|
860
987
|
}
|
|
861
988
|
//#endregion
|
|
862
|
-
//#region extensions/slack/src/stream-mode.ts
|
|
863
|
-
function resolveSlackStreamingConfig(params) {
|
|
864
|
-
return {
|
|
865
|
-
mode: resolveSlackStreamingMode(params),
|
|
866
|
-
nativeStreaming: resolveSlackNativeStreaming(params)
|
|
867
|
-
};
|
|
868
|
-
}
|
|
869
|
-
function applyAppendOnlyStreamUpdate(params) {
|
|
870
|
-
const incoming = params.incoming.trimEnd();
|
|
871
|
-
if (!incoming) return {
|
|
872
|
-
rendered: params.rendered,
|
|
873
|
-
source: params.source,
|
|
874
|
-
changed: false
|
|
875
|
-
};
|
|
876
|
-
if (!params.rendered) return {
|
|
877
|
-
rendered: incoming,
|
|
878
|
-
source: incoming,
|
|
879
|
-
changed: true
|
|
880
|
-
};
|
|
881
|
-
if (incoming === params.source) return {
|
|
882
|
-
rendered: params.rendered,
|
|
883
|
-
source: params.source,
|
|
884
|
-
changed: false
|
|
885
|
-
};
|
|
886
|
-
if (incoming.startsWith(params.rendered)) return {
|
|
887
|
-
rendered: incoming,
|
|
888
|
-
source: incoming,
|
|
889
|
-
changed: incoming !== params.rendered
|
|
890
|
-
};
|
|
891
|
-
if (incoming.startsWith(params.source)) {
|
|
892
|
-
const delta = incoming.slice(params.source.length);
|
|
893
|
-
return {
|
|
894
|
-
rendered: `${params.rendered}${delta}`,
|
|
895
|
-
source: incoming,
|
|
896
|
-
changed: delta.length > 0
|
|
897
|
-
};
|
|
898
|
-
}
|
|
899
|
-
if (params.source.startsWith(incoming)) return {
|
|
900
|
-
rendered: params.rendered,
|
|
901
|
-
source: params.source,
|
|
902
|
-
changed: false
|
|
903
|
-
};
|
|
904
|
-
const separator = params.rendered.endsWith("\n") ? "" : "\n";
|
|
905
|
-
return {
|
|
906
|
-
rendered: `${params.rendered}${separator}${incoming}`,
|
|
907
|
-
source: incoming,
|
|
908
|
-
changed: true
|
|
909
|
-
};
|
|
910
|
-
}
|
|
911
|
-
//#endregion
|
|
912
989
|
//#region extensions/slack/src/monitor/message-handler/dispatch-progress-render.ts
|
|
913
990
|
function resolveStructuredProgressLines(lines) {
|
|
914
991
|
return lines.map((line) => {
|
|
@@ -1098,12 +1175,9 @@ function createSlackDraftProgressCardRuntime(params) {
|
|
|
1098
1175
|
maxLineChars: params.maxLineChars,
|
|
1099
1176
|
diffStat: snapshot.diffStat,
|
|
1100
1177
|
...state === "working" ? {
|
|
1101
|
-
toolCalls: params.
|
|
1102
|
-
elapsedSeconds: params.
|
|
1103
|
-
} : {
|
|
1104
|
-
receiptSummary: params.progressReceipt.buildSummaryLine(),
|
|
1105
|
-
sessionUrl: resolveSessionUrl()
|
|
1106
|
-
}
|
|
1178
|
+
toolCalls: params.progressWorkCounter.toolCalls,
|
|
1179
|
+
elapsedSeconds: params.progressWorkCounter.elapsedSeconds
|
|
1180
|
+
} : { sessionUrl: resolveSessionUrl() }
|
|
1107
1181
|
});
|
|
1108
1182
|
};
|
|
1109
1183
|
const finalize = async (status, snapshot = params.getSnapshot(), fallbackText = resolveText(snapshot)) => {
|
|
@@ -1263,7 +1337,7 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1263
1337
|
log: logVerbose,
|
|
1264
1338
|
warn: logVerbose
|
|
1265
1339
|
}) : void 0;
|
|
1266
|
-
let
|
|
1340
|
+
let hasStreamedAnswer = false;
|
|
1267
1341
|
const isProgressMode = slackStreaming.mode === "progress";
|
|
1268
1342
|
const useNativeProgressStreaming = useStreaming && slackStreaming.mode === "progress";
|
|
1269
1343
|
const progressDraftActive = Boolean(draftStream) || useNativeProgressStreaming;
|
|
@@ -1276,12 +1350,11 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1276
1350
|
previewStreamingEnabled
|
|
1277
1351
|
});
|
|
1278
1352
|
let previewToolProgressSuppressed = false;
|
|
1279
|
-
let
|
|
1353
|
+
let nativeStreamSnapshot = EMPTY_SLACK_NATIVE_STREAM_SNAPSHOT;
|
|
1280
1354
|
let appendRenderedText = "";
|
|
1281
1355
|
let appendSourceText = "";
|
|
1282
1356
|
let nativeProgressCompletionSent = false;
|
|
1283
1357
|
let nativeProgressTerminalStatus = "complete";
|
|
1284
|
-
let nativeProgressChunkKey;
|
|
1285
1358
|
let nativeNarrationRenderedText = "";
|
|
1286
1359
|
let nativeNarrationSourceText = "";
|
|
1287
1360
|
let nativeStreamOrder = Promise.resolve();
|
|
@@ -1290,9 +1363,10 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1290
1363
|
nativeStreamOrder = run.catch(() => void 0);
|
|
1291
1364
|
return run;
|
|
1292
1365
|
};
|
|
1293
|
-
const
|
|
1366
|
+
const progressWorkCounter = createChannelProgressWorkCounter();
|
|
1294
1367
|
const progressSeed = `${account.accountId}:${message.channel}`;
|
|
1295
|
-
const
|
|
1368
|
+
const slackProgressStyle = resolveSlackProgressStyle(account.config);
|
|
1369
|
+
const useDraftProgressCard = Boolean(draftStream) && isProgressMode && slackProgressStyle === "card";
|
|
1296
1370
|
const explicitProgressTitle = resolveExplicitSlackProgressTitle(account.config);
|
|
1297
1371
|
const progressDraftMaxLineChars = resolveChannelProgressDraftMaxLineChars(account.config);
|
|
1298
1372
|
const progressCard = createSlackDraftProgressCardRuntime({
|
|
@@ -1305,7 +1379,7 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1305
1379
|
},
|
|
1306
1380
|
draftStream,
|
|
1307
1381
|
enabled: useDraftProgressCard,
|
|
1308
|
-
|
|
1382
|
+
progressWorkCounter,
|
|
1309
1383
|
progressSeed,
|
|
1310
1384
|
explicitTitle: explicitProgressTitle,
|
|
1311
1385
|
maxLineChars: progressDraftMaxLineChars,
|
|
@@ -1367,16 +1441,14 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1367
1441
|
const snapshot = progressDraft.getSnapshot();
|
|
1368
1442
|
const progressLines = resolveNativeProgressLines(snapshot);
|
|
1369
1443
|
const narrationUpdate = resolveNarrationUpdate(resolveNativeProgressNarration(snapshot));
|
|
1370
|
-
const hasRetirableNativeTasks = [...
|
|
1444
|
+
const hasRetirableNativeTasks = [...nativeStreamSnapshot.tasks.values()].some((task) => task.status !== "complete" && task.status !== "error");
|
|
1371
1445
|
if (!useNativeProgressStreaming || delivery.streamFailed || progressLines.length === 0 && !snapshot.plan?.length && !snapshot.statusHeadline && !explicitProgressTitle && !hasRetirableNativeTasks && !narrationUpdate.delta) return false;
|
|
1372
1446
|
if (!await nativeTransport.waitForStart()) return false;
|
|
1373
1447
|
const reconciled = reconcileSlackNativeTaskChunks({
|
|
1374
|
-
|
|
1448
|
+
previous: nativeStreamSnapshot,
|
|
1375
1449
|
chunks: buildNativeProgressChunks$1(snapshot)
|
|
1376
1450
|
});
|
|
1377
|
-
const
|
|
1378
|
-
const taskChunksChanged = chunkKey !== nativeProgressChunkKey;
|
|
1379
|
-
const chunks = taskChunksChanged ? reconciled.chunks : void 0;
|
|
1451
|
+
const chunks = reconciled.chunks;
|
|
1380
1452
|
if (!chunks?.length && !narrationUpdate.delta) return false;
|
|
1381
1453
|
try {
|
|
1382
1454
|
const hadSession = Boolean(delivery.streamSession);
|
|
@@ -1390,10 +1462,7 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1390
1462
|
nativeNarrationRenderedText = narrationUpdate.next.rendered;
|
|
1391
1463
|
nativeNarrationSourceText = narrationUpdate.next.source;
|
|
1392
1464
|
}
|
|
1393
|
-
if (
|
|
1394
|
-
nativeProgressChunkKey = chunkKey;
|
|
1395
|
-
nativeTaskState = reconciled.tasks;
|
|
1396
|
-
}
|
|
1465
|
+
if (chunks?.length) nativeStreamSnapshot = reconciled.snapshot;
|
|
1397
1466
|
return true;
|
|
1398
1467
|
} catch (err) {
|
|
1399
1468
|
runtime.error?.(danger(`slack-stream: native progress stream failed: ${formatSlackError(err)}, falling back`));
|
|
@@ -1420,7 +1489,7 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1420
1489
|
return true;
|
|
1421
1490
|
};
|
|
1422
1491
|
const resetProgressTurnState = () => {
|
|
1423
|
-
|
|
1492
|
+
progressWorkCounter.reset();
|
|
1424
1493
|
nativeNarrationRenderedText = "";
|
|
1425
1494
|
nativeNarrationSourceText = "";
|
|
1426
1495
|
};
|
|
@@ -1445,7 +1514,6 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1445
1514
|
text: previewText,
|
|
1446
1515
|
blocks: progressCard.resolvePresentation(snapshot, "working")
|
|
1447
1516
|
} : previewText);
|
|
1448
|
-
hasStreamedMessage = true;
|
|
1449
1517
|
if (options?.flush) await draftStream.flush();
|
|
1450
1518
|
return Boolean(draftStream.messageId() && draftStream.channelId());
|
|
1451
1519
|
}
|
|
@@ -1476,10 +1544,10 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1476
1544
|
const snapshot = progressDraft.getSnapshot();
|
|
1477
1545
|
const lines = resolveNativeProgressLines(snapshot);
|
|
1478
1546
|
const sessionUrl = progressCard.resolveSessionUrl();
|
|
1479
|
-
const hasRetirableNativeTasks = [...
|
|
1547
|
+
const hasRetirableNativeTasks = [...nativeStreamSnapshot.tasks.values()].some((task) => task.status !== "complete" && task.status !== "error");
|
|
1480
1548
|
if (lines.length === 0 && !snapshot.plan?.length && !hasRetirableNativeTasks && !snapshot.diffStat && !sessionUrl) return;
|
|
1481
1549
|
return reconcileSlackNativeTaskChunks({
|
|
1482
|
-
|
|
1550
|
+
previous: nativeStreamSnapshot,
|
|
1483
1551
|
chunks: buildSlackProgressStreamCompletionChunks({
|
|
1484
1552
|
title: resolveNativeProgressTitle(snapshot) ?? (lines.length === 0 && !snapshot.plan?.length ? "Working" : void 0),
|
|
1485
1553
|
lines,
|
|
@@ -1514,7 +1582,10 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1514
1582
|
delivery.streamFailed = false;
|
|
1515
1583
|
};
|
|
1516
1584
|
const pushPlanProgress = async (steps, explanation) => {
|
|
1517
|
-
if (isProgressMode)
|
|
1585
|
+
if (isProgressMode) {
|
|
1586
|
+
if (slackProgressStyle === "compact") return false;
|
|
1587
|
+
return await progressDraft.pushPlanProgress(steps, { explanation });
|
|
1588
|
+
}
|
|
1518
1589
|
if (previewToolProgressSuppressed || !draftStream) return false;
|
|
1519
1590
|
const text = formatChannelProgressDraftText({
|
|
1520
1591
|
entry: account.config,
|
|
@@ -1524,10 +1595,7 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1524
1595
|
narration: explanation,
|
|
1525
1596
|
plan: steps
|
|
1526
1597
|
});
|
|
1527
|
-
if (text)
|
|
1528
|
-
draftStream.update(text);
|
|
1529
|
-
hasStreamedMessage = true;
|
|
1530
|
-
}
|
|
1598
|
+
if (text) draftStream.update(text);
|
|
1531
1599
|
return false;
|
|
1532
1600
|
};
|
|
1533
1601
|
const pushPreviewProgress = async (line, options) => {
|
|
@@ -1542,7 +1610,7 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1542
1610
|
return await progressDraft.pushToolProgress(line, options);
|
|
1543
1611
|
};
|
|
1544
1612
|
const updateDraftFromPartial = (text) => {
|
|
1545
|
-
const trimmed = text
|
|
1613
|
+
const trimmed = text && sanitizeAssistantVisibleText(text).trimEnd();
|
|
1546
1614
|
if (!trimmed) return false;
|
|
1547
1615
|
if (slackStreaming.mode === "block") {
|
|
1548
1616
|
previewToolProgressSuppressed = true;
|
|
@@ -1556,14 +1624,14 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1556
1624
|
appendSourceText = next.source;
|
|
1557
1625
|
if (!next.changed) return false;
|
|
1558
1626
|
draftStream?.update(next.rendered);
|
|
1559
|
-
|
|
1627
|
+
hasStreamedAnswer = true;
|
|
1560
1628
|
return false;
|
|
1561
1629
|
}
|
|
1562
1630
|
if (isProgressMode) return false;
|
|
1563
1631
|
previewToolProgressSuppressed = true;
|
|
1564
1632
|
progressDraft.suppress();
|
|
1565
1633
|
draftStream?.update(trimmed);
|
|
1566
|
-
|
|
1634
|
+
hasStreamedAnswer = true;
|
|
1567
1635
|
return false;
|
|
1568
1636
|
};
|
|
1569
1637
|
const pushReasoningProgress = async (payload) => {
|
|
@@ -1580,11 +1648,10 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1580
1648
|
progressDraft.mergeReasoningProgress(normalized, { snapshot: true });
|
|
1581
1649
|
return visible;
|
|
1582
1650
|
}
|
|
1583
|
-
progressReceipt.noteReasoning();
|
|
1584
1651
|
return await progressDraft.pushReasoningProgress(payload.text, { snapshot: payload.isReasoningSnapshot === true });
|
|
1585
1652
|
};
|
|
1586
1653
|
const resetDraftDeliveryState = () => {
|
|
1587
|
-
|
|
1654
|
+
hasStreamedAnswer = false;
|
|
1588
1655
|
appendRenderedText = "";
|
|
1589
1656
|
appendSourceText = "";
|
|
1590
1657
|
};
|
|
@@ -1604,10 +1671,9 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1604
1671
|
await dropDetachedProgressCards();
|
|
1605
1672
|
}
|
|
1606
1673
|
resetProgressTurnState();
|
|
1607
|
-
|
|
1674
|
+
nativeStreamSnapshot = EMPTY_SLACK_NATIVE_STREAM_SNAPSHOT;
|
|
1608
1675
|
nativeProgressCompletionSent = false;
|
|
1609
1676
|
nativeProgressTerminalStatus = "complete";
|
|
1610
|
-
nativeProgressChunkKey = void 0;
|
|
1611
1677
|
progressCard.reset();
|
|
1612
1678
|
resetPreviewDeliveryState();
|
|
1613
1679
|
delivery.resetDeliveryTracker();
|
|
@@ -1618,7 +1684,7 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1618
1684
|
await beginNewProgressTurn();
|
|
1619
1685
|
return;
|
|
1620
1686
|
}
|
|
1621
|
-
if (
|
|
1687
|
+
if (hasStreamedAnswer) draftStream?.forceNewMessage();
|
|
1622
1688
|
resetDraftDeliveryState();
|
|
1623
1689
|
resetDraftProgressState();
|
|
1624
1690
|
};
|
|
@@ -1645,7 +1711,7 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1645
1711
|
suppressDefaultToolProgressMessages,
|
|
1646
1712
|
progressDraft,
|
|
1647
1713
|
commentaryProgressEnabled,
|
|
1648
|
-
|
|
1714
|
+
progressWorkCounter,
|
|
1649
1715
|
get nativeProgressCompletionSent() {
|
|
1650
1716
|
return nativeProgressCompletionSent;
|
|
1651
1717
|
},
|
|
@@ -1673,41 +1739,6 @@ function createSlackProgressRuntime(runtimeParams) {
|
|
|
1673
1739
|
};
|
|
1674
1740
|
}
|
|
1675
1741
|
//#endregion
|
|
1676
|
-
//#region extensions/slack/src/threading.ts
|
|
1677
|
-
function resolveSlackThreadContext(params) {
|
|
1678
|
-
const incomingThreadTs = params.message.thread_ts;
|
|
1679
|
-
const eventTs = params.message.event_ts;
|
|
1680
|
-
const messageTs = params.message.ts ?? eventTs;
|
|
1681
|
-
const hasThreadTs = typeof incomingThreadTs === "string" && incomingThreadTs.length > 0;
|
|
1682
|
-
const isThreadReply = hasThreadTs && (incomingThreadTs !== messageTs || Boolean(params.message.parent_user_id));
|
|
1683
|
-
const replyToId = isThreadReply ? incomingThreadTs : void 0;
|
|
1684
|
-
const isAssistantDmThreadRoot = hasThreadTs && !isThreadReply && params.isDirectMessage === true;
|
|
1685
|
-
return {
|
|
1686
|
-
incomingThreadTs,
|
|
1687
|
-
messageTs,
|
|
1688
|
-
isThreadReply,
|
|
1689
|
-
replyToId,
|
|
1690
|
-
messageThreadId: isThreadReply || isAssistantDmThreadRoot ? incomingThreadTs : params.replyToMode === "all" ? messageTs : void 0
|
|
1691
|
-
};
|
|
1692
|
-
}
|
|
1693
|
-
/**
|
|
1694
|
-
* Resolves Slack thread targeting for replies and status indicators.
|
|
1695
|
-
*
|
|
1696
|
-
* @returns replyThreadTs - Thread timestamp for reply messages
|
|
1697
|
-
* @returns statusThreadTs - Thread timestamp for status indicators (typing, etc.)
|
|
1698
|
-
* @returns isThreadReply - true if this is a genuine user reply in a thread,
|
|
1699
|
-
* false if thread_ts comes from a bot status message (e.g. typing indicator)
|
|
1700
|
-
*/
|
|
1701
|
-
function resolveSlackThreadTargets(params) {
|
|
1702
|
-
const { incomingThreadTs, messageTs, isThreadReply } = resolveSlackThreadContext(params);
|
|
1703
|
-
const replyThreadTs = isThreadReply ? incomingThreadTs : params.replyToMode === "all" ? messageTs : void 0;
|
|
1704
|
-
return {
|
|
1705
|
-
replyThreadTs,
|
|
1706
|
-
statusThreadTs: replyThreadTs,
|
|
1707
|
-
isThreadReply
|
|
1708
|
-
};
|
|
1709
|
-
}
|
|
1710
|
-
//#endregion
|
|
1711
1742
|
//#region extensions/slack/src/monitor/message-handler/dispatch-setup.ts
|
|
1712
1743
|
async function createSlackDispatchSetup(prepared) {
|
|
1713
1744
|
const { ctx, account, message, route } = prepared;
|
|
@@ -1829,10 +1860,7 @@ async function createSlackDispatchSetup(prepared) {
|
|
|
1829
1860
|
agentId: route.agentId,
|
|
1830
1861
|
channel: "slack",
|
|
1831
1862
|
accountId: route.accountId,
|
|
1832
|
-
transformReplyPayload:
|
|
1833
|
-
if (payload.isReasoning === true) return null;
|
|
1834
|
-
return payload;
|
|
1835
|
-
},
|
|
1863
|
+
transformReplyPayload: sanitizeSlackMonitorReplyPayload,
|
|
1836
1864
|
typing: {
|
|
1837
1865
|
start: async () => {
|
|
1838
1866
|
if (!threadStatusGate.hasVisibleOutput()) {
|
|
@@ -1980,11 +2008,6 @@ function createSlackStreamingDeliveryRuntime(setup) {
|
|
|
1980
2008
|
observedFinalReplyDelivery: false
|
|
1981
2009
|
};
|
|
1982
2010
|
const streamedDeliveries = [];
|
|
1983
|
-
const streamedFailuresOwnedByDispatcher = {
|
|
1984
|
-
tool: 0,
|
|
1985
|
-
block: 0,
|
|
1986
|
-
final: 0
|
|
1987
|
-
};
|
|
1988
2011
|
const refreshStreamedAcknowledgements = (session) => {
|
|
1989
2012
|
if (session.pendingText.length === 0) for (const delivery of streamedDeliveries) delivery.acknowledged = true;
|
|
1990
2013
|
};
|
|
@@ -2123,7 +2146,6 @@ function createSlackStreamingDeliveryRuntime(setup) {
|
|
|
2123
2146
|
}
|
|
2124
2147
|
};
|
|
2125
2148
|
const deliverNormally = async (params) => {
|
|
2126
|
-
if (params.payload.isReasoning === true) return;
|
|
2127
2149
|
const replyThreadTs = resolveDeliveryThreadTs(params);
|
|
2128
2150
|
const deliveryReplyThreadTs = replyDeliveryMode === "off" && !forcedReplyThreadTs && !isThreadReply ? void 0 : replyThreadTs;
|
|
2129
2151
|
if (deliveryTracker.hasDelivered({
|
|
@@ -2167,10 +2189,7 @@ function createSlackStreamingDeliveryRuntime(setup) {
|
|
|
2167
2189
|
return deliveryReplyThreadTs;
|
|
2168
2190
|
};
|
|
2169
2191
|
const deliverBufferedStreamFallback = async (params) => {
|
|
2170
|
-
if (!await deliverPendingStreamFallback(params.session, params.err))
|
|
2171
|
-
streamedFailuresOwnedByDispatcher[params.kind] += 1;
|
|
2172
|
-
return false;
|
|
2173
|
-
}
|
|
2192
|
+
if (!await deliverPendingStreamFallback(params.session, params.err)) return false;
|
|
2174
2193
|
replyPlan.markSent();
|
|
2175
2194
|
if (params.kind === "final") state.observedFinalReplyDelivery = true;
|
|
2176
2195
|
deliveryTracker.markDelivered({
|
|
@@ -2189,7 +2208,6 @@ function createSlackStreamingDeliveryRuntime(setup) {
|
|
|
2189
2208
|
return !state.streamFailed && !reply.hasMedia && renderPlan.mode !== "split" && !plannedBlocks?.length && !readSlackReplyBlocks(payload)?.length && reply.hasText && (!options?.maxTextBytes || countSlackTextUtf8Bytes(reply.trimmedText) <= options.maxTextBytes);
|
|
2190
2209
|
};
|
|
2191
2210
|
const deliverWithStreaming = async (params) => {
|
|
2192
|
-
if (params.payload.isReasoning === true) return;
|
|
2193
2211
|
const reply = resolveSendableOutboundReplyParts(params.payload);
|
|
2194
2212
|
if (!isStreamingEligible(params.payload)) {
|
|
2195
2213
|
await deliverNormally({
|
|
@@ -2329,23 +2347,6 @@ function createSlackStreamingDeliveryRuntime(setup) {
|
|
|
2329
2347
|
});
|
|
2330
2348
|
}
|
|
2331
2349
|
};
|
|
2332
|
-
const reconcileCounts = (counts) => {
|
|
2333
|
-
const next = { ...counts };
|
|
2334
|
-
let changed = false;
|
|
2335
|
-
for (const kind of [
|
|
2336
|
-
"tool",
|
|
2337
|
-
"block",
|
|
2338
|
-
"final"
|
|
2339
|
-
]) {
|
|
2340
|
-
const failedStreamedCount = streamedDeliveries.filter((delivery) => delivery.kind === kind && delivery.outcome === "failure").length;
|
|
2341
|
-
const additionalFailedStreamed = Math.max(0, failedStreamedCount - streamedFailuresOwnedByDispatcher[kind]);
|
|
2342
|
-
if (additionalFailedStreamed > 0) {
|
|
2343
|
-
next[kind] = Math.max(0, (next[kind] ?? 0) - additionalFailedStreamed);
|
|
2344
|
-
changed = true;
|
|
2345
|
-
}
|
|
2346
|
-
}
|
|
2347
|
-
return changed ? next : counts;
|
|
2348
|
-
};
|
|
2349
2350
|
return Object.assign(state, {
|
|
2350
2351
|
acknowledgeStoppedStreamedDeliveries,
|
|
2351
2352
|
deliverNormally,
|
|
@@ -2357,7 +2358,6 @@ function createSlackStreamingDeliveryRuntime(setup) {
|
|
|
2357
2358
|
isStreamingEligible,
|
|
2358
2359
|
markPreviewPayloadDelivered,
|
|
2359
2360
|
rememberDeliveredThreadTs,
|
|
2360
|
-
reconcileCounts,
|
|
2361
2361
|
resetDeliveryTracker: () => {
|
|
2362
2362
|
deliveryTracker = createSlackEventDeliveryTracker();
|
|
2363
2363
|
}
|
|
@@ -2409,7 +2409,6 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2409
2409
|
return payload;
|
|
2410
2410
|
};
|
|
2411
2411
|
const deliverSlackPayload = async (payload, info) => {
|
|
2412
|
-
if (payload.isReasoning === true) return { visibleReplySent: false };
|
|
2413
2412
|
if (info.kind === "final" && slackStreaming.mode === "progress" && progress.isProgressMode) {
|
|
2414
2413
|
if (progress.useNativeProgressStreaming) {
|
|
2415
2414
|
await progress.deliverNativeFinal(payload, info.kind);
|
|
@@ -2460,66 +2459,14 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2460
2459
|
const slackBlocks = replyRenderPlan.mode === "single" ? replyRenderPlan.blocks : replyRenderPlan.blockPart?.blocks;
|
|
2461
2460
|
const requiresSeparateFallbackDelivery = replyRenderPlan.mode === "split";
|
|
2462
2461
|
const trimmedFinalText = replyRenderPlan.mode === "single" ? replyRenderPlan.text.trim() : replyRenderPlan.fallbackText.trim();
|
|
2463
|
-
const previewFinalText = replyRenderPlan.mode === "single" && replyRenderPlan.textIsSlackMrkdwn ? trimmedFinalText : normalizeSlackOutboundText((replySourceText ?? "").trim()
|
|
2462
|
+
const previewFinalText = replyRenderPlan.mode === "single" && replyRenderPlan.textIsSlackMrkdwn ? trimmedFinalText : normalizeSlackOutboundText((replySourceText ?? "").trim(), { tableMode: resolveMarkdownTableMode({
|
|
2463
|
+
cfg,
|
|
2464
|
+
channel: "slack",
|
|
2465
|
+
accountId: account.accountId
|
|
2466
|
+
}) });
|
|
2464
2467
|
const previewFinalTextFitsEdit = countSlackTextUtf8Bytes(previewFinalText) <= SLACK_EDIT_TEXT_MAX_BYTES;
|
|
2465
2468
|
const shouldRestoreTtsSupplementTextForPreviewFallback = Boolean(ttsSupplement) && ttsSupplement?.visibleTextAlreadyDelivered !== true && Boolean(draftStream) && !draftPreviewCommitted.value && !delivery.observedFinalReplyDelivery && previewStreamingEnabled && !payload.text?.trim();
|
|
2466
|
-
|
|
2467
|
-
await draftStream.flush();
|
|
2468
|
-
const channelId = draftStream.channelId();
|
|
2469
|
-
const messageId = draftStream.messageId();
|
|
2470
|
-
if (channelId && messageId) {
|
|
2471
|
-
const finalThreadTs = delivery.usedReplyThreadTs ?? statusThreadTs;
|
|
2472
|
-
await draftStream.seal();
|
|
2473
|
-
try {
|
|
2474
|
-
if (!await draftStream.finalizeMessage(messageId, async () => {
|
|
2475
|
-
await finalizeSlackPreviewEdit({
|
|
2476
|
-
client: slackClient,
|
|
2477
|
-
token: ctx.botToken,
|
|
2478
|
-
accountId: account.accountId,
|
|
2479
|
-
channelId,
|
|
2480
|
-
messageId,
|
|
2481
|
-
text: previewFinalText,
|
|
2482
|
-
...slackBlocks?.length ? { blocks: slackBlocks } : {},
|
|
2483
|
-
threadTs: finalThreadTs
|
|
2484
|
-
});
|
|
2485
|
-
})) throw new Error("Slack preview moved below a newer conversation message");
|
|
2486
|
-
} catch (err) {
|
|
2487
|
-
logVerbose(`slack: preview final edit failed; falling back to standard send (${formatSlackError(err)})`);
|
|
2488
|
-
await draftStream.discardPending();
|
|
2489
|
-
let delivered = false;
|
|
2490
|
-
try {
|
|
2491
|
-
await delivery.deliverNormally({
|
|
2492
|
-
payload: payload.text?.trim() ? payload : {
|
|
2493
|
-
...payload,
|
|
2494
|
-
text: ttsSupplement.spokenText
|
|
2495
|
-
},
|
|
2496
|
-
kind: info.kind,
|
|
2497
|
-
forcedThreadTs: finalThreadTs
|
|
2498
|
-
});
|
|
2499
|
-
delivered = true;
|
|
2500
|
-
} finally {
|
|
2501
|
-
if (delivered) await draftStream.clear();
|
|
2502
|
-
}
|
|
2503
|
-
return;
|
|
2504
|
-
}
|
|
2505
|
-
draftPreviewCommitted.value = true;
|
|
2506
|
-
delivery.observedFinalReplyDelivery = true;
|
|
2507
|
-
delivery.observedReplyDelivery = true;
|
|
2508
|
-
replyPlan.markSent();
|
|
2509
|
-
await delivery.deliverNormally({
|
|
2510
|
-
payload: buildTtsSupplementMediaPayload(payload),
|
|
2511
|
-
kind: info.kind,
|
|
2512
|
-
forcedThreadTs: finalThreadTs
|
|
2513
|
-
});
|
|
2514
|
-
delivery.markPreviewPayloadDelivered({
|
|
2515
|
-
kind: info.kind,
|
|
2516
|
-
payload,
|
|
2517
|
-
threadTs: finalThreadTs
|
|
2518
|
-
});
|
|
2519
|
-
progress.progressDraft.markFinalReplyDelivered();
|
|
2520
|
-
return;
|
|
2521
|
-
}
|
|
2522
|
-
}
|
|
2469
|
+
let ttsPreviewFinalization;
|
|
2523
2470
|
await deliverWithFinalizableLivePreviewAdapter({
|
|
2524
2471
|
kind: info.kind,
|
|
2525
2472
|
payload,
|
|
@@ -2552,6 +2499,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2552
2499
|
payload,
|
|
2553
2500
|
threadTs: edit.threadTs
|
|
2554
2501
|
})) return;
|
|
2502
|
+
if (ttsSupplement) ttsPreviewFinalization = { threadTs: edit.threadTs };
|
|
2555
2503
|
if (!await draftStream?.finalizeMessage(preview.messageId, async () => {
|
|
2556
2504
|
await finalizeSlackPreviewEdit({
|
|
2557
2505
|
client: slackClient,
|
|
@@ -2607,11 +2555,12 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2607
2555
|
}),
|
|
2608
2556
|
deliverNormally: async () => {
|
|
2609
2557
|
await delivery.deliverNormally({
|
|
2610
|
-
payload: shouldRestoreTtsSupplementTextForPreviewFallback ? {
|
|
2558
|
+
payload: shouldRestoreTtsSupplementTextForPreviewFallback || ttsPreviewFinalization && !payload.text?.trim() ? {
|
|
2611
2559
|
...payload,
|
|
2612
2560
|
text: ttsSupplement?.spokenText
|
|
2613
2561
|
} : payload,
|
|
2614
|
-
kind: info.kind
|
|
2562
|
+
kind: info.kind,
|
|
2563
|
+
...ttsPreviewFinalization?.threadTs ? { forcedThreadTs: ttsPreviewFinalization.threadTs } : {}
|
|
2615
2564
|
});
|
|
2616
2565
|
}
|
|
2617
2566
|
});
|
|
@@ -2619,8 +2568,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2619
2568
|
};
|
|
2620
2569
|
let dispatchError;
|
|
2621
2570
|
let agentRunFailed = false;
|
|
2622
|
-
let
|
|
2623
|
-
let counts = {};
|
|
2571
|
+
let settledDispatchResult;
|
|
2624
2572
|
try {
|
|
2625
2573
|
const turnResult = await dispatchChannelInboundTurn({
|
|
2626
2574
|
cfg,
|
|
@@ -2631,6 +2579,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2631
2579
|
sessionKey: route.sessionKey
|
|
2632
2580
|
},
|
|
2633
2581
|
ctxPayload: prepared.ctxPayload,
|
|
2582
|
+
dispatchReplyFromConfig: ctx.dispatchReplyFromConfig,
|
|
2634
2583
|
dispatcherOptions: {
|
|
2635
2584
|
...replyPipeline,
|
|
2636
2585
|
transformReplyPayload: (payload) => {
|
|
@@ -2672,7 +2621,6 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2672
2621
|
return false;
|
|
2673
2622
|
} : void 0,
|
|
2674
2623
|
onReasoningEnd: async () => {
|
|
2675
|
-
progress.progressReceipt.closeReasoning();
|
|
2676
2624
|
await progress.onDraftBoundary?.();
|
|
2677
2625
|
return false;
|
|
2678
2626
|
},
|
|
@@ -2686,18 +2634,14 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2686
2634
|
} : void 0,
|
|
2687
2635
|
onToolStart: async (payload) => {
|
|
2688
2636
|
if (statusReactionsEnabled) await statusReactions.setTool(payload.name);
|
|
2689
|
-
if (payload.phase === "start") progress.
|
|
2637
|
+
if (payload.phase === "start") progress.progressWorkCounter.noteToolCall(payload.name);
|
|
2690
2638
|
return await progress.progressDraft.pushToolEvent(payload);
|
|
2691
2639
|
},
|
|
2692
2640
|
onItemEvent: async (payload) => {
|
|
2693
2641
|
if (progress.isProgressMode && payload.kind === "preamble") {
|
|
2694
2642
|
if (progress.shouldYieldDraftProgress()) return false;
|
|
2695
2643
|
const headlineVisible = await progress.progressDraft.pushPreambleHeadline(payload.progressText, { itemId: payload.itemId });
|
|
2696
|
-
if (progress.commentaryProgressEnabled) {
|
|
2697
|
-
const accepted = await progress.progressDraft.pushCommentaryProgress(payload.progressText, { itemId: payload.itemId });
|
|
2698
|
-
if (accepted) progress.progressReceipt.noteCommentary(payload.itemId, payload.progressText);
|
|
2699
|
-
return accepted || headlineVisible;
|
|
2700
|
-
}
|
|
2644
|
+
if (progress.commentaryProgressEnabled) return await progress.progressDraft.pushCommentaryProgress(payload.progressText, { itemId: payload.itemId }) || headlineVisible;
|
|
2701
2645
|
return headlineVisible;
|
|
2702
2646
|
}
|
|
2703
2647
|
return await progress.progressDraft.pushItemEvent(payload);
|
|
@@ -2719,8 +2663,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2719
2663
|
});
|
|
2720
2664
|
if (turnResult.dispatched) {
|
|
2721
2665
|
const result = turnResult.dispatchResult;
|
|
2722
|
-
|
|
2723
|
-
counts = result.counts;
|
|
2666
|
+
settledDispatchResult = result;
|
|
2724
2667
|
const agentRunOutcome = readAgentRunTerminalOutcome(result);
|
|
2725
2668
|
agentRunFailed = agentRunOutcome === "failed";
|
|
2726
2669
|
if (agentRunOutcome === "completed" && !sawTerminalFailurePayload && prepared.ctxPayload.ChatType === "channel") clearSlackThreadFailureNotice({
|
|
@@ -2759,12 +2702,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2759
2702
|
if (!finalStream.delivered) dispatchError ??= err;
|
|
2760
2703
|
}
|
|
2761
2704
|
}
|
|
2762
|
-
|
|
2763
|
-
queuedFinal = queuedFinal && (counts.final ?? 0) > 0;
|
|
2764
|
-
const anyReplyDelivered = hasVisibleInboundReplyDispatch({
|
|
2765
|
-
queuedFinal,
|
|
2766
|
-
counts
|
|
2767
|
-
}, {
|
|
2705
|
+
const anyReplyDelivered = hasVisibleInboundReplyDispatch(settledDispatchResult, {
|
|
2768
2706
|
observedReplyDelivery: delivery.observedReplyDelivery,
|
|
2769
2707
|
fallbackDelivered: streamFallbackDelivered
|
|
2770
2708
|
});
|
|
@@ -2786,11 +2724,11 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2786
2724
|
if (dispatchError) throw toErrorObject(dispatchError, "Slack dispatch failed");
|
|
2787
2725
|
if (!anyReplyDelivered && !draftPreviewCommitted.value && !(agentRunFailed && progress.useDraftProgressCard)) {
|
|
2788
2726
|
await draftStream?.clear();
|
|
2789
|
-
await
|
|
2727
|
+
await draftStream?.dropDetachedMessages();
|
|
2790
2728
|
return;
|
|
2791
2729
|
}
|
|
2792
2730
|
if (shouldLogVerbose()) {
|
|
2793
|
-
const finalCount =
|
|
2731
|
+
const finalCount = resolveInboundReplyDispatchCounts(settledDispatchResult).final;
|
|
2794
2732
|
logVerbose(`slack: delivered ${finalCount} reply${finalCount === 1 ? "" : "ies"} to ${prepared.replyTarget}`);
|
|
2795
2733
|
}
|
|
2796
2734
|
}
|
|
@@ -2834,6 +2772,153 @@ function normalizeSlackAppContextEntities(value) {
|
|
|
2834
2772
|
});
|
|
2835
2773
|
}
|
|
2836
2774
|
//#endregion
|
|
2775
|
+
//#region extensions/slack/src/monitor/thread.ts
|
|
2776
|
+
const THREAD_STARTER_CACHE = /* @__PURE__ */ new Map();
|
|
2777
|
+
const THREAD_STARTER_CACHE_TTL_MS = 360 * 6e4;
|
|
2778
|
+
const THREAD_STARTER_CACHE_MAX = 2e3;
|
|
2779
|
+
function evictThreadStarterCache() {
|
|
2780
|
+
const now = asDateTimestampMs(Date.now());
|
|
2781
|
+
if (now === void 0) {
|
|
2782
|
+
THREAD_STARTER_CACHE.clear();
|
|
2783
|
+
return;
|
|
2784
|
+
}
|
|
2785
|
+
for (const [cacheKey, entry] of THREAD_STARTER_CACHE.entries()) if (asDateTimestampMs(entry.expiresAt) === void 0 || entry.expiresAt <= now) THREAD_STARTER_CACHE.delete(cacheKey);
|
|
2786
|
+
pruneMapToMaxSize(THREAD_STARTER_CACHE, THREAD_STARTER_CACHE_MAX);
|
|
2787
|
+
}
|
|
2788
|
+
function formatSlackFilePlaceholder(files) {
|
|
2789
|
+
return `[attached: ${formatSlackFileReferenceList(files)}]`;
|
|
2790
|
+
}
|
|
2791
|
+
function pushUniqueText(parts, value, options = {}) {
|
|
2792
|
+
const text = options.preserveWhitespace ? typeof value === "string" && value.trim().length > 0 ? value : void 0 : normalizeOptionalString(value);
|
|
2793
|
+
if (text && !parts.includes(text)) parts.push(text);
|
|
2794
|
+
}
|
|
2795
|
+
function resolveSlackBlocksFallbackText(blocks) {
|
|
2796
|
+
return resolveSlackBlocksText(blocks)?.text;
|
|
2797
|
+
}
|
|
2798
|
+
function resolveSlackAttachmentFallbackText(attachments) {
|
|
2799
|
+
if (!Array.isArray(attachments) || attachments.length === 0) return;
|
|
2800
|
+
const parts = [];
|
|
2801
|
+
for (const attachment of attachments) {
|
|
2802
|
+
const excludeTableBlocks = isSlackUnfurlAttachment(attachment);
|
|
2803
|
+
const fallbackBlocks = (blocks) => excludeTableBlocks ? blocks?.filter((block) => !hasSlackTableBlock([block])) : blocks;
|
|
2804
|
+
pushUniqueText(parts, attachment.pretext);
|
|
2805
|
+
pushUniqueText(parts, attachment.title);
|
|
2806
|
+
pushUniqueText(parts, attachment.text);
|
|
2807
|
+
if (!(hasSlackTableBlock(attachment.blocks) && normalizeOptionalString(attachment.fallback) === "[no preview available]")) pushUniqueText(parts, attachment.fallback);
|
|
2808
|
+
for (const field of attachment.fields ?? []) {
|
|
2809
|
+
pushUniqueText(parts, field.title);
|
|
2810
|
+
pushUniqueText(parts, field.value);
|
|
2811
|
+
}
|
|
2812
|
+
pushUniqueText(parts, resolveSlackBlocksFallbackText(fallbackBlocks(attachment.blocks)), { preserveWhitespace: true });
|
|
2813
|
+
pushUniqueText(parts, resolveSlackBlocksFallbackText(fallbackBlocks(attachment.message_blocks)), { preserveWhitespace: true });
|
|
2814
|
+
}
|
|
2815
|
+
return parts.length > 0 ? parts.join("\n") : void 0;
|
|
2816
|
+
}
|
|
2817
|
+
function resolveSlackMessageText(message) {
|
|
2818
|
+
const messageText = normalizeOptionalString(message.text) ?? resolveSlackAttachmentFallbackText(message.attachments);
|
|
2819
|
+
return resolveSlackMessageText$1({
|
|
2820
|
+
...message,
|
|
2821
|
+
text: messageText
|
|
2822
|
+
}, { preserveMessageTextWhitespace: true });
|
|
2823
|
+
}
|
|
2824
|
+
async function resolveSlackThreadStarter(params) {
|
|
2825
|
+
evictThreadStarterCache();
|
|
2826
|
+
const cacheKey = JSON.stringify([
|
|
2827
|
+
params.workspaceScope.accountId,
|
|
2828
|
+
params.workspaceScope.teamId,
|
|
2829
|
+
params.channelId,
|
|
2830
|
+
params.threadTs
|
|
2831
|
+
]);
|
|
2832
|
+
const cached = THREAD_STARTER_CACHE.get(cacheKey);
|
|
2833
|
+
if (cached) {
|
|
2834
|
+
const now = asDateTimestampMs(Date.now());
|
|
2835
|
+
if (now !== void 0 && cached.expiresAt > now) return cached.value;
|
|
2836
|
+
THREAD_STARTER_CACHE.delete(cacheKey);
|
|
2837
|
+
}
|
|
2838
|
+
try {
|
|
2839
|
+
const message = (await params.client.conversations.replies({
|
|
2840
|
+
channel: params.channelId,
|
|
2841
|
+
ts: params.threadTs,
|
|
2842
|
+
limit: 1,
|
|
2843
|
+
inclusive: true
|
|
2844
|
+
}))?.messages?.[0];
|
|
2845
|
+
const text = message ? resolveSlackMessageText(message) : void 0;
|
|
2846
|
+
const files = message?.files?.length ? message.files : void 0;
|
|
2847
|
+
if (!message || !text && !files) return null;
|
|
2848
|
+
const starter = {
|
|
2849
|
+
text: text || formatSlackFilePlaceholder(files),
|
|
2850
|
+
userId: message.user,
|
|
2851
|
+
botId: message.bot_id,
|
|
2852
|
+
ts: message.ts,
|
|
2853
|
+
files
|
|
2854
|
+
};
|
|
2855
|
+
const expiresAt = resolveExpiresAtMsFromDurationMs(THREAD_STARTER_CACHE_TTL_MS);
|
|
2856
|
+
if (expiresAt !== void 0) {
|
|
2857
|
+
if (THREAD_STARTER_CACHE.has(cacheKey)) THREAD_STARTER_CACHE.delete(cacheKey);
|
|
2858
|
+
THREAD_STARTER_CACHE.set(cacheKey, {
|
|
2859
|
+
value: starter,
|
|
2860
|
+
expiresAt
|
|
2861
|
+
});
|
|
2862
|
+
evictThreadStarterCache();
|
|
2863
|
+
}
|
|
2864
|
+
return starter;
|
|
2865
|
+
} catch (err) {
|
|
2866
|
+
logVerbose$1(`slack thread starter fetch failed channel=${params.channelId} ts=${params.threadTs}: ${formatErrorMessage(err)}`);
|
|
2867
|
+
return null;
|
|
2868
|
+
}
|
|
2869
|
+
}
|
|
2870
|
+
const SLACK_THREAD_HISTORY_MAX_PAGES = 3;
|
|
2871
|
+
/**
|
|
2872
|
+
* Fetches the most recent messages in a Slack thread (excluding the current message).
|
|
2873
|
+
* Used to populate thread context when a new thread session starts.
|
|
2874
|
+
*
|
|
2875
|
+
* Uses cursor pagination and keeps only the latest N retained messages when the full
|
|
2876
|
+
* thread fits in the bounded fetch window.
|
|
2877
|
+
*/
|
|
2878
|
+
async function resolveSlackThreadHistory(params) {
|
|
2879
|
+
const maxMessages = params.limit ?? 20;
|
|
2880
|
+
if (!Number.isFinite(maxMessages) || maxMessages <= 0) return [];
|
|
2881
|
+
const fetchLimit = 200;
|
|
2882
|
+
const retained = [];
|
|
2883
|
+
let cursor;
|
|
2884
|
+
let pagesFetched = 0;
|
|
2885
|
+
try {
|
|
2886
|
+
do {
|
|
2887
|
+
pagesFetched += 1;
|
|
2888
|
+
const response = await params.client.conversations.replies({
|
|
2889
|
+
channel: params.channelId,
|
|
2890
|
+
ts: params.threadTs,
|
|
2891
|
+
limit: fetchLimit,
|
|
2892
|
+
inclusive: true,
|
|
2893
|
+
...cursor ? { cursor } : {}
|
|
2894
|
+
});
|
|
2895
|
+
for (const msg of response.messages ?? []) {
|
|
2896
|
+
const text = resolveSlackMessageText(msg);
|
|
2897
|
+
if (!text && !msg.files?.length) continue;
|
|
2898
|
+
if (params.currentMessageTs && msg.ts === params.currentMessageTs) continue;
|
|
2899
|
+
retained.push([msg, text]);
|
|
2900
|
+
}
|
|
2901
|
+
if (retained.length > maxMessages) retained.splice(0, retained.length - maxMessages);
|
|
2902
|
+
const next = response.response_metadata?.next_cursor;
|
|
2903
|
+
cursor = typeof next === "string" && next.trim().length > 0 ? next.trim() : void 0;
|
|
2904
|
+
} while (cursor && pagesFetched < SLACK_THREAD_HISTORY_MAX_PAGES);
|
|
2905
|
+
if (cursor) {
|
|
2906
|
+
logVerbose$1(`slack thread history capped channel=${params.channelId} ts=${params.threadTs} pages=${SLACK_THREAD_HISTORY_MAX_PAGES}`);
|
|
2907
|
+
return [];
|
|
2908
|
+
}
|
|
2909
|
+
return retained.map(([message, text]) => ({
|
|
2910
|
+
text: text ?? formatSlackFilePlaceholder(message.files),
|
|
2911
|
+
userId: message.user,
|
|
2912
|
+
botId: message.bot_id,
|
|
2913
|
+
ts: message.ts,
|
|
2914
|
+
files: message.files
|
|
2915
|
+
}));
|
|
2916
|
+
} catch (err) {
|
|
2917
|
+
logVerbose$1(`slack thread history fetch failed channel=${params.channelId} ts=${params.threadTs}: ${formatErrorMessage(err)}`);
|
|
2918
|
+
return [];
|
|
2919
|
+
}
|
|
2920
|
+
}
|
|
2921
|
+
//#endregion
|
|
2837
2922
|
//#region extensions/slack/src/monitor/message-handler/preflight-audio.ts
|
|
2838
2923
|
function isSlackAudioFile(file) {
|
|
2839
2924
|
if (file.subtype === "slack_audio") return true;
|
|
@@ -2849,7 +2934,7 @@ function findCaptionlessSlackAudioFile(message) {
|
|
|
2849
2934
|
return message.files?.slice(0, 8).find(isSlackAudioFile);
|
|
2850
2935
|
}
|
|
2851
2936
|
function formatSlackAudioTranscriptForAgent(params) {
|
|
2852
|
-
return [
|
|
2937
|
+
return [formatAudioTranscriptForAgent(params.transcript), params.rawBody].filter(Boolean).join("\n");
|
|
2853
2938
|
}
|
|
2854
2939
|
async function resolveSlackPreflightAudioTranscript(params) {
|
|
2855
2940
|
const mediaIndex = params.media.findIndex((entry) => entry.contentType?.toLowerCase().startsWith("audio/"));
|
|
@@ -2884,7 +2969,24 @@ async function discardSlackPreflightMedia(media) {
|
|
|
2884
2969
|
const SLACK_MENTION_RESOLUTION_CONCURRENCY = 4;
|
|
2885
2970
|
const SLACK_MENTION_RESOLUTION_MAX_LOOKUPS_PER_MESSAGE = 20;
|
|
2886
2971
|
const SLACK_USER_MENTION_RE$1 = /<@([A-Z0-9]+)(?:\|[^>]+)?>/gi;
|
|
2887
|
-
const
|
|
2972
|
+
const MAX_SLACK_UNAVAILABLE_FILE_TEXT_CHARS = 2e3;
|
|
2973
|
+
const loadSlackMediaModule$1 = createLazyRuntimeModule(() => import("./actions-BI7JkfVm.js").then((n) => n._));
|
|
2974
|
+
function formatSlackUnavailableMedia(params) {
|
|
2975
|
+
let fileReferences = params.files?.map((file) => `${formatSlackFileReference(file)} unavailable (${file.reason})`).join(", ");
|
|
2976
|
+
if (fileReferences && fileReferences.length > MAX_SLACK_UNAVAILABLE_FILE_TEXT_CHARS) fileReferences = `${truncateUtf16Safe(fileReferences, MAX_SLACK_UNAVAILABLE_FILE_TEXT_CHARS)}; … (file references truncated)`;
|
|
2977
|
+
const fileBlock = fileReferences ? `[Slack file: ${fileReferences}]` : void 0;
|
|
2978
|
+
const body = [params.body, fileBlock].filter(Boolean).join("\n");
|
|
2979
|
+
if (params.unavailableMediaCount === 0) return body;
|
|
2980
|
+
const notice = `[slack ${params.unavailableMediaCount > 1 ? `${params.unavailableMediaCount} attachments` : "attachment"} unavailable]`;
|
|
2981
|
+
return params.prependUnavailable ? [
|
|
2982
|
+
notice,
|
|
2983
|
+
fileBlock,
|
|
2984
|
+
params.body
|
|
2985
|
+
].filter(Boolean).join("\n") : formatInboundMediaUnavailableText({
|
|
2986
|
+
body,
|
|
2987
|
+
notice
|
|
2988
|
+
});
|
|
2989
|
+
}
|
|
2888
2990
|
function collectUniqueSlackMentionIds$1(texts) {
|
|
2889
2991
|
const seen = /* @__PURE__ */ new Set();
|
|
2890
2992
|
const mentionIds = [];
|
|
@@ -2922,8 +3024,9 @@ async function resolveSlackMessageContent(params) {
|
|
|
2922
3024
|
isThreadReply: params.isThreadReply,
|
|
2923
3025
|
threadStarter: params.threadStarter
|
|
2924
3026
|
});
|
|
2925
|
-
const
|
|
3027
|
+
const attachmentContent = ownFiles?.length || params.message.attachments?.length ? await loadSlackMediaModule$1().then(({ resolveSlackAttachmentContent }) => resolveSlackAttachmentContent({
|
|
2926
3028
|
files: ownFiles,
|
|
3029
|
+
attachments: params.message.attachments,
|
|
2927
3030
|
client: params.client,
|
|
2928
3031
|
token: params.botToken,
|
|
2929
3032
|
maxBytes: params.mediaMaxBytes,
|
|
@@ -2931,30 +3034,9 @@ async function resolveSlackMessageContent(params) {
|
|
|
2931
3034
|
totalTimeoutMs: params.mediaTotalTimeoutMs,
|
|
2932
3035
|
abortSignal: params.abortSignal,
|
|
2933
3036
|
preloadedMedia: params.preloadedMedia
|
|
2934
|
-
})) :
|
|
2935
|
-
const
|
|
2936
|
-
|
|
2937
|
-
client: params.client,
|
|
2938
|
-
token: params.botToken,
|
|
2939
|
-
maxBytes: params.mediaMaxBytes,
|
|
2940
|
-
readIdleTimeoutMs: params.mediaReadIdleTimeoutMs,
|
|
2941
|
-
totalTimeoutMs: params.mediaTotalTimeoutMs,
|
|
2942
|
-
abortSignal: params.abortSignal
|
|
2943
|
-
})) : Promise.resolve(null);
|
|
2944
|
-
const [media, attachmentContent] = await Promise.all([mediaPromise, attachmentContentPromise]);
|
|
2945
|
-
const mergedMedia = [...media ?? [], ...attachmentContent?.media ?? []];
|
|
2946
|
-
const effectiveDirectMedia = mergedMedia.length > 0 ? mergedMedia : null;
|
|
2947
|
-
const mediaPlaceholder = effectiveDirectMedia ? effectiveDirectMedia.map((item) => item.placeholder).join(" ") : void 0;
|
|
2948
|
-
const fallbackFileIds = /* @__PURE__ */ new Set();
|
|
2949
|
-
const fallbackFiles = [...ownFiles ?? [], ...attachmentContent?.files ?? []].filter((file) => {
|
|
2950
|
-
const fileId = normalizeOptionalString(file.id);
|
|
2951
|
-
if (!fileId) return true;
|
|
2952
|
-
if (fallbackFileIds.has(fileId)) return false;
|
|
2953
|
-
fallbackFileIds.add(fileId);
|
|
2954
|
-
return true;
|
|
2955
|
-
});
|
|
2956
|
-
const fileOnlyFallback = !mediaPlaceholder && fallbackFiles.length > 0 ? fallbackFiles.slice(0, 8).map((file) => formatSlackFileReference(file)).join(", ") : void 0;
|
|
2957
|
-
const fileOnlyPlaceholder = fileOnlyFallback ? `[Slack file: ${fileOnlyFallback}]` : void 0;
|
|
3037
|
+
})) : null;
|
|
3038
|
+
const effectiveDirectMedia = attachmentContent?.media.length ? attachmentContent.media : null;
|
|
3039
|
+
const mediaPlaceholder = effectiveDirectMedia?.map((item) => item.placeholder).join(" ");
|
|
2958
3040
|
let botAttachmentText;
|
|
2959
3041
|
if (params.isBotMessage && !attachmentContent?.text) {
|
|
2960
3042
|
const botAttachmentTextParts = [];
|
|
@@ -2965,7 +3047,7 @@ async function resolveSlackMessageContent(params) {
|
|
|
2965
3047
|
botAttachmentText = botAttachmentTextParts.length > 0 ? botAttachmentTextParts.join("\n") : void 0;
|
|
2966
3048
|
}
|
|
2967
3049
|
const textParts = [
|
|
2968
|
-
resolveSlackMessageText(params.message),
|
|
3050
|
+
resolveSlackMessageText$1(params.message),
|
|
2969
3051
|
attachmentContent?.text,
|
|
2970
3052
|
botAttachmentText
|
|
2971
3053
|
];
|
|
@@ -2991,23 +3073,20 @@ async function resolveSlackMessageContent(params) {
|
|
|
2991
3073
|
renderedMentions.set(result.userId, result.rendered);
|
|
2992
3074
|
}
|
|
2993
3075
|
}
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
body: rawBody,
|
|
3004
|
-
notice: `[slack ${unavailableImageCount > 1 ? `${unavailableImageCount} forwarded images` : "forwarded image"} unavailable]`
|
|
3076
|
+
const rawBody = formatSlackUnavailableMedia({
|
|
3077
|
+
body: [
|
|
3078
|
+
renderSlackUserMentions(textParts[0], renderedMentions),
|
|
3079
|
+
renderSlackUserMentions(textParts[1], renderedMentions),
|
|
3080
|
+
renderSlackUserMentions(textParts[2], renderedMentions),
|
|
3081
|
+
mediaPlaceholder
|
|
3082
|
+
].filter(Boolean).join("\n") || "",
|
|
3083
|
+
files: attachmentContent?.files,
|
|
3084
|
+
unavailableMediaCount: attachmentContent?.unavailableMediaCount ?? 0
|
|
3005
3085
|
});
|
|
3006
|
-
|
|
3007
|
-
return {
|
|
3086
|
+
return rawBody ? {
|
|
3008
3087
|
rawBody,
|
|
3009
3088
|
effectiveDirectMedia
|
|
3010
|
-
};
|
|
3089
|
+
} : null;
|
|
3011
3090
|
}
|
|
3012
3091
|
//#endregion
|
|
3013
3092
|
//#region extensions/slack/src/monitor/message-handler/prepare-dm-history.ts
|
|
@@ -3083,62 +3162,6 @@ async function resolveSlackDmHistoryContext(params) {
|
|
|
3083
3162
|
}
|
|
3084
3163
|
//#endregion
|
|
3085
3164
|
//#region extensions/slack/src/monitor/message-handler/prepare-routing.ts
|
|
3086
|
-
const slackRouteBindingConfigCache = /* @__PURE__ */ new WeakMap();
|
|
3087
|
-
function slackTargetDefaultKindForPeer(kind) {
|
|
3088
|
-
return kind === "direct" ? "user" : "channel";
|
|
3089
|
-
}
|
|
3090
|
-
function slackTargetKindMatchesPeer(peerKind, targetKind) {
|
|
3091
|
-
if (targetKind === "user") return peerKind === "direct";
|
|
3092
|
-
return peerKind === "channel" || peerKind === "group";
|
|
3093
|
-
}
|
|
3094
|
-
function normalizeSlackRouteBindingPeer(peer) {
|
|
3095
|
-
const rawId = peer.id.trim();
|
|
3096
|
-
if (!rawId || rawId === "*") return peer;
|
|
3097
|
-
const target = (() => {
|
|
3098
|
-
try {
|
|
3099
|
-
return parseSlackTarget(rawId, { defaultKind: slackTargetDefaultKindForPeer(peer.kind) });
|
|
3100
|
-
} catch {
|
|
3101
|
-
return;
|
|
3102
|
-
}
|
|
3103
|
-
})();
|
|
3104
|
-
if (!target || !slackTargetKindMatchesPeer(peer.kind, target.kind)) return peer;
|
|
3105
|
-
const normalizedId = target.teamId ? `team:${target.teamId}:${target.kind}:${target.id}` : target.id;
|
|
3106
|
-
return normalizedId === peer.id ? peer : {
|
|
3107
|
-
...peer,
|
|
3108
|
-
id: normalizedId
|
|
3109
|
-
};
|
|
3110
|
-
}
|
|
3111
|
-
function normalizeSlackRouteBindingConfig(cfg) {
|
|
3112
|
-
const bindings = cfg.bindings;
|
|
3113
|
-
const cached = slackRouteBindingConfigCache.get(cfg);
|
|
3114
|
-
if (cached && cached.bindingsRef === bindings) return cached.normalizedCfg;
|
|
3115
|
-
if (!Array.isArray(bindings)) return cfg;
|
|
3116
|
-
let changed = false;
|
|
3117
|
-
const normalizedBindings = bindings.map((binding) => {
|
|
3118
|
-
if (binding.type === "acp" || binding.match.channel.trim().toLowerCase() !== "slack") return binding;
|
|
3119
|
-
const peer = binding.match.peer;
|
|
3120
|
-
if (!peer) return binding;
|
|
3121
|
-
const normalizedPeer = normalizeSlackRouteBindingPeer(peer);
|
|
3122
|
-
if (normalizedPeer === peer) return binding;
|
|
3123
|
-
changed = true;
|
|
3124
|
-
return {
|
|
3125
|
-
...binding,
|
|
3126
|
-
match: {
|
|
3127
|
-
...binding.match,
|
|
3128
|
-
peer: normalizedPeer
|
|
3129
|
-
}
|
|
3130
|
-
};
|
|
3131
|
-
});
|
|
3132
|
-
const normalizedCfg = changed ? {
|
|
3133
|
-
...cfg,
|
|
3134
|
-
bindings: normalizedBindings
|
|
3135
|
-
} : cfg;
|
|
3136
|
-
slackRouteBindingConfigCache.set(cfg, {
|
|
3137
|
-
bindingsRef: bindings,
|
|
3138
|
-
normalizedCfg
|
|
3139
|
-
});
|
|
3140
|
-
return normalizedCfg;
|
|
3141
|
-
}
|
|
3142
3165
|
function resolveSlackBaseConversationId(params) {
|
|
3143
3166
|
return qualifySlackConversationId(params.isDirectMessage ? `user:${params.message.user ?? "unknown"}` : params.message.channel, params.eventScope);
|
|
3144
3167
|
}
|
|
@@ -3197,44 +3220,18 @@ function resolveSlackRoutingContext(params) {
|
|
|
3197
3220
|
eventScope
|
|
3198
3221
|
});
|
|
3199
3222
|
const runtimeBindingThreadId = routedThreadId ?? (isDirectMessage && isThreadReply ? threadTs : void 0);
|
|
3200
|
-
const
|
|
3201
|
-
|
|
3202
|
-
conversation: {
|
|
3203
|
-
channel: "slack",
|
|
3204
|
-
accountId: account.accountId,
|
|
3205
|
-
conversationId: runtimeBindingThreadId,
|
|
3206
|
-
parentConversationId: baseConversationId
|
|
3207
|
-
}
|
|
3208
|
-
}) : null;
|
|
3209
|
-
const runtimeRoute = eventScope ? {
|
|
3210
|
-
route,
|
|
3211
|
-
bindingRecord: null,
|
|
3212
|
-
boundSessionKey: void 0
|
|
3213
|
-
} : boundThreadRoute?.boundSessionKey || boundThreadRoute?.bindingRecord ? boundThreadRoute : resolveRuntimeConversationBindingRoute({
|
|
3223
|
+
const bindingRoute = resolveSlackConversationBindingRoute({
|
|
3224
|
+
cfg: ctx.cfg,
|
|
3214
3225
|
route,
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
}
|
|
3226
|
+
accountId: account.accountId,
|
|
3227
|
+
baseConversationId,
|
|
3228
|
+
runtimeBindingThreadId,
|
|
3229
|
+
bindingsEnabled: !eventScope
|
|
3220
3230
|
});
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
const configuredRoute = resolveConfiguredBindingRoute({
|
|
3226
|
-
cfg: ctx.cfg,
|
|
3227
|
-
route,
|
|
3228
|
-
conversation: {
|
|
3229
|
-
channel: "slack",
|
|
3230
|
-
accountId: account.accountId,
|
|
3231
|
-
conversationId: baseConversationId
|
|
3232
|
-
}
|
|
3233
|
-
});
|
|
3234
|
-
configuredBinding = configuredRoute.bindingResolution;
|
|
3235
|
-
configuredBindingSessionKey = configuredRoute.boundSessionKey ?? "";
|
|
3236
|
-
route = configuredRoute.route;
|
|
3237
|
-
}
|
|
3231
|
+
const runtimeRoute = bindingRoute.runtimeRoute;
|
|
3232
|
+
const configuredBinding = bindingRoute.configuredRoute?.bindingResolution ?? null;
|
|
3233
|
+
const configuredBindingSessionKey = bindingRoute.configuredRoute?.boundSessionKey ?? "";
|
|
3234
|
+
route = bindingRoute.route;
|
|
3238
3235
|
const threadKeys = runtimeRoute.boundSessionKey || configuredBindingSessionKey ? {
|
|
3239
3236
|
sessionKey: route.sessionKey,
|
|
3240
3237
|
parentSessionKey: void 0
|
|
@@ -3317,7 +3314,7 @@ function formatSlackThreadLabelSnippet(text) {
|
|
|
3317
3314
|
}
|
|
3318
3315
|
//#endregion
|
|
3319
3316
|
//#region extensions/slack/src/monitor/message-handler/prepare-thread-context.ts
|
|
3320
|
-
const loadSlackMediaModule = createLazyRuntimeModule(() => import("./actions-
|
|
3317
|
+
const loadSlackMediaModule = createLazyRuntimeModule(() => import("./actions-BI7JkfVm.js").then((n) => n._));
|
|
3321
3318
|
const SLACK_THREAD_CONTEXT_USER_LOOKUP_CONCURRENCY = 4;
|
|
3322
3319
|
function resolveSlackThreadSessionFreshness(params) {
|
|
3323
3320
|
return params.ctx.channelRuntime?.session?.resolveEntryResetFreshness?.({
|
|
@@ -3429,13 +3426,20 @@ async function resolveSlackThreadContextData(params) {
|
|
|
3429
3426
|
const snippet = formatSlackThreadLabelSnippet(starter.text);
|
|
3430
3427
|
threadLabel = `Slack thread ${params.roomLabel}${snippet ? `: ${snippet}` : ""}`;
|
|
3431
3428
|
if (shouldSeedInitialThreadContext && !params.effectiveDirectMedia && starter.files && starter.files.length > 0) {
|
|
3432
|
-
const {
|
|
3433
|
-
|
|
3429
|
+
const { resolveSlackAttachmentContent } = await loadSlackMediaModule();
|
|
3430
|
+
const attachmentContent = await resolveSlackAttachmentContent({
|
|
3434
3431
|
files: starter.files,
|
|
3435
3432
|
client: params.eventScope?.client ?? params.ctx.app.client,
|
|
3436
3433
|
token: params.ctx.botToken,
|
|
3437
3434
|
maxBytes: params.ctx.mediaMaxBytes
|
|
3438
3435
|
});
|
|
3436
|
+
threadStarterMedia = attachmentContent?.media.length ? attachmentContent.media : null;
|
|
3437
|
+
if (attachmentContent) threadStarterBody = formatSlackUnavailableMedia({
|
|
3438
|
+
body: threadStarterBody,
|
|
3439
|
+
files: attachmentContent.files,
|
|
3440
|
+
unavailableMediaCount: attachmentContent.unavailableMediaCount,
|
|
3441
|
+
prependUnavailable: true
|
|
3442
|
+
});
|
|
3439
3443
|
if (threadStarterMedia) logVerbose(`slack: hydrated thread starter file ${threadStarterMedia.map((item) => item.placeholder).join(", ")} from root message`);
|
|
3440
3444
|
}
|
|
3441
3445
|
} else threadLabel = `Slack thread ${params.roomLabel}`;
|
|
@@ -3456,14 +3460,20 @@ async function resolveSlackThreadContextData(params) {
|
|
|
3456
3460
|
const threadInitialHistoryLimit = params.account.config?.thread?.initialHistoryLimit ?? 20;
|
|
3457
3461
|
if (threadInitialHistoryLimit > 0 && shouldLoadInitialThreadHistory) {
|
|
3458
3462
|
const currentBotRootTs = starter?.ts ?? params.threadTs;
|
|
3463
|
+
const threadHistory = await resolveSlackThreadHistory({
|
|
3464
|
+
channelId: params.message.channel,
|
|
3465
|
+
threadTs: params.threadTs,
|
|
3466
|
+
client: params.eventScope?.client ?? params.ctx.app.client,
|
|
3467
|
+
currentMessageTs: params.message.ts,
|
|
3468
|
+
limit: threadInitialHistoryLimit
|
|
3469
|
+
});
|
|
3470
|
+
const enrichedStarter = starter && threadStarterBody && threadStarterBody !== starter.text ? {
|
|
3471
|
+
...starter,
|
|
3472
|
+
text: threadStarterBody,
|
|
3473
|
+
ts: currentBotRootTs
|
|
3474
|
+
} : null;
|
|
3459
3475
|
const threadHistoryWithBotRoot = ensureSlackThreadHistoryHasBotRoot({
|
|
3460
|
-
history:
|
|
3461
|
-
channelId: params.message.channel,
|
|
3462
|
-
threadTs: params.threadTs,
|
|
3463
|
-
client: params.eventScope?.client ?? params.ctx.app.client,
|
|
3464
|
-
currentMessageTs: params.message.ts,
|
|
3465
|
-
limit: threadInitialHistoryLimit
|
|
3466
|
-
}),
|
|
3476
|
+
history: enrichedStarter && !threadHistory.some((entry) => entry.ts === currentBotRootTs) ? [enrichedStarter, ...threadHistory.length >= threadInitialHistoryLimit ? threadHistory.slice(1) : threadHistory] : threadHistory,
|
|
3467
3477
|
includeBotStarterAsRootContext,
|
|
3468
3478
|
threadStarter: starter ? {
|
|
3469
3479
|
...starter,
|
|
@@ -3522,7 +3532,7 @@ async function resolveSlackThreadContextData(params) {
|
|
|
3522
3532
|
});
|
|
3523
3533
|
const role = isCurrentBot || isOtherBot || Boolean(historyMsg.botId) ? "assistant" : "user";
|
|
3524
3534
|
const msgSenderName = isCurrentBot ? "Bot (this assistant)" : msgUser?.name ?? (historyMsg.botId ? `Bot (${historyMsg.botId})` : "Unknown");
|
|
3525
|
-
const msgWithId = `${historyMsg.text}\n[slack message id: ${historyMsg.ts ?? "unknown"} channel: ${params.message.channel}]`;
|
|
3535
|
+
const msgWithId = `${historyMsg.ts === currentBotRootTs && threadStarterBody ? threadStarterBody : historyMsg.text}\n[slack message id: ${historyMsg.ts ?? "unknown"} channel: ${params.message.channel}]`;
|
|
3526
3536
|
historyParts.push(formatInboundEnvelope({
|
|
3527
3537
|
channel: "Slack",
|
|
3528
3538
|
from: `${msgSenderName} (${role})`,
|
|
@@ -4468,6 +4478,7 @@ async function prepareSlackMessage(params) {
|
|
|
4468
4478
|
workspaceName
|
|
4469
4479
|
}) : void 0;
|
|
4470
4480
|
const senderName = await resolveSenderName();
|
|
4481
|
+
const conversationAvatar = isDirectMessage && message.user ? ctx.resolveUserAvatar(message.user, opts.eventScope) : void 0;
|
|
4471
4482
|
const preview = truncateUtf16Safe(bodyForAgent.replace(/\s+/g, " "), 160);
|
|
4472
4483
|
const inboundLabel = isDirectMessage ? `Slack DM from ${senderName}` : `Slack message in ${roomLabel} from ${senderName}`;
|
|
4473
4484
|
const slackFrom = isDirectMessage ? `slack:${message.user}` : isRoom ? `slack:channel:${message.channel}` : `slack:group:${message.channel}`;
|
|
@@ -4600,10 +4611,19 @@ async function prepareSlackMessage(params) {
|
|
|
4600
4611
|
conversation: {
|
|
4601
4612
|
kind: chatType,
|
|
4602
4613
|
id: message.channel,
|
|
4614
|
+
routePeer: {
|
|
4615
|
+
kind: chatType,
|
|
4616
|
+
id: qualifySlackRoutePeerId({
|
|
4617
|
+
id: isDirectMessage ? message.user ?? "unknown" : message.channel,
|
|
4618
|
+
kind: isDirectMessage ? "user" : "channel",
|
|
4619
|
+
eventScope: opts.eventScope
|
|
4620
|
+
})
|
|
4621
|
+
},
|
|
4603
4622
|
label: envelopeFrom,
|
|
4604
4623
|
spaceId: opts.eventScope?.teamId || ctx.teamId || void 0,
|
|
4605
4624
|
threadId: boundMessageThreadId,
|
|
4606
|
-
nativeChannelId: message.channel
|
|
4625
|
+
nativeChannelId: message.channel,
|
|
4626
|
+
avatar: conversationAvatar
|
|
4607
4627
|
},
|
|
4608
4628
|
route: {
|
|
4609
4629
|
agentId: route.agentId,
|