@openclaw/slack 2026.8.1-beta.2 → 2026.9.1-beta.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-BoSeX09X.js} +76 -83
- package/dist/action-runtime.runtime-Dpa16J87.js +2 -0
- package/dist/{actions-BTDXwwE3.js → actions-XdQyjG_p.js} +134 -262
- package/dist/api.js +14 -14
- package/dist/{approval-handler.runtime-CJaNzAq2.js → approval-handler.runtime-DxXfGX_Z.js} +53 -174
- package/dist/{channel-D_tovcUL.js → channel-C_vnTgxo.js} +117 -72
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-type-B9MSdoGN.js → channel-type-j-2lalcC.js} +3 -7
- package/dist/{channel.setup-Bch9dYmA.js → channel.setup-aal8tokM.js} +34 -49
- package/dist/{config-schema-xto5jFIx.js → config-schema-CN3XZRX5.js} +23 -7
- 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-lC6X_Ru-.js} +2 -2
- package/dist/{group-policy-c4RP9bjc.js → group-policy-CU1tEGpS.js} +583 -642
- package/dist/{message-tool-api-BykQB4AU.js → message-tool-api-CWosHSi5.js} +6 -5
- package/dist/message-tool-api.js +1 -1
- package/dist/{monitor-1nF1NtqT.js → monitor-DrNCGneD.js} +3 -3
- package/dist/{outbound-adapter-S81tsswN.js → outbound-adapter-DkT2vUE9.js} +50 -19
- package/dist/{pipeline.runtime-BvYsM5JO.js → pipeline.runtime-CRRng_Nw.js} +440 -451
- package/dist/{policy-TapwbeaT.js → policy-BoP6t88v.js} +1 -1
- package/dist/{probe-HoEg_WxB.js → probe-4_aHtVT3.js} +2 -21
- package/dist/{provider-CDNvBXUi.js → provider-D4nDgxCh.js} +240 -95
- package/dist/{relay-source-C9leF11u.js → relay-source-CEmze11m.js} +1 -1
- package/dist/{replies-CeOfv82I.js → replies-D9XMM_S0.js} +47 -26
- package/dist/{resolve-channels-CNPrxaXY.js → resolve-channels-DSamDgVs.js} +1 -1
- package/dist/{resolve-users-Dzomuwnr.js → resolve-users-CIzwbaJR.js} +1 -1
- package/dist/runtime-api.js +11 -11
- package/dist/{scopes-cYXKkrRD.js → scopes-BBrUzpBH.js} +1 -1
- package/dist/security-contract-api.js +1 -1
- package/dist/{send-Nor0iBwY.js → send-DtjEnlLh.js} +86 -98
- package/dist/{send.runtime-BmgNe6S9.js → send.runtime-DQeNKa2J.js} +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-CbX1-Knh.js → setup-surface-CsBCM4rP.js} +6 -6
- package/dist/{shared-zdT5AMp-.js → shared-D9GeeR9K.js} +33 -9
- package/dist/{block-text-YtiNkqmx.js → slack-client-kind-hSfjXyUM.js} +17 -2
- package/dist/{slash-dispatch.runtime-Bnr9GR1S.js → slash-dispatch.runtime-Chr3YHnT.js} +3 -3
- 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 +43 -1
- 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/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 { B as SLACK_TEXT_LIMIT, G as truncateSlackText, K as truncateSlackTextByUtf8Bytes, L as SLACK_EDIT_TEXT_MAX_BYTES, N as buildSlackBlocksFallbackText, O as hasSlackNativeDataBlock, S as resolveSlackReplyRenderPlan, W as countSlackTextUtf8Bytes, Z as SLACK_SESSION_LINK_ACTION_ID, a as qualifySlackConversationId, ct as escapeSlackMrkdwn, d as normalizeSlackAllowOwnerEntry, o as qualifySlackRoutePeerId, ot as normalizeSlackOutboundText, p as resolveSlackAllowListMatch, s as resolveSlackEnterpriseMainDmSessionKey, u as normalizeAllowListLower } from "./group-policy-CU1tEGpS.js";
|
|
4
|
+
import { r as formatSlackError } from "./probe-4_aHtVT3.js";
|
|
6
5
|
import { n as resolveSlackStreamingMode, t as resolveSlackNativeStreaming } from "./streaming-compat-B-e0mqM0.js";
|
|
7
|
-
import {
|
|
8
|
-
import { a as resolveSlackMessageText } from "./
|
|
9
|
-
import { c as hasSlackThreadFailureNotice, d as recordSlackThreadFailureNotice, f as recordSlackThreadParticipation, l as hasSlackThreadParticipation,
|
|
10
|
-
import { C as
|
|
11
|
-
import { n as resolveSlackChannelConfig } from "./policy-
|
|
12
|
-
import { a as resolveDeliveredSlackReplyThreadTs, i as readSlackReplyBlocks, n as deliverReplies, o as resolveSlackThreadTs, s as
|
|
6
|
+
import { a as editSlackRenderedMessage, b as formatSlackFileReferenceList, d as reactSlackMessage, i as editSlackMessage, m as removeSlackReaction, n as deleteSlackMessage, v as logVerbose$1, x as buildSlackEditTextPayload, y as formatSlackFileReference } from "./actions-XdQyjG_p.js";
|
|
7
|
+
import { a as hasSlackTableBlock, c as resolveSlackMessageText$1, o as isSlackUnfurlAttachment, s as resolveSlackBlocksText } from "./slack-client-kind-hSfjXyUM.js";
|
|
8
|
+
import { c as hasSlackThreadFailureNotice, d as recordSlackThreadFailureNotice, f as recordSlackThreadParticipation, l as hasSlackThreadParticipation, m as buildSlackNativeDataDeliveryPlan, o as clearSlackThreadFailureNotice, r as sendMessageSlack, u as hasSlackThreadParticipationWithPersistence } from "./send-DtjEnlLh.js";
|
|
9
|
+
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-D4nDgxCh.js";
|
|
10
|
+
import { n as resolveSlackChannelConfig } from "./policy-BoP6t88v.js";
|
|
11
|
+
import { a as resolveDeliveredSlackReplyThreadTs, c as emitSlackMessageSentHooks, i as readSlackReplyBlocks, n as deliverReplies, o as resolveSlackThreadTs, s as sanitizeSlackMonitorReplyPayload, t as createSlackReplyDeliveryPlan } from "./replies-D9XMM_S0.js";
|
|
13
12
|
import { asOptionalRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
14
13
|
import { resolveAgentRoute, resolveInboundLastRouteSessionKey, resolveThreadSessionKeys } from "openclaw/plugin-sdk/routing";
|
|
15
|
-
import { buildChannelProgressDraftLine, buildChannelProgressDraftLineForEntry, createChannelMessageReplyPipeline, createChannelProgressDraftCompositor,
|
|
14
|
+
import { buildChannelProgressDraftLine, buildChannelProgressDraftLineForEntry, createChannelMessageReplyPipeline, createChannelProgressDraftCompositor, createChannelProgressWorkCounter, createFinalizableDraftStreamControlsForState, defineFinalizableLivePreviewAdapter, deliverWithFinalizableLivePreviewAdapter, formatChannelProgressDraftText, formatPlanChecklistLines, isChannelProgressDraftWorkToolName, resolveAgentOutboundIdentity, resolveChannelMessageSourceReplyDeliveryMode, resolveChannelProgressDraftConfig, resolveChannelProgressDraftMaxLineChars, resolveChannelStreamingBlockEnabled, resolveChannelStreamingPreviewToolProgress, resolveChannelStreamingSuppressDefaultToolProgressMessages } from "openclaw/plugin-sdk/channel-outbound";
|
|
16
15
|
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
17
16
|
import { danger, logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
|
|
17
|
+
import { sanitizeAssistantVisibleText } from "openclaw/plugin-sdk/text-chunking";
|
|
18
18
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
19
19
|
import { createHash } from "node:crypto";
|
|
20
|
+
import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
|
|
21
|
+
import { ensureConfiguredBindingRouteReady } from "openclaw/plugin-sdk/conversation-runtime";
|
|
20
22
|
import fs from "node:fs/promises";
|
|
23
|
+
import { runTasksWithConcurrency } from "openclaw/plugin-sdk/concurrency-runtime";
|
|
21
24
|
import { formatErrorMessage, toErrorObject } from "openclaw/plugin-sdk/error-runtime";
|
|
22
|
-
import { asDateTimestampMs, asFiniteNumberInRange, parseStrictFiniteNumber, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
|
|
23
25
|
import { buildTtsSupplementMediaPayload, getReplyPayloadTtsSupplement, isReplyPayloadNonTerminalToolErrorWarning, resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
|
|
24
26
|
import { filterSupplementalContextItems, resolvePinnedMainDmOwnerFromAllowlist, shouldIncludeSupplementalContext } from "openclaw/plugin-sdk/security-runtime";
|
|
25
27
|
import { mimeTypeFromFilePath } from "openclaw/plugin-sdk/media-mime";
|
|
26
|
-
import { ensureConfiguredBindingRouteReady, resolveConfiguredBindingRoute, resolveRuntimeConversationBindingRoute } from "openclaw/plugin-sdk/conversation-runtime";
|
|
27
28
|
import { createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
|
|
28
29
|
import { mergePairLoopGuardConfig } from "openclaw/plugin-sdk/pair-loop-guard-runtime";
|
|
29
30
|
import { enqueueRoutedSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
|
|
30
31
|
import { resolveChannelImplicitMentions } from "openclaw/plugin-sdk/channel-ingress-runtime";
|
|
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);
|
|
@@ -2463,63 +2462,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2463
2462
|
const previewFinalText = replyRenderPlan.mode === "single" && replyRenderPlan.textIsSlackMrkdwn ? trimmedFinalText : normalizeSlackOutboundText((replySourceText ?? "").trim());
|
|
2464
2463
|
const previewFinalTextFitsEdit = countSlackTextUtf8Bytes(previewFinalText) <= SLACK_EDIT_TEXT_MAX_BYTES;
|
|
2465
2464
|
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
|
-
}
|
|
2465
|
+
let ttsPreviewFinalization;
|
|
2523
2466
|
await deliverWithFinalizableLivePreviewAdapter({
|
|
2524
2467
|
kind: info.kind,
|
|
2525
2468
|
payload,
|
|
@@ -2552,6 +2495,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2552
2495
|
payload,
|
|
2553
2496
|
threadTs: edit.threadTs
|
|
2554
2497
|
})) return;
|
|
2498
|
+
if (ttsSupplement) ttsPreviewFinalization = { threadTs: edit.threadTs };
|
|
2555
2499
|
if (!await draftStream?.finalizeMessage(preview.messageId, async () => {
|
|
2556
2500
|
await finalizeSlackPreviewEdit({
|
|
2557
2501
|
client: slackClient,
|
|
@@ -2607,11 +2551,12 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2607
2551
|
}),
|
|
2608
2552
|
deliverNormally: async () => {
|
|
2609
2553
|
await delivery.deliverNormally({
|
|
2610
|
-
payload: shouldRestoreTtsSupplementTextForPreviewFallback ? {
|
|
2554
|
+
payload: shouldRestoreTtsSupplementTextForPreviewFallback || ttsPreviewFinalization && !payload.text?.trim() ? {
|
|
2611
2555
|
...payload,
|
|
2612
2556
|
text: ttsSupplement?.spokenText
|
|
2613
2557
|
} : payload,
|
|
2614
|
-
kind: info.kind
|
|
2558
|
+
kind: info.kind,
|
|
2559
|
+
...ttsPreviewFinalization?.threadTs ? { forcedThreadTs: ttsPreviewFinalization.threadTs } : {}
|
|
2615
2560
|
});
|
|
2616
2561
|
}
|
|
2617
2562
|
});
|
|
@@ -2619,8 +2564,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2619
2564
|
};
|
|
2620
2565
|
let dispatchError;
|
|
2621
2566
|
let agentRunFailed = false;
|
|
2622
|
-
let
|
|
2623
|
-
let counts = {};
|
|
2567
|
+
let settledDispatchResult;
|
|
2624
2568
|
try {
|
|
2625
2569
|
const turnResult = await dispatchChannelInboundTurn({
|
|
2626
2570
|
cfg,
|
|
@@ -2631,6 +2575,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2631
2575
|
sessionKey: route.sessionKey
|
|
2632
2576
|
},
|
|
2633
2577
|
ctxPayload: prepared.ctxPayload,
|
|
2578
|
+
dispatchReplyFromConfig: ctx.dispatchReplyFromConfig,
|
|
2634
2579
|
dispatcherOptions: {
|
|
2635
2580
|
...replyPipeline,
|
|
2636
2581
|
transformReplyPayload: (payload) => {
|
|
@@ -2672,7 +2617,6 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2672
2617
|
return false;
|
|
2673
2618
|
} : void 0,
|
|
2674
2619
|
onReasoningEnd: async () => {
|
|
2675
|
-
progress.progressReceipt.closeReasoning();
|
|
2676
2620
|
await progress.onDraftBoundary?.();
|
|
2677
2621
|
return false;
|
|
2678
2622
|
},
|
|
@@ -2686,18 +2630,14 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2686
2630
|
} : void 0,
|
|
2687
2631
|
onToolStart: async (payload) => {
|
|
2688
2632
|
if (statusReactionsEnabled) await statusReactions.setTool(payload.name);
|
|
2689
|
-
if (payload.phase === "start") progress.
|
|
2633
|
+
if (payload.phase === "start") progress.progressWorkCounter.noteToolCall(payload.name);
|
|
2690
2634
|
return await progress.progressDraft.pushToolEvent(payload);
|
|
2691
2635
|
},
|
|
2692
2636
|
onItemEvent: async (payload) => {
|
|
2693
2637
|
if (progress.isProgressMode && payload.kind === "preamble") {
|
|
2694
2638
|
if (progress.shouldYieldDraftProgress()) return false;
|
|
2695
2639
|
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
|
-
}
|
|
2640
|
+
if (progress.commentaryProgressEnabled) return await progress.progressDraft.pushCommentaryProgress(payload.progressText, { itemId: payload.itemId }) || headlineVisible;
|
|
2701
2641
|
return headlineVisible;
|
|
2702
2642
|
}
|
|
2703
2643
|
return await progress.progressDraft.pushItemEvent(payload);
|
|
@@ -2719,8 +2659,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2719
2659
|
});
|
|
2720
2660
|
if (turnResult.dispatched) {
|
|
2721
2661
|
const result = turnResult.dispatchResult;
|
|
2722
|
-
|
|
2723
|
-
counts = result.counts;
|
|
2662
|
+
settledDispatchResult = result;
|
|
2724
2663
|
const agentRunOutcome = readAgentRunTerminalOutcome(result);
|
|
2725
2664
|
agentRunFailed = agentRunOutcome === "failed";
|
|
2726
2665
|
if (agentRunOutcome === "completed" && !sawTerminalFailurePayload && prepared.ctxPayload.ChatType === "channel") clearSlackThreadFailureNotice({
|
|
@@ -2759,12 +2698,7 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2759
2698
|
if (!finalStream.delivered) dispatchError ??= err;
|
|
2760
2699
|
}
|
|
2761
2700
|
}
|
|
2762
|
-
|
|
2763
|
-
queuedFinal = queuedFinal && (counts.final ?? 0) > 0;
|
|
2764
|
-
const anyReplyDelivered = hasVisibleInboundReplyDispatch({
|
|
2765
|
-
queuedFinal,
|
|
2766
|
-
counts
|
|
2767
|
-
}, {
|
|
2701
|
+
const anyReplyDelivered = hasVisibleInboundReplyDispatch(settledDispatchResult, {
|
|
2768
2702
|
observedReplyDelivery: delivery.observedReplyDelivery,
|
|
2769
2703
|
fallbackDelivered: streamFallbackDelivered
|
|
2770
2704
|
});
|
|
@@ -2786,11 +2720,11 @@ async function dispatchPreparedSlackMessage(prepared) {
|
|
|
2786
2720
|
if (dispatchError) throw toErrorObject(dispatchError, "Slack dispatch failed");
|
|
2787
2721
|
if (!anyReplyDelivered && !draftPreviewCommitted.value && !(agentRunFailed && progress.useDraftProgressCard)) {
|
|
2788
2722
|
await draftStream?.clear();
|
|
2789
|
-
await
|
|
2723
|
+
await draftStream?.dropDetachedMessages();
|
|
2790
2724
|
return;
|
|
2791
2725
|
}
|
|
2792
2726
|
if (shouldLogVerbose()) {
|
|
2793
|
-
const finalCount =
|
|
2727
|
+
const finalCount = resolveInboundReplyDispatchCounts(settledDispatchResult).final;
|
|
2794
2728
|
logVerbose(`slack: delivered ${finalCount} reply${finalCount === 1 ? "" : "ies"} to ${prepared.replyTarget}`);
|
|
2795
2729
|
}
|
|
2796
2730
|
}
|
|
@@ -2834,6 +2768,153 @@ function normalizeSlackAppContextEntities(value) {
|
|
|
2834
2768
|
});
|
|
2835
2769
|
}
|
|
2836
2770
|
//#endregion
|
|
2771
|
+
//#region extensions/slack/src/monitor/thread.ts
|
|
2772
|
+
const THREAD_STARTER_CACHE = /* @__PURE__ */ new Map();
|
|
2773
|
+
const THREAD_STARTER_CACHE_TTL_MS = 360 * 6e4;
|
|
2774
|
+
const THREAD_STARTER_CACHE_MAX = 2e3;
|
|
2775
|
+
function evictThreadStarterCache() {
|
|
2776
|
+
const now = asDateTimestampMs(Date.now());
|
|
2777
|
+
if (now === void 0) {
|
|
2778
|
+
THREAD_STARTER_CACHE.clear();
|
|
2779
|
+
return;
|
|
2780
|
+
}
|
|
2781
|
+
for (const [cacheKey, entry] of THREAD_STARTER_CACHE.entries()) if (asDateTimestampMs(entry.expiresAt) === void 0 || entry.expiresAt <= now) THREAD_STARTER_CACHE.delete(cacheKey);
|
|
2782
|
+
pruneMapToMaxSize(THREAD_STARTER_CACHE, THREAD_STARTER_CACHE_MAX);
|
|
2783
|
+
}
|
|
2784
|
+
function formatSlackFilePlaceholder(files) {
|
|
2785
|
+
return `[attached: ${formatSlackFileReferenceList(files)}]`;
|
|
2786
|
+
}
|
|
2787
|
+
function pushUniqueText(parts, value, options = {}) {
|
|
2788
|
+
const text = options.preserveWhitespace ? typeof value === "string" && value.trim().length > 0 ? value : void 0 : normalizeOptionalString(value);
|
|
2789
|
+
if (text && !parts.includes(text)) parts.push(text);
|
|
2790
|
+
}
|
|
2791
|
+
function resolveSlackBlocksFallbackText(blocks) {
|
|
2792
|
+
return resolveSlackBlocksText(blocks)?.text;
|
|
2793
|
+
}
|
|
2794
|
+
function resolveSlackAttachmentFallbackText(attachments) {
|
|
2795
|
+
if (!Array.isArray(attachments) || attachments.length === 0) return;
|
|
2796
|
+
const parts = [];
|
|
2797
|
+
for (const attachment of attachments) {
|
|
2798
|
+
const excludeTableBlocks = isSlackUnfurlAttachment(attachment);
|
|
2799
|
+
const fallbackBlocks = (blocks) => excludeTableBlocks ? blocks?.filter((block) => !hasSlackTableBlock([block])) : blocks;
|
|
2800
|
+
pushUniqueText(parts, attachment.pretext);
|
|
2801
|
+
pushUniqueText(parts, attachment.title);
|
|
2802
|
+
pushUniqueText(parts, attachment.text);
|
|
2803
|
+
if (!(hasSlackTableBlock(attachment.blocks) && normalizeOptionalString(attachment.fallback) === "[no preview available]")) pushUniqueText(parts, attachment.fallback);
|
|
2804
|
+
for (const field of attachment.fields ?? []) {
|
|
2805
|
+
pushUniqueText(parts, field.title);
|
|
2806
|
+
pushUniqueText(parts, field.value);
|
|
2807
|
+
}
|
|
2808
|
+
pushUniqueText(parts, resolveSlackBlocksFallbackText(fallbackBlocks(attachment.blocks)), { preserveWhitespace: true });
|
|
2809
|
+
pushUniqueText(parts, resolveSlackBlocksFallbackText(fallbackBlocks(attachment.message_blocks)), { preserveWhitespace: true });
|
|
2810
|
+
}
|
|
2811
|
+
return parts.length > 0 ? parts.join("\n") : void 0;
|
|
2812
|
+
}
|
|
2813
|
+
function resolveSlackMessageText(message) {
|
|
2814
|
+
const messageText = normalizeOptionalString(message.text) ?? resolveSlackAttachmentFallbackText(message.attachments);
|
|
2815
|
+
return resolveSlackMessageText$1({
|
|
2816
|
+
...message,
|
|
2817
|
+
text: messageText
|
|
2818
|
+
}, { preserveMessageTextWhitespace: true });
|
|
2819
|
+
}
|
|
2820
|
+
async function resolveSlackThreadStarter(params) {
|
|
2821
|
+
evictThreadStarterCache();
|
|
2822
|
+
const cacheKey = JSON.stringify([
|
|
2823
|
+
params.workspaceScope.accountId,
|
|
2824
|
+
params.workspaceScope.teamId,
|
|
2825
|
+
params.channelId,
|
|
2826
|
+
params.threadTs
|
|
2827
|
+
]);
|
|
2828
|
+
const cached = THREAD_STARTER_CACHE.get(cacheKey);
|
|
2829
|
+
if (cached) {
|
|
2830
|
+
const now = asDateTimestampMs(Date.now());
|
|
2831
|
+
if (now !== void 0 && cached.expiresAt > now) return cached.value;
|
|
2832
|
+
THREAD_STARTER_CACHE.delete(cacheKey);
|
|
2833
|
+
}
|
|
2834
|
+
try {
|
|
2835
|
+
const message = (await params.client.conversations.replies({
|
|
2836
|
+
channel: params.channelId,
|
|
2837
|
+
ts: params.threadTs,
|
|
2838
|
+
limit: 1,
|
|
2839
|
+
inclusive: true
|
|
2840
|
+
}))?.messages?.[0];
|
|
2841
|
+
const text = message ? resolveSlackMessageText(message) : void 0;
|
|
2842
|
+
const files = message?.files?.length ? message.files : void 0;
|
|
2843
|
+
if (!message || !text && !files) return null;
|
|
2844
|
+
const starter = {
|
|
2845
|
+
text: text || formatSlackFilePlaceholder(files),
|
|
2846
|
+
userId: message.user,
|
|
2847
|
+
botId: message.bot_id,
|
|
2848
|
+
ts: message.ts,
|
|
2849
|
+
files
|
|
2850
|
+
};
|
|
2851
|
+
const expiresAt = resolveExpiresAtMsFromDurationMs(THREAD_STARTER_CACHE_TTL_MS);
|
|
2852
|
+
if (expiresAt !== void 0) {
|
|
2853
|
+
if (THREAD_STARTER_CACHE.has(cacheKey)) THREAD_STARTER_CACHE.delete(cacheKey);
|
|
2854
|
+
THREAD_STARTER_CACHE.set(cacheKey, {
|
|
2855
|
+
value: starter,
|
|
2856
|
+
expiresAt
|
|
2857
|
+
});
|
|
2858
|
+
evictThreadStarterCache();
|
|
2859
|
+
}
|
|
2860
|
+
return starter;
|
|
2861
|
+
} catch (err) {
|
|
2862
|
+
logVerbose$1(`slack thread starter fetch failed channel=${params.channelId} ts=${params.threadTs}: ${formatErrorMessage(err)}`);
|
|
2863
|
+
return null;
|
|
2864
|
+
}
|
|
2865
|
+
}
|
|
2866
|
+
const SLACK_THREAD_HISTORY_MAX_PAGES = 3;
|
|
2867
|
+
/**
|
|
2868
|
+
* Fetches the most recent messages in a Slack thread (excluding the current message).
|
|
2869
|
+
* Used to populate thread context when a new thread session starts.
|
|
2870
|
+
*
|
|
2871
|
+
* Uses cursor pagination and keeps only the latest N retained messages when the full
|
|
2872
|
+
* thread fits in the bounded fetch window.
|
|
2873
|
+
*/
|
|
2874
|
+
async function resolveSlackThreadHistory(params) {
|
|
2875
|
+
const maxMessages = params.limit ?? 20;
|
|
2876
|
+
if (!Number.isFinite(maxMessages) || maxMessages <= 0) return [];
|
|
2877
|
+
const fetchLimit = 200;
|
|
2878
|
+
const retained = [];
|
|
2879
|
+
let cursor;
|
|
2880
|
+
let pagesFetched = 0;
|
|
2881
|
+
try {
|
|
2882
|
+
do {
|
|
2883
|
+
pagesFetched += 1;
|
|
2884
|
+
const response = await params.client.conversations.replies({
|
|
2885
|
+
channel: params.channelId,
|
|
2886
|
+
ts: params.threadTs,
|
|
2887
|
+
limit: fetchLimit,
|
|
2888
|
+
inclusive: true,
|
|
2889
|
+
...cursor ? { cursor } : {}
|
|
2890
|
+
});
|
|
2891
|
+
for (const msg of response.messages ?? []) {
|
|
2892
|
+
const text = resolveSlackMessageText(msg);
|
|
2893
|
+
if (!text && !msg.files?.length) continue;
|
|
2894
|
+
if (params.currentMessageTs && msg.ts === params.currentMessageTs) continue;
|
|
2895
|
+
retained.push([msg, text]);
|
|
2896
|
+
}
|
|
2897
|
+
if (retained.length > maxMessages) retained.splice(0, retained.length - maxMessages);
|
|
2898
|
+
const next = response.response_metadata?.next_cursor;
|
|
2899
|
+
cursor = typeof next === "string" && next.trim().length > 0 ? next.trim() : void 0;
|
|
2900
|
+
} while (cursor && pagesFetched < SLACK_THREAD_HISTORY_MAX_PAGES);
|
|
2901
|
+
if (cursor) {
|
|
2902
|
+
logVerbose$1(`slack thread history capped channel=${params.channelId} ts=${params.threadTs} pages=${SLACK_THREAD_HISTORY_MAX_PAGES}`);
|
|
2903
|
+
return [];
|
|
2904
|
+
}
|
|
2905
|
+
return retained.map(([message, text]) => ({
|
|
2906
|
+
text: text ?? formatSlackFilePlaceholder(message.files),
|
|
2907
|
+
userId: message.user,
|
|
2908
|
+
botId: message.bot_id,
|
|
2909
|
+
ts: message.ts,
|
|
2910
|
+
files: message.files
|
|
2911
|
+
}));
|
|
2912
|
+
} catch (err) {
|
|
2913
|
+
logVerbose$1(`slack thread history fetch failed channel=${params.channelId} ts=${params.threadTs}: ${formatErrorMessage(err)}`);
|
|
2914
|
+
return [];
|
|
2915
|
+
}
|
|
2916
|
+
}
|
|
2917
|
+
//#endregion
|
|
2837
2918
|
//#region extensions/slack/src/monitor/message-handler/preflight-audio.ts
|
|
2838
2919
|
function isSlackAudioFile(file) {
|
|
2839
2920
|
if (file.subtype === "slack_audio") return true;
|
|
@@ -2849,7 +2930,7 @@ function findCaptionlessSlackAudioFile(message) {
|
|
|
2849
2930
|
return message.files?.slice(0, 8).find(isSlackAudioFile);
|
|
2850
2931
|
}
|
|
2851
2932
|
function formatSlackAudioTranscriptForAgent(params) {
|
|
2852
|
-
return [
|
|
2933
|
+
return [formatAudioTranscriptForAgent(params.transcript), params.rawBody].filter(Boolean).join("\n");
|
|
2853
2934
|
}
|
|
2854
2935
|
async function resolveSlackPreflightAudioTranscript(params) {
|
|
2855
2936
|
const mediaIndex = params.media.findIndex((entry) => entry.contentType?.toLowerCase().startsWith("audio/"));
|
|
@@ -2884,7 +2965,7 @@ async function discardSlackPreflightMedia(media) {
|
|
|
2884
2965
|
const SLACK_MENTION_RESOLUTION_CONCURRENCY = 4;
|
|
2885
2966
|
const SLACK_MENTION_RESOLUTION_MAX_LOOKUPS_PER_MESSAGE = 20;
|
|
2886
2967
|
const SLACK_USER_MENTION_RE$1 = /<@([A-Z0-9]+)(?:\|[^>]+)?>/gi;
|
|
2887
|
-
const loadSlackMediaModule$1 = createLazyRuntimeModule(() => import("./actions-
|
|
2968
|
+
const loadSlackMediaModule$1 = createLazyRuntimeModule(() => import("./actions-XdQyjG_p.js").then((n) => n._));
|
|
2888
2969
|
function collectUniqueSlackMentionIds$1(texts) {
|
|
2889
2970
|
const seen = /* @__PURE__ */ new Set();
|
|
2890
2971
|
const mentionIds = [];
|
|
@@ -2922,8 +3003,9 @@ async function resolveSlackMessageContent(params) {
|
|
|
2922
3003
|
isThreadReply: params.isThreadReply,
|
|
2923
3004
|
threadStarter: params.threadStarter
|
|
2924
3005
|
});
|
|
2925
|
-
const
|
|
3006
|
+
const attachmentContent = ownFiles?.length || params.message.attachments?.length ? await loadSlackMediaModule$1().then(({ resolveSlackAttachmentContent }) => resolveSlackAttachmentContent({
|
|
2926
3007
|
files: ownFiles,
|
|
3008
|
+
attachments: params.message.attachments,
|
|
2927
3009
|
client: params.client,
|
|
2928
3010
|
token: params.botToken,
|
|
2929
3011
|
maxBytes: params.mediaMaxBytes,
|
|
@@ -2931,30 +3013,10 @@ async function resolveSlackMessageContent(params) {
|
|
|
2931
3013
|
totalTimeoutMs: params.mediaTotalTimeoutMs,
|
|
2932
3014
|
abortSignal: params.abortSignal,
|
|
2933
3015
|
preloadedMedia: params.preloadedMedia
|
|
2934
|
-
})) :
|
|
2935
|
-
const
|
|
2936
|
-
|
|
2937
|
-
|
|
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;
|
|
3016
|
+
})) : null;
|
|
3017
|
+
const effectiveDirectMedia = attachmentContent?.media.length ? attachmentContent.media : null;
|
|
3018
|
+
const mediaPlaceholder = effectiveDirectMedia?.map((item) => item.placeholder).join(" ");
|
|
3019
|
+
const fileOnlyFallback = attachmentContent?.files?.map(formatSlackFileReference).join(", ");
|
|
2958
3020
|
let botAttachmentText;
|
|
2959
3021
|
if (params.isBotMessage && !attachmentContent?.text) {
|
|
2960
3022
|
const botAttachmentTextParts = [];
|
|
@@ -2965,7 +3027,7 @@ async function resolveSlackMessageContent(params) {
|
|
|
2965
3027
|
botAttachmentText = botAttachmentTextParts.length > 0 ? botAttachmentTextParts.join("\n") : void 0;
|
|
2966
3028
|
}
|
|
2967
3029
|
const textParts = [
|
|
2968
|
-
resolveSlackMessageText(params.message),
|
|
3030
|
+
resolveSlackMessageText$1(params.message),
|
|
2969
3031
|
attachmentContent?.text,
|
|
2970
3032
|
botAttachmentText
|
|
2971
3033
|
];
|
|
@@ -2996,18 +3058,17 @@ async function resolveSlackMessageContent(params) {
|
|
|
2996
3058
|
renderSlackUserMentions(textParts[1], renderedMentions),
|
|
2997
3059
|
renderSlackUserMentions(textParts[2], renderedMentions),
|
|
2998
3060
|
mediaPlaceholder,
|
|
2999
|
-
|
|
3061
|
+
fileOnlyFallback ? `[Slack file: ${fileOnlyFallback}]` : void 0
|
|
3000
3062
|
].filter(Boolean).join("\n") || "";
|
|
3001
3063
|
const unavailableImageCount = attachmentContent?.unavailableImageCount ?? 0;
|
|
3002
3064
|
if (unavailableImageCount > 0) rawBody = formatInboundMediaUnavailableText({
|
|
3003
3065
|
body: rawBody,
|
|
3004
3066
|
notice: `[slack ${unavailableImageCount > 1 ? `${unavailableImageCount} forwarded images` : "forwarded image"} unavailable]`
|
|
3005
3067
|
});
|
|
3006
|
-
|
|
3007
|
-
return {
|
|
3068
|
+
return rawBody ? {
|
|
3008
3069
|
rawBody,
|
|
3009
3070
|
effectiveDirectMedia
|
|
3010
|
-
};
|
|
3071
|
+
} : null;
|
|
3011
3072
|
}
|
|
3012
3073
|
//#endregion
|
|
3013
3074
|
//#region extensions/slack/src/monitor/message-handler/prepare-dm-history.ts
|
|
@@ -3083,62 +3144,6 @@ async function resolveSlackDmHistoryContext(params) {
|
|
|
3083
3144
|
}
|
|
3084
3145
|
//#endregion
|
|
3085
3146
|
//#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
3147
|
function resolveSlackBaseConversationId(params) {
|
|
3143
3148
|
return qualifySlackConversationId(params.isDirectMessage ? `user:${params.message.user ?? "unknown"}` : params.message.channel, params.eventScope);
|
|
3144
3149
|
}
|
|
@@ -3197,44 +3202,18 @@ function resolveSlackRoutingContext(params) {
|
|
|
3197
3202
|
eventScope
|
|
3198
3203
|
});
|
|
3199
3204
|
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({
|
|
3205
|
+
const bindingRoute = resolveSlackConversationBindingRoute({
|
|
3206
|
+
cfg: ctx.cfg,
|
|
3214
3207
|
route,
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
}
|
|
3208
|
+
accountId: account.accountId,
|
|
3209
|
+
baseConversationId,
|
|
3210
|
+
runtimeBindingThreadId,
|
|
3211
|
+
bindingsEnabled: !eventScope
|
|
3220
3212
|
});
|
|
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
|
-
}
|
|
3213
|
+
const runtimeRoute = bindingRoute.runtimeRoute;
|
|
3214
|
+
const configuredBinding = bindingRoute.configuredRoute?.bindingResolution ?? null;
|
|
3215
|
+
const configuredBindingSessionKey = bindingRoute.configuredRoute?.boundSessionKey ?? "";
|
|
3216
|
+
route = bindingRoute.route;
|
|
3238
3217
|
const threadKeys = runtimeRoute.boundSessionKey || configuredBindingSessionKey ? {
|
|
3239
3218
|
sessionKey: route.sessionKey,
|
|
3240
3219
|
parentSessionKey: void 0
|
|
@@ -3317,7 +3296,7 @@ function formatSlackThreadLabelSnippet(text) {
|
|
|
3317
3296
|
}
|
|
3318
3297
|
//#endregion
|
|
3319
3298
|
//#region extensions/slack/src/monitor/message-handler/prepare-thread-context.ts
|
|
3320
|
-
const loadSlackMediaModule = createLazyRuntimeModule(() => import("./actions-
|
|
3299
|
+
const loadSlackMediaModule = createLazyRuntimeModule(() => import("./actions-XdQyjG_p.js").then((n) => n._));
|
|
3321
3300
|
const SLACK_THREAD_CONTEXT_USER_LOOKUP_CONCURRENCY = 4;
|
|
3322
3301
|
function resolveSlackThreadSessionFreshness(params) {
|
|
3323
3302
|
return params.ctx.channelRuntime?.session?.resolveEntryResetFreshness?.({
|
|
@@ -4468,6 +4447,7 @@ async function prepareSlackMessage(params) {
|
|
|
4468
4447
|
workspaceName
|
|
4469
4448
|
}) : void 0;
|
|
4470
4449
|
const senderName = await resolveSenderName();
|
|
4450
|
+
const conversationAvatar = isDirectMessage && message.user ? ctx.resolveUserAvatar(message.user, opts.eventScope) : void 0;
|
|
4471
4451
|
const preview = truncateUtf16Safe(bodyForAgent.replace(/\s+/g, " "), 160);
|
|
4472
4452
|
const inboundLabel = isDirectMessage ? `Slack DM from ${senderName}` : `Slack message in ${roomLabel} from ${senderName}`;
|
|
4473
4453
|
const slackFrom = isDirectMessage ? `slack:${message.user}` : isRoom ? `slack:channel:${message.channel}` : `slack:group:${message.channel}`;
|
|
@@ -4600,10 +4580,19 @@ async function prepareSlackMessage(params) {
|
|
|
4600
4580
|
conversation: {
|
|
4601
4581
|
kind: chatType,
|
|
4602
4582
|
id: message.channel,
|
|
4583
|
+
routePeer: {
|
|
4584
|
+
kind: chatType,
|
|
4585
|
+
id: qualifySlackRoutePeerId({
|
|
4586
|
+
id: isDirectMessage ? message.user ?? "unknown" : message.channel,
|
|
4587
|
+
kind: isDirectMessage ? "user" : "channel",
|
|
4588
|
+
eventScope: opts.eventScope
|
|
4589
|
+
})
|
|
4590
|
+
},
|
|
4603
4591
|
label: envelopeFrom,
|
|
4604
4592
|
spaceId: opts.eventScope?.teamId || ctx.teamId || void 0,
|
|
4605
4593
|
threadId: boundMessageThreadId,
|
|
4606
|
-
nativeChannelId: message.channel
|
|
4594
|
+
nativeChannelId: message.channel,
|
|
4595
|
+
avatar: conversationAvatar
|
|
4607
4596
|
},
|
|
4608
4597
|
route: {
|
|
4609
4598
|
agentId: route.agentId,
|