@sentry/junior 0.181.1 → 0.183.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 (107) hide show
  1. package/dist/{agent-hooks-KO56HJ74.js → agent-hooks-SNRBZYAU.js} +11 -11
  2. package/dist/api/code/overview.d.ts +35 -0
  3. package/dist/api/code/routes.d.ts +4 -0
  4. package/dist/api/schema/code.d.ts +75 -0
  5. package/dist/api/schema.d.ts +2 -0
  6. package/dist/api/schema.js +9 -1
  7. package/dist/api.js +347 -149
  8. package/dist/app-adapter.d.ts +85 -0
  9. package/dist/app.d.ts +6 -1
  10. package/dist/app.js +380 -501
  11. package/dist/{catalog-runtime-CJTFLCK3.js → catalog-runtime-3I3JOIIH.js} +4 -4
  12. package/dist/chat/agent-invocations/store.d.ts +4 -2
  13. package/dist/chat/agent-invocations/work.d.ts +1 -3
  14. package/dist/chat/api-turns/adapter-conversations.d.ts +15 -0
  15. package/dist/chat/api-turns/stop.d.ts +12 -0
  16. package/dist/chat/api-turns/work.d.ts +9 -1
  17. package/dist/chat/app/conversation-work.d.ts +1 -1
  18. package/dist/chat/app/factory.d.ts +3 -3
  19. package/dist/chat/app/services.d.ts +3 -3
  20. package/dist/chat/code/publisher.d.ts +3 -0
  21. package/dist/chat/code/store.d.ts +9 -0
  22. package/dist/chat/event-tasks/store.d.ts +10 -0
  23. package/dist/chat/event-tasks/tool-support.d.ts +7 -1
  24. package/dist/chat/event-tasks/types.d.ts +1 -0
  25. package/dist/chat/experimental.d.ts +1 -1
  26. package/dist/chat/ingress/slack-webhook.d.ts +1 -1
  27. package/dist/chat/plugins/agent-hooks.d.ts +5 -0
  28. package/dist/chat/{runtime/slack-runtime.d.ts → providers/slack/runtime.d.ts} +2 -2
  29. package/dist/chat/{runtime/reply-executor.d.ts → providers/slack/turn.d.ts} +10 -9
  30. package/dist/chat/resource-events/catalog.d.ts +11 -1
  31. package/dist/chat/resource-events/store.d.ts +17 -1
  32. package/dist/chat/runtime/turn-execution.d.ts +30 -0
  33. package/dist/chat/services/subscribed-decision.d.ts +2 -1
  34. package/dist/chat/slack/dispatch-turn.d.ts +12 -14
  35. package/dist/chat/task-execution/slack-work.d.ts +1 -1
  36. package/dist/chat/tools/create-event-task.d.ts +3 -0
  37. package/dist/chat/tools/delete-event-task.d.ts +2 -0
  38. package/dist/chat/tools/list-event-tasks.d.ts +2 -0
  39. package/dist/chat/tools/list-resource-event-subscriptions.d.ts +2 -0
  40. package/dist/chat/tools/search-resource-event-types.d.ts +10 -0
  41. package/dist/chat/tools/update-event-task.d.ts +3 -0
  42. package/dist/chat/tools/watch-resource-events.d.ts +3 -0
  43. package/dist/{chunk-DTRCZOHE.js → chunk-24OJZ5OU.js} +6 -6
  44. package/dist/{chunk-Z2UG4FBT.js → chunk-2ADFGSUS.js} +1 -1
  45. package/dist/{chunk-RULGB5NX.js → chunk-2EPYYVJC.js} +9 -9
  46. package/dist/{chunk-VRS6WDK5.js → chunk-2LYHWMR4.js} +1 -1
  47. package/dist/{chunk-XQ56HNH5.js → chunk-35PM4YY5.js} +6 -6
  48. package/dist/{chunk-6TB7JN63.js → chunk-37IQ6DGU.js} +3 -3
  49. package/dist/{chunk-MR36BRPE.js → chunk-3HJ4F4L7.js} +4 -4
  50. package/dist/{chunk-4WYHL4EH.js → chunk-3L7CWDQQ.js} +1 -1
  51. package/dist/{chunk-CJRUBOJI.js → chunk-4WGFWHWP.js} +1 -1
  52. package/dist/{chunk-VHSBLFNT.js → chunk-56XONJPF.js} +1 -1
  53. package/dist/{chunk-ULM7P4EQ.js → chunk-6UXDTPEN.js} +233 -173
  54. package/dist/{chunk-WDNA4LML.js → chunk-AHMWPFIW.js} +188 -11
  55. package/dist/{chunk-YCW6RZGX.js → chunk-AX3UDIMA.js} +3 -3
  56. package/dist/{chunk-HG6HNOTQ.js → chunk-AYW7J6K4.js} +130 -200
  57. package/dist/{chunk-DXK3VTVP.js → chunk-E3OBGRHN.js} +1 -1
  58. package/dist/{chunk-7UF37LNL.js → chunk-EENQGEIP.js} +1 -1
  59. package/dist/{chunk-HRTW7FFX.js → chunk-FJMTMGBC.js} +1 -1
  60. package/dist/{chunk-H6MPFFBE.js → chunk-G2B2XZQW.js} +1 -1
  61. package/dist/{chunk-4GOZBB22.js → chunk-HUK5XIZL.js} +63 -7
  62. package/dist/{chunk-DINF4LMR.js → chunk-IO6KFXYE.js} +160 -97
  63. package/dist/{chunk-KH2SL2HT.js → chunk-KTXOGLNE.js} +2 -2
  64. package/dist/{chunk-S63LNPIV.js → chunk-LMNMMESF.js} +2 -2
  65. package/dist/{chunk-2CZ63QCL.js → chunk-LZBPGX5A.js} +1 -1
  66. package/dist/{chunk-PJ7EGFME.js → chunk-PLZT45VC.js} +5 -5
  67. package/dist/{chunk-ZQQWJMHE.js → chunk-QI5JW5AG.js} +6 -6
  68. package/dist/{chunk-IWRPJ3J5.js → chunk-QZV76CM4.js} +58 -32
  69. package/dist/{chunk-YFJDRORU.js → chunk-R767Y7QV.js} +202 -90
  70. package/dist/{chunk-4OSVTPYQ.js → chunk-SQHFVIMZ.js} +1 -1
  71. package/dist/{chunk-J4ID4ZI6.js → chunk-T5MTGX2E.js} +19 -19
  72. package/dist/{chunk-NRF23QZ4.js → chunk-V64JCZUV.js} +3 -3
  73. package/dist/{chunk-GITIZ6TZ.js → chunk-VOV3SCM3.js} +1 -1
  74. package/dist/{chunk-S5X2VQOD.js → chunk-W46NIB5H.js} +3 -2
  75. package/dist/{chunk-XL3C4NAR.js → chunk-W5JMPEBO.js} +9 -9
  76. package/dist/{chunk-HPFHC7YR.js → chunk-WOKJRLM2.js} +5 -5
  77. package/dist/chunk-WVIA7V3M.js +975 -0
  78. package/dist/{chunk-QA6RE6IB.js → chunk-X52ESOBP.js} +3 -3
  79. package/dist/cli/chat.js +35 -37
  80. package/dist/cli/check.js +5 -5
  81. package/dist/cli/plugins.js +12 -12
  82. package/dist/cli/snapshot-create.js +9 -9
  83. package/dist/cli/upgrade.js +6 -6
  84. package/dist/db/schema/code.d.ts +367 -0
  85. package/dist/db/schema.d.ts +367 -1
  86. package/dist/{db-4PXTD3OH.js → db-K2VMNLHQ.js} +6 -6
  87. package/dist/{experimental-SIJSRDJD.js → experimental-P5FZM4CU.js} +1 -1
  88. package/dist/instrumentation.js +3 -3
  89. package/dist/nitro.js +6 -6
  90. package/dist/{oauth-callback-server-TQWNEVR6.js → oauth-callback-server-DZZMTKSS.js} +26 -26
  91. package/dist/{runner-G5HLQA43.js → runner-IIAKWDXI.js} +18 -18
  92. package/dist/{skills-BNNNRYNT.js → skills-EXIQ7BP5.js} +5 -5
  93. package/dist/spawn-ZR6OOEAN.js +37 -0
  94. package/dist/task-runner-C52HYCVD.js +32 -0
  95. package/dist/{validation-IJSBB6JR.js → validation-XUGIWBJF.js} +5 -5
  96. package/dist/version.js +1 -1
  97. package/dist/{work-5FQI4P2A.js → work-G4RLJ634.js} +18 -18
  98. package/dist/worker-R2JEHK67.js +22 -0
  99. package/migrations/0036_complex_rage.sql +32 -0
  100. package/migrations/meta/0036_snapshot.json +3186 -0
  101. package/migrations/meta/_journal.json +8 -1
  102. package/package.json +6 -5
  103. package/dist/api/acp/route.d.ts +0 -13
  104. package/dist/chunk-CZYNWPWD.js +0 -930
  105. package/dist/spawn-U2RKOFP2.js +0 -37
  106. package/dist/task-runner-CDZJBEXP.js +0 -32
  107. package/dist/worker-KJ362GVB.js +0 -22
package/dist/api.js CHANGED
@@ -8,6 +8,7 @@ import {
8
8
  archiveConversationResponseSchema,
9
9
  cancelConversationPendingMessagesBodySchema,
10
10
  cancelConversationPendingMessagesResponseSchema,
11
+ codeOverviewReportSchema,
11
12
  conversationAttachmentParamsSchema,
12
13
  conversationDetailQuerySchema,
13
14
  conversationDetailReportSchema,
@@ -41,10 +42,9 @@ import {
41
42
  workspaceListSchema,
42
43
  workspaceParamsSchema,
43
44
  workspaceSchema
44
- } from "./chunk-CZYNWPWD.js";
45
+ } from "./chunk-WVIA7V3M.js";
45
46
  import {
46
47
  appendAndEnqueueApiConversationMessage,
47
- authenticatePersonalToken,
48
48
  conversationArchiveTimes,
49
49
  conversationArchivedForEmail,
50
50
  conversationArchivedForUser,
@@ -53,22 +53,19 @@ import {
53
53
  conversationNotArchivedForEmail,
54
54
  conversationNotArchivedForUser,
55
55
  createAndEnqueueApiConversation,
56
- createPersonalToken,
57
56
  createVercelAttachmentStorage,
58
57
  formatSlackConversationRedactedLabel,
59
- listPersonalTokens,
60
58
  readConversationAccessFromSql,
61
59
  readHealthReport,
62
60
  resolveSlackConversationContextFromThreadId,
63
- revokePersonalToken,
64
61
  viewerConversationMembership,
65
62
  webActorFromEmail
66
- } from "./chunk-HG6HNOTQ.js";
63
+ } from "./chunk-AYW7J6K4.js";
67
64
  import {
68
65
  buildSentryConversationUrl,
69
66
  getWebAuthorization
70
- } from "./chunk-CJRUBOJI.js";
71
- import "./chunk-HPFHC7YR.js";
67
+ } from "./chunk-4WGFWHWP.js";
68
+ import "./chunk-WOKJRLM2.js";
72
69
  import {
73
70
  readTaskExecutionByConversationId,
74
71
  readTaskExecutionDays,
@@ -76,9 +73,9 @@ import {
76
73
  readTaskExecutionSummaries,
77
74
  readTaskExecutions,
78
75
  readTaskRuns
79
- } from "./chunk-XL3C4NAR.js";
76
+ } from "./chunk-W5JMPEBO.js";
80
77
  import "./chunk-M3QYTBQ6.js";
81
- import "./chunk-PJ7EGFME.js";
78
+ import "./chunk-PLZT45VC.js";
82
79
  import {
83
80
  healthReportSchema,
84
81
  pluginOperationalReportFeedSchema,
@@ -86,7 +83,7 @@ import {
86
83
  runtimeInfoReportSchema,
87
84
  skillReportsSchema
88
85
  } from "./chunk-UTL3MHPC.js";
89
- import "./chunk-NRF23QZ4.js";
86
+ import "./chunk-V64JCZUV.js";
90
87
  import {
91
88
  deleteEventTask,
92
89
  eventTaskBelongsToUser,
@@ -103,31 +100,31 @@ import {
103
100
  readScheduledTask,
104
101
  readStats,
105
102
  saveScheduledTask
106
- } from "./chunk-YFJDRORU.js";
103
+ } from "./chunk-R767Y7QV.js";
107
104
  import {
108
105
  parseSlackThreadId
109
- } from "./chunk-4OSVTPYQ.js";
106
+ } from "./chunk-SQHFVIMZ.js";
110
107
  import {
111
108
  cancelHumanFacingPendingMessages,
112
109
  getConversation
113
- } from "./chunk-4GOZBB22.js";
114
- import "./chunk-VHSBLFNT.js";
110
+ } from "./chunk-HUK5XIZL.js";
111
+ import "./chunk-56XONJPF.js";
115
112
  import {
116
113
  agentTurnUsageSchema,
117
114
  fallbackShortTitle,
118
115
  hasAgentTurnUsage,
119
116
  renderJuniorNativeConversationEvent
120
- } from "./chunk-DTRCZOHE.js";
117
+ } from "./chunk-24OJZ5OU.js";
121
118
  import {
122
119
  getCachedSnapshot
123
- } from "./chunk-6TB7JN63.js";
120
+ } from "./chunk-37IQ6DGU.js";
124
121
  import "./chunk-PDO5BLNM.js";
125
122
  import {
126
123
  getVercelConversationWorkQueue
127
124
  } from "./chunk-DKIJ2RP5.js";
128
125
  import "./chunk-JAL3CH4G.js";
129
126
  import "./chunk-7H2VZTWN.js";
130
- import "./chunk-HRTW7FFX.js";
127
+ import "./chunk-FJMTMGBC.js";
131
128
  import {
132
129
  SANDBOX_RUNTIME,
133
130
  WorkspaceValidationError,
@@ -147,7 +144,7 @@ import {
147
144
  updateWorkspace,
148
145
  withSlackRetries,
149
146
  workspaceRepoCheckoutPath
150
- } from "./chunk-WDNA4LML.js";
147
+ } from "./chunk-AHMWPFIW.js";
151
148
  import "./chunk-3Y47VMHV.js";
152
149
  import {
153
150
  decodeStoredConversationEvent,
@@ -157,28 +154,31 @@ import {
157
154
  locationFromRow,
158
155
  parseSessionSource,
159
156
  resolveRootConversationId
160
- } from "./chunk-YCW6RZGX.js";
157
+ } from "./chunk-AX3UDIMA.js";
161
158
  import {
162
159
  conversationReadColumns,
160
+ juniorApiTokens,
161
+ juniorCodeChanges,
162
+ juniorCodeRepositories,
163
163
  juniorConversationEvents,
164
164
  juniorConversationParticipants,
165
165
  juniorConversations,
166
166
  juniorIdentities,
167
167
  juniorSchedulerTasks,
168
168
  juniorUsers
169
- } from "./chunk-ULM7P4EQ.js";
169
+ } from "./chunk-6UXDTPEN.js";
170
170
  import {
171
171
  create,
172
172
  hash
173
- } from "./chunk-QA6RE6IB.js";
174
- import "./chunk-H6MPFFBE.js";
173
+ } from "./chunk-X52ESOBP.js";
174
+ import "./chunk-G2B2XZQW.js";
175
175
  import {
176
176
  juniorDestinations
177
177
  } from "./chunk-VFUK3X5B.js";
178
- import "./chunk-S63LNPIV.js";
179
- import "./chunk-Z2UG4FBT.js";
180
- import "./chunk-DXK3VTVP.js";
181
- import "./chunk-7UF37LNL.js";
178
+ import "./chunk-LMNMMESF.js";
179
+ import "./chunk-2ADFGSUS.js";
180
+ import "./chunk-E3OBGRHN.js";
181
+ import "./chunk-EENQGEIP.js";
182
182
  import "./chunk-CEMMLV5L.js";
183
183
  import {
184
184
  parseSlackChannelId,
@@ -190,12 +190,12 @@ import "./chunk-TXKUKMVO.js";
190
190
  import {
191
191
  logException,
192
192
  logWarn
193
- } from "./chunk-2CZ63QCL.js";
193
+ } from "./chunk-LZBPGX5A.js";
194
194
  import "./chunk-PEQXYSSE.js";
195
- import "./chunk-S5X2VQOD.js";
195
+ import "./chunk-W46NIB5H.js";
196
196
 
197
197
  // src/api.ts
198
- import { Hono as Hono8 } from "hono";
198
+ import { Hono as Hono9 } from "hono";
199
199
  import { HTTPException as HTTPException2 } from "hono/http-exception";
200
200
 
201
201
  // src/api/conversations/routes.ts
@@ -2789,19 +2789,19 @@ var slackMailboxMetadataSchema = z4.object({
2789
2789
  function isoFromMs(value) {
2790
2790
  return new Date(value).toISOString();
2791
2791
  }
2792
- function actorIdentityFromApiMetadata(metadata) {
2792
+ function actorIdentityFromApiMetadata(metadata2) {
2793
2793
  return {
2794
- email: metadata.authorEmail.trim().toLowerCase(),
2795
- ...metadata.authorFullName ? { fullName: metadata.authorFullName } : void 0
2794
+ email: metadata2.authorEmail.trim().toLowerCase(),
2795
+ ...metadata2.authorFullName ? { fullName: metadata2.authorFullName } : void 0
2796
2796
  };
2797
2797
  }
2798
- async function actorIdentityFromSlackMetadata(metadata, teamId) {
2799
- if (metadata.message.author.isMe === true) return void 0;
2800
- const slackUserId = metadata.message.author.userId.trim();
2798
+ async function actorIdentityFromSlackMetadata(metadata2, teamId) {
2799
+ if (metadata2.message.author.isMe === true) return void 0;
2800
+ const slackUserId = metadata2.message.author.userId.trim();
2801
2801
  if (!slackUserId) return void 0;
2802
2802
  const profile = teamId ? await lookupSlackUser(teamId, slackUserId) : null;
2803
- const slackUserName = profile?.userName?.trim() || metadata.message.author.userName?.trim();
2804
- const fullName = profile?.fullName?.trim() || metadata.message.author.fullName?.trim();
2803
+ const slackUserName = profile?.userName?.trim() || metadata2.message.author.userName?.trim();
2804
+ const fullName = profile?.fullName?.trim() || metadata2.message.author.fullName?.trim();
2805
2805
  const email = profile?.email?.trim().toLowerCase();
2806
2806
  return {
2807
2807
  slackUserId,
@@ -2812,32 +2812,32 @@ async function actorIdentityFromSlackMetadata(metadata, teamId) {
2812
2812
  }
2813
2813
  async function projectPendingMessage(message2, canExposePayload) {
2814
2814
  if (message2.source === "web") {
2815
- const metadata = apiTurnMailboxMetadataSchema.safeParse(
2815
+ const metadata2 = apiTurnMailboxMetadataSchema.safeParse(
2816
2816
  message2.input.metadata
2817
2817
  );
2818
- if (!metadata.success) return void 0;
2818
+ if (!metadata2.success) return void 0;
2819
2819
  const text = message2.input.text.trim();
2820
2820
  if (!text) return void 0;
2821
2821
  return {
2822
2822
  createdAt: isoFromMs(message2.createdAtMs),
2823
2823
  delivery: message2.delivery,
2824
2824
  inboundMessageId: message2.inboundMessageId,
2825
- messageId: metadata.data.messageId,
2825
+ messageId: metadata2.data.messageId,
2826
2826
  receivedAt: isoFromMs(message2.receivedAtMs),
2827
2827
  role: "user",
2828
2828
  source: "web",
2829
2829
  ...canExposePayload ? {
2830
- actorIdentity: actorIdentityFromApiMetadata(metadata.data),
2830
+ actorIdentity: actorIdentityFromApiMetadata(metadata2.data),
2831
2831
  text
2832
2832
  } : { redacted: true }
2833
2833
  };
2834
2834
  }
2835
2835
  if (message2.source === "slack") {
2836
- const metadata = slackMailboxMetadataSchema.safeParse(
2836
+ const metadata2 = slackMailboxMetadataSchema.safeParse(
2837
2837
  message2.input.metadata
2838
2838
  );
2839
- if (!metadata.success) return void 0;
2840
- if (metadata.data.message.author.isMe === true) return void 0;
2839
+ if (!metadata2.success) return void 0;
2840
+ if (metadata2.data.message.author.isMe === true) return void 0;
2841
2841
  const text = message2.input.text.trim();
2842
2842
  if (!text) return void 0;
2843
2843
  if (!canExposePayload) {
@@ -2845,7 +2845,7 @@ async function projectPendingMessage(message2, canExposePayload) {
2845
2845
  createdAt: isoFromMs(message2.createdAtMs),
2846
2846
  delivery: message2.delivery,
2847
2847
  inboundMessageId: message2.inboundMessageId,
2848
- messageId: metadata.data.message.id,
2848
+ messageId: metadata2.data.message.id,
2849
2849
  receivedAt: isoFromMs(message2.receivedAtMs),
2850
2850
  redacted: true,
2851
2851
  role: "user",
@@ -2853,14 +2853,14 @@ async function projectPendingMessage(message2, canExposePayload) {
2853
2853
  };
2854
2854
  }
2855
2855
  const actorIdentity = await actorIdentityFromSlackMetadata(
2856
- metadata.data,
2856
+ metadata2.data,
2857
2857
  message2.destination?.platform === "slack" ? message2.destination.teamId : void 0
2858
2858
  );
2859
2859
  return {
2860
2860
  createdAt: isoFromMs(message2.createdAtMs),
2861
2861
  delivery: message2.delivery,
2862
2862
  inboundMessageId: message2.inboundMessageId,
2863
- messageId: metadata.data.message.id,
2863
+ messageId: metadata2.data.message.id,
2864
2864
  receivedAt: isoFromMs(message2.receivedAtMs),
2865
2865
  role: "user",
2866
2866
  source: "slack",
@@ -3492,11 +3492,131 @@ function createConversationRoutes(options) {
3492
3492
  return app;
3493
3493
  }
3494
3494
 
3495
- // src/api/locations/routes.ts
3495
+ // src/api/code/routes.ts
3496
3496
  import { Hono as Hono2 } from "hono";
3497
3497
 
3498
+ // src/api/code/overview.ts
3499
+ import { desc as desc4, eq as eq11, gte as gte2, or as or5, sql as sql11 } from "drizzle-orm";
3500
+ import { z as z5 } from "zod";
3501
+ var DAY_MS = 24 * 60 * 60 * 1e3;
3502
+ var WINDOW_DAYS2 = 30;
3503
+ var summaryRowSchema = z5.object({
3504
+ closed: z5.number().int().nonnegative(),
3505
+ created: z5.number().int().nonnegative(),
3506
+ merged: z5.number().int().nonnegative(),
3507
+ open: z5.number().int().nonnegative()
3508
+ }).strict();
3509
+ var repositoryRowSchema = summaryRowSchema.extend({
3510
+ id: z5.string().min(1),
3511
+ name: z5.string().min(1),
3512
+ provider: z5.string().min(1),
3513
+ url: z5.string().nullable()
3514
+ }).strict();
3515
+ function queryRows(result) {
3516
+ if (typeof result !== "object" || result === null || !("rows" in result) || !Array.isArray(result.rows)) {
3517
+ throw new TypeError("Code overview query did not return rows");
3518
+ }
3519
+ return result.rows;
3520
+ }
3521
+ async function readCodeOverview(nowMs = Date.now()) {
3522
+ const db = getDb();
3523
+ const windowEnd = new Date(nowMs);
3524
+ const windowStart = new Date(nowMs - WINDOW_DAYS2 * DAY_MS);
3525
+ const changes = juniorCodeChanges;
3526
+ const repositories = juniorCodeRepositories;
3527
+ const [summaryResult, repositoryResult, recentChanges] = await Promise.all([
3528
+ db.execute(sql11`
3529
+ SELECT
3530
+ count(*) FILTER (WHERE ${changes.openedAt} >= ${windowStart})::integer AS "created",
3531
+ count(*) FILTER (WHERE ${changes.mergedAt} >= ${windowStart})::integer AS "merged",
3532
+ count(*) FILTER (
3533
+ WHERE ${changes.state} = 'closed' AND ${changes.closedAt} >= ${windowStart}
3534
+ )::integer AS "closed",
3535
+ count(*) FILTER (WHERE ${changes.state} = 'open')::integer AS "open"
3536
+ FROM ${changes}
3537
+ `),
3538
+ db.execute(sql11`
3539
+ SELECT
3540
+ ${repositories.id} AS "id",
3541
+ ${repositories.name} AS "name",
3542
+ ${repositories.provider} AS "provider",
3543
+ ${repositories.url} AS "url",
3544
+ count(${changes.id}) FILTER (WHERE ${changes.openedAt} >= ${windowStart})::integer AS "created",
3545
+ count(${changes.id}) FILTER (WHERE ${changes.mergedAt} >= ${windowStart})::integer AS "merged",
3546
+ count(${changes.id}) FILTER (
3547
+ WHERE ${changes.state} = 'closed' AND ${changes.closedAt} >= ${windowStart}
3548
+ )::integer AS "closed",
3549
+ count(${changes.id}) FILTER (WHERE ${changes.state} = 'open')::integer AS "open"
3550
+ FROM ${repositories}
3551
+ LEFT JOIN ${changes} ON ${changes.repositoryId} = ${repositories.id}
3552
+ WHERE ${changes.openedAt} >= ${windowStart}
3553
+ OR ${changes.mergedAt} >= ${windowStart}
3554
+ OR ${changes.closedAt} >= ${windowStart}
3555
+ OR ${changes.state} = 'open'
3556
+ GROUP BY ${repositories.id}
3557
+ ORDER BY "merged" DESC, "created" DESC, ${repositories.name} ASC
3558
+ LIMIT 25
3559
+ `),
3560
+ db.select({
3561
+ closedAt: changes.closedAt,
3562
+ id: changes.id,
3563
+ mergedAt: changes.mergedAt,
3564
+ number: changes.number,
3565
+ openedAt: changes.openedAt,
3566
+ provider: changes.provider,
3567
+ repository: repositories.name,
3568
+ state: changes.state,
3569
+ title: changes.title,
3570
+ url: changes.url
3571
+ }).from(changes).innerJoin(repositories, eq11(changes.repositoryId, repositories.id)).where(
3572
+ or5(
3573
+ gte2(changes.openedAt, windowStart),
3574
+ gte2(changes.mergedAt, windowStart),
3575
+ gte2(changes.closedAt, windowStart),
3576
+ eq11(changes.state, "open")
3577
+ )
3578
+ ).orderBy(desc4(changes.updatedAt)).limit(25)
3579
+ ]);
3580
+ const summary = summaryRowSchema.parse(queryRows(summaryResult)[0]);
3581
+ const completed = summary.merged + summary.closed;
3582
+ return codeOverviewReportSchema.parse({
3583
+ changes: recentChanges.map((change) => ({
3584
+ ...change,
3585
+ closedAt: change.closedAt?.toISOString(),
3586
+ mergedAt: change.mergedAt?.toISOString(),
3587
+ openedAt: change.openedAt.toISOString(),
3588
+ title: change.title ?? void 0,
3589
+ url: change.url ?? void 0
3590
+ })),
3591
+ generatedAt: windowEnd.toISOString(),
3592
+ repositories: z5.array(repositoryRowSchema).parse(queryRows(repositoryResult)).map((repository) => ({
3593
+ ...repository,
3594
+ url: repository.url ?? void 0
3595
+ })),
3596
+ summary: {
3597
+ ...summary,
3598
+ mergeRate: completed > 0 ? summary.merged / completed : void 0
3599
+ },
3600
+ windowEnd: windowEnd.toISOString(),
3601
+ windowStart: windowStart.toISOString()
3602
+ });
3603
+ }
3604
+
3605
+ // src/api/code/routes.ts
3606
+ function createCodeRoutes() {
3607
+ const app = new Hono2();
3608
+ app.get(
3609
+ "/",
3610
+ async () => jsonResponse(codeOverviewReportSchema, await readCodeOverview())
3611
+ );
3612
+ return app;
3613
+ }
3614
+
3615
+ // src/api/locations/routes.ts
3616
+ import { Hono as Hono3 } from "hono";
3617
+
3498
3618
  // src/api/locations/query.ts
3499
- import { and as and11, asc as asc3, desc as desc4, eq as eq11, gte as gte2, isNull as isNull5, sql as sql11 } from "drizzle-orm";
3619
+ import { and as and11, asc as asc3, desc as desc5, eq as eq12, gte as gte3, isNull as isNull5, sql as sql12 } from "drizzle-orm";
3500
3620
  import { alias as alias4 } from "drizzle-orm/pg-core";
3501
3621
 
3502
3622
  // src/api/conversations/reporting.ts
@@ -3606,8 +3726,8 @@ function topLevelWhere() {
3606
3726
  function publicLocationWhere(destinationId) {
3607
3727
  return and11(
3608
3728
  topLevelWhere(),
3609
- eq11(juniorDestinations.id, destinationId),
3610
- eq11(juniorDestinations.visibility, "public")
3729
+ eq12(juniorDestinations.id, destinationId),
3730
+ eq12(juniorDestinations.visibility, "public")
3611
3731
  );
3612
3732
  }
3613
3733
  function locationColumns() {
@@ -3658,28 +3778,28 @@ async function directoryRows(db) {
3658
3778
  ...conversationRangeColumns()
3659
3779
  }).from(juniorConversations).innerJoin(
3660
3780
  treeConversation2,
3661
- eq11(
3781
+ eq12(
3662
3782
  treeConversation2.rootConversationId,
3663
3783
  juniorConversations.conversationId
3664
3784
  )
3665
3785
  ).leftJoin(
3666
3786
  juniorDestinations,
3667
- eq11(juniorDestinations.id, juniorConversations.destinationId)
3787
+ eq12(juniorDestinations.id, juniorConversations.destinationId)
3668
3788
  ).where(topLevelWhere()).groupBy(...locationGroupBy());
3669
3789
  }
3670
3790
  async function directoryActivityRows(db, start) {
3671
- const date = sql11`TO_CHAR(
3791
+ const date = sql12`TO_CHAR(
3672
3792
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
3673
3793
  'YYYY-MM-DD'
3674
3794
  )`;
3675
3795
  return db.select({
3676
- conversations: sql11`COUNT(*)::integer`,
3796
+ conversations: sql12`COUNT(*)::integer`,
3677
3797
  date,
3678
3798
  visibility: juniorDestinations.visibility
3679
3799
  }).from(juniorConversations).leftJoin(
3680
3800
  juniorDestinations,
3681
- eq11(juniorDestinations.id, juniorConversations.destinationId)
3682
- ).where(and11(topLevelWhere(), gte2(juniorConversations.lastActivityAt, start))).groupBy(date, juniorDestinations.visibility);
3801
+ eq12(juniorDestinations.id, juniorConversations.destinationId)
3802
+ ).where(and11(topLevelWhere(), gte3(juniorConversations.lastActivityAt, start))).groupBy(date, juniorDestinations.visibility);
3683
3803
  }
3684
3804
  function directoryActivityDays(rows, nowMs) {
3685
3805
  const days = /* @__PURE__ */ new Map();
@@ -3752,7 +3872,7 @@ async function recentLocationRows(db, locationId) {
3752
3872
  createdAt: juniorConversations.createdAt,
3753
3873
  destinationId: juniorDestinations.id,
3754
3874
  durationMs: juniorConversations.durationMs,
3755
- email: sql11`COALESCE(
3875
+ email: sql12`COALESCE(
3756
3876
  ${juniorUsers.primaryEmailNormalized},
3757
3877
  ${juniorIdentities.email}
3758
3878
  )`,
@@ -3761,7 +3881,7 @@ async function recentLocationRows(db, locationId) {
3761
3881
  fullName: juniorUsers.displayName,
3762
3882
  handle: juniorIdentities.handle,
3763
3883
  lastActivityAt: juniorConversations.lastActivityAt,
3764
- providerSubjectId: sql11`CASE
3884
+ providerSubjectId: sql12`CASE
3765
3885
  WHEN ${juniorIdentities.provider} = 'slack'
3766
3886
  THEN ${juniorIdentities.providerSubjectId}
3767
3887
  ELSE NULL
@@ -3772,12 +3892,12 @@ async function recentLocationRows(db, locationId) {
3772
3892
  usage: juniorConversations.usage
3773
3893
  }).from(juniorConversations).innerJoin(
3774
3894
  juniorDestinations,
3775
- eq11(juniorDestinations.id, juniorConversations.destinationId)
3895
+ eq12(juniorDestinations.id, juniorConversations.destinationId)
3776
3896
  ).leftJoin(
3777
3897
  juniorIdentities,
3778
- eq11(juniorIdentities.id, juniorConversations.actorIdentityId)
3779
- ).leftJoin(juniorUsers, eq11(juniorUsers.id, juniorIdentities.userId)).where(publicLocationWhere(locationId)).orderBy(
3780
- desc4(juniorConversations.lastActivityAt),
3898
+ eq12(juniorIdentities.id, juniorConversations.actorIdentityId)
3899
+ ).leftJoin(juniorUsers, eq12(juniorUsers.id, juniorIdentities.userId)).where(publicLocationWhere(locationId)).orderBy(
3900
+ desc5(juniorConversations.lastActivityAt),
3781
3901
  asc3(juniorConversations.conversationId)
3782
3902
  ).limit(RECENT_LIMIT);
3783
3903
  }
@@ -3788,7 +3908,7 @@ async function readLocationDetailFromSql(locationId, options = {}) {
3788
3908
  const start = new Date(end);
3789
3909
  start.setUTCDate(start.getUTCDate() - (ACTIVITY_DAYS - 1));
3790
3910
  const where = publicLocationWhere(locationId);
3791
- const activityDate = sql11`TO_CHAR(
3911
+ const activityDate = sql12`TO_CHAR(
3792
3912
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
3793
3913
  'YYYY-MM-DD'
3794
3914
  )`;
@@ -3799,27 +3919,27 @@ async function readLocationDetailFromSql(locationId, options = {}) {
3799
3919
  ...conversationRangeColumns()
3800
3920
  }).from(juniorConversations).innerJoin(
3801
3921
  treeConversation2,
3802
- eq11(
3922
+ eq12(
3803
3923
  treeConversation2.rootConversationId,
3804
3924
  juniorConversations.conversationId
3805
3925
  )
3806
3926
  ).innerJoin(
3807
3927
  juniorDestinations,
3808
- eq11(juniorDestinations.id, juniorConversations.destinationId)
3928
+ eq12(juniorDestinations.id, juniorConversations.destinationId)
3809
3929
  ).where(where).groupBy(...locationGroupBy()),
3810
3930
  getDb().select({
3811
3931
  date: activityDate,
3812
3932
  ...treeAggregateColumns2
3813
3933
  }).from(juniorConversations).innerJoin(
3814
3934
  treeConversation2,
3815
- eq11(
3935
+ eq12(
3816
3936
  treeConversation2.rootConversationId,
3817
3937
  juniorConversations.conversationId
3818
3938
  )
3819
3939
  ).innerJoin(
3820
3940
  juniorDestinations,
3821
- eq11(juniorDestinations.id, juniorConversations.destinationId)
3822
- ).where(and11(where, gte2(juniorConversations.lastActivityAt, start))).groupBy(activityDate),
3941
+ eq12(juniorDestinations.id, juniorConversations.destinationId)
3942
+ ).where(and11(where, gte3(juniorConversations.lastActivityAt, start))).groupBy(activityDate),
3823
3943
  getDb().select({
3824
3944
  actorIdentityId: juniorConversations.actorIdentityId,
3825
3945
  email: juniorUsers.primaryEmailNormalized,
@@ -3831,17 +3951,17 @@ async function readLocationDetailFromSql(locationId, options = {}) {
3831
3951
  ...treeAggregateColumns2
3832
3952
  }).from(juniorConversations).innerJoin(
3833
3953
  treeConversation2,
3834
- eq11(
3954
+ eq12(
3835
3955
  treeConversation2.rootConversationId,
3836
3956
  juniorConversations.conversationId
3837
3957
  )
3838
3958
  ).innerJoin(
3839
3959
  juniorDestinations,
3840
- eq11(juniorDestinations.id, juniorConversations.destinationId)
3960
+ eq12(juniorDestinations.id, juniorConversations.destinationId)
3841
3961
  ).leftJoin(
3842
3962
  juniorIdentities,
3843
- eq11(juniorIdentities.id, juniorConversations.actorIdentityId)
3844
- ).leftJoin(juniorUsers, eq11(juniorUsers.id, juniorIdentities.userId)).where(where).groupBy(
3963
+ eq12(juniorIdentities.id, juniorConversations.actorIdentityId)
3964
+ ).leftJoin(juniorUsers, eq12(juniorUsers.id, juniorIdentities.userId)).where(where).groupBy(
3845
3965
  juniorConversations.actorIdentityId,
3846
3966
  juniorUsers.primaryEmailNormalized,
3847
3967
  juniorUsers.displayName,
@@ -3924,7 +4044,7 @@ async function readLocationDirectory() {
3924
4044
 
3925
4045
  // src/api/locations/routes.ts
3926
4046
  function createLocationRoutes() {
3927
- const app = new Hono2();
4047
+ const app = new Hono3();
3928
4048
  app.get(
3929
4049
  "/",
3930
4050
  async () => jsonResponse(locationDirectoryReportSchema, await readLocationDirectory())
@@ -3951,13 +4071,13 @@ function createLocationRoutes() {
3951
4071
  }
3952
4072
 
3953
4073
  // src/api/people/routes.ts
3954
- import { Hono as Hono3 } from "hono";
4074
+ import { Hono as Hono4 } from "hono";
3955
4075
 
3956
4076
  // src/api/people/list.query.ts
3957
- import { and as and13, eq as eq13, gte as gte3, sql as sql13 } from "drizzle-orm";
4077
+ import { and as and13, eq as eq14, gte as gte4, sql as sql14 } from "drizzle-orm";
3958
4078
 
3959
4079
  // src/api/people/shared.ts
3960
- import { and as and12, asc as asc4, desc as desc5, eq as eq12, isNull as isNull6, notExists, or as or5, sql as sql12 } from "drizzle-orm";
4080
+ import { and as and12, asc as asc4, desc as desc6, eq as eq13, isNull as isNull6, notExists, or as or6, sql as sql13 } from "drizzle-orm";
3961
4081
  import { alias as alias5 } from "drizzle-orm/pg-core";
3962
4082
  var RECENT_LIMIT2 = 25;
3963
4083
  var ACTIVITY_DAYS2 = 365;
@@ -3977,37 +4097,37 @@ var peopleTreeAggregateColumns = conversationAggregateColumns({
3977
4097
  function peopleTreeMetricsJoin() {
3978
4098
  const rootOwnedByActor = getDb().select({ conversationId: peopleRootConversation.conversationId }).from(peopleRootConversation).innerJoin(
3979
4099
  peopleRootIdentity,
3980
- eq12(peopleRootIdentity.id, peopleRootConversation.actorIdentityId)
4100
+ eq13(peopleRootIdentity.id, peopleRootConversation.actorIdentityId)
3981
4101
  ).where(
3982
4102
  and12(
3983
- eq12(
4103
+ eq13(
3984
4104
  peopleRootConversation.conversationId,
3985
4105
  juniorConversations.rootConversationId
3986
4106
  ),
3987
4107
  isNull6(peopleRootConversation.parentConversationId),
3988
- eq12(
4108
+ eq13(
3989
4109
  peopleRootConversation.rootConversationId,
3990
4110
  peopleRootConversation.conversationId
3991
4111
  ),
3992
- eq12(
4112
+ eq13(
3993
4113
  peopleRootIdentity.emailNormalized,
3994
4114
  juniorUsers.primaryEmailNormalized
3995
4115
  ),
3996
- eq12(peopleRootIdentity.emailVerified, true)
4116
+ eq13(peopleRootIdentity.emailVerified, true)
3997
4117
  )
3998
4118
  );
3999
4119
  return and12(
4000
- eq12(
4120
+ eq13(
4001
4121
  peopleTreeConversation.rootConversationId,
4002
4122
  juniorConversations.rootConversationId
4003
4123
  ),
4004
- or5(
4005
- eq12(
4124
+ or6(
4125
+ eq13(
4006
4126
  juniorConversations.rootConversationId,
4007
4127
  juniorConversations.conversationId
4008
4128
  ),
4009
4129
  and12(
4010
- eq12(
4130
+ eq13(
4011
4131
  peopleTreeConversation.conversationId,
4012
4132
  juniorConversations.conversationId
4013
4133
  ),
@@ -4058,10 +4178,10 @@ function statsItems2(map) {
4058
4178
  function verifiedActorWhere(email) {
4059
4179
  const normalizedEmail = normalizeEmail(email);
4060
4180
  return and12(
4061
- eq12(juniorIdentities.provider, "slack"),
4062
- eq12(juniorIdentities.emailVerified, true),
4063
- sql12`${juniorUsers.primaryEmailNormalized} IS NOT NULL`,
4064
- normalizedEmail ? eq12(juniorUsers.primaryEmailNormalized, normalizedEmail) : void 0
4181
+ eq13(juniorIdentities.provider, "slack"),
4182
+ eq13(juniorIdentities.emailVerified, true),
4183
+ sql13`${juniorUsers.primaryEmailNormalized} IS NOT NULL`,
4184
+ normalizedEmail ? eq13(juniorUsers.primaryEmailNormalized, normalizedEmail) : void 0
4065
4185
  );
4066
4186
  }
4067
4187
  async function recentActorRows(email) {
@@ -4084,12 +4204,12 @@ async function recentActorRows(email) {
4084
4204
  usage: juniorConversations.usage
4085
4205
  }).from(juniorConversations).innerJoin(
4086
4206
  juniorIdentities,
4087
- eq12(juniorIdentities.id, juniorConversations.actorIdentityId)
4088
- ).innerJoin(juniorUsers, eq12(juniorUsers.id, juniorIdentities.userId)).leftJoin(
4207
+ eq13(juniorIdentities.id, juniorConversations.actorIdentityId)
4208
+ ).innerJoin(juniorUsers, eq13(juniorUsers.id, juniorIdentities.userId)).leftJoin(
4089
4209
  juniorDestinations,
4090
- eq12(juniorDestinations.id, juniorConversations.destinationId)
4210
+ eq13(juniorDestinations.id, juniorConversations.destinationId)
4091
4211
  ).where(verifiedActorWhere(email)).orderBy(
4092
- desc5(juniorConversations.lastActivityAt),
4212
+ desc6(juniorConversations.lastActivityAt),
4093
4213
  asc4(juniorConversations.conversationId)
4094
4214
  ).limit(RECENT_LIMIT2);
4095
4215
  }
@@ -4116,7 +4236,7 @@ function directoryActivityDays2(rows, nowMs) {
4116
4236
  async function readPeopleListFromSql() {
4117
4237
  const nowMs = Date.now();
4118
4238
  const { end, start } = activityWindow(nowMs);
4119
- const activityDate = sql13`TO_CHAR(
4239
+ const activityDate = sql14`TO_CHAR(
4120
4240
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
4121
4241
  'YYYY-MM-DD'
4122
4242
  )`;
@@ -4124,26 +4244,26 @@ async function readPeopleListFromSql() {
4124
4244
  getDb().select({
4125
4245
  email: juniorUsers.primaryEmailNormalized,
4126
4246
  fullName: juniorUsers.displayName,
4127
- slackUserId: sql13`MAX(${juniorIdentities.providerSubjectId})`,
4128
- slackUserName: sql13`MAX(${juniorIdentities.handle})`,
4247
+ slackUserId: sql14`MAX(${juniorIdentities.providerSubjectId})`,
4248
+ slackUserName: sql14`MAX(${juniorIdentities.handle})`,
4129
4249
  activeDays: conversationActiveDaysColumn(),
4130
4250
  ...peopleTreeAggregateColumns,
4131
4251
  ...conversationRangeColumns()
4132
4252
  }).from(juniorConversations).innerJoin(
4133
4253
  juniorIdentities,
4134
- eq13(juniorIdentities.id, juniorConversations.actorIdentityId)
4135
- ).innerJoin(juniorUsers, eq13(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, peopleTreeMetricsJoin()).where(verifiedActorWhere()).groupBy(juniorUsers.primaryEmailNormalized, juniorUsers.displayName),
4254
+ eq14(juniorIdentities.id, juniorConversations.actorIdentityId)
4255
+ ).innerJoin(juniorUsers, eq14(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, peopleTreeMetricsJoin()).where(verifiedActorWhere()).groupBy(juniorUsers.primaryEmailNormalized, juniorUsers.displayName),
4136
4256
  getDb().select({
4137
- activePeople: sql13`COUNT(DISTINCT ${juniorUsers.id})::int`,
4138
- conversations: sql13`COUNT(*)::int`,
4257
+ activePeople: sql14`COUNT(DISTINCT ${juniorUsers.id})::int`,
4258
+ conversations: sql14`COUNT(*)::int`,
4139
4259
  date: activityDate
4140
4260
  }).from(juniorConversations).innerJoin(
4141
4261
  juniorIdentities,
4142
- eq13(juniorIdentities.id, juniorConversations.actorIdentityId)
4143
- ).innerJoin(juniorUsers, eq13(juniorUsers.id, juniorIdentities.userId)).where(
4262
+ eq14(juniorIdentities.id, juniorConversations.actorIdentityId)
4263
+ ).innerJoin(juniorUsers, eq14(juniorUsers.id, juniorIdentities.userId)).where(
4144
4264
  and13(
4145
4265
  verifiedActorWhere(),
4146
- gte3(juniorConversations.lastActivityAt, start)
4266
+ gte4(juniorConversations.lastActivityAt, start)
4147
4267
  )
4148
4268
  ).groupBy(activityDate)
4149
4269
  ]);
@@ -4194,7 +4314,7 @@ async function readPeoplePluginReports(args) {
4194
4314
  source: "plugins"
4195
4315
  });
4196
4316
  }
4197
- const { getPluginProfileReports } = await import("./agent-hooks-KO56HJ74.js");
4317
+ const { getPluginProfileReports } = await import("./agent-hooks-SNRBZYAU.js");
4198
4318
  return pluginOperationalReportFeedSchema.parse({
4199
4319
  generatedAt: new Date(nowMs).toISOString(),
4200
4320
  reports: await getPluginProfileReports({
@@ -4207,7 +4327,7 @@ async function readPeoplePluginReports(args) {
4207
4327
  }
4208
4328
 
4209
4329
  // src/api/people/profile.query.ts
4210
- import { and as and14, eq as eq14, gte as gte4, sql as sql14 } from "drizzle-orm";
4330
+ import { and as and14, eq as eq15, gte as gte5, sql as sql15 } from "drizzle-orm";
4211
4331
  function emptyProfile(email, nowMs) {
4212
4332
  const end = new Date(nowMs);
4213
4333
  end.setUTCHours(0, 0, 0, 0);
@@ -4242,7 +4362,7 @@ function addAggregate2(map, label, row) {
4242
4362
  map.set(label, item);
4243
4363
  }
4244
4364
  function surfaceExpression() {
4245
- return sql14`CASE
4365
+ return sql15`CASE
4246
4366
  WHEN ${juniorConversations.source} IN ('api', 'scheduler', 'slack')
4247
4367
  THEN ${juniorConversations.source}
4248
4368
  WHEN ${juniorConversations.conversationId} LIKE 'slack:%' THEN 'slack'
@@ -4271,30 +4391,30 @@ async function readPeopleProfileFromSql(email, options = {}) {
4271
4391
  const where = verifiedActorWhere(normalizedEmail);
4272
4392
  const metricsJoin = peopleTreeMetricsJoin();
4273
4393
  const surface = surfaceExpression();
4274
- const activityDate = sql14`TO_CHAR(
4394
+ const activityDate = sql15`TO_CHAR(
4275
4395
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
4276
4396
  'YYYY-MM-DD'
4277
4397
  )`;
4278
- const channel = sql14`SPLIT_PART(${juniorConversations.conversationId}, ':', 2)`;
4398
+ const channel = sql15`SPLIT_PART(${juniorConversations.conversationId}, ':', 2)`;
4279
4399
  const [totalsRows, dayRows, locationRows, surfaceRows, recentRows] = await Promise.all([
4280
4400
  getDb().select({
4281
4401
  email: juniorUsers.primaryEmailNormalized,
4282
4402
  fullName: juniorUsers.displayName,
4283
- slackUserId: sql14`MAX(${juniorIdentities.providerSubjectId})`,
4284
- slackUserName: sql14`MAX(${juniorIdentities.handle})`,
4403
+ slackUserId: sql15`MAX(${juniorIdentities.providerSubjectId})`,
4404
+ slackUserName: sql15`MAX(${juniorIdentities.handle})`,
4285
4405
  activeDays: conversationActiveDaysColumn(),
4286
4406
  ...peopleTreeAggregateColumns
4287
4407
  }).from(juniorConversations).innerJoin(
4288
4408
  juniorIdentities,
4289
- eq14(juniorIdentities.id, juniorConversations.actorIdentityId)
4290
- ).innerJoin(juniorUsers, eq14(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(where).groupBy(juniorUsers.primaryEmailNormalized, juniorUsers.displayName),
4409
+ eq15(juniorIdentities.id, juniorConversations.actorIdentityId)
4410
+ ).innerJoin(juniorUsers, eq15(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(where).groupBy(juniorUsers.primaryEmailNormalized, juniorUsers.displayName),
4291
4411
  getDb().select({
4292
4412
  date: activityDate,
4293
4413
  ...peopleTreeAggregateColumns
4294
4414
  }).from(juniorConversations).innerJoin(
4295
4415
  juniorIdentities,
4296
- eq14(juniorIdentities.id, juniorConversations.actorIdentityId)
4297
- ).innerJoin(juniorUsers, eq14(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(and14(where, gte4(juniorConversations.lastActivityAt, start))).groupBy(activityDate),
4416
+ eq15(juniorIdentities.id, juniorConversations.actorIdentityId)
4417
+ ).innerJoin(juniorUsers, eq15(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(and14(where, gte5(juniorConversations.lastActivityAt, start))).groupBy(activityDate),
4298
4418
  getDb().select({
4299
4419
  channel,
4300
4420
  channelName: juniorConversations.channelName,
@@ -4303,10 +4423,10 @@ async function readPeopleProfileFromSql(email, options = {}) {
4303
4423
  ...peopleTreeAggregateColumns
4304
4424
  }).from(juniorConversations).innerJoin(
4305
4425
  juniorIdentities,
4306
- eq14(juniorIdentities.id, juniorConversations.actorIdentityId)
4307
- ).innerJoin(juniorUsers, eq14(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).leftJoin(
4426
+ eq15(juniorIdentities.id, juniorConversations.actorIdentityId)
4427
+ ).innerJoin(juniorUsers, eq15(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).leftJoin(
4308
4428
  juniorDestinations,
4309
- eq14(juniorDestinations.id, juniorConversations.destinationId)
4429
+ eq15(juniorDestinations.id, juniorConversations.destinationId)
4310
4430
  ).where(where).groupBy(
4311
4431
  channel,
4312
4432
  juniorConversations.channelName,
@@ -4315,8 +4435,8 @@ async function readPeopleProfileFromSql(email, options = {}) {
4315
4435
  ),
4316
4436
  getDb().select({ surface, ...peopleTreeAggregateColumns }).from(juniorConversations).innerJoin(
4317
4437
  juniorIdentities,
4318
- eq14(juniorIdentities.id, juniorConversations.actorIdentityId)
4319
- ).innerJoin(juniorUsers, eq14(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(where).groupBy(surface),
4438
+ eq15(juniorIdentities.id, juniorConversations.actorIdentityId)
4439
+ ).innerJoin(juniorUsers, eq15(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(where).groupBy(surface),
4320
4440
  recentActorRows(normalizedEmail)
4321
4441
  ]);
4322
4442
  const totalsRow = totalsRows[0];
@@ -4394,7 +4514,7 @@ async function readPeopleProfile(email, options = {}) {
4394
4514
  }
4395
4515
 
4396
4516
  // src/api/people/spend.query.ts
4397
- import { and as and15, eq as eq15, gte as gte5, lte as lte2, sql as sql15 } from "drizzle-orm";
4517
+ import { and as and15, eq as eq16, gte as gte6, lte as lte2, sql as sql16 } from "drizzle-orm";
4398
4518
  var SEVEN_DAY_OFFSET = 6;
4399
4519
  var THIRTY_DAY_OFFSET = 29;
4400
4520
  function addUsd2(current, next) {
@@ -4413,7 +4533,7 @@ function spendWindow(nowMs) {
4413
4533
  async function readPersonalSpendFromSql(email, nowMs = Date.now()) {
4414
4534
  const normalizedEmail = normalizeEmail(email);
4415
4535
  const { end, sevenDayStart, thirtyDayStart } = spendWindow(nowMs);
4416
- const activityDate = sql15`TO_CHAR(
4536
+ const activityDate = sql16`TO_CHAR(
4417
4537
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
4418
4538
  'YYYY-MM-DD'
4419
4539
  )`;
@@ -4423,11 +4543,11 @@ async function readPersonalSpendFromSql(email, nowMs = Date.now()) {
4423
4543
  date: activityDate
4424
4544
  }).from(juniorConversations).innerJoin(
4425
4545
  juniorIdentities,
4426
- eq15(juniorIdentities.id, juniorConversations.actorIdentityId)
4427
- ).innerJoin(juniorUsers, eq15(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(
4546
+ eq16(juniorIdentities.id, juniorConversations.actorIdentityId)
4547
+ ).innerJoin(juniorUsers, eq16(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(
4428
4548
  and15(
4429
4549
  verifiedActorWhere(normalizedEmail),
4430
- gte5(juniorConversations.lastActivityAt, thirtyDayStart),
4550
+ gte6(juniorConversations.lastActivityAt, thirtyDayStart),
4431
4551
  lte2(juniorConversations.lastActivityAt, end)
4432
4552
  )
4433
4553
  ).groupBy(activityDate) : [];
@@ -4480,7 +4600,7 @@ function createPersonalSpendReader() {
4480
4600
 
4481
4601
  // src/api/people/routes.ts
4482
4602
  function createPeopleRoutes() {
4483
- const app = new Hono3();
4603
+ const app = new Hono4();
4484
4604
  const readPersonalSpend = createPersonalSpendReader();
4485
4605
  app.get("/me/spend", requireViewer, async (context) => {
4486
4606
  const viewer = context.get("viewer");
@@ -4522,9 +4642,86 @@ function createPeopleRoutes() {
4522
4642
  }
4523
4643
 
4524
4644
  // src/api/personal-tokens/routes.ts
4525
- import { Hono as Hono4 } from "hono";
4645
+ import { Hono as Hono5 } from "hono";
4646
+
4647
+ // src/personal-tokens/store.ts
4648
+ import { createHash, randomBytes, randomUUID } from "crypto";
4649
+ import { and as and16, desc as desc7, eq as eq17, gt, isNull as isNull7 } from "drizzle-orm";
4650
+ var TOKEN_PREFIX = "jr_pat_";
4651
+ var TOKEN_SUFFIX_LENGTH = 8;
4652
+ var DEFAULT_TOKEN_LIFETIME_MS = 90 * 24 * 60 * 60 * 1e3;
4653
+ function normalizeEmail2(email) {
4654
+ return email.trim().toLowerCase();
4655
+ }
4656
+ function hashToken(token2) {
4657
+ return createHash("sha256").update(token2, "utf8").digest("hex");
4658
+ }
4659
+ function metadata(row) {
4660
+ return {
4661
+ id: row.id,
4662
+ name: row.name,
4663
+ tokenSuffix: row.tokenSuffix,
4664
+ createdAt: row.createdAt.toISOString(),
4665
+ expiresAt: row.expiresAt.toISOString(),
4666
+ lastUsedAt: row.lastUsedAt?.toISOString() ?? null
4667
+ };
4668
+ }
4669
+ async function createPersonalToken(args) {
4670
+ const now = args.now ?? /* @__PURE__ */ new Date();
4671
+ const token2 = `${TOKEN_PREFIX}${randomBytes(32).toString("base64url")}`;
4672
+ const row = {
4673
+ id: randomUUID(),
4674
+ ownerEmailNormalized: normalizeEmail2(args.email),
4675
+ name: args.name.trim(),
4676
+ tokenHash: hashToken(token2),
4677
+ tokenSuffix: token2.slice(-TOKEN_SUFFIX_LENGTH),
4678
+ createdAt: now,
4679
+ expiresAt: new Date(now.getTime() + DEFAULT_TOKEN_LIFETIME_MS)
4680
+ };
4681
+ await getDb().insert(juniorApiTokens).values(row);
4682
+ return { ...metadata({ ...row, lastUsedAt: null, revokedAt: null }), token: token2 };
4683
+ }
4684
+ async function listPersonalTokens(email, now = /* @__PURE__ */ new Date()) {
4685
+ const rows = await getDb().select().from(juniorApiTokens).where(
4686
+ and16(
4687
+ eq17(juniorApiTokens.ownerEmailNormalized, normalizeEmail2(email)),
4688
+ isNull7(juniorApiTokens.revokedAt),
4689
+ gt(juniorApiTokens.expiresAt, now)
4690
+ )
4691
+ ).orderBy(desc7(juniorApiTokens.createdAt));
4692
+ return rows.map(metadata);
4693
+ }
4694
+ async function revokePersonalToken(args) {
4695
+ const rows = await getDb().update(juniorApiTokens).set({ revokedAt: args.now ?? /* @__PURE__ */ new Date() }).where(
4696
+ and16(
4697
+ eq17(juniorApiTokens.id, args.id),
4698
+ eq17(juniorApiTokens.ownerEmailNormalized, normalizeEmail2(args.email)),
4699
+ isNull7(juniorApiTokens.revokedAt)
4700
+ )
4701
+ ).returning({ id: juniorApiTokens.id });
4702
+ return rows.length > 0;
4703
+ }
4704
+ async function authenticatePersonalToken(token2, now = /* @__PURE__ */ new Date()) {
4705
+ if (!token2.startsWith(TOKEN_PREFIX)) return void 0;
4706
+ const rows = await getDb().select({
4707
+ id: juniorApiTokens.id,
4708
+ ownerEmailNormalized: juniorApiTokens.ownerEmailNormalized
4709
+ }).from(juniorApiTokens).where(
4710
+ and16(
4711
+ eq17(juniorApiTokens.tokenHash, hashToken(token2)),
4712
+ isNull7(juniorApiTokens.revokedAt),
4713
+ gt(juniorApiTokens.expiresAt, now)
4714
+ )
4715
+ ).limit(1);
4716
+ const match = rows[0];
4717
+ if (!match) return void 0;
4718
+ await getDb().update(juniorApiTokens).set({ lastUsedAt: now }).where(eq17(juniorApiTokens.id, match.id));
4719
+ return match.ownerEmailNormalized;
4720
+ }
4721
+
4722
+ // src/api/personal-tokens/routes.ts
4526
4723
  function createPersonalTokenRoutes() {
4527
- const app = new Hono4();
4724
+ const app = new Hono5();
4528
4725
  app.get("/", requireViewer, async (context) => {
4529
4726
  const viewer = context.get("viewer");
4530
4727
  return jsonResponse(personalTokenListSchema, {
@@ -4571,8 +4768,8 @@ function createPersonalTokenRoutes() {
4571
4768
  }
4572
4769
 
4573
4770
  // src/api/user-pages/routes.ts
4574
- import { Hono as Hono5 } from "hono";
4575
- import { z as z5 } from "zod";
4771
+ import { Hono as Hono6 } from "hono";
4772
+ import { z as z6 } from "zod";
4576
4773
  import {
4577
4774
  pluginUserPageContentSchema as pluginUserPageContentSchema2,
4578
4775
  pluginUserPageCursorSchema,
@@ -4640,23 +4837,23 @@ async function readPluginUserPage(input) {
4640
4837
  }
4641
4838
 
4642
4839
  // src/api/user-pages/routes.ts
4643
- var userPageQuerySchema = z5.object({
4644
- cursor: z5.preprocess(
4840
+ var userPageQuerySchema = z6.object({
4841
+ cursor: z6.preprocess(
4645
4842
  (value) => value || void 0,
4646
4843
  pluginUserPageCursorSchema
4647
4844
  ),
4648
- filter: z5.preprocess(
4845
+ filter: z6.preprocess(
4649
4846
  (value) => value || void 0,
4650
4847
  pluginUserPageFilterSchema
4651
4848
  ),
4652
- limit: z5.preprocess(
4849
+ limit: z6.preprocess(
4653
4850
  (value) => value === "" ? void 0 : value,
4654
- z5.coerce.number().int().min(1).max(50).default(20)
4851
+ z6.coerce.number().int().min(1).max(50).default(20)
4655
4852
  ),
4656
- q: z5.preprocess((value) => value || void 0, pluginUserPageQuerySchema)
4853
+ q: z6.preprocess((value) => value || void 0, pluginUserPageQuerySchema)
4657
4854
  });
4658
4855
  function createUserPageRoutes() {
4659
- const app = new Hono5();
4856
+ const app = new Hono6();
4660
4857
  app.get(
4661
4858
  "/",
4662
4859
  () => jsonResponse(pluginUserPageLinksSchema2, readPluginUserPageLinks())
@@ -4685,9 +4882,9 @@ function createUserPageRoutes() {
4685
4882
  }
4686
4883
 
4687
4884
  // src/api/tasks/routes.ts
4688
- import { Hono as Hono6 } from "hono";
4885
+ import { Hono as Hono7 } from "hono";
4689
4886
  function createTaskRoutes() {
4690
- const app = new Hono6();
4887
+ const app = new Hono7();
4691
4888
  app.get("/", requireViewer, async (context) => {
4692
4889
  const user = context.get("viewer");
4693
4890
  return jsonResponse(taskListSchema, await readViewerTasks(user));
@@ -4746,7 +4943,7 @@ function createTaskRoutes() {
4746
4943
  }
4747
4944
 
4748
4945
  // src/api/workspaces/routes.ts
4749
- import { Hono as Hono7 } from "hono";
4946
+ import { Hono as Hono8 } from "hono";
4750
4947
  function snapshotView(workspace) {
4751
4948
  const recorded = workspace.snapshot;
4752
4949
  if (!recorded) return null;
@@ -4802,7 +4999,7 @@ function handleValidationError(error) {
4802
4999
  throw error;
4803
5000
  }
4804
5001
  function createWorkspaceRoutes() {
4805
- const app = new Hono7();
5002
+ const app = new Hono8();
4806
5003
  app.get("/", requireViewer, async () => {
4807
5004
  const [baselineSnapshot, workspaces] = await Promise.all([
4808
5005
  baselineSnapshotView(),
@@ -4885,13 +5082,13 @@ function createWorkspaceRoutes() {
4885
5082
  }
4886
5083
 
4887
5084
  // src/api/stats.ts
4888
- var WINDOW_DAYS2 = 90;
5085
+ var WINDOW_DAYS3 = 90;
4889
5086
  async function readStatsReport() {
4890
5087
  const now = /* @__PURE__ */ new Date();
4891
5088
  const end = now.toISOString().slice(0, 10);
4892
5089
  const startDate = new Date(now);
4893
5090
  startDate.setUTCHours(0, 0, 0, 0);
4894
- startDate.setUTCDate(startDate.getUTCDate() - (WINDOW_DAYS2 - 1));
5091
+ startDate.setUTCDate(startDate.getUTCDate() - (WINDOW_DAYS3 - 1));
4895
5092
  const start = startDate.toISOString().slice(0, 10);
4896
5093
  return statsReportSchema.parse({
4897
5094
  generatedAt: now.toISOString(),
@@ -4913,7 +5110,7 @@ function readDescriptionText(home) {
4913
5110
  }
4914
5111
  }
4915
5112
  async function readSkillReports() {
4916
- const { discoverSkills } = await import("./skills-BNNNRYNT.js");
5113
+ const { discoverSkills } = await import("./skills-EXIQ7BP5.js");
4917
5114
  const skills = await discoverSkills();
4918
5115
  return skillReportsSchema.parse(
4919
5116
  skills.map((skill) => ({
@@ -4923,7 +5120,7 @@ async function readSkillReports() {
4923
5120
  );
4924
5121
  }
4925
5122
  async function readPlugins() {
4926
- const { pluginCatalogRuntime } = await import("./catalog-runtime-CJTFLCK3.js");
5123
+ const { pluginCatalogRuntime } = await import("./catalog-runtime-3I3JOIIH.js");
4927
5124
  return pluginsSchema.parse(
4928
5125
  pluginCatalogRuntime.getProviders().map((plugin) => ({
4929
5126
  configKeys: plugin.manifest.configKeys ?? [],
@@ -4936,7 +5133,7 @@ async function readPlugins() {
4936
5133
  async function readRuntimeInfoReport() {
4937
5134
  const [{ homeDir }, { pluginCatalogRuntime }, plugins, skills] = await Promise.all([
4938
5135
  import("./discovery-DWVDM7UK.js"),
4939
- import("./catalog-runtime-CJTFLCK3.js"),
5136
+ import("./catalog-runtime-3I3JOIIH.js"),
4940
5137
  readPlugins(),
4941
5138
  readSkillReports()
4942
5139
  ]);
@@ -4952,7 +5149,7 @@ async function readRuntimeInfoReport() {
4952
5149
  }
4953
5150
  async function readPluginOperationalReportFeed() {
4954
5151
  const nowMs = Date.now();
4955
- const { getPluginOperationalReports } = await import("./agent-hooks-KO56HJ74.js");
5152
+ const { getPluginOperationalReports } = await import("./agent-hooks-SNRBZYAU.js");
4956
5153
  return pluginOperationalReportFeedSchema.parse({
4957
5154
  source: "plugins",
4958
5155
  generatedAt: new Date(nowMs).toISOString(),
@@ -4962,7 +5159,7 @@ async function readPluginOperationalReportFeed() {
4962
5159
 
4963
5160
  // src/api.ts
4964
5161
  function createJuniorApi() {
4965
- const app = new Hono8();
5162
+ const app = new Hono9();
4966
5163
  app.get(
4967
5164
  "/api/health",
4968
5165
  async () => jsonResponse(healthReportSchema, readHealthReport())
@@ -4996,6 +5193,7 @@ function createJuniorApi() {
4996
5193
  attachmentStorage: createVercelAttachmentStorage()
4997
5194
  })
4998
5195
  );
5196
+ app.route("/api/code", createCodeRoutes());
4999
5197
  app.route("/api/personal-tokens", createPersonalTokenRoutes());
5000
5198
  app.route("/api/people", createPeopleRoutes());
5001
5199
  app.route("/api/locations", createLocationRoutes());