mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-26 06:01:49 +00:00
fix(model_tools): log warnings for failed JSON-array coercion
When _coerce_json fails to parse a string as JSON or parses to the wrong type, log a clear WARNING instead of silently returning the original value. When coerce_tool_args wraps a bare string into a single-element list AND the string looks like a JSON array (starts with '['), warn that the model likely emitted a JSON-encoded string instead of a native array. This improves diagnostics for the open-weight model output drift described in #21933 (JSON-array-as-string), as well as any other tool whose array-typed argument arrives stringified through handle_function_call. Note: delegate_task does NOT go through coerce_tool_args (it is in _AGENT_LOOP_TOOLS and dispatched directly from run_agent.py with raw function_args from json.loads). The actual delegate_task fix for #21933 is the previous commit. These logging changes apply to all other array-typed arguments coerced via the shared pipeline. Salvaged from PR #22092.
This commit is contained in:
parent
326ca754ad
commit
7330183d08
1 changed files with 21 additions and 1 deletions
|
|
@ -550,6 +550,16 @@ def coerce_tool_args(tool_name: str, args: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
# nullable "null" → None).
|
# nullable "null" → None).
|
||||||
args[key] = coerced
|
args[key] = coerced
|
||||||
continue
|
continue
|
||||||
|
# If the string looks like a JSON array but _coerce_value
|
||||||
|
# failed to parse it, warn clearly instead of silently wrapping.
|
||||||
|
if value.strip().startswith("["):
|
||||||
|
logger.warning(
|
||||||
|
"coerce_tool_args: %s.%s looks like a JSON array string "
|
||||||
|
"but could not be parsed — model may have emitted a "
|
||||||
|
"JSON-encoded string instead of a native array. "
|
||||||
|
"Falling back to single-element list.",
|
||||||
|
tool_name, key,
|
||||||
|
)
|
||||||
args[key] = [value]
|
args[key] = [value]
|
||||||
logger.info(
|
logger.info(
|
||||||
"coerce_tool_args: wrapped bare string in list for %s.%s",
|
"coerce_tool_args: wrapped bare string in list for %s.%s",
|
||||||
|
|
@ -637,7 +647,12 @@ def _coerce_json(value: str, expected_python_type: type):
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
parsed = json.loads(value)
|
parsed = json.loads(value)
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError) as exc:
|
||||||
|
logger.warning(
|
||||||
|
"coerce_tool_args: failed to parse string as JSON for expected type %s: %s",
|
||||||
|
expected_python_type.__name__,
|
||||||
|
exc,
|
||||||
|
)
|
||||||
return value
|
return value
|
||||||
if isinstance(parsed, expected_python_type):
|
if isinstance(parsed, expected_python_type):
|
||||||
logger.debug(
|
logger.debug(
|
||||||
|
|
@ -645,6 +660,11 @@ def _coerce_json(value: str, expected_python_type: type):
|
||||||
expected_python_type.__name__,
|
expected_python_type.__name__,
|
||||||
)
|
)
|
||||||
return parsed
|
return parsed
|
||||||
|
logger.warning(
|
||||||
|
"coerce_tool_args: JSON-parsed value is %s, expected %s — skipping coercion",
|
||||||
|
type(parsed).__name__,
|
||||||
|
expected_python_type.__name__,
|
||||||
|
)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue