diff options
Diffstat (limited to 'makima/src/daemon/task/manager.rs')
| -rw-r--r-- | makima/src/daemon/task/manager.rs | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/makima/src/daemon/task/manager.rs b/makima/src/daemon/task/manager.rs index 555cd2a..179c07f 100644 --- a/makima/src/daemon/task/manager.rs +++ b/makima/src/daemon/task/manager.rs @@ -947,6 +947,8 @@ pub struct ManagedTask { pub contract_id: Option<Uuid>, /// Whether to run in autonomous loop mode. pub autonomous_loop: bool, + /// Override max_iterations for this task (None = use config default). + pub max_iterations: Option<u32>, /// Time task was created. pub created_at: Instant, /// Time task started running. @@ -985,6 +987,9 @@ pub struct TaskConfig { /// Interval in seconds between heartbeat commits (WIP checkpoints). /// Set to 0 to disable. Default: 300 (5 minutes). pub heartbeat_commit_interval_secs: u64, + /// Maximum iterations for autonomous task loops. + /// Set to 0 for unlimited (not recommended). Default: 10. + pub max_iterations: u32, } impl Default for TaskConfig { @@ -1002,6 +1007,7 @@ impl Default for TaskConfig { api_url: "https://api.makima.jp".to_string(), api_key: String::new(), heartbeat_commit_interval_secs: 300, // 5 minutes + max_iterations: 10, } } } @@ -1176,6 +1182,7 @@ impl TaskManager { autonomous_loop, resume_session, conversation_history, + max_iterations, } => { tracing::info!( task_id = %task_id, @@ -1194,6 +1201,7 @@ impl TaskManager { continue_from_task_id = ?continue_from_task_id, copy_files = ?copy_files, contract_id = ?contract_id, + max_iterations = ?max_iterations, plan_len = plan.len(), "Spawning new task" ); @@ -1202,7 +1210,7 @@ impl TaskManager { parent_task_id, depth, is_orchestrator, is_supervisor, target_repo_path, completion_action, continue_from_task_id, copy_files, contract_id, autonomous_loop, resume_session, - conversation_history, + conversation_history, max_iterations, ).await?; } DaemonCommand::PauseTask { task_id } => { @@ -1501,6 +1509,7 @@ impl TaskManager { autonomous_loop: bool, resume_session: bool, conversation_history: Option<serde_json::Value>, + max_iterations: Option<u32>, ) -> TaskResult<()> { tracing::info!(task_id = %task_id, is_orchestrator = is_orchestrator, is_supervisor = is_supervisor, depth = depth, "=== SPAWN_TASK START ==="); @@ -1554,6 +1563,7 @@ impl TaskManager { copy_files: copy_files.clone(), contract_id, autonomous_loop, + max_iterations, created_at: Instant::now(), started_at: None, completed_at: None, @@ -1578,7 +1588,7 @@ impl TaskManager { task_id, task_name, plan, repo_url, base_branch, target_branch, is_orchestrator, is_supervisor, target_repo_path, completion_action, continue_from_task_id, copy_files, contract_id, autonomous_loop, resume_session, - conversation_history, + conversation_history, max_iterations, ).await { tracing::error!(task_id = %task_id, error = %e, "Task execution failed"); inner.mark_failed(task_id, &e.to_string()).await; @@ -1604,6 +1614,7 @@ impl TaskManager { git_user_name: self.git_user_name.clone(), api_url: self.config.api_url.clone(), heartbeat_commit_interval_secs: self.config.heartbeat_commit_interval_secs, + max_iterations: self.config.max_iterations, } } @@ -2900,6 +2911,8 @@ struct TaskManagerInner { git_user_name: Arc<RwLock<Option<String>>>, api_url: String, heartbeat_commit_interval_secs: u64, + /// Maximum iterations for autonomous task loops (from config). + max_iterations: u32, } impl TaskManagerInner { @@ -2923,8 +2936,9 @@ impl TaskManagerInner { autonomous_loop: bool, resume_session: bool, conversation_history: Option<serde_json::Value>, + max_iterations: Option<u32>, ) -> Result<(), DaemonError> { - tracing::info!(task_id = %task_id, is_orchestrator = is_orchestrator, is_supervisor = is_supervisor, resume_session = resume_session, "=== RUN_TASK START ==="); + tracing::info!(task_id = %task_id, is_orchestrator = is_orchestrator, is_supervisor = is_supervisor, resume_session = resume_session, max_iterations = ?max_iterations, "=== RUN_TASK START ==="); // If resuming session, try to find existing worktree first let existing_worktree = if resume_session { @@ -3567,7 +3581,10 @@ impl TaskManagerInner { // For autonomous loop mode: track accumulated output for COMPLETION_GATE detection let mut accumulated_output = String::new(); - let mut circuit_breaker = CircuitBreaker::new(); + // Use task-specific max_iterations if provided, otherwise use config default + let effective_max_iterations = max_iterations.unwrap_or(self.max_iterations); + let mut circuit_breaker = CircuitBreaker::with_thresholds(3, 5, effective_max_iterations); + tracing::info!(task_id = %task_id, effective_max_iterations = effective_max_iterations, "Circuit breaker initialized"); let mut iteration_count = 0u32; let mut final_exit_code: i64 = -1; // Track the final exit code across iterations |
