@openclaw/slack 2026.5.12-beta.7

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 (88) hide show
  1. package/dist/account-inspect-D7AZNs8C.js +77 -0
  2. package/dist/account-inspect-api.js +10 -0
  3. package/dist/accounts-ClAPP5ry.js +139 -0
  4. package/dist/accounts.runtime-DDVcLJUI.js +2 -0
  5. package/dist/action-runtime-e2UhRsNx.js +350 -0
  6. package/dist/action-runtime.runtime-BFcqMbOm.js +2 -0
  7. package/dist/actions-CYLFK-Zy.js +292 -0
  8. package/dist/actions.runtime-CO3OaTLb.js +2 -0
  9. package/dist/allow-list-BPnnlRPL.js +82 -0
  10. package/dist/api.js +21 -0
  11. package/dist/approval-handler.runtime-CmeRr9qA.js +256 -0
  12. package/dist/blocks-input-CwTFVImV.js +29 -0
  13. package/dist/blocks-render-BIDw-Pom.js +161 -0
  14. package/dist/channel-DRjHBTDB.js +1020 -0
  15. package/dist/channel-api-B_nZwosg.js +20 -0
  16. package/dist/channel-config-api.js +2 -0
  17. package/dist/channel-entry.js +22 -0
  18. package/dist/channel-plugin-api.js +2 -0
  19. package/dist/channel.setup-Cayn7afd.js +73 -0
  20. package/dist/client-CPe4GmDR.js +103 -0
  21. package/dist/config-api-B_jq4NJW.js +2 -0
  22. package/dist/config-schema-D9B5LB_L.js +167 -0
  23. package/dist/configured-state.js +11 -0
  24. package/dist/contract-api.js +5 -0
  25. package/dist/directory-config-B3JiHeB7.js +54 -0
  26. package/dist/directory-contract-api.js +2 -0
  27. package/dist/directory-live-Bf16GwDh.js +133 -0
  28. package/dist/doctor-contract-KUjHnkQm.js +147 -0
  29. package/dist/doctor-contract-api.js +2 -0
  30. package/dist/errors-BYFHR24f.js +109 -0
  31. package/dist/exec-approvals-7xUNgLi9.js +58 -0
  32. package/dist/group-policy-CyLUK6My.js +41 -0
  33. package/dist/http-routes-api.js +2 -0
  34. package/dist/inbound-contract-test-api.js +3 -0
  35. package/dist/index.js +33 -0
  36. package/dist/interactive-replies-api.js +2 -0
  37. package/dist/interactive-replies-qAIfuBor.js +173 -0
  38. package/dist/magic-string.es-BMaGRRZ1.js +1011 -0
  39. package/dist/media-D1XCd1uP.js +469 -0
  40. package/dist/message-tool-api-6lowf9zE.js +104 -0
  41. package/dist/message-tool-api.js +2 -0
  42. package/dist/monitor-a97o17G6.js +13 -0
  43. package/dist/mrkdwn-Cax-eSfK.js +6 -0
  44. package/dist/outbound-adapter-B_5sEhCg.js +174 -0
  45. package/dist/outbound-payload-test-api.js +2 -0
  46. package/dist/outbound-payload.test-harness-CVCamg1x.js +13558 -0
  47. package/dist/pipeline.runtime-DT0hLnq2.js +1379 -0
  48. package/dist/plugin-routes-DtTPmga1.js +20 -0
  49. package/dist/prepare-D3YqV8jB.js +1482 -0
  50. package/dist/prepare.test-helpers-DVcjRhfG.js +49 -0
  51. package/dist/probe-3eZf1FjI.js +42 -0
  52. package/dist/provider-D7uAN3Fq.js +3235 -0
  53. package/dist/registry-CeaoNfoP.js +39 -0
  54. package/dist/replies-Xe_jMR6o.js +139 -0
  55. package/dist/reply-blocks-Z5l6_R6H.js +14 -0
  56. package/dist/resolve-allowlist-common-Bk3clYPK.js +43 -0
  57. package/dist/resolve-channels-BRYqyNVJ.js +81 -0
  58. package/dist/resolve-users-Bd_SdP8j.js +113 -0
  59. package/dist/rolldown-runtime-CiIaOW0V.js +13 -0
  60. package/dist/room-context-0vovmZPU.js +787 -0
  61. package/dist/runtime-Bo-KHM-F.js +8 -0
  62. package/dist/runtime-api-Dd1xIV5v.js +9 -0
  63. package/dist/runtime-api.js +14 -0
  64. package/dist/runtime-setter-api.js +2 -0
  65. package/dist/scopes-CDevO8jg.js +74 -0
  66. package/dist/secret-contract-Bo6lbSkh.js +141 -0
  67. package/dist/secret-contract-api.js +2 -0
  68. package/dist/security-audit-BtHGnD3d.js +51 -0
  69. package/dist/security-contract-api.js +2 -0
  70. package/dist/send-D_A9kL-C.js +721 -0
  71. package/dist/send.runtime-BRE_ncCU.js +2 -0
  72. package/dist/send.runtime-_l76lUuL.js +2 -0
  73. package/dist/setup-core-B9NetDkM.js +320 -0
  74. package/dist/setup-entry.js +15 -0
  75. package/dist/setup-plugin-api.js +2 -0
  76. package/dist/setup-surface-D88QBVOW.js +128 -0
  77. package/dist/shared-D8U42xFL.js +208 -0
  78. package/dist/slash-commands.runtime-22kgyst2.js +19 -0
  79. package/dist/slash-dispatch.runtime-BJgT0jwV.js +32 -0
  80. package/dist/slash-plugin-commands.runtime-CF-n3MeP.js +2 -0
  81. package/dist/slash-skill-commands.runtime-BMs0VjTe.js +7 -0
  82. package/dist/streaming-compat-RkZgTmQ2.js +43 -0
  83. package/dist/target-parsing-CQmv-iSm.js +55 -0
  84. package/dist/targets-B1tYCAr6.js +2 -0
  85. package/dist/test-api.js +8 -0
  86. package/dist/thread-ts-C2x7c5PP.js +24 -0
  87. package/openclaw.plugin.json +2405 -0
  88. package/package.json +84 -0
@@ -0,0 +1,20 @@
1
+ import "./target-parsing-CQmv-iSm.js";
2
+ import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1 } from "openclaw/plugin-sdk/account-id";
3
+ import { PAIRING_APPROVED_MESSAGE, projectCredentialSnapshotFields, resolveConfiguredFromRequiredCredentialStatuses } from "openclaw/plugin-sdk/channel-status";
4
+ //#region extensions/slack/src/channel-api.ts
5
+ const SLACK_CHANNEL_META = {
6
+ id: "slack",
7
+ label: "Slack",
8
+ selectionLabel: "Slack",
9
+ docsPath: "/channels/slack",
10
+ docsLabel: "slack",
11
+ blurb: "supports bot + app tokens, channels, threads, and interactive replies.",
12
+ systemImage: "number.square",
13
+ markdownCapable: true
14
+ };
15
+ function getChatChannelMeta(id) {
16
+ if (id !== SLACK_CHANNEL_META.id) throw new Error(`Unsupported Slack channel meta lookup: ${id}`);
17
+ return SLACK_CHANNEL_META;
18
+ }
19
+ //#endregion
20
+ export { resolveConfiguredFromRequiredCredentialStatuses as a, projectCredentialSnapshotFields as i, PAIRING_APPROVED_MESSAGE as n, getChatChannelMeta as r, DEFAULT_ACCOUNT_ID$1 as t };
@@ -0,0 +1,2 @@
1
+ import { t as SlackChannelConfigSchema } from "./config-schema-D9B5LB_L.js";
2
+ export { SlackChannelConfigSchema };
@@ -0,0 +1,22 @@
1
+ import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
2
+ //#region extensions/slack/channel-entry.ts
3
+ var channel_entry_default = defineBundledChannelEntry({
4
+ id: "slack",
5
+ name: "Slack",
6
+ description: "Slack channel plugin",
7
+ importMetaUrl: import.meta.url,
8
+ plugin: {
9
+ specifier: "./api.js",
10
+ exportName: "slackPlugin"
11
+ },
12
+ secrets: {
13
+ specifier: "./secret-contract-api.js",
14
+ exportName: "channelSecrets"
15
+ },
16
+ runtime: {
17
+ specifier: "./runtime-setter-api.js",
18
+ exportName: "setSlackRuntime"
19
+ }
20
+ });
21
+ //#endregion
22
+ export { channel_entry_default as default };
@@ -0,0 +1,2 @@
1
+ import { t as slackPlugin } from "./channel-DRjHBTDB.js";
2
+ export { slackPlugin };
@@ -0,0 +1,73 @@
1
+ import { a as resolveSlackAccount, c as resolveSlackConfigAccessorAccount, i as resolveDefaultSlackAccountId, n as listSlackAccountIds } from "./accounts-ClAPP5ry.js";
2
+ import { a as describeSlackSetupAccount, i as SLACK_CHANNEL, n as createSlackSetupWizardProxy, o as isSlackSetupAccountConfigured, r as slackSetupAdapter } from "./setup-core-B9NetDkM.js";
3
+ import { t as SlackChannelConfigSchema } from "./config-schema-D9B5LB_L.js";
4
+ import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
5
+ import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
6
+ //#region extensions/slack/src/channel.setup.ts
7
+ const slackSetupWizard = createSlackSetupWizardProxy(async () => ({ slackSetupWizard: (await import("./setup-surface-D88QBVOW.js")).slackSetupWizard }));
8
+ const slackSetupConfigAdapter = createScopedChannelConfigAdapter({
9
+ sectionKey: SLACK_CHANNEL,
10
+ listAccountIds: listSlackAccountIds,
11
+ resolveAccount: adaptScopedAccountAccessor(resolveSlackAccount),
12
+ resolveAccessorAccount: resolveSlackConfigAccessorAccount,
13
+ defaultAccountId: resolveDefaultSlackAccountId,
14
+ clearBaseFields: [
15
+ "botToken",
16
+ "appToken",
17
+ "name"
18
+ ],
19
+ resolveAllowFrom: (account) => account.allowFrom,
20
+ formatAllowFrom: (allowFrom) => formatAllowFromLowercase({ allowFrom }),
21
+ resolveDefaultTo: (account) => account.defaultTo
22
+ });
23
+ const slackSetupPlugin = {
24
+ id: SLACK_CHANNEL,
25
+ meta: {
26
+ id: SLACK_CHANNEL,
27
+ label: "Slack",
28
+ selectionLabel: "Slack (Socket Mode)",
29
+ detailLabel: "Slack Bot",
30
+ docsPath: "/channels/slack",
31
+ docsLabel: "slack",
32
+ blurb: "supported (Socket Mode).",
33
+ systemImage: "number",
34
+ markdownCapable: true,
35
+ preferSessionLookupForAnnounceTarget: true
36
+ },
37
+ setupWizard: slackSetupWizard,
38
+ capabilities: {
39
+ chatTypes: [
40
+ "direct",
41
+ "channel",
42
+ "thread"
43
+ ],
44
+ reactions: true,
45
+ threads: true,
46
+ media: true,
47
+ nativeCommands: true
48
+ },
49
+ commands: {
50
+ nativeCommandsAutoEnabled: false,
51
+ nativeSkillsAutoEnabled: false,
52
+ resolveNativeCommandName: ({ commandKey, defaultName }) => commandKey === "status" ? "agentstatus" : defaultName
53
+ },
54
+ streaming: { blockStreamingCoalesceDefaults: {
55
+ minChars: 1500,
56
+ idleMs: 1e3
57
+ } },
58
+ reload: { configPrefixes: ["channels.slack"] },
59
+ configSchema: SlackChannelConfigSchema,
60
+ config: {
61
+ ...slackSetupConfigAdapter,
62
+ hasConfiguredState: ({ env }) => [
63
+ "SLACK_APP_TOKEN",
64
+ "SLACK_BOT_TOKEN",
65
+ "SLACK_USER_TOKEN"
66
+ ].some((key) => typeof env?.[key] === "string" && env[key]?.trim().length > 0),
67
+ isConfigured: (account) => isSlackSetupAccountConfigured(account),
68
+ describeAccount: (account) => describeSlackSetupAccount(account)
69
+ },
70
+ setup: slackSetupAdapter
71
+ };
72
+ //#endregion
73
+ export { slackSetupPlugin as t };
@@ -0,0 +1,103 @@
1
+ import { createHash } from "node:crypto";
2
+ import { WebClient } from "@slack/web-api";
3
+ import { HttpsProxyAgent } from "https-proxy-agent";
4
+ import { resolveEnvHttpProxyUrl } from "openclaw/plugin-sdk/fetch-runtime";
5
+ //#region extensions/slack/src/client-options.ts
6
+ const SLACK_DEFAULT_RETRY_OPTIONS = {
7
+ retries: 2,
8
+ factor: 2,
9
+ minTimeout: 500,
10
+ maxTimeout: 3e3,
11
+ randomize: true
12
+ };
13
+ const SLACK_WRITE_RETRY_OPTIONS = { retries: 0 };
14
+ /**
15
+ * Check whether a hostname is excluded from proxying by `NO_PROXY` / `no_proxy`.
16
+ * Supports comma-separated entries with optional leading dots (e.g. `.slack.com`).
17
+ */
18
+ function isHostExcludedByNoProxy(hostname, env = process.env) {
19
+ const raw = env.no_proxy ?? env.NO_PROXY;
20
+ if (!raw) return false;
21
+ const entries = raw.split(/[,\s]+/).map((e) => e.trim().toLowerCase()).filter(Boolean);
22
+ const lower = hostname.toLowerCase();
23
+ for (const entry of entries) {
24
+ if (entry === "*") return true;
25
+ const bare = entry.startsWith("*.") ? entry.slice(2) : entry.startsWith(".") ? entry.slice(1) : entry;
26
+ if (lower === bare || lower.endsWith(`.${bare}`)) return true;
27
+ }
28
+ return false;
29
+ }
30
+ /**
31
+ * Build an HTTPS proxy agent from env vars (HTTPS_PROXY, HTTP_PROXY, etc.)
32
+ * for use as the `agent` option in Slack WebClient and Socket Mode connections.
33
+ *
34
+ * When set, this agent is forwarded through @slack/bolt -> @slack/socket-mode ->
35
+ * SlackWebSocket as the `httpAgent`, which the `ws` library uses to tunnel the
36
+ * WebSocket upgrade request through the proxy. This fixes Socket Mode in
37
+ * environments where outbound traffic must go through an HTTP CONNECT proxy.
38
+ *
39
+ * Respects `NO_PROXY` / `no_proxy`; if `*.slack.com` (or a matching pattern)
40
+ * appears in the exclusion list, returns `undefined` so the connection is direct.
41
+ *
42
+ * Returns `undefined` when no proxy env var is configured or when Slack hosts
43
+ * are excluded by `NO_PROXY`.
44
+ */
45
+ function resolveSlackProxyAgent() {
46
+ const proxyUrl = resolveEnvHttpProxyUrl("https");
47
+ if (!proxyUrl) return;
48
+ if (isHostExcludedByNoProxy("slack.com")) return;
49
+ try {
50
+ return new HttpsProxyAgent(proxyUrl);
51
+ } catch {
52
+ return;
53
+ }
54
+ }
55
+ function resolveSlackWebClientOptions(options = {}) {
56
+ return {
57
+ ...options,
58
+ agent: options.agent ?? resolveSlackProxyAgent(),
59
+ retryConfig: options.retryConfig ?? SLACK_DEFAULT_RETRY_OPTIONS
60
+ };
61
+ }
62
+ function resolveSlackWriteClientOptions(options = {}) {
63
+ return {
64
+ ...options,
65
+ agent: options.agent ?? resolveSlackProxyAgent(),
66
+ retryConfig: options.retryConfig ?? SLACK_WRITE_RETRY_OPTIONS,
67
+ maxRequestConcurrency: options.maxRequestConcurrency ?? 1
68
+ };
69
+ }
70
+ //#endregion
71
+ //#region extensions/slack/src/client.ts
72
+ const SLACK_WRITE_CLIENT_CACHE_MAX = 32;
73
+ const slackWriteClientCache = /* @__PURE__ */ new Map();
74
+ function createSlackWebClient(token, options = {}) {
75
+ return new WebClient(token, resolveSlackWebClientOptions(options));
76
+ }
77
+ function createSlackWriteClient(token, options = {}) {
78
+ return new WebClient(token, resolveSlackWriteClientOptions(options));
79
+ }
80
+ function createSlackTokenCacheKey(token) {
81
+ return `sha256:${createHash("sha256").update(token).digest("base64url")}`;
82
+ }
83
+ function getSlackWriteClient(token) {
84
+ const tokenKey = createSlackTokenCacheKey(token);
85
+ const cached = slackWriteClientCache.get(tokenKey);
86
+ if (cached) {
87
+ slackWriteClientCache.delete(tokenKey);
88
+ slackWriteClientCache.set(tokenKey, cached);
89
+ return cached;
90
+ }
91
+ const client = createSlackWriteClient(token);
92
+ if (slackWriteClientCache.size >= SLACK_WRITE_CLIENT_CACHE_MAX) {
93
+ const oldestTokenKey = slackWriteClientCache.keys().next().value;
94
+ if (oldestTokenKey) slackWriteClientCache.delete(oldestTokenKey);
95
+ }
96
+ slackWriteClientCache.set(tokenKey, client);
97
+ return client;
98
+ }
99
+ function clearSlackWriteClientCacheForTest() {
100
+ slackWriteClientCache.clear();
101
+ }
102
+ //#endregion
103
+ export { getSlackWriteClient as a, resolveSlackWebClientOptions as c, createSlackWriteClient as i, resolveSlackWriteClientOptions as l, createSlackTokenCacheKey as n, SLACK_DEFAULT_RETRY_OPTIONS as o, createSlackWebClient as r, SLACK_WRITE_RETRY_OPTIONS as s, clearSlackWriteClientCacheForTest as t };
@@ -0,0 +1,2 @@
1
+ import { SlackConfigSchema, buildChannelConfigSchema } from "openclaw/plugin-sdk/bundled-channel-config-schema";
2
+ export { buildChannelConfigSchema as n, SlackConfigSchema as t };
@@ -0,0 +1,167 @@
1
+ import { n as buildChannelConfigSchema, t as SlackConfigSchema } from "./config-api-B_jq4NJW.js";
2
+ //#endregion
3
+ //#region extensions/slack/src/config-schema.ts
4
+ const SlackChannelConfigSchema = buildChannelConfigSchema(SlackConfigSchema, { uiHints: {
5
+ "": {
6
+ label: "Slack",
7
+ help: "Slack channel provider configuration for bot/app tokens, streaming behavior, and DM policy controls. Keep token handling and thread behavior explicit to avoid noisy workspace interactions."
8
+ },
9
+ "dm.policy": {
10
+ label: "Slack DM Policy",
11
+ help: "Direct message access control (\"pairing\" recommended). \"open\" requires channels.slack.allowFrom=[\"*\"] (legacy: channels.slack.dm.allowFrom)."
12
+ },
13
+ dmPolicy: {
14
+ label: "Slack DM Policy",
15
+ help: "Direct message access control (\"pairing\" recommended). \"open\" requires channels.slack.allowFrom=[\"*\"]."
16
+ },
17
+ configWrites: {
18
+ label: "Slack Config Writes",
19
+ help: "Allow Slack to write config in response to channel events/commands (default: true)."
20
+ },
21
+ "commands.native": {
22
+ label: "Slack Native Commands",
23
+ help: "Override native commands for Slack (bool or \"auto\")."
24
+ },
25
+ "commands.nativeSkills": {
26
+ label: "Slack Native Skill Commands",
27
+ help: "Override native skill commands for Slack (bool or \"auto\")."
28
+ },
29
+ allowBots: {
30
+ label: "Slack Allow Bot Messages",
31
+ help: "Allow bot-authored messages to trigger Slack replies (default: false)."
32
+ },
33
+ socketMode: {
34
+ label: "Slack Socket Mode Transport",
35
+ help: "Slack Socket Mode transport tuning passed to the Slack SDK. Use only when investigating ping/pong timeout or stale websocket behavior."
36
+ },
37
+ "socketMode.clientPingTimeout": {
38
+ label: "Slack Socket Mode Pong Timeout",
39
+ help: "Milliseconds the Slack SDK waits for a pong after its client ping before treating the websocket as stale (OpenClaw default: 15000). Increase on hosts with event-loop starvation or slow network scheduling."
40
+ },
41
+ "socketMode.serverPingTimeout": {
42
+ label: "Slack Socket Mode Server Ping Timeout",
43
+ help: "Milliseconds the Slack SDK waits for Slack server pings before treating the websocket as stale."
44
+ },
45
+ "socketMode.pingPongLoggingEnabled": {
46
+ label: "Slack Socket Mode Ping/Pong Logging",
47
+ help: "Enable Slack SDK ping/pong transport logs while debugging Socket Mode websocket health."
48
+ },
49
+ botToken: {
50
+ label: "Slack Bot Token",
51
+ help: "Slack bot token used for standard chat actions in the configured workspace. Keep this credential scoped and rotate if workspace app permissions change."
52
+ },
53
+ appToken: {
54
+ label: "Slack App Token",
55
+ help: "Slack app-level token used for Socket Mode connections and event transport when enabled. Use least-privilege app scopes and store this token as a secret."
56
+ },
57
+ userToken: {
58
+ label: "Slack User Token",
59
+ help: "Optional Slack user token for workflows requiring user-context API access beyond bot permissions. Use sparingly and audit scopes because this token can carry broader authority."
60
+ },
61
+ userTokenReadOnly: {
62
+ label: "Slack User Token Read Only",
63
+ help: "When true, treat configured Slack user token usage as read-only helper behavior where possible. Keep enabled if you only need supplemental reads without user-context writes."
64
+ },
65
+ "capabilities.interactiveReplies": {
66
+ label: "Slack Interactive Replies",
67
+ help: "Enable agent-authored Slack interactive reply directives (`[[slack_buttons: ...]]`, `[[slack_select: ...]]`). Default: false."
68
+ },
69
+ execApprovals: {
70
+ label: "Slack Exec Approvals",
71
+ help: "Slack-native exec approval routing and approver authorization. When unset, OpenClaw auto-enables DM-first native approvals if approvers can be resolved for this workspace account."
72
+ },
73
+ "execApprovals.enabled": {
74
+ label: "Slack Exec Approvals Enabled",
75
+ help: "Controls Slack native exec approvals for this account: unset or \"auto\" enables DM-first native approvals when approvers can be resolved, true forces native approvals on, and false disables them."
76
+ },
77
+ "execApprovals.approvers": {
78
+ label: "Slack Exec Approval Approvers",
79
+ help: "Slack user IDs allowed to approve exec requests for this workspace account. Use Slack user IDs or user targets such as `U123`, `user:U123`, or `<@U123>`. If you leave this unset, OpenClaw falls back to commands.ownerAllowFrom when possible."
80
+ },
81
+ "execApprovals.agentFilter": {
82
+ label: "Slack Exec Approval Agent Filter",
83
+ help: "Optional allowlist of agent IDs eligible for Slack exec approvals, for example `[\"main\", \"ops-agent\"]`. Use this to keep approval prompts scoped to the agents you actually operate from Slack."
84
+ },
85
+ "execApprovals.sessionFilter": {
86
+ label: "Slack Exec Approval Session Filter",
87
+ help: "Optional session-key filters matched as substring or regex-style patterns before Slack approval routing is used. Use narrow patterns so Slack approvals only appear for intended sessions."
88
+ },
89
+ "execApprovals.target": {
90
+ label: "Slack Exec Approval Target",
91
+ help: "Controls where Slack approval prompts are sent: \"dm\" sends to approver DMs (default), \"channel\" sends to the originating Slack chat/thread, and \"both\" sends to both. Channel delivery exposes the command text to the chat, so only use it in trusted channels."
92
+ },
93
+ streaming: {
94
+ label: "Slack Streaming Mode",
95
+ help: "Unified Slack stream preview mode: \"off\" | \"partial\" | \"block\" | \"progress\". Legacy boolean/streamMode keys are auto-mapped."
96
+ },
97
+ "streaming.mode": {
98
+ label: "Slack Streaming Mode",
99
+ help: "Canonical Slack preview mode: \"off\" | \"partial\" | \"block\" | \"progress\"."
100
+ },
101
+ "streaming.chunkMode": {
102
+ label: "Slack Chunk Mode",
103
+ help: "Chunking mode for outbound Slack text delivery: \"length\" (default) or \"newline\"."
104
+ },
105
+ "streaming.block.enabled": {
106
+ label: "Slack Block Streaming Enabled",
107
+ help: "Enable chunked block-style Slack preview delivery when channels.slack.streaming.mode=\"block\"."
108
+ },
109
+ "streaming.block.coalesce": {
110
+ label: "Slack Block Streaming Coalesce",
111
+ help: "Merge streamed Slack block replies before final delivery."
112
+ },
113
+ "streaming.nativeTransport": {
114
+ label: "Slack Native Streaming",
115
+ help: "Enable native Slack text streaming (chat.startStream/chat.appendStream/chat.stopStream) when channels.slack.streaming.mode is partial (default: true). Native streaming and Slack assistant thread status require a reply thread target; top-level DMs can still use draft post-and-edit preview streaming."
116
+ },
117
+ "streaming.preview.toolProgress": {
118
+ label: "Slack Draft Tool Progress",
119
+ help: "Show tool/progress activity in the live draft preview message (default: true). Set false to hide interim tool updates while the draft preview stays active."
120
+ },
121
+ "streaming.preview.commandText": {
122
+ label: "Slack Draft Command Text",
123
+ help: "Command/exec detail in preview tool-progress lines: \"raw\" preserves released behavior; \"status\" shows only the tool label."
124
+ },
125
+ "streaming.progress.label": {
126
+ label: "Slack Progress Label",
127
+ help: "Initial progress draft title. Use \"auto\" for built-in single-word labels, a custom string, or false to hide the title."
128
+ },
129
+ "streaming.progress.labels": {
130
+ label: "Slack Progress Label Pool",
131
+ help: "Candidate labels for streaming.progress.label=\"auto\". Leave unset to use OpenClaw built-in progress labels."
132
+ },
133
+ "streaming.progress.maxLines": {
134
+ label: "Slack Progress Max Lines",
135
+ help: "Maximum number of compact progress lines to keep below the draft label (default: 8)."
136
+ },
137
+ "streaming.progress.render": {
138
+ label: "Slack Progress Renderer",
139
+ help: "Progress draft renderer: \"text\" uses one portable text body; \"rich\" renders structured Slack Block Kit fields with the same text fallback."
140
+ },
141
+ "streaming.progress.toolProgress": {
142
+ label: "Slack Progress Tool Lines",
143
+ help: "Show compact tool/progress lines in progress draft mode (default: true). Set false to keep only the label until final delivery."
144
+ },
145
+ "streaming.progress.commandText": {
146
+ label: "Slack Progress Command Text",
147
+ help: "Command/exec detail in progress draft lines: \"raw\" preserves released behavior; \"status\" shows only the tool label."
148
+ },
149
+ "thread.historyScope": {
150
+ label: "Slack Thread History Scope",
151
+ help: "Scope for Slack thread history context (\"thread\" isolates per thread; \"channel\" reuses channel history)."
152
+ },
153
+ "thread.inheritParent": {
154
+ label: "Slack Thread Parent Inheritance",
155
+ help: "If true, Slack thread sessions inherit the parent channel transcript (default: false)."
156
+ },
157
+ "thread.initialHistoryLimit": {
158
+ label: "Slack Thread Initial History Limit",
159
+ help: "Maximum number of existing Slack thread messages to fetch when starting a new thread session (default: 20, set to 0 to disable)."
160
+ },
161
+ "thread.requireExplicitMention": {
162
+ label: "Slack Thread Require Explicit Mention",
163
+ help: "If true, require an explicit @mention even inside threads where the bot has participated. Suppresses implicit thread mention behavior so the bot only responds to explicit @bot mentions in threads (default: false)."
164
+ }
165
+ } });
166
+ //#endregion
167
+ export { SlackChannelConfigSchema as t };
@@ -0,0 +1,11 @@
1
+ //#region extensions/slack/configured-state.ts
2
+ const SLACK_CONFIGURED_ENV_KEYS = [
3
+ "SLACK_APP_TOKEN",
4
+ "SLACK_BOT_TOKEN",
5
+ "SLACK_USER_TOKEN"
6
+ ];
7
+ function hasSlackConfiguredState(params) {
8
+ return SLACK_CONFIGURED_ENV_KEYS.some((key) => typeof params.env?.[key] === "string" && params.env[key]?.trim().length > 0);
9
+ }
10
+ //#endregion
11
+ export { hasSlackConfiguredState };
@@ -0,0 +1,5 @@
1
+ import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-KUjHnkQm.js";
2
+ import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-Bo6lbSkh.js";
3
+ import { n as listSlackDirectoryGroupsFromConfig, r as listSlackDirectoryPeersFromConfig } from "./directory-config-B3JiHeB7.js";
4
+ import { t as collectSlackSecurityAuditFindings } from "./security-audit-BtHGnD3d.js";
5
+ export { collectRuntimeConfigAssignments, collectSlackSecurityAuditFindings, legacyConfigRules, listSlackDirectoryGroupsFromConfig, listSlackDirectoryPeersFromConfig, normalizeCompatibilityConfig, secretTargetRegistryEntries };
@@ -0,0 +1,54 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-CiIaOW0V.js";
2
+ import { i as resolveDefaultSlackAccountId, o as resolveSlackAccountAllowFrom, r as mergeSlackAccountConfig } from "./accounts-ClAPP5ry.js";
3
+ import { r as parseSlackTarget } from "./target-parsing-CQmv-iSm.js";
4
+ import "./targets-B1tYCAr6.js";
5
+ import { normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
6
+ import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
7
+ import { createResolvedDirectoryEntriesLister } from "openclaw/plugin-sdk/directory-config-runtime";
8
+ //#region extensions/slack/src/directory-config.ts
9
+ var directory_config_exports = /* @__PURE__ */ __exportAll({
10
+ listSlackDirectoryGroupsFromConfig: () => listSlackDirectoryGroupsFromConfig,
11
+ listSlackDirectoryPeersFromConfig: () => listSlackDirectoryPeersFromConfig
12
+ });
13
+ function resolveSlackDirectoryConfigAccount(cfg, accountId) {
14
+ const resolvedAccountId = normalizeAccountId(accountId ?? resolveDefaultSlackAccountId(cfg));
15
+ const config = mergeSlackAccountConfig(cfg, resolvedAccountId);
16
+ return {
17
+ accountId: resolvedAccountId,
18
+ config,
19
+ dm: config.dm,
20
+ allowFrom: resolveSlackAccountAllowFrom({
21
+ cfg,
22
+ accountId: resolvedAccountId
23
+ }) ?? []
24
+ };
25
+ }
26
+ const listSlackDirectoryPeersFromConfig = createResolvedDirectoryEntriesLister({
27
+ kind: "user",
28
+ resolveAccount: (cfg, accountId) => resolveSlackDirectoryConfigAccount(cfg, accountId),
29
+ resolveSources: (account) => {
30
+ const channelUsers = Object.values(account.config.channels ?? {}).flatMap((channel) => channel.users ?? []);
31
+ return [
32
+ account.allowFrom,
33
+ Object.keys(account.config.dms ?? {}),
34
+ channelUsers
35
+ ];
36
+ },
37
+ normalizeId: (raw) => {
38
+ const normalizedUserId = (raw.match(/^<@([A-Z0-9]+)>$/i)?.[1] ?? raw).replace(/^(slack|user):/i, "").trim();
39
+ if (!normalizedUserId) return null;
40
+ const normalized = parseSlackTarget(`user:${normalizedUserId}`, { defaultKind: "user" });
41
+ return normalized?.kind === "user" ? `user:${normalizeLowercaseStringOrEmpty(normalized.id)}` : null;
42
+ }
43
+ });
44
+ const listSlackDirectoryGroupsFromConfig = createResolvedDirectoryEntriesLister({
45
+ kind: "group",
46
+ resolveAccount: (cfg, accountId) => resolveSlackDirectoryConfigAccount(cfg, accountId),
47
+ resolveSources: (account) => [Object.keys(account.config.channels ?? {})],
48
+ normalizeId: (raw) => {
49
+ const normalized = parseSlackTarget(raw, { defaultKind: "channel" });
50
+ return normalized?.kind === "channel" ? `channel:${normalizeLowercaseStringOrEmpty(normalized.id)}` : null;
51
+ }
52
+ });
53
+ //#endregion
54
+ export { listSlackDirectoryGroupsFromConfig as n, listSlackDirectoryPeersFromConfig as r, directory_config_exports as t };
@@ -0,0 +1,2 @@
1
+ import { n as listSlackDirectoryGroupsFromConfig, r as listSlackDirectoryPeersFromConfig } from "./directory-config-B3JiHeB7.js";
2
+ export { listSlackDirectoryGroupsFromConfig, listSlackDirectoryPeersFromConfig };
@@ -0,0 +1,133 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-CiIaOW0V.js";
2
+ import { a as resolveSlackAccount } from "./accounts-ClAPP5ry.js";
3
+ import { r as createSlackWebClient } from "./client-CPe4GmDR.js";
4
+ import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
5
+ //#region extensions/slack/src/directory-live.ts
6
+ var directory_live_exports = /* @__PURE__ */ __exportAll({
7
+ getSlackDirectorySelfLive: () => getSlackDirectorySelfLive,
8
+ listSlackDirectoryGroupsLive: () => listSlackDirectoryGroupsLive,
9
+ listSlackDirectoryPeersLive: () => listSlackDirectoryPeersLive
10
+ });
11
+ function resolveReadToken(params) {
12
+ const account = resolveSlackAccount({
13
+ cfg: params.cfg,
14
+ accountId: params.accountId
15
+ });
16
+ return account.userToken ?? account.botToken?.trim();
17
+ }
18
+ function normalizeQuery(value) {
19
+ return normalizeLowercaseStringOrEmpty(value);
20
+ }
21
+ function buildUserRank(user) {
22
+ let rank = 0;
23
+ if (!user.deleted) rank += 2;
24
+ if (!user.is_bot && !user.is_app_user) rank += 1;
25
+ return rank;
26
+ }
27
+ function buildChannelRank(channel) {
28
+ return channel.is_archived ? 0 : 1;
29
+ }
30
+ function slackUserToDirectoryEntry(user, fallback) {
31
+ const id = normalizeOptionalString(user.id) ?? normalizeOptionalString(fallback?.id);
32
+ if (!id) return null;
33
+ const handle = normalizeOptionalString(user.name) ?? normalizeOptionalString(fallback?.name);
34
+ const display = normalizeOptionalString(user.profile?.display_name) || normalizeOptionalString(user.profile?.real_name) || normalizeOptionalString(user.real_name) || handle;
35
+ return {
36
+ kind: "user",
37
+ id: `user:${id}`,
38
+ name: display || void 0,
39
+ handle: handle ? `@${handle}` : void 0,
40
+ rank: buildUserRank(user),
41
+ raw: user
42
+ };
43
+ }
44
+ async function getSlackDirectorySelfLive(params) {
45
+ const token = resolveReadToken(params);
46
+ if (!token) return null;
47
+ const client = createSlackWebClient(token);
48
+ const auth = await client.auth.test();
49
+ const userId = normalizeOptionalString(auth.user_id);
50
+ if (!userId) return null;
51
+ try {
52
+ return slackUserToDirectoryEntry((await client.users.info({ user: userId })).user ?? {}, {
53
+ id: userId,
54
+ name: auth.user
55
+ });
56
+ } catch {
57
+ return slackUserToDirectoryEntry({
58
+ id: userId,
59
+ name: auth.user
60
+ }, {
61
+ id: userId,
62
+ name: auth.user
63
+ });
64
+ }
65
+ }
66
+ async function listSlackDirectoryPeersLive(params) {
67
+ const token = resolveReadToken(params);
68
+ if (!token) return [];
69
+ const client = createSlackWebClient(token);
70
+ const query = normalizeQuery(params.query);
71
+ const members = [];
72
+ let cursor;
73
+ do {
74
+ const res = await client.users.list({
75
+ limit: 200,
76
+ cursor
77
+ });
78
+ if (Array.isArray(res.members)) members.push(...res.members);
79
+ const next = res.response_metadata?.next_cursor?.trim();
80
+ cursor = next ? next : void 0;
81
+ } while (cursor);
82
+ const rows = members.filter((member) => {
83
+ const candidates = [
84
+ member.profile?.display_name || member.profile?.real_name || member.real_name,
85
+ member.name,
86
+ member.profile?.email
87
+ ].map((item) => normalizeOptionalLowercaseString(item)).filter(Boolean);
88
+ if (!query) return true;
89
+ return candidates.some((candidate) => candidate?.includes(query));
90
+ }).map((member) => slackUserToDirectoryEntry(member)).filter(Boolean);
91
+ if (typeof params.limit === "number" && params.limit > 0) return rows.slice(0, params.limit);
92
+ return rows;
93
+ }
94
+ async function listSlackDirectoryGroupsLive(params) {
95
+ const token = resolveReadToken(params);
96
+ if (!token) return [];
97
+ const client = createSlackWebClient(token);
98
+ const query = normalizeQuery(params.query);
99
+ const channels = [];
100
+ let cursor;
101
+ do {
102
+ const res = await client.conversations.list({
103
+ types: "public_channel,private_channel",
104
+ exclude_archived: false,
105
+ limit: 1e3,
106
+ cursor
107
+ });
108
+ if (Array.isArray(res.channels)) channels.push(...res.channels);
109
+ const next = res.response_metadata?.next_cursor?.trim();
110
+ cursor = next ? next : void 0;
111
+ } while (cursor);
112
+ const rows = channels.filter((channel) => {
113
+ const name = normalizeOptionalLowercaseString(channel.name);
114
+ if (!query) return true;
115
+ return Boolean(name && name.includes(query));
116
+ }).map((channel) => {
117
+ const id = channel.id?.trim();
118
+ const name = channel.name?.trim();
119
+ if (!id || !name) return null;
120
+ return {
121
+ kind: "group",
122
+ id: `channel:${id}`,
123
+ name,
124
+ handle: `#${name}`,
125
+ rank: buildChannelRank(channel),
126
+ raw: channel
127
+ };
128
+ }).filter(Boolean);
129
+ if (typeof params.limit === "number" && params.limit > 0) return rows.slice(0, params.limit);
130
+ return rows;
131
+ }
132
+ //#endregion
133
+ export { listSlackDirectoryGroupsLive as n, listSlackDirectoryPeersLive as r, directory_live_exports as t };