mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-31 19:16:29 +00:00
fix(state): parse tool_calls JSON string before re-serializing
_insert_message_rows and append_message both do json.dumps(tool_calls)
to serialize the field for SQLite storage. But when tool_calls arrives
as a JSON string (from import_sessions / export_session, which store it
as TEXT), json.dumps double-encodes it — wrapping the already-serialized
string in quotes and escaping the inner quotes.
When _rows_to_conversation later does json.loads(row['tool_calls']),
the double-encoded string parses back to a plain string (not a list).
_history_to_messages then iterates this string character-by-character,
calling tc.get('function', {}) on each char — 'str' object has no
attribute 'get'.
This was a pre-existing bug (on main), but only triggered by the
import_sessions path (the live agent always passes tool_calls as a
Python list). The e2e error-banner guard caught it via the 'Resume
failed' notification toast.
Fix: in both append_message and _insert_message_rows, parse tool_calls
with json.loads first if it's a string, then re-serialize.
This commit is contained in:
parent
464a0645e7
commit
a84ffb1ba8
1 changed files with 17 additions and 0 deletions
|
|
@ -4203,6 +4203,14 @@ class SessionDB:
|
|||
json.dumps(codex_message_items)
|
||||
if codex_message_items else None
|
||||
)
|
||||
# tool_calls may arrive as a Python list (from the live agent) or
|
||||
# as a JSON string (from import/export). Parse first to avoid
|
||||
# double-encoding.
|
||||
if isinstance(tool_calls, str):
|
||||
try:
|
||||
tool_calls = json.loads(tool_calls)
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
tool_calls = []
|
||||
tool_calls_json = json.dumps(tool_calls) if tool_calls else None
|
||||
# Multimodal content (list of parts) must be JSON-encoded: sqlite3
|
||||
# cannot bind list/dict parameters directly.
|
||||
|
|
@ -4311,6 +4319,15 @@ class SessionDB:
|
|||
codex_message_items_json = (
|
||||
json.dumps(codex_message_items) if codex_message_items else None
|
||||
)
|
||||
# tool_calls may arrive as a Python list (from the live agent)
|
||||
# or as a JSON string (from import_sessions / export_session,
|
||||
# which store it as TEXT). json.dumps on an already-serialized
|
||||
# string double-encodes it, so parse first.
|
||||
if isinstance(tool_calls, str):
|
||||
try:
|
||||
tool_calls = json.loads(tool_calls)
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
tool_calls = []
|
||||
tool_calls_json = json.dumps(tool_calls) if tool_calls else None
|
||||
# Accept either `platform_message_id` (new explicit name) or
|
||||
# `message_id` (yuanbao's existing convention on message dicts).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue