fix(agents): cancel OpenRouter catalog error bodies · openclaw/openclaw@dba291e
vincentkoc
·
2026-06-19
·
via Recent Commits to openclaw:main
File tree
src/agents/embedded-agent-runner
| Original file line number | Diff line number | Diff line change |
|---|
@@ -105,6 +105,21 @@ describe("openrouter-model-capabilities", () => {
|
105 | 105 | }); |
106 | 106 | }); |
107 | 107 | |
| 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 | + |
108 | 123 | it("uses endpoint-specific OpenRouter context length when top_provider reports one", async () => { |
109 | 124 | await withOpenRouterStateDir(async () => { |
110 | 125 | vi.stubGlobal( |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -172,17 +172,24 @@ function parseModel(model: OpenRouterApiModel): OpenRouterModelCapabilities {
|
172 | 172 | }; |
173 | 173 | } |
174 | 174 | |
| 175 | +async function cancelUnreadResponseBody(response: Response | undefined): Promise<void> { |
| 176 | +if (response && !response.bodyUsed) { |
| 177 | +await response.body?.cancel().catch(() => undefined); |
| 178 | +} |
| 179 | +} |
| 180 | + |
175 | 181 | // --------------------------------------------------------------------------- |
176 | 182 | // API fetch |
177 | 183 | // --------------------------------------------------------------------------- |
178 | 184 | |
179 | 185 | async function doFetch(): Promise<void> { |
180 | 186 | const controller = new AbortController(); |
181 | 187 | const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS); |
| 188 | +let response: Response | undefined; |
182 | 189 | try { |
183 | 190 | const fetchFn = resolveProxyFetchFromEnv() ?? globalThis.fetch; |
184 | 191 | |
185 | | -const response = await fetchFn(OPENROUTER_MODELS_URL, { |
| 192 | +response = await fetchFn(OPENROUTER_MODELS_URL, { |
186 | 193 | signal: controller.signal, |
187 | 194 | }); |
188 | 195 | |
@@ -210,6 +217,7 @@ async function doFetch(): Promise<void> {
|
210 | 217 | log.warn(`Failed to fetch OpenRouter models: ${message}`); |
211 | 218 | } finally { |
212 | 219 | clearTimeout(timeout); |
| 220 | +await cancelUnreadResponseBody(response); |
213 | 221 | } |
214 | 222 | } |
215 | 223 | |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。