@credal/actions 0.2.150 → 0.2.151
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.
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { type KnownBlock } from "@slack/web-api";
|
|
1
2
|
import { type slackUserSearchSlackFunction } from "../../autogen/types.js";
|
|
3
|
+
import type { Attachment } from "@slack/web-api/dist/types/response/ChannelsHistoryResponse.js";
|
|
2
4
|
export type TimeRange = "latest" | "today" | "yesterday" | "last_7d" | "last_30d" | "all";
|
|
3
5
|
export interface SlackSearchMessage {
|
|
4
6
|
channelId: string;
|
|
@@ -19,5 +21,18 @@ export interface SlackSearchMessage {
|
|
|
19
21
|
userName?: string;
|
|
20
22
|
}>;
|
|
21
23
|
}
|
|
24
|
+
interface SlackMessage {
|
|
25
|
+
ts?: string;
|
|
26
|
+
text?: string;
|
|
27
|
+
user?: string;
|
|
28
|
+
username?: string;
|
|
29
|
+
thread_ts?: string;
|
|
30
|
+
blocks?: KnownBlock[];
|
|
31
|
+
attachments?: Attachment[];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Extracts all visible text from a Slack message
|
|
35
|
+
*/
|
|
36
|
+
export declare function extractMessageText(m: SlackMessage | undefined): string | undefined;
|
|
22
37
|
declare const searchSlack: slackUserSearchSlackFunction;
|
|
23
38
|
export default searchSlack;
|
|
@@ -63,6 +63,164 @@ class SlackUserCache {
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
/* ===================== Helpers ===================== */
|
|
66
|
+
/* ===================== Helpers ===================== */
|
|
67
|
+
/**
|
|
68
|
+
* Extracts all visible text from a Slack message
|
|
69
|
+
*/
|
|
70
|
+
export function extractMessageText(m) {
|
|
71
|
+
var _a, _b, _c, _d;
|
|
72
|
+
if (!m)
|
|
73
|
+
return undefined;
|
|
74
|
+
const pieces = [];
|
|
75
|
+
// ---- Rich text helpers ----
|
|
76
|
+
const walkRichTextInline = (el) => {
|
|
77
|
+
var _a;
|
|
78
|
+
const blockPieces = [];
|
|
79
|
+
switch (el.type) {
|
|
80
|
+
case "text":
|
|
81
|
+
blockPieces.push(el.text);
|
|
82
|
+
break;
|
|
83
|
+
case "link":
|
|
84
|
+
blockPieces.push(el.text || el.url);
|
|
85
|
+
break;
|
|
86
|
+
case "user":
|
|
87
|
+
blockPieces.push(`<@${el.user_id}>`);
|
|
88
|
+
break;
|
|
89
|
+
case "channel":
|
|
90
|
+
blockPieces.push(`<#${el.channel_id}>`);
|
|
91
|
+
break;
|
|
92
|
+
case "emoji":
|
|
93
|
+
blockPieces.push(`:${el.name}:`);
|
|
94
|
+
break;
|
|
95
|
+
case "broadcast":
|
|
96
|
+
blockPieces.push(`@${el.range}`);
|
|
97
|
+
break;
|
|
98
|
+
case "date":
|
|
99
|
+
blockPieces.push((_a = el.fallback) !== null && _a !== void 0 ? _a : `<date:${el.timestamp}>`);
|
|
100
|
+
break;
|
|
101
|
+
case "team":
|
|
102
|
+
blockPieces.push(`<team:${el.team_id}>`);
|
|
103
|
+
break;
|
|
104
|
+
case "usergroup":
|
|
105
|
+
blockPieces.push(`<usergroup:${el.usergroup_id}>`);
|
|
106
|
+
break;
|
|
107
|
+
case "color":
|
|
108
|
+
// Usually formatting only, skip
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
return blockPieces;
|
|
112
|
+
};
|
|
113
|
+
const walkRichTextElement = (el) => {
|
|
114
|
+
const result = [];
|
|
115
|
+
switch (el.type) {
|
|
116
|
+
case "rich_text_section":
|
|
117
|
+
case "rich_text_quote":
|
|
118
|
+
result.push(el.elements.map(walkRichTextInline).join("\n"));
|
|
119
|
+
break;
|
|
120
|
+
case "rich_text_list":
|
|
121
|
+
result.push(el.elements.map(section => section.elements.map(walkRichTextInline).join("\n")).join("\n"));
|
|
122
|
+
break;
|
|
123
|
+
case "rich_text_preformatted":
|
|
124
|
+
result.push(el.elements.map(walkRichTextInline).join("\n"));
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
return result;
|
|
128
|
+
};
|
|
129
|
+
// ---- Block helpers ----
|
|
130
|
+
const walkBlock = (block) => {
|
|
131
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
132
|
+
const blockPieces = [];
|
|
133
|
+
switch (block.type) {
|
|
134
|
+
case "section":
|
|
135
|
+
if ((_a = block.text) === null || _a === void 0 ? void 0 : _a.text)
|
|
136
|
+
blockPieces.push(block.text.text);
|
|
137
|
+
if (block.fields) {
|
|
138
|
+
for (const f of block.fields)
|
|
139
|
+
if (f.text)
|
|
140
|
+
blockPieces.push(f.text);
|
|
141
|
+
}
|
|
142
|
+
if (block.accessory && "text" in block.accessory && block.accessory.text) {
|
|
143
|
+
blockPieces.push(block.accessory.text.text);
|
|
144
|
+
}
|
|
145
|
+
break;
|
|
146
|
+
case "context":
|
|
147
|
+
if (Array.isArray(block.elements)) {
|
|
148
|
+
block.elements.forEach(el => {
|
|
149
|
+
if ("text" in el && el.text)
|
|
150
|
+
blockPieces.push(el.text);
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
break;
|
|
154
|
+
case "header":
|
|
155
|
+
if ((_b = block.text) === null || _b === void 0 ? void 0 : _b.text)
|
|
156
|
+
blockPieces.push(block.text.text);
|
|
157
|
+
break;
|
|
158
|
+
case "rich_text":
|
|
159
|
+
blockPieces.push(block.elements.map(walkRichTextElement).join("\n"));
|
|
160
|
+
break;
|
|
161
|
+
case "markdown":
|
|
162
|
+
if (block.text)
|
|
163
|
+
blockPieces.push(block.text);
|
|
164
|
+
break;
|
|
165
|
+
case "video":
|
|
166
|
+
if ((_c = block.title) === null || _c === void 0 ? void 0 : _c.text)
|
|
167
|
+
blockPieces.push(block.title.text);
|
|
168
|
+
if ((_d = block.description) === null || _d === void 0 ? void 0 : _d.text)
|
|
169
|
+
blockPieces.push(block.description.text);
|
|
170
|
+
break;
|
|
171
|
+
case "image":
|
|
172
|
+
if ((_e = block.title) === null || _e === void 0 ? void 0 : _e.text)
|
|
173
|
+
blockPieces.push(block.title.text);
|
|
174
|
+
break;
|
|
175
|
+
case "input":
|
|
176
|
+
if ((_f = block.label) === null || _f === void 0 ? void 0 : _f.text)
|
|
177
|
+
blockPieces.push(block.label.text);
|
|
178
|
+
if ((_g = block.hint) === null || _g === void 0 ? void 0 : _g.text)
|
|
179
|
+
blockPieces.push(block.hint.text);
|
|
180
|
+
break;
|
|
181
|
+
// divider, file, actions, input don’t contribute visible text
|
|
182
|
+
case "divider":
|
|
183
|
+
case "file":
|
|
184
|
+
case "actions":
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
return blockPieces;
|
|
188
|
+
};
|
|
189
|
+
let blockText = "";
|
|
190
|
+
if (Array.isArray(m.blocks)) {
|
|
191
|
+
const blockPieces = m.blocks.map(b => walkBlock(b));
|
|
192
|
+
blockText = blockPieces.join("\n");
|
|
193
|
+
}
|
|
194
|
+
if (blockText) {
|
|
195
|
+
pieces.push(blockText);
|
|
196
|
+
}
|
|
197
|
+
else if (m.text) {
|
|
198
|
+
pieces.push(m.text);
|
|
199
|
+
}
|
|
200
|
+
// 3. Attachments
|
|
201
|
+
if (m.attachments) {
|
|
202
|
+
for (const att of m.attachments) {
|
|
203
|
+
if (att.pretext)
|
|
204
|
+
pieces.push(att.pretext);
|
|
205
|
+
if (att.title)
|
|
206
|
+
pieces.push(att.title);
|
|
207
|
+
if (att.text)
|
|
208
|
+
pieces.push(att.text);
|
|
209
|
+
if (att.fields) {
|
|
210
|
+
for (const f of att.fields) {
|
|
211
|
+
const title = (_b = (_a = f.title) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : "";
|
|
212
|
+
const value = (_d = (_c = f.value) === null || _c === void 0 ? void 0 : _c.trim()) !== null && _d !== void 0 ? _d : "";
|
|
213
|
+
if (title || value) {
|
|
214
|
+
pieces.push(title && value ? `${title}: ${value}` : title || value);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// Deduplicate and join
|
|
221
|
+
const out = Array.from(new Set(pieces.map(s => s.trim()).filter(Boolean))).join("\n");
|
|
222
|
+
return out || undefined;
|
|
223
|
+
}
|
|
66
224
|
function normalizeChannelOperand(ch) {
|
|
67
225
|
const s = ch.trim();
|
|
68
226
|
if (/^[CGD][A-Z0-9]/i.test(s))
|
|
@@ -139,18 +297,32 @@ function getPermalink(client, channel, ts) {
|
|
|
139
297
|
}
|
|
140
298
|
});
|
|
141
299
|
}
|
|
300
|
+
function transformToSlackMessage(message) {
|
|
301
|
+
return {
|
|
302
|
+
ts: message.ts,
|
|
303
|
+
text: message.text,
|
|
304
|
+
user: message.user,
|
|
305
|
+
username: message.username,
|
|
306
|
+
thread_ts: message.thread_ts,
|
|
307
|
+
blocks: message.blocks,
|
|
308
|
+
attachments: message.attachments,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
142
311
|
function fetchOneMessage(client, channel, ts) {
|
|
143
312
|
return __awaiter(this, void 0, void 0, function* () {
|
|
144
313
|
var _a;
|
|
145
314
|
const r = yield client.conversations.history({ channel, latest: ts, inclusive: true, limit: 1 });
|
|
146
|
-
|
|
315
|
+
const message = (_a = r.messages) === null || _a === void 0 ? void 0 : _a[0];
|
|
316
|
+
if (!message)
|
|
317
|
+
return undefined;
|
|
318
|
+
return transformToSlackMessage(message);
|
|
147
319
|
});
|
|
148
320
|
}
|
|
149
321
|
function fetchThread(client, channel, threadTs) {
|
|
150
322
|
return __awaiter(this, void 0, void 0, function* () {
|
|
151
|
-
var _a;
|
|
323
|
+
var _a, _b;
|
|
152
324
|
const r = yield client.conversations.replies({ channel, ts: threadTs, limit: 20 });
|
|
153
|
-
return (_a = r.messages) !== null &&
|
|
325
|
+
return (_b = (_a = r.messages) === null || _a === void 0 ? void 0 : _a.map(transformToSlackMessage)) !== null && _b !== void 0 ? _b : [];
|
|
154
326
|
});
|
|
155
327
|
}
|
|
156
328
|
function fetchContextWindow(client, channel, ts) {
|
|
@@ -161,10 +333,12 @@ function fetchContextWindow(client, channel, ts) {
|
|
|
161
333
|
if (!anchor)
|
|
162
334
|
return out;
|
|
163
335
|
const before = yield client.conversations.history({ channel, latest: ts, inclusive: false, limit: 3 });
|
|
164
|
-
|
|
336
|
+
const beforeMessages = (_a = before.messages) === null || _a === void 0 ? void 0 : _a.map(transformToSlackMessage);
|
|
337
|
+
out.push(...(beforeMessages !== null && beforeMessages !== void 0 ? beforeMessages : []).reverse());
|
|
165
338
|
out.push(anchor);
|
|
166
339
|
const after = yield client.conversations.history({ channel, oldest: ts, inclusive: false, limit: 3 });
|
|
167
|
-
|
|
340
|
+
const afterMessages = (_b = after.messages) === null || _b === void 0 ? void 0 : _b.map(transformToSlackMessage);
|
|
341
|
+
out.push(...(afterMessages !== null && afterMessages !== void 0 ? afterMessages : []));
|
|
168
342
|
return out;
|
|
169
343
|
});
|
|
170
344
|
}
|
|
@@ -316,18 +490,20 @@ const searchSlack = (_a) => __awaiter(void 0, [_a], void 0, function* ({ params,
|
|
|
316
490
|
const context = yield Promise.all(contextMsgs.map((t) => __awaiter(void 0, void 0, void 0, function* () {
|
|
317
491
|
var _a;
|
|
318
492
|
const u = t.user ? yield cache.get(t.user) : undefined;
|
|
493
|
+
const rawText = extractMessageText(t);
|
|
319
494
|
return {
|
|
320
495
|
ts: t.ts,
|
|
321
|
-
text:
|
|
496
|
+
text: rawText ? yield expandSlackEntities(cache, rawText) : undefined,
|
|
322
497
|
userEmail: u === null || u === void 0 ? void 0 : u.email,
|
|
323
498
|
userName: (_a = u === null || u === void 0 ? void 0 : u.name) !== null && _a !== void 0 ? _a : t.username,
|
|
324
499
|
};
|
|
325
500
|
})));
|
|
326
501
|
const anchorUser = (anchor === null || anchor === void 0 ? void 0 : anchor.user) ? yield cache.get(anchor.user) : undefined;
|
|
502
|
+
const anchorText = extractMessageText(anchor);
|
|
327
503
|
return {
|
|
328
504
|
channelId: m.channel.id,
|
|
329
505
|
ts: rootTs,
|
|
330
|
-
text:
|
|
506
|
+
text: anchorText ? yield expandSlackEntities(cache, anchorText) : undefined,
|
|
331
507
|
userEmail: anchorUser === null || anchorUser === void 0 ? void 0 : anchorUser.email,
|
|
332
508
|
userName: (_j = anchorUser === null || anchorUser === void 0 ? void 0 : anchorUser.name) !== null && _j !== void 0 ? _j : anchor === null || anchor === void 0 ? void 0 : anchor.username,
|
|
333
509
|
context,
|