






















@@ -373,12 +373,12 @@ describe("buildGuardedModelFetch", () => {
373373});
374374const model = {
375375id: "gpt-5.4",
376-provider: "openai",
376+provider: "openrouter",
377377api: "openai-responses",
378-baseUrl: "https://api.openai.com/v1",
378+baseUrl: "https://openrouter.ai/api/v1",
379379} as unknown as Model<"openai-responses">;
380380381-const response = await buildGuardedModelFetch(model)("https://api.openai.com/v1/responses", {
381+const response = await buildGuardedModelFetch(model)("https://openrouter.ai/api/v1/responses", {
382382method: "POST",
383383});
384384const items = [];
@@ -389,6 +389,30 @@ describe("buildGuardedModelFetch", () => {
389389expect(items).toEqual([{ ok: true }]);
390390});
391391392+it("leaves official OpenAI SSE streams unmodified", async () => {
393+fetchWithSsrFGuardMock.mockResolvedValue({
394+response: new Response('event: response.created\n\ndata: {"ok": true}\n\n', {
395+headers: { "content-type": "text/event-stream" },
396+}),
397+finalUrl: "https://api.openai.com/v1/responses",
398+release: vi.fn(async () => undefined),
399+});
400+const model = {
401+id: "gpt-5.5",
402+provider: "openai",
403+api: "openai-responses",
404+baseUrl: "https://api.openai.com/v1",
405+} as unknown as Model<"openai-responses">;
406+407+const response = await buildGuardedModelFetch(model)("https://api.openai.com/v1/responses", {
408+method: "POST",
409+});
410+411+await expect(response.text()).resolves.toBe(
412+'event: response.created\n\ndata: {"ok": true}\n\n',
413+);
414+});
415+392416it("drops whitespace-only SSE data frames with CRLF delimiters", async () => {
393417fetchWithSsrFGuardMock.mockResolvedValue({
394418response: new Response('event: message\r\ndata: \r\n\r\ndata: {"ok": true}\r\n\r\n', {
@@ -399,13 +423,13 @@ describe("buildGuardedModelFetch", () => {
399423});
400424const model = {
401425id: "gpt-5.4",
402-provider: "openai",
426+provider: "openrouter",
403427api: "openai-completions",
404-baseUrl: "https://api.openai.com/v1",
428+baseUrl: "https://openrouter.ai/api/v1",
405429} as unknown as Model<"openai-completions">;
406430407431const response = await buildGuardedModelFetch(model)(
408-"https://api.openai.com/v1/chat/completions",
432+"https://openrouter.ai/api/v1/chat/completions",
409433{ method: "POST" },
410434);
411435const items = [];
@@ -448,6 +472,33 @@ describe("buildGuardedModelFetch", () => {
448472expect(items).toEqual([{ ok: true }]);
449473});
450474475+it("does not clone Request bodies while checking for streaming JSON fallbacks", async () => {
476+const cloneSpy = vi.spyOn(Request.prototype, "clone");
477+fetchWithSsrFGuardMock.mockResolvedValue({
478+response: new Response('{"ok": true}', {
479+headers: { "content-type": "application/json" },
480+}),
481+finalUrl: "https://api.openai.com/v1/responses",
482+release: vi.fn(async () => undefined),
483+});
484+const model = {
485+id: "gpt-5.5",
486+provider: "openai",
487+api: "openai-responses",
488+baseUrl: "https://api.openai.com/v1",
489+} as unknown as Model<"openai-responses">;
490+const request = new Request("https://api.openai.com/v1/responses", {
491+method: "POST",
492+headers: { "content-type": "application/json" },
493+body: JSON.stringify({ model: "gpt-5.5", stream: true }),
494+});
495+496+const response = await buildGuardedModelFetch(model)(request);
497+498+expect(cloneSpy).not.toHaveBeenCalled();
499+expect(response.headers.get("content-type")).toBe("application/json");
500+});
501+451502it("preserves JSON bodies when the request is not streaming", async () => {
452503fetchWithSsrFGuardMock.mockResolvedValue({
453504response: new Response('{"ok": true}', {
@@ -531,13 +582,13 @@ describe("buildGuardedModelFetch", () => {
531582});
532583const model = {
533584id: "gpt-5.4",
534-provider: "openai",
585+provider: "openrouter",
535586api: "openai-completions",
536-baseUrl: "https://api.openai.com/v1",
587+baseUrl: "https://openrouter.ai/api/v1",
537588} as unknown as Model<"openai-completions">;
538589539590const response = await buildGuardedModelFetch(model)(
540-"https://api.openai.com/v1/chat/completions",
591+"https://openrouter.ai/api/v1/chat/completions",
541592{ method: "POST" },
542593);
543594const items = [];
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。