From ee6d7841b1d29ea7ad024d003021de67c8c26cd5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 23 May 2026 17:37:31 +0000 Subject: [PATCH 1/7] Initial plan From 1776b0b19f1ef08dea7d1d6ab0b86c90bebffce9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 23 May 2026 17:46:26 +0000 Subject: [PATCH 2/7] fix: retry awf-reflect models fetch on startup 503 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/awf_reflect.cjs | 63 +++++++++++++++++---------- actions/setup/js/awf_reflect.test.cjs | 31 +++++++++++++ 2 files changed, 70 insertions(+), 24 deletions(-) diff --git a/actions/setup/js/awf_reflect.cjs b/actions/setup/js/awf_reflect.cjs index c76e456c8dd..59f193d1afa 100644 --- a/actions/setup/js/awf_reflect.cjs +++ b/actions/setup/js/awf_reflect.cjs @@ -29,6 +29,10 @@ const AWF_REFLECT_OUTPUT_PATH = "/tmp/gh-aw/sandbox/firewall/awf-reflect.json"; const AWF_REFLECT_TIMEOUT_MS = 60000; // Milliseconds to wait for each models_url fallback fetch (shorter than the main reflect timeout). const AWF_MODELS_URL_TIMEOUT_MS = 3000; +// Maximum attempts for models_url fallback fetches when the proxy is not yet ready. +const AWF_MODELS_URL_MAX_ATTEMPTS = 5; +// Base delay between models_url fallback retries. Uses exponential backoff. +const AWF_MODELS_URL_RETRY_BASE_MS = 250; // Gemini model name prefix stripped from model IDs in the Gemini models API response. // Example: { name: "models/gemini-1.5-pro" } → "gemini-1.5-pro" const GEMINI_MODEL_NAME_PREFIX = "models/"; @@ -84,33 +88,42 @@ function extractModelIds(json) { * @returns {Promise} */ async function fetchModelsFromUrl(modelsUrl, timeoutMs, logger) { - const ac = new AbortController(); - const timer = setTimeout(() => { - logger(`awf-reflect: models fetch timed out for ${modelsUrl}`); - ac.abort(); - }, timeoutMs); - try { - const res = await fetch(modelsUrl, { signal: ac.signal }); - if (!res.ok) { - logger(`awf-reflect: models fetch returned ${res.status} for ${modelsUrl}`); + for (let attempt = 1; attempt <= AWF_MODELS_URL_MAX_ATTEMPTS; attempt += 1) { + const ac = new AbortController(); + const timer = setTimeout(() => { + logger(`awf-reflect: models fetch timed out for ${modelsUrl}`); + ac.abort(); + }, timeoutMs); + try { + const res = await fetch(modelsUrl, { signal: ac.signal }); + if (!res.ok) { + if (res.status === 503 && attempt < AWF_MODELS_URL_MAX_ATTEMPTS) { + const backoffMs = AWF_MODELS_URL_RETRY_BASE_MS * 2 ** (attempt - 1); + logger(`awf-reflect: models fetch returned 503 for ${modelsUrl}; retrying in ${backoffMs}ms (attempt ${attempt + 1}/${AWF_MODELS_URL_MAX_ATTEMPTS})`); + await new Promise(resolve => setTimeout(resolve, backoffMs)); + continue; + } + logger(`awf-reflect: models fetch returned ${res.status} for ${modelsUrl}`); + return null; + } + const json = await res.json(); + const models = extractModelIds(json); + if (models) { + logger(`awf-reflect: fetched ${models.length} model(s) from ${modelsUrl}`); + } + return models; + } catch (err) { + const e = /** @type {Error} */ err; + if (e.name === "AbortError") { + return null; // already logged above + } + logger(`awf-reflect: models fetch error for ${modelsUrl}: ${e.message}`); return null; + } finally { + clearTimeout(timer); } - const json = await res.json(); - const models = extractModelIds(json); - if (models) { - logger(`awf-reflect: fetched ${models.length} model(s) from ${modelsUrl}`); - } - return models; - } catch (err) { - const e = /** @type {Error} */ err; - if (e.name === "AbortError") { - return null; // already logged above - } - logger(`awf-reflect: models fetch error for ${modelsUrl}: ${e.message}`); - return null; - } finally { - clearTimeout(timer); } + return null; } /** @@ -250,6 +263,8 @@ if (typeof module !== "undefined" && module.exports) { AWF_REFLECT_OUTPUT_PATH, AWF_REFLECT_TIMEOUT_MS, AWF_MODELS_URL_TIMEOUT_MS, + AWF_MODELS_URL_MAX_ATTEMPTS, + AWF_MODELS_URL_RETRY_BASE_MS, GEMINI_MODEL_NAME_PREFIX, enrichReflectModels, extractModelIds, diff --git a/actions/setup/js/awf_reflect.test.cjs b/actions/setup/js/awf_reflect.test.cjs index 72859de1c91..91c2616b30b 100644 --- a/actions/setup/js/awf_reflect.test.cjs +++ b/actions/setup/js/awf_reflect.test.cjs @@ -10,6 +10,8 @@ const { AWF_REFLECT_OUTPUT_PATH, AWF_REFLECT_TIMEOUT_MS, AWF_MODELS_URL_TIMEOUT_MS, + AWF_MODELS_URL_MAX_ATTEMPTS, + AWF_MODELS_URL_RETRY_BASE_MS, GEMINI_MODEL_NAME_PREFIX, enrichReflectModels, extractModelIds, @@ -24,6 +26,8 @@ describe("awf_reflect.cjs", () => { expect(AWF_REFLECT_OUTPUT_PATH).toBe("/tmp/gh-aw/sandbox/firewall/awf-reflect.json"); expect(AWF_REFLECT_TIMEOUT_MS).toBe(60000); expect(AWF_MODELS_URL_TIMEOUT_MS).toBe(3000); + expect(AWF_MODELS_URL_MAX_ATTEMPTS).toBe(5); + expect(AWF_MODELS_URL_RETRY_BASE_MS).toBe(250); expect(GEMINI_MODEL_NAME_PREFIX).toBe("models/"); }); }); @@ -171,6 +175,33 @@ describe("awf_reflect.cjs", () => { expect(result).toBeNull(); expect(logs.some(l => l.includes("models fetch error"))).toBe(true); }); + + it("retries on 503 and eventually succeeds", async () => { + vi.stubGlobal( + "fetch", + vi + .fn() + .mockResolvedValueOnce({ ok: false, status: 503 }) + .mockResolvedValueOnce({ ok: false, status: 503 }) + .mockResolvedValueOnce({ ok: true, status: 200, json: async () => ({ data: [{ id: "gpt-4o" }] }) }) + ); + + const logs = []; + const result = await fetchModelsFromUrl("http://api-proxy:10000/v1/models", 1000, msg => logs.push(msg)); + expect(result).toEqual(["gpt-4o"]); + expect(logs.filter(l => l.includes("retrying in")).length).toBe(2); + expect(logs.some(l => l.includes("fetched 1 model(s)"))).toBe(true); + }); + + it("stops retrying after max attempts on repeated 503 responses", async () => { + vi.stubGlobal("fetch", vi.fn().mockResolvedValue({ ok: false, status: 503 })); + + const logs = []; + const result = await fetchModelsFromUrl("http://api-proxy:10000/v1/models", 1000, msg => logs.push(msg)); + expect(result).toBeNull(); + expect(logs.filter(l => l.includes("retrying in")).length).toBe(AWF_MODELS_URL_MAX_ATTEMPTS - 1); + expect(logs.some(l => l.includes("models fetch returned 503"))).toBe(true); + }); }); describe("fetchAWFReflect", () => { From aee30d8ff766fe4ffb216c717fd7c25abf38b93b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 23 May 2026 17:47:36 +0000 Subject: [PATCH 3/7] test: cover awf-reflect 503 retry backoff behavior Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/awf_reflect.cjs | 5 ++++- actions/setup/js/awf_reflect.test.cjs | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/actions/setup/js/awf_reflect.cjs b/actions/setup/js/awf_reflect.cjs index 59f193d1afa..61535a671b3 100644 --- a/actions/setup/js/awf_reflect.cjs +++ b/actions/setup/js/awf_reflect.cjs @@ -33,6 +33,8 @@ const AWF_MODELS_URL_TIMEOUT_MS = 3000; const AWF_MODELS_URL_MAX_ATTEMPTS = 5; // Base delay between models_url fallback retries. Uses exponential backoff. const AWF_MODELS_URL_RETRY_BASE_MS = 250; +// Cap for exponential backoff delay between retries. +const AWF_MODELS_URL_RETRY_MAX_MS = 2000; // Gemini model name prefix stripped from model IDs in the Gemini models API response. // Example: { name: "models/gemini-1.5-pro" } → "gemini-1.5-pro" const GEMINI_MODEL_NAME_PREFIX = "models/"; @@ -98,7 +100,7 @@ async function fetchModelsFromUrl(modelsUrl, timeoutMs, logger) { const res = await fetch(modelsUrl, { signal: ac.signal }); if (!res.ok) { if (res.status === 503 && attempt < AWF_MODELS_URL_MAX_ATTEMPTS) { - const backoffMs = AWF_MODELS_URL_RETRY_BASE_MS * 2 ** (attempt - 1); + const backoffMs = Math.min(AWF_MODELS_URL_RETRY_BASE_MS * 2 ** (attempt - 1), AWF_MODELS_URL_RETRY_MAX_MS); logger(`awf-reflect: models fetch returned 503 for ${modelsUrl}; retrying in ${backoffMs}ms (attempt ${attempt + 1}/${AWF_MODELS_URL_MAX_ATTEMPTS})`); await new Promise(resolve => setTimeout(resolve, backoffMs)); continue; @@ -265,6 +267,7 @@ if (typeof module !== "undefined" && module.exports) { AWF_MODELS_URL_TIMEOUT_MS, AWF_MODELS_URL_MAX_ATTEMPTS, AWF_MODELS_URL_RETRY_BASE_MS, + AWF_MODELS_URL_RETRY_MAX_MS, GEMINI_MODEL_NAME_PREFIX, enrichReflectModels, extractModelIds, diff --git a/actions/setup/js/awf_reflect.test.cjs b/actions/setup/js/awf_reflect.test.cjs index 91c2616b30b..8ca7ab8c9ef 100644 --- a/actions/setup/js/awf_reflect.test.cjs +++ b/actions/setup/js/awf_reflect.test.cjs @@ -12,6 +12,7 @@ const { AWF_MODELS_URL_TIMEOUT_MS, AWF_MODELS_URL_MAX_ATTEMPTS, AWF_MODELS_URL_RETRY_BASE_MS, + AWF_MODELS_URL_RETRY_MAX_MS, GEMINI_MODEL_NAME_PREFIX, enrichReflectModels, extractModelIds, @@ -28,6 +29,7 @@ describe("awf_reflect.cjs", () => { expect(AWF_MODELS_URL_TIMEOUT_MS).toBe(3000); expect(AWF_MODELS_URL_MAX_ATTEMPTS).toBe(5); expect(AWF_MODELS_URL_RETRY_BASE_MS).toBe(250); + expect(AWF_MODELS_URL_RETRY_MAX_MS).toBe(2000); expect(GEMINI_MODEL_NAME_PREFIX).toBe("models/"); }); }); From bf57424405060d38fa7c5e49b32fd0288b65cbe8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 23 May 2026 19:00:24 +0000 Subject: [PATCH 4/7] refactor: use withRetry in awf_reflect models fetch Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/awf_reflect.cjs | 111 ++++++++++++++++++++++--------- 1 file changed, 79 insertions(+), 32 deletions(-) diff --git a/actions/setup/js/awf_reflect.cjs b/actions/setup/js/awf_reflect.cjs index 61535a671b3..d3c958517ce 100644 --- a/actions/setup/js/awf_reflect.cjs +++ b/actions/setup/js/awf_reflect.cjs @@ -15,8 +15,11 @@ "use strict"; +require("./shim.cjs"); + const fs = require("fs"); const path = require("path"); +const { withRetry } = require("./error_recovery.cjs"); // AWF API proxy management endpoint for discovering configured LLM providers and available models. // The api-proxy sidecar exposes /reflect on its management port (port 10000) inside the AWF @@ -90,42 +93,86 @@ function extractModelIds(json) { * @returns {Promise} */ async function fetchModelsFromUrl(modelsUrl, timeoutMs, logger) { - for (let attempt = 1; attempt <= AWF_MODELS_URL_MAX_ATTEMPTS; attempt += 1) { - const ac = new AbortController(); - const timer = setTimeout(() => { - logger(`awf-reflect: models fetch timed out for ${modelsUrl}`); - ac.abort(); - }, timeoutMs); - try { - const res = await fetch(modelsUrl, { signal: ac.signal }); - if (!res.ok) { - if (res.status === 503 && attempt < AWF_MODELS_URL_MAX_ATTEMPTS) { - const backoffMs = Math.min(AWF_MODELS_URL_RETRY_BASE_MS * 2 ** (attempt - 1), AWF_MODELS_URL_RETRY_MAX_MS); - logger(`awf-reflect: models fetch returned 503 for ${modelsUrl}; retrying in ${backoffMs}ms (attempt ${attempt + 1}/${AWF_MODELS_URL_MAX_ATTEMPTS})`); - await new Promise(resolve => setTimeout(resolve, backoffMs)); - continue; - } - logger(`awf-reflect: models fetch returned ${res.status} for ${modelsUrl}`); - return null; - } - const json = await res.json(); - const models = extractModelIds(json); - if (models) { - logger(`awf-reflect: fetched ${models.length} model(s) from ${modelsUrl}`); - } - return models; - } catch (err) { - const e = /** @type {Error} */ err; - if (e.name === "AbortError") { - return null; // already logged above + let attemptCounter = 0; + const retryConfig = { + maxRetries: AWF_MODELS_URL_MAX_ATTEMPTS - 1, + // withRetry multiplies delay before the next attempt, so divide by 2 here + // to preserve the intended first backoff of AWF_MODELS_URL_RETRY_BASE_MS. + initialDelayMs: Math.max(1, Math.floor(AWF_MODELS_URL_RETRY_BASE_MS / 2)), + maxDelayMs: AWF_MODELS_URL_RETRY_MAX_MS, + backoffMultiplier: 2, + jitterMs: 0, + shouldRetry: error => { + const original = error?.originalError || error; + const status = original?.status ?? original?.response?.status ?? null; + const attempt = original?.attempt ?? 1; + const shouldRetry = status === 503 && attempt < AWF_MODELS_URL_MAX_ATTEMPTS; + if (shouldRetry) { + const backoffMs = Math.min(AWF_MODELS_URL_RETRY_BASE_MS * 2 ** (attempt - 1), AWF_MODELS_URL_RETRY_MAX_MS); + logger(`awf-reflect: models fetch returned 503 for ${modelsUrl}; retrying in ${backoffMs}ms (attempt ${attempt + 1}/${AWF_MODELS_URL_MAX_ATTEMPTS})`); } - logger(`awf-reflect: models fetch error for ${modelsUrl}: ${e.message}`); + return shouldRetry; + }, + }; + + try { + return await withRetry( + async () => { + attemptCounter += 1; + const ac = new AbortController(); + const timer = setTimeout(() => { + logger(`awf-reflect: models fetch timed out for ${modelsUrl}`); + ac.abort(); + }, timeoutMs); + try { + const res = await fetch(modelsUrl, { signal: ac.signal }); + if (!res.ok) { + if (res.status === 503) { + const err = new Error(`models fetch returned 503 for ${modelsUrl}`); + // @ts-ignore attach status for withRetry shouldRetry inspection + err.status = 503; + // @ts-ignore attach attempt for retry logging + err.attempt = attemptCounter; + throw err; + } + logger(`awf-reflect: models fetch returned ${res.status} for ${modelsUrl}`); + return null; + } + const json = await res.json(); + const models = extractModelIds(json); + if (models) { + logger(`awf-reflect: fetched ${models.length} model(s) from ${modelsUrl}`); + } + return models; + } catch (err) { + const e = /** @type {Error} */ err; + if (e.name === "AbortError") { + return null; // already logged above + } + const status = e?.status ?? e?.response?.status ?? null; + if (status === 503) { + throw e; + } + logger(`awf-reflect: models fetch error for ${modelsUrl}: ${e.message}`); + return null; + } finally { + clearTimeout(timer); + } + }, + retryConfig, + `awf-reflect models fetch for ${modelsUrl}` + ); + } catch (err) { + const e = /** @type {Error} */ err; + const original = e?.originalError || e; + const status = original?.status ?? original?.response?.status ?? null; + if (status === 503) { + logger(`awf-reflect: models fetch returned 503 for ${modelsUrl}`); return null; - } finally { - clearTimeout(timer); } + logger(`awf-reflect: models fetch error for ${modelsUrl}: ${e.message}`); + return null; } - return null; } /** From 225cf6dfe64548ff3804cb2c0a10cdd307f4d244 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 23 May 2026 19:01:37 +0000 Subject: [PATCH 5/7] test: align awf_reflect retry log assertions with withRetry Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/awf_reflect.cjs | 3 +-- actions/setup/js/awf_reflect.test.cjs | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/actions/setup/js/awf_reflect.cjs b/actions/setup/js/awf_reflect.cjs index d3c958517ce..a878412c96c 100644 --- a/actions/setup/js/awf_reflect.cjs +++ b/actions/setup/js/awf_reflect.cjs @@ -108,8 +108,7 @@ async function fetchModelsFromUrl(modelsUrl, timeoutMs, logger) { const attempt = original?.attempt ?? 1; const shouldRetry = status === 503 && attempt < AWF_MODELS_URL_MAX_ATTEMPTS; if (shouldRetry) { - const backoffMs = Math.min(AWF_MODELS_URL_RETRY_BASE_MS * 2 ** (attempt - 1), AWF_MODELS_URL_RETRY_MAX_MS); - logger(`awf-reflect: models fetch returned 503 for ${modelsUrl}; retrying in ${backoffMs}ms (attempt ${attempt + 1}/${AWF_MODELS_URL_MAX_ATTEMPTS})`); + logger(`awf-reflect: models fetch returned 503 for ${modelsUrl}; retrying (attempt ${attempt + 1}/${AWF_MODELS_URL_MAX_ATTEMPTS})`); } return shouldRetry; }, diff --git a/actions/setup/js/awf_reflect.test.cjs b/actions/setup/js/awf_reflect.test.cjs index 8ca7ab8c9ef..30b904a2cfb 100644 --- a/actions/setup/js/awf_reflect.test.cjs +++ b/actions/setup/js/awf_reflect.test.cjs @@ -191,7 +191,7 @@ describe("awf_reflect.cjs", () => { const logs = []; const result = await fetchModelsFromUrl("http://api-proxy:10000/v1/models", 1000, msg => logs.push(msg)); expect(result).toEqual(["gpt-4o"]); - expect(logs.filter(l => l.includes("retrying in")).length).toBe(2); + expect(logs.filter(l => l.includes("retrying (attempt")).length).toBe(2); expect(logs.some(l => l.includes("fetched 1 model(s)"))).toBe(true); }); @@ -201,7 +201,7 @@ describe("awf_reflect.cjs", () => { const logs = []; const result = await fetchModelsFromUrl("http://api-proxy:10000/v1/models", 1000, msg => logs.push(msg)); expect(result).toBeNull(); - expect(logs.filter(l => l.includes("retrying in")).length).toBe(AWF_MODELS_URL_MAX_ATTEMPTS - 1); + expect(logs.filter(l => l.includes("retrying (attempt")).length).toBe(AWF_MODELS_URL_MAX_ATTEMPTS - 1); expect(logs.some(l => l.includes("models fetch returned 503"))).toBe(true); }); }); From 3f2ae34b3675bebbc344e938f7dcd83619dd9d70 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 23 May 2026 19:02:22 +0000 Subject: [PATCH 6/7] chore: tighten withRetry integration in awf_reflect Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/awf_reflect.cjs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/actions/setup/js/awf_reflect.cjs b/actions/setup/js/awf_reflect.cjs index a878412c96c..3bf2bdead42 100644 --- a/actions/setup/js/awf_reflect.cjs +++ b/actions/setup/js/awf_reflect.cjs @@ -98,7 +98,7 @@ async function fetchModelsFromUrl(modelsUrl, timeoutMs, logger) { maxRetries: AWF_MODELS_URL_MAX_ATTEMPTS - 1, // withRetry multiplies delay before the next attempt, so divide by 2 here // to preserve the intended first backoff of AWF_MODELS_URL_RETRY_BASE_MS. - initialDelayMs: Math.max(1, Math.floor(AWF_MODELS_URL_RETRY_BASE_MS / 2)), + initialDelayMs: Math.ceil(AWF_MODELS_URL_RETRY_BASE_MS / 2), maxDelayMs: AWF_MODELS_URL_RETRY_MAX_MS, backoffMultiplier: 2, jitterMs: 0, @@ -127,11 +127,7 @@ async function fetchModelsFromUrl(modelsUrl, timeoutMs, logger) { const res = await fetch(modelsUrl, { signal: ac.signal }); if (!res.ok) { if (res.status === 503) { - const err = new Error(`models fetch returned 503 for ${modelsUrl}`); - // @ts-ignore attach status for withRetry shouldRetry inspection - err.status = 503; - // @ts-ignore attach attempt for retry logging - err.attempt = attemptCounter; + const err = Object.assign(new Error(`models fetch returned 503 for ${modelsUrl}`), { status: 503, attempt: attemptCounter }); throw err; } logger(`awf-reflect: models fetch returned ${res.status} for ${modelsUrl}`); From 7a1c8758f68ecdbf43cc61d2cfa3359584082bfb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 23 May 2026 19:03:18 +0000 Subject: [PATCH 7/7] refine: simplify awf_reflect withRetry error metadata Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/awf_reflect.cjs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/actions/setup/js/awf_reflect.cjs b/actions/setup/js/awf_reflect.cjs index 3bf2bdead42..ed0491dc56d 100644 --- a/actions/setup/js/awf_reflect.cjs +++ b/actions/setup/js/awf_reflect.cjs @@ -105,10 +105,9 @@ async function fetchModelsFromUrl(modelsUrl, timeoutMs, logger) { shouldRetry: error => { const original = error?.originalError || error; const status = original?.status ?? original?.response?.status ?? null; - const attempt = original?.attempt ?? 1; - const shouldRetry = status === 503 && attempt < AWF_MODELS_URL_MAX_ATTEMPTS; - if (shouldRetry) { - logger(`awf-reflect: models fetch returned 503 for ${modelsUrl}; retrying (attempt ${attempt + 1}/${AWF_MODELS_URL_MAX_ATTEMPTS})`); + const shouldRetry = status === 503; + if (shouldRetry && attemptCounter < AWF_MODELS_URL_MAX_ATTEMPTS) { + logger(`awf-reflect: models fetch returned 503 for ${modelsUrl}; retrying (attempt ${attemptCounter + 1}/${AWF_MODELS_URL_MAX_ATTEMPTS})`); } return shouldRetry; }, @@ -127,7 +126,7 @@ async function fetchModelsFromUrl(modelsUrl, timeoutMs, logger) { const res = await fetch(modelsUrl, { signal: ac.signal }); if (!res.ok) { if (res.status === 503) { - const err = Object.assign(new Error(`models fetch returned 503 for ${modelsUrl}`), { status: 503, attempt: attemptCounter }); + const err = Object.assign(new Error(`models fetch returned 503 for ${modelsUrl}`), { status: 503 }); throw err; } logger(`awf-reflect: models fetch returned ${res.status} for ${modelsUrl}`);