Skip to content

Commit dba291e

Browse files
committed
fix(agents): cancel OpenRouter catalog error bodies
1 parent 32c02e8 commit dba291e

2 files changed

Lines changed: 24 additions & 1 deletion

File tree

src/agents/embedded-agent-runner/openrouter-model-capabilities.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,21 @@ describe("openrouter-model-capabilities", () => {
105105
});
106106
});
107107

108+
it("cancels failed OpenRouter catalog response bodies", async () => {
109+
await withOpenRouterStateDir(async () => {
110+
const response = new Response("temporarily unavailable", { status: 503 });
111+
const cancel = vi.spyOn(response.body!, "cancel").mockResolvedValue(undefined);
112+
const fetchSpy = vi.fn(async () => response);
113+
vi.stubGlobal("fetch", fetchSpy);
114+
115+
const module = await importOpenRouterModelCapabilities("failed-catalog-response");
116+
await module.loadOpenRouterModelCapabilities("acme/missing-model");
117+
118+
expect(fetchSpy).toHaveBeenCalledTimes(1);
119+
expect(cancel).toHaveBeenCalledOnce();
120+
});
121+
});
122+
108123
it("uses endpoint-specific OpenRouter context length when top_provider reports one", async () => {
109124
await withOpenRouterStateDir(async () => {
110125
vi.stubGlobal(

src/agents/embedded-agent-runner/openrouter-model-capabilities.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,17 +172,24 @@ function parseModel(model: OpenRouterApiModel): OpenRouterModelCapabilities {
172172
};
173173
}
174174

175+
async function cancelUnreadResponseBody(response: Response | undefined): Promise<void> {
176+
if (response && !response.bodyUsed) {
177+
await response.body?.cancel().catch(() => undefined);
178+
}
179+
}
180+
175181
// ---------------------------------------------------------------------------
176182
// API fetch
177183
// ---------------------------------------------------------------------------
178184

179185
async function doFetch(): Promise<void> {
180186
const controller = new AbortController();
181187
const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
188+
let response: Response | undefined;
182189
try {
183190
const fetchFn = resolveProxyFetchFromEnv() ?? globalThis.fetch;
184191

185-
const response = await fetchFn(OPENROUTER_MODELS_URL, {
192+
response = await fetchFn(OPENROUTER_MODELS_URL, {
186193
signal: controller.signal,
187194
});
188195

@@ -210,6 +217,7 @@ async function doFetch(): Promise<void> {
210217
log.warn(`Failed to fetch OpenRouter models: ${message}`);
211218
} finally {
212219
clearTimeout(timeout);
220+
await cancelUnreadResponseBody(response);
213221
}
214222
}
215223

0 commit comments

Comments
 (0)