From bb8772e902f84eea11014e8c85ef4356b8aa73fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BF=9D=E5=BA=93=EF=BC=88baoku=EF=BC=89?= Date: Thu, 29 Jan 2026 16:26:57 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B8=BA=20codeagent-wrapper=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20Gemini=20=E6=A8=A1=E5=9E=8B=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增功能: - 添加 --gemini-model 参数,支持指定 Gemini 模型(如 gemini-2.5-flash) - 支持 GEMINI_MODEL 环境变量配置,CLI 参数优先级高于环境变量 - 模型参数自动插入到 gemini CLI 调用的正确位置(-m 参数在其他参数之前) - 添加详细的日志记录和警告提示 - 更新帮助文档,说明参数用法和示例 技术实现: - Config 结构体新增 GeminiModel 字段 - parseArgs() 函数支持 --gemini-model 和 --gemini-model= 两种语法 - buildGeminiArgs() 函数在构建参数时优先插入模型参数 - 添加跨后端和并行模式的参数验证警告 版本更新:v5.7.1 → v5.7.2 --- codeagent-wrapper/backend.go | 12 +++++++++++- codeagent-wrapper/config.go | 24 +++++++++++++++++++++++- codeagent-wrapper/main.go | 35 ++++++++++++++++++++++++++++++++++- 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/codeagent-wrapper/backend.go b/codeagent-wrapper/backend.go index 9afc0c1..d3bac4a 100644 --- a/codeagent-wrapper/backend.go +++ b/codeagent-wrapper/backend.go @@ -4,6 +4,7 @@ import ( "encoding/json" "os" "path/filepath" + "strings" ) // Backend defines the contract for invoking different AI CLI backends. @@ -120,7 +121,16 @@ func buildGeminiArgs(cfg *Config, targetArg string) []string { if cfg == nil { return nil } - args := []string{"--output-format", "stream-json", "-y"} + + args := []string{} + + // Add model parameter first (if specified) + if model := strings.TrimSpace(cfg.GeminiModel); model != "" { + args = append(args, "-m", model) + } + + // Existing args + args = append(args, "-o", "stream-json", "-y") if cfg.Mode == "resume" { if cfg.SessionID != "" { diff --git a/codeagent-wrapper/config.go b/codeagent-wrapper/config.go index 9524770..1ff3486 100644 --- a/codeagent-wrapper/config.go +++ b/codeagent-wrapper/config.go @@ -20,6 +20,7 @@ type Config struct { Backend string SkipPermissions bool MaxParallelWorkers int + GeminiModel string // Gemini model name (empty = use default) } // ParallelConfig defines the JSON schema for parallel execution @@ -197,6 +198,9 @@ func parseArgs() (*Config, error) { return nil, fmt.Errorf("task required") } + // Read environment variable (lowest precedence) + geminiModel := strings.TrimSpace(os.Getenv("GEMINI_MODEL")) + backendName := defaultBackendName skipPermissions := envFlagEnabled("CODEAGENT_SKIP_PERMISSIONS") filtered := make([]string, 0, len(args)) @@ -220,6 +224,24 @@ func parseArgs() (*Config, error) { } backendName = value continue + case arg == "--gemini-model": + if i+1 >= len(args) { + return nil, fmt.Errorf("--gemini-model flag requires a non-empty model name") + } + value := strings.TrimSpace(args[i+1]) + if value == "" { + return nil, fmt.Errorf("--gemini-model flag requires a non-empty model name") + } + geminiModel = value + i++ + continue + case strings.HasPrefix(arg, "--gemini-model="): + value := strings.TrimSpace(strings.TrimPrefix(arg, "--gemini-model=")) + if value == "" { + return nil, fmt.Errorf("--gemini-model flag requires a non-empty model name") + } + geminiModel = value + continue case arg == "--skip-permissions", arg == "--dangerously-skip-permissions": skipPermissions = true continue @@ -238,7 +260,7 @@ func parseArgs() (*Config, error) { } args = filtered - cfg := &Config{WorkDir: defaultWorkdir, Backend: backendName, SkipPermissions: skipPermissions} + cfg := &Config{WorkDir: defaultWorkdir, Backend: backendName, SkipPermissions: skipPermissions, GeminiModel: geminiModel} cfg.MaxParallelWorkers = resolveMaxParallelWorkers() if args[0] == "resume" { diff --git a/codeagent-wrapper/main.go b/codeagent-wrapper/main.go index 49a7488..9f7179e 100644 --- a/codeagent-wrapper/main.go +++ b/codeagent-wrapper/main.go @@ -14,7 +14,7 @@ import ( ) const ( - version = "5.7.1" + version = "5.7.2" defaultWorkdir = "." defaultTimeout = 7200 // seconds (2 hours) defaultCoverageTarget = 90.0 @@ -197,6 +197,9 @@ func run() (exitCode int) { fullOutput := false var extras []string + // Check for gemini-model in parallel mode + geminiModelInParallel := false + for i := 0; i < len(args); i++ { arg := args[i] switch { @@ -218,11 +221,19 @@ func run() (exitCode int) { return 1 } backendName = value + case arg == "--gemini-model" || strings.HasPrefix(arg, "--gemini-model="): + geminiModelInParallel = true + continue default: extras = append(extras, arg) } } + // Warn about unsupported parameter + if geminiModelInParallel { + logWarn("--gemini-model parameter is not supported in parallel mode") + } + if len(extras) > 0 { fmt.Fprintln(os.Stderr, "ERROR: --parallel reads its task configuration from stdin; only --backend and --full-output are allowed.") fmt.Fprintln(os.Stderr, "Usage examples:") @@ -322,6 +333,14 @@ func run() (exitCode int) { } logInfo(fmt.Sprintf("Parsed args: mode=%s, task_len=%d, backend=%s", cfg.Mode, len(cfg.Task), cfg.Backend)) + // Log environment variable usage + if cfg.GeminiModel != "" { + envModel := strings.TrimSpace(os.Getenv("GEMINI_MODEL")) + if envModel != "" && envModel == cfg.GeminiModel { + logInfo(fmt.Sprintf("Gemini model from env: %s", cfg.GeminiModel)) + } + } + backend, err := selectBackendFn(cfg.Backend) if err != nil { logError(err.Error()) @@ -342,6 +361,16 @@ func run() (exitCode int) { } logInfo(fmt.Sprintf("Selected backend: %s", backend.Name())) + // Log model parameter usage + if cfg.GeminiModel != "" && cfg.Backend == "gemini" { + logInfo(fmt.Sprintf("Using Gemini model: %s", cfg.GeminiModel)) + } + + // Warn if model parameter used with non-gemini backend + if cfg.GeminiModel != "" && cfg.Backend != "gemini" { + logWarn("--gemini-model parameter is only effective with --backend gemini") + } + timeoutSec := resolveTimeout() logInfo(fmt.Sprintf("Timeout: %ds", timeoutSec)) cfg.Timeout = timeoutSec @@ -532,6 +561,10 @@ Parallel mode examples: Options: --lite, -L Lite mode: disable Web UI, faster response --backend Select backend (codex, gemini, claude) + --gemini-model Specify Gemini model (gemini backend only) + Can also be set via GEMINI_MODEL environment variable + CLI parameter takes precedence over environment variable + Examples: gemini-2.5-flash, gemini-1.5-pro Environment Variables: CODEX_TIMEOUT Timeout in milliseconds (default: 7200000)