praxis_graph/types/
events.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize)]
8#[serde(tag = "type", rename_all = "snake_case")]
9pub enum StreamEvent {
10 InitStream {
12 run_id: String,
13 conversation_id: String,
14 timestamp: i64,
15 },
16
17 Reasoning {
19 content: String,
20 },
21
22 Message {
24 content: String,
25 },
26
27 ToolCall {
29 index: u32,
30 #[serde(skip_serializing_if = "Option::is_none")]
31 id: Option<String>,
32 #[serde(skip_serializing_if = "Option::is_none")]
33 name: Option<String>,
34 #[serde(skip_serializing_if = "Option::is_none")]
35 arguments: Option<String>,
36 },
37
38 ToolResult {
40 tool_call_id: String,
41 result: String,
42 is_error: bool,
43 duration_ms: u64,
44 },
45
46 Done {
48 #[serde(skip_serializing_if = "Option::is_none")]
49 finish_reason: Option<String>,
50 },
51
52 Error {
54 message: String,
55 #[serde(skip_serializing_if = "Option::is_none")]
56 node_id: Option<String>,
57 },
58
59 EndStream {
61 status: String,
62 total_duration_ms: u64,
63 },
64}
65
66impl From<praxis_llm::StreamEvent> for StreamEvent {
68 fn from(event: praxis_llm::StreamEvent) -> Self {
69 match event {
70 praxis_llm::StreamEvent::Reasoning { content } => {
71 Self::Reasoning { content }
72 }
73 praxis_llm::StreamEvent::Message { content } => {
74 Self::Message { content }
75 }
76 praxis_llm::StreamEvent::ToolCall {
77 index,
78 id,
79 name,
80 arguments,
81 } => Self::ToolCall {
82 index,
83 id,
84 name,
85 arguments,
86 },
87 praxis_llm::StreamEvent::Done { finish_reason } => {
88 Self::Done { finish_reason }
89 }
90 }
91 }
92}
93
94impl praxis_persist::StreamEventExtractor for StreamEvent {
96 fn is_reasoning(&self) -> bool {
97 matches!(self, Self::Reasoning { .. })
98 }
99
100 fn is_message(&self) -> bool {
101 matches!(self, Self::Message { .. })
102 }
103
104 fn is_tool_call(&self) -> bool {
105 matches!(self, Self::ToolCall { .. })
106 }
107
108 fn reasoning_content(&self) -> Option<&str> {
109 match self {
110 Self::Reasoning { content } => Some(content),
111 _ => None,
112 }
113 }
114
115 fn message_content(&self) -> Option<&str> {
116 match self {
117 Self::Message { content } => Some(content),
118 _ => None,
119 }
120 }
121
122 fn tool_call_info(&self) -> Option<(u32, Option<&str>, Option<&str>, Option<&str>)> {
123 match self {
124 Self::ToolCall { index, id, name, arguments } => {
125 Some((
126 *index,
127 id.as_deref(),
128 name.as_deref(),
129 arguments.as_deref(),
130 ))
131 },
132 _ => None,
133 }
134 }
135}
136