@openclaw/slack 2026.7.2-beta.2 → 2026.7.2-beta.4
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.
- package/dist/{account-configured-DzC407uv.js → account-configured-BwfXBo_F.js} +1 -1
- package/dist/account-inspect-api.js +1 -1
- package/dist/{account-inspect-Di7ditqZ.js → account-inspect-jn1xLaVi.js} +9 -2
- package/dist/account-reply-mode-DrUXogvO.js +14 -0
- package/dist/{accounts-BOJJiHSr.js → accounts-BSr252c_.js} +13 -25
- package/dist/accounts.runtime-CjULMLTa.js +2 -0
- package/dist/{action-runtime-Cee2ih0s.js → action-runtime-CFU52n4W.js} +11 -17
- package/dist/action-runtime.runtime-9-17zvKH.js +2 -0
- package/dist/{actions-BZiuSTIq.js → actions-D51foiwR.js} +5 -5
- package/dist/{actions.runtime-DoD0-gxw.js → actions.runtime-BMJwtf5C.js} +1 -1
- package/dist/api.js +15 -15
- package/dist/{approval-handler.runtime-CUPtIM4k.js → approval-handler.runtime-3b4-wxMl.js} +2 -2
- package/dist/{channel-DaIiGUOp.js → channel-Ds8NKvfr.js} +75 -41
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-type-Cfm6_6n1.js → channel-type-DXkUajFP.js} +3 -3
- package/dist/{channel.setup-C-mLz50O.js → channel.setup-DOSTEDfA.js} +8 -5
- package/dist/{config-schema-xPSnK2VK.js → config-schema-B4j4tCOI.js} +236 -30
- package/dist/{directory-config-DRkFujwG.js → directory-config-B08pm5ZT.js} +1 -1
- package/dist/directory-contract-api.js +1 -1
- package/dist/{directory-live-D_yZhjgp.js → directory-live-DpPKzPrn.js} +2 -2
- package/dist/doctor-contract-U6oVntbM.js +173 -0
- package/dist/doctor-contract-api.js +1 -1
- package/dist/{group-policy-85UWiriS.js → group-policy-CdnQzQBI.js} +98 -125
- package/dist/{interactive-replies-BilWUdcI.js → interactive-replies-C3ffk6oN.js} +1 -1
- package/dist/interactive-replies-api.js +1 -1
- package/dist/{message-tool-api-CA9jZrCY.js → message-tool-api-ByVyIVOh.js} +3 -3
- package/dist/message-tool-api.js +1 -1
- package/dist/{monitor-CalGciTs.js → monitor-CnB_WKvF.js} +3 -3
- package/dist/{outbound-adapter-BiLKcnyH.js → outbound-adapter-DuPz2HHt.js} +49 -5
- package/dist/{pipeline.runtime-DofAvTtb.js → pipeline.runtime-5rRYZuX5.js} +490 -345
- package/dist/{policy-BVs4LiSa.js → policy-C31RYSuT.js} +1 -1
- package/dist/probe-CVRuArHA.js +340 -0
- package/dist/{provider-CmeoUiIM.js → provider-htuIJGFD.js} +791 -359
- package/dist/{relay-source-DMmgtvg4.js → relay-source-Df9EaiTF.js} +6 -11
- package/dist/{replies-CJJCp6qz.js → replies-Cgr2Gli4.js} +3 -3
- package/dist/{resolve-channels-Rfts6POK.js → resolve-channels-DodP2TFx.js} +1 -1
- package/dist/{resolve-users-y6wAxR8E.js → resolve-users-M9eF8891.js} +1 -1
- package/dist/{runtime-api-BGDyOt1D.js → runtime-api-D5XYMMsf.js} +3 -2
- package/dist/runtime-api.js +11 -11
- package/dist/{scopes-CuxNQZ6v.js → scopes-CJRpHkDC.js} +1 -2
- package/dist/{secret-contract-CMohXFWS.js → secret-contract-DxmvbxBF.js} +1 -0
- package/dist/secret-contract-api.js +1 -1
- package/dist/{security-audit-CikQhBUY.js → security-audit-Cz6erklv.js} +0 -10
- package/dist/security-contract-api.js +1 -1
- package/dist/{send-DYp8ca-l.js → send-BZ1tPv7-.js} +28 -11
- package/dist/send.runtime-a2pilFor.js +2 -0
- package/dist/setup-core-tPxMuFez.js +600 -0
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-oSd3NX9J.js → setup-surface-wV-S1dE_.js} +58 -32
- package/dist/{shared-D9yz5Otg.js → shared-BfMskaMx.js} +57 -10
- package/dist/{slash-dispatch.runtime-CSja9VuD.js → slash-dispatch.runtime-lfeIsXTX.js} +1 -1
- package/node_modules/@types/node/README.md +1 -1
- package/node_modules/@types/node/fs/promises.d.ts +16 -6
- package/node_modules/@types/node/package.json +2 -2
- package/node_modules/agent-base/README.md +145 -0
- package/node_modules/agent-base/dist/src/index.d.ts +78 -0
- package/node_modules/agent-base/dist/src/index.js +203 -0
- package/node_modules/agent-base/dist/src/index.js.map +1 -0
- package/node_modules/agent-base/dist/src/promisify.d.ts +4 -0
- package/node_modules/agent-base/dist/src/promisify.js +18 -0
- package/node_modules/agent-base/dist/src/promisify.js.map +1 -0
- package/node_modules/agent-base/package.json +64 -0
- package/node_modules/agent-base/src/index.ts +345 -0
- package/node_modules/agent-base/src/promisify.ts +33 -0
- package/node_modules/axios/CHANGELOG.md +197 -1
- package/node_modules/axios/README.md +424 -256
- package/node_modules/axios/dist/axios.js +589 -204
- package/node_modules/axios/dist/axios.min.js +3 -3
- package/node_modules/axios/dist/axios.min.js.map +1 -1
- package/node_modules/axios/dist/browser/axios.cjs +630 -185
- package/node_modules/axios/dist/esm/axios.js +630 -185
- package/node_modules/axios/dist/esm/axios.min.js +2 -2
- package/node_modules/axios/dist/esm/axios.min.js.map +1 -1
- package/node_modules/axios/dist/node/axios.cjs +949 -301
- package/node_modules/axios/index.d.cts +28 -5
- package/node_modules/axios/index.d.ts +24 -3
- package/node_modules/axios/lib/adapters/adapters.js +1 -1
- package/node_modules/axios/lib/adapters/fetch.js +223 -49
- package/node_modules/axios/lib/adapters/http.js +408 -193
- package/node_modules/axios/lib/adapters/xhr.js +3 -1
- package/node_modules/axios/lib/core/Axios.js +4 -2
- package/node_modules/axios/lib/core/AxiosError.js +13 -1
- package/node_modules/axios/lib/core/AxiosHeaders.js +13 -42
- package/node_modules/axios/lib/core/buildFullPath.js +29 -1
- package/node_modules/axios/lib/core/mergeConfig.js +35 -0
- package/node_modules/axios/lib/defaults/transitional.js +2 -0
- package/node_modules/axios/lib/env/data.js +1 -1
- package/node_modules/axios/lib/helpers/AxiosURLSearchParams.js +1 -3
- package/node_modules/axios/lib/helpers/Http2Sessions.js +119 -0
- package/node_modules/axios/lib/helpers/buildURL.js +7 -4
- package/node_modules/axios/lib/helpers/composeSignals.js +48 -47
- package/node_modules/axios/lib/helpers/cookies.js +5 -1
- package/node_modules/axios/lib/helpers/estimateDataURLDecodedBytes.js +16 -11
- package/node_modules/axios/lib/helpers/formDataToJSON.js +26 -4
- package/node_modules/axios/lib/helpers/formDataToStream.js +2 -2
- package/node_modules/axios/lib/helpers/fromDataURI.js +20 -5
- package/node_modules/axios/lib/helpers/progressEventReducer.js +3 -0
- package/node_modules/axios/lib/helpers/resolveConfig.js +26 -13
- package/node_modules/axios/lib/helpers/sanitizeHeaderValue.js +60 -0
- package/node_modules/axios/lib/helpers/shouldBypassProxy.js +33 -1
- package/node_modules/axios/lib/helpers/toFormData.js +48 -12
- package/node_modules/axios/lib/helpers/validator.js +1 -1
- package/node_modules/axios/lib/utils.js +105 -19
- package/node_modules/axios/package.json +31 -13
- package/node_modules/https-proxy-agent/README.md +137 -0
- package/node_modules/https-proxy-agent/dist/agent.d.ts +30 -0
- package/node_modules/https-proxy-agent/dist/agent.js +177 -0
- package/node_modules/https-proxy-agent/dist/agent.js.map +1 -0
- package/node_modules/https-proxy-agent/dist/index.d.ts +23 -0
- package/node_modules/https-proxy-agent/dist/index.js +14 -0
- package/node_modules/https-proxy-agent/dist/index.js.map +1 -0
- package/node_modules/https-proxy-agent/dist/parse-proxy-response.d.ts +7 -0
- package/node_modules/https-proxy-agent/dist/parse-proxy-response.js +66 -0
- package/node_modules/https-proxy-agent/dist/parse-proxy-response.js.map +1 -0
- package/node_modules/https-proxy-agent/package.json +56 -0
- package/node_modules/iconv-lite/encodings/sbcs-data.js +2 -0
- package/node_modules/iconv-lite/encodings/utf32.js +10 -3
- package/node_modules/iconv-lite/package.json +2 -2
- package/node_modules/iconv-lite/types/encodings.d.ts +2 -0
- package/node_modules/path-to-regexp/Readme.md +3 -3
- package/node_modules/path-to-regexp/dist/index.js +135 -158
- package/node_modules/path-to-regexp/dist/index.js.map +1 -1
- package/node_modules/path-to-regexp/package.json +2 -2
- package/node_modules/qs/CHANGELOG.md +11 -0
- package/node_modules/qs/dist/qs.js +17 -17
- package/node_modules/qs/lib/parse.js +19 -8
- package/node_modules/qs/lib/utils.js +47 -8
- package/node_modules/qs/package.json +6 -5
- package/node_modules/qs/test/parse.js +230 -0
- package/node_modules/qs/test/utils.js +194 -0
- package/node_modules/typebox/build/compile/validator.d.mts +1 -4
- package/node_modules/typebox/build/guard/guard.d.mts +1 -1
- package/node_modules/typebox/build/guard/guard.mjs +5 -2
- package/node_modules/typebox/build/guard/string.mjs +16 -4
- package/node_modules/typebox/build/schema/engine/_functions.mjs +34 -15
- package/node_modules/typebox/build/type/action/readonly_object.d.mts +5 -0
- package/node_modules/typebox/build/type/action/readonly_object.mjs +8 -0
- package/node_modules/typebox/build/typebox.d.mts +1 -1
- package/node_modules/typebox/build/typebox.mjs +1 -1
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/typebox/readme.md +29 -32
- package/node_modules/ws/lib/receiver.js +15 -32
- package/node_modules/ws/lib/websocket-server.js +4 -4
- package/node_modules/ws/lib/websocket.js +4 -4
- package/node_modules/ws/package.json +5 -1
- package/npm-shrinkwrap.json +54 -27
- package/openclaw.plugin.json +1331 -1424
- package/package.json +92 -14
- package/dist/accounts.runtime-KvftRRek.js +0 -2
- package/dist/action-runtime.runtime-DZfd7IFr.js +0 -2
- package/dist/client-WIPAS3Yr.js +0 -160
- package/dist/config-api-Df9a1B8C.js +0 -3
- package/dist/doctor-contract-DddfkMlF.js +0 -134
- package/dist/probe-CN0ssfLN.js +0 -48
- package/dist/send.runtime-CJLxAt26.js +0 -2
- package/dist/setup-core-CkwVLzFO.js +0 -337
- package/node_modules/axios/dist/axios.js.map +0 -1
- package/node_modules/axios/dist/browser/axios.cjs.map +0 -1
- package/node_modules/axios/dist/esm/axios.js.map +0 -1
- package/node_modules/axios/dist/node/axios.cjs.map +0 -1
|
@@ -0,0 +1,600 @@
|
|
|
1
|
+
import { t as inspectSlackAccount } from "./account-inspect-jn1xLaVi.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 { defineChannelSetupContract } from "openclaw/plugin-sdk/channel-setup";
|
|
6
|
+
import { DEFAULT_ACCOUNT_ID, createAccountScopedAllowFromSection, createAccountScopedGroupAccessSection, createAllowlistSetupWizardProxy, createPatchedAccountSetupAdapter, createSetupTranslator, createStandardChannelSetupStatus, defineTokenCredential, mergeAllowFromEntries, parseMentionOrPrefixedId, patchChannelConfigForAccount, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup-runtime";
|
|
7
|
+
import { formatDocsLink } from "openclaw/plugin-sdk/setup-tools";
|
|
8
|
+
import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
|
|
9
|
+
//#region extensions/slack/src/setup-shared.ts
|
|
10
|
+
const SLACK_CHANNEL = "slack";
|
|
11
|
+
function buildSlackManifest(botName = "OpenClaw") {
|
|
12
|
+
const safeName = botName.trim() || "OpenClaw";
|
|
13
|
+
const manifest = {
|
|
14
|
+
display_information: {
|
|
15
|
+
name: safeName,
|
|
16
|
+
description: `${safeName} connector for OpenClaw`
|
|
17
|
+
},
|
|
18
|
+
features: {
|
|
19
|
+
bot_user: {
|
|
20
|
+
display_name: safeName,
|
|
21
|
+
always_online: true
|
|
22
|
+
},
|
|
23
|
+
app_home: {
|
|
24
|
+
home_tab_enabled: true,
|
|
25
|
+
messages_tab_enabled: true,
|
|
26
|
+
messages_tab_read_only_enabled: false
|
|
27
|
+
},
|
|
28
|
+
agent_view: {
|
|
29
|
+
agent_description: `${safeName} connects Slack Agent View conversations to OpenClaw agents.`,
|
|
30
|
+
suggested_prompts: [
|
|
31
|
+
{
|
|
32
|
+
title: "What can you do?",
|
|
33
|
+
message: "What can you help me with?"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
title: "Summarize this channel",
|
|
37
|
+
message: "Summarize the recent activity in this channel."
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
title: "Draft a reply",
|
|
41
|
+
message: "Help me draft a reply."
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
slash_commands: [{
|
|
46
|
+
command: "/openclaw",
|
|
47
|
+
description: "Send a message to OpenClaw",
|
|
48
|
+
should_escape: false
|
|
49
|
+
}]
|
|
50
|
+
},
|
|
51
|
+
oauth_config: { scopes: { bot: [
|
|
52
|
+
"app_mentions:read",
|
|
53
|
+
"assistant:write",
|
|
54
|
+
"channels:history",
|
|
55
|
+
"channels:read",
|
|
56
|
+
"chat:write",
|
|
57
|
+
"commands",
|
|
58
|
+
"emoji:read",
|
|
59
|
+
"files:read",
|
|
60
|
+
"files:write",
|
|
61
|
+
"groups:history",
|
|
62
|
+
"groups:read",
|
|
63
|
+
"im:history",
|
|
64
|
+
"im:read",
|
|
65
|
+
"im:write",
|
|
66
|
+
"mpim:history",
|
|
67
|
+
"mpim:read",
|
|
68
|
+
"mpim:write",
|
|
69
|
+
"pins:read",
|
|
70
|
+
"pins:write",
|
|
71
|
+
"reactions:read",
|
|
72
|
+
"reactions:write",
|
|
73
|
+
"usergroups:read",
|
|
74
|
+
"users:read"
|
|
75
|
+
] } },
|
|
76
|
+
settings: {
|
|
77
|
+
socket_mode_enabled: true,
|
|
78
|
+
event_subscriptions: { bot_events: [
|
|
79
|
+
"app_home_opened",
|
|
80
|
+
"app_mention",
|
|
81
|
+
"app_context_changed",
|
|
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 Agent View events",
|
|
104
|
+
"5) App Home -> enable the Home tab, Messages tab for DMs, and Agent 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" ? { postAs: "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.postAs;
|
|
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.postAs === "user") nextAccount.postAs = "bot";
|
|
180
|
+
else delete nextAccount.postAs;
|
|
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
|
+
const setupInput = input;
|
|
267
|
+
if (setupInput.useEnv && accountId !== DEFAULT_ACCOUNT_ID) return "Slack env tokens can only be used for the default account.";
|
|
268
|
+
const account = inspectSlackAccount({
|
|
269
|
+
cfg,
|
|
270
|
+
accountId
|
|
271
|
+
});
|
|
272
|
+
const identity = setupInput.identity ?? account.config.postAs ?? "bot";
|
|
273
|
+
const mode = setupInput.mode ?? account.config.mode ?? "socket";
|
|
274
|
+
if (identity === "user" && mode === "relay") return "Slack user identity setup supports mode \"socket\" or \"http\", not \"relay\".";
|
|
275
|
+
if (setupInput.useEnv) return identity === "user" ? "Slack user identity setup does not support --use-env; configure userToken and the transport credential explicitly." : null;
|
|
276
|
+
if (hasSlackSetupCredentials({
|
|
277
|
+
input: setupInput,
|
|
278
|
+
identity,
|
|
279
|
+
mode
|
|
280
|
+
})) return null;
|
|
281
|
+
if (identity === "user") return mode === "http" ? "Slack user identity requires --user-token and --signing-secret." : "Slack user identity requires --user-token and --app-token.";
|
|
282
|
+
return "Slack requires --bot-token and --app-token (or --use-env).";
|
|
283
|
+
},
|
|
284
|
+
buildPatch: (input) => {
|
|
285
|
+
const setupInput = input;
|
|
286
|
+
return {
|
|
287
|
+
...setupInput.identity ? { postAs: setupInput.identity } : {},
|
|
288
|
+
...setupInput.identity === "user" && setupInput.mode ? { mode: setupInput.mode } : {},
|
|
289
|
+
...setupInput.botToken ? { botToken: setupInput.botToken } : {},
|
|
290
|
+
...setupInput.appToken ? { appToken: setupInput.appToken } : {},
|
|
291
|
+
...setupInput.userToken ? { userToken: setupInput.userToken } : {},
|
|
292
|
+
...setupInput.signingSecret ? { signingSecret: setupInput.signingSecret } : {}
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
const slackSetupAdapter = {
|
|
297
|
+
...slackSetupAdapterBase,
|
|
298
|
+
singleAccountKeysToMove: ["appToken"],
|
|
299
|
+
applyAccountConfig: ({ cfg, accountId, input }) => {
|
|
300
|
+
const setupInput = input;
|
|
301
|
+
const identity = setupInput.identity ?? inspectSlackAccount({
|
|
302
|
+
cfg,
|
|
303
|
+
accountId
|
|
304
|
+
}).config.postAs;
|
|
305
|
+
return slackSetupAdapterBase.applyAccountConfig({
|
|
306
|
+
cfg,
|
|
307
|
+
accountId,
|
|
308
|
+
input: identity === "user" ? {
|
|
309
|
+
...setupInput,
|
|
310
|
+
identity
|
|
311
|
+
} : setupInput
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
const slackSetupContract = defineChannelSetupContract({
|
|
316
|
+
fields: {
|
|
317
|
+
botToken: {
|
|
318
|
+
kind: "string",
|
|
319
|
+
sensitive: true,
|
|
320
|
+
cli: {
|
|
321
|
+
flags: "--bot-token <token>",
|
|
322
|
+
description: "Slack bot token"
|
|
323
|
+
}
|
|
324
|
+
},
|
|
325
|
+
appToken: {
|
|
326
|
+
kind: "string",
|
|
327
|
+
sensitive: true,
|
|
328
|
+
cli: {
|
|
329
|
+
flags: "--app-token <token>",
|
|
330
|
+
description: "Slack app token"
|
|
331
|
+
}
|
|
332
|
+
},
|
|
333
|
+
userToken: {
|
|
334
|
+
kind: "string",
|
|
335
|
+
sensitive: true,
|
|
336
|
+
cli: {
|
|
337
|
+
flags: "--user-token <token>",
|
|
338
|
+
description: "Slack user token"
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
signingSecret: {
|
|
342
|
+
kind: "string",
|
|
343
|
+
sensitive: true,
|
|
344
|
+
cli: {
|
|
345
|
+
flags: "--signing-secret <secret>",
|
|
346
|
+
description: "Slack signing secret"
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
identity: {
|
|
350
|
+
kind: "choice",
|
|
351
|
+
choices: ["bot", "user"],
|
|
352
|
+
cli: {
|
|
353
|
+
flags: "--identity <kind>",
|
|
354
|
+
description: "Slack identity"
|
|
355
|
+
}
|
|
356
|
+
},
|
|
357
|
+
mode: {
|
|
358
|
+
kind: "choice",
|
|
359
|
+
choices: ["socket", "http"],
|
|
360
|
+
cli: {
|
|
361
|
+
flags: "--mode <mode>",
|
|
362
|
+
description: "Slack connection mode"
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
useEnv: {
|
|
366
|
+
kind: "boolean",
|
|
367
|
+
cli: {
|
|
368
|
+
flags: "--use-env",
|
|
369
|
+
description: "Use Slack environment credentials"
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
legacyAdapter: slackSetupAdapter
|
|
374
|
+
});
|
|
375
|
+
function createSlackSetupWizardBase(handlers) {
|
|
376
|
+
const slackDmPolicy = {
|
|
377
|
+
label: "Slack",
|
|
378
|
+
channel: SLACK_CHANNEL,
|
|
379
|
+
policyKey: "channels.slack.dmPolicy",
|
|
380
|
+
allowFromKey: "channels.slack.allowFrom",
|
|
381
|
+
resolveConfigKeys: (_cfg, accountId) => accountId && accountId !== DEFAULT_ACCOUNT_ID ? {
|
|
382
|
+
policyKey: `channels.slack.accounts.${accountId}.dmPolicy`,
|
|
383
|
+
allowFromKey: `channels.slack.accounts.${accountId}.allowFrom`
|
|
384
|
+
} : {
|
|
385
|
+
policyKey: "channels.slack.dmPolicy",
|
|
386
|
+
allowFromKey: "channels.slack.allowFrom"
|
|
387
|
+
},
|
|
388
|
+
getCurrent: (cfg, accountId) => inspectSlackAccount({
|
|
389
|
+
cfg,
|
|
390
|
+
accountId
|
|
391
|
+
}).config.dmPolicy ?? "pairing",
|
|
392
|
+
setPolicy: (cfg, policy, accountId) => {
|
|
393
|
+
const account = inspectSlackAccount({
|
|
394
|
+
cfg,
|
|
395
|
+
accountId
|
|
396
|
+
});
|
|
397
|
+
return patchChannelConfigForAccount({
|
|
398
|
+
cfg,
|
|
399
|
+
channel: SLACK_CHANNEL,
|
|
400
|
+
accountId: account.accountId,
|
|
401
|
+
patch: {
|
|
402
|
+
dmPolicy: policy,
|
|
403
|
+
...policy === "open" ? { allowFrom: mergeAllowFromEntries(account.config.allowFrom ?? [], ["*"]) } : {},
|
|
404
|
+
dm: {
|
|
405
|
+
...account.config.dm,
|
|
406
|
+
enabled: typeof account.config.dm?.enabled === "boolean" ? account.config.dm.enabled : true
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
},
|
|
411
|
+
promptAllowFrom: handlers.promptAllowFrom
|
|
412
|
+
};
|
|
413
|
+
return {
|
|
414
|
+
channel: SLACK_CHANNEL,
|
|
415
|
+
status: createStandardChannelSetupStatus({
|
|
416
|
+
channelLabel: "Slack",
|
|
417
|
+
configuredLabel: t("wizard.channels.statusConfigured"),
|
|
418
|
+
unconfiguredLabel: t("wizard.channels.statusNeedsTokens"),
|
|
419
|
+
configuredHint: t("wizard.channels.statusConfigured"),
|
|
420
|
+
unconfiguredHint: t("wizard.channels.statusNeedsTokens"),
|
|
421
|
+
configuredScore: 2,
|
|
422
|
+
unconfiguredScore: 1,
|
|
423
|
+
resolveConfigured: ({ cfg, accountId }) => inspectSlackAccount({
|
|
424
|
+
cfg,
|
|
425
|
+
accountId
|
|
426
|
+
}).configured
|
|
427
|
+
}),
|
|
428
|
+
prepare: async ({ cfg, accountId, prompter }) => {
|
|
429
|
+
const currentAccount = inspectSlackAccount({
|
|
430
|
+
cfg,
|
|
431
|
+
accountId
|
|
432
|
+
});
|
|
433
|
+
if (currentAccount.configured && currentAccount.config.postAs !== "user") return { cfg };
|
|
434
|
+
const identity = await prompter.select({
|
|
435
|
+
message: "How should OpenClaw appear in Slack?",
|
|
436
|
+
options: [{
|
|
437
|
+
value: "bot",
|
|
438
|
+
label: "Slack bot",
|
|
439
|
+
hint: "Post as the Slack app (default)"
|
|
440
|
+
}, {
|
|
441
|
+
value: "user",
|
|
442
|
+
label: "Slack user",
|
|
443
|
+
hint: "Post as the authorizing human"
|
|
444
|
+
}],
|
|
445
|
+
initialValue: currentAccount.config.postAs ?? "bot"
|
|
446
|
+
});
|
|
447
|
+
const next = setSlackSetupIdentity({
|
|
448
|
+
cfg,
|
|
449
|
+
accountId,
|
|
450
|
+
identity
|
|
451
|
+
});
|
|
452
|
+
if (currentAccount.configured && identity === currentAccount.config.postAs) return { cfg: next };
|
|
453
|
+
if (identity === "user") {
|
|
454
|
+
if (currentAccount.config.mode === "relay") throw new Error("Slack user identity setup supports mode \"socket\" or \"http\", not \"relay\".");
|
|
455
|
+
await prompter.note([
|
|
456
|
+
"Use a Slack user OAuth token with the User Token Scopes listed in the Slack docs.",
|
|
457
|
+
"Subscribe the companion app under 'Subscribe to events on behalf of users' using the documented user events.",
|
|
458
|
+
"Socket Mode needs an app-level token; HTTP mode needs the app signing secret.",
|
|
459
|
+
"No bot token or bot user is required.",
|
|
460
|
+
`Docs: ${formatDocsLink("/channels/slack#user-identity-post-as-a-real-person", "channels/slack")}`
|
|
461
|
+
].join("\n"), "Slack user identity");
|
|
462
|
+
} else {
|
|
463
|
+
await prompter.note(buildSlackSetupLines().join("\n"), t("wizard.slack.socketModeTokensTitle"));
|
|
464
|
+
const manifest = buildSlackManifest();
|
|
465
|
+
if (prompter.plain) await prompter.plain(manifest);
|
|
466
|
+
else await prompter.note(manifest, "Slack manifest JSON");
|
|
467
|
+
}
|
|
468
|
+
return { cfg: next };
|
|
469
|
+
},
|
|
470
|
+
envShortcut: {
|
|
471
|
+
prompt: t("wizard.slack.envPrompt"),
|
|
472
|
+
preferredEnvVar: "SLACK_BOT_TOKEN",
|
|
473
|
+
isAvailable: ({ cfg, accountId }) => accountId === DEFAULT_ACCOUNT_ID && (inspectSlackAccount({
|
|
474
|
+
cfg,
|
|
475
|
+
accountId
|
|
476
|
+
}).config.postAs ?? "bot") === "bot" && Boolean(process.env.SLACK_BOT_TOKEN?.trim()) && Boolean(process.env.SLACK_APP_TOKEN?.trim()) && !inspectSlackAccount({
|
|
477
|
+
cfg,
|
|
478
|
+
accountId
|
|
479
|
+
}).configured,
|
|
480
|
+
apply: ({ cfg, accountId }) => enableSlackAccount(cfg, accountId)
|
|
481
|
+
},
|
|
482
|
+
credentials: [
|
|
483
|
+
createSlackTokenCredential({
|
|
484
|
+
inputKey: "botToken",
|
|
485
|
+
providerHint: "slack-bot",
|
|
486
|
+
credentialLabel: t("wizard.slack.botToken"),
|
|
487
|
+
preferredEnvVar: "SLACK_BOT_TOKEN",
|
|
488
|
+
keepPrompt: t("wizard.slack.botTokenKeep"),
|
|
489
|
+
inputPrompt: t("wizard.slack.botTokenInput"),
|
|
490
|
+
shouldPrompt: ({ cfg, accountId }) => (inspectSlackAccount({
|
|
491
|
+
cfg,
|
|
492
|
+
accountId
|
|
493
|
+
}).config.postAs ?? "bot") === "bot"
|
|
494
|
+
}),
|
|
495
|
+
createSlackTokenCredential({
|
|
496
|
+
inputKey: "userToken",
|
|
497
|
+
providerHint: "slack-user",
|
|
498
|
+
credentialLabel: "Slack user OAuth token",
|
|
499
|
+
preferredEnvVar: "SLACK_USER_TOKEN",
|
|
500
|
+
keepPrompt: "Slack user OAuth token already configured. Keep it?",
|
|
501
|
+
inputPrompt: "Enter Slack user OAuth token",
|
|
502
|
+
shouldPrompt: ({ cfg, accountId }) => inspectSlackAccount({
|
|
503
|
+
cfg,
|
|
504
|
+
accountId
|
|
505
|
+
}).config.postAs === "user"
|
|
506
|
+
}),
|
|
507
|
+
createSlackTokenCredential({
|
|
508
|
+
inputKey: "appToken",
|
|
509
|
+
providerHint: "slack-app",
|
|
510
|
+
credentialLabel: t("wizard.slack.appToken"),
|
|
511
|
+
preferredEnvVar: "SLACK_APP_TOKEN",
|
|
512
|
+
keepPrompt: t("wizard.slack.appTokenKeep"),
|
|
513
|
+
inputPrompt: t("wizard.slack.appTokenInput"),
|
|
514
|
+
shouldPrompt: ({ cfg, accountId }) => {
|
|
515
|
+
const account = inspectSlackAccount({
|
|
516
|
+
cfg,
|
|
517
|
+
accountId
|
|
518
|
+
});
|
|
519
|
+
return (account.config.postAs ?? "bot") === "bot" || (account.config.mode ?? "socket") === "socket";
|
|
520
|
+
}
|
|
521
|
+
}),
|
|
522
|
+
createSlackTokenCredential({
|
|
523
|
+
inputKey: "signingSecret",
|
|
524
|
+
providerHint: "slack-signing-secret",
|
|
525
|
+
credentialLabel: "Slack signing secret",
|
|
526
|
+
keepPrompt: "Slack signing secret already configured. Keep it?",
|
|
527
|
+
inputPrompt: "Enter Slack signing secret",
|
|
528
|
+
shouldPrompt: ({ cfg, accountId }) => {
|
|
529
|
+
const account = inspectSlackAccount({
|
|
530
|
+
cfg,
|
|
531
|
+
accountId
|
|
532
|
+
});
|
|
533
|
+
return account.config.postAs === "user" && account.config.mode === "http";
|
|
534
|
+
}
|
|
535
|
+
})
|
|
536
|
+
],
|
|
537
|
+
dmPolicy: slackDmPolicy,
|
|
538
|
+
allowFrom: createAccountScopedAllowFromSection({
|
|
539
|
+
channel: SLACK_CHANNEL,
|
|
540
|
+
helpTitle: t("wizard.slack.allowlistTitle"),
|
|
541
|
+
helpLines: [
|
|
542
|
+
t("wizard.slack.allowlistIntro"),
|
|
543
|
+
t("wizard.slack.examples"),
|
|
544
|
+
"- U12345678",
|
|
545
|
+
"- @alice",
|
|
546
|
+
t("wizard.slack.multipleEntries"),
|
|
547
|
+
t("wizard.channels.docs", { link: formatDocsLink("/slack", "slack") })
|
|
548
|
+
],
|
|
549
|
+
message: t("wizard.slack.allowFromPrompt"),
|
|
550
|
+
placeholder: "@alice, U12345678",
|
|
551
|
+
invalidWithoutCredentialNote: t("wizard.slack.allowFromInvalidWithoutToken"),
|
|
552
|
+
parseId: (value) => parseMentionOrPrefixedId({
|
|
553
|
+
value,
|
|
554
|
+
mentionPattern: /^<@([A-Z0-9]+)>$/i,
|
|
555
|
+
prefixPattern: /^(slack:|user:)/i,
|
|
556
|
+
idPattern: /^[A-Z][A-Z0-9]+$/i,
|
|
557
|
+
normalizeId: (id) => id.toUpperCase()
|
|
558
|
+
}),
|
|
559
|
+
resolveEntries: handlers.resolveAllowFromEntries
|
|
560
|
+
}),
|
|
561
|
+
groupAccess: createAccountScopedGroupAccessSection({
|
|
562
|
+
channel: SLACK_CHANNEL,
|
|
563
|
+
label: t("wizard.slack.channelsLabel"),
|
|
564
|
+
placeholder: "#general, #private, C123",
|
|
565
|
+
currentPolicy: ({ cfg, accountId }) => inspectSlackAccount({
|
|
566
|
+
cfg,
|
|
567
|
+
accountId
|
|
568
|
+
}).config.groupPolicy ?? "allowlist",
|
|
569
|
+
currentEntries: ({ cfg, accountId }) => Object.entries(inspectSlackAccount({
|
|
570
|
+
cfg,
|
|
571
|
+
accountId
|
|
572
|
+
}).config.channels ?? {}).filter(([, value]) => value?.enabled !== false).map(([key]) => key),
|
|
573
|
+
updatePrompt: ({ cfg, accountId }) => Boolean(inspectSlackAccount({
|
|
574
|
+
cfg,
|
|
575
|
+
accountId
|
|
576
|
+
}).config.channels),
|
|
577
|
+
resolveAllowlist: handlers.resolveGroupAllowlist,
|
|
578
|
+
fallbackResolved: (entries) => entries,
|
|
579
|
+
applyAllowlist: ({ cfg, accountId, resolved }) => setSlackChannelAllowlist(cfg, accountId, resolved)
|
|
580
|
+
}),
|
|
581
|
+
finalize: async ({ cfg, accountId, options, prompter }) => {
|
|
582
|
+
if (hasSlackInteractiveRepliesConfig(cfg, accountId)) return;
|
|
583
|
+
if (options?.quickstartDefaults) return { cfg: setSlackInteractiveReplies(cfg, accountId, true) };
|
|
584
|
+
return { cfg: setSlackInteractiveReplies(cfg, accountId, await prompter.confirm({
|
|
585
|
+
message: t("wizard.slack.interactiveRepliesPrompt"),
|
|
586
|
+
initialValue: true
|
|
587
|
+
})) };
|
|
588
|
+
},
|
|
589
|
+
disable: (cfg) => setSetupChannelEnabled(cfg, SLACK_CHANNEL, false)
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
function createSlackSetupWizardProxy(loadWizard) {
|
|
593
|
+
return createAllowlistSetupWizardProxy({
|
|
594
|
+
loadWizard: async () => (await loadWizard()).slackSetupWizard,
|
|
595
|
+
createBase: createSlackSetupWizardBase,
|
|
596
|
+
fallbackResolvedGroupAllowlist: (entries) => entries
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
//#endregion
|
|
600
|
+
export { SLACK_CHANNEL as a, slackSetupContract as i, createSlackSetupWizardProxy as n, describeSlackSetupAccount as o, slackSetupAdapter as r, isSlackSetupAccountConfigured as s, createSlackSetupWizardBase as t };
|
package/dist/setup-plugin-api.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as slackSetupPlugin } from "./channel.setup-
|
|
1
|
+
import { t as slackSetupPlugin } from "./channel.setup-DOSTEDfA.js";
|
|
2
2
|
export { slackSetupPlugin };
|