@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
- return (_a = r.messages) === null || _a === void 0 ? void 0 : _a[0];
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 && _a !== void 0 ? _a : [];
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
- out.push(...((_a = before.messages) !== null && _a !== void 0 ? _a : []).reverse());
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
- out.push(...((_b = after.messages) !== null && _b !== void 0 ? _b : []));
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: t.text ? yield expandSlackEntities(cache, t.text) : undefined,
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: (anchor === null || anchor === void 0 ? void 0 : anchor.text) ? yield expandSlackEntities(cache, anchor.text) : undefined,
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,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@credal/actions",
3
- "version": "0.2.150",
3
+ "version": "0.2.151",
4
4
  "type": "module",
5
5
  "description": "AI Actions by Credal AI",
6
6
  "sideEffects": false,