From 6547e97bd4fd5619ae4c4b1aaca763ecaca999a8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Oct 2025 22:34:33 +0000 Subject: [PATCH 1/4] Initial plan From 734261d2c4f6ad581a5cc33307fd32a626874e25 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Oct 2025 22:47:09 +0000 Subject: [PATCH 2/4] Separate GitHub tools lists for local and remote modes - Created DefaultGitHubToolsLocal constant for Docker-based servers - Created DefaultGitHubToolsRemote constant for hosted servers - Kept DefaultGitHubTools for backward compatibility (points to local) - Updated compiler.go to use mode-specific constants - Updated claude_engine.go to use mode-specific constants - All tests passing Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/constants/constants.go | 80 ++++++++++++++++++++++++++++++++++- pkg/workflow/claude_engine.go | 11 ++++- pkg/workflow/compiler.go | 11 ++++- 3 files changed, 97 insertions(+), 5 deletions(-) diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index e07c47db0f3..a4690c71733 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -145,8 +145,8 @@ const ActivatedOutput = "activated" var AgenticEngines = []string{"claude", "codex", "copilot"} -// DefaultGitHubTools defines the default read-only GitHub MCP tools -var DefaultGitHubTools = []string{ +// DefaultGitHubToolsLocal defines the default read-only GitHub MCP tools for local (Docker) mode +var DefaultGitHubToolsLocal = []string{ // actions "download_workflow_run_artifact", "get_job_logs", @@ -217,6 +217,82 @@ var DefaultGitHubTools = []string{ "list_sub_issues", } +// DefaultGitHubToolsRemote defines the default read-only GitHub MCP tools for remote (hosted) mode +var DefaultGitHubToolsRemote = []string{ + // actions + "download_workflow_run_artifact", + "get_job_logs", + "get_workflow_run", + "get_workflow_run_logs", + "get_workflow_run_usage", + "list_workflow_jobs", + "list_workflow_run_artifacts", + "list_workflow_runs", + "list_workflows", + // code security + "get_code_scanning_alert", + "list_code_scanning_alerts", + // context + "get_me", + // dependabot + "get_dependabot_alert", + "list_dependabot_alerts", + // discussions + "get_discussion", + "get_discussion_comments", + "list_discussion_categories", + "list_discussions", + // issues + "get_issue", + "get_issue_comments", + "list_issues", + "search_issues", + // notifications + "get_notification_details", + "list_notifications", + // organizations + "search_orgs", + // labels + "get_label", + "list_label", + // prs + "get_pull_request", + "get_pull_request_comments", + "get_pull_request_diff", + "get_pull_request_files", + "get_pull_request_reviews", + "get_pull_request_status", + "list_pull_requests", + "pull_request_read", + "search_pull_requests", + // repos + "get_commit", + "get_file_contents", + "get_tag", + "list_branches", + "list_commits", + "list_tags", + "search_code", + "search_repositories", + // secret protection + "get_secret_scanning_alert", + "list_secret_scanning_alerts", + // users + "search_users", + // additional unique tools (previously duplicated block extras) + "get_latest_release", + "get_pull_request_review_comments", + "get_release_by_tag", + "list_issue_types", + "list_releases", + "list_starred_repositories", + "list_sub_issues", +} + +// DefaultGitHubTools is deprecated. Use DefaultGitHubToolsLocal or DefaultGitHubToolsRemote instead. +// Kept for backward compatibility and defaults to local mode tools. +var DefaultGitHubTools = DefaultGitHubToolsLocal + // DefaultBashTools defines basic bash commands that should be available by default when bash is enabled var DefaultBashTools = []string{ "echo", diff --git a/pkg/workflow/claude_engine.go b/pkg/workflow/claude_engine.go index 7ed9af53baa..a227433772c 100644 --- a/pkg/workflow/claude_engine.go +++ b/pkg/workflow/claude_engine.go @@ -556,8 +556,15 @@ func (e *ClaudeEngine) computeAllowedClaudeToolsString(tools map[string]any, saf } } } else if toolName == "github" { - // For GitHub tools without explicit allowed list, use default GitHub tools - for _, defaultTool := range constants.DefaultGitHubTools { + // For GitHub tools without explicit allowed list, use appropriate default GitHub tools based on mode + githubMode := getGitHubType(mcpConfig) + var defaultTools []string + if githubMode == "remote" { + defaultTools = constants.DefaultGitHubToolsRemote + } else { + defaultTools = constants.DefaultGitHubToolsLocal + } + for _, defaultTool := range defaultTools { allowedTools = append(allowedTools, fmt.Sprintf("mcp__github__%s", defaultTool)) } } diff --git a/pkg/workflow/compiler.go b/pkg/workflow/compiler.go index 919b4caec54..12fc3b695f1 100644 --- a/pkg/workflow/compiler.go +++ b/pkg/workflow/compiler.go @@ -1544,11 +1544,20 @@ func (c *Compiler) applyDefaultTools(tools map[string]any, safeOutputs *SafeOutp } } + // Determine which default tools list to use based on mode + githubMode := getGitHubType(githubTool) + var defaultTools []string + if githubMode == "remote" { + defaultTools = constants.DefaultGitHubToolsRemote + } else { + defaultTools = constants.DefaultGitHubToolsLocal + } + // Add default GitHub tools that aren't already present newAllowed := make([]any, len(existingAllowed)) copy(newAllowed, existingAllowed) - for _, defaultTool := range constants.DefaultGitHubTools { + for _, defaultTool := range defaultTools { if !existingToolsSet[defaultTool] { newAllowed = append(newAllowed, defaultTool) } From eef92841100484c8f06f3406420037ee7d5c0748 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Oct 2025 22:50:33 +0000 Subject: [PATCH 3/4] Add tests for GitHub tools mode separation - Added TestGitHubToolsModeSeparation to verify constants exist - Added TestApplyDefaultToolsUsesCorrectMode to verify mode-based selection - All unit tests passing - Build successful - Workflows recompiled successfully Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/workflow/github_tools_mode_test.go | 128 +++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 pkg/workflow/github_tools_mode_test.go diff --git a/pkg/workflow/github_tools_mode_test.go b/pkg/workflow/github_tools_mode_test.go new file mode 100644 index 00000000000..95b32c67331 --- /dev/null +++ b/pkg/workflow/github_tools_mode_test.go @@ -0,0 +1,128 @@ +package workflow + +import ( + "testing" + + "github.com/githubnext/gh-aw/pkg/constants" +) + +// TestGitHubToolsModeSeparation verifies that local and remote GitHub tools lists are properly separated +func TestGitHubToolsModeSeparation(t *testing.T) { + // Verify both lists exist and are not empty + if len(constants.DefaultGitHubToolsLocal) == 0 { + t.Error("DefaultGitHubToolsLocal should not be empty") + } + + if len(constants.DefaultGitHubToolsRemote) == 0 { + t.Error("DefaultGitHubToolsRemote should not be empty") + } + + // Verify backward compatibility - DefaultGitHubTools should point to local + if len(constants.DefaultGitHubTools) == 0 { + t.Error("DefaultGitHubTools should not be empty (backward compatibility)") + } + + // Verify DefaultGitHubTools points to the same data as DefaultGitHubToolsLocal + if len(constants.DefaultGitHubTools) != len(constants.DefaultGitHubToolsLocal) { + t.Errorf("DefaultGitHubTools should have same length as DefaultGitHubToolsLocal for backward compatibility") + } + + // Verify they contain expected core tools + expectedCoreTools := []string{ + "get_issue", + "list_issues", + "get_commit", + "get_file_contents", + "search_repositories", + } + + // Check local tools + localToolsMap := make(map[string]bool) + for _, tool := range constants.DefaultGitHubToolsLocal { + localToolsMap[tool] = true + } + + for _, expectedTool := range expectedCoreTools { + if !localToolsMap[expectedTool] { + t.Errorf("Expected core tool '%s' not found in DefaultGitHubToolsLocal", expectedTool) + } + } + + // Check remote tools + remoteToolsMap := make(map[string]bool) + for _, tool := range constants.DefaultGitHubToolsRemote { + remoteToolsMap[tool] = true + } + + for _, expectedTool := range expectedCoreTools { + if !remoteToolsMap[expectedTool] { + t.Errorf("Expected core tool '%s' not found in DefaultGitHubToolsRemote", expectedTool) + } + } +} + +// TestApplyDefaultToolsUsesCorrectMode verifies that applyDefaultTools uses the correct tool list based on mode +func TestApplyDefaultToolsUsesCorrectMode(t *testing.T) { + compiler := NewCompiler(false, "", "test") + + tests := []struct { + name string + tools map[string]any + expectedList string // "local" or "remote" + }{ + { + name: "Local mode (default)", + tools: map[string]any{ + "github": map[string]any{}, + }, + expectedList: "local", + }, + { + name: "Explicit local mode", + tools: map[string]any{ + "github": map[string]any{ + "mode": "local", + }, + }, + expectedList: "local", + }, + { + name: "Remote mode", + tools: map[string]any{ + "github": map[string]any{ + "mode": "remote", + }, + }, + expectedList: "remote", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := compiler.applyDefaultTools(tt.tools, nil) + + // Get the allowed tools from the github configuration + githubConfig, ok := result["github"].(map[string]any) + if !ok { + t.Fatal("Expected github configuration to be a map") + } + + allowed, ok := githubConfig["allowed"].([]any) + if !ok { + t.Fatal("Expected allowed to be a slice") + } + + // Verify that the number of tools matches the expected list + var expectedCount int + if tt.expectedList == "local" { + expectedCount = len(constants.DefaultGitHubToolsLocal) + } else { + expectedCount = len(constants.DefaultGitHubToolsRemote) + } + + if len(allowed) != expectedCount { + t.Errorf("Expected %d tools for %s mode, got %d", expectedCount, tt.expectedList, len(allowed)) + } + }) + } +} From 0612108caf104b22221d3ecc4cc6f4325f81c406 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 16 Oct 2025 22:52:35 +0000 Subject: [PATCH 4/4] Add changeset for GitHub tools separation --- .changeset/patch-separate-github-tools-lists.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/patch-separate-github-tools-lists.md diff --git a/.changeset/patch-separate-github-tools-lists.md b/.changeset/patch-separate-github-tools-lists.md new file mode 100644 index 00000000000..cbd4385a62c --- /dev/null +++ b/.changeset/patch-separate-github-tools-lists.md @@ -0,0 +1,5 @@ +--- +"gh-aw": patch +--- + +Separate default list of GitHub tools for local and remote servers