1use adk_core::{
2 Agent, Artifacts, CallbackContext, Content, InvocationContext as InvocationContextTrait,
3 Memory, ReadonlyContext, RunConfig,
4};
5use adk_session::{Session as AdkSession, State as AdkState};
6use async_trait::async_trait;
7use std::collections::HashMap;
8use std::sync::{atomic::AtomicBool, Arc};
9
10#[allow(dead_code)] struct StateAdapter<'a>(&'a dyn AdkState);
13
14impl<'a> adk_core::State for StateAdapter<'a> {
15 fn get(&self, key: &str) -> Option<serde_json::Value> {
16 self.0.get(key)
17 }
18
19 fn set(&mut self, _key: String, _value: serde_json::Value) {
20 panic!("Direct state mutation not supported in InvocationContext");
23 }
24
25 fn all(&self) -> HashMap<String, serde_json::Value> {
26 self.0.all()
27 }
28}
29
30struct SessionAdapter(Arc<dyn AdkSession>);
32
33impl adk_core::Session for SessionAdapter {
34 fn id(&self) -> &str {
35 self.0.id()
36 }
37
38 fn app_name(&self) -> &str {
39 self.0.app_name()
40 }
41
42 fn user_id(&self) -> &str {
43 self.0.user_id()
44 }
45
46 fn state(&self) -> &dyn adk_core::State {
47 unsafe { &*(self as *const Self as *const dyn adk_core::State) }
62 }
63
64 fn conversation_history(&self) -> Vec<adk_core::Content> {
65 let events = self.0.events();
67 let mut history = Vec::new();
68
69 for event in events.all() {
70 if let Some(content) = event.llm_response.content {
72 let role = match event.author.as_str() {
74 "user" => "user".to_string(),
75 _ => "model".to_string(),
76 };
77
78 let mut mapped_content = content;
80 mapped_content.role = role;
81 history.push(mapped_content);
82 }
83 }
84
85 history
86 }
87}
88
89impl adk_core::State for SessionAdapter {
90 fn get(&self, key: &str) -> Option<serde_json::Value> {
91 self.0.state().get(key)
92 }
93
94 fn set(&mut self, _key: String, _value: serde_json::Value) {
95 panic!("Direct state mutation not supported");
96 }
97
98 fn all(&self) -> HashMap<String, serde_json::Value> {
99 self.0.state().all()
100 }
101}
102
103pub struct InvocationContext {
104 invocation_id: String,
105 agent: Arc<dyn Agent>,
106 user_id: String,
107 app_name: String,
108 session_id: String,
109 branch: String,
110 user_content: Content,
111 artifacts: Option<Arc<dyn Artifacts>>,
112 memory: Option<Arc<dyn Memory>>,
113 run_config: RunConfig,
114 ended: Arc<AtomicBool>,
115 session: Arc<SessionAdapter>,
116}
117
118impl InvocationContext {
119 pub fn new(
120 invocation_id: String,
121 agent: Arc<dyn Agent>,
122 user_id: String,
123 app_name: String,
124 session_id: String,
125 user_content: Content,
126 session: Arc<dyn AdkSession>,
127 ) -> Self {
128 Self {
129 invocation_id,
130 agent,
131 user_id,
132 app_name,
133 session_id,
134 branch: String::new(),
135 user_content,
136 artifacts: None,
137 memory: None,
138 run_config: RunConfig::default(),
139 ended: Arc::new(AtomicBool::new(false)),
140 session: Arc::new(SessionAdapter(session)),
141 }
142 }
143
144 pub fn with_branch(mut self, branch: String) -> Self {
145 self.branch = branch;
146 self
147 }
148
149 pub fn with_artifacts(mut self, artifacts: Arc<dyn Artifacts>) -> Self {
150 self.artifacts = Some(artifacts);
151 self
152 }
153
154 pub fn with_memory(mut self, memory: Arc<dyn Memory>) -> Self {
155 self.memory = Some(memory);
156 self
157 }
158
159 pub fn with_run_config(mut self, config: RunConfig) -> Self {
160 self.run_config = config;
161 self
162 }
163}
164
165#[async_trait]
166impl ReadonlyContext for InvocationContext {
167 fn invocation_id(&self) -> &str {
168 &self.invocation_id
169 }
170
171 fn agent_name(&self) -> &str {
172 self.agent.name()
173 }
174
175 fn user_id(&self) -> &str {
176 &self.user_id
177 }
178
179 fn app_name(&self) -> &str {
180 &self.app_name
181 }
182
183 fn session_id(&self) -> &str {
184 &self.session_id
185 }
186
187 fn branch(&self) -> &str {
188 &self.branch
189 }
190
191 fn user_content(&self) -> &Content {
192 &self.user_content
193 }
194}
195
196#[async_trait]
197impl CallbackContext for InvocationContext {
198 fn artifacts(&self) -> Option<Arc<dyn Artifacts>> {
199 self.artifacts.clone()
200 }
201}
202
203#[async_trait]
204impl InvocationContextTrait for InvocationContext {
205 fn agent(&self) -> Arc<dyn Agent> {
206 self.agent.clone()
207 }
208
209 fn memory(&self) -> Option<Arc<dyn Memory>> {
210 self.memory.clone()
211 }
212
213 fn session(&self) -> &dyn adk_core::Session {
214 self.session.as_ref()
215 }
216
217 fn run_config(&self) -> &RunConfig {
218 &self.run_config
219 }
220
221 fn end_invocation(&self) {
222 self.ended.store(true, std::sync::atomic::Ordering::SeqCst);
223 }
224
225 fn ended(&self) -> bool {
226 self.ended.load(std::sync::atomic::Ordering::SeqCst)
227 }
228}