@openclaw/slack 2026.7.2-beta.2 → 2026.7.2-beta.3

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.
Files changed (57) hide show
  1. package/dist/{account-configured-DzC407uv.js → account-configured-BwfXBo_F.js} +1 -1
  2. package/dist/{account-inspect-Di7ditqZ.js → account-inspect-Bvbtu3iH.js} +9 -2
  3. package/dist/account-inspect-api.js +1 -1
  4. package/dist/{accounts-BOJJiHSr.js → accounts-DQEbYKh9.js} +9 -0
  5. package/dist/accounts.runtime-BIKmJdtJ.js +2 -0
  6. package/dist/{action-runtime-Cee2ih0s.js → action-runtime-DqkRwO3Z.js} +10 -16
  7. package/dist/action-runtime.runtime-DEWOcFM4.js +2 -0
  8. package/dist/{actions-BZiuSTIq.js → actions-CF0tUY5q.js} +4 -4
  9. package/dist/{actions.runtime-DoD0-gxw.js → actions.runtime-hCbx4RXg.js} +1 -1
  10. package/dist/api.js +13 -14
  11. package/dist/{approval-handler.runtime-CUPtIM4k.js → approval-handler.runtime-Em8I1-8-.js} +2 -2
  12. package/dist/{channel-DaIiGUOp.js → channel-4-TRi1D6.js} +72 -40
  13. package/dist/channel-config-api.js +1 -1
  14. package/dist/channel-plugin-api.js +1 -1
  15. package/dist/{channel-type-Cfm6_6n1.js → channel-type-Cu1yjNg2.js} +3 -3
  16. package/dist/{channel.setup-C-mLz50O.js → channel.setup-CgkADtZg.js} +6 -4
  17. package/dist/{config-schema-xPSnK2VK.js → config-schema-XjJGfwQC.js} +6 -5
  18. package/dist/{directory-config-DRkFujwG.js → directory-config-Bv0lcUlH.js} +1 -1
  19. package/dist/directory-contract-api.js +1 -1
  20. package/dist/{directory-live-D_yZhjgp.js → directory-live-CzUIB7th.js} +2 -2
  21. package/dist/{doctor-contract-DddfkMlF.js → doctor-contract-DKpe5VBr.js} +80 -12
  22. package/dist/doctor-contract-api.js +1 -1
  23. package/dist/{group-policy-85UWiriS.js → group-policy-Bw-65m3V.js} +67 -121
  24. package/dist/{interactive-replies-BilWUdcI.js → interactive-replies-Dm_t2R9S.js} +1 -1
  25. package/dist/interactive-replies-api.js +1 -1
  26. package/dist/{message-tool-api-CA9jZrCY.js → message-tool-api-C2pcf5du.js} +3 -3
  27. package/dist/message-tool-api.js +1 -1
  28. package/dist/{monitor-CalGciTs.js → monitor-CNFeF30h.js} +3 -3
  29. package/dist/{outbound-adapter-BiLKcnyH.js → outbound-adapter-CVi2uok0.js} +49 -5
  30. package/dist/{pipeline.runtime-DofAvTtb.js → pipeline.runtime-CTvokbty.js} +391 -279
  31. package/dist/{policy-BVs4LiSa.js → policy-b_dOPDCq.js} +1 -1
  32. package/dist/probe-Borhn9PQ.js +340 -0
  33. package/dist/{provider-CmeoUiIM.js → provider-B-HVL5ZE.js} +573 -306
  34. package/dist/{relay-source-DMmgtvg4.js → relay-source-Ea_P9VcO.js} +6 -11
  35. package/dist/{replies-CJJCp6qz.js → replies-B4bOdrYb.js} +3 -3
  36. package/dist/{resolve-channels-Rfts6POK.js → resolve-channels-KTc568SU.js} +1 -1
  37. package/dist/{resolve-users-y6wAxR8E.js → resolve-users-DeGJf1yp.js} +1 -1
  38. package/dist/{runtime-api-BGDyOt1D.js → runtime-api-BFfNpzDe.js} +1 -1
  39. package/dist/runtime-api.js +11 -11
  40. package/dist/{scopes-CuxNQZ6v.js → scopes-lx08L56K.js} +1 -2
  41. package/dist/{secret-contract-CMohXFWS.js → secret-contract-DxmvbxBF.js} +1 -0
  42. package/dist/secret-contract-api.js +1 -1
  43. package/dist/{send-DYp8ca-l.js → send-KuTDky7i.js} +28 -11
  44. package/dist/send.runtime-CXyxws1D.js +2 -0
  45. package/dist/{setup-core-CkwVLzFO.js → setup-core-CeiAVwQ3.js} +218 -53
  46. package/dist/setup-plugin-api.js +1 -1
  47. package/dist/{setup-surface-oSd3NX9J.js → setup-surface-DLA0vHXp.js} +23 -13
  48. package/dist/{shared-D9yz5Otg.js → shared-C4yVB0Q-.js} +55 -9
  49. package/dist/{slash-dispatch.runtime-CSja9VuD.js → slash-dispatch.runtime-BT-mMm-f.js} +1 -1
  50. package/npm-shrinkwrap.json +3 -3
  51. package/openclaw.plugin.json +66 -10
  52. package/package.json +4 -4
  53. package/dist/accounts.runtime-KvftRRek.js +0 -2
  54. package/dist/action-runtime.runtime-DZfd7IFr.js +0 -2
  55. package/dist/client-WIPAS3Yr.js +0 -160
  56. package/dist/probe-CN0ssfLN.js +0 -48
  57. package/dist/send.runtime-CJLxAt26.js +0 -2
@@ -1,4 +1,4 @@
1
- import { c as formatUnknownError, s as SLACK_SOCKET_RECONNECT_POLICY } from "./provider-CmeoUiIM.js";
1
+ import { c as formatUnknownError, s as SLACK_SOCKET_RECONNECT_POLICY } from "./provider-B-HVL5ZE.js";
2
2
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  import { computeBackoff, sleepWithAbort, warn } from "openclaw/plugin-sdk/runtime-env";
4
4
  import { Buffer } from "node:buffer";
@@ -27,7 +27,7 @@ async function monitorSlackRelaySource(params) {
27
27
  params.runtime.log?.(`slack relay mode connected gateway_id:${params.config.gatewayId}`);
28
28
  await runRelayWebSocket({
29
29
  connection,
30
- handleSlackMessage: params.handleSlackMessage,
30
+ acceptRelayEvent: params.acceptRelayEvent,
31
31
  runtime: params.runtime,
32
32
  abortSignal: params.abortSignal,
33
33
  setStatus: params.setStatus,
@@ -90,7 +90,6 @@ function openRelayWebSocket(config, abortSignal) {
90
90
  }
91
91
  function runRelayWebSocket(params) {
92
92
  const ws = params.connection;
93
- const relayState = {};
94
93
  let pending = Promise.resolve();
95
94
  return new Promise((resolve, reject) => {
96
95
  const cleanup = () => {
@@ -111,8 +110,7 @@ function runRelayWebSocket(params) {
111
110
  pending = pending.then(() => handleRelayFrame({
112
111
  ws,
113
112
  data,
114
- handleSlackMessage: params.handleSlackMessage,
115
- relayState,
113
+ acceptRelayEvent: params.acceptRelayEvent,
116
114
  setStatus: params.setStatus,
117
115
  setIdentity: params.setIdentity
118
116
  })).catch((err) => {
@@ -150,7 +148,6 @@ async function handleRelayFrame(params) {
150
148
  const frame = parseRelayFrame(params.data);
151
149
  const hello = extractRelayHello(frame);
152
150
  if (hello) {
153
- params.relayState.identity = hello.identity;
154
151
  params.setIdentity?.(hello.identity);
155
152
  params.setStatus?.({ relayIdentity: hello.identity ?? null });
156
153
  return;
@@ -163,11 +160,9 @@ async function handleRelayFrame(params) {
163
160
  lastInboundAt: now
164
161
  });
165
162
  params.setStatus?.({ relayRoute: event.route });
166
- await params.handleSlackMessage(event.message, {
167
- source: "message",
168
- wasMentioned: true,
169
- awaitDispatch: true,
170
- ...params.relayState.identity ? { relayIdentity: params.relayState.identity } : {}
163
+ await params.acceptRelayEvent({
164
+ deliveryId: event.deliveryId,
165
+ message: event.message
171
166
  });
172
167
  sendRelayAck(params.ws, event.deliveryId);
173
168
  }
@@ -1,6 +1,6 @@
1
- import { A as buildSlackBlocksFallbackText, I as SLACK_TEXT_LIMIT, O as markdownToSlackMrkdwnChunks, S as buildSlackNativeDataAccessibilityText, T as isSlackInvalidBlocksError, g as resolveSlackReplyBlocks, h as resolveSlackReplyBlockResolution, p as hasSlackReplyStructuredContent, w as hasSlackNativeDataBlock } from "./group-policy-85UWiriS.js";
2
- import { l as buildSlackNativeDataDeliveryPlan, r as sendMessageSlack, u as chunkSlackTextAtHardLimit } from "./send-DYp8ca-l.js";
3
- import { a as createSlackResponseUrlBudget, i as SlackResponseAlreadyReportedError } from "./provider-CmeoUiIM.js";
1
+ import { C as hasSlackNativeDataBlock, D as markdownToSlackMrkdwnChunks, F as SLACK_TEXT_LIMIT, f as hasSlackReplyStructuredContent, h as resolveSlackReplyBlocks, k as buildSlackBlocksFallbackText, m as resolveSlackReplyBlockResolution, w as isSlackInvalidBlocksError, x as buildSlackNativeDataAccessibilityText } from "./group-policy-Bw-65m3V.js";
2
+ import { d as chunkSlackTextAtHardLimit, r as sendMessageSlack, u as buildSlackNativeDataDeliveryPlan } from "./send-KuTDky7i.js";
3
+ import { a as createSlackResponseUrlBudget, i as SlackResponseAlreadyReportedError } from "./provider-B-HVL5ZE.js";
4
4
  import { createReplyReferencePlanner } from "openclaw/plugin-sdk/reply-reference";
5
5
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
6
6
  import { SILENT_REPLY_TOKEN, chunkMarkdownTextWithMode, isSilentReplyText } from "openclaw/plugin-sdk/reply-chunking";
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
- import { n as createSlackLookupClient } from "./client-WIPAS3Yr.js";
2
+ import { a as createSlackLookupClient } from "./probe-Borhn9PQ.js";
3
3
  import { t as collectSlackCursorPages } from "./cursor-pages-DSmTg0su.js";
4
4
  import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
5
5
  import { resolveDirectoryAllowlistEntries } from "openclaw/plugin-sdk/directory-runtime";
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
- import { n as createSlackLookupClient } from "./client-WIPAS3Yr.js";
2
+ import { a as createSlackLookupClient } from "./probe-Borhn9PQ.js";
3
3
  import { t as collectSlackCursorPages } from "./cursor-pages-DSmTg0su.js";
4
4
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
5
5
  import { resolveDirectoryAllowlistEntries } from "openclaw/plugin-sdk/directory-runtime";
@@ -1,5 +1,5 @@
1
1
  import "./target-parsing-N6lHogYZ.js";
2
- import "./client-WIPAS3Yr.js";
2
+ import "./probe-Borhn9PQ.js";
3
3
  import "./config-api-Df9a1B8C.js";
4
4
  import "openclaw/plugin-sdk/account-id";
5
5
  import { createActionGate as createActionGate$1, imageResultFromFile, jsonResult, readPositiveIntegerParam, readReactionParams, readStringParam, withNormalizedTimestamp } from "openclaw/plugin-sdk/channel-actions";
@@ -1,14 +1,14 @@
1
1
  import { t as registerSlackPluginHttpRoutes } from "./plugin-routes-CLp4obpN.js";
2
- import { a as resolveSlackAccount, f as resolveSlackAppToken, i as resolveDefaultSlackAccountId, n as listSlackAccountIds, p as resolveSlackBotToken, t as listEnabledSlackAccounts } from "./accounts-BOJJiHSr.js";
3
- import { n as resolveSlackGroupRequireMention, r as resolveSlackGroupToolPolicy } from "./group-policy-85UWiriS.js";
2
+ import { a as resolveSlackAccount, f as resolveSlackAppToken, i as resolveDefaultSlackAccountId, n as listSlackAccountIds, p as resolveSlackBotToken, t as listEnabledSlackAccounts } from "./accounts-DQEbYKh9.js";
3
+ import { n as resolveSlackGroupRequireMention, r as resolveSlackGroupToolPolicy } from "./group-policy-Bw-65m3V.js";
4
+ import { t as probeSlack } from "./probe-Borhn9PQ.js";
4
5
  import { r as setSlackRuntime } from "./runtime-JSVZSWAj.js";
5
- import { a as listSlackEmojis, c as pinSlackMessage, d as removeOwnSlackReactions, f as removeSlackReaction, h as unpinSlackMessage, i as getSlackMemberInfo, l as reactSlackMessage, m as sendSlackMessage, o as listSlackPins, r as editSlackMessage, s as listSlackReactions, t as deleteSlackMessage, u as readSlackMessages } from "./actions-BZiuSTIq.js";
6
- import { r as sendMessageSlack } from "./send-DYp8ca-l.js";
7
- import { t as probeSlack } from "./probe-CN0ssfLN.js";
8
- import { t as resolveSlackChannelAllowlist } from "./resolve-channels-Rfts6POK.js";
9
- import { t as resolveSlackUserAllowlist } from "./resolve-users-y6wAxR8E.js";
10
- import { t as monitorSlackProvider } from "./provider-CmeoUiIM.js";
11
- import { n as slackActionRuntime, t as handleSlackAction } from "./action-runtime-Cee2ih0s.js";
12
- import { n as listSlackDirectoryGroupsLive, r as listSlackDirectoryPeersLive } from "./directory-live-D_yZhjgp.js";
13
- import "./monitor-CalGciTs.js";
6
+ import { a as listSlackEmojis, c as pinSlackMessage, d as removeOwnSlackReactions, f as removeSlackReaction, h as unpinSlackMessage, i as getSlackMemberInfo, l as reactSlackMessage, m as sendSlackMessage, o as listSlackPins, r as editSlackMessage, s as listSlackReactions, t as deleteSlackMessage, u as readSlackMessages } from "./actions-CF0tUY5q.js";
7
+ import { r as sendMessageSlack } from "./send-KuTDky7i.js";
8
+ import { t as resolveSlackChannelAllowlist } from "./resolve-channels-KTc568SU.js";
9
+ import { t as resolveSlackUserAllowlist } from "./resolve-users-DeGJf1yp.js";
10
+ import { t as monitorSlackProvider } from "./provider-B-HVL5ZE.js";
11
+ import { n as slackActionRuntime, t as handleSlackAction } from "./action-runtime-DqkRwO3Z.js";
12
+ import { n as listSlackDirectoryGroupsLive, r as listSlackDirectoryPeersLive } from "./directory-live-CzUIB7th.js";
13
+ import "./monitor-CNFeF30h.js";
14
14
  export { deleteSlackMessage, editSlackMessage, getSlackMemberInfo, handleSlackAction, listEnabledSlackAccounts, listSlackAccountIds, listSlackDirectoryGroupsLive, listSlackDirectoryPeersLive, listSlackEmojis, listSlackPins, listSlackReactions, monitorSlackProvider, pinSlackMessage, probeSlack, reactSlackMessage, readSlackMessages, registerSlackPluginHttpRoutes, removeOwnSlackReactions, removeSlackReaction, resolveDefaultSlackAccountId, resolveSlackAccount, resolveSlackAppToken, resolveSlackBotToken, resolveSlackChannelAllowlist, resolveSlackGroupRequireMention, resolveSlackGroupToolPolicy, resolveSlackUserAllowlist, sendMessageSlack, sendSlackMessage, setSlackRuntime, slackActionRuntime, unpinSlackMessage };
@@ -1,5 +1,4 @@
1
- import { i as formatSlackError } from "./group-policy-85UWiriS.js";
2
- import { a as createSlackWebClient } from "./client-WIPAS3Yr.js";
1
+ import { c as createSlackWebClient, r as formatSlackError } from "./probe-Borhn9PQ.js";
3
2
  import { isRecord, normalizeOptionalString, normalizeStringEntries, sortUniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
4
3
  //#region extensions/slack/src/scopes.ts
5
4
  function collectScopes(value, into) {
@@ -73,6 +73,7 @@ function collectRuntimeConfigAssignments(params) {
73
73
  defaults: params.defaults,
74
74
  context: params.context,
75
75
  topLevelActive: surface.channelEnabled && (!surface.hasExplicitAccounts && baseMode === "relay" || surface.accounts.some(({ account, enabled }) => enabled && resolveAccountMode(account) === "relay" && !hasNestedAuthTokenOverride(account))),
76
+ topLevelInheritedAccountActive: ({ account, enabled }) => enabled && resolveAccountMode(account) === "relay" && !hasNestedAuthTokenOverride(account),
76
77
  topInactiveReason: "no enabled Slack relay-mode surface inherits this top-level relay authToken.",
77
78
  accountActive: ({ account, enabled }) => enabled && resolveAccountMode(account) === "relay",
78
79
  accountInactiveReason: "Slack account is disabled or not running in relay mode."
@@ -1,2 +1,2 @@
1
- import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./secret-contract-CMohXFWS.js";
1
+ import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./secret-contract-DxmvbxBF.js";
2
2
  export { channelSecrets, collectRuntimeConfigAssignments, secretTargetRegistryEntries };
@@ -1,10 +1,10 @@
1
- import { a as resolveSlackAccount, l as resolveSlackOperationToken, p as resolveSlackBotToken } from "./accounts-BOJJiHSr.js";
1
+ import { a as resolveSlackAccount, l as resolveSlackOperationToken } from "./accounts-DQEbYKh9.js";
2
2
  import { i as parseSlackTarget, t as canonicalizeSlackApiTargetId } from "./target-parsing-N6lHogYZ.js";
3
- import { B as truncateSlackText, C as createSlackNativeDataBaseTextConsumer, D as chunkSlackMrkdwnText, E as stripSlackNativeDataBlocks, F as SLACK_MESSAGE_TEXT_HARD_LIMIT, I as SLACK_TEXT_LIMIT, M as renderSlackBlockFallbackText, O as markdownToSlackMrkdwnChunks, Q as validateSlackBlocksArray, S as buildSlackNativeDataAccessibilityText, T as isSlackInvalidBlocksError, a as assertSlackDirectSendAllowed, j as buildSlackCompleteBlocksFallbackText, w as hasSlackNativeDataBlock, x as appendSlackNativeDataPlainTextFallback } from "./group-policy-85UWiriS.js";
3
+ import { A as buildSlackCompleteBlocksFallbackText, C as hasSlackNativeDataBlock, D as markdownToSlackMrkdwnChunks, E as chunkSlackMrkdwnText, F as SLACK_TEXT_LIMIT, P as SLACK_MESSAGE_TEXT_HARD_LIMIT, S as createSlackNativeDataBaseTextConsumer, T as stripSlackNativeDataBlocks, b as appendSlackNativeDataPlainTextFallback, et as validateSlackBlocksArray, i as assertSlackDirectSendAllowed, j as renderSlackBlockFallbackText, w as isSlackInvalidBlocksError, x as buildSlackNativeDataAccessibilityText, z as truncateSlackText } from "./group-policy-Bw-65m3V.js";
4
4
  import { n as resolveSlackThreadTsValue, t as normalizeSlackThreadTsCandidate } from "./thread-ts-DUGhaYKq.js";
5
- import { a as createSlackWebClient, c as getSlackWriteClient, i as createSlackTokenCacheKey } from "./client-WIPAS3Yr.js";
5
+ import { c as createSlackWebClient, d as getSlackWriteClient, s as createSlackTokenCacheKey } from "./probe-Borhn9PQ.js";
6
6
  import { t as getOptionalSlackRuntime } from "./runtime-JSVZSWAj.js";
7
- import { i as loadOutboundMediaFromUrl } from "./runtime-api-BGDyOt1D.js";
7
+ import { i as loadOutboundMediaFromUrl } from "./runtime-api-BFfNpzDe.js";
8
8
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
9
9
  import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
10
10
  import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
@@ -389,6 +389,7 @@ async function uploadSlackFile(params) {
389
389
  ...contentType ? { headers: { "Content-Type": contentType } } : {},
390
390
  body: new Uint8Array(buffer)
391
391
  },
392
+ timeoutMs: SLACK_UPLOAD_POST_TIMEOUT_MS,
392
393
  signal: uploadTimeoutSignal,
393
394
  requireHttps: uploadTransport.requireHttps,
394
395
  policy: uploadTransport.policy,
@@ -545,6 +546,22 @@ function resolvePostedMessageThreadTs(response) {
545
546
  const threadTs = response.message?.thread_ts;
546
547
  return typeof threadTs === "string" ? normalizeSlackThreadTsCandidate(threadTs) : void 0;
547
548
  }
549
+ async function updateMessageSlack(params) {
550
+ const account = resolveSlackAccount({
551
+ cfg: requireRuntimeConfig(params.cfg, "Slack update"),
552
+ accountId: params.accountId
553
+ });
554
+ await getSlackWriteClient(resolveToken({
555
+ accountId: account.accountId,
556
+ fallbackToken: account.botToken,
557
+ fallbackSource: account.botTokenSource
558
+ })).chat.update({
559
+ channel: params.channelId,
560
+ ts: params.messageTs,
561
+ text: truncateSlackText(params.text, SLACK_TEXT_LIMIT),
562
+ blocks: validateSlackBlocksArray(params.blocks)
563
+ });
564
+ }
548
565
  function createSlackSendReceipt(params) {
549
566
  return createMessageReceiptFromOutboundResults({
550
567
  results: params.platformMessageIds.map((messageId) => messageId.trim()).filter((messageId) => messageId && messageId !== "unknown" && messageId !== "suppressed").map((messageId) => {
@@ -560,12 +577,12 @@ function createSlackSendReceipt(params) {
560
577
  });
561
578
  }
562
579
  function resolveToken(params) {
563
- const explicit = resolveSlackBotToken(params.explicit);
580
+ const explicit = normalizeOptionalString(params.explicit);
564
581
  if (explicit) return explicit;
565
- const fallback = resolveSlackBotToken(params.fallbackToken);
582
+ const fallback = normalizeOptionalString(params.fallbackToken);
566
583
  if (!fallback) {
567
- logVerbose(`slack send: missing bot token for account=${params.accountId} explicit=${Boolean(params.explicit)} source=${params.fallbackSource ?? "unknown"}`);
568
- throw new Error(`Slack bot token missing for account "${params.accountId}" (set channels.slack.accounts.${params.accountId}.botToken or SLACK_BOT_TOKEN for default).`);
584
+ logVerbose(`slack send: missing write token for account=${params.accountId} explicit=${Boolean(params.explicit)} source=${params.fallbackSource ?? "unknown"}`);
585
+ throw new Error(`Slack write token missing for account "${params.accountId}".`);
569
586
  }
570
587
  return fallback;
571
588
  }
@@ -969,8 +986,8 @@ async function sendMessageSlack(to, message, opts) {
969
986
  const token = enterpriseDelivery ? SLACK_ENTERPRISE_LISTENER_QUEUE_CREDENTIAL : resolveToken({
970
987
  explicit: opts.token,
971
988
  accountId: account.accountId,
972
- fallbackToken: account.botToken,
973
- fallbackSource: account.botTokenSource
989
+ fallbackToken: resolveSlackOperationToken(account, "write"),
990
+ fallbackSource: account.identity === "user" ? account.userTokenSource : account.botTokenSource
974
991
  });
975
992
  const recipient = enterpriseDelivery ? parseEnterpriseEventRecipient(to) : parseRecipient(to);
976
993
  const queueKey = createSlackSendQueueKey({
@@ -1263,4 +1280,4 @@ async function sendMessageSlackQueuedInner(params) {
1263
1280
  };
1264
1281
  }
1265
1282
  //#endregion
1266
- export { clearSlackThreadParticipationCache as a, recordSlackThreadParticipation as c, setSlackDefaultSendIdentity as i, buildSlackNativeDataDeliveryPlan as l, resolveSlackDmChannelId as n, hasSlackThreadParticipation as o, sendMessageSlack as r, hasSlackThreadParticipationWithPersistence as s, reconcileSlackUnknownSend as t, chunkSlackTextAtHardLimit as u };
1283
+ export { updateMessageSlack as a, hasSlackThreadParticipationWithPersistence as c, chunkSlackTextAtHardLimit as d, setSlackDefaultSendIdentity as i, recordSlackThreadParticipation as l, resolveSlackDmChannelId as n, clearSlackThreadParticipationCache as o, sendMessageSlack as r, hasSlackThreadParticipation as s, reconcileSlackUnknownSend as t, buildSlackNativeDataDeliveryPlan as u };
@@ -0,0 +1,2 @@
1
+ import { a as updateMessageSlack, n as resolveSlackDmChannelId, r as sendMessageSlack, t as reconcileSlackUnknownSend } from "./send-KuTDky7i.js";
2
+ export { reconcileSlackUnknownSend, resolveSlackDmChannelId, sendMessageSlack, updateMessageSlack };
@@ -1,9 +1,8 @@
1
- import { a as resolveSlackAccount } from "./accounts-BOJJiHSr.js";
2
- import { t as inspectSlackAccount } from "./account-inspect-Di7ditqZ.js";
3
- import { t as isSlackPluginAccountConfigured } from "./account-configured-DzC407uv.js";
4
- import { hasConfiguredSecretInput } from "openclaw/plugin-sdk/secret-input";
1
+ import { t as inspectSlackAccount } from "./account-inspect-Bvbtu3iH.js";
2
+ import { t as isSlackPluginAccountConfigured } from "./account-configured-BwfXBo_F.js";
3
+ import { hasConfiguredSecretInput, normalizeSecretInputString } from "openclaw/plugin-sdk/secret-input";
5
4
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
6
- import { DEFAULT_ACCOUNT_ID, createAccountScopedAllowFromSection, createAccountScopedGroupAccessSection, createAllowlistSetupWizardProxy, createEnvPatchedAccountSetupAdapter, createLegacyCompatChannelDmPolicy, createSetupTranslator, createStandardChannelSetupStatus, defineTokenCredential, parseMentionOrPrefixedId, patchChannelConfigForAccount, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup-runtime";
5
+ import { DEFAULT_ACCOUNT_ID, createAccountScopedAllowFromSection, createAccountScopedGroupAccessSection, createAllowlistSetupWizardProxy, createLegacyCompatChannelDmPolicy, createPatchedAccountSetupAdapter, createSetupTranslator, createStandardChannelSetupStatus, defineTokenCredential, parseMentionOrPrefixedId, patchChannelConfigForAccount, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup-runtime";
7
6
  import { formatDocsLink } from "openclaw/plugin-sdk/setup-tools";
8
7
  import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
9
8
  //#region extensions/slack/src/setup-shared.ts
@@ -119,8 +118,13 @@ function setSlackChannelAllowlist(cfg, accountId, channelKeys) {
119
118
  }
120
119
  function isSlackSetupAccountConfigured(account) {
121
120
  if (account.config.mode === "relay") return isSlackPluginAccountConfigured(account);
121
+ const hasConfiguredUserToken = Boolean(account.userToken?.trim()) || hasConfiguredSecretInput(account.config.userToken);
122
122
  const hasConfiguredBotToken = Boolean(account.botToken?.trim()) || hasConfiguredSecretInput(account.config.botToken);
123
123
  const hasConfiguredAppToken = Boolean(account.appToken?.trim()) || hasConfiguredSecretInput(account.config.appToken);
124
+ if (account.identity === "user") {
125
+ const hasTransportCredential = account.config.mode === "http" ? hasConfiguredSecretInput(account.config.signingSecret) : hasConfiguredAppToken;
126
+ return hasConfiguredUserToken && hasTransportCredential;
127
+ }
124
128
  return hasConfiguredBotToken && hasConfiguredAppToken;
125
129
  }
126
130
  function describeSlackSetupAccount(account) {
@@ -129,7 +133,11 @@ function describeSlackSetupAccount(account) {
129
133
  configured: isSlackSetupAccountConfigured(account),
130
134
  extra: {
131
135
  botTokenSource: account.botTokenSource,
132
- appTokenSource: account.appTokenSource
136
+ appTokenSource: account.appTokenSource,
137
+ ...account.identity === "user" ? {
138
+ identity: account.identity,
139
+ userTokenSource: account.userTokenSource
140
+ } : {}
133
141
  }
134
142
  });
135
143
  }
@@ -144,8 +152,48 @@ function enableSlackAccount(cfg, accountId) {
144
152
  patch: { enabled: true }
145
153
  });
146
154
  }
155
+ function setSlackSetupIdentity(params) {
156
+ const next = patchChannelConfigForAccount({
157
+ cfg: params.cfg,
158
+ channel: SLACK_CHANNEL,
159
+ accountId: params.accountId,
160
+ patch: params.identity === "user" ? { identity: "user" } : {}
161
+ });
162
+ if (params.identity === "user") return next;
163
+ const slack = next.channels?.slack;
164
+ if (!slack) return next;
165
+ if (params.accountId === DEFAULT_ACCOUNT_ID) {
166
+ const nextSlack = { ...slack };
167
+ delete nextSlack.identity;
168
+ return {
169
+ ...next,
170
+ channels: {
171
+ ...next.channels,
172
+ slack: nextSlack
173
+ }
174
+ };
175
+ }
176
+ const account = slack.accounts?.[params.accountId];
177
+ if (!account) return next;
178
+ const nextAccount = { ...account };
179
+ if (slack.identity === "user") nextAccount.identity = "bot";
180
+ else delete nextAccount.identity;
181
+ return {
182
+ ...next,
183
+ channels: {
184
+ ...next.channels,
185
+ slack: {
186
+ ...slack,
187
+ accounts: {
188
+ ...slack.accounts,
189
+ [params.accountId]: nextAccount
190
+ }
191
+ }
192
+ }
193
+ };
194
+ }
147
195
  function hasSlackInteractiveRepliesConfig(cfg, accountId) {
148
- const capabilities = resolveSlackAccount({
196
+ const capabilities = inspectSlackAccount({
149
197
  cfg,
150
198
  accountId
151
199
  }).config.capabilities;
@@ -154,7 +202,7 @@ function hasSlackInteractiveRepliesConfig(cfg, accountId) {
154
202
  return "interactiveReplies" in capabilities;
155
203
  }
156
204
  function setSlackInteractiveReplies(cfg, accountId, interactiveReplies) {
157
- const capabilities = resolveSlackAccount({
205
+ const capabilities = inspectSlackAccount({
158
206
  cfg,
159
207
  accountId
160
208
  }).config.capabilities;
@@ -175,16 +223,21 @@ function createSlackTokenCredential(params) {
175
223
  providerHint: params.providerHint,
176
224
  credentialLabel: params.credentialLabel,
177
225
  preferredEnvVar: params.preferredEnvVar,
178
- envPrompt: `${params.preferredEnvVar} detected. Use env var?`,
226
+ envPrompt: params.preferredEnvVar ? `${params.preferredEnvVar} detected. Use env var?` : "Use the configured Slack credential?",
179
227
  keepPrompt: params.keepPrompt,
180
228
  inputPrompt: params.inputPrompt,
181
- allowEnv: ({ accountId }) => accountId === DEFAULT_ACCOUNT_ID,
182
- resolveAccount: ({ cfg, accountId }) => resolveSlackAccount({
229
+ allowEnv: ({ accountId }) => Boolean(params.preferredEnvVar) && accountId === DEFAULT_ACCOUNT_ID,
230
+ resolveAccount: ({ cfg, accountId }) => inspectSlackAccount({
183
231
  cfg,
184
232
  accountId
185
233
  }),
186
- resolvedValue: (account) => normalizeOptionalString(params.inputKey === "botToken" ? account.botToken : account.appToken),
187
- envValue: ({ accountId }) => accountId === DEFAULT_ACCOUNT_ID ? normalizeOptionalString(process.env[params.preferredEnvVar]) : void 0,
234
+ resolvedValue: (account) => {
235
+ if (params.inputKey === "botToken") return normalizeOptionalString(account.botToken);
236
+ if (params.inputKey === "appToken") return normalizeOptionalString(account.appToken);
237
+ if (params.inputKey === "userToken") return normalizeOptionalString(account.userToken);
238
+ return normalizeSecretInputString(account.config.signingSecret);
239
+ },
240
+ envValue: ({ accountId }) => params.preferredEnvVar && accountId === DEFAULT_ACCOUNT_ID ? normalizeOptionalString(process.env[params.preferredEnvVar]) : void 0,
188
241
  patchAccount: ({ cfg, accountId, mode, patch }) => mode === "env" ? enableSlackAccount(cfg, accountId) : patchChannelConfigForAccount({
189
242
  cfg,
190
243
  channel: SLACK_CHANNEL,
@@ -195,19 +248,64 @@ function createSlackTokenCredential(params) {
195
248
  }
196
249
  }),
197
250
  useEnv: { clearFields: [] },
198
- set: {}
251
+ set: {},
252
+ shouldPrompt: params.shouldPrompt
199
253
  });
200
254
  }
201
- const slackSetupAdapter = createEnvPatchedAccountSetupAdapter({
255
+ function hasSlackSetupCredentials(params) {
256
+ if (params.identity !== "user") {
257
+ const { input } = params;
258
+ return Boolean(input.botToken && input.appToken);
259
+ }
260
+ if (params.mode === "http") return Boolean(params.input.userToken && params.input.signingSecret);
261
+ return params.mode === "socket" && Boolean(params.input.userToken && params.input.appToken);
262
+ }
263
+ const slackSetupAdapterBase = createPatchedAccountSetupAdapter({
202
264
  channelKey: SLACK_CHANNEL,
203
- defaultAccountOnlyEnvError: "Slack env tokens can only be used for the default account.",
204
- missingCredentialError: "Slack requires --bot-token and --app-token (or --use-env).",
205
- hasCredentials: (input) => Boolean(input.botToken && input.appToken),
265
+ validateInput: ({ cfg, accountId, input }) => {
266
+ if (input.useEnv && accountId !== DEFAULT_ACCOUNT_ID) return "Slack env tokens can only be used for the default account.";
267
+ const account = inspectSlackAccount({
268
+ cfg,
269
+ accountId
270
+ });
271
+ const identity = input.identity ?? account.config.identity ?? "bot";
272
+ const mode = input.mode ?? account.config.mode ?? "socket";
273
+ if (identity === "user" && mode === "relay") return "Slack user identity setup supports mode \"socket\" or \"http\", not \"relay\".";
274
+ if (input.useEnv) return identity === "user" ? "Slack user identity setup does not support --use-env; configure userToken and the transport credential explicitly." : null;
275
+ if (hasSlackSetupCredentials({
276
+ input,
277
+ identity,
278
+ mode
279
+ })) return null;
280
+ if (identity === "user") return mode === "http" ? "Slack user identity requires --user-token and --signing-secret." : "Slack user identity requires --user-token and --app-token.";
281
+ return "Slack requires --bot-token and --app-token (or --use-env).";
282
+ },
206
283
  buildPatch: (input) => ({
284
+ ...input.identity ? { identity: input.identity } : {},
285
+ ...input.identity === "user" && input.mode ? { mode: input.mode } : {},
207
286
  ...input.botToken ? { botToken: input.botToken } : {},
208
- ...input.appToken ? { appToken: input.appToken } : {}
287
+ ...input.appToken ? { appToken: input.appToken } : {},
288
+ ...input.userToken ? { userToken: input.userToken } : {},
289
+ ...input.signingSecret ? { signingSecret: input.signingSecret } : {}
209
290
  })
210
291
  });
292
+ const slackSetupAdapter = {
293
+ ...slackSetupAdapterBase,
294
+ applyAccountConfig: ({ cfg, accountId, input }) => {
295
+ const identity = input.identity ?? inspectSlackAccount({
296
+ cfg,
297
+ accountId
298
+ }).config.identity;
299
+ return slackSetupAdapterBase.applyAccountConfig({
300
+ cfg,
301
+ accountId,
302
+ input: identity === "user" ? {
303
+ ...input,
304
+ identity
305
+ } : input
306
+ });
307
+ }
308
+ };
211
309
  function createSlackSetupWizardBase(handlers) {
212
310
  const slackDmPolicy = createLegacyCompatChannelDmPolicy({
213
311
  label: "Slack",
@@ -229,51 +327,118 @@ function createSlackSetupWizardBase(handlers) {
229
327
  accountId
230
328
  }).configured
231
329
  }),
232
- introNote: {
233
- title: t("wizard.slack.socketModeTokensTitle"),
234
- lines: buildSlackSetupLines(),
235
- shouldShow: ({ cfg, accountId }) => !isSlackSetupAccountConfigured(resolveSlackAccount({
236
- cfg,
237
- accountId
238
- }))
239
- },
240
330
  prepare: async ({ cfg, accountId, prompter }) => {
241
- if (isSlackSetupAccountConfigured(resolveSlackAccount({
331
+ const currentAccount = inspectSlackAccount({
242
332
  cfg,
243
333
  accountId
244
- }))) return;
245
- const manifest = buildSlackManifest();
246
- if (prompter.plain) await prompter.plain(manifest);
247
- else await prompter.note(manifest, "Slack manifest JSON");
334
+ });
335
+ if (currentAccount.configured && currentAccount.config.identity !== "user") return { cfg };
336
+ const identity = await prompter.select({
337
+ message: "How should OpenClaw appear in Slack?",
338
+ options: [{
339
+ value: "bot",
340
+ label: "Slack bot",
341
+ hint: "Post as the Slack app (default)"
342
+ }, {
343
+ value: "user",
344
+ label: "Slack user",
345
+ hint: "Post as the authorizing human"
346
+ }],
347
+ initialValue: currentAccount.config.identity ?? "bot"
348
+ });
349
+ const next = setSlackSetupIdentity({
350
+ cfg,
351
+ accountId,
352
+ identity
353
+ });
354
+ if (currentAccount.configured && identity === currentAccount.config.identity) return { cfg: next };
355
+ if (identity === "user") {
356
+ if (currentAccount.config.mode === "relay") throw new Error("Slack user identity setup supports mode \"socket\" or \"http\", not \"relay\".");
357
+ await prompter.note([
358
+ "Use a Slack user OAuth token with the User Token Scopes listed in the Slack docs.",
359
+ "Subscribe the companion app under 'Subscribe to events on behalf of users' using the documented user events.",
360
+ "Socket Mode needs an app-level token; HTTP mode needs the app signing secret.",
361
+ "No bot token or bot user is required.",
362
+ `Docs: ${formatDocsLink("/channels/slack#user-identity-post-as-a-real-person", "channels/slack")}`
363
+ ].join("\n"), "Slack user identity");
364
+ } else {
365
+ await prompter.note(buildSlackSetupLines().join("\n"), t("wizard.slack.socketModeTokensTitle"));
366
+ const manifest = buildSlackManifest();
367
+ if (prompter.plain) await prompter.plain(manifest);
368
+ else await prompter.note(manifest, "Slack manifest JSON");
369
+ }
370
+ return { cfg: next };
248
371
  },
249
372
  envShortcut: {
250
373
  prompt: t("wizard.slack.envPrompt"),
251
374
  preferredEnvVar: "SLACK_BOT_TOKEN",
252
- isAvailable: ({ cfg, accountId }) => accountId === DEFAULT_ACCOUNT_ID && Boolean(process.env.SLACK_BOT_TOKEN?.trim()) && Boolean(process.env.SLACK_APP_TOKEN?.trim()) && !isSlackSetupAccountConfigured(resolveSlackAccount({
375
+ isAvailable: ({ cfg, accountId }) => accountId === DEFAULT_ACCOUNT_ID && (inspectSlackAccount({
253
376
  cfg,
254
377
  accountId
255
- })),
378
+ }).config.identity ?? "bot") === "bot" && Boolean(process.env.SLACK_BOT_TOKEN?.trim()) && Boolean(process.env.SLACK_APP_TOKEN?.trim()) && !inspectSlackAccount({
379
+ cfg,
380
+ accountId
381
+ }).configured,
256
382
  apply: ({ cfg, accountId }) => enableSlackAccount(cfg, accountId)
257
383
  },
258
- credentials: [createSlackTokenCredential({
259
- inputKey: "botToken",
260
- providerHint: "slack-bot",
261
- credentialLabel: t("wizard.slack.botToken"),
262
- preferredEnvVar: "SLACK_BOT_TOKEN",
263
- keepPrompt: t("wizard.slack.botTokenKeep"),
264
- inputPrompt: t("wizard.slack.botTokenInput")
265
- }), createSlackTokenCredential({
266
- inputKey: "appToken",
267
- providerHint: "slack-app",
268
- credentialLabel: t("wizard.slack.appToken"),
269
- preferredEnvVar: "SLACK_APP_TOKEN",
270
- keepPrompt: t("wizard.slack.appTokenKeep"),
271
- inputPrompt: t("wizard.slack.appTokenInput")
272
- })],
384
+ credentials: [
385
+ createSlackTokenCredential({
386
+ inputKey: "botToken",
387
+ providerHint: "slack-bot",
388
+ credentialLabel: t("wizard.slack.botToken"),
389
+ preferredEnvVar: "SLACK_BOT_TOKEN",
390
+ keepPrompt: t("wizard.slack.botTokenKeep"),
391
+ inputPrompt: t("wizard.slack.botTokenInput"),
392
+ shouldPrompt: ({ cfg, accountId }) => (inspectSlackAccount({
393
+ cfg,
394
+ accountId
395
+ }).config.identity ?? "bot") === "bot"
396
+ }),
397
+ createSlackTokenCredential({
398
+ inputKey: "userToken",
399
+ providerHint: "slack-user",
400
+ credentialLabel: "Slack user OAuth token",
401
+ preferredEnvVar: "SLACK_USER_TOKEN",
402
+ keepPrompt: "Slack user OAuth token already configured. Keep it?",
403
+ inputPrompt: "Enter Slack user OAuth token",
404
+ shouldPrompt: ({ cfg, accountId }) => inspectSlackAccount({
405
+ cfg,
406
+ accountId
407
+ }).config.identity === "user"
408
+ }),
409
+ createSlackTokenCredential({
410
+ inputKey: "appToken",
411
+ providerHint: "slack-app",
412
+ credentialLabel: t("wizard.slack.appToken"),
413
+ preferredEnvVar: "SLACK_APP_TOKEN",
414
+ keepPrompt: t("wizard.slack.appTokenKeep"),
415
+ inputPrompt: t("wizard.slack.appTokenInput"),
416
+ shouldPrompt: ({ cfg, accountId }) => {
417
+ const account = inspectSlackAccount({
418
+ cfg,
419
+ accountId
420
+ });
421
+ return (account.config.identity ?? "bot") === "bot" || (account.config.mode ?? "socket") === "socket";
422
+ }
423
+ }),
424
+ createSlackTokenCredential({
425
+ inputKey: "signingSecret",
426
+ providerHint: "slack-signing-secret",
427
+ credentialLabel: "Slack signing secret",
428
+ keepPrompt: "Slack signing secret already configured. Keep it?",
429
+ inputPrompt: "Enter Slack signing secret",
430
+ shouldPrompt: ({ cfg, accountId }) => {
431
+ const account = inspectSlackAccount({
432
+ cfg,
433
+ accountId
434
+ });
435
+ return account.config.identity === "user" && account.config.mode === "http";
436
+ }
437
+ })
438
+ ],
273
439
  dmPolicy: slackDmPolicy,
274
440
  allowFrom: createAccountScopedAllowFromSection({
275
441
  channel: SLACK_CHANNEL,
276
- credentialInputKey: "botToken",
277
442
  helpTitle: t("wizard.slack.allowlistTitle"),
278
443
  helpLines: [
279
444
  t("wizard.slack.allowlistIntro"),
@@ -299,15 +464,15 @@ function createSlackSetupWizardBase(handlers) {
299
464
  channel: SLACK_CHANNEL,
300
465
  label: t("wizard.slack.channelsLabel"),
301
466
  placeholder: "#general, #private, C123",
302
- currentPolicy: ({ cfg, accountId }) => resolveSlackAccount({
467
+ currentPolicy: ({ cfg, accountId }) => inspectSlackAccount({
303
468
  cfg,
304
469
  accountId
305
470
  }).config.groupPolicy ?? "allowlist",
306
- currentEntries: ({ cfg, accountId }) => Object.entries(resolveSlackAccount({
471
+ currentEntries: ({ cfg, accountId }) => Object.entries(inspectSlackAccount({
307
472
  cfg,
308
473
  accountId
309
474
  }).config.channels ?? {}).filter(([, value]) => value?.enabled !== false).map(([key]) => key),
310
- updatePrompt: ({ cfg, accountId }) => Boolean(resolveSlackAccount({
475
+ updatePrompt: ({ cfg, accountId }) => Boolean(inspectSlackAccount({
311
476
  cfg,
312
477
  accountId
313
478
  }).config.channels),
@@ -1,2 +1,2 @@
1
- import { t as slackSetupPlugin } from "./channel.setup-C-mLz50O.js";
1
+ import { t as slackSetupPlugin } from "./channel.setup-CgkADtZg.js";
2
2
  export { slackSetupPlugin };