fix(agent): summarize structured provider error messages

This commit is contained in:
Gille 2026-06-18 16:49:14 -06:00 committed by Teknium
parent 620fd59b8e
commit e4452ffb8a
2 changed files with 59 additions and 0 deletions

View file

@ -1840,6 +1840,35 @@ class AIAgent:
return detail
return f"{detail}{hint}"
@staticmethod
def _coerce_api_error_detail(value: Any) -> str:
"""Return a display-safe string for structured provider error fields."""
if isinstance(value, str):
return value
if isinstance(value, dict):
for key in ("message", "detail", "error", "code", "type"):
nested = value.get(key)
if isinstance(nested, str) and nested.strip():
return nested
for key in ("message", "detail", "error", "code", "type"):
if key in value:
nested_detail = AIAgent._coerce_api_error_detail(value[key])
if nested_detail:
return nested_detail
try:
return json.dumps(value, ensure_ascii=False, sort_keys=True)
except TypeError:
return str(value)
if isinstance(value, (list, tuple)):
parts = [
AIAgent._coerce_api_error_detail(item)
for item in value
]
return "; ".join(part for part in parts if part)
if value is None:
return ""
return str(value)
@staticmethod
def _summarize_api_error(error: Exception) -> str:
"""Extract a human-readable one-liner from an API error.
@ -1879,6 +1908,7 @@ class AIAgent:
if msg:
status_code = getattr(error, "status_code", None)
prefix = f"HTTP {status_code}: " if status_code else ""
msg = AIAgent._coerce_api_error_detail(msg)
return AIAgent._decorate_xai_entitlement_error(f"{prefix}{msg[:300]}")
# Fallback: truncate the raw string but give more room than 200 chars

View file

@ -252,6 +252,35 @@ def test_summarize_api_error_decorates_xai_body_message():
assert "X Premium+ does NOT include" in summary
def test_summarize_api_error_handles_nested_provider_message():
"""HF router may put a structured object in error.message."""
from run_agent import AIAgent
class _NestedProviderErr(Exception):
status_code = 400
body = {
"error": {
"message": {
"type": "Bad Request",
"code": "context_length_exceeded",
"message": (
"This model's maximum context length is 262144 tokens. "
"Please reduce the length of the messages."
),
"param": None,
},
"type": "invalid_request_error",
"param": None,
"code": None,
}
}
summary = AIAgent._summarize_api_error(_NestedProviderErr("400"))
assert "HTTP 400" in summary
assert "maximum context length is 262144 tokens" in summary
assert "context_length_exceeded" not in summary
def test_summarize_api_error_idempotent_for_entitlement_hint():
"""Decorating twice must not double up the hint."""
from run_agent import AIAgent