@studious-lms/server 1.14.0 → 1.16.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 (129) hide show
  1. package/dist/lib/inferDocumentFormat.d.ts +10 -0
  2. package/dist/lib/inferDocumentFormat.d.ts.map +1 -0
  3. package/dist/lib/inferDocumentFormat.js +48 -0
  4. package/dist/lib/inferDocumentFormat.js.map +1 -0
  5. package/dist/models/announcement.d.ts +45 -45
  6. package/dist/models/assignment.d.ts +75 -75
  7. package/dist/models/class.d.ts +13 -13
  8. package/dist/models/comment.d.ts +6 -6
  9. package/dist/models/conversation.d.ts +23 -23
  10. package/dist/models/event.d.ts +18 -18
  11. package/dist/models/file.d.ts +9 -9
  12. package/dist/models/labChat.d.ts +4 -4
  13. package/dist/models/message.d.ts +13 -13
  14. package/dist/models/newtonChat.d.ts +3 -3
  15. package/dist/models/notification.d.ts +4 -4
  16. package/dist/models/worksheet.d.ts +121 -121
  17. package/dist/pipelines/aiLabChat.d.ts +7 -1
  18. package/dist/pipelines/aiLabChat.d.ts.map +1 -1
  19. package/dist/pipelines/aiLabChat.js +145 -67
  20. package/dist/pipelines/aiLabChat.js.map +1 -1
  21. package/dist/pipelines/aiLabChatContract.d.ts +34 -195
  22. package/dist/pipelines/aiLabChatContract.d.ts.map +1 -1
  23. package/dist/pipelines/aiLabChatContract.js +9 -19
  24. package/dist/pipelines/aiLabChatContract.js.map +1 -1
  25. package/dist/pipelines/gradeWorksheet.d.ts +6 -6
  26. package/dist/pipelines/gradeWorksheet.d.ts.map +1 -1
  27. package/dist/pipelines/gradeWorksheet.js +75 -36
  28. package/dist/pipelines/gradeWorksheet.js.map +1 -1
  29. package/dist/pipelines/labChatPrompt.d.ts +8 -3
  30. package/dist/pipelines/labChatPrompt.d.ts.map +1 -1
  31. package/dist/pipelines/labChatPrompt.js +49 -14
  32. package/dist/pipelines/labChatPrompt.js.map +1 -1
  33. package/dist/pipelines/pdfToWorksheet.d.ts +1 -1
  34. package/dist/routers/_app.d.ts +524 -516
  35. package/dist/routers/_app.d.ts.map +1 -1
  36. package/dist/routers/announcement.d.ts +40 -40
  37. package/dist/routers/assignment.d.ts +121 -121
  38. package/dist/routers/class.d.ts +8 -8
  39. package/dist/routers/comment.d.ts +5 -5
  40. package/dist/routers/conversation.d.ts +6 -6
  41. package/dist/routers/discussion.d.ts +3 -3
  42. package/dist/routers/embedding.d.ts +6 -2
  43. package/dist/routers/embedding.d.ts.map +1 -1
  44. package/dist/routers/embedding.js +44 -36
  45. package/dist/routers/embedding.js.map +1 -1
  46. package/dist/routers/event.d.ts +18 -18
  47. package/dist/routers/file.d.ts +2 -2
  48. package/dist/routers/labChat.d.ts +3 -3
  49. package/dist/routers/notifications.d.ts +4 -4
  50. package/dist/routers/search.d.ts +2 -2
  51. package/dist/routers/worksheet.d.ts +44 -44
  52. package/dist/routes/aiStream.d.ts.map +1 -1
  53. package/dist/routes/aiStream.js +41 -11
  54. package/dist/routes/aiStream.js.map +1 -1
  55. package/dist/seedDatabase.d.ts +1 -1
  56. package/dist/services/aiChatStream.d.ts +18 -0
  57. package/dist/services/aiChatStream.d.ts.map +1 -1
  58. package/dist/services/aiChatStream.js +81 -11
  59. package/dist/services/aiChatStream.js.map +1 -1
  60. package/dist/services/aiModifierTools.d.ts +0 -16
  61. package/dist/services/aiModifierTools.d.ts.map +1 -1
  62. package/dist/services/aiModifierTools.js +112 -3
  63. package/dist/services/aiModifierTools.js.map +1 -1
  64. package/dist/services/aiProposalTools.d.ts.map +1 -1
  65. package/dist/services/aiProposalTools.js +25 -25
  66. package/dist/services/aiProposalTools.js.map +1 -1
  67. package/dist/services/announcement.d.ts +34 -34
  68. package/dist/services/assignment.d.ts +111 -111
  69. package/dist/services/assignment.d.ts.map +1 -1
  70. package/dist/services/assignment.js +4 -2
  71. package/dist/services/assignment.js.map +1 -1
  72. package/dist/services/class.d.ts +6 -6
  73. package/dist/services/class.d.ts.map +1 -1
  74. package/dist/services/class.js +7 -3
  75. package/dist/services/class.js.map +1 -1
  76. package/dist/services/comment.d.ts +5 -5
  77. package/dist/services/conversation.d.ts +6 -6
  78. package/dist/services/discussion.d.ts.map +1 -1
  79. package/dist/services/discussion.js +9 -2
  80. package/dist/services/discussion.js.map +1 -1
  81. package/dist/services/embedding.d.ts +19 -1
  82. package/dist/services/embedding.d.ts.map +1 -1
  83. package/dist/services/embedding.js +154 -8
  84. package/dist/services/embedding.js.map +1 -1
  85. package/dist/services/event.d.ts +18 -18
  86. package/dist/services/file.d.ts +4 -4
  87. package/dist/services/folder.d.ts.map +1 -1
  88. package/dist/services/folder.js +32 -2
  89. package/dist/services/folder.js.map +1 -1
  90. package/dist/services/labChat.d.ts +3 -3
  91. package/dist/services/notification.d.ts +4 -4
  92. package/dist/services/openaiDocumentGen.d.ts +25 -0
  93. package/dist/services/openaiDocumentGen.d.ts.map +1 -0
  94. package/dist/services/openaiDocumentGen.js +195 -0
  95. package/dist/services/openaiDocumentGen.js.map +1 -0
  96. package/dist/services/search.d.ts +1 -1
  97. package/dist/services/search.d.ts.map +1 -1
  98. package/dist/services/search.js +27 -2
  99. package/dist/services/search.js.map +1 -1
  100. package/dist/services/worksheet.d.ts +66 -49
  101. package/dist/services/worksheet.d.ts.map +1 -1
  102. package/dist/services/worksheet.js +48 -3
  103. package/dist/services/worksheet.js.map +1 -1
  104. package/dist/workers/processors/embedContent.d.ts.map +1 -1
  105. package/dist/workers/processors/embedContent.js +16 -25
  106. package/dist/workers/processors/embedContent.js.map +1 -1
  107. package/package.json +1 -1
  108. package/prisma/migrations/20260610140000_expand_embedding_source_types/migration.sql +4 -0
  109. package/prisma/schema.prisma +3 -0
  110. package/src/lib/inferDocumentFormat.ts +58 -0
  111. package/src/pipelines/aiLabChat.ts +185 -74
  112. package/src/pipelines/aiLabChatContract.ts +7 -17
  113. package/src/pipelines/gradeWorksheet.ts +95 -38
  114. package/src/pipelines/labChatPrompt.ts +61 -14
  115. package/src/routers/embedding.ts +44 -39
  116. package/src/routes/aiStream.ts +47 -9
  117. package/src/services/aiChatStream.ts +103 -8
  118. package/src/services/aiModifierTools.ts +154 -1
  119. package/src/services/aiProposalTools.ts +26 -25
  120. package/src/services/assignment.ts +3 -0
  121. package/src/services/class.ts +7 -1
  122. package/src/services/discussion.ts +13 -0
  123. package/src/services/embedding.ts +167 -6
  124. package/src/services/folder.ts +31 -0
  125. package/src/services/openaiDocumentGen.ts +237 -0
  126. package/src/services/search.ts +25 -1
  127. package/src/services/worksheet.ts +68 -1
  128. package/src/workers/processors/embedContent.ts +18 -22
  129. package/tests/unit/lib/inferDocumentFormat.test.ts +33 -0
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Generate files via OpenAI Code Interpreter (Responses API).
3
+ * Supports every format the sandbox can produce (pdf, docx, xlsx, pptx, …).
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]="cd65973d-ca13-5498-8d6b-ff056b093631")}catch(e){}}();
7
+ import OpenAI from 'openai';
8
+ import { logger } from '../utils/logger.js';
9
+ const DOCUMENT_GEN_MODEL = 'gpt-4o-mini';
10
+ export const SUPPORTED_DOCUMENT_FORMATS = [
11
+ 'pdf', 'docx', 'doc', 'xlsx', 'pptx', 'csv', 'md', 'html', 'txt', 'json',
12
+ 'xml', 'tex', 'png', 'jpeg', 'jpg', 'gif', 'zip', 'tar', 'py', 'js', 'ts',
13
+ 'css', 'sh',
14
+ ];
15
+ const FORMAT_MIME = {
16
+ pdf: 'application/pdf',
17
+ docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
18
+ doc: 'application/msword',
19
+ xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
20
+ pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
21
+ csv: 'text/csv',
22
+ md: 'text/markdown',
23
+ html: 'text/html',
24
+ txt: 'text/plain',
25
+ json: 'application/json',
26
+ xml: 'application/xml',
27
+ tex: 'text/x-tex',
28
+ png: 'image/png',
29
+ jpeg: 'image/jpeg',
30
+ jpg: 'image/jpeg',
31
+ gif: 'image/gif',
32
+ zip: 'application/zip',
33
+ tar: 'application/x-tar',
34
+ py: 'text/x-python',
35
+ js: 'text/javascript',
36
+ ts: 'application/typescript',
37
+ css: 'text/css',
38
+ sh: 'application/x-sh',
39
+ };
40
+ const FORMAT_HINTS = {
41
+ pdf: 'fpdf2 or reportlab',
42
+ docx: 'python-docx',
43
+ doc: 'python-docx',
44
+ xlsx: 'openpyxl or pandas',
45
+ pptx: 'python-pptx',
46
+ csv: 'pandas or csv module',
47
+ md: 'write markdown directly',
48
+ html: 'write a complete HTML page',
49
+ txt: 'write plain text',
50
+ json: 'json.dumps with indentation',
51
+ xml: 'well-formed XML',
52
+ tex: 'LaTeX source',
53
+ png: 'matplotlib or Pillow',
54
+ jpeg: 'matplotlib or Pillow',
55
+ jpg: 'matplotlib or Pillow',
56
+ gif: 'matplotlib or Pillow',
57
+ zip: 'zipfile',
58
+ tar: 'tarfile',
59
+ py: 'Python source',
60
+ js: 'JavaScript source',
61
+ ts: 'TypeScript source',
62
+ css: 'CSS stylesheet',
63
+ sh: 'shell script',
64
+ };
65
+ export function normalizeDocumentFormat(format) {
66
+ const raw = (format ?? 'pdf').toLowerCase().replace(/^\./, '');
67
+ if (SUPPORTED_DOCUMENT_FORMATS.includes(raw)) {
68
+ return raw;
69
+ }
70
+ return 'pdf';
71
+ }
72
+ export function mimeTypeForFormat(format) {
73
+ return FORMAT_MIME[format];
74
+ }
75
+ export function extractContainerGeneratedFiles(response, extension) {
76
+ const suffix = `.${extension}`;
77
+ const seen = new Set();
78
+ const files = [];
79
+ for (const item of response.output ?? []) {
80
+ if (item.type !== 'message')
81
+ continue;
82
+ for (const block of item.content ?? []) {
83
+ if (block.type !== 'output_text')
84
+ continue;
85
+ for (const ann of block.annotations ?? []) {
86
+ if (ann.type !== 'container_file_citation')
87
+ continue;
88
+ const name = ann.filename?.toLowerCase() ?? '';
89
+ if (!name.endsWith(suffix))
90
+ continue;
91
+ const key = `${ann.container_id}:${ann.file_id}`;
92
+ if (seen.has(key))
93
+ continue;
94
+ seen.add(key);
95
+ files.push({
96
+ containerId: ann.container_id,
97
+ fileId: ann.file_id,
98
+ filename: ann.filename,
99
+ });
100
+ }
101
+ }
102
+ }
103
+ return files;
104
+ }
105
+ function containerIdFromResponse(response) {
106
+ for (const item of response.output ?? []) {
107
+ if (item.type === 'code_interpreter_call' && item.container_id) {
108
+ return item.container_id;
109
+ }
110
+ }
111
+ return undefined;
112
+ }
113
+ async function listContainerGeneratedFiles(client, containerId, extension) {
114
+ const suffix = `.${extension}`;
115
+ const files = [];
116
+ for await (const file of client.containers.files.list(containerId)) {
117
+ const path = file.path?.toLowerCase() ?? '';
118
+ if (path.endsWith(suffix) && file.source === 'assistant') {
119
+ files.push({
120
+ containerId,
121
+ fileId: file.id,
122
+ filename: file.path.split('/').pop() ?? file.path,
123
+ });
124
+ }
125
+ }
126
+ return files;
127
+ }
128
+ function safeBasename(title) {
129
+ return (title
130
+ .replace(/[^a-zA-Z0-9\s\-_]/g, '')
131
+ .replace(/\s+/g, '_')
132
+ .substring(0, 60) || 'document');
133
+ }
134
+ /** Generate a file via OpenAI Code Interpreter. */
135
+ export async function generateDocumentWithOpenAI(input) {
136
+ const client = new OpenAI();
137
+ const format = normalizeDocumentFormat(input.format);
138
+ const ext = format === 'jpg' ? 'jpg' : format;
139
+ const filename = `${safeBasename(input.title)}.${ext}`;
140
+ try {
141
+ const response = await client.responses.create({
142
+ model: DOCUMENT_GEN_MODEL,
143
+ instructions: [
144
+ 'You generate classroom-ready files for teachers using the python tool.',
145
+ `You MUST output a ${ext.toUpperCase()} file — not any other format.`,
146
+ `Use: ${FORMAT_HINTS[format]}.`,
147
+ `The saved filename MUST end with .${ext}.`,
148
+ 'Save exactly one output file with the requested filename.',
149
+ 'Include only educational content — no chat commentary.',
150
+ ...(format !== 'pdf' ? [`Do NOT create a PDF when ${ext.toUpperCase()} was requested.`] : []),
151
+ ].join(' '),
152
+ tools: [{ type: 'code_interpreter', container: { type: 'auto' } }],
153
+ tool_choice: 'required',
154
+ input: [
155
+ `Create a ${ext.toUpperCase()} file.`,
156
+ `Filename (exact): ${filename}`,
157
+ `Title: ${input.title}`,
158
+ 'Content:',
159
+ input.content,
160
+ ].join('\n\n'),
161
+ });
162
+ let matches = extractContainerGeneratedFiles(response, format);
163
+ if (matches.length === 0) {
164
+ const containerId = containerIdFromResponse(response);
165
+ if (containerId) {
166
+ matches = await listContainerGeneratedFiles(client, containerId, format);
167
+ }
168
+ }
169
+ if (matches.length === 0) {
170
+ logger.error('OpenAI document gen: no output file', {
171
+ title: input.title,
172
+ format,
173
+ });
174
+ return null;
175
+ }
176
+ const preferred = matches.find((f) => f.filename.toLowerCase() === filename.toLowerCase()) ??
177
+ matches[0];
178
+ const res = await client.containers.files.content.retrieve(preferred.fileId, {
179
+ container_id: preferred.containerId,
180
+ });
181
+ const bytes = Buffer.from(await res.arrayBuffer());
182
+ return {
183
+ bytes,
184
+ filename: preferred.filename,
185
+ mimeType: mimeTypeForFormat(format),
186
+ format,
187
+ };
188
+ }
189
+ catch (error) {
190
+ logger.error('OpenAI document generation failed', { error, title: input.title, format });
191
+ return null;
192
+ }
193
+ }
194
+ //# sourceMappingURL=openaiDocumentGen.js.map
195
+ //# debugId=cd65973d-ca13-5498-8d6b-ff056b093631
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openaiDocumentGen.js","sources":["services/openaiDocumentGen.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Generate files via OpenAI Code Interpreter (Responses API).\n * Supports every format the sandbox can produce (pdf, docx, xlsx, pptx, …).\n */\nimport OpenAI from 'openai';\nimport type { Response } from 'openai/resources/responses/responses.js';\nimport { logger } from '../utils/logger.js';\n\nconst DOCUMENT_GEN_MODEL = 'gpt-4o-mini';\n\nexport const SUPPORTED_DOCUMENT_FORMATS = [\n 'pdf', 'docx', 'doc', 'xlsx', 'pptx', 'csv', 'md', 'html', 'txt', 'json',\n 'xml', 'tex', 'png', 'jpeg', 'jpg', 'gif', 'zip', 'tar', 'py', 'js', 'ts',\n 'css', 'sh',\n] as const;\n\nexport type DocumentFormat = (typeof SUPPORTED_DOCUMENT_FORMATS)[number];\n\nconst FORMAT_MIME: Record<DocumentFormat, string> = {\n pdf: 'application/pdf',\n docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n doc: 'application/msword',\n xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n csv: 'text/csv',\n md: 'text/markdown',\n html: 'text/html',\n txt: 'text/plain',\n json: 'application/json',\n xml: 'application/xml',\n tex: 'text/x-tex',\n png: 'image/png',\n jpeg: 'image/jpeg',\n jpg: 'image/jpeg',\n gif: 'image/gif',\n zip: 'application/zip',\n tar: 'application/x-tar',\n py: 'text/x-python',\n js: 'text/javascript',\n ts: 'application/typescript',\n css: 'text/css',\n sh: 'application/x-sh',\n};\n\nconst FORMAT_HINTS: Record<DocumentFormat, string> = {\n pdf: 'fpdf2 or reportlab',\n docx: 'python-docx',\n doc: 'python-docx',\n xlsx: 'openpyxl or pandas',\n pptx: 'python-pptx',\n csv: 'pandas or csv module',\n md: 'write markdown directly',\n html: 'write a complete HTML page',\n txt: 'write plain text',\n json: 'json.dumps with indentation',\n xml: 'well-formed XML',\n tex: 'LaTeX source',\n png: 'matplotlib or Pillow',\n jpeg: 'matplotlib or Pillow',\n jpg: 'matplotlib or Pillow',\n gif: 'matplotlib or Pillow',\n zip: 'zipfile',\n tar: 'tarfile',\n py: 'Python source',\n js: 'JavaScript source',\n ts: 'TypeScript source',\n css: 'CSS stylesheet',\n sh: 'shell script',\n};\n\nexport interface GenerateDocumentInput {\n title: string;\n content: string;\n format?: DocumentFormat | string;\n}\n\nexport interface GeneratedDocumentResult {\n bytes: Buffer;\n filename: string;\n mimeType: string;\n format: DocumentFormat;\n}\n\nexport interface ContainerGeneratedFile {\n containerId: string;\n fileId: string;\n filename: string;\n}\n\nexport function normalizeDocumentFormat(format?: string | null): DocumentFormat {\n const raw = (format ?? 'pdf').toLowerCase().replace(/^\\./, '');\n if ((SUPPORTED_DOCUMENT_FORMATS as readonly string[]).includes(raw)) {\n return raw as DocumentFormat;\n }\n return 'pdf';\n}\n\nexport function mimeTypeForFormat(format: DocumentFormat): string {\n return FORMAT_MIME[format];\n}\n\nexport function extractContainerGeneratedFiles(\n response: Response,\n extension: DocumentFormat,\n): ContainerGeneratedFile[] {\n const suffix = `.${extension}`;\n const seen = new Set<string>();\n const files: ContainerGeneratedFile[] = [];\n\n for (const item of response.output ?? []) {\n if (item.type !== 'message') continue;\n for (const block of item.content ?? []) {\n if (block.type !== 'output_text') continue;\n for (const ann of block.annotations ?? []) {\n if (ann.type !== 'container_file_citation') continue;\n const name = ann.filename?.toLowerCase() ?? '';\n if (!name.endsWith(suffix)) continue;\n const key = `${ann.container_id}:${ann.file_id}`;\n if (seen.has(key)) continue;\n seen.add(key);\n files.push({\n containerId: ann.container_id,\n fileId: ann.file_id,\n filename: ann.filename,\n });\n }\n }\n }\n return files;\n}\n\nfunction containerIdFromResponse(response: Response): string | undefined {\n for (const item of response.output ?? []) {\n if (item.type === 'code_interpreter_call' && item.container_id) {\n return item.container_id;\n }\n }\n return undefined;\n}\n\nasync function listContainerGeneratedFiles(\n client: OpenAI,\n containerId: string,\n extension: DocumentFormat,\n): Promise<ContainerGeneratedFile[]> {\n const suffix = `.${extension}`;\n const files: ContainerGeneratedFile[] = [];\n for await (const file of client.containers.files.list(containerId)) {\n const path = file.path?.toLowerCase() ?? '';\n if (path.endsWith(suffix) && file.source === 'assistant') {\n files.push({\n containerId,\n fileId: file.id,\n filename: file.path.split('/').pop() ?? file.path,\n });\n }\n }\n return files;\n}\n\nfunction safeBasename(title: string): string {\n return (\n title\n .replace(/[^a-zA-Z0-9\\s\\-_]/g, '')\n .replace(/\\s+/g, '_')\n .substring(0, 60) || 'document'\n );\n}\n\n/** Generate a file via OpenAI Code Interpreter. */\nexport async function generateDocumentWithOpenAI(\n input: GenerateDocumentInput,\n): Promise<GeneratedDocumentResult | null> {\n const client = new OpenAI();\n const format = normalizeDocumentFormat(input.format);\n const ext = format === 'jpg' ? 'jpg' : format;\n const filename = `${safeBasename(input.title)}.${ext}`;\n\n try {\n const response = await client.responses.create({\n model: DOCUMENT_GEN_MODEL,\n instructions: [\n 'You generate classroom-ready files for teachers using the python tool.',\n `You MUST output a ${ext.toUpperCase()} file — not any other format.`,\n `Use: ${FORMAT_HINTS[format]}.`,\n `The saved filename MUST end with .${ext}.`,\n 'Save exactly one output file with the requested filename.',\n 'Include only educational content — no chat commentary.',\n ...(format !== 'pdf' ? [`Do NOT create a PDF when ${ext.toUpperCase()} was requested.`] : []),\n ].join(' '),\n tools: [{ type: 'code_interpreter', container: { type: 'auto' } }],\n tool_choice: 'required',\n input: [\n `Create a ${ext.toUpperCase()} file.`,\n `Filename (exact): ${filename}`,\n `Title: ${input.title}`,\n 'Content:',\n input.content,\n ].join('\\n\\n'),\n });\n\n let matches = extractContainerGeneratedFiles(response, format);\n if (matches.length === 0) {\n const containerId = containerIdFromResponse(response);\n if (containerId) {\n matches = await listContainerGeneratedFiles(client, containerId, format);\n }\n }\n\n if (matches.length === 0) {\n logger.error('OpenAI document gen: no output file', {\n title: input.title,\n format,\n });\n return null;\n }\n\n const preferred =\n matches.find((f) => f.filename.toLowerCase() === filename.toLowerCase()) ??\n matches[0];\n\n const res = await client.containers.files.content.retrieve(preferred.fileId, {\n container_id: preferred.containerId,\n });\n const bytes = Buffer.from(await res.arrayBuffer());\n\n return {\n bytes,\n filename: preferred.filename,\n mimeType: mimeTypeForFormat(format),\n format,\n };\n } catch (error) {\n logger.error('OpenAI document generation failed', { error, title: input.title, format });\n return null;\n }\n}\n"],"names":[],"mappings":"AAAA;;;GAGG;;;AACH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,kBAAkB,GAAG,aAAa,CAAC;AAEzC,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IACxE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;IACzE,KAAK,EAAE,IAAI;CACH,CAAC;AAIX,MAAM,WAAW,GAAmC;IAClD,GAAG,EAAE,iBAAiB;IACtB,IAAI,EAAE,yEAAyE;IAC/E,GAAG,EAAE,oBAAoB;IACzB,IAAI,EAAE,mEAAmE;IACzE,IAAI,EAAE,2EAA2E;IACjF,GAAG,EAAE,UAAU;IACf,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,WAAW;IACjB,GAAG,EAAE,YAAY;IACjB,IAAI,EAAE,kBAAkB;IACxB,GAAG,EAAE,iBAAiB;IACtB,GAAG,EAAE,YAAY;IACjB,GAAG,EAAE,WAAW;IAChB,IAAI,EAAE,YAAY;IAClB,GAAG,EAAE,YAAY;IACjB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,iBAAiB;IACtB,GAAG,EAAE,mBAAmB;IACxB,EAAE,EAAE,eAAe;IACnB,EAAE,EAAE,iBAAiB;IACrB,EAAE,EAAE,wBAAwB;IAC5B,GAAG,EAAE,UAAU;IACf,EAAE,EAAE,kBAAkB;CACvB,CAAC;AAEF,MAAM,YAAY,GAAmC;IACnD,GAAG,EAAE,oBAAoB;IACzB,IAAI,EAAE,aAAa;IACnB,GAAG,EAAE,aAAa;IAClB,IAAI,EAAE,oBAAoB;IAC1B,IAAI,EAAE,aAAa;IACnB,GAAG,EAAE,sBAAsB;IAC3B,EAAE,EAAE,yBAAyB;IAC7B,IAAI,EAAE,4BAA4B;IAClC,GAAG,EAAE,kBAAkB;IACvB,IAAI,EAAE,6BAA6B;IACnC,GAAG,EAAE,iBAAiB;IACtB,GAAG,EAAE,cAAc;IACnB,GAAG,EAAE,sBAAsB;IAC3B,IAAI,EAAE,sBAAsB;IAC5B,GAAG,EAAE,sBAAsB;IAC3B,GAAG,EAAE,sBAAsB;IAC3B,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,EAAE,EAAE,eAAe;IACnB,EAAE,EAAE,mBAAmB;IACvB,EAAE,EAAE,mBAAmB;IACvB,GAAG,EAAE,gBAAgB;IACrB,EAAE,EAAE,cAAc;CACnB,CAAC;AAqBF,MAAM,UAAU,uBAAuB,CAAC,MAAsB;IAC5D,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC/D,IAAK,0BAAgD,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACpE,OAAO,GAAqB,CAAC;IAC/B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAsB;IACtD,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,8BAA8B,CAC5C,QAAkB,EAClB,SAAyB;IAEzB,MAAM,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;IAC/B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,KAAK,GAA6B,EAAE,CAAC;IAE3C,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QACzC,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;YAAE,SAAS;QACtC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;YACvC,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa;gBAAE,SAAS;YAC3C,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,WAAW,IAAI,EAAE,EAAE,CAAC;gBAC1C,IAAI,GAAG,CAAC,IAAI,KAAK,yBAAyB;oBAAE,SAAS;gBACrD,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;gBAC/C,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;oBAAE,SAAS;gBACrC,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;gBACjD,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;oBAAE,SAAS;gBAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACd,KAAK,CAAC,IAAI,CAAC;oBACT,WAAW,EAAE,GAAG,CAAC,YAAY;oBAC7B,MAAM,EAAE,GAAG,CAAC,OAAO;oBACnB,QAAQ,EAAE,GAAG,CAAC,QAAQ;iBACvB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,uBAAuB,CAAC,QAAkB;IACjD,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QACzC,IAAI,IAAI,CAAC,IAAI,KAAK,uBAAuB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YAC/D,OAAO,IAAI,CAAC,YAAY,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,KAAK,UAAU,2BAA2B,CACxC,MAAc,EACd,WAAmB,EACnB,SAAyB;IAEzB,MAAM,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;IAC/B,MAAM,KAAK,GAA6B,EAAE,CAAC;IAC3C,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QACnE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;QAC5C,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YACzD,KAAK,CAAC,IAAI,CAAC;gBACT,WAAW;gBACX,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,IAAI;aAClD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,CACL,KAAK;SACF,OAAO,CAAC,oBAAoB,EAAE,EAAE,CAAC;SACjC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,UAAU,CAClC,CAAC;AACJ,CAAC;AAED,mDAAmD;AACnD,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,KAA4B;IAE5B,MAAM,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,uBAAuB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACrD,MAAM,GAAG,GAAG,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;IAC9C,MAAM,QAAQ,GAAG,GAAG,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,EAAE,CAAC;IAEvD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;YAC7C,KAAK,EAAE,kBAAkB;YACzB,YAAY,EAAE;gBACZ,wEAAwE;gBACxE,qBAAqB,GAAG,CAAC,WAAW,EAAE,+BAA+B;gBACrE,QAAQ,YAAY,CAAC,MAAM,CAAC,GAAG;gBAC/B,qCAAqC,GAAG,GAAG;gBAC3C,2DAA2D;gBAC3D,wDAAwD;gBACxD,GAAG,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,4BAA4B,GAAG,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;aAC9F,CAAC,IAAI,CAAC,GAAG,CAAC;YACX,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC;YAClE,WAAW,EAAE,UAAU;YACvB,KAAK,EAAE;gBACL,YAAY,GAAG,CAAC,WAAW,EAAE,QAAQ;gBACrC,qBAAqB,QAAQ,EAAE;gBAC/B,UAAU,KAAK,CAAC,KAAK,EAAE;gBACvB,UAAU;gBACV,KAAK,CAAC,OAAO;aACd,CAAC,IAAI,CAAC,MAAM,CAAC;SACf,CAAC,CAAC;QAEH,IAAI,OAAO,GAAG,8BAA8B,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC/D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,WAAW,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;YACtD,IAAI,WAAW,EAAE,CAAC;gBAChB,OAAO,GAAG,MAAM,2BAA2B,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;YAC3E,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,CAAC,KAAK,CAAC,qCAAqC,EAAE;gBAClD,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,MAAM;aACP,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,SAAS,GACb,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,QAAQ,CAAC,WAAW,EAAE,CAAC;YACxE,OAAO,CAAC,CAAC,CAAC,CAAC;QAEb,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE;YAC3E,YAAY,EAAE,SAAS,CAAC,WAAW;SACpC,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;QAEnD,OAAO;YACL,KAAK;YACL,QAAQ,EAAE,SAAS,CAAC,QAAQ;YAC5B,QAAQ,EAAE,iBAAiB,CAAC,MAAM,CAAC;YACnC,MAAM;SACP,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,mCAAmC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACzF,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC","debug_id":"cd65973d-ca13-5498-8d6b-ff056b093631"}
@@ -1,4 +1,4 @@
1
- type SearchScope = "class" | "assignment" | "event" | "syllabus" | "worksheet" | "file" | "announcement" | "section";
1
+ type SearchScope = "class" | "assignment" | "event" | "syllabus" | "worksheet" | "file" | "announcement" | "section" | "discussion" | "submission";
2
2
  type SearchResult = {
3
3
  id: string;
4
4
  type: SearchScope;
@@ -1 +1 @@
1
- {"version":3,"file":"search.d.ts","sourceRoot":"/","sources":["services/search.ts"],"names":[],"mappings":"AAKA,KAAK,WAAW,GACZ,OAAO,GACP,YAAY,GACZ,OAAO,GACP,UAAU,GACV,WAAW,GACX,MAAM,GACN,cAAc,GACd,SAAS,CAAC;AAEd,KAAK,YAAY,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACpB,CAAC;AA6CF,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE;;aA0BR,YAAY,EAAE;GA6ShD;AAYD;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE;;aAIP,YAAY,EAAE;GAgHhD"}
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"/","sources":["services/search.ts"],"names":[],"mappings":"AAKA,KAAK,WAAW,GACZ,OAAO,GACP,YAAY,GACZ,OAAO,GACP,UAAU,GACV,WAAW,GACX,MAAM,GACN,cAAc,GACd,SAAS,GACT,YAAY,GACZ,YAAY,CAAC;AAEjB,KAAK,YAAY,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACpB,CAAC;AA+CF,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE;;aA0BR,YAAY,EAAE;GA6ShD;AAeD;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE;;aAIP,YAAY,EAAE;GAiIhD"}
@@ -1,5 +1,5 @@
1
1
 
2
- !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]="95067932-0f2f-5d5f-bd33-0e2156d5ed88")}catch(e){}}();
2
+ !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]="cb499420-fdcc-5847-9586-9b9927cf72a2")}catch(e){}}();
3
3
  import { prisma } from "../lib/prisma.js";
4
4
  import { generateEmbedding } from "./embedding.js";
5
5
  import { logger } from "../utils/logger.js";
@@ -35,6 +35,8 @@ const trimResults = (results, limit) => results
35
35
  file: 5,
36
36
  announcement: 6,
37
37
  section: 7,
38
+ discussion: 8,
39
+ submission: 9,
38
40
  };
39
41
  const priorityDiff = priority[a.type] - priority[b.type];
40
42
  if (priorityDiff !== 0)
@@ -356,6 +358,9 @@ const SOURCE_TYPE_TO_SCOPE = {
356
358
  ANNOUNCEMENT: "announcement",
357
359
  FILE: "file",
358
360
  SECTION: "section",
361
+ DISCUSSION: "discussion",
362
+ SUBMISSION: "submission",
363
+ SYLLABUS: "syllabus",
359
364
  };
360
365
  const MIN_SIMILARITY = 0.25;
361
366
  /**
@@ -453,6 +458,26 @@ export async function searchSemanticGlobal(userId, input) {
453
458
  title = section?.name ?? title;
454
459
  href = `/class/${hit.classId}/assignments`;
455
460
  }
461
+ else if (scope === "discussion") {
462
+ const discussion = await prisma.discussion.findUnique({
463
+ where: { id: hit.sourceId },
464
+ select: { title: true },
465
+ });
466
+ title = discussion?.title ?? title;
467
+ href = `/class/${hit.classId}/discussions/${hit.sourceId}`;
468
+ }
469
+ else if (scope === "submission") {
470
+ const submission = await prisma.submission.findUnique({
471
+ where: { id: hit.sourceId },
472
+ select: { assignment: { select: { title: true, id: true } } },
473
+ });
474
+ title = submission?.assignment.title ? `Submission: ${submission.assignment.title}` : title;
475
+ href = submission?.assignment.id ? `/class/${hit.classId}/assignment/${submission.assignment.id}` : href;
476
+ }
477
+ else if (scope === "syllabus") {
478
+ title = `${className} Syllabus`;
479
+ href = `/class/${hit.classId}/syllabus`;
480
+ }
456
481
  results.push({
457
482
  id: `semantic:${hit.sourceId}`,
458
483
  type: scope,
@@ -467,4 +492,4 @@ export async function searchSemanticGlobal(userId, input) {
467
492
  return { query, results };
468
493
  }
469
494
  //# sourceMappingURL=search.js.map
470
- //# debugId=95067932-0f2f-5d5f-bd33-0e2156d5ed88
495
+ //# debugId=cb499420-fdcc-5847-9586-9b9927cf72a2
@@ -1 +1 @@
1
- {"version":3,"file":"search.js","sources":["services/search.ts"],"sourceRoot":"/","sourcesContent":["import { prisma } from \"../lib/prisma.js\";\nimport { generateEmbedding } from \"./embedding.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { EmbeddingSourceType } from \"@prisma/client\";\n\ntype SearchScope =\n | \"class\"\n | \"assignment\"\n | \"event\"\n | \"syllabus\"\n | \"worksheet\"\n | \"file\"\n | \"announcement\"\n | \"section\";\n\ntype SearchResult = {\n id: string;\n type: SearchScope;\n title: string;\n subtitle: string;\n classId: string;\n className: string;\n href: string;\n matchedText?: string | null;\n date?: Date | null;\n};\n\nconst SEARCH_LIMIT = 12;\n\nconst contains = (query: string) => ({\n contains: query,\n mode: \"insensitive\" as const,\n});\n\nconst includesToken = (query: string, ...tokens: string[]) =>\n tokens.some((token) => token.includes(query.toLowerCase()));\n\nconst excerpt = (value: string | null | undefined, query: string) => {\n if (!value) return null;\n const trimmed = value.replace(/\\s+/g, \" \").trim();\n if (!trimmed) return null;\n if (!query) return trimmed.slice(0, 140);\n\n const index = trimmed.toLowerCase().indexOf(query.toLowerCase());\n if (index < 0) return trimmed.slice(0, 140);\n\n const start = Math.max(0, index - 48);\n const end = Math.min(trimmed.length, index + query.length + 92);\n return `${start > 0 ? \"...\" : \"\"}${trimmed.slice(start, end)}${end < trimmed.length ? \"...\" : \"\"}`;\n};\n\nconst trimResults = (results: SearchResult[], limit: number) =>\n results\n .sort((a, b) => {\n const priority: Record<SearchScope, number> = {\n class: 0,\n assignment: 1,\n event: 2,\n syllabus: 3,\n worksheet: 4,\n file: 5,\n announcement: 6,\n section: 7,\n };\n const priorityDiff = priority[a.type] - priority[b.type];\n if (priorityDiff !== 0) return priorityDiff;\n return (b.date?.getTime() ?? 0) - (a.date?.getTime() ?? 0);\n })\n .slice(0, limit);\n\nexport async function searchGlobalClasses(\n userId: string,\n input: { query?: string; limit?: number }\n) {\n const rawQuery = input.query?.trim() ?? \"\";\n const query = rawQuery.slice(0, 80);\n const limit = Math.min(Math.max(input.limit ?? SEARCH_LIMIT, 1), 30);\n\n const memberships = await prisma.class.findMany({\n where: {\n OR: [\n { teachers: { some: { id: userId } } },\n { students: { some: { id: userId } } },\n ],\n },\n select: {\n id: true,\n name: true,\n section: true,\n subject: true,\n syllabus: true,\n teachers: { where: { id: userId }, select: { id: true } },\n students: { where: { id: userId }, select: { id: true } },\n },\n });\n\n const allClassIds = memberships.map((cls) => cls.id);\n if (allClassIds.length === 0) {\n return { query, results: [] as SearchResult[] };\n }\n\n const teacherClassIds = memberships\n .filter((cls) => cls.teachers.length > 0)\n .map((cls) => cls.id);\n const studentClassIds = memberships\n .filter((cls) => cls.students.length > 0 && cls.teachers.length === 0)\n .map((cls) => cls.id);\n const classById = new Map(memberships.map((cls) => [cls.id, cls]));\n\n const queryFilters = query\n ? {\n class: [\n { name: contains(query) },\n { section: contains(query) },\n { subject: contains(query) },\n ],\n assignment: [\n { title: contains(query) },\n { instructions: contains(query) },\n ],\n event: [\n { name: contains(query) },\n { location: contains(query) },\n { remarks: contains(query) },\n ],\n worksheet: [{ name: contains(query) }],\n file: [{ name: contains(query) }, { type: contains(query) }],\n announcement: [{ remarks: contains(query) }],\n section: [{ name: contains(query) }],\n }\n : null;\n\n const assignmentAccess = [\n ...(teacherClassIds.length > 0\n ? [{ classId: { in: teacherClassIds } }]\n : []),\n ...(studentClassIds.length > 0\n ? [\n {\n classId: { in: studentClassIds },\n OR: [\n { assignedTo: { some: { id: userId } } },\n { assignedTo: { none: {} } },\n ],\n },\n ]\n : []),\n ];\n\n const [\n classes,\n assignments,\n events,\n worksheets,\n files,\n announcements,\n sections,\n ] = await Promise.all([\n prisma.class.findMany({\n where: {\n id: { in: allClassIds },\n ...(queryFilters ? { OR: queryFilters.class } : {}),\n },\n select: { id: true, name: true, section: true, subject: true },\n take: limit,\n }),\n prisma.assignment.findMany({\n where: {\n template: false,\n AND: [\n ...(queryFilters ? [{ OR: queryFilters.assignment }] : []),\n ...(assignmentAccess.length > 0 ? [{ OR: assignmentAccess }] : []),\n ],\n },\n select: {\n id: true,\n title: true,\n instructions: true,\n dueDate: true,\n modifiedAt: true,\n classId: true,\n class: { select: { name: true } },\n },\n orderBy: { dueDate: \"asc\" },\n take: limit,\n }),\n prisma.event.findMany({\n where: {\n classId: { in: allClassIds },\n ...(queryFilters ? { OR: queryFilters.event } : {}),\n },\n select: {\n id: true,\n name: true,\n location: true,\n remarks: true,\n startTime: true,\n classId: true,\n class: { select: { name: true } },\n },\n orderBy: { startTime: \"asc\" },\n take: limit,\n }),\n prisma.worksheet.findMany({\n where: {\n classId: { in: allClassIds },\n ...(queryFilters && !includesToken(query, \"worksheet\", \"worksheets\")\n ? { OR: queryFilters.worksheet }\n : {}),\n },\n select: {\n id: true,\n name: true,\n updatedAt: true,\n classId: true,\n class: { select: { name: true } },\n },\n orderBy: { updatedAt: \"desc\" },\n take: limit,\n }),\n prisma.file.findMany({\n where: {\n ...(queryFilters ? { OR: queryFilters.file } : {}),\n AND: [\n {\n OR: [\n { folder: { classId: { in: allClassIds } } },\n { classDraftId: { in: teacherClassIds } },\n {\n assignment: {\n OR: assignmentAccess,\n },\n },\n { announcement: { classId: { in: allClassIds } } },\n ],\n },\n ],\n },\n select: {\n id: true,\n name: true,\n type: true,\n uploadedAt: true,\n folder: { select: { classId: true, class: { select: { name: true } } } },\n classDraft: { select: { id: true, name: true } },\n assignment: { select: { classId: true, class: { select: { name: true } } } },\n announcement: { select: { classId: true, class: { select: { name: true } } } },\n },\n orderBy: { uploadedAt: \"desc\" },\n take: limit,\n }),\n prisma.announcement.findMany({\n where: {\n classId: { in: allClassIds },\n ...(queryFilters ? { OR: queryFilters.announcement } : {}),\n },\n select: {\n id: true,\n remarks: true,\n createdAt: true,\n classId: true,\n class: { select: { name: true } },\n },\n orderBy: { createdAt: \"desc\" },\n take: limit,\n }),\n prisma.section.findMany({\n where: {\n classId: { in: allClassIds },\n ...(queryFilters && !includesToken(query, \"section\", \"sections\", \"assignment\", \"assignments\")\n ? { OR: queryFilters.section }\n : {}),\n },\n select: {\n id: true,\n name: true,\n classId: true,\n class: { select: { name: true } },\n },\n take: limit,\n }),\n ]);\n\n const results: SearchResult[] = [\n ...classes.map((cls) => ({\n id: cls.id,\n type: \"class\" as const,\n title: cls.name,\n subtitle: [cls.subject, cls.section].filter(Boolean).join(\" · \"),\n classId: cls.id,\n className: cls.name,\n href: `/class/${cls.id}`,\n })),\n ...assignments.map((assignment) => ({\n id: assignment.id,\n type: \"assignment\" as const,\n title: assignment.title,\n subtitle: `${assignment.class.name} · Assignment`,\n classId: assignment.classId,\n className: assignment.class.name,\n href: `/class/${assignment.classId}/assignment/${assignment.id}`,\n matchedText: excerpt(assignment.instructions, query),\n date: assignment.dueDate ?? assignment.modifiedAt,\n })),\n ...events.map((event) => ({\n id: event.id,\n type: \"event\" as const,\n title: event.name || \"Untitled event\",\n subtitle: `${event.class?.name ?? \"Class\"} · Event`,\n classId: event.classId!,\n className: event.class?.name ?? \"Class\",\n href: `/class/${event.classId}/attendance/${event.id}`,\n matchedText: excerpt(event.location || event.remarks, query),\n date: event.startTime,\n })),\n ...memberships\n .filter((cls) => {\n if (!cls.syllabus) return false;\n if (!query) return true;\n return (\n includesToken(query, \"syllabus\") ||\n cls.name.toLowerCase().includes(query.toLowerCase()) ||\n cls.subject.toLowerCase().includes(query.toLowerCase()) ||\n cls.syllabus.toLowerCase().includes(query.toLowerCase())\n );\n })\n .slice(0, limit)\n .map((cls) => ({\n id: `${cls.id}:syllabus`,\n type: \"syllabus\" as const,\n title: `${cls.name} syllabus`,\n subtitle: `${cls.subject} · Syllabus`,\n classId: cls.id,\n className: cls.name,\n href: `/class/${cls.id}/syllabus`,\n matchedText: excerpt(cls.syllabus, query),\n })),\n ...worksheets.map((worksheet) => ({\n id: worksheet.id,\n type: \"worksheet\" as const,\n title: worksheet.name,\n subtitle: `${worksheet.class?.name ?? \"Class\"} · Worksheet`,\n classId: worksheet.classId,\n className: worksheet.class?.name ?? \"Class\",\n href: `/class/${worksheet.classId}/worksheets`,\n date: worksheet.updatedAt,\n })),\n ...files.flatMap((file) => {\n const classId =\n file.folder?.classId ??\n file.classDraft?.id ??\n file.assignment?.classId ??\n file.announcement?.classId;\n const className =\n file.folder?.class?.name ??\n file.classDraft?.name ??\n file.assignment?.class?.name ??\n file.announcement?.class?.name ??\n (classId ? classById.get(classId)?.name : undefined);\n\n if (!classId || !className) return [];\n\n return [\n {\n id: file.id,\n type: \"file\" as const,\n title: file.name,\n subtitle: `${className} · File`,\n classId,\n className,\n href: `/class/${classId}/files`,\n matchedText: file.type,\n date: file.uploadedAt,\n },\n ];\n }),\n ...announcements.map((announcement) => ({\n id: announcement.id,\n type: \"announcement\" as const,\n title: excerpt(announcement.remarks, query) ?? \"Announcement\",\n subtitle: `${announcement.class.name} · Announcement`,\n classId: announcement.classId,\n className: announcement.class.name,\n href: `/class/${announcement.classId}`,\n matchedText: excerpt(announcement.remarks, query),\n date: announcement.createdAt,\n })),\n ...sections.map((section) => ({\n id: section.id,\n type: \"section\" as const,\n title: section.name,\n subtitle: `${section.class.name} · Section`,\n classId: section.classId,\n className: section.class.name,\n href: `/class/${section.classId}/assignments`,\n })),\n ];\n\n return { query, results: trimResults(results, limit) };\n}\n\nconst SOURCE_TYPE_TO_SCOPE: Record<EmbeddingSourceType, SearchScope> = {\n ASSIGNMENT: \"assignment\",\n WORKSHEET: \"worksheet\",\n ANNOUNCEMENT: \"announcement\",\n FILE: \"file\",\n SECTION: \"section\",\n};\n\nconst MIN_SIMILARITY = 0.25;\n\n/**\n * Cross-class semantic search via pgvector.\n * Generates an embedding for `query`, searches across all classes the user\n * belongs to, and maps hits back to SearchResult shape.\n */\nexport async function searchSemanticGlobal(\n userId: string,\n input: { query: string; limit?: number },\n) {\n const query = input.query.trim().slice(0, 200);\n if (!query) {\n return { query, results: [] as SearchResult[] };\n }\n const limit = Math.min(Math.max(input.limit ?? SEARCH_LIMIT, 1), 30);\n\n const memberships = await prisma.class.findMany({\n where: {\n OR: [\n { teachers: { some: { id: userId } } },\n { students: { some: { id: userId } } },\n ],\n },\n select: { id: true, name: true },\n });\n const allClassIds = memberships.map((cls) => cls.id);\n if (allClassIds.length === 0) {\n return { query, results: [] as SearchResult[] };\n }\n const classById = new Map(memberships.map((cls) => [cls.id, cls]));\n\n let queryVector: number[];\n try {\n queryVector = await generateEmbedding(query);\n } catch (err) {\n logger.error(\"Semantic search embedding failed\", { err });\n return { query, results: [] as SearchResult[] };\n }\n\n const vectorStr = `[${queryVector.join(\",\")}]`;\n\n type SemanticRow = {\n sourceType: EmbeddingSourceType;\n sourceId: string;\n classId: string;\n content: string;\n similarity: number;\n };\n\n const hits = await prisma.$queryRaw<SemanticRow[]>`\n SELECT DISTINCT ON (\"sourceType\", \"sourceId\")\n \"sourceType\",\n \"sourceId\",\n \"classId\",\n content,\n 1 - (vector <=> ${vectorStr}::vector) as similarity\n FROM \"Embedding\"\n WHERE \"classId\" = ANY(${allClassIds}::text[])\n ORDER BY \"sourceType\", \"sourceId\", vector <=> ${vectorStr}::vector\n LIMIT ${limit * 3}\n `;\n\n const filtered = hits\n .filter((h) => h.similarity >= MIN_SIMILARITY)\n .sort((a, b) => b.similarity - a.similarity)\n .slice(0, limit);\n\n const results: SearchResult[] = [];\n for (const hit of filtered) {\n const cls = classById.get(hit.classId);\n const className = cls?.name ?? \"Class\";\n const scope = SOURCE_TYPE_TO_SCOPE[hit.sourceType];\n if (!scope) continue;\n\n const snippet = hit.content.replace(/\\s+/g, \" \").trim().slice(0, 140);\n\n let title = snippet.slice(0, 60);\n let href = `/class/${hit.classId}`;\n\n if (scope === \"assignment\") {\n const assignment = await prisma.assignment.findUnique({\n where: { id: hit.sourceId },\n select: { title: true },\n });\n title = assignment?.title ?? title;\n href = `/class/${hit.classId}/assignment/${hit.sourceId}`;\n } else if (scope === \"worksheet\") {\n const worksheet = await prisma.worksheet.findUnique({\n where: { id: hit.sourceId },\n select: { name: true },\n });\n title = worksheet?.name ?? title;\n href = `/class/${hit.classId}/worksheets`;\n } else if (scope === \"announcement\") {\n href = `/class/${hit.classId}`;\n } else if (scope === \"file\") {\n const file = await prisma.file.findUnique({\n where: { id: hit.sourceId },\n select: { name: true },\n });\n title = file?.name ?? title;\n href = `/class/${hit.classId}/files`;\n } else if (scope === \"section\") {\n const section = await prisma.section.findUnique({\n where: { id: hit.sourceId },\n select: { name: true },\n });\n title = section?.name ?? title;\n href = `/class/${hit.classId}/assignments`;\n }\n\n results.push({\n id: `semantic:${hit.sourceId}`,\n type: scope,\n title,\n subtitle: `${className} · ${scope.charAt(0).toUpperCase() + scope.slice(1)}`,\n classId: hit.classId,\n className,\n href,\n matchedText: snippet,\n });\n }\n\n return { query, results };\n}\n"],"names":[],"mappings":"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","debug_id":"95067932-0f2f-5d5f-bd33-0e2156d5ed88"}
1
+ {"version":3,"file":"search.js","sources":["services/search.ts"],"sourceRoot":"/","sourcesContent":["import { prisma } from \"../lib/prisma.js\";\nimport { generateEmbedding } from \"./embedding.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { EmbeddingSourceType } from \"@prisma/client\";\n\ntype SearchScope =\n | \"class\"\n | \"assignment\"\n | \"event\"\n | \"syllabus\"\n | \"worksheet\"\n | \"file\"\n | \"announcement\"\n | \"section\"\n | \"discussion\"\n | \"submission\";\n\ntype SearchResult = {\n id: string;\n type: SearchScope;\n title: string;\n subtitle: string;\n classId: string;\n className: string;\n href: string;\n matchedText?: string | null;\n date?: Date | null;\n};\n\nconst SEARCH_LIMIT = 12;\n\nconst contains = (query: string) => ({\n contains: query,\n mode: \"insensitive\" as const,\n});\n\nconst includesToken = (query: string, ...tokens: string[]) =>\n tokens.some((token) => token.includes(query.toLowerCase()));\n\nconst excerpt = (value: string | null | undefined, query: string) => {\n if (!value) return null;\n const trimmed = value.replace(/\\s+/g, \" \").trim();\n if (!trimmed) return null;\n if (!query) return trimmed.slice(0, 140);\n\n const index = trimmed.toLowerCase().indexOf(query.toLowerCase());\n if (index < 0) return trimmed.slice(0, 140);\n\n const start = Math.max(0, index - 48);\n const end = Math.min(trimmed.length, index + query.length + 92);\n return `${start > 0 ? \"...\" : \"\"}${trimmed.slice(start, end)}${end < trimmed.length ? \"...\" : \"\"}`;\n};\n\nconst trimResults = (results: SearchResult[], limit: number) =>\n results\n .sort((a, b) => {\n const priority: Record<SearchScope, number> = {\n class: 0,\n assignment: 1,\n event: 2,\n syllabus: 3,\n worksheet: 4,\n file: 5,\n announcement: 6,\n section: 7,\n discussion: 8,\n submission: 9,\n };\n const priorityDiff = priority[a.type] - priority[b.type];\n if (priorityDiff !== 0) return priorityDiff;\n return (b.date?.getTime() ?? 0) - (a.date?.getTime() ?? 0);\n })\n .slice(0, limit);\n\nexport async function searchGlobalClasses(\n userId: string,\n input: { query?: string; limit?: number }\n) {\n const rawQuery = input.query?.trim() ?? \"\";\n const query = rawQuery.slice(0, 80);\n const limit = Math.min(Math.max(input.limit ?? SEARCH_LIMIT, 1), 30);\n\n const memberships = await prisma.class.findMany({\n where: {\n OR: [\n { teachers: { some: { id: userId } } },\n { students: { some: { id: userId } } },\n ],\n },\n select: {\n id: true,\n name: true,\n section: true,\n subject: true,\n syllabus: true,\n teachers: { where: { id: userId }, select: { id: true } },\n students: { where: { id: userId }, select: { id: true } },\n },\n });\n\n const allClassIds = memberships.map((cls) => cls.id);\n if (allClassIds.length === 0) {\n return { query, results: [] as SearchResult[] };\n }\n\n const teacherClassIds = memberships\n .filter((cls) => cls.teachers.length > 0)\n .map((cls) => cls.id);\n const studentClassIds = memberships\n .filter((cls) => cls.students.length > 0 && cls.teachers.length === 0)\n .map((cls) => cls.id);\n const classById = new Map(memberships.map((cls) => [cls.id, cls]));\n\n const queryFilters = query\n ? {\n class: [\n { name: contains(query) },\n { section: contains(query) },\n { subject: contains(query) },\n ],\n assignment: [\n { title: contains(query) },\n { instructions: contains(query) },\n ],\n event: [\n { name: contains(query) },\n { location: contains(query) },\n { remarks: contains(query) },\n ],\n worksheet: [{ name: contains(query) }],\n file: [{ name: contains(query) }, { type: contains(query) }],\n announcement: [{ remarks: contains(query) }],\n section: [{ name: contains(query) }],\n }\n : null;\n\n const assignmentAccess = [\n ...(teacherClassIds.length > 0\n ? [{ classId: { in: teacherClassIds } }]\n : []),\n ...(studentClassIds.length > 0\n ? [\n {\n classId: { in: studentClassIds },\n OR: [\n { assignedTo: { some: { id: userId } } },\n { assignedTo: { none: {} } },\n ],\n },\n ]\n : []),\n ];\n\n const [\n classes,\n assignments,\n events,\n worksheets,\n files,\n announcements,\n sections,\n ] = await Promise.all([\n prisma.class.findMany({\n where: {\n id: { in: allClassIds },\n ...(queryFilters ? { OR: queryFilters.class } : {}),\n },\n select: { id: true, name: true, section: true, subject: true },\n take: limit,\n }),\n prisma.assignment.findMany({\n where: {\n template: false,\n AND: [\n ...(queryFilters ? [{ OR: queryFilters.assignment }] : []),\n ...(assignmentAccess.length > 0 ? [{ OR: assignmentAccess }] : []),\n ],\n },\n select: {\n id: true,\n title: true,\n instructions: true,\n dueDate: true,\n modifiedAt: true,\n classId: true,\n class: { select: { name: true } },\n },\n orderBy: { dueDate: \"asc\" },\n take: limit,\n }),\n prisma.event.findMany({\n where: {\n classId: { in: allClassIds },\n ...(queryFilters ? { OR: queryFilters.event } : {}),\n },\n select: {\n id: true,\n name: true,\n location: true,\n remarks: true,\n startTime: true,\n classId: true,\n class: { select: { name: true } },\n },\n orderBy: { startTime: \"asc\" },\n take: limit,\n }),\n prisma.worksheet.findMany({\n where: {\n classId: { in: allClassIds },\n ...(queryFilters && !includesToken(query, \"worksheet\", \"worksheets\")\n ? { OR: queryFilters.worksheet }\n : {}),\n },\n select: {\n id: true,\n name: true,\n updatedAt: true,\n classId: true,\n class: { select: { name: true } },\n },\n orderBy: { updatedAt: \"desc\" },\n take: limit,\n }),\n prisma.file.findMany({\n where: {\n ...(queryFilters ? { OR: queryFilters.file } : {}),\n AND: [\n {\n OR: [\n { folder: { classId: { in: allClassIds } } },\n { classDraftId: { in: teacherClassIds } },\n {\n assignment: {\n OR: assignmentAccess,\n },\n },\n { announcement: { classId: { in: allClassIds } } },\n ],\n },\n ],\n },\n select: {\n id: true,\n name: true,\n type: true,\n uploadedAt: true,\n folder: { select: { classId: true, class: { select: { name: true } } } },\n classDraft: { select: { id: true, name: true } },\n assignment: { select: { classId: true, class: { select: { name: true } } } },\n announcement: { select: { classId: true, class: { select: { name: true } } } },\n },\n orderBy: { uploadedAt: \"desc\" },\n take: limit,\n }),\n prisma.announcement.findMany({\n where: {\n classId: { in: allClassIds },\n ...(queryFilters ? { OR: queryFilters.announcement } : {}),\n },\n select: {\n id: true,\n remarks: true,\n createdAt: true,\n classId: true,\n class: { select: { name: true } },\n },\n orderBy: { createdAt: \"desc\" },\n take: limit,\n }),\n prisma.section.findMany({\n where: {\n classId: { in: allClassIds },\n ...(queryFilters && !includesToken(query, \"section\", \"sections\", \"assignment\", \"assignments\")\n ? { OR: queryFilters.section }\n : {}),\n },\n select: {\n id: true,\n name: true,\n classId: true,\n class: { select: { name: true } },\n },\n take: limit,\n }),\n ]);\n\n const results: SearchResult[] = [\n ...classes.map((cls) => ({\n id: cls.id,\n type: \"class\" as const,\n title: cls.name,\n subtitle: [cls.subject, cls.section].filter(Boolean).join(\" · \"),\n classId: cls.id,\n className: cls.name,\n href: `/class/${cls.id}`,\n })),\n ...assignments.map((assignment) => ({\n id: assignment.id,\n type: \"assignment\" as const,\n title: assignment.title,\n subtitle: `${assignment.class.name} · Assignment`,\n classId: assignment.classId,\n className: assignment.class.name,\n href: `/class/${assignment.classId}/assignment/${assignment.id}`,\n matchedText: excerpt(assignment.instructions, query),\n date: assignment.dueDate ?? assignment.modifiedAt,\n })),\n ...events.map((event) => ({\n id: event.id,\n type: \"event\" as const,\n title: event.name || \"Untitled event\",\n subtitle: `${event.class?.name ?? \"Class\"} · Event`,\n classId: event.classId!,\n className: event.class?.name ?? \"Class\",\n href: `/class/${event.classId}/attendance/${event.id}`,\n matchedText: excerpt(event.location || event.remarks, query),\n date: event.startTime,\n })),\n ...memberships\n .filter((cls) => {\n if (!cls.syllabus) return false;\n if (!query) return true;\n return (\n includesToken(query, \"syllabus\") ||\n cls.name.toLowerCase().includes(query.toLowerCase()) ||\n cls.subject.toLowerCase().includes(query.toLowerCase()) ||\n cls.syllabus.toLowerCase().includes(query.toLowerCase())\n );\n })\n .slice(0, limit)\n .map((cls) => ({\n id: `${cls.id}:syllabus`,\n type: \"syllabus\" as const,\n title: `${cls.name} syllabus`,\n subtitle: `${cls.subject} · Syllabus`,\n classId: cls.id,\n className: cls.name,\n href: `/class/${cls.id}/syllabus`,\n matchedText: excerpt(cls.syllabus, query),\n })),\n ...worksheets.map((worksheet) => ({\n id: worksheet.id,\n type: \"worksheet\" as const,\n title: worksheet.name,\n subtitle: `${worksheet.class?.name ?? \"Class\"} · Worksheet`,\n classId: worksheet.classId,\n className: worksheet.class?.name ?? \"Class\",\n href: `/class/${worksheet.classId}/worksheets`,\n date: worksheet.updatedAt,\n })),\n ...files.flatMap((file) => {\n const classId =\n file.folder?.classId ??\n file.classDraft?.id ??\n file.assignment?.classId ??\n file.announcement?.classId;\n const className =\n file.folder?.class?.name ??\n file.classDraft?.name ??\n file.assignment?.class?.name ??\n file.announcement?.class?.name ??\n (classId ? classById.get(classId)?.name : undefined);\n\n if (!classId || !className) return [];\n\n return [\n {\n id: file.id,\n type: \"file\" as const,\n title: file.name,\n subtitle: `${className} · File`,\n classId,\n className,\n href: `/class/${classId}/files`,\n matchedText: file.type,\n date: file.uploadedAt,\n },\n ];\n }),\n ...announcements.map((announcement) => ({\n id: announcement.id,\n type: \"announcement\" as const,\n title: excerpt(announcement.remarks, query) ?? \"Announcement\",\n subtitle: `${announcement.class.name} · Announcement`,\n classId: announcement.classId,\n className: announcement.class.name,\n href: `/class/${announcement.classId}`,\n matchedText: excerpt(announcement.remarks, query),\n date: announcement.createdAt,\n })),\n ...sections.map((section) => ({\n id: section.id,\n type: \"section\" as const,\n title: section.name,\n subtitle: `${section.class.name} · Section`,\n classId: section.classId,\n className: section.class.name,\n href: `/class/${section.classId}/assignments`,\n })),\n ];\n\n return { query, results: trimResults(results, limit) };\n}\n\nconst SOURCE_TYPE_TO_SCOPE: Record<EmbeddingSourceType, SearchScope> = {\n ASSIGNMENT: \"assignment\",\n WORKSHEET: \"worksheet\",\n ANNOUNCEMENT: \"announcement\",\n FILE: \"file\",\n SECTION: \"section\",\n DISCUSSION: \"discussion\",\n SUBMISSION: \"submission\",\n SYLLABUS: \"syllabus\",\n};\n\nconst MIN_SIMILARITY = 0.25;\n\n/**\n * Cross-class semantic search via pgvector.\n * Generates an embedding for `query`, searches across all classes the user\n * belongs to, and maps hits back to SearchResult shape.\n */\nexport async function searchSemanticGlobal(\n userId: string,\n input: { query: string; limit?: number },\n) {\n const query = input.query.trim().slice(0, 200);\n if (!query) {\n return { query, results: [] as SearchResult[] };\n }\n const limit = Math.min(Math.max(input.limit ?? SEARCH_LIMIT, 1), 30);\n\n const memberships = await prisma.class.findMany({\n where: {\n OR: [\n { teachers: { some: { id: userId } } },\n { students: { some: { id: userId } } },\n ],\n },\n select: { id: true, name: true },\n });\n const allClassIds = memberships.map((cls) => cls.id);\n if (allClassIds.length === 0) {\n return { query, results: [] as SearchResult[] };\n }\n const classById = new Map(memberships.map((cls) => [cls.id, cls]));\n\n let queryVector: number[];\n try {\n queryVector = await generateEmbedding(query);\n } catch (err) {\n logger.error(\"Semantic search embedding failed\", { err });\n return { query, results: [] as SearchResult[] };\n }\n\n const vectorStr = `[${queryVector.join(\",\")}]`;\n\n type SemanticRow = {\n sourceType: EmbeddingSourceType;\n sourceId: string;\n classId: string;\n content: string;\n similarity: number;\n };\n\n const hits = await prisma.$queryRaw<SemanticRow[]>`\n SELECT DISTINCT ON (\"sourceType\", \"sourceId\")\n \"sourceType\",\n \"sourceId\",\n \"classId\",\n content,\n 1 - (vector <=> ${vectorStr}::vector) as similarity\n FROM \"Embedding\"\n WHERE \"classId\" = ANY(${allClassIds}::text[])\n ORDER BY \"sourceType\", \"sourceId\", vector <=> ${vectorStr}::vector\n LIMIT ${limit * 3}\n `;\n\n const filtered = hits\n .filter((h) => h.similarity >= MIN_SIMILARITY)\n .sort((a, b) => b.similarity - a.similarity)\n .slice(0, limit);\n\n const results: SearchResult[] = [];\n for (const hit of filtered) {\n const cls = classById.get(hit.classId);\n const className = cls?.name ?? \"Class\";\n const scope = SOURCE_TYPE_TO_SCOPE[hit.sourceType];\n if (!scope) continue;\n\n const snippet = hit.content.replace(/\\s+/g, \" \").trim().slice(0, 140);\n\n let title = snippet.slice(0, 60);\n let href = `/class/${hit.classId}`;\n\n if (scope === \"assignment\") {\n const assignment = await prisma.assignment.findUnique({\n where: { id: hit.sourceId },\n select: { title: true },\n });\n title = assignment?.title ?? title;\n href = `/class/${hit.classId}/assignment/${hit.sourceId}`;\n } else if (scope === \"worksheet\") {\n const worksheet = await prisma.worksheet.findUnique({\n where: { id: hit.sourceId },\n select: { name: true },\n });\n title = worksheet?.name ?? title;\n href = `/class/${hit.classId}/worksheets`;\n } else if (scope === \"announcement\") {\n href = `/class/${hit.classId}`;\n } else if (scope === \"file\") {\n const file = await prisma.file.findUnique({\n where: { id: hit.sourceId },\n select: { name: true },\n });\n title = file?.name ?? title;\n href = `/class/${hit.classId}/files`;\n } else if (scope === \"section\") {\n const section = await prisma.section.findUnique({\n where: { id: hit.sourceId },\n select: { name: true },\n });\n title = section?.name ?? title;\n href = `/class/${hit.classId}/assignments`;\n } else if (scope === \"discussion\") {\n const discussion = await prisma.discussion.findUnique({\n where: { id: hit.sourceId },\n select: { title: true },\n });\n title = discussion?.title ?? title;\n href = `/class/${hit.classId}/discussions/${hit.sourceId}`;\n } else if (scope === \"submission\") {\n const submission = await prisma.submission.findUnique({\n where: { id: hit.sourceId },\n select: { assignment: { select: { title: true, id: true } } },\n });\n title = submission?.assignment.title ? `Submission: ${submission.assignment.title}` : title;\n href = submission?.assignment.id ? `/class/${hit.classId}/assignment/${submission.assignment.id}` : href;\n } else if (scope === \"syllabus\") {\n title = `${className} Syllabus`;\n href = `/class/${hit.classId}/syllabus`;\n }\n\n results.push({\n id: `semantic:${hit.sourceId}`,\n type: scope,\n title,\n subtitle: `${className} · ${scope.charAt(0).toUpperCase() + scope.slice(1)}`,\n classId: hit.classId,\n className,\n href,\n matchedText: snippet,\n });\n }\n\n return { query, results };\n}\n"],"names":[],"mappings":"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","debug_id":"cb499420-fdcc-5847-9586-9b9927cf72a2"}