// Shared helpers for the PolyLLM OpenAI probes. The API key is read from the OPENAI_API_KEY // environment variable by the SDK; nothing secret is stored in these files or in results/. import OpenAI from "openai"; import fs from "node:fs"; import zlib from "node:zlib"; export const client = new OpenAI({ maxRetries: 1, timeout: 180_000 }); // Six focus models required by the audit (+ broad sweep list in 02-basic.ts). export const PROBE_MODELS = ["gpt-5.5", "gpt-5.4-mini", "gpt-5.6-sol", "gpt-6-astra", "gpt-4.1-mini", "o4-mini"]; export const REASONING_MODELS = new Set(["gpt-5.5", "gpt-5.4-mini", "gpt-5.6-sol", "gpt-6-astra", "o4-mini"]); export function errInfo(e: any) { return { status: e?.status ?? null, code: e?.code ?? e?.error?.code ?? null, type: e?.type ?? e?.error?.type ?? null, param: e?.param ?? e?.error?.param ?? null, message: e?.error?.message ?? e?.message ?? String(e), request_id: e?.requestID ?? null, sdk_class: e?.constructor?.name ?? null, }; } export async function attempt(label: string, fn: () => Promise) { const t0 = Date.now(); try { const result = await fn(); const r = { label, ok: true as const, ms: Date.now() - t0, result }; console.log(`OK ${label} (${r.ms} ms)`); return r; } catch (e: any) { const r = { label, ok: false as const, ms: Date.now() - t0, error: errInfo(e) }; console.log(`FAIL ${label} -> ${r.error.status} ${r.error.code ?? ""} ${r.error.message}`); return r; } } export function save(name: string, data: unknown) { fs.mkdirSync("results", { recursive: true }); fs.writeFileSync(`results/${name}.json`, JSON.stringify(data, null, 1)); console.log(`saved results/${name}.json`); } export function pickHeaders(h: Headers) { const out: Record = {}; h.forEach((v, k) => { if (/^(x-ratelimit|x-request-id|openai-|retry-after|x-openai|cf-ray|content-type)/i.test(k)) out[k] = v; }); return out; } export function summarizeResponse(r: any) { return { id: r.id, model: r.model, status: r.status, incomplete_details: r.incomplete_details ?? null, service_tier: r.service_tier ?? null, store: r.store ?? null, output_item_types: (r.output ?? []).map((o: any) => o.type + (o.type === "message" ? `[${(o.content ?? []).map((c: any) => c.type).join(",")}]` : "")), output_text: (r.output_text ?? "").slice(0, 160), usage: r.usage ?? null, reasoning: r.reasoning ?? null, text: r.text ?? null, temperature: r.temperature ?? null, top_p: r.top_p ?? null, truncation: r.truncation ?? null, max_output_tokens: r.max_output_tokens ?? null, }; } // 2x2 RGBA PNG (red, green / blue, white) built with zlib, no deps. export function tinyPngBase64(): string { const w = 2, h = 2; const px = [[255, 0, 0, 255], [0, 255, 0, 255], [0, 0, 255, 255], [255, 255, 255, 255]]; const raw = Buffer.alloc((1 + w * 4) * h); for (let y = 0; y < h; y++) { raw[y * (1 + w * 4)] = 0; for (let x = 0; x < w; x++) Buffer.from(px[y * w + x]).copy(raw, y * (1 + w * 4) + 1 + x * 4); } const crcTable = new Int32Array(256).map((_, n) => { let c = n; for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1; return c; }); const crc = (b: Buffer) => { let c = -1; for (const x of b) c = crcTable[(c ^ x) & 0xff] ^ (c >>> 8); return (c ^ -1) >>> 0; }; const chunk = (type: string, data: Buffer) => { const len = Buffer.alloc(4); len.writeUInt32BE(data.length); const td = Buffer.concat([Buffer.from(type), data]); const c = Buffer.alloc(4); c.writeUInt32BE(crc(td)); return Buffer.concat([len, td, c]); }; const ihdr = Buffer.alloc(13); ihdr.writeUInt32BE(w, 0); ihdr.writeUInt32BE(h, 4); ihdr[8] = 8; ihdr[9] = 6; ihdr[10] = 0; ihdr[11] = 0; ihdr[12] = 0; return Buffer.concat([Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]), chunk("IHDR", ihdr), chunk("IDAT", zlib.deflateSync(raw)), chunk("IEND", Buffer.alloc(0))]).toString("base64"); } // Minimal one-page PDF with the text "PolyLLM probe PDF". export function tinyPdfBase64(): string { const objs = [ "<< /Type /Catalog /Pages 2 0 R >>", "<< /Type /Pages /Kids [3 0 R] /Count 1 >>", "<< /Type /Page /Parent 2 0 R /MediaBox [0 0 200 100] /Contents 4 0 R /Resources << /Font << /F1 5 0 R >> >> >>", "<< /Length 60 >>\nstream\nBT /F1 14 Tf 10 50 Td (PolyLLM probe PDF secret=42) Tj ET\nendstream", "<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>", ]; let pdf = "%PDF-1.4\n"; const offs: number[] = []; objs.forEach((o, i) => { offs.push(pdf.length); pdf += `${i + 1} 0 obj\n${o}\nendobj\n`; }); const xref = pdf.length; pdf += `xref\n0 ${objs.length + 1}\n0000000000 65535 f \n` + offs.map(o => String(o).padStart(10, "0") + " 00000 n \n").join("") + `trailer\n<< /Size ${objs.length + 1} /Root 1 0 R >>\nstartxref\n${xref}\n%%EOF\n`; return Buffer.from(pdf, "latin1").toString("base64"); }