@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.
- package/dist/account-inspect-D7AZNs8C.js +77 -0
- package/dist/account-inspect-api.js +10 -0
- package/dist/accounts-ClAPP5ry.js +139 -0
- package/dist/accounts.runtime-DDVcLJUI.js +2 -0
- package/dist/action-runtime-e2UhRsNx.js +350 -0
- package/dist/action-runtime.runtime-BFcqMbOm.js +2 -0
- package/dist/actions-CYLFK-Zy.js +292 -0
- package/dist/actions.runtime-CO3OaTLb.js +2 -0
- package/dist/allow-list-BPnnlRPL.js +82 -0
- package/dist/api.js +21 -0
- package/dist/approval-handler.runtime-CmeRr9qA.js +256 -0
- package/dist/blocks-input-CwTFVImV.js +29 -0
- package/dist/blocks-render-BIDw-Pom.js +161 -0
- package/dist/channel-DRjHBTDB.js +1020 -0
- package/dist/channel-api-B_nZwosg.js +20 -0
- package/dist/channel-config-api.js +2 -0
- package/dist/channel-entry.js +22 -0
- package/dist/channel-plugin-api.js +2 -0
- package/dist/channel.setup-Cayn7afd.js +73 -0
- package/dist/client-CPe4GmDR.js +103 -0
- package/dist/config-api-B_jq4NJW.js +2 -0
- package/dist/config-schema-D9B5LB_L.js +167 -0
- package/dist/configured-state.js +11 -0
- package/dist/contract-api.js +5 -0
- package/dist/directory-config-B3JiHeB7.js +54 -0
- package/dist/directory-contract-api.js +2 -0
- package/dist/directory-live-Bf16GwDh.js +133 -0
- package/dist/doctor-contract-KUjHnkQm.js +147 -0
- package/dist/doctor-contract-api.js +2 -0
- package/dist/errors-BYFHR24f.js +109 -0
- package/dist/exec-approvals-7xUNgLi9.js +58 -0
- package/dist/group-policy-CyLUK6My.js +41 -0
- package/dist/http-routes-api.js +2 -0
- package/dist/inbound-contract-test-api.js +3 -0
- package/dist/index.js +33 -0
- package/dist/interactive-replies-api.js +2 -0
- package/dist/interactive-replies-qAIfuBor.js +173 -0
- package/dist/magic-string.es-BMaGRRZ1.js +1011 -0
- package/dist/media-D1XCd1uP.js +469 -0
- package/dist/message-tool-api-6lowf9zE.js +104 -0
- package/dist/message-tool-api.js +2 -0
- package/dist/monitor-a97o17G6.js +13 -0
- package/dist/mrkdwn-Cax-eSfK.js +6 -0
- package/dist/outbound-adapter-B_5sEhCg.js +174 -0
- package/dist/outbound-payload-test-api.js +2 -0
- package/dist/outbound-payload.test-harness-CVCamg1x.js +13558 -0
- package/dist/pipeline.runtime-DT0hLnq2.js +1379 -0
- package/dist/plugin-routes-DtTPmga1.js +20 -0
- package/dist/prepare-D3YqV8jB.js +1482 -0
- package/dist/prepare.test-helpers-DVcjRhfG.js +49 -0
- package/dist/probe-3eZf1FjI.js +42 -0
- package/dist/provider-D7uAN3Fq.js +3235 -0
- package/dist/registry-CeaoNfoP.js +39 -0
- package/dist/replies-Xe_jMR6o.js +139 -0
- package/dist/reply-blocks-Z5l6_R6H.js +14 -0
- package/dist/resolve-allowlist-common-Bk3clYPK.js +43 -0
- package/dist/resolve-channels-BRYqyNVJ.js +81 -0
- package/dist/resolve-users-Bd_SdP8j.js +113 -0
- package/dist/rolldown-runtime-CiIaOW0V.js +13 -0
- package/dist/room-context-0vovmZPU.js +787 -0
- package/dist/runtime-Bo-KHM-F.js +8 -0
- package/dist/runtime-api-Dd1xIV5v.js +9 -0
- package/dist/runtime-api.js +14 -0
- package/dist/runtime-setter-api.js +2 -0
- package/dist/scopes-CDevO8jg.js +74 -0
- package/dist/secret-contract-Bo6lbSkh.js +141 -0
- package/dist/secret-contract-api.js +2 -0
- package/dist/security-audit-BtHGnD3d.js +51 -0
- package/dist/security-contract-api.js +2 -0
- package/dist/send-D_A9kL-C.js +721 -0
- package/dist/send.runtime-BRE_ncCU.js +2 -0
- package/dist/send.runtime-_l76lUuL.js +2 -0
- package/dist/setup-core-B9NetDkM.js +320 -0
- package/dist/setup-entry.js +15 -0
- package/dist/setup-plugin-api.js +2 -0
- package/dist/setup-surface-D88QBVOW.js +128 -0
- package/dist/shared-D8U42xFL.js +208 -0
- package/dist/slash-commands.runtime-22kgyst2.js +19 -0
- package/dist/slash-dispatch.runtime-BJgT0jwV.js +32 -0
- package/dist/slash-plugin-commands.runtime-CF-n3MeP.js +2 -0
- package/dist/slash-skill-commands.runtime-BMs0VjTe.js +7 -0
- package/dist/streaming-compat-RkZgTmQ2.js +43 -0
- package/dist/target-parsing-CQmv-iSm.js +55 -0
- package/dist/targets-B1tYCAr6.js +2 -0
- package/dist/test-api.js +8 -0
- package/dist/thread-ts-C2x7c5PP.js +24 -0
- package/openclaw.plugin.json +2405 -0
- package/package.json +84 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { i as resolveDefaultSlackAccountId, r as mergeSlackAccountConfig } from "./accounts-ClAPP5ry.js";
|
|
2
|
+
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
|
|
3
|
+
import { hasConfiguredSecretInput, normalizeSecretInputString } from "openclaw/plugin-sdk/secret-input";
|
|
4
|
+
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
5
|
+
//#region extensions/slack/src/account-inspect.ts
|
|
6
|
+
function inspectSlackToken(value) {
|
|
7
|
+
const token = normalizeSecretInputString(value);
|
|
8
|
+
if (token) return {
|
|
9
|
+
token,
|
|
10
|
+
source: "config",
|
|
11
|
+
status: "available"
|
|
12
|
+
};
|
|
13
|
+
if (hasConfiguredSecretInput(value)) return {
|
|
14
|
+
source: "config",
|
|
15
|
+
status: "configured_unavailable"
|
|
16
|
+
};
|
|
17
|
+
return {
|
|
18
|
+
source: "none",
|
|
19
|
+
status: "missing"
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function inspectSlackAccount(params) {
|
|
23
|
+
const accountId = normalizeAccountId(params.accountId ?? resolveDefaultSlackAccountId(params.cfg));
|
|
24
|
+
const merged = mergeSlackAccountConfig(params.cfg, accountId);
|
|
25
|
+
const enabled = params.cfg.channels?.slack?.enabled !== false && merged.enabled !== false;
|
|
26
|
+
const allowEnv = accountId === DEFAULT_ACCOUNT_ID;
|
|
27
|
+
const mode = merged.mode ?? "socket";
|
|
28
|
+
const isHttpMode = mode === "http";
|
|
29
|
+
const configBot = inspectSlackToken(merged.botToken);
|
|
30
|
+
const configApp = inspectSlackToken(merged.appToken);
|
|
31
|
+
const configSigningSecret = inspectSlackToken(merged.signingSecret);
|
|
32
|
+
const configUser = inspectSlackToken(merged.userToken);
|
|
33
|
+
const envBot = allowEnv ? normalizeSecretInputString(params.envBotToken ?? process.env.SLACK_BOT_TOKEN) : void 0;
|
|
34
|
+
const envApp = allowEnv ? normalizeSecretInputString(params.envAppToken ?? process.env.SLACK_APP_TOKEN) : void 0;
|
|
35
|
+
const envUser = allowEnv ? normalizeSecretInputString(params.envUserToken ?? process.env.SLACK_USER_TOKEN) : void 0;
|
|
36
|
+
const botToken = configBot.token ?? envBot;
|
|
37
|
+
const appToken = configApp.token ?? envApp;
|
|
38
|
+
const signingSecret = configSigningSecret.token;
|
|
39
|
+
const userToken = configUser.token ?? envUser;
|
|
40
|
+
const botTokenSource = configBot.token ? "config" : configBot.status === "configured_unavailable" ? "config" : envBot ? "env" : "none";
|
|
41
|
+
const appTokenSource = configApp.token ? "config" : configApp.status === "configured_unavailable" ? "config" : envApp ? "env" : "none";
|
|
42
|
+
const signingSecretSource = configSigningSecret.token ? "config" : configSigningSecret.status === "configured_unavailable" ? "config" : "none";
|
|
43
|
+
const userTokenSource = configUser.token ? "config" : configUser.status === "configured_unavailable" ? "config" : envUser ? "env" : "none";
|
|
44
|
+
return {
|
|
45
|
+
accountId,
|
|
46
|
+
enabled,
|
|
47
|
+
name: normalizeOptionalString(merged.name),
|
|
48
|
+
mode,
|
|
49
|
+
botToken,
|
|
50
|
+
appToken,
|
|
51
|
+
...isHttpMode ? { signingSecret } : {},
|
|
52
|
+
userToken,
|
|
53
|
+
botTokenSource,
|
|
54
|
+
appTokenSource,
|
|
55
|
+
...isHttpMode ? { signingSecretSource } : {},
|
|
56
|
+
userTokenSource,
|
|
57
|
+
botTokenStatus: configBot.token ? "available" : configBot.status === "configured_unavailable" ? "configured_unavailable" : envBot ? "available" : "missing",
|
|
58
|
+
appTokenStatus: configApp.token ? "available" : configApp.status === "configured_unavailable" ? "configured_unavailable" : envApp ? "available" : "missing",
|
|
59
|
+
...isHttpMode ? { signingSecretStatus: configSigningSecret.token ? "available" : configSigningSecret.status === "configured_unavailable" ? "configured_unavailable" : "missing" } : {},
|
|
60
|
+
userTokenStatus: configUser.token ? "available" : configUser.status === "configured_unavailable" ? "configured_unavailable" : envUser ? "available" : "missing",
|
|
61
|
+
configured: isHttpMode ? (configBot.status !== "missing" || Boolean(envBot)) && configSigningSecret.status !== "missing" : (configBot.status !== "missing" || Boolean(envBot)) && (configApp.status !== "missing" || Boolean(envApp)),
|
|
62
|
+
config: merged,
|
|
63
|
+
groupPolicy: merged.groupPolicy,
|
|
64
|
+
textChunkLimit: merged.textChunkLimit,
|
|
65
|
+
mediaMaxMb: merged.mediaMaxMb,
|
|
66
|
+
reactionNotifications: merged.reactionNotifications,
|
|
67
|
+
reactionAllowlist: merged.reactionAllowlist,
|
|
68
|
+
replyToMode: merged.replyToMode,
|
|
69
|
+
replyToModeByChatType: merged.replyToModeByChatType,
|
|
70
|
+
actions: merged.actions,
|
|
71
|
+
slashCommand: merged.slashCommand,
|
|
72
|
+
dm: merged.dm,
|
|
73
|
+
channels: merged.channels
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//#endregion
|
|
77
|
+
export { inspectSlackAccount as t };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { t as inspectSlackAccount } from "./account-inspect-D7AZNs8C.js";
|
|
2
|
+
//#region extensions/slack/account-inspect-api.ts
|
|
3
|
+
function inspectSlackReadOnlyAccount(cfg, accountId) {
|
|
4
|
+
return inspectSlackAccount({
|
|
5
|
+
cfg,
|
|
6
|
+
accountId
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
export { inspectSlackReadOnlyAccount };
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { DEFAULT_ACCOUNT_ID, createAccountListHelpers, normalizeAccountId, resolveMergedAccountConfig } from "openclaw/plugin-sdk/account-resolution";
|
|
2
|
+
import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
|
|
3
|
+
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
|
+
import { mapAllowFromEntries, normalizeChannelDmPolicy, resolveChannelDmAllowFrom, resolveChannelDmPolicy } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
5
|
+
import { resolveAccountEntry } from "openclaw/plugin-sdk/routing";
|
|
6
|
+
//#region extensions/slack/src/token.ts
|
|
7
|
+
function resolveSlackBotToken(raw, path = "channels.slack.botToken") {
|
|
8
|
+
return normalizeResolvedSecretInputString({
|
|
9
|
+
value: raw,
|
|
10
|
+
path
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
function resolveSlackAppToken(raw, path = "channels.slack.appToken") {
|
|
14
|
+
return normalizeResolvedSecretInputString({
|
|
15
|
+
value: raw,
|
|
16
|
+
path
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function resolveSlackUserToken(raw, path = "channels.slack.userToken") {
|
|
20
|
+
return normalizeResolvedSecretInputString({
|
|
21
|
+
value: raw,
|
|
22
|
+
path
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region extensions/slack/src/account-reply-mode.ts
|
|
27
|
+
function normalizeSlackChatType(raw) {
|
|
28
|
+
const value = raw?.trim().toLowerCase();
|
|
29
|
+
if (!value) return;
|
|
30
|
+
if (value === "direct" || value === "dm") return "direct";
|
|
31
|
+
if (value === "group" || value === "channel") return value;
|
|
32
|
+
}
|
|
33
|
+
function resolveSlackReplyToMode(account, chatType) {
|
|
34
|
+
const normalized = normalizeSlackChatType(chatType ?? void 0);
|
|
35
|
+
if (normalized && account.replyToModeByChatType?.[normalized] !== void 0) return account.replyToModeByChatType[normalized] ?? "off";
|
|
36
|
+
if (normalized === "direct" && account.dm?.replyToMode !== void 0) return account.dm.replyToMode;
|
|
37
|
+
return account.replyToMode ?? "off";
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region extensions/slack/src/accounts.ts
|
|
41
|
+
const { listAccountIds, resolveDefaultAccountId } = createAccountListHelpers("slack");
|
|
42
|
+
const listSlackAccountIds = listAccountIds;
|
|
43
|
+
const resolveDefaultSlackAccountId = resolveDefaultAccountId;
|
|
44
|
+
function resolveSlackAccountConfig(cfg, accountId) {
|
|
45
|
+
return resolveAccountEntry(cfg.channels?.slack?.accounts, accountId);
|
|
46
|
+
}
|
|
47
|
+
function mergeSlackAccountConfig(cfg, accountId) {
|
|
48
|
+
return resolveMergedAccountConfig({
|
|
49
|
+
channelConfig: cfg.channels?.slack,
|
|
50
|
+
accounts: cfg.channels?.slack?.accounts,
|
|
51
|
+
accountId
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function resolveSlackAccountAllowFrom(params) {
|
|
55
|
+
const accountId = normalizeAccountId(params.accountId ?? resolveDefaultSlackAccountId(params.cfg));
|
|
56
|
+
const accountConfig = resolveSlackAccountConfig(params.cfg, accountId);
|
|
57
|
+
const rootConfig = params.cfg.channels?.slack;
|
|
58
|
+
const allowFrom = resolveChannelDmAllowFrom({
|
|
59
|
+
account: accountConfig,
|
|
60
|
+
parent: rootConfig
|
|
61
|
+
});
|
|
62
|
+
return allowFrom ? mapAllowFromEntries(allowFrom) : void 0;
|
|
63
|
+
}
|
|
64
|
+
function resolveSlackConfigAccessorAccount(params) {
|
|
65
|
+
const accountId = normalizeAccountId(params.accountId ?? resolveDefaultSlackAccountId(params.cfg));
|
|
66
|
+
const config = mergeSlackAccountConfig(params.cfg, accountId);
|
|
67
|
+
return {
|
|
68
|
+
allowFrom: resolveSlackAccountAllowFrom({
|
|
69
|
+
cfg: params.cfg,
|
|
70
|
+
accountId
|
|
71
|
+
}),
|
|
72
|
+
defaultTo: config.defaultTo
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function resolveSlackAccountDmPolicy(params) {
|
|
76
|
+
const accountId = normalizeAccountId(params.accountId ?? resolveDefaultSlackAccountId(params.cfg));
|
|
77
|
+
const accountConfig = resolveSlackAccountConfig(params.cfg, accountId);
|
|
78
|
+
const rootConfig = params.cfg.channels?.slack;
|
|
79
|
+
return normalizeChannelDmPolicy(resolveChannelDmPolicy({
|
|
80
|
+
account: accountConfig,
|
|
81
|
+
parent: rootConfig,
|
|
82
|
+
defaultPolicy: "pairing"
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
function resolveSlackAccount(params) {
|
|
86
|
+
const accountId = normalizeAccountId(params.accountId ?? resolveDefaultSlackAccountId(params.cfg));
|
|
87
|
+
const baseEnabled = params.cfg.channels?.slack?.enabled !== false;
|
|
88
|
+
const merged = mergeSlackAccountConfig(params.cfg, accountId);
|
|
89
|
+
const accountEnabled = merged.enabled !== false;
|
|
90
|
+
const enabled = baseEnabled && accountEnabled;
|
|
91
|
+
const mode = merged.mode ?? "socket";
|
|
92
|
+
const baseAllowEnv = accountId === DEFAULT_ACCOUNT_ID;
|
|
93
|
+
const botActive = enabled;
|
|
94
|
+
const appActive = enabled && mode !== "http";
|
|
95
|
+
const userActive = enabled;
|
|
96
|
+
const envBot = botActive && baseAllowEnv ? resolveSlackBotToken(process.env.SLACK_BOT_TOKEN) : void 0;
|
|
97
|
+
const envApp = appActive && baseAllowEnv ? resolveSlackAppToken(process.env.SLACK_APP_TOKEN) : void 0;
|
|
98
|
+
const envUser = userActive && baseAllowEnv ? resolveSlackUserToken(process.env.SLACK_USER_TOKEN) : void 0;
|
|
99
|
+
const configBot = botActive ? resolveSlackBotToken(merged.botToken, `channels.slack.accounts.${accountId}.botToken`) : void 0;
|
|
100
|
+
const configApp = appActive ? resolveSlackAppToken(merged.appToken, `channels.slack.accounts.${accountId}.appToken`) : void 0;
|
|
101
|
+
const configUser = userActive ? resolveSlackUserToken(merged.userToken, `channels.slack.accounts.${accountId}.userToken`) : void 0;
|
|
102
|
+
const botToken = configBot ?? envBot;
|
|
103
|
+
const appToken = configApp ?? envApp;
|
|
104
|
+
const userToken = configUser ?? envUser;
|
|
105
|
+
const botTokenSource = configBot ? "config" : envBot ? "env" : "none";
|
|
106
|
+
const appTokenSource = configApp ? "config" : envApp ? "env" : "none";
|
|
107
|
+
const userTokenSource = configUser ? "config" : envUser ? "env" : "none";
|
|
108
|
+
return {
|
|
109
|
+
accountId,
|
|
110
|
+
enabled,
|
|
111
|
+
name: normalizeOptionalString(merged.name),
|
|
112
|
+
botToken,
|
|
113
|
+
appToken,
|
|
114
|
+
userToken,
|
|
115
|
+
botTokenSource,
|
|
116
|
+
appTokenSource,
|
|
117
|
+
userTokenSource,
|
|
118
|
+
config: merged,
|
|
119
|
+
groupPolicy: merged.groupPolicy,
|
|
120
|
+
textChunkLimit: merged.textChunkLimit,
|
|
121
|
+
mediaMaxMb: merged.mediaMaxMb,
|
|
122
|
+
reactionNotifications: merged.reactionNotifications,
|
|
123
|
+
reactionAllowlist: merged.reactionAllowlist,
|
|
124
|
+
replyToMode: merged.replyToMode,
|
|
125
|
+
replyToModeByChatType: merged.replyToModeByChatType,
|
|
126
|
+
actions: merged.actions,
|
|
127
|
+
slashCommand: merged.slashCommand,
|
|
128
|
+
dm: merged.dm,
|
|
129
|
+
channels: merged.channels
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function listEnabledSlackAccounts(cfg) {
|
|
133
|
+
return listSlackAccountIds(cfg).map((accountId) => resolveSlackAccount({
|
|
134
|
+
cfg,
|
|
135
|
+
accountId
|
|
136
|
+
})).filter((account) => account.enabled);
|
|
137
|
+
}
|
|
138
|
+
//#endregion
|
|
139
|
+
export { resolveSlackAccount as a, resolveSlackConfigAccessorAccount as c, resolveSlackBotToken as d, resolveDefaultSlackAccountId as i, resolveSlackReplyToMode as l, listSlackAccountIds as n, resolveSlackAccountAllowFrom as o, mergeSlackAccountConfig as r, resolveSlackAccountDmPolicy as s, listEnabledSlackAccounts as t, resolveSlackAppToken as u };
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
import { i as resolveSlackChannelId, r as parseSlackTarget } from "./target-parsing-CQmv-iSm.js";
|
|
2
|
+
import "./targets-B1tYCAr6.js";
|
|
3
|
+
import { n as parseSlackBlocksInput } from "./blocks-input-CwTFVImV.js";
|
|
4
|
+
import { a as readNumberParam, c as withNormalizedTimestamp, n as imageResultFromFile, o as readReactionParams, r as jsonResult, s as readStringParam, t as createActionGate } from "./runtime-api-Dd1xIV5v.js";
|
|
5
|
+
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
6
|
+
import { isSingleUseReplyToMode } from "openclaw/plugin-sdk/reply-reference";
|
|
7
|
+
import { readBooleanParam } from "openclaw/plugin-sdk/boolean-param";
|
|
8
|
+
//#region extensions/slack/src/action-runtime.ts
|
|
9
|
+
const messagingActions = new Set([
|
|
10
|
+
"sendMessage",
|
|
11
|
+
"uploadFile",
|
|
12
|
+
"editMessage",
|
|
13
|
+
"deleteMessage",
|
|
14
|
+
"readMessages",
|
|
15
|
+
"downloadFile"
|
|
16
|
+
]);
|
|
17
|
+
const reactionsActions = new Set(["react", "reactions"]);
|
|
18
|
+
const pinActions = new Set([
|
|
19
|
+
"pinMessage",
|
|
20
|
+
"unpinMessage",
|
|
21
|
+
"listPins"
|
|
22
|
+
]);
|
|
23
|
+
function sameSlackChannelTarget(targetChannel, currentChannelId) {
|
|
24
|
+
const parsedTarget = parseSlackTarget(targetChannel, { defaultKind: "channel" });
|
|
25
|
+
if (!parsedTarget || parsedTarget.kind !== "channel") return false;
|
|
26
|
+
return normalizeLowercaseStringOrEmpty(parsedTarget.id) === normalizeLowercaseStringOrEmpty(currentChannelId);
|
|
27
|
+
}
|
|
28
|
+
let slackActionsRuntimePromise;
|
|
29
|
+
let slackAccountsRuntimePromise;
|
|
30
|
+
function loadSlackActionsRuntime() {
|
|
31
|
+
slackActionsRuntimePromise ??= import("./actions.runtime-CO3OaTLb.js");
|
|
32
|
+
return slackActionsRuntimePromise;
|
|
33
|
+
}
|
|
34
|
+
function loadSlackAccountsRuntime() {
|
|
35
|
+
slackAccountsRuntimePromise ??= import("./accounts.runtime-DDVcLJUI.js");
|
|
36
|
+
return slackAccountsRuntimePromise;
|
|
37
|
+
}
|
|
38
|
+
function createLazySlackAction(key) {
|
|
39
|
+
return (async (...args) => {
|
|
40
|
+
const action = (await loadSlackActionsRuntime())[key];
|
|
41
|
+
return action(...args);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
const slackActionRuntime = {
|
|
45
|
+
deleteSlackMessage: createLazySlackAction("deleteSlackMessage"),
|
|
46
|
+
downloadSlackFile: createLazySlackAction("downloadSlackFile"),
|
|
47
|
+
editSlackMessage: createLazySlackAction("editSlackMessage"),
|
|
48
|
+
getSlackMemberInfo: createLazySlackAction("getSlackMemberInfo"),
|
|
49
|
+
listSlackEmojis: createLazySlackAction("listSlackEmojis"),
|
|
50
|
+
listSlackPins: createLazySlackAction("listSlackPins"),
|
|
51
|
+
listSlackReactions: createLazySlackAction("listSlackReactions"),
|
|
52
|
+
parseSlackBlocksInput,
|
|
53
|
+
pinSlackMessage: createLazySlackAction("pinSlackMessage"),
|
|
54
|
+
reactSlackMessage: createLazySlackAction("reactSlackMessage"),
|
|
55
|
+
readSlackMessages: createLazySlackAction("readSlackMessages"),
|
|
56
|
+
removeOwnSlackReactions: createLazySlackAction("removeOwnSlackReactions"),
|
|
57
|
+
removeSlackReaction: createLazySlackAction("removeSlackReaction"),
|
|
58
|
+
sendSlackMessage: createLazySlackAction("sendSlackMessage"),
|
|
59
|
+
unpinSlackMessage: createLazySlackAction("unpinSlackMessage")
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Resolve threadTs for a Slack message based on context and replyToMode.
|
|
63
|
+
* - "all": always inject threadTs
|
|
64
|
+
* - "first"/"batched": inject only for the first eligible message (updates hasRepliedRef)
|
|
65
|
+
* - "off": never auto-inject
|
|
66
|
+
*/
|
|
67
|
+
function resolveThreadTsFromContext(explicitThreadTs, targetChannel, context, opts) {
|
|
68
|
+
if (explicitThreadTs) return explicitThreadTs;
|
|
69
|
+
if (opts?.suppressImplicitThread) return;
|
|
70
|
+
if (!context?.currentThreadTs || !context?.currentChannelId) return;
|
|
71
|
+
if (!sameSlackChannelTarget(targetChannel, context.currentChannelId)) return;
|
|
72
|
+
if (context.replyToMode === "all") return context.currentThreadTs;
|
|
73
|
+
if (isSingleUseReplyToMode(context.replyToMode ?? "off") && context.hasRepliedRef && !context.hasRepliedRef.value) {
|
|
74
|
+
context.hasRepliedRef.value = true;
|
|
75
|
+
return context.currentThreadTs;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function readSlackBlocksParam(params) {
|
|
79
|
+
return slackActionRuntime.parseSlackBlocksInput(params.blocks);
|
|
80
|
+
}
|
|
81
|
+
function isImageContentType(value) {
|
|
82
|
+
return value?.trim().toLowerCase().startsWith("image/") === true;
|
|
83
|
+
}
|
|
84
|
+
async function handleSlackAction(params, cfg, context) {
|
|
85
|
+
const resolveChannelId = () => resolveSlackChannelId(readStringParam(params, "channelId", { required: true }));
|
|
86
|
+
const action = readStringParam(params, "action", { required: true });
|
|
87
|
+
const accountId = readStringParam(params, "accountId");
|
|
88
|
+
const { resolveSlackAccount } = await loadSlackAccountsRuntime();
|
|
89
|
+
const account = resolveSlackAccount({
|
|
90
|
+
cfg,
|
|
91
|
+
accountId
|
|
92
|
+
});
|
|
93
|
+
const isActionEnabled = createActionGate(account.actions ?? cfg.channels?.slack?.actions);
|
|
94
|
+
const userToken = account.userToken;
|
|
95
|
+
const botToken = account.botToken?.trim();
|
|
96
|
+
const allowUserWrites = account.config.userTokenReadOnly === false;
|
|
97
|
+
const getTokenForOperation = (operation) => {
|
|
98
|
+
if (operation === "read") return userToken ?? botToken;
|
|
99
|
+
if (!allowUserWrites) return botToken;
|
|
100
|
+
return botToken ?? userToken;
|
|
101
|
+
};
|
|
102
|
+
const buildActionOpts = (operation) => {
|
|
103
|
+
const token = getTokenForOperation(operation);
|
|
104
|
+
const tokenOverride = token && token !== botToken ? token : void 0;
|
|
105
|
+
return {
|
|
106
|
+
cfg,
|
|
107
|
+
...accountId ? { accountId } : {},
|
|
108
|
+
...tokenOverride ? { token: tokenOverride } : {}
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
const readOpts = buildActionOpts("read");
|
|
112
|
+
const writeOpts = buildActionOpts("write");
|
|
113
|
+
if (reactionsActions.has(action)) {
|
|
114
|
+
if (!isActionEnabled("reactions")) throw new Error("Slack reactions are disabled.");
|
|
115
|
+
const channelId = resolveChannelId();
|
|
116
|
+
const messageId = readStringParam(params, "messageId", { required: true });
|
|
117
|
+
if (action === "react") {
|
|
118
|
+
const { emoji, remove, isEmpty } = readReactionParams(params, { removeErrorMessage: "Emoji is required to remove a Slack reaction." });
|
|
119
|
+
if (remove) {
|
|
120
|
+
if (writeOpts) await slackActionRuntime.removeSlackReaction(channelId, messageId, emoji, writeOpts);
|
|
121
|
+
else await slackActionRuntime.removeSlackReaction(channelId, messageId, emoji);
|
|
122
|
+
return jsonResult({
|
|
123
|
+
ok: true,
|
|
124
|
+
removed: emoji
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
if (isEmpty) return jsonResult({
|
|
128
|
+
ok: true,
|
|
129
|
+
removed: writeOpts ? await slackActionRuntime.removeOwnSlackReactions(channelId, messageId, writeOpts) : await slackActionRuntime.removeOwnSlackReactions(channelId, messageId)
|
|
130
|
+
});
|
|
131
|
+
if (writeOpts) await slackActionRuntime.reactSlackMessage(channelId, messageId, emoji, writeOpts);
|
|
132
|
+
else await slackActionRuntime.reactSlackMessage(channelId, messageId, emoji);
|
|
133
|
+
return jsonResult({
|
|
134
|
+
ok: true,
|
|
135
|
+
added: emoji
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
return jsonResult({
|
|
139
|
+
ok: true,
|
|
140
|
+
reactions: readOpts ? await slackActionRuntime.listSlackReactions(channelId, messageId, readOpts) : await slackActionRuntime.listSlackReactions(channelId, messageId)
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
if (messagingActions.has(action)) {
|
|
144
|
+
if (!isActionEnabled("messages")) throw new Error("Slack messages are disabled.");
|
|
145
|
+
switch (action) {
|
|
146
|
+
case "sendMessage": {
|
|
147
|
+
const to = readStringParam(params, "to", { required: true });
|
|
148
|
+
const content = readStringParam(params, "content", { allowEmpty: true });
|
|
149
|
+
const mediaUrl = readStringParam(params, "mediaUrl");
|
|
150
|
+
const blocks = readSlackBlocksParam(params);
|
|
151
|
+
const replyBroadcast = readBooleanParam(params, "replyBroadcast");
|
|
152
|
+
if (!content && !mediaUrl && !blocks) throw new Error("Slack sendMessage requires content, blocks, or mediaUrl.");
|
|
153
|
+
if (replyBroadcast && mediaUrl) throw new Error("Slack replyBroadcast is only supported for text or block thread replies.");
|
|
154
|
+
const threadTs = resolveThreadTsFromContext(readStringParam(params, "threadTs"), to, context, { suppressImplicitThread: params.topLevel === true || params.threadTs === null });
|
|
155
|
+
const sendOpts = {
|
|
156
|
+
...writeOpts,
|
|
157
|
+
mediaLocalRoots: context?.mediaLocalRoots,
|
|
158
|
+
mediaReadFile: context?.mediaReadFile,
|
|
159
|
+
threadTs: threadTs ?? void 0,
|
|
160
|
+
...replyBroadcast ? { replyBroadcast } : {}
|
|
161
|
+
};
|
|
162
|
+
const result = mediaUrl && blocks ? await (async () => {
|
|
163
|
+
await slackActionRuntime.sendSlackMessage(to, "", {
|
|
164
|
+
...sendOpts,
|
|
165
|
+
mediaUrl
|
|
166
|
+
});
|
|
167
|
+
return await slackActionRuntime.sendSlackMessage(to, content ?? "", {
|
|
168
|
+
...sendOpts,
|
|
169
|
+
blocks
|
|
170
|
+
});
|
|
171
|
+
})() : await slackActionRuntime.sendSlackMessage(to, content ?? "", {
|
|
172
|
+
...sendOpts,
|
|
173
|
+
mediaUrl: mediaUrl ?? void 0,
|
|
174
|
+
blocks
|
|
175
|
+
});
|
|
176
|
+
if (context?.hasRepliedRef && context.currentChannelId) {
|
|
177
|
+
if (sameSlackChannelTarget(to, context.currentChannelId)) context.hasRepliedRef.value = true;
|
|
178
|
+
}
|
|
179
|
+
return jsonResult({
|
|
180
|
+
ok: true,
|
|
181
|
+
result
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
case "uploadFile": {
|
|
185
|
+
const to = readStringParam(params, "to", { required: true });
|
|
186
|
+
const filePath = readStringParam(params, "filePath", {
|
|
187
|
+
required: true,
|
|
188
|
+
trim: false
|
|
189
|
+
});
|
|
190
|
+
const initialComment = readStringParam(params, "initialComment", { allowEmpty: true });
|
|
191
|
+
const filename = readStringParam(params, "filename");
|
|
192
|
+
const title = readStringParam(params, "title");
|
|
193
|
+
if (readBooleanParam(params, "replyBroadcast")) throw new Error("Slack replyBroadcast is only supported for text or block thread replies.");
|
|
194
|
+
const threadTs = resolveThreadTsFromContext(readStringParam(params, "threadTs"), to, context, { suppressImplicitThread: params.topLevel === true || params.threadTs === null });
|
|
195
|
+
const result = await slackActionRuntime.sendSlackMessage(to, initialComment ?? "", {
|
|
196
|
+
...writeOpts,
|
|
197
|
+
mediaUrl: filePath,
|
|
198
|
+
mediaLocalRoots: context?.mediaLocalRoots,
|
|
199
|
+
mediaReadFile: context?.mediaReadFile,
|
|
200
|
+
threadTs: threadTs ?? void 0,
|
|
201
|
+
...filename ? { uploadFileName: filename } : {},
|
|
202
|
+
...title ? { uploadTitle: title } : {}
|
|
203
|
+
});
|
|
204
|
+
if (context?.hasRepliedRef && context.currentChannelId) {
|
|
205
|
+
if (sameSlackChannelTarget(to, context.currentChannelId)) context.hasRepliedRef.value = true;
|
|
206
|
+
}
|
|
207
|
+
return jsonResult({
|
|
208
|
+
ok: true,
|
|
209
|
+
result
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
case "editMessage": {
|
|
213
|
+
const channelId = resolveChannelId();
|
|
214
|
+
const messageId = readStringParam(params, "messageId", { required: true });
|
|
215
|
+
const content = readStringParam(params, "content", { allowEmpty: true });
|
|
216
|
+
const blocks = readSlackBlocksParam(params);
|
|
217
|
+
if (!content && !blocks) throw new Error("Slack editMessage requires content or blocks.");
|
|
218
|
+
if (writeOpts) await slackActionRuntime.editSlackMessage(channelId, messageId, content ?? "", {
|
|
219
|
+
...writeOpts,
|
|
220
|
+
blocks
|
|
221
|
+
});
|
|
222
|
+
else await slackActionRuntime.editSlackMessage(channelId, messageId, content ?? "", { blocks });
|
|
223
|
+
return jsonResult({ ok: true });
|
|
224
|
+
}
|
|
225
|
+
case "deleteMessage": {
|
|
226
|
+
const channelId = resolveChannelId();
|
|
227
|
+
const messageId = readStringParam(params, "messageId", { required: true });
|
|
228
|
+
if (writeOpts) await slackActionRuntime.deleteSlackMessage(channelId, messageId, writeOpts);
|
|
229
|
+
else await slackActionRuntime.deleteSlackMessage(channelId, messageId);
|
|
230
|
+
return jsonResult({ ok: true });
|
|
231
|
+
}
|
|
232
|
+
case "readMessages": {
|
|
233
|
+
const channelId = resolveChannelId();
|
|
234
|
+
const limitRaw = params.limit;
|
|
235
|
+
const limit = typeof limitRaw === "number" && Number.isFinite(limitRaw) ? limitRaw : void 0;
|
|
236
|
+
const before = readStringParam(params, "before");
|
|
237
|
+
const after = readStringParam(params, "after");
|
|
238
|
+
const threadId = readStringParam(params, "threadId");
|
|
239
|
+
const messageId = readStringParam(params, "messageId");
|
|
240
|
+
const result = await slackActionRuntime.readSlackMessages(channelId, {
|
|
241
|
+
...readOpts,
|
|
242
|
+
limit,
|
|
243
|
+
before: before ?? void 0,
|
|
244
|
+
after: after ?? void 0,
|
|
245
|
+
threadId: threadId ?? void 0,
|
|
246
|
+
messageId: messageId ?? void 0
|
|
247
|
+
});
|
|
248
|
+
return jsonResult({
|
|
249
|
+
ok: true,
|
|
250
|
+
messages: result.messages.map((message) => withNormalizedTimestamp(message, message.ts)),
|
|
251
|
+
hasMore: result.hasMore
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
case "downloadFile": {
|
|
255
|
+
const fileId = readStringParam(params, "fileId", { required: true });
|
|
256
|
+
const channelTarget = readStringParam(params, "channelId") ?? readStringParam(params, "to");
|
|
257
|
+
const channelId = channelTarget ? resolveSlackChannelId(channelTarget) : void 0;
|
|
258
|
+
const threadId = readStringParam(params, "threadId") ?? readStringParam(params, "replyTo");
|
|
259
|
+
const maxBytes = account.config?.mediaMaxMb ? account.config.mediaMaxMb * 1024 * 1024 : 20 * 1024 * 1024;
|
|
260
|
+
const readToken = getTokenForOperation("read");
|
|
261
|
+
const downloaded = await slackActionRuntime.downloadSlackFile(fileId, {
|
|
262
|
+
...readOpts,
|
|
263
|
+
...readToken && !readOpts?.token ? { token: readToken } : {},
|
|
264
|
+
maxBytes,
|
|
265
|
+
channelId,
|
|
266
|
+
threadId: threadId ?? void 0
|
|
267
|
+
});
|
|
268
|
+
if (!downloaded) return jsonResult({
|
|
269
|
+
ok: false,
|
|
270
|
+
error: "File could not be downloaded (not found, too large, or inaccessible)."
|
|
271
|
+
});
|
|
272
|
+
if (!isImageContentType(downloaded.contentType)) return jsonResult({
|
|
273
|
+
ok: true,
|
|
274
|
+
fileId,
|
|
275
|
+
path: downloaded.path,
|
|
276
|
+
contentType: downloaded.contentType,
|
|
277
|
+
placeholder: downloaded.placeholder,
|
|
278
|
+
media: {
|
|
279
|
+
mediaUrl: downloaded.path,
|
|
280
|
+
...downloaded.contentType ? { contentType: downloaded.contentType } : {}
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
return await imageResultFromFile({
|
|
284
|
+
label: "slack-file",
|
|
285
|
+
path: downloaded.path,
|
|
286
|
+
extraText: downloaded.placeholder,
|
|
287
|
+
details: {
|
|
288
|
+
fileId,
|
|
289
|
+
path: downloaded.path,
|
|
290
|
+
...downloaded.contentType ? { contentType: downloaded.contentType } : {}
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
default: break;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
if (pinActions.has(action)) {
|
|
298
|
+
if (!isActionEnabled("pins")) throw new Error("Slack pins are disabled.");
|
|
299
|
+
const channelId = resolveChannelId();
|
|
300
|
+
if (action === "pinMessage") {
|
|
301
|
+
const messageId = readStringParam(params, "messageId", { required: true });
|
|
302
|
+
if (writeOpts) await slackActionRuntime.pinSlackMessage(channelId, messageId, writeOpts);
|
|
303
|
+
else await slackActionRuntime.pinSlackMessage(channelId, messageId);
|
|
304
|
+
return jsonResult({ ok: true });
|
|
305
|
+
}
|
|
306
|
+
if (action === "unpinMessage") {
|
|
307
|
+
const messageId = readStringParam(params, "messageId", { required: true });
|
|
308
|
+
if (writeOpts) await slackActionRuntime.unpinSlackMessage(channelId, messageId, writeOpts);
|
|
309
|
+
else await slackActionRuntime.unpinSlackMessage(channelId, messageId);
|
|
310
|
+
return jsonResult({ ok: true });
|
|
311
|
+
}
|
|
312
|
+
return jsonResult({
|
|
313
|
+
ok: true,
|
|
314
|
+
pins: (writeOpts ? await slackActionRuntime.listSlackPins(channelId, readOpts) : await slackActionRuntime.listSlackPins(channelId)).map((pin) => {
|
|
315
|
+
const message = pin.message ? withNormalizedTimestamp(pin.message, pin.message.ts) : pin.message;
|
|
316
|
+
return message ? Object.assign({}, pin, { message }) : pin;
|
|
317
|
+
})
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
if (action === "memberInfo") {
|
|
321
|
+
if (!isActionEnabled("memberInfo")) throw new Error("Slack member info is disabled.");
|
|
322
|
+
const userId = readStringParam(params, "userId", { required: true });
|
|
323
|
+
return jsonResult({
|
|
324
|
+
ok: true,
|
|
325
|
+
info: writeOpts ? await slackActionRuntime.getSlackMemberInfo(userId, readOpts) : await slackActionRuntime.getSlackMemberInfo(userId)
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
if (action === "emojiList") {
|
|
329
|
+
if (!isActionEnabled("emojiList")) throw new Error("Slack emoji list is disabled.");
|
|
330
|
+
const result = readOpts ? await slackActionRuntime.listSlackEmojis(readOpts) : await slackActionRuntime.listSlackEmojis();
|
|
331
|
+
const limit = readNumberParam(params, "limit", { integer: true });
|
|
332
|
+
if (limit != null && limit > 0 && result.emoji != null) {
|
|
333
|
+
const entries = Object.entries(result.emoji).toSorted(([a], [b]) => a.localeCompare(b));
|
|
334
|
+
if (entries.length > limit) return jsonResult({
|
|
335
|
+
ok: true,
|
|
336
|
+
emojis: {
|
|
337
|
+
...result,
|
|
338
|
+
emoji: Object.fromEntries(entries.slice(0, limit))
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
return jsonResult({
|
|
343
|
+
ok: true,
|
|
344
|
+
emojis: result
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
throw new Error(`Unknown action: ${action}`);
|
|
348
|
+
}
|
|
349
|
+
//#endregion
|
|
350
|
+
export { slackActionRuntime as n, handleSlackAction as t };
|