diff --git a/.changeset/openai-gpt-image-2.md b/.changeset/openai-gpt-image-2.md new file mode 100644 index 000000000..bc987807e --- /dev/null +++ b/.changeset/openai-gpt-image-2.md @@ -0,0 +1,22 @@ +--- +'@tanstack/ai-openai': minor +--- + +Add `gpt-image-2` to the OpenAI image model list. The new model is exposed +through the same tree-shakeable `openaiImage` adapter as `gpt-image-1` and +shares its provider options (`quality`, `background`, `output_format`, +`output_compression`, `moderation`, `partial_images`) and size set +(`1024x1024`, `1536x1024`, `1024x1536`, `auto`). + +```ts +import { openaiImage } from '@tanstack/ai-openai/adapters' +import { generate } from '@tanstack/ai' + +const adapter = openaiImage({ apiKey: process.env.OPENAI_API_KEY! }) + +const result = await generate({ + adapter, + model: 'gpt-image-2', + prompt: 'A watercolor fox in a snowy forest', +}) +``` diff --git a/.changeset/openrouter-web-fetch-tool-capability.md b/.changeset/openrouter-web-fetch-tool-capability.md new file mode 100644 index 000000000..5054fe92d --- /dev/null +++ b/.changeset/openrouter-web-fetch-tool-capability.md @@ -0,0 +1,5 @@ +--- +'@tanstack/ai-openrouter': patch +--- + +Restore `web_fetch` in `OpenRouterChatModelToolCapabilitiesByName` so `webFetchTool()` is assignable to OpenRouter text adapters again. The recent model-metadata sync (#623) regenerated this map with `web_search` only, breaking the per-model type-safety tests added in #611. diff --git a/docs/media/image-generation.md b/docs/media/image-generation.md index 6c3c6e115..1fb23499f 100644 --- a/docs/media/image-generation.md +++ b/docs/media/image-generation.md @@ -90,6 +90,7 @@ All image adapters support these common options: | Model | Supported Sizes | |-------|----------------| +| `gpt-image-2` | `1024x1024`, `1536x1024`, `1024x1536`, `auto` | | `gpt-image-1` | `1024x1024`, `1536x1024`, `1024x1536`, `auto` | | `gpt-image-1-mini` | `1024x1024`, `1536x1024`, `1024x1536`, `auto` | | `dall-e-3` | `1024x1024`, `1792x1024`, `1024x1792` | @@ -138,11 +139,11 @@ const result = await generateImage({ OpenAI models support model-specific Model Options: -#### GPT-Image-1 / GPT-Image-1-Mini +#### GPT-Image-2 / GPT-Image-1 / GPT-Image-1-Mini ```typescript const result = await generateImage({ - adapter: openaiImage('gpt-image-1'), + adapter: openaiImage('gpt-image-2'), prompt: 'A cat wearing a hat', modelOptions: { quality: 'high', // 'high' | 'medium' | 'low' | 'auto' @@ -223,6 +224,7 @@ interface GeneratedImage { | Model | Images per Request | |-------|-------------------| +| `gpt-image-2` | 1-10 | | `gpt-image-1` | 1-10 | | `gpt-image-1-mini` | 1-10 | | `dall-e-3` | 1 | diff --git a/packages/typescript/ai-openai/src/adapters/image.ts b/packages/typescript/ai-openai/src/adapters/image.ts index 1380c7a26..bc4826305 100644 --- a/packages/typescript/ai-openai/src/adapters/image.ts +++ b/packages/typescript/ai-openai/src/adapters/image.ts @@ -31,7 +31,7 @@ export interface OpenAIImageConfig extends OpenAIClientConfig {} * OpenAI Image Generation Adapter * * Tree-shakeable adapter for OpenAI image generation functionality. - * Supports gpt-image-1, gpt-image-1-mini, dall-e-3, and dall-e-2 models. + * Supports gpt-image-2, gpt-image-1, gpt-image-1-mini, dall-e-3, and dall-e-2 models. * * Features: * - Model-specific type-safe provider options diff --git a/packages/typescript/ai-openai/src/image/image-provider-options.ts b/packages/typescript/ai-openai/src/image/image-provider-options.ts index a16281cfd..d6e221ec3 100644 --- a/packages/typescript/ai-openai/src/image/image-provider-options.ts +++ b/packages/typescript/ai-openai/src/image/image-provider-options.ts @@ -181,6 +181,7 @@ export type OpenAIImageProviderOptions = * Used by the core AI types to narrow providerOptions based on the selected model. */ export type OpenAIImageModelProviderOptionsByName = { + 'gpt-image-2': GptImage1ProviderOptions 'gpt-image-1': GptImage1ProviderOptions 'gpt-image-1-mini': GptImage1MiniProviderOptions 'dall-e-3': DallE3ProviderOptions @@ -191,6 +192,7 @@ export type OpenAIImageModelProviderOptionsByName = { * Type-only map from model name to its supported sizes. */ export type OpenAIImageModelSizeByName = { + 'gpt-image-2': GptImageSize 'gpt-image-1': GptImageSize 'gpt-image-1-mini': GptImageSize 'dall-e-3': DallE3Size @@ -217,6 +219,7 @@ export function validateImageSize( if (!size || size === 'auto') return const validSizes: Record> = { + 'gpt-image-2': ['1024x1024', '1536x1024', '1024x1536', 'auto'], 'gpt-image-1': ['1024x1024', '1536x1024', '1024x1536', 'auto'], 'gpt-image-1-mini': ['1024x1024', '1536x1024', '1024x1536', 'auto'], 'dall-e-3': ['1024x1024', '1792x1024', '1024x1792'], @@ -263,7 +266,7 @@ export function validateNumberOfImages( export const validateBackground = (options: ImageValidationOptions) => { if (options.background) { - const supportedModels = ['gpt-image-1', 'gpt-image-1-mini'] + const supportedModels = ['gpt-image-2', 'gpt-image-1', 'gpt-image-1-mini'] if (!supportedModels.includes(options.model)) { throw new Error( `The model ${options.model} does not support background option.`, @@ -277,11 +280,13 @@ export const validatePrompt = (options: ImageValidationOptions) => { throw new Error('Prompt cannot be empty.') } if ( - (options.model === 'gpt-image-1' || options.model === 'gpt-image-1-mini') && + (options.model === 'gpt-image-2' || + options.model === 'gpt-image-1' || + options.model === 'gpt-image-1-mini') && options.prompt.length > 32000 ) { throw new Error( - 'For gpt-image-1/gpt-image-1-mini, prompt length must be less than or equal to 32000 characters.', + 'For gpt-image-2/gpt-image-1/gpt-image-1-mini, prompt length must be less than or equal to 32000 characters.', ) } if (options.model === 'dall-e-2' && options.prompt.length > 1000) { diff --git a/packages/typescript/ai-openai/src/model-meta.ts b/packages/typescript/ai-openai/src/model-meta.ts index 1d6d0a06d..4ed863083 100644 --- a/packages/typescript/ai-openai/src/model-meta.ts +++ b/packages/typescript/ai-openai/src/model-meta.ts @@ -572,6 +572,28 @@ const GPT_IMAGE_1_MINI = { OpenAIBaseOptions & OpenAIStreamingOptions & OpenAIMetadataOptions > +const GPT_IMAGE_2 = { + name: 'gpt-image-2', + knowledge_cutoff: '2026-04-21', + pricing: { + input: { + normal: 5, + cached: 1.25, + }, + output: { + normal: 30, + }, + }, + supports: { + input: ['text', 'image'], + output: ['image'], + endpoints: ['image-generation', 'image-edit'], + features: [], + }, +} as const satisfies ModelMeta< + OpenAIBaseOptions & OpenAIStreamingOptions & OpenAIMetadataOptions +> + const O3_DEEP_RESEARCH = { name: 'o3-deep-research', context_window: 200_000, @@ -2217,6 +2239,7 @@ export type OpenAIChatModel = (typeof OPENAI_CHAT_MODELS)[number] // Image generation models (based on endpoints: "image-generation" or "image-edit") export const OPENAI_IMAGE_MODELS = [ + GPT_IMAGE_2.name, GPT_IMAGE_1.name, GPT_IMAGE_1_MINI.name, DALL_E_3.name, diff --git a/packages/typescript/ai-openrouter/src/model-meta.ts b/packages/typescript/ai-openrouter/src/model-meta.ts index bc273258a..cec4ced80 100644 --- a/packages/typescript/ai-openrouter/src/model-meta.ts +++ b/packages/typescript/ai-openrouter/src/model-meta.ts @@ -16379,7 +16379,10 @@ export const OPENROUTER_CHAT_MODELS = [ ] as const export type OpenRouterChatModelToolCapabilitiesByName = { - [K in (typeof OPENROUTER_CHAT_MODELS)[number]]: readonly ['web_search'] + [K in (typeof OPENROUTER_CHAT_MODELS)[number]]: readonly [ + 'web_search', + 'web_fetch', + ] } export const OPENROUTER_IMAGE_MODELS = [ diff --git a/packages/typescript/ai/skills/ai-core/media-generation/SKILL.md b/packages/typescript/ai/skills/ai-core/media-generation/SKILL.md index 0cd507a56..09a552b73 100644 --- a/packages/typescript/ai/skills/ai-core/media-generation/SKILL.md +++ b/packages/typescript/ai/skills/ai-core/media-generation/SKILL.md @@ -149,7 +149,7 @@ function ImageGenerator() { ### 1. Image Generation Supported adapters: `openaiImage` (dall-e-2, dall-e-3, gpt-image-1, -gpt-image-1-mini) and `geminiImage` (gemini-3.1-flash-image-preview, +gpt-image-1-mini, gpt-image-2) and `geminiImage` (gemini-3.1-flash-image-preview, imagen-4.0-generate-001, etc.). ```typescript