@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.
- package/dist/lib/inferDocumentFormat.d.ts +10 -0
- package/dist/lib/inferDocumentFormat.d.ts.map +1 -0
- package/dist/lib/inferDocumentFormat.js +48 -0
- package/dist/lib/inferDocumentFormat.js.map +1 -0
- package/dist/models/announcement.d.ts +45 -45
- package/dist/models/assignment.d.ts +75 -75
- package/dist/models/class.d.ts +13 -13
- package/dist/models/comment.d.ts +6 -6
- package/dist/models/conversation.d.ts +23 -23
- package/dist/models/event.d.ts +18 -18
- package/dist/models/file.d.ts +9 -9
- package/dist/models/labChat.d.ts +4 -4
- package/dist/models/message.d.ts +13 -13
- package/dist/models/newtonChat.d.ts +3 -3
- package/dist/models/notification.d.ts +4 -4
- package/dist/models/worksheet.d.ts +121 -121
- package/dist/pipelines/aiLabChat.d.ts +7 -1
- package/dist/pipelines/aiLabChat.d.ts.map +1 -1
- package/dist/pipelines/aiLabChat.js +145 -67
- package/dist/pipelines/aiLabChat.js.map +1 -1
- package/dist/pipelines/aiLabChatContract.d.ts +34 -195
- package/dist/pipelines/aiLabChatContract.d.ts.map +1 -1
- package/dist/pipelines/aiLabChatContract.js +9 -19
- package/dist/pipelines/aiLabChatContract.js.map +1 -1
- package/dist/pipelines/gradeWorksheet.d.ts +6 -6
- package/dist/pipelines/gradeWorksheet.d.ts.map +1 -1
- package/dist/pipelines/gradeWorksheet.js +75 -36
- package/dist/pipelines/gradeWorksheet.js.map +1 -1
- package/dist/pipelines/labChatPrompt.d.ts +8 -3
- package/dist/pipelines/labChatPrompt.d.ts.map +1 -1
- package/dist/pipelines/labChatPrompt.js +49 -14
- package/dist/pipelines/labChatPrompt.js.map +1 -1
- package/dist/pipelines/pdfToWorksheet.d.ts +1 -1
- package/dist/routers/_app.d.ts +524 -516
- package/dist/routers/_app.d.ts.map +1 -1
- package/dist/routers/announcement.d.ts +40 -40
- package/dist/routers/assignment.d.ts +121 -121
- package/dist/routers/class.d.ts +8 -8
- package/dist/routers/comment.d.ts +5 -5
- package/dist/routers/conversation.d.ts +6 -6
- package/dist/routers/discussion.d.ts +3 -3
- package/dist/routers/embedding.d.ts +6 -2
- package/dist/routers/embedding.d.ts.map +1 -1
- package/dist/routers/embedding.js +44 -36
- package/dist/routers/embedding.js.map +1 -1
- package/dist/routers/event.d.ts +18 -18
- package/dist/routers/file.d.ts +2 -2
- package/dist/routers/labChat.d.ts +3 -3
- package/dist/routers/notifications.d.ts +4 -4
- package/dist/routers/search.d.ts +2 -2
- package/dist/routers/worksheet.d.ts +44 -44
- package/dist/routes/aiStream.d.ts.map +1 -1
- package/dist/routes/aiStream.js +41 -11
- package/dist/routes/aiStream.js.map +1 -1
- package/dist/seedDatabase.d.ts +1 -1
- package/dist/services/aiChatStream.d.ts +18 -0
- package/dist/services/aiChatStream.d.ts.map +1 -1
- package/dist/services/aiChatStream.js +81 -11
- package/dist/services/aiChatStream.js.map +1 -1
- package/dist/services/aiModifierTools.d.ts +0 -16
- package/dist/services/aiModifierTools.d.ts.map +1 -1
- package/dist/services/aiModifierTools.js +112 -3
- package/dist/services/aiModifierTools.js.map +1 -1
- package/dist/services/aiProposalTools.d.ts.map +1 -1
- package/dist/services/aiProposalTools.js +25 -25
- package/dist/services/aiProposalTools.js.map +1 -1
- package/dist/services/announcement.d.ts +34 -34
- package/dist/services/assignment.d.ts +111 -111
- package/dist/services/assignment.d.ts.map +1 -1
- package/dist/services/assignment.js +4 -2
- package/dist/services/assignment.js.map +1 -1
- package/dist/services/class.d.ts +6 -6
- package/dist/services/class.d.ts.map +1 -1
- package/dist/services/class.js +7 -3
- package/dist/services/class.js.map +1 -1
- package/dist/services/comment.d.ts +5 -5
- package/dist/services/conversation.d.ts +6 -6
- package/dist/services/discussion.d.ts.map +1 -1
- package/dist/services/discussion.js +9 -2
- package/dist/services/discussion.js.map +1 -1
- package/dist/services/embedding.d.ts +19 -1
- package/dist/services/embedding.d.ts.map +1 -1
- package/dist/services/embedding.js +154 -8
- package/dist/services/embedding.js.map +1 -1
- package/dist/services/event.d.ts +18 -18
- package/dist/services/file.d.ts +4 -4
- package/dist/services/folder.d.ts.map +1 -1
- package/dist/services/folder.js +32 -2
- package/dist/services/folder.js.map +1 -1
- package/dist/services/labChat.d.ts +3 -3
- package/dist/services/notification.d.ts +4 -4
- package/dist/services/openaiDocumentGen.d.ts +25 -0
- package/dist/services/openaiDocumentGen.d.ts.map +1 -0
- package/dist/services/openaiDocumentGen.js +195 -0
- package/dist/services/openaiDocumentGen.js.map +1 -0
- package/dist/services/search.d.ts +1 -1
- package/dist/services/search.d.ts.map +1 -1
- package/dist/services/search.js +27 -2
- package/dist/services/search.js.map +1 -1
- package/dist/services/worksheet.d.ts +66 -49
- package/dist/services/worksheet.d.ts.map +1 -1
- package/dist/services/worksheet.js +48 -3
- package/dist/services/worksheet.js.map +1 -1
- package/dist/workers/processors/embedContent.d.ts.map +1 -1
- package/dist/workers/processors/embedContent.js +16 -25
- package/dist/workers/processors/embedContent.js.map +1 -1
- package/package.json +1 -1
- package/prisma/migrations/20260610140000_expand_embedding_source_types/migration.sql +4 -0
- package/prisma/schema.prisma +3 -0
- package/src/lib/inferDocumentFormat.ts +58 -0
- package/src/pipelines/aiLabChat.ts +185 -74
- package/src/pipelines/aiLabChatContract.ts +7 -17
- package/src/pipelines/gradeWorksheet.ts +95 -38
- package/src/pipelines/labChatPrompt.ts +61 -14
- package/src/routers/embedding.ts +44 -39
- package/src/routes/aiStream.ts +47 -9
- package/src/services/aiChatStream.ts +103 -8
- package/src/services/aiModifierTools.ts +154 -1
- package/src/services/aiProposalTools.ts +26 -25
- package/src/services/assignment.ts +3 -0
- package/src/services/class.ts +7 -1
- package/src/services/discussion.ts +13 -0
- package/src/services/embedding.ts +167 -6
- package/src/services/folder.ts +31 -0
- package/src/services/openaiDocumentGen.ts +237 -0
- package/src/services/search.ts +25 -1
- package/src/services/worksheet.ts +68 -1
- package/src/workers/processors/embedContent.ts +18 -22
- 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;
|
|
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"}
|
package/dist/services/search.js
CHANGED
|
@@ -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]="
|
|
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=
|
|
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":";;AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AA2B5C,MAAM,YAAY,GAAG,EAAE,CAAC;AAExB,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC;IACnC,QAAQ,EAAE,KAAK;IACf,IAAI,EAAE,aAAsB;CAC7B,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG,CAAC,KAAa,EAAE,GAAG,MAAgB,EAAE,EAAE,CAC3D,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;AAE9D,MAAM,OAAO,GAAG,CAAC,KAAgC,EAAE,KAAa,EAAE,EAAE;IAClE,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAClD,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,IAAI,CAAC,KAAK;QAAE,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAEzC,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;IACjE,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAE5C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,EAAE,CAAC,CAAC;IACtC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAChE,OAAO,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AACrG,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,OAAuB,EAAE,KAAa,EAAE,EAAE,CAC7D,OAAO;KACJ,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;IACb,MAAM,QAAQ,GAAgC;QAC5C,KAAK,EAAE,CAAC;QACR,UAAU,EAAE,CAAC;QACb,KAAK,EAAE,CAAC;QACR,QAAQ,EAAE,CAAC;QACX,SAAS,EAAE,CAAC;QACZ,IAAI,EAAE,CAAC;QACP,YAAY,EAAE,CAAC;QACf,OAAO,EAAE,CAAC;QACV,UAAU,EAAE,CAAC;QACb,UAAU,EAAE,CAAC;KACd,CAAC;IACF,MAAM,YAAY,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACzD,IAAI,YAAY,KAAK,CAAC;QAAE,OAAO,YAAY,CAAC;IAC5C,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;AAC7D,CAAC,CAAC;KACD,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AAErB,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAc,EACd,KAAyC;IAEzC,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC3C,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAErE,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;QAC9C,KAAK,EAAE;YACL,EAAE,EAAE;gBACF,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;gBACtC,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;aACvC;SACF;QACD,MAAM,EAAE;YACN,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,IAAI;YACV,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;YACzD,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;SAC1D;KACF,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACrD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAoB,EAAE,CAAC;IAClD,CAAC;IAED,MAAM,eAAe,GAAG,WAAW;SAChC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;SACxC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACxB,MAAM,eAAe,GAAG,WAAW;SAChC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC;SACrE,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACxB,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IAEnE,MAAM,YAAY,GAAG,KAAK;QACxB,CAAC,CAAC;YACE,KAAK,EAAE;gBACL,EAAE,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE;gBACzB,EAAE,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE;gBAC5B,EAAE,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE;aAC7B;YACD,UAAU,EAAE;gBACV,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE;gBAC1B,EAAE,YAAY,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE;aAClC;YACD,KAAK,EAAE;gBACL,EAAE,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE;gBACzB,EAAE,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE;gBAC7B,EAAE,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE;aAC7B;YACD,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACtC,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5D,YAAY,EAAE,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5C,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;SACrC;QACH,CAAC,CAAC,IAAI,CAAC;IAET,MAAM,gBAAgB,GAAG;QACvB,GAAG,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC;YAC5B,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,eAAe,EAAE,EAAE,CAAC;YACxC,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC;YAC5B,CAAC,CAAC;gBACE;oBACE,OAAO,EAAE,EAAE,EAAE,EAAE,eAAe,EAAE;oBAChC,EAAE,EAAE;wBACF,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;wBACxC,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE;qBAC7B;iBACF;aACF;YACH,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;IAEF,MAAM,CACJ,OAAO,EACP,WAAW,EACX,MAAM,EACN,UAAU,EACV,KAAK,EACL,aAAa,EACb,QAAQ,EACT,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACpB,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;YACpB,KAAK,EAAE;gBACL,EAAE,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE;gBACvB,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACpD;YACD,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE;YAC9D,IAAI,EAAE,KAAK;SACZ,CAAC;QACF,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC;YACzB,KAAK,EAAE;gBACL,QAAQ,EAAE,KAAK;gBACf,GAAG,EAAE;oBACH,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,YAAY,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC1D,GAAG,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;iBACnE;aACF;YACD,MAAM,EAAE;gBACN,EAAE,EAAE,IAAI;gBACR,KAAK,EAAE,IAAI;gBACX,YAAY,EAAE,IAAI;gBAClB,OAAO,EAAE,IAAI;gBACb,UAAU,EAAE,IAAI;gBAChB,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;aAClC;YACD,OAAO,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE;YAC3B,IAAI,EAAE,KAAK;SACZ,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;YACpB,KAAK,EAAE;gBACL,OAAO,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE;gBAC5B,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACpD;YACD,MAAM,EAAE;gBACN,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,IAAI;gBACV,QAAQ,EAAE,IAAI;gBACd,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE,IAAI;gBACf,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;aAClC;YACD,OAAO,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE;YAC7B,IAAI,EAAE,KAAK;SACZ,CAAC;QACF,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC;YACxB,KAAK,EAAE;gBACL,OAAO,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE;gBAC5B,GAAG,CAAC,YAAY,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,YAAY,CAAC;oBAClE,CAAC,CAAC,EAAE,EAAE,EAAE,YAAY,CAAC,SAAS,EAAE;oBAChC,CAAC,CAAC,EAAE,CAAC;aACR;YACD,MAAM,EAAE;gBACN,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,IAAI;gBACV,SAAS,EAAE,IAAI;gBACf,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;aAClC;YACD,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE;YAC9B,IAAI,EAAE,KAAK;SACZ,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;YACnB,KAAK,EAAE;gBACL,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAClD,GAAG,EAAE;oBACH;wBACE,EAAE,EAAE;4BACF,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE;4BAC5C,EAAE,YAAY,EAAE,EAAE,EAAE,EAAE,eAAe,EAAE,EAAE;4BACzC;gCACE,UAAU,EAAE;oCACV,EAAE,EAAE,gBAAgB;iCACrB;6BACF;4BACD,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE;yBACnD;qBACF;iBACF;aACF;YACD,MAAM,EAAE;gBACN,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,IAAI;gBACV,IAAI,EAAE,IAAI;gBACV,UAAU,EAAE,IAAI;gBAChB,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE;gBACxE,UAAU,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;gBAChD,UAAU,EAAE,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE;gBAC5E,YAAY,EAAE,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE;aAC/E;YACD,OAAO,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE;YAC/B,IAAI,EAAE,KAAK;SACZ,CAAC;QACF,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC;YAC3B,KAAK,EAAE;gBACL,OAAO,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE;gBAC5B,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,YAAY,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC3D;YACD,MAAM,EAAE;gBACN,EAAE,EAAE,IAAI;gBACR,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE,IAAI;gBACf,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;aAClC;YACD,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE;YAC9B,IAAI,EAAE,KAAK;SACZ,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;YACtB,KAAK,EAAE;gBACL,OAAO,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE;gBAC5B,GAAG,CAAC,YAAY,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,CAAC;oBAC3F,CAAC,CAAC,EAAE,EAAE,EAAE,YAAY,CAAC,OAAO,EAAE;oBAC9B,CAAC,CAAC,EAAE,CAAC;aACR;YACD,MAAM,EAAE;gBACN,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,IAAI;gBACV,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;aAClC;YACD,IAAI,EAAE,KAAK;SACZ,CAAC;KACH,CAAC,CAAC;IAEH,MAAM,OAAO,GAAmB;QAC9B,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACvB,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,IAAI,EAAE,OAAgB;YACtB,KAAK,EAAE,GAAG,CAAC,IAAI;YACf,QAAQ,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;YAChE,OAAO,EAAE,GAAG,CAAC,EAAE;YACf,SAAS,EAAE,GAAG,CAAC,IAAI;YACnB,IAAI,EAAE,UAAU,GAAG,CAAC,EAAE,EAAE;SACzB,CAAC,CAAC;QACH,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;YAClC,EAAE,EAAE,UAAU,CAAC,EAAE;YACjB,IAAI,EAAE,YAAqB;YAC3B,KAAK,EAAE,UAAU,CAAC,KAAK;YACvB,QAAQ,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,eAAe;YACjD,OAAO,EAAE,UAAU,CAAC,OAAO;YAC3B,SAAS,EAAE,UAAU,CAAC,KAAK,CAAC,IAAI;YAChC,IAAI,EAAE,UAAU,UAAU,CAAC,OAAO,eAAe,UAAU,CAAC,EAAE,EAAE;YAChE,WAAW,EAAE,OAAO,CAAC,UAAU,CAAC,YAAY,EAAE,KAAK,CAAC;YACpD,IAAI,EAAE,UAAU,CAAC,OAAO,IAAI,UAAU,CAAC,UAAU;SAClD,CAAC,CAAC;QACH,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACxB,EAAE,EAAE,KAAK,CAAC,EAAE;YACZ,IAAI,EAAE,OAAgB;YACtB,KAAK,EAAE,KAAK,CAAC,IAAI,IAAI,gBAAgB;YACrC,QAAQ,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE,IAAI,IAAI,OAAO,UAAU;YACnD,OAAO,EAAE,KAAK,CAAC,OAAQ;YACvB,SAAS,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI,IAAI,OAAO;YACvC,IAAI,EAAE,UAAU,KAAK,CAAC,OAAO,eAAe,KAAK,CAAC,EAAE,EAAE;YACtD,WAAW,EAAE,OAAO,CAAC,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC;YAC5D,IAAI,EAAE,KAAK,CAAC,SAAS;SACtB,CAAC,CAAC;QACH,GAAG,WAAW;aACX,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE;YACd,IAAI,CAAC,GAAG,CAAC,QAAQ;gBAAE,OAAO,KAAK,CAAC;YAChC,IAAI,CAAC,KAAK;gBAAE,OAAO,IAAI,CAAC;YACxB,OAAO,CACL,aAAa,CAAC,KAAK,EAAE,UAAU,CAAC;gBAChC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;gBACpD,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;gBACvD,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CACzD,CAAC;QACJ,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;aACf,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACb,EAAE,EAAE,GAAG,GAAG,CAAC,EAAE,WAAW;YACxB,IAAI,EAAE,UAAmB;YACzB,KAAK,EAAE,GAAG,GAAG,CAAC,IAAI,WAAW;YAC7B,QAAQ,EAAE,GAAG,GAAG,CAAC,OAAO,aAAa;YACrC,OAAO,EAAE,GAAG,CAAC,EAAE;YACf,SAAS,EAAE,GAAG,CAAC,IAAI;YACnB,IAAI,EAAE,UAAU,GAAG,CAAC,EAAE,WAAW;YACjC,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC;SAC1C,CAAC,CAAC;QACL,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YAChC,EAAE,EAAE,SAAS,CAAC,EAAE;YAChB,IAAI,EAAE,WAAoB;YAC1B,KAAK,EAAE,SAAS,CAAC,IAAI;YACrB,QAAQ,EAAE,GAAG,SAAS,CAAC,KAAK,EAAE,IAAI,IAAI,OAAO,cAAc;YAC3D,OAAO,EAAE,SAAS,CAAC,OAAO;YAC1B,SAAS,EAAE,SAAS,CAAC,KAAK,EAAE,IAAI,IAAI,OAAO;YAC3C,IAAI,EAAE,UAAU,SAAS,CAAC,OAAO,aAAa;YAC9C,IAAI,EAAE,SAAS,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YACxB,MAAM,OAAO,GACX,IAAI,CAAC,MAAM,EAAE,OAAO;gBACpB,IAAI,CAAC,UAAU,EAAE,EAAE;gBACnB,IAAI,CAAC,UAAU,EAAE,OAAO;gBACxB,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC;YAC7B,MAAM,SAAS,GACb,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI;gBACxB,IAAI,CAAC,UAAU,EAAE,IAAI;gBACrB,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,IAAI;gBAC5B,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE,IAAI;gBAC9B,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAEvD,IAAI,CAAC,OAAO,IAAI,CAAC,SAAS;gBAAE,OAAO,EAAE,CAAC;YAEtC,OAAO;gBACL;oBACE,EAAE,EAAE,IAAI,CAAC,EAAE;oBACX,IAAI,EAAE,MAAe;oBACrB,KAAK,EAAE,IAAI,CAAC,IAAI;oBAChB,QAAQ,EAAE,GAAG,SAAS,SAAS;oBAC/B,OAAO;oBACP,SAAS;oBACT,IAAI,EAAE,UAAU,OAAO,QAAQ;oBAC/B,WAAW,EAAE,IAAI,CAAC,IAAI;oBACtB,IAAI,EAAE,IAAI,CAAC,UAAU;iBACtB;aACF,CAAC;QACJ,CAAC,CAAC;QACF,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;YACtC,EAAE,EAAE,YAAY,CAAC,EAAE;YACnB,IAAI,EAAE,cAAuB;YAC7B,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,cAAc;YAC7D,QAAQ,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,iBAAiB;YACrD,OAAO,EAAE,YAAY,CAAC,OAAO;YAC7B,SAAS,EAAE,YAAY,CAAC,KAAK,CAAC,IAAI;YAClC,IAAI,EAAE,UAAU,YAAY,CAAC,OAAO,EAAE;YACtC,WAAW,EAAE,OAAO,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC;YACjD,IAAI,EAAE,YAAY,CAAC,SAAS;SAC7B,CAAC,CAAC;QACH,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAC5B,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,IAAI,EAAE,SAAkB;YACxB,KAAK,EAAE,OAAO,CAAC,IAAI;YACnB,QAAQ,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,YAAY;YAC3C,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI;YAC7B,IAAI,EAAE,UAAU,OAAO,CAAC,OAAO,cAAc;SAC9C,CAAC,CAAC;KACJ,CAAC;IAEF,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC;AACzD,CAAC;AAED,MAAM,oBAAoB,GAA6C;IACrE,UAAU,EAAE,YAAY;IACxB,SAAS,EAAE,WAAW;IACtB,YAAY,EAAE,cAAc;IAC5B,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;IAClB,UAAU,EAAE,YAAY;IACxB,UAAU,EAAE,YAAY;IACxB,QAAQ,EAAE,UAAU;CACrB,CAAC;AAEF,MAAM,cAAc,GAAG,IAAI,CAAC;AAE5B;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAAc,EACd,KAAwC;IAExC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC/C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAoB,EAAE,CAAC;IAClD,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAErE,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;QAC9C,KAAK,EAAE;YACL,EAAE,EAAE;gBACF,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;gBACtC,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;aACvC;SACF;QACD,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE;KACjC,CAAC,CAAC;IACH,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACrD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAoB,EAAE,CAAC;IAClD,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IAEnE,IAAI,WAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,WAAW,GAAG,MAAM,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,KAAK,CAAC,kCAAkC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;QAC1D,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAoB,EAAE,CAAC;IAClD,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IAU/C,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,SAAS,CAAe;;;;;;wBAM5B,SAAS;;4BAEL,WAAW;oDACa,SAAS;YACjD,KAAK,GAAG,CAAC;GAClB,CAAC;IAEF,MAAM,QAAQ,GAAG,IAAI;SAClB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,cAAc,CAAC;SAC7C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC;SAC3C,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAEnB,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACvC,MAAM,SAAS,GAAG,GAAG,EAAE,IAAI,IAAI,OAAO,CAAC;QACvC,MAAM,KAAK,GAAG,oBAAoB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACnD,IAAI,CAAC,KAAK;YAAE,SAAS;QAErB,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAEtE,IAAI,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACjC,IAAI,IAAI,GAAG,UAAU,GAAG,CAAC,OAAO,EAAE,CAAC;QAEnC,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;YAC3B,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC;gBACpD,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,QAAQ,EAAE;gBAC3B,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE;aACxB,CAAC,CAAC;YACH,KAAK,GAAG,UAAU,EAAE,KAAK,IAAI,KAAK,CAAC;YACnC,IAAI,GAAG,UAAU,GAAG,CAAC,OAAO,eAAe,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC5D,CAAC;aAAM,IAAI,KAAK,KAAK,WAAW,EAAE,CAAC;YACjC,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC;gBAClD,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,QAAQ,EAAE;gBAC3B,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;aACvB,CAAC,CAAC;YACH,KAAK,GAAG,SAAS,EAAE,IAAI,IAAI,KAAK,CAAC;YACjC,IAAI,GAAG,UAAU,GAAG,CAAC,OAAO,aAAa,CAAC;QAC5C,CAAC;aAAM,IAAI,KAAK,KAAK,cAAc,EAAE,CAAC;YACpC,IAAI,GAAG,UAAU,GAAG,CAAC,OAAO,EAAE,CAAC;QACjC,CAAC;aAAM,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;gBACxC,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,QAAQ,EAAE;gBAC3B,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;aACvB,CAAC,CAAC;YACH,KAAK,GAAG,IAAI,EAAE,IAAI,IAAI,KAAK,CAAC;YAC5B,IAAI,GAAG,UAAU,GAAG,CAAC,OAAO,QAAQ,CAAC;QACvC,CAAC;aAAM,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YAC/B,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;gBAC9C,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,QAAQ,EAAE;gBAC3B,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;aACvB,CAAC,CAAC;YACH,KAAK,GAAG,OAAO,EAAE,IAAI,IAAI,KAAK,CAAC;YAC/B,IAAI,GAAG,UAAU,GAAG,CAAC,OAAO,cAAc,CAAC;QAC7C,CAAC;aAAM,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;YAClC,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC;gBACpD,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,QAAQ,EAAE;gBAC3B,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE;aACxB,CAAC,CAAC;YACH,KAAK,GAAG,UAAU,EAAE,KAAK,IAAI,KAAK,CAAC;YACnC,IAAI,GAAG,UAAU,GAAG,CAAC,OAAO,gBAAgB,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC7D,CAAC;aAAM,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;YAClC,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC;gBACpD,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,QAAQ,EAAE;gBAC3B,MAAM,EAAE,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;aAC9D,CAAC,CAAC;YACH,KAAK,GAAG,UAAU,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,eAAe,UAAU,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;YAC5F,IAAI,GAAG,UAAU,EAAE,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,OAAO,eAAe,UAAU,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QAC3G,CAAC;aAAM,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;YAChC,KAAK,GAAG,GAAG,SAAS,WAAW,CAAC;YAChC,IAAI,GAAG,UAAU,GAAG,CAAC,OAAO,WAAW,CAAC;QAC1C,CAAC;QAED,OAAO,CAAC,IAAI,CAAC;YACX,EAAE,EAAE,YAAY,GAAG,CAAC,QAAQ,EAAE;YAC9B,IAAI,EAAE,KAAK;YACX,KAAK;YACL,QAAQ,EAAE,GAAG,SAAS,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;YAC5E,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,SAAS;YACT,IAAI;YACJ,WAAW,EAAE,OAAO;SACrB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC5B,CAAC","debug_id":"cb499420-fdcc-5847-9586-9b9927cf72a2"}
|