Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions pkg/stringutil/ansi.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ package stringutil

import (
"strings"

"github.com/github/gh-aw/pkg/logger"
)

var ansiLog = logger.New("stringutil:ansi")

// StripANSI removes ANSI escape codes from a string using a comprehensive byte scanner.
// It handles CSI sequences (\x1b[), OSC sequences (\x1b]), G0/G1 character set selections,
// keypad mode sequences, reset sequences, and other common 2-character escape sequences.
Expand All @@ -16,6 +20,8 @@ func StripANSI(s string) string {
return s
}

ansiLog.Printf("StripANSI: input length=%d", len(s))

var result strings.Builder
result.Grow(len(s)) // Pre-allocate capacity for efficiency

Expand Down
10 changes: 10 additions & 0 deletions pkg/workflow/compiler_safe_outputs_builder.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package workflow

import "github.com/github/gh-aw/pkg/logger"

var safeOutputsBuilderLog = logger.New("workflow:safe_outputs_builder")

// handlerConfigBuilder provides a fluent API for building handler configurations
type handlerConfigBuilder struct {
config map[string]any
Expand Down Expand Up @@ -89,6 +93,7 @@ type handlerBuilder func(*SafeOutputsConfig) map[string]any
// Returns nil if neither is set (default to true in JavaScript).
func getEffectiveFooterForTemplatable(localFooter *string, globalFooter *bool) *string {
if localFooter != nil {
safeOutputsBuilderLog.Printf("Footer: using local override %q", *localFooter)
return localFooter
}
if globalFooter != nil {
Expand All @@ -98,8 +103,10 @@ func getEffectiveFooterForTemplatable(localFooter *string, globalFooter *bool) *
} else {
s = "false"
}
safeOutputsBuilderLog.Printf("Footer: derived %q from global bool", s)
return &s
}
safeOutputsBuilderLog.Print("Footer: not configured, deferring to JS default")
return nil
}

Expand All @@ -108,6 +115,7 @@ func getEffectiveFooterForTemplatable(localFooter *string, globalFooter *bool) *
// Returns nil if neither is set (default to "always" in JavaScript).
func getEffectiveFooterString(localFooter *string, globalFooter *bool) *string {
if localFooter != nil {
safeOutputsBuilderLog.Printf("FooterString: using local override %q", *localFooter)
return localFooter
}
if globalFooter != nil {
Expand All @@ -117,7 +125,9 @@ func getEffectiveFooterString(localFooter *string, globalFooter *bool) *string {
} else {
s = "none"
}
safeOutputsBuilderLog.Printf("FooterString: derived %q from global bool", s)
return &s
}
safeOutputsBuilderLog.Print("FooterString: not configured, deferring to JS default")
return nil
}
10 changes: 7 additions & 3 deletions pkg/workflow/mcp_playwright_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ package workflow

import (
"strings"

"github.com/github/gh-aw/pkg/logger"
)

var playwrightConfigLog = logger.New("workflow:mcp_playwright")

// PlaywrightDockerArgs represents the common Docker arguments for Playwright container
type PlaywrightDockerArgs struct {
ImageVersion string // Version for Docker image (mcr.microsoft.com/playwright:version)
Expand All @@ -14,7 +18,7 @@ type PlaywrightDockerArgs struct {
// Returns a map of environment variable names to their original expressions
// Uses the same ExpressionExtractor as used for shell script security
func extractExpressionsFromPlaywrightArgs(customArgs []string) map[string]string {
log.Printf("Extracting expressions from %d Playwright args", len(customArgs))
playwrightConfigLog.Printf("Extracting expressions from %d Playwright args", len(customArgs))
if len(customArgs) == 0 {
return make(map[string]string)
}
Expand All @@ -26,7 +30,7 @@ func extractExpressionsFromPlaywrightArgs(customArgs []string) map[string]string
extractor := NewExpressionExtractor()
mappings, err := extractor.ExtractExpressions(combined)
if err != nil {
log.Printf("Failed to extract expressions from Playwright args: %s", err)
playwrightConfigLog.Printf("Failed to extract expressions from Playwright args: %s", err)
return make(map[string]string)
}

Expand All @@ -36,7 +40,7 @@ func extractExpressionsFromPlaywrightArgs(customArgs []string) map[string]string
result[mapping.EnvVar] = mapping.Original
}

log.Printf("Extracted %d unique expressions from Playwright args", len(result))
playwrightConfigLog.Printf("Extracted %d unique expressions from Playwright args", len(result))
return result
}

Expand Down
22 changes: 13 additions & 9 deletions pkg/workflow/prompts.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ package workflow

import (
"strings"

"github.com/github/gh-aw/pkg/logger"
)

var promptsLog = logger.New("workflow:prompts")

// prompts.go consolidates all prompt-related functions for agentic workflows.
// This file contains functions that generate workflow steps to append various
// contextual instructions to the agent's prompt file during execution.
Expand All @@ -21,11 +25,11 @@ import (
// hasPlaywrightTool checks if the playwright tool is enabled in the tools configuration
func hasPlaywrightTool(parsedTools *Tools) bool {
if parsedTools == nil {
log.Print("Checking for Playwright tool: no parsed tools provided")
promptsLog.Print("Checking for Playwright tool: no parsed tools provided")
return false
}
hasPlaywright := parsedTools.Playwright != nil
log.Printf("Playwright tool enabled: %v", hasPlaywright)
promptsLog.Printf("Playwright tool enabled: %v", hasPlaywright)
return hasPlaywright
}

Expand All @@ -36,11 +40,11 @@ func hasPlaywrightTool(parsedTools *Tools) bool {
// hasAgenticWorkflowsTool checks if the agentic workflows tool is enabled in the tools configuration
func hasAgenticWorkflowsTool(parsedTools *Tools) bool {
if parsedTools == nil {
log.Print("Checking for agentic-workflows tool: no parsed tools provided")
promptsLog.Print("Checking for agentic-workflows tool: no parsed tools provided")
return false
}
hasAgenticWorkflows := parsedTools.AgenticWorkflows != nil
log.Printf("Agentic-workflows tool enabled: %v", hasAgenticWorkflows)
promptsLog.Printf("Agentic-workflows tool enabled: %v", hasAgenticWorkflows)
return hasAgenticWorkflows
}

Expand All @@ -50,28 +54,28 @@ func hasAgenticWorkflowsTool(parsedTools *Tools) bool {

// hasCommentRelatedTriggers checks if the workflow has any comment-related event triggers
func (c *Compiler) hasCommentRelatedTriggers(data *WorkflowData) bool {
log.Printf("Checking for comment-related triggers: command_count=%d, on=%s", len(data.Command), data.On)
promptsLog.Printf("Checking for comment-related triggers: command_count=%d, on=%s", len(data.Command), data.On)

// Check for command trigger (which expands to comment events)
if len(data.Command) > 0 {
log.Print("Found command trigger, enabling comment-related features")
promptsLog.Print("Found command trigger, enabling comment-related features")
return true
}

if data.On == "" {
log.Print("No 'on' trigger defined")
promptsLog.Print("No 'on' trigger defined")
return false
}

// Check for comment-related event types in the "on" configuration
commentEvents := []string{"issue_comment", "pull_request_review_comment", "pull_request_review"}
for _, event := range commentEvents {
if strings.Contains(data.On, event) {
log.Printf("Found comment-related event trigger: %s", event)
promptsLog.Printf("Found comment-related event trigger: %s", event)
return true
}
}

log.Print("No comment-related triggers found")
promptsLog.Print("No comment-related triggers found")
return false
}
19 changes: 11 additions & 8 deletions pkg/workflow/runtime_deduplication.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import (
"fmt"
"strings"

"github.com/github/gh-aw/pkg/logger"
"github.com/goccy/go-yaml"
)

var runtimeDeduplicationLog = logger.New("workflow:runtime_deduplication")

// 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,
Expand All @@ -19,7 +22,7 @@ func DeduplicateRuntimeSetupStepsFromCustomSteps(customSteps string, runtimeRequ
return customSteps, runtimeRequirements, nil
}

log.Printf("Deduplicating runtime setup steps from custom steps (%d runtimes)", len(runtimeRequirements))
runtimeDeduplicationLog.Printf("Deduplicating runtime setup steps from custom steps (%d runtimes)", len(runtimeRequirements))

// Extract version comments from uses lines before unmarshaling
// This is necessary because YAML treats "# comment" as a comment, not part of the value
Expand Down Expand Up @@ -60,7 +63,7 @@ func DeduplicateRuntimeSetupStepsFromCustomSteps(customSteps string, runtimeRequ
for i := range runtimeRequirements {
if runtimeRequirements[i].Runtime.ActionRepo != "" {
actionRepoToReq[runtimeRequirements[i].Runtime.ActionRepo] = &runtimeRequirements[i]
log.Printf(" Will check steps using action: %s", runtimeRequirements[i].Runtime.ActionRepo)
runtimeDeduplicationLog.Printf(" Will check steps using action: %s", runtimeRequirements[i].Runtime.ActionRepo)
}
}

Expand Down Expand Up @@ -145,7 +148,7 @@ func DeduplicateRuntimeSetupStepsFromCustomSteps(customSteps string, runtimeRequ
// User has truly customized the setup action - preserve it
shouldPreserve = true
filteredRuntimeIDs[req.Runtime.ID] = true
log.Printf(" Preserving user-customized runtime setup step: %s", usesStr)
runtimeDeduplicationLog.Printf(" Preserving user-customized runtime setup step: %s", usesStr)
preservedCount++
break
}
Expand All @@ -166,14 +169,14 @@ func DeduplicateRuntimeSetupStepsFromCustomSteps(customSteps string, runtimeRequ
}
// Carry over any other fields
req.ExtraFields[key] = value
log.Printf(" Capturing extra field from setup step: %s = %v", key, value)
runtimeDeduplicationLog.Printf(" Capturing extra field from setup step: %s = %v", key, value)
}
}
}

// No real customization - remove this duplicate but keep extra fields
shouldRemove = true
log.Printf(" Removing duplicate runtime setup step: %s", usesStr)
runtimeDeduplicationLog.Printf(" Removing duplicate runtime setup step: %s", usesStr)
removedCount++
break
}
Expand All @@ -185,19 +188,19 @@ func DeduplicateRuntimeSetupStepsFromCustomSteps(customSteps string, runtimeRequ
}

if removedCount == 0 && preservedCount == 0 {
log.Print(" No duplicate runtime setup steps found")
runtimeDeduplicationLog.Print(" No duplicate runtime setup steps found")
return customSteps, runtimeRequirements, nil
}

log.Printf(" Removed %d duplicate runtime setup steps, preserved %d user-customized steps", removedCount, preservedCount)
runtimeDeduplicationLog.Printf(" Removed %d duplicate runtime setup steps, preserved %d user-customized steps", removedCount, preservedCount)

// Filter runtime requirements to exclude those with user-customized setup actions
var filteredRequirements []RuntimeRequirement
for _, req := range runtimeRequirements {
if !filteredRuntimeIDs[req.Runtime.ID] {
filteredRequirements = append(filteredRequirements, req)
} else {
log.Printf(" Excluding runtime %s from generated setup steps (user has custom setup)", req.Runtime.ID)
runtimeDeduplicationLog.Printf(" Excluding runtime %s from generated setup steps (user has custom setup)", req.Runtime.ID)
}
}

Expand Down