============================= test session starts ============================= platform win32 -- Python 3.11.6, pytest-9.0.2, pluggy-1.6.0 rootdir: C:\projects\manual_slop configfile: pyproject.toml plugins: anyio-4.12.1 collected 113 items tests\conductor\test_infrastructure.py .... [ 3%] tests\test_agent_capabilities.py . [ 4%] tests\test_agent_tools_wiring.py .. [ 6%] tests\test_ai_client_cli.py . [ 7%] tests\test_ai_context_history.py . [ 7%] tests\test_api_events.py .... [ 11%] tests\test_api_hook_client.py ...... [ 16%] tests\test_api_hook_extensions.py ..... [ 21%] tests\test_cli_tool_bridge.py .FF [ 23%] tests\test_conductor_api_hook_integration.py ... [ 26%] tests\test_extended_sims.py .... [ 30%] tests\test_gemini_cli_adapter.py .... [ 33%] tests\test_gemini_cli_integration.py FF [ 35%] tests\test_gemini_metrics.py . [ 36%] tests\test_gui2_events.py . [ 37%] tests\test_gui2_layout.py .. [ 38%] tests\test_gui2_mcp.py . [ 39%] tests\test_gui2_parity.py ... [ 42%] tests\test_gui2_performance.py .s [ 44%] tests\test_gui_diagnostics.py .. [ 46%] tests\test_gui_events.py . [ 46%] tests\test_gui_performance_requirements.py . [ 47%] tests\test_gui_stress_performance.py . [ 48%] tests\test_gui_updates.py .. [ 50%] tests\test_headless_api.py ......... [ 58%] tests\test_headless_dependencies.py .. [ 60%] tests\test_headless_startup.py .. [ 61%] tests\test_history_blacklist.py .. [ 63%] tests\test_history_bleed.py F ================================== FAILURES =================================== ____________________ TestCliToolBridge.test_deny_decision _____________________ self = mock_request = mock_stdout = <_io.StringIO object at 0x00000271259C3B50> mock_stdin = <_io.StringIO object at 0x0000027158FFF2E0> @patch('sys.stdin', new_callable=io.StringIO) @patch('sys.stdout', new_callable=io.StringIO) @patch('api_hook_client.ApiHookClient.request_confirmation') def test_deny_decision(self, mock_request, mock_stdout, mock_stdin): # Mock stdin mock_stdin.write(json.dumps(self.tool_call)) mock_stdin.seek(0) # 4. Mock ApiHookClient to return denied mock_request.return_value = {'approved': False} main() # Assert deny output = json.loads(mock_stdout.getvalue().strip()) > self.assertEqual(output.get('decision'), 'deny') E AssertionError: 'allow' != 'deny' E - allow E + deny tests\test_cli_tool_bridge.py:54: AssertionError _______________ TestCliToolBridge.test_unreachable_hook_server ________________ self = mock_request = mock_stdout = <_io.StringIO object at 0x0000027158FFF1C0> mock_stdin = <_io.StringIO object at 0x00000271593A0A60> @patch('sys.stdin', new_callable=io.StringIO) @patch('sys.stdout', new_callable=io.StringIO) @patch('api_hook_client.ApiHookClient.request_confirmation') def test_unreachable_hook_server(self, mock_request, mock_stdout, mock_stdin): # Mock stdin mock_stdin.write(json.dumps(self.tool_call)) mock_stdin.seek(0) # 5. Test case where hook server is unreachable (exception) mock_request.side_effect = Exception("Connection refused") main() # Assert deny on error output = json.loads(mock_stdout.getvalue().strip()) > self.assertEqual(output.get('decision'), 'deny') E AssertionError: 'allow' != 'deny' E - allow E + deny tests\test_cli_tool_bridge.py:71: AssertionError ______________________ test_gemini_cli_full_integration _______________________ live_gui = (, 'gui_2.py') def test_gemini_cli_full_integration(live_gui): """ Integration test for the Gemini CLI provider and tool bridge. """ client = ApiHookClient("http://127.0.0.1:8999") # 1. Setup paths and configure the GUI mock_script = os.path.abspath("tests/mock_gemini_cli.py") # Wrap in quotes for shell execution if path has spaces cli_cmd = f'"{sys.executable}" "{mock_script}"' # Set provider and binary path via GUI hooks # Note: Using set_value which now triggers the property setter in gui_2.py print(f"[TEST] Setting current_provider to gemini_cli") client.set_value("current_provider", "gemini_cli") print(f"[TEST] Setting gcli_path to {cli_cmd}") client.set_value("gcli_path", cli_cmd) # Verify settings were applied assert client.get_value("current_provider") == "gemini_cli" assert client.get_value("gcli_path") == cli_cmd # Clear events client.get_events() # 2. Trigger a message in the GUI print("[TEST] Sending user message...") client.set_value("ai_input", "Please read test.txt") client.click("btn_gen_send") # 3. Monitor for the 'ask_received' event print("[TEST] Waiting for ask_received event...") request_id = None timeout = 30 start_time = time.time() while time.time() - start_time < timeout: events = client.get_events() if events: print(f"[TEST] Received {len(events)} events: {[e.get('type') for e in events]}") for ev in events: if ev.get("type") == "ask_received": request_id = ev.get("request_id") print(f"[TEST] Found request_id: {request_id}") break if request_id: break time.sleep(0.5) assert request_id is not None, "Timed out waiting for 'ask_received' event from the bridge" # 4. Respond to the permission request print("[TEST] Responding to ask with approval") resp = requests.post( "http://127.0.0.1:8999/api/ask/respond", json={ "request_id": request_id, "response": {"approved": True} } ) assert resp.status_code == 200 # 5. Verify that the final response is displayed in the GUI print("[TEST] Waiting for final message in history...") final_message_received = False start_time = time.time() while time.time() - start_time < timeout: session = client.get_session() entries = session.get("session", {}).get("entries", []) for entry in entries: content = entry.get("content", "") if "Hello from mock!" in content: print(f"[TEST] Success! Found message: {content[:50]}...") final_message_received = True break if final_message_received: break time.sleep(1.0) > assert final_message_received, "Final message from mock CLI was not found in the GUI history" E AssertionError: Final message from mock CLI was not found in the GUI history E assert False tests\test_gemini_cli_integration.py:86: AssertionError ---------------------------- Captured stdout call ----------------------------- [TEST] Setting current_provider to gemini_cli [TEST] Setting gcli_path to "C:\projects\manual_slop\.venv\Scripts\python.exe" "C:\projects\manual_slop\tests\mock_gemini_cli.py" [TEST] Sending user message... [TEST] Waiting for ask_received event... [TEST] Received 1 events: ['ask_received'] [TEST] Found request_id: e24686e7-274a-4cd0-a8a4-dc026d322dc9 [TEST] Responding to ask with approval [TEST] Waiting for final message in history... ____________________ test_gemini_cli_rejection_and_history ____________________ live_gui = (, 'gui_2.py') def test_gemini_cli_rejection_and_history(live_gui): """ Integration test for the Gemini CLI provider: Rejection flow and history. """ client = ApiHookClient("http://127.0.0.1:8999") # 1. Setup paths and configure the GUI mock_script = os.path.abspath("tests/mock_gemini_cli.py") cli_cmd = f'"{sys.executable}" "{mock_script}"' client.set_value("current_provider", "gemini_cli") client.set_value("gcli_path", cli_cmd) # 2. Trigger a message that will be denied print("[TEST] Sending user message (to be denied)...") client.set_value("ai_input", "Deny me") client.click("btn_gen_send") # 3. Wait for 'ask_received' and respond with rejection request_id = None timeout = 15 start_time = time.time() while time.time() - start_time < timeout: for ev in client.get_events(): if ev.get("type") == "ask_received": request_id = ev.get("request_id") break if request_id: break time.sleep(0.5) assert request_id is not None print("[TEST] Responding to ask with REJECTION") requests.post("http://127.0.0.1:8999/api/ask/respond", json={"request_id": request_id, "response": {"approved": False}}) # 4. Verify rejection message in history print("[TEST] Waiting for rejection message in history...") rejection_found = False start_time = time.time() while time.time() - start_time < timeout: session = client.get_session() entries = session.get("session", {}).get("entries", []) for entry in entries: if "Tool execution was denied. Decision: deny" in entry.get("content", ""): rejection_found = True break if rejection_found: break time.sleep(1.0) > assert rejection_found, "Rejection message not found in history" E AssertionError: Rejection message not found in history E assert False tests\test_gemini_cli_integration.py:138: AssertionError ---------------------------- Captured stdout call ----------------------------- [TEST] Sending user message (to be denied)... [TEST] Responding to ask with REJECTION [TEST] Waiting for rejection message in history... _____________________ test_get_history_bleed_stats_basic ______________________ def test_get_history_bleed_stats_basic(): # Reset state ai_client.reset_session() # Mock some history ai_client.history_trunc_limit = 1000 # Simulate 500 tokens used with MagicMock() as mock_stats: # This would usually involve patching the encoder or session logic pass stats = ai_client.get_history_bleed_stats() assert 'current' in stats assert 'limit' in stats # ai_client.py hardcodes Gemini limit to 900_000 > assert stats['limit'] == 900000 E assert 0 == 900000 tests\test_history_bleed.py:26: AssertionError -------------------------- Captured stdout teardown --------------------------- [Fixture] Finally block triggered: Shutting down gui_2.py... [Fixture] Attempting to kill process tree for PID 5788... [Fixture] Process tree 5788 killed. =========================== short test summary info =========================== FAILED tests/test_cli_tool_bridge.py::TestCliToolBridge::test_deny_decision - AssertionError: 'allow' != 'deny' - allow + deny FAILED tests/test_cli_tool_bridge.py::TestCliToolBridge::test_unreachable_hook_server - AssertionError: 'allow' != 'deny' - allow + deny FAILED tests/test_gemini_cli_integration.py::test_gemini_cli_full_integration - AssertionError: Final message from mock CLI was not found in the GUI history assert False FAILED tests/test_gemini_cli_integration.py::test_gemini_cli_rejection_and_history - AssertionError: Rejection message not found in history assert False FAILED tests/test_history_bleed.py::test_get_history_bleed_stats_basic - assert 0 == 900000 !!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 5 failures !!!!!!!!!!!!!!!!!!!!!!!!!! ============= 5 failed, 67 passed, 1 skipped in 163.79s (0:02:43) =============