@goscribe/server 1.6.0 → 1.7.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 (281) hide show
  1. package/dist/generated/prisma/client.d.ts +224 -0
  2. package/dist/generated/prisma/client.js +34 -0
  3. package/dist/generated/prisma/commonInputTypes.d.ts +941 -0
  4. package/dist/generated/prisma/commonInputTypes.js +10 -0
  5. package/dist/generated/prisma/enums.d.ts +67 -0
  6. package/dist/generated/prisma/enums.js +66 -0
  7. package/dist/generated/prisma/internal/class.d.ts +539 -0
  8. package/dist/generated/prisma/internal/class.js +49 -0
  9. package/dist/generated/prisma/internal/prismaNamespace.d.ts +3924 -0
  10. package/dist/generated/prisma/internal/prismaNamespace.js +557 -0
  11. package/dist/generated/prisma/models/ActivityLog.d.ts +1847 -0
  12. package/dist/generated/prisma/models/ActivityLog.js +1 -0
  13. package/dist/generated/prisma/models/Artifact.d.ts +2345 -0
  14. package/dist/generated/prisma/models/Artifact.js +1 -0
  15. package/dist/generated/prisma/models/ArtifactVersion.d.ts +1550 -0
  16. package/dist/generated/prisma/models/ArtifactVersion.js +1 -0
  17. package/dist/generated/prisma/models/Channel.d.ts +1257 -0
  18. package/dist/generated/prisma/models/Channel.js +1 -0
  19. package/dist/generated/prisma/models/Chat.d.ts +1339 -0
  20. package/dist/generated/prisma/models/Chat.js +1 -0
  21. package/dist/generated/prisma/models/CopilotConversation.d.ts +1450 -0
  22. package/dist/generated/prisma/models/CopilotConversation.js +1 -0
  23. package/dist/generated/prisma/models/CopilotMessage.d.ts +1179 -0
  24. package/dist/generated/prisma/models/CopilotMessage.js +1 -0
  25. package/dist/generated/prisma/models/FileAsset.d.ts +1832 -0
  26. package/dist/generated/prisma/models/FileAsset.js +1 -0
  27. package/dist/generated/prisma/models/Flashcard.d.ts +1460 -0
  28. package/dist/generated/prisma/models/Flashcard.js +1 -0
  29. package/dist/generated/prisma/models/FlashcardProgress.d.ts +1782 -0
  30. package/dist/generated/prisma/models/FlashcardProgress.js +1 -0
  31. package/dist/generated/prisma/models/Folder.d.ts +1685 -0
  32. package/dist/generated/prisma/models/Folder.js +1 -0
  33. package/dist/generated/prisma/models/IdempotencyRecord.d.ts +1319 -0
  34. package/dist/generated/prisma/models/IdempotencyRecord.js +1 -0
  35. package/dist/generated/prisma/models/Invoice.d.ts +1586 -0
  36. package/dist/generated/prisma/models/Invoice.js +1 -0
  37. package/dist/generated/prisma/models/KnowledgeBase.d.ts +1721 -0
  38. package/dist/generated/prisma/models/KnowledgeBase.js +1 -0
  39. package/dist/generated/prisma/models/KnowledgeBaseChunk.d.ts +1333 -0
  40. package/dist/generated/prisma/models/KnowledgeBaseChunk.js +1 -0
  41. package/dist/generated/prisma/models/KnowledgeBaseDocument.d.ts +1695 -0
  42. package/dist/generated/prisma/models/KnowledgeBaseDocument.js +1 -0
  43. package/dist/generated/prisma/models/Notification.d.ts +1992 -0
  44. package/dist/generated/prisma/models/Notification.js +1 -0
  45. package/dist/generated/prisma/models/PasswordResetToken.d.ts +1210 -0
  46. package/dist/generated/prisma/models/PasswordResetToken.js +1 -0
  47. package/dist/generated/prisma/models/Plan.d.ts +1431 -0
  48. package/dist/generated/prisma/models/Plan.js +1 -0
  49. package/dist/generated/prisma/models/PlanLimit.d.ts +1328 -0
  50. package/dist/generated/prisma/models/PlanLimit.js +1 -0
  51. package/dist/generated/prisma/models/PodcastSegment.d.ts +1564 -0
  52. package/dist/generated/prisma/models/PodcastSegment.js +1 -0
  53. package/dist/generated/prisma/models/ResourcePrice.d.ts +1008 -0
  54. package/dist/generated/prisma/models/ResourcePrice.js +1 -0
  55. package/dist/generated/prisma/models/Role.d.ts +1065 -0
  56. package/dist/generated/prisma/models/Role.js +1 -0
  57. package/dist/generated/prisma/models/Session.d.ts +1105 -0
  58. package/dist/generated/prisma/models/Session.js +1 -0
  59. package/dist/generated/prisma/models/StripeEvent.d.ts +1081 -0
  60. package/dist/generated/prisma/models/StripeEvent.js +1 -0
  61. package/dist/generated/prisma/models/StudyGuideComment.d.ts +1321 -0
  62. package/dist/generated/prisma/models/StudyGuideComment.js +1 -0
  63. package/dist/generated/prisma/models/StudyGuideHighlight.d.ts +1629 -0
  64. package/dist/generated/prisma/models/StudyGuideHighlight.js +1 -0
  65. package/dist/generated/prisma/models/Subscription.d.ts +1677 -0
  66. package/dist/generated/prisma/models/Subscription.js +1 -0
  67. package/dist/generated/prisma/models/User.d.ts +7559 -0
  68. package/dist/generated/prisma/models/User.js +1 -0
  69. package/dist/generated/prisma/models/UserCredit.d.ts +1249 -0
  70. package/dist/generated/prisma/models/UserCredit.js +1 -0
  71. package/dist/generated/prisma/models/VerificationToken.d.ts +946 -0
  72. package/dist/generated/prisma/models/VerificationToken.js +1 -0
  73. package/dist/generated/prisma/models/WorksheetPreset.d.ts +1433 -0
  74. package/dist/generated/prisma/models/WorksheetPreset.js +1 -0
  75. package/dist/generated/prisma/models/WorksheetQuestion.d.ts +1491 -0
  76. package/dist/generated/prisma/models/WorksheetQuestion.js +1 -0
  77. package/dist/generated/prisma/models/WorksheetQuestionProgress.d.ts +1620 -0
  78. package/dist/generated/prisma/models/WorksheetQuestionProgress.js +1 -0
  79. package/dist/generated/prisma/models/Workspace.d.ts +3620 -0
  80. package/dist/generated/prisma/models/Workspace.js +1 -0
  81. package/dist/generated/prisma/models/WorkspaceInvitation.d.ts +1490 -0
  82. package/dist/generated/prisma/models/WorkspaceInvitation.js +1 -0
  83. package/dist/generated/prisma/models/WorkspaceKnowledgeBase.d.ts +1410 -0
  84. package/dist/generated/prisma/models/WorkspaceKnowledgeBase.js +1 -0
  85. package/dist/generated/prisma/models/WorkspaceMember.d.ts +1326 -0
  86. package/dist/generated/prisma/models/WorkspaceMember.js +1 -0
  87. package/dist/generated/prisma/models.d.ts +39 -0
  88. package/dist/generated/prisma/models.js +1 -0
  89. package/dist/src/context.d.ts +27 -0
  90. package/dist/src/context.js +33 -0
  91. package/dist/src/index.d.ts +3 -0
  92. package/dist/src/index.js +1 -0
  93. package/dist/src/lib/ai/config.d.ts +20 -0
  94. package/dist/src/lib/ai/config.js +31 -0
  95. package/dist/src/lib/ai/embedding-client.d.ts +8 -0
  96. package/dist/src/lib/ai/embedding-client.js +30 -0
  97. package/dist/src/lib/ai/index.d.ts +48 -0
  98. package/dist/src/lib/ai/index.js +29 -0
  99. package/dist/src/lib/ai/inference-backend/client.d.ts +28 -0
  100. package/dist/src/lib/ai/inference-backend/client.js +301 -0
  101. package/dist/src/lib/ai/inference-backend/mocks.d.ts +12 -0
  102. package/dist/src/lib/ai/inference-backend/mocks.js +133 -0
  103. package/dist/src/lib/ai/inference-backend/types.d.ts +44 -0
  104. package/dist/src/lib/ai/inference-backend/types.js +1 -0
  105. package/dist/src/lib/ai/json-parse.d.ts +2 -0
  106. package/dist/src/lib/ai/json-parse.js +34 -0
  107. package/dist/src/lib/ai/llm-client.d.ts +7 -0
  108. package/dist/src/lib/ai/llm-client.js +36 -0
  109. package/dist/src/lib/ai/mock.d.ts +2 -0
  110. package/dist/src/lib/ai/mock.js +10 -0
  111. package/dist/src/lib/ai/types.d.ts +9 -0
  112. package/dist/src/lib/ai/types.js +1 -0
  113. package/dist/src/lib/auth.d.ts +36 -0
  114. package/dist/src/lib/auth.js +117 -0
  115. package/dist/src/lib/chunking.d.ts +19 -0
  116. package/dist/src/lib/chunking.js +47 -0
  117. package/dist/src/lib/constants.d.ts +13 -0
  118. package/dist/src/lib/constants.js +12 -0
  119. package/dist/src/lib/curated-kb-seed.d.ts +12 -0
  120. package/dist/src/lib/curated-kb-seed.js +155 -0
  121. package/dist/src/lib/email.d.ts +11 -0
  122. package/dist/src/lib/email.js +152 -0
  123. package/dist/src/lib/embeddings.d.ts +2 -0
  124. package/dist/src/lib/embeddings.js +1 -0
  125. package/dist/src/lib/ensure-curated-kb-catalog.d.ts +6 -0
  126. package/dist/src/lib/ensure-curated-kb-catalog.js +53 -0
  127. package/dist/src/lib/env.d.ts +41 -0
  128. package/dist/src/lib/env.js +57 -0
  129. package/dist/src/lib/errors.d.ts +33 -0
  130. package/dist/src/lib/errors.js +78 -0
  131. package/dist/src/lib/file.d.ts +0 -0
  132. package/dist/src/lib/file.js +1 -0
  133. package/dist/src/lib/inference.d.ts +1 -0
  134. package/dist/src/lib/inference.js +1 -0
  135. package/dist/src/lib/kb-meta.d.ts +8 -0
  136. package/dist/src/lib/kb-meta.js +77 -0
  137. package/dist/src/lib/logger.d.ts +62 -0
  138. package/dist/src/lib/logger.js +364 -0
  139. package/dist/src/lib/pdf.d.ts +11 -0
  140. package/dist/src/lib/pdf.js +11 -0
  141. package/dist/src/lib/prisma.d.ts +3 -0
  142. package/dist/src/lib/prisma.js +15 -0
  143. package/dist/src/lib/pusher.d.ts +38 -0
  144. package/dist/src/lib/pusher.js +170 -0
  145. package/dist/src/lib/retry.d.ts +15 -0
  146. package/dist/src/lib/retry.js +37 -0
  147. package/dist/src/lib/storage.d.ts +11 -0
  148. package/dist/src/lib/storage.js +71 -0
  149. package/dist/src/lib/stripe.d.ts +10 -0
  150. package/dist/src/lib/stripe.js +36 -0
  151. package/dist/src/lib/validation.d.ts +51 -0
  152. package/dist/src/lib/validation.js +64 -0
  153. package/dist/src/lib/workspace-kb.d.ts +5 -0
  154. package/dist/src/lib/workspace-kb.js +7 -0
  155. package/dist/src/repositories/artifact.repository.d.ts +64 -0
  156. package/dist/src/repositories/artifact.repository.js +40 -0
  157. package/dist/src/repositories/base.repository.d.ts +14 -0
  158. package/dist/src/repositories/base.repository.js +14 -0
  159. package/dist/src/repositories/invitation.repository.d.ts +104 -0
  160. package/dist/src/repositories/invitation.repository.js +44 -0
  161. package/dist/src/repositories/notification.repository.d.ts +76 -0
  162. package/dist/src/repositories/notification.repository.js +44 -0
  163. package/dist/src/repositories/user.repository.d.ts +84 -0
  164. package/dist/src/repositories/user.repository.js +37 -0
  165. package/dist/src/repositories/workspace-member.repository.d.ts +35 -0
  166. package/dist/src/repositories/workspace-member.repository.js +31 -0
  167. package/dist/src/repositories/workspace.repository.d.ts +101 -0
  168. package/dist/src/repositories/workspace.repository.js +79 -0
  169. package/dist/src/routers/_app.d.ts +3464 -0
  170. package/dist/src/routers/_app.js +36 -0
  171. package/dist/src/routers/admin.d.ts +358 -0
  172. package/dist/src/routers/admin.js +105 -0
  173. package/dist/src/routers/annotations.d.ts +219 -0
  174. package/dist/src/routers/annotations.js +29 -0
  175. package/dist/src/routers/artifactVersions.d.ts +65 -0
  176. package/dist/src/routers/artifactVersions.js +14 -0
  177. package/dist/src/routers/auth.d.ts +161 -0
  178. package/dist/src/routers/auth.js +97 -0
  179. package/dist/src/routers/chat.d.ts +170 -0
  180. package/dist/src/routers/chat.js +32 -0
  181. package/dist/src/routers/copilot.d.ts +200 -0
  182. package/dist/src/routers/copilot.js +52 -0
  183. package/dist/src/routers/flashcards.d.ts +336 -0
  184. package/dist/src/routers/flashcards.js +93 -0
  185. package/dist/src/routers/knowledgeBase.d.ts +421 -0
  186. package/dist/src/routers/knowledgeBase.js +118 -0
  187. package/dist/src/routers/members.d.ts +169 -0
  188. package/dist/src/routers/members.js +47 -0
  189. package/dist/src/routers/notifications.d.ts +99 -0
  190. package/dist/src/routers/notifications.js +25 -0
  191. package/dist/src/routers/payment.d.ts +80 -0
  192. package/dist/src/routers/payment.js +21 -0
  193. package/dist/src/routers/podcast.d.ts +287 -0
  194. package/dist/src/routers/podcast.js +34 -0
  195. package/dist/src/routers/studyguide.d.ts +36 -0
  196. package/dist/src/routers/studyguide.js +8 -0
  197. package/dist/src/routers/worksheets.d.ts +429 -0
  198. package/dist/src/routers/worksheets.js +139 -0
  199. package/dist/src/routers/workspace.d.ts +563 -0
  200. package/dist/src/routers/workspace.js +104 -0
  201. package/dist/src/scripts/purge-deleted-users.d.ts +1 -0
  202. package/dist/src/scripts/purge-deleted-users.js +148 -0
  203. package/dist/src/server.d.ts +1 -0
  204. package/dist/src/server.js +190 -0
  205. package/dist/src/services/activity/activity-human-description.service.d.ts +13 -0
  206. package/dist/src/services/activity/activity-human-description.service.js +221 -0
  207. package/dist/src/services/activity/activity-human-description.service.test.d.ts +1 -0
  208. package/dist/src/services/activity/activity-human-description.service.test.js +16 -0
  209. package/dist/src/services/activity/activity-log.service.d.ts +87 -0
  210. package/dist/src/services/activity/activity-log.service.js +276 -0
  211. package/dist/src/services/activity/activity-log.service.test.d.ts +1 -0
  212. package/dist/src/services/activity/activity-log.service.test.js +27 -0
  213. package/dist/src/services/admin/admin.service.d.ts +270 -0
  214. package/dist/src/services/admin/admin.service.js +476 -0
  215. package/dist/src/services/ai/ai-session.service.d.ts +5 -0
  216. package/dist/src/services/ai/ai-session.service.js +4 -0
  217. package/dist/src/services/artifacts/annotation.service.d.ts +177 -0
  218. package/dist/src/services/artifacts/annotation.service.js +154 -0
  219. package/dist/src/services/artifacts/artifact-version.service.d.ts +38 -0
  220. package/dist/src/services/artifacts/artifact-version.service.js +129 -0
  221. package/dist/src/services/artifacts/chat.service.d.ts +127 -0
  222. package/dist/src/services/artifacts/chat.service.js +182 -0
  223. package/dist/src/services/artifacts/study-guide.service.d.ts +18 -0
  224. package/dist/src/services/artifacts/study-guide.service.js +65 -0
  225. package/dist/src/services/auth/auth.service.d.ts +94 -0
  226. package/dist/src/services/auth/auth.service.js +368 -0
  227. package/dist/src/services/base.service.d.ts +14 -0
  228. package/dist/src/services/base.service.js +14 -0
  229. package/dist/src/services/billing/payment.service.d.ts +44 -0
  230. package/dist/src/services/billing/payment.service.js +365 -0
  231. package/dist/src/services/billing/subscription.service.d.ts +37 -0
  232. package/dist/src/services/billing/subscription.service.js +654 -0
  233. package/dist/src/services/billing/usage.service.d.ts +47 -0
  234. package/dist/src/services/billing/usage.service.js +149 -0
  235. package/dist/src/services/content/copilot.service.d.ts +113 -0
  236. package/dist/src/services/content/copilot.service.js +439 -0
  237. package/dist/src/services/content/flashcard-progress.service.d.ts +159 -0
  238. package/dist/src/services/content/flashcard-progress.service.js +432 -0
  239. package/dist/src/services/content/flashcard.service.d.ts +184 -0
  240. package/dist/src/services/content/flashcard.service.js +339 -0
  241. package/dist/src/services/content/media-analysis.service.d.ts +23 -0
  242. package/dist/src/services/content/media-analysis.service.js +404 -0
  243. package/dist/src/services/content/podcast.service.d.ts +267 -0
  244. package/dist/src/services/content/podcast.service.js +653 -0
  245. package/dist/src/services/content/worksheet-content.service.d.ts +37 -0
  246. package/dist/src/services/content/worksheet-content.service.js +84 -0
  247. package/dist/src/services/content/worksheet-content.service.test.d.ts +1 -0
  248. package/dist/src/services/content/worksheet-content.service.test.js +69 -0
  249. package/dist/src/services/content/worksheet-generation.service.d.ts +91 -0
  250. package/dist/src/services/content/worksheet-generation.service.js +95 -0
  251. package/dist/src/services/content/worksheet-generation.service.test.d.ts +1 -0
  252. package/dist/src/services/content/worksheet-generation.service.test.js +20 -0
  253. package/dist/src/services/content/worksheet.service.d.ts +347 -0
  254. package/dist/src/services/content/worksheet.service.js +599 -0
  255. package/dist/src/services/knowledge/knowledge-base.service.d.ts +316 -0
  256. package/dist/src/services/knowledge/knowledge-base.service.js +544 -0
  257. package/dist/src/services/members/invitation.service.d.ts +66 -0
  258. package/dist/src/services/members/invitation.service.js +348 -0
  259. package/dist/src/services/members/member.service.d.ts +36 -0
  260. package/dist/src/services/members/member.service.js +193 -0
  261. package/dist/src/services/notifications/notification.service.d.ts +214 -0
  262. package/dist/src/services/notifications/notification.service.js +550 -0
  263. package/dist/src/services/notifications/notification.service.test.d.ts +1 -0
  264. package/dist/src/services/notifications/notification.service.test.js +87 -0
  265. package/dist/src/services/workspace/workspace-analytics.service.d.ts +24 -0
  266. package/dist/src/services/workspace/workspace-analytics.service.js +95 -0
  267. package/dist/src/services/workspace/workspace-kb.service.d.ts +40 -0
  268. package/dist/src/services/workspace/workspace-kb.service.js +184 -0
  269. package/dist/src/services/workspace/workspace.service.d.ts +263 -0
  270. package/dist/src/services/workspace/workspace.service.js +401 -0
  271. package/dist/src/trpc.d.ts +60 -0
  272. package/dist/src/trpc.js +217 -0
  273. package/dist/src/types/index.d.ts +126 -0
  274. package/dist/src/types/index.js +1 -0
  275. package/package.json +8 -9
  276. package/prisma/schema.prisma +3 -4
  277. package/prisma/seed.mjs +5 -2
  278. package/prisma.config.ts +16 -0
  279. package/src/lib/prisma.ts +18 -9
  280. package/src/scripts/purge-deleted-users.ts +1 -3
  281. package/tsconfig.json +3 -0
@@ -0,0 +1,133 @@
1
+ export function mockStudyGuide() {
2
+ return `# Mock Study Guide
3
+
4
+ ## Overview
5
+ This is a mock study guide generated for testing purposes.
6
+
7
+ ## Key Concepts
8
+ 1. **Concept A**: Mock concept derived from uploaded materials
9
+ 2. **Concept B**: Another mock concept with explanations
10
+ 3. **Concept C**: A third concept with examples
11
+
12
+ ## Summary
13
+ Mock study guide for local development when \`DONT_TEST_INFERENCE=true\`.`;
14
+ }
15
+ export function mockFlashcards(numQuestions, difficulty) {
16
+ return Array.from({ length: numQuestions }, (_, i) => ({
17
+ id: `mock-flashcard-${i + 1}`,
18
+ question: `Mock question ${i + 1}: What is the main concept covered in this material?`,
19
+ answer: `Mock answer ${i + 1}: Sample answer based on uploaded content.`,
20
+ difficulty,
21
+ category: `Mock Category ${(i % 3) + 1}`,
22
+ }));
23
+ }
24
+ export function mockWorksheet(numQuestions, difficulty, options) {
25
+ const mode = options?.mode ?? 'practice';
26
+ const isQuiz = mode === 'quiz';
27
+ return {
28
+ title: isQuiz ? `Mock Quiz - ${difficulty}` : `Mock Worksheet - ${difficulty} Level`,
29
+ description: 'Mock generated content',
30
+ difficulty,
31
+ estimatedTime: `${numQuestions * 2} min`,
32
+ problems: Array.from({ length: numQuestions }, (_, i) => {
33
+ if (isQuiz) {
34
+ return {
35
+ question: `Mock MCQ ${i + 1}: What is 2+2?`,
36
+ answer: '1',
37
+ type: 'MULTIPLE_CHOICE',
38
+ options: ['3', '4', '5', '6'],
39
+ mark_scheme: {
40
+ points: [{ point: 1, requirements: 'Select correct option' }],
41
+ totalPoints: 1,
42
+ },
43
+ };
44
+ }
45
+ return {
46
+ question: `Mock question ${i + 1}: Explain a concept.`,
47
+ answer: 'Mock answer',
48
+ type: 'TEXT',
49
+ options: [],
50
+ mark_scheme: {
51
+ points: [{ point: 1, requirements: 'Clear explanation' }],
52
+ totalPoints: 1,
53
+ },
54
+ };
55
+ }),
56
+ };
57
+ }
58
+ export function mockProcessFile(fileType) {
59
+ const mockPageCount = fileType === 'pdf' ? 15 : 1;
60
+ return {
61
+ status: 'success',
62
+ textContent: `Mock extracted text content from ${fileType} file.`,
63
+ imageDescriptions: Array.from({ length: mockPageCount }, (_, i) => ({
64
+ page: i + 1,
65
+ description: `Page ${i + 1} contains educational content with diagrams and text.`,
66
+ hasVisualContent: true,
67
+ })),
68
+ comprehensiveDescription: `DOCUMENT SUMMARY (${mockPageCount} ${mockPageCount === 1 ? 'page' : 'pages'})\n\nTEXT CONTENT:\nMock extracted text content...`,
69
+ pageCount: mockPageCount,
70
+ };
71
+ }
72
+ export function mockPodcastStructure(title, speakers) {
73
+ const voiceId = speakers[0]?.id || 'mock-voice-1';
74
+ return {
75
+ success: true,
76
+ structure: {
77
+ episodeTitle: `${title} - AI Generated Episode`,
78
+ totalEstimatedDuration: '15 minutes',
79
+ segments: [
80
+ {
81
+ title: 'Welcome & Introduction',
82
+ content: "HOST: Welcome to today's episode!\nGUEST: Thanks for having me!\nHOST: Let's dive into the topic.",
83
+ speaker: 'dialogue',
84
+ voiceId,
85
+ keyPoints: ['Introduction', 'What to expect'],
86
+ estimatedDuration: '3 minutes',
87
+ order: 1,
88
+ },
89
+ {
90
+ title: 'Main Discussion',
91
+ content: 'This is the main content section where we explore the key concepts in detail.',
92
+ speaker: 'host',
93
+ voiceId,
94
+ keyPoints: ['Key concept 1', 'Key concept 2'],
95
+ estimatedDuration: '8 minutes',
96
+ order: 2,
97
+ },
98
+ {
99
+ title: 'Conclusion & Takeaways',
100
+ content: "HOST: Let's wrap up what we've learned today.\nGUEST: The main takeaway is...\nHOST: Thanks for joining us!",
101
+ speaker: 'dialogue',
102
+ voiceId,
103
+ keyPoints: ['Summary', 'Next steps'],
104
+ estimatedDuration: '4 minutes',
105
+ order: 3,
106
+ },
107
+ ],
108
+ },
109
+ };
110
+ }
111
+ export function mockPodcastAudio(user, sessionId, podcastId, segmentIndex, text) {
112
+ const isDialogue = text.includes('HOST:') || text.includes('GUEST:');
113
+ return {
114
+ success: true,
115
+ segmentIndex,
116
+ objectKey: `${user}/${sessionId}/podcasts/${podcastId}/segment_${segmentIndex}.mp3`,
117
+ duration: 45 + Math.floor(Math.random() * 30),
118
+ type: isDialogue ? 'dialogue' : 'monologue',
119
+ ...(isDialogue ? { partCount: 4 } : {}),
120
+ };
121
+ }
122
+ export function mockStudyGuideSegmentation() {
123
+ return [
124
+ { hint: 'Overview', content: 'Mock segment 1 content' },
125
+ { hint: 'Key concepts', content: 'Mock segment 2 content' },
126
+ ];
127
+ }
128
+ export function mockSegmentSummaryValidation() {
129
+ return {
130
+ valid: true,
131
+ feedback: 'Mock validation feedback for local development.',
132
+ };
133
+ }
@@ -0,0 +1,44 @@
1
+ export interface AISession {
2
+ id: string;
3
+ workspaceId: string;
4
+ status: 'initialized' | 'processing' | 'ready' | 'error';
5
+ files: string[];
6
+ instructionText?: string;
7
+ createdAt: Date;
8
+ updatedAt: Date;
9
+ }
10
+ export interface ProcessFileResult {
11
+ status: 'success' | 'error';
12
+ textContent: string | null;
13
+ imageDescriptions: Array<{
14
+ page: number;
15
+ description: string;
16
+ hasVisualContent: boolean;
17
+ }>;
18
+ comprehensiveDescription: string | null;
19
+ pageCount: number;
20
+ error?: string;
21
+ }
22
+ export interface PodcastSpeaker {
23
+ id: string;
24
+ role: string;
25
+ name?: string;
26
+ }
27
+ export interface WorksheetGenerationOptions {
28
+ mode?: 'practice' | 'quiz';
29
+ mcqRatio?: number;
30
+ questionTypes?: string[];
31
+ prompt?: string;
32
+ ragContext?: string;
33
+ }
34
+ export interface BackendGenerationOptions {
35
+ ragContext?: string;
36
+ }
37
+ export interface StudyGuideSegment {
38
+ hint: string;
39
+ content: string;
40
+ }
41
+ export interface SegmentSummaryValidation {
42
+ valid: boolean;
43
+ feedback: string;
44
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export declare function extractJson(content: string): Record<string, unknown> | null;
2
+ export declare function parseJsonField<T>(value: unknown, field: string): T;
@@ -0,0 +1,34 @@
1
+ export function extractJson(content) {
2
+ const fencedMatch = content.match(/```json\s*([\s\S]*?)```/i);
3
+ if (fencedMatch?.[1]) {
4
+ try {
5
+ return JSON.parse(fencedMatch[1]);
6
+ }
7
+ catch {
8
+ // fall through
9
+ }
10
+ }
11
+ const objectMatch = content.match(/\{[\s\S]*\}/);
12
+ if (objectMatch?.[0]) {
13
+ try {
14
+ return JSON.parse(objectMatch[0]);
15
+ }
16
+ catch {
17
+ return null;
18
+ }
19
+ }
20
+ return null;
21
+ }
22
+ export function parseJsonField(value, field) {
23
+ if (typeof value === 'string') {
24
+ return JSON.parse(value);
25
+ }
26
+ if (value && typeof value === 'object' && field in value) {
27
+ const nested = value[field];
28
+ if (typeof nested === 'string') {
29
+ return JSON.parse(nested);
30
+ }
31
+ return nested;
32
+ }
33
+ throw new Error(`Expected JSON field "${field}" in AI response`);
34
+ }
@@ -0,0 +1,7 @@
1
+ import type { ChatCompletion } from 'openai/resources/chat/completions';
2
+ import type { ChatMessage, CompleteOptions } from './types.js';
3
+ export declare function complete(messages: ChatMessage[], options?: CompleteOptions): Promise<ChatCompletion>;
4
+ export declare function completeText(messages: ChatMessage[], options?: CompleteOptions): Promise<string>;
5
+ export declare function streamComplete(messages: ChatMessage[], onDelta: (delta: string) => void | Promise<void>, options?: CompleteOptions): Promise<string>;
6
+ /** @deprecated Use `complete()` from the ai module instead. */
7
+ export default complete;
@@ -0,0 +1,36 @@
1
+ import OpenAI from 'openai';
2
+ import { aiConfig } from './config.js';
3
+ const client = new OpenAI({
4
+ apiKey: aiConfig.llm.apiKey,
5
+ baseURL: aiConfig.llm.baseUrl,
6
+ });
7
+ export async function complete(messages, options = {}) {
8
+ return client.chat.completions.create({
9
+ model: options.model ?? aiConfig.llm.model,
10
+ messages,
11
+ ...(options.temperature !== undefined ? { temperature: options.temperature } : {}),
12
+ });
13
+ }
14
+ export async function completeText(messages, options = {}) {
15
+ const response = await complete(messages, options);
16
+ return response.choices?.[0]?.message?.content ?? '';
17
+ }
18
+ export async function streamComplete(messages, onDelta, options = {}) {
19
+ const stream = await client.chat.completions.create({
20
+ model: options.model ?? aiConfig.llm.model,
21
+ messages,
22
+ stream: true,
23
+ ...(options.temperature !== undefined ? { temperature: options.temperature } : {}),
24
+ });
25
+ let content = '';
26
+ for await (const chunk of stream) {
27
+ const delta = chunk.choices?.[0]?.delta?.content ?? '';
28
+ if (!delta)
29
+ continue;
30
+ content += delta;
31
+ await onDelta(delta);
32
+ }
33
+ return content;
34
+ }
35
+ /** @deprecated Use `complete()` from the ai module instead. */
36
+ export default complete;
@@ -0,0 +1,2 @@
1
+ export declare function isAiMockMode(): boolean;
2
+ export declare function mockDelay(): Promise<void>;
@@ -0,0 +1,10 @@
1
+ import { aiConfig } from './config.js';
2
+ export function isAiMockMode() {
3
+ return aiConfig.inferenceBackend.mockEnabled;
4
+ }
5
+ export async function mockDelay() {
6
+ const delay = aiConfig.inferenceBackend.mockDelayMs;
7
+ if (delay > 0) {
8
+ await new Promise((resolve) => setTimeout(resolve, delay));
9
+ }
10
+ }
@@ -0,0 +1,9 @@
1
+ export type ChatRole = 'system' | 'user' | 'assistant';
2
+ export interface ChatMessage {
3
+ role: ChatRole;
4
+ content: string;
5
+ }
6
+ export interface CompleteOptions {
7
+ model?: string;
8
+ temperature?: number;
9
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Authentication utilities for custom HMAC-based cookie verification.
3
+ *
4
+ * This module provides secure authentication using HMAC-SHA256 signatures
5
+ * to verify user identity through signed cookies.
6
+ *
7
+ * @fileoverview Custom authentication system with HMAC cookie verification
8
+ * @author Scribe Team
9
+ * @version 1.0.0
10
+ */
11
+ /**
12
+ * Represents the result of successful authentication verification.
13
+ */
14
+ export interface AuthResult {
15
+ /** The authenticated user's unique identifier */
16
+ userId: string;
17
+ }
18
+ /**
19
+ * Verifies a custom HMAC-signed authentication cookie.
20
+ *
21
+ * The cookie format is: `base64(userId).hex(hmacSHA256(base64(userId), secret))`
22
+ *
23
+ * @param cookieValue - The raw cookie value to verify, or undefined if no cookie exists
24
+ * @returns Authentication result with userId if valid, null if invalid or missing
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * const result = verifyCustomAuthCookie("dXNlcjEyMw.abc123def456...");
29
+ * if (result) {
30
+ * console.log(`Authenticated user: ${result.userId}`);
31
+ * }
32
+ * ```
33
+ *
34
+ * @throws {Error} Never throws - returns null for all error conditions
35
+ */
36
+ export declare function verifyCustomAuthCookie(cookieValue: string | undefined): AuthResult | null;
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Authentication utilities for custom HMAC-based cookie verification.
3
+ *
4
+ * This module provides secure authentication using HMAC-SHA256 signatures
5
+ * to verify user identity through signed cookies.
6
+ *
7
+ * @fileoverview Custom authentication system with HMAC cookie verification
8
+ * @author Scribe Team
9
+ * @version 1.0.0
10
+ */
11
+ import crypto from "node:crypto";
12
+ /**
13
+ * Verifies a custom HMAC-signed authentication cookie.
14
+ *
15
+ * The cookie format is: `base64(userId).hex(hmacSHA256(base64(userId), secret))`
16
+ *
17
+ * @param cookieValue - The raw cookie value to verify, or undefined if no cookie exists
18
+ * @returns Authentication result with userId if valid, null if invalid or missing
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const result = verifyCustomAuthCookie("dXNlcjEyMw.abc123def456...");
23
+ * if (result) {
24
+ * console.log(`Authenticated user: ${result.userId}`);
25
+ * }
26
+ * ```
27
+ *
28
+ * @throws {Error} Never throws - returns null for all error conditions
29
+ */
30
+ export function verifyCustomAuthCookie(cookieValue) {
31
+ // Early return for missing cookie
32
+ if (!cookieValue) {
33
+ return null;
34
+ }
35
+ // Get authentication secret from environment
36
+ const secret = process.env.AUTH_SECRET;
37
+ if (!secret) {
38
+ return null;
39
+ }
40
+ // Parse cookie format: base64UserId.signatureHex
41
+ const parts = cookieValue.split(".");
42
+ if (parts.length !== 2) {
43
+ return null;
44
+ }
45
+ const [base64UserId, signatureHex] = parts;
46
+ // Decode the user ID from base64url encoding
47
+ const userId = decodeBase64UrlUserId(base64UserId);
48
+ if (!userId) {
49
+ return null;
50
+ }
51
+ // Verify the HMAC signature
52
+ const isValidSignature = verifyHmacSignature(base64UserId, signatureHex, secret);
53
+ if (!isValidSignature) {
54
+ return null;
55
+ }
56
+ return { userId };
57
+ }
58
+ /**
59
+ * Decodes a base64url-encoded user ID string.
60
+ *
61
+ * @param base64UserId - The base64url-encoded user ID
62
+ * @returns The decoded user ID string, or null if decoding fails
63
+ *
64
+ * @private
65
+ */
66
+ function decodeBase64UrlUserId(base64UserId) {
67
+ try {
68
+ const buffer = Buffer.from(base64UserId, "base64url");
69
+ return buffer.toString("utf8");
70
+ }
71
+ catch (error) {
72
+ return null;
73
+ }
74
+ }
75
+ /**
76
+ * Verifies an HMAC-SHA256 signature against the expected value.
77
+ *
78
+ * @param data - The data that was signed (base64url-encoded user ID)
79
+ * @param signatureHex - The hex-encoded signature to verify
80
+ * @param secret - The secret key used for signing
81
+ * @returns True if the signature is valid, false otherwise
82
+ *
83
+ * @private
84
+ */
85
+ function verifyHmacSignature(data, signatureHex, secret) {
86
+ const hmac = crypto.createHmac("sha256", secret);
87
+ hmac.update(data);
88
+ const expectedSignature = hmac.digest("hex");
89
+ return timingSafeEqualHex(signatureHex, expectedSignature);
90
+ }
91
+ /**
92
+ * Performs a timing-safe comparison of two hex-encoded strings.
93
+ *
94
+ * This function prevents timing attacks by ensuring the comparison
95
+ * takes the same amount of time regardless of where the strings differ.
96
+ *
97
+ * @param a - First hex string to compare
98
+ * @param b - Second hex string to compare
99
+ * @returns True if the strings are equal, false otherwise
100
+ *
101
+ * @private
102
+ */
103
+ function timingSafeEqualHex(a, b) {
104
+ try {
105
+ const bufferA = Buffer.from(a, "hex");
106
+ const bufferB = Buffer.from(b, "hex");
107
+ // Length check prevents timing attacks on different-length inputs
108
+ if (bufferA.length !== bufferB.length) {
109
+ return false;
110
+ }
111
+ return crypto.timingSafeEqual(bufferA, bufferB);
112
+ }
113
+ catch {
114
+ // Return false for any parsing errors
115
+ return false;
116
+ }
117
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Approximate text chunker for RAG indexing.
3
+ *
4
+ * Splits a long document into overlapping windows aimed at a target token
5
+ * count. We don't have a tokenizer dependency, so we approximate using
6
+ * `chars / 4` (a rule of thumb that matches GPT-style BPE within ~10-20%).
7
+ * Chunk boundaries snap to paragraph / sentence breaks when possible so we
8
+ * don't slice mid-thought.
9
+ */
10
+ export interface ChunkOptions {
11
+ targetTokens?: number;
12
+ overlapTokens?: number;
13
+ }
14
+ export interface Chunk {
15
+ index: number;
16
+ content: string;
17
+ approxTokens: number;
18
+ }
19
+ export declare function chunkText(text: string, opts?: ChunkOptions): Chunk[];
@@ -0,0 +1,47 @@
1
+ const CHARS_PER_TOKEN = 4;
2
+ export function chunkText(text, opts = {}) {
3
+ const targetTokens = opts.targetTokens ?? 500;
4
+ const overlapTokens = opts.overlapTokens ?? 60;
5
+ const targetChars = targetTokens * CHARS_PER_TOKEN;
6
+ const overlapChars = overlapTokens * CHARS_PER_TOKEN;
7
+ const cleaned = text.replace(/\r\n/g, '\n').replace(/[ \t]+/g, ' ').trim();
8
+ if (!cleaned)
9
+ return [];
10
+ const chunks = [];
11
+ let cursor = 0;
12
+ let index = 0;
13
+ while (cursor < cleaned.length) {
14
+ const hardEnd = Math.min(cleaned.length, cursor + targetChars);
15
+ let end = hardEnd;
16
+ if (hardEnd < cleaned.length) {
17
+ // Prefer a paragraph break, then a sentence break, then a space.
18
+ const window = cleaned.slice(cursor, hardEnd);
19
+ const lastPara = window.lastIndexOf('\n\n');
20
+ const lastSentence = Math.max(window.lastIndexOf('. '), window.lastIndexOf('! '), window.lastIndexOf('? '), window.lastIndexOf('.\n'));
21
+ const lastSpace = window.lastIndexOf(' ');
22
+ const minBreak = Math.floor(targetChars * 0.5);
23
+ if (lastPara >= minBreak) {
24
+ end = cursor + lastPara + 2;
25
+ }
26
+ else if (lastSentence >= minBreak) {
27
+ end = cursor + lastSentence + 2;
28
+ }
29
+ else if (lastSpace >= minBreak) {
30
+ end = cursor + lastSpace + 1;
31
+ }
32
+ }
33
+ const piece = cleaned.slice(cursor, end).trim();
34
+ if (piece) {
35
+ chunks.push({
36
+ index,
37
+ content: piece,
38
+ approxTokens: Math.max(1, Math.round(piece.length / CHARS_PER_TOKEN)),
39
+ });
40
+ index += 1;
41
+ }
42
+ if (end >= cleaned.length)
43
+ break;
44
+ cursor = Math.max(end - overlapChars, cursor + 1);
45
+ }
46
+ return chunks;
47
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Shared constants for artifact types.
3
+ * Mirrors the Prisma ArtifactType enum to avoid direct type imports
4
+ * in contexts where Prisma client types may not be available.
5
+ */
6
+ export declare const ArtifactType: {
7
+ readonly STUDY_GUIDE: "STUDY_GUIDE";
8
+ readonly FLASHCARD_SET: "FLASHCARD_SET";
9
+ readonly WORKSHEET: "WORKSHEET";
10
+ readonly MEETING_SUMMARY: "MEETING_SUMMARY";
11
+ readonly PODCAST_EPISODE: "PODCAST_EPISODE";
12
+ };
13
+ export type ArtifactTypeValue = (typeof ArtifactType)[keyof typeof ArtifactType];
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Shared constants for artifact types.
3
+ * Mirrors the Prisma ArtifactType enum to avoid direct type imports
4
+ * in contexts where Prisma client types may not be available.
5
+ */
6
+ export const ArtifactType = {
7
+ STUDY_GUIDE: 'STUDY_GUIDE',
8
+ FLASHCARD_SET: 'FLASHCARD_SET',
9
+ WORKSHEET: 'WORKSHEET',
10
+ MEETING_SUMMARY: 'MEETING_SUMMARY',
11
+ PODCAST_EPISODE: 'PODCAST_EPISODE',
12
+ };
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Curated AP & IB knowledge bases seeded on server startup.
3
+ * Each entry uses a stable slug in `meta` so the client can pick icons/colors.
4
+ */
5
+ export interface CuratedKbSeed {
6
+ slug: string;
7
+ name: string;
8
+ description: string;
9
+ category: 'AP' | 'IB';
10
+ subject: string;
11
+ }
12
+ export declare const CURATED_KB_SEEDS: CuratedKbSeed[];