From 87654339e36294360451de03b92ec1ccdac578e7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 17 May 2026 16:11:02 +0000 Subject: [PATCH 1/6] Initial plan From fbf4c664046a2ace598200dfb08f77203bd045b5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 17 May 2026 16:19:40 +0000 Subject: [PATCH 2/6] fix: restore large-content offloading for create_issue safe output handler Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/safe_outputs_handlers.cjs | 60 ++++++++++++---------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/actions/setup/js/safe_outputs_handlers.cjs b/actions/setup/js/safe_outputs_handlers.cjs index b50dba29e3e..764f73183e6 100644 --- a/actions/setup/js/safe_outputs_handlers.cjs +++ b/actions/setup/js/safe_outputs_handlers.cjs @@ -31,19 +31,16 @@ const { parseDeduplicateByTitle, normalizeTitleForDedup, findDuplicateByTitle } * @returns {Object} An object containing all handler functions */ function createHandlers(server, appendSafeOutput, config = {}) { + const TOKEN_THRESHOLD = 16000; + /** - * Default handler for safe output tools - * Spec cross-reference: Safe Output Outcome Evaluation §2/§4/§5/§6/§7/§8/§9/§10/§11/§12/§13/§14/§15/§16/§18/§19/§20/§21/§22/§23/§24/§25/§26/§27/§28/§29. - * @param {string} type - The tool type - * @returns {Function} Handler function + * Detect and offload large string fields to files. + * @param {Record} entry + * @returns {Object | null} MCP response if large content was handled, else null */ - const defaultHandler = type => args => { - const entry = { ...(args || {}), type }; - - // Check if any field in the entry has content exceeding 16000 tokens + const maybeHandleLargeContent = entry => { let largeContent = null; let largeFieldName = null; - const TOKEN_THRESHOLD = 16000; for (const [key, value] of Object.entries(entry)) { if (typeof value === "string") { @@ -57,26 +54,34 @@ function createHandlers(server, appendSafeOutput, config = {}) { } } - if (largeContent && largeFieldName) { - // Write large content to file - const fileInfo = writeLargeContentToFile(largeContent); + if (!largeContent || !largeFieldName) { + return null; + } - // Replace large field with file reference - entry[largeFieldName] = `[Content too large, saved to file: ${fileInfo.filename}]`; + const fileInfo = writeLargeContentToFile(largeContent); + entry[largeFieldName] = `[Content too large, saved to file: ${fileInfo.filename}]`; + appendSafeOutput(entry); - // Append modified entry to safe outputs - appendSafeOutput(entry); + return { + content: [ + { + type: "text", + text: JSON.stringify(fileInfo), + }, + ], + }; + }; - // Return file info to the agent - return { - content: [ - { - type: "text", - text: JSON.stringify(fileInfo), - }, - ], - }; - } + /** + * Default handler for safe output tools + * Spec cross-reference: Safe Output Outcome Evaluation §2/§4/§5/§6/§7/§8/§9/§10/§11/§12/§13/§14/§15/§16/§18/§19/§20/§21/§22/§23/§24/§25/§26/§27/§28/§29. + * @param {string} type - The tool type + * @returns {Function} Handler function + */ + const defaultHandler = type => args => { + const entry = { ...(args || {}), type }; + const largeContentResponse = maybeHandleLargeContent(entry); + if (largeContentResponse) return largeContentResponse; // Normal case - no large content appendSafeOutput(entry); @@ -1025,6 +1030,9 @@ function createHandlers(server, appendSafeOutput, config = {}) { seenIssueTitlesByRepo.set(resolvedRepo, seenTitles); } + const largeContentResponse = maybeHandleLargeContent(entry); + if (largeContentResponse) return largeContentResponse; + appendSafeOutput(entry); return { content: [ From c062e61338660aeb6efc271cd46c8357863f5dc6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 17 May 2026 16:33:33 +0000 Subject: [PATCH 3/6] fix: offload large content for duplicate create_issue entries Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/safe_outputs_handlers.cjs | 5 ++++- actions/setup/js/safe_outputs_handlers.test.cjs | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/actions/setup/js/safe_outputs_handlers.cjs b/actions/setup/js/safe_outputs_handlers.cjs index 764f73183e6..e2c7b9cd15f 100644 --- a/actions/setup/js/safe_outputs_handlers.cjs +++ b/actions/setup/js/safe_outputs_handlers.cjs @@ -1013,7 +1013,10 @@ function createHandlers(server, appendSafeOutput, config = {}) { _duplicate_title: duplicate.title, _duplicate_distance: duplicate.distance, }; - appendSafeOutput(droppedEntry); + const largeContentResponse = maybeHandleLargeContent(droppedEntry); + if (!largeContentResponse) { + appendSafeOutput(droppedEntry); + } return { content: [ { diff --git a/actions/setup/js/safe_outputs_handlers.test.cjs b/actions/setup/js/safe_outputs_handlers.test.cjs index c9fafb3a175..dc50f96d66d 100644 --- a/actions/setup/js/safe_outputs_handlers.test.cjs +++ b/actions/setup/js/safe_outputs_handlers.test.cjs @@ -1295,6 +1295,21 @@ describe("safe_outputs_handlers", () => { expect(secondResponse.result).toBe("duplicate_dropped"); }); + it("should offload large duplicate create_issue body before appending dropped entry", () => { + const h = createHandlers(mockServer, mockAppendSafeOutput, { + create_issue: { + deduplicate_by_title: true, + }, + }); + + h.createIssueHandler({ title: "Duplicate Issue", body: "First body" }); + h.createIssueHandler({ title: "Duplicate Issue", body: "A".repeat(70000) }); + + const droppedEntry = mockAppendSafeOutput.mock.calls[1][0]; + expect(droppedEntry._dropped_duplicate_by_title).toBe(true); + expect(droppedEntry.body).toContain("[Content too large, saved to file:"); + }); + it("should reject invalid deduplicate-by-title configuration", () => { expect(() => createHandlers(mockServer, mockAppendSafeOutput, { From d891ed3dc4c975b1bc0cee21e81e13763b4ef24a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 17 May 2026 16:34:14 +0000 Subject: [PATCH 4/6] test: assert duplicate large-content entry is appended Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/safe_outputs_handlers.test.cjs | 1 + 1 file changed, 1 insertion(+) diff --git a/actions/setup/js/safe_outputs_handlers.test.cjs b/actions/setup/js/safe_outputs_handlers.test.cjs index dc50f96d66d..783e76dc47c 100644 --- a/actions/setup/js/safe_outputs_handlers.test.cjs +++ b/actions/setup/js/safe_outputs_handlers.test.cjs @@ -1305,6 +1305,7 @@ describe("safe_outputs_handlers", () => { h.createIssueHandler({ title: "Duplicate Issue", body: "First body" }); h.createIssueHandler({ title: "Duplicate Issue", body: "A".repeat(70000) }); + expect(mockAppendSafeOutput.mock.calls).toHaveLength(2); const droppedEntry = mockAppendSafeOutput.mock.calls[1][0]; expect(droppedEntry._dropped_duplicate_by_title).toBe(true); expect(droppedEntry.body).toContain("[Content too large, saved to file:"); From bb515ab8a487ff0c68f4fc8f3536b649fdbc539c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 17 May 2026 16:34:48 +0000 Subject: [PATCH 5/6] test: clarify large duplicate create_issue coverage Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/safe_outputs_handlers.test.cjs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/actions/setup/js/safe_outputs_handlers.test.cjs b/actions/setup/js/safe_outputs_handlers.test.cjs index 783e76dc47c..00efebff002 100644 --- a/actions/setup/js/safe_outputs_handlers.test.cjs +++ b/actions/setup/js/safe_outputs_handlers.test.cjs @@ -1,6 +1,8 @@ import { describe, it, expect, beforeEach, afterEach, vi } from "vitest"; import fs from "fs"; import path from "path"; + +const LARGE_CONTENT_BODY = "A".repeat(70000); import { execSync } from "child_process"; import { createHandlers } from "./safe_outputs_handlers.cjs"; @@ -1295,7 +1297,7 @@ describe("safe_outputs_handlers", () => { expect(secondResponse.result).toBe("duplicate_dropped"); }); - it("should offload large duplicate create_issue body before appending dropped entry", () => { + it("should offload large body when appending duplicate create_issue entry", () => { const h = createHandlers(mockServer, mockAppendSafeOutput, { create_issue: { deduplicate_by_title: true, @@ -1303,7 +1305,7 @@ describe("safe_outputs_handlers", () => { }); h.createIssueHandler({ title: "Duplicate Issue", body: "First body" }); - h.createIssueHandler({ title: "Duplicate Issue", body: "A".repeat(70000) }); + h.createIssueHandler({ title: "Duplicate Issue", body: LARGE_CONTENT_BODY }); expect(mockAppendSafeOutput.mock.calls).toHaveLength(2); const droppedEntry = mockAppendSafeOutput.mock.calls[1][0]; From 9e558f958f21002bebce73419367bb065fb3c627 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 17 May 2026 16:35:22 +0000 Subject: [PATCH 6/6] test: keep imports before constants in handlers tests Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/safe_outputs_handlers.test.cjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actions/setup/js/safe_outputs_handlers.test.cjs b/actions/setup/js/safe_outputs_handlers.test.cjs index 00efebff002..5d26205379d 100644 --- a/actions/setup/js/safe_outputs_handlers.test.cjs +++ b/actions/setup/js/safe_outputs_handlers.test.cjs @@ -1,11 +1,11 @@ import { describe, it, expect, beforeEach, afterEach, vi } from "vitest"; import fs from "fs"; import path from "path"; - -const LARGE_CONTENT_BODY = "A".repeat(70000); import { execSync } from "child_process"; import { createHandlers } from "./safe_outputs_handlers.cjs"; +const LARGE_CONTENT_BODY = "A".repeat(70000); + // Mock the global objects that GitHub Actions provides const mockCore = { debug: vi.fn(),