@openclaw/slack 2026.10.10-beta.5 → 2026.11.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 → account-configured-35y0-Hso.mjs} +1 -2
- package/dist/.setup/{account-inspect-CmkKiSb9.mjs → account-inspect-DgQgj0wk.mjs} +13 -11
- package/dist/.setup/{accounts-msihSF3-.mjs → accounts-EaPP0fFY.mjs} +16 -11
- package/dist/.setup/{action-runtime-ChRfnnBu.mjs → action-runtime-CK9QZgQl.mjs} +39 -47
- package/dist/.setup/action-runtime.runtime-CpZktret.mjs +1 -0
- package/dist/.setup/{actions-By7tvpvv.mjs → actions-s3CcFO45.mjs} +98 -93
- package/dist/.setup/{approval-handler.runtime-D8ArtDQt.mjs → approval-handler.runtime-Ch7BecYK.mjs} +27 -32
- package/dist/.setup/{approval-message-updates-DT7XBPbV.mjs → approval-message-updates-CqcRoa28.mjs} +2 -3
- package/dist/.setup/{channel-6YzXl_63.mjs → channel-CAvo_WNZ.mjs} +573 -352
- package/dist/.setup/{channel-meta-C443t-lI.mjs → channel-meta-C5vsCo3a.mjs} +1 -2
- package/dist/.setup/{channel-type-BEFP2ORi.mjs → channel-type-9Lw6yLf2.mjs} +6 -11
- package/dist/.setup/{channel.setup-u6QQdbTa.mjs → channel.setup-BlgXNuCJ.mjs} +19 -23
- package/dist/.setup/{config-schema-DNnh6bWU.mjs → config-schema-Bx1tCZB0.mjs} +5 -11
- package/dist/.setup/cursor-pages-jVn3Vkfi.mjs +309 -0
- package/dist/.setup/{directory-config-Cjj0N8R0.mjs → directory-config-CGvKYg9F.mjs} +5 -6
- package/dist/.setup/{directory-live-BIKD-5B_.mjs → directory-live-DNdw97LA.mjs} +6 -7
- package/dist/.setup/{doctor-contract-Cd4-VzIM.mjs → doctor-contract-BB2KJ9Ni.mjs} +44 -58
- package/dist/.setup/{message-tool-api-BS5ekEA_.mjs → message-tool-api-B38BpEaE.mjs} +7 -8
- package/dist/.setup/{monitor-BFilOuM_.mjs → monitor-BD86SotB.mjs} +3416 -3750
- package/dist/.setup/{outbound-adapter-9dbnYtL1.mjs → outbound-adapter-BH6iPWBj.mjs} +32 -39
- package/dist/.setup/paths-CQZI_5WY.mjs +7 -0
- package/dist/.setup/{pipeline.runtime-BG5swHnj.mjs → pipeline.runtime-C4ELxaRU.mjs} +444 -590
- package/dist/.setup/{policy-yhn48xf5.mjs → policy-C6_DdlSf.mjs} +3 -6
- package/dist/.setup/{session-status-Dv8wNBEt.mjs → probe-B_Ax1vS1.mjs} +1015 -678
- package/dist/.setup/question-delivery-D3qAIwuv.mjs +38 -0
- package/dist/.setup/{relay-source-oY9SbDiX.mjs → relay-source-a8jodKuO.mjs} +12 -6
- package/dist/.setup/{replies-CJwjTqDr.mjs → replies-Bq7n0gfM.mjs} +37 -24
- package/dist/.setup/{reply-blocks-Ca-raz2z.mjs → reply-blocks-DyYYRrP_.mjs} +202 -210
- package/dist/.setup/{resolve-channels-DRRhElwz.mjs → resolve-channels-CF2JME9q.mjs} +6 -10
- package/dist/.setup/{resolve-users-Cz8e17ky.mjs → resolve-users-DDcCAjH1.mjs} +10 -19
- package/dist/.setup/{rolldown-runtime-B4FMCO8f.mjs → rolldown-runtime-nwUcYXjP.mjs} +1 -2
- package/dist/.setup/{runtime-JSVZSWAj.mjs → runtime-C6HKn7Av.mjs} +1 -2
- package/dist/.setup/runtime-setter-api-DrXr965r.mjs +2 -0
- package/dist/.setup/{scopes-DfQVi8Jw.mjs → scopes-CzHC_dwV.mjs} +3 -3
- package/dist/.setup/{secret-contract-B-Qm6aQQ.mjs → secret-contract-CqVqR7MP.mjs} +5 -4
- package/dist/.setup/{secret-contract-api-DB6CMdgc.mjs → secret-contract-api-DaCXZ47j.mjs} +1 -1
- package/dist/.setup/{security-audit-DFGiFLqd.mjs → security-audit-C3hXCfDt.mjs} +2 -3
- package/dist/.setup/{send-C-8wY0lK.mjs → send-WJZ73VSf.mjs} +306 -349
- package/dist/.setup/{send-results-eeOu_HYm.mjs → send-results-Bm6V1ekL.mjs} +4 -6
- package/dist/.setup/setup-plugin-api-DJXIB8CF.mjs +2 -0
- package/dist/.setup/{setup-surface-9WVQgYCT.mjs → setup-surface-uIqP2B0Y.mjs} +6 -8
- package/dist/.setup/{slash-dispatch.runtime-v5kQqJPh.mjs → slash-dispatch.runtime-Cwuwv7FL.mjs} +2 -2
- package/dist/.setup/{target-parsing-FFE26kOV.mjs → target-parsing-DwYAP3ts.mjs} +2 -4
- package/dist/.setup/{targets-C6LZQL1Q.mjs → targets-eeOxA_b_.mjs} +2 -3
- package/dist/.setup/{thread-ts-Cvt7WD6B.mjs → thread-ts-47Au2-Yn.mjs} +1 -2
- package/dist/.source-module-urls/c5ffd0957b234c7c12090e7de4eca2482ef339b8561e078da55b734211b0ba58.json +1 -0
- package/dist/account-inspect-api.js +2 -3
- package/dist/api.js +17 -18
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-entry.js +1 -2
- package/dist/channel-plugin-api.js +1 -1
- package/dist/configured-state.js +2 -3
- package/dist/directory-contract-api.js +1 -1
- package/dist/doctor-contract-api.js +1 -1
- package/dist/index.js +1 -8
- package/dist/message-tool-api.js +1 -1
- package/dist/runtime-api.js +11 -13
- package/dist/runtime-setter-api.js +1 -1
- package/dist/secret-contract-api.js +1 -1
- package/dist/security-contract-api.js +1 -1
- package/dist/setup-entry.js +4 -5
- package/dist/setup-plugin-api.js +1 -1
- package/node_modules/@slack/bolt/node_modules/@types/node/README.md +1 -1
- package/node_modules/@slack/bolt/node_modules/@types/node/package.json +2 -2
- package/node_modules/@slack/bolt/node_modules/@types/node/util.d.ts +6 -3
- package/node_modules/@slack/bolt/node_modules/content-disposition/README.md +105 -35
- package/node_modules/@slack/bolt/node_modules/content-disposition/dist/index.d.ts +72 -0
- package/node_modules/@slack/bolt/node_modules/content-disposition/dist/index.js +388 -0
- package/node_modules/@slack/bolt/node_modules/content-disposition/dist/index.js.map +1 -0
- package/node_modules/@slack/bolt/node_modules/content-disposition/package.json +31 -19
- package/node_modules/@slack/bolt/node_modules/content-type/README.md +34 -57
- package/node_modules/@slack/bolt/node_modules/content-type/package.json +35 -25
- package/node_modules/@slack/bolt/node_modules/express/Readme.md +15 -9
- package/node_modules/@slack/bolt/node_modules/express/lib/application.js +2 -2
- package/node_modules/@slack/bolt/node_modules/express/lib/request.js +32 -19
- package/node_modules/@slack/bolt/node_modules/express/lib/response.js +27 -30
- package/node_modules/@slack/bolt/node_modules/express/package.json +10 -10
- package/node_modules/@slack/bolt/node_modules/qs/.github/THREAT_MODEL.md +4 -2
- package/node_modules/@slack/bolt/node_modules/qs/CHANGELOG.md +38 -14
- package/node_modules/@slack/bolt/node_modules/qs/README.md +31 -3
- package/node_modules/@slack/bolt/node_modules/qs/dist/qs.js +20 -20
- package/node_modules/@slack/bolt/node_modules/qs/lib/parse.js +94 -4
- package/node_modules/@slack/bolt/node_modules/qs/lib/stringify.js +4 -4
- package/node_modules/@slack/bolt/node_modules/qs/lib/utils.js +130 -6
- package/node_modules/@slack/bolt/node_modules/qs/package.json +4 -4
- package/node_modules/@slack/bolt/node_modules/qs/test/parse.js +174 -0
- package/node_modules/@slack/bolt/node_modules/qs/test/stringify.js +263 -33
- package/node_modules/@slack/bolt/node_modules/qs/test/utils.js +184 -0
- package/node_modules/@slack/web-api/node_modules/@types/node/README.md +1 -1
- package/node_modules/@slack/web-api/node_modules/@types/node/package.json +2 -2
- package/node_modules/@slack/web-api/node_modules/@types/node/util.d.ts +6 -3
- package/node_modules/typebox/build/format/duration.d.mts +2 -2
- package/node_modules/typebox/build/format/duration.mjs +2 -2
- package/node_modules/typebox/build/format/idn_email.d.mts +1 -0
- package/node_modules/typebox/build/format/idn_email.mjs +1 -0
- package/node_modules/typebox/build/format/idn_hostname.d.mts +1 -1
- package/node_modules/typebox/build/format/idn_hostname.mjs +1 -1
- package/node_modules/typebox/build/format/ipv4.d.mts +2 -2
- package/node_modules/typebox/build/format/ipv4.mjs +2 -2
- package/node_modules/typebox/build/format/ipv6.d.mts +1 -1
- package/node_modules/typebox/build/format/ipv6.mjs +1 -1
- package/node_modules/typebox/build/format/relative_json_pointer.d.mts +2 -2
- package/node_modules/typebox/build/format/relative_json_pointer.mjs +2 -2
- package/node_modules/typebox/build/schema/build.mjs +1 -0
- package/node_modules/typebox/build/schema/engine/_unique.d.mts +4 -2
- package/node_modules/typebox/build/schema/engine/_unique.mjs +7 -3
- package/node_modules/typebox/build/schema/engine/additionalItems.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/additionalProperties.d.mts +0 -3
- package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +15 -17
- package/node_modules/typebox/build/schema/engine/contains.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/index.d.mts +1 -0
- package/node_modules/typebox/build/schema/engine/index.mjs +1 -0
- package/node_modules/typebox/build/schema/engine/items.mjs +7 -4
- package/node_modules/typebox/build/schema/engine/maxContains.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/minContains.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/oneOf.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/patternProperties.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/unevaluatedItems.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/unevaluatedProperties.mjs +2 -2
- package/node_modules/typebox/build/system/hashing/hash.mjs +63 -34
- package/node_modules/typebox/build/system/locale/en_US.mjs +2 -1
- package/node_modules/typebox/build/system/memory/assign.d.mts +2 -8
- package/node_modules/typebox/build/system/memory/assign.mjs +13 -6
- package/node_modules/typebox/build/system/memory/clone.d.mts +4 -5
- package/node_modules/typebox/build/system/memory/clone.mjs +8 -96
- package/node_modules/typebox/build/system/memory/create.d.mts +1 -5
- package/node_modules/typebox/build/system/memory/create.mjs +18 -13
- package/node_modules/typebox/build/system/memory/deep.d.mts +2 -0
- package/node_modules/typebox/build/system/memory/deep.mjs +108 -0
- package/node_modules/typebox/build/system/memory/discard.d.mts +1 -1
- package/node_modules/typebox/build/system/memory/discard.mjs +9 -8
- package/node_modules/typebox/build/system/memory/finalize.d.mts +4 -0
- package/node_modules/typebox/build/system/memory/finalize.mjs +30 -0
- package/node_modules/typebox/build/system/memory/keys.d.mts +2 -0
- package/node_modules/typebox/build/system/memory/keys.mjs +8 -0
- package/node_modules/typebox/build/system/memory/update.d.mts +1 -4
- package/node_modules/typebox/build/system/memory/update.mjs +43 -16
- package/node_modules/typebox/build/type/engine/call/index.d.mts +1 -0
- package/node_modules/typebox/build/type/engine/call/index.mjs +1 -0
- package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +2 -24
- package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +2 -29
- package/node_modules/typebox/build/type/engine/evaluate/index.d.mts +1 -0
- package/node_modules/typebox/build/type/engine/evaluate/index.mjs +1 -0
- package/node_modules/typebox/build/type/engine/evaluate/narrow.d.mts +5 -1
- package/node_modules/typebox/build/type/engine/evaluate/narrow.mjs +6 -1
- package/node_modules/typebox/build/type/engine/evaluate/property.d.mts +30 -0
- package/node_modules/typebox/build/type/engine/evaluate/property.mjs +29 -0
- package/node_modules/typebox/build/type/engine/immutable/instantiate_add.d.mts +1 -3
- package/node_modules/typebox/build/type/engine/immutable/instantiate_add.mjs +1 -4
- package/node_modules/typebox/build/type/engine/object/from_intersect.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/object/from_intersect.mjs +2 -2
- package/node_modules/typebox/build/type/engine/object/from_union.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/object/from_union.mjs +2 -2
- package/node_modules/typebox/build/type/engine/optional/instantiate_add.d.mts +1 -3
- package/node_modules/typebox/build/type/engine/optional/instantiate_add.mjs +1 -4
- package/node_modules/typebox/build/type/engine/readonly/instantiate_add.d.mts +1 -3
- package/node_modules/typebox/build/type/engine/readonly/instantiate_add.mjs +1 -4
- package/node_modules/typebox/build/type/engine/this/index.d.mts +1 -0
- package/node_modules/typebox/build/type/engine/this/index.mjs +1 -0
- package/node_modules/typebox/build/value/clone/clone.d.mts +4 -3
- package/node_modules/typebox/build/value/clone/clone.mjs +5 -7
- package/node_modules/typebox/build/value/repair/from_cyclic.d.mts +2 -0
- package/node_modules/typebox/build/value/repair/from_cyclic.mjs +6 -0
- package/node_modules/typebox/build/value/shared/union_priority_sort.mjs +25 -14
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/typebox/readme.md +1 -1
- package/node_modules/undici/README.md +25 -3
- package/node_modules/undici/docs/docs/api/CacheStore.md +24 -9
- package/node_modules/undici/docs/docs/api/Client.md +11 -6
- package/node_modules/undici/docs/docs/api/Dispatcher.md +3 -0
- package/node_modules/undici/docs/docs/api/Errors.md +76 -1
- package/node_modules/undici/docs/docs/api/H2CClient.md +3 -2
- package/node_modules/undici/docs/docs/api/Interceptors.md +28 -8
- package/node_modules/undici/docs/docs/api/RedirectHandler.md +13 -10
- package/node_modules/undici/docs/docs/index.md +12 -12
- package/node_modules/undici/docs/docs/type-map.json +66 -66
- package/node_modules/undici/lib/cache/memory-cache-store.js +48 -13
- package/node_modules/undici/lib/cache/sqlite-cache-store.js +83 -5
- package/node_modules/undici/lib/core/connect.js +10 -4
- package/node_modules/undici/lib/core/constants.js +12 -1
- package/node_modules/undici/lib/core/errors.js +38 -1
- package/node_modules/undici/lib/core/request.js +16 -1
- package/node_modules/undici/lib/core/symbols.js +2 -0
- package/node_modules/undici/lib/core/util.js +26 -1
- package/node_modules/undici/lib/dispatcher/agent.js +6 -2
- package/node_modules/undici/lib/dispatcher/client-h1.js +116 -80
- package/node_modules/undici/lib/dispatcher/client-h2.js +124 -17
- package/node_modules/undici/lib/dispatcher/client.js +4 -1
- package/node_modules/undici/lib/dispatcher/dispatcher-base.js +3 -2
- package/node_modules/undici/lib/dispatcher/dispatcher1-wrapper.js +20 -3
- package/node_modules/undici/lib/dispatcher/parser-h1.js +1064 -0
- package/node_modules/undici/lib/dispatcher/pool-base.js +85 -31
- package/node_modules/undici/lib/dispatcher/pool.js +11 -8
- package/node_modules/undici/lib/dispatcher/proxy-agent.js +18 -8
- package/node_modules/undici/lib/dispatcher/retry-agent.js +10 -0
- package/node_modules/undici/lib/dispatcher/round-robin-pool.js +15 -5
- package/node_modules/undici/lib/handler/cache-handler.js +153 -15
- package/node_modules/undici/lib/handler/deduplication-handler.js +112 -51
- package/node_modules/undici/lib/handler/redirect-handler.js +28 -8
- package/node_modules/undici/lib/handler/retry-handler.js +44 -11
- package/node_modules/undici/lib/interceptor/cache.js +11 -3
- package/node_modules/undici/lib/interceptor/decompress.js +22 -9
- package/node_modules/undici/lib/interceptor/dns.js +11 -0
- package/node_modules/undici/lib/interceptor/response-error.js +72 -28
- package/node_modules/undici/lib/milo/LICENSE.md +7 -0
- package/node_modules/undici/lib/milo/no-simd.js +1002 -0
- package/node_modules/undici/lib/milo/simd.js +1002 -0
- package/node_modules/undici/lib/mock/mock-agent.js +11 -0
- package/node_modules/undici/lib/mock/snapshot-recorder.js +3 -2
- package/node_modules/undici/lib/mock/snapshot-utils.js +3 -2
- package/node_modules/undici/lib/util/cache.js +11 -5
- package/node_modules/undici/lib/web/cookies/util.js +19 -2
- package/node_modules/undici/lib/web/eventsource/eventsource-stream.js +69 -15
- package/node_modules/undici/lib/web/eventsource/eventsource.js +25 -2
- package/node_modules/undici/lib/web/fetch/body.js +47 -38
- package/node_modules/undici/lib/web/fetch/formdata-parser.js +12 -4
- package/node_modules/undici/lib/web/fetch/headers.js +2 -2
- package/node_modules/undici/lib/web/fetch/index.js +8 -4
- package/node_modules/undici/lib/web/subresource-integrity/subresource-integrity.js +5 -5
- package/node_modules/undici/lib/web/websocket/receiver.js +25 -4
- package/node_modules/undici/package.json +9 -7
- package/node_modules/undici/types/api.d.ts +1 -1
- package/node_modules/undici/types/cache-interceptor.d.ts +10 -0
- package/node_modules/undici/types/client.d.ts +10 -4
- package/node_modules/undici/types/errors.d.ts +16 -1
- package/node_modules/undici/types/h2c-client.d.ts +1 -1
- package/node_modules/undici/types/interceptors.d.ts +6 -1
- package/node_modules/undici/types/utility.d.ts +4 -4
- package/node_modules/zod/package.json +1 -1
- package/node_modules/zod/src/v4/classic/tests/array.test.ts +27 -0
- package/node_modules/zod/src/v4/classic/tests/map.test.ts +7 -0
- package/node_modules/zod/src/v4/classic/tests/set.test.ts +6 -0
- package/node_modules/zod/src/v4/core/compile.ts +9 -0
- package/node_modules/zod/src/v4/core/schemas.ts +35 -1
- package/node_modules/zod/src/v4/core/util.ts +13 -0
- package/node_modules/zod/src/v4/core/versions.ts +1 -1
- package/node_modules/zod/v4/core/compile.cjs +8 -0
- package/node_modules/zod/v4/core/compile.js +8 -0
- package/node_modules/zod/v4/core/schemas.cjs +30 -0
- package/node_modules/zod/v4/core/schemas.d.cts +3 -1
- package/node_modules/zod/v4/core/schemas.d.ts +3 -1
- package/node_modules/zod/v4/core/schemas.js +30 -0
- package/node_modules/zod/v4/core/util.cjs +15 -0
- package/node_modules/zod/v4/core/util.d.cts +2 -0
- package/node_modules/zod/v4/core/util.d.ts +2 -0
- package/node_modules/zod/v4/core/util.js +14 -0
- package/node_modules/zod/v4/core/versions.cjs +1 -1
- package/node_modules/zod/v4/core/versions.js +1 -1
- package/openclaw.plugin.json +6 -30
- package/package.json +7 -7
- package/dist/.setup/action-runtime.runtime-Ck_j1YTn.mjs +0 -1
- package/dist/.setup/http-C9sM-FXe.mjs +0 -2
- package/dist/.setup/plugin-routes-D4qozHVn.mjs +0 -22
- package/dist/.setup/probe-IiHogLQN.mjs +0 -694
- package/dist/.setup/registry-DizWcnNp.mjs +0 -36
- package/dist/.setup/runtime-setter-api-Cx_PV-xu.mjs +0 -2
- package/dist/.setup/setup-plugin-api-B18kDKtr.mjs +0 -2
- package/dist/.setup/shared-DpHCoKy2.mjs +0 -259
- package/dist/.source-module-urls/562d694877afe9d9dcbb3b32a8883c16974738f2aa892c48d45572cdc9a62529.json +0 -1
- package/dist/http-routes-api.js +0 -1
- package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/LICENSE +0 -22
- package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/README.md +0 -71
- package/node_modules/@slack/bolt/node_modules/body-parser/node_modules/content-type/package.json +0 -52
- package/node_modules/@slack/bolt/node_modules/content-disposition/index.js +0 -536
- package/node_modules/@slack/bolt/node_modules/content-type/HISTORY.md +0 -29
- package/node_modules/@slack/bolt/node_modules/content-type/index.js +0 -225
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/LICENSE +0 -22
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/README.md +0 -71
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.d.ts +0 -46
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.js +0 -176
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/dist/index.js.map +0 -1
- package/node_modules/@slack/bolt/node_modules/negotiator/node_modules/content-type/package.json +0 -52
- package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/LICENSE +0 -22
- package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/README.md +0 -71
- package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.d.ts +0 -46
- package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.js +0 -176
- package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/dist/index.js.map +0 -1
- package/node_modules/@slack/bolt/node_modules/type-is/node_modules/content-type/package.json +0 -52
- package/node_modules/typebox/build/system/memory/freeze.d.mts +0 -4
- package/node_modules/typebox/build/system/memory/freeze.mjs +0 -6
- /package/node_modules/@slack/bolt/node_modules/{body-parser/node_modules/content-type → content-type}/dist/index.d.ts +0 -0
- /package/node_modules/@slack/bolt/node_modules/{body-parser/node_modules/content-type → content-type}/dist/index.js +0 -0
- /package/node_modules/@slack/bolt/node_modules/{body-parser/node_modules/content-type → content-type}/dist/index.js.map +0 -0
|
@@ -1,21 +1,23 @@
|
|
|
1
|
-
import { r as isSlackPluginAccountConfigured } from "./account-configured-
|
|
2
|
-
import { c as resolveSlackAccountAllowFrom, d as
|
|
3
|
-
import {
|
|
4
|
-
import { t as
|
|
5
|
-
import {
|
|
6
|
-
import { _ as
|
|
7
|
-
import {
|
|
8
|
-
import { n as
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { n as
|
|
13
|
-
import { i as SLACK_CHANNEL } from "./channel.setup-
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
1
|
+
import { r as isSlackPluginAccountConfigured } from "./account-configured-35y0-Hso.mjs";
|
|
2
|
+
import { a as mergeSlackAccountConfig, c as resolveSlackAccountAllowFrom, d as resolveSlackMarkdownOptions, f as resolveSlackOperationToken, i as listSlackAccountIds, l as resolveSlackAccountDmPolicy, n as hasImplicitDefaultSlackAccount, o as resolveDefaultSlackAccountId, p as resolveSlackReplyToMode, s as resolveSlackAccount } from "./accounts-EaPP0fFY.mjs";
|
|
3
|
+
import { t as inspectSlackAccount } from "./account-inspect-DgQgj0wk.mjs";
|
|
4
|
+
import { a as parseSlackTarget, i as normalizeSlackMessagingTarget, n as formatSlackTarget, o as resolveSlackChannelId, r as looksLikeSlackTargetId, t as canonicalizeSlackApiTargetId } from "./target-parsing-DwYAP3ts.mjs";
|
|
5
|
+
import { t as slackContextTargetsMatch } from "./targets-eeOxA_b_.mjs";
|
|
6
|
+
import { $t as resolveSlackExecApprovalTarget, At as resolveSessionSlackOriginTarget, Dt as isSlackPluginApprovalRequest, Et as isSlackAnyNativeApprovalClientEnabled, Ft as shouldHandleSlackPluginViaForwardingSession, It as slackTargetsMatch, Kt as getSlackInstallationKind, Lt as getSlackApprovalApproversForTeam, Mt as resolveSlackFallbackOriginTarget, Nt as resolveTurnSourceSlackOriginTarget, Ot as normalizeSlackForwardTarget, P as countSlackTextUtf8Bytes, Pt as shouldHandleSlackNativeApprovalRequest, Rt as isSlackPluginApprovalAuthorizedSender, S as assertSlackDetachedTargetAllowed, Xt as isSlackExecApprovalAuthorizedSender, Yt as getSlackExecApprovalApprovers, Zt as isSlackExecApprovalClientEnabled, _ as qualifySlackRoutePeerId, _t as renderSlackMessagePresentationFallbackText, b as resolveSlackConversationBindingRoute, d as resolveSlackGroupRequireMention, en as shouldSuppressLocalSlackExecApprovalPrompt, f as resolveSlackGroupToolPolicy, g as qualifySlackConversationId, i as setSlackSessionStatus, jt as resolveSlackApproverDmTargets, kt as normalizeSlackOriginTarget, m as formatSlackError, mt as SLACK_PRESENTATION_CAPABILITIES, qt as isSlackWorkspaceInstallation, rn as resolveSlackAutoThreadId, s as slackIngressIdentity, t as probeSlack, tn as resolvePluginApprovalSlackApprovers, vt as SLACK_EDIT_TEXT_MAX_BYTES, wt as normalizeSlackOutboundText, xt as SLACK_TEXT_LIMIT, y as normalizeSlackRouteBindingConfig, zt as resolveSlackApprovalTeamId } from "./probe-B_Ax1vS1.mjs";
|
|
7
|
+
import { n as resolveSlackReplyThreadTs, r as resolveSlackThreadTsValue, t as normalizeSlackThreadTsCandidate } from "./thread-ts-47Au2-Yn.mjs";
|
|
8
|
+
import { n as extractSlackToolSend, t as describeSlackMessageTool } from "./message-tool-api-B38BpEaE.mjs";
|
|
9
|
+
import { a as resolveSlackReplyBlockResolution, o as resolveSlackReplyBlocks, r as normalizeSlackReplyPayload, s as resolveSlackReplyDeliveryMessages } from "./reply-blocks-DyYYRrP_.mjs";
|
|
10
|
+
import { r as createSlackLookupClient, t as collectSlackCursorPages, u as getSlackWriteClient } from "./cursor-pages-jVn3Vkfi.mjs";
|
|
11
|
+
import { n as resolveSlackChannelType, r as resolveSlackConversationInfo } from "./channel-type-9Lw6yLf2.mjs";
|
|
12
|
+
import { n as SLACK_CHANNEL_META } from "./channel-meta-C5vsCo3a.mjs";
|
|
13
|
+
import { i as SLACK_CHANNEL, r as slackBaseConfigAdapter, t as slackSetupPlugin } from "./channel.setup-BlgXNuCJ.mjs";
|
|
14
|
+
import { n as normalizeCompatibilityConfig, r as runtime_doctor_migrations_exports, t as legacyConfigRules } from "./doctor-contract-BB2KJ9Ni.mjs";
|
|
15
|
+
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-CqVqR7MP.mjs";
|
|
16
|
+
import { normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
|
|
16
17
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
17
|
-
import { adaptScopedAccountAccessor } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
18
|
+
import { adaptScopedAccountAccessor, createScopedDmSecurityResolver } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
18
19
|
import { buildOutboundBaseSessionKey, normalizeMessageChannel, resolveAccountEntry, resolveAgentRoute } from "openclaw/plugin-sdk/routing";
|
|
20
|
+
import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, normalizeAccountId as normalizeAccountId$2 } from "openclaw/plugin-sdk/account-id";
|
|
19
21
|
import { buildLegacyDmAccountAllowlistAdapter, createAccountScopedAllowlistNameResolver, createFlatAllowlistOverrideResolver } from "openclaw/plugin-sdk/allowlist-config-edit";
|
|
20
22
|
import { buildThreadAwareOutboundSessionRoute, createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core";
|
|
21
23
|
import { createChannelMessageAdapterFromOutbound, createRuntimeOutboundDelegates } from "openclaw/plugin-sdk/channel-outbound";
|
|
@@ -33,9 +35,11 @@ import { createChannelNativeOriginTargetResolverAsync, createNativeApprovalForwa
|
|
|
33
35
|
import { readBooleanParam } from "openclaw/plugin-sdk/boolean-param";
|
|
34
36
|
import { resolveReactionMessageId } from "openclaw/plugin-sdk/channel-actions";
|
|
35
37
|
import { normalizeLegacyInteractiveReply, normalizeMessagePresentation } from "openclaw/plugin-sdk/interactive-runtime";
|
|
36
|
-
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
37
38
|
import { readPositiveIntegerParam as readPositiveIntegerParam$1, readStringParam as readStringParam$1 } from "openclaw/plugin-sdk/param-readers";
|
|
38
|
-
|
|
39
|
+
import { buildMutableAllowEntryDetector, collectStandardAllowlistLists, createConditionalWarningCollector, createDangerousNameMatchingMutableAllowlistWarningCollector, createOpenProviderConfiguredRouteWarningCollector } from "openclaw/plugin-sdk/channel-policy";
|
|
40
|
+
import { identityEntryAuthenticationClassifier } from "openclaw/plugin-sdk/channel-ingress-runtime";
|
|
41
|
+
import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
|
|
42
|
+
// extensions/slack/src/approval-native.ts
|
|
39
43
|
function resolveSlackNativeSuppressionAccountId({ target, request }) {
|
|
40
44
|
return normalizeOptionalString(target.accountId) ?? normalizeOptionalString(request.request.turnSourceAccountId);
|
|
41
45
|
}
|
|
@@ -99,7 +103,7 @@ const baseSlackApprovalCapability = createApproverRestrictedNativeApprovalCapabi
|
|
|
99
103
|
],
|
|
100
104
|
isConfigured: isSlackAnyNativeApprovalClientEnabled,
|
|
101
105
|
shouldHandle: shouldHandleSlackNativeApprovalRequest,
|
|
102
|
-
load: async () => (await import("./approval-handler.runtime-
|
|
106
|
+
load: async () => (await import("./approval-handler.runtime-Ch7BecYK.mjs")).slackApprovalNativeRuntime
|
|
103
107
|
})
|
|
104
108
|
});
|
|
105
109
|
const baseSlackNativeAdapter = baseSlackApprovalCapability.nativeAsync;
|
|
@@ -167,8 +171,7 @@ const slackApprovalCapability = {
|
|
|
167
171
|
}
|
|
168
172
|
} : void 0
|
|
169
173
|
};
|
|
170
|
-
|
|
171
|
-
//#region extensions/slack/src/message-action-dispatch.ts
|
|
174
|
+
// extensions/slack/src/channel-actions.ts
|
|
172
175
|
const SLACK_MESSAGE_ACTIONS = /* @__PURE__ */ new Map([
|
|
173
176
|
["reactions", "reactions"],
|
|
174
177
|
["delete", "deleteMessage"],
|
|
@@ -179,196 +182,28 @@ const SLACK_MESSAGE_ACTIONS = /* @__PURE__ */ new Map([
|
|
|
179
182
|
function readSlackForceDocument(params) {
|
|
180
183
|
return readBooleanParam(params, "forceDocument") ?? readBooleanParam(params, "asDocument") ?? false;
|
|
181
184
|
}
|
|
182
|
-
function renderSlackActionPresentation(content, presentation) {
|
|
185
|
+
function renderSlackActionPresentation(content, presentation, markdownOptions) {
|
|
186
|
+
const renderedContent = normalizeSlackOutboundText(content ?? "", markdownOptions);
|
|
183
187
|
if (!presentation) return {
|
|
184
|
-
text:
|
|
188
|
+
text: renderedContent,
|
|
185
189
|
usesPresentationTextFallback: false
|
|
186
190
|
};
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
|
|
191
|
+
const resolution = resolveSlackReplyBlockResolution({
|
|
192
|
+
text: content,
|
|
193
|
+
presentation
|
|
194
|
+
}, markdownOptions);
|
|
195
|
+
const segment = resolution.segments.length === 1 ? resolution.segments[0] : void 0;
|
|
196
|
+
const usesPresentationTextFallback = segment?.kind !== "blocks" || presentation.blocks.some((block) => (block.type === "text" || block.type === "context") && block.text.trim().length > 3e3);
|
|
197
|
+
const blocks = !usesPresentationTextFallback && segment?.kind === "blocks" ? segment.blocks : void 0;
|
|
190
198
|
return {
|
|
191
199
|
...blocks?.length ? { blocks } : {},
|
|
192
200
|
text: usesPresentationTextFallback || presentation.blocks.some((block) => block.type === "chart" || block.type === "table") ? renderSlackMessagePresentationFallbackText({
|
|
193
|
-
text:
|
|
201
|
+
text: resolution.authoredTextPlacement === "blocks" ? void 0 : renderedContent,
|
|
194
202
|
presentation
|
|
195
|
-
}) :
|
|
203
|
+
}) : renderedContent,
|
|
196
204
|
usesPresentationTextFallback
|
|
197
205
|
};
|
|
198
206
|
}
|
|
199
|
-
async function handleSlackMessageAction(params) {
|
|
200
|
-
const { providerId, ctx, invoke } = params;
|
|
201
|
-
const { action, cfg, params: actionParams } = ctx;
|
|
202
|
-
const accountId = ctx.accountId ?? void 0;
|
|
203
|
-
const invokeSlackAction = (request, toolContext = ctx.toolContext) => invoke({
|
|
204
|
-
...request,
|
|
205
|
-
accountId
|
|
206
|
-
}, cfg, toolContext);
|
|
207
|
-
const resolveChannelId = () => {
|
|
208
|
-
const raw = readStringParam$1(actionParams, "channelId") ?? readStringParam$1(actionParams, "to", { required: true });
|
|
209
|
-
const target = parseSlackTarget(raw, { defaultKind: "channel" });
|
|
210
|
-
const channelId = resolveSlackChannelId(raw);
|
|
211
|
-
return formatSlackTarget({
|
|
212
|
-
teamId: target?.teamId,
|
|
213
|
-
kind: "channel",
|
|
214
|
-
id: channelId
|
|
215
|
-
});
|
|
216
|
-
};
|
|
217
|
-
if (action === "conversation-open") return await invokeSlackAction({
|
|
218
|
-
action: "openConversation",
|
|
219
|
-
userIds: actionParams.userIds,
|
|
220
|
-
teamId: readStringParam$1(actionParams, "teamId")
|
|
221
|
-
});
|
|
222
|
-
if (action === "send") {
|
|
223
|
-
const to = readStringParam$1(actionParams, "to", { required: true });
|
|
224
|
-
const content = readStringParam$1(actionParams, "message", {
|
|
225
|
-
required: false,
|
|
226
|
-
allowEmpty: true
|
|
227
|
-
});
|
|
228
|
-
const mediaUrl = readStringParam$1(actionParams, "media", { trim: false });
|
|
229
|
-
const presentation = normalizeMessagePresentation(actionParams.presentation);
|
|
230
|
-
const interactive = normalizeLegacyInteractiveReply(actionParams.interactive);
|
|
231
|
-
const hasStructuredContent = Boolean(presentation || interactive?.blocks.length);
|
|
232
|
-
const resolution = resolveSlackReplyBlockResolution({
|
|
233
|
-
text: content,
|
|
234
|
-
presentation,
|
|
235
|
-
interactive
|
|
236
|
-
}, { materializeAuthoredText: hasStructuredContent });
|
|
237
|
-
const preparedMessages = resolution.segments.length > 0 ? resolveSlackReplyDeliveryMessages({
|
|
238
|
-
authoredTextPlacement: resolution.authoredTextPlacement,
|
|
239
|
-
segments: resolution.segments,
|
|
240
|
-
text: content
|
|
241
|
-
}) : [];
|
|
242
|
-
if (!content && preparedMessages.length === 0 && !mediaUrl) throw new Error("Slack send requires message, blocks, or media.");
|
|
243
|
-
const replyBroadcast = readBooleanParam(actionParams, "replyBroadcast");
|
|
244
|
-
if (replyBroadcast && mediaUrl) throw new Error("Slack replyBroadcast is only supported for text or block thread replies.");
|
|
245
|
-
const threadId = readStringParam$1(actionParams, "threadId");
|
|
246
|
-
const replyTo = readStringParam$1(actionParams, "replyTo");
|
|
247
|
-
const topLevel = readBooleanParam(actionParams, "topLevel") === true || actionParams.threadId === null;
|
|
248
|
-
const toolContext = preparedMessages.length > 0 ? {
|
|
249
|
-
...ctx.toolContext,
|
|
250
|
-
preparedMessages
|
|
251
|
-
} : ctx.toolContext;
|
|
252
|
-
return await invokeSlackAction({
|
|
253
|
-
action: "sendMessage",
|
|
254
|
-
to,
|
|
255
|
-
content: content ?? "",
|
|
256
|
-
mediaUrl: mediaUrl ?? void 0,
|
|
257
|
-
...readSlackForceDocument(actionParams) ? { forceDocument: true } : {},
|
|
258
|
-
threadTs: resolveSlackThreadTsValue({
|
|
259
|
-
replyToId: replyTo,
|
|
260
|
-
threadId
|
|
261
|
-
}),
|
|
262
|
-
...topLevel ? { topLevel: true } : {},
|
|
263
|
-
...replyBroadcast ? { replyBroadcast } : {}
|
|
264
|
-
}, toolContext);
|
|
265
|
-
}
|
|
266
|
-
if (action === "react") {
|
|
267
|
-
const messageIdRaw = resolveReactionMessageId({
|
|
268
|
-
args: actionParams,
|
|
269
|
-
toolContext: ctx.toolContext
|
|
270
|
-
});
|
|
271
|
-
if (messageIdRaw == null) throw new Error("messageId required. Provide messageId explicitly or react to the current inbound message.");
|
|
272
|
-
const messageId = String(messageIdRaw);
|
|
273
|
-
const emoji = readStringParam$1(actionParams, "emoji", { allowEmpty: true });
|
|
274
|
-
const remove = typeof actionParams.remove === "boolean" ? actionParams.remove : void 0;
|
|
275
|
-
return await invokeSlackAction({
|
|
276
|
-
action: "react",
|
|
277
|
-
channelId: resolveChannelId(),
|
|
278
|
-
messageId,
|
|
279
|
-
emoji,
|
|
280
|
-
remove
|
|
281
|
-
});
|
|
282
|
-
}
|
|
283
|
-
const messageAction = SLACK_MESSAGE_ACTIONS.get(action);
|
|
284
|
-
if (messageAction) {
|
|
285
|
-
const messageId = action === "list-pins" ? void 0 : readStringParam$1(actionParams, "messageId", { required: true });
|
|
286
|
-
return await invokeSlackAction({
|
|
287
|
-
action: messageAction,
|
|
288
|
-
channelId: resolveChannelId(),
|
|
289
|
-
messageId,
|
|
290
|
-
...action === "reactions" ? { limit: actionParams.limit } : {}
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
if (action === "read") return await invokeSlackAction({
|
|
294
|
-
action: "readMessages",
|
|
295
|
-
channelId: resolveChannelId(),
|
|
296
|
-
limit: actionParams.limit,
|
|
297
|
-
before: readStringParam$1(actionParams, "before"),
|
|
298
|
-
after: readStringParam$1(actionParams, "after"),
|
|
299
|
-
messageId: readStringParam$1(actionParams, "messageId"),
|
|
300
|
-
threadId: readStringParam$1(actionParams, "threadId")
|
|
301
|
-
});
|
|
302
|
-
if (action === "edit") {
|
|
303
|
-
const messageId = readStringParam$1(actionParams, "messageId", { required: true });
|
|
304
|
-
const { blocks, text: accessibleContent, usesPresentationTextFallback } = renderSlackActionPresentation(readStringParam$1(actionParams, "message", { allowEmpty: true }), normalizeMessagePresentation(actionParams.presentation));
|
|
305
|
-
const tableMode = resolveMarkdownTableMode({
|
|
306
|
-
cfg,
|
|
307
|
-
channel: "slack",
|
|
308
|
-
accountId: accountId ?? resolveDefaultSlackAccountId(cfg)
|
|
309
|
-
});
|
|
310
|
-
if (!blocks && countSlackTextUtf8Bytes(normalizeSlackOutboundText(accessibleContent, { tableMode })) > 4e3) throw new Error(`${usesPresentationTextFallback ? "Slack presentation fallback" : "Slack edit"} exceeds the ${String(SLACK_EDIT_TEXT_MAX_BYTES)}-byte edit limit. Send a new message instead.`);
|
|
311
|
-
if (!accessibleContent && !blocks) throw new Error("Slack edit requires message or blocks.");
|
|
312
|
-
return await invokeSlackAction({
|
|
313
|
-
action: "editMessage",
|
|
314
|
-
channelId: resolveChannelId(),
|
|
315
|
-
messageId,
|
|
316
|
-
content: accessibleContent,
|
|
317
|
-
blocks
|
|
318
|
-
});
|
|
319
|
-
}
|
|
320
|
-
if (action === "member-info") {
|
|
321
|
-
const requesterAccountId = ctx.requesterAccountId ? normalizeAccountId$1(ctx.requesterAccountId) : void 0;
|
|
322
|
-
const targetAccountId = normalizeAccountId$1(accountId ?? resolveDefaultSlackAccountId(cfg));
|
|
323
|
-
const requesterUserId = normalizeOptionalLowercaseString(ctx.toolContext?.currentChannelProvider) === "slack" && requesterAccountId !== void 0 && requesterAccountId === targetAccountId ? normalizeOptionalString(ctx.requesterSenderId) : void 0;
|
|
324
|
-
const userId = readStringParam$1(actionParams, "userId") ?? requesterUserId;
|
|
325
|
-
if (!userId) throw new Error("member-info requires a userId outside a current Slack conversation.");
|
|
326
|
-
return await invokeSlackAction({
|
|
327
|
-
action: "memberInfo",
|
|
328
|
-
userId
|
|
329
|
-
});
|
|
330
|
-
}
|
|
331
|
-
if (action === "emoji-list") return await invokeSlackAction({
|
|
332
|
-
action: "emojiList",
|
|
333
|
-
limit: readPositiveIntegerParam$1(actionParams, "limit", { message: "limit must be a positive integer." })
|
|
334
|
-
});
|
|
335
|
-
if (action === "download-file") {
|
|
336
|
-
const fileIdParam = readStringParam$1(actionParams, "fileId");
|
|
337
|
-
const messageIdParam = readStringParam$1(actionParams, "messageId") ?? readStringParam$1(actionParams, "message_id");
|
|
338
|
-
if (!fileIdParam && messageIdParam) throw new Error("download-file requires fileId (the Slack file id, for example F0B0LTT8M36 from event.files[].id), not messageId. Did you mean to pass fileId? messageId is the Slack message timestamp and is used by react / reactions / edit / delete / pin / unpin actions, not download-file.");
|
|
339
|
-
const fileId = readStringParam$1(actionParams, "fileId", { required: true });
|
|
340
|
-
const channelId = readStringParam$1(actionParams, "channelId") ?? readStringParam$1(actionParams, "to");
|
|
341
|
-
const threadId = readStringParam$1(actionParams, "threadId") ?? readStringParam$1(actionParams, "replyTo");
|
|
342
|
-
return await invokeSlackAction({
|
|
343
|
-
action: "downloadFile",
|
|
344
|
-
fileId,
|
|
345
|
-
channelId: channelId ?? void 0,
|
|
346
|
-
threadId: threadId ?? void 0
|
|
347
|
-
});
|
|
348
|
-
}
|
|
349
|
-
if (action === "upload-file") {
|
|
350
|
-
if (readBooleanParam(actionParams, "replyBroadcast")) throw new Error("Slack replyBroadcast is only supported for text or block thread replies.");
|
|
351
|
-
const to = readStringParam$1(actionParams, "to") ?? resolveChannelId();
|
|
352
|
-
const filePath = readStringParam$1(actionParams, "filePath", { trim: false }) ?? readStringParam$1(actionParams, "path", { trim: false }) ?? readStringParam$1(actionParams, "media", { trim: false });
|
|
353
|
-
if (!filePath) throw new Error("upload-file requires filePath, path, or media");
|
|
354
|
-
const threadId = readStringParam$1(actionParams, "threadId") ?? readStringParam$1(actionParams, "replyTo");
|
|
355
|
-
const topLevel = readBooleanParam(actionParams, "topLevel") === true || actionParams.threadId === null;
|
|
356
|
-
return await invokeSlackAction({
|
|
357
|
-
action: "uploadFile",
|
|
358
|
-
to,
|
|
359
|
-
filePath,
|
|
360
|
-
initialComment: readStringParam$1(actionParams, "initialComment", { allowEmpty: true }) ?? readStringParam$1(actionParams, "message", { allowEmpty: true }) ?? readStringParam$1(actionParams, "caption", { allowEmpty: true }) ?? "",
|
|
361
|
-
filename: readStringParam$1(actionParams, "filename"),
|
|
362
|
-
title: readStringParam$1(actionParams, "title"),
|
|
363
|
-
threadTs: threadId ?? void 0,
|
|
364
|
-
...readSlackForceDocument(actionParams) ? { forceDocument: true } : {},
|
|
365
|
-
...topLevel ? { topLevel: true } : {}
|
|
366
|
-
});
|
|
367
|
-
}
|
|
368
|
-
throw new Error(`Action ${action} is not supported for provider ${providerId}.`);
|
|
369
|
-
}
|
|
370
|
-
//#endregion
|
|
371
|
-
//#region extensions/slack/src/channel-actions.ts
|
|
372
207
|
const SLACK_TOOL_DELIVERY_ACTIONS = /* @__PURE__ */ new Set([
|
|
373
208
|
"deleteMessage",
|
|
374
209
|
"editMessage",
|
|
@@ -378,7 +213,7 @@ const SLACK_TOOL_DELIVERY_ACTIONS = /* @__PURE__ */ new Set([
|
|
|
378
213
|
"unpinMessage",
|
|
379
214
|
"uploadFile"
|
|
380
215
|
]);
|
|
381
|
-
const loadSlackActionRuntime
|
|
216
|
+
const loadSlackActionRuntime = createLazyRuntimeModule(() => import("./action-runtime.runtime-CpZktret.mjs"));
|
|
382
217
|
function resolveSlackActionContext(ctx, toolContext) {
|
|
383
218
|
if (!toolContext && !ctx.mediaAccess && !ctx.mediaLocalRoots && !ctx.mediaReadFile && !ctx.conversationReadOrigin && !ctx.requesterAccountId && !ctx.requesterSenderId && !ctx.assertDirectAdapterHandoff) return;
|
|
384
219
|
return {
|
|
@@ -408,14 +243,187 @@ function createSlackActions(providerId, options) {
|
|
|
408
243
|
isToolDeliveryAction: ({ args }) => typeof args.action === "string" && SLACK_TOOL_DELIVERY_ACTIONS.has(args.action),
|
|
409
244
|
prepareSendPayload: ({ ctx, to, payload }) => ctx.action === "send" && !shouldUseWorkspaceAwareSlackActionSend(to, ctx.toolContext) ? payload : null,
|
|
410
245
|
handleAction: async (ctx) => {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
}
|
|
246
|
+
const { action, cfg, params: actionParams } = ctx;
|
|
247
|
+
const accountId = ctx.accountId ?? void 0;
|
|
248
|
+
const invokeSlackAction = async (request, toolContext = ctx.toolContext) => {
|
|
249
|
+
const requestAction = {
|
|
250
|
+
...request,
|
|
251
|
+
accountId
|
|
252
|
+
};
|
|
253
|
+
const actionContext = resolveSlackActionContext(ctx, toolContext);
|
|
254
|
+
return await (options?.invoke ? options.invoke(requestAction, cfg, actionContext) : (await loadSlackActionRuntime()).handleSlackAction(requestAction, cfg, actionContext));
|
|
255
|
+
};
|
|
256
|
+
const resolveChannelId = () => {
|
|
257
|
+
const raw = readStringParam$1(actionParams, "channelId") ?? readStringParam$1(actionParams, "to", { required: true });
|
|
258
|
+
const target = parseSlackTarget(raw, { defaultKind: "channel" });
|
|
259
|
+
const channelId = resolveSlackChannelId(raw);
|
|
260
|
+
return formatSlackTarget({
|
|
261
|
+
teamId: target?.teamId,
|
|
262
|
+
kind: "channel",
|
|
263
|
+
id: channelId
|
|
264
|
+
});
|
|
265
|
+
};
|
|
266
|
+
if (action === "channel-create") return await invokeSlackAction({
|
|
267
|
+
action: "createChannel",
|
|
268
|
+
name: readStringParam$1(actionParams, "name", { required: true }),
|
|
269
|
+
teamId: readStringParam$1(actionParams, "teamId")
|
|
270
|
+
});
|
|
271
|
+
if (action === "conversation-open") return await invokeSlackAction({
|
|
272
|
+
action: "openConversation",
|
|
273
|
+
userIds: actionParams.userIds,
|
|
274
|
+
teamId: readStringParam$1(actionParams, "teamId")
|
|
418
275
|
});
|
|
276
|
+
if (action === "send") {
|
|
277
|
+
const to = readStringParam$1(actionParams, "to", { required: true });
|
|
278
|
+
const content = readStringParam$1(actionParams, "message", {
|
|
279
|
+
required: false,
|
|
280
|
+
allowEmpty: true
|
|
281
|
+
});
|
|
282
|
+
const mediaUrl = readStringParam$1(actionParams, "media", { trim: false });
|
|
283
|
+
const presentation = normalizeMessagePresentation(actionParams.presentation);
|
|
284
|
+
const interactive = normalizeLegacyInteractiveReply(actionParams.interactive);
|
|
285
|
+
const hasStructuredContent = Boolean(presentation || interactive?.blocks.length);
|
|
286
|
+
const resolution = resolveSlackReplyBlockResolution({
|
|
287
|
+
text: content,
|
|
288
|
+
presentation,
|
|
289
|
+
interactive
|
|
290
|
+
}, {
|
|
291
|
+
...resolveSlackMarkdownOptions({
|
|
292
|
+
cfg,
|
|
293
|
+
accountId
|
|
294
|
+
}),
|
|
295
|
+
materializeAuthoredText: hasStructuredContent
|
|
296
|
+
});
|
|
297
|
+
const preparedMessages = resolution.segments.length > 0 ? resolveSlackReplyDeliveryMessages({
|
|
298
|
+
authoredTextPlacement: resolution.authoredTextPlacement,
|
|
299
|
+
segments: resolution.segments,
|
|
300
|
+
text: content
|
|
301
|
+
}) : [];
|
|
302
|
+
if (!content && preparedMessages.length === 0 && !mediaUrl) throw new Error("Slack send requires message, blocks, or media.");
|
|
303
|
+
const replyBroadcast = readBooleanParam(actionParams, "replyBroadcast");
|
|
304
|
+
if (replyBroadcast && mediaUrl) throw new Error("Slack replyBroadcast is only supported for text or block thread replies.");
|
|
305
|
+
const threadId = readStringParam$1(actionParams, "threadId");
|
|
306
|
+
const replyTo = readStringParam$1(actionParams, "replyTo");
|
|
307
|
+
const topLevel = readBooleanParam(actionParams, "topLevel") === true || actionParams.threadId === null;
|
|
308
|
+
const toolContext = preparedMessages.length > 0 ? {
|
|
309
|
+
...ctx.toolContext,
|
|
310
|
+
preparedMessages
|
|
311
|
+
} : ctx.toolContext;
|
|
312
|
+
return await invokeSlackAction({
|
|
313
|
+
action: "sendMessage",
|
|
314
|
+
to,
|
|
315
|
+
content: content ?? "",
|
|
316
|
+
mediaUrl,
|
|
317
|
+
...readSlackForceDocument(actionParams) ? { forceDocument: true } : {},
|
|
318
|
+
threadTs: resolveSlackThreadTsValue({
|
|
319
|
+
replyToId: replyTo,
|
|
320
|
+
threadId
|
|
321
|
+
}),
|
|
322
|
+
...topLevel ? { topLevel: true } : {},
|
|
323
|
+
...replyBroadcast ? { replyBroadcast } : {}
|
|
324
|
+
}, toolContext);
|
|
325
|
+
}
|
|
326
|
+
if (action === "react") {
|
|
327
|
+
const messageIdRaw = resolveReactionMessageId({
|
|
328
|
+
args: actionParams,
|
|
329
|
+
toolContext: ctx.toolContext
|
|
330
|
+
});
|
|
331
|
+
if (messageIdRaw == null) throw new Error("messageId required. Provide messageId explicitly or react to the current inbound message.");
|
|
332
|
+
const messageId = String(messageIdRaw);
|
|
333
|
+
const emoji = readStringParam$1(actionParams, "emoji", { allowEmpty: true });
|
|
334
|
+
const remove = typeof actionParams.remove === "boolean" ? actionParams.remove : void 0;
|
|
335
|
+
return await invokeSlackAction({
|
|
336
|
+
action: "react",
|
|
337
|
+
channelId: resolveChannelId(),
|
|
338
|
+
messageId,
|
|
339
|
+
emoji,
|
|
340
|
+
remove
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
const messageAction = SLACK_MESSAGE_ACTIONS.get(action);
|
|
344
|
+
if (messageAction) {
|
|
345
|
+
const messageId = action === "list-pins" ? void 0 : readStringParam$1(actionParams, "messageId", { required: true });
|
|
346
|
+
return await invokeSlackAction({
|
|
347
|
+
action: messageAction,
|
|
348
|
+
channelId: resolveChannelId(),
|
|
349
|
+
messageId,
|
|
350
|
+
...action === "reactions" ? { limit: actionParams.limit } : {}
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
if (action === "read") return await invokeSlackAction({
|
|
354
|
+
action: "readMessages",
|
|
355
|
+
channelId: resolveChannelId(),
|
|
356
|
+
limit: actionParams.limit,
|
|
357
|
+
before: readStringParam$1(actionParams, "before"),
|
|
358
|
+
after: readStringParam$1(actionParams, "after"),
|
|
359
|
+
messageId: readStringParam$1(actionParams, "messageId"),
|
|
360
|
+
threadId: readStringParam$1(actionParams, "threadId")
|
|
361
|
+
});
|
|
362
|
+
if (action === "edit") {
|
|
363
|
+
const messageId = readStringParam$1(actionParams, "messageId", { required: true });
|
|
364
|
+
const { blocks, text: accessibleContent, usesPresentationTextFallback } = renderSlackActionPresentation(readStringParam$1(actionParams, "message", { allowEmpty: true }), normalizeMessagePresentation(actionParams.presentation), resolveSlackMarkdownOptions({
|
|
365
|
+
cfg,
|
|
366
|
+
accountId
|
|
367
|
+
}));
|
|
368
|
+
if (!blocks && countSlackTextUtf8Bytes(accessibleContent) > 4e3) throw new Error(`${usesPresentationTextFallback ? "Slack presentation fallback" : "Slack edit"} exceeds the ${String(SLACK_EDIT_TEXT_MAX_BYTES)}-byte edit limit. Send a new message instead.`);
|
|
369
|
+
if (!accessibleContent && !blocks) throw new Error("Slack edit requires message or blocks.");
|
|
370
|
+
return await invokeSlackAction({
|
|
371
|
+
action: "editMessage",
|
|
372
|
+
channelId: resolveChannelId(),
|
|
373
|
+
messageId,
|
|
374
|
+
content: accessibleContent,
|
|
375
|
+
blocks
|
|
376
|
+
}, {
|
|
377
|
+
...ctx.toolContext,
|
|
378
|
+
preparedEditText: accessibleContent
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
if (action === "member-info") {
|
|
382
|
+
const requesterAccountId = ctx.requesterAccountId ? normalizeAccountId(ctx.requesterAccountId) : void 0;
|
|
383
|
+
const targetAccountId = normalizeAccountId(accountId ?? resolveDefaultSlackAccountId(cfg));
|
|
384
|
+
const requesterUserId = normalizeOptionalLowercaseString(ctx.toolContext?.currentChannelProvider) === "slack" && requesterAccountId !== void 0 && requesterAccountId === targetAccountId ? normalizeOptionalString(ctx.requesterSenderId) : void 0;
|
|
385
|
+
const userId = readStringParam$1(actionParams, "userId") ?? requesterUserId;
|
|
386
|
+
if (!userId) throw new Error("member-info requires a userId outside a current Slack conversation.");
|
|
387
|
+
return await invokeSlackAction({
|
|
388
|
+
action: "memberInfo",
|
|
389
|
+
userId
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
if (action === "emoji-list") return await invokeSlackAction({
|
|
393
|
+
action: "emojiList",
|
|
394
|
+
limit: readPositiveIntegerParam$1(actionParams, "limit", { message: "limit must be a positive integer." })
|
|
395
|
+
});
|
|
396
|
+
if (action === "download-file") {
|
|
397
|
+
const fileIdParam = readStringParam$1(actionParams, "fileId");
|
|
398
|
+
const messageIdParam = readStringParam$1(actionParams, "messageId") ?? readStringParam$1(actionParams, "message_id");
|
|
399
|
+
if (!fileIdParam && messageIdParam) throw new Error("download-file requires fileId (the Slack file id, for example F0B0LTT8M36 from event.files[].id), not messageId. Did you mean to pass fileId? messageId is the Slack message timestamp and is used by react / reactions / edit / delete / pin / unpin actions, not download-file.");
|
|
400
|
+
return await invokeSlackAction({
|
|
401
|
+
action: "downloadFile",
|
|
402
|
+
fileId: fileIdParam ?? readStringParam$1(actionParams, "fileId", { required: true }),
|
|
403
|
+
channelId: readStringParam$1(actionParams, "channelId") ?? readStringParam$1(actionParams, "to"),
|
|
404
|
+
threadId: readStringParam$1(actionParams, "threadId") ?? readStringParam$1(actionParams, "replyTo")
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
if (action === "upload-file") {
|
|
408
|
+
if (readBooleanParam(actionParams, "replyBroadcast")) throw new Error("Slack replyBroadcast is only supported for text or block thread replies.");
|
|
409
|
+
const to = readStringParam$1(actionParams, "to") ?? resolveChannelId();
|
|
410
|
+
const filePath = readStringParam$1(actionParams, "filePath", { trim: false }) ?? readStringParam$1(actionParams, "path", { trim: false }) ?? readStringParam$1(actionParams, "media", { trim: false });
|
|
411
|
+
if (!filePath) throw new Error("upload-file requires filePath, path, or media");
|
|
412
|
+
const threadId = readStringParam$1(actionParams, "threadId") ?? readStringParam$1(actionParams, "replyTo");
|
|
413
|
+
const topLevel = readBooleanParam(actionParams, "topLevel") === true || actionParams.threadId === null;
|
|
414
|
+
return await invokeSlackAction({
|
|
415
|
+
action: "uploadFile",
|
|
416
|
+
to,
|
|
417
|
+
filePath,
|
|
418
|
+
initialComment: readStringParam$1(actionParams, "initialComment", { allowEmpty: true }) ?? readStringParam$1(actionParams, "message", { allowEmpty: true }) ?? readStringParam$1(actionParams, "caption", { allowEmpty: true }) ?? "",
|
|
419
|
+
filename: readStringParam$1(actionParams, "filename"),
|
|
420
|
+
title: readStringParam$1(actionParams, "title"),
|
|
421
|
+
threadTs: threadId,
|
|
422
|
+
...readSlackForceDocument(actionParams) ? { forceDocument: true } : {},
|
|
423
|
+
...topLevel ? { topLevel: true } : {}
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
throw new Error(`Action ${action} is not supported for provider ${providerId}.`);
|
|
419
427
|
}
|
|
420
428
|
};
|
|
421
429
|
}
|
|
@@ -429,12 +437,11 @@ function shouldUseWorkspaceAwareSlackActionSend(rawTarget, context) {
|
|
|
429
437
|
}
|
|
430
438
|
return false;
|
|
431
439
|
}
|
|
432
|
-
|
|
433
|
-
//#region extensions/slack/src/conversation-route-owner.ts
|
|
440
|
+
// extensions/slack/src/conversation-route-owner.ts
|
|
434
441
|
function prepareSlackConversationRouteOwner(params) {
|
|
435
|
-
const accountId = normalizeAccountId(params.accountId);
|
|
442
|
+
const accountId = normalizeAccountId$2(params.accountId);
|
|
436
443
|
const accountConfig = resolveAccountEntry(params.cfg.channels?.slack?.accounts, accountId);
|
|
437
|
-
if (params.cfg.channels?.slack?.enabled === false || accountConfig?.enabled === false || !accountConfig && (accountId !== DEFAULT_ACCOUNT_ID || !hasImplicitDefaultSlackAccount(params.cfg))) return {
|
|
444
|
+
if (params.cfg.channels?.slack?.enabled === false || accountConfig?.enabled === false || !accountConfig && (accountId !== DEFAULT_ACCOUNT_ID$1 || !hasImplicitDefaultSlackAccount(params.cfg))) return {
|
|
438
445
|
kind: "terminal",
|
|
439
446
|
owner: null
|
|
440
447
|
};
|
|
@@ -516,7 +523,7 @@ function prepareSlackConversationRouteOwner(params) {
|
|
|
516
523
|
}
|
|
517
524
|
};
|
|
518
525
|
}
|
|
519
|
-
async
|
|
526
|
+
const slackConversationRouteOwners = { prepareConversationRouteOwnersAsync: async (inputs, inspectBindings) => {
|
|
520
527
|
const prepared = inputs.map(prepareSlackConversationRouteOwner);
|
|
521
528
|
const inspect = await inspectBindings(prepared.flatMap((item) => item.kind === "prepared" && item.route.bindingsEnabled ? [{
|
|
522
529
|
channel: "slack",
|
|
@@ -549,10 +556,8 @@ async function prepareSlackConversationRouteOwnersAsync(inputs, inspectBindings)
|
|
|
549
556
|
thread: thread()
|
|
550
557
|
});
|
|
551
558
|
});
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
//#endregion
|
|
555
|
-
//#region extensions/slack/src/enterprise-user-route.ts
|
|
559
|
+
} };
|
|
560
|
+
// extensions/slack/src/enterprise-user-route.ts
|
|
556
561
|
/** Resolve a workspace for a detached Enterprise DM without opening a conversation. */
|
|
557
562
|
async function resolveSlackEnterpriseUserTeamId(params) {
|
|
558
563
|
const account = resolveSlackAccount(params);
|
|
@@ -577,8 +582,245 @@ async function resolveSlackEnterpriseUserTeamId(params) {
|
|
|
577
582
|
if (!teamId) throw new Error("unsupported_enterprise_slack_delivery: recipient shares no verified installed workspace");
|
|
578
583
|
return teamId;
|
|
579
584
|
}
|
|
580
|
-
|
|
581
|
-
|
|
585
|
+
// extensions/slack/src/security.ts
|
|
586
|
+
const resolveSlackDmPolicy = createScopedDmSecurityResolver({
|
|
587
|
+
channelKey: "slack",
|
|
588
|
+
resolvePolicy: (account) => account.config.dmPolicy,
|
|
589
|
+
resolveAllowFrom: (account) => account.config.allowFrom,
|
|
590
|
+
resolveAccess: ({ cfg, account }) => ({
|
|
591
|
+
dmPolicy: resolveSlackAccountDmPolicy({
|
|
592
|
+
cfg,
|
|
593
|
+
accountId: account.accountId
|
|
594
|
+
}),
|
|
595
|
+
allowFrom: resolveSlackAccountAllowFrom({
|
|
596
|
+
cfg,
|
|
597
|
+
accountId: account.accountId
|
|
598
|
+
})
|
|
599
|
+
}),
|
|
600
|
+
policyPathSuffix: "dmPolicy",
|
|
601
|
+
classifyEntryAuthentication: identityEntryAuthenticationClassifier(slackIngressIdentity),
|
|
602
|
+
normalizeEntry: (raw) => raw.trim().replace(/^(slack|user):/i, "").trim()
|
|
603
|
+
});
|
|
604
|
+
const collectSlackSecurityWarnings = createOpenProviderConfiguredRouteWarningCollector({
|
|
605
|
+
providerConfigPresent: (cfg) => cfg.channels?.slack !== void 0,
|
|
606
|
+
resolveGroupPolicy: (account) => account.config.groupPolicy,
|
|
607
|
+
resolveRouteAllowlistConfigured: (account) => Boolean(account.config.channels) && Object.keys(account.config.channels ?? {}).length > 0,
|
|
608
|
+
configureRouteAllowlist: {
|
|
609
|
+
surface: "Slack channels",
|
|
610
|
+
openScope: "any channel not explicitly denied",
|
|
611
|
+
groupPolicyPath: "channels.slack.groupPolicy",
|
|
612
|
+
routeAllowlistPath: "channels.slack.channels"
|
|
613
|
+
},
|
|
614
|
+
missingRouteAllowlist: {
|
|
615
|
+
surface: "Slack channels",
|
|
616
|
+
openBehavior: "with no channel allowlist; any channel can trigger (mention-gated)",
|
|
617
|
+
remediation: "Set channels.slack.groupPolicy=\"allowlist\" and configure channels.slack.channels"
|
|
618
|
+
}
|
|
619
|
+
});
|
|
620
|
+
const collectSlackSecurityFindings = createConditionalWarningCollector.findings({
|
|
621
|
+
collectWarnings: collectSlackSecurityWarnings,
|
|
622
|
+
checkId: "channels.slack.groups.open",
|
|
623
|
+
severity: "warn",
|
|
624
|
+
title: "Slack security warning"
|
|
625
|
+
});
|
|
626
|
+
const loadSlackSecurityAuditModule = createLazyRuntimeModule(() => import("./security-audit-C3hXCfDt.mjs").then((n) => n.n));
|
|
627
|
+
const slackSecurityAdapter = {
|
|
628
|
+
resolveDmPolicy: resolveSlackDmPolicy,
|
|
629
|
+
collectWarnings: collectSlackSecurityFindings,
|
|
630
|
+
collectAuditFindings: async (params) => {
|
|
631
|
+
const { collectSlackSecurityAuditFindings } = await loadSlackSecurityAuditModule();
|
|
632
|
+
return await collectSlackSecurityAuditFindings(params);
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
// extensions/slack/src/doctor.ts
|
|
636
|
+
const isSlackMutableUnqualifiedAllowEntry = buildMutableAllowEntryDetector({ stableIdPattern: /^(?:(?:(?:[sS][lL][aA][cC][kK]|[uU][sS][eE][rR]):)?(?:[UWBCGDT][A-Z0-9]{2,}|[A-Za-z0-9]{8,})|<@[A-Za-z0-9]{8,}>)$/ });
|
|
637
|
+
const collectSlackMutableAllowlistWarnings = createDangerousNameMatchingMutableAllowlistWarningCollector({
|
|
638
|
+
channel: "slack",
|
|
639
|
+
detector: (entry) => {
|
|
640
|
+
if (/^team:/i.test(entry)) try {
|
|
641
|
+
const target = parseSlackTarget(entry);
|
|
642
|
+
if (target?.kind === "user" && target.teamId) return false;
|
|
643
|
+
} catch {}
|
|
644
|
+
return isSlackMutableUnqualifiedAllowEntry(entry);
|
|
645
|
+
},
|
|
646
|
+
collectLists: (scope) => collectStandardAllowlistLists(scope, {
|
|
647
|
+
includeGroupAllowFrom: false,
|
|
648
|
+
includeDm: true,
|
|
649
|
+
includeGroups: true,
|
|
650
|
+
groupsKey: "channels",
|
|
651
|
+
groupField: "users"
|
|
652
|
+
})
|
|
653
|
+
});
|
|
654
|
+
const SLACK_CANONICAL_CHANNEL_ID_RE = /^(?:channel:)?[CG][A-Z0-9]{8,}$/;
|
|
655
|
+
const SLACK_LOWERCASE_CHANNEL_ID_RE = /^(?:channel:)?[cg][0-9][a-z0-9]{7,}$/;
|
|
656
|
+
const SLACK_CANONICAL_DM_ID_RE = /^(?:channel:)?D[A-Z0-9]{8,}$/;
|
|
657
|
+
const SLACK_PREFIXED_LOWERCASE_DM_ID_RE = /^channel:d[a-z0-9]{8,}$/;
|
|
658
|
+
const SLACK_AMBIGUOUS_LOWERCASE_DM_ID_RE = /^d[a-z0-9]{8,}$/;
|
|
659
|
+
const SLACK_AMBIGUOUS_LOWERCASE_CHANNEL_ID_RE = /^(?:channel:)?[cgd][a-z][a-z0-9]{7,}$/;
|
|
660
|
+
const SLACK_CHANNEL_NAME_RE = /^[\p{L}\p{M}\p{N}_-]{1,80}$/u;
|
|
661
|
+
const SLACK_CHANNEL_NAME_ALPHANUMERIC_RE = /[\p{L}\p{N}]/u;
|
|
662
|
+
function looksLikeSlackChannelId(channelKey) {
|
|
663
|
+
const workspaceChannelId = parseWorkspaceQualifiedChannelId(channelKey);
|
|
664
|
+
return workspaceChannelId !== void 0 && /^[CG]/i.test(workspaceChannelId) || SLACK_CANONICAL_CHANNEL_ID_RE.test(channelKey) || SLACK_LOWERCASE_CHANNEL_ID_RE.test(channelKey);
|
|
665
|
+
}
|
|
666
|
+
function looksLikeSlackDmId(channelKey) {
|
|
667
|
+
const workspaceChannelId = parseWorkspaceQualifiedChannelId(channelKey);
|
|
668
|
+
return workspaceChannelId !== void 0 && /^D/i.test(workspaceChannelId) || SLACK_CANONICAL_DM_ID_RE.test(channelKey) || SLACK_PREFIXED_LOWERCASE_DM_ID_RE.test(channelKey);
|
|
669
|
+
}
|
|
670
|
+
function parseWorkspaceQualifiedChannelId(channelKey) {
|
|
671
|
+
if (!/^team:/i.test(channelKey)) return;
|
|
672
|
+
try {
|
|
673
|
+
const target = parseSlackTarget(channelKey);
|
|
674
|
+
return target?.kind === "channel" && target.teamId ? target.id : void 0;
|
|
675
|
+
} catch {
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
function looksLikeSlackChannelNameKey(channelKey) {
|
|
680
|
+
const name = channelKey.startsWith("#") ? channelKey.slice(1) : channelKey;
|
|
681
|
+
return name === name.toLowerCase() && SLACK_CHANNEL_NAME_RE.test(name) && SLACK_CHANNEL_NAME_ALPHANUMERIC_RE.test(name);
|
|
682
|
+
}
|
|
683
|
+
function collectSlackNameKeyedChannelWarnings({ cfg }) {
|
|
684
|
+
const warnings = /* @__PURE__ */ new Set();
|
|
685
|
+
const slackCfg = (0, runtime_doctor_migrations_exports.asObjectRecord)((0, runtime_doctor_migrations_exports.asObjectRecord)(cfg.channels)?.slack);
|
|
686
|
+
const providerChannels = (0, runtime_doctor_migrations_exports.asObjectRecord)(slackCfg?.channels);
|
|
687
|
+
const accounts = (0, runtime_doctor_migrations_exports.asObjectRecord)(slackCfg?.accounts);
|
|
688
|
+
for (const accountId of listSlackAccountIds(cfg)) {
|
|
689
|
+
const account = (0, runtime_doctor_migrations_exports.asObjectRecord)(mergeSlackAccountConfig(cfg, accountId));
|
|
690
|
+
if (!account || slackCfg?.enabled === false || account.enabled === false) continue;
|
|
691
|
+
const effectiveGroupPolicy = (typeof account.groupPolicy === "string" ? account.groupPolicy : void 0) ?? "allowlist";
|
|
692
|
+
const rawAccount = (0, runtime_doctor_migrations_exports.asObjectRecord)(accounts?.[accountId]);
|
|
693
|
+
const accountPrefix = rawAccount ? `channels.slack.accounts.${accountId}` : "channels.slack";
|
|
694
|
+
const accountChannels = (0, runtime_doctor_migrations_exports.asObjectRecord)(rawAccount?.channels);
|
|
695
|
+
const channels = accountChannels ?? providerChannels;
|
|
696
|
+
if (!channels) continue;
|
|
697
|
+
const channelsPrefix = accountChannels ? `channels.slack.accounts.${accountId}` : "channels.slack";
|
|
698
|
+
const fallbackDescription = Object.hasOwn(channels, "*") ? `${channelsPrefix}.channels."*" applies instead and this entry's overrides are ignored` : effectiveGroupPolicy === "open" ? "this entry's overrides are ignored and the channel remains allowed by groupPolicy: \"open\"" : "messages from the channel are dropped";
|
|
699
|
+
for (const channelKey of Object.keys(channels)) {
|
|
700
|
+
if (channelKey === "*") continue;
|
|
701
|
+
if (looksLikeSlackDmId(channelKey)) {
|
|
702
|
+
warnings.add(`${channelsPrefix}.channels."${channelKey}" is a Slack DM conversation ID, but ${channelsPrefix}.channels only configures channel and group rooms. Configure DM access with ${accountPrefix}.dmPolicy and ${accountPrefix}.allowFrom instead.`);
|
|
703
|
+
continue;
|
|
704
|
+
}
|
|
705
|
+
if (SLACK_AMBIGUOUS_LOWERCASE_DM_ID_RE.test(channelKey)) {
|
|
706
|
+
if (account.dangerouslyAllowNameMatching === true && looksLikeSlackChannelNameKey(channelKey)) continue;
|
|
707
|
+
warnings.add(`${channelsPrefix}.channels."${channelKey}" is ambiguous: it may be a lowercase Slack DM conversation ID or a channel name. Configure DMs with ${accountPrefix}.dmPolicy and ${accountPrefix}.allowFrom; otherwise re-key the room with its stable C/G ID.`);
|
|
708
|
+
continue;
|
|
709
|
+
}
|
|
710
|
+
if (effectiveGroupPolicy === "disabled") continue;
|
|
711
|
+
const channelConfig = (0, runtime_doctor_migrations_exports.asObjectRecord)(channels[channelKey]);
|
|
712
|
+
if (effectiveGroupPolicy === "open" && Object.keys(channelConfig ?? {}).length === 0) continue;
|
|
713
|
+
if (looksLikeSlackChannelId(channelKey)) continue;
|
|
714
|
+
if (account.dangerouslyAllowNameMatching === true && looksLikeSlackChannelNameKey(channelKey)) continue;
|
|
715
|
+
if (SLACK_AMBIGUOUS_LOWERCASE_CHANNEL_ID_RE.test(channelKey)) {
|
|
716
|
+
warnings.add(`${channelsPrefix}.channels."${channelKey}" is ambiguous: it may be a lowercase Slack channel ID or a channel name. If it is a channel name, inbound routing will not match it and ${fallbackDescription}. Re-key it with the channel's stable ID (e.g. C0123ABCD, from the channel's About details or conversations.info).`);
|
|
717
|
+
continue;
|
|
718
|
+
}
|
|
719
|
+
warnings.add(`${channelsPrefix}.channels."${channelKey}" is keyed by a channel name or unsupported ID form, not a routable Slack channel ID; under groupPolicy: "${effectiveGroupPolicy}" inbound routing does not match this entry, so ${fallbackDescription}. Re-key it with the channel's ID (e.g. C0123ABCD, from the channel's About details or conversations.info).`);
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
return [...warnings];
|
|
723
|
+
}
|
|
724
|
+
async function collectSlackUserIdentityWarnings(params) {
|
|
725
|
+
const warnings = [];
|
|
726
|
+
for (const accountId of listSlackAccountIds(params.cfg)) {
|
|
727
|
+
const account = inspectSlackAccount({
|
|
728
|
+
cfg: params.cfg,
|
|
729
|
+
accountId,
|
|
730
|
+
envBotToken: params.env?.SLACK_BOT_TOKEN,
|
|
731
|
+
envAppToken: params.env?.SLACK_APP_TOKEN,
|
|
732
|
+
envUserToken: params.env?.SLACK_USER_TOKEN
|
|
733
|
+
});
|
|
734
|
+
if (!account.enabled || account.identity !== "user") continue;
|
|
735
|
+
const path = accountId === "default" ? "channels.slack" : `channels.slack.accounts.${accountId}`;
|
|
736
|
+
const mode = account.mode ?? "socket";
|
|
737
|
+
if (mode === "socket" && account.appTokenStatus === "missing") warnings.push(`- ${path}: identity "user" in Socket Mode requires appToken for companion-app events.`);
|
|
738
|
+
else if (mode === "http" && account.signingSecretStatus === "missing") warnings.push(`- ${path}: identity "user" in HTTP mode requires signingSecret for companion-app events.`);
|
|
739
|
+
if (!account.userToken) {
|
|
740
|
+
warnings.push(account.userTokenStatus === "configured_unavailable" ? `- ${path}: userToken is configured but unavailable; Slack auth.test validation was skipped.` : `- ${path}: identity "user" requires userToken for the authorizing human.`);
|
|
741
|
+
continue;
|
|
742
|
+
}
|
|
743
|
+
const probe = await probeSlack(account.userToken, 2500, {
|
|
744
|
+
accountId,
|
|
745
|
+
identity: "user"
|
|
746
|
+
});
|
|
747
|
+
if (!probe.ok) {
|
|
748
|
+
warnings.push(`- ${path}: userToken auth.test failed: ${probe.error ?? "unknown error"}.`);
|
|
749
|
+
continue;
|
|
750
|
+
}
|
|
751
|
+
const userId = probe.user?.id?.trim();
|
|
752
|
+
const userName = probe.user?.name?.trim();
|
|
753
|
+
if (!userId) {
|
|
754
|
+
warnings.push(`- ${path}: userToken auth.test succeeded but returned no human user_id.`);
|
|
755
|
+
continue;
|
|
756
|
+
}
|
|
757
|
+
warnings.push(`- ${path}: user identity authenticated as ${userName ? `@${userName} ` : ""}(${userId}).`);
|
|
758
|
+
}
|
|
759
|
+
return warnings;
|
|
760
|
+
}
|
|
761
|
+
const slackDoctor = {
|
|
762
|
+
dmAllowFromMode: "topOnly",
|
|
763
|
+
groupModel: "route",
|
|
764
|
+
groupAllowFromFallbackToAllowFrom: false,
|
|
765
|
+
warnOnEmptyGroupSenderAllowlist: false,
|
|
766
|
+
legacyConfigRules,
|
|
767
|
+
normalizeCompatibilityConfig,
|
|
768
|
+
collectPreviewWarnings: collectSlackUserIdentityWarnings,
|
|
769
|
+
collectMutableAllowlistWarnings: ({ cfg }) => [...collectSlackMutableAllowlistWarnings({ cfg }), ...collectSlackNameKeyedChannelWarnings({ cfg })]
|
|
770
|
+
};
|
|
771
|
+
// extensions/slack/src/shared.ts
|
|
772
|
+
const slackConfigAdapter = {
|
|
773
|
+
...slackBaseConfigAdapter,
|
|
774
|
+
inspectAccount: adaptScopedAccountAccessor(inspectSlackAccount)
|
|
775
|
+
};
|
|
776
|
+
const slackPluginBase = {
|
|
777
|
+
...slackSetupPlugin,
|
|
778
|
+
meta: {
|
|
779
|
+
...SLACK_CHANNEL_META,
|
|
780
|
+
preferSessionLookupForAnnounceTarget: true
|
|
781
|
+
},
|
|
782
|
+
doctor: slackDoctor,
|
|
783
|
+
agentPrompt: {
|
|
784
|
+
questionInputMode: "buttons",
|
|
785
|
+
customInlineButtonHint: true,
|
|
786
|
+
inboundFormattingHints: () => ({
|
|
787
|
+
text_markup: "markdown",
|
|
788
|
+
rules: [
|
|
789
|
+
"Write replies in standard Markdown; OpenClaw converts them to Slack mrkdwn.",
|
|
790
|
+
"Bold uses **double asterisks**; *single asterisks* or _underscores_ produce italics.",
|
|
791
|
+
"Links use [label](url). Keep Slack mentions as <@USER_ID>.",
|
|
792
|
+
"Use presentation table blocks for tabular data; Markdown pipe tables are not auto-promoted.",
|
|
793
|
+
"Only raw Block Kit or presentation text fields use Slack mrkdwn directly: *bold*, _italic_, ~strike~, and <url|label> links. Avoid Markdown headings or pipe tables in those fields."
|
|
794
|
+
]
|
|
795
|
+
}),
|
|
796
|
+
messageToolHints: () => [
|
|
797
|
+
"- Use `presentation` buttons/selects for discrete choices or parameter picks instead of asking the user to type one.",
|
|
798
|
+
"- For line, bar, area, or pie data, use a `presentation` chart block; Slack renders it as a native chart and retains a text data summary for accessibility.",
|
|
799
|
+
"- For row-and-column data, use an explicit `presentation` table block; Slack renders it as a native table and retains a linear text summary for accessibility. Markdown pipe tables are not auto-promoted.",
|
|
800
|
+
"- Slack plain text sends: write standard Markdown; OpenClaw converts it to Slack mrkdwn, including `**bold**`, headings, lists, and `[label](url)` links.",
|
|
801
|
+
"- When mentioning Slack users, use the stable `<@USER_ID>` token from Slack context instead of plain `@name` text so Slack notifies and links the user.",
|
|
802
|
+
"- Slack Block Kit or presentation text fields are sent as Slack mrkdwn directly; use `*bold*`, `_italic_`, `~strike~`, `<url|label>` links, and avoid Markdown headings or pipe tables there."
|
|
803
|
+
]
|
|
804
|
+
},
|
|
805
|
+
config: {
|
|
806
|
+
...slackSetupPlugin.config,
|
|
807
|
+
...slackConfigAdapter,
|
|
808
|
+
isConfigured: isSlackPluginAccountConfigured,
|
|
809
|
+
describeAccount: (account) => describeAccountSnapshot({
|
|
810
|
+
account,
|
|
811
|
+
configured: isSlackPluginAccountConfigured(account),
|
|
812
|
+
extra: {
|
|
813
|
+
botTokenSource: account.botTokenSource,
|
|
814
|
+
appTokenSource: account.appTokenSource
|
|
815
|
+
}
|
|
816
|
+
})
|
|
817
|
+
},
|
|
818
|
+
secrets: {
|
|
819
|
+
secretTargetRegistryEntries,
|
|
820
|
+
collectRuntimeConfigAssignments
|
|
821
|
+
}
|
|
822
|
+
};
|
|
823
|
+
// extensions/slack/src/threading-tool-context.ts
|
|
582
824
|
function buildSlackThreadingToolContext(params) {
|
|
583
825
|
const account = resolveSlackAccount({
|
|
584
826
|
cfg: params.cfg,
|
|
@@ -608,24 +850,19 @@ function buildSlackThreadingToolContext(params) {
|
|
|
608
850
|
sameChannelThreadRequired: hasExplicitThreadTarget
|
|
609
851
|
};
|
|
610
852
|
}
|
|
611
|
-
|
|
612
|
-
//#region extensions/slack/src/channel.ts
|
|
853
|
+
// extensions/slack/src/channel.ts
|
|
613
854
|
const loadExtensionSharedSdk = createLazyRuntimeModule(() => import("openclaw/plugin-sdk/extension-shared"));
|
|
614
855
|
const loadTargetResolverRuntimeSdk = createLazyRuntimeModule(() => import("openclaw/plugin-sdk/target-resolver-runtime"));
|
|
615
|
-
const loadSlackScopesModule = createLazyRuntimeModule(() => import("./scopes-
|
|
616
|
-
const loadSlackOutboundAdapterModule = createLazyRuntimeModule(() => import("./outbound-adapter-
|
|
856
|
+
const loadSlackScopesModule = createLazyRuntimeModule(() => import("./scopes-CzHC_dwV.mjs"));
|
|
857
|
+
const loadSlackOutboundAdapterModule = createLazyRuntimeModule(() => import("./outbound-adapter-BH6iPWBj.mjs"));
|
|
617
858
|
const bindSlackOutbound = createLazyRuntimeMethodBinder(loadSlackOutboundAdapterModule);
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
const
|
|
622
|
-
const
|
|
623
|
-
const
|
|
624
|
-
const
|
|
625
|
-
const loadSlackSendRuntime = createLazyRuntimeModule(() => import("./send-C-8wY0lK.mjs").then((n) => n.n));
|
|
626
|
-
const loadSlackProbeModule = createLazyRuntimeModule(() => import("./probe-IiHogLQN.mjs").then((n) => n.n));
|
|
627
|
-
const loadSlackMonitorModule = createLazyRuntimeModule(() => import("./monitor-BFilOuM_.mjs").then((n) => n.t));
|
|
628
|
-
const loadSlackDirectoryLiveModule = createLazyRuntimeModule(() => import("./directory-live-BIKD-5B_.mjs").then((n) => n.t));
|
|
859
|
+
const loadSlackDirectoryConfigModule = createLazyRuntimeModule(() => import("./directory-config-CGvKYg9F.mjs").then((n) => n.t));
|
|
860
|
+
const loadSlackResolveChannelsModule = createLazyRuntimeModule(() => import("./resolve-channels-CF2JME9q.mjs").then((n) => n.n));
|
|
861
|
+
const loadSlackResolveUsersModule = createLazyRuntimeModule(() => import("./resolve-users-DDcCAjH1.mjs").then((n) => n.n));
|
|
862
|
+
const loadSlackSendRuntime = createLazyRuntimeModule(() => import("./send-WJZ73VSf.mjs").then((n) => n.n));
|
|
863
|
+
const loadSlackProbeModule = createLazyRuntimeModule(() => import("./probe-B_Ax1vS1.mjs").then((n) => n.n));
|
|
864
|
+
const loadSlackMonitorModule = createLazyRuntimeModule(() => import("./monitor-BD86SotB.mjs").then((n) => n.t));
|
|
865
|
+
const loadSlackDirectoryLiveModule = createLazyRuntimeModule(() => import("./directory-live-DNdw97LA.mjs").then((n) => n.t));
|
|
629
866
|
async function setSlackHeartbeatThreadStatus(params) {
|
|
630
867
|
const threadTs = resolveSlackThreadTsValue({ threadId: params.threadId });
|
|
631
868
|
const target = parseSlackTarget(params.to, { defaultKind: "channel" });
|
|
@@ -672,106 +909,6 @@ function normalizeSlackAcpConversationId(raw) {
|
|
|
672
909
|
const conversationId = normalizeLowercaseStringOrEmpty(parsed?.id ?? trimmed.replace(/^slack:/i, "").replace(/^(?:channel|group|direct|user):/i, ""));
|
|
673
910
|
return conversationId ? { conversationId } : null;
|
|
674
911
|
}
|
|
675
|
-
function matchSlackAcpConversation(params) {
|
|
676
|
-
const bindingConversationId = normalizeSlackAcpConversationId(params.bindingConversationId)?.conversationId;
|
|
677
|
-
const conversationId = normalizeSlackAcpConversationId(params.conversationId)?.conversationId;
|
|
678
|
-
const parentConversationId = normalizeSlackAcpConversationId(params.parentConversationId)?.conversationId;
|
|
679
|
-
if (!bindingConversationId || !conversationId) return null;
|
|
680
|
-
if (bindingConversationId === conversationId) return {
|
|
681
|
-
conversationId,
|
|
682
|
-
matchPriority: 2
|
|
683
|
-
};
|
|
684
|
-
if (parentConversationId && parentConversationId !== conversationId && bindingConversationId === parentConversationId) return {
|
|
685
|
-
conversationId: parentConversationId,
|
|
686
|
-
matchPriority: 1
|
|
687
|
-
};
|
|
688
|
-
return null;
|
|
689
|
-
}
|
|
690
|
-
async function resolveSlackOutboundSessionRoute(params) {
|
|
691
|
-
const parsed = parseSlackTarget(params.target, { defaultKind: "channel" });
|
|
692
|
-
if (!parsed) return null;
|
|
693
|
-
const apiTargetId = canonicalizeSlackApiTargetId(parsed.kind, parsed.id, params.target);
|
|
694
|
-
const isDm = parsed.kind === "user";
|
|
695
|
-
if (params.deliveryPurpose === "heartbeat-owner" && isDm && !parsed.teamId && /^[UW][A-Z0-9]{8,}$/.test(apiTargetId)) {
|
|
696
|
-
const teamId = await resolveSlackEnterpriseUserTeamId({
|
|
697
|
-
cfg: params.cfg,
|
|
698
|
-
accountId: params.accountId,
|
|
699
|
-
userId: apiTargetId
|
|
700
|
-
});
|
|
701
|
-
if (teamId) {
|
|
702
|
-
parsed.teamId = teamId;
|
|
703
|
-
parsed.id = apiTargetId;
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
let peerKind = isDm ? "direct" : "channel";
|
|
707
|
-
let peerId = formatSlackTarget(parsed);
|
|
708
|
-
let recipientSessionExact = isDm ? /^[UW][A-Z0-9]{8,}$/i.test(parsed.id) : /^C[A-Z0-9]{8,}$/i.test(parsed.id);
|
|
709
|
-
if (!isDm && /^D/i.test(parsed.id)) {
|
|
710
|
-
const conversation = await resolveSlackConversationInfo({
|
|
711
|
-
cfg: params.cfg,
|
|
712
|
-
accountId: params.accountId,
|
|
713
|
-
channelId: apiTargetId,
|
|
714
|
-
teamId: parsed.teamId
|
|
715
|
-
});
|
|
716
|
-
if (conversation.type !== "dm" || !conversation.user) return null;
|
|
717
|
-
peerKind = "direct";
|
|
718
|
-
peerId = formatSlackTarget({
|
|
719
|
-
teamId: parsed.teamId,
|
|
720
|
-
kind: "user",
|
|
721
|
-
id: conversation.user
|
|
722
|
-
});
|
|
723
|
-
recipientSessionExact = true;
|
|
724
|
-
} else if (!isDm && /^G/i.test(parsed.id)) {
|
|
725
|
-
const channelType = await resolveSlackChannelType({
|
|
726
|
-
cfg: params.cfg,
|
|
727
|
-
accountId: params.accountId,
|
|
728
|
-
channelId: apiTargetId,
|
|
729
|
-
teamId: parsed.teamId
|
|
730
|
-
});
|
|
731
|
-
if (channelType === "group") peerKind = "group";
|
|
732
|
-
if (channelType === "dm") peerKind = "direct";
|
|
733
|
-
recipientSessionExact = channelType !== "unknown";
|
|
734
|
-
}
|
|
735
|
-
const peer = {
|
|
736
|
-
kind: peerKind,
|
|
737
|
-
id: peerId
|
|
738
|
-
};
|
|
739
|
-
const unpartitionedBaseSessionKey = buildOutboundBaseSessionKey({
|
|
740
|
-
channel: "slack",
|
|
741
|
-
cfg: params.cfg,
|
|
742
|
-
agentId: params.agentId,
|
|
743
|
-
accountId: params.accountId,
|
|
744
|
-
peer
|
|
745
|
-
});
|
|
746
|
-
const baseSessionKey = parsed.teamId && peerKind === "direct" && (params.cfg.session?.dmScope ?? "main") === "main" ? `${unpartitionedBaseSessionKey}:account:${encodeURIComponent(resolveSlackAccount({
|
|
747
|
-
cfg: params.cfg,
|
|
748
|
-
accountId: params.accountId
|
|
749
|
-
}).accountId).toLowerCase()}:team:${encodeURIComponent(parsed.teamId).toLowerCase()}` : unpartitionedBaseSessionKey;
|
|
750
|
-
return buildThreadAwareOutboundSessionRoute({
|
|
751
|
-
route: {
|
|
752
|
-
sessionKey: baseSessionKey,
|
|
753
|
-
baseSessionKey,
|
|
754
|
-
recipientSessionExact,
|
|
755
|
-
peer,
|
|
756
|
-
chatType: peerKind === "direct" ? "direct" : "channel",
|
|
757
|
-
from: peerKind === "direct" ? `slack:${peerId}` : peerKind === "group" ? `slack:group:${peerId}` : `slack:channel:${peerId}`,
|
|
758
|
-
to: parsed.teamId ? peerId : peerKind === "direct" ? `user:${peerId}` : `channel:${peerId}`
|
|
759
|
-
},
|
|
760
|
-
replyToId: params.replyToId,
|
|
761
|
-
threadId: params.threadId,
|
|
762
|
-
currentSessionKey: params.currentSessionKey,
|
|
763
|
-
canRecoverCurrentThread: () => peerKind !== "direct" || (params.cfg.session?.dmScope ?? "main") !== "main"
|
|
764
|
-
});
|
|
765
|
-
}
|
|
766
|
-
function formatSlackScopeDiagnostic(params) {
|
|
767
|
-
const source = params.result.source ? ` (${params.result.source})` : "";
|
|
768
|
-
const label = params.tokenType === "user" ? "User scopes" : "Bot scopes";
|
|
769
|
-
if (params.result.ok && params.result.scopes?.length) return { text: `${label}${source}: ${params.result.scopes.join(", ")}` };
|
|
770
|
-
return {
|
|
771
|
-
text: `${label}: ${params.result.error ?? "scope lookup failed"}`,
|
|
772
|
-
tone: "error"
|
|
773
|
-
};
|
|
774
|
-
}
|
|
775
912
|
const resolveSlackAllowlistGroupOverrides = createFlatAllowlistOverrideResolver({
|
|
776
913
|
resolveRecord: (account) => account.channels,
|
|
777
914
|
label: (key) => key,
|
|
@@ -887,11 +1024,21 @@ const slackPlugin = createChatChannelPlugin({
|
|
|
887
1024
|
},
|
|
888
1025
|
bindings: {
|
|
889
1026
|
compileConfiguredBinding: ({ conversationId }) => normalizeSlackAcpConversationId(conversationId),
|
|
890
|
-
matchInboundConversation: ({ compiledBinding, conversationId, parentConversationId }) =>
|
|
891
|
-
bindingConversationId
|
|
892
|
-
conversationId
|
|
893
|
-
parentConversationId
|
|
894
|
-
|
|
1027
|
+
matchInboundConversation: ({ compiledBinding, conversationId: rawConversationId, parentConversationId: rawParentConversationId }) => {
|
|
1028
|
+
const bindingConversationId = normalizeSlackAcpConversationId(compiledBinding.conversationId)?.conversationId;
|
|
1029
|
+
const conversationId = normalizeSlackAcpConversationId(rawConversationId)?.conversationId;
|
|
1030
|
+
const parentConversationId = normalizeSlackAcpConversationId(rawParentConversationId)?.conversationId;
|
|
1031
|
+
if (!bindingConversationId || !conversationId) return null;
|
|
1032
|
+
if (bindingConversationId === conversationId) return {
|
|
1033
|
+
conversationId,
|
|
1034
|
+
matchPriority: 2
|
|
1035
|
+
};
|
|
1036
|
+
if (parentConversationId && parentConversationId !== conversationId && bindingConversationId === parentConversationId) return {
|
|
1037
|
+
conversationId: parentConversationId,
|
|
1038
|
+
matchPriority: 1
|
|
1039
|
+
};
|
|
1040
|
+
return null;
|
|
1041
|
+
}
|
|
895
1042
|
},
|
|
896
1043
|
conversationBindings: { isCurrentConversationBindingSupported: ({ accountId }) => isSlackWorkspaceInstallation(accountId) },
|
|
897
1044
|
messaging: {
|
|
@@ -912,7 +1059,82 @@ const slackPlugin = createChatChannelPlugin({
|
|
|
912
1059
|
return normalizeSlackMessagingTarget(`channel:${id}`);
|
|
913
1060
|
},
|
|
914
1061
|
inferTargetChatType: ({ to }) => resolveSlackRouteTarget(to)?.chatType,
|
|
915
|
-
resolveOutboundSessionRoute:
|
|
1062
|
+
resolveOutboundSessionRoute: async (params) => {
|
|
1063
|
+
const parsed = parseSlackTarget(params.target, { defaultKind: "channel" });
|
|
1064
|
+
if (!parsed) return null;
|
|
1065
|
+
const apiTargetId = canonicalizeSlackApiTargetId(parsed.kind, parsed.id, params.target);
|
|
1066
|
+
const isDm = parsed.kind === "user";
|
|
1067
|
+
if (params.deliveryPurpose === "heartbeat-owner" && isDm && !parsed.teamId && /^[UW][A-Z0-9]{8,}$/.test(apiTargetId)) {
|
|
1068
|
+
const teamId = await resolveSlackEnterpriseUserTeamId({
|
|
1069
|
+
cfg: params.cfg,
|
|
1070
|
+
accountId: params.accountId,
|
|
1071
|
+
userId: apiTargetId
|
|
1072
|
+
});
|
|
1073
|
+
if (teamId) {
|
|
1074
|
+
parsed.teamId = teamId;
|
|
1075
|
+
parsed.id = apiTargetId;
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
let peerKind = isDm ? "direct" : "channel";
|
|
1079
|
+
let peerId = formatSlackTarget(parsed);
|
|
1080
|
+
let recipientSessionExact = isDm ? /^[UW][A-Z0-9]{8,}$/i.test(parsed.id) : /^C[A-Z0-9]{8,}$/i.test(parsed.id);
|
|
1081
|
+
if (!isDm && /^D/i.test(parsed.id)) {
|
|
1082
|
+
const conversation = await resolveSlackConversationInfo({
|
|
1083
|
+
cfg: params.cfg,
|
|
1084
|
+
accountId: params.accountId,
|
|
1085
|
+
channelId: apiTargetId,
|
|
1086
|
+
teamId: parsed.teamId
|
|
1087
|
+
});
|
|
1088
|
+
if (conversation.type !== "dm" || !conversation.user) return null;
|
|
1089
|
+
peerKind = "direct";
|
|
1090
|
+
peerId = formatSlackTarget({
|
|
1091
|
+
teamId: parsed.teamId,
|
|
1092
|
+
kind: "user",
|
|
1093
|
+
id: conversation.user
|
|
1094
|
+
});
|
|
1095
|
+
recipientSessionExact = true;
|
|
1096
|
+
} else if (!isDm && /^G/i.test(parsed.id)) {
|
|
1097
|
+
const channelType = await resolveSlackChannelType({
|
|
1098
|
+
cfg: params.cfg,
|
|
1099
|
+
accountId: params.accountId,
|
|
1100
|
+
channelId: apiTargetId,
|
|
1101
|
+
teamId: parsed.teamId
|
|
1102
|
+
});
|
|
1103
|
+
if (channelType === "group") peerKind = "group";
|
|
1104
|
+
if (channelType === "dm") peerKind = "direct";
|
|
1105
|
+
recipientSessionExact = channelType !== "unknown";
|
|
1106
|
+
}
|
|
1107
|
+
const peer = {
|
|
1108
|
+
kind: peerKind,
|
|
1109
|
+
id: peerId
|
|
1110
|
+
};
|
|
1111
|
+
const unpartitionedBaseSessionKey = buildOutboundBaseSessionKey({
|
|
1112
|
+
channel: "slack",
|
|
1113
|
+
cfg: params.cfg,
|
|
1114
|
+
agentId: params.agentId,
|
|
1115
|
+
accountId: params.accountId,
|
|
1116
|
+
peer
|
|
1117
|
+
});
|
|
1118
|
+
const baseSessionKey = parsed.teamId && peerKind === "direct" && (params.cfg.session?.dmScope ?? "main") === "main" ? `${unpartitionedBaseSessionKey}:account:${encodeURIComponent(resolveSlackAccount({
|
|
1119
|
+
cfg: params.cfg,
|
|
1120
|
+
accountId: params.accountId
|
|
1121
|
+
}).accountId).toLowerCase()}:team:${encodeURIComponent(parsed.teamId).toLowerCase()}` : unpartitionedBaseSessionKey;
|
|
1122
|
+
return buildThreadAwareOutboundSessionRoute({
|
|
1123
|
+
route: {
|
|
1124
|
+
sessionKey: baseSessionKey,
|
|
1125
|
+
baseSessionKey,
|
|
1126
|
+
recipientSessionExact,
|
|
1127
|
+
peer,
|
|
1128
|
+
chatType: peerKind === "direct" ? "direct" : "channel",
|
|
1129
|
+
from: peerKind === "direct" ? `slack:${peerId}` : peerKind === "group" ? `slack:group:${peerId}` : `slack:channel:${peerId}`,
|
|
1130
|
+
to: parsed.teamId ? peerId : peerKind === "direct" ? `user:${peerId}` : `channel:${peerId}`
|
|
1131
|
+
},
|
|
1132
|
+
replyToId: params.replyToId,
|
|
1133
|
+
threadId: params.threadId,
|
|
1134
|
+
currentSessionKey: params.currentSessionKey,
|
|
1135
|
+
canRecoverCurrentThread: () => peerKind !== "direct" || (params.cfg.session?.dmScope ?? "main") !== "main"
|
|
1136
|
+
});
|
|
1137
|
+
},
|
|
916
1138
|
hasStructuredReplyPayload: ({ payload }) => {
|
|
917
1139
|
try {
|
|
918
1140
|
return Boolean(resolveSlackReplyBlocks(payload)?.length);
|
|
@@ -974,7 +1196,7 @@ const slackPlugin = createChatChannelPlugin({
|
|
|
974
1196
|
mapResolved: (entry) => entry
|
|
975
1197
|
});
|
|
976
1198
|
} },
|
|
977
|
-
actions: createSlackActions(SLACK_CHANNEL
|
|
1199
|
+
actions: createSlackActions(SLACK_CHANNEL),
|
|
978
1200
|
message: slackMessageAdapter,
|
|
979
1201
|
heartbeat: {
|
|
980
1202
|
sendTyping: (params) => setSlackHeartbeatThreadStatus({
|
|
@@ -987,7 +1209,7 @@ const slackPlugin = createChatChannelPlugin({
|
|
|
987
1209
|
})
|
|
988
1210
|
},
|
|
989
1211
|
status: createComputedAccountStatusAdapter({
|
|
990
|
-
defaultRuntime: createDefaultChannelRuntimeState(DEFAULT_ACCOUNT_ID),
|
|
1212
|
+
defaultRuntime: createDefaultChannelRuntimeState(DEFAULT_ACCOUNT_ID$1),
|
|
991
1213
|
buildChannelSummary: async ({ snapshot }) => {
|
|
992
1214
|
const { buildPassiveProbedChannelStatusSummary } = await loadExtensionSharedSdk();
|
|
993
1215
|
return buildPassiveProbedChannelStatusSummary(snapshot, snapshot.identity === "user" ? {
|
|
@@ -1010,8 +1232,7 @@ const slackPlugin = createChatChannelPlugin({
|
|
|
1010
1232
|
...account.identity === "user" ? { identity: "user" } : {}
|
|
1011
1233
|
});
|
|
1012
1234
|
},
|
|
1013
|
-
formatCapabilitiesProbe: ({ probe }) => {
|
|
1014
|
-
const slackProbe = probe;
|
|
1235
|
+
formatCapabilitiesProbe: ({ probe: slackProbe }) => {
|
|
1015
1236
|
const lines = [];
|
|
1016
1237
|
if (slackProbe?.warning) lines.push({
|
|
1017
1238
|
text: `Warning: ${slackProbe.warning}`,
|
|
@@ -1041,10 +1262,12 @@ const slackPlugin = createChatChannelPlugin({
|
|
|
1041
1262
|
ok: false,
|
|
1042
1263
|
error: `Slack ${tokenType} token missing.`
|
|
1043
1264
|
};
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1265
|
+
const source = result.source ? ` (${result.source})` : "";
|
|
1266
|
+
const label = tokenType === "user" ? "User scopes" : "Bot scopes";
|
|
1267
|
+
lines.push(result.ok && result.scopes?.length ? { text: `${label}${source}: ${result.scopes.join(", ")}` } : {
|
|
1268
|
+
text: `${label}: ${result.error ?? "scope lookup failed"}`,
|
|
1269
|
+
tone: "error"
|
|
1270
|
+
});
|
|
1048
1271
|
details[`${tokenType}Scopes`] = result;
|
|
1049
1272
|
}
|
|
1050
1273
|
return {
|
|
@@ -1090,8 +1313,7 @@ const slackPlugin = createChatChannelPlugin({
|
|
|
1090
1313
|
abortSignal: ctx.abortSignal,
|
|
1091
1314
|
mediaMaxMb: account.config.mediaMaxMb,
|
|
1092
1315
|
slashCommand: account.config.slashCommand,
|
|
1093
|
-
setStatus: ctx.setStatus
|
|
1094
|
-
getStatus: ctx.getStatus
|
|
1316
|
+
setStatus: ctx.setStatus
|
|
1095
1317
|
});
|
|
1096
1318
|
}
|
|
1097
1319
|
},
|
|
@@ -1161,5 +1383,4 @@ const slackPlugin = createChatChannelPlugin({
|
|
|
1161
1383
|
},
|
|
1162
1384
|
outbound: slackChannelOutbound
|
|
1163
1385
|
});
|
|
1164
|
-
//#endregion
|
|
1165
1386
|
export { buildSlackThreadingToolContext as n, slackPlugin as t };
|