feat: 为 codeagent-wrapper 添加 Gemini 模型参数支持

新增功能:
- 添加 --gemini-model 参数,支持指定 Gemini 模型(如 gemini-2.5-flash)
- 支持 GEMINI_MODEL 环境变量配置,CLI 参数优先级高于环境变量
- 模型参数自动插入到 gemini CLI 调用的正确位置(-m 参数在其他参数之前)
- 添加详细的日志记录和警告提示
- 更新帮助文档,说明参数用法和示例

技术实现:
- Config 结构体新增 GeminiModel 字段
- parseArgs() 函数支持 --gemini-model 和 --gemini-model=<value> 两种语法
- buildGeminiArgs() 函数在构建参数时优先插入模型参数
- 添加跨后端和并行模式的参数验证警告

版本更新:v5.7.1 → v5.7.2
This commit is contained in:
保库(baoku) committed 2026-01-29 16:26:57 +08:00
1 parent e14496868f
commit bb8772e902
3 files changed
+68 -3

No files matched your search

+11 -1
View File
@@ -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 != "" {
+23 -1
View File
@@ -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" {
+34 -1
View File
@@ -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 <name> Select backend (codex, gemini, claude)
--gemini-model <name> 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)