Skip to content

Conversation

@jespo2021
Copy link

@jespo2021 jespo2021 commented Dec 13, 2025

Summary

Fixes memory curation failing silently due to JSON parsing errors and incorrect CLI response extraction.

Changes

  • Fix JSON syntax in curation prompt: Changed example JSON from Python dict syntax (single quotes) to valid JSON (double quotes)
  • Fix CLI response extraction: Handle Claude Code's nested message format message["message"]["content"] instead of message["content"]
  • Add fallback JSON parsing: Use ast.literal_eval when LLM returns Python dict syntax despite instructions
  • Implement real stats: /memory/stats now returns actual counts instead of placeholder zeros

Root Cause

The curator was returning 0 memories because:

  1. Prompt examples used Python syntax: The curation prompt showed 'key': 'value' examples, so Claude followed that format and returned invalid JSON
  2. Wrong extraction path: Claude Code CLI outputs {"type":"assistant","message":{"content":[...]}} but the code looked for message["content"] directly
  3. No error recovery: When JSON parsing failed, it silently returned empty results

Testing

Regression tests added to verify the fixes:

  • test_cli_response_extraction.py: Validates nested Claude Code message format handling
  • test_json_parsing_fallback.py: Validates ast.literal_eval fallback for single-quote JSON
  • test_storage_stats.py: Validates get_stats() returns real database counts

All tests verified to fail on main branch and pass on this branch.

# Run tests
uv run pytest tests/ -v

# Before fix (on main)
3 failed

# After fix (on this branch)
3 passed

🤖 Generated with Claude Code

- Fix JSON syntax in curation prompt (single quotes → double quotes)
- Fix CLI response extraction for Claude Code nested message format
- Add ast.literal_eval fallback for non-compliant LLM responses
- Implement real stats gathering in /memory/stats endpoint
- Add get_stats() method to storage layer

The curator was failing because:
1. Prompt examples used Python dict syntax, causing Claude to return
   invalid JSON with single quotes
2. Claude Code CLI outputs {"type":"assistant","message":{"content":[...]}}
   but extraction looked for message["content"] instead of
   message["message"]["content"]
3. No fallback when LLM ignored format instructions

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@jespo2021
Copy link
Author

I had an issue while testing on my Mac and hope this helps

jespo2021 added a commit to jespo2021/memory that referenced this pull request Dec 13, 2025
Tests added:
- test_cli_response_extraction: Validates nested Claude Code message format handling (message.message.content)
- test_json_parsing_fallback: Validates ast.literal_eval fallback for single-quote JSON from LLM
- test_storage_stats: Validates get_stats() returns real database counts

Code changes:
- Formatted all source files with black
- Fixed ruff linting issues (unused imports, import ordering, trailing whitespace)
- Removed f-string prefix from strings without placeholders
- Removed unused variable assignments

All tests verified to fail on main branch and pass on this branch.
Tests added:
- test_cli_response_extraction: Validates nested Claude Code message format handling (message.message.content)
- test_json_parsing_fallback: Validates ast.literal_eval fallback for single-quote JSON from LLM
- test_storage_stats: Validates get_stats() returns real database counts

All tests verified to fail on main branch and pass on this branch.
@jespo2021 jespo2021 force-pushed the fix/curator-json-parsing branch from 2fd3d92 to 7894a1d Compare December 13, 2025 20:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant