@studious-lms/server 1.13.0 → 1.14.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 (306) hide show
  1. package/.dockerignore +28 -0
  2. package/.env.example +5 -0
  3. package/.github/workflows/deploy.yml +123 -0
  4. package/Dockerfile +54 -0
  5. package/dist/index.js +5 -2
  6. package/dist/index.js.map +1 -1
  7. package/dist/lib/config/cors.d.ts.map +1 -1
  8. package/dist/lib/config/cors.js +31 -11
  9. package/dist/lib/config/cors.js.map +1 -1
  10. package/dist/lib/config/env.d.ts +17 -0
  11. package/dist/lib/config/env.d.ts.map +1 -1
  12. package/dist/lib/config/env.js +8 -2
  13. package/dist/lib/config/env.js.map +1 -1
  14. package/dist/lib/googleCloudStorage.d.ts +10 -0
  15. package/dist/lib/googleCloudStorage.d.ts.map +1 -1
  16. package/dist/lib/googleCloudStorage.js +22 -2
  17. package/dist/lib/googleCloudStorage.js.map +1 -1
  18. package/dist/lib/prisma.d.ts +104 -5
  19. package/dist/lib/prisma.d.ts.map +1 -1
  20. package/dist/lib/prisma.js +33 -2
  21. package/dist/lib/prisma.js.map +1 -1
  22. package/dist/models/agenda.d.ts +20 -20
  23. package/dist/models/announcement.d.ts +177 -69
  24. package/dist/models/announcement.d.ts.map +1 -1
  25. package/dist/models/assignment.d.ts +551 -353
  26. package/dist/models/assignment.d.ts.map +1 -1
  27. package/dist/models/attendance.d.ts +197 -71
  28. package/dist/models/attendance.d.ts.map +1 -1
  29. package/dist/models/auth.d.ts +348 -114
  30. package/dist/models/auth.d.ts.map +1 -1
  31. package/dist/models/class.d.ts +324 -198
  32. package/dist/models/class.d.ts.map +1 -1
  33. package/dist/models/class.js +2 -2
  34. package/dist/models/class.js.map +1 -1
  35. package/dist/models/cloudStorage.d.ts +146 -56
  36. package/dist/models/cloudStorage.d.ts.map +1 -1
  37. package/dist/models/comment.d.ts +267 -115
  38. package/dist/models/comment.d.ts.map +1 -1
  39. package/dist/models/conversation.d.ts +199 -73
  40. package/dist/models/conversation.d.ts.map +1 -1
  41. package/dist/models/department.d.ts +196 -70
  42. package/dist/models/department.d.ts.map +1 -1
  43. package/dist/models/event.d.ts +287 -125
  44. package/dist/models/event.d.ts.map +1 -1
  45. package/dist/models/file.d.ts +389 -263
  46. package/dist/models/file.d.ts.map +1 -1
  47. package/dist/models/folder.d.ts +433 -181
  48. package/dist/models/folder.d.ts.map +1 -1
  49. package/dist/models/labChat.d.ts +209 -83
  50. package/dist/models/labChat.d.ts.map +1 -1
  51. package/dist/models/marketing.d.ts +80 -26
  52. package/dist/models/marketing.d.ts.map +1 -1
  53. package/dist/models/message.d.ts +95 -41
  54. package/dist/models/message.d.ts.map +1 -1
  55. package/dist/models/newtonChat.d.ts +83 -29
  56. package/dist/models/newtonChat.d.ts.map +1 -1
  57. package/dist/models/notification.d.ts +61 -25
  58. package/dist/models/notification.d.ts.map +1 -1
  59. package/dist/models/school.d.ts +349 -133
  60. package/dist/models/school.d.ts.map +1 -1
  61. package/dist/models/section.d.ts +216 -72
  62. package/dist/models/section.d.ts.map +1 -1
  63. package/dist/models/tag.d.ts +156 -48
  64. package/dist/models/tag.d.ts.map +1 -1
  65. package/dist/models/user.d.ts +82 -28
  66. package/dist/models/user.d.ts.map +1 -1
  67. package/dist/models/worksheet.d.ts +1020 -411
  68. package/dist/models/worksheet.d.ts.map +1 -1
  69. package/dist/models/worksheet.js +8 -2
  70. package/dist/models/worksheet.js.map +1 -1
  71. package/dist/pipelines/aiLabChat.d.ts +0 -8
  72. package/dist/pipelines/aiLabChat.d.ts.map +1 -1
  73. package/dist/pipelines/aiLabChat.js +50 -67
  74. package/dist/pipelines/aiLabChat.js.map +1 -1
  75. package/dist/pipelines/aiLabChatContract.d.ts +393 -388
  76. package/dist/pipelines/aiLabChatContract.d.ts.map +1 -1
  77. package/dist/pipelines/aiLabChatContract.js +63 -69
  78. package/dist/pipelines/aiLabChatContract.js.map +1 -1
  79. package/dist/pipelines/aiNewtonChat.d.ts.map +1 -1
  80. package/dist/pipelines/aiNewtonChat.js +41 -41
  81. package/dist/pipelines/aiNewtonChat.js.map +1 -1
  82. package/dist/pipelines/gradeWorksheet.d.ts +8 -8
  83. package/dist/pipelines/labChatPrompt.d.ts +10 -8
  84. package/dist/pipelines/labChatPrompt.d.ts.map +1 -1
  85. package/dist/pipelines/labChatPrompt.js +47 -67
  86. package/dist/pipelines/labChatPrompt.js.map +1 -1
  87. package/dist/pipelines/pdfToWorksheet.d.ts +2 -2
  88. package/dist/routers/_app.d.ts +2203 -1957
  89. package/dist/routers/_app.d.ts.map +1 -1
  90. package/dist/routers/_app.js +4 -2
  91. package/dist/routers/_app.js.map +1 -1
  92. package/dist/routers/admin.d.ts +13 -13
  93. package/dist/routers/agenda.d.ts +18 -18
  94. package/dist/routers/announcement.d.ts +32 -32
  95. package/dist/routers/assignment.d.ts +335 -335
  96. package/dist/routers/attendance.d.ts +10 -10
  97. package/dist/routers/auth.d.ts +2 -2
  98. package/dist/routers/class.d.ts +147 -147
  99. package/dist/routers/comment.d.ts +22 -22
  100. package/dist/routers/conversation.d.ts +17 -17
  101. package/dist/routers/department.d.ts +34 -34
  102. package/dist/routers/discussion.d.ts +65 -53
  103. package/dist/routers/discussion.d.ts.map +1 -1
  104. package/dist/routers/discussion.js +6 -2
  105. package/dist/routers/discussion.js.map +1 -1
  106. package/dist/routers/embedding.d.ts +69 -0
  107. package/dist/routers/embedding.d.ts.map +1 -0
  108. package/dist/routers/embedding.js +143 -0
  109. package/dist/routers/embedding.js.map +1 -0
  110. package/dist/routers/event.d.ts +39 -39
  111. package/dist/routers/file.d.ts +12 -12
  112. package/dist/routers/folder.d.ts +38 -38
  113. package/dist/routers/labChat.d.ts +19 -19
  114. package/dist/routers/marketing.d.ts +2 -2
  115. package/dist/routers/message.d.ts +13 -13
  116. package/dist/routers/newtonChat.d.ts +4 -4
  117. package/dist/routers/notifications.d.ts +9 -9
  118. package/dist/routers/permissions.d.ts +14 -14
  119. package/dist/routers/school.d.ts +55 -55
  120. package/dist/routers/search.d.ts +22 -1
  121. package/dist/routers/search.d.ts.map +1 -1
  122. package/dist/routers/search.js +9 -3
  123. package/dist/routers/search.js.map +1 -1
  124. package/dist/routers/section.d.ts +4 -4
  125. package/dist/routers/studentProgress.d.ts +1 -1
  126. package/dist/routers/tag.d.ts +7 -7
  127. package/dist/routers/user.d.ts +10 -10
  128. package/dist/routers/worksheet.d.ts +95 -57
  129. package/dist/routers/worksheet.d.ts.map +1 -1
  130. package/dist/routers/worksheet.js +26 -2
  131. package/dist/routers/worksheet.js.map +1 -1
  132. package/dist/routes/aiStream.d.ts +2 -0
  133. package/dist/routes/aiStream.d.ts.map +1 -0
  134. package/dist/routes/aiStream.js +696 -0
  135. package/dist/routes/aiStream.js.map +1 -0
  136. package/dist/seedDatabase.d.ts +2 -2
  137. package/dist/seedDatabase.js +6 -6
  138. package/dist/seedDatabase.js.map +1 -1
  139. package/dist/services/adminInstitution.d.ts +8 -8
  140. package/dist/services/adminRunJob.d.ts +4 -4
  141. package/dist/services/agenda.d.ts +18 -18
  142. package/dist/services/aiChatStream.d.ts +68 -0
  143. package/dist/services/aiChatStream.d.ts.map +1 -0
  144. package/dist/services/aiChatStream.js +157 -0
  145. package/dist/services/aiChatStream.js.map +1 -0
  146. package/dist/services/aiModifierTools.d.ts +32 -0
  147. package/dist/services/aiModifierTools.d.ts.map +1 -0
  148. package/dist/services/aiModifierTools.js +165 -0
  149. package/dist/services/aiModifierTools.js.map +1 -0
  150. package/dist/services/aiProposalTools.d.ts +32 -0
  151. package/dist/services/aiProposalTools.d.ts.map +1 -0
  152. package/dist/services/aiProposalTools.js +207 -0
  153. package/dist/services/aiProposalTools.js.map +1 -0
  154. package/dist/services/aiStream.d.ts +22 -0
  155. package/dist/services/aiStream.d.ts.map +1 -0
  156. package/dist/services/aiStream.js +142 -0
  157. package/dist/services/aiStream.js.map +1 -0
  158. package/dist/services/aiTools.d.ts +16 -0
  159. package/dist/services/aiTools.d.ts.map +1 -0
  160. package/dist/services/aiTools.js +271 -0
  161. package/dist/services/aiTools.js.map +1 -0
  162. package/dist/services/announcement.d.ts +12 -12
  163. package/dist/services/announcement.d.ts.map +1 -1
  164. package/dist/services/announcement.js +7 -2
  165. package/dist/services/announcement.js.map +1 -1
  166. package/dist/services/assignment.d.ts +293 -293
  167. package/dist/services/assignment.d.ts.map +1 -1
  168. package/dist/services/assignment.js +28 -9
  169. package/dist/services/assignment.js.map +1 -1
  170. package/dist/services/attendance.d.ts +10 -10
  171. package/dist/services/auth.d.ts +2 -2
  172. package/dist/services/class.d.ts +138 -138
  173. package/dist/services/class.d.ts.map +1 -1
  174. package/dist/services/class.js +19 -3
  175. package/dist/services/class.js.map +1 -1
  176. package/dist/services/comment.d.ts +22 -22
  177. package/dist/services/conversation.d.ts +17 -17
  178. package/dist/services/department.d.ts +33 -33
  179. package/dist/services/discussion.d.ts +58 -58
  180. package/dist/services/discussion.d.ts.map +1 -1
  181. package/dist/services/discussion.js +8 -8
  182. package/dist/services/discussion.js.map +1 -1
  183. package/dist/services/discussionSummary.d.ts +21 -0
  184. package/dist/services/discussionSummary.d.ts.map +1 -0
  185. package/dist/services/discussionSummary.js +179 -0
  186. package/dist/services/discussionSummary.js.map +1 -0
  187. package/dist/services/embedding.d.ts +67 -0
  188. package/dist/services/embedding.d.ts.map +1 -0
  189. package/dist/services/embedding.js +226 -0
  190. package/dist/services/embedding.js.map +1 -0
  191. package/dist/services/event.d.ts +37 -37
  192. package/dist/services/file.d.ts +24 -24
  193. package/dist/services/folder.d.ts +36 -36
  194. package/dist/services/labChat.d.ts +19 -19
  195. package/dist/services/marketing.d.ts +2 -2
  196. package/dist/services/message.d.ts +11 -11
  197. package/dist/services/message.d.ts.map +1 -1
  198. package/dist/services/message.js +2 -2
  199. package/dist/services/message.js.map +1 -1
  200. package/dist/services/newtonChat.d.ts +4 -4
  201. package/dist/services/notification.d.ts +9 -9
  202. package/dist/services/notification.d.ts.map +1 -1
  203. package/dist/services/permissions.d.ts +14 -14
  204. package/dist/services/school.d.ts +50 -50
  205. package/dist/services/search.d.ts +12 -0
  206. package/dist/services/search.d.ts.map +1 -1
  207. package/dist/services/search.js +120 -2
  208. package/dist/services/search.js.map +1 -1
  209. package/dist/services/section.d.ts +3 -3
  210. package/dist/services/tag.d.ts +4 -4
  211. package/dist/services/user.d.ts +4 -4
  212. package/dist/services/user.d.ts.map +1 -1
  213. package/dist/services/user.js +10 -15
  214. package/dist/services/user.js.map +1 -1
  215. package/dist/services/worksheet.d.ts +60 -48
  216. package/dist/services/worksheet.d.ts.map +1 -1
  217. package/dist/services/worksheet.js +11 -4
  218. package/dist/services/worksheet.js.map +1 -1
  219. package/dist/utils/streamBroadcast.d.ts +11 -0
  220. package/dist/utils/streamBroadcast.d.ts.map +1 -0
  221. package/dist/utils/streamBroadcast.js +32 -0
  222. package/dist/utils/streamBroadcast.js.map +1 -0
  223. package/dist/workers/connection.d.ts +15 -0
  224. package/dist/workers/connection.d.ts.map +1 -1
  225. package/dist/workers/connection.js +20 -2
  226. package/dist/workers/connection.js.map +1 -1
  227. package/dist/workers/index.js +4 -2
  228. package/dist/workers/index.js.map +1 -1
  229. package/dist/workers/processors/createRunJobWorker.d.ts.map +1 -1
  230. package/dist/workers/processors/createRunJobWorker.js +31 -8
  231. package/dist/workers/processors/createRunJobWorker.js.map +1 -1
  232. package/dist/workers/processors/embedContent.d.ts +8 -0
  233. package/dist/workers/processors/embedContent.d.ts.map +1 -0
  234. package/dist/workers/processors/embedContent.js +76 -0
  235. package/dist/workers/processors/embedContent.js.map +1 -0
  236. package/dist/workers/queues.d.ts +6 -0
  237. package/dist/workers/queues.d.ts.map +1 -1
  238. package/dist/workers/queues.js +5 -3
  239. package/dist/workers/queues.js.map +1 -1
  240. package/package.json +5 -1
  241. package/prisma/migrations/20260609215135_init/migration.sql +1412 -0
  242. package/prisma/migrations/20260610130000_add_worksheet_tags/migration.sql +13 -0
  243. package/prisma/schema.prisma +38 -7
  244. package/src/index.ts +4 -0
  245. package/src/lib/config/cors.ts +32 -9
  246. package/src/lib/config/env.ts +6 -0
  247. package/src/lib/googleCloudStorage.ts +21 -0
  248. package/src/lib/prisma.ts +40 -1
  249. package/src/models/class.ts +3 -2
  250. package/src/models/worksheet.ts +5 -2
  251. package/src/pipelines/aiLabChat.ts +54 -79
  252. package/src/pipelines/aiLabChatContract.ts +69 -69
  253. package/src/pipelines/aiNewtonChat.ts +46 -43
  254. package/src/pipelines/labChatPrompt.ts +63 -88
  255. package/src/routers/_app.ts +2 -0
  256. package/src/routers/discussion.ts +7 -0
  257. package/src/routers/embedding.ts +159 -0
  258. package/src/routers/search.ts +10 -1
  259. package/src/routers/worksheet.ts +27 -0
  260. package/src/routes/aiStream.ts +789 -0
  261. package/src/seedDatabase.ts +4 -4
  262. package/src/services/aiChatStream.ts +219 -0
  263. package/src/services/aiModifierTools.ts +188 -0
  264. package/src/services/aiProposalTools.ts +272 -0
  265. package/src/services/aiStream.ts +175 -0
  266. package/src/services/aiTools.ts +290 -0
  267. package/src/services/announcement.ts +7 -0
  268. package/src/services/assignment.ts +28 -7
  269. package/src/services/class.ts +20 -1
  270. package/src/services/discussion.ts +9 -8
  271. package/src/services/discussionSummary.ts +226 -0
  272. package/src/services/embedding.ts +285 -0
  273. package/src/services/message.ts +2 -2
  274. package/src/services/search.ts +138 -0
  275. package/src/services/user.ts +9 -17
  276. package/src/services/worksheet.ts +9 -2
  277. package/src/utils/streamBroadcast.ts +48 -0
  278. package/src/workers/connection.ts +19 -0
  279. package/src/workers/index.ts +2 -0
  280. package/src/workers/processors/createRunJobWorker.ts +32 -6
  281. package/src/workers/processors/embedContent.ts +90 -0
  282. package/src/workers/queues.ts +5 -1
  283. package/tests/unit/pipelines/aiLabChatContract.test.ts +38 -21
  284. package/tests/unit/pipelines/labChatPrompt.test.ts +23 -36
  285. package/prisma/migrations/20250807062924_init/migration.sql +0 -436
  286. package/prisma/migrations/20250919063704_init2/migration.sql +0 -24
  287. package/prisma/migrations/20250920143543_add_profile_fields/migration.sql +0 -15
  288. package/prisma/migrations/20250922165147_add_chat_models/migration.sql +0 -68
  289. package/prisma/migrations/20250922165314_add_chat_roles/migration.sql +0 -5
  290. package/prisma/migrations/20250922171242_refactor_notification_system/migration.sql +0 -20
  291. package/prisma/migrations/20250922172208_add_mentions_system/migration.sql +0 -21
  292. package/prisma/migrations/20250925072732_add_lab_chat_system/migration.sql +0 -25
  293. package/prisma/migrations/20251020151505_add_upload_tracking_fields/migration.sql +0 -57
  294. package/prisma/migrations/20251109122857_annuoncements_comments/migration.sql +0 -30
  295. package/prisma/migrations/20251109135555_reactions_announcements_comments/migration.sql +0 -35
  296. package/prisma/migrations/20260410124000_add_submission_recommendation_state/migration.sql +0 -14
  297. package/prisma/migrations/20260415103500_add_session_type/migration.sql +0 -33
  298. package/prisma/migrations/20260415133000_add_ai_usage_logs/migration.sql +0 -19
  299. package/prisma/migrations/20260417083000_add_conversation_member_hidden_at/migration.sql +0 -2
  300. package/prisma/migrations/20260502230500_assignment_submission_comments/migration.sql +0 -60
  301. package/prisma/migrations/20260504071500_school_memberships/migration.sql +0 -81
  302. package/prisma/migrations/20260506162500_consolidate_run_job_and_unify_job_status/migration.sql +0 -166
  303. package/prisma/migrations/20260509220000_institution_overhaul/migration.sql +0 -184
  304. package/prisma/migrations/20260510170000_add_folder_permissions/migration.sql +0 -93
  305. package/prisma/migrations/20260510183000_add_discussions/migration.sql +0 -151
  306. /package/.github/workflows/{npm.yml → npm-publish.yml} +0 -0
@@ -0,0 +1,226 @@
1
+ /**
2
+ * Embedding service – pgvector-backed RAG for class materials.
3
+ * Handles text chunking, embedding generation, storage, and semantic search.
4
+ */
5
+
6
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="684f6339-11e3-5a32-a920-de2f3c9797e6")}catch(e){}}();
7
+ import { prisma } from '../lib/prisma.js';
8
+ import { openAIClient } from '../utils/inference.js';
9
+ import { logger } from '../utils/logger.js';
10
+ import { enqueueRunJob } from '../workers/queues.js';
11
+ const EMBEDDING_MODEL = 'text-embedding-3-small';
12
+ const EMBEDDING_DIMENSIONS = 1536;
13
+ const CHUNK_SIZE = 512; // tokens (~2048 chars)
14
+ const CHUNK_OVERLAP = 100; // tokens (~400 chars)
15
+ const CHARS_PER_TOKEN = 4;
16
+ /**
17
+ * Split text into overlapping chunks for embedding.
18
+ */
19
+ export function chunkText(text, chunkSize = CHUNK_SIZE, overlap = CHUNK_OVERLAP) {
20
+ const maxChars = chunkSize * CHARS_PER_TOKEN;
21
+ const overlapChars = overlap * CHARS_PER_TOKEN;
22
+ if (text.length <= maxChars) {
23
+ return [text];
24
+ }
25
+ const chunks = [];
26
+ let start = 0;
27
+ while (start < text.length) {
28
+ const end = Math.min(start + maxChars, text.length);
29
+ chunks.push(text.slice(start, end));
30
+ if (end >= text.length)
31
+ break;
32
+ start = end - overlapChars;
33
+ }
34
+ return chunks;
35
+ }
36
+ /**
37
+ * Generate embedding vector for a text string.
38
+ */
39
+ export async function generateEmbedding(text) {
40
+ const response = await openAIClient.embeddings.create({
41
+ model: EMBEDDING_MODEL,
42
+ input: text,
43
+ dimensions: EMBEDDING_DIMENSIONS,
44
+ });
45
+ return response.data[0].embedding;
46
+ }
47
+ /**
48
+ * Generate embeddings for multiple texts in a single batch.
49
+ */
50
+ export async function generateEmbeddings(texts) {
51
+ if (texts.length === 0)
52
+ return [];
53
+ const response = await openAIClient.embeddings.create({
54
+ model: EMBEDDING_MODEL,
55
+ input: texts,
56
+ dimensions: EMBEDDING_DIMENSIONS,
57
+ });
58
+ return response.data
59
+ .sort((a, b) => a.index - b.index)
60
+ .map((item) => item.embedding);
61
+ }
62
+ /**
63
+ * Store embeddings for a source document. Replaces any existing embeddings for
64
+ * the same sourceType + sourceId combination.
65
+ */
66
+ export async function indexContent(params) {
67
+ const { classId, sourceType, sourceId, text, metadata = {} } = params;
68
+ // Remove existing embeddings for this source
69
+ await prisma.embedding.deleteMany({
70
+ where: { classId, sourceType, sourceId },
71
+ });
72
+ const chunks = chunkText(text);
73
+ if (chunks.length === 0)
74
+ return 0;
75
+ const embeddings = await generateEmbeddings(chunks);
76
+ // Insert using raw SQL for pgvector support
77
+ for (let i = 0; i < chunks.length; i++) {
78
+ const vectorStr = `[${embeddings[i].join(',')}]`;
79
+ const chunkMetadata = { ...metadata, chunkIndex: i, totalChunks: chunks.length };
80
+ await prisma.$executeRaw `
81
+ INSERT INTO "Embedding" (id, "classId", "sourceType", "sourceId", content, vector, metadata, "createdAt")
82
+ VALUES (
83
+ gen_random_uuid(),
84
+ ${classId},
85
+ ${sourceType}::"EmbeddingSourceType",
86
+ ${sourceId},
87
+ ${chunks[i]},
88
+ ${vectorStr}::vector,
89
+ ${JSON.stringify(chunkMetadata)}::jsonb,
90
+ NOW()
91
+ )
92
+ `;
93
+ }
94
+ logger.info('Content indexed', { classId, sourceType, sourceId, chunks: chunks.length });
95
+ return chunks.length;
96
+ }
97
+ /**
98
+ * Semantic search over class embeddings using cosine similarity.
99
+ */
100
+ export async function searchEmbeddings(params) {
101
+ const { classId, query, limit = 5, sourceTypes } = params;
102
+ const queryEmbedding = await generateEmbedding(query);
103
+ const vectorStr = `[${queryEmbedding.join(',')}]`;
104
+ let results;
105
+ if (sourceTypes && sourceTypes.length > 0) {
106
+ results = await prisma.$queryRaw `
107
+ SELECT
108
+ id,
109
+ "sourceType",
110
+ "sourceId",
111
+ content,
112
+ metadata,
113
+ 1 - (vector <=> ${vectorStr}::vector) as similarity
114
+ FROM "Embedding"
115
+ WHERE "classId" = ${classId}
116
+ AND "sourceType" = ANY(${sourceTypes}::"EmbeddingSourceType"[])
117
+ ORDER BY vector <=> ${vectorStr}::vector
118
+ LIMIT ${limit}
119
+ `;
120
+ }
121
+ else {
122
+ results = await prisma.$queryRaw `
123
+ SELECT
124
+ id,
125
+ "sourceType",
126
+ "sourceId",
127
+ content,
128
+ metadata,
129
+ 1 - (vector <=> ${vectorStr}::vector) as similarity
130
+ FROM "Embedding"
131
+ WHERE "classId" = ${classId}
132
+ ORDER BY vector <=> ${vectorStr}::vector
133
+ LIMIT ${limit}
134
+ `;
135
+ }
136
+ return results;
137
+ }
138
+ /**
139
+ * Remove all embeddings for a given source.
140
+ */
141
+ export async function removeEmbeddings(params) {
142
+ await prisma.embedding.deleteMany({
143
+ where: {
144
+ classId: params.classId,
145
+ sourceType: params.sourceType,
146
+ sourceId: params.sourceId,
147
+ },
148
+ });
149
+ }
150
+ /**
151
+ * Index an assignment (title + instructions) into the vector store.
152
+ */
153
+ export async function indexAssignment(classId, assignmentId) {
154
+ const assignment = await prisma.assignment.findUnique({
155
+ where: { id: assignmentId },
156
+ select: { title: true, instructions: true, type: true },
157
+ });
158
+ if (!assignment)
159
+ return;
160
+ const text = [
161
+ `Title: ${assignment.title}`,
162
+ `Type: ${assignment.type}`,
163
+ assignment.instructions ? `Instructions: ${assignment.instructions}` : '',
164
+ ].filter(Boolean).join('\n');
165
+ await indexContent({
166
+ classId,
167
+ sourceType: 'ASSIGNMENT',
168
+ sourceId: assignmentId,
169
+ text,
170
+ metadata: { title: assignment.title, type: assignment.type },
171
+ });
172
+ }
173
+ /**
174
+ * Index a worksheet (questions + answers) into the vector store.
175
+ */
176
+ export async function indexWorksheet(classId, worksheetId) {
177
+ const worksheet = await prisma.worksheet.findUnique({
178
+ where: { id: worksheetId },
179
+ include: { questions: true },
180
+ });
181
+ if (!worksheet)
182
+ return;
183
+ const questionTexts = worksheet.questions.map((q, i) => `Question ${i + 1} (${q.type}): ${q.question}\nAnswer: ${q.answer}`);
184
+ const text = [
185
+ `Worksheet: ${worksheet.name}`,
186
+ ...questionTexts,
187
+ ].join('\n\n');
188
+ await indexContent({
189
+ classId,
190
+ sourceType: 'WORKSHEET',
191
+ sourceId: worksheetId,
192
+ text,
193
+ metadata: { name: worksheet.name, questionCount: worksheet.questions.length },
194
+ });
195
+ }
196
+ /**
197
+ * Index an announcement into the vector store.
198
+ */
199
+ export async function indexAnnouncement(classId, announcementId) {
200
+ const announcement = await prisma.announcement.findUnique({
201
+ where: { id: announcementId },
202
+ select: { remarks: true, teacherId: true },
203
+ });
204
+ if (!announcement || !announcement.remarks)
205
+ return;
206
+ const text = `Announcement: ${announcement.remarks}`;
207
+ await indexContent({
208
+ classId,
209
+ sourceType: 'ANNOUNCEMENT',
210
+ sourceId: announcementId,
211
+ text,
212
+ metadata: { teacherId: announcement.teacherId },
213
+ });
214
+ }
215
+ /**
216
+ * Fire-and-forget: enqueue a background job to embed content.
217
+ * Safe to call from service functions after a create/update.
218
+ */
219
+ export function enqueueEmbedding(classId, sourceType, sourceId) {
220
+ enqueueRunJob('EMBED_CONTENT', { classId, sourceType: sourceType, sourceId }, { classId })
221
+ .catch((err) => {
222
+ logger.error('Failed to enqueue embedding job', { err, classId, sourceType, sourceId });
223
+ });
224
+ }
225
+ //# sourceMappingURL=embedding.js.map
226
+ //# debugId=684f6339-11e3-5a32-a920-de2f3c9797e6
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedding.js","sources":["services/embedding.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Embedding service – pgvector-backed RAG for class materials.\n * Handles text chunking, embedding generation, storage, and semantic search.\n */\nimport { prisma } from '../lib/prisma.js';\nimport { openAIClient } from '../utils/inference.js';\nimport { logger } from '../utils/logger.js';\nimport { enqueueRunJob } from '../workers/queues.js';\nimport type { EmbeddingSourceType } from '@prisma/client';\n\nconst EMBEDDING_MODEL = 'text-embedding-3-small';\nconst EMBEDDING_DIMENSIONS = 1536;\nconst CHUNK_SIZE = 512; // tokens (~2048 chars)\nconst CHUNK_OVERLAP = 100; // tokens (~400 chars)\nconst CHARS_PER_TOKEN = 4;\n\nexport interface EmbeddingSearchResult {\n id: string;\n sourceType: EmbeddingSourceType;\n sourceId: string;\n content: string;\n metadata: Record<string, unknown>;\n similarity: number;\n}\n\n/**\n * Split text into overlapping chunks for embedding.\n */\nexport function chunkText(text: string, chunkSize = CHUNK_SIZE, overlap = CHUNK_OVERLAP): string[] {\n const maxChars = chunkSize * CHARS_PER_TOKEN;\n const overlapChars = overlap * CHARS_PER_TOKEN;\n\n if (text.length <= maxChars) {\n return [text];\n }\n\n const chunks: string[] = [];\n let start = 0;\n\n while (start < text.length) {\n const end = Math.min(start + maxChars, text.length);\n chunks.push(text.slice(start, end));\n\n if (end >= text.length) break;\n start = end - overlapChars;\n }\n\n return chunks;\n}\n\n/**\n * Generate embedding vector for a text string.\n */\nexport async function generateEmbedding(text: string): Promise<number[]> {\n const response = await openAIClient.embeddings.create({\n model: EMBEDDING_MODEL,\n input: text,\n dimensions: EMBEDDING_DIMENSIONS,\n });\n\n return response.data[0].embedding;\n}\n\n/**\n * Generate embeddings for multiple texts in a single batch.\n */\nexport async function generateEmbeddings(texts: string[]): Promise<number[][]> {\n if (texts.length === 0) return [];\n\n const response = await openAIClient.embeddings.create({\n model: EMBEDDING_MODEL,\n input: texts,\n dimensions: EMBEDDING_DIMENSIONS,\n });\n\n return response.data\n .sort((a, b) => a.index - b.index)\n .map((item) => item.embedding);\n}\n\n/**\n * Store embeddings for a source document. Replaces any existing embeddings for\n * the same sourceType + sourceId combination.\n */\nexport async function indexContent(params: {\n classId: string;\n sourceType: EmbeddingSourceType;\n sourceId: string;\n text: string;\n metadata?: Record<string, unknown>;\n}): Promise<number> {\n const { classId, sourceType, sourceId, text, metadata = {} } = params;\n\n // Remove existing embeddings for this source\n await prisma.embedding.deleteMany({\n where: { classId, sourceType, sourceId },\n });\n\n const chunks = chunkText(text);\n if (chunks.length === 0) return 0;\n\n const embeddings = await generateEmbeddings(chunks);\n\n // Insert using raw SQL for pgvector support\n for (let i = 0; i < chunks.length; i++) {\n const vectorStr = `[${embeddings[i].join(',')}]`;\n const chunkMetadata = { ...metadata, chunkIndex: i, totalChunks: chunks.length };\n\n await prisma.$executeRaw`\n INSERT INTO \"Embedding\" (id, \"classId\", \"sourceType\", \"sourceId\", content, vector, metadata, \"createdAt\")\n VALUES (\n gen_random_uuid(),\n ${classId},\n ${sourceType}::\"EmbeddingSourceType\",\n ${sourceId},\n ${chunks[i]},\n ${vectorStr}::vector,\n ${JSON.stringify(chunkMetadata)}::jsonb,\n NOW()\n )\n `;\n }\n\n logger.info('Content indexed', { classId, sourceType, sourceId, chunks: chunks.length });\n return chunks.length;\n}\n\n/**\n * Semantic search over class embeddings using cosine similarity.\n */\nexport async function searchEmbeddings(params: {\n classId: string;\n query: string;\n limit?: number;\n sourceTypes?: EmbeddingSourceType[];\n}): Promise<EmbeddingSearchResult[]> {\n const { classId, query, limit = 5, sourceTypes } = params;\n\n const queryEmbedding = await generateEmbedding(query);\n const vectorStr = `[${queryEmbedding.join(',')}]`;\n\n let results: EmbeddingSearchResult[];\n\n if (sourceTypes && sourceTypes.length > 0) {\n results = await prisma.$queryRaw<EmbeddingSearchResult[]>`\n SELECT\n id,\n \"sourceType\",\n \"sourceId\",\n content,\n metadata,\n 1 - (vector <=> ${vectorStr}::vector) as similarity\n FROM \"Embedding\"\n WHERE \"classId\" = ${classId}\n AND \"sourceType\" = ANY(${sourceTypes}::\"EmbeddingSourceType\"[])\n ORDER BY vector <=> ${vectorStr}::vector\n LIMIT ${limit}\n `;\n } else {\n results = await prisma.$queryRaw<EmbeddingSearchResult[]>`\n SELECT\n id,\n \"sourceType\",\n \"sourceId\",\n content,\n metadata,\n 1 - (vector <=> ${vectorStr}::vector) as similarity\n FROM \"Embedding\"\n WHERE \"classId\" = ${classId}\n ORDER BY vector <=> ${vectorStr}::vector\n LIMIT ${limit}\n `;\n }\n\n return results;\n}\n\n/**\n * Remove all embeddings for a given source.\n */\nexport async function removeEmbeddings(params: {\n classId: string;\n sourceType: EmbeddingSourceType;\n sourceId: string;\n}): Promise<void> {\n await prisma.embedding.deleteMany({\n where: {\n classId: params.classId,\n sourceType: params.sourceType,\n sourceId: params.sourceId,\n },\n });\n}\n\n/**\n * Index an assignment (title + instructions) into the vector store.\n */\nexport async function indexAssignment(classId: string, assignmentId: string): Promise<void> {\n const assignment = await prisma.assignment.findUnique({\n where: { id: assignmentId },\n select: { title: true, instructions: true, type: true },\n });\n\n if (!assignment) return;\n\n const text = [\n `Title: ${assignment.title}`,\n `Type: ${assignment.type}`,\n assignment.instructions ? `Instructions: ${assignment.instructions}` : '',\n ].filter(Boolean).join('\\n');\n\n await indexContent({\n classId,\n sourceType: 'ASSIGNMENT',\n sourceId: assignmentId,\n text,\n metadata: { title: assignment.title, type: assignment.type },\n });\n}\n\n/**\n * Index a worksheet (questions + answers) into the vector store.\n */\nexport async function indexWorksheet(classId: string, worksheetId: string): Promise<void> {\n const worksheet = await prisma.worksheet.findUnique({\n where: { id: worksheetId },\n include: { questions: true },\n });\n\n if (!worksheet) return;\n\n const questionTexts = worksheet.questions.map((q, i) =>\n `Question ${i + 1} (${q.type}): ${q.question}\\nAnswer: ${q.answer}`\n );\n\n const text = [\n `Worksheet: ${worksheet.name}`,\n ...questionTexts,\n ].join('\\n\\n');\n\n await indexContent({\n classId,\n sourceType: 'WORKSHEET',\n sourceId: worksheetId,\n text,\n metadata: { name: worksheet.name, questionCount: worksheet.questions.length },\n });\n}\n\n/**\n * Index an announcement into the vector store.\n */\nexport async function indexAnnouncement(classId: string, announcementId: string): Promise<void> {\n const announcement = await prisma.announcement.findUnique({\n where: { id: announcementId },\n select: { remarks: true, teacherId: true },\n });\n\n if (!announcement || !announcement.remarks) return;\n\n const text = `Announcement: ${announcement.remarks}`;\n\n await indexContent({\n classId,\n sourceType: 'ANNOUNCEMENT',\n sourceId: announcementId,\n text,\n metadata: { teacherId: announcement.teacherId },\n });\n}\n\n/**\n * Fire-and-forget: enqueue a background job to embed content.\n * Safe to call from service functions after a create/update.\n */\nexport function enqueueEmbedding(\n classId: string,\n sourceType: EmbeddingSourceType,\n sourceId: string,\n): void {\n enqueueRunJob('EMBED_CONTENT', { classId, sourceType: sourceType as string, sourceId }, { classId })\n .catch((err) => {\n logger.error('Failed to enqueue embedding job', { err, classId, sourceType, sourceId });\n });\n}\n"],"names":[],"mappings":"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","debug_id":"684f6339-11e3-5a32-a920-de2f3c9797e6"}
@@ -18,24 +18,24 @@ export declare function getEvent(userId: string, id: string): Promise<{
18
18
  userId: string;
19
19
  }[];
20
20
  } & {
21
- name: string;
22
21
  id: string;
22
+ createdAt: Date;
23
+ updatedAt: Date;
24
+ name: string;
23
25
  description: string | null;
24
26
  logoId: string | null;
25
27
  subdomain: string | null;
26
- createdAt: Date;
27
- updatedAt: Date;
28
28
  }) | null;
29
29
  teachers: {
30
30
  id: string;
31
31
  }[];
32
32
  } & {
33
- name: string;
33
+ section: string;
34
34
  id: string;
35
+ name: string;
35
36
  schoolId: string | null;
36
- subject: string;
37
37
  color: string | null;
38
- section: string;
38
+ subject: string;
39
39
  syllabus: string | null;
40
40
  departmentId: string | null;
41
41
  discussionsEnabled: boolean;
@@ -44,16 +44,16 @@ export declare function getEvent(userId: string, id: string): Promise<{
44
44
  }) | null;
45
45
  assignmentsAttached: {
46
46
  type: import(".prisma/client").$Enums.AssignmentType;
47
- id: string;
48
47
  section: {
49
- name: string;
50
48
  id: string;
49
+ name: string;
51
50
  } | null;
51
+ id: string;
52
52
  title: string;
53
- instructions: string;
54
53
  dueDate: Date;
55
- graded: boolean;
56
54
  maxGrade: number | null;
55
+ instructions: string;
56
+ graded: boolean;
57
57
  weight: number;
58
58
  teacher: {
59
59
  id: string;
@@ -61,19 +61,19 @@ export declare function getEvent(userId: string, id: string): Promise<{
61
61
  };
62
62
  attachments: {
63
63
  type: string;
64
- name: string;
65
64
  id: string;
65
+ name: string;
66
66
  }[];
67
67
  }[];
68
68
  } & {
69
- name: string | null;
70
69
  id: string;
71
70
  userId: string | null;
71
+ location: string | null;
72
+ name: string | null;
72
73
  color: string | null;
73
74
  classId: string | null;
74
75
  startTime: Date;
75
76
  endTime: Date;
76
- location: string | null;
77
77
  remarks: string | null;
78
78
  };
79
79
  }>;
@@ -88,18 +88,18 @@ export declare function createEventRecord(userId: string, input: {
88
88
  color?: string;
89
89
  }): Promise<{
90
90
  event: {
91
- name: string | null;
92
- id: string;
93
- userId: string | null;
94
91
  class: {
95
- name: string;
96
92
  id: string;
93
+ name: string;
97
94
  } | null;
95
+ id: string;
96
+ userId: string | null;
97
+ location: string | null;
98
+ name: string | null;
98
99
  color: string | null;
99
100
  classId: string | null;
100
101
  startTime: Date;
101
102
  endTime: Date;
102
- location: string | null;
103
103
  remarks: string | null;
104
104
  };
105
105
  }>;
@@ -113,14 +113,14 @@ export declare function updateEventRecord(userId: string, id: string, data: {
113
113
  classId?: string;
114
114
  }): Promise<{
115
115
  event: {
116
- name: string | null;
117
116
  id: string;
118
117
  userId: string | null;
118
+ location: string | null;
119
+ name: string | null;
119
120
  color: string | null;
120
121
  classId: string | null;
121
122
  startTime: Date;
122
123
  endTime: Date;
123
- location: string | null;
124
124
  remarks: string | null;
125
125
  };
126
126
  }>;
@@ -130,8 +130,8 @@ export declare function deleteEventRecord(userId: string, id: string): Promise<{
130
130
  export declare function attachAssignment(userId: string, eventId: string, assignmentId: string): Promise<{
131
131
  assignment: {
132
132
  section: {
133
- name: string;
134
133
  id: string;
134
+ name: string;
135
135
  } | null;
136
136
  teacher: {
137
137
  id: string;
@@ -139,18 +139,20 @@ export declare function attachAssignment(userId: string, eventId: string, assign
139
139
  };
140
140
  attachments: {
141
141
  type: string;
142
- name: string;
143
142
  id: string;
143
+ name: string;
144
144
  }[];
145
145
  } & {
146
146
  type: import(".prisma/client").$Enums.AssignmentType;
147
147
  id: string;
148
148
  createdAt: Date | null;
149
149
  classId: string;
150
- modifiedAt: Date | null;
151
150
  title: string;
152
- instructions: string;
153
151
  dueDate: Date;
152
+ maxGrade: number | null;
153
+ eventId: string | null;
154
+ instructions: string;
155
+ modifiedAt: Date | null;
154
156
  teacherId: string;
155
157
  acceptFiles: boolean;
156
158
  acceptExtendedResponse: boolean;
@@ -159,11 +161,9 @@ export declare function attachAssignment(userId: string, eventId: string, assign
159
161
  aiPolicyLevel: number;
160
162
  sectionId: string | null;
161
163
  graded: boolean;
162
- maxGrade: number | null;
163
164
  weight: number;
164
165
  inProgress: boolean;
165
166
  template: boolean;
166
- eventId: string | null;
167
167
  markSchemeId: string | null;
168
168
  order: number | null;
169
169
  gradingBoundaryId: string | null;
@@ -172,8 +172,8 @@ export declare function attachAssignment(userId: string, eventId: string, assign
172
172
  export declare function detachAssignment(userId: string, eventId: string, assignmentId: string): Promise<{
173
173
  assignment: {
174
174
  section: {
175
- name: string;
176
175
  id: string;
176
+ name: string;
177
177
  } | null;
178
178
  teacher: {
179
179
  id: string;
@@ -181,18 +181,20 @@ export declare function detachAssignment(userId: string, eventId: string, assign
181
181
  };
182
182
  attachments: {
183
183
  type: string;
184
- name: string;
185
184
  id: string;
185
+ name: string;
186
186
  }[];
187
187
  } & {
188
188
  type: import(".prisma/client").$Enums.AssignmentType;
189
189
  id: string;
190
190
  createdAt: Date | null;
191
191
  classId: string;
192
- modifiedAt: Date | null;
193
192
  title: string;
194
- instructions: string;
195
193
  dueDate: Date;
194
+ maxGrade: number | null;
195
+ eventId: string | null;
196
+ instructions: string;
197
+ modifiedAt: Date | null;
196
198
  teacherId: string;
197
199
  acceptFiles: boolean;
198
200
  acceptExtendedResponse: boolean;
@@ -201,11 +203,9 @@ export declare function detachAssignment(userId: string, eventId: string, assign
201
203
  aiPolicyLevel: number;
202
204
  sectionId: string | null;
203
205
  graded: boolean;
204
- maxGrade: number | null;
205
206
  weight: number;
206
207
  inProgress: boolean;
207
208
  template: boolean;
208
- eventId: string | null;
209
209
  markSchemeId: string | null;
210
210
  order: number | null;
211
211
  gradingBoundaryId: string | null;
@@ -214,16 +214,16 @@ export declare function detachAssignment(userId: string, eventId: string, assign
214
214
  export declare function getAvailableAssignments(userId: string, eventId: string): Promise<{
215
215
  assignments: {
216
216
  type: import(".prisma/client").$Enums.AssignmentType;
217
- id: string;
218
217
  section: {
219
- name: string;
220
218
  id: string;
219
+ name: string;
221
220
  } | null;
221
+ id: string;
222
222
  title: string;
223
- instructions: string;
224
223
  dueDate: Date;
225
- graded: boolean;
226
224
  maxGrade: number | null;
225
+ instructions: string;
226
+ graded: boolean;
227
227
  weight: number;
228
228
  teacher: {
229
229
  id: string;
@@ -231,8 +231,8 @@ export declare function getAvailableAssignments(userId: string, eventId: string)
231
231
  };
232
232
  attachments: {
233
233
  type: string;
234
- name: string;
235
234
  id: string;
235
+ name: string;
236
236
  }[];
237
237
  }[];
238
238
  }>;
@@ -27,12 +27,15 @@ export declare function moveFile(fileId: string, targetFolderId: string): Promis
27
27
  } & {
28
28
  path: string;
29
29
  type: string;
30
- name: string;
31
30
  id: string;
32
31
  userId: string | null;
33
- folderId: string | null;
32
+ name: string;
34
33
  size: number | null;
35
34
  uploadedAt: Date | null;
35
+ assignmentId: string | null;
36
+ submissionId: string | null;
37
+ thumbnailId: string | null;
38
+ annotationId: string | null;
36
39
  uploadStatus: import(".prisma/client").$Enums.UploadStatus;
37
40
  uploadUrl: string | null;
38
41
  uploadExpiresAt: Date | null;
@@ -42,11 +45,8 @@ export declare function moveFile(fileId: string, targetFolderId: string): Promis
42
45
  uploadRetryCount: number;
43
46
  isOrphaned: boolean;
44
47
  cleanupAt: Date | null;
45
- thumbnailId: string | null;
46
- assignmentId: string | null;
47
- submissionId: string | null;
48
- annotationId: string | null;
49
48
  classDraftId: string | null;
49
+ folderId: string | null;
50
50
  conversationId: string | null;
51
51
  messageId: string | null;
52
52
  announcementId: string | null;
@@ -62,12 +62,15 @@ export declare function renameFile(fileId: string, newName: string): Promise<{
62
62
  } & {
63
63
  path: string;
64
64
  type: string;
65
- name: string;
66
65
  id: string;
67
66
  userId: string | null;
68
- folderId: string | null;
67
+ name: string;
69
68
  size: number | null;
70
69
  uploadedAt: Date | null;
70
+ assignmentId: string | null;
71
+ submissionId: string | null;
72
+ thumbnailId: string | null;
73
+ annotationId: string | null;
71
74
  uploadStatus: import(".prisma/client").$Enums.UploadStatus;
72
75
  uploadUrl: string | null;
73
76
  uploadExpiresAt: Date | null;
@@ -77,11 +80,8 @@ export declare function renameFile(fileId: string, newName: string): Promise<{
77
80
  uploadRetryCount: number;
78
81
  isOrphaned: boolean;
79
82
  cleanupAt: Date | null;
80
- thumbnailId: string | null;
81
- assignmentId: string | null;
82
- submissionId: string | null;
83
- annotationId: string | null;
84
83
  classDraftId: string | null;
84
+ folderId: string | null;
85
85
  conversationId: string | null;
86
86
  messageId: string | null;
87
87
  announcementId: string | null;
@@ -107,12 +107,15 @@ export declare function moveFileScoped(userId: string, input: {
107
107
  } & {
108
108
  path: string;
109
109
  type: string;
110
- name: string;
111
110
  id: string;
112
111
  userId: string | null;
113
- folderId: string | null;
112
+ name: string;
114
113
  size: number | null;
115
114
  uploadedAt: Date | null;
115
+ assignmentId: string | null;
116
+ submissionId: string | null;
117
+ thumbnailId: string | null;
118
+ annotationId: string | null;
116
119
  uploadStatus: import(".prisma/client").$Enums.UploadStatus;
117
120
  uploadUrl: string | null;
118
121
  uploadExpiresAt: Date | null;
@@ -122,11 +125,8 @@ export declare function moveFileScoped(userId: string, input: {
122
125
  uploadRetryCount: number;
123
126
  isOrphaned: boolean;
124
127
  cleanupAt: Date | null;
125
- thumbnailId: string | null;
126
- assignmentId: string | null;
127
- submissionId: string | null;
128
- annotationId: string | null;
129
128
  classDraftId: string | null;
129
+ folderId: string | null;
130
130
  conversationId: string | null;
131
131
  messageId: string | null;
132
132
  announcementId: string | null;
@@ -146,12 +146,15 @@ export declare function renameFileScoped(userId: string, input: {
146
146
  } & {
147
147
  path: string;
148
148
  type: string;
149
- name: string;
150
149
  id: string;
151
150
  userId: string | null;
152
- folderId: string | null;
151
+ name: string;
153
152
  size: number | null;
154
153
  uploadedAt: Date | null;
154
+ assignmentId: string | null;
155
+ submissionId: string | null;
156
+ thumbnailId: string | null;
157
+ annotationId: string | null;
155
158
  uploadStatus: import(".prisma/client").$Enums.UploadStatus;
156
159
  uploadUrl: string | null;
157
160
  uploadExpiresAt: Date | null;
@@ -161,11 +164,8 @@ export declare function renameFileScoped(userId: string, input: {
161
164
  uploadRetryCount: number;
162
165
  isOrphaned: boolean;
163
166
  cleanupAt: Date | null;
164
- thumbnailId: string | null;
165
- assignmentId: string | null;
166
- submissionId: string | null;
167
- annotationId: string | null;
168
167
  classDraftId: string | null;
168
+ folderId: string | null;
169
169
  conversationId: string | null;
170
170
  messageId: string | null;
171
171
  announcementId: string | null;