refactor(ai_client): migrate _anthropic_history call sites to provider_state.get_history('anthropic')
TIER-2 READ conductor/code_styleguides/error_handling.md before Phase 1 (anthropic migration).
Phase 1 of code_path_audit_phase_3_provider_state_20260624. 13 call sites in _send_anthropic (lines 1430-1575) migrated from the module-level _anthropic_history alias to a local capture history = provider_state.get_history('anthropic'). The local capture pattern is used (instead of repeated provider_state.get_history() calls) to minimize lock acquisitions and improve readability.
The migration preserves behavior: ProviderHistory is the same singleton that _anthropic_history aliased to, so the migration is a pure refactor. The lock acquisition pattern is unchanged (this function does not acquire _anthropic_history_lock; thread-safety comes from _send_anthropic being called per-thread).
Verified: 37 tests pass across test_provider_state_migration.py + 6 ai_client test files.
Conventions: 1-space indentation, CRLF preserved, no comments added.
This commit is contained in:
+14
-13
@@ -1427,16 +1427,17 @@ def _send_anthropic(
|
||||
try:
|
||||
_ensure_anthropic_client()
|
||||
mcp_client.configure(file_items or [], [base_dir])
|
||||
history = provider_state.get_history("anthropic")
|
||||
stable_prompt = _get_combined_system_prompt()
|
||||
stable_blocks: list[Metadata] = [{"type": "text", "text": stable_prompt, "cache_control": {"type": "ephemeral"}}]
|
||||
context_text = f"\n\n<context>\n{md_content}\n</context>"
|
||||
context_blocks = _build_chunked_context_blocks(context_text)
|
||||
system_blocks = stable_blocks + context_blocks
|
||||
if discussion_history and not _anthropic_history:
|
||||
if discussion_history and not history:
|
||||
user_content: list[Metadata] = [{"type": "text", "text": f"[DISCUSSION HISTORY]\n\n{discussion_history}\n\n---\n\n{user_message}"}]
|
||||
else:
|
||||
user_content = [{"type": "text", "text": user_message}]
|
||||
for msg in _anthropic_history:
|
||||
for msg in history:
|
||||
if msg.get("role") == "user" and isinstance(msg.get("content"), list):
|
||||
modified = False
|
||||
for block in cast(List[dict[str, Any]], msg["content"]):
|
||||
@@ -1446,10 +1447,10 @@ def _send_anthropic(
|
||||
block["content"] = t_content[:_history_trunc_limit] + "\n\n... [TRUNCATED BY SYSTEM TO SAVE TOKENS. Original output was too large.]"
|
||||
modified = True
|
||||
if modified: _invalidate_token_estimate(msg)
|
||||
_strip_cache_controls(_anthropic_history)
|
||||
_repair_anthropic_history(_anthropic_history)
|
||||
_anthropic_history.append({"role": "user", "content": user_content})
|
||||
_add_history_cache_breakpoint(_anthropic_history)
|
||||
_strip_cache_controls(history)
|
||||
_repair_anthropic_history(history)
|
||||
history.append({"role": "user", "content": user_content})
|
||||
_add_history_cache_breakpoint(history)
|
||||
all_text_parts: list[str] = []
|
||||
_cumulative_tool_bytes = 0
|
||||
|
||||
@@ -1458,13 +1459,13 @@ def _send_anthropic(
|
||||
|
||||
for round_idx in range(MAX_TOOL_ROUNDS + 2):
|
||||
response: Any = None
|
||||
dropped = _trim_anthropic_history(system_blocks, _anthropic_history)
|
||||
dropped = _trim_anthropic_history(system_blocks, history)
|
||||
if dropped > 0:
|
||||
est_tokens = _estimate_prompt_tokens(system_blocks, _anthropic_history)
|
||||
est_tokens = _estimate_prompt_tokens(system_blocks, history)
|
||||
_append_comms("OUT", "request", {
|
||||
"message": (
|
||||
f"[HISTORY TRIMMED: dropped {dropped} old messages to fit token budget. "
|
||||
f"Estimated {est_tokens} tokens remaining. {len(_anthropic_history)} messages in history.]"
|
||||
f"Estimated {est_tokens} tokens remaining. {len(history)} messages in history.]"
|
||||
),
|
||||
})
|
||||
|
||||
@@ -1478,7 +1479,7 @@ def _send_anthropic(
|
||||
top_p = _top_p,
|
||||
system = cast(Iterable[anthropic.types.TextBlockParam], system_blocks),
|
||||
tools = cast(Iterable[anthropic.types.ToolParam], _get_anthropic_tools()),
|
||||
messages = cast(Iterable[anthropic.types.MessageParam], _strip_private_keys(_anthropic_history)),
|
||||
messages = cast(Iterable[anthropic.types.MessageParam], _strip_private_keys(history)),
|
||||
) as stream:
|
||||
for event in stream:
|
||||
if isinstance(event, anthropic.types.ContentBlockDeltaEvent) and event.delta.type == "text_delta":
|
||||
@@ -1492,10 +1493,10 @@ def _send_anthropic(
|
||||
top_p = _top_p,
|
||||
system = cast(Iterable[anthropic.types.TextBlockParam], system_blocks),
|
||||
tools = cast(Iterable[anthropic.types.ToolParam], _get_anthropic_tools()),
|
||||
messages = cast(Iterable[anthropic.types.MessageParam], _strip_private_keys(_anthropic_history)),
|
||||
messages = cast(Iterable[anthropic.types.MessageParam], _strip_private_keys(history)),
|
||||
)
|
||||
serialised_content = [_content_block_to_dict(b) for b in response.content]
|
||||
_anthropic_history.append({
|
||||
history.append({
|
||||
"role": "assistant",
|
||||
"content": serialised_content,
|
||||
})
|
||||
@@ -1571,7 +1572,7 @@ def _send_anthropic(
|
||||
"type": "text",
|
||||
"text": "SYSTEM WARNING: MAX TOOL ROUNDS REACHED. YOU MUST PROVIDE YOUR FINAL ANSWER NOW WITHOUT CALLING ANY MORE TOOLS."
|
||||
})
|
||||
_anthropic_history.append({
|
||||
history.append({
|
||||
"role": "user",
|
||||
"content": tool_results,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user