From 33431b7e74517a32872b2b093629df82ca9004a8 Mon Sep 17 00:00:00 2001 From: JSap0914 Date: Fri, 3 Jul 2026 20:27:41 +0900 Subject: [PATCH] fix(openai): limit stream_options to official API --- .../openai-adapters/src/apis/OpenAI.test.ts | 32 +++++++++++++++++++ packages/openai-adapters/src/apis/OpenAI.ts | 7 ++-- 2 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 packages/openai-adapters/src/apis/OpenAI.test.ts diff --git a/packages/openai-adapters/src/apis/OpenAI.test.ts b/packages/openai-adapters/src/apis/OpenAI.test.ts new file mode 100644 index 00000000000..c3aab18d719 --- /dev/null +++ b/packages/openai-adapters/src/apis/OpenAI.test.ts @@ -0,0 +1,32 @@ +import { ChatCompletionCreateParams } from "openai/resources/index"; +import { describe, expect, it } from "vitest"; + +import { OpenAIApi } from "./OpenAI.js"; + +const streamingBody = (): ChatCompletionCreateParams => ({ + model: "gpt-4.1", + messages: [{ role: "user", content: "hello" }], + stream: true, +}); + +describe("OpenAIApi modifyChatBody stream_options", () => { + it("adds stream_options for official OpenAI streaming requests", () => { + const api = new OpenAIApi({ provider: "openai", apiKey: "test-key" }); + + const modifiedBody = api.modifyChatBody(streamingBody()); + + expect((modifiedBody as any).stream_options).toEqual({ include_usage: true }); + }); + + it("does not add OpenAI-only stream_options for compatible endpoints", () => { + const api = new OpenAIApi({ + provider: "openai", + apiKey: "test-key", + apiBase: "https://example.cloud.databricks.com/serving-endpoints/chat/invocations", + }); + + const modifiedBody = api.modifyChatBody(streamingBody()); + + expect((modifiedBody as any).stream_options).toBeUndefined(); + }); +}); diff --git a/packages/openai-adapters/src/apis/OpenAI.ts b/packages/openai-adapters/src/apis/OpenAI.ts index d0f8d30ca3a..0810bbe26b5 100644 --- a/packages/openai-adapters/src/apis/OpenAI.ts +++ b/packages/openai-adapters/src/apis/OpenAI.ts @@ -49,8 +49,10 @@ export class OpenAIApi implements BaseLlmApi { }); } modifyChatBody(body: T): T { - // Add stream_options to include usage in streaming responses - if (body.stream) { + const isOfficialOpenAIAPI = this.apiBase === "https://api.openai.com/v1/"; + + // Add stream_options to include usage in official OpenAI streaming responses + if (body.stream && isOfficialOpenAIAPI) { (body as any).stream_options = { include_usage: true }; } @@ -65,7 +67,6 @@ export class OpenAIApi implements BaseLlmApi { } // o-series models - only apply for official OpenAI API - const isOfficialOpenAIAPI = this.apiBase === "https://api.openai.com/v1/"; if (isOfficialOpenAIAPI) { if (body.model.startsWith("o") || body.model.includes("gpt-5")) { // a) use max_completion_tokens instead of max_tokens