diff options
Diffstat (limited to 'internal/aitool/dispatch.go')
| -rw-r--r-- | internal/aitool/dispatch.go | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/internal/aitool/dispatch.go b/internal/aitool/dispatch.go new file mode 100644 index 0000000..0924c8b --- /dev/null +++ b/internal/aitool/dispatch.go @@ -0,0 +1,76 @@ +package aitool + +import "os/exec" + +type Tool string + +const ( + ToolOpencode Tool = "opencode" + ToolHexAI Tool = "hexai" + ToolClaude Tool = "claude" + ToolAmp Tool = "amp" +) + +type LookPathFunc func(file string) (string, error) + +func Chain(preferred string) []Tool { + switch preferred { + case "", string(ToolOpencode): + return []Tool{ToolOpencode, ToolHexAI, ToolClaude, ToolAmp} + case string(ToolHexAI): + return []Tool{ToolHexAI, ToolClaude, ToolAmp} + case string(ToolClaude), "claude-code": + return []Tool{ToolClaude, ToolAmp} + case string(ToolAmp): + return []Tool{ToolAmp} + default: + return nil + } +} + +func FirstAvailable(preferred string, lookPath LookPathFunc) Tool { + for _, tool := range Chain(preferred) { + if IsAvailable(tool, lookPath) { + return tool + } + } + + return "" +} + +func AvailableChain(preferred string, lookPath LookPathFunc) []Tool { + chain := Chain(preferred) + available := make([]Tool, 0, len(chain)) + for _, tool := range chain { + if IsAvailable(tool, lookPath) { + available = append(available, tool) + } + } + + return available +} + +func IsAvailable(tool Tool, lookPath LookPathFunc) bool { + if lookPath == nil { + lookPath = exec.LookPath + } + + binary, ok := availabilityBinary(tool) + if !ok { + return false + } + + _, err := lookPath(binary) + return err == nil +} + +func availabilityBinary(tool Tool) (string, bool) { + switch tool { + case ToolOpencode: + return "ollama", true + case ToolHexAI, ToolClaude, ToolAmp: + return string(tool), true + default: + return "", false + } +} |
