feat: Cricket DRS AI — Real-time Third Umpire using Gemini Live + YOLO#379
feat: Cricket DRS AI — Real-time Third Umpire using Gemini Live + YOLO#379jaya6400 wants to merge 15 commits intoGetStream:mainfrom
Conversation
- cricket_umpire.py: Main agent using Gemini Live + YOLO pose detection - cricket_umpire.md: Third umpire instructions (run out, stumping, catch, boundary) - pyproject.toml: Project dependencies - README.md: Setup and usage documentation
- Fixed YOLOPoseProcessor import and model name - Added keepalive loop (every 20s) to prevent Gemini disconnecting - Added separate token_server.py on port 8001 for frontend auth - Agent continuously watches video and announces decisions"
- Built React frontend with Stream Video SDK - Cricket-branded dark UI (Third Umpire AI branding) - 5 scenario buttons: Run Out, Stumping, Catch, Boundary, LBW - Decision log panel showing AI verdicts in real-time - Screen share, camera, mic controls - YOLO Pose Detection active badge - Token fetched from token_server.py on port 8001"
- Simplified to LBW and Run Out only (DRS-focused) - Removed YOLO processor to fix AudioQueue buffer overflow - Added Text-to-Speech for spoken verdict on decision - Removed fake setTimeout, replaced with DRS-accurate decisions - Updated cricket_umpire.md with voice-trigger instructions - Fixed run.sh to use correct script directory paths - Cleaned up App.css to match two-panel layout - Removed screen share audio to prevent WebRTC track timeout
- Re-added YOLOPoseProcessor at imgsz=256 (down from 320/1080p) - Reduced Gemini fps to 2 to reduce processing load - Root cause of AudioQueue overflow was SCREEN_SHARE_AUDIO track - Fix: uncheck 'Share tab audio' in Chrome screen share dialog - YOLO now runs without timeout at 256px resolution on CPU
- Added FastAPI server on port 8002 to receive review triggers - Button click now calls POST /review/lbw or /review/runout - Triggers agent.llm.simple_response() with analysis prompt - Gemini watches live screen share and speaks real verdict - YOLO pose detection running at imgsz=256 without timeouts - Added requirements.txt for Python dependencies - Verified: real DECISION/REVIEW TYPE/REASON/CONFIDENCE from Gemini
📝 WalkthroughWalkthroughIntroduces a complete Cricket DRS example application featuring a decision-review system for women's cricket. Includes a Python backend with an AI umpire agent using Gemini Realtime and YOLO pose detection, a token server, a FastAPI review endpoint, and a React + Vite frontend UI for managing review scenarios and displaying verdicts. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 12
🧹 Nitpick comments (12)
examples/09_cricket_umpire/pyproject.toml (1)
14-14: Non-standard build backend specified.
setuptools.backends.legacy:buildis atypical. The standard backend issetuptools.build_meta.🛠️ Proposed fix
-build-backend = "setuptools.backends.legacy:build" +build-backend = "setuptools.build_meta"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/09_cricket_umpire/pyproject.toml` at line 14, The pyproject specifies a non-standard build backend via build-backend = "setuptools.backends.legacy:build"; replace this with the standard setuptools backend by setting build-backend to "setuptools.build_meta" (update the build-backend entry in pyproject.toml to use setuptools.build_meta) so the project uses the supported build backend.examples/09_cricket_umpire/README.md (1)
109-120: Consider adding language identifiers to fenced code blocks.Markdown linters recommend specifying a language (e.g.,
textorplaintext) for code blocks to improve rendering consistency.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/09_cricket_umpire/README.md` around lines 109 - 120, Update the fenced code block in examples/09_cricket_umpire/README.md (the directory tree block showing cricket_umpire.py, cricket_umpire.md, token_server.py, run.sh, requirements.txt, and frontend/src/App.jsx/App.css) to include a language identifier such as "text" or "plaintext" (i.e., replace the opening ``` with ```text) so Markdown linters/renderers correctly treat the block as plain text.examples/09_cricket_umpire/frontend/eslint.config.js (1)
16-24: RedundantecmaVersionsettings.
ecmaVersionis set to2020at line 17 and'latest'at line 20. TheparserOptions.ecmaVersionwill override the outer setting. Consider keeping only one.🛠️ Proposed fix
languageOptions: { - ecmaVersion: 2020, globals: globals.browser, parserOptions: { ecmaVersion: 'latest',🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/09_cricket_umpire/frontend/eslint.config.js` around lines 16 - 24, Remove the redundant ecmaVersion by keeping a single definitive setting: either delete the outer languageOptions.ecmaVersion or remove parserOptions.ecmaVersion so only one ecmaVersion remains; locate the languageOptions block and the nested parserOptions (symbols: languageOptions, parserOptions, ecmaVersion) and ensure the chosen ecmaVersion is the one in parserOptions if you expect parser-specific behavior (or keep the outer one and remove the nested override).examples/09_cricket_umpire/frontend/README.md (1)
1-16: Consider customizing this README for the Cricket DRS frontend.This appears to be the default Vite template README. Consider replacing or augmenting it with project-specific documentation covering the DRS UI components, Stream Video SDK integration, and how to trigger reviews.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/09_cricket_umpire/frontend/README.md` around lines 1 - 16, The README.md in the frontend currently contains the default Vite template text; replace or augment it with Cricket DRS-specific documentation: update README.md to describe the DRS UI (key components like UmpireReviewPanel, BallEventList, DecisionModal), explain how to set up and run the frontend dev server, list Stream Video SDK integration steps and required environment variables, and document how to trigger and test reviews (manual steps and any API endpoints or mock data used). Ensure the new README includes a quick start, development commands, testing instructions, and links to relevant source files and components so contributors can quickly run and exercise the DRS review flow.examples/09_cricket_umpire/token_server.py (1)
27-37: Consider adding return type annotations and a brief docstring.Functions lack return type hints and docstrings per coding guidelines.
🛠️ Proposed fix
`@app.get`("/token") -async def get_token(user_id: str): +async def get_token(user_id: str) -> JSONResponse: + """Generate a Stream token for the given user_id.""" try:`@app.get`("/health") -async def health(): +async def health() -> dict[str, str]: + """Health check endpoint.""" return {"status": "ok"}As per coding guidelines: "Use modern type annotation syntax everywhere" and "Use Google style docstrings."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/09_cricket_umpire/token_server.py` around lines 27 - 37, Add a Google-style docstring and explicit return type annotation to the FastAPI handler get_token: document the user_id parameter and that the function returns a fastapi.responses.JSONResponse containing either token and user_id or an error; annotate the function signature as async def get_token(user_id: str) -> JSONResponse. Reference the existing get_token function and the use of StreamClient.create_token so the docstring briefly explains that it creates a Stream token for the given user_id and returns a JSONResponse with {"token": token, "user_id": user_id} or an error payload on exception.examples/09_cricket_umpire/cricket_umpire.py (4)
34-43: Add a brief Google-style docstring tojoin_call.Same as above—document the function purpose.
📝 Proposed fix
async def join_call(agent: Agent, call_type: str, call_id: str, **kwargs) -> None: + """Join a call with the agent and announce readiness.""" global active_agentAs per coding guidelines: "Use Google style docstrings and keep them short."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/09_cricket_umpire/cricket_umpire.py` around lines 34 - 43, Add a short Google-style docstring to the async function join_call describing its purpose, parameters, and return type; place it immediately below the def line in cricket_umpire.py and mention that it sets the global active_agent, creates and joins a call via Agent.create_call/Agent.join, sends a simple_response, and finishes the agent; include param entries for agent (Agent), call_type (str), call_id (str), and **kwargs, plus a Returns: None line.
18-31: Add a brief Google-style docstring tocreate_agent.Per guidelines, functions should have docstrings following Google style. A short summary suffices.
📝 Proposed fix
async def create_agent(**kwargs) -> Agent: + """Create a Cricket DRS Third Umpire agent with Gemini and YOLO processors.""" agent = Agent(As per coding guidelines: "Use Google style docstrings and keep them short."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/09_cricket_umpire/cricket_umpire.py` around lines 18 - 31, Add a short Google-style docstring to the create_agent function that briefly describes its purpose (e.g., constructs and returns an Agent configured for the Third Umpire DRS with edge, user, instructions, LLM, and processors), mention the return type (Agent), and place it immediately below the async def create_agent(**kwargs) signature; ensure it is concise (one or two lines) and follows Google docstring format (summary line plus "Returns:" section).
53-65: Add a brief docstring totrigger_reviewand consider returning a proper error status code.Currently, when no agent is connected, the endpoint returns a 200 with
{"error": "Agent not connected"}. A 503 or 400 would be more semantically correct.♻️ Proposed fix
+from fastapi import FastAPI, HTTPException + `@review_app.post`("/review/{review_type}") async def trigger_review(review_type: str): + """Trigger an LBW or Run Out review analysis via the active agent.""" global active_agent if active_agent is None: - return {"error": "Agent not connected"} + raise HTTPException(status_code=503, detail="Agent not connected")🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/09_cricket_umpire/cricket_umpire.py` around lines 53 - 65, Add a short docstring to the endpoint function trigger_review explaining its purpose and parameters, and change the error path so it returns a proper HTTP status instead of a 200 JSON error; e.g., raise FastAPI's HTTPException(status_code=503, detail="Agent not connected") or return a Response with status_code=503 when active_agent is None, while keeping the rest of the logic unchanged.
1-12: Movethreadinganduvicornimports to the top of the module.The coding guidelines specify that local imports should be avoided—imports belong at the module level. Currently
threadinganduvicornare imported inside__main__(lines 69-70).♻️ Proposed fix
import asyncio import logging +import threading from contextlib import asynccontextmanager from dotenv import load_dotenv from fastapi import FastAPI +import uvicorn from vision_agents.core import Agent, Runner, User from vision_agents.core.agents import AgentLauncher from vision_agents.plugins import gemini, getstream, ultralyticsThen remove the local imports in
__main__:if __name__ == "__main__": - import threading - import uvicorn - def run_api():As per coding guidelines: "Do not use local imports; import at the top of the module."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/09_cricket_umpire/cricket_umpire.py` around lines 1 - 12, The threading and uvicorn imports currently done inside the __main__ block should be moved to module-level imports at the top of the file; add "import threading" and "import uvicorn" alongside the existing imports and remove the local imports inside the if __name__ == '__main__': section so that no local imports remain (look for the local usage in the __main__ block and any calls to threading or uvicorn.run to verify behavior after moving).examples/09_cricket_umpire/frontend/src/App.css (1)
1-1: Consider using string notation for the font import.Stylelint prefers string notation over
url()for@importstatements.📝 Proposed fix
-@import url('https://fonts.googleapis.com/css2?family=Oswald:wght@400;600;700&family=IBM+Plex+Mono:wght@400;500&family=Source+Sans+3:wght@400;500;600&display=swap'); +@import 'https://fonts.googleapis.com/css2?family=Oswald:wght@400;600;700&family=IBM+Plex+Mono:wght@400;500&family=Source+Sans+3:wght@400;500;600&display=swap';🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/09_cricket_umpire/frontend/src/App.css` at line 1, The `@import` line in App.css uses url(...) which Stylelint flags; replace the url(...) form with string notation by changing the `@import` to use a quoted string (keeping the same Google Fonts URL and query parameters) so the rule uses `@import` 'https://fonts.googleapis.com/…' instead of `@import` url(...), ensuring the font families (Oswald, IBM Plex Mono, Source Sans 3) and display parameter remain unchanged.examples/09_cricket_umpire/frontend/src/App.jsx (1)
13-16: Consider externalizing backend URLs to environment variables.The hardcoded
localhost:8001andlocalhost:8002URLs (lines 59, 194) will break outside local development. Extract these toimport.meta.envvariables for flexibility.♻️ Proposed fix
const API_KEY = import.meta.env.VITE_STREAM_API_KEY; +const TOKEN_SERVER_URL = import.meta.env.VITE_TOKEN_SERVER_URL || "http://localhost:8001"; +const REVIEW_API_URL = import.meta.env.VITE_REVIEW_API_URL || "http://localhost:8002"; const CALL_TYPE = "default";Then update usages:
- await fetch("http://localhost:8002/review/" + scenario.id, { method: "POST" }); + await fetch(`${REVIEW_API_URL}/review/${scenario.id}`, { method: "POST" });- const res = await fetch("http://localhost:8001/token?user_id=" + USER.id); + const res = await fetch(`${TOKEN_SERVER_URL}/token?user_id=${USER.id}`);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/09_cricket_umpire/frontend/src/App.jsx` around lines 13 - 16, Replace the hardcoded backend URLs with environment variables accessed via import.meta.env (e.g. add VITE_BACKEND_URL and VITE_SIGNALING_URL constants and fall back to "http://localhost:8001" / "http://localhost:8002" for local dev); update every usage of the literal "localhost:8001" and "localhost:8002" (the fetch/connection calls in the App where the backend and signaling endpoints are constructed) to use these new constants so the app works outside local development. Ensure the new env vars are referenced where CALL_ID / API_KEY are defined and used so all endpoint construction uses the env-driven base URLs.examples/09_cricket_umpire/frontend/index.html (1)
5-7: Update the page title and verify the favicon exists.The generic title "frontend" should reflect the application purpose. Also ensure
/vite.svgis present in thepublic/folder or update the href.📝 Proposed fix
- <link rel="icon" type="image/svg+xml" href="/vite.svg" /> + <link rel="icon" type="image/svg+xml" href="/vite.svg" /> <!-- or use a cricket emoji favicon --> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> - <title>frontend</title> + <title>Cricket DRS AI</title>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/09_cricket_umpire/frontend/index.html` around lines 5 - 7, Update the generic <title> element to a descriptive app name (replace "frontend" in the <title> tag with something like "Cricket Umpire" or the actual app name) and verify the favicon href (currently href="/vite.svg" on the <link rel="icon">) points to an existing file in your public assets; if the file is missing, either add vite.svg to the public/ folder or update the href to the correct favicon path (e.g., /favicon.svg or /assets/favicon.ico) so the icon resolves.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@examples/09_cricket_umpire/cricket_umpire.py`:
- Around line 14-15: The global active_agent variable creates a race condition
when concurrent HTTP requests (e.g., /review/{review_type}) call join_call and
set/clear active_agent; protect access by introducing an asyncio.Lock (e.g.,
agent_lock) and acquire it around all places that read or write active_agent
(including join_call and any HTTP handler functions that inspect or mutate
active_agent) so modifications are serialized; ensure the lock is awaited (async
with agent_lock:) wherever active_agent is mutated or checked to prevent
interleaving and clear/reset operations from racing.
- Around line 68-80: The current pattern starts uvicorn in a daemon thread
(run_api -> uvicorn.run) and logs the server as running immediately, which can
hide startup errors; modify run_api to wrap uvicorn.run in a try/except that
logs any exception via logger.error and sets a threading.Event on success,
create a threading.Event (e.g., server_started_event) before starting
api_thread, start the thread non-daemon (api_thread = threading.Thread(...,
daemon=False)) or keep daemon but wait on the event, and only call logger.info
after the event is set (or perform a short health-check loop against
http://localhost:8002 to confirm the server is listening) so startup failures
are caught and reported before launching AgentLauncher/Runner.
In `@examples/09_cricket_umpire/frontend/src/App.jsx`:
- Around line 211-218: The disconnect function can throw from call.leave() or
client.disconnectUser(); wrap the await calls inside a try/catch and handle
errors (e.g., log them) to prevent unhandled rejections, and move state cleanup
(setCall(null), setClient(null), setStatus("idle"), setLastDecision(null)) into
a finally block so state is reset regardless of errors; update the disconnect
function and reference the existing call.leave(), client.disconnectUser(),
setCall, setClient, setStatus and setLastDecision identifiers.
- Around line 49-74: sendScenario currently starts a timeout that may run after
unmount and it also swallows fetch failures while still showing the fallback
decision; update sendScenario to store the timeout id (and any in-flight fetch
controller) in a ref, only schedule the fallback decision if the POST succeeded,
and in the catch branch push an error message to the transcript and clear
sending instead of showing the fallback decision; also add a cleanup useEffect
that clears the timeout and aborts the request on unmount to avoid setState
after unmount. Ensure you modify the logic around fetch, setTimeout,
setTranscript, setSending and call onDecision only when appropriate.
In `@examples/09_cricket_umpire/pyproject.toml`:
- Line 5: The pyproject.toml's requires-python = ">=3.12" conflicts with the
README's "Python 3.10+"; update one to match the other so they are
consistent—either change pyproject.toml's requires-python to ">=3.10" or update
the README to state "Python 3.12+"; edit the requires-python key in
pyproject.toml (and/or the Python version text in README.md) so both files
reference the same minimum Python version.
In `@examples/09_cricket_umpire/README.md`:
- Around line 13-16: Update the table link text to be descriptive for
accessibility: replace the generic "Link" label for the Frontend entry with a
descriptive phrase such as "Live demo" or the full URL (e.g., "Live demo —
ai-drs-vision-agents-sdk") and update the Backend entry text from "Runs locally
(see setup below)" to something like "Local backend (see setup below)" so screen
readers convey the destination; edit the README table row entries where the
Frontend and Backend link texts appear.
In `@examples/09_cricket_umpire/requirements.txt`:
- Around line 102-103: The requirements file currently lists Windows-only
packages pywin32 and pywin32-ctypes which will break installs on non-Windows
systems; update the requirements to conditionally install these packages using
environment markers (e.g., append a sys_platform marker like ; sys_platform ==
"win32" to the pywin32 and pywin32-ctypes entries) or move them into a
Windows-specific extras entry and/or add a README note documenting the platform
limitation so non-Windows users don’t attempt to install them unconditionally.
- Around line 136-139: Update the git dependency URLs in requirements.txt to
point to the official GetStream repository and use POSIX path separators;
specifically replace occurrences of
"git+https://github.com/jaya6400/Vision-Agents.git@..." with
"git+https://github.com/GetStream/Vision-Agents.git@..." and change any
backslashes in subdirectory fragments (e.g., "plugins\gemini" or
"plugins\ultralytics") to forward slashes ("plugins/gemini",
"plugins/ultralytics"), keeping the same `#egg` names (vision_agents,
vision_agents_plugins_gemini, vision_agents_plugins_getstream,
vision_agents_plugins_ultralytics) so pip can resolve the editable git
subpackages correctly.
In `@examples/09_cricket_umpire/run.sh`:
- Around line 6-7: The script sets SCRIPT_DIR and then runs cd "$SCRIPT_DIR"
without checking for failure; change the cd invocation (the line using
SCRIPT_DIR and the cd command) to guard against failure by testing its exit
status and aborting (or returning a non-zero exit) with an error message if cd
fails (e.g., use a conditional or "|| exit 1" style) so the script never
continues in the wrong working directory.
- Around line 28-31: The trap and directory change need two small fixes: quote
the trap body to make intent explicit (e.g., use single quotes so the kill
command is not expanded at trap definition: trap 'kill "$TOKEN_PID" "$AGENT_PID"
2>/dev/null' EXIT) and guard the cd frontend by failing early if it cannot
change directories (e.g., change the cd frontend line in run.sh to cd frontend
|| exit 1 or similar error handling) so npm run dev is not executed in the wrong
directory; update references to TOKEN_PID and AGENT_PID in the trap as shown.
In `@examples/09_cricket_umpire/token_server.py`:
- Around line 18-24: The CORS setup in app.add_middleware using CORSMiddleware
currently sets allow_origins=["*"] together with allow_credentials=True which is
insecure and blocked by browsers; update the CORSMiddleware configuration in
token_server.py (the app.add_middleware call) to either set
allow_credentials=False or replace the wildcard origin with an explicit list
(e.g., "http://localhost:3000" or your frontend URL) — alternatively use
allow_origin_regex to match trusted origins — and ensure
allow_methods/allow_headers remain as intended.
- Around line 36-37: Replace the bare except in token_server.py that currently
returns JSONResponse({"error": str(e)}, status_code=500) with explicit exception
handlers: catch KeyError for missing environment variables and return a
JSONResponse with a clear message and 400/500 as appropriate, and catch the
SDK-specific error type used by the token creation call (import and reference
the actual SDK exception class instead of a generic name) to return a
JSONResponse with that error and a 500 status; keep a final generic fallback
only if you re-raise or log it, and ensure you still use JSONResponse for the
handled cases (reference: JSONResponse and the existing except block).
---
Nitpick comments:
In `@examples/09_cricket_umpire/cricket_umpire.py`:
- Around line 34-43: Add a short Google-style docstring to the async function
join_call describing its purpose, parameters, and return type; place it
immediately below the def line in cricket_umpire.py and mention that it sets the
global active_agent, creates and joins a call via Agent.create_call/Agent.join,
sends a simple_response, and finishes the agent; include param entries for agent
(Agent), call_type (str), call_id (str), and **kwargs, plus a Returns: None
line.
- Around line 18-31: Add a short Google-style docstring to the create_agent
function that briefly describes its purpose (e.g., constructs and returns an
Agent configured for the Third Umpire DRS with edge, user, instructions, LLM,
and processors), mention the return type (Agent), and place it immediately below
the async def create_agent(**kwargs) signature; ensure it is concise (one or two
lines) and follows Google docstring format (summary line plus "Returns:"
section).
- Around line 53-65: Add a short docstring to the endpoint function
trigger_review explaining its purpose and parameters, and change the error path
so it returns a proper HTTP status instead of a 200 JSON error; e.g., raise
FastAPI's HTTPException(status_code=503, detail="Agent not connected") or return
a Response with status_code=503 when active_agent is None, while keeping the
rest of the logic unchanged.
- Around line 1-12: The threading and uvicorn imports currently done inside the
__main__ block should be moved to module-level imports at the top of the file;
add "import threading" and "import uvicorn" alongside the existing imports and
remove the local imports inside the if __name__ == '__main__': section so that
no local imports remain (look for the local usage in the __main__ block and any
calls to threading or uvicorn.run to verify behavior after moving).
In `@examples/09_cricket_umpire/frontend/eslint.config.js`:
- Around line 16-24: Remove the redundant ecmaVersion by keeping a single
definitive setting: either delete the outer languageOptions.ecmaVersion or
remove parserOptions.ecmaVersion so only one ecmaVersion remains; locate the
languageOptions block and the nested parserOptions (symbols: languageOptions,
parserOptions, ecmaVersion) and ensure the chosen ecmaVersion is the one in
parserOptions if you expect parser-specific behavior (or keep the outer one and
remove the nested override).
In `@examples/09_cricket_umpire/frontend/index.html`:
- Around line 5-7: Update the generic <title> element to a descriptive app name
(replace "frontend" in the <title> tag with something like "Cricket Umpire" or
the actual app name) and verify the favicon href (currently href="/vite.svg" on
the <link rel="icon">) points to an existing file in your public assets; if the
file is missing, either add vite.svg to the public/ folder or update the href to
the correct favicon path (e.g., /favicon.svg or /assets/favicon.ico) so the icon
resolves.
In `@examples/09_cricket_umpire/frontend/README.md`:
- Around line 1-16: The README.md in the frontend currently contains the default
Vite template text; replace or augment it with Cricket DRS-specific
documentation: update README.md to describe the DRS UI (key components like
UmpireReviewPanel, BallEventList, DecisionModal), explain how to set up and run
the frontend dev server, list Stream Video SDK integration steps and required
environment variables, and document how to trigger and test reviews (manual
steps and any API endpoints or mock data used). Ensure the new README includes a
quick start, development commands, testing instructions, and links to relevant
source files and components so contributors can quickly run and exercise the DRS
review flow.
In `@examples/09_cricket_umpire/frontend/src/App.css`:
- Line 1: The `@import` line in App.css uses url(...) which Stylelint flags;
replace the url(...) form with string notation by changing the `@import` to use a
quoted string (keeping the same Google Fonts URL and query parameters) so the
rule uses `@import` 'https://fonts.googleapis.com/…' instead of `@import` url(...),
ensuring the font families (Oswald, IBM Plex Mono, Source Sans 3) and display
parameter remain unchanged.
In `@examples/09_cricket_umpire/frontend/src/App.jsx`:
- Around line 13-16: Replace the hardcoded backend URLs with environment
variables accessed via import.meta.env (e.g. add VITE_BACKEND_URL and
VITE_SIGNALING_URL constants and fall back to "http://localhost:8001" /
"http://localhost:8002" for local dev); update every usage of the literal
"localhost:8001" and "localhost:8002" (the fetch/connection calls in the App
where the backend and signaling endpoints are constructed) to use these new
constants so the app works outside local development. Ensure the new env vars
are referenced where CALL_ID / API_KEY are defined and used so all endpoint
construction uses the env-driven base URLs.
In `@examples/09_cricket_umpire/pyproject.toml`:
- Line 14: The pyproject specifies a non-standard build backend via
build-backend = "setuptools.backends.legacy:build"; replace this with the
standard setuptools backend by setting build-backend to "setuptools.build_meta"
(update the build-backend entry in pyproject.toml to use setuptools.build_meta)
so the project uses the supported build backend.
In `@examples/09_cricket_umpire/README.md`:
- Around line 109-120: Update the fenced code block in
examples/09_cricket_umpire/README.md (the directory tree block showing
cricket_umpire.py, cricket_umpire.md, token_server.py, run.sh, requirements.txt,
and frontend/src/App.jsx/App.css) to include a language identifier such as
"text" or "plaintext" (i.e., replace the opening ``` with ```text) so Markdown
linters/renderers correctly treat the block as plain text.
In `@examples/09_cricket_umpire/token_server.py`:
- Around line 27-37: Add a Google-style docstring and explicit return type
annotation to the FastAPI handler get_token: document the user_id parameter and
that the function returns a fastapi.responses.JSONResponse containing either
token and user_id or an error; annotate the function signature as async def
get_token(user_id: str) -> JSONResponse. Reference the existing get_token
function and the use of StreamClient.create_token so the docstring briefly
explains that it creates a Stream token for the given user_id and returns a
JSONResponse with {"token": token, "user_id": user_id} or an error payload on
exception.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (9)
examples/09_cricket_umpire/docs/screenshots/bash.PNGis excluded by!**/*.pngexamples/09_cricket_umpire/docs/screenshots/frontend.PNGis excluded by!**/*.pngexamples/09_cricket_umpire/docs/screenshots/realtime-voice-agent.PNGis excluded by!**/*.pngexamples/09_cricket_umpire/docs/screenshots/stream-ui.PNGis excluded by!**/*.pngexamples/09_cricket_umpire/docs/videos/lbw.mp4is excluded by!**/*.mp4examples/09_cricket_umpire/docs/videos/ro.mp4is excluded by!**/*.mp4examples/09_cricket_umpire/frontend/package-lock.jsonis excluded by!**/package-lock.jsonexamples/09_cricket_umpire/frontend/public/vite.svgis excluded by!**/*.svgexamples/09_cricket_umpire/frontend/src/assets/react.svgis excluded by!**/*.svg
📒 Files selected for processing (17)
examples/09_cricket_umpire/README.mdexamples/09_cricket_umpire/cricket_umpire.mdexamples/09_cricket_umpire/cricket_umpire.pyexamples/09_cricket_umpire/frontend/.gitignoreexamples/09_cricket_umpire/frontend/README.mdexamples/09_cricket_umpire/frontend/eslint.config.jsexamples/09_cricket_umpire/frontend/index.htmlexamples/09_cricket_umpire/frontend/package.jsonexamples/09_cricket_umpire/frontend/src/App.cssexamples/09_cricket_umpire/frontend/src/App.jsxexamples/09_cricket_umpire/frontend/src/index.cssexamples/09_cricket_umpire/frontend/src/main.jsxexamples/09_cricket_umpire/frontend/vite.config.jsexamples/09_cricket_umpire/pyproject.tomlexamples/09_cricket_umpire/requirements.txtexamples/09_cricket_umpire/run.shexamples/09_cricket_umpire/token_server.py
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 4 potential issues.
Bugbot Free Tier Details
Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.
To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
|
Hi Vision Agents team 👋 |
Hi 👋 Just following up on this PR — happy to address any remaining feedback or fix the issues flagged by the bots (CORS, path fixes, decision badge logic) if that helps move things forward. Let me know if there's anything blocking the review. Thanks for your time! |
AI-powered Third Umpire that reduces DRS review time from minutes to seconds using Gemini Live vision, YOLO pose detection,
and Stream's Voice Agents SDK.
What's added
examples/09_cricket_umpire/— full working exampleDemo
Watch Here
Blog
Medium link
Note
Medium Risk
Adds a full new runnable example (backend agent, FastAPI endpoints, token server, and React UI) plus large dependency lockfiles; main risk is integration/runtime issues from WebRTC/Gemini websocket requirements and new service credentials handling.
Overview
Adds a new
examples/09_cricket_umpireend-to-end demo: a Vision AgentsAgentwired to Gemini Live (2fps) plusYOLOPoseProcessor(256px) to deliver LBW/Run Out decisions via voice.Introduces a lightweight FastAPI review trigger service (
POST /review/{review_type}) that prompts the active agent, a separate FastAPI token server for Stream JWTs (/token), and a one-commandrun.shto start token server, agent, and the Vite-based React UI.Includes comprehensive documentation/instructions (
README.md,cricket_umpire.md) and pins Python/Node dependencies (newrequirements.txt,pyproject.toml, and frontendpackage-lock.json).Written by Cursor Bugbot for commit c35a7a7. This will update automatically on new commits. Configure here.
Summary by CodeRabbit
New Features
Documentation