refactor: streamline agent turn handling and background review process

This commit is contained in:
asepharyana
2026-07-20 17:25:23 +07:00
parent 4c186b62d4
commit dd7825b481
14 changed files with 409 additions and 327 deletions
+70
View File
@@ -203,6 +203,76 @@ pub fn apply_action(state: &mut crate::state::AppStateRest, action: Action) {
// Mark dirty so spinner disappears
state.dirty = true;
}
zesdex_infrastructure::TurnEvent::WorkflowAgentUpdate {
agent_id,
agent_name,
status,
} => {
// Find existing agent by ID, or create new one
let idx = state
.workflow_engine
.agents
.iter()
.position(|a| a.name == agent_id);
match status {
zesdex_infrastructure::AgentStatus::Pending => {
if idx.is_none() {
state.workflow_engine.agents.push(
crate::state::SimpleAgent::with_display(
agent_id,
agent_name,
),
);
}
}
zesdex_infrastructure::AgentStatus::Running => {
if let Some(i) = idx {
state.workflow_engine.agents[i].state =
crate::state::AgentState::Running;
state.workflow_engine.agents[i].display_name =
agent_name;
state.workflow_engine.agents[i].started_at =
Some(chrono::Utc::now().timestamp_millis());
} else {
let mut agent =
crate::state::SimpleAgent::with_display(
agent_id,
agent_name,
);
agent.state = crate::state::AgentState::Running;
agent.started_at =
Some(chrono::Utc::now().timestamp_millis());
state.workflow_engine.agents.push(agent);
}
}
zesdex_infrastructure::AgentStatus::Completed => {
if let Some(i) = idx {
state.workflow_engine.agents[i].state =
crate::state::AgentState::Completed;
state.workflow_engine.agents[i].display_name =
agent_name;
state.workflow_engine.agents[i].completed_at =
Some(chrono::Utc::now().timestamp_millis());
}
}
zesdex_infrastructure::AgentStatus::Failed(msg) => {
if let Some(i) = idx {
state.workflow_engine.agents[i].state =
crate::state::AgentState::Failed;
state.workflow_engine.agents[i].display_name =
agent_name;
state.workflow_engine.agents[i].error = Some(msg);
}
}
zesdex_infrastructure::AgentStatus::Cancelled => {
if let Some(i) = idx {
state.workflow_engine.agents.remove(i);
}
}
}
state.dirty = true;
}
_ => {
debug!("unhandled turn event variant");
state.dirty = true;
+18 -2
View File
@@ -616,8 +616,10 @@ pub enum AgentState {
/// A single agent entry in the workflow sidebar.
#[derive(Debug, Clone)]
pub struct SimpleAgent {
/// Agent display name.
/// Agent unique ID (e.g. "auto-review", "Node-0-1").
pub name: String,
/// Human-readable display label (e.g. "Auto-Review", "Backend API Agent").
pub display_name: String,
/// Current lifecycle state.
pub state: AgentState,
/// Millisecond timestamp when the agent started.
@@ -631,9 +633,10 @@ pub struct SimpleAgent {
}
impl SimpleAgent {
/// Create a new agent with the given name.
/// Create a new agent with the given name (used as both ID and display name).
pub fn new(name: String) -> Self {
SimpleAgent {
display_name: name.clone(),
name,
state: AgentState::Idle,
started_at: None,
@@ -642,6 +645,19 @@ impl SimpleAgent {
progress: None,
}
}
/// Create a new agent with separate ID and display label.
pub fn with_display(name: String, display_name: String) -> Self {
SimpleAgent {
name,
display_name,
state: AgentState::Idle,
started_at: None,
completed_at: None,
error: None,
progress: None,
}
}
}
/// Simplified workflow engine state for TUI display.
-13
View File
@@ -61,17 +61,6 @@ pub fn spawn_agent_turn(state: &mut AppStateRest, text: String) {
info!("delegating agent turn to infrastructure engine (model: {})", model);
let edit_count = state
.session_runtime
.as_ref()
.map(|rt| rt.edit_count)
.unwrap_or(0);
let consecutive_empty_reviews = state
.session_runtime
.as_ref()
.map(|rt| rt.consecutive_empty_reviews)
.unwrap_or(0);
let params = AgentTurnParams {
messages,
session_dir,
@@ -82,8 +71,6 @@ pub fn spawn_agent_turn(state: &mut AppStateRest, text: String) {
api_key,
model,
api_base,
edit_count,
consecutive_empty_reviews,
};
backend_spawn_agent_turn(params);
+1 -1
View File
@@ -130,7 +130,7 @@ pub fn draw_workflow_panel(
Style::default().fg(color).add_modifier(Modifier::BOLD),
),
Span::styled(
format!(" {}", agent.name),
format!(" {}", agent.display_name),
Style::default()
.fg(Theme::TEXT)
.add_modifier(Modifier::BOLD),