workflow

package
v0.43.23 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 14, 2026 License: MIT Imports: 37 Imported by: 0

Documentation

Overview

Package workflow implements workflow compilation orchestration.

The compiler orchestrator is split into 5 focused modules for maintainability:

  • orchestrator.go: Shared logger and constants used across orchestrator modules
  • orchestrator_engine.go: Engine detection, validation, and setup logic
  • orchestrator_frontmatter.go: Frontmatter parsing and validation
  • orchestrator_tools.go: Tool configuration and MCP server setup
  • orchestrator_workflow.go: Main workflow orchestration and YAML generation

The orchestrator follows a phased approach with typed result structures for clear data flow between compilation stages. Each module handles a specific concern in the compilation pipeline, making the codebase easier to understand and maintain.

Package workflow provides compilation and generation of GitHub Actions workflows from markdown-based agentic workflow specifications.

The workflow package is the core of gh-aw, handling the transformation of user-friendly markdown files into production-ready GitHub Actions YAML workflows. It supports advanced features including:

  • Agentic AI workflow execution with Claude, Codex, and Copilot engines
  • Safe output handling with configurable permissions
  • MCP (Model Context Protocol) server integration
  • Network sandboxing and firewall configuration
  • GitHub Actions security best practices (SHA pinning, input sanitization)

Basic Usage

compiler := workflow.NewCompiler(workflow.CompilerOptions{
	Verbose: true,
})
err := compiler.CompileWorkflow("path/to/workflow.md")
if err != nil {
	log.Fatal(err)
}

Architecture

The compilation process consists of:

  1. Frontmatter parsing - Extracts YAML metadata (triggers, permissions, tools)
  2. Markdown processing - Extracts the AI prompt text from markdown body
  3. Tool configuration - Configures MCP servers, safe outputs, and GitHub tools
  4. Job generation - Creates main agent job, activation jobs, and safe output jobs
  5. YAML generation - Produces final GitHub Actions workflow with security features

Key Components

Compiler: The main orchestrator that coordinates all compilation phases. Handles markdown parsing, frontmatter extraction, and YAML generation.

Engine Configuration: Supports multiple AI engines (copilot, claude, codex, custom). Each engine has specific tool integrations and execution patterns.

MCP Servers: Model Context Protocol servers provide tools to AI agents. Configured via frontmatter and can run as stdio processes, HTTP endpoints, or containerized services.

Safe Outputs: Write operations (create issue, add comment, etc.) are sanitized and executed in separate jobs with minimal permissions to prevent prompt injection attacks.

Network Sandboxing: Firewall configuration restricts network access to approved domains, preventing data exfiltration and unauthorized API calls.

Security Features

The workflow package implements multiple security layers:

  • SHA-pinned GitHub Actions (no tag-based references)
  • Input sanitization for all user-provided data
  • Read-only execution by default with explicit safe-output gates
  • Network firewalls with domain allowlists
  • Tool allowlisting (MCP servers, safe outputs)
  • Template injection prevention
  • Secrets redaction and masking

pkg/parser - Markdown and YAML frontmatter parsing

pkg/cli - Command-line interface for compilation and workflow management

pkg/types - Shared type definitions for MCP and workflow configuration

Package workflow provides built-in MCP server configuration rendering.

Built-in MCP Servers

This file implements rendering functions for gh-aw's built-in MCP servers: safe-outputs, agentic-workflows, and their variations. These servers provide core functionality for AI agent workflows including controlled output storage, workflow execution, and memory management.

Key responsibilities:

  • Rendering safe-outputs MCP server configuration (HTTP transport)
  • Rendering agentic-workflows MCP server configuration (stdio transport)
  • Engine-specific format handling (JSON vs TOML)
  • Managing HTTP server endpoints and authentication
  • Configuring Docker containers for stdio servers
  • Handling environment variable passthrough

Built-in MCP servers:

1. Safe-outputs MCP server:

  • Transport: HTTP (runs on host, accessed via HTTP)
  • Port: 3001 (configurable via GH_AW_SAFE_OUTPUTS_PORT)
  • Authentication: API key in Authorization header
  • Purpose: Provides controlled storage for AI agent outputs
  • Tools: add_issue_comment, create_issue, update_issue, upload_asset, etc.

2. Agentic-workflows MCP server:

  • Transport: stdio (runs in Docker container)
  • Container: Alpine Linux with gh-aw binary mounted (or localhost/gh-aw:dev in dev mode)
  • Entrypoint: /opt/gh-aw/gh-aw mcp-server (release mode) or container default (dev mode)
  • Network: Enabled via --network host for GitHub API access (api.github.com)
  • Purpose: Enables workflow compilation, validation, and execution via gh aw CLI
  • Tools: compile, validate, list, status, audit, logs, add, update, fix

HTTP vs stdio transport: - HTTP: Server runs on host, accessible via HTTP URL with authentication - stdio: Server runs in Docker container, communicates via stdin/stdout

Engine compatibility: The renderer supports multiple output formats:

  • JSON (Copilot, Claude, Custom): JSON-like MCP configuration
  • TOML (Codex): TOML-like MCP configuration

Copilot-specific features: When IncludeCopilotFields is true, the renderer adds:

  • "type" field: Specifies transport type (http or stdio)
  • Backslash-escaped variables: \${VAR} for MCP passthrough

Safe-outputs configuration: Safe-outputs runs as an HTTP server and requires:

  • Port and API key from step outputs
  • Config files: config.json, tools.json, validation.json
  • Environment variables for feature configuration

The HTTP URL uses either:

  • host.docker.internal: When agent runs in firewall container
  • localhost: When agent firewall is disabled (sandbox.agent.disabled)

Agentic-workflows configuration: Agentic-workflows runs in a stdio container and requires:

  • Mounted gh-aw binary from /opt/gh-aw (release mode) or baked into image (dev mode)
  • Mounted gh CLI binary for GitHub API access (release mode) or baked into image (dev mode)
  • Mounted workspace for workflow files
  • Mounted temp directory for logs
  • GITHUB_TOKEN for GitHub API access
  • Network access enabled via --network host for api.github.com

Related files:

  • mcp_renderer.go: Main renderer that calls these functions
  • mcp_setup_generator.go: Generates setup steps for these servers
  • safe_outputs.go: Safe-outputs configuration and validation
  • safe_inputs.go: Safe-inputs configuration (similar pattern)

Example safe-outputs config:

{
  "safe_outputs": {
    "type": "http",
    "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT",
    "headers": {
      "Authorization": "$GH_AW_SAFE_OUTPUTS_API_KEY"
    }
  }
}

Example agentic-workflows config:

{
  "agenticworkflows": {
    "type": "stdio",
    "container": "alpine:3.20",
    "entrypoint": "/opt/gh-aw/gh-aw",
    "entrypointArgs": ["mcp-server"],
    "mounts": ["/opt/gh-aw:/opt/gh-aw:ro", ...],
    "env": {
      "GITHUB_TOKEN": "$GITHUB_TOKEN"
    }
  }
}

Package workflow provides Playwright MCP server configuration and Docker setup.

Playwright MCP Server

This file handles the configuration and rendering of the Playwright MCP server, which provides AI agents with browser automation capabilities through the Model Context Protocol (MCP). Playwright enables agents to interact with web pages, take screenshots, extract content, and perform accessibility testing.

Key responsibilities:

  • Generating Playwright MCP server configuration
  • Managing Docker container setup for Playwright
  • Handling allowed domains for browser navigation
  • Processing custom Playwright arguments
  • Extracting and managing domain secrets from expressions
  • Rendering configuration for different AI engines

Container configuration: Playwright runs in a Docker container using the official Microsoft Playwright MCP image (mcr.microsoft.com/playwright/mcp). The container is configured with:

  • --init flag for proper signal handling
  • --network host for network access
  • Volume mounts for log storage
  • Output directory for screenshots and artifacts

Domain restrictions: For security, Playwright is restricted to specific allowed domains configured in the workflow frontmatter. These domains are passed via:

  • --allowed-hosts: Domains the browser can navigate to
  • --allowed-origins: Domains that can be used as origins

Expression handling: When allowed_domains contains GitHub Actions expressions like ${{ secrets.DOMAIN }}, these are extracted and made available as environment variables. The actual secret values are resolved at runtime and passed to the Playwright container.

Engine compatibility: The renderer supports multiple AI engines with engine-specific formatting:

  • Copilot: Includes "type" field, inline args
  • Claude/Custom: Multi-line args, simplified format
  • All engines: Same core configuration structure

Related files:

  • mcp_playwright_config.go: Playwright configuration types and parsing
  • mcp_renderer.go: Main MCP renderer that calls this function
  • mcp_setup_generator.go: Includes Playwright in setup sequence

Example configuration:

tools:
  playwright:
    version: v1.41.0
    allowed_domains:
      - github.com
      - api.github.com
      - ${{ secrets.CUSTOM_DOMAIN }}
    custom_args:
      - --debug
      - --timeout=30000

Package workflow provides utility functions for MCP configuration processing.

MCP Configuration Utilities

This file contains helper functions for processing and transforming MCP configuration data during workflow compilation. These utilities handle common operations needed across different MCP server types.

Key functionality:

  • URL rewriting for Docker networking
  • Localhost to host.docker.internal translation

URL rewriting: When MCP servers run on the host machine (like safe-outputs HTTP server on port 3001) but need to be accessed from within a Docker container (like the firewall container running the AI agent), localhost URLs must be rewritten to use host.docker.internal.

This ensures that containerized AI agents can communicate with MCP servers running on the host system while maintaining network isolation.

Supported URL patterns:

Use cases:

  • Safe-outputs HTTP server accessed from firewall container
  • Safe-inputs HTTP server accessed from firewall container
  • Custom HTTP MCP servers on localhost

Related files:

  • mcp_renderer.go: Uses URL rewriting for HTTP MCP servers
  • safe_outputs.go: Safe outputs HTTP server configuration
  • safe_inputs.go: Safe inputs HTTP server configuration

Example:

// Before: http://localhost:3001
// After:  http://host.docker.internal:3001
url := rewriteLocalhostToDockerHost("http://localhost:3001")

Package workflow provides environment variable management for MCP server execution.

MCP Environment Variables

This file is responsible for collecting and managing all environment variables required by MCP servers during workflow execution. Environment variables are used to pass configuration, authentication tokens, and runtime settings to MCP servers running in the gateway.

Key responsibilities:

  • Collecting MCP-related environment variables from workflow configuration
  • Managing GitHub MCP server tokens (custom, default, and GitHub App tokens)
  • Handling safe-outputs and safe-inputs environment variables
  • Processing Playwright domain secrets
  • Extracting secrets from HTTP MCP server headers
  • Managing agentic-workflows GITHUB_TOKEN

Environment variable categories:

  • GitHub MCP: GITHUB_MCP_SERVER_TOKEN, GITHUB_MCP_LOCKDOWN
  • Safe Outputs: GH_AW_SAFE_OUTPUTS_*, GH_AW_ASSETS_*
  • Safe Inputs: GH_AW_SAFE_INPUTS_PORT, GH_AW_SAFE_INPUTS_API_KEY
  • Serena: GH_AW_SERENA_PORT (local mode only)
  • Playwright: Domain secrets from allowed_domains expressions
  • HTTP MCP: Custom secrets from headers and env sections

Token precedence for GitHub MCP:

  1. GitHub App token (if app configuration exists)
  2. Custom github-token from tool configuration
  3. Top-level github-token from frontmatter
  4. Default GITHUB_TOKEN secret

The environment variables collected here are passed to both the "Start MCP gateway" step and the "MCP Gateway" step to ensure MCP servers have access to necessary configuration and secrets.

Related files:

  • mcp_setup_generator.go: Uses collected env vars in gateway setup
  • mcp_github_config.go: GitHub-specific token and configuration
  • safe_outputs.go: Safe outputs configuration
  • safe_inputs.go: Safe inputs configuration

Example usage:

envVars := collectMCPEnvironmentVariables(tools, mcpTools, workflowData, hasAgenticWorkflows)
// Returns map[string]string with all required environment variables

Package workflow provides MCP gateway configuration management for agentic workflows.

MCP Gateway Configuration

The MCP gateway acts as a proxy between AI engines and MCP servers, providing protocol translation, connection management, and security features. This file handles the configuration and setup of the MCP gateway for workflow execution.

Key responsibilities:

  • Setting default MCP gateway container and version
  • Ensuring gateway configuration exists with sensible defaults
  • Building gateway configuration for MCP config files
  • Managing gateway port, domain, and API key settings

The gateway configuration includes:

  • Container image and version (defaults to github/gh-aw-mcpg)
  • Network port (default: 80)
  • Domain for gateway access (localhost or host.docker.internal)
  • API key for authentication
  • Volume mounts for workspace and temporary directories

Configuration flow:

  1. ensureDefaultMCPGatewayConfig: Sets defaults if not provided
  2. buildMCPGatewayConfig: Builds gateway config for MCP files
  3. isSandboxDisabled: Checks if sandbox features are disabled

When sandbox is disabled (sandbox: false), the gateway is skipped entirely and MCP servers communicate directly without the gateway proxy.

Related files:

  • mcp_gateway_constants.go: Gateway version and container constants
  • mcp_setup_generator.go: Setup step generation with gateway startup
  • mcp_renderer.go: YAML rendering for MCP configurations

Example gateway configuration:

sandbox:
  mcp:
    container: github/gh-aw-mcpg
    version: v0.0.12
    port: 80
    domain: host.docker.internal
    mounts:
      - /opt:/opt:ro
      - /tmp:/tmp:rw

Package workflow provides constants for MCP gateway configuration.

MCP Gateway Constants

This file provides access to MCP gateway configuration constants.

Gateway default values:

  • Port: 80 (HTTP standard port) - defined in pkg/constants

The MCP gateway port is used when:

  • No custom port is specified in sandbox.mcp.port
  • Building gateway configuration in mcp_gateway_config.go
  • Generating gateway startup commands in mcp_setup_generator.go

Historical note: This constant was originally defined locally but has been moved to pkg/constants for centralization with other network port constants.

Related files:

  • mcp_gateway_config.go: Uses DefaultMCPGatewayPort for configuration
  • mcp_setup_generator.go: Uses port for gateway startup
  • constants/constants.go: Defines all MCP-related constants (versions, containers, ports)

Related constants in pkg/constants:

  • DefaultMCPGatewayPort: Gateway port (80)
  • DefaultMCPGatewayVersion: Gateway container version
  • DefaultMCPGatewayContainer: Gateway container image
  • DefaultGitHubMCPServerVersion: GitHub MCP server version

Package workflow provides GitHub MCP server configuration and toolset management.

GitHub MCP Server Configuration

This file manages the configuration of the GitHub MCP server, which provides AI agents with access to GitHub's API through the Model Context Protocol (MCP). It handles both local (Docker-based) and remote (hosted) deployment modes.

Key responsibilities:

  • Extracting GitHub tool configuration from workflow frontmatter
  • Managing GitHub MCP server modes (local Docker vs remote hosted)
  • Handling GitHub authentication tokens (custom, default, GitHub App)
  • Managing read-only and lockdown security modes
  • Expanding and managing GitHub toolsets (repos, issues, pull_requests, etc.)
  • Handling allowed tool lists for fine-grained access control
  • Determining Docker image versions for local mode
  • Generating automatic lockdown detection steps
  • Managing GitHub App token minting and invalidation

GitHub MCP modes:

  • Local (default): Runs GitHub MCP server in Docker container
  • Remote: Uses hosted GitHub MCP service

Security features:

  • Read-only mode: Prevents write operations (default: true)
  • GitHub lockdown mode: Restricts access to current repository only
  • Automatic lockdown: Enables lockdown for public repositories with GH_AW_GITHUB_TOKEN
  • Allowed tools: Restricts available GitHub API operations

GitHub toolsets:

  • default/action-friendly: Standard toolsets safe for GitHub Actions
  • repos, issues, pull_requests, discussions, search, code_scanning
  • secret_scanning, labels, releases, milestones, projects, gists
  • teams, actions, packages (requires specific permissions)
  • users (excluded from action-friendly due to token limitations)

Token precedence:

  1. GitHub App token (minted from app configuration)
  2. Custom github-token from tool configuration
  3. Top-level github-token from frontmatter
  4. Default GITHUB_TOKEN secret

Automatic lockdown detection: When lockdown is not explicitly set, a step is generated to automatically enable lockdown for public repositories ONLY when GH_AW_GITHUB_TOKEN is configured.

Related files:

  • mcp_renderer.go: Renders GitHub MCP configuration to YAML
  • mcp_environment.go: Manages GitHub MCP environment variables
  • mcp_setup_generator.go: Generates GitHub MCP setup steps
  • safe_outputs_app.go: GitHub App token minting helpers

Example configuration:

tools:
  github:
    mode: remote                    # or "local" for Docker
    github-token: ${{ secrets.PAT }}
    read-only: true
    lockdown: true                  # or omit for automatic detection
    toolsets: [repos, issues, pull_requests]
    allowed: [get_repo, list_issues, get_pull_request]

Package workflow provides YAML rendering for MCP server configurations.

MCP Configuration Renderer

This file implements the unified MCP configuration renderer that generates YAML configuration for various MCP servers across different AI engines (Copilot, Claude, Codex, Custom). It provides a consistent interface for rendering MCP configurations while handling engine-specific format requirements.

Key responsibilities:

  • Unified rendering interface for all MCP server types
  • Engine-specific format handling (JSON-like vs TOML-like)
  • GitHub MCP server configuration (local Docker and remote hosted)
  • Playwright MCP server configuration
  • Safe-outputs and safe-inputs MCP server configuration
  • Agentic-workflows MCP server configuration
  • Cache-memory MCP server configuration
  • Serena MCP server configuration
  • Custom HTTP and stdio MCP server configuration

Renderer architecture: The renderer uses the MCPConfigRendererUnified struct with MCPRendererOptions to configure engine-specific behaviors:

  • IncludeCopilotFields: Add "type" and "tools" fields for Copilot
  • InlineArgs: Render args inline (Copilot) vs multi-line (Claude/Custom)
  • Format: "json" for JSON-like or "toml" for TOML-like output
  • IsLast: Control trailing commas in rendered configuration

Supported MCP server types:

  • GitHub: Local (Docker) or remote (hosted) GitHub API access
  • Playwright: Browser automation with domain restrictions
  • Safe-outputs: Controlled output storage for AI agents
  • Safe-inputs: Custom tool execution with secret passthrough
  • Cache-memory: Memory/knowledge base management
  • Agentic-workflows: Workflow execution via gh-aw extension
  • Serena: Local search functionality
  • Custom HTTP: User-defined HTTP-based MCP servers
  • Custom stdio: User-defined stdio-based MCP servers

Engine-specific rendering:

  • Copilot: JSON format with "type" and "tools" fields, inline args
  • Claude: JSON format without Copilot fields, multi-line args
  • Codex: TOML format for MCP configuration
  • Custom: Same as Claude (JSON, multi-line args)

Configuration structure: All MCP servers follow the MCP Gateway Specification v1.0.0:

  • HTTP servers: type, url, headers
  • Stdio servers: type, container, entrypoint, entrypointArgs, mounts, env

Variable resolution: The renderer handles two types of variable syntax:

  • Shell variables: $VAR or ${VAR} - resolved by shell before gateway
  • Gateway variables: ${VAR} in JSON - resolved by gateway at runtime

Copilot-specific features: Copilot uses backslash-escaped variables (\${VAR}) for proper MCP passthrough and includes additional fields required by the Copilot MCP specification.

Related files:

  • mcp_github_config.go: GitHub MCP server configuration
  • mcp_config_playwright_renderer.go: Playwright-specific rendering
  • mcp_config_builtin.go: Built-in MCP server rendering
  • mcp_config_custom.go: Custom MCP server rendering
  • mcp_setup_generator.go: Calls renderer for configuration generation

Example usage:

renderer := NewMCPConfigRenderer(MCPRendererOptions{
    IncludeCopilotFields: true,
    InlineArgs: true,
    Format: "json",
    IsLast: false,
})
renderer.RenderGitHubMCP(yaml, githubTool, workflowData)

Package workflow provides GitHub Actions setup step generation for MCP servers.

MCP Setup Generator

This file generates the complete setup sequence for MCP servers in GitHub Actions workflows. It orchestrates the initialization of all MCP tools including built-in servers (GitHub, Playwright, safe-outputs, safe-inputs) and custom HTTP/stdio MCP servers.

Key responsibilities:

  • Identifying and collecting MCP tools from workflow configuration
  • Generating Docker image download steps
  • Installing gh-aw extension for agentic-workflows tool
  • Setting up safe-outputs MCP server (config, API key, HTTP server)
  • Setting up safe-inputs MCP server (config, tool files, HTTP server)
  • Starting Serena MCP server in local mode
  • Starting the MCP gateway with proper environment variables
  • Rendering MCP configuration for the selected AI engine

Setup sequence:

  1. Download required Docker images
  2. Install gh-aw extension (if agentic-workflows enabled)
  3. Write safe-outputs config files (config.json, tools.json, validation.json)
  4. Generate and start safe-outputs HTTP server
  5. Setup safe-inputs config and tool files (JavaScript, Python, Shell, Go)
  6. Generate and start safe-inputs HTTP server
  7. Start Serena local mode server
  8. Start MCP gateway with all environment variables
  9. Render engine-specific MCP configuration

MCP tools supported:

  • github: GitHub API access via MCP (local Docker or remote hosted)
  • playwright: Browser automation with Playwright
  • safe-outputs: Controlled output storage for AI agents
  • safe-inputs: Custom tool execution with secret passthrough
  • cache-memory: Memory/knowledge base management
  • agentic-workflows: Workflow execution via gh-aw
  • serena: Local Serena search functionality
  • Custom HTTP/stdio MCP servers

Gateway modes:

  • Enabled (default): MCP servers run through gateway proxy
  • Disabled (sandbox: false): Direct MCP server communication

Related files:

  • mcp_gateway_config.go: Gateway configuration management
  • mcp_environment.go: Environment variable collection
  • mcp_renderer.go: MCP configuration YAML rendering
  • safe_outputs.go: Safe outputs server configuration
  • safe_inputs.go: Safe inputs server configuration

Example workflow setup:

  • Download Docker images
  • Write safe-outputs config to /opt/gh-aw/safeoutputs/
  • Start safe-outputs HTTP server on port 3001
  • Write safe-inputs config to /opt/gh-aw/safe-inputs/
  • Start safe-inputs HTTP server on port 3000
  • Start MCP gateway on port 80
  • Render MCP config based on engine (copilot/claude/codex/custom)

Index

Constants

View Source
const (
	// MaxLockFileSize is the maximum allowed size for generated lock workflow files (500KB)
	MaxLockFileSize = 512000 // 500KB in bytes

	// MaxExpressionSize is the maximum allowed size for GitHub Actions expression values (21KB)
	// This includes environment variable values, if conditions, and other expression contexts
	// See: https://docs.github.com/en/actions/learn-github-actions/usage-limits-billing-and-administration
	MaxExpressionSize = 21000 // 21KB in bytes

	// MaxPromptChunkSize is the maximum size for each chunk when splitting prompt text (20KB)
	// This limit ensures each heredoc block stays under GitHub Actions step size limits (21KB)
	MaxPromptChunkSize = 20000 // 20KB limit for each chunk

	// MaxPromptChunks is the maximum number of chunks allowed when splitting prompt text
	// This prevents excessive step generation for extremely large prompt texts
	MaxPromptChunks = 5 // Maximum number of chunks
)
View Source
const (
	MaxBodyLength           = 65000
	MaxGitHubUsernameLength = 39
)

Constants for validation

View Source
const (
	// MaxTimeDeltaMonths is the maximum allowed months in a time delta (1 year)
	MaxTimeDeltaMonths = 12

	// MaxTimeDeltaWeeks is the maximum allowed weeks in a time delta (approximately 1 year)
	MaxTimeDeltaWeeks = 52

	// MaxTimeDeltaDays is the maximum allowed days in a time delta (1 year, non-leap)
	MaxTimeDeltaDays = 365

	// MaxTimeDeltaHours is the maximum allowed hours in a time delta (365 days * 24 hours)
	MaxTimeDeltaHours = 8760

	// MaxTimeDeltaMinutes is the maximum allowed minutes in a time delta (365 days * 24 hours * 60 minutes)
	MaxTimeDeltaMinutes = 525600
)

Time delta validation limits

Policy: Maximum stop-after time is 1 year to prevent scheduling too far in the future. These constants define the maximum allowed values for each time unit when parsing time deltas in workflow schedules. The limits ensure workflows don't schedule actions unreasonably far into the future, which could indicate configuration errors or create operational challenges.

All limits are equivalent to approximately 1 year:

  • 12 months = 1 year (exact)
  • 52 weeks = 364 days ≈ 1 year
  • 365 days = 1 year (non-leap year)
  • 8760 hours = 365 days * 24 hours
  • 525600 minutes = 365 days * 24 hours * 60 minutes
View Source
const (
	// CacheFileName is the name of the cache file in .github/aw/.
	CacheFileName = "actions-lock.json"
)
View Source
const DefaultMCPGatewayPort = constants.DefaultMCPGatewayPort

DefaultMCPGatewayPort is the default port for the MCP gateway This is now an alias to the constant defined in pkg/constants for backwards compatibility with existing code.

View Source
const (
	// GitHubOrgRepo is the organization and repository name for custom action references
	GitHubOrgRepo = "github/gh-aw"
)
View Source
const GitHubScriptGlobalsPreamble = `` /* 179-byte string literal not displayed */

GitHubScriptGlobalsPreamble is JavaScript code that exposes the github-script built-in objects (github, context, core, exec, io) on the global JavaScript object. This allows required modules to access these globals via globalThis.

View Source
const RedactedURLsLogPath = "/tmp/gh-aw/redacted-urls.log"

RedactedURLsLogPath is the path where redacted URL domains are logged during sanitization

View Source
const SafeInputsDirectory = "/opt/gh-aw/safe-inputs"

SafeInputsDirectory is the directory where safe-inputs files are generated

View Source
const (
	SafeInputsModeHTTP = "http"
)

SafeInputsMode constants define the available transport modes

View Source
const ScriptsBasePath = "/opt/gh-aw/actions"

ScriptsBasePath is the directory where JavaScript files are written at runtime This must match SetupActionDestination since files are copied there by the setup action

View Source
const SetupActionDestination = "/opt/gh-aw/actions"

SetupActionDestination is the directory where the setup action writes activation scripts

Variables

View Source
var (
	// ExpressionPattern matches GitHub Actions expressions: ${{ ... }}
	// Uses non-greedy matching to handle nested braces properly
	ExpressionPattern = regexp.MustCompile(`\$\{\{(.*?)\}\}`)

	// ExpressionPatternDotAll matches expressions with dotall mode enabled
	// The (?s) flag enables dotall mode where . matches newlines
	ExpressionPatternDotAll = regexp.MustCompile(`(?s)\$\{\{(.*?)\}\}`)
)

Core Expression Patterns

View Source
var (
	// NeedsStepsPattern matches needs.* and steps.* context patterns
	// Example: needs.build.outputs.version, steps.setup.outputs.path
	NeedsStepsPattern = regexp.MustCompile(`^(needs|steps)\.[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)*$`)

	// InputsPattern matches github.event.inputs.* patterns
	// Example: github.event.inputs.workflow_id
	InputsPattern = regexp.MustCompile(`^github\.event\.inputs\.[a-zA-Z0-9_-]+$`)

	// WorkflowCallInputsPattern matches inputs.* patterns for workflow_call
	// Example: inputs.branch_name
	WorkflowCallInputsPattern = regexp.MustCompile(`^inputs\.[a-zA-Z0-9_-]+$`)

	// AWInputsPattern matches github.aw.inputs.* patterns
	// Example: github.aw.inputs.custom_param
	AWInputsPattern = regexp.MustCompile(`^github\.aw\.inputs\.[a-zA-Z0-9_-]+$`)

	// AWInputsExpressionPattern matches full ${{ github.aw.inputs.* }} expressions
	// Used for extraction rather than validation
	AWInputsExpressionPattern = regexp.MustCompile(`\$\{\{\s*github\.aw\.inputs\.([a-zA-Z0-9_-]+)\s*\}\}`)

	// EnvPattern matches env.* patterns
	// Example: env.NODE_VERSION
	EnvPattern = regexp.MustCompile(`^env\.[a-zA-Z0-9_-]+$`)
)

Context Access Patterns

View Source
var (
	// SecretExpressionPattern matches ${{ secrets.SECRET_NAME }} expressions
	// Captures the secret name and supports optional || fallback
	SecretExpressionPattern = regexp.MustCompile(`\$\{\{\s*secrets\.([A-Z_][A-Z0-9_]*)\s*(?:\|\|.*?)?\s*\}\}`)

	// SecretsExpressionPattern validates complete secrets expression syntax
	// Supports chained || fallbacks: ${{ secrets.A || secrets.B }}
	SecretsExpressionPattern = regexp.MustCompile(`^\$\{\{\s*secrets\.[A-Za-z_][A-Za-z0-9_]*(\s*\|\|\s*secrets\.[A-Za-z_][A-Za-z0-9_]*)*\s*\}\}$`)
)

Secret Patterns

View Source
var (
	// InlineExpressionPattern matches inline ${{ ... }} expressions in templates
	InlineExpressionPattern = regexp.MustCompile(`\$\{\{[^}]+\}\}`)

	// UnsafeContextPattern matches potentially unsafe context patterns
	// These patterns may allow injection attacks in templates
	UnsafeContextPattern = regexp.MustCompile(`\$\{\{\s*(github\.event\.|steps\.[^}]+\.outputs\.|inputs\.)[^}]+\}\}`)

	// TemplateIfPattern matches {{#if condition }} template conditionals
	// Captures the condition expression (which may contain ${{ ... }})
	TemplateIfPattern = regexp.MustCompile(`\{\{#if\s+((?:\$\{\{[^\}]*\}\}|[^\}])*)\s*\}\}`)
)

Template Patterns

View Source
var (
	// ComparisonExtractionPattern extracts property accesses from comparison expressions
	// Matches patterns like "github.workflow == 'value'" and extracts "github.workflow"
	ComparisonExtractionPattern = regexp.MustCompile(`([a-zA-Z_][a-zA-Z0-9_.]*)\s*(?:==|!=|<|>|<=|>=)\s*`)

	// OrPattern matches logical OR expressions
	// Example: value1 || value2
	OrPattern = regexp.MustCompile(`^(.+?)\s*\|\|\s*(.+)$`)

	// StringLiteralPattern matches string literals in single quotes, double quotes, or backticks
	// Example: 'hello', "world", `template`
	StringLiteralPattern = regexp.MustCompile(`^'[^']*'$|^"[^"]*"$|^` + "`[^`]*`$")

	// NumberLiteralPattern matches numeric literals (integers and decimals)
	// Example: 42, -3.14, 0.5
	NumberLiteralPattern = regexp.MustCompile(`^-?\d+(\.\d+)?$`)

	// RangePattern matches numeric range patterns
	// Example: 1-10, 100-200
	RangePattern = regexp.MustCompile(`^\d+-\d+$`)
)

Comparison and Literal Patterns

View Source
var ActionFriendlyGitHubToolsets = []string{"context", "repos", "issues", "pull_requests"}

ActionFriendlyGitHubToolsets defines the default toolsets that work with GitHub Actions tokens. This excludes "users" toolset because GitHub Actions tokens do not support user operations. Use this when the workflow will run in GitHub Actions with GITHUB_TOKEN.

View Source
var ClaudeDefaultDomains = []string{
	"*.githubusercontent.com",
	"anthropic.com",
	"api.anthropic.com",
	"api.github.com",
	"api.snapcraft.io",
	"archive.ubuntu.com",
	"azure.archive.ubuntu.com",
	"cdn.playwright.dev",
	"codeload.github.com",
	"crl.geotrust.com",
	"crl.globalsign.com",
	"crl.identrust.com",
	"crl.sectigo.com",
	"crl.thawte.com",
	"crl.usertrust.com",
	"crl.verisign.com",
	"crl3.digicert.com",
	"crl4.digicert.com",
	"crls.ssl.com",
	"files.pythonhosted.org",
	"ghcr.io",
	"github-cloud.githubusercontent.com",
	"github-cloud.s3.amazonaws.com",
	"github.com",
	"host.docker.internal",
	"json-schema.org",
	"json.schemastore.org",
	"keyserver.ubuntu.com",
	"lfs.github.com",
	"objects.githubusercontent.com",
	"ocsp.digicert.com",
	"ocsp.geotrust.com",
	"ocsp.globalsign.com",
	"ocsp.identrust.com",
	"ocsp.sectigo.com",
	"ocsp.ssl.com",
	"ocsp.thawte.com",
	"ocsp.usertrust.com",
	"ocsp.verisign.com",
	"packagecloud.io",
	"packages.cloud.google.com",
	"packages.microsoft.com",
	"playwright.download.prss.microsoft.com",
	"ppa.launchpad.net",
	"pypi.org",
	"raw.githubusercontent.com",
	"registry.npmjs.org",
	"s.symcb.com",
	"s.symcd.com",
	"security.ubuntu.com",
	"sentry.io",
	"statsig.anthropic.com",
	"ts-crl.ws.symantec.com",
	"ts-ocsp.ws.symantec.com",
}

ClaudeDefaultDomains are the default domains required for Claude Code CLI authentication and operation

View Source
var CodexDefaultDomains = []string{
	"172.30.0.1",
	"api.openai.com",
	"host.docker.internal",
	"openai.com",
}

CodexDefaultDomains are the minimal default domains required for Codex CLI operation

View Source
var CopilotDefaultDomains = []string{
	"api.business.githubcopilot.com",
	"api.enterprise.githubcopilot.com",
	"api.github.com",
	"api.githubcopilot.com",
	"api.individual.githubcopilot.com",
	"github.com",
	"host.docker.internal",
	"raw.githubusercontent.com",
	"registry.npmjs.org",
	"telemetry.enterprise.githubcopilot.com",
}

CopilotDefaultDomains are the default domains required for GitHub Copilot CLI authentication and operation

View Source
var DefaultGitHubToolsets = []string{"context", "repos", "issues", "pull_requests"}

DefaultGitHubToolsets defines the toolsets that are enabled by default when toolsets are not explicitly specified in the GitHub MCP configuration. These match the documented default toolsets in github-mcp-server.instructions.md

View Source
var DefaultMarshalOptions = []yaml.EncodeOption{
	yaml.Indent(2),
	yaml.UseLiteralStyleIfMultiline(true),
}

DefaultMarshalOptions provides standard YAML formatting options used throughout gh-aw for workflow and frontmatter generation.

These options ensure consistent YAML output that follows GitHub Actions conventions and best practices:

  • yaml.Indent(2): Use 2-space indentation (GitHub Actions standard)
  • yaml.UseLiteralStyleIfMultiline(true): Use literal block scalars (|) for multiline strings to preserve formatting and readability
View Source
var DefaultScriptRegistry = NewScriptRegistry()

DefaultScriptRegistry is the global script registry used by the workflow package. Scripts are registered during package initialization via init() functions.

View Source
var GitHubToolToToolsetMap map[string]string

GitHubToolToToolsetMap maps individual GitHub MCP tools to their respective toolsets This mapping is loaded from an embedded JSON file based on the documentation in .github/instructions/github-mcp-server.instructions.md

View Source
var MirroredEnvVars = []string{

	"JAVA_HOME",
	"JAVA_HOME_8_X64",
	"JAVA_HOME_11_X64",
	"JAVA_HOME_17_X64",
	"JAVA_HOME_21_X64",
	"JAVA_HOME_25_X64",

	"ANDROID_HOME",
	"ANDROID_SDK_ROOT",
	"ANDROID_NDK",
	"ANDROID_NDK_HOME",
	"ANDROID_NDK_ROOT",
	"ANDROID_NDK_LATEST_HOME",

	"CHROMEWEBDRIVER",
	"EDGEWEBDRIVER",
	"GECKOWEBDRIVER",
	"SELENIUM_JAR_PATH",

	"CONDA",
	"VCPKG_INSTALLATION_ROOT",

	"GOPATH",

	"DOTNET_ROOT",

	"PIPX_HOME",
	"PIPX_BIN_DIR",

	"GEM_HOME",
	"GEM_PATH",

	"CARGO_HOME",
	"RUSTUP_HOME",

	"HOMEBREW_PREFIX",
	"HOMEBREW_CELLAR",
	"HOMEBREW_REPOSITORY",

	"SWIFT_PATH",

	"GOROOT",
	"NVM_DIR",

	"AZURE_EXTENSION_DIR",
}

MirroredEnvVars is the list of environment variables from the GitHub Actions Ubuntu runner that should be mirrored into the agent container.

These are grouped by category: - Java JDK homes (for multiple Java versions) - Android SDK paths - Browser WebDriver paths - Package manager paths - Go workspace path

Variables are only passed through if they exist on the host runner. Reference: scratchpad/ubuntulatest.md

View Source
var ValidationConfig = map[string]TypeValidationConfig{
	"create_issue": {
		DefaultMax: 1,
		Fields: map[string]FieldValidation{
			"title":        {Required: true, Type: "string", Sanitize: true, MaxLength: 128},
			"body":         {Required: true, Type: "string", Sanitize: true, MaxLength: MaxBodyLength},
			"labels":       {Type: "array", ItemType: "string", ItemSanitize: true, ItemMaxLength: 128},
			"parent":       {IssueOrPRNumber: true},
			"temporary_id": {Type: "string"},
			"repo":         {Type: "string", MaxLength: 256},
		},
	},
	"create_agent_session": {
		DefaultMax: 1,
		Fields: map[string]FieldValidation{
			"body": {Required: true, Type: "string", Sanitize: true, MaxLength: MaxBodyLength},
		},
	},
	"add_comment": {
		DefaultMax: 1,
		Fields: map[string]FieldValidation{
			"body":        {Required: true, Type: "string", Sanitize: true, MaxLength: MaxBodyLength},
			"item_number": {IssueOrPRNumber: true},
		},
	},
	"create_pull_request": {
		DefaultMax: 1,
		Fields: map[string]FieldValidation{
			"title":  {Required: true, Type: "string", Sanitize: true, MaxLength: 128},
			"body":   {Required: true, Type: "string", Sanitize: true, MaxLength: MaxBodyLength},
			"branch": {Required: true, Type: "string", Sanitize: true, MaxLength: 256},
			"labels": {Type: "array", ItemType: "string", ItemSanitize: true, ItemMaxLength: 128},
		},
	},
	"add_labels": {
		DefaultMax: 5,
		Fields: map[string]FieldValidation{
			"labels":      {Required: true, Type: "array", ItemType: "string", ItemSanitize: true, ItemMaxLength: 128},
			"item_number": {IssueOrPRNumber: true},
		},
	},
	"add_reviewer": {
		DefaultMax: 3,
		Fields: map[string]FieldValidation{
			"reviewers":           {Required: true, Type: "array", ItemType: "string", ItemSanitize: true, ItemMaxLength: MaxGitHubUsernameLength},
			"pull_request_number": {IssueOrPRNumber: true},
		},
	},
	"assign_milestone": {
		DefaultMax: 1,
		Fields: map[string]FieldValidation{
			"issue_number":     {IssueOrPRNumber: true},
			"milestone_number": {Required: true, PositiveInteger: true},
		},
	},
	"assign_to_agent": {
		DefaultMax:       1,
		CustomValidation: "requiresOneOf:issue_number,pull_number",
		Fields: map[string]FieldValidation{
			"issue_number": {IssueNumberOrTemporaryID: true},
			"pull_number":  {OptionalPositiveInteger: true},
			"agent":        {Type: "string", Sanitize: true, MaxLength: 128},
		},
	},
	"assign_to_user": {
		DefaultMax: 1,
		Fields: map[string]FieldValidation{
			"issue_number": {IssueOrPRNumber: true},
			"assignees":    {Type: "[]string", Sanitize: true, MaxLength: 39},
			"assignee":     {Type: "string", Sanitize: true, MaxLength: 39},
		},
	},
	"update_issue": {
		DefaultMax:       1,
		CustomValidation: "requiresOneOf:status,title,body",
		Fields: map[string]FieldValidation{
			"status":       {Type: "string", Enum: []string{"open", "closed"}},
			"title":        {Type: "string", Sanitize: true, MaxLength: 128},
			"body":         {Type: "string", Sanitize: true, MaxLength: MaxBodyLength},
			"issue_number": {IssueOrPRNumber: true},
		},
	},
	"update_pull_request": {
		DefaultMax:       1,
		CustomValidation: "requiresOneOf:title,body",
		Fields: map[string]FieldValidation{
			"title":               {Type: "string", Sanitize: true, MaxLength: 256},
			"body":                {Type: "string", Sanitize: true, MaxLength: MaxBodyLength},
			"operation":           {Type: "string", Enum: []string{"replace", "append", "prepend"}},
			"pull_request_number": {IssueOrPRNumber: true},
		},
	},
	"push_to_pull_request_branch": {
		DefaultMax: 1,
		Fields: map[string]FieldValidation{
			"branch":              {Required: true, Type: "string", Sanitize: true, MaxLength: 256},
			"message":             {Required: true, Type: "string", Sanitize: true, MaxLength: MaxBodyLength},
			"pull_request_number": {IssueOrPRNumber: true},
		},
	},
	"create_pull_request_review_comment": {
		DefaultMax:       1,
		CustomValidation: "startLineLessOrEqualLine",
		Fields: map[string]FieldValidation{
			"path":       {Required: true, Type: "string"},
			"line":       {Required: true, PositiveInteger: true},
			"body":       {Required: true, Type: "string", Sanitize: true, MaxLength: MaxBodyLength},
			"start_line": {OptionalPositiveInteger: true},
			"side":       {Type: "string", Enum: []string{"LEFT", "RIGHT"}},
		},
	},
	"submit_pull_request_review": {
		DefaultMax: 1,
		Fields: map[string]FieldValidation{
			"body":  {Type: "string", Sanitize: true, MaxLength: MaxBodyLength},
			"event": {Type: "string", Enum: []string{"APPROVE", "REQUEST_CHANGES", "COMMENT"}},
		},
	},
	"create_discussion": {
		DefaultMax: 1,
		Fields: map[string]FieldValidation{
			"title":    {Required: true, Type: "string", Sanitize: true, MaxLength: 128},
			"body":     {Required: true, Type: "string", Sanitize: true, MaxLength: MaxBodyLength},
			"category": {Type: "string", Sanitize: true, MaxLength: 128},
			"repo":     {Type: "string", MaxLength: 256},
		},
	},
	"close_discussion": {
		DefaultMax: 1,
		Fields: map[string]FieldValidation{
			"body":              {Required: true, Type: "string", Sanitize: true, MaxLength: MaxBodyLength},
			"reason":            {Type: "string", Enum: []string{"RESOLVED", "DUPLICATE", "OUTDATED", "ANSWERED"}},
			"discussion_number": {OptionalPositiveInteger: true},
		},
	},
	"close_issue": {
		DefaultMax: 1,
		Fields: map[string]FieldValidation{
			"body":         {Required: true, Type: "string", Sanitize: true, MaxLength: MaxBodyLength},
			"issue_number": {OptionalPositiveInteger: true},
		},
	},
	"close_pull_request": {
		DefaultMax: 1,
		Fields: map[string]FieldValidation{
			"body":                {Required: true, Type: "string", Sanitize: true, MaxLength: MaxBodyLength},
			"pull_request_number": {OptionalPositiveInteger: true},
		},
	},
	"missing_tool": {
		DefaultMax: 20,
		Fields: map[string]FieldValidation{
			"tool":         {Required: false, Type: "string", Sanitize: true, MaxLength: 128},
			"reason":       {Required: true, Type: "string", Sanitize: true, MaxLength: 256},
			"alternatives": {Type: "string", Sanitize: true, MaxLength: 512},
		},
	},
	"update_release": {
		DefaultMax: 1,
		Fields: map[string]FieldValidation{
			"tag":       {Type: "string", Sanitize: true, MaxLength: 256},
			"operation": {Required: true, Type: "string", Enum: []string{"replace", "append", "prepend"}},
			"body":      {Required: true, Type: "string", Sanitize: true, MaxLength: MaxBodyLength},
		},
	},
	"upload_asset": {
		DefaultMax: 10,
		Fields: map[string]FieldValidation{
			"path": {Required: true, Type: "string"},
		},
	},
	"noop": {
		DefaultMax: 1,
		Fields: map[string]FieldValidation{
			"message": {Required: true, Type: "string", Sanitize: true, MaxLength: MaxBodyLength},
		},
	},
	"create_code_scanning_alert": {
		DefaultMax: 40,
		Fields: map[string]FieldValidation{
			"file":         {Required: true, Type: "string", Sanitize: true, MaxLength: 512},
			"line":         {Required: true, PositiveInteger: true},
			"severity":     {Required: true, Type: "string", Enum: []string{"error", "warning", "info", "note"}},
			"message":      {Required: true, Type: "string", Sanitize: true, MaxLength: 2048},
			"column":       {OptionalPositiveInteger: true},
			"ruleIdSuffix": {Type: "string", Pattern: "^[a-zA-Z0-9_-]+$", PatternError: "must contain only alphanumeric characters, hyphens, and underscores", Sanitize: true, MaxLength: 128},
		},
	},
	"link_sub_issue": {
		DefaultMax:       5,
		CustomValidation: "parentAndSubDifferent",
		Fields: map[string]FieldValidation{
			"parent_issue_number": {Required: true, IssueNumberOrTemporaryID: true},
			"sub_issue_number":    {Required: true, IssueNumberOrTemporaryID: true},
		},
	},
	"update_project": {
		DefaultMax: 10,
		Fields: map[string]FieldValidation{
			"project":        {Required: true, Type: "string", Sanitize: true, MaxLength: 512, Pattern: "^https://github\\.com/(orgs|users)/[^/]+/projects/\\d+", PatternError: "must be a full GitHub project URL (e.g., https://github.com/orgs/myorg/projects/42)"},
			"content_type":   {Type: "string", Enum: []string{"issue", "pull_request", "draft_issue"}},
			"content_number": {IssueNumberOrTemporaryID: true},
			"issue":          {OptionalPositiveInteger: true},
			"pull_request":   {OptionalPositiveInteger: true},
			"draft_title":    {Type: "string", Sanitize: true, MaxLength: 256},
			"draft_body":     {Type: "string", Sanitize: true, MaxLength: MaxBodyLength},
			"fields":         {Type: "object"},
		},
	},
	"create_project": {
		DefaultMax: 1,
		Fields: map[string]FieldValidation{
			"title":      {Type: "string", Sanitize: true, MaxLength: 256},
			"owner":      {Type: "string", Sanitize: true, MaxLength: 128},
			"owner_type": {Type: "string", Enum: []string{"org", "user"}},
			"item_url":   {Type: "string", Sanitize: true, MaxLength: 512},
		},
	},
	"create_project_status_update": {
		DefaultMax: 10,
		Fields: map[string]FieldValidation{
			"project":     {Required: true, Type: "string", Sanitize: true, MaxLength: 512, Pattern: "^https://github\\.com/(orgs|users)/[^/]+/projects/\\d+", PatternError: "must be a full GitHub project URL (e.g., https://github.com/orgs/myorg/projects/42)"},
			"body":        {Required: true, Type: "string", Sanitize: true, MaxLength: 65536},
			"status":      {Type: "string", Enum: []string{"INACTIVE", "ON_TRACK", "AT_RISK", "OFF_TRACK", "COMPLETE"}},
			"start_date":  {Type: "string", Pattern: "^\\d{4}-\\d{2}-\\d{2}$", PatternError: "must be in YYYY-MM-DD format"},
			"target_date": {Type: "string", Pattern: "^\\d{4}-\\d{2}-\\d{2}$", PatternError: "must be in YYYY-MM-DD format"},
		},
	},
}

ValidationConfig contains all safe output type validation rules This is the single source of truth for validation rules

Functions

func AddDetectionSuccessCheck

func AddDetectionSuccessCheck(existingCondition string) string

AddDetectionSuccessCheck adds a check for detection job success to an existing condition This ensures safe output jobs only run when threat detection passes

func AddMCPFetchServerIfNeeded

func AddMCPFetchServerIfNeeded(tools map[string]any, engine CodingAgentEngine) (map[string]any, []string)

AddMCPFetchServerIfNeeded adds the mcp/fetch dockerized MCP server to the tools configuration if the engine doesn't have built-in web-fetch support and web-fetch tool is requested

func BreakAtParentheses

func BreakAtParentheses(expression string) []string

BreakAtParentheses attempts to break long lines at parentheses for function calls

func BreakLongExpression

func BreakLongExpression(expression string) []string

BreakLongExpression breaks a long expression into multiple lines at logical points such as after || and && operators for better readability

func BuildAllowedListEnvVar

func BuildAllowedListEnvVar(envVarName string, allowed []string) []string

BuildAllowedListEnvVar builds an allowed list environment variable line for safe-output jobs. envVarName should be the full env var name like "GH_AW_LABELS_ALLOWED". Always outputs the env var, even when empty (empty string means "allow all").

func BuildCloseJobEnvVars

func BuildCloseJobEnvVars(prefix string, config CloseJobConfig) []string

BuildCloseJobEnvVars builds common environment variables for close operations. prefix should be like "GH_AW_CLOSE_ISSUE" or "GH_AW_CLOSE_PR". Returns a slice of environment variable lines.

func BuildListJobEnvVars

func BuildListJobEnvVars(prefix string, config ListJobConfig, maxCount int) []string

BuildListJobEnvVars builds common environment variables for list-based operations. prefix should be like "GH_AW_LABELS" or "GH_AW_REVIEWERS". Returns a slice of environment variable lines.

func BuildMaxCountEnvVar

func BuildMaxCountEnvVar(envVarName string, maxCount int) []string

BuildMaxCountEnvVar builds a max count environment variable line for safe-output jobs. envVarName should be the full env var name like "GH_AW_CLOSE_ISSUE_MAX_COUNT".

func BuildRequiredCategoryEnvVar

func BuildRequiredCategoryEnvVar(envVarName string, requiredCategory string) []string

BuildRequiredCategoryEnvVar builds a required-category environment variable line for discussion safe-output jobs. envVarName should be the full env var name like "GH_AW_CLOSE_DISCUSSION_REQUIRED_CATEGORY". Returns an empty slice if requiredCategory is empty.

func BuildRequiredLabelsEnvVar

func BuildRequiredLabelsEnvVar(envVarName string, requiredLabels []string) []string

BuildRequiredLabelsEnvVar builds a required-labels environment variable line for safe-output jobs. envVarName should be the full env var name like "GH_AW_CLOSE_ISSUE_REQUIRED_LABELS". Returns an empty slice if requiredLabels is empty.

func BuildRequiredTitlePrefixEnvVar

func BuildRequiredTitlePrefixEnvVar(envVarName string, requiredTitlePrefix string) []string

BuildRequiredTitlePrefixEnvVar builds a required-title-prefix environment variable line for safe-output jobs. envVarName should be the full env var name like "GH_AW_CLOSE_ISSUE_REQUIRED_TITLE_PREFIX". Returns an empty slice if requiredTitlePrefix is empty.

func BuildTargetEnvVar

func BuildTargetEnvVar(envVarName string, target string) []string

BuildTargetEnvVar builds a target environment variable line for safe-output jobs. envVarName should be the full env var name like "GH_AW_CLOSE_ISSUE_TARGET". Returns an empty slice if target is empty.

func BundleJavaScriptFromSources

func BundleJavaScriptFromSources(mainContent string, sources map[string]string, basePath string) (string, error)

BundleJavaScriptFromSources bundles JavaScript from in-memory sources sources is a map where keys are file paths (e.g., "sanitize.cjs") and values are the content mainContent is the main JavaScript content that may contain require() calls basePath is the base directory path for resolving relative imports (e.g., "js")

DEPRECATED: Use BundleJavaScriptWithMode instead to specify runtime mode explicitly. This function defaults to RuntimeModeGitHubScript for backward compatibility.

Migration guide:

  • For GitHub Script action (inline in YAML): use BundleJavaScriptWithMode(content, sources, basePath, RuntimeModeGitHubScript)
  • For Node.js scripts (filesystem-based): use BundleJavaScriptWithMode(content, sources, basePath, RuntimeModeNodeJS)

This function will be maintained for backward compatibility but new code should use BundleJavaScriptWithMode.

func BundleJavaScriptWithMode

func BundleJavaScriptWithMode(mainContent string, sources map[string]string, basePath string, mode RuntimeMode) (string, error)

BundleJavaScriptWithMode bundles JavaScript from in-memory sources with specified runtime mode sources is a map where keys are file paths (e.g., "sanitize.cjs") and values are the content mainContent is the main JavaScript content that may contain require() calls basePath is the base directory path for resolving relative imports (e.g., "js") mode specifies the target runtime environment (GitHub script action vs Node.js)

func CleanYAMLNullValues

func CleanYAMLNullValues(yamlStr string) string

CleanYAMLNullValues removes " null" from YAML key-value pairs where the value is null.

GitHub Actions YAML treats workflow_dispatch: and workflow_dispatch: null identically, but the former is more concise and matches GitHub's documentation style. This function post-processes YAML strings to convert `: null` to `:` for better readability.

The function only replaces null values at the end of lines (after a colon and optional whitespace) to avoid incorrectly modifying string values that contain the word "null".

Parameters:

  • yamlStr: The YAML string to process

Returns:

  • The YAML string with `: null` replaced by `:`

Example:

input := "on:\n  workflow_dispatch: null\n  schedule:\n    - cron: '0 0 * * *'"
result := CleanYAMLNullValues(input)
// result: "on:\n  workflow_dispatch:\n  schedule:\n    - cron: '0 0 * * *'"

func ClearRepositoryFeaturesCache

func ClearRepositoryFeaturesCache()

ClearRepositoryFeaturesCache clears the repository features cache This is useful for testing or when repository settings might have changed

func CollectSecretReferences

func CollectSecretReferences(yamlContent string) []string

CollectSecretReferences extracts all secret references from the workflow YAML This scans for patterns like ${{ secrets.SECRET_NAME }} or secrets.SECRET_NAME

func ContainsCheckout

func ContainsCheckout(customSteps string) bool

ContainsCheckout returns true if the given custom steps contain an actions/checkout step

func ConvertStepToYAML

func ConvertStepToYAML(stepMap map[string]any) (string, error)

ConvertStepToYAML converts a step map to YAML string with proper indentation This is a shared utility function used by all engines and the compiler

func ConvertToFloat

func ConvertToFloat(val any) float64

ConvertToFloat safely converts any to float64

func ConvertToInt

func ConvertToInt(val any) int

ConvertToInt safely converts any to int

func EngineHasValidateSecretStep

func EngineHasValidateSecretStep(engine CodingAgentEngine, data *WorkflowData) bool

EngineHasValidateSecretStep checks if the engine's installation steps include the validate-secret step. This is used to determine whether the secret_verification_result job output should be added.

The validate-secret step is only added by engines that include it in GetInstallationSteps():

  • Copilot engine: Adds step when GetRequiredSecretNames returns non-empty
  • Claude engine: Adds step when GetRequiredSecretNames returns non-empty
  • Codex engine: Adds step when GetRequiredSecretNames returns non-empty
  • Custom engine: Never adds this step (returns empty from GetInstallationSteps)

Implementation Note: This uses simple string matching which is acceptable because:

  • Installation steps are generated by our code, not user input
  • The "id: validate-secret" format is controlled by GenerateMultiSecretValidationStep()
  • GitHubActionStep is already a string slice, not structured YAML

Parameters:

  • engine: The agentic engine to check
  • data: The workflow data (needed for GetInstallationSteps)

Returns:

  • bool: true if the engine includes the validate-secret step, false otherwise

func EnhanceError

func EnhanceError(err error, context, suggestion string) error

EnhanceError adds context to an existing error

func ExecGH

func ExecGH(args ...string) *exec.Cmd

ExecGH wraps gh CLI calls and ensures proper token configuration. It uses go-gh/v2 to execute gh commands when GH_TOKEN or GITHUB_TOKEN is available, otherwise falls back to direct exec.Command for backward compatibility.

Usage:

cmd := ExecGH("api", "/user")
output, err := cmd.Output()

func ExecGHContext

func ExecGHContext(ctx context.Context, args ...string) *exec.Cmd

ExecGHContext wraps gh CLI calls with context support and ensures proper token configuration. Similar to ExecGH but accepts a context for cancellation and timeout support.

Usage:

cmd := ExecGHContext(ctx, "api", "/user")
output, err := cmd.Output()

func ExecGHWithOutput

func ExecGHWithOutput(args ...string) (stdout, stderr bytes.Buffer, err error)

ExecGHWithOutput executes a gh CLI command using go-gh/v2 and returns stdout, stderr, and error. This is a convenience wrapper that directly uses go-gh/v2's Exec function.

Usage:

stdout, stderr, err := ExecGHWithOutput("api", "/user")

func ExtractAgentIdentifier

func ExtractAgentIdentifier(agentFile string) string

ExtractAgentIdentifier extracts the agent identifier (filename without extension) from an agent file path. This is used by the Copilot CLI which expects agent identifiers, not full paths.

Parameters:

  • agentFile: The relative path to the agent file (e.g., ".github/agents/test-agent.md" or ".github/agents/test-agent.agent.md")

Returns:

  • string: The agent identifier (e.g., "test-agent")

Example:

identifier := ExtractAgentIdentifier(".github/agents/my-agent.md")
// Returns: "my-agent"

identifier := ExtractAgentIdentifier(".github/agents/my-agent.agent.md")
// Returns: "my-agent"

func ExtractEnvExpressionsFromValue added in v0.43.6

func ExtractEnvExpressionsFromValue(value string) map[string]string

ExtractEnvExpressionsFromValue extracts all GitHub Actions env expressions from a string value Returns a map of environment variable names to their full env expressions Examples:

  • "${{ env.SENTRY_HOST }}" -> {"SENTRY_HOST": "${{ env.SENTRY_HOST }}"}
  • "${{ env.DD_SITE || 'default' }}" -> {"DD_SITE": "${{ env.DD_SITE || 'default' }}"}

func ExtractFirstMatch

func ExtractFirstMatch(text, pattern string) string

ExtractFirstMatch extracts the first regex match from a string Note: This function compiles the regex on each call. For frequently-used patterns, consider pre-compiling at package level or caching the compiled regex.

func ExtractIntField

func ExtractIntField(frontmatter map[string]any, key string) int

ExtractIntField is a convenience wrapper for extracting integer fields. Returns 0 if the key doesn't exist or cannot be converted.

func ExtractJSONCost

func ExtractJSONCost(data map[string]any) float64

ExtractJSONCost extracts cost information from JSON data

func ExtractJSONTokenUsage

func ExtractJSONTokenUsage(data map[string]any) int

ExtractJSONTokenUsage extracts token usage from JSON data

func ExtractMCPServer

func ExtractMCPServer(toolName string) string

ExtractMCPServer extracts the MCP server name from a tool name

func ExtractMapField

func ExtractMapField(frontmatter map[string]any, key string) map[string]any

ExtractMapField is a convenience wrapper for extracting map[string]any fields from frontmatter. This maintains backward compatibility with existing extraction patterns while preserving original types (avoiding JSON conversion which would convert all numbers to float64).

Returns an empty map if the key doesn't exist (for backward compatibility).

func ExtractSecretName

func ExtractSecretName(value string) string

ExtractSecretName extracts just the secret name from a GitHub Actions expression Examples:

  • "${{ secrets.DD_API_KEY }}" -> "DD_API_KEY"
  • "${{ secrets.DD_SITE || 'datadoghq.com' }}" -> "DD_SITE"
  • "plain value" -> ""

func ExtractSecretsFromMap

func ExtractSecretsFromMap(values map[string]string) map[string]string

ExtractSecretsFromMap extracts all secrets from a map of string values Returns a map of environment variable names to their full secret expressions Example:

Input: {"DD_API_KEY": "${{ secrets.DD_API_KEY }}", "DD_SITE": "${{ secrets.DD_SITE || 'default' }}"}
Output: {"DD_API_KEY": "${{ secrets.DD_API_KEY }}", "DD_SITE": "${{ secrets.DD_SITE || 'default' }}"}

func ExtractSecretsFromValue

func ExtractSecretsFromValue(value string) map[string]string

ExtractSecretsFromValue extracts all GitHub Actions secret expressions from a string value Returns a map of environment variable names to their full secret expressions Examples:

  • "${{ secrets.DD_API_KEY }}" -> {"DD_API_KEY": "${{ secrets.DD_API_KEY }}"}
  • "${{ secrets.DD_SITE || 'datadoghq.com' }}" -> {"DD_SITE": "${{ secrets.DD_SITE || 'datadoghq.com' }}"}
  • "Bearer ${{ secrets.TOKEN }}" -> {"TOKEN": "${{ secrets.TOKEN }}"}

func ExtractStopTimeFromLockFile

func ExtractStopTimeFromLockFile(lockFilePath string) string

ExtractStopTimeFromLockFile extracts the STOP_TIME value from a compiled workflow lock file

func ExtractStringField

func ExtractStringField(frontmatter map[string]any, key string) string

ExtractStringField is a convenience wrapper for extracting string fields. Returns empty string if the key doesn't exist or cannot be converted.

func FilterEnvForSecrets

func FilterEnvForSecrets(env map[string]string, allowedSecrets []string) map[string]string

FilterEnvForSecrets filters environment variables to only include allowed secrets This is a security measure to ensure that only necessary secrets are passed to the execution step

Parameters:

  • env: Map of all environment variables
  • allowedSecrets: List of secret names that are allowed to be passed

Returns:

  • map[string]string: Filtered environment variables with only allowed secrets

func FinalizeToolCallsAndSequence

func FinalizeToolCallsAndSequence(
	metrics *LogMetrics,
	toolCallMap map[string]*ToolCallInfo,
	currentSequence []string,
)

FinalizeToolCallsAndSequence completes the tool call and sequence finalization. Use this function when the engine extracts token usage and turns from structured result entries, rather than accumulating them during line-by-line log parsing. This is a lighter version of FinalizeToolMetrics for engines that do not need to finalize token usage and turns here.

func FinalizeToolMetrics

func FinalizeToolMetrics(opts FinalizeToolMetricsOptions)

FinalizeToolMetrics completes the metric collection process by finalizing sequences, converting tool call maps to sorted slices, and optionally counting errors using patterns. This function is called by engine-specific ParseLogMetrics implementations to avoid code duplication.

func FindJavaScriptDependencies

func FindJavaScriptDependencies(mainContent string, sources map[string]string, basePath string) (map[string]bool, error)

FindJavaScriptDependencies analyzes a JavaScript file and recursively finds all its dependencies without actually bundling the code. Returns a map of file paths that are required.

Parameters:

  • mainContent: The JavaScript content to analyze
  • sources: Map of file paths to their content
  • basePath: Base directory path for resolving relative imports (e.g., "js")

Returns:

  • Map of file paths (relative to basePath) that are dependencies
  • Error if a required file is not found in sources

func FormatAggregatedError

func FormatAggregatedError(err error, category string) error

FormatAggregatedError formats aggregated errors with a summary header Returns a formatted error with count and categorization if multiple errors exist

func FormatJavaScriptForYAML

func FormatJavaScriptForYAML(script string) []string

FormatJavaScriptForYAML formats a JavaScript script with proper indentation for embedding in YAML

func FormatSecurityFindings added in v0.43.12

func FormatSecurityFindings(findings []SecurityFinding) string

FormatSecurityFindings formats a list of findings into a human-readable error message

func FormatStepWithCommandAndEnv

func FormatStepWithCommandAndEnv(stepLines []string, command string, env map[string]string) []string

RenderCustomMCPToolConfigHandler is a function type that engines must provide to render their specific MCP config FormatStepWithCommandAndEnv formats a GitHub Actions step with command and environment variables. This shared function extracts the common pattern used by Copilot and Codex engines.

Parameters:

  • stepLines: Existing step lines to append to (e.g., name, id, comments, timeout)
  • command: The command to execute (may contain multiple lines)
  • env: Map of environment variables to include in the step

Returns:

  • []string: Complete step lines including run command and env section

func FormatValidationMessage

func FormatValidationMessage(result *PermissionsValidationResult, strict bool) string

FormatValidationMessage formats the validation result into a human-readable message

func GenerateConcurrencyConfig

func GenerateConcurrencyConfig(workflowData *WorkflowData, isCommandTrigger bool) string

GenerateConcurrencyConfig generates the concurrency configuration for a workflow based on its trigger types and characteristics.

func GenerateHeredocDelimiter added in v0.43.6

func GenerateHeredocDelimiter(name string) string

GenerateHeredocDelimiter creates a standardized heredoc delimiter with the GH_AW prefix. All heredoc delimiters in compiled lock.yml files should use this format for consistency.

The function generates delimiters in the format: GH_AW_<NAME>_EOF

Parameters:

  • name: A descriptive identifier for the heredoc content (e.g., "PROMPT", "MCP_CONFIG", "TOOLS_JSON") The name should use SCREAMING_SNAKE_CASE without the _EOF suffix.

Returns a delimiter string in the format "GH_AW_<NAME>_EOF"

Example:

GenerateHeredocDelimiter("PROMPT")          // returns "GH_AW_PROMPT_EOF"
GenerateHeredocDelimiter("MCP_CONFIG")      // returns "GH_AW_MCP_CONFIG_EOF"
GenerateHeredocDelimiter("TOOLS_JSON")      // returns "GH_AW_TOOLS_JSON_EOF"
GenerateHeredocDelimiter("SRT_CONFIG")      // returns "GH_AW_SRT_CONFIG_EOF"
GenerateHeredocDelimiter("FILE_123ABC")     // returns "GH_AW_FILE_123ABC_EOF"

Usage in heredoc generation:

delimiter := GenerateHeredocDelimiter("PROMPT")
yaml.WriteString(fmt.Sprintf("cat << '%s' >> \"$GH_AW_PROMPT\"\n", delimiter))
yaml.WriteString("content here\n")
yaml.WriteString(delimiter + "\n")

func GenerateJobConcurrencyConfig

func GenerateJobConcurrencyConfig(workflowData *WorkflowData) string

GenerateJobConcurrencyConfig generates the agent concurrency configuration for the agent job based on engine.concurrency field

func GenerateMaintenanceWorkflow

func GenerateMaintenanceWorkflow(workflowDataList []*WorkflowData, workflowDir string, version string, actionMode ActionMode, verbose bool) error

GenerateMaintenanceWorkflow generates the agentics-maintenance.yml workflow if any workflows use the expires field for discussions or issues

func GenerateRequireScript

func GenerateRequireScript(mainScriptPath string) string

GenerateRequireScript generates the JavaScript code that requires the main script from the filesystem instead of inlining the bundled code.

For GitHub Script mode, the script is wrapped in an async IIFE to support top-level await patterns used in the JavaScript files (e.g., `await main();`). The globals (github, context, core, exec, io) are automatically available in the GitHub Script execution context.

func GenerateSafeInputGoToolScriptForInspector

func GenerateSafeInputGoToolScriptForInspector(toolConfig *SafeInputToolConfig) string

GenerateSafeInputGoToolScriptForInspector generates a Go script tool handler This is a public wrapper for use by the CLI inspector command

func GenerateSafeInputJavaScriptToolScriptForInspector

func GenerateSafeInputJavaScriptToolScriptForInspector(toolConfig *SafeInputToolConfig) string

GenerateSafeInputJavaScriptToolScriptForInspector generates a JavaScript tool handler script This is a public wrapper for use by the CLI inspector command

func GenerateSafeInputPythonToolScriptForInspector

func GenerateSafeInputPythonToolScriptForInspector(toolConfig *SafeInputToolConfig) string

GenerateSafeInputPythonToolScriptForInspector generates a Python script tool handler This is a public wrapper for use by the CLI inspector command

func GenerateSafeInputShellToolScriptForInspector

func GenerateSafeInputShellToolScriptForInspector(toolConfig *SafeInputToolConfig) string

GenerateSafeInputShellToolScriptForInspector generates a shell script tool handler This is a public wrapper for use by the CLI inspector command

func GenerateSafeInputsMCPServerScriptForInspector

func GenerateSafeInputsMCPServerScriptForInspector(safeInputs *SafeInputsConfig) string

GenerateSafeInputsMCPServerScriptForInspector generates the MCP server entry point script This is a public wrapper for use by the CLI inspector command

func GenerateSafeInputsToolsConfigForInspector

func GenerateSafeInputsToolsConfigForInspector(safeInputs *SafeInputsConfig) string

GenerateSafeInputsToolsConfigForInspector generates the tools.json configuration for the safe-inputs MCP server This is a public wrapper for use by the CLI inspector command

func GenerateWorkflowHeader

func GenerateWorkflowHeader(sourceFile string, generatedBy string, customInstructions string) string

GenerateWorkflowHeader generates the standard header comment for generated workflow files. It includes the ASCII art logo and instructions on how to regenerate the file.

Parameters:

  • sourceFile: The source file path (e.g., ".md" file) that generated this workflow, or empty if not applicable
  • generatedBy: Description of what generated this file (e.g., "gh-aw", "pkg/workflow/maintenance_workflow.go")
  • customInstructions: Optional additional instructions to display after the standard regeneration instructions

func GenerateWriteScriptsStep

func GenerateWriteScriptsStep(files []ScriptFile) []string

GenerateWriteScriptsStep generates the YAML for a step that writes all collected JavaScript files to /opt/gh-aw/scripts/. This step should be added once at the beginning of the safe_outputs job.

The generated step uses a heredoc to write each file efficiently.

func GetActionPin

func GetActionPin(actionRepo string) string

GetActionPin returns the pinned action reference for a given action repository When multiple versions exist for the same repo, it returns the latest version by semver If no pin is found, it returns an empty string The returned reference includes a comment with the version tag (e.g., "repo@sha # v1")

func GetActionPinWithData

func GetActionPinWithData(actionRepo, version string, data *WorkflowData) (string, error)

GetActionPinWithData returns the pinned action reference for a given action@version It tries dynamic resolution first, then falls back to hardcoded pins If resolution fails, emits a warning and returns empty string (in both strict and non-strict modes) The returned reference includes a comment with the version tag (e.g., "repo@sha # v1")

func GetActualGitHubEventName

func GetActualGitHubEventName(identifier string) string

GetActualGitHubEventName returns the actual GitHub Actions event name for a given identifier This maps pull_request_comment to issue_comment since that's the actual event in GitHub Actions

func GetAllScriptFilenames

func GetAllScriptFilenames() []string

GetAllScriptFilenames returns a sorted list of all .cjs filenames from the JavaScript sources. This is used by the build system to discover which files need to be embedded in custom actions. The returned list includes all .cjs files found in pkg/workflow/js/, including dependencies.

func GetAllowedDomains

func GetAllowedDomains(network *NetworkPermissions) []string

GetAllowedDomains returns the allowed domains from network permissions.

Behavior based on network permissions configuration:

  1. No network permissions (nil): Returns default ecosystem domains for backwards compatibility.

  2. Allowed list with "defaults" only: network: defaults OR network: { allowed: [defaults] } Returns default ecosystem domains.

  3. Allowed list with multiple ecosystems: network: allowed: - defaults - github Processes the Allowed list, expanding all ecosystem identifiers and merging them.

  4. Allowed list with custom domains: network: allowed: - example.com - python Processes the Allowed list, expanding ecosystem identifiers.

  5. Empty Allowed list (deny-all): network: {} OR network: { allowed: [] } Returns empty slice (no network access).

The returned list is sorted and deduplicated.

Supported ecosystem identifiers:

  • "defaults": basic infrastructure (certs, JSON schema, Ubuntu, package mirrors)
  • "containers": container registries (Docker, GHCR, etc.)
  • "dotnet": .NET and NuGet ecosystem
  • "dart": Dart/Flutter ecosystem
  • "github": GitHub domains (*.githubusercontent.com, github.githubassets.com, etc.)
  • "go": Go ecosystem
  • "terraform": HashiCorp/Terraform
  • "haskell": Haskell ecosystem
  • "java": Java/Maven/Gradle
  • "linux-distros": Linux distribution package repositories
  • "node": Node.js/NPM/Yarn
  • "perl": Perl/CPAN
  • "php": PHP/Composer
  • "playwright": Playwright testing framework
  • "python": Python/PyPI/Conda
  • "ruby": Ruby/RubyGems
  • "rust": Rust/Cargo/Crates
  • "swift": Swift/CocoaPods
  • "github-actions": GitHub Actions blob storage domains

func GetBlockedDomains

func GetBlockedDomains(network *NetworkPermissions) []string

GetBlockedDomains returns the blocked domains from network permissions Returns empty slice if no network permissions configured or no domains blocked The returned list is sorted and deduplicated Supports ecosystem identifiers (same as allowed domains)

func GetClaudeAllowedDomains

func GetClaudeAllowedDomains(network *NetworkPermissions) string

GetClaudeAllowedDomains merges Claude default domains with NetworkPermissions allowed domains Returns a deduplicated, sorted, comma-separated string suitable for AWF's --allow-domains flag

func GetClaudeAllowedDomainsWithSafeInputs

func GetClaudeAllowedDomainsWithSafeInputs(network *NetworkPermissions, hasSafeInputs bool) string

GetClaudeAllowedDomainsWithSafeInputs merges Claude default domains with NetworkPermissions allowed domains Returns a deduplicated, sorted, comma-separated string suitable for AWF's --allow-domains flag The hasSafeInputs parameter is maintained for backward compatibility but is no longer used since host.docker.internal is now in ClaudeDefaultDomains

func GetClaudeAllowedDomainsWithTools

func GetClaudeAllowedDomainsWithTools(network *NetworkPermissions, tools map[string]any) string

GetClaudeAllowedDomainsWithTools merges Claude default domains with NetworkPermissions allowed domains and HTTP MCP server domains Returns a deduplicated, sorted, comma-separated string suitable for AWF's --allow-domains flag

func GetClaudeAllowedDomainsWithToolsAndRuntimes

func GetClaudeAllowedDomainsWithToolsAndRuntimes(network *NetworkPermissions, tools map[string]any, runtimes map[string]any) string

GetClaudeAllowedDomainsWithToolsAndRuntimes merges Claude default domains with NetworkPermissions, HTTP MCP server domains, and runtime ecosystem domains Returns a deduplicated, sorted, comma-separated string suitable for AWF's --allow-domains flag

func GetCodexAllowedDomains

func GetCodexAllowedDomains(network *NetworkPermissions) string

GetCodexAllowedDomains merges Codex default domains with NetworkPermissions allowed domains Returns a deduplicated, sorted, comma-separated string suitable for AWF's --allow-domains flag

func GetCodexAllowedDomainsWithTools

func GetCodexAllowedDomainsWithTools(network *NetworkPermissions, tools map[string]any) string

GetCodexAllowedDomainsWithTools merges Codex default domains with NetworkPermissions allowed domains and HTTP MCP server domains Returns a deduplicated, sorted, comma-separated string suitable for AWF's --allow-domains flag

func GetCodexAllowedDomainsWithToolsAndRuntimes

func GetCodexAllowedDomainsWithToolsAndRuntimes(network *NetworkPermissions, tools map[string]any, runtimes map[string]any) string

GetCodexAllowedDomainsWithToolsAndRuntimes merges Codex default domains with NetworkPermissions, HTTP MCP server domains, and runtime ecosystem domains Returns a deduplicated, sorted, comma-separated string suitable for AWF's --allow-domains flag

func GetCommentEventNames

func GetCommentEventNames(mappings []CommentEventMapping) []string

GetCommentEventNames returns just the event names from a list of mappings

func GetCopilotAgentPlaywrightTools

func GetCopilotAgentPlaywrightTools() []any

GetCopilotAgentPlaywrightTools returns the list of playwright tools available in the copilot agent This matches the tools available in the copilot agent MCP server configuration This is a shared function used by all engines for consistent playwright tool configuration

func GetCopilotAllowedDomains

func GetCopilotAllowedDomains(network *NetworkPermissions) string

GetCopilotAllowedDomains merges Copilot default domains with NetworkPermissions allowed domains Returns a deduplicated, sorted, comma-separated string suitable for AWF's --allow-domains flag

func GetCopilotAllowedDomainsWithSafeInputs

func GetCopilotAllowedDomainsWithSafeInputs(network *NetworkPermissions, hasSafeInputs bool) string

GetCopilotAllowedDomainsWithSafeInputs merges Copilot default domains with NetworkPermissions allowed domains Returns a deduplicated, sorted, comma-separated string suitable for AWF's --allow-domains flag The hasSafeInputs parameter is maintained for backward compatibility but is no longer used since host.docker.internal is now in CopilotDefaultDomains

func GetCopilotAllowedDomainsWithTools

func GetCopilotAllowedDomainsWithTools(network *NetworkPermissions, tools map[string]any) string

GetCopilotAllowedDomainsWithTools merges Copilot default domains with NetworkPermissions allowed domains and HTTP MCP server domains Returns a deduplicated, sorted, comma-separated string suitable for AWF's --allow-domains flag

func GetCopilotAllowedDomainsWithToolsAndRuntimes

func GetCopilotAllowedDomainsWithToolsAndRuntimes(network *NetworkPermissions, tools map[string]any, runtimes map[string]any) string

GetCopilotAllowedDomainsWithToolsAndRuntimes merges Copilot default domains with NetworkPermissions, HTTP MCP server domains, and runtime ecosystem domains Returns a deduplicated, sorted, comma-separated string suitable for AWF's --allow-domains flag

func GetCurrentGitTag

func GetCurrentGitTag() string

GetCurrentGitTag returns the current git tag if available. Returns empty string if not on a tag.

func GetDefaultMaxForType

func GetDefaultMaxForType(typeName string) int

GetDefaultMaxForType returns the default max for a type

func GetDefaultVersion

func GetDefaultVersion() string

GetDefaultVersion returns the default version

func GetDomainEcosystem

func GetDomainEcosystem(domain string) string

GetDomainEcosystem returns the ecosystem identifier for a given domain, or empty string if not found

func GetEnabledSafeOutputToolNames

func GetEnabledSafeOutputToolNames(safeOutputs *SafeOutputsConfig) []string

GetEnabledSafeOutputToolNames returns a list of enabled safe output tool names. NOTE: Tool names should NOT be included in agent prompts. The agent should query the MCP server to discover available tools. This function is used for generating the tools.json file that the MCP server provides, and for diagnostic logging.

func GetHostedToolcachePathSetup

func GetHostedToolcachePathSetup() string

GetHostedToolcachePathSetup returns a shell command that adds all runtime binaries from /opt/hostedtoolcache to PATH. This includes Node.js, Python, Go, Ruby, and other runtimes installed via actions/setup-* steps.

The hostedtoolcache directory structure is: /opt/hostedtoolcache/<tool>/<version>/<arch>/bin This function generates a command that finds all bin directories and adds them to PATH.

IMPORTANT: The command uses GH_AW_TOOL_BINS (computed by GetToolBinsSetup) which contains the specific tool paths from environment variables like GOROOT, JAVA_HOME, etc. These paths are computed on the RUNNER side and passed to the container as a literal value via --env, avoiding shell injection risks from variable expansion inside the container.

This ensures that the version configured by actions/setup-* takes precedence over other versions that may exist in hostedtoolcache. Without this, the generic `find` command returns directories in alphabetical order, causing older versions (e.g., Go 1.22.12) to shadow newer ones (e.g., Go 1.25.6) because "1.22" < "1.25" alphabetically.

This is used by all engine implementations (Copilot, Claude, Codex) to ensure consistent access to runtime tools inside the agent container.

Returns:

  • string: A shell command that sets up PATH with all hostedtoolcache binaries

Example output:

export PATH="$GH_AW_TOOL_BINS$(find /opt/hostedtoolcache -maxdepth 4 -type d -name bin 2>/dev/null | tr '\n' ':')$PATH"

func GetInlinedScriptForFileMode

func GetInlinedScriptForFileMode(scriptName string) (string, error)

GetInlinedScriptForFileMode gets the main script content and transforms it for inlining in the github-script action while using file mode for dependencies.

This function: 1. Adds a preamble to expose github-script globals (github, context, core, exec, io) on globalThis 2. Gets the script content from the registry 3. Transforms relative require() calls to absolute paths (e.g., './helper.cjs' -> '/opt/gh-aw/scripts/helper.cjs') 4. Patches top-level await patterns to work in the execution context

This is different from GenerateRequireScript which just generates a require() call. Inlining the main script is necessary because: - require() runs in a separate module context without the GitHub Script globals - The main script needs access to github, context, core, etc. in its top-level scope

Dependencies are still loaded from files using require() and can access the globals via globalThis (e.g., globalThis.github, globalThis.core).

func GetJavaScriptSources

func GetJavaScriptSources() map[string]string

func GetLogParserBootstrap

func GetLogParserBootstrap() string

func GetLogParserScript

func GetLogParserScript(name string) string

func GetMCPHTTPTransportScript

func GetMCPHTTPTransportScript() string

func GetMCPHandlerPythonScript

func GetMCPHandlerPythonScript() string

func GetMCPHandlerShellScript

func GetMCPHandlerShellScript() string

func GetMCPLoggerScript

func GetMCPLoggerScript() string

func GetMCPServerCoreScript

func GetMCPServerCoreScript() string

func GetMirroredEnvArgs

func GetMirroredEnvArgs() []string

GetMirroredEnvArgs returns the AWF command-line arguments for mirroring environment variables from the runner into the agent container.

AWF uses the --env flag to pass environment variables in KEY=VALUE format. The output uses shell variable expansion syntax (e.g., JAVA_HOME=${JAVA_HOME}) so that the actual value is resolved at runtime from the host environment.

Example output: ["--env", "JAVA_HOME=${JAVA_HOME}", "--env", "ANDROID_HOME=${ANDROID_HOME}", ...]

This function always returns the same list of environment variables to mirror. Variables that don't exist on the host will expand to empty strings at runtime.

func GetMirroredEnvVarsList

func GetMirroredEnvVarsList() []string

GetMirroredEnvVarsList returns the list of environment variables that are mirrored from the runner to the agent container.

This is useful for documentation and debugging purposes.

func GetNpmBinPathSetup added in v0.42.0

func GetNpmBinPathSetup() string

GetNpmBinPathSetup returns a simple shell command that adds hostedtoolcache bin directories to PATH. This is specifically for npm-installed CLIs (like Claude and Codex) that need to find their binaries installed via `npm install -g`.

Unlike GetHostedToolcachePathSetup(), this does NOT use GH_AW_TOOL_BINS because AWF's native chroot mode already handles tool-specific paths (GOROOT, JAVA_HOME, etc.) via AWF_HOST_PATH and the entrypoint.sh script. This function only adds the generic hostedtoolcache bin directories for npm packages.

Returns:

  • string: A shell command that exports PATH with hostedtoolcache bin directories prepended

func GetReadBufferScript

func GetReadBufferScript() string

func GetSafeInputsBootstrapScript

func GetSafeInputsBootstrapScript() string

func GetSafeInputsConfigLoaderScript

func GetSafeInputsConfigLoaderScript() string

func GetSafeInputsMCPServerHTTPScript

func GetSafeInputsMCPServerHTTPScript() string

func GetSafeInputsMCPServerScript

func GetSafeInputsMCPServerScript() string

func GetSafeInputsToolFactoryScript

func GetSafeInputsToolFactoryScript() string

func GetSafeInputsValidationScript

func GetSafeInputsValidationScript() string

func GetSafeOutputsAppendScript

func GetSafeOutputsAppendScript() string

func GetSafeOutputsBootstrapScript

func GetSafeOutputsBootstrapScript() string

func GetSafeOutputsConfigScript

func GetSafeOutputsConfigScript() string

func GetSafeOutputsHandlersScript

func GetSafeOutputsHandlersScript() string

func GetSafeOutputsMCPServerScript

func GetSafeOutputsMCPServerScript() string

func GetSafeOutputsToolsJSON

func GetSafeOutputsToolsJSON() string

func GetSafeOutputsToolsLoaderScript

func GetSafeOutputsToolsLoaderScript() string

func GetSanitizedPATHExport

func GetSanitizedPATHExport(rawPath string) string

GetSanitizedPATHExport returns a shell command that sets PATH to the given value with sanitization to remove security risks from malformed PATH entries.

The sanitization removes:

  • Leading colons (e.g., ":/usr/bin" -> "/usr/bin")
  • Trailing colons (e.g., "/usr/bin:" -> "/usr/bin")
  • Empty elements (e.g., "/a::/b" -> "/a:/b", multiple colons collapsed to one)

Empty PATH elements are a security risk because they cause the current directory to be searched for executables, which could allow malicious code execution.

The sanitization logic is implemented in actions/setup/sh/sanitize_path.sh and is sourced at runtime from /opt/gh-aw/actions/sanitize_path.sh.

Parameters:

  • rawPath: The unsanitized PATH value (may contain shell expansions like $PATH)

Returns:

  • string: A shell command that sources the sanitize script to export the sanitized PATH

Example:

GetSanitizedPATHExport("$GH_AW_TOOL_BINS$PATH")
// Returns: source /opt/gh-aw/actions/sanitize_path.sh "$GH_AW_TOOL_BINS$PATH"

func GetScript

func GetScript(name string) string

GetScript retrieves a bundled script from the default registry. This is a convenience function equivalent to DefaultScriptRegistry.Get(name).

DEPRECATED: Use GetScriptWithMode to specify the expected runtime mode.

func GetScriptWithMode

func GetScriptWithMode(name string, mode RuntimeMode) string

GetScriptWithMode retrieves a bundled script from the default registry with mode verification. This is a convenience function equivalent to DefaultScriptRegistry.GetWithMode(name, mode).

func GetToolBinsEnvArg

func GetToolBinsEnvArg() []string

GetToolBinsEnvArg returns the AWF --env argument for passing GH_AW_TOOL_BINS to the container. This should be used after GetToolBinsSetup() has been run to compute the value.

Returns:

  • []string: AWF arguments ["--env", "GH_AW_TOOL_BINS=$GH_AW_TOOL_BINS"]

func GetToolBinsSetup

func GetToolBinsSetup() string

GetToolBinsSetup returns a shell command that computes the GH_AW_TOOL_BINS environment variable from specific tool paths (GOROOT, JAVA_HOME, etc.).

This command should be run on the RUNNER side before invoking AWF, and the resulting GH_AW_TOOL_BINS should be passed to the container via --env. This ensures the paths are computed where they are trusted, avoiding shell injection risks.

The computed paths are prepended to PATH (via GetHostedToolcachePathSetup) before the generic find results, ensuring versions set by actions/setup-* take precedence over alphabetically-earlier versions in hostedtoolcache.

Returns:

  • string: A shell command that sets GH_AW_TOOL_BINS

Example output when GOROOT=/opt/hostedtoolcache/go/1.25.6/x64 and JAVA_HOME=/opt/hostedtoolcache/Java/17.0.0/x64:

GH_AW_TOOL_BINS="/opt/hostedtoolcache/go/1.25.6/x64/bin:/opt/hostedtoolcache/Java/17.0.0/x64/bin:"

func GetValidationConfigJSON

func GetValidationConfigJSON(enabledTypes []string) (string, error)

GetValidationConfigJSON returns the validation configuration as indented JSON If enabledTypes is empty or nil, returns all validation configs If enabledTypes is provided, returns only configs for the specified types

func GetVersion

func GetVersion() string

GetVersion returns the current compiler version.

func GetWorkflowIDFromPath

func GetWorkflowIDFromPath(markdownPath string) string

GetWorkflowIDFromPath extracts the workflow ID from a markdown file path. The workflow ID is the filename without the .md extension. Example: "/path/to/ai-moderator.md" -> "ai-moderator"

func HandleCustomMCPToolInSwitch

func HandleCustomMCPToolInSwitch(
	yaml *strings.Builder,
	toolName string,
	tools map[string]any,
	isLast bool,
	renderFunc RenderCustomMCPToolConfigHandler,
) bool

HandleCustomMCPToolInSwitch processes custom MCP tools in the default case of a switch statement. This shared function extracts the common pattern used across all workflow engines.

Parameters:

  • yaml: The string builder for YAML output
  • toolName: The name of the tool being processed
  • tools: The tools map containing tool configurations (supports both expanded and non-expanded tools)
  • isLast: Whether this is the last tool in the list
  • renderFunc: Engine-specific function to render the MCP configuration

Returns:

  • bool: true if a custom MCP tool was handled, false otherwise

func HasMCPServers

func HasMCPServers(workflowData *WorkflowData) bool

HasMCPServers checks if the workflow has any MCP servers configured

func HasSafeInputs

func HasSafeInputs(safeInputs *SafeInputsConfig) bool

HasSafeInputs checks if safe-inputs are configured

func HasSafeJobsEnabled

func HasSafeJobsEnabled(safeJobs map[string]*SafeJobConfig) bool

HasSafeJobsEnabled checks if any safe-jobs are enabled at the top level

func HasSafeOutputsEnabled

func HasSafeOutputsEnabled(safeOutputs *SafeOutputsConfig) bool

HasSafeOutputsEnabled checks if any safe-outputs are enabled

func IsRelease

func IsRelease() bool

IsRelease returns whether this binary was built as a release.

func IsReleasedVersion

func IsReleasedVersion(version string) bool

IsReleasedVersion checks if a version string represents a released build. It relies on the isReleaseBuild flag set at build time via -X linker flag.

func IsSafeInputsEnabled

func IsSafeInputsEnabled(safeInputs *SafeInputsConfig, workflowData *WorkflowData) bool

IsSafeInputsEnabled checks if safe-inputs are configured. Safe-inputs are enabled by default when configured in the workflow. The workflowData parameter is kept for backward compatibility but is not used.

func IsSafeInputsHTTPMode

func IsSafeInputsHTTPMode(safeInputs *SafeInputsConfig) bool

IsSafeInputsHTTPMode checks if safe-inputs is configured to use HTTP mode Note: All safe-inputs configurations now use HTTP mode exclusively

func MarshalWithFieldOrder

func MarshalWithFieldOrder(data map[string]any, priorityFields []string) ([]byte, error)

MarshalWithFieldOrder marshals a map to YAML with fields in a specific order.

This function ensures deterministic field ordering in the generated YAML by using yaml.MapSlice internally. Priority fields are emitted first in the order specified, then remaining fields are emitted alphabetically.

This is the primary function used throughout the workflow compiler to generate user-facing YAML for GitHub Actions workflows. It ensures workflows follow the conventional GitHub Actions field ordering, making them more readable and consistent with GitHub's documentation.

Parameters:

  • data: A map of field names to values to marshal
  • priorityFields: A slice of field names that should appear first, in order

Returns:

  • The marshaled YAML bytes with deterministic field ordering
  • An error if marshaling fails

The function uses the following YAML marshaling options:

  • 2-space indentation (GitHub Actions standard)
  • Literal block scalars for multiline strings (improves readability)

Example:

data := map[string]any{
    "jobs": map[string]any{...},
    "name": "My Workflow",
    "on": map[string]any{...},
    "permissions": map[string]any{...},
}
// Generate YAML with conventional field order: name, on, permissions, jobs
yaml, err := MarshalWithFieldOrder(data, []string{"name", "on", "permissions", "jobs"})
// Result:
// name: My Workflow
// on: ...
// permissions: ...
// jobs: ...

func NormalizeExpressionForComparison

func NormalizeExpressionForComparison(expression string) string

NormalizeExpressionForComparison normalizes an expression by removing extra spaces and newlines This is used for comparing multiline expressions with their single-line equivalents

func OrderMapFields

func OrderMapFields(data map[string]any, priorityFields []string) yaml.MapSlice

OrderMapFields converts a map to yaml.MapSlice with fields in a specific order.

yaml.MapSlice is a slice of key-value pairs that preserves insertion order during YAML marshaling. This function creates a MapSlice from a regular Go map, ensuring fields appear in a deterministic order.

The ordering strategy is:

  1. Priority fields are added first, in the exact order specified
  2. Remaining fields are added alphabetically

This function is useful when you need the MapSlice structure directly (e.g., for nested structures or when you need to add more items to the slice). For simple marshaling to YAML bytes, use MarshalWithFieldOrder instead.

Parameters:

  • data: A map of field names to values to order
  • priorityFields: Field names that should appear first, in order. If empty, all fields are sorted alphabetically.

Returns:

  • A yaml.MapSlice with fields in the specified order

Example use case - Ordering job step fields:

step := map[string]any{
    "env": map[string]string{"FOO": "bar"},
    "name": "Build project",
    "run": "make build",
}
// Order step fields: name, run, env (conventional GitHub Actions order)
orderedStep := OrderMapFields(step, []string{"name", "id", "if", "uses", "run", "with", "env"})
// orderedStep will have: name, run, env (only fields that exist)

Example use case - Alphabetical ordering:

permissions := map[string]any{
    "issues": "write",
    "contents": "read",
    "pull-requests": "write",
}
// Order alphabetically by passing empty priority list
orderedPerms := OrderMapFields(permissions, []string{})
// orderedPerms will have: contents, issues, pull-requests

func ParseBoolFromConfig

func ParseBoolFromConfig(m map[string]any, key string, log *logger.Logger) bool

ParseBoolFromConfig is a generic helper that extracts and validates a boolean value from a map. Returns the boolean value, or false if not present or invalid. If log is provided, it will log the extracted value for debugging.

func ParseCommandEvents

func ParseCommandEvents(eventsValue any) []string

ParseCommandEvents parses the events field from command configuration Returns a list of event identifiers to enable, or nil for default (all events)

func ParseGitHubToolsets

func ParseGitHubToolsets(toolsetsStr string) []string

ParseGitHubToolsets parses the toolsets string and expands "default" and "all" into their constituent toolsets. It handles comma-separated lists and deduplicates.

func ParseInputDefinitions

func ParseInputDefinitions(inputsMap map[string]any) map[string]*InputDefinition

ParseInputDefinitions parses a map of input definitions from a frontmatter map. Returns a map of input name to InputDefinition.

func ParseIntFromConfig

func ParseIntFromConfig(m map[string]any, key string, log *logger.Logger) int

ParseIntFromConfig is a generic helper that extracts and validates an integer value from a map. Supports int, int64, float64, and uint64 types. Returns the integer value, or 0 if not present or invalid. If log is provided, it will log the extracted value for debugging. Note: For uint64 values, returns 0 if the value would overflow int.

func ParseStringArrayFromConfig

func ParseStringArrayFromConfig(m map[string]any, key string, log *logger.Logger) []string

ParseStringArrayFromConfig is a generic helper that extracts and validates a string array from a map Returns a slice of strings, or nil if not present or invalid If log is provided, it will log the extracted values for debugging

func PrettifyToolName

func PrettifyToolName(toolName string) string

PrettifyToolName removes "mcp__" prefix and formats tool names nicely

func RenderConditionAsIf

func RenderConditionAsIf(yaml *strings.Builder, condition ConditionNode, indent string)

RenderConditionAsIf renders a ConditionNode as an 'if' condition with proper YAML indentation

func RenderGitHubMCPDockerConfig

func RenderGitHubMCPDockerConfig(yaml *strings.Builder, options GitHubMCPDockerOptions)

RenderGitHubMCPDockerConfig renders the GitHub MCP server configuration for Docker (local mode). Per MCP Gateway Specification v1.0.0 section 3.2.1, stdio-based MCP servers MUST be containerized. Uses MCP Gateway spec format: container, entrypointArgs, and env fields.

Parameters:

  • yaml: The string builder for YAML output
  • options: GitHub MCP Docker rendering options

func RenderGitHubMCPRemoteConfig

func RenderGitHubMCPRemoteConfig(yaml *strings.Builder, options GitHubMCPRemoteOptions)

RenderGitHubMCPRemoteConfig renders the GitHub MCP server configuration for remote (hosted) mode. This shared function extracts the duplicate pattern from Claude and Copilot engines.

Parameters:

  • yaml: The string builder for YAML output
  • options: GitHub MCP remote rendering options

func RenderJSONMCPConfig

func RenderJSONMCPConfig(
	yaml *strings.Builder,
	tools map[string]any,
	mcpTools []string,
	workflowData *WorkflowData,
	options JSONMCPConfigOptions,
) error

RenderJSONMCPConfig renders MCP configuration in JSON format with the common mcpServers structure. This shared function extracts the duplicate pattern from Claude, Copilot, and Custom engines.

Parameters:

  • yaml: The string builder for YAML output
  • tools: Map of tool configurations
  • mcpTools: Ordered list of MCP tool names to render
  • workflowData: Workflow configuration data
  • options: JSON MCP config rendering options

func ReplaceSecretsWithEnvVars

func ReplaceSecretsWithEnvVars(value string, secrets map[string]string) string

ReplaceSecretsWithEnvVars replaces secret expressions in a value with environment variable references Example: "${{ secrets.DD_API_KEY }}" -> "\${DD_API_KEY}" The backslash is used to escape the ${} for proper JSON rendering in Copilot configs

func ReplaceTemplateExpressionsWithEnvVars added in v0.43.6

func ReplaceTemplateExpressionsWithEnvVars(value string) string

ReplaceTemplateExpressionsWithEnvVars replaces all template expressions with environment variable references Handles: secrets.*, env.*, and github.workspace Examples:

  • "${{ secrets.DD_API_KEY }}" -> "\${DD_API_KEY}"
  • "${{ env.SENTRY_HOST }}" -> "\${SENTRY_HOST}"
  • "${{ github.workspace }}" -> "\${GITHUB_WORKSPACE}"

func ResolveAgentFilePath

func ResolveAgentFilePath(agentFile string) string

ResolveAgentFilePath returns the properly quoted agent file path with GITHUB_WORKSPACE prefix. This helper extracts the common pattern shared by Copilot, Codex, and Claude engines.

The agent file path is relative to the repository root, so we prefix it with ${GITHUB_WORKSPACE} and wrap the entire expression in double quotes to handle paths with spaces while allowing shell variable expansion.

Parameters:

  • agentFile: The relative path to the agent file (e.g., ".github/agents/test-agent.md")

Returns:

  • string: The double-quoted path with GITHUB_WORKSPACE prefix (e.g., "${GITHUB_WORKSPACE}/.github/agents/test-agent.md")

Example:

agentPath := ResolveAgentFilePath(".github/agents/my-agent.md")
// Returns: "${GITHUB_WORKSPACE}/.github/agents/my-agent.md"

Note: The entire path is wrapped in double quotes (not just the variable) to ensure:

  1. The shellEscapeArg function recognizes it as already-quoted and doesn't add single quotes
  2. Shell variable expansion works (${GITHUB_WORKSPACE} gets expanded inside double quotes)
  3. Paths with spaces are properly handled

func ResolveRelativeDate

func ResolveRelativeDate(dateStr string, baseTime time.Time) (string, error)

ResolveRelativeDate resolves a relative date string to an absolute timestamp suitable for use with GitHub CLI. If the date string is not relative, it returns the original string.

Returns a full ISO 8601 timestamp (YYYY-MM-DDTHH:MM:SSZ) for precise filtering.

func ResolveSetupActionReference

func ResolveSetupActionReference(actionMode ActionMode, version string, actionTag string, data *WorkflowData) string

ResolveSetupActionReference resolves the actions/setup action reference based on action mode and version. This is a standalone helper function that can be used by both Compiler methods and standalone workflow generators (like maintenance workflow) that don't have access to WorkflowData.

Parameters:

  • actionMode: The action mode (dev or release)
  • version: The version string to use for release mode
  • actionTag: Optional override tag/SHA (takes precedence over version when in release mode)
  • data: Optional WorkflowData for SHA resolution (can be nil for standalone use)

Returns:

  • For dev mode: "./actions/setup" (local path)
  • For release mode with data: "github/gh-aw/actions/setup@<sha> # <version>" (SHA-pinned)
  • For release mode without data: "github/gh-aw/actions/setup@<version>" (tag-based, SHA resolved later)
  • Falls back to local path if version is invalid in release mode

func ResolveWorkflowName

func ResolveWorkflowName(workflowInput string) (string, error)

ResolveWorkflowName converts an agentic workflow ID to the GitHub Actions workflow name. It normalizes the input by removing .md and .lock.yml extensions, then finds the corresponding workflow files and extracts the actual workflow name from the lock.yml file.

The agentic workflow ID is the basename of the markdown file without the .md extension. The GitHub Actions workflow name is extracted from the "name:" field in the corresponding .lock.yml file.

Examples:

  • "weekly-research" -> "Weekly Research" (from weekly-research.lock.yml name field)
  • "weekly-research.md" -> "Weekly Research" (from weekly-research.lock.yml name field)
  • "weekly-research.lock.yml" -> "Weekly Research" (from weekly-research.lock.yml name field)

func RewriteScriptForFileMode

func RewriteScriptForFileMode(content string, currentPath string) string

RewriteScriptForFileMode rewrites a script's require statements to use absolute paths from /tmp/gh-aw/scripts/ instead of relative paths.

This transforms:

const { helper } = require('./helper.cjs');

Into:

const { helper } = require('/opt/gh-aw/scripts/helper.cjs');

func RunGH

func RunGH(spinnerMessage string, args ...string) ([]byte, error)

RunGH executes a gh CLI command with a spinner and returns the stdout output. The spinner is shown in interactive terminals to provide feedback during network operations. The spinnerMessage parameter describes what operation is being performed.

Usage:

output, err := RunGH("Fetching user info...", "api", "/user")

func RunGHCombined

func RunGHCombined(spinnerMessage string, args ...string) ([]byte, error)

RunGHCombined executes a gh CLI command with a spinner and returns combined stdout+stderr output. The spinner is shown in interactive terminals to provide feedback during network operations. Use this when you need to capture error messages from stderr.

Usage:

output, err := RunGHCombined("Creating repository...", "repo", "create", "myrepo")

func SanitizeIdentifier

func SanitizeIdentifier(name string) string

SanitizeIdentifier sanitizes a workflow name to create a safe identifier suitable for use as a user agent string or similar context.

This is a SANITIZE function (character validity pattern). Use this when creating identifiers that must be purely alphanumeric with hyphens, with no special characters preserved. Unlike SanitizeWorkflowName which preserves dots and underscores, this function removes ALL special characters except hyphens.

The function:

  • Converts to lowercase
  • Replaces spaces and underscores with hyphens
  • Removes non-alphanumeric characters (except hyphens)
  • Consolidates multiple hyphens into a single hyphen
  • Trims leading and trailing hyphens
  • Returns "github-agentic-workflow" if the result would be empty

Example inputs and outputs:

SanitizeIdentifier("My Workflow")         // returns "my-workflow"
SanitizeIdentifier("test_workflow")       // returns "test-workflow"
SanitizeIdentifier("@@@")                 // returns "github-agentic-workflow" (default)
SanitizeIdentifier("Weekly v2.0")         // returns "weekly-v2-0"

This function uses the unified SanitizeName function with options configured to trim leading/trailing hyphens and return a default value for empty results. Hyphens are preserved by default in SanitizeName, not via PreserveSpecialChars.

See package documentation for guidance on when to use sanitize vs normalize patterns.

func SanitizeName

func SanitizeName(name string, opts *SanitizeOptions) string

SanitizeName sanitizes a string for use as an identifier, file name, or similar context. It provides configurable behavior through the SanitizeOptions parameter.

The function performs the following transformations:

  • Converts to lowercase
  • Replaces common separators (colons, slashes, backslashes, spaces) with hyphens
  • Replaces underscores with hyphens unless preserved in opts.PreserveSpecialChars
  • Removes or replaces characters based on opts.PreserveSpecialChars
  • Consolidates multiple consecutive hyphens into a single hyphen
  • Optionally trims leading/trailing hyphens (controlled by opts.TrimHyphens)
  • Returns opts.DefaultValue if the result is empty (controlled by opts.DefaultValue)

Example:

// Preserve dots and underscores (like SanitizeWorkflowName)
opts := &SanitizeOptions{
    PreserveSpecialChars: []rune{'.', '_'},
}
SanitizeName("My.Workflow_Name", opts) // returns "my.workflow_name"

// Trim hyphens and use default (like SanitizeIdentifier)
opts := &SanitizeOptions{
    TrimHyphens:  true,
    DefaultValue: "default-name",
}
SanitizeName("@@@", opts) // returns "default-name"

func SanitizeWorkflowIDForCacheKey added in v0.43.23

func SanitizeWorkflowIDForCacheKey(workflowID string) string

SanitizeWorkflowIDForCacheKey sanitizes a workflow ID for use in cache keys. It removes all hyphens and converts to lowercase to create a filesystem-safe identifier. Example: "Smoke-Copilot" -> "smokecopilot"

func SanitizeWorkflowName

func SanitizeWorkflowName(name string) string

SanitizeWorkflowName sanitizes a workflow name for use in artifact names and file paths. It converts the name to lowercase and replaces or removes characters that are invalid in YAML artifact names or filesystem paths.

This is a SANITIZE function (character validity pattern). Use this when processing user input or workflow names that may contain invalid characters. Do NOT use this for removing file extensions - use stringutil.NormalizeWorkflowName instead.

The function performs the following transformations:

  • Converts to lowercase
  • Replaces colons, slashes, backslashes, and spaces with hyphens
  • Replaces any remaining special characters (except dots, underscores, and hyphens) with hyphens
  • Consolidates multiple consecutive hyphens into a single hyphen

Example inputs and outputs:

SanitizeWorkflowName("My Workflow: Test/Build")  // returns "my-workflow-test-build"
SanitizeWorkflowName("Weekly Research v2.0")     // returns "weekly-research-v2.0"
SanitizeWorkflowName("test_workflow")            // returns "test_workflow"

See package documentation for guidance on when to use sanitize vs normalize patterns.

func SetDefaultVersion

func SetDefaultVersion(version string)

SetDefaultVersion sets the default version for compiler creation This should be called once during CLI initialization

func SetIsRelease

func SetIsRelease(release bool)

SetIsRelease sets whether this binary was built as a release.

func SetVersion

func SetVersion(v string)

SetVersion sets the compiler version for inclusion in generated workflow headers. Only non-dev versions are included in the generated headers.

func ShortenCommand

func ShortenCommand(command string) string

ShortenCommand creates a short identifier for bash commands in workflow logs. It replaces newlines with spaces and truncates to 20 characters if needed.

This is a domain-specific function for workflow log parsing. It creates unique identifiers for bash commands by:

  • Replacing newlines with spaces (bash commands can be multi-line)
  • Truncating to a fixed 20 characters with "..." suffix
  • Producing identifiers like "bash_echo hello world..."

For general-purpose string truncation with configurable length, use stringutil.Truncate instead.

func ShouldGeneratePRCheckoutStep added in v0.42.14

func ShouldGeneratePRCheckoutStep(data *WorkflowData) bool

ShouldGeneratePRCheckoutStep returns true if the checkout-pr step should be generated based on the workflow permissions. The step requires contents read access.

func ShouldSkipRuntimeSetup

func ShouldSkipRuntimeSetup(workflowData *WorkflowData) bool

ShouldSkipRuntimeSetup checks if we should skip automatic runtime setup Deprecated: Runtime detection now smartly filters out existing runtimes instead of skipping entirely This function now always returns false for backward compatibility

func SortPermissionScopes

func SortPermissionScopes(s []PermissionScope)

SortPermissionScopes sorts a slice of PermissionScope in place using Go's standard library sort

func SortStrings

func SortStrings(s []string)

SortStrings sorts a slice of strings in place using Go's standard library sort

func SplitJoinedErrors

func SplitJoinedErrors(err error) []error

SplitJoinedErrors splits a joined error into individual error strings

func StepsToSlice

func StepsToSlice(steps []*WorkflowStep) []any

StepsToSlice converts a typed slice of WorkflowStep pointers back to []any for backward compatibility with existing YAML generation code

func SubstituteImportInputs

func SubstituteImportInputs(content string, importInputs map[string]any) string

SubstituteImportInputs replaces ${{ github.aw.inputs.<key> }} expressions with the corresponding values from the importInputs map. This is called before expression extraction to inject import input values.

func TransformRequiresToAbsolutePath

func TransformRequiresToAbsolutePath(content string, basePath string) string

TransformRequiresToAbsolutePath rewrites all relative require statements in content to use the specified absolute base path.

This transforms:

const { helper } = require('./helper.cjs');

Into:

const { helper } = require('/base/path/helper.cjs');

Parameters:

  • content: The JavaScript content to transform
  • basePath: The absolute path to use for requires (e.g., "/opt/gh-aw/safeoutputs")

func UnfenceMarkdown added in v0.42.0

func UnfenceMarkdown(content string) string

UnfenceMarkdown removes an outer code fence from markdown content if the entire content is wrapped in a markdown/md code fence. This handles cases where agents accidentally wrap the entire markdown body in a code fence.

The function detects: - Content starting with ```markdown, ```md, ~~~markdown, or ~~~md (case insensitive) - Content ending with ``` or ~~~ - The closing fence must match the opening fence type (backticks or tildes)

Returns the unfenced content if a wrapping fence is detected, otherwise returns the original content unchanged.

func UnquoteYAMLKey

func UnquoteYAMLKey(yamlStr string, key string) string

UnquoteYAMLKey removes quotes from a YAML key at the start of a line.

The YAML marshaler automatically adds quotes around YAML reserved words and keywords to prevent parsing ambiguity. For example, the word "on" is a YAML boolean value, so the marshaler outputs it as "on": to distinguish it from the boolean.

However, GitHub Actions uses "on" as a top-level key for workflow triggers, and the Actions UI and documentation always show it unquoted. This function removes those quotes to match the conventional GitHub Actions syntax.

The function only replaces quoted keys at the start of a line (optionally preceded by whitespace) to avoid incorrectly unquoting string values that happen to contain the same text. For example, description: "This is about on: something" would be left unchanged.

Parameters:

  • yamlStr: The YAML string to process
  • key: The key to unquote (e.g., "on", "if", "true", "false")

Returns:

  • The YAML string with the specified key unquoted at line starts

Example:

input := "\"on\":\n  push:\n    branches:\n      - main"
result := UnquoteYAMLKey(input, "on")
// result: "on:\n  push:\n    branches:\n      - main"

func ValidateActionSHAsInLockFile

func ValidateActionSHAsInLockFile(lockFilePath string, cache *ActionCache, verbose bool) error

ValidateActionSHAsInLockFile validates action SHAs in a lock file and emits warnings

func ValidateEmbeddedResourceRequires

func ValidateEmbeddedResourceRequires(sources map[string]string) error

ValidateEmbeddedResourceRequires checks that all embedded JavaScript files in the sources map have their local require() dependencies available in the sources map. This prevents bundling failures when a file requires a local module that isn't embedded.

This validation helps catch missing files in GetJavaScriptSources() at build/test time rather than at runtime when bundling fails.

Parameters:

  • sources: map of file paths to their content (from GetJavaScriptSources())

Returns an error if any embedded file has local requires that reference files not in sources

func ValidateEventFilters

func ValidateEventFilters(frontmatter map[string]any) error

ValidateEventFilters checks for GitHub Actions filter mutual exclusivity rules

func ValidateExpressionSafetyPublic

func ValidateExpressionSafetyPublic(markdownContent string) error

ValidateExpressionSafetyPublic is a public wrapper for validateExpressionSafety that allows testing expression validation from external packages

func ValidateGitHubToolsAgainstToolsets

func ValidateGitHubToolsAgainstToolsets(allowedTools []string, enabledToolsets []string) error

ValidateGitHubToolsAgainstToolsets validates that all allowed GitHub tools have their corresponding toolsets enabled in the configuration

func ValidateInList

func ValidateInList(field, value string, allowedValues []string) error

ValidateInList validates that a value is in an allowed list

func ValidateLogLevel

func ValidateLogLevel(level string) error

ValidateLogLevel validates that a firewall log-level value is one of the allowed enum values. Valid values are: "debug", "info", "warn", "error". Empty string is allowed as it defaults to "info" at runtime. Returns an error if the log-level is invalid.

func ValidateMCPConfigs

func ValidateMCPConfigs(tools map[string]any) error

ValidateMCPConfigs validates all MCP configurations in the tools section using JSON schema

func ValidateMaxLength

func ValidateMaxLength(field, value string, maxLength int) error

ValidateMaxLength validates that a field does not exceed maximum length

func ValidateMinLength

func ValidateMinLength(field, value string, minLength int) error

ValidateMinLength validates that a field meets minimum length requirement

func ValidateNonNegativeInt

func ValidateNonNegativeInt(field string, value int) error

ValidateNonNegativeInt validates that a value is a non-negative integer

func ValidatePositiveInt

func ValidatePositiveInt(field string, value int) error

ValidatePositiveInt validates that a value is a positive integer

func ValidateRequired

func ValidateRequired(field, value string) error

ValidateRequired validates that a required field is not empty

func VisitExpressionTree

func VisitExpressionTree(node ConditionNode, visitor func(expr *ExpressionNode) error) error

VisitExpressionTree walks through an expression tree and calls the visitor function for each ExpressionNode (literal expression) found in the tree

func WrapErrorWithContext

func WrapErrorWithContext(err error, context, suggestion string) error

WrapErrorWithContext wraps an error with additional context using fmt.Errorf %w This preserves error unwrapping while adding context

func WriteJavaScriptToYAML

func WriteJavaScriptToYAML(yaml *strings.Builder, script string)

WriteJavaScriptToYAML writes a JavaScript script with proper indentation to a strings.Builder

func WriteJavaScriptToYAMLPreservingComments

func WriteJavaScriptToYAMLPreservingComments(yaml *strings.Builder, script string)

WriteJavaScriptToYAMLPreservingComments writes a JavaScript script with proper indentation to a strings.Builder while preserving JSDoc and inline comments, but removing TypeScript-specific comments. Used for security-sensitive scripts like redact_secrets.

func WritePromptFileToYAML

func WritePromptFileToYAML(yaml *strings.Builder, filename string, indent string)

WritePromptFileToYAML writes a shell command to cat a prompt file from /opt/gh-aw/prompts/ This replaces the previous approach of embedding prompt text in the binary.

func WritePromptTextToYAML

func WritePromptTextToYAML(yaml *strings.Builder, text string, indent string)

WritePromptTextToYAML writes static prompt text to a YAML heredoc with proper indentation. Use this function for prompt text that contains NO variable placeholders or expressions. It chunks the text into groups of lines of less than MaxPromptChunkSize characters, with a maximum of MaxPromptChunks chunks. Each chunk is written as a separate heredoc to avoid GitHub Actions step size limits (21KB).

For prompt text with variable placeholders that need substitution, use WritePromptTextToYAMLWithPlaceholders instead.

func WritePromptTextToYAMLWithPlaceholders

func WritePromptTextToYAMLWithPlaceholders(yaml *strings.Builder, text string, indent string)

WritePromptTextToYAMLWithPlaceholders writes prompt text with variable placeholders to a YAML heredoc with proper indentation. Use this function for prompt text containing __VAR__ placeholders that will be substituted with sed commands. The caller is responsible for adding the sed substitution commands after calling this function. It uses placeholder format (__VAR__) instead of shell variable expansion, to prevent template injection.

For static prompt text without variables, use WritePromptTextToYAML instead.

func WriteShellScriptToYAML

func WriteShellScriptToYAML(yaml *strings.Builder, script string, indent string)

WriteShellScriptToYAML writes a shell script with proper indentation to a strings.Builder

Types

type ActionCache

type ActionCache struct {
	Entries map[string]ActionCacheEntry `json:"entries"` // key: "repo@version"
	// contains filtered or unexported fields
}

ActionCache manages cached action pin resolutions.

func NewActionCache

func NewActionCache(repoRoot string) *ActionCache

NewActionCache creates a new action cache instance

func (*ActionCache) FindEntryBySHA

func (c *ActionCache) FindEntryBySHA(repo, sha string) (ActionCacheEntry, bool)

FindEntryBySHA finds a cache entry with the given repo and SHA Returns the entry and true if found, or empty entry and false if not found

func (*ActionCache) Get

func (c *ActionCache) Get(repo, version string) (string, bool)

Get retrieves a cached entry if it exists

func (*ActionCache) GetCachePath

func (c *ActionCache) GetCachePath() string

GetCachePath returns the path to the cache file

func (*ActionCache) Load

func (c *ActionCache) Load() error

Load loads the cache from disk

func (*ActionCache) Save

func (c *ActionCache) Save() error

Save saves the cache to disk with sorted entries If the cache is empty, the file is not created or is deleted if it exists Deduplicates entries by keeping only the most precise version reference for each repo+SHA combination Only saves if the cache has been modified (dirty flag is true)

func (*ActionCache) Set

func (c *ActionCache) Set(repo, version, sha string)

Set stores a new cache entry

type ActionCacheEntry

type ActionCacheEntry struct {
	Repo    string `json:"repo"`
	Version string `json:"version"`
	SHA     string `json:"sha"`
}

ActionCacheEntry represents a cached action pin resolution.

type ActionMode

type ActionMode string

ActionMode defines how JavaScript is embedded in workflow steps

const (
	// ActionModeDev references custom actions using local paths (development mode, default)
	ActionModeDev ActionMode = "dev"

	// ActionModeRelease references custom actions using SHA-pinned remote paths (release mode)
	ActionModeRelease ActionMode = "release"

	// ActionModeScript runs setup.sh script from checked-out .github folder instead of using action steps
	ActionModeScript ActionMode = "script"
)

func DetectActionMode

func DetectActionMode(version string) ActionMode

DetectActionMode determines the appropriate action mode based on the release flag. Returns ActionModeRelease if this binary was built as a release (controlled by the isReleaseBuild flag set via -X linker flag at build time), otherwise returns ActionModeDev. Can be overridden with GH_AW_ACTION_MODE environment variable or GitHub Actions context. The version parameter is kept for backward compatibility but is no longer used for detection.

func GetActionModeFromWorkflowData added in v0.42.4

func GetActionModeFromWorkflowData(workflowData *WorkflowData) ActionMode

GetActionModeFromWorkflowData extracts the ActionMode from WorkflowData, defaulting to dev mode if nil

func (ActionMode) IsDev

func (m ActionMode) IsDev() bool

IsDev returns true if the action mode is development mode

func (ActionMode) IsRelease

func (m ActionMode) IsRelease() bool

IsRelease returns true if the action mode is release mode

func (ActionMode) IsScript

func (m ActionMode) IsScript() bool

IsScript returns true if the action mode is script mode

func (ActionMode) IsValid

func (m ActionMode) IsValid() bool

IsValid checks if the action mode is valid

func (ActionMode) String

func (m ActionMode) String() string

String returns the string representation of the action mode

func (ActionMode) UsesExternalActions

func (m ActionMode) UsesExternalActions() bool

UsesExternalActions returns true (always true since inline mode was removed)

type ActionPin

type ActionPin struct {
	Repo    string `json:"repo"`    // e.g., "actions/checkout"
	Version string `json:"version"` // e.g., "v5" - the golden/default version
	SHA     string `json:"sha"`     // Full commit SHA for the pinned version
}

ActionPin represents a pinned GitHub Action with its commit SHA

func GetActionPinByRepo

func GetActionPinByRepo(repo string) (ActionPin, bool)

GetActionPinByRepo returns the ActionPin for a given repository, if it exists When multiple versions exist for the same repo, it returns the latest version by semver

type ActionPinsData

type ActionPinsData struct {
	Entries map[string]ActionPin `json:"entries"` // key: "repo@version"
}

ActionPinsData represents the structure of the embedded JSON file This matches the schema used by ActionCache for consistency

type ActionResolver

type ActionResolver struct {
	// contains filtered or unexported fields
}

ActionResolver handles resolving action SHAs using GitHub CLI

func NewActionResolver

func NewActionResolver(cache *ActionCache) *ActionResolver

NewActionResolver creates a new action resolver

func (*ActionResolver) ResolveSHA

func (r *ActionResolver) ResolveSHA(repo, version string) (string, error)

ResolveSHA resolves the SHA for a given action@version using GitHub CLI Returns the SHA and an error if resolution fails

type ActionUpdateCheck

type ActionUpdateCheck struct {
	Action      ActionUsage
	NeedsUpdate bool
	LatestSHA   string
	Message     string
}

ActionUpdateCheck represents the result of checking if an action needs updating

func CheckActionSHAUpdates

func CheckActionSHAUpdates(actions []ActionUsage, resolver *ActionResolver) []ActionUpdateCheck

CheckActionSHAUpdates checks if actions need updating by comparing with latest SHAs

type ActionUsage

type ActionUsage struct {
	Repo    string // e.g., "actions/checkout"
	SHA     string // The SHA currently used
	Version string // The version tag if available (e.g., "v5")
}

ActionUsage represents an action used in a workflow with its SHA

func ExtractActionsFromLockFile

func ExtractActionsFromLockFile(lockFilePath string) ([]ActionUsage, error)

ExtractActionsFromLockFile parses a lock.yml file and extracts all action usages

type AddCommentConfig

type AddCommentConfig struct {
}

AddCommentConfig holds configuration for creating GitHub issue/PR comments from agent output (deprecated, use AddCommentsConfig)

type AddCommentsConfig

type AddCommentsConfig struct {
	BaseSafeOutputConfig `yaml:",inline"`
	Target               string   `yaml:"target,omitempty"`              // Target for comments: "triggering" (default), "*" (any issue), or explicit issue number
	TargetRepoSlug       string   `yaml:"target-repo,omitempty"`         // Target repository in format "owner/repo" for cross-repository comments
	AllowedRepos         []string `yaml:"allowed-repos,omitempty"`       // List of additional repositories that comments can be added to (additionally to the target-repo)
	Discussion           *bool    `yaml:"discussion,omitempty"`          // Target discussion comments instead of issue/PR comments. Must be true if present.
	HideOlderComments    bool     `yaml:"hide-older-comments,omitempty"` // When true, minimizes/hides all previous comments from the same workflow before creating the new comment
	AllowedReasons       []string `yaml:"allowed-reasons,omitempty"`     // List of allowed reasons for hiding older comments (default: all reasons allowed)
}

AddCommentsConfig holds configuration for creating GitHub issue/PR comments from agent output

type AddLabelsConfig

type AddLabelsConfig struct {
	BaseSafeOutputConfig   `yaml:",inline"`
	SafeOutputTargetConfig `yaml:",inline"`
	Allowed                []string `yaml:"allowed,omitempty"` // Optional list of allowed labels. Labels will be created if they don't already exist in the repository. If omitted, any labels are allowed (including creating new ones).
}

AddLabelsConfig holds configuration for adding labels to issues/PRs from agent output

type AddReviewerConfig

type AddReviewerConfig struct {
	BaseSafeOutputConfig   `yaml:",inline"`
	SafeOutputTargetConfig `yaml:",inline"`
	Reviewers              []string `yaml:"reviewers,omitempty"` // Optional list of allowed reviewers. If omitted, any reviewers are allowed.
}

AddReviewerConfig holds configuration for adding reviewers to PRs from agent output

type AgentSandboxConfig

type AgentSandboxConfig struct {
	ID       string                `yaml:"id,omitempty"`      // Agent ID: "awf" or "srt" (replaces Type in new object format)
	Type     SandboxType           `yaml:"type,omitempty"`    // Sandbox type: "awf" or "srt" (legacy, use ID instead)
	Disabled bool                  `yaml:"-"`                 // True when agent is explicitly set to false (disables firewall). This is a runtime flag, not serialized to YAML.
	Config   *SandboxRuntimeConfig `yaml:"config,omitempty"`  // Custom SRT config (optional)
	Command  string                `yaml:"command,omitempty"` // Custom command to replace AWF or SRT installation
	Args     []string              `yaml:"args,omitempty"`    // Additional arguments to append to the command
	Env      map[string]string     `yaml:"env,omitempty"`     // Environment variables to set on the step
	Mounts   []string              `yaml:"mounts,omitempty"`  // Container mounts to add for AWF (format: "source:dest:mode")
}

AgentSandboxConfig represents the agent sandbox configuration

type AgenticWorkflowsToolConfig

type AgenticWorkflowsToolConfig struct {
	// Can be boolean or nil
	Enabled bool `yaml:"-"`
}

AgenticWorkflowsToolConfig represents the configuration for the agentic-workflows tool

type AndNode

type AndNode struct {
	Left, Right ConditionNode
}

AndNode represents an AND operation between two conditions

func (*AndNode) Render

func (a *AndNode) Render() string

type ArtifactDownload

type ArtifactDownload struct {
	// Name is the artifact name to download (optional if using Pattern)
	Name string

	// Pattern is a glob pattern to match multiple artifacts (v4 feature)
	Pattern string

	// Path is where the artifact will be downloaded
	Path string

	// MergeMultiple determines if multiple artifacts should be merged
	// into the same directory (only applies when using Pattern)
	MergeMultiple bool

	// JobName is the name of the job downloading this artifact
	JobName string

	// DependsOn lists job names this job depends on (from needs:)
	DependsOn []string
}

ArtifactDownload represents an artifact download operation

type ArtifactDownloadConfig

type ArtifactDownloadConfig struct {
	ArtifactName     string // Name of the artifact to download (e.g., "agent-output", "prompt")
	ArtifactFilename string // Filename inside the artifact directory (e.g., "agent_output.json", "prompt.txt")
	DownloadPath     string // Path where artifact will be downloaded (e.g., "/tmp/gh-aw/safeoutputs/")
	SetupEnvStep     bool   // Whether to add environment variable setup step
	EnvVarName       string // Environment variable name to set (e.g., "GH_AW_AGENT_OUTPUT")
	StepName         string // Optional custom step name (defaults to "Download {artifact} artifact")
	IfCondition      string // Optional conditional expression for the step (e.g., "needs.agent.outputs.has_patch == 'true'")
}

ArtifactDownloadConfig holds configuration for building artifact download steps

type ArtifactFile

type ArtifactFile struct {
	// ArtifactName is the name of the artifact containing this file
	ArtifactName string

	// OriginalPath is the path as uploaded
	OriginalPath string

	// DownloadPath is the computed path after download
	DownloadPath string

	// JobName is the job that uploaded this file
	JobName string
}

ArtifactFile represents a file within an artifact

type ArtifactManager

type ArtifactManager struct {
	// contains filtered or unexported fields
}

ArtifactManager simulates the behavior of actions/upload-artifact and actions/download-artifact to track artifacts and compute actual file locations during compilation.

This manager implements the v4 behavior of GitHub Actions artifacts: - Upload: artifacts are immutable, each upload creates a new artifact - Download: files extracted directly to path (not path/artifact-name/) - Pattern downloads: separate subdirectories unless merge-multiple is used

func NewArtifactManager

func NewArtifactManager() *ArtifactManager

NewArtifactManager creates a new artifact manager

func (*ArtifactManager) ComputeDownloadPath

func (am *ArtifactManager) ComputeDownloadPath(download *ArtifactDownload, upload *ArtifactUpload, originalPath string) string

ComputeDownloadPath computes the actual file path after download based on GitHub Actions v4 behavior.

Rules: - Download by name: files extracted directly to path/ (e.g., path/file.txt) - Download by pattern without merge: files in path/artifact-name/ (e.g., path/artifact-1/file.txt) - Download by pattern with merge: files extracted directly to path/ (e.g., path/file.txt) - Common parent directories are stripped during upload (simulated via NormalizedPaths)

func (*ArtifactManager) FindUploadedArtifact

func (am *ArtifactManager) FindUploadedArtifact(artifactName string, dependsOn []string) *ArtifactUpload

FindUploadedArtifact finds an uploaded artifact by name from jobs this job depends on

func (*ArtifactManager) GetAllArtifacts

func (am *ArtifactManager) GetAllArtifacts() map[string][]*ArtifactUpload

GetAllArtifacts returns all uploaded artifacts

func (*ArtifactManager) GetCurrentJob

func (am *ArtifactManager) GetCurrentJob() string

GetCurrentJob returns the current job name

func (*ArtifactManager) GetDownloadsForJob

func (am *ArtifactManager) GetDownloadsForJob(jobName string) []*ArtifactDownload

GetDownloadsForJob returns all downloads for a specific job

func (*ArtifactManager) GetUploadsForJob

func (am *ArtifactManager) GetUploadsForJob(jobName string) []*ArtifactUpload

GetUploadsForJob returns all uploads for a specific job

func (*ArtifactManager) RecordDownload

func (am *ArtifactManager) RecordDownload(download *ArtifactDownload) error

RecordDownload records an artifact download operation

func (*ArtifactManager) RecordUpload

func (am *ArtifactManager) RecordUpload(upload *ArtifactUpload) error

RecordUpload records an artifact upload operation

func (*ArtifactManager) Reset

func (am *ArtifactManager) Reset()

Reset clears all tracked uploads and downloads

func (*ArtifactManager) SetCurrentJob

func (am *ArtifactManager) SetCurrentJob(jobName string)

SetCurrentJob sets the job currently being processed

func (*ArtifactManager) ValidateAllDownloads

func (am *ArtifactManager) ValidateAllDownloads() []error

ValidateAllDownloads validates all download operations

func (*ArtifactManager) ValidateDownload

func (am *ArtifactManager) ValidateDownload(download *ArtifactDownload) error

ValidateDownload validates that a download operation can find its artifact

type ArtifactUpload

type ArtifactUpload struct {
	// Name is the artifact name (e.g., "agent-artifacts")
	Name string

	// Paths are the file/directory paths being uploaded
	// These can be absolute paths or glob patterns
	Paths []string

	// NormalizedPaths are the paths after common parent directory removal
	// This simulates GitHub Actions behavior where the common parent is stripped
	NormalizedPaths map[string]string

	// IfNoFilesFound specifies behavior when no files match
	// Values: "warn", "error", "ignore"
	IfNoFilesFound string

	// IncludeHiddenFiles determines if hidden files are included
	IncludeHiddenFiles bool

	// JobName is the name of the job uploading this artifact
	JobName string
}

ArtifactUpload represents an artifact upload operation

type AssignMilestoneConfig

type AssignMilestoneConfig struct {
	BaseSafeOutputConfig   `yaml:",inline"`
	SafeOutputTargetConfig `yaml:",inline"`
	Allowed                []string `yaml:"allowed,omitempty"` // Optional list of allowed milestone titles or IDs
}

AssignMilestoneConfig holds configuration for assigning milestones to issues from agent output

type AssignToAgentConfig

type AssignToAgentConfig struct {
	BaseSafeOutputConfig   `yaml:",inline"`
	SafeOutputTargetConfig `yaml:",inline"`
	DefaultAgent           string   `yaml:"name,omitempty"`            // Default agent to assign (e.g., "copilot")
	Allowed                []string `yaml:"allowed,omitempty"`         // Optional list of allowed agent names. If omitted, any agents are allowed.
	IgnoreIfError          bool     `yaml:"ignore-if-error,omitempty"` // If true, workflow continues when agent assignment fails
}

AssignToAgentConfig holds configuration for assigning agents to issues from agent output

type AssignToUserConfig

type AssignToUserConfig struct {
	BaseSafeOutputConfig   `yaml:",inline"`
	SafeOutputTargetConfig `yaml:",inline"`
	Allowed                []string `yaml:"allowed,omitempty"` // Optional list of allowed usernames. If omitted, any users are allowed.
}

AssignToUserConfig holds configuration for assigning users to issues from agent output

type AutofixCodeScanningAlertConfig

type AutofixCodeScanningAlertConfig struct {
	BaseSafeOutputConfig `yaml:",inline"`
}

AutofixCodeScanningAlertConfig holds configuration for adding autofixes to code scanning alerts

type BaseEngine

type BaseEngine struct {
	// contains filtered or unexported fields
}

BaseEngine provides common functionality for agentic engines

func (*BaseEngine) GetDeclaredOutputFiles

func (e *BaseEngine) GetDeclaredOutputFiles() []string

GetDeclaredOutputFiles returns an empty list by default (engines can override)

func (*BaseEngine) GetDefaultDetectionModel

func (e *BaseEngine) GetDefaultDetectionModel() string

GetDefaultDetectionModel returns empty string by default (no default model) Engines can override this to provide a cost-effective default for detection jobs

func (*BaseEngine) GetDescription

func (e *BaseEngine) GetDescription() string

func (*BaseEngine) GetDisplayName

func (e *BaseEngine) GetDisplayName() string

func (*BaseEngine) GetID

func (e *BaseEngine) GetID() string

func (*BaseEngine) GetLogFileForParsing

func (e *BaseEngine) GetLogFileForParsing() string

GetLogFileForParsing returns the default log file path for parsing Engines can override this to use engine-specific log files

func (*BaseEngine) GetRequiredSecretNames

func (e *BaseEngine) GetRequiredSecretNames(workflowData *WorkflowData) []string

GetRequiredSecretNames returns an empty list by default Engines must override this to specify their required secrets

func (*BaseEngine) IsExperimental

func (e *BaseEngine) IsExperimental() bool

func (*BaseEngine) SupportsFirewall

func (e *BaseEngine) SupportsFirewall() bool

func (*BaseEngine) SupportsHTTPTransport

func (e *BaseEngine) SupportsHTTPTransport() bool

func (*BaseEngine) SupportsLLMGateway added in v0.43.19

func (e *BaseEngine) SupportsLLMGateway() bool

func (*BaseEngine) SupportsMaxTurns

func (e *BaseEngine) SupportsMaxTurns() bool

func (*BaseEngine) SupportsPlugins added in v0.42.15

func (e *BaseEngine) SupportsPlugins() bool

func (*BaseEngine) SupportsToolsAllowlist

func (e *BaseEngine) SupportsToolsAllowlist() bool

func (*BaseEngine) SupportsWebFetch

func (e *BaseEngine) SupportsWebFetch() bool

func (*BaseEngine) SupportsWebSearch

func (e *BaseEngine) SupportsWebSearch() bool

type BaseSafeOutputConfig

type BaseSafeOutputConfig struct {
	Max         int    `yaml:"max,omitempty"`          // Maximum number of items to create
	GitHubToken string `yaml:"github-token,omitempty"` // GitHub token for this specific output type
}

BaseSafeOutputConfig holds common configuration fields for all safe output types

type BashToolConfig

type BashToolConfig struct {
	AllowedCommands []string `yaml:"-"` // List of allowed bash commands
}

BashToolConfig represents the configuration for the Bash tool Can be nil (all commands allowed) or an array of allowed commands

type BooleanLiteralNode

type BooleanLiteralNode struct {
	Value bool
}

BooleanLiteralNode represents a boolean literal value

func BuildBooleanLiteral

func BuildBooleanLiteral(value bool) *BooleanLiteralNode

BuildBooleanLiteral creates a boolean literal node

func (*BooleanLiteralNode) Render

func (b *BooleanLiteralNode) Render() string

type CacheMemoryConfig

type CacheMemoryConfig struct {
	Caches []CacheMemoryEntry `yaml:"caches,omitempty"` // cache configurations
}

CacheMemoryConfig holds configuration for cache-memory functionality

type CacheMemoryEntry

type CacheMemoryEntry struct {
	ID                string   `yaml:"id"`                           // cache identifier (required for array notation)
	Key               string   `yaml:"key,omitempty"`                // custom cache key
	Description       string   `yaml:"description,omitempty"`        // optional description for this cache
	RetentionDays     *int     `yaml:"retention-days,omitempty"`     // retention days for upload-artifact action
	RestoreOnly       bool     `yaml:"restore-only,omitempty"`       // if true, only restore cache without saving
	Scope             string   `yaml:"scope,omitempty"`              // scope for restore keys: "workflow" (default) or "repo"
	AllowedExtensions []string `yaml:"allowed-extensions,omitempty"` // allowed file extensions (default: [".json", ".jsonl", ".txt", ".md", ".csv"])
}

CacheMemoryEntry represents a single cache-memory configuration

type CacheMemoryToolConfig

type CacheMemoryToolConfig struct {
	// Can be boolean, object, or array - handled by cache.go
	Raw any `yaml:"-"`
}

CacheMemoryToolConfig represents the configuration for cache-memory This is handled separately by the existing CacheMemoryConfig in cache.go

type CapabilityProvider

type CapabilityProvider interface {
	// SupportsToolsAllowlist returns true if this engine supports MCP tool allow-listing
	SupportsToolsAllowlist() bool

	// SupportsHTTPTransport returns true if this engine supports HTTP transport for MCP servers
	SupportsHTTPTransport() bool

	// SupportsMaxTurns returns true if this engine supports the max-turns feature
	SupportsMaxTurns() bool

	// SupportsWebFetch returns true if this engine has built-in support for the web-fetch tool
	SupportsWebFetch() bool

	// SupportsWebSearch returns true if this engine has built-in support for the web-search tool
	SupportsWebSearch() bool

	// SupportsFirewall returns true if this engine supports network firewalling/sandboxing
	// When true, the engine can enforce network restrictions defined in the workflow
	SupportsFirewall() bool

	// SupportsPlugins returns true if this engine supports plugin installation
	// When true, plugins can be installed using the engine's plugin install command
	SupportsPlugins() bool

	// SupportsLLMGateway returns true if this engine supports an LLM gateway
	// When true, the engine can use a gateway service to proxy LLM API calls
	// In strict mode, engines without LLM gateway support require additional security constraints
	SupportsLLMGateway() bool
}

CapabilityProvider detects what capabilities an engine supports Engines can optionally implement this to indicate feature support

type ClaudeEngine

type ClaudeEngine struct {
	BaseEngine
}

ClaudeEngine represents the Claude Code agentic engine

func NewClaudeEngine

func NewClaudeEngine() *ClaudeEngine

func (*ClaudeEngine) GetDeclaredOutputFiles

func (e *ClaudeEngine) GetDeclaredOutputFiles() []string

GetDeclaredOutputFiles returns the output files that Claude may produce

func (*ClaudeEngine) GetExecutionSteps

func (e *ClaudeEngine) GetExecutionSteps(workflowData *WorkflowData, logFile string) []GitHubActionStep

GetExecutionSteps returns the GitHub Actions steps for executing Claude

func (*ClaudeEngine) GetFirewallLogsCollectionStep

func (e *ClaudeEngine) GetFirewallLogsCollectionStep(workflowData *WorkflowData) []GitHubActionStep

GetFirewallLogsCollectionStep returns the step for collecting firewall logs (before secret redaction) No longer needed since we know where the logs are in the sandbox folder structure

func (*ClaudeEngine) GetInstallationSteps

func (e *ClaudeEngine) GetInstallationSteps(workflowData *WorkflowData) []GitHubActionStep

func (*ClaudeEngine) GetLogParserScriptId

func (e *ClaudeEngine) GetLogParserScriptId() string

GetLogParserScriptId returns the JavaScript script name for parsing Claude logs

func (*ClaudeEngine) GetRequiredSecretNames

func (e *ClaudeEngine) GetRequiredSecretNames(workflowData *WorkflowData) []string

GetRequiredSecretNames returns the list of secrets required by the Claude engine This includes ANTHROPIC_API_KEY, CLAUDE_CODE_OAUTH_TOKEN, and optionally MCP_GATEWAY_API_KEY

func (*ClaudeEngine) GetSquidLogsSteps

func (e *ClaudeEngine) GetSquidLogsSteps(workflowData *WorkflowData) []GitHubActionStep

GetSquidLogsSteps returns the steps for uploading and parsing Squid logs (after secret redaction)

func (*ClaudeEngine) ParseLogMetrics

func (e *ClaudeEngine) ParseLogMetrics(logContent string, verbose bool) LogMetrics

ParseLogMetrics implements engine-specific log parsing for Claude

func (*ClaudeEngine) RenderMCPConfig

func (e *ClaudeEngine) RenderMCPConfig(yaml *strings.Builder, tools map[string]any, mcpTools []string, workflowData *WorkflowData)

RenderMCPConfig renders the MCP configuration for Claude engine

type CloseDiscussionsConfig

type CloseDiscussionsConfig = CloseEntityConfig

type CloseEntityConfig

type CloseEntityConfig struct {
	BaseSafeOutputConfig             `yaml:",inline"`
	SafeOutputTargetConfig           `yaml:",inline"`
	SafeOutputFilterConfig           `yaml:",inline"`
	SafeOutputDiscussionFilterConfig `yaml:",inline"` // Only used for discussions
}

CloseEntityConfig holds the configuration for a close entity operation

type CloseEntityJobParams

type CloseEntityJobParams struct {
	EntityType       CloseEntityType
	ConfigKey        string // e.g., "close-issue", "close-pull-request"
	EnvVarPrefix     string // e.g., "GH_AW_CLOSE_ISSUE", "GH_AW_CLOSE_PR"
	JobName          string // e.g., "close_issue", "close_pull_request"
	StepName         string // e.g., "Close Issue", "Close Pull Request"
	OutputNumberKey  string // e.g., "issue_number", "pull_request_number"
	OutputURLKey     string // e.g., "issue_url", "pull_request_url"
	EventNumberPath1 string // e.g., "github.event.issue.number"
	EventNumberPath2 string // e.g., "github.event.comment.issue.number"
	PermissionsFunc  func() *Permissions
}

CloseEntityJobParams holds the parameters needed to build a close entity job

type CloseEntityType

type CloseEntityType string

CloseEntityType represents the type of entity being closed

const (
	CloseEntityIssue       CloseEntityType = "issue"
	CloseEntityPullRequest CloseEntityType = "pull_request"
	CloseEntityDiscussion  CloseEntityType = "discussion"
)

type CloseIssuesConfig

type CloseIssuesConfig = CloseEntityConfig

Type aliases for backward compatibility

type CloseJobConfig

type CloseJobConfig struct {
	SafeOutputTargetConfig `yaml:",inline"`
	SafeOutputFilterConfig `yaml:",inline"`
}

CloseJobConfig represents common configuration for close operations (close-issue, close-discussion, close-pull-request)

func ParseCloseJobConfig

func ParseCloseJobConfig(configMap map[string]any) (CloseJobConfig, bool)

ParseCloseJobConfig parses common close job fields from a config map. Returns the parsed CloseJobConfig and a boolean indicating if there was a validation error.

type ClosePullRequestsConfig

type ClosePullRequestsConfig = CloseEntityConfig

type CodexEngine

type CodexEngine struct {
	BaseEngine
}

CodexEngine represents the Codex agentic engine

func NewCodexEngine

func NewCodexEngine() *CodexEngine

func (*CodexEngine) GetDeclaredOutputFiles

func (e *CodexEngine) GetDeclaredOutputFiles() []string

GetDeclaredOutputFiles returns the output files that Codex may produce Codex (written in Rust) writes logs to ~/.codex/log/codex-tui.log

func (*CodexEngine) GetExecutionSteps

func (e *CodexEngine) GetExecutionSteps(workflowData *WorkflowData, logFile string) []GitHubActionStep

GetExecutionSteps returns the GitHub Actions steps for executing Codex

func (*CodexEngine) GetFirewallLogsCollectionStep

func (e *CodexEngine) GetFirewallLogsCollectionStep(workflowData *WorkflowData) []GitHubActionStep

GetFirewallLogsCollectionStep returns the step for collecting firewall logs (before secret redaction). This method is part of the firewall integration interface. It returns an empty slice because firewall logs are written to a known location (/tmp/gh-aw/sandbox/firewall/logs/) and don't need a separate collection step. The method is still called from compiler_yaml_main_job.go to maintain consistent behavior with other engines that may need log collection steps.

func (*CodexEngine) GetInstallationSteps

func (e *CodexEngine) GetInstallationSteps(workflowData *WorkflowData) []GitHubActionStep

func (*CodexEngine) GetLogParserScriptId

func (e *CodexEngine) GetLogParserScriptId() string

GetLogParserScriptId returns the JavaScript script name for parsing Codex logs

func (*CodexEngine) GetRequiredSecretNames

func (e *CodexEngine) GetRequiredSecretNames(workflowData *WorkflowData) []string

GetRequiredSecretNames returns the list of secrets required by the Codex engine This includes CODEX_API_KEY, OPENAI_API_KEY, and optionally MCP_GATEWAY_API_KEY

func (*CodexEngine) GetSquidLogsSteps

func (e *CodexEngine) GetSquidLogsSteps(workflowData *WorkflowData) []GitHubActionStep

GetSquidLogsSteps returns the steps for uploading and parsing Squid logs (after secret redaction)

func (*CodexEngine) ParseLogMetrics

func (e *CodexEngine) ParseLogMetrics(logContent string, verbose bool) LogMetrics

ParseLogMetrics implements engine-specific log parsing for Codex

func (*CodexEngine) RenderMCPConfig

func (e *CodexEngine) RenderMCPConfig(yaml *strings.Builder, tools map[string]any, mcpTools []string, workflowData *WorkflowData)

RenderMCPConfig generates MCP server configuration for Codex

type CodingAgentEngine

CodingAgentEngine is a composite interface that combines all focused interfaces This maintains backward compatibility with existing code while allowing more flexibility Implementations can choose to implement only the interfaces they need by embedding BaseEngine

type CommentEventMapping

type CommentEventMapping struct {
	EventName      string   // GitHub Actions event name (e.g., "issues", "issue_comment")
	Types          []string // Event types (e.g., ["opened", "edited", "reopened"])
	IsPRComment    bool     // True if this is pull_request_comment (issue_comment on PRs only)
	IsIssueComment bool     // True if this is issue_comment (issue_comment on issues only)
}

CommentEventMapping defines the mapping between event identifiers and their GitHub Actions event configurations

func FilterCommentEvents

func FilterCommentEvents(identifiers []string) []CommentEventMapping

FilterCommentEvents returns only the comment events specified by the identifiers If identifiers is nil or empty, returns all comment events

func GetAllCommentEvents

func GetAllCommentEvents() []CommentEventMapping

GetAllCommentEvents returns all possible comment-related events for command triggers

func GetCommentEventByIdentifier

func GetCommentEventByIdentifier(identifier string) *CommentEventMapping

GetCommentEventByIdentifier returns the event mapping for a given identifier Uses GitHub Actions event names (e.g., "issues", "issue_comment", "pull_request_comment", "pull_request", "pull_request_review_comment")

func MergeEventsForYAML

func MergeEventsForYAML(mappings []CommentEventMapping) []CommentEventMapping

MergeEventsForYAML merges comment events for YAML generation, combining pull_request_comment and issue_comment

type ComparisonNode

type ComparisonNode struct {
	Left     ConditionNode
	Operator string
	Right    ConditionNode
}

ComparisonNode represents comparison operations like ==, !=, <, >, <=, >=

func BuildActionEquals

func BuildActionEquals(action string) *ComparisonNode

BuildActionEquals creates a condition to check if the event action equals a specific value

func BuildComparison

func BuildComparison(left ConditionNode, operator string, right ConditionNode) *ComparisonNode

BuildComparison creates a comparison node with the specified operator

func BuildEquals

func BuildEquals(left ConditionNode, right ConditionNode) *ComparisonNode

BuildEquals creates an equality comparison

func BuildEventTypeEquals

func BuildEventTypeEquals(eventType string) *ComparisonNode

BuildEventTypeEquals creates a condition to check if the event type equals a specific value

func BuildNotEquals

func BuildNotEquals(left ConditionNode, right ConditionNode) *ComparisonNode

BuildNotEquals creates an inequality comparison

func BuildNotFromFork

func BuildNotFromFork() *ComparisonNode

BuildNotFromFork creates a condition to check that a pull request is not from a forked repository This prevents the job from running on forked PRs where write permissions are not available Uses repository ID comparison instead of full name for more reliable matching

func (*ComparisonNode) Render

func (c *ComparisonNode) Render() string

type Compiler

type Compiler struct {
	// contains filtered or unexported fields
}

Compiler handles converting markdown workflows to GitHub Actions YAML

func NewCompiler

func NewCompiler(opts ...CompilerOption) *Compiler

NewCompiler creates a new workflow compiler with functional options. By default, it auto-detects the version and action mode. Common options: WithVerbose, WithEngineOverride, WithCustomOutput, WithVersion, WithActionMode

func NewCompilerWithVersion

func NewCompilerWithVersion(version string) *Compiler

NewCompilerWithVersion creates a new workflow compiler with the legacy signature. Deprecated: Use NewCompiler with functional options instead. This function is kept for backward compatibility during migration.

func (*Compiler) BuildListSafeOutputJob

func (c *Compiler) BuildListSafeOutputJob(data *WorkflowData, mainJobName string, listJobConfig ListJobConfig, baseSafeOutputConfig BaseSafeOutputConfig, builderConfig ListJobBuilderConfig) (*Job, error)

BuildListSafeOutputJob builds a list-based safe-output job using shared logic. This consolidates the common builder pattern used by add-labels, assign-milestone, and assign-to-user.

func (*Compiler) CompileWorkflow

func (c *Compiler) CompileWorkflow(markdownPath string) error

CompileWorkflow compiles a workflow markdown file into a GitHub Actions YAML file. It reads the file from disk, parses frontmatter and markdown sections, and generates the corresponding workflow YAML. Returns the compiled workflow data or an error.

The compilation process includes:

  • Reading and parsing the markdown file
  • Extracting frontmatter configuration
  • Validating workflow configuration
  • Generating GitHub Actions YAML
  • Writing the compiled workflow to a .lock.yml file

This is the main entry point for compiling workflows from disk. For compiling pre-parsed workflow data, use CompileWorkflowData instead.

func (*Compiler) CompileWorkflowData

func (c *Compiler) CompileWorkflowData(workflowData *WorkflowData, markdownPath string) error

CompileWorkflowData compiles pre-parsed workflow content into GitHub Actions YAML. Unlike CompileWorkflow, this accepts already-parsed frontmatter and markdown content rather than reading from disk. This is useful for testing and programmatic workflow generation.

The compilation process includes:

  • Validating workflow configuration and features
  • Checking permissions and tool configurations
  • Generating GitHub Actions YAML structure
  • Writing the compiled workflow to a .lock.yml file

This function avoids re-parsing when workflow data has already been extracted, making it efficient for scenarios where the same workflow is compiled multiple times or when workflow data comes from a non-file source.

func (*Compiler) ExtractEngineConfig

func (c *Compiler) ExtractEngineConfig(frontmatter map[string]any) (string, *EngineConfig)

ExtractEngineConfig extracts engine configuration from frontmatter, supporting both string and object formats

func (*Compiler) GenerateDependabotManifests

func (c *Compiler) GenerateDependabotManifests(workflowDataList []*WorkflowData, workflowDir string, forceOverwrite bool) error

GenerateDependabotManifests generates manifest files and dependabot.yml for detected dependencies

func (*Compiler) GetActionMode

func (c *Compiler) GetActionMode() ActionMode

GetActionMode returns the current action mode

func (*Compiler) GetActionTag

func (c *Compiler) GetActionTag() string

GetActionTag returns the action tag override (empty if not set)

func (*Compiler) GetArtifactManager

func (c *Compiler) GetArtifactManager() *ArtifactManager

GetArtifactManager returns the artifact manager for tracking uploads/downloads

func (*Compiler) GetRepositorySlug

func (c *Compiler) GetRepositorySlug() string

GetRepositorySlug returns the repository slug

func (*Compiler) GetScheduleWarnings

func (c *Compiler) GetScheduleWarnings() []string

GetScheduleWarnings returns all accumulated schedule warnings for this compiler instance

func (*Compiler) GetSharedActionCache

func (c *Compiler) GetSharedActionCache() *ActionCache

GetSharedActionCache returns the shared action cache used by this compiler instance. The cache is lazily initialized on first access and shared across all workflows. This allows action SHA validation and other operations to reuse cached resolutions.

func (*Compiler) GetSharedActionResolverForTest

func (c *Compiler) GetSharedActionResolverForTest() (*ActionCache, *ActionResolver)

GetSharedActionResolverForTest exposes the shared action resolver for testing purposes This should only be used in tests

func (*Compiler) GetVersion

func (c *Compiler) GetVersion() string

GetVersion returns the version string used by the compiler

func (*Compiler) GetWarningCount

func (c *Compiler) GetWarningCount() int

GetWarningCount returns the current warning count

func (*Compiler) GetWorkflowIdentifier

func (c *Compiler) GetWorkflowIdentifier() string

GetWorkflowIdentifier returns the current workflow identifier

func (*Compiler) IncrementWarningCount

func (c *Compiler) IncrementWarningCount()

IncrementWarningCount increments the warning counter

func (*Compiler) MergeMCPServers

func (c *Compiler) MergeMCPServers(topMCPServers map[string]any, importedMCPServersJSON string) (map[string]any, error)

MergeMCPServers merges mcp-servers from imports with top-level mcp-servers Takes object maps and merges them directly

func (*Compiler) MergeNetworkPermissions

func (c *Compiler) MergeNetworkPermissions(topNetwork *NetworkPermissions, importedNetworkJSON string) (*NetworkPermissions, error)

MergeNetworkPermissions merges network permissions from imports with top-level network permissions Combines allowed domains from both sources into a single list

func (*Compiler) MergeSafeOutputs

func (c *Compiler) MergeSafeOutputs(topSafeOutputs *SafeOutputsConfig, importedSafeOutputsJSON []string) (*SafeOutputsConfig, error)

MergeSafeOutputs merges safe-outputs configurations from imports into the top-level safe-outputs Returns an error if a conflict is detected (same safe-output type defined in both main and imported)

func (*Compiler) MergeSecretMasking

func (c *Compiler) MergeSecretMasking(topConfig *SecretMaskingConfig, importedSecretMaskingJSON string) (*SecretMaskingConfig, error)

MergeSecretMasking merges secret-masking configurations from imports with top-level config

func (*Compiler) MergeTools

func (c *Compiler) MergeTools(topTools map[string]any, includedToolsJSON string) (map[string]any, error)

MergeTools merges two tools maps, combining allowed arrays when keys coincide Handles newline-separated JSON objects from multiple imports/includes

func (*Compiler) ParseWorkflowFile

func (c *Compiler) ParseWorkflowFile(markdownPath string) (*WorkflowData, error)

ParseWorkflowFile parses a workflow markdown file and returns a WorkflowData structure. This is the main orchestration function that coordinates all compilation phases.

func (*Compiler) ResetWarningCount

func (c *Compiler) ResetWarningCount()

ResetWarningCount resets the warning counter to zero

func (*Compiler) SetActionMode

func (c *Compiler) SetActionMode(mode ActionMode)

SetActionMode configures the action mode for JavaScript step generation

func (*Compiler) SetActionTag

func (c *Compiler) SetActionTag(tag string)

SetActionTag sets the action tag override for actions/setup

func (*Compiler) SetFileTracker

func (c *Compiler) SetFileTracker(tracker FileTracker)

SetFileTracker sets the file tracker for tracking created files

func (*Compiler) SetForceRefreshActionPins

func (c *Compiler) SetForceRefreshActionPins(force bool)

SetForceRefreshActionPins configures whether to force refresh of action pins

func (*Compiler) SetNoEmit

func (c *Compiler) SetNoEmit(noEmit bool)

SetNoEmit configures whether to validate without generating lock files

func (*Compiler) SetQuiet

func (c *Compiler) SetQuiet(quiet bool)

SetQuiet configures whether to suppress success messages (for interactive mode)

func (*Compiler) SetRefreshStopTime

func (c *Compiler) SetRefreshStopTime(refresh bool)

SetRefreshStopTime configures whether to force regeneration of stop-after times

func (*Compiler) SetRepositorySlug

func (c *Compiler) SetRepositorySlug(slug string)

SetRepositorySlug sets the repository slug for schedule scattering

func (*Compiler) SetSkipValidation

func (c *Compiler) SetSkipValidation(skip bool)

SetSkipValidation configures whether to skip schema validation

func (*Compiler) SetStrictMode

func (c *Compiler) SetStrictMode(strict bool)

SetStrictMode configures whether to enable strict validation mode

func (*Compiler) SetTrialLogicalRepoSlug

func (c *Compiler) SetTrialLogicalRepoSlug(repo string)

SetTrialLogicalRepoSlug configures the target repository for trial mode

func (*Compiler) SetTrialMode

func (c *Compiler) SetTrialMode(trialMode bool)

SetTrialMode configures whether to run in trial mode (suppresses safe outputs)

func (*Compiler) SetWorkflowIdentifier

func (c *Compiler) SetWorkflowIdentifier(identifier string)

SetWorkflowIdentifier sets the identifier for the current workflow being compiled This is used for deterministic schedule scattering

func (*Compiler) ValidateIncludedPermissions

func (c *Compiler) ValidateIncludedPermissions(topPermissionsYAML string, importedPermissionsJSON string) error

ValidateIncludedPermissions validates that the main workflow permissions satisfy the imported workflow requirements This function is specifically used when merging included/imported workflow files to ensure the main workflow has sufficient permissions to support the requirements from all imported files. Takes the top-level permissions YAML string and imported permissions JSON string Returns an error if the main workflow permissions are insufficient

Use ValidatePermissions (in permissions_validator.go) for general permission validation against GitHub MCP toolsets. Use ValidateIncludedPermissions (this function) when validating permissions from included/imported workflow files.

type CompilerOption

type CompilerOption func(*Compiler)

CompilerOption is a functional option for configuring a Compiler

func WithActionMode

func WithActionMode(mode ActionMode) CompilerOption

WithActionMode overrides the auto-detected action mode

func WithCustomOutput

func WithCustomOutput(path string) CompilerOption

WithCustomOutput sets a custom output path for the compiled workflow

func WithEngineOverride

func WithEngineOverride(engine string) CompilerOption

WithEngineOverride sets the AI engine override

func WithFailFast

func WithFailFast(failFast bool) CompilerOption

WithFailFast configures whether to stop at first validation error

func WithForceRefreshActionPins

func WithForceRefreshActionPins(force bool) CompilerOption

WithForceRefreshActionPins configures whether to force refresh of action pins

func WithGitRoot added in v0.43.0

func WithGitRoot(gitRoot string) CompilerOption

WithGitRoot sets the git repository root directory for action cache path

func WithNoEmit

func WithNoEmit(noEmit bool) CompilerOption

WithNoEmit configures whether to validate without generating lock files

func WithRepositorySlug

func WithRepositorySlug(slug string) CompilerOption

WithRepositorySlug sets the repository slug for schedule scattering

func WithSkipValidation

func WithSkipValidation(skip bool) CompilerOption

WithSkipValidation configures whether to skip schema validation

func WithStrictMode

func WithStrictMode(strict bool) CompilerOption

WithStrictMode configures whether to enable strict validation mode

func WithVerbose

func WithVerbose(verbose bool) CompilerOption

WithVerbose sets the verbose logging flag

func WithVersion

func WithVersion(version string) CompilerOption

WithVersion overrides the auto-detected version

func WithWorkflowIdentifier

func WithWorkflowIdentifier(identifier string) CompilerOption

WithWorkflowIdentifier sets the identifier for the current workflow being compiled

type ConditionNode

type ConditionNode interface {
	Render() string
}

ConditionNode represents a node in a condition expression tree

func BuildAnd

func BuildAnd(left ConditionNode, right ConditionNode) ConditionNode

BuildAnd creates an AND node combining two conditions

func BuildConditionTree

func BuildConditionTree(existingCondition string, draftCondition string) ConditionNode

BuildConditionTree creates a condition tree from existing if condition and new draft condition

func BuildFromAllowedForks

func BuildFromAllowedForks(allowedForks []string) ConditionNode

BuildFromAllowedForks creates a condition to check if a pull request is from an allowed fork Supports glob patterns like "org/*" and exact matches like "org/repo"

func BuildOr

func BuildOr(left ConditionNode, right ConditionNode) ConditionNode

BuildOr creates an OR node combining two conditions

func BuildPRCommentCondition

func BuildPRCommentCondition() ConditionNode

BuildPRCommentCondition creates a condition to check if the event is a comment on a pull request This checks for: - issue_comment on a PR (github.event.issue.pull_request != null) - pull_request_review_comment - pull_request_review

func BuildReactionCondition

func BuildReactionCondition() ConditionNode

BuildReactionCondition creates a condition tree for the add_reaction job

func BuildSafeOutputType

func BuildSafeOutputType(outputType string) ConditionNode

func ParseExpression

func ParseExpression(expression string) (ConditionNode, error)

ParseExpression parses a string expression into a ConditionNode tree Supports && (AND), || (OR), ! (NOT), and parentheses for grouping Example: "condition1 && (condition2 || !condition3)"

type ConfigurationError

type ConfigurationError struct {
	ConfigKey  string
	Value      string
	Reason     string
	Suggestion string
	Timestamp  time.Time
}

ConfigurationError represents an error in safe-outputs configuration

func NewConfigurationError

func NewConfigurationError(configKey, value, reason, suggestion string) *ConfigurationError

NewConfigurationError creates a new configuration error with context

func (*ConfigurationError) Error

func (e *ConfigurationError) Error() string

Error implements the error interface

type ContainsNode

type ContainsNode struct {
	Array ConditionNode
	Value ConditionNode
}

ContainsNode represents array membership checks using contains() function

func BuildContains

func BuildContains(array ConditionNode, value ConditionNode) *ContainsNode

BuildContains creates a contains() function call node

func BuildLabelContains

func BuildLabelContains(labelName string) *ContainsNode

BuildLabelContains creates a condition to check if an issue/PR contains a specific label

func (*ContainsNode) Render

func (c *ContainsNode) Render() string

type CopilotEngine

type CopilotEngine struct {
	BaseEngine
}

CopilotEngine represents the GitHub Copilot CLI agentic engine. It provides integration with GitHub Copilot CLI for agentic workflows, including MCP server support, sandboxing (AWF/SRT), and tool permissions.

func NewCopilotEngine

func NewCopilotEngine() *CopilotEngine

func (*CopilotEngine) GetCleanupStep

func (e *CopilotEngine) GetCleanupStep(workflowData *WorkflowData) GitHubActionStep

GetCleanupStep returns the post-execution cleanup step (currently empty)

func (*CopilotEngine) GetDeclaredOutputFiles

func (e *CopilotEngine) GetDeclaredOutputFiles() []string

func (*CopilotEngine) GetDefaultDetectionModel

func (e *CopilotEngine) GetDefaultDetectionModel() string

GetDefaultDetectionModel returns the default model for threat detection Uses gpt-5.1-codex-mini as a cost-effective model for detection tasks (replacement for deprecated gpt-5-mini)

func (*CopilotEngine) GetExecutionSteps

func (e *CopilotEngine) GetExecutionSteps(workflowData *WorkflowData, logFile string) []GitHubActionStep

GetExecutionSteps returns the GitHub Actions steps for executing GitHub Copilot CLI

func (*CopilotEngine) GetFirewallLogsCollectionStep

func (e *CopilotEngine) GetFirewallLogsCollectionStep(workflowData *WorkflowData) []GitHubActionStep

GetFirewallLogsCollectionStep returns steps for collecting firewall logs and copying session state files

func (*CopilotEngine) GetInstallationSteps

func (e *CopilotEngine) GetInstallationSteps(workflowData *WorkflowData) []GitHubActionStep

GetInstallationSteps generates the complete installation workflow for Copilot CLI. This includes secret validation, Node.js setup, sandbox installation (SRT or AWF), and Copilot CLI installation. The installation order is critical: 1. Secret validation 2. Node.js setup 3. Sandbox installation (SRT or AWF, if needed) 4. Copilot CLI installation

If a custom command is specified in the engine configuration, this function returns an empty list of steps, skipping the standard installation process.

func (*CopilotEngine) GetLogFileForParsing

func (e *CopilotEngine) GetLogFileForParsing() string

GetLogFileForParsing returns the log directory for Copilot CLI logs Copilot writes detailed debug logs to /tmp/gh-aw/sandbox/agent/logs/

func (*CopilotEngine) GetLogParserScriptId

func (e *CopilotEngine) GetLogParserScriptId() string

GetLogParserScriptId returns the JavaScript script name for parsing Copilot logs

func (*CopilotEngine) GetRequiredSecretNames

func (e *CopilotEngine) GetRequiredSecretNames(workflowData *WorkflowData) []string

GetRequiredSecretNames returns the list of secrets required by the Copilot engine This includes COPILOT_GITHUB_TOKEN and optionally MCP_GATEWAY_API_KEY

func (*CopilotEngine) GetSquidLogsSteps

func (e *CopilotEngine) GetSquidLogsSteps(workflowData *WorkflowData) []GitHubActionStep

GetSquidLogsSteps returns the steps for uploading and parsing Squid logs (after secret redaction)

func (*CopilotEngine) ParseLogMetrics

func (e *CopilotEngine) ParseLogMetrics(logContent string, verbose bool) LogMetrics

ParseLogMetrics implements engine-specific log parsing for Copilot CLI.

Parsing Strategy: 1. First attempts to parse as JSONL session format (from ~/.copilot/session-state/*.jsonl) 2. Falls back to debug log format if JSONL parsing fails or finds no entries

Token Counting Behavior: Copilot CLI makes multiple API calls during a workflow run (one per turn). Each API call returns a response with usage statistics including token counts. This function accumulates token counts from ALL API responses to get the total token usage for the entire workflow run.

Example: If a run has 3 turns with token counts [1000, 1500, 800], the total token usage will be 3300 (sum of all turns).

This matches the behavior of the JavaScript parser in parse_copilot_log.cjs.

func (*CopilotEngine) RenderMCPConfig

func (e *CopilotEngine) RenderMCPConfig(yaml *strings.Builder, tools map[string]any, mcpTools []string, workflowData *WorkflowData)

RenderMCPConfig generates MCP server configuration for Copilot CLI

type CopilotParticipantConfig

type CopilotParticipantConfig struct {
	// Participants is the list of users/bots to assign/review
	Participants []string
	// ParticipantType is either "assignee" or "reviewer"
	ParticipantType string
	// CustomToken is the custom GitHub token from the safe output config
	CustomToken string
	// SafeOutputsToken is the GitHub token from the safe-outputs config
	SafeOutputsToken string
	// WorkflowToken is the top-level GitHub token from the workflow
	WorkflowToken string
	// ConditionStepID is the step ID to check for output (e.g., "create_issue", "create_pull_request")
	ConditionStepID string
	// ConditionOutputKey is the output key to check (e.g., "issue_number", "pull_request_url")
	ConditionOutputKey string
}

CopilotParticipantConfig holds configuration for generating Copilot participant steps

type CreateAgentSessionConfig

type CreateAgentSessionConfig struct {
	BaseSafeOutputConfig `yaml:",inline"`
	Base                 string   `yaml:"base,omitempty"`          // Base branch for the pull request
	TargetRepoSlug       string   `yaml:"target-repo,omitempty"`   // Target repository in format "owner/repo" for cross-repository agent sessions
	AllowedRepos         []string `yaml:"allowed-repos,omitempty"` // List of additional repositories that agent sessions can be created in (additionally to the target-repo)
}

CreateAgentSessionConfig holds configuration for creating GitHub Copilot agent sessions from agent output

type CreateCodeScanningAlertsConfig

type CreateCodeScanningAlertsConfig struct {
	BaseSafeOutputConfig `yaml:",inline"`
	Driver               string `yaml:"driver,omitempty"` // Driver name for SARIF tool.driver.name field (default: "GitHub Agentic Workflows Security Scanner")
}

CreateCodeScanningAlertsConfig holds configuration for creating repository security advisories (SARIF format) from agent output

type CreateDiscussionsConfig

type CreateDiscussionsConfig struct {
	BaseSafeOutputConfig  `yaml:",inline"`
	TitlePrefix           string   `yaml:"title-prefix,omitempty"`
	Category              string   `yaml:"category,omitempty"`                // Discussion category ID or name
	Labels                []string `yaml:"labels,omitempty"`                  // Labels to attach to discussions and match when closing older ones
	AllowedLabels         []string `yaml:"allowed-labels,omitempty"`          // Optional list of allowed labels. If omitted, any labels are allowed (including creating new ones).
	TargetRepoSlug        string   `yaml:"target-repo,omitempty"`             // Target repository in format "owner/repo" for cross-repository discussions
	AllowedRepos          []string `yaml:"allowed-repos,omitempty"`           // List of additional repositories that discussions can be created in
	CloseOlderDiscussions bool     `yaml:"close-older-discussions,omitempty"` // When true, close older discussions with same title prefix or labels as outdated
	RequiredCategory      string   `yaml:"required-category,omitempty"`       // Required category for matching when close-older-discussions is enabled
	Expires               int      `yaml:"expires,omitempty"`                 // Hours until the discussion expires and should be automatically closed
	FallbackToIssue       *bool    `yaml:"fallback-to-issue,omitempty"`       // When true (default), fallback to create-issue if discussion creation fails due to permissions
	Footer                *bool    `yaml:"footer,omitempty"`                  // Controls whether AI-generated footer is added. When false, visible footer is omitted but XML markers are kept.
}

CreateDiscussionsConfig holds configuration for creating GitHub discussions from agent output

type CreateIssuesConfig

type CreateIssuesConfig struct {
	BaseSafeOutputConfig `yaml:",inline"`
	TitlePrefix          string   `yaml:"title-prefix,omitempty"`
	Labels               []string `yaml:"labels,omitempty"`
	AllowedLabels        []string `yaml:"allowed-labels,omitempty"`     // Optional list of allowed labels. If omitted, any labels are allowed (including creating new ones).
	Assignees            []string `yaml:"assignees,omitempty"`          // List of users/bots to assign the issue to
	TargetRepoSlug       string   `yaml:"target-repo,omitempty"`        // Target repository in format "owner/repo" for cross-repository issues
	AllowedRepos         []string `yaml:"allowed-repos,omitempty"`      // List of additional repositories that issues can be created in
	CloseOlderIssues     bool     `yaml:"close-older-issues,omitempty"` // When true, close older issues with same title prefix or labels as "not planned"
	Expires              int      `yaml:"expires,omitempty"`            // Hours until the issue expires and should be automatically closed
	Group                bool     `yaml:"group,omitempty"`              // If true, group issues as sub-issues under a parent issue (workflow ID is used as group identifier)
	Footer               *bool    `yaml:"footer,omitempty"`             // Controls whether AI-generated footer is added. When false, visible footer is omitted but XML markers are kept.
}

CreateIssuesConfig holds configuration for creating GitHub issues from agent output

type CreateProjectStatusUpdateConfig

type CreateProjectStatusUpdateConfig struct {
	BaseSafeOutputConfig
	GitHubToken string `yaml:"github-token,omitempty"` // Optional custom GitHub token for project status updates
	Project     string `yaml:"project,omitempty"`      // Optional default project URL for status updates
}

CreateProjectStatusUpdateConfig holds configuration for creating GitHub project status updates

type CreateProjectsConfig

type CreateProjectsConfig struct {
	BaseSafeOutputConfig `yaml:",inline"`
	GitHubToken          string                   `yaml:"github-token,omitempty"`
	TargetOwner          string                   `yaml:"target-owner,omitempty"`      // Default target owner (org/user) for the new project
	TitlePrefix          string                   `yaml:"title-prefix,omitempty"`      // Default prefix for auto-generated project titles
	Views                []ProjectView            `yaml:"views,omitempty"`             // Project views to create automatically after project creation
	FieldDefinitions     []ProjectFieldDefinition `yaml:"field-definitions,omitempty"` // Project field definitions to create automatically after project creation
}

CreateProjectsConfig holds configuration for creating GitHub Projects V2

type CreatePullRequestReviewCommentsConfig

type CreatePullRequestReviewCommentsConfig struct {
	BaseSafeOutputConfig `yaml:",inline"`
	Side                 string   `yaml:"side,omitempty"`          // Side of the diff: "LEFT" or "RIGHT" (default: "RIGHT")
	Target               string   `yaml:"target,omitempty"`        // Target for comments: "triggering" (default), "*" (any PR), or explicit PR number
	TargetRepoSlug       string   `yaml:"target-repo,omitempty"`   // Target repository in format "owner/repo" for cross-repository PR review comments
	AllowedRepos         []string `yaml:"allowed-repos,omitempty"` // List of additional repositories that PR review comments can be added to (additionally to the target-repo)
}

CreatePullRequestReviewCommentsConfig holds configuration for creating GitHub pull request review comments from agent output

type CreatePullRequestsConfig

type CreatePullRequestsConfig struct {
	BaseSafeOutputConfig `yaml:",inline"`
	TitlePrefix          string   `yaml:"title-prefix,omitempty"`
	Labels               []string `yaml:"labels,omitempty"`
	AllowedLabels        []string `yaml:"allowed-labels,omitempty"`    // Optional list of allowed labels. If omitted, any labels are allowed (including creating new ones).
	Reviewers            []string `yaml:"reviewers,omitempty"`         // List of users/bots to assign as reviewers to the pull request
	Draft                *bool    `yaml:"draft,omitempty"`             // Pointer to distinguish between unset (nil) and explicitly false
	IfNoChanges          string   `yaml:"if-no-changes,omitempty"`     // Behavior when no changes to push: "warn" (default), "error", or "ignore"
	AllowEmpty           bool     `yaml:"allow-empty,omitempty"`       // Allow creating PR without patch file or with empty patch (useful for preparing feature branches)
	TargetRepoSlug       string   `yaml:"target-repo,omitempty"`       // Target repository in format "owner/repo" for cross-repository pull requests
	AllowedRepos         []string `yaml:"allowed-repos,omitempty"`     // List of additional repositories that pull requests can be created in (additionally to the target-repo)
	Expires              int      `yaml:"expires,omitempty"`           // Hours until the pull request expires and should be automatically closed (only for same-repo PRs)
	AutoMerge            bool     `yaml:"auto-merge,omitempty"`        // Enable auto-merge for the pull request when all required checks pass
	BaseBranch           string   `yaml:"base-branch,omitempty"`       // Base branch for the pull request (defaults to github.ref_name if not specified)
	Footer               *bool    `yaml:"footer,omitempty"`            // Controls whether AI-generated footer is added. When false, visible footer is omitted but XML markers are kept.
	FallbackAsIssue      *bool    `yaml:"fallback-as-issue,omitempty"` // When true (default), creates an issue if PR creation fails. When false, no fallback occurs and issues: write permission is not requested.
}

CreatePullRequestsConfig holds configuration for creating GitHub pull requests from agent output

type CustomEngine

type CustomEngine struct {
	BaseEngine
}

CustomEngine represents a custom agentic engine that executes user-defined GitHub Actions steps

func NewCustomEngine

func NewCustomEngine() *CustomEngine

NewCustomEngine creates a new CustomEngine instance

func (*CustomEngine) GetExecutionSteps

func (e *CustomEngine) GetExecutionSteps(workflowData *WorkflowData, logFile string) []GitHubActionStep

GetExecutionSteps returns the GitHub Actions steps for executing custom steps

func (*CustomEngine) GetInstallationSteps

func (e *CustomEngine) GetInstallationSteps(workflowData *WorkflowData) []GitHubActionStep

GetInstallationSteps returns empty installation steps since custom engine doesn't need installation

func (*CustomEngine) GetLogParserScriptId

func (e *CustomEngine) GetLogParserScriptId() string

GetLogParserScriptId returns the JavaScript script name for parsing custom engine logs

func (*CustomEngine) GetRequiredSecretNames

func (e *CustomEngine) GetRequiredSecretNames(workflowData *WorkflowData) []string

GetRequiredSecretNames returns empty for custom engine as secrets depend on user-defined steps Custom engine steps should explicitly reference the secrets they need

func (*CustomEngine) ParseLogMetrics

func (e *CustomEngine) ParseLogMetrics(logContent string, verbose bool) LogMetrics

ParseLogMetrics implements basic log parsing for custom engine For custom engines, try both Claude and Codex parsing approaches to extract turn information

func (*CustomEngine) RenderMCPConfig

func (e *CustomEngine) RenderMCPConfig(yaml *strings.Builder, tools map[string]any, mcpTools []string, workflowData *WorkflowData)

RenderMCPConfig renders MCP configuration using unified renderer

type DependabotConfig

type DependabotConfig struct {
	Version int                     `yaml:"version"`
	Updates []DependabotUpdateEntry `yaml:"updates"`
}

DependabotConfig represents the structure of .github/dependabot.yml

type DependabotUpdateEntry

type DependabotUpdateEntry struct {
	PackageEcosystem string `yaml:"package-ecosystem"`
	Directory        string `yaml:"directory"`
	Schedule         struct {
		Interval string `yaml:"interval"`
	} `yaml:"schedule"`
}

DependabotUpdateEntry represents a single update configuration in dependabot.yml

type DisjunctionNode

type DisjunctionNode struct {
	Terms     []ConditionNode
	Multiline bool // If true, render each term on separate line with comments
}

DisjunctionNode represents an OR operation with multiple terms to avoid deep nesting

func BuildDisjunction

func BuildDisjunction(multiline bool, terms ...ConditionNode) *DisjunctionNode

BuildDisjunction creates a disjunction node (OR operation) from the given terms Handles arrays of size 0, 1, or more correctly The multiline parameter controls whether to render each term on a separate line

func (*DisjunctionNode) Render

func (d *DisjunctionNode) Render() string

func (*DisjunctionNode) RenderMultiline

func (d *DisjunctionNode) RenderMultiline() string

RenderMultiline renders the disjunction with each term on a separate line, including comments for expressions that have descriptions

type DispatchWorkflowConfig

type DispatchWorkflowConfig struct {
	BaseSafeOutputConfig `yaml:",inline"`
	Workflows            []string          `yaml:"workflows,omitempty"`      // List of workflow names (without .md extension) to allow dispatching
	WorkflowFiles        map[string]string `yaml:"workflow_files,omitempty"` // Map of workflow name to file extension (.lock.yml or .yml) - populated at compile time
}

DispatchWorkflowConfig holds configuration for dispatching workflows from agent output

type EditToolConfig

type EditToolConfig struct {
}

EditToolConfig represents the configuration for the edit tool

type Engine

type Engine interface {
	// GetID returns the unique identifier for this engine
	GetID() string

	// GetDisplayName returns the human-readable name for this engine
	GetDisplayName() string

	// GetDescription returns a description of this engine's capabilities
	GetDescription() string

	// IsExperimental returns true if this engine is experimental
	IsExperimental() bool
}

Engine represents the core identity of an AI coding agent All engines must implement this interface to provide basic identification

type EngineConfig

type EngineConfig struct {
	ID          string
	Version     string
	Model       string
	MaxTurns    string
	Concurrency string // Agent job-level concurrency configuration (YAML format)
	UserAgent   string
	Command     string // Custom executable path (when set, skip installation steps)
	Env         map[string]string
	Steps       []map[string]any
	Config      string
	Args        []string
	Firewall    *FirewallConfig // AWF firewall configuration
	Agent       string          // Agent identifier for copilot --agent flag (copilot engine only)
}

EngineConfig represents the parsed engine configuration

type EngineInstallConfig

type EngineInstallConfig struct {
	// Secrets is a list of secret names to validate (at least one must be set)
	Secrets []string
	// DocsURL is the documentation URL shown when secret validation fails
	DocsURL string
	// NpmPackage is the npm package name (e.g., "@github/copilot")
	NpmPackage string
	// Version is the default version of the npm package
	Version string
	// Name is the engine display name for secret validation messages (e.g., "Claude Code")
	Name string
	// CliName is the CLI name used for cache key prefix (e.g., "copilot")
	CliName string
	// InstallStepName is the display name for the npm install step (e.g., "Install Claude Code CLI")
	InstallStepName string
}

EngineInstallConfig contains configuration for engine installation steps. This struct centralizes the configuration needed to generate the common installation steps shared by all engines (secret validation and npm installation).

type EngineNetworkConfig

type EngineNetworkConfig struct {
	Engine  *EngineConfig
	Network *NetworkPermissions
}

EngineNetworkConfig combines engine configuration with top-level network permissions

type EngineRegistry

type EngineRegistry struct {
	// contains filtered or unexported fields
}

EngineRegistry manages available agentic engines

func GetGlobalEngineRegistry

func GetGlobalEngineRegistry() *EngineRegistry

GetGlobalEngineRegistry returns the singleton engine registry

func NewEngineRegistry

func NewEngineRegistry() *EngineRegistry

NewEngineRegistry creates a new engine registry with built-in engines

func (*EngineRegistry) GetAllEngines

func (r *EngineRegistry) GetAllEngines() []CodingAgentEngine

GetAllEngines returns all registered engines

func (*EngineRegistry) GetDefaultEngine

func (r *EngineRegistry) GetDefaultEngine() CodingAgentEngine

GetDefaultEngine returns the default engine (Copilot)

func (*EngineRegistry) GetEngine

func (r *EngineRegistry) GetEngine(id string) (CodingAgentEngine, error)

GetEngine retrieves an engine by ID

func (*EngineRegistry) GetEngineByPrefix

func (r *EngineRegistry) GetEngineByPrefix(prefix string) (CodingAgentEngine, error)

GetEngineByPrefix returns an engine that matches the given prefix This is useful for backward compatibility with strings like "codex-experimental"

func (*EngineRegistry) GetSupportedEngines

func (r *EngineRegistry) GetSupportedEngines() []string

GetSupportedEngines returns a list of all supported engine IDs

func (*EngineRegistry) IsValidEngine

func (r *EngineRegistry) IsValidEngine(id string) bool

IsValidEngine checks if an engine ID is valid

func (*EngineRegistry) Register

func (r *EngineRegistry) Register(engine CodingAgentEngine)

Register adds an engine to the registry

type ErrorCollector

type ErrorCollector struct {
	// contains filtered or unexported fields
}

ErrorCollector collects multiple validation errors

func NewErrorCollector

func NewErrorCollector(failFast bool) *ErrorCollector

NewErrorCollector creates a new error collector If failFast is true, the collector will stop at the first error

func (*ErrorCollector) Add

func (c *ErrorCollector) Add(err error) error

Add adds an error to the collector If failFast is enabled, returns the error immediately Otherwise, adds it to the collection and returns nil

func (*ErrorCollector) Count

func (c *ErrorCollector) Count() int

Count returns the number of errors collected

func (*ErrorCollector) Error

func (c *ErrorCollector) Error() error

Error returns the aggregated error using errors.Join Returns nil if no errors were collected

func (*ErrorCollector) FormattedError

func (c *ErrorCollector) FormattedError(category string) error

FormattedError returns the aggregated error with a formatted header showing the count Returns nil if no errors were collected This method is preferred over Error() + FormatAggregatedError for better accuracy

func (*ErrorCollector) HasErrors

func (c *ErrorCollector) HasErrors() bool

HasErrors returns true if any errors have been collected

type ExpressionExtractor

type ExpressionExtractor struct {
	// contains filtered or unexported fields
}

ExpressionExtractor extracts GitHub Actions expressions from markdown content and creates environment variable mappings for them

func NewExpressionExtractor

func NewExpressionExtractor() *ExpressionExtractor

NewExpressionExtractor creates a new ExpressionExtractor

func (*ExpressionExtractor) ExtractExpressions

func (e *ExpressionExtractor) ExtractExpressions(markdown string) ([]*ExpressionMapping, error)

ExtractExpressions extracts all ${{ ... }} expressions from the markdown content and creates environment variable mappings for each unique expression

func (*ExpressionExtractor) GetMappings

func (e *ExpressionExtractor) GetMappings() []*ExpressionMapping

GetMappings returns all expression mappings

func (*ExpressionExtractor) ReplaceExpressionsWithEnvVars

func (e *ExpressionExtractor) ReplaceExpressionsWithEnvVars(markdown string) string

ReplaceExpressionsWithEnvVars replaces all ${{ ... }} expressions in the markdown with references to their corresponding environment variables using placeholder format

type ExpressionMapping

type ExpressionMapping struct {
	Original string // The original ${{ ... }} expression
	EnvVar   string // The GH_AW_ prefixed environment variable name
	Content  string // The expression content without ${{ }}
}

ExpressionMapping represents a mapping between a GitHub expression and its environment variable

type ExpressionNode

type ExpressionNode struct {
	Expression  string
	Description string // Optional comment/description for the expression
}

ExpressionNode represents a leaf expression

func BuildExpressionWithDescription

func BuildExpressionWithDescription(expression, description string) *ExpressionNode

BuildExpressionWithDescription creates an expression node with an optional description

func BuildNullLiteral

func BuildNullLiteral() *ExpressionNode

BuildNullLiteral creates a null literal node

func (*ExpressionNode) Render

func (e *ExpressionNode) Render() string

type ExpressionParser

type ExpressionParser struct {
	// contains filtered or unexported fields
}

ExpressionParser handles parsing of expression strings into ConditionNode trees

type ExpressionValidationOptions

type ExpressionValidationOptions struct {
	NeedsStepsRe            *regexp.Regexp
	InputsRe                *regexp.Regexp
	WorkflowCallInputsRe    *regexp.Regexp
	AwInputsRe              *regexp.Regexp
	EnvRe                   *regexp.Regexp
	UnauthorizedExpressions *[]string
}

ExpressionValidationOptions contains the options for validating a single expression

type FieldParsingMode

type FieldParsingMode int

FieldParsingMode determines how boolean fields are parsed from the config

const (
	// FieldParsingKeyExistence mode: Field presence (even if nil) indicates it can be updated
	// Used by update-issue and update-discussion
	FieldParsingKeyExistence FieldParsingMode = iota
	// FieldParsingBoolValue mode: Field's boolean value determines if it can be updated.
	// Special case: nil values are treated as true for backward compatibility.
	// Used by body/footer fields in all update entities.
	FieldParsingBoolValue
)

type FieldValidation

type FieldValidation struct {
	Required                 bool     `json:"required,omitempty"`
	Type                     string   `json:"type,omitempty"`
	Sanitize                 bool     `json:"sanitize,omitempty"`
	MaxLength                int      `json:"maxLength,omitempty"`
	PositiveInteger          bool     `json:"positiveInteger,omitempty"`
	OptionalPositiveInteger  bool     `json:"optionalPositiveInteger,omitempty"`
	IssueOrPRNumber          bool     `json:"issueOrPRNumber,omitempty"`
	IssueNumberOrTemporaryID bool     `json:"issueNumberOrTemporaryId,omitempty"`
	Enum                     []string `json:"enum,omitempty"`
	ItemType                 string   `json:"itemType,omitempty"`
	ItemSanitize             bool     `json:"itemSanitize,omitempty"`
	ItemMaxLength            int      `json:"itemMaxLength,omitempty"`
	Pattern                  string   `json:"pattern,omitempty"`
	PatternError             string   `json:"patternError,omitempty"`
	TemporaryID              bool     `json:"temporaryId,omitempty"`
}

FieldValidation defines validation rules for a single field

type FileTracker

type FileTracker interface {
	TrackCreated(filePath string)
}

FileTracker interface for tracking files created during compilation

type FinalizeToolMetricsOptions

type FinalizeToolMetricsOptions struct {
	Metrics         *LogMetrics
	ToolCallMap     map[string]*ToolCallInfo
	CurrentSequence []string
	Turns           int
	TokenUsage      int
}

FinalizeToolMetricsOptions holds the options for FinalizeToolMetrics

type FirewallConfig

type FirewallConfig struct {
	Enabled       bool     `yaml:"enabled,omitempty"`        // Enable/disable AWF (default: true for copilot when network restrictions present)
	Version       string   `yaml:"version,omitempty"`        // AWF version (empty = latest)
	Args          []string `yaml:"args,omitempty"`           // Additional arguments to pass to AWF
	LogLevel      string   `yaml:"log_level,omitempty"`      // AWF log level (default: "info")
	CleanupScript string   `yaml:"cleanup_script,omitempty"` // Cleanup script path (default: "./scripts/ci/cleanup.sh")
	SSLBump       bool     `yaml:"ssl_bump,omitempty"`       // AWF-only: Enable SSL Bump for HTTPS content inspection (allows URL path filtering)
	AllowURLs     []string `yaml:"allow_urls,omitempty"`     // AWF-only: URL patterns to allow for HTTPS (requires SSLBump), e.g., "https://github.com/githubnext/*"
}

FirewallConfig represents AWF (gh-aw-firewall) configuration for network egress control. These settings are specific to the AWF sandbox and do not apply to Sandbox Runtime (SRT).

type FrontmatterConfig

type FrontmatterConfig struct {
	// Core workflow fields
	Name           string   `json:"name,omitempty"`
	Description    string   `json:"description,omitempty"`
	Engine         string   `json:"engine,omitempty"`
	Source         string   `json:"source,omitempty"`
	TrackerID      string   `json:"tracker-id,omitempty"`
	Version        string   `json:"version,omitempty"`
	TimeoutMinutes int      `json:"timeout-minutes,omitempty"`
	Strict         *bool    `json:"strict,omitempty"` // Pointer to distinguish unset from false
	Labels         []string `json:"labels,omitempty"`

	// Configuration sections - using strongly-typed structs
	Tools            *ToolsConfig       `json:"tools,omitempty"`
	MCPServers       map[string]any     `json:"mcp-servers,omitempty"` // Legacy field, use Tools instead
	RuntimesTyped    *RuntimesConfig    `json:"-"`                     // New typed field (not in JSON to avoid conflict)
	Runtimes         map[string]any     `json:"runtimes,omitempty"`    // Deprecated: use RuntimesTyped
	Jobs             map[string]any     `json:"jobs,omitempty"`        // Custom workflow jobs (too dynamic to type)
	SafeOutputs      *SafeOutputsConfig `json:"safe-outputs,omitempty"`
	SafeInputs       *SafeInputsConfig  `json:"safe-inputs,omitempty"`
	PermissionsTyped *PermissionsConfig `json:"-"` // New typed field (not in JSON to avoid conflict)

	// Event and trigger configuration
	On          map[string]any `json:"on,omitempty"`          // Complex trigger config with many variants (too dynamic to type)
	Permissions map[string]any `json:"permissions,omitempty"` // Deprecated: use PermissionsTyped (can be string or map)
	Concurrency map[string]any `json:"concurrency,omitempty"`
	If          string         `json:"if,omitempty"`

	// Network and sandbox configuration
	Network *NetworkPermissions `json:"network,omitempty"`
	Sandbox *SandboxConfig      `json:"sandbox,omitempty"`

	// Plugin configuration
	// Supports both array format ([]string) and object format (PluginsConfig)
	// This field is handled specially in parsing to support both formats
	Plugins      any            `json:"plugins,omitempty"` // Can be []string or map[string]any
	PluginsTyped *PluginsConfig `json:"-"`                 // Typed plugin configuration (not in JSON)
	PluginsRepos []string       `json:"-"`                 // Extracted plugin repos (not in JSON)
	PluginsToken string         `json:"-"`                 // Extracted plugin token (not in JSON)

	// Feature flags and other settings
	Features map[string]any    `json:"features,omitempty"` // Dynamic feature flags
	Env      map[string]string `json:"env,omitempty"`
	Secrets  map[string]any    `json:"secrets,omitempty"`

	// Workflow execution settings
	RunsOn      string         `json:"runs-on,omitempty"`
	RunName     string         `json:"run-name,omitempty"`
	Steps       []any          `json:"steps,omitempty"`       // Custom workflow steps
	PostSteps   []any          `json:"post-steps,omitempty"`  // Post-workflow steps
	Environment map[string]any `json:"environment,omitempty"` // GitHub environment
	Container   map[string]any `json:"container,omitempty"`
	Services    map[string]any `json:"services,omitempty"`
	Cache       map[string]any `json:"cache,omitempty"`

	// Import and inclusion
	Imports any `json:"imports,omitempty"` // Can be string or array
	Include any `json:"include,omitempty"` // Can be string or array

	// Metadata
	Metadata      map[string]string    `json:"metadata,omitempty"` // Custom metadata key-value pairs
	SecretMasking *SecretMaskingConfig `json:"secret-masking,omitempty"`
	GithubToken   string               `json:"github-token,omitempty"`

	// Command/bot configuration
	Roles     []string         `json:"roles,omitempty"`
	Bots      []string         `json:"bots,omitempty"`
	RateLimit *RateLimitConfig `json:"rate-limit,omitempty"`
}

FrontmatterConfig represents the structured configuration from workflow frontmatter This provides compile-time type safety and clearer error messages compared to map[string]any

func ParseFrontmatterConfig

func ParseFrontmatterConfig(frontmatter map[string]any) (*FrontmatterConfig, error)

ParseFrontmatterConfig creates a FrontmatterConfig from a raw frontmatter map This provides a single entry point for converting untyped frontmatter into a structured configuration with better error handling.

func (*FrontmatterConfig) ToMap

func (fc *FrontmatterConfig) ToMap() map[string]any

ToMap converts FrontmatterConfig back to map[string]any for backward compatibility This allows gradual migration from map[string]any to strongly-typed config

type FunctionCallNode

type FunctionCallNode struct {
	FunctionName string
	Arguments    []ConditionNode
}

FunctionCallNode represents a function call expression like contains(array, value)

func BuildFunctionCall

func BuildFunctionCall(functionName string, args ...ConditionNode) *FunctionCallNode

BuildFunctionCall creates a function call node

func BuildRefStartsWith

func BuildRefStartsWith(prefix string) *FunctionCallNode

BuildRefStartsWith creates a condition to check if github.ref starts with a prefix

func (*FunctionCallNode) Render

func (f *FunctionCallNode) Render() string

type GitHubActionStep

type GitHubActionStep []string

GitHubActionStep represents the YAML lines for a single step in a GitHub Actions workflow

func BuildStandardNpmEngineInstallSteps

func BuildStandardNpmEngineInstallSteps(
	packageName string,
	defaultVersion string,
	stepName string,
	cacheKeyPrefix string,
	workflowData *WorkflowData,
) []GitHubActionStep

BuildStandardNpmEngineInstallSteps creates standard npm installation steps for engines This helper extracts the common pattern shared by Copilot, Codex, and Claude engines.

Parameters:

  • packageName: The npm package name (e.g., "@github/copilot")
  • defaultVersion: The default version constant (e.g., constants.DefaultCopilotVersion)
  • stepName: The display name for the install step (e.g., "Install GitHub Copilot CLI")
  • cacheKeyPrefix: The cache key prefix (e.g., "copilot")
  • workflowData: The workflow data containing engine configuration

Returns:

  • []GitHubActionStep: The installation steps including Node.js setup

func GenerateCopilotInstallerSteps

func GenerateCopilotInstallerSteps(version, stepName string) []GitHubActionStep

GenerateCopilotInstallerSteps creates GitHub Actions steps to install the Copilot CLI using the official installer.

func GenerateMultiSecretValidationStep

func GenerateMultiSecretValidationStep(secretNames []string, engineName, docsURL string) GitHubActionStep

GenerateMultiSecretValidationStep creates a GitHub Actions step that validates at least one of multiple secrets is available secretNames: slice of secret names to validate (e.g., []string{"CODEX_API_KEY", "OPENAI_API_KEY"}) engineName: the display name of the engine (e.g., "Codex") docsURL: URL to the documentation page for setting up the secret

func GenerateNodeJsSetupStep

func GenerateNodeJsSetupStep() GitHubActionStep

GenerateNodeJsSetupStep creates a GitHub Actions step for setting up Node.js Returns a step that installs Node.js using the default version from constants.DefaultNodeVersion Caching is disabled by default to prevent cache poisoning vulnerabilities in release workflows

func GenerateNpmInstallSteps

func GenerateNpmInstallSteps(packageName, version, stepName, cacheKeyPrefix string, includeNodeSetup bool) []GitHubActionStep

GenerateNpmInstallSteps creates GitHub Actions steps for installing an npm package globally Parameters:

  • packageName: The npm package name (e.g., "@anthropic-ai/claude-code")
  • version: The package version to install
  • stepName: The name to display for the install step (e.g., "Install Claude Code CLI")
  • cacheKeyPrefix: The prefix for the cache key (unused, kept for API compatibility)
  • includeNodeSetup: If true, includes Node.js setup step before npm install

Returns steps for installing the npm package (optionally with Node.js setup)

func GenerateNpmInstallStepsWithScope

func GenerateNpmInstallStepsWithScope(packageName, version, stepName, cacheKeyPrefix string, includeNodeSetup bool, isGlobal bool) []GitHubActionStep

GenerateNpmInstallStepsWithScope generates npm installation steps with control over global vs local installation

func GeneratePluginInstallationSteps added in v0.42.6

func GeneratePluginInstallationSteps(plugins []string, engineID string, githubToken string) []GitHubActionStep

GeneratePluginInstallationSteps generates GitHub Actions steps to install plugins for the given engine. Each plugin is installed using the engine-specific CLI command with the github-token environment variable set.

Parameters:

  • plugins: List of plugin repository slugs (e.g., ["org/repo", "org2/repo2"])
  • engineID: The engine identifier ("copilot", "claude", "codex")
  • githubToken: The GitHub token expression to use for authentication (uses cascading resolution if empty)

Returns:

  • Slice of GitHubActionStep containing the installation steps for all plugins

func GenerateRuntimeSetupSteps

func GenerateRuntimeSetupSteps(requirements []RuntimeRequirement) []GitHubActionStep

GenerateRuntimeSetupSteps creates GitHub Actions steps for runtime setup

func GenerateSecretValidationStep

func GenerateSecretValidationStep(secretName, engineName, docsURL string) GitHubActionStep

GenerateSecretValidationStep creates a GitHub Actions step that validates required secrets are available secretName: the name of the secret to validate (e.g., "ANTHROPIC_API_KEY") engineName: the display name of the engine (e.g., "Claude Code") docsURL: URL to the documentation page for setting up the secret

func GenerateSerenaLanguageServiceSteps

func GenerateSerenaLanguageServiceSteps(tools *ToolsConfig) []GitHubActionStep

GenerateSerenaLanguageServiceSteps creates installation steps for Serena language services NOTE: This function is now obsolete since Serena runs in a Docker container. Language services are provided inside the container and do not require host installation. This function is kept for backward compatibility but returns an empty slice.

func GetBaseInstallationSteps

func GetBaseInstallationSteps(config EngineInstallConfig, workflowData *WorkflowData) []GitHubActionStep

GetBaseInstallationSteps returns the common installation steps for an engine. This includes secret validation and npm package installation steps that are shared across all engines.

Parameters:

  • config: Engine-specific configuration for installation
  • workflowData: The workflow data containing engine configuration

Returns:

  • []GitHubActionStep: The base installation steps (secret validation + npm install)

func InjectCustomEngineSteps

func InjectCustomEngineSteps(
	workflowData *WorkflowData,
	convertStepFunc func(map[string]any) (string, error),
) []GitHubActionStep

InjectCustomEngineSteps processes custom steps from engine config and converts them to GitHubActionSteps. This shared function extracts the common pattern used by Copilot, Codex, and Claude engines.

Parameters:

  • workflowData: The workflow data containing engine configuration
  • convertStepFunc: A function that converts a step map to YAML string (engine-specific)

Returns:

  • []GitHubActionStep: Array of custom steps ready to be included in the execution pipeline

type GitHubAllowedTools

type GitHubAllowedTools []GitHubToolName

GitHubAllowedTools is a slice of GitHub tool names

func (GitHubAllowedTools) ToStringSlice

func (g GitHubAllowedTools) ToStringSlice() []string

ToStringSlice converts GitHubAllowedTools to []string

type GitHubAppConfig

type GitHubAppConfig struct {
	AppID        string   `yaml:"app-id,omitempty"`       // GitHub App ID (e.g., "${{ vars.APP_ID }}")
	PrivateKey   string   `yaml:"private-key,omitempty"`  // GitHub App private key (e.g., "${{ secrets.APP_PRIVATE_KEY }}")
	Owner        string   `yaml:"owner,omitempty"`        // Optional: owner of the GitHub App installation (defaults to current repository owner)
	Repositories []string `yaml:"repositories,omitempty"` // Optional: comma or newline-separated list of repositories to grant access to
}

GitHubAppConfig holds configuration for GitHub App-based token minting

type GitHubMCPDockerOptions

type GitHubMCPDockerOptions struct {
	// ReadOnly enables read-only mode for GitHub API operations
	ReadOnly bool
	// Lockdown enables lockdown mode for GitHub MCP server (limits content from public repos)
	Lockdown bool
	// LockdownFromStep indicates if lockdown value should be read from step output
	LockdownFromStep bool
	// Toolsets specifies the GitHub toolsets to enable
	Toolsets string
	// DockerImageVersion specifies the GitHub MCP server Docker image version
	DockerImageVersion string
	// CustomArgs are additional arguments to append to the Docker command
	CustomArgs []string
	// IncludeTypeField indicates whether to include the "type": "stdio" field (Copilot needs it, Claude doesn't)
	IncludeTypeField bool
	// AllowedTools specifies the list of allowed tools (Copilot uses this, Claude doesn't)
	AllowedTools []string
	// EffectiveToken is the GitHub token to use (Claude uses this, Copilot uses env passthrough)
	EffectiveToken string
	// Mounts specifies volume mounts for the GitHub MCP server container (format: "host:container:mode")
	Mounts []string
}

GitHubMCPDockerOptions defines configuration for GitHub MCP Docker rendering

type GitHubMCPRemoteOptions

type GitHubMCPRemoteOptions struct {
	// ReadOnly enables read-only mode for GitHub API operations
	ReadOnly bool
	// Lockdown enables lockdown mode for GitHub MCP server (limits content from public repos)
	Lockdown bool
	// LockdownFromStep indicates if lockdown value should be read from step output
	LockdownFromStep bool
	// Toolsets specifies the GitHub toolsets to enable
	Toolsets string
	// AuthorizationValue is the value for the Authorization header
	// For Claude: "Bearer {effectiveToken}"
	// For Copilot: "Bearer \\${GITHUB_PERSONAL_ACCESS_TOKEN}"
	AuthorizationValue string
	// IncludeToolsField indicates whether to include the "tools" field (Copilot needs it, Claude doesn't)
	IncludeToolsField bool
	// AllowedTools specifies the list of allowed tools (Copilot uses this, Claude doesn't)
	AllowedTools []string
	// IncludeEnvSection indicates whether to include the env section (Copilot needs it, Claude doesn't)
	IncludeEnvSection bool
}

GitHubMCPRemoteOptions defines configuration for GitHub MCP remote mode rendering

type GitHubScriptStepConfig

type GitHubScriptStepConfig struct {
	// Step metadata
	StepName string // e.g., "Create Output Issue"
	StepID   string // e.g., "create_issue"

	// Main job reference for agent output
	MainJobName string

	// Environment variables specific to this safe output type
	// These are added after GH_AW_AGENT_OUTPUT
	CustomEnvVars []string

	// JavaScript script constant to format and include (for inline mode)
	Script string

	// ScriptFile is the .cjs filename to require (e.g., "noop.cjs")
	// If empty, Script will be inlined instead
	ScriptFile string

	// Token configuration (passed to addSafeOutputGitHubTokenForConfig or addSafeOutputCopilotGitHubTokenForConfig)
	Token string

	// UseCopilotToken indicates whether to use the Copilot token preference chain
	// (COPILOT_GITHUB_TOKEN > GH_AW_GITHUB_TOKEN (legacy))
	// This should be true for Copilot-related operations like creating agent tasks,
	// assigning copilot to issues, or adding copilot as PR reviewer
	UseCopilotToken bool

	// UseAgentToken indicates whether to use the agent token preference chain
	// (config token > GH_AW_AGENT_TOKEN)
	// This should be true for agent assignment operations (assign-to-agent)
	UseAgentToken bool
}

GitHubScriptStepConfig holds configuration for building a GitHub Script step

type GitHubToolConfig

type GitHubToolConfig struct {
	Allowed     GitHubAllowedTools `yaml:"allowed,omitempty"`
	Mode        string             `yaml:"mode,omitempty"`
	Version     string             `yaml:"version,omitempty"`
	Args        []string           `yaml:"args,omitempty"`
	ReadOnly    bool               `yaml:"read-only,omitempty"`
	GitHubToken string             `yaml:"github-token,omitempty"`
	Toolset     GitHubToolsets     `yaml:"toolsets,omitempty"`
	Lockdown    bool               `yaml:"lockdown,omitempty"`
	App         *GitHubAppConfig   `yaml:"app,omitempty"` // GitHub App configuration for token minting
}

GitHubToolConfig represents the configuration for the GitHub tool Can be nil (enabled with defaults), string, or an object with specific settings

func (*GitHubToolConfig) GetToolsets

func (g *GitHubToolConfig) GetToolsets() string

GetToolsets implements ValidatableTool for GitHubToolConfig

func (*GitHubToolConfig) IsReadOnly

func (g *GitHubToolConfig) IsReadOnly() bool

IsReadOnly implements ValidatableTool for GitHubToolConfig

type GitHubToolName

type GitHubToolName string

GitHubToolName represents a GitHub tool name (e.g., "issue_read", "create_issue")

type GitHubToolset

type GitHubToolset string

GitHubToolset represents a GitHub toolset name (e.g., "default", "repos", "issues")

type GitHubToolsetPermissions

type GitHubToolsetPermissions struct {
	ReadPermissions  []PermissionScope
	WritePermissions []PermissionScope
	Tools            []string // List of tools in this toolset (for verification)
}

GitHubToolsetPermissions maps GitHub MCP toolsets to their required permissions

type GitHubToolsetValidationError

type GitHubToolsetValidationError struct {
	// MissingToolsets maps toolset name to the list of tools that require it
	MissingToolsets map[string][]string
}

GitHubToolsetValidationError represents an error when GitHub tools are specified but their required toolsets are not enabled

func NewGitHubToolsetValidationError

func NewGitHubToolsetValidationError(missingToolsets map[string][]string) *GitHubToolsetValidationError

NewGitHubToolsetValidationError creates a new validation error

func (*GitHubToolsetValidationError) Error

Error implements the error interface

type GitHubToolsets

type GitHubToolsets []GitHubToolset

GitHubToolsets is a slice of GitHub toolset names

func (GitHubToolsets) ToStringSlice

func (g GitHubToolsets) ToStringSlice() []string

ToStringSlice converts GitHubToolsets to []string

type GitHubToolsetsData

type GitHubToolsetsData struct {
	Version     string `json:"version"`
	Description string `json:"description"`
	Toolsets    map[string]struct {
		Description      string   `json:"description"`
		ReadPermissions  []string `json:"read_permissions"`
		WritePermissions []string `json:"write_permissions"`
		Tools            []string `json:"tools"`
	} `json:"toolsets"`
}

GitHubToolsetsData represents the structure of the embedded JSON file

func GetToolsetsData

func GetToolsetsData() GitHubToolsetsData

GetToolsetsData returns the parsed GitHub toolsets data (for use by workflows)

type GoDependency

type GoDependency struct {
	Path    string // import path (e.g., github.com/user/repo)
	Version string // version or pseudo-version
}

GoDependency represents a parsed Go package

type HideCommentConfig

type HideCommentConfig struct {
	BaseSafeOutputConfig   `yaml:",inline"`
	SafeOutputTargetConfig `yaml:",inline"`
	AllowedReasons         []string `yaml:"allowed-reasons,omitempty"` // List of allowed reasons for hiding comments (default: all reasons allowed)
}

HideCommentConfig holds configuration for hiding comments from agent output

type InputDefinition

type InputDefinition struct {
	Description string   `yaml:"description,omitempty" json:"description,omitempty"`
	Required    bool     `yaml:"required,omitempty" json:"required,omitempty"`
	Default     any      `yaml:"default,omitempty" json:"default,omitempty"` // Can be string, number, or boolean
	Type        string   `yaml:"type,omitempty" json:"type,omitempty"`       // "string", "choice", "boolean", "number", "environment"
	Options     []string `yaml:"options,omitempty" json:"options,omitempty"` // Options for choice type
}

InputDefinition defines an input parameter for workflows, safe-jobs, and imported workflows. This is a unified type that consolidates the common input schema used across: - workflow_dispatch inputs (GitHub Actions native) - safe-jobs inputs (safe-outputs.jobs.[name].inputs) - imported workflow inputs (imports with inputs parameter)

The structure follows the workflow_dispatch input schema from GitHub Actions: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#onworkflow_dispatchinputs

func ParseInputDefinition

func ParseInputDefinition(inputConfig map[string]any) *InputDefinition

ParseInputDefinition parses an input definition from a map. This is a shared helper function that handles the common parsing logic for input definitions regardless of their source (safe-jobs, imports, etc.).

func (*InputDefinition) GetDefaultAsString

func (i *InputDefinition) GetDefaultAsString() string

GetDefaultAsString returns the default value as a string. Useful for backwards compatibility with code that expects string defaults.

type JSONMCPConfigOptions

type JSONMCPConfigOptions struct {
	// ConfigPath is the file path for the MCP config (e.g., "/tmp/gh-aw/mcp-config/mcp-servers.json")
	ConfigPath string
	// Renderers contains engine-specific rendering functions for each tool
	Renderers MCPToolRenderers
	// FilterTool is an optional function to filter out tools before processing
	// Returns true if the tool should be included, false to skip it
	FilterTool func(toolName string) bool
	// PostEOFCommands is an optional function to add commands after the EOF (e.g., debug output)
	PostEOFCommands func(yaml *strings.Builder)
	// GatewayConfig is an optional gateway configuration to include in the MCP config
	// When set, adds a "gateway" section with port and apiKey for awmg to use
	GatewayConfig *MCPGatewayRuntimeConfig
}

JSONMCPConfigOptions defines configuration for JSON-based MCP config rendering

type Job

type Job struct {
	Name                       string
	DisplayName                string // Optional display name for the job (name property in YAML)
	RunsOn                     string
	If                         string
	HasWorkflowRunSafetyChecks bool // If true, the job's if condition includes workflow_run safety checks
	Permissions                string
	TimeoutMinutes             int
	Concurrency                string            // Job-level concurrency configuration
	Environment                string            // Job environment configuration
	Container                  string            // Job container configuration
	Services                   string            // Job services configuration
	Env                        map[string]string // Job-level environment variables
	Steps                      []string
	Needs                      []string // Job dependencies (needs clause)
	Outputs                    map[string]string

	// Reusable workflow call properties
	Uses    string            // Path to reusable workflow (e.g., ./.github/workflows/reusable.yml)
	With    map[string]any    // Input parameters for reusable workflow
	Secrets map[string]string // Secrets for reusable workflow
}

Job represents a GitHub Actions job with all its properties

type JobManager

type JobManager struct {
	// contains filtered or unexported fields
}

JobManager manages a collection of jobs and handles dependency validation

func NewJobManager

func NewJobManager() *JobManager

NewJobManager creates a new JobManager instance

func (*JobManager) AddJob

func (jm *JobManager) AddJob(job *Job) error

AddJob adds a job to the manager

func (*JobManager) GetAllJobs

func (jm *JobManager) GetAllJobs() map[string]*Job

GetAllJobs returns all jobs in the manager

func (*JobManager) GetJob

func (jm *JobManager) GetJob(name string) (*Job, bool)

GetJob retrieves a job by name

func (*JobManager) GetTopologicalOrder

func (jm *JobManager) GetTopologicalOrder() ([]string, error)

GetTopologicalOrder returns jobs in topological order (dependencies before dependents)

func (*JobManager) RenderToYAML

func (jm *JobManager) RenderToYAML() string

RenderToYAML generates the jobs section of a GitHub Actions workflow

func (*JobManager) ValidateDependencies

func (jm *JobManager) ValidateDependencies() error

ValidateDependencies checks that all job dependencies exist and there are no cycles

func (*JobManager) ValidateDuplicateSteps

func (jm *JobManager) ValidateDuplicateSteps() error

ValidateDuplicateSteps checks that no job has duplicate steps This detects compiler bugs where the same step is added multiple times

type LinkSubIssueConfig

type LinkSubIssueConfig struct {
	BaseSafeOutputConfig   `yaml:",inline"`
	SafeOutputTargetConfig `yaml:",inline"`
	ParentRequiredLabels   []string `yaml:"parent-required-labels,omitempty"` // Required labels the parent issue must have
	ParentTitlePrefix      string   `yaml:"parent-title-prefix,omitempty"`    // Required title prefix for parent issue
	SubRequiredLabels      []string `yaml:"sub-required-labels,omitempty"`    // Required labels the sub-issue must have
	SubTitlePrefix         string   `yaml:"sub-title-prefix,omitempty"`       // Required title prefix for sub-issue
}

LinkSubIssueConfig holds configuration for linking issues as sub-issues from agent output

type ListJobBuilderConfig

type ListJobBuilderConfig struct {
	JobName        string        // e.g., "add_labels", "assign_milestone"
	StepName       string        // e.g., "Add Labels", "Assign Milestone"
	StepID         string        // e.g., "add_labels", "assign_milestone"
	EnvPrefix      string        // e.g., "GH_AW_LABELS", "GH_AW_MILESTONE"
	OutputName     string        // e.g., "labels_added", "assigned_milestones"
	Script         string        // JavaScript script for the operation
	Permissions    *Permissions  // Job permissions
	DefaultMax     int           // Default max count if not specified in config
	ExtraCondition ConditionNode // Additional condition to append (optional)
}

ListJobBuilderConfig contains parameters for building list-based safe-output jobs

type ListJobConfig

type ListJobConfig struct {
	SafeOutputTargetConfig `yaml:",inline"`
	Allowed                []string `yaml:"allowed,omitempty"` // Optional list of allowed values
}

ListJobConfig represents common configuration for list-based operations (add-labels, add-reviewer, assign-milestone)

func ParseListJobConfig

func ParseListJobConfig(configMap map[string]any, allowedKey string) (ListJobConfig, bool)

ParseListJobConfig parses common list job fields from a config map. Returns the parsed ListJobConfig and a boolean indicating if there was a validation error.

type LogMetrics

type LogMetrics struct {
	TokenUsage    int
	EstimatedCost float64
	Turns         int            // Number of turns needed to complete the task
	ToolCalls     []ToolCallInfo // Tool call statistics
	ToolSequences [][]string     // Sequences of tool calls preserving order

}

LogMetrics represents extracted metrics from log files

func ExtractJSONMetrics

func ExtractJSONMetrics(line string, verbose bool) LogMetrics

ExtractJSONMetrics extracts metrics from streaming JSON log lines

type LogParser

type LogParser interface {
	// ParseLogMetrics extracts metrics from engine-specific log content
	ParseLogMetrics(logContent string, verbose bool) LogMetrics

	// GetLogParserScriptId returns the name of the JavaScript script to parse logs for this engine
	GetLogParserScriptId() string

	// GetLogFileForParsing returns the log file path to use for JavaScript parsing in the workflow
	// This may be different from the stdout/stderr log file if the engine produces separate detailed logs
	GetLogFileForParsing() string
}

LogParser handles parsing and analyzing engine logs Engines can optionally implement this to provide detailed log parsing

type MCPConfigProvider

type MCPConfigProvider interface {
	// RenderMCPConfig renders the MCP configuration for this engine to the given YAML builder
	RenderMCPConfig(yaml *strings.Builder, tools map[string]any, mcpTools []string, workflowData *WorkflowData)
}

MCPConfigProvider handles MCP (Model Context Protocol) configuration Engines that support MCP servers should implement this

type MCPConfigRenderer

type MCPConfigRenderer struct {
	// IndentLevel controls the indentation level for properties (e.g., "                " for JSON, "          " for TOML)
	IndentLevel string
	// Format specifies the output format ("json" for JSON-like, "toml" for TOML-like)
	Format string
	// RequiresCopilotFields indicates if the engine requires "type" and "tools" fields (true for copilot engine)
	RequiresCopilotFields bool
	// RewriteLocalhostToDocker indicates if localhost URLs should be rewritten to host.docker.internal
	// This is needed when the agent runs inside a firewall container and needs to access MCP servers on the host
	RewriteLocalhostToDocker bool
}

MCPConfigRenderer contains configuration options for rendering MCP config

type MCPConfigRendererUnified

type MCPConfigRendererUnified struct {
	// contains filtered or unexported fields
}

MCPConfigRendererUnified provides unified rendering methods for MCP configurations across different engines (Claude, Copilot, Codex, Custom)

func NewMCPConfigRenderer

func NewMCPConfigRenderer(opts MCPRendererOptions) *MCPConfigRendererUnified

NewMCPConfigRenderer creates a new unified MCP config renderer with the specified options

func (*MCPConfigRendererUnified) RenderAgenticWorkflowsMCP

func (r *MCPConfigRendererUnified) RenderAgenticWorkflowsMCP(yaml *strings.Builder)

RenderAgenticWorkflowsMCP generates the Agentic Workflows MCP server configuration

func (*MCPConfigRendererUnified) RenderGitHubMCP

func (r *MCPConfigRendererUnified) RenderGitHubMCP(yaml *strings.Builder, githubTool any, workflowData *WorkflowData)

RenderGitHubMCP generates the GitHub MCP server configuration Supports both local (Docker) and remote (hosted) modes

func (*MCPConfigRendererUnified) RenderPlaywrightMCP

func (r *MCPConfigRendererUnified) RenderPlaywrightMCP(yaml *strings.Builder, playwrightTool any)

RenderPlaywrightMCP generates the Playwright MCP server configuration

func (*MCPConfigRendererUnified) RenderSafeInputsMCP

func (r *MCPConfigRendererUnified) RenderSafeInputsMCP(yaml *strings.Builder, safeInputs *SafeInputsConfig, workflowData *WorkflowData)

RenderSafeInputsMCP generates the Safe Inputs MCP server configuration

func (*MCPConfigRendererUnified) RenderSafeOutputsMCP

func (r *MCPConfigRendererUnified) RenderSafeOutputsMCP(yaml *strings.Builder, workflowData *WorkflowData)

RenderSafeOutputsMCP generates the Safe Outputs MCP server configuration

func (*MCPConfigRendererUnified) RenderSerenaMCP

func (r *MCPConfigRendererUnified) RenderSerenaMCP(yaml *strings.Builder, serenaTool any)

RenderSerenaMCP generates Serena MCP server configuration

type MCPGatewayRuntimeConfig

type MCPGatewayRuntimeConfig struct {
	Container      string            `yaml:"container,omitempty"`      // Container image for the gateway (required)
	Version        string            `yaml:"version,omitempty"`        // Optional version/tag for the container
	Entrypoint     string            `yaml:"entrypoint,omitempty"`     // Optional entrypoint override for the container
	Args           []string          `yaml:"args,omitempty"`           // Arguments for docker run
	EntrypointArgs []string          `yaml:"entrypointArgs,omitempty"` // Arguments passed to container entrypoint
	Env            map[string]string `yaml:"env,omitempty"`            // Environment variables for the gateway
	Port           int               `yaml:"port,omitempty"`           // Port for the gateway HTTP server (default: 8080)
	APIKey         string            `yaml:"api-key,omitempty"`        // API key for gateway authentication
	Domain         string            `yaml:"domain,omitempty"`         // Domain for gateway URL (localhost or host.docker.internal)
	Mounts         []string          `yaml:"mounts,omitempty"`         // Volume mounts for the gateway container (format: "source:dest:mode")
	PayloadDir     string            `yaml:"payload-dir,omitempty"`    // Directory path for storing large payload JSON files (must be absolute path)
}

MCPGatewayRuntimeConfig represents the configuration for the MCP gateway runtime execution The gateway routes MCP server calls through a unified HTTP endpoint Per MCP Gateway Specification v1.0.0: All stdio-based MCP servers MUST be containerized. Direct command execution is not supported.

type MCPRendererOptions

type MCPRendererOptions struct {
	// IncludeCopilotFields indicates if the engine requires "type" and "tools" fields (true for copilot engine)
	IncludeCopilotFields bool
	// InlineArgs indicates if args should be rendered inline (true for copilot) or multi-line (false for claude/custom)
	InlineArgs bool
	// Format specifies the output format ("json" for JSON-like, "toml" for TOML-like)
	Format string
	// IsLast indicates if this is the last server in the configuration (affects trailing comma)
	IsLast bool
	// ActionMode indicates the action mode for workflow compilation (dev, release, script)
	ActionMode ActionMode
}

MCPRendererOptions contains configuration options for the unified MCP renderer

type MCPServerConfig

type MCPServerConfig struct {
	types.BaseMCPServerConfig

	// Workflow-specific fields
	Mode     string   `yaml:"mode,omitempty"`     // MCP server mode (stdio, http, remote, local)
	Toolsets []string `yaml:"toolsets,omitempty"` // Toolsets to enable

	// For truly dynamic configuration (server-specific fields not covered above)
	CustomFields map[string]any `yaml:",inline"`
}

MCPServerConfig represents the configuration for a custom MCP server. It embeds BaseMCPServerConfig for common fields and adds workflow-specific fields. This provides partial type safety for common MCP configuration fields while maintaining flexibility for truly dynamic configurations.

type MCPToolRenderers

type MCPToolRenderers struct {
	RenderGitHub           func(yaml *strings.Builder, githubTool any, isLast bool, workflowData *WorkflowData)
	RenderPlaywright       func(yaml *strings.Builder, playwrightTool any, isLast bool)
	RenderSerena           func(yaml *strings.Builder, serenaTool any, isLast bool)
	RenderCacheMemory      func(yaml *strings.Builder, isLast bool, workflowData *WorkflowData)
	RenderAgenticWorkflows func(yaml *strings.Builder, isLast bool)
	RenderSafeOutputs      func(yaml *strings.Builder, isLast bool, workflowData *WorkflowData)
	RenderSafeInputs       func(yaml *strings.Builder, safeInputs *SafeInputsConfig, isLast bool)
	RenderWebFetch         func(yaml *strings.Builder, isLast bool)
	RenderCustomMCPConfig  RenderCustomMCPToolConfigHandler
}

MCPToolRenderers holds engine-specific rendering functions for each MCP tool type

type MapToolConfig

type MapToolConfig map[string]any

MapToolConfig implements ToolConfig for map[string]any

func (MapToolConfig) GetAny

func (m MapToolConfig) GetAny(key string) (any, bool)

func (MapToolConfig) GetString

func (m MapToolConfig) GetString(key string) (string, bool)

func (MapToolConfig) GetStringArray

func (m MapToolConfig) GetStringArray(key string) ([]string, bool)

func (MapToolConfig) GetStringMap

func (m MapToolConfig) GetStringMap(key string) (map[string]string, bool)

type MarkPullRequestAsReadyForReviewConfig

type MarkPullRequestAsReadyForReviewConfig struct {
	BaseSafeOutputConfig   `yaml:",inline"`
	SafeOutputTargetConfig `yaml:",inline"`
	SafeOutputFilterConfig `yaml:",inline"`
}

MarkPullRequestAsReadyForReviewConfig holds configuration for marking draft PRs as ready for review

type MentionsConfig

type MentionsConfig struct {
	// Enabled can be:
	//   true: mentions always allowed (error in strict mode)
	//   false: mentions always escaped
	//   nil: use default behavior with team members and context
	Enabled *bool `yaml:"enabled,omitempty" json:"enabled,omitempty"`

	// AllowTeamMembers determines if team members can be mentioned (default: true)
	AllowTeamMembers *bool `yaml:"allow-team-members,omitempty" json:"allowTeamMembers,omitempty"`

	// AllowContext determines if mentions from event context are allowed (default: true)
	AllowContext *bool `yaml:"allow-context,omitempty" json:"allowContext,omitempty"`

	// Allowed is a list of user/bot names always allowed (bots not allowed by default)
	Allowed []string `yaml:"allowed,omitempty" json:"allowed,omitempty"`

	// Max is the maximum number of mentions per message (default: 50)
	Max *int `yaml:"max,omitempty" json:"max,omitempty"`
}

MentionsConfig holds configuration for @mention filtering in safe outputs

type MissingDataConfig

type MissingDataConfig struct {
	BaseSafeOutputConfig `yaml:",inline"`
	CreateIssue          bool     `yaml:"create-issue,omitempty"` // Whether to create/update issues for missing data (default: true)
	TitlePrefix          string   `yaml:"title-prefix,omitempty"` // Prefix for issue titles (default: "[missing data]")
	Labels               []string `yaml:"labels,omitempty"`       // Labels to add to created issues
}

MissingDataConfig holds configuration for reporting missing data required to achieve goals

type MissingToolConfig

type MissingToolConfig struct {
	BaseSafeOutputConfig `yaml:",inline"`
	CreateIssue          bool     `yaml:"create-issue,omitempty"` // Whether to create/update issues for missing tools (default: true)
	TitlePrefix          string   `yaml:"title-prefix,omitempty"` // Prefix for issue titles (default: "[missing tool]")
	Labels               []string `yaml:"labels,omitempty"`       // Labels to add to created issues
}

MissingToolConfig holds configuration for reporting missing tools or functionality

type NetworkPermissions

type NetworkPermissions struct {
	Allowed           []string        `yaml:"allowed,omitempty"`  // List of allowed domains or ecosystem identifiers (e.g., "defaults", "github", "python")
	Blocked           []string        `yaml:"blocked,omitempty"`  // List of blocked domains (takes precedence over allowed)
	Firewall          *FirewallConfig `yaml:"firewall,omitempty"` // AWF firewall configuration (see firewall.go)
	ExplicitlyDefined bool            `yaml:"-"`                  // Internal flag: true if network field was explicitly set in frontmatter
}

NetworkPermissions represents network access permissions for workflow execution Controls which domains the workflow can access during execution.

The Allowed field specifies which domains/ecosystems are permitted:

  • nil/not set: Use default ecosystem domains (backwards compatibility)
  • []: Empty list means deny all network access
  • ["defaults"]: Use default ecosystem domains
  • ["defaults", "github", "python"]: Expand and merge multiple ecosystems
  • ["example.com"]: Allow specific domain only

Examples:

  1. String format - use default domains only: network: defaults Result: NetworkPermissions{Allowed: ["defaults"], ExplicitlyDefined: true}

  2. Object format - specify allowed ecosystems/domains: network: allowed: - defaults # Expands to default ecosystem domains (certs, JSON schema, Ubuntu, etc.) - github # Expands to GitHub ecosystem domains (*.githubusercontent.com, etc.) - example.com # Literal domain Result: NetworkPermissions{Allowed: ["defaults", "github", "example.com"], ExplicitlyDefined: true}

  3. Empty object - deny all network access: network: {} Result: NetworkPermissions{Allowed: [], ExplicitlyDefined: true}

Ecosystem identifiers in the Allowed list are expanded to their corresponding domain lists. See GetAllowedDomains() for the list of supported ecosystem identifiers.

type NoOpConfig

type NoOpConfig struct {
	BaseSafeOutputConfig `yaml:",inline"`
	ReportAsIssue        bool `yaml:"report-as-issue,omitempty"` // Controls whether noop runs are reported as issue comments (default: true)
}

NoOpConfig holds configuration for no-op safe output (logging only)

type NotNode

type NotNode struct {
	Child ConditionNode
}

NotNode represents a NOT operation on a condition

func (*NotNode) Render

func (n *NotNode) Render() string

type NpmDependency

type NpmDependency struct {
	Name    string
	Version string // semver range or specific version
}

NpmDependency represents a parsed npm package with version

type NumberLiteralNode

type NumberLiteralNode struct {
	Value string
}

NumberLiteralNode represents a numeric literal value

func BuildNumberLiteral

func BuildNumberLiteral(value string) *NumberLiteralNode

BuildNumberLiteral creates a number literal node

func (*NumberLiteralNode) Render

func (n *NumberLiteralNode) Render() string

type OperationError

type OperationError struct {
	Operation  string
	EntityType string
	EntityID   string
	Cause      error
	Suggestion string
	Timestamp  time.Time
}

OperationError represents an error that occurred during an operation

func NewOperationError

func NewOperationError(operation, entityType, entityID string, cause error, suggestion string) *OperationError

NewOperationError creates a new operation error with context

func (*OperationError) Error

func (e *OperationError) Error() string

Error implements the error interface

func (*OperationError) Unwrap

func (e *OperationError) Unwrap() error

Unwrap returns the underlying error

type OrNode

type OrNode struct {
	Left, Right ConditionNode
}

OrNode represents an OR operation between two conditions

func (*OrNode) Render

func (o *OrNode) Render() string

type PackageExtractor

type PackageExtractor struct {
	// CommandNames is the list of command names to look for.
	// Include all variations of the command (e.g., ["pip", "pip3"]).
	// Matching is case-sensitive and exact.
	//
	// Examples:
	//   - ["npx"] for npm packages
	//   - ["pip", "pip3"] for Python packages
	//   - ["go"] for Go packages
	//   - ["uvx"] for uv tool packages
	CommandNames []string

	// RequiredSubcommand is the subcommand that must follow the command name
	// before the package name appears. Set to empty string if the package name
	// comes directly after the command.
	//
	// Examples:
	//   - "install" for pip (pip install <package>)
	//   - "get" for go (go get <package>)
	//   - "" for npx (npx <package>)
	//
	// Deprecated: Use RequiredSubcommands for multiple subcommand support.
	// This field is maintained for backward compatibility.
	RequiredSubcommand string

	// RequiredSubcommands is a list of subcommands that can follow the command name
	// before the package name appears. If any of these subcommands is found, the
	// package name following it will be extracted. Set to empty slice if the package
	// name comes directly after the command.
	//
	// This field takes precedence over RequiredSubcommand if both are set.
	//
	// Examples:
	//   - ["install"] for pip (pip install <package>)
	//   - ["install", "get"] for go (go install <pkg> or go get <pkg>)
	//   - [] for npx (npx <package>)
	RequiredSubcommands []string

	// TrimSuffixes is a string of characters to trim from the end of package names.
	// This is useful for removing shell operators that may appear after package names
	// in command strings.
	//
	// Recommended value: "&|;" (covers common shell operators)
	//
	// Examples:
	//   - "pip install requests;" → extracts "requests" (trims ";")
	//   - "npx playwright&" → extracts "playwright" (trims "&")
	TrimSuffixes string
}

PackageExtractor provides a configurable framework for extracting package names from command-line strings. It can be configured to handle different package managers (npm, pip, uv, go) by setting the appropriate command names and options.

This type is the core of the package extraction pattern. Use it instead of writing custom parsing logic to avoid code duplication.

Configuration:

  • Set CommandNames to all variants of the command (e.g., ["pip", "pip3"])
  • Set RequiredSubcommand if the package manager requires a subcommand (e.g., "install" for pip, "get" for go)
  • Set TrimSuffixes to remove shell operators from package names (typically "&|;")

Examples:

// For npx (no subcommand):
extractor := PackageExtractor{
    CommandNames:       []string{"npx"},
    RequiredSubcommand: "",
    TrimSuffixes:       "&|;",
}

// For pip (with "install" subcommand):
extractor := PackageExtractor{
    CommandNames:       []string{"pip", "pip3"},
    RequiredSubcommand: "install",
    TrimSuffixes:       "&|;",
}

func (*PackageExtractor) ExtractPackages

func (pe *PackageExtractor) ExtractPackages(commands string) []string

ExtractPackages extracts package names from command strings using the configured extraction rules. It processes multi-line command strings and returns all found package names.

This is the main entry point for package extraction. Call this method with your command string(s) after configuring the PackageExtractor.

The extraction process:

  1. Split commands by newlines
  2. Split each line into words
  3. Find command name matches (from CommandNames)
  4. If RequiredSubcommand is set, look for that subcommand
  5. Skip flags (words starting with -)
  6. Extract package name and trim configured suffixes
  7. Return first package found per command invocation

Multi-line commands are supported:

commands := `pip install requests
pip install numpy`
packages := extractor.ExtractPackages(commands)
// Returns: []string{"requests", "numpy"}

Flags are automatically skipped:

packages := extractor.ExtractPackages("pip install --upgrade requests")
// Returns: []string{"requests"}

Shell operators are automatically trimmed:

packages := extractor.ExtractPackages("npx playwright;")
// Returns: []string{"playwright"}

Example usage with pip:

extractor := PackageExtractor{
    CommandNames:       []string{"pip", "pip3"},
    RequiredSubcommand: "install",
    TrimSuffixes:       "&|;",
}
packages := extractor.ExtractPackages("pip install requests==2.28.0")
// Returns: []string{"requests==2.28.0"}

Example usage with npx:

extractor := PackageExtractor{
    CommandNames:       []string{"npx"},
    RequiredSubcommand: "",
    TrimSuffixes:       "&|;",
}
packages := extractor.ExtractPackages("npx @playwright/mcp@latest")
// Returns: []string{"@playwright/mcp@latest"}

func (*PackageExtractor) FindPackageName

func (pe *PackageExtractor) FindPackageName(words []string, startIndex int) string

findPackageName finds and processes the package name starting at the given index. It skips flags (words starting with -) and returns the first non-flag word, trimming configured suffixes.

This method is exported to allow special-case extraction patterns (like uv) to reuse the package finding logic.

type PackageJSON

type PackageJSON struct {
	Name            string            `json:"name"`
	Private         bool              `json:"private"`
	License         string            `json:"license,omitempty"`
	Dependencies    map[string]string `json:"dependencies,omitempty"`
	DevDependencies map[string]string `json:"devDependencies,omitempty"`
}

PackageJSON represents the structure of a package.json file

type ParenthesesNode

type ParenthesesNode struct {
	Child ConditionNode
}

ParenthesesNode wraps a condition in parentheses for proper YAML interpretation

func (*ParenthesesNode) Render

func (p *ParenthesesNode) Render() string

type PermissionLevel

type PermissionLevel string

PermissionLevel represents the level of access (read, write, none)

const (
	PermissionRead  PermissionLevel = "read"
	PermissionWrite PermissionLevel = "write"
	PermissionNone  PermissionLevel = "none"
)

type PermissionScope

type PermissionScope string

PermissionScope represents a GitHub Actions permission scope

const (
	PermissionActions          PermissionScope = "actions"
	PermissionAttestations     PermissionScope = "attestations"
	PermissionChecks           PermissionScope = "checks"
	PermissionContents         PermissionScope = "contents"
	PermissionDeployments      PermissionScope = "deployments"
	PermissionDiscussions      PermissionScope = "discussions"
	PermissionIdToken          PermissionScope = "id-token"
	PermissionIssues           PermissionScope = "issues"
	PermissionMetadata         PermissionScope = "metadata"
	PermissionModels           PermissionScope = "models"
	PermissionPackages         PermissionScope = "packages"
	PermissionPages            PermissionScope = "pages"
	PermissionPullRequests     PermissionScope = "pull-requests"
	PermissionRepositoryProj   PermissionScope = "repository-projects"
	PermissionOrganizationProj PermissionScope = "organization-projects"
	PermissionSecurityEvents   PermissionScope = "security-events"
	PermissionStatuses         PermissionScope = "statuses"
)

func GetAllPermissionScopes

func GetAllPermissionScopes() []PermissionScope

GetAllPermissionScopes returns all available permission scopes

type Permissions

type Permissions struct {
	// contains filtered or unexported fields
}

Permissions represents GitHub Actions permissions It can be a shorthand (read-all, write-all, read, write, none) or a map of scopes to levels It can also have an "all" permission that expands to all scopes

func NewPermissions

func NewPermissions() *Permissions

NewPermissions creates a new Permissions with an empty map

func NewPermissionsActionsWrite

func NewPermissionsActionsWrite() *Permissions

NewPermissionsActionsWrite creates permissions with actions: write This is required for dispatching workflows via workflow_dispatch

func NewPermissionsActionsWriteContentsWriteIssuesWritePRWrite

func NewPermissionsActionsWriteContentsWriteIssuesWritePRWrite() *Permissions

NewPermissionsActionsWriteContentsWriteIssuesWritePRWrite creates permissions with actions: write, contents: write, issues: write, pull-requests: write This is required for the replaceActorsForAssignable GraphQL mutation used to assign GitHub Copilot agents to issues

func NewPermissionsAllRead

func NewPermissionsAllRead() *Permissions

NewPermissionsAllRead creates a Permissions with all: read

func NewPermissionsContentsRead

func NewPermissionsContentsRead() *Permissions

NewPermissionsContentsRead creates permissions with contents: read

func NewPermissionsContentsReadDiscussionsWrite

func NewPermissionsContentsReadDiscussionsWrite() *Permissions

NewPermissionsContentsReadDiscussionsWrite creates permissions with contents: read and discussions: write

func NewPermissionsContentsReadIssuesWrite

func NewPermissionsContentsReadIssuesWrite() *Permissions

NewPermissionsContentsReadIssuesWrite creates permissions with contents: read and issues: write

func NewPermissionsContentsReadIssuesWriteDiscussionsWrite added in v0.42.3

func NewPermissionsContentsReadIssuesWriteDiscussionsWrite() *Permissions

NewPermissionsContentsReadIssuesWriteDiscussionsWrite creates permissions with contents: read, issues: write, discussions: write This is used for create-discussion jobs that support fallback-to-issue when discussion creation fails

func NewPermissionsContentsReadIssuesWritePRWrite

func NewPermissionsContentsReadIssuesWritePRWrite() *Permissions

NewPermissionsContentsReadIssuesWritePRWrite creates permissions with contents: read, issues: write, pull-requests: write

func NewPermissionsContentsReadIssuesWritePRWriteDiscussionsWrite

func NewPermissionsContentsReadIssuesWritePRWriteDiscussionsWrite() *Permissions

NewPermissionsContentsReadIssuesWritePRWriteDiscussionsWrite creates permissions with contents: read, issues: write, pull-requests: write, discussions: write

func NewPermissionsContentsReadPRWrite

func NewPermissionsContentsReadPRWrite() *Permissions

NewPermissionsContentsReadPRWrite creates permissions with contents: read and pull-requests: write

func NewPermissionsContentsReadProjectsWrite

func NewPermissionsContentsReadProjectsWrite() *Permissions

NewPermissionsContentsReadProjectsWrite creates permissions with contents: read and organization-projects: write Note: organization-projects is only valid for GitHub App tokens, not workflow permissions

func NewPermissionsContentsReadSecurityEventsWrite

func NewPermissionsContentsReadSecurityEventsWrite() *Permissions

NewPermissionsContentsReadSecurityEventsWrite creates permissions with contents: read and security-events: write

func NewPermissionsContentsReadSecurityEventsWriteActionsRead

func NewPermissionsContentsReadSecurityEventsWriteActionsRead() *Permissions

NewPermissionsContentsReadSecurityEventsWriteActionsRead creates permissions with contents: read, security-events: write, actions: read

func NewPermissionsContentsWrite

func NewPermissionsContentsWrite() *Permissions

NewPermissionsContentsWrite creates permissions with contents: write

func NewPermissionsContentsWriteIssuesWritePRWrite

func NewPermissionsContentsWriteIssuesWritePRWrite() *Permissions

NewPermissionsContentsWriteIssuesWritePRWrite creates permissions with contents: write, issues: write, pull-requests: write

func NewPermissionsContentsWriteIssuesWritePRWriteDiscussionsWrite

func NewPermissionsContentsWriteIssuesWritePRWriteDiscussionsWrite() *Permissions

NewPermissionsContentsWriteIssuesWritePRWriteDiscussionsWrite creates permissions with contents: write, issues: write, pull-requests: write, discussions: write

func NewPermissionsContentsWritePRReadIssuesRead

func NewPermissionsContentsWritePRReadIssuesRead() *Permissions

NewPermissionsContentsWritePRReadIssuesRead creates permissions with contents: write, pull-requests: read, issues: read

func NewPermissionsContentsWritePRWrite added in v0.43.16

func NewPermissionsContentsWritePRWrite() *Permissions

NewPermissionsContentsWritePRWrite creates permissions with contents: write, pull-requests: write Used when create-pull-request has fallback-as-issue: false (no issue creation fallback)

func NewPermissionsDiscussionsWrite

func NewPermissionsDiscussionsWrite() *Permissions

NewPermissionsDiscussionsWrite creates permissions with discussions: write

func NewPermissionsEmpty

func NewPermissionsEmpty() *Permissions

NewPermissionsEmpty creates a Permissions that explicitly renders as "permissions: {}"

func NewPermissionsFromMap

func NewPermissionsFromMap(perms map[PermissionScope]PermissionLevel) *Permissions

NewPermissionsFromMap creates a Permissions from a map of scopes to levels

func NewPermissionsNone

func NewPermissionsNone() *Permissions

NewPermissionsNone creates a Permissions with none shorthand

func NewPermissionsReadAll

func NewPermissionsReadAll() *Permissions

NewPermissionsReadAll creates a Permissions with read-all shorthand

func NewPermissionsWriteAll

func NewPermissionsWriteAll() *Permissions

NewPermissionsWriteAll creates a Permissions with write-all shorthand

func (*Permissions) Get

Get gets the permission level for a specific scope

func (*Permissions) Merge

func (p *Permissions) Merge(other *Permissions)

Merge merges another Permissions into this one Write permission takes precedence over read (write implies read) Individual scope permissions override shorthand

func (*Permissions) RenderToYAML

func (p *Permissions) RenderToYAML() string

RenderToYAML renders the Permissions to GitHub Actions YAML format

func (*Permissions) Set

func (p *Permissions) Set(scope PermissionScope, level PermissionLevel)

Set sets a permission for a specific scope

type PermissionsConfig

type PermissionsConfig struct {
	// Shorthand permission (read-all, write-all, read, write, none)
	Shorthand string `json:"-"` // Not in JSON, set when parsing shorthand format

	// Detailed permissions by scope
	Actions              string `json:"actions,omitempty"`
	Checks               string `json:"checks,omitempty"`
	Contents             string `json:"contents,omitempty"`
	Deployments          string `json:"deployments,omitempty"`
	IDToken              string `json:"id-token,omitempty"`
	Issues               string `json:"issues,omitempty"`
	Discussions          string `json:"discussions,omitempty"`
	Packages             string `json:"packages,omitempty"`
	Pages                string `json:"pages,omitempty"`
	PullRequests         string `json:"pull-requests,omitempty"`
	RepositoryProjects   string `json:"repository-projects,omitempty"`
	SecurityEvents       string `json:"security-events,omitempty"`
	Statuses             string `json:"statuses,omitempty"`
	OrganizationProjects string `json:"organization-projects,omitempty"`
	OrganizationPackages string `json:"organization-packages,omitempty"`
}

PermissionsConfig represents GitHub Actions permissions configuration Supports both shorthand (read-all, write-all) and detailed scope-based permissions

type PermissionsParser

type PermissionsParser struct {
	// contains filtered or unexported fields
}

PermissionsParser provides functionality to parse and analyze GitHub Actions permissions

func NewPermissionsParser

func NewPermissionsParser(permissionsYAML string) *PermissionsParser

NewPermissionsParser creates a new PermissionsParser instance

func NewPermissionsParserFromValue

func NewPermissionsParserFromValue(permissionsValue any) *PermissionsParser

NewPermissionsParserFromValue creates a PermissionsParser from a frontmatter value (any type)

func (*PermissionsParser) HasContentsReadAccess

func (p *PermissionsParser) HasContentsReadAccess() bool

HasContentsReadAccess returns true if the permissions allow reading contents

func (*PermissionsParser) IsAllowed

func (p *PermissionsParser) IsAllowed(scope, level string) bool

IsAllowed checks if a specific permission scope has the specified access level scope: "contents", "issues", "pull-requests", etc. level: "read", "write", "none"

func (*PermissionsParser) ToPermissions

func (p *PermissionsParser) ToPermissions() *Permissions

ToPermissions converts a PermissionsParser to a Permissions object

type PermissionsValidationResult

type PermissionsValidationResult struct {
	MissingPermissions    map[PermissionScope]PermissionLevel // Permissions required but not granted
	ReadOnlyMode          bool                                // Whether the GitHub MCP is in read-only mode
	HasValidationIssues   bool                                // Whether there are any validation issues
	MissingToolsetDetails map[string][]PermissionScope        // Maps toolset name to missing permissions
}

PermissionsValidationResult contains the result of permissions validation

func ValidatePermissions

func ValidatePermissions(permissions *Permissions, githubTool ValidatableTool) *PermissionsValidationResult

ValidatePermissions validates that workflow permissions match the required GitHub MCP toolsets This is the general-purpose permission validator used during workflow compilation to check that the declared permissions are sufficient for the GitHub MCP toolsets being used.

Parameters:

  • permissions: The workflow's declared permissions
  • githubTool: The GitHub tool configuration implementing ValidatableTool interface

Returns:

  • A validation result indicating any missing permissions and which toolsets require them

Use ValidatePermissions (this function) for general permission validation against GitHub MCP toolsets. Use ValidateIncludedPermissions (in imports.go) when validating permissions from included/imported workflow files.

type PipDependency

type PipDependency struct {
	Name    string
	Version string // version specifier (e.g., ==1.0.0, >=2.0.0)
}

PipDependency represents a parsed pip package with version

type PlaywrightAllowedDomains

type PlaywrightAllowedDomains []PlaywrightDomain

PlaywrightAllowedDomains is a slice of allowed domain names for Playwright

func (PlaywrightAllowedDomains) ToStringSlice

func (p PlaywrightAllowedDomains) ToStringSlice() []string

ToStringSlice converts PlaywrightAllowedDomains to []string

type PlaywrightDockerArgs

type PlaywrightDockerArgs struct {
	ImageVersion      string // Version for Docker image (mcr.microsoft.com/playwright:version)
	MCPPackageVersion string // Version for NPM package (@playwright/mcp@version)
	AllowedDomains    []string
}

PlaywrightDockerArgs represents the common Docker arguments for Playwright container

type PlaywrightDomain

type PlaywrightDomain string

PlaywrightDomain represents a domain name allowed for Playwright browser automation

type PlaywrightToolConfig

type PlaywrightToolConfig struct {
	Version        string                   `yaml:"version,omitempty"`
	AllowedDomains PlaywrightAllowedDomains `yaml:"allowed_domains,omitempty"`
	Args           []string                 `yaml:"args,omitempty"`
}

PlaywrightToolConfig represents the configuration for the Playwright tool

type PluginInfo added in v0.42.14

type PluginInfo struct {
	Plugins     []string                    // Plugin repository slugs to install
	CustomToken string                      // Custom github-token for plugin installation
	MCPConfigs  map[string]*PluginMCPConfig // Per-plugin MCP configurations (keyed by plugin ID)
}

PluginInfo encapsulates all plugin-related configuration This consolidates plugins list, custom token, and per-plugin MCP configs

type PluginItem added in v0.42.14

type PluginItem struct {
	ID  string           `json:"id"`            // Plugin identifier/repository slug (e.g., "org/repo")
	MCP *PluginMCPConfig `json:"mcp,omitempty"` // Optional MCP configuration
}

PluginItem represents configuration for a single plugin Supports both simple string format and object format with MCP configuration

type PluginMCPConfig added in v0.42.14

type PluginMCPConfig struct {
	Env map[string]string `json:"env,omitempty"` // Environment variables for MCP server instantiation
}

PluginMCPConfig represents MCP configuration for a plugin

type PluginsConfig added in v0.42.6

type PluginsConfig struct {
	Repos       []string `json:"repos"`                  // List of plugin repository slugs (required)
	GitHubToken string   `json:"github-token,omitempty"` // Custom GitHub token for plugin installation
}

PluginsConfig represents plugin configuration for installation (for parsing only) Supports object format with repos list, optional custom github-token

type ProjectFieldDefinition

type ProjectFieldDefinition struct {
	Name     string   `yaml:"name" json:"name"`
	DataType string   `yaml:"data-type" json:"data_type"`
	Options  []string `yaml:"options,omitempty" json:"options,omitempty"`
}

ProjectFieldDefinition defines a project custom field configuration used by update_project operation=create_fields.

type ProjectView

type ProjectView struct {
	Name          string `yaml:"name" json:"name"`
	Layout        string `yaml:"layout" json:"layout"`
	Filter        string `yaml:"filter,omitempty" json:"filter,omitempty"`
	VisibleFields []int  `yaml:"visible-fields,omitempty" json:"visible_fields,omitempty"`
	Description   string `yaml:"description,omitempty" json:"description,omitempty"`
}

ProjectView defines a project view configuration

type PromptSection

type PromptSection struct {
	// Content is the actual prompt text or a reference to a file
	Content string
	// IsFile indicates if Content is a filename (true) or inline text (false)
	IsFile bool
	// ShellCondition is an optional bash condition (without 'if' keyword) to wrap this section
	// Example: "${{ github.event_name == 'issue_comment' }}" becomes a shell condition
	ShellCondition string
	// EnvVars contains environment variables needed for expressions in this section
	EnvVars map[string]string
}

PromptSection represents a section of prompt text to be appended

type PropertyAccessNode

type PropertyAccessNode struct {
	PropertyPath string
}

PropertyAccessNode represents property access like github.event.action

func BuildPropertyAccess

func BuildPropertyAccess(path string) *PropertyAccessNode

BuildPropertyAccess creates a property access node for GitHub context properties

func (*PropertyAccessNode) Render

func (p *PropertyAccessNode) Render() string

type PushToPullRequestBranchConfig

type PushToPullRequestBranchConfig struct {
	BaseSafeOutputConfig `yaml:",inline"`
	Target               string   `yaml:"target,omitempty"`              // Target for push-to-pull-request-branch: like add-comment but for pull requests
	TitlePrefix          string   `yaml:"title-prefix,omitempty"`        // Required title prefix for pull request validation
	Labels               []string `yaml:"labels,omitempty"`              // Required labels for pull request validation
	IfNoChanges          string   `yaml:"if-no-changes,omitempty"`       // Behavior when no changes to push: "warn", "error", or "ignore" (default: "warn")
	CommitTitleSuffix    string   `yaml:"commit-title-suffix,omitempty"` // Optional suffix to append to generated commit titles
}

PushToPullRequestBranchConfig holds configuration for pushing changes to a specific branch from agent output

type RateLimitConfig added in v0.43.6

type RateLimitConfig struct {
	Max          int      `json:"max,omitempty"`           // Maximum number of runs allowed per time window (default: 5)
	Window       int      `json:"window,omitempty"`        // Time window in minutes (default: 60)
	Events       []string `json:"events,omitempty"`        // Event types to apply rate limiting to (e.g., ["workflow_dispatch", "issue_comment"])
	IgnoredRoles []string `json:"ignored-roles,omitempty"` // Roles that are exempt from rate limiting (e.g., ["admin", "maintainer"])
}

RateLimitConfig represents rate limiting configuration for workflow triggers Limits how many times a user can trigger a workflow within a time window

type RemoveLabelsConfig

type RemoveLabelsConfig struct {
	BaseSafeOutputConfig   `yaml:",inline"`
	SafeOutputTargetConfig `yaml:",inline"`
	Allowed                []string `yaml:"allowed,omitempty"` // Optional list of allowed labels to remove. If omitted, any labels can be removed.
}

RemoveLabelsConfig holds configuration for removing labels from issues/PRs from agent output

type RenderCustomMCPToolConfigHandler

type RenderCustomMCPToolConfigHandler func(yaml *strings.Builder, toolName string, toolConfig map[string]any, isLast bool) error

RenderCustomMCPToolConfigHandler is a function type for rendering custom MCP tool configurations

type RepoMemoryConfig

type RepoMemoryConfig struct {
	BranchPrefix string            `yaml:"branch-prefix,omitempty"` // branch prefix (default: "memory")
	Memories     []RepoMemoryEntry `yaml:"memories,omitempty"`      // repo-memory configurations
}

RepoMemoryConfig holds configuration for repo-memory functionality

type RepoMemoryEntry

type RepoMemoryEntry struct {
	ID                string   `yaml:"id"`                           // memory identifier (required for array notation)
	TargetRepo        string   `yaml:"target-repo,omitempty"`        // target repository (default: current repo)
	BranchName        string   `yaml:"branch-name,omitempty"`        // branch name (default: memory/{memory-id})
	FileGlob          []string `yaml:"file-glob,omitempty"`          // file glob patterns for allowed files
	MaxFileSize       int      `yaml:"max-file-size,omitempty"`      // maximum size per file in bytes (default: 10KB)
	MaxFileCount      int      `yaml:"max-file-count,omitempty"`     // maximum file count per commit (default: 100)
	Description       string   `yaml:"description,omitempty"`        // optional description for this memory
	CreateOrphan      bool     `yaml:"create-orphan,omitempty"`      // create orphaned branch if missing (default: true)
	AllowedExtensions []string `yaml:"allowed-extensions,omitempty"` // allowed file extensions (default: [".json", ".jsonl", ".txt", ".md", ".csv"])
}

RepoMemoryEntry represents a single repo-memory configuration

type RepoMemoryToolConfig

type RepoMemoryToolConfig struct {
	// Can be boolean, object, or array - handled by this file
	Raw any `yaml:"-"`
}

RepoMemoryToolConfig represents the configuration for repo-memory in tools

type RepositoryFeatures

type RepositoryFeatures struct {
	HasDiscussions bool
	HasIssues      bool
}

RepositoryFeatures holds cached information about repository capabilities

type Runtime

type Runtime struct {
	ID              string            // Unique identifier (e.g., "node", "python")
	Name            string            // Display name (e.g., "Node.js", "Python")
	ActionRepo      string            // GitHub Actions repository (e.g., "actions/setup-node")
	ActionVersion   string            // Action version (e.g., "v4", without @ prefix)
	VersionField    string            // Field name for version in action (e.g., "node-version")
	DefaultVersion  string            // Default version to use
	Commands        []string          // Commands that indicate this runtime is needed
	ExtraWithFields map[string]string // Additional 'with' fields for the action
}

Runtime represents configuration for a runtime environment

type RuntimeConfig

type RuntimeConfig struct {
	Version string `json:"version,omitempty"` // Version of the runtime (e.g., "20" for Node, "3.11" for Python)
}

RuntimeConfig represents the configuration for a single runtime

type RuntimeMode

type RuntimeMode int

RuntimeMode represents the JavaScript runtime environment

const (
	// RuntimeModeGitHubScript indicates JavaScript running in actions/github-script
	// In this mode:
	// - All local requires must be bundled (no module system)
	// - module.exports statements must be removed
	// - No module object references allowed
	RuntimeModeGitHubScript RuntimeMode = iota

	// RuntimeModeNodeJS indicates JavaScript running as a Node.js script
	// In this mode:
	// - module.exports can be preserved
	// - Local requires can be kept if modules are available on filesystem
	// - Full Node.js module system is available
	RuntimeModeNodeJS
)

func (RuntimeMode) String

func (r RuntimeMode) String() string

String returns a string representation of the RuntimeMode

type RuntimeRequirement

type RuntimeRequirement struct {
	Runtime     *Runtime
	Version     string         // Empty string means use default
	ExtraFields map[string]any // Additional 'with' fields from user's setup step (e.g., cache settings)
	GoModFile   string         // Path to go.mod file for Go runtime (Go-specific)
}

RuntimeRequirement represents a detected runtime requirement

func DeduplicateRuntimeSetupStepsFromCustomSteps

func DeduplicateRuntimeSetupStepsFromCustomSteps(customSteps string, runtimeRequirements []RuntimeRequirement) (string, []RuntimeRequirement, error)

DeduplicateRuntimeSetupStepsFromCustomSteps removes runtime setup action steps from custom steps to avoid duplication when runtime steps are added before custom steps. This function parses the YAML custom steps, removes any steps that use runtime setup actions, and returns the deduplicated YAML.

It preserves user-customized setup actions (e.g., with specific versions) and filters the corresponding runtime from the requirements so we don't generate a duplicate runtime setup step.

func DetectRuntimeRequirements

func DetectRuntimeRequirements(workflowData *WorkflowData) []RuntimeRequirement

DetectRuntimeRequirements analyzes workflow data to detect required runtimes

type RuntimesConfig

type RuntimesConfig struct {
	Node   *RuntimeConfig `json:"node,omitempty"`   // Node.js runtime
	Python *RuntimeConfig `json:"python,omitempty"` // Python runtime
	Go     *RuntimeConfig `json:"go,omitempty"`     // Go runtime
	UV     *RuntimeConfig `json:"uv,omitempty"`     // uv package installer
	Bun    *RuntimeConfig `json:"bun,omitempty"`    // Bun runtime
	Deno   *RuntimeConfig `json:"deno,omitempty"`   // Deno runtime
}

RuntimesConfig represents the configuration for all runtime environments This provides type-safe access to runtime version overrides

type SRTFilesystemConfig

type SRTFilesystemConfig struct {
	DenyRead   []string `yaml:"denyRead" json:"denyRead"`
	AllowWrite []string `yaml:"allowWrite,omitempty" json:"allowWrite,omitempty"`
	DenyWrite  []string `yaml:"denyWrite" json:"denyWrite"`
}

SRTFilesystemConfig represents filesystem configuration for SRT

type SRTNetworkConfig

type SRTNetworkConfig struct {
	AllowedDomains      []string `yaml:"allowedDomains,omitempty" json:"allowedDomains,omitempty"`
	BlockedDomains      []string `yaml:"blockedDomains,omitempty" json:"blockedDomains"`
	AllowUnixSockets    []string `yaml:"allowUnixSockets,omitempty" json:"allowUnixSockets,omitempty"`
	AllowLocalBinding   bool     `yaml:"allowLocalBinding" json:"allowLocalBinding"`
	AllowAllUnixSockets bool     `yaml:"allowAllUnixSockets" json:"allowAllUnixSockets"`
}

SRTNetworkConfig represents network configuration for SRT

type SafeInputParam

type SafeInputParam struct {
	Type        string // JSON schema type (string, number, boolean, array, object)
	Description string // Description of the parameter
	Required    bool   // Whether the parameter is required
	Default     any    // Default value
}

SafeInputParam holds the configuration for a tool input parameter

type SafeInputToolConfig

type SafeInputToolConfig struct {
	Name        string                     // Tool name (key from the config)
	Description string                     // Required: tool description
	Inputs      map[string]*SafeInputParam // Optional: input parameters
	Script      string                     // JavaScript implementation (mutually exclusive with Run, Py, and Go)
	Run         string                     // Shell script implementation (mutually exclusive with Script, Py, and Go)
	Py          string                     // Python script implementation (mutually exclusive with Script, Run, and Go)
	Go          string                     // Go script implementation (mutually exclusive with Script, Run, and Py)
	Env         map[string]string          // Environment variables (typically for secrets)
	Timeout     int                        // Timeout in seconds for tool execution (default: 60)
}

SafeInputToolConfig holds the configuration for a single safe-input tool

type SafeInputsConfig

type SafeInputsConfig struct {
	Mode  string // Transport mode: "http" (default) or "stdio"
	Tools map[string]*SafeInputToolConfig
}

SafeInputsConfig holds the configuration for safe-inputs custom tools

func ParseSafeInputs

func ParseSafeInputs(frontmatter map[string]any) *SafeInputsConfig

ParseSafeInputs parses safe-inputs configuration from frontmatter (standalone function for testing)

type SafeInputsConfigJSON

type SafeInputsConfigJSON struct {
	ServerName string               `json:"serverName"`
	Version    string               `json:"version"`
	LogDir     string               `json:"logDir,omitempty"`
	Tools      []SafeInputsToolJSON `json:"tools"`
}

SafeInputsConfigJSON represents the tools.json configuration file structure

type SafeInputsToolJSON

type SafeInputsToolJSON struct {
	Name        string            `json:"name"`
	Description string            `json:"description"`
	InputSchema map[string]any    `json:"inputSchema"`
	Handler     string            `json:"handler,omitempty"`
	Env         map[string]string `json:"env,omitempty"`
	Timeout     int               `json:"timeout,omitempty"`
}

SafeInputsToolJSON represents a tool configuration for the tools.json file

type SafeJobConfig

type SafeJobConfig struct {
	// Standard GitHub Actions job properties
	Name        string            `yaml:"name,omitempty"`
	Description string            `yaml:"description,omitempty"`
	RunsOn      any               `yaml:"runs-on,omitempty"`
	If          string            `yaml:"if,omitempty"`
	Needs       []string          `yaml:"needs,omitempty"`
	Steps       []any             `yaml:"steps,omitempty"`
	Env         map[string]string `yaml:"env,omitempty"`
	Permissions map[string]string `yaml:"permissions,omitempty"`

	// Additional safe-job specific properties
	Inputs      map[string]*InputDefinition `yaml:"inputs,omitempty"`
	GitHubToken string                      `yaml:"github-token,omitempty"`
	Output      string                      `yaml:"output,omitempty"`
}

SafeJobConfig defines a safe job configuration with GitHub Actions job properties

type SafeOutputDiscussionFilterConfig

type SafeOutputDiscussionFilterConfig struct {
	SafeOutputFilterConfig `yaml:",inline"`
	RequiredCategory       string `yaml:"required-category,omitempty"` // Required category for discussion operations
}

SafeOutputDiscussionFilterConfig extends SafeOutputFilterConfig with discussion-specific fields.

func ParseDiscussionFilterConfig

func ParseDiscussionFilterConfig(configMap map[string]any) SafeOutputDiscussionFilterConfig

ParseDiscussionFilterConfig parses filter config plus required-category for discussion operations.

type SafeOutputFilterConfig

type SafeOutputFilterConfig struct {
	RequiredLabels      []string `yaml:"required-labels,omitempty"`       // Required labels for the operation
	RequiredTitlePrefix string   `yaml:"required-title-prefix,omitempty"` // Required title prefix for the operation
}

SafeOutputFilterConfig contains common filtering fields for safe output configurations. Embed this in safe output config structs that support filtering by labels or title prefix.

func ParseFilterConfig

func ParseFilterConfig(configMap map[string]any) SafeOutputFilterConfig

ParseFilterConfig parses required-labels and required-title-prefix fields from a config map.

type SafeOutputJobConfig

type SafeOutputJobConfig struct {
	// Job metadata
	JobName     string // e.g., "create_issue"
	StepName    string // e.g., "Create Output Issue"
	StepID      string // e.g., "create_issue"
	MainJobName string // Main workflow job name for dependencies

	// Custom environment variables specific to this safe output type
	CustomEnvVars []string

	// JavaScript script constant to include in the GitHub Script step
	Script string

	// Script name for looking up custom action path (optional)
	// If provided and action mode is custom, the compiler will use a custom action
	// instead of inline JavaScript. Example: "create_issue"
	ScriptName string

	// Job configuration
	Permissions     *Permissions      // Job permissions
	Outputs         map[string]string // Job outputs
	Condition       ConditionNode     // Job condition (if clause)
	Needs           []string          // Job dependencies
	PreSteps        []string          // Optional steps to run before the GitHub Script step
	PostSteps       []string          // Optional steps to run after the GitHub Script step
	Token           string            // GitHub token for this output type
	UseCopilotToken bool              // Whether to use Copilot token preference chain
	UseAgentToken   bool              // Whether to use agent token preference chain (config token > GH_AW_AGENT_TOKEN)
	TargetRepoSlug  string            // Target repository for cross-repo operations
}

SafeOutputJobConfig holds configuration for building a safe output job This config struct extracts the common parameters across all safe output job builders

type SafeOutputMessagesConfig

type SafeOutputMessagesConfig struct {
	Footer                         string `yaml:"footer,omitempty" json:"footer,omitempty"`                                                    // Custom footer message template
	FooterInstall                  string `yaml:"footer-install,omitempty" json:"footerInstall,omitempty"`                                     // Custom installation instructions template
	FooterWorkflowRecompile        string `yaml:"footer-workflow-recompile,omitempty" json:"footerWorkflowRecompile,omitempty"`                // Custom footer template for workflow recompile issues
	FooterWorkflowRecompileComment string `yaml:"footer-workflow-recompile-comment,omitempty" json:"footerWorkflowRecompileComment,omitempty"` // Custom footer template for comments on workflow recompile issues
	StagedTitle                    string `yaml:"staged-title,omitempty" json:"stagedTitle,omitempty"`                                         // Custom styled mode title template
	StagedDescription              string `yaml:"staged-description,omitempty" json:"stagedDescription,omitempty"`                             // Custom staged mode description template
	AppendOnlyComments             bool   `yaml:"append-only-comments,omitempty" json:"appendOnlyComments,omitempty"`                          // If true, post run status as new comments instead of updating the activation comment
	RunStarted                     string `yaml:"run-started,omitempty" json:"runStarted,omitempty"`                                           // Custom workflow activation message template
	RunSuccess                     string `yaml:"run-success,omitempty" json:"runSuccess,omitempty"`                                           // Custom workflow success message template
	RunFailure                     string `yaml:"run-failure,omitempty" json:"runFailure,omitempty"`                                           // Custom workflow failure message template
	DetectionFailure               string `yaml:"detection-failure,omitempty" json:"detectionFailure,omitempty"`                               // Custom detection job failure message template
	AgentFailureIssue              string `yaml:"agent-failure-issue,omitempty" json:"agentFailureIssue,omitempty"`                            // Custom footer template for agent failure tracking issues
	AgentFailureComment            string `yaml:"agent-failure-comment,omitempty" json:"agentFailureComment,omitempty"`                        // Custom footer template for comments on agent failure tracking issues
}

SafeOutputMessagesConfig holds custom message templates for safe-output footer and notification messages

type SafeOutputStepConfig

type SafeOutputStepConfig struct {
	StepName        string            // Human-readable step name (e.g., "Create Issue")
	StepID          string            // Step ID for referencing outputs (e.g., "create_issue")
	Script          string            // JavaScript script to execute (for inline mode)
	ScriptName      string            // Name of the script in the registry (for file mode)
	CustomEnvVars   []string          // Environment variables specific to this step
	Condition       ConditionNode     // Step-level condition (if clause)
	Token           string            // GitHub token for this step
	UseCopilotToken bool              // Whether to use Copilot token preference chain
	UseAgentToken   bool              // Whether to use agent token preference chain
	PreSteps        []string          // Optional steps to run before the script step
	PostSteps       []string          // Optional steps to run after the script step
	Outputs         map[string]string // Outputs from this step
}

SafeOutputStepConfig holds configuration for building a single safe output step within the consolidated safe-outputs job

type SafeOutputTargetConfig

type SafeOutputTargetConfig struct {
	Target         string   `yaml:"target,omitempty"`        // Target for the operation: "triggering" (default), "*" (any item), or explicit number
	TargetRepoSlug string   `yaml:"target-repo,omitempty"`   // Target repository in format "owner/repo" for cross-repository operations
	AllowedRepos   []string `yaml:"allowed-repos,omitempty"` // List of additional repositories that operations can target (additionally to the target-repo)
}

SafeOutputTargetConfig contains common target-related fields for safe output configurations. Embed this in safe output config structs that support targeting specific items.

func ParseTargetConfig

func ParseTargetConfig(configMap map[string]any) (SafeOutputTargetConfig, bool)

ParseTargetConfig parses target and target-repo fields from a config map. Returns the parsed SafeOutputTargetConfig and a boolean indicating if there was a validation error. If target-repo is "*" (wildcard), it returns an error (second return value is true).

type SafeOutputsConfig

type SafeOutputsConfig struct {
	CreateIssues                    *CreateIssuesConfig                    `yaml:"create-issues,omitempty"`
	CreateDiscussions               *CreateDiscussionsConfig               `yaml:"create-discussions,omitempty"`
	UpdateDiscussions               *UpdateDiscussionsConfig               `yaml:"update-discussion,omitempty"`
	CloseDiscussions                *CloseDiscussionsConfig                `yaml:"close-discussions,omitempty"`
	CloseIssues                     *CloseIssuesConfig                     `yaml:"close-issue,omitempty"`
	ClosePullRequests               *ClosePullRequestsConfig               `yaml:"close-pull-request,omitempty"`
	MarkPullRequestAsReadyForReview *MarkPullRequestAsReadyForReviewConfig `yaml:"mark-pull-request-as-ready-for-review,omitempty"`
	AddComments                     *AddCommentsConfig                     `yaml:"add-comments,omitempty"`
	CreatePullRequests              *CreatePullRequestsConfig              `yaml:"create-pull-requests,omitempty"`
	CreatePullRequestReviewComments *CreatePullRequestReviewCommentsConfig `yaml:"create-pull-request-review-comments,omitempty"`
	SubmitPullRequestReview         *SubmitPullRequestReviewConfig         `yaml:"submit-pull-request-review,omitempty"` // Submit a PR review with status (APPROVE, REQUEST_CHANGES, COMMENT)
	CreateCodeScanningAlerts        *CreateCodeScanningAlertsConfig        `yaml:"create-code-scanning-alerts,omitempty"`
	AutofixCodeScanningAlert        *AutofixCodeScanningAlertConfig        `yaml:"autofix-code-scanning-alert,omitempty"`
	AddLabels                       *AddLabelsConfig                       `yaml:"add-labels,omitempty"`
	RemoveLabels                    *RemoveLabelsConfig                    `yaml:"remove-labels,omitempty"`
	AddReviewer                     *AddReviewerConfig                     `yaml:"add-reviewer,omitempty"`
	AssignMilestone                 *AssignMilestoneConfig                 `yaml:"assign-milestone,omitempty"`
	AssignToAgent                   *AssignToAgentConfig                   `yaml:"assign-to-agent,omitempty"`
	AssignToUser                    *AssignToUserConfig                    `yaml:"assign-to-user,omitempty"`     // Assign users to issues
	UnassignFromUser                *UnassignFromUserConfig                `yaml:"unassign-from-user,omitempty"` // Remove assignees from issues
	UpdateIssues                    *UpdateIssuesConfig                    `yaml:"update-issues,omitempty"`
	UpdatePullRequests              *UpdatePullRequestsConfig              `yaml:"update-pull-request,omitempty"` // Update GitHub pull request title/body
	PushToPullRequestBranch         *PushToPullRequestBranchConfig         `yaml:"push-to-pull-request-branch,omitempty"`
	UploadAssets                    *UploadAssetsConfig                    `yaml:"upload-asset,omitempty"`
	UpdateRelease                   *UpdateReleaseConfig                   `yaml:"update-release,omitempty"`               // Update GitHub release descriptions
	CreateAgentSessions             *CreateAgentSessionConfig              `yaml:"create-agent-session,omitempty"`         // Create GitHub Copilot agent sessions
	UpdateProjects                  *UpdateProjectConfig                   `yaml:"update-project,omitempty"`               // Smart project board management (create/add/update)
	CreateProjects                  *CreateProjectsConfig                  `yaml:"create-project,omitempty"`               // Create GitHub Projects V2
	CreateProjectStatusUpdates      *CreateProjectStatusUpdateConfig       `yaml:"create-project-status-update,omitempty"` // Create GitHub project status updates
	LinkSubIssue                    *LinkSubIssueConfig                    `yaml:"link-sub-issue,omitempty"`               // Link issues as sub-issues
	HideComment                     *HideCommentConfig                     `yaml:"hide-comment,omitempty"`                 // Hide comments
	DispatchWorkflow                *DispatchWorkflowConfig                `yaml:"dispatch-workflow,omitempty"`            // Dispatch workflow_dispatch events to other workflows
	MissingTool                     *MissingToolConfig                     `yaml:"missing-tool,omitempty"`                 // Optional for reporting missing functionality
	MissingData                     *MissingDataConfig                     `yaml:"missing-data,omitempty"`                 // Optional for reporting missing data required to achieve goals
	NoOp                            *NoOpConfig                            `yaml:"noop,omitempty"`                         // No-op output for logging only (always available as fallback)
	ThreatDetection                 *ThreatDetectionConfig                 `yaml:"threat-detection,omitempty"`             // Threat detection configuration
	Jobs                            map[string]*SafeJobConfig              `yaml:"jobs,omitempty"`                         // Safe-jobs configuration (moved from top-level)
	App                             *GitHubAppConfig                       `yaml:"app,omitempty"`                          // GitHub App credentials for token minting
	AllowedDomains                  []string                               `yaml:"allowed-domains,omitempty"`
	AllowGitHubReferences           []string                               `yaml:"allowed-github-references,omitempty"` // Allowed repositories for GitHub references (e.g., ["repo", "org/repo2"])
	Staged                          bool                                   `yaml:"staged,omitempty"`                    // If true, emit step summary messages instead of making GitHub API calls
	Env                             map[string]string                      `yaml:"env,omitempty"`                       // Environment variables to pass to safe output jobs
	GitHubToken                     string                                 `yaml:"github-token,omitempty"`              // GitHub token for safe output jobs
	MaximumPatchSize                int                                    `yaml:"max-patch-size,omitempty"`            // Maximum allowed patch size in KB (defaults to 1024)
	RunsOn                          string                                 `yaml:"runs-on,omitempty"`                   // Runner configuration for safe-outputs jobs
	Messages                        *SafeOutputMessagesConfig              `yaml:"messages,omitempty"`                  // Custom message templates for footer and notifications
	Mentions                        *MentionsConfig                        `yaml:"mentions,omitempty"`                  // Configuration for @mention filtering in safe outputs
	Footer                          *bool                                  `yaml:"footer,omitempty"`                    // Global footer control - when false, omits visible footer from all safe outputs (XML markers still included)
}

SafeOutputsConfig holds configuration for automatic output routes

type SandboxConfig

type SandboxConfig struct {
	// New fields
	Agent *AgentSandboxConfig      `yaml:"agent,omitempty"` // Agent sandbox configuration
	MCP   *MCPGatewayRuntimeConfig `yaml:"mcp,omitempty"`   // MCP gateway configuration

	// Legacy fields (for backward compatibility)
	Type   SandboxType           `yaml:"type,omitempty"`   // Sandbox type: "default" or "sandbox-runtime"
	Config *SandboxRuntimeConfig `yaml:"config,omitempty"` // Custom SRT config (optional)
}

SandboxConfig represents the top-level sandbox configuration from front matter New format: { agent: "awf"|"srt"|{type, config}, mcp: {port, command, ...} } Legacy format: "default"|"sandbox-runtime" or { type, config }

type SandboxRuntimeConfig

type SandboxRuntimeConfig struct {
	// Network is only used internally for generating SRT settings JSON output.
	// It is NOT user-configurable from sandbox.agent.config (yaml:"-" prevents parsing).
	// The json tag is needed for output serialization to .srt-settings.json.
	Network                   *SRTNetworkConfig    `yaml:"-" json:"network,omitempty"`
	Filesystem                *SRTFilesystemConfig `yaml:"filesystem,omitempty" json:"filesystem,omitempty"`
	IgnoreViolations          map[string][]string  `yaml:"ignoreViolations,omitempty" json:"ignoreViolations,omitempty"`
	EnableWeakerNestedSandbox bool                 `yaml:"enableWeakerNestedSandbox" json:"enableWeakerNestedSandbox"`
}

SandboxRuntimeConfig represents the Anthropic Sandbox Runtime configuration This matches the TypeScript SandboxRuntimeConfig interface Note: Network configuration is controlled by the top-level 'network' field, not this struct

type SandboxType

type SandboxType string

SandboxType represents the type of sandbox to use

const (
	SandboxTypeAWF     SandboxType = "awf"             // Uses AWF (Agent Workflow Firewall)
	SandboxTypeSRT     SandboxType = "srt"             // Uses Anthropic Sandbox Runtime
	SandboxTypeDefault SandboxType = "default"         // Alias for AWF (backward compat)
	SandboxTypeRuntime SandboxType = "sandbox-runtime" // Alias for SRT (backward compat)
)

type SanitizeOptions

type SanitizeOptions struct {
	// PreserveSpecialChars is a list of special characters to preserve during sanitization.
	// Common characters include '.', '_'. If nil or empty, only alphanumeric and hyphens are preserved.
	PreserveSpecialChars []rune

	// TrimHyphens controls whether leading and trailing hyphens are removed from the result.
	// When true, hyphens at the start and end of the sanitized name are trimmed.
	TrimHyphens bool

	// DefaultValue is returned when the sanitized name is empty after all transformations.
	// If empty string, no default is applied.
	DefaultValue string
}

SanitizeOptions configures the behavior of the SanitizeName function.

type ScriptFile

type ScriptFile struct {
	// Path is the relative path within ScriptsBasePath (e.g., "create_issue.cjs")
	Path string
	// Content is the JavaScript content to write
	Content string
	// Hash is a short hash of the content for cache invalidation
	Hash string
}

ScriptFile represents a JavaScript file to be written to disk

func PrepareFilesForFileMode

func PrepareFilesForFileMode(files []ScriptFile) []ScriptFile

PrepareFilesForFileMode prepares all collected files for file mode by rewriting their require statements to use absolute paths.

type ScriptFilesResult

type ScriptFilesResult struct {
	// Files is the list of files to write, deduplicated and sorted
	Files []ScriptFile
	// MainScriptPath is the path to the main entry point script
	MainScriptPath string
	// TotalSize is the total size of all files in bytes
	TotalSize int
}

ScriptFilesResult contains the collected script files and metadata

func CollectAllJobScriptFiles

func CollectAllJobScriptFiles(scriptNames []string, sources map[string]string) (*ScriptFilesResult, error)

CollectAllJobScriptFiles collects all JavaScript files needed by multiple scripts in a single job. This deduplicates common helper files across different safe output types.

Parameters:

  • scriptNames: List of script names to collect (e.g., ["create_issue", "add_comment"])
  • sources: Map of all available JavaScript sources

Returns a combined ScriptFilesResult with all deduplicated files.

func CollectScriptDependencies

func CollectScriptDependencies(scriptName string, mainContent string, sources map[string]string) (*ScriptFilesResult, error)

CollectScriptDependencies collects only the dependencies of a script (not the main script itself). This is used when the main script is inlined in github-script but its dependencies need to be written to disk.

Parameters:

  • scriptName: Name of the main script (e.g., "create_issue")
  • mainContent: The main script content
  • sources: Map of all available JavaScript sources (from GetJavaScriptSources())

Returns a ScriptFilesResult with only the dependency files, or an error if a required file is missing.

func CollectScriptFiles

func CollectScriptFiles(scriptName string, mainContent string, sources map[string]string) (*ScriptFilesResult, error)

CollectScriptFiles recursively collects all JavaScript files used by a script. It starts from the main script and follows all local require() statements. Top-level await patterns (like `await main();`) are patched to work in CommonJS.

Parameters:

  • scriptName: Name of the main script (e.g., "create_issue")
  • mainContent: The main script content
  • sources: Map of all available JavaScript sources (from GetJavaScriptSources())

Returns a ScriptFilesResult with all files needed, or an error if a required file is missing.

Note: This includes the main script in the output. Use CollectScriptDependencies if you only want the dependencies (for when the main script is inlined in github-script).

type ScriptRegistry

type ScriptRegistry struct {
	// contains filtered or unexported fields
}

ScriptRegistry manages lazy bundling of JavaScript scripts. It provides a centralized place to register source scripts and retrieve bundled versions on-demand with caching.

Thread-safe: All operations use internal synchronization.

Usage:

registry := NewScriptRegistry()
registry.Register("my_script", myScriptSource)
bundled := registry.Get("my_script")

func NewScriptRegistry

func NewScriptRegistry() *ScriptRegistry

NewScriptRegistry creates a new empty script registry.

func (*ScriptRegistry) Get

func (r *ScriptRegistry) Get(name string) string

Get retrieves a bundled script by name. Bundling is performed lazily on first access and cached for subsequent calls.

If bundling fails, the original source is returned as a fallback. If the script is not registered, an empty string is returned.

Thread-safe: Multiple goroutines can call Get concurrently.

DEPRECATED: Use GetWithMode instead to specify the expected runtime mode. This allows the compiler to verify the runtime mode matches the registered mode.

func (*ScriptRegistry) GetActionPath

func (r *ScriptRegistry) GetActionPath(name string) string

GetActionPath retrieves the custom action path for a script, if registered. Returns an empty string if the script doesn't have a custom action path.

func (*ScriptRegistry) GetSource

func (r *ScriptRegistry) GetSource(name string) string

GetSource retrieves the original (unbundled) source for a script. Useful for testing or when bundling is not needed.

func (*ScriptRegistry) GetWithMode

func (r *ScriptRegistry) GetWithMode(name string, expectedMode RuntimeMode) string

GetWithMode retrieves a bundled script by name with runtime mode verification. Bundling is performed lazily on first access and cached for subsequent calls.

The expectedMode parameter allows the compiler to verify that the registered runtime mode matches what the caller expects. If there's a mismatch, a warning is logged but the script is still returned to avoid breaking existing workflows.

If bundling fails, the original source is returned as a fallback. If the script is not registered, an empty string is returned.

Thread-safe: Multiple goroutines can call GetWithMode concurrently.

func (*ScriptRegistry) Has

func (r *ScriptRegistry) Has(name string) bool

Has checks if a script is registered in the registry.

func (*ScriptRegistry) Names

func (r *ScriptRegistry) Names() []string

Names returns a list of all registered script names. Useful for debugging and testing.

func (*ScriptRegistry) Register

func (r *ScriptRegistry) Register(name string, source string) error

Register adds a script source to the registry. The script will be bundled lazily on first access via Get(). Scripts registered this way default to RuntimeModeGitHubScript.

Parameters:

  • name: Unique identifier for the script (e.g., "create_issue", "add_comment")
  • source: The raw JavaScript source code (typically from go:embed)

If a script with the same name already exists, it will be overwritten. This is useful for testing but should be avoided in production.

Returns an error if validation fails.

func (*ScriptRegistry) RegisterWithAction

func (r *ScriptRegistry) RegisterWithAction(name string, source string, mode RuntimeMode, actionPath string) error

RegisterWithAction registers a script with both inline code and a custom action path. This allows the compiler to choose between inline mode (using actions/github-script) or custom action mode (using the provided action path).

Parameters:

  • name: Unique identifier for the script (e.g., "create_issue")
  • source: The raw JavaScript source code (for inline mode)
  • mode: Runtime mode for bundling (GitHub Script or Node.js)
  • actionPath: Path to custom action (e.g., "./actions/create-issue" for development)

The actionPath should be a relative path from the repository root for development mode. In the future, this can be extended to support versioned references like "github/gh-aw/.github/actions/create-issue@SHA" for release mode.

Returns an error if validation fails, allowing the caller to handle gracefully instead of crashing the process.

func (*ScriptRegistry) RegisterWithMode

func (r *ScriptRegistry) RegisterWithMode(name string, source string, mode RuntimeMode) error

RegisterWithMode adds a script source to the registry with a specific runtime mode. The script will be bundled lazily on first access via Get(). Performs compile-time validation to ensure the script follows runtime mode conventions.

Parameters:

  • name: Unique identifier for the script (e.g., "create_issue", "add_comment")
  • source: The raw JavaScript source code (typically from go:embed)
  • mode: Runtime mode for bundling (GitHub Script or Node.js)

If a script with the same name already exists, it will be overwritten. This is useful for testing but should be avoided in production.

Compile-time validations:

  • GitHub Script mode: validates no execSync usage (should use exec instead)
  • Node.js mode: validates no GitHub Actions globals (core.*, exec.*, github.*)

Returns an error if validation fails, allowing the caller to handle gracefully instead of crashing the process.

type SecretExpression

type SecretExpression struct {
	VarName  string // The secret variable name (e.g., "DD_API_KEY")
	FullExpr string // The full expression (e.g., "${{ secrets.DD_API_KEY }}")
}

SecretExpression represents a parsed secret expression

type SecretMaskingConfig

type SecretMaskingConfig struct {
	Steps []map[string]any `yaml:"steps,omitempty"` // Additional secret redaction steps to inject after built-in redaction
}

SecretMaskingConfig holds configuration for secret redaction behavior

type SecurityFinding added in v0.43.12

type SecurityFinding struct {
	Category    SecurityFindingCategory
	Description string
	Line        int    // 1-based line number where the issue was found, 0 if unknown
	Snippet     string // Short excerpt of the problematic content
}

SecurityFinding represents a single security issue found in markdown content

func ScanMarkdownSecurity added in v0.43.12

func ScanMarkdownSecurity(content string) []SecurityFinding

ScanMarkdownSecurity scans markdown content for dangerous or malicious patterns. It automatically strips YAML frontmatter (delimited by ---) so that only the markdown body is scanned. Line numbers in returned findings are adjusted to match the original file. Returns a list of findings. If non-empty, the content should be rejected.

func (SecurityFinding) String added in v0.43.12

func (f SecurityFinding) String() string

String returns a human-readable description of the finding

type SecurityFindingCategory added in v0.43.12

type SecurityFindingCategory string

SecurityFindingCategory represents a category of security finding

const (
	// CategoryUnicodeAbuse covers zero-width characters, bidi overrides, and control characters
	CategoryUnicodeAbuse SecurityFindingCategory = "unicode-abuse"
	// CategoryHiddenContent covers HTML comments with payloads, hidden spans, CSS hiding
	CategoryHiddenContent SecurityFindingCategory = "hidden-content"
	// CategoryObfuscatedLinks covers data URIs, mismatched links, encoded URLs
	CategoryObfuscatedLinks SecurityFindingCategory = "obfuscated-links"
	// CategoryHTMLAbuse covers script/iframe/object/embed tags and event handlers
	CategoryHTMLAbuse SecurityFindingCategory = "html-abuse"
	// CategoryEmbeddedFiles covers SVG scripts, data-URI image payloads
	CategoryEmbeddedFiles SecurityFindingCategory = "embedded-files"
	// CategorySocialEngineering covers misleading formatting and disguised commands
	CategorySocialEngineering SecurityFindingCategory = "social-engineering"
)

type SecurityProvider

type SecurityProvider interface {
	// GetDefaultDetectionModel returns the default model to use for threat detection
	// If empty, no default model is applied and the engine uses its standard default
	GetDefaultDetectionModel() string

	// GetRequiredSecretNames returns the list of secret names that this engine needs for execution
	// This includes engine-specific auth tokens and the MCP gateway API key when MCP servers are present
	// Returns: slice of secret names (e.g., ["COPILOT_GITHUB_TOKEN", "MCP_GATEWAY_API_KEY"])
	GetRequiredSecretNames(workflowData *WorkflowData) []string
}

SecurityProvider handles security-related configuration Engines can optionally implement this to provide security features

type SerenaLangConfig

type SerenaLangConfig struct {
	Version      string `yaml:"version,omitempty"`
	GoModFile    string `yaml:"go-mod-file,omitempty"`   // Path to go.mod file (Go only)
	GoplsVersion string `yaml:"gopls-version,omitempty"` // Version of gopls to install (Go only)
}

SerenaLangConfig represents per-language configuration for Serena

type SerenaToolConfig

type SerenaToolConfig struct {
	Version   string                       `yaml:"version,omitempty"`
	Args      []string                     `yaml:"args,omitempty"`
	Mode      string                       `yaml:"mode,omitempty"` // "docker" (default) or "local" (uses uvx)
	Languages map[string]*SerenaLangConfig `yaml:"languages,omitempty"`
	// ShortSyntax stores the array of language names when using short syntax (e.g., ["go", "typescript"])
	ShortSyntax []string `yaml:"-"`
}

SerenaToolConfig represents the configuration for the Serena MCP tool

type SessionContent

type SessionContent struct {
	Type      string         `json:"type"`
	Text      string         `json:"text,omitempty"`
	ID        string         `json:"id,omitempty"`
	Name      string         `json:"name,omitempty"`
	Input     map[string]any `json:"input,omitempty"`
	ToolUseID string         `json:"tool_use_id,omitempty"`
	Content   string         `json:"content,omitempty"`
}

SessionContent represents content items in messages

type SessionEntry

type SessionEntry struct {
	Type     string          `json:"type"`
	Subtype  string          `json:"subtype,omitempty"`
	Message  *SessionMessage `json:"message,omitempty"`
	Usage    *SessionUsage   `json:"usage,omitempty"`
	NumTurns int             `json:"num_turns,omitempty"`
	RawData  map[string]any  `json:"-"`
}

SessionEntry represents a single entry in a Copilot session JSONL file

type SessionMessage

type SessionMessage struct {
	Content []SessionContent `json:"content"`
}

SessionMessage represents the message field in session entries

type SessionUsage

type SessionUsage struct {
	InputTokens  int `json:"input_tokens"`
	OutputTokens int `json:"output_tokens"`
}

SessionUsage represents token usage in a session result entry

type SharedWorkflowError

type SharedWorkflowError struct {
	Path string // File path of the shared workflow
}

SharedWorkflowError represents a workflow that is missing the 'on' field and should be treated as a shared/importable workflow component rather than a standalone workflow. This is not an actual error - it's a signal that compilation should be skipped with an informational message.

func NewSharedWorkflowError

func NewSharedWorkflowError(path string) *SharedWorkflowError

NewSharedWorkflowError creates a new shared workflow error

func (*SharedWorkflowError) Error

func (e *SharedWorkflowError) Error() string

Error implements the error interface Returns a formatted info message explaining that this is a shared workflow

func (*SharedWorkflowError) IsSharedWorkflow

func (e *SharedWorkflowError) IsSharedWorkflow() bool

IsSharedWorkflow returns true, indicating this is a shared workflow

type SkipIfMatchConfig

type SkipIfMatchConfig struct {
	Query string // GitHub search query to check before running workflow
	Max   int    // Maximum number of matches before skipping (defaults to 1)
}

SkipIfMatchConfig holds the configuration for skip-if-match conditions

type SkipIfNoMatchConfig

type SkipIfNoMatchConfig struct {
	Query string // GitHub search query to check before running workflow
	Min   int    // Minimum number of matches required to proceed (defaults to 1)
}

SkipIfNoMatchConfig holds the configuration for skip-if-no-match conditions

type StepOrderTracker

type StepOrderTracker struct {
	// contains filtered or unexported fields
}

StepOrderTracker tracks the order of steps generated during compilation

func NewStepOrderTracker

func NewStepOrderTracker() *StepOrderTracker

NewStepOrderTracker creates a new step order tracker

func (*StepOrderTracker) MarkAgentExecutionComplete

func (t *StepOrderTracker) MarkAgentExecutionComplete()

MarkAgentExecutionComplete marks that we've passed the agent execution step Validation only applies to steps after this point

func (*StepOrderTracker) RecordArtifactUpload

func (t *StepOrderTracker) RecordArtifactUpload(stepName string, uploadPaths []string)

RecordArtifactUpload records that an artifact upload step was added

func (*StepOrderTracker) RecordSecretRedaction

func (t *StepOrderTracker) RecordSecretRedaction(stepName string)

RecordSecretRedaction records that a secret redaction step was added

func (*StepOrderTracker) ValidateStepOrdering

func (t *StepOrderTracker) ValidateStepOrdering() error

ValidateStepOrdering validates that secret redaction happens before artifact uploads and that all uploaded paths are covered by secret redaction

type StepRecord

type StepRecord struct {
	Type        StepType
	Name        string
	Order       int      // Order in which this step was added
	UploadPaths []string // For artifact upload steps, the paths being uploaded
}

StepRecord tracks a step that was generated during compilation

type StepType

type StepType int

StepType represents the type of step being generated

const (
	StepTypeSecretRedaction StepType = iota
	StepTypeArtifactUpload
	StepTypeOther
)

type StringLiteralNode

type StringLiteralNode struct {
	Value string
}

StringLiteralNode represents a string literal value

func BuildStringLiteral

func BuildStringLiteral(value string) *StringLiteralNode

BuildStringLiteral creates a string literal node

func (*StringLiteralNode) Render

func (s *StringLiteralNode) Render() string

type SubmitPullRequestReviewConfig added in v0.43.17

type SubmitPullRequestReviewConfig struct {
	BaseSafeOutputConfig `yaml:",inline"`
	Footer               *bool `yaml:"footer,omitempty"` // Controls whether AI-generated footer is added to the review body. When false, footer is omitted.
}

SubmitPullRequestReviewConfig holds configuration for submitting a GitHub pull request review This works in conjunction with create-pull-request-review-comment: all review comments are collected and submitted as a single PR review with the configured event type. If this safe output type is not configured, review comments default to event: "COMMENT".

type TemplateInjectionViolation

type TemplateInjectionViolation struct {
	Expression string // The unsafe expression (e.g., "${{ github.event.issue.title }}")
	Snippet    string // Code snippet showing the violation context
	Context    string // Expression context (e.g., "github.event", "steps.*.outputs")
}

TemplateInjectionViolation represents a detected template injection risk

type TernaryNode

type TernaryNode struct {
	Condition  ConditionNode
	TrueValue  ConditionNode
	FalseValue ConditionNode
}

TernaryNode represents ternary conditional expressions like condition ? true_value : false_value

func BuildTernary

func BuildTernary(condition ConditionNode, trueValue ConditionNode, falseValue ConditionNode) *TernaryNode

BuildTernary creates a ternary conditional expression

func (*TernaryNode) Render

func (t *TernaryNode) Render() string

type ThreatDetectionConfig

type ThreatDetectionConfig struct {
	Prompt         string        `yaml:"prompt,omitempty"`        // Additional custom prompt instructions to append
	Steps          []any         `yaml:"steps,omitempty"`         // Array of extra job steps
	EngineConfig   *EngineConfig `yaml:"engine-config,omitempty"` // Extended engine configuration for threat detection
	EngineDisabled bool          `yaml:"-"`                       // Internal flag: true when engine is explicitly set to false
}

ThreatDetectionConfig holds configuration for threat detection in agent output

type TimeDelta

type TimeDelta struct {
	Hours   int
	Days    int
	Minutes int
	Weeks   int
	Months  int
}

TimeDelta represents a time duration that can be added to a base time

func (*TimeDelta) String

func (td *TimeDelta) String() string

String returns a human-readable representation of the TimeDelta

type ToolCallInfo

type ToolCallInfo struct {
	Name          string        // Prettified tool name (e.g., "github::search_issues", "bash")
	CallCount     int           // Number of times this tool was called
	MaxInputSize  int           // Maximum input size in tokens for any call
	MaxOutputSize int           // Maximum output size in tokens for any call
	MaxDuration   time.Duration // Maximum execution duration for any call
}

ToolCallInfo represents statistics for a single tool

type ToolConfig

type ToolConfig interface {
	GetString(key string) (string, bool)
	GetStringArray(key string) ([]string, bool)
	GetStringMap(key string) (map[string]string, bool)
	GetAny(key string) (any, bool)
}

ToolConfig represents a tool configuration interface for type safety

type Tools

type Tools = ToolsConfig

Tools is a type alias for ToolsConfig for backward compatibility. New code should prefer using ToolsConfig to be explicit about the unified configuration pattern.

func NewTools

func NewTools(toolsMap map[string]any) *Tools

NewTools creates a new Tools instance from a map

func (*Tools) GetToolNames

func (t *Tools) GetToolNames() []string

GetToolNames returns a list of all tool names configured

func (*Tools) HasTool

func (t *Tools) HasTool(name string) bool

HasTool checks if a tool is present in the configuration

type ToolsConfig

type ToolsConfig struct {
	// Built-in tools - using pointers to distinguish between "not set" and "set to nil/empty"
	GitHub           *GitHubToolConfig           `yaml:"github,omitempty"`
	Bash             *BashToolConfig             `yaml:"bash,omitempty"`
	WebFetch         *WebFetchToolConfig         `yaml:"web-fetch,omitempty"`
	WebSearch        *WebSearchToolConfig        `yaml:"web-search,omitempty"`
	Edit             *EditToolConfig             `yaml:"edit,omitempty"`
	Playwright       *PlaywrightToolConfig       `yaml:"playwright,omitempty"`
	Serena           *SerenaToolConfig           `yaml:"serena,omitempty"`
	AgenticWorkflows *AgenticWorkflowsToolConfig `yaml:"agentic-workflows,omitempty"`
	CacheMemory      *CacheMemoryToolConfig      `yaml:"cache-memory,omitempty"`
	RepoMemory       *RepoMemoryToolConfig       `yaml:"repo-memory,omitempty"`
	Timeout          *int                        `yaml:"timeout,omitempty"`
	StartupTimeout   *int                        `yaml:"startup-timeout,omitempty"`

	// Custom MCP tools (anything not in the above list)
	Custom map[string]MCPServerConfig `yaml:",inline"`
	// contains filtered or unexported fields
}

ToolsConfig represents the unified configuration for all tools in a workflow. This type provides a structured alternative to the pervasive map[string]any pattern. It includes strongly-typed fields for built-in tools and a flexible Custom map for MCP server configurations.

Migration Pattern

This unified type helps eliminate unnecessary type assertions and runtime validation by replacing map[string]any with strongly-typed configuration structs.

Usage Examples

Creating a ToolsConfig from a map[string]any:

toolsMap := map[string]any{
    "github": map[string]any{"allowed": []any{"issue_read"}},
    "bash":   []any{"echo", "ls"},
}
config, err := ParseToolsConfig(toolsMap)
if err != nil {
    // handle error
}

Converting back to map[string]any for legacy code:

toolsMap := config.ToMap()

Backward Compatibility

For functions that currently accept map[string]any, create wrapper functions that handle conversion:

// New signature using ToolsConfig
func processTools(config *ToolsConfig) error {
    if config.GitHub != nil {
        // Access strongly-typed GitHub config
    }
    return nil
}

// Backward compatibility wrapper
func processToolsFromMap(tools map[string]any) error {
    config, err := ParseToolsConfig(tools)
    if err != nil {
        return err
    }
    return processTools(config)
}

Design Notes

  • Built-in tool fields use pointers to distinguish between "not configured" (nil) and "configured with defaults" (non-nil but empty struct)
  • The Custom map stores MCP server configurations that aren't built-in tools
  • The raw map is preserved for perfect round-trip conversion when needed
  • Type alias Tools = ToolsConfig provides backward compatibility for existing code

func ParseToolsConfig

func ParseToolsConfig(toolsMap map[string]any) (*ToolsConfig, error)

ParseToolsConfig creates a ToolsConfig from a map[string]any. This function provides backward compatibility for code that uses map[string]any. It parses all known tool types into their strongly-typed equivalents and stores unknown tools in the Custom map.

func (*ToolsConfig) ToMap

func (t *ToolsConfig) ToMap() map[string]any

ToMap converts the ToolsConfig back to a map[string]any for backward compatibility. This is useful when interfacing with legacy code that expects map[string]any.

type TriggerIR

type TriggerIR struct {
	// Event is the main GitHub Actions event type (e.g., "push", "pull_request", "issues")
	Event string

	// Types contains the activity types for the event (e.g., ["opened", "edited"])
	Types []string

	// Filters contains additional event filters (branches, paths, tags, labels, etc.)
	Filters map[string]any

	// Conditions contains job-level conditions for complex filtering
	Conditions []string

	// AdditionalEvents contains other events to include (e.g., workflow_dispatch)
	AdditionalEvents map[string]any
}

TriggerIR represents the intermediate representation of a parsed trigger

func ParseTriggerShorthand

func ParseTriggerShorthand(input string) (*TriggerIR, error)

ParseTriggerShorthand parses a human-readable trigger shorthand string and returns a structured intermediate representation that can be converted to YAML. Returns nil if the input is not a recognized trigger shorthand.

func (*TriggerIR) ToYAMLMap

func (ir *TriggerIR) ToYAMLMap() map[string]any

ToYAMLMap converts a TriggerIR to a map structure suitable for YAML generation

type TypeValidationConfig

type TypeValidationConfig struct {
	DefaultMax       int                        `json:"defaultMax"`
	Fields           map[string]FieldValidation `json:"fields"`
	CustomValidation string                     `json:"customValidation,omitempty"`
}

TypeValidationConfig defines validation configuration for a safe output type

func GetValidationConfigForType

func GetValidationConfigForType(typeName string) (TypeValidationConfig, bool)

GetValidationConfigForType returns the validation config for a specific type

type UnassignFromUserConfig added in v0.43.9

type UnassignFromUserConfig struct {
	BaseSafeOutputConfig   `yaml:",inline"`
	SafeOutputTargetConfig `yaml:",inline"`
	Allowed                []string `yaml:"allowed,omitempty"` // Optional list of allowed usernames. If omitted, any users can be unassigned.
}

UnassignFromUserConfig holds configuration for removing assignees from issues

type UpdateDiscussionsConfig

type UpdateDiscussionsConfig struct {
	UpdateEntityConfig `yaml:",inline"`
	Title              *bool    `yaml:"title,omitempty"`          // Allow updating discussion title - presence indicates field can be updated
	Body               *bool    `yaml:"body,omitempty"`           // Allow updating discussion body - presence indicates field can be updated
	Labels             *bool    `yaml:"labels,omitempty"`         // Allow updating discussion labels - presence indicates field can be updated
	AllowedLabels      []string `yaml:"allowed-labels,omitempty"` // Optional list of allowed labels. If omitted, any labels are allowed (including creating new ones).
	Footer             *bool    `yaml:"footer,omitempty"`         // Controls whether AI-generated footer is added. When false, visible footer is omitted but XML markers are kept.
}

UpdateDiscussionsConfig holds configuration for updating GitHub discussions from agent output

type UpdateEntityConfig

type UpdateEntityConfig struct {
	BaseSafeOutputConfig   `yaml:",inline"`
	SafeOutputTargetConfig `yaml:",inline"`
}

UpdateEntityConfig holds the configuration for an update entity operation

type UpdateEntityFieldSpec

type UpdateEntityFieldSpec struct {
	Name string           // Field name in config (e.g., "title", "body", "status")
	Mode FieldParsingMode // Parsing mode for this field
	Dest **bool           // Pointer to the destination field in the config struct
}

UpdateEntityFieldSpec defines a boolean field to be parsed from config

type UpdateEntityJobBuilder

type UpdateEntityJobBuilder struct {
	EntityType          UpdateEntityType
	ConfigKey           string
	JobName             string
	StepName            string
	ScriptGetter        func() string
	PermissionsFunc     func() *Permissions
	BuildCustomEnvVars  func(*UpdateEntityConfig) []string
	BuildOutputs        func() map[string]string
	BuildEventCondition func(string) ConditionNode // Optional: builds event condition if target is empty
}

UpdateEntityJobBuilder encapsulates entity-specific configuration for building update jobs

type UpdateEntityJobParams

type UpdateEntityJobParams struct {
	EntityType      UpdateEntityType
	ConfigKey       string // e.g., "update-issue", "update-pull-request"
	JobName         string // e.g., "update_issue", "update_pull_request"
	StepName        string // e.g., "Update Issue", "Update Pull Request"
	ScriptGetter    func() string
	PermissionsFunc func() *Permissions
	CustomEnvVars   []string          // Type-specific environment variables
	Outputs         map[string]string // Type-specific outputs
	Condition       ConditionNode     // Job condition expression
}

UpdateEntityJobParams holds the parameters needed to build an update entity job

type UpdateEntityParseOptions

type UpdateEntityParseOptions struct {
	EntityType   UpdateEntityType        // Type of entity being parsed
	ConfigKey    string                  // Config key (e.g., "update-issue")
	Logger       *logger.Logger          // Logger for this entity type
	Fields       []UpdateEntityFieldSpec // Field specifications to parse
	CustomParser func(map[string]any)    // Optional custom field parser
}

UpdateEntityParseOptions holds options for parsing entity-specific configuration

type UpdateEntityType

type UpdateEntityType string

UpdateEntityType represents the type of entity being updated

const (
	UpdateEntityIssue       UpdateEntityType = "issue"
	UpdateEntityPullRequest UpdateEntityType = "pull_request"
	UpdateEntityDiscussion  UpdateEntityType = "discussion"
	UpdateEntityRelease     UpdateEntityType = "release"
)

type UpdateIssuesConfig

type UpdateIssuesConfig struct {
	UpdateEntityConfig `yaml:",inline"`
	Status             *bool `yaml:"status,omitempty"` // Allow updating issue status (open/closed) - presence indicates field can be updated
	Title              *bool `yaml:"title,omitempty"`  // Allow updating issue title - presence indicates field can be updated
	Body               *bool `yaml:"body,omitempty"`   // Allow updating issue body - boolean value controls permission (defaults to true)
	Footer             *bool `yaml:"footer,omitempty"` // Controls whether AI-generated footer is added. When false, visible footer is omitted but XML markers are kept.
}

UpdateIssuesConfig holds configuration for updating GitHub issues from agent output

type UpdateProjectConfig

type UpdateProjectConfig struct {
	BaseSafeOutputConfig `yaml:",inline"`
	GitHubToken          string                   `yaml:"github-token,omitempty"`
	Project              string                   `yaml:"project,omitempty"` // Default project URL for operations
	Views                []ProjectView            `yaml:"views,omitempty"`
	FieldDefinitions     []ProjectFieldDefinition `yaml:"field-definitions,omitempty" json:"field_definitions,omitempty"`
}

UpdateProjectConfig holds configuration for unified project board management

type UpdatePullRequestsConfig

type UpdatePullRequestsConfig struct {
	UpdateEntityConfig `yaml:",inline"`
	Title              *bool   `yaml:"title,omitempty"`     // Allow updating PR title - defaults to true, set to false to disable
	Body               *bool   `yaml:"body,omitempty"`      // Allow updating PR body - defaults to true, set to false to disable
	Operation          *string `yaml:"operation,omitempty"` // Default operation for body updates: "append", "prepend", or "replace" (defaults to "replace")
}

UpdatePullRequestsConfig holds configuration for updating GitHub pull requests from agent output

type UpdateReleaseConfig

type UpdateReleaseConfig struct {
	UpdateEntityConfig `yaml:",inline"`
	Footer             *bool `yaml:"footer,omitempty"` // Controls whether AI-generated footer is added. When false, visible footer is omitted but XML markers are kept.
}

UpdateReleaseConfig holds configuration for updating GitHub releases from agent output

type UploadAssetsConfig

type UploadAssetsConfig struct {
	BaseSafeOutputConfig `yaml:",inline"`
	BranchName           string   `yaml:"branch,omitempty"`       // Branch name (default: "assets/${{ github.workflow }}")
	MaxSizeKB            int      `yaml:"max-size,omitempty"`     // Maximum file size in KB (default: 10240 = 10MB)
	AllowedExts          []string `yaml:"allowed-exts,omitempty"` // Allowed file extensions (default: common non-executable types)
}

UploadAssetsConfig holds configuration for publishing assets to an orphaned git branch

type ValidatableTool

type ValidatableTool interface {
	// GetToolsets returns the comma-separated list of toolsets configured for this tool
	GetToolsets() string
	// IsReadOnly returns whether the tool is configured in read-only mode
	IsReadOnly() bool
}

ValidatableTool represents a tool configuration that can be validated for permissions This interface abstracts the tool configuration structure to enable type-safe permission validation

type WebFetchToolConfig

type WebFetchToolConfig struct {
}

WebFetchToolConfig represents the configuration for the web-fetch tool

type WebSearchToolConfig

type WebSearchToolConfig struct {
}

WebSearchToolConfig represents the configuration for the web-search tool

type WellKnownContainer

type WellKnownContainer struct {
	Image      string // Container image (e.g., "node:lts-alpine")
	Entrypoint string // Entrypoint command (e.g., "npx")
}

WellKnownContainer represents a container configuration for a well-known command

type WorkflowData

type WorkflowData struct {
	Name                  string
	WorkflowID            string         // workflow identifier derived from markdown filename (basename without extension)
	TrialMode             bool           // whether the workflow is running in trial mode
	TrialLogicalRepo      string         // target repository slug for trial mode (owner/repo)
	FrontmatterName       string         // name field from frontmatter (for code scanning alert driver default)
	FrontmatterYAML       string         // raw frontmatter YAML content (rendered as comment in lock file for reference)
	Description           string         // optional description rendered as comment in lock file
	Source                string         // optional source field (owner/repo@ref/path) rendered as comment in lock file
	TrackerID             string         // optional tracker identifier for created assets (min 8 chars, alphanumeric + hyphens/underscores)
	ImportedFiles         []string       // list of files imported via imports field (rendered as comment in lock file)
	ImportedMarkdown      string         // Only imports WITH inputs (for compile-time substitution)
	ImportPaths           []string       // Import file paths for runtime-import macro generation (imports without inputs)
	MainWorkflowMarkdown  string         // main workflow markdown without imports (for runtime-import)
	IncludedFiles         []string       // list of files included via @include directives (rendered as comment in lock file)
	ImportInputs          map[string]any // input values from imports with inputs (for github.aw.inputs.* substitution)
	On                    string
	Permissions           string
	Network               string // top-level network permissions configuration
	Concurrency           string // workflow-level concurrency configuration
	RunName               string
	Env                   string
	If                    string
	TimeoutMinutes        string
	CustomSteps           string
	PostSteps             string // steps to run after AI execution
	RunsOn                string
	Environment           string // environment setting for the main job
	Container             string // container setting for the main job
	Services              string // services setting for the main job
	Tools                 map[string]any
	ParsedTools           *Tools // Structured tools configuration (NEW: parsed from Tools map)
	MarkdownContent       string
	AI                    string        // "claude" or "codex" (for backwards compatibility)
	EngineConfig          *EngineConfig // Extended engine configuration
	AgentFile             string        // Path to custom agent file (from imports)
	AgentImportSpec       string        // Original import specification for agent file (e.g., "owner/repo/path@ref")
	RepositoryImports     []string      // Repository-only imports (format: "owner/repo@ref") for .github folder merging
	StopTime              string
	SkipIfMatch           *SkipIfMatchConfig   // skip-if-match configuration with query and max threshold
	SkipIfNoMatch         *SkipIfNoMatchConfig // skip-if-no-match configuration with query and min threshold
	ManualApproval        string               // environment name for manual approval from on: section
	Command               []string             // for /command trigger support - multiple command names
	CommandEvents         []string             // events where command should be active (nil = all events)
	CommandOtherEvents    map[string]any       // for merging command with other events
	AIReaction            string               // AI reaction type like "eyes", "heart", etc.
	LockForAgent          bool                 // whether to lock the issue during agent workflow execution
	Jobs                  map[string]any       // custom job configurations with dependencies
	Cache                 string               // cache configuration
	NeedsTextOutput       bool                 // whether the workflow uses ${{ needs.task.outputs.text }}
	NetworkPermissions    *NetworkPermissions  // parsed network permissions
	SandboxConfig         *SandboxConfig       // parsed sandbox configuration (AWF or SRT)
	SafeOutputs           *SafeOutputsConfig   // output configuration for automatic output routes
	SafeInputs            *SafeInputsConfig    // safe-inputs configuration for custom MCP tools
	Roles                 []string             // permission levels required to trigger workflow
	Bots                  []string             // allow list of bot identifiers that can trigger workflow
	RateLimit             *RateLimitConfig     // rate limiting configuration for workflow triggers
	CacheMemoryConfig     *CacheMemoryConfig   // parsed cache-memory configuration
	RepoMemoryConfig      *RepoMemoryConfig    // parsed repo-memory configuration
	Runtimes              map[string]any       // runtime version overrides from frontmatter
	PluginInfo            *PluginInfo          // Consolidated plugin information (plugins, custom token, MCP configs)
	ToolsTimeout          int                  // timeout in seconds for tool/MCP operations (0 = use engine default)
	GitHubToken           string               // top-level github-token expression from frontmatter
	ToolsStartupTimeout   int                  // timeout in seconds for MCP server startup (0 = use engine default)
	Features              map[string]any       // feature flags and configuration options from frontmatter (supports bool and string values)
	ActionCache           *ActionCache         // cache for action pin resolutions
	ActionResolver        *ActionResolver      // resolver for action pins
	StrictMode            bool                 // strict mode for action pinning
	SecretMasking         *SecretMaskingConfig // secret masking configuration
	ParsedFrontmatter     *FrontmatterConfig   // cached parsed frontmatter configuration (for performance optimization)
	ActionPinWarnings     map[string]bool      // cache of already-warned action pin failures (key: "repo@version")
	ActionMode            ActionMode           // action mode for workflow compilation (dev, release, script)
	HasExplicitGitHubTool bool                 // true if tools.github was explicitly configured in frontmatter
}

WorkflowData holds all the data needed to generate a GitHub Actions workflow

type WorkflowExecutor

type WorkflowExecutor interface {
	// GetDeclaredOutputFiles returns a list of output files that this engine may produce
	// These files will be automatically uploaded as artifacts if they exist
	GetDeclaredOutputFiles() []string

	// GetInstallationSteps returns the GitHub Actions steps needed to install this engine
	GetInstallationSteps(workflowData *WorkflowData) []GitHubActionStep

	// GetExecutionSteps returns the GitHub Actions steps for executing this engine
	GetExecutionSteps(workflowData *WorkflowData, logFile string) []GitHubActionStep
}

WorkflowExecutor handles workflow compilation and execution All engines must implement this to generate GitHub Actions steps

type WorkflowStep

type WorkflowStep struct {
	Name             string            `yaml:"name,omitempty"`
	ID               string            `yaml:"id,omitempty"`
	If               string            `yaml:"if,omitempty"`
	Uses             string            `yaml:"uses,omitempty"`
	Run              string            `yaml:"run,omitempty"`
	WorkingDirectory string            `yaml:"working-directory,omitempty"`
	Shell            string            `yaml:"shell,omitempty"`
	With             map[string]any    `yaml:"with,omitempty"`
	Env              map[string]string `yaml:"env,omitempty"`
	ContinueOnError  any               `yaml:"continue-on-error,omitempty"` // Can be bool or string expression
	TimeoutMinutes   int               `yaml:"timeout-minutes,omitempty"`
}

WorkflowStep represents a single step in a GitHub Actions workflow job This struct provides type safety and compile-time validation for step configurations

func ApplyActionPinToTypedStep

func ApplyActionPinToTypedStep(step *WorkflowStep, data *WorkflowData) *WorkflowStep

ApplyActionPinToTypedStep applies SHA pinning to a WorkflowStep if it uses an action. Returns a modified copy of the step with pinned references. If the step doesn't use an action or the action is not pinned, returns the original step.

func ApplyActionPinsToTypedSteps

func ApplyActionPinsToTypedSteps(steps []*WorkflowStep, data *WorkflowData) []*WorkflowStep

ApplyActionPinsToTypedSteps applies SHA pinning to a slice of typed WorkflowStep pointers Returns a new slice with pinned references - this is the type-safe version

func MapToStep

func MapToStep(stepMap map[string]any) (*WorkflowStep, error)

MapToStep converts a map[string]any to a WorkflowStep This is the inverse of ToMap and is used when parsing step configurations

func SliceToSteps

func SliceToSteps(steps []any) ([]*WorkflowStep, error)

SliceToSteps converts a slice of any (typically []map[string]any from YAML parsing) to a typed slice of WorkflowStep pointers for type-safe manipulation

func (*WorkflowStep) Clone

func (s *WorkflowStep) Clone() *WorkflowStep

Clone creates a deep copy of the WorkflowStep

func (*WorkflowStep) IsRunStep

func (s *WorkflowStep) IsRunStep() bool

IsRunStep returns true if this step runs a command (has a "run" field)

func (*WorkflowStep) IsUsesStep

func (s *WorkflowStep) IsUsesStep() bool

IsUsesStep returns true if this step uses an action (has a "uses" field)

func (*WorkflowStep) ToMap

func (s *WorkflowStep) ToMap() map[string]any

ToMap converts a WorkflowStep to a map[string]any for YAML generation This is used when generating the final workflow YAML output

func (*WorkflowStep) ToYAML

func (s *WorkflowStep) ToYAML() (string, error)

ToYAML converts the WorkflowStep to YAML string

type WorkflowValidationError

type WorkflowValidationError struct {
	Field      string
	Value      string
	Reason     string
	Suggestion string
	Timestamp  time.Time
}

WorkflowValidationError represents an error that occurred during input validation

func NewValidationError

func NewValidationError(field, value, reason, suggestion string) *WorkflowValidationError

NewValidationError creates a new validation error with context

func (*WorkflowValidationError) Error

func (e *WorkflowValidationError) Error() string

Error implements the error interface

Source Files

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL