@credal/actions 0.2.110 → 0.2.112
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.
|
@@ -4,13 +4,14 @@ export interface SlackSearchMessage {
|
|
|
4
4
|
channelId: string;
|
|
5
5
|
ts: string;
|
|
6
6
|
text?: string;
|
|
7
|
-
|
|
7
|
+
userEmail?: string;
|
|
8
8
|
permalink?: string;
|
|
9
9
|
/** If thread: full thread (root first). If not thread: small context window around the hit. */
|
|
10
10
|
context?: Array<{
|
|
11
11
|
ts: string;
|
|
12
12
|
text?: string;
|
|
13
|
-
|
|
13
|
+
userEmail?: string;
|
|
14
|
+
userName?: string;
|
|
14
15
|
}>;
|
|
15
16
|
}
|
|
16
17
|
declare const searchSlack: slackUserSearchSlackFunction;
|
|
@@ -9,6 +9,37 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import { WebClient } from "@slack/web-api";
|
|
11
11
|
import { MISSING_AUTH_TOKEN } from "../../util/missingAuthConstants.js";
|
|
12
|
+
import pLimit from "p-limit";
|
|
13
|
+
const HIT_ENRICH_POOL = 10;
|
|
14
|
+
const limitHit = pLimit(HIT_ENRICH_POOL);
|
|
15
|
+
class SlackUserCache {
|
|
16
|
+
constructor(client) {
|
|
17
|
+
this.client = client;
|
|
18
|
+
this.cache = new Map();
|
|
19
|
+
this.client = client;
|
|
20
|
+
}
|
|
21
|
+
get(id) {
|
|
22
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
23
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
24
|
+
const result = this.cache.get(id);
|
|
25
|
+
if (result)
|
|
26
|
+
return result;
|
|
27
|
+
const res = yield this.client.users.info({ user: id });
|
|
28
|
+
const u = {
|
|
29
|
+
name: (_e = (_c = (_b = (_a = res.user) === null || _a === void 0 ? void 0 : _a.profile) === null || _b === void 0 ? void 0 : _b.display_name) !== null && _c !== void 0 ? _c : (_d = res.user) === null || _d === void 0 ? void 0 : _d.real_name) !== null && _e !== void 0 ? _e : "",
|
|
30
|
+
email: (_h = (_g = (_f = res.user) === null || _f === void 0 ? void 0 : _f.profile) === null || _g === void 0 ? void 0 : _g.email) !== null && _h !== void 0 ? _h : "",
|
|
31
|
+
};
|
|
32
|
+
if (res.user && id && res.user.name) {
|
|
33
|
+
this.cache.set(id, u);
|
|
34
|
+
return u;
|
|
35
|
+
}
|
|
36
|
+
return undefined;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
set(id, { email, name }) {
|
|
40
|
+
this.cache.set(id, { email, name });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
12
43
|
/* ===================== Helpers ===================== */
|
|
13
44
|
function normalizeChannelOperand(ch) {
|
|
14
45
|
const s = ch.trim();
|
|
@@ -30,19 +61,27 @@ function timeFilter(range) {
|
|
|
30
61
|
return "";
|
|
31
62
|
}
|
|
32
63
|
}
|
|
33
|
-
function lookupUserIdsByEmail(client, emails) {
|
|
64
|
+
function lookupUserIdsByEmail(client, emails, slackUserCache) {
|
|
34
65
|
return __awaiter(this, void 0, void 0, function* () {
|
|
35
|
-
var _a;
|
|
36
66
|
const ids = [];
|
|
37
|
-
|
|
67
|
+
const tasks = emails.map((raw) => __awaiter(this, void 0, void 0, function* () {
|
|
68
|
+
var _a;
|
|
38
69
|
const email = raw.trim();
|
|
39
70
|
if (!email)
|
|
40
|
-
|
|
71
|
+
return null;
|
|
41
72
|
const res = yield client.users.lookupByEmail({ email });
|
|
42
73
|
const id = (_a = res.user) === null || _a === void 0 ? void 0 : _a.id;
|
|
74
|
+
if (res.user && id && res.user.name) {
|
|
75
|
+
slackUserCache.set(id, { email, name: res.user.name });
|
|
76
|
+
}
|
|
43
77
|
if (id)
|
|
44
|
-
|
|
45
|
-
|
|
78
|
+
return id;
|
|
79
|
+
return null;
|
|
80
|
+
}));
|
|
81
|
+
const settled = yield Promise.allSettled(tasks);
|
|
82
|
+
for (const r of settled)
|
|
83
|
+
if (r.status === "fulfilled" && r.value)
|
|
84
|
+
ids.push(r.value);
|
|
46
85
|
return ids;
|
|
47
86
|
});
|
|
48
87
|
}
|
|
@@ -119,22 +158,27 @@ function fetchContextWindow(client, channel, ts) {
|
|
|
119
158
|
}
|
|
120
159
|
/* ===================== Main Export ===================== */
|
|
121
160
|
const searchSlack = (_a) => __awaiter(void 0, [_a], void 0, function* ({ params, authParams, }) {
|
|
122
|
-
var _b, _c
|
|
161
|
+
var _b, _c;
|
|
123
162
|
if (!authParams.authToken) {
|
|
124
163
|
throw new Error(MISSING_AUTH_TOKEN);
|
|
125
164
|
}
|
|
126
165
|
const client = new WebClient(authParams.authToken);
|
|
166
|
+
const slackUserCache = new SlackUserCache(client);
|
|
127
167
|
const { emails, channel, topic, timeRange, limit } = params;
|
|
128
168
|
const parts = [];
|
|
129
169
|
if (emails === null || emails === void 0 ? void 0 : emails.length) {
|
|
130
|
-
const userIds = yield lookupUserIdsByEmail(client, emails);
|
|
131
|
-
|
|
170
|
+
const userIds = yield lookupUserIdsByEmail(client, emails, slackUserCache);
|
|
171
|
+
const { user_id: myUserId } = yield client.auth.test();
|
|
172
|
+
if (!myUserId)
|
|
173
|
+
throw new Error("Failed to get my user ID.");
|
|
174
|
+
const userIdsWithoutMe = userIds.filter(id => id !== myUserId);
|
|
175
|
+
if (userIdsWithoutMe.length === 0)
|
|
132
176
|
throw new Error("No users resolved from emails.");
|
|
133
|
-
if (
|
|
134
|
-
parts.push(`in:<@${
|
|
177
|
+
if (userIdsWithoutMe.length == 1) {
|
|
178
|
+
parts.push(`in:<@${userIdsWithoutMe[0]}>`);
|
|
135
179
|
}
|
|
136
180
|
else {
|
|
137
|
-
const convoName = yield getMPIMName(client,
|
|
181
|
+
const convoName = yield getMPIMName(client, userIdsWithoutMe);
|
|
138
182
|
parts.push(`in:${convoName}`);
|
|
139
183
|
}
|
|
140
184
|
}
|
|
@@ -152,67 +196,103 @@ const searchSlack = (_a) => __awaiter(void 0, [_a], void 0, function* ({ params,
|
|
|
152
196
|
const count = Math.max(1, Math.min(100, limit));
|
|
153
197
|
const searchRes = yield client.search.messages({ query, count, highlight: true });
|
|
154
198
|
const matches = (_c = (_b = searchRes.messages) === null || _b === void 0 ? void 0 : _b.matches) !== null && _c !== void 0 ? _c : [];
|
|
155
|
-
const
|
|
156
|
-
var _a, _b;
|
|
157
|
-
|
|
199
|
+
const hitsPromises = matches.slice(0, limit).map((m) => __awaiter(void 0, void 0, void 0, function* () {
|
|
200
|
+
var _a, _b, _c, _d;
|
|
201
|
+
const user = m.user ? yield slackUserCache.get(m.user) : undefined;
|
|
202
|
+
return {
|
|
158
203
|
channelId: ((_a = m.channel) === null || _a === void 0 ? void 0 : _a.id) || ((_b = m.channel) === null || _b === void 0 ? void 0 : _b.name) || "",
|
|
159
204
|
ts: m.ts,
|
|
160
205
|
text: m.text,
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
206
|
+
userEmail: (_c = user === null || user === void 0 ? void 0 : user.email) !== null && _c !== void 0 ? _c : undefined,
|
|
207
|
+
userName: (_d = user === null || user === void 0 ? void 0 : user.name) !== null && _d !== void 0 ? _d : undefined,
|
|
208
|
+
};
|
|
209
|
+
}));
|
|
210
|
+
const hits = yield Promise.all(hitsPromises);
|
|
211
|
+
const tasks = hits.map(h => limitHit(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
212
|
+
var _a, _b, _c, _d, _e, _f;
|
|
166
213
|
if (!h.ts)
|
|
167
|
-
|
|
214
|
+
return null;
|
|
168
215
|
try {
|
|
169
216
|
const anchor = yield fetchOneMessage(client, h.channelId, h.ts);
|
|
170
217
|
const rootTs = (anchor === null || anchor === void 0 ? void 0 : anchor.thread_ts) || h.ts;
|
|
171
218
|
if (anchor === null || anchor === void 0 ? void 0 : anchor.thread_ts) {
|
|
172
|
-
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
219
|
+
// thread: fetch thread + permalink concurrently
|
|
220
|
+
const [thread, permalink] = yield Promise.all([
|
|
221
|
+
fetchThread(client, h.channelId, rootTs),
|
|
222
|
+
getPermalink(client, h.channelId, rootTs),
|
|
223
|
+
]);
|
|
224
|
+
const contextPromises = thread
|
|
225
|
+
.filter(t => t.ts)
|
|
226
|
+
.map((t) => __awaiter(void 0, void 0, void 0, function* () {
|
|
227
|
+
var _a, _b;
|
|
228
|
+
const user = t.user ? yield slackUserCache.get(t.user) : undefined;
|
|
229
|
+
return {
|
|
230
|
+
ts: t.ts,
|
|
231
|
+
text: t.text,
|
|
232
|
+
userEmail: (_a = user === null || user === void 0 ? void 0 : user.email) !== null && _a !== void 0 ? _a : undefined,
|
|
233
|
+
userName: (_b = user === null || user === void 0 ? void 0 : user.name) !== null && _b !== void 0 ? _b : undefined,
|
|
234
|
+
};
|
|
235
|
+
}));
|
|
236
|
+
const context = yield Promise.all(contextPromises);
|
|
237
|
+
const user = anchor.user ? yield slackUserCache.get(anchor.user) : undefined;
|
|
238
|
+
return {
|
|
180
239
|
channelId: h.channelId,
|
|
181
240
|
ts: rootTs,
|
|
182
|
-
text: (
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
241
|
+
text: (_a = anchor.text) !== null && _a !== void 0 ? _a : h.text,
|
|
242
|
+
userEmail: (_b = user === null || user === void 0 ? void 0 : user.email) !== null && _b !== void 0 ? _b : h.userEmail,
|
|
243
|
+
userName: (_c = user === null || user === void 0 ? void 0 : user.name) !== null && _c !== void 0 ? _c : h.userName,
|
|
244
|
+
context,
|
|
245
|
+
permalink,
|
|
246
|
+
};
|
|
187
247
|
}
|
|
188
248
|
else {
|
|
189
|
-
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
249
|
+
// not a thread: fetch context window + permalink concurrently
|
|
250
|
+
const [ctx, permalink] = yield Promise.all([
|
|
251
|
+
fetchContextWindow(client, h.channelId, h.ts),
|
|
252
|
+
getPermalink(client, h.channelId, h.ts),
|
|
253
|
+
]);
|
|
254
|
+
const contextPromises = ctx
|
|
255
|
+
.filter(t => t.ts)
|
|
256
|
+
.map((t) => __awaiter(void 0, void 0, void 0, function* () {
|
|
257
|
+
var _a, _b;
|
|
258
|
+
const user = t.user ? yield slackUserCache.get(t.user) : undefined;
|
|
259
|
+
return {
|
|
260
|
+
ts: t.ts,
|
|
261
|
+
text: t.text,
|
|
262
|
+
userEmail: (_a = user === null || user === void 0 ? void 0 : user.email) !== null && _a !== void 0 ? _a : undefined,
|
|
263
|
+
userName: (_b = user === null || user === void 0 ? void 0 : user.name) !== null && _b !== void 0 ? _b : undefined,
|
|
264
|
+
};
|
|
265
|
+
}));
|
|
266
|
+
const context = yield Promise.all(contextPromises);
|
|
267
|
+
const user = (anchor === null || anchor === void 0 ? void 0 : anchor.user) ? yield slackUserCache.get(anchor.user) : undefined;
|
|
268
|
+
return {
|
|
197
269
|
channelId: h.channelId,
|
|
198
270
|
ts: h.ts,
|
|
199
|
-
text: (
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
271
|
+
text: (_d = anchor === null || anchor === void 0 ? void 0 : anchor.text) !== null && _d !== void 0 ? _d : h.text,
|
|
272
|
+
userEmail: (_e = user === null || user === void 0 ? void 0 : user.email) !== null && _e !== void 0 ? _e : h.userEmail,
|
|
273
|
+
userName: (_f = user === null || user === void 0 ? void 0 : user.name) !== null && _f !== void 0 ? _f : h.userName,
|
|
274
|
+
context,
|
|
275
|
+
permalink,
|
|
276
|
+
};
|
|
204
277
|
}
|
|
205
278
|
}
|
|
206
|
-
catch (
|
|
207
|
-
|
|
279
|
+
catch (_g) {
|
|
280
|
+
// fallback minimal object; still in parallel
|
|
281
|
+
return {
|
|
208
282
|
channelId: h.channelId,
|
|
209
283
|
ts: h.ts,
|
|
210
284
|
text: h.text,
|
|
211
|
-
|
|
285
|
+
userEmail: h.userEmail,
|
|
286
|
+
userName: h.userName,
|
|
212
287
|
permalink: yield getPermalink(client, h.channelId, h.ts),
|
|
213
|
-
}
|
|
288
|
+
};
|
|
214
289
|
}
|
|
215
|
-
}
|
|
290
|
+
})));
|
|
291
|
+
const settled = yield Promise.allSettled(tasks);
|
|
292
|
+
const results = [];
|
|
293
|
+
for (const r of settled)
|
|
294
|
+
if (r.status === "fulfilled" && r.value)
|
|
295
|
+
results.push(r.value);
|
|
216
296
|
results.sort((a, b) => Number(b.ts) - Number(a.ts));
|
|
217
297
|
return { query, results };
|
|
218
298
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@credal/actions",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.112",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "AI Actions by Credal AI",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
"mammoth": "^1.4.27",
|
|
67
67
|
"mongodb": "^6.13.1",
|
|
68
68
|
"node-forge": "^1.3.1",
|
|
69
|
+
"p-limit": "^7.1.1",
|
|
69
70
|
"pdf2json": "^3.1.6",
|
|
70
71
|
"resend": "^4.7.0",
|
|
71
72
|
"snowflake-sdk": "^2.0.2",
|