1use std::path::PathBuf;
2use std::sync::{Arc, Mutex};
3
4use crate::model::ModelRef;
5use crate::types::Metadata;
6
7#[derive(Clone, Default)]
8pub struct RunContext {
9 pub run_id: String,
10 pub agent_name: String,
11 pub model: Option<ModelRef>,
12 pub workspace: Option<PathBuf>,
13 pub metadata: Metadata,
14 pub app_state: Option<Arc<dyn std::any::Any + Send + Sync>>,
15}
16
17impl RunContext {
18 pub fn app_state<T: Send + Sync + 'static>(&self) -> Option<&T> {
19 self.app_state.as_ref()?.downcast_ref::<T>()
20 }
21}
22
23#[derive(Clone)]
24pub struct ToolCallContext {
25 pub run: RunContext,
26 pub tool_call_id: String,
27 pub tool_name: String,
28 pub raw_arguments: serde_json::Value,
29 pub idempotency_key: Option<String>,
30 pub metadata: Metadata,
31 pub app_state: Option<Arc<dyn std::any::Any + Send + Sync>>,
32 pub shared_state: Arc<Mutex<Metadata>>,
33}
34
35impl ToolCallContext {
36 pub fn app_state<T: Send + Sync + 'static>(&self) -> Option<&T> {
37 self.app_state.as_ref()?.downcast_ref::<T>()
38 }
39
40 pub fn shared_state_snapshot(&self) -> Metadata {
41 self.shared_state
42 .lock()
43 .unwrap_or_else(std::sync::PoisonError::into_inner)
44 .clone()
45 }
46
47 pub fn shared_state_value(&self, key: &str) -> Option<serde_json::Value> {
48 self.shared_state
49 .lock()
50 .unwrap_or_else(std::sync::PoisonError::into_inner)
51 .get(key)
52 .cloned()
53 }
54
55 pub fn set_shared_state_value(
56 &self,
57 key: impl Into<String>,
58 value: serde_json::Value,
59 ) -> Option<serde_json::Value> {
60 self.shared_state
61 .lock()
62 .unwrap_or_else(std::sync::PoisonError::into_inner)
63 .insert(key.into(), value)
64 }
65
66 pub fn remove_shared_state_value(&self, key: &str) -> Option<serde_json::Value> {
67 self.shared_state
68 .lock()
69 .unwrap_or_else(std::sync::PoisonError::into_inner)
70 .remove(key)
71 }
72}