Repository navigation
@ai-sdk/openai@4.0.110
Patch Changes
-
c6efa4b: Refactor Azure model ID logic into a model catalog that declares capabilities and provider options, and generate provider capability documentation from it. Export the OpenAI catalog internally for Azure to reuse. Request behavior is unchanged.
-
f6dbf04: fix(openai): surface Chat Completions refusals as text content
The Chat Completions model ignored
message.refusal(non-streaming) anddelta.refusal(streaming). When the model refused to answer,contentwasnull, so the AI SDK returned empty text with astopfinish reason and silently dropped the refusal. Refusal text is now emitted as text content in bothgenerateTextandstreamTextresults, and it is emitted in addition to content when the API returns both. A refusal with astopfinish reason is now reported as acontent-filterfinish reason, matching the Anthropic provider and the Responses API. -
646a7e3: fix(openai,openai-compatible): surface refusal logprobs and openai-compatible refusals
@ai-sdk/openai: Chat Completions responses that contain a refusal can returnlogprobs.refusalnext tologprobs.content. The provider previously read onlylogprobs.content, soproviderMetadata.openai.logprobswas empty or missing for refusals. Refusal logprobs are now included in emission order (content logprobs followed by refusal logprobs) in bothgenerateTextandstreamText.Streaming logprobs are now collected across all chunks in
streamText: previously only the logprobs of the last streamed chunk were reported. This applies to content logprobs as well, soproviderMetadata.openai.logprobsnow contains the logprobs of every streamed token instead of only the last chunk's tokens. Explicitly empty logprobs (logprobs: { content: [], refusal: null }) are reported as an empty array, as before.A refusal that arrives in the same streamed chunk as the
finish_reasonis now taken into account: such a response is reported with acontent-filterfinish reason instead ofstop.@ai-sdk/openai-compatible: Chat Completions responses that carrymessage.refusal(non-streaming) ordelta.refusal(streaming) were ignored, so providers such as OpenAI served throughcreateOpenAICompatiblelost the refusal text and reported an emptystopresponse. Refusals are now returned as text content after any content text, and a non-empty refusal with astopfinish reason is reported as acontent-filterfinish reason. This also applies when the refusal and the finish reason arrive in the same streamed chunk. Non-string refusals (for examplerefusal: falsefrom servers that use booleans) are ignored instead of failing the response. -
6b97088: fix(openai): handle refusal content parts in the Responses API
The Responses API returns a
refusalcontent part instead ofoutput_textwhen the model declines a request. The response schema rejected these parts, so non-streaming calls failed with anAPICallError("Invalid JSON response"), and streamedresponse.refusal.delta/response.refusal.doneevents were dropped, producing empty text. Refusal content parts and stream events are now parsed: the refusal explanation is surfaced as text and the finish reason is mapped tocontent-filter. When the response also contains a client-side function call, the finish reason staystool-callsso the tools are still executed.