Files
openmaic/OpenMAIC/app/api/runtime/v1/courses/jobs/[jobId]/route.ts
T

62 lines
2.6 KiB
TypeScript

import type { NextRequest } from 'next/server';
import { readCourseRecordReconciled } from '@/lib/course-framework/store';
import { authorizeLearningRuntime, runtimeUnauthorized } from '@/lib/makelore-runtime/auth';
import { LEARNING_GENERATION_CONTRACT_VERSION } from '@/lib/makelore-runtime/generation-request';
import { isValidClassroomJobId, readClassroomGenerationJob } from '@/lib/server/classroom-job-store';
function largeCourseProgress(status: string, succeeded: number, total: number): number {
if (status === 'completed') return 100;
if (status === 'framework_ready') return 25;
if (status === 'framework_generating') return 10;
if (status === 'queued') return 0;
if (total > 0) return Math.min(99, Math.round(25 + (succeeded / total) * 75));
return 0;
}
export async function GET(request: NextRequest, context: { params: Promise<{ jobId: string }> }) {
if (!authorizeLearningRuntime(request)) return runtimeUnauthorized();
const { jobId } = await context.params;
const owner = request.headers.get('x-owner-user-id')?.trim();
if (!owner || !isValidClassroomJobId(jobId)) return Response.json({ error: 'invalid_request' }, { status: 400 });
const job = await readClassroomGenerationJob(jobId);
if (job) {
if (job.ownerPrincipalId !== owner) return Response.json({ error: 'job_not_found' }, { status: 404 });
return Response.json({
contractVersion: LEARNING_GENERATION_CONTRACT_VERSION,
jobId,
mode: 'single',
status: job.status,
step: job.step,
progress: job.progress,
message: job.message,
scenesGenerated: job.scenesGenerated,
totalScenes: job.totalScenes,
courseId: job.result?.classroomId,
error: job.error,
done: ['succeeded', 'failed', 'cancelled'].includes(job.status),
});
}
const course = await readCourseRecordReconciled(jobId);
if (!course || course.ownerPrincipalId !== owner) {
return Response.json({ error: 'job_not_found' }, { status: 404 });
}
const succeeded = course.modules.filter((module) => module.status === 'succeeded').length;
const total = course.modules.length;
return Response.json({
contractVersion: LEARNING_GENERATION_CONTRACT_VERSION,
jobId,
mode: 'large',
status: course.status,
step: course.status,
progress: largeCourseProgress(course.status, succeeded, total),
message:
course.status === 'framework_ready'
? 'Course framework is ready for operations review'
: undefined,
courseId: course.id,
error: course.error,
done: ['completed', 'failed', 'cancelled'].includes(course.status),
});
}