@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,39 @@
|
|
|
1
|
+
//#region extensions/slack/src/http/paths.ts
|
|
2
|
+
function normalizeSlackWebhookPath(path) {
|
|
3
|
+
const trimmed = path?.trim();
|
|
4
|
+
if (!trimmed) return "/slack/events";
|
|
5
|
+
return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region extensions/slack/src/http/registry.ts
|
|
9
|
+
const SLACK_HTTP_ROUTES_GLOBAL_KEY = Symbol.for("openclaw.slack.httpRoutes.v1");
|
|
10
|
+
function getSlackHttpRoutes() {
|
|
11
|
+
const globalStore = globalThis;
|
|
12
|
+
const existing = globalStore[SLACK_HTTP_ROUTES_GLOBAL_KEY];
|
|
13
|
+
if (existing instanceof Map) return existing;
|
|
14
|
+
const routes = /* @__PURE__ */ new Map();
|
|
15
|
+
globalStore[SLACK_HTTP_ROUTES_GLOBAL_KEY] = routes;
|
|
16
|
+
return routes;
|
|
17
|
+
}
|
|
18
|
+
function registerSlackHttpHandler(params) {
|
|
19
|
+
const normalizedPath = normalizeSlackWebhookPath(params.path);
|
|
20
|
+
const routes = getSlackHttpRoutes();
|
|
21
|
+
if (routes.has(normalizedPath)) {
|
|
22
|
+
const suffix = params.accountId ? ` for account "${params.accountId}"` : "";
|
|
23
|
+
params.log?.(`slack: webhook path ${normalizedPath} already registered${suffix}`);
|
|
24
|
+
return () => {};
|
|
25
|
+
}
|
|
26
|
+
routes.set(normalizedPath, params.handler);
|
|
27
|
+
return () => {
|
|
28
|
+
getSlackHttpRoutes().delete(normalizedPath);
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
async function handleSlackHttpRequest(req, res) {
|
|
32
|
+
const url = new URL(req.url ?? "/", "http://localhost");
|
|
33
|
+
const handler = getSlackHttpRoutes().get(url.pathname);
|
|
34
|
+
if (!handler) return false;
|
|
35
|
+
await handler(req, res);
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
export { registerSlackHttpHandler as n, normalizeSlackWebhookPath as r, handleSlackHttpRequest as t };
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { r as SLACK_TEXT_LIMIT } from "./thread-ts-C2x7c5PP.js";
|
|
2
|
+
import { t as resolveSlackReplyBlocks } from "./reply-blocks-Z5l6_R6H.js";
|
|
3
|
+
import { o as markdownToSlackMrkdwnChunks, t as sendMessageSlack } from "./send-D_A9kL-C.js";
|
|
4
|
+
import "./send.runtime-BRE_ncCU.js";
|
|
5
|
+
import { createReplyReferencePlanner } from "openclaw/plugin-sdk/reply-reference";
|
|
6
|
+
import { SILENT_REPLY_TOKEN, chunkMarkdownTextWithMode, isSilentReplyText } from "openclaw/plugin-sdk/reply-chunking";
|
|
7
|
+
import { deliverTextOrMediaReply, resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
|
|
8
|
+
//#region extensions/slack/src/monitor/replies.ts
|
|
9
|
+
function readSlackReplyBlocks(payload) {
|
|
10
|
+
return resolveSlackReplyBlocks(payload);
|
|
11
|
+
}
|
|
12
|
+
function resolveDeliveredSlackReplyThreadTs(params) {
|
|
13
|
+
return (params.replyToMode === "off" ? void 0 : params.payloadReplyToId) ?? params.replyThreadTs;
|
|
14
|
+
}
|
|
15
|
+
async function deliverReplies(params) {
|
|
16
|
+
for (const payload of params.replies) {
|
|
17
|
+
const threadTs = resolveDeliveredSlackReplyThreadTs({
|
|
18
|
+
replyToMode: params.replyToMode,
|
|
19
|
+
payloadReplyToId: payload.replyToId,
|
|
20
|
+
replyThreadTs: params.replyThreadTs
|
|
21
|
+
});
|
|
22
|
+
const reply = resolveSendableOutboundReplyParts(payload);
|
|
23
|
+
const slackBlocks = readSlackReplyBlocks(payload);
|
|
24
|
+
if (!reply.hasContent && !slackBlocks?.length) continue;
|
|
25
|
+
if (!reply.hasMedia && slackBlocks?.length) {
|
|
26
|
+
const trimmed = reply.trimmedText;
|
|
27
|
+
if (!trimmed && !slackBlocks?.length) continue;
|
|
28
|
+
if (trimmed && isSilentReplyText(trimmed, SILENT_REPLY_TOKEN)) continue;
|
|
29
|
+
await sendMessageSlack(params.target, trimmed, {
|
|
30
|
+
cfg: params.cfg,
|
|
31
|
+
token: params.token,
|
|
32
|
+
threadTs,
|
|
33
|
+
accountId: params.accountId,
|
|
34
|
+
...slackBlocks?.length ? { blocks: slackBlocks } : {},
|
|
35
|
+
...params.identity ? { identity: params.identity } : {}
|
|
36
|
+
});
|
|
37
|
+
params.runtime.log?.(`delivered reply to ${params.target}`);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (await deliverTextOrMediaReply({
|
|
41
|
+
payload,
|
|
42
|
+
text: reply.text,
|
|
43
|
+
chunkText: !reply.hasMedia ? (value) => {
|
|
44
|
+
const trimmed = value.trim();
|
|
45
|
+
if (!trimmed || isSilentReplyText(trimmed, SILENT_REPLY_TOKEN)) return [];
|
|
46
|
+
return [trimmed];
|
|
47
|
+
} : void 0,
|
|
48
|
+
sendText: async (trimmed) => {
|
|
49
|
+
await sendMessageSlack(params.target, trimmed, {
|
|
50
|
+
cfg: params.cfg,
|
|
51
|
+
token: params.token,
|
|
52
|
+
threadTs,
|
|
53
|
+
accountId: params.accountId,
|
|
54
|
+
...params.identity ? { identity: params.identity } : {}
|
|
55
|
+
});
|
|
56
|
+
},
|
|
57
|
+
sendMedia: async ({ mediaUrl, caption }) => {
|
|
58
|
+
await sendMessageSlack(params.target, caption ?? "", {
|
|
59
|
+
cfg: params.cfg,
|
|
60
|
+
token: params.token,
|
|
61
|
+
mediaUrl,
|
|
62
|
+
threadTs,
|
|
63
|
+
accountId: params.accountId,
|
|
64
|
+
...params.identity ? { identity: params.identity } : {}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}) !== "empty") params.runtime.log?.(`delivered reply to ${params.target}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Compute effective threadTs for a Slack reply based on replyToMode.
|
|
72
|
+
* - "off": stay in thread if already in one, otherwise main channel
|
|
73
|
+
* - "first": first reply goes to thread, subsequent replies to main channel
|
|
74
|
+
* - "all": all replies go to thread
|
|
75
|
+
*/
|
|
76
|
+
function resolveSlackThreadTs(params) {
|
|
77
|
+
return createSlackReplyReferencePlanner({
|
|
78
|
+
replyToMode: params.replyToMode,
|
|
79
|
+
incomingThreadTs: params.incomingThreadTs,
|
|
80
|
+
messageTs: params.messageTs,
|
|
81
|
+
hasReplied: params.hasReplied,
|
|
82
|
+
isThreadReply: params.isThreadReply
|
|
83
|
+
}).use();
|
|
84
|
+
}
|
|
85
|
+
function createSlackReplyReferencePlanner(params) {
|
|
86
|
+
return createReplyReferencePlanner({
|
|
87
|
+
replyToMode: params.isThreadReply ?? Boolean(params.incomingThreadTs && params.incomingThreadTs !== params.messageTs) ? "all" : params.replyToMode,
|
|
88
|
+
existingId: params.incomingThreadTs,
|
|
89
|
+
startId: params.messageTs,
|
|
90
|
+
hasReplied: params.hasReplied
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
function createSlackReplyDeliveryPlan(params) {
|
|
94
|
+
const replyReference = createSlackReplyReferencePlanner({
|
|
95
|
+
replyToMode: params.replyToMode,
|
|
96
|
+
incomingThreadTs: params.incomingThreadTs,
|
|
97
|
+
messageTs: params.messageTs,
|
|
98
|
+
hasReplied: params.hasRepliedRef.value,
|
|
99
|
+
isThreadReply: params.isThreadReply
|
|
100
|
+
});
|
|
101
|
+
return {
|
|
102
|
+
peekThreadTs: () => replyReference.peek(),
|
|
103
|
+
nextThreadTs: () => replyReference.use(),
|
|
104
|
+
markSent: () => {
|
|
105
|
+
replyReference.markSent();
|
|
106
|
+
params.hasRepliedRef.value = replyReference.hasReplied();
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
async function deliverSlackSlashReplies(params) {
|
|
111
|
+
const messages = [];
|
|
112
|
+
const chunkLimit = Math.min(params.textLimit, SLACK_TEXT_LIMIT);
|
|
113
|
+
for (const payload of params.replies) {
|
|
114
|
+
const reply = resolveSendableOutboundReplyParts(payload);
|
|
115
|
+
const slackBlocks = readSlackReplyBlocks(payload);
|
|
116
|
+
const text = reply.hasText && !isSilentReplyText(reply.trimmedText, SILENT_REPLY_TOKEN) ? reply.trimmedText : void 0;
|
|
117
|
+
if (slackBlocks?.length && !reply.hasMedia) {
|
|
118
|
+
messages.push({
|
|
119
|
+
text: text ?? "",
|
|
120
|
+
blocks: slackBlocks
|
|
121
|
+
});
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
const combined = [text ?? "", ...reply.mediaUrls].filter(Boolean).join("\n");
|
|
125
|
+
if (!combined) continue;
|
|
126
|
+
const chunkMode = params.chunkMode ?? "length";
|
|
127
|
+
const chunks = (chunkMode === "newline" ? chunkMarkdownTextWithMode(combined, chunkLimit, chunkMode) : [combined]).flatMap((markdown) => markdownToSlackMrkdwnChunks(markdown, chunkLimit, { tableMode: params.tableMode }));
|
|
128
|
+
if (!chunks.length && combined) chunks.push(combined);
|
|
129
|
+
for (const chunk of chunks) messages.push({ text: chunk });
|
|
130
|
+
}
|
|
131
|
+
if (messages.length === 0) return;
|
|
132
|
+
const responseType = params.ephemeral ? "ephemeral" : "in_channel";
|
|
133
|
+
for (const message of messages) await params.respond({
|
|
134
|
+
...message,
|
|
135
|
+
response_type: responseType
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
//#endregion
|
|
139
|
+
export { resolveDeliveredSlackReplyThreadTs as a, readSlackReplyBlocks as i, deliverReplies as n, resolveSlackThreadTs as o, deliverSlackSlashReplies as r, createSlackReplyDeliveryPlan as t };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { t as buildSlackInteractiveBlocks } from "./blocks-render-BIDw-Pom.js";
|
|
2
|
+
import { n as parseSlackBlocksInput } from "./blocks-input-CwTFVImV.js";
|
|
3
|
+
//#region extensions/slack/src/reply-blocks.ts
|
|
4
|
+
function resolveSlackReplyBlocks(payload) {
|
|
5
|
+
const slackData = payload.channelData?.slack;
|
|
6
|
+
const interactiveBlocks = buildSlackInteractiveBlocks(payload.interactive);
|
|
7
|
+
let channelBlocks = [];
|
|
8
|
+
if (slackData && typeof slackData === "object" && !Array.isArray(slackData)) channelBlocks = parseSlackBlocksInput(slackData.blocks) ?? [];
|
|
9
|
+
const blocks = [...channelBlocks, ...interactiveBlocks];
|
|
10
|
+
if (blocks.length > 50) throw new Error(`Slack blocks cannot exceed 50 items after interactive render`);
|
|
11
|
+
return blocks.length > 0 ? blocks : void 0;
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { resolveSlackReplyBlocks as t };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
//#region extensions/slack/src/resolve-allowlist-common.ts
|
|
2
|
+
function readSlackNextCursor(response) {
|
|
3
|
+
const next = response.response_metadata?.next_cursor?.trim();
|
|
4
|
+
return next ? next : void 0;
|
|
5
|
+
}
|
|
6
|
+
async function collectSlackCursorItems(params) {
|
|
7
|
+
const items = [];
|
|
8
|
+
let cursor;
|
|
9
|
+
do {
|
|
10
|
+
const response = await params.fetchPage(cursor);
|
|
11
|
+
items.push(...params.collectPageItems(response));
|
|
12
|
+
cursor = readSlackNextCursor(response);
|
|
13
|
+
} while (cursor);
|
|
14
|
+
return items;
|
|
15
|
+
}
|
|
16
|
+
function resolveSlackAllowlistEntries(params) {
|
|
17
|
+
const results = [];
|
|
18
|
+
for (const input of params.entries) {
|
|
19
|
+
const parsed = params.parseInput(input);
|
|
20
|
+
if (parsed.id) {
|
|
21
|
+
const match = params.findById(params.lookup, parsed.id);
|
|
22
|
+
results.push(params.buildIdResolved({
|
|
23
|
+
input,
|
|
24
|
+
parsed,
|
|
25
|
+
match
|
|
26
|
+
}));
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
const resolved = params.resolveNonId({
|
|
30
|
+
input,
|
|
31
|
+
parsed,
|
|
32
|
+
lookup: params.lookup
|
|
33
|
+
});
|
|
34
|
+
if (resolved) {
|
|
35
|
+
results.push(resolved);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
results.push(params.buildUnresolved(input));
|
|
39
|
+
}
|
|
40
|
+
return results;
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { resolveSlackAllowlistEntries as n, collectSlackCursorItems as t };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-CiIaOW0V.js";
|
|
2
|
+
import { r as createSlackWebClient } from "./client-CPe4GmDR.js";
|
|
3
|
+
import { n as resolveSlackAllowlistEntries, t as collectSlackCursorItems } from "./resolve-allowlist-common-Bk3clYPK.js";
|
|
4
|
+
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
5
|
+
//#region extensions/slack/src/resolve-channels.ts
|
|
6
|
+
var resolve_channels_exports = /* @__PURE__ */ __exportAll({ resolveSlackChannelAllowlist: () => resolveSlackChannelAllowlist });
|
|
7
|
+
function parseSlackChannelMention(raw) {
|
|
8
|
+
const trimmed = raw.trim();
|
|
9
|
+
if (!trimmed) return {};
|
|
10
|
+
const mention = trimmed.match(/^<#([A-Z0-9]+)(?:\|([^>]+))?>$/i);
|
|
11
|
+
if (mention) return {
|
|
12
|
+
id: mention[1]?.toUpperCase(),
|
|
13
|
+
name: mention[2]?.trim()
|
|
14
|
+
};
|
|
15
|
+
const prefixed = trimmed.replace(/^(slack:|channel:)/i, "");
|
|
16
|
+
if (/^[CG][A-Z0-9]+$/i.test(prefixed)) return { id: prefixed.toUpperCase() };
|
|
17
|
+
const name = prefixed.replace(/^#/, "").trim();
|
|
18
|
+
return name ? { name } : {};
|
|
19
|
+
}
|
|
20
|
+
async function listSlackChannels(client) {
|
|
21
|
+
return collectSlackCursorItems({
|
|
22
|
+
fetchPage: async (cursor) => await client.conversations.list({
|
|
23
|
+
types: "public_channel,private_channel",
|
|
24
|
+
exclude_archived: false,
|
|
25
|
+
limit: 1e3,
|
|
26
|
+
cursor
|
|
27
|
+
}),
|
|
28
|
+
collectPageItems: (res) => (res.channels ?? []).map((channel) => {
|
|
29
|
+
const id = channel.id?.trim();
|
|
30
|
+
const name = channel.name?.trim();
|
|
31
|
+
if (!id || !name) return null;
|
|
32
|
+
return {
|
|
33
|
+
id,
|
|
34
|
+
name,
|
|
35
|
+
archived: Boolean(channel.is_archived),
|
|
36
|
+
isPrivate: Boolean(channel.is_private)
|
|
37
|
+
};
|
|
38
|
+
}).filter(Boolean)
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
function resolveByName(name, channels) {
|
|
42
|
+
const target = normalizeLowercaseStringOrEmpty(name);
|
|
43
|
+
if (!target) return;
|
|
44
|
+
const matches = channels.filter((channel) => normalizeLowercaseStringOrEmpty(channel.name) === target);
|
|
45
|
+
if (matches.length === 0) return;
|
|
46
|
+
return matches.find((channel) => !channel.archived) ?? matches[0];
|
|
47
|
+
}
|
|
48
|
+
async function resolveSlackChannelAllowlist(params) {
|
|
49
|
+
const channels = await listSlackChannels(params.client ?? createSlackWebClient(params.token));
|
|
50
|
+
return resolveSlackAllowlistEntries({
|
|
51
|
+
entries: params.entries,
|
|
52
|
+
lookup: channels,
|
|
53
|
+
parseInput: parseSlackChannelMention,
|
|
54
|
+
findById: (lookup, id) => lookup.find((channel) => channel.id === id),
|
|
55
|
+
buildIdResolved: ({ input, parsed, match }) => ({
|
|
56
|
+
input,
|
|
57
|
+
resolved: true,
|
|
58
|
+
id: parsed.id,
|
|
59
|
+
name: match?.name ?? parsed.name,
|
|
60
|
+
archived: match?.archived
|
|
61
|
+
}),
|
|
62
|
+
resolveNonId: ({ input, parsed, lookup }) => {
|
|
63
|
+
if (!parsed.name) return;
|
|
64
|
+
const match = resolveByName(parsed.name, lookup);
|
|
65
|
+
if (!match) return;
|
|
66
|
+
return {
|
|
67
|
+
input,
|
|
68
|
+
resolved: true,
|
|
69
|
+
id: match.id,
|
|
70
|
+
name: match.name,
|
|
71
|
+
archived: match.archived
|
|
72
|
+
};
|
|
73
|
+
},
|
|
74
|
+
buildUnresolved: (input) => ({
|
|
75
|
+
input,
|
|
76
|
+
resolved: false
|
|
77
|
+
})
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
export { resolve_channels_exports as n, resolveSlackChannelAllowlist as t };
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-CiIaOW0V.js";
|
|
2
|
+
import { r as createSlackWebClient } from "./client-CPe4GmDR.js";
|
|
3
|
+
import { n as resolveSlackAllowlistEntries, t as collectSlackCursorItems } from "./resolve-allowlist-common-Bk3clYPK.js";
|
|
4
|
+
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
5
|
+
//#region extensions/slack/src/resolve-users.ts
|
|
6
|
+
var resolve_users_exports = /* @__PURE__ */ __exportAll({ resolveSlackUserAllowlist: () => resolveSlackUserAllowlist });
|
|
7
|
+
function parseSlackUserInput(raw) {
|
|
8
|
+
const trimmed = raw.trim();
|
|
9
|
+
if (!trimmed) return {};
|
|
10
|
+
const mention = trimmed.match(/^<@([A-Z0-9]+)>$/i);
|
|
11
|
+
if (mention) return { id: mention[1]?.toUpperCase() };
|
|
12
|
+
const prefixed = trimmed.replace(/^(slack:|user:)/i, "");
|
|
13
|
+
if (/^[A-Z][A-Z0-9]+$/i.test(prefixed)) return { id: prefixed.toUpperCase() };
|
|
14
|
+
if (trimmed.includes("@") && !trimmed.startsWith("@")) return { email: normalizeLowercaseStringOrEmpty(trimmed) };
|
|
15
|
+
const name = trimmed.replace(/^@/, "").trim();
|
|
16
|
+
return name ? { name } : {};
|
|
17
|
+
}
|
|
18
|
+
async function listSlackUsers(client) {
|
|
19
|
+
return collectSlackCursorItems({
|
|
20
|
+
fetchPage: async (cursor) => await client.users.list({
|
|
21
|
+
limit: 200,
|
|
22
|
+
cursor
|
|
23
|
+
}),
|
|
24
|
+
collectPageItems: (res) => (res.members ?? []).map((member) => {
|
|
25
|
+
const id = normalizeOptionalString(member.id);
|
|
26
|
+
const name = normalizeOptionalString(member.name);
|
|
27
|
+
if (!id || !name) return null;
|
|
28
|
+
const profile = member.profile ?? {};
|
|
29
|
+
return {
|
|
30
|
+
id,
|
|
31
|
+
name,
|
|
32
|
+
displayName: normalizeOptionalString(profile.display_name),
|
|
33
|
+
realName: normalizeOptionalString(profile.real_name) ?? normalizeOptionalString(member.real_name),
|
|
34
|
+
email: normalizeOptionalString(profile.email) == null ? void 0 : normalizeLowercaseStringOrEmpty(profile.email),
|
|
35
|
+
deleted: Boolean(member.deleted),
|
|
36
|
+
isBot: Boolean(member.is_bot),
|
|
37
|
+
isAppUser: Boolean(member.is_app_user)
|
|
38
|
+
};
|
|
39
|
+
}).filter(Boolean)
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function scoreSlackUser(user, match) {
|
|
43
|
+
let score = 0;
|
|
44
|
+
if (!user.deleted) score += 3;
|
|
45
|
+
if (!user.isBot && !user.isAppUser) score += 2;
|
|
46
|
+
if (match.email && user.email === match.email) score += 5;
|
|
47
|
+
if (match.name) {
|
|
48
|
+
const target = normalizeLowercaseStringOrEmpty(match.name);
|
|
49
|
+
if ([
|
|
50
|
+
user.name,
|
|
51
|
+
user.displayName,
|
|
52
|
+
user.realName
|
|
53
|
+
].map((value) => normalizeLowercaseStringOrEmpty(value)).filter(Boolean).some((value) => value === target)) score += 2;
|
|
54
|
+
}
|
|
55
|
+
return score;
|
|
56
|
+
}
|
|
57
|
+
function resolveSlackUserFromMatches(input, matches, parsed) {
|
|
58
|
+
const best = matches.map((user) => ({
|
|
59
|
+
user,
|
|
60
|
+
score: scoreSlackUser(user, parsed)
|
|
61
|
+
})).toSorted((a, b) => b.score - a.score)[0]?.user ?? matches[0];
|
|
62
|
+
return {
|
|
63
|
+
input,
|
|
64
|
+
resolved: true,
|
|
65
|
+
id: best.id,
|
|
66
|
+
name: best.displayName ?? best.realName ?? best.name,
|
|
67
|
+
email: best.email,
|
|
68
|
+
deleted: best.deleted,
|
|
69
|
+
isBot: best.isBot,
|
|
70
|
+
note: matches.length > 1 ? "multiple matches; chose best" : void 0
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
async function resolveSlackUserAllowlist(params) {
|
|
74
|
+
const users = await listSlackUsers(params.client ?? createSlackWebClient(params.token));
|
|
75
|
+
return resolveSlackAllowlistEntries({
|
|
76
|
+
entries: params.entries,
|
|
77
|
+
lookup: users,
|
|
78
|
+
parseInput: parseSlackUserInput,
|
|
79
|
+
findById: (lookup, id) => lookup.find((user) => user.id === id),
|
|
80
|
+
buildIdResolved: ({ input, parsed, match }) => ({
|
|
81
|
+
input,
|
|
82
|
+
resolved: true,
|
|
83
|
+
id: parsed.id,
|
|
84
|
+
name: match?.displayName ?? match?.realName ?? match?.name,
|
|
85
|
+
email: match?.email,
|
|
86
|
+
deleted: match?.deleted,
|
|
87
|
+
isBot: match?.isBot
|
|
88
|
+
}),
|
|
89
|
+
resolveNonId: ({ input, parsed, lookup }) => {
|
|
90
|
+
if (parsed.email) {
|
|
91
|
+
const matches = lookup.filter((user) => user.email === parsed.email);
|
|
92
|
+
if (matches.length > 0) return resolveSlackUserFromMatches(input, matches, parsed);
|
|
93
|
+
}
|
|
94
|
+
if (parsed.name) {
|
|
95
|
+
const target = normalizeLowercaseStringOrEmpty(parsed.name);
|
|
96
|
+
const matches = lookup.filter((user) => {
|
|
97
|
+
return [
|
|
98
|
+
user.name,
|
|
99
|
+
user.displayName,
|
|
100
|
+
user.realName
|
|
101
|
+
].map((value) => normalizeLowercaseStringOrEmpty(value)).filter(Boolean).includes(target);
|
|
102
|
+
});
|
|
103
|
+
if (matches.length > 0) return resolveSlackUserFromMatches(input, matches, parsed);
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
buildUnresolved: (input) => ({
|
|
107
|
+
input,
|
|
108
|
+
resolved: false
|
|
109
|
+
})
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
//#endregion
|
|
113
|
+
export { resolve_users_exports as n, resolveSlackUserAllowlist as t };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __exportAll = (all, no_symbols) => {
|
|
4
|
+
let target = {};
|
|
5
|
+
for (var name in all) __defProp(target, name, {
|
|
6
|
+
get: all[name],
|
|
7
|
+
enumerable: true
|
|
8
|
+
});
|
|
9
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
10
|
+
return target;
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
export { __exportAll as t };
|