diff --git a/actions/setup/js/log_parser_bootstrap.cjs b/actions/setup/js/log_parser_bootstrap.cjs
index 172125c4f83..782da3d536a 100644
--- a/actions/setup/js/log_parser_bootstrap.cjs
+++ b/actions/setup/js/log_parser_bootstrap.cjs
@@ -1,7 +1,7 @@
// @ts-check
///
-const { generatePlainTextSummary, generateCopilotCliStyleSummary, formatSafeOutputsPreview } = require("./log_parser_shared.cjs");
+const { generatePlainTextSummary, generateCopilotCliStyleSummary, wrapAgentLogInSection, formatSafeOutputsPreview } = require("./log_parser_shared.cjs");
const { getErrorMessage } = require("./error_helpers.cjs");
/**
@@ -157,8 +157,14 @@ async function runLogParser(options) {
parserName,
});
+ // Wrap the agent log in a details/summary section (open by default)
+ const wrappedAgentLog = wrapAgentLogInSection(copilotCliStyleMarkdown, {
+ parserName,
+ open: true,
+ });
+
// Add safe outputs preview to step summary
- let fullMarkdown = copilotCliStyleMarkdown;
+ let fullMarkdown = wrappedAgentLog;
if (safeOutputsContent) {
const safeOutputsMarkdown = formatSafeOutputsPreview(safeOutputsContent, { isPlainText: false });
if (safeOutputsMarkdown) {
@@ -179,8 +185,14 @@ async function runLogParser(options) {
}
}
- // Write original markdown to step summary if available
- let fullMarkdown = markdown;
+ // Wrap the original markdown in a details/summary section (open by default)
+ const wrappedAgentLog = wrapAgentLogInSection(markdown, {
+ parserName,
+ open: true,
+ });
+
+ // Write wrapped markdown to step summary if available
+ let fullMarkdown = wrappedAgentLog;
if (safeOutputsContent) {
const safeOutputsMarkdown = formatSafeOutputsPreview(safeOutputsContent, { isPlainText: false });
if (safeOutputsMarkdown) {
diff --git a/actions/setup/js/log_parser_bootstrap.test.cjs b/actions/setup/js/log_parser_bootstrap.test.cjs
index 9007de6e788..57c08a8ba29 100644
--- a/actions/setup/js/log_parser_bootstrap.test.cjs
+++ b/actions/setup/js/log_parser_bootstrap.test.cjs
@@ -45,7 +45,7 @@ describe("log_parser_bootstrap.cjs", () => {
(runLogParser({ parseLog: mockParseLog, parserName: "TestParser" }),
expect(mockParseLog).toHaveBeenCalledWith("Test log content"),
expect(mockCore.info).toHaveBeenCalledWith("TestParser log parsed successfully"),
- expect(mockCore.summary.addRaw).toHaveBeenCalledWith("## Parsed Log\n\nSuccess!"),
+ expect(mockCore.summary.addRaw).toHaveBeenCalledWith("\n🤖 TestParser CLI Session
\n\n## Parsed Log\n\nSuccess!\n "),
expect(mockCore.summary.write).toHaveBeenCalled(),
fs.unlinkSync(logFile),
fs.rmdirSync(tmpDir));
@@ -57,7 +57,7 @@ describe("log_parser_bootstrap.cjs", () => {
const mockParseLog = vi.fn().mockReturnValue({ markdown: "## Result\n", mcpFailures: [], maxTurnsHit: !1 });
(runLogParser({ parseLog: mockParseLog, parserName: "TestParser" }),
expect(mockCore.info).toHaveBeenCalledWith("TestParser log parsed successfully"),
- expect(mockCore.summary.addRaw).toHaveBeenCalledWith("## Result\n"),
+ expect(mockCore.summary.addRaw).toHaveBeenCalledWith("\n🤖 TestParser CLI Session
\n\n## Result\n\n "),
expect(mockCore.setFailed).not.toHaveBeenCalled(),
fs.unlinkSync(logFile),
fs.rmdirSync(tmpDir));
diff --git a/actions/setup/js/log_parser_shared.cjs b/actions/setup/js/log_parser_shared.cjs
index 7fa71f9c96f..f6c918bff69 100644
--- a/actions/setup/js/log_parser_shared.cjs
+++ b/actions/setup/js/log_parser_shared.cjs
@@ -1414,6 +1414,28 @@ function generateCopilotCliStyleSummary(logEntries, options = {}) {
return lines.join("\n");
}
+/**
+ * Wraps agent log markdown in a details/summary section
+ * @param {string} markdown - The agent log markdown content
+ * @param {Object} options - Configuration options
+ * @param {string} [options.parserName="Agent"] - Name of the parser (e.g., "Copilot", "Claude")
+ * @param {boolean} [options.open=true] - Whether the section should be open by default
+ * @returns {string} Wrapped markdown in details/summary tags
+ */
+function wrapAgentLogInSection(markdown, options = {}) {
+ const { parserName = "Agent", open = true } = options;
+
+ if (!markdown || markdown.trim().length === 0) {
+ return "";
+ }
+
+ const openAttr = open ? " open" : "";
+ const emoji = "🤖";
+ const title = `${emoji} ${parserName} CLI Session`;
+
+ return `\n${title}
\n\n${markdown}\n `;
+}
+
/**
* Formats safe outputs preview for display in logs
* @param {string} safeOutputsContent - The raw JSONL content from safe outputs file
@@ -1591,6 +1613,7 @@ module.exports = {
formatToolCallAsDetails,
generatePlainTextSummary,
generateCopilotCliStyleSummary,
+ wrapAgentLogInSection,
formatSafeOutputsPreview,
wrapLogParser,
createEngineLogParser,
diff --git a/actions/setup/js/log_parser_shared.test.cjs b/actions/setup/js/log_parser_shared.test.cjs
index f1a8b8e5d9a..6b157c27b47 100644
--- a/actions/setup/js/log_parser_shared.test.cjs
+++ b/actions/setup/js/log_parser_shared.test.cjs
@@ -2087,6 +2087,66 @@ describe("log_parser_shared.cjs", () => {
});
});
+ describe("wrapAgentLogInSection", () => {
+ it("should wrap markdown in details/summary with default open attribute", async () => {
+ const { wrapAgentLogInSection } = await import("./log_parser_shared.cjs");
+
+ const markdown = "```\nConversation:\n\nAgent: Hello\n```";
+ const result = wrapAgentLogInSection(markdown, { parserName: "Copilot" });
+
+ expect(result).toContain("");
+ expect(result).toContain("🤖 Copilot CLI Session
");
+ expect(result).toContain(markdown);
+ expect(result).toContain(" ");
+ });
+
+ it("should support custom parser names", async () => {
+ const { wrapAgentLogInSection } = await import("./log_parser_shared.cjs");
+
+ const markdown = "Test content";
+ const result = wrapAgentLogInSection(markdown, { parserName: "Claude" });
+
+ expect(result).toContain("🤖 Claude CLI Session");
+ });
+
+ it("should allow closed state when open is false", async () => {
+ const { wrapAgentLogInSection } = await import("./log_parser_shared.cjs");
+
+ const markdown = "Test content";
+ const result = wrapAgentLogInSection(markdown, { parserName: "Copilot", open: false });
+
+ expect(result).toContain("");
+ expect(result).not.toContain("");
+ });
+
+ it("should default to Agent parser name when not provided", async () => {
+ const { wrapAgentLogInSection } = await import("./log_parser_shared.cjs");
+
+ const markdown = "Test content";
+ const result = wrapAgentLogInSection(markdown);
+
+ expect(result).toContain("🤖 Agent CLI Session");
+ });
+
+ it("should return empty string for empty or undefined markdown", async () => {
+ const { wrapAgentLogInSection } = await import("./log_parser_shared.cjs");
+
+ expect(wrapAgentLogInSection("")).toBe("");
+ expect(wrapAgentLogInSection(" ")).toBe("");
+ });
+
+ it("should properly escape markdown content", async () => {
+ const { wrapAgentLogInSection } = await import("./log_parser_shared.cjs");
+
+ const markdown = "Content with and `code`";
+ const result = wrapAgentLogInSection(markdown, { parserName: "Copilot" });
+
+ expect(result).toContain(markdown);
+ expect(result).toContain("");
+ expect(result).toContain(" ");
+ });
+ });
+
describe("wrapLogParser", () => {
it("should call parser function and return result on success", async () => {
const { wrapLogParser } = await import("./log_parser_shared.cjs");