@sentry/junior 0.126.1 → 0.128.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 (124) hide show
  1. package/dist/{agent-hooks-U5YGLX6Y.js → agent-hooks-F75ANGBV.js} +9 -9
  2. package/dist/api/people/spend.d.ts +4 -0
  3. package/dist/api/people/spend.query.d.ts +3 -0
  4. package/dist/api/schema/person.d.ts +9 -0
  5. package/dist/api/schema.d.ts +2 -2
  6. package/dist/api/schema.js +3 -1
  7. package/dist/api.js +141 -40
  8. package/dist/app.js +289 -146
  9. package/dist/{catalog-runtime-OUPLWD7F.js → catalog-runtime-ZPSA5QM2.js} +6 -6
  10. package/dist/chat/agent-dispatch/context.d.ts +17 -0
  11. package/dist/chat/agent-dispatch/store.d.ts +1 -1
  12. package/dist/chat/agent-dispatch/work.d.ts +1 -1
  13. package/dist/chat/credentials/context.d.ts +27 -0
  14. package/dist/chat/credentials/subject.d.ts +15 -0
  15. package/dist/chat/event-tasks/ingest.d.ts +9 -0
  16. package/dist/chat/event-tasks/store.d.ts +15 -0
  17. package/dist/chat/event-tasks/tool-support.d.ts +140 -0
  18. package/dist/chat/event-tasks/types.d.ts +44 -0
  19. package/dist/chat/plugins/agent-hooks.d.ts +4 -2
  20. package/dist/chat/plugins/viewer.d.ts +16 -0
  21. package/dist/chat/resource-events/catalog.d.ts +21 -0
  22. package/dist/chat/resource-events/ingest.d.ts +2 -1
  23. package/dist/chat/resource-events/notification.d.ts +2 -2
  24. package/dist/chat/resource-events/store.d.ts +11 -9
  25. package/dist/chat/resource-events/tool-support.d.ts +10 -0
  26. package/dist/chat/resource-events/workspace.d.ts +4 -0
  27. package/dist/chat/sandbox/command-result.d.ts +3 -22
  28. package/dist/chat/sandbox/egress/schemas.d.ts +11 -0
  29. package/dist/chat/services/guardian-action-policy.d.ts +1 -1
  30. package/dist/chat/slack/dispatch-turn.d.ts +1 -1
  31. package/dist/chat/slack/tools/canvas/create.d.ts +0 -16
  32. package/dist/chat/slack/tools/canvas/edit.d.ts +0 -16
  33. package/dist/chat/slack/tools/canvas/read.d.ts +0 -16
  34. package/dist/chat/slack/tools/canvas/write.d.ts +0 -16
  35. package/dist/chat/slack/tools/channel-list-messages.d.ts +0 -16
  36. package/dist/chat/slack/tools/conversation-search.d.ts +0 -16
  37. package/dist/chat/slack/tools/list/add-items.d.ts +0 -16
  38. package/dist/chat/slack/tools/list/create.d.ts +0 -16
  39. package/dist/chat/slack/tools/list/get-items.d.ts +0 -16
  40. package/dist/chat/slack/tools/list/update-item.d.ts +0 -16
  41. package/dist/chat/slack/tools/message-add-reaction.d.ts +0 -16
  42. package/dist/chat/slack/tools/public-search.d.ts +0 -16
  43. package/dist/chat/slack/tools/send-files.d.ts +10 -28
  44. package/dist/chat/slack/tools/thread-read.d.ts +0 -16
  45. package/dist/chat/slack/tools/user-lookup.d.ts +0 -16
  46. package/dist/chat/task-execution/slack-work.d.ts +4 -4
  47. package/dist/chat/tool-support/action-review.d.ts +1 -1
  48. package/dist/chat/tool-support/structured-result.d.ts +17 -46
  49. package/dist/chat/tool-support/text-range-result.d.ts +8 -32
  50. package/dist/chat/tool-support/zod-tool.d.ts +6 -7
  51. package/dist/chat/tools/create-event-task.d.ts +65 -0
  52. package/dist/chat/tools/definition.d.ts +4 -0
  53. package/dist/chat/tools/delete-event-task.d.ts +57 -0
  54. package/dist/chat/tools/event-tasks.d.ts +5 -0
  55. package/dist/chat/tools/handoff/tool.d.ts +0 -16
  56. package/dist/chat/tools/list-event-tasks.d.ts +55 -0
  57. package/dist/chat/tools/list-resource-event-subscriptions.d.ts +42 -0
  58. package/dist/chat/tools/query-conversation-events.d.ts +0 -16
  59. package/dist/chat/tools/resource-events.d.ts +2 -1
  60. package/dist/chat/tools/runtime/report-progress.d.ts +0 -16
  61. package/dist/chat/tools/sandbox/edit-file.d.ts +0 -23
  62. package/dist/chat/tools/sandbox/file-utils.d.ts +2 -17
  63. package/dist/chat/tools/sandbox/find-files.d.ts +5 -8
  64. package/dist/chat/tools/sandbox/grep.d.ts +1 -4
  65. package/dist/chat/tools/sandbox/list-dir.d.ts +1 -4
  66. package/dist/chat/tools/search-resource-event-types.d.ts +44 -0
  67. package/dist/chat/tools/search-tools.d.ts +0 -16
  68. package/dist/chat/tools/skill/load-skill.d.ts +0 -20
  69. package/dist/chat/tools/skill/search-mcp-tools.d.ts +0 -16
  70. package/dist/chat/tools/stop-watching-resources.d.ts +28 -0
  71. package/dist/chat/tools/system-time.d.ts +0 -16
  72. package/dist/chat/tools/types.d.ts +8 -4
  73. package/dist/chat/tools/update-event-task.d.ts +66 -0
  74. package/dist/chat/tools/watch-resource-events.d.ts +59 -0
  75. package/dist/chat/tools/web/fetch-content.d.ts +0 -2
  76. package/dist/chat/tools/web/fetch-tool.d.ts +0 -16
  77. package/dist/chat/tools/web/image-generate.d.ts +0 -16
  78. package/dist/chat/tools/web/search.d.ts +0 -16
  79. package/dist/{chunk-QVSYR5CV.js → chunk-2HTHX6XV.js} +4 -4
  80. package/dist/{chunk-Y2QRKPI7.js → chunk-3PKF6YNU.js} +1 -1
  81. package/dist/{chunk-GLNB2R42.js → chunk-5KKIBIIP.js} +12 -12
  82. package/dist/{chunk-W3U3YQYI.js → chunk-77VDLF3Z.js} +18 -1
  83. package/dist/{chunk-YZHA2L7P.js → chunk-A76LKS5W.js} +230 -102
  84. package/dist/{chunk-6ZBSTNYN.js → chunk-AFJF3RGU.js} +9 -0
  85. package/dist/{chunk-PD6J33TO.js → chunk-B6E3YA2H.js} +1 -1
  86. package/dist/{chunk-S4LM6UB7.js → chunk-B7FPRGUJ.js} +3 -3
  87. package/dist/{chunk-R3GXQJEE.js → chunk-BY43CEXN.js} +2 -2
  88. package/dist/{chunk-HDSDCEPK.js → chunk-EPBBYMNE.js} +1 -1
  89. package/dist/{chunk-YFE6VNHU.js → chunk-FJEIX3AH.js} +2 -2
  90. package/dist/{chunk-F2ARYRKC.js → chunk-G6XQODHM.js} +1 -1
  91. package/dist/{chunk-KBW6J5GA.js → chunk-HBFQLSGV.js} +4 -4
  92. package/dist/{chunk-YUPNY2HZ.js → chunk-JDCPDJ54.js} +2 -2
  93. package/dist/{chunk-WIIPHGJY.js → chunk-K5ZB3WWH.js} +2 -2
  94. package/dist/{chunk-OG6E44DH.js → chunk-KNRODVH2.js} +6 -6
  95. package/dist/{chunk-W3JHZHAN.js → chunk-KTGJAWRO.js} +1 -1
  96. package/dist/{chunk-7VF3JAVF.js → chunk-NHWE6Y7G.js} +7 -7
  97. package/dist/{chunk-HXWOZ4HG.js → chunk-OLGB5Y7R.js} +2 -2
  98. package/dist/{chunk-QMK2VF6K.js → chunk-PBWUUVVG.js} +1 -1
  99. package/dist/{chunk-7ZMY4GCG.js → chunk-RYWMDDWK.js} +1 -1
  100. package/dist/{chunk-S4PUICSB.js → chunk-SHMHHXD5.js} +34 -5
  101. package/dist/{chunk-JKV244BI.js → chunk-WZ365SQC.js} +1 -1
  102. package/dist/{chunk-SD2VFSN6.js → chunk-YY6CVET7.js} +1428 -1116
  103. package/dist/{chunk-U36WL4OL.js → chunk-Z4KTQMWW.js} +1 -1
  104. package/dist/cli/chat.js +27 -27
  105. package/dist/cli/check.js +7 -7
  106. package/dist/cli/plugins.js +13 -13
  107. package/dist/cli/snapshot-create.js +10 -10
  108. package/dist/cli/upgrade.js +8 -8
  109. package/dist/db/schema/event-tasks.d.ts +161 -0
  110. package/dist/db/schema.d.ts +163 -1
  111. package/dist/{db-FQID26JW.js → db-FYJYPAKG.js} +7 -7
  112. package/dist/instrumentation.js +4 -4
  113. package/dist/nitro.js +2 -2
  114. package/dist/{oauth-callback-server-Z5MHHKFD.js → oauth-callback-server-W3PPIHCS.js} +18 -18
  115. package/dist/{runner-PGPGKYSF.js → runner-5NOFUYKR.js} +11 -11
  116. package/dist/{sandbox-egress-signals-CDFAP67O.js → sandbox-egress-signals-A5HWIQH4.js} +2 -2
  117. package/dist/{skills-BCQHR636.js → skills-ENIBKF5V.js} +7 -7
  118. package/dist/{validation-QP3FYBLZ.js → validation-BHLBOO6K.js} +7 -7
  119. package/dist/version.js +1 -1
  120. package/migrations/0015_magical_ezekiel_stane.sql +11 -0
  121. package/migrations/meta/0015_snapshot.json +1360 -0
  122. package/migrations/meta/_journal.json +7 -0
  123. package/package.json +5 -5
  124. package/dist/chat/plugins/viewer-actors.d.ts +0 -6
@@ -11,19 +11,19 @@ import {
11
11
  getPlugins,
12
12
  setPlugins,
13
13
  validatePlugins
14
- } from "./chunk-YZHA2L7P.js";
15
- import "./chunk-S4LM6UB7.js";
16
- import "./chunk-S4PUICSB.js";
17
- import "./chunk-F2ARYRKC.js";
18
- import "./chunk-WIIPHGJY.js";
14
+ } from "./chunk-A76LKS5W.js";
15
+ import "./chunk-B7FPRGUJ.js";
16
+ import "./chunk-SHMHHXD5.js";
17
+ import "./chunk-G6XQODHM.js";
18
+ import "./chunk-K5ZB3WWH.js";
19
19
  import "./chunk-VFUK3X5B.js";
20
- import "./chunk-U36WL4OL.js";
20
+ import "./chunk-Z4KTQMWW.js";
21
21
  import "./chunk-HZF5P5UN.js";
22
22
  import "./chunk-F3B2YJ76.js";
23
- import "./chunk-PD6J33TO.js";
23
+ import "./chunk-B6E3YA2H.js";
24
24
  import "./chunk-6GWA276C.js";
25
- import "./chunk-7ZMY4GCG.js";
26
- import "./chunk-W3JHZHAN.js";
25
+ import "./chunk-RYWMDDWK.js";
26
+ import "./chunk-KTGJAWRO.js";
27
27
  import "./chunk-MLKGABMK.js";
28
28
  export {
29
29
  PluginHookDeniedError,
@@ -0,0 +1,4 @@
1
+ import { type ApiRoute } from "../route";
2
+ import { personalSpendReportSchema } from "../schema/person";
3
+ /** Create the self-only spend route with an app-scoped five-minute cache. */
4
+ export declare function createPersonalSpendRoute(): ApiRoute<typeof personalSpendReportSchema>;
@@ -0,0 +1,3 @@
1
+ import type { PersonalSpendReport } from "../schema/person";
2
+ /** Read one viewer's rolling model spend with one bounded aggregate query. */
3
+ export declare function readPersonalSpendFromSql(email: string, nowMs?: number): Promise<PersonalSpendReport>;
@@ -185,6 +185,14 @@ export declare const actorProfileReportSchema: z.ZodObject<{
185
185
  windowEnd: z.ZodString;
186
186
  windowStart: z.ZodString;
187
187
  }, z.core.$strict>;
188
+ export declare const personalSpendReportSchema: z.ZodObject<{
189
+ generatedAt: z.ZodString;
190
+ sevenDaysUsd: z.ZodNumber;
191
+ source: z.ZodLiteral<"conversation_index">;
192
+ thirtyDaysUsd: z.ZodNumber;
193
+ windowEnd: z.ZodString;
194
+ windowStart: z.ZodString;
195
+ }, z.core.$strict>;
188
196
  export type ActorIdentity = z.infer<typeof actorIdentitySchema>;
189
197
  export type ConversationSummaryReport = z.infer<typeof conversationSummaryReportSchema>;
190
198
  export type ConversationStatsItem = z.infer<typeof peopleConversationStatsItemSchema>;
@@ -194,4 +202,5 @@ export type ActorTotalsReport = z.infer<typeof actorTotalsReportSchema>;
194
202
  export type ActorSummaryReport = z.infer<typeof actorSummaryReportSchema>;
195
203
  export type ActorDirectoryReport = z.infer<typeof actorDirectoryReportSchema>;
196
204
  export type ActorProfileReport = z.infer<typeof actorProfileReportSchema>;
205
+ export type PersonalSpendReport = z.infer<typeof personalSpendReportSchema>;
197
206
  export type PersonParams = z.infer<typeof personParamsSchema>;
@@ -2,10 +2,10 @@ export { dailyConversationActivitySchema } from "./activity";
2
2
  export type { DailyConversationActivity } from "./activity";
3
3
  export { archiveConversationBodySchema, archiveConversationResponseSchema, conversationAuxiliaryCostsSchema, conversationDetailQuerySchema, conversationDetailReportSchema, conversationEventPageSchema, conversationEventHistorySchema, conversationEventsQuerySchema, conversationFeedQuerySchema, conversationFeedSchema, conversationParamsSchema, conversationReportEventDataSchema, conversationReportEventSchema, conversationStatsReportSchema, conversationSummaryReportSchema, } from "./schema/conversation";
4
4
  export type { ArchiveConversationBody, ArchiveConversationResponse, ActorIdentity, ConversationAuxiliaryCosts, ConversationCost, ConversationDetailReport, ConversationEventPage, ConversationEventHistory, ConversationFeed, ConversationReportEvent, ConversationReportEventData, ConversationReportStatus, ConversationMetricDay, ConversationModelUsage, ConversationParams, ConversationStatsItem, ConversationStatsReport, ConversationSummaryReport, ConversationSurface, ConversationUsage, GuardianMetricDay, GuardianStats, } from "./schema/conversation";
5
- export { actorDirectoryReportSchema, actorProfileReportSchema, personParamsSchema, } from "./schema/person";
5
+ export { actorDirectoryReportSchema, actorProfileReportSchema, personalSpendReportSchema, personParamsSchema, } from "./schema/person";
6
6
  export { locationActivityDayReportSchema, locationDetailReportSchema, locationDirectoryReportSchema, locationParamsSchema, } from "./schema/location";
7
7
  export type { LocationActorSummaryReport, LocationActivityDayReport, LocationDetailReport, LocationDirectoryReport, LocationSummaryReport, LocationParams, } from "./schema/location";
8
- export type { ActorActivityDayReport, ActorDirectoryReport, ActorProfileReport, ActorSummaryReport, ActorTotalsReport, PeopleActivityDayReport, PersonParams, } from "./schema/person";
8
+ export type { ActorActivityDayReport, ActorDirectoryReport, ActorProfileReport, ActorSummaryReport, ActorTotalsReport, PeopleActivityDayReport, PersonalSpendReport, PersonParams, } from "./schema/person";
9
9
  export { apiErrorSchema } from "./schema/common";
10
10
  export type { ApiError } from "./schema/common";
11
11
  export { createPersonalTokenBodySchema, createdPersonalTokenSchema, personalTokenListSchema, personalTokenMetadataSchema, personalTokenParamsSchema, revokePersonalTokenResponseSchema, } from "./schema/personal-token";
@@ -25,13 +25,14 @@ import {
25
25
  locationDirectoryReportSchema,
26
26
  locationParamsSchema,
27
27
  personParamsSchema,
28
+ personalSpendReportSchema,
28
29
  personalTokenListSchema,
29
30
  personalTokenMetadataSchema,
30
31
  personalTokenParamsSchema,
31
32
  revokePersonalTokenResponseSchema,
32
33
  statSchema,
33
34
  statsReportSchema
34
- } from "../chunk-6ZBSTNYN.js";
35
+ } from "../chunk-AFJF3RGU.js";
35
36
  import {
36
37
  healthReportSchema,
37
38
  pluginOperationalReportFeedSchema,
@@ -75,6 +76,7 @@ export {
75
76
  locationDirectoryReportSchema,
76
77
  locationParamsSchema,
77
78
  personParamsSchema,
79
+ personalSpendReportSchema,
78
80
  personalTokenListSchema,
79
81
  personalTokenMetadataSchema,
80
82
  personalTokenParamsSchema,
package/dist/api.js CHANGED
@@ -20,16 +20,17 @@ import {
20
20
  locationDirectoryReportSchema,
21
21
  locationParamsSchema,
22
22
  personParamsSchema,
23
+ personalSpendReportSchema,
23
24
  personalTokenListSchema,
24
25
  personalTokenParamsSchema,
25
26
  revokePersonalTokenResponseSchema,
26
27
  statsReportSchema
27
- } from "./chunk-6ZBSTNYN.js";
28
+ } from "./chunk-AFJF3RGU.js";
28
29
  import {
29
30
  formatSlackConversationRedactedLabel,
30
31
  readHealthReport,
31
32
  resolveSlackConversationContextFromThreadId
32
- } from "./chunk-YUPNY2HZ.js";
33
+ } from "./chunk-JDCPDJ54.js";
33
34
  import {
34
35
  buildSentryConversationUrl
35
36
  } from "./chunk-4CODA7P5.js";
@@ -42,10 +43,10 @@ import {
42
43
  } from "./chunk-UTL3MHPC.js";
43
44
  import {
44
45
  readStats
45
- } from "./chunk-YFE6VNHU.js";
46
+ } from "./chunk-FJEIX3AH.js";
46
47
  import {
47
48
  parseSlackThreadId
48
- } from "./chunk-QMK2VF6K.js";
49
+ } from "./chunk-PBWUUVVG.js";
49
50
  import {
50
51
  agentTurnUsageSchema,
51
52
  hasAgentTurnUsage,
@@ -56,39 +57,39 @@ import {
56
57
  createPluginLogger,
57
58
  getPlugins,
58
59
  listConversationAnnotations,
59
- readViewerActors,
60
- renderPluginConversationEvent
61
- } from "./chunk-YZHA2L7P.js";
60
+ renderPluginConversationEvent,
61
+ resolveViewerUser
62
+ } from "./chunk-A76LKS5W.js";
62
63
  import {
63
64
  decodeStoredConversationEvent,
64
65
  getDb,
65
66
  getSqlExecutor,
66
67
  parseSessionSource
67
- } from "./chunk-S4LM6UB7.js";
68
+ } from "./chunk-B7FPRGUJ.js";
68
69
  import {
69
70
  juniorApiTokens,
70
71
  juniorConversationEvents,
71
72
  juniorConversations,
72
73
  juniorIdentities,
73
74
  juniorUsers
74
- } from "./chunk-S4PUICSB.js";
75
- import "./chunk-F2ARYRKC.js";
76
- import "./chunk-WIIPHGJY.js";
75
+ } from "./chunk-SHMHHXD5.js";
76
+ import "./chunk-G6XQODHM.js";
77
+ import "./chunk-K5ZB3WWH.js";
77
78
  import {
78
79
  juniorDestinations
79
80
  } from "./chunk-VFUK3X5B.js";
80
81
  import {
81
82
  canExposeConversationPayload
82
- } from "./chunk-U36WL4OL.js";
83
+ } from "./chunk-Z4KTQMWW.js";
83
84
  import "./chunk-HZF5P5UN.js";
84
85
  import {
85
86
  parseSlackChannelId,
86
87
  parseSlackTeamId
87
88
  } from "./chunk-F3B2YJ76.js";
88
- import "./chunk-PD6J33TO.js";
89
+ import "./chunk-B6E3YA2H.js";
89
90
  import "./chunk-6GWA276C.js";
90
- import "./chunk-7ZMY4GCG.js";
91
- import "./chunk-W3JHZHAN.js";
91
+ import "./chunk-RYWMDDWK.js";
92
+ import "./chunk-KTGJAWRO.js";
92
93
  import "./chunk-MLKGABMK.js";
93
94
 
94
95
  // src/api.ts
@@ -129,8 +130,8 @@ function parseBody(schema, body) {
129
130
  function defineApiRoute(route) {
130
131
  return route;
131
132
  }
132
- function registerApiRoutes(app, routes6) {
133
- for (const route of routes6) {
133
+ function registerApiRoutes(app, routes5) {
134
+ for (const route of routes5) {
134
135
  app.on(
135
136
  route.method,
136
137
  route.path,
@@ -2014,7 +2015,7 @@ function readDescriptionText(home) {
2014
2015
  }
2015
2016
  }
2016
2017
  async function readSkillReports() {
2017
- const { discoverSkills } = await import("./skills-BCQHR636.js");
2018
+ const { discoverSkills } = await import("./skills-ENIBKF5V.js");
2018
2019
  const skills = await discoverSkills();
2019
2020
  return skillReportsSchema.parse(
2020
2021
  skills.map((skill) => ({
@@ -2024,7 +2025,7 @@ async function readSkillReports() {
2024
2025
  );
2025
2026
  }
2026
2027
  async function readPlugins() {
2027
- const { pluginCatalogRuntime } = await import("./catalog-runtime-OUPLWD7F.js");
2028
+ const { pluginCatalogRuntime } = await import("./catalog-runtime-ZPSA5QM2.js");
2028
2029
  return pluginsSchema.parse(
2029
2030
  pluginCatalogRuntime.getProviders().map((plugin) => ({
2030
2031
  configKeys: plugin.manifest.configKeys ?? [],
@@ -2037,7 +2038,7 @@ async function readPlugins() {
2037
2038
  async function readRuntimeInfoReport() {
2038
2039
  const [{ homeDir }, { pluginCatalogRuntime }, plugins, skills] = await Promise.all([
2039
2040
  import("./discovery-GUFTFBTL.js"),
2040
- import("./catalog-runtime-OUPLWD7F.js"),
2041
+ import("./catalog-runtime-ZPSA5QM2.js"),
2041
2042
  readPlugins(),
2042
2043
  readSkillReports()
2043
2044
  ]);
@@ -2053,7 +2054,7 @@ async function readRuntimeInfoReport() {
2053
2054
  }
2054
2055
  async function readPluginOperationalReportFeed() {
2055
2056
  const nowMs = Date.now();
2056
- const { getPluginOperationalReports } = await import("./agent-hooks-U5YGLX6Y.js");
2057
+ const { getPluginOperationalReports } = await import("./agent-hooks-F75ANGBV.js");
2057
2058
  return pluginOperationalReportFeedSchema.parse({
2058
2059
  source: "plugins",
2059
2060
  generatedAt: new Date(nowMs).toISOString(),
@@ -2974,11 +2975,110 @@ var profile_default = defineApiRoute({
2974
2975
  }
2975
2976
  });
2976
2977
 
2978
+ // src/api/people/spend.query.ts
2979
+ import { and as and12, eq as eq13, gte as gte5, lte as lte2, sql as sql11 } from "drizzle-orm";
2980
+ var SEVEN_DAY_OFFSET = 6;
2981
+ var THIRTY_DAY_OFFSET = 29;
2982
+ function addUsd2(current, next) {
2983
+ return Math.round((current + next) * 1e12) / 1e12;
2984
+ }
2985
+ function spendWindow(nowMs) {
2986
+ const end = new Date(nowMs);
2987
+ const currentDay = new Date(end);
2988
+ currentDay.setUTCHours(0, 0, 0, 0);
2989
+ const sevenDayStart = new Date(currentDay);
2990
+ sevenDayStart.setUTCDate(sevenDayStart.getUTCDate() - SEVEN_DAY_OFFSET);
2991
+ const thirtyDayStart = new Date(currentDay);
2992
+ thirtyDayStart.setUTCDate(thirtyDayStart.getUTCDate() - THIRTY_DAY_OFFSET);
2993
+ return { end, sevenDayStart, thirtyDayStart };
2994
+ }
2995
+ async function readPersonalSpendFromSql(email, nowMs = Date.now()) {
2996
+ const normalizedEmail = normalizeEmail(email);
2997
+ const { end, sevenDayStart, thirtyDayStart } = spendWindow(nowMs);
2998
+ const activityDate = sql11`TO_CHAR(
2999
+ ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
3000
+ 'YYYY-MM-DD'
3001
+ )`;
3002
+ const metricsJoin = peopleTreeMetricsJoin();
3003
+ const rows = normalizedEmail ? await getDb().select({
3004
+ costUsd: peopleTreeAggregateColumns.costUsd,
3005
+ date: activityDate
3006
+ }).from(juniorConversations).innerJoin(
3007
+ juniorIdentities,
3008
+ eq13(juniorIdentities.id, juniorConversations.actorIdentityId)
3009
+ ).innerJoin(juniorUsers, eq13(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(
3010
+ and12(
3011
+ verifiedActorWhere(normalizedEmail),
3012
+ gte5(juniorConversations.lastActivityAt, thirtyDayStart),
3013
+ lte2(juniorConversations.lastActivityAt, end)
3014
+ )
3015
+ ).groupBy(activityDate) : [];
3016
+ const sevenDayStartDate = sevenDayStart.toISOString().slice(0, 10);
3017
+ let sevenDaysUsd = 0;
3018
+ let thirtyDaysUsd = 0;
3019
+ for (const row of rows) {
3020
+ if (row.costUsd === null) continue;
3021
+ thirtyDaysUsd = addUsd2(thirtyDaysUsd, row.costUsd);
3022
+ if (row.date >= sevenDayStartDate) {
3023
+ sevenDaysUsd = addUsd2(sevenDaysUsd, row.costUsd);
3024
+ }
3025
+ }
3026
+ return {
3027
+ generatedAt: new Date(nowMs).toISOString(),
3028
+ sevenDaysUsd,
3029
+ source: "conversation_index",
3030
+ thirtyDaysUsd,
3031
+ windowEnd: end.toISOString(),
3032
+ windowStart: thirtyDayStart.toISOString()
3033
+ };
3034
+ }
3035
+
3036
+ // src/api/people/spend.ts
3037
+ var PERSONAL_SPEND_CACHE_TTL_MS = 5 * 6e4;
3038
+ function createPersonalSpendRoute() {
3039
+ const cache = /* @__PURE__ */ new Map();
3040
+ async function read(email) {
3041
+ const normalizedEmail = email.trim().toLowerCase();
3042
+ const nowMs = Date.now();
3043
+ const cached = cache.get(normalizedEmail);
3044
+ if (cached && cached.expiresAtMs > nowMs) {
3045
+ return cached.report;
3046
+ }
3047
+ cache.delete(normalizedEmail);
3048
+ const report = readPersonalSpendFromSql(normalizedEmail, nowMs);
3049
+ const entry = {
3050
+ expiresAtMs: nowMs + PERSONAL_SPEND_CACHE_TTL_MS,
3051
+ report
3052
+ };
3053
+ cache.set(normalizedEmail, entry);
3054
+ try {
3055
+ return await report;
3056
+ } catch (error) {
3057
+ if (cache.get(normalizedEmail) === entry) cache.delete(normalizedEmail);
3058
+ throw error;
3059
+ }
3060
+ }
3061
+ return defineApiRoute({
3062
+ method: "get",
3063
+ path: "/me/spend",
3064
+ responseSchema: personalSpendReportSchema,
3065
+ handler: async (context) => {
3066
+ const email = context.get("verifiedViewerEmail");
3067
+ if (!email) throwApiError(403, "Verified viewer email required.");
3068
+ return read(email);
3069
+ }
3070
+ });
3071
+ }
3072
+
2977
3073
  // src/api/people/routes.ts
2978
- var routes3 = [list_default3, profile_default];
2979
3074
  function createPeopleRoutes() {
2980
3075
  const app = new Hono3();
2981
- registerApiRoutes(app, routes3);
3076
+ const routes5 = [
3077
+ createPersonalSpendRoute(),
3078
+ list_default3,
3079
+ profile_default
3080
+ ];
3081
+ registerApiRoutes(app, routes5);
2982
3082
  return app;
2983
3083
  }
2984
3084
 
@@ -2995,7 +3095,7 @@ import { Hono as Hono4 } from "hono";
2995
3095
 
2996
3096
  // src/personal-tokens/store.ts
2997
3097
  import { createHash, randomBytes, randomUUID } from "crypto";
2998
- import { and as and12, desc as desc5, eq as eq13, gt, isNull as isNull7 } from "drizzle-orm";
3098
+ import { and as and13, desc as desc5, eq as eq14, gt, isNull as isNull7 } from "drizzle-orm";
2999
3099
  var TOKEN_PREFIX = "jr_pat_";
3000
3100
  var TOKEN_SUFFIX_LENGTH = 8;
3001
3101
  var DEFAULT_TOKEN_LIFETIME_MS = 90 * 24 * 60 * 60 * 1e3;
@@ -3032,8 +3132,8 @@ async function createPersonalToken(args) {
3032
3132
  }
3033
3133
  async function listPersonalTokens(email, now = /* @__PURE__ */ new Date()) {
3034
3134
  const rows = await getDb().select().from(juniorApiTokens).where(
3035
- and12(
3036
- eq13(juniorApiTokens.ownerEmailNormalized, normalizeEmail2(email)),
3135
+ and13(
3136
+ eq14(juniorApiTokens.ownerEmailNormalized, normalizeEmail2(email)),
3037
3137
  isNull7(juniorApiTokens.revokedAt),
3038
3138
  gt(juniorApiTokens.expiresAt, now)
3039
3139
  )
@@ -3042,9 +3142,9 @@ async function listPersonalTokens(email, now = /* @__PURE__ */ new Date()) {
3042
3142
  }
3043
3143
  async function revokePersonalToken(args) {
3044
3144
  const rows = await getDb().update(juniorApiTokens).set({ revokedAt: args.now ?? /* @__PURE__ */ new Date() }).where(
3045
- and12(
3046
- eq13(juniorApiTokens.id, args.id),
3047
- eq13(juniorApiTokens.ownerEmailNormalized, normalizeEmail2(args.email)),
3145
+ and13(
3146
+ eq14(juniorApiTokens.id, args.id),
3147
+ eq14(juniorApiTokens.ownerEmailNormalized, normalizeEmail2(args.email)),
3048
3148
  isNull7(juniorApiTokens.revokedAt)
3049
3149
  )
3050
3150
  ).returning({ id: juniorApiTokens.id });
@@ -3056,15 +3156,15 @@ async function authenticatePersonalToken(token2, now = /* @__PURE__ */ new Date(
3056
3156
  id: juniorApiTokens.id,
3057
3157
  ownerEmailNormalized: juniorApiTokens.ownerEmailNormalized
3058
3158
  }).from(juniorApiTokens).where(
3059
- and12(
3060
- eq13(juniorApiTokens.tokenHash, hashToken(token2)),
3159
+ and13(
3160
+ eq14(juniorApiTokens.tokenHash, hashToken(token2)),
3061
3161
  isNull7(juniorApiTokens.revokedAt),
3062
3162
  gt(juniorApiTokens.expiresAt, now)
3063
3163
  )
3064
3164
  ).limit(1);
3065
3165
  const match = rows[0];
3066
3166
  if (!match) return void 0;
3067
- await getDb().update(juniorApiTokens).set({ lastUsedAt: now }).where(eq13(juniorApiTokens.id, match.id));
3167
+ await getDb().update(juniorApiTokens).set({ lastUsedAt: now }).where(eq14(juniorApiTokens.id, match.id));
3068
3168
  return match.ownerEmailNormalized;
3069
3169
  }
3070
3170
 
@@ -3116,10 +3216,10 @@ var revoke_default = defineApiRoute({
3116
3216
  });
3117
3217
 
3118
3218
  // src/api/personal-tokens/routes.ts
3119
- var routes4 = [list_default4, create_default, revoke_default];
3219
+ var routes3 = [list_default4, create_default, revoke_default];
3120
3220
  function createPersonalTokenRoutes() {
3121
3221
  const app = new Hono4();
3122
- registerApiRoutes(app, routes4);
3222
+ registerApiRoutes(app, routes3);
3123
3223
  return app;
3124
3224
  }
3125
3225
 
@@ -3162,16 +3262,17 @@ async function readPluginUserPage(input) {
3162
3262
  (candidate) => candidate.id === input.pageId
3163
3263
  );
3164
3264
  if (!plugin || !page) return void 0;
3265
+ const viewer = await resolveViewerUser(input.email);
3266
+ if (!viewer) {
3267
+ throw new Error("Authenticated viewer user could not be resolved");
3268
+ }
3165
3269
  const content = pluginUserPageContentSchema.parse(
3166
3270
  await page.read(
3167
3271
  {
3168
3272
  db: getDb(),
3169
3273
  log: createPluginLogger(plugin.manifest.name),
3170
3274
  plugin: { name: plugin.manifest.name },
3171
- viewer: {
3172
- actors: await readViewerActors(input.email),
3173
- email: input.email
3174
- }
3275
+ viewer
3175
3276
  },
3176
3277
  input.query
3177
3278
  )
@@ -3280,7 +3381,7 @@ var stats_default2 = defineApiRoute({
3280
3381
  });
3281
3382
 
3282
3383
  // src/api.ts
3283
- var routes5 = [
3384
+ var routes4 = [
3284
3385
  health_default,
3285
3386
  runtime_default,
3286
3387
  plugins_default,
@@ -3290,7 +3391,7 @@ var routes5 = [
3290
3391
  ];
3291
3392
  function createJuniorApi() {
3292
3393
  const app = new Hono6();
3293
- registerApiRoutes(app, routes5);
3394
+ registerApiRoutes(app, routes4);
3294
3395
  app.route("/api/conversations", createConversationRoutes());
3295
3396
  app.route("/api/personal-tokens", createPersonalTokenRoutes());
3296
3397
  app.route("/api/people", createPeopleRoutes());