@goscribe/server 1.3.4 → 1.5.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 (378) 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/controllers/admin.controller.d.ts +715 -0
  6. package/dist/controllers/admin.controller.js +9 -0
  7. package/dist/controllers/annotations.controller.d.ts +439 -0
  8. package/dist/controllers/annotations.controller.js +9 -0
  9. package/dist/controllers/app-router.controller.d.ts +3011 -0
  10. package/dist/controllers/app-router.controller.js +38 -0
  11. package/dist/controllers/app-router.controller.test.d.ts +1 -0
  12. package/dist/controllers/app-router.controller.test.js +36 -0
  13. package/dist/controllers/auth.controller.d.ts +323 -0
  14. package/dist/controllers/auth.controller.js +9 -0
  15. package/dist/controllers/base.controller.d.ts +4 -0
  16. package/dist/controllers/base.controller.js +5 -0
  17. package/dist/controllers/chat.controller.d.ts +341 -0
  18. package/dist/controllers/chat.controller.js +9 -0
  19. package/dist/controllers/copilot.controller.d.ts +397 -0
  20. package/dist/controllers/copilot.controller.js +9 -0
  21. package/dist/controllers/flashcards.controller.d.ts +651 -0
  22. package/dist/controllers/flashcards.controller.js +9 -0
  23. package/dist/controllers/members.controller.d.ts +339 -0
  24. package/dist/controllers/members.controller.js +9 -0
  25. package/dist/controllers/notifications.controller.d.ts +199 -0
  26. package/dist/controllers/notifications.controller.js +9 -0
  27. package/dist/controllers/payment.controller.d.ts +181 -0
  28. package/dist/controllers/payment.controller.js +9 -0
  29. package/dist/controllers/podcast.controller.d.ts +575 -0
  30. package/dist/controllers/podcast.controller.js +9 -0
  31. package/dist/controllers/router-module.controller.d.ts +5 -0
  32. package/dist/controllers/router-module.controller.js +6 -0
  33. package/dist/controllers/studyguide.controller.d.ts +73 -0
  34. package/dist/controllers/studyguide.controller.js +9 -0
  35. package/dist/controllers/worksheets.controller.d.ts +829 -0
  36. package/dist/controllers/worksheets.controller.js +9 -0
  37. package/dist/controllers/workspace.controller.d.ts +1207 -0
  38. package/dist/controllers/workspace.controller.js +9 -0
  39. package/dist/lib/activity_human_description.test.js +16 -15
  40. package/dist/lib/activity_log_service.test.js +28 -23
  41. package/dist/lib/ai/config.d.ts +20 -0
  42. package/dist/lib/ai/config.js +31 -0
  43. package/dist/lib/ai/embedding-client.d.ts +8 -0
  44. package/dist/lib/ai/embedding-client.js +30 -0
  45. package/dist/lib/ai/index.d.ts +47 -0
  46. package/dist/lib/ai/index.js +28 -0
  47. package/dist/lib/ai/inference-backend/client.d.ts +28 -0
  48. package/dist/lib/ai/inference-backend/client.js +301 -0
  49. package/dist/lib/ai/inference-backend/mocks.d.ts +12 -0
  50. package/dist/lib/ai/inference-backend/mocks.js +133 -0
  51. package/dist/lib/ai/inference-backend/types.d.ts +44 -0
  52. package/dist/lib/ai/inference-backend/types.js +1 -0
  53. package/dist/lib/ai/json-parse.d.ts +2 -0
  54. package/dist/lib/ai/json-parse.js +34 -0
  55. package/dist/lib/ai/llm-client.d.ts +6 -0
  56. package/dist/lib/ai/llm-client.js +19 -0
  57. package/dist/lib/ai/mock.d.ts +2 -0
  58. package/dist/lib/ai/mock.js +10 -0
  59. package/dist/lib/ai/types.d.ts +9 -0
  60. package/dist/lib/ai/types.js +1 -0
  61. package/dist/lib/chunking.d.ts +19 -0
  62. package/dist/lib/chunking.js +47 -0
  63. package/dist/lib/curated-kb-seed.d.ts +12 -0
  64. package/dist/lib/curated-kb-seed.js +155 -0
  65. package/dist/lib/email.js +67 -108
  66. package/dist/lib/embeddings.d.ts +2 -0
  67. package/dist/lib/embeddings.js +1 -0
  68. package/dist/lib/ensure-curated-kb-catalog.d.ts +6 -0
  69. package/dist/lib/ensure-curated-kb-catalog.js +53 -0
  70. package/dist/lib/env.d.ts +1 -5
  71. package/dist/lib/env.js +2 -7
  72. package/dist/lib/inference.d.ts +1 -8
  73. package/dist/lib/inference.js +1 -19
  74. package/dist/lib/kb-meta.d.ts +8 -0
  75. package/dist/lib/kb-meta.js +77 -0
  76. package/dist/lib/note-text.d.ts +1 -0
  77. package/dist/lib/note-text.js +47 -0
  78. package/dist/lib/notification-service.test.js +37 -36
  79. package/dist/lib/pdf.d.ts +11 -0
  80. package/dist/lib/pdf.js +11 -0
  81. package/dist/lib/usage_service.d.ts +2 -1
  82. package/dist/lib/usage_service.js +30 -12
  83. package/dist/lib/worksheet-generation.js +4 -4
  84. package/dist/lib/worksheet-generation.test.js +32 -17
  85. package/dist/lib/workspace-kb.d.ts +5 -0
  86. package/dist/lib/workspace-kb.js +7 -0
  87. package/dist/models/controller-context.model.d.ts +8 -0
  88. package/dist/models/controller-context.model.js +1 -0
  89. package/dist/repositories/artifact.repository.d.ts +60 -0
  90. package/dist/repositories/artifact.repository.js +40 -0
  91. package/dist/repositories/base.repository.d.ts +14 -0
  92. package/dist/repositories/base.repository.js +14 -0
  93. package/dist/repositories/invitation.repository.d.ts +94 -0
  94. package/dist/repositories/invitation.repository.js +44 -0
  95. package/dist/repositories/notification.repository.d.ts +72 -0
  96. package/dist/repositories/notification.repository.js +44 -0
  97. package/dist/repositories/router-module.repository.d.ts +10 -0
  98. package/dist/repositories/router-module.repository.js +14 -0
  99. package/dist/repositories/user.repository.d.ts +74 -0
  100. package/dist/repositories/user.repository.js +37 -0
  101. package/dist/repositories/workspace-member.repository.d.ts +31 -0
  102. package/dist/repositories/workspace-member.repository.js +31 -0
  103. package/dist/repositories/workspace.repository.d.ts +97 -0
  104. package/dist/repositories/workspace.repository.js +79 -0
  105. package/dist/routers/_app.d.ts +528 -33
  106. package/dist/routers/_app.js +4 -0
  107. package/dist/routers/admin.d.ts +0 -4
  108. package/dist/routers/admin.js +21 -549
  109. package/dist/routers/annotations.js +12 -170
  110. package/dist/routers/artifactVersions.d.ts +65 -0
  111. package/dist/routers/artifactVersions.js +14 -0
  112. package/dist/routers/auth.d.ts +0 -6
  113. package/dist/routers/auth.js +36 -421
  114. package/dist/routers/chat.js +15 -229
  115. package/dist/routers/copilot.d.ts +14 -13
  116. package/dist/routers/copilot.js +13 -532
  117. package/dist/routers/flashcards.d.ts +5 -5
  118. package/dist/routers/flashcards.js +23 -349
  119. package/dist/routers/knowledgeBase.d.ts +421 -0
  120. package/dist/routers/knowledgeBase.js +118 -0
  121. package/dist/routers/members.d.ts +0 -41
  122. package/dist/routers/members.js +22 -710
  123. package/dist/routers/notes.d.ts +94 -0
  124. package/dist/routers/notes.js +37 -0
  125. package/dist/routers/notifications.js +7 -109
  126. package/dist/routers/payment.d.ts +3 -2
  127. package/dist/routers/payment.js +11 -393
  128. package/dist/routers/podcast.d.ts +1 -1
  129. package/dist/routers/podcast.js +11 -784
  130. package/dist/routers/studyguide.js +3 -129
  131. package/dist/routers/worksheets.d.ts +29 -14
  132. package/dist/routers/worksheets.js +49 -628
  133. package/dist/routers/workspace.d.ts +0 -4
  134. package/dist/routers/workspace.js +28 -922
  135. package/dist/scripts/purge-deleted-users.js +2 -2
  136. package/dist/server.js +10 -3
  137. package/dist/services/activity/activity-human-description.service.d.ts +13 -0
  138. package/dist/services/activity/activity-human-description.service.js +221 -0
  139. package/dist/services/activity/activity-human-description.service.test.d.ts +1 -0
  140. package/dist/services/activity/activity-human-description.service.test.js +16 -0
  141. package/dist/services/activity/activity-log.service.d.ts +87 -0
  142. package/dist/services/activity/activity-log.service.js +276 -0
  143. package/dist/services/activity/activity-log.service.test.d.ts +1 -0
  144. package/dist/services/activity/activity-log.service.test.js +27 -0
  145. package/dist/services/activity-human-description.service.d.ts +13 -0
  146. package/dist/services/activity-human-description.service.js +221 -0
  147. package/dist/services/activity-human-description.service.test.d.ts +1 -0
  148. package/dist/services/activity-human-description.service.test.js +16 -0
  149. package/dist/services/activity-log.service.d.ts +87 -0
  150. package/dist/services/activity-log.service.js +276 -0
  151. package/dist/services/activity-log.service.test.d.ts +1 -0
  152. package/dist/services/activity-log.service.test.js +27 -0
  153. package/dist/services/admin/admin.service.d.ts +270 -0
  154. package/dist/services/admin/admin.service.js +476 -0
  155. package/dist/services/admin.service.d.ts +270 -0
  156. package/dist/services/admin.service.js +476 -0
  157. package/dist/services/ai/ai-session.service.d.ts +5 -0
  158. package/dist/services/ai/ai-session.service.js +4 -0
  159. package/dist/services/ai-session.service.d.ts +60 -0
  160. package/dist/services/ai-session.service.js +561 -0
  161. package/dist/services/annotation.service.d.ts +177 -0
  162. package/dist/services/annotation.service.js +154 -0
  163. package/dist/services/artifact-notification.service.d.ts +14 -0
  164. package/dist/services/artifact-notification.service.js +20 -0
  165. package/dist/services/artifact-version.service.d.ts +38 -0
  166. package/dist/services/artifact-version.service.js +129 -0
  167. package/dist/services/artifacts/annotation.service.d.ts +177 -0
  168. package/dist/services/artifacts/annotation.service.js +154 -0
  169. package/dist/services/artifacts/artifact-version.service.d.ts +38 -0
  170. package/dist/services/artifacts/artifact-version.service.js +129 -0
  171. package/dist/services/artifacts/chat.service.d.ts +127 -0
  172. package/dist/services/artifacts/chat.service.js +182 -0
  173. package/dist/services/artifacts/study-guide.service.d.ts +18 -0
  174. package/dist/services/artifacts/study-guide.service.js +65 -0
  175. package/dist/services/auth/auth.service.d.ts +94 -0
  176. package/dist/services/auth/auth.service.js +368 -0
  177. package/dist/services/auth.service.d.ts +94 -0
  178. package/dist/services/auth.service.js +368 -0
  179. package/dist/services/base.service.d.ts +14 -0
  180. package/dist/services/base.service.js +14 -0
  181. package/dist/services/billing/payment.service.d.ts +55 -0
  182. package/dist/services/billing/payment.service.js +368 -0
  183. package/dist/services/billing/subscription.service.d.ts +37 -0
  184. package/dist/services/billing/subscription.service.js +654 -0
  185. package/dist/services/billing/usage.service.d.ts +27 -0
  186. package/dist/services/billing/usage.service.js +77 -0
  187. package/dist/services/chat.service.d.ts +127 -0
  188. package/dist/services/chat.service.js +182 -0
  189. package/dist/services/content/copilot.service.d.ts +113 -0
  190. package/dist/services/content/copilot.service.js +453 -0
  191. package/dist/services/content/flashcard-progress.service.d.ts +159 -0
  192. package/dist/services/content/flashcard-progress.service.js +432 -0
  193. package/dist/services/content/flashcard.service.d.ts +140 -0
  194. package/dist/services/content/flashcard.service.js +326 -0
  195. package/dist/services/content/media-analysis.service.d.ts +23 -0
  196. package/dist/services/content/media-analysis.service.js +404 -0
  197. package/dist/services/content/podcast.service.d.ts +267 -0
  198. package/dist/services/content/podcast.service.js +653 -0
  199. package/dist/services/content/worksheet-content.service.d.ts +37 -0
  200. package/dist/services/content/worksheet-content.service.js +84 -0
  201. package/dist/services/content/worksheet-content.service.test.d.ts +1 -0
  202. package/dist/services/content/worksheet-content.service.test.js +69 -0
  203. package/dist/services/content/worksheet-generation.service.d.ts +91 -0
  204. package/dist/services/content/worksheet-generation.service.js +95 -0
  205. package/dist/services/content/worksheet-generation.service.test.d.ts +1 -0
  206. package/dist/services/content/worksheet-generation.service.test.js +20 -0
  207. package/dist/services/content/worksheet.service.d.ts +347 -0
  208. package/dist/services/content/worksheet.service.js +599 -0
  209. package/dist/services/copilot.service.d.ts +116 -0
  210. package/dist/services/copilot.service.js +447 -0
  211. package/dist/services/flashcard-progress.service.d.ts +2 -2
  212. package/dist/services/flashcard-progress.service.js +3 -2
  213. package/dist/services/flashcard.service.d.ts +140 -0
  214. package/dist/services/flashcard.service.js +325 -0
  215. package/dist/services/invitation.service.d.ts +66 -0
  216. package/dist/services/invitation.service.js +348 -0
  217. package/dist/services/knowledge/knowledge-base.service.d.ts +316 -0
  218. package/dist/services/knowledge/knowledge-base.service.js +544 -0
  219. package/dist/services/knowledge-base.service.d.ts +316 -0
  220. package/dist/services/knowledge-base.service.js +536 -0
  221. package/dist/services/media-analysis.service.d.ts +23 -0
  222. package/dist/services/media-analysis.service.js +384 -0
  223. package/dist/services/member.service.d.ts +36 -0
  224. package/dist/services/member.service.js +193 -0
  225. package/dist/services/members/invitation.service.d.ts +66 -0
  226. package/dist/services/members/invitation.service.js +348 -0
  227. package/dist/services/members/member.service.d.ts +36 -0
  228. package/dist/services/members/member.service.js +193 -0
  229. package/dist/services/note.service.d.ts +55 -0
  230. package/dist/services/note.service.js +111 -0
  231. package/dist/services/notification.service.d.ts +214 -0
  232. package/dist/services/notification.service.js +550 -0
  233. package/dist/services/notification.service.test.d.ts +1 -0
  234. package/dist/services/notification.service.test.js +87 -0
  235. package/dist/services/notifications/notification.service.d.ts +214 -0
  236. package/dist/services/notifications/notification.service.js +550 -0
  237. package/dist/services/notifications/notification.service.test.d.ts +1 -0
  238. package/dist/services/notifications/notification.service.test.js +87 -0
  239. package/dist/services/payment.service.d.ts +55 -0
  240. package/dist/services/payment.service.js +368 -0
  241. package/dist/services/podcast.service.d.ts +267 -0
  242. package/dist/services/podcast.service.js +654 -0
  243. package/dist/services/router-module.service.d.ts +7 -0
  244. package/dist/services/router-module.service.js +10 -0
  245. package/dist/services/study-guide.service.d.ts +18 -0
  246. package/dist/services/study-guide.service.js +65 -0
  247. package/dist/services/subscription.service.d.ts +37 -0
  248. package/dist/services/subscription.service.js +654 -0
  249. package/dist/services/usage-limit-policy.service.d.ts +12 -0
  250. package/dist/services/usage-limit-policy.service.js +22 -0
  251. package/dist/services/usage-limit-policy.service.test.d.ts +1 -0
  252. package/dist/services/usage-limit-policy.service.test.js +46 -0
  253. package/dist/services/usage.service.d.ts +27 -0
  254. package/dist/services/usage.service.js +77 -0
  255. package/dist/services/worksheet-content.service.d.ts +42 -0
  256. package/dist/services/worksheet-content.service.js +84 -0
  257. package/dist/services/worksheet-content.service.test.d.ts +1 -0
  258. package/dist/services/worksheet-content.service.test.js +69 -0
  259. package/dist/services/worksheet-generation.service.d.ts +91 -0
  260. package/dist/services/worksheet-generation.service.js +95 -0
  261. package/dist/services/worksheet-generation.service.test.d.ts +1 -0
  262. package/dist/services/worksheet-generation.service.test.js +20 -0
  263. package/dist/services/worksheet.service.d.ts +385 -0
  264. package/dist/services/worksheet.service.js +596 -0
  265. package/dist/services/workspace/workspace-analytics.service.d.ts +24 -0
  266. package/dist/services/workspace/workspace-analytics.service.js +95 -0
  267. package/dist/services/workspace/workspace-kb.service.d.ts +40 -0
  268. package/dist/services/workspace/workspace-kb.service.js +184 -0
  269. package/dist/services/workspace/workspace.service.d.ts +307 -0
  270. package/dist/services/workspace/workspace.service.js +394 -0
  271. package/dist/services/workspace-analytics.service.d.ts +24 -0
  272. package/dist/services/workspace-analytics.service.js +95 -0
  273. package/dist/services/workspace-kb.service.d.ts +40 -0
  274. package/dist/services/workspace-kb.service.js +184 -0
  275. package/dist/services/workspace-progress.service.d.ts +27 -0
  276. package/dist/services/workspace-progress.service.js +56 -0
  277. package/dist/services/workspace-progress.service.test.d.ts +1 -0
  278. package/dist/services/workspace-progress.service.test.js +49 -0
  279. package/dist/services/workspace.service.d.ts +307 -0
  280. package/dist/services/workspace.service.js +390 -0
  281. package/dist/trpc.js +2 -2
  282. package/package.json +5 -6
  283. package/prisma/migrations/20260509000001_add_knowledge_base/migration.sql +99 -0
  284. package/prisma/migrations/20260509000002_curate_knowledge_base/migration.sql +52 -0
  285. package/prisma/migrations/20260522000000_add_notes/migration.sql +27 -0
  286. package/prisma/migrations/20260524000000_remove_notes/migration.sql +3 -0
  287. package/prisma/schema.prisma +150 -48
  288. package/prisma/seed.mjs +67 -0
  289. package/scripts/debug/README.md +4 -0
  290. package/src/README.md +63 -0
  291. package/src/lib/ai/config.ts +34 -0
  292. package/src/lib/ai/embedding-client.ts +47 -0
  293. package/src/lib/ai/index.ts +62 -0
  294. package/src/lib/ai/inference-backend/client.ts +479 -0
  295. package/src/lib/ai/inference-backend/mocks.ts +171 -0
  296. package/src/lib/ai/inference-backend/types.ts +50 -0
  297. package/src/lib/ai/json-parse.ts +35 -0
  298. package/src/lib/ai/llm-client.ts +31 -0
  299. package/src/lib/ai/mock.ts +12 -0
  300. package/src/lib/ai/types.ts +11 -0
  301. package/src/lib/chunking.ts +81 -0
  302. package/src/lib/curated-kb-seed.ts +164 -0
  303. package/src/lib/email.ts +77 -115
  304. package/src/lib/embeddings.ts +9 -0
  305. package/src/lib/ensure-curated-kb-catalog.ts +60 -0
  306. package/src/lib/env.ts +2 -7
  307. package/src/lib/inference.ts +1 -21
  308. package/src/lib/kb-meta.ts +81 -0
  309. package/src/lib/pdf.ts +23 -0
  310. package/src/lib/workspace-kb.ts +7 -0
  311. package/src/repositories/artifact.repository.ts +55 -0
  312. package/src/repositories/base.repository.ts +19 -0
  313. package/src/repositories/invitation.repository.ts +53 -0
  314. package/src/repositories/notification.repository.ts +53 -0
  315. package/src/repositories/user.repository.ts +44 -0
  316. package/src/repositories/workspace-member.repository.ts +38 -0
  317. package/src/repositories/workspace.repository.ts +89 -0
  318. package/src/routers/_app.ts +4 -0
  319. package/src/routers/admin.ts +124 -692
  320. package/src/routers/annotations.ts +25 -203
  321. package/src/routers/artifactVersions.ts +32 -0
  322. package/src/routers/auth.ts +81 -519
  323. package/src/routers/chat.ts +42 -245
  324. package/src/routers/copilot.ts +41 -666
  325. package/src/routers/flashcards.ts +108 -404
  326. package/src/routers/knowledgeBase.ts +216 -0
  327. package/src/routers/members.ts +60 -782
  328. package/src/routers/notifications.ts +15 -117
  329. package/src/routers/payment.ts +37 -446
  330. package/src/routers/podcast.ts +36 -898
  331. package/src/routers/studyguide.ts +5 -144
  332. package/src/routers/worksheets.ts +171 -735
  333. package/src/routers/workspace.ts +138 -1109
  334. package/src/scripts/purge-deleted-users.ts +2 -2
  335. package/src/server.ts +10 -3
  336. package/src/{lib/activity_human_description.test.ts → services/activity/activity-human-description.service.test.ts} +1 -1
  337. package/src/{lib/activity_log_service.test.ts → services/activity/activity-log.service.test.ts} +1 -1
  338. package/src/{lib/activity_log_service.ts → services/activity/activity-log.service.ts} +2 -2
  339. package/src/services/admin/admin.service.ts +612 -0
  340. package/src/services/ai/ai-session.service.ts +5 -0
  341. package/src/services/artifacts/annotation.service.ts +189 -0
  342. package/src/services/artifacts/artifact-version.service.ts +151 -0
  343. package/src/services/artifacts/chat.service.ts +197 -0
  344. package/src/services/artifacts/study-guide.service.ts +72 -0
  345. package/src/services/auth/auth.service.ts +473 -0
  346. package/src/services/base.service.ts +19 -0
  347. package/src/services/billing/payment.service.ts +436 -0
  348. package/src/{lib/subscription_service.ts → services/billing/subscription.service.ts} +5 -5
  349. package/src/{lib/usage_service.ts → services/billing/usage.service.ts} +32 -12
  350. package/src/services/content/copilot.service.ts +596 -0
  351. package/src/services/{flashcard-progress.service.ts → content/flashcard-progress.service.ts} +6 -3
  352. package/src/services/content/flashcard.service.ts +394 -0
  353. package/src/services/content/media-analysis.service.ts +556 -0
  354. package/src/services/content/podcast.service.ts +777 -0
  355. package/src/services/content/worksheet-content.service.test.ts +83 -0
  356. package/src/services/content/worksheet-content.service.ts +117 -0
  357. package/src/{lib/worksheet-generation.test.ts → services/content/worksheet-generation.service.test.ts} +1 -1
  358. package/src/services/content/worksheet.service.ts +751 -0
  359. package/src/services/knowledge/knowledge-base.service.ts +705 -0
  360. package/src/services/members/invitation.service.ts +427 -0
  361. package/src/services/members/member.service.ts +241 -0
  362. package/src/{lib/notification-service.test.ts → services/notifications/notification.service.test.ts} +2 -2
  363. package/src/{lib/notification-service.ts → services/notifications/notification.service.ts} +102 -1
  364. package/src/services/workspace/workspace-analytics.service.ts +107 -0
  365. package/src/services/workspace/workspace-kb.service.ts +273 -0
  366. package/src/services/workspace/workspace.service.ts +481 -0
  367. package/src/trpc.ts +2 -2
  368. package/src/lib/ai-session.ts +0 -704
  369. package/src/lib/workspace-access.ts +0 -13
  370. /package/{check-difficulty.cjs → scripts/debug/check-difficulty.cjs} +0 -0
  371. /package/{check-questions.cjs → scripts/debug/check-questions.cjs} +0 -0
  372. /package/{db-summary.cjs → scripts/debug/db-summary.cjs} +0 -0
  373. /package/{mcq-test.cjs → scripts/debug/mcq-test.cjs} +0 -0
  374. /package/{test-generate.js → scripts/debug/test-generate.js} +0 -0
  375. /package/{test-ratio.cjs → scripts/debug/test-ratio.cjs} +0 -0
  376. /package/{zod-test.cjs → scripts/debug/zod-test.cjs} +0 -0
  377. /package/src/{lib/activity_human_description.ts → services/activity/activity-human-description.service.ts} +0 -0
  378. /package/src/{lib/worksheet-generation.ts → services/content/worksheet-generation.service.ts} +0 -0
@@ -0,0 +1,81 @@
1
+ import { CURATED_KB_SEEDS, type CuratedKbSeed } from './curated-kb-seed.js';
2
+
3
+ export type KbMetaRecord = {
4
+ slug?: string;
5
+ category?: string;
6
+ subject?: string;
7
+ kind?: string;
8
+ };
9
+
10
+ const CURATED_BY_NAME = new Map<string, CuratedKbSeed>(
11
+ CURATED_KB_SEEDS.map((seed) => [seed.name.trim().toLowerCase(), seed]),
12
+ );
13
+
14
+ function inferSubject(name: string): string | undefined {
15
+ const lower = name.toLowerCase();
16
+ if (lower.includes('biology') || /\bbio\b/.test(lower)) return 'biology';
17
+ if (lower.includes('chemistry') || /\bchem\b/.test(lower)) return 'chemistry';
18
+ if (lower.includes('physics')) return 'physics';
19
+ if (lower.includes('calculus')) return 'calculus';
20
+ if (lower.includes('statistics') || lower.includes('stats')) return 'math';
21
+ if (lower.includes('math') || lower.includes('algebra') || lower.includes('geometry')) {
22
+ return 'math';
23
+ }
24
+ if (lower.includes('literature') || lower.includes('literary')) return 'literature';
25
+ if (lower.includes('english') || lower.includes('writing') || lower.includes('rhetoric')) {
26
+ return 'english';
27
+ }
28
+ if (lower.includes('history') || lower.includes('historical')) return 'history';
29
+ if (lower.includes('psychology') || lower.includes('psych')) return 'psychology';
30
+ if (lower.includes('economics') || lower.includes('econ')) return 'economics';
31
+ if (lower.includes('environmental') || lower.includes('ecology')) return 'environmental';
32
+ if (lower.includes('computer') || lower.includes('programming') || lower.includes('cs ')) {
33
+ return 'science';
34
+ }
35
+ if (lower.includes('government') || lower.includes('politics')) return 'history';
36
+ return undefined;
37
+ }
38
+
39
+ function inferCategory(name: string, category?: string): 'AP' | 'IB' | 'General' {
40
+ if (category === 'AP' || category === 'IB') return category;
41
+ const lower = name.toLowerCase();
42
+ if (lower.startsWith('ap ') || lower.includes(' ap ') || lower.includes('advanced placement')) {
43
+ return 'AP';
44
+ }
45
+ if (lower.startsWith('ib ') || lower.includes(' ib ') || lower.includes('baccalaureate')) {
46
+ return 'IB';
47
+ }
48
+ return 'General';
49
+ }
50
+
51
+ function slugify(name: string): string {
52
+ return name
53
+ .toLowerCase()
54
+ .replace(/[^a-z0-9]+/g, '-')
55
+ .replace(/^-+|-+$/g, '')
56
+ .slice(0, 80);
57
+ }
58
+
59
+ /** Build catalog meta for new KBs so clients can assign icons and banner colors. */
60
+ export function buildKbMetaFromName(name: string, existing?: KbMetaRecord | null): KbMetaRecord {
61
+ const trimmed = name.trim();
62
+ const curated = CURATED_BY_NAME.get(trimmed.toLowerCase());
63
+ if (curated) {
64
+ return {
65
+ slug: curated.slug,
66
+ category: curated.category,
67
+ subject: curated.subject,
68
+ };
69
+ }
70
+
71
+ const subject = existing?.subject ?? inferSubject(trimmed);
72
+ const category = inferCategory(trimmed, existing?.category);
73
+ const slug = existing?.slug ?? (subject ? `${slugify(trimmed)}-${subject}` : slugify(trimmed));
74
+
75
+ return {
76
+ slug: slug || undefined,
77
+ category: category === 'General' ? undefined : category,
78
+ subject,
79
+ ...(existing?.kind ? { kind: existing.kind } : {}),
80
+ };
81
+ }
package/src/lib/pdf.ts ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Thin wrapper around `pdf-parse` that returns plain text + page count.
3
+ *
4
+ * pdf-parse is loaded lazily and via a deep import to avoid the package's
5
+ * top-level "test" code that runs when the module index is loaded directly.
6
+ */
7
+ export interface ExtractedPdf {
8
+ text: string;
9
+ numPages: number;
10
+ }
11
+
12
+ export async function extractPdfText(buffer: Buffer): Promise<ExtractedPdf> {
13
+ // Deep import skips pdf-parse's top-level demo block (`if (!module.parent)`).
14
+ // @ts-ignore - no types ship for the deep file
15
+ const mod = await import('pdf-parse/lib/pdf-parse.js');
16
+ const pdfParse: (b: Buffer) => Promise<{ text: string; numpages: number }> =
17
+ (mod as any).default ?? (mod as any);
18
+ const data = await pdfParse(buffer);
19
+ return {
20
+ text: data.text ?? '',
21
+ numPages: data.numpages ?? 0,
22
+ };
23
+ }
@@ -0,0 +1,7 @@
1
+ /** Meta.kind value for the private, auto-managed KB attached to each workspace. */
2
+ export const WORKSPACE_KB_KIND = 'workspace';
3
+
4
+ export function isWorkspaceManagedKb(kb: { meta: unknown }): boolean {
5
+ if (!kb.meta || typeof kb.meta !== 'object') return false;
6
+ return (kb.meta as Record<string, unknown>).kind === WORKSPACE_KB_KIND;
7
+ }
@@ -0,0 +1,55 @@
1
+ import type { ArtifactType, Prisma, PrismaClient } from '@prisma/client';
2
+ import { BaseRepository } from './base.repository.js';
3
+ import { workspaceAccessWhere } from './workspace.repository.js';
4
+
5
+ export class ArtifactRepository extends BaseRepository {
6
+ constructor(db: PrismaClient) {
7
+ super(db);
8
+ }
9
+
10
+ /**
11
+ * Fetch an artifact if the user can access the containing workspace
12
+ * (owner or member).
13
+ */
14
+ findByIdAccessible(artifactId: string, userId: string, include?: Prisma.ArtifactInclude) {
15
+ return this.db.artifact.findFirst({
16
+ where: {
17
+ id: artifactId,
18
+ workspace: workspaceAccessWhere(userId),
19
+ },
20
+ include,
21
+ });
22
+ }
23
+
24
+ findByIdAndTypeAccessible(
25
+ artifactId: string,
26
+ type: ArtifactType,
27
+ userId: string,
28
+ include?: Prisma.ArtifactInclude,
29
+ ) {
30
+ return this.db.artifact.findFirst({
31
+ where: {
32
+ id: artifactId,
33
+ type,
34
+ workspace: workspaceAccessWhere(userId),
35
+ },
36
+ include,
37
+ });
38
+ }
39
+
40
+ listByWorkspaceAndType(
41
+ workspaceId: string,
42
+ type: ArtifactType,
43
+ userId: string,
44
+ args?: Omit<Prisma.ArtifactFindManyArgs, 'where'>,
45
+ ) {
46
+ return this.db.artifact.findMany({
47
+ ...args,
48
+ where: {
49
+ workspaceId,
50
+ type,
51
+ workspace: workspaceAccessWhere(userId),
52
+ },
53
+ });
54
+ }
55
+ }
@@ -0,0 +1,19 @@
1
+ import type { PrismaClient } from '@prisma/client';
2
+ import { logger } from '../lib/logger.js';
3
+
4
+ /**
5
+ * Shared base class for repositories.
6
+ *
7
+ * Repositories own data access. They wrap a Prisma client and expose
8
+ * intent-revealing methods (e.g. `findAccessibleById(workspaceId, userId)`)
9
+ * so that the shape of `where` clauses doesn't leak into services/routers.
10
+ */
11
+ export abstract class BaseRepository {
12
+ protected readonly db: PrismaClient;
13
+ protected readonly logger: typeof logger;
14
+
15
+ constructor(db: PrismaClient) {
16
+ this.db = db;
17
+ this.logger = logger;
18
+ }
19
+ }
@@ -0,0 +1,53 @@
1
+ import type { Prisma, PrismaClient } from '@prisma/client';
2
+ import { BaseRepository } from './base.repository.js';
3
+
4
+ /**
5
+ * Data access for `WorkspaceInvitation`. Members router currently performs
6
+ * invitation CRUD + token validation directly against Prisma — this
7
+ * repository is the target of that extraction during Phase 4.
8
+ */
9
+ export class InvitationRepository extends BaseRepository {
10
+ constructor(db: PrismaClient) {
11
+ super(db);
12
+ }
13
+
14
+ findById(id: string, include?: Prisma.WorkspaceInvitationInclude) {
15
+ return this.db.workspaceInvitation.findFirst({
16
+ where: { id },
17
+ include,
18
+ });
19
+ }
20
+
21
+ findFirst(args: Prisma.WorkspaceInvitationFindFirstArgs) {
22
+ return this.db.workspaceInvitation.findFirst(args);
23
+ }
24
+
25
+ listByWorkspace(workspaceId: string, args?: Omit<Prisma.WorkspaceInvitationFindManyArgs, 'where'>) {
26
+ return this.db.workspaceInvitation.findMany({
27
+ ...args,
28
+ where: { workspaceId },
29
+ });
30
+ }
31
+
32
+ listForUserEmail(email: string, args?: Omit<Prisma.WorkspaceInvitationFindManyArgs, 'where'>) {
33
+ return this.db.workspaceInvitation.findMany({
34
+ ...args,
35
+ where: { email },
36
+ });
37
+ }
38
+
39
+ create(data: Prisma.WorkspaceInvitationCreateInput) {
40
+ return this.db.workspaceInvitation.create({ data });
41
+ }
42
+
43
+ update(id: string, data: Prisma.WorkspaceInvitationUpdateInput) {
44
+ return this.db.workspaceInvitation.update({
45
+ where: { id },
46
+ data,
47
+ });
48
+ }
49
+
50
+ delete(id: string) {
51
+ return this.db.workspaceInvitation.delete({ where: { id } });
52
+ }
53
+ }
@@ -0,0 +1,53 @@
1
+ import type { Prisma, PrismaClient } from '@prisma/client';
2
+ import { BaseRepository } from './base.repository.js';
3
+
4
+ /**
5
+ * Thin data-access wrapper around `Notification`. `NotificationService`
6
+ * currently calls `ctx.db.notification.*` directly; Phase 4 will migrate it
7
+ * to use this repository so services don't need Prisma-specific types at
8
+ * their API boundary.
9
+ */
10
+ export class NotificationRepository extends BaseRepository {
11
+ constructor(db: PrismaClient) {
12
+ super(db);
13
+ }
14
+
15
+ findFirst(args: Prisma.NotificationFindFirstArgs) {
16
+ return this.db.notification.findFirst(args);
17
+ }
18
+
19
+ listByUser(userId: string, args?: Omit<Prisma.NotificationFindManyArgs, 'where'>) {
20
+ return this.db.notification.findMany({
21
+ ...args,
22
+ where: { userId },
23
+ });
24
+ }
25
+
26
+ count(args: Prisma.NotificationCountArgs) {
27
+ return this.db.notification.count(args);
28
+ }
29
+
30
+ create(data: Prisma.NotificationCreateInput) {
31
+ return this.db.notification.create({ data });
32
+ }
33
+
34
+ markRead(id: string, userId: string) {
35
+ return this.db.notification.updateMany({
36
+ where: { id, userId },
37
+ data: { read: true },
38
+ });
39
+ }
40
+
41
+ markAllRead(userId: string) {
42
+ return this.db.notification.updateMany({
43
+ where: { userId, read: false },
44
+ data: { read: true },
45
+ });
46
+ }
47
+
48
+ delete(id: string, userId: string) {
49
+ return this.db.notification.deleteMany({
50
+ where: { id, userId },
51
+ });
52
+ }
53
+ }
@@ -0,0 +1,44 @@
1
+ import type { Prisma, PrismaClient } from '@prisma/client';
2
+ import { BaseRepository } from './base.repository.js';
3
+
4
+ export class UserRepository extends BaseRepository {
5
+ constructor(db: PrismaClient) {
6
+ super(db);
7
+ }
8
+
9
+ findById(id: string, args?: Omit<Prisma.UserFindUniqueArgs, 'where'>) {
10
+ return this.db.user.findUnique({
11
+ ...args,
12
+ where: { id },
13
+ });
14
+ }
15
+
16
+ findByEmail(email: string, args?: Omit<Prisma.UserFindUniqueArgs, 'where'>) {
17
+ return this.db.user.findUnique({
18
+ ...args,
19
+ where: { email },
20
+ });
21
+ }
22
+
23
+ create(data: Prisma.UserCreateInput) {
24
+ return this.db.user.create({ data });
25
+ }
26
+
27
+ update(id: string, data: Prisma.UserUpdateInput) {
28
+ return this.db.user.update({
29
+ where: { id },
30
+ data,
31
+ });
32
+ }
33
+
34
+ /**
35
+ * Soft-delete marker: set `deletedAt`. Hard-delete happens in
36
+ * `scripts/purge-deleted-users.ts`.
37
+ */
38
+ softDelete(id: string) {
39
+ return this.db.user.update({
40
+ where: { id },
41
+ data: { deletedAt: new Date() },
42
+ });
43
+ }
44
+ }
@@ -0,0 +1,38 @@
1
+ import type { Prisma, PrismaClient } from '@prisma/client';
2
+ import { BaseRepository } from './base.repository.js';
3
+
4
+ export class WorkspaceMemberRepository extends BaseRepository {
5
+ constructor(db: PrismaClient) {
6
+ super(db);
7
+ }
8
+
9
+ findByWorkspaceAndUser(workspaceId: string, userId: string) {
10
+ return this.db.workspaceMember.findFirst({
11
+ where: { workspaceId, userId },
12
+ });
13
+ }
14
+
15
+ listByWorkspace(workspaceId: string, include?: Prisma.WorkspaceMemberInclude) {
16
+ return this.db.workspaceMember.findMany({
17
+ where: { workspaceId },
18
+ include,
19
+ });
20
+ }
21
+
22
+ create(data: Prisma.WorkspaceMemberCreateInput) {
23
+ return this.db.workspaceMember.create({ data });
24
+ }
25
+
26
+ delete(workspaceId: string, userId: string) {
27
+ return this.db.workspaceMember.deleteMany({
28
+ where: { workspaceId, userId },
29
+ });
30
+ }
31
+
32
+ updateRole(workspaceId: string, userId: string, role: string) {
33
+ return this.db.workspaceMember.updateMany({
34
+ where: { workspaceId, userId },
35
+ data: { role },
36
+ });
37
+ }
38
+ }
@@ -0,0 +1,89 @@
1
+ import type { Prisma, PrismaClient } from '@prisma/client';
2
+ import { BaseRepository } from './base.repository.js';
3
+
4
+ /**
5
+ * Prisma `where` fragment: workspace is accessible to the user if they are
6
+ * the owner OR a workspace member. Prefer this over ad-hoc `{ ownerId }`
7
+ * checks to keep collaborative-workspace behavior consistent.
8
+ *
9
+ * NOTE: This is the canonical replacement for the former
10
+ * `lib/workspace-access.ts#workspaceAccessFilter`. Call sites that previously
11
+ * spread the filter into a larger `where` can still do so.
12
+ */
13
+ export function workspaceAccessWhere(userId: string): Prisma.WorkspaceWhereInput {
14
+ return {
15
+ OR: [
16
+ { ownerId: userId },
17
+ { members: { some: { userId } } },
18
+ ],
19
+ };
20
+ }
21
+
22
+ /**
23
+ * Prisma `where` fragment for owner-only access. Some legacy call sites
24
+ * (e.g. `workspace.list`, `workspace.create`, some `workspace.getTree`
25
+ * paths) intentionally use owner-only semantics. Keep a separate helper so
26
+ * the difference is explicit at the call site.
27
+ */
28
+ export function workspaceOwnerWhere(userId: string): Prisma.WorkspaceWhereInput {
29
+ return { ownerId: userId };
30
+ }
31
+
32
+ export class WorkspaceRepository extends BaseRepository {
33
+ constructor(db: PrismaClient) {
34
+ super(db);
35
+ }
36
+
37
+ /**
38
+ * Fetch a workspace if the user is the owner OR a member.
39
+ * Preserves the member-inclusive behavior used by most read paths.
40
+ */
41
+ findByIdAccessible(workspaceId: string, userId: string) {
42
+ return this.db.workspace.findFirst({
43
+ where: {
44
+ id: workspaceId,
45
+ ...workspaceAccessWhere(userId),
46
+ },
47
+ });
48
+ }
49
+
50
+ /**
51
+ * Fetch a workspace only if the user owns it. Preserves the owner-only
52
+ * semantics used today by `workspace.list`, `workspace.create`, and some
53
+ * management paths.
54
+ */
55
+ findByIdOwned(workspaceId: string, userId: string) {
56
+ return this.db.workspace.findFirst({
57
+ where: {
58
+ id: workspaceId,
59
+ ownerId: userId,
60
+ },
61
+ });
62
+ }
63
+
64
+ listAccessible(userId: string, args?: Omit<Prisma.WorkspaceFindManyArgs, 'where'>) {
65
+ return this.db.workspace.findMany({
66
+ ...args,
67
+ where: workspaceAccessWhere(userId),
68
+ });
69
+ }
70
+
71
+ listOwned(userId: string, args?: Omit<Prisma.WorkspaceFindManyArgs, 'where'>) {
72
+ return this.db.workspace.findMany({
73
+ ...args,
74
+ where: { ownerId: userId },
75
+ });
76
+ }
77
+
78
+ /**
79
+ * Escape hatch for services that need to splice the access clause into a
80
+ * larger query (e.g. `artifact.findFirst({ where: { ..., workspace: ... } })`).
81
+ */
82
+ static accessibleWhere(userId: string): Prisma.WorkspaceWhereInput {
83
+ return workspaceAccessWhere(userId);
84
+ }
85
+
86
+ static ownedWhere(userId: string): Prisma.WorkspaceWhereInput {
87
+ return workspaceOwnerWhere(userId);
88
+ }
89
+ }
@@ -14,6 +14,8 @@ import { admin } from './admin.js';
14
14
  import { paymentRouter } from './payment.js';
15
15
  import { copilot } from './copilot.js';
16
16
  import { notifications } from './notifications.js';
17
+ import { knowledgeBase } from './knowledgeBase.js';
18
+ import { artifactVersions } from './artifactVersions.js';
17
19
 
18
20
  export const appRouter = router({
19
21
  auth,
@@ -28,6 +30,8 @@ export const appRouter = router({
28
30
  payment: paymentRouter,
29
31
  copilot,
30
32
  notifications,
33
+ knowledgeBase,
34
+ artifactVersions,
31
35
  // Public member endpoints (for invitation acceptance)
32
36
  member: router({
33
37
  acceptInvite: members.acceptInvite,