@sentry/junior 0.98.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 (82) 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.d.ts +7 -2
  6. package/dist/api/conversations/list.query.d.ts +12 -3
  7. package/dist/api/conversations/projection.d.ts +1 -0
  8. package/dist/api/conversations/reporting.d.ts +42 -0
  9. package/dist/api/conversations/schema.d.ts +7 -7
  10. package/dist/api/conversations/stats.query.d.ts +1 -1
  11. package/dist/api/locations/detail.d.ts +81 -0
  12. package/dist/api/locations/list.d.ts +30 -0
  13. package/dist/api/locations/query.d.ts +5 -0
  14. package/dist/api/locations/schema.d.ts +175 -0
  15. package/dist/api/people/list.query.d.ts +1 -1
  16. package/dist/api/people/profile.query.d.ts +1 -1
  17. package/dist/api/people/schema.d.ts +10 -14
  18. package/dist/api/people/shared.d.ts +38 -78
  19. package/dist/api/schema.d.ts +11 -0
  20. package/dist/api/schema.js +16 -3
  21. package/dist/api-reference.d.ts +1 -1
  22. package/dist/api.js +41 -13
  23. package/dist/app.js +35 -27
  24. package/dist/chat/agent/request.d.ts +3 -0
  25. package/dist/chat/config.d.ts +2 -0
  26. package/dist/chat/reasoning-level.d.ts +4 -0
  27. package/dist/chat/services/context-compaction.d.ts +1 -0
  28. package/dist/chat/services/{turn-thinking-level.d.ts → turn-reasoning-level.d.ts} +11 -10
  29. package/dist/chat/services/turn-result.d.ts +3 -3
  30. package/dist/chat/tools/search-tools.d.ts +2 -2
  31. package/dist/{chunk-UAMKJPDF.js → chunk-2RNOB32R.js} +7 -1
  32. package/dist/{chunk-NJEDJFK4.js → chunk-2T7DCRAW.js} +1 -1
  33. package/dist/{chunk-DPHWDS6I.js → chunk-45DMFMY2.js} +81 -69
  34. package/dist/chunk-4AQUWWEM.js +75 -0
  35. package/dist/{chunk-EEZCY5WX.js → chunk-A7X2FDUO.js} +18 -2
  36. package/dist/{chunk-WTYEKPXU.js → chunk-FP5N5OWZ.js} +1 -1
  37. package/dist/chunk-FXFQNHRU.js +48 -0
  38. package/dist/chunk-GEUUJRQF.js +102 -0
  39. package/dist/{chunk-CRQVIHDI.js → chunk-IDZBM3NW.js} +2 -8
  40. package/dist/{chunk-DHHU2WSG.js → chunk-IQIBZXGB.js} +2 -2
  41. package/dist/{chunk-OL6XQ23W.js → chunk-IVXL57YF.js} +3 -3
  42. package/dist/{chunk-IO65E4ZD.js → chunk-JPQISMMJ.js} +3 -3
  43. package/dist/{chunk-KJHAW6VE.js → chunk-JSAANELJ.js} +28 -9
  44. package/dist/{chunk-EUZ44ROE.js → chunk-MM5UFDAC.js} +1 -3
  45. package/dist/{chunk-WJ7STXT6.js → chunk-NSOCZGOH.js} +3 -3
  46. package/dist/chunk-PGGEOCQY.js +77 -0
  47. package/dist/{chunk-EOWXRY5E.js → chunk-PWC24W5F.js} +1 -1
  48. package/dist/chunk-QOZOJNSE.js +96 -0
  49. package/dist/chunk-QSBQJ3PA.js +275 -0
  50. package/dist/{chunk-FTTFV6DC.js → chunk-TPTJEHUE.js} +4 -4
  51. package/dist/{chunk-OGHXZ4KQ.js → chunk-VHRM6GNH.js} +88 -122
  52. package/dist/{chunk-NG2AV7IB.js → chunk-VVIXK2BX.js} +1 -1
  53. package/dist/{chunk-6HHEZENZ.js → chunk-VY7BT4SM.js} +16 -7
  54. package/dist/{chunk-H66UCBPW.js → chunk-XJA7BPHS.js} +1 -1
  55. package/dist/{chunk-ER45IV77.js → chunk-XSBIISXS.js} +9 -9
  56. package/dist/cli/chat.js +15 -14
  57. package/dist/cli/plugins.js +6 -5
  58. package/dist/cli/snapshot-warmup.js +2 -2
  59. package/dist/cli/upgrade.js +8 -7
  60. package/dist/db/schema/conversations.d.ts +17 -0
  61. package/dist/db/schema/destinations.d.ts +12 -3
  62. package/dist/db/schema.d.ts +19 -2
  63. package/dist/{db-GFSCDAHS.js → db-RCZB7KNM.js} +3 -2
  64. package/dist/detail-5SLCGT6J.js +29 -0
  65. package/dist/{detail-W4ZSD45K.js → detail-LU6COZO6.js} +11 -10
  66. package/dist/{legacy-import-6WWXMALY.js → legacy-import-VCYLWT2V.js} +4 -3
  67. package/dist/list-2FI5SFV7.js +80 -0
  68. package/dist/list-4ALSU6ZW.js +30 -0
  69. package/dist/{list-3KZNG3SJ.js → list-KHRAWZWU.js} +11 -8
  70. package/dist/{plugin-conversations-ZYRWZYEA.js → plugin-conversations-JANXC4GA.js} +7 -6
  71. package/dist/profile-3O3OVENT.js +212 -0
  72. package/dist/{runner-267ZRLZD.js → runner-BM7D35YW.js} +12 -11
  73. package/dist/stats-J3YGCYDF.js +174 -0
  74. package/dist/{subagent-5HZPQC7V.js → subagent-P7HOSMVC.js} +10 -9
  75. package/migrations/0003_peaceful_scalphunter.sql +4 -0
  76. package/migrations/meta/0003_snapshot.json +1035 -0
  77. package/migrations/meta/_journal.json +8 -1
  78. package/package.json +5 -5
  79. package/dist/chunk-CV22LUIV.js +0 -261
  80. package/dist/list-M5BRWW3D.js +0 -92
  81. package/dist/profile-UEIRSVT3.js +0 -146
  82. package/dist/stats-L62E4O4U.js +0 -207
@@ -0,0 +1,212 @@
1
+ import {
2
+ slackLocationLabel,
3
+ summaryFromRow,
4
+ surfaceLabel
5
+ } from "./chunk-QOZOJNSE.js";
6
+ import {
7
+ ACTIVITY_DAYS,
8
+ activityDays,
9
+ emptyTotals,
10
+ normalizeEmail,
11
+ recentActorRows,
12
+ statsItems,
13
+ verifiedActorWhere
14
+ } from "./chunk-GEUUJRQF.js";
15
+ import {
16
+ conversationActiveDaysColumn,
17
+ conversationAggregateColumns
18
+ } from "./chunk-PGGEOCQY.js";
19
+ import {
20
+ actorProfileReportSchema
21
+ } from "./chunk-IDZBM3NW.js";
22
+ import "./chunk-MM5UFDAC.js";
23
+ import "./chunk-PDO5BLNM.js";
24
+ import {
25
+ getDb,
26
+ juniorConversations,
27
+ juniorIdentities,
28
+ juniorUsers
29
+ } from "./chunk-VHRM6GNH.js";
30
+ import "./chunk-A7X2FDUO.js";
31
+ import {
32
+ juniorDestinations
33
+ } from "./chunk-FXFQNHRU.js";
34
+ import "./chunk-LVA4I4H7.js";
35
+ import "./chunk-B7PUBQQM.js";
36
+ import "./chunk-I35CTGPO.js";
37
+ import "./chunk-OB42YVAE.js";
38
+ import "./chunk-6GWA276C.js";
39
+ import "./chunk-7FBGKXPE.js";
40
+ import "./chunk-MLKGABMK.js";
41
+
42
+ // src/api/people/profile.query.ts
43
+ import { and, eq, gte, sql } from "drizzle-orm";
44
+ function emptyProfile(email, nowMs) {
45
+ const end = new Date(nowMs);
46
+ end.setUTCHours(0, 0, 0, 0);
47
+ const start = new Date(end);
48
+ start.setUTCDate(start.getUTCDate() - (ACTIVITY_DAYS - 1));
49
+ return {
50
+ activityDays: activityDays(/* @__PURE__ */ new Map(), nowMs),
51
+ generatedAt: new Date(nowMs).toISOString(),
52
+ locations: [],
53
+ recentConversations: [],
54
+ actor: { email },
55
+ source: "conversation_index",
56
+ surfaces: [],
57
+ totals: emptyTotals(),
58
+ windowEnd: end.toISOString(),
59
+ windowStart: start.toISOString()
60
+ };
61
+ }
62
+ function addAggregate(map, label, row) {
63
+ const item = map.get(label) ?? {
64
+ active: 0,
65
+ conversations: 0,
66
+ durationMs: 0,
67
+ failed: 0,
68
+ label
69
+ };
70
+ item.active += row.active;
71
+ item.conversations += row.conversations;
72
+ item.durationMs += row.durationMs;
73
+ item.failed += row.failed;
74
+ if (row.tokens !== null) item.tokens = (item.tokens ?? 0) + row.tokens;
75
+ map.set(label, item);
76
+ }
77
+ function surfaceExpression() {
78
+ return sql`CASE
79
+ WHEN ${juniorConversations.source} IN ('api', 'scheduler', 'slack')
80
+ THEN ${juniorConversations.source}
81
+ WHEN ${juniorConversations.conversationId} LIKE 'slack:%' THEN 'slack'
82
+ WHEN ${juniorConversations.conversationId} LIKE 'scheduler:%' THEN 'scheduler'
83
+ WHEN ${juniorConversations.conversationId} LIKE 'api:%' THEN 'api'
84
+ ELSE 'internal'
85
+ END`;
86
+ }
87
+ function locationLabel(row) {
88
+ if (row.surface !== "slack")
89
+ return surfaceLabel(row.surface);
90
+ if (row.destinationVisibility !== "public") return "Private Conversation";
91
+ return slackLocationLabel({
92
+ channel: row.channel || void 0,
93
+ channelName: row.channelName ?? void 0
94
+ }) ?? "Conversation";
95
+ }
96
+ async function readPeopleProfileFromSql(email) {
97
+ const nowMs = Date.now();
98
+ const normalizedEmail = normalizeEmail(email);
99
+ if (!normalizedEmail) return emptyProfile("", nowMs);
100
+ const end = new Date(nowMs);
101
+ end.setUTCHours(0, 0, 0, 0);
102
+ const start = new Date(end);
103
+ start.setUTCDate(start.getUTCDate() - (ACTIVITY_DAYS - 1));
104
+ const where = verifiedActorWhere(normalizedEmail);
105
+ const surface = surfaceExpression();
106
+ const activityDate = sql`TO_CHAR(
107
+ ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
108
+ 'YYYY-MM-DD'
109
+ )`;
110
+ const channel = sql`SPLIT_PART(${juniorConversations.conversationId}, ':', 2)`;
111
+ const [totalsRows, dayRows, locationRows, surfaceRows, recentRows] = await Promise.all([
112
+ getDb().select({
113
+ email: juniorUsers.primaryEmailNormalized,
114
+ fullName: juniorUsers.displayName,
115
+ slackUserId: sql`MAX(${juniorIdentities.providerSubjectId})`,
116
+ slackUserName: sql`MAX(${juniorIdentities.handle})`,
117
+ activeDays: conversationActiveDaysColumn(),
118
+ ...conversationAggregateColumns()
119
+ }).from(juniorConversations).innerJoin(
120
+ juniorIdentities,
121
+ eq(juniorIdentities.id, juniorConversations.actorIdentityId)
122
+ ).innerJoin(juniorUsers, eq(juniorUsers.id, juniorIdentities.userId)).where(where).groupBy(juniorUsers.primaryEmailNormalized, juniorUsers.displayName),
123
+ getDb().select({
124
+ date: activityDate,
125
+ ...conversationAggregateColumns()
126
+ }).from(juniorConversations).innerJoin(
127
+ juniorIdentities,
128
+ eq(juniorIdentities.id, juniorConversations.actorIdentityId)
129
+ ).innerJoin(juniorUsers, eq(juniorUsers.id, juniorIdentities.userId)).where(and(where, gte(juniorConversations.lastActivityAt, start))).groupBy(activityDate),
130
+ getDb().select({
131
+ channel,
132
+ channelName: juniorConversations.channelName,
133
+ destinationVisibility: juniorDestinations.visibility,
134
+ surface,
135
+ ...conversationAggregateColumns()
136
+ }).from(juniorConversations).innerJoin(
137
+ juniorIdentities,
138
+ eq(juniorIdentities.id, juniorConversations.actorIdentityId)
139
+ ).innerJoin(juniorUsers, eq(juniorUsers.id, juniorIdentities.userId)).leftJoin(
140
+ juniorDestinations,
141
+ eq(juniorDestinations.id, juniorConversations.destinationId)
142
+ ).where(where).groupBy(
143
+ channel,
144
+ juniorConversations.channelName,
145
+ juniorDestinations.visibility,
146
+ surface
147
+ ),
148
+ getDb().select({ surface, ...conversationAggregateColumns() }).from(juniorConversations).innerJoin(
149
+ juniorIdentities,
150
+ eq(juniorIdentities.id, juniorConversations.actorIdentityId)
151
+ ).innerJoin(juniorUsers, eq(juniorUsers.id, juniorIdentities.userId)).where(where).groupBy(surface),
152
+ recentActorRows(normalizedEmail)
153
+ ]);
154
+ const totalsRow = totalsRows[0];
155
+ if (!totalsRow) return emptyProfile(normalizedEmail, nowMs);
156
+ const actor = {
157
+ email: totalsRow.email,
158
+ ...totalsRow.fullName ? { fullName: totalsRow.fullName } : {},
159
+ ...totalsRow.slackUserId ? { slackUserId: totalsRow.slackUserId } : {},
160
+ ...totalsRow.slackUserName ? { slackUserName: totalsRow.slackUserName } : {}
161
+ };
162
+ const days = /* @__PURE__ */ new Map();
163
+ for (const row of dayRows) {
164
+ days.set(row.date, {
165
+ active: row.active,
166
+ conversations: row.conversations,
167
+ date: row.date,
168
+ durationMs: row.durationMs,
169
+ failed: row.failed,
170
+ ...row.tokens !== null ? { tokens: row.tokens } : {}
171
+ });
172
+ }
173
+ const locations = /* @__PURE__ */ new Map();
174
+ for (const row of locationRows) {
175
+ addAggregate(locations, locationLabel(row), row);
176
+ }
177
+ const surfaces = /* @__PURE__ */ new Map();
178
+ for (const row of surfaceRows) {
179
+ addAggregate(
180
+ surfaces,
181
+ surfaceLabel(row.surface),
182
+ row
183
+ );
184
+ }
185
+ return {
186
+ activityDays: activityDays(days, nowMs),
187
+ generatedAt: new Date(nowMs).toISOString(),
188
+ locations: statsItems(locations),
189
+ recentConversations: recentRows.map(summaryFromRow),
190
+ actor,
191
+ source: "conversation_index",
192
+ surfaces: statsItems(surfaces),
193
+ totals: {
194
+ active: totalsRow.active,
195
+ activeDays: totalsRow.activeDays,
196
+ conversations: totalsRow.conversations,
197
+ durationMs: totalsRow.durationMs,
198
+ failed: totalsRow.failed,
199
+ ...totalsRow.tokens !== null ? { tokens: totalsRow.tokens } : {}
200
+ },
201
+ windowEnd: end.toISOString(),
202
+ windowStart: start.toISOString()
203
+ };
204
+ }
205
+
206
+ // src/api/people/profile.ts
207
+ async function readPeopleProfile(email) {
208
+ return actorProfileReportSchema.parse(await readPeopleProfileFromSql(email));
209
+ }
210
+ export {
211
+ readPeopleProfile
212
+ };
@@ -3,7 +3,7 @@ import {
3
3
  finalizeFailedTurnReply,
4
4
  processPluginTask,
5
5
  scheduleSessionCompletedPluginTasks
6
- } from "./chunk-ER45IV77.js";
6
+ } from "./chunk-XSBIISXS.js";
7
7
  import "./chunk-KNFROR7R.js";
8
8
  import {
9
9
  coerceThreadArtifactsState,
@@ -13,15 +13,15 @@ import {
13
13
  markTurnFailed,
14
14
  persistThreadStateById,
15
15
  startActiveTurn
16
- } from "./chunk-WJ7STXT6.js";
16
+ } from "./chunk-NSOCZGOH.js";
17
17
  import {
18
18
  coerceThreadConversationState
19
19
  } from "./chunk-6DTVCPLO.js";
20
- import "./chunk-OL6XQ23W.js";
20
+ import "./chunk-IVXL57YF.js";
21
21
  import {
22
22
  commitMessages,
23
23
  loadProjection
24
- } from "./chunk-DHHU2WSG.js";
24
+ } from "./chunk-IQIBZXGB.js";
25
25
  import {
26
26
  buildConversationContext,
27
27
  hydrateConversationMessages,
@@ -29,12 +29,12 @@ import {
29
29
  normalizeConversationText,
30
30
  updateConversationStats,
31
31
  upsertConversationMessage
32
- } from "./chunk-IO65E4ZD.js";
32
+ } from "./chunk-JPQISMMJ.js";
33
33
  import "./chunk-PDO5BLNM.js";
34
- import "./chunk-FTTFV6DC.js";
35
- import "./chunk-WTYEKPXU.js";
36
- import "./chunk-EOWXRY5E.js";
37
- import "./chunk-OGHXZ4KQ.js";
34
+ import "./chunk-TPTJEHUE.js";
35
+ import "./chunk-FP5N5OWZ.js";
36
+ import "./chunk-PWC24W5F.js";
37
+ import "./chunk-VHRM6GNH.js";
38
38
  import "./chunk-G3E7SCME.js";
39
39
  import {
40
40
  sleep
@@ -42,7 +42,8 @@ import {
42
42
  import {
43
43
  stripRuntimeTurnContext,
44
44
  trimTrailingAssistantMessages
45
- } from "./chunk-EEZCY5WX.js";
45
+ } from "./chunk-A7X2FDUO.js";
46
+ import "./chunk-FXFQNHRU.js";
46
47
  import "./chunk-LVA4I4H7.js";
47
48
  import "./chunk-B7PUBQQM.js";
48
49
  import {
@@ -287,7 +288,7 @@ async function runLocalAgentTurn(input, deps) {
287
288
  modelId: reply.diagnostics.modelId,
288
289
  durationMs: reply.diagnostics.durationMs,
289
290
  usage: reply.diagnostics.usage,
290
- reasoningLevel: reply.diagnostics.thinkingLevel,
291
+ reasoningLevel: reply.diagnostics.reasoningLevel,
291
292
  destination,
292
293
  source,
293
294
  actor: localActor,
@@ -0,0 +1,174 @@
1
+ import {
2
+ conversationAggregateColumns
3
+ } from "./chunk-PGGEOCQY.js";
4
+ import {
5
+ conversationStatsReportSchema
6
+ } from "./chunk-MM5UFDAC.js";
7
+ import "./chunk-PDO5BLNM.js";
8
+ import {
9
+ getDb,
10
+ juniorConversations,
11
+ juniorIdentities,
12
+ juniorUsers
13
+ } from "./chunk-VHRM6GNH.js";
14
+ import "./chunk-A7X2FDUO.js";
15
+ import {
16
+ juniorDestinations
17
+ } from "./chunk-FXFQNHRU.js";
18
+ import "./chunk-LVA4I4H7.js";
19
+ import "./chunk-B7PUBQQM.js";
20
+ import "./chunk-I35CTGPO.js";
21
+ import "./chunk-OB42YVAE.js";
22
+ import "./chunk-6GWA276C.js";
23
+ import "./chunk-7FBGKXPE.js";
24
+ import "./chunk-MLKGABMK.js";
25
+
26
+ // src/api/conversations/stats.query.ts
27
+ import { and, eq, gte, isNull, lte } from "drizzle-orm";
28
+ var WINDOW_MS = 7 * 24 * 60 * 60 * 1e3;
29
+ function emptyStatsItem(label) {
30
+ return {
31
+ active: 0,
32
+ conversations: 0,
33
+ durationMs: 0,
34
+ failed: 0,
35
+ label
36
+ };
37
+ }
38
+ function addUsd(current, next) {
39
+ return Math.round(((current ?? 0) + next) * 1e12) / 1e12;
40
+ }
41
+ function actorLabel(row) {
42
+ return row.userEmail?.trim() || row.identityEmail?.trim() || row.userDisplayName?.trim() || row.identityDisplayName?.trim() || row.identityHandle?.trim() || row.identitySubjectId?.trim() || "Unknown";
43
+ }
44
+ function surfaceLabel(source) {
45
+ if (source === "scheduler") return "Scheduler";
46
+ if (source === "api") return "API";
47
+ if (source === "internal" || source === "local") return "Internal";
48
+ return "Conversation";
49
+ }
50
+ function locationLabel(row) {
51
+ if (row.destinationProvider !== "slack") {
52
+ return surfaceLabel(row.source);
53
+ }
54
+ if (row.destinationKind === "dm") {
55
+ return "Direct Message";
56
+ }
57
+ if (row.destinationVisibility !== "public") {
58
+ return "Private Conversation";
59
+ }
60
+ const name = (row.channelName ?? row.destinationDisplayName)?.trim().replace(/^#/, "");
61
+ return name ? `#${name}` : "Public Channel";
62
+ }
63
+ function addAggregate(map, label, row) {
64
+ const item = map.get(label) ?? emptyStatsItem(label);
65
+ item.active += row.active;
66
+ item.conversations += row.conversations;
67
+ item.durationMs += row.durationMs;
68
+ item.failed += row.failed;
69
+ if (row.tokens !== null) {
70
+ item.tokens = (item.tokens ?? 0) + row.tokens;
71
+ }
72
+ if (row.costUsd !== null) {
73
+ item.costUsd = addUsd(item.costUsd, row.costUsd);
74
+ }
75
+ map.set(label, item);
76
+ }
77
+ function statsItems(map) {
78
+ return [...map.values()].sort(
79
+ (left, right) => right.conversations - left.conversations || left.label.localeCompare(right.label)
80
+ );
81
+ }
82
+ function statsWhere(start, end) {
83
+ return and(
84
+ isNull(juniorConversations.parentConversationId),
85
+ gte(juniorConversations.lastActivityAt, start),
86
+ lte(juniorConversations.lastActivityAt, end)
87
+ );
88
+ }
89
+ async function aggregateStats(db, start, end) {
90
+ const where = statsWhere(start, end);
91
+ const [totalsRows, actorRows, locationRows] = await Promise.all([
92
+ db.select(conversationAggregateColumns()).from(juniorConversations).where(where),
93
+ db.select({
94
+ identityDisplayName: juniorIdentities.displayName,
95
+ identityEmail: juniorIdentities.emailNormalized,
96
+ identityHandle: juniorIdentities.handle,
97
+ identitySubjectId: juniorIdentities.providerSubjectId,
98
+ userDisplayName: juniorUsers.displayName,
99
+ userEmail: juniorUsers.primaryEmailNormalized,
100
+ ...conversationAggregateColumns()
101
+ }).from(juniorConversations).leftJoin(
102
+ juniorIdentities,
103
+ eq(juniorIdentities.id, juniorConversations.actorIdentityId)
104
+ ).leftJoin(juniorUsers, eq(juniorUsers.id, juniorIdentities.userId)).where(where).groupBy(
105
+ juniorIdentities.displayName,
106
+ juniorIdentities.emailNormalized,
107
+ juniorIdentities.handle,
108
+ juniorIdentities.providerSubjectId,
109
+ juniorUsers.displayName,
110
+ juniorUsers.primaryEmailNormalized
111
+ ),
112
+ db.select({
113
+ channelName: juniorConversations.channelName,
114
+ destinationDisplayName: juniorDestinations.displayName,
115
+ destinationKind: juniorDestinations.kind,
116
+ destinationProvider: juniorDestinations.provider,
117
+ destinationVisibility: juniorDestinations.visibility,
118
+ source: juniorConversations.source,
119
+ ...conversationAggregateColumns()
120
+ }).from(juniorConversations).leftJoin(
121
+ juniorDestinations,
122
+ eq(juniorDestinations.id, juniorConversations.destinationId)
123
+ ).where(where).groupBy(
124
+ juniorConversations.channelName,
125
+ juniorConversations.source,
126
+ juniorDestinations.displayName,
127
+ juniorDestinations.kind,
128
+ juniorDestinations.provider,
129
+ juniorDestinations.visibility
130
+ )
131
+ ]);
132
+ return { actorRows, locationRows, totals: totalsRows[0] };
133
+ }
134
+ async function readConversationStatsFromSql() {
135
+ const nowMs = Date.now();
136
+ const windowStartMs = nowMs - WINDOW_MS;
137
+ const { actorRows, locationRows, totals } = await aggregateStats(
138
+ getDb(),
139
+ new Date(windowStartMs),
140
+ new Date(nowMs)
141
+ );
142
+ const actors = /* @__PURE__ */ new Map();
143
+ const locations = /* @__PURE__ */ new Map();
144
+ for (const row of actorRows) {
145
+ addAggregate(actors, actorLabel(row), row);
146
+ }
147
+ for (const row of locationRows) {
148
+ addAggregate(locations, locationLabel(row), row);
149
+ }
150
+ return {
151
+ active: totals?.active ?? 0,
152
+ conversations: totals?.conversations ?? 0,
153
+ durationMs: totals?.durationMs ?? 0,
154
+ failed: totals?.failed ?? 0,
155
+ generatedAt: new Date(nowMs).toISOString(),
156
+ locations: statsItems(locations),
157
+ actors: statsItems(actors),
158
+ source: "conversation_index",
159
+ ...totals?.costUsd !== null && totals?.costUsd !== void 0 ? { costUsd: addUsd(void 0, totals.costUsd) } : {},
160
+ ...totals?.tokens !== null && totals?.tokens !== void 0 ? { tokens: totals.tokens } : {},
161
+ windowEnd: new Date(nowMs).toISOString(),
162
+ windowStart: new Date(windowStartMs).toISOString()
163
+ };
164
+ }
165
+
166
+ // src/api/conversations/stats.ts
167
+ async function readConversationStats() {
168
+ return conversationStatsReportSchema.parse(
169
+ await readConversationStatsFromSql()
170
+ );
171
+ }
172
+ export {
173
+ readConversationStats
174
+ };
@@ -1,21 +1,22 @@
1
1
  import {
2
2
  buildConversationSubagent
3
- } from "./chunk-6HHEZENZ.js";
3
+ } from "./chunk-VY7BT4SM.js";
4
4
  import {
5
5
  readConversationRecordFromSql
6
- } from "./chunk-KJHAW6VE.js";
6
+ } from "./chunk-JSAANELJ.js";
7
7
  import {
8
8
  conversationSubagentTranscriptReportSchema
9
- } from "./chunk-EUZ44ROE.js";
9
+ } from "./chunk-MM5UFDAC.js";
10
10
  import "./chunk-LVUKF5CE.js";
11
- import "./chunk-NG2AV7IB.js";
12
- import "./chunk-DHHU2WSG.js";
13
- import "./chunk-IO65E4ZD.js";
11
+ import "./chunk-VVIXK2BX.js";
12
+ import "./chunk-IQIBZXGB.js";
13
+ import "./chunk-JPQISMMJ.js";
14
14
  import "./chunk-PDO5BLNM.js";
15
- import "./chunk-WTYEKPXU.js";
16
- import "./chunk-OGHXZ4KQ.js";
15
+ import "./chunk-FP5N5OWZ.js";
16
+ import "./chunk-VHRM6GNH.js";
17
17
  import "./chunk-4ZNGQH7C.js";
18
- import "./chunk-EEZCY5WX.js";
18
+ import "./chunk-A7X2FDUO.js";
19
+ import "./chunk-FXFQNHRU.js";
19
20
  import "./chunk-LVA4I4H7.js";
20
21
  import "./chunk-B7PUBQQM.js";
21
22
  import "./chunk-I35CTGPO.js";
@@ -0,0 +1,4 @@
1
+ ALTER TABLE "junior_conversations" ADD COLUMN IF NOT EXISTS "metric_run_id" text;--> statement-breakpoint
2
+ UPDATE "junior_conversations"
3
+ SET "metric_run_id" = "run_id"
4
+ WHERE "execution_duration_ms" > 0;