import { z } from 'zod' import { AiModelError, assertAiModelAdmin, assertAiModelAdminForWrite } from './ai-model-access' import { aiModelAudit, aiModelTransaction } from './ai-model-repository' import { assertAiModelRecoveryTextSafe, getAiModelAdminState } from './ai-model-service' import { AI_MODEL_VERIFICATION_COLUMNS, lockAiModelVerificationExecution, verificationExecutionId, type AiModelVerificationRow } from './ai-model-verification-state' import { detailTransactionLock } from './detail-generator/repository' const proofSchema = z.object({ requestId: z.string().uuid(), executionEnded: z.literal(true), billingFinalized: z.literal(true), reference: z.string().trim().min(3).max(160), note: z.string().trim().min(20).max(500), confirmed: z.literal(true) }).strict() /** Records execution completion only. Original unknown rows and their same-model retry fence remain untouched. */ export async function releaseAiModelVerificationExecution(userId: string, providerId: string, verificationId: string, body: unknown) { const parsed = proofSchema.safeParse(body) if (!z.string().uuid().safeParse(verificationId).success || !parsed.success) throw new AiModelError('须提供原请求号及执行已结束、计费已结算的核查凭证') await assertAiModelAdmin(userId) await assertAiModelRecoveryTextSafe(providerId, `${parsed.data.reference}\n${parsed.data.note}`) await aiModelTransaction(async db => { await assertAiModelAdminForWrite(userId, db) const rows = await db.$queryRawUnsafe(`SELECT ${AI_MODEL_VERIFICATION_COLUMNS} FROM ai_model_verifications WHERE id=$1 AND model_key IN (SELECT id FROM ai_model_catalog WHERE provider_id=$2) FOR UPDATE`, verificationId, providerId) if (!rows[0]) throw new AiModelError('测试记录不存在', 404) const execution = await lockAiModelVerificationExecution(db, rows[0]) if (execution.some(row => row.status !== 'unknown' || row.taskId || row.requestId !== parsed.data.requestId)) throw new AiModelError('仅可登记同一原请求的未知同步结果;不能替换请求或关闭异步任务', 409, 'execution_proof_conflict') await detailTransactionLock(db, 'detail-generator-execution') const executionGroupId = verificationExecutionId(rows[0]) const prior = await db.$queryRawUnsafe>(`SELECT id FROM ai_model_audit WHERE action='model.verification-execution-ended' AND details->>'executionGroupId'=$1 AND details->>'originalRequestId'=$2`, executionGroupId, parsed.data.requestId) if (prior[0]) return await aiModelAudit(db, userId, 'model.verification-execution-ended', providerId, { ...parsed.data, originalRequestId: parsed.data.requestId, executionGroupId, verificationIds: execution.map(row => row.id), modelKey: rows[0].modelKey, resultStillUnknown: true, retryAllowed: false }) }) return getAiModelAdminState() }