feat: integrate learning module
This commit is contained in:
168
shared/learning.ts
Normal file
168
shared/learning.ts
Normal file
@@ -0,0 +1,168 @@
|
||||
/** Stable boundary between Makelore, downloaded course packages and Works Square. */
|
||||
|
||||
export const LEARNING_API_PATH = '/api/works/learning';
|
||||
|
||||
export const LEARNING_GENERATION_CONTRACT_VERSION = 2;
|
||||
export const LEARNING_MATERIAL_MAX_FILES = 5;
|
||||
export const LEARNING_MATERIAL_MAX_FILE_BYTES = 50 * 1024 * 1024;
|
||||
export const LEARNING_MATERIAL_MAX_TOTAL_BYTES = 150 * 1024 * 1024;
|
||||
|
||||
export type LearningGenerationOptions = {
|
||||
requirement: string;
|
||||
enableWebSearch: boolean;
|
||||
enableImageGeneration: boolean;
|
||||
enableVideoGeneration: boolean;
|
||||
enableTTS: boolean;
|
||||
interactiveMode: boolean;
|
||||
taskEngineMode: boolean;
|
||||
};
|
||||
|
||||
export type LearningGenerationMaterialRef = {
|
||||
id: string;
|
||||
name: string;
|
||||
mimeType: string;
|
||||
size: number;
|
||||
lastModified: number;
|
||||
order: number;
|
||||
};
|
||||
|
||||
/** IPC-only upload shape. File bytes are never persisted in Renderer state. */
|
||||
export type LearningGenerationMaterialUpload = LearningGenerationMaterialRef & {
|
||||
bytes: Uint8Array;
|
||||
};
|
||||
|
||||
export type LearningGenerationUploadRequest = {
|
||||
options: LearningGenerationOptions;
|
||||
materials: LearningGenerationMaterialUpload[];
|
||||
};
|
||||
|
||||
export type LearningRuntimeCapability =
|
||||
| 'quiz-grade'
|
||||
| 'pbl/v2/task/update'
|
||||
| 'pbl/v2/open-task'
|
||||
| 'pbl/v2/simulator'
|
||||
| 'pbl/v2/instructor'
|
||||
| 'pbl/v2/evaluate';
|
||||
|
||||
export type LearningRuntimeBridgeRequest = {
|
||||
requestId: string;
|
||||
courseId: string;
|
||||
contentHash: string;
|
||||
capability: LearningRuntimeCapability;
|
||||
method: 'POST';
|
||||
context: {
|
||||
moduleId: string | null;
|
||||
moduleContentHash: string;
|
||||
anchor: {
|
||||
sceneId: string;
|
||||
sceneOrder?: number;
|
||||
};
|
||||
};
|
||||
body: unknown;
|
||||
};
|
||||
|
||||
export type LearningRuntimeBridgeEvent =
|
||||
| { requestId: string; type: 'start'; status: number; contentType: string }
|
||||
| { requestId: string; type: 'chunk'; chunk: Uint8Array }
|
||||
| { requestId: string; type: 'end' }
|
||||
| { requestId: string; type: 'error'; code: string; message: string };
|
||||
|
||||
export type LearningSceneKind = 'slide' | 'interactive' | 'quiz' | 'pbl';
|
||||
export type LearningCourseStatus = 'generating' | 'ready' | 'published' | 'failed' | 'archived';
|
||||
|
||||
export type LearningSingleCourseCapabilities = {
|
||||
modular?: false;
|
||||
sceneKinds: LearningSceneKind[];
|
||||
hasAudio: boolean;
|
||||
hasWhiteboard: boolean;
|
||||
hasAgent: boolean;
|
||||
};
|
||||
|
||||
export type LearningLargeCourseCapabilities = {
|
||||
modular: true;
|
||||
orderedModules: true;
|
||||
productionStagePerModule: true;
|
||||
};
|
||||
|
||||
export type LearningCourseCapabilities = LearningSingleCourseCapabilities | LearningLargeCourseCapabilities;
|
||||
|
||||
export type LearningCourseModule = {
|
||||
moduleId: string;
|
||||
title: string;
|
||||
summary: string | null;
|
||||
sceneCount: number;
|
||||
contentHash: string;
|
||||
};
|
||||
|
||||
export type LearningCourse = {
|
||||
id: string;
|
||||
origin: 'user_single' | 'ops_large';
|
||||
status: LearningCourseStatus;
|
||||
title: string;
|
||||
summary: string | null;
|
||||
language: string | null;
|
||||
contentHash: string;
|
||||
archiveSha256: string;
|
||||
archiveBytes: number;
|
||||
formatVersion: number;
|
||||
minPlayerVersion: string;
|
||||
sceneCount: number;
|
||||
/** Ordered learning units inside one product-level course. */
|
||||
modules?: LearningCourseModule[];
|
||||
capabilities: LearningCourseCapabilities;
|
||||
createdAt: string;
|
||||
publishedAt: string | null;
|
||||
};
|
||||
|
||||
export type LearningProgress = {
|
||||
courseId: string;
|
||||
/** Aggregate course hash used by Works ownership and entitlement checks. */
|
||||
contentHash: string;
|
||||
moduleId?: string | null;
|
||||
moduleContentHash?: string | null;
|
||||
sceneOrder: number;
|
||||
actionIndex: number | null;
|
||||
positionMs: number | null;
|
||||
completed: boolean;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
export type LearningProgressWrite = Pick<
|
||||
LearningProgress,
|
||||
'contentHash' | 'moduleId' | 'sceneOrder' | 'actionIndex' | 'positionMs' | 'completed'
|
||||
>;
|
||||
|
||||
export type InstalledLearningCourse = {
|
||||
schemaVersion: 1;
|
||||
course: LearningCourse;
|
||||
archivePath: string;
|
||||
installedAt: string;
|
||||
};
|
||||
|
||||
export type LearningClassroomPayload = {
|
||||
courseId: string;
|
||||
/** Aggregate package identity used to address immutable local assets. */
|
||||
courseContentHash: string;
|
||||
/** Aggregate hash kept as a compatibility alias for existing Stage bridges. */
|
||||
contentHash: string;
|
||||
moduleId: string | null;
|
||||
/** Selected frozen module hash; equals courseContentHash for legacy single-classroom packages. */
|
||||
moduleContentHash: string;
|
||||
modules: LearningCourseModule[];
|
||||
classroom: { stage: Record<string, unknown>; scenes: unknown[] };
|
||||
};
|
||||
|
||||
export type LearningGeneration = {
|
||||
contractVersion?: number;
|
||||
jobId: string;
|
||||
status: string;
|
||||
mode?: 'single' | 'large';
|
||||
step: string | null;
|
||||
progress: number | null;
|
||||
message: string | null;
|
||||
scenesGenerated: number | null;
|
||||
totalScenes: number | null;
|
||||
courseId: string | null;
|
||||
error: string | null;
|
||||
done: boolean;
|
||||
};
|
||||
Reference in New Issue
Block a user