release: opensource snapshot 2026-02-27 19:25:00

This commit is contained in:
saturn
2026-02-27 19:25:00 +08:00
commit 5de9622c8b
1055 changed files with 164772 additions and 0 deletions

View File

@@ -0,0 +1,323 @@
import { prisma } from '@/lib/prisma'
import { TASK_TYPE } from '@/lib/task/types'
type AnyJson = unknown
type Match = {
path: string
value: string
}
type Options = {
minutes: number
limit: number
projectId: string | null
strictNoData: boolean
includeEvents: boolean
maxEventsPerTask: number
json: boolean
}
type FailureType = 'normalize' | 'model' | 'cancelled' | 'other'
const MODEL_ERROR_CODES = new Set([
'GENERATION_FAILED',
'GENERATION_TIMEOUT',
'RATE_LIMIT',
'EXTERNAL_ERROR',
'SENSITIVE_CONTENT',
])
function parseNumberArg(name: string, fallback: number): number {
const raw = process.argv.find((arg) => arg.startsWith(`--${name}=`))
if (!raw) return fallback
const value = Number.parseInt(raw.split('=')[1] || '', 10)
return Number.isFinite(value) && value > 0 ? value : fallback
}
function parseStringArg(name: string): string | null {
const raw = process.argv.find((arg) => arg.startsWith(`--${name}=`))
if (!raw) return null
const value = (raw.split('=')[1] || '').trim()
return value || null
}
function parseBooleanArg(name: string, fallback = false): boolean {
const raw = process.argv.find((arg) => arg.startsWith(`--${name}=`))
if (!raw) return fallback
const value = (raw.split('=')[1] || '').trim().toLowerCase()
return value === '1' || value === 'true' || value === 'yes' || value === 'on'
}
function parseOptions(): Options {
return {
minutes: parseNumberArg('minutes', 60 * 24),
limit: parseNumberArg('limit', 200),
projectId: parseStringArg('projectId'),
strictNoData: parseBooleanArg('strictNoData', false),
includeEvents: parseBooleanArg('includeEvents', false),
maxEventsPerTask: parseNumberArg('maxEventsPerTask', 40),
json: parseBooleanArg('json', false),
}
}
function toExcerpt(value: string, max = 180): string {
if (value.length <= max) return value
return `${value.slice(0, max)}...`
}
function findStringMatches(
value: AnyJson,
predicate: (input: string) => boolean,
path = '$',
matches: Match[] = [],
): Match[] {
if (typeof value === 'string') {
if (predicate(value)) matches.push({ path, value })
return matches
}
if (Array.isArray(value)) {
value.forEach((item, index) => {
findStringMatches(item, predicate, `${path}[${index}]`, matches)
})
return matches
}
if (value && typeof value === 'object') {
for (const [key, next] of Object.entries(value as Record<string, unknown>)) {
findStringMatches(next, predicate, `${path}.${key}`, matches)
}
}
return matches
}
function classifyFailure(task: {
errorCode: string | null
errorMessage: string | null
result: AnyJson | null
events: Array<{ payload: AnyJson | null }>
}): FailureType {
const code = (task.errorCode || '').trim().toUpperCase()
const normalizeRe = /normalize|video_frame_normalize|normalizeReferenceImagesForGeneration|reference image normalize failed|outbound image input is empty|relative_path_rejected/i
const modelRe = /generation failed|provider|upstream|rate limit|timed out|timeout|sensitive/i
if (code === 'TASK_CANCELLED') return 'cancelled'
if (MODEL_ERROR_CODES.has(code)) return 'model'
if (code) {
const explicitNormalizeCode = code === 'INVALID_PARAMS' || code === 'OUTBOUND_IMAGE_FETCH_FAILED'
if (explicitNormalizeCode) return 'normalize'
return 'other'
}
const values: string[] = []
if (code) values.push(code)
if (task.errorMessage) values.push(task.errorMessage)
if (task.result) {
for (const hit of findStringMatches(task.result, () => true)) {
values.push(hit.value)
}
}
for (const event of task.events) {
if (!event.payload) continue
for (const hit of findStringMatches(event.payload, () => true)) {
values.push(hit.value)
}
}
if (values.some((item) => normalizeRe.test(item))) return 'normalize'
if (values.some((item) => modelRe.test(item))) return 'model'
return 'other'
}
async function main() {
const options = parseOptions()
const since = new Date(Date.now() - options.minutes * 60_000)
const monitoredTypes = [
TASK_TYPE.MODIFY_ASSET_IMAGE,
TASK_TYPE.ASSET_HUB_MODIFY,
TASK_TYPE.VIDEO_PANEL,
]
const tasks = await prisma.task.findMany({
where: {
type: { in: monitoredTypes },
createdAt: { gte: since },
...(options.projectId ? { projectId: options.projectId } : {}),
},
select: {
id: true,
type: true,
status: true,
projectId: true,
targetType: true,
targetId: true,
createdAt: true,
errorCode: true,
errorMessage: true,
payload: true,
result: true,
},
orderBy: { createdAt: 'desc' },
take: options.limit,
})
if (tasks.length === 0) {
process.stdout.write(
`[check:outbound-image-runtime-sample] no data window=${options.minutes}m limit=${options.limit} strictNoData=${options.strictNoData}\n`,
)
if (options.strictNoData) process.exit(2)
return
}
const eventsByTaskId = new Map<string, Array<{ eventType: string; payload: AnyJson | null; createdAt: Date }>>()
let eventCount = 0
if (options.includeEvents) {
for (const task of tasks) {
const rows = await prisma.taskEvent.findMany({
where: { taskId: task.id },
select: {
taskId: true,
eventType: true,
payload: true,
createdAt: true,
},
orderBy: { id: 'desc' },
take: options.maxEventsPerTask,
})
const ordered = [...rows].reverse()
eventCount += ordered.length
if (ordered.length > 0) {
eventsByTaskId.set(
task.id,
ordered.map((event) => ({
eventType: event.eventType,
payload: event.payload,
createdAt: event.createdAt,
})),
)
}
}
}
const nextImagePredicate = (input: string) => input.includes('/_next/image')
const hits: Array<{
taskId: string
taskType: string
source: 'task.payload' | 'task.result' | 'task.event'
path: string
value: string
}> = []
let failedCount = 0
const failedByClass: Record<FailureType, number> = {
normalize: 0,
model: 0,
cancelled: 0,
other: 0,
}
const failedByCode: Record<string, number> = {}
for (const task of tasks) {
const taskEventsForTask = eventsByTaskId.get(task.id) || []
if (task.payload) {
for (const match of findStringMatches(task.payload, nextImagePredicate)) {
hits.push({
taskId: task.id,
taskType: task.type,
source: 'task.payload',
path: match.path,
value: match.value,
})
}
}
if (task.result) {
for (const match of findStringMatches(task.result, nextImagePredicate)) {
hits.push({
taskId: task.id,
taskType: task.type,
source: 'task.result',
path: match.path,
value: match.value,
})
}
}
for (const event of taskEventsForTask) {
if (!event.payload) continue
for (const match of findStringMatches(event.payload, nextImagePredicate)) {
hits.push({
taskId: task.id,
taskType: task.type,
source: 'task.event',
path: match.path,
value: match.value,
})
}
}
if (task.status === 'failed') {
failedCount += 1
const code = (task.errorCode || 'UNKNOWN').trim() || 'UNKNOWN'
failedByCode[code] = (failedByCode[code] || 0) + 1
const failureType = classifyFailure({
errorCode: task.errorCode,
errorMessage: task.errorMessage,
result: task.result,
events: taskEventsForTask,
})
failedByClass[failureType] += 1
}
}
const typeCount = tasks.reduce<Record<string, number>>((acc, item) => {
acc[item.type] = (acc[item.type] || 0) + 1
return acc
}, {})
process.stdout.write(
`[check:outbound-image-runtime-sample] window=${options.minutes}m sampled=${tasks.length} events=${eventCount} includeEvents=${options.includeEvents} next_image_hits=${hits.length}\n`,
)
process.stdout.write(`[check:outbound-image-runtime-sample] task_types=${JSON.stringify(typeCount)}\n`)
process.stdout.write(
`[check:outbound-image-runtime-sample] failures total=${failedCount} normalize=${failedByClass.normalize} model=${failedByClass.model} cancelled=${failedByClass.cancelled} other=${failedByClass.other} by_code=${JSON.stringify(failedByCode)}\n`,
)
if (options.json) {
process.stdout.write(
`${JSON.stringify({
windowMinutes: options.minutes,
sampled: tasks.length,
events: eventCount,
includeEvents: options.includeEvents,
nextImageHits: hits.length,
taskTypes: typeCount,
failures: {
total: failedCount,
byClass: failedByClass,
byCode: failedByCode,
},
})}\n`,
)
}
if (hits.length > 0) {
process.stderr.write('[check:outbound-image-runtime-sample] found /_next/image contamination:\n')
for (const hit of hits.slice(0, 20)) {
process.stderr.write(
`- task=${hit.taskId} type=${hit.taskType} source=${hit.source} path=${hit.path} value=${toExcerpt(hit.value)}\n`,
)
}
process.exit(1)
}
}
main()
.catch((error) => {
const message = error instanceof Error ? error.message : String(error)
process.stderr.write(`[check:outbound-image-runtime-sample] failed: ${message}\n`)
process.exit(1)
})
.finally(async () => {
await prisma.$disconnect()
})