Skip to content

fix: persist interaction image encodings#237

Merged
yyiilluu merged 3 commits into
mainfrom
codex/persist-interaction-images
Jun 26, 2026
Merged

fix: persist interaction image encodings#237
yyiilluu merged 3 commits into
mainfrom
codex/persist-interaction-images

Conversation

@yyiilluu

@yyiilluu yyiilluu commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Persist base64 interaction images through SQLite storage so extraction reads can use visual context after publish.
  • Keep legacy SQLite databases compatible by adding a defaulted image_encoding column during schema migration.
  • Add focused coverage for direct reads, extraction-window reads, and prompt construction after a storage round trip.

Changes

  • SQLite storage writes and reads Interaction.image_encoding alongside existing interaction media fields.
  • SQLite DDL and migration add image_encoding TEXT NOT NULL DEFAULT ''.
  • Tests assert image encodings survive storage and appear as image_url blocks in profile extraction prompts.

Test Plan

  • uv run ruff check ...
  • uv run pyright ...
  • uv run pytest -o 'addopts=' tests/server/services/storage/test_storage_contract_profiles.py::TestInteractionCRUD::test_interaction_image_encoding_round_trips_through_extraction_reads tests/server/services/profile/test_profile_generation_service_utils.py::test_profile_extraction_prompt_keeps_image_encoding_after_storage_round_trip -q

Summary by CodeRabbit

  • New Features
    • Added support for image_encoding on interactions, including persistence and return across storage and profile-extraction flows.
    • Profile message images now generate correctly typed data:<mime>;base64,... URLs (JPEG/PNG/GIF/WebP), not just JPEG.
  • Bug Fixes
    • Prevented image_encoding from being dropped or changed during saves, schema migrations, and grouped/flat reads.
  • Tests
    • Added round-trip and contract tests to verify image_encoding preservation and correct MIME/data-URL construction, including rejection of unsupported signatures.

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

The SQLite interactions schema, persistence paths, and message construction now preserve image_encoding. Tests were updated to cover storage round-trips and MIME-aware image data URLs.

Changes

Image encoding persistence and prompt flow

Layer / File(s) Summary
Schema and row mapping
reflexio/server/services/storage/sqlite_storage/_base.py
The interaction row mapper, schema migration, and base DDL now include image_encoding.
Interaction inserts
reflexio/server/services/storage/sqlite_storage/_profiles.py
Both interaction insert branches now write image_encoding in the column list and bound values.
Image data URL construction
reflexio/server/services/service_utils.py
construct_messages_from_interactions now normalizes image_encoding into a MIME-aware data URL before emitting the final image block.
Storage contract tests
tests/server/services/storage/test_storage_contract_profiles.py
A new contract test stores image_encoding on an interaction and checks the direct, grouped, and operation-state read paths return the same value.
Prompt construction tests
tests/server/services/profile/test_profile_generation_service_utils.py, tests/server/services/test_service_utils_extended.py
The profile extraction test now uses UserActionType values, and new/updated tests verify the generated prompt preserves the image data URL and MIME type.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

Hoppy bytes in a burrow deep,
image_encoding snugly I did keep.
SQLite sparkled, prompts shone bright,
WebP and JPEG hopped into line just right.
A bunny grin: “This code feels just right!” 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: persisting interaction image encodings in storage.
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 codex/persist-interaction-images

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/server/services/profile/test_profile_generation_service_utils.py`:
- Around line 156-158: The profile generation test is hardcoding a JPEG data URL
for a PNG fixture, so update the test data to match the actual image type or
make the MIME type flow through the implementation. In
test_profile_generation_service_utils, use the real type derived from the
fixture in the assertions around image data URLs, and check the corresponding
storage/prompt construction in the profile generation path so it preserves the
MIME type instead of assuming image/jpeg.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 1f00f1a1-db10-4094-9414-072702703d5c

📥 Commits

Reviewing files that changed from the base of the PR and between 63b3a84 and fa1b218.

📒 Files selected for processing (4)
  • reflexio/server/services/storage/sqlite_storage/_base.py
  • reflexio/server/services/storage/sqlite_storage/_profiles.py
  • tests/server/services/profile/test_profile_generation_service_utils.py
  • tests/server/services/storage/test_storage_contract_profiles.py

Comment thread tests/server/services/profile/test_profile_generation_service_utils.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@reflexio/server/services/service_utils.py`:
- Around line 62-76: The helper _image_data_url_from_encoding is defaulting
unknown payloads to data:image/jpeg, which relabels non-JPEG images and breaks
round-trips. Update this path so unknown headers are not rewritten as JPEG:
either return an error/raise for unsupported image signatures, or change the
flow to carry the original MIME type through InteractionData.image_encoding and
use it here. Keep the existing sniffing logic in _image_mime_type_from_bytes,
but remove the unconditional JPEG fallback in _image_data_url_from_encoding.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 0a8a7658-e801-4ade-8c9b-462ece2a5ebf

📥 Commits

Reviewing files that changed from the base of the PR and between fa1b218 and f6cdcc2.

📒 Files selected for processing (3)
  • reflexio/server/services/service_utils.py
  • tests/server/services/profile/test_profile_generation_service_utils.py
  • tests/server/services/test_service_utils_extended.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/server/services/profile/test_profile_generation_service_utils.py

Comment thread reflexio/server/services/service_utils.py
@yyiilluu yyiilluu merged commit cc7392f into main Jun 26, 2026
1 check was pending
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