fix: resume waiting_approval workflows directly instead of re-planning
When a user approves a wait_for_approval step, resume execution from that step instead of calling process_feedback which may trigger revise_plan and restart from step 1. Also check state snapshot for WaitingApproval steps to handle pod restart scenarios where DB status may already be 'executing' but state still has the waiting step.
This commit is contained in:
18
src/agent.rs
18
src/agent.rs
@@ -426,15 +426,21 @@ async fn agent_loop(
|
|||||||
.and_then(|json| serde_json::from_str::<AgentState>(&json).ok())
|
.and_then(|json| serde_json::from_str::<AgentState>(&json).ok())
|
||||||
.unwrap_or_else(AgentState::new);
|
.unwrap_or_else(AgentState::new);
|
||||||
|
|
||||||
// For failed/done workflows: reset failed steps and continue directly
|
// Resume directly if: workflow is failed/done/waiting_approval,
|
||||||
// For running workflows: process feedback via LLM
|
// OR if state snapshot has a WaitingApproval step (e.g. after pod restart)
|
||||||
let is_resuming = wf.status == "failed" || wf.status == "done";
|
let has_waiting_step = state.steps.iter().any(|s| matches!(s.status, StepStatus::WaitingApproval));
|
||||||
|
let is_resuming = wf.status == "failed" || wf.status == "done"
|
||||||
|
|| wf.status == "waiting_approval" || has_waiting_step;
|
||||||
if is_resuming {
|
if is_resuming {
|
||||||
// Reset Failed steps to Pending so they get re-executed
|
// Reset Failed/WaitingApproval steps so they get re-executed
|
||||||
for step in &mut state.steps {
|
for step in &mut state.steps {
|
||||||
if matches!(step.status, StepStatus::Failed) {
|
if matches!(step.status, StepStatus::Failed) {
|
||||||
step.status = StepStatus::Pending;
|
step.status = StepStatus::Pending;
|
||||||
}
|
}
|
||||||
|
if matches!(step.status, StepStatus::WaitingApproval) {
|
||||||
|
// Mark as Running so it continues (not re-plans)
|
||||||
|
step.status = StepStatus::Running;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Attach comment as feedback to the first actionable step
|
// Attach comment as feedback to the first actionable step
|
||||||
if let Some(order) = state.first_actionable_step() {
|
if let Some(order) = state.first_actionable_step() {
|
||||||
@@ -442,8 +448,8 @@ async fn agent_loop(
|
|||||||
step.user_feedbacks.push(content.clone());
|
step.user_feedbacks.push(content.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tracing::info!("[workflow {}] Resuming from state, first actionable: {:?}",
|
tracing::info!("[workflow {}] Resuming from state (status={}), first actionable: {:?}",
|
||||||
workflow_id, state.first_actionable_step());
|
workflow_id, wf.status, state.first_actionable_step());
|
||||||
} else {
|
} else {
|
||||||
// Active workflow: LLM decides whether to revise plan
|
// Active workflow: LLM decides whether to revise plan
|
||||||
state = process_feedback(
|
state = process_feedback(
|
||||||
|
|||||||
Reference in New Issue
Block a user