From 5834628111a0a50204ed3c04f860ef9bf2e29a8d Mon Sep 17 00:00:00 2001 From: Ed_ Date: Sun, 21 Jun 2026 19:47:40 -0400 Subject: [PATCH] refactor(ai_client): migrate _send_grok/_send_minimax/_send_llama to ChatMessage API Completes the deferred t2_6 task from any_type_componentization_20260621 Phase 2. The 3 OpenAI-compatible senders now construct OpenAICompatibleRequest with messages=[ChatMessage(role=, content=)] instead of list[dict] literals. The __history global lists are still dicts (Phase 3 deferred to a separate track); the migration converts each dict to ChatMessage at the request-build boundary via list comprehension. The backward-compat shim in openai_compatible.py:86 (m.to_dict() if hasattr(m, 'to_dict') else m) handles both ChatMessage and dict transparently. Verified: 20/20 provider tests pass; tier-1-unit (5 pre-existing sandbox-pollution failures unchanged); no new regressions. --- src/ai_client.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/ai_client.py b/src/ai_client.py index 9d6f1d0b..95a5aac0 100644 --- a/src/ai_client.py +++ b/src/ai_client.py @@ -2570,6 +2570,7 @@ def _send_grok(md_content: str, user_message: str, base_dir: str, Runs synchronously in the caller thread; synchronizes Grok history using _grok_history_lock. """ from src.openai_compatible import OpenAICompatibleRequest, _classify_openai_compatible_error + from src.openai_schemas import ChatMessage try: client = _ensure_grok_client() tools: list[Metadata] | None = _get_deepseek_tools() or None @@ -2586,8 +2587,9 @@ def _send_grok(md_content: str, user_message: str, base_dir: str, _grok_history.append({"role": "user", "content": user_content}) def _build_grok_request(_round_idx: int) -> OpenAICompatibleRequest: with _grok_history_lock: - messages: list[Metadata] = [{"role": "system", "content": f"{_get_combined_system_prompt()}\n\n\n{md_content}\n"}] - messages.extend(_grok_history) + history_msgs: list[ChatMessage] = [ChatMessage(role=m["role"], content=m["content"]) for m in _grok_history] + messages: list[ChatMessage] = [ChatMessage(role="system", content=f"{_get_combined_system_prompt()}\n\n\n{md_content}\n")] + messages.extend(history_msgs) extra_body: Metadata = {} if caps.web_search: extra_body["search_parameters"] = {"mode": "auto"} @@ -2655,6 +2657,7 @@ def _send_minimax(md_content: str, user_message: str, base_dir: str, Runs synchronously in the caller thread; synchronizes MiniMax history using _minimax_history_lock. """ from src.openai_compatible import OpenAICompatibleRequest + from src.openai_schemas import ChatMessage try: _ensure_minimax_client() tools: list[Metadata] | None = _get_deepseek_tools() or None @@ -2665,8 +2668,9 @@ def _send_minimax(md_content: str, user_message: str, base_dir: str, _minimax_history.append({"role": "user", "content": user_message}) def _build_minimax_request(_round_idx: int) -> OpenAICompatibleRequest: with _minimax_history_lock: - messages: list[Metadata] = [{"role": "system", "content": f"{_get_combined_system_prompt()}\n\n\n{md_content}\n"}] - messages.extend(_minimax_history) + history_msgs: list[ChatMessage] = [ChatMessage(role=m["role"], content=m["content"]) for m in _minimax_history] + messages: list[ChatMessage] = [ChatMessage(role="system", content=f"{_get_combined_system_prompt()}\n\n\n{md_content}\n")] + messages.extend(history_msgs) return OpenAICompatibleRequest( messages=messages, model=_model, temperature=_temperature, top_p=_top_p, max_tokens=min(_max_tokens, 8192), stream=stream, stream_callback=stream_callback, @@ -2895,6 +2899,7 @@ def _send_llama(md_content: str, user_message: str, base_dir: str, Runs synchronously in the caller thread; synchronizes history using _llama_history_lock. """ from src.openai_compatible import OpenAICompatibleRequest, _classify_openai_compatible_error + from src.openai_schemas import ChatMessage try: if "localhost" in _llama_base_url or "127.0.0.1" in _llama_base_url: return _send_llama_native(md_content, user_message, base_dir, file_items, discussion_history, stream, pre_tool_callback, qa_callback, stream_callback, patch_callback) @@ -2912,8 +2917,9 @@ def _send_llama(md_content: str, user_message: str, base_dir: str, _llama_history.append({"role": "user", "content": user_content}) def _build_llama_request(_round_idx: int) -> OpenAICompatibleRequest: with _llama_history_lock: - messages: list[Metadata] = [{"role": "system", "content": f"{_get_combined_system_prompt()}\n\n\n{md_content}\n"}] - messages.extend(_llama_history) + history_msgs: list[ChatMessage] = [ChatMessage(role=m["role"], content=m["content"]) for m in _llama_history] + messages: list[ChatMessage] = [ChatMessage(role="system", content=f"{_get_combined_system_prompt()}\n\n\n{md_content}\n")] + messages.extend(history_msgs) return OpenAICompatibleRequest( messages=messages, model=_model, temperature=_temperature, top_p=_top_p, max_tokens=_max_tokens, stream=stream, stream_callback=stream_callback,