// Shared helpers for Mistral probes. Key comes from process.env.MISTRAL_API_KEY (never logged). import { mkdirSync, writeFileSync } from "node:fs"; import { deflateSync } from "node:zlib"; import OpenAI from "openai"; import { Mistral } from "@mistralai/mistralai"; export const BASE = "https://api.mistral.ai/v1"; export const KEY = process.env.MISTRAL_API_KEY ?? ""; if (!KEY) { console.error("MISTRAL_API_KEY missing (run: set -a; . ./.env; set +a)"); process.exit(1); } export const OUT = new URL("./out/", import.meta.url).pathname; mkdirSync(OUT, { recursive: true }); export const openai = new OpenAI({ apiKey: KEY, baseURL: BASE, timeout: 120_000, maxRetries: 0 }); export const mistral = new Mistral({ apiKey: KEY, retryConfig: { strategy: "none" } }); export const CHAT_MODELS = [ "mistral-large-latest", "mistral-medium-latest", "mistral-small-latest", "ministral-8b-latest", "magistral-medium-latest", "magistral-small-latest", "codestral-latest", ]; export function save(name: string, data: unknown) { writeFileSync(`${OUT}${name}`, JSON.stringify(data, null, 2)); console.log(`saved out/${name}`); } const HDR = /ratelimit|request-id|x-request|retry-after|content-type|server|date|cf-ray|x-kong|x-envoy|x-mistral|x-ms/i; /** Raw request; returns status, selected headers, and parsed body (never echoes the key). */ export async function raw(path: string, init: RequestInit & { key?: string } = {}) { const { key, ...rest } = init; const res = await fetch(`${BASE}${path}`, { ...rest, headers: { "Content-Type": "application/json", Accept: "application/json", Authorization: `Bearer ${key ?? KEY}`, ...(rest.headers ?? {}), }, }); const text = await res.text(); let body: unknown = text; try { body = JSON.parse(text); } catch {} const headers: Record = {}; res.headers.forEach((v, k) => { if (HDR.test(k)) headers[k] = v; }); return { status: res.status, headers, body }; } export function post(path: string, payload: unknown, key?: string) { return raw(path, { method: "POST", body: JSON.stringify(payload), key }); } /** Raw SSE POST; returns list of parsed events (data lines). */ export async function rawSSE(path: string, payload: unknown, key?: string) { const res = await fetch(`${BASE}${path}`, { method: "POST", headers: { "Content-Type": "application/json", Accept: "text/event-stream", Authorization: `Bearer ${key ?? KEY}` }, body: JSON.stringify(payload), }); const headers: Record = {}; res.headers.forEach((v, k) => { if (HDR.test(k)) headers[k] = v; }); if (!res.ok || !res.body) { const text = await res.text(); let body: unknown = text; try { body = JSON.parse(text); } catch {} return { status: res.status, headers, error: body, events: [] as any[] }; } const reader = res.body.getReader(); const dec = new TextDecoder(); let buf = ""; const events: { event?: string; data: any; raw?: string }[] = []; for (;;) { const { value, done } = await reader.read(); if (done) break; buf += dec.decode(value, { stream: true }); let idx; while ((idx = buf.indexOf("\n\n")) >= 0) { const block = buf.slice(0, idx); buf = buf.slice(idx + 2); let ev: string | undefined; const datas: string[] = []; for (const line of block.split("\n")) { if (line.startsWith("event:")) ev = line.slice(6).trim(); else if (line.startsWith("data:")) datas.push(line.slice(5).trim()); } if (!datas.length) continue; const d = datas.join("\n"); if (d === "[DONE]") { events.push({ event: ev, data: "[DONE]" }); continue; } try { events.push({ event: ev, data: JSON.parse(d) }); } catch { events.push({ event: ev, data: null, raw: d }); } } } return { status: res.status, headers, events }; } export function short(s: unknown, n = 300) { const t = typeof s === "string" ? s : JSON.stringify(s) ?? String(s); return t.length > n ? t.slice(0, n) + "…" : t; } /** Minimal valid PNG (RGB, solid colour with a diagonal), size x size, base64 data URL. */ export function pngDataUrl(size = 32): string { const crcTable = new Int32Array(256); for (let n = 0; n < 256; n++) { let c = n; for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1; crcTable[n] = c; } const crc32 = (buf: Buffer) => { let c = -1; for (const b of buf) c = crcTable[(c ^ b) & 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, "ascii"), data]); const crc = Buffer.alloc(4); crc.writeUInt32BE(crc32(td)); return Buffer.concat([len, td, crc]); }; const ihdr = Buffer.alloc(13); ihdr.writeUInt32BE(size, 0); ihdr.writeUInt32BE(size, 4); ihdr[8] = 8; // bit depth ihdr[9] = 2; // RGB const rows: Buffer[] = []; for (let y = 0; y < size; y++) { const row = Buffer.alloc(1 + size * 3); for (let x = 0; x < size; x++) { const onDiag = Math.abs(x - y) < 2; row[1 + x * 3] = onDiag ? 255 : 30; // R row[2 + x * 3] = onDiag ? 255 : 60; // G row[3 + x * 3] = onDiag ? 255 : 200; // B } rows.push(row); } const idat = deflateSync(Buffer.concat(rows)); const png = Buffer.concat([ Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]), chunk("IHDR", ihdr), chunk("IDAT", idat), chunk("IEND", Buffer.alloc(0)), ]); return `data:image/png;base64,${png.toString("base64")}`; }