#!/usr/bin/env python3 """ Test script to verify that LLMGeneratedTextFrame signaling works correctly with the new local variable approach. """ def test_local_variable_logic(): """Test the core logic using the same pattern as the implementation""" print("=== Testing Local Variable Logic ===") # Simulate the logic from _process_context text_generation_signaled = False frames_sent = [] # Simulate chunks with text content chunks_with_content = ["Hello", " world", "!"] for content in chunks_with_content: # This is the exact logic from our implementation if content: # equivalent to chunk.choices[0].delta.content if not text_generation_signaled: frames_sent.append("LLMGeneratedTextFrame") text_generation_signaled = True frames_sent.append(f"LLMTextFrame({content})") print(f"Frames sent: {frames_sent}") # Verify behavior generated_signals = [f for f in frames_sent if f == "LLMGeneratedTextFrame"] text_frames = [f for f in frames_sent if f.startswith("LLMTextFrame")] assert len(generated_signals) == 1, ( f"Expected 1 signal, got {len(generated_signals)}" ) assert len(text_frames) == 3, f"Expected 3 text frames, got {len(text_frames)}" assert frames_sent[0] == "LLMGeneratedTextFrame", "Signal should be first" print("✅ Local variable logic works correctly") return True def test_no_text_logic(): """Test that no signal is sent when there's no text""" print("\n=== Testing No Text Logic ===") text_generation_signaled = False frames_sent = [] # Simulate chunks with no text content (function calls only) chunks_with_content = [None, None, None] # No text content for content in chunks_with_content: if content: # This will be False for all chunks if not text_generation_signaled: frames_sent.append("LLMGeneratedTextFrame") text_generation_signaled = True frames_sent.append(f"LLMTextFrame({content})") print(f"Frames sent: {frames_sent}") assert len(frames_sent) == 0, f"Expected no frames, got {frames_sent}" print("✅ No signal sent when no text content") return True def test_mixed_content_logic(): """Test behavior with mixed function calls and text""" print("\n=== Testing Mixed Content Logic ===") text_generation_signaled = False frames_sent = [] # Simulate chunks: function call, text, function call, text chunks = [ {"type": "function", "content": None}, {"type": "text", "content": "Hello"}, {"type": "function", "content": None}, {"type": "text", "content": " world"}, ] for chunk in chunks: if chunk["type"] == "function": frames_sent.append("FunctionCallFrame") elif chunk["content"]: # text content if not text_generation_signaled: frames_sent.append("LLMGeneratedTextFrame") text_generation_signaled = True frames_sent.append(f"LLMTextFrame({chunk['content']})") print(f"Frames sent: {frames_sent}") generated_signals = [f for f in frames_sent if f == "LLMGeneratedTextFrame"] assert len(generated_signals) == 1, ( f"Expected 1 signal, got {len(generated_signals)}" ) # Signal should come before first text frame but after any function frames signal_index = frames_sent.index("LLMGeneratedTextFrame") first_text_index = next( i for i, f in enumerate(frames_sent) if f.startswith("LLMTextFrame") ) assert signal_index == first_text_index - 1, ( "Signal should come right before first text" ) print("✅ Mixed content logic works correctly") return True def main(): try: test1_result = test_local_variable_logic() test2_result = test_no_text_logic() test3_result = test_mixed_content_logic() print(f"\n=== Test Results ===") print(f"Local variable test: {'✅ PASS' if test1_result else '❌ FAIL'}") print(f"No text test: {'✅ PASS' if test2_result else '❌ FAIL'}") print(f"Mixed content test: {'✅ PASS' if test3_result else '❌ FAIL'}") if test1_result and test2_result and test3_result: print("\n🎉 All LLMGeneratedTextFrame signaling logic tests passed!") print( "✅ Implementation correctly signals text generation once, as early as possible" ) else: print("\n❌ Some tests failed.") except Exception as e: print(f"❌ Test failed with error: {e}") import traceback traceback.print_exc() if __name__ == "__main__": main()