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>
77 lines
2.7 KiB
TypeScript
77 lines
2.7 KiB
TypeScript
import { Controller, Get, Post, Param, Body, Req, UseGuards, HttpCode, HttpStatus } from '@nestjs/common';
|
|
import { InternalAuthGuard } from '../../../common/guards/internal-auth.guard';
|
|
import { RuntimeInternalService } from './runtime-internal.service';
|
|
import {
|
|
RuntimePollJobsRequestDto, RuntimeLockJobRequestDto, RuntimeHeartbeatRequestDto,
|
|
RuntimeResolveCredentialRequestDto, RuntimeSubmitResultRequestDto,
|
|
RuntimeSubmitFailureRequestDto, RuntimeSubmitInvocationLogsRequestDto,
|
|
} from './dto/runtime-internal.dto';
|
|
|
|
@Controller('internal/runtime')
|
|
@UseGuards(InternalAuthGuard)
|
|
export class RuntimeInternalController {
|
|
constructor(private readonly service: RuntimeInternalService) {}
|
|
|
|
private instanceId(req: any): string {
|
|
return (req.headers['x-runtime-instance-id'] as string) || 'unknown';
|
|
}
|
|
|
|
// ── Poll ──
|
|
|
|
@Post('jobs/poll')
|
|
async pollJobs(@Req() req: any, @Body() dto: RuntimePollJobsRequestDto) {
|
|
return this.service.pollJobs(this.instanceId(req), dto.supportedJobTypes, dto.limit ?? 5, dto.capabilities);
|
|
}
|
|
|
|
// ── Lock ──
|
|
|
|
@Post('jobs/:jobId/lock')
|
|
async lockJob(@Req() req: any, @Param('jobId') jobId: string, @Body() dto: RuntimeLockJobRequestDto) {
|
|
return this.service.lockJob(jobId, dto.runtimeInstanceId || this.instanceId(req));
|
|
}
|
|
|
|
// ── Heartbeat ──
|
|
|
|
@Post('jobs/:jobId/heartbeat')
|
|
async heartbeatJob(@Req() req: any, @Param('jobId') jobId: string, @Body() dto: RuntimeHeartbeatRequestDto) {
|
|
return this.service.heartbeatJob(jobId, dto.runtimeInstanceId || this.instanceId(req));
|
|
}
|
|
|
|
// ── Snapshot ──
|
|
|
|
@Get('jobs/:jobId/snapshot')
|
|
async getSnapshot(@Param('jobId') jobId: string) {
|
|
return this.service.getSnapshot(jobId);
|
|
}
|
|
|
|
// ── Credential Resolve ──
|
|
|
|
@Post('model-credentials/resolve')
|
|
async resolveCredential(@Body() dto: RuntimeResolveCredentialRequestDto) {
|
|
return this.service.resolveCredential(dto.jobId, dto.apiKeyMode, dto.provider, dto.credentialId);
|
|
}
|
|
|
|
// ── Submit Result ──
|
|
|
|
@Post('jobs/:jobId/result')
|
|
@HttpCode(HttpStatus.CREATED)
|
|
async submitResult(@Param('jobId') jobId: string, @Body() dto: RuntimeSubmitResultRequestDto) {
|
|
return this.service.submitResult(jobId, dto);
|
|
}
|
|
|
|
// ── Submit Failure ──
|
|
|
|
@Post('jobs/:jobId/fail')
|
|
async submitFailure(@Param('jobId') jobId: string, @Body() dto: RuntimeSubmitFailureRequestDto) {
|
|
return this.service.submitFailure(jobId, dto);
|
|
}
|
|
|
|
// ── Submit Invocation Logs ──
|
|
|
|
@Post('invocation-logs')
|
|
@HttpCode(HttpStatus.CREATED)
|
|
async submitInvocationLogs(@Body() dto: RuntimeSubmitInvocationLogsRequestDto) {
|
|
return this.service.submitInvocationLogs(dto.logs);
|
|
}
|
|
}
|