summaryrefslogtreecommitdiff
path: root/makima/src/daemon/task
diff options
context:
space:
mode:
Diffstat (limited to 'makima/src/daemon/task')
-rw-r--r--makima/src/daemon/task/manager.rs25
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