chore: sync actions from gh-aw@v0.83.5 - #201
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot could not run the full agentic suite for this review because it was automatically requested on a bot-authored pull request. Request a review from Copilot under Reviewers to retry with the full agentic suite. Improved support for bot-authored pull requests is coming soon.
This PR improves workflow robustness and diagnostics across agent runs by adding better failure categorization/remediation (notably missing model pricing), enhancing safe-outputs with optional structured data validation/persistence, and tightening infra handling (gateway/tool discovery, watchdog timeouts, firewall domain summaries, and PR review pinning).
Changes:
- Add a dedicated “missing model pricing” failure context with optional live pricing lookup + remediation template, and wire it into failure issue/comment templates.
- Introduce structured
datasupport for safe-outputs (schema normalization + validation + rendering in summaries/previews). - Improve operational resilience: pin PR reviews to specific commits, detect empty safeoutputs gateway tool registration, normalize MCP config regressions, centralize watchdog timeout logic, and filter internal sidecar domains from blocked-domain reporting.
Show a summary per file
| File | Description |
|---|---|
| setup/sh/convert_gateway_config_gemini.sh | Clarifies Gemini gateway host/domain behavior under network isolation. |
| setup/setup.sh | Adds new JS helper to safe-outputs allowlist in setup. |
| setup/md/missing_model_pricing.md | New remediation template for missing model pricing failures. |
| setup/md/agent_failure_issue.md | Injects missing-model-pricing context into failure issue body. |
| setup/md/agent_failure_comment.md | Injects missing-model-pricing context into failure comment body. |
| setup/js/submit_pr_review.cjs | Adds support to pin PR reviews to a specific commit SHA via config. |
| setup/js/start_mcp_gateway.cjs | Normalizes known sink-visibility double-encoding regression in MCP config. |
| setup/js/safe_outputs_tools.json | Updates tool schemas/descriptions; starts introducing structured-data documentation. |
| setup/js/safe_outputs_handlers.cjs | Validates/enforces structured data enablement + schema validation at handler layer. |
| setup/js/safe_output_type_validator.cjs | Validates structured data, normalizes it, and persists it via body appending. |
| setup/js/safe_output_summary.cjs | Renders structured data into generated step summaries. |
| setup/js/render_template.cjs | Preserves leading newline when stripping template blocks to avoid line-joining. |
| setup/js/push_to_pull_request_branch.cjs | Refactors git auth extraheader override into shared helper. |
| setup/js/process_runner.cjs | Centralizes post-result watchdog timeout constants and resolver. |
| setup/js/pr_review_buffer.cjs | Implements commit pinning for PR reviews (trigger-time SHA / configured SHA). |
| setup/js/parse_firewall_logs.cjs | Filters internal sidecar hostnames from blocked-domain reporting/summaries. |
| setup/js/package.json | Bumps Copilot SDK and updates minimatch version constraint. |
| setup/js/mount_mcp_as_cli.cjs | Adds “gateway empty tools” flag and fails fast when safeoutputs tools/list is empty. |
| setup/js/models.json | Adds pricing entry for gemini-3.6-flash. |
| setup/js/mcp_scripts_validation.cjs | Exposes validateValueAgainstSchema for non-argument schema validation. |
| setup/js/log_parser_shared.cjs | Adds structured data preview rendering in safe-outputs log preview. |
| setup/js/handle_agent_failure.cjs | Adds missing-model-pricing detection/context, fetches pricing from models.dev, and improves titles/categories. |
| setup/js/git_auth_helpers.cjs | Introduces shared withGitHubHostToken helper for temporary extraheader overrides. |
| setup/js/firewall_blocked_domains.cjs | Filters internal sidecar hostnames from blocked-domain warnings shown externally. |
| setup/js/detect_agent_errors.cjs | Detects missing-model-pricing via stdio + firewall audit logs, outputs model name. |
| setup/js/data_schema_normalizer.cjs | New normalizer for structured-data schemas (shorthand + keyword validation). |
| setup/js/create_pull_request.cjs | Uses shared git auth helper and scopes git ops via cwd for correctness. |
| setup/js/create_pr_review_comment.cjs | Adds support to pin PR review comments to a commit SHA via config. |
| setup/js/copilot_harness.cjs | Reuses centralized watchdog timeout logic and refines retry/success suppression rules. |
| setup/js/collect_ndjson_output.cjs | Fails hard on missing outputs when gateway-empty flag exists; passes structured-data config into validation. |
| setup/js/codex_harness.cjs | Adds post-result watchdog + terminal safe-output detection to treat exit-hangs as success. |
| setup/js/apply_samples.cjs | Improves PR head ref resolution using args/inputs/config target and adds helpers. |
| setup/js/ai_credits_context.cjs | Expands audit/event JSONL path probing and extracts model name for unknown-model AI credits events. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 33/33 changed files
- Comments generated: 7
- Review effort level: Low
| if (entry.data !== undefined) { | ||
| const toolConfig = getSafeOutputsToolConfig(config, type); | ||
| const dataEnabled = toolConfig?.data_enabled === true || (toolConfig?.data_schema && typeof toolConfig.data_schema === "object"); | ||
| if (!dataEnabled) { | ||
| return buildIntentErrorResponse(`${type} data is not enabled (set safe-outputs.data in workflow frontmatter)`); | ||
| } |
| const requiredSet = new Set(Object.keys(normalizedProperties)); | ||
| if (node.required !== undefined) { | ||
| if (!Array.isArray(node.required)) { | ||
| throw new Error(`${path}.required: must be an array of strings`); | ||
| } | ||
| for (let i = 0; i < node.required.length; i++) { | ||
| const requiredName = node.required[i]; | ||
| if (typeof requiredName !== "string" || requiredName.trim().length === 0) { | ||
| throw new Error(`${path}.required[${i}]: must be a non-empty string`); | ||
| } | ||
| if (!Object.prototype.hasOwnProperty.call(normalizedProperties, requiredName)) { | ||
| throw new Error(`${path}.required[${i}]: unknown property "${requiredName}"`); | ||
| } | ||
| requiredSet.add(requiredName); | ||
| } | ||
| } | ||
| result.required = [...requiredSet].sort(); |
| "inputSchema": { | ||
| "type": "object", | ||
| "required": ["title", "body"], | ||
| "$defs": { | ||
| "structured_data": { | ||
| "type": "object", | ||
| "description": "Optional structured data to carry machine-readable context through sanitization-safe channels. When provided, this object is preserved and appended to the body as fenced JSON.", | ||
| "additionalProperties": true | ||
| } | ||
| }, | ||
| "properties": { |
| // If this safe-output type supports a body field, append structured data | ||
| // as fenced JSON so it survives body sanitization. | ||
| if (Object.prototype.hasOwnProperty.call(typeConfig.fields, "body")) { | ||
| const dataBlock = `${STRUCTURED_DATA_LABEL}\n\`\`\`json\n${dataJSON}\n\`\`\``; | ||
| if (typeof normalizedItem.body === "string" && normalizedItem.body.length > 0) { | ||
| normalizedItem.body = `${normalizedItem.body}\n\n${dataBlock}`; | ||
| } else { | ||
| normalizedItem.body = dataBlock; | ||
| } | ||
| } |
| function recoverSafeOutputsToolsIfNeeded(tools, core) { | ||
| if (tools.length > 0) { | ||
| return tools; | ||
| } | ||
| const fallbackPath = process.env.GH_AW_SAFE_OUTPUTS_TOOLS_PATH || `${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json`; | ||
| const recovered = loadToolsFromJSONFile(fallbackPath, core); | ||
| if (recovered.length > 0) { | ||
| core.warning(` safeoutputs tools/list returned empty; recovered ${recovered.length} tool(s) from ${fallbackPath}`); | ||
| return recovered; | ||
| } | ||
| throw new Error(`safeoutputs tool schema is empty (tools/list returned 0 and fallback ${fallbackPath} is empty/missing). ` + `Failing fast to avoid agent runs without discoverable safe-output tools.`); | ||
|
|
||
| // The live MCP gateway returned 0 tools for safeoutputs. Write a flag file so | ||
| // that collect_ndjson_output.cjs can surface this as a hard failure instead of | ||
| // silently concluding "graceful no-op" when outputs.jsonl is never written. | ||
| writeSafeOutputsGatewayEmptyFlag(core); | ||
|
|
||
| throw new Error(`safeoutputs tools/list returned 0 tools. ` + `Failing fast — the live MCP gateway has no tools registered. ` + `Check the MCP gateway startup logs for ECONNRESET errors or delayed backend registration.`); |
| "@vitest/coverage-v8": "^4.1.8", | ||
| "@vitest/ui": "^4.1.10", | ||
| "minimatch": ">=3.1.3", | ||
| "minimatch": ">=10.2.6", |
| /** | ||
| * Build a frontmatter YAML pricing snippet for the missing model. | ||
| * Returns null when pricing data is unavailable. | ||
| * @param {string} modelName | ||
| * @param {string} engineId | ||
| * @param {{input: number, output: number, cacheRead?: number, cacheWrite?: number}|null} pricing Per-million-token values from models.dev | ||
| * @returns {string|null} | ||
| */ | ||
| function buildModelPricingFrontmatterSnippet(modelName, engineId, pricing, isPlaceholderPricing = false) { |
Automated sync of actions from gh-aw at
v0.83.5.