@credal/actions 0.2.145 → 0.2.147

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.
Files changed (29) hide show
  1. package/README.md +1 -1
  2. package/dist/actions/autogen/templates.js +22 -1
  3. package/dist/actions/autogen/types.d.ts +43 -0
  4. package/dist/actions/autogen/types.js +9 -1
  5. package/dist/actions/groups.d.ts +6 -0
  6. package/dist/actions/groups.js +261 -0
  7. package/dist/actions/providers/confluence/updatePage.d.ts +3 -0
  8. package/dist/actions/providers/confluence/updatePage.js +47 -0
  9. package/dist/actions/providers/credal/callCopilot.d.ts +3 -0
  10. package/dist/actions/providers/credal/callCopilot.js +36 -0
  11. package/dist/actions/providers/gitlab/getFileContent.js +4 -1
  12. package/dist/actions/providers/gitlab/searchGroup.js +1 -27
  13. package/dist/actions/providers/gitlab/utils.d.ts +3 -0
  14. package/dist/actions/providers/gitlab/utils.js +37 -0
  15. package/dist/actions/providers/jamf/types.d.ts +8 -0
  16. package/dist/actions/providers/jamf/types.js +7 -0
  17. package/dist/actions/providers/math/index.d.ts +1 -0
  18. package/dist/actions/providers/math/index.js +37 -0
  19. package/dist/actions/providers/slack/archiveChannel.d.ts +3 -0
  20. package/dist/actions/providers/slack/archiveChannel.js +42 -0
  21. package/dist/actions/providers/slack/index.d.ts +1 -0
  22. package/dist/actions/providers/slack/index.js +37 -0
  23. package/dist/actions/providers/slack/listConversations.d.ts +3 -0
  24. package/dist/actions/providers/slack/listConversations.js +41 -0
  25. package/dist/actions/providers/slackUser/searchSlack.d.ts +6 -1
  26. package/dist/actions/providers/slackUser/searchSlack.js +183 -242
  27. package/package.json +1 -1
  28. package/dist/actions/providers/jira/updateServiceDeskRequest.d.ts +0 -3
  29. package/dist/actions/providers/jira/updateServiceDeskRequest.js +0 -72
@@ -10,12 +10,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import { WebClient } from "@slack/web-api";
11
11
  import { MISSING_AUTH_TOKEN } from "../../util/missingAuthConstants.js";
12
12
  import pLimit from "p-limit";
13
+ /* ===================== Constants ===================== */
13
14
  const HIT_ENRICH_POOL = 5;
14
15
  const limitHit = pLimit(HIT_ENRICH_POOL);
15
16
  const MENTION_USER_RE = /<@([UW][A-Z0-9]+)(?:\|[^>]+)?>/g;
16
17
  const MENTION_CHANNEL_RE = /<#(C[A-Z0-9]+)(?:\|[^>]+)?>/g;
17
18
  const SPECIAL_RE = /<!(channel|here|everyone)>/g;
18
- const SUBTEAM_RE = /<!subteam\^([A-Z0-9]+)(?:\|[^>]+)?>/g; // user group
19
+ const SUBTEAM_RE = /<!subteam\^([A-Z0-9]+)(?:\|[^>]+)?>/g;
20
+ /* ===================== Cache ===================== */
19
21
  class SlackUserCache {
20
22
  constructor(client) {
21
23
  this.client = client;
@@ -25,9 +27,9 @@ class SlackUserCache {
25
27
  get(id) {
26
28
  return __awaiter(this, void 0, void 0, function* () {
27
29
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
28
- const result = this.cache.get(id);
29
- if (result)
30
- return result;
30
+ const cached = this.cache.get(id);
31
+ if (cached)
32
+ return cached;
31
33
  const res = yield this.client.users.info({ user: id });
32
34
  const u = {
33
35
  name: (_g = (_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 : (_f = res.user) === null || _f === void 0 ? void 0 : _f.name) !== null && _g !== void 0 ? _g : "",
@@ -54,7 +56,7 @@ function normalizeChannelOperand(ch) {
54
56
  function fmtDaysAgo(n) {
55
57
  const d = new Date();
56
58
  d.setDate(d.getDate() - n);
57
- return d.toISOString().slice(0, 10); // YYYY-MM-DD
59
+ return d.toISOString().slice(0, 10);
58
60
  }
59
61
  function timeFilter(range) {
60
62
  switch (range) {
@@ -70,45 +72,44 @@ function timeFilter(range) {
70
72
  return "";
71
73
  }
72
74
  }
73
- function lookupUserIdsByEmail(client, emails, slackUserCache) {
75
+ function lookupUserIdsByEmail(client, emails, cache) {
74
76
  return __awaiter(this, void 0, void 0, function* () {
75
77
  const ids = [];
76
- const tasks = emails.map((raw) => __awaiter(this, void 0, void 0, function* () {
77
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
78
+ const settled = yield Promise.allSettled(emails.map((raw) => __awaiter(this, void 0, void 0, function* () {
79
+ var _a, _b, _c, _d, _e, _f, _g;
78
80
  const email = raw.trim();
79
81
  if (!email)
80
82
  return null;
81
83
  const res = yield client.users.lookupByEmail({ email });
82
84
  const id = (_a = res.user) === null || _a === void 0 ? void 0 : _a.id;
83
- const u = {
84
- name: (_h = (_f = (_d = (_c = (_b = res.user) === null || _b === void 0 ? void 0 : _b.profile) === null || _c === void 0 ? void 0 : _c.display_name) !== null && _d !== void 0 ? _d : (_e = res.user) === null || _e === void 0 ? void 0 : _e.real_name) !== null && _f !== void 0 ? _f : (_g = res.user) === null || _g === void 0 ? void 0 : _g.name) !== null && _h !== void 0 ? _h : "",
85
- email: (_l = (_k = (_j = res.user) === null || _j === void 0 ? void 0 : _j.profile) === null || _k === void 0 ? void 0 : _k.email) !== null && _l !== void 0 ? _l : "",
86
- };
87
- if (res.user && id) {
88
- slackUserCache.set(id, u);
85
+ if (id && res.user) {
86
+ cache.set(id, {
87
+ name: (_e = (_d = (_c = (_b = res.user.profile) === null || _b === void 0 ? void 0 : _b.display_name) !== null && _c !== void 0 ? _c : res.user.real_name) !== null && _d !== void 0 ? _d : res.user.name) !== null && _e !== void 0 ? _e : "",
88
+ email: (_g = (_f = res.user.profile) === null || _f === void 0 ? void 0 : _f.email) !== null && _g !== void 0 ? _g : "",
89
+ });
89
90
  }
90
- if (id)
91
- return id;
92
- return null;
93
- }));
94
- const settled = yield Promise.allSettled(tasks);
91
+ return id !== null && id !== void 0 ? id : null;
92
+ })));
95
93
  for (const r of settled)
96
94
  if (r.status === "fulfilled" && r.value)
97
95
  ids.push(r.value);
98
96
  return ids;
99
97
  });
100
98
  }
101
- function getMPIMName(client, userIds) {
99
+ function tryGetMPIMName(client, userIds) {
102
100
  return __awaiter(this, void 0, void 0, function* () {
103
- var _a, _b;
104
- const res = yield client.conversations.open({ users: userIds.join(",") });
105
- const id = (_a = res.channel) === null || _a === void 0 ? void 0 : _a.id;
106
- if (!id)
107
- throw new Error("Failed to open conversation for provided users.");
108
- const info = yield client.conversations.info({ channel: id });
109
- if (!((_b = info.channel) === null || _b === void 0 ? void 0 : _b.name))
110
- throw new Error("Failed to open conversation for provided users.");
111
- return info.channel.name;
101
+ var _a, _b, _c;
102
+ try {
103
+ const res = yield client.conversations.open({ users: userIds.join(",") });
104
+ const id = (_a = res.channel) === null || _a === void 0 ? void 0 : _a.id;
105
+ if (!id)
106
+ return null;
107
+ const info = yield client.conversations.info({ channel: id });
108
+ return (_c = (_b = info.channel) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : null;
109
+ }
110
+ catch (_d) {
111
+ return null;
112
+ }
112
113
  });
113
114
  }
114
115
  function getPermalink(client, channel, ts) {
@@ -124,23 +125,15 @@ function getPermalink(client, channel, ts) {
124
125
  }
125
126
  function fetchOneMessage(client, channel, ts) {
126
127
  return __awaiter(this, void 0, void 0, function* () {
127
- const r = yield client.conversations.history({
128
- channel,
129
- latest: ts,
130
- inclusive: true,
131
- limit: 1,
132
- });
133
- return (r.messages && r.messages[0]) || undefined;
128
+ var _a;
129
+ const r = yield client.conversations.history({ channel, latest: ts, inclusive: true, limit: 1 });
130
+ return (_a = r.messages) === null || _a === void 0 ? void 0 : _a[0];
134
131
  });
135
132
  }
136
133
  function fetchThread(client, channel, threadTs) {
137
134
  return __awaiter(this, void 0, void 0, function* () {
138
135
  var _a;
139
- const r = yield client.conversations.replies({
140
- channel,
141
- ts: threadTs,
142
- limit: 50,
143
- });
136
+ const r = yield client.conversations.replies({ channel, ts: threadTs, limit: 50 });
144
137
  return (_a = r.messages) !== null && _a !== void 0 ? _a : [];
145
138
  });
146
139
  }
@@ -151,232 +144,180 @@ function fetchContextWindow(client, channel, ts) {
151
144
  const anchor = yield fetchOneMessage(client, channel, ts);
152
145
  if (!anchor)
153
146
  return out;
154
- const beforeRes = yield client.conversations.history({
155
- channel,
156
- latest: ts,
157
- inclusive: false,
158
- limit: 4,
159
- });
160
- out.push(...((_a = beforeRes.messages) !== null && _a !== void 0 ? _a : []).reverse());
147
+ const before = yield client.conversations.history({ channel, latest: ts, inclusive: false, limit: 4 });
148
+ out.push(...((_a = before.messages) !== null && _a !== void 0 ? _a : []).reverse());
161
149
  out.push(anchor);
162
- const afterRes = yield client.conversations.history({
163
- channel,
164
- oldest: ts,
165
- inclusive: false,
166
- limit: 5,
167
- });
168
- out.push(...((_b = afterRes.messages) !== null && _b !== void 0 ? _b : []));
150
+ const after = yield client.conversations.history({ channel, oldest: ts, inclusive: false, limit: 5 });
151
+ out.push(...((_b = after.messages) !== null && _b !== void 0 ? _b : []));
169
152
  return out;
170
153
  });
171
154
  }
172
- /* ===================== Main Export ===================== */
155
+ function hasOverlap(messages, ids, minOverlap) {
156
+ const participants = new Set(messages.map(m => m.user).filter(Boolean));
157
+ const overlap = ids.filter(id => participants.has(id)).length;
158
+ return overlap >= minOverlap;
159
+ }
160
+ function expandSlackEntities(client, cache, raw) {
161
+ return __awaiter(this, void 0, void 0, function* () {
162
+ let text = raw;
163
+ // resolve users
164
+ const userIds = new Set();
165
+ for (const m of raw.matchAll(MENTION_USER_RE))
166
+ userIds.add(m[1]);
167
+ const idToUser = {};
168
+ yield Promise.all([...userIds].map((id) => __awaiter(this, void 0, void 0, function* () {
169
+ const u = yield cache.get(id);
170
+ idToUser[id] = { name: u === null || u === void 0 ? void 0 : u.name };
171
+ })));
172
+ text = text.replace(MENTION_USER_RE, (_, id) => { var _a, _b; return `@${(_b = (_a = idToUser[id]) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : id}`; });
173
+ // channels
174
+ text = text.replace(MENTION_CHANNEL_RE, (_, id) => `#${id}`);
175
+ // special mentions
176
+ text = text.replace(SPECIAL_RE, (_, kind) => `@${kind}`);
177
+ // subteams
178
+ text = text.replace(SUBTEAM_RE, (_m, sid) => `@${sid}`);
179
+ // links
180
+ text = text.replace(/<([^>|]+)\|([^>]+)>/g, (_m, _url, label) => label);
181
+ text = text.replace(/<([^>|]+)>/g, (_m, url) => url);
182
+ return text;
183
+ });
184
+ }
185
+ function searchScoped(input) {
186
+ return __awaiter(this, void 0, void 0, function* () {
187
+ var _a, _b;
188
+ const { client, scope, topic, timeRange, limit } = input;
189
+ const parts = [`in:${scope}`];
190
+ if (topic === null || topic === void 0 ? void 0 : topic.trim())
191
+ parts.push(topic.trim());
192
+ const tf = timeFilter(timeRange);
193
+ if (tf)
194
+ parts.push(tf);
195
+ const query = parts.join(" ");
196
+ const searchRes = yield client.search.messages({ query, count: limit, highlight: true });
197
+ return (_b = (_a = searchRes.messages) === null || _a === void 0 ? void 0 : _a.matches) !== null && _b !== void 0 ? _b : [];
198
+ });
199
+ }
200
+ function searchByTopic(input) {
201
+ return __awaiter(this, void 0, void 0, function* () {
202
+ var _a, _b;
203
+ const { client, topic, timeRange, limit } = input;
204
+ const parts = [];
205
+ if (topic === null || topic === void 0 ? void 0 : topic.trim())
206
+ parts.push(topic.trim());
207
+ const tf = timeFilter(timeRange);
208
+ if (tf)
209
+ parts.push(tf);
210
+ const query = parts.join(" ");
211
+ const searchRes = yield client.search.messages({ query, count: limit, highlight: true });
212
+ return (_b = (_a = searchRes.messages) === null || _a === void 0 ? void 0 : _a.matches) !== null && _b !== void 0 ? _b : [];
213
+ });
214
+ }
215
+ function dedupeAndSort(results) {
216
+ const seen = new Set();
217
+ const out = [];
218
+ for (const r of results) {
219
+ const key = `${r.channelId}-${r.ts}`;
220
+ if (!seen.has(key)) {
221
+ seen.add(key);
222
+ out.push(r);
223
+ }
224
+ }
225
+ return out.sort((a, b) => Number(b.ts) - Number(a.ts));
226
+ }
227
+ /* ===================== MAIN EXPORT ===================== */
173
228
  const searchSlack = (_a) => __awaiter(void 0, [_a], void 0, function* ({ params, authParams, }) {
174
- var _b, _c;
175
- if (!authParams.authToken) {
229
+ if (!authParams.authToken)
176
230
  throw new Error(MISSING_AUTH_TOKEN);
177
- }
178
231
  const client = new WebClient(authParams.authToken);
179
- const slackUserCache = new SlackUserCache(client);
180
- const { emails, channel, topic, timeRange, limit } = params;
181
- const parts = [];
232
+ const cache = new SlackUserCache(client);
233
+ const { emails, topic, timeRange, limit = 20, channel } = params;
182
234
  const { user_id: myUserId } = yield client.auth.test();
183
235
  if (!myUserId)
184
236
  throw new Error("Failed to get my user ID.");
185
- const me = yield slackUserCache.get(myUserId);
186
- const currentUser = {
187
- userId: myUserId,
188
- userName: me === null || me === void 0 ? void 0 : me.name,
189
- userEmail: me === null || me === void 0 ? void 0 : me.email,
190
- };
191
- if (emails === null || emails === void 0 ? void 0 : emails.length) {
192
- const userIds = yield lookupUserIdsByEmail(client, emails, slackUserCache);
193
- const userIdsWithoutMe = userIds.filter(id => id !== myUserId);
194
- if (userIdsWithoutMe.length === 0)
195
- throw new Error("No users resolved from emails.");
196
- if (userIdsWithoutMe.length == 1) {
197
- parts.push(`in:<@${userIdsWithoutMe[0]}>`);
237
+ const me = myUserId ? yield cache.get(myUserId) : undefined;
238
+ const targetIds = (emails === null || emails === void 0 ? void 0 : emails.length) ? yield lookupUserIdsByEmail(client, emails, cache) : [];
239
+ const filteredTargetIds = targetIds.filter(id => id !== myUserId);
240
+ const allMatches = [];
241
+ // --- Scoped DM/MPIM searches ---
242
+ if (filteredTargetIds.length === 1) {
243
+ allMatches.push(...(yield searchScoped({ client, scope: `<@${filteredTargetIds[0]}>`, topic, timeRange, limit })));
244
+ }
245
+ else if (filteredTargetIds.length >= 2) {
246
+ const mpimName = yield tryGetMPIMName(client, filteredTargetIds);
247
+ if (mpimName) {
248
+ allMatches.push(...(yield searchScoped({ client, scope: mpimName, topic, timeRange, limit })));
198
249
  }
199
- else {
200
- const convoName = yield getMPIMName(client, userIdsWithoutMe);
201
- parts.push(`in:${convoName}`);
250
+ for (const id of filteredTargetIds) {
251
+ allMatches.push(...(yield searchScoped({ client, scope: `<@${id}>`, topic, timeRange, limit })));
202
252
  }
203
253
  }
204
254
  else if (channel) {
205
- parts.push(`in:${normalizeChannelOperand(channel)}`);
255
+ allMatches.push(...(yield searchScoped({ client, scope: normalizeChannelOperand(channel), topic, timeRange, limit })));
206
256
  }
207
- if (topic && topic.trim())
208
- parts.push(topic.trim());
209
- const tf = timeFilter(timeRange);
210
- if (tf)
211
- parts.push(tf);
212
- const query = parts.join(" ").trim();
213
- if (!query)
214
- throw new Error("No query built — provide emails, channel, or topic.");
215
- const count = Math.max(1, Math.min(100, limit));
216
- const searchRes = yield client.search.messages({ query, count, highlight: true });
217
- const matches = (_c = (_b = searchRes.messages) === null || _b === void 0 ? void 0 : _b.matches) !== null && _c !== void 0 ? _c : [];
218
- const hitsPromises = matches.slice(0, limit).map((m) => __awaiter(void 0, void 0, void 0, function* () {
219
- var _a, _b, _c, _d;
220
- const user = m.user ? yield slackUserCache.get(m.user) : undefined;
221
- const prettyText = m.text ? yield expandSlackEntities(client, slackUserCache, m.text) : undefined;
222
- return {
223
- channelId: ((_a = m.channel) === null || _a === void 0 ? void 0 : _a.id) || ((_b = m.channel) === null || _b === void 0 ? void 0 : _b.name) || "",
224
- ts: m.ts,
225
- text: prettyText,
226
- userEmail: (_c = user === null || user === void 0 ? void 0 : user.email) !== null && _c !== void 0 ? _c : undefined,
227
- userName: (_d = user === null || user === void 0 ? void 0 : user.name) !== null && _d !== void 0 ? _d : undefined,
228
- };
229
- }));
230
- const hits = yield Promise.all(hitsPromises);
231
- const tasks = hits.map(h => limitHit(() => __awaiter(void 0, void 0, void 0, function* () {
257
+ // --- Topic-wide search ---
258
+ const topicMatches = topic ? yield searchByTopic({ client, topic, timeRange, limit }) : [];
259
+ allMatches.push(...topicMatches);
260
+ // --- Expand hits with context + filter overlap ---
261
+ const expanded = yield Promise.all(allMatches.map(m => limitHit(() => __awaiter(void 0, void 0, void 0, function* () {
232
262
  var _a, _b, _c, _d, _e, _f;
233
- if (!h.ts)
263
+ if (!m.ts || !((_a = m.channel) === null || _a === void 0 ? void 0 : _a.id))
234
264
  return null;
235
- try {
236
- const anchor = yield fetchOneMessage(client, h.channelId, h.ts);
237
- const rootTs = (anchor === null || anchor === void 0 ? void 0 : anchor.thread_ts) || h.ts;
238
- if (anchor === null || anchor === void 0 ? void 0 : anchor.thread_ts) {
239
- // thread: fetch thread + permalink concurrently
240
- const [thread, permalink] = yield Promise.all([
241
- fetchThread(client, h.channelId, rootTs),
242
- getPermalink(client, h.channelId, rootTs),
243
- ]);
244
- const contextPromises = thread
245
- .filter(t => t.ts)
246
- .map((t) => __awaiter(void 0, void 0, void 0, function* () {
247
- var _a, _b;
248
- const user = t.user ? yield slackUserCache.get(t.user) : undefined;
249
- const prettyText = t.text ? yield expandSlackEntities(client, slackUserCache, t.text) : undefined;
250
- return {
251
- ts: t.ts,
252
- text: prettyText,
253
- userEmail: (_a = user === null || user === void 0 ? void 0 : user.email) !== null && _a !== void 0 ? _a : undefined,
254
- userName: (_b = user === null || user === void 0 ? void 0 : user.name) !== null && _b !== void 0 ? _b : undefined,
255
- };
256
- }));
257
- const context = yield Promise.all(contextPromises);
258
- const user = anchor.user ? yield slackUserCache.get(anchor.user) : undefined;
259
- const textResponse = (_a = anchor.text) !== null && _a !== void 0 ? _a : h.text;
260
- const prettyText = textResponse ? yield expandSlackEntities(client, slackUserCache, textResponse) : undefined;
261
- return {
262
- channelId: h.channelId,
263
- ts: rootTs,
264
- text: prettyText,
265
- userEmail: (_b = user === null || user === void 0 ? void 0 : user.email) !== null && _b !== void 0 ? _b : h.userEmail,
266
- userName: (_c = user === null || user === void 0 ? void 0 : user.name) !== null && _c !== void 0 ? _c : h.userName,
267
- context,
268
- permalink,
269
- };
270
- }
271
- else {
272
- // not a thread: fetch context window + permalink concurrently
273
- const [ctx, permalink] = yield Promise.all([
274
- fetchContextWindow(client, h.channelId, h.ts),
275
- getPermalink(client, h.channelId, h.ts),
276
- ]);
277
- const contextPromises = ctx
278
- .filter(t => t.ts)
279
- .map((t) => __awaiter(void 0, void 0, void 0, function* () {
280
- var _a, _b;
281
- const user = t.user ? yield slackUserCache.get(t.user) : undefined;
282
- const prettyText = t.text ? yield expandSlackEntities(client, slackUserCache, t.text) : undefined;
283
- return {
284
- ts: t.ts,
285
- text: prettyText,
286
- userEmail: (_a = user === null || user === void 0 ? void 0 : user.email) !== null && _a !== void 0 ? _a : undefined,
287
- userName: (_b = user === null || user === void 0 ? void 0 : user.name) !== null && _b !== void 0 ? _b : undefined,
288
- };
289
- }));
290
- const context = yield Promise.all(contextPromises);
291
- const user = (anchor === null || anchor === void 0 ? void 0 : anchor.user) ? yield slackUserCache.get(anchor.user) : undefined;
292
- return {
293
- channelId: h.channelId,
294
- ts: h.ts,
295
- text: (_d = anchor === null || anchor === void 0 ? void 0 : anchor.text) !== null && _d !== void 0 ? _d : h.text,
296
- userEmail: (_e = user === null || user === void 0 ? void 0 : user.email) !== null && _e !== void 0 ? _e : h.userEmail,
297
- userName: (_f = user === null || user === void 0 ? void 0 : user.name) !== null && _f !== void 0 ? _f : h.userName,
298
- context,
299
- permalink,
300
- };
301
- }
265
+ const anchor = yield fetchOneMessage(client, m.channel.id, m.ts);
266
+ const rootTs = (anchor === null || anchor === void 0 ? void 0 : anchor.thread_ts) || m.ts;
267
+ let members = [];
268
+ // Check convo type (DM, MPIM, channel)
269
+ const convoInfo = yield client.conversations.info({ channel: m.channel.id });
270
+ const isIm = (_b = convoInfo.channel) === null || _b === void 0 ? void 0 : _b.is_im;
271
+ const isMpim = (_c = convoInfo.channel) === null || _c === void 0 ? void 0 : _c.is_mpim;
272
+ const [contextMsgs, permalink] = (anchor === null || anchor === void 0 ? void 0 : anchor.thread_ts)
273
+ ? [yield fetchThread(client, m.channel.id, rootTs), yield getPermalink(client, m.channel.id, rootTs)]
274
+ : [yield fetchContextWindow(client, m.channel.id, m.ts), yield getPermalink(client, m.channel.id, m.ts)];
275
+ let passesFilter = false;
276
+ if (isIm || isMpim) {
277
+ // DM/MPIM: use members, not authorship
278
+ const membersRes = (_d = (yield client.conversations.members({ channel: m.channel.id })).members) !== null && _d !== void 0 ? _d : [];
279
+ members = yield Promise.all(membersRes.map((uid) => __awaiter(void 0, void 0, void 0, function* () {
280
+ const u = yield cache.get(uid);
281
+ return { userId: uid, userEmail: u === null || u === void 0 ? void 0 : u.email, userName: u === null || u === void 0 ? void 0 : u.name };
282
+ })));
283
+ const overlap = filteredTargetIds.filter(id => membersRes.includes(id)).length;
284
+ passesFilter = overlap >= 1;
302
285
  }
303
- catch (_g) {
304
- // fallback minimal object; still in parallel
305
- return {
306
- channelId: h.channelId,
307
- ts: h.ts,
308
- text: h.text ? yield expandSlackEntities(client, slackUserCache, h.text) : undefined,
309
- userEmail: h.userEmail,
310
- userName: h.userName,
311
- permalink: yield getPermalink(client, h.channelId, h.ts),
312
- };
286
+ else {
287
+ // Channel: use authorship
288
+ passesFilter = hasOverlap(contextMsgs, filteredTargetIds, 1);
313
289
  }
314
- })));
315
- const settled = yield Promise.allSettled(tasks);
316
- const results = [];
317
- for (const r of settled)
318
- if (r.status === "fulfilled" && r.value)
319
- results.push(r.value);
320
- results.sort((a, b) => Number(b.ts) - Number(a.ts));
290
+ if (filteredTargetIds.length && !passesFilter)
291
+ return null;
292
+ const context = yield Promise.all(contextMsgs.map((t) => __awaiter(void 0, void 0, void 0, function* () {
293
+ var _a, _b;
294
+ return ({
295
+ ts: t.ts,
296
+ text: t.text ? yield expandSlackEntities(client, cache, t.text) : undefined,
297
+ userEmail: t.user ? (_a = (yield cache.get(t.user))) === null || _a === void 0 ? void 0 : _a.email : undefined,
298
+ userName: t.user ? (_b = (yield cache.get(t.user))) === null || _b === void 0 ? void 0 : _b.name : undefined,
299
+ });
300
+ })));
301
+ return {
302
+ channelId: m.channel.id,
303
+ ts: rootTs,
304
+ text: (anchor === null || anchor === void 0 ? void 0 : anchor.text) ? yield expandSlackEntities(client, cache, anchor.text) : undefined,
305
+ userEmail: (anchor === null || anchor === void 0 ? void 0 : anchor.user) ? (_e = (yield cache.get(anchor.user))) === null || _e === void 0 ? void 0 : _e.email : undefined,
306
+ userName: (anchor === null || anchor === void 0 ? void 0 : anchor.user) ? (_f = (yield cache.get(anchor.user))) === null || _f === void 0 ? void 0 : _f.name : undefined,
307
+ context,
308
+ permalink,
309
+ members,
310
+ };
311
+ }))));
312
+ const results = dedupeAndSort(expanded.filter(h => h !== null));
321
313
  return {
322
- query,
314
+ query: topic !== null && topic !== void 0 ? topic : "",
323
315
  results: results.map(r => ({
324
316
  name: r.text || "Untitled",
325
317
  url: r.permalink || "",
326
318
  contents: r,
327
319
  })),
328
- currentUser,
320
+ currentUser: { userId: myUserId, userName: me === null || me === void 0 ? void 0 : me.name, userEmail: me === null || me === void 0 ? void 0 : me.email },
329
321
  };
330
322
  });
331
- function expandSlackEntities(client_1, cache_1, raw_1) {
332
- return __awaiter(this, arguments, void 0, function* (client, cache, raw, { includeEmail = false } = {}) {
333
- let text = raw;
334
- // 1) Users: <@U12345> -> @Name (or @Name <email>)
335
- const userIds = new Set();
336
- for (const m of raw.matchAll(MENTION_USER_RE))
337
- userIds.add(m[1]);
338
- const idToUser = {};
339
- yield Promise.all([...userIds].map((id) => __awaiter(this, void 0, void 0, function* () {
340
- try {
341
- const u = yield cache.get(id);
342
- idToUser[id] = { name: u === null || u === void 0 ? void 0 : u.name, email: u === null || u === void 0 ? void 0 : u.email };
343
- }
344
- catch (_a) {
345
- idToUser[id] = {};
346
- }
347
- })));
348
- text = text.replace(MENTION_USER_RE, (_, id) => {
349
- const u = idToUser[id];
350
- if (u === null || u === void 0 ? void 0 : u.name) {
351
- return includeEmail && u.email ? `@${u.name} <${u.email}>` : `@${u.name}`;
352
- }
353
- // fallback: keep original token if we can't resolve
354
- return `@${id}`;
355
- });
356
- // 2) Channels: <#C12345|name> -> #name (fallback to #C12345)
357
- const channelIds = new Set();
358
- for (const m of raw.matchAll(MENTION_CHANNEL_RE))
359
- channelIds.add(m[1]);
360
- const idToChannel = {};
361
- yield Promise.all([...channelIds].map((id) => __awaiter(this, void 0, void 0, function* () {
362
- var _a, _b;
363
- try {
364
- const info = yield client.conversations.info({ channel: id });
365
- idToChannel[id] = (_b = (_a = info.channel) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : undefined;
366
- }
367
- catch (_c) {
368
- idToChannel[id] = undefined;
369
- }
370
- })));
371
- text = text.replace(MENTION_CHANNEL_RE, (_, id) => { var _a; return `#${(_a = idToChannel[id]) !== null && _a !== void 0 ? _a : id}`; });
372
- // 3) Special mentions: <!here>, <!channel>, <!everyone>
373
- text = text.replace(SPECIAL_RE, (_, kind) => `@${kind}`);
374
- // 4) User groups: <!subteam^S123|@group> -> @group (fallback to @S123)
375
- text = text.replace(SUBTEAM_RE, (_m, sid) => `@${sid}`);
376
- // 5) Slack links: <https://x|label> -> label (or the URL)
377
- text = text.replace(/<([^>|]+)\|([^>]+)>/g, (_m, _url, label) => label); // keep label
378
- text = text.replace(/<([^>|]+)>/g, (_m, url) => url); // bare <https://…>
379
- return text;
380
- });
381
- }
382
323
  export default searchSlack;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@credal/actions",
3
- "version": "0.2.145",
3
+ "version": "0.2.147",
4
4
  "type": "module",
5
5
  "description": "AI Actions by Credal AI",
6
6
  "sideEffects": false,
@@ -1,3 +0,0 @@
1
- import type { jiraUpdateServiceDeskRequestFunction } from "../../autogen/types.js";
2
- declare const updateServiceDeskRequest: jiraUpdateServiceDeskRequestFunction;
3
- export default updateServiceDeskRequest;
@@ -1,72 +0,0 @@
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 { axiosClient } from "../../util/axiosClient.js";
11
- const updateServiceDeskRequest = (_a) => __awaiter(void 0, [_a], void 0, function* ({ params, authParams, }) {
12
- const { issueId, requestTypeId, summary, description, priority, customFields } = params;
13
- const { authToken, cloudId, baseUrl } = authParams;
14
- if (!cloudId || !authToken) {
15
- throw new Error("Valid Cloud ID and auth token are required to update service desk request");
16
- }
17
- // Use the regular Jira API for updating service desk requests as they are still Jira issues
18
- const apiUrl = `https://api.atlassian.com/ex/jira/${cloudId}/rest/api/3/issue/${issueId}`;
19
- const formattedDescription = description
20
- ? {
21
- type: "doc",
22
- version: 1,
23
- content: [
24
- {
25
- type: "paragraph",
26
- content: [
27
- {
28
- type: "text",
29
- text: description,
30
- },
31
- ],
32
- },
33
- ],
34
- }
35
- : undefined;
36
- const payload = {
37
- fields: Object.assign(Object.assign(Object.assign(Object.assign({}, (summary && { summary })), (formattedDescription && { description: formattedDescription })), (priority && { priority: { name: priority } })), (customFields && Object.assign({}, customFields))),
38
- };
39
- try {
40
- yield axiosClient.put(apiUrl, payload, {
41
- headers: {
42
- Authorization: `Bearer ${authToken}`,
43
- Accept: "application/json",
44
- "Content-Type": "application/json",
45
- },
46
- });
47
- // Get the updated issue details to return current status and web link
48
- const getResponse = yield axiosClient.get(apiUrl, {
49
- headers: {
50
- Authorization: `Bearer ${authToken}`,
51
- Accept: "application/json",
52
- },
53
- });
54
- const issueKey = getResponse.data.key;
55
- const currentStatus = getResponse.data.fields.status.name;
56
- const webLink = `${baseUrl}/browse/${issueKey}`;
57
- return {
58
- success: true,
59
- issueKey,
60
- webLink,
61
- currentStatus,
62
- };
63
- }
64
- catch (error) {
65
- console.error("Error updating service desk request:", error);
66
- return {
67
- success: false,
68
- error: error instanceof Error ? error.message : "Unknown error",
69
- };
70
- }
71
- });
72
- export default updateServiceDeskRequest;