@sentry/junior 0.99.0 → 0.100.0

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 (79) hide show
  1. package/dist/{agent-hooks-OSW6C3CJ.js → agent-hooks-V6KU7PQN.js} +6 -5
  2. package/dist/api/activity.d.ts +14 -0
  3. package/dist/api/conversations/aggregate.d.ts +16 -0
  4. package/dist/api/conversations/detail-projection.d.ts +1 -0
  5. package/dist/api/conversations/list.query.d.ts +3 -0
  6. package/dist/api/conversations/projection.d.ts +1 -0
  7. package/dist/api/conversations/reporting.d.ts +42 -0
  8. package/dist/api/conversations/schema.d.ts +7 -7
  9. package/dist/api/conversations/stats.query.d.ts +1 -1
  10. package/dist/api/locations/detail.d.ts +81 -0
  11. package/dist/api/locations/list.d.ts +30 -0
  12. package/dist/api/locations/query.d.ts +5 -0
  13. package/dist/api/locations/schema.d.ts +175 -0
  14. package/dist/api/people/list.query.d.ts +1 -1
  15. package/dist/api/people/profile.query.d.ts +1 -1
  16. package/dist/api/people/schema.d.ts +10 -14
  17. package/dist/api/people/shared.d.ts +38 -78
  18. package/dist/api/schema.d.ts +8 -0
  19. package/dist/api/schema.js +14 -3
  20. package/dist/api.js +24 -11
  21. package/dist/app.js +25 -19
  22. package/dist/chat/agent/request.d.ts +3 -0
  23. package/dist/chat/config.d.ts +2 -0
  24. package/dist/chat/reasoning-level.d.ts +4 -0
  25. package/dist/chat/services/{turn-thinking-level.d.ts → turn-reasoning-level.d.ts} +11 -10
  26. package/dist/chat/services/turn-result.d.ts +3 -3
  27. package/dist/chat/tools/search-tools.d.ts +2 -2
  28. package/dist/{chunk-T55RBE4Z.js → chunk-2RNOB32R.js} +3 -1
  29. package/dist/{chunk-NJEDJFK4.js → chunk-2T7DCRAW.js} +1 -1
  30. package/dist/{chunk-PYK7R5A7.js → chunk-45DMFMY2.js} +66 -65
  31. package/dist/chunk-4AQUWWEM.js +75 -0
  32. package/dist/{chunk-EEZCY5WX.js → chunk-A7X2FDUO.js} +18 -2
  33. package/dist/{chunk-WTYEKPXU.js → chunk-FP5N5OWZ.js} +1 -1
  34. package/dist/chunk-FXFQNHRU.js +48 -0
  35. package/dist/chunk-GEUUJRQF.js +102 -0
  36. package/dist/{chunk-CRQVIHDI.js → chunk-IDZBM3NW.js} +2 -8
  37. package/dist/{chunk-DHHU2WSG.js → chunk-IQIBZXGB.js} +2 -2
  38. package/dist/{chunk-OL6XQ23W.js → chunk-IVXL57YF.js} +3 -3
  39. package/dist/{chunk-IO65E4ZD.js → chunk-JPQISMMJ.js} +3 -3
  40. package/dist/{chunk-KFUSLFLL.js → chunk-JSAANELJ.js} +11 -4
  41. package/dist/{chunk-EUZ44ROE.js → chunk-MM5UFDAC.js} +1 -3
  42. package/dist/{chunk-WJ7STXT6.js → chunk-NSOCZGOH.js} +3 -3
  43. package/dist/chunk-PGGEOCQY.js +77 -0
  44. package/dist/{chunk-EOWXRY5E.js → chunk-PWC24W5F.js} +1 -1
  45. package/dist/chunk-QOZOJNSE.js +96 -0
  46. package/dist/chunk-QSBQJ3PA.js +275 -0
  47. package/dist/{chunk-FTTFV6DC.js → chunk-TPTJEHUE.js} +4 -4
  48. package/dist/{chunk-OGHXZ4KQ.js → chunk-VHRM6GNH.js} +88 -122
  49. package/dist/{chunk-NG2AV7IB.js → chunk-VVIXK2BX.js} +1 -1
  50. package/dist/{chunk-ZZUBLPXD.js → chunk-VY7BT4SM.js} +5 -4
  51. package/dist/{chunk-H66UCBPW.js → chunk-XJA7BPHS.js} +1 -1
  52. package/dist/{chunk-ER45IV77.js → chunk-XSBIISXS.js} +9 -9
  53. package/dist/cli/chat.js +15 -14
  54. package/dist/cli/plugins.js +6 -5
  55. package/dist/cli/snapshot-warmup.js +2 -2
  56. package/dist/cli/upgrade.js +8 -7
  57. package/dist/db/schema/conversations.d.ts +17 -0
  58. package/dist/db/schema/destinations.d.ts +12 -3
  59. package/dist/db/schema.d.ts +19 -2
  60. package/dist/{db-GFSCDAHS.js → db-RCZB7KNM.js} +3 -2
  61. package/dist/detail-5SLCGT6J.js +29 -0
  62. package/dist/{detail-Q4IVDNGS.js → detail-LU6COZO6.js} +11 -10
  63. package/dist/{legacy-import-6WWXMALY.js → legacy-import-VCYLWT2V.js} +4 -3
  64. package/dist/list-2FI5SFV7.js +80 -0
  65. package/dist/list-4ALSU6ZW.js +30 -0
  66. package/dist/{list-A3F5JDYV.js → list-KHRAWZWU.js} +7 -6
  67. package/dist/{plugin-conversations-PDCQWU3O.js → plugin-conversations-JANXC4GA.js} +6 -5
  68. package/dist/profile-3O3OVENT.js +212 -0
  69. package/dist/{runner-267ZRLZD.js → runner-BM7D35YW.js} +12 -11
  70. package/dist/stats-J3YGCYDF.js +174 -0
  71. package/dist/{subagent-UN3MP6LV.js → subagent-P7HOSMVC.js} +10 -9
  72. package/migrations/0003_peaceful_scalphunter.sql +4 -0
  73. package/migrations/meta/0003_snapshot.json +1035 -0
  74. package/migrations/meta/_journal.json +8 -1
  75. package/package.json +5 -5
  76. package/dist/chunk-CV22LUIV.js +0 -261
  77. package/dist/list-M5BRWW3D.js +0 -92
  78. package/dist/profile-UEIRSVT3.js +0 -146
  79. package/dist/stats-L62E4O4U.js +0 -207
@@ -0,0 +1,102 @@
1
+ import {
2
+ getDb,
3
+ juniorConversations,
4
+ juniorIdentities,
5
+ juniorUsers
6
+ } from "./chunk-VHRM6GNH.js";
7
+ import {
8
+ juniorDestinations
9
+ } from "./chunk-FXFQNHRU.js";
10
+
11
+ // src/api/people/shared.ts
12
+ import { and, asc, desc, eq, sql } from "drizzle-orm";
13
+ var RECENT_LIMIT = 25;
14
+ var ACTIVITY_DAYS = 366;
15
+ function normalizeEmail(email) {
16
+ const normalized = email?.trim().toLowerCase();
17
+ return normalized || void 0;
18
+ }
19
+ function emptyTotals() {
20
+ return {
21
+ active: 0,
22
+ activeDays: 0,
23
+ conversations: 0,
24
+ durationMs: 0,
25
+ failed: 0
26
+ };
27
+ }
28
+ function emptyActivityDay(date) {
29
+ return {
30
+ active: 0,
31
+ conversations: 0,
32
+ date,
33
+ durationMs: 0,
34
+ failed: 0
35
+ };
36
+ }
37
+ function activityDays(days, nowMs) {
38
+ const items = [];
39
+ const end = new Date(nowMs);
40
+ end.setUTCHours(0, 0, 0, 0);
41
+ const start = new Date(end);
42
+ start.setUTCDate(start.getUTCDate() - (ACTIVITY_DAYS - 1));
43
+ for (const cursor = new Date(start); cursor.getTime() <= end.getTime(); cursor.setUTCDate(cursor.getUTCDate() + 1)) {
44
+ const date = cursor.toISOString().slice(0, 10);
45
+ items.push(days.get(date) ?? emptyActivityDay(date));
46
+ }
47
+ return items;
48
+ }
49
+ function statsItems(map) {
50
+ return [...map.values()].sort(
51
+ (left, right) => right.conversations - left.conversations || right.durationMs - left.durationMs || left.label.localeCompare(right.label)
52
+ );
53
+ }
54
+ function verifiedActorWhere(email) {
55
+ const normalizedEmail = normalizeEmail(email);
56
+ return and(
57
+ eq(juniorIdentities.provider, "slack"),
58
+ eq(juniorIdentities.emailVerified, true),
59
+ sql`${juniorUsers.primaryEmailNormalized} IS NOT NULL`,
60
+ normalizedEmail ? eq(juniorUsers.primaryEmailNormalized, normalizedEmail) : void 0
61
+ );
62
+ }
63
+ async function recentActorRows(email) {
64
+ return getDb().select({
65
+ channelName: juniorConversations.channelName,
66
+ conversationId: juniorConversations.conversationId,
67
+ createdAt: juniorConversations.createdAt,
68
+ destinationId: juniorDestinations.id,
69
+ destinationVisibility: juniorDestinations.visibility,
70
+ durationMs: juniorConversations.durationMs,
71
+ email: juniorUsers.primaryEmailNormalized,
72
+ executionStatus: juniorConversations.executionStatus,
73
+ executionUpdatedAt: juniorConversations.executionUpdatedAt,
74
+ fullName: juniorUsers.displayName,
75
+ handle: juniorIdentities.handle,
76
+ lastActivityAt: juniorConversations.lastActivityAt,
77
+ providerSubjectId: juniorIdentities.providerSubjectId,
78
+ source: juniorConversations.source,
79
+ title: juniorConversations.title,
80
+ updatedAt: juniorConversations.updatedAt,
81
+ usage: juniorConversations.usage
82
+ }).from(juniorConversations).innerJoin(
83
+ juniorIdentities,
84
+ eq(juniorIdentities.id, juniorConversations.actorIdentityId)
85
+ ).innerJoin(juniorUsers, eq(juniorUsers.id, juniorIdentities.userId)).leftJoin(
86
+ juniorDestinations,
87
+ eq(juniorDestinations.id, juniorConversations.destinationId)
88
+ ).where(verifiedActorWhere(email)).orderBy(
89
+ desc(juniorConversations.lastActivityAt),
90
+ asc(juniorConversations.conversationId)
91
+ ).limit(RECENT_LIMIT);
92
+ }
93
+
94
+ export {
95
+ ACTIVITY_DAYS,
96
+ normalizeEmail,
97
+ emptyTotals,
98
+ activityDays,
99
+ statsItems,
100
+ verifiedActorWhere,
101
+ recentActorRows
102
+ };
@@ -2,7 +2,7 @@ import {
2
2
  actorIdentitySchema,
3
3
  conversationStatsItemSchema,
4
4
  conversationSummaryReportSchema
5
- } from "./chunk-EUZ44ROE.js";
5
+ } from "./chunk-MM5UFDAC.js";
6
6
 
7
7
  // src/api/people/schema.ts
8
8
  import { z } from "zod";
@@ -37,10 +37,7 @@ var actorSummaryReportSchema = actorTotalsReportSchema.extend({
37
37
  var actorDirectoryReportSchema = z.object({
38
38
  generatedAt: z.string(),
39
39
  people: z.array(actorSummaryReportSchema),
40
- sampleLimit: z.number(),
41
- sampleSize: z.number(),
42
- source: z.literal("conversation_index"),
43
- truncated: z.boolean()
40
+ source: z.literal("conversation_index")
44
41
  }).strict();
45
42
  var actorProfileReportSchema = z.object({
46
43
  activityDays: z.array(actorActivityDayReportSchema),
@@ -48,12 +45,9 @@ var actorProfileReportSchema = z.object({
48
45
  locations: z.array(peopleConversationStatsItemSchema),
49
46
  recentConversations: z.array(peopleConversationSummaryReportSchema),
50
47
  actor: identifiedActorSchema,
51
- sampleLimit: z.number(),
52
- sampleSize: z.number(),
53
48
  source: z.literal("conversation_index"),
54
49
  surfaces: z.array(peopleConversationStatsItemSchema),
55
50
  totals: actorTotalsReportSchema,
56
- truncated: z.boolean(),
57
51
  windowEnd: z.string(),
58
52
  windowStart: z.string()
59
53
  }).strict();
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  ensureLegacyConversationImport
3
- } from "./chunk-IO65E4ZD.js";
3
+ } from "./chunk-JPQISMMJ.js";
4
4
  import {
5
5
  contextProvenance,
6
6
  getAgentStepStore
7
- } from "./chunk-OGHXZ4KQ.js";
7
+ } from "./chunk-VHRM6GNH.js";
8
8
 
9
9
  // src/chat/conversations/projection.ts
10
10
  import { isDeepStrictEqual } from "util";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  commitMessages,
3
3
  loadTurnProjection
4
- } from "./chunk-DHHU2WSG.js";
4
+ } from "./chunk-IQIBZXGB.js";
5
5
  import {
6
6
  usageSchema
7
7
  } from "./chunk-PDO5BLNM.js";
@@ -9,10 +9,10 @@ import {
9
9
  getConversationStore,
10
10
  instructionActors,
11
11
  instructionProvenanceFor
12
- } from "./chunk-OGHXZ4KQ.js";
12
+ } from "./chunk-VHRM6GNH.js";
13
13
  import {
14
14
  getStateAdapter
15
- } from "./chunk-EEZCY5WX.js";
15
+ } from "./chunk-A7X2FDUO.js";
16
16
  import {
17
17
  toStoredSlackActor
18
18
  } from "./chunk-I35CTGPO.js";
@@ -11,14 +11,14 @@ import {
11
11
  legacyActorProvenance,
12
12
  piMessageSchema,
13
13
  readSessionLogEntries
14
- } from "./chunk-OGHXZ4KQ.js";
14
+ } from "./chunk-VHRM6GNH.js";
15
15
  import {
16
16
  botConfig,
17
17
  escapeXml,
18
18
  getStateAdapter,
19
19
  resolveGatewayModel,
20
20
  unescapeXml
21
- } from "./chunk-EEZCY5WX.js";
21
+ } from "./chunk-A7X2FDUO.js";
22
22
  import {
23
23
  logWarn,
24
24
  setSpanAttributes
@@ -464,7 +464,7 @@ async function hydrateConversationMessages(args) {
464
464
  args.conversation.messages = [];
465
465
  return;
466
466
  }
467
- const { ensureLegacyConversationImport: ensureLegacyConversationImport2 } = await import("./legacy-import-6WWXMALY.js");
467
+ const { ensureLegacyConversationImport: ensureLegacyConversationImport2 } = await import("./legacy-import-VCYLWT2V.js");
468
468
  await ensureLegacyConversationImport2({ conversationId: args.conversationId });
469
469
  await hydrateConversationCompactions({
470
470
  conversation: args.conversation,
@@ -1,13 +1,15 @@
1
1
  import {
2
2
  formatSlackConversationRedactedLabel,
3
3
  resolveSlackConversationContextFromThreadId
4
- } from "./chunk-NG2AV7IB.js";
4
+ } from "./chunk-VVIXK2BX.js";
5
5
  import {
6
6
  getDb,
7
7
  juniorConversations,
8
- juniorDestinations,
9
8
  juniorIdentities
10
- } from "./chunk-OGHXZ4KQ.js";
9
+ } from "./chunk-VHRM6GNH.js";
10
+ import {
11
+ juniorDestinations
12
+ } from "./chunk-FXFQNHRU.js";
11
13
  import {
12
14
  parseSlackThreadId,
13
15
  resolveConversationPrivacy
@@ -148,7 +150,8 @@ function conversationSummaryFromStoredConversation(args) {
148
150
  ...actorIdentity ? { actorIdentity } : {},
149
151
  ...slackThread ? { channel: slackThread.channelId } : {},
150
152
  ...channelName ? { channelName } : {},
151
- ...channelNameRedacted ? { channelNameRedacted: true } : {}
153
+ ...channelNameRedacted ? { channelNameRedacted: true } : {},
154
+ ...args.locationId && !channelNameRedacted ? { locationId: args.locationId } : {}
152
155
  };
153
156
  }
154
157
 
@@ -157,6 +160,7 @@ var CONVERSATION_FEED_LIMIT = 50;
157
160
  async function conversationRows(db, limit, actorEmail) {
158
161
  return db.select({
159
162
  conversation: juniorConversations,
163
+ destinationId: juniorDestinations.id,
160
164
  destinationVisibility: juniorDestinations.visibility,
161
165
  identityDisplayName: juniorIdentities.displayName,
162
166
  identityEmail: juniorIdentities.email,
@@ -218,6 +222,7 @@ async function readConversationRecordFromSql(conversationId) {
218
222
  const db = getDb();
219
223
  const rows = await db.select({
220
224
  conversation: juniorConversations,
225
+ destinationId: juniorDestinations.id,
221
226
  destinationVisibility: juniorDestinations.visibility,
222
227
  identityDisplayName: juniorIdentities.displayName,
223
228
  identityEmail: juniorIdentities.email,
@@ -236,6 +241,7 @@ async function readConversationRecordFromSql(conversationId) {
236
241
  return row ? {
237
242
  conversation: conversationFromRow(row),
238
243
  durationMs: row.conversation.durationMs,
244
+ ...row.destinationVisibility === "public" && row.destinationId ? { locationId: row.destinationId } : {},
239
245
  usage: row.conversation.usage
240
246
  } : void 0;
241
247
  }
@@ -251,6 +257,7 @@ async function readConversationFeedFromSql(options = {}) {
251
257
  (row) => conversationSummaryFromStoredConversation({
252
258
  conversation: conversationFromRow(row),
253
259
  durationMs: row.conversation.durationMs,
260
+ ...row.destinationVisibility === "public" && row.destinationId ? { locationId: row.destinationId } : {},
254
261
  usage: row.conversation.usage ?? void 0
255
262
  })
256
263
  ),
@@ -36,6 +36,7 @@ var conversationSummaryReportSchema = z.object({
36
36
  channel: z.string().optional(),
37
37
  channelName: z.string().optional(),
38
38
  channelNameRedacted: z.boolean().optional(),
39
+ locationId: z.string().optional(),
39
40
  sentryTraceUrl: z.string().optional(),
40
41
  traceId: z.string().optional()
41
42
  }).strict();
@@ -195,12 +196,9 @@ var conversationStatsReportSchema = z.object({
195
196
  generatedAt: z.string(),
196
197
  locations: z.array(conversationStatsItemSchema),
197
198
  actors: z.array(conversationStatsItemSchema),
198
- sampleLimit: z.number(),
199
- sampleSize: z.number(),
200
199
  source: z.literal("conversation_index"),
201
200
  costUsd: z.number().optional(),
202
201
  tokens: z.number().optional(),
203
- truncated: z.boolean(),
204
202
  windowEnd: z.string(),
205
203
  windowStart: z.string()
206
204
  }).strict();
@@ -7,10 +7,10 @@ import {
7
7
  addAgentTurnUsage,
8
8
  getAgentTurnSessionRecord,
9
9
  upsertAgentTurnSessionRecord
10
- } from "./chunk-OL6XQ23W.js";
10
+ } from "./chunk-IVXL57YF.js";
11
11
  import {
12
12
  persistConversationMessages
13
- } from "./chunk-IO65E4ZD.js";
13
+ } from "./chunk-JPQISMMJ.js";
14
14
  import {
15
15
  sleep
16
16
  } from "./chunk-4ZNGQH7C.js";
@@ -18,7 +18,7 @@ import {
18
18
  getPiMessageRole,
19
19
  getStateAdapter,
20
20
  trimTrailingAssistantMessages
21
- } from "./chunk-EEZCY5WX.js";
21
+ } from "./chunk-A7X2FDUO.js";
22
22
  import {
23
23
  getActiveTraceId,
24
24
  logException
@@ -0,0 +1,77 @@
1
+ import {
2
+ juniorConversations
3
+ } from "./chunk-VHRM6GNH.js";
4
+
5
+ // src/api/conversations/aggregate.ts
6
+ import { sql } from "drizzle-orm";
7
+ function tokenValue() {
8
+ return sql`
9
+ CASE
10
+ WHEN ${juniorConversations.usage}->>'totalTokens' IS NOT NULL
11
+ THEN (${juniorConversations.usage}->>'totalTokens')::double precision
12
+ WHEN COALESCE(
13
+ ${juniorConversations.usage}->>'inputTokens',
14
+ ${juniorConversations.usage}->>'outputTokens',
15
+ ${juniorConversations.usage}->>'cachedInputTokens',
16
+ ${juniorConversations.usage}->>'cacheCreationTokens'
17
+ ) IS NOT NULL
18
+ THEN COALESCE((${juniorConversations.usage}->>'inputTokens')::double precision, 0)
19
+ + COALESCE((${juniorConversations.usage}->>'outputTokens')::double precision, 0)
20
+ + COALESCE((${juniorConversations.usage}->>'cachedInputTokens')::double precision, 0)
21
+ + COALESCE((${juniorConversations.usage}->>'cacheCreationTokens')::double precision, 0)
22
+ ELSE NULL
23
+ END
24
+ `;
25
+ }
26
+ function costValue() {
27
+ return sql`
28
+ CASE
29
+ WHEN ${juniorConversations.usage}->'cost'->>'total' IS NOT NULL
30
+ THEN (${juniorConversations.usage}->'cost'->>'total')::double precision
31
+ WHEN COALESCE(
32
+ ${juniorConversations.usage}->'cost'->>'input',
33
+ ${juniorConversations.usage}->'cost'->>'output',
34
+ ${juniorConversations.usage}->'cost'->>'cacheRead',
35
+ ${juniorConversations.usage}->'cost'->>'cacheWrite'
36
+ ) IS NOT NULL
37
+ THEN COALESCE((${juniorConversations.usage}->'cost'->>'input')::double precision, 0)
38
+ + COALESCE((${juniorConversations.usage}->'cost'->>'output')::double precision, 0)
39
+ + COALESCE((${juniorConversations.usage}->'cost'->>'cacheRead')::double precision, 0)
40
+ + COALESCE((${juniorConversations.usage}->'cost'->>'cacheWrite')::double precision, 0)
41
+ ELSE NULL
42
+ END
43
+ `;
44
+ }
45
+ function conversationAggregateColumns() {
46
+ return {
47
+ active: sql`COUNT(*) FILTER (
48
+ WHERE ${juniorConversations.executionStatus} NOT IN ('idle', 'failed')
49
+ )::integer`,
50
+ conversations: sql`COUNT(*)::integer`,
51
+ costUsd: sql`SUM(${costValue()})::double precision`,
52
+ durationMs: sql`COALESCE(SUM(${juniorConversations.durationMs}), 0)::double precision`,
53
+ failed: sql`COUNT(*) FILTER (
54
+ WHERE ${juniorConversations.executionStatus} = 'failed'
55
+ )::integer`,
56
+ tokens: sql`SUM(${tokenValue()})::double precision`
57
+ };
58
+ }
59
+ function conversationRangeColumns() {
60
+ return {
61
+ firstSeenAt: sql`MIN(${juniorConversations.createdAt})`.mapWith(
62
+ juniorConversations.createdAt
63
+ ),
64
+ lastSeenAt: sql`MAX(${juniorConversations.lastActivityAt})`.mapWith(
65
+ juniorConversations.lastActivityAt
66
+ )
67
+ };
68
+ }
69
+ function conversationActiveDaysColumn() {
70
+ return sql`COUNT(DISTINCT (${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC')::date)::integer`;
71
+ }
72
+
73
+ export {
74
+ conversationAggregateColumns,
75
+ conversationRangeColumns,
76
+ conversationActiveDaysColumn
77
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getStateAdapter
3
- } from "./chunk-EEZCY5WX.js";
3
+ } from "./chunk-A7X2FDUO.js";
4
4
  import {
5
5
  logException,
6
6
  logInfo,
@@ -0,0 +1,96 @@
1
+ // src/api/conversations/reporting.ts
2
+ var PRIVATE_CONVERSATION_LABEL = "Private Conversation";
3
+ function channelFromConversationId(conversationId) {
4
+ const [provider, channel] = conversationId.split(":");
5
+ return provider === "slack" && channel ? channel : void 0;
6
+ }
7
+ function surfaceFromRow(row) {
8
+ if (row.source === "api" || row.source === "scheduler" || row.source === "slack") {
9
+ return row.source;
10
+ }
11
+ if (row.conversationId.startsWith("slack:")) return "slack";
12
+ if (row.conversationId.startsWith("scheduler:")) return "scheduler";
13
+ if (row.conversationId.startsWith("api:")) return "api";
14
+ return "internal";
15
+ }
16
+ function statusFromRow(row) {
17
+ if (row.executionStatus === "failed") return "failed";
18
+ if (row.executionStatus === "idle") return "completed";
19
+ return "active";
20
+ }
21
+ function surfaceLabel(surface) {
22
+ if (surface === "scheduler") return "Scheduler";
23
+ if (surface === "api") return "API";
24
+ if (surface === "internal") return "Internal";
25
+ return "Conversation";
26
+ }
27
+ function slackLocationLabel(args) {
28
+ const channelId = args.channel;
29
+ if (!channelId) return void 0;
30
+ if (args.channelNameRedacted && args.channelName) return args.channelName;
31
+ const name = args.channelName?.replace(/^#/, "");
32
+ if (channelId.startsWith("D")) return "Direct Message";
33
+ if (channelId.startsWith("C")) {
34
+ return name ? `#${name}` : "Public Channel";
35
+ }
36
+ if (channelId.startsWith("G")) {
37
+ if (name?.startsWith("mpdm-")) return "Group DM";
38
+ return "Private Channel";
39
+ }
40
+ return name || channelId;
41
+ }
42
+ function channelNameFromRow(row) {
43
+ if (row.destinationVisibility !== "public") {
44
+ return PRIVATE_CONVERSATION_LABEL;
45
+ }
46
+ return row.channelName ?? void 0;
47
+ }
48
+ function titleFromRow(row, surface) {
49
+ if (row.destinationVisibility !== "public") {
50
+ return PRIVATE_CONVERSATION_LABEL;
51
+ }
52
+ const channel = channelFromConversationId(row.conversationId);
53
+ return row.title ?? slackLocationLabel({
54
+ channel,
55
+ channelName: row.channelName ?? void 0
56
+ }) ?? surfaceLabel(surface);
57
+ }
58
+ function actorFromRow(row) {
59
+ const actor = {
60
+ ...row.email ? { email: row.email } : {},
61
+ ...row.fullName ? { fullName: row.fullName } : {},
62
+ ...row.providerSubjectId ? { slackUserId: row.providerSubjectId } : {},
63
+ ...row.handle ? { slackUserName: row.handle } : {}
64
+ };
65
+ return Object.keys(actor).length ? actor : void 0;
66
+ }
67
+ function summaryFromRow(row) {
68
+ const surface = surfaceFromRow(row);
69
+ const channel = channelFromConversationId(row.conversationId);
70
+ const channelName = channelNameFromRow(row);
71
+ const channelNameRedacted = row.destinationVisibility !== "public";
72
+ const actorIdentity = actorFromRow(row);
73
+ return {
74
+ conversationId: row.conversationId,
75
+ cumulativeDurationMs: row.durationMs,
76
+ displayTitle: titleFromRow(row, surface),
77
+ lastProgressAt: new Date(
78
+ row.executionUpdatedAt ?? row.updatedAt
79
+ ).toISOString(),
80
+ lastSeenAt: row.lastActivityAt.toISOString(),
81
+ startedAt: row.createdAt.toISOString(),
82
+ status: statusFromRow(row),
83
+ surface,
84
+ ...actorIdentity ? { actorIdentity } : {},
85
+ ...channel ? { channel } : {},
86
+ ...channelName ? { channelName } : {},
87
+ ...channelNameRedacted ? { channelNameRedacted: true } : {},
88
+ ...row.destinationVisibility === "public" && row.destinationId ? { locationId: row.destinationId } : {}
89
+ };
90
+ }
91
+
92
+ export {
93
+ surfaceLabel,
94
+ slackLocationLabel,
95
+ summaryFromRow
96
+ };