@studious-lms/server 1.18.0 → 1.20.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 (160) hide show
  1. package/dist/index.js +8 -2
  2. package/dist/index.js.map +1 -1
  3. package/dist/lib/pusher.d.ts +3 -1
  4. package/dist/lib/pusher.d.ts.map +1 -1
  5. package/dist/lib/pusher.js +5 -3
  6. package/dist/lib/pusher.js.map +1 -1
  7. package/dist/middleware/security.d.ts.map +1 -1
  8. package/dist/middleware/security.js +4 -4
  9. package/dist/middleware/security.js.map +1 -1
  10. package/dist/models/class.d.ts +1 -1
  11. package/dist/models/class.d.ts.map +1 -1
  12. package/dist/models/class.js +5 -4
  13. package/dist/models/class.js.map +1 -1
  14. package/dist/models/conversation.d.ts +17 -17
  15. package/dist/models/notification.d.ts +63 -11
  16. package/dist/models/notification.d.ts.map +1 -1
  17. package/dist/models/notification.js +24 -10
  18. package/dist/models/notification.js.map +1 -1
  19. package/dist/models/worksheet.d.ts +1 -0
  20. package/dist/models/worksheet.d.ts.map +1 -1
  21. package/dist/models/worksheet.js +3 -3
  22. package/dist/models/worksheet.js.map +1 -1
  23. package/dist/pipelines/aiLabChat.d.ts +1 -0
  24. package/dist/pipelines/aiLabChat.d.ts.map +1 -1
  25. package/dist/pipelines/aiLabChat.js +7 -2
  26. package/dist/pipelines/aiLabChat.js.map +1 -1
  27. package/dist/pipelines/aiNewtonChat.d.ts +2 -2
  28. package/dist/pipelines/aiNewtonChat.d.ts.map +1 -1
  29. package/dist/pipelines/aiNewtonChat.js +12 -4
  30. package/dist/pipelines/aiNewtonChat.js.map +1 -1
  31. package/dist/pipelines/gradeWorksheet.d.ts +3 -3
  32. package/dist/pipelines/gradeWorksheet.d.ts.map +1 -1
  33. package/dist/pipelines/gradeWorksheet.js +13 -9
  34. package/dist/pipelines/gradeWorksheet.js.map +1 -1
  35. package/dist/pipelines/pdfToWorksheet.d.ts +2 -0
  36. package/dist/pipelines/pdfToWorksheet.d.ts.map +1 -1
  37. package/dist/pipelines/pdfToWorksheet.js +3 -2
  38. package/dist/pipelines/pdfToWorksheet.js.map +1 -1
  39. package/dist/routers/_app.d.ts +176 -82
  40. package/dist/routers/_app.d.ts.map +1 -1
  41. package/dist/routers/announcement.d.ts.map +1 -1
  42. package/dist/routers/announcement.js +2 -2
  43. package/dist/routers/announcement.js.map +1 -1
  44. package/dist/routers/assignment.d.ts.map +1 -1
  45. package/dist/routers/assignment.js +12 -2
  46. package/dist/routers/assignment.js.map +1 -1
  47. package/dist/routers/notifications.d.ts +51 -41
  48. package/dist/routers/notifications.d.ts.map +1 -1
  49. package/dist/routers/notifications.js +22 -18
  50. package/dist/routers/notifications.js.map +1 -1
  51. package/dist/routers/school.d.ts +30 -0
  52. package/dist/routers/school.d.ts.map +1 -1
  53. package/dist/routers/school.js +11 -2
  54. package/dist/routers/school.js.map +1 -1
  55. package/dist/routers/user.d.ts +12 -0
  56. package/dist/routers/user.d.ts.map +1 -1
  57. package/dist/routers/user.js +11 -2
  58. package/dist/routers/user.js.map +1 -1
  59. package/dist/routers/worksheet.d.ts +1 -0
  60. package/dist/routers/worksheet.d.ts.map +1 -1
  61. package/dist/seedDatabase.d.ts +4 -0
  62. package/dist/seedDatabase.d.ts.map +1 -1
  63. package/dist/services/aiChatStream.d.ts +5 -0
  64. package/dist/services/aiChatStream.d.ts.map +1 -1
  65. package/dist/services/aiChatStream.js +32 -3
  66. package/dist/services/aiChatStream.js.map +1 -1
  67. package/dist/services/aiStream.d.ts +5 -0
  68. package/dist/services/aiStream.d.ts.map +1 -1
  69. package/dist/services/aiStream.js +29 -3
  70. package/dist/services/aiStream.js.map +1 -1
  71. package/dist/services/aiUsage.d.ts +72 -0
  72. package/dist/services/aiUsage.d.ts.map +1 -0
  73. package/dist/services/aiUsage.js +150 -0
  74. package/dist/services/aiUsage.js.map +1 -0
  75. package/dist/services/announcement.d.ts.map +1 -1
  76. package/dist/services/announcement.js +7 -2
  77. package/dist/services/announcement.js.map +1 -1
  78. package/dist/services/assignment.d.ts.map +1 -1
  79. package/dist/services/assignment.js +29 -4
  80. package/dist/services/assignment.js.map +1 -1
  81. package/dist/services/attendance.js +10 -2
  82. package/dist/services/attendance.js.map +1 -1
  83. package/dist/services/class.d.ts.map +1 -1
  84. package/dist/services/class.js +6 -2
  85. package/dist/services/class.js.map +1 -1
  86. package/dist/services/discussion.d.ts.map +1 -1
  87. package/dist/services/discussion.js +41 -12
  88. package/dist/services/discussion.js.map +1 -1
  89. package/dist/services/discussionSummary.d.ts.map +1 -1
  90. package/dist/services/discussionSummary.js +3 -2
  91. package/dist/services/discussionSummary.js.map +1 -1
  92. package/dist/services/notification.d.ts +79 -16
  93. package/dist/services/notification.d.ts.map +1 -1
  94. package/dist/services/notification.js +64 -16
  95. package/dist/services/notification.js.map +1 -1
  96. package/dist/services/studentProgress.d.ts.map +1 -1
  97. package/dist/services/studentProgress.js +6 -2
  98. package/dist/services/studentProgress.js.map +1 -1
  99. package/dist/services/userPrivacy.d.ts +4 -0
  100. package/dist/services/userPrivacy.d.ts.map +1 -1
  101. package/dist/services/userPrivacy.js +6 -2
  102. package/dist/services/userPrivacy.js.map +1 -1
  103. package/dist/services/worksheet.d.ts +1 -0
  104. package/dist/services/worksheet.d.ts.map +1 -1
  105. package/dist/services/worksheet.js +4 -4
  106. package/dist/services/worksheet.js.map +1 -1
  107. package/dist/utils/inference.d.ts +27 -0
  108. package/dist/utils/inference.d.ts.map +1 -1
  109. package/dist/utils/inference.js +23 -3
  110. package/dist/utils/inference.js.map +1 -1
  111. package/dist/workers/processors/aiLabChat.d.ts.map +1 -1
  112. package/dist/workers/processors/aiLabChat.js +4 -3
  113. package/dist/workers/processors/aiLabChat.js.map +1 -1
  114. package/dist/workers/processors/aiNewtonChat.d.ts.map +1 -1
  115. package/dist/workers/processors/aiNewtonChat.js +5 -5
  116. package/dist/workers/processors/aiNewtonChat.js.map +1 -1
  117. package/dist/workers/processors/gradeWorksheet.js +4 -4
  118. package/dist/workers/processors/gradeWorksheet.js.map +1 -1
  119. package/dist/workers/processors/pdfToWorksheet.d.ts.map +1 -1
  120. package/dist/workers/processors/pdfToWorksheet.js +7 -4
  121. package/dist/workers/processors/pdfToWorksheet.js.map +1 -1
  122. package/package.json +1 -1
  123. package/prisma/migrations/20260708011500_add_ai_usage_attribution/migration.sql +13 -0
  124. package/prisma/migrations/20260708013000_add_notification_type_and_entity/migration.sql +14 -0
  125. package/prisma/schema.prisma +29 -5
  126. package/src/index.ts +7 -0
  127. package/src/lib/pusher.ts +3 -1
  128. package/src/middleware/security.ts +2 -2
  129. package/src/models/class.ts +3 -2
  130. package/src/models/notification.ts +42 -13
  131. package/src/models/worksheet.ts +1 -1
  132. package/src/pipelines/aiLabChat.ts +6 -1
  133. package/src/pipelines/aiNewtonChat.ts +10 -0
  134. package/src/pipelines/gradeWorksheet.ts +25 -7
  135. package/src/pipelines/pdfToWorksheet.ts +3 -0
  136. package/src/routers/announcement.ts +0 -1
  137. package/src/routers/assignment.ts +10 -0
  138. package/src/routers/notifications.ts +26 -24
  139. package/src/routers/school.ts +12 -0
  140. package/src/routers/user.ts +12 -0
  141. package/src/services/aiChatStream.ts +35 -0
  142. package/src/services/aiStream.ts +34 -0
  143. package/src/services/aiUsage.ts +202 -0
  144. package/src/services/announcement.ts +5 -0
  145. package/src/services/assignment.ts +29 -2
  146. package/src/services/attendance.ts +12 -0
  147. package/src/services/class.ts +4 -0
  148. package/src/services/discussion.ts +50 -11
  149. package/src/services/discussionSummary.ts +1 -0
  150. package/src/services/notification.ts +83 -20
  151. package/src/services/studentProgress.ts +4 -0
  152. package/src/services/userPrivacy.ts +4 -0
  153. package/src/services/worksheet.ts +2 -2
  154. package/src/utils/inference.ts +40 -2
  155. package/src/workers/processors/aiLabChat.ts +2 -1
  156. package/src/workers/processors/aiNewtonChat.ts +3 -1
  157. package/src/workers/processors/gradeWorksheet.ts +2 -2
  158. package/src/workers/processors/pdfToWorksheet.ts +5 -2
  159. package/tests/integration/routers/notification.test.ts +68 -20
  160. package/tests/unit/services/aiUsage.test.ts +105 -0
@@ -1,4 +1,10 @@
1
1
  import { z } from "zod";
2
+ /**
3
+ * Read-only notification API. Notifications are emitted exclusively by
4
+ * server-side domain services — there is intentionally no public "send"
5
+ * endpoint (the previous sendTo/sendToMultiple procedures allowed any logged-in
6
+ * user to notify arbitrary users and were removed).
7
+ */
2
8
  export declare const notificationRouter: import("@trpc/server").TRPCBuiltRouter<{
3
9
  ctx: import("../trpc.js").Context;
4
10
  meta: object;
@@ -17,23 +23,33 @@ export declare const notificationRouter: import("@trpc/server").TRPCBuiltRouter<
17
23
  transformer: false;
18
24
  }, import("@trpc/server").TRPCDecorateCreateRouterOptions<{
19
25
  list: import("@trpc/server").TRPCQueryProcedure<{
20
- input: void;
21
- output: ({
22
- sender: {
23
- username: string;
24
- } | null;
25
- receiver: {
26
- username: string;
27
- };
28
- } & {
29
- id: string;
30
- createdAt: Date;
31
- title: string;
32
- content: string;
33
- senderId: string | null;
34
- read: boolean;
35
- receiverId: string;
36
- })[];
26
+ input: {
27
+ cursor?: string | null | undefined;
28
+ limit?: number | undefined;
29
+ } | undefined;
30
+ output: {
31
+ items: ({
32
+ sender: {
33
+ username: string;
34
+ } | null;
35
+ receiver: {
36
+ username: string;
37
+ };
38
+ } & {
39
+ type: import(".prisma/client").$Enums.NotificationType;
40
+ id: string;
41
+ createdAt: Date;
42
+ classId: string | null;
43
+ title: string;
44
+ content: string;
45
+ senderId: string | null;
46
+ read: boolean;
47
+ receiverId: string;
48
+ entityType: string | null;
49
+ entityId: string | null;
50
+ })[];
51
+ nextCursor: string | null;
52
+ };
37
53
  meta: object;
38
54
  }>;
39
55
  get: import("@trpc/server").TRPCQueryProcedure<{
@@ -48,40 +64,23 @@ export declare const notificationRouter: import("@trpc/server").TRPCBuiltRouter<
48
64
  username: string;
49
65
  };
50
66
  } & {
67
+ type: import(".prisma/client").$Enums.NotificationType;
51
68
  id: string;
52
69
  createdAt: Date;
70
+ classId: string | null;
53
71
  title: string;
54
72
  content: string;
55
73
  senderId: string | null;
56
74
  read: boolean;
57
75
  receiverId: string;
76
+ entityType: string | null;
77
+ entityId: string | null;
58
78
  };
59
79
  meta: object;
60
80
  }>;
61
- sendTo: import("@trpc/server").TRPCMutationProcedure<{
62
- input: {
63
- title: string;
64
- content: string;
65
- receiverId: string;
66
- };
67
- output: {
68
- id: string;
69
- createdAt: Date;
70
- title: string;
71
- content: string;
72
- senderId: string | null;
73
- read: boolean;
74
- receiverId: string;
75
- };
76
- meta: object;
77
- }>;
78
- sendToMultiple: import("@trpc/server").TRPCMutationProcedure<{
79
- input: {
80
- title: string;
81
- content: string;
82
- receiverIds: string[];
83
- };
84
- output: import("@prisma/client/runtime/library.js").GetBatchResult;
81
+ unreadCount: import("@trpc/server").TRPCQueryProcedure<{
82
+ input: void;
83
+ output: number;
85
84
  meta: object;
86
85
  }>;
87
86
  markAsRead: import("@trpc/server").TRPCMutationProcedure<{
@@ -96,13 +95,24 @@ export declare const notificationRouter: import("@trpc/server").TRPCBuiltRouter<
96
95
  username: string;
97
96
  };
98
97
  } & {
98
+ type: import(".prisma/client").$Enums.NotificationType;
99
99
  id: string;
100
100
  createdAt: Date;
101
+ classId: string | null;
101
102
  title: string;
102
103
  content: string;
103
104
  senderId: string | null;
104
105
  read: boolean;
105
106
  receiverId: string;
107
+ entityType: string | null;
108
+ entityId: string | null;
109
+ };
110
+ meta: object;
111
+ }>;
112
+ markAllAsRead: import("@trpc/server").TRPCMutationProcedure<{
113
+ input: void;
114
+ output: {
115
+ count: number;
106
116
  };
107
117
  meta: object;
108
118
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"notifications.d.ts","sourceRoot":"/","sources":["routers/notifications.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgC7B,CAAC"}
1
+ {"version":3,"file":"notifications.d.ts","sourceRoot":"/","sources":["routers/notifications.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4B7B,CAAC"}
@@ -1,30 +1,34 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="326a74b5-821e-501b-8db6-78f578a43fc3")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="21917f4d-f637-5db5-b39f-2e1cfdbf692a")}catch(e){}}();
3
3
  import { createTRPCRouter, protectedProcedure } from "../trpc.js";
4
4
  import { z } from "zod";
5
- import { listNotifications, getNotification, sendNotification, sendToMultiple, markAsRead, } from "../services/notification.js";
5
+ import { listNotifications, getNotification, getUnreadCount, markAsRead, markAllAsRead, } from "../services/notification.js";
6
+ /**
7
+ * Read-only notification API. Notifications are emitted exclusively by
8
+ * server-side domain services — there is intentionally no public "send"
9
+ * endpoint (the previous sendTo/sendToMultiple procedures allowed any logged-in
10
+ * user to notify arbitrary users and were removed).
11
+ */
6
12
  export const notificationRouter = createTRPCRouter({
7
- list: protectedProcedure.query(({ ctx }) => listNotifications(ctx.user.id)),
13
+ list: protectedProcedure
14
+ .input(z
15
+ .object({
16
+ limit: z.number().int().min(1).max(100).default(20),
17
+ cursor: z.string().nullish(),
18
+ })
19
+ .optional())
20
+ .query(({ ctx, input }) => listNotifications(ctx.user.id, {
21
+ limit: input?.limit,
22
+ cursor: input?.cursor,
23
+ })),
8
24
  get: protectedProcedure
9
25
  .input(z.object({ id: z.string() }))
10
26
  .query(({ ctx, input }) => getNotification(ctx.user.id, input.id)),
11
- sendTo: protectedProcedure
12
- .input(z.object({
13
- receiverId: z.string(),
14
- title: z.string(),
15
- content: z.string(),
16
- }))
17
- .mutation(({ input }) => sendNotification(input)),
18
- sendToMultiple: protectedProcedure
19
- .input(z.object({
20
- receiverIds: z.array(z.string()),
21
- title: z.string(),
22
- content: z.string(),
23
- }))
24
- .mutation(({ input }) => sendToMultiple(input)),
27
+ unreadCount: protectedProcedure.query(({ ctx }) => getUnreadCount(ctx.user.id)),
25
28
  markAsRead: protectedProcedure
26
29
  .input(z.object({ id: z.string() }))
27
30
  .mutation(({ ctx, input }) => markAsRead(ctx.user.id, input.id)),
31
+ markAllAsRead: protectedProcedure.mutation(({ ctx }) => markAllAsRead(ctx.user.id)),
28
32
  });
29
33
  //# sourceMappingURL=notifications.js.map
30
- //# debugId=326a74b5-821e-501b-8db6-78f578a43fc3
34
+ //# debugId=21917f4d-f637-5db5-b39f-2e1cfdbf692a
@@ -1 +1 @@
1
- {"version":3,"file":"notifications.js","sources":["routers/notifications.ts"],"sourceRoot":"/","sourcesContent":["import { createTRPCRouter, protectedProcedure } from \"../trpc.js\";\nimport { z } from \"zod\";\nimport {\n listNotifications,\n getNotification,\n sendNotification,\n sendToMultiple,\n markAsRead,\n} from \"../services/notification.js\";\n\nexport const notificationRouter = createTRPCRouter({\n list: protectedProcedure.query(({ ctx }) =>\n listNotifications(ctx.user!.id)\n ),\n\n get: protectedProcedure\n .input(z.object({ id: z.string() }))\n .query(({ ctx, input }) => getNotification(ctx.user!.id, input.id)),\n\n sendTo: protectedProcedure\n .input(\n z.object({\n receiverId: z.string(),\n title: z.string(),\n content: z.string(),\n })\n )\n .mutation(({ input }) => sendNotification(input)),\n\n sendToMultiple: protectedProcedure\n .input(\n z.object({\n receiverIds: z.array(z.string()),\n title: z.string(),\n content: z.string(),\n })\n )\n .mutation(({ input }) => sendToMultiple(input)),\n\n markAsRead: protectedProcedure\n .input(z.object({ id: z.string() }))\n .mutation(({ ctx, input }) => markAsRead(ctx.user!.id, input.id)),\n});\n"],"names":[],"mappings":";;AAAA,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,UAAU,GACX,MAAM,6BAA6B,CAAC;AAErC,MAAM,CAAC,MAAM,kBAAkB,GAAG,gBAAgB,CAAC;IACjD,IAAI,EAAE,kBAAkB,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CACzC,iBAAiB,CAAC,GAAG,CAAC,IAAK,CAAC,EAAE,CAAC,CAChC;IAED,GAAG,EAAE,kBAAkB;SACpB,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;SACnC,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,IAAK,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;IAErE,MAAM,EAAE,kBAAkB;SACvB,KAAK,CACJ,CAAC,CAAC,MAAM,CAAC;QACP,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;QACtB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;QACjB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;KACpB,CAAC,CACH;SACA,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAEnD,cAAc,EAAE,kBAAkB;SAC/B,KAAK,CACJ,CAAC,CAAC,MAAM,CAAC;QACP,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAChC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;QACjB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;KACpB,CAAC,CACH;SACA,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAEjD,UAAU,EAAE,kBAAkB;SAC3B,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;SACnC,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,IAAK,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;CACpE,CAAC,CAAC","debug_id":"326a74b5-821e-501b-8db6-78f578a43fc3"}
1
+ {"version":3,"file":"notifications.js","sources":["routers/notifications.ts"],"sourceRoot":"/","sourcesContent":["import { createTRPCRouter, protectedProcedure } from \"../trpc.js\";\nimport { z } from \"zod\";\nimport {\n listNotifications,\n getNotification,\n getUnreadCount,\n markAsRead,\n markAllAsRead,\n} from \"../services/notification.js\";\n\n/**\n * Read-only notification API. Notifications are emitted exclusively by\n * server-side domain services — there is intentionally no public \"send\"\n * endpoint (the previous sendTo/sendToMultiple procedures allowed any logged-in\n * user to notify arbitrary users and were removed).\n */\nexport const notificationRouter = createTRPCRouter({\n list: protectedProcedure\n .input(\n z\n .object({\n limit: z.number().int().min(1).max(100).default(20),\n cursor: z.string().nullish(),\n })\n .optional()\n )\n .query(({ ctx, input }) =>\n listNotifications(ctx.user!.id, {\n limit: input?.limit,\n cursor: input?.cursor,\n })\n ),\n\n get: protectedProcedure\n .input(z.object({ id: z.string() }))\n .query(({ ctx, input }) => getNotification(ctx.user!.id, input.id)),\n\n unreadCount: protectedProcedure.query(({ ctx }) => getUnreadCount(ctx.user!.id)),\n\n markAsRead: protectedProcedure\n .input(z.object({ id: z.string() }))\n .mutation(({ ctx, input }) => markAsRead(ctx.user!.id, input.id)),\n\n markAllAsRead: protectedProcedure.mutation(({ ctx }) => markAllAsRead(ctx.user!.id)),\n});\n"],"names":[],"mappings":";;AAAA,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,UAAU,EACV,aAAa,GACd,MAAM,6BAA6B,CAAC;AAErC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,gBAAgB,CAAC;IACjD,IAAI,EAAE,kBAAkB;SACrB,KAAK,CACJ,CAAC;SACE,MAAM,CAAC;QACN,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;QACnD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;KAC7B,CAAC;SACD,QAAQ,EAAE,CACd;SACA,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,CACxB,iBAAiB,CAAC,GAAG,CAAC,IAAK,CAAC,EAAE,EAAE;QAC9B,KAAK,EAAE,KAAK,EAAE,KAAK;QACnB,MAAM,EAAE,KAAK,EAAE,MAAM;KACtB,CAAC,CACH;IAEH,GAAG,EAAE,kBAAkB;SACpB,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;SACnC,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,IAAK,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;IAErE,WAAW,EAAE,kBAAkB,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,IAAK,CAAC,EAAE,CAAC,CAAC;IAEhF,UAAU,EAAE,kBAAkB;SAC3B,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;SACnC,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,IAAK,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;IAEnE,aAAa,EAAE,kBAAkB,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,IAAK,CAAC,EAAE,CAAC,CAAC;CACrF,CAAC,CAAC","debug_id":"21917f4d-f637-5db5-b39f-2e1cfdbf692a"}
@@ -361,6 +361,36 @@ export declare const schoolRouter: import("@trpc/server").TRPCBuiltRouter<{
361
361
  };
362
362
  meta: object;
363
363
  }>;
364
+ getAiUsage: import("@trpc/server").TRPCQueryProcedure<{
365
+ input: {
366
+ schoolId: string;
367
+ startDate?: Date | undefined;
368
+ endDate?: Date | undefined;
369
+ topUsersLimit?: number | undefined;
370
+ };
371
+ output: {
372
+ topUsers: {
373
+ username: string | null;
374
+ displayName: string | null;
375
+ userId: string;
376
+ requests: number;
377
+ promptTokens: number;
378
+ completionTokens: number;
379
+ totalTokens: number;
380
+ }[];
381
+ totals: import("../services/aiUsage.js").UsageBucket;
382
+ byDay: Array<{
383
+ day: string;
384
+ } & import("../services/aiUsage.js").UsageBucket>;
385
+ byModel: Array<{
386
+ model: string;
387
+ } & import("../services/aiUsage.js").UsageBucket>;
388
+ byOperation: Array<{
389
+ operation: string;
390
+ } & import("../services/aiUsage.js").UsageBucket>;
391
+ };
392
+ meta: object;
393
+ }>;
364
394
  listClasses: import("@trpc/server").TRPCQueryProcedure<{
365
395
  input: {
366
396
  schoolId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"school.d.ts","sourceRoot":"/","sources":["routers/school.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAoCxB,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0LvB,CAAC"}
1
+ {"version":3,"file":"school.d.ts","sourceRoot":"/","sources":["routers/school.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAqCxB,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqMvB,CAAC"}
@@ -1,8 +1,9 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="7294ce25-ed53-5755-ad08-cea15228d21b")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="759dd2ee-8976-5f58-97d2-8af3f9706ff4")}catch(e){}}();
3
3
  import { z } from "zod";
4
4
  import { createTRPCRouter, protectedProcedure, publicProcedure, } from "../trpc.js";
5
5
  import { acceptInvite, addMember, confirmSchoolAssetUpload, createInvite, createSchoolClass, createSchoolRecord, getAdminOverview, getCurrentSchool, getInvite, getMemberTimeline, getSchoolAssetUploadUrl, getStudentTimeline, listClasses, listInvites, listMemberIds, listMembers, removeMember, revokeInvite, searchMembers, updateMemberRole, updateSchoolDetails, } from "../services/school.js";
6
+ import { getSchoolAiUsage } from "../services/aiUsage.js";
6
7
  const schoolRoleSchema = z.enum(["ADMIN", "TEACHER", "STUDENT"]);
7
8
  const schoolIdSchema = z.object({
8
9
  schoolId: z.string(),
@@ -71,6 +72,14 @@ export const schoolRouter = createTRPCRouter({
71
72
  getAdminOverview: protectedProcedure
72
73
  .input(schoolIdSchema)
73
74
  .query(({ ctx, input }) => getAdminOverview(ctx.user.id, input.schoolId)),
75
+ getAiUsage: protectedProcedure
76
+ .input(z.object({
77
+ schoolId: z.string(),
78
+ startDate: z.date().optional(),
79
+ endDate: z.date().optional(),
80
+ topUsersLimit: z.number().min(1).max(50).optional(),
81
+ }))
82
+ .query(({ ctx, input }) => getSchoolAiUsage(ctx.user.id, input)),
74
83
  listClasses: protectedProcedure
75
84
  .input(schoolIdSchema)
76
85
  .query(({ ctx, input }) => listClasses(ctx.user.id, input.schoolId)),
@@ -133,4 +142,4 @@ export const schoolRouter = createTRPCRouter({
133
142
  .mutation(({ ctx, input }) => acceptInvite(ctx.user.id, input.token)),
134
143
  });
135
144
  //# sourceMappingURL=school.js.map
136
- //# debugId=7294ce25-ed53-5755-ad08-cea15228d21b
145
+ //# debugId=759dd2ee-8976-5f58-97d2-8af3f9706ff4
@@ -1 +1 @@
1
- {"version":3,"file":"school.js","sources":["routers/school.ts"],"sourceRoot":"/","sourcesContent":["import { z } from \"zod\";\nimport {\n createTRPCRouter,\n protectedProcedure,\n publicProcedure,\n} from \"../trpc.js\";\nimport {\n acceptInvite,\n addMember,\n confirmSchoolAssetUpload,\n createInvite,\n createSchoolClass,\n createSchoolRecord,\n getAdminOverview,\n getCurrentSchool,\n getInvite,\n getMemberTimeline,\n getSchoolAssetUploadUrl,\n getStudentTimeline,\n listClasses,\n listInvites,\n listMemberIds,\n listMembers,\n removeMember,\n revokeInvite,\n searchMembers,\n updateMemberRole,\n updateSchoolDetails,\n} from \"../services/school.js\";\n\nconst schoolRoleSchema = z.enum([\"ADMIN\", \"TEACHER\", \"STUDENT\"]);\n\nconst schoolIdSchema = z.object({\n schoolId: z.string(),\n});\n\nexport const schoolRouter = createTRPCRouter({\n getCurrent: protectedProcedure\n .input(z.object({ schoolId: z.string().optional() }).optional())\n .query(({ ctx, input }) =>\n getCurrentSchool(ctx.user!.id, input?.schoolId)\n ),\n\n create: protectedProcedure\n .input(\n z.object({\n name: z.string().min(1),\n description: z.string().optional(),\n subdomain: z.string().min(1).optional(),\n logoId: z.string().optional(),\n })\n )\n .mutation(({ ctx, input }) => createSchoolRecord(ctx.user!.id, input)),\n\n update: protectedProcedure\n .input(\n z.object({\n schoolId: z.string(),\n name: z.string().min(1).optional(),\n description: z.string().nullable().optional(),\n subdomain: z.string().nullable().optional(),\n logoId: z.string().nullable().optional(),\n })\n )\n .mutation(({ ctx, input }) => updateSchoolDetails(ctx.user!.id, input)),\n\n searchMembers: protectedProcedure\n .input(\n z.object({\n schoolId: z.string(),\n query: z.string(),\n limit: z.number().min(1).max(50).optional(),\n role: schoolRoleSchema.optional(),\n })\n )\n .query(({ ctx, input }) =>\n searchMembers(\n ctx.user!.id,\n input.schoolId,\n input.query,\n input.limit,\n input.role\n )\n ),\n\n listMemberIds: protectedProcedure\n .input(schoolIdSchema)\n .query(({ ctx, input }) => listMemberIds(ctx.user!.id, input.schoolId)),\n\n getAssetUploadUrl: protectedProcedure\n .input(\n z.object({\n fileName: z.string(),\n fileType: z.string(),\n fileSize: z.number(),\n })\n )\n .mutation(({ ctx, input }) =>\n getSchoolAssetUploadUrl(ctx.user!.id, input)\n ),\n\n confirmAssetUpload: protectedProcedure\n .input(\n z.object({\n fileId: z.string(),\n uploadSuccess: z.boolean(),\n })\n )\n .mutation(({ ctx, input }) =>\n confirmSchoolAssetUpload(\n ctx.user!.id,\n input.fileId,\n input.uploadSuccess\n )\n ),\n\n getStudentTimeline: protectedProcedure\n .input(\n z.object({\n schoolId: z.string(),\n studentId: z.string(),\n from: z.date().optional(),\n to: z.date().optional(),\n })\n )\n .query(({ ctx, input }) =>\n getStudentTimeline(ctx.user!.id, input)\n ),\n\n getMemberTimeline: protectedProcedure\n .input(\n z.object({\n schoolId: z.string(),\n memberId: z.string(),\n from: z.date().optional(),\n to: z.date().optional(),\n })\n )\n .query(({ ctx, input }) => getMemberTimeline(ctx.user!.id, input)),\n\n getAdminOverview: protectedProcedure\n .input(schoolIdSchema)\n .query(({ ctx, input }) => getAdminOverview(ctx.user!.id, input.schoolId)),\n\n listClasses: protectedProcedure\n .input(schoolIdSchema)\n .query(({ ctx, input }) => listClasses(ctx.user!.id, input.schoolId)),\n\n createClass: protectedProcedure\n .input(\n z.object({\n schoolId: z.string(),\n name: z.string(),\n section: z.string(),\n subject: z.string(),\n color: z.string().optional(),\n symbol: z.string().nullable().optional(),\n departmentId: z.string().optional(),\n teachers: z.array(z.string()).optional(),\n students: z.array(z.string()).optional(),\n })\n )\n .mutation(({ ctx, input }) => createSchoolClass(ctx.user!.id, input)),\n\n listMembers: protectedProcedure\n .input(schoolIdSchema)\n .query(({ ctx, input }) => listMembers(ctx.user!.id, input.schoolId)),\n\n addMember: protectedProcedure\n .input(\n z.object({\n schoolId: z.string(),\n memberUserId: z.string(),\n role: schoolRoleSchema,\n })\n )\n .mutation(({ ctx, input }) => addMember(ctx.user!.id, input)),\n\n updateMemberRole: protectedProcedure\n .input(\n z.object({\n schoolId: z.string(),\n memberUserId: z.string(),\n role: schoolRoleSchema,\n })\n )\n .mutation(({ ctx, input }) => updateMemberRole(ctx.user!.id, input)),\n\n removeMember: protectedProcedure\n .input(z.object({ schoolId: z.string(), memberUserId: z.string() }))\n .mutation(({ ctx, input }) => removeMember(ctx.user!.id, input)),\n\n listInvites: protectedProcedure\n .input(schoolIdSchema)\n .query(({ ctx, input }) => listInvites(ctx.user!.id, input.schoolId)),\n\n createInvite: protectedProcedure\n .input(\n z.object({\n schoolId: z.string(),\n email: z.string().email(),\n role: schoolRoleSchema,\n username: z\n .string()\n .min(3, \"Username must be at least 3 characters\")\n .optional(),\n displayName: z.string().min(1).optional(),\n })\n )\n .mutation(({ ctx, input }) => createInvite(ctx.user!.id, input)),\n\n revokeInvite: protectedProcedure\n .input(z.object({ schoolId: z.string(), inviteId: z.string() }))\n .mutation(({ ctx, input }) => revokeInvite(ctx.user!.id, input)),\n\n getInvite: publicProcedure\n .input(z.object({ token: z.string() }))\n .query(({ input }) => getInvite(input.token)),\n\n acceptInvite: protectedProcedure\n .input(z.object({ token: z.string() }))\n .mutation(({ ctx, input }) => acceptInvite(ctx.user!.id, input.token)),\n});\n"],"names":[],"mappings":"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","debug_id":"7294ce25-ed53-5755-ad08-cea15228d21b"}
1
+ {"version":3,"file":"school.js","sources":["routers/school.ts"],"sourceRoot":"/","sourcesContent":["import { z } from \"zod\";\nimport {\n createTRPCRouter,\n protectedProcedure,\n publicProcedure,\n} from \"../trpc.js\";\nimport {\n acceptInvite,\n addMember,\n confirmSchoolAssetUpload,\n createInvite,\n createSchoolClass,\n createSchoolRecord,\n getAdminOverview,\n getCurrentSchool,\n getInvite,\n getMemberTimeline,\n getSchoolAssetUploadUrl,\n getStudentTimeline,\n listClasses,\n listInvites,\n listMemberIds,\n listMembers,\n removeMember,\n revokeInvite,\n searchMembers,\n updateMemberRole,\n updateSchoolDetails,\n} from \"../services/school.js\";\nimport { getSchoolAiUsage } from \"../services/aiUsage.js\";\n\nconst schoolRoleSchema = z.enum([\"ADMIN\", \"TEACHER\", \"STUDENT\"]);\n\nconst schoolIdSchema = z.object({\n schoolId: z.string(),\n});\n\nexport const schoolRouter = createTRPCRouter({\n getCurrent: protectedProcedure\n .input(z.object({ schoolId: z.string().optional() }).optional())\n .query(({ ctx, input }) =>\n getCurrentSchool(ctx.user!.id, input?.schoolId)\n ),\n\n create: protectedProcedure\n .input(\n z.object({\n name: z.string().min(1),\n description: z.string().optional(),\n subdomain: z.string().min(1).optional(),\n logoId: z.string().optional(),\n })\n )\n .mutation(({ ctx, input }) => createSchoolRecord(ctx.user!.id, input)),\n\n update: protectedProcedure\n .input(\n z.object({\n schoolId: z.string(),\n name: z.string().min(1).optional(),\n description: z.string().nullable().optional(),\n subdomain: z.string().nullable().optional(),\n logoId: z.string().nullable().optional(),\n })\n )\n .mutation(({ ctx, input }) => updateSchoolDetails(ctx.user!.id, input)),\n\n searchMembers: protectedProcedure\n .input(\n z.object({\n schoolId: z.string(),\n query: z.string(),\n limit: z.number().min(1).max(50).optional(),\n role: schoolRoleSchema.optional(),\n })\n )\n .query(({ ctx, input }) =>\n searchMembers(\n ctx.user!.id,\n input.schoolId,\n input.query,\n input.limit,\n input.role\n )\n ),\n\n listMemberIds: protectedProcedure\n .input(schoolIdSchema)\n .query(({ ctx, input }) => listMemberIds(ctx.user!.id, input.schoolId)),\n\n getAssetUploadUrl: protectedProcedure\n .input(\n z.object({\n fileName: z.string(),\n fileType: z.string(),\n fileSize: z.number(),\n })\n )\n .mutation(({ ctx, input }) =>\n getSchoolAssetUploadUrl(ctx.user!.id, input)\n ),\n\n confirmAssetUpload: protectedProcedure\n .input(\n z.object({\n fileId: z.string(),\n uploadSuccess: z.boolean(),\n })\n )\n .mutation(({ ctx, input }) =>\n confirmSchoolAssetUpload(\n ctx.user!.id,\n input.fileId,\n input.uploadSuccess\n )\n ),\n\n getStudentTimeline: protectedProcedure\n .input(\n z.object({\n schoolId: z.string(),\n studentId: z.string(),\n from: z.date().optional(),\n to: z.date().optional(),\n })\n )\n .query(({ ctx, input }) =>\n getStudentTimeline(ctx.user!.id, input)\n ),\n\n getMemberTimeline: protectedProcedure\n .input(\n z.object({\n schoolId: z.string(),\n memberId: z.string(),\n from: z.date().optional(),\n to: z.date().optional(),\n })\n )\n .query(({ ctx, input }) => getMemberTimeline(ctx.user!.id, input)),\n\n getAdminOverview: protectedProcedure\n .input(schoolIdSchema)\n .query(({ ctx, input }) => getAdminOverview(ctx.user!.id, input.schoolId)),\n\n getAiUsage: protectedProcedure\n .input(\n z.object({\n schoolId: z.string(),\n startDate: z.date().optional(),\n endDate: z.date().optional(),\n topUsersLimit: z.number().min(1).max(50).optional(),\n })\n )\n .query(({ ctx, input }) => getSchoolAiUsage(ctx.user!.id, input)),\n\n listClasses: protectedProcedure\n .input(schoolIdSchema)\n .query(({ ctx, input }) => listClasses(ctx.user!.id, input.schoolId)),\n\n createClass: protectedProcedure\n .input(\n z.object({\n schoolId: z.string(),\n name: z.string(),\n section: z.string(),\n subject: z.string(),\n color: z.string().optional(),\n symbol: z.string().nullable().optional(),\n departmentId: z.string().optional(),\n teachers: z.array(z.string()).optional(),\n students: z.array(z.string()).optional(),\n })\n )\n .mutation(({ ctx, input }) => createSchoolClass(ctx.user!.id, input)),\n\n listMembers: protectedProcedure\n .input(schoolIdSchema)\n .query(({ ctx, input }) => listMembers(ctx.user!.id, input.schoolId)),\n\n addMember: protectedProcedure\n .input(\n z.object({\n schoolId: z.string(),\n memberUserId: z.string(),\n role: schoolRoleSchema,\n })\n )\n .mutation(({ ctx, input }) => addMember(ctx.user!.id, input)),\n\n updateMemberRole: protectedProcedure\n .input(\n z.object({\n schoolId: z.string(),\n memberUserId: z.string(),\n role: schoolRoleSchema,\n })\n )\n .mutation(({ ctx, input }) => updateMemberRole(ctx.user!.id, input)),\n\n removeMember: protectedProcedure\n .input(z.object({ schoolId: z.string(), memberUserId: z.string() }))\n .mutation(({ ctx, input }) => removeMember(ctx.user!.id, input)),\n\n listInvites: protectedProcedure\n .input(schoolIdSchema)\n .query(({ ctx, input }) => listInvites(ctx.user!.id, input.schoolId)),\n\n createInvite: protectedProcedure\n .input(\n z.object({\n schoolId: z.string(),\n email: z.string().email(),\n role: schoolRoleSchema,\n username: z\n .string()\n .min(3, \"Username must be at least 3 characters\")\n .optional(),\n displayName: z.string().min(1).optional(),\n })\n )\n .mutation(({ ctx, input }) => createInvite(ctx.user!.id, input)),\n\n revokeInvite: protectedProcedure\n .input(z.object({ schoolId: z.string(), inviteId: z.string() }))\n .mutation(({ ctx, input }) => revokeInvite(ctx.user!.id, input)),\n\n getInvite: publicProcedure\n .input(z.object({ token: z.string() }))\n .query(({ input }) => getInvite(input.token)),\n\n acceptInvite: protectedProcedure\n .input(z.object({ token: z.string() }))\n .mutation(({ ctx, input }) => acceptInvite(ctx.user!.id, input.token)),\n});\n"],"names":[],"mappings":"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","debug_id":"759dd2ee-8976-5f58-97d2-8af3f9706ff4"}
@@ -132,11 +132,15 @@ export declare const userRouter: import("@trpc/server").TRPCBuiltRouter<{
132
132
  remarks: string | null;
133
133
  }[];
134
134
  notificationsReceived: {
135
+ type: import(".prisma/client").$Enums.NotificationType;
135
136
  id: string;
136
137
  createdAt: Date;
138
+ classId: string | null;
137
139
  title: string;
138
140
  content: string;
139
141
  read: boolean;
142
+ entityType: string | null;
143
+ entityId: string | null;
140
144
  }[];
141
145
  schoolMemberships: {
142
146
  status: import(".prisma/client").$Enums.SchoolMembershipStatus;
@@ -156,6 +160,14 @@ export declare const userRouter: import("@trpc/server").TRPCBuiltRouter<{
156
160
  };
157
161
  meta: object;
158
162
  }>;
163
+ getMyAiUsage: import("@trpc/server").TRPCQueryProcedure<{
164
+ input: {
165
+ startDate?: Date | undefined;
166
+ endDate?: Date | undefined;
167
+ } | undefined;
168
+ output: import("../services/aiUsage.js").UsageAggregation;
169
+ meta: object;
170
+ }>;
159
171
  deleteAccount: import("@trpc/server").TRPCMutationProcedure<{
160
172
  input: {
161
173
  confirmUsername: string;
@@ -1 +1 @@
1
- {"version":3,"file":"user.d.ts","sourceRoot":"/","sources":["routers/user.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAqExB,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCrB,CAAC"}
1
+ {"version":3,"file":"user.d.ts","sourceRoot":"/","sources":["routers/user.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAsExB,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDrB,CAAC"}
@@ -1,10 +1,11 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="10c9f9c2-5706-58e3-b2db-3ca52ac3e956")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="b8d02342-dad1-5c39-b0a5-a1d51df22f8e")}catch(e){}}();
3
3
  import { TRPCError } from "@trpc/server";
4
4
  import { z } from "zod";
5
5
  import { createTRPCRouter, protectedProcedure } from "../trpc.js";
6
6
  import { getProfile, updateProfile, getUploadUrl, } from "../services/user.js";
7
7
  import { deleteUserAccount, exportUserData, } from "../services/userPrivacy.js";
8
+ import { getMyAiUsage } from "../services/aiUsage.js";
8
9
  const fileUploadSchema = z.object({
9
10
  filePath: z.string().min(1, "File path is required"),
10
11
  fileName: z.string().min(1, "File name is required"),
@@ -60,6 +61,14 @@ export const userRouter = createTRPCRouter({
60
61
  .input(getUploadUrlSchema)
61
62
  .mutation(({ ctx, input }) => getUploadUrl(ctx.user.id, input.fileName, input.fileType)),
62
63
  exportData: protectedProcedure.query(({ ctx }) => exportUserData(ctx.user.id)),
64
+ getMyAiUsage: protectedProcedure
65
+ .input(z
66
+ .object({
67
+ startDate: z.date().optional(),
68
+ endDate: z.date().optional(),
69
+ })
70
+ .optional())
71
+ .query(({ ctx, input }) => getMyAiUsage(ctx.user.id, input ?? {})),
63
72
  deleteAccount: protectedProcedure
64
73
  .input(z.object({
65
74
  confirmUsername: z.string().min(1),
@@ -76,4 +85,4 @@ export const userRouter = createTRPCRouter({
76
85
  }),
77
86
  });
78
87
  //# sourceMappingURL=user.js.map
79
- //# debugId=10c9f9c2-5706-58e3-b2db-3ca52ac3e956
88
+ //# debugId=b8d02342-dad1-5c39-b0a5-a1d51df22f8e
@@ -1 +1 @@
1
- {"version":3,"file":"user.js","sources":["routers/user.ts"],"sourceRoot":"/","sourcesContent":["import { TRPCError } from \"@trpc/server\";\nimport { z } from \"zod\";\nimport { createTRPCRouter, protectedProcedure } from \"../trpc.js\";\nimport {\n getProfile,\n updateProfile,\n getUploadUrl,\n} from \"../services/user.js\";\nimport {\n deleteUserAccount,\n exportUserData,\n} from \"../services/userPrivacy.js\";\n\nconst fileUploadSchema = z.object({\n filePath: z.string().min(1, \"File path is required\"),\n fileName: z.string().min(1, \"File name is required\"),\n fileType: z\n .string()\n .regex(\n /^image\\/(jpeg|jpg|png|gif|webp)$/i,\n \"Only image files (JPEG, PNG, GIF, WebP) are allowed\"\n ),\n fileSize: z.number().max(5 * 1024 * 1024, \"File size must be less than 5MB\"),\n});\n\nconst dicebearSchema = z.object({\n url: z.string().url(\"Invalid DiceBear avatar URL\"),\n});\n\nconst profileSchema = z.object({\n displayName: z\n .string()\n .nullable()\n .optional()\n .transform((val) => (val === null ? undefined : val)),\n bio: z\n .string()\n .nullable()\n .optional()\n .transform((val) => (val === null ? undefined : val)),\n location: z\n .string()\n .nullable()\n .optional()\n .transform((val) => (val === null ? undefined : val)),\n website: z\n .union([\n z.string().url(),\n z.literal(\"\"),\n z.null().transform(() => undefined),\n ])\n .optional(),\n});\n\nconst updateProfileSchema = z.object({\n profile: profileSchema.optional(),\n profilePicture: fileUploadSchema.optional(),\n dicebearAvatar: dicebearSchema.optional(),\n});\n\nconst getUploadUrlSchema = z.object({\n fileName: z.string().min(1, \"File name is required\"),\n fileType: z\n .string()\n .regex(\n /^image\\/(jpeg|jpg|png|gif|webp)$/i,\n \"Only image files are allowed\"\n ),\n});\n\nexport const userRouter = createTRPCRouter({\n getProfile: protectedProcedure.query(({ ctx }) =>\n getProfile(ctx.user!.id)\n ),\n\n updateProfile: protectedProcedure\n .input(updateProfileSchema)\n .mutation(({ ctx, input }) =>\n updateProfile(ctx.user!.id, input)\n ),\n\n getUploadUrl: protectedProcedure\n .input(getUploadUrlSchema)\n .mutation(({ ctx, input }) =>\n getUploadUrl(ctx.user!.id, input.fileName, input.fileType)\n ),\n\n exportData: protectedProcedure.query(({ ctx }) =>\n exportUserData(ctx.user!.id),\n ),\n\n deleteAccount: protectedProcedure\n .input(\n z.object({\n confirmUsername: z.string().min(1),\n }),\n )\n .mutation(async ({ ctx, input }) => {\n const profile = await getProfile(ctx.user!.id);\n if (profile.username !== input.confirmUsername) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Username confirmation does not match\",\n });\n }\n return deleteUserAccount(ctx.user!.id);\n }),\n});\n"],"names":[],"mappings":"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","debug_id":"10c9f9c2-5706-58e3-b2db-3ca52ac3e956"}
1
+ {"version":3,"file":"user.js","sources":["routers/user.ts"],"sourceRoot":"/","sourcesContent":["import { TRPCError } from \"@trpc/server\";\nimport { z } from \"zod\";\nimport { createTRPCRouter, protectedProcedure } from \"../trpc.js\";\nimport {\n getProfile,\n updateProfile,\n getUploadUrl,\n} from \"../services/user.js\";\nimport {\n deleteUserAccount,\n exportUserData,\n} from \"../services/userPrivacy.js\";\nimport { getMyAiUsage } from \"../services/aiUsage.js\";\n\nconst fileUploadSchema = z.object({\n filePath: z.string().min(1, \"File path is required\"),\n fileName: z.string().min(1, \"File name is required\"),\n fileType: z\n .string()\n .regex(\n /^image\\/(jpeg|jpg|png|gif|webp)$/i,\n \"Only image files (JPEG, PNG, GIF, WebP) are allowed\"\n ),\n fileSize: z.number().max(5 * 1024 * 1024, \"File size must be less than 5MB\"),\n});\n\nconst dicebearSchema = z.object({\n url: z.string().url(\"Invalid DiceBear avatar URL\"),\n});\n\nconst profileSchema = z.object({\n displayName: z\n .string()\n .nullable()\n .optional()\n .transform((val) => (val === null ? undefined : val)),\n bio: z\n .string()\n .nullable()\n .optional()\n .transform((val) => (val === null ? undefined : val)),\n location: z\n .string()\n .nullable()\n .optional()\n .transform((val) => (val === null ? undefined : val)),\n website: z\n .union([\n z.string().url(),\n z.literal(\"\"),\n z.null().transform(() => undefined),\n ])\n .optional(),\n});\n\nconst updateProfileSchema = z.object({\n profile: profileSchema.optional(),\n profilePicture: fileUploadSchema.optional(),\n dicebearAvatar: dicebearSchema.optional(),\n});\n\nconst getUploadUrlSchema = z.object({\n fileName: z.string().min(1, \"File name is required\"),\n fileType: z\n .string()\n .regex(\n /^image\\/(jpeg|jpg|png|gif|webp)$/i,\n \"Only image files are allowed\"\n ),\n});\n\nexport const userRouter = createTRPCRouter({\n getProfile: protectedProcedure.query(({ ctx }) =>\n getProfile(ctx.user!.id)\n ),\n\n updateProfile: protectedProcedure\n .input(updateProfileSchema)\n .mutation(({ ctx, input }) =>\n updateProfile(ctx.user!.id, input)\n ),\n\n getUploadUrl: protectedProcedure\n .input(getUploadUrlSchema)\n .mutation(({ ctx, input }) =>\n getUploadUrl(ctx.user!.id, input.fileName, input.fileType)\n ),\n\n exportData: protectedProcedure.query(({ ctx }) =>\n exportUserData(ctx.user!.id),\n ),\n\n getMyAiUsage: protectedProcedure\n .input(\n z\n .object({\n startDate: z.date().optional(),\n endDate: z.date().optional(),\n })\n .optional(),\n )\n .query(({ ctx, input }) => getMyAiUsage(ctx.user!.id, input ?? {})),\n\n deleteAccount: protectedProcedure\n .input(\n z.object({\n confirmUsername: z.string().min(1),\n }),\n )\n .mutation(async ({ ctx, input }) => {\n const profile = await getProfile(ctx.user!.id);\n if (profile.username !== input.confirmUsername) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Username confirmation does not match\",\n });\n }\n return deleteUserAccount(ctx.user!.id);\n }),\n});\n"],"names":[],"mappings":"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","debug_id":"b8d02342-dad1-5c39-b0a5-a1d51df22f8e"}
@@ -90,6 +90,7 @@ export declare const worksheetRouter: import("@trpc/server").TRPCBuiltRouter<{
90
90
  }[];
91
91
  questions: {
92
92
  id: string;
93
+ question: string;
93
94
  }[];
94
95
  status: import(".prisma/client").$Enums.JobStatus | null;
95
96
  id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"worksheet.d.ts","sourceRoot":"/","sources":["routers/worksheet.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA0DxB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8Z1B,CAAC"}
1
+ {"version":3,"file":"worksheet.d.ts","sourceRoot":"/","sources":["routers/worksheet.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA0DxB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8Z1B,CAAC"}
@@ -10,13 +10,17 @@ export declare function createUser(email: string, password: string, username: st
10
10
  schoolId: string | null;
11
11
  }>;
12
12
  export declare function addNotification(userId: string, title: string, content: string): Promise<{
13
+ type: import(".prisma/client").$Enums.NotificationType;
13
14
  id: string;
14
15
  createdAt: Date;
16
+ classId: string | null;
15
17
  title: string;
16
18
  content: string;
17
19
  senderId: string | null;
18
20
  read: boolean;
19
21
  receiverId: string;
22
+ entityType: string | null;
23
+ entityId: string | null;
20
24
  }>;
21
25
  export declare const seedDatabase: () => Promise<void>;
22
26
  //# sourceMappingURL=seedDatabase.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"seedDatabase.d.ts","sourceRoot":"/","sources":["seedDatabase.ts"],"names":[],"mappings":"AAwBA,wBAAsB,aAAa,kBA+ElC;AA6CD,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;;;;;;;;;GAKjF;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;;;;;;;;GAQnF;AA+HD,eAAO,MAAM,YAAY,qBAskDxB,CAAC"}
1
+ {"version":3,"file":"seedDatabase.d.ts","sourceRoot":"/","sources":["seedDatabase.ts"],"names":[],"mappings":"AAwBA,wBAAsB,aAAa,kBA+ElC;AA6CD,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;;;;;;;;;GAKjF;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;;;;;;;;;;;;GAQnF;AA+HD,eAAO,MAAM,YAAY,qBAskDxB,CAAC"}
@@ -12,6 +12,7 @@
12
12
  * terminal `message-stream-complete` / `message-updated` events.
13
13
  */
14
14
  import { type ModelMessage, type ToolSet } from 'ai';
15
+ import { type AiUsageAttribution } from '../utils/inference.js';
15
16
  /** Default streaming model — matches the existing streamAIResponse path. */
16
17
  export declare const DEFAULT_STREAM_MODEL = "gpt-4o-mini";
17
18
  export interface StreamedToolCall {
@@ -71,6 +72,10 @@ export interface StreamChatOptions {
71
72
  maxOutputTokens?: number;
72
73
  /** Max agent steps (tool round-trips). Defaults to 6. */
73
74
  maxSteps?: number;
75
+ /** Reason recorded on the AiUsageLog row. Defaults to 'chat_stream'. */
76
+ usageReason?: string;
77
+ /** Who/what this usage is attributed to (user / school / class). */
78
+ attribution?: AiUsageAttribution;
74
79
  }
75
80
  export interface StreamChatResult {
76
81
  text: string;
@@ -1 +1 @@
1
- {"version":3,"file":"aiChatStream.d.ts","sourceRoot":"/","sources":["services/aiChatStream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAA2B,KAAK,YAAY,EAAE,KAAK,OAAO,EAAE,MAAM,IAAI,CAAC;AAS9E,4EAA4E;AAC5E,eAAO,MAAM,oBAAoB,gBAAgB,CAAC;AAElD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,KAAK,EAAE,OAAO,CAAC;IACf,6EAA6E;IAC7E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,WAAW,GAAG,QAAQ,CAAC;CAChC;AAED;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IACE,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,QAAQ,CAAC;CAC9C,CAAC;AAEN,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,yEAAyE;AACzE,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,UAAU,EAAE,EACnB,IAAI,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,GAC7C,UAAU,EAAE,CAmBd;AASD,mFAAmF;AACnF,wBAAgB,mCAAmC,CACjD,KAAK,EAAE,UAAU,EAAE,EACnB,KAAK,EAAE,oBAAoB,EAAE,GAC5B,UAAU,EAAE,CAuCd;AAED,iGAAiG;AACjG,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAS3E;AAmBD,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,2EAA2E;IAC3E,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,gBAAgB,CAAC,CA8I3B"}
1
+ {"version":3,"file":"aiChatStream.d.ts","sourceRoot":"/","sources":["services/aiChatStream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAA2B,KAAK,YAAY,EAAE,KAAK,OAAO,EAAE,MAAM,IAAI,CAAC;AAK9E,OAAO,EAAqB,KAAK,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAKnF,4EAA4E;AAC5E,eAAO,MAAM,oBAAoB,gBAAgB,CAAC;AAElD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,KAAK,EAAE,OAAO,CAAC;IACf,6EAA6E;IAC7E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,WAAW,GAAG,QAAQ,CAAC;CAChC;AAED;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IACE,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,QAAQ,CAAC;CAC9C,CAAC;AAEN,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,yEAAyE;AACzE,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,UAAU,EAAE,EACnB,IAAI,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,GAC7C,UAAU,EAAE,CAmBd;AASD,mFAAmF;AACnF,wBAAgB,mCAAmC,CACjD,KAAK,EAAE,UAAU,EAAE,EACnB,KAAK,EAAE,oBAAoB,EAAE,GAC5B,UAAU,EAAE,CAuCd;AAED,iGAAiG;AACjG,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAS3E;AAmBD,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,2EAA2E;IAC3E,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,gBAAgB,CAAC,CA4K3B"}
@@ -12,12 +12,13 @@
12
12
  * terminal `message-stream-complete` / `message-updated` events.
13
13
  */
14
14
 
15
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="5a03c108-e33a-50c7-a5fd-24f570b1b507")}catch(e){}}();
15
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="b26c8408-f190-53b7-8fce-428be7591574")}catch(e){}}();
16
16
  import { streamText, stepCountIs } from 'ai';
17
17
  import { openai } from '@ai-sdk/openai';
18
18
  import { getRedis } from '../lib/redis.js';
19
19
  import { pusher, chatChannel } from '../lib/pusher.js';
20
20
  import { logger } from '../utils/logger.js';
21
+ import { logInferenceUsage } from '../utils/inference.js';
21
22
  const STREAM_REDIS_TTL = 600; // 10 minutes
22
23
  const STREAM_KEY_PREFIX = 'stream:';
23
24
  /** Default streaming model — matches the existing streamAIResponse path. */
@@ -121,7 +122,7 @@ function toolTitleFromInput(input) {
121
122
  * final `content`/`meta` (e.g. PDF attachments, structured proposals).
122
123
  */
123
124
  export async function streamChatResponse(options) {
124
- const { conversationId, aiMessageId, system, messages, tools, model = DEFAULT_STREAM_MODEL, temperature = 0.7, maxOutputTokens = 4096, maxSteps = 6, } = options;
125
+ const { conversationId, aiMessageId, system, messages, tools, model = DEFAULT_STREAM_MODEL, temperature = 0.7, maxOutputTokens = 4096, maxSteps = 6, usageReason = 'chat_stream', attribution, } = options;
125
126
  const redis = getRedis();
126
127
  const streamKey = `${STREAM_KEY_PREFIX}${aiMessageId}`;
127
128
  if (redis) {
@@ -242,8 +243,36 @@ export async function streamChatResponse(options) {
242
243
  break;
243
244
  }
244
245
  }
246
+ const usage = await Promise.resolve(result.totalUsage).catch(() => undefined);
247
+ await logInferenceUsage({
248
+ model,
249
+ operation: 'stream.text',
250
+ success: true,
251
+ estimatedInputTokens: 0,
252
+ reason: usageReason,
253
+ usage: usage
254
+ ? {
255
+ promptTokens: usage.inputTokens,
256
+ completionTokens: usage.outputTokens,
257
+ totalTokens: usage.totalTokens,
258
+ }
259
+ : undefined,
260
+ attribution,
261
+ });
245
262
  return { text: fullText, toolCalls, parts };
246
263
  }
264
+ catch (error) {
265
+ await logInferenceUsage({
266
+ model,
267
+ operation: 'stream.text',
268
+ success: false,
269
+ estimatedInputTokens: 0,
270
+ reason: usageReason,
271
+ error,
272
+ attribution,
273
+ });
274
+ throw error;
275
+ }
247
276
  finally {
248
277
  if (redis) {
249
278
  await redis.del(streamKey).catch(() => { });
@@ -251,4 +280,4 @@ export async function streamChatResponse(options) {
251
280
  }
252
281
  }
253
282
  //# sourceMappingURL=aiChatStream.js.map
254
- //# debugId=5a03c108-e33a-50c7-a5fd-24f570b1b507
283
+ //# debugId=b26c8408-f190-53b7-8fce-428be7591574