helper max turns splitToolArgsMultiline faz split de argv estilo shell, mas com suporte a multilinha. Regras: - separa por whitespace (inclui \n) quando NÃO estiver dentro de aspas - suporta aspas simples e duplas - permite newline dentro de aspas (vira parte do mesmo argumento) - "\" funciona como
(ctx context.Context)
| 3016 | // - não interpreta sequências como \n => newline; mantém literal \ + n (quem interpreta é o plugin, se quiser) |
| 3017 | // - retorna erro se aspas não balanceadas ou escape pendente no final |
| 3018 | func (a *AgentMode) initMultiAgent(ctx context.Context) bool { |
| 3019 | modeStr := strings.TrimSpace(strings.ToLower(os.Getenv("CHATCLI_AGENT_PARALLEL_MODE"))) |
| 3020 | if modeStr == "false" || modeStr == "0" { |
| 3021 | a.parallelMode = false |
| 3022 | return false |
| 3023 | } |
| 3024 | |
| 3025 | // Registry already initialized — just update provider/model in case |
| 3026 | // the user switched providers at runtime. |
| 3027 | if a.agentRegistry != nil { |
| 3028 | a.parallelMode = true |
| 3029 | if a.agentDispatcher != nil { |
| 3030 | provider := a.cli.Provider |
| 3031 | if provider == "" { |
| 3032 | provider = os.Getenv("LLM_PROVIDER") |
| 3033 | } |
| 3034 | if provider == "" { |
| 3035 | provider = config.Global.GetString("LLM_PROVIDER") |
| 3036 | } |
| 3037 | model := a.cli.Model |
| 3038 | a.agentDispatcher.UpdateProviderModel(provider, model) |
| 3039 | a.logger.Info("Dispatcher provider/model updated for parallel agents", |
| 3040 | zap.String("provider", provider), |
| 3041 | zap.String("model", model), |
| 3042 | ) |
| 3043 | } |
| 3044 | return true |
| 3045 | } |
| 3046 | |
| 3047 | a.agentRegistry = workers.SetupDefaultRegistry() |
| 3048 | |
| 3049 | // Load custom persona agents into the worker registry |
| 3050 | if a.cli.personaHandler != nil { |
| 3051 | mgr := a.cli.personaHandler.GetManager() |
| 3052 | if customCount := workers.LoadCustomAgents(a.agentRegistry, mgr, a.logger); customCount > 0 { |
| 3053 | a.logger.Info("Custom persona agents loaded as workers", |
| 3054 | zap.Int("count", customCount), |
| 3055 | ) |
| 3056 | } |
| 3057 | } |
| 3058 | |
| 3059 | a.fileLockMgr = workers.NewFileLockManager() |
| 3060 | |
| 3061 | maxWorkersStr := os.Getenv("CHATCLI_AGENT_MAX_WORKERS") |
| 3062 | maxWorkers := workers.DefaultMaxWorkers |
| 3063 | if maxWorkersStr != "" { |
| 3064 | if v, err := strconv.Atoi(maxWorkersStr); err == nil && v > 0 { |
| 3065 | maxWorkers = v |
| 3066 | } |
| 3067 | } |
| 3068 | |
| 3069 | workerTimeout := workers.DefaultWorkerTimeout |
| 3070 | if ts := os.Getenv("CHATCLI_AGENT_WORKER_TIMEOUT"); ts != "" { |
| 3071 | if d, err := time.ParseDuration(ts); err == nil && d > 0 { |
| 3072 | workerTimeout = d |
| 3073 | } |
| 3074 | } |
| 3075 |
no test coverage detected