Skip to content

#115 Tile 2: rewire vision card + /ui/vision/large modal#118

Merged
BrettKinny merged 2 commits into
mainfrom
dashboard-rewire-vision
May 23, 2026
Merged

#115 Tile 2: rewire vision card + /ui/vision/large modal#118
BrettKinny merged 2 commits into
mainfrom
dashboard-rewire-vision

Conversation

@BrettKinny
Copy link
Copy Markdown
Owner

Summary

Tile 2 of #115. Restores live vision data to the dashboard's vision card, /ui/vision/large modal, and the robot-modal photo tile.

Endpoints added (dotty-behaviour):

  • GET /api/vision/cache — JSON dump of PerceptionState.vision_cache, metadata only (jpeg_bytes stripped).
  • GET /api/vision/photo/{device_id} — raw JPEG (image/jpeg), 404 when no entry / no photo.

Bridge wiring:

  • Tile 1's _dotty_behaviour_get() helper reused verbatim — same 2 s cache, 1.5 s timeout, fallback-on-error contract.
  • New _dashboard_vision_cache_getter passed to dashboard via vision_cache_getter= (replacing the old vision_cache=_vision_cache dict arg).
  • _vision_cache stub dict deleted from bridge.py.

Dashboard:

  • _state["vision_cache"]_state["vision_cache_getter"] + new _vision_cache_snapshot() read-through helper.
  • Five direct cache-read sites converted to the helper: _latest_vision_entry, _pick_perception_device_id, _build_perception_card_ctx, status_strip photo check, _build_security_panel_ctx.
  • has_photo flags now derive from entry presence (the explain writer always populates jpeg_bytes alongside metadata; the JSON dump strips it for transport efficiency).

Robot-photo proxy strategy: option (a) — bridge HTTP-proxies /api/vision/photo/{device_id} through both /ui/host/robot/photo/{device_id} and /ui/vision/photo. Browser keeps a single dashboard origin (CORS-safe; dotty-behaviour's :8090 stays server-side). Body strategy is Response.content rather than StreamingResponse — vision JPEGs are sub-MB and the proxy uses a 2 s timeout, so non-streaming is the simpler choice. Single _fetch_robot_photo() helper backs both routes.

Test plan

  • dotty-behaviour: 205 passing (+4 from baseline 201) — new tests cover metadata-only filter, empty cache, binary JPEG response, 404 on missing device.
  • dotty-stackchan (bridge): 69 passing (baseline).
  • python -c "import bridge; from bridge.dashboard import *" clean.
  • Visual smoke after merge + deploy — /ui/vision/large modal shows recent photo with description after a vision capture; the robot-modal <img src="/ui/host/robot/photo/{device_id}"> resolves to a real JPEG.

Refs #115 (4 more tiles after this).

🤖 Generated with Claude Code

BrettKinny and others added 2 commits May 24, 2026 00:23
…} routes

Exposes the existing PerceptionState.vision_cache over HTTP so the
bridge dashboard's vision card + /ui/vision/large modal can fetch
live data. Used by the vision-rewire follow-up commit on bridge.py.

The JSON endpoint strips jpeg_bytes — base64-expanding raw image
bytes through the JSON encoder is wasteful and the dashboard fetches
the binary separately via /api/vision/photo/{device_id}.

The binary endpoint returns 404 when no entry exists or the entry
has no jpeg_bytes, which the bridge dashboard's /ui/host/robot/
photo/{device_id} proxy maps through to its own 404.

Refs #115

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…iour

Tile 2 of #115. Replaces the empty `_vision_cache` dict + direct
configure-time arg with a metadata-only getter against dotty-behaviour's
new /api/vision/cache route, plus an HTTP proxy for the binary photo
endpoint so the browser keeps the bridge as its single origin.

  - bridge.py: add `_dashboard_vision_cache_getter` (same cache +
    timeout + circuit-breaker contract as Tile 1's perception getters).
    Drop the `_vision_cache: dict` stub.
  - bridge/dashboard.py: replace `_state["vision_cache"]` with
    `_state["vision_cache_getter"]` + `_vision_cache_snapshot()`
    read-through accessor. Five direct cache reads converted:
      * _latest_vision_entry (line ~744)
      * _pick_perception_device_id (line ~1132)
      * _build_perception_card_ctx (line ~1160)
      * status_strip have_photo check (line ~2136)
      * _build_security_panel_ctx (line ~2441)
  - bridge/dashboard.py: robot-photo strategy is option (a) — bridge
    HTTP-proxies dotty-behaviour's /api/vision/photo/{device_id}
    through /ui/host/robot/photo/{device_id} + /ui/vision/photo. Single
    `_fetch_robot_photo()` helper used by both routes. Uses
    `requests.get` with a 2 s timeout and returns the bytes as
    Response.content (small, sub-MB JPEGs — no need for streaming).
  - has_photo flags derive from entry presence — jpeg_bytes is no
    longer in the metadata-only payload, but the explain writer
    always populates it alongside the metadata fields.

Refs #115

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 23, 2026 14:27
@BrettKinny BrettKinny merged commit 25cebbf into main May 23, 2026
7 of 9 checks passed
@BrettKinny BrettKinny deleted the dashboard-rewire-vision branch May 23, 2026 14:28
@BrettKinny BrettKinny review requested due to automatic review settings May 23, 2026 14:49
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