fixing...
This commit is contained in:
39
ai_client.py
39
ai_client.py
@@ -277,6 +277,29 @@ def _run_script(script: str, base_dir: str) -> str:
|
||||
return output
|
||||
|
||||
|
||||
# ------------------------------------------------------------------ content block serialisation
|
||||
|
||||
def _content_block_to_dict(block) -> dict:
|
||||
"""
|
||||
Convert an Anthropic SDK content block object to a plain dict.
|
||||
This ensures history entries are always JSON-serialisable dicts,
|
||||
not opaque SDK objects that may fail on re-serialisation.
|
||||
"""
|
||||
if isinstance(block, dict):
|
||||
return block
|
||||
if hasattr(block, "model_dump"):
|
||||
return block.model_dump()
|
||||
if hasattr(block, "to_dict"):
|
||||
return block.to_dict()
|
||||
# Fallback: manually construct based on type
|
||||
block_type = getattr(block, "type", None)
|
||||
if block_type == "text":
|
||||
return {"type": "text", "text": block.text}
|
||||
if block_type == "tool_use":
|
||||
return {"type": "tool_use", "id": block.id, "name": block.name, "input": block.input}
|
||||
return {"type": "text", "text": str(block)}
|
||||
|
||||
|
||||
# ------------------------------------------------------------------ gemini
|
||||
|
||||
def _ensure_gemini_client():
|
||||
@@ -322,10 +345,10 @@ def _send_gemini(md_content: str, user_message: str, base_dir: str) -> str:
|
||||
part.function_call
|
||||
for candidate in response.candidates
|
||||
for part in candidate.content.parts
|
||||
if part.function_call is not None
|
||||
if hasattr(part, "function_call") and part.function_call is not None
|
||||
]
|
||||
|
||||
_append_comms("IN", "response", {
|
||||
_append_comms("IN", "response", {
|
||||
"round": round_idx,
|
||||
"text": "\n".join(text_parts_raw),
|
||||
"tool_calls": [{"name": fc.name, "args": dict(fc.args)} for fc in tool_calls],
|
||||
@@ -434,9 +457,6 @@ def _repair_anthropic_history(history: list[dict]):
|
||||
if isinstance(block, dict):
|
||||
if block.get("type") == "tool_use":
|
||||
tool_use_ids.append(block["id"])
|
||||
else:
|
||||
if getattr(block, "type", None) == "tool_use":
|
||||
tool_use_ids.append(block.id)
|
||||
if not tool_use_ids:
|
||||
return
|
||||
history.append({
|
||||
@@ -489,16 +509,19 @@ def _send_anthropic(md_content: str, user_message: str, base_dir: str) -> str:
|
||||
messages=_anthropic_history,
|
||||
)
|
||||
|
||||
# Convert SDK content block objects to plain dicts before storing in history
|
||||
serialised_content = [_content_block_to_dict(b) for b in response.content]
|
||||
|
||||
_anthropic_history.append({
|
||||
"role": "assistant",
|
||||
"content": response.content,
|
||||
"content": serialised_content,
|
||||
})
|
||||
|
||||
text_blocks = [b.text for b in response.content if hasattr(b, "text") and b.text]
|
||||
tool_use_blocks = [
|
||||
{"id": b.id, "name": b.name, "input": b.input}
|
||||
for b in response.content
|
||||
if b.type == "tool_use"
|
||||
if getattr(b, "type", None) == "tool_use"
|
||||
]
|
||||
|
||||
usage_dict: dict = {}
|
||||
@@ -525,7 +548,7 @@ def _send_anthropic(md_content: str, user_message: str, base_dir: str) -> str:
|
||||
|
||||
tool_results = []
|
||||
for block in response.content:
|
||||
if block.type == "tool_use" and block.name == TOOL_NAME:
|
||||
if getattr(block, "type", None) == "tool_use" and getattr(block, "name", None) == TOOL_NAME:
|
||||
script = block.input.get("script", "")
|
||||
_append_comms("OUT", "tool_call", {
|
||||
"name": TOOL_NAME,
|
||||
|
||||
Reference in New Issue
Block a user