Skip to content

Ship Reflex integration as xy[reflex] - #408

Merged
Alek99 merged 10 commits into
mainfrom
agent/ship-reflex-as-xy-extra
Jul 31, 2026
Merged

Ship Reflex integration as xy[reflex]#408
Alek99 merged 10 commits into
mainfrom
agent/ship-reflex-as-xy-extra

Conversation

@Alek99

@Alek99 Alek99 commented Jul 31, 2026

Copy link
Copy Markdown
Member

Summary

  • move the reflex_xy adapter source into the main xy distribution
  • add a reflex extra with reflex>=0.9.6, while keeping plain xy framework-free
  • remove the separate reflex-xy package metadata, lockfile, release workflow, version gate, and distribution verifier
  • update CI, release smoke checks, artifact verification, docs, examples, specs, and dependency locks for xy[reflex]
  • make the Reflex websocket smoke deterministic by scrolling the target chart into view and selecting a real point from its pick buffer

Why

The Reflex integration is owned and maintained with XY, so publishing it as a separate distribution creates an unnecessary third-party-looking package boundary and allows the adapter, browser client, and core library to drift. Shipping the adapter in every xy wheel keeps those pieces version-coherent; the extra only selects the supported Reflex dependency floor.

User impact

Reflex users install:

uv add "xy[reflex]"
# or
python -m pip install "xy[reflex]"

The Python import remains import reflex_xy. Existing users no longer need a separately versioned reflex-xy distribution. Users who install plain xy do not acquire Reflex.

Validation

  • full test suite: 3760 passed, 108 skipped
  • docs unit suite: 103 passed, 1 xfailed
  • docs app production compile and browser render; all sitemap, Markdown asset, and HTML route validators passed
  • canonical Reflex showcase production smoke: one shared backend websocket, binary chart rendering, density drilldown, exact-point hover round-trip, and streaming appends
  • fresh isolated app installed only from the built xy wheel with [reflex]: matching xy/reflex_xy versions, no reflex-xy distribution, successful production compile, one mounted live chart, and nonblank rendered pixels
  • final wheel and sdist rebuilt and passed their artifact verifiers
  • ruff check ., ruff format --check ., workflow verification, and git diff --check

Review in cubic

Summary by CodeRabbit

  • New Features
    • Bundled the Reflex integration directly with XY.
    • Added static and live charts, streaming updates, selections, view changes, hover, and click events.
    • Added the xy[reflex] installation option with compatible Reflex dependency selection.
  • Bug Fixes
    • Improved handling of stale updates, reconnects, resynchronization, and concurrent payload generation.
  • Documentation
    • Updated installation, deployment, examples, and API guidance.
  • Release & Packaging
    • XY and its Reflex integration now ship and version together.
  • Tests
    • Expanded integration and artifact validation.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR bundles the Reflex integration into xy through the xy[reflex] extra. It packages and verifies reflex_xy, removes the independent release workflow, updates runtime version handling, and revises documentation, examples, specifications, and tests.

Changes

Bundled Reflex integration

Layer / File(s) Summary
Package and installation integration
pyproject.toml, python/reflex_xy/..., README.md, docs/..., examples/reflex/...
reflex_xy is included in xy wheels and sdists. The xy[reflex] extra provides reflex>=0.9.6. Installation and version guidance now use the bundled integration.
Reflex runtime and chart integration
python/reflex_xy/...
The integration adds app setup, figure variables, token handling, registry generations, payload assets, Socket.IO versioning, chart components, typed events, selections, and live client checks.
Release workflow and artifact verification
.github/workflows/..., scripts/...
CI and release checks install and import reflex_xy, verify version alignment, and validate bundled files and metadata. Independent Reflex release support is removed.
Specifications and release documentation
spec/..., CHANGELOG.md, CLAUDE.md
Documentation describes one xy release line, bundled reflex_xy files, the xy[reflex] extra, updated paths, and artifact requirements.
Tests and fixtures
tests/...
Tests cover runtime generations, payload concurrency, bundled metadata, required assets, release validation, local setup, and updated integration paths.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

  • reflex-dev/xy#260: The bundled integration and updated deployment guidance revise the Reflex integration introduced there.
  • reflex-dev/xy#275: Both changes align reflex_xy.__version__ with xy distribution metadata.
  • reflex-dev/xy#277: This PR removes the independent Reflex release infrastructure introduced there.

Suggested reviewers: masenf, farhanaliraza

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.91% 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 and concisely describes the main change: bundling the Reflex integration under the xy[reflex] extra.
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 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/ship-reflex-as-xy-extra

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

@codspeed-hq

codspeed-hq Bot commented Jul 31, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 109 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing agent/ship-reflex-as-xy-extra (db80d0f) with main (a2f2976)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@Alek99
Alek99 marked this pull request as ready for review July 31, 2026 06:29

@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: 12

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
spec/design/reflex-shaped-api.md (1)

556-581: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Align this section with the shipped integration.

These lines describe bundled reflex_xy and xy[reflex], but the same document still presents the adapter as future work and recommends adding a separate adapter package. Update the surrounding section so it describes the current bundled integration. Mark smaller-dependency or separate-package work as future work only.

As per coding guidelines, the spec/ directory must remain current with relevant code, configuration, build, and release changes.

🤖 Prompt for 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.

In `@spec/design/reflex-shaped-api.md` around lines 556 - 581, Update the
surrounding design section to present the bundled reflex_xy integration and
xy[reflex] extra as the current shipped implementation, removing stale
future-work language and separate-adapter-package recommendations. Retain
smaller dependency surfaces or extracting a separate package only as explicitly
identified future work, and ensure the documented behavior matches the relevant
code, configuration, build, and release metadata.

Source: Coding guidelines

🧹 Nitpick comments (2)
python/reflex_xy/component.py (1)

205-220: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider removing the implicit dependency on chart initializing _component_cls.

_facet_grid calls _component_cls.create(...) but never initializes _component_cls. Today the only caller is chart, which builds the class first, so the code is correct. Any new caller of _facet_grid would raise AttributeError: 'NoneType' object has no attribute 'create'. Extract the lazy initialization into a small helper and call it in both places.

♻️ Proposed helper
+def _component() -> Any:
+    global _component_cls
+    if _component_cls is None:
+        _component_cls = _build_component_cls()
+    return _component_cls

Then use _component().create(...) in _facet_grid and in chart.

🤖 Prompt for 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.

In `@python/reflex_xy/component.py` around lines 205 - 220, Extract lazy
_component_cls initialization into a shared _component() helper, then replace
direct _component_cls.create calls with _component().create in both _facet_grid
and chart. Preserve the existing class construction behavior while ensuring
_facet_grid works independently of chart initialization.
python/reflex_xy/assets/XYChart.jsx (1)

361-380: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Consider aborting the static payload fetch on unmount.

The cancelled flag suppresses the result, but the request keeps running after unmount. An AbortController releases the connection immediately, which matters for pages that mount and unmount many static charts.

♻️ Proposed change
     let cancelled = false;
+    const controller = new AbortController();
     const handleViewChange = (event) => cbRef.current.onViewChange?.(event.detail);
     el.addEventListener("xy:view_change", handleViewChange);
-    fetch(src)
+    fetch(src, { signal: controller.signal })
       .then((resp) => {
       .catch((err) => {
-        if (!cancelled) console.warn(`xy: static payload failed for ${src}`, err);
+        if (!cancelled) console.warn(`xy: static payload failed for ${src}`, err);
       });
     return () => {
       cancelled = true;
+      controller.abort();
🤖 Prompt for 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.

In `@python/reflex_xy/assets/XYChart.jsx` around lines 361 - 380, Update the
static payload fetch flow in the visible effect around fetch(src) to create an
AbortController, pass its signal to fetch, and abort it during unmount cleanup.
Preserve the existing cancelled checks and ensure abort errors remain safely
handled by the current catch path.
🤖 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 @.github/workflows/release.yml:
- Around line 127-129: Update the smoke-test Python commands in the release
workflow to import importlib.metadata and assert that reflex_xy.__version__
equals importlib.metadata.version("xy"), while preserving the existing native
backend assertion and output behavior in both Unix and Windows fallbacks.

In `@docs/integrations/reflex.md`:
- Around line 20-21: Update the installation text in the Reflex integration
documentation to say that the extra installs the supported Reflex dependency
floor, reflecting the metadata constraint reflex>=0.9.6 rather than implying a
bounded compatible version. Revise the warning around the package’s PyPI
availability and adapter tag requirements to describe the bundled distribution
accurately, removing claims that it has no PyPI release or requires a matching
adapter tag.

In `@python/reflex_xy/events.py`:
- Around line 38-206: Move all numeric semantic-event payloads in
python/reflex_xy/events.py:38-206—including point coordinates, selection
bounds/polygons, row IDs, row projections, and counts—into a defined binary
event ABI, leaving only non-numeric metadata and attachment references in JSON;
update PointData, ScreenPoint, DataBounds, SelectionPayload, and the event
TypedDicts consistently. In python/reflex_xy/selections.py:17-19 and 37-42,
decode the binary selection geometry before calling select_range or
select_polygon, and update resolve_selection() to consume the binary IDs, rows,
and counts while preserving truncation and clear-selection behavior.

In `@python/reflex_xy/namespace.py`:
- Around line 153-167: Add a FigureRegistry operation that atomically snapshots
each entry’s figure and version under the registry mutex, coordinated with
publish. Update on_sub and the other affected handlers to use that snapshot for
payload building and message processing instead of reading entry.figure and
entry.version independently. Before emitting any interaction reply, compare the
current registry version with the captured version and discard the reply when
they differ.
- Around line 132-141: Update on_connect to validate the query-string token
through Reflex’s server-side session manager before calling save_session. Reject
the connection when the token is missing or validation fails, and only store the
validated token for authenticated connections; use the existing
session-validation symbol and connection rejection mechanism already available
in the namespace.

In `@python/reflex_xy/payload_asset.py`:
- Around line 76-82: Update the temporary path construction in the asset-writing
block around dest and tmp so each writer gets a unique filename, using the
process ID plus a random or otherwise collision-resistant suffix. Keep the
existing write_bytes and replace flow, ensuring concurrent writers never share
the same temporary file while publishing the identical final dest.

In `@python/reflex_xy/registry.py`:
- Around line 111-127: Synchronize figure replacement in publish with
entry.lock, using the same generation-safe path as payload construction and
append mutation. Keep figure replacement, version increment, payload or delta
construction, and version capture coordinated so each emitted message references
the exact figure or delta used to build it, preventing stale figures or
incompatible deltas.

In `@python/reflex_xy/state_bridge.py`:
- Around line 63-65: Update the chart conversion flow around _figure_of so its
result is validated as a Figure before publication. If the converted value is
invalid, return None or raise the established controlled builder error; preserve
the existing None handling and only publish valid Figure instances.

In `@scripts/verify_sdist.py`:
- Around line 257-274: Require exactly one valid Reflex requirement for the
reflex extra in scripts/verify_sdist.py:257-274 and
scripts/verify_wheel.py:202-224, rejecting duplicate or conflicting constraints
while preserving the existing minimum-version validation. Add conflicting
second-Reflex-requirement cases in tests/test_verify_sdist.py:231-248 and
tests/test_verify_wheel.py:279-296 to verify both artifact verifiers reject the
metadata.

In `@spec/api/export.md`:
- Line 51: Update the user-facing wording in the export documentation by
replacing “kernel-lessly” with “without a kernel,” while preserving the
surrounding statement and meaning.

In `@spec/process/production-readiness.md`:
- Around line 386-390: Update the wheel verification checklist to apply
scripts/verify_wheel.py --expect-native only to native wheels, and add a
separate fallback-wheel verification using --expect-pure. Keep the release
checks aligned with the native and fallback gates described earlier in the
document.

In `@tests/reflex_adapter/conftest.py`:
- Line 5: Replace the malformed comment text “importorskips” in the Reflex
dependency-rule note with clear wording that directly states these tests are
skipped when the Reflex dependency cannot be imported.

---

Outside diff comments:
In `@spec/design/reflex-shaped-api.md`:
- Around line 556-581: Update the surrounding design section to present the
bundled reflex_xy integration and xy[reflex] extra as the current shipped
implementation, removing stale future-work language and separate-adapter-package
recommendations. Retain smaller dependency surfaces or extracting a separate
package only as explicitly identified future work, and ensure the documented
behavior matches the relevant code, configuration, build, and release metadata.

---

Nitpick comments:
In `@python/reflex_xy/assets/XYChart.jsx`:
- Around line 361-380: Update the static payload fetch flow in the visible
effect around fetch(src) to create an AbortController, pass its signal to fetch,
and abort it during unmount cleanup. Preserve the existing cancelled checks and
ensure abort errors remain safely handled by the current catch path.

In `@python/reflex_xy/component.py`:
- Around line 205-220: Extract lazy _component_cls initialization into a shared
_component() helper, then replace direct _component_cls.create calls with
_component().create in both _facet_grid and chart. Preserve the existing class
construction behavior while ensuring _facet_grid works independently of chart
initialization.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 522321d0-e1ab-4f9c-9f27-abaa3e094c27

📥 Commits

Reviewing files that changed from the base of the PR and between d505ef5 and ef535cb.

⛔ Files ignored due to path filters (4)
  • docs/app/reflex.lock/bun.lock is excluded by !**/*.lock
  • docs/app/uv.lock is excluded by !**/*.lock
  • python/reflex-xy/uv.lock is excluded by !**/*.lock
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (84)
  • .github/workflows/ci.yml
  • .github/workflows/release-reflex-xy.yml
  • .github/workflows/release.yml
  • CHANGELOG.md
  • CLAUDE.md
  • Makefile
  • README.md
  • docs/advanced/runtime-and-deployment.md
  • docs/api-reference/events-and-callbacks.md
  • docs/app/pyproject.toml
  • docs/app/reflex.lock/package.json
  • docs/app/rxconfig.py
  • docs/app/tests/test_docs_site.py
  • docs/app/xy_docs/api_reference.py
  • docs/app/xy_docs/demos/benchmark_charts.py
  • docs/app/xy_docs/demos/xy_sdf_plots.py
  • docs/app/xy_docs/playground.py
  • docs/guides/deployment-recipes.md
  • docs/integrations/index.md
  • docs/integrations/reflex.md
  • docs/overview/installation.md
  • examples/reflex/README.md
  • examples/reflex/assets/.gitkeep
  • examples/reflex/pyproject.toml
  • examples/reflex/rxconfig.py
  • examples/reflex/xy_reflex_demo/__init__.py
  • examples/reflex/xy_reflex_demo/xy_reflex_demo.py
  • pyproject.toml
  • python/reflex-xy/CHANGELOG.md
  • python/reflex-xy/README.md
  • python/reflex-xy/pyproject.toml
  • python/reflex_xy/__init__.py
  • python/reflex_xy/app.py
  • python/reflex_xy/assets/XYChart.jsx
  • python/reflex_xy/assets/__init__.py
  • python/reflex_xy/component.py
  • python/reflex_xy/events.py
  • python/reflex_xy/namespace.py
  • python/reflex_xy/payload_asset.py
  • python/reflex_xy/registry.py
  • python/reflex_xy/selections.py
  • python/reflex_xy/state_bridge.py
  • python/reflex_xy/tokens.py
  • python/reflex_xy/vars.py
  • scripts/check_release_version.py
  • scripts/reflex_ws_smoke.py
  • scripts/verify_ci_workflow.py
  • scripts/verify_reflex_xy_dist.py
  • scripts/verify_sdist.py
  • scripts/verify_wheel.py
  • spec/README.md
  • spec/api/chart-roadmap.md
  • spec/api/export.md
  • spec/api/interaction.md
  • spec/design/chart-grammar.md
  • spec/design/reflex-integration.md
  • spec/design/reflex-shaped-api.md
  • spec/design/renderer-architecture.md
  • spec/design/view-state.md
  • spec/design/wire-protocol.md
  • spec/process/contributing.md
  • spec/process/production-readiness.md
  • tests/reflex_adapter/__init__.py
  • tests/reflex_adapter/conftest.py
  • tests/reflex_adapter/test_assets.py
  • tests/reflex_adapter/test_async_figure_var.py
  • tests/reflex_adapter/test_component.py
  • tests/reflex_adapter/test_figure_var.py
  • tests/reflex_adapter/test_payload_asset.py
  • tests/reflex_adapter/test_registry.py
  • tests/reflex_adapter/test_selections.py
  • tests/reflex_adapter/test_socket_data_plane.py
  • tests/reflex_adapter/test_state_bridge.py
  • tests/reflex_adapter/test_tokens.py
  • tests/reflex_adapter/test_view_state_push.py
  • tests/test_check_release_version.py
  • tests/test_dependencies.py
  • tests/test_payload_update_rehome.py
  • tests/test_tailwind_root_customization.py
  • tests/test_verify_ci_workflow.py
  • tests/test_verify_local.py
  • tests/test_verify_reflex_xy_dist.py
  • tests/test_verify_sdist.py
  • tests/test_verify_wheel.py
💤 Files with no reviewable changes (8)
  • docs/app/reflex.lock/package.json
  • .github/workflows/release-reflex-xy.yml
  • python/reflex-xy/README.md
  • python/reflex-xy/CHANGELOG.md
  • python/reflex-xy/pyproject.toml
  • scripts/verify_reflex_xy_dist.py
  • tests/test_verify_ci_workflow.py
  • tests/test_verify_reflex_xy_dist.py

Comment thread .github/workflows/release.yml Outdated
Comment thread docs/integrations/reflex.md Outdated
Comment thread scripts/verify_sdist.py Outdated
Comment thread spec/api/export.md Outdated
Comment thread spec/process/production-readiness.md Outdated
Comment thread tests/reflex_adapter/conftest.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.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 12

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
spec/design/reflex-shaped-api.md (1)

556-581: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Align this section with the shipped integration.

These lines describe bundled reflex_xy and xy[reflex], but the same document still presents the adapter as future work and recommends adding a separate adapter package. Update the surrounding section so it describes the current bundled integration. Mark smaller-dependency or separate-package work as future work only.

As per coding guidelines, the spec/ directory must remain current with relevant code, configuration, build, and release changes.

🤖 Prompt for 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.

In `@spec/design/reflex-shaped-api.md` around lines 556 - 581, Update the
surrounding design section to present the bundled reflex_xy integration and
xy[reflex] extra as the current shipped implementation, removing stale
future-work language and separate-adapter-package recommendations. Retain
smaller dependency surfaces or extracting a separate package only as explicitly
identified future work, and ensure the documented behavior matches the relevant
code, configuration, build, and release metadata.

Source: Coding guidelines

🧹 Nitpick comments (2)
python/reflex_xy/component.py (1)

205-220: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider removing the implicit dependency on chart initializing _component_cls.

_facet_grid calls _component_cls.create(...) but never initializes _component_cls. Today the only caller is chart, which builds the class first, so the code is correct. Any new caller of _facet_grid would raise AttributeError: 'NoneType' object has no attribute 'create'. Extract the lazy initialization into a small helper and call it in both places.

♻️ Proposed helper
+def _component() -> Any:
+    global _component_cls
+    if _component_cls is None:
+        _component_cls = _build_component_cls()
+    return _component_cls

Then use _component().create(...) in _facet_grid and in chart.

🤖 Prompt for 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.

In `@python/reflex_xy/component.py` around lines 205 - 220, Extract lazy
_component_cls initialization into a shared _component() helper, then replace
direct _component_cls.create calls with _component().create in both _facet_grid
and chart. Preserve the existing class construction behavior while ensuring
_facet_grid works independently of chart initialization.
python/reflex_xy/assets/XYChart.jsx (1)

361-380: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Consider aborting the static payload fetch on unmount.

The cancelled flag suppresses the result, but the request keeps running after unmount. An AbortController releases the connection immediately, which matters for pages that mount and unmount many static charts.

♻️ Proposed change
     let cancelled = false;
+    const controller = new AbortController();
     const handleViewChange = (event) => cbRef.current.onViewChange?.(event.detail);
     el.addEventListener("xy:view_change", handleViewChange);
-    fetch(src)
+    fetch(src, { signal: controller.signal })
       .then((resp) => {
       .catch((err) => {
-        if (!cancelled) console.warn(`xy: static payload failed for ${src}`, err);
+        if (!cancelled) console.warn(`xy: static payload failed for ${src}`, err);
       });
     return () => {
       cancelled = true;
+      controller.abort();
🤖 Prompt for 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.

In `@python/reflex_xy/assets/XYChart.jsx` around lines 361 - 380, Update the
static payload fetch flow in the visible effect around fetch(src) to create an
AbortController, pass its signal to fetch, and abort it during unmount cleanup.
Preserve the existing cancelled checks and ensure abort errors remain safely
handled by the current catch path.
🤖 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 @.github/workflows/release.yml:
- Around line 127-129: Update the smoke-test Python commands in the release
workflow to import importlib.metadata and assert that reflex_xy.__version__
equals importlib.metadata.version("xy"), while preserving the existing native
backend assertion and output behavior in both Unix and Windows fallbacks.

In `@docs/integrations/reflex.md`:
- Around line 20-21: Update the installation text in the Reflex integration
documentation to say that the extra installs the supported Reflex dependency
floor, reflecting the metadata constraint reflex>=0.9.6 rather than implying a
bounded compatible version. Revise the warning around the package’s PyPI
availability and adapter tag requirements to describe the bundled distribution
accurately, removing claims that it has no PyPI release or requires a matching
adapter tag.

In `@python/reflex_xy/events.py`:
- Around line 38-206: Move all numeric semantic-event payloads in
python/reflex_xy/events.py:38-206—including point coordinates, selection
bounds/polygons, row IDs, row projections, and counts—into a defined binary
event ABI, leaving only non-numeric metadata and attachment references in JSON;
update PointData, ScreenPoint, DataBounds, SelectionPayload, and the event
TypedDicts consistently. In python/reflex_xy/selections.py:17-19 and 37-42,
decode the binary selection geometry before calling select_range or
select_polygon, and update resolve_selection() to consume the binary IDs, rows,
and counts while preserving truncation and clear-selection behavior.

In `@python/reflex_xy/namespace.py`:
- Around line 153-167: Add a FigureRegistry operation that atomically snapshots
each entry’s figure and version under the registry mutex, coordinated with
publish. Update on_sub and the other affected handlers to use that snapshot for
payload building and message processing instead of reading entry.figure and
entry.version independently. Before emitting any interaction reply, compare the
current registry version with the captured version and discard the reply when
they differ.
- Around line 132-141: Update on_connect to validate the query-string token
through Reflex’s server-side session manager before calling save_session. Reject
the connection when the token is missing or validation fails, and only store the
validated token for authenticated connections; use the existing
session-validation symbol and connection rejection mechanism already available
in the namespace.

In `@python/reflex_xy/payload_asset.py`:
- Around line 76-82: Update the temporary path construction in the asset-writing
block around dest and tmp so each writer gets a unique filename, using the
process ID plus a random or otherwise collision-resistant suffix. Keep the
existing write_bytes and replace flow, ensuring concurrent writers never share
the same temporary file while publishing the identical final dest.

In `@python/reflex_xy/registry.py`:
- Around line 111-127: Synchronize figure replacement in publish with
entry.lock, using the same generation-safe path as payload construction and
append mutation. Keep figure replacement, version increment, payload or delta
construction, and version capture coordinated so each emitted message references
the exact figure or delta used to build it, preventing stale figures or
incompatible deltas.

In `@python/reflex_xy/state_bridge.py`:
- Around line 63-65: Update the chart conversion flow around _figure_of so its
result is validated as a Figure before publication. If the converted value is
invalid, return None or raise the established controlled builder error; preserve
the existing None handling and only publish valid Figure instances.

In `@scripts/verify_sdist.py`:
- Around line 257-274: Require exactly one valid Reflex requirement for the
reflex extra in scripts/verify_sdist.py:257-274 and
scripts/verify_wheel.py:202-224, rejecting duplicate or conflicting constraints
while preserving the existing minimum-version validation. Add conflicting
second-Reflex-requirement cases in tests/test_verify_sdist.py:231-248 and
tests/test_verify_wheel.py:279-296 to verify both artifact verifiers reject the
metadata.

In `@spec/api/export.md`:
- Line 51: Update the user-facing wording in the export documentation by
replacing “kernel-lessly” with “without a kernel,” while preserving the
surrounding statement and meaning.

In `@spec/process/production-readiness.md`:
- Around line 386-390: Update the wheel verification checklist to apply
scripts/verify_wheel.py --expect-native only to native wheels, and add a
separate fallback-wheel verification using --expect-pure. Keep the release
checks aligned with the native and fallback gates described earlier in the
document.

In `@tests/reflex_adapter/conftest.py`:
- Line 5: Replace the malformed comment text “importorskips” in the Reflex
dependency-rule note with clear wording that directly states these tests are
skipped when the Reflex dependency cannot be imported.

---

Outside diff comments:
In `@spec/design/reflex-shaped-api.md`:
- Around line 556-581: Update the surrounding design section to present the
bundled reflex_xy integration and xy[reflex] extra as the current shipped
implementation, removing stale future-work language and separate-adapter-package
recommendations. Retain smaller dependency surfaces or extracting a separate
package only as explicitly identified future work, and ensure the documented
behavior matches the relevant code, configuration, build, and release metadata.

---

Nitpick comments:
In `@python/reflex_xy/assets/XYChart.jsx`:
- Around line 361-380: Update the static payload fetch flow in the visible
effect around fetch(src) to create an AbortController, pass its signal to fetch,
and abort it during unmount cleanup. Preserve the existing cancelled checks and
ensure abort errors remain safely handled by the current catch path.

In `@python/reflex_xy/component.py`:
- Around line 205-220: Extract lazy _component_cls initialization into a shared
_component() helper, then replace direct _component_cls.create calls with
_component().create in both _facet_grid and chart. Preserve the existing class
construction behavior while ensuring _facet_grid works independently of chart
initialization.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 522321d0-e1ab-4f9c-9f27-abaa3e094c27

📥 Commits

Reviewing files that changed from the base of the PR and between d505ef5 and ef535cb.

⛔ Files ignored due to path filters (4)
  • docs/app/reflex.lock/bun.lock is excluded by !**/*.lock
  • docs/app/uv.lock is excluded by !**/*.lock
  • python/reflex-xy/uv.lock is excluded by !**/*.lock
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (84)
  • .github/workflows/ci.yml
  • .github/workflows/release-reflex-xy.yml
  • .github/workflows/release.yml
  • CHANGELOG.md
  • CLAUDE.md
  • Makefile
  • README.md
  • docs/advanced/runtime-and-deployment.md
  • docs/api-reference/events-and-callbacks.md
  • docs/app/pyproject.toml
  • docs/app/reflex.lock/package.json
  • docs/app/rxconfig.py
  • docs/app/tests/test_docs_site.py
  • docs/app/xy_docs/api_reference.py
  • docs/app/xy_docs/demos/benchmark_charts.py
  • docs/app/xy_docs/demos/xy_sdf_plots.py
  • docs/app/xy_docs/playground.py
  • docs/guides/deployment-recipes.md
  • docs/integrations/index.md
  • docs/integrations/reflex.md
  • docs/overview/installation.md
  • examples/reflex/README.md
  • examples/reflex/assets/.gitkeep
  • examples/reflex/pyproject.toml
  • examples/reflex/rxconfig.py
  • examples/reflex/xy_reflex_demo/__init__.py
  • examples/reflex/xy_reflex_demo/xy_reflex_demo.py
  • pyproject.toml
  • python/reflex-xy/CHANGELOG.md
  • python/reflex-xy/README.md
  • python/reflex-xy/pyproject.toml
  • python/reflex_xy/__init__.py
  • python/reflex_xy/app.py
  • python/reflex_xy/assets/XYChart.jsx
  • python/reflex_xy/assets/__init__.py
  • python/reflex_xy/component.py
  • python/reflex_xy/events.py
  • python/reflex_xy/namespace.py
  • python/reflex_xy/payload_asset.py
  • python/reflex_xy/registry.py
  • python/reflex_xy/selections.py
  • python/reflex_xy/state_bridge.py
  • python/reflex_xy/tokens.py
  • python/reflex_xy/vars.py
  • scripts/check_release_version.py
  • scripts/reflex_ws_smoke.py
  • scripts/verify_ci_workflow.py
  • scripts/verify_reflex_xy_dist.py
  • scripts/verify_sdist.py
  • scripts/verify_wheel.py
  • spec/README.md
  • spec/api/chart-roadmap.md
  • spec/api/export.md
  • spec/api/interaction.md
  • spec/design/chart-grammar.md
  • spec/design/reflex-integration.md
  • spec/design/reflex-shaped-api.md
  • spec/design/renderer-architecture.md
  • spec/design/view-state.md
  • spec/design/wire-protocol.md
  • spec/process/contributing.md
  • spec/process/production-readiness.md
  • tests/reflex_adapter/__init__.py
  • tests/reflex_adapter/conftest.py
  • tests/reflex_adapter/test_assets.py
  • tests/reflex_adapter/test_async_figure_var.py
  • tests/reflex_adapter/test_component.py
  • tests/reflex_adapter/test_figure_var.py
  • tests/reflex_adapter/test_payload_asset.py
  • tests/reflex_adapter/test_registry.py
  • tests/reflex_adapter/test_selections.py
  • tests/reflex_adapter/test_socket_data_plane.py
  • tests/reflex_adapter/test_state_bridge.py
  • tests/reflex_adapter/test_tokens.py
  • tests/reflex_adapter/test_view_state_push.py
  • tests/test_check_release_version.py
  • tests/test_dependencies.py
  • tests/test_payload_update_rehome.py
  • tests/test_tailwind_root_customization.py
  • tests/test_verify_ci_workflow.py
  • tests/test_verify_local.py
  • tests/test_verify_reflex_xy_dist.py
  • tests/test_verify_sdist.py
  • tests/test_verify_wheel.py
💤 Files with no reviewable changes (8)
  • docs/app/reflex.lock/package.json
  • .github/workflows/release-reflex-xy.yml
  • python/reflex-xy/README.md
  • python/reflex-xy/CHANGELOG.md
  • python/reflex-xy/pyproject.toml
  • scripts/verify_reflex_xy_dist.py
  • tests/test_verify_ci_workflow.py
  • tests/test_verify_reflex_xy_dist.py
🛑 Comments failed to post (6)
python/reflex_xy/events.py (1)

38-206: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Trace the semantic-event producer, its transport, and the documented ABI.
rg -n -C 4 \
  'pointEnvelope|point_hover|point_click|select_end|view_change|JSON\.stringify|data_bounds|polygon|x_domain|y_domain|canonical_row_id' \
  python/reflex_xy/assets/XYChart.jsx \
  python/reflex_xy/events.py \
  python/reflex_xy/selections.py \
  spec/design/reflex-integration.md

Repository: reflex-dev/xy

Length of output: 34309


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- event transport and serialization ---'
rg -n -C 5 \
  'addEvents|onPointHover|onPointClick|onSelectEnd|onViewChange|event-trigger|JSON|arrayBuffer|Float32Array|raw buffer|control plane|data plane' \
  python/reflex_xy/assets/XYChart.jsx \
  python/reflex_xy \
  spec/design/reflex-integration.md \
  spec/design/wire-protocol.md

printf '%s\n' '--- selection resolver implementation ---'
cat -n python/reflex_xy/selections.py

printf '%s\n' '--- relevant client sections ---'
sed -n '230,275p;440,535p;600,670p' python/reflex_xy/assets/XYChart.jsx

printf '%s\n' '--- protocol declarations ---'
rg -n -C 8 \
  'semantic event|point_hover|point_click|select_end|view_change|f32|Float32Array|binary' \
  spec/design/wire-protocol.md spec/design/reflex-integration.md

Repository: reflex-dev/xy

Length of output: 50372


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- component event contract ---'
sed -n '15,35p;78,92p' python/reflex_xy/component.py

printf '%s\n' '--- selection resolver ---'
cat -n python/reflex_xy/selections.py

printf '%s\n' '--- client event construction ---'
sed -n '241,252p;470,480p;644,665p' python/reflex_xy/assets/XYChart.jsx

printf '%s\n' '--- data-plane binary contract ---'
sed -n '108,118p' spec/design/reflex-integration.md
sed -n '490,515p' spec/design/reflex-integration.md

printf '%s\n' '--- read-only invariant check ---'
python3 - <<'PY'
from pathlib import Path

component = Path("python/reflex_xy/component.py").read_text()
events = Path("python/reflex_xy/events.py").read_text()
client = Path("python/reflex_xy/assets/XYChart.jsx").read_text()
selections = Path("python/reflex_xy/selections.py").read_text()
design = Path("spec/design/reflex-integration.md").read_text()

checks = {
    "semantic events use normal Reflex event props": "on_point_hover: rx.EventHandler" in component,
    "event types expose numeric fields": '"data": {"x": float, "y": float}' in events
    and '"x_domain": [x0, x1]' in events,
    "client constructs numeric point payloads": "data: { x, y }" in client,
    "client constructs numeric view payloads": "x_domain: [m.x0, m.x1]" in client,
    "client constructs numeric selection geometry": "data_bounds: message.bounds" in client,
    "resolver consumes numeric selection geometry": 'bounds["x0"]' in selections
    and 'selection["polygon"]' in selections,
    "design permits JSON semantic events": "semantic events out" in design
    and "low-frequency, JSON" in design,
    "design requires binary data columns": "No JSON numbers for data" in design,
}

for name, result in checks.items():
    print(f"{'PASS' if result else 'FAIL'}: {name}")

if not all(checks.values()):
    raise SystemExit(1)
PY

Repository: reflex-dev/xy

Length of output: 8103


Move numeric semantic-event fields to binary attachments.

The data plane is binary, but semantic events currently send numeric coordinates, bounds, polygons, IDs, rows, and counts through Reflex JSON. This violates the no-JSON-numbers wire requirement. Define a binary event ABI, decode selection geometry before select_range or select_polygon, and update events.py and resolve_selection() accordingly.

📍 Affects 2 files
  • python/reflex_xy/events.py#L38-L206 (this comment)
  • python/reflex_xy/selections.py#L17-L19
  • python/reflex_xy/selections.py#L37-L42
🤖 Prompt for 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.

In `@python/reflex_xy/events.py` around lines 38 - 206, Move all numeric
semantic-event payloads in python/reflex_xy/events.py:38-206—including point
coordinates, selection bounds/polygons, row IDs, row projections, and
counts—into a defined binary event ABI, leaving only non-numeric metadata and
attachment references in JSON; update PointData, ScreenPoint, DataBounds,
SelectionPayload, and the event TypedDicts consistently. In
python/reflex_xy/selections.py:17-19 and 37-42, decode the binary selection
geometry before calling select_range or select_polygon, and update
resolve_selection() to consume the binary IDs, rows, and counts while preserving
truncation and clear-selection behavior.

Source: Coding guidelines

python/reflex_xy/namespace.py (2)

132-141: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect namespace connection handlers and application authentication hooks.
ast-grep outline python/reflex_xy/namespace.py --match 'XYNamespace' --view expanded
rg -n -C5 \
  'on_connect|connect.*auth|authenticate|authorization|client_token|save_session|get_session' \
  --type=py .

Repository: reflex-dev/xy

Length of output: 35143


🏁 Script executed:

#!/bin/bash
set -euo pipefail

cat -n python/reflex_xy/namespace.py | sed -n '1,340p'
printf '\n--- adapter setup and socket registrations ---\n'
rg -n -C8 \
  'XYNamespace|AsyncServer|register_namespace|/_xy|socketio|/_event|QUERY_STRING|client_token' \
  python tests pyproject.toml uv.lock 2>/dev/null || true
printf '\n--- targeted socket tests ---\n'
cat -n tests/reflex_adapter/test_socket_data_plane.py | sed -n '1,120p;320,390p'

Repository: reflex-dev/xy

Length of output: 50370


🌐 Web query:

python-socketio server namespace on_connect authentication shared Engine.IO connection namespace independently authenticated

💡 Result:

In Python-SocketIO, namespaces are logical connections multiplexed over a single physical Engine.IO transport [1][2]. Because each namespace operates as an independent logical connection, you can authenticate them individually [1]. Authentication Strategy The recommended way to authenticate a namespace is via its individual 'connect' event handler [3][1]. When a client attempts to connect to a specific namespace, the server triggers the 'connect' event for that namespace [1]. You can reject the connection by returning False or raising an exception from this handler [3][4][5]. Example Implementation You can define independent 'connect' handlers for different namespaces [1]: @sio.on('connect', namespace='/chat') def connect_chat(sid, environ, auth): # Perform authentication logic specific to /chat if not authenticate_chat(auth): return False # Success: allow connection @sio.on('connect', namespace='/admin') def connect_admin(sid, environ, auth): # Perform authentication logic specific to /admin if not authenticate_admin(auth): return False # Success: allow connection Key Considerations 1. Authentication Data: Clients can pass an 'auth' dictionary (e.g., tokens) in their 'connect' call [6][5]. This data is passed to the server-side 'connect' handler [5]. 2. Independent Sessions: Each namespace connection is assigned its own unique SID [2][7]. You can use 'sio.session(sid, namespace=...)' to manage session data independently for each namespace [8]. 3. Class-based Namespaces: If using class-based namespaces, define an 'on_connect(self, sid, environ, auth)' method within your class to handle authentication for that specific namespace [1][9]. 4. Connection State: Since namespaces are multiplexed, if the underlying Engine.IO connection fails, all namespace connections will also be disconnected [1][2]. However, rejecting a connection at the namespace level only affects that specific logical path [1][5]. While you can technically perform authentication at the Engine.IO level (e.g., using middleware), doing so at the namespace 'connect' handler provides the most granular control, allowing you to easily handle different authentication requirements per namespace [1][5].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import ast
from pathlib import Path

path = Path("python/reflex_xy/namespace.py")
tree = ast.parse(path.read_text(encoding="utf-8"), filename=str(path))
klass = next(n for n in tree.body if isinstance(n, ast.ClassDef) and n.name == "XYNamespace")
methods = {n.name: n for n in klass.body if isinstance(n, (ast.FunctionDef, ast.AsyncFunctionDef))}

connect = methods["on_connect"]
connect_calls = [
    ast.unparse(node)
    for node in ast.walk(connect)
    if isinstance(node, ast.Call)
]
connect_returns = [
    ast.unparse(node.value) if node.value is not None else None
    for node in ast.walk(connect)
    if isinstance(node, ast.Return)
]

entry = methods["_entry_for"]
entry_session_checks = [
    ast.unparse(node)
    for node in ast.walk(entry)
    if isinstance(node, ast.Compare)
    and "client_token" in ast.unparse(node)
]

print("on_connect calls:", connect_calls)
print("on_connect returns:", connect_returns)
print("_entry_for client-token checks:", entry_session_checks)
print("namespace registration:", "sio.register_namespace(namespace)" in Path("python/reflex_xy/app.py").read_text())
PY

printf '\n--- focused client handshake and auth-related tests ---\n'
rg -n -C4 \
  'query: \{ token|connect\(|namespaces|/_event|/_xy|auth=|on_connect|reject|unauthor' \
  python/reflex_xy/assets/XYChart.jsx tests/reflex_adapter/test_socket_data_plane.py \
  tests/reflex_adapter/test_assets.py python/reflex_xy/app.py

Repository: reflex-dev/xy

Length of output: 33936


🌐 Web query:

Reflex framework socket.io client token authentication server connect handler _event namespace client_token

💡 Result:

In the Reflex framework, authentication and connection management are handled through the Socket.IO /_event namespace, which manages client sessions using a client_token [1][2][3]. The client_token is a unique UUID generated by the frontend and is sent automatically by the Reflex client during the initial WebSocket connection as a query parameter (?token=...) [4][1][3]. The backend's EventNamespace (via the TokenManager) maps this client_token to the Socket.IO Session ID (sid) to maintain state consistency [1][5][6]. Key points regarding the connection and authentication flow: 1. Connection Handler: While developers typically use Reflex's high-level rx.State and event decorators, the underlying WebSocket connection is managed by EventNamespace.on_connect [1][7]. You can access session information, including the client_token, within your state handlers via self.router.session.client_token [4]. 2. Token Lifecycle: The system relies on the TokenManager to link tokens to connections [5]. If a client reconnects (e.g., after a network blip), the framework attempts to resolve the client_token to an existing session [8][9]. If a client_token is detected as already belonging to an active sid, the system may trigger a new_token event to handle potential duplicate tab scenarios or state conflicts [8][9]. 3. Advanced Management: If you need to monitor connection status for background tasks, you can use rx.get_token_manager() (introduced in recent versions) to access lifecycle APIs [5]. These APIs allow you to track when a session or token connects or disconnects: python # Example: Tracking connection lifecycle in a background task from reflex.utils import get_token_manager class State(rx.State): `@rx.background` async def monitor_session(self): tm = get_token_manager() # Wait for specific token to connect await tm.when_token_connects(self.router.session.client_token) # Perform logic... 4. Multiplexing: Reflex's architecture allows for custom namespaces to multiplex onto the existing /_event connection [2][3]. These custom namespaces inherit the same authentication (via query parameters) and connection lifecycle as the main app event stream, meaning you do not need to reimplement token validation if you are building on the same engine.io connection [2][3]. For direct access to the mapping between tokens and socket IDs, you can reference app.event_namespace.token_to_sid [6], though utilizing the official TokenManager lifecycle APIs is the recommended approach for stable integration [5].

Citations:


Reject unauthenticated /_xy connections.

on_connect stores the query-string token without validating it through Reflex's server-side session manager. Because /_xy has independent namespace authentication, a client can connect directly with an arbitrary token, and _entry_for treats a matching embedded token as authorization. Validate the token before saving the session and reject the connection when validation fails.

🤖 Prompt for 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.

In `@python/reflex_xy/namespace.py` around lines 132 - 141, Update on_connect to
validate the query-string token through Reflex’s server-side session manager
before calling save_session. Reject the connection when the token is missing or
validation fails, and only store the validated token for authenticated
connections; use the existing session-validation symbol and connection rejection
mechanism already available in the namespace.

153-167: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Synchronize entry.figure and entry.version as one snapshot.

entry.lock does not synchronize with FigureRegistry.publish. publish can replace entry.figure and increment entry.version while these handlers build a payload or process a message.

The server can emit an old figure with a new version. It can also emit an interaction reply from a figure that has already been replaced.

Add a registry operation that captures the figure and version under the registry mutex. Use that snapshot throughout each operation. Before sending an interaction reply, discard it if the current version no longer matches the captured version.

Also applies to: 179-217, 246-256, 304-315

🤖 Prompt for 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.

In `@python/reflex_xy/namespace.py` around lines 153 - 167, Add a FigureRegistry
operation that atomically snapshots each entry’s figure and version under the
registry mutex, coordinated with publish. Update on_sub and the other affected
handlers to use that snapshot for payload building and message processing
instead of reading entry.figure and entry.version independently. Before emitting
any interaction reply, compare the current registry version with the captured
version and discard the reply when they differ.
python/reflex_xy/payload_asset.py (1)

76-82: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Use a unique temporary filename per writer.

The temporary path .{name}.tmp is identical for every process that writes the same digest. The module documentation states that several workers can import the app module and write concurrently. Path.write_bytes truncates the file first, so one writer can truncate the temporary file while another writer is still writing it. Either replace call can then publish a short or empty .xyf file, which the frontend fetches and fails to decode. Content addressing keeps the final bytes identical, but it does not protect the shared temporary file.

Make the temporary name unique per writer, for example with the process id and a random suffix.

🐛 Proposed fix for the temporary-file race
+import os
+import secrets
     if _should_write():
         asset_dir = Path.cwd() / "assets" / ASSET_SUBDIR
         asset_dir.mkdir(parents=True, exist_ok=True)
         dest = asset_dir / name
         if not dest.exists():
             # Content-addressed, so concurrent writers (multiple workers
             # importing the app module) produce identical bytes; the rename
             # keeps a racing reader from ever seeing a partial file.
-            tmp = asset_dir / f".{name}.tmp"
+            # The temporary name is per-writer so concurrent writers never
+            # truncate each other's in-progress file.
+            tmp = asset_dir / f".{name}.{os.getpid()}.{secrets.token_hex(4)}.tmp"
             tmp.write_bytes(frame)
             tmp.replace(dest)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

        if not dest.exists():
            # Content-addressed, so concurrent writers (multiple workers
            # importing the app module) produce identical bytes; the rename
            # keeps a racing reader from ever seeing a partial file.
            # The temporary name is per-writer so concurrent writers never
            # truncate each other's in-progress file.
            tmp = asset_dir / f".{name}.{os.getpid()}.{secrets.token_hex(4)}.tmp"
            tmp.write_bytes(frame)
            tmp.replace(dest)
🤖 Prompt for 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.

In `@python/reflex_xy/payload_asset.py` around lines 76 - 82, Update the temporary
path construction in the asset-writing block around dest and tmp so each writer
gets a unique filename, using the process ID plus a random or otherwise
collision-resistant suffix. Keep the existing write_bytes and replace flow,
ensuring concurrent writers never share the same temporary file while publishing
the identical final dest.
python/reflex_xy/registry.py (1)

111-127: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Serialize figure replacement with payload and delta generation.

publish replaces entry.figure and increments entry.version without acquiring entry.lock. Concurrent payload and append paths use that lock.

An on_sub task can build the old figure and then emit the new version. An append task can mutate the old figure, bump the replacement version, and push an incompatible delta.

Use one generation-safe synchronization path for replacement, payload construction, mutation, and version capture. Verify that each emitted version identifies the exact figure or delta used to build the message.

Also applies to: 224-235

🤖 Prompt for 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.

In `@python/reflex_xy/registry.py` around lines 111 - 127, Synchronize figure
replacement in publish with entry.lock, using the same generation-safe path as
payload construction and append mutation. Keep figure replacement, version
increment, payload or delta construction, and version capture coordinated so
each emitted message references the exact figure or delta used to build it,
preventing stale figures or incompatible deltas.
python/reflex_xy/state_bridge.py (1)

63-65: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Reject invalid figure-builder results before publishing them.

_figure_of(chart) returns arbitrary objects unchanged. A builder that returns a string can therefore enter the registry. The next subscription calls build_payload_split on that string and raises AttributeError.

Validate the converted result as a Figure. Return None or raise a controlled builder error when the result is invalid.

Proposed fix
-from typing import TYPE_CHECKING, Any, Optional
+from typing import Any, Optional
+
+from xy._figure import Figure

-if TYPE_CHECKING:
-    from xy._figure import Figure
-
 ...
-    return _figure_of(chart)
+    figure = _figure_of(chart)
+    if not isinstance(figure, Figure):
+        return None
+    return figure
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    if chart is None:
        return None
    figure = _figure_of(chart)
    if not isinstance(figure, Figure):
        return None
    return figure
🤖 Prompt for 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.

In `@python/reflex_xy/state_bridge.py` around lines 63 - 65, Update the chart
conversion flow around _figure_of so its result is validated as a Figure before
publication. If the converted value is invalid, return None or raise the
established controlled builder error; preserve the existing None handling and
only publish valid Figure instances.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 88 files

Tip: instead of fixing issues one by one fix them all with cubic

Re-trigger cubic

Comment thread scripts/verify_wheel.py
Comment thread docs/integrations/reflex.md Outdated
Comment thread scripts/verify_sdist.py Outdated
Comment thread scripts/reflex_ws_smoke.py
Comment thread CLAUDE.md Outdated
Comment thread scripts/verify_ci_workflow.py
Comment thread scripts/verify_sdist.py Outdated
@Alek99

Alek99 commented Jul 31, 2026

Copy link
Copy Markdown
Member Author

Addressed the remaining review-body feedback in 3d918317.

Implemented:

  • generation-safe figure replacement, stale reply/payload suppression, and versioned append pushes;
  • race-safe content-addressed asset writes plus fetch cancellation;
  • strict rebuilt-figure validation;
  • a lazy component-class helper used by both chart and facet paths;
  • current xy[reflex] spec/docs wording;
  • shared exact wheel/sdist dependency metadata validation and reflex_xy/py.typed coverage;
  • CI, release-smoke, and deterministic browser-smoke corrections.

Two suggestions were intentionally not applied:

  • Semantic event envelopes remain bounded JSON on Reflex's control plane. The authoritative integration design explicitly separates those small row/summary events from high-frequency numeric data, which already uses binary Socket.IO attachments.
  • There is no reusable Reflex query-token authenticator to call here: Reflex's current TokenManager links the client-supplied ?token= value to a SID rather than authenticating it. The figure token is the bearer capability, state-derived tokens enforce affinity to their embedded client id, and engine-level origin/auth policy is inherited from the shared connection. The namespace docstring now states that contract without calling the query token “authenticated.”

Verification: 3772 passed, 108 skipped; Ruff and targeted python/reflex_xy type checks pass; real wheel and sdist builds pass their artifact verifiers.

@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: 2

🤖 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 `@scripts/artifact_metadata.py`:
- Around line 18-26: The _dependency_satisfies_floor function currently accepts
pre-release or development versions such as 1.24.dev0 as meeting the stable
minimum. Update its requirement validation to parse and compare the version
portion against minimum, or explicitly reject pre-release/development suffixes
before returning true, while preserving package and optional-extra matching.

In `@spec/design/reflex-shaped-api.md`:
- Around line 789-795: Update the stale separate-adapter roadmap item in Section
10 to remove references to a future independent `reflex-xy` distribution,
keeping the specification consistent with the shipped bundled `reflex_xy`
namespace and existing optional `xy[reflex]` packaging.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 13b5be2b-7d1a-4a64-a6b5-b1b269d37b40

📥 Commits

Reviewing files that changed from the base of the PR and between ef535cb and 3d91831.

📒 Files selected for processing (31)
  • .github/workflows/ci.yml
  • .github/workflows/release.yml
  • CLAUDE.md
  • Makefile
  • docs/integrations/reflex.md
  • python/reflex_xy/assets/XYChart.jsx
  • python/reflex_xy/component.py
  • python/reflex_xy/namespace.py
  • python/reflex_xy/payload_asset.py
  • python/reflex_xy/py.typed
  • python/reflex_xy/registry.py
  • python/reflex_xy/state_bridge.py
  • scripts/artifact_metadata.py
  • scripts/reflex_ws_smoke.py
  • scripts/verify_ci_workflow.py
  • scripts/verify_sdist.py
  • scripts/verify_wheel.py
  • spec/api/export.md
  • spec/design/reflex-integration.md
  • spec/design/reflex-shaped-api.md
  • spec/process/production-readiness.md
  • tests/reflex_adapter/conftest.py
  • tests/reflex_adapter/test_assets.py
  • tests/reflex_adapter/test_payload_asset.py
  • tests/reflex_adapter/test_registry.py
  • tests/reflex_adapter/test_socket_data_plane.py
  • tests/reflex_adapter/test_state_bridge.py
  • tests/reflex_adapter/test_view_state_push.py
  • tests/test_verify_local.py
  • tests/test_verify_sdist.py
  • tests/test_verify_wheel.py
🚧 Files skipped from review as they are similar to previous changes (22)
  • .github/workflows/ci.yml
  • .github/workflows/release.yml
  • CLAUDE.md
  • scripts/reflex_ws_smoke.py
  • tests/reflex_adapter/conftest.py
  • tests/test_verify_local.py
  • python/reflex_xy/state_bridge.py
  • Makefile
  • python/reflex_xy/payload_asset.py
  • tests/test_verify_sdist.py
  • spec/api/export.md
  • python/reflex_xy/component.py
  • tests/reflex_adapter/test_view_state_push.py
  • tests/reflex_adapter/test_state_bridge.py
  • python/reflex_xy/assets/XYChart.jsx
  • tests/test_verify_wheel.py
  • python/reflex_xy/namespace.py
  • scripts/verify_wheel.py
  • spec/design/reflex-integration.md
  • scripts/verify_ci_workflow.py
  • scripts/verify_sdist.py
  • spec/process/production-readiness.md

Comment thread scripts/artifact_metadata.py Outdated
Comment thread spec/design/reflex-shaped-api.md

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 31 files (changes from recent commits).

Tip: instead of fixing issues one by one fix them all with cubic

Re-trigger cubic

Comment thread python/reflex_xy/registry.py Outdated
Comment thread python/reflex_xy/assets/XYChart.jsx
Comment thread scripts/artifact_metadata.py Outdated
Comment thread python/reflex_xy/namespace.py Outdated
Comment thread scripts/artifact_metadata.py Outdated
Comment thread .github/workflows/ci.yml Outdated
Comment thread python/reflex_xy/registry.py
Comment thread python/reflex_xy/namespace.py
Comment thread python/reflex_xy/assets/XYChart.jsx Outdated
Comment thread spec/design/reflex-shaped-api.md

@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

🧹 Nitpick comments (1)
python/reflex_xy/assets/XYChart.jsx (1)

420-428: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the repeated interaction-bookkeeping reset into a helper.

clickInputs.clear(); restoreSelectionSeqs.clear(); appears identically in subscribe (Line 425-426), the payload version-change branch (Lines 588-589), and the unaddressed-append version-bump branch (Lines 716-717). Extract a small helper, for example resetInteractionBookkeeping(), and call it from all three sites.

♻️ Proposed refactor
+    const resetInteractionBookkeeping = () => {
+      clickInputs.clear();
+      restoreSelectionSeqs.clear();
+    };
+
     const subscribe = () => {
       payloadVersion = null;
       awaitingPayload = true;
-      clickInputs.clear();
-      restoreSelectionSeqs.clear();
+      resetInteractionBookkeeping();
       socket.emit("sub", { fig: token, px: el.clientWidth || null, mid });
     };
       if (payloadVersion !== null && nextPayloadVersion !== payloadVersion) {
-        clickInputs.clear();
-        restoreSelectionSeqs.clear();
+        resetInteractionBookkeeping();
       }
       if (wireVersion !== null && message.type === "append" && data.mid == null) {
-        clickInputs.clear();
-        restoreSelectionSeqs.clear();
+        resetInteractionBookkeeping();
         payloadVersion = wireVersion;
       }

Also applies to: 585-590, 715-719

🤖 Prompt for 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.

In `@python/reflex_xy/assets/XYChart.jsx` around lines 420 - 428, Extract the
duplicated clickInputs and restoreSelectionSeqs clearing logic into a
resetInteractionBookkeeping helper, then call that helper from subscribe, the
payload version-change branch, and the unaddressed-append version-bump branch.
Preserve the existing reset timing and surrounding version-handling behavior.
🤖 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 `@python/reflex_xy/registry.py`:
- Around line 71-74: Bound the lifetime of entries created in Registry.sweep()
by storing each evicted version with its eviction timestamp, then prune entries
older than a defined multiple of the configured TTL during subsequent sweeps.
Update publish() and release() to continue removing the corresponding records
while preserving the scalar version used for state-driven rebuilds.

---

Nitpick comments:
In `@python/reflex_xy/assets/XYChart.jsx`:
- Around line 420-428: Extract the duplicated clickInputs and
restoreSelectionSeqs clearing logic into a resetInteractionBookkeeping helper,
then call that helper from subscribe, the payload version-change branch, and the
unaddressed-append version-bump branch. Preserve the existing reset timing and
surrounding version-handling behavior.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 615424e9-b16b-4e51-81c3-71b68c7da6ce

📥 Commits

Reviewing files that changed from the base of the PR and between 3d91831 and 10a6c01.

📒 Files selected for processing (14)
  • .github/workflows/ci.yml
  • python/reflex_xy/assets/XYChart.jsx
  • python/reflex_xy/namespace.py
  • python/reflex_xy/registry.py
  • scripts/artifact_metadata.py
  • scripts/verify_ci_workflow.py
  • spec/design/reflex-integration.md
  • spec/design/reflex-shaped-api.md
  • tests/reflex_adapter/test_assets.py
  • tests/reflex_adapter/test_registry.py
  • tests/reflex_adapter/test_socket_data_plane.py
  • tests/test_verify_ci_workflow.py
  • tests/test_verify_sdist.py
  • tests/test_verify_wheel.py
🚧 Files skipped from review as they are similar to previous changes (6)
  • .github/workflows/ci.yml
  • scripts/artifact_metadata.py
  • tests/reflex_adapter/test_assets.py
  • spec/design/reflex-shaped-api.md
  • scripts/verify_ci_workflow.py
  • tests/test_verify_wheel.py

Comment thread python/reflex_xy/registry.py

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 14 files (changes from recent commits).

Tip: instead of fixing issues one by one fix them all with cubic
Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread python/reflex_xy/namespace.py Outdated
Comment thread scripts/artifact_metadata.py Outdated
Comment thread python/reflex_xy/registry.py Outdated
Comment thread python/reflex_xy/registry.py Outdated
Comment thread python/reflex_xy/assets/XYChart.jsx
Comment thread python/reflex_xy/assets/XYChart.jsx

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 14 files (changes from recent commits).

Tip: instead of fixing issues one by one fix them all with cubic
Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread python/reflex_xy/namespace.py Outdated
Comment thread python/reflex_xy/registry.py
Comment thread python/reflex_xy/namespace.py Outdated
Comment thread scripts/artifact_metadata.py Outdated
Comment thread python/reflex_xy/assets/XYChart.jsx
Comment thread scripts/verify_ci_workflow.py Outdated
Comment thread python/reflex_xy/namespace.py Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 13 files (changes from recent commits).

Tip: instead of fixing issues one by one fix them all with cubic
Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread scripts/verify_ci_workflow.py Outdated
Comment thread scripts/verify_ci_workflow.py Outdated
Comment thread python/reflex_xy/assets/XYChart.jsx Outdated
Comment thread python/reflex_xy/registry.py Outdated
Comment thread python/reflex_xy/namespace.py Outdated
Comment thread scripts/verify_ci_workflow.py
Comment thread python/reflex_xy/assets/XYChart.jsx 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

🧹 Nitpick comments (2)
python/reflex_xy/namespace.py (1)

443-446: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Record the builder failure before you discard it.

The except Exception branch replaces any builder error with figure = None. The client then receives unknown figure token, and the operator gets no signal about the real cause. Add a debug or warning log with the token and exception so rebuild failures stay diagnosable.

♻️ Proposed logging addition
             try:
                 figure = await rebuild(token)
-            except Exception:  # noqa: BLE001 - user builder code is an input boundary
+            except Exception:  # noqa: BLE001 - user builder code is an input boundary
+                _LOGGER.warning("figure rebuild failed for %s", token, exc_info=True)
                 figure = None

Define the module logger once near the imports:

import logging

_LOGGER = logging.getLogger(__name__)
🤖 Prompt for 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.

In `@python/reflex_xy/namespace.py` around lines 443 - 446, Update the rebuild
exception handler around rebuild to log the failed token and caught exception
before setting figure to None. Define and reuse the module-level _LOGGER near
the imports, using debug or warning-level logging without changing the existing
fallback behavior.
tests/test_verify_ci_workflow.py (1)

57-59: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Read ci.yml through a repository-root helper.

Every new test resolves Path(".github/workflows/ci.yml") relative to the current working directory. The suite then only passes when pytest runs from the repository root, while _load_verify_module (Line 24) already anchors on __file__. Extract one module-level helper and reuse it; that also removes the repeated read in thirteen tests.

♻️ Proposed helper
REPO_ROOT = Path(__file__).resolve().parents[1]


def _ci_workflow_text() -> str:
    return (REPO_ROOT / ".github" / "workflows" / "ci.yml").read_text(encoding="utf-8")
 def test_locked_reflex_environment_must_be_in_named_install_step(tmp_path: Path) -> None:
-    workflow = Path(".github/workflows/ci.yml").read_text(encoding="utf-8")
+    workflow = _ci_workflow_text()
     required = "          uv sync --locked --extra reflex --group dev"
🤖 Prompt for 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.

In `@tests/test_verify_ci_workflow.py` around lines 57 - 59, Define a module-level
repository-root constant and _ci_workflow_text() helper in
tests/test_verify_ci_workflow.py, anchored from __file__ like
_load_verify_module. Replace all direct
Path(".github/workflows/ci.yml").read_text(...) calls across the tests with this
helper, including the shown test, so workflow loading is independent of pytest’s
working directory and the repeated reads are centralized.
🤖 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 `@spec/design/reflex-integration.md`:
- Around line 145-153: Update the envelope table in the reflex integration
specification so its mid notation matches the optional implementation contract:
mark mid optional for msg and remove it from unsub, which does not consume the
field. Keep the existing payload and message field names unchanged.

---

Nitpick comments:
In `@python/reflex_xy/namespace.py`:
- Around line 443-446: Update the rebuild exception handler around rebuild to
log the failed token and caught exception before setting figure to None. Define
and reuse the module-level _LOGGER near the imports, using debug or
warning-level logging without changing the existing fallback behavior.

In `@tests/test_verify_ci_workflow.py`:
- Around line 57-59: Define a module-level repository-root constant and
_ci_workflow_text() helper in tests/test_verify_ci_workflow.py, anchored from
__file__ like _load_verify_module. Replace all direct
Path(".github/workflows/ci.yml").read_text(...) calls across the tests with this
helper, including the shown test, so workflow loading is independent of pytest’s
working directory and the repeated reads are centralized.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4c481e96-0a93-4e9f-8a8f-e50e8b0fb98a

📥 Commits

Reviewing files that changed from the base of the PR and between 66fcf1a and 0281759.

📒 Files selected for processing (18)
  • README.md
  • pyproject.toml
  • python/reflex_xy/assets/XYChart.jsx
  • python/reflex_xy/namespace.py
  • python/reflex_xy/registry.py
  • scripts/artifact_metadata.py
  • scripts/verify_ci_workflow.py
  • scripts/verify_sdist.py
  • spec/design/reflex-integration.md
  • spec/process/production-readiness.md
  • spec/process/rendering-verification.md
  • tests/reflex_adapter/test_assets.py
  • tests/reflex_adapter/test_registry.py
  • tests/reflex_adapter/test_socket_data_plane.py
  • tests/test_tailwind_root_customization.py
  • tests/test_verify_ci_workflow.py
  • tests/test_verify_sdist.py
  • tests/test_verify_wheel.py
🚧 Files skipped from review as they are similar to previous changes (10)
  • tests/test_tailwind_root_customization.py
  • scripts/verify_sdist.py
  • tests/reflex_adapter/test_assets.py
  • scripts/artifact_metadata.py
  • pyproject.toml
  • spec/process/production-readiness.md
  • tests/test_verify_sdist.py
  • README.md
  • python/reflex_xy/assets/XYChart.jsx
  • tests/test_verify_wheel.py

Comment thread spec/design/reflex-integration.md

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 12 files (changes from recent commits).

Tip: instead of fixing issues one by one fix them all with cubic
Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread python/reflex_xy/assets/XYChart.jsx
Comment thread scripts/verify_ci_workflow.py Outdated
Comment thread scripts/verify_ci_workflow.py
Comment thread scripts/verify_ci_workflow.py Outdated
Comment thread python/reflex_xy/registry.py
@Alek99
Alek99 merged commit 87260f7 into main Jul 31, 2026
30 checks 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