diff --git a/package.json b/package.json index 3a7699d..0526410 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "dependencies": { "@ai-sdk/anthropic": "^2.0.45", "@ai-sdk/google": "^2.0.39", + "@ai-sdk/openai": "^2.0.71", "@anthropic-ai/sdk": "^0.68.0", "@axe-core/puppeteer": "^4.10.2", "@genkit-ai/compat-oai": "1.23.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f0c1046..16ea310 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: '@ai-sdk/google': specifier: ^2.0.39 version: 2.0.39(zod@3.25.76) + '@ai-sdk/openai': + specifier: ^2.0.71 + version: 2.0.71(zod@3.25.76) '@anthropic-ai/sdk': specifier: ^0.68.0 version: 0.68.0(zod@3.25.76) @@ -268,6 +271,12 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 + '@ai-sdk/openai@2.0.71': + resolution: {integrity: sha512-tg+gj+R0z/On9P4V7hy7/7o04cQPjKGayMCL3gzWD/aNGjAKkhEnaocuNDidSnghizt8g2zJn16cAuAolnW+qQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + '@ai-sdk/provider-utils@3.0.17': resolution: {integrity: sha512-TR3Gs4I3Tym4Ll+EPdzRdvo/rc8Js6c4nVhFLuvGLX/Y4V9ZcQMa/HTiYsHEgmYrf1zVi6Q145UEZUfleOwOjw==} engines: {node: '>=18'} @@ -7404,6 +7413,12 @@ snapshots: '@ai-sdk/provider-utils': 3.0.17(zod@3.25.76) zod: 3.25.76 + '@ai-sdk/openai@2.0.71(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 2.0.0 + '@ai-sdk/provider-utils': 3.0.17(zod@3.25.76) + zod: 3.25.76 + '@ai-sdk/provider-utils@3.0.17(zod@3.25.76)': dependencies: '@ai-sdk/provider': 2.0.0 diff --git a/runner/codegen/ai-sdk-runner.ts b/runner/codegen/ai-sdk-runner.ts index db2d6f1..c033e34 100644 --- a/runner/codegen/ai-sdk-runner.ts +++ b/runner/codegen/ai-sdk-runner.ts @@ -19,6 +19,7 @@ import { } from 'ai'; import {google, GoogleGenerativeAIProviderOptions} from '@ai-sdk/google'; import {anthropic, AnthropicProviderOptions} from '@ai-sdk/anthropic'; +import {openai, OpenAIResponsesProviderOptions} from '@ai-sdk/openai'; import z from 'zod'; import {callWithTimeout} from '../utils/timeout.js'; import {combineAbortSignals} from '../utils/abort-signal.js'; @@ -32,6 +33,10 @@ const SUPPORTED_MODELS = [ 'gemini-2.5-flash', 'gemini-2.5-pro', 'gemini-3-pro-preview', + 'gpt-5.1-no-thinking', + 'gpt-5.1-thinking-low', + 'gpt-5.1-thinking-high', + 'gpt-5.1-thinking-medium', ] as const; // Increased to a very high value as we rely on an actual timeout @@ -133,9 +138,13 @@ export class AiSDKRunner implements LlmRunner { ); } - private async _getAiSdkModelOptions( - request: LocalLlmGenerateTextRequestOptions, - ): Promise<{model: LanguageModel; providerOptions: {}}> { + private async _getAiSdkModelOptions(request: LocalLlmGenerateTextRequestOptions): Promise<{ + model: LanguageModel; + providerOptions: + | {anthropic: AnthropicProviderOptions} + | {google: GoogleGenerativeAIProviderOptions} + | {openai: OpenAIResponsesProviderOptions}; + }> { const modelName = request.model as (typeof SUPPORTED_MODELS)[number]; switch (modelName) { case 'claude-opus-4.1-no-thinking': @@ -144,9 +153,11 @@ export class AiSDKRunner implements LlmRunner { return { model: anthropic('claude-opus-4-1'), providerOptions: { - sendReasoning: thinkingEnabled, - thinking: {type: thinkingEnabled ? 'enabled' : 'disabled'}, - } satisfies AnthropicProviderOptions, + anthropic: { + sendReasoning: thinkingEnabled, + thinking: {type: thinkingEnabled ? 'enabled' : 'disabled'}, + } satisfies AnthropicProviderOptions, + }, }; } case 'claude-sonnet-4.5-no-thinking': @@ -155,9 +166,11 @@ export class AiSDKRunner implements LlmRunner { return { model: anthropic('claude-sonnet-4-5'), providerOptions: { - sendReasoning: thinkingEnabled, - thinking: {type: thinkingEnabled ? 'enabled' : 'disabled'}, - } satisfies AnthropicProviderOptions, + anthropic: { + sendReasoning: thinkingEnabled, + thinking: {type: thinkingEnabled ? 'enabled' : 'disabled'}, + } satisfies AnthropicProviderOptions, + }, }; } case 'gemini-2.5-flash-lite': @@ -167,10 +180,33 @@ export class AiSDKRunner implements LlmRunner { return { model: google(modelName), providerOptions: { - thinkingConfig: { - includeThoughts: request.thinkingConfig?.includeThoughts, - }, - } satisfies GoogleGenerativeAIProviderOptions, + google: { + thinkingConfig: { + includeThoughts: request.thinkingConfig?.includeThoughts, + }, + } satisfies GoogleGenerativeAIProviderOptions, + }, + }; + case 'gpt-5.1-no-thinking': + case 'gpt-5.1-thinking-low': + case 'gpt-5.1-thinking-medium': + case 'gpt-5.1-thinking-high': + let reasoningEffort: string = 'none'; + if (modelName === 'gpt-5.1-thinking-high') { + reasoningEffort = 'high'; + } else if (modelName === 'gpt-5.1-thinking-medium') { + reasoningEffort = 'medium'; + } else if (modelName === 'gpt-5.1-thinking-low') { + reasoningEffort = 'low'; + } + return { + model: openai('gpt-5.1'), + providerOptions: { + openai: { + reasoningEffort, + reasoningSummary: 'detailed', + } satisfies OpenAIResponsesProviderOptions, + }, }; default: throw new Error(`Unexpected model in AI SDK runner: ${request.model}.`);