Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Generate images via OpenAI, Google, OpenRouter, DashScope, Jimeng, Seedream, and Replicate APIs with batch support.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
scripts/providers/agnes.test.ts
1import assert from "node:assert/strict";2import fs from "node:fs/promises";3import os from "node:os";4import path from "node:path";5import test, { type TestContext } from "node:test";67import type { CliArgs } from "../types.ts";8import {9buildRequestBody,10extractImageFromResponse,11parseAspectRatio,12resolveReferenceImages,13resolveSize,14snapDim,15validateArgs,16} from "./agnes.ts";1718function useEnv(19t: TestContext,20values: Record<string, string | null>,21): void {22const previous = new Map<string, string | undefined>();23for (const [key, value] of Object.entries(values)) {24previous.set(key, process.env[key]);25if (value == null) {26delete process.env[key];27} else {28process.env[key] = value;29}30}3132t.after(() => {33for (const [key, value] of previous.entries()) {34if (value == null) {35delete process.env[key];36} else {37process.env[key] = value;38}39}40});41}4243function makeArgs(overrides: Partial<CliArgs> = {}): CliArgs {44return {45prompt: null,46promptFiles: [],47imagePath: null,48provider: null,49model: null,50aspectRatio: null,51size: null,52quality: null,53imageSize: null,54imageApiDialect: null,55referenceImages: [],56n: 1,57batchFile: null,58jobs: null,59json: false,60help: false,61responseFormat: null,62...overrides,63};64}6566test("snapDim rounds to the nearest multiple of 32", () => {67assert.equal(snapDim(767), 768);68assert.equal(snapDim(1023), 1024);69assert.equal(snapDim(1024), 1024);70assert.equal(snapDim(32), 32);71assert.equal(snapDim(0), 32);72assert.equal(snapDim(16), 32);73assert.equal(snapDim(48), 64);74});7576test("parseAspectRatio parses valid ratios and rejects invalid inputs", () => {77assert.deepEqual(parseAspectRatio("3:4"), { width: 3, height: 4 });78assert.deepEqual(parseAspectRatio("16:9"), { width: 16, height: 9 });79assert.deepEqual(parseAspectRatio("1:1"), { width: 1, height: 1 });80assert.deepEqual(parseAspectRatio("1.5:1"), { width: 1.5, height: 1 });8182assert.equal(parseAspectRatio(""), null);83assert.equal(parseAspectRatio("invalid"), null);84assert.equal(parseAspectRatio("3x4"), null);85assert.equal(parseAspectRatio("0:1"), null);86assert.equal(parseAspectRatio("1:0"), null);87});8889test("resolveSize returns explicit --size directly", () => {90assert.equal(resolveSize({ size: "1024x1024" }), "1024x1024");91assert.equal(resolveSize({ size: "768x1024", aspectRatio: "16:9" }), "768x1024");92});9394test("resolveSize returns default 1024x1024 when no size or ratio given", () => {95assert.equal(resolveSize({}), "1024x1024");96assert.equal(resolveSize({ size: null, aspectRatio: null }), "1024x1024");97});9899test("resolveSize computes 32-aligned size within 2048 max edge", () => {100assert.equal(resolveSize({ aspectRatio: "1:1" }), "1024x1024");101assert.equal(resolveSize({ aspectRatio: "16:9" }), "2048x1152");102assert.equal(resolveSize({ aspectRatio: "4:3" }), "2048x1536");103assert.equal(resolveSize({ aspectRatio: "3:4" }), "1536x2048");104assert.equal(resolveSize({ aspectRatio: "9:16" }), "1152x2048");105});106107test("resolveSize aligns to 32 and respects max edge", () => {108assert.equal(resolveSize({ aspectRatio: "3:1" }), "2048x672");109assert.equal(resolveSize({ aspectRatio: "1:3" }), "672x2048");110});111112test("validateArgs rejects --n > 1", () => {113assert.throws(114() => validateArgs("agnes-image-2.1-flash", makeArgs({ n: 2 })),115/returns a single image per request/,116);117assert.doesNotThrow(() =>118validateArgs("agnes-image-2.1-flash", makeArgs({ n: 1 })),119);120});121122test("buildRequestBody maps prompt, model, size, and reference images", () => {123const body = buildRequestBody("a cat", "agnes-image-2.1-flash", {124size: "1024x1024",125aspectRatio: null,126referenceImages: [],127});128assert.equal(body.model, "agnes-image-2.1-flash");129assert.equal(body.prompt, "a cat");130assert.equal(body.size, "1024x1024");131assert.deepEqual(body.extra_body, { response_format: "url" });132133const bodyWithRef = buildRequestBody("a cat", "agnes-image-2.1-flash", {134size: null,135aspectRatio: "3:4",136referenceImages: ["https://example.com/ref.jpg"],137});138assert.equal(bodyWithRef.size, "1536x2048");139assert.deepEqual(bodyWithRef.image, ["https://example.com/ref.jpg"]);140});141142test("extractImageFromResponse decodes b64_json payloads", async () => {143const fromBase64 = await extractImageFromResponse({144data: [{ b64_json: Buffer.from("hello").toString("base64") }],145});146assert.equal(Buffer.from(fromBase64).toString("utf8"), "hello");147});148149test("extractImageFromResponse downloads URL payloads", async (t) => {150const originalFetch = globalThis.fetch;151t.after(() => {152globalThis.fetch = originalFetch;153});154155globalThis.fetch = async () =>156new Response(Uint8Array.from([1, 2, 3]), {157status: 200,158headers: { "Content-Type": "image/png" },159});160161const fromUrl = await extractImageFromResponse({162data: [{ url: "https://example.com/output.png" }],163});164assert.deepEqual([...fromUrl], [1, 2, 3]);165});166167test("extractImageFromResponse throws on empty data", async () => {168await assert.rejects(169() => extractImageFromResponse({ data: [] }),170/No image/,171);172await assert.rejects(173() => extractImageFromResponse({ data: [{}] }),174/No image/,175);176});177178test("resolveReferenceImages converts local files to data URIs and passes URLs through", async (t) => {179const dir = await fs.mkdtemp(path.join(os.tmpdir(), "agnes-ref-"));180t.after(() => fs.rm(dir, { recursive: true, force: true }));181182const localPath = path.join(dir, "ref.png");183const localBytes = Buffer.from([0x89, 0x50, 0x4e, 0x47]);184await fs.writeFile(localPath, localBytes);185186const jpegPath = path.join(dir, "photo.jpeg");187await fs.writeFile(jpegPath, Buffer.from([0xff, 0xd8]));188189const results = await resolveReferenceImages([190localPath,191"https://example.com/remote.jpg",192jpegPath,193]);194195assert.equal(results.length, 3);196assert.match(results[0]!, /^data:image\/png;base64,/);197assert.match(results[1]!, /^https:\/\/example.com\/remote.jpg$/);198assert.match(results[2]!, /^data:image\/jpeg;base64,/);199});200201test("resolveReferenceImages detects gif and webp mime types", async (t) => {202const dir = await fs.mkdtemp(path.join(os.tmpdir(), "agnes-mime-"));203t.after(() => fs.rm(dir, { recursive: true, force: true }));204205const webpPath = path.join(dir, "ref.webp");206const gifPath = path.join(dir, "ref.gif");207await fs.writeFile(webpPath, Buffer.from([0x00]));208await fs.writeFile(gifPath, Buffer.from([0x00]));209210const results = await resolveReferenceImages([webpPath, gifPath]);211assert.match(results[0]!, /^data:image\/webp;base64,/);212assert.match(results[1]!, /^data:image\/gif;base64,/);213});214