Conversation
When the Copilot CLI runs with --log-dir pointing to a directory, debug JSON logs go to that directory and stdout only contains the pretty-print format (✗/● markers for tool calls). The existing parser only handled JSON array, debug log (with [DEBUG] data: blocks), and JSONL formats, so all Copilot runs with a --log-dir produced "Log format not recognized" in the step summary instead of useful output. Adds parsePrettyPrintFormat() which detects and parses the ✗/● marker format by: - Filtering Docker Compose and infrastructure log lines - Extracting failed tool calls (✗), successful tool calls (●), and their indented continuation lines (└) - Collecting agent text paragraphs - Parsing token usage from the model breakdown section Also updates additionalInfoCallback to read _premium_requests from the result entry (set by parsePrettyPrintFormat) rather than re-scanning the raw log content. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds support for parsing the Copilot CLI “pretty-print” stdout log format (tool markers + indented continuations) so Copilot workflow runs using --log-dir produce a usable Agent Log Summary instead of “format not recognized”.
Changes:
- Adds a new
parsePrettyPrintFormat()fallback inparseCopilotLog()when JSON array / debug-block / JSONL parsing yields no entries. - Extracts tool calls (success/failure), agent text, token usage, and premium usage metadata from the pretty-print format.
- Updates the Information section’s premium request count logic to prefer a parsed
_premium_requestsvalue when available.
Comments suppressed due to low confidence (1)
actions/setup/js/parse_copilot_log.cjs:159
- SUCCESS_TOOL_RE currently matches only the ● marker. If the CLI emits ✓ for successful tool calls, those lines will be misclassified as agent text instead of tool calls. Consider expanding this regex to match both ✓ and ● (and keep the comment/docstring consistent with the accepted markers).
const FAILED_TOOL_RE = /^✗\s+(\S+)/;
const SUCCESS_TOOL_RE = /^●\s+(\S+)/;
const CONTINUATION_RE = /^\s+[└│]/;
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| * This format uses ✗ for failed tool calls and ● for successful ones. | ||
| * @param {string} logContent - Raw log content as a string | ||
| * @returns {Array} Array of log entries in structured format, or empty array if not detected | ||
| */ | ||
| function parsePrettyPrintFormat(logContent) { | ||
| // Only attempt this format if the characteristic markers are present | ||
| if (!/^[✗●]/m.test(logContent)) { | ||
| return []; | ||
| } | ||
|
|
||
| const INFRA_LINE_RE = /^\[(INFO|WARN|SUCCESS|ERROR|entrypoint|health-check)\]|^ (?:Container|Network|Volume) |^Process exiting with code:/; | ||
| const FAILED_TOOL_RE = /^✗\s+(\S+)/; | ||
| const SUCCESS_TOOL_RE = /^●\s+(\S+)/; |
There was a problem hiding this comment.
The pretty-print format detection only looks for lines starting with ✗ or ●. Copilot CLI output (and this PR’s example) appears to use ✓ for successful tool calls, and runs with only successful tools would fail detection and fall through to “Log format not recognized”. Consider accepting ✓ as a success marker (and including it in the initial marker detection).
This issue also appears on line 157 of the same file.
| * This format uses ✗ for failed tool calls and ● for successful ones. | |
| * @param {string} logContent - Raw log content as a string | |
| * @returns {Array} Array of log entries in structured format, or empty array if not detected | |
| */ | |
| function parsePrettyPrintFormat(logContent) { | |
| // Only attempt this format if the characteristic markers are present | |
| if (!/^[✗●]/m.test(logContent)) { | |
| return []; | |
| } | |
| const INFRA_LINE_RE = /^\[(INFO|WARN|SUCCESS|ERROR|entrypoint|health-check)\]|^ (?:Container|Network|Volume) |^Process exiting with code:/; | |
| const FAILED_TOOL_RE = /^✗\s+(\S+)/; | |
| const SUCCESS_TOOL_RE = /^●\s+(\S+)/; | |
| * This format uses ✗ for failed tool calls and ● or ✓ for successful ones. | |
| * @param {string} logContent - Raw log content as a string | |
| * @returns {Array} Array of log entries in structured format, or empty array if not detected | |
| */ | |
| function parsePrettyPrintFormat(logContent) { | |
| // Only attempt this format if the characteristic markers are present | |
| if (!/^[✗●✓]/m.test(logContent)) { | |
| return []; | |
| } | |
| const INFRA_LINE_RE = /^\[(INFO|WARN|SUCCESS|ERROR|entrypoint|health-check)\]|^ (?:Container|Network|Volume) |^Process exiting with code:/; | |
| const FAILED_TOOL_RE = /^✗\s+(\S+)/; | |
| const SUCCESS_TOOL_RE = /^(?:●|✓)\s+(\S+)/; |
| // If still nothing, try the pretty-print stdout format (✗/● markers) | ||
| if (!logEntries || logEntries.length === 0) { | ||
| const prettyPrintEntries = parsePrettyPrintFormat(logContent); | ||
| if (prettyPrintEntries && prettyPrintEntries.length > 0) { | ||
| logEntries = prettyPrintEntries; |
There was a problem hiding this comment.
New pretty-print fallback parsing is not covered by tests. Since this adds a new supported log format (and regex-heavy parsing), add vitest cases in parse_copilot_log.test.cjs exercising: (1) success + failure tool markers, (2) continuation/indented output capture, and (3) token + premium request extraction.
| entries.push({ | ||
| type: "result", | ||
| num_turns: toolEntries.length, |
There was a problem hiding this comment.
num_turns is currently set to toolEntries.length, which is likely not the same as the CLI’s “Turns:” count (e.g., a single turn may include multiple tool calls, or zero tool calls). This will make the Information section’s Turns value inaccurate. Consider parsing the “Turns:” line from the Statistics/usage section (if present) and storing that value in the result entry instead.
| entries.push({ | |
| type: "result", | |
| num_turns: toolEntries.length, | |
| // Derive the number of turns from the CLI's "Turns:" statistic if available. | |
| // Fallback to the number of tool entries to preserve existing behavior when absent. | |
| let numTurns = toolEntries.length; | |
| const turnsMatch = logContent && logContent.match(/Turns:\s*(\d+)/i); | |
| if (turnsMatch && turnsMatch[1]) { | |
| const parsedTurns = parseInt(turnsMatch[1], 10); | |
| if (!Number.isNaN(parsedTurns) && parsedTurns > 0) { | |
| numTurns = parsedTurns; | |
| } | |
| } | |
| entries.push({ | |
| type: "result", | |
| num_turns: numTurns, |
|
@copilot review comments |
- Add ✓ as success marker alongside ● in detection regex and SUCCESS_TOOL_RE - Parse Turns: line from log for num_turns with fallback to toolEntries.length - Add 6 tests covering: success/failure markers, ✓ marker, continuation output, token extraction, premium flag, and Turns: count parsing Agent-Logs-Url: https://github.com/github/gh-aw/sessions/74f36bfb-a0dd-4357-b3d4-74c9f6569bec Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
- Remove unnecessary `logContent &&` guard (logContent is already used without null checks) - Use optional chaining `resultEntry?.num_turns` in test to prevent potential null reference Agent-Logs-Url: https://github.com/github/gh-aw/sessions/74f36bfb-a0dd-4357-b3d4-74c9f6569bec Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Addressed all three review comments in commit
|
Discovered via run §23896942706 (Issue Monster, copilot engine).
Problem
When the Copilot CLI is invoked with
--log-dir(which routes debug JSON logs to a file),agent-stdio.logonly captures the pretty-print stdout format that uses✗/●/✓markers for tool calls. The existing parser tried three formats — JSON array,[DEBUG](redacted) debug blocks, and JSONL — and fell through to "Log format not recognized".This affected every Copilot workflow run that uses the standard
--log-dirflag.Fix
Added
parsePrettyPrintFormat()toparse_copilot_log.cjsas a fourth fallback. The function:✗,●, or✓markersContainer awf-...) and infra log lines ([INFO],[entrypoint], etc.)✗), successful tool calls (●or✓), and their indented continuation output (└)Breakdown by AI model:sectionTurns:line from the statistics section for accurate turn count (falls back to tool entry count when absent)model_info.billing.is_premium = truewhen premium model usage is detectedAlso updated
additionalInfoCallbackto read_premium_requestsfrom the result entry (set by the new parser) instead of re-scanning the raw log content.Testing
parse_copilot_logtests pass (23 original + 6 new)●/✗marker parsing,✓marker parsing, continuation/indented output capture, token count extraction, premium flag detection, andTurns:count parsing