Skip to content

Commit f40da83

Browse files
Copilotpelikhan
andauthored
refactor: extract AWF_INFRA_LINE_RE to log_parser_shared and make status page guidance engine-specific
- Extract INFRA_LINE_RE as AWF_INFRA_LINE_RE into log_parser_shared.cjs so parse_copilot_log.cjs and handle_agent_failure.cjs share the same constant (no more duplication risk when infra log format changes) - Make startup-failure status page guidance engine-specific: copilot gets "GitHub Copilot status page", all other engines get "provider status page" - Add test verifying provider-agnostic guidance for claude engine - Update existing engine ID startup-failure test to also verify Copilot status page text Agent-Logs-Url: https://github.com/github/gh-aw/sessions/de02b350-d94e-4ee6-aceb-0e1f8d2b9ae8 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
1 parent 3bbfb9b commit f40da83

File tree

4 files changed

+54
-11
lines changed

4 files changed

+54
-11
lines changed

actions/setup/js/handle_agent_failure.cjs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const { createExpirationLine, generateFooterWithExpiration } = require("./epheme
1010
const { MAX_SUB_ISSUES, getSubIssueCount } = require("./sub_issue_helpers.cjs");
1111
const { formatMissingData } = require("./missing_info_formatter.cjs");
1212
const { generateHistoryUrl } = require("./generate_history_link.cjs");
13+
const { AWF_INFRA_LINE_RE } = require("./log_parser_shared.cjs");
1314
const fs = require("fs");
1415
const path = require("path");
1516

@@ -840,11 +841,9 @@ function buildEngineFailureContext() {
840841
// the engine itself. They must be filtered out of the fallback tail so the failure
841842
// context surfaces actual agent output rather than container lifecycle noise
842843
// (e.g. "Container awf-squid Removed", "[WARN] Command completed with exit code: 1",
843-
// "Process exiting with code: 1"). Uses the same pattern as parse_copilot_log.cjs.
844-
// Note: INFO/WARN/SUCCESS/ERROR are uppercase (AWF wrapper convention); entrypoint and
845-
// health-check are lowercase (container script convention) — mixed casing is intentional
846-
// and reflects the actual log output format produced by different AWF components.
847-
const INFRA_LINE_RE = /^\[(INFO|WARN|SUCCESS|ERROR|entrypoint|health-check)\]|^ (?:Container|Network|Volume) |^Process exiting with code:/;
844+
// "Process exiting with code: 1"). Shared constant from log_parser_shared.cjs keeps the
845+
// pattern in sync with parse_copilot_log.cjs.
846+
const INFRA_LINE_RE = AWF_INFRA_LINE_RE;
848847

849848
// Fallback: no known error patterns found — include the last non-empty lines so that
850849
// failures caused by timeouts or unexpected terminations still surface useful context.
@@ -860,12 +859,14 @@ function buildEngineFailureContext() {
860859
if (agentLines.length === 0) {
861860
// The log contains only AWF infrastructure lines — the engine exited before producing
862861
// any substantive output. This pattern is characteristic of a transient startup failure
863-
// (e.g., Copilot API service unavailable, rate-limiting, token not yet provisioned).
862+
// (e.g., API service unavailable, rate-limiting, token not yet provisioned).
864863
core.info("agent-stdio.log contains only infrastructure lines — engine likely failed at startup (possible transient failure)");
864+
const recurringFailureGuidance =
865+
process.env.GH_AW_ENGINE_ID === "copilot"
866+
? "If this failure recurs, check the GitHub Copilot status page and review the firewall audit logs.\n\n"
867+
: "If this failure recurs, check the provider status page (if available) and review the firewall audit logs.\n\n";
865868
let context = `\n**⚠️ Engine Failure**: The${engineLabel} engine terminated before producing output.\n\n`;
866-
context +=
867-
"The engine exited immediately without producing any output. This often indicates a transient infrastructure issue (e.g., service unavailable, API rate limiting). " +
868-
"If this failure recurs, check the GitHub Copilot status page and review the firewall audit logs.\n\n";
869+
context += "The engine exited immediately without producing any output. This often indicates a transient infrastructure issue (e.g., service unavailable, API rate limiting). " + recurringFailureGuidance;
869870
return context;
870871
}
871872

actions/setup/js/handle_agent_failure.test.cjs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,22 @@ describe("handle_agent_failure", () => {
662662
const result = buildEngineFailureContext();
663663
expect(result).toContain("`copilot` engine");
664664
expect(result).toContain("terminated before producing output");
665+
// Copilot-specific status page guidance
666+
expect(result).toContain("GitHub Copilot status page");
667+
});
668+
669+
it("shows provider-agnostic status page guidance for non-copilot engines", () => {
670+
process.env.GH_AW_ENGINE_ID = "claude";
671+
vi.resetModules();
672+
({ buildEngineFailureContext } = require("./handle_agent_failure.cjs"));
673+
const infraLines = ["[WARN] Command completed with exit code: 1", "Process exiting with code: 1"];
674+
fs.writeFileSync(stdioLogPath, infraLines.join("\n") + "\n");
675+
const result = buildEngineFailureContext();
676+
expect(result).toContain("`claude` engine");
677+
expect(result).toContain("terminated before producing output");
678+
// Generic guidance for non-copilot engines
679+
expect(result).toContain("provider status page");
680+
expect(result).not.toContain("GitHub Copilot status page");
665681
});
666682

667683
it("includes engine ID in failure message when GH_AW_ENGINE_ID is set", () => {

actions/setup/js/log_parser_shared.cjs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,31 @@ const MAX_AGENT_TEXT_LENGTH = 2000;
4343
*/
4444
const SIZE_LIMIT_WARNING = "\n\n⚠️ *Step summary size limit reached. Additional content truncated.*\n\n";
4545

46+
/**
47+
* Matches AWF infrastructure lines written by the firewall/container wrapper.
48+
* These lines are produced by the AWF infrastructure (container lifecycle, firewall proxy)
49+
* rather than by the engine itself, and must be excluded when analysing agent output.
50+
*
51+
* Examples of matched lines:
52+
* - [INFO] API proxy logs available at: …
53+
* - [WARN] Command completed with exit code: 1
54+
* - [SUCCESS] Containers stopped successfully
55+
* - [ERROR] …
56+
* - [entrypoint] Starting firewall… (lowercase — container script convention)
57+
* - [health-check] Proxy ready (lowercase — container script convention)
58+
* - Container awf-squid Removed (Docker Compose lifecycle output)
59+
* - Network … Removed
60+
* - Process exiting with code: 1 (AWF wrapper exit line)
61+
*
62+
* Note: INFO/WARN/SUCCESS/ERROR are uppercase (AWF wrapper convention); entrypoint and
63+
* health-check are lowercase (container script convention). Mixed casing is intentional
64+
* and reflects the actual output produced by different AWF components.
65+
*
66+
* Used by parse_copilot_log.cjs (parsePrettyPrintFormat) and handle_agent_failure.cjs
67+
* (buildEngineFailureContext) to strip infrastructure noise from engine log analysis.
68+
*/
69+
const AWF_INFRA_LINE_RE = /^\[(INFO|WARN|SUCCESS|ERROR|entrypoint|health-check)\]|^ (?:Container|Network|Volume) |^Process exiting with code:/;
70+
4671
/**
4772
* Tracks the size of content being added to a step summary.
4873
* Used to prevent exceeding GitHub Actions step summary size limits.
@@ -1650,6 +1675,7 @@ module.exports = {
16501675
// Constants
16511676
MAX_TOOL_OUTPUT_LENGTH,
16521677
MAX_STEP_SUMMARY_SIZE,
1678+
AWF_INFRA_LINE_RE,
16531679
// Classes
16541680
StepSummaryTracker,
16551681
// Functions

actions/setup/js/parse_copilot_log.cjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// @ts-check
22
/// <reference types="@actions/github-script" />
33

4-
const { createEngineLogParser, generateConversationMarkdown, generateInformationSection, formatInitializationSummary, formatToolUse, parseLogEntries } = require("./log_parser_shared.cjs");
4+
const { createEngineLogParser, generateConversationMarkdown, generateInformationSection, formatInitializationSummary, formatToolUse, parseLogEntries, AWF_INFRA_LINE_RE } = require("./log_parser_shared.cjs");
55
const { ERR_PARSE } = require("./error_codes.cjs");
66

77
const main = createEngineLogParser({
@@ -153,7 +153,7 @@ function parsePrettyPrintFormat(logContent) {
153153
return [];
154154
}
155155

156-
const INFRA_LINE_RE = /^\[(INFO|WARN|SUCCESS|ERROR|entrypoint|health-check)\]|^ (?:Container|Network|Volume) |^Process exiting with code:/;
156+
const INFRA_LINE_RE = AWF_INFRA_LINE_RE;
157157
const FAILED_TOOL_RE = /^\s+(\S+)/;
158158
const SUCCESS_TOOL_RE = /^(?:|)\s+(\S+)/;
159159
const CONTINUATION_RE = /^\s+[]/;

0 commit comments

Comments
 (0)