// Probe 06: which generateContent-capable text models actually answer with this (free-tier) key? // One tiny request per model, serial and paced. Classifies: ok / 404 gone / 429 free-tier-zero / other. import { readFileSync } from "node:fs"; import { ai, save, errInfo, quotaKind, sleep, PACE_MS, shortText } from "./lib.js"; const models: any[] = JSON.parse(readFileSync("out/models.json", "utf8")); const skip = /embedding|veo|lyria|tts|image|aqa|transcribe|live|native-audio|robotics|computer-use|deep-research|antigravity|nano-banana/; const targets = models.filter((m) => m.supportedGenerationMethods?.includes("generateContent") && !skip.test(m.name)).map((m) => m.name.replace("models/", "")); console.log("targets:", targets.join(", ")); const results: any = {}; for (const model of targets) { const t0 = Date.now(); try { const res = await ai.models.generateContent({ model, contents: "Reply with the single word: pong", config: { maxOutputTokens: 100 } }); results[model] = { status: "ok", text: shortText(res), modelVersion: res.modelVersion, usage: res.usageMetadata, finishReason: res.candidates?.[0]?.finishReason, ms: Date.now() - t0 }; } catch (e) { const info = errInfo(e); const kind = quotaKind(e); results[model] = { status: info.httpStatus === 404 ? "gone-404" : kind === "day" ? "free-tier-zero-429" : `error-${info.httpStatus}`, error: info, ms: Date.now() - t0 }; } const r = results[model]; console.log(model.padEnd(36), r.status.padEnd(20), r.status === "ok" ? `"${r.text}" v=${r.modelVersion} thoughts=${r.usage?.thoughtsTokenCount ?? 0}` : r.error.message.slice(0, 110).replace(/\n/g, " ")); await sleep(1500); } save("06-availability.json", results);