Resolve returns the agent Provider using priority: flagAgent > CHIEF_AGENT env > config > "claude". flagPath overrides the CLI path when non-empty (flag > CHIEF_AGENT_PATH > config agent.cliPath). Returns an error if the resolved provider name is not recognised.
(flagAgent, flagPath string, cfg *config.Config)
| 14 | // flagPath overrides the CLI path when non-empty (flag > CHIEF_AGENT_PATH > config agent.cliPath). |
| 15 | // Returns an error if the resolved provider name is not recognised. |
| 16 | func Resolve(flagAgent, flagPath string, cfg *config.Config) (loop.Provider, error) { |
| 17 | providerName := "claude" |
| 18 | if flagAgent != "" { |
| 19 | providerName = strings.ToLower(strings.TrimSpace(flagAgent)) |
| 20 | } else if v := os.Getenv("CHIEF_AGENT"); v != "" { |
| 21 | providerName = strings.ToLower(strings.TrimSpace(v)) |
| 22 | } else if cfg != nil && cfg.Agent.Provider != "" { |
| 23 | providerName = strings.ToLower(strings.TrimSpace(cfg.Agent.Provider)) |
| 24 | } |
| 25 | |
| 26 | cliPath := "" |
| 27 | if flagPath != "" { |
| 28 | cliPath = flagPath |
| 29 | } else if v := os.Getenv("CHIEF_AGENT_PATH"); v != "" { |
| 30 | cliPath = strings.TrimSpace(v) |
| 31 | } else if cfg != nil && cfg.Agent.CLIPath != "" { |
| 32 | cliPath = strings.TrimSpace(cfg.Agent.CLIPath) |
| 33 | } |
| 34 | |
| 35 | switch providerName { |
| 36 | case "claude": |
| 37 | return NewClaudeProvider(cliPath), nil |
| 38 | case "codex": |
| 39 | return NewCodexProvider(cliPath), nil |
| 40 | case "opencode": |
| 41 | return NewOpenCodeProvider(cliPath), nil |
| 42 | case "cursor": |
| 43 | return NewCursorProvider(cliPath), nil |
| 44 | default: |
| 45 | return nil, fmt.Errorf("unknown agent provider %q: expected \"claude\", \"codex\", \"opencode\", or \"cursor\"", providerName) |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | // CheckInstalled verifies that the provider's CLI binary is found in PATH (or at cliPath). |
| 50 | func CheckInstalled(p loop.Provider) error { |