/** Isolated local HTTP acceptance only. Never submits a generation request. */ import assert from 'node:assert/strict' import { writeFile } from 'node:fs/promises' import { PrismaClient } from '@prisma/client' import type { AiModelAdminState } from '../lib/ai-model-types' const database = new URL(process.env.DATABASE_URL || '') assert.equal(database.hostname, '127.0.0.1') assert.equal(database.port, '55441') assert.equal(database.pathname, '/ai_model_test') const base = 'http://localhost:3120' const prisma = new PrismaClient({ log: [] }) const evidence: Record = { generationCalls: 0 } async function signIn(index: number) { const jar = new Map() function store(response: Response) { for (const cookie of response.headers.getSetCookie()) { const first = cookie.split(';')[0], position = first.indexOf('=') jar.set(first.slice(0, position), first.slice(position + 1)) } } const csrf = await fetch(base + '/api/auth/csrf'); store(csrf) const { csrfToken } = await csrf.json() const login = await fetch(base + '/api/auth/callback/credentials', { method: 'POST', redirect: 'manual', headers: { 'Content-Type': 'application/x-www-form-urlencoded', Origin: base, Cookie: [...jar].map(([key, value]) => `${key}=${value}`).join('; ') }, body: new URLSearchParams({ csrfToken, email: `ai-admin-${index}@example.invalid`, password: 'AiAdminLocalTest-20261012', callbackUrl: base + '/admin', json: 'true' }), }) store(login); assert.equal(login.status, 200) return [...jar].map(([key, value]) => `${key}=${value}`).join('; ') } async function request(cookie: string, path = '', method = 'GET', body?: unknown) { const response = await fetch(base + '/api/admin/ai-models' + path, { method, redirect: 'manual', headers: { Cookie: cookie, 'Content-Type': 'application/json' }, ...(body === undefined ? {} : { body: JSON.stringify(body) }), }) const text = await response.text() if (process.env.DETAIL_GENERATOR_API_KEY) assert.ok(!text.includes(process.env.DETAIL_GENERATOR_API_KEY)) return { status: response.status, data: JSON.parse(text) } } function input(state: AiModelAdminState) { return { revision: state.revision, defaults: state.defaults, providers: state.providers.map(provider => ({ id: provider.id, revision: provider.revision, models: provider.models.map(({ key, enabled, stages, compatibility }) => ({ key, enabled, stages, compatibility })), })) } } async function main() { const beforeJobs = await prisma.detailGeneratorJob.count() const admin = await signIn(0), ordinary = await signIn(2) assert.equal((await request('')).status, 401) assert.equal((await request(ordinary)).status, 403) let state = (await request(admin)).data as AiModelAdminState const imported = state.providers.find(provider => provider.credentialSource === 'environment') assert.ok(imported) const sync = await request(admin, `/providers/${imported.id}/sync`, 'POST', { revision: imported.revision }) assert.equal(sync.status, 200, JSON.stringify(sync.data)) state = sync.data const provider = state.providers.find(value => value.id === imported.id)! const present = provider.models.filter(model => model.present) const repeat = await request(admin, `/providers/${provider.id}/sync`, 'POST', { revision: provider.revision }) assert.equal(repeat.status, 200, JSON.stringify(repeat.data)) assert.equal(repeat.data.providers.find((value: { id: string }) => value.id === provider.id).revision, provider.revision) evidence.unchangedCatalogKeepsBindingRevision = true evidence.catalogCount = present.length evidence.classification = Object.fromEntries(['text', 'vision', 'image', 'other', 'unknown'].map(kind => [kind, present.filter(model => model.capabilities.kind === kind).length])) assert.ok(present.some(model => model.capabilities.kind === 'image')) assert.ok(present.some(model => model.capabilities.kind === 'text' || model.capabilities.kind === 'vision')) const conversation = present.find(model => model.capabilities.allowedStages.includes('copy') && !model.capabilities.allowedStages.includes('image'))! assert.ok(conversation) const bad = input(state) const badModel = bad.providers.find(value => value.id === provider.id)!.models.find(model => model.key === conversation.key)! badModel.stages = ['image']; badModel.enabled = true; badModel.compatibility = 'confirmed' assert.equal((await request(admin, '/configuration', 'PUT', bad)).status, 400) assert.equal((await request(ordinary, '/configuration', 'PUT', bad)).status, 403) evidence.conversationImageAssignmentDenied = true const forged = input(state) Object.assign(forged.providers[0].models[0], { capabilities: { allowedStages: ['image'], kind: 'image', source: 'verified', reason: '' } }) assert.equal((await request(admin, '/configuration', 'PUT', forged)).status, 400) evidence.clientCapabilityForgeryDenied = true const unchanged = (await request(admin)).data as AiModelAdminState assert.equal(unchanged.revision, state.revision) evidence.rejectedConfigurationDoesNotWrite = true // Only existing administrator-open models are exposed to the detail generator. const response = await fetch(base + '/api/detail-generator', { headers: { Cookie: admin } }) assert.equal(response.status, 200) const { config } = await response.json() for (const stage of ['analysis', 'copy', 'image'] as const) { const expected = state.providers.flatMap(source => source.models.filter(model => source.enabled && source.hasApiKey && model.present && model.enabled && model.compatibility === 'confirmed' && model.stages.includes(stage) && model.capabilities.allowedStages.includes(stage)).map(model => model.key)).sort() assert.deepEqual(config.models[stage].slice().sort(), expected) } evidence.userChoicesEqualAdministratorOpenCapabilityIntersection = true const after = await prisma.detailGeneratorJob.count() assert.equal(after, beforeJobs) evidence.jobCountUnchanged = true await writeFile('output/detail-generator/ai-capabilities-http-evidence.json', JSON.stringify(evidence, null, 2)) console.log(JSON.stringify(evidence)) } main().catch(error => { console.error(error.message); process.exitCode = 1 }).finally(() => prisma.$disconnect())