@fractaal/pi-ai 0.84.5 → 0.84.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"openai-responses.d.ts","sourceRoot":"","sources":["../../src/api/openai-responses.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,yCAAyC,CAAC;AAE7F,OAAO,KAAK,EASX,mBAAmB,EACnB,cAAc,EACd,aAAa,EAEb,MAAM,aAAa,CAAC;AA0ErB,MAAM,WAAW,sBAAuB,SAAQ,aAAa;IAC5D,eAAe,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;IAC1E,gBAAgB,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,IAAI,CAAC;IAC1D,WAAW,CAAC,EAAE,6BAA6B,CAAC,cAAc,CAAC,CAAC;IAC5D,UAAU,CAAC,EAAE,6BAA6B,CAAC,aAAa,CAAC,CAAC;CAC1D;AAED;;GAEG;AACH,eAAO,MAAM,MAAM,EAAE,cAAc,CAAC,kBAAkB,EAAE,sBAAsB,CA6F7E,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,kBAAkB,EAAE,mBAAmB,CAehF,CAAC","sourcesContent":["import OpenAI from \"openai\";\nimport type { ResponseCreateParamsStreaming } from \"openai/resources/responses/responses.js\";\nimport { clampThinkingLevel } from \"../models.ts\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tCacheRetention,\n\tContext,\n\tModel,\n\tOpenAIResponsesCompat,\n\tProviderEnv,\n\tProviderHeaders,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tUsage,\n} from \"../types.ts\";\nimport { splitDeferredTools } from \"../utils/deferred-tools.ts\";\nimport { formatProviderError, normalizeProviderError } from \"../utils/error-body.ts\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.ts\";\nimport { headersToRecord } from \"../utils/headers.ts\";\nimport { getProviderEnvValue } from \"../utils/provider-env.ts\";\nimport { retryProviderRequest } from \"../utils/provider-retry.ts\";\nimport { createGrammarToolInputProperties } from \"./constrained-sampling.ts\";\nimport { buildCopilotDynamicHeaders, hasCopilotVisionInput } from \"./github-copilot-headers.ts\";\nimport { clampOpenAIPromptCacheKey } from \"./openai-prompt-cache.ts\";\nimport { convertResponsesMessages, convertResponsesTools, processResponsesStream } from \"./openai-responses-shared.ts\";\nimport { buildBaseOptions } from \"./simple-options.ts\";\n\nconst OPENAI_TOOL_CALL_PROVIDERS = new Set([\"openai\", \"openai-codex\", \"opencode\"]);\n// OpenAI Responses rejects max_output_tokens below 16: https://github.com/earendil-works/pi/issues/6265\nconst OPENAI_RESPONSES_MIN_OUTPUT_TOKENS = 16;\n\nfunction hasHeader(headers: ProviderHeaders | undefined, name: string): boolean {\n\tif (!headers) return false;\n\tconst expected = name.toLowerCase();\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tif (key.toLowerCase() === expected && value !== null && value.trim().length > 0) return true;\n\t}\n\treturn false;\n}\n\nfunction getClientApiKey(provider: string, apiKey: string | undefined, headers: ProviderHeaders | undefined): string {\n\tif (apiKey) return apiKey;\n\tif (hasHeader(headers, \"authorization\") || hasHeader(headers, \"cf-aig-authorization\")) return \"unused\";\n\tthrow new Error(`No API key for provider: ${provider}`);\n}\n\nfunction detectSessionAffinityFormat(model: Pick<Model<\"openai-responses\">, \"provider\" | \"baseUrl\">) {\n\treturn model.provider === \"openrouter\" || model.baseUrl.includes(\"openrouter.ai\") ? \"openrouter\" : \"openai\";\n}\n\n/**\n * Resolve cache retention preference.\n * Defaults to \"short\" and uses PI_CACHE_RETENTION for backward compatibility.\n */\nfunction resolveCacheRetention(cacheRetention?: CacheRetention, env?: ProviderEnv): CacheRetention {\n\tif (cacheRetention) {\n\t\treturn cacheRetention;\n\t}\n\tif (getProviderEnvValue(\"PI_CACHE_RETENTION\", env) === \"long\") {\n\t\treturn \"long\";\n\t}\n\treturn \"short\";\n}\n\nfunction getCompat(model: Model<\"openai-responses\">): Required<OpenAIResponsesCompat> {\n\treturn {\n\t\tsupportsDeveloperRole: model.compat?.supportsDeveloperRole ?? true,\n\t\tsessionAffinityFormat: model.compat?.sessionAffinityFormat ?? detectSessionAffinityFormat(model),\n\t\tsupportsLongCacheRetention: model.compat?.supportsLongCacheRetention ?? true,\n\t\tsupportsStrictMode: model.compat?.supportsStrictMode ?? false,\n\t\tsupportsOpenAIGrammarTools: model.compat?.supportsOpenAIGrammarTools ?? false,\n\t\tsupportsToolSearch: model.compat?.supportsToolSearch ?? false,\n\t\tsupportsExplicitPromptCacheMode: model.compat?.supportsExplicitPromptCacheMode ?? false,\n\t};\n}\n\nfunction getPromptCacheRetention(\n\tcompat: Required<OpenAIResponsesCompat>,\n\tcacheRetention: CacheRetention,\n): \"24h\" | undefined {\n\treturn cacheRetention === \"long\" && compat.supportsLongCacheRetention ? \"24h\" : undefined;\n}\n\nfunction formatOpenAIResponsesError(error: unknown): string {\n\treturn formatProviderError(normalizeProviderError(error), \"OpenAI API error\");\n}\n\n// OpenAI Responses-specific options\nexport interface OpenAIResponsesOptions extends StreamOptions {\n\treasoningEffort?: \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\";\n\treasoningSummary?: \"auto\" | \"detailed\" | \"concise\" | null;\n\tserviceTier?: ResponseCreateParamsStreaming[\"service_tier\"];\n\ttoolChoice?: ResponseCreateParamsStreaming[\"tool_choice\"];\n}\n\n/**\n * Generate function for OpenAI Responses API\n */\nexport const stream: StreamFunction<\"openai-responses\", OpenAIResponsesOptions> = (\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions?: OpenAIResponsesOptions,\n): AssistantMessageEventStream => {\n\tconst stream = new AssistantMessageEventStream();\n\n\t// Start async processing\n\t(async () => {\n\t\tconst output: AssistantMessage = {\n\t\t\trole: \"assistant\",\n\t\t\tcontent: [],\n\t\t\tapi: model.api as Api,\n\t\t\tprovider: model.provider,\n\t\t\tmodel: model.id,\n\t\t\tusage: {\n\t\t\t\tinput: 0,\n\t\t\t\toutput: 0,\n\t\t\t\tcacheRead: 0,\n\t\t\t\tcacheWrite: 0,\n\t\t\t\ttotalTokens: 0,\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t},\n\t\t\tstopReason: \"pending\",\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\ttry {\n\t\t\t// Create OpenAI client\n\t\t\tconst apiKey = getClientApiKey(model.provider, options?.apiKey, options?.headers);\n\t\t\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);\n\t\t\tconst cacheSessionId = cacheRetention === \"none\" ? undefined : options?.sessionId;\n\t\t\tconst compat = getCompat(model);\n\t\t\tconst grammarToolInputProperties = createGrammarToolInputProperties(\n\t\t\t\tcontext.tools,\n\t\t\t\tcompat.supportsOpenAIGrammarTools,\n\t\t\t);\n\t\t\tconst client = createClient(model, context, apiKey, options?.headers, options?.fetch, cacheSessionId);\n\t\t\tlet params = buildParams(model, context, options, compat, grammarToolInputProperties);\n\t\t\tconst nextParams = await options?.onPayload?.(params, model);\n\t\t\tif (nextParams !== undefined) {\n\t\t\t\tparams = nextParams as ResponseCreateParamsStreaming;\n\t\t\t}\n\t\t\tconst requestOptions = {\n\t\t\t\t...(options?.signal ? { signal: options.signal } : {}),\n\t\t\t\t...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),\n\t\t\t\tmaxRetries: 0,\n\t\t\t};\n\t\t\tconst { data: openaiStream, response } = await retryProviderRequest(\n\t\t\t\t() => client.responses.create(params, requestOptions).withResponse(),\n\t\t\t\t{\n\t\t\t\t\tmaxRetries: options?.maxRetries,\n\t\t\t\t\tmaxRetryDelayMs: options?.maxRetryDelayMs,\n\t\t\t\t\tsignal: options?.signal,\n\t\t\t\t},\n\t\t\t);\n\t\t\tawait options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);\n\t\t\tstream.push({ type: \"start\", partial: output });\n\n\t\t\tawait processResponsesStream(openaiStream, output, stream, model, {\n\t\t\t\tserviceTier: options?.serviceTier,\n\t\t\t\tgrammarToolInputProperties,\n\t\t\t\tapplyServiceTierPricing: (usage, serviceTier) => applyServiceTierPricing(usage, serviceTier, model),\n\t\t\t});\n\n\t\t\tif (options?.signal?.aborted) {\n\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t}\n\n\t\t\tif (output.stopReason === \"pending\") {\n\t\t\t\tthrow new Error(\"OpenAI Responses stream ended without a stop reason\");\n\t\t\t}\n\t\t\tif (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n\t\t\t\tthrow new Error(\"An unknown error occurred\");\n\t\t\t}\n\n\t\t\tstream.push({ type: \"done\", reason: output.stopReason, message: output });\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\tfor (const block of output.content) {\n\t\t\t\tdelete (block as { index?: number }).index;\n\t\t\t\t// Streaming scratch buffers are only used during parsing; never persist them.\n\t\t\t\tdelete (block as { partialJson?: string }).partialJson;\n\t\t\t\tdelete (block as { customInput?: unknown }).customInput;\n\t\t\t}\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\toutput.errorMessage = formatOpenAIResponsesError(error);\n\t\t\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n};\n\nexport const streamSimple: StreamFunction<\"openai-responses\", SimpleStreamOptions> = (\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream => {\n\tgetClientApiKey(model.provider, options?.apiKey, options?.headers);\n\n\tconst base = buildBaseOptions(model, context, options, options?.apiKey);\n\tconst clampedReasoning = options?.reasoning ? clampThinkingLevel(model, options.reasoning) : undefined;\n\tconst reasoningEffort = clampedReasoning === \"off\" ? undefined : clampedReasoning;\n\n\treturn stream(model, context, {\n\t\t...base,\n\t\treasoningEffort,\n\t} satisfies OpenAIResponsesOptions);\n};\n\nfunction createClient(\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\tapiKey: string,\n\toptionsHeaders?: ProviderHeaders,\n\tfetch?: typeof globalThis.fetch,\n\tsessionId?: string,\n) {\n\tconst compat = getCompat(model);\n\tconst headers: ProviderHeaders = { ...model.headers };\n\tif (model.provider === \"github-copilot\") {\n\t\tconst hasImages = hasCopilotVisionInput(context.messages);\n\t\tconst copilotHeaders = buildCopilotDynamicHeaders({\n\t\t\tmessages: context.messages,\n\t\t\thasImages,\n\t\t});\n\t\tObject.assign(headers, copilotHeaders);\n\t}\n\n\tif (sessionId) {\n\t\tif (compat.sessionAffinityFormat === \"openrouter\") {\n\t\t\theaders[\"x-session-id\"] = sessionId;\n\t\t} else {\n\t\t\tif (compat.sessionAffinityFormat === \"openai\") {\n\t\t\t\theaders.session_id = sessionId;\n\t\t\t}\n\t\t\theaders[\"x-client-request-id\"] = sessionId;\n\t\t}\n\t}\n\n\t// Merge options headers last so they can override defaults\n\tif (optionsHeaders) {\n\t\tObject.assign(headers, optionsHeaders);\n\t}\n\n\treturn new OpenAI({\n\t\tapiKey,\n\t\tbaseURL: model.baseUrl,\n\t\tdangerouslyAllowBrowser: true,\n\t\tfetch,\n\t\tdefaultHeaders: headers,\n\t});\n}\n\nfunction buildParams(\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions: OpenAIResponsesOptions | undefined,\n\tcompat: Required<OpenAIResponsesCompat> = getCompat(model),\n\tgrammarToolInputProperties: ReadonlyMap<string, string> = createGrammarToolInputProperties(\n\t\tcontext.tools,\n\t\tcompat.supportsOpenAIGrammarTools,\n\t),\n) {\n\tconst toolPlacement = splitDeferredTools(context, compat.supportsToolSearch);\n\tconst messages = convertResponsesMessages(model, context, OPENAI_TOOL_CALL_PROVIDERS, {\n\t\tgrammarToolInputProperties,\n\t\tdeferredTools: toolPlacement.deferred,\n\t\ttoolOptions: {\n\t\t\tsupportsStrictMode: compat.supportsStrictMode,\n\t\t\tsupportsOpenAIGrammarTools: compat.supportsOpenAIGrammarTools,\n\t\t},\n\t});\n\n\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);\n\tconst disableImplicitPromptCache = cacheRetention === \"none\" && compat.supportsExplicitPromptCacheMode;\n\tconst params: ResponseCreateParamsStreaming & { prompt_cache_options?: { mode: \"explicit\" } } = {\n\t\tmodel: model.id,\n\t\tinput: messages,\n\t\tstream: true,\n\t\tprompt_cache_key: cacheRetention === \"none\" ? undefined : clampOpenAIPromptCacheKey(options?.sessionId),\n\t\tprompt_cache_retention: getPromptCacheRetention(compat, cacheRetention),\n\t\tprompt_cache_options: disableImplicitPromptCache ? { mode: \"explicit\" } : undefined,\n\t\tstore: false,\n\t};\n\n\tif (options?.maxTokens) {\n\t\tparams.max_output_tokens = Math.max(options.maxTokens, OPENAI_RESPONSES_MIN_OUTPUT_TOKENS);\n\t}\n\n\tif (options?.temperature !== undefined) {\n\t\tparams.temperature = options?.temperature;\n\t}\n\n\tif (options?.serviceTier !== undefined) {\n\t\tparams.service_tier = options.serviceTier;\n\t}\n\n\tif (toolPlacement.immediate.length > 0) {\n\t\tparams.tools = convertResponsesTools(toolPlacement.immediate, {\n\t\t\tsupportsStrictMode: compat.supportsStrictMode,\n\t\t\tsupportsOpenAIGrammarTools: compat.supportsOpenAIGrammarTools,\n\t\t});\n\t}\n\n\tif (options?.toolChoice !== undefined) {\n\t\tparams.tool_choice = options.toolChoice;\n\t}\n\n\tif (model.reasoning) {\n\t\tif (options?.reasoningEffort || options?.reasoningSummary) {\n\t\t\tconst effort = options?.reasoningEffort\n\t\t\t\t? (model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort)\n\t\t\t\t: \"medium\";\n\t\t\tparams.reasoning = {\n\t\t\t\teffort: effort as NonNullable<typeof params.reasoning>[\"effort\"],\n\t\t\t\tsummary: options?.reasoningSummary || \"auto\",\n\t\t\t};\n\t\t\tparams.include = [\"reasoning.encrypted_content\"];\n\t\t} else if (model.provider !== \"github-copilot\" && model.thinkingLevelMap?.off !== null) {\n\t\t\tparams.reasoning = {\n\t\t\t\teffort: (model.thinkingLevelMap?.off ?? \"none\") as NonNullable<typeof params.reasoning>[\"effort\"],\n\t\t\t};\n\t\t}\n\t\tif (model.provider === \"xai\") params.include = [\"reasoning.encrypted_content\"];\n\t}\n\n\treturn params;\n}\n\nfunction getServiceTierCostMultiplier(\n\tmodel: Pick<Model<\"openai-responses\">, \"id\">,\n\tserviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined,\n): number {\n\tswitch (serviceTier) {\n\t\tcase \"flex\":\n\t\t\treturn 0.5;\n\t\tcase \"priority\":\n\t\t\treturn model.id === \"gpt-5.5\" ? 2.5 : 2;\n\t\tdefault:\n\t\t\treturn 1;\n\t}\n}\n\nfunction applyServiceTierPricing(\n\tusage: Usage,\n\tserviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined,\n\tmodel: Pick<Model<\"openai-responses\">, \"id\">,\n) {\n\tconst multiplier = getServiceTierCostMultiplier(model, serviceTier);\n\tif (multiplier === 1) return;\n\n\tusage.cost.input *= multiplier;\n\tusage.cost.output *= multiplier;\n\tusage.cost.cacheRead *= multiplier;\n\tusage.cost.cacheWrite *= multiplier;\n\tusage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;\n}\n"]}
1
+ {"version":3,"file":"openai-responses.d.ts","sourceRoot":"","sources":["../../src/api/openai-responses.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,yCAAyC,CAAC;AAE7F,OAAO,KAAK,EASX,mBAAmB,EACnB,cAAc,EACd,aAAa,EAEb,MAAM,aAAa,CAAC;AAsFrB,MAAM,WAAW,sBAAuB,SAAQ,aAAa;IAC5D,eAAe,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;IAC1E,gBAAgB,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,IAAI,CAAC;IAC1D,WAAW,CAAC,EAAE,6BAA6B,CAAC,cAAc,CAAC,CAAC;IAC5D,UAAU,CAAC,EAAE,6BAA6B,CAAC,aAAa,CAAC,CAAC;CAC1D;AAED;;GAEG;AACH,eAAO,MAAM,MAAM,EAAE,cAAc,CAAC,kBAAkB,EAAE,sBAAsB,CA6F7E,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,kBAAkB,EAAE,mBAAmB,CAehF,CAAC","sourcesContent":["import OpenAI from \"openai\";\nimport type { ResponseCreateParamsStreaming } from \"openai/resources/responses/responses.js\";\nimport { clampThinkingLevel } from \"../models.ts\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tCacheRetention,\n\tContext,\n\tModel,\n\tOpenAIResponsesCompat,\n\tProviderEnv,\n\tProviderHeaders,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tUsage,\n} from \"../types.ts\";\nimport { splitDeferredTools } from \"../utils/deferred-tools.ts\";\nimport { formatProviderError, normalizeProviderError } from \"../utils/error-body.ts\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.ts\";\nimport { headersToRecord } from \"../utils/headers.ts\";\nimport { getProviderEnvValue } from \"../utils/provider-env.ts\";\nimport { retryProviderRequest } from \"../utils/provider-retry.ts\";\nimport { createGrammarToolInputProperties } from \"./constrained-sampling.ts\";\nimport { buildCopilotDynamicHeaders, hasCopilotVisionInput } from \"./github-copilot-headers.ts\";\nimport { clampOpenAIPromptCacheKey } from \"./openai-prompt-cache.ts\";\nimport { convertResponsesMessages, convertResponsesTools, processResponsesStream } from \"./openai-responses-shared.ts\";\nimport { buildBaseOptions } from \"./simple-options.ts\";\n\nconst OPENAI_TOOL_CALL_PROVIDERS = new Set([\"openai\", \"openai-codex\", \"opencode\"]);\n// OpenAI Responses rejects max_output_tokens below 16: https://github.com/earendil-works/pi/issues/6265\nconst OPENAI_RESPONSES_MIN_OUTPUT_TOKENS = 16;\n\nfunction hasHeader(headers: ProviderHeaders | undefined, name: string): boolean {\n\tif (!headers) return false;\n\tconst expected = name.toLowerCase();\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tif (key.toLowerCase() === expected && value !== null && value.trim().length > 0) return true;\n\t}\n\treturn false;\n}\n\nfunction getClientApiKey(provider: string, apiKey: string | undefined, headers: ProviderHeaders | undefined): string {\n\tif (apiKey) return apiKey;\n\tif (hasHeader(headers, \"authorization\") || hasHeader(headers, \"cf-aig-authorization\")) return \"unused\";\n\tthrow new Error(`No API key for provider: ${provider}`);\n}\n\nfunction detectSessionAffinityFormat(model: Pick<Model<\"openai-responses\">, \"provider\" | \"baseUrl\">) {\n\treturn model.provider === \"openrouter\" || model.baseUrl.includes(\"openrouter.ai\") ? \"openrouter\" : \"openai\";\n}\n\n/**\n * Resolve cache retention preference.\n * Defaults to \"short\" and uses PI_CACHE_RETENTION for backward compatibility.\n */\nfunction resolveCacheRetention(cacheRetention?: CacheRetention, env?: ProviderEnv): CacheRetention {\n\tif (cacheRetention) {\n\t\treturn cacheRetention;\n\t}\n\tif (getProviderEnvValue(\"PI_CACHE_RETENTION\", env) === \"long\") {\n\t\treturn \"long\";\n\t}\n\treturn \"short\";\n}\n\nfunction getCompat(model: Model<\"openai-responses\">): Required<OpenAIResponsesCompat> {\n\treturn {\n\t\tsupportsDeveloperRole: model.compat?.supportsDeveloperRole ?? true,\n\t\tsessionAffinityFormat: model.compat?.sessionAffinityFormat ?? detectSessionAffinityFormat(model),\n\t\tsupportsLongCacheRetention: model.compat?.supportsLongCacheRetention ?? true,\n\t\tsupportsStrictMode: model.compat?.supportsStrictMode ?? false,\n\t\tsupportsOpenAIGrammarTools: model.compat?.supportsOpenAIGrammarTools ?? false,\n\t\tsupportsToolSearch: model.compat?.supportsToolSearch ?? false,\n\t\tsupportsExplicitPromptCacheMode: model.compat?.supportsExplicitPromptCacheMode ?? false,\n\t};\n}\n\nfunction getPromptCacheRetention(\n\tcompat: Required<OpenAIResponsesCompat>,\n\tcacheRetention: CacheRetention,\n): \"24h\" | undefined {\n\treturn cacheRetention === \"long\" && compat.supportsLongCacheRetention && !compat.supportsExplicitPromptCacheMode\n\t\t? \"24h\"\n\t\t: undefined;\n}\n\nfunction getPromptCacheOptions(\n\tcompat: Required<OpenAIResponsesCompat>,\n\tcacheRetention: CacheRetention,\n): { mode?: \"explicit\"; ttl?: \"30m\" } | undefined {\n\tif (!compat.supportsExplicitPromptCacheMode) return undefined;\n\tif (cacheRetention === \"none\") return { mode: \"explicit\" };\n\tif (cacheRetention === \"long\" && compat.supportsLongCacheRetention) return { ttl: \"30m\" };\n\treturn undefined;\n}\n\nfunction formatOpenAIResponsesError(error: unknown): string {\n\treturn formatProviderError(normalizeProviderError(error), \"OpenAI API error\");\n}\n\n// OpenAI Responses-specific options\nexport interface OpenAIResponsesOptions extends StreamOptions {\n\treasoningEffort?: \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\";\n\treasoningSummary?: \"auto\" | \"detailed\" | \"concise\" | null;\n\tserviceTier?: ResponseCreateParamsStreaming[\"service_tier\"];\n\ttoolChoice?: ResponseCreateParamsStreaming[\"tool_choice\"];\n}\n\n/**\n * Generate function for OpenAI Responses API\n */\nexport const stream: StreamFunction<\"openai-responses\", OpenAIResponsesOptions> = (\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions?: OpenAIResponsesOptions,\n): AssistantMessageEventStream => {\n\tconst stream = new AssistantMessageEventStream();\n\n\t// Start async processing\n\t(async () => {\n\t\tconst output: AssistantMessage = {\n\t\t\trole: \"assistant\",\n\t\t\tcontent: [],\n\t\t\tapi: model.api as Api,\n\t\t\tprovider: model.provider,\n\t\t\tmodel: model.id,\n\t\t\tusage: {\n\t\t\t\tinput: 0,\n\t\t\t\toutput: 0,\n\t\t\t\tcacheRead: 0,\n\t\t\t\tcacheWrite: 0,\n\t\t\t\ttotalTokens: 0,\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t},\n\t\t\tstopReason: \"pending\",\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\ttry {\n\t\t\t// Create OpenAI client\n\t\t\tconst apiKey = getClientApiKey(model.provider, options?.apiKey, options?.headers);\n\t\t\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);\n\t\t\tconst cacheSessionId = cacheRetention === \"none\" ? undefined : options?.sessionId;\n\t\t\tconst compat = getCompat(model);\n\t\t\tconst grammarToolInputProperties = createGrammarToolInputProperties(\n\t\t\t\tcontext.tools,\n\t\t\t\tcompat.supportsOpenAIGrammarTools,\n\t\t\t);\n\t\t\tconst client = createClient(model, context, apiKey, options?.headers, options?.fetch, cacheSessionId);\n\t\t\tlet params = buildParams(model, context, options, compat, grammarToolInputProperties);\n\t\t\tconst nextParams = await options?.onPayload?.(params, model);\n\t\t\tif (nextParams !== undefined) {\n\t\t\t\tparams = nextParams as ResponseCreateParamsStreaming;\n\t\t\t}\n\t\t\tconst requestOptions = {\n\t\t\t\t...(options?.signal ? { signal: options.signal } : {}),\n\t\t\t\t...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),\n\t\t\t\tmaxRetries: 0,\n\t\t\t};\n\t\t\tconst { data: openaiStream, response } = await retryProviderRequest(\n\t\t\t\t() => client.responses.create(params, requestOptions).withResponse(),\n\t\t\t\t{\n\t\t\t\t\tmaxRetries: options?.maxRetries,\n\t\t\t\t\tmaxRetryDelayMs: options?.maxRetryDelayMs,\n\t\t\t\t\tsignal: options?.signal,\n\t\t\t\t},\n\t\t\t);\n\t\t\tawait options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);\n\t\t\tstream.push({ type: \"start\", partial: output });\n\n\t\t\tawait processResponsesStream(openaiStream, output, stream, model, {\n\t\t\t\tserviceTier: options?.serviceTier,\n\t\t\t\tgrammarToolInputProperties,\n\t\t\t\tapplyServiceTierPricing: (usage, serviceTier) => applyServiceTierPricing(usage, serviceTier, model),\n\t\t\t});\n\n\t\t\tif (options?.signal?.aborted) {\n\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t}\n\n\t\t\tif (output.stopReason === \"pending\") {\n\t\t\t\tthrow new Error(\"OpenAI Responses stream ended without a stop reason\");\n\t\t\t}\n\t\t\tif (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n\t\t\t\tthrow new Error(\"An unknown error occurred\");\n\t\t\t}\n\n\t\t\tstream.push({ type: \"done\", reason: output.stopReason, message: output });\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\tfor (const block of output.content) {\n\t\t\t\tdelete (block as { index?: number }).index;\n\t\t\t\t// Streaming scratch buffers are only used during parsing; never persist them.\n\t\t\t\tdelete (block as { partialJson?: string }).partialJson;\n\t\t\t\tdelete (block as { customInput?: unknown }).customInput;\n\t\t\t}\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\toutput.errorMessage = formatOpenAIResponsesError(error);\n\t\t\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n};\n\nexport const streamSimple: StreamFunction<\"openai-responses\", SimpleStreamOptions> = (\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream => {\n\tgetClientApiKey(model.provider, options?.apiKey, options?.headers);\n\n\tconst base = buildBaseOptions(model, context, options, options?.apiKey);\n\tconst clampedReasoning = options?.reasoning ? clampThinkingLevel(model, options.reasoning) : undefined;\n\tconst reasoningEffort = clampedReasoning === \"off\" ? undefined : clampedReasoning;\n\n\treturn stream(model, context, {\n\t\t...base,\n\t\treasoningEffort,\n\t} satisfies OpenAIResponsesOptions);\n};\n\nfunction createClient(\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\tapiKey: string,\n\toptionsHeaders?: ProviderHeaders,\n\tfetch?: typeof globalThis.fetch,\n\tsessionId?: string,\n) {\n\tconst compat = getCompat(model);\n\tconst headers: ProviderHeaders = { ...model.headers };\n\tif (model.provider === \"github-copilot\") {\n\t\tconst hasImages = hasCopilotVisionInput(context.messages);\n\t\tconst copilotHeaders = buildCopilotDynamicHeaders({\n\t\t\tmessages: context.messages,\n\t\t\thasImages,\n\t\t});\n\t\tObject.assign(headers, copilotHeaders);\n\t}\n\n\tif (sessionId) {\n\t\tif (compat.sessionAffinityFormat === \"openrouter\") {\n\t\t\theaders[\"x-session-id\"] = sessionId;\n\t\t} else {\n\t\t\tif (compat.sessionAffinityFormat === \"openai\") {\n\t\t\t\theaders.session_id = sessionId;\n\t\t\t}\n\t\t\theaders[\"x-client-request-id\"] = sessionId;\n\t\t}\n\t}\n\n\t// Merge options headers last so they can override defaults\n\tif (optionsHeaders) {\n\t\tObject.assign(headers, optionsHeaders);\n\t}\n\n\treturn new OpenAI({\n\t\tapiKey,\n\t\tbaseURL: model.baseUrl,\n\t\tdangerouslyAllowBrowser: true,\n\t\tfetch,\n\t\tdefaultHeaders: headers,\n\t});\n}\n\nfunction buildParams(\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions: OpenAIResponsesOptions | undefined,\n\tcompat: Required<OpenAIResponsesCompat> = getCompat(model),\n\tgrammarToolInputProperties: ReadonlyMap<string, string> = createGrammarToolInputProperties(\n\t\tcontext.tools,\n\t\tcompat.supportsOpenAIGrammarTools,\n\t),\n) {\n\tconst toolPlacement = splitDeferredTools(context, compat.supportsToolSearch);\n\tconst messages = convertResponsesMessages(model, context, OPENAI_TOOL_CALL_PROVIDERS, {\n\t\tgrammarToolInputProperties,\n\t\tdeferredTools: toolPlacement.deferred,\n\t\ttoolOptions: {\n\t\t\tsupportsStrictMode: compat.supportsStrictMode,\n\t\t\tsupportsOpenAIGrammarTools: compat.supportsOpenAIGrammarTools,\n\t\t},\n\t});\n\n\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);\n\tconst params: ResponseCreateParamsStreaming & {\n\t\tprompt_cache_options?: { mode?: \"explicit\"; ttl?: \"30m\" };\n\t} = {\n\t\tmodel: model.id,\n\t\tinput: messages,\n\t\tstream: true,\n\t\tprompt_cache_key: cacheRetention === \"none\" ? undefined : clampOpenAIPromptCacheKey(options?.sessionId),\n\t\tprompt_cache_retention: getPromptCacheRetention(compat, cacheRetention),\n\t\tprompt_cache_options: getPromptCacheOptions(compat, cacheRetention),\n\t\tstore: false,\n\t};\n\n\tif (options?.maxTokens) {\n\t\tparams.max_output_tokens = Math.max(options.maxTokens, OPENAI_RESPONSES_MIN_OUTPUT_TOKENS);\n\t}\n\n\tif (options?.temperature !== undefined) {\n\t\tparams.temperature = options?.temperature;\n\t}\n\n\tif (options?.serviceTier !== undefined) {\n\t\tparams.service_tier = options.serviceTier;\n\t}\n\n\tif (toolPlacement.immediate.length > 0) {\n\t\tparams.tools = convertResponsesTools(toolPlacement.immediate, {\n\t\t\tsupportsStrictMode: compat.supportsStrictMode,\n\t\t\tsupportsOpenAIGrammarTools: compat.supportsOpenAIGrammarTools,\n\t\t});\n\t}\n\n\tif (options?.toolChoice !== undefined) {\n\t\tparams.tool_choice = options.toolChoice;\n\t}\n\n\tif (model.reasoning) {\n\t\tif (options?.reasoningEffort || options?.reasoningSummary) {\n\t\t\tconst effort = options?.reasoningEffort\n\t\t\t\t? (model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort)\n\t\t\t\t: \"medium\";\n\t\t\tparams.reasoning = {\n\t\t\t\teffort: effort as NonNullable<typeof params.reasoning>[\"effort\"],\n\t\t\t\tsummary: options?.reasoningSummary || \"auto\",\n\t\t\t};\n\t\t\tparams.include = [\"reasoning.encrypted_content\"];\n\t\t} else if (model.provider !== \"github-copilot\" && model.thinkingLevelMap?.off !== null) {\n\t\t\tparams.reasoning = {\n\t\t\t\teffort: (model.thinkingLevelMap?.off ?? \"none\") as NonNullable<typeof params.reasoning>[\"effort\"],\n\t\t\t};\n\t\t}\n\t\tif (model.provider === \"xai\") params.include = [\"reasoning.encrypted_content\"];\n\t}\n\n\treturn params;\n}\n\nfunction getServiceTierCostMultiplier(\n\tmodel: Pick<Model<\"openai-responses\">, \"id\">,\n\tserviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined,\n): number {\n\tswitch (serviceTier) {\n\t\tcase \"flex\":\n\t\t\treturn 0.5;\n\t\tcase \"priority\":\n\t\t\treturn model.id === \"gpt-5.5\" ? 2.5 : 2;\n\t\tdefault:\n\t\t\treturn 1;\n\t}\n}\n\nfunction applyServiceTierPricing(\n\tusage: Usage,\n\tserviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined,\n\tmodel: Pick<Model<\"openai-responses\">, \"id\">,\n) {\n\tconst multiplier = getServiceTierCostMultiplier(model, serviceTier);\n\tif (multiplier === 1) return;\n\n\tusage.cost.input *= multiplier;\n\tusage.cost.output *= multiplier;\n\tusage.cost.cacheRead *= multiplier;\n\tusage.cost.cacheWrite *= multiplier;\n\tusage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;\n}\n"]}
@@ -59,7 +59,18 @@ function getCompat(model) {
59
59
  };
60
60
  }
61
61
  function getPromptCacheRetention(compat, cacheRetention) {
62
- return cacheRetention === "long" && compat.supportsLongCacheRetention ? "24h" : undefined;
62
+ return cacheRetention === "long" && compat.supportsLongCacheRetention && !compat.supportsExplicitPromptCacheMode
63
+ ? "24h"
64
+ : undefined;
65
+ }
66
+ function getPromptCacheOptions(compat, cacheRetention) {
67
+ if (!compat.supportsExplicitPromptCacheMode)
68
+ return undefined;
69
+ if (cacheRetention === "none")
70
+ return { mode: "explicit" };
71
+ if (cacheRetention === "long" && compat.supportsLongCacheRetention)
72
+ return { ttl: "30m" };
73
+ return undefined;
63
74
  }
64
75
  function formatOpenAIResponsesError(error) {
65
76
  return formatProviderError(normalizeProviderError(error), "OpenAI API error");
@@ -200,14 +211,13 @@ function buildParams(model, context, options, compat = getCompat(model), grammar
200
211
  },
201
212
  });
202
213
  const cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);
203
- const disableImplicitPromptCache = cacheRetention === "none" && compat.supportsExplicitPromptCacheMode;
204
214
  const params = {
205
215
  model: model.id,
206
216
  input: messages,
207
217
  stream: true,
208
218
  prompt_cache_key: cacheRetention === "none" ? undefined : clampOpenAIPromptCacheKey(options?.sessionId),
209
219
  prompt_cache_retention: getPromptCacheRetention(compat, cacheRetention),
210
- prompt_cache_options: disableImplicitPromptCache ? { mode: "explicit" } : undefined,
220
+ prompt_cache_options: getPromptCacheOptions(compat, cacheRetention),
211
221
  store: false,
212
222
  };
213
223
  if (options?.maxTokens) {
@@ -1 +1 @@
1
- {"version":3,"file":"openai-responses.js","sourceRoot":"","sources":["../../src/api/openai-responses.ts"],"names":[],"mappings":"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","sourcesContent":["import OpenAI from \"openai\";\nimport type { ResponseCreateParamsStreaming } from \"openai/resources/responses/responses.js\";\nimport { clampThinkingLevel } from \"../models.ts\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tCacheRetention,\n\tContext,\n\tModel,\n\tOpenAIResponsesCompat,\n\tProviderEnv,\n\tProviderHeaders,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tUsage,\n} from \"../types.ts\";\nimport { splitDeferredTools } from \"../utils/deferred-tools.ts\";\nimport { formatProviderError, normalizeProviderError } from \"../utils/error-body.ts\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.ts\";\nimport { headersToRecord } from \"../utils/headers.ts\";\nimport { getProviderEnvValue } from \"../utils/provider-env.ts\";\nimport { retryProviderRequest } from \"../utils/provider-retry.ts\";\nimport { createGrammarToolInputProperties } from \"./constrained-sampling.ts\";\nimport { buildCopilotDynamicHeaders, hasCopilotVisionInput } from \"./github-copilot-headers.ts\";\nimport { clampOpenAIPromptCacheKey } from \"./openai-prompt-cache.ts\";\nimport { convertResponsesMessages, convertResponsesTools, processResponsesStream } from \"./openai-responses-shared.ts\";\nimport { buildBaseOptions } from \"./simple-options.ts\";\n\nconst OPENAI_TOOL_CALL_PROVIDERS = new Set([\"openai\", \"openai-codex\", \"opencode\"]);\n// OpenAI Responses rejects max_output_tokens below 16: https://github.com/earendil-works/pi/issues/6265\nconst OPENAI_RESPONSES_MIN_OUTPUT_TOKENS = 16;\n\nfunction hasHeader(headers: ProviderHeaders | undefined, name: string): boolean {\n\tif (!headers) return false;\n\tconst expected = name.toLowerCase();\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tif (key.toLowerCase() === expected && value !== null && value.trim().length > 0) return true;\n\t}\n\treturn false;\n}\n\nfunction getClientApiKey(provider: string, apiKey: string | undefined, headers: ProviderHeaders | undefined): string {\n\tif (apiKey) return apiKey;\n\tif (hasHeader(headers, \"authorization\") || hasHeader(headers, \"cf-aig-authorization\")) return \"unused\";\n\tthrow new Error(`No API key for provider: ${provider}`);\n}\n\nfunction detectSessionAffinityFormat(model: Pick<Model<\"openai-responses\">, \"provider\" | \"baseUrl\">) {\n\treturn model.provider === \"openrouter\" || model.baseUrl.includes(\"openrouter.ai\") ? \"openrouter\" : \"openai\";\n}\n\n/**\n * Resolve cache retention preference.\n * Defaults to \"short\" and uses PI_CACHE_RETENTION for backward compatibility.\n */\nfunction resolveCacheRetention(cacheRetention?: CacheRetention, env?: ProviderEnv): CacheRetention {\n\tif (cacheRetention) {\n\t\treturn cacheRetention;\n\t}\n\tif (getProviderEnvValue(\"PI_CACHE_RETENTION\", env) === \"long\") {\n\t\treturn \"long\";\n\t}\n\treturn \"short\";\n}\n\nfunction getCompat(model: Model<\"openai-responses\">): Required<OpenAIResponsesCompat> {\n\treturn {\n\t\tsupportsDeveloperRole: model.compat?.supportsDeveloperRole ?? true,\n\t\tsessionAffinityFormat: model.compat?.sessionAffinityFormat ?? detectSessionAffinityFormat(model),\n\t\tsupportsLongCacheRetention: model.compat?.supportsLongCacheRetention ?? true,\n\t\tsupportsStrictMode: model.compat?.supportsStrictMode ?? false,\n\t\tsupportsOpenAIGrammarTools: model.compat?.supportsOpenAIGrammarTools ?? false,\n\t\tsupportsToolSearch: model.compat?.supportsToolSearch ?? false,\n\t\tsupportsExplicitPromptCacheMode: model.compat?.supportsExplicitPromptCacheMode ?? false,\n\t};\n}\n\nfunction getPromptCacheRetention(\n\tcompat: Required<OpenAIResponsesCompat>,\n\tcacheRetention: CacheRetention,\n): \"24h\" | undefined {\n\treturn cacheRetention === \"long\" && compat.supportsLongCacheRetention ? \"24h\" : undefined;\n}\n\nfunction formatOpenAIResponsesError(error: unknown): string {\n\treturn formatProviderError(normalizeProviderError(error), \"OpenAI API error\");\n}\n\n// OpenAI Responses-specific options\nexport interface OpenAIResponsesOptions extends StreamOptions {\n\treasoningEffort?: \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\";\n\treasoningSummary?: \"auto\" | \"detailed\" | \"concise\" | null;\n\tserviceTier?: ResponseCreateParamsStreaming[\"service_tier\"];\n\ttoolChoice?: ResponseCreateParamsStreaming[\"tool_choice\"];\n}\n\n/**\n * Generate function for OpenAI Responses API\n */\nexport const stream: StreamFunction<\"openai-responses\", OpenAIResponsesOptions> = (\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions?: OpenAIResponsesOptions,\n): AssistantMessageEventStream => {\n\tconst stream = new AssistantMessageEventStream();\n\n\t// Start async processing\n\t(async () => {\n\t\tconst output: AssistantMessage = {\n\t\t\trole: \"assistant\",\n\t\t\tcontent: [],\n\t\t\tapi: model.api as Api,\n\t\t\tprovider: model.provider,\n\t\t\tmodel: model.id,\n\t\t\tusage: {\n\t\t\t\tinput: 0,\n\t\t\t\toutput: 0,\n\t\t\t\tcacheRead: 0,\n\t\t\t\tcacheWrite: 0,\n\t\t\t\ttotalTokens: 0,\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t},\n\t\t\tstopReason: \"pending\",\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\ttry {\n\t\t\t// Create OpenAI client\n\t\t\tconst apiKey = getClientApiKey(model.provider, options?.apiKey, options?.headers);\n\t\t\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);\n\t\t\tconst cacheSessionId = cacheRetention === \"none\" ? undefined : options?.sessionId;\n\t\t\tconst compat = getCompat(model);\n\t\t\tconst grammarToolInputProperties = createGrammarToolInputProperties(\n\t\t\t\tcontext.tools,\n\t\t\t\tcompat.supportsOpenAIGrammarTools,\n\t\t\t);\n\t\t\tconst client = createClient(model, context, apiKey, options?.headers, options?.fetch, cacheSessionId);\n\t\t\tlet params = buildParams(model, context, options, compat, grammarToolInputProperties);\n\t\t\tconst nextParams = await options?.onPayload?.(params, model);\n\t\t\tif (nextParams !== undefined) {\n\t\t\t\tparams = nextParams as ResponseCreateParamsStreaming;\n\t\t\t}\n\t\t\tconst requestOptions = {\n\t\t\t\t...(options?.signal ? { signal: options.signal } : {}),\n\t\t\t\t...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),\n\t\t\t\tmaxRetries: 0,\n\t\t\t};\n\t\t\tconst { data: openaiStream, response } = await retryProviderRequest(\n\t\t\t\t() => client.responses.create(params, requestOptions).withResponse(),\n\t\t\t\t{\n\t\t\t\t\tmaxRetries: options?.maxRetries,\n\t\t\t\t\tmaxRetryDelayMs: options?.maxRetryDelayMs,\n\t\t\t\t\tsignal: options?.signal,\n\t\t\t\t},\n\t\t\t);\n\t\t\tawait options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);\n\t\t\tstream.push({ type: \"start\", partial: output });\n\n\t\t\tawait processResponsesStream(openaiStream, output, stream, model, {\n\t\t\t\tserviceTier: options?.serviceTier,\n\t\t\t\tgrammarToolInputProperties,\n\t\t\t\tapplyServiceTierPricing: (usage, serviceTier) => applyServiceTierPricing(usage, serviceTier, model),\n\t\t\t});\n\n\t\t\tif (options?.signal?.aborted) {\n\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t}\n\n\t\t\tif (output.stopReason === \"pending\") {\n\t\t\t\tthrow new Error(\"OpenAI Responses stream ended without a stop reason\");\n\t\t\t}\n\t\t\tif (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n\t\t\t\tthrow new Error(\"An unknown error occurred\");\n\t\t\t}\n\n\t\t\tstream.push({ type: \"done\", reason: output.stopReason, message: output });\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\tfor (const block of output.content) {\n\t\t\t\tdelete (block as { index?: number }).index;\n\t\t\t\t// Streaming scratch buffers are only used during parsing; never persist them.\n\t\t\t\tdelete (block as { partialJson?: string }).partialJson;\n\t\t\t\tdelete (block as { customInput?: unknown }).customInput;\n\t\t\t}\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\toutput.errorMessage = formatOpenAIResponsesError(error);\n\t\t\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n};\n\nexport const streamSimple: StreamFunction<\"openai-responses\", SimpleStreamOptions> = (\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream => {\n\tgetClientApiKey(model.provider, options?.apiKey, options?.headers);\n\n\tconst base = buildBaseOptions(model, context, options, options?.apiKey);\n\tconst clampedReasoning = options?.reasoning ? clampThinkingLevel(model, options.reasoning) : undefined;\n\tconst reasoningEffort = clampedReasoning === \"off\" ? undefined : clampedReasoning;\n\n\treturn stream(model, context, {\n\t\t...base,\n\t\treasoningEffort,\n\t} satisfies OpenAIResponsesOptions);\n};\n\nfunction createClient(\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\tapiKey: string,\n\toptionsHeaders?: ProviderHeaders,\n\tfetch?: typeof globalThis.fetch,\n\tsessionId?: string,\n) {\n\tconst compat = getCompat(model);\n\tconst headers: ProviderHeaders = { ...model.headers };\n\tif (model.provider === \"github-copilot\") {\n\t\tconst hasImages = hasCopilotVisionInput(context.messages);\n\t\tconst copilotHeaders = buildCopilotDynamicHeaders({\n\t\t\tmessages: context.messages,\n\t\t\thasImages,\n\t\t});\n\t\tObject.assign(headers, copilotHeaders);\n\t}\n\n\tif (sessionId) {\n\t\tif (compat.sessionAffinityFormat === \"openrouter\") {\n\t\t\theaders[\"x-session-id\"] = sessionId;\n\t\t} else {\n\t\t\tif (compat.sessionAffinityFormat === \"openai\") {\n\t\t\t\theaders.session_id = sessionId;\n\t\t\t}\n\t\t\theaders[\"x-client-request-id\"] = sessionId;\n\t\t}\n\t}\n\n\t// Merge options headers last so they can override defaults\n\tif (optionsHeaders) {\n\t\tObject.assign(headers, optionsHeaders);\n\t}\n\n\treturn new OpenAI({\n\t\tapiKey,\n\t\tbaseURL: model.baseUrl,\n\t\tdangerouslyAllowBrowser: true,\n\t\tfetch,\n\t\tdefaultHeaders: headers,\n\t});\n}\n\nfunction buildParams(\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions: OpenAIResponsesOptions | undefined,\n\tcompat: Required<OpenAIResponsesCompat> = getCompat(model),\n\tgrammarToolInputProperties: ReadonlyMap<string, string> = createGrammarToolInputProperties(\n\t\tcontext.tools,\n\t\tcompat.supportsOpenAIGrammarTools,\n\t),\n) {\n\tconst toolPlacement = splitDeferredTools(context, compat.supportsToolSearch);\n\tconst messages = convertResponsesMessages(model, context, OPENAI_TOOL_CALL_PROVIDERS, {\n\t\tgrammarToolInputProperties,\n\t\tdeferredTools: toolPlacement.deferred,\n\t\ttoolOptions: {\n\t\t\tsupportsStrictMode: compat.supportsStrictMode,\n\t\t\tsupportsOpenAIGrammarTools: compat.supportsOpenAIGrammarTools,\n\t\t},\n\t});\n\n\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);\n\tconst disableImplicitPromptCache = cacheRetention === \"none\" && compat.supportsExplicitPromptCacheMode;\n\tconst params: ResponseCreateParamsStreaming & { prompt_cache_options?: { mode: \"explicit\" } } = {\n\t\tmodel: model.id,\n\t\tinput: messages,\n\t\tstream: true,\n\t\tprompt_cache_key: cacheRetention === \"none\" ? undefined : clampOpenAIPromptCacheKey(options?.sessionId),\n\t\tprompt_cache_retention: getPromptCacheRetention(compat, cacheRetention),\n\t\tprompt_cache_options: disableImplicitPromptCache ? { mode: \"explicit\" } : undefined,\n\t\tstore: false,\n\t};\n\n\tif (options?.maxTokens) {\n\t\tparams.max_output_tokens = Math.max(options.maxTokens, OPENAI_RESPONSES_MIN_OUTPUT_TOKENS);\n\t}\n\n\tif (options?.temperature !== undefined) {\n\t\tparams.temperature = options?.temperature;\n\t}\n\n\tif (options?.serviceTier !== undefined) {\n\t\tparams.service_tier = options.serviceTier;\n\t}\n\n\tif (toolPlacement.immediate.length > 0) {\n\t\tparams.tools = convertResponsesTools(toolPlacement.immediate, {\n\t\t\tsupportsStrictMode: compat.supportsStrictMode,\n\t\t\tsupportsOpenAIGrammarTools: compat.supportsOpenAIGrammarTools,\n\t\t});\n\t}\n\n\tif (options?.toolChoice !== undefined) {\n\t\tparams.tool_choice = options.toolChoice;\n\t}\n\n\tif (model.reasoning) {\n\t\tif (options?.reasoningEffort || options?.reasoningSummary) {\n\t\t\tconst effort = options?.reasoningEffort\n\t\t\t\t? (model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort)\n\t\t\t\t: \"medium\";\n\t\t\tparams.reasoning = {\n\t\t\t\teffort: effort as NonNullable<typeof params.reasoning>[\"effort\"],\n\t\t\t\tsummary: options?.reasoningSummary || \"auto\",\n\t\t\t};\n\t\t\tparams.include = [\"reasoning.encrypted_content\"];\n\t\t} else if (model.provider !== \"github-copilot\" && model.thinkingLevelMap?.off !== null) {\n\t\t\tparams.reasoning = {\n\t\t\t\teffort: (model.thinkingLevelMap?.off ?? \"none\") as NonNullable<typeof params.reasoning>[\"effort\"],\n\t\t\t};\n\t\t}\n\t\tif (model.provider === \"xai\") params.include = [\"reasoning.encrypted_content\"];\n\t}\n\n\treturn params;\n}\n\nfunction getServiceTierCostMultiplier(\n\tmodel: Pick<Model<\"openai-responses\">, \"id\">,\n\tserviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined,\n): number {\n\tswitch (serviceTier) {\n\t\tcase \"flex\":\n\t\t\treturn 0.5;\n\t\tcase \"priority\":\n\t\t\treturn model.id === \"gpt-5.5\" ? 2.5 : 2;\n\t\tdefault:\n\t\t\treturn 1;\n\t}\n}\n\nfunction applyServiceTierPricing(\n\tusage: Usage,\n\tserviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined,\n\tmodel: Pick<Model<\"openai-responses\">, \"id\">,\n) {\n\tconst multiplier = getServiceTierCostMultiplier(model, serviceTier);\n\tif (multiplier === 1) return;\n\n\tusage.cost.input *= multiplier;\n\tusage.cost.output *= multiplier;\n\tusage.cost.cacheRead *= multiplier;\n\tusage.cost.cacheWrite *= multiplier;\n\tusage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;\n}\n"]}
1
+ {"version":3,"file":"openai-responses.js","sourceRoot":"","sources":["../../src/api/openai-responses.ts"],"names":[],"mappings":"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","sourcesContent":["import OpenAI from \"openai\";\nimport type { ResponseCreateParamsStreaming } from \"openai/resources/responses/responses.js\";\nimport { clampThinkingLevel } from \"../models.ts\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tCacheRetention,\n\tContext,\n\tModel,\n\tOpenAIResponsesCompat,\n\tProviderEnv,\n\tProviderHeaders,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tUsage,\n} from \"../types.ts\";\nimport { splitDeferredTools } from \"../utils/deferred-tools.ts\";\nimport { formatProviderError, normalizeProviderError } from \"../utils/error-body.ts\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.ts\";\nimport { headersToRecord } from \"../utils/headers.ts\";\nimport { getProviderEnvValue } from \"../utils/provider-env.ts\";\nimport { retryProviderRequest } from \"../utils/provider-retry.ts\";\nimport { createGrammarToolInputProperties } from \"./constrained-sampling.ts\";\nimport { buildCopilotDynamicHeaders, hasCopilotVisionInput } from \"./github-copilot-headers.ts\";\nimport { clampOpenAIPromptCacheKey } from \"./openai-prompt-cache.ts\";\nimport { convertResponsesMessages, convertResponsesTools, processResponsesStream } from \"./openai-responses-shared.ts\";\nimport { buildBaseOptions } from \"./simple-options.ts\";\n\nconst OPENAI_TOOL_CALL_PROVIDERS = new Set([\"openai\", \"openai-codex\", \"opencode\"]);\n// OpenAI Responses rejects max_output_tokens below 16: https://github.com/earendil-works/pi/issues/6265\nconst OPENAI_RESPONSES_MIN_OUTPUT_TOKENS = 16;\n\nfunction hasHeader(headers: ProviderHeaders | undefined, name: string): boolean {\n\tif (!headers) return false;\n\tconst expected = name.toLowerCase();\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tif (key.toLowerCase() === expected && value !== null && value.trim().length > 0) return true;\n\t}\n\treturn false;\n}\n\nfunction getClientApiKey(provider: string, apiKey: string | undefined, headers: ProviderHeaders | undefined): string {\n\tif (apiKey) return apiKey;\n\tif (hasHeader(headers, \"authorization\") || hasHeader(headers, \"cf-aig-authorization\")) return \"unused\";\n\tthrow new Error(`No API key for provider: ${provider}`);\n}\n\nfunction detectSessionAffinityFormat(model: Pick<Model<\"openai-responses\">, \"provider\" | \"baseUrl\">) {\n\treturn model.provider === \"openrouter\" || model.baseUrl.includes(\"openrouter.ai\") ? \"openrouter\" : \"openai\";\n}\n\n/**\n * Resolve cache retention preference.\n * Defaults to \"short\" and uses PI_CACHE_RETENTION for backward compatibility.\n */\nfunction resolveCacheRetention(cacheRetention?: CacheRetention, env?: ProviderEnv): CacheRetention {\n\tif (cacheRetention) {\n\t\treturn cacheRetention;\n\t}\n\tif (getProviderEnvValue(\"PI_CACHE_RETENTION\", env) === \"long\") {\n\t\treturn \"long\";\n\t}\n\treturn \"short\";\n}\n\nfunction getCompat(model: Model<\"openai-responses\">): Required<OpenAIResponsesCompat> {\n\treturn {\n\t\tsupportsDeveloperRole: model.compat?.supportsDeveloperRole ?? true,\n\t\tsessionAffinityFormat: model.compat?.sessionAffinityFormat ?? detectSessionAffinityFormat(model),\n\t\tsupportsLongCacheRetention: model.compat?.supportsLongCacheRetention ?? true,\n\t\tsupportsStrictMode: model.compat?.supportsStrictMode ?? false,\n\t\tsupportsOpenAIGrammarTools: model.compat?.supportsOpenAIGrammarTools ?? false,\n\t\tsupportsToolSearch: model.compat?.supportsToolSearch ?? false,\n\t\tsupportsExplicitPromptCacheMode: model.compat?.supportsExplicitPromptCacheMode ?? false,\n\t};\n}\n\nfunction getPromptCacheRetention(\n\tcompat: Required<OpenAIResponsesCompat>,\n\tcacheRetention: CacheRetention,\n): \"24h\" | undefined {\n\treturn cacheRetention === \"long\" && compat.supportsLongCacheRetention && !compat.supportsExplicitPromptCacheMode\n\t\t? \"24h\"\n\t\t: undefined;\n}\n\nfunction getPromptCacheOptions(\n\tcompat: Required<OpenAIResponsesCompat>,\n\tcacheRetention: CacheRetention,\n): { mode?: \"explicit\"; ttl?: \"30m\" } | undefined {\n\tif (!compat.supportsExplicitPromptCacheMode) return undefined;\n\tif (cacheRetention === \"none\") return { mode: \"explicit\" };\n\tif (cacheRetention === \"long\" && compat.supportsLongCacheRetention) return { ttl: \"30m\" };\n\treturn undefined;\n}\n\nfunction formatOpenAIResponsesError(error: unknown): string {\n\treturn formatProviderError(normalizeProviderError(error), \"OpenAI API error\");\n}\n\n// OpenAI Responses-specific options\nexport interface OpenAIResponsesOptions extends StreamOptions {\n\treasoningEffort?: \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\";\n\treasoningSummary?: \"auto\" | \"detailed\" | \"concise\" | null;\n\tserviceTier?: ResponseCreateParamsStreaming[\"service_tier\"];\n\ttoolChoice?: ResponseCreateParamsStreaming[\"tool_choice\"];\n}\n\n/**\n * Generate function for OpenAI Responses API\n */\nexport const stream: StreamFunction<\"openai-responses\", OpenAIResponsesOptions> = (\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions?: OpenAIResponsesOptions,\n): AssistantMessageEventStream => {\n\tconst stream = new AssistantMessageEventStream();\n\n\t// Start async processing\n\t(async () => {\n\t\tconst output: AssistantMessage = {\n\t\t\trole: \"assistant\",\n\t\t\tcontent: [],\n\t\t\tapi: model.api as Api,\n\t\t\tprovider: model.provider,\n\t\t\tmodel: model.id,\n\t\t\tusage: {\n\t\t\t\tinput: 0,\n\t\t\t\toutput: 0,\n\t\t\t\tcacheRead: 0,\n\t\t\t\tcacheWrite: 0,\n\t\t\t\ttotalTokens: 0,\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t},\n\t\t\tstopReason: \"pending\",\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\ttry {\n\t\t\t// Create OpenAI client\n\t\t\tconst apiKey = getClientApiKey(model.provider, options?.apiKey, options?.headers);\n\t\t\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);\n\t\t\tconst cacheSessionId = cacheRetention === \"none\" ? undefined : options?.sessionId;\n\t\t\tconst compat = getCompat(model);\n\t\t\tconst grammarToolInputProperties = createGrammarToolInputProperties(\n\t\t\t\tcontext.tools,\n\t\t\t\tcompat.supportsOpenAIGrammarTools,\n\t\t\t);\n\t\t\tconst client = createClient(model, context, apiKey, options?.headers, options?.fetch, cacheSessionId);\n\t\t\tlet params = buildParams(model, context, options, compat, grammarToolInputProperties);\n\t\t\tconst nextParams = await options?.onPayload?.(params, model);\n\t\t\tif (nextParams !== undefined) {\n\t\t\t\tparams = nextParams as ResponseCreateParamsStreaming;\n\t\t\t}\n\t\t\tconst requestOptions = {\n\t\t\t\t...(options?.signal ? { signal: options.signal } : {}),\n\t\t\t\t...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),\n\t\t\t\tmaxRetries: 0,\n\t\t\t};\n\t\t\tconst { data: openaiStream, response } = await retryProviderRequest(\n\t\t\t\t() => client.responses.create(params, requestOptions).withResponse(),\n\t\t\t\t{\n\t\t\t\t\tmaxRetries: options?.maxRetries,\n\t\t\t\t\tmaxRetryDelayMs: options?.maxRetryDelayMs,\n\t\t\t\t\tsignal: options?.signal,\n\t\t\t\t},\n\t\t\t);\n\t\t\tawait options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);\n\t\t\tstream.push({ type: \"start\", partial: output });\n\n\t\t\tawait processResponsesStream(openaiStream, output, stream, model, {\n\t\t\t\tserviceTier: options?.serviceTier,\n\t\t\t\tgrammarToolInputProperties,\n\t\t\t\tapplyServiceTierPricing: (usage, serviceTier) => applyServiceTierPricing(usage, serviceTier, model),\n\t\t\t});\n\n\t\t\tif (options?.signal?.aborted) {\n\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t}\n\n\t\t\tif (output.stopReason === \"pending\") {\n\t\t\t\tthrow new Error(\"OpenAI Responses stream ended without a stop reason\");\n\t\t\t}\n\t\t\tif (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n\t\t\t\tthrow new Error(\"An unknown error occurred\");\n\t\t\t}\n\n\t\t\tstream.push({ type: \"done\", reason: output.stopReason, message: output });\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\tfor (const block of output.content) {\n\t\t\t\tdelete (block as { index?: number }).index;\n\t\t\t\t// Streaming scratch buffers are only used during parsing; never persist them.\n\t\t\t\tdelete (block as { partialJson?: string }).partialJson;\n\t\t\t\tdelete (block as { customInput?: unknown }).customInput;\n\t\t\t}\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\toutput.errorMessage = formatOpenAIResponsesError(error);\n\t\t\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n};\n\nexport const streamSimple: StreamFunction<\"openai-responses\", SimpleStreamOptions> = (\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream => {\n\tgetClientApiKey(model.provider, options?.apiKey, options?.headers);\n\n\tconst base = buildBaseOptions(model, context, options, options?.apiKey);\n\tconst clampedReasoning = options?.reasoning ? clampThinkingLevel(model, options.reasoning) : undefined;\n\tconst reasoningEffort = clampedReasoning === \"off\" ? undefined : clampedReasoning;\n\n\treturn stream(model, context, {\n\t\t...base,\n\t\treasoningEffort,\n\t} satisfies OpenAIResponsesOptions);\n};\n\nfunction createClient(\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\tapiKey: string,\n\toptionsHeaders?: ProviderHeaders,\n\tfetch?: typeof globalThis.fetch,\n\tsessionId?: string,\n) {\n\tconst compat = getCompat(model);\n\tconst headers: ProviderHeaders = { ...model.headers };\n\tif (model.provider === \"github-copilot\") {\n\t\tconst hasImages = hasCopilotVisionInput(context.messages);\n\t\tconst copilotHeaders = buildCopilotDynamicHeaders({\n\t\t\tmessages: context.messages,\n\t\t\thasImages,\n\t\t});\n\t\tObject.assign(headers, copilotHeaders);\n\t}\n\n\tif (sessionId) {\n\t\tif (compat.sessionAffinityFormat === \"openrouter\") {\n\t\t\theaders[\"x-session-id\"] = sessionId;\n\t\t} else {\n\t\t\tif (compat.sessionAffinityFormat === \"openai\") {\n\t\t\t\theaders.session_id = sessionId;\n\t\t\t}\n\t\t\theaders[\"x-client-request-id\"] = sessionId;\n\t\t}\n\t}\n\n\t// Merge options headers last so they can override defaults\n\tif (optionsHeaders) {\n\t\tObject.assign(headers, optionsHeaders);\n\t}\n\n\treturn new OpenAI({\n\t\tapiKey,\n\t\tbaseURL: model.baseUrl,\n\t\tdangerouslyAllowBrowser: true,\n\t\tfetch,\n\t\tdefaultHeaders: headers,\n\t});\n}\n\nfunction buildParams(\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions: OpenAIResponsesOptions | undefined,\n\tcompat: Required<OpenAIResponsesCompat> = getCompat(model),\n\tgrammarToolInputProperties: ReadonlyMap<string, string> = createGrammarToolInputProperties(\n\t\tcontext.tools,\n\t\tcompat.supportsOpenAIGrammarTools,\n\t),\n) {\n\tconst toolPlacement = splitDeferredTools(context, compat.supportsToolSearch);\n\tconst messages = convertResponsesMessages(model, context, OPENAI_TOOL_CALL_PROVIDERS, {\n\t\tgrammarToolInputProperties,\n\t\tdeferredTools: toolPlacement.deferred,\n\t\ttoolOptions: {\n\t\t\tsupportsStrictMode: compat.supportsStrictMode,\n\t\t\tsupportsOpenAIGrammarTools: compat.supportsOpenAIGrammarTools,\n\t\t},\n\t});\n\n\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);\n\tconst params: ResponseCreateParamsStreaming & {\n\t\tprompt_cache_options?: { mode?: \"explicit\"; ttl?: \"30m\" };\n\t} = {\n\t\tmodel: model.id,\n\t\tinput: messages,\n\t\tstream: true,\n\t\tprompt_cache_key: cacheRetention === \"none\" ? undefined : clampOpenAIPromptCacheKey(options?.sessionId),\n\t\tprompt_cache_retention: getPromptCacheRetention(compat, cacheRetention),\n\t\tprompt_cache_options: getPromptCacheOptions(compat, cacheRetention),\n\t\tstore: false,\n\t};\n\n\tif (options?.maxTokens) {\n\t\tparams.max_output_tokens = Math.max(options.maxTokens, OPENAI_RESPONSES_MIN_OUTPUT_TOKENS);\n\t}\n\n\tif (options?.temperature !== undefined) {\n\t\tparams.temperature = options?.temperature;\n\t}\n\n\tif (options?.serviceTier !== undefined) {\n\t\tparams.service_tier = options.serviceTier;\n\t}\n\n\tif (toolPlacement.immediate.length > 0) {\n\t\tparams.tools = convertResponsesTools(toolPlacement.immediate, {\n\t\t\tsupportsStrictMode: compat.supportsStrictMode,\n\t\t\tsupportsOpenAIGrammarTools: compat.supportsOpenAIGrammarTools,\n\t\t});\n\t}\n\n\tif (options?.toolChoice !== undefined) {\n\t\tparams.tool_choice = options.toolChoice;\n\t}\n\n\tif (model.reasoning) {\n\t\tif (options?.reasoningEffort || options?.reasoningSummary) {\n\t\t\tconst effort = options?.reasoningEffort\n\t\t\t\t? (model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort)\n\t\t\t\t: \"medium\";\n\t\t\tparams.reasoning = {\n\t\t\t\teffort: effort as NonNullable<typeof params.reasoning>[\"effort\"],\n\t\t\t\tsummary: options?.reasoningSummary || \"auto\",\n\t\t\t};\n\t\t\tparams.include = [\"reasoning.encrypted_content\"];\n\t\t} else if (model.provider !== \"github-copilot\" && model.thinkingLevelMap?.off !== null) {\n\t\t\tparams.reasoning = {\n\t\t\t\teffort: (model.thinkingLevelMap?.off ?? \"none\") as NonNullable<typeof params.reasoning>[\"effort\"],\n\t\t\t};\n\t\t}\n\t\tif (model.provider === \"xai\") params.include = [\"reasoning.encrypted_content\"];\n\t}\n\n\treturn params;\n}\n\nfunction getServiceTierCostMultiplier(\n\tmodel: Pick<Model<\"openai-responses\">, \"id\">,\n\tserviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined,\n): number {\n\tswitch (serviceTier) {\n\t\tcase \"flex\":\n\t\t\treturn 0.5;\n\t\tcase \"priority\":\n\t\t\treturn model.id === \"gpt-5.5\" ? 2.5 : 2;\n\t\tdefault:\n\t\t\treturn 1;\n\t}\n}\n\nfunction applyServiceTierPricing(\n\tusage: Usage,\n\tserviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined,\n\tmodel: Pick<Model<\"openai-responses\">, \"id\">,\n) {\n\tconst multiplier = getServiceTierCostMultiplier(model, serviceTier);\n\tif (multiplier === 1) return;\n\n\tusage.cost.input *= multiplier;\n\tusage.cost.output *= multiplier;\n\tusage.cost.cacheRead *= multiplier;\n\tusage.cost.cacheWrite *= multiplier;\n\tusage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;\n}\n"]}
@@ -1 +1 @@
1
- {"schemaVersion":3,"generatedAt":"2026-08-03T20:01:51.755Z","structureHash":"843a91eacffa6eb098685595d6d931a562b1d4e845ad8de031eae6dba35df81b","files":{"amazon-bedrock.json":"ec39015e353797d4a8256801ccbbc4da3bb9e832cfbcd06c521b200f98639788","ant-ling.json":"4979fe79d99ed97382d7ce40170c6132e932e77906de1eb54464c042e7d63633","anthropic.json":"fea1226a62396c8d4a3d9c3b7f65d4dc527ac025d05719880418d3a2b0665a69","azure-openai-responses.json":"5315b6a2299fefbdbb6cc13a720544077c9498132ad5e3a7d76a8c1daa8e9335","cerebras.json":"3fd3e19b83ab4be07d27817e25e5be0ffe4158b1394f0311d6a22d9f03847728","cloudflare-ai-gateway.json":"692b375a3bcb11743a9c1899442caecc3861163d9424356d3d073d9fa5c04091","cloudflare-workers-ai.json":"03b19d69433c843512e953390d51d4578e9b91f19098a9b14ff820c001623598","deepseek.json":"0dcc807a4e5827b488c6ceac87884ff6e735e01cf4f2ddfec9dd812e6fde041b","fireworks.json":"8c9931528b1d1afedb47cc1c7a112622d52bea38e69aac019e036f05b61d1d89","github-copilot.json":"f22a85d3bf3222ddb41075186c85e99e9d35fab7cb9ba0d05a6acca5a7b8eb67","google-vertex.json":"99d0b89ac9d8dc460ed922236abffbe88c9381af4d35046d2ad3a8f08fa2560c","google.json":"bcf8a8d59ccbb75bc6fb4a261a37ac4b7c806f40ee7313b4411178964be5fa37","groq.json":"868c90a897f75f866e09a585f6aee5cb991e40a9c3281497b5842a23de7d9add","huggingface.json":"c5e6e5a9a273f3829160b66ca41d7b400e1bd9e75b44364040962c69f38ba1e2","kimi-coding.json":"ba42a26a69e5cb2122c0b384ba572efae93f42239ad86f26c2b7320a14aa75a1","minimax-cn.json":"8ccd71ff838f4b78bb88809babb0dc32a4fcfaec2bc4f4083841000428df4f77","minimax.json":"253edd4c910a41c8bb252400ba099f3a4de0a8900ce154319288ab091b372987","mistral.json":"4f9d84bf1ba10cb14ff2c9e23e77d63441756ef3500375dd4ad10094614b215b","moonshotai-cn.json":"1e6146ff3477883636448c0f44222f0a52b3c4562ef8f4eecf7e941cdd59d12e","moonshotai.json":"d8d5209873058ddccd37c1f026833e2ea3f9476c3dc9628b4a940d407acc0b2e","nvidia.json":"33c498ab62940fe9ca659826c35cc922a77938a5f7edbe4443c10d9133323e87","openai-codex.json":"03a4c4ad1915d43de9f9ef305ee34fb6bd4609e680ca530d1016bd23e062b2d4","openai.json":"b5e3fc582f99a781b134213c2f461d825943a30cf7f9c7f6517437b591b144fe","opencode-go.json":"5e6d8256e3b3db2ee3f6783763b8e72b415612f1aa4acf6a305cea51888dde85","opencode.json":"ecbe3d11546152f121b24ae152cade09963ac8f4cf6fcb0cca9049ef292ac8d7","openrouter.json":"5125b9923fec9fd7cd0f428e255f1f6c53068aa95227d8e71056323a417accb7","qwen-token-plan-cn.json":"cc345d44c31b0ba3b1b244f8b56342ede6657584653f3af176026bf8dbb37cd5","qwen-token-plan.json":"12c43b2b8032e1b64222616588daf400156f3819be4de3124fc997a69eccbda8","together.json":"71ad3e3c0cd989e75bcedc5637b94725415e336e43eda6749bf6ddf44500ae84","vercel-ai-gateway.json":"e478b51fe8cf191aeaa76a2004a1c4d4dc66fef951aeb2894bc24e646468027c","xai.json":"4cbdbfbbf915246369b9bacbc6f1feeb56accdac9f3444456343f750547f2f38","xiaomi-token-plan-ams.json":"7ce8ed244672c45737d286ff3ca9c3a2686a5d4b2f0c5f71ab9348c14b14daf3","xiaomi-token-plan-cn.json":"684892b5fe6fa371d6040d2011c0fa33facd650d2eaf19f5dbee8efb33016200","xiaomi-token-plan-sgp.json":"b19e79b82ac4fdcb080e6d220106797504c885ed70b27fc2b3c1aa4810f32963","xiaomi.json":"810368d3828c8bb9498012a0d48639030c0c216b8c13e79da02daa515aa23448","zai-coding-cn.json":"c2d1e137238b6f248b5f620f76b64520aa2ba1543e991dd0d14b708e50c8cd66","zai.json":"cb48b354442f1e49919cd93b928216d5d881d2f98a55349ad592a8e68bb8e6c3"}}
1
+ {"schemaVersion":3,"generatedAt":"2026-09-05T02:21:12.961Z","structureHash":"b74c20ffd96b98d417aa5eb5326705d23020a322c47a9e6a2852d0106436d727","files":{"amazon-bedrock.json":"ec39015e353797d4a8256801ccbbc4da3bb9e832cfbcd06c521b200f98639788","ant-ling.json":"4979fe79d99ed97382d7ce40170c6132e932e77906de1eb54464c042e7d63633","anthropic.json":"fea1226a62396c8d4a3d9c3b7f65d4dc527ac025d05719880418d3a2b0665a69","azure-openai-responses.json":"5315b6a2299fefbdbb6cc13a720544077c9498132ad5e3a7d76a8c1daa8e9335","cerebras.json":"3fd3e19b83ab4be07d27817e25e5be0ffe4158b1394f0311d6a22d9f03847728","cloudflare-ai-gateway.json":"692b375a3bcb11743a9c1899442caecc3861163d9424356d3d073d9fa5c04091","cloudflare-workers-ai.json":"03b19d69433c843512e953390d51d4578e9b91f19098a9b14ff820c001623598","deepseek.json":"0dcc807a4e5827b488c6ceac87884ff6e735e01cf4f2ddfec9dd812e6fde041b","fireworks.json":"8c9931528b1d1afedb47cc1c7a112622d52bea38e69aac019e036f05b61d1d89","github-copilot.json":"f22a85d3bf3222ddb41075186c85e99e9d35fab7cb9ba0d05a6acca5a7b8eb67","google-vertex.json":"99d0b89ac9d8dc460ed922236abffbe88c9381af4d35046d2ad3a8f08fa2560c","google.json":"bcf8a8d59ccbb75bc6fb4a261a37ac4b7c806f40ee7313b4411178964be5fa37","groq.json":"868c90a897f75f866e09a585f6aee5cb991e40a9c3281497b5842a23de7d9add","huggingface.json":"c5e6e5a9a273f3829160b66ca41d7b400e1bd9e75b44364040962c69f38ba1e2","kimi-coding.json":"ba42a26a69e5cb2122c0b384ba572efae93f42239ad86f26c2b7320a14aa75a1","minimax-cn.json":"8ccd71ff838f4b78bb88809babb0dc32a4fcfaec2bc4f4083841000428df4f77","minimax.json":"253edd4c910a41c8bb252400ba099f3a4de0a8900ce154319288ab091b372987","mistral.json":"4f9d84bf1ba10cb14ff2c9e23e77d63441756ef3500375dd4ad10094614b215b","moonshotai-cn.json":"1e6146ff3477883636448c0f44222f0a52b3c4562ef8f4eecf7e941cdd59d12e","moonshotai.json":"d8d5209873058ddccd37c1f026833e2ea3f9476c3dc9628b4a940d407acc0b2e","nvidia.json":"33c498ab62940fe9ca659826c35cc922a77938a5f7edbe4443c10d9133323e87","openai-codex.json":"95d4d23cbe5d525e217e5655558737b81aa7e40ca20f23af58208b26ad9018e3","openai.json":"8ba1cc7fb2c65c3caec18dc2ec741699458196a192faff4ce17ad05d884ed2d8","opencode-go.json":"5e6d8256e3b3db2ee3f6783763b8e72b415612f1aa4acf6a305cea51888dde85","opencode.json":"ecbe3d11546152f121b24ae152cade09963ac8f4cf6fcb0cca9049ef292ac8d7","openrouter.json":"5125b9923fec9fd7cd0f428e255f1f6c53068aa95227d8e71056323a417accb7","qwen-token-plan-cn.json":"cc345d44c31b0ba3b1b244f8b56342ede6657584653f3af176026bf8dbb37cd5","qwen-token-plan.json":"12c43b2b8032e1b64222616588daf400156f3819be4de3124fc997a69eccbda8","together.json":"71ad3e3c0cd989e75bcedc5637b94725415e336e43eda6749bf6ddf44500ae84","vercel-ai-gateway.json":"e478b51fe8cf191aeaa76a2004a1c4d4dc66fef951aeb2894bc24e646468027c","xai.json":"4cbdbfbbf915246369b9bacbc6f1feeb56accdac9f3444456343f750547f2f38","xiaomi-token-plan-ams.json":"7ce8ed244672c45737d286ff3ca9c3a2686a5d4b2f0c5f71ab9348c14b14daf3","xiaomi-token-plan-cn.json":"684892b5fe6fa371d6040d2011c0fa33facd650d2eaf19f5dbee8efb33016200","xiaomi-token-plan-sgp.json":"b19e79b82ac4fdcb080e6d220106797504c885ed70b27fc2b3c1aa4810f32963","xiaomi.json":"810368d3828c8bb9498012a0d48639030c0c216b8c13e79da02daa515aa23448","zai-coding-cn.json":"c2d1e137238b6f248b5f620f76b64520aa2ba1543e991dd0d14b708e50c8cd66","zai.json":"cb48b354442f1e49919cd93b928216d5d881d2f98a55349ad592a8e68bb8e6c3"}}
@@ -1 +1 @@
1
- {"openai-codex-responses":{"gpt-5.3-codex-spark":{"id":"gpt-5.3-codex-spark","name":"GPT-5.3 Codex Spark","api":"openai-codex-responses","provider":"openai-codex","baseUrl":"https://chatgpt.com/backend-api","reasoning":true,"input":["text"],"cost":{"input":1.75,"output":14,"cacheRead":0.175,"cacheWrite":0},"contextWindow":128000,"maxTokens":128000,"thinkingLevelMap":{"xhigh":"xhigh","minimal":"low"},"compat":{"supportsOpenAIGrammarTools":true}},"gpt-5.4":{"id":"gpt-5.4","name":"GPT-5.4","api":"openai-codex-responses","provider":"openai-codex","baseUrl":"https://chatgpt.com/backend-api","reasoning":true,"input":["text","image"],"cost":{"input":2.5,"output":15,"cacheRead":0.25,"cacheWrite":0,"tiers":[{"inputTokensAbove":272000,"input":5,"output":22.5,"cacheRead":0.5,"cacheWrite":0}]},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"xhigh":"xhigh","minimal":"low"},"compat":{"supportsOpenAIGrammarTools":true,"supportsToolSearch":true}},"gpt-5.4-mini":{"id":"gpt-5.4-mini","name":"GPT-5.4 mini","api":"openai-codex-responses","provider":"openai-codex","baseUrl":"https://chatgpt.com/backend-api","reasoning":true,"input":["text","image"],"cost":{"input":0.75,"output":4.5,"cacheRead":0.075,"cacheWrite":0},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"xhigh":"xhigh","minimal":"low"},"compat":{"supportsOpenAIGrammarTools":true,"supportsToolSearch":true}},"gpt-5.5":{"id":"gpt-5.5","name":"GPT-5.5","api":"openai-codex-responses","provider":"openai-codex","baseUrl":"https://chatgpt.com/backend-api","reasoning":true,"input":["text","image"],"cost":{"input":5,"output":30,"cacheRead":0.5,"cacheWrite":0,"tiers":[{"inputTokensAbove":272000,"input":10,"output":45,"cacheRead":1,"cacheWrite":0}]},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"xhigh":"xhigh","minimal":"low"},"compat":{"supportsOpenAIGrammarTools":true,"supportsToolSearch":true}},"gpt-5.6-luna":{"id":"gpt-5.6-luna","name":"GPT-5.6 Luna","api":"openai-codex-responses","provider":"openai-codex","baseUrl":"https://chatgpt.com/backend-api","reasoning":true,"input":["text","image"],"cost":{"input":1,"output":6,"cacheRead":0.1,"cacheWrite":1.25,"tiers":[{"inputTokensAbove":272000,"input":2,"output":9,"cacheRead":0.2,"cacheWrite":2.5}]},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"xhigh":"xhigh","max":"max","minimal":"low"},"compat":{"supportsOpenAIGrammarTools":true,"supportsToolSearch":true}},"gpt-5.6-sol":{"id":"gpt-5.6-sol","name":"GPT-5.6 Sol","api":"openai-codex-responses","provider":"openai-codex","baseUrl":"https://chatgpt.com/backend-api","reasoning":true,"input":["text","image"],"cost":{"input":5,"output":30,"cacheRead":0.5,"cacheWrite":6.25,"tiers":[{"inputTokensAbove":272000,"input":10,"output":45,"cacheRead":1,"cacheWrite":12.5}]},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"xhigh":"xhigh","max":"max","minimal":"low"},"compat":{"supportsOpenAIGrammarTools":true,"supportsToolSearch":true}},"gpt-5.6-terra":{"id":"gpt-5.6-terra","name":"GPT-5.6 Terra","api":"openai-codex-responses","provider":"openai-codex","baseUrl":"https://chatgpt.com/backend-api","reasoning":true,"input":["text","image"],"cost":{"input":2.5,"output":15,"cacheRead":0.25,"cacheWrite":3.125,"tiers":[{"inputTokensAbove":272000,"input":5,"output":22.5,"cacheRead":0.5,"cacheWrite":6.25}]},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"xhigh":"xhigh","max":"max","minimal":"low"},"compat":{"supportsOpenAIGrammarTools":true,"supportsToolSearch":true}}}}
1
+ {"openai-codex-responses":{"gpt-5.3-codex-spark":{"id":"gpt-5.3-codex-spark","name":"GPT-5.3 Codex Spark","api":"openai-codex-responses","provider":"openai-codex","baseUrl":"https://chatgpt.com/backend-api","reasoning":true,"input":["text"],"cost":{"input":1.75,"output":14,"cacheRead":0.175,"cacheWrite":0},"contextWindow":128000,"maxTokens":128000,"thinkingLevelMap":{"xhigh":"xhigh","minimal":"low"},"compat":{"supportsOpenAIGrammarTools":true}},"gpt-5.4":{"id":"gpt-5.4","name":"GPT-5.4","api":"openai-codex-responses","provider":"openai-codex","baseUrl":"https://chatgpt.com/backend-api","reasoning":true,"input":["text","image"],"cost":{"input":2.5,"output":15,"cacheRead":0.25,"cacheWrite":0,"tiers":[{"inputTokensAbove":272000,"input":5,"output":22.5,"cacheRead":0.5,"cacheWrite":0}]},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"xhigh":"xhigh","minimal":"low"},"compat":{"supportsOpenAIGrammarTools":true,"supportsToolSearch":true}},"gpt-5.4-mini":{"id":"gpt-5.4-mini","name":"GPT-5.4 mini","api":"openai-codex-responses","provider":"openai-codex","baseUrl":"https://chatgpt.com/backend-api","reasoning":true,"input":["text","image"],"cost":{"input":0.75,"output":4.5,"cacheRead":0.075,"cacheWrite":0},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"xhigh":"xhigh","minimal":"low"},"compat":{"supportsOpenAIGrammarTools":true,"supportsToolSearch":true}},"gpt-5.5":{"id":"gpt-5.5","name":"GPT-5.5","api":"openai-codex-responses","provider":"openai-codex","baseUrl":"https://chatgpt.com/backend-api","reasoning":true,"input":["text","image"],"cost":{"input":5,"output":30,"cacheRead":0.5,"cacheWrite":0,"tiers":[{"inputTokensAbove":272000,"input":10,"output":45,"cacheRead":1,"cacheWrite":0}]},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"xhigh":"xhigh","minimal":"low"},"compat":{"supportsOpenAIGrammarTools":true,"supportsToolSearch":true}},"gpt-5.6-luna":{"id":"gpt-5.6-luna","name":"GPT-5.6 Luna","api":"openai-codex-responses","provider":"openai-codex","baseUrl":"https://chatgpt.com/backend-api","reasoning":true,"input":["text","image"],"cost":{"input":1,"output":6,"cacheRead":0.1,"cacheWrite":1.25,"tiers":[{"inputTokensAbove":272000,"input":2,"output":9,"cacheRead":0.2,"cacheWrite":2.5}]},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"xhigh":"xhigh","max":"max","minimal":"low"},"compat":{"supportsOpenAIGrammarTools":true,"supportsToolSearch":true}},"gpt-5.6-sol":{"id":"gpt-5.6-sol","name":"GPT-5.6 Sol","api":"openai-codex-responses","provider":"openai-codex","baseUrl":"https://chatgpt.com/backend-api","reasoning":true,"input":["text","image"],"cost":{"input":5,"output":30,"cacheRead":0.5,"cacheWrite":6.25,"tiers":[{"inputTokensAbove":272000,"input":10,"output":45,"cacheRead":1,"cacheWrite":12.5}]},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"xhigh":"xhigh","max":"max","minimal":"low"},"compat":{"supportsOpenAIGrammarTools":true,"supportsToolSearch":true}},"gpt-5.6-terra":{"id":"gpt-5.6-terra","name":"GPT-5.6 Terra","api":"openai-codex-responses","provider":"openai-codex","baseUrl":"https://chatgpt.com/backend-api","reasoning":true,"input":["text","image"],"cost":{"input":2.5,"output":15,"cacheRead":0.25,"cacheWrite":3.125,"tiers":[{"inputTokensAbove":272000,"input":5,"output":22.5,"cacheRead":0.5,"cacheWrite":6.25}]},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"xhigh":"xhigh","max":"max","minimal":"low"},"compat":{"supportsOpenAIGrammarTools":true,"supportsToolSearch":true}},"gpt-6-astra":{"id":"gpt-6-astra","name":"GPT-6 Astra","api":"openai-codex-responses","provider":"openai-codex","baseUrl":"https://chatgpt.com/backend-api","reasoning":true,"input":["text","image"],"cost":{"input":10,"output":50,"cacheRead":1,"cacheWrite":12.5,"tiers":[{"inputTokensAbove":272000,"input":20,"output":75,"cacheRead":2,"cacheWrite":25}]},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"xhigh":"xhigh","max":"max","off":null,"minimal":"low","low":"low","medium":"medium","high":"high"},"compat":{"supportsOpenAIGrammarTools":true,"supportsToolSearch":true}}}}
@@ -1 +1 @@
1
- {"openai-responses":{"gpt-4":{"id":"gpt-4","name":"GPT-4","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":false,"input":["text"],"cost":{"input":30,"output":60,"cacheRead":0,"cacheWrite":0},"contextWindow":8192,"maxTokens":8192,"compat":{"supportsStrictMode":true}},"gpt-4-turbo":{"id":"gpt-4-turbo","name":"GPT-4 Turbo","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":false,"input":["text","image"],"cost":{"input":10,"output":30,"cacheRead":0,"cacheWrite":0},"contextWindow":128000,"maxTokens":4096,"compat":{"supportsStrictMode":true}},"gpt-4.1":{"id":"gpt-4.1","name":"GPT-4.1","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":false,"input":["text","image"],"cost":{"input":2,"output":8,"cacheRead":0.5,"cacheWrite":0},"contextWindow":1047576,"maxTokens":32768,"compat":{"supportsStrictMode":true}},"gpt-4.1-mini":{"id":"gpt-4.1-mini","name":"GPT-4.1 mini","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":false,"input":["text","image"],"cost":{"input":0.4,"output":1.6,"cacheRead":0.1,"cacheWrite":0},"contextWindow":1047576,"maxTokens":32768,"compat":{"supportsStrictMode":true}},"gpt-4.1-nano":{"id":"gpt-4.1-nano","name":"GPT-4.1 nano","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":false,"input":["text","image"],"cost":{"input":0.1,"output":0.4,"cacheRead":0.025,"cacheWrite":0},"contextWindow":1047576,"maxTokens":32768,"compat":{"supportsStrictMode":true}},"gpt-4o":{"id":"gpt-4o","name":"GPT-4o","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":false,"input":["text","image"],"cost":{"input":2.5,"output":10,"cacheRead":1.25,"cacheWrite":0},"contextWindow":128000,"maxTokens":16384,"compat":{"supportsStrictMode":true}},"gpt-4o-2024-05-13":{"id":"gpt-4o-2024-05-13","name":"GPT-4o (2024-05-13)","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":false,"input":["text","image"],"cost":{"input":5,"output":15,"cacheRead":0,"cacheWrite":0},"contextWindow":128000,"maxTokens":4096,"compat":{"supportsStrictMode":true}},"gpt-4o-2024-08-06":{"id":"gpt-4o-2024-08-06","name":"GPT-4o (2024-08-06)","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":false,"input":["text","image"],"cost":{"input":2.5,"output":10,"cacheRead":1.25,"cacheWrite":0},"contextWindow":128000,"maxTokens":16384,"compat":{"supportsStrictMode":true}},"gpt-4o-2024-11-20":{"id":"gpt-4o-2024-11-20","name":"GPT-4o (2024-11-20)","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":false,"input":["text","image"],"cost":{"input":2.5,"output":10,"cacheRead":1.25,"cacheWrite":0},"contextWindow":128000,"maxTokens":16384,"compat":{"supportsStrictMode":true}},"gpt-4o-mini":{"id":"gpt-4o-mini","name":"GPT-4o mini","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":false,"input":["text","image"],"cost":{"input":0.15,"output":0.6,"cacheRead":0.075,"cacheWrite":0},"contextWindow":128000,"maxTokens":16384,"compat":{"supportsStrictMode":true}},"gpt-5":{"id":"gpt-5","name":"GPT-5","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":1.25,"output":10,"cacheRead":0.125,"cacheWrite":0},"contextWindow":400000,"maxTokens":128000,"thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null,"max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5-chat-latest":{"id":"gpt-5-chat-latest","name":"GPT-5 Chat Latest","api":"openai-responses","baseUrl":"https://api.openai.com/v1","provider":"openai","reasoning":false,"input":["text","image"],"cost":{"input":1.25,"output":10,"cacheRead":0.125,"cacheWrite":0},"contextWindow":128000,"maxTokens":16384,"thinkingLevelMap":{"off":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5-mini":{"id":"gpt-5-mini","name":"GPT-5 Mini","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.25,"output":2,"cacheRead":0.025,"cacheWrite":0},"contextWindow":400000,"maxTokens":128000,"thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null,"max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5-nano":{"id":"gpt-5-nano","name":"GPT-5 Nano","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.05,"output":0.4,"cacheRead":0.005,"cacheWrite":0},"contextWindow":400000,"maxTokens":128000,"thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null,"max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5-pro":{"id":"gpt-5-pro","name":"GPT-5 Pro","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":15,"output":120,"cacheRead":0,"cacheWrite":0},"contextWindow":400000,"maxTokens":128000,"thinkingLevelMap":{"off":null,"minimal":null,"low":null,"medium":null,"high":"high","xhigh":null,"max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5.1":{"id":"gpt-5.1","name":"GPT-5.1","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":1.25,"output":10,"cacheRead":0.125,"cacheWrite":0},"contextWindow":400000,"maxTokens":128000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null,"max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5.2":{"id":"gpt-5.2","name":"GPT-5.2","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":1.75,"output":14,"cacheRead":0.175,"cacheWrite":0},"contextWindow":400000,"maxTokens":128000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5.2-chat-latest":{"id":"gpt-5.2-chat-latest","name":"GPT-5.2 Chat","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":1.75,"output":14,"cacheRead":0.175,"cacheWrite":0},"contextWindow":128000,"maxTokens":16384,"thinkingLevelMap":{"off":null,"minimal":null,"low":null,"medium":"medium","high":null,"xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5.2-pro":{"id":"gpt-5.2-pro","name":"GPT-5.2 Pro","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":21,"output":168,"cacheRead":0,"cacheWrite":0},"contextWindow":400000,"maxTokens":128000,"thinkingLevelMap":{"off":null,"minimal":null,"low":null,"medium":"medium","high":"high","xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5.3-chat-latest":{"id":"gpt-5.3-chat-latest","name":"GPT-5.3 Chat (latest)","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":false,"input":["text","image"],"cost":{"input":1.75,"output":14,"cacheRead":0.175,"cacheWrite":0},"contextWindow":128000,"maxTokens":16384,"thinkingLevelMap":{"off":null,"xhigh":"xhigh"},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5.3-codex":{"id":"gpt-5.3-codex","name":"GPT-5.3 Codex","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":1.75,"output":14,"cacheRead":0.175,"cacheWrite":0},"contextWindow":400000,"maxTokens":128000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5.3-codex-spark":{"id":"gpt-5.3-codex-spark","name":"GPT-5.3 Codex Spark","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":1.75,"output":14,"cacheRead":0.175,"cacheWrite":0},"contextWindow":128000,"maxTokens":32000,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5.4":{"id":"gpt-5.4","name":"GPT-5.4","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":2.5,"output":15,"cacheRead":0.25,"cacheWrite":0,"tiers":[{"inputTokensAbove":272000,"input":5,"output":22.5,"cacheRead":0.5,"cacheWrite":0}]},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true,"supportsToolSearch":true}},"gpt-5.4-mini":{"id":"gpt-5.4-mini","name":"GPT-5.4 mini","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.75,"output":4.5,"cacheRead":0.075,"cacheWrite":0},"contextWindow":400000,"maxTokens":128000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true,"supportsToolSearch":true}},"gpt-5.4-nano":{"id":"gpt-5.4-nano","name":"GPT-5.4 nano","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.2,"output":1.25,"cacheRead":0.02,"cacheWrite":0},"contextWindow":400000,"maxTokens":128000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5.4-pro":{"id":"gpt-5.4-pro","name":"GPT-5.4 Pro","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":30,"output":180,"cacheRead":0,"cacheWrite":0,"tiers":[{"inputTokensAbove":272000,"input":60,"output":270,"cacheRead":0,"cacheWrite":0}]},"contextWindow":1050000,"maxTokens":128000,"thinkingLevelMap":{"off":null,"minimal":null,"low":null,"medium":"medium","high":"high","xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true,"supportsToolSearch":true}},"gpt-5.5":{"id":"gpt-5.5","name":"GPT-5.5","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":5,"output":30,"cacheRead":0.5,"cacheWrite":0,"tiers":[{"inputTokensAbove":272000,"input":10,"output":45,"cacheRead":1,"cacheWrite":0}]},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true,"supportsToolSearch":true}},"gpt-5.5-pro":{"id":"gpt-5.5-pro","name":"GPT-5.5 Pro","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":30,"output":180,"cacheRead":0,"cacheWrite":0,"tiers":[{"inputTokensAbove":272000,"input":60,"output":270,"cacheRead":0,"cacheWrite":0}]},"contextWindow":1050000,"maxTokens":128000,"thinkingLevelMap":{"off":null,"minimal":null,"low":null,"medium":"medium","high":"high","xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5.6-luna":{"id":"gpt-5.6-luna","name":"GPT-5.6 Luna","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.2,"output":1.2,"cacheRead":0.02,"cacheWrite":0.25,"tiers":[{"inputTokensAbove":272000,"input":0.4,"output":1.7999999999999998,"cacheRead":0.04,"cacheWrite":0.5}]},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":"max"},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true,"supportsToolSearch":true,"supportsExplicitPromptCacheMode":true}},"gpt-5.6-sol":{"id":"gpt-5.6-sol","name":"GPT-5.6 Sol","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":5,"output":30,"cacheRead":0.5,"cacheWrite":6.25,"tiers":[{"inputTokensAbove":272000,"input":10,"output":45,"cacheRead":1,"cacheWrite":12.5}]},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":"max"},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true,"supportsToolSearch":true,"supportsExplicitPromptCacheMode":true}},"gpt-5.6-terra":{"id":"gpt-5.6-terra","name":"GPT-5.6 Terra","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":2,"output":12,"cacheRead":0.2,"cacheWrite":2.5,"tiers":[{"inputTokensAbove":272000,"input":4,"output":18,"cacheRead":0.4,"cacheWrite":5}]},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":"max"},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true,"supportsToolSearch":true,"supportsExplicitPromptCacheMode":true}},"gpt-realtime-2.1":{"id":"gpt-realtime-2.1","name":"GPT-Realtime-2.1","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":4,"output":24,"cacheRead":0.4,"cacheWrite":0},"contextWindow":128000,"maxTokens":32000,"thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true}},"o1":{"id":"o1","name":"o1","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":15,"output":60,"cacheRead":7.5,"cacheWrite":0},"contextWindow":200000,"maxTokens":100000,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null,"max":null},"compat":{"supportsStrictMode":true}},"o1-pro":{"id":"o1-pro","name":"o1-pro","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":150,"output":600,"cacheRead":0,"cacheWrite":0},"contextWindow":200000,"maxTokens":100000,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null,"max":null},"compat":{"supportsStrictMode":true}},"o3":{"id":"o3","name":"o3","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":2,"output":8,"cacheRead":0.5,"cacheWrite":0},"contextWindow":200000,"maxTokens":100000,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null,"max":null},"compat":{"supportsStrictMode":true}},"o3-mini":{"id":"o3-mini","name":"o3-mini","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text"],"cost":{"input":1.1,"output":4.4,"cacheRead":0.55,"cacheWrite":0},"contextWindow":200000,"maxTokens":100000,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null,"max":null},"compat":{"supportsStrictMode":true}},"o3-pro":{"id":"o3-pro","name":"o3-pro","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":20,"output":80,"cacheRead":0,"cacheWrite":0},"contextWindow":200000,"maxTokens":100000,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null,"max":null},"compat":{"supportsStrictMode":true}},"o4-mini":{"id":"o4-mini","name":"o4-mini","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":1.1,"output":4.4,"cacheRead":0.275,"cacheWrite":0},"contextWindow":200000,"maxTokens":100000,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null,"max":null},"compat":{"supportsStrictMode":true}}}}
1
+ {"openai-responses":{"gpt-4":{"id":"gpt-4","name":"GPT-4","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":false,"input":["text"],"cost":{"input":30,"output":60,"cacheRead":0,"cacheWrite":0},"contextWindow":8192,"maxTokens":8192,"compat":{"supportsStrictMode":true}},"gpt-4-turbo":{"id":"gpt-4-turbo","name":"GPT-4 Turbo","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":false,"input":["text","image"],"cost":{"input":10,"output":30,"cacheRead":0,"cacheWrite":0},"contextWindow":128000,"maxTokens":4096,"compat":{"supportsStrictMode":true}},"gpt-4.1":{"id":"gpt-4.1","name":"GPT-4.1","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":false,"input":["text","image"],"cost":{"input":2,"output":8,"cacheRead":0.5,"cacheWrite":0},"contextWindow":1047576,"maxTokens":32768,"compat":{"supportsStrictMode":true}},"gpt-4.1-mini":{"id":"gpt-4.1-mini","name":"GPT-4.1 mini","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":false,"input":["text","image"],"cost":{"input":0.4,"output":1.6,"cacheRead":0.1,"cacheWrite":0},"contextWindow":1047576,"maxTokens":32768,"compat":{"supportsStrictMode":true}},"gpt-4.1-nano":{"id":"gpt-4.1-nano","name":"GPT-4.1 nano","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":false,"input":["text","image"],"cost":{"input":0.1,"output":0.4,"cacheRead":0.025,"cacheWrite":0},"contextWindow":1047576,"maxTokens":32768,"compat":{"supportsStrictMode":true}},"gpt-4o":{"id":"gpt-4o","name":"GPT-4o","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":false,"input":["text","image"],"cost":{"input":2.5,"output":10,"cacheRead":1.25,"cacheWrite":0},"contextWindow":128000,"maxTokens":16384,"compat":{"supportsStrictMode":true}},"gpt-4o-2024-05-13":{"id":"gpt-4o-2024-05-13","name":"GPT-4o (2024-05-13)","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":false,"input":["text","image"],"cost":{"input":5,"output":15,"cacheRead":0,"cacheWrite":0},"contextWindow":128000,"maxTokens":4096,"compat":{"supportsStrictMode":true}},"gpt-4o-2024-08-06":{"id":"gpt-4o-2024-08-06","name":"GPT-4o (2024-08-06)","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":false,"input":["text","image"],"cost":{"input":2.5,"output":10,"cacheRead":1.25,"cacheWrite":0},"contextWindow":128000,"maxTokens":16384,"compat":{"supportsStrictMode":true}},"gpt-4o-2024-11-20":{"id":"gpt-4o-2024-11-20","name":"GPT-4o (2024-11-20)","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":false,"input":["text","image"],"cost":{"input":2.5,"output":10,"cacheRead":1.25,"cacheWrite":0},"contextWindow":128000,"maxTokens":16384,"compat":{"supportsStrictMode":true}},"gpt-4o-mini":{"id":"gpt-4o-mini","name":"GPT-4o mini","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":false,"input":["text","image"],"cost":{"input":0.15,"output":0.6,"cacheRead":0.075,"cacheWrite":0},"contextWindow":128000,"maxTokens":16384,"compat":{"supportsStrictMode":true}},"gpt-5":{"id":"gpt-5","name":"GPT-5","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":1.25,"output":10,"cacheRead":0.125,"cacheWrite":0},"contextWindow":400000,"maxTokens":128000,"thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null,"max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5-chat-latest":{"id":"gpt-5-chat-latest","name":"GPT-5 Chat Latest","api":"openai-responses","baseUrl":"https://api.openai.com/v1","provider":"openai","reasoning":false,"input":["text","image"],"cost":{"input":1.25,"output":10,"cacheRead":0.125,"cacheWrite":0},"contextWindow":128000,"maxTokens":16384,"thinkingLevelMap":{"off":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5-mini":{"id":"gpt-5-mini","name":"GPT-5 Mini","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.25,"output":2,"cacheRead":0.025,"cacheWrite":0},"contextWindow":400000,"maxTokens":128000,"thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null,"max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5-nano":{"id":"gpt-5-nano","name":"GPT-5 Nano","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.05,"output":0.4,"cacheRead":0.005,"cacheWrite":0},"contextWindow":400000,"maxTokens":128000,"thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null,"max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5-pro":{"id":"gpt-5-pro","name":"GPT-5 Pro","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":15,"output":120,"cacheRead":0,"cacheWrite":0},"contextWindow":400000,"maxTokens":128000,"thinkingLevelMap":{"off":null,"minimal":null,"low":null,"medium":null,"high":"high","xhigh":null,"max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5.1":{"id":"gpt-5.1","name":"GPT-5.1","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":1.25,"output":10,"cacheRead":0.125,"cacheWrite":0},"contextWindow":400000,"maxTokens":128000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null,"max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5.2":{"id":"gpt-5.2","name":"GPT-5.2","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":1.75,"output":14,"cacheRead":0.175,"cacheWrite":0},"contextWindow":400000,"maxTokens":128000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5.2-chat-latest":{"id":"gpt-5.2-chat-latest","name":"GPT-5.2 Chat","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":1.75,"output":14,"cacheRead":0.175,"cacheWrite":0},"contextWindow":128000,"maxTokens":16384,"thinkingLevelMap":{"off":null,"minimal":null,"low":null,"medium":"medium","high":null,"xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5.2-pro":{"id":"gpt-5.2-pro","name":"GPT-5.2 Pro","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":21,"output":168,"cacheRead":0,"cacheWrite":0},"contextWindow":400000,"maxTokens":128000,"thinkingLevelMap":{"off":null,"minimal":null,"low":null,"medium":"medium","high":"high","xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5.3-chat-latest":{"id":"gpt-5.3-chat-latest","name":"GPT-5.3 Chat (latest)","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":false,"input":["text","image"],"cost":{"input":1.75,"output":14,"cacheRead":0.175,"cacheWrite":0},"contextWindow":128000,"maxTokens":16384,"thinkingLevelMap":{"off":null,"xhigh":"xhigh"},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5.3-codex":{"id":"gpt-5.3-codex","name":"GPT-5.3 Codex","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":1.75,"output":14,"cacheRead":0.175,"cacheWrite":0},"contextWindow":400000,"maxTokens":128000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5.3-codex-spark":{"id":"gpt-5.3-codex-spark","name":"GPT-5.3 Codex Spark","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":1.75,"output":14,"cacheRead":0.175,"cacheWrite":0},"contextWindow":128000,"maxTokens":32000,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5.4":{"id":"gpt-5.4","name":"GPT-5.4","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":2.5,"output":15,"cacheRead":0.25,"cacheWrite":0,"tiers":[{"inputTokensAbove":272000,"input":5,"output":22.5,"cacheRead":0.5,"cacheWrite":0}]},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true,"supportsToolSearch":true}},"gpt-5.4-mini":{"id":"gpt-5.4-mini","name":"GPT-5.4 mini","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.75,"output":4.5,"cacheRead":0.075,"cacheWrite":0},"contextWindow":400000,"maxTokens":128000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true,"supportsToolSearch":true}},"gpt-5.4-nano":{"id":"gpt-5.4-nano","name":"GPT-5.4 nano","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.2,"output":1.25,"cacheRead":0.02,"cacheWrite":0},"contextWindow":400000,"maxTokens":128000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5.4-pro":{"id":"gpt-5.4-pro","name":"GPT-5.4 Pro","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":30,"output":180,"cacheRead":0,"cacheWrite":0,"tiers":[{"inputTokensAbove":272000,"input":60,"output":270,"cacheRead":0,"cacheWrite":0}]},"contextWindow":1050000,"maxTokens":128000,"thinkingLevelMap":{"off":null,"minimal":null,"low":null,"medium":"medium","high":"high","xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true,"supportsToolSearch":true}},"gpt-5.5":{"id":"gpt-5.5","name":"GPT-5.5","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":5,"output":30,"cacheRead":0.5,"cacheWrite":0,"tiers":[{"inputTokensAbove":272000,"input":10,"output":45,"cacheRead":1,"cacheWrite":0}]},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true,"supportsToolSearch":true}},"gpt-5.5-pro":{"id":"gpt-5.5-pro","name":"GPT-5.5 Pro","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":30,"output":180,"cacheRead":0,"cacheWrite":0,"tiers":[{"inputTokensAbove":272000,"input":60,"output":270,"cacheRead":0,"cacheWrite":0}]},"contextWindow":1050000,"maxTokens":128000,"thinkingLevelMap":{"off":null,"minimal":null,"low":null,"medium":"medium","high":"high","xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true}},"gpt-5.6-luna":{"id":"gpt-5.6-luna","name":"GPT-5.6 Luna","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.2,"output":1.2,"cacheRead":0.02,"cacheWrite":0.25,"tiers":[{"inputTokensAbove":272000,"input":0.4,"output":1.7999999999999998,"cacheRead":0.04,"cacheWrite":0.5}]},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":"max"},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true,"supportsToolSearch":true,"supportsExplicitPromptCacheMode":true}},"gpt-5.6-sol":{"id":"gpt-5.6-sol","name":"GPT-5.6 Sol","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":4,"output":20,"cacheRead":0.4,"cacheWrite":5,"tiers":[{"inputTokensAbove":272000,"input":8,"output":30,"cacheRead":0.8,"cacheWrite":10}]},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":"max"},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true,"supportsToolSearch":true,"supportsExplicitPromptCacheMode":true}},"gpt-5.6-terra":{"id":"gpt-5.6-terra","name":"GPT-5.6 Terra","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":2,"output":12,"cacheRead":0.2,"cacheWrite":2.5,"tiers":[{"inputTokensAbove":272000,"input":4,"output":18,"cacheRead":0.4,"cacheWrite":5}]},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":"max"},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true,"supportsToolSearch":true,"supportsExplicitPromptCacheMode":true}},"gpt-6-astra":{"id":"gpt-6-astra","name":"GPT-6 Astra","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":10,"output":50,"cacheRead":1,"cacheWrite":12.5,"tiers":[{"inputTokensAbove":272000,"input":20,"output":75,"cacheRead":2,"cacheWrite":25}]},"contextWindow":272000,"maxTokens":128000,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":"max"},"compat":{"supportsStrictMode":true,"supportsOpenAIGrammarTools":true,"supportsToolSearch":true,"supportsExplicitPromptCacheMode":true}},"gpt-realtime-2.1":{"id":"gpt-realtime-2.1","name":"GPT-Realtime-2.1","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":4,"output":24,"cacheRead":0.4,"cacheWrite":0},"contextWindow":128000,"maxTokens":32000,"thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null},"compat":{"supportsStrictMode":true}},"o1":{"id":"o1","name":"o1","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":15,"output":60,"cacheRead":7.5,"cacheWrite":0},"contextWindow":200000,"maxTokens":100000,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null,"max":null},"compat":{"supportsStrictMode":true}},"o1-pro":{"id":"o1-pro","name":"o1-pro","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":150,"output":600,"cacheRead":0,"cacheWrite":0},"contextWindow":200000,"maxTokens":100000,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null,"max":null},"compat":{"supportsStrictMode":true}},"o3":{"id":"o3","name":"o3","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":2,"output":8,"cacheRead":0.5,"cacheWrite":0},"contextWindow":200000,"maxTokens":100000,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null,"max":null},"compat":{"supportsStrictMode":true}},"o3-mini":{"id":"o3-mini","name":"o3-mini","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text"],"cost":{"input":1.1,"output":4.4,"cacheRead":0.55,"cacheWrite":0},"contextWindow":200000,"maxTokens":100000,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null,"max":null},"compat":{"supportsStrictMode":true}},"o3-pro":{"id":"o3-pro","name":"o3-pro","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":20,"output":80,"cacheRead":0,"cacheWrite":0},"contextWindow":200000,"maxTokens":100000,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null,"max":null},"compat":{"supportsStrictMode":true}},"o4-mini":{"id":"o4-mini","name":"o4-mini","api":"openai-responses","provider":"openai","baseUrl":"https://api.openai.com/v1","reasoning":true,"input":["text","image"],"cost":{"input":1.1,"output":4.4,"cacheRead":0.275,"cacheWrite":0},"contextWindow":200000,"maxTokens":100000,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null,"max":null},"compat":{"supportsStrictMode":true}}}}
package/dist/types.d.ts CHANGED
@@ -480,7 +480,7 @@ export interface OpenAIResponsesCompat {
480
480
  supportsDeveloperRole?: boolean;
481
481
  /** Session-affinity header format: `openai` sends `session_id` and `x-client-request-id`; `openai-nosession` sends `x-client-request-id`; `openrouter` sends `x-session-id`. Does not affect the `prompt_cache_key` body param, which is governed by cache retention. Default: auto-detected. */
482
482
  sessionAffinityFormat?: SessionAffinityFormat;
483
- /** Whether the provider supports `prompt_cache_retention: "24h"`. Default: true. */
483
+ /** Whether the provider supports long prompt cache retention. This uses `prompt_cache_options.ttl: "30m"` on GPT-5.6+ and `prompt_cache_retention: "24h"` on earlier models. Default: true. */
484
484
  supportsLongCacheRetention?: boolean;
485
485
  /** Whether the provider supports strict JSON-schema function tools. Defaults are API-specific; generated OpenAI models enable it explicitly. */
486
486
  supportsStrictMode?: boolean;
@@ -488,7 +488,7 @@ export interface OpenAIResponsesCompat {
488
488
  supportsOpenAIGrammarTools?: boolean;
489
489
  /** Whether the model supports client-executed tool search for deferred tools. Default: false. */
490
490
  supportsToolSearch?: boolean;
491
- /** Whether the model accepts `prompt_cache_options` (OpenAI GPT-5.6+ explicit prompt caching). Older OpenAI models reject the parameter. Default: false. */
491
+ /** Whether the model accepts `prompt_cache_options` (OpenAI GPT-5.6+ prompt caching). Older models reject the parameter. Default: false. */
492
492
  supportsExplicitPromptCacheMode?: boolean;
493
493
  }
494
494
  /** Compatibility settings for Anthropic Messages-compatible APIs. */