All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 45s
- runtime-internal.service: resolveSnapshot 自动重建、persistResult 5种jobType持久化、validateOutput 校验、convertQuizCandidates/convertFlashcardCandidates 候选转换、notifyJobComplete 通知、JOB_CANCELLED处理、heartbeat 双阶段更新+取消检测 - user-ai.service: createAnalysisJob 11步流程、cancelJob、publishQuiz/publishFlashcard、getAnalysis/listAnalyses等 - user-ai.controller: 20+ 用户API端点 - 新增服务: SnapshotBuilderService、PriorityRulesService、SnapshotCleanupService、JobReaperService - 新增模块: admin-learning (CRUD管理) - Prisma schema: cancelRequestedAt/cancelledAt/sourceBlockIds 字段、expiresAt 索引 - 文档: ai-runtime-user-api.md、Issue 记录 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
102 lines
3.4 KiB
TypeScript
102 lines
3.4 KiB
TypeScript
import { IsArray, IsBoolean, IsEnum, IsIn, IsInt, IsOptional, IsString, Max, Min } from 'class-validator';
|
|
|
|
// ── LearningProfile ──
|
|
|
|
export class SaveLearningProfileDto {
|
|
@IsOptional() @IsString() learningGoal?: string;
|
|
@IsOptional() @IsString() currentLevel?: string;
|
|
@IsOptional() @IsInt() @Min(1) @Max(480) dailyAvailableMinutes?: number;
|
|
@IsOptional() @IsString() qualityPreference?: string;
|
|
@IsOptional() @IsString() ageRange?: string;
|
|
@IsOptional() @IsString() occupation?: string;
|
|
@IsOptional() @IsString() examTarget?: string;
|
|
@IsOptional() @IsString() learningDeadline?: string;
|
|
@IsOptional() @IsString() learningStyle?: string;
|
|
@IsOptional() @IsString() aiAcceptanceLevel?: string;
|
|
@IsOptional() @IsString() digitalSkillLevel?: string;
|
|
@IsOptional() @IsArray() @IsString({ each: true }) preferredQuestionTypes?: string[];
|
|
@IsOptional() @IsString() preferredLanguage?: string;
|
|
}
|
|
|
|
// ── AiSettings ──
|
|
|
|
export class UpdateAiSettingsDto {
|
|
@IsOptional() @IsBoolean() allowAiAnalysis?: boolean;
|
|
@IsOptional() @IsBoolean() allowUseLearningBehavior?: boolean;
|
|
@IsOptional() @IsBoolean() allowUseUserProfile?: boolean;
|
|
@IsOptional() @IsBoolean() allowUseDocumentContent?: boolean;
|
|
@IsOptional() @IsBoolean() allowStoreAiAnalysisHistory?: boolean;
|
|
@IsOptional() @IsString() apiKeyMode?: string;
|
|
@IsOptional() @IsString() defaultCredentialId?: string;
|
|
@IsOptional() @IsBoolean() fallbackToPlatformKey?: boolean;
|
|
@IsOptional() @IsInt() @Min(0) maxDailyAiJobs?: number;
|
|
@IsOptional() @IsInt() @Min(0) maxDailyTokenBudget?: number;
|
|
}
|
|
|
|
// ── ModelCredential ──
|
|
|
|
export class CreateCredentialDto {
|
|
@IsString() provider!: string;
|
|
@IsString() apiKey!: string;
|
|
@IsOptional() @IsString() keyAlias?: string;
|
|
}
|
|
|
|
export class UpdateCredentialDto {
|
|
@IsString() apiKey!: string;
|
|
@IsOptional() @IsString() keyAlias?: string;
|
|
}
|
|
|
|
export class CredentialResponseDto {
|
|
id!: string;
|
|
provider!: string;
|
|
keyAlias?: string;
|
|
maskedKey!: string;
|
|
status!: string;
|
|
lastTestedAt?: string;
|
|
lastUsedAt?: string;
|
|
createdAt!: string;
|
|
updatedAt!: string;
|
|
}
|
|
|
|
// ── Analysis Job ──
|
|
|
|
export const VALID_JOB_TYPES = [
|
|
'learning_state_analysis',
|
|
'weak_point_analysis',
|
|
'next_action_planning',
|
|
'quiz_generation',
|
|
'flashcard_generation',
|
|
] as const;
|
|
|
|
export const VALID_TARGET_TYPES = ['user', 'material', 'knowledge_base'] as const;
|
|
const VALID_DIFFICULTY_LEVELS = ['easy', 'medium', 'hard'] as const;
|
|
|
|
export class CreateAnalysisJobDto {
|
|
@IsIn(VALID_JOB_TYPES) jobType!: string;
|
|
@IsIn(VALID_TARGET_TYPES) targetType!: string;
|
|
@IsString() targetId!: string;
|
|
@IsOptional() @IsString() idempotencyKey?: string;
|
|
@IsOptional() @IsString() apiKeyMode?: string;
|
|
@IsOptional() @IsString() credentialId?: string;
|
|
@IsOptional() @IsString() promptVersion?: string;
|
|
@IsOptional() @IsString() outputSchemaVersion?: string;
|
|
|
|
// Quiz-specific (API-AI-023)
|
|
@IsOptional() @IsInt() @Min(1) @Max(50) questionCount?: number;
|
|
@IsOptional() @IsArray() @IsString({ each: true }) questionTypes?: string[];
|
|
|
|
// Flashcard-specific (API-AI-024)
|
|
@IsOptional() @IsInt() @Min(1) @Max(100) cardCount?: number;
|
|
|
|
// Shared by quiz & flashcard
|
|
@IsOptional() @IsIn(VALID_DIFFICULTY_LEVELS) difficultyLevel?: string;
|
|
@IsOptional() @IsArray() @IsString({ each: true }) knowledgePointIds?: string[];
|
|
}
|
|
|
|
export class CreateAnalysisJobResponseDto {
|
|
jobId!: string;
|
|
status!: string;
|
|
createdAt!: string;
|
|
@IsOptional() @IsString() planId?: string;
|
|
}
|