Skip to content

fix(client): serialize request bodies in JSON mode - #390

Merged
yyiilluu merged 1 commit into
mainfrom
fix/client-datetime-json-serialization
Jul 28, 2026
Merged

fix(client): serialize request bodies in JSON mode#390
yyiilluu merged 1 commit into
mainfrom
fix/client-datetime-json-serialization

Conversation

@yyiilluu

@yyiilluu yyiilluu commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Problem

Every request model carrying a datetime field was unusable over the client.
model_dump() leaves start_time / end_time as datetime objects, and
requests then raises before the request ever leaves the process:

TypeError: Object of type datetime is not JSON serializable

Reproducing against a live backend, on the plain kwargs path:

c.get_agent_success_evaluation_results(start_time=A, end_time=B)   # TypeError
c.get_retrieved_learning_evaluation_results(start_time=A, end_time=B)  # TypeError
c.get_requests(source="x", start_time=A, end_time=B)               # TypeError

11 request models carry the field, so this covered every time-filtered read —
get_requests, get_interactions, get_profiles, get_user_playbooks,
get_agent_playbooks, the four search_* methods, and both evaluation reads —
on the kwargs path and the request-object path alike.

Fix

All 51 json=<model>.model_dump() call sites become
model_dump(mode="json"). Datetimes render as ISO strings; every other field
type serializes identically, so the wire format is otherwise unchanged.

params= call sites were checked and are plain str/int dicts — no models,
nothing to change there.

Test change worth a look

test_get_retrieved_learning_evaluation_results_posts_filters asserted the
buggy payload — raw datetime objects in the JSON body. That expectation
is why the unserializable body went unnoticed, so it is corrected rather than
worked around. The body it described could never have been sent.

New tests

tests/client/test_request_serialization.py:

  • Each time-filtered read is invoked and its body passed through json.dumps.
    This is the assertion a mock-based call check structurally cannot make, since
    the mock never serializes — which is how the bug survived existing coverage.
  • An AST guard that fails on any new json= call site omitting mode="json",
    so the class cannot return one method at a time.

All 9 fail without the fix and pass with it (verified by reverting the source
change and re-running).

Verification

  • tests/client/: 68 passed
  • Full unit tier: 4005 passed, 2 failed
  • Both failures (test_extraction_eval.py::test_live_extraction_provider_returns_canned_items,
    test_llm_mock_schema_compliance.py::...[playbook_extraction-playbook_extraction])
    reproduce on a clean tree — pre-existing, unrelated to serialization
  • ruff + pyright clean on all touched files

Summary by CodeRabbit

  • Bug Fixes

    • Fixed request serialization so date and time filters are sent in JSON-compatible ISO 8601 format.
    • Improved compatibility for API operations involving searches, retrievals, evaluations, deletions, and other requests that include date/time values.
  • Tests

    • Added coverage to verify request payloads are valid JSON and preserve date/time values accurately.

Every request model with a `datetime` field was unusable: `model_dump()`
leaves `start_time` / `end_time` as `datetime` objects, and `requests` then
raises `TypeError: Object of type datetime is not JSON serializable` before
the request leaves the process.

This hit every time-filtered read — `get_requests`, `get_interactions`,
`get_profiles`, `get_user_playbooks`, `get_agent_playbooks`, the four
`search_*` methods, and both evaluation reads — on the kwargs path and the
request-object path alike. 11 request models carry the field.

Switch all 51 `json=<model>.model_dump()` call sites to
`model_dump(mode="json")`. Datetimes become ISO strings; every other field
type serializes identically, so the wire format is otherwise unchanged.

`test_get_retrieved_learning_evaluation_results_posts_filters` asserted the
buggy payload (raw `datetime` objects in the body) — that expectation is why
the unserializable body went unnoticed, so it is corrected here rather than
worked around.

Adds `tests/client/test_request_serialization.py`:
- every time-filtered read is called and its body passed through
  `json.dumps`, which is the assertion a mock-based call check cannot make
  because the mock never serializes;
- an AST guard failing on any new `json=` call site that omits
  `mode="json"`, so the bug class cannot come back one method at a time.

All 9 fail without the fix and pass with it.
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 13f6ef5d-f762-4b8f-9a62-7bc6fa30f547

📥 Commits

Reviewing files that changed from the base of the PR and between c509be8 and 34063a4.

📒 Files selected for processing (3)
  • reflexio/client/client.py
  • tests/client/test_evaluation_client.py
  • tests/client/test_request_serialization.py

📝 Walkthrough

Walkthrough

The client changes request-body serialization from Pydantic’s default model_dump() to model_dump(mode="json") across API methods. Tests verify JSON-safe datetime serialization, ISO timestamps, request-object behavior, and future call-site compliance.

Changes

Request serialization

Layer / File(s) Summary
Read and search request serialization
reflexio/client/client.py
Interaction, profile, playbook, evaluation, configuration, and unified search requests now send JSON-compatible Pydantic payloads.
Mutation and job request serialization
reflexio/client/client.py
Deletion, creation, update, generation, upgrade, aggregation, bulk deletion, and user-data clearing requests now use JSON-mode serialization.
Serialization regression coverage
tests/client/test_request_serialization.py, tests/client/test_evaluation_client.py
Tests validate JSON-safe datetime fields, ISO-formatted timestamps, request-object serialization, and JSON-mode usage at all request-body call sites.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: client request bodies are now serialized in JSON mode.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/client-datetime-json-serialization

Comment @coderabbitai help to get the list of available commands.

@yyiilluu
yyiilluu merged commit c690e7d into main Jul 28, 2026
1 check passed
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