From 9233b3b2a92663b5b63e7a5271133b5d5011188a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Apr 2026 06:51:38 +0000 Subject: [PATCH 1/4] Initial plan From 8fb4c2d10f81d7e8e1cbbec9cea0cd9659bb5a10 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Apr 2026 07:22:34 +0000 Subject: [PATCH 2/4] Fix schema-less numeric coercion in MCP CLI bridge args Agent-Logs-Url: https://github.com/github/gh-aw/sessions/55e39088-50c1-442b-b53b-40bb60d9981c Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/mcp_cli_bridge.cjs | 26 +++++++++++++++++++++--- actions/setup/js/mcp_cli_bridge.test.cjs | 18 ++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/actions/setup/js/mcp_cli_bridge.cjs b/actions/setup/js/mcp_cli_bridge.cjs index bbd5403662a..e5f7d7fad7d 100644 --- a/actions/setup/js/mcp_cli_bridge.cjs +++ b/actions/setup/js/mcp_cli_bridge.cjs @@ -445,6 +445,7 @@ function parseToolArgs(args, schemaProperties = {}) { /** @type {Record} */ const result = {}; let jsonOutput = false; + const hasSchemaProperties = Object.keys(schemaProperties).length > 0; const { normalizedSchemaKeyMap, ambiguousNormalizedSchemaKeys } = buildNormalizedSchemaKeyMap(schemaProperties); for (let i = 0; i < args.length; i++) { @@ -458,13 +459,13 @@ function parseToolArgs(args, schemaProperties = {}) { jsonOutput = true; } else { const canonicalKey = resolveSchemaPropertyKey(key, schemaProperties, normalizedSchemaKeyMap, ambiguousNormalizedSchemaKeys); - result[canonicalKey] = coerceToolArgValue(canonicalKey, raw.slice(eqIdx + 1), schemaProperties[canonicalKey], result[canonicalKey]); + result[canonicalKey] = coerceToolArgValue(canonicalKey, raw.slice(eqIdx + 1), schemaProperties[canonicalKey], result[canonicalKey], !hasSchemaProperties); } } else if (raw === "json") { jsonOutput = true; } else if (i + 1 < args.length && !args[i + 1].startsWith("--")) { const canonicalKey = resolveSchemaPropertyKey(raw, schemaProperties, normalizedSchemaKeyMap, ambiguousNormalizedSchemaKeys); - result[canonicalKey] = coerceToolArgValue(canonicalKey, args[i + 1], schemaProperties[canonicalKey], result[canonicalKey]); + result[canonicalKey] = coerceToolArgValue(canonicalKey, args[i + 1], schemaProperties[canonicalKey], result[canonicalKey], !hasSchemaProperties); i++; } else { const canonicalKey = resolveSchemaPropertyKey(raw, schemaProperties, normalizedSchemaKeyMap, ambiguousNormalizedSchemaKeys); @@ -549,9 +550,10 @@ function resolveSchemaPropertyKey(key, schemaProperties, normalizedSchemaKeyMap, * @param {string} rawValue - Raw CLI value * @param {{type?: string|string[]}|undefined} schemaProperty - JSON schema property * @param {unknown} existingValue - Existing value (for repeated flags) + * @param {boolean} [allowNumericFallback=false] - Allow numeric parsing when schema is unavailable * @returns {unknown} */ -function coerceToolArgValue(key, rawValue, schemaProperty, existingValue) { +function coerceToolArgValue(key, rawValue, schemaProperty, existingValue, allowNumericFallback = false) { /** @type {string[]} */ const types = []; if (schemaProperty && typeof schemaProperty === "object" && "type" in schemaProperty && schemaProperty.type != null) { @@ -620,6 +622,24 @@ function coerceToolArgValue(key, rawValue, schemaProperty, existingValue) { } } + // When schema metadata is unavailable (e.g. empty tools cache), apply + // conservative numeric coercion fallback for CLI ergonomics. + if (allowNumericFallback && types.length === 0) { + if (/^-?\d+$/.test(rawValue)) { + const parsedInt = Number.parseInt(rawValue, 10); + if (Number.isSafeInteger(parsedInt)) { + return parsedInt; + } + } + + if (/^-?(?:\d+\.\d+|\d+\.|\.\d+)(?:[eE][+-]?\d+)?$/.test(rawValue)) { + const parsedFloat = Number.parseFloat(rawValue); + if (!Number.isNaN(parsedFloat) && Number.isFinite(parsedFloat)) { + return parsedFloat; + } + } + } + return rawValue; } diff --git a/actions/setup/js/mcp_cli_bridge.test.cjs b/actions/setup/js/mcp_cli_bridge.test.cjs index c66eb74413f..22dbf050c2a 100644 --- a/actions/setup/js/mcp_cli_bridge.test.cjs +++ b/actions/setup/js/mcp_cli_bridge.test.cjs @@ -145,6 +145,24 @@ describe("mcp_cli_bridge.cjs", () => { }); }); + it("falls back to numeric coercion when schema properties are unavailable", () => { + const { args } = parseToolArgs(["--count", "3", "--max_tokens", "3000"], {}); + + expect(args).toEqual({ + count: 3, + max_tokens: 3000, + }); + }); + + it("preserves non-numeric values when schema properties are unavailable", () => { + const { args } = parseToolArgs(["--start_date", "-1d", "--workflow_name", "daily-issues-report"], {}); + + expect(args).toEqual({ + start_date: "-1d", + workflow_name: "daily-issues-report", + }); + }); + it("treats MCP result envelopes with isError=true as errors", () => { formatResponse( { From 27d48794e700821a21ab28e20e1b30da7580ed43 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Apr 2026 12:25:22 +0000 Subject: [PATCH 3/4] Adjust numeric fallback to parseInt/parseFloat with NaN checks Agent-Logs-Url: https://github.com/github/gh-aw/sessions/0c365ea8-8206-4477-bdf5-17411e8520c7 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/mcp_cli_bridge.cjs | 12 +++++++----- actions/setup/js/mcp_cli_bridge.test.cjs | 9 +++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/actions/setup/js/mcp_cli_bridge.cjs b/actions/setup/js/mcp_cli_bridge.cjs index e5f7d7fad7d..2cf673478df 100644 --- a/actions/setup/js/mcp_cli_bridge.cjs +++ b/actions/setup/js/mcp_cli_bridge.cjs @@ -625,15 +625,17 @@ function coerceToolArgValue(key, rawValue, schemaProperty, existingValue, allowN // When schema metadata is unavailable (e.g. empty tools cache), apply // conservative numeric coercion fallback for CLI ergonomics. if (allowNumericFallback && types.length === 0) { - if (/^-?\d+$/.test(rawValue)) { - const parsedInt = Number.parseInt(rawValue, 10); - if (Number.isSafeInteger(parsedInt)) { + const trimmedValue = rawValue.trim(); + + if (/^-?\d+$/.test(trimmedValue)) { + const parsedInt = Number.parseInt(trimmedValue, 10); + if (!Number.isNaN(parsedInt) && Number.isSafeInteger(parsedInt)) { return parsedInt; } } - if (/^-?(?:\d+\.\d+|\d+\.|\.\d+)(?:[eE][+-]?\d+)?$/.test(rawValue)) { - const parsedFloat = Number.parseFloat(rawValue); + if (/^-?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?$/.test(trimmedValue)) { + const parsedFloat = Number.parseFloat(trimmedValue); if (!Number.isNaN(parsedFloat) && Number.isFinite(parsedFloat)) { return parsedFloat; } diff --git a/actions/setup/js/mcp_cli_bridge.test.cjs b/actions/setup/js/mcp_cli_bridge.test.cjs index 22dbf050c2a..7668945fdcd 100644 --- a/actions/setup/js/mcp_cli_bridge.test.cjs +++ b/actions/setup/js/mcp_cli_bridge.test.cjs @@ -154,6 +154,15 @@ describe("mcp_cli_bridge.cjs", () => { }); }); + it("coerces scientific notation when schema properties are unavailable", () => { + const { args } = parseToolArgs(["--max_tokens", "1e3", "--threshold", "-2E-4"], {}); + + expect(args).toEqual({ + max_tokens: 1000, + threshold: -0.0002, + }); + }); + it("preserves non-numeric values when schema properties are unavailable", () => { const { args } = parseToolArgs(["--start_date", "-1d", "--workflow_name", "daily-issues-report"], {}); From a29c5c2b1005c3d11b2b11d8be5919607cc3808e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Apr 2026 12:28:27 +0000 Subject: [PATCH 4/4] Refine numeric fallback regex to support exponent-only floats Agent-Logs-Url: https://github.com/github/gh-aw/sessions/0c365ea8-8206-4477-bdf5-17411e8520c7 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/mcp_cli_bridge.cjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/setup/js/mcp_cli_bridge.cjs b/actions/setup/js/mcp_cli_bridge.cjs index 2cf673478df..cd782debc20 100644 --- a/actions/setup/js/mcp_cli_bridge.cjs +++ b/actions/setup/js/mcp_cli_bridge.cjs @@ -634,7 +634,7 @@ function coerceToolArgValue(key, rawValue, schemaProperty, existingValue, allowN } } - if (/^-?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?$/.test(trimmedValue)) { + if (/^-?(?:(?:\d+\.\d*|\.\d+)(?:[eE][+-]?\d+)?|\d+[eE][+-]?\d+)$/.test(trimmedValue)) { const parsedFloat = Number.parseFloat(trimmedValue); if (!Number.isNaN(parsedFloat) && Number.isFinite(parsedFloat)) { return parsedFloat;