#115 Tile 2: rewire vision card + /ui/vision/large modal#118
Merged
Conversation
…} 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>
This was referenced May 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Tile 2 of #115. Restores live vision data to the dashboard's vision card,
/ui/vision/largemodal, and the robot-modal photo tile.Endpoints added (dotty-behaviour):
GET /api/vision/cache— JSON dump ofPerceptionState.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:
_dotty_behaviour_get()helper reused verbatim — same 2 s cache, 1.5 s timeout, fallback-on-error contract._dashboard_vision_cache_getterpassed to dashboard viavision_cache_getter=(replacing the oldvision_cache=_vision_cachedict arg)._vision_cachestub dict deleted from bridge.py.Dashboard:
_state["vision_cache"]→_state["vision_cache_getter"]+ new_vision_cache_snapshot()read-through helper._latest_vision_entry,_pick_perception_device_id,_build_perception_card_ctx,status_stripphoto check,_build_security_panel_ctx.has_photoflags now derive from entry presence (the explain writer always populatesjpeg_bytesalongside 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 isResponse.contentrather thanStreamingResponse— 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./ui/vision/largemodal 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