@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
package/dist/lib/email.js CHANGED
@@ -1,20 +1,34 @@
1
- import nodemailer from 'nodemailer';
1
+ import { Resend } from 'resend';
2
2
  import { logger } from './logger.js';
3
3
  import { env } from './env.js';
4
- // Commented out Resend flow as requested
5
- // import { Resend } from 'resend';
6
- // const resend = env.RESEND_API_KEY ? new Resend(env.RESEND_API_KEY) : null;
7
- const transporter = nodemailer.createTransport({
8
- host: env.SMTP_HOST,
9
- port: env.SMTP_PORT,
10
- secure: env.SMTP_SECURE,
11
- auth: {
12
- user: env.SMTP_USER,
13
- pass: env.SMTP_PASSWORD,
14
- },
15
- });
4
+ const resend = env.RESEND_API_KEY ? new Resend(env.RESEND_API_KEY) : null;
16
5
  const FROM_EMAIL = env.EMAIL_FROM;
17
6
  const APP_URL = env.FRONTEND_URL;
7
+ async function sendEmail(options) {
8
+ try {
9
+ if (!resend) {
10
+ logger.warn(`${options.missingConfigLog} Logging instead:`);
11
+ logger.info(options.devLogDetail);
12
+ return true;
13
+ }
14
+ const { data, error } = await resend.emails.send({
15
+ from: FROM_EMAIL,
16
+ to: options.to,
17
+ subject: options.subject,
18
+ html: options.html,
19
+ });
20
+ if (error) {
21
+ logger.error('Email send error:', error);
22
+ return false;
23
+ }
24
+ logger.info(options.successLog + (data?.id ? ` (id: ${data.id})` : ''));
25
+ return true;
26
+ }
27
+ catch (err) {
28
+ logger.error('Email send error:', err);
29
+ return false;
30
+ }
31
+ }
18
32
  export async function sendVerificationEmail(email, token, name) {
19
33
  const verifyUrl = `${APP_URL}/verify-email?token=${token}`;
20
34
  const greeting = name ? `, ${name}` : '';
@@ -31,25 +45,14 @@ export async function sendVerificationEmail(email, token, name) {
31
45
  </p>
32
46
  </div>
33
47
  `;
34
- try {
35
- if (!env.SMTP_HOST) {
36
- logger.warn('Email service not configured (SMTP_HOST missing). Logging email content instead:');
37
- logger.info(`Verification Email to ${email}: ${verifyUrl}`);
38
- return true;
39
- }
40
- await transporter.sendMail({
41
- from: FROM_EMAIL,
42
- to: email,
43
- subject: 'Verify your email - Scribe',
44
- html,
45
- });
46
- logger.info(`Verification email sent to ${email}`);
47
- return true;
48
- }
49
- catch (err) {
50
- logger.error('Email send error:', err);
51
- return false;
52
- }
48
+ return sendEmail({
49
+ to: email,
50
+ subject: 'Verify your email - Scribe',
51
+ html,
52
+ successLog: `Verification email sent to ${email}`,
53
+ missingConfigLog: 'Email service not configured (RESEND_API_KEY missing).',
54
+ devLogDetail: `Verification Email to ${email}: ${verifyUrl}`,
55
+ });
53
56
  }
54
57
  export async function sendInvitationEmail(invitation) {
55
58
  const inviteUrl = `${APP_URL}/accept-invite?token=${invitation.token}`;
@@ -68,25 +71,14 @@ export async function sendInvitationEmail(invitation) {
68
71
  </p>
69
72
  </div>
70
73
  `;
71
- try {
72
- if (!env.SMTP_HOST) {
73
- logger.warn('Email service not configured (SMTP_HOST missing). Logging invitation link instead:');
74
- logger.info(`Invitation Link for ${invitation.email}: ${inviteUrl}`);
75
- return true;
76
- }
77
- await transporter.sendMail({
78
- from: FROM_EMAIL,
79
- to: invitation.email,
80
- subject: `Invitation to join ${invitation.workspaceTitle} on Scribe`,
81
- html,
82
- });
83
- logger.info(`Invitation email sent to ${invitation.email}`);
84
- return true;
85
- }
86
- catch (err) {
87
- logger.error('Email send error:', err);
88
- return false;
89
- }
74
+ return sendEmail({
75
+ to: invitation.email,
76
+ subject: `Invitation to join ${invitation.workspaceTitle} on Scribe`,
77
+ html,
78
+ successLog: `Invitation email sent to ${invitation.email}`,
79
+ missingConfigLog: 'Email service not configured (RESEND_API_KEY missing).',
80
+ devLogDetail: `Invitation Link for ${invitation.email}: ${inviteUrl}`,
81
+ });
90
82
  }
91
83
  export async function sendAccountDeletionScheduledEmail(email, token) {
92
84
  const restoreUrl = `${APP_URL}/restore-account?token=${token}`;
@@ -105,25 +97,14 @@ export async function sendAccountDeletionScheduledEmail(email, token) {
105
97
  </p>
106
98
  </div>
107
99
  `;
108
- try {
109
- if (!env.SMTP_HOST) {
110
- logger.warn('Email service not configured (SMTP_HOST missing). Logging email content instead:');
111
- logger.info(`Account Deletion Scheduled Email to ${email}: ${restoreUrl}`);
112
- return true;
113
- }
114
- await transporter.sendMail({
115
- from: FROM_EMAIL,
116
- to: email,
117
- subject: 'Account Deletion Scheduled - Scribe',
118
- html,
119
- });
120
- logger.info(`Account deletion scheduled email sent to ${email}`);
121
- return true;
122
- }
123
- catch (err) {
124
- logger.error('Email send error:', err);
125
- return false;
126
- }
100
+ return sendEmail({
101
+ to: email,
102
+ subject: 'Account Deletion Scheduled - Scribe',
103
+ html,
104
+ successLog: `Account deletion scheduled email sent to ${email}`,
105
+ missingConfigLog: 'Email service not configured (RESEND_API_KEY missing).',
106
+ devLogDetail: `Account Deletion Scheduled Email to ${email}: ${restoreUrl}`,
107
+ });
127
108
  }
128
109
  export async function sendPasswordResetEmail(email, token, name) {
129
110
  const resetUrl = `${APP_URL}/reset-password?token=${encodeURIComponent(token)}`;
@@ -140,25 +121,14 @@ export async function sendPasswordResetEmail(email, token, name) {
140
121
  </p>
141
122
  </div>
142
123
  `;
143
- try {
144
- if (!env.SMTP_HOST) {
145
- logger.warn('Email service not configured (SMTP_HOST missing). Logging reset link instead:');
146
- logger.info(`Password reset for ${email}: ${resetUrl}`);
147
- return true;
148
- }
149
- await transporter.sendMail({
150
- from: FROM_EMAIL,
151
- to: email,
152
- subject: 'Reset your password - Scribe',
153
- html,
154
- });
155
- logger.info(`Password reset email sent to ${email}`);
156
- return true;
157
- }
158
- catch (err) {
159
- logger.error('Email send error:', err);
160
- return false;
161
- }
124
+ return sendEmail({
125
+ to: email,
126
+ subject: 'Reset your password - Scribe',
127
+ html,
128
+ successLog: `Password reset email sent to ${email}`,
129
+ missingConfigLog: 'Email service not configured (RESEND_API_KEY missing).',
130
+ devLogDetail: `Password reset for ${email}: ${resetUrl}`,
131
+ });
162
132
  }
163
133
  export async function sendAccountRestoredEmail(email) {
164
134
  const loginUrl = `${APP_URL}/login`;
@@ -171,23 +141,12 @@ export async function sendAccountRestoredEmail(email) {
171
141
  <a href="${loginUrl}" style="display:inline-block;background-color:#7c3aed;color:#fff;text-decoration:none;padding:10px 24px;border-radius:6px;font-size:14px;font-weight:500;">Log In</a>
172
142
  </div>
173
143
  `;
174
- try {
175
- if (!env.SMTP_HOST) {
176
- logger.warn('Email service not configured (SMTP_HOST missing). Logging email content instead:');
177
- logger.info(`Account Restored Email to ${email}`);
178
- return true;
179
- }
180
- await transporter.sendMail({
181
- from: FROM_EMAIL,
182
- to: email,
183
- subject: 'Account Restored - Scribe',
184
- html,
185
- });
186
- logger.info(`Account restored email sent to ${email}`);
187
- return true;
188
- }
189
- catch (err) {
190
- logger.error('Email send error:', err);
191
- return false;
192
- }
144
+ return sendEmail({
145
+ to: email,
146
+ subject: 'Account Restored - Scribe',
147
+ html,
148
+ successLog: `Account restored email sent to ${email}`,
149
+ missingConfigLog: 'Email service not configured (RESEND_API_KEY missing).',
150
+ devLogDetail: `Account Restored Email to ${email}: ${loginUrl}`,
151
+ });
193
152
  }
@@ -0,0 +1,2 @@
1
+ export { DEFAULT_EMBEDDING_DIM, DEFAULT_EMBEDDING_MODEL, embedQuery, embedTexts, toVectorLiteral, } from './ai/embedding-client.js';
2
+ export type { EmbedOptions } from './ai/embedding-client.js';
@@ -0,0 +1 @@
1
+ export { DEFAULT_EMBEDDING_DIM, DEFAULT_EMBEDDING_MODEL, embedQuery, embedTexts, toVectorLiteral, } from './ai/embedding-client.js';
@@ -0,0 +1,6 @@
1
+ import type { PrismaClient } from '@prisma/client';
2
+ /**
3
+ * Ensures the curated AP/IB catalog exists. Idempotent — safe to call on every
4
+ * server boot. Matches existing KBs by slug stored in `meta.slug`.
5
+ */
6
+ export declare function ensureCuratedKbCatalog(db: PrismaClient): Promise<void>;
@@ -0,0 +1,53 @@
1
+ import { CURATED_KB_SEEDS } from '../lib/curated-kb-seed.js';
2
+ import { logger } from '../lib/logger.js';
3
+ /**
4
+ * Ensures the curated AP/IB catalog exists. Idempotent — safe to call on every
5
+ * server boot. Matches existing KBs by slug stored in `meta.slug`.
6
+ */
7
+ export async function ensureCuratedKbCatalog(db) {
8
+ let created = 0;
9
+ for (const seed of CURATED_KB_SEEDS) {
10
+ const existing = (await db.knowledgeBase.findFirst({
11
+ where: {
12
+ meta: { path: ['slug'], equals: seed.slug },
13
+ },
14
+ })) ??
15
+ (await db.knowledgeBase.findFirst({
16
+ where: {
17
+ name: { equals: seed.name, mode: 'insensitive' },
18
+ },
19
+ }));
20
+ if (existing) {
21
+ await db.knowledgeBase.update({
22
+ where: { id: existing.id },
23
+ data: {
24
+ name: seed.name,
25
+ description: seed.description,
26
+ isCurated: true,
27
+ meta: {
28
+ slug: seed.slug,
29
+ category: seed.category,
30
+ subject: seed.subject,
31
+ },
32
+ },
33
+ });
34
+ continue;
35
+ }
36
+ await db.knowledgeBase.create({
37
+ data: {
38
+ name: seed.name,
39
+ description: seed.description,
40
+ isCurated: true,
41
+ meta: {
42
+ slug: seed.slug,
43
+ category: seed.category,
44
+ subject: seed.subject,
45
+ },
46
+ },
47
+ });
48
+ created += 1;
49
+ }
50
+ if (created > 0) {
51
+ logger.info(`Seeded ${created} curated knowledge base(s)`, 'KB');
52
+ }
53
+ }
package/dist/lib/env.d.ts CHANGED
@@ -6,9 +6,6 @@ export declare const env: {
6
6
  PORT: number;
7
7
  NODE_ENV: "production" | "development" | "test";
8
8
  FRONTEND_URL: string;
9
- SMTP_HOST: string;
10
- SMTP_PORT: number;
11
- SMTP_SECURE: boolean;
12
9
  EMAIL_FROM: string;
13
10
  STRIPE_SUCCESS_URL: string;
14
11
  STRIPE_CANCEL_URL: string;
@@ -23,8 +20,7 @@ export declare const env: {
23
20
  PUSHER_SECRET?: string | undefined;
24
21
  PUSHER_CLUSTER?: string | undefined;
25
22
  INFERENCE_API_URL?: string | undefined;
26
- SMTP_USER?: string | undefined;
27
- SMTP_PASSWORD?: string | undefined;
23
+ RESEND_API_KEY?: string | undefined;
28
24
  STRIPE_SECRET_KEY?: string | undefined;
29
25
  STRIPE_PRICE_SUB_BASIC?: string | undefined;
30
26
  STRIPE_PRICE_SUB_PRO?: string | undefined;
package/dist/lib/env.js CHANGED
@@ -27,12 +27,8 @@ const envSchema = z.object({
27
27
  INFERENCE_API_URL: z.string().url().optional(),
28
28
  // CORS
29
29
  FRONTEND_URL: z.string().url().default('http://localhost:3000'),
30
- // Email
31
- SMTP_HOST: z.string(),
32
- SMTP_PORT: z.string().regex(/^\d+$/).default('587').transform(Number),
33
- SMTP_USER: z.string().optional(),
34
- SMTP_PASSWORD: z.string().optional(),
35
- SMTP_SECURE: z.enum(['true', 'false']).default('false').transform((v) => v === 'true'),
30
+ // Email (Resend)
31
+ RESEND_API_KEY: z.string().optional(),
36
32
  EMAIL_FROM: z.string().default('Scribe <hello@scribe.study>'),
37
33
  // Stripe
38
34
  STRIPE_SECRET_KEY: z.string().startsWith('sk_').optional(),
@@ -47,7 +43,6 @@ const envSchema = z.object({
47
43
  * Parsed and validated environment variables
48
44
  */
49
45
  export const env = envSchema.parse(process.env);
50
- // console.log('DEBUG: SMTP_HOST loaded:', env.SMTP_HOST ? 'Yes' : 'No');
51
46
  /**
52
47
  * Check if running in production
53
48
  */
@@ -1,8 +1 @@
1
- import OpenAI from 'openai';
2
- declare function inference(messages: {
3
- role: 'system' | 'user' | 'assistant';
4
- content: string;
5
- }[]): Promise<OpenAI.Chat.Completions.ChatCompletion & {
6
- _request_id?: string | null;
7
- }>;
8
- export default inference;
1
+ export { complete as default, complete, completeText } from './ai/llm-client.js';
@@ -1,19 +1 @@
1
- import OpenAI from 'openai';
2
- const openai = new OpenAI({
3
- apiKey: process.env.INFERENCE_API_KEY,
4
- baseURL: process.env.INFERENCE_BASE_URL,
5
- });
6
- async function inference(messages) {
7
- try {
8
- const response = await openai.chat.completions.create({
9
- model: "command-a-03-2025",
10
- messages: messages,
11
- });
12
- return response;
13
- }
14
- catch (error) {
15
- // Inference error logged at call site
16
- throw error;
17
- }
18
- }
19
- export default inference;
1
+ export { complete as default, complete, completeText } from './ai/llm-client.js';
@@ -0,0 +1,8 @@
1
+ export type KbMetaRecord = {
2
+ slug?: string;
3
+ category?: string;
4
+ subject?: string;
5
+ kind?: string;
6
+ };
7
+ /** Build catalog meta for new KBs so clients can assign icons and banner colors. */
8
+ export declare function buildKbMetaFromName(name: string, existing?: KbMetaRecord | null): KbMetaRecord;
@@ -0,0 +1,77 @@
1
+ import { CURATED_KB_SEEDS } from './curated-kb-seed.js';
2
+ const CURATED_BY_NAME = new Map(CURATED_KB_SEEDS.map((seed) => [seed.name.trim().toLowerCase(), seed]));
3
+ function inferSubject(name) {
4
+ const lower = name.toLowerCase();
5
+ if (lower.includes('biology') || /\bbio\b/.test(lower))
6
+ return 'biology';
7
+ if (lower.includes('chemistry') || /\bchem\b/.test(lower))
8
+ return 'chemistry';
9
+ if (lower.includes('physics'))
10
+ return 'physics';
11
+ if (lower.includes('calculus'))
12
+ return 'calculus';
13
+ if (lower.includes('statistics') || lower.includes('stats'))
14
+ return 'math';
15
+ if (lower.includes('math') || lower.includes('algebra') || lower.includes('geometry')) {
16
+ return 'math';
17
+ }
18
+ if (lower.includes('literature') || lower.includes('literary'))
19
+ return 'literature';
20
+ if (lower.includes('english') || lower.includes('writing') || lower.includes('rhetoric')) {
21
+ return 'english';
22
+ }
23
+ if (lower.includes('history') || lower.includes('historical'))
24
+ return 'history';
25
+ if (lower.includes('psychology') || lower.includes('psych'))
26
+ return 'psychology';
27
+ if (lower.includes('economics') || lower.includes('econ'))
28
+ return 'economics';
29
+ if (lower.includes('environmental') || lower.includes('ecology'))
30
+ return 'environmental';
31
+ if (lower.includes('computer') || lower.includes('programming') || lower.includes('cs ')) {
32
+ return 'science';
33
+ }
34
+ if (lower.includes('government') || lower.includes('politics'))
35
+ return 'history';
36
+ return undefined;
37
+ }
38
+ function inferCategory(name, category) {
39
+ if (category === 'AP' || category === 'IB')
40
+ 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
+ function slugify(name) {
51
+ return name
52
+ .toLowerCase()
53
+ .replace(/[^a-z0-9]+/g, '-')
54
+ .replace(/^-+|-+$/g, '')
55
+ .slice(0, 80);
56
+ }
57
+ /** Build catalog meta for new KBs so clients can assign icons and banner colors. */
58
+ export function buildKbMetaFromName(name, existing) {
59
+ const trimmed = name.trim();
60
+ const curated = CURATED_BY_NAME.get(trimmed.toLowerCase());
61
+ if (curated) {
62
+ return {
63
+ slug: curated.slug,
64
+ category: curated.category,
65
+ subject: curated.subject,
66
+ };
67
+ }
68
+ const subject = existing?.subject ?? inferSubject(trimmed);
69
+ const category = inferCategory(trimmed, existing?.category);
70
+ const slug = existing?.slug ?? (subject ? `${slugify(trimmed)}-${subject}` : slugify(trimmed));
71
+ return {
72
+ slug: slug || undefined,
73
+ category: category === 'General' ? undefined : category,
74
+ subject,
75
+ ...(existing?.kind ? { kind: existing.kind } : {}),
76
+ };
77
+ }
@@ -0,0 +1 @@
1
+ export declare function extractNoteText(blocks: unknown, title?: string): string;
@@ -0,0 +1,47 @@
1
+ function inlineText(content) {
2
+ if (!Array.isArray(content))
3
+ return '';
4
+ return content
5
+ .map((item) => {
6
+ if (!item || typeof item !== 'object')
7
+ return '';
8
+ const node = item;
9
+ if (node.type === 'text')
10
+ return node.text ?? '';
11
+ if (Array.isArray(node.content))
12
+ return inlineText(node.content);
13
+ return '';
14
+ })
15
+ .join('');
16
+ }
17
+ function blockText(block) {
18
+ const text = inlineText(block.content);
19
+ if (text)
20
+ return text;
21
+ if (block.type === 'image' || block.type === 'file' || block.type === 'audio') {
22
+ return block.props?.caption || block.props?.name || '';
23
+ }
24
+ return '';
25
+ }
26
+ function flattenBlocks(blocks) {
27
+ const out = [];
28
+ for (const block of blocks) {
29
+ out.push(block);
30
+ if (Array.isArray(block.children) && block.children.length > 0) {
31
+ out.push(...flattenBlocks(block.children));
32
+ }
33
+ }
34
+ return out;
35
+ }
36
+ export function extractNoteText(blocks, title) {
37
+ const parts = [];
38
+ if (title && title !== 'Untitled')
39
+ parts.push(title);
40
+ if (Array.isArray(blocks)) {
41
+ const texts = flattenBlocks(blocks)
42
+ .map(blockText)
43
+ .filter(Boolean);
44
+ parts.push(...texts);
45
+ }
46
+ return parts.join('\n\n').trim();
47
+ }
@@ -1,5 +1,4 @@
1
- import test from 'node:test';
2
- import assert from 'node:assert/strict';
1
+ import { describe, it, expect } from 'vitest';
3
2
  import PusherService from './pusher.js';
4
3
  import { NotificationType, createNotification } from './notification-service.js';
5
4
  function createFakeDb() {
@@ -48,40 +47,42 @@ function createFakeDb() {
48
47
  };
49
48
  return { db, store };
50
49
  }
51
- test('createNotification deduplicates by sourceId', async () => {
52
- const { db, store } = createFakeDb();
53
- const originalEmit = PusherService.emitNotificationNew;
54
- PusherService.emitNotificationNew = async () => { };
55
- await createNotification(db, {
56
- userId: 'u1',
57
- type: NotificationType.PAYMENT_SUCCEEDED,
58
- title: 'Payment successful',
59
- body: 'Paid',
60
- sourceId: 'source-1',
50
+ describe('createNotification', () => {
51
+ it('deduplicates by sourceId', async () => {
52
+ const { db, store } = createFakeDb();
53
+ const originalEmit = PusherService.emitNotificationNew;
54
+ PusherService.emitNotificationNew = async () => { };
55
+ await createNotification(db, {
56
+ userId: 'u1',
57
+ type: NotificationType.PAYMENT_SUCCEEDED,
58
+ title: 'Payment successful',
59
+ body: 'Paid',
60
+ sourceId: 'source-1',
61
+ });
62
+ await createNotification(db, {
63
+ userId: 'u1',
64
+ type: NotificationType.PAYMENT_SUCCEEDED,
65
+ title: 'Payment successful',
66
+ body: 'Paid',
67
+ sourceId: 'source-1',
68
+ });
69
+ expect(store.length).toBe(1);
70
+ PusherService.emitNotificationNew = originalEmit;
61
71
  });
62
- await createNotification(db, {
63
- userId: 'u1',
64
- type: NotificationType.PAYMENT_SUCCEEDED,
65
- title: 'Payment successful',
66
- body: 'Paid',
67
- sourceId: 'source-1',
72
+ it('emits unread count payload', async () => {
73
+ const { db } = createFakeDb();
74
+ const originalEmit = PusherService.emitNotificationNew;
75
+ let capturedUnread = -1;
76
+ PusherService.emitNotificationNew = async (_userId, payload) => {
77
+ capturedUnread = payload.unreadCount;
78
+ };
79
+ await createNotification(db, {
80
+ userId: 'u1',
81
+ type: NotificationType.GENERAL,
82
+ title: 'Hello',
83
+ body: 'World',
84
+ });
85
+ expect(capturedUnread).toBe(1);
86
+ PusherService.emitNotificationNew = originalEmit;
68
87
  });
69
- assert.equal(store.length, 1);
70
- PusherService.emitNotificationNew = originalEmit;
71
- });
72
- test('createNotification emits unread count payload', async () => {
73
- const { db } = createFakeDb();
74
- const originalEmit = PusherService.emitNotificationNew;
75
- let capturedUnread = -1;
76
- PusherService.emitNotificationNew = async (_userId, payload) => {
77
- capturedUnread = payload.unreadCount;
78
- };
79
- await createNotification(db, {
80
- userId: 'u1',
81
- type: NotificationType.GENERAL,
82
- title: 'Hello',
83
- body: 'World',
84
- });
85
- assert.equal(capturedUnread, 1);
86
- PusherService.emitNotificationNew = originalEmit;
87
88
  });
@@ -0,0 +1,11 @@
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
+ export declare function extractPdfText(buffer: Buffer): Promise<ExtractedPdf>;
@@ -0,0 +1,11 @@
1
+ export async function extractPdfText(buffer) {
2
+ // Deep import skips pdf-parse's top-level demo block (`if (!module.parent)`).
3
+ // @ts-ignore - no types ship for the deep file
4
+ const mod = await import('pdf-parse/lib/pdf-parse.js');
5
+ const pdfParse = mod.default ?? mod;
6
+ const data = await pdfParse(buffer);
7
+ return {
8
+ text: data.text ?? '',
9
+ numPages: data.numpages ?? 0,
10
+ };
11
+ }
@@ -23,4 +23,5 @@ export declare function getUserPlanLimits(userId: string): Promise<{
23
23
  maxStudyGuides: number;
24
24
  createdAt: Date;
25
25
  updatedAt: Date;
26
- } | null>;
26
+ isFallbackPlan: boolean;
27
+ }>;