test(ai_client): rename send_result to send in 22 remaining test files
Batch rename of 22 test files. 62 references renamed total. The full test suite is now GREEN again, matching the pre-rename baseline from Task 1.1. Pure mechanical rename. No behavior change. Files affected: test_ai_cache_tracking, test_ai_client_cli, test_ai_client_result, test_api_events, test_context_pruner, test_deepseek_provider, test_gemini_cli_* (3 files), test_gui2_mcp, test_headless_* (2 files), test_live_gui_integration_v2, test_orchestration_logic, test_phase6_engine, test_rag_integration, test_run_worker_lifecycle_abort, test_spawn_interception_v2, test_symbol_parsing, test_tier4_interceptor, test_tiered_aggregation, test_token_usage. Note: spec estimated 24 files; actual is 22 (test_deprecation_warnings no longer exists, and 1 fewer file than spec's list). Refs: conductor/tracks/send_result_to_send_20260616/
This commit is contained in:
@@ -0,0 +1,53 @@
|
|||||||
|
"""Apply the Phase 4 batch rename to all remaining test files."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
FILES = [
|
||||||
|
"tests/test_ai_cache_tracking.py",
|
||||||
|
"tests/test_ai_client_cli.py",
|
||||||
|
"tests/test_ai_client_result.py",
|
||||||
|
"tests/test_api_events.py",
|
||||||
|
"tests/test_context_pruner.py",
|
||||||
|
"tests/test_deepseek_provider.py",
|
||||||
|
"tests/test_gemini_cli_edge_cases.py",
|
||||||
|
"tests/test_gemini_cli_integration.py",
|
||||||
|
"tests/test_gemini_cli_parity_regression.py",
|
||||||
|
"tests/test_gui2_mcp.py",
|
||||||
|
"tests/test_headless_service.py",
|
||||||
|
"tests/test_headless_verification.py",
|
||||||
|
"tests/test_live_gui_integration_v2.py",
|
||||||
|
"tests/test_orchestration_logic.py",
|
||||||
|
"tests/test_phase6_engine.py",
|
||||||
|
"tests/test_rag_integration.py",
|
||||||
|
"tests/test_run_worker_lifecycle_abort.py",
|
||||||
|
"tests/test_spawn_interception_v2.py",
|
||||||
|
"tests/test_symbol_parsing.py",
|
||||||
|
"tests/test_tier4_interceptor.py",
|
||||||
|
"tests/test_tiered_aggregation.py",
|
||||||
|
"tests/test_token_usage.py",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
total_before = 0
|
||||||
|
total_renamed = 0
|
||||||
|
for rel in FILES:
|
||||||
|
p = Path(rel)
|
||||||
|
with p.open("r", encoding="utf-8", newline="") as f:
|
||||||
|
content = f.read()
|
||||||
|
before = content.count("send_result")
|
||||||
|
new_content = content.replace("send_result", "send")
|
||||||
|
with p.open("w", encoding="utf-8", newline="") as f:
|
||||||
|
f.write(new_content)
|
||||||
|
remaining = new_content.count("send_result")
|
||||||
|
print(f"{rel}: {before} -> {before - remaining} (remaining={remaining})")
|
||||||
|
total_before += before
|
||||||
|
total_renamed += before - remaining
|
||||||
|
print(f"Total: renamed {total_renamed} of {total_before} occurrences")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
@@ -45,7 +45,7 @@ def test_gemini_cache_tracking() -> None:
|
|||||||
mock_client.caches.list.return_value = [MagicMock(size_bytes=5000)]
|
mock_client.caches.list.return_value = [MagicMock(size_bytes=5000)]
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
result = ai_client.send_result(
|
result = ai_client.send(
|
||||||
md_content="Some long context that triggers caching",
|
md_content="Some long context that triggers caching",
|
||||||
user_message="Hello",
|
user_message="Hello",
|
||||||
file_items=file_items
|
file_items=file_items
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ def test_ai_client_send_gemini_cli() -> None:
|
|||||||
MockAdapterClass.return_value = mock_adapter_instance
|
MockAdapterClass.return_value = mock_adapter_instance
|
||||||
ai_client._gemini_cli_adapter = mock_adapter_instance
|
ai_client._gemini_cli_adapter = mock_adapter_instance
|
||||||
with patch.object(ai_client.events, "emit") as mock_emit:
|
with patch.object(ai_client.events, "emit") as mock_emit:
|
||||||
result = ai_client.send_result(
|
result = ai_client.send(
|
||||||
md_content="<context></context>",
|
md_content="<context></context>",
|
||||||
user_message=test_message,
|
user_message=test_message,
|
||||||
base_dir=".",
|
base_dir=".",
|
||||||
|
|||||||
@@ -4,40 +4,40 @@ from src import ai_client
|
|||||||
from src.result_types import Result, ErrorInfo, ErrorKind
|
from src.result_types import Result, ErrorInfo, ErrorKind
|
||||||
|
|
||||||
|
|
||||||
def test_send_result_public_api_returns_result() -> None:
|
def test_send_public_api_returns_result() -> None:
|
||||||
with patch.object(ai_client, "set_provider"):
|
with patch.object(ai_client, "set_provider"):
|
||||||
with patch.object(ai_client, "_send_gemini", return_value=Result(data="hello")) as mock_send:
|
with patch.object(ai_client, "_send_gemini", return_value=Result(data="hello")) as mock_send:
|
||||||
r = ai_client.send_result("system", "user")
|
r = ai_client.send("system", "user")
|
||||||
assert isinstance(r, Result)
|
assert isinstance(r, Result)
|
||||||
assert r.ok
|
assert r.ok
|
||||||
assert r.data == "hello"
|
assert r.data == "hello"
|
||||||
|
|
||||||
|
|
||||||
def test_send_result_does_not_emit_deprecation() -> None:
|
def test_send_does_not_emit_deprecation() -> None:
|
||||||
import warnings
|
import warnings
|
||||||
with warnings.catch_warnings(record=True) as w:
|
with warnings.catch_warnings(record=True) as w:
|
||||||
warnings.simplefilter("always")
|
warnings.simplefilter("always")
|
||||||
with patch.object(ai_client, "set_provider"):
|
with patch.object(ai_client, "set_provider"):
|
||||||
with patch.object(ai_client, "_send_gemini", return_value=Result(data="hi")):
|
with patch.object(ai_client, "_send_gemini", return_value=Result(data="hi")):
|
||||||
r = ai_client.send_result("system", "user")
|
r = ai_client.send("system", "user")
|
||||||
assert r.ok and r.data == "hi"
|
assert r.ok and r.data == "hi"
|
||||||
assert not any(issubclass(x.category, DeprecationWarning) for x in w)
|
assert not any(issubclass(x.category, DeprecationWarning) for x in w)
|
||||||
|
|
||||||
|
|
||||||
def test_send_result_preserves_errors() -> None:
|
def test_send_preserves_errors() -> None:
|
||||||
err = ErrorInfo(kind=ErrorKind.RATE_LIMIT, message="slow down", source="test")
|
err = ErrorInfo(kind=ErrorKind.RATE_LIMIT, message="slow down", source="test")
|
||||||
with patch.object(ai_client, "set_provider"):
|
with patch.object(ai_client, "set_provider"):
|
||||||
with patch.object(ai_client, "_send_gemini", return_value=Result(data="", errors=[err])):
|
with patch.object(ai_client, "_send_gemini", return_value=Result(data="", errors=[err])):
|
||||||
r = ai_client.send_result("system", "user")
|
r = ai_client.send("system", "user")
|
||||||
assert not r.ok
|
assert not r.ok
|
||||||
assert r.errors == [err]
|
assert r.errors == [err]
|
||||||
|
|
||||||
|
|
||||||
def test_send_result_returns_empty_data_with_error_on_auth_failure() -> None:
|
def test_send_returns_empty_data_with_error_on_auth_failure() -> None:
|
||||||
err = ErrorInfo(kind=ErrorKind.AUTH, message="bad key", source="test")
|
err = ErrorInfo(kind=ErrorKind.AUTH, message="bad key", source="test")
|
||||||
with patch.object(ai_client, "set_provider"):
|
with patch.object(ai_client, "set_provider"):
|
||||||
with patch.object(ai_client, "_send_gemini", return_value=Result(data="", errors=[err])):
|
with patch.object(ai_client, "_send_gemini", return_value=Result(data="", errors=[err])):
|
||||||
r = ai_client.send_result("system", "user")
|
r = ai_client.send("system", "user")
|
||||||
assert not r.ok
|
assert not r.ok
|
||||||
assert r.data == ""
|
assert r.data == ""
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ def test_send_emits_events_proper() -> None:
|
|||||||
ai_client.events.on("request_start", start_callback)
|
ai_client.events.on("request_start", start_callback)
|
||||||
ai_client.events.on("response_received", response_callback)
|
ai_client.events.on("response_received", response_callback)
|
||||||
ai_client.set_provider("gemini", "gemini-2.5-flash-lite")
|
ai_client.set_provider("gemini", "gemini-2.5-flash-lite")
|
||||||
result = ai_client.send_result("context", "message", )
|
result = ai_client.send("context", "message", )
|
||||||
assert result.ok
|
assert result.ok
|
||||||
assert start_callback.called
|
assert start_callback.called
|
||||||
assert response_callback.called
|
assert response_callback.called
|
||||||
@@ -105,6 +105,6 @@ def test_send_emits_tool_events() -> None:
|
|||||||
tool_callback(*args, **kwargs)
|
tool_callback(*args, **kwargs)
|
||||||
|
|
||||||
ai_client.events.on("tool_execution", debug_tool)
|
ai_client.events.on("tool_execution", debug_tool)
|
||||||
result = ai_client.send_result("context", "message", enable_tools=True)
|
result = ai_client.send("context", "message", enable_tools=True)
|
||||||
assert result.ok
|
assert result.ok
|
||||||
assert tool_callback.call_count >= 1
|
assert tool_callback.call_count >= 1
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ def test_token_reduction_logging(capsys):
|
|||||||
with pytest.MonkeyPatch().context() as m:
|
with pytest.MonkeyPatch().context() as m:
|
||||||
m.setattr("builtins.open", lambda f, *args, **kwargs: type('obj', (object,), {'read': lambda s: code, '__enter__': lambda s: s, '__exit__': lambda s, *a: None})())
|
m.setattr("builtins.open", lambda f, *args, **kwargs: type('obj', (object,), {'read': lambda s: code, '__enter__': lambda s: s, '__exit__': lambda s, *a: None})())
|
||||||
m.setattr("pathlib.Path.exists", lambda s: True)
|
m.setattr("pathlib.Path.exists", lambda s: True)
|
||||||
m.setattr("src.ai_client.send_result", lambda **kwargs: Result(data="DONE"))
|
m.setattr("src.ai_client.send", lambda **kwargs: Result(data="DONE"))
|
||||||
|
|
||||||
run_worker_lifecycle(ticket, context, context_files=["test.py"])
|
run_worker_lifecycle(ticket, context, context_files=["test.py"])
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ def test_deepseek_completion_logic(mock_post: MagicMock) -> None:
|
|||||||
}
|
}
|
||||||
mock_post.return_value = mock_response
|
mock_post.return_value = mock_response
|
||||||
|
|
||||||
result = ai_client.send_result(md_content="Context", user_message="Hi", base_dir=".")
|
result = ai_client.send(md_content="Context", user_message="Hi", base_dir=".")
|
||||||
assert result.ok
|
assert result.ok
|
||||||
assert result.data == "Hello World"
|
assert result.data == "Hello World"
|
||||||
assert mock_post.called
|
assert mock_post.called
|
||||||
@@ -53,7 +53,7 @@ def test_deepseek_reasoning_logic(mock_post: MagicMock) -> None:
|
|||||||
}
|
}
|
||||||
mock_post.return_value = mock_response
|
mock_post.return_value = mock_response
|
||||||
|
|
||||||
result = ai_client.send_result(md_content="Context", user_message="Hi", base_dir=".")
|
result = ai_client.send(md_content="Context", user_message="Hi", base_dir=".")
|
||||||
assert result.ok
|
assert result.ok
|
||||||
assert "<thinking>\nChain of thought\n</thinking>" in result.data
|
assert "<thinking>\nChain of thought\n</thinking>" in result.data
|
||||||
assert "Final answer" in result.data
|
assert "Final answer" in result.data
|
||||||
@@ -96,7 +96,7 @@ def test_deepseek_tool_calling(mock_post: MagicMock) -> None:
|
|||||||
mock_post.side_effect = [mock_resp1, mock_resp2]
|
mock_post.side_effect = [mock_resp1, mock_resp2]
|
||||||
mock_dispatch.return_value = "Hello World"
|
mock_dispatch.return_value = "Hello World"
|
||||||
|
|
||||||
result = ai_client.send_result(md_content="Context", user_message="Read test.txt", base_dir=".")
|
result = ai_client.send(md_content="Context", user_message="Read test.txt", base_dir=".")
|
||||||
assert result.ok
|
assert result.ok
|
||||||
assert "File content is: Hello World" in result.data
|
assert "File content is: Hello World" in result.data
|
||||||
assert mock_dispatch.called
|
assert mock_dispatch.called
|
||||||
@@ -123,7 +123,7 @@ def test_deepseek_streaming(mock_post: MagicMock) -> None:
|
|||||||
mock_response.iter_lines.return_value = [c.encode('utf-8') for c in chunks]
|
mock_response.iter_lines.return_value = [c.encode('utf-8') for c in chunks]
|
||||||
mock_post.return_value = mock_response
|
mock_post.return_value = mock_response
|
||||||
|
|
||||||
result = ai_client.send_result(md_content="Context", user_message="Stream test", base_dir=".", stream=True)
|
result = ai_client.send(md_content="Context", user_message="Stream test", base_dir=".", stream=True)
|
||||||
assert result.ok
|
assert result.ok
|
||||||
assert result.data == "Hello World"
|
assert result.data == "Hello World"
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@ def test_deepseek_payload_verification(mock_post: MagicMock) -> None:
|
|||||||
}
|
}
|
||||||
mock_post.return_value = mock_response
|
mock_post.return_value = mock_response
|
||||||
|
|
||||||
result = ai_client.send_result(md_content="Context", user_message="Message 1", base_dir=".", discussion_history="History")
|
result = ai_client.send(md_content="Context", user_message="Message 1", base_dir=".", discussion_history="History")
|
||||||
assert result.ok
|
assert result.ok
|
||||||
|
|
||||||
args, kwargs = mock_post.call_args
|
args, kwargs = mock_post.call_args
|
||||||
@@ -174,7 +174,7 @@ def test_deepseek_reasoner_payload_verification(mock_post: MagicMock) -> None:
|
|||||||
}
|
}
|
||||||
mock_post.return_value = mock_response
|
mock_post.return_value = mock_response
|
||||||
|
|
||||||
result = ai_client.send_result(md_content="Context", user_message="Message 1", base_dir=".")
|
result = ai_client.send(md_content="Context", user_message="Message 1", base_dir=".")
|
||||||
assert result.ok
|
assert result.ok
|
||||||
|
|
||||||
args, kwargs = mock_post.call_args
|
args, kwargs = mock_post.call_args
|
||||||
|
|||||||
@@ -36,6 +36,6 @@ def test_gemini_cli_loop_termination() -> None:
|
|||||||
mock_process.returncode = 0
|
mock_process.returncode = 0
|
||||||
mock_popen.return_value = mock_process
|
mock_popen.return_value = mock_process
|
||||||
ai_client.set_provider("gemini_cli", "gemini-2.0-flash")
|
ai_client.set_provider("gemini_cli", "gemini-2.0-flash")
|
||||||
result = ai_client.send_result("context", "prompt")
|
result = ai_client.send("context", "prompt")
|
||||||
assert result.ok
|
assert result.ok
|
||||||
assert result.data == "Final answer"
|
assert result.data == "Final answer"
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ def test_gemini_cli_full_integration() -> None:
|
|||||||
}
|
}
|
||||||
mock_adapter.last_usage = {"total_tokens": 10}
|
mock_adapter.last_usage = {"total_tokens": 10}
|
||||||
ai_client._gemini_cli_adapter = mock_adapter
|
ai_client._gemini_cli_adapter = mock_adapter
|
||||||
result = ai_client.send_result("context", "integrated test")
|
result = ai_client.send("context", "integrated test")
|
||||||
assert result.ok
|
assert result.ok
|
||||||
assert "Final integrated answer" in result.data
|
assert "Final integrated answer" in result.data
|
||||||
|
|
||||||
@@ -28,5 +28,5 @@ def test_gemini_cli_rejection_and_history() -> None:
|
|||||||
}
|
}
|
||||||
mock_adapter.last_usage = {}
|
mock_adapter.last_usage = {}
|
||||||
ai_client._gemini_cli_adapter = mock_adapter
|
ai_client._gemini_cli_adapter = mock_adapter
|
||||||
result = ai_client.send_result("ctx", "msg", pre_tool_callback=lambda *a, **kw: None)
|
result = ai_client.send("ctx", "msg", pre_tool_callback=lambda *a, **kw: None)
|
||||||
assert result is not None
|
assert result is not None
|
||||||
|
|||||||
@@ -10,6 +10,6 @@ def test_send_invokes_adapter_send() -> None:
|
|||||||
mock_process.returncode = 0
|
mock_process.returncode = 0
|
||||||
mock_popen.return_value = mock_process
|
mock_popen.return_value = mock_process
|
||||||
ai_client.set_provider("gemini_cli", "gemini-2.0-flash")
|
ai_client.set_provider("gemini_cli", "gemini-2.0-flash")
|
||||||
res = ai_client.send_result("context", "msg")
|
res = ai_client.send("context", "msg")
|
||||||
assert res.ok
|
assert res.ok
|
||||||
assert res.data == "Hello from mock adapter"
|
assert res.data == "Hello from mock adapter"
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ def test_mcp_tool_call_is_dispatched(app_instance: App) -> None:
|
|||||||
mock_chat.send_message.side_effect = [mock_response_with_tool, mock_response_final]
|
mock_chat.send_message.side_effect = [mock_response_with_tool, mock_response_final]
|
||||||
ai_client.set_provider("gemini", "mock-model")
|
ai_client.set_provider("gemini", "mock-model")
|
||||||
# 5. Call the send function
|
# 5. Call the send function
|
||||||
result = ai_client.send_result(
|
result = ai_client.send(
|
||||||
md_content="some context",
|
md_content="some context",
|
||||||
user_message="read the file",
|
user_message="read the file",
|
||||||
base_dir=".",
|
base_dir=".",
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ class TestHeadlessAPI(unittest.TestCase):
|
|||||||
self.assertIn("not configured", response.json()["detail"])
|
self.assertIn("not configured", response.json()["detail"])
|
||||||
|
|
||||||
def test_generate_endpoint(self) -> None:
|
def test_generate_endpoint(self) -> None:
|
||||||
with patch('src.ai_client.send_result', return_value=Result(data="AI Response")), \
|
with patch('src.ai_client.send', return_value=Result(data="AI Response")), \
|
||||||
patch('src.app_controller.AppController._do_generate', return_value=("md", "path", [], "stable", "disc")):
|
patch('src.app_controller.AppController._do_generate', return_value=("md", "path", [], "stable", "disc")):
|
||||||
payload = {"prompt": "test prompt", "auto_add_history": False}
|
payload = {"prompt": "test prompt", "auto_add_history": False}
|
||||||
response = self.client.post("/api/v1/generate", json=payload, headers=self.headers)
|
response = self.client.post("/api/v1/generate", json=payload, headers=self.headers)
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ async def test_headless_verification_full_run(vlogger) -> None:
|
|||||||
vlogger.log_state("T2 Status Initial", "todo", t2.status)
|
vlogger.log_state("T2 Status Initial", "todo", t2.status)
|
||||||
|
|
||||||
# We must patch where it is USED: multi_agent_conductor
|
# We must patch where it is USED: multi_agent_conductor
|
||||||
with patch("src.multi_agent_conductor.ai_client.send_result") as mock_send, \
|
with patch("src.multi_agent_conductor.ai_client.send") as mock_send, \
|
||||||
patch("src.multi_agent_conductor.ai_client.reset_session") as mock_reset, \
|
patch("src.multi_agent_conductor.ai_client.reset_session") as mock_reset, \
|
||||||
patch("src.multi_agent_conductor.confirm_spawn", return_value=(True, "mock_prompt", "mock_ctx")):
|
patch("src.multi_agent_conductor.confirm_spawn", return_value=(True, "mock_prompt", "mock_ctx")):
|
||||||
# We need mock_send to return something that doesn't contain "BLOCKED"
|
# We need mock_send to return something that doesn't contain "BLOCKED"
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ def test_user_request_integration_flow(mock_app: App) -> None:
|
|||||||
# Mock all ai_client methods called during _handle_request_event
|
# Mock all ai_client methods called during _handle_request_event
|
||||||
mock_response = "This is a test AI response"
|
mock_response = "This is a test AI response"
|
||||||
with (
|
with (
|
||||||
patch('src.ai_client.send_result', return_value=Result(data=mock_response)) as mock_send,
|
patch('src.ai_client.send', return_value=Result(data=mock_response)) as mock_send,
|
||||||
patch('src.ai_client.set_custom_system_prompt'),
|
patch('src.ai_client.set_custom_system_prompt'),
|
||||||
patch('src.ai_client.set_model_params'),
|
patch('src.ai_client.set_model_params'),
|
||||||
patch('src.ai_client.set_agent_tools'),
|
patch('src.ai_client.set_agent_tools'),
|
||||||
@@ -52,8 +52,8 @@ def test_user_request_integration_flow(mock_app: App) -> None:
|
|||||||
# Let's call the handler
|
# Let's call the handler
|
||||||
app.controller._handle_request_event(event)
|
app.controller._handle_request_event(event)
|
||||||
|
|
||||||
# 3. Verify ai_client.send_result was called
|
# 3. Verify ai_client.send was called
|
||||||
assert mock_send.called, "ai_client.send_result was not called"
|
assert mock_send.called, "ai_client.send was not called"
|
||||||
|
|
||||||
# 4. First event should be 'comms' (request logging)
|
# 4. First event should be 'comms' (request logging)
|
||||||
event_name, payload = app.controller.event_queue.get()
|
event_name, payload = app.controller.event_queue.get()
|
||||||
@@ -85,7 +85,7 @@ def test_user_request_error_handling(mock_app: App) -> None:
|
|||||||
app = mock_app
|
app = mock_app
|
||||||
err = ErrorInfo(kind=ErrorKind.NETWORK, message="API Failure", source="ai_client.test")
|
err = ErrorInfo(kind=ErrorKind.NETWORK, message="API Failure", source="ai_client.test")
|
||||||
with (
|
with (
|
||||||
patch('src.ai_client.send_result', return_value=Result(data="", errors=[err])),
|
patch('src.ai_client.send', return_value=Result(data="", errors=[err])),
|
||||||
patch('src.ai_client.set_custom_system_prompt'),
|
patch('src.ai_client.set_custom_system_prompt'),
|
||||||
patch('src.ai_client.set_model_params'),
|
patch('src.ai_client.set_model_params'),
|
||||||
patch('src.ai_client.set_agent_tools'),
|
patch('src.ai_client.set_agent_tools'),
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ def test_generate_tracks() -> None:
|
|||||||
{"id": "track_2", "title": "Refactor", "goal": "decouple modules", "type": "refactor"}
|
{"id": "track_2", "title": "Refactor", "goal": "decouple modules", "type": "refactor"}
|
||||||
]
|
]
|
||||||
"""
|
"""
|
||||||
with patch("src.ai_client.send_result", return_value=Result(data=mock_response)):
|
with patch("src.ai_client.send", return_value=Result(data=mock_response)):
|
||||||
tracks = orchestrator_pm.generate_tracks("Develop feature X", {}, [])
|
tracks = orchestrator_pm.generate_tracks("Develop feature X", {}, [])
|
||||||
assert len(tracks) == 2
|
assert len(tracks) == 2
|
||||||
assert tracks[0]["id"] == "track_1"
|
assert tracks[0]["id"] == "track_1"
|
||||||
@@ -26,7 +26,7 @@ def test_generate_tickets() -> None:
|
|||||||
{"id": "T2", "description": "task 2", "depends_on": ["T1"]}
|
{"id": "T2", "description": "task 2", "depends_on": ["T1"]}
|
||||||
]
|
]
|
||||||
"""
|
"""
|
||||||
with patch("src.ai_client.send_result", return_value=Result(data=mock_response)):
|
with patch("src.ai_client.send", return_value=Result(data=mock_response)):
|
||||||
tickets = conductor_tech_lead.generate_tickets("Track goal", "code skeletons")
|
tickets = conductor_tech_lead.generate_tickets("Track goal", "code skeletons")
|
||||||
assert len(tickets) == 2
|
assert len(tickets) == 2
|
||||||
assert tickets[0]["id"] == "T1"
|
assert tickets[0]["id"] == "T1"
|
||||||
@@ -105,7 +105,7 @@ def test_conductor_engine_parse_json_tickets() -> None:
|
|||||||
def test_run_worker_lifecycle_blocked() -> None:
|
def test_run_worker_lifecycle_blocked() -> None:
|
||||||
ticket = Ticket(id="T1", description="desc", status="todo", assigned_to="worker1")
|
ticket = Ticket(id="T1", description="desc", status="todo", assigned_to="worker1")
|
||||||
context = WorkerContext(ticket_id="T1", model_name="model", messages=[])
|
context = WorkerContext(ticket_id="T1", model_name="model", messages=[])
|
||||||
with patch("src.ai_client.send_result") as mock_ai_client, \
|
with patch("src.ai_client.send") as mock_ai_client, \
|
||||||
patch("src.ai_client.reset_session"), \
|
patch("src.ai_client.reset_session"), \
|
||||||
patch("src.ai_client.set_provider"), \
|
patch("src.ai_client.set_provider"), \
|
||||||
patch("src.multi_agent_conductor.confirm_spawn", return_value=(True, "p", "c")):
|
patch("src.multi_agent_conductor.confirm_spawn", return_value=(True, "p", "c")):
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ def test_worker_streaming_intermediate():
|
|||||||
event_queue = MagicMock()
|
event_queue = MagicMock()
|
||||||
|
|
||||||
with (
|
with (
|
||||||
patch("src.ai_client.send_result") as mock_send_result,
|
patch("src.ai_client.send") as mock_send,
|
||||||
patch("src.multi_agent_conductor._queue_put") as mock_q_put,
|
patch("src.multi_agent_conductor._queue_put") as mock_q_put,
|
||||||
patch("src.multi_agent_conductor.confirm_spawn", return_value=(True, "p", "c")),
|
patch("src.multi_agent_conductor.confirm_spawn", return_value=(True, "p", "c")),
|
||||||
patch("src.ai_client.reset_session"),
|
patch("src.ai_client.reset_session"),
|
||||||
@@ -26,7 +26,7 @@ def test_worker_streaming_intermediate():
|
|||||||
cb({"kind": "tool_result", "payload": {"name": "test_tool", "output": "hello"}})
|
cb({"kind": "tool_result", "payload": {"name": "test_tool", "output": "hello"}})
|
||||||
return Result(data="DONE")
|
return Result(data="DONE")
|
||||||
|
|
||||||
mock_send_result.side_effect = side_effect
|
mock_send.side_effect = side_effect
|
||||||
run_worker_lifecycle(ticket, context, event_queue=event_queue)
|
run_worker_lifecycle(ticket, context, event_queue=event_queue)
|
||||||
|
|
||||||
# _queue_put(event_queue, event_name, payload)
|
# _queue_put(event_queue, event_name, payload)
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ def test_rag_integration(mock_project):
|
|||||||
# message sent to the provider. We use 'wraps' to let the real logic run
|
# message sent to the provider. We use 'wraps' to let the real logic run
|
||||||
# while still having a mock we can inspect. We also mock the internal
|
# while still having a mock we can inspect. We also mock the internal
|
||||||
# _send_gemini which is what actually "sends to the provider".
|
# _send_gemini which is what actually "sends to the provider".
|
||||||
with patch('src.ai_client.send_result', wraps=ai_client.send_result) as mock_send:
|
with patch('src.ai_client.send', wraps=ai_client.send) as mock_send:
|
||||||
with patch('src.ai_client._send_gemini') as mock_provider:
|
with patch('src.ai_client._send_gemini') as mock_provider:
|
||||||
mock_provider.return_value = Result(data="Mock AI Response")
|
mock_provider.return_value = Result(data="Mock AI Response")
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ class TestRunWorkerLifecycleAbort(unittest.TestCase):
|
|||||||
Test that run_worker_lifecycle returns early and marks ticket as 'killed'
|
Test that run_worker_lifecycle returns early and marks ticket as 'killed'
|
||||||
if the abort event is set for the ticket.
|
if the abort event is set for the ticket.
|
||||||
"""
|
"""
|
||||||
# Mock ai_client.send_result
|
# Mock ai_client.send
|
||||||
with patch('src.ai_client.send_result') as mock_send_result:
|
with patch('src.ai_client.send') as mock_send:
|
||||||
# Mock ticket and context
|
# Mock ticket and context
|
||||||
ticket = Ticket(id="T-001", description="Test task")
|
ticket = Ticket(id="T-001", description="Test task")
|
||||||
ticket = Ticket(id="T-001", description="Test task")
|
ticket = Ticket(id="T-001", description="Test task")
|
||||||
@@ -34,8 +34,8 @@ class TestRunWorkerLifecycleAbort(unittest.TestCase):
|
|||||||
# Assert ticket status is 'killed'
|
# Assert ticket status is 'killed'
|
||||||
self.assertEqual(ticket.status, "killed")
|
self.assertEqual(ticket.status, "killed")
|
||||||
|
|
||||||
# Also assert ai_client.send_result was NOT called (abort fires before the call)
|
# Also assert ai_client.send was NOT called (abort fires before the call)
|
||||||
mock_send_result.assert_not_called()
|
mock_send.assert_not_called()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
@@ -20,9 +20,9 @@ class MockDialog:
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def mock_ai_client() -> Generator[MagicMock, None, None]:
|
def mock_ai_client() -> Generator[MagicMock, None, None]:
|
||||||
with patch("src.ai_client.send_result") as mock_send_result:
|
with patch("src.ai_client.send") as mock_send:
|
||||||
mock_send_result.return_value = Result(data="Task completed")
|
mock_send.return_value = Result(data="Task completed")
|
||||||
yield mock_send_result
|
yield mock_send
|
||||||
|
|
||||||
def test_confirm_spawn_pushed_to_queue() -> None:
|
def test_confirm_spawn_pushed_to_queue() -> None:
|
||||||
event_queue = events.SyncEventQueue()
|
event_queue = events.SyncEventQueue()
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ def test_handle_request_event_appends_definitions(controller):
|
|||||||
with (
|
with (
|
||||||
patch('src.app_controller.parse_symbols', return_value=["Track"]) as mock_parse,
|
patch('src.app_controller.parse_symbols', return_value=["Track"]) as mock_parse,
|
||||||
patch('src.app_controller.get_symbol_definition', return_value=("src/models.py", "class Track: pass", 42)) as mock_get_def,
|
patch('src.app_controller.get_symbol_definition', return_value=("src/models.py", "class Track: pass", 42)) as mock_get_def,
|
||||||
patch('src.ai_client.send_result', return_value=Result(data="mocked response")) as mock_send_result
|
patch('src.ai_client.send', return_value=Result(data="mocked response")) as mock_send
|
||||||
):
|
):
|
||||||
# Execute
|
# Execute
|
||||||
controller._handle_request_event(event)
|
controller._handle_request_event(event)
|
||||||
@@ -54,8 +54,8 @@ def test_handle_request_event_appends_definitions(controller):
|
|||||||
|
|
||||||
# Check if enriched prompt was sent to AI
|
# Check if enriched prompt was sent to AI
|
||||||
expected_suffix = "\n\n[Definition: Track from src/models.py (line 42)]\n```python\nclass Track: pass\n```"
|
expected_suffix = "\n\n[Definition: Track from src/models.py (line 42)]\n```python\nclass Track: pass\n```"
|
||||||
mock_send_result.assert_called_once()
|
mock_send.assert_called_once()
|
||||||
args, kwargs = mock_send_result.call_args
|
args, kwargs = mock_send.call_args
|
||||||
sent_prompt = args[1]
|
sent_prompt = args[1]
|
||||||
assert sent_prompt == "Explain @Track object" + expected_suffix
|
assert sent_prompt == "Explain @Track object" + expected_suffix
|
||||||
|
|
||||||
@@ -72,13 +72,13 @@ def test_handle_request_event_no_symbols(controller):
|
|||||||
|
|
||||||
with (
|
with (
|
||||||
patch('src.app_controller.parse_symbols', return_value=[]) as mock_parse,
|
patch('src.app_controller.parse_symbols', return_value=[]) as mock_parse,
|
||||||
patch('src.ai_client.send_result', return_value=Result(data="mocked response")) as mock_send_result
|
patch('src.ai_client.send', return_value=Result(data="mocked response")) as mock_send
|
||||||
):
|
):
|
||||||
# Execute
|
# Execute
|
||||||
controller._handle_request_event(event)
|
controller._handle_request_event(event)
|
||||||
|
|
||||||
# Verify
|
# Verify
|
||||||
mock_send_result.assert_called_once()
|
mock_send.assert_called_once()
|
||||||
args, kwargs = mock_send_result.call_args
|
args, kwargs = mock_send.call_args
|
||||||
sent_prompt = args[1]
|
sent_prompt = args[1]
|
||||||
assert sent_prompt == "Just a normal prompt"
|
assert sent_prompt == "Just a normal prompt"
|
||||||
|
|||||||
@@ -76,17 +76,17 @@ def test_end_to_end_tier4_integration(vlogger) -> None:
|
|||||||
vlogger.finalize("E2E Tier 4 Integration", "PASS", "ai_client.run_tier4_analysis correctly called and results merged.")
|
vlogger.finalize("E2E Tier 4 Integration", "PASS", "ai_client.run_tier4_analysis correctly called and results merged.")
|
||||||
|
|
||||||
def test_ai_client_passes_qa_callback() -> None:
|
def test_ai_client_passes_qa_callback() -> None:
|
||||||
"""Verifies that ai_client.send_result passes the qa_callback down to the provider function."""
|
"""Verifies that ai_client.send passes the qa_callback down to the provider function."""
|
||||||
qa_callback = lambda x: "analysis"
|
qa_callback = lambda x: "analysis"
|
||||||
|
|
||||||
with patch("src.ai_client._send_gemini", return_value=Result(data="ok")) as mock_send:
|
with patch("src.ai_client._send_gemini", return_value=Result(data="ok")) as mock_send:
|
||||||
ai_client.set_provider("gemini", "gemini-2.5-flash-lite")
|
ai_client.set_provider("gemini", "gemini-2.5-flash-lite")
|
||||||
result = ai_client.send_result("ctx", "msg", qa_callback=qa_callback)
|
result = ai_client.send("ctx", "msg", qa_callback=qa_callback)
|
||||||
assert result.ok
|
assert result.ok
|
||||||
args, kwargs = mock_send.call_args
|
args, kwargs = mock_send.call_args
|
||||||
# It might be passed as positional or keyword depending on how 'send_result' calls it
|
# It might be passed as positional or keyword depending on how 'send' calls it
|
||||||
# send_result() calls _send_gemini(md_content, user_message, base_dir, ..., qa_callback, ...)
|
# send() calls _send_gemini(md_content, user_message, base_dir, ..., qa_callback, ...)
|
||||||
# In current impl of send_result(), it is the 7th argument after md_content, user_msg, base_dir, file_items, disc_hist, pre_tool
|
# In current impl of send(), it is the 7th argument after md_content, user_msg, base_dir, file_items, disc_hist, pre_tool
|
||||||
assert args[6] == qa_callback or kwargs.get("qa_callback") == qa_callback
|
assert args[6] == qa_callback or kwargs.get("qa_callback") == qa_callback
|
||||||
|
|
||||||
def test_gemini_provider_passes_qa_callback_to_run_script() -> None:
|
def test_gemini_provider_passes_qa_callback_to_run_script() -> None:
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ def test_app_controller_do_generate_uses_persona_strategy(mock_build):
|
|||||||
assert call_kwargs.get("aggregation_strategy") == "full"
|
assert call_kwargs.get("aggregation_strategy") == "full"
|
||||||
|
|
||||||
@patch("src.summarize.summarise_file")
|
@patch("src.summarize.summarise_file")
|
||||||
@patch("src.multi_agent_conductor.ai_client.send_result")
|
@patch("src.multi_agent_conductor.ai_client.send")
|
||||||
def test_run_worker_lifecycle_uses_strategy(mock_send, mock_summarise, tmp_path):
|
def test_run_worker_lifecycle_uses_strategy(mock_send, mock_summarise, tmp_path):
|
||||||
mock_send.return_value = Result(data="fake response")
|
mock_send.return_value = Result(data="fake response")
|
||||||
mock_summarise.return_value = "fake summary"
|
mock_summarise.return_value = "fake summary"
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ def test_token_usage_tracking() -> None:
|
|||||||
mock_response.text = "Mock Response"
|
mock_response.text = "Mock Response"
|
||||||
mock_chat.send_message.return_value = mock_response
|
mock_chat.send_message.return_value = mock_response
|
||||||
ai_client.set_provider("gemini", "gemini-2.5-flash-lite")
|
ai_client.set_provider("gemini", "gemini-2.5-flash-lite")
|
||||||
result = ai_client.send_result("Context", "Hello")
|
result = ai_client.send("Context", "Hello")
|
||||||
assert result.ok
|
assert result.ok
|
||||||
comms = ai_client.get_comms_log()
|
comms = ai_client.get_comms_log()
|
||||||
response_entries = [e for e in comms if e.get("direction") == "IN" and e["kind"] == "response"]
|
response_entries = [e for e in comms if e.get("direction") == "IN" and e["kind"] == "response"]
|
||||||
|
|||||||
Reference in New Issue
Block a user