mirror of https://github.com/kortix-ai/suna.git
3.5 KiB
3.5 KiB
Double Escaping Fix - Summary of Changes
Overview
Fixed the double escaping issue where JSON content was being stored as escaped strings in JSONB columns in the database.
Root Cause
- The
add_message
method inthread_manager.py
was usingjson.dumps()
on content before inserting into JSONB columns - JSONB columns automatically handle JSON serialization, so this caused double escaping
- Other parts of the code expected JSON strings and were using
json.loads()
on data that was now properly stored as objects
Changes Made
1. Backend - thread_manager.py
File: backend/agentpress/thread_manager.py
- Removed
json.dumps()
calls in theadd_message
method - Now passes content and metadata directly to the database
# Before:
'content': json.dumps(content) if isinstance(content, (dict, list)) else content,
'metadata': json.dumps(metadata or {}),
# After:
'content': content,
'metadata': metadata or {},
2. Backend - JSON Helper Utilities
File: backend/agentpress/utils/json_helpers.py
(new)
- Created helper functions to handle both old (JSON string) and new (dict/list) formats
- Key functions:
ensure_dict()
- Ensures a value is a dict, handling both formatssafe_json_parse()
- Safely parses JSON that might already be parsedformat_for_yield()
- Formats messages for yielding with JSON string content/metadata
3. Backend - response_processor.py
File: backend/agentpress/response_processor.py
- Updated to use the new JSON helper functions
- Replaced all
json.loads()
calls withsafe_json_parse()
- Replaced all
json.dumps()
calls withto_json_string()
- All yielded messages are now formatted using
format_for_yield()
to ensure backward compatibility
Key changes:
- Line 403: Fixed metadata parsing
- Lines 190, 252: Fixed chunk content/metadata formatting
- Lines 265, 274, 384, 676, 1114: Fixed function arguments parsing
- All yield statements: Wrapped with
format_for_yield()
4. Frontend - Backward Compatibility
File: frontend/src/components/thread/utils.ts
- Updated
safeJsonParse
function to handle double-escaped JSON - Automatically detects and handles both old and new formats
- Tries a second parse if the first parse returns a JSON-like string
Migration Guide
For New Deployments
No action needed - the code will work correctly out of the box.
For Existing Deployments with Old Data
-
Option 1: Run Database Migration (Recommended)
-- Creates a backup table and fixes all messages -- See backend/migrations/fix_double_escaped_json.sql
-
Option 2: Leave Old Data As-Is
- The frontend will automatically handle both formats
- New messages will be stored correctly
- Old messages will continue to work
Testing
Backend Test
# Run: python backend/tests/test_double_escape_fix.py
# Verifies that:
# - Dict content is stored as dict (not string)
# - List content is stored as list (not string)
# - String content remains string
Frontend Compatibility
The updated safeJsonParse
function handles:
- New format:
{"key": "value"}
(proper object) - Old format:
"{\"key\": \"value\"}"
(double-escaped string) - Mixed environments during migration
Benefits
- Proper Data Storage: JSON data is stored correctly in JSONB columns
- Better Performance: Database can index and query JSON fields
- Cleaner Code: No unnecessary JSON serialization/deserialization
- Backward Compatible: Works with both old and new data formats