@openclaw/slack 2026.10.1 → 2026.10.5-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/.setup/account-configured-zcR9TJJN.mjs +35 -0
- package/dist/.setup/{account-inspect-Cs-7DXXW.mjs → account-inspect-D58VVDjk.mjs} +15 -35
- package/dist/.setup/{accounts-CDgkV7Cm.mjs → accounts-BMg9YLIv.mjs} +44 -53
- package/dist/.setup/{action-runtime-DJ1daRAZ.mjs → action-runtime-BiRZNsIG.mjs} +20 -22
- package/dist/.setup/action-runtime.runtime-C5xceJoS.mjs +2 -0
- package/dist/.setup/{actions-DDoAJnrH.mjs → actions-KGKwTAKO.mjs} +34 -43
- package/dist/.setup/{approval-handler.runtime-BcE_shWc.mjs → approval-handler.runtime-DYrsG2Ox.mjs} +44 -70
- package/dist/.setup/{approval-message-updates-EgKGmFXx.mjs → approval-message-updates-CwdDew9i.mjs} +1 -1
- package/dist/.setup/{channel-DgKSu8Iv.mjs → channel-C7MY-Hhg.mjs} +138 -97
- package/dist/.setup/{channel-type-B9zYYzBU.mjs → channel-type-NjX2SwvS.mjs} +3 -3
- package/dist/.setup/{channel.setup-BYIlwbQ7.mjs → channel.setup-BFpQowO3.mjs} +7 -14
- package/dist/.setup/{directory-config-B_by7zrc.mjs → directory-config-BEDZPfDn.mjs} +1 -1
- package/dist/.setup/{directory-live-C48wazJt.mjs → directory-live-FipfeCwt.mjs} +33 -36
- package/dist/.setup/{message-tool-api-CcjLPN3v.mjs → message-tool-api-C7im5ETh.mjs} +2 -2
- package/dist/.setup/{monitor-BuYBDmm7.mjs → monitor-BnN2px0N.mjs} +609 -801
- package/dist/.setup/{outbound-adapter-BZFkK-mw.mjs → outbound-adapter-4HdGq-8r.mjs} +4 -4
- package/dist/.setup/{pipeline.runtime-CIepKmZt.mjs → pipeline.runtime-ByPbC6MN.mjs} +287 -365
- package/dist/.setup/{policy-KKTqEiDv.mjs → policy-BaY9_eh1.mjs} +2 -2
- package/dist/.setup/{probe-BVlJ3dp0.mjs → probe-CyX52GtD.mjs} +54 -61
- package/dist/.setup/{relay-source-CC3h6M7y.mjs → relay-source-CVfH-fBO.mjs} +28 -45
- package/dist/.setup/{replies-DHbuthIR.mjs → replies-WmfwvQxc.mjs} +38 -49
- package/dist/.setup/{reply-blocks-CKnO4BSG.mjs → reply-blocks-rqHQ_3pr.mjs} +87 -138
- package/dist/.setup/{resolve-channels-HR0TgArR.mjs → resolve-channels-B96cgprw.mjs} +17 -41
- package/dist/.setup/{resolve-users-BNYBhF0q.mjs → resolve-users-Xz9aPdns.mjs} +22 -58
- package/dist/.setup/{scopes-DrDbyUH2.mjs → scopes-aMcMHhXk.mjs} +1 -1
- package/dist/.setup/{send-CgPI3Zj8.mjs → send-CLmsR42r.mjs} +157 -284
- package/dist/.setup/{session-status-D46GHwOV.mjs → session-status-CcXe10zN.mjs} +181 -238
- package/dist/.setup/{setup-plugin-api-ZrHs0N4U.mjs → setup-plugin-api-D92P5p51.mjs} +1 -1
- package/dist/.setup/{setup-surface-83lxvE2y.mjs → setup-surface-368jx6Uc.mjs} +6 -6
- package/dist/.setup/{shared-VtmYNj-v.mjs → shared-CtprVh_G.mjs} +5 -5
- package/dist/.setup/{slash-dispatch.runtime-gBj_uaLM.mjs → slash-dispatch.runtime-Dzwj6TPI.mjs} +1 -1
- package/dist/account-inspect-api.js +1 -1
- package/dist/api.js +12 -12
- package/dist/channel-plugin-api.js +1 -1
- package/dist/configured-state.js +6 -13
- package/dist/directory-contract-api.js +1 -1
- package/dist/message-tool-api.js +1 -1
- package/dist/runtime-api.js +10 -10
- package/dist/setup-entry.js +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/node_modules/@slack/types/dist/block-kit/block-elements.d.ts +1 -1
- package/node_modules/@slack/types/dist/block-kit/block-elements.d.ts.map +1 -1
- package/node_modules/@slack/types/dist/block-kit/blocks.d.ts +79 -4
- package/node_modules/@slack/types/dist/block-kit/blocks.d.ts.map +1 -1
- package/node_modules/@slack/types/dist/block-kit/composition-objects.d.ts +17 -0
- package/node_modules/@slack/types/dist/block-kit/composition-objects.d.ts.map +1 -1
- package/node_modules/@slack/types/package.json +1 -1
- package/node_modules/@slack/web-api/dist/methods.d.ts +49 -2
- package/node_modules/@slack/web-api/dist/methods.d.ts.map +1 -1
- package/node_modules/@slack/web-api/dist/methods.js +47 -0
- package/node_modules/@slack/web-api/dist/methods.js.map +1 -1
- package/node_modules/@slack/web-api/dist/types/request/agents.d.ts +186 -0
- package/node_modules/@slack/web-api/dist/types/request/agents.d.ts.map +1 -1
- package/node_modules/@slack/web-api/dist/types/request/index.d.ts +1 -1
- package/node_modules/@slack/web-api/dist/types/request/index.d.ts.map +1 -1
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsArchiveResponse.d.ts +9 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsArchiveResponse.d.ts.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsArchiveResponse.js +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsArchiveResponse.js.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsCreateResponse.d.ts +10 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsCreateResponse.d.ts.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsCreateResponse.js +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsCreateResponse.js.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsGetCanvasResponse.d.ts +29 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsGetCanvasResponse.d.ts.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsGetCanvasResponse.js +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsGetCanvasResponse.js.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsListViewsResponse.d.ts +18 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsListViewsResponse.d.ts.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsListViewsResponse.js +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsListViewsResponse.js.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsRemoveViewResponse.d.ts +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsRemoveViewResponse.d.ts.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsRemoveViewResponse.js +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsRemoveViewResponse.js.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCanvasContentResponse.d.ts +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCanvasContentResponse.d.ts.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCanvasContentResponse.js +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCanvasContentResponse.js.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCommandsResponse.d.ts +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCommandsResponse.d.ts.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCommandsResponse.js +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCommandsResponse.js.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetPropertiesResponse.d.ts +10 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetPropertiesResponse.d.ts.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetPropertiesResponse.js +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetPropertiesResponse.js.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetViewResponse.d.ts +15 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetViewResponse.d.ts.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetViewResponse.js +11 -0
- package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetViewResponse.js.map +1 -0
- package/node_modules/@slack/web-api/dist/types/response/ConversationsInfoResponse.d.ts +31 -0
- package/node_modules/@slack/web-api/dist/types/response/ConversationsInfoResponse.d.ts.map +1 -1
- package/node_modules/@slack/web-api/dist/types/response/index.d.ts +9 -0
- package/node_modules/@slack/web-api/dist/types/response/index.d.ts.map +1 -1
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/LICENSE +21 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/README.md +15 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/assert/strict.d.ts +68 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/assert.d.ts +1077 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/async_hooks.d.ts +711 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/buffer.buffer.d.ts +471 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/buffer.d.ts +1800 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/child_process.d.ts +1361 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/cluster.d.ts +432 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/console.d.ts +93 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/constants.d.ts +14 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/crypto.d.ts +3964 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/dgram.d.ts +652 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/diagnostics_channel.d.ts +794 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/dns/promises.d.ts +497 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/dns.d.ts +876 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/domain.d.ts +150 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/events.d.ts +1008 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/ffi.d.ts +500 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/fs/promises.d.ts +1477 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/fs.d.ts +4803 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/globals.d.ts +150 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/globals.typedarray.d.ts +101 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/http.d.ts +2218 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/http2.d.ts +2498 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/https.d.ts +400 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/index.d.ts +116 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/inspector/promises.d.ts +35 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/inspector.d.ts +265 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/inspector.generated.d.ts +4406 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/module.d.ts +726 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/net.d.ts +1074 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/os.d.ts +498 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/package.json +155 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/path/posix.d.ts +8 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/path/win32.d.ts +8 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/path.d.ts +178 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/perf_hooks.d.ts +617 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/process.d.ts +2269 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/punycode.d.ts +89 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/querystring.d.ts +139 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/quic.d.ts +2191 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/readline/promises.d.ts +158 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/readline.d.ts +508 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/repl.d.ts +420 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/sea.d.ts +47 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/sqlite.d.ts +1140 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/stream/consumers.d.ts +114 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/stream/iter.d.ts +449 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/stream/promises.d.ts +211 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/stream/web.d.ts +320 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/stream.d.ts +1806 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/string_decoder.d.ts +27 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/test/reporters.d.ts +60 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/test.d.ts +2558 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/timers/promises.d.ts +93 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/timers.d.ts +149 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/tls.d.ts +1232 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/trace_events.d.ts +103 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/ts5.6/buffer.buffer.d.ts +467 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/ts5.6/compatibility/float16array.d.ts +71 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/ts5.6/globals.typedarray.d.ts +36 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/ts5.6/index.d.ts +118 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/ts5.7/compatibility/float16array.d.ts +72 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/ts5.7/index.d.ts +118 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/tty.d.ts +226 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/url.d.ts +556 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/util/types.d.ts +558 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/util.d.ts +1677 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/v8.d.ts +1059 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/vfs.d.ts +211 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/vm.d.ts +1137 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/wasi.d.ts +131 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/web-globals/abortcontroller.d.ts +59 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/web-globals/blob.d.ts +23 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/web-globals/console.d.ts +9 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/web-globals/crypto.d.ts +39 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/web-globals/domexception.d.ts +83 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/web-globals/encoding.d.ts +11 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/web-globals/events.d.ts +106 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/web-globals/fetch.d.ts +69 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/web-globals/importmeta.d.ts +13 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/web-globals/messaging.d.ts +23 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/web-globals/navigator.d.ts +25 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/web-globals/performance.d.ts +45 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/web-globals/storage.d.ts +24 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/web-globals/streams.d.ts +119 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/web-globals/timers.d.ts +44 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/web-globals/url.d.ts +24 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/worker_threads.d.ts +672 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/zlib/iter.d.ts +131 -0
- package/node_modules/@slack/web-api/node_modules/@slack/logger/node_modules/@types/node/zlib.d.ts +606 -0
- package/node_modules/@slack/web-api/node_modules/@types/node/README.md +2 -2
- package/node_modules/@slack/web-api/node_modules/@types/node/package.json +2 -17
- package/node_modules/@slack/web-api/package.json +2 -2
- package/openclaw.plugin.json +0 -3
- package/package.json +6 -14
- package/dist/.setup/account-configured-sUohAxZr.mjs +0 -33
- package/dist/.setup/action-runtime.runtime-CdWL2mLC.mjs +0 -2
- package/dist/control-ui/2f4b1e827be6b68ced2ea0d8b7da8529a4eafbe72be27ee37e1064bdd530ec10/index.js +0 -1
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.mjs";
|
|
2
2
|
import { n as registerSlackHttpHandler, r as normalizeSlackWebhookPath } from "./registry-CIbMfuf8.mjs";
|
|
3
|
-
import { a as mergeSlackAccountConfig, c as resolveSlackAccountAllowFrom, f as resolveSlackReplyToMode, h as resolveSlackBotToken, l as resolveSlackAccountDmPolicy, m as resolveSlackAppToken, o as resolveDefaultSlackAccountId, p as formatSlackBotTokenIdentityWarning, s as resolveSlackAccount } from "./accounts-
|
|
3
|
+
import { a as mergeSlackAccountConfig, c as resolveSlackAccountAllowFrom, f as resolveSlackReplyToMode, h as resolveSlackBotToken, l as resolveSlackAccountDmPolicy, m as resolveSlackAppToken, o as resolveDefaultSlackAccountId, p as formatSlackBotTokenIdentityWarning, s as resolveSlackAccount } from "./accounts-BMg9YLIv.mjs";
|
|
4
4
|
import { a as parseSlackTarget, n as formatSlackTarget } from "./target-parsing-FFE26kOV.mjs";
|
|
5
|
-
import {
|
|
6
|
-
import { A as
|
|
5
|
+
import { A as SLACK_TEXT_LIMIT, Dt as isSlackPluginApprovalAuthorizedSender, G as decodeSlackQuestionAction, H as isSlackCallbackActionId, M as truncateSlackText, Nt as isSlackExecApprovalAuthorizedSender, U as isSlackQuestionActionId, V as isSlackApprovalActionId, at as escapeSlackMrkdwn, c as qualifySlackRoutePeerId, d as resolveSlackConversationBindingRoute, ht as isSlackAnyNativeApprovalClientEnabled, jt as registerSlackInstallationState, l as resolveSlackAgentRoute, n as setSlackSessionStatus, q as resolveSlackQuestionAction, r as buildSlackChannelIdCandidates, s as qualifySlackConversationId, st as decodeSlackApprovalAction, t as renameSlackSession, u as normalizeSlackRouteBindingConfig } from "./session-status-CcXe10zN.mjs";
|
|
6
|
+
import { A as resolveSlackAllowListMatch, C as resolveSlackLookupClientOptions, D as allowListMatches, O as normalizeSlackAllowOwnerEntry, T as resolveSlackWebClientOptions, a as slackIngressIdentity, b as writeLruMapEntry, c as collectSlackCursorPages, f as createSlackStartupAuthClient, g as getSlackListenerWriteClient, i as createSlackIngressSubject, j as resolveSlackUserAllowListForTeam, k as normalizeSlackSlug, m as createSlackWebClient, o as formatSlackError, v as pruneExpiredMapEntries, w as resolveSlackMonitorDispatchers, y as readLruMapEntry } from "./probe-CyX52GtD.mjs";
|
|
7
7
|
import { n as getSlackRuntime, t as getOptionalSlackRuntime } from "./runtime-JSVZSWAj.mjs";
|
|
8
8
|
import { t as DEFAULT_SLACK_SUGGESTED_PROMPTS } from "./channel-meta-C443t-lI.mjs";
|
|
9
|
-
import { S as hasSlackMessageTableBlock, f as readSlackMessages, v as isGovSlackClient, y as saveRemoteMedia } from "./actions-
|
|
10
|
-
import { d as requireSlackPostMessageTimestamp, f as buildSlackMessageIdentityPayload, r as setSlackDefaultSendIdentity } from "./send-
|
|
11
|
-
import { n as resolveSlackChannelConfig, r as resolveSlackChannelLabel, t as isSlackChannelAllowedByPolicy } from "./policy-
|
|
12
|
-
import { t as resolveSlackChannelAllowlist } from "./resolve-channels-
|
|
13
|
-
import { t as resolveSlackUserAllowlist } from "./resolve-users-
|
|
14
|
-
import { n as runSlackApprovalMessageUpdate, t as hasSlackApprovalControl } from "./approval-message-updates-
|
|
9
|
+
import { S as hasSlackMessageTableBlock, f as readSlackMessages, v as isGovSlackClient, y as saveRemoteMedia } from "./actions-KGKwTAKO.mjs";
|
|
10
|
+
import { d as requireSlackPostMessageTimestamp, f as buildSlackMessageIdentityPayload, r as setSlackDefaultSendIdentity } from "./send-CLmsR42r.mjs";
|
|
11
|
+
import { n as resolveSlackChannelConfig, r as resolveSlackChannelLabel, t as isSlackChannelAllowedByPolicy } from "./policy-BaY9_eh1.mjs";
|
|
12
|
+
import { t as resolveSlackChannelAllowlist } from "./resolve-channels-B96cgprw.mjs";
|
|
13
|
+
import { t as resolveSlackUserAllowlist } from "./resolve-users-Xz9aPdns.mjs";
|
|
14
|
+
import { n as runSlackApprovalMessageUpdate, t as hasSlackApprovalControl } from "./approval-message-updates-CwdDew9i.mjs";
|
|
15
15
|
import { normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
|
|
16
16
|
import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
|
|
17
|
-
import { asNonArrayRecord, asOptionalRecord, isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries, normalizeUniqueTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
17
|
+
import { asNonArrayRecord, asOptionalObjectRecord, asOptionalRecord, isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries, normalizeUniqueTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
18
18
|
import { normalizeAccountId as normalizeAccountId$1, normalizeMainKey, resolveAgentIdFromSessionKey, resolveAgentRoute, resolveThreadSessionKeys } from "openclaw/plugin-sdk/routing";
|
|
19
19
|
import { createChannelIngressError, createChannelIngressMonitor, waitUntilAbort } from "openclaw/plugin-sdk/channel-outbound";
|
|
20
20
|
import { createChannelPairingChallengeIssuer } from "openclaw/plugin-sdk/channel-pairing";
|
|
@@ -27,7 +27,7 @@ import { normalizeStringEntries as normalizeStringEntries$1, normalizeStringEntr
|
|
|
27
27
|
import { addAllowlistUserEntriesFromConfigEntry, buildAllowlistResolutionSummary, formatAllowlistMatchMeta, mergeAllowlist, patchAllowlistUsersInConfigEntries, summarizeMapping } from "openclaw/plugin-sdk/allow-from";
|
|
28
28
|
import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
|
|
29
29
|
import { parseExecApprovalCommandText } from "openclaw/plugin-sdk/approval-reply-runtime";
|
|
30
|
-
import { asDateTimestampMs,
|
|
30
|
+
import { asDateTimestampMs, parseStrictFiniteNumber, resolveExpiresAtMsFromDurationMs, resolvePromptHistoryLimit, timestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
|
|
31
31
|
import { WebAPIHTTPError, WebAPIPlatformError, WebAPIRateLimitedError, WebAPIRequestError, WebClient } from "@slack/web-api";
|
|
32
32
|
import { classifyTransientNetworkErrorCode } from "openclaw/plugin-sdk/retry-runtime";
|
|
33
33
|
import { buildPluginBindingResolvedText, parsePluginBindingApprovalCustomId, resolvePluginConversationBindingApproval, resolveRuntimeConversationBindingRoute, upsertChannelPairingRequest } from "openclaw/plugin-sdk/conversation-runtime";
|
|
@@ -44,8 +44,9 @@ import { registerChannelRuntimeContext } from "openclaw/plugin-sdk/channel-runti
|
|
|
44
44
|
import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/dangerous-name-runtime";
|
|
45
45
|
import { channelBlockedPatch, channelReadyPatch } from "openclaw/plugin-sdk/gateway-runtime";
|
|
46
46
|
import { getConversationSession, getSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
|
|
47
|
+
import { captureSessionEntryCurrentCheck } from "openclaw/plugin-sdk/session-binding-runtime";
|
|
47
48
|
import { loadPreparedModelCatalog, resolveAgentDir, resolveDefaultModelForAgent } from "openclaw/plugin-sdk/agent-runtime";
|
|
48
|
-
import { formatCommandArgMenuTitle, resolveCommandAuthorization, resolveEffectiveAgentRuntime, resolveNativeCommandSessionTargets, resolveStoredModelOverride } from "openclaw/plugin-sdk/command-auth-native";
|
|
49
|
+
import { buildCommandTextFromArgs, findCommandByNativeName, formatCommandArgMenuTitle, listNativeCommandSpecsForConfig, listSkillCommandsForAgents, parseCommandArgs, resolveCommandArgMenu, resolveCommandAuthorization, resolveEffectiveAgentRuntime, resolveNativeCommandSessionTargets, resolveStoredModelOverride } from "openclaw/plugin-sdk/command-auth-native";
|
|
49
50
|
import { mergeNativeCommandSpecs } from "openclaw/plugin-sdk/native-command-registry";
|
|
50
51
|
import { generateSecureToken } from "openclaw/plugin-sdk/secure-random-runtime";
|
|
51
52
|
import { resolveChannelConfigWrites } from "openclaw/plugin-sdk/channel-config-writes";
|
|
@@ -140,19 +141,20 @@ function createSlackAgentViewState(params) {
|
|
|
140
141
|
};
|
|
141
142
|
const openWorkspaceStore = createStoreOpener(SLACK_AGENT_VIEW_STATE_NAMESPACE, SLACK_AGENT_VIEW_STATE_MAX_ENTRIES);
|
|
142
143
|
const openThreadStore = createStoreOpener(SLACK_AGENT_VIEW_THREAD_STATE_NAMESPACE, SLACK_AGENT_VIEW_THREAD_STATE_MAX_ENTRIES);
|
|
143
|
-
const
|
|
144
|
+
const resolveStateKey = (thread) => {
|
|
144
145
|
const apiAppId = params.getApiAppId();
|
|
145
146
|
return apiAppId ? JSON.stringify([
|
|
146
|
-
"workspace",
|
|
147
|
+
thread ? "thread" : "workspace",
|
|
147
148
|
params.accountId,
|
|
148
149
|
params.getTeamId(),
|
|
149
|
-
apiAppId
|
|
150
|
+
apiAppId,
|
|
151
|
+
...thread ?? []
|
|
150
152
|
]) : void 0;
|
|
151
153
|
};
|
|
152
154
|
const record = async () => {
|
|
153
155
|
enabled = true;
|
|
154
156
|
loaded = true;
|
|
155
|
-
const stateKey =
|
|
157
|
+
const stateKey = resolveStateKey();
|
|
156
158
|
if (persisted || !stateKey) return;
|
|
157
159
|
const openedStore = openWorkspaceStore();
|
|
158
160
|
if (!openedStore) return;
|
|
@@ -169,7 +171,7 @@ function createSlackAgentViewState(params) {
|
|
|
169
171
|
const isEnabled = async () => {
|
|
170
172
|
if (enabled) return true;
|
|
171
173
|
if (loaded) return false;
|
|
172
|
-
const stateKey =
|
|
174
|
+
const stateKey = resolveStateKey();
|
|
173
175
|
if (!stateKey) return false;
|
|
174
176
|
const openedStore = openWorkspaceStore();
|
|
175
177
|
if (!openedStore) return false;
|
|
@@ -185,24 +187,13 @@ function createSlackAgentViewState(params) {
|
|
|
185
187
|
}
|
|
186
188
|
};
|
|
187
189
|
const managedThreadKey = (channelId, threadTs) => JSON.stringify([channelId, threadTs]);
|
|
188
|
-
const managedThreadStateKey = (channelId, threadTs) => {
|
|
189
|
-
const apiAppId = params.getApiAppId();
|
|
190
|
-
return apiAppId ? JSON.stringify([
|
|
191
|
-
"thread",
|
|
192
|
-
params.accountId,
|
|
193
|
-
params.getTeamId(),
|
|
194
|
-
apiAppId,
|
|
195
|
-
channelId,
|
|
196
|
-
threadTs
|
|
197
|
-
]) : void 0;
|
|
198
|
-
};
|
|
199
190
|
const rememberManagedThread = (key) => {
|
|
200
191
|
writeLruMapEntry(managedThreads, key, true, SLACK_MANAGED_THREAD_CACHE_MAX_ENTRIES);
|
|
201
192
|
};
|
|
202
193
|
const recordManagedThread = async (channelId, threadTs) => {
|
|
203
194
|
const key = managedThreadKey(channelId, threadTs);
|
|
204
195
|
rememberManagedThread(key);
|
|
205
|
-
const stateKey =
|
|
196
|
+
const stateKey = resolveStateKey([channelId, threadTs]);
|
|
206
197
|
const openedStore = stateKey ? openThreadStore() : void 0;
|
|
207
198
|
if (!openedStore || !stateKey) return;
|
|
208
199
|
try {
|
|
@@ -217,7 +208,7 @@ function createSlackAgentViewState(params) {
|
|
|
217
208
|
const isManagedThread = async (channelId, threadTs) => {
|
|
218
209
|
const key = managedThreadKey(channelId, threadTs);
|
|
219
210
|
if (managedThreads.has(key)) return true;
|
|
220
|
-
const stateKey =
|
|
211
|
+
const stateKey = resolveStateKey([channelId, threadTs]);
|
|
221
212
|
const openedStore = stateKey ? openThreadStore() : void 0;
|
|
222
213
|
if (!openedStore || !stateKey) return false;
|
|
223
214
|
try {
|
|
@@ -323,13 +314,14 @@ function inferSlackChannelType(channelId) {
|
|
|
323
314
|
if (trimmed.startsWith("C")) return "channel";
|
|
324
315
|
if (trimmed.startsWith("G")) return "group";
|
|
325
316
|
}
|
|
326
|
-
function
|
|
317
|
+
function parseSlackChannelType(channelType) {
|
|
327
318
|
const normalized = normalizeOptionalLowercaseString(channelType);
|
|
319
|
+
if (normalized === "im" || normalized === "mpim" || normalized === "channel" || normalized === "group") return normalized;
|
|
320
|
+
}
|
|
321
|
+
function normalizeSlackChannelType(channelType, channelId) {
|
|
322
|
+
const normalized = parseSlackChannelType(channelType);
|
|
328
323
|
const inferred = inferSlackChannelType(channelId);
|
|
329
|
-
if (normalized
|
|
330
|
-
if (inferred === "im" && normalized !== "im") return "im";
|
|
331
|
-
return normalized;
|
|
332
|
-
}
|
|
324
|
+
if (normalized && inferred !== "im") return normalized;
|
|
333
325
|
return inferred ?? "channel";
|
|
334
326
|
}
|
|
335
327
|
function resolveSlackChatType(channelType) {
|
|
@@ -617,13 +609,13 @@ const OPENCLAW_SLACK_NATIVE_RECONNECT_OBSERVER_KEY = "__openclawNativeReconnectF
|
|
|
617
609
|
const SLACK_SOCKET_PONG_TIMEOUT_WARNING_PREFIX = "A pong wasn't received from the server";
|
|
618
610
|
const SLACK_SOCKET_PING_TIMEOUT_WARNING_PREFIX = "A ping wasn't received from the server";
|
|
619
611
|
const SLACK_SOCKET_LOG_LEVEL_IGNORED_WARNING_RE = /^The logLevel given to .+ was ignored as you also gave logger$/;
|
|
612
|
+
const SLACK_SOCKET_FOREIGN_DIAGNOSTICS_WARNING_RE = /^Received unexpected (?:ping|pong) diagnostics message format$/;
|
|
620
613
|
function isConstructorFunction(value) {
|
|
621
614
|
return typeof value === "function";
|
|
622
615
|
}
|
|
623
616
|
function installSlackNativeReconnectFailureObserver(receiver) {
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
if (!client || typeof client !== "object") return;
|
|
617
|
+
const client = asOptionalObjectRecord(asOptionalObjectRecord(receiver)?.client);
|
|
618
|
+
if (!client) return;
|
|
627
619
|
if (Reflect.get(client, OPENCLAW_SLACK_NATIVE_RECONNECT_OBSERVER_KEY)) return;
|
|
628
620
|
const delayReconnectAttempt = Reflect.get(client, "delayReconnectAttempt");
|
|
629
621
|
const emit = Reflect.get(client, "emit");
|
|
@@ -681,10 +673,11 @@ function resolveSlackBoltModule(value) {
|
|
|
681
673
|
}
|
|
682
674
|
function resolveSlackBoltInterop(params) {
|
|
683
675
|
const { defaultImport, namespaceImport } = params;
|
|
684
|
-
const nestedDefault =
|
|
685
|
-
const
|
|
686
|
-
const
|
|
687
|
-
const
|
|
676
|
+
const nestedDefault = asOptionalObjectRecord(defaultImport)?.default;
|
|
677
|
+
const namespace = asOptionalObjectRecord(namespaceImport);
|
|
678
|
+
const namespaceDefault = namespace?.default;
|
|
679
|
+
const namespaceReceiver = namespace?.HTTPReceiver;
|
|
680
|
+
const namespaceSocketModeReceiver = namespace?.SocketModeReceiver;
|
|
688
681
|
const directModule = resolveSlackBoltModule(defaultImport) ?? resolveSlackBoltModule(nestedDefault) ?? resolveSlackBoltModule(namespaceDefault) ?? resolveSlackBoltModule(namespaceImport);
|
|
689
682
|
if (directModule) return directModule;
|
|
690
683
|
if (isConstructorFunction(defaultImport) && isConstructorFunction(namespaceReceiver) && isConstructorFunction(namespaceSocketModeReceiver)) return {
|
|
@@ -723,11 +716,9 @@ function publishSlackDisconnectedStatus(setStatus, error) {
|
|
|
723
716
|
lastError: message ?? null
|
|
724
717
|
});
|
|
725
718
|
}
|
|
726
|
-
function
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
function isSlackSocketSelfInflictedLoggerWarning(args) {
|
|
730
|
-
return typeof args[0] === "string" && SLACK_SOCKET_LOG_LEVEL_IGNORED_WARNING_RE.test(args[0]);
|
|
719
|
+
function isSlackSocketNoiseWarning(args) {
|
|
720
|
+
const message = args[0];
|
|
721
|
+
return typeof message === "string" && (message.startsWith(SLACK_SOCKET_PONG_TIMEOUT_WARNING_PREFIX) || message.startsWith(SLACK_SOCKET_PING_TIMEOUT_WARNING_PREFIX) || SLACK_SOCKET_LOG_LEVEL_IGNORED_WARNING_RE.test(message) || SLACK_SOCKET_FOREIGN_DIAGNOSTICS_WARNING_RE.test(message));
|
|
731
722
|
}
|
|
732
723
|
function formatSlackSdkLogArgs(args) {
|
|
733
724
|
return args.map((arg) => formatSlackError(arg, "")).filter(Boolean).join(" ");
|
|
@@ -745,7 +736,7 @@ function createSlackSocketModeLogger() {
|
|
|
745
736
|
debug: () => {},
|
|
746
737
|
info: () => {},
|
|
747
738
|
warn: (...args) => {
|
|
748
|
-
if (
|
|
739
|
+
if (isSlackSocketNoiseWarning(args)) return;
|
|
749
740
|
remember(args);
|
|
750
741
|
console.warn(prefix(), ...args);
|
|
751
742
|
},
|
|
@@ -853,16 +844,9 @@ async function startSlackSocketAndWaitForDisconnect(params) {
|
|
|
853
844
|
function isMissingSocketStartErrorDetail(err) {
|
|
854
845
|
return err === void 0 || err === null || err === "" || err instanceof Error && err.message === "";
|
|
855
846
|
}
|
|
856
|
-
function resolveSlackSocketShutdownClient(app) {
|
|
857
|
-
if (!app || typeof app !== "object") return;
|
|
858
|
-
const receiver = Reflect.get(app, "receiver");
|
|
859
|
-
if (!receiver || typeof receiver !== "object") return;
|
|
860
|
-
const client = Reflect.get(receiver, "client");
|
|
861
|
-
if (!client || typeof client !== "object") return;
|
|
862
|
-
return client;
|
|
863
|
-
}
|
|
864
847
|
async function gracefulStopSlackApp(app) {
|
|
865
|
-
const
|
|
848
|
+
const receiver = asOptionalObjectRecord(asOptionalObjectRecord(app)?.receiver);
|
|
849
|
+
const socketClient = asOptionalObjectRecord(receiver?.client);
|
|
866
850
|
if (socketClient) socketClient.shuttingDown = true;
|
|
867
851
|
await Promise.resolve(app.stop()).catch(() => void 0);
|
|
868
852
|
}
|
|
@@ -911,32 +895,16 @@ function createSlackSystemEventRouteResolver(params) {
|
|
|
911
895
|
};
|
|
912
896
|
const peerId = isDirectMessage ? senderId : channelId;
|
|
913
897
|
if (!peerId) throw new Error("Slack system event route requires a peer");
|
|
914
|
-
|
|
898
|
+
const route = resolveSlackAgentRoute({
|
|
915
899
|
cfg: params.cfg,
|
|
916
|
-
channel: "slack",
|
|
917
900
|
accountId: params.accountId,
|
|
918
901
|
teamId: event.eventScope?.teamId ?? params.getTeamId(),
|
|
919
902
|
peer: {
|
|
920
903
|
kind: resolveSlackChatType(channelType),
|
|
921
|
-
id:
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
eventScope: event.eventScope
|
|
925
|
-
})
|
|
926
|
-
}
|
|
904
|
+
id: peerId
|
|
905
|
+
},
|
|
906
|
+
eventScope: event.eventScope
|
|
927
907
|
});
|
|
928
|
-
if (event.eventScope && isDirectMessage && route.dmScope === "main") {
|
|
929
|
-
const sessionKey = resolveSlackEnterpriseMainDmSessionKey({
|
|
930
|
-
baseSessionKey: route.sessionKey,
|
|
931
|
-
accountId: params.accountId,
|
|
932
|
-
eventScope: event.eventScope
|
|
933
|
-
});
|
|
934
|
-
route = {
|
|
935
|
-
...route,
|
|
936
|
-
sessionKey,
|
|
937
|
-
mainSessionKey: sessionKey
|
|
938
|
-
};
|
|
939
|
-
}
|
|
940
908
|
const threadTs = normalizeOptionalString(event.threadTs);
|
|
941
909
|
const baseConversationId = qualifySlackConversationId(isDirectMessage ? `user:${senderId}` : channelId, event.eventScope);
|
|
942
910
|
const threadBindingRoute = !event.eventScope && threadTs ? resolveRuntimeConversationBindingRoute({
|
|
@@ -1108,7 +1076,7 @@ async function resolveWorkspacePolicy(ctx, resolveToken) {
|
|
|
1108
1076
|
} catch (err) {
|
|
1109
1077
|
runtime.log?.(`slack channel resolve failed; using config entries. ${formatSlackError(err)}`);
|
|
1110
1078
|
}
|
|
1111
|
-
const dmEntries = new Set(
|
|
1079
|
+
const dmEntries = new Set(allowFrom.filter((entry) => entry !== "*"));
|
|
1112
1080
|
const userEntries = new Set(dmEntries);
|
|
1113
1081
|
for (const channel of Object.values(channelsConfig ?? {})) addAllowlistUserEntriesFromConfigEntry(userEntries, channel);
|
|
1114
1082
|
const entries = [...userEntries];
|
|
@@ -1129,10 +1097,10 @@ async function resolveWorkspacePolicy(ctx, resolveToken) {
|
|
|
1129
1097
|
runtime.log?.(`slack user resolve failed; using config entries. ${formatSlackError(err)}`);
|
|
1130
1098
|
}
|
|
1131
1099
|
const { additions } = buildAllowlistResolutionSummary(resolved.filter((entry) => dmEntries.has(entry.input)), { formatResolved: formatSlackUserResolved });
|
|
1132
|
-
ctx.allowFrom =
|
|
1100
|
+
ctx.allowFrom = mergeAllowlist({
|
|
1133
1101
|
existing: allowFrom,
|
|
1134
1102
|
additions
|
|
1135
|
-
})
|
|
1103
|
+
});
|
|
1136
1104
|
const { resolvedMap, mapping, unresolved } = buildAllowlistResolutionSummary(resolved, { formatResolved: formatSlackUserResolved });
|
|
1137
1105
|
if (channelsConfig) ctx.channelsConfig = patchAllowlistUsersInConfigEntries({
|
|
1138
1106
|
entries: channelsConfig,
|
|
@@ -1170,6 +1138,17 @@ async function updateSlackSuggestedPrompts(params) {
|
|
|
1170
1138
|
}
|
|
1171
1139
|
//#endregion
|
|
1172
1140
|
//#region extensions/slack/src/monitor/context.ts
|
|
1141
|
+
function classifySlackChannelLookupFailure(error) {
|
|
1142
|
+
if (error instanceof WebAPIRateLimitedError) return "rate_limited";
|
|
1143
|
+
if (error instanceof WebAPIHTTPError) return error.statusCode === 429 ? "rate_limited" : error.statusCode === 404 ? "not_found" : "other";
|
|
1144
|
+
if (error instanceof WebAPIPlatformError) {
|
|
1145
|
+
if (error.data.error === "ratelimited") return "rate_limited";
|
|
1146
|
+
if (error.data.error === "channel_not_found" || error.data.error === "not_found") return "not_found";
|
|
1147
|
+
if (error.data.error === "missing_scope" || error.data.error === "not_in_channel") return "permission";
|
|
1148
|
+
}
|
|
1149
|
+
if (error instanceof WebAPIRequestError) return /^A rate limit was exceeded \(url: .+, retry-after: \d+\)$/.test(error.original.message) ? "rate_limited" : "network";
|
|
1150
|
+
return "other";
|
|
1151
|
+
}
|
|
1173
1152
|
const SLACK_CHANNEL_CACHE_MAX_ENTRIES = 1024;
|
|
1174
1153
|
const SLACK_USER_CACHE_MAX_ENTRIES = 2048;
|
|
1175
1154
|
const SLACK_AVATAR_CACHE_MAX_ENTRIES = 128;
|
|
@@ -1208,8 +1187,8 @@ function createSlackMonitorContextFields(params) {
|
|
|
1208
1187
|
const scopedKey = (key, eventScope) => eventScope ? `${params.accountId}:${eventScope.teamId}:${key}` : key;
|
|
1209
1188
|
const rememberSlackChannelType = (channelId, channelType, eventScope) => {
|
|
1210
1189
|
const id = normalizeOptionalString(channelId);
|
|
1211
|
-
const normalizedType =
|
|
1212
|
-
if (!id || normalizedType
|
|
1190
|
+
const normalizedType = parseSlackChannelType(channelType);
|
|
1191
|
+
if (!id || !normalizedType) return;
|
|
1213
1192
|
const cacheKey = scopedKey(id, eventScope);
|
|
1214
1193
|
const cached = readLruMapEntry(channelCache, cacheKey);
|
|
1215
1194
|
const type = normalizeSlackChannelType(normalizedType, id);
|
|
@@ -1259,8 +1238,11 @@ function createSlackMonitorContextFields(params) {
|
|
|
1259
1238
|
};
|
|
1260
1239
|
writeLruMapEntry(channelCache, cacheKey, entry, SLACK_CHANNEL_CACHE_MAX_ENTRIES);
|
|
1261
1240
|
return entry.info;
|
|
1262
|
-
} catch {
|
|
1263
|
-
return
|
|
1241
|
+
} catch (error) {
|
|
1242
|
+
return {
|
|
1243
|
+
...cached?.info,
|
|
1244
|
+
lookupFailureCategory: classifySlackChannelLookupFailure(error)
|
|
1245
|
+
};
|
|
1264
1246
|
}
|
|
1265
1247
|
};
|
|
1266
1248
|
const resolveUserName = async (userId, eventScope) => {
|
|
@@ -1682,26 +1664,22 @@ async function resolveThreadTsFromHistory(params) {
|
|
|
1682
1664
|
return normalizeOptionalString(message?.thread_ts);
|
|
1683
1665
|
}
|
|
1684
1666
|
function createSlackThreadTsResolver(params) {
|
|
1685
|
-
const ttlMs = Math.max(0, parseFiniteNumber(params.cacheTtlMs) ?? DEFAULT_THREAD_TS_CACHE_TTL_MS);
|
|
1686
|
-
const maxSize = Math.max(0, parseFiniteNumber(params.maxSize) ?? DEFAULT_THREAD_TS_CACHE_MAX);
|
|
1687
1667
|
const cache = /* @__PURE__ */ new Map();
|
|
1688
1668
|
const inflight = /* @__PURE__ */ new Map();
|
|
1689
1669
|
const getCached = (key, now) => {
|
|
1690
1670
|
const entry = cache.get(key);
|
|
1691
1671
|
if (!entry) return;
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
return;
|
|
1697
|
-
}
|
|
1672
|
+
const normalizedNow = asDateTimestampMs(now);
|
|
1673
|
+
if (normalizedNow === void 0 || entry.expiresAt <= normalizedNow) {
|
|
1674
|
+
cache.delete(key);
|
|
1675
|
+
return;
|
|
1698
1676
|
}
|
|
1699
1677
|
cache.delete(key);
|
|
1700
1678
|
cache.set(key, entry);
|
|
1701
1679
|
return entry.threadTs;
|
|
1702
1680
|
};
|
|
1703
1681
|
const setCached = (key, threadTs, now) => {
|
|
1704
|
-
const expiresAt =
|
|
1682
|
+
const expiresAt = resolveExpiresAtMsFromDurationMs(DEFAULT_THREAD_TS_CACHE_TTL_MS, { nowMs: now });
|
|
1705
1683
|
if (expiresAt === void 0) {
|
|
1706
1684
|
cache.delete(key);
|
|
1707
1685
|
return;
|
|
@@ -1711,7 +1689,7 @@ function createSlackThreadTsResolver(params) {
|
|
|
1711
1689
|
threadTs,
|
|
1712
1690
|
expiresAt
|
|
1713
1691
|
});
|
|
1714
|
-
pruneMapToMaxSize(cache,
|
|
1692
|
+
pruneMapToMaxSize(cache, DEFAULT_THREAD_TS_CACHE_MAX);
|
|
1715
1693
|
};
|
|
1716
1694
|
return { resolve: async (request) => {
|
|
1717
1695
|
const { message } = request;
|
|
@@ -1759,7 +1737,7 @@ function createSlackThreadTsResolver(params) {
|
|
|
1759
1737
|
//#endregion
|
|
1760
1738
|
//#region extensions/slack/src/monitor/auth.ts
|
|
1761
1739
|
const slackChannelMembersCache = /* @__PURE__ */ new WeakMap();
|
|
1762
|
-
const
|
|
1740
|
+
const CHANNEL_MEMBERS_CACHE_TTL_MS = 6e4;
|
|
1763
1741
|
const CHANNEL_MEMBERS_CACHE_MAX = 512;
|
|
1764
1742
|
const SLACK_CHANNEL_ID = "slack";
|
|
1765
1743
|
var SlackSystemEventAuthRetryError = class extends Error {};
|
|
@@ -1771,12 +1749,6 @@ function createSlackIngressResolver(ctx) {
|
|
|
1771
1749
|
cfg: ctx.cfg
|
|
1772
1750
|
});
|
|
1773
1751
|
}
|
|
1774
|
-
function readSlackCacheTtlMs(envName, fallback) {
|
|
1775
|
-
const raw = process.env[envName]?.trim();
|
|
1776
|
-
if (!raw) return fallback;
|
|
1777
|
-
const parsed = /^\d+$/.test(raw) ? Number(raw) : NaN;
|
|
1778
|
-
return Number.isSafeInteger(parsed) ? parsed : fallback;
|
|
1779
|
-
}
|
|
1780
1752
|
function getChannelMembersCache(ctx) {
|
|
1781
1753
|
const existing = slackChannelMembersCache.get(ctx);
|
|
1782
1754
|
if (existing) return existing;
|
|
@@ -1822,17 +1794,16 @@ async function fetchSlackChannelMemberIds(ctx, channelId, eventScope) {
|
|
|
1822
1794
|
async function resolveSlackChannelMemberIds(ctx, channelId, eventScope) {
|
|
1823
1795
|
const cache = getChannelMembersCache(ctx);
|
|
1824
1796
|
const key = `${ctx.accountId}:${eventScope ? `${eventScope.teamId}:` : ""}${channelId}`;
|
|
1825
|
-
const ttlMs = readSlackCacheTtlMs("OPENCLAW_SLACK_CHANNEL_MEMBERS_CACHE_TTL_MS", DEFAULT_CHANNEL_MEMBERS_CACHE_TTL_MS);
|
|
1826
1797
|
const rawNowMs = Date.now();
|
|
1827
1798
|
const nowMs = asDateTimestampMs(rawNowMs);
|
|
1828
1799
|
const cached = cache.get(key);
|
|
1829
1800
|
if (cached?.members) {
|
|
1830
|
-
if (
|
|
1801
|
+
if (nowMs !== void 0 && cached.expiresAtMs >= nowMs) return cached.members;
|
|
1831
1802
|
cache.delete(key);
|
|
1832
1803
|
}
|
|
1833
1804
|
if (cached?.pending) return await cached.pending;
|
|
1834
1805
|
const pending = fetchSlackChannelMemberIds(ctx, channelId, eventScope);
|
|
1835
|
-
const pendingExpiresAtMs =
|
|
1806
|
+
const pendingExpiresAtMs = resolveExpiresAtMsFromDurationMs(CHANNEL_MEMBERS_CACHE_TTL_MS, { nowMs: rawNowMs });
|
|
1836
1807
|
cache.set(key, {
|
|
1837
1808
|
expiresAtMs: pendingExpiresAtMs ?? 0,
|
|
1838
1809
|
pending
|
|
@@ -1840,7 +1811,7 @@ async function resolveSlackChannelMemberIds(ctx, channelId, eventScope) {
|
|
|
1840
1811
|
pruneMapToMaxSize(cache, CHANNEL_MEMBERS_CACHE_MAX);
|
|
1841
1812
|
try {
|
|
1842
1813
|
const members = await pending;
|
|
1843
|
-
const membersExpiresAtMs =
|
|
1814
|
+
const membersExpiresAtMs = resolveExpiresAtMsFromDurationMs(CHANNEL_MEMBERS_CACHE_TTL_MS);
|
|
1844
1815
|
if (membersExpiresAtMs !== void 0) {
|
|
1845
1816
|
cache.set(key, {
|
|
1846
1817
|
expiresAtMs: membersExpiresAtMs,
|
|
@@ -2037,9 +2008,7 @@ async function authorizeSlackSystemEventSender(params) {
|
|
|
2037
2008
|
channelName
|
|
2038
2009
|
};
|
|
2039
2010
|
if (params.interactiveEvent) {
|
|
2040
|
-
|
|
2041
|
-
const sourceNormalized = typeof resolvedTypeSource === "string" ? resolvedTypeSource.toLowerCase().trim() : void 0;
|
|
2042
|
-
if (inferredFromId === void 0 && !(sourceNormalized === "im" || sourceNormalized === "mpim" || sourceNormalized === "channel" || sourceNormalized === "group")) return {
|
|
2011
|
+
if (inferSlackChannelType(channelId) === void 0 && !parseSlackChannelType(resolvedTypeSource)) return {
|
|
2043
2012
|
allowed: false,
|
|
2044
2013
|
reason: "ambiguous-channel-type",
|
|
2045
2014
|
channelType,
|
|
@@ -2105,6 +2074,39 @@ async function authorizeSlackSystemEventSender(params) {
|
|
|
2105
2074
|
};
|
|
2106
2075
|
}
|
|
2107
2076
|
//#endregion
|
|
2077
|
+
//#region extensions/slack/src/monitor/event-scope.ts
|
|
2078
|
+
function resolveSlackMonitorEventScope(params) {
|
|
2079
|
+
const identity = params.ctx.installationIdentity;
|
|
2080
|
+
const clientOptions = params.ctx.app.webClientOptions;
|
|
2081
|
+
const onDrop = params.onDrop ?? ((reason) => logVerbose(`slack: drop listener event (${reason})`));
|
|
2082
|
+
const drop = (reason) => {
|
|
2083
|
+
onDrop(reason);
|
|
2084
|
+
return null;
|
|
2085
|
+
};
|
|
2086
|
+
const context = params.context ?? {};
|
|
2087
|
+
if (identity.kind !== "enterprise") return context.isEnterpriseInstall === true ? drop("enterprise_event_for_workspace_account") : void 0;
|
|
2088
|
+
const body = params.body && typeof params.body === "object" ? params.body : {};
|
|
2089
|
+
const apiAppId = normalizeOptionalString(body.api_app_id);
|
|
2090
|
+
if (apiAppId && identity.apiAppId && apiAppId !== identity.apiAppId) return drop("wrong_app");
|
|
2091
|
+
if (context.isEnterpriseInstall !== true) return drop("not_enterprise_install");
|
|
2092
|
+
const enterpriseId = normalizeOptionalString(context.enterpriseId);
|
|
2093
|
+
if (!enterpriseId) return drop("missing_enterprise_id");
|
|
2094
|
+
if (enterpriseId !== identity.enterpriseId) return drop("wrong_enterprise");
|
|
2095
|
+
const teamId = normalizeOptionalString(context.teamId);
|
|
2096
|
+
if (!teamId) return drop("missing_team_id");
|
|
2097
|
+
if (!params.client) return drop("missing_listener_client");
|
|
2098
|
+
const writeClient = getSlackListenerWriteClient({
|
|
2099
|
+
listenerClient: params.client,
|
|
2100
|
+
teamId,
|
|
2101
|
+
clientOptions
|
|
2102
|
+
});
|
|
2103
|
+
return {
|
|
2104
|
+
teamId,
|
|
2105
|
+
client: params.client,
|
|
2106
|
+
...writeClient ? { writeClient } : {}
|
|
2107
|
+
};
|
|
2108
|
+
}
|
|
2109
|
+
//#endregion
|
|
2108
2110
|
//#region extensions/slack/src/types.ts
|
|
2109
2111
|
function parseSlackMessageEvent(value) {
|
|
2110
2112
|
const record = asOptionalRecord(value);
|
|
@@ -2464,17 +2466,14 @@ function resolveSlackThreadContext(params) {
|
|
|
2464
2466
|
}
|
|
2465
2467
|
//#endregion
|
|
2466
2468
|
//#region extensions/slack/src/monitor/session-run-targets.ts
|
|
2467
|
-
function captureSlackSessionTargetGuard(ctx, route, isActive) {
|
|
2468
|
-
const
|
|
2469
|
+
async function captureSlackSessionTargetGuard(ctx, route, isActive) {
|
|
2470
|
+
const { isCurrent } = await captureSessionEntryCurrentCheck({
|
|
2469
2471
|
agentId: route.agentId,
|
|
2470
2472
|
sessionKey: route.sessionKey,
|
|
2471
|
-
storePath: resolveStorePath(ctx.cfg.session?.store, { agentId: route.agentId })
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
return
|
|
2475
|
-
const current = getSessionEntry(scope);
|
|
2476
|
-
return isActive?.() !== false && current?.sessionId === selected?.sessionId && current?.lifecycleRevision === selected?.lifecycleRevision;
|
|
2477
|
-
};
|
|
2473
|
+
storePath: resolveStorePath(ctx.cfg.session?.store, { agentId: route.agentId }),
|
|
2474
|
+
isActive
|
|
2475
|
+
});
|
|
2476
|
+
return isCurrent;
|
|
2478
2477
|
}
|
|
2479
2478
|
const runs = /* @__PURE__ */ new WeakMap();
|
|
2480
2479
|
function addressKey(address) {
|
|
@@ -2511,34 +2510,6 @@ function getSlackSessionRuns(ctx, address) {
|
|
|
2511
2510
|
}
|
|
2512
2511
|
//#endregion
|
|
2513
2512
|
//#region extensions/slack/src/monitor/message-handler/prepare-routing.ts
|
|
2514
|
-
function resolveSlackInitialAgentRoute(params) {
|
|
2515
|
-
const route = resolveAgentRoute({
|
|
2516
|
-
cfg: params.boundAgentId || !params.bindingOwnerAvailable ? { session: params.ctx.cfg.session } : normalizeSlackRouteBindingConfig(params.ctx.cfg),
|
|
2517
|
-
defaultAgentId: params.boundAgentId,
|
|
2518
|
-
channel: "slack",
|
|
2519
|
-
accountId: params.account.accountId,
|
|
2520
|
-
teamId: params.eventScope?.teamId || params.ctx.teamId || void 0,
|
|
2521
|
-
peer: {
|
|
2522
|
-
kind: params.chatType,
|
|
2523
|
-
id: qualifySlackRoutePeerId({
|
|
2524
|
-
id: params.chatType === "direct" ? params.message.user ?? "unknown" : params.message.channel,
|
|
2525
|
-
kind: params.chatType === "direct" ? "user" : "channel",
|
|
2526
|
-
eventScope: params.eventScope
|
|
2527
|
-
})
|
|
2528
|
-
}
|
|
2529
|
-
});
|
|
2530
|
-
if (!params.eventScope || params.chatType !== "direct" || route.dmScope !== "main") return route;
|
|
2531
|
-
const sessionKey = resolveSlackEnterpriseMainDmSessionKey({
|
|
2532
|
-
baseSessionKey: route.sessionKey,
|
|
2533
|
-
accountId: params.account.accountId,
|
|
2534
|
-
eventScope: params.eventScope
|
|
2535
|
-
});
|
|
2536
|
-
return {
|
|
2537
|
-
...route,
|
|
2538
|
-
sessionKey,
|
|
2539
|
-
mainSessionKey: sessionKey
|
|
2540
|
-
};
|
|
2541
|
-
}
|
|
2542
2513
|
function resolveSlackRoutingContext(params) {
|
|
2543
2514
|
const { ctx, account, message, chatType, channelConfig, seedTopLevelRoomThread, assistantThreadTs, agentViewThreadTs, eventScope } = params;
|
|
2544
2515
|
const isDirectMessage = chatType === "direct";
|
|
@@ -2557,12 +2528,15 @@ function resolveSlackRoutingContext(params) {
|
|
|
2557
2528
|
const runtimeBindingThreadId = routedThreadId ?? (isDirectMessage && isThreadReply ? threadTs : void 0);
|
|
2558
2529
|
const bindingRoute = resolveSlackConversationBindingRoute({
|
|
2559
2530
|
cfg: ctx.cfg,
|
|
2560
|
-
resolveRoute: (
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
account,
|
|
2564
|
-
|
|
2565
|
-
|
|
2531
|
+
resolveRoute: ({ boundAgentId, bindingOwnerAvailable }) => resolveSlackAgentRoute({
|
|
2532
|
+
cfg: boundAgentId || !bindingOwnerAvailable ? { session: ctx.cfg.session } : normalizeSlackRouteBindingConfig(ctx.cfg),
|
|
2533
|
+
defaultAgentId: boundAgentId,
|
|
2534
|
+
accountId: account.accountId,
|
|
2535
|
+
teamId: eventScope?.teamId || ctx.teamId || void 0,
|
|
2536
|
+
peer: {
|
|
2537
|
+
kind: chatType,
|
|
2538
|
+
id: isDirectMessage ? message.user ?? "unknown" : message.channel
|
|
2539
|
+
},
|
|
2566
2540
|
eventScope
|
|
2567
2541
|
}),
|
|
2568
2542
|
accountId: account.accountId,
|
|
@@ -2663,12 +2637,44 @@ async function resolveSlackSessionEventRoutingContext(params) {
|
|
|
2663
2637
|
}
|
|
2664
2638
|
if (!owner) throw new Error("No recorded session owns this Slack conversation");
|
|
2665
2639
|
const { route } = owner;
|
|
2666
|
-
const
|
|
2640
|
+
const readLiveOwner = () => getSlackSessionRuns(ctx, liveAddress).at(-1);
|
|
2641
|
+
const current = await captureSessionEntryCurrentCheck({
|
|
2642
|
+
agentId: route.agentId,
|
|
2643
|
+
sessionKey: route.sessionKey,
|
|
2644
|
+
storePath: resolveStorePath(ctx.cfg.session?.store, { agentId: route.agentId }),
|
|
2645
|
+
isActive: params.intent === "stop" ? owner.isActive : void 0,
|
|
2646
|
+
matchGeneration: params.intent === "stop",
|
|
2647
|
+
errorMessage: params.intent === "title" ? "Slack conversation owner changed before the title update" : "The selected session changed before it could be stopped.",
|
|
2648
|
+
alternatives: [
|
|
2649
|
+
{ conversations: [{
|
|
2650
|
+
...threadAddress,
|
|
2651
|
+
sessionKey: route.sessionKey
|
|
2652
|
+
}] },
|
|
2653
|
+
{
|
|
2654
|
+
conversations: [{
|
|
2655
|
+
...threadAddress,
|
|
2656
|
+
sessionKey: null
|
|
2657
|
+
}],
|
|
2658
|
+
isActive: () => readLiveOwner()?.route.sessionKey === route.sessionKey
|
|
2659
|
+
},
|
|
2660
|
+
...allowDirectParent ? [{
|
|
2661
|
+
conversations: [{
|
|
2662
|
+
...threadAddress,
|
|
2663
|
+
sessionKey: null
|
|
2664
|
+
}, {
|
|
2665
|
+
...address,
|
|
2666
|
+
sessionKey: route.sessionKey
|
|
2667
|
+
}],
|
|
2668
|
+
isActive: () => !readLiveOwner()
|
|
2669
|
+
}] : []
|
|
2670
|
+
]
|
|
2671
|
+
});
|
|
2667
2672
|
return {
|
|
2668
2673
|
...routing,
|
|
2669
2674
|
route,
|
|
2670
2675
|
sessionKey: route.sessionKey,
|
|
2671
|
-
isCurrentSession:
|
|
2676
|
+
isCurrentSession: current.isCurrent,
|
|
2677
|
+
assertCurrentSession: current.assertCurrent
|
|
2672
2678
|
};
|
|
2673
2679
|
}
|
|
2674
2680
|
//#endregion
|
|
@@ -2743,77 +2749,11 @@ async function authorizeSlackDirectMessage(params) {
|
|
|
2743
2749
|
return false;
|
|
2744
2750
|
}
|
|
2745
2751
|
//#endregion
|
|
2746
|
-
//#region extensions/slack/src/monitor/event-scope.ts
|
|
2747
|
-
function resolveSlackListenerEventScope$1(params) {
|
|
2748
|
-
const resolved = resolveSlackEventScope(params);
|
|
2749
|
-
if (!resolved.ok) {
|
|
2750
|
-
params.onDrop?.(resolved.reason);
|
|
2751
|
-
return null;
|
|
2752
|
-
}
|
|
2753
|
-
return resolved.scope;
|
|
2754
|
-
}
|
|
2755
|
-
function resolveSlackEventScope(params) {
|
|
2756
|
-
const context = params.context ?? {};
|
|
2757
|
-
if (params.identity.kind !== "enterprise") return context.isEnterpriseInstall === true ? {
|
|
2758
|
-
ok: false,
|
|
2759
|
-
reason: "enterprise_event_for_workspace_account"
|
|
2760
|
-
} : { ok: true };
|
|
2761
|
-
const body = params.body && typeof params.body === "object" ? params.body : {};
|
|
2762
|
-
const apiAppId = normalizeOptionalString(body.api_app_id);
|
|
2763
|
-
if (apiAppId && params.identity.apiAppId && apiAppId !== params.identity.apiAppId) return {
|
|
2764
|
-
ok: false,
|
|
2765
|
-
reason: "wrong_app"
|
|
2766
|
-
};
|
|
2767
|
-
if (context.isEnterpriseInstall !== true) return {
|
|
2768
|
-
ok: false,
|
|
2769
|
-
reason: "not_enterprise_install"
|
|
2770
|
-
};
|
|
2771
|
-
const enterpriseId = normalizeOptionalString(context.enterpriseId);
|
|
2772
|
-
if (!enterpriseId) return {
|
|
2773
|
-
ok: false,
|
|
2774
|
-
reason: "missing_enterprise_id"
|
|
2775
|
-
};
|
|
2776
|
-
if (enterpriseId !== params.identity.enterpriseId) return {
|
|
2777
|
-
ok: false,
|
|
2778
|
-
reason: "wrong_enterprise"
|
|
2779
|
-
};
|
|
2780
|
-
const teamId = normalizeOptionalString(context.teamId);
|
|
2781
|
-
if (!teamId) return {
|
|
2782
|
-
ok: false,
|
|
2783
|
-
reason: "missing_team_id"
|
|
2784
|
-
};
|
|
2785
|
-
if (!params.client) return {
|
|
2786
|
-
ok: false,
|
|
2787
|
-
reason: "missing_listener_client"
|
|
2788
|
-
};
|
|
2789
|
-
const writeClient = getSlackListenerWriteClient({
|
|
2790
|
-
listenerClient: params.client,
|
|
2791
|
-
teamId,
|
|
2792
|
-
clientOptions: params.clientOptions
|
|
2793
|
-
});
|
|
2794
|
-
return {
|
|
2795
|
-
ok: true,
|
|
2796
|
-
scope: {
|
|
2797
|
-
teamId,
|
|
2798
|
-
client: params.client,
|
|
2799
|
-
...writeClient ? { writeClient } : {}
|
|
2800
|
-
}
|
|
2801
|
-
};
|
|
2802
|
-
}
|
|
2803
|
-
//#endregion
|
|
2804
2752
|
//#region extensions/slack/src/monitor/external-arg-menu-store.ts
|
|
2805
2753
|
const SLACK_EXTERNAL_ARG_MENU_TOKEN_BYTES = 18;
|
|
2806
2754
|
const SLACK_EXTERNAL_ARG_MENU_TOKEN_PATTERN = new RegExp(`^[A-Za-z0-9_-]{${Math.ceil(24)}}$`);
|
|
2807
2755
|
const SLACK_EXTERNAL_ARG_MENU_TTL_MS = 6e5;
|
|
2808
2756
|
const SLACK_EXTERNAL_ARG_MENU_PREFIX = "openclaw_cmdarg_ext:";
|
|
2809
|
-
function pruneSlackExternalArgMenuStore(store, rawNow) {
|
|
2810
|
-
const now = asDateTimestampMs(rawNow);
|
|
2811
|
-
if (now === void 0) {
|
|
2812
|
-
store.clear();
|
|
2813
|
-
return;
|
|
2814
|
-
}
|
|
2815
|
-
for (const [token, entry] of store.entries()) if (asDateTimestampMs(entry.expiresAt) === void 0 || entry.expiresAt <= now) store.delete(token);
|
|
2816
|
-
}
|
|
2817
2757
|
function createSlackExternalArgMenuToken(store) {
|
|
2818
2758
|
let token;
|
|
2819
2759
|
do
|
|
@@ -2825,7 +2765,7 @@ function createSlackExternalArgMenuStore() {
|
|
|
2825
2765
|
const store = /* @__PURE__ */ new Map();
|
|
2826
2766
|
return {
|
|
2827
2767
|
create(params, now = Date.now()) {
|
|
2828
|
-
|
|
2768
|
+
pruneExpiredMapEntries(store, now);
|
|
2829
2769
|
const token = createSlackExternalArgMenuToken(store);
|
|
2830
2770
|
const expiresAt = resolveExpiresAtMsFromDurationMs(SLACK_EXTERNAL_ARG_MENU_TTL_MS, { nowMs: now });
|
|
2831
2771
|
if (expiresAt !== void 0) store.set(token, {
|
|
@@ -2841,7 +2781,7 @@ function createSlackExternalArgMenuStore() {
|
|
|
2841
2781
|
return SLACK_EXTERNAL_ARG_MENU_TOKEN_PATTERN.test(token) ? token : void 0;
|
|
2842
2782
|
},
|
|
2843
2783
|
get(token, now = Date.now()) {
|
|
2844
|
-
|
|
2784
|
+
pruneExpiredMapEntries(store, now);
|
|
2845
2785
|
return store.get(token);
|
|
2846
2786
|
}
|
|
2847
2787
|
};
|
|
@@ -2890,8 +2830,7 @@ const SLACK_COMMAND_ARG_BUTTON_VALUE_MAX = 2e3;
|
|
|
2890
2830
|
const SLACK_COMMAND_ARG_CONFIRM_TEXT_MAX = 300;
|
|
2891
2831
|
const SLACK_HEADER_TEXT_MAX = 150;
|
|
2892
2832
|
const SLACK_COMMAND_ARG_ACTION_BLOCKS_MAX = 47;
|
|
2893
|
-
const
|
|
2894
|
-
const loadSlashDispatchRuntime = createLazyRuntimeModule(() => import("./slash-dispatch.runtime-gBj_uaLM.mjs"));
|
|
2833
|
+
const loadSlashDispatchRuntime = createLazyRuntimeModule(() => import("./slash-dispatch.runtime-Dzwj6TPI.mjs"));
|
|
2895
2834
|
const loadPluginCommandRuntime = createLazyRuntimeModule(() => import("openclaw/plugin-sdk/plugin-command-runtime"));
|
|
2896
2835
|
function resolveSlackCommandMenuModelContext(params) {
|
|
2897
2836
|
if (!params.sessionKey.trim()) return {};
|
|
@@ -3211,7 +3150,7 @@ function createSlackCommandHandler(params) {
|
|
|
3211
3150
|
if (p.threadTs) {
|
|
3212
3151
|
if (p.sessionTarget) {
|
|
3213
3152
|
resolvedSlashRoute = p.sessionTarget;
|
|
3214
|
-
isCurrentSession = captureSlackSessionTargetGuard(ctx, p.sessionTarget, p.isSessionTargetCurrent);
|
|
3153
|
+
isCurrentSession = await captureSlackSessionTargetGuard(ctx, p.sessionTarget, p.isSessionTargetCurrent);
|
|
3215
3154
|
return resolvedSlashRoute;
|
|
3216
3155
|
}
|
|
3217
3156
|
const routing = await resolveSlackSessionEventRoutingContext({
|
|
@@ -3247,7 +3186,6 @@ function createSlackCommandHandler(params) {
|
|
|
3247
3186
|
return resolvedSlashRoute;
|
|
3248
3187
|
};
|
|
3249
3188
|
if (commandDefinition && supportsInteractiveArgMenus) {
|
|
3250
|
-
const { resolveCommandArgMenu } = await loadSlashCommandsRuntime();
|
|
3251
3189
|
const menuNeedsModelContext = !(commandArgs?.raw && !commandArgs.values) && commandDefinition.args?.some((arg) => typeof arg.choices === "function" && commandArgs?.values?.[arg.name] == null);
|
|
3252
3190
|
const menuRoute = menuNeedsModelContext || commandDefinition.key === "verbose" ? await resolveSlashRoute() : void 0;
|
|
3253
3191
|
const menuModelContext = menuNeedsModelContext && menuRoute ? resolveSlackCommandMenuModelContext({
|
|
@@ -3407,12 +3345,10 @@ function createSlackCommandHandler(params) {
|
|
|
3407
3345
|
dispatcherOptions: { onSettled: async () => {
|
|
3408
3346
|
if (pendingSlashReplies.length === 0) return;
|
|
3409
3347
|
const pending = pendingSlashReplies.splice(0);
|
|
3410
|
-
const settled = /* @__PURE__ */ new Set();
|
|
3411
3348
|
try {
|
|
3412
3349
|
await deliverSlashPayloads(pending.map((entry) => entry.payload), ({ replyIndex, visibleReplySent, error }) => {
|
|
3413
3350
|
const entry = pending[replyIndex];
|
|
3414
|
-
if (!entry
|
|
3415
|
-
settled.add(replyIndex);
|
|
3351
|
+
if (!entry) return;
|
|
3416
3352
|
if (error !== void 0) {
|
|
3417
3353
|
entry.finalization.reject(error);
|
|
3418
3354
|
return;
|
|
@@ -3421,7 +3357,7 @@ function createSlackCommandHandler(params) {
|
|
|
3421
3357
|
});
|
|
3422
3358
|
} catch (error) {
|
|
3423
3359
|
const unsettledError = isChannelPartialDeliveryError(error) ? error.cause ?? error : error;
|
|
3424
|
-
for (const
|
|
3360
|
+
for (const entry of pending) entry.finalization.reject(unsettledError);
|
|
3425
3361
|
throw error;
|
|
3426
3362
|
}
|
|
3427
3363
|
} },
|
|
@@ -3470,12 +3406,9 @@ async function registerSlackMonitorSlashCommands(params) {
|
|
|
3470
3406
|
const { ctx, account, trackEvent } = params;
|
|
3471
3407
|
const startupCfg = ctx.cfg;
|
|
3472
3408
|
const runtime = ctx.runtime;
|
|
3473
|
-
const resolveEventScope = (args) =>
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
context: args.context,
|
|
3477
|
-
client: args.client,
|
|
3478
|
-
clientOptions: ctx.app.webClientOptions,
|
|
3409
|
+
const resolveEventScope = (args) => resolveSlackMonitorEventScope({
|
|
3410
|
+
...args,
|
|
3411
|
+
ctx,
|
|
3479
3412
|
onDrop: (reason) => runtime.log?.(`slack: drop slash payload (${reason})`)
|
|
3480
3413
|
});
|
|
3481
3414
|
const supportsInteractiveArgMenus = typeof ctx.app.action === "function";
|
|
@@ -3520,20 +3453,18 @@ async function registerSlackMonitorSlashCommands(params) {
|
|
|
3520
3453
|
});
|
|
3521
3454
|
};
|
|
3522
3455
|
let nativeCommands = [];
|
|
3523
|
-
let slashCommandsRuntime = null;
|
|
3524
3456
|
let pluginCommandRuntimeModule = null;
|
|
3525
3457
|
if (registration.mode === "disabled" && resolveNativeCommandsEnabled({
|
|
3526
3458
|
providerId: "slack",
|
|
3527
3459
|
providerSetting: account.config.commands?.native,
|
|
3528
3460
|
globalSetting: startupCfg.commands?.native
|
|
3529
3461
|
})) {
|
|
3530
|
-
slashCommandsRuntime = await loadSlashCommandsRuntime();
|
|
3531
3462
|
const skillCommands = resolveNativeSkillsEnabled({
|
|
3532
3463
|
providerId: "slack",
|
|
3533
3464
|
providerSetting: account.config.commands?.nativeSkills,
|
|
3534
3465
|
globalSetting: startupCfg.commands?.nativeSkills
|
|
3535
|
-
}) ?
|
|
3536
|
-
nativeCommands =
|
|
3466
|
+
}) ? listSkillCommandsForAgents({ cfg: startupCfg }) : [];
|
|
3467
|
+
nativeCommands = listNativeCommandSpecsForConfig(startupCfg, {
|
|
3537
3468
|
skillCommands,
|
|
3538
3469
|
provider: "slack"
|
|
3539
3470
|
});
|
|
@@ -3547,16 +3478,16 @@ async function registerSlackMonitorSlashCommands(params) {
|
|
|
3547
3478
|
}
|
|
3548
3479
|
if (registration.mode === "single") registerCommand(buildSlackSlashCommandMatcher(registration.name));
|
|
3549
3480
|
else if (registration.mode === "native") {
|
|
3550
|
-
if (!
|
|
3481
|
+
if (!pluginCommandRuntimeModule) throw new Error("Missing command runtimes for native Slack commands.");
|
|
3551
3482
|
for (const command of nativeCommands) {
|
|
3552
3483
|
const pluginCommandCandidate = "prepareDispatch" in command ? command : void 0;
|
|
3553
3484
|
registerCommand(`/${command.name}`, (cmd) => {
|
|
3554
|
-
const commandDefinition = pluginCommandCandidate ? void 0 :
|
|
3485
|
+
const commandDefinition = pluginCommandCandidate ? void 0 : findCommandByNativeName(command.name, "slack");
|
|
3555
3486
|
const rawText = cmd.text?.trim() ?? "";
|
|
3556
3487
|
const pluginCommandDispatch = pluginCommandCandidate?.prepareDispatch(rawText) ?? NON_PLUGIN_COMMAND_DISPATCH;
|
|
3557
|
-
const commandArgs = commandDefinition ?
|
|
3488
|
+
const commandArgs = commandDefinition ? parseCommandArgs(commandDefinition, rawText) : rawText ? { raw: rawText } : void 0;
|
|
3558
3489
|
return {
|
|
3559
|
-
prompt: commandDefinition ?
|
|
3490
|
+
prompt: commandDefinition ? buildCommandTextFromArgs(commandDefinition, commandArgs) : rawText ? `/${command.name} ${rawText}` : `/${command.name}`,
|
|
3560
3491
|
commandArgs,
|
|
3561
3492
|
commandDefinition: commandDefinition ?? void 0,
|
|
3562
3493
|
pluginCommandReplyOptions: { [pluginCommandRuntimeModule.PLUGIN_COMMAND_DISPATCH]: pluginCommandDispatch }
|
|
@@ -3648,7 +3579,6 @@ async function registerSlackMonitorSlashCommands(params) {
|
|
|
3648
3579
|
});
|
|
3649
3580
|
return;
|
|
3650
3581
|
}
|
|
3651
|
-
const { buildCommandTextFromArgs, findCommandByNativeName } = await loadSlashCommandsRuntime();
|
|
3652
3582
|
const commandDefinition = findCommandByNativeName(parsed.command, "slack");
|
|
3653
3583
|
const commandArgs = { values: { [parsed.arg]: parsed.value } };
|
|
3654
3584
|
const prompt = commandDefinition ? buildCommandTextFromArgs(commandDefinition, commandArgs) : `/${parsed.command} ${parsed.value}`;
|
|
@@ -3719,47 +3649,6 @@ function isSlackBoltRespondError(error) {
|
|
|
3719
3649
|
return Boolean(error) && typeof error === "object" && error.code === "slack_bolt_respond_error";
|
|
3720
3650
|
}
|
|
3721
3651
|
//#endregion
|
|
3722
|
-
//#region extensions/slack/src/monitor/events/system-event-context.ts
|
|
3723
|
-
async function authorizeAndResolveSlackSystemEventContext(params) {
|
|
3724
|
-
const { senderId, channelId, channelType, eventKind } = params;
|
|
3725
|
-
const ctx = await params.ctx.readRuntimeContext();
|
|
3726
|
-
const auth = await authorizeSlackSystemEventSender({
|
|
3727
|
-
ctx,
|
|
3728
|
-
senderId,
|
|
3729
|
-
channelId,
|
|
3730
|
-
channelType,
|
|
3731
|
-
eventScope: params.eventScope,
|
|
3732
|
-
retryNameLookup: eventKind.startsWith("member-")
|
|
3733
|
-
});
|
|
3734
|
-
if (!auth.allowed) {
|
|
3735
|
-
logVerbose(`slack: drop ${eventKind} sender ${senderId ?? "unknown"} channel=${channelId ?? "unknown"} reason=${auth.reason ?? "unauthorized"}`);
|
|
3736
|
-
return;
|
|
3737
|
-
}
|
|
3738
|
-
return {
|
|
3739
|
-
channelLabel: resolveSlackChannelLabel({
|
|
3740
|
-
channelId,
|
|
3741
|
-
channelName: auth.channelName
|
|
3742
|
-
}),
|
|
3743
|
-
route: ctx.resolveSlackSystemEventRoute({
|
|
3744
|
-
channelId,
|
|
3745
|
-
channelType: auth.channelType,
|
|
3746
|
-
senderId,
|
|
3747
|
-
threadTs: auth.channelType === "im" ? void 0 : params.threadTs,
|
|
3748
|
-
eventScope: params.eventScope
|
|
3749
|
-
})
|
|
3750
|
-
};
|
|
3751
|
-
}
|
|
3752
|
-
function resolveSlackListenerEventScope(params) {
|
|
3753
|
-
return resolveSlackListenerEventScope$1({
|
|
3754
|
-
identity: params.ctx.installationIdentity,
|
|
3755
|
-
body: params.body,
|
|
3756
|
-
context: params.context,
|
|
3757
|
-
client: params.client,
|
|
3758
|
-
clientOptions: params.ctx.app.webClientOptions,
|
|
3759
|
-
onDrop: (reason) => logVerbose(`slack: drop listener event (${reason})`)
|
|
3760
|
-
});
|
|
3761
|
-
}
|
|
3762
|
-
//#endregion
|
|
3763
3652
|
//#region extensions/slack/src/monitor/events/agent.ts
|
|
3764
3653
|
function registerSlackAgentEvents(params) {
|
|
3765
3654
|
const { ctx, trackEvent } = params;
|
|
@@ -3778,7 +3667,7 @@ function registerSlackAgentEvents(params) {
|
|
|
3778
3667
|
});
|
|
3779
3668
|
ctx.app.event("agent_session_stopped", async ({ event, body, context, client }) => {
|
|
3780
3669
|
if (ctx.shouldDropMismatchedSlackEvent(body)) return;
|
|
3781
|
-
const eventScope =
|
|
3670
|
+
const eventScope = resolveSlackMonitorEventScope({
|
|
3782
3671
|
ctx,
|
|
3783
3672
|
body,
|
|
3784
3673
|
context,
|
|
@@ -3843,7 +3732,7 @@ function registerSlackAgentEvents(params) {
|
|
|
3843
3732
|
accountId: runtimeContext.accountId
|
|
3844
3733
|
});
|
|
3845
3734
|
if (runtimeContext.shouldDropMismatchedSlackEvent(body)) return;
|
|
3846
|
-
const eventScope =
|
|
3735
|
+
const eventScope = resolveSlackMonitorEventScope({
|
|
3847
3736
|
ctx: runtimeContext,
|
|
3848
3737
|
body,
|
|
3849
3738
|
context,
|
|
@@ -3878,9 +3767,7 @@ function registerSlackAgentEvents(params) {
|
|
|
3878
3767
|
storePath: resolveStorePath(runtimeContext.cfg.session?.store, { agentId: routing.route.agentId }),
|
|
3879
3768
|
sessionKey: routing.sessionKey,
|
|
3880
3769
|
preserveActivity: true,
|
|
3881
|
-
assertCommitAllowed:
|
|
3882
|
-
if (!routing.isCurrentSession()) throw new Error("Slack conversation owner changed before the title update");
|
|
3883
|
-
},
|
|
3770
|
+
assertCommitAllowed: routing.assertCurrentSession,
|
|
3884
3771
|
update: () => ({ displayName: event.title })
|
|
3885
3772
|
})) throw new Error("Slack conversation session disappeared before the title update");
|
|
3886
3773
|
runtimeContext.recordSlackSessionTitle({
|
|
@@ -4015,7 +3902,7 @@ function registerSlackChannelEvents(params) {
|
|
|
4015
3902
|
const { ctx, trackEvent } = params;
|
|
4016
3903
|
for (const [eventName, kind] of [["channel_created", "created"], ["channel_rename", "renamed"]]) ctx.app.event(eventName, async (args) => {
|
|
4017
3904
|
const { event, body, context, client } = args;
|
|
4018
|
-
const eventScope =
|
|
3905
|
+
const eventScope = resolveSlackMonitorEventScope({
|
|
4019
3906
|
ctx,
|
|
4020
3907
|
body,
|
|
4021
3908
|
context,
|
|
@@ -4180,18 +4067,117 @@ async function dispatchSlackPluginInteractiveHandler(params) {
|
|
|
4180
4067
|
}
|
|
4181
4068
|
//#endregion
|
|
4182
4069
|
//#region extensions/slack/src/monitor/events/interaction-event.ts
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4070
|
+
const SLACK_INTERACTION_EVENT_PREFIX = "Slack interaction: ";
|
|
4071
|
+
const REDACTED_INTERACTION_VALUE = "[redacted]";
|
|
4072
|
+
const SLACK_INTERACTION_EVENT_MAX_CHARS = 2400;
|
|
4073
|
+
const SLACK_INTERACTION_STRING_MAX_CHARS = 160;
|
|
4074
|
+
const SLACK_INTERACTION_ARRAY_MAX_ITEMS = 64;
|
|
4075
|
+
const SLACK_INTERACTION_COMPACT_INPUTS_MAX_ITEMS = 3;
|
|
4076
|
+
const SLACK_INTERACTION_REDACTED_KEYS = /* @__PURE__ */ new Set([
|
|
4077
|
+
"triggerId",
|
|
4078
|
+
"responseUrl",
|
|
4079
|
+
"workflowTriggerUrl",
|
|
4080
|
+
"privateMetadata",
|
|
4081
|
+
"viewHash"
|
|
4082
|
+
]);
|
|
4083
|
+
function sanitizeSlackInteractionPayloadValue(value, key) {
|
|
4084
|
+
if (value === void 0) return;
|
|
4085
|
+
if (key && SLACK_INTERACTION_REDACTED_KEYS.has(key)) {
|
|
4086
|
+
if (typeof value !== "string" || value.trim().length === 0) return;
|
|
4087
|
+
return REDACTED_INTERACTION_VALUE;
|
|
4088
|
+
}
|
|
4089
|
+
if (typeof value === "string") return truncateSlackText(value, SLACK_INTERACTION_STRING_MAX_CHARS);
|
|
4090
|
+
if (Array.isArray(value)) {
|
|
4091
|
+
const sanitized = value.slice(0, SLACK_INTERACTION_ARRAY_MAX_ITEMS).map((entry) => sanitizeSlackInteractionPayloadValue(entry)).filter((entry) => entry !== void 0);
|
|
4092
|
+
if (value.length > SLACK_INTERACTION_ARRAY_MAX_ITEMS) sanitized.push(`…+${value.length - SLACK_INTERACTION_ARRAY_MAX_ITEMS} more`);
|
|
4093
|
+
return sanitized;
|
|
4094
|
+
}
|
|
4095
|
+
if (!value || typeof value !== "object") return value;
|
|
4096
|
+
const output = {};
|
|
4097
|
+
for (const [entryKey, entryValue] of Object.entries(value)) {
|
|
4098
|
+
const sanitized = sanitizeSlackInteractionPayloadValue(entryValue, entryKey);
|
|
4099
|
+
if (sanitized === void 0) continue;
|
|
4100
|
+
if (typeof sanitized === "string" && sanitized.length === 0) continue;
|
|
4101
|
+
if (Array.isArray(sanitized) && sanitized.length === 0) continue;
|
|
4102
|
+
output[entryKey] = sanitized;
|
|
4194
4103
|
}
|
|
4104
|
+
return output;
|
|
4105
|
+
}
|
|
4106
|
+
function buildCompactSlackInteractionPayload(payload) {
|
|
4107
|
+
const rawInputs = Array.isArray(payload.inputs) ? payload.inputs : [];
|
|
4108
|
+
const compactInputs = rawInputs.slice(0, SLACK_INTERACTION_COMPACT_INPUTS_MAX_ITEMS).flatMap((entry) => {
|
|
4109
|
+
const typed = asOptionalObjectRecord(entry);
|
|
4110
|
+
if (!typed) return [];
|
|
4111
|
+
return [{
|
|
4112
|
+
actionId: typed.actionId,
|
|
4113
|
+
blockId: typed.blockId,
|
|
4114
|
+
actionType: typed.actionType,
|
|
4115
|
+
inputKind: typed.inputKind,
|
|
4116
|
+
selectedValues: typed.selectedValues,
|
|
4117
|
+
selectedLabels: typed.selectedLabels,
|
|
4118
|
+
inputValue: typed.inputValue,
|
|
4119
|
+
inputNumber: typed.inputNumber,
|
|
4120
|
+
selectedDate: typed.selectedDate,
|
|
4121
|
+
selectedTime: typed.selectedTime,
|
|
4122
|
+
selectedDateTime: typed.selectedDateTime,
|
|
4123
|
+
richTextPreview: typed.richTextPreview
|
|
4124
|
+
}];
|
|
4125
|
+
});
|
|
4126
|
+
return {
|
|
4127
|
+
interactionType: payload.interactionType,
|
|
4128
|
+
actionId: payload.actionId,
|
|
4129
|
+
callbackId: payload.callbackId,
|
|
4130
|
+
actionType: payload.actionType,
|
|
4131
|
+
actionTs: payload.actionTs,
|
|
4132
|
+
userId: payload.userId,
|
|
4133
|
+
teamId: payload.teamId,
|
|
4134
|
+
channelId: payload.channelId ?? payload.routedChannelId,
|
|
4135
|
+
messageTs: payload.messageTs,
|
|
4136
|
+
threadTs: payload.threadTs,
|
|
4137
|
+
messageUserId: payload.messageUserId,
|
|
4138
|
+
messageText: payload.messageText,
|
|
4139
|
+
viewId: payload.viewId,
|
|
4140
|
+
isCleared: payload.isCleared,
|
|
4141
|
+
selectedValues: payload.selectedValues,
|
|
4142
|
+
selectedLabels: payload.selectedLabels,
|
|
4143
|
+
selectedDate: payload.selectedDate,
|
|
4144
|
+
selectedTime: payload.selectedTime,
|
|
4145
|
+
selectedDateTime: payload.selectedDateTime,
|
|
4146
|
+
workflowId: payload.workflowId,
|
|
4147
|
+
routedChannelType: payload.routedChannelType,
|
|
4148
|
+
pluginHandled: payload.pluginHandled,
|
|
4149
|
+
pluginNamespace: payload.pluginNamespace,
|
|
4150
|
+
pluginDuplicate: payload.pluginDuplicate,
|
|
4151
|
+
pluginSystemEvent: payload.pluginSystemEvent,
|
|
4152
|
+
inputs: compactInputs.length > 0 ? compactInputs : void 0,
|
|
4153
|
+
inputsOmitted: rawInputs.length > SLACK_INTERACTION_COMPACT_INPUTS_MAX_ITEMS ? rawInputs.length - SLACK_INTERACTION_COMPACT_INPUTS_MAX_ITEMS : void 0,
|
|
4154
|
+
payloadTruncated: true
|
|
4155
|
+
};
|
|
4156
|
+
}
|
|
4157
|
+
function formatSlackInteractionSystemEvent(payload) {
|
|
4158
|
+
const toEventText = (value) => `${SLACK_INTERACTION_EVENT_PREFIX}${JSON.stringify(value)}`;
|
|
4159
|
+
const sanitizedPayload = sanitizeSlackInteractionPayloadValue(payload) ?? {};
|
|
4160
|
+
let eventText = toEventText(sanitizedPayload);
|
|
4161
|
+
if (eventText.length <= SLACK_INTERACTION_EVENT_MAX_CHARS) return eventText;
|
|
4162
|
+
eventText = toEventText(sanitizeSlackInteractionPayloadValue(buildCompactSlackInteractionPayload(sanitizedPayload)));
|
|
4163
|
+
if (eventText.length <= SLACK_INTERACTION_EVENT_MAX_CHARS) return eventText;
|
|
4164
|
+
return toEventText({
|
|
4165
|
+
interactionType: sanitizedPayload.interactionType,
|
|
4166
|
+
actionId: sanitizedPayload.actionId ?? "unknown",
|
|
4167
|
+
userId: sanitizedPayload.userId,
|
|
4168
|
+
channelId: sanitizedPayload.channelId ?? sanitizedPayload.routedChannelId,
|
|
4169
|
+
payloadTruncated: true
|
|
4170
|
+
});
|
|
4171
|
+
}
|
|
4172
|
+
function enqueueSlackInteractionEvent(payload, route, options) {
|
|
4173
|
+
if (enqueueRoutedSystemEvent(formatSlackInteractionSystemEvent(payload), route, options)) requestHeartbeat({
|
|
4174
|
+
source: "hook",
|
|
4175
|
+
intent: "immediate",
|
|
4176
|
+
reason: "hook:slack-interaction",
|
|
4177
|
+
agentId: route.agentId,
|
|
4178
|
+
sessionKey: route.sessionKey,
|
|
4179
|
+
heartbeat: { target: "last" }
|
|
4180
|
+
});
|
|
4195
4181
|
}
|
|
4196
4182
|
//#endregion
|
|
4197
4183
|
//#region extensions/slack/src/monitor/events/interactions.approval-sender.ts
|
|
@@ -4211,14 +4197,14 @@ function resolveSlackPluginApprovalSender(params) {
|
|
|
4211
4197
|
};
|
|
4212
4198
|
}
|
|
4213
4199
|
//#endregion
|
|
4214
|
-
//#region extensions/slack/src/monitor/events/
|
|
4200
|
+
//#region extensions/slack/src/monitor/events/modal-input-summary.ts
|
|
4215
4201
|
function readOptionStrings(options, read) {
|
|
4216
4202
|
if (!Array.isArray(options)) return [];
|
|
4217
4203
|
return options.map((option) => option && typeof option === "object" ? read(option) : void 0).filter((value) => typeof value === "string" && value.trim().length > 0);
|
|
4218
4204
|
}
|
|
4219
4205
|
function collectRichTextFragments(value, out) {
|
|
4220
|
-
|
|
4221
|
-
|
|
4206
|
+
const typed = asOptionalObjectRecord(value);
|
|
4207
|
+
if (!typed) return;
|
|
4222
4208
|
if (typeof typed.text === "string" && typed.text.trim().length > 0) out.push(typed.text.trim());
|
|
4223
4209
|
if (Array.isArray(typed.elements)) for (const child of typed.elements) collectRichTextFragments(child, out);
|
|
4224
4210
|
}
|
|
@@ -4246,12 +4232,7 @@ function summarizeAction(action) {
|
|
|
4246
4232
|
const inputValue = typeof typed.value === "string" ? typed.value : void 0;
|
|
4247
4233
|
const inputNumber = actionType === "number_input" && inputValue != null ? parseStrictFiniteNumber(inputValue) : void 0;
|
|
4248
4234
|
const inputEmail = actionType === "email_text_input" && inputValue?.includes("@") ? inputValue : void 0;
|
|
4249
|
-
|
|
4250
|
-
if (actionType === "url_text_input" && inputValue) try {
|
|
4251
|
-
inputUrl = new URL(inputValue).toString();
|
|
4252
|
-
} catch {
|
|
4253
|
-
inputUrl = void 0;
|
|
4254
|
-
}
|
|
4235
|
+
const inputUrl = actionType === "url_text_input" && inputValue ? URL.parse(inputValue)?.toString() : void 0;
|
|
4255
4236
|
const richTextValue = actionType === "rich_text_input" ? typed.rich_text_value : void 0;
|
|
4256
4237
|
const richTextPreview = summarizeRichTextPreview(richTextValue);
|
|
4257
4238
|
return {
|
|
@@ -4276,10 +4257,32 @@ function summarizeAction(action) {
|
|
|
4276
4257
|
workflowId: typed.workflow?.workflow_id
|
|
4277
4258
|
};
|
|
4278
4259
|
}
|
|
4279
|
-
function
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4260
|
+
function summarizeSlackViewState(values) {
|
|
4261
|
+
const blocks = asOptionalObjectRecord(values);
|
|
4262
|
+
if (!blocks) return [];
|
|
4263
|
+
const entries = [];
|
|
4264
|
+
for (const [blockId, blockValue] of Object.entries(blocks)) {
|
|
4265
|
+
const actions = asOptionalObjectRecord(blockValue);
|
|
4266
|
+
if (!actions) continue;
|
|
4267
|
+
for (const [actionId, rawAction] of Object.entries(actions)) {
|
|
4268
|
+
const action = asOptionalObjectRecord(rawAction);
|
|
4269
|
+
if (!action) continue;
|
|
4270
|
+
const actionSummary = summarizeAction(action);
|
|
4271
|
+
entries.push({
|
|
4272
|
+
blockId,
|
|
4273
|
+
actionId,
|
|
4274
|
+
...actionSummary
|
|
4275
|
+
});
|
|
4276
|
+
}
|
|
4277
|
+
}
|
|
4278
|
+
return entries;
|
|
4279
|
+
}
|
|
4280
|
+
//#endregion
|
|
4281
|
+
//#region extensions/slack/src/monitor/events/interactions.block-actions.ts
|
|
4282
|
+
function formatInteractionSelectionLabel(params) {
|
|
4283
|
+
if (params.summary.actionType === "button" && params.buttonText?.trim()) return params.buttonText.trim();
|
|
4284
|
+
const selected = params.summary.selectedLabels?.length ? params.summary.selectedLabels : params.summary.selectedValues;
|
|
4285
|
+
if (selected?.length) return selected.length <= 3 ? selected.join(", ") : `${selected.slice(0, 3).join(", ")} +${selected.length - 3}`;
|
|
4283
4286
|
if (params.summary.selectedDate) return params.summary.selectedDate;
|
|
4284
4287
|
if (params.summary.selectedTime) return params.summary.selectedTime;
|
|
4285
4288
|
if (typeof params.summary.selectedDateTime === "number") {
|
|
@@ -4458,7 +4461,7 @@ async function handleSlackApprovalInteraction(params) {
|
|
|
4458
4461
|
channelId,
|
|
4459
4462
|
messageTs
|
|
4460
4463
|
}, async () => {
|
|
4461
|
-
const { readSlackMessages } = await import("./actions-
|
|
4464
|
+
const { readSlackMessages } = await import("./actions-KGKwTAKO.mjs").then((n) => n.t);
|
|
4462
4465
|
const { messages } = await readSlackMessages(channelId, {
|
|
4463
4466
|
client: params.eventScope?.client ?? params.ctx.app.client,
|
|
4464
4467
|
messageId: messageTs,
|
|
@@ -4657,23 +4660,21 @@ function enqueueSlackBlockActionEvent(params) {
|
|
|
4657
4660
|
threadTs: params.parsed.threadTs
|
|
4658
4661
|
};
|
|
4659
4662
|
params.ctx.runtime.log?.(`slack:interaction action=${params.parsed.actionId} type=${params.parsed.actionSummary.actionType ?? "unknown"} user=${params.parsed.userId} channel=${params.parsed.channelId}`);
|
|
4660
|
-
|
|
4663
|
+
enqueueSlackInteractionEvent(eventPayload, params.ctx.resolveSlackSystemEventRoute({
|
|
4661
4664
|
channelId: params.parsed.channelId,
|
|
4662
4665
|
channelType: params.auth.channelType,
|
|
4663
4666
|
senderId: params.parsed.userId,
|
|
4664
4667
|
threadTs: params.parsed.threadTs,
|
|
4665
4668
|
eventScope: params.eventScope
|
|
4666
|
-
})
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
enqueueSlackInteractionEvent(params.formatSystemEvent(eventPayload), route, {
|
|
4676
|
-
contextKey: contextParts.join(":"),
|
|
4669
|
+
}), {
|
|
4670
|
+
contextKey: [
|
|
4671
|
+
"slack:interaction",
|
|
4672
|
+
params.teamId,
|
|
4673
|
+
params.parsed.channelId,
|
|
4674
|
+
params.parsed.messageTs,
|
|
4675
|
+
params.parsed.actionId,
|
|
4676
|
+
normalizeOptionalString(params.parsed.typedActionWithText.action_ts) ?? params.parsed.typedBody.trigger_id
|
|
4677
|
+
].filter(Boolean).join(":"),
|
|
4677
4678
|
deliveryContext: {
|
|
4678
4679
|
channel: "slack",
|
|
4679
4680
|
to: deferredTarget?.target,
|
|
@@ -4723,12 +4724,11 @@ function registerSlackBlockActionHandler(params) {
|
|
|
4723
4724
|
const { ack, body, action, respond } = args;
|
|
4724
4725
|
await ack();
|
|
4725
4726
|
const runtimeContext = await params.ctx.readRuntimeContext();
|
|
4726
|
-
const eventScope =
|
|
4727
|
-
|
|
4727
|
+
const eventScope = resolveSlackMonitorEventScope({
|
|
4728
|
+
ctx: runtimeContext,
|
|
4728
4729
|
body,
|
|
4729
4730
|
context: args.context,
|
|
4730
4731
|
client: args.client,
|
|
4731
|
-
clientOptions: runtimeContext.app.webClientOptions,
|
|
4732
4732
|
onDrop: (reason) => runtimeContext.runtime.log?.(`slack:interaction drop action ${reason}`)
|
|
4733
4733
|
});
|
|
4734
4734
|
if (eventScope === null) return;
|
|
@@ -4811,8 +4811,7 @@ function registerSlackBlockActionHandler(params) {
|
|
|
4811
4811
|
enqueueSlackBlockActionEvent({
|
|
4812
4812
|
...actionContext,
|
|
4813
4813
|
teamId: args.context.teamId,
|
|
4814
|
-
auth
|
|
4815
|
-
formatSystemEvent: params.formatSystemEvent
|
|
4814
|
+
auth
|
|
4816
4815
|
});
|
|
4817
4816
|
await updateSlackLegacyBlockAction(actionContext);
|
|
4818
4817
|
});
|
|
@@ -4850,14 +4849,12 @@ function shouldHandleSlackModalLifecycleBody(body) {
|
|
|
4850
4849
|
return Boolean(metadata.pluginInteractiveData?.trim());
|
|
4851
4850
|
}
|
|
4852
4851
|
function resolveSlackPluginSystemEventPayload(result) {
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
if (!systemEvent || typeof systemEvent !== "object") return;
|
|
4856
|
-
const typed = systemEvent;
|
|
4852
|
+
const systemEvent = asOptionalObjectRecord(asOptionalObjectRecord(result)?.systemEvent);
|
|
4853
|
+
if (!systemEvent) return;
|
|
4857
4854
|
const output = {};
|
|
4858
|
-
if (typeof
|
|
4859
|
-
if (typeof
|
|
4860
|
-
if (
|
|
4855
|
+
if (typeof systemEvent.summary === "string" && systemEvent.summary.trim()) output.summary = systemEvent.summary;
|
|
4856
|
+
if (typeof systemEvent.reference === "string" && systemEvent.reference.trim()) output.reference = systemEvent.reference;
|
|
4857
|
+
if (systemEvent.data && typeof systemEvent.data === "object" && !Array.isArray(systemEvent.data)) output.data = systemEvent.data;
|
|
4861
4858
|
return Object.keys(output).length > 0 ? output : void 0;
|
|
4862
4859
|
}
|
|
4863
4860
|
function resolveModalSessionRouting(params) {
|
|
@@ -4869,22 +4866,19 @@ function resolveModalSessionRouting(params) {
|
|
|
4869
4866
|
channelId: metadata.channelId,
|
|
4870
4867
|
channelType: metadata.channelType
|
|
4871
4868
|
};
|
|
4872
|
-
const routing =
|
|
4873
|
-
...params.ctx.resolveSlackSystemEventRoute({
|
|
4874
|
-
channelId: metadata.channelId,
|
|
4875
|
-
channelType: metadata.channelType,
|
|
4876
|
-
senderId: params.userId,
|
|
4877
|
-
eventScope: params.eventScope
|
|
4878
|
-
}),
|
|
4879
|
-
channelId: metadata.channelId,
|
|
4880
|
-
channelType: metadata.channelType
|
|
4881
|
-
} : {
|
|
4869
|
+
const routing = {
|
|
4882
4870
|
...params.ctx.resolveSlackSystemEventRoute({
|
|
4883
|
-
|
|
4871
|
+
...metadata.channelId ? {
|
|
4872
|
+
channelId: metadata.channelId,
|
|
4873
|
+
channelType: metadata.channelType
|
|
4874
|
+
} : { channelType: "im" },
|
|
4884
4875
|
senderId: params.userId,
|
|
4885
4876
|
eventScope: params.eventScope
|
|
4886
4877
|
}),
|
|
4887
|
-
|
|
4878
|
+
...metadata.channelId ? {
|
|
4879
|
+
channelId: metadata.channelId,
|
|
4880
|
+
channelType: metadata.channelType
|
|
4881
|
+
} : { channelType: params.eventScope ? "im" : void 0 }
|
|
4888
4882
|
};
|
|
4889
4883
|
if (metadata.sessionKey && (metadata.sessionKey === routing.sessionKey || metadata.sessionKey.startsWith(`${routing.sessionKey}:thread:`))) return {
|
|
4890
4884
|
...routing,
|
|
@@ -4892,105 +4886,35 @@ function resolveModalSessionRouting(params) {
|
|
|
4892
4886
|
};
|
|
4893
4887
|
return routing;
|
|
4894
4888
|
}
|
|
4895
|
-
function
|
|
4889
|
+
async function emitSlackModalLifecycleEvent(params) {
|
|
4896
4890
|
const metadata = parseSlackModalPrivateMetadata(params.body.view?.private_metadata);
|
|
4897
4891
|
const callbackId = params.body.view?.callback_id ?? "unknown";
|
|
4898
4892
|
const userId = params.body.user?.id ?? "unknown";
|
|
4899
4893
|
const viewId = params.body.view?.id;
|
|
4900
|
-
const inputs =
|
|
4894
|
+
const inputs = summarizeSlackViewState(params.body.view?.state?.values);
|
|
4901
4895
|
const sessionRouting = resolveModalSessionRouting({
|
|
4902
4896
|
ctx: params.ctx,
|
|
4903
4897
|
metadata,
|
|
4904
4898
|
userId,
|
|
4905
4899
|
eventScope: params.eventScope
|
|
4906
4900
|
});
|
|
4907
|
-
|
|
4901
|
+
const stateValues = params.body.view?.state?.values;
|
|
4902
|
+
const payload = {
|
|
4903
|
+
actionId: `view:${callbackId}`,
|
|
4908
4904
|
callbackId,
|
|
4909
|
-
userId,
|
|
4910
|
-
metadata,
|
|
4911
4905
|
viewId,
|
|
4912
|
-
|
|
4913
|
-
stateValues: params.body.view?.state?.values,
|
|
4914
|
-
payload: {
|
|
4915
|
-
actionId: `view:${callbackId}`,
|
|
4916
|
-
callbackId,
|
|
4917
|
-
viewId,
|
|
4918
|
-
userId,
|
|
4919
|
-
teamId: params.teamId,
|
|
4920
|
-
rootViewId: params.body.view?.root_view_id,
|
|
4921
|
-
previousViewId: params.body.view?.previous_view_id,
|
|
4922
|
-
externalId: params.body.view?.external_id,
|
|
4923
|
-
viewHash: params.body.view?.hash,
|
|
4924
|
-
isStackedView: Boolean(params.body.view?.previous_view_id),
|
|
4925
|
-
privateMetadata: params.body.view?.private_metadata,
|
|
4926
|
-
routedChannelId: sessionRouting.channelId,
|
|
4927
|
-
routedChannelType: sessionRouting.channelType,
|
|
4928
|
-
inputs
|
|
4929
|
-
}
|
|
4930
|
-
};
|
|
4931
|
-
}
|
|
4932
|
-
async function dispatchSlackModalPluginInteractiveHandler(params) {
|
|
4933
|
-
if (!params.data) return {
|
|
4934
|
-
matched: false,
|
|
4935
|
-
handled: false,
|
|
4936
|
-
duplicate: false
|
|
4937
|
-
};
|
|
4938
|
-
const isViewClosed = params.interactionType === "view_closed";
|
|
4939
|
-
const interactionId = [
|
|
4940
|
-
params.interactionType,
|
|
4941
|
-
params.payload.callbackId,
|
|
4942
|
-
params.payload.viewId,
|
|
4943
|
-
params.payload.userId
|
|
4944
|
-
].filter(Boolean).join(":");
|
|
4945
|
-
const result = await dispatchSlackPluginInteractiveHandler({
|
|
4946
|
-
data: params.data,
|
|
4947
|
-
interactionId,
|
|
4948
|
-
teamId: params.eventScope?.teamId,
|
|
4949
|
-
channelType: params.channelType,
|
|
4950
|
-
ctx: {
|
|
4951
|
-
accountId: params.ctx.accountId,
|
|
4952
|
-
interactionId,
|
|
4953
|
-
conversationId: params.sessionRouting.channelId ?? "",
|
|
4954
|
-
parentConversationId: void 0,
|
|
4955
|
-
threadId: void 0,
|
|
4956
|
-
senderId: params.payload.userId,
|
|
4957
|
-
senderUsername: void 0,
|
|
4958
|
-
auth: params.auth,
|
|
4959
|
-
interaction: {
|
|
4960
|
-
kind: params.interactionType,
|
|
4961
|
-
callbackId: params.payload.callbackId,
|
|
4962
|
-
viewId: params.payload.viewId,
|
|
4963
|
-
rootViewId: params.payload.rootViewId,
|
|
4964
|
-
previousViewId: params.payload.previousViewId,
|
|
4965
|
-
externalId: params.payload.externalId,
|
|
4966
|
-
isStackedView: params.payload.isStackedView,
|
|
4967
|
-
isCleared: isViewClosed ? params.body.is_cleared === true : void 0,
|
|
4968
|
-
inputs: params.payload.inputs,
|
|
4969
|
-
stateValues: params.stateValues,
|
|
4970
|
-
triggerId: params.body.trigger_id
|
|
4971
|
-
}
|
|
4972
|
-
},
|
|
4973
|
-
respond: {
|
|
4974
|
-
acknowledge: async () => {},
|
|
4975
|
-
reply: async () => {},
|
|
4976
|
-
followUp: async () => {},
|
|
4977
|
-
editMessage: async () => {}
|
|
4978
|
-
}
|
|
4979
|
-
});
|
|
4980
|
-
return {
|
|
4981
|
-
...result,
|
|
4982
|
-
namespace: result.matched ? params.data.split(":", 1)[0] : void 0,
|
|
4983
|
-
systemEvent: result.matched ? resolveSlackPluginSystemEventPayload(result.result) : void 0
|
|
4984
|
-
};
|
|
4985
|
-
}
|
|
4986
|
-
async function emitSlackModalLifecycleEvent(params) {
|
|
4987
|
-
const { callbackId, userId, metadata, viewId, sessionRouting, stateValues, payload } = resolveSlackModalEventBase({
|
|
4988
|
-
ctx: params.ctx,
|
|
4989
|
-
body: params.body,
|
|
4990
|
-
eventScope: params.eventScope,
|
|
4906
|
+
userId,
|
|
4991
4907
|
teamId: params.teamId,
|
|
4992
|
-
|
|
4993
|
-
|
|
4908
|
+
rootViewId: params.body.view?.root_view_id,
|
|
4909
|
+
previousViewId: params.body.view?.previous_view_id,
|
|
4910
|
+
externalId: params.body.view?.external_id,
|
|
4911
|
+
viewHash: params.body.view?.hash,
|
|
4912
|
+
isStackedView: Boolean(params.body.view?.previous_view_id),
|
|
4913
|
+
privateMetadata: params.body.view?.private_metadata,
|
|
4914
|
+
routedChannelId: sessionRouting.channelId,
|
|
4915
|
+
routedChannelType: sessionRouting.channelType,
|
|
4916
|
+
inputs
|
|
4917
|
+
};
|
|
4994
4918
|
const pluginInteractiveData = resolveSlackModalPluginInteractiveData({
|
|
4995
4919
|
callbackId,
|
|
4996
4920
|
metadata
|
|
@@ -5006,18 +4930,53 @@ async function emitSlackModalLifecycleEvent(params) {
|
|
|
5006
4930
|
else params.ctx.runtime.log?.(`slack:interaction view_submission callback=${callbackId} user=${userId} inputs=${payload.inputs.length}`);
|
|
5007
4931
|
const dispatchPlugin = async (isAuthorizedSender, channelType) => {
|
|
5008
4932
|
try {
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
4933
|
+
if (!pluginInteractiveData) return;
|
|
4934
|
+
const interactionId = [
|
|
4935
|
+
params.interactionType,
|
|
4936
|
+
payload.callbackId,
|
|
4937
|
+
payload.viewId,
|
|
4938
|
+
payload.userId
|
|
4939
|
+
].filter(Boolean).join(":");
|
|
4940
|
+
const result = await dispatchSlackPluginInteractiveHandler({
|
|
5014
4941
|
data: pluginInteractiveData,
|
|
5015
|
-
|
|
4942
|
+
interactionId,
|
|
4943
|
+
teamId: params.eventScope?.teamId,
|
|
5016
4944
|
channelType,
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
4945
|
+
ctx: {
|
|
4946
|
+
accountId: params.ctx.accountId,
|
|
4947
|
+
interactionId,
|
|
4948
|
+
conversationId: sessionRouting.channelId ?? "",
|
|
4949
|
+
parentConversationId: void 0,
|
|
4950
|
+
threadId: void 0,
|
|
4951
|
+
senderId: payload.userId,
|
|
4952
|
+
senderUsername: void 0,
|
|
4953
|
+
auth: { isAuthorizedSender },
|
|
4954
|
+
interaction: {
|
|
4955
|
+
kind: params.interactionType,
|
|
4956
|
+
callbackId: payload.callbackId,
|
|
4957
|
+
viewId: payload.viewId,
|
|
4958
|
+
rootViewId: payload.rootViewId,
|
|
4959
|
+
previousViewId: payload.previousViewId,
|
|
4960
|
+
externalId: payload.externalId,
|
|
4961
|
+
isStackedView: payload.isStackedView,
|
|
4962
|
+
isCleared: isViewClosed ? params.body.is_cleared === true : void 0,
|
|
4963
|
+
inputs: payload.inputs,
|
|
4964
|
+
stateValues,
|
|
4965
|
+
triggerId: params.body.trigger_id
|
|
4966
|
+
}
|
|
4967
|
+
},
|
|
4968
|
+
respond: {
|
|
4969
|
+
acknowledge: async () => {},
|
|
4970
|
+
reply: async () => {},
|
|
4971
|
+
followUp: async () => {},
|
|
4972
|
+
editMessage: async () => {}
|
|
4973
|
+
}
|
|
5020
4974
|
});
|
|
4975
|
+
return {
|
|
4976
|
+
...result,
|
|
4977
|
+
namespace: result.matched ? pluginInteractiveData.split(":", 1)[0] : void 0,
|
|
4978
|
+
systemEvent: result.matched ? resolveSlackPluginSystemEventPayload(result.result) : void 0
|
|
4979
|
+
};
|
|
5021
4980
|
} catch (error) {
|
|
5022
4981
|
params.ctx.runtime.log?.(`slack:interaction modal plugin dispatch failed callback=${callbackId} error=${error instanceof Error ? error.message : String(error)}`);
|
|
5023
4982
|
return;
|
|
@@ -5055,12 +5014,12 @@ async function emitSlackModalLifecycleEvent(params) {
|
|
|
5055
5014
|
kind: targetKind,
|
|
5056
5015
|
id: targetId
|
|
5057
5016
|
}) : void 0;
|
|
5058
|
-
enqueueSlackInteractionEvent(
|
|
5017
|
+
enqueueSlackInteractionEvent({
|
|
5059
5018
|
...eventPayload,
|
|
5060
5019
|
...pluginEventFields
|
|
5061
|
-
}
|
|
5020
|
+
}, sessionRouting, {
|
|
5062
5021
|
contextKey: [
|
|
5063
|
-
|
|
5022
|
+
isViewClosed ? "slack:interaction:view-closed" : "slack:interaction:view",
|
|
5064
5023
|
params.teamId,
|
|
5065
5024
|
callbackId,
|
|
5066
5025
|
viewId,
|
|
@@ -5074,16 +5033,18 @@ async function emitSlackModalLifecycleEvent(params) {
|
|
|
5074
5033
|
});
|
|
5075
5034
|
}
|
|
5076
5035
|
function registerModalLifecycleHandler(params) {
|
|
5077
|
-
params.
|
|
5036
|
+
params.ctx.app.view({
|
|
5037
|
+
callback_id: /.*/,
|
|
5038
|
+
type: params.interactionType
|
|
5039
|
+
}, async (args) => {
|
|
5078
5040
|
const { ack, body } = args;
|
|
5079
5041
|
if (!shouldHandleSlackModalLifecycleBody(body)) return;
|
|
5080
5042
|
await ack();
|
|
5081
|
-
const eventScope =
|
|
5082
|
-
|
|
5043
|
+
const eventScope = resolveSlackMonitorEventScope({
|
|
5044
|
+
ctx: params.ctx,
|
|
5083
5045
|
body,
|
|
5084
5046
|
context: args.context,
|
|
5085
5047
|
client: args.client,
|
|
5086
|
-
clientOptions: params.ctx.app.webClientOptions,
|
|
5087
5048
|
onDrop: (reason) => params.ctx.runtime.log?.(`slack:interaction drop ${params.interactionType} ${reason}`)
|
|
5088
5049
|
});
|
|
5089
5050
|
if (eventScope === null) return;
|
|
@@ -5098,10 +5059,7 @@ function registerModalLifecycleHandler(params) {
|
|
|
5098
5059
|
body: typedBody,
|
|
5099
5060
|
eventScope,
|
|
5100
5061
|
teamId: args.context.teamId,
|
|
5101
|
-
interactionType: params.interactionType
|
|
5102
|
-
contextPrefix: params.contextPrefix,
|
|
5103
|
-
summarizeViewState: params.summarizeViewState,
|
|
5104
|
-
formatSystemEvent: params.formatSystemEvent
|
|
5062
|
+
interactionType: params.interactionType
|
|
5105
5063
|
});
|
|
5106
5064
|
});
|
|
5107
5065
|
}
|
|
@@ -5113,12 +5071,11 @@ function registerSlackShortcutHandler(params) {
|
|
|
5113
5071
|
const { ack, body } = args;
|
|
5114
5072
|
await ack();
|
|
5115
5073
|
const runtimeContext = await params.ctx.readRuntimeContext();
|
|
5116
|
-
const eventScope =
|
|
5117
|
-
|
|
5074
|
+
const eventScope = resolveSlackMonitorEventScope({
|
|
5075
|
+
ctx: runtimeContext,
|
|
5118
5076
|
body,
|
|
5119
5077
|
context: args.context,
|
|
5120
5078
|
client: args.client,
|
|
5121
|
-
clientOptions: runtimeContext.app.webClientOptions,
|
|
5122
5079
|
onDrop: (reason) => runtimeContext.runtime.log?.(`slack:interaction drop shortcut ${reason}`)
|
|
5123
5080
|
});
|
|
5124
5081
|
if (eventScope === null) return;
|
|
@@ -5195,7 +5152,7 @@ function registerSlackShortcutHandler(params) {
|
|
|
5195
5152
|
body.action_ts
|
|
5196
5153
|
].filter(Boolean).join(":");
|
|
5197
5154
|
runtimeContext.runtime.log?.(`slack:interaction ${interactionType} callback=${callbackId} user=${userId} channel=${channelId ?? "direct"}`);
|
|
5198
|
-
enqueueSlackInteractionEvent(
|
|
5155
|
+
enqueueSlackInteractionEvent(eventPayload, route, {
|
|
5199
5156
|
contextKey,
|
|
5200
5157
|
deliveryContext: {
|
|
5201
5158
|
channel: "slack",
|
|
@@ -5208,152 +5165,47 @@ function registerSlackShortcutHandler(params) {
|
|
|
5208
5165
|
}
|
|
5209
5166
|
//#endregion
|
|
5210
5167
|
//#region extensions/slack/src/monitor/events/interactions.ts
|
|
5211
|
-
const SLACK_INTERACTION_EVENT_PREFIX = "Slack interaction: ";
|
|
5212
|
-
const REDACTED_INTERACTION_VALUE = "[redacted]";
|
|
5213
|
-
const SLACK_INTERACTION_EVENT_MAX_CHARS = 2400;
|
|
5214
|
-
const SLACK_INTERACTION_STRING_MAX_CHARS = 160;
|
|
5215
|
-
const SLACK_INTERACTION_ARRAY_MAX_ITEMS = 64;
|
|
5216
|
-
const SLACK_INTERACTION_COMPACT_INPUTS_MAX_ITEMS = 3;
|
|
5217
|
-
const SLACK_INTERACTION_REDACTED_KEYS = /* @__PURE__ */ new Set([
|
|
5218
|
-
"triggerId",
|
|
5219
|
-
"responseUrl",
|
|
5220
|
-
"workflowTriggerUrl",
|
|
5221
|
-
"privateMetadata",
|
|
5222
|
-
"viewHash"
|
|
5223
|
-
]);
|
|
5224
|
-
function sanitizeSlackInteractionPayloadValue(value, key) {
|
|
5225
|
-
if (value === void 0) return;
|
|
5226
|
-
if (key && SLACK_INTERACTION_REDACTED_KEYS.has(key)) {
|
|
5227
|
-
if (typeof value !== "string" || value.trim().length === 0) return;
|
|
5228
|
-
return REDACTED_INTERACTION_VALUE;
|
|
5229
|
-
}
|
|
5230
|
-
if (typeof value === "string") return truncateSlackText(value, SLACK_INTERACTION_STRING_MAX_CHARS);
|
|
5231
|
-
if (Array.isArray(value)) {
|
|
5232
|
-
const sanitized = value.slice(0, SLACK_INTERACTION_ARRAY_MAX_ITEMS).map((entry) => sanitizeSlackInteractionPayloadValue(entry)).filter((entry) => entry !== void 0);
|
|
5233
|
-
if (value.length > SLACK_INTERACTION_ARRAY_MAX_ITEMS) sanitized.push(`…+${value.length - SLACK_INTERACTION_ARRAY_MAX_ITEMS} more`);
|
|
5234
|
-
return sanitized;
|
|
5235
|
-
}
|
|
5236
|
-
if (!value || typeof value !== "object") return value;
|
|
5237
|
-
const output = {};
|
|
5238
|
-
for (const [entryKey, entryValue] of Object.entries(value)) {
|
|
5239
|
-
const sanitized = sanitizeSlackInteractionPayloadValue(entryValue, entryKey);
|
|
5240
|
-
if (sanitized === void 0) continue;
|
|
5241
|
-
if (typeof sanitized === "string" && sanitized.length === 0) continue;
|
|
5242
|
-
if (Array.isArray(sanitized) && sanitized.length === 0) continue;
|
|
5243
|
-
output[entryKey] = sanitized;
|
|
5244
|
-
}
|
|
5245
|
-
return output;
|
|
5246
|
-
}
|
|
5247
|
-
function buildCompactSlackInteractionPayload(payload) {
|
|
5248
|
-
const rawInputs = Array.isArray(payload.inputs) ? payload.inputs : [];
|
|
5249
|
-
const compactInputs = rawInputs.slice(0, SLACK_INTERACTION_COMPACT_INPUTS_MAX_ITEMS).flatMap((entry) => {
|
|
5250
|
-
if (!entry || typeof entry !== "object") return [];
|
|
5251
|
-
const typed = entry;
|
|
5252
|
-
return [{
|
|
5253
|
-
actionId: typed.actionId,
|
|
5254
|
-
blockId: typed.blockId,
|
|
5255
|
-
actionType: typed.actionType,
|
|
5256
|
-
inputKind: typed.inputKind,
|
|
5257
|
-
selectedValues: typed.selectedValues,
|
|
5258
|
-
selectedLabels: typed.selectedLabels,
|
|
5259
|
-
inputValue: typed.inputValue,
|
|
5260
|
-
inputNumber: typed.inputNumber,
|
|
5261
|
-
selectedDate: typed.selectedDate,
|
|
5262
|
-
selectedTime: typed.selectedTime,
|
|
5263
|
-
selectedDateTime: typed.selectedDateTime,
|
|
5264
|
-
richTextPreview: typed.richTextPreview
|
|
5265
|
-
}];
|
|
5266
|
-
});
|
|
5267
|
-
return {
|
|
5268
|
-
interactionType: payload.interactionType,
|
|
5269
|
-
actionId: payload.actionId,
|
|
5270
|
-
callbackId: payload.callbackId,
|
|
5271
|
-
actionType: payload.actionType,
|
|
5272
|
-
actionTs: payload.actionTs,
|
|
5273
|
-
userId: payload.userId,
|
|
5274
|
-
teamId: payload.teamId,
|
|
5275
|
-
channelId: payload.channelId ?? payload.routedChannelId,
|
|
5276
|
-
messageTs: payload.messageTs,
|
|
5277
|
-
threadTs: payload.threadTs,
|
|
5278
|
-
messageUserId: payload.messageUserId,
|
|
5279
|
-
messageText: payload.messageText,
|
|
5280
|
-
viewId: payload.viewId,
|
|
5281
|
-
isCleared: payload.isCleared,
|
|
5282
|
-
selectedValues: payload.selectedValues,
|
|
5283
|
-
selectedLabels: payload.selectedLabels,
|
|
5284
|
-
selectedDate: payload.selectedDate,
|
|
5285
|
-
selectedTime: payload.selectedTime,
|
|
5286
|
-
selectedDateTime: payload.selectedDateTime,
|
|
5287
|
-
workflowId: payload.workflowId,
|
|
5288
|
-
routedChannelType: payload.routedChannelType,
|
|
5289
|
-
pluginHandled: payload.pluginHandled,
|
|
5290
|
-
pluginNamespace: payload.pluginNamespace,
|
|
5291
|
-
pluginDuplicate: payload.pluginDuplicate,
|
|
5292
|
-
pluginSystemEvent: payload.pluginSystemEvent,
|
|
5293
|
-
inputs: compactInputs.length > 0 ? compactInputs : void 0,
|
|
5294
|
-
inputsOmitted: rawInputs.length > SLACK_INTERACTION_COMPACT_INPUTS_MAX_ITEMS ? rawInputs.length - SLACK_INTERACTION_COMPACT_INPUTS_MAX_ITEMS : void 0,
|
|
5295
|
-
payloadTruncated: true
|
|
5296
|
-
};
|
|
5297
|
-
}
|
|
5298
|
-
function formatSlackInteractionSystemEvent(payload) {
|
|
5299
|
-
const toEventText = (value) => `${SLACK_INTERACTION_EVENT_PREFIX}${JSON.stringify(value)}`;
|
|
5300
|
-
const sanitizedPayload = sanitizeSlackInteractionPayloadValue(payload) ?? {};
|
|
5301
|
-
let eventText = toEventText(sanitizedPayload);
|
|
5302
|
-
if (eventText.length <= SLACK_INTERACTION_EVENT_MAX_CHARS) return eventText;
|
|
5303
|
-
eventText = toEventText(sanitizeSlackInteractionPayloadValue(buildCompactSlackInteractionPayload(sanitizedPayload)));
|
|
5304
|
-
if (eventText.length <= SLACK_INTERACTION_EVENT_MAX_CHARS) return eventText;
|
|
5305
|
-
return toEventText({
|
|
5306
|
-
interactionType: sanitizedPayload.interactionType,
|
|
5307
|
-
actionId: sanitizedPayload.actionId ?? "unknown",
|
|
5308
|
-
userId: sanitizedPayload.userId,
|
|
5309
|
-
channelId: sanitizedPayload.channelId ?? sanitizedPayload.routedChannelId,
|
|
5310
|
-
payloadTruncated: true
|
|
5311
|
-
});
|
|
5312
|
-
}
|
|
5313
|
-
function summarizeViewState(values) {
|
|
5314
|
-
if (!values || typeof values !== "object") return [];
|
|
5315
|
-
const entries = [];
|
|
5316
|
-
for (const [blockId, blockValue] of Object.entries(values)) {
|
|
5317
|
-
if (!blockValue || typeof blockValue !== "object") continue;
|
|
5318
|
-
for (const [actionId, rawAction] of Object.entries(blockValue)) {
|
|
5319
|
-
if (!rawAction || typeof rawAction !== "object") continue;
|
|
5320
|
-
const actionSummary = summarizeAction(rawAction);
|
|
5321
|
-
entries.push({
|
|
5322
|
-
blockId,
|
|
5323
|
-
actionId,
|
|
5324
|
-
...actionSummary
|
|
5325
|
-
});
|
|
5326
|
-
}
|
|
5327
|
-
}
|
|
5328
|
-
return entries;
|
|
5329
|
-
}
|
|
5330
5168
|
function registerSlackInteractionEvents(params) {
|
|
5331
5169
|
const { ctx, trackEvent } = params;
|
|
5332
|
-
registerSlackBlockActionHandler(
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
});
|
|
5337
|
-
registerSlackShortcutHandler({
|
|
5170
|
+
registerSlackBlockActionHandler(params);
|
|
5171
|
+
registerSlackShortcutHandler(params);
|
|
5172
|
+
if (typeof ctx.app.view !== "function") return;
|
|
5173
|
+
for (const interactionType of ["view_submission", "view_closed"]) registerModalLifecycleHandler({
|
|
5338
5174
|
ctx,
|
|
5339
5175
|
trackEvent,
|
|
5340
|
-
|
|
5176
|
+
interactionType
|
|
5341
5177
|
});
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
matcher: modalMatcher,
|
|
5178
|
+
}
|
|
5179
|
+
//#endregion
|
|
5180
|
+
//#region extensions/slack/src/monitor/events/system-event-context.ts
|
|
5181
|
+
async function authorizeAndResolveSlackSystemEventContext(params) {
|
|
5182
|
+
const { senderId, channelId, channelType, eventKind } = params;
|
|
5183
|
+
const ctx = await params.ctx.readRuntimeContext();
|
|
5184
|
+
const auth = await authorizeSlackSystemEventSender({
|
|
5350
5185
|
ctx,
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5186
|
+
senderId,
|
|
5187
|
+
channelId,
|
|
5188
|
+
channelType,
|
|
5189
|
+
eventScope: params.eventScope,
|
|
5190
|
+
retryNameLookup: eventKind.startsWith("member-")
|
|
5356
5191
|
});
|
|
5192
|
+
if (!auth.allowed) {
|
|
5193
|
+
logVerbose(`slack: drop ${eventKind} sender ${senderId ?? "unknown"} channel=${channelId ?? "unknown"} reason=${auth.reason ?? "unauthorized"}`);
|
|
5194
|
+
return;
|
|
5195
|
+
}
|
|
5196
|
+
return {
|
|
5197
|
+
channelLabel: resolveSlackChannelLabel({
|
|
5198
|
+
channelId,
|
|
5199
|
+
channelName: auth.channelName
|
|
5200
|
+
}),
|
|
5201
|
+
route: ctx.resolveSlackSystemEventRoute({
|
|
5202
|
+
channelId,
|
|
5203
|
+
channelType: auth.channelType,
|
|
5204
|
+
senderId,
|
|
5205
|
+
threadTs: auth.channelType === "im" ? void 0 : params.threadTs,
|
|
5206
|
+
eventScope: params.eventScope
|
|
5207
|
+
})
|
|
5208
|
+
};
|
|
5357
5209
|
}
|
|
5358
5210
|
//#endregion
|
|
5359
5211
|
//#region extensions/slack/src/monitor/events/members.ts
|
|
@@ -5364,7 +5216,7 @@ function registerSlackMemberEvents(params) {
|
|
|
5364
5216
|
const eventId = body.event_id;
|
|
5365
5217
|
try {
|
|
5366
5218
|
const runtimeContext = await params.ctx.readRuntimeContext();
|
|
5367
|
-
const eventScope =
|
|
5219
|
+
const eventScope = resolveSlackMonitorEventScope({
|
|
5368
5220
|
ctx: runtimeContext,
|
|
5369
5221
|
body,
|
|
5370
5222
|
context,
|
|
@@ -5497,51 +5349,28 @@ function noteSlackDraftConversationMessage(conversation) {
|
|
|
5497
5349
|
}
|
|
5498
5350
|
//#endregion
|
|
5499
5351
|
//#region extensions/slack/src/monitor/events/message-subtype-handlers.ts
|
|
5500
|
-
function resolveNestedThreadTs(event) {
|
|
5501
|
-
const changed = event;
|
|
5502
|
-
const message = changed.message?.thread_ts ? changed.message : changed.previous_message;
|
|
5503
|
-
if (!message) return;
|
|
5504
|
-
return resolveSlackThreadContext({
|
|
5505
|
-
message: {
|
|
5506
|
-
type: "message",
|
|
5507
|
-
channel: event.channel,
|
|
5508
|
-
...message
|
|
5509
|
-
},
|
|
5510
|
-
replyToMode: "off"
|
|
5511
|
-
}).replyToId;
|
|
5512
|
-
}
|
|
5513
|
-
const SUBTYPE_HANDLER_REGISTRY = {
|
|
5514
|
-
message_changed: {
|
|
5515
|
-
eventKind: "message_changed",
|
|
5516
|
-
describe: (channelLabel) => `Slack message edited in ${channelLabel}.`,
|
|
5517
|
-
contextKey: (event) => {
|
|
5518
|
-
const changed = event;
|
|
5519
|
-
return `slack:message:changed:${changed.channel ?? "unknown"}:${changed.message?.ts ?? changed.previous_message?.ts ?? changed.event_ts ?? "unknown"}`;
|
|
5520
|
-
},
|
|
5521
|
-
resolveSenderId: (event) => {
|
|
5522
|
-
const changed = event;
|
|
5523
|
-
return changed.message?.user ?? changed.previous_message?.user ?? changed.message?.bot_id ?? changed.previous_message?.bot_id;
|
|
5524
|
-
},
|
|
5525
|
-
resolveThreadTs: resolveNestedThreadTs
|
|
5526
|
-
},
|
|
5527
|
-
message_deleted: {
|
|
5528
|
-
eventKind: "message_deleted",
|
|
5529
|
-
describe: (channelLabel) => `Slack message deleted in ${channelLabel}.`,
|
|
5530
|
-
contextKey: (event) => {
|
|
5531
|
-
const deleted = event;
|
|
5532
|
-
return `slack:message:deleted:${deleted.channel ?? "unknown"}:${deleted.deleted_ts ?? deleted.event_ts ?? "unknown"}`;
|
|
5533
|
-
},
|
|
5534
|
-
resolveSenderId: (event) => {
|
|
5535
|
-
const deleted = event;
|
|
5536
|
-
return deleted.previous_message?.user ?? deleted.previous_message?.bot_id;
|
|
5537
|
-
},
|
|
5538
|
-
resolveThreadTs: resolveNestedThreadTs
|
|
5539
|
-
}
|
|
5540
|
-
};
|
|
5541
5352
|
function resolveSlackMessageSubtypeHandler(event) {
|
|
5542
5353
|
const subtype = event.subtype;
|
|
5543
5354
|
if (subtype !== "message_changed" && subtype !== "message_deleted") return;
|
|
5544
|
-
|
|
5355
|
+
const changed = event;
|
|
5356
|
+
const message = changed.message?.thread_ts ? changed.message : changed.previous_message;
|
|
5357
|
+
const isChanged = subtype === "message_changed";
|
|
5358
|
+
const senderId = isChanged ? changed.message?.user ?? changed.previous_message?.user ?? changed.message?.bot_id ?? changed.previous_message?.bot_id : changed.previous_message?.user ?? changed.previous_message?.bot_id;
|
|
5359
|
+
const messageId = isChanged ? changed.message?.ts ?? changed.previous_message?.ts ?? changed.event_ts : event.deleted_ts ?? event.event_ts;
|
|
5360
|
+
return {
|
|
5361
|
+
eventKind: subtype,
|
|
5362
|
+
describe: (channelLabel) => `Slack message ${isChanged ? "edited" : "deleted"} in ${channelLabel}.`,
|
|
5363
|
+
contextKey: `slack:message:${isChanged ? "changed" : "deleted"}:${event.channel ?? "unknown"}:${messageId ?? "unknown"}`,
|
|
5364
|
+
senderId,
|
|
5365
|
+
threadTs: message ? resolveSlackThreadContext({
|
|
5366
|
+
message: {
|
|
5367
|
+
type: "message",
|
|
5368
|
+
channel: event.channel,
|
|
5369
|
+
...message
|
|
5370
|
+
},
|
|
5371
|
+
replyToMode: "off"
|
|
5372
|
+
}).replyToId : void 0
|
|
5373
|
+
};
|
|
5545
5374
|
}
|
|
5546
5375
|
//#endregion
|
|
5547
5376
|
//#region extensions/slack/src/monitor/events/messages.ts
|
|
@@ -5551,11 +5380,17 @@ function isBotAuthoredEnterpriseEvent(event) {
|
|
|
5551
5380
|
}
|
|
5552
5381
|
async function resolveSlackAppMentionChannelType(params) {
|
|
5553
5382
|
const explicitType = normalizeOptionalString(params.mention.channel_type);
|
|
5554
|
-
if (explicitType) return normalizeSlackChannelType(explicitType, params.mention.channel);
|
|
5383
|
+
if (explicitType) return { type: normalizeSlackChannelType(explicitType, params.mention.channel) };
|
|
5555
5384
|
const rememberedType = params.ctx.recallSlackChannelType(params.mention.channel, params.eventScope);
|
|
5556
|
-
if (rememberedType) return normalizeSlackChannelType(rememberedType, params.mention.channel);
|
|
5557
|
-
const resolved = await params.ctx.resolveChannelName(params.mention.channel, params.eventScope).catch(() => ({
|
|
5558
|
-
|
|
5385
|
+
if (rememberedType) return { type: normalizeSlackChannelType(rememberedType, params.mention.channel) };
|
|
5386
|
+
const resolved = await params.ctx.resolveChannelName(params.mention.channel, params.eventScope).catch(() => ({
|
|
5387
|
+
type: void 0,
|
|
5388
|
+
lookupFailureCategory: "other"
|
|
5389
|
+
}));
|
|
5390
|
+
return {
|
|
5391
|
+
type: resolved.type ? normalizeSlackChannelType(resolved.type, params.mention.channel) : void 0,
|
|
5392
|
+
lookupFailureCategory: resolved.lookupFailureCategory
|
|
5393
|
+
};
|
|
5559
5394
|
}
|
|
5560
5395
|
function resolveAssistantMessageChangedSender(params) {
|
|
5561
5396
|
const payload = asOptionalRecord(asOptionalRecord(params.message?.metadata)?.event_payload);
|
|
@@ -5614,14 +5449,6 @@ function resolveAssistantMessageChangedInbound(params) {
|
|
|
5614
5449
|
}
|
|
5615
5450
|
function registerSlackMessageEvents(params) {
|
|
5616
5451
|
const { ctx, handleSlackMessage } = params;
|
|
5617
|
-
const resolveEventScope = (args) => resolveSlackListenerEventScope$1({
|
|
5618
|
-
identity: ctx.installationIdentity,
|
|
5619
|
-
body: args.body,
|
|
5620
|
-
context: args.context,
|
|
5621
|
-
client: args.client,
|
|
5622
|
-
clientOptions: ctx.app.webClientOptions,
|
|
5623
|
-
onDrop: (reason) => logVerbose(`slack: drop event (${reason})`)
|
|
5624
|
-
});
|
|
5625
5452
|
const noteConversationMessage = (message, eventScope) => {
|
|
5626
5453
|
noteSlackDraftConversationMessage({
|
|
5627
5454
|
accountId: ctx.accountId,
|
|
@@ -5635,96 +5462,82 @@ function registerSlackMessageEvents(params) {
|
|
|
5635
5462
|
subtype: "subtype" in message ? normalizeOptionalString(message.subtype) : void 0
|
|
5636
5463
|
});
|
|
5637
5464
|
};
|
|
5638
|
-
const
|
|
5465
|
+
for (const source of ["message", "app_mention"]) ctx.app.event(source, async ({ event, body, context, client }) => {
|
|
5639
5466
|
const turnAdoptionLifecycle = resolveSlackIngressTurnLifecycle(context);
|
|
5640
5467
|
try {
|
|
5641
|
-
const eventScope =
|
|
5468
|
+
const eventScope = resolveSlackMonitorEventScope({
|
|
5469
|
+
ctx,
|
|
5642
5470
|
body,
|
|
5643
5471
|
context,
|
|
5644
|
-
client
|
|
5472
|
+
client,
|
|
5473
|
+
onDrop: (reason) => logVerbose(`slack: drop event (${reason})`)
|
|
5645
5474
|
});
|
|
5646
|
-
if (eventScope === null) return;
|
|
5647
|
-
if (ctx.shouldDropMismatchedSlackEvent(body)) return;
|
|
5475
|
+
if (eventScope === null || ctx.shouldDropMismatchedSlackEvent(body)) return;
|
|
5648
5476
|
const message = event;
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
const
|
|
5477
|
+
let assistantChangedInbound;
|
|
5478
|
+
if (source === "message") {
|
|
5479
|
+
ctx.rememberSlackChannelType(message.channel, message.channel_type, eventScope);
|
|
5480
|
+
assistantChangedInbound = resolveAssistantMessageChangedInbound({
|
|
5481
|
+
event: message,
|
|
5482
|
+
ctx
|
|
5483
|
+
});
|
|
5484
|
+
if (!assistantChangedInbound && message.subtype === "message_changed" && isSelfAttributedMessageChange({
|
|
5485
|
+
event: message,
|
|
5486
|
+
message: asOptionalRecord(message.message),
|
|
5487
|
+
ctx
|
|
5488
|
+
})) return;
|
|
5489
|
+
const subtypeHandler = assistantChangedInbound ? void 0 : resolveSlackMessageSubtypeHandler(message);
|
|
5490
|
+
if (subtypeHandler) {
|
|
5491
|
+
const ingressContext = await authorizeAndResolveSlackSystemEventContext({
|
|
5492
|
+
ctx,
|
|
5493
|
+
senderId: subtypeHandler.senderId,
|
|
5494
|
+
channelId: message.channel,
|
|
5495
|
+
threadTs: subtypeHandler.threadTs,
|
|
5496
|
+
eventKind: subtypeHandler.eventKind,
|
|
5497
|
+
eventScope
|
|
5498
|
+
});
|
|
5499
|
+
if (!ingressContext) return;
|
|
5500
|
+
enqueueRoutedSystemEvent(subtypeHandler.describe(ingressContext.channelLabel), ingressContext.route, { contextKey: `${subtypeHandler.contextKey}:${body.event_id}` });
|
|
5501
|
+
return;
|
|
5502
|
+
}
|
|
5503
|
+
} else {
|
|
5504
|
+
const mention = event;
|
|
5505
|
+
if (eventScope && isBotAuthoredEnterpriseEvent(mention)) {
|
|
5506
|
+
logVerbose("slack: drop enterprise bot-authored app_mention");
|
|
5507
|
+
return;
|
|
5508
|
+
}
|
|
5509
|
+
const { type: channelType, lookupFailureCategory } = await resolveSlackAppMentionChannelType({
|
|
5662
5510
|
ctx,
|
|
5663
|
-
|
|
5664
|
-
channelId: message.channel,
|
|
5665
|
-
threadTs: subtypeHandler.resolveThreadTs(message),
|
|
5666
|
-
eventKind: subtypeHandler.eventKind,
|
|
5511
|
+
mention,
|
|
5667
5512
|
eventScope
|
|
5668
5513
|
});
|
|
5669
|
-
if (!
|
|
5670
|
-
|
|
5671
|
-
|
|
5514
|
+
if (!channelType) {
|
|
5515
|
+
const channelId = /^[CDG][A-Z0-9]{1,32}$/.test(mention.channel) ? mention.channel : "unrecognized";
|
|
5516
|
+
const category = lookupFailureCategory ?? "missing_type";
|
|
5517
|
+
slackInboundLog.info(`Slack app_mention skipped: conversation type unresolved; channelId=${channelId} lookupFailureCategory=${category}; waiting for message event`, {
|
|
5518
|
+
channelId,
|
|
5519
|
+
lookupFailureCategory: category
|
|
5520
|
+
});
|
|
5521
|
+
return;
|
|
5522
|
+
}
|
|
5523
|
+
if (channelType === "im" || channelType === "mpim") return;
|
|
5524
|
+
const from = `slack:${eventScope?.teamId ?? ctx.teamId}:channel:${mention.channel}:user:${normalizeOptionalString(mention.user) ?? "unknown"}`;
|
|
5525
|
+
slackInboundLog.info(`Inbound app_mention ${from} -> bot:${ctx.botUserId} (${channelType}, ${normalizeOptionalString(mention.text)?.length ?? 0} chars)`);
|
|
5672
5526
|
}
|
|
5673
5527
|
const inbound = assistantChangedInbound ?? message;
|
|
5674
5528
|
noteConversationMessage(inbound, eventScope);
|
|
5675
5529
|
await handleSlackMessage(inbound, {
|
|
5676
|
-
source
|
|
5530
|
+
source,
|
|
5677
5531
|
senderAuthentication: assistantChangedInbound ? void 0 : resolveSlackSenderAuthentication(context),
|
|
5532
|
+
...source === "app_mention" ? { wasMentioned: true } : {},
|
|
5678
5533
|
eventScope,
|
|
5679
5534
|
...turnAdoptionLifecycle ? { turnAdoptionLifecycle } : {},
|
|
5680
5535
|
...eventScope || turnAdoptionLifecycle ? { awaitDispatch: true } : {}
|
|
5681
5536
|
});
|
|
5682
5537
|
} catch (err) {
|
|
5683
5538
|
if (turnAdoptionLifecycle) throw err;
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
};
|
|
5687
|
-
ctx.app.event("message", handleIncomingMessageEvent);
|
|
5688
|
-
ctx.app.event("app_mention", async (args) => {
|
|
5689
|
-
const { event, body, context, client } = args;
|
|
5690
|
-
const turnAdoptionLifecycle = resolveSlackIngressTurnLifecycle(context);
|
|
5691
|
-
try {
|
|
5692
|
-
const eventScope = resolveEventScope({
|
|
5693
|
-
body,
|
|
5694
|
-
context,
|
|
5695
|
-
client
|
|
5696
|
-
});
|
|
5697
|
-
if (eventScope === null) return;
|
|
5698
|
-
if (ctx.shouldDropMismatchedSlackEvent(body)) return;
|
|
5699
|
-
const mention = event;
|
|
5700
|
-
if (eventScope && isBotAuthoredEnterpriseEvent(mention)) {
|
|
5701
|
-
logVerbose("slack: drop enterprise bot-authored app_mention");
|
|
5702
|
-
return;
|
|
5703
|
-
}
|
|
5704
|
-
const channelType = await resolveSlackAppMentionChannelType({
|
|
5705
|
-
ctx,
|
|
5706
|
-
mention,
|
|
5707
|
-
eventScope
|
|
5708
|
-
});
|
|
5709
|
-
if (!channelType) {
|
|
5710
|
-
logVerbose(`slack: drop typeless app_mention channel=${mention.channel} (conversation type unresolved; waiting for message event)`);
|
|
5711
|
-
return;
|
|
5712
|
-
}
|
|
5713
|
-
if (channelType === "im" || channelType === "mpim") return;
|
|
5714
|
-
const from = `slack:${eventScope?.teamId ?? ctx.teamId}:channel:${mention.channel}:user:${normalizeOptionalString(mention.user) ?? "unknown"}`;
|
|
5715
|
-
slackInboundLog.info(`Inbound app_mention ${from} -> bot:${ctx.botUserId} (${channelType}, ${normalizeOptionalString(mention.text)?.length ?? 0} chars)`);
|
|
5716
|
-
noteConversationMessage(mention, eventScope);
|
|
5717
|
-
await handleSlackMessage(mention, {
|
|
5718
|
-
source: "app_mention",
|
|
5719
|
-
senderAuthentication: resolveSlackSenderAuthentication(context),
|
|
5720
|
-
wasMentioned: true,
|
|
5721
|
-
eventScope,
|
|
5722
|
-
...turnAdoptionLifecycle ? { turnAdoptionLifecycle } : {},
|
|
5723
|
-
...eventScope || turnAdoptionLifecycle ? { awaitDispatch: true } : {}
|
|
5724
|
-
});
|
|
5725
|
-
} catch (err) {
|
|
5726
|
-
if (turnAdoptionLifecycle) throw err;
|
|
5727
|
-
ctx.runtime.error?.(danger(`slack mention handler failed: ${formatErrorMessage(err)}`));
|
|
5539
|
+
const handler = source === "app_mention" ? "mention handler" : "handler";
|
|
5540
|
+
ctx.runtime.error?.(danger(`slack ${handler} failed: ${formatErrorMessage(err)}`));
|
|
5728
5541
|
}
|
|
5729
5542
|
});
|
|
5730
5543
|
}
|
|
@@ -5737,7 +5550,7 @@ function registerSlackPinEvents(params) {
|
|
|
5737
5550
|
ctx.app.event(`pin_${contextKeySuffix}`, async (args) => {
|
|
5738
5551
|
const { event, body, context, client } = args;
|
|
5739
5552
|
try {
|
|
5740
|
-
const eventScope =
|
|
5553
|
+
const eventScope = resolveSlackMonitorEventScope({
|
|
5741
5554
|
ctx,
|
|
5742
5555
|
body,
|
|
5743
5556
|
context,
|
|
@@ -5791,7 +5604,7 @@ function registerSlackReactionEvents(params) {
|
|
|
5791
5604
|
for (const action of ["added", "removed"]) ctx.app.event(`reaction_${action}`, async (args) => {
|
|
5792
5605
|
const { body, context, client } = args;
|
|
5793
5606
|
const event = args.event;
|
|
5794
|
-
const eventScope =
|
|
5607
|
+
const eventScope = resolveSlackMonitorEventScope({
|
|
5795
5608
|
ctx,
|
|
5796
5609
|
body,
|
|
5797
5610
|
context,
|
|
@@ -5987,7 +5800,7 @@ function buildSlackDebounceKey(message, accountId, teamId) {
|
|
|
5987
5800
|
}
|
|
5988
5801
|
//#endregion
|
|
5989
5802
|
//#region extensions/slack/src/monitor/message-handler.ts
|
|
5990
|
-
const loadSlackMessagePipeline = createLazyRuntimeModule(() => import("./pipeline.runtime-
|
|
5803
|
+
const loadSlackMessagePipeline = createLazyRuntimeModule(() => import("./pipeline.runtime-ByPbC6MN.mjs"));
|
|
5991
5804
|
const RETRYABLE_FLUSH_MAX_ATTEMPTS = 3;
|
|
5992
5805
|
const RETRYABLE_FLUSH_RETRY_DELAY_MS = 1e3;
|
|
5993
5806
|
const REPLY_SESSION_INIT_CONFLICT_MESSAGE_RE = /reply session initialization conflicted for \S+/u;
|
|
@@ -6345,14 +6158,26 @@ function createSlackPresenceMonitor(params) {
|
|
|
6345
6158
|
const scheduler = params.scheduler.scope();
|
|
6346
6159
|
let started = false;
|
|
6347
6160
|
const rateLimitedUntilByWorkspace = /* @__PURE__ */ new Map();
|
|
6161
|
+
const collectEligibleSubjects = () => {
|
|
6162
|
+
const subjects = /* @__PURE__ */ new Map();
|
|
6163
|
+
for (const target of targets.values()) {
|
|
6164
|
+
if (!isTargetEligible(target)) continue;
|
|
6165
|
+
for (const userId of target.participants.keys()) {
|
|
6166
|
+
const subject = {
|
|
6167
|
+
teamId: target.teamId,
|
|
6168
|
+
userId
|
|
6169
|
+
};
|
|
6170
|
+
subjects.set(presenceSubjectKey(subject), subject);
|
|
6171
|
+
}
|
|
6172
|
+
}
|
|
6173
|
+
return subjects;
|
|
6174
|
+
};
|
|
6348
6175
|
const pruneTargets = (now) => {
|
|
6349
6176
|
for (const [key, target] of targets) if (!target.isPolicyCurrent() || now - target.lastActivityAtMs >= SLACK_PRESENCE_TARGET_TTL_MS) targets.delete(key);
|
|
6350
6177
|
pruneMapToMaxSize(targets, SLACK_PRESENCE_MAX_TARGETS);
|
|
6351
|
-
const
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
}))));
|
|
6355
|
-
for (const userId of presenceByUser.keys()) if (!eligibleUsers.has(userId)) presenceByUser.delete(userId);
|
|
6178
|
+
const eligibleSubjects = collectEligibleSubjects();
|
|
6179
|
+
for (const userId of presenceByUser.keys()) if (!eligibleSubjects.has(userId)) presenceByUser.delete(userId);
|
|
6180
|
+
return eligibleSubjects;
|
|
6356
6181
|
};
|
|
6357
6182
|
const observe = (prepared) => {
|
|
6358
6183
|
const now = nowMs();
|
|
@@ -6425,19 +6250,7 @@ function createSlackPresenceMonitor(params) {
|
|
|
6425
6250
|
};
|
|
6426
6251
|
const performPoll = async () => {
|
|
6427
6252
|
const now = nowMs();
|
|
6428
|
-
pruneTargets(now);
|
|
6429
|
-
const candidatesByKey = /* @__PURE__ */ new Map();
|
|
6430
|
-
for (const target of targets.values()) {
|
|
6431
|
-
if (!isTargetEligible(target)) continue;
|
|
6432
|
-
for (const userId of target.participants.keys()) {
|
|
6433
|
-
const subject = {
|
|
6434
|
-
teamId: target.teamId,
|
|
6435
|
-
userId
|
|
6436
|
-
};
|
|
6437
|
-
candidatesByKey.set(presenceSubjectKey(subject), subject);
|
|
6438
|
-
}
|
|
6439
|
-
}
|
|
6440
|
-
const candidates = Array.from(candidatesByKey.entries()).toSorted(([left], [right]) => left.localeCompare(right)).map(([, subject]) => subject);
|
|
6253
|
+
const candidates = Array.from(pruneTargets(now).entries()).toSorted(([left], [right]) => left.localeCompare(right)).map(([, subject]) => subject);
|
|
6441
6254
|
if (candidates.length === 0) return;
|
|
6442
6255
|
const count = Math.min(candidates.length, SLACK_PRESENCE_MAX_POLLS_PER_INTERVAL);
|
|
6443
6256
|
const selected = Array.from({ length: count }, (_, index) => candidates[(pollOffset + index) % candidates.length]).filter((subject) => Boolean(subject));
|
|
@@ -6532,7 +6345,7 @@ async function getSlackBoltInterop() {
|
|
|
6532
6345
|
}
|
|
6533
6346
|
return slackBoltInterop;
|
|
6534
6347
|
}
|
|
6535
|
-
const loadSlackRelaySource = createLazyRuntimeModule(() => import("./relay-source-
|
|
6348
|
+
const loadSlackRelaySource = createLazyRuntimeModule(() => import("./relay-source-CVfH-fBO.mjs"));
|
|
6536
6349
|
function resolveSlackRuntimeIdentity(params) {
|
|
6537
6350
|
const botUserId = normalizeOptionalString(params.botUserId);
|
|
6538
6351
|
const botId = normalizeOptionalString(params.botId);
|
|
@@ -6832,8 +6645,7 @@ async function monitorSlackProvider(opts) {
|
|
|
6832
6645
|
const appHomeSlashCommandName = commandRegistration.mode === "single" ? commandRegistration.name : void 0;
|
|
6833
6646
|
let workspaceRuntimePromise;
|
|
6834
6647
|
const installSlackWorkspaceRuntime = async () => {
|
|
6835
|
-
|
|
6836
|
-
workspaceRuntimePromise = (async () => {
|
|
6648
|
+
workspaceRuntimePromise ??= (async () => {
|
|
6837
6649
|
registerSlackWorkspaceEvents({
|
|
6838
6650
|
ctx,
|
|
6839
6651
|
appHomeSlashCommandName,
|
|
@@ -6931,63 +6743,60 @@ async function monitorSlackProvider(opts) {
|
|
|
6931
6743
|
if (slackMode === "socket") {
|
|
6932
6744
|
let reconnectAttempts = 0;
|
|
6933
6745
|
let hasLoggedSocketConnected = false;
|
|
6934
|
-
while (!opts.abortSignal?.aborted)
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
|
|
6938
|
-
|
|
6939
|
-
|
|
6940
|
-
|
|
6941
|
-
|
|
6942
|
-
|
|
6943
|
-
|
|
6944
|
-
|
|
6746
|
+
while (!opts.abortSignal?.aborted) {
|
|
6747
|
+
let delayMs;
|
|
6748
|
+
try {
|
|
6749
|
+
const disconnect = await startSlackSocketAndWaitForDisconnect({
|
|
6750
|
+
app,
|
|
6751
|
+
abortSignal: opts.abortSignal,
|
|
6752
|
+
onStarted: async () => {
|
|
6753
|
+
reconnectAttempts = 0;
|
|
6754
|
+
await recoverSlackIdentity();
|
|
6755
|
+
publishSlackConnectedStatus(opts.setStatus, ctx.identityHealth);
|
|
6756
|
+
if (!hasLoggedSocketConnected) {
|
|
6757
|
+
hasLoggedSocketConnected = true;
|
|
6758
|
+
runtime.log?.(ctx.identityHealth.lifecycle === "blocked" ? "slack socket mode connected (degraded identity)" : "slack socket mode connected");
|
|
6759
|
+
}
|
|
6945
6760
|
}
|
|
6761
|
+
});
|
|
6762
|
+
if (!disconnect) break;
|
|
6763
|
+
if (opts.abortSignal?.aborted) break;
|
|
6764
|
+
publishSlackDisconnectedStatus(opts.setStatus, disconnect.error);
|
|
6765
|
+
if (disconnect.error && isNonRecoverableSlackAuthError(disconnect.error)) {
|
|
6766
|
+
publishSlackBlockedStatus(opts.setStatus, disconnect.error);
|
|
6767
|
+
runtime.error?.(`slack socket mode disconnected due to non-recoverable auth error — skipping channel (${formatSlackError(disconnect.error)})`);
|
|
6768
|
+
throw disconnect.error instanceof Error ? disconnect.error : new Error(formatSlackError(disconnect.error));
|
|
6946
6769
|
}
|
|
6947
|
-
|
|
6948
|
-
|
|
6949
|
-
|
|
6950
|
-
|
|
6951
|
-
|
|
6952
|
-
|
|
6953
|
-
|
|
6954
|
-
|
|
6955
|
-
|
|
6956
|
-
|
|
6957
|
-
|
|
6958
|
-
|
|
6959
|
-
|
|
6960
|
-
|
|
6961
|
-
|
|
6962
|
-
|
|
6963
|
-
|
|
6964
|
-
|
|
6965
|
-
|
|
6966
|
-
|
|
6967
|
-
|
|
6968
|
-
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
if (isNonRecoverableSlackAuthError(err)) {
|
|
6972
|
-
publishSlackBlockedStatus(opts.setStatus, err);
|
|
6973
|
-
runtime.error?.(`slack socket mode failed to start due to non-recoverable auth error — skipping channel (${formatSlackError(err)})`);
|
|
6974
|
-
throw err;
|
|
6770
|
+
reconnectAttempts += 1;
|
|
6771
|
+
delayMs = computeBackoff(SLACK_SOCKET_RECONNECT_POLICY, reconnectAttempts);
|
|
6772
|
+
runtime.log?.(warn(formatSlackSocketReconnectMessage({
|
|
6773
|
+
event: disconnect.event,
|
|
6774
|
+
attempt: reconnectAttempts,
|
|
6775
|
+
delayMs,
|
|
6776
|
+
error: disconnect.error
|
|
6777
|
+
})));
|
|
6778
|
+
await gracefulStopSlackApp(app);
|
|
6779
|
+
} catch (err) {
|
|
6780
|
+
if (isNonRecoverableSlackAuthError(err)) {
|
|
6781
|
+
publishSlackBlockedStatus(opts.setStatus, err);
|
|
6782
|
+
runtime.error?.(`slack socket mode failed to start due to non-recoverable auth error — skipping channel (${formatSlackError(err)})`);
|
|
6783
|
+
throw err;
|
|
6784
|
+
}
|
|
6785
|
+
publishSlackDisconnectedStatus(opts.setStatus, err);
|
|
6786
|
+
reconnectAttempts += 1;
|
|
6787
|
+
delayMs = computeBackoff(SLACK_SOCKET_RECONNECT_POLICY, reconnectAttempts);
|
|
6788
|
+
runtime.error?.(formatSlackSocketStartRetryMessage({
|
|
6789
|
+
attempt: reconnectAttempts,
|
|
6790
|
+
delayMs,
|
|
6791
|
+
error: err,
|
|
6792
|
+
sdkContext: socketModeLogger.getLastMessage()
|
|
6793
|
+
}));
|
|
6975
6794
|
}
|
|
6976
|
-
publishSlackDisconnectedStatus(opts.setStatus, err);
|
|
6977
|
-
reconnectAttempts += 1;
|
|
6978
|
-
const delayMs = computeBackoff(SLACK_SOCKET_RECONNECT_POLICY, reconnectAttempts);
|
|
6979
|
-
runtime.error?.(formatSlackSocketStartRetryMessage({
|
|
6980
|
-
attempt: reconnectAttempts,
|
|
6981
|
-
delayMs,
|
|
6982
|
-
error: err,
|
|
6983
|
-
sdkContext: socketModeLogger.getLastMessage()
|
|
6984
|
-
}));
|
|
6985
6795
|
try {
|
|
6986
6796
|
await sleepWithAbort(delayMs, opts.abortSignal);
|
|
6987
6797
|
} catch {
|
|
6988
6798
|
break;
|
|
6989
6799
|
}
|
|
6990
|
-
continue;
|
|
6991
6800
|
}
|
|
6992
6801
|
} else if (slackMode === "relay" && relayConfig) {
|
|
6993
6802
|
const relaySource = await loadSlackRelaySource();
|
|
@@ -7030,8 +6839,7 @@ async function monitorSlackProvider(opts) {
|
|
|
7030
6839
|
function createSlackWorkspaceClientResolver(params) {
|
|
7031
6840
|
if (params.installationIdentity.kind !== "enterprise") return () => params.appClient;
|
|
7032
6841
|
const clients = /* @__PURE__ */ new Map();
|
|
7033
|
-
return (
|
|
7034
|
-
const teamId = rawTeamId;
|
|
6842
|
+
return (teamId) => {
|
|
7035
6843
|
if (!teamId || !/^T[A-Z0-9]+$/.test(teamId)) throw new Error("Slack Enterprise Grid workspace client requires a valid teamId");
|
|
7036
6844
|
const cached = clients.get(teamId);
|
|
7037
6845
|
if (cached) return cached;
|