diff options
Diffstat (limited to 'internal/cli')
| -rw-r--r-- | internal/cli/root.go | 19 | ||||
| -rw-r--r-- | internal/cli/run.go | 16 | ||||
| -rw-r--r-- | internal/cli/serve.go | 31 |
3 files changed, 42 insertions, 24 deletions
diff --git a/internal/cli/root.go b/internal/cli/root.go index e57a9d9..2cc8f71 100644 --- a/internal/cli/root.go +++ b/internal/cli/root.go @@ -38,18 +38,27 @@ func NewRootCmd() *cobra.Command { cmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose output") // Re-derive DBPath and LogDir after flags are parsed, so --data-dir takes effect. - // If --config is provided, load that file first; explicit CLI flags override it. + // Load config file: explicit --config flag, then default location, then defaults-only. cmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error { - if cfgFile != "" { + filePath := cfgFile + if filePath == "" { + home, _ := os.UserHomeDir() + filePath = filepath.Join(home, ".claudomator", "config.toml") + } + + if filePath != "" { // Save values set by explicit CLI flags before overwriting cfg from file. flagDataDir := cfg.DataDir flagClaudeBin := cfg.ClaudeBinaryPath - loaded, err := config.LoadFile(cfgFile) - if err != nil { + loaded, err := config.LoadFile(filePath) + if err != nil && cfgFile != "" { + // Only hard-fail if the file was explicitly specified. return err } - *cfg = *loaded + if err == nil { + *cfg = *loaded + } if cmd.Flags().Changed("data-dir") { cfg.DataDir = flagDataDir diff --git a/internal/cli/run.go b/internal/cli/run.go index 48f34b7..771c7b7 100644 --- a/internal/cli/run.go +++ b/internal/cli/run.go @@ -77,8 +77,10 @@ func runTasks(file string, parallel int, dryRun bool) error { apiURL = "http://" + cfg.ServerAddr } - runners := map[string]executor.Runner{ - "claude": &executor.ContainerRunner{ + runners := map[string]executor.Runner{} + + if cfg.Runners.ClaudeEnabled() { + runners["claude"] = &executor.ContainerRunner{ Image: cfg.ClaudeImage, Logger: logger, LogDir: cfg.LogDir, @@ -87,8 +89,10 @@ func runTasks(file string, parallel int, dryRun bool) error { SSHAuthSock: cfg.SSHAuthSock, ClaudeBinary: cfg.ClaudeBinaryPath, GeminiBinary: cfg.GeminiBinaryPath, - }, - "gemini": &executor.ContainerRunner{ + } + } + if cfg.Runners.GeminiEnabled() { + runners["gemini"] = &executor.ContainerRunner{ Image: cfg.GeminiImage, Logger: logger, LogDir: cfg.LogDir, @@ -97,11 +101,11 @@ func runTasks(file string, parallel int, dryRun bool) error { SSHAuthSock: cfg.SSHAuthSock, ClaudeBinary: cfg.ClaudeBinaryPath, GeminiBinary: cfg.GeminiBinaryPath, - }, + } } localClient := buildLocalLLMClient(cfg.LocalModel, logger) - if localClient != nil { + if localClient != nil && cfg.Runners.LocalEnabled() { runners["local"] = &executor.LocalRunner{ Client: localClient, Logger: logger, diff --git a/internal/cli/serve.go b/internal/cli/serve.go index fe0ba8e..f687e14 100644 --- a/internal/cli/serve.go +++ b/internal/cli/serve.go @@ -86,13 +86,16 @@ func serve(addr, basePath string) error { claudeConfigDir := cfg.ClaudeConfigDir repoDir, _ := os.Getwd() + // Shared per-task agent MCP token registry: runners mint tokens; the API // server mounts /mcp and resolves them. agentRegistry := executor.NewRegistry() - runners := map[string]executor.Runner{ - // ContainerRunner: binaries are resolved via PATH inside the container image, - // so ClaudeBinary/GeminiBinary are left empty (host paths would not exist inside). - "claude": &executor.ContainerRunner{ + runners := map[string]executor.Runner{} + + // ContainerRunner: binaries are resolved via PATH inside the container image, + // so ClaudeBinary/GeminiBinary are left empty (host paths would not exist inside). + if cfg.Runners.ClaudeEnabled() { + runners["claude"] = &executor.ContainerRunner{ Image: cfg.ClaudeImage, Logger: logger, LogDir: cfg.LogDir, @@ -103,8 +106,10 @@ func serve(addr, basePath string) error { CredentialSyncCmd: filepath.Join(repoDir, "scripts", "sync-credentials"), Store: store, Registry: agentRegistry, - }, - "gemini": &executor.ContainerRunner{ + } + } + if cfg.Runners.GeminiEnabled() { + runners["gemini"] = &executor.ContainerRunner{ Image: cfg.GeminiImage, Logger: logger, LogDir: cfg.LogDir, @@ -115,8 +120,10 @@ func serve(addr, basePath string) error { CredentialSyncCmd: filepath.Join(repoDir, "scripts", "sync-credentials"), Store: store, Registry: agentRegistry, - }, - "container": &executor.ContainerRunner{ + } + } + if cfg.Runners.ContainerEnabled() { + runners["container"] = &executor.ContainerRunner{ Image: "claudomator-agent:latest", Logger: logger, LogDir: cfg.LogDir, @@ -127,11 +134,11 @@ func serve(addr, basePath string) error { CredentialSyncCmd: filepath.Join(repoDir, "scripts", "sync-credentials"), Store: store, Registry: agentRegistry, - }, + } } localClient := buildLocalLLMClient(cfg.LocalModel, logger) - if localClient != nil { + if localClient != nil && cfg.Runners.LocalEnabled() { runners["local"] = &executor.LocalRunner{ Client: localClient, Logger: logger, @@ -141,7 +148,6 @@ func serve(addr, basePath string) error { logger.Info("local runner registered", "endpoint", cfg.LocalModel.Endpoint, "model", cfg.LocalModel.Model) } - pool := executor.NewPool(cfg.MaxConcurrent, runners, store, logger) pool.Classifier = &executor.Classifier{ LLM: localClient, @@ -152,7 +158,7 @@ func serve(addr, basePath string) error { } // Budget accountant: gate paid providers against rolling per-provider caps. - // With no limits configured this is created but allows everything. + // With no limits configured this is a no-op. var accountant *budget.Accountant if len(cfg.Budget.Provider5hUSD) > 0 { window := budget.DefaultWindow @@ -268,4 +274,3 @@ func serve(addr, basePath string) error { } return nil } - |
