@studious-lms/server 1.26.0 → 1.27.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/.env.example +3 -1
  2. package/.github/workflows/npm-publish.yml +1 -0
  3. package/AGENTS.md +84 -0
  4. package/dist/models/cloudStorage.d.ts +11 -0
  5. package/dist/models/cloudStorage.d.ts.map +1 -1
  6. package/dist/models/cloudStorage.js +18 -2
  7. package/dist/models/cloudStorage.js.map +1 -1
  8. package/dist/models/conversation.d.ts +1 -0
  9. package/dist/models/conversation.d.ts.map +1 -1
  10. package/dist/models/labChat.d.ts +40 -0
  11. package/dist/models/labChat.d.ts.map +1 -1
  12. package/dist/models/labChat.js +32 -2
  13. package/dist/models/labChat.js.map +1 -1
  14. package/dist/models/message.d.ts +3 -0
  15. package/dist/models/message.d.ts.map +1 -1
  16. package/dist/pipelines/aiLabChat.d.ts +2 -0
  17. package/dist/pipelines/aiLabChat.d.ts.map +1 -1
  18. package/dist/pipelines/aiLabChat.js +60 -16
  19. package/dist/pipelines/aiLabChat.js.map +1 -1
  20. package/dist/pipelines/aiLabChatContract.d.ts +170 -2
  21. package/dist/pipelines/aiLabChatContract.d.ts.map +1 -1
  22. package/dist/pipelines/aiLabChatContract.js +30 -2
  23. package/dist/pipelines/aiLabChatContract.js.map +1 -1
  24. package/dist/pipelines/aiNewtonChat.d.ts.map +1 -1
  25. package/dist/pipelines/aiNewtonChat.js +30 -5
  26. package/dist/pipelines/aiNewtonChat.js.map +1 -1
  27. package/dist/pipelines/labChatPrompt.d.ts +1 -1
  28. package/dist/pipelines/labChatPrompt.d.ts.map +1 -1
  29. package/dist/pipelines/labChatPrompt.js +13 -14
  30. package/dist/pipelines/labChatPrompt.js.map +1 -1
  31. package/dist/routers/_app.d.ts +220 -10
  32. package/dist/routers/_app.d.ts.map +1 -1
  33. package/dist/routers/admin.d.ts +0 -1
  34. package/dist/routers/admin.d.ts.map +1 -1
  35. package/dist/routers/conversation.d.ts +1 -0
  36. package/dist/routers/conversation.d.ts.map +1 -1
  37. package/dist/routers/labChat.d.ts +10 -0
  38. package/dist/routers/labChat.d.ts.map +1 -1
  39. package/dist/routers/labChat.js +6 -3
  40. package/dist/routers/labChat.js.map +1 -1
  41. package/dist/routers/message.d.ts +37 -4
  42. package/dist/routers/message.d.ts.map +1 -1
  43. package/dist/routers/message.js +24 -7
  44. package/dist/routers/message.js.map +1 -1
  45. package/dist/routers/parent.d.ts +18 -0
  46. package/dist/routers/parent.d.ts.map +1 -1
  47. package/dist/routers/parent.js +10 -3
  48. package/dist/routers/parent.js.map +1 -1
  49. package/dist/routers/studentProgress.d.ts +44 -0
  50. package/dist/routers/studentProgress.d.ts.map +1 -1
  51. package/dist/routers/studentProgress.js +12 -3
  52. package/dist/routers/studentProgress.js.map +1 -1
  53. package/dist/routes/aiStream.js +32 -2
  54. package/dist/routes/aiStream.js.map +1 -1
  55. package/dist/seedDatabase.d.ts.map +1 -1
  56. package/dist/seedDatabase.js +107 -3
  57. package/dist/seedDatabase.js.map +1 -1
  58. package/dist/services/adminUser.d.ts +0 -1
  59. package/dist/services/adminUser.d.ts.map +1 -1
  60. package/dist/services/adminUser.js +7 -4
  61. package/dist/services/adminUser.js.map +1 -1
  62. package/dist/services/aiChatStream.d.ts +15 -0
  63. package/dist/services/aiChatStream.d.ts.map +1 -1
  64. package/dist/services/aiChatStream.js +144 -74
  65. package/dist/services/aiChatStream.js.map +1 -1
  66. package/dist/services/aiGeneration.d.ts +4 -0
  67. package/dist/services/aiGeneration.d.ts.map +1 -0
  68. package/dist/services/aiGeneration.js +88 -0
  69. package/dist/services/aiGeneration.js.map +1 -0
  70. package/dist/services/aiProposalTools.d.ts +4 -1
  71. package/dist/services/aiProposalTools.d.ts.map +1 -1
  72. package/dist/services/aiProposalTools.js +128 -3
  73. package/dist/services/aiProposalTools.js.map +1 -1
  74. package/dist/services/aiProposals.d.ts +70 -0
  75. package/dist/services/aiProposals.d.ts.map +1 -0
  76. package/dist/services/aiProposals.js +363 -0
  77. package/dist/services/aiProposals.js.map +1 -0
  78. package/dist/services/conversation.d.ts +1 -0
  79. package/dist/services/conversation.d.ts.map +1 -1
  80. package/dist/services/labChat.d.ts +10 -0
  81. package/dist/services/labChat.d.ts.map +1 -1
  82. package/dist/services/labChat.js +52 -3
  83. package/dist/services/labChat.js.map +1 -1
  84. package/dist/services/message.d.ts +24 -8
  85. package/dist/services/message.d.ts.map +1 -1
  86. package/dist/services/message.js +170 -117
  87. package/dist/services/message.js.map +1 -1
  88. package/dist/services/parentPortal.d.ts +14 -0
  89. package/dist/services/parentPortal.d.ts.map +1 -1
  90. package/dist/services/parentPortal.js +72 -2
  91. package/dist/services/parentPortal.js.map +1 -1
  92. package/dist/services/studentProgress.d.ts +50 -0
  93. package/dist/services/studentProgress.d.ts.map +1 -1
  94. package/dist/services/studentProgress.js +107 -2
  95. package/dist/services/studentProgress.js.map +1 -1
  96. package/dist/utils/inference.d.ts +10 -0
  97. package/dist/utils/inference.d.ts.map +1 -1
  98. package/dist/utils/inference.js +77 -2
  99. package/dist/utils/inference.js.map +1 -1
  100. package/dist/workers/processors/createRunJobWorker.js +17 -16
  101. package/dist/workers/processors/createRunJobWorker.js.map +1 -1
  102. package/package.json +1 -1
  103. package/prisma/migrations/20260811130000_add_ai_message_feedback/migration.sql +7 -0
  104. package/prisma/schema.prisma +8 -0
  105. package/src/models/cloudStorage.ts +19 -0
  106. package/src/models/labChat.ts +34 -0
  107. package/src/pipelines/aiLabChat.ts +79 -18
  108. package/src/pipelines/aiLabChatContract.ts +35 -0
  109. package/src/pipelines/aiNewtonChat.ts +34 -2
  110. package/src/pipelines/labChatPrompt.ts +11 -12
  111. package/src/routers/labChat.ts +5 -0
  112. package/src/routers/message.ts +34 -5
  113. package/src/routers/parent.ts +11 -0
  114. package/src/routers/studentProgress.ts +15 -0
  115. package/src/routes/aiStream.ts +32 -0
  116. package/src/seedDatabase.ts +107 -2
  117. package/src/services/adminUser.ts +5 -2
  118. package/src/services/aiChatStream.ts +83 -7
  119. package/src/services/aiGeneration.ts +92 -0
  120. package/src/services/aiProposalTools.ts +166 -1
  121. package/src/services/aiProposals.ts +428 -0
  122. package/src/services/labChat.ts +65 -0
  123. package/src/services/message.ts +205 -142
  124. package/src/services/parentPortal.ts +85 -0
  125. package/src/services/studentProgress.ts +135 -0
  126. package/src/utils/inference.ts +85 -0
  127. package/src/workers/processors/createRunJobWorker.ts +17 -17
  128. package/tests/unit/services/adminUser.test.ts +75 -0
  129. package/tests/unit/utils/adminPanelAccess.test.ts +26 -0
@@ -1 +1 @@
1
- {"version":3,"file":"studentProgress.js","sources":["services/studentProgress.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Student progress service - assignment recommendations and progress chat.\n */\nimport { TRPCError } from \"@trpc/server\";\nimport type { AssignmentType } from \"@prisma/client\";\nimport { z } from \"zod\";\nimport { prisma } from \"../lib/prisma.js\";\nimport { isTeacherInClass } from \"../models/class.js\";\nimport { inference } from \"../utils/inference.js\";\nimport { logger } from \"../utils/logger.js\";\nimport {\n getStudentProgressInferenceCacheHit,\n setStudentProgressInferenceCache,\n} from \"./studentProgressInferenceCache.js\";\n\ntype ProgressChatMessage = {\n role: \"user\" | \"assistant\";\n content: string;\n};\n\ntype GradeSubmission = {\n id: string;\n gradeReceived: number | null;\n submitted: boolean | null;\n returned: boolean | null;\n submittedAt: Date | null;\n recommendationState: \"NONE\" | \"OPEN\" | \"ASSIGNED\" | \"DISMISSED\";\n targetedAssignmentId: string | null;\n assignment: {\n id: string;\n title: string;\n dueDate: Date;\n maxGrade: number | null;\n weight: number;\n type: AssignmentType;\n section: { id: string; name: string } | null;\n };\n};\n\ntype ProgressStudent = {\n id: string;\n username: string;\n profile: { displayName: string | null } | null;\n};\n\nconst insightItemSchema = z.object({\n label: z.string(),\n evidence: z.string(),\n});\n\nconst studentProgressInsightsSchema = z.object({\n summary: z.string(),\n strengths: z.array(insightItemSchema).min(2).max(4),\n growth: z.array(insightItemSchema).min(2).max(4),\n talkingPoints: z.array(z.string()).min(3).max(5),\n});\n\nconst studentProgressForecastSchema = z.object({\n forecastLow: z.number().min(0).max(100),\n forecastHigh: z.number().min(0).max(100),\n risk: z.enum([\"on_track\", \"watch\", \"at_risk\"]),\n reason: z.string(),\n});\n\nconst studentProgressFocusSchema = z.object({\n focusItems: z.array(z.string()).min(3).max(5),\n});\n\nexport type StudentProgressInsights = z.infer<\n typeof studentProgressInsightsSchema\n>;\nexport type StudentProgressForecast = z.infer<\n typeof studentProgressForecastSchema\n>;\nexport type StudentProgressFocus = z.infer<typeof studentProgressFocusSchema>;\n\ntype RecommendationType = \"missing\" | \"low_score\" | \"awaiting_feedback\";\n\nfunction calculatePercentage(submission: GradeSubmission) {\n if (submission.gradeReceived == null || !submission.assignment.maxGrade) {\n return null;\n }\n\n return (\n Math.round(\n (submission.gradeReceived / submission.assignment.maxGrade) * 1000,\n ) / 10\n );\n}\n\nfunction calculateTrend(submissions: GradeSubmission[]) {\n const graded = submissions\n .filter(\n (submission) =>\n submission.gradeReceived != null && submission.assignment.maxGrade,\n )\n .sort((a, b) => {\n const aTime = a.submittedAt?.getTime() ?? a.assignment.dueDate.getTime();\n const bTime = b.submittedAt?.getTime() ?? b.assignment.dueDate.getTime();\n return aTime - bTime;\n })\n .map((submission) => calculatePercentage(submission))\n .filter((value): value is number => value != null);\n\n if (graded.length < 2) return 0;\n\n const midpoint = Math.floor(graded.length / 2);\n const first = graded.slice(0, midpoint);\n const second = graded.slice(midpoint);\n const average = (values: number[]) =>\n values.reduce((sum, value) => sum + value, 0) / values.length;\n\n return Math.round((average(second) - average(first)) * 10) / 10;\n}\n\nfunction getOverallGrade(submissions: GradeSubmission[]) {\n let totalWeighted = 0;\n let totalWeight = 0;\n\n for (const submission of submissions) {\n if (\n submission.gradeReceived != null &&\n submission.assignment.maxGrade &&\n submission.assignment.weight\n ) {\n totalWeighted +=\n (submission.gradeReceived / submission.assignment.maxGrade) *\n submission.assignment.weight;\n totalWeight += submission.assignment.weight;\n }\n }\n\n return totalWeight > 0\n ? Math.round((totalWeighted / totalWeight) * 1000) / 10\n : null;\n}\n\nfunction normalizeAssignmentType(\n assignmentType: AssignmentType,\n): AssignmentType {\n if (assignmentType === \"TEST\" || assignmentType === \"QUIZ\") {\n return \"HOMEWORK\";\n }\n\n return assignmentType;\n}\n\nfunction buildSuggestedAssignment(\n recommendationType: RecommendationType,\n submission: GradeSubmission,\n displayName: string,\n percentage: number | null,\n) {\n const sourceTitle = submission.assignment.title;\n const section = submission.assignment.section?.name;\n const titleByType: Record<RecommendationType, string> = {\n missing: `Make-up: ${sourceTitle}`,\n low_score: `Targeted practice: ${sourceTitle}`,\n awaiting_feedback: `Revision follow-up: ${sourceTitle}`,\n };\n const leadByType: Record<RecommendationType, string> = {\n missing: `${displayName} missed the original assignment and needs a focused make-up task on the same material.`,\n low_score:\n percentage != null\n ? `${displayName} scored ${percentage}% and needs targeted reinforcement on the underlying concepts.`\n : `${displayName} needs targeted reinforcement on the underlying concepts.`,\n awaiting_feedback: `${displayName} has work in progress here, so a short follow-up can keep momentum once feedback lands.`,\n };\n\n return {\n title: titleByType[recommendationType],\n instructions: [\n leadByType[recommendationType],\n `Source assignment: ${sourceTitle}.`,\n section ? `Section: ${section}.` : null,\n \"Keep the work concise and focused on the specific area of concern.\",\n ]\n .filter((line): line is string => Boolean(line))\n .join(\"\\n\\n\"),\n type: normalizeAssignmentType(submission.assignment.type),\n maxGrade: submission.assignment.maxGrade ?? 100,\n weight: submission.assignment.weight || 1,\n graded: true,\n sectionId: submission.assignment.section?.id ?? null,\n sourceAssignmentId: submission.assignment.id,\n };\n}\n\nfunction buildRecommendationCandidate(\n submission: GradeSubmission,\n displayName: string,\n now: Date,\n) {\n if (\n submission.recommendationState === \"ASSIGNED\" ||\n submission.recommendationState === \"DISMISSED\"\n ) {\n return null;\n }\n\n const percentage = calculatePercentage(submission);\n const isMissing =\n !submission.submitted &&\n submission.assignment.dueDate.getTime() < now.getTime();\n const isLowScore = percentage != null && percentage < 70;\n const isUnreturned =\n Boolean(submission.submitted) &&\n submission.gradeReceived == null &&\n !submission.returned;\n const reasons: string[] = [];\n let priorityScore = 0;\n let recommendationType: RecommendationType | null = null;\n\n if (isMissing) {\n reasons.push(\"Missing past-due work\");\n priorityScore += 100;\n recommendationType = \"missing\";\n }\n if (isLowScore) {\n reasons.push(`Scored ${percentage}%`);\n priorityScore += 85 - (percentage ?? 0);\n recommendationType ??= \"low_score\";\n }\n if (isUnreturned) {\n reasons.push(\"Awaiting grade or feedback\");\n priorityScore += 15;\n recommendationType ??= \"awaiting_feedback\";\n }\n\n if (priorityScore <= 0 || !recommendationType) {\n return null;\n }\n\n return {\n assignmentId: submission.assignment.id,\n submissionId: submission.id,\n title: submission.assignment.title,\n type: submission.assignment.type,\n sectionId: submission.assignment.section?.id ?? null,\n sectionName: submission.assignment.section?.name ?? null,\n dueDate: submission.assignment.dueDate,\n gradeReceived: submission.gradeReceived,\n maxGrade: submission.assignment.maxGrade,\n percentage,\n submitted: Boolean(submission.submitted),\n returned: Boolean(submission.returned),\n recommendationType,\n reasons,\n priorityScore,\n suggestedAssignment: buildSuggestedAssignment(\n recommendationType,\n submission,\n displayName,\n percentage,\n ),\n };\n}\n\nfunction summarizeStudentRecommendations(\n student: ProgressStudent,\n submissions: GradeSubmission[],\n) {\n const now = new Date();\n const displayName = student.profile?.displayName ?? student.username;\n const recommendationCandidates = submissions\n .map((submission) =>\n buildRecommendationCandidate(submission, displayName, now),\n )\n .filter(\n (\n candidate,\n ): candidate is NonNullable<\n ReturnType<typeof buildRecommendationCandidate>\n > => candidate != null,\n )\n .sort((a, b) => b.priorityScore - a.priorityScore);\n\n const recommendations = recommendationCandidates\n .slice(0, 5)\n .map(({ priorityScore, ...candidate }) => candidate);\n\n const gradedPercentages = submissions\n .map(calculatePercentage)\n .filter((value): value is number => value != null);\n const lowScoreCount = gradedPercentages.filter(\n (percentage) => percentage < 70,\n ).length;\n const missingCount = submissions.filter(\n (submission) =>\n !submission.submitted &&\n submission.assignment.dueDate.getTime() < now.getTime(),\n ).length;\n const trend = calculateTrend(submissions);\n const overallGrade = getOverallGrade(submissions);\n\n const nextSteps = [\n missingCount > 0\n ? `Prioritize ${missingCount} missing assignment${missingCount === 1 ? \"\" : \"s\"}.`\n : null,\n lowScoreCount > 0\n ? `Review ${lowScoreCount} low-scoring assignment${lowScoreCount === 1 ? \"\" : \"s\"} before introducing new material.`\n : null,\n trend < -5\n ? \"Schedule a check-in because recent performance is trending down.\"\n : null,\n recommendationCandidates.length === 0\n ? \"No urgent assignment issues detected from the available grades.\"\n : null,\n ].filter((step): step is string => Boolean(step));\n\n return {\n student: {\n id: student.id,\n username: student.username,\n displayName,\n },\n summary: {\n overallGrade,\n trend,\n completedAssignments: submissions.filter((submission) =>\n Boolean(submission.submitted),\n ).length,\n totalAssignments: submissions.length,\n missingCount,\n lowScoreCount,\n },\n recommendations,\n recommendationCandidates,\n nextSteps,\n priorityScore: recommendationCandidates[0]?.priorityScore ?? 0,\n };\n}\n\nasync function syncRecommendationStates(\n submissions: GradeSubmission[],\n recommendationCandidates: Array<\n NonNullable<ReturnType<typeof buildRecommendationCandidate>>\n >,\n) {\n const candidateSubmissionIds = new Set(\n recommendationCandidates.map((candidate) => candidate.submissionId),\n );\n const updates: Promise<unknown>[] = [];\n\n for (const submission of submissions) {\n const shouldBeOpen = candidateSubmissionIds.has(submission.id);\n\n if (shouldBeOpen && submission.recommendationState === \"NONE\") {\n updates.push(\n prisma.submission.update({\n where: { id: submission.id },\n data: {\n recommendationState: \"OPEN\",\n recommendationUpdatedAt: new Date(),\n },\n }),\n );\n continue;\n }\n\n if (!shouldBeOpen && submission.recommendationState === \"OPEN\") {\n updates.push(\n prisma.submission.update({\n where: { id: submission.id },\n data: {\n recommendationState: \"NONE\",\n recommendationUpdatedAt: new Date(),\n },\n }),\n );\n }\n }\n\n if (updates.length) {\n await Promise.all(updates);\n }\n}\n\nasync function summarizeStudentRecommendationsWithCases(\n student: ProgressStudent,\n submissions: GradeSubmission[],\n) {\n const summary = summarizeStudentRecommendations(student, submissions);\n await syncRecommendationStates(submissions, summary.recommendationCandidates);\n return summary;\n}\n\nasync function loadStudentProgressContext(\n viewerId: string,\n classId: string,\n studentId: string,\n) {\n const isTeacher = await isTeacherInClass(classId, viewerId);\n if (viewerId !== studentId && !isTeacher) {\n throw new TRPCError({\n code: \"UNAUTHORIZED\",\n message: \"You can only view your own progress\",\n });\n }\n\n const [classData, student, submissions] = await Promise.all([\n prisma.class.findUnique({\n where: { id: classId },\n select: { id: true, name: true, subject: true },\n }),\n prisma.user.findFirst({\n where: {\n id: studentId,\n studentIn: { some: { id: classId } },\n },\n select: {\n id: true,\n username: true,\n profile: { select: { displayName: true } },\n },\n }),\n prisma.submission.findMany({\n where: {\n studentId,\n assignment: { classId, graded: true },\n },\n include: {\n assignment: {\n select: {\n id: true,\n title: true,\n dueDate: true,\n maxGrade: true,\n weight: true,\n type: true,\n section: { select: { id: true, name: true } },\n },\n },\n },\n orderBy: { assignment: { dueDate: \"asc\" } },\n }),\n ]);\n\n if (!classData) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Class not found\" });\n }\n\n if (!student) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Student not found in this class\",\n });\n }\n\n return { classData, student, submissions };\n}\n\nexport async function getStudentProgressRecommendations(\n viewerId: string,\n classId: string,\n studentId: string,\n) {\n const { student, submissions } = await loadStudentProgressContext(\n viewerId,\n classId,\n studentId,\n );\n\n const summary = await summarizeStudentRecommendationsWithCases(\n student,\n submissions,\n );\n const {\n recommendationCandidates: _recommendationCandidates,\n ...summaryResponse\n } = summary;\n return {\n student: summaryResponse.student,\n summary: summaryResponse.summary,\n recommendations: summaryResponse.recommendations,\n nextSteps: summaryResponse.nextSteps,\n };\n}\n\nexport async function getClassProgressRecommendations(\n viewerId: string,\n classId: string,\n) {\n const teacherInClass = await isTeacherInClass(classId, viewerId);\n if (!teacherInClass) {\n throw new TRPCError({\n code: \"UNAUTHORIZED\",\n message: \"Only teachers can view class-wide recommendations\",\n });\n }\n\n const classData = await prisma.class.findUnique({\n where: { id: classId },\n select: {\n id: true,\n name: true,\n subject: true,\n students: {\n select: {\n id: true,\n username: true,\n profile: { select: { displayName: true } },\n submissions: {\n where: {\n assignment: { classId, graded: true },\n },\n include: {\n assignment: {\n select: {\n id: true,\n title: true,\n dueDate: true,\n maxGrade: true,\n weight: true,\n type: true,\n section: { select: { id: true, name: true } },\n },\n },\n },\n orderBy: { assignment: { dueDate: \"asc\" } },\n },\n },\n },\n },\n });\n\n if (!classData) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Class not found\" });\n }\n\n const students = (\n await Promise.all(\n classData.students.map((student) =>\n summarizeStudentRecommendationsWithCases(student, student.submissions),\n ),\n )\n )\n .map(\n ({ recommendationCandidates: _recommendationCandidates, ...student }) =>\n student,\n )\n .filter((student) => student.recommendations.length > 0)\n .sort((a, b) => b.priorityScore - a.priorityScore);\n\n const totalRecommendations = students.reduce(\n (sum, student) => sum + student.recommendations.length,\n 0,\n );\n const studentsWithConcerns = students.length;\n const totalMissingAssignments = students.reduce(\n (sum, student) => sum + student.summary.missingCount,\n 0,\n );\n const totalLowScoreAssignments = students.reduce(\n (sum, student) => sum + student.summary.lowScoreCount,\n 0,\n );\n\n return {\n class: {\n id: classData.id,\n name: classData.name,\n subject: classData.subject,\n },\n summary: {\n studentsWithConcerns,\n totalRecommendations,\n totalMissingAssignments,\n totalLowScoreAssignments,\n },\n students: students.map(({ priorityScore, ...student }) => student),\n };\n}\n\nexport async function dismissStudentRecommendation(\n viewerId: string,\n input: {\n classId: string;\n studentId: string;\n submissionId: string;\n },\n) {\n const teacherInClass = await isTeacherInClass(input.classId, viewerId);\n if (!teacherInClass) {\n throw new TRPCError({\n code: \"UNAUTHORIZED\",\n message: \"Only teachers can dismiss recommendations\",\n });\n }\n\n const submission = await prisma.submission.findFirst({\n where: {\n id: input.submissionId,\n studentId: input.studentId,\n assignment: {\n classId: input.classId,\n },\n },\n select: { id: true },\n });\n\n if (!submission) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Submission not found for this student in this class\",\n });\n }\n\n await prisma.submission.update({\n where: { id: input.submissionId },\n data: {\n recommendationState: \"DISMISSED\",\n recommendationUpdatedAt: new Date(),\n },\n });\n\n return { success: true };\n}\n\nfunction buildProgressSummary(submissions: GradeSubmission[]) {\n return submissions.map((submission) => ({\n title: submission.assignment.title,\n type: submission.assignment.type,\n dueDate: submission.assignment.dueDate.toISOString(),\n submitted: Boolean(submission.submitted),\n returned: Boolean(submission.returned),\n gradeReceived: submission.gradeReceived,\n maxGrade: submission.assignment.maxGrade,\n percentage: calculatePercentage(submission),\n section: submission.assignment.section?.name ?? null,\n }));\n}\n\nfunction buildStructuredProgressContext(\n classData: { id: string; name: string; subject: string | null },\n student: ProgressStudent,\n submissions: GradeSubmission[],\n) {\n const displayName = student.profile?.displayName ?? student.username;\n const recommendationSummary = summarizeStudentRecommendations(\n student,\n submissions,\n );\n\n return {\n class: classData,\n student: { id: student.id, username: student.username, displayName },\n progress: {\n overallGrade: getOverallGrade(submissions),\n trend: calculateTrend(submissions),\n summary: recommendationSummary.summary,\n assignments: buildProgressSummary(submissions),\n recommendations: recommendationSummary.recommendations.map(\n (recommendation) => ({\n title: recommendation.title,\n recommendationType: recommendation.recommendationType,\n percentage: recommendation.percentage,\n submitted: recommendation.submitted,\n reasons: recommendation.reasons,\n sectionName: recommendation.sectionName,\n }),\n ),\n },\n };\n}\n\nfunction buildStructuredInferenceMessages(\n instruction: string,\n context: ReturnType<typeof buildStructuredProgressContext>,\n) {\n return [\n {\n role: \"system\" as const,\n content:\n \"You are an educational progress analyst. Use only the provided class and grade context. Be specific, concise, supportive, and do not fabricate assignments, grades, or sections.\",\n },\n {\n role: \"user\" as const,\n content: JSON.stringify(context),\n },\n {\n role: \"user\" as const,\n content: instruction,\n },\n ];\n}\n\ntype ProgressInferenceCacheRow<T> = {\n epoch: number;\n cachedAt: number;\n value: T;\n};\n\nconst studentProgressInsightsCache = new Map<\n string,\n ProgressInferenceCacheRow<StudentProgressInsights>\n>();\nconst studentProgressForecastCache = new Map<\n string,\n ProgressInferenceCacheRow<StudentProgressForecast>\n>();\nconst studentProgressFocusCache = new Map<\n string,\n ProgressInferenceCacheRow<StudentProgressFocus>\n>();\n\nexport async function getStudentProgressInsights(\n viewerId: string,\n classId: string,\n studentId: string,\n) {\n const cached = getStudentProgressInferenceCacheHit(\n studentProgressInsightsCache,\n classId,\n studentId,\n );\n\n const { classData, student, submissions } = await loadStudentProgressContext(\n viewerId,\n classId,\n studentId,\n );\n\n if (cached !== undefined) {\n return cached;\n }\n\n const context = buildStructuredProgressContext(\n classData,\n student,\n submissions,\n );\n\n const value = await inference<StudentProgressInsights>(\n buildStructuredInferenceMessages(\n [\n \"Generate an AI analytics summary for this one student's dashboard.\",\n \"The summary must be 2-4 plain-prose sentences: lead with overall grade and trajectory, then call out one strength and one concern with assignment titles.\",\n \"Strengths and growth items need 2-6 word labels and one-line evidence grounded in assignment titles or sections.\",\n \"Talking points must be 3-5 specific teacher check-in prompts with no numbering.\",\n ].join(\" \"),\n context,\n ),\n studentProgressInsightsSchema,\n {\n reason: \"student_progress_insights\",\n metadata: { viewerId, classId, studentId },\n attribution: { userId: viewerId, classId },\n },\n );\n setStudentProgressInferenceCache(\n studentProgressInsightsCache,\n classId,\n studentId,\n value,\n );\n return value;\n}\n\nexport async function getStudentProgressForecast(\n viewerId: string,\n classId: string,\n studentId: string,\n) {\n const cached = getStudentProgressInferenceCacheHit(\n studentProgressForecastCache,\n classId,\n studentId,\n );\n\n const { classData, student, submissions } = await loadStudentProgressContext(\n viewerId,\n classId,\n studentId,\n );\n\n if (cached !== undefined) {\n return cached;\n }\n\n const context = buildStructuredProgressContext(\n classData,\n student,\n submissions,\n );\n\n const value = await inference<StudentProgressForecast>(\n buildStructuredInferenceMessages(\n \"Predict the student's next graded assignment percentage band and risk status. Base the forecast on trajectory, missing work, low scores, and assignment recency. Keep the reason to one sentence.\",\n context,\n ),\n studentProgressForecastSchema,\n {\n reason: \"student_progress_forecast\",\n metadata: { viewerId, classId, studentId },\n attribution: { userId: viewerId, classId },\n },\n );\n setStudentProgressInferenceCache(\n studentProgressForecastCache,\n classId,\n studentId,\n value,\n );\n return value;\n}\n\nexport async function getStudentProgressFocus(\n viewerId: string,\n classId: string,\n studentId: string,\n) {\n const cached = getStudentProgressInferenceCacheHit(\n studentProgressFocusCache,\n classId,\n studentId,\n );\n\n const { classData, student, submissions } = await loadStudentProgressContext(\n viewerId,\n classId,\n studentId,\n );\n\n if (cached !== undefined) {\n return cached;\n }\n \n const context = buildStructuredProgressContext(\n classData,\n student,\n submissions,\n );\n\n const value = await inference<StudentProgressFocus>(\n buildStructuredInferenceMessages(\n \"Generate 3-5 student-facing weekly focus items. Each item should be specific, actionable, and grounded in the student's grade pattern or assignment titles. No numbering in the strings.\",\n context,\n ),\n studentProgressFocusSchema,\n {\n reason: \"student_progress_focus\",\n metadata: { viewerId, classId, studentId },\n attribution: { userId: viewerId, classId },\n },\n );\n setStudentProgressInferenceCache(\n studentProgressFocusCache,\n classId,\n studentId,\n value,\n );\n return value;\n}\n\nexport async function chatAboutStudentProgress(\n viewerId: string,\n input: {\n classId: string;\n studentId: string;\n message: string;\n history?: ProgressChatMessage[];\n },\n) {\n const { classData, student, submissions } = await loadStudentProgressContext(\n viewerId,\n input.classId,\n input.studentId,\n );\n\n const displayName = student.profile?.displayName ?? student.username;\n const summary = {\n overallGrade: getOverallGrade(submissions),\n trend: calculateTrend(submissions),\n assignments: buildProgressSummary(submissions),\n };\n\n const messages = [\n {\n role: \"system\" as const,\n content:\n \"You are an educational progress assistant for teachers and students. Use only the provided class and grade context. Be concise, specific, supportive, and avoid fabricating grades or assignments.\",\n },\n {\n role: \"user\" as const,\n content: JSON.stringify({\n class: classData,\n student: { id: student.id, username: student.username, displayName },\n progress: summary,\n }),\n },\n ...(input.history ?? []).slice(-8).map((message) => ({\n role: message.role,\n content: message.content,\n })),\n { role: \"user\" as const, content: input.message },\n ];\n\n try {\n const response = await inference<string>(messages, undefined, {\n reason: \"student_progress_chat\",\n metadata: {\n viewerId,\n classId: input.classId,\n studentId: input.studentId,\n },\n attribution: { userId: viewerId, classId: input.classId },\n });\n if (typeof response !== \"string\" || response.trim().length === 0) {\n throw new Error(\"Student progress chat returned an empty response\");\n }\n return { message: response, isFallback: false };\n } catch (error) {\n logger.error(\"Failed to generate student progress chat response\", {\n error,\n classId: input.classId,\n studentId: input.studentId,\n });\n\n const overall =\n summary.overallGrade == null\n ? \"not enough graded work\"\n : `${summary.overallGrade}%`;\n const missingItems = summary.assignments.filter(\n (assignment) =>\n !assignment.submitted &&\n new Date(assignment.dueDate).getTime() < Date.now(),\n ).length;\n const lowScores = summary.assignments.filter(\n (assignment) =>\n assignment.percentage != null && assignment.percentage < 70,\n ).length;\n const awaitingFeedback = summary.assignments.filter(\n (assignment) =>\n assignment.submitted &&\n assignment.gradeReceived == null &&\n !assignment.returned,\n ).length;\n\n const fallbackParts = [\n `${displayName}'s current overall grade is ${overall}.`,\n missingItems > 0\n ? `${missingItems} assignment${missingItems === 1 ? \"\" : \"s\"} ${missingItems === 1 ? \"appears\" : \"appear\"} overdue.`\n : null,\n lowScores > 0\n ? `${lowScores} graded assignment${lowScores === 1 ? \" is\" : \"s are\"} below 70%.`\n : null,\n awaitingFeedback > 0\n ? `${awaitingFeedback} assignment${awaitingFeedback === 1 ? \" is\" : \"s are\"} still awaiting feedback.`\n : null,\n summary.trend < -5\n ? \"Recent performance is trending down, so a check-in would be reasonable.\"\n : \"Performance looks relatively steady from the available data.\",\n ].filter((part): part is string => Boolean(part));\n\n return {\n message: fallbackParts.join(\" \"),\n isFallback: true,\n };\n }\n}\n"],"names":[],"mappings":"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","debug_id":"6599ea6f-6b1e-5e33-98c2-31a09ed91bc9"}
1
+ {"version":3,"file":"studentProgress.js","sources":["services/studentProgress.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Student progress service - assignment recommendations and progress chat.\n */\nimport { TRPCError } from \"@trpc/server\";\nimport type { AssignmentType } from \"@prisma/client\";\nimport { z } from \"zod\";\nimport { prisma } from \"../lib/prisma.js\";\nimport { isTeacherInClass } from \"../models/class.js\";\nimport { createAssignmentRecord } from \"./assignment.js\";\nimport { inference } from \"../utils/inference.js\";\nimport { logger } from \"../utils/logger.js\";\nimport {\n getStudentProgressInferenceCacheHit,\n setStudentProgressInferenceCache,\n} from \"./studentProgressInferenceCache.js\";\n\ntype ProgressChatMessage = {\n role: \"user\" | \"assistant\";\n content: string;\n};\n\ntype GradeSubmission = {\n id: string;\n gradeReceived: number | null;\n submitted: boolean | null;\n returned: boolean | null;\n submittedAt: Date | null;\n recommendationState: \"NONE\" | \"OPEN\" | \"ASSIGNED\" | \"DISMISSED\";\n targetedAssignmentId: string | null;\n assignment: {\n id: string;\n title: string;\n dueDate: Date;\n maxGrade: number | null;\n weight: number;\n type: AssignmentType;\n section: { id: string; name: string } | null;\n };\n};\n\ntype ProgressStudent = {\n id: string;\n username: string;\n profile: { displayName: string | null } | null;\n};\n\nconst insightItemSchema = z.object({\n label: z.string(),\n evidence: z.string(),\n});\n\nconst studentProgressInsightsSchema = z.object({\n summary: z.string(),\n strengths: z.array(insightItemSchema).min(2).max(4),\n growth: z.array(insightItemSchema).min(2).max(4),\n talkingPoints: z.array(z.string()).min(3).max(5),\n});\n\nconst studentProgressForecastSchema = z.object({\n forecastLow: z.number().min(0).max(100),\n forecastHigh: z.number().min(0).max(100),\n risk: z.enum([\"on_track\", \"watch\", \"at_risk\"]),\n reason: z.string(),\n});\n\nconst studentProgressFocusSchema = z.object({\n focusItems: z.array(z.string()).min(3).max(5),\n});\n\nexport type StudentProgressInsights = z.infer<\n typeof studentProgressInsightsSchema\n>;\nexport type StudentProgressForecast = z.infer<\n typeof studentProgressForecastSchema\n>;\nexport type StudentProgressFocus = z.infer<typeof studentProgressFocusSchema>;\n\ntype RecommendationType = \"missing\" | \"low_score\" | \"awaiting_feedback\";\n\nfunction calculatePercentage(submission: GradeSubmission) {\n if (submission.gradeReceived == null || !submission.assignment.maxGrade) {\n return null;\n }\n\n return (\n Math.round(\n (submission.gradeReceived / submission.assignment.maxGrade) * 1000,\n ) / 10\n );\n}\n\nfunction calculateTrend(submissions: GradeSubmission[]) {\n const graded = submissions\n .filter(\n (submission) =>\n submission.gradeReceived != null && submission.assignment.maxGrade,\n )\n .sort((a, b) => {\n const aTime = a.submittedAt?.getTime() ?? a.assignment.dueDate.getTime();\n const bTime = b.submittedAt?.getTime() ?? b.assignment.dueDate.getTime();\n return aTime - bTime;\n })\n .map((submission) => calculatePercentage(submission))\n .filter((value): value is number => value != null);\n\n if (graded.length < 2) return 0;\n\n const midpoint = Math.floor(graded.length / 2);\n const first = graded.slice(0, midpoint);\n const second = graded.slice(midpoint);\n const average = (values: number[]) =>\n values.reduce((sum, value) => sum + value, 0) / values.length;\n\n return Math.round((average(second) - average(first)) * 10) / 10;\n}\n\nfunction getOverallGrade(submissions: GradeSubmission[]) {\n let totalWeighted = 0;\n let totalWeight = 0;\n\n for (const submission of submissions) {\n if (\n submission.gradeReceived != null &&\n submission.assignment.maxGrade &&\n submission.assignment.weight\n ) {\n totalWeighted +=\n (submission.gradeReceived / submission.assignment.maxGrade) *\n submission.assignment.weight;\n totalWeight += submission.assignment.weight;\n }\n }\n\n return totalWeight > 0\n ? Math.round((totalWeighted / totalWeight) * 1000) / 10\n : null;\n}\n\nfunction normalizeAssignmentType(\n assignmentType: AssignmentType,\n): AssignmentType {\n if (assignmentType === \"TEST\" || assignmentType === \"QUIZ\") {\n return \"HOMEWORK\";\n }\n\n return assignmentType;\n}\n\nfunction buildSuggestedAssignment(\n recommendationType: RecommendationType,\n submission: GradeSubmission,\n displayName: string,\n percentage: number | null,\n) {\n const sourceTitle = submission.assignment.title;\n const section = submission.assignment.section?.name;\n const titleByType: Record<RecommendationType, string> = {\n missing: `Make-up: ${sourceTitle}`,\n low_score: `Targeted practice: ${sourceTitle}`,\n awaiting_feedback: `Revision follow-up: ${sourceTitle}`,\n };\n const leadByType: Record<RecommendationType, string> = {\n missing: `${displayName} missed the original assignment and needs a focused make-up task on the same material.`,\n low_score:\n percentage != null\n ? `${displayName} scored ${percentage}% and needs targeted reinforcement on the underlying concepts.`\n : `${displayName} needs targeted reinforcement on the underlying concepts.`,\n awaiting_feedback: `${displayName} has work in progress here, so a short follow-up can keep momentum once feedback lands.`,\n };\n\n return {\n title: titleByType[recommendationType],\n instructions: [\n leadByType[recommendationType],\n `Source assignment: ${sourceTitle}.`,\n section ? `Section: ${section}.` : null,\n \"Keep the work concise and focused on the specific area of concern.\",\n ]\n .filter((line): line is string => Boolean(line))\n .join(\"\\n\\n\"),\n type: normalizeAssignmentType(submission.assignment.type),\n maxGrade: submission.assignment.maxGrade ?? 100,\n weight: submission.assignment.weight || 1,\n graded: true,\n sectionId: submission.assignment.section?.id ?? null,\n sourceAssignmentId: submission.assignment.id,\n };\n}\n\nfunction buildRecommendationCandidate(\n submission: GradeSubmission,\n displayName: string,\n now: Date,\n) {\n if (\n submission.recommendationState === \"ASSIGNED\" ||\n submission.recommendationState === \"DISMISSED\"\n ) {\n return null;\n }\n\n const percentage = calculatePercentage(submission);\n const isMissing =\n !submission.submitted &&\n submission.assignment.dueDate.getTime() < now.getTime();\n const isLowScore = percentage != null && percentage < 70;\n const isUnreturned =\n Boolean(submission.submitted) &&\n submission.gradeReceived == null &&\n !submission.returned;\n const reasons: string[] = [];\n let priorityScore = 0;\n let recommendationType: RecommendationType | null = null;\n\n if (isMissing) {\n reasons.push(\"Missing past-due work\");\n priorityScore += 100;\n recommendationType = \"missing\";\n }\n if (isLowScore) {\n reasons.push(`Scored ${percentage}%`);\n priorityScore += 85 - (percentage ?? 0);\n recommendationType ??= \"low_score\";\n }\n if (isUnreturned) {\n reasons.push(\"Awaiting grade or feedback\");\n priorityScore += 15;\n recommendationType ??= \"awaiting_feedback\";\n }\n\n if (priorityScore <= 0 || !recommendationType) {\n return null;\n }\n\n return {\n assignmentId: submission.assignment.id,\n submissionId: submission.id,\n title: submission.assignment.title,\n type: submission.assignment.type,\n sectionId: submission.assignment.section?.id ?? null,\n sectionName: submission.assignment.section?.name ?? null,\n dueDate: submission.assignment.dueDate,\n gradeReceived: submission.gradeReceived,\n maxGrade: submission.assignment.maxGrade,\n percentage,\n submitted: Boolean(submission.submitted),\n returned: Boolean(submission.returned),\n recommendationType,\n reasons,\n priorityScore,\n suggestedAssignment: buildSuggestedAssignment(\n recommendationType,\n submission,\n displayName,\n percentage,\n ),\n };\n}\n\nfunction summarizeStudentRecommendations(\n student: ProgressStudent,\n submissions: GradeSubmission[],\n) {\n const now = new Date();\n const displayName = student.profile?.displayName ?? student.username;\n const recommendationCandidates = submissions\n .map((submission) =>\n buildRecommendationCandidate(submission, displayName, now),\n )\n .filter(\n (\n candidate,\n ): candidate is NonNullable<\n ReturnType<typeof buildRecommendationCandidate>\n > => candidate != null,\n )\n .sort((a, b) => b.priorityScore - a.priorityScore);\n\n const recommendations = recommendationCandidates\n .slice(0, 5)\n .map(({ priorityScore, ...candidate }) => candidate);\n\n const gradedPercentages = submissions\n .map(calculatePercentage)\n .filter((value): value is number => value != null);\n const lowScoreCount = gradedPercentages.filter(\n (percentage) => percentage < 70,\n ).length;\n const missingCount = submissions.filter(\n (submission) =>\n !submission.submitted &&\n submission.assignment.dueDate.getTime() < now.getTime(),\n ).length;\n const trend = calculateTrend(submissions);\n const overallGrade = getOverallGrade(submissions);\n\n const nextSteps = [\n missingCount > 0\n ? `Prioritize ${missingCount} missing assignment${missingCount === 1 ? \"\" : \"s\"}.`\n : null,\n lowScoreCount > 0\n ? `Review ${lowScoreCount} low-scoring assignment${lowScoreCount === 1 ? \"\" : \"s\"} before introducing new material.`\n : null,\n trend < -5\n ? \"Schedule a check-in because recent performance is trending down.\"\n : null,\n recommendationCandidates.length === 0\n ? \"No urgent assignment issues detected from the available grades.\"\n : null,\n ].filter((step): step is string => Boolean(step));\n\n return {\n student: {\n id: student.id,\n username: student.username,\n displayName,\n },\n summary: {\n overallGrade,\n trend,\n completedAssignments: submissions.filter((submission) =>\n Boolean(submission.submitted),\n ).length,\n totalAssignments: submissions.length,\n missingCount,\n lowScoreCount,\n },\n recommendations,\n recommendationCandidates,\n nextSteps,\n priorityScore: recommendationCandidates[0]?.priorityScore ?? 0,\n };\n}\n\nasync function syncRecommendationStates(\n submissions: GradeSubmission[],\n recommendationCandidates: Array<\n NonNullable<ReturnType<typeof buildRecommendationCandidate>>\n >,\n) {\n const candidateSubmissionIds = new Set(\n recommendationCandidates.map((candidate) => candidate.submissionId),\n );\n const updates: Promise<unknown>[] = [];\n\n for (const submission of submissions) {\n const shouldBeOpen = candidateSubmissionIds.has(submission.id);\n\n if (shouldBeOpen && submission.recommendationState === \"NONE\") {\n updates.push(\n prisma.submission.update({\n where: { id: submission.id },\n data: {\n recommendationState: \"OPEN\",\n recommendationUpdatedAt: new Date(),\n },\n }),\n );\n continue;\n }\n\n if (!shouldBeOpen && submission.recommendationState === \"OPEN\") {\n updates.push(\n prisma.submission.update({\n where: { id: submission.id },\n data: {\n recommendationState: \"NONE\",\n recommendationUpdatedAt: new Date(),\n },\n }),\n );\n }\n }\n\n if (updates.length) {\n await Promise.all(updates);\n }\n}\n\nasync function summarizeStudentRecommendationsWithCases(\n student: ProgressStudent,\n submissions: GradeSubmission[],\n) {\n const summary = summarizeStudentRecommendations(student, submissions);\n await syncRecommendationStates(submissions, summary.recommendationCandidates);\n return summary;\n}\n\nasync function loadStudentProgressContext(\n viewerId: string,\n classId: string,\n studentId: string,\n) {\n const isTeacher = await isTeacherInClass(classId, viewerId);\n if (viewerId !== studentId && !isTeacher) {\n throw new TRPCError({\n code: \"UNAUTHORIZED\",\n message: \"You can only view your own progress\",\n });\n }\n\n const [classData, student, submissions] = await Promise.all([\n prisma.class.findUnique({\n where: { id: classId },\n select: { id: true, name: true, subject: true },\n }),\n prisma.user.findFirst({\n where: {\n id: studentId,\n studentIn: { some: { id: classId } },\n },\n select: {\n id: true,\n username: true,\n profile: { select: { displayName: true } },\n },\n }),\n prisma.submission.findMany({\n where: {\n studentId,\n assignment: { classId, graded: true },\n },\n include: {\n assignment: {\n select: {\n id: true,\n title: true,\n dueDate: true,\n maxGrade: true,\n weight: true,\n type: true,\n section: { select: { id: true, name: true } },\n },\n },\n },\n orderBy: { assignment: { dueDate: \"asc\" } },\n }),\n ]);\n\n if (!classData) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Class not found\" });\n }\n\n if (!student) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Student not found in this class\",\n });\n }\n\n return { classData, student, submissions };\n}\n\nexport async function getStudentProgressRecommendations(\n viewerId: string,\n classId: string,\n studentId: string,\n) {\n const { student, submissions } = await loadStudentProgressContext(\n viewerId,\n classId,\n studentId,\n );\n\n const summary = await summarizeStudentRecommendationsWithCases(\n student,\n submissions,\n );\n const {\n recommendationCandidates: _recommendationCandidates,\n ...summaryResponse\n } = summary;\n return {\n student: summaryResponse.student,\n summary: summaryResponse.summary,\n recommendations: summaryResponse.recommendations,\n nextSteps: summaryResponse.nextSteps,\n };\n}\n\nexport async function getClassProgressRecommendations(\n viewerId: string,\n classId: string,\n) {\n const teacherInClass = await isTeacherInClass(classId, viewerId);\n if (!teacherInClass) {\n throw new TRPCError({\n code: \"UNAUTHORIZED\",\n message: \"Only teachers can view class-wide recommendations\",\n });\n }\n\n const classData = await prisma.class.findUnique({\n where: { id: classId },\n select: {\n id: true,\n name: true,\n subject: true,\n students: {\n select: {\n id: true,\n username: true,\n profile: { select: { displayName: true } },\n submissions: {\n where: {\n assignment: { classId, graded: true },\n },\n include: {\n assignment: {\n select: {\n id: true,\n title: true,\n dueDate: true,\n maxGrade: true,\n weight: true,\n type: true,\n section: { select: { id: true, name: true } },\n },\n },\n },\n orderBy: { assignment: { dueDate: \"asc\" } },\n },\n },\n },\n },\n });\n\n if (!classData) {\n throw new TRPCError({ code: \"NOT_FOUND\", message: \"Class not found\" });\n }\n\n const students = (\n await Promise.all(\n classData.students.map((student) =>\n summarizeStudentRecommendationsWithCases(student, student.submissions),\n ),\n )\n )\n .map(\n ({ recommendationCandidates: _recommendationCandidates, ...student }) =>\n student,\n )\n .filter((student) => student.recommendations.length > 0)\n .sort((a, b) => b.priorityScore - a.priorityScore);\n\n const totalRecommendations = students.reduce(\n (sum, student) => sum + student.recommendations.length,\n 0,\n );\n const studentsWithConcerns = students.length;\n const totalMissingAssignments = students.reduce(\n (sum, student) => sum + student.summary.missingCount,\n 0,\n );\n const totalLowScoreAssignments = students.reduce(\n (sum, student) => sum + student.summary.lowScoreCount,\n 0,\n );\n\n return {\n class: {\n id: classData.id,\n name: classData.name,\n subject: classData.subject,\n },\n summary: {\n studentsWithConcerns,\n totalRecommendations,\n totalMissingAssignments,\n totalLowScoreAssignments,\n },\n students: students.map(({ priorityScore, ...student }) => student),\n };\n}\n\nexport async function dismissStudentRecommendation(\n viewerId: string,\n input: {\n classId: string;\n studentId: string;\n submissionId: string;\n },\n) {\n const teacherInClass = await isTeacherInClass(input.classId, viewerId);\n if (!teacherInClass) {\n throw new TRPCError({\n code: \"UNAUTHORIZED\",\n message: \"Only teachers can dismiss recommendations\",\n });\n }\n\n const submission = await prisma.submission.findFirst({\n where: {\n id: input.submissionId,\n studentId: input.studentId,\n assignment: {\n classId: input.classId,\n },\n },\n select: { id: true },\n });\n\n if (!submission) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Submission not found for this student in this class\",\n });\n }\n\n await prisma.submission.update({\n where: { id: input.submissionId },\n data: {\n recommendationState: \"DISMISSED\",\n recommendationUpdatedAt: new Date(),\n },\n });\n\n return { success: true };\n}\n\nconst followUpAssignmentSchema = z.object({\n title: z.string().min(1).max(200),\n instructions: z.string().min(1),\n});\n\nexport type FollowUpAssignmentDraft = z.infer<typeof followUpAssignmentSchema>;\n\nexport async function generateFollowUpAssignment(\n viewerId: string,\n input: {\n classId: string;\n studentId: string;\n submissionId: string;\n prompt: string;\n dueDate?: string;\n },\n) {\n const teacherInClass = await isTeacherInClass(input.classId, viewerId);\n if (!teacherInClass) {\n throw new TRPCError({\n code: \"UNAUTHORIZED\",\n message: \"Only teachers can generate follow-up assignments\",\n });\n }\n\n const submission = await prisma.submission.findFirst({\n where: {\n id: input.submissionId,\n studentId: input.studentId,\n assignment: { classId: input.classId },\n },\n select: {\n id: true,\n gradeReceived: true,\n teacherComments: true,\n student: {\n select: {\n id: true,\n username: true,\n profile: { select: { displayName: true } },\n },\n },\n assignment: {\n select: {\n id: true,\n title: true,\n instructions: true,\n type: true,\n maxGrade: true,\n weight: true,\n section: { select: { id: true, name: true } },\n },\n },\n },\n });\n\n if (!submission) {\n throw new TRPCError({\n code: \"NOT_FOUND\",\n message: \"Submission not found for this student in this class\",\n });\n }\n\n const displayName =\n submission.student.profile?.displayName ?? submission.student.username;\n const percentage =\n submission.gradeReceived != null && submission.assignment.maxGrade\n ? Math.round(\n (submission.gradeReceived / submission.assignment.maxGrade) * 1000,\n ) / 10\n : null;\n\n const draft = await inference<FollowUpAssignmentDraft>(\n [\n {\n role: \"system\" as const,\n content:\n \"You are an experienced teacher creating a targeted follow-up assignment for one student. Ground the task in the source assignment and the teacher's request. Do not fabricate material beyond the source assignment's topic. Return a concise title and clear, student-facing instructions.\",\n },\n {\n role: \"user\" as const,\n content: JSON.stringify({\n student: { displayName },\n sourceAssignment: {\n title: submission.assignment.title,\n instructions: submission.assignment.instructions,\n type: submission.assignment.type,\n maxGrade: submission.assignment.maxGrade,\n section: submission.assignment.section?.name ?? null,\n },\n submission: {\n gradeReceived: submission.gradeReceived,\n percentage,\n teacherFeedback: submission.teacherComments,\n },\n }),\n },\n { role: \"user\" as const, content: input.prompt },\n ],\n followUpAssignmentSchema,\n {\n reason: \"student_progress_follow_up_assignment\",\n metadata: {\n viewerId,\n classId: input.classId,\n studentId: input.studentId,\n submissionId: input.submissionId,\n },\n attribution: { userId: viewerId, classId: input.classId },\n },\n );\n\n const dueDate =\n input.dueDate ??\n new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString();\n\n const assignment = await createAssignmentRecord(viewerId, {\n classId: input.classId,\n title: draft.title,\n instructions: draft.instructions,\n dueDate,\n studentIds: [input.studentId],\n maxGrade: submission.assignment.maxGrade ?? 100,\n graded: true,\n weight: submission.assignment.weight || 1,\n sectionId: submission.assignment.section?.id ?? undefined,\n type: normalizeAssignmentType(submission.assignment.type),\n acceptExtendedResponse: true,\n sourceAssignmentId: submission.assignment.id,\n });\n\n return { assignment, draft };\n}\n\nfunction buildProgressSummary(submissions: GradeSubmission[]) {\n return submissions.map((submission) => ({\n title: submission.assignment.title,\n type: submission.assignment.type,\n dueDate: submission.assignment.dueDate.toISOString(),\n submitted: Boolean(submission.submitted),\n returned: Boolean(submission.returned),\n gradeReceived: submission.gradeReceived,\n maxGrade: submission.assignment.maxGrade,\n percentage: calculatePercentage(submission),\n section: submission.assignment.section?.name ?? null,\n }));\n}\n\nfunction buildStructuredProgressContext(\n classData: { id: string; name: string; subject: string | null },\n student: ProgressStudent,\n submissions: GradeSubmission[],\n) {\n const displayName = student.profile?.displayName ?? student.username;\n const recommendationSummary = summarizeStudentRecommendations(\n student,\n submissions,\n );\n\n return {\n class: classData,\n student: { id: student.id, username: student.username, displayName },\n progress: {\n overallGrade: getOverallGrade(submissions),\n trend: calculateTrend(submissions),\n summary: recommendationSummary.summary,\n assignments: buildProgressSummary(submissions),\n recommendations: recommendationSummary.recommendations.map(\n (recommendation) => ({\n title: recommendation.title,\n recommendationType: recommendation.recommendationType,\n percentage: recommendation.percentage,\n submitted: recommendation.submitted,\n reasons: recommendation.reasons,\n sectionName: recommendation.sectionName,\n }),\n ),\n },\n };\n}\n\nfunction buildStructuredInferenceMessages(\n instruction: string,\n context: ReturnType<typeof buildStructuredProgressContext>,\n) {\n return [\n {\n role: \"system\" as const,\n content:\n \"You are an educational progress analyst. Use only the provided class and grade context. Be specific, concise, supportive, and do not fabricate assignments, grades, or sections.\",\n },\n {\n role: \"user\" as const,\n content: JSON.stringify(context),\n },\n {\n role: \"user\" as const,\n content: instruction,\n },\n ];\n}\n\ntype ProgressInferenceCacheRow<T> = {\n epoch: number;\n cachedAt: number;\n value: T;\n};\n\nconst studentProgressInsightsCache = new Map<\n string,\n ProgressInferenceCacheRow<StudentProgressInsights>\n>();\nconst studentProgressForecastCache = new Map<\n string,\n ProgressInferenceCacheRow<StudentProgressForecast>\n>();\nconst studentProgressFocusCache = new Map<\n string,\n ProgressInferenceCacheRow<StudentProgressFocus>\n>();\n\nexport async function getStudentProgressInsights(\n viewerId: string,\n classId: string,\n studentId: string,\n) {\n const cached = getStudentProgressInferenceCacheHit(\n studentProgressInsightsCache,\n classId,\n studentId,\n );\n\n const { classData, student, submissions } = await loadStudentProgressContext(\n viewerId,\n classId,\n studentId,\n );\n\n if (cached !== undefined) {\n return cached;\n }\n\n const context = buildStructuredProgressContext(\n classData,\n student,\n submissions,\n );\n\n const value = await inference<StudentProgressInsights>(\n buildStructuredInferenceMessages(\n [\n \"Generate an AI analytics summary for this one student's dashboard.\",\n \"The summary must be 2-4 plain-prose sentences: lead with overall grade and trajectory, then call out one strength and one concern with assignment titles.\",\n \"Strengths and growth items need 2-6 word labels and one-line evidence grounded in assignment titles or sections.\",\n \"Talking points must be 3-5 specific teacher check-in prompts with no numbering.\",\n ].join(\" \"),\n context,\n ),\n studentProgressInsightsSchema,\n {\n reason: \"student_progress_insights\",\n metadata: { viewerId, classId, studentId },\n attribution: { userId: viewerId, classId },\n },\n );\n setStudentProgressInferenceCache(\n studentProgressInsightsCache,\n classId,\n studentId,\n value,\n );\n return value;\n}\n\nexport async function getStudentProgressForecast(\n viewerId: string,\n classId: string,\n studentId: string,\n) {\n const cached = getStudentProgressInferenceCacheHit(\n studentProgressForecastCache,\n classId,\n studentId,\n );\n\n const { classData, student, submissions } = await loadStudentProgressContext(\n viewerId,\n classId,\n studentId,\n );\n\n if (cached !== undefined) {\n return cached;\n }\n\n const context = buildStructuredProgressContext(\n classData,\n student,\n submissions,\n );\n\n const value = await inference<StudentProgressForecast>(\n buildStructuredInferenceMessages(\n \"Predict the student's next graded assignment percentage band and risk status. Base the forecast on trajectory, missing work, low scores, and assignment recency. Keep the reason to one sentence.\",\n context,\n ),\n studentProgressForecastSchema,\n {\n reason: \"student_progress_forecast\",\n metadata: { viewerId, classId, studentId },\n attribution: { userId: viewerId, classId },\n },\n );\n setStudentProgressInferenceCache(\n studentProgressForecastCache,\n classId,\n studentId,\n value,\n );\n return value;\n}\n\nexport async function getStudentProgressFocus(\n viewerId: string,\n classId: string,\n studentId: string,\n) {\n const cached = getStudentProgressInferenceCacheHit(\n studentProgressFocusCache,\n classId,\n studentId,\n );\n\n const { classData, student, submissions } = await loadStudentProgressContext(\n viewerId,\n classId,\n studentId,\n );\n\n if (cached !== undefined) {\n return cached;\n }\n \n const context = buildStructuredProgressContext(\n classData,\n student,\n submissions,\n );\n\n const value = await inference<StudentProgressFocus>(\n buildStructuredInferenceMessages(\n \"Generate 3-5 student-facing weekly focus items. Each item should be specific, actionable, and grounded in the student's grade pattern or assignment titles. No numbering in the strings.\",\n context,\n ),\n studentProgressFocusSchema,\n {\n reason: \"student_progress_focus\",\n metadata: { viewerId, classId, studentId },\n attribution: { userId: viewerId, classId },\n },\n );\n setStudentProgressInferenceCache(\n studentProgressFocusCache,\n classId,\n studentId,\n value,\n );\n return value;\n}\n\nexport async function chatAboutStudentProgress(\n viewerId: string,\n input: {\n classId: string;\n studentId: string;\n message: string;\n history?: ProgressChatMessage[];\n },\n) {\n const { classData, student, submissions } = await loadStudentProgressContext(\n viewerId,\n input.classId,\n input.studentId,\n );\n\n const displayName = student.profile?.displayName ?? student.username;\n const summary = {\n overallGrade: getOverallGrade(submissions),\n trend: calculateTrend(submissions),\n assignments: buildProgressSummary(submissions),\n };\n\n const messages = [\n {\n role: \"system\" as const,\n content:\n \"You are an educational progress assistant for teachers and students. Use only the provided class and grade context. Be concise, specific, supportive, and avoid fabricating grades or assignments.\",\n },\n {\n role: \"user\" as const,\n content: JSON.stringify({\n class: classData,\n student: { id: student.id, username: student.username, displayName },\n progress: summary,\n }),\n },\n ...(input.history ?? []).slice(-8).map((message) => ({\n role: message.role,\n content: message.content,\n })),\n { role: \"user\" as const, content: input.message },\n ];\n\n try {\n const response = await inference<string>(messages, undefined, {\n reason: \"student_progress_chat\",\n metadata: {\n viewerId,\n classId: input.classId,\n studentId: input.studentId,\n },\n attribution: { userId: viewerId, classId: input.classId },\n });\n if (typeof response !== \"string\" || response.trim().length === 0) {\n throw new Error(\"Student progress chat returned an empty response\");\n }\n return { message: response, isFallback: false };\n } catch (error) {\n logger.error(\"Failed to generate student progress chat response\", {\n error,\n classId: input.classId,\n studentId: input.studentId,\n });\n\n const overall =\n summary.overallGrade == null\n ? \"not enough graded work\"\n : `${summary.overallGrade}%`;\n const missingItems = summary.assignments.filter(\n (assignment) =>\n !assignment.submitted &&\n new Date(assignment.dueDate).getTime() < Date.now(),\n ).length;\n const lowScores = summary.assignments.filter(\n (assignment) =>\n assignment.percentage != null && assignment.percentage < 70,\n ).length;\n const awaitingFeedback = summary.assignments.filter(\n (assignment) =>\n assignment.submitted &&\n assignment.gradeReceived == null &&\n !assignment.returned,\n ).length;\n\n const fallbackParts = [\n `${displayName}'s current overall grade is ${overall}.`,\n missingItems > 0\n ? `${missingItems} assignment${missingItems === 1 ? \"\" : \"s\"} ${missingItems === 1 ? \"appears\" : \"appear\"} overdue.`\n : null,\n lowScores > 0\n ? `${lowScores} graded assignment${lowScores === 1 ? \" is\" : \"s are\"} below 70%.`\n : null,\n awaitingFeedback > 0\n ? `${awaitingFeedback} assignment${awaitingFeedback === 1 ? \" is\" : \"s are\"} still awaiting feedback.`\n : null,\n summary.trend < -5\n ? \"Recent performance is trending down, so a check-in would be reasonable.\"\n : \"Performance looks relatively steady from the available data.\",\n ].filter((part): part is string => Boolean(part));\n\n return {\n message: fallbackParts.join(\" \"),\n isFallback: true,\n };\n }\n}\n"],"names":[],"mappings":"AAAA;;GAEG;;;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EACL,mCAAmC,EACnC,gCAAgC,GACjC,MAAM,oCAAoC,CAAC;AAgC5C,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;CACrB,CAAC,CAAC;AAEH,MAAM,6BAA6B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACnD,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAChD,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;CACjD,CAAC,CAAC;AAEH,MAAM,6BAA6B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IACvC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IACxC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IAC9C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;CACnB,CAAC,CAAC;AAEH,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;CAC9C,CAAC,CAAC;AAYH,SAAS,mBAAmB,CAAC,UAA2B;IACtD,IAAI,UAAU,CAAC,aAAa,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;QACxE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CACL,IAAI,CAAC,KAAK,CACR,CAAC,UAAU,CAAC,aAAa,GAAG,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,IAAI,CACnE,GAAG,EAAE,CACP,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,WAA8B;IACpD,MAAM,MAAM,GAAG,WAAW;SACvB,MAAM,CACL,CAAC,UAAU,EAAE,EAAE,CACb,UAAU,CAAC,aAAa,IAAI,IAAI,IAAI,UAAU,CAAC,UAAU,CAAC,QAAQ,CACrE;SACA,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACb,MAAM,KAAK,GAAG,CAAC,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACzE,MAAM,KAAK,GAAG,CAAC,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACzE,OAAO,KAAK,GAAG,KAAK,CAAC;IACvB,CAAC,CAAC;SACD,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;SACpD,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;IAErD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IAEhC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,CAAC,MAAgB,EAAE,EAAE,CACnC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;IAEhE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC;AAClE,CAAC;AAED,SAAS,eAAe,CAAC,WAA8B;IACrD,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,IACE,UAAU,CAAC,aAAa,IAAI,IAAI;YAChC,UAAU,CAAC,UAAU,CAAC,QAAQ;YAC9B,UAAU,CAAC,UAAU,CAAC,MAAM,EAC5B,CAAC;YACD,aAAa;gBACX,CAAC,UAAU,CAAC,aAAa,GAAG,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC;oBAC3D,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC;YAC/B,WAAW,IAAI,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,OAAO,WAAW,GAAG,CAAC;QACpB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,aAAa,GAAG,WAAW,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE;QACvD,CAAC,CAAC,IAAI,CAAC;AACX,CAAC;AAED,SAAS,uBAAuB,CAC9B,cAA8B;IAE9B,IAAI,cAAc,KAAK,MAAM,IAAI,cAAc,KAAK,MAAM,EAAE,CAAC;QAC3D,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,SAAS,wBAAwB,CAC/B,kBAAsC,EACtC,UAA2B,EAC3B,WAAmB,EACnB,UAAyB;IAEzB,MAAM,WAAW,GAAG,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC;IAChD,MAAM,OAAO,GAAG,UAAU,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC;IACpD,MAAM,WAAW,GAAuC;QACtD,OAAO,EAAE,YAAY,WAAW,EAAE;QAClC,SAAS,EAAE,sBAAsB,WAAW,EAAE;QAC9C,iBAAiB,EAAE,uBAAuB,WAAW,EAAE;KACxD,CAAC;IACF,MAAM,UAAU,GAAuC;QACrD,OAAO,EAAE,GAAG,WAAW,wFAAwF;QAC/G,SAAS,EACP,UAAU,IAAI,IAAI;YAChB,CAAC,CAAC,GAAG,WAAW,WAAW,UAAU,gEAAgE;YACrG,CAAC,CAAC,GAAG,WAAW,2DAA2D;QAC/E,iBAAiB,EAAE,GAAG,WAAW,yFAAyF;KAC3H,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,WAAW,CAAC,kBAAkB,CAAC;QACtC,YAAY,EAAE;YACZ,UAAU,CAAC,kBAAkB,CAAC;YAC9B,sBAAsB,WAAW,GAAG;YACpC,OAAO,CAAC,CAAC,CAAC,YAAY,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI;YACvC,oEAAoE;SACrE;aACE,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;aAC/C,IAAI,CAAC,MAAM,CAAC;QACf,IAAI,EAAE,uBAAuB,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC;QACzD,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,QAAQ,IAAI,GAAG;QAC/C,MAAM,EAAE,UAAU,CAAC,UAAU,CAAC,MAAM,IAAI,CAAC;QACzC,MAAM,EAAE,IAAI;QACZ,SAAS,EAAE,UAAU,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,IAAI,IAAI;QACpD,kBAAkB,EAAE,UAAU,CAAC,UAAU,CAAC,EAAE;KAC7C,CAAC;AACJ,CAAC;AAED,SAAS,4BAA4B,CACnC,UAA2B,EAC3B,WAAmB,EACnB,GAAS;IAET,IACE,UAAU,CAAC,mBAAmB,KAAK,UAAU;QAC7C,UAAU,CAAC,mBAAmB,KAAK,WAAW,EAC9C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,UAAU,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;IACnD,MAAM,SAAS,GACb,CAAC,UAAU,CAAC,SAAS;QACrB,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;IAC1D,MAAM,UAAU,GAAG,UAAU,IAAI,IAAI,IAAI,UAAU,GAAG,EAAE,CAAC;IACzD,MAAM,YAAY,GAChB,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC;QAC7B,UAAU,CAAC,aAAa,IAAI,IAAI;QAChC,CAAC,UAAU,CAAC,QAAQ,CAAC;IACvB,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,IAAI,kBAAkB,GAA8B,IAAI,CAAC;IAEzD,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QACtC,aAAa,IAAI,GAAG,CAAC;QACrB,kBAAkB,GAAG,SAAS,CAAC;IACjC,CAAC;IACD,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,UAAU,UAAU,GAAG,CAAC,CAAC;QACtC,aAAa,IAAI,EAAE,GAAG,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC;QACxC,kBAAkB,KAAlB,kBAAkB,GAAK,WAAW,EAAC;IACrC,CAAC;IACD,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QAC3C,aAAa,IAAI,EAAE,CAAC;QACpB,kBAAkB,KAAlB,kBAAkB,GAAK,mBAAmB,EAAC;IAC7C,CAAC;IAED,IAAI,aAAa,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,YAAY,EAAE,UAAU,CAAC,UAAU,CAAC,EAAE;QACtC,YAAY,EAAE,UAAU,CAAC,EAAE;QAC3B,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK;QAClC,IAAI,EAAE,UAAU,CAAC,UAAU,CAAC,IAAI;QAChC,SAAS,EAAE,UAAU,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,IAAI,IAAI;QACpD,WAAW,EAAE,UAAU,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,IAAI,IAAI;QACxD,OAAO,EAAE,UAAU,CAAC,UAAU,CAAC,OAAO;QACtC,aAAa,EAAE,UAAU,CAAC,aAAa;QACvC,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,QAAQ;QACxC,UAAU;QACV,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC;QACxC,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC;QACtC,kBAAkB;QAClB,OAAO;QACP,aAAa;QACb,mBAAmB,EAAE,wBAAwB,CAC3C,kBAAkB,EAClB,UAAU,EACV,WAAW,EACX,UAAU,CACX;KACF,CAAC;AACJ,CAAC;AAED,SAAS,+BAA+B,CACtC,OAAwB,EACxB,WAA8B;IAE9B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,EAAE,WAAW,IAAI,OAAO,CAAC,QAAQ,CAAC;IACrE,MAAM,wBAAwB,GAAG,WAAW;SACzC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAClB,4BAA4B,CAAC,UAAU,EAAE,WAAW,EAAE,GAAG,CAAC,CAC3D;SACA,MAAM,CACL,CACE,SAAS,EAGT,EAAE,CAAC,SAAS,IAAI,IAAI,CACvB;SACA,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC;IAErD,MAAM,eAAe,GAAG,wBAAwB;SAC7C,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;SACX,GAAG,CAAC,CAAC,EAAE,aAAa,EAAE,GAAG,SAAS,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC;IAEvD,MAAM,iBAAiB,GAAG,WAAW;SAClC,GAAG,CAAC,mBAAmB,CAAC;SACxB,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;IACrD,MAAM,aAAa,GAAG,iBAAiB,CAAC,MAAM,CAC5C,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG,EAAE,CAChC,CAAC,MAAM,CAAC;IACT,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CACrC,CAAC,UAAU,EAAE,EAAE,CACb,CAAC,UAAU,CAAC,SAAS;QACrB,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAC1D,CAAC,MAAM,CAAC;IACT,MAAM,KAAK,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,YAAY,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IAElD,MAAM,SAAS,GAAG;QAChB,YAAY,GAAG,CAAC;YACd,CAAC,CAAC,cAAc,YAAY,sBAAsB,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG;YAClF,CAAC,CAAC,IAAI;QACR,aAAa,GAAG,CAAC;YACf,CAAC,CAAC,UAAU,aAAa,0BAA0B,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,mCAAmC;YACpH,CAAC,CAAC,IAAI;QACR,KAAK,GAAG,CAAC,CAAC;YACR,CAAC,CAAC,kEAAkE;YACpE,CAAC,CAAC,IAAI;QACR,wBAAwB,CAAC,MAAM,KAAK,CAAC;YACnC,CAAC,CAAC,iEAAiE;YACnE,CAAC,CAAC,IAAI;KACT,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAElD,OAAO;QACL,OAAO,EAAE;YACP,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,WAAW;SACZ;QACD,OAAO,EAAE;YACP,YAAY;YACZ,KAAK;YACL,oBAAoB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CACtD,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAC9B,CAAC,MAAM;YACR,gBAAgB,EAAE,WAAW,CAAC,MAAM;YACpC,YAAY;YACZ,aAAa;SACd;QACD,eAAe;QACf,wBAAwB;QACxB,SAAS;QACT,aAAa,EAAE,wBAAwB,CAAC,CAAC,CAAC,EAAE,aAAa,IAAI,CAAC;KAC/D,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,wBAAwB,CACrC,WAA8B,EAC9B,wBAEC;IAED,MAAM,sBAAsB,GAAG,IAAI,GAAG,CACpC,wBAAwB,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,YAAY,CAAC,CACpE,CAAC;IACF,MAAM,OAAO,GAAuB,EAAE,CAAC;IAEvC,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,MAAM,YAAY,GAAG,sBAAsB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAE/D,IAAI,YAAY,IAAI,UAAU,CAAC,mBAAmB,KAAK,MAAM,EAAE,CAAC;YAC9D,OAAO,CAAC,IAAI,CACV,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC;gBACvB,KAAK,EAAE,EAAE,EAAE,EAAE,UAAU,CAAC,EAAE,EAAE;gBAC5B,IAAI,EAAE;oBACJ,mBAAmB,EAAE,MAAM;oBAC3B,uBAAuB,EAAE,IAAI,IAAI,EAAE;iBACpC;aACF,CAAC,CACH,CAAC;YACF,SAAS;QACX,CAAC;QAED,IAAI,CAAC,YAAY,IAAI,UAAU,CAAC,mBAAmB,KAAK,MAAM,EAAE,CAAC;YAC/D,OAAO,CAAC,IAAI,CACV,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC;gBACvB,KAAK,EAAE,EAAE,EAAE,EAAE,UAAU,CAAC,EAAE,EAAE;gBAC5B,IAAI,EAAE;oBACJ,mBAAmB,EAAE,MAAM;oBAC3B,uBAAuB,EAAE,IAAI,IAAI,EAAE;iBACpC;aACF,CAAC,CACH,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;AACH,CAAC;AAED,KAAK,UAAU,wCAAwC,CACrD,OAAwB,EACxB,WAA8B;IAE9B,MAAM,OAAO,GAAG,+BAA+B,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACtE,MAAM,wBAAwB,CAAC,WAAW,EAAE,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAC9E,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,0BAA0B,CACvC,QAAgB,EAChB,OAAe,EACf,SAAiB;IAEjB,MAAM,SAAS,GAAG,MAAM,gBAAgB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC5D,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,SAAS,EAAE,CAAC;QACzC,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,cAAc;YACpB,OAAO,EAAE,qCAAqC;SAC/C,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,WAAW,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC1D,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC;YACtB,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE;YACtB,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE;SAChD,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;YACpB,KAAK,EAAE;gBACL,EAAE,EAAE,SAAS;gBACb,SAAS,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE;aACrC;YACD,MAAM,EAAE;gBACN,EAAE,EAAE,IAAI;gBACR,QAAQ,EAAE,IAAI;gBACd,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE;aAC3C;SACF,CAAC;QACF,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC;YACzB,KAAK,EAAE;gBACL,SAAS;gBACT,UAAU,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE;aACtC;YACD,OAAO,EAAE;gBACP,UAAU,EAAE;oBACV,MAAM,EAAE;wBACN,EAAE,EAAE,IAAI;wBACR,KAAK,EAAE,IAAI;wBACX,OAAO,EAAE,IAAI;wBACb,QAAQ,EAAE,IAAI;wBACd,MAAM,EAAE,IAAI;wBACZ,IAAI,EAAE,IAAI;wBACV,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;qBAC9C;iBACF;aACF;YACD,OAAO,EAAE,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;SAC5C,CAAC;KACH,CAAC,CAAC;IAEH,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,iCAAiC;SAC3C,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iCAAiC,CACrD,QAAgB,EAChB,OAAe,EACf,SAAiB;IAEjB,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,0BAA0B,CAC/D,QAAQ,EACR,OAAO,EACP,SAAS,CACV,CAAC;IAEF,MAAM,OAAO,GAAG,MAAM,wCAAwC,CAC5D,OAAO,EACP,WAAW,CACZ,CAAC;IACF,MAAM,EACJ,wBAAwB,EAAE,yBAAyB,EACnD,GAAG,eAAe,EACnB,GAAG,OAAO,CAAC;IACZ,OAAO;QACL,OAAO,EAAE,eAAe,CAAC,OAAO;QAChC,OAAO,EAAE,eAAe,CAAC,OAAO;QAChC,eAAe,EAAE,eAAe,CAAC,eAAe;QAChD,SAAS,EAAE,eAAe,CAAC,SAAS;KACrC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,+BAA+B,CACnD,QAAgB,EAChB,OAAe;IAEf,MAAM,cAAc,GAAG,MAAM,gBAAgB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACjE,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,cAAc;YACpB,OAAO,EAAE,mDAAmD;SAC7D,CAAC,CAAC;IACL,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC;QAC9C,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE;QACtB,MAAM,EAAE;YACN,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,IAAI;YACV,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE;gBACR,MAAM,EAAE;oBACN,EAAE,EAAE,IAAI;oBACR,QAAQ,EAAE,IAAI;oBACd,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE;oBAC1C,WAAW,EAAE;wBACX,KAAK,EAAE;4BACL,UAAU,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE;yBACtC;wBACD,OAAO,EAAE;4BACP,UAAU,EAAE;gCACV,MAAM,EAAE;oCACN,EAAE,EAAE,IAAI;oCACR,KAAK,EAAE,IAAI;oCACX,OAAO,EAAE,IAAI;oCACb,QAAQ,EAAE,IAAI;oCACd,MAAM,EAAE,IAAI;oCACZ,IAAI,EAAE,IAAI;oCACV,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;iCAC9C;6BACF;yBACF;wBACD,OAAO,EAAE,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;qBAC5C;iBACF;aACF;SACF;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,QAAQ,GAAG,CACf,MAAM,OAAO,CAAC,GAAG,CACf,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CACjC,wCAAwC,CAAC,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,CACvE,CACF,CACF;SACE,GAAG,CACF,CAAC,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,GAAG,OAAO,EAAE,EAAE,EAAE,CACtE,OAAO,CACV;SACA,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC;SACvD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC;IAErD,MAAM,oBAAoB,GAAG,QAAQ,CAAC,MAAM,CAC1C,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,GAAG,OAAO,CAAC,eAAe,CAAC,MAAM,EACtD,CAAC,CACF,CAAC;IACF,MAAM,oBAAoB,GAAG,QAAQ,CAAC,MAAM,CAAC;IAC7C,MAAM,uBAAuB,GAAG,QAAQ,CAAC,MAAM,CAC7C,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,EACpD,CAAC,CACF,CAAC;IACF,MAAM,wBAAwB,GAAG,QAAQ,CAAC,MAAM,CAC9C,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,EACrD,CAAC,CACF,CAAC;IAEF,OAAO;QACL,KAAK,EAAE;YACL,EAAE,EAAE,SAAS,CAAC,EAAE;YAChB,IAAI,EAAE,SAAS,CAAC,IAAI;YACpB,OAAO,EAAE,SAAS,CAAC,OAAO;SAC3B;QACD,OAAO,EAAE;YACP,oBAAoB;YACpB,oBAAoB;YACpB,uBAAuB;YACvB,wBAAwB;SACzB;QACD,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC;KACnE,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,QAAgB,EAChB,KAIC;IAED,MAAM,cAAc,GAAG,MAAM,gBAAgB,CAAC,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACvE,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,cAAc;YACpB,OAAO,EAAE,2CAA2C;SACrD,CAAC,CAAC;IACL,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC;QACnD,KAAK,EAAE;YACL,EAAE,EAAE,KAAK,CAAC,YAAY;YACtB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,UAAU,EAAE;gBACV,OAAO,EAAE,KAAK,CAAC,OAAO;aACvB;SACF;QACD,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE;KACrB,CAAC,CAAC;IAEH,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,qDAAqD;SAC/D,CAAC,CAAC;IACL,CAAC;IAED,MAAM,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC;QAC7B,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,YAAY,EAAE;QACjC,IAAI,EAAE;YACJ,mBAAmB,EAAE,WAAW;YAChC,uBAAuB,EAAE,IAAI,IAAI,EAAE;SACpC;KACF,CAAC,CAAC;IAEH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IACjC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAChC,CAAC,CAAC;AAIH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,QAAgB,EAChB,KAMC;IAED,MAAM,cAAc,GAAG,MAAM,gBAAgB,CAAC,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACvE,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,cAAc;YACpB,OAAO,EAAE,kDAAkD;SAC5D,CAAC,CAAC;IACL,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC;QACnD,KAAK,EAAE;YACL,EAAE,EAAE,KAAK,CAAC,YAAY;YACtB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,UAAU,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;SACvC;QACD,MAAM,EAAE;YACN,EAAE,EAAE,IAAI;YACR,aAAa,EAAE,IAAI;YACnB,eAAe,EAAE,IAAI;YACrB,OAAO,EAAE;gBACP,MAAM,EAAE;oBACN,EAAE,EAAE,IAAI;oBACR,QAAQ,EAAE,IAAI;oBACd,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE;iBAC3C;aACF;YACD,UAAU,EAAE;gBACV,MAAM,EAAE;oBACN,EAAE,EAAE,IAAI;oBACR,KAAK,EAAE,IAAI;oBACX,YAAY,EAAE,IAAI;oBAClB,IAAI,EAAE,IAAI;oBACV,QAAQ,EAAE,IAAI;oBACd,MAAM,EAAE,IAAI;oBACZ,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;iBAC9C;aACF;SACF;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,SAAS,CAAC;YAClB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,qDAAqD;SAC/D,CAAC,CAAC;IACL,CAAC;IAED,MAAM,WAAW,GACf,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,WAAW,IAAI,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC;IACzE,MAAM,UAAU,GACd,UAAU,CAAC,aAAa,IAAI,IAAI,IAAI,UAAU,CAAC,UAAU,CAAC,QAAQ;QAChE,CAAC,CAAC,IAAI,CAAC,KAAK,CACR,CAAC,UAAU,CAAC,aAAa,GAAG,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,IAAI,CACnE,GAAG,EAAE;QACR,CAAC,CAAC,IAAI,CAAC;IAEX,MAAM,KAAK,GAAG,MAAM,SAAS,CAC3B;QACE;YACE,IAAI,EAAE,QAAiB;YACvB,OAAO,EACL,6RAA6R;SAChS;QACD;YACE,IAAI,EAAE,MAAe;YACrB,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC;gBACtB,OAAO,EAAE,EAAE,WAAW,EAAE;gBACxB,gBAAgB,EAAE;oBAChB,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK;oBAClC,YAAY,EAAE,UAAU,CAAC,UAAU,CAAC,YAAY;oBAChD,IAAI,EAAE,UAAU,CAAC,UAAU,CAAC,IAAI;oBAChC,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,QAAQ;oBACxC,OAAO,EAAE,UAAU,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,IAAI,IAAI;iBACrD;gBACD,UAAU,EAAE;oBACV,aAAa,EAAE,UAAU,CAAC,aAAa;oBACvC,UAAU;oBACV,eAAe,EAAE,UAAU,CAAC,eAAe;iBAC5C;aACF,CAAC;SACH;QACD,EAAE,IAAI,EAAE,MAAe,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,EAAE;KACjD,EACD,wBAAwB,EACxB;QACE,MAAM,EAAE,uCAAuC;QAC/C,QAAQ,EAAE;YACR,QAAQ;YACR,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,YAAY,EAAE,KAAK,CAAC,YAAY;SACjC;QACD,WAAW,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;KAC1D,CACF,CAAC;IAEF,MAAM,OAAO,GACX,KAAK,CAAC,OAAO;QACb,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IAE/D,MAAM,UAAU,GAAG,MAAM,sBAAsB,CAAC,QAAQ,EAAE;QACxD,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,OAAO;QACP,UAAU,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC;QAC7B,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,QAAQ,IAAI,GAAG;QAC/C,MAAM,EAAE,IAAI;QACZ,MAAM,EAAE,UAAU,CAAC,UAAU,CAAC,MAAM,IAAI,CAAC;QACzC,SAAS,EAAE,UAAU,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,IAAI,SAAS;QACzD,IAAI,EAAE,uBAAuB,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC;QACzD,sBAAsB,EAAE,IAAI;QAC5B,kBAAkB,EAAE,UAAU,CAAC,UAAU,CAAC,EAAE;KAC7C,CAAC,CAAC;IAEH,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;AAC/B,CAAC;AAED,SAAS,oBAAoB,CAAC,WAA8B;IAC1D,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QACtC,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK;QAClC,IAAI,EAAE,UAAU,CAAC,UAAU,CAAC,IAAI;QAChC,OAAO,EAAE,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,WAAW,EAAE;QACpD,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC;QACxC,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC;QACtC,aAAa,EAAE,UAAU,CAAC,aAAa;QACvC,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,QAAQ;QACxC,UAAU,EAAE,mBAAmB,CAAC,UAAU,CAAC;QAC3C,OAAO,EAAE,UAAU,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,IAAI,IAAI;KACrD,CAAC,CAAC,CAAC;AACN,CAAC;AAED,SAAS,8BAA8B,CACrC,SAA+D,EAC/D,OAAwB,EACxB,WAA8B;IAE9B,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,EAAE,WAAW,IAAI,OAAO,CAAC,QAAQ,CAAC;IACrE,MAAM,qBAAqB,GAAG,+BAA+B,CAC3D,OAAO,EACP,WAAW,CACZ,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,SAAS;QAChB,OAAO,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,WAAW,EAAE;QACpE,QAAQ,EAAE;YACR,YAAY,EAAE,eAAe,CAAC,WAAW,CAAC;YAC1C,KAAK,EAAE,cAAc,CAAC,WAAW,CAAC;YAClC,OAAO,EAAE,qBAAqB,CAAC,OAAO;YACtC,WAAW,EAAE,oBAAoB,CAAC,WAAW,CAAC;YAC9C,eAAe,EAAE,qBAAqB,CAAC,eAAe,CAAC,GAAG,CACxD,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;gBACnB,KAAK,EAAE,cAAc,CAAC,KAAK;gBAC3B,kBAAkB,EAAE,cAAc,CAAC,kBAAkB;gBACrD,UAAU,EAAE,cAAc,CAAC,UAAU;gBACrC,SAAS,EAAE,cAAc,CAAC,SAAS;gBACnC,OAAO,EAAE,cAAc,CAAC,OAAO;gBAC/B,WAAW,EAAE,cAAc,CAAC,WAAW;aACxC,CAAC,CACH;SACF;KACF,CAAC;AACJ,CAAC;AAED,SAAS,gCAAgC,CACvC,WAAmB,EACnB,OAA0D;IAE1D,OAAO;QACL;YACE,IAAI,EAAE,QAAiB;YACvB,OAAO,EACL,kLAAkL;SACrL;QACD;YACE,IAAI,EAAE,MAAe;YACrB,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;SACjC;QACD;YACE,IAAI,EAAE,MAAe;YACrB,OAAO,EAAE,WAAW;SACrB;KACF,CAAC;AACJ,CAAC;AAQD,MAAM,4BAA4B,GAAG,IAAI,GAAG,EAGzC,CAAC;AACJ,MAAM,4BAA4B,GAAG,IAAI,GAAG,EAGzC,CAAC;AACJ,MAAM,yBAAyB,GAAG,IAAI,GAAG,EAGtC,CAAC;AAEJ,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,QAAgB,EAChB,OAAe,EACf,SAAiB;IAEjB,MAAM,MAAM,GAAG,mCAAmC,CAChD,4BAA4B,EAC5B,OAAO,EACP,SAAS,CACV,CAAC;IAEF,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,0BAA0B,CAC1E,QAAQ,EACR,OAAO,EACP,SAAS,CACV,CAAC;IAEF,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,OAAO,GAAG,8BAA8B,CAC5C,SAAS,EACT,OAAO,EACP,WAAW,CACZ,CAAC;IAEF,MAAM,KAAK,GAAG,MAAM,SAAS,CAC3B,gCAAgC,CAC9B;QACE,oEAAoE;QACpE,2JAA2J;QAC3J,kHAAkH;QAClH,iFAAiF;KAClF,CAAC,IAAI,CAAC,GAAG,CAAC,EACX,OAAO,CACR,EACD,6BAA6B,EAC7B;QACE,MAAM,EAAE,2BAA2B;QACnC,QAAQ,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE;QAC1C,WAAW,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE;KAC3C,CACF,CAAC;IACF,gCAAgC,CAC9B,4BAA4B,EAC5B,OAAO,EACP,SAAS,EACT,KAAK,CACN,CAAC;IACF,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,QAAgB,EAChB,OAAe,EACf,SAAiB;IAEjB,MAAM,MAAM,GAAG,mCAAmC,CAChD,4BAA4B,EAC5B,OAAO,EACP,SAAS,CACV,CAAC;IAEF,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,0BAA0B,CAC1E,QAAQ,EACR,OAAO,EACP,SAAS,CACV,CAAC;IAEF,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,OAAO,GAAG,8BAA8B,CAC5C,SAAS,EACT,OAAO,EACP,WAAW,CACZ,CAAC;IAEF,MAAM,KAAK,GAAG,MAAM,SAAS,CAC3B,gCAAgC,CAC9B,mMAAmM,EACnM,OAAO,CACR,EACD,6BAA6B,EAC7B;QACE,MAAM,EAAE,2BAA2B;QACnC,QAAQ,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE;QAC1C,WAAW,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE;KAC3C,CACF,CAAC;IACF,gCAAgC,CAC9B,4BAA4B,EAC5B,OAAO,EACP,SAAS,EACT,KAAK,CACN,CAAC;IACF,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,QAAgB,EAChB,OAAe,EACf,SAAiB;IAEjB,MAAM,MAAM,GAAG,mCAAmC,CAChD,yBAAyB,EACzB,OAAO,EACP,SAAS,CACV,CAAC;IAEF,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,0BAA0B,CAC1E,QAAQ,EACR,OAAO,EACP,SAAS,CACV,CAAC;IAEF,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,OAAO,GAAG,8BAA8B,CAC5C,SAAS,EACT,OAAO,EACP,WAAW,CACZ,CAAC;IAEF,MAAM,KAAK,GAAG,MAAM,SAAS,CAC3B,gCAAgC,CAC9B,0LAA0L,EAC1L,OAAO,CACR,EACD,0BAA0B,EAC1B;QACE,MAAM,EAAE,wBAAwB;QAChC,QAAQ,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE;QAC1C,WAAW,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE;KAC3C,CACF,CAAC;IACF,gCAAgC,CAC9B,yBAAyB,EACzB,OAAO,EACP,SAAS,EACT,KAAK,CACN,CAAC;IACF,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,QAAgB,EAChB,KAKC;IAED,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,0BAA0B,CAC1E,QAAQ,EACR,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,SAAS,CAChB,CAAC;IAEF,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,EAAE,WAAW,IAAI,OAAO,CAAC,QAAQ,CAAC;IACrE,MAAM,OAAO,GAAG;QACd,YAAY,EAAE,eAAe,CAAC,WAAW,CAAC;QAC1C,KAAK,EAAE,cAAc,CAAC,WAAW,CAAC;QAClC,WAAW,EAAE,oBAAoB,CAAC,WAAW,CAAC;KAC/C,CAAC;IAEF,MAAM,QAAQ,GAAG;QACf;YACE,IAAI,EAAE,QAAiB;YACvB,OAAO,EACL,oMAAoM;SACvM;QACD;YACE,IAAI,EAAE,MAAe;YACrB,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC;gBACtB,KAAK,EAAE,SAAS;gBAChB,OAAO,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,WAAW,EAAE;gBACpE,QAAQ,EAAE,OAAO;aAClB,CAAC;SACH;QACD,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACnD,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC,CAAC;QACH,EAAE,IAAI,EAAE,MAAe,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;KAClD,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAS,QAAQ,EAAE,SAAS,EAAE;YAC5D,MAAM,EAAE,uBAAuB;YAC/B,QAAQ,EAAE;gBACR,QAAQ;gBACR,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,SAAS,EAAE,KAAK,CAAC,SAAS;aAC3B;YACD,WAAW,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;SAC1D,CAAC,CAAC;QACH,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjE,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;QACtE,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IAClD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,mDAAmD,EAAE;YAChE,KAAK;YACL,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B,CAAC,CAAC;QAEH,MAAM,OAAO,GACX,OAAO,CAAC,YAAY,IAAI,IAAI;YAC1B,CAAC,CAAC,wBAAwB;YAC1B,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,GAAG,CAAC;QACjC,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,CAC7C,CAAC,UAAU,EAAE,EAAE,CACb,CAAC,UAAU,CAAC,SAAS;YACrB,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CACtD,CAAC,MAAM,CAAC;QACT,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,CAC1C,CAAC,UAAU,EAAE,EAAE,CACb,UAAU,CAAC,UAAU,IAAI,IAAI,IAAI,UAAU,CAAC,UAAU,GAAG,EAAE,CAC9D,CAAC,MAAM,CAAC;QACT,MAAM,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,CACjD,CAAC,UAAU,EAAE,EAAE,CACb,UAAU,CAAC,SAAS;YACpB,UAAU,CAAC,aAAa,IAAI,IAAI;YAChC,CAAC,UAAU,CAAC,QAAQ,CACvB,CAAC,MAAM,CAAC;QAET,MAAM,aAAa,GAAG;YACpB,GAAG,WAAW,+BAA+B,OAAO,GAAG;YACvD,YAAY,GAAG,CAAC;gBACd,CAAC,CAAC,GAAG,YAAY,cAAc,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,WAAW;gBACpH,CAAC,CAAC,IAAI;YACR,SAAS,GAAG,CAAC;gBACX,CAAC,CAAC,GAAG,SAAS,qBAAqB,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,aAAa;gBACjF,CAAC,CAAC,IAAI;YACR,gBAAgB,GAAG,CAAC;gBAClB,CAAC,CAAC,GAAG,gBAAgB,cAAc,gBAAgB,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,2BAA2B;gBACtG,CAAC,CAAC,IAAI;YACR,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC;gBAChB,CAAC,CAAC,yEAAyE;gBAC3E,CAAC,CAAC,8DAA8D;SACnE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAElD,OAAO;YACL,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC;YAChC,UAAU,EAAE,IAAI;SACjB,CAAC;IACJ,CAAC;AACH,CAAC","debug_id":"95393c1d-f8f7-5a00-adf1-4b143ba57f36"}
@@ -122,6 +122,16 @@ export declare function completePendingAIMessage(messageId: string, content: str
122
122
  createdAt: Date;
123
123
  status: JobStatus;
124
124
  }>;
125
+ /**
126
+ * Persist the partial output of a cancelled generation and flip the AI
127
+ * message to CANCELLED. Whatever text/tool parts streamed before the stop
128
+ * are kept on the row (content + meta) so they survive reloads. Broadcasts
129
+ * `message-updated` so clients patch the bubble in place.
130
+ */
131
+ export declare function cancelPendingAIMessage(messageId: string, content: string, options?: {
132
+ meta?: Record<string, any>;
133
+ customSender?: AIMessageSenderInfo;
134
+ }): Promise<void>;
125
135
  /**
126
136
  * Flip a PENDING AI message to FAILED and broadcast the status change.
127
137
  * Does NOT throw — failure paths in the pipelines call this in catch blocks
@@ -1 +1 @@
1
- {"version":3,"file":"inference.d.ts","sourceRoot":"/","sources":["utils/inference.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"inference.d.ts","sourceRoot":"/","sources":["utils/inference.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
  * Inference util – OpenAI client, inference() for structured output, sendAIMessage for chat.
3
3
  */
4
4
 
5
- !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]="9b4ef7a2-3350-5df6-a238-3340a03e8b3e")}catch(e){}}();
5
+ !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]="ba92dc8c-6ba8-5d95-a027-50c47894fcc3")}catch(e){}}();
6
6
  import OpenAI from 'openai';
7
7
  import { logger } from './logger.js';
8
8
  import { prisma } from '../lib/prisma.js';
@@ -306,6 +306,68 @@ export async function completePendingAIMessage(messageId, content, options = {})
306
306
  status: (updated.status ?? JobStatus.COMPLETED),
307
307
  };
308
308
  }
309
+ /**
310
+ * Persist the partial output of a cancelled generation and flip the AI
311
+ * message to CANCELLED. Whatever text/tool parts streamed before the stop
312
+ * are kept on the row (content + meta) so they survive reloads. Broadcasts
313
+ * `message-updated` so clients patch the bubble in place.
314
+ */
315
+ export async function cancelPendingAIMessage(messageId, content, options = {}) {
316
+ try {
317
+ const updated = await prisma.message.update({
318
+ where: { id: messageId },
319
+ data: {
320
+ content,
321
+ status: JobStatus.CANCELLED,
322
+ ...(options.meta !== undefined && {
323
+ meta: options.meta,
324
+ }),
325
+ },
326
+ include: {
327
+ attachments: true,
328
+ },
329
+ });
330
+ logger.info('AI message cancelled', {
331
+ messageId: updated.id,
332
+ conversationId: updated.conversationId,
333
+ contentLength: content.length,
334
+ });
335
+ const senderInfo = buildAISenderInfo(options.customSender);
336
+ try {
337
+ await pusher.trigger(chatChannel(updated.conversationId), 'message-updated', {
338
+ id: updated.id,
339
+ content: updated.content,
340
+ senderId: updated.senderId,
341
+ conversationId: updated.conversationId,
342
+ status: updated.status,
343
+ createdAt: updated.createdAt,
344
+ sender: senderInfo,
345
+ mentionedUserIds: [],
346
+ meta: updated.meta ?? {},
347
+ attachments: updated.attachments.map((attachment) => ({
348
+ id: attachment.id,
349
+ attachmentId: attachment.id,
350
+ name: attachment.name,
351
+ type: attachment.type,
352
+ size: attachment.size,
353
+ path: attachment.path,
354
+ })),
355
+ });
356
+ }
357
+ catch (broadcastError) {
358
+ logger.error('Failed to broadcast cancelled AI message:', {
359
+ error: broadcastError,
360
+ messageId,
361
+ });
362
+ }
363
+ }
364
+ catch (error) {
365
+ logger.error('Failed to mark AI message as cancelled:', {
366
+ error,
367
+ messageId,
368
+ });
369
+ }
370
+ }
309
371
  /**
310
372
  * Flip a PENDING AI message to FAILED and broadcast the status change.
311
373
  * Does NOT throw — failure paths in the pipelines call this in catch blocks
@@ -313,6 +375,19 @@ export async function completePendingAIMessage(messageId, content, options = {})
313
375
  */
314
376
  export async function failPendingAIMessage(messageId, options = {}) {
315
377
  try {
378
+ const current = await prisma.message.findUnique({
379
+ where: { id: messageId },
380
+ select: { status: true },
381
+ });
382
+ // A message the user already cancelled must stay CANCELLED — late
383
+ // failures from the aborted pipeline are a consequence of the cancel.
384
+ if (current?.status === JobStatus.CANCELLED) {
385
+ logger.info('Skipping FAILED flip; AI message already cancelled', {
386
+ messageId,
387
+ reason: options.reason,
388
+ });
389
+ return;
390
+ }
316
391
  const updated = await prisma.message.update({
317
392
  where: { id: messageId },
318
393
  data: { status: JobStatus.FAILED },
@@ -489,4 +564,4 @@ export function estimateTokenCount(text) {
489
564
  return Math.ceil(text.length / 4);
490
565
  }
491
566
  //# sourceMappingURL=inference.js.map
492
- //# debugId=9b4ef7a2-3350-5df6-a238-3340a03e8b3e
567
+ //# debugId=ba92dc8c-6ba8-5d95-a027-50c47894fcc3
@@ -1 +1 @@
1
- {"version":3,"file":"inference.js","sources":["utils/inference.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Inference util – OpenAI client, inference() for structured output, sendAIMessage for chat.\n */\nimport OpenAI from 'openai';\nimport type { ResponseInput } from \"openai/resources/responses/responses.js\";\nimport { logger } from './logger.js';\nimport { prisma } from '../lib/prisma.js';\nimport { chatChannel, pusher } from '../lib/pusher.js';\nimport { ensureAIUserExists, getAIUserId } from './aiUser.js';\nimport { env } from '../lib/config/env.js';\nimport { JobStatus, Prisma } from '@prisma/client';\nimport { ZodSchema } from 'zod';\nimport { zodTextFormat } from 'openai/helpers/zod';\n\nexport const inferenceClient = new OpenAI({\n apiKey: env.INFERENCE_API_KEY,\n baseURL: env.INFERENCE_API_BASE_URL,\n});\n\nexport const openAIClient = new OpenAI();\n\nconst DEFAULT_INFERENCE_MODEL = 'gpt-5-nano';\n\ntype InferenceMessage = {\n role: 'user' | 'assistant' | 'system';\n content: string;\n};\n\n/**\n * Attribution context for AI usage logging. `schoolId` is resolved from\n * `classId` at log time when not supplied by the caller.\n */\nexport interface AiUsageAttribution {\n userId?: string | null;\n schoolId?: string | null;\n classId?: string | null;\n}\n\nexport interface InferenceOptions {\n reason?: string;\n metadata?: Prisma.InputJsonValue;\n model?: string;\n temperature?: number;\n maxTokens?: number;\n attribution?: AiUsageAttribution;\n}\n\ninterface InferenceUsage {\n promptTokens?: number;\n completionTokens?: number;\n totalTokens?: number;\n}\n\ninterface InferenceAuditLog {\n model: string;\n operation: 'chat.completions' | 'responses.parse' | 'stream.text';\n success: boolean;\n estimatedInputTokens: number;\n reason: string;\n metadata?: Prisma.InputJsonValue;\n usage?: InferenceUsage;\n error?: unknown;\n attribution?: AiUsageAttribution;\n}\n\n// Types for lab chat context\nexport interface LabChatContext {\n subject: string;\n topic: string;\n difficulty: 'beginner' | 'intermediate' | 'advanced';\n objectives: string[];\n resources?: string[];\n persona: string;\n constraints: string[];\n examples?: any[];\n metadata?: Record<string, any>;\n}\n\nexport interface InferenceResponse {\n content: string;\n model: string;\n tokensUsed: number;\n finishReason: string;\n}\n\nfunction normalizeInferenceInput(\n content: string | OpenAI.Chat.Completions.ChatCompletionMessageParam[],\n): InferenceMessage[] {\n if (typeof content === 'string') {\n return [{ role: 'user', content }];\n }\n\n return content.map((message) => ({\n role: message.role as InferenceMessage['role'],\n content: typeof message.content === 'string' ? message.content : JSON.stringify(message.content),\n }));\n}\n\nfunction getInferenceReason(options?: InferenceOptions) {\n return options?.reason?.trim() || 'unspecified';\n}\n\nfunction serializeInferenceError(error: unknown) {\n if (error instanceof Error) {\n return error.message;\n }\n\n if (typeof error === 'string') {\n return error;\n }\n\n try {\n return JSON.stringify(error);\n } catch {\n return 'Unknown inference error';\n }\n}\n\nasync function resolveAttribution(\n attribution?: AiUsageAttribution,\n): Promise<{ userId: string | null; schoolId: string | null; classId: string | null }> {\n const userId = attribution?.userId ?? null;\n const classId = attribution?.classId ?? null;\n let schoolId = attribution?.schoolId ?? null;\n\n if (!schoolId && classId) {\n const classRow = await prisma.class.findUnique({\n where: { id: classId },\n select: { schoolId: true },\n });\n schoolId = classRow?.schoolId ?? null;\n }\n\n return { userId, schoolId, classId };\n}\n\nexport async function logInferenceUsage({\n model,\n operation,\n success,\n estimatedInputTokens,\n reason,\n metadata,\n usage,\n error,\n attribution,\n}: InferenceAuditLog) {\n const context = {\n reason,\n model,\n operation,\n success,\n estimatedInputTokens,\n promptTokens: usage?.promptTokens,\n completionTokens: usage?.completionTokens,\n totalTokens: usage?.totalTokens,\n metadata,\n ...(error ? { error: serializeInferenceError(error) } : {}),\n };\n\n try {\n const resolved = await resolveAttribution(attribution);\n await prisma.aiUsageLog.create({\n data: {\n reason,\n model,\n operation,\n success,\n estimatedInputTokens,\n promptTokens: usage?.promptTokens,\n completionTokens: usage?.completionTokens,\n totalTokens: usage?.totalTokens,\n userId: resolved.userId,\n schoolId: resolved.schoolId,\n classId: resolved.classId,\n ...(metadata !== undefined ? { metadata } : {}),\n ...(error ? { error: serializeInferenceError(error) } : {}),\n },\n });\n } catch (loggingError) {\n logger.error('Failed to persist AI usage log', {\n ...context,\n loggingError: serializeInferenceError(loggingError),\n });\n return;\n }\n\n logger.info('AI usage logged', context);\n}\n\nfunction getChatCompletionUsage(completion: {\n usage?: {\n prompt_tokens?: number;\n completion_tokens?: number;\n total_tokens?: number;\n };\n}): InferenceUsage {\n return {\n promptTokens: completion.usage?.prompt_tokens,\n completionTokens: completion.usage?.completion_tokens,\n totalTokens: completion.usage?.total_tokens,\n };\n}\n\nfunction getResponseUsage(completion: {\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n total_tokens?: number;\n };\n}): InferenceUsage {\n return {\n promptTokens: completion.usage?.input_tokens,\n completionTokens: completion.usage?.output_tokens,\n totalTokens: completion.usage?.total_tokens,\n };\n}\n\n/**\n * Centralized function to send AI messages to conversations\n * Handles database storage and Pusher broadcasting\n */\nexport async function sendAIMessage(\n content: string,\n conversationId: string,\n options: {\n subject?: string;\n attachments?: {\n connect: { id: string }[];\n };\n meta?: Record<string, any>;\n customSender?: {\n displayName: string;\n profilePicture?: string | null;\n };\n } = {}\n): Promise<{\n id: string;\n content: string;\n senderId: string;\n conversationId: string;\n createdAt: Date;\n meta?: Record<string, any>;\n}> {\n await ensureAIUserExists();\n\n const aiMessage = await prisma.message.create({\n data: {\n content,\n senderId: getAIUserId(),\n conversationId,\n ...(options.attachments && {\n attachments: {\n connect: options.attachments.connect,\n },\n }),\n ...(options.meta && {\n meta: options.meta,\n }),\n },\n include: {\n attachments: true,\n },\n });\n\n logger.info('AI Message sent', {\n messageId: aiMessage.id,\n conversationId,\n contentLength: content.length,\n });\n\n const senderInfo = {\n id: getAIUserId(),\n username: 'Newton_AI',\n profile: {\n displayName: 'Newton AI',\n profilePicture: options.customSender?.profilePicture || null,\n },\n };\n\n try {\n await pusher.trigger(chatChannel(conversationId), 'new-message', {\n id: aiMessage.id,\n content: aiMessage.content,\n senderId: getAIUserId(),\n conversationId: aiMessage.conversationId,\n createdAt: aiMessage.createdAt,\n sender: senderInfo,\n mentionedUserIds: [],\n meta: aiMessage.meta,\n attachments: aiMessage.attachments.map((attachment) => ({\n id: attachment.id,\n attachmentId: attachment.id,\n name: attachment.name,\n type: attachment.type,\n size: attachment.size,\n path: attachment.path,\n })),\n });\n } catch (error) {\n logger.error('Failed to broadcast AI message:', { error, messageId: aiMessage.id });\n }\n\n return {\n id: aiMessage.id,\n content: aiMessage.content,\n senderId: getAIUserId(),\n conversationId: aiMessage.conversationId,\n createdAt: aiMessage.createdAt,\n meta: aiMessage.meta as Record<string, any>,\n };\n}\n\ninterface AIMessageSenderInfo {\n displayName?: string;\n profilePicture?: string | null;\n}\n\nfunction buildAISenderInfo(customSender?: AIMessageSenderInfo) {\n return {\n id: getAIUserId(),\n username: 'Newton_AI',\n profile: {\n displayName: customSender?.displayName ?? 'Newton AI',\n profilePicture: customSender?.profilePicture ?? null,\n },\n };\n}\n\n/**\n * Create an AI message placeholder in PENDING state and broadcast it.\n *\n * The AI message lifecycle == job lifecycle: this row is the bubble the\n * client renders for \"AI is thinking...\" and is later flipped by\n * {@link completePendingAIMessage} / {@link failPendingAIMessage}.\n */\nexport async function createPendingAIMessage(\n conversationId: string,\n options: {\n customSender?: AIMessageSenderInfo;\n } = {},\n): Promise<{\n id: string;\n conversationId: string;\n createdAt: Date;\n senderId: string;\n status: JobStatus;\n}> {\n await ensureAIUserExists();\n\n const aiMessage = await prisma.message.create({\n data: {\n content: '',\n senderId: getAIUserId(),\n conversationId,\n status: JobStatus.PENDING,\n },\n });\n\n logger.info('AI placeholder message created', {\n messageId: aiMessage.id,\n conversationId,\n });\n\n const senderInfo = buildAISenderInfo(options.customSender);\n\n try {\n await pusher.trigger(chatChannel(conversationId), 'new-message', {\n id: aiMessage.id,\n content: '',\n senderId: getAIUserId(),\n conversationId: aiMessage.conversationId,\n status: JobStatus.PENDING,\n createdAt: aiMessage.createdAt,\n sender: senderInfo,\n mentionedUserIds: [],\n meta: {},\n attachments: [],\n });\n } catch (error) {\n logger.error('Failed to broadcast pending AI message:', {\n error,\n messageId: aiMessage.id,\n });\n }\n\n return {\n id: aiMessage.id,\n conversationId: aiMessage.conversationId,\n createdAt: aiMessage.createdAt,\n senderId: aiMessage.senderId,\n status: JobStatus.PENDING,\n };\n}\n\n/**\n * Fill a PENDING AI message with its generated content and flip it to\n * COMPLETED. Broadcasts a `message-updated` event so clients that already\n * rendered the placeholder can patch it in place.\n */\nexport async function completePendingAIMessage(\n messageId: string,\n content: string,\n options: {\n attachments?: { connect: { id: string }[] };\n meta?: Record<string, any>;\n customSender?: AIMessageSenderInfo;\n } = {},\n): Promise<{\n id: string;\n content: string;\n conversationId: string;\n createdAt: Date;\n status: JobStatus;\n}> {\n const updated = await prisma.message.update({\n where: { id: messageId },\n data: {\n content,\n status: JobStatus.COMPLETED,\n ...(options.attachments && {\n attachments: {\n connect: options.attachments.connect,\n },\n }),\n ...(options.meta !== undefined && {\n meta: options.meta as Prisma.InputJsonValue,\n }),\n },\n include: {\n attachments: true,\n },\n });\n\n logger.info('AI message completed', {\n messageId: updated.id,\n conversationId: updated.conversationId,\n contentLength: content.length,\n });\n\n const senderInfo = buildAISenderInfo(options.customSender);\n\n try {\n await pusher.trigger(chatChannel(updated.conversationId), 'message-updated', {\n id: updated.id,\n content: updated.content,\n senderId: updated.senderId,\n conversationId: updated.conversationId,\n status: updated.status,\n createdAt: updated.createdAt,\n sender: senderInfo,\n mentionedUserIds: [],\n meta: updated.meta ?? {},\n attachments: updated.attachments.map((attachment) => ({\n id: attachment.id,\n attachmentId: attachment.id,\n name: attachment.name,\n type: attachment.type,\n size: attachment.size,\n path: attachment.path,\n })),\n });\n } catch (error) {\n logger.error('Failed to broadcast completed AI message:', {\n error,\n messageId,\n });\n }\n\n return {\n id: updated.id,\n content: updated.content,\n conversationId: updated.conversationId,\n createdAt: updated.createdAt,\n status: (updated.status ?? JobStatus.COMPLETED) as JobStatus,\n };\n}\n\n/**\n * Flip a PENDING AI message to FAILED and broadcast the status change.\n * Does NOT throw — failure paths in the pipelines call this in catch blocks\n * and we do not want broadcast/DB errors to mask the original error.\n */\nexport async function failPendingAIMessage(\n messageId: string,\n options: { reason?: string } = {},\n): Promise<void> {\n try {\n const updated = await prisma.message.update({\n where: { id: messageId },\n data: { status: JobStatus.FAILED },\n select: { id: true, conversationId: true, status: true },\n });\n\n logger.info('AI message marked as failed', {\n messageId: updated.id,\n conversationId: updated.conversationId,\n reason: options.reason,\n });\n\n try {\n await pusher.trigger(chatChannel(updated.conversationId), 'message-updated', {\n id: updated.id,\n conversationId: updated.conversationId,\n status: updated.status,\n });\n } catch (broadcastError) {\n logger.error('Failed to broadcast failed AI message:', {\n error: broadcastError,\n messageId,\n });\n }\n } catch (error) {\n logger.error('Failed to mark AI message as failed:', {\n error,\n messageId,\n reason: options.reason,\n });\n }\n}\n\n/** Responses API user parts use `type: \"input_*\"`; chat completions use `text` / `image_url` / etc. */\nfunction isResponseInputWithInputParts(\n content: OpenAI.Chat.Completions.ChatCompletionMessageParam[] | ResponseInput\n): content is ResponseInput {\n if (!Array.isArray(content)) return false;\n for (const msg of content) {\n if (!msg || typeof msg !== \"object\" || !(\"content\" in msg)) continue;\n const parts = (msg as { content?: unknown }).content;\n if (!Array.isArray(parts)) continue;\n for (const part of parts) {\n if (\n part &&\n typeof part === \"object\" &&\n \"type\" in part &&\n typeof (part as { type: string }).type === \"string\" &&\n (part as { type: string }).type.startsWith(\"input_\")\n ) {\n return true;\n }\n }\n }\n return false;\n}\n\nfunction buildResponsesParseInput(\n content: string | OpenAI.Chat.Completions.ChatCompletionMessageParam[] | ResponseInput\n): ResponseInput {\n if (typeof content === \"string\") {\n return [{ role: \"user\", content: [{ type: \"input_text\", text: content }] }];\n }\n if (isResponseInputWithInputParts(content)) {\n return content;\n }\n return content as unknown as ResponseInput;\n}\n\nexport async function inference<T>(\n content:\n | string\n | OpenAI.Chat.Completions.ChatCompletionMessageParam[]\n | ResponseInput,\n format?: ZodSchema,\n options?: InferenceOptions,\n): Promise<T> {\n const reason = getInferenceReason(options);\n const model = options?.model ?? DEFAULT_INFERENCE_MODEL;\n const estimatedInputTokens =\n typeof content === 'string'\n ? estimateTokenCount(content)\n : isResponseInputWithInputParts(content)\n ? estimateTokenCount(\n content\n .flatMap((item) =>\n typeof (item as any)?.content === 'string'\n ? [(item as any).content]\n : Array.isArray((item as any)?.content)\n ? (item as any).content\n .filter((p: any) => p?.type === 'input_text')\n .map((p: any) => p?.text ?? '')\n : [],\n )\n .join('\\n'),\n )\n : (content as OpenAI.Chat.Completions.ChatCompletionMessageParam[]).reduce(\n (total, message) =>\n total +\n estimateTokenCount(\n typeof message.content === 'string' ? message.content : '',\n ),\n 0,\n );\n const operation = format ? 'responses.parse' : 'chat.completions';\n\n try {\n if (!format) {\n if (typeof content !== 'string' && isResponseInputWithInputParts(content)) {\n throw new Error(\n 'normalizeInferenceInput cannot handle ResponseInput content with input_* parts when format is undefined; pass a format to use responses.parse.',\n );\n }\n\n const messages = normalizeInferenceInput(\n content as string | OpenAI.Chat.Completions.ChatCompletionMessageParam[],\n );\n const completion = await openAIClient.chat.completions.create({\n model,\n messages,\n ...(options?.temperature !== undefined\n ? { temperature: options.temperature }\n : {}),\n ...(options?.maxTokens !== undefined\n ? { max_tokens: options.maxTokens }\n : {}),\n });\n\n await logInferenceUsage({\n model,\n operation,\n success: true,\n estimatedInputTokens,\n reason,\n metadata: options?.metadata,\n usage: getChatCompletionUsage(completion),\n attribution: options?.attribution,\n });\n\n return completion.choices[0]?.message?.content as T;\n }\n\n const input = buildResponsesParseInput(content);\n const completion = await openAIClient.responses.parse({\n model,\n input,\n text: {\n format: zodTextFormat(format, 'newton_response_format'),\n },\n });\n\n if (!completion) {\n throw new Error('No response generated from inference API');\n }\n\n await logInferenceUsage({\n model,\n operation,\n success: true,\n estimatedInputTokens,\n reason,\n metadata: options?.metadata,\n usage: getResponseUsage(completion),\n attribution: options?.attribution,\n });\n\n return completion.output_parsed as T;\n } catch (error) {\n await logInferenceUsage({\n model,\n operation,\n success: false,\n estimatedInputTokens,\n reason,\n metadata: options?.metadata,\n error,\n attribution: options?.attribution,\n });\n\n logger.error('Failed to generate inference response', {\n error,\n reason,\n model,\n operation,\n metadata: options?.metadata,\n });\n throw error;\n }\n}\n\n/**\n * Get available inference models (for admin/config purposes)\n */\nexport async function getAvailableModels(): Promise<string[]> {\n try {\n const models = await inferenceClient.models.list();\n return models.data\n .filter(model => model.id.includes('command'))\n .map(model => model.id)\n .sort();\n } catch (error) {\n logger.error('Failed to fetch inference models', { error });\n return ['command-r-plus', 'command-r', 'command-light'];\n }\n}\n\n/**\n * Estimate token count for a message (rough approximation)\n */\nexport function estimateTokenCount(text: string): number {\n return Math.ceil(text.length / 4);\n}\n"],"names":[],"mappings":"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","debug_id":"9b4ef7a2-3350-5df6-a238-3340a03e8b3e"}
1
+ {"version":3,"file":"inference.js","sources":["utils/inference.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Inference util – OpenAI client, inference() for structured output, sendAIMessage for chat.\n */\nimport OpenAI from 'openai';\nimport type { ResponseInput } from \"openai/resources/responses/responses.js\";\nimport { logger } from './logger.js';\nimport { prisma } from '../lib/prisma.js';\nimport { chatChannel, pusher } from '../lib/pusher.js';\nimport { ensureAIUserExists, getAIUserId } from './aiUser.js';\nimport { env } from '../lib/config/env.js';\nimport { JobStatus, Prisma } from '@prisma/client';\nimport { ZodSchema } from 'zod';\nimport { zodTextFormat } from 'openai/helpers/zod';\n\nexport const inferenceClient = new OpenAI({\n apiKey: env.INFERENCE_API_KEY,\n baseURL: env.INFERENCE_API_BASE_URL,\n});\n\nexport const openAIClient = new OpenAI();\n\nconst DEFAULT_INFERENCE_MODEL = 'gpt-5-nano';\n\ntype InferenceMessage = {\n role: 'user' | 'assistant' | 'system';\n content: string;\n};\n\n/**\n * Attribution context for AI usage logging. `schoolId` is resolved from\n * `classId` at log time when not supplied by the caller.\n */\nexport interface AiUsageAttribution {\n userId?: string | null;\n schoolId?: string | null;\n classId?: string | null;\n}\n\nexport interface InferenceOptions {\n reason?: string;\n metadata?: Prisma.InputJsonValue;\n model?: string;\n temperature?: number;\n maxTokens?: number;\n attribution?: AiUsageAttribution;\n}\n\ninterface InferenceUsage {\n promptTokens?: number;\n completionTokens?: number;\n totalTokens?: number;\n}\n\ninterface InferenceAuditLog {\n model: string;\n operation: 'chat.completions' | 'responses.parse' | 'stream.text';\n success: boolean;\n estimatedInputTokens: number;\n reason: string;\n metadata?: Prisma.InputJsonValue;\n usage?: InferenceUsage;\n error?: unknown;\n attribution?: AiUsageAttribution;\n}\n\n// Types for lab chat context\nexport interface LabChatContext {\n subject: string;\n topic: string;\n difficulty: 'beginner' | 'intermediate' | 'advanced';\n objectives: string[];\n resources?: string[];\n persona: string;\n constraints: string[];\n examples?: any[];\n metadata?: Record<string, any>;\n}\n\nexport interface InferenceResponse {\n content: string;\n model: string;\n tokensUsed: number;\n finishReason: string;\n}\n\nfunction normalizeInferenceInput(\n content: string | OpenAI.Chat.Completions.ChatCompletionMessageParam[],\n): InferenceMessage[] {\n if (typeof content === 'string') {\n return [{ role: 'user', content }];\n }\n\n return content.map((message) => ({\n role: message.role as InferenceMessage['role'],\n content: typeof message.content === 'string' ? message.content : JSON.stringify(message.content),\n }));\n}\n\nfunction getInferenceReason(options?: InferenceOptions) {\n return options?.reason?.trim() || 'unspecified';\n}\n\nfunction serializeInferenceError(error: unknown) {\n if (error instanceof Error) {\n return error.message;\n }\n\n if (typeof error === 'string') {\n return error;\n }\n\n try {\n return JSON.stringify(error);\n } catch {\n return 'Unknown inference error';\n }\n}\n\nasync function resolveAttribution(\n attribution?: AiUsageAttribution,\n): Promise<{ userId: string | null; schoolId: string | null; classId: string | null }> {\n const userId = attribution?.userId ?? null;\n const classId = attribution?.classId ?? null;\n let schoolId = attribution?.schoolId ?? null;\n\n if (!schoolId && classId) {\n const classRow = await prisma.class.findUnique({\n where: { id: classId },\n select: { schoolId: true },\n });\n schoolId = classRow?.schoolId ?? null;\n }\n\n return { userId, schoolId, classId };\n}\n\nexport async function logInferenceUsage({\n model,\n operation,\n success,\n estimatedInputTokens,\n reason,\n metadata,\n usage,\n error,\n attribution,\n}: InferenceAuditLog) {\n const context = {\n reason,\n model,\n operation,\n success,\n estimatedInputTokens,\n promptTokens: usage?.promptTokens,\n completionTokens: usage?.completionTokens,\n totalTokens: usage?.totalTokens,\n metadata,\n ...(error ? { error: serializeInferenceError(error) } : {}),\n };\n\n try {\n const resolved = await resolveAttribution(attribution);\n await prisma.aiUsageLog.create({\n data: {\n reason,\n model,\n operation,\n success,\n estimatedInputTokens,\n promptTokens: usage?.promptTokens,\n completionTokens: usage?.completionTokens,\n totalTokens: usage?.totalTokens,\n userId: resolved.userId,\n schoolId: resolved.schoolId,\n classId: resolved.classId,\n ...(metadata !== undefined ? { metadata } : {}),\n ...(error ? { error: serializeInferenceError(error) } : {}),\n },\n });\n } catch (loggingError) {\n logger.error('Failed to persist AI usage log', {\n ...context,\n loggingError: serializeInferenceError(loggingError),\n });\n return;\n }\n\n logger.info('AI usage logged', context);\n}\n\nfunction getChatCompletionUsage(completion: {\n usage?: {\n prompt_tokens?: number;\n completion_tokens?: number;\n total_tokens?: number;\n };\n}): InferenceUsage {\n return {\n promptTokens: completion.usage?.prompt_tokens,\n completionTokens: completion.usage?.completion_tokens,\n totalTokens: completion.usage?.total_tokens,\n };\n}\n\nfunction getResponseUsage(completion: {\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n total_tokens?: number;\n };\n}): InferenceUsage {\n return {\n promptTokens: completion.usage?.input_tokens,\n completionTokens: completion.usage?.output_tokens,\n totalTokens: completion.usage?.total_tokens,\n };\n}\n\n/**\n * Centralized function to send AI messages to conversations\n * Handles database storage and Pusher broadcasting\n */\nexport async function sendAIMessage(\n content: string,\n conversationId: string,\n options: {\n subject?: string;\n attachments?: {\n connect: { id: string }[];\n };\n meta?: Record<string, any>;\n customSender?: {\n displayName: string;\n profilePicture?: string | null;\n };\n } = {}\n): Promise<{\n id: string;\n content: string;\n senderId: string;\n conversationId: string;\n createdAt: Date;\n meta?: Record<string, any>;\n}> {\n await ensureAIUserExists();\n\n const aiMessage = await prisma.message.create({\n data: {\n content,\n senderId: getAIUserId(),\n conversationId,\n ...(options.attachments && {\n attachments: {\n connect: options.attachments.connect,\n },\n }),\n ...(options.meta && {\n meta: options.meta,\n }),\n },\n include: {\n attachments: true,\n },\n });\n\n logger.info('AI Message sent', {\n messageId: aiMessage.id,\n conversationId,\n contentLength: content.length,\n });\n\n const senderInfo = {\n id: getAIUserId(),\n username: 'Newton_AI',\n profile: {\n displayName: 'Newton AI',\n profilePicture: options.customSender?.profilePicture || null,\n },\n };\n\n try {\n await pusher.trigger(chatChannel(conversationId), 'new-message', {\n id: aiMessage.id,\n content: aiMessage.content,\n senderId: getAIUserId(),\n conversationId: aiMessage.conversationId,\n createdAt: aiMessage.createdAt,\n sender: senderInfo,\n mentionedUserIds: [],\n meta: aiMessage.meta,\n attachments: aiMessage.attachments.map((attachment) => ({\n id: attachment.id,\n attachmentId: attachment.id,\n name: attachment.name,\n type: attachment.type,\n size: attachment.size,\n path: attachment.path,\n })),\n });\n } catch (error) {\n logger.error('Failed to broadcast AI message:', { error, messageId: aiMessage.id });\n }\n\n return {\n id: aiMessage.id,\n content: aiMessage.content,\n senderId: getAIUserId(),\n conversationId: aiMessage.conversationId,\n createdAt: aiMessage.createdAt,\n meta: aiMessage.meta as Record<string, any>,\n };\n}\n\ninterface AIMessageSenderInfo {\n displayName?: string;\n profilePicture?: string | null;\n}\n\nfunction buildAISenderInfo(customSender?: AIMessageSenderInfo) {\n return {\n id: getAIUserId(),\n username: 'Newton_AI',\n profile: {\n displayName: customSender?.displayName ?? 'Newton AI',\n profilePicture: customSender?.profilePicture ?? null,\n },\n };\n}\n\n/**\n * Create an AI message placeholder in PENDING state and broadcast it.\n *\n * The AI message lifecycle == job lifecycle: this row is the bubble the\n * client renders for \"AI is thinking...\" and is later flipped by\n * {@link completePendingAIMessage} / {@link failPendingAIMessage}.\n */\nexport async function createPendingAIMessage(\n conversationId: string,\n options: {\n customSender?: AIMessageSenderInfo;\n } = {},\n): Promise<{\n id: string;\n conversationId: string;\n createdAt: Date;\n senderId: string;\n status: JobStatus;\n}> {\n await ensureAIUserExists();\n\n const aiMessage = await prisma.message.create({\n data: {\n content: '',\n senderId: getAIUserId(),\n conversationId,\n status: JobStatus.PENDING,\n },\n });\n\n logger.info('AI placeholder message created', {\n messageId: aiMessage.id,\n conversationId,\n });\n\n const senderInfo = buildAISenderInfo(options.customSender);\n\n try {\n await pusher.trigger(chatChannel(conversationId), 'new-message', {\n id: aiMessage.id,\n content: '',\n senderId: getAIUserId(),\n conversationId: aiMessage.conversationId,\n status: JobStatus.PENDING,\n createdAt: aiMessage.createdAt,\n sender: senderInfo,\n mentionedUserIds: [],\n meta: {},\n attachments: [],\n });\n } catch (error) {\n logger.error('Failed to broadcast pending AI message:', {\n error,\n messageId: aiMessage.id,\n });\n }\n\n return {\n id: aiMessage.id,\n conversationId: aiMessage.conversationId,\n createdAt: aiMessage.createdAt,\n senderId: aiMessage.senderId,\n status: JobStatus.PENDING,\n };\n}\n\n/**\n * Fill a PENDING AI message with its generated content and flip it to\n * COMPLETED. Broadcasts a `message-updated` event so clients that already\n * rendered the placeholder can patch it in place.\n */\nexport async function completePendingAIMessage(\n messageId: string,\n content: string,\n options: {\n attachments?: { connect: { id: string }[] };\n meta?: Record<string, any>;\n customSender?: AIMessageSenderInfo;\n } = {},\n): Promise<{\n id: string;\n content: string;\n conversationId: string;\n createdAt: Date;\n status: JobStatus;\n}> {\n const updated = await prisma.message.update({\n where: { id: messageId },\n data: {\n content,\n status: JobStatus.COMPLETED,\n ...(options.attachments && {\n attachments: {\n connect: options.attachments.connect,\n },\n }),\n ...(options.meta !== undefined && {\n meta: options.meta as Prisma.InputJsonValue,\n }),\n },\n include: {\n attachments: true,\n },\n });\n\n logger.info('AI message completed', {\n messageId: updated.id,\n conversationId: updated.conversationId,\n contentLength: content.length,\n });\n\n const senderInfo = buildAISenderInfo(options.customSender);\n\n try {\n await pusher.trigger(chatChannel(updated.conversationId), 'message-updated', {\n id: updated.id,\n content: updated.content,\n senderId: updated.senderId,\n conversationId: updated.conversationId,\n status: updated.status,\n createdAt: updated.createdAt,\n sender: senderInfo,\n mentionedUserIds: [],\n meta: updated.meta ?? {},\n attachments: updated.attachments.map((attachment) => ({\n id: attachment.id,\n attachmentId: attachment.id,\n name: attachment.name,\n type: attachment.type,\n size: attachment.size,\n path: attachment.path,\n })),\n });\n } catch (error) {\n logger.error('Failed to broadcast completed AI message:', {\n error,\n messageId,\n });\n }\n\n return {\n id: updated.id,\n content: updated.content,\n conversationId: updated.conversationId,\n createdAt: updated.createdAt,\n status: (updated.status ?? JobStatus.COMPLETED) as JobStatus,\n };\n}\n\n/**\n * Persist the partial output of a cancelled generation and flip the AI\n * message to CANCELLED. Whatever text/tool parts streamed before the stop\n * are kept on the row (content + meta) so they survive reloads. Broadcasts\n * `message-updated` so clients patch the bubble in place.\n */\nexport async function cancelPendingAIMessage(\n messageId: string,\n content: string,\n options: {\n meta?: Record<string, any>;\n customSender?: AIMessageSenderInfo;\n } = {},\n): Promise<void> {\n try {\n const updated = await prisma.message.update({\n where: { id: messageId },\n data: {\n content,\n status: JobStatus.CANCELLED,\n ...(options.meta !== undefined && {\n meta: options.meta as Prisma.InputJsonValue,\n }),\n },\n include: {\n attachments: true,\n },\n });\n\n logger.info('AI message cancelled', {\n messageId: updated.id,\n conversationId: updated.conversationId,\n contentLength: content.length,\n });\n\n const senderInfo = buildAISenderInfo(options.customSender);\n\n try {\n await pusher.trigger(chatChannel(updated.conversationId), 'message-updated', {\n id: updated.id,\n content: updated.content,\n senderId: updated.senderId,\n conversationId: updated.conversationId,\n status: updated.status,\n createdAt: updated.createdAt,\n sender: senderInfo,\n mentionedUserIds: [],\n meta: updated.meta ?? {},\n attachments: updated.attachments.map((attachment) => ({\n id: attachment.id,\n attachmentId: attachment.id,\n name: attachment.name,\n type: attachment.type,\n size: attachment.size,\n path: attachment.path,\n })),\n });\n } catch (broadcastError) {\n logger.error('Failed to broadcast cancelled AI message:', {\n error: broadcastError,\n messageId,\n });\n }\n } catch (error) {\n logger.error('Failed to mark AI message as cancelled:', {\n error,\n messageId,\n });\n }\n}\n\n/**\n * Flip a PENDING AI message to FAILED and broadcast the status change.\n * Does NOT throw — failure paths in the pipelines call this in catch blocks\n * and we do not want broadcast/DB errors to mask the original error.\n */\nexport async function failPendingAIMessage(\n messageId: string,\n options: { reason?: string } = {},\n): Promise<void> {\n try {\n const current = await prisma.message.findUnique({\n where: { id: messageId },\n select: { status: true },\n });\n // A message the user already cancelled must stay CANCELLED — late\n // failures from the aborted pipeline are a consequence of the cancel.\n if (current?.status === JobStatus.CANCELLED) {\n logger.info('Skipping FAILED flip; AI message already cancelled', {\n messageId,\n reason: options.reason,\n });\n return;\n }\n\n const updated = await prisma.message.update({\n where: { id: messageId },\n data: { status: JobStatus.FAILED },\n select: { id: true, conversationId: true, status: true },\n });\n\n logger.info('AI message marked as failed', {\n messageId: updated.id,\n conversationId: updated.conversationId,\n reason: options.reason,\n });\n\n try {\n await pusher.trigger(chatChannel(updated.conversationId), 'message-updated', {\n id: updated.id,\n conversationId: updated.conversationId,\n status: updated.status,\n });\n } catch (broadcastError) {\n logger.error('Failed to broadcast failed AI message:', {\n error: broadcastError,\n messageId,\n });\n }\n } catch (error) {\n logger.error('Failed to mark AI message as failed:', {\n error,\n messageId,\n reason: options.reason,\n });\n }\n}\n\n/** Responses API user parts use `type: \"input_*\"`; chat completions use `text` / `image_url` / etc. */\nfunction isResponseInputWithInputParts(\n content: OpenAI.Chat.Completions.ChatCompletionMessageParam[] | ResponseInput\n): content is ResponseInput {\n if (!Array.isArray(content)) return false;\n for (const msg of content) {\n if (!msg || typeof msg !== \"object\" || !(\"content\" in msg)) continue;\n const parts = (msg as { content?: unknown }).content;\n if (!Array.isArray(parts)) continue;\n for (const part of parts) {\n if (\n part &&\n typeof part === \"object\" &&\n \"type\" in part &&\n typeof (part as { type: string }).type === \"string\" &&\n (part as { type: string }).type.startsWith(\"input_\")\n ) {\n return true;\n }\n }\n }\n return false;\n}\n\nfunction buildResponsesParseInput(\n content: string | OpenAI.Chat.Completions.ChatCompletionMessageParam[] | ResponseInput\n): ResponseInput {\n if (typeof content === \"string\") {\n return [{ role: \"user\", content: [{ type: \"input_text\", text: content }] }];\n }\n if (isResponseInputWithInputParts(content)) {\n return content;\n }\n return content as unknown as ResponseInput;\n}\n\nexport async function inference<T>(\n content:\n | string\n | OpenAI.Chat.Completions.ChatCompletionMessageParam[]\n | ResponseInput,\n format?: ZodSchema,\n options?: InferenceOptions,\n): Promise<T> {\n const reason = getInferenceReason(options);\n const model = options?.model ?? DEFAULT_INFERENCE_MODEL;\n const estimatedInputTokens =\n typeof content === 'string'\n ? estimateTokenCount(content)\n : isResponseInputWithInputParts(content)\n ? estimateTokenCount(\n content\n .flatMap((item) =>\n typeof (item as any)?.content === 'string'\n ? [(item as any).content]\n : Array.isArray((item as any)?.content)\n ? (item as any).content\n .filter((p: any) => p?.type === 'input_text')\n .map((p: any) => p?.text ?? '')\n : [],\n )\n .join('\\n'),\n )\n : (content as OpenAI.Chat.Completions.ChatCompletionMessageParam[]).reduce(\n (total, message) =>\n total +\n estimateTokenCount(\n typeof message.content === 'string' ? message.content : '',\n ),\n 0,\n );\n const operation = format ? 'responses.parse' : 'chat.completions';\n\n try {\n if (!format) {\n if (typeof content !== 'string' && isResponseInputWithInputParts(content)) {\n throw new Error(\n 'normalizeInferenceInput cannot handle ResponseInput content with input_* parts when format is undefined; pass a format to use responses.parse.',\n );\n }\n\n const messages = normalizeInferenceInput(\n content as string | OpenAI.Chat.Completions.ChatCompletionMessageParam[],\n );\n const completion = await openAIClient.chat.completions.create({\n model,\n messages,\n ...(options?.temperature !== undefined\n ? { temperature: options.temperature }\n : {}),\n ...(options?.maxTokens !== undefined\n ? { max_tokens: options.maxTokens }\n : {}),\n });\n\n await logInferenceUsage({\n model,\n operation,\n success: true,\n estimatedInputTokens,\n reason,\n metadata: options?.metadata,\n usage: getChatCompletionUsage(completion),\n attribution: options?.attribution,\n });\n\n return completion.choices[0]?.message?.content as T;\n }\n\n const input = buildResponsesParseInput(content);\n const completion = await openAIClient.responses.parse({\n model,\n input,\n text: {\n format: zodTextFormat(format, 'newton_response_format'),\n },\n });\n\n if (!completion) {\n throw new Error('No response generated from inference API');\n }\n\n await logInferenceUsage({\n model,\n operation,\n success: true,\n estimatedInputTokens,\n reason,\n metadata: options?.metadata,\n usage: getResponseUsage(completion),\n attribution: options?.attribution,\n });\n\n return completion.output_parsed as T;\n } catch (error) {\n await logInferenceUsage({\n model,\n operation,\n success: false,\n estimatedInputTokens,\n reason,\n metadata: options?.metadata,\n error,\n attribution: options?.attribution,\n });\n\n logger.error('Failed to generate inference response', {\n error,\n reason,\n model,\n operation,\n metadata: options?.metadata,\n });\n throw error;\n }\n}\n\n/**\n * Get available inference models (for admin/config purposes)\n */\nexport async function getAvailableModels(): Promise<string[]> {\n try {\n const models = await inferenceClient.models.list();\n return models.data\n .filter(model => model.id.includes('command'))\n .map(model => model.id)\n .sort();\n } catch (error) {\n logger.error('Failed to fetch inference models', { error });\n return ['command-r-plus', 'command-r', 'command-light'];\n }\n}\n\n/**\n * Estimate token count for a message (rough approximation)\n */\nexport function estimateTokenCount(text: string): number {\n return Math.ceil(text.length / 4);\n}\n"],"names":[],"mappings":"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","debug_id":"ba92dc8c-6ba8-5d95-a027-50c47894fcc3"}