@sentry/junior 0.124.2 → 0.126.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 (87) hide show
  1. package/dist/{agent-hooks-HJQTURNC.js → agent-hooks-HDSNWDQM.js} +9 -10
  2. package/dist/api/conversations/auxiliary-costs.d.ts +6 -0
  3. package/dist/api/conversations/detail.d.ts +10 -0
  4. package/dist/api/conversations/list.d.ts +11 -0
  5. package/dist/api/conversations/projection.d.ts +2 -1
  6. package/dist/api/locations/detail.d.ts +20 -0
  7. package/dist/api/people/profile.d.ts +10 -0
  8. package/dist/api/people/shared.d.ts +36 -0
  9. package/dist/api/plugin-reports.d.ts +1 -0
  10. package/dist/api/schema/conversation.d.ts +40 -0
  11. package/dist/api/schema/location.d.ts +10 -0
  12. package/dist/api/schema/person.d.ts +10 -0
  13. package/dist/api/schema.d.ts +2 -2
  14. package/dist/api/schema.js +4 -2
  15. package/dist/api.js +339 -180
  16. package/dist/app.js +52 -41
  17. package/dist/{catalog-runtime-F356WNZS.js → catalog-runtime-BDC3UWPG.js} +5 -6
  18. package/dist/chat/agent/prompt.d.ts +1 -0
  19. package/dist/chat/agent/request.d.ts +2 -1
  20. package/dist/chat/agent/resume.d.ts +2 -0
  21. package/dist/chat/agent-dispatch/types.d.ts +2 -1
  22. package/dist/chat/conversation-privacy.d.ts +7 -12
  23. package/dist/chat/conversations/destination-visibility.d.ts +7 -0
  24. package/dist/chat/conversations/history.d.ts +4 -2
  25. package/dist/chat/conversations/sql/conversation-row.d.ts +7 -4
  26. package/dist/chat/conversations/sql/store.d.ts +2 -1
  27. package/dist/chat/conversations/store.d.ts +12 -4
  28. package/dist/chat/pi/client.d.ts +1 -0
  29. package/dist/chat/plugins/agent-hooks.d.ts +1 -0
  30. package/dist/chat/plugins/conversation-event-stats.d.ts +3 -0
  31. package/dist/chat/plugins/conversation-events.d.ts +1 -1
  32. package/dist/chat/services/turn-session-record.d.ts +4 -1
  33. package/dist/chat/slack/conversation-context.d.ts +4 -7
  34. package/dist/chat/slack/footer.d.ts +10 -1
  35. package/dist/chat/slack/reply.d.ts +9 -2
  36. package/dist/chat/slack/source-link.d.ts +5 -0
  37. package/dist/chat/source.d.ts +16 -0
  38. package/dist/chat/state/turn-session.d.ts +2 -6
  39. package/dist/{chunk-L7EZRQ2J.js → chunk-4PV73JHH.js} +11 -13
  40. package/dist/{chunk-IXTIJQ7Z.js → chunk-6KWO5DU3.js} +167 -20
  41. package/dist/{chunk-AYQZCJZJ.js → chunk-6ZBSTNYN.js} +14 -0
  42. package/dist/chunk-72SDEHFP.js +102 -0
  43. package/dist/{chunk-SMTAXLX4.js → chunk-ACJZZY5W.js} +2 -2
  44. package/dist/{chunk-KYKLQYSU.js → chunk-APYVVX2Y.js} +1 -1
  45. package/dist/{chunk-EOSC6JOC.js → chunk-EFQX6XBW.js} +1 -1
  46. package/dist/{chunk-IMLJE2NY.js → chunk-EQMSKORN.js} +2 -2
  47. package/dist/{chunk-ZO6E537B.js → chunk-GHNO2WUH.js} +1 -1
  48. package/dist/{chunk-WKBPFZ25.js → chunk-GK55KLEH.js} +1 -1
  49. package/dist/{chunk-PR3M62LK.js → chunk-HX236W2U.js} +6 -4
  50. package/dist/{chunk-7LDOW4QA.js → chunk-JFW62B3Y.js} +1 -1
  51. package/dist/{chunk-ASK74NM6.js → chunk-JP2ZOSQK.js} +15 -5
  52. package/dist/{chunk-NNKVDYXN.js → chunk-KISG7E24.js} +57 -36
  53. package/dist/{chunk-DW6SLS5F.js → chunk-KP7E267S.js} +83 -24
  54. package/dist/{chunk-VMRKIKGO.js → chunk-LCRWDMCH.js} +1 -1
  55. package/dist/{chunk-AQKVWIPR.js → chunk-LIDEU7QS.js} +4 -4
  56. package/dist/{chunk-GCGJGSQL.js → chunk-S4PUICSB.js} +2 -0
  57. package/dist/{chunk-SS7MAJF5.js → chunk-TUHUIBDX.js} +60 -40
  58. package/dist/{chunk-PE44LDDQ.js → chunk-UTL3MHPC.js} +1 -0
  59. package/dist/{chunk-S7G34U75.js → chunk-VUBUFT66.js} +5 -121
  60. package/dist/{chunk-CMYDYVOD.js → chunk-WRH7DWFO.js} +15 -12
  61. package/dist/{chunk-574YK7QW.js → chunk-XLIAQRDI.js} +25 -10
  62. package/dist/{chunk-7P7YVJKH.js → chunk-XVKJJXHF.js} +17 -15
  63. package/dist/{chunk-4JW3YNQZ.js → chunk-YMSVBWBY.js} +9 -11
  64. package/dist/cli/chat.js +25 -25
  65. package/dist/cli/check.js +6 -7
  66. package/dist/cli/plugins.js +12 -13
  67. package/dist/cli/snapshot-create.js +9 -10
  68. package/dist/cli/upgrade.js +7 -8
  69. package/dist/db/schema/conversations.d.ts +20 -0
  70. package/dist/db/schema.d.ts +19 -0
  71. package/dist/{db-4SU2HJSV.js → db-AZB6AGJL.js} +7 -8
  72. package/dist/instrumentation.js +4 -5
  73. package/dist/nitro.js +2 -2
  74. package/dist/{oauth-callback-server-MMCH5QV6.js → oauth-callback-server-XK4QJLPZ.js} +18 -19
  75. package/dist/reporting-schema.d.ts +2 -0
  76. package/dist/{runner-ZDSNVGYA.js → runner-DSGDSATN.js} +13 -15
  77. package/dist/{skills-7G7LBHLK.js → skills-CO6E3BQJ.js} +6 -7
  78. package/dist/{validation-2ETDADPB.js → validation-IHLISKM5.js} +6 -7
  79. package/dist/version.js +1 -1
  80. package/migrations/0013_conversation_session_source.sql +38 -0
  81. package/migrations/0014_source_visibility.sql +8 -0
  82. package/migrations/meta/0013_snapshot.json +1250 -0
  83. package/migrations/meta/0014_snapshot.json +1201 -0
  84. package/migrations/meta/_journal.json +14 -0
  85. package/package.json +6 -6
  86. package/dist/chunk-BA5KHLPQ.js +0 -55
  87. package/dist/chunk-OB42YVAE.js +0 -16
package/dist/api.js CHANGED
@@ -24,68 +24,71 @@ import {
24
24
  personalTokenParamsSchema,
25
25
  revokePersonalTokenResponseSchema,
26
26
  statsReportSchema
27
- } from "./chunk-AYQZCJZJ.js";
27
+ } from "./chunk-6ZBSTNYN.js";
28
28
  import {
29
29
  formatSlackConversationRedactedLabel,
30
30
  readHealthReport,
31
31
  resolveSlackConversationContextFromThreadId
32
- } from "./chunk-7P7YVJKH.js";
32
+ } from "./chunk-XVKJJXHF.js";
33
33
  import {
34
34
  buildSentryConversationUrl
35
35
  } from "./chunk-4CODA7P5.js";
36
- import {
37
- renderPluginConversationEvent
38
- } from "./chunk-BA5KHLPQ.js";
39
36
  import {
40
37
  healthReportSchema,
41
38
  pluginOperationalReportFeedSchema,
42
39
  pluginsSchema,
43
40
  runtimeInfoReportSchema,
44
41
  skillReportsSchema
45
- } from "./chunk-PE44LDDQ.js";
42
+ } from "./chunk-UTL3MHPC.js";
46
43
  import {
47
44
  readStats
48
- } from "./chunk-IMLJE2NY.js";
45
+ } from "./chunk-EQMSKORN.js";
46
+ import {
47
+ parseSlackThreadId
48
+ } from "./chunk-72SDEHFP.js";
49
49
  import {
50
50
  agentTurnUsageSchema,
51
51
  hasAgentTurnUsage,
52
52
  renderJuniorNativeConversationEvent
53
- } from "./chunk-PR3M62LK.js";
53
+ } from "./chunk-HX236W2U.js";
54
54
  import "./chunk-PDO5BLNM.js";
55
55
  import {
56
56
  createPluginLogger,
57
57
  getPlugins,
58
58
  listConversationAnnotations,
59
- readViewerActors
60
- } from "./chunk-IXTIJQ7Z.js";
59
+ readViewerActors,
60
+ renderPluginConversationEvent
61
+ } from "./chunk-6KWO5DU3.js";
61
62
  import {
62
63
  decodeStoredConversationEvent,
63
64
  getDb,
64
- getSqlExecutor
65
- } from "./chunk-DW6SLS5F.js";
65
+ getSqlExecutor,
66
+ parseSessionSource
67
+ } from "./chunk-KP7E267S.js";
66
68
  import {
67
69
  juniorApiTokens,
68
70
  juniorConversationEvents,
69
71
  juniorConversations,
70
72
  juniorIdentities,
71
73
  juniorUsers
72
- } from "./chunk-GCGJGSQL.js";
73
- import "./chunk-KYKLQYSU.js";
74
- import "./chunk-574YK7QW.js";
74
+ } from "./chunk-S4PUICSB.js";
75
+ import "./chunk-APYVVX2Y.js";
76
+ import "./chunk-XLIAQRDI.js";
75
77
  import {
76
78
  juniorDestinations
77
79
  } from "./chunk-VFUK3X5B.js";
78
80
  import {
79
- canExposeConversationPayload,
80
- parseSlackThreadId
81
- } from "./chunk-S7G34U75.js";
81
+ canExposeConversationPayload
82
+ } from "./chunk-VUBUFT66.js";
82
83
  import "./chunk-HZF5P5UN.js";
83
- import "./chunk-ASK74NM6.js";
84
- import "./chunk-OB42YVAE.js";
85
- import "./chunk-F3B2YJ76.js";
84
+ import {
85
+ parseSlackChannelId,
86
+ parseSlackTeamId
87
+ } from "./chunk-F3B2YJ76.js";
88
+ import "./chunk-JP2ZOSQK.js";
86
89
  import "./chunk-6GWA276C.js";
87
- import "./chunk-VMRKIKGO.js";
88
- import "./chunk-7LDOW4QA.js";
90
+ import "./chunk-LCRWDMCH.js";
91
+ import "./chunk-JFW62B3Y.js";
89
92
  import "./chunk-MLKGABMK.js";
90
93
 
91
94
  // src/api.ts
@@ -853,7 +856,18 @@ async function readConversationEventPage(executor, args) {
853
856
  }
854
857
 
855
858
  // src/api/conversations/list.ts
856
- import { and as and5, asc as asc2, desc as desc2, eq as eq6, isNull as isNull2 } from "drizzle-orm";
859
+ import { and as and6, asc as asc2, desc as desc2, eq as eq7, isNull as isNull3 } from "drizzle-orm";
860
+
861
+ // src/chat/slack/source-link.ts
862
+ function buildSlackSourceUrl(args) {
863
+ const channelId = parseSlackChannelId(args.channelId);
864
+ const teamId = parseSlackTeamId(args.teamId);
865
+ if (!channelId || !teamId) return void 0;
866
+ const url = new URL("https://slack.com/app_redirect");
867
+ url.searchParams.set("channel", channelId);
868
+ url.searchParams.set("team", teamId);
869
+ return url.toString();
870
+ }
857
871
 
858
872
  // src/api/conversations/shared.ts
859
873
  function slackStatsLocationLabel(input) {
@@ -898,6 +912,12 @@ function surfaceFromSource(source, conversationId) {
898
912
  }
899
913
  return surfaceFromConversationId(conversationId);
900
914
  }
915
+ function sourceUrlFromConversation(conversation, canViewPrivateContent) {
916
+ if (!canViewPrivateContent || conversation.sessionSource?.platform !== "slack") {
917
+ return void 0;
918
+ }
919
+ return buildSlackSourceUrl(conversation.sessionSource);
920
+ }
901
921
  function actorIdentityReport(actor) {
902
922
  if (!actor) return void 0;
903
923
  const identity = {
@@ -922,7 +942,8 @@ function titleFromConversation(args) {
922
942
  const effectiveChannelName = args.conversation.channelName;
923
943
  const slackConversation = resolveSlackConversationContextFromThreadId({
924
944
  threadId: args.conversation.conversationId,
925
- channelName: effectiveChannelName
945
+ channelName: effectiveChannelName,
946
+ ...args.visibility ? { visibility: args.visibility } : {}
926
947
  });
927
948
  const privateLabel = args.canViewPrivateContent ? void 0 : privateConversationLabel(slackConversation);
928
949
  return privateLabel ?? args.conversation.title ?? slackStatsLocationLabel({
@@ -930,7 +951,7 @@ function titleFromConversation(args) {
930
951
  channelName: effectiveChannelName
931
952
  }) ?? surfaceFallbackLabel(args.surface);
932
953
  }
933
- function channelNameFromConversation(conversation, canViewPrivateContent) {
954
+ function channelNameFromConversation(conversation, canViewPrivateContent, visibility) {
934
955
  const effectiveChannelName = conversation.channelName;
935
956
  const slackThread = parseSlackThreadId(conversation.conversationId);
936
957
  if (!effectiveChannelName && !slackThread) {
@@ -938,7 +959,8 @@ function channelNameFromConversation(conversation, canViewPrivateContent) {
938
959
  }
939
960
  const slackConversation = resolveSlackConversationContextFromThreadId({
940
961
  threadId: conversation.conversationId,
941
- channelName: effectiveChannelName
962
+ channelName: effectiveChannelName,
963
+ ...visibility ? { visibility } : {}
942
964
  });
943
965
  if (!canViewPrivateContent) {
944
966
  return privateConversationLabel(slackConversation);
@@ -965,15 +987,22 @@ function conversationEventHistory(args) {
965
987
  function conversationSummaryFromStoredConversation(args) {
966
988
  const { conversation, durationMs, usage: usage3 } = args;
967
989
  const canViewPrivateContent = args.access?.canViewPrivateContent ?? false;
990
+ const accessVisibility = args.access?.visibility;
991
+ const visibility = accessVisibility === "public" || accessVisibility === "private" ? accessVisibility : void 0;
968
992
  const surface = surfaceFromSource(
969
993
  conversation.source,
970
994
  conversation.conversationId
971
995
  );
972
996
  const actorIdentity = actorIdentityReport(conversation.actor);
997
+ const sourceUrl = sourceUrlFromConversation(
998
+ conversation,
999
+ canViewPrivateContent
1000
+ );
973
1001
  const slackThread = parseSlackThreadId(conversation.conversationId);
974
1002
  const channelName = channelNameFromConversation(
975
1003
  conversation,
976
- canViewPrivateContent
1004
+ canViewPrivateContent,
1005
+ visibility
977
1006
  );
978
1007
  const channelNameRedacted = channelNameRedactedFromConversation(
979
1008
  conversation,
@@ -985,7 +1014,8 @@ function conversationSummaryFromStoredConversation(args) {
985
1014
  displayTitle: titleFromConversation({
986
1015
  canViewPrivateContent,
987
1016
  conversation,
988
- surface
1017
+ surface,
1018
+ visibility
989
1019
  }),
990
1020
  isParticipant: args.access?.isParticipant ?? false,
991
1021
  lastProgressAt: new Date(
@@ -995,8 +1025,10 @@ function conversationSummaryFromStoredConversation(args) {
995
1025
  startedAt: new Date(conversation.createdAtMs).toISOString(),
996
1026
  status: statusFromConversation(conversation),
997
1027
  surface,
1028
+ ...args.auxiliaryCosts ? { auxiliaryCosts: args.auxiliaryCosts } : {},
998
1029
  ...usage3 ? { cumulativeUsage: usage3 } : {},
999
1030
  ...actorIdentity ? { actorIdentity } : {},
1031
+ ...sourceUrl ? { sourceUrl } : {},
1000
1032
  ...conversation.archivedAtMs ? { archivedAt: new Date(conversation.archivedAtMs).toISOString() } : {},
1001
1033
  ...slackThread ? { channel: slackThread.channelId } : {},
1002
1034
  ...channelName ? { channelName } : {},
@@ -1044,8 +1076,7 @@ async function readConversationAccessFromSql(db, conversationIds, verifiedViewer
1044
1076
  const visibility = validRootConversationId === void 0 ? null : row.visibility;
1045
1077
  const isParticipant = validRootConversationId !== void 0 && normalizedViewerEmail !== void 0 && row.rootEmailVerified === true && row.rootEmailNormalized === normalizedViewerEmail;
1046
1078
  const canViewPrivateContent = isParticipant || validRootConversationId !== void 0 && canExposeConversationPayload({
1047
- conversationId: validRootConversationId,
1048
- ...visibility === "public" || visibility === "private" ? { visibility } : {}
1079
+ visibility: visibility ?? void 0
1049
1080
  });
1050
1081
  return [
1051
1082
  row.conversationId,
@@ -1162,6 +1193,112 @@ async function readRootConversationMetricsFromSql(db, rootConversationIds) {
1162
1193
  );
1163
1194
  }
1164
1195
 
1196
+ // src/api/conversations/auxiliary-costs.ts
1197
+ import {
1198
+ and as and5,
1199
+ eq as eq6,
1200
+ inArray as inArray4,
1201
+ isNotNull as isNotNull2,
1202
+ isNull as isNull2,
1203
+ or,
1204
+ sql as sql4
1205
+ } from "drizzle-orm";
1206
+ import { alias as alias3 } from "drizzle-orm/pg-core";
1207
+ var auxiliaryRootConversation = alias3(
1208
+ juniorConversations,
1209
+ "auxiliary_root_conversation"
1210
+ );
1211
+ function eventCost() {
1212
+ return sql4`CASE
1213
+ WHEN ${juniorConversationEvents.type} = 'structured_event'
1214
+ AND jsonb_typeof(${juniorConversationEvents.payload}->'content'->'costUsd') = 'number'
1215
+ THEN (${juniorConversationEvents.payload}->'content'->>'costUsd')::numeric
1216
+ WHEN ${juniorConversationEvents.type} = 'guardian_action_reviewed'
1217
+ AND jsonb_typeof(${juniorConversationEvents.payload}->'costUsd') = 'number'
1218
+ THEN (${juniorConversationEvents.payload}->>'costUsd')::numeric
1219
+ ELSE NULL
1220
+ END`;
1221
+ }
1222
+ async function readConversationAuxiliaryCostsFromSql(db, conversationIds, options) {
1223
+ if (conversationIds.length === 0) return /* @__PURE__ */ new Map();
1224
+ const selectedIds = [...conversationIds];
1225
+ const conversationId = options.includeDescendants ? sql4`coalesce(
1226
+ ${auxiliaryRootConversation.conversationId},
1227
+ ${juniorConversations.conversationId}
1228
+ )` : sql4`${juniorConversations.conversationId}`;
1229
+ const namespace = sql4`CASE
1230
+ WHEN ${juniorConversationEvents.type} = 'structured_event'
1231
+ THEN ${juniorConversationEvents.payload}->>'namespace'
1232
+ ELSE 'junior'
1233
+ END`;
1234
+ const name = sql4`CASE
1235
+ WHEN ${juniorConversationEvents.type} = 'structured_event'
1236
+ THEN ${juniorConversationEvents.payload}->>'name'
1237
+ ELSE ${juniorConversationEvents.type}
1238
+ END`;
1239
+ const cost2 = eventCost();
1240
+ const selectedConversation = options.includeDescendants ? or(
1241
+ and5(
1242
+ inArray4(juniorConversations.rootConversationId, selectedIds),
1243
+ isNotNull2(auxiliaryRootConversation.conversationId)
1244
+ ),
1245
+ inArray4(juniorConversations.conversationId, selectedIds)
1246
+ ) : inArray4(juniorConversations.conversationId, selectedIds);
1247
+ const rows = await db.select({
1248
+ conversationId,
1249
+ costUsd: sql4`round(sum(${cost2}), 12)::double precision`.mapWith(
1250
+ Number
1251
+ ),
1252
+ events: sql4`count(*)::integer`.mapWith(Number),
1253
+ name,
1254
+ namespace
1255
+ }).from(juniorConversationEvents).innerJoin(
1256
+ juniorConversations,
1257
+ eq6(
1258
+ juniorConversations.conversationId,
1259
+ juniorConversationEvents.conversationId
1260
+ )
1261
+ ).leftJoin(
1262
+ auxiliaryRootConversation,
1263
+ and5(
1264
+ eq6(
1265
+ auxiliaryRootConversation.conversationId,
1266
+ juniorConversations.rootConversationId
1267
+ ),
1268
+ isNull2(auxiliaryRootConversation.parentConversationId),
1269
+ eq6(
1270
+ auxiliaryRootConversation.rootConversationId,
1271
+ auxiliaryRootConversation.conversationId
1272
+ )
1273
+ )
1274
+ ).where(
1275
+ and5(
1276
+ selectedConversation,
1277
+ or(
1278
+ eq6(juniorConversationEvents.type, "structured_event"),
1279
+ eq6(juniorConversationEvents.type, "guardian_action_reviewed")
1280
+ ),
1281
+ sql4`${cost2} >= 0`
1282
+ )
1283
+ ).groupBy(conversationId, namespace, name).orderBy(conversationId, namespace, name);
1284
+ const result = /* @__PURE__ */ new Map();
1285
+ for (const row of rows) {
1286
+ const current = result.get(row.conversationId) ?? {
1287
+ costUsd: 0,
1288
+ operations: []
1289
+ };
1290
+ current.costUsd = Math.round((current.costUsd + row.costUsd) * 1e12) / 1e12;
1291
+ current.operations.push({
1292
+ costUsd: row.costUsd,
1293
+ events: row.events,
1294
+ name: row.name,
1295
+ namespace: row.namespace
1296
+ });
1297
+ result.set(row.conversationId, current);
1298
+ }
1299
+ return result;
1300
+ }
1301
+
1165
1302
  // src/api/conversations/list.ts
1166
1303
  var CONVERSATION_FEED_LIMIT = 50;
1167
1304
  async function conversationRows(db, limit, actorEmail) {
@@ -1178,17 +1315,17 @@ async function conversationRows(db, limit, actorEmail) {
1178
1315
  userDisplayName: juniorUsers.displayName
1179
1316
  }).from(juniorConversations).leftJoin(
1180
1317
  juniorDestinations,
1181
- eq6(juniorDestinations.id, juniorConversations.destinationId)
1318
+ eq7(juniorDestinations.id, juniorConversations.destinationId)
1182
1319
  ).leftJoin(
1183
1320
  juniorIdentities,
1184
- eq6(juniorIdentities.id, juniorConversations.actorIdentityId)
1185
- ).leftJoin(juniorUsers, eq6(juniorUsers.id, juniorIdentities.userId)).where(
1186
- and5(
1187
- isNull2(juniorConversations.parentConversationId),
1188
- isNull2(juniorConversations.archivedAt),
1189
- actorEmail ? and5(
1190
- eq6(juniorIdentities.emailNormalized, actorEmail),
1191
- eq6(juniorIdentities.emailVerified, true)
1321
+ eq7(juniorIdentities.id, juniorConversations.actorIdentityId)
1322
+ ).leftJoin(juniorUsers, eq7(juniorUsers.id, juniorIdentities.userId)).where(
1323
+ and6(
1324
+ isNull3(juniorConversations.parentConversationId),
1325
+ isNull3(juniorConversations.archivedAt),
1326
+ actorEmail ? and6(
1327
+ eq7(juniorIdentities.emailNormalized, actorEmail),
1328
+ eq7(juniorIdentities.emailVerified, true)
1192
1329
  ) : void 0
1193
1330
  )
1194
1331
  ).orderBy(
@@ -1198,6 +1335,10 @@ async function conversationRows(db, limit, actorEmail) {
1198
1335
  }
1199
1336
  function conversationFromRow(row) {
1200
1337
  const value = row.conversation;
1338
+ const sessionSource = value.sessionSource === null ? void 0 : parseSessionSource(value.sessionSource);
1339
+ if (value.sessionSource !== null && !sessionSource) {
1340
+ throw new Error("Conversation record session source is invalid");
1341
+ }
1201
1342
  const actorFullName = row.userDisplayName?.trim() ? row.userDisplayName : row.identityDisplayName;
1202
1343
  const actor = row.identityProvider === "slack" ? {
1203
1344
  platform: "slack",
@@ -1222,6 +1363,7 @@ function conversationFromRow(row) {
1222
1363
  ...value.archivedAt ? { archivedAtMs: value.archivedAt.getTime() } : {},
1223
1364
  ...value.channelName ? { channelName: value.channelName } : {},
1224
1365
  ...value.source ? { source: value.source } : {},
1366
+ ...sessionSource ? { sessionSource } : {},
1225
1367
  ...value.title ? { title: value.title } : {},
1226
1368
  ...value.transcriptPurgedAt ? { transcriptPurgedAtMs: value.transcriptPurgedAt.getTime() } : {}
1227
1369
  };
@@ -1241,11 +1383,11 @@ async function readConversationRecordFromSql(conversationId) {
1241
1383
  userDisplayName: juniorUsers.displayName
1242
1384
  }).from(juniorConversations).leftJoin(
1243
1385
  juniorDestinations,
1244
- eq6(juniorDestinations.id, juniorConversations.destinationId)
1386
+ eq7(juniorDestinations.id, juniorConversations.destinationId)
1245
1387
  ).leftJoin(
1246
1388
  juniorIdentities,
1247
- eq6(juniorIdentities.id, juniorConversations.actorIdentityId)
1248
- ).leftJoin(juniorUsers, eq6(juniorUsers.id, juniorIdentities.userId)).where(eq6(juniorConversations.conversationId, conversationId)).limit(1);
1389
+ eq7(juniorIdentities.id, juniorConversations.actorIdentityId)
1390
+ ).leftJoin(juniorUsers, eq7(juniorUsers.id, juniorIdentities.userId)).where(eq7(juniorConversations.conversationId, conversationId)).limit(1);
1249
1391
  const row = rows[0];
1250
1392
  return row ? {
1251
1393
  conversation: conversationFromRow(row),
@@ -1264,12 +1406,15 @@ async function readConversationFeedFromSql(options = {}) {
1264
1406
  options.actorEmail
1265
1407
  );
1266
1408
  const conversationIds = rows.map((row) => row.conversation.conversationId);
1267
- const [accessByConversation, metricsByRoot] = await Promise.all([
1409
+ const [accessByConversation, auxiliaryCostsByRoot, metricsByRoot] = await Promise.all([
1268
1410
  readConversationAccessFromSql(
1269
1411
  db,
1270
1412
  conversationIds,
1271
1413
  options.verifiedViewerEmail
1272
1414
  ),
1415
+ readConversationAuxiliaryCostsFromSql(db, conversationIds, {
1416
+ includeDescendants: true
1417
+ }),
1273
1418
  readRootConversationMetricsFromSql(db, conversationIds)
1274
1419
  ]);
1275
1420
  return {
@@ -1278,6 +1423,9 @@ async function readConversationFeedFromSql(options = {}) {
1278
1423
  return conversationSummaryFromStoredConversation({
1279
1424
  conversation: conversationFromRow(row),
1280
1425
  access: accessByConversation.get(row.conversation.conversationId),
1426
+ auxiliaryCosts: auxiliaryCostsByRoot.get(
1427
+ row.conversation.conversationId
1428
+ ),
1281
1429
  durationMs: metrics?.durationMs ?? row.conversation.durationMs,
1282
1430
  ...row.destinationVisibility === "public" && row.destinationId ? { locationId: row.destinationId } : {},
1283
1431
  usage: metrics?.usage ?? row.conversation.usage ?? void 0
@@ -1320,6 +1468,7 @@ function projectConversationDetail(args) {
1320
1468
  return {
1321
1469
  ...conversationSummaryFromStoredConversation({
1322
1470
  access: args.access,
1471
+ auxiliaryCosts: args.auxiliaryCosts,
1323
1472
  conversation,
1324
1473
  durationMs: args.durationMs,
1325
1474
  ...args.locationId ? { locationId: args.locationId } : {},
@@ -1347,13 +1496,22 @@ async function readConversationDetailFromSql(conversationId, options) {
1347
1496
  if (!record) return void 0;
1348
1497
  const executor = getSqlExecutor();
1349
1498
  const includeDescendantMetrics = record.rootConversationId === conversationId;
1350
- const [accessByConversation, annotations, modelUsage, metricsByRoot] = await Promise.all([
1499
+ const [
1500
+ accessByConversation,
1501
+ annotations,
1502
+ auxiliaryCostsByConversation,
1503
+ modelUsage,
1504
+ metricsByRoot
1505
+ ] = await Promise.all([
1351
1506
  readConversationAccessFromSql(
1352
1507
  getDb(),
1353
1508
  [conversationId],
1354
1509
  options.verifiedViewerEmail
1355
1510
  ),
1356
1511
  listConversationAnnotations(getDb(), conversationId),
1512
+ readConversationAuxiliaryCostsFromSql(getDb(), [conversationId], {
1513
+ includeDescendants: includeDescendantMetrics
1514
+ }),
1357
1515
  record.conversation.transcriptPurgedAtMs === void 0 ? readConversationModelUsageFromSql(executor, {
1358
1516
  conversationId,
1359
1517
  includeDescendants: includeDescendantMetrics
@@ -1374,6 +1532,7 @@ async function readConversationDetailFromSql(conversationId, options) {
1374
1532
  ...record,
1375
1533
  access,
1376
1534
  annotations,
1535
+ auxiliaryCosts: auxiliaryCostsByConversation.get(conversationId),
1377
1536
  durationMs: metrics?.durationMs ?? record.durationMs,
1378
1537
  events: page.events,
1379
1538
  modelUsage,
@@ -1470,13 +1629,13 @@ var event_list_default = defineApiRoute({
1470
1629
  });
1471
1630
 
1472
1631
  // src/api/conversations/stats.query.ts
1473
- import { and as and6, eq as eq7, gte, isNull as isNull3, lte, sql as sql5 } from "drizzle-orm";
1474
- import { alias as alias3 } from "drizzle-orm/pg-core";
1632
+ import { and as and7, eq as eq8, gte, isNull as isNull4, lte, sql as sql6 } from "drizzle-orm";
1633
+ import { alias as alias4 } from "drizzle-orm/pg-core";
1475
1634
 
1476
1635
  // src/api/conversations/aggregate.ts
1477
- import { sql as sql4 } from "drizzle-orm";
1636
+ import { sql as sql5 } from "drizzle-orm";
1478
1637
  function tokenValue(source) {
1479
- return sql4`
1638
+ return sql5`
1480
1639
  CASE
1481
1640
  WHEN COALESCE(
1482
1641
  ${source.usage}->>'inputTokens',
@@ -1495,7 +1654,7 @@ function tokenValue(source) {
1495
1654
  `;
1496
1655
  }
1497
1656
  function costValue(source) {
1498
- return sql4`
1657
+ return sql5`
1499
1658
  CASE
1500
1659
  WHEN ${source.usage}->'cost'->>'total' IS NOT NULL
1501
1660
  THEN (${source.usage}->'cost'->>'total')::double precision
@@ -1516,37 +1675,37 @@ function costValue(source) {
1516
1675
  function conversationAggregateColumns(sources) {
1517
1676
  const metrics = sources?.metrics ?? juniorConversations;
1518
1677
  const roots = sources?.roots ?? juniorConversations;
1519
- const conversationCount = sources ? sql4`COUNT(DISTINCT ${roots.conversationId})` : sql4`COUNT(*)`;
1678
+ const conversationCount = sources ? sql5`COUNT(DISTINCT ${roots.conversationId})` : sql5`COUNT(*)`;
1520
1679
  return {
1521
- active: sql4`${conversationCount} FILTER (
1680
+ active: sql5`${conversationCount} FILTER (
1522
1681
  WHERE ${roots.executionStatus} NOT IN ('idle', 'failed')
1523
1682
  )::integer`,
1524
- conversations: sql4`${conversationCount}::integer`,
1525
- costUsd: sql4`SUM(${costValue(metrics)})::double precision`,
1526
- durationMs: sql4`COALESCE(SUM(${metrics.durationMs}), 0)::double precision`,
1527
- failed: sql4`${conversationCount} FILTER (
1683
+ conversations: sql5`${conversationCount}::integer`,
1684
+ costUsd: sql5`SUM(${costValue(metrics)})::double precision`,
1685
+ durationMs: sql5`COALESCE(SUM(${metrics.durationMs}), 0)::double precision`,
1686
+ failed: sql5`${conversationCount} FILTER (
1528
1687
  WHERE ${roots.executionStatus} = 'failed'
1529
1688
  )::integer`,
1530
- tokens: sql4`SUM(${tokenValue(metrics)})::double precision`
1689
+ tokens: sql5`SUM(${tokenValue(metrics)})::double precision`
1531
1690
  };
1532
1691
  }
1533
1692
  function conversationRangeColumns() {
1534
1693
  return {
1535
- firstSeenAt: sql4`MIN(${juniorConversations.createdAt})`.mapWith(
1694
+ firstSeenAt: sql5`MIN(${juniorConversations.createdAt})`.mapWith(
1536
1695
  juniorConversations.createdAt
1537
1696
  ),
1538
- lastSeenAt: sql4`MAX(${juniorConversations.lastActivityAt})`.mapWith(
1697
+ lastSeenAt: sql5`MAX(${juniorConversations.lastActivityAt})`.mapWith(
1539
1698
  juniorConversations.lastActivityAt
1540
1699
  )
1541
1700
  };
1542
1701
  }
1543
1702
  function conversationActiveDaysColumn() {
1544
- return sql4`COUNT(DISTINCT (${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC')::date)::integer`;
1703
+ return sql5`COUNT(DISTINCT (${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC')::date)::integer`;
1545
1704
  }
1546
1705
 
1547
1706
  // src/api/conversations/stats.query.ts
1548
1707
  var WINDOW_DAYS = 90;
1549
- var treeConversation = alias3(juniorConversations, "stats_tree_conversation");
1708
+ var treeConversation = alias4(juniorConversations, "stats_tree_conversation");
1550
1709
  var treeAggregateColumns = conversationAggregateColumns({
1551
1710
  metrics: treeConversation,
1552
1711
  roots: juniorConversations
@@ -1605,8 +1764,8 @@ function statsItems(map) {
1605
1764
  );
1606
1765
  }
1607
1766
  function statsWhere(start, end) {
1608
- return and6(
1609
- isNull3(juniorConversations.parentConversationId),
1767
+ return and7(
1768
+ isNull4(juniorConversations.parentConversationId),
1610
1769
  gte(juniorConversations.lastActivityAt, start),
1611
1770
  lte(juniorConversations.lastActivityAt, end)
1612
1771
  );
@@ -1679,14 +1838,14 @@ function guardianStats(rows, endMs) {
1679
1838
  }
1680
1839
  async function aggregateStats(db, start, end) {
1681
1840
  const where = statsWhere(start, end);
1682
- const activityDate = sql5`TO_CHAR(
1841
+ const activityDate = sql6`TO_CHAR(
1683
1842
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
1684
1843
  'YYYY-MM-DD'
1685
1844
  )`;
1686
1845
  const [totalsRows, actorRows, locationRows, metricRows] = await Promise.all([
1687
1846
  db.select(treeAggregateColumns).from(juniorConversations).innerJoin(
1688
1847
  treeConversation,
1689
- eq7(
1848
+ eq8(
1690
1849
  treeConversation.rootConversationId,
1691
1850
  juniorConversations.conversationId
1692
1851
  )
@@ -1701,14 +1860,14 @@ async function aggregateStats(db, start, end) {
1701
1860
  ...treeAggregateColumns
1702
1861
  }).from(juniorConversations).innerJoin(
1703
1862
  treeConversation,
1704
- eq7(
1863
+ eq8(
1705
1864
  treeConversation.rootConversationId,
1706
1865
  juniorConversations.conversationId
1707
1866
  )
1708
1867
  ).leftJoin(
1709
1868
  juniorIdentities,
1710
- eq7(juniorIdentities.id, juniorConversations.actorIdentityId)
1711
- ).leftJoin(juniorUsers, eq7(juniorUsers.id, juniorIdentities.userId)).where(where).groupBy(
1869
+ eq8(juniorIdentities.id, juniorConversations.actorIdentityId)
1870
+ ).leftJoin(juniorUsers, eq8(juniorUsers.id, juniorIdentities.userId)).where(where).groupBy(
1712
1871
  juniorIdentities.displayName,
1713
1872
  juniorIdentities.emailNormalized,
1714
1873
  juniorIdentities.handle,
@@ -1726,13 +1885,13 @@ async function aggregateStats(db, start, end) {
1726
1885
  ...treeAggregateColumns
1727
1886
  }).from(juniorConversations).innerJoin(
1728
1887
  treeConversation,
1729
- eq7(
1888
+ eq8(
1730
1889
  treeConversation.rootConversationId,
1731
1890
  juniorConversations.conversationId
1732
1891
  )
1733
1892
  ).leftJoin(
1734
1893
  juniorDestinations,
1735
- eq7(juniorDestinations.id, juniorConversations.destinationId)
1894
+ eq8(juniorDestinations.id, juniorConversations.destinationId)
1736
1895
  ).where(where).groupBy(
1737
1896
  juniorConversations.channelName,
1738
1897
  juniorConversations.source,
@@ -1748,7 +1907,7 @@ async function aggregateStats(db, start, end) {
1748
1907
  tokens: treeAggregateColumns.tokens
1749
1908
  }).from(juniorConversations).innerJoin(
1750
1909
  treeConversation,
1751
- eq7(
1910
+ eq8(
1752
1911
  treeConversation.rootConversationId,
1753
1912
  juniorConversations.conversationId
1754
1913
  )
@@ -1757,26 +1916,26 @@ async function aggregateStats(db, start, end) {
1757
1916
  return { actorRows, locationRows, metricRows, totals: totalsRows[0] };
1758
1917
  }
1759
1918
  async function aggregateGuardianStats(db, start, end) {
1760
- const date = sql5`TO_CHAR(
1919
+ const date = sql6`TO_CHAR(
1761
1920
  ${juniorConversationEvents.createdAt} AT TIME ZONE 'UTC',
1762
1921
  'YYYY-MM-DD'
1763
1922
  )`;
1764
- const decision = sql5`${juniorConversationEvents.payload}->>'decision'`;
1765
- const cost2 = sql5`CASE
1923
+ const decision = sql6`${juniorConversationEvents.payload}->>'decision'`;
1924
+ const cost2 = sql6`CASE
1766
1925
  WHEN jsonb_typeof(${juniorConversationEvents.payload}->'costUsd') = 'number'
1767
1926
  THEN (${juniorConversationEvents.payload}->>'costUsd')::double precision
1768
1927
  ELSE NULL
1769
1928
  END`;
1770
1929
  return await db.select({
1771
- allow: sql5`COUNT(*) FILTER (WHERE ${decision} = 'allow')::integer`,
1772
- ask: sql5`COUNT(*) FILTER (WHERE ${decision} = 'ask')::integer`,
1773
- costUsd: sql5`SUM(${cost2})::double precision`,
1930
+ allow: sql6`COUNT(*) FILTER (WHERE ${decision} = 'allow')::integer`,
1931
+ ask: sql6`COUNT(*) FILTER (WHERE ${decision} = 'ask')::integer`,
1932
+ costUsd: sql6`SUM(${cost2})::double precision`,
1774
1933
  date,
1775
- deny: sql5`COUNT(*) FILTER (WHERE ${decision} = 'deny')::integer`,
1776
- requests: sql5`COUNT(*)::integer`
1934
+ deny: sql6`COUNT(*) FILTER (WHERE ${decision} = 'deny')::integer`,
1935
+ requests: sql6`COUNT(*)::integer`
1777
1936
  }).from(juniorConversationEvents).where(
1778
- and6(
1779
- eq7(juniorConversationEvents.type, "guardian_action_reviewed"),
1937
+ and7(
1938
+ eq8(juniorConversationEvents.type, "guardian_action_reviewed"),
1780
1939
  gte(juniorConversationEvents.createdAt, start),
1781
1940
  lte(juniorConversationEvents.createdAt, end)
1782
1941
  )
@@ -1855,7 +2014,7 @@ function readDescriptionText(home) {
1855
2014
  }
1856
2015
  }
1857
2016
  async function readSkillReports() {
1858
- const { discoverSkills } = await import("./skills-7G7LBHLK.js");
2017
+ const { discoverSkills } = await import("./skills-CO6E3BQJ.js");
1859
2018
  const skills = await discoverSkills();
1860
2019
  return skillReportsSchema.parse(
1861
2020
  skills.map((skill) => ({
@@ -1865,7 +2024,7 @@ async function readSkillReports() {
1865
2024
  );
1866
2025
  }
1867
2026
  async function readPlugins() {
1868
- const { pluginCatalogRuntime } = await import("./catalog-runtime-F356WNZS.js");
2027
+ const { pluginCatalogRuntime } = await import("./catalog-runtime-BDC3UWPG.js");
1869
2028
  return pluginsSchema.parse(
1870
2029
  pluginCatalogRuntime.getProviders().map((plugin) => ({
1871
2030
  configKeys: plugin.manifest.configKeys ?? [],
@@ -1878,7 +2037,7 @@ async function readPlugins() {
1878
2037
  async function readRuntimeInfoReport() {
1879
2038
  const [{ homeDir }, { pluginCatalogRuntime }, plugins, skills] = await Promise.all([
1880
2039
  import("./discovery-GUFTFBTL.js"),
1881
- import("./catalog-runtime-F356WNZS.js"),
2040
+ import("./catalog-runtime-BDC3UWPG.js"),
1882
2041
  readPlugins(),
1883
2042
  readSkillReports()
1884
2043
  ]);
@@ -1894,7 +2053,7 @@ async function readRuntimeInfoReport() {
1894
2053
  }
1895
2054
  async function readPluginOperationalReportFeed() {
1896
2055
  const nowMs = Date.now();
1897
- const { getPluginOperationalReports } = await import("./agent-hooks-HJQTURNC.js");
2056
+ const { getPluginOperationalReports } = await import("./agent-hooks-HDSNWDQM.js");
1898
2057
  return pluginOperationalReportFeedSchema.parse({
1899
2058
  source: "plugins",
1900
2059
  generatedAt: new Date(nowMs).toISOString(),
@@ -1914,8 +2073,8 @@ var health_default = defineApiRoute({
1914
2073
  import { Hono as Hono2 } from "hono";
1915
2074
 
1916
2075
  // src/api/locations/query.ts
1917
- import { and as and7, asc as asc3, desc as desc3, eq as eq8, gte as gte2, isNull as isNull4, sql as sql6 } from "drizzle-orm";
1918
- import { alias as alias4 } from "drizzle-orm/pg-core";
2076
+ import { and as and8, asc as asc3, desc as desc3, eq as eq9, gte as gte2, isNull as isNull5, sql as sql7 } from "drizzle-orm";
2077
+ import { alias as alias5 } from "drizzle-orm/pg-core";
1919
2078
 
1920
2079
  // src/api/conversations/reporting.ts
1921
2080
  function surfaceLabel2(surface) {
@@ -1976,7 +2135,7 @@ function summaryFromRow(row, options = {}) {
1976
2135
  // src/api/locations/query.ts
1977
2136
  var RECENT_LIMIT = 25;
1978
2137
  var ACTIVITY_DAYS = 90;
1979
- var treeConversation2 = alias4(
2138
+ var treeConversation2 = alias5(
1980
2139
  juniorConversations,
1981
2140
  "location_tree_conversation"
1982
2141
  );
@@ -2019,13 +2178,13 @@ function emptyActor(actor) {
2019
2178
  };
2020
2179
  }
2021
2180
  function topLevelWhere() {
2022
- return isNull4(juniorConversations.parentConversationId);
2181
+ return isNull5(juniorConversations.parentConversationId);
2023
2182
  }
2024
2183
  function publicLocationWhere(destinationId) {
2025
- return and7(
2184
+ return and8(
2026
2185
  topLevelWhere(),
2027
- eq8(juniorDestinations.id, destinationId),
2028
- eq8(juniorDestinations.visibility, "public")
2186
+ eq9(juniorDestinations.id, destinationId),
2187
+ eq9(juniorDestinations.visibility, "public")
2029
2188
  );
2030
2189
  }
2031
2190
  function locationColumns() {
@@ -2076,28 +2235,28 @@ async function directoryRows(db) {
2076
2235
  ...conversationRangeColumns()
2077
2236
  }).from(juniorConversations).innerJoin(
2078
2237
  treeConversation2,
2079
- eq8(
2238
+ eq9(
2080
2239
  treeConversation2.rootConversationId,
2081
2240
  juniorConversations.conversationId
2082
2241
  )
2083
2242
  ).leftJoin(
2084
2243
  juniorDestinations,
2085
- eq8(juniorDestinations.id, juniorConversations.destinationId)
2244
+ eq9(juniorDestinations.id, juniorConversations.destinationId)
2086
2245
  ).where(topLevelWhere()).groupBy(...locationGroupBy());
2087
2246
  }
2088
2247
  async function directoryActivityRows(db, start) {
2089
- const date = sql6`TO_CHAR(
2248
+ const date = sql7`TO_CHAR(
2090
2249
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
2091
2250
  'YYYY-MM-DD'
2092
2251
  )`;
2093
2252
  return db.select({
2094
- conversations: sql6`COUNT(*)::integer`,
2253
+ conversations: sql7`COUNT(*)::integer`,
2095
2254
  date,
2096
2255
  visibility: juniorDestinations.visibility
2097
2256
  }).from(juniorConversations).leftJoin(
2098
2257
  juniorDestinations,
2099
- eq8(juniorDestinations.id, juniorConversations.destinationId)
2100
- ).where(and7(topLevelWhere(), gte2(juniorConversations.lastActivityAt, start))).groupBy(date, juniorDestinations.visibility);
2258
+ eq9(juniorDestinations.id, juniorConversations.destinationId)
2259
+ ).where(and8(topLevelWhere(), gte2(juniorConversations.lastActivityAt, start))).groupBy(date, juniorDestinations.visibility);
2101
2260
  }
2102
2261
  function directoryActivityDays(rows, nowMs) {
2103
2262
  const days = /* @__PURE__ */ new Map();
@@ -2170,7 +2329,7 @@ async function recentLocationRows(db, locationId) {
2170
2329
  createdAt: juniorConversations.createdAt,
2171
2330
  destinationId: juniorDestinations.id,
2172
2331
  durationMs: juniorConversations.durationMs,
2173
- email: sql6`COALESCE(
2332
+ email: sql7`COALESCE(
2174
2333
  ${juniorUsers.primaryEmailNormalized},
2175
2334
  ${juniorIdentities.email}
2176
2335
  )`,
@@ -2179,7 +2338,7 @@ async function recentLocationRows(db, locationId) {
2179
2338
  fullName: juniorUsers.displayName,
2180
2339
  handle: juniorIdentities.handle,
2181
2340
  lastActivityAt: juniorConversations.lastActivityAt,
2182
- providerSubjectId: sql6`CASE
2341
+ providerSubjectId: sql7`CASE
2183
2342
  WHEN ${juniorIdentities.provider} = 'slack'
2184
2343
  THEN ${juniorIdentities.providerSubjectId}
2185
2344
  ELSE NULL
@@ -2190,14 +2349,14 @@ async function recentLocationRows(db, locationId) {
2190
2349
  usage: juniorConversations.usage
2191
2350
  }).from(juniorConversations).innerJoin(
2192
2351
  juniorDestinations,
2193
- eq8(juniorDestinations.id, juniorConversations.destinationId)
2352
+ eq9(juniorDestinations.id, juniorConversations.destinationId)
2194
2353
  ).leftJoin(
2195
2354
  juniorIdentities,
2196
- eq8(juniorIdentities.id, juniorConversations.actorIdentityId)
2197
- ).leftJoin(juniorUsers, eq8(juniorUsers.id, juniorIdentities.userId)).where(
2198
- and7(
2355
+ eq9(juniorIdentities.id, juniorConversations.actorIdentityId)
2356
+ ).leftJoin(juniorUsers, eq9(juniorUsers.id, juniorIdentities.userId)).where(
2357
+ and8(
2199
2358
  publicLocationWhere(locationId),
2200
- isNull4(juniorConversations.archivedAt)
2359
+ isNull5(juniorConversations.archivedAt)
2201
2360
  )
2202
2361
  ).orderBy(
2203
2362
  desc3(juniorConversations.lastActivityAt),
@@ -2211,7 +2370,7 @@ async function readLocationDetailFromSql(locationId, options = {}) {
2211
2370
  const start = new Date(end);
2212
2371
  start.setUTCDate(start.getUTCDate() - (ACTIVITY_DAYS - 1));
2213
2372
  const where = publicLocationWhere(locationId);
2214
- const activityDate = sql6`TO_CHAR(
2373
+ const activityDate = sql7`TO_CHAR(
2215
2374
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
2216
2375
  'YYYY-MM-DD'
2217
2376
  )`;
@@ -2222,27 +2381,27 @@ async function readLocationDetailFromSql(locationId, options = {}) {
2222
2381
  ...conversationRangeColumns()
2223
2382
  }).from(juniorConversations).innerJoin(
2224
2383
  treeConversation2,
2225
- eq8(
2384
+ eq9(
2226
2385
  treeConversation2.rootConversationId,
2227
2386
  juniorConversations.conversationId
2228
2387
  )
2229
2388
  ).innerJoin(
2230
2389
  juniorDestinations,
2231
- eq8(juniorDestinations.id, juniorConversations.destinationId)
2390
+ eq9(juniorDestinations.id, juniorConversations.destinationId)
2232
2391
  ).where(where).groupBy(...locationGroupBy()),
2233
2392
  getDb().select({
2234
2393
  date: activityDate,
2235
2394
  ...treeAggregateColumns2
2236
2395
  }).from(juniorConversations).innerJoin(
2237
2396
  treeConversation2,
2238
- eq8(
2397
+ eq9(
2239
2398
  treeConversation2.rootConversationId,
2240
2399
  juniorConversations.conversationId
2241
2400
  )
2242
2401
  ).innerJoin(
2243
2402
  juniorDestinations,
2244
- eq8(juniorDestinations.id, juniorConversations.destinationId)
2245
- ).where(and7(where, gte2(juniorConversations.lastActivityAt, start))).groupBy(activityDate),
2403
+ eq9(juniorDestinations.id, juniorConversations.destinationId)
2404
+ ).where(and8(where, gte2(juniorConversations.lastActivityAt, start))).groupBy(activityDate),
2246
2405
  getDb().select({
2247
2406
  actorIdentityId: juniorConversations.actorIdentityId,
2248
2407
  email: juniorUsers.primaryEmailNormalized,
@@ -2254,17 +2413,17 @@ async function readLocationDetailFromSql(locationId, options = {}) {
2254
2413
  ...treeAggregateColumns2
2255
2414
  }).from(juniorConversations).innerJoin(
2256
2415
  treeConversation2,
2257
- eq8(
2416
+ eq9(
2258
2417
  treeConversation2.rootConversationId,
2259
2418
  juniorConversations.conversationId
2260
2419
  )
2261
2420
  ).innerJoin(
2262
2421
  juniorDestinations,
2263
- eq8(juniorDestinations.id, juniorConversations.destinationId)
2422
+ eq9(juniorDestinations.id, juniorConversations.destinationId)
2264
2423
  ).leftJoin(
2265
2424
  juniorIdentities,
2266
- eq8(juniorIdentities.id, juniorConversations.actorIdentityId)
2267
- ).leftJoin(juniorUsers, eq8(juniorUsers.id, juniorIdentities.userId)).where(where).groupBy(
2425
+ eq9(juniorIdentities.id, juniorConversations.actorIdentityId)
2426
+ ).leftJoin(juniorUsers, eq9(juniorUsers.id, juniorIdentities.userId)).where(where).groupBy(
2268
2427
  juniorConversations.actorIdentityId,
2269
2428
  juniorUsers.primaryEmailNormalized,
2270
2429
  juniorUsers.displayName,
@@ -2378,22 +2537,22 @@ function createLocationRoutes() {
2378
2537
  import { Hono as Hono3 } from "hono";
2379
2538
 
2380
2539
  // src/api/people/list.query.ts
2381
- import { and as and9, eq as eq10, gte as gte3, sql as sql8 } from "drizzle-orm";
2540
+ import { and as and10, eq as eq11, gte as gte3, sql as sql9 } from "drizzle-orm";
2382
2541
 
2383
2542
  // src/api/people/shared.ts
2384
- import { and as and8, asc as asc4, desc as desc4, eq as eq9, isNull as isNull5, notExists, or, sql as sql7 } from "drizzle-orm";
2385
- import { alias as alias5 } from "drizzle-orm/pg-core";
2543
+ import { and as and9, asc as asc4, desc as desc4, eq as eq10, isNull as isNull6, notExists, or as or2, sql as sql8 } from "drizzle-orm";
2544
+ import { alias as alias6 } from "drizzle-orm/pg-core";
2386
2545
  var RECENT_LIMIT2 = 25;
2387
2546
  var ACTIVITY_DAYS2 = 365;
2388
- var peopleTreeConversation = alias5(
2547
+ var peopleTreeConversation = alias6(
2389
2548
  juniorConversations,
2390
2549
  "people_tree_conversation"
2391
2550
  );
2392
- var peopleRootConversation = alias5(
2551
+ var peopleRootConversation = alias6(
2393
2552
  juniorConversations,
2394
2553
  "people_root_conversation"
2395
2554
  );
2396
- var peopleRootIdentity = alias5(juniorIdentities, "people_root_identity");
2555
+ var peopleRootIdentity = alias6(juniorIdentities, "people_root_identity");
2397
2556
  var peopleTreeAggregateColumns = conversationAggregateColumns({
2398
2557
  metrics: peopleTreeConversation,
2399
2558
  roots: juniorConversations
@@ -2401,37 +2560,37 @@ var peopleTreeAggregateColumns = conversationAggregateColumns({
2401
2560
  function peopleTreeMetricsJoin() {
2402
2561
  const rootOwnedByActor = getDb().select({ conversationId: peopleRootConversation.conversationId }).from(peopleRootConversation).innerJoin(
2403
2562
  peopleRootIdentity,
2404
- eq9(peopleRootIdentity.id, peopleRootConversation.actorIdentityId)
2563
+ eq10(peopleRootIdentity.id, peopleRootConversation.actorIdentityId)
2405
2564
  ).where(
2406
- and8(
2407
- eq9(
2565
+ and9(
2566
+ eq10(
2408
2567
  peopleRootConversation.conversationId,
2409
2568
  juniorConversations.rootConversationId
2410
2569
  ),
2411
- isNull5(peopleRootConversation.parentConversationId),
2412
- eq9(
2570
+ isNull6(peopleRootConversation.parentConversationId),
2571
+ eq10(
2413
2572
  peopleRootConversation.rootConversationId,
2414
2573
  peopleRootConversation.conversationId
2415
2574
  ),
2416
- eq9(
2575
+ eq10(
2417
2576
  peopleRootIdentity.emailNormalized,
2418
2577
  juniorUsers.primaryEmailNormalized
2419
2578
  ),
2420
- eq9(peopleRootIdentity.emailVerified, true)
2579
+ eq10(peopleRootIdentity.emailVerified, true)
2421
2580
  )
2422
2581
  );
2423
- return and8(
2424
- eq9(
2582
+ return and9(
2583
+ eq10(
2425
2584
  peopleTreeConversation.rootConversationId,
2426
2585
  juniorConversations.rootConversationId
2427
2586
  ),
2428
- or(
2429
- eq9(
2587
+ or2(
2588
+ eq10(
2430
2589
  juniorConversations.rootConversationId,
2431
2590
  juniorConversations.conversationId
2432
2591
  ),
2433
- and8(
2434
- eq9(
2592
+ and9(
2593
+ eq10(
2435
2594
  peopleTreeConversation.conversationId,
2436
2595
  juniorConversations.conversationId
2437
2596
  ),
@@ -2481,11 +2640,11 @@ function statsItems2(map) {
2481
2640
  }
2482
2641
  function verifiedActorWhere(email) {
2483
2642
  const normalizedEmail = normalizeEmail(email);
2484
- return and8(
2485
- eq9(juniorIdentities.provider, "slack"),
2486
- eq9(juniorIdentities.emailVerified, true),
2487
- sql7`${juniorUsers.primaryEmailNormalized} IS NOT NULL`,
2488
- normalizedEmail ? eq9(juniorUsers.primaryEmailNormalized, normalizedEmail) : void 0
2643
+ return and9(
2644
+ eq10(juniorIdentities.provider, "slack"),
2645
+ eq10(juniorIdentities.emailVerified, true),
2646
+ sql8`${juniorUsers.primaryEmailNormalized} IS NOT NULL`,
2647
+ normalizedEmail ? eq10(juniorUsers.primaryEmailNormalized, normalizedEmail) : void 0
2489
2648
  );
2490
2649
  }
2491
2650
  async function recentActorRows(email) {
@@ -2508,12 +2667,12 @@ async function recentActorRows(email) {
2508
2667
  usage: juniorConversations.usage
2509
2668
  }).from(juniorConversations).innerJoin(
2510
2669
  juniorIdentities,
2511
- eq9(juniorIdentities.id, juniorConversations.actorIdentityId)
2512
- ).innerJoin(juniorUsers, eq9(juniorUsers.id, juniorIdentities.userId)).leftJoin(
2670
+ eq10(juniorIdentities.id, juniorConversations.actorIdentityId)
2671
+ ).innerJoin(juniorUsers, eq10(juniorUsers.id, juniorIdentities.userId)).leftJoin(
2513
2672
  juniorDestinations,
2514
- eq9(juniorDestinations.id, juniorConversations.destinationId)
2673
+ eq10(juniorDestinations.id, juniorConversations.destinationId)
2515
2674
  ).where(
2516
- and8(verifiedActorWhere(email), isNull5(juniorConversations.archivedAt))
2675
+ and9(verifiedActorWhere(email), isNull6(juniorConversations.archivedAt))
2517
2676
  ).orderBy(
2518
2677
  desc4(juniorConversations.lastActivityAt),
2519
2678
  asc4(juniorConversations.conversationId)
@@ -2542,7 +2701,7 @@ function directoryActivityDays2(rows, nowMs) {
2542
2701
  async function readPeopleListFromSql() {
2543
2702
  const nowMs = Date.now();
2544
2703
  const { end, start } = activityWindow(nowMs);
2545
- const activityDate = sql8`TO_CHAR(
2704
+ const activityDate = sql9`TO_CHAR(
2546
2705
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
2547
2706
  'YYYY-MM-DD'
2548
2707
  )`;
@@ -2550,24 +2709,24 @@ async function readPeopleListFromSql() {
2550
2709
  getDb().select({
2551
2710
  email: juniorUsers.primaryEmailNormalized,
2552
2711
  fullName: juniorUsers.displayName,
2553
- slackUserId: sql8`MAX(${juniorIdentities.providerSubjectId})`,
2554
- slackUserName: sql8`MAX(${juniorIdentities.handle})`,
2712
+ slackUserId: sql9`MAX(${juniorIdentities.providerSubjectId})`,
2713
+ slackUserName: sql9`MAX(${juniorIdentities.handle})`,
2555
2714
  activeDays: conversationActiveDaysColumn(),
2556
2715
  ...peopleTreeAggregateColumns,
2557
2716
  ...conversationRangeColumns()
2558
2717
  }).from(juniorConversations).innerJoin(
2559
2718
  juniorIdentities,
2560
- eq10(juniorIdentities.id, juniorConversations.actorIdentityId)
2561
- ).innerJoin(juniorUsers, eq10(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, peopleTreeMetricsJoin()).where(verifiedActorWhere()).groupBy(juniorUsers.primaryEmailNormalized, juniorUsers.displayName),
2719
+ eq11(juniorIdentities.id, juniorConversations.actorIdentityId)
2720
+ ).innerJoin(juniorUsers, eq11(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, peopleTreeMetricsJoin()).where(verifiedActorWhere()).groupBy(juniorUsers.primaryEmailNormalized, juniorUsers.displayName),
2562
2721
  getDb().select({
2563
- activePeople: sql8`COUNT(DISTINCT ${juniorUsers.id})::int`,
2564
- conversations: sql8`COUNT(*)::int`,
2722
+ activePeople: sql9`COUNT(DISTINCT ${juniorUsers.id})::int`,
2723
+ conversations: sql9`COUNT(*)::int`,
2565
2724
  date: activityDate
2566
2725
  }).from(juniorConversations).innerJoin(
2567
2726
  juniorIdentities,
2568
- eq10(juniorIdentities.id, juniorConversations.actorIdentityId)
2569
- ).innerJoin(juniorUsers, eq10(juniorUsers.id, juniorIdentities.userId)).where(
2570
- and9(
2727
+ eq11(juniorIdentities.id, juniorConversations.actorIdentityId)
2728
+ ).innerJoin(juniorUsers, eq11(juniorUsers.id, juniorIdentities.userId)).where(
2729
+ and10(
2571
2730
  verifiedActorWhere(),
2572
2731
  gte3(juniorConversations.lastActivityAt, start)
2573
2732
  )
@@ -2616,7 +2775,7 @@ var list_default3 = defineApiRoute({
2616
2775
  });
2617
2776
 
2618
2777
  // src/api/people/profile.query.ts
2619
- import { and as and10, eq as eq11, gte as gte4, sql as sql9 } from "drizzle-orm";
2778
+ import { and as and11, eq as eq12, gte as gte4, sql as sql10 } from "drizzle-orm";
2620
2779
  function emptyProfile(email, nowMs) {
2621
2780
  const end = new Date(nowMs);
2622
2781
  end.setUTCHours(0, 0, 0, 0);
@@ -2651,7 +2810,7 @@ function addAggregate2(map, label, row) {
2651
2810
  map.set(label, item);
2652
2811
  }
2653
2812
  function surfaceExpression() {
2654
- return sql9`CASE
2813
+ return sql10`CASE
2655
2814
  WHEN ${juniorConversations.source} IN ('api', 'scheduler', 'slack')
2656
2815
  THEN ${juniorConversations.source}
2657
2816
  WHEN ${juniorConversations.conversationId} LIKE 'slack:%' THEN 'slack'
@@ -2680,30 +2839,30 @@ async function readPeopleProfileFromSql(email, options = {}) {
2680
2839
  const where = verifiedActorWhere(normalizedEmail);
2681
2840
  const metricsJoin = peopleTreeMetricsJoin();
2682
2841
  const surface = surfaceExpression();
2683
- const activityDate = sql9`TO_CHAR(
2842
+ const activityDate = sql10`TO_CHAR(
2684
2843
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
2685
2844
  'YYYY-MM-DD'
2686
2845
  )`;
2687
- const channel = sql9`SPLIT_PART(${juniorConversations.conversationId}, ':', 2)`;
2846
+ const channel = sql10`SPLIT_PART(${juniorConversations.conversationId}, ':', 2)`;
2688
2847
  const [totalsRows, dayRows, locationRows, surfaceRows, recentRows] = await Promise.all([
2689
2848
  getDb().select({
2690
2849
  email: juniorUsers.primaryEmailNormalized,
2691
2850
  fullName: juniorUsers.displayName,
2692
- slackUserId: sql9`MAX(${juniorIdentities.providerSubjectId})`,
2693
- slackUserName: sql9`MAX(${juniorIdentities.handle})`,
2851
+ slackUserId: sql10`MAX(${juniorIdentities.providerSubjectId})`,
2852
+ slackUserName: sql10`MAX(${juniorIdentities.handle})`,
2694
2853
  activeDays: conversationActiveDaysColumn(),
2695
2854
  ...peopleTreeAggregateColumns
2696
2855
  }).from(juniorConversations).innerJoin(
2697
2856
  juniorIdentities,
2698
- eq11(juniorIdentities.id, juniorConversations.actorIdentityId)
2699
- ).innerJoin(juniorUsers, eq11(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(where).groupBy(juniorUsers.primaryEmailNormalized, juniorUsers.displayName),
2857
+ eq12(juniorIdentities.id, juniorConversations.actorIdentityId)
2858
+ ).innerJoin(juniorUsers, eq12(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(where).groupBy(juniorUsers.primaryEmailNormalized, juniorUsers.displayName),
2700
2859
  getDb().select({
2701
2860
  date: activityDate,
2702
2861
  ...peopleTreeAggregateColumns
2703
2862
  }).from(juniorConversations).innerJoin(
2704
2863
  juniorIdentities,
2705
- eq11(juniorIdentities.id, juniorConversations.actorIdentityId)
2706
- ).innerJoin(juniorUsers, eq11(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(and10(where, gte4(juniorConversations.lastActivityAt, start))).groupBy(activityDate),
2864
+ eq12(juniorIdentities.id, juniorConversations.actorIdentityId)
2865
+ ).innerJoin(juniorUsers, eq12(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(and11(where, gte4(juniorConversations.lastActivityAt, start))).groupBy(activityDate),
2707
2866
  getDb().select({
2708
2867
  channel,
2709
2868
  channelName: juniorConversations.channelName,
@@ -2712,10 +2871,10 @@ async function readPeopleProfileFromSql(email, options = {}) {
2712
2871
  ...peopleTreeAggregateColumns
2713
2872
  }).from(juniorConversations).innerJoin(
2714
2873
  juniorIdentities,
2715
- eq11(juniorIdentities.id, juniorConversations.actorIdentityId)
2716
- ).innerJoin(juniorUsers, eq11(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).leftJoin(
2874
+ eq12(juniorIdentities.id, juniorConversations.actorIdentityId)
2875
+ ).innerJoin(juniorUsers, eq12(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).leftJoin(
2717
2876
  juniorDestinations,
2718
- eq11(juniorDestinations.id, juniorConversations.destinationId)
2877
+ eq12(juniorDestinations.id, juniorConversations.destinationId)
2719
2878
  ).where(where).groupBy(
2720
2879
  channel,
2721
2880
  juniorConversations.channelName,
@@ -2724,8 +2883,8 @@ async function readPeopleProfileFromSql(email, options = {}) {
2724
2883
  ),
2725
2884
  getDb().select({ surface, ...peopleTreeAggregateColumns }).from(juniorConversations).innerJoin(
2726
2885
  juniorIdentities,
2727
- eq11(juniorIdentities.id, juniorConversations.actorIdentityId)
2728
- ).innerJoin(juniorUsers, eq11(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(where).groupBy(surface),
2886
+ eq12(juniorIdentities.id, juniorConversations.actorIdentityId)
2887
+ ).innerJoin(juniorUsers, eq12(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(where).groupBy(surface),
2729
2888
  recentActorRows(normalizedEmail)
2730
2889
  ]);
2731
2890
  const totalsRow = totalsRows[0];
@@ -2836,7 +2995,7 @@ import { Hono as Hono4 } from "hono";
2836
2995
 
2837
2996
  // src/personal-tokens/store.ts
2838
2997
  import { createHash, randomBytes, randomUUID } from "crypto";
2839
- import { and as and11, desc as desc5, eq as eq12, gt, isNull as isNull6 } from "drizzle-orm";
2998
+ import { and as and12, desc as desc5, eq as eq13, gt, isNull as isNull7 } from "drizzle-orm";
2840
2999
  var TOKEN_PREFIX = "jr_pat_";
2841
3000
  var TOKEN_SUFFIX_LENGTH = 8;
2842
3001
  var DEFAULT_TOKEN_LIFETIME_MS = 90 * 24 * 60 * 60 * 1e3;
@@ -2873,9 +3032,9 @@ async function createPersonalToken(args) {
2873
3032
  }
2874
3033
  async function listPersonalTokens(email, now = /* @__PURE__ */ new Date()) {
2875
3034
  const rows = await getDb().select().from(juniorApiTokens).where(
2876
- and11(
2877
- eq12(juniorApiTokens.ownerEmailNormalized, normalizeEmail2(email)),
2878
- isNull6(juniorApiTokens.revokedAt),
3035
+ and12(
3036
+ eq13(juniorApiTokens.ownerEmailNormalized, normalizeEmail2(email)),
3037
+ isNull7(juniorApiTokens.revokedAt),
2879
3038
  gt(juniorApiTokens.expiresAt, now)
2880
3039
  )
2881
3040
  ).orderBy(desc5(juniorApiTokens.createdAt));
@@ -2883,10 +3042,10 @@ async function listPersonalTokens(email, now = /* @__PURE__ */ new Date()) {
2883
3042
  }
2884
3043
  async function revokePersonalToken(args) {
2885
3044
  const rows = await getDb().update(juniorApiTokens).set({ revokedAt: args.now ?? /* @__PURE__ */ new Date() }).where(
2886
- and11(
2887
- eq12(juniorApiTokens.id, args.id),
2888
- eq12(juniorApiTokens.ownerEmailNormalized, normalizeEmail2(args.email)),
2889
- isNull6(juniorApiTokens.revokedAt)
3045
+ and12(
3046
+ eq13(juniorApiTokens.id, args.id),
3047
+ eq13(juniorApiTokens.ownerEmailNormalized, normalizeEmail2(args.email)),
3048
+ isNull7(juniorApiTokens.revokedAt)
2890
3049
  )
2891
3050
  ).returning({ id: juniorApiTokens.id });
2892
3051
  return rows.length > 0;
@@ -2897,15 +3056,15 @@ async function authenticatePersonalToken(token2, now = /* @__PURE__ */ new Date(
2897
3056
  id: juniorApiTokens.id,
2898
3057
  ownerEmailNormalized: juniorApiTokens.ownerEmailNormalized
2899
3058
  }).from(juniorApiTokens).where(
2900
- and11(
2901
- eq12(juniorApiTokens.tokenHash, hashToken(token2)),
2902
- isNull6(juniorApiTokens.revokedAt),
3059
+ and12(
3060
+ eq13(juniorApiTokens.tokenHash, hashToken(token2)),
3061
+ isNull7(juniorApiTokens.revokedAt),
2903
3062
  gt(juniorApiTokens.expiresAt, now)
2904
3063
  )
2905
3064
  ).limit(1);
2906
3065
  const match = rows[0];
2907
3066
  if (!match) return void 0;
2908
- await getDb().update(juniorApiTokens).set({ lastUsedAt: now }).where(eq12(juniorApiTokens.id, match.id));
3067
+ await getDb().update(juniorApiTokens).set({ lastUsedAt: now }).where(eq13(juniorApiTokens.id, match.id));
2909
3068
  return match.ownerEmailNormalized;
2910
3069
  }
2911
3070