@ai-sdk/openai 3.0.83 → 3.0.84

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.
@@ -201,16 +201,20 @@ The following provider options are available:
201
201
  - **user** _string_
202
202
  A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. Defaults to `undefined`.
203
203
 
204
- - **reasoningEffort** _'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh'_
204
+ - **reasoningEffort** _'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max'_
205
205
  Reasoning effort for reasoning models. Defaults to `medium`. If you use `providerOptions` to set the `reasoningEffort` option, this model setting will be ignored.
206
206
 
207
207
  <Note>
208
- The 'none' type for `reasoningEffort` is only available for OpenAI's GPT-5.1
209
- models. Also, the 'xhigh' type for `reasoningEffort` is only available for
210
- OpenAI's GPT-5.1-Codex-Max model. Setting `reasoningEffort` to 'none' or
211
- 'xhigh' with unsupported models will result in an error.
208
+ Supported reasoning efforts vary by model. GPT-5.6 supports `'none'`, `'low'`,
209
+ `'medium'`, `'high'`, `'xhigh'`, and `'max'`.
212
210
  </Note>
213
211
 
212
+ - **reasoningMode** _'standard' | 'pro'_
213
+ Controls how much model work GPT-5.6 performs before returning a final answer. `'standard'` is the default. Use `'pro'` for difficult tasks where quality matters more than latency and token usage.
214
+
215
+ - **reasoningContext** _'auto' | 'current_turn' | 'all_turns'_
216
+ Controls which available reasoning items GPT-5.6 can reuse. `'auto'` uses the model default, `'current_turn'` excludes reasoning from earlier turns, and `'all_turns'` makes compatible earlier reasoning available. The effective context is returned as `providerMetadata.openai.reasoningContext`.
217
+
214
218
  - **reasoningSummary** _'auto' | 'detailed'_
215
219
  Controls whether the model returns its reasoning process. Set to `'auto'` for a condensed summary, `'detailed'` for more comprehensive reasoning. Defaults to `undefined` (no reasoning summaries). When enabled, reasoning summaries appear in the stream as events with type `'reasoning'` and in non-streaming responses within the `reasoning` field.
216
220
 
@@ -253,8 +257,11 @@ The following provider options are available:
253
257
  - **promptCacheKey** _string_
254
258
  A cache key for manual prompt caching control. Used by OpenAI to cache responses for similar requests to optimize your cache hit rates.
255
259
 
260
+ - **promptCacheOptions** _object_
261
+ Configures prompt caching for GPT-5.6 and later models. `mode` can be `'implicit'` or `'explicit'`, and `ttl` currently only supports `'30m'`. In explicit mode, only content blocks marked with a prompt cache breakpoint are cached.
262
+
256
263
  - **promptCacheRetention** _'in_memory' | '24h'_
257
- The retention policy for the prompt cache. Set to `'24h'` to enable extended prompt caching, which keeps cached prefixes active for up to 24 hours. Defaults to `'in_memory'` for standard prompt caching. Note: `'24h'` is currently only available for the 5.1 series of models.
264
+ The legacy retention policy for models before GPT-5.6. Set to `'24h'` to enable extended prompt caching on supported models. For GPT-5.6 and later models, use `promptCacheOptions.ttl` instead.
258
265
 
259
266
  - **safetyIdentifier** _string_
260
267
  A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely identifies each user.
@@ -281,7 +288,8 @@ const providerMetadata = result.providerMetadata as
281
288
  | OpenaiResponsesProviderMetadata
282
289
  | undefined;
283
290
 
284
- const { responseId, logprobs, serviceTier } = providerMetadata?.openai ?? {};
291
+ const { responseId, logprobs, serviceTier, reasoningContext } =
292
+ providerMetadata?.openai ?? {};
285
293
 
286
294
  // responseId can be used to continue a conversation (previousResponseId).
287
295
  console.log(responseId);
@@ -295,6 +303,8 @@ The following OpenAI-specific metadata may be returned:
295
303
  Log probabilities of output tokens (when enabled).
296
304
  - **serviceTier** _(optional)_
297
305
  Service tier information returned by the API.
306
+ - **reasoningContext** _(optional)_
307
+ Effective persisted-reasoning context returned by GPT-5.6 (`'current_turn'` or `'all_turns'`).
298
308
 
299
309
  #### Reasoning Output
300
310
 
@@ -1671,12 +1681,14 @@ The following optional provider options are available for OpenAI chat models:
1671
1681
  A unique identifier representing your end-user, which can help OpenAI to
1672
1682
  monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices/end-user-ids).
1673
1683
 
1674
- - **reasoningEffort** _'minimal' | 'low' | 'medium' | 'high' | 'xhigh'_
1684
+ - **reasoningEffort** _'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max'_
1675
1685
 
1676
1686
  Reasoning effort for reasoning models. Defaults to `medium`. If you use
1677
1687
  `providerOptions` to set the `reasoningEffort` option, this
1678
1688
  model setting will be ignored.
1679
1689
 
1690
+ Supported reasoning efforts vary by model. GPT-5.6 supports `'none'`, `'low'`, `'medium'`, `'high'`, `'xhigh'`, and `'max'`.
1691
+
1680
1692
  - **maxCompletionTokens** _number_
1681
1693
 
1682
1694
  Maximum number of completion tokens to generate. Useful for reasoning models.
@@ -1714,9 +1726,13 @@ The following optional provider options are available for OpenAI chat models:
1714
1726
 
1715
1727
  A cache key for manual prompt caching control. Used by OpenAI to cache responses for similar requests to optimize your cache hit rates.
1716
1728
 
1729
+ - **promptCacheOptions** _object_
1730
+
1731
+ Configures prompt caching for GPT-5.6 and later models. `mode` can be `'implicit'` or `'explicit'`, and `ttl` currently only supports `'30m'`. In explicit mode, only content blocks marked with a prompt cache breakpoint are cached.
1732
+
1717
1733
  - **promptCacheRetention** _'in_memory' | '24h'_
1718
1734
 
1719
- The retention policy for the prompt cache. Set to `'24h'` to enable extended prompt caching, which keeps cached prefixes active for up to 24 hours. Defaults to `'in_memory'` for standard prompt caching. Note: `'24h'` is currently only available for the 5.1 series of models.
1735
+ The legacy retention policy for models before GPT-5.6. Set to `'24h'` to enable extended prompt caching on supported models. For GPT-5.6 and later models, use `promptCacheOptions.ttl` instead.
1720
1736
 
1721
1737
  - **safetyIdentifier** _string_
1722
1738
 
@@ -2021,7 +2037,7 @@ const rejectedPredictionTokens = openaiMetadata?.rejectedPredictionTokens;
2021
2037
 
2022
2038
  #### Image Detail
2023
2039
 
2024
- You can use the `openai` provider option to set the [image input detail](https://platform.openai.com/docs/guides/images-vision?api-mode=responses#specify-image-input-detail-level) to `high`, `low`, or `auto`:
2040
+ You can use the `openai` provider option to set the [image input detail](https://platform.openai.com/docs/guides/images-vision?api-mode=responses#specify-image-input-detail-level) to `high`, `low`, `original`, or `auto`:
2025
2041
 
2026
2042
  ```ts highlight="13-16"
2027
2043
  const result = await generateText({
@@ -2047,6 +2063,8 @@ const result = await generateText({
2047
2063
  });
2048
2064
  ```
2049
2065
 
2066
+ For GPT-5.6, `original` preserves the input dimensions without resizing to a patch budget or pixel-dimension limit. `auto` and an omitted detail setting use the same sizing behavior as `original`, which can increase input token usage for large images.
2067
+
2050
2068
  <Note type="warning">
2051
2069
  Because the `UIMessage` type (used by AI SDK UI hooks like `useChat`) does not
2052
2070
  support the `providerOptions` property, you can use `convertToModelMessages`
@@ -2095,24 +2113,20 @@ including `gpt-4o` and `gpt-4o-mini`.
2095
2113
 
2096
2114
  - Prompt caching is automatically enabled for these models, when the prompt is 1024 tokens or longer. It does
2097
2115
  not need to be explicitly enabled.
2098
- - You can use response `providerMetadata` to access the number of prompt tokens that were a cache hit.
2099
- - Note that caching behavior is dependent on load on OpenAI's infrastructure. Prompt prefixes generally remain in the
2100
- cache following 5-10 minutes of inactivity before they are evicted, but during off-peak periods they may persist for up
2101
- to an hour.
2116
+ - You can use the response `usage` to access the number of prompt tokens that were a cache hit via `usage.inputTokenDetails.cacheReadTokens`.
2117
+ - For GPT-5.6 and later models, `usage.inputTokenDetails.cacheWriteTokens` reports tokens written to the cache.
2118
+ - For GPT-5.6 and later models, `promptCacheOptions.ttl` sets a minimum cache lifetime of 30 minutes. Earlier models generally retain in-memory prefixes for 5-10 minutes of inactivity, up to one hour.
2102
2119
 
2103
2120
  ```ts highlight="11"
2104
2121
  import { openai } from '@ai-sdk/openai';
2105
2122
  import { generateText } from 'ai';
2106
2123
 
2107
- const { text, usage, providerMetadata } = await generateText({
2124
+ const { text, usage } = await generateText({
2108
2125
  model: openai.chat('gpt-4o-mini'),
2109
2126
  prompt: `A 1024-token or longer prompt...`,
2110
2127
  });
2111
2128
 
2112
- console.log(`usage:`, {
2113
- ...usage,
2114
- cachedPromptTokens: providerMetadata?.openai?.cachedPromptTokens,
2115
- });
2129
+ console.log('Cached tokens:', usage.inputTokenDetails.cacheReadTokens);
2116
2130
  ```
2117
2131
 
2118
2132
  To improve cache hit rates, you can manually control caching using the `promptCacheKey` option:
@@ -2121,7 +2135,7 @@ To improve cache hit rates, you can manually control caching using the `promptCa
2121
2135
  import { openai, type OpenAILanguageModelChatOptions } from '@ai-sdk/openai';
2122
2136
  import { generateText } from 'ai';
2123
2137
 
2124
- const { text, usage, providerMetadata } = await generateText({
2138
+ const { text, usage } = await generateText({
2125
2139
  model: openai.chat('gpt-5'),
2126
2140
  prompt: `A 1024-token or longer prompt...`,
2127
2141
  providerOptions: {
@@ -2131,33 +2145,69 @@ const { text, usage, providerMetadata } = await generateText({
2131
2145
  },
2132
2146
  });
2133
2147
 
2134
- console.log(`usage:`, {
2135
- ...usage,
2136
- cachedPromptTokens: providerMetadata?.openai?.cachedPromptTokens,
2148
+ console.log('Cached tokens:', usage.inputTokenDetails.cacheReadTokens);
2149
+ ```
2150
+
2151
+ GPT-5.6 and later models support explicit cache breakpoints on text, image, and file content blocks. Set a request-level cache key and mark the end of each reusable prefix with `promptCacheBreakpoint`:
2152
+
2153
+ ```ts highlight="9-12,20-28"
2154
+ import {
2155
+ openai,
2156
+ type OpenAILanguageModelResponsesOptions,
2157
+ } from '@ai-sdk/openai';
2158
+ import { generateText } from 'ai';
2159
+
2160
+ const { usage } = await generateText({
2161
+ model: openai('gpt-5.6'),
2162
+ providerOptions: {
2163
+ openai: {
2164
+ promptCacheKey: 'tenant:acme:support-v1',
2165
+ promptCacheOptions: { mode: 'explicit', ttl: '30m' },
2166
+ } satisfies OpenAILanguageModelResponsesOptions,
2167
+ },
2168
+ messages: [
2169
+ {
2170
+ role: 'user',
2171
+ content: [
2172
+ {
2173
+ type: 'text',
2174
+ text: `A stable prefix of at least 1024 tokens...`,
2175
+ providerOptions: {
2176
+ openai: {
2177
+ promptCacheBreakpoint: { mode: 'explicit' },
2178
+ },
2179
+ },
2180
+ },
2181
+ { type: 'text', text: 'What should I do next?' },
2182
+ ],
2183
+ },
2184
+ ],
2137
2185
  });
2186
+
2187
+ console.log('Cache reads:', usage.inputTokenDetails.cacheReadTokens);
2188
+ console.log('Cache writes:', usage.inputTokenDetails.cacheWriteTokens);
2138
2189
  ```
2139
2190
 
2140
- For GPT-5.1 models, you can enable extended prompt caching that keeps cached prefixes active for up to 24 hours:
2191
+ In `'implicit'` mode, OpenAI places an automatic breakpoint on the latest message and also honors explicit breakpoints. In `'explicit'` mode, only marked content blocks are eligible for caching; a request without any explicit breakpoint does not use prompt caching.
2192
+
2193
+ For models before GPT-5.6 that support extended caching, you can keep cached prefixes active for up to 24 hours:
2141
2194
 
2142
2195
  ```ts highlight="7-12"
2143
2196
  import { openai, type OpenAILanguageModelChatOptions } from '@ai-sdk/openai';
2144
2197
  import { generateText } from 'ai';
2145
2198
 
2146
- const { text, usage, providerMetadata } = await generateText({
2147
- model: openai.chat('gpt-5.1'),
2199
+ const { text, usage } = await generateText({
2200
+ model: openai.chat('gpt-5.5'),
2148
2201
  prompt: `A 1024-token or longer prompt...`,
2149
2202
  providerOptions: {
2150
2203
  openai: {
2151
2204
  promptCacheKey: 'my-custom-cache-key-123',
2152
- promptCacheRetention: '24h', // Extended caching for GPT-5.1
2205
+ promptCacheRetention: '24h',
2153
2206
  } satisfies OpenAILanguageModelChatOptions,
2154
2207
  },
2155
2208
  });
2156
2209
 
2157
- console.log(`usage:`, {
2158
- ...usage,
2159
- cachedPromptTokens: providerMetadata?.openai?.cachedPromptTokens,
2160
- });
2210
+ console.log('Cached tokens:', usage.inputTokenDetails.cacheReadTokens);
2161
2211
  ```
2162
2212
 
2163
2213
  #### Audio Input
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/openai",
3
- "version": "3.0.83",
3
+ "version": "3.0.84",
4
4
  "license": "Apache-2.0",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
@@ -6,6 +6,7 @@ export type OpenAIChatUsage = {
6
6
  total_tokens?: number | null;
7
7
  prompt_tokens_details?: {
8
8
  cached_tokens?: number | null;
9
+ cache_write_tokens?: number | null;
9
10
  } | null;
10
11
  completion_tokens_details?: {
11
12
  reasoning_tokens?: number | null;
@@ -37,15 +38,17 @@ export function convertOpenAIChatUsage(
37
38
  const promptTokens = usage.prompt_tokens ?? 0;
38
39
  const completionTokens = usage.completion_tokens ?? 0;
39
40
  const cachedTokens = usage.prompt_tokens_details?.cached_tokens ?? 0;
41
+ const cacheWriteTokens =
42
+ usage.prompt_tokens_details?.cache_write_tokens ?? undefined;
40
43
  const reasoningTokens =
41
44
  usage.completion_tokens_details?.reasoning_tokens ?? 0;
42
45
 
43
46
  return {
44
47
  inputTokens: {
45
48
  total: promptTokens,
46
- noCache: promptTokens - cachedTokens,
49
+ noCache: promptTokens - cachedTokens - (cacheWriteTokens ?? 0),
47
50
  cacheRead: cachedTokens,
48
- cacheWrite: undefined,
51
+ cacheWrite: cacheWriteTokens,
49
52
  },
50
53
  outputTokens: {
51
54
  total: completionTokens,
@@ -2,6 +2,7 @@ import {
2
2
  UnsupportedFunctionalityError,
3
3
  type SharedV3Warning,
4
4
  type LanguageModelV3Prompt,
5
+ type SharedV3ProviderOptions,
5
6
  } from '@ai-sdk/provider';
6
7
  import type { OpenAIChatPrompt } from './openai-chat-prompt';
7
8
  import { convertToBase64 } from '@ai-sdk/provider-utils';
@@ -10,6 +11,16 @@ function serializeToolCallArguments(input: unknown): string {
10
11
  return JSON.stringify(input === undefined ? {} : input);
11
12
  }
12
13
 
14
+ type OpenAIPromptCacheBreakpoint = { mode: 'explicit' };
15
+
16
+ function getPromptCacheBreakpoint(
17
+ providerOptions: SharedV3ProviderOptions | undefined,
18
+ ): OpenAIPromptCacheBreakpoint | undefined {
19
+ return providerOptions?.openai?.promptCacheBreakpoint as
20
+ | OpenAIPromptCacheBreakpoint
21
+ | undefined;
22
+ }
23
+
13
24
  export function convertToOpenAIChatMessages({
14
25
  prompt,
15
26
  systemMessageMode = 'system',
@@ -23,16 +34,44 @@ export function convertToOpenAIChatMessages({
23
34
  const messages: OpenAIChatPrompt = [];
24
35
  const warnings: Array<SharedV3Warning> = [];
25
36
 
26
- for (const { role, content } of prompt) {
37
+ for (const { role, content, providerOptions } of prompt) {
27
38
  switch (role) {
28
39
  case 'system': {
29
40
  switch (systemMessageMode) {
30
41
  case 'system': {
31
- messages.push({ role: 'system', content });
42
+ const promptCacheBreakpoint =
43
+ getPromptCacheBreakpoint(providerOptions);
44
+ messages.push({
45
+ role: 'system',
46
+ content:
47
+ promptCacheBreakpoint == null
48
+ ? content
49
+ : [
50
+ {
51
+ type: 'text',
52
+ text: content,
53
+ prompt_cache_breakpoint: promptCacheBreakpoint,
54
+ },
55
+ ],
56
+ });
32
57
  break;
33
58
  }
34
59
  case 'developer': {
35
- messages.push({ role: 'developer', content });
60
+ const promptCacheBreakpoint =
61
+ getPromptCacheBreakpoint(providerOptions);
62
+ messages.push({
63
+ role: 'developer',
64
+ content:
65
+ promptCacheBreakpoint == null
66
+ ? content
67
+ : [
68
+ {
69
+ type: 'text',
70
+ text: content,
71
+ prompt_cache_breakpoint: promptCacheBreakpoint,
72
+ },
73
+ ],
74
+ });
36
75
  break;
37
76
  }
38
77
  case 'remove': {
@@ -53,7 +92,11 @@ export function convertToOpenAIChatMessages({
53
92
  }
54
93
 
55
94
  case 'user': {
56
- if (content.length === 1 && content[0].type === 'text') {
95
+ if (
96
+ content.length === 1 &&
97
+ content[0].type === 'text' &&
98
+ getPromptCacheBreakpoint(content[0].providerOptions) == null
99
+ ) {
57
100
  messages.push({ role: 'user', content: content[0].text });
58
101
  break;
59
102
  }
@@ -63,9 +106,21 @@ export function convertToOpenAIChatMessages({
63
106
  content: content.map((part, index) => {
64
107
  switch (part.type) {
65
108
  case 'text': {
66
- return { type: 'text', text: part.text };
109
+ const promptCacheBreakpoint = getPromptCacheBreakpoint(
110
+ part.providerOptions,
111
+ );
112
+ return {
113
+ type: 'text',
114
+ text: part.text,
115
+ ...(promptCacheBreakpoint != null && {
116
+ prompt_cache_breakpoint: promptCacheBreakpoint,
117
+ }),
118
+ };
67
119
  }
68
120
  case 'file': {
121
+ const promptCacheBreakpoint = getPromptCacheBreakpoint(
122
+ part.providerOptions,
123
+ );
69
124
  if (part.mediaType.startsWith('image/')) {
70
125
  const mediaType =
71
126
  part.mediaType === 'image/*'
@@ -83,6 +138,9 @@ export function convertToOpenAIChatMessages({
83
138
  // OpenAI specific extension: image detail
84
139
  detail: part.providerOptions?.openai?.imageDetail,
85
140
  },
141
+ ...(promptCacheBreakpoint != null && {
142
+ prompt_cache_breakpoint: promptCacheBreakpoint,
143
+ }),
86
144
  };
87
145
  } else if (part.mediaType.startsWith('audio/')) {
88
146
  if (part.data instanceof URL) {
@@ -99,6 +157,9 @@ export function convertToOpenAIChatMessages({
99
157
  data: convertToBase64(part.data),
100
158
  format: 'wav',
101
159
  },
160
+ ...(promptCacheBreakpoint != null && {
161
+ prompt_cache_breakpoint: promptCacheBreakpoint,
162
+ }),
102
163
  };
103
164
  }
104
165
  case 'audio/mp3':
@@ -109,6 +170,9 @@ export function convertToOpenAIChatMessages({
109
170
  data: convertToBase64(part.data),
110
171
  format: 'mp3',
111
172
  },
173
+ ...(promptCacheBreakpoint != null && {
174
+ prompt_cache_breakpoint: promptCacheBreakpoint,
175
+ }),
112
176
  };
113
177
  }
114
178
 
@@ -135,6 +199,9 @@ export function convertToOpenAIChatMessages({
135
199
  filename: part.filename ?? `part-${index}.pdf`,
136
200
  file_data: `data:application/pdf;base64,${convertToBase64(part.data)}`,
137
201
  },
202
+ ...(promptCacheBreakpoint != null && {
203
+ prompt_cache_breakpoint: promptCacheBreakpoint,
204
+ }),
138
205
  };
139
206
  } else {
140
207
  throw new UnsupportedFunctionalityError({
@@ -151,6 +218,12 @@ export function convertToOpenAIChatMessages({
151
218
 
152
219
  case 'assistant': {
153
220
  let text = '';
221
+ const textParts: Array<{
222
+ type: 'text';
223
+ text: string;
224
+ prompt_cache_breakpoint?: OpenAIPromptCacheBreakpoint;
225
+ }> = [];
226
+ let hasPromptCacheBreakpoint = false;
154
227
  const toolCalls: Array<{
155
228
  id: string;
156
229
  type: 'function';
@@ -160,7 +233,18 @@ export function convertToOpenAIChatMessages({
160
233
  for (const part of content) {
161
234
  switch (part.type) {
162
235
  case 'text': {
236
+ const promptCacheBreakpoint = getPromptCacheBreakpoint(
237
+ part.providerOptions,
238
+ );
163
239
  text += part.text;
240
+ textParts.push({
241
+ type: 'text',
242
+ text: part.text,
243
+ ...(promptCacheBreakpoint != null && {
244
+ prompt_cache_breakpoint: promptCacheBreakpoint,
245
+ }),
246
+ });
247
+ hasPromptCacheBreakpoint ||= promptCacheBreakpoint != null;
164
248
  break;
165
249
  }
166
250
  case 'tool-call': {
@@ -179,7 +263,11 @@ export function convertToOpenAIChatMessages({
179
263
 
180
264
  messages.push({
181
265
  role: 'assistant',
182
- content: toolCalls.length > 0 ? text || null : text,
266
+ content: hasPromptCacheBreakpoint
267
+ ? textParts
268
+ : toolCalls.length > 0
269
+ ? text || null
270
+ : text,
183
271
  tool_calls: toolCalls.length > 0 ? toolCalls : undefined,
184
272
  });
185
273
 
@@ -192,6 +280,13 @@ export function convertToOpenAIChatMessages({
192
280
  continue;
193
281
  }
194
282
  const output = toolResponse.output;
283
+ const promptCacheBreakpoint =
284
+ (output.type === 'content'
285
+ ? output.value
286
+ .map(part => getPromptCacheBreakpoint(part.providerOptions))
287
+ .find(breakpoint => breakpoint != null)
288
+ : getPromptCacheBreakpoint(output.providerOptions)) ??
289
+ getPromptCacheBreakpoint(toolResponse.providerOptions);
195
290
 
196
291
  let contentValue: string;
197
292
  switch (output.type) {
@@ -212,7 +307,16 @@ export function convertToOpenAIChatMessages({
212
307
  messages.push({
213
308
  role: 'tool',
214
309
  tool_call_id: toolResponse.toolCallId,
215
- content: contentValue,
310
+ content:
311
+ promptCacheBreakpoint == null
312
+ ? contentValue
313
+ : [
314
+ {
315
+ type: 'text',
316
+ text: contentValue,
317
+ prompt_cache_breakpoint: promptCacheBreakpoint,
318
+ },
319
+ ],
216
320
  });
217
321
  }
218
322
  break;
@@ -92,6 +92,7 @@ export const openaiChatResponseSchema = lazySchema(() =>
92
92
  prompt_tokens_details: z
93
93
  .object({
94
94
  cached_tokens: z.number().nullish(),
95
+ cache_write_tokens: z.number().nullish(),
95
96
  })
96
97
  .nullish(),
97
98
  completion_tokens_details: z
@@ -180,6 +181,7 @@ export const openaiChatChunkSchema = lazySchema(() =>
180
181
  prompt_tokens_details: z
181
182
  .object({
182
183
  cached_tokens: z.number().nullish(),
184
+ cache_write_tokens: z.number().nullish(),
183
185
  })
184
186
  .nullish(),
185
187
  completion_tokens_details: z
@@ -171,6 +171,7 @@ export class OpenAIChatLanguageModel implements LanguageModelV3 {
171
171
  reasoning_effort: openaiOptions.reasoningEffort,
172
172
  service_tier: openaiOptions.serviceTier,
173
173
  prompt_cache_key: openaiOptions.promptCacheKey,
174
+ prompt_cache_options: openaiOptions.promptCacheOptions,
174
175
  prompt_cache_retention: openaiOptions.promptCacheRetention,
175
176
  safety_identifier: openaiOptions.safetyIdentifier,
176
177
 
@@ -109,7 +109,7 @@ export const openaiLanguageModelChatOptions = lazySchema(() =>
109
109
  * Reasoning effort for reasoning models. Defaults to `medium`.
110
110
  */
111
111
  reasoningEffort: z
112
- .enum(['none', 'minimal', 'low', 'medium', 'high', 'xhigh'])
112
+ .enum(['none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'])
113
113
  .optional(),
114
114
 
115
115
  /**
@@ -163,11 +163,25 @@ export const openaiLanguageModelChatOptions = lazySchema(() =>
163
163
  */
164
164
  promptCacheKey: z.string().optional(),
165
165
 
166
+ /**
167
+ * Prompt cache behavior for GPT-5.6 and later models.
168
+ * `mode` controls whether OpenAI also places an implicit breakpoint.
169
+ * `ttl` sets the minimum cache lifetime and currently only supports 30 minutes.
170
+ */
171
+ promptCacheOptions: z
172
+ .object({
173
+ mode: z.enum(['implicit', 'explicit']).optional(),
174
+ ttl: z.literal('30m').optional(),
175
+ })
176
+ .optional(),
177
+
166
178
  /**
167
179
  * The retention policy for the prompt cache.
168
180
  * - 'in_memory': Default. Standard prompt caching behavior.
169
181
  * - '24h': Extended prompt caching that keeps cached prefixes active for up to 24 hours.
170
- * Currently only available for 5.1 series models.
182
+ * Available for models before GPT-5.6 that support extended caching.
183
+ *
184
+ * @deprecated For GPT-5.6 and later models, use `promptCacheOptions.ttl`.
171
185
  *
172
186
  * @default 'in_memory'
173
187
  */
@@ -9,12 +9,12 @@ export type ChatCompletionMessage =
9
9
 
10
10
  export interface ChatCompletionSystemMessage {
11
11
  role: 'system';
12
- content: string;
12
+ content: string | Array<ChatCompletionContentPartText>;
13
13
  }
14
14
 
15
15
  export interface ChatCompletionDeveloperMessage {
16
16
  role: 'developer';
17
- content: string;
17
+ content: string | Array<ChatCompletionContentPartText>;
18
18
  }
19
19
 
20
20
  export interface ChatCompletionUserMessage {
@@ -31,26 +31,30 @@ export type ChatCompletionContentPart =
31
31
  export interface ChatCompletionContentPartText {
32
32
  type: 'text';
33
33
  text: string;
34
+ prompt_cache_breakpoint?: { mode: 'explicit' };
34
35
  }
35
36
 
36
37
  export interface ChatCompletionContentPartImage {
37
38
  type: 'image_url';
38
39
  image_url: { url: string };
40
+ prompt_cache_breakpoint?: { mode: 'explicit' };
39
41
  }
40
42
 
41
43
  export interface ChatCompletionContentPartInputAudio {
42
44
  type: 'input_audio';
43
45
  input_audio: { data: string; format: 'wav' | 'mp3' };
46
+ prompt_cache_breakpoint?: { mode: 'explicit' };
44
47
  }
45
48
 
46
49
  export interface ChatCompletionContentPartFile {
47
50
  type: 'file';
48
51
  file: { filename: string; file_data: string } | { file_id: string };
52
+ prompt_cache_breakpoint?: { mode: 'explicit' };
49
53
  }
50
54
 
51
55
  export interface ChatCompletionAssistantMessage {
52
56
  role: 'assistant';
53
- content?: string | null;
57
+ content?: string | null | Array<ChatCompletionContentPartText>;
54
58
  tool_calls?: Array<ChatCompletionMessageToolCall>;
55
59
  }
56
60
 
@@ -65,6 +69,6 @@ export interface ChatCompletionMessageToolCall {
65
69
 
66
70
  export interface ChatCompletionToolMessage {
67
71
  role: 'tool';
68
- content: string;
72
+ content: string | Array<ChatCompletionContentPartText>;
69
73
  tool_call_id: string;
70
74
  }
@@ -5,6 +5,7 @@ export type OpenAIResponsesUsage = {
5
5
  output_tokens: number;
6
6
  input_tokens_details?: {
7
7
  cached_tokens?: number | null;
8
+ cache_write_tokens?: number | null;
8
9
  orchestration_input_tokens?: number | null;
9
10
  orchestration_input_cached_tokens?: number | null;
10
11
  } | null;
@@ -37,14 +38,16 @@ export function convertOpenAIResponsesUsage(
37
38
  const inputTokens = usage.input_tokens;
38
39
  const outputTokens = usage.output_tokens;
39
40
  const cachedTokens = usage.input_tokens_details?.cached_tokens ?? 0;
41
+ const cacheWriteTokens =
42
+ usage.input_tokens_details?.cache_write_tokens ?? undefined;
40
43
  const reasoningTokens = usage.output_tokens_details?.reasoning_tokens ?? 0;
41
44
 
42
45
  return {
43
46
  inputTokens: {
44
47
  total: inputTokens,
45
- noCache: inputTokens - cachedTokens,
48
+ noCache: inputTokens - cachedTokens - (cacheWriteTokens ?? 0),
46
49
  cacheRead: cachedTokens,
47
- cacheWrite: undefined,
50
+ cacheWrite: cacheWriteTokens,
48
51
  },
49
52
  outputTokens: {
50
53
  total: outputTokens,