orchestral_runtime/
interaction.rs1use chrono::{DateTime, Utc};
11use serde::{Deserialize, Serialize};
12
13use super::thread::ThreadId;
14use orchestral_core::types::TaskId;
15
16pub use orchestral_core::store::InteractionId;
17
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
20#[serde(rename_all = "snake_case")]
21pub enum InteractionState {
22 Active,
24 WaitingUser,
26 WaitingEvent,
28 Paused,
30 Completed,
32 Failed,
34 Cancelled,
36}
37
38impl InteractionState {
39 pub fn is_terminal(&self) -> bool {
41 matches!(
42 self,
43 InteractionState::Completed | InteractionState::Failed | InteractionState::Cancelled
44 )
45 }
46
47 pub fn is_active(&self) -> bool {
49 matches!(self, InteractionState::Active)
50 }
51
52 pub fn is_waiting(&self) -> bool {
54 matches!(
55 self,
56 InteractionState::WaitingUser | InteractionState::WaitingEvent
57 )
58 }
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct Interaction {
64 pub id: InteractionId,
66 pub thread_id: ThreadId,
68 pub state: InteractionState,
70 pub task_ids: Vec<TaskId>,
72 pub started_at: DateTime<Utc>,
74 pub ended_at: Option<DateTime<Utc>>,
76}
77
78impl Interaction {
79 pub fn new(thread_id: impl Into<ThreadId>) -> Self {
81 Self {
82 id: InteractionId::from(uuid::Uuid::new_v4().to_string()),
83 thread_id: thread_id.into(),
84 state: InteractionState::Active,
85 task_ids: Vec::new(),
86 started_at: Utc::now(),
87 ended_at: None,
88 }
89 }
90
91 pub fn with_id(id: impl Into<InteractionId>, thread_id: impl Into<ThreadId>) -> Self {
93 Self {
94 id: id.into(),
95 thread_id: thread_id.into(),
96 state: InteractionState::Active,
97 task_ids: Vec::new(),
98 started_at: Utc::now(),
99 ended_at: None,
100 }
101 }
102
103 pub fn add_task(&mut self, task_id: TaskId) {
105 self.task_ids.push(task_id);
106 }
107
108 pub fn set_state(&mut self, state: InteractionState) {
110 let is_terminal = state.is_terminal();
111 self.state = state;
112 if is_terminal && self.ended_at.is_none() {
113 self.ended_at = Some(Utc::now());
114 }
115 }
116
117 pub fn complete(&mut self) {
119 self.set_state(InteractionState::Completed);
120 }
121
122 pub fn fail(&mut self) {
124 self.set_state(InteractionState::Failed);
125 }
126
127 pub fn cancel(&mut self) {
129 self.set_state(InteractionState::Cancelled);
130 }
131
132 pub fn wait_for_user(&mut self) {
134 self.set_state(InteractionState::WaitingUser);
135 }
136
137 pub fn wait_for_event(&mut self) {
139 self.set_state(InteractionState::WaitingEvent);
140 }
141
142 pub fn resume(&mut self) {
144 if !self.state.is_terminal() {
145 self.state = InteractionState::Active;
146 }
147 }
148
149 pub fn duration(&self) -> Option<chrono::Duration> {
151 self.ended_at.map(|end| end - self.started_at)
152 }
153}