From 51b38ddbcd2b25e4ecad74d8a7d0a4c5935c1e5c Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Fri, 9 Oct 2026 20:12:56 +0000 Subject: [PATCH] fix(ads): move ad hero images off gpt-image-1 before its Oct 23 shutdown (#346) gpt-image-2.5-sunburst is OpenAI's listed replacement; same request shape, returns medium 1536x1024 b64_json (probed with the prod key). Bumps 0.3.4. Closes #346 Co-Authored-By: Claude Opus 5.5 --- lib/ads/creative.ts | 2 +- lib/ads/heroImage.ts | 7 ++++--- package.json | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/ads/creative.ts b/lib/ads/creative.ts index d31566d9..7f921508 100644 --- a/lib/ads/creative.ts +++ b/lib/ads/creative.ts @@ -494,7 +494,7 @@ export async function generateAdCreatives( anthropicEffort: "low", }); - // Hero image: the advertiser's og:image when it exists, else a gpt-image-1 + // Hero image: the advertiser's og:image when it exists, else a gpt-image-2.5 // fallback (only when we have a Supabase client to host the upload). Best- // effort — a failure just leaves the accent-tint background. let heroUrl: string | null = null; diff --git a/lib/ads/heroImage.ts b/lib/ads/heroImage.ts index 23aee087..f5e9662c 100644 --- a/lib/ads/heroImage.ts +++ b/lib/ads/heroImage.ts @@ -6,7 +6,7 @@ import { serviceClient } from "@/lib/supabase/service"; import type { SiteBrand } from "./brand"; // The ad hero image shown behind the Medium Rectangle. Chooses, in order: -// 1. a gpt-image-1 hero generated from the brand + ad copy, uploaded to the +// 1. a gpt-image-2.5 hero generated from the brand + ad copy, uploaded to the // public ad-assets bucket — purpose-built ad art reads far better than a // site's share image, so we prefer it. // 2. the advertiser's own og:image / share image (free, already hosted) as a @@ -15,7 +15,8 @@ import type { SiteBrand } from "./brand"; // accent-tinted wash, never a broken image. const ASSET_BUCKET = "ad-assets"; -const IMAGE_MODEL = "gpt-image-1"; +// gpt-image-1 is shut down by OpenAI on 2026-10-23 (#346). +const IMAGE_MODEL = "gpt-image-2.5-sunburst"; const VALIDATE_TIMEOUT_MS = 4000; const MIN_IMAGE_BYTES = 2000; // <2KB is almost certainly a tracking pixel/placeholder @@ -114,7 +115,7 @@ async function uploadHero(bytes: Buffer): Promise { return svc.storage.from(ASSET_BUCKET).getPublicUrl(path).data.publicUrl; } -// Resolve the hero image URL for a set of ad creatives. A gpt-image-1 hero +// Resolve the hero image URL for a set of ad creatives. A gpt-image-2.5 hero // first (purpose-built ad art), then the advertiser's og:image as a fallback // when AI is unavailable/fails. Returns null if neither works — the renderer // then uses the accent-tinted fallback. diff --git a/package.json b/package.json index 16e502e6..d2e37967 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "crawlproof", - "version": "0.3.3", + "version": "0.3.4", "bin": { "crawlproof": "./bin/crawlproof.mjs" },