@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,21 +1 @@
1
- import OpenAI from 'openai';
2
-
3
- const openai = new OpenAI({
4
- apiKey: process.env.INFERENCE_API_KEY,
5
- baseURL: process.env.INFERENCE_BASE_URL,
6
- });
7
-
8
- async function inference(messages: { role: 'system' | 'user' | 'assistant', content: string }[]) {
9
- try {
10
- const response = await openai.chat.completions.create({
11
- model: "command-a-03-2025",
12
- messages: messages,
13
- });
14
- return response;
15
- } catch (error) {
16
- // Inference error logged at call site
17
- throw error;
18
- }
19
- }
20
-
21
- export default inference;
1
+ export { complete as default, complete, completeText } from './ai/llm-client.js';
@@ -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,