perspt_core/
events.rs

1//! Agent Events
2//!
3//! Event types for communication between the SRBN Orchestrator and TUI.
4//! Enables async, decoupled control flow for interactive agent sessions.
5
6use serde::{Deserialize, Serialize};
7
8/// Events emitted by the Orchestrator for TUI consumption
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub enum AgentEvent {
11    /// Task status changed
12    TaskStatusChanged { node_id: String, status: NodeStatus },
13
14    /// Plan generated by Architect
15    PlanGenerated(crate::types::TaskPlan),
16
17    /// Lyapunov energy updated
18    EnergyUpdated { node_id: String, energy: f32 },
19
20    /// Log message for display
21    Log(String),
22
23    /// Node completed successfully
24    NodeCompleted { node_id: String, goal: String },
25
26    /// Approval required before proceeding
27    ApprovalRequest {
28        request_id: String,
29        node_id: String,
30        action_type: ActionType,
31        description: String,
32        diff: Option<String>,
33    },
34
35    /// Orchestration finished
36    Complete { success: bool, message: String },
37
38    /// Error occurred
39    Error(String),
40}
41
42/// Node status for TUI display (mirrors NodeState but simplified)
43#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
44pub enum NodeStatus {
45    Pending,
46    Running,
47    Verifying,
48    Completed,
49    Failed,
50    Escalated,
51}
52
53/// Type of action requiring approval
54#[derive(Debug, Clone, Serialize, Deserialize)]
55pub enum ActionType {
56    /// File creation or modification
57    FileWrite { path: String },
58    /// Shell command execution
59    Command { command: String },
60    /// Multiple files in a sub-graph
61    SubGraph { node_count: usize },
62    /// Project initialization (with editable name)
63    ProjectInit {
64        command: String,
65        suggested_name: String,
66    },
67}
68
69/// Actions sent from TUI to Orchestrator
70#[derive(Debug, Clone, Serialize, Deserialize)]
71pub enum AgentAction {
72    /// Approve a pending request
73    Approve { request_id: String },
74    /// Approve with an edited value (e.g., project name)
75    ApproveWithEdit {
76        request_id: String,
77        edited_value: String,
78    },
79    /// Reject a pending request
80    Reject {
81        request_id: String,
82        reason: Option<String>,
83    },
84    /// Pause orchestration
85    Pause,
86    /// Resume orchestration
87    Resume,
88    /// Abort the entire session
89    Abort,
90}
91
92/// Channel types for agent communication
93pub mod channel {
94    use super::{AgentAction, AgentEvent};
95    use tokio::sync::mpsc;
96
97    /// Sender for AgentEvents (Orchestrator → TUI)
98    pub type EventSender = mpsc::UnboundedSender<AgentEvent>;
99    /// Receiver for AgentEvents (Orchestrator → TUI)
100    pub type EventReceiver = mpsc::UnboundedReceiver<AgentEvent>;
101
102    /// Sender for AgentActions (TUI → Orchestrator)
103    pub type ActionSender = mpsc::UnboundedSender<AgentAction>;
104    /// Receiver for AgentActions (TUI → Orchestrator)
105    pub type ActionReceiver = mpsc::UnboundedReceiver<AgentAction>;
106
107    /// Create event channel (Orchestrator → TUI)
108    pub fn event_channel() -> (EventSender, EventReceiver) {
109        mpsc::unbounded_channel()
110    }
111
112    /// Create action channel (TUI → Orchestrator)
113    pub fn action_channel() -> (ActionSender, ActionReceiver) {
114        mpsc::unbounded_channel()
115    }
116}