-
Notifications
You must be signed in to change notification settings - Fork 122
Add fuzzy matching "did you mean" suggestions for engine and tool validation #14260
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b2edd37
2e8848a
80e9ca4
e2d9cb2
7fb0fde
0a1b81e
df362cf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -3,8 +3,11 @@ package workflow | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _ "embed" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "encoding/json" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "fmt" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "sort" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/github/gh-aw/pkg/logger" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/github/gh-aw/pkg/parser" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var githubToolToToolsetLog = logger.New("workflow:github_tool_to_toolset") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -45,10 +48,37 @@ func ValidateGitHubToolsAgainstToolsets(allowedTools []string, enabledToolsets [ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Track missing toolsets and which tools need them | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| missingToolsets := make(map[string][]string) // toolset -> list of tools that need it | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Track unknown tools for suggestions | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var unknownTools []string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var suggestions []string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for _, tool := range allowedTools { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Skip wildcard - it means "allow all tools" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if tool == "*" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| requiredToolset, exists := GitHubToolToToolsetMap[tool] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !exists { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| githubToolToToolsetLog.Printf("Tool %s not found in mapping, skipping validation", tool) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| githubToolToToolsetLog.Printf("Tool %s not found in mapping, checking for typo", tool) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Get all valid tool names for suggestion | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| validTools := make([]string, 0, len(GitHubToolToToolsetMap)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for validTool := range GitHubToolToToolsetMap { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| validTools = append(validTools, validTool) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sort.Strings(validTools) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+65
to
+70
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Try to find close matches | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| matches := parser.FindClosestMatches(tool, validTools, 1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if len(matches) > 0 { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| githubToolToToolsetLog.Printf("Found suggestion for unknown tool %s: %s", tool, matches[0]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| unknownTools = append(unknownTools, tool) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| suggestions = append(suggestions, fmt.Sprintf("%s → %s", tool, matches[0])) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| githubToolToToolsetLog.Printf("No suggestion found for unknown tool: %s", tool) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| unknownTools = append(unknownTools, tool) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Tool not in our mapping - this could be a new tool or a typo | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // We'll skip validation for unknown tools to avoid false positives | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // We'll skip validation for unknown tools to avoid false positives | |
| // Record the unknown tool and skip further checks for this entry; unknown tools will cause validation to fail later. |
Copilot
AI
Feb 7, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
formatList produces awkward/incorrect grammar for 3+ items (e.g., "a and b, and c" instead of "a, b, and c") due to the recursive construction. This will make the new error messages harder to read when listing multiple tools. Consider implementing proper comma-separated formatting (e.g., join all but last with ", ", then add ", and ").
| if len(items) == 0 { | |
| return "" | |
| } | |
| if len(items) == 1 { | |
| return items[0] | |
| } | |
| if len(items) == 2 { | |
| return items[0] + " and " + items[1] | |
| } | |
| return fmt.Sprintf("%s, and %s", formatList(items[:len(items)-1]), items[len(items)-1]) | |
| switch len(items) { | |
| case 0: | |
| return "" | |
| case 1: | |
| return items[0] | |
| case 2: | |
| return items[0] + " and " + items[1] | |
| default: | |
| result := items[0] | |
| for i := 1; i < len(items); i++ { | |
| if i == len(items)-1 { | |
| result += ", and " + items[i] | |
| } else { | |
| result += ", " + items[i] | |
| } | |
| } | |
| return result | |
| } |
Uh oh!
There was an error while loading. Please reload this page.