From 5ea7f480d4a3c343a5853c7109e6beb71aa92852 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Jun 2026 23:06:07 +0000 Subject: [PATCH 1/3] Initial plan From ffe011f01e57ca5d0bf5da822674dd037780f007 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Jun 2026 23:15:01 +0000 Subject: [PATCH 2/3] Deduplicate guard parsing helpers into guard-utils --- .../api-proxy/guards/effective-token-guard.js | 25 +---------- containers/api-proxy/guards/guard-utils.js | 25 +++++++++++ .../api-proxy/guards/guard-utils.test.js | 43 ++++++++++++++++++- .../guards/max-model-multiplier-guard.js | 24 +---------- 4 files changed, 69 insertions(+), 48 deletions(-) diff --git a/containers/api-proxy/guards/effective-token-guard.js b/containers/api-proxy/guards/effective-token-guard.js index 0a5d90c1a..5e94b99cc 100644 --- a/containers/api-proxy/guards/effective-token-guard.js +++ b/containers/api-proxy/guards/effective-token-guard.js @@ -1,6 +1,6 @@ 'use strict'; -const { parsePositiveInteger } = require('./guard-utils'); +const { parsePositiveInteger, parseModelMultipliers, parsePositiveNumber } = require('./guard-utils'); const { logRequest, sanitizeForLog } = require('../logging'); const ET_WARNING_THRESHOLDS = [80, 90, 95, 99]; @@ -38,29 +38,6 @@ const effectiveTokenConfigCache = { parsed: { max: null, multipliers: {}, defaultMultiplier: 1 }, }; -function parseModelMultipliers(raw) { - if (!raw || String(raw).trim() === '') return {}; - try { - const parsed = JSON.parse(raw); - if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return {}; - const result = {}; - for (const [model, value] of Object.entries(parsed)) { - const num = Number(value); - if (Number.isFinite(num) && num > 0) { - result[model] = num; - } - } - return result; - } catch { - return {}; - } -} - -function parsePositiveNumber(raw) { - const value = Number(raw); - return Number.isFinite(value) && value > 0 ? value : null; -} - function getEffectiveTokenConfig() { const rawMax = process.env.AWF_MAX_EFFECTIVE_TOKENS; const rawMultipliers = process.env.AWF_EFFECTIVE_TOKEN_MODEL_MULTIPLIERS; diff --git a/containers/api-proxy/guards/guard-utils.js b/containers/api-proxy/guards/guard-utils.js index 84b0a9c72..c410bee62 100644 --- a/containers/api-proxy/guards/guard-utils.js +++ b/containers/api-proxy/guards/guard-utils.js @@ -7,6 +7,31 @@ function parsePositiveInteger(raw) { return parsed; } +function parseModelMultipliers(raw) { + if (!raw || String(raw).trim() === '') return {}; + try { + const parsed = JSON.parse(raw); + if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return {}; + const result = {}; + for (const [model, value] of Object.entries(parsed)) { + const num = Number(value); + if (Number.isFinite(num) && num > 0) { + result[model] = num; + } + } + return result; + } catch { + return {}; + } +} + +function parsePositiveNumber(raw) { + const value = Number(raw); + return Number.isFinite(value) && value > 0 ? value : null; +} + module.exports = { parsePositiveInteger, + parseModelMultipliers, + parsePositiveNumber, }; diff --git a/containers/api-proxy/guards/guard-utils.test.js b/containers/api-proxy/guards/guard-utils.test.js index 9edcfe7f7..d01c02e4e 100644 --- a/containers/api-proxy/guards/guard-utils.test.js +++ b/containers/api-proxy/guards/guard-utils.test.js @@ -1,4 +1,4 @@ -const { parsePositiveInteger } = require('./guard-utils'); +const { parsePositiveInteger, parseModelMultipliers, parsePositiveNumber } = require('./guard-utils'); describe('guard-utils', () => { describe('parsePositiveInteger', () => { @@ -25,4 +25,45 @@ describe('guard-utils', () => { expect(parsePositiveInteger(raw)).toBe(expected); }); }); + + describe('parseModelMultipliers', () => { + it.each([undefined, null, '', ' ', 'invalid-json', '[]', '42'])( + 'returns empty object for %p', + (raw) => { + expect(parseModelMultipliers(raw)).toEqual({}); + } + ); + + it('parses only finite positive multipliers', () => { + expect( + parseModelMultipliers( + JSON.stringify({ + valid: 2, + stringValid: '3.5', + zero: 0, + negative: -1, + notANumber: 'abc', + infinity: Infinity, + }) + ) + ).toEqual({ + valid: 2, + stringValid: 3.5, + }); + }); + }); + + describe('parsePositiveNumber', () => { + it.each([undefined, null, '', 'abc', 0, -1, Infinity])('returns null for %p', (raw) => { + expect(parsePositiveNumber(raw)).toBeNull(); + }); + + it.each([ + [1, 1], + ['2.5', 2.5], + [' 3 ', 3], + ])('for raw value %p returns %p', (raw, expected) => { + expect(parsePositiveNumber(raw)).toBe(expected); + }); + }); }); diff --git a/containers/api-proxy/guards/max-model-multiplier-guard.js b/containers/api-proxy/guards/max-model-multiplier-guard.js index 1588b0353..a4d5ea82a 100644 --- a/containers/api-proxy/guards/max-model-multiplier-guard.js +++ b/containers/api-proxy/guards/max-model-multiplier-guard.js @@ -1,6 +1,7 @@ 'use strict'; const { sanitizeForLog } = require('../logging'); +const { parseModelMultipliers, parsePositiveNumber } = require('./guard-utils'); const maxModelMultiplierConfigCache = { rawCap: undefined, @@ -9,29 +10,6 @@ const maxModelMultiplierConfigCache = { parsed: { cap: null, multipliers: {}, defaultMultiplier: 1 }, }; -function parseModelMultipliers(raw) { - if (!raw || String(raw).trim() === '') return {}; - try { - const parsed = JSON.parse(raw); - if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return {}; - const result = {}; - for (const [model, value] of Object.entries(parsed)) { - const num = Number(value); - if (Number.isFinite(num) && num > 0) { - result[model] = num; - } - } - return result; - } catch { - return {}; - } -} - -function parsePositiveNumber(raw) { - const value = Number(raw); - return Number.isFinite(value) && value > 0 ? value : null; -} - function getMaxModelMultiplierConfig() { const rawCap = process.env.AWF_MAX_MODEL_MULTIPLIER; const rawMultipliers = process.env.AWF_EFFECTIVE_TOKEN_MODEL_MULTIPLIERS; From a17e096637bd9a574fb89bc5561d5760d7855805 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 4 Jun 2026 00:36:11 +0000 Subject: [PATCH 3/3] test(integration): retry github curl in blocked-domain case --- tests/integration/blocked-domains.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/blocked-domains.test.ts b/tests/integration/blocked-domains.test.ts index 6ebde1f54..bc4de891a 100644 --- a/tests/integration/blocked-domains.test.ts +++ b/tests/integration/blocked-domains.test.ts @@ -214,7 +214,7 @@ describe('Block Domains Deny-List (--block-domains)', () => { test('should still allow non-blocked subdomains when parent is allowed', async () => { const result = await runner.runWithSudo( - 'curl -f --max-time 10 https://github.com', + 'curl -f --retry 3 --retry-all-errors --retry-delay 1 --max-time 10 https://github.com', { allowDomains: ['github.com'], blockDomains: ['api.github.com'],