


























@@ -791,6 +791,57 @@ describe("openrouter provider hooks", () => {
791791}
792792});
793793794+it("falls back to streamed cost estimate when generation metadata response is oversized", async () => {
795+const provider = await registerSingleProviderPlugin(openrouterPlugin);
796+// Body exceeds the 16 MiB cap; readProviderJsonResponse must reject it and
797+// applyOpenRouterBilledCost must fall back to the streamed estimate.
798+const oversizedBody = new ReadableStream<Uint8Array>({
799+start(controller) {
800+controller.enqueue(new Uint8Array(16 * 1024 * 1024 + 1).fill(0x78));
801+controller.close();
802+},
803+});
804+const fetchMock = vi.fn(async (url: string) => {
805+expect(url).toBe("https://openrouter.ai/api/v1/generation?id=gen-oversized-1");
806+return new Response(oversizedBody, {
807+headers: { "Content-Type": "application/json" },
808+status: 200,
809+});
810+});
811+vi.stubGlobal("fetch", fetchMock);
812+const baseStreamFn = vi.fn(() =>
813+createOpenRouterDoneStream({ responseId: "gen-oversized-1", totalCost: 0.001 }),
814+);
815+816+try {
817+const wrapped = provider.wrapStreamFn?.({
818+provider: "openrouter",
819+modelId: "openrouter/auto",
820+streamFn: baseStreamFn,
821+} as never);
822+if (!wrapped) {
823+throw new Error("expected OpenRouter wrapper");
824+}
825+const stream = await wrapped(
826+{
827+provider: "openrouter",
828+api: "openai-completions",
829+id: "openrouter/auto",
830+baseUrl: "https://openrouter.ai/api/v1",
831+compat: {},
832+} as never,
833+{ messages: [] } as never,
834+{ apiKey: "or-test-key" } as never,
835+);
836+const message = await stream.result();
837+838+expect(fetchMock).toHaveBeenCalledOnce();
839+expect(message.usage.cost.total).toBe(0.001);
840+} finally {
841+vi.unstubAllGlobals();
842+}
843+});
844+794845it("does not fetch generation metadata for custom OpenRouter-compatible routes", async () => {
795846const provider = await registerSingleProviderPlugin(openrouterPlugin);
796847const fetchMock = vi.fn();
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。