refactor(ai_client): migrate _deepseek_history call sites to provider_state.get_history('deepseek')
TIER-2 READ conductor/code_styleguides/error_handling.md before Phase 2 (deepseek migration; RLock re-entrance critical).
Phase 2 of code_path_audit_phase_3_provider_state_20260624. 11 sites in _send_deepseek (lines 2186-2414) migrated from _deepseek_history/_deepseek_history_lock to local capture history = provider_state.get_history('deepseek'). The RLock re-entrance is critical here — this was the deadlock-prone site that prompted cc7993e5. The local capture pattern uses one acquisition per function instead of one per call site, minimizing lock acquisitions while preserving the same RLock instance that _deepseek_history_lock aliased to.
4 with-blocks migrated (lines 2195, 2215, 2347, 2412). 6 _deepseek_history alias references migrated to history (lines 2196, 2197, 2201, 2216, 2354, 2414).
Verified: 30 tests pass across test_provider_state_migration (14) + test_deepseek_provider (7) + 5 ai_client test files. The test_lock_acquisition_no_deadlock regression test verifies RLock re-entrance works correctly inside the with history.lock: blocks.
Conventions: 1-space indentation, CRLF preserved, no comments added.
This commit is contained in:
+11
-10
@@ -2183,6 +2183,7 @@ def _send_deepseek(md_content: str, user_message: str, base_dir: str,
|
|||||||
if not api_key:
|
if not api_key:
|
||||||
if monitor.enabled: monitor.end_component("ai_client._send_deepseek")
|
if monitor.enabled: monitor.end_component("ai_client._send_deepseek")
|
||||||
raise ValueError("DeepSeek API key not found in credentials.toml")
|
raise ValueError("DeepSeek API key not found in credentials.toml")
|
||||||
|
history = provider_state.get_history("deepseek")
|
||||||
api_url = "https://api.deepseek.com/chat/completions"
|
api_url = "https://api.deepseek.com/chat/completions"
|
||||||
headers = {
|
headers = {
|
||||||
"Authorization": f"Bearer {api_key}",
|
"Authorization": f"Bearer {api_key}",
|
||||||
@@ -2192,13 +2193,13 @@ def _send_deepseek(md_content: str, user_message: str, base_dir: str,
|
|||||||
is_reasoner = _model in ("deepseek-reasoner", "deepseek-r1")
|
is_reasoner = _model in ("deepseek-reasoner", "deepseek-r1")
|
||||||
|
|
||||||
# Update history following Anthropic pattern
|
# Update history following Anthropic pattern
|
||||||
with _deepseek_history_lock:
|
with history.lock:
|
||||||
_repair_deepseek_history(_deepseek_history)
|
_repair_deepseek_history(history)
|
||||||
if discussion_history and not _deepseek_history:
|
if discussion_history and not history:
|
||||||
user_content = f"[DISCUSSION HISTORY]\n\n{discussion_history}\n\n---\n\n{user_message}"
|
user_content = f"[DISCUSSION HISTORY]\n\n{discussion_history}\n\n---\n\n{user_message}"
|
||||||
else:
|
else:
|
||||||
user_content = user_message
|
user_content = user_message
|
||||||
_deepseek_history.append({"role": "user", "content": user_content})
|
history.append({"role": "user", "content": user_content})
|
||||||
|
|
||||||
all_text_parts: list[str] = []
|
all_text_parts: list[str] = []
|
||||||
_cumulative_tool_bytes = 0
|
_cumulative_tool_bytes = 0
|
||||||
@@ -2212,8 +2213,8 @@ def _send_deepseek(md_content: str, user_message: str, base_dir: str,
|
|||||||
sys_msg = {"role": "system", "content": f"{_get_combined_system_prompt()}\n\n<context>\n{md_content}\n</context>"}
|
sys_msg = {"role": "system", "content": f"{_get_combined_system_prompt()}\n\n<context>\n{md_content}\n</context>"}
|
||||||
current_api_messages.append(sys_msg)
|
current_api_messages.append(sys_msg)
|
||||||
|
|
||||||
with _deepseek_history_lock:
|
with history.lock:
|
||||||
for i, msg in enumerate(_deepseek_history):
|
for i, msg in enumerate(history):
|
||||||
# Create a clean copy of the message for the API
|
# Create a clean copy of the message for the API
|
||||||
role = msg.get("role")
|
role = msg.get("role")
|
||||||
api_msg = {"role": role}
|
api_msg = {"role": role}
|
||||||
@@ -2344,14 +2345,14 @@ def _send_deepseek(md_content: str, user_message: str, base_dir: str,
|
|||||||
thinking_tags = f"<thinking>\n{reasoning_content}\n</thinking>\n"
|
thinking_tags = f"<thinking>\n{reasoning_content}\n</thinking>\n"
|
||||||
full_assistant_text = thinking_tags + assistant_text
|
full_assistant_text = thinking_tags + assistant_text
|
||||||
|
|
||||||
with _deepseek_history_lock:
|
with history.lock:
|
||||||
# DeepSeek/OpenAI: If tool_calls are present, content can be null but should usually be present
|
# DeepSeek/OpenAI: If tool_calls are present, content can be null but should usually be present
|
||||||
msg_to_store: Metadata = {"role": "assistant", "content": assistant_text or None}
|
msg_to_store: Metadata = {"role": "assistant", "content": assistant_text or None}
|
||||||
if reasoning_content:
|
if reasoning_content:
|
||||||
msg_to_store["reasoning_content"] = reasoning_content
|
msg_to_store["reasoning_content"] = reasoning_content
|
||||||
if tool_calls_raw:
|
if tool_calls_raw:
|
||||||
msg_to_store["tool_calls"] = tool_calls_raw
|
msg_to_store["tool_calls"] = tool_calls_raw
|
||||||
_deepseek_history.append(msg_to_store)
|
history.append(msg_to_store)
|
||||||
|
|
||||||
if full_assistant_text:
|
if full_assistant_text:
|
||||||
all_text_parts.append(full_assistant_text)
|
all_text_parts.append(full_assistant_text)
|
||||||
@@ -2409,9 +2410,9 @@ def _send_deepseek(md_content: str, user_message: str, base_dir: str,
|
|||||||
})
|
})
|
||||||
_append_comms("OUT", "request", {"message": f"[TOOL OUTPUT BUDGET EXCEEDED: {_cumulative_tool_bytes} bytes]"})
|
_append_comms("OUT", "request", {"message": f"[TOOL OUTPUT BUDGET EXCEEDED: {_cumulative_tool_bytes} bytes]"})
|
||||||
|
|
||||||
with _deepseek_history_lock:
|
with history.lock:
|
||||||
for tr in tool_results_for_history:
|
for tr in tool_results_for_history:
|
||||||
_deepseek_history.append(tr)
|
history.append(tr)
|
||||||
|
|
||||||
res = "\n\n".join(all_text_parts) if all_text_parts else "(No text returned)"
|
res = "\n\n".join(all_text_parts) if all_text_parts else "(No text returned)"
|
||||||
if monitor.enabled: monitor.end_component("ai_client._send_deepseek")
|
if monitor.enabled: monitor.end_component("ai_client._send_deepseek")
|
||||||
|
|||||||
Reference in New Issue
Block a user