@goscribe/server 1.3.4 → 1.6.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 (383) hide show
  1. package/.env.example +12 -0
  2. package/.vscode/settings.json +3 -0
  3. package/REFACTOR_NOTES.md +60 -0
  4. package/TESTING_PROMPT.md +225 -0
  5. package/dist/context.d.ts +14 -1
  6. package/dist/context.js +23 -2
  7. package/dist/controllers/admin.controller.d.ts +715 -0
  8. package/dist/controllers/admin.controller.js +9 -0
  9. package/dist/controllers/annotations.controller.d.ts +439 -0
  10. package/dist/controllers/annotations.controller.js +9 -0
  11. package/dist/controllers/app-router.controller.d.ts +3011 -0
  12. package/dist/controllers/app-router.controller.js +38 -0
  13. package/dist/controllers/app-router.controller.test.d.ts +1 -0
  14. package/dist/controllers/app-router.controller.test.js +36 -0
  15. package/dist/controllers/auth.controller.d.ts +323 -0
  16. package/dist/controllers/auth.controller.js +9 -0
  17. package/dist/controllers/base.controller.d.ts +4 -0
  18. package/dist/controllers/base.controller.js +5 -0
  19. package/dist/controllers/chat.controller.d.ts +341 -0
  20. package/dist/controllers/chat.controller.js +9 -0
  21. package/dist/controllers/copilot.controller.d.ts +397 -0
  22. package/dist/controllers/copilot.controller.js +9 -0
  23. package/dist/controllers/flashcards.controller.d.ts +651 -0
  24. package/dist/controllers/flashcards.controller.js +9 -0
  25. package/dist/controllers/members.controller.d.ts +339 -0
  26. package/dist/controllers/members.controller.js +9 -0
  27. package/dist/controllers/notifications.controller.d.ts +199 -0
  28. package/dist/controllers/notifications.controller.js +9 -0
  29. package/dist/controllers/payment.controller.d.ts +181 -0
  30. package/dist/controllers/payment.controller.js +9 -0
  31. package/dist/controllers/podcast.controller.d.ts +575 -0
  32. package/dist/controllers/podcast.controller.js +9 -0
  33. package/dist/controllers/router-module.controller.d.ts +5 -0
  34. package/dist/controllers/router-module.controller.js +6 -0
  35. package/dist/controllers/studyguide.controller.d.ts +73 -0
  36. package/dist/controllers/studyguide.controller.js +9 -0
  37. package/dist/controllers/worksheets.controller.d.ts +829 -0
  38. package/dist/controllers/worksheets.controller.js +9 -0
  39. package/dist/controllers/workspace.controller.d.ts +1207 -0
  40. package/dist/controllers/workspace.controller.js +9 -0
  41. package/dist/lib/activity_human_description.test.js +16 -15
  42. package/dist/lib/activity_log_service.test.js +28 -23
  43. package/dist/lib/ai/config.d.ts +20 -0
  44. package/dist/lib/ai/config.js +31 -0
  45. package/dist/lib/ai/embedding-client.d.ts +8 -0
  46. package/dist/lib/ai/embedding-client.js +30 -0
  47. package/dist/lib/ai/index.d.ts +48 -0
  48. package/dist/lib/ai/index.js +29 -0
  49. package/dist/lib/ai/inference-backend/client.d.ts +28 -0
  50. package/dist/lib/ai/inference-backend/client.js +301 -0
  51. package/dist/lib/ai/inference-backend/mocks.d.ts +12 -0
  52. package/dist/lib/ai/inference-backend/mocks.js +133 -0
  53. package/dist/lib/ai/inference-backend/types.d.ts +44 -0
  54. package/dist/lib/ai/inference-backend/types.js +1 -0
  55. package/dist/lib/ai/json-parse.d.ts +2 -0
  56. package/dist/lib/ai/json-parse.js +34 -0
  57. package/dist/lib/ai/llm-client.d.ts +7 -0
  58. package/dist/lib/ai/llm-client.js +36 -0
  59. package/dist/lib/ai/mock.d.ts +2 -0
  60. package/dist/lib/ai/mock.js +10 -0
  61. package/dist/lib/ai/types.d.ts +9 -0
  62. package/dist/lib/ai/types.js +1 -0
  63. package/dist/lib/chunking.d.ts +19 -0
  64. package/dist/lib/chunking.js +47 -0
  65. package/dist/lib/curated-kb-seed.d.ts +12 -0
  66. package/dist/lib/curated-kb-seed.js +155 -0
  67. package/dist/lib/email.js +67 -108
  68. package/dist/lib/embeddings.d.ts +2 -0
  69. package/dist/lib/embeddings.js +1 -0
  70. package/dist/lib/ensure-curated-kb-catalog.d.ts +6 -0
  71. package/dist/lib/ensure-curated-kb-catalog.js +53 -0
  72. package/dist/lib/env.d.ts +1 -5
  73. package/dist/lib/env.js +2 -7
  74. package/dist/lib/inference.d.ts +1 -8
  75. package/dist/lib/inference.js +1 -19
  76. package/dist/lib/kb-meta.d.ts +8 -0
  77. package/dist/lib/kb-meta.js +77 -0
  78. package/dist/lib/note-text.d.ts +1 -0
  79. package/dist/lib/note-text.js +47 -0
  80. package/dist/lib/notification-service.test.js +37 -36
  81. package/dist/lib/pdf.d.ts +11 -0
  82. package/dist/lib/pdf.js +11 -0
  83. package/dist/lib/usage_service.d.ts +2 -1
  84. package/dist/lib/usage_service.js +30 -12
  85. package/dist/lib/worksheet-generation.js +4 -4
  86. package/dist/lib/worksheet-generation.test.js +32 -17
  87. package/dist/lib/workspace-kb.d.ts +5 -0
  88. package/dist/lib/workspace-kb.js +7 -0
  89. package/dist/models/controller-context.model.d.ts +8 -0
  90. package/dist/models/controller-context.model.js +1 -0
  91. package/dist/repositories/artifact.repository.d.ts +60 -0
  92. package/dist/repositories/artifact.repository.js +40 -0
  93. package/dist/repositories/base.repository.d.ts +14 -0
  94. package/dist/repositories/base.repository.js +14 -0
  95. package/dist/repositories/invitation.repository.d.ts +94 -0
  96. package/dist/repositories/invitation.repository.js +44 -0
  97. package/dist/repositories/notification.repository.d.ts +72 -0
  98. package/dist/repositories/notification.repository.js +44 -0
  99. package/dist/repositories/router-module.repository.d.ts +10 -0
  100. package/dist/repositories/router-module.repository.js +14 -0
  101. package/dist/repositories/user.repository.d.ts +74 -0
  102. package/dist/repositories/user.repository.js +37 -0
  103. package/dist/repositories/workspace-member.repository.d.ts +31 -0
  104. package/dist/repositories/workspace-member.repository.js +31 -0
  105. package/dist/repositories/workspace.repository.d.ts +97 -0
  106. package/dist/repositories/workspace.repository.js +79 -0
  107. package/dist/routers/_app.d.ts +566 -111
  108. package/dist/routers/_app.js +4 -0
  109. package/dist/routers/admin.d.ts +0 -4
  110. package/dist/routers/admin.js +21 -549
  111. package/dist/routers/annotations.js +12 -170
  112. package/dist/routers/artifactVersions.d.ts +65 -0
  113. package/dist/routers/artifactVersions.js +14 -0
  114. package/dist/routers/auth.d.ts +0 -6
  115. package/dist/routers/auth.js +37 -422
  116. package/dist/routers/chat.js +15 -229
  117. package/dist/routers/copilot.d.ts +14 -13
  118. package/dist/routers/copilot.js +13 -532
  119. package/dist/routers/flashcards.d.ts +17 -6
  120. package/dist/routers/flashcards.js +23 -349
  121. package/dist/routers/knowledgeBase.d.ts +421 -0
  122. package/dist/routers/knowledgeBase.js +118 -0
  123. package/dist/routers/members.d.ts +0 -41
  124. package/dist/routers/members.js +22 -710
  125. package/dist/routers/notes.d.ts +94 -0
  126. package/dist/routers/notes.js +37 -0
  127. package/dist/routers/notifications.js +7 -109
  128. package/dist/routers/payment.d.ts +2 -12
  129. package/dist/routers/payment.js +11 -393
  130. package/dist/routers/podcast.d.ts +1 -1
  131. package/dist/routers/podcast.js +11 -784
  132. package/dist/routers/studyguide.js +3 -129
  133. package/dist/routers/worksheets.d.ts +29 -14
  134. package/dist/routers/worksheets.js +49 -628
  135. package/dist/routers/workspace.d.ts +27 -71
  136. package/dist/routers/workspace.js +29 -922
  137. package/dist/scripts/purge-deleted-users.js +2 -2
  138. package/dist/server.js +10 -3
  139. package/dist/services/activity/activity-human-description.service.d.ts +13 -0
  140. package/dist/services/activity/activity-human-description.service.js +221 -0
  141. package/dist/services/activity/activity-human-description.service.test.d.ts +1 -0
  142. package/dist/services/activity/activity-human-description.service.test.js +16 -0
  143. package/dist/services/activity/activity-log.service.d.ts +87 -0
  144. package/dist/services/activity/activity-log.service.js +276 -0
  145. package/dist/services/activity/activity-log.service.test.d.ts +1 -0
  146. package/dist/services/activity/activity-log.service.test.js +27 -0
  147. package/dist/services/activity-human-description.service.d.ts +13 -0
  148. package/dist/services/activity-human-description.service.js +221 -0
  149. package/dist/services/activity-human-description.service.test.d.ts +1 -0
  150. package/dist/services/activity-human-description.service.test.js +16 -0
  151. package/dist/services/activity-log.service.d.ts +87 -0
  152. package/dist/services/activity-log.service.js +276 -0
  153. package/dist/services/activity-log.service.test.d.ts +1 -0
  154. package/dist/services/activity-log.service.test.js +27 -0
  155. package/dist/services/admin/admin.service.d.ts +270 -0
  156. package/dist/services/admin/admin.service.js +476 -0
  157. package/dist/services/admin.service.d.ts +270 -0
  158. package/dist/services/admin.service.js +476 -0
  159. package/dist/services/ai/ai-session.service.d.ts +5 -0
  160. package/dist/services/ai/ai-session.service.js +4 -0
  161. package/dist/services/ai-session.service.d.ts +60 -0
  162. package/dist/services/ai-session.service.js +561 -0
  163. package/dist/services/annotation.service.d.ts +177 -0
  164. package/dist/services/annotation.service.js +154 -0
  165. package/dist/services/artifact-notification.service.d.ts +14 -0
  166. package/dist/services/artifact-notification.service.js +20 -0
  167. package/dist/services/artifact-version.service.d.ts +38 -0
  168. package/dist/services/artifact-version.service.js +129 -0
  169. package/dist/services/artifacts/annotation.service.d.ts +177 -0
  170. package/dist/services/artifacts/annotation.service.js +154 -0
  171. package/dist/services/artifacts/artifact-version.service.d.ts +38 -0
  172. package/dist/services/artifacts/artifact-version.service.js +129 -0
  173. package/dist/services/artifacts/chat.service.d.ts +127 -0
  174. package/dist/services/artifacts/chat.service.js +182 -0
  175. package/dist/services/artifacts/study-guide.service.d.ts +18 -0
  176. package/dist/services/artifacts/study-guide.service.js +65 -0
  177. package/dist/services/auth/auth.service.d.ts +94 -0
  178. package/dist/services/auth/auth.service.js +368 -0
  179. package/dist/services/auth.service.d.ts +94 -0
  180. package/dist/services/auth.service.js +368 -0
  181. package/dist/services/base.service.d.ts +14 -0
  182. package/dist/services/base.service.js +14 -0
  183. package/dist/services/billing/payment.service.d.ts +44 -0
  184. package/dist/services/billing/payment.service.js +365 -0
  185. package/dist/services/billing/subscription.service.d.ts +37 -0
  186. package/dist/services/billing/subscription.service.js +654 -0
  187. package/dist/services/billing/usage.service.d.ts +47 -0
  188. package/dist/services/billing/usage.service.js +149 -0
  189. package/dist/services/chat.service.d.ts +127 -0
  190. package/dist/services/chat.service.js +182 -0
  191. package/dist/services/content/copilot.service.d.ts +113 -0
  192. package/dist/services/content/copilot.service.js +439 -0
  193. package/dist/services/content/flashcard-progress.service.d.ts +159 -0
  194. package/dist/services/content/flashcard-progress.service.js +432 -0
  195. package/dist/services/content/flashcard.service.d.ts +184 -0
  196. package/dist/services/content/flashcard.service.js +339 -0
  197. package/dist/services/content/media-analysis.service.d.ts +23 -0
  198. package/dist/services/content/media-analysis.service.js +404 -0
  199. package/dist/services/content/podcast.service.d.ts +267 -0
  200. package/dist/services/content/podcast.service.js +653 -0
  201. package/dist/services/content/worksheet-content.service.d.ts +37 -0
  202. package/dist/services/content/worksheet-content.service.js +84 -0
  203. package/dist/services/content/worksheet-content.service.test.d.ts +1 -0
  204. package/dist/services/content/worksheet-content.service.test.js +69 -0
  205. package/dist/services/content/worksheet-generation.service.d.ts +91 -0
  206. package/dist/services/content/worksheet-generation.service.js +95 -0
  207. package/dist/services/content/worksheet-generation.service.test.d.ts +1 -0
  208. package/dist/services/content/worksheet-generation.service.test.js +20 -0
  209. package/dist/services/content/worksheet.service.d.ts +347 -0
  210. package/dist/services/content/worksheet.service.js +599 -0
  211. package/dist/services/copilot.service.d.ts +116 -0
  212. package/dist/services/copilot.service.js +447 -0
  213. package/dist/services/flashcard-progress.service.d.ts +2 -2
  214. package/dist/services/flashcard-progress.service.js +3 -2
  215. package/dist/services/flashcard.service.d.ts +140 -0
  216. package/dist/services/flashcard.service.js +325 -0
  217. package/dist/services/invitation.service.d.ts +66 -0
  218. package/dist/services/invitation.service.js +348 -0
  219. package/dist/services/knowledge/knowledge-base.service.d.ts +316 -0
  220. package/dist/services/knowledge/knowledge-base.service.js +544 -0
  221. package/dist/services/knowledge-base.service.d.ts +316 -0
  222. package/dist/services/knowledge-base.service.js +536 -0
  223. package/dist/services/media-analysis.service.d.ts +23 -0
  224. package/dist/services/media-analysis.service.js +384 -0
  225. package/dist/services/member.service.d.ts +36 -0
  226. package/dist/services/member.service.js +193 -0
  227. package/dist/services/members/invitation.service.d.ts +66 -0
  228. package/dist/services/members/invitation.service.js +348 -0
  229. package/dist/services/members/member.service.d.ts +36 -0
  230. package/dist/services/members/member.service.js +193 -0
  231. package/dist/services/note.service.d.ts +55 -0
  232. package/dist/services/note.service.js +111 -0
  233. package/dist/services/notification.service.d.ts +214 -0
  234. package/dist/services/notification.service.js +550 -0
  235. package/dist/services/notification.service.test.d.ts +1 -0
  236. package/dist/services/notification.service.test.js +87 -0
  237. package/dist/services/notifications/notification.service.d.ts +214 -0
  238. package/dist/services/notifications/notification.service.js +550 -0
  239. package/dist/services/notifications/notification.service.test.d.ts +1 -0
  240. package/dist/services/notifications/notification.service.test.js +87 -0
  241. package/dist/services/payment.service.d.ts +55 -0
  242. package/dist/services/payment.service.js +368 -0
  243. package/dist/services/podcast.service.d.ts +267 -0
  244. package/dist/services/podcast.service.js +654 -0
  245. package/dist/services/router-module.service.d.ts +7 -0
  246. package/dist/services/router-module.service.js +10 -0
  247. package/dist/services/study-guide.service.d.ts +18 -0
  248. package/dist/services/study-guide.service.js +65 -0
  249. package/dist/services/subscription.service.d.ts +37 -0
  250. package/dist/services/subscription.service.js +654 -0
  251. package/dist/services/usage-limit-policy.service.d.ts +12 -0
  252. package/dist/services/usage-limit-policy.service.js +22 -0
  253. package/dist/services/usage-limit-policy.service.test.d.ts +1 -0
  254. package/dist/services/usage-limit-policy.service.test.js +46 -0
  255. package/dist/services/usage.service.d.ts +27 -0
  256. package/dist/services/usage.service.js +77 -0
  257. package/dist/services/worksheet-content.service.d.ts +42 -0
  258. package/dist/services/worksheet-content.service.js +84 -0
  259. package/dist/services/worksheet-content.service.test.d.ts +1 -0
  260. package/dist/services/worksheet-content.service.test.js +69 -0
  261. package/dist/services/worksheet-generation.service.d.ts +91 -0
  262. package/dist/services/worksheet-generation.service.js +95 -0
  263. package/dist/services/worksheet-generation.service.test.d.ts +1 -0
  264. package/dist/services/worksheet-generation.service.test.js +20 -0
  265. package/dist/services/worksheet.service.d.ts +385 -0
  266. package/dist/services/worksheet.service.js +596 -0
  267. package/dist/services/workspace/workspace-analytics.service.d.ts +24 -0
  268. package/dist/services/workspace/workspace-analytics.service.js +95 -0
  269. package/dist/services/workspace/workspace-kb.service.d.ts +40 -0
  270. package/dist/services/workspace/workspace-kb.service.js +184 -0
  271. package/dist/services/workspace/workspace.service.d.ts +263 -0
  272. package/dist/services/workspace/workspace.service.js +401 -0
  273. package/dist/services/workspace-analytics.service.d.ts +24 -0
  274. package/dist/services/workspace-analytics.service.js +95 -0
  275. package/dist/services/workspace-kb.service.d.ts +40 -0
  276. package/dist/services/workspace-kb.service.js +184 -0
  277. package/dist/services/workspace-progress.service.d.ts +27 -0
  278. package/dist/services/workspace-progress.service.js +56 -0
  279. package/dist/services/workspace-progress.service.test.d.ts +1 -0
  280. package/dist/services/workspace-progress.service.test.js +49 -0
  281. package/dist/services/workspace.service.d.ts +307 -0
  282. package/dist/services/workspace.service.js +390 -0
  283. package/dist/trpc.d.ts +12 -4
  284. package/dist/trpc.js +7 -13
  285. package/package.json +5 -6
  286. package/prisma/migrations/20260509000001_add_knowledge_base/migration.sql +99 -0
  287. package/prisma/migrations/20260509000002_curate_knowledge_base/migration.sql +52 -0
  288. package/prisma/migrations/20260522000000_add_notes/migration.sql +27 -0
  289. package/prisma/migrations/20260524000000_remove_notes/migration.sql +3 -0
  290. package/prisma/schema.prisma +150 -48
  291. package/prisma/seed.mjs +67 -0
  292. package/scripts/debug/README.md +4 -0
  293. package/src/README.md +63 -0
  294. package/src/context.ts +33 -3
  295. package/src/lib/ai/config.ts +34 -0
  296. package/src/lib/ai/embedding-client.ts +47 -0
  297. package/src/lib/ai/index.ts +65 -0
  298. package/src/lib/ai/inference-backend/client.ts +479 -0
  299. package/src/lib/ai/inference-backend/mocks.ts +171 -0
  300. package/src/lib/ai/inference-backend/types.ts +50 -0
  301. package/src/lib/ai/json-parse.ts +35 -0
  302. package/src/lib/ai/llm-client.ts +54 -0
  303. package/src/lib/ai/mock.ts +12 -0
  304. package/src/lib/ai/types.ts +11 -0
  305. package/src/lib/chunking.ts +81 -0
  306. package/src/lib/curated-kb-seed.ts +164 -0
  307. package/src/lib/email.ts +77 -115
  308. package/src/lib/embeddings.ts +9 -0
  309. package/src/lib/ensure-curated-kb-catalog.ts +60 -0
  310. package/src/lib/env.ts +2 -7
  311. package/src/lib/inference.ts +1 -21
  312. package/src/lib/kb-meta.ts +81 -0
  313. package/src/lib/pdf.ts +23 -0
  314. package/src/lib/workspace-kb.ts +7 -0
  315. package/src/repositories/artifact.repository.ts +55 -0
  316. package/src/repositories/base.repository.ts +19 -0
  317. package/src/repositories/invitation.repository.ts +53 -0
  318. package/src/repositories/notification.repository.ts +53 -0
  319. package/src/repositories/user.repository.ts +44 -0
  320. package/src/repositories/workspace-member.repository.ts +38 -0
  321. package/src/repositories/workspace.repository.ts +89 -0
  322. package/src/routers/_app.ts +4 -0
  323. package/src/routers/admin.ts +124 -692
  324. package/src/routers/annotations.ts +25 -203
  325. package/src/routers/artifactVersions.ts +32 -0
  326. package/src/routers/auth.ts +82 -520
  327. package/src/routers/chat.ts +42 -245
  328. package/src/routers/copilot.ts +41 -666
  329. package/src/routers/flashcards.ts +108 -404
  330. package/src/routers/knowledgeBase.ts +216 -0
  331. package/src/routers/members.ts +60 -782
  332. package/src/routers/notifications.ts +15 -117
  333. package/src/routers/payment.ts +37 -446
  334. package/src/routers/podcast.ts +36 -898
  335. package/src/routers/studyguide.ts +5 -144
  336. package/src/routers/worksheets.ts +171 -735
  337. package/src/routers/workspace.ts +141 -1108
  338. package/src/scripts/purge-deleted-users.ts +2 -2
  339. package/src/server.ts +10 -3
  340. package/src/{lib/activity_human_description.test.ts → services/activity/activity-human-description.service.test.ts} +1 -1
  341. package/src/{lib/activity_log_service.test.ts → services/activity/activity-log.service.test.ts} +1 -1
  342. package/src/{lib/activity_log_service.ts → services/activity/activity-log.service.ts} +2 -2
  343. package/src/services/admin/admin.service.ts +612 -0
  344. package/src/services/ai/ai-session.service.ts +5 -0
  345. package/src/services/artifacts/annotation.service.ts +189 -0
  346. package/src/services/artifacts/artifact-version.service.ts +151 -0
  347. package/src/services/artifacts/chat.service.ts +197 -0
  348. package/src/services/artifacts/study-guide.service.ts +72 -0
  349. package/src/services/auth/auth.service.ts +473 -0
  350. package/src/services/base.service.ts +19 -0
  351. package/src/services/billing/payment.service.ts +433 -0
  352. package/src/{lib/subscription_service.ts → services/billing/subscription.service.ts} +5 -5
  353. package/src/services/billing/usage.service.ts +207 -0
  354. package/src/services/content/copilot.service.ts +587 -0
  355. package/src/services/{flashcard-progress.service.ts → content/flashcard-progress.service.ts} +18 -12
  356. package/src/services/content/flashcard.service.ts +417 -0
  357. package/src/services/content/media-analysis.service.ts +561 -0
  358. package/src/services/content/podcast.service.ts +777 -0
  359. package/src/services/content/worksheet-content.service.test.ts +83 -0
  360. package/src/services/content/worksheet-content.service.ts +117 -0
  361. package/src/{lib/worksheet-generation.test.ts → services/content/worksheet-generation.service.test.ts} +3 -3
  362. package/src/services/content/worksheet.service.ts +751 -0
  363. package/src/services/knowledge/knowledge-base.service.ts +705 -0
  364. package/src/services/members/invitation.service.ts +427 -0
  365. package/src/services/members/member.service.ts +241 -0
  366. package/src/{lib/notification-service.test.ts → services/notifications/notification.service.test.ts} +2 -2
  367. package/src/{lib/notification-service.ts → services/notifications/notification.service.ts} +102 -1
  368. package/src/services/workspace/workspace-analytics.service.ts +107 -0
  369. package/src/services/workspace/workspace-kb.service.ts +273 -0
  370. package/src/services/workspace/workspace.service.ts +488 -0
  371. package/src/trpc.ts +7 -15
  372. package/src/lib/ai-session.ts +0 -704
  373. package/src/lib/usage_service.ts +0 -74
  374. package/src/lib/workspace-access.ts +0 -13
  375. /package/{check-difficulty.cjs → scripts/debug/check-difficulty.cjs} +0 -0
  376. /package/{check-questions.cjs → scripts/debug/check-questions.cjs} +0 -0
  377. /package/{db-summary.cjs → scripts/debug/db-summary.cjs} +0 -0
  378. /package/{mcq-test.cjs → scripts/debug/mcq-test.cjs} +0 -0
  379. /package/{test-generate.js → scripts/debug/test-generate.js} +0 -0
  380. /package/{test-ratio.cjs → scripts/debug/test-ratio.cjs} +0 -0
  381. /package/{zod-test.cjs → scripts/debug/zod-test.cjs} +0 -0
  382. /package/src/{lib/activity_human_description.ts → services/activity/activity-human-description.service.ts} +0 -0
  383. /package/src/{lib/worksheet-generation.ts → services/content/worksheet-generation.service.ts} +0 -0
@@ -1,94 +1,17 @@
1
1
  import { z } from 'zod';
2
- import { TRPCError } from '@trpc/server';
3
2
  import { router, authedProcedure, limitedProcedure } from '../trpc.js';
4
- import { aiSessionService } from '../lib/ai-session.js';
5
- import PusherService from '../lib/pusher.js';
6
- import { notifyArtifactFailed, notifyArtifactReady } from '../lib/notification-service.js';
7
- import { createFlashcardProgressService } from '../services/flashcard-progress.service.js';
8
- import { ArtifactType } from '../lib/constants.js';
9
- import { workspaceAccessFilter } from '../lib/workspace-access.js';
10
- import inference from '../lib/inference.js';
11
- const typedAnswerGradeSchema = z.object({
12
- isCorrect: z.boolean(),
13
- confidence: z.number().min(0).max(1),
14
- reason: z.string().min(1),
15
- matchedAnswer: z.string().nullable(),
16
- });
17
- function normalizeAcceptedAnswers(answers) {
18
- if (!answers || answers.length === 0)
19
- return [];
20
- const seen = new Set();
21
- const normalized = [];
22
- for (const answer of answers) {
23
- const trimmed = answer.trim();
24
- if (!trimmed)
25
- continue;
26
- const key = trimmed.toLowerCase();
27
- if (seen.has(key))
28
- continue;
29
- seen.add(key);
30
- normalized.push(trimmed);
31
- }
32
- return normalized;
33
- }
34
- function extractFirstJsonObject(text) {
35
- const start = text.indexOf('{');
36
- const end = text.lastIndexOf('}');
37
- if (start === -1 || end === -1 || end <= start)
38
- return null;
39
- return text.slice(start, end + 1);
40
- }
3
+ import { FlashcardService } from '../services/content/flashcard.service.js';
4
+ import { createFlashcardProgressService } from '../services/content/flashcard-progress.service.js';
41
5
  export const flashcards = router({
42
6
  listSets: authedProcedure
43
7
  .input(z.object({ workspaceId: z.string() }))
44
- .query(async ({ ctx, input }) => {
45
- const workspace = await ctx.db.workspace.findFirst({
46
- where: { id: input.workspaceId, ownerId: ctx.session.user.id },
47
- });
48
- if (!workspace)
49
- throw new TRPCError({ code: 'NOT_FOUND' });
50
- return ctx.db.artifact.findMany({
51
- where: { workspaceId: input.workspaceId, type: ArtifactType.FLASHCARD_SET },
52
- include: {
53
- versions: {
54
- orderBy: { version: 'desc' },
55
- take: 1, // Get only the latest version
56
- },
57
- },
58
- orderBy: { updatedAt: 'desc' },
59
- });
60
- }),
8
+ .query(({ ctx, input }) => new FlashcardService(ctx.db).listSets(ctx.session.user.id, input.workspaceId)),
61
9
  listCards: authedProcedure
62
10
  .input(z.object({ workspaceId: z.string() }))
63
- .query(async ({ ctx, input }) => {
64
- const set = await ctx.db.artifact.findFirst({
65
- where: { workspaceId: input.workspaceId, type: ArtifactType.FLASHCARD_SET, workspace: workspaceAccessFilter(ctx.session.user.id) },
66
- include: {
67
- flashcards: {
68
- include: {
69
- progress: {
70
- where: {
71
- userId: ctx.session.user.id,
72
- },
73
- },
74
- }
75
- },
76
- },
77
- orderBy: { createdAt: 'desc' },
78
- });
79
- if (!set)
80
- throw new TRPCError({ code: 'NOT_FOUND' });
81
- return set.flashcards;
82
- }),
11
+ .query(({ ctx, input }) => new FlashcardService(ctx.db).listCards(ctx.session.user.id, input.workspaceId)),
83
12
  isGenerating: authedProcedure
84
13
  .input(z.object({ workspaceId: z.string() }))
85
- .query(async ({ ctx, input }) => {
86
- const artifact = await ctx.db.artifact.findFirst({
87
- where: { workspaceId: input.workspaceId, type: ArtifactType.FLASHCARD_SET, workspace: workspaceAccessFilter(ctx.session.user.id) },
88
- orderBy: { createdAt: 'desc' },
89
- });
90
- return artifact?.generating;
91
- }),
14
+ .query(({ ctx, input }) => new FlashcardService(ctx.db).isGenerating(ctx.session.user.id, input.workspaceId)),
92
15
  createCard: limitedProcedure
93
16
  .input(z.object({
94
17
  workspaceId: z.string(),
@@ -98,31 +21,7 @@ export const flashcards = router({
98
21
  tags: z.array(z.string()).optional(),
99
22
  order: z.number().int().optional(),
100
23
  }))
101
- .mutation(async ({ ctx, input }) => {
102
- const set = await ctx.db.artifact.findFirst({
103
- where: {
104
- type: ArtifactType.FLASHCARD_SET, workspace: {
105
- id: input.workspaceId,
106
- }
107
- },
108
- include: {
109
- flashcards: true,
110
- },
111
- orderBy: { updatedAt: 'desc' },
112
- });
113
- if (!set)
114
- throw new TRPCError({ code: 'NOT_FOUND' });
115
- return ctx.db.flashcard.create({
116
- data: {
117
- artifactId: set.id,
118
- front: input.front,
119
- back: input.back,
120
- acceptedAnswers: normalizeAcceptedAnswers(input.acceptedAnswers),
121
- tags: input.tags ?? [],
122
- order: input.order ?? 0,
123
- },
124
- });
125
- }),
24
+ .mutation(({ ctx, input }) => new FlashcardService(ctx.db).createCard(ctx.session.user.id, input)),
126
25
  updateCard: authedProcedure
127
26
  .input(z.object({
128
27
  cardId: z.string(),
@@ -132,109 +31,19 @@ export const flashcards = router({
132
31
  tags: z.array(z.string()).optional(),
133
32
  order: z.number().int().optional(),
134
33
  }))
135
- .mutation(async ({ ctx, input }) => {
136
- const card = await ctx.db.flashcard.findFirst({
137
- where: { id: input.cardId, artifact: { type: ArtifactType.FLASHCARD_SET, workspace: workspaceAccessFilter(ctx.session.user.id) } },
138
- });
139
- if (!card)
140
- throw new TRPCError({ code: 'NOT_FOUND' });
141
- return ctx.db.flashcard.update({
142
- where: { id: input.cardId },
143
- data: {
144
- front: input.front ?? card.front,
145
- back: input.back ?? card.back,
146
- acceptedAnswers: input.acceptedAnswers ? normalizeAcceptedAnswers(input.acceptedAnswers) : card.acceptedAnswers,
147
- tags: input.tags ?? card.tags,
148
- order: input.order ?? card.order,
149
- },
150
- });
151
- }),
34
+ .mutation(({ ctx, input }) => new FlashcardService(ctx.db).updateCard(ctx.session.user.id, input)),
152
35
  gradeTypedAnswer: authedProcedure
153
36
  .input(z.object({
154
37
  flashcardId: z.string().cuid(),
155
38
  userAnswer: z.string().min(1),
156
39
  }))
157
- .mutation(async ({ ctx, input }) => {
158
- const flashcard = await ctx.db.flashcard.findFirst({
159
- where: {
160
- id: input.flashcardId,
161
- artifact: {
162
- type: ArtifactType.FLASHCARD_SET,
163
- workspace: workspaceAccessFilter(ctx.session.user.id),
164
- },
165
- },
166
- select: {
167
- id: true,
168
- front: true,
169
- back: true,
170
- acceptedAnswers: true,
171
- },
172
- });
173
- if (!flashcard) {
174
- throw new TRPCError({ code: 'NOT_FOUND', message: 'Flashcard not found' });
175
- }
176
- const acceptedAnswers = [
177
- flashcard.back,
178
- ...normalizeAcceptedAnswers(flashcard.acceptedAnswers),
179
- ];
180
- const prompt = [
181
- 'Grade whether the student answer is semantically correct for the flashcard.',
182
- '',
183
- 'Return ONLY valid JSON with this exact shape:',
184
- '{"isCorrect": boolean, "confidence": number, "reason": string, "matchedAnswer": string | null}',
185
- '',
186
- 'Rules:',
187
- '- Accept synonyms, short paraphrases, and equivalent wording.',
188
- '- Reject answers that are contradictory, unrelated, or materially incomplete.',
189
- '- confidence must be from 0 to 1.',
190
- '- reason must be under 160 characters.',
191
- '- matchedAnswer must be the matched canonical/alias answer, or null if incorrect.',
192
- '',
193
- `Question: ${flashcard.front}`,
194
- `Canonical answer: ${flashcard.back}`,
195
- `Accepted aliases: ${JSON.stringify(acceptedAnswers)}`,
196
- `Student answer: ${input.userAnswer}`,
197
- ].join('\n');
198
- try {
199
- const response = await inference([{ role: 'user', content: prompt }]);
200
- const content = response.choices?.[0]?.message?.content ?? '';
201
- const jsonCandidate = extractFirstJsonObject(content);
202
- if (!jsonCandidate) {
203
- throw new Error('No JSON object found in grading response');
204
- }
205
- const parsed = JSON.parse(jsonCandidate);
206
- return typedAnswerGradeSchema.parse(parsed);
207
- }
208
- catch (error) {
209
- throw new TRPCError({
210
- code: 'INTERNAL_SERVER_ERROR',
211
- message: 'Failed to grade typed answer. Please retry.',
212
- cause: error,
213
- });
214
- }
215
- }),
40
+ .mutation(({ ctx, input }) => new FlashcardService(ctx.db).gradeTypedAnswer(ctx.session.user.id, input)),
216
41
  deleteCard: authedProcedure
217
42
  .input(z.object({ cardId: z.string() }))
218
- .mutation(async ({ ctx, input }) => {
219
- const card = await ctx.db.flashcard.findFirst({
220
- where: { id: input.cardId, artifact: { workspace: workspaceAccessFilter(ctx.session.user.id) } },
221
- });
222
- if (!card)
223
- throw new TRPCError({ code: 'NOT_FOUND' });
224
- await ctx.db.flashcard.delete({ where: { id: input.cardId } });
225
- return true;
226
- }),
43
+ .mutation(({ ctx, input }) => new FlashcardService(ctx.db).deleteCard(ctx.session.user.id, input.cardId)),
227
44
  deleteSet: authedProcedure
228
45
  .input(z.object({ setId: z.string().uuid() }))
229
- .mutation(async ({ ctx, input }) => {
230
- const deleted = await ctx.db.artifact.deleteMany({
231
- where: { id: input.setId, type: ArtifactType.FLASHCARD_SET, workspace: workspaceAccessFilter(ctx.session.user.id) },
232
- });
233
- if (deleted.count === 0)
234
- throw new TRPCError({ code: 'NOT_FOUND' });
235
- return true;
236
- }),
237
- // Generate a flashcard set from a user prompt
46
+ .mutation(({ ctx, input }) => new FlashcardService(ctx.db).deleteSet(ctx.session.user.id, input.setId)),
238
47
  generateFromPrompt: limitedProcedure
239
48
  .input(z.object({
240
49
  workspaceId: z.string(),
@@ -244,119 +53,7 @@ export const flashcards = router({
244
53
  title: z.string().optional(),
245
54
  tags: z.array(z.string()).optional(),
246
55
  }))
247
- .mutation(async ({ ctx, input }) => {
248
- // Verify workspace ownership
249
- const workspace = await ctx.db.workspace.findFirst({
250
- where: { id: input.workspaceId, ownerId: ctx.session.user.id },
251
- });
252
- if (!workspace)
253
- throw new TRPCError({ code: 'NOT_FOUND' });
254
- const flashcardCurrent = await ctx.db.artifact.findFirst({
255
- where: {
256
- workspaceId: input.workspaceId,
257
- type: ArtifactType.FLASHCARD_SET,
258
- },
259
- select: {
260
- id: true,
261
- flashcards: true,
262
- },
263
- orderBy: {
264
- updatedAt: 'desc',
265
- },
266
- });
267
- try {
268
- await PusherService.emitTaskComplete(input.workspaceId, 'flash_card_info', { status: 'generating', numCards: input.numCards, difficulty: input.difficulty });
269
- const artifact = await ctx.db.artifact.create({
270
- data: {
271
- workspaceId: input.workspaceId,
272
- type: ArtifactType.FLASHCARD_SET,
273
- title: input.title || `Flashcards - ${new Date().toLocaleString()}`,
274
- createdById: ctx.session.user.id,
275
- generating: true,
276
- generatingMetadata: { quantity: input.numCards, difficulty: input.difficulty.toLowerCase() },
277
- flashcards: {
278
- create: flashcardCurrent?.flashcards.map((card) => ({
279
- front: card.front,
280
- back: card.back,
281
- })),
282
- },
283
- },
284
- });
285
- const currentCards = flashcardCurrent?.flashcards.length || 0;
286
- const newCards = input.numCards - currentCards;
287
- // Generate
288
- const content = await aiSessionService.generateFlashcardQuestions(input.workspaceId, ctx.session.user.id, input.numCards, input.difficulty, input.prompt);
289
- let createdCards = 0;
290
- try {
291
- const parsed = typeof content === 'string' ? JSON.parse(content) : content;
292
- const flashcardData = Array.isArray(parsed) ? parsed : (parsed.flashcards || []);
293
- for (let i = 0; i < Math.min(flashcardData.length, input.numCards); i++) {
294
- const card = flashcardData[i];
295
- const front = card.term || card.front || card.question || card.prompt || `Question ${i + 1}`;
296
- const back = card.definition || card.back || card.answer || card.solution || `Answer ${i + 1}`;
297
- await ctx.db.flashcard.create({
298
- data: {
299
- artifactId: artifact.id,
300
- front,
301
- back,
302
- order: i,
303
- tags: input.tags ?? ['ai-generated', input.difficulty],
304
- },
305
- });
306
- createdCards++;
307
- }
308
- }
309
- catch (error) {
310
- console.error("Failed to parse flashcard JSON or create cards:", error);
311
- // Fallback to text parsing if JSON fails
312
- const lines = content.split('\n').filter(line => line.trim());
313
- for (let i = 0; i < Math.min(lines.length, input.numCards); i++) {
314
- const line = lines[i];
315
- if (line.includes(' - ')) {
316
- const [front, back] = line.split(' - ');
317
- await ctx.db.flashcard.create({
318
- data: {
319
- artifactId: artifact.id,
320
- front: front.trim(),
321
- back: back.trim(),
322
- order: i,
323
- tags: input.tags ?? ['ai-generated', input.difficulty],
324
- },
325
- });
326
- createdCards++;
327
- }
328
- }
329
- }
330
- // Pusher complete
331
- await PusherService.emitFlashcardComplete(input.workspaceId, artifact);
332
- // Set generating to false on the artifact
333
- await ctx.db.artifact.update({ where: { id: artifact.id }, data: { generating: false } });
334
- await notifyArtifactReady(ctx.db, {
335
- userId: ctx.session.user.id,
336
- workspaceId: input.workspaceId,
337
- artifactId: artifact.id,
338
- artifactType: ArtifactType.FLASHCARD_SET,
339
- title: artifact.title,
340
- }).catch(() => { });
341
- return { artifact, createdCards };
342
- }
343
- catch (error) {
344
- if (flashcardCurrent?.id) {
345
- await ctx.db.artifact.update({ where: { id: flashcardCurrent.id }, data: { generating: false } });
346
- }
347
- await PusherService.emitError(input.workspaceId, `Failed to generate flashcards: ${error}`, 'flash_card_generation');
348
- await notifyArtifactFailed(ctx.db, {
349
- userId: ctx.session.user.id,
350
- workspaceId: input.workspaceId,
351
- artifactType: ArtifactType.FLASHCARD_SET,
352
- message: error instanceof Error
353
- ? error.message
354
- : 'Flashcard generation failed.',
355
- }).catch(() => { });
356
- throw error;
357
- }
358
- }),
359
- // Record study attempt
56
+ .mutation(({ ctx, input }) => new FlashcardService(ctx.db).generateFromPrompt(ctx.session.user.id, input)),
360
57
  recordStudyAttempt: authedProcedure
361
58
  .input(z.object({
362
59
  flashcardId: z.string().cuid(),
@@ -364,42 +61,22 @@ export const flashcards = router({
364
61
  confidence: z.enum(['easy', 'medium', 'hard']).optional(),
365
62
  timeSpentMs: z.number().optional(),
366
63
  }))
367
- .mutation(async ({ ctx, input }) => {
368
- const service = createFlashcardProgressService(ctx.db);
369
- return service.recordStudyAttempt({
370
- userId: ctx.userId,
371
- ...input,
372
- });
373
- }),
374
- // Get progress for a flashcard set
64
+ .mutation(({ ctx, input }) => createFlashcardProgressService(ctx.db).recordStudyAttempt({
65
+ userId: ctx.userId,
66
+ ...input,
67
+ })),
375
68
  getSetProgress: authedProcedure
376
69
  .input(z.object({ artifactId: z.string().cuid() }))
377
- .query(async ({ ctx, input }) => {
378
- const service = createFlashcardProgressService(ctx.db);
379
- return service.getSetProgress(ctx.userId, input.artifactId);
380
- }),
381
- // Get flashcards due for review
70
+ .query(({ ctx, input }) => createFlashcardProgressService(ctx.db).getSetProgress(ctx.userId, input.artifactId)),
382
71
  getDueFlashcards: authedProcedure
383
72
  .input(z.object({ workspaceId: z.string() }))
384
- .query(async ({ ctx, input }) => {
385
- const service = createFlashcardProgressService(ctx.db);
386
- return service.getDueFlashcards(ctx.userId, input.workspaceId);
387
- }),
388
- // Get statistics for a flashcard set
73
+ .query(({ ctx, input }) => createFlashcardProgressService(ctx.db).getDueFlashcards(ctx.userId, input.workspaceId)),
389
74
  getSetStatistics: authedProcedure
390
75
  .input(z.object({ artifactId: z.string().cuid() }))
391
- .query(async ({ ctx, input }) => {
392
- const service = createFlashcardProgressService(ctx.db);
393
- return service.getSetStatistics(ctx.userId, input.artifactId);
394
- }),
395
- // Reset progress for a flashcard
76
+ .query(({ ctx, input }) => createFlashcardProgressService(ctx.db).getSetStatistics(ctx.userId, input.artifactId)),
396
77
  resetProgress: authedProcedure
397
78
  .input(z.object({ flashcardId: z.string().cuid() }))
398
- .mutation(async ({ ctx, input }) => {
399
- const service = createFlashcardProgressService(ctx.db);
400
- return service.resetProgress(ctx.userId, input.flashcardId);
401
- }),
402
- // Bulk record study session
79
+ .mutation(({ ctx, input }) => createFlashcardProgressService(ctx.db).resetProgress(ctx.userId, input.flashcardId)),
403
80
  recordStudySession: authedProcedure
404
81
  .input(z.object({
405
82
  attempts: z.array(z.object({
@@ -409,11 +86,8 @@ export const flashcards = router({
409
86
  timeSpentMs: z.number().optional(),
410
87
  })),
411
88
  }))
412
- .mutation(async ({ ctx, input }) => {
413
- const service = createFlashcardProgressService(ctx.db);
414
- return service.recordStudySession({
415
- userId: ctx.userId,
416
- ...input,
417
- });
418
- }),
89
+ .mutation(({ ctx, input }) => createFlashcardProgressService(ctx.db).recordStudySession({
90
+ userId: ctx.userId,
91
+ ...input,
92
+ })),
419
93
  });