@@ -28,8 +28,8 @@ def mock_step(self):
2828
2929 def test_init (self , handler ):
3030 """Test handler initialization."""
31- assert handler ._step_stack == []
3231 assert handler ._event_id_to_step == {}
32+ assert handler ._parent_map == {}
3333
3434 @patch ('praisonaiui.integrations.llama_index.Step' )
3535 @patch ('asyncio.create_task' )
@@ -51,7 +51,6 @@ def test_on_event_start_query(self, mock_create_task, mock_step_class, handler,
5151 )
5252
5353 # Verify tracking
54- assert mock_step in handler ._step_stack
5554 assert handler ._event_id_to_step [event_id ] == mock_step
5655
5756 @patch ('praisonaiui.integrations.llama_index.Step' )
@@ -162,12 +161,15 @@ def test_on_event_start_unknown(self, mock_create_task, mock_step_class, handler
162161 metadata = {"event_type" : event_type , "payload" : payload }
163162 )
164163
164+ @patch ('asyncio.get_running_loop' )
165165 @patch ('asyncio.create_task' )
166- def test_on_event_end (self , mock_create_task , handler , mock_step ):
166+ def test_on_event_end (self , mock_create_task , mock_get_loop , handler , mock_step ):
167167 """Test event end handling."""
168+ # Mock that there's a running event loop
169+ mock_get_loop .return_value = MagicMock ()
170+
168171 event_id = "test_event_123"
169172 handler ._event_id_to_step [event_id ] = mock_step
170- handler ._step_stack .append (mock_step )
171173
172174 payload = {"response" : "Test response" }
173175 handler .on_event_end ("query" , payload , event_id )
@@ -176,15 +178,18 @@ def test_on_event_end(self, mock_create_task, handler, mock_step):
176178 mock_create_task .assert_called_once ()
177179
178180 # Verify cleanup
179- assert mock_step not in handler . _step_stack
181+ # Step should be removed from tracking maps
180182 assert event_id not in handler ._event_id_to_step
181183
184+ @patch ('asyncio.get_running_loop' )
182185 @patch ('asyncio.create_task' )
183- def test_on_event_error (self , mock_create_task , handler , mock_step ):
186+ def test_on_event_error (self , mock_create_task , mock_get_loop , handler , mock_step ):
184187 """Test event error handling."""
188+ # Mock that there's a running event loop
189+ mock_get_loop .return_value = MagicMock ()
190+
185191 event_id = "test_event_123"
186192 handler ._event_id_to_step [event_id ] = mock_step
187- handler ._step_stack .append (mock_step )
188193
189194 exception = ValueError ("Test error" )
190195 handler .on_event_error ("query" , exception , event_id )
@@ -193,7 +198,7 @@ def test_on_event_error(self, mock_create_task, handler, mock_step):
193198 mock_create_task .assert_called_once ()
194199
195200 # Verify cleanup
196- assert mock_step not in handler . _step_stack
201+ # Step should be removed from tracking maps
197202 assert event_id not in handler ._event_id_to_step
198203
199204 def test_start_trace_end_trace (self , handler ):
@@ -226,15 +231,14 @@ def test_on_query_end(self, mock_create_task, handler, mock_step):
226231 """Test query end convenience method."""
227232 event_id = "query_123"
228233 handler ._event_id_to_step [event_id ] = mock_step
229- handler ._step_stack .append (mock_step )
230234
231235 response = MagicMock ()
232236 response .__str__ = MagicMock (return_value = "AI is a field of computer science" )
233237
234238 handler .on_query_end (response , event_id = event_id )
235239
236240 # Verify cleanup
237- assert mock_step not in handler . _step_stack
241+ # Step should be removed from tracking maps
238242 assert event_id not in handler ._event_id_to_step
239243
240244 @patch ('praisonaiui.integrations.llama_index.Step' )
@@ -258,7 +262,6 @@ def test_on_retrieve_end(self, mock_create_task, handler, mock_step):
258262 """Test retrieval end convenience method."""
259263 event_id = "retrieve_123"
260264 handler ._event_id_to_step [event_id ] = mock_step
261- handler ._step_stack .append (mock_step )
262265
263266 # Mock nodes
264267 node1 = MagicMock ()
@@ -270,7 +273,7 @@ def test_on_retrieve_end(self, mock_create_task, handler, mock_step):
270273 handler .on_retrieve_end (nodes , event_id = event_id )
271274
272275 # Verify cleanup
273- assert mock_step not in handler . _step_stack
276+ # Step should be removed from tracking maps
274277 assert event_id not in handler ._event_id_to_step
275278
276279 @patch ('praisonaiui.integrations.llama_index.Step' )
@@ -289,9 +292,13 @@ def test_on_llm_start(self, mock_create_task, mock_step_class, handler, mock_ste
289292 metadata = {"event_type" : "llm" , "payload" : {"messages" : messages }}
290293 )
291294
295+ @patch ('asyncio.get_running_loop' )
292296 @patch ('asyncio.create_task' )
293- def test_on_llm_new_token (self , mock_create_task , handler , mock_step ):
297+ def test_on_llm_new_token (self , mock_create_task , mock_get_loop , handler , mock_step ):
294298 """Test LLM token streaming."""
299+ # Mock that there's a running event loop
300+ mock_get_loop .return_value = MagicMock ()
301+
295302 event_id = "llm_123"
296303 handler ._event_id_to_step [event_id ] = mock_step
297304
@@ -306,13 +313,12 @@ def test_on_llm_end(self, mock_create_task, handler, mock_step):
306313 """Test LLM end convenience method."""
307314 event_id = "llm_123"
308315 handler ._event_id_to_step [event_id ] = mock_step
309- handler ._step_stack .append (mock_step )
310316
311317 response = "Python is a programming language"
312318 handler .on_llm_end (response , event_id = event_id )
313319
314320 # Verify cleanup
315- assert mock_step not in handler . _step_stack
321+ # Step should be removed from tracking maps
316322 assert event_id not in handler ._event_id_to_step
317323
318324 def test_no_event_loop_handling (self , handler , mock_step ):
@@ -323,13 +329,11 @@ def test_no_event_loop_handling(self, handler, mock_step):
323329
324330 event_id = "test_event_123"
325331 handler ._event_id_to_step [event_id ] = mock_step
326- handler ._step_stack .append (mock_step )
327332
328333 # Should not raise exception
329334 handler .on_event_end ("query" , {}, event_id )
330335
331336 # Cleanup should still happen
332- assert mock_step not in handler ._step_stack
333337 assert event_id not in handler ._event_id_to_step
334338
335339 def test_missing_event_id (self , handler ):
@@ -339,7 +343,7 @@ def test_missing_event_id(self, handler):
339343 handler .on_event_error ("query" , Exception ("test" ), event_id = None )
340344 handler .on_llm_new_token ("token" , event_id = None )
341345
342- assert len (handler ._step_stack ) == 0
346+ assert len (handler ._event_id_to_step ) == 0
343347 assert len (handler ._event_id_to_step ) == 0
344348
345349 def test_unknown_event_id (self , handler ):
@@ -349,7 +353,7 @@ def test_unknown_event_id(self, handler):
349353 handler .on_event_error ("query" , Exception ("test" ), event_id = "unknown_123" )
350354 handler .on_llm_new_token ("token" , event_id = "unknown_123" )
351355
352- assert len (handler ._step_stack ) == 0
356+ assert len (handler ._event_id_to_step ) == 0
353357 assert len (handler ._event_id_to_step ) == 0
354358
355359 @patch ('praisonaiui.integrations.llama_index.Step' )
@@ -365,8 +369,8 @@ def test_nested_events(self, mock_create_task, mock_step_class, handler):
365369 # Start parent query
366370 parent_id = handler .on_event_start ("query" , {"query" : "test" })
367371
368- # Start nested retrieval
369- child_id = handler .on_event_start ("retrieve" , {"query" : "test" })
372+ # Start nested retrieval with parent_id
373+ child_id = handler .on_event_start ("retrieve" , {"query" : "test" }, parent_id = parent_id )
370374
371375 # Verify child step was created with parent
372376 assert mock_step_class .call_count == 2
0 commit comments