Skip to content

Commit ff820d3

Browse files
fix(openai-completions): bound SSE response reads via buildGuardedModelFetch
Rebased and narrowed to the current-main OpenAI completions guarded-fetch fix. Validation passed locally and GitHub checks were green before merge.
1 parent 74a9beb commit ff820d3

2 files changed

Lines changed: 27 additions & 0 deletions

File tree

src/llm/providers/openai-completions.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,14 @@ type OpenAICompatibleChatCompletionChunk = Omit<DeepPartial<ChatCompletionChunk>
1616
};
1717

1818
const mockChunksRef: { chunks: OpenAICompatibleChatCompletionChunk[] } = { chunks: [] };
19+
const mockOpenAIOptionsRef: { options: unknown[] } = { options: [] };
1920

2021
vi.mock("openai", () => {
2122
class MockOpenAI {
23+
constructor(options: unknown) {
24+
mockOpenAIOptionsRef.options.push(options);
25+
}
26+
2227
chat = {
2328
completions: {
2429
create: () => ({
@@ -118,6 +123,26 @@ function makeFinishChunk(
118123
}
119124

120125
describe("OpenAI-compatible completions params", () => {
126+
it("configures the OpenAI SDK client with guarded fetch", async () => {
127+
mockOpenAIOptionsRef.options = [];
128+
mockChunksRef.chunks = [makeTextChunk("ok"), makeFinishChunk("stop")];
129+
130+
const stream = streamOpenAICompletions(model, context, {
131+
apiKey: "sk-test",
132+
});
133+
const result = await stream.result();
134+
135+
expect(result.stopReason).toBe("stop");
136+
expect(mockOpenAIOptionsRef.options).toHaveLength(1);
137+
expect(mockOpenAIOptionsRef.options[0]).toMatchObject({
138+
baseURL: "https://api.openai.com/v1",
139+
dangerouslyAllowBrowser: true,
140+
});
141+
expect((mockOpenAIOptionsRef.options[0] as { fetch?: unknown }).fetch).toEqual(
142+
expect.any(Function),
143+
);
144+
});
145+
121146
it("skips unreadable schemas while preserving healthy official OpenAI tools", async () => {
122147
let capturedPayload: Record<string, unknown> | undefined;
123148
const stream = streamOpenAICompletions(

src/llm/providers/openai-completions.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
type OpenAICompletionsToolChoice,
1818
type OpenAIToolProjection,
1919
} from "../../agents/openai-tool-projection.js";
20+
import { buildGuardedModelFetch } from "../../agents/provider-transport-fetch.js";
2021
import {
2122
splitSystemPromptCacheBoundary,
2223
stripSystemPromptCacheBoundary,
@@ -616,6 +617,7 @@ function createClient(
616617
baseURL: isCloudflareProvider(model.provider) ? resolveCloudflareBaseUrl(model) : model.baseUrl,
617618
dangerouslyAllowBrowser: true,
618619
defaultHeaders,
620+
fetch: buildGuardedModelFetch(model),
619621
});
620622
}
621623

0 commit comments

Comments
 (0)