@studious-lms/server 1.12.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.
- package/.dockerignore +28 -0
- package/.env.example +5 -0
- package/.github/workflows/deploy.yml +123 -0
- package/Dockerfile +54 -0
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/config/cors.d.ts.map +1 -1
- package/dist/lib/config/cors.js +31 -11
- package/dist/lib/config/cors.js.map +1 -1
- package/dist/lib/config/env.d.ts +17 -0
- package/dist/lib/config/env.d.ts.map +1 -1
- package/dist/lib/config/env.js +8 -2
- package/dist/lib/config/env.js.map +1 -1
- package/dist/lib/googleCloudStorage.d.ts +10 -0
- package/dist/lib/googleCloudStorage.d.ts.map +1 -1
- package/dist/lib/googleCloudStorage.js +22 -2
- package/dist/lib/googleCloudStorage.js.map +1 -1
- package/dist/lib/prisma.d.ts +104 -5
- package/dist/lib/prisma.d.ts.map +1 -1
- package/dist/lib/prisma.js +33 -2
- package/dist/lib/prisma.js.map +1 -1
- package/dist/models/agenda.d.ts +20 -20
- package/dist/models/announcement.d.ts +177 -69
- package/dist/models/announcement.d.ts.map +1 -1
- package/dist/models/assignment.d.ts +551 -353
- package/dist/models/assignment.d.ts.map +1 -1
- package/dist/models/attendance.d.ts +197 -71
- package/dist/models/attendance.d.ts.map +1 -1
- package/dist/models/auth.d.ts +348 -114
- package/dist/models/auth.d.ts.map +1 -1
- package/dist/models/class.d.ts +324 -188
- package/dist/models/class.d.ts.map +1 -1
- package/dist/models/class.js +9 -3
- package/dist/models/class.js.map +1 -1
- package/dist/models/cloudStorage.d.ts +146 -56
- package/dist/models/cloudStorage.d.ts.map +1 -1
- package/dist/models/comment.d.ts +269 -110
- package/dist/models/comment.d.ts.map +1 -1
- package/dist/models/comment.js +3 -2
- package/dist/models/comment.js.map +1 -1
- package/dist/models/conversation.d.ts +206 -63
- package/dist/models/conversation.d.ts.map +1 -1
- package/dist/models/conversation.js +13 -2
- package/dist/models/conversation.js.map +1 -1
- package/dist/models/department.d.ts +196 -70
- package/dist/models/department.d.ts.map +1 -1
- package/dist/models/event.d.ts +287 -125
- package/dist/models/event.d.ts.map +1 -1
- package/dist/models/file.d.ts +389 -263
- package/dist/models/file.d.ts.map +1 -1
- package/dist/models/folder.d.ts +433 -181
- package/dist/models/folder.d.ts.map +1 -1
- package/dist/models/labChat.d.ts +209 -83
- package/dist/models/labChat.d.ts.map +1 -1
- package/dist/models/marketing.d.ts +80 -26
- package/dist/models/marketing.d.ts.map +1 -1
- package/dist/models/message.d.ts +95 -41
- package/dist/models/message.d.ts.map +1 -1
- package/dist/models/newtonChat.d.ts +83 -29
- package/dist/models/newtonChat.d.ts.map +1 -1
- package/dist/models/notification.d.ts +61 -25
- package/dist/models/notification.d.ts.map +1 -1
- package/dist/models/school.d.ts +349 -133
- package/dist/models/school.d.ts.map +1 -1
- package/dist/models/section.d.ts +216 -72
- package/dist/models/section.d.ts.map +1 -1
- package/dist/models/tag.d.ts +156 -48
- package/dist/models/tag.d.ts.map +1 -1
- package/dist/models/user.d.ts +82 -28
- package/dist/models/user.d.ts.map +1 -1
- package/dist/models/worksheet.d.ts +1023 -410
- package/dist/models/worksheet.d.ts.map +1 -1
- package/dist/models/worksheet.js +19 -7
- package/dist/models/worksheet.js.map +1 -1
- package/dist/pipelines/aiLabChat.d.ts +0 -8
- package/dist/pipelines/aiLabChat.d.ts.map +1 -1
- package/dist/pipelines/aiLabChat.js +50 -67
- package/dist/pipelines/aiLabChat.js.map +1 -1
- package/dist/pipelines/aiLabChatContract.d.ts +393 -388
- package/dist/pipelines/aiLabChatContract.d.ts.map +1 -1
- package/dist/pipelines/aiLabChatContract.js +63 -69
- package/dist/pipelines/aiLabChatContract.js.map +1 -1
- package/dist/pipelines/aiNewtonChat.d.ts.map +1 -1
- package/dist/pipelines/aiNewtonChat.js +41 -41
- package/dist/pipelines/aiNewtonChat.js.map +1 -1
- package/dist/pipelines/gradeWorksheet.d.ts +8 -8
- package/dist/pipelines/gradeWorksheet.d.ts.map +1 -1
- package/dist/pipelines/gradeWorksheet.js +59 -14
- package/dist/pipelines/gradeWorksheet.js.map +1 -1
- package/dist/pipelines/labChatPrompt.d.ts +10 -8
- package/dist/pipelines/labChatPrompt.d.ts.map +1 -1
- package/dist/pipelines/labChatPrompt.js +47 -67
- package/dist/pipelines/labChatPrompt.js.map +1 -1
- package/dist/pipelines/pdfToWorksheet.d.ts +2 -2
- package/dist/routers/_app.d.ts +2268 -1898
- package/dist/routers/_app.d.ts.map +1 -1
- package/dist/routers/_app.js +4 -2
- package/dist/routers/_app.js.map +1 -1
- package/dist/routers/admin.d.ts +13 -13
- package/dist/routers/agenda.d.ts +18 -18
- package/dist/routers/announcement.d.ts +32 -28
- package/dist/routers/announcement.d.ts.map +1 -1
- package/dist/routers/announcement.js +6 -5
- package/dist/routers/announcement.js.map +1 -1
- package/dist/routers/assignment.d.ts +335 -327
- package/dist/routers/assignment.d.ts.map +1 -1
- package/dist/routers/assignment.js +4 -4
- package/dist/routers/assignment.js.map +1 -1
- package/dist/routers/attendance.d.ts +10 -10
- package/dist/routers/auth.d.ts +2 -2
- package/dist/routers/class.d.ts +170 -147
- package/dist/routers/class.d.ts.map +1 -1
- package/dist/routers/comment.d.ts +40 -16
- package/dist/routers/comment.d.ts.map +1 -1
- package/dist/routers/comment.js +6 -3
- package/dist/routers/comment.js.map +1 -1
- package/dist/routers/conversation.d.ts +17 -17
- package/dist/routers/department.d.ts +34 -34
- package/dist/routers/discussion.d.ts +65 -53
- package/dist/routers/discussion.d.ts.map +1 -1
- package/dist/routers/discussion.js +6 -2
- package/dist/routers/discussion.js.map +1 -1
- package/dist/routers/embedding.d.ts +69 -0
- package/dist/routers/embedding.d.ts.map +1 -0
- package/dist/routers/embedding.js +143 -0
- package/dist/routers/embedding.js.map +1 -0
- package/dist/routers/event.d.ts +39 -39
- package/dist/routers/file.d.ts +12 -12
- package/dist/routers/folder.d.ts +38 -38
- package/dist/routers/labChat.d.ts +19 -19
- package/dist/routers/marketing.d.ts +2 -2
- package/dist/routers/message.d.ts +13 -13
- package/dist/routers/newtonChat.d.ts +4 -4
- package/dist/routers/notifications.d.ts +9 -9
- package/dist/routers/permissions.d.ts +14 -14
- package/dist/routers/school.d.ts +55 -55
- package/dist/routers/search.d.ts +22 -1
- package/dist/routers/search.d.ts.map +1 -1
- package/dist/routers/search.js +9 -3
- package/dist/routers/search.js.map +1 -1
- package/dist/routers/section.d.ts +4 -4
- package/dist/routers/studentProgress.d.ts +1 -1
- package/dist/routers/tag.d.ts +7 -7
- package/dist/routers/user.d.ts +10 -10
- package/dist/routers/worksheet.d.ts +97 -56
- package/dist/routers/worksheet.d.ts.map +1 -1
- package/dist/routers/worksheet.js +28 -2
- package/dist/routers/worksheet.js.map +1 -1
- package/dist/routes/aiStream.d.ts +2 -0
- package/dist/routes/aiStream.d.ts.map +1 -0
- package/dist/routes/aiStream.js +696 -0
- package/dist/routes/aiStream.js.map +1 -0
- package/dist/seedDatabase.d.ts +2 -2
- package/dist/seedDatabase.js +6 -6
- package/dist/seedDatabase.js.map +1 -1
- package/dist/services/adminInstitution.d.ts +8 -8
- package/dist/services/adminRunJob.d.ts +4 -4
- package/dist/services/agenda.d.ts +18 -18
- package/dist/services/aiChatStream.d.ts +68 -0
- package/dist/services/aiChatStream.d.ts.map +1 -0
- package/dist/services/aiChatStream.js +157 -0
- package/dist/services/aiChatStream.js.map +1 -0
- package/dist/services/aiModifierTools.d.ts +32 -0
- package/dist/services/aiModifierTools.d.ts.map +1 -0
- package/dist/services/aiModifierTools.js +165 -0
- package/dist/services/aiModifierTools.js.map +1 -0
- package/dist/services/aiProposalTools.d.ts +32 -0
- package/dist/services/aiProposalTools.d.ts.map +1 -0
- package/dist/services/aiProposalTools.js +207 -0
- package/dist/services/aiProposalTools.js.map +1 -0
- package/dist/services/aiStream.d.ts +22 -0
- package/dist/services/aiStream.d.ts.map +1 -0
- package/dist/services/aiStream.js +142 -0
- package/dist/services/aiStream.js.map +1 -0
- package/dist/services/aiTools.d.ts +16 -0
- package/dist/services/aiTools.d.ts.map +1 -0
- package/dist/services/aiTools.js +271 -0
- package/dist/services/aiTools.js.map +1 -0
- package/dist/services/announcement.d.ts +12 -12
- package/dist/services/announcement.d.ts.map +1 -1
- package/dist/services/announcement.js +7 -2
- package/dist/services/announcement.js.map +1 -1
- package/dist/services/assignment.d.ts +293 -293
- package/dist/services/assignment.d.ts.map +1 -1
- package/dist/services/assignment.js +36 -15
- package/dist/services/assignment.js.map +1 -1
- package/dist/services/attendance.d.ts +10 -10
- package/dist/services/auth.d.ts +2 -2
- package/dist/services/class.d.ts +161 -138
- package/dist/services/class.d.ts.map +1 -1
- package/dist/services/class.js +25 -4
- package/dist/services/class.js.map +1 -1
- package/dist/services/comment.d.ts +34 -16
- package/dist/services/comment.d.ts.map +1 -1
- package/dist/services/comment.js +23 -2
- package/dist/services/comment.js.map +1 -1
- package/dist/services/conversation.d.ts +17 -17
- package/dist/services/conversation.d.ts.map +1 -1
- package/dist/services/conversation.js +9 -7
- package/dist/services/conversation.js.map +1 -1
- package/dist/services/department.d.ts +33 -33
- package/dist/services/discussion.d.ts +58 -58
- package/dist/services/discussion.d.ts.map +1 -1
- package/dist/services/discussion.js +8 -8
- package/dist/services/discussion.js.map +1 -1
- package/dist/services/discussionSummary.d.ts +21 -0
- package/dist/services/discussionSummary.d.ts.map +1 -0
- package/dist/services/discussionSummary.js +179 -0
- package/dist/services/discussionSummary.js.map +1 -0
- package/dist/services/embedding.d.ts +67 -0
- package/dist/services/embedding.d.ts.map +1 -0
- package/dist/services/embedding.js +226 -0
- package/dist/services/embedding.js.map +1 -0
- package/dist/services/event.d.ts +37 -37
- package/dist/services/file.d.ts +24 -24
- package/dist/services/folder.d.ts +36 -36
- package/dist/services/labChat.d.ts +19 -19
- package/dist/services/marketing.d.ts +2 -2
- package/dist/services/message.d.ts +11 -11
- package/dist/services/message.d.ts.map +1 -1
- package/dist/services/message.js +2 -2
- package/dist/services/message.js.map +1 -1
- package/dist/services/newtonChat.d.ts +4 -4
- package/dist/services/notification.d.ts +9 -9
- package/dist/services/notification.d.ts.map +1 -1
- package/dist/services/permissions.d.ts +14 -14
- package/dist/services/school.d.ts +50 -50
- package/dist/services/search.d.ts +12 -0
- package/dist/services/search.d.ts.map +1 -1
- package/dist/services/search.js +120 -2
- package/dist/services/search.js.map +1 -1
- package/dist/services/section.d.ts +3 -3
- package/dist/services/tag.d.ts +4 -4
- package/dist/services/user.d.ts +4 -4
- package/dist/services/user.d.ts.map +1 -1
- package/dist/services/user.js +10 -15
- package/dist/services/user.js.map +1 -1
- package/dist/services/worksheet.d.ts +62 -47
- package/dist/services/worksheet.d.ts.map +1 -1
- package/dist/services/worksheet.js +11 -4
- package/dist/services/worksheet.js.map +1 -1
- package/dist/utils/streamBroadcast.d.ts +11 -0
- package/dist/utils/streamBroadcast.d.ts.map +1 -0
- package/dist/utils/streamBroadcast.js +32 -0
- package/dist/utils/streamBroadcast.js.map +1 -0
- package/dist/workers/connection.d.ts +15 -0
- package/dist/workers/connection.d.ts.map +1 -1
- package/dist/workers/connection.js +20 -2
- package/dist/workers/connection.js.map +1 -1
- package/dist/workers/index.js +4 -2
- package/dist/workers/index.js.map +1 -1
- package/dist/workers/processors/createRunJobWorker.d.ts.map +1 -1
- package/dist/workers/processors/createRunJobWorker.js +31 -8
- package/dist/workers/processors/createRunJobWorker.js.map +1 -1
- package/dist/workers/processors/embedContent.d.ts +8 -0
- package/dist/workers/processors/embedContent.d.ts.map +1 -0
- package/dist/workers/processors/embedContent.js +76 -0
- package/dist/workers/processors/embedContent.js.map +1 -0
- package/dist/workers/queues.d.ts +6 -0
- package/dist/workers/queues.d.ts.map +1 -1
- package/dist/workers/queues.js +5 -3
- package/dist/workers/queues.js.map +1 -1
- package/package.json +5 -1
- package/prisma/migrations/20260609215135_init/migration.sql +1412 -0
- package/prisma/migrations/20260610130000_add_worksheet_tags/migration.sql +13 -0
- package/prisma/schema.prisma +39 -7
- package/src/index.ts +4 -0
- package/src/lib/config/cors.ts +32 -9
- package/src/lib/config/env.ts +6 -0
- package/src/lib/googleCloudStorage.ts +21 -0
- package/src/lib/prisma.ts +40 -1
- package/src/models/class.ts +10 -3
- package/src/models/comment.ts +1 -0
- package/src/models/conversation.ts +12 -0
- package/src/models/worksheet.ts +16 -7
- package/src/pipelines/aiLabChat.ts +54 -79
- package/src/pipelines/aiLabChatContract.ts +69 -69
- package/src/pipelines/aiNewtonChat.ts +46 -43
- package/src/pipelines/gradeWorksheet.ts +66 -15
- package/src/pipelines/labChatPrompt.ts +63 -88
- package/src/routers/_app.ts +2 -0
- package/src/routers/announcement.ts +4 -3
- package/src/routers/assignment.ts +2 -2
- package/src/routers/comment.ts +5 -0
- package/src/routers/discussion.ts +7 -0
- package/src/routers/embedding.ts +159 -0
- package/src/routers/search.ts +10 -1
- package/src/routers/worksheet.ts +29 -0
- package/src/routes/aiStream.ts +789 -0
- package/src/seedDatabase.ts +4 -4
- package/src/services/aiChatStream.ts +219 -0
- package/src/services/aiModifierTools.ts +188 -0
- package/src/services/aiProposalTools.ts +272 -0
- package/src/services/aiStream.ts +175 -0
- package/src/services/aiTools.ts +290 -0
- package/src/services/announcement.ts +7 -0
- package/src/services/assignment.ts +36 -14
- package/src/services/class.ts +30 -2
- package/src/services/comment.ts +22 -0
- package/src/services/conversation.ts +9 -4
- package/src/services/discussion.ts +9 -8
- package/src/services/discussionSummary.ts +226 -0
- package/src/services/embedding.ts +285 -0
- package/src/services/message.ts +2 -2
- package/src/services/search.ts +138 -0
- package/src/services/user.ts +9 -17
- package/src/services/worksheet.ts +10 -2
- package/src/utils/streamBroadcast.ts +48 -0
- package/src/workers/connection.ts +19 -0
- package/src/workers/index.ts +2 -0
- package/src/workers/processors/createRunJobWorker.ts +32 -6
- package/src/workers/processors/embedContent.ts +90 -0
- package/src/workers/queues.ts +5 -1
- package/tests/integration/routers/conversation.test.ts +9 -7
- package/tests/unit/pipelines/aiLabChatContract.test.ts +38 -21
- package/tests/unit/pipelines/labChatPrompt.test.ts +23 -36
- package/prisma/migrations/20250807062924_init/migration.sql +0 -436
- package/prisma/migrations/20250919063704_init2/migration.sql +0 -24
- package/prisma/migrations/20250920143543_add_profile_fields/migration.sql +0 -15
- package/prisma/migrations/20250922165147_add_chat_models/migration.sql +0 -68
- package/prisma/migrations/20250922165314_add_chat_roles/migration.sql +0 -5
- package/prisma/migrations/20250922171242_refactor_notification_system/migration.sql +0 -20
- package/prisma/migrations/20250922172208_add_mentions_system/migration.sql +0 -21
- package/prisma/migrations/20250925072732_add_lab_chat_system/migration.sql +0 -25
- package/prisma/migrations/20251020151505_add_upload_tracking_fields/migration.sql +0 -57
- package/prisma/migrations/20251109122857_annuoncements_comments/migration.sql +0 -30
- package/prisma/migrations/20251109135555_reactions_announcements_comments/migration.sql +0 -35
- package/prisma/migrations/20260410124000_add_submission_recommendation_state/migration.sql +0 -14
- package/prisma/migrations/20260415103500_add_session_type/migration.sql +0 -33
- package/prisma/migrations/20260415133000_add_ai_usage_logs/migration.sql +0 -19
- package/prisma/migrations/20260417083000_add_conversation_member_hidden_at/migration.sql +0 -2
- package/prisma/migrations/20260502230500_assignment_submission_comments/migration.sql +0 -60
- package/prisma/migrations/20260504071500_school_memberships/migration.sql +0 -81
- package/prisma/migrations/20260506162500_consolidate_run_job_and_unify_job_status/migration.sql +0 -166
- package/prisma/migrations/20260509220000_institution_overhaul/migration.sql +0 -184
- package/prisma/migrations/20260510170000_add_folder_permissions/migration.sql +0 -93
- package/prisma/migrations/20260510183000_add_discussions/migration.sql +0 -151
- /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"}
|
package/dist/services/event.d.ts
CHANGED
|
@@ -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
|
-
|
|
33
|
+
section: string;
|
|
34
34
|
id: string;
|
|
35
|
+
name: string;
|
|
35
36
|
schoolId: string | null;
|
|
36
|
-
subject: string;
|
|
37
37
|
color: string | null;
|
|
38
|
-
|
|
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
|
}>;
|
package/dist/services/file.d.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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;
|