Spaces:
Paused
Paused
Mirrowel commited on
Commit Β·
4d4a198
1
Parent(s): 0ea3b2d
fix(antigravity): π handle malformed double-encoded JSON responses
Browse filesAntigravity sometimes returns malformed JSON strings with extra trailing characters (e.g., '[{...}]}' instead of '[{...}]'). This enhancement extends the JSON parsing logic to automatically detect and correct such malformations by:
- Detecting JSON-like strings that don't have proper closing delimiters
- Finding the last valid closing bracket/brace and truncating extra characters
- Logging warnings when auto-correction is applied for debugging purposes
- Recursively parsing the corrected JSON structures
This prevents parsing failures when Antigravity returns double-encoded or malformed JSON in tool arguments.
src/rotator_library/providers/antigravity_provider.py
CHANGED
|
@@ -168,6 +168,9 @@ def _recursively_parse_json_strings(obj: Any) -> Any:
|
|
| 168 |
|
| 169 |
Antigravity sometimes returns tool arguments with JSON-stringified values:
|
| 170 |
{"files": "[{...}]"} instead of {"files": [{...}]}.
|
|
|
|
|
|
|
|
|
|
| 171 |
"""
|
| 172 |
if isinstance(obj, dict):
|
| 173 |
return {k: _recursively_parse_json_strings(v) for k, v in obj.items()}
|
|
@@ -175,13 +178,49 @@ def _recursively_parse_json_strings(obj: Any) -> Any:
|
|
| 175 |
return [_recursively_parse_json_strings(item) for item in obj]
|
| 176 |
elif isinstance(obj, str):
|
| 177 |
stripped = obj.strip()
|
| 178 |
-
if
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 185 |
return obj
|
| 186 |
|
| 187 |
|
|
|
|
| 168 |
|
| 169 |
Antigravity sometimes returns tool arguments with JSON-stringified values:
|
| 170 |
{"files": "[{...}]"} instead of {"files": [{...}]}.
|
| 171 |
+
|
| 172 |
+
Additionally handles malformed double-encoded JSON where Antigravity
|
| 173 |
+
returns strings like '[{...}]}' (extra trailing '}').
|
| 174 |
"""
|
| 175 |
if isinstance(obj, dict):
|
| 176 |
return {k: _recursively_parse_json_strings(v) for k, v in obj.items()}
|
|
|
|
| 178 |
return [_recursively_parse_json_strings(item) for item in obj]
|
| 179 |
elif isinstance(obj, str):
|
| 180 |
stripped = obj.strip()
|
| 181 |
+
# Check if it looks like JSON (starts with { or [)
|
| 182 |
+
if stripped and stripped[0] in ('{', '['):
|
| 183 |
+
# Try standard parsing first
|
| 184 |
+
if (stripped.startswith('{') and stripped.endswith('}')) or \
|
| 185 |
+
(stripped.startswith('[') and stripped.endswith(']')):
|
| 186 |
+
try:
|
| 187 |
+
parsed = json.loads(obj)
|
| 188 |
+
return _recursively_parse_json_strings(parsed)
|
| 189 |
+
except (json.JSONDecodeError, ValueError):
|
| 190 |
+
pass
|
| 191 |
+
|
| 192 |
+
# Handle malformed JSON: array that doesn't end with ]
|
| 193 |
+
# e.g., '[{"path": "..."}]}' instead of '[{"path": "..."}]'
|
| 194 |
+
if stripped.startswith('[') and not stripped.endswith(']'):
|
| 195 |
+
try:
|
| 196 |
+
# Find the last ] and truncate there
|
| 197 |
+
last_bracket = stripped.rfind(']')
|
| 198 |
+
if last_bracket > 0:
|
| 199 |
+
cleaned = stripped[:last_bracket+1]
|
| 200 |
+
parsed = json.loads(cleaned)
|
| 201 |
+
lib_logger.warning(
|
| 202 |
+
f"Auto-corrected malformed JSON string: "
|
| 203 |
+
f"truncated {len(stripped) - len(cleaned)} extra chars"
|
| 204 |
+
)
|
| 205 |
+
return _recursively_parse_json_strings(parsed)
|
| 206 |
+
except (json.JSONDecodeError, ValueError):
|
| 207 |
+
pass
|
| 208 |
+
|
| 209 |
+
# Handle malformed JSON: object that doesn't end with }
|
| 210 |
+
if stripped.startswith('{') and not stripped.endswith('}'):
|
| 211 |
+
try:
|
| 212 |
+
# Find the last } and truncate there
|
| 213 |
+
last_brace = stripped.rfind('}')
|
| 214 |
+
if last_brace > 0:
|
| 215 |
+
cleaned = stripped[:last_brace+1]
|
| 216 |
+
parsed = json.loads(cleaned)
|
| 217 |
+
lib_logger.warning(
|
| 218 |
+
f"Auto-corrected malformed JSON string: "
|
| 219 |
+
f"truncated {len(stripped) - len(cleaned)} extra chars"
|
| 220 |
+
)
|
| 221 |
+
return _recursively_parse_json_strings(parsed)
|
| 222 |
+
except (json.JSONDecodeError, ValueError):
|
| 223 |
+
pass
|
| 224 |
return obj
|
| 225 |
|
| 226 |
|