plexus_substrate/activations/orcha/
context.rs1use crate::activations::arbor::{ArborStorage, NodeId, TreeId};
7use std::sync::Arc;
8use tokio::sync::Mutex;
9
10pub struct OrchaContext {
12 arbor: Arc<ArborStorage>,
13 tree_id: TreeId,
14 session_id: String,
15 last_node_id: Mutex<Option<NodeId>>,
16}
17
18impl OrchaContext {
19 pub async fn new(
21 arbor: Arc<ArborStorage>,
22 session_id: String,
23 task: String,
24 model: String,
25 ) -> Result<Self, String> {
26 let tree_id = arbor
28 .tree_create(
29 Some(serde_json::json!({
30 "session_id": session_id.clone(),
31 "task": task.clone(),
32 "model": model.clone(),
33 })),
34 "orcha",
35 )
36 .await
37 .map_err(|e| format!("Failed to create arbor tree: {}", e))?;
38
39 let ctx = Self {
40 arbor,
41 tree_id,
42 session_id: session_id.clone(),
43 last_node_id: Mutex::new(None),
44 };
45
46 ctx.write_node(
48 format!(
49 "session_started: {}\ntask: {}\nmodel: {}",
50 session_id, task, model
51 ),
52 serde_json::json!({
53 "event": "session_started",
54 "session_id": session_id,
55 }),
56 )
57 .await;
58
59 Ok(ctx)
60 }
61
62 pub fn tree_id(&self) -> String {
64 self.tree_id.to_string()
65 }
66
67 async fn write_node(&self, content: String, metadata: serde_json::Value) {
69 let parent = *self.last_node_id.lock().await;
70 match self
71 .arbor
72 .node_create_text(&self.tree_id, parent, content, Some(metadata))
73 .await
74 {
75 Ok(node_id) => {
76 *self.last_node_id.lock().await = Some(node_id);
77 }
78 Err(e) => {
79 tracing::warn!("Failed to write arbor node: {}", e);
80 }
81 }
82 }
83
84 pub async fn claude_session_created(&self, claude_session_id: String, session_name: String) {
86 self.write_node(
87 format!(
88 "claude_session_created: {}\nsession_name: {}",
89 claude_session_id, session_name
90 ),
91 serde_json::json!({
92 "event": "claude_session_started",
93 "claude_session_id": claude_session_id,
94 "session_name": session_name,
95 }),
96 )
97 .await;
98 }
99
100 pub async fn prompt_created(&self, prompt: String, retry_count: u32) {
102 self.write_node(
103 format!("prompt_created (retry {}):\n{}", retry_count, prompt),
104 serde_json::json!({
105 "event": "prompt_created",
106 "prompt": prompt,
107 "retry_count": retry_count,
108 }),
109 )
110 .await;
111 }
112
113 pub async fn claude_session_complete(&self, claude_session_id: String) {
115 self.write_node(
116 format!("claude_session_complete: {}", claude_session_id),
117 serde_json::json!({
118 "event": "claude_session_complete",
119 "claude_session_id": claude_session_id,
120 }),
121 )
122 .await;
123 }
124
125 pub async fn validation_started(&self, test_command: String, cwd: String) {
127 self.write_node(
128 format!("validation_started:\n{}", test_command),
129 serde_json::json!({
130 "event": "validation_started",
131 "test_command": test_command,
132 "cwd": cwd,
133 }),
134 )
135 .await;
136 }
137
138 pub async fn validation_result(&self, success: bool, output: String) {
140 self.write_node(
141 format!(
142 "validation_result: {}\noutput:\n{}",
143 if success { "SUCCESS" } else { "FAILED" },
144 output
145 ),
146 serde_json::json!({
147 "event": "validation_result",
148 "success": success,
149 "output": output,
150 }),
151 )
152 .await;
153 }
154
155 pub async fn session_complete(&self, status: &str) {
157 self.write_node(
158 format!("session_complete: {} status={}", self.session_id, status),
159 serde_json::json!({
160 "event": "session_complete",
161 "status": status,
162 }),
163 )
164 .await;
165 }
166
167 pub async fn tool_use(&self, tool_name: String, tool_use_id: String, input: String) {
169 self.write_node(
170 format!(
171 "tool_use: {}\nid: {}\ninput:\n{}",
172 tool_name, tool_use_id, input
173 ),
174 serde_json::json!({
175 "event": "tool_use",
176 "tool_name": tool_name,
177 "tool_use_id": tool_use_id,
178 "input": input,
179 }),
180 )
181 .await;
182 }
183
184 pub async fn tool_result(&self, tool_use_id: String, output: String, is_error: bool) {
186 self.write_node(
187 format!(
188 "tool_result for {}: {}\n{}",
189 tool_use_id,
190 if is_error { "ERROR" } else { "SUCCESS" },
191 output
192 ),
193 serde_json::json!({
194 "event": "tool_result",
195 "tool_use_id": tool_use_id,
196 "output": output,
197 "is_error": is_error,
198 }),
199 )
200 .await;
201 }
202
203 pub async fn claude_output(&self, text: String) {
205 self.write_node(
206 format!("claude_output:\n{}", text),
207 serde_json::json!({
208 "event": "claude_output",
209 "text": text,
210 }),
211 )
212 .await;
213 }
214}