Skip to main content

vtcode_core/subagents/matrix/
projection.rs

1use super::*;
2use crate::subagents::{SubagentStatus, SubagentStatusEntry};
3
4impl SubagentController {
5    /// Existing Local Agents rows are derived from durable task checkpoints.
6    pub(in crate::subagents) async fn matrix_projection_entries(&self) -> Vec<SubagentStatusEntry> {
7        let guard = self.matrix.state.lock().await;
8        let Some(state) = guard.as_ref() else {
9            return vec![];
10        };
11        let snapshot = state.snapshot();
12        let parent = self.parent_session_id.read().await.clone();
13        let updated_at = *self.matrix.updated_at.read();
14        snapshot
15            .tasks
16            .iter()
17            .zip(&snapshot.spec.tasks)
18            .map(|(state, task)| {
19                let attempt = state.attempts.last();
20                let (status, summary) = match state.status {
21                    MatrixTaskStatus::Queued => (
22                        SubagentStatus::Queued,
23                        if task.dependencies.iter().any(|id| {
24                            snapshot.tasks.iter().any(|task| {
25                                &task.id == id
26                                    && !matches!(task.status, MatrixTaskStatus::Executed | MatrixTaskStatus::Verified)
27                            })
28                        }) {
29                            "waiting for dependencies"
30                        } else {
31                            "waiting for worker, resources or workspace lease"
32                        },
33                    ),
34                    MatrixTaskStatus::Assigned => (
35                        SubagentStatus::Running,
36                        if attempt.is_some_and(|attempt| attempt.phase == MatrixPhase::Verify) {
37                            "final verification in progress"
38                        } else {
39                            "execution in progress"
40                        },
41                    ),
42                    MatrixTaskStatus::Executed => {
43                        (SubagentStatus::Waiting, "execution finished; final verification pending")
44                    }
45                    MatrixTaskStatus::Verified => (
46                        if snapshot.lifecycle == MatrixLifecycle::Succeeded {
47                            SubagentStatus::Completed
48                        } else {
49                            SubagentStatus::Waiting
50                        },
51                        "verified against current generation",
52                    ),
53                    MatrixTaskStatus::CleanupUncertain => {
54                        (SubagentStatus::Failed, "owned cleanup uncertain; resources held")
55                    }
56                    _ => (SubagentStatus::Failed, "coordinator decision required"),
57                };
58                let status = if snapshot.lifecycle == MatrixLifecycle::Cancelled {
59                    SubagentStatus::Closed
60                } else {
61                    status
62                };
63                SubagentStatusEntry {
64                    id: format!("matrix-{}-{}", snapshot.spec.id, task.id),
65                    session_id: attempt
66                        .map(|attempt| format!("matrix-{}-{}", parent, attempt.worker_id))
67                        .unwrap_or_default(),
68                    parent_thread_id: parent.clone(),
69                    agent_name: "matrix".into(),
70                    display_label: format!("{} / {}", snapshot.spec.id, task.id),
71                    description: task.instructions.clone(),
72                    source: "matrix".into(),
73                    color: None,
74                    status,
75                    background: false,
76                    depth: self.config.depth + 1,
77                    created_at: updated_at,
78                    updated_at,
79                    completed_at: status.is_terminal().then_some(updated_at),
80                    summary: Some(summary.into()),
81                    error: self.matrix.error.read().clone(),
82                    transcript_path: None,
83                    nickname: None,
84                }
85            })
86            .collect()
87    }
88}
89
90pub(super) fn tracker_result(snapshot: &MatrixSnapshot) -> Value {
91    let items = snapshot
92        .tasks
93        .iter()
94        .map(|task| {
95            let status = if snapshot.lifecycle == MatrixLifecycle::Cancelled {
96                "blocked"
97            } else {
98                match task.status {
99                    MatrixTaskStatus::Queued => "pending",
100                    MatrixTaskStatus::Assigned | MatrixTaskStatus::Executed => "in_progress",
101                    MatrixTaskStatus::Verified if snapshot.lifecycle == MatrixLifecycle::Succeeded => "completed",
102                    MatrixTaskStatus::Verified => "in_progress",
103                    _ => "blocked",
104                }
105            };
106            json!({"description":task.id,"status":status})
107        })
108        .collect::<Vec<_>>();
109    let lines = crate::tools::handlers::task_tracking::compact_task_tree_view_from_items(&items);
110    json!({"success":true,"matrix_id":snapshot.spec.id,"revision":snapshot.revision,
111        "view":{"title":format!("Matrix {}",snapshot.spec.id),"lines":lines},
112        "summary":{"total":items.len(),"completed":items.iter().filter(|item|item["status"]=="completed").count(),"in_progress":items.iter().filter(|item|item["status"]=="in_progress").count(),"pending":items.iter().filter(|item|item["status"]=="pending").count(),"blocked":items.iter().filter(|item|item["status"]=="blocked").count()}})
113}
114
115impl SubagentController {
116    pub async fn matrix_tracker_projection(&self) -> Option<Value> {
117        self.matrix
118            .state
119            .lock()
120            .await
121            .as_ref()
122            .map(|state| tracker_result(state.snapshot()))
123    }
124}