@studious-lms/server 1.12.0 → 1.14.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 (338) hide show
  1. package/.dockerignore +28 -0
  2. package/.env.example +5 -0
  3. package/.github/workflows/deploy.yml +123 -0
  4. package/Dockerfile +54 -0
  5. package/dist/index.js +5 -2
  6. package/dist/index.js.map +1 -1
  7. package/dist/lib/config/cors.d.ts.map +1 -1
  8. package/dist/lib/config/cors.js +31 -11
  9. package/dist/lib/config/cors.js.map +1 -1
  10. package/dist/lib/config/env.d.ts +17 -0
  11. package/dist/lib/config/env.d.ts.map +1 -1
  12. package/dist/lib/config/env.js +8 -2
  13. package/dist/lib/config/env.js.map +1 -1
  14. package/dist/lib/googleCloudStorage.d.ts +10 -0
  15. package/dist/lib/googleCloudStorage.d.ts.map +1 -1
  16. package/dist/lib/googleCloudStorage.js +22 -2
  17. package/dist/lib/googleCloudStorage.js.map +1 -1
  18. package/dist/lib/prisma.d.ts +104 -5
  19. package/dist/lib/prisma.d.ts.map +1 -1
  20. package/dist/lib/prisma.js +33 -2
  21. package/dist/lib/prisma.js.map +1 -1
  22. package/dist/models/agenda.d.ts +20 -20
  23. package/dist/models/announcement.d.ts +177 -69
  24. package/dist/models/announcement.d.ts.map +1 -1
  25. package/dist/models/assignment.d.ts +551 -353
  26. package/dist/models/assignment.d.ts.map +1 -1
  27. package/dist/models/attendance.d.ts +197 -71
  28. package/dist/models/attendance.d.ts.map +1 -1
  29. package/dist/models/auth.d.ts +348 -114
  30. package/dist/models/auth.d.ts.map +1 -1
  31. package/dist/models/class.d.ts +324 -188
  32. package/dist/models/class.d.ts.map +1 -1
  33. package/dist/models/class.js +9 -3
  34. package/dist/models/class.js.map +1 -1
  35. package/dist/models/cloudStorage.d.ts +146 -56
  36. package/dist/models/cloudStorage.d.ts.map +1 -1
  37. package/dist/models/comment.d.ts +269 -110
  38. package/dist/models/comment.d.ts.map +1 -1
  39. package/dist/models/comment.js +3 -2
  40. package/dist/models/comment.js.map +1 -1
  41. package/dist/models/conversation.d.ts +206 -63
  42. package/dist/models/conversation.d.ts.map +1 -1
  43. package/dist/models/conversation.js +13 -2
  44. package/dist/models/conversation.js.map +1 -1
  45. package/dist/models/department.d.ts +196 -70
  46. package/dist/models/department.d.ts.map +1 -1
  47. package/dist/models/event.d.ts +287 -125
  48. package/dist/models/event.d.ts.map +1 -1
  49. package/dist/models/file.d.ts +389 -263
  50. package/dist/models/file.d.ts.map +1 -1
  51. package/dist/models/folder.d.ts +433 -181
  52. package/dist/models/folder.d.ts.map +1 -1
  53. package/dist/models/labChat.d.ts +209 -83
  54. package/dist/models/labChat.d.ts.map +1 -1
  55. package/dist/models/marketing.d.ts +80 -26
  56. package/dist/models/marketing.d.ts.map +1 -1
  57. package/dist/models/message.d.ts +95 -41
  58. package/dist/models/message.d.ts.map +1 -1
  59. package/dist/models/newtonChat.d.ts +83 -29
  60. package/dist/models/newtonChat.d.ts.map +1 -1
  61. package/dist/models/notification.d.ts +61 -25
  62. package/dist/models/notification.d.ts.map +1 -1
  63. package/dist/models/school.d.ts +349 -133
  64. package/dist/models/school.d.ts.map +1 -1
  65. package/dist/models/section.d.ts +216 -72
  66. package/dist/models/section.d.ts.map +1 -1
  67. package/dist/models/tag.d.ts +156 -48
  68. package/dist/models/tag.d.ts.map +1 -1
  69. package/dist/models/user.d.ts +82 -28
  70. package/dist/models/user.d.ts.map +1 -1
  71. package/dist/models/worksheet.d.ts +1023 -410
  72. package/dist/models/worksheet.d.ts.map +1 -1
  73. package/dist/models/worksheet.js +19 -7
  74. package/dist/models/worksheet.js.map +1 -1
  75. package/dist/pipelines/aiLabChat.d.ts +0 -8
  76. package/dist/pipelines/aiLabChat.d.ts.map +1 -1
  77. package/dist/pipelines/aiLabChat.js +50 -67
  78. package/dist/pipelines/aiLabChat.js.map +1 -1
  79. package/dist/pipelines/aiLabChatContract.d.ts +393 -388
  80. package/dist/pipelines/aiLabChatContract.d.ts.map +1 -1
  81. package/dist/pipelines/aiLabChatContract.js +63 -69
  82. package/dist/pipelines/aiLabChatContract.js.map +1 -1
  83. package/dist/pipelines/aiNewtonChat.d.ts.map +1 -1
  84. package/dist/pipelines/aiNewtonChat.js +41 -41
  85. package/dist/pipelines/aiNewtonChat.js.map +1 -1
  86. package/dist/pipelines/gradeWorksheet.d.ts +8 -8
  87. package/dist/pipelines/gradeWorksheet.d.ts.map +1 -1
  88. package/dist/pipelines/gradeWorksheet.js +59 -14
  89. package/dist/pipelines/gradeWorksheet.js.map +1 -1
  90. package/dist/pipelines/labChatPrompt.d.ts +10 -8
  91. package/dist/pipelines/labChatPrompt.d.ts.map +1 -1
  92. package/dist/pipelines/labChatPrompt.js +47 -67
  93. package/dist/pipelines/labChatPrompt.js.map +1 -1
  94. package/dist/pipelines/pdfToWorksheet.d.ts +2 -2
  95. package/dist/routers/_app.d.ts +2268 -1898
  96. package/dist/routers/_app.d.ts.map +1 -1
  97. package/dist/routers/_app.js +4 -2
  98. package/dist/routers/_app.js.map +1 -1
  99. package/dist/routers/admin.d.ts +13 -13
  100. package/dist/routers/agenda.d.ts +18 -18
  101. package/dist/routers/announcement.d.ts +32 -28
  102. package/dist/routers/announcement.d.ts.map +1 -1
  103. package/dist/routers/announcement.js +6 -5
  104. package/dist/routers/announcement.js.map +1 -1
  105. package/dist/routers/assignment.d.ts +335 -327
  106. package/dist/routers/assignment.d.ts.map +1 -1
  107. package/dist/routers/assignment.js +4 -4
  108. package/dist/routers/assignment.js.map +1 -1
  109. package/dist/routers/attendance.d.ts +10 -10
  110. package/dist/routers/auth.d.ts +2 -2
  111. package/dist/routers/class.d.ts +170 -147
  112. package/dist/routers/class.d.ts.map +1 -1
  113. package/dist/routers/comment.d.ts +40 -16
  114. package/dist/routers/comment.d.ts.map +1 -1
  115. package/dist/routers/comment.js +6 -3
  116. package/dist/routers/comment.js.map +1 -1
  117. package/dist/routers/conversation.d.ts +17 -17
  118. package/dist/routers/department.d.ts +34 -34
  119. package/dist/routers/discussion.d.ts +65 -53
  120. package/dist/routers/discussion.d.ts.map +1 -1
  121. package/dist/routers/discussion.js +6 -2
  122. package/dist/routers/discussion.js.map +1 -1
  123. package/dist/routers/embedding.d.ts +69 -0
  124. package/dist/routers/embedding.d.ts.map +1 -0
  125. package/dist/routers/embedding.js +143 -0
  126. package/dist/routers/embedding.js.map +1 -0
  127. package/dist/routers/event.d.ts +39 -39
  128. package/dist/routers/file.d.ts +12 -12
  129. package/dist/routers/folder.d.ts +38 -38
  130. package/dist/routers/labChat.d.ts +19 -19
  131. package/dist/routers/marketing.d.ts +2 -2
  132. package/dist/routers/message.d.ts +13 -13
  133. package/dist/routers/newtonChat.d.ts +4 -4
  134. package/dist/routers/notifications.d.ts +9 -9
  135. package/dist/routers/permissions.d.ts +14 -14
  136. package/dist/routers/school.d.ts +55 -55
  137. package/dist/routers/search.d.ts +22 -1
  138. package/dist/routers/search.d.ts.map +1 -1
  139. package/dist/routers/search.js +9 -3
  140. package/dist/routers/search.js.map +1 -1
  141. package/dist/routers/section.d.ts +4 -4
  142. package/dist/routers/studentProgress.d.ts +1 -1
  143. package/dist/routers/tag.d.ts +7 -7
  144. package/dist/routers/user.d.ts +10 -10
  145. package/dist/routers/worksheet.d.ts +97 -56
  146. package/dist/routers/worksheet.d.ts.map +1 -1
  147. package/dist/routers/worksheet.js +28 -2
  148. package/dist/routers/worksheet.js.map +1 -1
  149. package/dist/routes/aiStream.d.ts +2 -0
  150. package/dist/routes/aiStream.d.ts.map +1 -0
  151. package/dist/routes/aiStream.js +696 -0
  152. package/dist/routes/aiStream.js.map +1 -0
  153. package/dist/seedDatabase.d.ts +2 -2
  154. package/dist/seedDatabase.js +6 -6
  155. package/dist/seedDatabase.js.map +1 -1
  156. package/dist/services/adminInstitution.d.ts +8 -8
  157. package/dist/services/adminRunJob.d.ts +4 -4
  158. package/dist/services/agenda.d.ts +18 -18
  159. package/dist/services/aiChatStream.d.ts +68 -0
  160. package/dist/services/aiChatStream.d.ts.map +1 -0
  161. package/dist/services/aiChatStream.js +157 -0
  162. package/dist/services/aiChatStream.js.map +1 -0
  163. package/dist/services/aiModifierTools.d.ts +32 -0
  164. package/dist/services/aiModifierTools.d.ts.map +1 -0
  165. package/dist/services/aiModifierTools.js +165 -0
  166. package/dist/services/aiModifierTools.js.map +1 -0
  167. package/dist/services/aiProposalTools.d.ts +32 -0
  168. package/dist/services/aiProposalTools.d.ts.map +1 -0
  169. package/dist/services/aiProposalTools.js +207 -0
  170. package/dist/services/aiProposalTools.js.map +1 -0
  171. package/dist/services/aiStream.d.ts +22 -0
  172. package/dist/services/aiStream.d.ts.map +1 -0
  173. package/dist/services/aiStream.js +142 -0
  174. package/dist/services/aiStream.js.map +1 -0
  175. package/dist/services/aiTools.d.ts +16 -0
  176. package/dist/services/aiTools.d.ts.map +1 -0
  177. package/dist/services/aiTools.js +271 -0
  178. package/dist/services/aiTools.js.map +1 -0
  179. package/dist/services/announcement.d.ts +12 -12
  180. package/dist/services/announcement.d.ts.map +1 -1
  181. package/dist/services/announcement.js +7 -2
  182. package/dist/services/announcement.js.map +1 -1
  183. package/dist/services/assignment.d.ts +293 -293
  184. package/dist/services/assignment.d.ts.map +1 -1
  185. package/dist/services/assignment.js +36 -15
  186. package/dist/services/assignment.js.map +1 -1
  187. package/dist/services/attendance.d.ts +10 -10
  188. package/dist/services/auth.d.ts +2 -2
  189. package/dist/services/class.d.ts +161 -138
  190. package/dist/services/class.d.ts.map +1 -1
  191. package/dist/services/class.js +25 -4
  192. package/dist/services/class.js.map +1 -1
  193. package/dist/services/comment.d.ts +34 -16
  194. package/dist/services/comment.d.ts.map +1 -1
  195. package/dist/services/comment.js +23 -2
  196. package/dist/services/comment.js.map +1 -1
  197. package/dist/services/conversation.d.ts +17 -17
  198. package/dist/services/conversation.d.ts.map +1 -1
  199. package/dist/services/conversation.js +9 -7
  200. package/dist/services/conversation.js.map +1 -1
  201. package/dist/services/department.d.ts +33 -33
  202. package/dist/services/discussion.d.ts +58 -58
  203. package/dist/services/discussion.d.ts.map +1 -1
  204. package/dist/services/discussion.js +8 -8
  205. package/dist/services/discussion.js.map +1 -1
  206. package/dist/services/discussionSummary.d.ts +21 -0
  207. package/dist/services/discussionSummary.d.ts.map +1 -0
  208. package/dist/services/discussionSummary.js +179 -0
  209. package/dist/services/discussionSummary.js.map +1 -0
  210. package/dist/services/embedding.d.ts +67 -0
  211. package/dist/services/embedding.d.ts.map +1 -0
  212. package/dist/services/embedding.js +226 -0
  213. package/dist/services/embedding.js.map +1 -0
  214. package/dist/services/event.d.ts +37 -37
  215. package/dist/services/file.d.ts +24 -24
  216. package/dist/services/folder.d.ts +36 -36
  217. package/dist/services/labChat.d.ts +19 -19
  218. package/dist/services/marketing.d.ts +2 -2
  219. package/dist/services/message.d.ts +11 -11
  220. package/dist/services/message.d.ts.map +1 -1
  221. package/dist/services/message.js +2 -2
  222. package/dist/services/message.js.map +1 -1
  223. package/dist/services/newtonChat.d.ts +4 -4
  224. package/dist/services/notification.d.ts +9 -9
  225. package/dist/services/notification.d.ts.map +1 -1
  226. package/dist/services/permissions.d.ts +14 -14
  227. package/dist/services/school.d.ts +50 -50
  228. package/dist/services/search.d.ts +12 -0
  229. package/dist/services/search.d.ts.map +1 -1
  230. package/dist/services/search.js +120 -2
  231. package/dist/services/search.js.map +1 -1
  232. package/dist/services/section.d.ts +3 -3
  233. package/dist/services/tag.d.ts +4 -4
  234. package/dist/services/user.d.ts +4 -4
  235. package/dist/services/user.d.ts.map +1 -1
  236. package/dist/services/user.js +10 -15
  237. package/dist/services/user.js.map +1 -1
  238. package/dist/services/worksheet.d.ts +62 -47
  239. package/dist/services/worksheet.d.ts.map +1 -1
  240. package/dist/services/worksheet.js +11 -4
  241. package/dist/services/worksheet.js.map +1 -1
  242. package/dist/utils/streamBroadcast.d.ts +11 -0
  243. package/dist/utils/streamBroadcast.d.ts.map +1 -0
  244. package/dist/utils/streamBroadcast.js +32 -0
  245. package/dist/utils/streamBroadcast.js.map +1 -0
  246. package/dist/workers/connection.d.ts +15 -0
  247. package/dist/workers/connection.d.ts.map +1 -1
  248. package/dist/workers/connection.js +20 -2
  249. package/dist/workers/connection.js.map +1 -1
  250. package/dist/workers/index.js +4 -2
  251. package/dist/workers/index.js.map +1 -1
  252. package/dist/workers/processors/createRunJobWorker.d.ts.map +1 -1
  253. package/dist/workers/processors/createRunJobWorker.js +31 -8
  254. package/dist/workers/processors/createRunJobWorker.js.map +1 -1
  255. package/dist/workers/processors/embedContent.d.ts +8 -0
  256. package/dist/workers/processors/embedContent.d.ts.map +1 -0
  257. package/dist/workers/processors/embedContent.js +76 -0
  258. package/dist/workers/processors/embedContent.js.map +1 -0
  259. package/dist/workers/queues.d.ts +6 -0
  260. package/dist/workers/queues.d.ts.map +1 -1
  261. package/dist/workers/queues.js +5 -3
  262. package/dist/workers/queues.js.map +1 -1
  263. package/package.json +5 -1
  264. package/prisma/migrations/20260609215135_init/migration.sql +1412 -0
  265. package/prisma/migrations/20260610130000_add_worksheet_tags/migration.sql +13 -0
  266. package/prisma/schema.prisma +39 -7
  267. package/src/index.ts +4 -0
  268. package/src/lib/config/cors.ts +32 -9
  269. package/src/lib/config/env.ts +6 -0
  270. package/src/lib/googleCloudStorage.ts +21 -0
  271. package/src/lib/prisma.ts +40 -1
  272. package/src/models/class.ts +10 -3
  273. package/src/models/comment.ts +1 -0
  274. package/src/models/conversation.ts +12 -0
  275. package/src/models/worksheet.ts +16 -7
  276. package/src/pipelines/aiLabChat.ts +54 -79
  277. package/src/pipelines/aiLabChatContract.ts +69 -69
  278. package/src/pipelines/aiNewtonChat.ts +46 -43
  279. package/src/pipelines/gradeWorksheet.ts +66 -15
  280. package/src/pipelines/labChatPrompt.ts +63 -88
  281. package/src/routers/_app.ts +2 -0
  282. package/src/routers/announcement.ts +4 -3
  283. package/src/routers/assignment.ts +2 -2
  284. package/src/routers/comment.ts +5 -0
  285. package/src/routers/discussion.ts +7 -0
  286. package/src/routers/embedding.ts +159 -0
  287. package/src/routers/search.ts +10 -1
  288. package/src/routers/worksheet.ts +29 -0
  289. package/src/routes/aiStream.ts +789 -0
  290. package/src/seedDatabase.ts +4 -4
  291. package/src/services/aiChatStream.ts +219 -0
  292. package/src/services/aiModifierTools.ts +188 -0
  293. package/src/services/aiProposalTools.ts +272 -0
  294. package/src/services/aiStream.ts +175 -0
  295. package/src/services/aiTools.ts +290 -0
  296. package/src/services/announcement.ts +7 -0
  297. package/src/services/assignment.ts +36 -14
  298. package/src/services/class.ts +30 -2
  299. package/src/services/comment.ts +22 -0
  300. package/src/services/conversation.ts +9 -4
  301. package/src/services/discussion.ts +9 -8
  302. package/src/services/discussionSummary.ts +226 -0
  303. package/src/services/embedding.ts +285 -0
  304. package/src/services/message.ts +2 -2
  305. package/src/services/search.ts +138 -0
  306. package/src/services/user.ts +9 -17
  307. package/src/services/worksheet.ts +10 -2
  308. package/src/utils/streamBroadcast.ts +48 -0
  309. package/src/workers/connection.ts +19 -0
  310. package/src/workers/index.ts +2 -0
  311. package/src/workers/processors/createRunJobWorker.ts +32 -6
  312. package/src/workers/processors/embedContent.ts +90 -0
  313. package/src/workers/queues.ts +5 -1
  314. package/tests/integration/routers/conversation.test.ts +9 -7
  315. package/tests/unit/pipelines/aiLabChatContract.test.ts +38 -21
  316. package/tests/unit/pipelines/labChatPrompt.test.ts +23 -36
  317. package/prisma/migrations/20250807062924_init/migration.sql +0 -436
  318. package/prisma/migrations/20250919063704_init2/migration.sql +0 -24
  319. package/prisma/migrations/20250920143543_add_profile_fields/migration.sql +0 -15
  320. package/prisma/migrations/20250922165147_add_chat_models/migration.sql +0 -68
  321. package/prisma/migrations/20250922165314_add_chat_roles/migration.sql +0 -5
  322. package/prisma/migrations/20250922171242_refactor_notification_system/migration.sql +0 -20
  323. package/prisma/migrations/20250922172208_add_mentions_system/migration.sql +0 -21
  324. package/prisma/migrations/20250925072732_add_lab_chat_system/migration.sql +0 -25
  325. package/prisma/migrations/20251020151505_add_upload_tracking_fields/migration.sql +0 -57
  326. package/prisma/migrations/20251109122857_annuoncements_comments/migration.sql +0 -30
  327. package/prisma/migrations/20251109135555_reactions_announcements_comments/migration.sql +0 -35
  328. package/prisma/migrations/20260410124000_add_submission_recommendation_state/migration.sql +0 -14
  329. package/prisma/migrations/20260415103500_add_session_type/migration.sql +0 -33
  330. package/prisma/migrations/20260415133000_add_ai_usage_logs/migration.sql +0 -19
  331. package/prisma/migrations/20260417083000_add_conversation_member_hidden_at/migration.sql +0 -2
  332. package/prisma/migrations/20260502230500_assignment_submission_comments/migration.sql +0 -60
  333. package/prisma/migrations/20260504071500_school_memberships/migration.sql +0 -81
  334. package/prisma/migrations/20260506162500_consolidate_run_job_and_unify_job_status/migration.sql +0 -166
  335. package/prisma/migrations/20260509220000_institution_overhaul/migration.sql +0 -184
  336. package/prisma/migrations/20260510170000_add_folder_permissions/migration.sql +0 -93
  337. package/prisma/migrations/20260510183000_add_discussions/migration.sql +0 -151
  338. /package/.github/workflows/{npm.yml → npm-publish.yml} +0 -0
@@ -2,88 +2,100 @@ import { type WorksheetQuestionType } from "@prisma/client";
2
2
  /** Get worksheet with questions and mark schemes. */
3
3
  export declare function getWorksheet(worksheetId: string, userId: string): Promise<{
4
4
  class: {
5
- name: string;
5
+ section: string;
6
6
  id: string;
7
+ name: string;
7
8
  schoolId: string | null;
8
- subject: string;
9
9
  color: string | null;
10
- section: string;
10
+ subject: string;
11
11
  syllabus: string | null;
12
12
  departmentId: string | null;
13
13
  discussionsEnabled: boolean;
14
14
  studentsCanCreateDiscussions: boolean;
15
15
  studentsCanReply: boolean;
16
16
  } | null;
17
+ tags: {
18
+ id: string;
19
+ name: string;
20
+ color: string;
21
+ classId: string;
22
+ }[];
17
23
  questions: {
18
24
  type: import(".prisma/client").$Enums.WorksheetQuestionType;
19
25
  options: import("@prisma/client/runtime/library.js").JsonValue | null;
26
+ markScheme: import("@prisma/client/runtime/library.js").JsonValue | null;
20
27
  id: string;
21
28
  createdAt: Date;
22
29
  updatedAt: Date;
23
30
  order: number | null;
24
- points: number;
25
31
  worksheetId: string;
26
- markScheme: import("@prisma/client/runtime/library.js").JsonValue | null;
27
32
  question: string;
28
33
  answer: string;
34
+ points: number;
29
35
  }[];
30
36
  } & {
31
37
  status: import(".prisma/client").$Enums.JobStatus | null;
32
- name: string;
33
38
  id: string;
34
39
  createdAt: Date;
35
40
  updatedAt: Date;
41
+ name: string;
36
42
  classId: string;
37
- runJobId: string | null;
38
43
  sourceUrl: string | null;
44
+ runJobId: string | null;
39
45
  }>;
40
46
  /** Check if worksheet exists. */
41
47
  export declare function worksheetExists(id: string): Promise<boolean>;
42
48
  export declare function listWorksheets(classId: string): Promise<{
43
49
  questionCount: number;
50
+ tags: {
51
+ id: string;
52
+ name: string;
53
+ color: string;
54
+ classId: string;
55
+ }[];
44
56
  questions: {
45
57
  id: string;
46
58
  }[];
47
59
  status: import(".prisma/client").$Enums.JobStatus | null;
48
- name: string;
49
60
  id: string;
50
61
  createdAt: Date;
51
62
  updatedAt: Date;
63
+ name: string;
52
64
  classId: string;
53
- runJobId: string | null;
54
65
  sourceUrl: string | null;
66
+ runJobId: string | null;
55
67
  }[]>;
56
68
  export declare function updateWorksheetRecord(worksheetId: string, userId: string, data: {
57
69
  name?: string;
58
70
  }): Promise<{
59
71
  status: import(".prisma/client").$Enums.JobStatus | null;
60
- name: string;
61
72
  id: string;
62
73
  createdAt: Date;
63
74
  updatedAt: Date;
75
+ name: string;
64
76
  classId: string;
65
- runJobId: string | null;
66
77
  sourceUrl: string | null;
78
+ runJobId: string | null;
67
79
  }>;
68
80
  export declare function deleteWorksheetRecord(worksheetId: string, userId: string): Promise<{
69
81
  status: import(".prisma/client").$Enums.JobStatus | null;
70
- name: string;
71
82
  id: string;
72
83
  createdAt: Date;
73
84
  updatedAt: Date;
85
+ name: string;
74
86
  classId: string;
75
- runJobId: string | null;
76
87
  sourceUrl: string | null;
88
+ runJobId: string | null;
77
89
  }>;
78
90
  export declare function createWorksheetRecord(classId: string, name: string): Promise<{
79
91
  status: import(".prisma/client").$Enums.JobStatus | null;
80
- name: string;
81
92
  id: string;
82
93
  createdAt: Date;
83
94
  updatedAt: Date;
95
+ name: string;
84
96
  classId: string;
85
- runJobId: string | null;
86
97
  sourceUrl: string | null;
98
+ runJobId: string | null;
87
99
  }>;
88
100
  /**
89
101
  * Duplicate a worksheet into another class. Caller must teach both the source worksheet's class
@@ -91,13 +103,13 @@ export declare function createWorksheetRecord(classId: string, name: string): Pr
91
103
  */
92
104
  export declare function duplicateWorksheetRecord(worksheetId: string, classId: string, name: string, userId: string): Promise<{
93
105
  status: import(".prisma/client").$Enums.JobStatus | null;
94
- name: string;
95
106
  id: string;
96
107
  createdAt: Date;
97
108
  updatedAt: Date;
109
+ name: string;
98
110
  classId: string;
99
- runJobId: string | null;
100
111
  sourceUrl: string | null;
112
+ runJobId: string | null;
101
113
  }>;
102
114
  /**
103
115
  * Kick off PDF-to-worksheet conversion asynchronously.
@@ -113,10 +125,10 @@ export declare function createWorksheetFromPdf(classId: string, url: string, use
113
125
  }): Promise<{
114
126
  runJobId: string;
115
127
  status: import(".prisma/client").$Enums.JobStatus | null;
116
- name: string;
117
128
  id: string;
118
129
  createdAt: Date;
119
130
  updatedAt: Date;
131
+ name: string;
120
132
  classId: string;
121
133
  sourceUrl: string | null;
122
134
  }>;
@@ -128,10 +140,10 @@ export declare function createWorksheetFromUploadedPdf(classId: string, fileId:
128
140
  }): Promise<{
129
141
  runJobId: string;
130
142
  status: import(".prisma/client").$Enums.JobStatus | null;
131
- name: string;
132
143
  id: string;
133
144
  createdAt: Date;
134
145
  updatedAt: Date;
146
+ name: string;
135
147
  classId: string;
136
148
  sourceUrl: string | null;
137
149
  }>;
@@ -142,18 +154,19 @@ export declare function addQuestionToWorksheet(worksheetId: string, userId: stri
142
154
  options?: object;
143
155
  markScheme?: object;
144
156
  type: WorksheetQuestionType;
157
+ order?: number;
145
158
  }): Promise<{
146
159
  type: import(".prisma/client").$Enums.WorksheetQuestionType;
147
160
  options: import("@prisma/client/runtime/library.js").JsonValue | null;
161
+ markScheme: import("@prisma/client/runtime/library.js").JsonValue | null;
148
162
  id: string;
149
163
  createdAt: Date;
150
164
  updatedAt: Date;
151
165
  order: number | null;
152
- points: number;
153
166
  worksheetId: string;
154
- markScheme: import("@prisma/client/runtime/library.js").JsonValue | null;
155
167
  question: string;
156
168
  answer: string;
169
+ points: number;
157
170
  }>;
158
171
  export declare function reorderWorksheetQuestions(worksheetId: string, userId: string, movedId: string, position: "before" | "after", targetId: string): Promise<{
159
172
  id: string;
@@ -168,48 +181,49 @@ export declare function updateWorksheetQuestionRecord(worksheetId: string, quest
168
181
  }): Promise<{
169
182
  type: import(".prisma/client").$Enums.WorksheetQuestionType;
170
183
  options: import("@prisma/client/runtime/library.js").JsonValue | null;
184
+ markScheme: import("@prisma/client/runtime/library.js").JsonValue | null;
171
185
  id: string;
172
186
  createdAt: Date;
173
187
  updatedAt: Date;
174
188
  order: number | null;
175
- points: number;
176
189
  worksheetId: string;
177
- markScheme: import("@prisma/client/runtime/library.js").JsonValue | null;
178
190
  question: string;
179
191
  answer: string;
192
+ points: number;
180
193
  }>;
181
194
  export declare function deleteWorksheetQuestionRecord(worksheetId: string, questionId: string, userId: string): Promise<{
182
195
  type: import(".prisma/client").$Enums.WorksheetQuestionType;
183
196
  options: import("@prisma/client/runtime/library.js").JsonValue | null;
197
+ markScheme: import("@prisma/client/runtime/library.js").JsonValue | null;
184
198
  id: string;
185
199
  createdAt: Date;
186
200
  updatedAt: Date;
187
201
  order: number | null;
188
- points: number;
189
202
  worksheetId: string;
190
- markScheme: import("@prisma/client/runtime/library.js").JsonValue | null;
191
203
  question: string;
192
204
  answer: string;
205
+ points: number;
193
206
  }>;
194
207
  export declare function getWorksheetSubmission(worksheetId: string, submissionId: string, userId: string): Promise<{
195
208
  responses: ({
196
209
  comments: {
197
210
  id: string;
211
+ isPinned: boolean;
198
212
  }[];
199
213
  } & {
200
214
  status: import(".prisma/client").$Enums.JobStatus | null;
201
215
  id: string;
202
216
  createdAt: Date;
203
217
  updatedAt: Date | null;
218
+ feedback: string | null;
204
219
  studentId: string;
205
- questionId: string;
220
+ runJobId: string | null;
221
+ points: number;
206
222
  response: string;
207
223
  isCorrect: boolean;
208
224
  markschemeState: import("@prisma/client/runtime/library.js").JsonValue | null;
209
- points: number;
210
- feedback: string | null;
211
225
  studentWorksheetResponseId: string | null;
212
- runJobId: string | null;
226
+ questionId: string;
213
227
  })[];
214
228
  } & {
215
229
  id: string;
@@ -227,15 +241,15 @@ export declare function answerWorksheetQuestion(worksheetResponseId: string, que
227
241
  id: string;
228
242
  createdAt: Date;
229
243
  updatedAt: Date | null;
244
+ feedback: string | null;
230
245
  studentId: string;
231
- questionId: string;
246
+ runJobId: string | null;
247
+ points: number;
232
248
  response: string;
233
249
  isCorrect: boolean;
234
250
  markschemeState: import("@prisma/client/runtime/library.js").JsonValue | null;
235
- points: number;
236
- feedback: string | null;
237
251
  studentWorksheetResponseId: string | null;
238
- runJobId: string | null;
252
+ questionId: string;
239
253
  }[];
240
254
  } & {
241
255
  id: string;
@@ -252,30 +266,30 @@ export declare function cancelGrading(worksheetResponseId: string, progressId: s
252
266
  id: string;
253
267
  createdAt: Date;
254
268
  updatedAt: Date | null;
269
+ feedback: string | null;
255
270
  studentId: string;
256
- questionId: string;
271
+ runJobId: string | null;
272
+ points: number;
257
273
  response: string;
258
274
  isCorrect: boolean;
259
275
  markschemeState: import("@prisma/client/runtime/library.js").JsonValue | null;
260
- points: number;
261
- feedback: string | null;
262
276
  studentWorksheetResponseId: string | null;
263
- runJobId: string | null;
277
+ questionId: string;
264
278
  }>;
265
279
  export declare function regradeQuestion(worksheetResponseId: string, progressId: string, userId: string): Promise<{
266
280
  status: import(".prisma/client").$Enums.JobStatus | null;
267
281
  id: string;
268
282
  createdAt: Date;
269
283
  updatedAt: Date | null;
284
+ feedback: string | null;
270
285
  studentId: string;
271
- questionId: string;
286
+ runJobId: string | null;
287
+ points: number;
272
288
  response: string;
273
289
  isCorrect: boolean;
274
290
  markschemeState: import("@prisma/client/runtime/library.js").JsonValue | null;
275
- points: number;
276
- feedback: string | null;
277
291
  studentWorksheetResponseId: string | null;
278
- runJobId: string | null;
292
+ questionId: string;
279
293
  } | null>;
280
294
  export declare function gradeAnswer(questionId: string, studentWorksheetResponseId: string, userId: string, data: {
281
295
  responseId?: string;
@@ -289,25 +303,26 @@ export declare function gradeAnswer(questionId: string, studentWorksheetResponse
289
303
  id: string;
290
304
  createdAt: Date;
291
305
  updatedAt: Date | null;
306
+ feedback: string | null;
292
307
  studentId: string;
293
- questionId: string;
308
+ runJobId: string | null;
309
+ points: number;
294
310
  response: string;
295
311
  isCorrect: boolean;
296
312
  markschemeState: import("@prisma/client/runtime/library.js").JsonValue | null;
297
- points: number;
298
- feedback: string | null;
299
313
  studentWorksheetResponseId: string | null;
300
- runJobId: string | null;
314
+ questionId: string;
301
315
  }>;
302
316
  export declare function addCommentToResponse(responseId: string, comment: string, authorId: string): Promise<{
303
317
  id: string;
304
318
  createdAt: Date;
319
+ content: string;
305
320
  assignmentId: string | null;
306
321
  submissionId: string | null;
307
- announcementId: string | null;
308
322
  modifiedAt: Date | null;
309
- content: string;
323
+ announcementId: string | null;
310
324
  authorId: string;
325
+ isPinned: boolean;
311
326
  parentCommentId: string | null;
312
327
  studentQuestionProgressId: string | null;
313
328
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"worksheet.d.ts","sourceRoot":"/","sources":["services/worksheet.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"worksheet.d.ts","sourceRoot":"/","sources":["services/worksheet.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,7 @@
3
3
  * Integrates with gradeWorksheet pipeline for auto-grading.
4
4
  */
5
5
 
6
- !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]="dbf4168b-2ccd-58fc-80da-0cb74d76cf44")}catch(e){}}();
6
+ !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]="d0f14b4e-0601-5f64-8c75-5790d8da194e")}catch(e){}}();
7
7
  import { TRPCError } from "@trpc/server";
8
8
  import { JobStatus } from "@prisma/client";
9
9
  import { prisma } from "../lib/prisma.js";
@@ -12,6 +12,7 @@ import { cancelGradePipeline, regradeWorksheetPipeline } from "../pipelines/grad
12
12
  import { enqueueRunJob } from "../workers/queues.js";
13
13
  import { logger } from "../utils/logger.js";
14
14
  import { findWorksheetByIdMinimal, findWorksheetByIdForClassMember, findWorksheetByIdForTeacher, findWorksheetsByClassId, createWorksheet, duplicateWorksheet, updateWorksheet, deleteWorksheet, findQuestionsByWorksheetId, createWorksheetQuestion, updateWorksheetQuestion, deleteWorksheetQuestion, findSubmissionByIdForWorksheetAccess, findOrCreateWorksheetResponse, findWorksheetResponseByIdForTeacher, findWorksheetResponseWithResponsesForStudent, findWorksheetQuestionByIdForTeacher, findWorksheetQuestionByIdInWorksheet, updateStudentQuestionProgress, createStudentQuestionProgress, findStudentQuestionProgress, updateStudentQuestionProgressForGrading, createStudentQuestionProgressForGrading, createComment, findStudentQuestionProgressByIdForTeacher, findStudentQuestionProgressByIdForStudentOrTeacher, findStudentQuestionProgressByIdForTeacherAndResponse, } from "../models/worksheet.js";
15
+ import { enqueueEmbedding } from "./embedding.js";
15
16
  const sanitizeQuestionOptionsForStudent = (options) => {
16
17
  if (!Array.isArray(options))
17
18
  return options;
@@ -66,7 +67,10 @@ export async function updateWorksheetRecord(worksheetId, userId, data) {
66
67
  message: "Only class teachers can update worksheets",
67
68
  });
68
69
  }
69
- return updateWorksheet(worksheetId, data);
70
+ const updated = await updateWorksheet(worksheetId, data);
71
+ // Re-index worksheet for RAG search
72
+ enqueueEmbedding(worksheet.classId, 'WORKSHEET', worksheetId);
73
+ return updated;
70
74
  }
71
75
  export async function deleteWorksheetRecord(worksheetId, userId) {
72
76
  const worksheet = await findWorksheetByIdForTeacher(worksheetId, userId);
@@ -79,7 +83,10 @@ export async function deleteWorksheetRecord(worksheetId, userId) {
79
83
  return deleteWorksheet(worksheetId);
80
84
  }
81
85
  export async function createWorksheetRecord(classId, name) {
82
- return createWorksheet({ classId, name });
86
+ const worksheet = await createWorksheet({ classId, name });
87
+ // Auto-index worksheet for RAG search
88
+ enqueueEmbedding(classId, 'WORKSHEET', worksheet.id);
89
+ return worksheet;
83
90
  }
84
91
  /**
85
92
  * Duplicate a worksheet into another class. Caller must teach both the source worksheet's class
@@ -442,4 +449,4 @@ export async function addCommentToResponse(responseId, comment, authorId) {
442
449
  });
443
450
  }
444
451
  //# sourceMappingURL=worksheet.js.map
445
- //# debugId=dbf4168b-2ccd-58fc-80da-0cb74d76cf44
452
+ //# debugId=d0f14b4e-0601-5f64-8c75-5790d8da194e
@@ -1 +1 @@
1
- {"version":3,"file":"worksheet.js","sources":["services/worksheet.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Worksheet service – CRUD for worksheets, questions, submissions, and AI grading.\n * Integrates with gradeWorksheet pipeline for auto-grading.\n */\nimport { TRPCError } from \"@trpc/server\";\nimport { JobStatus, type WorksheetQuestionType } from \"@prisma/client\";\nimport { prisma } from \"../lib/prisma.js\";\nimport { getFileUrl } from \"../lib/fileUpload.js\";\nimport { cancelGradePipeline, regradeWorksheetPipeline } from \"../pipelines/gradeWorksheet.js\";\nimport { enqueueRunJob } from \"../workers/queues.js\";\nimport { logger } from \"../utils/logger.js\";\nimport {\n findWorksheetByIdMinimal,\n findWorksheetByIdForClassMember,\n findWorksheetByIdForTeacher,\n findWorksheetsByClassId,\n createWorksheet,\n duplicateWorksheet,\n updateWorksheet,\n deleteWorksheet,\n findQuestionsByWorksheetId,\n createWorksheetQuestion,\n updateWorksheetQuestion,\n deleteWorksheetQuestion,\n findSubmissionByIdForWorksheetAccess,\n findOrCreateWorksheetResponse,\n findWorksheetResponseByIdForTeacher,\n findWorksheetResponseWithResponsesForStudent,\n findWorksheetQuestionByIdForTeacher,\n findWorksheetQuestionByIdInWorksheet,\n updateStudentQuestionProgress,\n createStudentQuestionProgress,\n findStudentQuestionProgress,\n updateStudentQuestionProgressForGrading,\n createStudentQuestionProgressForGrading,\n createComment,\n findStudentQuestionProgressByIdForTeacher,\n findStudentQuestionProgressByIdForStudentOrTeacher,\n findStudentQuestionProgressByIdForTeacherAndResponse,\n} from \"../models/worksheet.js\";\n\ntype MCQOptions = { id: string; text: string; isCorrect: boolean }[];\n\nconst sanitizeQuestionOptionsForStudent = (options: unknown) => {\n if (!Array.isArray(options)) return options;\n\n return options.map((option) => {\n if (!option || typeof option !== \"object\") return option;\n\n const { isCorrect: _isCorrect, ...rest } = option as Record<string, unknown>;\n return rest;\n });\n};\n\nconst sanitizeWorksheetForStudent = <T extends {\n questions: Array<Record<string, unknown>>;\n}>(worksheet: T) => ({\n ...worksheet,\n questions: worksheet.questions.map((question) => ({\n ...question,\n answer: \"\",\n markScheme: null,\n options: sanitizeQuestionOptionsForStudent(question.options),\n })),\n});\n\n/** Get worksheet with questions and mark schemes. */\nexport async function getWorksheet(worksheetId: string, userId: string) {\n const teacherWorksheet = await findWorksheetByIdForTeacher(worksheetId, userId);\n if (teacherWorksheet) {\n return teacherWorksheet;\n }\n\n const studentWorksheet = await findWorksheetByIdForClassMember(worksheetId, userId);\n if (!studentWorksheet) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You do not have access to this worksheet\",\n });\n }\n\n return sanitizeWorksheetForStudent(studentWorksheet);\n}\n\n/** Check if worksheet exists. */\nexport async function worksheetExists(id: string) {\n const worksheet = await findWorksheetByIdMinimal(id);\n return !!worksheet;\n}\n\nexport async function listWorksheets(classId: string) {\n const worksheets = await findWorksheetsByClassId(classId);\n return worksheets.map((w) => ({\n ...w,\n questionCount: w.questions.length,\n }));\n}\n\nexport async function updateWorksheetRecord(\n worksheetId: string,\n userId: string,\n data: { name?: string }\n) {\n const worksheet = await findWorksheetByIdForTeacher(worksheetId, userId);\n if (!worksheet) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only class teachers can update worksheets\",\n });\n }\n return updateWorksheet(worksheetId, data);\n}\n\nexport async function deleteWorksheetRecord(worksheetId: string, userId: string) {\n const worksheet = await findWorksheetByIdForTeacher(worksheetId, userId);\n if (!worksheet) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only class teachers can delete worksheets\",\n });\n }\n return deleteWorksheet(worksheetId);\n}\n\nexport async function createWorksheetRecord(classId: string, name: string) {\n return createWorksheet({ classId, name });\n}\n\n/**\n * Duplicate a worksheet into another class. Caller must teach both the source worksheet's class\n * and the target class.\n */\nexport async function duplicateWorksheetRecord(\n worksheetId: string,\n classId: string,\n name: string,\n userId: string\n) {\n const source = await findWorksheetByIdForTeacher(worksheetId, userId);\n if (!source) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message:\n \"Worksheet not found or you are not a teacher of the class it belongs to\",\n });\n }\n\n const targetOk = await prisma.class.findFirst({\n where: {\n id: classId,\n teachers: { some: { id: userId } },\n },\n select: { id: true },\n });\n\n if (!targetOk) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You are not a teacher of the target class\",\n });\n }\n\n const created = await duplicateWorksheet(worksheetId, classId, name);\n if (!created) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Worksheet not found\",\n });\n }\n\n return created;\n}\n\n/**\n * Kick off PDF-to-worksheet conversion asynchronously.\n *\n * We synchronously create a placeholder Worksheet row (status PENDING) so the\n * caller has an id to navigate to immediately, then enqueue a BullMQ job that\n * fills in the real title and questions. Progress is broadcast on the\n * per-worksheet job Pusher channel; clients should subscribe there to drive\n * loading UI.\n */\nexport async function createWorksheetFromPdf(\n classId: string,\n url: string,\n userId?: string,\n options: { name?: string } = {},\n) {\n const placeholder = await prisma.worksheet.create({\n data: {\n classId,\n name: options.name?.trim() || \"Converting PDF…\",\n status: JobStatus.PENDING,\n },\n });\n\n try {\n const { runJobId } = await enqueueRunJob(\n \"PDF_TO_WORKSHEET\",\n { gcsUrl: url, classId, worksheetId: placeholder.id },\n { classId, userId: userId ?? null },\n );\n\n await prisma.worksheet\n .update({\n where: { id: placeholder.id },\n data: { runJobId },\n })\n .catch((linkError) => {\n logger.error(\n \"createWorksheetFromPdf: failed to link RunJob to Worksheet\",\n {\n worksheetId: placeholder.id,\n runJobId,\n error:\n linkError instanceof Error\n ? linkError.message\n : String(linkError),\n },\n );\n });\n\n return {\n ...placeholder,\n runJobId,\n };\n } catch (error) {\n await prisma.worksheet\n .update({\n where: { id: placeholder.id },\n data: { status: JobStatus.FAILED },\n })\n .catch(() => undefined);\n\n logger.error(\"createWorksheetFromPdf: failed to enqueue conversion\", {\n worksheetId: placeholder.id,\n classId,\n error: error instanceof Error ? error.message : String(error),\n });\n\n throw new TRPCError({\n code: \"INTERNAL_SERVER_ERROR\",\n message: \"Failed to start worksheet conversion\",\n });\n }\n}\n\n/**\n * Create a worksheet from a PDF that was uploaded through the direct-upload flow.\n */\nexport async function createWorksheetFromUploadedPdf(\n classId: string,\n fileId: string,\n userId: string,\n options: { name?: string } = {},\n) {\n const file = await prisma.file.findFirst({\n where: {\n id: fileId,\n userId,\n uploadStatus: \"COMPLETED\",\n },\n select: {\n id: true,\n path: true,\n type: true,\n name: true,\n },\n });\n\n if (!file) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Uploaded file not found or not ready\",\n });\n }\n\n const isPdf =\n file.type === \"application/pdf\" || file.path.toLowerCase().endsWith(\".pdf\");\n if (!isPdf) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Only PDF files can be converted into worksheets\",\n });\n }\n\n const signedUrl = await getFileUrl(file.path);\n return createWorksheetFromPdf(classId, signedUrl, userId, {\n name: options.name ?? file.name ?? undefined,\n });\n}\n\nexport async function addQuestionToWorksheet(\n worksheetId: string,\n userId: string,\n data: {\n question: string;\n answer: string;\n points?: number;\n options?: object;\n markScheme?: object;\n type: WorksheetQuestionType;\n }\n) {\n const worksheet = await findWorksheetByIdForTeacher(worksheetId, userId);\n if (!worksheet) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only class teachers can modify worksheet questions\",\n });\n }\n return createWorksheetQuestion({\n worksheetId,\n ...data,\n });\n}\n\nexport async function reorderWorksheetQuestions(\n worksheetId: string,\n userId: string,\n movedId: string,\n position: \"before\" | \"after\",\n targetId: string\n) {\n const worksheet = await findWorksheetByIdForTeacher(worksheetId, userId);\n if (!worksheet) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only class teachers can reorder worksheet questions\",\n });\n }\n\n const questions = await findQuestionsByWorksheetId(worksheetId);\n const movedIdx = questions.findIndex((q) => q.id === movedId);\n if (movedIdx === -1) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Moved question not found\",\n });\n }\n const targetIdx = questions.findIndex((q) => q.id === targetId);\n if (targetIdx === -1) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Target question not found\",\n });\n }\n if (movedId === targetId) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Moved question and target question must be different\",\n });\n }\n\n const withoutMoved = questions.filter((q) => q.id !== movedId);\n const targetIdxWithoutMoved = withoutMoved.findIndex((q) => q.id === targetId);\n const insertIdx =\n position === \"before\" ? targetIdxWithoutMoved : targetIdxWithoutMoved + 1;\n const next = [\n ...withoutMoved.slice(0, insertIdx).map((item) => ({ id: item.id })),\n { id: movedId },\n ...withoutMoved.slice(insertIdx).map((item) => ({ id: item.id })),\n ];\n\n await prisma.$transaction(\n next.map((item, index) =>\n prisma.worksheetQuestion.update({\n where: { id: item.id },\n data: { order: index },\n })\n )\n );\n return next;\n}\n\nexport async function updateWorksheetQuestionRecord(\n worksheetId: string,\n questionId: string,\n userId: string,\n data: {\n question?: string;\n answer?: string;\n points?: number;\n options?: object;\n markScheme?: object;\n type?: WorksheetQuestionType;\n }\n) {\n const question = await findWorksheetQuestionByIdForTeacher(questionId, userId);\n if (!question || question.worksheetId !== worksheetId) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only class teachers can update worksheet questions\",\n });\n }\n return updateWorksheetQuestion(questionId, data);\n}\n\nexport async function deleteWorksheetQuestionRecord(\n worksheetId: string,\n questionId: string,\n userId: string\n) {\n const question = await findWorksheetQuestionByIdForTeacher(questionId, userId);\n if (!question || question.worksheetId !== worksheetId) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only class teachers can delete worksheet questions\",\n });\n }\n return deleteWorksheetQuestion(questionId);\n}\n\nexport async function getWorksheetSubmission(\n worksheetId: string,\n submissionId: string,\n userId: string\n) {\n const worksheet = await findWorksheetByIdForClassMember(worksheetId, userId);\n if (!worksheet) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You do not have access to this worksheet\",\n });\n }\n\n const submission = await findSubmissionByIdForWorksheetAccess(\n submissionId,\n worksheetId,\n worksheet.classId,\n userId\n );\n if (!submission) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You do not have access to this worksheet submission\",\n });\n }\n return findOrCreateWorksheetResponse(\n submissionId,\n worksheetId,\n submission.studentId\n );\n}\n\nexport async function answerWorksheetQuestion(\n worksheetResponseId: string,\n questionId: string,\n response: string,\n userId: string\n) {\n const worksheetResponse = await findWorksheetResponseWithResponsesForStudent(\n worksheetResponseId,\n userId,\n questionId\n );\n if (!worksheetResponse) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You can only answer your own worksheet responses\",\n });\n }\n\n const question = await findWorksheetQuestionByIdInWorksheet(\n questionId,\n worksheetResponse.worksheetId\n );\n if (!question) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Worksheet question not found\",\n });\n }\n\n const isMarkableByAlgo =\n question.type === \"MULTIPLE_CHOICE\" || question.type === \"TRUE_FALSE\";\n const marksAwardedIfCorrect = question.points || 0;\n const correctAnswer = isMarkableByAlgo\n ? question.type === \"MULTIPLE_CHOICE\"\n ? (question.options as MCQOptions)?.find((o) => o.isCorrect)?.id\n : question.answer?.toString()\n : null;\n\n const existingResponse = worksheetResponse.responses[0];\n\n if (existingResponse) {\n await updateStudentQuestionProgress(existingResponse.id, {\n response,\n ...(isMarkableByAlgo && {\n isCorrect: response === correctAnswer,\n }),\n ...(isMarkableByAlgo && {\n points: response === correctAnswer ? marksAwardedIfCorrect : 0,\n }),\n status: JobStatus.NOT_STARTED,\n });\n } else {\n await createStudentQuestionProgress({\n studentId: worksheetResponse.studentId,\n questionId,\n response,\n studentWorksheetResponseId: worksheetResponseId,\n ...(isMarkableByAlgo && {\n isCorrect: response === correctAnswer,\n }),\n ...(isMarkableByAlgo && {\n points: response === correctAnswer ? marksAwardedIfCorrect : 0,\n }),\n });\n }\n\n const updated = await prisma.studentWorksheetResponse.findUnique({\n where: { id: worksheetResponseId },\n include: { responses: true },\n });\n return updated!;\n}\n\nexport async function cancelGrading(\n worksheetResponseId: string,\n progressId: string,\n userId: string\n) {\n const progress = await findStudentQuestionProgressByIdForTeacherAndResponse(\n progressId,\n worksheetResponseId,\n userId\n );\n if (!progress) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only class teachers can cancel worksheet grading\",\n });\n }\n return cancelGradePipeline(worksheetResponseId, progressId);\n}\n\nexport async function regradeQuestion(\n worksheetResponseId: string,\n progressId: string,\n userId: string\n) {\n const progress = await findStudentQuestionProgressByIdForTeacherAndResponse(\n progressId,\n worksheetResponseId,\n userId\n );\n if (!progress) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only class teachers can regrade worksheet answers\",\n });\n }\n return regradeWorksheetPipeline(worksheetResponseId, progressId);\n}\n\nexport async function gradeAnswer(\n questionId: string,\n studentWorksheetResponseId: string,\n userId: string,\n data: {\n responseId?: string;\n response?: string;\n isCorrect: boolean;\n feedback?: string;\n markschemeState?: object;\n points?: number;\n }\n) {\n const worksheetResponse = await findWorksheetResponseByIdForTeacher(\n studentWorksheetResponseId,\n userId\n );\n if (!worksheetResponse) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only class teachers can grade worksheet answers\",\n });\n }\n\n const question = await findWorksheetQuestionByIdInWorksheet(\n questionId,\n worksheetResponse.worksheetId\n );\n if (!question) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Worksheet question not found\",\n });\n }\n\n if (data.responseId) {\n const existingProgress = await findStudentQuestionProgressByIdForTeacher(\n data.responseId,\n userId\n );\n if (\n !existingProgress ||\n existingProgress.studentWorksheetResponseId !== studentWorksheetResponseId ||\n existingProgress.questionId !== questionId\n ) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only class teachers can grade worksheet answers\",\n });\n }\n\n return updateStudentQuestionProgressForGrading(data.responseId, {\n isCorrect: data.isCorrect,\n feedback: data.feedback,\n markschemeState: data.markschemeState,\n points: data.points,\n });\n }\n\n const existing = await findStudentQuestionProgress(\n worksheetResponse.studentId,\n questionId,\n studentWorksheetResponseId\n );\n\n if (existing) {\n return updateStudentQuestionProgressForGrading(existing.id, {\n isCorrect: data.isCorrect,\n response: data.response,\n feedback: data.feedback,\n markschemeState: data.markschemeState,\n points: data.points,\n });\n }\n\n return createStudentQuestionProgressForGrading({\n studentId: worksheetResponse.studentId,\n questionId,\n studentWorksheetResponseId,\n response: data.response || \"\",\n isCorrect: data.isCorrect,\n feedback: data.feedback,\n markschemeState: data.markschemeState,\n points: data.points || 0,\n });\n}\n\nexport async function addCommentToResponse(\n responseId: string,\n comment: string,\n authorId: string\n) {\n const progress = await findStudentQuestionProgressByIdForStudentOrTeacher(\n responseId,\n authorId\n );\n if (!progress) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message:\n \"You can only comment on your own worksheet answers or on answers for classes you teach\",\n });\n }\n\n return createComment({\n studentQuestionProgressId: responseId,\n content: comment,\n authorId,\n });\n}\n"],"names":[],"mappings":"AAAA;;;GAGG;;;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,SAAS,EAA8B,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAC/F,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EACL,wBAAwB,EACxB,+BAA+B,EAC/B,2BAA2B,EAC3B,uBAAuB,EACvB,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,0BAA0B,EAC1B,uBAAuB,EACvB,uBAAuB,EACvB,uBAAuB,EACvB,oCAAoC,EACpC,6BAA6B,EAC7B,mCAAmC,EACnC,4CAA4C,EAC5C,mCAAmC,EACnC,oCAAoC,EACpC,6BAA6B,EAC7B,6BAA6B,EAC7B,2BAA2B,EAC3B,uCAAuC,EACvC,uCAAuC,EACvC,aAAa,EACb,yCAAyC,EACzC,kDAAkD,EAClD,oDAAoD,GACrD,MAAM,wBAAwB,CAAC;AAIhC,MAAM,iCAAiC,GAAG,CAAC,OAAgB,EAAE,EAAE;IAC7D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC;IAE5C,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QAC5B,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,OAAO,MAAM,CAAC;QAEzD,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,IAAI,EAAE,GAAG,MAAiC,CAAC;QAC7E,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,2BAA2B,GAAG,CAEjC,SAAY,EAAE,EAAE,CAAC,CAAC;IACnB,GAAG,SAAS;IACZ,SAAS,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAChD,GAAG,QAAQ;QACX,MAAM,EAAE,EAAE;QACV,UAAU,EAAE,IAAI;QAChB,OAAO,EAAE,iCAAiC,CAAC,QAAQ,CAAC,OAAO,CAAC;KAC7D,CAAC,CAAC;CACJ,CAAC,CAAC;AAEH,qDAAqD;AACrD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAAmB,EAAE,MAAc;IACpE,MAAM,gBAAgB,GAAG,MAAM,2BAA2B,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAChF,IAAI,gBAAgB,EAAE,CAAC;QACrB,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,MAAM,gBAAgB,GAAG,MAAM,+BAA+B,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACpF,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,0CAA0C;SACpD,CAAC,CAAC;IACL,CAAC;IAED,OAAO,2BAA2B,CAAC,gBAAgB,CAAC,CAAC;AACvD,CAAC;AAED,iCAAiC;AACjC,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,EAAU;IAC9C,MAAM,SAAS,GAAG,MAAM,wBAAwB,CAAC,EAAE,CAAC,CAAC;IACrD,OAAO,CAAC,CAAC,SAAS,CAAC;AACrB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAe;IAClD,MAAM,UAAU,GAAG,MAAM,uBAAuB,CAAC,OAAO,CAAC,CAAC;IAC1D,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC5B,GAAG,CAAC;QACJ,aAAa,EAAE,CAAC,CAAC,SAAS,CAAC,MAAM;KAClC,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,WAAmB,EACnB,MAAc,EACd,IAAuB;IAEvB,MAAM,SAAS,GAAG,MAAM,2BAA2B,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACzE,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,2CAA2C;SACrD,CAAC,CAAC;IACL,CAAC;IACD,OAAO,eAAe,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,WAAmB,EAAE,MAAc;IAC7E,MAAM,SAAS,GAAG,MAAM,2BAA2B,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACzE,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,2CAA2C;SACrD,CAAC,CAAC;IACL,CAAC;IACD,OAAO,eAAe,CAAC,WAAW,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,OAAe,EAAE,IAAY;IACvE,OAAO,eAAe,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;AAC5C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,WAAmB,EACnB,OAAe,EACf,IAAY,EACZ,MAAc;IAEd,MAAM,MAAM,GAAG,MAAM,2BAA2B,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACtE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EACL,yEAAyE;SAC5E,CAAC,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC;QAC5C,KAAK,EAAE;YACL,EAAE,EAAE,OAAO;YACX,QAAQ,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE;SACnC;QACD,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE;KACrB,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,2CAA2C;SACrD,CAAC,CAAC;IACL,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACrE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,qBAAqB;SAC/B,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,OAAe,EACf,GAAW,EACX,MAAe,EACf,UAA6B,EAAE;IAE/B,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;QAChD,IAAI,EAAE;YACJ,OAAO;YACP,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,iBAAiB;YAC/C,MAAM,EAAE,SAAS,CAAC,OAAO;SAC1B;KACF,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,aAAa,CACtC,kBAAkB,EAClB,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,CAAC,EAAE,EAAE,EACrD,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,IAAI,EAAE,CACpC,CAAC;QAEF,MAAM,MAAM,CAAC,SAAS;aACnB,MAAM,CAAC;YACN,KAAK,EAAE,EAAE,EAAE,EAAE,WAAW,CAAC,EAAE,EAAE;YAC7B,IAAI,EAAE,EAAE,QAAQ,EAAE;SACnB,CAAC;aACD,KAAK,CAAC,CAAC,SAAS,EAAE,EAAE;YACnB,MAAM,CAAC,KAAK,CACV,4DAA4D,EAC5D;gBACE,WAAW,EAAE,WAAW,CAAC,EAAE;gBAC3B,QAAQ;gBACR,KAAK,EACH,SAAS,YAAY,KAAK;oBACxB,CAAC,CAAC,SAAS,CAAC,OAAO;oBACnB,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC;aACxB,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;QAEL,OAAO;YACL,GAAG,WAAW;YACd,QAAQ;SACT,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,CAAC,SAAS;aACnB,MAAM,CAAC;YACN,KAAK,EAAE,EAAE,EAAE,EAAE,WAAW,CAAC,EAAE,EAAE;YAC7B,IAAI,EAAE,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE;SACnC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAE1B,MAAM,CAAC,KAAK,CAAC,sDAAsD,EAAE;YACnE,WAAW,EAAE,WAAW,CAAC,EAAE;YAC3B,OAAO;YACP,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAC9D,CAAC,CAAC;QAEH,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,uBAAuB;YAC7B,OAAO,EAAE,sCAAsC;SAChD,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAClD,OAAe,EACf,MAAc,EACd,MAAc,EACd,UAA6B,EAAE;IAE/B,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;QACvC,KAAK,EAAE;YACL,EAAE,EAAE,MAAM;YACV,MAAM;YACN,YAAY,EAAE,WAAW;SAC1B;QACD,MAAM,EAAE;YACN,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,IAAI;YACV,IAAI,EAAE,IAAI;YACV,IAAI,EAAE,IAAI;SACX;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,sCAAsC;SAChD,CAAC,CAAC;IACL,CAAC;IAED,MAAM,KAAK,GACT,IAAI,CAAC,IAAI,KAAK,iBAAiB,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC9E,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,iDAAiD;SAC3D,CAAC,CAAC;IACL,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9C,OAAO,sBAAsB,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE;QACxD,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,SAAS;KAC7C,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,WAAmB,EACnB,MAAc,EACd,IAOC;IAED,MAAM,SAAS,GAAG,MAAM,2BAA2B,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACzE,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,oDAAoD;SAC9D,CAAC,CAAC;IACL,CAAC;IACD,OAAO,uBAAuB,CAAC;QAC7B,WAAW;QACX,GAAG,IAAI;KACR,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,WAAmB,EACnB,MAAc,EACd,OAAe,EACf,QAA4B,EAC5B,QAAgB;IAEhB,MAAM,SAAS,GAAG,MAAM,2BAA2B,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACzE,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,qDAAqD;SAC/D,CAAC,CAAC;IACL,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,0BAA0B,CAAC,WAAW,CAAC,CAAC;IAChE,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC;IAC9D,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,0BAA0B;SACpC,CAAC,CAAC;IACL,CAAC;IACD,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;IAChE,IAAI,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,2BAA2B;SACrC,CAAC,CAAC;IACL,CAAC;IACD,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACzB,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,sDAAsD;SAChE,CAAC,CAAC;IACL,CAAC;IAED,MAAM,YAAY,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC;IAC/D,MAAM,qBAAqB,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;IAC/E,MAAM,SAAS,GACb,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,qBAAqB,GAAG,CAAC,CAAC;IAC5E,MAAM,IAAI,GAAG;QACX,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QACpE,EAAE,EAAE,EAAE,OAAO,EAAE;QACf,GAAG,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;KAClE,CAAC;IAEF,MAAM,MAAM,CAAC,YAAY,CACvB,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACvB,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC;QAC9B,KAAK,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE;QACtB,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE;KACvB,CAAC,CACH,CACF,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,WAAmB,EACnB,UAAkB,EAClB,MAAc,EACd,IAOC;IAED,MAAM,QAAQ,GAAG,MAAM,mCAAmC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC/E,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,WAAW,KAAK,WAAW,EAAE,CAAC;QACtD,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,oDAAoD;SAC9D,CAAC,CAAC;IACL,CAAC;IACD,OAAO,uBAAuB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,WAAmB,EACnB,UAAkB,EAClB,MAAc;IAEd,MAAM,QAAQ,GAAG,MAAM,mCAAmC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC/E,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,WAAW,KAAK,WAAW,EAAE,CAAC;QACtD,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,oDAAoD;SAC9D,CAAC,CAAC;IACL,CAAC;IACD,OAAO,uBAAuB,CAAC,UAAU,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,WAAmB,EACnB,YAAoB,EACpB,MAAc;IAEd,MAAM,SAAS,GAAG,MAAM,+BAA+B,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAC7E,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,0CAA0C;SACpD,CAAC,CAAC;IACL,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,oCAAoC,CAC3D,YAAY,EACZ,WAAW,EACX,SAAS,CAAC,OAAO,EACjB,MAAM,CACP,CAAC;IACF,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,qDAAqD;SAC/D,CAAC,CAAC;IACL,CAAC;IACD,OAAO,6BAA6B,CAClC,YAAY,EACZ,WAAW,EACX,UAAU,CAAC,SAAS,CACrB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,mBAA2B,EAC3B,UAAkB,EAClB,QAAgB,EAChB,MAAc;IAEd,MAAM,iBAAiB,GAAG,MAAM,4CAA4C,CAC1E,mBAAmB,EACnB,MAAM,EACN,UAAU,CACX,CAAC;IACF,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,kDAAkD;SAC5D,CAAC,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,oCAAoC,CACzD,UAAU,EACV,iBAAiB,CAAC,WAAW,CAC9B,CAAC;IACF,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,8BAA8B;SACxC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,gBAAgB,GACpB,QAAQ,CAAC,IAAI,KAAK,iBAAiB,IAAI,QAAQ,CAAC,IAAI,KAAK,YAAY,CAAC;IACxE,MAAM,qBAAqB,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC;IACnD,MAAM,aAAa,GAAG,gBAAgB;QACpC,CAAC,CAAC,QAAQ,CAAC,IAAI,KAAK,iBAAiB;YACnC,CAAC,CAAE,QAAQ,CAAC,OAAsB,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE;YAChE,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE;QAC/B,CAAC,CAAC,IAAI,CAAC;IAET,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAExD,IAAI,gBAAgB,EAAE,CAAC;QACrB,MAAM,6BAA6B,CAAC,gBAAgB,CAAC,EAAE,EAAE;YACvD,QAAQ;YACR,GAAG,CAAC,gBAAgB,IAAI;gBACtB,SAAS,EAAE,QAAQ,KAAK,aAAa;aACtC,CAAC;YACF,GAAG,CAAC,gBAAgB,IAAI;gBACtB,MAAM,EAAE,QAAQ,KAAK,aAAa,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;aAC/D,CAAC;YACF,MAAM,EAAE,SAAS,CAAC,WAAW;SAC9B,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,MAAM,6BAA6B,CAAC;YAClC,SAAS,EAAE,iBAAiB,CAAC,SAAS;YACtC,UAAU;YACV,QAAQ;YACR,0BAA0B,EAAE,mBAAmB;YAC/C,GAAG,CAAC,gBAAgB,IAAI;gBACtB,SAAS,EAAE,QAAQ,KAAK,aAAa;aACtC,CAAC;YACF,GAAG,CAAC,gBAAgB,IAAI;gBACtB,MAAM,EAAE,QAAQ,KAAK,aAAa,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;aAC/D,CAAC;SACH,CAAC,CAAC;IACL,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,UAAU,CAAC;QAC/D,KAAK,EAAE,EAAE,EAAE,EAAE,mBAAmB,EAAE;QAClC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE;KAC7B,CAAC,CAAC;IACH,OAAO,OAAQ,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,mBAA2B,EAC3B,UAAkB,EAClB,MAAc;IAEd,MAAM,QAAQ,GAAG,MAAM,oDAAoD,CACzE,UAAU,EACV,mBAAmB,EACnB,MAAM,CACP,CAAC;IACF,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,kDAAkD;SAC5D,CAAC,CAAC;IACL,CAAC;IACD,OAAO,mBAAmB,CAAC,mBAAmB,EAAE,UAAU,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,mBAA2B,EAC3B,UAAkB,EAClB,MAAc;IAEd,MAAM,QAAQ,GAAG,MAAM,oDAAoD,CACzE,UAAU,EACV,mBAAmB,EACnB,MAAM,CACP,CAAC;IACF,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,mDAAmD;SAC7D,CAAC,CAAC;IACL,CAAC;IACD,OAAO,wBAAwB,CAAC,mBAAmB,EAAE,UAAU,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,UAAkB,EAClB,0BAAkC,EAClC,MAAc,EACd,IAOC;IAED,MAAM,iBAAiB,GAAG,MAAM,mCAAmC,CACjE,0BAA0B,EAC1B,MAAM,CACP,CAAC;IACF,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,iDAAiD;SAC3D,CAAC,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,oCAAoC,CACzD,UAAU,EACV,iBAAiB,CAAC,WAAW,CAC9B,CAAC;IACF,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,8BAA8B;SACxC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,MAAM,gBAAgB,GAAG,MAAM,yCAAyC,CACtE,IAAI,CAAC,UAAU,EACf,MAAM,CACP,CAAC;QACF,IACE,CAAC,gBAAgB;YACjB,gBAAgB,CAAC,0BAA0B,KAAK,0BAA0B;YAC1E,gBAAgB,CAAC,UAAU,KAAK,UAAU,EAC1C,CAAC;YACD,MAAM,IAAI,SAAS,CAAC;gBAClB,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,iDAAiD;aAC3D,CAAC,CAAC;QACL,CAAC;QAED,OAAO,uCAAuC,CAAC,IAAI,CAAC,UAAU,EAAE;YAC9D,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,2BAA2B,CAChD,iBAAiB,CAAC,SAAS,EAC3B,UAAU,EACV,0BAA0B,CAC3B,CAAC;IAEF,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,uCAAuC,CAAC,QAAQ,CAAC,EAAE,EAAE;YAC1D,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,uCAAuC,CAAC;QAC7C,SAAS,EAAE,iBAAiB,CAAC,SAAS;QACtC,UAAU;QACV,0BAA0B;QAC1B,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE;QAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,eAAe,EAAE,IAAI,CAAC,eAAe;QACrC,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,CAAC;KACzB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,UAAkB,EAClB,OAAe,EACf,QAAgB;IAEhB,MAAM,QAAQ,GAAG,MAAM,kDAAkD,CACvE,UAAU,EACV,QAAQ,CACT,CAAC;IACF,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EACL,wFAAwF;SAC3F,CAAC,CAAC;IACL,CAAC;IAED,OAAO,aAAa,CAAC;QACnB,yBAAyB,EAAE,UAAU;QACrC,OAAO,EAAE,OAAO;QAChB,QAAQ;KACT,CAAC,CAAC;AACL,CAAC","debug_id":"dbf4168b-2ccd-58fc-80da-0cb74d76cf44"}
1
+ {"version":3,"file":"worksheet.js","sources":["services/worksheet.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Worksheet service – CRUD for worksheets, questions, submissions, and AI grading.\n * Integrates with gradeWorksheet pipeline for auto-grading.\n */\nimport { TRPCError } from \"@trpc/server\";\nimport { JobStatus, type WorksheetQuestionType } from \"@prisma/client\";\nimport { prisma } from \"../lib/prisma.js\";\nimport { getFileUrl } from \"../lib/fileUpload.js\";\nimport { cancelGradePipeline, regradeWorksheetPipeline } from \"../pipelines/gradeWorksheet.js\";\nimport { enqueueRunJob } from \"../workers/queues.js\";\nimport { logger } from \"../utils/logger.js\";\nimport {\n findWorksheetByIdMinimal,\n findWorksheetByIdForClassMember,\n findWorksheetByIdForTeacher,\n findWorksheetsByClassId,\n createWorksheet,\n duplicateWorksheet,\n updateWorksheet,\n deleteWorksheet,\n findQuestionsByWorksheetId,\n createWorksheetQuestion,\n updateWorksheetQuestion,\n deleteWorksheetQuestion,\n findSubmissionByIdForWorksheetAccess,\n findOrCreateWorksheetResponse,\n findWorksheetResponseByIdForTeacher,\n findWorksheetResponseWithResponsesForStudent,\n findWorksheetQuestionByIdForTeacher,\n findWorksheetQuestionByIdInWorksheet,\n updateStudentQuestionProgress,\n createStudentQuestionProgress,\n findStudentQuestionProgress,\n updateStudentQuestionProgressForGrading,\n createStudentQuestionProgressForGrading,\n createComment,\n findStudentQuestionProgressByIdForTeacher,\n findStudentQuestionProgressByIdForStudentOrTeacher,\n findStudentQuestionProgressByIdForTeacherAndResponse,\n} from \"../models/worksheet.js\";\nimport { enqueueEmbedding } from \"./embedding.js\";\n\ntype MCQOptions = { id: string; text: string; isCorrect: boolean }[];\n\nconst sanitizeQuestionOptionsForStudent = (options: unknown) => {\n if (!Array.isArray(options)) return options;\n\n return options.map((option) => {\n if (!option || typeof option !== \"object\") return option;\n\n const { isCorrect: _isCorrect, ...rest } = option as Record<string, unknown>;\n return rest;\n });\n};\n\nconst sanitizeWorksheetForStudent = <T extends {\n questions: Array<Record<string, unknown>>;\n}>(worksheet: T) => ({\n ...worksheet,\n questions: worksheet.questions.map((question) => ({\n ...question,\n answer: \"\",\n markScheme: null,\n options: sanitizeQuestionOptionsForStudent(question.options),\n })),\n});\n\n/** Get worksheet with questions and mark schemes. */\nexport async function getWorksheet(worksheetId: string, userId: string) {\n const teacherWorksheet = await findWorksheetByIdForTeacher(worksheetId, userId);\n if (teacherWorksheet) {\n return teacherWorksheet;\n }\n\n const studentWorksheet = await findWorksheetByIdForClassMember(worksheetId, userId);\n if (!studentWorksheet) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You do not have access to this worksheet\",\n });\n }\n\n return sanitizeWorksheetForStudent(studentWorksheet);\n}\n\n/** Check if worksheet exists. */\nexport async function worksheetExists(id: string) {\n const worksheet = await findWorksheetByIdMinimal(id);\n return !!worksheet;\n}\n\nexport async function listWorksheets(classId: string) {\n const worksheets = await findWorksheetsByClassId(classId);\n return worksheets.map((w) => ({\n ...w,\n questionCount: w.questions.length,\n }));\n}\n\nexport async function updateWorksheetRecord(\n worksheetId: string,\n userId: string,\n data: { name?: string }\n) {\n const worksheet = await findWorksheetByIdForTeacher(worksheetId, userId);\n if (!worksheet) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only class teachers can update worksheets\",\n });\n }\n const updated = await updateWorksheet(worksheetId, data);\n // Re-index worksheet for RAG search\n enqueueEmbedding(worksheet.classId, 'WORKSHEET', worksheetId);\n return updated;\n}\n\nexport async function deleteWorksheetRecord(worksheetId: string, userId: string) {\n const worksheet = await findWorksheetByIdForTeacher(worksheetId, userId);\n if (!worksheet) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only class teachers can delete worksheets\",\n });\n }\n return deleteWorksheet(worksheetId);\n}\n\nexport async function createWorksheetRecord(classId: string, name: string) {\n const worksheet = await createWorksheet({ classId, name });\n // Auto-index worksheet for RAG search\n enqueueEmbedding(classId, 'WORKSHEET', worksheet.id);\n return worksheet;\n}\n\n/**\n * Duplicate a worksheet into another class. Caller must teach both the source worksheet's class\n * and the target class.\n */\nexport async function duplicateWorksheetRecord(\n worksheetId: string,\n classId: string,\n name: string,\n userId: string\n) {\n const source = await findWorksheetByIdForTeacher(worksheetId, userId);\n if (!source) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message:\n \"Worksheet not found or you are not a teacher of the class it belongs to\",\n });\n }\n\n const targetOk = await prisma.class.findFirst({\n where: {\n id: classId,\n teachers: { some: { id: userId } },\n },\n select: { id: true },\n });\n\n if (!targetOk) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You are not a teacher of the target class\",\n });\n }\n\n const created = await duplicateWorksheet(worksheetId, classId, name);\n if (!created) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Worksheet not found\",\n });\n }\n\n return created;\n}\n\n/**\n * Kick off PDF-to-worksheet conversion asynchronously.\n *\n * We synchronously create a placeholder Worksheet row (status PENDING) so the\n * caller has an id to navigate to immediately, then enqueue a BullMQ job that\n * fills in the real title and questions. Progress is broadcast on the\n * per-worksheet job Pusher channel; clients should subscribe there to drive\n * loading UI.\n */\nexport async function createWorksheetFromPdf(\n classId: string,\n url: string,\n userId?: string,\n options: { name?: string } = {},\n) {\n const placeholder = await prisma.worksheet.create({\n data: {\n classId,\n name: options.name?.trim() || \"Converting PDF…\",\n status: JobStatus.PENDING,\n },\n });\n\n try {\n const { runJobId } = await enqueueRunJob(\n \"PDF_TO_WORKSHEET\",\n { gcsUrl: url, classId, worksheetId: placeholder.id },\n { classId, userId: userId ?? null },\n );\n\n await prisma.worksheet\n .update({\n where: { id: placeholder.id },\n data: { runJobId },\n })\n .catch((linkError) => {\n logger.error(\n \"createWorksheetFromPdf: failed to link RunJob to Worksheet\",\n {\n worksheetId: placeholder.id,\n runJobId,\n error:\n linkError instanceof Error\n ? linkError.message\n : String(linkError),\n },\n );\n });\n\n return {\n ...placeholder,\n runJobId,\n };\n } catch (error) {\n await prisma.worksheet\n .update({\n where: { id: placeholder.id },\n data: { status: JobStatus.FAILED },\n })\n .catch(() => undefined);\n\n logger.error(\"createWorksheetFromPdf: failed to enqueue conversion\", {\n worksheetId: placeholder.id,\n classId,\n error: error instanceof Error ? error.message : String(error),\n });\n\n throw new TRPCError({\n code: \"INTERNAL_SERVER_ERROR\",\n message: \"Failed to start worksheet conversion\",\n });\n }\n}\n\n/**\n * Create a worksheet from a PDF that was uploaded through the direct-upload flow.\n */\nexport async function createWorksheetFromUploadedPdf(\n classId: string,\n fileId: string,\n userId: string,\n options: { name?: string } = {},\n) {\n const file = await prisma.file.findFirst({\n where: {\n id: fileId,\n userId,\n uploadStatus: \"COMPLETED\",\n },\n select: {\n id: true,\n path: true,\n type: true,\n name: true,\n },\n });\n\n if (!file) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Uploaded file not found or not ready\",\n });\n }\n\n const isPdf =\n file.type === \"application/pdf\" || file.path.toLowerCase().endsWith(\".pdf\");\n if (!isPdf) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Only PDF files can be converted into worksheets\",\n });\n }\n\n const signedUrl = await getFileUrl(file.path);\n return createWorksheetFromPdf(classId, signedUrl, userId, {\n name: options.name ?? file.name ?? undefined,\n });\n}\n\nexport async function addQuestionToWorksheet(\n worksheetId: string,\n userId: string,\n data: {\n question: string;\n answer: string;\n points?: number;\n options?: object;\n markScheme?: object;\n type: WorksheetQuestionType;\n order?: number;\n }\n) {\n const worksheet = await findWorksheetByIdForTeacher(worksheetId, userId);\n if (!worksheet) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only class teachers can modify worksheet questions\",\n });\n }\n return createWorksheetQuestion({\n worksheetId,\n ...data,\n });\n}\n\nexport async function reorderWorksheetQuestions(\n worksheetId: string,\n userId: string,\n movedId: string,\n position: \"before\" | \"after\",\n targetId: string\n) {\n const worksheet = await findWorksheetByIdForTeacher(worksheetId, userId);\n if (!worksheet) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only class teachers can reorder worksheet questions\",\n });\n }\n\n const questions = await findQuestionsByWorksheetId(worksheetId);\n const movedIdx = questions.findIndex((q) => q.id === movedId);\n if (movedIdx === -1) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Moved question not found\",\n });\n }\n const targetIdx = questions.findIndex((q) => q.id === targetId);\n if (targetIdx === -1) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Target question not found\",\n });\n }\n if (movedId === targetId) {\n throw new TRPCError({\n code: \"BAD_REQUEST\",\n message: \"Moved question and target question must be different\",\n });\n }\n\n const withoutMoved = questions.filter((q) => q.id !== movedId);\n const targetIdxWithoutMoved = withoutMoved.findIndex((q) => q.id === targetId);\n const insertIdx =\n position === \"before\" ? targetIdxWithoutMoved : targetIdxWithoutMoved + 1;\n const next = [\n ...withoutMoved.slice(0, insertIdx).map((item) => ({ id: item.id })),\n { id: movedId },\n ...withoutMoved.slice(insertIdx).map((item) => ({ id: item.id })),\n ];\n\n await prisma.$transaction(\n next.map((item, index) =>\n prisma.worksheetQuestion.update({\n where: { id: item.id },\n data: { order: index },\n })\n )\n );\n return next;\n}\n\nexport async function updateWorksheetQuestionRecord(\n worksheetId: string,\n questionId: string,\n userId: string,\n data: {\n question?: string;\n answer?: string;\n points?: number;\n options?: object;\n markScheme?: object;\n type?: WorksheetQuestionType;\n }\n) {\n const question = await findWorksheetQuestionByIdForTeacher(questionId, userId);\n if (!question || question.worksheetId !== worksheetId) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only class teachers can update worksheet questions\",\n });\n }\n return updateWorksheetQuestion(questionId, data);\n}\n\nexport async function deleteWorksheetQuestionRecord(\n worksheetId: string,\n questionId: string,\n userId: string\n) {\n const question = await findWorksheetQuestionByIdForTeacher(questionId, userId);\n if (!question || question.worksheetId !== worksheetId) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only class teachers can delete worksheet questions\",\n });\n }\n return deleteWorksheetQuestion(questionId);\n}\n\nexport async function getWorksheetSubmission(\n worksheetId: string,\n submissionId: string,\n userId: string\n) {\n const worksheet = await findWorksheetByIdForClassMember(worksheetId, userId);\n if (!worksheet) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You do not have access to this worksheet\",\n });\n }\n\n const submission = await findSubmissionByIdForWorksheetAccess(\n submissionId,\n worksheetId,\n worksheet.classId,\n userId\n );\n if (!submission) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You do not have access to this worksheet submission\",\n });\n }\n return findOrCreateWorksheetResponse(\n submissionId,\n worksheetId,\n submission.studentId\n );\n}\n\nexport async function answerWorksheetQuestion(\n worksheetResponseId: string,\n questionId: string,\n response: string,\n userId: string\n) {\n const worksheetResponse = await findWorksheetResponseWithResponsesForStudent(\n worksheetResponseId,\n userId,\n questionId\n );\n if (!worksheetResponse) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"You can only answer your own worksheet responses\",\n });\n }\n\n const question = await findWorksheetQuestionByIdInWorksheet(\n questionId,\n worksheetResponse.worksheetId\n );\n if (!question) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Worksheet question not found\",\n });\n }\n\n const isMarkableByAlgo =\n question.type === \"MULTIPLE_CHOICE\" || question.type === \"TRUE_FALSE\";\n const marksAwardedIfCorrect = question.points || 0;\n const correctAnswer = isMarkableByAlgo\n ? question.type === \"MULTIPLE_CHOICE\"\n ? (question.options as MCQOptions)?.find((o) => o.isCorrect)?.id\n : question.answer?.toString()\n : null;\n\n const existingResponse = worksheetResponse.responses[0];\n\n if (existingResponse) {\n await updateStudentQuestionProgress(existingResponse.id, {\n response,\n ...(isMarkableByAlgo && {\n isCorrect: response === correctAnswer,\n }),\n ...(isMarkableByAlgo && {\n points: response === correctAnswer ? marksAwardedIfCorrect : 0,\n }),\n status: JobStatus.NOT_STARTED,\n });\n } else {\n await createStudentQuestionProgress({\n studentId: worksheetResponse.studentId,\n questionId,\n response,\n studentWorksheetResponseId: worksheetResponseId,\n ...(isMarkableByAlgo && {\n isCorrect: response === correctAnswer,\n }),\n ...(isMarkableByAlgo && {\n points: response === correctAnswer ? marksAwardedIfCorrect : 0,\n }),\n });\n }\n\n const updated = await prisma.studentWorksheetResponse.findUnique({\n where: { id: worksheetResponseId },\n include: { responses: true },\n });\n return updated!;\n}\n\nexport async function cancelGrading(\n worksheetResponseId: string,\n progressId: string,\n userId: string\n) {\n const progress = await findStudentQuestionProgressByIdForTeacherAndResponse(\n progressId,\n worksheetResponseId,\n userId\n );\n if (!progress) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only class teachers can cancel worksheet grading\",\n });\n }\n return cancelGradePipeline(worksheetResponseId, progressId);\n}\n\nexport async function regradeQuestion(\n worksheetResponseId: string,\n progressId: string,\n userId: string\n) {\n const progress = await findStudentQuestionProgressByIdForTeacherAndResponse(\n progressId,\n worksheetResponseId,\n userId\n );\n if (!progress) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only class teachers can regrade worksheet answers\",\n });\n }\n return regradeWorksheetPipeline(worksheetResponseId, progressId);\n}\n\nexport async function gradeAnswer(\n questionId: string,\n studentWorksheetResponseId: string,\n userId: string,\n data: {\n responseId?: string;\n response?: string;\n isCorrect: boolean;\n feedback?: string;\n markschemeState?: object;\n points?: number;\n }\n) {\n const worksheetResponse = await findWorksheetResponseByIdForTeacher(\n studentWorksheetResponseId,\n userId\n );\n if (!worksheetResponse) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only class teachers can grade worksheet answers\",\n });\n }\n\n const question = await findWorksheetQuestionByIdInWorksheet(\n questionId,\n worksheetResponse.worksheetId\n );\n if (!question) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Worksheet question not found\",\n });\n }\n\n if (data.responseId) {\n const existingProgress = await findStudentQuestionProgressByIdForTeacher(\n data.responseId,\n userId\n );\n if (\n !existingProgress ||\n existingProgress.studentWorksheetResponseId !== studentWorksheetResponseId ||\n existingProgress.questionId !== questionId\n ) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message: \"Only class teachers can grade worksheet answers\",\n });\n }\n\n return updateStudentQuestionProgressForGrading(data.responseId, {\n isCorrect: data.isCorrect,\n feedback: data.feedback,\n markschemeState: data.markschemeState,\n points: data.points,\n });\n }\n\n const existing = await findStudentQuestionProgress(\n worksheetResponse.studentId,\n questionId,\n studentWorksheetResponseId\n );\n\n if (existing) {\n return updateStudentQuestionProgressForGrading(existing.id, {\n isCorrect: data.isCorrect,\n response: data.response,\n feedback: data.feedback,\n markschemeState: data.markschemeState,\n points: data.points,\n });\n }\n\n return createStudentQuestionProgressForGrading({\n studentId: worksheetResponse.studentId,\n questionId,\n studentWorksheetResponseId,\n response: data.response || \"\",\n isCorrect: data.isCorrect,\n feedback: data.feedback,\n markschemeState: data.markschemeState,\n points: data.points || 0,\n });\n}\n\nexport async function addCommentToResponse(\n responseId: string,\n comment: string,\n authorId: string\n) {\n const progress = await findStudentQuestionProgressByIdForStudentOrTeacher(\n responseId,\n authorId\n );\n if (!progress) {\n throw new TRPCError({\n code: \"FORBIDDEN\",\n message:\n \"You can only comment on your own worksheet answers or on answers for classes you teach\",\n });\n }\n\n return createComment({\n studentQuestionProgressId: responseId,\n content: comment,\n authorId,\n });\n}\n"],"names":[],"mappings":"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","debug_id":"d0f14b4e-0601-5f64-8c75-5790d8da194e"}
@@ -0,0 +1,11 @@
1
+ interface BroadcastTextChunksOptions {
2
+ /** When true, skip the `message-stream-complete` event at the end.
3
+ * Callers that need to broadcast additional events (e.g. tool-call
4
+ * indicators) before the stream ends should set this to `true` and
5
+ * call {@link broadcastStreamComplete} explicitly when done. */
6
+ skipComplete?: boolean;
7
+ }
8
+ export declare function broadcastTextChunks(conversationId: string, messageId: string, text: string, options?: BroadcastTextChunksOptions): Promise<void>;
9
+ export declare function broadcastStreamComplete(conversationId: string, messageId: string): Promise<void>;
10
+ export {};
11
+ //# sourceMappingURL=streamBroadcast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streamBroadcast.d.ts","sourceRoot":"/","sources":["utils/streamBroadcast.ts"],"names":[],"mappings":"AASA,UAAU,0BAA0B;IAClC;;;qEAGiE;IACjE,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,wBAAsB,mBAAmB,CACvC,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,0BAA0B,GACnC,OAAO,CAAC,IAAI,CAAC,CAcf;AAED,wBAAsB,uBAAuB,CAC3C,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAMf"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Broadcast text content as sequential Pusher chunks so connected clients
3
+ * can render progressive streaming even when the underlying inference call
4
+ * returns the full text at once (structured-output pipelines).
5
+ */
6
+
7
+ !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]="4d446101-229c-5c73-81df-7c16b110b221")}catch(e){}}();
8
+ import { pusher, chatChannel } from '../lib/pusher.js';
9
+ const CHUNK_SIZE = 80;
10
+ export async function broadcastTextChunks(conversationId, messageId, text, options) {
11
+ for (let i = 0; i < text.length; i += CHUNK_SIZE) {
12
+ const chunk = text.slice(i, i + CHUNK_SIZE);
13
+ await pusher
14
+ .trigger(chatChannel(conversationId), 'message-stream-chunk', {
15
+ messageId,
16
+ chunk,
17
+ })
18
+ .catch(() => { });
19
+ }
20
+ if (!options?.skipComplete) {
21
+ await broadcastStreamComplete(conversationId, messageId);
22
+ }
23
+ }
24
+ export async function broadcastStreamComplete(conversationId, messageId) {
25
+ await pusher
26
+ .trigger(chatChannel(conversationId), 'message-stream-complete', {
27
+ messageId,
28
+ })
29
+ .catch(() => { });
30
+ }
31
+ //# sourceMappingURL=streamBroadcast.js.map
32
+ //# debugId=4d446101-229c-5c73-81df-7c16b110b221
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streamBroadcast.js","sources":["utils/streamBroadcast.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Broadcast text content as sequential Pusher chunks so connected clients\n * can render progressive streaming even when the underlying inference call\n * returns the full text at once (structured-output pipelines).\n */\nimport { pusher, chatChannel } from '../lib/pusher.js';\n\nconst CHUNK_SIZE = 80;\n\ninterface BroadcastTextChunksOptions {\n /** When true, skip the `message-stream-complete` event at the end.\n * Callers that need to broadcast additional events (e.g. tool-call\n * indicators) before the stream ends should set this to `true` and\n * call {@link broadcastStreamComplete} explicitly when done. */\n skipComplete?: boolean;\n}\n\nexport async function broadcastTextChunks(\n conversationId: string,\n messageId: string,\n text: string,\n options?: BroadcastTextChunksOptions,\n): Promise<void> {\n for (let i = 0; i < text.length; i += CHUNK_SIZE) {\n const chunk = text.slice(i, i + CHUNK_SIZE);\n await pusher\n .trigger(chatChannel(conversationId), 'message-stream-chunk', {\n messageId,\n chunk,\n })\n .catch(() => {});\n }\n\n if (!options?.skipComplete) {\n await broadcastStreamComplete(conversationId, messageId);\n }\n}\n\nexport async function broadcastStreamComplete(\n conversationId: string,\n messageId: string,\n): Promise<void> {\n await pusher\n .trigger(chatChannel(conversationId), 'message-stream-complete', {\n messageId,\n })\n .catch(() => {});\n}\n"],"names":[],"mappings":"AAAA;;;;GAIG;;;AACH,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEvD,MAAM,UAAU,GAAG,EAAE,CAAC;AAUtB,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,cAAsB,EACtB,SAAiB,EACjB,IAAY,EACZ,OAAoC;IAEpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,UAAU,EAAE,CAAC;QACjD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC;QAC5C,MAAM,MAAM;aACT,OAAO,CAAC,WAAW,CAAC,cAAc,CAAC,EAAE,sBAAsB,EAAE;YAC5D,SAAS;YACT,KAAK;SACN,CAAC;aACD,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACrB,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC;QAC3B,MAAM,uBAAuB,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,cAAsB,EACtB,SAAiB;IAEjB,MAAM,MAAM;SACT,OAAO,CAAC,WAAW,CAAC,cAAc,CAAC,EAAE,yBAAyB,EAAE;QAC/D,SAAS;KACV,CAAC;SACD,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;AACrB,CAAC","debug_id":"4d446101-229c-5c73-81df-7c16b110b221"}
@@ -1,3 +1,18 @@
1
1
  import IORedis from 'ioredis';
2
2
  export declare const bullConnection: IORedis;
3
+ /**
4
+ * Key prefix applied to every BullMQ Queue and Worker.
5
+ *
6
+ * Without this, BullMQ defaults to the `bull` namespace, so ANY process
7
+ * pointed at the same Redis instance shares the same queues. That is a
8
+ * problem when a single Redis (e.g. a shared Upstash instance) is used across
9
+ * environments while each environment has its own database: a worker can pick
10
+ * up a job enqueued elsewhere, fail to find its `RunJob` row, and crash-loop
11
+ * with "No record was found for an update".
12
+ *
13
+ * Namespacing by environment keeps each environment's jobs isolated. Override
14
+ * with `BULL_PREFIX` when you need finer-grained separation (e.g. per
15
+ * developer sharing one Redis).
16
+ */
17
+ export declare function getBullPrefix(): string;
3
18
  //# sourceMappingURL=connection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"connection.d.ts","sourceRoot":"/","sources":["workers/connection.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAoC9B,eAAO,MAAM,cAAc,SAAwB,CAAC"}
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"/","sources":["workers/connection.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAoC9B,eAAO,MAAM,cAAc,SAAwB,CAAC;AAEpD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAGtC"}