@sentry/junior 0.154.0 → 0.156.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 (96) hide show
  1. package/dist/{agent-hooks-VEHV2QUA.js → agent-hooks-CCAR46PQ.js} +11 -12
  2. package/dist/api/conversations/list.d.ts +5 -3
  3. package/dist/api/conversations/membership.d.ts +16 -0
  4. package/dist/api/locations/detail.d.ts +2 -0
  5. package/dist/api/schema/conversation.d.ts +22 -4
  6. package/dist/api/schema/location.d.ts +2 -0
  7. package/dist/api/schema/person.d.ts +2 -0
  8. package/dist/api/schema.js +1 -1
  9. package/dist/api.js +331 -188
  10. package/dist/app.js +154 -51
  11. package/dist/catalog-runtime-3SNKYCBG.js +16 -0
  12. package/dist/chat/agent/types.d.ts +2 -0
  13. package/dist/chat/attachments/storage.d.ts +12 -0
  14. package/dist/chat/attachments/store.d.ts +52 -0
  15. package/dist/chat/attachments/vercel.d.ts +3 -0
  16. package/dist/chat/conversations/retention.d.ts +4 -0
  17. package/dist/chat/conversations/sql/event-actor.d.ts +14 -0
  18. package/dist/chat/conversations/sql/event-lock.d.ts +1 -1
  19. package/dist/chat/conversations/sql/participants.d.ts +17 -0
  20. package/dist/chat/ingress/bot-mention.d.ts +13 -0
  21. package/dist/chat/plugins/unfinished-work.d.ts +8 -0
  22. package/dist/chat/runtime/agent-runner.d.ts +4 -0
  23. package/dist/chat/runtime/slack-resume.d.ts +1 -1
  24. package/dist/chat/services/conversation-memory.d.ts +1 -1
  25. package/dist/chat/slack/tools/send-files.d.ts +17 -11
  26. package/dist/chat/state/conversation.d.ts +3 -1
  27. package/dist/chat/tools/types.d.ts +2 -0
  28. package/dist/{chunk-XYMCZGH6.js → chunk-3FFUC32L.js} +8 -10
  29. package/dist/{chunk-4U4MNYGP.js → chunk-3L2PMOSR.js} +6 -8
  30. package/dist/{chunk-PTJ75ZWR.js → chunk-4ZZDTHFC.js} +94 -9
  31. package/dist/{chunk-DAJZZFU7.js → chunk-53W3LZEW.js} +386 -93
  32. package/dist/{chunk-F7QUK3YP.js → chunk-6CINHXIL.js} +5 -5
  33. package/dist/{chunk-6VWMX7NS.js → chunk-6JUU7J2B.js} +4 -4
  34. package/dist/{chunk-HUO3UTAQ.js → chunk-7MA4HV4W.js} +1 -1
  35. package/dist/{chunk-O4AQDOKA.js → chunk-7RAETIYO.js} +7 -7
  36. package/dist/{chunk-4R2XCKUH.js → chunk-A6WPDFHQ.js} +1 -1
  37. package/dist/{chunk-CZD6M57V.js → chunk-AIJRG227.js} +191 -126
  38. package/dist/{chunk-RUIXF3YQ.js → chunk-BDUENQD3.js} +1 -1
  39. package/dist/{chunk-NUG3VYHL.js → chunk-CK2H7CFO.js} +2 -2
  40. package/dist/{chunk-HOGJ6TBT.js → chunk-CN2XSVKF.js} +6 -6
  41. package/dist/{chunk-3567VGCN.js → chunk-EDJ64P2P.js} +1 -1
  42. package/dist/{chunk-6PJXR4BC.js → chunk-GKC43TLS.js} +2 -2
  43. package/dist/{chunk-A6LWN4K6.js → chunk-GSBPZHLQ.js} +11 -11
  44. package/dist/{chunk-Y654CTW2.js → chunk-IIO5PFZX.js} +366 -138
  45. package/dist/{chunk-F2Q3ZHW2.js → chunk-IZEBHYI4.js} +1 -1
  46. package/dist/{chunk-QGR6QTC4.js → chunk-JUJR6WTL.js} +4 -4
  47. package/dist/{chunk-ZQT4RHUO.js → chunk-KBGMYLSV.js} +4 -1
  48. package/dist/{chunk-DK2FSQHS.js → chunk-KCA5MKHU.js} +5 -5
  49. package/dist/{chunk-NNN2WYAD.js → chunk-MC57E5U5.js} +1 -1
  50. package/dist/{chunk-6AF5GOZA.js → chunk-MJE7XKWP.js} +1 -1
  51. package/dist/{chunk-7CPN5JTA.js → chunk-NTNU6T2D.js} +3 -3
  52. package/dist/{chunk-NG4IAOVD.js → chunk-OGZPRMZA.js} +1 -1
  53. package/dist/{chunk-UCH55IGZ.js → chunk-OMQJB7YN.js} +28 -37
  54. package/dist/{chunk-2XNVS6RC.js → chunk-PMFGVLDU.js} +12 -11
  55. package/dist/{chunk-65IAU2L2.js → chunk-SE3D225X.js} +1 -1
  56. package/dist/{chunk-CCAU73CE.js → chunk-SRJA6QLM.js} +2 -2
  57. package/dist/{chunk-7RFWIHPM.js → chunk-TN4LVILT.js} +5 -5
  58. package/dist/{chunk-3ZR2R5EQ.js → chunk-TNXGMFWV.js} +1 -1
  59. package/dist/{chunk-HZF5P5UN.js → chunk-V7YE4WCP.js} +58 -7
  60. package/dist/{chunk-MSOZLASC.js → chunk-WD7SEUZO.js} +2 -2
  61. package/dist/{chunk-UG5UCHHJ.js → chunk-X5NZQH5U.js} +4 -2
  62. package/dist/{chunk-3HX67UPN.js → chunk-X7W45B5G.js} +1 -1
  63. package/dist/{chunk-FVY7AJ46.js → chunk-ZNWRYNCA.js} +7 -7
  64. package/dist/cli/chat.js +36 -36
  65. package/dist/cli/check.js +8 -9
  66. package/dist/cli/init.js +41 -7
  67. package/dist/cli/plugins.js +15 -16
  68. package/dist/cli/snapshot-create.js +11 -12
  69. package/dist/cli/upgrade.js +9 -10
  70. package/dist/db/schema/attachments.d.ts +178 -0
  71. package/dist/db/schema/conversation-events.d.ts +20 -0
  72. package/dist/db/schema/conversation-participants.d.ts +63 -0
  73. package/dist/db/schema.d.ts +255 -1
  74. package/dist/{db-SOJJLMJK.js → db-TYUUKGJX.js} +8 -8
  75. package/dist/handlers/retention.d.ts +4 -1
  76. package/dist/instrumentation.js +4 -4
  77. package/dist/nitro.js +2 -2
  78. package/dist/{oauth-callback-server-GCJROMVO.js → oauth-callback-server-AWVDKPR5.js} +26 -26
  79. package/dist/{runner-SY6KDQCN.js → runner-JUQXMACC.js} +15 -16
  80. package/dist/{sandbox-egress-signals-EKPAVWQL.js → sandbox-egress-signals-U3ZX7C5W.js} +3 -4
  81. package/dist/{skills-XJ2LJ2ML.js → skills-4GZTZX4V.js} +8 -9
  82. package/dist/spawn-32SSRWU4.js +37 -0
  83. package/dist/{validation-XQWY6QRY.js → validation-DRLNJRND.js} +8 -9
  84. package/dist/version.js +1 -1
  85. package/dist/{work-FFT5JAOU.js → work-TGIXRRJY.js} +20 -21
  86. package/dist/worker-IFXZOYED.js +24 -0
  87. package/migrations/0026_conversation_event_actor_and_participants.sql +140 -0
  88. package/migrations/0027_attachment_storage.sql +16 -0
  89. package/migrations/meta/0026_snapshot.json +2424 -0
  90. package/migrations/meta/0027_snapshot.json +2554 -0
  91. package/migrations/meta/_journal.json +15 -1
  92. package/package.json +10 -7
  93. package/dist/catalog-runtime-AK5MY63F.js +0 -17
  94. package/dist/chunk-F3B2YJ76.js +0 -57
  95. package/dist/spawn-QFCQREEP.js +0 -38
  96. package/dist/worker-JAITK72F.js +0 -25
package/dist/api.js CHANGED
@@ -33,7 +33,7 @@ import {
33
33
  taskListSchema,
34
34
  taskParamsSchema,
35
35
  taskRunListSchema
36
- } from "./chunk-UG5UCHHJ.js";
36
+ } from "./chunk-X5NZQH5U.js";
37
37
  import {
38
38
  appendAndEnqueueApiConversationMessage,
39
39
  createAndEnqueueApiConversation,
@@ -42,14 +42,14 @@ import {
42
42
  readHealthReport,
43
43
  resolveSlackConversationContextFromThreadId,
44
44
  webActorFromEmail
45
- } from "./chunk-2XNVS6RC.js";
45
+ } from "./chunk-PMFGVLDU.js";
46
46
  import {
47
47
  buildSentryConversationUrl,
48
48
  getWebAuthorization
49
- } from "./chunk-65IAU2L2.js";
49
+ } from "./chunk-SE3D225X.js";
50
50
  import {
51
51
  getConversation
52
- } from "./chunk-F7QUK3YP.js";
52
+ } from "./chunk-6CINHXIL.js";
53
53
  import {
54
54
  readTaskExecutionByConversationId,
55
55
  readTaskExecutionDays,
@@ -57,8 +57,8 @@ import {
57
57
  readTaskExecutionSummaries,
58
58
  readTaskExecutions,
59
59
  readTaskRuns
60
- } from "./chunk-A6LWN4K6.js";
61
- import "./chunk-7RFWIHPM.js";
60
+ } from "./chunk-GSBPZHLQ.js";
61
+ import "./chunk-TN4LVILT.js";
62
62
  import {
63
63
  healthReportSchema,
64
64
  pluginOperationalReportFeedSchema,
@@ -82,16 +82,16 @@ import {
82
82
  listPublicEventTasksForTeams,
83
83
  listPublicScheduledTasksForTeams,
84
84
  readStats
85
- } from "./chunk-DK2FSQHS.js";
85
+ } from "./chunk-KCA5MKHU.js";
86
86
  import {
87
87
  parseSlackThreadId
88
- } from "./chunk-NUG3VYHL.js";
88
+ } from "./chunk-CK2H7CFO.js";
89
89
  import {
90
90
  agentTurnUsageSchema,
91
91
  fallbackShortTitle,
92
92
  hasAgentTurnUsage,
93
93
  renderJuniorNativeConversationEvent
94
- } from "./chunk-4U4MNYGP.js";
94
+ } from "./chunk-3L2PMOSR.js";
95
95
  import "./chunk-3Y47VMHV.js";
96
96
  import "./chunk-PDO5BLNM.js";
97
97
  import {
@@ -101,11 +101,11 @@ import {
101
101
  renderPluginConversationEvent,
102
102
  resolveViewerUser,
103
103
  updateViewerDisplayName
104
- } from "./chunk-XYMCZGH6.js";
104
+ } from "./chunk-3FFUC32L.js";
105
105
  import {
106
106
  getSlackClient,
107
107
  withSlackRetries
108
- } from "./chunk-7CPN5JTA.js";
108
+ } from "./chunk-NTNU6T2D.js";
109
109
  import {
110
110
  decodeStoredConversationEvent,
111
111
  getConversationStore,
@@ -113,36 +113,37 @@ import {
113
113
  getSqlExecutor,
114
114
  locationFromRow,
115
115
  parseSessionSource
116
- } from "./chunk-Y654CTW2.js";
116
+ } from "./chunk-IIO5PFZX.js";
117
117
  import {
118
118
  juniorApiTokens,
119
119
  juniorConversationEvents,
120
+ juniorConversationParticipants,
120
121
  juniorConversations,
121
122
  juniorIdentities,
122
123
  juniorUsers
123
- } from "./chunk-CZD6M57V.js";
124
+ } from "./chunk-AIJRG227.js";
124
125
  import "./chunk-EM225ITJ.js";
125
- import "./chunk-NNN2WYAD.js";
126
- import "./chunk-6PJXR4BC.js";
126
+ import "./chunk-MC57E5U5.js";
127
+ import "./chunk-GKC43TLS.js";
127
128
  import {
128
129
  juniorDestinations
129
130
  } from "./chunk-VFUK3X5B.js";
130
131
  import {
131
132
  canExposeConversationPayload
132
- } from "./chunk-6AF5GOZA.js";
133
- import "./chunk-RUIXF3YQ.js";
134
- import "./chunk-HZF5P5UN.js";
133
+ } from "./chunk-MJE7XKWP.js";
134
+ import "./chunk-BDUENQD3.js";
135
135
  import {
136
136
  parseSlackChannelId,
137
137
  parseSlackMessageTs,
138
138
  parseSlackTeamId
139
- } from "./chunk-F3B2YJ76.js";
139
+ } from "./chunk-V7YE4WCP.js";
140
140
  import {
141
- logException
142
- } from "./chunk-3HX67UPN.js";
141
+ logException,
142
+ logWarn
143
+ } from "./chunk-X7W45B5G.js";
143
144
  import "./chunk-6GWA276C.js";
144
- import "./chunk-NG4IAOVD.js";
145
- import "./chunk-ZQT4RHUO.js";
145
+ import "./chunk-OGZPRMZA.js";
146
+ import "./chunk-KBGMYLSV.js";
146
147
  import "./chunk-MLKGABMK.js";
147
148
 
148
149
  // src/api.ts
@@ -227,8 +228,66 @@ async function archiveConversation(conversationId, body) {
227
228
  }
228
229
 
229
230
  // src/api/conversations/access.ts
230
- import { eq as eq2, inArray } from "drizzle-orm";
231
+ import { eq as eq3, inArray as inArray2 } from "drizzle-orm";
231
232
  import { alias } from "drizzle-orm/pg-core";
233
+
234
+ // src/api/conversations/membership.ts
235
+ import { and as and2, eq as eq2, exists, inArray, or } from "drizzle-orm";
236
+ function conversationHasParticipantUser(userId) {
237
+ const participant = getDb().select({
238
+ rootConversationId: juniorConversationParticipants.rootConversationId
239
+ }).from(juniorConversationParticipants).where(
240
+ and2(
241
+ eq2(
242
+ juniorConversationParticipants.rootConversationId,
243
+ juniorConversations.conversationId
244
+ ),
245
+ eq2(juniorConversationParticipants.userId, userId)
246
+ )
247
+ );
248
+ return exists(participant);
249
+ }
250
+ function conversationHasParticipantEmail(email) {
251
+ const participant = getDb().select({
252
+ rootConversationId: juniorConversationParticipants.rootConversationId
253
+ }).from(juniorConversationParticipants).innerJoin(
254
+ juniorUsers,
255
+ eq2(juniorUsers.id, juniorConversationParticipants.userId)
256
+ ).where(
257
+ and2(
258
+ eq2(
259
+ juniorConversationParticipants.rootConversationId,
260
+ juniorConversations.conversationId
261
+ ),
262
+ eq2(juniorUsers.primaryEmailNormalized, email)
263
+ )
264
+ );
265
+ return exists(participant);
266
+ }
267
+ function viewerConversationMembership(args) {
268
+ if (args.actorMatch && args.participantMatch) {
269
+ return or(args.actorMatch, args.participantMatch);
270
+ }
271
+ return args.actorMatch ?? args.participantMatch;
272
+ }
273
+ async function conversationIdsWithParticipantUser(db, conversationIds, userId) {
274
+ if (conversationIds.length === 0) {
275
+ return /* @__PURE__ */ new Set();
276
+ }
277
+ const rows = await db.select({
278
+ rootConversationId: juniorConversationParticipants.rootConversationId
279
+ }).from(juniorConversationParticipants).where(
280
+ and2(
281
+ eq2(juniorConversationParticipants.userId, userId),
282
+ inArray(juniorConversationParticipants.rootConversationId, [
283
+ ...conversationIds
284
+ ])
285
+ )
286
+ );
287
+ return new Set(rows.map((row) => row.rootConversationId));
288
+ }
289
+
290
+ // src/api/conversations/access.ts
232
291
  var rootConversation = alias(juniorConversations, "access_root_conversation");
233
292
  var rootDestination = alias(juniorDestinations, "access_root_destination");
234
293
  var rootIdentity = alias(juniorIdentities, "access_root_identity");
@@ -248,23 +307,37 @@ async function readConversationAccessFromSql(db, conversationIds, viewer) {
248
307
  rootUserId: rootIdentity.userId
249
308
  }).from(juniorConversations).leftJoin(
250
309
  rootConversation,
251
- eq2(
310
+ eq3(
252
311
  rootConversation.conversationId,
253
312
  juniorConversations.rootConversationId
254
313
  )
255
314
  ).leftJoin(
256
315
  rootDestination,
257
- eq2(rootDestination.id, rootConversation.destinationId)
316
+ eq3(rootDestination.id, rootConversation.destinationId)
258
317
  ).leftJoin(
259
318
  rootIdentity,
260
- eq2(rootIdentity.id, rootConversation.actorIdentityId)
261
- ).where(inArray(juniorConversations.conversationId, [...conversationIds]));
319
+ eq3(rootIdentity.id, rootConversation.actorIdentityId)
320
+ ).where(inArray2(juniorConversations.conversationId, [...conversationIds]));
321
+ const membershipConversationIds = /* @__PURE__ */ new Set();
322
+ for (const row of rows) {
323
+ membershipConversationIds.add(row.conversationId);
324
+ if (row.storedRootConversationId) {
325
+ membershipConversationIds.add(row.storedRootConversationId);
326
+ }
327
+ }
328
+ const participantRootIds = viewer !== void 0 ? await conversationIdsWithParticipantUser(
329
+ db,
330
+ [...membershipConversationIds],
331
+ viewer.id
332
+ ) : /* @__PURE__ */ new Set();
262
333
  return new Map(
263
334
  rows.map((row) => {
264
335
  const hasValidRoot = row.rootConversationId !== null && row.rootConversationId === row.storedRootConversationId && row.rootRootConversationId === row.rootConversationId && row.rootParentConversationId === null && (row.parentConversationId !== null || row.storedRootConversationId === row.conversationId);
265
336
  const validRootConversationId = hasValidRoot ? row.rootConversationId ?? void 0 : void 0;
266
337
  const visibility = validRootConversationId === void 0 ? null : row.visibility;
267
- const isParticipant = validRootConversationId !== void 0 && viewer !== void 0 && (row.rootUserId === viewer.id || normalizedViewerEmail !== void 0 && row.rootEmailVerified === true && row.rootEmailNormalized === normalizedViewerEmail);
338
+ const isRootActor = validRootConversationId !== void 0 && viewer !== void 0 && (row.rootUserId === viewer.id || normalizedViewerEmail !== void 0 && row.rootEmailVerified === true && row.rootEmailNormalized === normalizedViewerEmail);
339
+ const isMaterializedParticipant = participantRootIds.has(row.conversationId) || validRootConversationId !== void 0 && participantRootIds.has(validRootConversationId);
340
+ const isParticipant = isRootActor || isMaterializedParticipant;
268
341
  const canViewPrivateContent = isParticipant || validRootConversationId !== void 0 && canExposeConversationPayload({
269
342
  visibility: visibility ?? void 0
270
343
  });
@@ -459,7 +532,7 @@ async function resolveSlackTeamDomains(teamIds) {
459
532
  }
460
533
 
461
534
  // src/chat/pi/sql-model-usage.ts
462
- import { and as and2, eq as eq3, sql } from "drizzle-orm";
535
+ import { and as and3, eq as eq4, sql } from "drizzle-orm";
463
536
  var message = sql`${juniorConversationEvents.payload}`;
464
537
  var usage = sql`${message}->'usage'`;
465
538
  var cost = sql`${usage}->'cost'`;
@@ -557,14 +630,14 @@ async function readConversationModelUsageFromSql(executor, options) {
557
630
  costTotal: summedCost(nonnegativeNumber(cost, "total"))
558
631
  }).from(juniorConversationEvents).innerJoin(
559
632
  juniorConversations,
560
- eq3(
633
+ eq4(
561
634
  juniorConversations.conversationId,
562
635
  juniorConversationEvents.conversationId
563
636
  )
564
637
  ).where(
565
- and2(
566
- options.includeDescendants ? eq3(juniorConversations.rootConversationId, options.conversationId) : eq3(juniorConversationEvents.conversationId, options.conversationId),
567
- eq3(juniorConversationEvents.type, "assistant_message"),
638
+ and3(
639
+ options.includeDescendants ? eq4(juniorConversations.rootConversationId, options.conversationId) : eq4(juniorConversationEvents.conversationId, options.conversationId),
640
+ eq4(juniorConversationEvents.type, "assistant_message"),
568
641
  sql`jsonb_typeof(${message}->'provider') = 'string'`,
569
642
  sql`jsonb_typeof(${message}->'model') = 'string'`,
570
643
  sql`coalesce(${message}->>'provider', '') <> ''`,
@@ -626,12 +699,12 @@ function decodeConversationCursor(args) {
626
699
 
627
700
  // src/api/conversations/event-page.ts
628
701
  import {
629
- and as and3,
702
+ and as and4,
630
703
  asc,
631
704
  desc,
632
- eq as eq4,
705
+ eq as eq5,
633
706
  getTableColumns,
634
- inArray as inArray2,
707
+ inArray as inArray3,
635
708
  lt,
636
709
  sql as sql2
637
710
  } from "drizzle-orm";
@@ -836,7 +909,7 @@ function reportEventData(args) {
836
909
  type: "message",
837
910
  messageId: data.messageId,
838
911
  role: data.role,
839
- ...data.meta?.source === "web" ? { source: "web" } : {},
912
+ ...data.meta?.source === "web" || data.meta?.source === "slack" ? { source: data.meta.source } : {},
840
913
  ...actorIdentity ? { actorIdentity } : {},
841
914
  ...typeof data.meta?.eventType === "string" ? { eventType: data.meta.eventType } : {},
842
915
  ...typeof data.meta?.explicitMention === "boolean" ? { explicitMention: data.meta.explicitMention } : {},
@@ -1045,18 +1118,18 @@ async function readConversationEventRows(executor, args) {
1045
1118
  else ${juniorConversationEvents.payload}
1046
1119
  end`
1047
1120
  }).from(juniorConversationEvents).where(
1048
- and3(
1049
- eq4(juniorConversationEvents.conversationId, args.conversationId),
1121
+ and4(
1122
+ eq5(juniorConversationEvents.conversationId, args.conversationId),
1050
1123
  args.beforeSeq === void 0 ? void 0 : lt(juniorConversationEvents.seq, args.beforeSeq),
1051
- inArray2(
1124
+ inArray3(
1052
1125
  juniorConversationEvents.type,
1053
1126
  args.types ?? [...conversationReportSourceEventTypes]
1054
1127
  ),
1055
- args.subagentInvocationIds === void 0 ? void 0 : inArray2(
1128
+ args.subagentInvocationIds === void 0 ? void 0 : inArray3(
1056
1129
  sql2`${juniorConversationEvents.payload}->>'subagentInvocationId'`,
1057
1130
  args.subagentInvocationIds
1058
1131
  ),
1059
- args.toolCallIds === void 0 ? void 0 : inArray2(
1132
+ args.toolCallIds === void 0 ? void 0 : inArray3(
1060
1133
  sql2`${juniorConversationEvents.payload}->>'toolCallId'`,
1061
1134
  args.toolCallIds
1062
1135
  )
@@ -1137,7 +1210,7 @@ async function readConversationEventPage(executor, args) {
1137
1210
  }
1138
1211
 
1139
1212
  // src/api/conversations/list.ts
1140
- import { and as and6, asc as asc2, desc as desc2, eq as eq7, isNull as isNull3 } from "drizzle-orm";
1213
+ import { and as and7, asc as asc2, desc as desc2, eq as eq8, isNull as isNull3 } from "drizzle-orm";
1141
1214
 
1142
1215
  // src/api/conversations/shared.ts
1143
1216
  function slackStatsLocationLabel(input) {
@@ -1320,7 +1393,7 @@ function conversationSummaryFromStoredConversation(args) {
1320
1393
  }
1321
1394
 
1322
1395
  // src/api/conversations/usage.ts
1323
- import { and as and4, eq as eq5, inArray as inArray3, isNull, sql as sql3 } from "drizzle-orm";
1396
+ import { and as and5, eq as eq6, inArray as inArray4, isNull, sql as sql3 } from "drizzle-orm";
1324
1397
  import { alias as alias2 } from "drizzle-orm/pg-core";
1325
1398
  var usage2 = juniorConversations.usage;
1326
1399
  var metricRootConversation = alias2(
@@ -1394,19 +1467,19 @@ async function readRootConversationMetricsFromSql(db, rootConversationIds) {
1394
1467
  costTotal: summedCostNumber("total")
1395
1468
  }).from(juniorConversations).innerJoin(
1396
1469
  metricRootConversation,
1397
- and4(
1398
- eq5(
1470
+ and5(
1471
+ eq6(
1399
1472
  metricRootConversation.conversationId,
1400
1473
  juniorConversations.rootConversationId
1401
1474
  ),
1402
1475
  isNull(metricRootConversation.parentConversationId),
1403
- eq5(
1476
+ eq6(
1404
1477
  metricRootConversation.rootConversationId,
1405
1478
  metricRootConversation.conversationId
1406
1479
  )
1407
1480
  )
1408
1481
  ).where(
1409
- inArray3(juniorConversations.rootConversationId, [...rootConversationIds])
1482
+ inArray4(juniorConversations.rootConversationId, [...rootConversationIds])
1410
1483
  ).groupBy(juniorConversations.rootConversationId);
1411
1484
  return new Map(
1412
1485
  rows.flatMap((row) => {
@@ -1424,12 +1497,12 @@ async function readRootConversationMetricsFromSql(db, rootConversationIds) {
1424
1497
 
1425
1498
  // src/api/conversations/auxiliary-costs.ts
1426
1499
  import {
1427
- and as and5,
1428
- eq as eq6,
1429
- inArray as inArray4,
1500
+ and as and6,
1501
+ eq as eq7,
1502
+ inArray as inArray5,
1430
1503
  isNotNull as isNotNull2,
1431
1504
  isNull as isNull2,
1432
- or,
1505
+ or as or2,
1433
1506
  sql as sql4
1434
1507
  } from "drizzle-orm";
1435
1508
  import { alias as alias3 } from "drizzle-orm/pg-core";
@@ -1466,13 +1539,13 @@ async function readConversationAuxiliaryCostsFromSql(db, conversationIds, option
1466
1539
  ELSE ${juniorConversationEvents.type}
1467
1540
  END`;
1468
1541
  const cost2 = eventCost();
1469
- const selectedConversation = options.includeDescendants ? or(
1470
- and5(
1471
- inArray4(juniorConversations.rootConversationId, selectedIds),
1542
+ const selectedConversation = options.includeDescendants ? or2(
1543
+ and6(
1544
+ inArray5(juniorConversations.rootConversationId, selectedIds),
1472
1545
  isNotNull2(auxiliaryRootConversation.conversationId)
1473
1546
  ),
1474
- inArray4(juniorConversations.conversationId, selectedIds)
1475
- ) : inArray4(juniorConversations.conversationId, selectedIds);
1547
+ inArray5(juniorConversations.conversationId, selectedIds)
1548
+ ) : inArray5(juniorConversations.conversationId, selectedIds);
1476
1549
  const rows = await db.select({
1477
1550
  conversationId,
1478
1551
  costUsd: sql4`round(sum(${cost2}), 12)::double precision`.mapWith(
@@ -1483,29 +1556,29 @@ async function readConversationAuxiliaryCostsFromSql(db, conversationIds, option
1483
1556
  namespace
1484
1557
  }).from(juniorConversationEvents).innerJoin(
1485
1558
  juniorConversations,
1486
- eq6(
1559
+ eq7(
1487
1560
  juniorConversations.conversationId,
1488
1561
  juniorConversationEvents.conversationId
1489
1562
  )
1490
1563
  ).leftJoin(
1491
1564
  auxiliaryRootConversation,
1492
- and5(
1493
- eq6(
1565
+ and6(
1566
+ eq7(
1494
1567
  auxiliaryRootConversation.conversationId,
1495
1568
  juniorConversations.rootConversationId
1496
1569
  ),
1497
1570
  isNull2(auxiliaryRootConversation.parentConversationId),
1498
- eq6(
1571
+ eq7(
1499
1572
  auxiliaryRootConversation.rootConversationId,
1500
1573
  auxiliaryRootConversation.conversationId
1501
1574
  )
1502
1575
  )
1503
1576
  ).where(
1504
- and5(
1577
+ and6(
1505
1578
  selectedConversation,
1506
- or(
1507
- eq6(juniorConversationEvents.type, "structured_event"),
1508
- inArray4(juniorConversationEvents.type, [
1579
+ or2(
1580
+ eq7(juniorConversationEvents.type, "structured_event"),
1581
+ inArray5(juniorConversationEvents.type, [
1509
1582
  "guardian_action_reviewed",
1510
1583
  "turn_routed"
1511
1584
  ])
@@ -1531,8 +1604,64 @@ async function readConversationAuxiliaryCostsFromSql(db, conversationIds, option
1531
1604
  return result;
1532
1605
  }
1533
1606
 
1607
+ // src/chat/plugins/unfinished-work.ts
1608
+ async function listConversationWork(conversationIds) {
1609
+ if (conversationIds.length === 0) {
1610
+ return { assignedIds: [], unfinishedIds: [] };
1611
+ }
1612
+ const candidates = new Set(conversationIds);
1613
+ const assigned = /* @__PURE__ */ new Set();
1614
+ const unfinished = /* @__PURE__ */ new Set();
1615
+ for (const plugin of getPlugins()) {
1616
+ const hook = plugin.hooks?.unfinishedWork;
1617
+ if (!hook) continue;
1618
+ try {
1619
+ const result = await hook({
1620
+ conversationIds,
1621
+ db: getDb(),
1622
+ log: createPluginLogger(plugin.manifest.name),
1623
+ plugin: { name: plugin.manifest.name }
1624
+ });
1625
+ for (const conversationId of result.conversationIds) {
1626
+ if (!candidates.has(conversationId)) continue;
1627
+ unfinished.add(conversationId);
1628
+ assigned.add(conversationId);
1629
+ }
1630
+ for (const conversationId of result.assignedConversationIds ?? []) {
1631
+ if (candidates.has(conversationId)) assigned.add(conversationId);
1632
+ }
1633
+ } catch (error) {
1634
+ logWarn("plugin.unfinished_work.hook.failed", {
1635
+ "app.plugin.name": plugin.manifest.name,
1636
+ "exception.message": error instanceof Error ? error.message : String(error)
1637
+ });
1638
+ }
1639
+ }
1640
+ return {
1641
+ assignedIds: conversationIds.filter(
1642
+ (conversationId) => assigned.has(conversationId)
1643
+ ),
1644
+ unfinishedIds: conversationIds.filter(
1645
+ (conversationId) => unfinished.has(conversationId)
1646
+ )
1647
+ };
1648
+ }
1649
+
1534
1650
  // src/api/conversations/list.ts
1535
1651
  var CONVERSATION_FEED_LIMIT = 50;
1652
+ function conversationFeedMembershipFilter(filter) {
1653
+ if (!filter) return void 0;
1654
+ if (filter.kind === "viewer") {
1655
+ return viewerConversationMembership({
1656
+ actorMatch: eq8(juniorIdentities.userId, filter.userId),
1657
+ participantMatch: conversationHasParticipantUser(filter.userId)
1658
+ });
1659
+ }
1660
+ return viewerConversationMembership({
1661
+ actorMatch: eq8(juniorUsers.primaryEmailNormalized, filter.email),
1662
+ participantMatch: conversationHasParticipantEmail(filter.email)
1663
+ });
1664
+ }
1536
1665
  async function conversationRows(db, limit, filter) {
1537
1666
  return db.select({
1538
1667
  conversation: juniorConversations,
@@ -1546,15 +1675,15 @@ async function conversationRows(db, limit, filter) {
1546
1675
  userDisplayName: juniorUsers.displayName
1547
1676
  }).from(juniorConversations).leftJoin(
1548
1677
  juniorDestinations,
1549
- eq7(juniorDestinations.id, juniorConversations.destinationId)
1678
+ eq8(juniorDestinations.id, juniorConversations.destinationId)
1550
1679
  ).leftJoin(
1551
1680
  juniorIdentities,
1552
- eq7(juniorIdentities.id, juniorConversations.actorIdentityId)
1553
- ).leftJoin(juniorUsers, eq7(juniorUsers.id, juniorIdentities.userId)).where(
1554
- and6(
1681
+ eq8(juniorIdentities.id, juniorConversations.actorIdentityId)
1682
+ ).leftJoin(juniorUsers, eq8(juniorUsers.id, juniorIdentities.userId)).where(
1683
+ and7(
1555
1684
  isNull3(juniorConversations.parentConversationId),
1556
1685
  isNull3(juniorConversations.archivedAt),
1557
- filter?.kind === "viewer" ? eq7(juniorIdentities.userId, filter.userId) : filter?.kind === "actorEmail" ? eq7(juniorUsers.primaryEmailNormalized, filter.email) : void 0
1686
+ conversationFeedMembershipFilter(filter)
1558
1687
  )
1559
1688
  ).orderBy(
1560
1689
  desc2(juniorConversations.lastActivityAt),
@@ -1612,11 +1741,11 @@ async function readConversationRecordFromSql(conversationId) {
1612
1741
  userDisplayName: juniorUsers.displayName
1613
1742
  }).from(juniorConversations).leftJoin(
1614
1743
  juniorDestinations,
1615
- eq7(juniorDestinations.id, juniorConversations.destinationId)
1744
+ eq8(juniorDestinations.id, juniorConversations.destinationId)
1616
1745
  ).leftJoin(
1617
1746
  juniorIdentities,
1618
- eq7(juniorIdentities.id, juniorConversations.actorIdentityId)
1619
- ).leftJoin(juniorUsers, eq7(juniorUsers.id, juniorIdentities.userId)).where(eq7(juniorConversations.conversationId, conversationId)).limit(1);
1747
+ eq8(juniorIdentities.id, juniorConversations.actorIdentityId)
1748
+ ).leftJoin(juniorUsers, eq8(juniorUsers.id, juniorIdentities.userId)).where(eq8(juniorConversations.conversationId, conversationId)).limit(1);
1620
1749
  const row = rows[0];
1621
1750
  return row ? {
1622
1751
  conversation: conversationFromRow(row),
@@ -1628,10 +1757,16 @@ async function readConversationRecordFromSql(conversationId) {
1628
1757
  }
1629
1758
  function conversationFeedFilter(options) {
1630
1759
  if (options.viewer) {
1631
- return { kind: "viewer", userId: options.viewer.id };
1760
+ return {
1761
+ kind: "viewer",
1762
+ userId: options.viewer.id
1763
+ };
1632
1764
  }
1633
1765
  if (options.actorEmail) {
1634
- return { kind: "actorEmail", email: options.actorEmail };
1766
+ return {
1767
+ kind: "actorEmail",
1768
+ email: options.actorEmail
1769
+ };
1635
1770
  }
1636
1771
  return void 0;
1637
1772
  }
@@ -1651,7 +1786,8 @@ async function readConversationFeedFromSql(options = {}) {
1651
1786
  accessByConversation,
1652
1787
  auxiliaryCostsByRoot,
1653
1788
  metricsByRoot,
1654
- teamDomainByTeamId
1789
+ teamDomainByTeamId,
1790
+ conversationWork
1655
1791
  ] = await Promise.all([
1656
1792
  readConversationAccessFromSql(db, conversationIds, options.viewer),
1657
1793
  readConversationAuxiliaryCostsFromSql(db, conversationIds, {
@@ -1662,21 +1798,28 @@ async function readConversationFeedFromSql(options = {}) {
1662
1798
  conversations.flatMap(
1663
1799
  (conversation) => conversation.sessionSource?.platform === "slack" ? [conversation.sessionSource.teamId] : []
1664
1800
  )
1665
- )
1801
+ ),
1802
+ listConversationWork(conversationIds)
1666
1803
  ]);
1804
+ const assignedWork = new Set(conversationWork.assignedIds);
1805
+ const unfinishedWork = new Set(conversationWork.unfinishedIds);
1667
1806
  return {
1668
1807
  conversations: conversations.map((conversation, index) => {
1669
1808
  const row = rows[index];
1670
1809
  const metrics = metricsByRoot.get(conversation.conversationId);
1671
- return conversationSummaryFromStoredConversation({
1672
- conversation,
1673
- access: accessByConversation.get(conversation.conversationId),
1674
- auxiliaryCosts: auxiliaryCostsByRoot.get(conversation.conversationId),
1675
- durationMs: metrics?.durationMs ?? row.conversation.durationMs,
1676
- teamDomainByTeamId,
1677
- ...row.destination?.visibility === "public" ? { locationId: row.destination.id } : {},
1678
- usage: metrics?.usage ?? row.conversation.usage ?? void 0
1679
- });
1810
+ return {
1811
+ ...conversationSummaryFromStoredConversation({
1812
+ conversation,
1813
+ access: accessByConversation.get(conversation.conversationId),
1814
+ auxiliaryCosts: auxiliaryCostsByRoot.get(conversation.conversationId),
1815
+ durationMs: metrics?.durationMs ?? row.conversation.durationMs,
1816
+ teamDomainByTeamId,
1817
+ ...row.destination?.visibility === "public" ? { locationId: row.destination.id } : {},
1818
+ usage: metrics?.usage ?? row.conversation.usage ?? void 0
1819
+ }),
1820
+ ...assignedWork.has(conversation.conversationId) ? { assignedWork: true } : {},
1821
+ ...unfinishedWork.has(conversation.conversationId) ? { unfinishedWork: true } : {}
1822
+ };
1680
1823
  }),
1681
1824
  generatedAt: new Date(nowMs).toISOString(),
1682
1825
  source: "conversation_index"
@@ -1689,7 +1832,7 @@ async function readConversationFeed(options = {}) {
1689
1832
  }
1690
1833
 
1691
1834
  // src/chat/tasks/read.ts
1692
- import { and as and7, eq as eq8, or as or2 } from "drizzle-orm";
1835
+ import { and as and8, eq as eq9, or as or3 } from "drizzle-orm";
1693
1836
 
1694
1837
  // src/chat/scheduled-tasks/personal.ts
1695
1838
  import { z as z3 } from "zod";
@@ -1799,16 +1942,16 @@ async function creatorProfileEmails(candidates) {
1799
1942
  email: juniorUsers.primaryEmailNormalized,
1800
1943
  slackUserId: juniorIdentities.providerSubjectId,
1801
1944
  teamId: juniorIdentities.providerTenantId
1802
- }).from(juniorIdentities).innerJoin(juniorUsers, eq8(juniorUsers.id, juniorIdentities.userId)).where(
1803
- and7(
1804
- eq8(juniorIdentities.kind, "user"),
1805
- eq8(juniorIdentities.provider, "slack"),
1806
- eq8(juniorIdentities.emailVerified, true),
1807
- or2(
1945
+ }).from(juniorIdentities).innerJoin(juniorUsers, eq9(juniorUsers.id, juniorIdentities.userId)).where(
1946
+ and8(
1947
+ eq9(juniorIdentities.kind, "user"),
1948
+ eq9(juniorIdentities.provider, "slack"),
1949
+ eq9(juniorIdentities.emailVerified, true),
1950
+ or3(
1808
1951
  ...[...selectors.values()].map(
1809
- (selector) => and7(
1810
- eq8(juniorIdentities.providerTenantId, selector.teamId),
1811
- eq8(juniorIdentities.providerSubjectId, selector.slackUserId)
1952
+ (selector) => and8(
1953
+ eq9(juniorIdentities.providerTenantId, selector.teamId),
1954
+ eq9(juniorIdentities.providerSubjectId, selector.slackUserId)
1812
1955
  )
1813
1956
  )
1814
1957
  )
@@ -1844,12 +1987,12 @@ async function destinationDetails(destinations) {
1844
1987
  providerTenantId: juniorDestinations.providerTenantId,
1845
1988
  visibility: juniorDestinations.visibility
1846
1989
  }).from(juniorDestinations).where(
1847
- or2(
1990
+ or3(
1848
1991
  ...[...selectors.values()].map(
1849
- (destination) => and7(
1850
- eq8(juniorDestinations.provider, "slack"),
1851
- eq8(juniorDestinations.providerTenantId, destination.teamId),
1852
- eq8(juniorDestinations.providerDestinationId, destination.channelId)
1992
+ (destination) => and8(
1993
+ eq9(juniorDestinations.provider, "slack"),
1994
+ eq9(juniorDestinations.providerTenantId, destination.teamId),
1995
+ eq9(juniorDestinations.providerDestinationId, destination.channelId)
1853
1996
  )
1854
1997
  )
1855
1998
  )
@@ -2502,7 +2645,7 @@ async function requireConversationPendingMessages(conversationId, options = {})
2502
2645
  }
2503
2646
 
2504
2647
  // src/api/conversations/stats.query.ts
2505
- import { and as and8, eq as eq9, gte, isNull as isNull4, lte, sql as sql6 } from "drizzle-orm";
2648
+ import { and as and9, eq as eq10, gte, isNull as isNull4, lte, sql as sql6 } from "drizzle-orm";
2506
2649
  import { alias as alias4 } from "drizzle-orm/pg-core";
2507
2650
 
2508
2651
  // src/api/conversations/aggregate.ts
@@ -2646,7 +2789,7 @@ function statsItems(map) {
2646
2789
  );
2647
2790
  }
2648
2791
  function statsWhere(start, end) {
2649
- return and8(
2792
+ return and9(
2650
2793
  isNull4(juniorConversations.parentConversationId),
2651
2794
  gte(juniorConversations.lastActivityAt, start),
2652
2795
  lte(juniorConversations.lastActivityAt, end)
@@ -2730,7 +2873,7 @@ async function aggregateStats(db, start, end) {
2730
2873
  const [totalsRows, actorRows, locationRows, metricRows] = await Promise.all([
2731
2874
  db.select(treeAggregateColumns).from(juniorConversations).innerJoin(
2732
2875
  treeConversation,
2733
- eq9(
2876
+ eq10(
2734
2877
  treeConversation.rootConversationId,
2735
2878
  juniorConversations.conversationId
2736
2879
  )
@@ -2745,14 +2888,14 @@ async function aggregateStats(db, start, end) {
2745
2888
  ...treeAggregateColumns
2746
2889
  }).from(juniorConversations).innerJoin(
2747
2890
  treeConversation,
2748
- eq9(
2891
+ eq10(
2749
2892
  treeConversation.rootConversationId,
2750
2893
  juniorConversations.conversationId
2751
2894
  )
2752
2895
  ).leftJoin(
2753
2896
  juniorIdentities,
2754
- eq9(juniorIdentities.id, juniorConversations.actorIdentityId)
2755
- ).leftJoin(juniorUsers, eq9(juniorUsers.id, juniorIdentities.userId)).where(where).groupBy(
2897
+ eq10(juniorIdentities.id, juniorConversations.actorIdentityId)
2898
+ ).leftJoin(juniorUsers, eq10(juniorUsers.id, juniorIdentities.userId)).where(where).groupBy(
2756
2899
  juniorIdentities.displayName,
2757
2900
  juniorIdentities.emailNormalized,
2758
2901
  juniorIdentities.handle,
@@ -2770,13 +2913,13 @@ async function aggregateStats(db, start, end) {
2770
2913
  ...treeAggregateColumns
2771
2914
  }).from(juniorConversations).innerJoin(
2772
2915
  treeConversation,
2773
- eq9(
2916
+ eq10(
2774
2917
  treeConversation.rootConversationId,
2775
2918
  juniorConversations.conversationId
2776
2919
  )
2777
2920
  ).leftJoin(
2778
2921
  juniorDestinations,
2779
- eq9(juniorDestinations.id, juniorConversations.destinationId)
2922
+ eq10(juniorDestinations.id, juniorConversations.destinationId)
2780
2923
  ).where(where).groupBy(
2781
2924
  juniorConversations.channelName,
2782
2925
  juniorConversations.source,
@@ -2795,7 +2938,7 @@ async function aggregateStats(db, start, end) {
2795
2938
  tokens: treeAggregateColumns.tokens
2796
2939
  }).from(juniorConversations).innerJoin(
2797
2940
  treeConversation,
2798
- eq9(
2941
+ eq10(
2799
2942
  treeConversation.rootConversationId,
2800
2943
  juniorConversations.conversationId
2801
2944
  )
@@ -2822,8 +2965,8 @@ async function aggregateGuardianStats(db, start, end) {
2822
2965
  deny: sql6`COUNT(*) FILTER (WHERE ${decision} = 'deny')::integer`,
2823
2966
  requests: sql6`COUNT(*)::integer`
2824
2967
  }).from(juniorConversationEvents).where(
2825
- and8(
2826
- eq9(juniorConversationEvents.type, "guardian_action_reviewed"),
2968
+ and9(
2969
+ eq10(juniorConversationEvents.type, "guardian_action_reviewed"),
2827
2970
  gte(juniorConversationEvents.createdAt, start),
2828
2971
  lte(juniorConversationEvents.createdAt, end)
2829
2972
  )
@@ -3032,7 +3175,7 @@ function createConversationRoutes() {
3032
3175
  import { Hono as Hono2 } from "hono";
3033
3176
 
3034
3177
  // src/api/locations/query.ts
3035
- import { and as and9, asc as asc3, desc as desc3, eq as eq10, gte as gte2, isNull as isNull5, sql as sql7 } from "drizzle-orm";
3178
+ import { and as and10, asc as asc3, desc as desc3, eq as eq11, gte as gte2, isNull as isNull5, sql as sql7 } from "drizzle-orm";
3036
3179
  import { alias as alias5 } from "drizzle-orm/pg-core";
3037
3180
 
3038
3181
  // src/api/conversations/reporting.ts
@@ -3140,10 +3283,10 @@ function topLevelWhere() {
3140
3283
  return isNull5(juniorConversations.parentConversationId);
3141
3284
  }
3142
3285
  function publicLocationWhere(destinationId) {
3143
- return and9(
3286
+ return and10(
3144
3287
  topLevelWhere(),
3145
- eq10(juniorDestinations.id, destinationId),
3146
- eq10(juniorDestinations.visibility, "public")
3288
+ eq11(juniorDestinations.id, destinationId),
3289
+ eq11(juniorDestinations.visibility, "public")
3147
3290
  );
3148
3291
  }
3149
3292
  function locationColumns() {
@@ -3194,13 +3337,13 @@ async function directoryRows(db) {
3194
3337
  ...conversationRangeColumns()
3195
3338
  }).from(juniorConversations).innerJoin(
3196
3339
  treeConversation2,
3197
- eq10(
3340
+ eq11(
3198
3341
  treeConversation2.rootConversationId,
3199
3342
  juniorConversations.conversationId
3200
3343
  )
3201
3344
  ).leftJoin(
3202
3345
  juniorDestinations,
3203
- eq10(juniorDestinations.id, juniorConversations.destinationId)
3346
+ eq11(juniorDestinations.id, juniorConversations.destinationId)
3204
3347
  ).where(topLevelWhere()).groupBy(...locationGroupBy());
3205
3348
  }
3206
3349
  async function directoryActivityRows(db, start) {
@@ -3214,8 +3357,8 @@ async function directoryActivityRows(db, start) {
3214
3357
  visibility: juniorDestinations.visibility
3215
3358
  }).from(juniorConversations).leftJoin(
3216
3359
  juniorDestinations,
3217
- eq10(juniorDestinations.id, juniorConversations.destinationId)
3218
- ).where(and9(topLevelWhere(), gte2(juniorConversations.lastActivityAt, start))).groupBy(date, juniorDestinations.visibility);
3360
+ eq11(juniorDestinations.id, juniorConversations.destinationId)
3361
+ ).where(and10(topLevelWhere(), gte2(juniorConversations.lastActivityAt, start))).groupBy(date, juniorDestinations.visibility);
3219
3362
  }
3220
3363
  function directoryActivityDays(rows, nowMs) {
3221
3364
  const days = /* @__PURE__ */ new Map();
@@ -3308,12 +3451,12 @@ async function recentLocationRows(db, locationId) {
3308
3451
  usage: juniorConversations.usage
3309
3452
  }).from(juniorConversations).innerJoin(
3310
3453
  juniorDestinations,
3311
- eq10(juniorDestinations.id, juniorConversations.destinationId)
3454
+ eq11(juniorDestinations.id, juniorConversations.destinationId)
3312
3455
  ).leftJoin(
3313
3456
  juniorIdentities,
3314
- eq10(juniorIdentities.id, juniorConversations.actorIdentityId)
3315
- ).leftJoin(juniorUsers, eq10(juniorUsers.id, juniorIdentities.userId)).where(
3316
- and9(
3457
+ eq11(juniorIdentities.id, juniorConversations.actorIdentityId)
3458
+ ).leftJoin(juniorUsers, eq11(juniorUsers.id, juniorIdentities.userId)).where(
3459
+ and10(
3317
3460
  publicLocationWhere(locationId),
3318
3461
  isNull5(juniorConversations.archivedAt)
3319
3462
  )
@@ -3340,27 +3483,27 @@ async function readLocationDetailFromSql(locationId, options = {}) {
3340
3483
  ...conversationRangeColumns()
3341
3484
  }).from(juniorConversations).innerJoin(
3342
3485
  treeConversation2,
3343
- eq10(
3486
+ eq11(
3344
3487
  treeConversation2.rootConversationId,
3345
3488
  juniorConversations.conversationId
3346
3489
  )
3347
3490
  ).innerJoin(
3348
3491
  juniorDestinations,
3349
- eq10(juniorDestinations.id, juniorConversations.destinationId)
3492
+ eq11(juniorDestinations.id, juniorConversations.destinationId)
3350
3493
  ).where(where).groupBy(...locationGroupBy()),
3351
3494
  getDb().select({
3352
3495
  date: activityDate,
3353
3496
  ...treeAggregateColumns2
3354
3497
  }).from(juniorConversations).innerJoin(
3355
3498
  treeConversation2,
3356
- eq10(
3499
+ eq11(
3357
3500
  treeConversation2.rootConversationId,
3358
3501
  juniorConversations.conversationId
3359
3502
  )
3360
3503
  ).innerJoin(
3361
3504
  juniorDestinations,
3362
- eq10(juniorDestinations.id, juniorConversations.destinationId)
3363
- ).where(and9(where, gte2(juniorConversations.lastActivityAt, start))).groupBy(activityDate),
3505
+ eq11(juniorDestinations.id, juniorConversations.destinationId)
3506
+ ).where(and10(where, gte2(juniorConversations.lastActivityAt, start))).groupBy(activityDate),
3364
3507
  getDb().select({
3365
3508
  actorIdentityId: juniorConversations.actorIdentityId,
3366
3509
  email: juniorUsers.primaryEmailNormalized,
@@ -3372,17 +3515,17 @@ async function readLocationDetailFromSql(locationId, options = {}) {
3372
3515
  ...treeAggregateColumns2
3373
3516
  }).from(juniorConversations).innerJoin(
3374
3517
  treeConversation2,
3375
- eq10(
3518
+ eq11(
3376
3519
  treeConversation2.rootConversationId,
3377
3520
  juniorConversations.conversationId
3378
3521
  )
3379
3522
  ).innerJoin(
3380
3523
  juniorDestinations,
3381
- eq10(juniorDestinations.id, juniorConversations.destinationId)
3524
+ eq11(juniorDestinations.id, juniorConversations.destinationId)
3382
3525
  ).leftJoin(
3383
3526
  juniorIdentities,
3384
- eq10(juniorIdentities.id, juniorConversations.actorIdentityId)
3385
- ).leftJoin(juniorUsers, eq10(juniorUsers.id, juniorIdentities.userId)).where(where).groupBy(
3527
+ eq11(juniorIdentities.id, juniorConversations.actorIdentityId)
3528
+ ).leftJoin(juniorUsers, eq11(juniorUsers.id, juniorIdentities.userId)).where(where).groupBy(
3386
3529
  juniorConversations.actorIdentityId,
3387
3530
  juniorUsers.primaryEmailNormalized,
3388
3531
  juniorUsers.displayName,
@@ -3495,10 +3638,10 @@ function createLocationRoutes() {
3495
3638
  import { Hono as Hono3 } from "hono";
3496
3639
 
3497
3640
  // src/api/people/list.query.ts
3498
- import { and as and11, eq as eq12, gte as gte3, sql as sql9 } from "drizzle-orm";
3641
+ import { and as and12, eq as eq13, gte as gte3, sql as sql9 } from "drizzle-orm";
3499
3642
 
3500
3643
  // src/api/people/shared.ts
3501
- import { and as and10, asc as asc4, desc as desc4, eq as eq11, isNull as isNull6, notExists, or as or3, sql as sql8 } from "drizzle-orm";
3644
+ import { and as and11, asc as asc4, desc as desc4, eq as eq12, isNull as isNull6, notExists, or as or4, sql as sql8 } from "drizzle-orm";
3502
3645
  import { alias as alias6 } from "drizzle-orm/pg-core";
3503
3646
  var RECENT_LIMIT2 = 25;
3504
3647
  var ACTIVITY_DAYS2 = 365;
@@ -3518,37 +3661,37 @@ var peopleTreeAggregateColumns = conversationAggregateColumns({
3518
3661
  function peopleTreeMetricsJoin() {
3519
3662
  const rootOwnedByActor = getDb().select({ conversationId: peopleRootConversation.conversationId }).from(peopleRootConversation).innerJoin(
3520
3663
  peopleRootIdentity,
3521
- eq11(peopleRootIdentity.id, peopleRootConversation.actorIdentityId)
3664
+ eq12(peopleRootIdentity.id, peopleRootConversation.actorIdentityId)
3522
3665
  ).where(
3523
- and10(
3524
- eq11(
3666
+ and11(
3667
+ eq12(
3525
3668
  peopleRootConversation.conversationId,
3526
3669
  juniorConversations.rootConversationId
3527
3670
  ),
3528
3671
  isNull6(peopleRootConversation.parentConversationId),
3529
- eq11(
3672
+ eq12(
3530
3673
  peopleRootConversation.rootConversationId,
3531
3674
  peopleRootConversation.conversationId
3532
3675
  ),
3533
- eq11(
3676
+ eq12(
3534
3677
  peopleRootIdentity.emailNormalized,
3535
3678
  juniorUsers.primaryEmailNormalized
3536
3679
  ),
3537
- eq11(peopleRootIdentity.emailVerified, true)
3680
+ eq12(peopleRootIdentity.emailVerified, true)
3538
3681
  )
3539
3682
  );
3540
- return and10(
3541
- eq11(
3683
+ return and11(
3684
+ eq12(
3542
3685
  peopleTreeConversation.rootConversationId,
3543
3686
  juniorConversations.rootConversationId
3544
3687
  ),
3545
- or3(
3546
- eq11(
3688
+ or4(
3689
+ eq12(
3547
3690
  juniorConversations.rootConversationId,
3548
3691
  juniorConversations.conversationId
3549
3692
  ),
3550
- and10(
3551
- eq11(
3693
+ and11(
3694
+ eq12(
3552
3695
  peopleTreeConversation.conversationId,
3553
3696
  juniorConversations.conversationId
3554
3697
  ),
@@ -3598,11 +3741,11 @@ function statsItems2(map) {
3598
3741
  }
3599
3742
  function verifiedActorWhere(email) {
3600
3743
  const normalizedEmail = normalizeEmail(email);
3601
- return and10(
3602
- eq11(juniorIdentities.provider, "slack"),
3603
- eq11(juniorIdentities.emailVerified, true),
3744
+ return and11(
3745
+ eq12(juniorIdentities.provider, "slack"),
3746
+ eq12(juniorIdentities.emailVerified, true),
3604
3747
  sql8`${juniorUsers.primaryEmailNormalized} IS NOT NULL`,
3605
- normalizedEmail ? eq11(juniorUsers.primaryEmailNormalized, normalizedEmail) : void 0
3748
+ normalizedEmail ? eq12(juniorUsers.primaryEmailNormalized, normalizedEmail) : void 0
3606
3749
  );
3607
3750
  }
3608
3751
  async function recentActorRows(email) {
@@ -3625,12 +3768,12 @@ async function recentActorRows(email) {
3625
3768
  usage: juniorConversations.usage
3626
3769
  }).from(juniorConversations).innerJoin(
3627
3770
  juniorIdentities,
3628
- eq11(juniorIdentities.id, juniorConversations.actorIdentityId)
3629
- ).innerJoin(juniorUsers, eq11(juniorUsers.id, juniorIdentities.userId)).leftJoin(
3771
+ eq12(juniorIdentities.id, juniorConversations.actorIdentityId)
3772
+ ).innerJoin(juniorUsers, eq12(juniorUsers.id, juniorIdentities.userId)).leftJoin(
3630
3773
  juniorDestinations,
3631
- eq11(juniorDestinations.id, juniorConversations.destinationId)
3774
+ eq12(juniorDestinations.id, juniorConversations.destinationId)
3632
3775
  ).where(
3633
- and10(verifiedActorWhere(email), isNull6(juniorConversations.archivedAt))
3776
+ and11(verifiedActorWhere(email), isNull6(juniorConversations.archivedAt))
3634
3777
  ).orderBy(
3635
3778
  desc4(juniorConversations.lastActivityAt),
3636
3779
  asc4(juniorConversations.conversationId)
@@ -3674,17 +3817,17 @@ async function readPeopleListFromSql() {
3674
3817
  ...conversationRangeColumns()
3675
3818
  }).from(juniorConversations).innerJoin(
3676
3819
  juniorIdentities,
3677
- eq12(juniorIdentities.id, juniorConversations.actorIdentityId)
3678
- ).innerJoin(juniorUsers, eq12(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, peopleTreeMetricsJoin()).where(verifiedActorWhere()).groupBy(juniorUsers.primaryEmailNormalized, juniorUsers.displayName),
3820
+ eq13(juniorIdentities.id, juniorConversations.actorIdentityId)
3821
+ ).innerJoin(juniorUsers, eq13(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, peopleTreeMetricsJoin()).where(verifiedActorWhere()).groupBy(juniorUsers.primaryEmailNormalized, juniorUsers.displayName),
3679
3822
  getDb().select({
3680
3823
  activePeople: sql9`COUNT(DISTINCT ${juniorUsers.id})::int`,
3681
3824
  conversations: sql9`COUNT(*)::int`,
3682
3825
  date: activityDate
3683
3826
  }).from(juniorConversations).innerJoin(
3684
3827
  juniorIdentities,
3685
- eq12(juniorIdentities.id, juniorConversations.actorIdentityId)
3686
- ).innerJoin(juniorUsers, eq12(juniorUsers.id, juniorIdentities.userId)).where(
3687
- and11(
3828
+ eq13(juniorIdentities.id, juniorConversations.actorIdentityId)
3829
+ ).innerJoin(juniorUsers, eq13(juniorUsers.id, juniorIdentities.userId)).where(
3830
+ and12(
3688
3831
  verifiedActorWhere(),
3689
3832
  gte3(juniorConversations.lastActivityAt, start)
3690
3833
  )
@@ -3727,7 +3870,7 @@ async function readPeopleList() {
3727
3870
  }
3728
3871
 
3729
3872
  // src/api/people/profile.query.ts
3730
- import { and as and12, eq as eq13, gte as gte4, sql as sql10 } from "drizzle-orm";
3873
+ import { and as and13, eq as eq14, gte as gte4, sql as sql10 } from "drizzle-orm";
3731
3874
  function emptyProfile(email, nowMs) {
3732
3875
  const end = new Date(nowMs);
3733
3876
  end.setUTCHours(0, 0, 0, 0);
@@ -3806,15 +3949,15 @@ async function readPeopleProfileFromSql(email, options = {}) {
3806
3949
  ...peopleTreeAggregateColumns
3807
3950
  }).from(juniorConversations).innerJoin(
3808
3951
  juniorIdentities,
3809
- eq13(juniorIdentities.id, juniorConversations.actorIdentityId)
3810
- ).innerJoin(juniorUsers, eq13(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(where).groupBy(juniorUsers.primaryEmailNormalized, juniorUsers.displayName),
3952
+ eq14(juniorIdentities.id, juniorConversations.actorIdentityId)
3953
+ ).innerJoin(juniorUsers, eq14(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(where).groupBy(juniorUsers.primaryEmailNormalized, juniorUsers.displayName),
3811
3954
  getDb().select({
3812
3955
  date: activityDate,
3813
3956
  ...peopleTreeAggregateColumns
3814
3957
  }).from(juniorConversations).innerJoin(
3815
3958
  juniorIdentities,
3816
- eq13(juniorIdentities.id, juniorConversations.actorIdentityId)
3817
- ).innerJoin(juniorUsers, eq13(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(and12(where, gte4(juniorConversations.lastActivityAt, start))).groupBy(activityDate),
3959
+ eq14(juniorIdentities.id, juniorConversations.actorIdentityId)
3960
+ ).innerJoin(juniorUsers, eq14(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(and13(where, gte4(juniorConversations.lastActivityAt, start))).groupBy(activityDate),
3818
3961
  getDb().select({
3819
3962
  channel,
3820
3963
  channelName: juniorConversations.channelName,
@@ -3823,10 +3966,10 @@ async function readPeopleProfileFromSql(email, options = {}) {
3823
3966
  ...peopleTreeAggregateColumns
3824
3967
  }).from(juniorConversations).innerJoin(
3825
3968
  juniorIdentities,
3826
- eq13(juniorIdentities.id, juniorConversations.actorIdentityId)
3827
- ).innerJoin(juniorUsers, eq13(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).leftJoin(
3969
+ eq14(juniorIdentities.id, juniorConversations.actorIdentityId)
3970
+ ).innerJoin(juniorUsers, eq14(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).leftJoin(
3828
3971
  juniorDestinations,
3829
- eq13(juniorDestinations.id, juniorConversations.destinationId)
3972
+ eq14(juniorDestinations.id, juniorConversations.destinationId)
3830
3973
  ).where(where).groupBy(
3831
3974
  channel,
3832
3975
  juniorConversations.channelName,
@@ -3835,8 +3978,8 @@ async function readPeopleProfileFromSql(email, options = {}) {
3835
3978
  ),
3836
3979
  getDb().select({ surface, ...peopleTreeAggregateColumns }).from(juniorConversations).innerJoin(
3837
3980
  juniorIdentities,
3838
- eq13(juniorIdentities.id, juniorConversations.actorIdentityId)
3839
- ).innerJoin(juniorUsers, eq13(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(where).groupBy(surface),
3981
+ eq14(juniorIdentities.id, juniorConversations.actorIdentityId)
3982
+ ).innerJoin(juniorUsers, eq14(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(where).groupBy(surface),
3840
3983
  recentActorRows(normalizedEmail)
3841
3984
  ]);
3842
3985
  const totalsRow = totalsRows[0];
@@ -3914,7 +4057,7 @@ async function readPeopleProfile(email, options = {}) {
3914
4057
  }
3915
4058
 
3916
4059
  // src/api/people/spend.query.ts
3917
- import { and as and13, eq as eq14, gte as gte5, lte as lte2, sql as sql11 } from "drizzle-orm";
4060
+ import { and as and14, eq as eq15, gte as gte5, lte as lte2, sql as sql11 } from "drizzle-orm";
3918
4061
  var SEVEN_DAY_OFFSET = 6;
3919
4062
  var THIRTY_DAY_OFFSET = 29;
3920
4063
  function addUsd2(current, next) {
@@ -3943,9 +4086,9 @@ async function readPersonalSpendFromSql(email, nowMs = Date.now()) {
3943
4086
  date: activityDate
3944
4087
  }).from(juniorConversations).innerJoin(
3945
4088
  juniorIdentities,
3946
- eq14(juniorIdentities.id, juniorConversations.actorIdentityId)
3947
- ).innerJoin(juniorUsers, eq14(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(
3948
- and13(
4089
+ eq15(juniorIdentities.id, juniorConversations.actorIdentityId)
4090
+ ).innerJoin(juniorUsers, eq15(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(
4091
+ and14(
3949
4092
  verifiedActorWhere(normalizedEmail),
3950
4093
  gte5(juniorConversations.lastActivityAt, thirtyDayStart),
3951
4094
  lte2(juniorConversations.lastActivityAt, end)
@@ -4033,7 +4176,7 @@ import { Hono as Hono4 } from "hono";
4033
4176
 
4034
4177
  // src/personal-tokens/store.ts
4035
4178
  import { createHash, randomBytes, randomUUID } from "crypto";
4036
- import { and as and14, desc as desc5, eq as eq15, gt, isNull as isNull7 } from "drizzle-orm";
4179
+ import { and as and15, desc as desc5, eq as eq16, gt, isNull as isNull7 } from "drizzle-orm";
4037
4180
  var TOKEN_PREFIX = "jr_pat_";
4038
4181
  var TOKEN_SUFFIX_LENGTH = 8;
4039
4182
  var DEFAULT_TOKEN_LIFETIME_MS = 90 * 24 * 60 * 60 * 1e3;
@@ -4070,8 +4213,8 @@ async function createPersonalToken(args) {
4070
4213
  }
4071
4214
  async function listPersonalTokens(email, now = /* @__PURE__ */ new Date()) {
4072
4215
  const rows = await getDb().select().from(juniorApiTokens).where(
4073
- and14(
4074
- eq15(juniorApiTokens.ownerEmailNormalized, normalizeEmail2(email)),
4216
+ and15(
4217
+ eq16(juniorApiTokens.ownerEmailNormalized, normalizeEmail2(email)),
4075
4218
  isNull7(juniorApiTokens.revokedAt),
4076
4219
  gt(juniorApiTokens.expiresAt, now)
4077
4220
  )
@@ -4080,9 +4223,9 @@ async function listPersonalTokens(email, now = /* @__PURE__ */ new Date()) {
4080
4223
  }
4081
4224
  async function revokePersonalToken(args) {
4082
4225
  const rows = await getDb().update(juniorApiTokens).set({ revokedAt: args.now ?? /* @__PURE__ */ new Date() }).where(
4083
- and14(
4084
- eq15(juniorApiTokens.id, args.id),
4085
- eq15(juniorApiTokens.ownerEmailNormalized, normalizeEmail2(args.email)),
4226
+ and15(
4227
+ eq16(juniorApiTokens.id, args.id),
4228
+ eq16(juniorApiTokens.ownerEmailNormalized, normalizeEmail2(args.email)),
4086
4229
  isNull7(juniorApiTokens.revokedAt)
4087
4230
  )
4088
4231
  ).returning({ id: juniorApiTokens.id });
@@ -4094,15 +4237,15 @@ async function authenticatePersonalToken(token2, now = /* @__PURE__ */ new Date(
4094
4237
  id: juniorApiTokens.id,
4095
4238
  ownerEmailNormalized: juniorApiTokens.ownerEmailNormalized
4096
4239
  }).from(juniorApiTokens).where(
4097
- and14(
4098
- eq15(juniorApiTokens.tokenHash, hashToken(token2)),
4240
+ and15(
4241
+ eq16(juniorApiTokens.tokenHash, hashToken(token2)),
4099
4242
  isNull7(juniorApiTokens.revokedAt),
4100
4243
  gt(juniorApiTokens.expiresAt, now)
4101
4244
  )
4102
4245
  ).limit(1);
4103
4246
  const match = rows[0];
4104
4247
  if (!match) return void 0;
4105
- await getDb().update(juniorApiTokens).set({ lastUsedAt: now }).where(eq15(juniorApiTokens.id, match.id));
4248
+ await getDb().update(juniorApiTokens).set({ lastUsedAt: now }).where(eq16(juniorApiTokens.id, match.id));
4106
4249
  return match.ownerEmailNormalized;
4107
4250
  }
4108
4251
 
@@ -4359,7 +4502,7 @@ function readDescriptionText(home) {
4359
4502
  }
4360
4503
  }
4361
4504
  async function readSkillReports() {
4362
- const { discoverSkills } = await import("./skills-XJ2LJ2ML.js");
4505
+ const { discoverSkills } = await import("./skills-4GZTZX4V.js");
4363
4506
  const skills = await discoverSkills();
4364
4507
  return skillReportsSchema.parse(
4365
4508
  skills.map((skill) => ({
@@ -4369,7 +4512,7 @@ async function readSkillReports() {
4369
4512
  );
4370
4513
  }
4371
4514
  async function readPlugins() {
4372
- const { pluginCatalogRuntime } = await import("./catalog-runtime-AK5MY63F.js");
4515
+ const { pluginCatalogRuntime } = await import("./catalog-runtime-3SNKYCBG.js");
4373
4516
  return pluginsSchema.parse(
4374
4517
  pluginCatalogRuntime.getProviders().map((plugin) => ({
4375
4518
  configKeys: plugin.manifest.configKeys ?? [],
@@ -4382,7 +4525,7 @@ async function readPlugins() {
4382
4525
  async function readRuntimeInfoReport() {
4383
4526
  const [{ homeDir }, { pluginCatalogRuntime }, plugins, skills] = await Promise.all([
4384
4527
  import("./discovery-GUFTFBTL.js"),
4385
- import("./catalog-runtime-AK5MY63F.js"),
4528
+ import("./catalog-runtime-3SNKYCBG.js"),
4386
4529
  readPlugins(),
4387
4530
  readSkillReports()
4388
4531
  ]);
@@ -4398,7 +4541,7 @@ async function readRuntimeInfoReport() {
4398
4541
  }
4399
4542
  async function readPluginOperationalReportFeed() {
4400
4543
  const nowMs = Date.now();
4401
- const { getPluginOperationalReports } = await import("./agent-hooks-VEHV2QUA.js");
4544
+ const { getPluginOperationalReports } = await import("./agent-hooks-CCAR46PQ.js");
4402
4545
  return pluginOperationalReportFeedSchema.parse({
4403
4546
  source: "plugins",
4404
4547
  generatedAt: new Date(nowMs).toISOString(),