everruns_core/
execution_context.rs1use everruns_provider::typed_id::{ExecId, MessageId, SessionId, TurnId, WorkspaceId};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct ExecutionContext {
9 pub session_id: SessionId,
11 pub turn_id: TurnId,
13 pub input_message_id: MessageId,
15 pub exec_id: ExecId,
17 #[serde(default)]
19 pub workspace_id: Option<WorkspaceId>,
20}
21
22impl ExecutionContext {
23 pub fn new(session_id: SessionId, turn_id: TurnId, input_message_id: MessageId) -> Self {
25 Self {
26 session_id,
27 turn_id,
28 input_message_id,
29 exec_id: ExecId::new(),
30 workspace_id: None,
31 }
32 }
33
34 pub fn with_workspace_id(mut self, workspace_id: WorkspaceId) -> Self {
36 self.workspace_id = Some(workspace_id);
37 self
38 }
39
40 pub fn next_exec(&self) -> Self {
42 Self {
43 session_id: self.session_id,
44 turn_id: self.turn_id,
45 input_message_id: self.input_message_id,
46 exec_id: ExecId::new(),
47 workspace_id: self.workspace_id,
48 }
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 #[test]
57 fn next_exec_preserves_lineage_and_changes_execution_id() {
58 let context = ExecutionContext::new(SessionId::new(), TurnId::new(), MessageId::new());
59 let next = context.next_exec();
60
61 assert_eq!(next.session_id, context.session_id);
62 assert_eq!(next.turn_id, context.turn_id);
63 assert_eq!(next.input_message_id, context.input_message_id);
64 assert_ne!(next.exec_id, context.exec_id);
65 }
66
67 #[test]
68 fn serialization_round_trips() {
69 let context = ExecutionContext::new(SessionId::new(), TurnId::new(), MessageId::new());
70 let json = serde_json::to_string(&context).unwrap();
71 let parsed: ExecutionContext = serde_json::from_str(&json).unwrap();
72
73 assert_eq!(parsed.session_id, context.session_id);
74 assert_eq!(parsed.turn_id, context.turn_id);
75 assert_eq!(parsed.input_message_id, context.input_message_id);
76 assert_eq!(parsed.exec_id, context.exec_id);
77 }
78}