mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 21:07:01 -06:00
fix(openrouter): bound generation-cost JSON response reads (#97490)
(cherry picked from commit c0883a531d)
This commit is contained in:
@@ -791,6 +791,57 @@ describe("openrouter provider hooks", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("falls back to streamed cost estimate when generation metadata response is oversized", async () => {
|
||||
const provider = await registerSingleProviderPlugin(openrouterPlugin);
|
||||
// Body exceeds the 16 MiB cap; readProviderJsonResponse must reject it and
|
||||
// applyOpenRouterBilledCost must fall back to the streamed estimate.
|
||||
const oversizedBody = new ReadableStream<Uint8Array>({
|
||||
start(controller) {
|
||||
controller.enqueue(new Uint8Array(16 * 1024 * 1024 + 1).fill(0x78));
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
const fetchMock = vi.fn(async (url: string) => {
|
||||
expect(url).toBe("https://openrouter.ai/api/v1/generation?id=gen-oversized-1");
|
||||
return new Response(oversizedBody, {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
status: 200,
|
||||
});
|
||||
});
|
||||
vi.stubGlobal("fetch", fetchMock);
|
||||
const baseStreamFn = vi.fn(() =>
|
||||
createOpenRouterDoneStream({ responseId: "gen-oversized-1", totalCost: 0.001 }),
|
||||
);
|
||||
|
||||
try {
|
||||
const wrapped = provider.wrapStreamFn?.({
|
||||
provider: "openrouter",
|
||||
modelId: "openrouter/auto",
|
||||
streamFn: baseStreamFn,
|
||||
} as never);
|
||||
if (!wrapped) {
|
||||
throw new Error("expected OpenRouter wrapper");
|
||||
}
|
||||
const stream = await wrapped(
|
||||
{
|
||||
provider: "openrouter",
|
||||
api: "openai-completions",
|
||||
id: "openrouter/auto",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
compat: {},
|
||||
} as never,
|
||||
{ messages: [] } as never,
|
||||
{ apiKey: "or-test-key" } as never,
|
||||
);
|
||||
const message = await stream.result();
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledOnce();
|
||||
expect(message.usage.cost.total).toBe(0.001);
|
||||
} finally {
|
||||
vi.unstubAllGlobals();
|
||||
}
|
||||
});
|
||||
|
||||
it("does not fetch generation metadata for custom OpenRouter-compatible routes", async () => {
|
||||
const provider = await registerSingleProviderPlugin(openrouterPlugin);
|
||||
const fetchMock = vi.fn();
|
||||
|
||||
@@ -9,6 +9,7 @@ import type { ProviderWrapStreamFnContext } from "openclaw/plugin-sdk/plugin-ent
|
||||
import {
|
||||
assertOkOrThrowHttpError,
|
||||
fetchWithTimeoutGuarded,
|
||||
readProviderJsonResponse,
|
||||
} from "openclaw/plugin-sdk/provider-http";
|
||||
import { OPENROUTER_THINKING_STREAM_HOOKS } from "openclaw/plugin-sdk/provider-stream-family";
|
||||
import {
|
||||
@@ -124,7 +125,12 @@ async function fetchOpenRouterGenerationTotalCost(params: {
|
||||
);
|
||||
try {
|
||||
await assertOkOrThrowHttpError(response, "OpenRouter generation metadata request failed");
|
||||
return readOpenRouterTotalCost((await response.json()) as OpenRouterGenerationResponse);
|
||||
return readOpenRouterTotalCost(
|
||||
await readProviderJsonResponse<OpenRouterGenerationResponse>(
|
||||
response,
|
||||
"openrouter.generation-cost",
|
||||
),
|
||||
);
|
||||
} finally {
|
||||
await release();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user