@openclaw/slack 2026.10.2 → 2026.10.5-beta.2

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 (116) hide show
  1. package/dist/.setup/account-configured-zcR9TJJN.mjs +35 -0
  2. package/dist/.setup/{account-inspect-Cs-7DXXW.mjs → account-inspect-D58VVDjk.mjs} +15 -35
  3. package/dist/.setup/{accounts-CDgkV7Cm.mjs → accounts-BMg9YLIv.mjs} +44 -53
  4. package/dist/.setup/{action-runtime-DJ1daRAZ.mjs → action-runtime-BiRZNsIG.mjs} +20 -22
  5. package/dist/.setup/action-runtime.runtime-C5xceJoS.mjs +2 -0
  6. package/dist/.setup/{actions-DDoAJnrH.mjs → actions-KGKwTAKO.mjs} +34 -43
  7. package/dist/.setup/{approval-handler.runtime-BcE_shWc.mjs → approval-handler.runtime-DYrsG2Ox.mjs} +44 -70
  8. package/dist/.setup/{approval-message-updates-EgKGmFXx.mjs → approval-message-updates-CwdDew9i.mjs} +1 -1
  9. package/dist/.setup/{channel-DgKSu8Iv.mjs → channel-C7MY-Hhg.mjs} +138 -97
  10. package/dist/.setup/{channel-type-B9zYYzBU.mjs → channel-type-NjX2SwvS.mjs} +3 -3
  11. package/dist/.setup/{channel.setup-BYIlwbQ7.mjs → channel.setup-BFpQowO3.mjs} +7 -14
  12. package/dist/.setup/{directory-config-B_by7zrc.mjs → directory-config-BEDZPfDn.mjs} +1 -1
  13. package/dist/.setup/{directory-live-C48wazJt.mjs → directory-live-FipfeCwt.mjs} +33 -36
  14. package/dist/.setup/{message-tool-api-CcjLPN3v.mjs → message-tool-api-C7im5ETh.mjs} +2 -2
  15. package/dist/.setup/{monitor-BuYBDmm7.mjs → monitor-BnN2px0N.mjs} +609 -801
  16. package/dist/.setup/{outbound-adapter-BZFkK-mw.mjs → outbound-adapter-4HdGq-8r.mjs} +4 -4
  17. package/dist/.setup/{pipeline.runtime-CIepKmZt.mjs → pipeline.runtime-ByPbC6MN.mjs} +287 -365
  18. package/dist/.setup/{policy-KKTqEiDv.mjs → policy-BaY9_eh1.mjs} +2 -2
  19. package/dist/.setup/{probe-BVlJ3dp0.mjs → probe-CyX52GtD.mjs} +54 -61
  20. package/dist/.setup/{relay-source-CC3h6M7y.mjs → relay-source-CVfH-fBO.mjs} +28 -45
  21. package/dist/.setup/{replies-DHbuthIR.mjs → replies-WmfwvQxc.mjs} +38 -49
  22. package/dist/.setup/{reply-blocks-CKnO4BSG.mjs → reply-blocks-rqHQ_3pr.mjs} +87 -138
  23. package/dist/.setup/{resolve-channels-HR0TgArR.mjs → resolve-channels-B96cgprw.mjs} +17 -41
  24. package/dist/.setup/{resolve-users-BNYBhF0q.mjs → resolve-users-Xz9aPdns.mjs} +22 -58
  25. package/dist/.setup/{scopes-DrDbyUH2.mjs → scopes-aMcMHhXk.mjs} +1 -1
  26. package/dist/.setup/{send-CgPI3Zj8.mjs → send-CLmsR42r.mjs} +157 -284
  27. package/dist/.setup/{session-status-D46GHwOV.mjs → session-status-CcXe10zN.mjs} +181 -238
  28. package/dist/.setup/{setup-plugin-api-ZrHs0N4U.mjs → setup-plugin-api-D92P5p51.mjs} +1 -1
  29. package/dist/.setup/{setup-surface-83lxvE2y.mjs → setup-surface-368jx6Uc.mjs} +6 -6
  30. package/dist/.setup/{shared-VtmYNj-v.mjs → shared-CtprVh_G.mjs} +5 -5
  31. package/dist/.setup/{slash-dispatch.runtime-gBj_uaLM.mjs → slash-dispatch.runtime-Dzwj6TPI.mjs} +1 -1
  32. package/dist/account-inspect-api.js +1 -1
  33. package/dist/api.js +12 -12
  34. package/dist/channel-plugin-api.js +1 -1
  35. package/dist/configured-state.js +6 -13
  36. package/dist/directory-contract-api.js +1 -1
  37. package/dist/message-tool-api.js +1 -1
  38. package/dist/runtime-api.js +10 -10
  39. package/dist/setup-entry.js +1 -1
  40. package/dist/setup-plugin-api.js +1 -1
  41. package/node_modules/@slack/bolt/node_modules/@slack/socket-mode/dist/package.json +4 -4
  42. package/node_modules/@slack/bolt/node_modules/@slack/socket-mode/dist/src/SlackWebSocket.d.ts.map +1 -1
  43. package/node_modules/@slack/bolt/node_modules/@slack/socket-mode/dist/src/SlackWebSocket.js +9 -17
  44. package/node_modules/@slack/bolt/node_modules/@slack/socket-mode/dist/src/SlackWebSocket.js.map +1 -1
  45. package/node_modules/@slack/bolt/node_modules/@slack/socket-mode/package.json +4 -4
  46. package/node_modules/@slack/bolt/node_modules/@types/node/README.md +2 -2
  47. package/node_modules/@slack/bolt/node_modules/@types/node/crypto.d.ts +2 -2
  48. package/node_modules/@slack/bolt/node_modules/@types/node/dgram.d.ts +1 -1
  49. package/node_modules/@slack/bolt/node_modules/@types/node/package.json +2 -17
  50. package/node_modules/@slack/bolt/node_modules/@types/node/zlib.d.ts +6 -0
  51. package/node_modules/@slack/types/dist/block-kit/block-elements.d.ts +1 -1
  52. package/node_modules/@slack/types/dist/block-kit/block-elements.d.ts.map +1 -1
  53. package/node_modules/@slack/types/dist/block-kit/blocks.d.ts +79 -4
  54. package/node_modules/@slack/types/dist/block-kit/blocks.d.ts.map +1 -1
  55. package/node_modules/@slack/types/dist/block-kit/composition-objects.d.ts +17 -0
  56. package/node_modules/@slack/types/dist/block-kit/composition-objects.d.ts.map +1 -1
  57. package/node_modules/@slack/types/package.json +1 -1
  58. package/node_modules/@slack/web-api/dist/methods.d.ts +49 -2
  59. package/node_modules/@slack/web-api/dist/methods.d.ts.map +1 -1
  60. package/node_modules/@slack/web-api/dist/methods.js +47 -0
  61. package/node_modules/@slack/web-api/dist/methods.js.map +1 -1
  62. package/node_modules/@slack/web-api/dist/types/request/agents.d.ts +186 -0
  63. package/node_modules/@slack/web-api/dist/types/request/agents.d.ts.map +1 -1
  64. package/node_modules/@slack/web-api/dist/types/request/index.d.ts +1 -1
  65. package/node_modules/@slack/web-api/dist/types/request/index.d.ts.map +1 -1
  66. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsArchiveResponse.d.ts +9 -0
  67. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsArchiveResponse.d.ts.map +1 -0
  68. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsArchiveResponse.js +11 -0
  69. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsArchiveResponse.js.map +1 -0
  70. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsCreateResponse.d.ts +10 -0
  71. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsCreateResponse.d.ts.map +1 -0
  72. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsCreateResponse.js +11 -0
  73. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsCreateResponse.js.map +1 -0
  74. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsGetCanvasResponse.d.ts +29 -0
  75. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsGetCanvasResponse.d.ts.map +1 -0
  76. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsGetCanvasResponse.js +11 -0
  77. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsGetCanvasResponse.js.map +1 -0
  78. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsListViewsResponse.d.ts +18 -0
  79. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsListViewsResponse.d.ts.map +1 -0
  80. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsListViewsResponse.js +11 -0
  81. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsListViewsResponse.js.map +1 -0
  82. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsRemoveViewResponse.d.ts +11 -0
  83. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsRemoveViewResponse.d.ts.map +1 -0
  84. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsRemoveViewResponse.js +11 -0
  85. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsRemoveViewResponse.js.map +1 -0
  86. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCanvasContentResponse.d.ts +11 -0
  87. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCanvasContentResponse.d.ts.map +1 -0
  88. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCanvasContentResponse.js +11 -0
  89. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCanvasContentResponse.js.map +1 -0
  90. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCommandsResponse.d.ts +11 -0
  91. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCommandsResponse.d.ts.map +1 -0
  92. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCommandsResponse.js +11 -0
  93. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetCommandsResponse.js.map +1 -0
  94. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetPropertiesResponse.d.ts +10 -0
  95. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetPropertiesResponse.d.ts.map +1 -0
  96. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetPropertiesResponse.js +11 -0
  97. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetPropertiesResponse.js.map +1 -0
  98. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetViewResponse.d.ts +15 -0
  99. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetViewResponse.d.ts.map +1 -0
  100. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetViewResponse.js +11 -0
  101. package/node_modules/@slack/web-api/dist/types/response/AgentsConversationsSetViewResponse.js.map +1 -0
  102. package/node_modules/@slack/web-api/dist/types/response/ConversationsInfoResponse.d.ts +31 -0
  103. package/node_modules/@slack/web-api/dist/types/response/ConversationsInfoResponse.d.ts.map +1 -1
  104. package/node_modules/@slack/web-api/dist/types/response/index.d.ts +9 -0
  105. package/node_modules/@slack/web-api/dist/types/response/index.d.ts.map +1 -1
  106. package/node_modules/@slack/web-api/node_modules/@types/node/README.md +2 -2
  107. package/node_modules/@slack/web-api/node_modules/@types/node/crypto.d.ts +2 -2
  108. package/node_modules/@slack/web-api/node_modules/@types/node/dgram.d.ts +1 -1
  109. package/node_modules/@slack/web-api/node_modules/@types/node/package.json +2 -17
  110. package/node_modules/@slack/web-api/node_modules/@types/node/zlib.d.ts +6 -0
  111. package/node_modules/@slack/web-api/package.json +2 -2
  112. package/openclaw.plugin.json +0 -3
  113. package/package.json +6 -14
  114. package/dist/.setup/account-configured-sUohAxZr.mjs +0 -33
  115. package/dist/.setup/action-runtime.runtime-CdWL2mLC.mjs +0 -2
  116. package/dist/control-ui/2f4b1e827be6b68ced2ea0d8b7da8529a4eafbe72be27ee37e1064bdd530ec10/index.js +0 -1
@@ -0,0 +1,35 @@
1
+ import { hasConfiguredAccountValue } from "openclaw/plugin-sdk/account-resolution";
2
+ import { hasConfiguredSecretInput } from "openclaw/plugin-sdk/secret-input";
3
+ //#region extensions/slack/src/account-configured.ts
4
+ function hasSlackAccountCredentials(params) {
5
+ if (!params.identityTokenConfigured) return false;
6
+ const mode = params.config.mode ?? "socket";
7
+ if (mode === "http") return hasConfiguredAccountValue(params.config.signingSecret);
8
+ if (mode === "relay") {
9
+ const relay = params.config.relay;
10
+ return hasConfiguredAccountValue(relay?.url) && hasConfiguredAccountValue(relay?.authToken) && hasConfiguredAccountValue(relay?.gatewayId);
11
+ }
12
+ return params.appTokenConfigured;
13
+ }
14
+ function hasSlackAccountCredentialsFromConfig(config, env) {
15
+ const userIdentity = config?.postAs === "user";
16
+ return hasSlackAccountCredentials({
17
+ config: config ?? {},
18
+ identityTokenConfigured: hasConfiguredAccountValue(userIdentity ? config?.userToken : config?.botToken) || hasConfiguredAccountValue(userIdentity ? env.SLACK_USER_TOKEN : env.SLACK_BOT_TOKEN),
19
+ appTokenConfigured: hasConfiguredAccountValue(config?.appToken) || hasConfiguredAccountValue(env.SLACK_APP_TOKEN)
20
+ });
21
+ }
22
+ function createSlackAccountConfiguredChecker(allowSecretRefs) {
23
+ return (account) => {
24
+ const hasToken = (key) => Boolean(account[key]?.trim()) || allowSecretRefs && account.config.mode !== "relay" && hasConfiguredSecretInput(account.config[key]);
25
+ return hasSlackAccountCredentials({
26
+ config: account.config,
27
+ identityTokenConfigured: hasToken(account.identity === "user" ? "userToken" : "botToken"),
28
+ appTokenConfigured: hasToken("appToken")
29
+ });
30
+ };
31
+ }
32
+ const isSlackPluginAccountConfigured = createSlackAccountConfiguredChecker(false);
33
+ const isSlackSetupAccountConfigured = createSlackAccountConfiguredChecker(true);
34
+ //#endregion
35
+ export { isSlackSetupAccountConfigured as i, hasSlackAccountCredentialsFromConfig as n, isSlackPluginAccountConfigured as r, hasSlackAccountCredentials as t };
@@ -1,31 +1,24 @@
1
- import { t as hasSlackAccountCredentials } from "./account-configured-sUohAxZr.mjs";
2
- import { a as mergeSlackAccountConfig, o as resolveDefaultSlackAccountId } from "./accounts-CDgkV7Cm.mjs";
1
+ import { t as hasSlackAccountCredentials } from "./account-configured-zcR9TJJN.mjs";
2
+ import { a as mergeSlackAccountConfig, g as buildSlackAccountSurfaceFields, o as resolveDefaultSlackAccountId } from "./accounts-BMg9YLIv.mjs";
3
3
  import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
4
4
  import { hasConfiguredSecretInput, normalizeSecretInputString } from "openclaw/plugin-sdk/secret-input";
5
5
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
6
6
  //#region extensions/slack/src/account-inspect.ts
7
- function inspectSlackToken(value) {
7
+ function inspectSlackToken(value, envToken) {
8
8
  const token = normalizeSecretInputString(value);
9
- if (token) return {
9
+ if (token || hasConfiguredSecretInput(value)) return {
10
10
  token,
11
11
  source: "config",
12
- status: "available"
13
- };
14
- if (hasConfiguredSecretInput(value)) return {
15
- source: "config",
16
- status: "configured_unavailable"
17
- };
18
- return {
19
- source: "none",
20
- status: "missing"
12
+ status: token ? "available" : "configured_unavailable"
21
13
  };
22
- }
23
- function resolveInspectedSlackToken(configured, envToken) {
24
- return configured.status === "missing" && envToken ? {
14
+ return envToken ? {
25
15
  token: envToken,
26
16
  source: "env",
27
17
  status: "available"
28
- } : configured;
18
+ } : {
19
+ source: "none",
20
+ status: "missing"
21
+ };
29
22
  }
30
23
  function inspectSlackAccount(params) {
31
24
  const accountId = normalizeAccountId(params.accountId ?? resolveDefaultSlackAccountId(params.cfg));
@@ -36,16 +29,13 @@ function inspectSlackAccount(params) {
36
29
  const identity = merged.postAs ?? "bot";
37
30
  const isHttpMode = mode === "http";
38
31
  const isSocketMode = mode === "socket";
39
- const configBot = inspectSlackToken(merged.botToken);
40
- const configApp = inspectSlackToken(isSocketMode ? merged.appToken : void 0);
41
- const configSigningSecret = inspectSlackToken(merged.signingSecret);
42
- const configUser = inspectSlackToken(merged.userToken);
43
32
  const envBot = allowEnv ? normalizeSecretInputString(params.envBotToken ?? process.env.SLACK_BOT_TOKEN) : void 0;
44
33
  const envApp = allowEnv && isSocketMode ? normalizeSecretInputString(params.envAppToken ?? process.env.SLACK_APP_TOKEN) : void 0;
45
34
  const envUser = allowEnv ? normalizeSecretInputString(params.envUserToken ?? process.env.SLACK_USER_TOKEN) : void 0;
46
- const botCredential = resolveInspectedSlackToken(configBot, envBot);
47
- const appCredential = resolveInspectedSlackToken(configApp, envApp);
48
- const userCredential = resolveInspectedSlackToken(configUser, envUser);
35
+ const botCredential = inspectSlackToken(merged.botToken, envBot);
36
+ const appCredential = inspectSlackToken(isSocketMode ? merged.appToken : void 0, envApp);
37
+ const configSigningSecret = inspectSlackToken(merged.signingSecret);
38
+ const userCredential = inspectSlackToken(merged.userToken, envUser);
49
39
  return {
50
40
  accountId,
51
41
  enabled,
@@ -70,17 +60,7 @@ function inspectSlackAccount(params) {
70
60
  appTokenConfigured: appCredential.status !== "missing"
71
61
  }),
72
62
  config: merged,
73
- groupPolicy: merged.groupPolicy,
74
- textChunkLimit: merged.textChunkLimit,
75
- mediaMaxMb: merged.mediaMaxMb,
76
- reactionNotifications: merged.reactionNotifications,
77
- reactionAllowlist: merged.reactionAllowlist,
78
- replyToMode: merged.replyToMode,
79
- replyToModeByChatType: merged.replyToModeByChatType,
80
- actions: merged.actions,
81
- slashCommand: merged.slashCommand,
82
- dm: merged.dm,
83
- channels: merged.channels
63
+ ...buildSlackAccountSurfaceFields(merged)
84
64
  };
85
65
  }
86
66
  //#endregion
@@ -1,11 +1,28 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.mjs";
2
- import { t as hasSlackAccountCredentials } from "./account-configured-sUohAxZr.mjs";
3
- import { DEFAULT_ACCOUNT_ID, createAccountListHelpers, hasConfiguredAccountValue, normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
2
+ import { n as hasSlackAccountCredentialsFromConfig } from "./account-configured-zcR9TJJN.mjs";
3
+ import { DEFAULT_ACCOUNT_ID, createAccountListHelpers, normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
4
4
  import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
5
5
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
6
6
  import { mapAllowFromEntries, normalizeChannelDmPolicy } from "openclaw/plugin-sdk/channel-config-helpers";
7
7
  import { resolveAccountEntry } from "openclaw/plugin-sdk/routing";
8
8
  import { normalizeChatType } from "openclaw/plugin-sdk/account-core";
9
+ //#region extensions/slack/src/account-surface-fields.ts
10
+ function buildSlackAccountSurfaceFields(config) {
11
+ return {
12
+ groupPolicy: config.groupPolicy,
13
+ textChunkLimit: config.textChunkLimit,
14
+ mediaMaxMb: config.mediaMaxMb,
15
+ reactionNotifications: config.reactionNotifications,
16
+ reactionAllowlist: config.reactionAllowlist,
17
+ replyToMode: config.replyToMode,
18
+ replyToModeByChatType: config.replyToModeByChatType,
19
+ actions: config.actions,
20
+ slashCommand: config.slashCommand,
21
+ dm: config.dm,
22
+ channels: config.channels
23
+ };
24
+ }
25
+ //#endregion
9
26
  //#region extensions/slack/src/token.ts
10
27
  function formatSlackBotTokenIdentityWarning(params) {
11
28
  const userId = params.auth.user_id?.trim();
@@ -14,24 +31,15 @@ function formatSlackBotTokenIdentityWarning(params) {
14
31
  const accountId = params.accountId?.trim() || "default";
15
32
  return `Slack auth.test identified account "${accountId}" as user ${userId} without bot_id. ${accountId === "default" ? "channels.slack.botToken, channels.slack.accounts.default.botToken, or SLACK_BOT_TOKEN" : `channels.slack.accounts.${accountId}.botToken`} appears to contain a user token; replace it with a Bot User OAuth Token. Until replaced, explicit bot-mention detection is disabled and required-mention channels fail closed.`;
16
33
  }
17
- function resolveSlackBotToken(raw, path = "channels.slack.botToken") {
18
- return normalizeResolvedSecretInputString({
19
- value: raw,
20
- path
21
- });
22
- }
23
- function resolveSlackAppToken(raw, path = "channels.slack.appToken") {
24
- return normalizeResolvedSecretInputString({
25
- value: raw,
26
- path
27
- });
28
- }
29
- function resolveSlackUserToken(raw, path = "channels.slack.userToken") {
30
- return normalizeResolvedSecretInputString({
34
+ function createSlackTokenResolver(defaultPath) {
35
+ return (raw, path = defaultPath) => normalizeResolvedSecretInputString({
31
36
  value: raw,
32
37
  path
33
38
  });
34
39
  }
40
+ const resolveSlackBotToken = createSlackTokenResolver("channels.slack.botToken");
41
+ const resolveSlackAppToken = createSlackTokenResolver("channels.slack.appToken");
42
+ const resolveSlackUserToken = createSlackTokenResolver("channels.slack.userToken");
35
43
  //#endregion
36
44
  //#region extensions/slack/src/account-reply-mode.ts
37
45
  function resolveSlackReplyToMode(account, chatType) {
@@ -62,13 +70,7 @@ function resolveSlackOperationToken(account, operation) {
62
70
  return account.config.userTokenReadOnly === false ? botToken ?? userToken : botToken;
63
71
  }
64
72
  function hasImplicitDefaultSlackAccount(cfg) {
65
- const slack = cfg.channels?.slack;
66
- const userIdentity = slack?.postAs === "user";
67
- return hasSlackAccountCredentials({
68
- config: slack ?? {},
69
- identityTokenConfigured: hasConfiguredAccountValue(userIdentity ? slack?.userToken : slack?.botToken) || hasConfiguredAccountValue(userIdentity ? process.env.SLACK_USER_TOKEN : process.env.SLACK_BOT_TOKEN),
70
- appTokenConfigured: hasConfiguredAccountValue(slack?.appToken) || hasConfiguredAccountValue(process.env.SLACK_APP_TOKEN)
71
- });
73
+ return hasSlackAccountCredentialsFromConfig(cfg.channels?.slack, process.env);
72
74
  }
73
75
  const { listAccountIds, resolveDefaultAccountId, resolveAccountConfig: resolveMergedSlackAccountConfig } = createAccountListHelpers("slack", {
74
76
  nestedObjectKeys: [
@@ -85,26 +87,25 @@ function resolveSlackAccountConfig(cfg, accountId) {
85
87
  }
86
88
  function mergeSlackStreamingConfig(baseConfig, accountConfig) {
87
89
  if (!baseConfig || !accountConfig) return accountConfig ?? baseConfig;
88
- return {
90
+ const merged = {
89
91
  ...baseConfig,
90
- ...accountConfig,
91
- ...baseConfig.preview || accountConfig.preview ? { preview: {
92
- ...baseConfig.preview,
93
- ...accountConfig.preview
94
- } } : {},
95
- ...baseConfig.progress || accountConfig.progress ? { progress: {
96
- ...baseConfig.progress,
97
- ...accountConfig.progress
98
- } } : {},
99
- ...baseConfig.block || accountConfig.block ? { block: {
100
- ...baseConfig.block,
101
- ...accountConfig.block,
102
- ...baseConfig.block?.coalesce || accountConfig.block?.coalesce ? { coalesce: {
103
- ...baseConfig.block?.coalesce,
104
- ...accountConfig.block?.coalesce
105
- } } : {}
106
- } } : {}
92
+ ...accountConfig
93
+ };
94
+ for (const key of [
95
+ "preview",
96
+ "progress",
97
+ "block"
98
+ ]) if (baseConfig[key] || accountConfig[key]) merged[key] = {
99
+ ...baseConfig[key],
100
+ ...accountConfig[key]
101
+ };
102
+ const baseCoalesce = baseConfig.block?.coalesce;
103
+ const accountCoalesce = accountConfig.block?.coalesce;
104
+ if (merged.block && (baseCoalesce || accountCoalesce)) merged.block.coalesce = {
105
+ ...baseCoalesce,
106
+ ...accountCoalesce
107
107
  };
108
+ return merged;
108
109
  }
109
110
  function mergeSlackAccountConfig(cfg, accountId) {
110
111
  const accountConfig = resolveSlackAccountConfig(cfg, accountId);
@@ -175,17 +176,7 @@ function resolveSlackAccount(params) {
175
176
  appTokenSource,
176
177
  userTokenSource,
177
178
  config: merged,
178
- groupPolicy: merged.groupPolicy,
179
- textChunkLimit: merged.textChunkLimit,
180
- mediaMaxMb: merged.mediaMaxMb,
181
- reactionNotifications: merged.reactionNotifications,
182
- reactionAllowlist: merged.reactionAllowlist,
183
- replyToMode: merged.replyToMode,
184
- replyToModeByChatType: merged.replyToModeByChatType,
185
- actions: merged.actions,
186
- slashCommand: merged.slashCommand,
187
- dm: merged.dm,
188
- channels: merged.channels
179
+ ...buildSlackAccountSurfaceFields(merged)
189
180
  };
190
181
  }
191
182
  function listEnabledSlackAccounts(cfg) {
@@ -195,4 +186,4 @@ function listEnabledSlackAccounts(cfg) {
195
186
  })).filter((account) => account.enabled);
196
187
  }
197
188
  //#endregion
198
- export { mergeSlackAccountConfig as a, resolveSlackAccountAllowFrom as c, resolveSlackOperationToken as d, resolveSlackReplyToMode as f, resolveSlackBotToken as h, listSlackAccountIds as i, resolveSlackAccountDmPolicy as l, resolveSlackAppToken as m, hasImplicitDefaultSlackAccount as n, resolveDefaultSlackAccountId as o, formatSlackBotTokenIdentityWarning as p, listEnabledSlackAccounts as r, resolveSlackAccount as s, accounts_exports as t, resolveSlackConfigAccessorAccount as u };
189
+ export { mergeSlackAccountConfig as a, resolveSlackAccountAllowFrom as c, resolveSlackOperationToken as d, resolveSlackReplyToMode as f, buildSlackAccountSurfaceFields as g, resolveSlackBotToken as h, listSlackAccountIds as i, resolveSlackAccountDmPolicy as l, resolveSlackAppToken as m, hasImplicitDefaultSlackAccount as n, resolveDefaultSlackAccountId as o, formatSlackBotTokenIdentityWarning as p, listEnabledSlackAccounts as r, resolveSlackAccount as s, accounts_exports as t, resolveSlackConfigAccessorAccount as u };
@@ -1,7 +1,7 @@
1
1
  import { a as parseSlackTarget, n as formatSlackTarget, o as resolveSlackChannelId } from "./target-parsing-FFE26kOV.mjs";
2
2
  import { t as slackContextTargetsMatch } from "./targets-C6LZQL1Q.mjs";
3
- import { At as getSlackInstallationKind, Bt as SLACK_PRIVATE_ACTION_DELIVERY_RESULT, Vt as resolveSlackAutoThreadId, f as assertSlackDetachedTargetAllowed, mt as parseSlackBlocksInput, r as buildSlackChannelIdCandidates, v as hasSlackNativeDataBlock } from "./session-status-D46GHwOV.mjs";
4
- import { n as resolveSlackChannelConfig, t as isSlackChannelAllowedByPolicy } from "./policy-KKTqEiDv.mjs";
3
+ import { Bt as resolveSlackAutoThreadId, f as assertSlackDetachedTargetAllowed, kt as getSlackInstallationKind, pt as parseSlackBlocksInput, r as buildSlackChannelIdCandidates, v as hasSlackNativeDataBlock, zt as SLACK_PRIVATE_ACTION_DELIVERY_RESULT } from "./session-status-CcXe10zN.mjs";
4
+ import { n as resolveSlackChannelConfig, t as isSlackChannelAllowedByPolicy } from "./policy-BaY9_eh1.mjs";
5
5
  import { t as mergeSlackSendResults } from "./send-results-eeOu_HYm.mjs";
6
6
  import { normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
7
7
  import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/string-coerce-runtime";
@@ -27,10 +27,13 @@ const pinActions = /* @__PURE__ */ new Set([
27
27
  "listPins"
28
28
  ]);
29
29
  const SLACK_REACTION_RESULT_LIMIT = 100;
30
- const loadSlackActionsRuntime = createLazyRuntimeModule(() => import("./actions-DDoAJnrH.mjs").then((n) => n.t));
30
+ function readSlackResultLimit(params) {
31
+ return Math.min(readPositiveIntegerParam(params, "limit", { message: "limit must be a positive integer." }) ?? SLACK_REACTION_RESULT_LIMIT, SLACK_REACTION_RESULT_LIMIT);
32
+ }
33
+ const loadSlackActionsRuntime = createLazyRuntimeModule(() => import("./actions-KGKwTAKO.mjs").then((n) => n.t));
31
34
  const bindSlackAction = createLazyRuntimeMethodBinder(loadSlackActionsRuntime);
32
- const loadSlackAccountsRuntime = createLazyRuntimeModule(() => import("./accounts-CDgkV7Cm.mjs").then((n) => n.t));
33
- const loadSlackChannelTypeRuntime = createLazyRuntimeModule(() => import("./channel-type-B9zYYzBU.mjs").then((n) => n.t));
35
+ const loadSlackAccountsRuntime = createLazyRuntimeModule(() => import("./accounts-BMg9YLIv.mjs").then((n) => n.t));
36
+ const loadSlackChannelTypeRuntime = createLazyRuntimeModule(() => import("./channel-type-NjX2SwvS.mjs").then((n) => n.t));
34
37
  const bindSlackChannelType = createLazyRuntimeMethodBinder(loadSlackChannelTypeRuntime);
35
38
  const slackActionRuntime = {
36
39
  deleteSlackMessage: bindSlackAction((runtime) => runtime.deleteSlackMessage),
@@ -95,15 +98,14 @@ async function isSlackDmTargetConfigured(params) {
95
98
  ...defaultTo ? [defaultTo] : []
96
99
  ].some((entry) => normalizeConfiguredSlackDmUserId(entry) === userId);
97
100
  }
98
- function isCurrentSlackReadTarget(params) {
99
- const requesterAccountId = params.context?.requesterAccountId?.trim();
100
- return Boolean(normalizeOptionalLowercaseString(params.context?.currentChannelProvider) === "slack" && requesterAccountId && normalizeAccountId(requesterAccountId) === normalizeAccountId(params.account.accountId) && params.context && slackContextTargetsMatch(params.target, params.context));
101
+ function hasSlackRequesterAccount(account, context) {
102
+ const requesterAccountId = context?.requesterAccountId?.trim();
103
+ return Boolean(normalizeOptionalLowercaseString(context?.currentChannelProvider) === "slack" && requesterAccountId && normalizeAccountId(requesterAccountId) === normalizeAccountId(account.accountId));
101
104
  }
102
105
  function assertSlackMemberInfoAllowed(params) {
103
106
  if (params.context?.conversationReadOrigin === "direct-operator") return;
104
- const requesterAccountId = params.context?.requesterAccountId?.trim();
105
107
  const requesterSenderId = normalizeOptionalLowercaseString(params.context?.requesterSenderId);
106
- if (normalizeOptionalLowercaseString(params.context?.currentChannelProvider) !== "slack" || !requesterAccountId || normalizeAccountId(requesterAccountId) !== normalizeAccountId(params.account.accountId) || !requesterSenderId || requesterSenderId !== normalizeOptionalLowercaseString(params.userId)) throw new Error("Delegated Slack member info is limited to the current requester.");
108
+ if (!hasSlackRequesterAccount(params.account, params.context) || !requesterSenderId || requesterSenderId !== normalizeOptionalLowercaseString(params.userId)) throw new Error("Delegated Slack member info is limited to the current requester.");
107
109
  }
108
110
  function resolveSlackChannelReadPolicy(params) {
109
111
  const channels = params.account.config.channels;
@@ -154,15 +156,12 @@ async function assertSlackReadTargetAllowed(params) {
154
156
  const deny = () => {
155
157
  throw new Error("Slack read target channel is not allowed.");
156
158
  };
157
- const currentConversation = isCurrentSlackReadTarget({
158
- account: params.account,
159
- target: formatSlackTarget({
160
- teamId: params.teamId,
161
- kind: "channel",
162
- id: params.channelId
163
- }),
164
- context: params.context
159
+ const target = formatSlackTarget({
160
+ teamId: params.teamId,
161
+ kind: "channel",
162
+ id: params.channelId
165
163
  });
164
+ const currentConversation = Boolean(hasSlackRequesterAccount(params.account, params.context) && params.context && slackContextTargetsMatch(target, params.context));
166
165
  const directOperator = params.conversationReadOrigin === "direct-operator";
167
166
  if (/^D/i.test(params.channelId)) {
168
167
  if (!resolveSlackDmReadAllowed(params.account)) deny();
@@ -227,8 +226,7 @@ function isSlackGroupDmTargetConfigured(account, channelId, teamId) {
227
226
  });
228
227
  }
229
228
  function resolveTrustedCurrentSlackTeamId(params) {
230
- const requesterAccountId = params.context?.requesterAccountId?.trim();
231
- if (normalizeOptionalLowercaseString(params.context?.currentChannelProvider) !== "slack" || !requesterAccountId || normalizeAccountId(requesterAccountId) !== normalizeAccountId(params.account.accountId)) return;
229
+ if (!hasSlackRequesterAccount(params.account, params.context)) return;
232
230
  const matchingTeams = /* @__PURE__ */ new Map();
233
231
  for (const raw of [params.context?.currentChannelId, params.context?.currentMessagingTarget]) {
234
232
  if (!raw) continue;
@@ -327,7 +325,7 @@ async function handleSlackAction(params, cfg, context) {
327
325
  });
328
326
  }
329
327
  await assertReadTargetAllowed(target);
330
- const limit = Math.min(readPositiveIntegerParam(params, "limit", { message: "limit must be a positive integer." }) ?? SLACK_REACTION_RESULT_LIMIT, SLACK_REACTION_RESULT_LIMIT);
328
+ const limit = readSlackResultLimit(params);
331
329
  const reactions = await slackActionRuntime.listSlackReactions(channelId, messageId, readOpts);
332
330
  return jsonResult({
333
331
  ok: true,
@@ -600,7 +598,7 @@ async function handleSlackAction(params, cfg, context) {
600
598
  }
601
599
  if (action === "emojiList") {
602
600
  if (!isActionEnabled("emojiList")) throw new Error("Slack emoji list is disabled.");
603
- const limit = Math.min(readPositiveIntegerParam(params, "limit", { message: "limit must be a positive integer." }) ?? SLACK_REACTION_RESULT_LIMIT, SLACK_REACTION_RESULT_LIMIT);
601
+ const limit = readSlackResultLimit(params);
604
602
  const teamId = resolveTrustedCurrentSlackTeamId({
605
603
  account,
606
604
  context
@@ -0,0 +1,2 @@
1
+ import { t as handleSlackAction } from "./action-runtime-BiRZNsIG.mjs";
2
+ export { handleSlackAction };
@@ -1,9 +1,9 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.mjs";
2
- import { h as resolveSlackBotToken, o as resolveDefaultSlackAccountId, s as resolveSlackAccount } from "./accounts-CDgkV7Cm.mjs";
2
+ import { h as resolveSlackBotToken, o as resolveDefaultSlackAccountId, s as resolveSlackAccount } from "./accounts-BMg9YLIv.mjs";
3
3
  import { n as formatSlackTarget } from "./target-parsing-FFE26kOV.mjs";
4
- import { A as countSlackTextUtf8Bytes, Bt as SLACK_PRIVATE_ACTION_DELIVERY_RESULT, C as buildSlackBlocksFallbackText, E as SLACK_EDIT_TEXT_MAX_BYTES, M as truncateSlackTextByUtf8Bytes, S as stripSlackNativeDataBlocks, T as renderSlackBlockFallbackText, Y as normalizeSlackOutboundText, f as assertSlackDetachedTargetAllowed, h as appendSlackNativeDataPlainTextFallback, ht as validateSlackBlocksArray, m as appendSlackNativeDataFallbackText, ot as escapeSlackMrkdwn, v as hasSlackNativeDataBlock, w as buildSlackCompleteBlocksFallbackText, y as isSlackInvalidBlocksError } from "./session-status-D46GHwOV.mjs";
5
- import { _ as getSlackWriteClient, h as createSlackWriteClient, u as createSlackLookupClient } from "./probe-BVlJ3dp0.mjs";
6
- import { m as buildSlackNativeDataDeliveryPlan, t as sendMessageSlack } from "./send-CgPI3Zj8.mjs";
4
+ import { C as stripSlackNativeDataBlocks, D as SLACK_EDIT_TEXT_MAX_BYTES, E as renderSlackBlockFallbackText, N as truncateSlackTextByUtf8Bytes, T as buildSlackCompleteBlocksFallbackText, X as normalizeSlackOutboundText, at as escapeSlackMrkdwn, f as assertSlackDetachedTargetAllowed, h as appendSlackNativeDataPlainTextFallback, j as countSlackTextUtf8Bytes, m as appendSlackNativeDataFallbackText, mt as validateSlackBlocksArray, v as hasSlackNativeDataBlock, w as buildSlackBlocksFallbackText, y as isSlackInvalidBlocksError, zt as SLACK_PRIVATE_ACTION_DELIVERY_RESULT } from "./session-status-CcXe10zN.mjs";
5
+ import { _ as getSlackWriteClient, h as createSlackWriteClient, u as createSlackLookupClient } from "./probe-CyX52GtD.mjs";
6
+ import { m as buildSlackNativeDataDeliveryPlan, t as sendMessageSlack } from "./send-CLmsR42r.mjs";
7
7
  import { normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
8
8
  import { asOptionalObjectRecord, asOptionalRecord, isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, readNonBlankString } from "openclaw/plugin-sdk/string-coerce-runtime";
9
9
  import { createSubsystemLogger, logVerbose } from "openclaw/plugin-sdk/runtime-env";
@@ -157,13 +157,8 @@ const slackMediaLog = createSubsystemLogger("gateway/channels/slack").child("med
157
157
  //#region extensions/slack/src/monitor/slack-client-kind.ts
158
158
  /** Detects the isolated GovSlack API plane without consulting mutable config. */
159
159
  function isGovSlackClient(client) {
160
- if (!client?.slackApiUrl) return false;
161
- try {
162
- const apiUrl = new URL(client.slackApiUrl);
163
- return apiUrl.protocol === "https:" && !apiUrl.port && normalizeHostname(apiUrl.hostname) === "slack-gov.com";
164
- } catch {
165
- return false;
166
- }
160
+ const apiUrl = client?.slackApiUrl ? URL.parse(client.slackApiUrl) : null;
161
+ return apiUrl?.protocol === "https:" && !apiUrl.port && normalizeHostname(apiUrl.hostname) === "slack-gov.com";
167
162
  }
168
163
  //#endregion
169
164
  //#region extensions/slack/src/monitor/media.ts
@@ -183,12 +178,8 @@ function isSlackHostname(hostname, govSlack) {
183
178
  ].some((suffix) => normalized === suffix || normalized.endsWith(`.${suffix}`));
184
179
  }
185
180
  function assertSlackFileUrl(rawUrl, govSlack) {
186
- let parsed;
187
- try {
188
- parsed = new URL(rawUrl);
189
- } catch {
190
- throw new Error(`Invalid Slack file URL: ${rawUrl}`);
191
- }
181
+ const parsed = URL.parse(rawUrl);
182
+ if (!parsed) throw new Error(`Invalid Slack file URL: ${rawUrl}`);
192
183
  if (parsed.protocol !== "https:") throw new Error(`Refusing Slack file URL with non-HTTPS protocol: ${parsed.protocol}`);
193
184
  if (!isSlackHostname(parsed.hostname, govSlack)) throw new Error(`Refusing to send Slack token to non-Slack host "${parsed.hostname}" (url: ${rawUrl})`);
194
185
  return parsed;
@@ -362,10 +353,6 @@ function resolveForwardedAttachmentImageUrl(attachment, govSlack) {
362
353
  return null;
363
354
  }
364
355
  }
365
- /**
366
- * Downloads all files attached to a Slack message and returns them as an array.
367
- * Returns `null` when no files could be downloaded.
368
- */
369
356
  async function resolveSlackMedia(params) {
370
357
  const assertCurrent = captureSlackMediaReadGuard(params);
371
358
  const govSlack = isGovSlackClient(params.client);
@@ -412,25 +399,28 @@ async function resolveSlackMedia(params) {
412
399
  const resolved = results.filter((result) => result !== null);
413
400
  return resolved.length > 0 ? resolved : null;
414
401
  }
415
- /** Extracts text and media from forwarded-message attachments. Returns null when empty. */
416
402
  async function resolveSlackAttachmentContent(params) {
417
403
  const forwardedAttachments = (params.attachments ?? []).filter((attachment) => attachment.is_share === true).slice(0, MAX_SLACK_FORWARDED_ATTACHMENTS);
418
404
  const candidates = [...params.files ?? [], ...forwardedAttachments.flatMap((attachment) => attachment.files ?? [])];
419
405
  if (forwardedAttachments.length === 0 && candidates.length === 0) return null;
420
- const fileIds = /* @__PURE__ */ new Set();
406
+ const fileGroups = /* @__PURE__ */ new Map();
421
407
  const allFiles = candidates.filter((file) => {
422
408
  const fileId = normalizeOptionalString(file.id);
423
409
  if (!fileId) return true;
424
- if (fileIds.has(fileId)) return false;
425
- fileIds.add(fileId);
410
+ const group = fileGroups.get(fileId);
411
+ if (group) {
412
+ group.push(file);
413
+ return false;
414
+ }
415
+ fileGroups.set(fileId, [file]);
426
416
  return true;
427
417
  }).map((file, index) => {
428
418
  if (index >= 8) return file;
429
- const fileId = normalizeOptionalString(file.id);
430
- const preloaded = fileId && candidates.find((candidate) => normalizeOptionalString(candidate.id) === fileId && params.preloadedMedia?.has(candidate));
419
+ const group = fileGroups.get(normalizeOptionalString(file.id) ?? "");
420
+ const preloaded = group?.find((candidate) => params.preloadedMedia?.has(candidate));
431
421
  if (preloaded) return preloaded;
432
- if (!fileId || file.url_private_download || file.url_private) return file;
433
- const downloadable = candidates.find((candidate) => normalizeOptionalString(candidate.id) === fileId && (candidate.url_private_download || candidate.url_private));
422
+ if (!group || file.url_private_download || file.url_private) return file;
423
+ const downloadable = group.find((candidate) => candidate.url_private_download || candidate.url_private);
434
424
  return downloadable ? Object.assign({}, file, downloadable) : file;
435
425
  });
436
426
  const pendingFiles = new Map(allFiles.slice(0, 8).map((file) => [normalizeOptionalString(file.id) ?? file, file]));
@@ -708,13 +698,16 @@ async function editSlackMessage(channelId, messageId, content, opts = {}) {
708
698
  });
709
699
  await editSlackRenderedMessage(channelId, messageId, normalizeSlackOutboundText(content, { tableMode }), opts);
710
700
  }
701
+ function slackNativeEditLimitError(options) {
702
+ return new Error(`Slack native chart or table fallback exceeds the ${String(SLACK_EDIT_TEXT_MAX_BYTES)}-byte edit limit. Send a new message instead.`, options);
703
+ }
711
704
  async function editSlackRenderedMessage(channelId, messageId, content, opts = {}) {
712
705
  const client = await getClient(opts, "write");
713
706
  const blocks = opts.blocks == null ? void 0 : validateSlackBlocksArray(opts.blocks);
714
707
  const editText = buildSlackEditTextPayload(content, blocks);
715
708
  const hasNativeData = hasSlackNativeDataBlock(blocks);
716
709
  const nativeFallbackText = hasNativeData ? appendSlackNativeDataFallbackText(editText, blocks) : editText;
717
- if (hasNativeData && countSlackTextUtf8Bytes(nativeFallbackText) > 4e3) throw new Error(`Slack native chart or table fallback exceeds the ${String(SLACK_EDIT_TEXT_MAX_BYTES)}-byte edit limit. Send a new message instead.`);
710
+ if (hasNativeData && countSlackTextUtf8Bytes(nativeFallbackText) > 4e3) throw slackNativeEditLimitError();
718
711
  const update = {
719
712
  channel: channelId,
720
713
  ts: messageId,
@@ -736,9 +729,9 @@ async function editSlackRenderedMessage(channelId, messageId, content, opts = {}
736
729
  });
737
730
  if (fallbackPlan.fallbackMessages.length !== 1) throw new Error("Slack native chart or table edit fallback requires multiple messages. Send a new message instead.", { cause: error });
738
731
  const fallback = fallbackPlan.fallbackMessages[0];
739
- if (!fallback || countSlackTextUtf8Bytes(fallback.text) > 4e3) throw new Error(`Slack native chart or table fallback exceeds the ${String(SLACK_EDIT_TEXT_MAX_BYTES)}-byte edit limit. Send a new message instead.`, { cause: error });
732
+ if (!fallback || countSlackTextUtf8Bytes(fallback.text) > 4e3) throw slackNativeEditLimitError({ cause: error });
740
733
  const fallbackText = fallback.blocks ? escapeSlackMrkdwn(fallback.text) : truncateSlackTextByUtf8Bytes(appendSlackNativeDataFallbackText(editText, blocks), SLACK_EDIT_TEXT_MAX_BYTES);
741
- if (countSlackTextUtf8Bytes(fallbackText) > 4e3) throw new Error(`Slack native chart or table fallback exceeds the ${String(SLACK_EDIT_TEXT_MAX_BYTES)}-byte edit limit. Send a new message instead.`, { cause: error });
734
+ if (countSlackTextUtf8Bytes(fallbackText) > 4e3) throw slackNativeEditLimitError({ cause: error });
742
735
  await client.chat.update({
743
736
  channel: channelId,
744
737
  ts: messageId,
@@ -793,18 +786,16 @@ async function getSlackMemberInfo(userId, opts = {}) {
793
786
  async function listSlackEmojis(opts = {}) {
794
787
  return await (await getClient(opts)).emoji.list();
795
788
  }
796
- async function pinSlackMessage(channelId, messageId, opts = {}) {
797
- await (await getClient(opts, "write")).pins.add({
798
- channel: channelId,
799
- timestamp: messageId
800
- });
801
- }
802
- async function unpinSlackMessage(channelId, messageId, opts = {}) {
803
- await (await getClient(opts, "write")).pins.remove({
804
- channel: channelId,
805
- timestamp: messageId
806
- });
789
+ function createSlackPinUpdater(method) {
790
+ return async (channelId, messageId, opts = {}) => {
791
+ await (await getClient(opts, "write")).pins[method]({
792
+ channel: channelId,
793
+ timestamp: messageId
794
+ });
795
+ };
807
796
  }
797
+ const pinSlackMessage = createSlackPinUpdater("add");
798
+ const unpinSlackMessage = createSlackPinUpdater("remove");
808
799
  async function listSlackPins(channelId, opts = {}) {
809
800
  return (await (await getClient(opts)).pins.list({ channel: channelId })).items ?? [];
810
801
  }