@sentry/junior 0.193.0 → 0.195.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 (99) hide show
  1. package/dist/{agent-hooks-DWY3MZZ7.js → agent-hooks-VIBTIP5F.js} +11 -11
  2. package/dist/api/activity.d.ts +9 -1
  3. package/dist/api/code/overview.d.ts +12 -0
  4. package/dist/api/conversations/aggregate.d.ts +2 -0
  5. package/dist/api/conversations/list.d.ts +1 -1
  6. package/dist/api/conversations/projection.d.ts +1 -1
  7. package/dist/api/locations/detail.d.ts +9 -1
  8. package/dist/api/locations/list.d.ts +5 -0
  9. package/dist/api/people/code.d.ts +6 -0
  10. package/dist/api/people/shared.d.ts +9 -1
  11. package/dist/api/reporting-window.d.ts +39 -1
  12. package/dist/api/schema/code.d.ts +12 -0
  13. package/dist/api/schema/conversation.d.ts +28 -3
  14. package/dist/api/schema/location.d.ts +14 -1
  15. package/dist/api/schema/person.d.ts +15 -1
  16. package/dist/api/schema/task.d.ts +83 -8
  17. package/dist/api/schema.d.ts +2 -2
  18. package/dist/api/schema.js +3 -1
  19. package/dist/api.js +320 -222
  20. package/dist/app.js +108 -39
  21. package/dist/{catalog-runtime-NAD44W5K.js → catalog-runtime-6E6SGRZK.js} +4 -4
  22. package/dist/chat/agent/resume.d.ts +2 -0
  23. package/dist/chat/config.d.ts +2 -0
  24. package/dist/chat/conversations/history.d.ts +4 -2
  25. package/dist/chat/event-tasks/store.d.ts +27 -17
  26. package/dist/chat/resource-events/notification.d.ts +2 -1
  27. package/dist/chat/services/automated-turn-limit.d.ts +110 -0
  28. package/dist/chat/services/turn-limit.d.ts +11 -1
  29. package/dist/chat/slack/automated-turn-limit-notice.d.ts +38 -0
  30. package/dist/chat/slack/{source-link.d.ts → location-url.d.ts} +1 -1
  31. package/dist/chat/task-execution/checkpoint.d.ts +2 -0
  32. package/dist/chat/task-execution/turn-cursor.d.ts +3 -0
  33. package/dist/chat/tasks/execution-stats.d.ts +15 -2
  34. package/dist/chat/tasks/read.d.ts +5 -2
  35. package/dist/chat/usage.d.ts +4 -0
  36. package/dist/{chunk-GUKGU6R7.js → chunk-3VWIZVK7.js} +1 -1
  37. package/dist/{chunk-THYNA2QN.js → chunk-5HNXLP4W.js} +1 -1
  38. package/dist/{chunk-GUMBIDDL.js → chunk-5NR7N567.js} +194 -43
  39. package/dist/{chunk-N6Q2PNSI.js → chunk-6GGDBXXP.js} +3 -3
  40. package/dist/{chunk-HMBTX5RK.js → chunk-6TRQLG3D.js} +1 -1
  41. package/dist/{chunk-IOUUS6H4.js → chunk-7MYXH5LA.js} +1 -1
  42. package/dist/{chunk-WH5VV2RW.js → chunk-7PQMTME5.js} +1 -1
  43. package/dist/{chunk-5E5SLAVD.js → chunk-7UED4D5T.js} +23 -25
  44. package/dist/{chunk-4UA5C7AM.js → chunk-BJZML4RT.js} +8 -8
  45. package/dist/{chunk-QDU5MW2R.js → chunk-C4NY6L7S.js} +1 -1
  46. package/dist/{chunk-DVU734PI.js → chunk-CE2P6TOV.js} +3 -3
  47. package/dist/{chunk-BFP3ZKG6.js → chunk-DTYOEHUP.js} +148 -19
  48. package/dist/{chunk-S5HS6WRH.js → chunk-FE3Y4KES.js} +5 -5
  49. package/dist/{chunk-PYBFVK6K.js → chunk-FEZIEEOP.js} +985 -569
  50. package/dist/{chunk-5S6AQFNG.js → chunk-FPQPYJEG.js} +23 -29
  51. package/dist/{chunk-42N6CDWF.js → chunk-HE5PZAPS.js} +4 -4
  52. package/dist/{chunk-QY2IU47O.js → chunk-HUQOXMDG.js} +1 -1
  53. package/dist/{chunk-IQCL5JGL.js → chunk-I4RH3KLJ.js} +1 -1
  54. package/dist/{chunk-LXRTHE43.js → chunk-JBSCMOLR.js} +5 -5
  55. package/dist/{chunk-OICYQPKP.js → chunk-KBPWC7NU.js} +1 -1
  56. package/dist/{chunk-2CYWEVOP.js → chunk-KQ3GZGBK.js} +88 -68
  57. package/dist/{chunk-GTXQHZ2O.js → chunk-KUQRWV53.js} +5 -5
  58. package/dist/{chunk-IBXXTO3J.js → chunk-L62JVQPL.js} +3 -3
  59. package/dist/{chunk-KWXZMHJS.js → chunk-LM7UE523.js} +3 -3
  60. package/dist/{chunk-WJJDQLVL.js → chunk-LMYRF6HX.js} +6 -2
  61. package/dist/{chunk-AZVDODSP.js → chunk-N67T4VY3.js} +9 -9
  62. package/dist/{chunk-D4XQZOHB.js → chunk-OQHO62VA.js} +8 -8
  63. package/dist/{chunk-FQ5HFSFR.js → chunk-PFQRZ4IB.js} +9 -6
  64. package/dist/{chunk-LG7Q4OW4.js → chunk-PYTRZZ4V.js} +8 -8
  65. package/dist/{chunk-THFNL3TL.js → chunk-QHJZSYKY.js} +2 -2
  66. package/dist/{chunk-5LEVZYXF.js → chunk-QKHZF2LH.js} +4 -4
  67. package/dist/{chunk-EYIMZY5O.js → chunk-QPZL2IYT.js} +100 -9
  68. package/dist/{chunk-D5YQPCEG.js → chunk-R5BGW4WR.js} +24 -2
  69. package/dist/{chunk-COCVPDWX.js → chunk-R5OHONYU.js} +6 -6
  70. package/dist/{chunk-DXFUYLHX.js → chunk-RKA22BQP.js} +1 -1
  71. package/dist/{chunk-3YZ2Q6AW.js → chunk-RQO67SAO.js} +2 -2
  72. package/dist/{chunk-ZFPEPWOO.js → chunk-RZ3PBNDV.js} +60 -29
  73. package/dist/{chunk-K47OVEO4.js → chunk-VYDIA2UL.js} +1 -1
  74. package/dist/{chunk-QWY4KI2V.js → chunk-X3PBQ4BK.js} +1 -1
  75. package/dist/cli/chat.js +33 -33
  76. package/dist/cli/check.js +5 -5
  77. package/dist/cli/plugins.js +12 -12
  78. package/dist/cli/snapshot-create.js +9 -9
  79. package/dist/cli/upgrade.js +6 -6
  80. package/dist/db/schema/event-tasks.d.ts +21 -0
  81. package/dist/db/schema.d.ts +19 -0
  82. package/dist/{db-H5MDRQEY.js → db-FVCSDROR.js} +6 -6
  83. package/dist/instrumentation.js +3 -3
  84. package/dist/nitro.js +6 -6
  85. package/dist/{oauth-callback-server-IOU3NUHT.js → oauth-callback-server-Z5PXTDOE.js} +29 -29
  86. package/dist/{runner-FZ5ZHLFG.js → runner-RHYU7OGV.js} +21 -21
  87. package/dist/{skills-AR3WD6BX.js → skills-QTN73DN5.js} +5 -5
  88. package/dist/spawn-R56OWLUH.js +42 -0
  89. package/dist/task-runner-LLJZTLRP.js +36 -0
  90. package/dist/{validation-VYE7TQY7.js → validation-2ZK7GA6N.js} +5 -5
  91. package/dist/version.js +1 -1
  92. package/dist/{work-CTQFWYKE.js → work-7IBKSZRU.js} +21 -21
  93. package/dist/{worker-6WQU3IT5.js → worker-RNVQVCO7.js} +10 -10
  94. package/migrations/0038_event_task_status.sql +5 -0
  95. package/migrations/meta/0038_snapshot.json +3323 -0
  96. package/migrations/meta/_journal.json +8 -1
  97. package/package.json +4 -4
  98. package/dist/spawn-ZU6JABR7.js +0 -42
  99. package/dist/task-runner-EEGGG2PM.js +0 -36
package/dist/api.js CHANGED
@@ -1,9 +1,11 @@
1
1
  import {
2
2
  DAY_MS,
3
3
  HOUR_MS,
4
+ WINDOW_SEVEN_DAY_HOURS,
4
5
  acceptedConversationMessageSchema,
5
6
  activityDays,
6
7
  activityHours,
8
+ activitySixHours,
7
9
  actorDirectoryReportSchema,
8
10
  actorProfileReportSchema,
9
11
  apiErrorSchema,
@@ -31,6 +33,7 @@ import {
31
33
  deleteWorkspaceResponseSchema,
32
34
  fillUtcDays,
33
35
  fillUtcHours,
36
+ fillUtcSixHours,
34
37
  locationDetailReportSchema,
35
38
  locationDirectoryReportSchema,
36
39
  locationParamsSchema,
@@ -39,20 +42,23 @@ import {
39
42
  personalTokenListSchema,
40
43
  personalTokenParamsSchema,
41
44
  revokePersonalTokenResponseSchema,
45
+ startOfUtcHour,
42
46
  statsReportSchema,
47
+ sumUtcHoursIntoSixHours,
43
48
  taskExecutionListSchema,
44
49
  taskListSchema,
45
50
  taskParamsSchema,
46
51
  taskRunListSchema,
47
52
  trailingUtcDayWindow,
48
53
  trailingUtcHourWindow,
54
+ trailingUtcSixHourWindow,
49
55
  utcDayKey,
50
56
  utcHourKey,
51
57
  workspaceBodySchema,
52
58
  workspaceListSchema,
53
59
  workspaceParamsSchema,
54
60
  workspaceSchema
55
- } from "./chunk-EYIMZY5O.js";
61
+ } from "./chunk-QPZL2IYT.js";
56
62
  import {
57
63
  appendAndEnqueueWebMessage,
58
64
  conversationArchiveTimes,
@@ -72,13 +78,17 @@ import {
72
78
  resolveSlackConversationContextFromThreadId,
73
79
  viewerConversationMembership,
74
80
  webActorFromEmail
75
- } from "./chunk-LG7Q4OW4.js";
81
+ } from "./chunk-PYTRZZ4V.js";
76
82
  import {
77
83
  buildSentryConversationUrl,
78
84
  buildSentryEventUrl,
79
85
  getWebAuthorization
80
- } from "./chunk-THYNA2QN.js";
86
+ } from "./chunk-5HNXLP4W.js";
81
87
  import {
88
+ conversationActiveDaysColumn,
89
+ conversationAggregateColumns,
90
+ conversationRangeColumns,
91
+ emptyTaskRunWindows,
82
92
  readTaskExecutionByConversationId,
83
93
  readTaskExecutionDays,
84
94
  readTaskExecutionHours,
@@ -87,7 +97,7 @@ import {
87
97
  readTaskExecutionSummaries,
88
98
  readTaskExecutions,
89
99
  readTaskRuns
90
- } from "./chunk-GUMBIDDL.js";
100
+ } from "./chunk-5NR7N567.js";
91
101
  import {
92
102
  healthReportSchema,
93
103
  pluginOperationalReportFeedSchema,
@@ -102,6 +112,7 @@ import {
102
112
  getEventTask,
103
113
  getResourceEventCatalog,
104
114
  isListedScheduledTask,
115
+ listDeletedEventTasksCreatedBy,
105
116
  listEventTasksCreatedBy,
106
117
  listPublicEventTasksForTeams,
107
118
  listPublicScheduledTasksForTeams,
@@ -110,24 +121,24 @@ import {
110
121
  readScheduledTask,
111
122
  readStats,
112
123
  saveScheduledTask
113
- } from "./chunk-BFP3ZKG6.js";
124
+ } from "./chunk-DTYOEHUP.js";
114
125
  import {
115
126
  parseSlackThreadId
116
- } from "./chunk-HMBTX5RK.js";
127
+ } from "./chunk-6TRQLG3D.js";
117
128
  import {
118
129
  cancelHumanFacingPendingMessages,
119
130
  getConversation
120
- } from "./chunk-5LEVZYXF.js";
131
+ } from "./chunk-QKHZF2LH.js";
121
132
  import "./chunk-DA2KGZZI.js";
122
133
  import {
123
134
  agentTurnUsageSchema,
124
135
  fallbackShortTitle,
125
136
  hasAgentTurnUsage,
126
137
  renderJuniorNativeConversationEvent
127
- } from "./chunk-D5YQPCEG.js";
138
+ } from "./chunk-R5BGW4WR.js";
128
139
  import {
129
140
  getCachedSnapshot
130
- } from "./chunk-IBXXTO3J.js";
141
+ } from "./chunk-L62JVQPL.js";
131
142
  import "./chunk-PDO5BLNM.js";
132
143
  import {
133
144
  getVercelConversationWorkQueue
@@ -153,7 +164,7 @@ import {
153
164
  updateWorkspace,
154
165
  withSlackRetries,
155
166
  workspaceRepoCheckoutPath
156
- } from "./chunk-FQ5HFSFR.js";
167
+ } from "./chunk-PFQRZ4IB.js";
157
168
  import "./chunk-3Y47VMHV.js";
158
169
  import {
159
170
  getConversationStore,
@@ -162,7 +173,7 @@ import {
162
173
  locationFromRow,
163
174
  parseSessionSource,
164
175
  resolveRootConversationId
165
- } from "./chunk-2CYWEVOP.js";
176
+ } from "./chunk-KQ3GZGBK.js";
166
177
  import {
167
178
  conversationReadColumns,
168
179
  juniorApiTokens,
@@ -174,23 +185,23 @@ import {
174
185
  juniorIdentities,
175
186
  juniorSchedulerTasks,
176
187
  juniorUsers
177
- } from "./chunk-5S6AQFNG.js";
188
+ } from "./chunk-FPQPYJEG.js";
178
189
  import {
179
190
  create,
180
191
  hash
181
- } from "./chunk-KWXZMHJS.js";
182
- import "./chunk-IOUUS6H4.js";
192
+ } from "./chunk-LM7UE523.js";
193
+ import "./chunk-7MYXH5LA.js";
183
194
  import {
184
195
  decodeStoredConversationEvent
185
196
  } from "./chunk-GFBR4S3Q.js";
186
197
  import {
187
198
  juniorDestinations
188
199
  } from "./chunk-VFUK3X5B.js";
189
- import "./chunk-WJJDQLVL.js";
200
+ import "./chunk-LMYRF6HX.js";
190
201
  import "./chunk-D4YV5TDV.js";
191
- import "./chunk-OICYQPKP.js";
192
- import "./chunk-DXFUYLHX.js";
193
- import "./chunk-QWY4KI2V.js";
202
+ import "./chunk-KBPWC7NU.js";
203
+ import "./chunk-RKA22BQP.js";
204
+ import "./chunk-X3PBQ4BK.js";
194
205
  import "./chunk-CEMMLV5L.js";
195
206
  import {
196
207
  parseSlackChannelId,
@@ -202,9 +213,9 @@ import "./chunk-TXKUKMVO.js";
202
213
  import {
203
214
  logException,
204
215
  logWarn
205
- } from "./chunk-QY2IU47O.js";
216
+ } from "./chunk-HUQOXMDG.js";
206
217
  import "./chunk-PEQXYSSE.js";
207
- import "./chunk-QDU5MW2R.js";
218
+ import "./chunk-C4NY6L7S.js";
208
219
 
209
220
  // src/api.ts
210
221
  import { Hono as Hono9 } from "hono";
@@ -450,7 +461,7 @@ async function appendConversationMessageForViewer(viewer, conversationId, body)
450
461
  }
451
462
  }
452
463
 
453
- // src/chat/slack/source-link.ts
464
+ // src/chat/slack/location-url.ts
454
465
  function parseSlackTeamDomain(value) {
455
466
  if (typeof value !== "string") return void 0;
456
467
  const domain = value.trim().toLowerCase();
@@ -463,7 +474,7 @@ function archivePathFromThreadTs(threadTs) {
463
474
  const [seconds, fraction = ""] = threadTs.split(".");
464
475
  return `p${seconds}${(fraction ?? "").padEnd(6, "0").slice(0, 6)}`;
465
476
  }
466
- function buildSlackSourceUrl(args) {
477
+ function buildSlackLocationUrl(args) {
467
478
  const channelId = parseSlackChannelId(args.channelId);
468
479
  const teamDomain = parseSlackTeamDomain(args.teamDomain);
469
480
  const threadTs = parseSlackMessageTs(args.threadTs);
@@ -1305,18 +1316,16 @@ function surfaceFromSource(source, conversationId) {
1305
1316
  }
1306
1317
  return surfaceFromConversationId(conversationId);
1307
1318
  }
1308
- function sourceUrlFromConversation(args) {
1319
+ function locationUrlFromConversation(args) {
1309
1320
  const { conversation } = args;
1310
- if (!args.canViewPrivateContent || conversation.sessionSource?.kind !== "slack") {
1321
+ if (!args.canViewPrivateContent || conversation.location?.provider !== "slack") {
1311
1322
  return void 0;
1312
1323
  }
1313
- const teamDomain = args.teamDomainByTeamId?.get(
1314
- conversation.sessionSource.teamId
1315
- );
1316
- const threadTs = conversation.sessionSource.threadTs;
1324
+ const teamDomain = args.teamDomainByTeamId?.get(conversation.location.teamId);
1325
+ const threadTs = conversation.location.threadTs;
1317
1326
  if (!teamDomain || !threadTs) return void 0;
1318
- return buildSlackSourceUrl({
1319
- channelId: conversation.sessionSource.channelId,
1327
+ return buildSlackLocationUrl({
1328
+ channelId: conversation.location.channelId,
1320
1329
  teamDomain,
1321
1330
  threadTs
1322
1331
  });
@@ -1397,7 +1406,7 @@ function conversationSummaryFromStoredConversation(args) {
1397
1406
  conversation.conversationId
1398
1407
  );
1399
1408
  const actorIdentity = actorIdentityReport(conversation.actor);
1400
- const sourceUrl = sourceUrlFromConversation({
1409
+ const locationUrl = locationUrlFromConversation({
1401
1410
  canViewPrivateContent,
1402
1411
  conversation,
1403
1412
  ...args.teamDomainByTeamId ? { teamDomainByTeamId: args.teamDomainByTeamId } : void 0
@@ -1433,7 +1442,7 @@ function conversationSummaryFromStoredConversation(args) {
1433
1442
  ...args.auxiliaryCosts ? { auxiliaryCosts: args.auxiliaryCosts } : void 0,
1434
1443
  ...usage3 ? { cumulativeUsage: usage3 } : void 0,
1435
1444
  ...actorIdentity ? { actorIdentity } : void 0,
1436
- ...sourceUrl ? { sourceUrl } : void 0,
1445
+ ...locationUrl ? { locationUrl } : void 0,
1437
1446
  archivedAt: args.archivedAtMs === void 0 ? null : new Date(args.archivedAtMs).toISOString(),
1438
1447
  ...slackThread ? { channel: slackThread.channelId } : void 0,
1439
1448
  ...channelName ? { channelName } : void 0,
@@ -1838,7 +1847,7 @@ function conversationFeedMembershipFilter(status, filter) {
1838
1847
  async function conversationRows(db, limit, status, filter) {
1839
1848
  return db.select({
1840
1849
  conversation: conversationReadColumns(),
1841
- destination: juniorDestinations,
1850
+ location: juniorDestinations,
1842
1851
  identityDisplayName: juniorIdentities.displayName,
1843
1852
  identityEmail: juniorIdentities.email,
1844
1853
  identityHandle: juniorIdentities.handle,
@@ -1864,9 +1873,9 @@ async function conversationRows(db, limit, status, filter) {
1864
1873
  }
1865
1874
  function conversationFromRow(row) {
1866
1875
  const value = row.conversation;
1867
- const sessionSource = value.sessionSource === null ? void 0 : parseSessionSource(value.sessionSource);
1868
- if (value.sessionSource !== null && !sessionSource) {
1869
- throw new Error("Conversation record session source is invalid");
1876
+ const legacySessionSource = value.sessionSource === null ? void 0 : parseSessionSource(value.sessionSource);
1877
+ if (value.sessionSource !== null && !legacySessionSource) {
1878
+ throw new Error("Conversation legacy source_json is invalid");
1870
1879
  }
1871
1880
  const actorFullName = row.userDisplayName?.trim() ? row.userDisplayName : row.identityDisplayName;
1872
1881
  const actor = row.identityProvider === "slack" ? {
@@ -1879,8 +1888,8 @@ function conversationFromRow(row) {
1879
1888
  } : void 0;
1880
1889
  const location = locationFromRow(
1881
1890
  value.location,
1882
- row.destination,
1883
- sessionSource
1891
+ row.location,
1892
+ legacySessionSource
1884
1893
  );
1885
1894
  return {
1886
1895
  schemaVersion: 1,
@@ -1897,7 +1906,6 @@ function conversationFromRow(row) {
1897
1906
  ...location ? { location } : void 0,
1898
1907
  ...value.channelName ? { channelName: value.channelName } : void 0,
1899
1908
  ...value.source ? { source: value.source } : void 0,
1900
- ...sessionSource ? { sessionSource } : void 0,
1901
1909
  ...value.title ? { title: value.title } : void 0,
1902
1910
  ...value.transcriptPurgedAt ? { transcriptPurgedAtMs: value.transcriptPurgedAt.getTime() } : void 0
1903
1911
  };
@@ -1906,7 +1914,7 @@ async function readConversationRecordFromSql(conversationId) {
1906
1914
  const db = getDb();
1907
1915
  const rows = await db.select({
1908
1916
  conversation: conversationReadColumns(),
1909
- destination: juniorDestinations,
1917
+ location: juniorDestinations,
1910
1918
  identityDisplayName: juniorIdentities.displayName,
1911
1919
  identityEmail: juniorIdentities.email,
1912
1920
  identityHandle: juniorIdentities.handle,
@@ -1925,7 +1933,7 @@ async function readConversationRecordFromSql(conversationId) {
1925
1933
  return row ? {
1926
1934
  conversation: conversationFromRow(row),
1927
1935
  durationMs: row.conversation.durationMs,
1928
- ...row.destination?.visibility === "public" ? { locationId: row.destination.id } : void 0,
1936
+ ...row.location?.visibility === "public" ? { locationId: row.location.id } : void 0,
1929
1937
  usage: row.conversation.usage,
1930
1938
  rootConversationId: row.conversation.rootConversationId
1931
1939
  } : void 0;
@@ -1982,7 +1990,7 @@ async function readConversationFeedFromSql(options = {}) {
1982
1990
  readRootConversationMetricsFromSql(db, conversationIds),
1983
1991
  resolveSlackTeamDomains(
1984
1992
  conversations.flatMap(
1985
- (conversation) => conversation.sessionSource?.kind === "slack" ? [conversation.sessionSource.teamId] : []
1993
+ (conversation) => conversation.location?.provider === "slack" ? [conversation.location.teamId] : []
1986
1994
  )
1987
1995
  ),
1988
1996
  listConversationWork(conversationIds),
@@ -2015,7 +2023,7 @@ async function readConversationFeedFromSql(options = {}) {
2015
2023
  auxiliaryCosts: auxiliaryCostsByRoot.get(conversation.conversationId),
2016
2024
  durationMs: metrics?.durationMs ?? row.conversation.durationMs,
2017
2025
  teamDomainByTeamId,
2018
- ...row.destination?.visibility === "public" ? { locationId: row.destination.id } : void 0,
2026
+ ...row.location?.visibility === "public" ? { locationId: row.location.id } : void 0,
2019
2027
  usage: metrics?.usage ?? row.conversation.usage ?? void 0
2020
2028
  });
2021
2029
  const work = {
@@ -2056,7 +2064,7 @@ async function readConversationFeed(options = {}) {
2056
2064
  }
2057
2065
 
2058
2066
  // src/chat/tasks/read.ts
2059
- import { and as and9, eq as eq9, or as or4 } from "drizzle-orm";
2067
+ import { and as and9, desc as desc4, eq as eq9, inArray as inArray6, or as or4 } from "drizzle-orm";
2060
2068
 
2061
2069
  // src/chat/scheduled-tasks/personal.ts
2062
2070
  import { and as and8, desc as desc3, eq as eq8, inArray as inArray5, lt as lt2, notInArray, or as or3, sql as sql8 } from "drizzle-orm";
@@ -2274,7 +2282,7 @@ function executionSummaryFields(stats) {
2274
2282
  return {
2275
2283
  ...stats?.lastConversationId ? { lastConversationId: stats.lastConversationId } : void 0,
2276
2284
  ...stats?.lastExecutedAtMs ? { lastRunAt: new Date(stats.lastExecutedAtMs).toISOString() } : void 0,
2277
- runsLast7Days: stats?.runsLast7Days ?? 0,
2285
+ runs: stats?.runs ?? emptyTaskRunWindows(),
2278
2286
  totalRuns: stats?.totalRuns ?? 0
2279
2287
  };
2280
2288
  }
@@ -2359,7 +2367,7 @@ async function resolveViewerTaskCandidate(user, kind, id) {
2359
2367
  };
2360
2368
  }
2361
2369
  const task = await getEventTask(db, id);
2362
- if (!task) return void 0;
2370
+ if (!task || task.status === "deleted") return void 0;
2363
2371
  const ownedByViewer = eventTaskBelongsToUser(task, user);
2364
2372
  const destinations = await destinationDetails([task.destination]);
2365
2373
  const destination = destinations.get(destinationKey(task.destination));
@@ -2407,6 +2415,26 @@ async function taskSummaryForCandidate(candidate) {
2407
2415
  createdByEmail
2408
2416
  );
2409
2417
  }
2418
+ function emptyTaskExecutionDay(date) {
2419
+ return { costUsd: 0, date, event: 0, scheduled: 0 };
2420
+ }
2421
+ function emptyTaskExecutionStatusDay(date) {
2422
+ return { blocked: 0, completed: 0, date, failed: 0 };
2423
+ }
2424
+ function taskExecutionSixHours(hours, nowMs = Date.now()) {
2425
+ return sumUtcHoursIntoSixHours({
2426
+ empty: emptyTaskExecutionDay,
2427
+ hours,
2428
+ nowMs
2429
+ });
2430
+ }
2431
+ function taskExecutionStatusSixHours(hours, nowMs = Date.now()) {
2432
+ return sumUtcHoursIntoSixHours({
2433
+ empty: emptyTaskExecutionStatusDay,
2434
+ hours,
2435
+ nowMs
2436
+ });
2437
+ }
2410
2438
  async function readViewerTasks(user) {
2411
2439
  const db = getDb();
2412
2440
  const identityIds = new Set(user.identities.map((identity) => identity.id));
@@ -2498,26 +2526,94 @@ async function readViewerTasks(user) {
2498
2526
  return {
2499
2527
  executionDays,
2500
2528
  executionHours,
2529
+ executionSixHours: taskExecutionSixHours(executionHours),
2501
2530
  tasks,
2502
2531
  truncated: ownedCandidates.length > TASK_LIST_LIMIT || publicCandidates.length > TASK_LIST_LIMIT
2503
2532
  };
2504
2533
  }
2505
- async function readViewerTaskRuns(user) {
2506
- const taskList = await readViewerTasks(user);
2507
- const taskTitles = new Map(
2508
- taskList.tasks.map((task) => [`${task.kind}:${task.id}`, task.title])
2534
+ async function readDeletedOwnedScheduledTasks(user) {
2535
+ const identityIds = user.identities.map((identity) => identity.id);
2536
+ if (identityIds.length === 0) return [];
2537
+ const rows = await getDb().select({
2538
+ creatorIdentityId: juniorSchedulerTasks.creatorIdentityId,
2539
+ id: juniorSchedulerTasks.id,
2540
+ record: juniorSchedulerTasks.record,
2541
+ title: juniorSchedulerTasks.title
2542
+ }).from(juniorSchedulerTasks).where(
2543
+ and9(
2544
+ eq9(juniorSchedulerTasks.status, "deleted"),
2545
+ inArray6(juniorSchedulerTasks.creatorIdentityId, identityIds)
2546
+ )
2547
+ ).orderBy(
2548
+ desc4(juniorSchedulerTasks.createdAtMs),
2549
+ desc4(juniorSchedulerTasks.id)
2550
+ ).limit(TASK_EXECUTION_LIST_LIMIT);
2551
+ return rows.map(parseScheduledTaskRow).filter((task) => task?.status === "deleted");
2552
+ }
2553
+ async function readDeletedOwnedEventTasks(user) {
2554
+ return await listDeletedEventTasksCreatedBy(
2555
+ getDb(),
2556
+ user,
2557
+ TASK_EXECUTION_LIST_LIMIT
2509
2558
  );
2559
+ }
2560
+ function taskTitleForRun(run, taskTitles) {
2561
+ return taskTitles.get(`${run.kind}:${run.taskId}`) ?? run.title?.trim() ?? "Untitled task";
2562
+ }
2563
+ function addDeletedTaskRun(args, taskTitles, tasks) {
2564
+ const key = `${args.kind}:${args.taskId}`;
2565
+ if (taskTitles.has(key)) return;
2566
+ taskTitles.set(key, args.title);
2567
+ tasks.push({ kind: args.kind, taskId: args.taskId });
2568
+ }
2569
+ async function readViewerTaskRuns(user) {
2570
+ const [taskList, deletedScheduled, deletedEvent] = await Promise.all([
2571
+ readViewerTasks(user),
2572
+ readDeletedOwnedScheduledTasks(user),
2573
+ readDeletedOwnedEventTasks(user)
2574
+ ]);
2575
+ const taskTitles = /* @__PURE__ */ new Map();
2576
+ const tasks = [];
2577
+ for (const task of taskList.tasks) {
2578
+ taskTitles.set(`${task.kind}:${task.id}`, task.title);
2579
+ tasks.push({ kind: task.kind, taskId: task.id });
2580
+ }
2581
+ for (const task of deletedScheduled) {
2582
+ const instruction = displayText(task.task.text, "Untitled scheduled task");
2583
+ addDeletedTaskRun(
2584
+ {
2585
+ kind: "scheduled",
2586
+ taskId: task.id,
2587
+ title: taskDisplayTitle(
2588
+ task.title,
2589
+ instruction,
2590
+ "Untitled scheduled task"
2591
+ )
2592
+ },
2593
+ taskTitles,
2594
+ tasks
2595
+ );
2596
+ }
2597
+ for (const task of deletedEvent) {
2598
+ const instruction = displayText(task.task.text, "Untitled event task");
2599
+ addDeletedTaskRun(
2600
+ {
2601
+ kind: "event",
2602
+ taskId: task.id,
2603
+ title: taskDisplayTitle(task.title, instruction, "Untitled event task")
2604
+ },
2605
+ taskTitles,
2606
+ tasks
2607
+ );
2608
+ }
2510
2609
  const runs = await readTaskRuns({
2511
2610
  limit: TASK_EXECUTION_LIST_LIMIT + 1,
2512
- tasks: taskList.tasks.map((task) => ({
2513
- kind: task.kind,
2514
- taskId: task.id
2515
- }))
2611
+ tasks
2516
2612
  });
2517
2613
  return {
2518
2614
  runs: runs.slice(0, TASK_EXECUTION_LIST_LIMIT).map((run) => ({
2519
2615
  ...run,
2520
- taskTitle: taskTitles.get(`${run.kind}:${run.taskId}`) ?? "Untitled task"
2616
+ taskTitle: taskTitleForRun(run, taskTitles)
2521
2617
  })),
2522
2618
  truncated: runs.length > TASK_EXECUTION_LIST_LIMIT
2523
2619
  };
@@ -2550,6 +2646,7 @@ async function readViewerTaskExecutions(user, kind, id) {
2550
2646
  return {
2551
2647
  executionDays,
2552
2648
  executionHours,
2649
+ executionSixHours: taskExecutionStatusSixHours(executionHours),
2553
2650
  executions: executions.slice(0, TASK_EXECUTION_LIST_LIMIT),
2554
2651
  task,
2555
2652
  truncated: executions.length > TASK_EXECUTION_LIST_LIMIT
@@ -2611,7 +2708,7 @@ async function deleteViewerTask(user, kind, id) {
2611
2708
  }
2612
2709
  }
2613
2710
  const task = await getEventTask(getDb(), id);
2614
- if (!task || !eventTaskBelongsToUser(task, user)) {
2711
+ if (!task || task.status === "deleted" || !eventTaskBelongsToUser(task, user)) {
2615
2712
  throw new ViewerTaskNotFoundError();
2616
2713
  }
2617
2714
  await deleteEventTask(getDb(), id);
@@ -2687,7 +2784,7 @@ async function readConversationDetailFromSql(conversationId, options) {
2687
2784
  ...options.viewer ? { viewer: options.viewer } : void 0
2688
2785
  }),
2689
2786
  resolveSlackTeamDomains(
2690
- record.conversation.sessionSource?.kind === "slack" ? [record.conversation.sessionSource.teamId] : []
2787
+ record.conversation.location?.provider === "slack" ? [record.conversation.location.teamId] : []
2691
2788
  )
2692
2789
  ]);
2693
2790
  const access = accessByConversation.get(conversationId);
@@ -2934,90 +3031,8 @@ async function requireConversationPendingMessages(conversationId, options = {})
2934
3031
  }
2935
3032
 
2936
3033
  // src/api/conversations/stats.query.ts
2937
- import { and as and10, eq as eq10, gte, isNull as isNull4, lte, sql as sql10 } from "drizzle-orm";
3034
+ import { and as and10, eq as eq10, gte, isNull as isNull4, lte, sql as sql9 } from "drizzle-orm";
2938
3035
  import { alias as alias3 } from "drizzle-orm/pg-core";
2939
-
2940
- // src/api/conversations/aggregate.ts
2941
- import { sql as sql9 } from "drizzle-orm";
2942
- function usageTokenValue(source, field) {
2943
- return sql9`CASE
2944
- WHEN ${source.usage}->>${field} IS NOT NULL
2945
- THEN (${source.usage}->>${field})::double precision
2946
- ELSE NULL
2947
- END`;
2948
- }
2949
- function tokenValue(source) {
2950
- return sql9`
2951
- CASE
2952
- WHEN COALESCE(
2953
- ${source.usage}->>'inputTokens',
2954
- ${source.usage}->>'outputTokens',
2955
- ${source.usage}->>'cachedInputTokens',
2956
- ${source.usage}->>'cacheCreationTokens'
2957
- ) IS NOT NULL
2958
- THEN COALESCE((${source.usage}->>'inputTokens')::double precision, 0)
2959
- + COALESCE((${source.usage}->>'outputTokens')::double precision, 0)
2960
- + COALESCE((${source.usage}->>'cachedInputTokens')::double precision, 0)
2961
- + COALESCE((${source.usage}->>'cacheCreationTokens')::double precision, 0)
2962
- WHEN ${source.usage}->>'totalTokens' IS NOT NULL
2963
- THEN (${source.usage}->>'totalTokens')::double precision
2964
- ELSE NULL
2965
- END
2966
- `;
2967
- }
2968
- function costValue(source) {
2969
- return sql9`
2970
- CASE
2971
- WHEN ${source.usage}->'cost'->>'total' IS NOT NULL
2972
- THEN (${source.usage}->'cost'->>'total')::double precision
2973
- WHEN COALESCE(
2974
- ${source.usage}->'cost'->>'input',
2975
- ${source.usage}->'cost'->>'output',
2976
- ${source.usage}->'cost'->>'cacheRead',
2977
- ${source.usage}->'cost'->>'cacheWrite'
2978
- ) IS NOT NULL
2979
- THEN COALESCE((${source.usage}->'cost'->>'input')::double precision, 0)
2980
- + COALESCE((${source.usage}->'cost'->>'output')::double precision, 0)
2981
- + COALESCE((${source.usage}->'cost'->>'cacheRead')::double precision, 0)
2982
- + COALESCE((${source.usage}->'cost'->>'cacheWrite')::double precision, 0)
2983
- ELSE NULL
2984
- END
2985
- `;
2986
- }
2987
- function conversationAggregateColumns(sources) {
2988
- const metrics = sources?.metrics ?? juniorConversations;
2989
- const roots = sources?.roots ?? juniorConversations;
2990
- const conversationCount = sources ? sql9`COUNT(DISTINCT ${roots.conversationId})` : sql9`COUNT(*)`;
2991
- return {
2992
- active: sql9`${conversationCount} FILTER (
2993
- WHERE ${roots.executionStatus} NOT IN ('idle', 'failed')
2994
- )::integer`,
2995
- conversations: sql9`${conversationCount}::integer`,
2996
- cachedInputTokens: sql9`SUM(${usageTokenValue(metrics, "cachedInputTokens")})::double precision`,
2997
- costUsd: sql9`SUM(${costValue(metrics)})::double precision`,
2998
- durationMs: sql9`COALESCE(SUM(${metrics.durationMs}), 0)::double precision`,
2999
- failed: sql9`${conversationCount} FILTER (
3000
- WHERE ${roots.executionStatus} = 'failed'
3001
- )::integer`,
3002
- inputTokens: sql9`SUM(${usageTokenValue(metrics, "inputTokens")})::double precision`,
3003
- tokens: sql9`SUM(${tokenValue(metrics)})::double precision`
3004
- };
3005
- }
3006
- function conversationRangeColumns() {
3007
- return {
3008
- firstSeenAt: sql9`MIN(${juniorConversations.createdAt})`.mapWith(
3009
- juniorConversations.createdAt
3010
- ),
3011
- lastSeenAt: sql9`MAX(${juniorConversations.lastActivityAt})`.mapWith(
3012
- juniorConversations.lastActivityAt
3013
- )
3014
- };
3015
- }
3016
- function conversationActiveDaysColumn() {
3017
- return sql9`COUNT(DISTINCT (${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC')::date)::integer`;
3018
- }
3019
-
3020
- // src/api/conversations/stats.query.ts
3021
3036
  var WINDOW_DAYS = 90;
3022
3037
  var treeConversation = alias3(juniorConversations, "stats_tree_conversation");
3023
3038
  var treeAggregateColumns = conversationAggregateColumns({
@@ -3092,15 +3107,7 @@ function statsWindow(nowMs) {
3092
3107
  return { end, start };
3093
3108
  }
3094
3109
  var HOUR_MS2 = 60 * 60 * 1e3;
3095
- var WINDOW_HOURS = 24;
3096
- function startOfUtcHour(valueMs) {
3097
- const date = new Date(valueMs);
3098
- date.setUTCMinutes(0, 0, 0);
3099
- return date;
3100
- }
3101
- function utcHourKey2(value) {
3102
- return value.toISOString().slice(0, 13);
3103
- }
3110
+ var WINDOW_HOURS = WINDOW_SEVEN_DAY_HOURS;
3104
3111
  function metricPoint(date, row) {
3105
3112
  return {
3106
3113
  conversations: row?.conversations ?? 0,
@@ -3125,13 +3132,33 @@ function metricDays(rows, endMs) {
3125
3132
  }
3126
3133
  return days;
3127
3134
  }
3135
+ function emptyMetricDay(date) {
3136
+ return { conversations: 0, date, durationMs: 0 };
3137
+ }
3138
+ function emptyGuardianDay(date) {
3139
+ return { allow: 0, ask: 0, date, deny: 0, requests: 0 };
3140
+ }
3141
+ function sumMetricHoursIntoSixHours(hours, endMs) {
3142
+ return sumUtcHoursIntoSixHours({
3143
+ empty: emptyMetricDay,
3144
+ hours,
3145
+ nowMs: endMs
3146
+ });
3147
+ }
3148
+ function sumGuardianHoursIntoSixHours(hours, endMs) {
3149
+ return sumUtcHoursIntoSixHours({
3150
+ empty: emptyGuardianDay,
3151
+ hours,
3152
+ nowMs: endMs
3153
+ });
3154
+ }
3128
3155
  function metricHours(rows, endMs) {
3129
3156
  const byHour = new Map(rows.map((row) => [row.date, row]));
3130
3157
  const end = startOfUtcHour(endMs);
3131
3158
  const start = new Date(end.getTime() - (WINDOW_HOURS - 1) * HOUR_MS2);
3132
3159
  const hours = [];
3133
3160
  for (const cursor = new Date(start); cursor.getTime() <= end.getTime(); cursor.setTime(cursor.getTime() + HOUR_MS2)) {
3134
- const date = utcHourKey2(cursor);
3161
+ const date = utcHourKey(cursor);
3135
3162
  hours.push(metricPoint(date, byHour.get(date)));
3136
3163
  }
3137
3164
  return hours;
@@ -3175,7 +3202,7 @@ function guardianStats(dayRows, hourRows, endMs) {
3175
3202
  const hourStart = new Date(hourEnd.getTime() - (WINDOW_HOURS - 1) * HOUR_MS2);
3176
3203
  const metricHours2 = [];
3177
3204
  for (const cursor = new Date(hourStart); cursor.getTime() <= hourEnd.getTime(); cursor.setTime(cursor.getTime() + HOUR_MS2)) {
3178
- const date = utcHourKey2(cursor);
3205
+ const date = utcHourKey(cursor);
3179
3206
  metricHours2.push(guardianPoint(date, byHour.get(date)));
3180
3207
  }
3181
3208
  return {
@@ -3184,17 +3211,18 @@ function guardianStats(dayRows, hourRows, endMs) {
3184
3211
  deny,
3185
3212
  metricDays: metricDays2,
3186
3213
  metricHours: metricHours2,
3214
+ metricSixHours: sumGuardianHoursIntoSixHours(metricHours2, endMs),
3187
3215
  requests,
3188
3216
  ...costUsd !== void 0 ? { costUsd } : void 0
3189
3217
  };
3190
3218
  }
3191
3219
  async function aggregateStats(db, start, end) {
3192
3220
  const where = statsWhere(start, end);
3193
- const activityDate = sql10`TO_CHAR(
3221
+ const activityDate = sql9`TO_CHAR(
3194
3222
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
3195
3223
  'YYYY-MM-DD'
3196
3224
  )`;
3197
- const activityHour = sql10`TO_CHAR(
3225
+ const activityHour = sql9`TO_CHAR(
3198
3226
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
3199
3227
  'YYYY-MM-DD"T"HH24'
3200
3228
  )`;
@@ -3302,26 +3330,26 @@ async function aggregateStats(db, start, end) {
3302
3330
  };
3303
3331
  }
3304
3332
  async function aggregateGuardianStats(db, start, end) {
3305
- const day = sql10`TO_CHAR(
3333
+ const day = sql9`TO_CHAR(
3306
3334
  ${juniorConversationEvents.createdAt} AT TIME ZONE 'UTC',
3307
3335
  'YYYY-MM-DD'
3308
3336
  )`;
3309
- const hour = sql10`TO_CHAR(
3337
+ const hour = sql9`TO_CHAR(
3310
3338
  ${juniorConversationEvents.createdAt} AT TIME ZONE 'UTC',
3311
3339
  'YYYY-MM-DD"T"HH24'
3312
3340
  )`;
3313
- const decision = sql10`${juniorConversationEvents.payload}->>'decision'`;
3314
- const cost2 = sql10`CASE
3341
+ const decision = sql9`${juniorConversationEvents.payload}->>'decision'`;
3342
+ const cost2 = sql9`CASE
3315
3343
  WHEN jsonb_typeof(${juniorConversationEvents.payload}->'costUsd') = 'number'
3316
3344
  THEN (${juniorConversationEvents.payload}->>'costUsd')::double precision
3317
3345
  ELSE NULL
3318
3346
  END`;
3319
3347
  const selectColumns = {
3320
- allow: sql10`COUNT(*) FILTER (WHERE ${decision} = 'allow')::integer`,
3321
- ask: sql10`COUNT(*) FILTER (WHERE ${decision} = 'ask')::integer`,
3322
- costUsd: sql10`SUM(${cost2})::double precision`,
3323
- deny: sql10`COUNT(*) FILTER (WHERE ${decision} = 'deny')::integer`,
3324
- requests: sql10`COUNT(*)::integer`
3348
+ allow: sql9`COUNT(*) FILTER (WHERE ${decision} = 'allow')::integer`,
3349
+ ask: sql9`COUNT(*) FILTER (WHERE ${decision} = 'ask')::integer`,
3350
+ costUsd: sql9`SUM(${cost2})::double precision`,
3351
+ deny: sql9`COUNT(*) FILTER (WHERE ${decision} = 'deny')::integer`,
3352
+ requests: sql9`COUNT(*)::integer`
3325
3353
  };
3326
3354
  const where = and10(
3327
3355
  eq10(juniorConversationEvents.type, "guardian_action_reviewed"),
@@ -3362,7 +3390,13 @@ async function readConversationStatsFromSql() {
3362
3390
  generatedAt: new Date(nowMs).toISOString(),
3363
3391
  guardian: guardianStats(guardian.dayRows, guardian.hourRows, nowMs),
3364
3392
  metricDays: metricDays(metricRows, nowMs),
3365
- metricHours: metricHours(metricHourRows, nowMs),
3393
+ ...(() => {
3394
+ const hours = metricHours(metricHourRows, nowMs);
3395
+ return {
3396
+ metricHours: hours,
3397
+ metricSixHours: sumMetricHoursIntoSixHours(hours, nowMs)
3398
+ };
3399
+ })(),
3366
3400
  locations: statsItems(locations),
3367
3401
  actors: statsItems(actors),
3368
3402
  source: "conversation_index",
@@ -3596,7 +3630,7 @@ function createConversationRoutes(options) {
3596
3630
  import { Hono as Hono2 } from "hono";
3597
3631
 
3598
3632
  // src/api/code/overview.ts
3599
- import { desc as desc4, eq as eq11, gte as gte2, or as or5, sql as sql11 } from "drizzle-orm";
3633
+ import { desc as desc5, eq as eq11, gte as gte2, or as or5, sql as sql10 } from "drizzle-orm";
3600
3634
  import { z as z5 } from "zod";
3601
3635
  var DAY_MS2 = 24 * 60 * 60 * 1e3;
3602
3636
  var WINDOW_DAYS2 = 30;
@@ -3651,7 +3685,7 @@ function mergeRate(merged, closed) {
3651
3685
  return completed > 0 ? merged / completed : void 0;
3652
3686
  }
3653
3687
  function conversationTreeCostExpr() {
3654
- return sql11`
3688
+ return sql10`
3655
3689
  coalesce((
3656
3690
  SELECT sum(
3657
3691
  CASE
@@ -3680,7 +3714,7 @@ function conversationTreeCostExpr() {
3680
3714
  `;
3681
3715
  }
3682
3716
  function ownedByUserSql(conversationIds, userId) {
3683
- return sql11`EXISTS (
3717
+ return sql10`EXISTS (
3684
3718
  SELECT 1
3685
3719
  FROM unnest(${conversationIds}) AS linked(conversation_id)
3686
3720
  INNER JOIN junior_conversations AS conversations
@@ -3692,7 +3726,7 @@ function ownedByUserSql(conversationIds, userId) {
3692
3726
  }
3693
3727
  function ownershipFilter(userId) {
3694
3728
  if (!userId) return void 0;
3695
- return ownedByUserSql(sql11`${juniorCodeChanges.conversationIds}`, userId);
3729
+ return ownedByUserSql(sql10`${juniorCodeChanges.conversationIds}`, userId);
3696
3730
  }
3697
3731
  async function readCodeWindows(args) {
3698
3732
  const db = getDb();
@@ -3705,10 +3739,10 @@ async function readCodeWindows(args) {
3705
3739
  const activityHourEnd = new Date(args.nowMs);
3706
3740
  activityHourEnd.setUTCMinutes(0, 0, 0);
3707
3741
  const activityHourStart = new Date(
3708
- activityHourEnd.getTime() - 23 * (DAY_MS2 / 24)
3742
+ activityHourEnd.getTime() - (7 * 24 - 1) * (DAY_MS2 / 24)
3709
3743
  );
3710
3744
  const [summaryResult, activityResult, activityHourResult] = await Promise.all([
3711
- db.execute(sql11`
3745
+ db.execute(sql10`
3712
3746
  WITH recent_changes AS (
3713
3747
  SELECT
3714
3748
  ${changes.id},
@@ -3718,7 +3752,7 @@ async function readCodeWindows(args) {
3718
3752
  ${changes.state},
3719
3753
  ${changes.conversationIds} AS conversation_ids
3720
3754
  FROM ${changes}
3721
- ${ownership ? sql11`WHERE ${ownership}` : sql11``}
3755
+ ${ownership ? sql10`WHERE ${ownership}` : sql10``}
3722
3756
  ), change_costs AS (
3723
3757
  SELECT
3724
3758
  recent_changes.id,
@@ -3767,7 +3801,7 @@ async function readCodeWindows(args) {
3767
3801
  )::double precision AS "medianCostUsd"
3768
3802
  FROM recent_changes
3769
3803
  `),
3770
- db.execute(sql11`
3804
+ db.execute(sql10`
3771
3805
  WITH days AS (
3772
3806
  SELECT generate_series(
3773
3807
  date_trunc('day', ${activityStart}::timestamptz AT TIME ZONE 'UTC'),
@@ -3784,18 +3818,18 @@ async function readCodeWindows(args) {
3784
3818
  SELECT ${changes.openedAt} AS event_at, 'created'::text AS kind
3785
3819
  FROM ${changes}
3786
3820
  WHERE ${changes.openedAt} >= ${activityStart}
3787
- ${ownership ? sql11`AND ${ownership}` : sql11``}
3821
+ ${ownership ? sql10`AND ${ownership}` : sql10``}
3788
3822
  UNION ALL
3789
3823
  SELECT ${changes.mergedAt} AS event_at, 'merged'::text AS kind
3790
3824
  FROM ${changes}
3791
3825
  WHERE ${changes.mergedAt} >= ${activityStart}
3792
- ${ownership ? sql11`AND ${ownership}` : sql11``}
3826
+ ${ownership ? sql10`AND ${ownership}` : sql10``}
3793
3827
  UNION ALL
3794
3828
  SELECT ${changes.closedAt} AS event_at, 'closed'::text AS kind
3795
3829
  FROM ${changes}
3796
3830
  WHERE ${changes.state} = 'closed'
3797
3831
  AND ${changes.closedAt} >= ${activityStart}
3798
- ${ownership ? sql11`AND ${ownership}` : sql11``}
3832
+ ${ownership ? sql10`AND ${ownership}` : sql10``}
3799
3833
  ) AS events
3800
3834
  GROUP BY date_trunc('day', event_at AT TIME ZONE 'UTC')
3801
3835
  )
@@ -3808,7 +3842,7 @@ async function readCodeWindows(args) {
3808
3842
  LEFT JOIN daily ON daily.day = days.day
3809
3843
  ORDER BY days.day
3810
3844
  `),
3811
- db.execute(sql11`
3845
+ db.execute(sql10`
3812
3846
  WITH hours AS (
3813
3847
  SELECT generate_series(
3814
3848
  date_trunc('hour', ${activityHourStart}::timestamptz AT TIME ZONE 'UTC'),
@@ -3825,18 +3859,18 @@ async function readCodeWindows(args) {
3825
3859
  SELECT ${changes.openedAt} AS event_at, 'created'::text AS kind
3826
3860
  FROM ${changes}
3827
3861
  WHERE ${changes.openedAt} >= ${activityHourStart}
3828
- ${ownership ? sql11`AND ${ownership}` : sql11``}
3862
+ ${ownership ? sql10`AND ${ownership}` : sql10``}
3829
3863
  UNION ALL
3830
3864
  SELECT ${changes.mergedAt} AS event_at, 'merged'::text AS kind
3831
3865
  FROM ${changes}
3832
3866
  WHERE ${changes.mergedAt} >= ${activityHourStart}
3833
- ${ownership ? sql11`AND ${ownership}` : sql11``}
3867
+ ${ownership ? sql10`AND ${ownership}` : sql10``}
3834
3868
  UNION ALL
3835
3869
  SELECT ${changes.closedAt} AS event_at, 'closed'::text AS kind
3836
3870
  FROM ${changes}
3837
3871
  WHERE ${changes.state} = 'closed'
3838
3872
  AND ${changes.closedAt} >= ${activityHourStart}
3839
- ${ownership ? sql11`AND ${ownership}` : sql11``}
3873
+ ${ownership ? sql10`AND ${ownership}` : sql10``}
3840
3874
  ) AS events
3841
3875
  GROUP BY date_trunc('hour', event_at AT TIME ZONE 'UTC')
3842
3876
  )
@@ -3861,9 +3895,15 @@ async function readCodeWindows(args) {
3861
3895
  open: 0
3862
3896
  }
3863
3897
  );
3898
+ const activityHours3 = z5.array(activityDaySchema).parse(queryRows(activityHourResult));
3864
3899
  return {
3865
3900
  activityDays: z5.array(activityDaySchema).parse(queryRows(activityResult)),
3866
- activityHours: z5.array(activityDaySchema).parse(queryRows(activityHourResult)),
3901
+ activityHours: activityHours3,
3902
+ activitySixHours: sumUtcHoursIntoSixHours({
3903
+ empty: (date) => ({ closed: 0, created: 0, date, merged: 0 }),
3904
+ hours: activityHours3,
3905
+ nowMs: args.nowMs
3906
+ }),
3867
3907
  summary: {
3868
3908
  ...summary,
3869
3909
  mergeRate: mergeRate(summary.merged, summary.closed)
@@ -3879,7 +3919,7 @@ async function readCodeOverview(nowMs = Date.now()) {
3879
3919
  const windows = await readCodeWindows({ nowMs });
3880
3920
  const conversationTreeCost = conversationTreeCostExpr();
3881
3921
  const [repositoryResult, recentChanges] = await Promise.all([
3882
- db.execute(sql11`
3922
+ db.execute(sql10`
3883
3923
  WITH recent_changes AS (
3884
3924
  SELECT
3885
3925
  ${changes.id},
@@ -3956,11 +3996,12 @@ async function readCodeOverview(nowMs = Date.now()) {
3956
3996
  gte2(changes.closedAt, windows.windowStart),
3957
3997
  eq11(changes.state, "open")
3958
3998
  )
3959
- ).orderBy(desc4(changes.updatedAt)).limit(25)
3999
+ ).orderBy(desc5(changes.updatedAt)).limit(25)
3960
4000
  ]);
3961
4001
  return codeOverviewReportSchema.parse({
3962
4002
  activityDays: windows.activityDays,
3963
4003
  activityHours: windows.activityHours,
4004
+ activitySixHours: windows.activitySixHours,
3964
4005
  changes: recentChanges.map((change) => ({
3965
4006
  ...change,
3966
4007
  closedAt: change.closedAt?.toISOString(),
@@ -3989,6 +4030,7 @@ async function readPersonCodeOverview(args) {
3989
4030
  return codePersonReportSchema.parse({
3990
4031
  activityDays: windows.activityDays,
3991
4032
  activityHours: windows.activityHours,
4033
+ activitySixHours: windows.activitySixHours,
3992
4034
  generatedAt: windows.windowEnd.toISOString(),
3993
4035
  summary: windows.summary,
3994
4036
  windowEnd: windows.windowEnd.toISOString(),
@@ -4010,7 +4052,7 @@ function createCodeRoutes() {
4010
4052
  import { Hono as Hono3 } from "hono";
4011
4053
 
4012
4054
  // src/api/locations/query.ts
4013
- 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";
4055
+ import { and as and11, asc as asc3, desc as desc6, eq as eq12, gte as gte3, isNull as isNull5, sql as sql11 } from "drizzle-orm";
4014
4056
  import { alias as alias4 } from "drizzle-orm/pg-core";
4015
4057
 
4016
4058
  // src/api/conversations/reporting.ts
@@ -4182,16 +4224,16 @@ async function directoryRows(db) {
4182
4224
  ).where(topLevelWhere()).groupBy(...locationGroupBy());
4183
4225
  }
4184
4226
  async function directoryActivityRows(db, start, hourStart) {
4185
- const day = sql12`TO_CHAR(
4227
+ const day = sql11`TO_CHAR(
4186
4228
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
4187
4229
  'YYYY-MM-DD'
4188
4230
  )`;
4189
- const hour = sql12`TO_CHAR(
4231
+ const hour = sql11`TO_CHAR(
4190
4232
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
4191
4233
  'YYYY-MM-DD"T"HH24'
4192
4234
  )`;
4193
4235
  const select = {
4194
- conversations: sql12`COUNT(*)::integer`,
4236
+ conversations: sql11`COUNT(*)::integer`,
4195
4237
  visibility: juniorDestinations.visibility
4196
4238
  };
4197
4239
  const [dayRows, hourRows] = await Promise.all([
@@ -4243,15 +4285,29 @@ function directoryActivityDays(rows, nowMs) {
4243
4285
  }
4244
4286
  function directoryActivityHours(rows, nowMs) {
4245
4287
  return fillUtcHours({
4288
+ count: WINDOW_SEVEN_DAY_HOURS,
4246
4289
  empty: emptyLocationActivityDay,
4247
4290
  nowMs,
4248
4291
  rows: accumulateLocationActivity(rows)
4249
4292
  });
4250
4293
  }
4294
+ function directoryActivitySixHours(rows, nowMs) {
4295
+ const hours = fillUtcHours({
4296
+ count: WINDOW_SEVEN_DAY_HOURS,
4297
+ empty: emptyLocationActivityDay,
4298
+ nowMs,
4299
+ rows: accumulateLocationActivity(rows)
4300
+ });
4301
+ return sumUtcHoursIntoSixHours({
4302
+ empty: emptyLocationActivityDay,
4303
+ hours,
4304
+ nowMs
4305
+ });
4306
+ }
4251
4307
  async function readLocationDirectoryFromSql() {
4252
4308
  const nowMs = Date.now();
4253
4309
  const { end, start } = trailingUtcDayWindow(nowMs, ACTIVITY_DAYS2);
4254
- const hourWindow = trailingUtcHourWindow(nowMs);
4310
+ const hourWindow = trailingUtcHourWindow(nowMs, WINDOW_SEVEN_DAY_HOURS);
4255
4311
  const [rows, activity] = await Promise.all([
4256
4312
  directoryRows(getDb()),
4257
4313
  directoryActivityRows(getDb(), start, hourWindow.start)
@@ -4269,6 +4325,7 @@ async function readLocationDirectoryFromSql() {
4269
4325
  return {
4270
4326
  activityDays: directoryActivityDays(activity.dayRows, nowMs),
4271
4327
  activityHours: directoryActivityHours(activity.hourRows, nowMs),
4328
+ activitySixHours: directoryActivitySixHours(activity.hourRows, nowMs),
4272
4329
  generatedAt: new Date(nowMs).toISOString(),
4273
4330
  locations: locations.sort(
4274
4331
  (left, right) => Date.parse(right.lastSeenAt) - Date.parse(left.lastSeenAt) || right.conversations - left.conversations || left.label.localeCompare(right.label)
@@ -4286,7 +4343,7 @@ async function recentLocationRows(db, locationId) {
4286
4343
  createdAt: juniorConversations.createdAt,
4287
4344
  destinationId: juniorDestinations.id,
4288
4345
  durationMs: juniorConversations.durationMs,
4289
- email: sql12`COALESCE(
4346
+ email: sql11`COALESCE(
4290
4347
  ${juniorUsers.primaryEmailNormalized},
4291
4348
  ${juniorIdentities.email}
4292
4349
  )`,
@@ -4295,7 +4352,7 @@ async function recentLocationRows(db, locationId) {
4295
4352
  fullName: juniorUsers.displayName,
4296
4353
  handle: juniorIdentities.handle,
4297
4354
  lastActivityAt: juniorConversations.lastActivityAt,
4298
- providerSubjectId: sql12`CASE
4355
+ providerSubjectId: sql11`CASE
4299
4356
  WHEN ${juniorIdentities.provider} = 'slack'
4300
4357
  THEN ${juniorIdentities.providerSubjectId}
4301
4358
  ELSE NULL
@@ -4311,20 +4368,20 @@ async function recentLocationRows(db, locationId) {
4311
4368
  juniorIdentities,
4312
4369
  eq12(juniorIdentities.id, juniorConversations.actorIdentityId)
4313
4370
  ).leftJoin(juniorUsers, eq12(juniorUsers.id, juniorIdentities.userId)).where(publicLocationWhere(locationId)).orderBy(
4314
- desc5(juniorConversations.lastActivityAt),
4371
+ desc6(juniorConversations.lastActivityAt),
4315
4372
  asc3(juniorConversations.conversationId)
4316
4373
  ).limit(RECENT_LIMIT);
4317
4374
  }
4318
4375
  async function readLocationDetailFromSql(locationId, options = {}) {
4319
4376
  const nowMs = Date.now();
4320
4377
  const { end, start } = trailingUtcDayWindow(nowMs, ACTIVITY_DAYS2);
4321
- const hourWindow = trailingUtcHourWindow(nowMs);
4378
+ const hourWindow = trailingUtcHourWindow(nowMs, WINDOW_SEVEN_DAY_HOURS);
4322
4379
  const where = publicLocationWhere(locationId);
4323
- const activityDate = sql12`TO_CHAR(
4380
+ const activityDate = sql11`TO_CHAR(
4324
4381
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
4325
4382
  'YYYY-MM-DD'
4326
4383
  )`;
4327
- const activityHour = sql12`TO_CHAR(
4384
+ const activityHour = sql11`TO_CHAR(
4328
4385
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
4329
4386
  'YYYY-MM-DD"T"HH24'
4330
4387
  )`;
@@ -4457,6 +4514,7 @@ async function readLocationDetailFromSql(locationId, options = {}) {
4457
4514
  ...location,
4458
4515
  activityDays: activity,
4459
4516
  activityHours: hourlyActivity,
4517
+ activitySixHours: activitySixHours(hourlyActivity, nowMs),
4460
4518
  actors: actors.sort(
4461
4519
  (left, right) => right.conversations - left.conversations || left.label.localeCompare(right.label)
4462
4520
  ),
@@ -4539,10 +4597,10 @@ async function readPeopleCode(email) {
4539
4597
  }
4540
4598
 
4541
4599
  // src/api/people/list.query.ts
4542
- import { and as and13, eq as eq14, gte as gte4, sql as sql14 } from "drizzle-orm";
4600
+ import { and as and13, eq as eq14, gte as gte4, sql as sql13 } from "drizzle-orm";
4543
4601
 
4544
4602
  // src/api/people/shared.ts
4545
- 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";
4603
+ import { and as and12, asc as asc4, desc as desc7, eq as eq13, isNull as isNull6, notExists, or as or6, sql as sql12 } from "drizzle-orm";
4546
4604
  import { alias as alias5 } from "drizzle-orm/pg-core";
4547
4605
  var RECENT_LIMIT2 = 25;
4548
4606
  var ACTIVITY_DAYS3 = 365;
@@ -4633,11 +4691,20 @@ function activityDays2(days, nowMs) {
4633
4691
  }
4634
4692
  function activityHours2(hours, nowMs) {
4635
4693
  return fillUtcHours({
4694
+ count: WINDOW_SEVEN_DAY_HOURS,
4636
4695
  empty: emptyActivityDay,
4637
4696
  nowMs,
4638
4697
  rows: hours
4639
4698
  });
4640
4699
  }
4700
+ function activitySixHours2(hours, nowMs) {
4701
+ const series = hours instanceof Map ? activityHours2(hours, nowMs) : [...hours];
4702
+ return sumUtcHoursIntoSixHours({
4703
+ empty: emptyActivityDay,
4704
+ hours: series,
4705
+ nowMs
4706
+ });
4707
+ }
4641
4708
  function statsItems2(map) {
4642
4709
  return [...map.values()].sort(
4643
4710
  (left, right) => right.conversations - left.conversations || right.durationMs - left.durationMs || left.label.localeCompare(right.label)
@@ -4648,7 +4715,7 @@ function verifiedActorWhere(email) {
4648
4715
  return and12(
4649
4716
  eq13(juniorIdentities.provider, "slack"),
4650
4717
  eq13(juniorIdentities.emailVerified, true),
4651
- sql13`${juniorUsers.primaryEmailNormalized} IS NOT NULL`,
4718
+ sql12`${juniorUsers.primaryEmailNormalized} IS NOT NULL`,
4652
4719
  normalizedEmail ? eq13(juniorUsers.primaryEmailNormalized, normalizedEmail) : void 0
4653
4720
  );
4654
4721
  }
@@ -4677,7 +4744,7 @@ async function recentActorRows(email) {
4677
4744
  juniorDestinations,
4678
4745
  eq13(juniorDestinations.id, juniorConversations.destinationId)
4679
4746
  ).where(verifiedActorWhere(email)).orderBy(
4680
- desc6(juniorConversations.lastActivityAt),
4747
+ desc7(juniorConversations.lastActivityAt),
4681
4748
  asc4(juniorConversations.conversationId)
4682
4749
  ).limit(RECENT_LIMIT2);
4683
4750
  }
@@ -4705,6 +4772,14 @@ function directoryActivityDays2(rows, nowMs) {
4705
4772
  }
4706
4773
  function directoryActivityHours2(rows, nowMs) {
4707
4774
  return fillUtcHours({
4775
+ count: WINDOW_SEVEN_DAY_HOURS,
4776
+ empty: emptyDirectoryDay,
4777
+ nowMs,
4778
+ rows: new Map(rows.map((row) => [row.date, row]))
4779
+ });
4780
+ }
4781
+ function directoryActivitySixHours2(rows, nowMs) {
4782
+ return fillUtcSixHours({
4708
4783
  empty: emptyDirectoryDay,
4709
4784
  nowMs,
4710
4785
  rows: new Map(rows.map((row) => [row.date, row]))
@@ -4782,33 +4857,40 @@ function buildActorWindows(args) {
4782
4857
  async function readPeopleListFromSql() {
4783
4858
  const nowMs = Date.now();
4784
4859
  const { end, start } = trailingUtcDayWindow(nowMs, DIRECTORY_ACTIVITY_DAYS);
4785
- const activityDate = sql14`TO_CHAR(
4860
+ const activityDate = sql13`TO_CHAR(
4786
4861
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
4787
4862
  'YYYY-MM-DD'
4788
4863
  )`;
4789
- const activityHour = sql14`TO_CHAR(
4864
+ const activityHour = sql13`TO_CHAR(
4790
4865
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
4791
4866
  'YYYY-MM-DD"T"HH24'
4792
4867
  )`;
4793
- const hourWindow = trailingUtcHourWindow(nowMs);
4868
+ const hourWindow = trailingUtcHourWindow(nowMs, WINDOW_SEVEN_DAY_HOURS);
4869
+ const sixHourWindow = trailingUtcSixHourWindow(nowMs);
4794
4870
  const dayMetricStart = trailingUtcDayWindow(nowMs, DAY_METRIC_LOOKBACK).start;
4795
4871
  const hourMetricStart = trailingUtcHourWindow(
4796
4872
  nowMs,
4797
4873
  HOUR_METRIC_LOOKBACK
4798
4874
  ).start;
4799
4875
  const metricsJoin = peopleTreeMetricsJoin();
4876
+ const activitySixHour = sql13`TO_CHAR(
4877
+ date_trunc('day', ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC')
4878
+ + (FLOOR(EXTRACT(HOUR FROM ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC') / 6) * INTERVAL '6 hours'),
4879
+ 'YYYY-MM-DD"T"HH24'
4880
+ )`;
4800
4881
  const [
4801
4882
  rows,
4802
4883
  activityRows,
4803
4884
  activityHourRows,
4885
+ activitySixHourRows,
4804
4886
  dayMetricRows,
4805
4887
  hourMetricRows
4806
4888
  ] = await Promise.all([
4807
4889
  getDb().select({
4808
4890
  email: juniorUsers.primaryEmailNormalized,
4809
4891
  fullName: juniorUsers.displayName,
4810
- slackUserId: sql14`MAX(${juniorIdentities.providerSubjectId})`,
4811
- slackUserName: sql14`MAX(${juniorIdentities.handle})`,
4892
+ slackUserId: sql13`MAX(${juniorIdentities.providerSubjectId})`,
4893
+ slackUserName: sql13`MAX(${juniorIdentities.handle})`,
4812
4894
  activeDays: conversationActiveDaysColumn(),
4813
4895
  ...peopleTreeAggregateColumns,
4814
4896
  ...conversationRangeColumns()
@@ -4817,8 +4899,8 @@ async function readPeopleListFromSql() {
4817
4899
  eq14(juniorIdentities.id, juniorConversations.actorIdentityId)
4818
4900
  ).innerJoin(juniorUsers, eq14(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(verifiedActorWhere()).groupBy(juniorUsers.primaryEmailNormalized, juniorUsers.displayName),
4819
4901
  getDb().select({
4820
- activePeople: sql14`COUNT(DISTINCT ${juniorUsers.id})::int`,
4821
- conversations: sql14`COUNT(*)::int`,
4902
+ activePeople: sql13`COUNT(DISTINCT ${juniorUsers.id})::int`,
4903
+ conversations: sql13`COUNT(*)::int`,
4822
4904
  date: activityDate
4823
4905
  }).from(juniorConversations).innerJoin(
4824
4906
  juniorIdentities,
@@ -4830,8 +4912,8 @@ async function readPeopleListFromSql() {
4830
4912
  )
4831
4913
  ).groupBy(activityDate),
4832
4914
  getDb().select({
4833
- activePeople: sql14`COUNT(DISTINCT ${juniorUsers.id})::int`,
4834
- conversations: sql14`COUNT(*)::int`,
4915
+ activePeople: sql13`COUNT(DISTINCT ${juniorUsers.id})::int`,
4916
+ conversations: sql13`COUNT(*)::int`,
4835
4917
  date: activityHour
4836
4918
  }).from(juniorConversations).innerJoin(
4837
4919
  juniorIdentities,
@@ -4842,6 +4924,19 @@ async function readPeopleListFromSql() {
4842
4924
  gte4(juniorConversations.lastActivityAt, hourWindow.start)
4843
4925
  )
4844
4926
  ).groupBy(activityHour),
4927
+ getDb().select({
4928
+ activePeople: sql13`COUNT(DISTINCT ${juniorUsers.id})::int`,
4929
+ conversations: sql13`COUNT(*)::int`,
4930
+ date: activitySixHour
4931
+ }).from(juniorConversations).innerJoin(
4932
+ juniorIdentities,
4933
+ eq14(juniorIdentities.id, juniorConversations.actorIdentityId)
4934
+ ).innerJoin(juniorUsers, eq14(juniorUsers.id, juniorIdentities.userId)).where(
4935
+ and13(
4936
+ verifiedActorWhere(),
4937
+ gte4(juniorConversations.lastActivityAt, sixHourWindow.start)
4938
+ )
4939
+ ).groupBy(activitySixHour),
4845
4940
  getDb().select({
4846
4941
  email: juniorUsers.primaryEmailNormalized,
4847
4942
  date: activityDate,
@@ -4926,6 +5021,7 @@ async function readPeopleListFromSql() {
4926
5021
  return {
4927
5022
  activityDays: directoryActivityDays2(activityRows, nowMs),
4928
5023
  activityHours: directoryActivityHours2(activityHourRows, nowMs),
5024
+ activitySixHours: directoryActivitySixHours2(activitySixHourRows, nowMs),
4929
5025
  generatedAt: new Date(nowMs).toISOString(),
4930
5026
  people: people.sort(
4931
5027
  (left, right) => Date.parse(right.lastSeenAt) - Date.parse(left.lastSeenAt) || right.conversations - left.conversations || left.actor.email.localeCompare(right.actor.email)
@@ -4952,7 +5048,7 @@ async function readPeoplePluginReports(args) {
4952
5048
  source: "plugins"
4953
5049
  });
4954
5050
  }
4955
- const { getPluginProfileReports } = await import("./agent-hooks-DWY3MZZ7.js");
5051
+ const { getPluginProfileReports } = await import("./agent-hooks-VIBTIP5F.js");
4956
5052
  return pluginOperationalReportFeedSchema.parse({
4957
5053
  generatedAt: new Date(nowMs).toISOString(),
4958
5054
  reports: await getPluginProfileReports({
@@ -4965,7 +5061,7 @@ async function readPeoplePluginReports(args) {
4965
5061
  }
4966
5062
 
4967
5063
  // src/api/people/profile.query.ts
4968
- import { and as and14, eq as eq15, gte as gte5, sql as sql15 } from "drizzle-orm";
5064
+ import { and as and14, eq as eq15, gte as gte5, sql as sql14 } from "drizzle-orm";
4969
5065
  function emptyProfile(email, nowMs) {
4970
5066
  const end = new Date(nowMs);
4971
5067
  end.setUTCHours(0, 0, 0, 0);
@@ -4974,6 +5070,7 @@ function emptyProfile(email, nowMs) {
4974
5070
  return {
4975
5071
  activityDays: activityDays2(/* @__PURE__ */ new Map(), nowMs),
4976
5072
  activityHours: activityHours2(/* @__PURE__ */ new Map(), nowMs),
5073
+ activitySixHours: activitySixHours2(/* @__PURE__ */ new Map(), nowMs),
4977
5074
  generatedAt: new Date(nowMs).toISOString(),
4978
5075
  locations: [],
4979
5076
  recentConversations: [],
@@ -5001,7 +5098,7 @@ function addAggregate2(map, label, row) {
5001
5098
  map.set(label, item);
5002
5099
  }
5003
5100
  function surfaceExpression() {
5004
- return sql15`CASE
5101
+ return sql14`CASE
5005
5102
  WHEN ${juniorConversations.source} IN ('api', 'scheduler', 'slack')
5006
5103
  THEN ${juniorConversations.source}
5007
5104
  WHEN ${juniorConversations.conversationId} LIKE 'slack:%' THEN 'slack'
@@ -5030,22 +5127,22 @@ async function readPeopleProfileFromSql(email, options = {}) {
5030
5127
  const where = verifiedActorWhere(normalizedEmail);
5031
5128
  const metricsJoin = peopleTreeMetricsJoin();
5032
5129
  const surface = surfaceExpression();
5033
- const activityDate = sql15`TO_CHAR(
5130
+ const activityDate = sql14`TO_CHAR(
5034
5131
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
5035
5132
  'YYYY-MM-DD'
5036
5133
  )`;
5037
- const activityHour = sql15`TO_CHAR(
5134
+ const activityHour = sql14`TO_CHAR(
5038
5135
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
5039
5136
  'YYYY-MM-DD"T"HH24'
5040
5137
  )`;
5041
- const channel = sql15`SPLIT_PART(${juniorConversations.conversationId}, ':', 2)`;
5042
- const hourWindow = trailingUtcHourWindow(nowMs);
5138
+ const channel = sql14`SPLIT_PART(${juniorConversations.conversationId}, ':', 2)`;
5139
+ const hourWindow = trailingUtcHourWindow(nowMs, 7 * 24);
5043
5140
  const [totalsRows, dayRows, hourRows, locationRows, surfaceRows, recentRows] = await Promise.all([
5044
5141
  getDb().select({
5045
5142
  email: juniorUsers.primaryEmailNormalized,
5046
5143
  fullName: juniorUsers.displayName,
5047
- slackUserId: sql15`MAX(${juniorIdentities.providerSubjectId})`,
5048
- slackUserName: sql15`MAX(${juniorIdentities.handle})`,
5144
+ slackUserId: sql14`MAX(${juniorIdentities.providerSubjectId})`,
5145
+ slackUserName: sql14`MAX(${juniorIdentities.handle})`,
5049
5146
  activeDays: conversationActiveDaysColumn(),
5050
5147
  ...peopleTreeAggregateColumns
5051
5148
  }).from(juniorConversations).innerJoin(
@@ -5148,6 +5245,7 @@ async function readPeopleProfileFromSql(email, options = {}) {
5148
5245
  return {
5149
5246
  activityDays: activityDays2(days, nowMs),
5150
5247
  activityHours: activityHours2(hours, nowMs),
5248
+ activitySixHours: activitySixHours2(hours, nowMs),
5151
5249
  generatedAt: new Date(nowMs).toISOString(),
5152
5250
  locations: statsItems2(locations),
5153
5251
  recentConversations: recentRows.map(
@@ -5180,7 +5278,7 @@ async function readPeopleProfile(email, options = {}) {
5180
5278
  }
5181
5279
 
5182
5280
  // src/api/people/spend.query.ts
5183
- import { and as and15, eq as eq16, gte as gte6, lte as lte2, sql as sql16 } from "drizzle-orm";
5281
+ import { and as and15, eq as eq16, gte as gte6, lte as lte2, sql as sql15 } from "drizzle-orm";
5184
5282
  var SEVEN_DAY_OFFSET = 6;
5185
5283
  var THIRTY_DAY_OFFSET = 29;
5186
5284
  function addUsd3(current, next) {
@@ -5199,7 +5297,7 @@ function spendWindow(nowMs) {
5199
5297
  async function readPersonalSpendFromSql(email, nowMs = Date.now()) {
5200
5298
  const normalizedEmail = normalizeEmail(email);
5201
5299
  const { end, sevenDayStart, thirtyDayStart } = spendWindow(nowMs);
5202
- const activityDate = sql16`TO_CHAR(
5300
+ const activityDate = sql15`TO_CHAR(
5203
5301
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
5204
5302
  'YYYY-MM-DD'
5205
5303
  )`;
@@ -5320,7 +5418,7 @@ import { Hono as Hono5 } from "hono";
5320
5418
 
5321
5419
  // src/personal-tokens/store.ts
5322
5420
  import { createHash, randomBytes, randomUUID } from "crypto";
5323
- import { and as and16, desc as desc7, eq as eq17, gt, isNull as isNull7 } from "drizzle-orm";
5421
+ import { and as and16, desc as desc8, eq as eq17, gt, isNull as isNull7 } from "drizzle-orm";
5324
5422
  var TOKEN_PREFIX = "jr_pat_";
5325
5423
  var TOKEN_SUFFIX_LENGTH = 8;
5326
5424
  var DEFAULT_TOKEN_LIFETIME_MS = 90 * 24 * 60 * 60 * 1e3;
@@ -5362,7 +5460,7 @@ async function listPersonalTokens(email, now = /* @__PURE__ */ new Date()) {
5362
5460
  isNull7(juniorApiTokens.revokedAt),
5363
5461
  gt(juniorApiTokens.expiresAt, now)
5364
5462
  )
5365
- ).orderBy(desc7(juniorApiTokens.createdAt));
5463
+ ).orderBy(desc8(juniorApiTokens.createdAt));
5366
5464
  return rows.map(metadata);
5367
5465
  }
5368
5466
  async function revokePersonalToken(args) {
@@ -5784,7 +5882,7 @@ function readDescriptionText(home) {
5784
5882
  }
5785
5883
  }
5786
5884
  async function readSkillReports() {
5787
- const { discoverSkills } = await import("./skills-AR3WD6BX.js");
5885
+ const { discoverSkills } = await import("./skills-QTN73DN5.js");
5788
5886
  const skills = await discoverSkills();
5789
5887
  return skillReportsSchema.parse(
5790
5888
  skills.map((skill) => ({
@@ -5794,7 +5892,7 @@ async function readSkillReports() {
5794
5892
  );
5795
5893
  }
5796
5894
  async function readPlugins() {
5797
- const { pluginCatalogRuntime } = await import("./catalog-runtime-NAD44W5K.js");
5895
+ const { pluginCatalogRuntime } = await import("./catalog-runtime-6E6SGRZK.js");
5798
5896
  return pluginsSchema.parse(
5799
5897
  pluginCatalogRuntime.getProviders().map((plugin) => ({
5800
5898
  configKeys: plugin.manifest.configKeys ?? [],
@@ -5807,7 +5905,7 @@ async function readPlugins() {
5807
5905
  async function readRuntimeInfoReport() {
5808
5906
  const [{ homeDir }, { pluginCatalogRuntime }, plugins, skills] = await Promise.all([
5809
5907
  import("./discovery-DWVDM7UK.js"),
5810
- import("./catalog-runtime-NAD44W5K.js"),
5908
+ import("./catalog-runtime-6E6SGRZK.js"),
5811
5909
  readPlugins(),
5812
5910
  readSkillReports()
5813
5911
  ]);
@@ -5823,7 +5921,7 @@ async function readRuntimeInfoReport() {
5823
5921
  }
5824
5922
  async function readPluginOperationalReportFeed() {
5825
5923
  const nowMs = Date.now();
5826
- const { getPluginOperationalReports } = await import("./agent-hooks-DWY3MZZ7.js");
5924
+ const { getPluginOperationalReports } = await import("./agent-hooks-VIBTIP5F.js");
5827
5925
  return pluginOperationalReportFeedSchema.parse({
5828
5926
  source: "plugins",
5829
5927
  generatedAt: new Date(nowMs).toISOString(),