@openclaw/slack 2026.5.14-beta.1 → 2026.5.16-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.
Files changed (83) hide show
  1. package/dist/{action-runtime-gtC-RM3r.js → action-runtime-p39JLqwf.js} +4 -4
  2. package/dist/action-runtime.runtime-BzrPV3EA.js +2 -0
  3. package/dist/{media-B-nNpS2G.js → actions-BCRbHv1Q.js} +309 -3
  4. package/dist/{actions.runtime-DD6hfFCA.js → actions.runtime-CpywQR3D.js} +1 -1
  5. package/dist/api.js +16 -16
  6. package/dist/{approval-handler.runtime-DeYBuIaU.js → approval-handler.runtime-DXrdRbkT.js} +3 -4
  7. package/dist/{blocks-render-BdLueE_v.js → blocks-render-BAVfd6r0.js} +1 -1
  8. package/dist/{channel-CC04F-xs.js → channel-CVSopl66.js} +23 -27
  9. package/dist/channel-config-api.js +1 -1
  10. package/dist/channel-plugin-api.js +1 -1
  11. package/dist/{channel.setup-jzYjY634.js → channel.setup-DknBgufI.js} +3 -3
  12. package/dist/{client-8r7r7aZ3.js → client-C_IaJbi5.js} +20 -1
  13. package/dist/{config-schema-Bueih4yH.js → config-schema-CNRousxw.js} +1 -1
  14. package/dist/contract-api.js +4 -4
  15. package/dist/directory-contract-api.js +1 -1
  16. package/dist/{directory-live-CuaWaGnM.js → directory-live-CZPzpQZF.js} +1 -1
  17. package/dist/{doctor-contract-DCkS8eNN.js → doctor-contract-B8QIWMs1.js} +1 -1
  18. package/dist/doctor-contract-api.js +1 -1
  19. package/dist/http-routes-api.js +1 -1
  20. package/dist/inbound-contract-test-api.js +2 -2
  21. package/dist/interactive-replies-api.js +1 -1
  22. package/dist/{message-tool-api-B_bKUmP0.js → message-tool-api-C7gc7goF.js} +1 -1
  23. package/dist/message-tool-api.js +1 -1
  24. package/dist/{monitor-B3QB1ysK.js → monitor-CdVxsuHi.js} +3 -3
  25. package/dist/{outbound-adapter-DsAvCwpZ.js → outbound-adapter-CHm6e-0Q.js} +4 -5
  26. package/dist/outbound-payload-test-api.js +1 -1
  27. package/dist/{outbound-payload.test-harness-DM9ZdY2f.js → outbound-payload.test-harness-C0CW7_CE.js} +2 -2
  28. package/dist/{pipeline.runtime-D-YJZZaI.js → pipeline.runtime-CakcaQh9.js} +119 -143
  29. package/dist/{plugin-routes-Dt_jh9W8.js → plugin-routes-CRnfsTTX.js} +1 -1
  30. package/dist/{prepare-CXI8nHbJ.js → prepare-DSRUr44d.js} +223 -85
  31. package/dist/{prepare.test-helpers-BhFHtbz3.js → prepare.test-helpers-CU1qB54Q.js} +1 -1
  32. package/dist/{probe-D1wYA05H.js → probe-FL4sUJsH.js} +2 -2
  33. package/dist/{provider-Ut7IF0Mn.js → provider-bKg1hkf5.js} +158 -24
  34. package/dist/{replies-CzfjCaLG.js → replies-Fg1T3ZzU.js} +4 -4
  35. package/dist/reply-blocks-BFaJ_ejG.js +134 -0
  36. package/dist/{resolve-channels-BiVxSLVm.js → resolve-channels-B_eKaOkE.js} +2 -2
  37. package/dist/{resolve-users-CcpSlYw-.js → resolve-users-BzBAJwvq.js} +2 -2
  38. package/dist/{room-context-D0hGOp8m.js → room-context-Cd8jFpS-.js} +2 -2
  39. package/dist/{runtime-api-D8wiG9BS.js → runtime-api-B5HGOzX3.js} +2 -2
  40. package/dist/runtime-api.js +12 -12
  41. package/dist/runtime-setter-api.js +1 -1
  42. package/dist/{scopes-BTkB8PPE.js → scopes-Bvg_ZzqZ.js} +2 -2
  43. package/dist/secret-contract-api.js +1 -1
  44. package/dist/security-contract-api.js +1 -1
  45. package/dist/{send-ioky2Xpy.js → send-CxXFbqN1.js} +5 -6
  46. package/dist/send.runtime-BHCPpSj_.js +2 -0
  47. package/dist/send.runtime-CDG5AgU3.js +2 -0
  48. package/dist/{setup-core-DgLJ7dQY.js → setup-core-B7pou7oe.js} +23 -22
  49. package/dist/setup-plugin-api.js +1 -1
  50. package/dist/{setup-surface-B6w9gtds.js → setup-surface-D6LLzeRz.js} +16 -15
  51. package/dist/{shared-CSiHkaVO.js → shared-7Vi9j4aV.js} +7 -7
  52. package/dist/{slash-dispatch.runtime-DNr1EDON.js → slash-dispatch.runtime-Cg7uU92H.js} +1 -1
  53. package/dist/test-api.js +7 -7
  54. package/dist/thread-ts-As_dcNbD.js +52 -0
  55. package/package.json +5 -5
  56. package/dist/action-runtime.runtime-DbVd7_Na.js +0 -2
  57. package/dist/actions-Cqyj7oRr.js +0 -309
  58. package/dist/approval-auth-D3xf0sS6.js +0 -28
  59. package/dist/blocks-input-BJZ8vv03.js +0 -29
  60. package/dist/channel-api-BfBK89IN.js +0 -20
  61. package/dist/exec-approvals-BLn4Zx7V.js +0 -58
  62. package/dist/group-policy-utF2iWnE.js +0 -41
  63. package/dist/mrkdwn-18IzcEAY.js +0 -6
  64. package/dist/reply-blocks-DWoZrUll.js +0 -14
  65. package/dist/send.runtime-5Kl3Wzbf.js +0 -2
  66. package/dist/send.runtime-DoifekaA.js +0 -2
  67. package/dist/thread-ts-o-QBwB3k.js +0 -24
  68. /package/dist/{accounts.runtime-CkfFIisb.js → accounts.runtime-BhbEu1ZK.js} +0 -0
  69. /package/dist/{allow-list-T7ZDpUsF.js → allow-list-nwXs_eCP.js} +0 -0
  70. /package/dist/{config-api-B48Z4H47.js → config-api-CmgE_ORg.js} +0 -0
  71. /package/dist/{directory-config-BKKNBkCq.js → directory-config-CMvFiswf.js} +0 -0
  72. /package/dist/{errors-BrtayXHa.js → errors-C_sW0Zgl.js} +0 -0
  73. /package/dist/{interactive-replies-CawNPL-h.js → interactive-replies-BSg5hXhj.js} +0 -0
  74. /package/dist/{magic-string.es-BLAi6qQC.js → magic-string.es-9lw4MGoF.js} +0 -0
  75. /package/dist/{registry-BdfKYina.js → registry-D2cWOLZV.js} +0 -0
  76. /package/dist/{resolve-allowlist-common-rhfyDyWi.js → resolve-allowlist-common-DLub2I2i.js} +0 -0
  77. /package/dist/{runtime--VlVtTPu.js → runtime-DQxkf7k2.js} +0 -0
  78. /package/dist/{secret-contract-BurGIyhv.js → secret-contract-0TL3L5Kb.js} +0 -0
  79. /package/dist/{security-audit-DvOpSaZM.js → security-audit-BJzADAw3.js} +0 -0
  80. /package/dist/{slash-commands.runtime-DRkNgIQ2.js → slash-commands.runtime-bcDwsGnu.js} +0 -0
  81. /package/dist/{slash-plugin-commands.runtime-Dj5h8hmv.js → slash-plugin-commands.runtime-DBHGUSj2.js} +0 -0
  82. /package/dist/{slash-skill-commands.runtime-B-_KAk0C.js → slash-skill-commands.runtime-rrY2hXvN.js} +0 -0
  83. /package/dist/{streaming-compat-C6rySwiD.js → streaming-compat-eu5Rj5gj.js} +0 -0
@@ -2,7 +2,7 @@ import { a as resolveSlackAccount } from "./accounts-yk5K3wQU.js";
2
2
  import { t as inspectSlackAccount } from "./account-inspect-BJyQLSkN.js";
3
3
  import { hasConfiguredSecretInput } from "openclaw/plugin-sdk/secret-input";
4
4
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
5
- import { DEFAULT_ACCOUNT_ID, createAccountScopedAllowFromSection, createAccountScopedGroupAccessSection, createAllowlistSetupWizardProxy, createEnvPatchedAccountSetupAdapter, createLegacyCompatChannelDmPolicy, createStandardChannelSetupStatus, parseMentionOrPrefixedId, patchChannelConfigForAccount, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup-runtime";
5
+ import { DEFAULT_ACCOUNT_ID, createAccountScopedAllowFromSection, createAccountScopedGroupAccessSection, createAllowlistSetupWizardProxy, createEnvPatchedAccountSetupAdapter, createLegacyCompatChannelDmPolicy, createSetupTranslator, createStandardChannelSetupStatus, parseMentionOrPrefixedId, patchChannelConfigForAccount, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup-runtime";
6
6
  import { formatDocsLink } from "openclaw/plugin-sdk/setup-tools";
7
7
  import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
8
8
  //#region extensions/slack/src/setup-shared.ts
@@ -113,6 +113,7 @@ function describeSlackSetupAccount(account) {
113
113
  }
114
114
  //#endregion
115
115
  //#region extensions/slack/src/setup-core.ts
116
+ const t = createSetupTranslator();
116
117
  function enableSlackAccount(cfg, accountId) {
117
118
  return patchChannelConfigForAccount({
118
119
  cfg,
@@ -201,10 +202,10 @@ function createSlackSetupWizardBase(handlers) {
201
202
  channel: SLACK_CHANNEL,
202
203
  status: createStandardChannelSetupStatus({
203
204
  channelLabel: "Slack",
204
- configuredLabel: "configured",
205
- unconfiguredLabel: "needs tokens",
206
- configuredHint: "configured",
207
- unconfiguredHint: "needs tokens",
205
+ configuredLabel: t("wizard.channels.statusConfigured"),
206
+ unconfiguredLabel: t("wizard.channels.statusNeedsTokens"),
207
+ configuredHint: t("wizard.channels.statusConfigured"),
208
+ unconfiguredHint: t("wizard.channels.statusNeedsTokens"),
208
209
  configuredScore: 2,
209
210
  unconfiguredScore: 1,
210
211
  resolveConfigured: ({ cfg, accountId }) => inspectSlackAccount({
@@ -213,7 +214,7 @@ function createSlackSetupWizardBase(handlers) {
213
214
  }).configured
214
215
  }),
215
216
  introNote: {
216
- title: "Slack socket mode tokens",
217
+ title: t("wizard.slack.socketModeTokensTitle"),
217
218
  lines: buildSlackSetupLines(),
218
219
  shouldShow: ({ cfg, accountId }) => !isSlackSetupAccountConfigured(resolveSlackAccount({
219
220
  cfg,
@@ -230,7 +231,7 @@ function createSlackSetupWizardBase(handlers) {
230
231
  else await prompter.note(manifest, "Slack manifest JSON");
231
232
  },
232
233
  envShortcut: {
233
- prompt: "SLACK_BOT_TOKEN + SLACK_APP_TOKEN detected. Use env vars?",
234
+ prompt: t("wizard.slack.envPrompt"),
234
235
  preferredEnvVar: "SLACK_BOT_TOKEN",
235
236
  isAvailable: ({ cfg, accountId }) => accountId === DEFAULT_ACCOUNT_ID && Boolean(process.env.SLACK_BOT_TOKEN?.trim()) && Boolean(process.env.SLACK_APP_TOKEN?.trim()) && !isSlackSetupAccountConfigured(resolveSlackAccount({
236
237
  cfg,
@@ -241,34 +242,34 @@ function createSlackSetupWizardBase(handlers) {
241
242
  credentials: [createSlackTokenCredential({
242
243
  inputKey: "botToken",
243
244
  providerHint: "slack-bot",
244
- credentialLabel: "Slack bot token",
245
+ credentialLabel: t("wizard.slack.botToken"),
245
246
  preferredEnvVar: "SLACK_BOT_TOKEN",
246
- keepPrompt: "Slack bot token already configured. Keep it?",
247
- inputPrompt: "Enter Slack bot token (xoxb-...)"
247
+ keepPrompt: t("wizard.slack.botTokenKeep"),
248
+ inputPrompt: t("wizard.slack.botTokenInput")
248
249
  }), createSlackTokenCredential({
249
250
  inputKey: "appToken",
250
251
  providerHint: "slack-app",
251
- credentialLabel: "Slack app token",
252
+ credentialLabel: t("wizard.slack.appToken"),
252
253
  preferredEnvVar: "SLACK_APP_TOKEN",
253
- keepPrompt: "Slack app token already configured. Keep it?",
254
- inputPrompt: "Enter Slack app token (xapp-...)"
254
+ keepPrompt: t("wizard.slack.appTokenKeep"),
255
+ inputPrompt: t("wizard.slack.appTokenInput")
255
256
  })],
256
257
  dmPolicy: slackDmPolicy,
257
258
  allowFrom: createAccountScopedAllowFromSection({
258
259
  channel: SLACK_CHANNEL,
259
260
  credentialInputKey: "botToken",
260
- helpTitle: "Slack allowlist",
261
+ helpTitle: t("wizard.slack.allowlistTitle"),
261
262
  helpLines: [
262
- "Allowlist Slack DMs by username (we resolve to user ids).",
263
- "Examples:",
263
+ t("wizard.slack.allowlistIntro"),
264
+ t("wizard.slack.examples"),
264
265
  "- U12345678",
265
266
  "- @alice",
266
- "Multiple entries: comma-separated.",
267
- `Docs: ${formatDocsLink("/slack", "slack")}`
267
+ t("wizard.slack.multipleEntries"),
268
+ t("wizard.channels.docs", { link: formatDocsLink("/slack", "slack") })
268
269
  ],
269
- message: "Slack allowFrom (usernames or ids)",
270
+ message: t("wizard.slack.allowFromPrompt"),
270
271
  placeholder: "@alice, U12345678",
271
- invalidWithoutCredentialNote: "Slack token missing; use user ids (or mention form) only.",
272
+ invalidWithoutCredentialNote: t("wizard.slack.allowFromInvalidWithoutToken"),
272
273
  parseId: (value) => parseMentionOrPrefixedId({
273
274
  value,
274
275
  mentionPattern: /^<@([A-Z0-9]+)>$/i,
@@ -280,7 +281,7 @@ function createSlackSetupWizardBase(handlers) {
280
281
  }),
281
282
  groupAccess: createAccountScopedGroupAccessSection({
282
283
  channel: SLACK_CHANNEL,
283
- label: "Slack channels",
284
+ label: t("wizard.slack.channelsLabel"),
284
285
  placeholder: "#general, #private, C123",
285
286
  currentPolicy: ({ cfg, accountId }) => resolveSlackAccount({
286
287
  cfg,
@@ -302,7 +303,7 @@ function createSlackSetupWizardBase(handlers) {
302
303
  if (hasSlackInteractiveRepliesConfig(cfg, accountId)) return;
303
304
  if (options?.quickstartDefaults) return { cfg: setSlackInteractiveReplies(cfg, accountId, true) };
304
305
  return { cfg: setSlackInteractiveReplies(cfg, accountId, await prompter.confirm({
305
- message: "Enable Slack interactive replies (buttons/selects) for agent responses?",
306
+ message: t("wizard.slack.interactiveRepliesPrompt"),
306
307
  initialValue: true
307
308
  })) };
308
309
  },
@@ -1,2 +1,2 @@
1
- import { t as slackSetupPlugin } from "./channel.setup-jzYjY634.js";
1
+ import { t as slackSetupPlugin } from "./channel.setup-DknBgufI.js";
2
2
  export { slackSetupPlugin };
@@ -1,12 +1,13 @@
1
1
  import { a as resolveSlackAccount, i as resolveDefaultSlackAccountId, o as resolveSlackAccountAllowFrom } from "./accounts-yk5K3wQU.js";
2
- import "./shared-CSiHkaVO.js";
3
- import { i as SLACK_CHANNEL, t as createSlackSetupWizardBase } from "./setup-core-DgLJ7dQY.js";
4
- import { t as resolveSlackChannelAllowlist } from "./resolve-channels-BiVxSLVm.js";
5
- import { t as resolveSlackUserAllowlist } from "./resolve-users-CcpSlYw-.js";
2
+ import "./shared-7Vi9j4aV.js";
3
+ import { i as SLACK_CHANNEL, t as createSlackSetupWizardBase } from "./setup-core-B7pou7oe.js";
4
+ import { t as resolveSlackChannelAllowlist } from "./resolve-channels-B_eKaOkE.js";
5
+ import { t as resolveSlackUserAllowlist } from "./resolve-users-BzBAJwvq.js";
6
6
  import { adaptScopedAccountAccessor } from "openclaw/plugin-sdk/channel-config-helpers";
7
- import { noteChannelLookupFailure, noteChannelLookupSummary, parseMentionOrPrefixedId, promptLegacyChannelAllowFromForAccount, resolveEntriesWithOptionalToken } from "openclaw/plugin-sdk/setup-runtime";
7
+ import { createSetupTranslator, noteChannelLookupFailure, noteChannelLookupSummary, parseMentionOrPrefixedId, promptLegacyChannelAllowFromForAccount, resolveEntriesWithOptionalToken } from "openclaw/plugin-sdk/setup-runtime";
8
8
  import { formatDocsLink } from "openclaw/plugin-sdk/setup-tools";
9
9
  //#region extensions/slack/src/setup-surface.ts
10
+ const t = createSetupTranslator();
10
11
  async function resolveSlackAllowFromEntries(params) {
11
12
  return await resolveEntriesWithOptionalToken({
12
13
  token: params.token,
@@ -46,19 +47,19 @@ async function promptSlackAllowFrom(params) {
46
47
  accountId: account.accountId
47
48
  }) ?? [],
48
49
  resolveToken: (account) => account.userToken ?? account.botToken ?? "",
49
- noteTitle: "Slack allowlist",
50
+ noteTitle: t("wizard.slack.allowlistTitle"),
50
51
  noteLines: [
51
- "Allowlist Slack DMs by username (we resolve to user ids).",
52
- "Examples:",
52
+ t("wizard.slack.allowlistIntro"),
53
+ t("wizard.slack.examples"),
53
54
  "- U12345678",
54
55
  "- @alice",
55
- "Multiple entries: comma-separated.",
56
- `Docs: ${formatDocsLink("/slack", "slack")}`
56
+ t("wizard.slack.multipleEntries"),
57
+ t("wizard.channels.docs", { link: formatDocsLink("/slack", "slack") })
57
58
  ],
58
- message: "Slack allowFrom (usernames or ids)",
59
+ message: t("wizard.slack.allowFromPrompt"),
59
60
  placeholder: "@alice, U12345678",
60
61
  parseId,
61
- invalidWithoutTokenNote: "Slack token missing; use user ids (or mention form) only.",
62
+ invalidWithoutTokenNote: t("wizard.slack.allowFromInvalidWithoutToken"),
62
63
  resolveEntries: async ({ token, entries }) => (await resolveSlackUserAllowlist({
63
64
  token,
64
65
  entries
@@ -94,9 +95,9 @@ async function resolveSlackGroupAllowlist(params) {
94
95
  keys = [...resolvedKeys, ...unresolved.map((entry) => entry.trim()).filter(Boolean)];
95
96
  await noteChannelLookupSummary({
96
97
  prompter: params.prompter,
97
- label: "Slack channels",
98
+ label: t("wizard.slack.channelsLabel"),
98
99
  resolvedSections: [{
99
- title: "Resolved",
100
+ title: t("wizard.channels.resolvedTitle"),
100
101
  values: resolvedKeys
101
102
  }],
102
103
  unresolved
@@ -104,7 +105,7 @@ async function resolveSlackGroupAllowlist(params) {
104
105
  } catch (error) {
105
106
  await noteChannelLookupFailure({
106
107
  prompter: params.prompter,
107
- label: "Slack channels",
108
+ label: t("wizard.slack.channelsLabel"),
108
109
  error
109
110
  });
110
111
  }
@@ -1,11 +1,11 @@
1
1
  import { a as resolveSlackAccount, c as resolveSlackConfigAccessorAccount, i as resolveDefaultSlackAccountId, n as listSlackAccountIds, o as resolveSlackAccountAllowFrom, s as resolveSlackAccountDmPolicy } from "./accounts-yk5K3wQU.js";
2
2
  import { t as inspectSlackAccount } from "./account-inspect-BJyQLSkN.js";
3
- import { n as isSlackInteractiveRepliesEnabled } from "./interactive-replies-CawNPL-h.js";
4
- import { r as getChatChannelMeta } from "./channel-api-BfBK89IN.js";
5
- import { i as SLACK_CHANNEL } from "./setup-core-DgLJ7dQY.js";
6
- import { t as SlackChannelConfigSchema } from "./config-schema-Bueih4yH.js";
7
- import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-DCkS8eNN.js";
8
- import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-BurGIyhv.js";
3
+ import { n as isSlackInteractiveRepliesEnabled } from "./interactive-replies-BSg5hXhj.js";
4
+ import { f as getChatChannelMeta } from "./client-C_IaJbi5.js";
5
+ import { i as SLACK_CHANNEL } from "./setup-core-B7pou7oe.js";
6
+ import { t as SlackChannelConfigSchema } from "./config-schema-CNRousxw.js";
7
+ import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-B8QIWMs1.js";
8
+ import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-0TL3L5Kb.js";
9
9
  import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter, createScopedDmSecurityResolver } from "openclaw/plugin-sdk/channel-config-helpers";
10
10
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
11
11
  import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
@@ -45,7 +45,7 @@ const collectSlackSecurityWarnings = createOpenProviderConfiguredRouteWarningCol
45
45
  remediation: "Set channels.slack.groupPolicy=\"allowlist\" and configure channels.slack.channels"
46
46
  }
47
47
  });
48
- const loadSlackSecurityAuditModule = createLazyRuntimeModule(() => import("./security-audit-DvOpSaZM.js").then((n) => n.n));
48
+ const loadSlackSecurityAuditModule = createLazyRuntimeModule(() => import("./security-audit-BJzADAw3.js").then((n) => n.n));
49
49
  const slackSecurityAdapter = {
50
50
  resolveDmPolicy: resolveSlackDmPolicy,
51
51
  collectWarnings: collectSlackSecurityWarnings,
@@ -1,4 +1,4 @@
1
- import { r as deliverSlackSlashReplies$1 } from "./replies-CzfjCaLG.js";
1
+ import { r as deliverSlackSlashReplies$1 } from "./replies-Fg1T3ZzU.js";
2
2
  import { resolveAgentRoute as resolveAgentRoute$1 } from "openclaw/plugin-sdk/routing";
3
3
  import { resolveMarkdownTableMode as resolveMarkdownTableMode$1 } from "openclaw/plugin-sdk/markdown-table-runtime";
4
4
  import { recordInboundSessionMetaSafe as recordInboundSessionMetaSafe$1, resolveConversationLabel as resolveConversationLabel$1 } from "openclaw/plugin-sdk/conversation-runtime";
package/dist/test-api.js CHANGED
@@ -1,8 +1,8 @@
1
- import { a as createSlackActions, t as slackPlugin } from "./channel-CC04F-xs.js";
2
- import { n as setSlackRuntime } from "./runtime--VlVtTPu.js";
3
- import { t as sendMessageSlack } from "./send-ioky2Xpy.js";
4
- import { t as prepareSlackMessage } from "./prepare-CXI8nHbJ.js";
5
- import { t as createInboundSlackTestContext } from "./prepare.test-helpers-BhFHtbz3.js";
6
- import { t as createSlackOutboundPayloadHarness } from "./outbound-payload.test-harness-DM9ZdY2f.js";
7
- import { n as slackOutbound } from "./outbound-adapter-DsAvCwpZ.js";
1
+ import { a as createSlackActions, t as slackPlugin } from "./channel-CVSopl66.js";
2
+ import { n as setSlackRuntime } from "./runtime-DQxkf7k2.js";
3
+ import { t as sendMessageSlack } from "./send-CxXFbqN1.js";
4
+ import { t as prepareSlackMessage } from "./prepare-DSRUr44d.js";
5
+ import { t as createInboundSlackTestContext } from "./prepare.test-helpers-CU1qB54Q.js";
6
+ import { t as createSlackOutboundPayloadHarness } from "./outbound-payload.test-harness-C0CW7_CE.js";
7
+ import { n as slackOutbound } from "./outbound-adapter-CHm6e-0Q.js";
8
8
  export { createInboundSlackTestContext, createSlackActions, createSlackOutboundPayloadHarness, prepareSlackMessage, sendMessageSlack, setSlackRuntime, slackOutbound, slackPlugin };
@@ -0,0 +1,52 @@
1
+ import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
2
+ //#region extensions/slack/src/truncate.ts
3
+ function truncateSlackText(value, max) {
4
+ const trimmed = value.trim();
5
+ if (trimmed.length <= max) return trimmed;
6
+ if (max <= 1) return trimmed.slice(0, max);
7
+ return `${trimmed.slice(0, max - 1)}…`;
8
+ }
9
+ //#endregion
10
+ //#region extensions/slack/src/limits.ts
11
+ const SLACK_TEXT_LIMIT = 8e3;
12
+ //#endregion
13
+ //#region extensions/slack/src/blocks-input.ts
14
+ const SLACK_MAX_BLOCKS = 50;
15
+ function parseBlocksJson(raw) {
16
+ try {
17
+ return JSON.parse(raw);
18
+ } catch {
19
+ throw new Error("blocks must be valid JSON");
20
+ }
21
+ }
22
+ function assertBlocksArray(raw) {
23
+ if (!Array.isArray(raw)) throw new Error("blocks must be an array");
24
+ if (raw.length === 0) throw new Error("blocks must contain at least one block");
25
+ if (raw.length > 50) throw new Error(`blocks cannot exceed 50 items`);
26
+ for (const block of raw) {
27
+ if (!block || typeof block !== "object" || Array.isArray(block)) throw new Error("each block must be an object");
28
+ const type = block.type;
29
+ if (typeof type !== "string" || type.trim().length === 0) throw new Error("each block must include a non-empty string type");
30
+ }
31
+ }
32
+ function validateSlackBlocksArray(raw) {
33
+ assertBlocksArray(raw);
34
+ return raw;
35
+ }
36
+ function parseSlackBlocksInput(raw) {
37
+ if (raw == null) return;
38
+ return validateSlackBlocksArray(typeof raw === "string" ? parseBlocksJson(raw) : raw);
39
+ }
40
+ //#endregion
41
+ //#region extensions/slack/src/thread-ts.ts
42
+ const SLACK_THREAD_TS_PATTERN = /^\d+\.\d+$/;
43
+ function normalizeSlackThreadTsCandidate(value) {
44
+ if (typeof value !== "string") return;
45
+ const normalized = normalizeOptionalString(value);
46
+ return normalized && SLACK_THREAD_TS_PATTERN.test(normalized) ? normalized : void 0;
47
+ }
48
+ function resolveSlackThreadTsValue(params) {
49
+ return normalizeSlackThreadTsCandidate(params.replyToId) ?? normalizeSlackThreadTsCandidate(params.threadId);
50
+ }
51
+ //#endregion
52
+ export { validateSlackBlocksArray as a, parseSlackBlocksInput as i, resolveSlackThreadTsValue as n, SLACK_TEXT_LIMIT as o, SLACK_MAX_BLOCKS as r, truncateSlackText as s, normalizeSlackThreadTsCandidate as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/slack",
3
- "version": "2026.5.14-beta.1",
3
+ "version": "2026.5.16-beta.1",
4
4
  "description": "OpenClaw Slack channel plugin",
5
5
  "repository": {
6
6
  "type": "git",
@@ -10,7 +10,7 @@
10
10
  "dependencies": {
11
11
  "@slack/bolt": "4.7.2",
12
12
  "@slack/types": "2.21.1",
13
- "@slack/web-api": "7.15.2",
13
+ "@slack/web-api": "7.16.0",
14
14
  "https-proxy-agent": "9.0.0",
15
15
  "typebox": "1.1.38",
16
16
  "zod": "4.4.3"
@@ -20,7 +20,7 @@
20
20
  "openclaw": "workspace:*"
21
21
  },
22
22
  "peerDependencies": {
23
- "openclaw": ">=2026.5.14-beta.1"
23
+ "openclaw": ">=2026.5.16-beta.1"
24
24
  },
25
25
  "peerDependenciesMeta": {
26
26
  "openclaw": {
@@ -64,10 +64,10 @@
64
64
  "minHostVersion": ">=2026.5.12-beta.1"
65
65
  },
66
66
  "compat": {
67
- "pluginApi": ">=2026.5.14-beta.1"
67
+ "pluginApi": ">=2026.5.16-beta.1"
68
68
  },
69
69
  "build": {
70
- "openclawVersion": "2026.5.14-beta.1",
70
+ "openclawVersion": "2026.5.16-beta.1",
71
71
  "bundledDist": false
72
72
  },
73
73
  "release": {
@@ -1,2 +0,0 @@
1
- import { t as handleSlackAction } from "./action-runtime-gtC-RM3r.js";
2
- export { handleSlackAction };
@@ -1,309 +0,0 @@
1
- import { a as resolveSlackAccount, d as resolveSlackBotToken } from "./accounts-yk5K3wQU.js";
2
- import { i as truncateSlackText, r as SLACK_TEXT_LIMIT } from "./thread-ts-o-QBwB3k.js";
3
- import { a as getSlackWriteClient, r as createSlackWebClient } from "./client-8r7r7aZ3.js";
4
- import { r as validateSlackBlocksArray } from "./blocks-input-BJZ8vv03.js";
5
- import { c as buildSlackBlocksFallbackText, t as sendMessageSlack } from "./send-ioky2Xpy.js";
6
- import { n as resolveSlackMedia } from "./media-B-nNpS2G.js";
7
- import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
8
- import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
9
- import { z } from "zod";
10
- //#region extensions/slack/src/edit-text.ts
11
- function buildSlackEditTextPayload(content, blocks) {
12
- const trimmedContent = content.trim();
13
- if (trimmedContent) return trimmedContent;
14
- if (blocks?.length) return truncateSlackText(buildSlackBlocksFallbackText(blocks), SLACK_TEXT_LIMIT);
15
- return " ";
16
- }
17
- //#endregion
18
- //#region extensions/slack/src/actions.ts
19
- function resolveToken(explicit, accountId, cfg) {
20
- if (explicit?.trim()) {
21
- const token = resolveSlackBotToken(explicit);
22
- if (token) return token;
23
- }
24
- if (!cfg) throw new Error("Slack actions requires a resolved runtime config. Load and resolve config at the command or gateway boundary, then pass cfg through the runtime path.");
25
- const account = resolveSlackAccount({
26
- cfg: requireRuntimeConfig(cfg, "Slack actions"),
27
- accountId
28
- });
29
- const token = resolveSlackBotToken(account.botToken ?? void 0);
30
- if (!token) {
31
- logVerbose(`slack actions: missing bot token for account=${account.accountId} explicit=${Boolean(explicit)} source=${account.botTokenSource ?? "unknown"}`);
32
- throw new Error("SLACK_BOT_TOKEN or channels.slack.botToken is required for Slack actions");
33
- }
34
- return token;
35
- }
36
- function normalizeEmoji(raw) {
37
- const trimmed = raw.trim();
38
- if (!trimmed) throw new Error("Emoji is required for Slack reactions");
39
- return trimmed.replace(/^:+|:+$/g, "");
40
- }
41
- const SLACK_TIMESTAMP_RE = /^\d+(?:\.\d+)?$/;
42
- const ISO_8601_TIMESTAMP_SCHEMA = z.iso.datetime({ offset: true });
43
- function formatEpochSeconds(milliseconds) {
44
- const seconds = milliseconds / 1e3;
45
- if (Number.isInteger(seconds)) return String(seconds);
46
- return seconds.toFixed(3).replace(/0+$/, "").replace(/\.$/, "");
47
- }
48
- function normalizeSlackReadTimestamp(raw, field) {
49
- const trimmed = raw?.trim();
50
- if (!trimmed) return;
51
- if (SLACK_TIMESTAMP_RE.test(trimmed)) return trimmed;
52
- if (!ISO_8601_TIMESTAMP_SCHEMA.safeParse(trimmed).success) throw new Error(`Invalid Slack read ${field} timestamp "${trimmed}": expected a Slack timestamp or ISO-8601 date string`);
53
- const parsed = Date.parse(trimmed);
54
- if (!Number.isFinite(parsed)) throw new Error(`Invalid Slack read ${field} timestamp "${trimmed}": expected a Slack timestamp or ISO-8601 date string`);
55
- return formatEpochSeconds(parsed);
56
- }
57
- function hasSlackPlatformError(err, code) {
58
- if (!err || typeof err !== "object") return false;
59
- const data = err.data;
60
- if (!data || typeof data !== "object") return false;
61
- return data.error === code;
62
- }
63
- async function getClient(opts = {}, mode = "read") {
64
- if (opts.client) return opts.client;
65
- const token = resolveToken(opts.token, opts.accountId, opts.cfg);
66
- return mode === "write" ? getSlackWriteClient(token) : createSlackWebClient(token);
67
- }
68
- async function resolveBotUserId(client) {
69
- const auth = await client.auth.test();
70
- if (!auth?.user_id) throw new Error("Failed to resolve Slack bot user id");
71
- return auth.user_id;
72
- }
73
- async function reactSlackMessage(channelId, messageId, emoji, opts = {}) {
74
- const client = await getClient(opts, "write");
75
- try {
76
- await client.reactions.add({
77
- channel: channelId,
78
- timestamp: messageId,
79
- name: normalizeEmoji(emoji)
80
- });
81
- } catch (err) {
82
- if (hasSlackPlatformError(err, "already_reacted")) return;
83
- throw err;
84
- }
85
- }
86
- async function removeSlackReaction(channelId, messageId, emoji, opts = {}) {
87
- const client = await getClient(opts, "write");
88
- try {
89
- await client.reactions.remove({
90
- channel: channelId,
91
- timestamp: messageId,
92
- name: normalizeEmoji(emoji)
93
- });
94
- } catch (err) {
95
- if (hasSlackPlatformError(err, "no_reaction")) return;
96
- throw err;
97
- }
98
- }
99
- async function removeOwnSlackReactions(channelId, messageId, opts = {}) {
100
- const client = await getClient(opts, "write");
101
- const userId = await resolveBotUserId(client);
102
- const reactions = await listSlackReactions(channelId, messageId, { client });
103
- const toRemove = /* @__PURE__ */ new Set();
104
- for (const reaction of reactions ?? []) {
105
- const name = reaction?.name;
106
- if (!name) continue;
107
- if ((reaction?.users ?? []).includes(userId)) toRemove.add(name);
108
- }
109
- if (toRemove.size === 0) return [];
110
- await Promise.all(Array.from(toRemove, (name) => removeSlackReaction(channelId, messageId, name, {
111
- ...opts,
112
- client
113
- })));
114
- return Array.from(toRemove);
115
- }
116
- async function listSlackReactions(channelId, messageId, opts = {}) {
117
- return (await (await getClient(opts)).reactions.get({
118
- channel: channelId,
119
- timestamp: messageId,
120
- full: true
121
- })).message?.reactions ?? [];
122
- }
123
- async function sendSlackMessage(to, content, opts) {
124
- return await sendMessageSlack(to, content, {
125
- accountId: opts.accountId,
126
- cfg: opts.cfg,
127
- token: opts.token,
128
- mediaUrl: opts.mediaUrl,
129
- mediaAccess: opts.mediaAccess,
130
- mediaLocalRoots: opts.mediaLocalRoots,
131
- mediaReadFile: opts.mediaReadFile,
132
- client: opts.client,
133
- threadTs: opts.threadTs,
134
- replyBroadcast: opts.replyBroadcast,
135
- ...opts.uploadFileName ? { uploadFileName: opts.uploadFileName } : {},
136
- ...opts.uploadTitle ? { uploadTitle: opts.uploadTitle } : {},
137
- blocks: opts.blocks
138
- });
139
- }
140
- async function editSlackMessage(channelId, messageId, content, opts = {}) {
141
- const client = await getClient(opts, "write");
142
- const blocks = opts.blocks == null ? void 0 : validateSlackBlocksArray(opts.blocks);
143
- await client.chat.update({
144
- channel: channelId,
145
- ts: messageId,
146
- text: buildSlackEditTextPayload(content, blocks),
147
- ...blocks ? { blocks } : {}
148
- });
149
- }
150
- async function deleteSlackMessage(channelId, messageId, opts = {}) {
151
- await (await getClient(opts, "write")).chat.delete({
152
- channel: channelId,
153
- ts: messageId
154
- });
155
- }
156
- async function readSlackMessages(channelId, opts = {}) {
157
- const exactMessageId = opts.messageId?.trim();
158
- const readLimit = exactMessageId ? 1 : opts.limit;
159
- const exactBounds = exactMessageId ? {
160
- inclusive: true,
161
- latest: exactMessageId,
162
- oldest: void 0
163
- } : {
164
- latest: normalizeSlackReadTimestamp(opts.before, "before"),
165
- oldest: normalizeSlackReadTimestamp(opts.after, "after")
166
- };
167
- const client = await getClient(opts);
168
- if (opts.threadId) {
169
- const result = await client.conversations.replies({
170
- channel: channelId,
171
- ts: opts.threadId,
172
- limit: readLimit,
173
- ...exactBounds
174
- });
175
- return {
176
- messages: (result.messages ?? []).filter((message) => {
177
- if (exactMessageId) return message.ts === exactMessageId;
178
- return message.ts !== opts.threadId;
179
- }),
180
- hasMore: exactMessageId ? false : Boolean(result.has_more)
181
- };
182
- }
183
- const result = await client.conversations.history({
184
- channel: channelId,
185
- limit: readLimit,
186
- ...exactBounds
187
- });
188
- return {
189
- messages: (result.messages ?? []).filter((message) => !exactMessageId || message.ts === exactMessageId),
190
- hasMore: exactMessageId ? false : Boolean(result.has_more)
191
- };
192
- }
193
- async function getSlackMemberInfo(userId, opts = {}) {
194
- return await (await getClient(opts)).users.info({ user: userId });
195
- }
196
- async function listSlackEmojis(opts = {}) {
197
- return await (await getClient(opts)).emoji.list();
198
- }
199
- async function pinSlackMessage(channelId, messageId, opts = {}) {
200
- await (await getClient(opts, "write")).pins.add({
201
- channel: channelId,
202
- timestamp: messageId
203
- });
204
- }
205
- async function unpinSlackMessage(channelId, messageId, opts = {}) {
206
- await (await getClient(opts, "write")).pins.remove({
207
- channel: channelId,
208
- timestamp: messageId
209
- });
210
- }
211
- async function listSlackPins(channelId, opts = {}) {
212
- return (await (await getClient(opts)).pins.list({ channel: channelId })).items ?? [];
213
- }
214
- function normalizeSlackScopeValue(value) {
215
- const trimmed = value?.trim();
216
- return trimmed ? trimmed : void 0;
217
- }
218
- function collectSlackDirectShareChannelIds(file) {
219
- const ids = /* @__PURE__ */ new Set();
220
- for (const group of [
221
- file.channels,
222
- file.groups,
223
- file.ims
224
- ]) {
225
- if (!Array.isArray(group)) continue;
226
- for (const entry of group) {
227
- if (typeof entry !== "string") continue;
228
- const normalized = normalizeSlackScopeValue(entry);
229
- if (normalized) ids.add(normalized);
230
- }
231
- }
232
- return ids;
233
- }
234
- function collectSlackShareMaps(file) {
235
- if (!file.shares || typeof file.shares !== "object" || Array.isArray(file.shares)) return [];
236
- const shares = file.shares;
237
- return [shares.public, shares.private].filter((value) => Boolean(value) && typeof value === "object" && !Array.isArray(value));
238
- }
239
- function collectSlackSharedChannelIds(file) {
240
- const ids = /* @__PURE__ */ new Set();
241
- for (const shareMap of collectSlackShareMaps(file)) for (const channelId of Object.keys(shareMap)) {
242
- const normalized = normalizeSlackScopeValue(channelId);
243
- if (normalized) ids.add(normalized);
244
- }
245
- return ids;
246
- }
247
- function collectSlackThreadShares(file, channelId) {
248
- const matches = [];
249
- for (const shareMap of collectSlackShareMaps(file)) {
250
- const rawEntries = shareMap[channelId];
251
- if (!Array.isArray(rawEntries)) continue;
252
- for (const rawEntry of rawEntries) {
253
- if (!rawEntry || typeof rawEntry !== "object" || Array.isArray(rawEntry)) continue;
254
- const entry = rawEntry;
255
- const ts = typeof entry.ts === "string" ? normalizeSlackScopeValue(entry.ts) : void 0;
256
- const threadTs = typeof entry.thread_ts === "string" ? normalizeSlackScopeValue(entry.thread_ts) : void 0;
257
- matches.push({
258
- channelId,
259
- ts,
260
- threadTs
261
- });
262
- }
263
- }
264
- return matches;
265
- }
266
- function hasSlackScopeMismatch(params) {
267
- const channelId = normalizeSlackScopeValue(params.channelId);
268
- if (!channelId) return false;
269
- const threadId = normalizeSlackScopeValue(params.threadId);
270
- const directIds = collectSlackDirectShareChannelIds(params.file);
271
- const sharedIds = collectSlackSharedChannelIds(params.file);
272
- const hasChannelEvidence = directIds.size > 0 || sharedIds.size > 0;
273
- const inChannel = directIds.has(channelId) || sharedIds.has(channelId);
274
- if (hasChannelEvidence && !inChannel) return true;
275
- if (!threadId) return false;
276
- const threadShares = collectSlackThreadShares(params.file, channelId);
277
- if (threadShares.length === 0) return false;
278
- const threadEvidence = threadShares.filter((entry) => entry.threadTs || entry.ts);
279
- if (threadEvidence.length === 0) return false;
280
- return !threadEvidence.some((entry) => entry.threadTs === threadId || entry.ts === threadId);
281
- }
282
- /**
283
- * Downloads a Slack file by ID and saves it to the local media store.
284
- * Fetches a fresh download URL via files.info to avoid using stale private URLs.
285
- * Returns null when the file cannot be found or downloaded.
286
- */
287
- async function downloadSlackFile(fileId, opts) {
288
- const token = resolveToken(opts.token, opts.accountId, opts.cfg);
289
- const file = (await (await getClient(opts)).files.info({ file: fileId })).file;
290
- if (!file?.url_private_download && !file?.url_private) return null;
291
- if (hasSlackScopeMismatch({
292
- file,
293
- channelId: opts.channelId,
294
- threadId: opts.threadId
295
- })) return null;
296
- return (await resolveSlackMedia({
297
- files: [{
298
- id: file.id,
299
- name: file.name,
300
- mimetype: file.mimetype,
301
- url_private: file.url_private,
302
- url_private_download: file.url_private_download
303
- }],
304
- token,
305
- maxBytes: opts.maxBytes
306
- }))?.[0] ?? null;
307
- }
308
- //#endregion
309
- export { listSlackEmojis as a, pinSlackMessage as c, removeOwnSlackReactions as d, removeSlackReaction as f, buildSlackEditTextPayload as h, getSlackMemberInfo as i, reactSlackMessage as l, unpinSlackMessage as m, downloadSlackFile as n, listSlackPins as o, sendSlackMessage as p, editSlackMessage as r, listSlackReactions as s, deleteSlackMessage as t, readSlackMessages as u };