@openclaw/slack 2026.7.2-beta.1 → 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 (61) 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-p6M2ULpv.js → action-runtime-DqkRwO3Z.js} +14 -17
  7. package/dist/action-runtime.runtime-DEWOcFM4.js +2 -0
  8. package/dist/{actions-DkTcWmpT.js → actions-CF0tUY5q.js} +5 -9
  9. package/dist/{actions.runtime-BSxpwgUc.js → actions.runtime-hCbx4RXg.js} +1 -1
  10. package/dist/api.js +13 -14
  11. package/dist/{approval-handler.runtime-UGbnz9OC.js → approval-handler.runtime-Em8I1-8-.js} +2 -2
  12. package/dist/{channel-B0_j6C6z.js → channel-4-TRi1D6.js} +75 -41
  13. package/dist/channel-config-api.js +1 -1
  14. package/dist/channel-plugin-api.js +1 -1
  15. package/dist/{channel-type-BpeTezY4.js → channel-type-Cu1yjNg2.js} +3 -3
  16. package/dist/{channel.setup-BQFut21T.js → channel.setup-CgkADtZg.js} +6 -4
  17. package/dist/{config-schema-DYI01PV2.js → config-schema-XjJGfwQC.js} +18 -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-DX7yFsM-.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-C-b2ZnSl.js → group-policy-Bw-65m3V.js} +94 -135
  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-BN_uuvrQ.js → monitor-CNFeF30h.js} +3 -3
  29. package/dist/{outbound-adapter-ECl0go7d.js → outbound-adapter-CVi2uok0.js} +49 -5
  30. package/dist/{pipeline.runtime-f0eJJoJL.js → pipeline.runtime-CTvokbty.js} +485 -251
  31. package/dist/{policy-f8b0edSi.js → policy-b_dOPDCq.js} +7 -7
  32. package/dist/probe-Borhn9PQ.js +340 -0
  33. package/dist/{provider-Ds-y-imP.js → provider-B-HVL5ZE.js} +831 -329
  34. package/dist/{relay-source-B-6LFUdz.js → relay-source-Ea_P9VcO.js} +6 -11
  35. package/dist/{replies-BMvf3ihj.js → replies-B4bOdrYb.js} +3 -3
  36. package/dist/{resolve-channels-DOMgNCWb.js → resolve-channels-KTc568SU.js} +1 -1
  37. package/dist/{resolve-users-aL6-Ssee.js → resolve-users-DeGJf1yp.js} +1 -1
  38. package/dist/{runtime-CauEvswP.js → runtime-JSVZSWAj.js} +2 -2
  39. package/dist/{runtime-api-CVb6CQjX.js → runtime-api-BFfNpzDe.js} +1 -1
  40. package/dist/runtime-api.js +12 -12
  41. package/dist/runtime-setter-api.js +1 -1
  42. package/dist/{scopes-Dw8wbU0j.js → scopes-lx08L56K.js} +1 -2
  43. package/dist/{secret-contract-CMohXFWS.js → secret-contract-DxmvbxBF.js} +1 -0
  44. package/dist/secret-contract-api.js +1 -1
  45. package/dist/{send-NEfJ0GvM.js → send-KuTDky7i.js} +29 -12
  46. package/dist/send.runtime-CXyxws1D.js +2 -0
  47. package/dist/setup-core-CeiAVwQ3.js +502 -0
  48. package/dist/setup-plugin-api.js +1 -1
  49. package/dist/{setup-surface-BN2WeG5c.js → setup-surface-DLA0vHXp.js} +23 -13
  50. package/dist/{shared-BLnB9R1T.js → shared-C4yVB0Q-.js} +64 -41
  51. package/dist/{slash-dispatch.runtime-C0Otuf_T.js → slash-dispatch.runtime-BT-mMm-f.js} +1 -1
  52. package/npm-shrinkwrap.json +3 -3
  53. package/openclaw.plugin.json +134 -10
  54. package/package.json +5 -7
  55. package/dist/accounts.runtime-KvftRRek.js +0 -2
  56. package/dist/action-runtime.runtime-DQstDkHG.js +0 -2
  57. package/dist/client-D2F6m8CP.js +0 -152
  58. package/dist/configured-state.js +0 -11
  59. package/dist/probe-CfALk0l4.js +0 -48
  60. package/dist/send.runtime-BkKpitPu.js +0 -2
  61. package/dist/setup-core-fGd6Gquy.js +0 -343
@@ -0,0 +1,502 @@
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";
4
+ import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
5
+ import { DEFAULT_ACCOUNT_ID, createAccountScopedAllowFromSection, createAccountScopedGroupAccessSection, createAllowlistSetupWizardProxy, createLegacyCompatChannelDmPolicy, createPatchedAccountSetupAdapter, createSetupTranslator, createStandardChannelSetupStatus, defineTokenCredential, parseMentionOrPrefixedId, patchChannelConfigForAccount, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup-runtime";
6
+ import { formatDocsLink } from "openclaw/plugin-sdk/setup-tools";
7
+ import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
8
+ //#region extensions/slack/src/setup-shared.ts
9
+ const SLACK_CHANNEL = "slack";
10
+ function buildSlackManifest(botName = "OpenClaw") {
11
+ const safeName = botName.trim() || "OpenClaw";
12
+ const manifest = {
13
+ display_information: {
14
+ name: safeName,
15
+ description: `${safeName} connector for OpenClaw`
16
+ },
17
+ features: {
18
+ bot_user: {
19
+ display_name: safeName,
20
+ always_online: true
21
+ },
22
+ app_home: {
23
+ home_tab_enabled: true,
24
+ messages_tab_enabled: true,
25
+ messages_tab_read_only_enabled: false
26
+ },
27
+ assistant_view: {
28
+ assistant_description: `${safeName} connects Slack assistant threads to OpenClaw agents.`,
29
+ suggested_prompts: [
30
+ {
31
+ title: "What can you do?",
32
+ message: "What can you help me with?"
33
+ },
34
+ {
35
+ title: "Summarize this channel",
36
+ message: "Summarize the recent activity in this channel."
37
+ },
38
+ {
39
+ title: "Draft a reply",
40
+ message: "Help me draft a reply."
41
+ }
42
+ ]
43
+ },
44
+ slash_commands: [{
45
+ command: "/openclaw",
46
+ description: "Send a message to OpenClaw",
47
+ should_escape: false
48
+ }]
49
+ },
50
+ oauth_config: { scopes: { bot: [
51
+ "app_mentions:read",
52
+ "assistant:write",
53
+ "channels:history",
54
+ "channels:read",
55
+ "chat:write",
56
+ "commands",
57
+ "emoji:read",
58
+ "files:read",
59
+ "files:write",
60
+ "groups:history",
61
+ "groups:read",
62
+ "im:history",
63
+ "im:read",
64
+ "im:write",
65
+ "mpim:history",
66
+ "mpim:read",
67
+ "mpim:write",
68
+ "pins:read",
69
+ "pins:write",
70
+ "reactions:read",
71
+ "reactions:write",
72
+ "usergroups:read",
73
+ "users:read"
74
+ ] } },
75
+ settings: {
76
+ socket_mode_enabled: true,
77
+ event_subscriptions: { bot_events: [
78
+ "app_home_opened",
79
+ "app_mention",
80
+ "assistant_thread_context_changed",
81
+ "assistant_thread_started",
82
+ "channel_rename",
83
+ "member_joined_channel",
84
+ "member_left_channel",
85
+ "message.channels",
86
+ "message.groups",
87
+ "message.im",
88
+ "message.mpim",
89
+ "pin_added",
90
+ "pin_removed",
91
+ "reaction_added",
92
+ "reaction_removed"
93
+ ] }
94
+ }
95
+ };
96
+ return JSON.stringify(manifest, null, 2);
97
+ }
98
+ function buildSlackSetupLines() {
99
+ return [
100
+ "1) Slack API -> Create App -> From scratch or From manifest (with the JSON below)",
101
+ "2) Add Socket Mode + enable it to get the app-level token (xapp-...)",
102
+ "3) Install App to workspace to get the xoxb- bot token",
103
+ "4) Enable Event Subscriptions (socket) for message, App Home, and assistant events",
104
+ "5) App Home -> enable the Home tab, Messages tab for DMs, and AI assistant view",
105
+ "Manifest JSON follows as plain text for copy/paste.",
106
+ "Tip: set SLACK_BOT_TOKEN + SLACK_APP_TOKEN in your env.",
107
+ `Docs: ${formatDocsLink("/slack", "slack")}`
108
+ ];
109
+ }
110
+ function setSlackChannelAllowlist(cfg, accountId, channelKeys) {
111
+ const channels = Object.fromEntries(channelKeys.map((key) => [key, { enabled: true }]));
112
+ return patchChannelConfigForAccount({
113
+ cfg,
114
+ channel: SLACK_CHANNEL,
115
+ accountId,
116
+ patch: { channels }
117
+ });
118
+ }
119
+ function isSlackSetupAccountConfigured(account) {
120
+ if (account.config.mode === "relay") return isSlackPluginAccountConfigured(account);
121
+ const hasConfiguredUserToken = Boolean(account.userToken?.trim()) || hasConfiguredSecretInput(account.config.userToken);
122
+ const hasConfiguredBotToken = Boolean(account.botToken?.trim()) || hasConfiguredSecretInput(account.config.botToken);
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
+ }
128
+ return hasConfiguredBotToken && hasConfiguredAppToken;
129
+ }
130
+ function describeSlackSetupAccount(account) {
131
+ return describeAccountSnapshot({
132
+ account,
133
+ configured: isSlackSetupAccountConfigured(account),
134
+ extra: {
135
+ botTokenSource: account.botTokenSource,
136
+ appTokenSource: account.appTokenSource,
137
+ ...account.identity === "user" ? {
138
+ identity: account.identity,
139
+ userTokenSource: account.userTokenSource
140
+ } : {}
141
+ }
142
+ });
143
+ }
144
+ //#endregion
145
+ //#region extensions/slack/src/setup-core.ts
146
+ const t = createSetupTranslator();
147
+ function enableSlackAccount(cfg, accountId) {
148
+ return patchChannelConfigForAccount({
149
+ cfg,
150
+ channel: SLACK_CHANNEL,
151
+ accountId,
152
+ patch: { enabled: true }
153
+ });
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
+ }
195
+ function hasSlackInteractiveRepliesConfig(cfg, accountId) {
196
+ const capabilities = inspectSlackAccount({
197
+ cfg,
198
+ accountId
199
+ }).config.capabilities;
200
+ if (Array.isArray(capabilities)) return capabilities.some((entry) => normalizeLowercaseStringOrEmpty(entry) === "interactivereplies");
201
+ if (!capabilities || typeof capabilities !== "object") return false;
202
+ return "interactiveReplies" in capabilities;
203
+ }
204
+ function setSlackInteractiveReplies(cfg, accountId, interactiveReplies) {
205
+ const capabilities = inspectSlackAccount({
206
+ cfg,
207
+ accountId
208
+ }).config.capabilities;
209
+ return patchChannelConfigForAccount({
210
+ cfg,
211
+ channel: SLACK_CHANNEL,
212
+ accountId,
213
+ patch: { capabilities: Array.isArray(capabilities) ? interactiveReplies ? uniqueStrings([...capabilities, "interactiveReplies"]) : capabilities.filter((entry) => normalizeLowercaseStringOrEmpty(entry) !== "interactivereplies") : {
214
+ ...capabilities && typeof capabilities === "object" ? capabilities : {},
215
+ interactiveReplies
216
+ } }
217
+ });
218
+ }
219
+ function createSlackTokenCredential(params) {
220
+ return defineTokenCredential({
221
+ inputKey: params.inputKey,
222
+ configKey: params.inputKey,
223
+ providerHint: params.providerHint,
224
+ credentialLabel: params.credentialLabel,
225
+ preferredEnvVar: params.preferredEnvVar,
226
+ envPrompt: params.preferredEnvVar ? `${params.preferredEnvVar} detected. Use env var?` : "Use the configured Slack credential?",
227
+ keepPrompt: params.keepPrompt,
228
+ inputPrompt: params.inputPrompt,
229
+ allowEnv: ({ accountId }) => Boolean(params.preferredEnvVar) && accountId === DEFAULT_ACCOUNT_ID,
230
+ resolveAccount: ({ cfg, accountId }) => inspectSlackAccount({
231
+ cfg,
232
+ accountId
233
+ }),
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,
241
+ patchAccount: ({ cfg, accountId, mode, patch }) => mode === "env" ? enableSlackAccount(cfg, accountId) : patchChannelConfigForAccount({
242
+ cfg,
243
+ channel: SLACK_CHANNEL,
244
+ accountId,
245
+ patch: {
246
+ enabled: true,
247
+ ...patch
248
+ }
249
+ }),
250
+ useEnv: { clearFields: [] },
251
+ set: {},
252
+ shouldPrompt: params.shouldPrompt
253
+ });
254
+ }
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({
264
+ channelKey: SLACK_CHANNEL,
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
+ },
283
+ buildPatch: (input) => ({
284
+ ...input.identity ? { identity: input.identity } : {},
285
+ ...input.identity === "user" && input.mode ? { mode: input.mode } : {},
286
+ ...input.botToken ? { botToken: input.botToken } : {},
287
+ ...input.appToken ? { appToken: input.appToken } : {},
288
+ ...input.userToken ? { userToken: input.userToken } : {},
289
+ ...input.signingSecret ? { signingSecret: input.signingSecret } : {}
290
+ })
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
+ };
309
+ function createSlackSetupWizardBase(handlers) {
310
+ const slackDmPolicy = createLegacyCompatChannelDmPolicy({
311
+ label: "Slack",
312
+ channel: SLACK_CHANNEL,
313
+ promptAllowFrom: handlers.promptAllowFrom
314
+ });
315
+ return {
316
+ channel: SLACK_CHANNEL,
317
+ status: createStandardChannelSetupStatus({
318
+ channelLabel: "Slack",
319
+ configuredLabel: t("wizard.channels.statusConfigured"),
320
+ unconfiguredLabel: t("wizard.channels.statusNeedsTokens"),
321
+ configuredHint: t("wizard.channels.statusConfigured"),
322
+ unconfiguredHint: t("wizard.channels.statusNeedsTokens"),
323
+ configuredScore: 2,
324
+ unconfiguredScore: 1,
325
+ resolveConfigured: ({ cfg, accountId }) => inspectSlackAccount({
326
+ cfg,
327
+ accountId
328
+ }).configured
329
+ }),
330
+ prepare: async ({ cfg, accountId, prompter }) => {
331
+ const currentAccount = inspectSlackAccount({
332
+ cfg,
333
+ accountId
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 };
371
+ },
372
+ envShortcut: {
373
+ prompt: t("wizard.slack.envPrompt"),
374
+ preferredEnvVar: "SLACK_BOT_TOKEN",
375
+ isAvailable: ({ cfg, accountId }) => accountId === DEFAULT_ACCOUNT_ID && (inspectSlackAccount({
376
+ cfg,
377
+ accountId
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,
382
+ apply: ({ cfg, accountId }) => enableSlackAccount(cfg, accountId)
383
+ },
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
+ ],
439
+ dmPolicy: slackDmPolicy,
440
+ allowFrom: createAccountScopedAllowFromSection({
441
+ channel: SLACK_CHANNEL,
442
+ helpTitle: t("wizard.slack.allowlistTitle"),
443
+ helpLines: [
444
+ t("wizard.slack.allowlistIntro"),
445
+ t("wizard.slack.examples"),
446
+ "- U12345678",
447
+ "- @alice",
448
+ t("wizard.slack.multipleEntries"),
449
+ t("wizard.channels.docs", { link: formatDocsLink("/slack", "slack") })
450
+ ],
451
+ message: t("wizard.slack.allowFromPrompt"),
452
+ placeholder: "@alice, U12345678",
453
+ invalidWithoutCredentialNote: t("wizard.slack.allowFromInvalidWithoutToken"),
454
+ parseId: (value) => parseMentionOrPrefixedId({
455
+ value,
456
+ mentionPattern: /^<@([A-Z0-9]+)>$/i,
457
+ prefixPattern: /^(slack:|user:)/i,
458
+ idPattern: /^[A-Z][A-Z0-9]+$/i,
459
+ normalizeId: (id) => id.toUpperCase()
460
+ }),
461
+ resolveEntries: handlers.resolveAllowFromEntries
462
+ }),
463
+ groupAccess: createAccountScopedGroupAccessSection({
464
+ channel: SLACK_CHANNEL,
465
+ label: t("wizard.slack.channelsLabel"),
466
+ placeholder: "#general, #private, C123",
467
+ currentPolicy: ({ cfg, accountId }) => inspectSlackAccount({
468
+ cfg,
469
+ accountId
470
+ }).config.groupPolicy ?? "allowlist",
471
+ currentEntries: ({ cfg, accountId }) => Object.entries(inspectSlackAccount({
472
+ cfg,
473
+ accountId
474
+ }).config.channels ?? {}).filter(([, value]) => value?.enabled !== false).map(([key]) => key),
475
+ updatePrompt: ({ cfg, accountId }) => Boolean(inspectSlackAccount({
476
+ cfg,
477
+ accountId
478
+ }).config.channels),
479
+ resolveAllowlist: handlers.resolveGroupAllowlist,
480
+ fallbackResolved: (entries) => entries,
481
+ applyAllowlist: ({ cfg, accountId, resolved }) => setSlackChannelAllowlist(cfg, accountId, resolved)
482
+ }),
483
+ finalize: async ({ cfg, accountId, options, prompter }) => {
484
+ if (hasSlackInteractiveRepliesConfig(cfg, accountId)) return;
485
+ if (options?.quickstartDefaults) return { cfg: setSlackInteractiveReplies(cfg, accountId, true) };
486
+ return { cfg: setSlackInteractiveReplies(cfg, accountId, await prompter.confirm({
487
+ message: t("wizard.slack.interactiveRepliesPrompt"),
488
+ initialValue: true
489
+ })) };
490
+ },
491
+ disable: (cfg) => setSetupChannelEnabled(cfg, SLACK_CHANNEL, false)
492
+ };
493
+ }
494
+ function createSlackSetupWizardProxy(loadWizard) {
495
+ return createAllowlistSetupWizardProxy({
496
+ loadWizard: async () => (await loadWizard()).slackSetupWizard,
497
+ createBase: createSlackSetupWizardBase,
498
+ fallbackResolvedGroupAllowlist: (entries) => entries
499
+ });
500
+ }
501
+ //#endregion
502
+ export { describeSlackSetupAccount as a, SLACK_CHANNEL as i, createSlackSetupWizardProxy as n, isSlackSetupAccountConfigured as o, slackSetupAdapter as r, createSlackSetupWizardBase as t };
@@ -1,2 +1,2 @@
1
- import { t as slackSetupPlugin } from "./channel.setup-BQFut21T.js";
1
+ import { t as slackSetupPlugin } from "./channel.setup-CgkADtZg.js";
2
2
  export { slackSetupPlugin };
@@ -1,14 +1,19 @@
1
- import { a as resolveSlackAccount, i as resolveDefaultSlackAccountId, o as resolveSlackAccountAllowFrom } from "./accounts-BOJJiHSr.js";
2
- import "./shared-BLnB9R1T.js";
3
- import { i as SLACK_CHANNEL, t as createSlackSetupWizardBase } from "./setup-core-fGd6Gquy.js";
4
- import { t as resolveSlackChannelAllowlist } from "./resolve-channels-DOMgNCWb.js";
5
- import { t as resolveSlackUserAllowlist } from "./resolve-users-aL6-Ssee.js";
1
+ import { i as resolveDefaultSlackAccountId, o as resolveSlackAccountAllowFrom } from "./accounts-DQEbYKh9.js";
2
+ import { t as inspectSlackAccount } from "./account-inspect-Bvbtu3iH.js";
3
+ import "./shared-C4yVB0Q-.js";
4
+ import { i as SLACK_CHANNEL, t as createSlackSetupWizardBase } from "./setup-core-CeiAVwQ3.js";
5
+ import { t as resolveSlackChannelAllowlist } from "./resolve-channels-KTc568SU.js";
6
+ import { t as resolveSlackUserAllowlist } from "./resolve-users-DeGJf1yp.js";
6
7
  import { normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
7
8
  import { adaptScopedAccountAccessor } from "openclaw/plugin-sdk/channel-config-helpers";
8
9
  import { createSetupTranslator, noteChannelLookupFailure, noteChannelLookupSummary, parseMentionOrPrefixedId, promptLegacyChannelAllowFromForAccount, resolveEntriesWithOptionalToken } from "openclaw/plugin-sdk/setup-runtime";
9
10
  import { formatDocsLink } from "openclaw/plugin-sdk/setup-tools";
10
11
  //#region extensions/slack/src/setup-surface.ts
11
12
  const t = createSetupTranslator();
13
+ function resolveSlackSetupAuth(account, credentialValues) {
14
+ if (account.config.identity === "user") return credentialValues.userToken || account.userToken;
15
+ return credentialValues.botToken || account.botToken;
16
+ }
12
17
  async function resolveSlackAllowFromEntries(params) {
13
18
  return await resolveEntriesWithOptionalToken({
14
19
  token: params.token,
@@ -42,7 +47,7 @@ async function promptSlackAllowFrom(params) {
42
47
  prompter: params.prompter,
43
48
  accountId: params.accountId,
44
49
  defaultAccountId: resolveDefaultSlackAccountId(params.cfg),
45
- resolveAccount: adaptScopedAccountAccessor(resolveSlackAccount),
50
+ resolveAccount: adaptScopedAccountAccessor(inspectSlackAccount),
46
51
  resolveExisting: (account, cfg) => resolveSlackAccountAllowFrom({
47
52
  cfg,
48
53
  accountId: account.accountId
@@ -73,13 +78,13 @@ async function promptSlackAllowFrom(params) {
73
78
  }
74
79
  async function resolveSlackGroupAllowlist(params) {
75
80
  let keys = params.entries;
76
- const activeBotToken = resolveSlackAccount({
81
+ const auth = resolveSlackSetupAuth(inspectSlackAccount({
77
82
  cfg: params.cfg,
78
83
  accountId: params.accountId
79
- }).botToken || params.credentialValues.botToken || "";
84
+ }), params.credentialValues) || "";
80
85
  if (params.entries.length > 0) try {
81
86
  const resolved = await resolveEntriesWithOptionalToken({
82
- token: activeBotToken,
87
+ token: auth,
83
88
  entries: params.entries,
84
89
  buildWithoutToken: (input) => ({
85
90
  input,
@@ -114,10 +119,15 @@ async function resolveSlackGroupAllowlist(params) {
114
119
  }
115
120
  const slackSetupWizard = createSlackSetupWizardBase({
116
121
  promptAllowFrom: promptSlackAllowFrom,
117
- resolveAllowFromEntries: async ({ credentialValues, entries }) => await resolveSlackAllowFromEntries({
118
- token: credentialValues.botToken,
119
- entries
120
- }),
122
+ resolveAllowFromEntries: async ({ cfg, accountId, credentialValues, entries }) => {
123
+ return await resolveSlackAllowFromEntries({
124
+ token: resolveSlackSetupAuth(inspectSlackAccount({
125
+ cfg,
126
+ accountId
127
+ }), credentialValues),
128
+ entries
129
+ });
130
+ },
121
131
  resolveGroupAllowlist: async ({ cfg, accountId, credentialValues, entries, prompter }) => await resolveSlackGroupAllowlist({
122
132
  cfg,
123
133
  accountId,