@credal/actions 0.2.153 → 0.2.155
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/actions/autogen/templates.js +29 -0
- package/dist/actions/autogen/types.d.ts +25 -4
- package/dist/actions/autogen/types.js +28 -0
- package/dist/actions/groups.js +14 -1
- package/dist/actions/providers/confluence/updatePage.d.ts +3 -0
- package/dist/actions/providers/confluence/updatePage.js +46 -0
- package/dist/actions/providers/generic/fillTemplateAction.d.ts +7 -0
- package/dist/actions/providers/generic/fillTemplateAction.js +18 -0
- package/dist/actions/providers/generic/genericApiCall.d.ts +3 -0
- package/dist/actions/providers/generic/genericApiCall.js +38 -0
- package/dist/actions/providers/google-oauth/getDriveContentById.d.ts +3 -0
- package/dist/actions/providers/google-oauth/getDriveContentById.js +161 -0
- package/dist/actions/providers/google-oauth/searchAndGetDriveContentByKeywords.d.ts +3 -0
- package/dist/actions/providers/google-oauth/searchAndGetDriveContentByKeywords.js +47 -0
- package/dist/actions/providers/google-oauth/searchDriveAndGetContentByKeywords.d.ts +3 -0
- package/dist/actions/providers/google-oauth/searchDriveAndGetContentByKeywords.js +110 -0
- package/dist/actions/providers/google-oauth/searchDriveAndGetContentByQuery.d.ts +3 -0
- package/dist/actions/providers/google-oauth/searchDriveAndGetContentByQuery.js +78 -0
- package/dist/actions/providers/google-oauth/utils/extractContentFromDriveFileId.d.ts +15 -0
- package/dist/actions/providers/google-oauth/utils/extractContentFromDriveFileId.js +129 -0
- package/dist/actions/providers/googlemaps/nearbysearch.d.ts +3 -0
- package/dist/actions/providers/googlemaps/nearbysearch.js +96 -0
- package/dist/actions/providers/slack/archiveChannel.js +9 -2
- package/dist/actions/providers/slack/getChannelMessages.js +98 -2
- package/dist/actions/providers/slack/messageTransformers.d.ts +53 -0
- package/dist/actions/providers/slack/messageTransformers.js +267 -0
- package/dist/actions/providers/slackUser/getSlackMessagesInTimeRange.d.ts +3 -0
- package/dist/actions/providers/slackUser/getSlackMessagesInTimeRange.js +81 -0
- package/dist/actions/providers/slackUser/searchSlack.d.ts +0 -15
- package/dist/actions/providers/slackUser/searchSlack.js +70 -193
- package/dist/actions/providers/snowflake/runSnowflakeQueryWriteResultsToS3.d.ts +3 -0
- package/dist/actions/providers/snowflake/runSnowflakeQueryWriteResultsToS3.js +154 -0
- package/dist/actions/providers/x/scrapeTweetDataWithNitter.d.ts +3 -0
- package/dist/actions/providers/x/scrapeTweetDataWithNitter.js +45 -0
- package/package.json +2 -2
- package/dist/actions/providers/salesforce/getSalesforceRecordByQuery.d.ts +0 -3
- package/dist/actions/providers/salesforce/getSalesforceRecordByQuery.js +0 -43
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the highest quality thumbnail from a file
|
|
3
|
+
*/
|
|
4
|
+
export function getHighestQualityThumb(file) {
|
|
5
|
+
const thumbSizes = [
|
|
6
|
+
"thumb_1024",
|
|
7
|
+
"thumb_960",
|
|
8
|
+
"thumb_800",
|
|
9
|
+
"thumb_720",
|
|
10
|
+
"thumb_480",
|
|
11
|
+
"thumb_360",
|
|
12
|
+
"thumb_160",
|
|
13
|
+
"thumb_80",
|
|
14
|
+
"thumb_64",
|
|
15
|
+
];
|
|
16
|
+
for (const size of thumbSizes) {
|
|
17
|
+
const thumb = file[size];
|
|
18
|
+
if (thumb && typeof thumb === "string") {
|
|
19
|
+
return thumb;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Simplify file objects to only include essential fields and highest quality thumbnail
|
|
26
|
+
*/
|
|
27
|
+
export function simplifyFile(file) {
|
|
28
|
+
const simplified = {
|
|
29
|
+
id: file.id,
|
|
30
|
+
created: file.created,
|
|
31
|
+
timestamp: file.timestamp,
|
|
32
|
+
name: file.name,
|
|
33
|
+
title: file.title,
|
|
34
|
+
mimetype: file.mimetype,
|
|
35
|
+
file_access: file.file_access,
|
|
36
|
+
};
|
|
37
|
+
const highestThumb = getHighestQualityThumb(file);
|
|
38
|
+
if (highestThumb) {
|
|
39
|
+
simplified.highest_thumb = highestThumb;
|
|
40
|
+
}
|
|
41
|
+
return simplified;
|
|
42
|
+
}
|
|
43
|
+
// Redundant fields to remove from messages - not useful (fills up context window so we can ditch these)
|
|
44
|
+
const REDUNDANT_FIELDS = [
|
|
45
|
+
// Image/media metadata
|
|
46
|
+
"app_icons",
|
|
47
|
+
"image_width",
|
|
48
|
+
"image_height",
|
|
49
|
+
"image_bytes",
|
|
50
|
+
"fallback",
|
|
51
|
+
"is_animated",
|
|
52
|
+
// Message metadata (not content-related)
|
|
53
|
+
"team",
|
|
54
|
+
"client_msg_id",
|
|
55
|
+
"is_locked",
|
|
56
|
+
"subscribed",
|
|
57
|
+
"display_as_bot",
|
|
58
|
+
"upload",
|
|
59
|
+
// Block metadata
|
|
60
|
+
"block_id",
|
|
61
|
+
"unicode", // Emoji unicode values (name is sufficient)
|
|
62
|
+
// File metadata (duplicates or not useful)
|
|
63
|
+
"file_access",
|
|
64
|
+
"filetype", // Redundant with mimetype
|
|
65
|
+
"pretty_type", // Redundant with mimetype
|
|
66
|
+
"thumb_tiny", // Base64 preview, not needed
|
|
67
|
+
// Attachment metadata
|
|
68
|
+
"service_icon", // Icon URLs for link previews
|
|
69
|
+
"from_url", // Duplicate of original_url
|
|
70
|
+
];
|
|
71
|
+
/**
|
|
72
|
+
* Recursively remove redundant fields from an object to reduce payload size
|
|
73
|
+
*/
|
|
74
|
+
export function removeRedundantFields(obj) {
|
|
75
|
+
for (const key of REDUNDANT_FIELDS) {
|
|
76
|
+
delete obj[key];
|
|
77
|
+
}
|
|
78
|
+
// Recursively clean nested objects and arrays
|
|
79
|
+
for (const key in obj) {
|
|
80
|
+
const value = obj[key];
|
|
81
|
+
if (value && typeof value === "object") {
|
|
82
|
+
if (Array.isArray(value)) {
|
|
83
|
+
value.forEach(item => {
|
|
84
|
+
if (item && typeof item === "object") {
|
|
85
|
+
removeRedundantFields(item);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
removeRedundantFields(value);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Extracts all visible text from a Slack message
|
|
97
|
+
*/
|
|
98
|
+
export function extractMessageText(m) {
|
|
99
|
+
var _a, _b, _c, _d;
|
|
100
|
+
if (!m)
|
|
101
|
+
return undefined;
|
|
102
|
+
const pieces = [];
|
|
103
|
+
// ---- Rich text helpers ----
|
|
104
|
+
const walkRichTextInline = (el) => {
|
|
105
|
+
var _a;
|
|
106
|
+
const blockPieces = [];
|
|
107
|
+
switch (el.type) {
|
|
108
|
+
case "text":
|
|
109
|
+
blockPieces.push(el.text);
|
|
110
|
+
break;
|
|
111
|
+
case "link":
|
|
112
|
+
blockPieces.push(el.text || el.url);
|
|
113
|
+
break;
|
|
114
|
+
case "user":
|
|
115
|
+
blockPieces.push(`<@${el.user_id}>`);
|
|
116
|
+
break;
|
|
117
|
+
case "channel":
|
|
118
|
+
blockPieces.push(`<#${el.channel_id}>`);
|
|
119
|
+
break;
|
|
120
|
+
case "emoji":
|
|
121
|
+
blockPieces.push(`:${el.name}:`);
|
|
122
|
+
break;
|
|
123
|
+
case "broadcast":
|
|
124
|
+
blockPieces.push(`@${el.range}`);
|
|
125
|
+
break;
|
|
126
|
+
case "date":
|
|
127
|
+
blockPieces.push((_a = el.fallback) !== null && _a !== void 0 ? _a : `<date:${el.timestamp}>`);
|
|
128
|
+
break;
|
|
129
|
+
case "team":
|
|
130
|
+
blockPieces.push(`<team:${el.team_id}>`);
|
|
131
|
+
break;
|
|
132
|
+
case "usergroup":
|
|
133
|
+
blockPieces.push(`<usergroup:${el.usergroup_id}>`);
|
|
134
|
+
break;
|
|
135
|
+
case "color":
|
|
136
|
+
// Usually formatting only, skip
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
return blockPieces;
|
|
140
|
+
};
|
|
141
|
+
const walkRichTextElement = (el) => {
|
|
142
|
+
const result = [];
|
|
143
|
+
switch (el.type) {
|
|
144
|
+
case "rich_text_section":
|
|
145
|
+
case "rich_text_quote":
|
|
146
|
+
result.push(el.elements.map(walkRichTextInline).join("\n"));
|
|
147
|
+
break;
|
|
148
|
+
case "rich_text_list":
|
|
149
|
+
result.push(el.elements.map(section => section.elements.map(walkRichTextInline).join("\n")).join("\n"));
|
|
150
|
+
break;
|
|
151
|
+
case "rich_text_preformatted":
|
|
152
|
+
result.push(el.elements.map(walkRichTextInline).join("\n"));
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
return result;
|
|
156
|
+
};
|
|
157
|
+
// ---- Block helpers ----
|
|
158
|
+
const walkBlock = (block) => {
|
|
159
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
160
|
+
const blockPieces = [];
|
|
161
|
+
switch (block.type) {
|
|
162
|
+
case "section":
|
|
163
|
+
if ((_a = block.text) === null || _a === void 0 ? void 0 : _a.text)
|
|
164
|
+
blockPieces.push(block.text.text);
|
|
165
|
+
if (block.fields) {
|
|
166
|
+
for (const f of block.fields)
|
|
167
|
+
if (f.text)
|
|
168
|
+
blockPieces.push(f.text);
|
|
169
|
+
}
|
|
170
|
+
if (block.accessory && "text" in block.accessory && block.accessory.text) {
|
|
171
|
+
blockPieces.push(block.accessory.text.text);
|
|
172
|
+
}
|
|
173
|
+
break;
|
|
174
|
+
case "context":
|
|
175
|
+
if (Array.isArray(block.elements)) {
|
|
176
|
+
block.elements.forEach(el => {
|
|
177
|
+
if ("text" in el && el.text)
|
|
178
|
+
blockPieces.push(el.text);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
break;
|
|
182
|
+
case "header":
|
|
183
|
+
if ((_b = block.text) === null || _b === void 0 ? void 0 : _b.text)
|
|
184
|
+
blockPieces.push(block.text.text);
|
|
185
|
+
break;
|
|
186
|
+
case "rich_text":
|
|
187
|
+
blockPieces.push(block.elements.map(walkRichTextElement).join("\n"));
|
|
188
|
+
break;
|
|
189
|
+
case "markdown":
|
|
190
|
+
if (block.text)
|
|
191
|
+
blockPieces.push(block.text);
|
|
192
|
+
break;
|
|
193
|
+
case "video":
|
|
194
|
+
if ((_c = block.title) === null || _c === void 0 ? void 0 : _c.text)
|
|
195
|
+
blockPieces.push(block.title.text);
|
|
196
|
+
if ((_d = block.description) === null || _d === void 0 ? void 0 : _d.text)
|
|
197
|
+
blockPieces.push(block.description.text);
|
|
198
|
+
break;
|
|
199
|
+
case "image":
|
|
200
|
+
if ((_e = block.title) === null || _e === void 0 ? void 0 : _e.text)
|
|
201
|
+
blockPieces.push(block.title.text);
|
|
202
|
+
break;
|
|
203
|
+
case "input":
|
|
204
|
+
if ((_f = block.label) === null || _f === void 0 ? void 0 : _f.text)
|
|
205
|
+
blockPieces.push(block.label.text);
|
|
206
|
+
if ((_g = block.hint) === null || _g === void 0 ? void 0 : _g.text)
|
|
207
|
+
blockPieces.push(block.hint.text);
|
|
208
|
+
break;
|
|
209
|
+
// divider, file, actions, input don't contribute visible text
|
|
210
|
+
case "divider":
|
|
211
|
+
case "file":
|
|
212
|
+
case "actions":
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
return blockPieces;
|
|
216
|
+
};
|
|
217
|
+
let blockText = "";
|
|
218
|
+
if (Array.isArray(m.blocks)) {
|
|
219
|
+
const blockPieces = m.blocks.map(b => walkBlock(b));
|
|
220
|
+
blockText = blockPieces.join("\n");
|
|
221
|
+
}
|
|
222
|
+
if (blockText) {
|
|
223
|
+
pieces.push(blockText);
|
|
224
|
+
}
|
|
225
|
+
else if (m.text) {
|
|
226
|
+
pieces.push(m.text);
|
|
227
|
+
}
|
|
228
|
+
// 3. Attachments
|
|
229
|
+
if (m.attachments) {
|
|
230
|
+
for (const att of m.attachments) {
|
|
231
|
+
if (att.pretext)
|
|
232
|
+
pieces.push(att.pretext);
|
|
233
|
+
if (att.title)
|
|
234
|
+
pieces.push(att.title);
|
|
235
|
+
if (att.text)
|
|
236
|
+
pieces.push(att.text);
|
|
237
|
+
if (att.fields) {
|
|
238
|
+
for (const f of att.fields) {
|
|
239
|
+
const title = (_b = (_a = f.title) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : "";
|
|
240
|
+
const value = (_d = (_c = f.value) === null || _c === void 0 ? void 0 : _c.trim()) !== null && _d !== void 0 ? _d : "";
|
|
241
|
+
if (title || value) {
|
|
242
|
+
pieces.push(title && value ? `${title}: ${value}` : title || value);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// Deduplicate and join
|
|
249
|
+
const out = Array.from(new Set(pieces.map(s => s.trim()).filter(Boolean))).join("\n");
|
|
250
|
+
return out || undefined;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Transforms a Slack MessageElement to a simplified SlackMessage
|
|
254
|
+
*/
|
|
255
|
+
export function transformToSlackMessage(message) {
|
|
256
|
+
return {
|
|
257
|
+
ts: message.ts,
|
|
258
|
+
text: message.text,
|
|
259
|
+
user: message.user,
|
|
260
|
+
username: message.username,
|
|
261
|
+
thread_ts: message.thread_ts,
|
|
262
|
+
blocks: message.blocks,
|
|
263
|
+
attachments: message.attachments,
|
|
264
|
+
reactions: message.reactions,
|
|
265
|
+
files: message.files,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { WebClient } from "@slack/web-api";
|
|
11
|
+
import { MISSING_AUTH_TOKEN } from "../../util/missingAuthConstants.js";
|
|
12
|
+
import { extractMessageText, SlackUserCache, normalizeChannelOperand } from "./searchSlack.js";
|
|
13
|
+
/* ===================== Helpers ===================== */
|
|
14
|
+
function searchMessagesInTimeRange(input) {
|
|
15
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
16
|
+
var _a, _b;
|
|
17
|
+
const { client, channel, oldest, latest, limit } = input;
|
|
18
|
+
// Build search query - use wildcard to match all messages
|
|
19
|
+
const parts = [`in:${normalizeChannelOperand(channel)}`];
|
|
20
|
+
if (oldest) {
|
|
21
|
+
parts.push(`after:${oldest}`);
|
|
22
|
+
}
|
|
23
|
+
if (latest) {
|
|
24
|
+
parts.push(`before:${latest}`);
|
|
25
|
+
}
|
|
26
|
+
// Use * as a wildcard to match all messages
|
|
27
|
+
const query = parts.join(" ") + " *";
|
|
28
|
+
const searchRes = yield client.search.messages({ query, count: limit, highlight: true });
|
|
29
|
+
return (_b = (_a = searchRes.messages) === null || _a === void 0 ? void 0 : _a.matches) !== null && _b !== void 0 ? _b : [];
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/* ===================== MAIN EXPORT ===================== */
|
|
33
|
+
const getSlackMessagesInTimeRange = (_a) => __awaiter(void 0, [_a], void 0, function* ({ params, authParams, }) {
|
|
34
|
+
if (!authParams.authToken)
|
|
35
|
+
throw new Error(MISSING_AUTH_TOKEN);
|
|
36
|
+
const client = new WebClient(authParams.authToken);
|
|
37
|
+
const cache = new SlackUserCache(client);
|
|
38
|
+
const { channel, oldest, limit = 50 } = params;
|
|
39
|
+
let { latest } = params;
|
|
40
|
+
// Ensure latest doesn't exceed current time
|
|
41
|
+
const now = Math.floor(Date.now() / 1000);
|
|
42
|
+
if (latest && latest > now) {
|
|
43
|
+
latest = now;
|
|
44
|
+
}
|
|
45
|
+
const { user_id: myUserId } = yield client.auth.test();
|
|
46
|
+
if (!myUserId)
|
|
47
|
+
throw new Error("Failed to get my user ID.");
|
|
48
|
+
const meInfo = yield cache.get(myUserId);
|
|
49
|
+
// Search for messages in the channel using search API
|
|
50
|
+
const matches = yield searchMessagesInTimeRange({ client, channel, oldest, latest, limit });
|
|
51
|
+
// Convert matches to results
|
|
52
|
+
const results = yield Promise.all(matches.map((m) => __awaiter(void 0, void 0, void 0, function* () {
|
|
53
|
+
var _a, _b, _c, _d;
|
|
54
|
+
if (!m.ts || !((_a = m.channel) === null || _a === void 0 ? void 0 : _a.id))
|
|
55
|
+
return null;
|
|
56
|
+
// Get user info for the message author
|
|
57
|
+
const userId = (_b = m.user) !== null && _b !== void 0 ? _b : m.username;
|
|
58
|
+
const userInfo = userId ? yield cache.get(userId) : undefined;
|
|
59
|
+
// Extract text from the match
|
|
60
|
+
const text = (_d = (_c = extractMessageText(m)) !== null && _c !== void 0 ? _c : m.text) !== null && _d !== void 0 ? _d : "";
|
|
61
|
+
return {
|
|
62
|
+
channelId: m.channel.id,
|
|
63
|
+
ts: m.ts,
|
|
64
|
+
text,
|
|
65
|
+
userEmail: userInfo === null || userInfo === void 0 ? void 0 : userInfo.email,
|
|
66
|
+
userName: userInfo === null || userInfo === void 0 ? void 0 : userInfo.name,
|
|
67
|
+
permalink: m.permalink,
|
|
68
|
+
};
|
|
69
|
+
})));
|
|
70
|
+
// Filter out nulls and sort by timestamp descending
|
|
71
|
+
const validResults = results.filter(Boolean).sort((a, b) => Number(b.ts) - Number(a.ts));
|
|
72
|
+
return {
|
|
73
|
+
results: validResults.map(r => ({
|
|
74
|
+
name: r.text || "Untitled",
|
|
75
|
+
url: r.permalink || "",
|
|
76
|
+
contents: r,
|
|
77
|
+
})),
|
|
78
|
+
currentUser: { userId: myUserId, userName: meInfo === null || meInfo === void 0 ? void 0 : meInfo.name, userEmail: meInfo === null || meInfo === void 0 ? void 0 : meInfo.email },
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
export default getSlackMessagesInTimeRange;
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { type KnownBlock } from "@slack/web-api";
|
|
2
1
|
import { type slackUserSearchSlackFunction } from "../../autogen/types.js";
|
|
3
|
-
import type { Attachment } from "@slack/web-api/dist/types/response/ChannelsHistoryResponse.js";
|
|
4
2
|
export type TimeRange = "latest" | "today" | "yesterday" | "last_7d" | "last_30d" | "all";
|
|
5
3
|
export interface SlackSearchMessage {
|
|
6
4
|
channelId: string;
|
|
@@ -21,18 +19,5 @@ export interface SlackSearchMessage {
|
|
|
21
19
|
userName?: string;
|
|
22
20
|
}>;
|
|
23
21
|
}
|
|
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;
|
|
37
22
|
declare const searchSlack: slackUserSearchSlackFunction;
|
|
38
23
|
export default searchSlack;
|