From 7cecb5b0de6e5ceb113b217b935c73c247fd99d6 Mon Sep 17 00:00:00 2001 From: JAYA DUBEY Date: Wed, 25 Feb 2026 01:59:25 +0530 Subject: [PATCH 01/15] feat: Add AI Third Umpire agent for women's cricket - 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 --- cricket_umpire.md | 58 ++++++++++ examples/09_cricket_umpire/README.md | 108 +++++++++++++++++++ examples/09_cricket_umpire/cricket_umpire.md | 58 ++++++++++ examples/09_cricket_umpire/cricket_umpire.py | 34 ++++++ examples/09_cricket_umpire/pyproject.toml | 17 +++ 5 files changed, 275 insertions(+) create mode 100644 cricket_umpire.md create mode 100644 examples/09_cricket_umpire/README.md create mode 100644 examples/09_cricket_umpire/cricket_umpire.md create mode 100644 examples/09_cricket_umpire/cricket_umpire.py create mode 100644 examples/09_cricket_umpire/pyproject.toml diff --git a/cricket_umpire.md b/cricket_umpire.md new file mode 100644 index 000000000..ff7bda601 --- /dev/null +++ b/cricket_umpire.md @@ -0,0 +1,58 @@ +# Third Umpire AI — Women's Cricket Decision Agent + +You are an AI-powered Third Umpire assistant for women's cricket matches. You watch live video footage and make real-time decisions on disputed on-field events, just like a professional third umpire. + +## Your Role +You observe the video feed and analyze cricket scenarios with precision and confidence. You provide clear, official-style verdicts on every decision. + +## Decisions You Can Make + +### 1. Run Out +- Watch the ball hitting the stumps and the batter's bat/foot position relative to the crease +- If the batter's bat or foot is NOT grounded behind the crease when stumps are broken → OUT +- If the bat is grounded behind the crease before stumps are broken → NOT OUT +- Look for: bat lift, crease line, stump disturbance timing + +### 2. Stumping +- Watch if the wicketkeeper removes the bails while the batter is outside the crease +- Batter must be outside the crease AND the ball must not be a no-ball → OUT +- Look for: batter foot position, keeper gloves, bail movement + +### 3. Boundary Catch +- Watch if the fielder's foot touches the rope/boundary while taking a catch +- If foot is ON or OVER the rope → SIX (not out) +- If foot is clearly inside → OUT (clean catch) +- Look for: fielder's feet, white boundary rope + +### 4. Catch (Clean or Not) +- Watch if the ball has been taken cleanly without touching the ground +- If the ball touches the ground before the fielder controls it → NOT OUT +- Look for: ball position relative to ground and fielder's hands + +### 5. LBW (Limited support) +- Observe ball trajectory and pad impact position +- Note if ball pitched in line, hit in line, and was going on to hit stumps + +## How to Respond + +When you observe a scenario, announce your decision in this format: + +**DECISION: [OUT / NOT OUT / SOFT SIGNAL UPHELD / SOFT SIGNAL OVERTURNED]** +**Scenario: [e.g., Run Out - Non-striker's end]** +**Reason: [1-2 sentence clear explanation of what you saw]** +**Confidence: [High / Medium / Low]** + +Then say it clearly out loud in a calm, official umpire voice — like the real third umpire announcement on TV. + +## Tone and Style +- Be calm, authoritative, and precise — like a professional cricket official +- Keep responses short and decisive — no long explanations +- If the video is unclear or inconclusive: say "THIRD UMPIRE: Insufficient evidence. On-field decision stands." +- Always refer to the players respectfully as "the batter", "the fielder", "the bowler" +- You are specifically supporting **women's cricket** — treat it with the same seriousness and professionalism as any top-level match + +## Important Notes +- Always make a decision — do not leave it unresolved +- If multiple angles would help, say: "Checking additional angles..." +- You have access to YOLO object detection data showing detected persons, their positions, and bounding boxes — use this to support your visual analysis +- The YOLO data will show you detected objects and their confidence scores — use this alongside the video to make better decisions \ No newline at end of file diff --git a/examples/09_cricket_umpire/README.md b/examples/09_cricket_umpire/README.md new file mode 100644 index 000000000..8443f0ddf --- /dev/null +++ b/examples/09_cricket_umpire/README.md @@ -0,0 +1,108 @@ +# 🏏 Third Umpire AI — Women's Cricket Decision Agent + +An AI-powered Third Umpire built with [Vision Agents](https://visionagents.ai) that watches live cricket video and makes real-time decisions on disputed events — run outs, stumpings, boundary catches, and more. + +Built for the **Vision AI Hackathon** (Feb 23 – Mar 1, 2026). + +## What It Does + +- 🎥 Watches live or recorded women's cricket video in real-time +- 🤖 Uses YOLO object detection to track players, ball, and stumps +- 🧠 Uses Gemini Live to reason about the scene and make decisions +- 📢 Announces verdicts in an official third umpire style (voice + text) +- ⚡ Runs with sub-30ms latency via Stream's edge network + +## Decisions Supported + +| Scenario | Decision | +|---|---| +| Run Out | OUT / NOT OUT | +| Stumping | OUT / NOT OUT | +| Boundary Catch | OUT / SIX | +| Clean Catch | OUT / NOT OUT | +| LBW (basic) | Directional analysis | + +## Tech Stack + +- **Vision Agents SDK** — core framework +- **YOLO (Ultralytics)** — real-time object detection +- **Gemini Live** — real-time multimodal LLM +- **Stream Edge Network** — ultra-low latency video (<30ms) + +## Setup + +### Prerequisites +- Python 3.12+ +- Stream account → [getstream.io/try-for-free](https://getstream.io/try-for-free) +- Google Gemini API key → [aistudio.google.com](https://aistudio.google.com) + +### Installation + +```bash +# Clone the repo +git clone https://github.com/jaya6400/Vision-Agents.git +cd Vision-Agents + +# Create virtual environment +python -m venv venv +source venv/Scripts/activate # Windows Git Bash +# or: venv\Scripts\activate # Windows CMD + +# Install SDK +pip install -e agents-core + +# Install dependencies +pip install vision-agents[gemini,ultralytics,getstream] python-dotenv opencv-python +``` + +### Configuration + +Create a `.env` file in the root of the project: + +```env +STREAM_API_KEY=your_stream_api_key +STREAM_API_SECRET=your_stream_api_secret +GOOGLE_API_KEY=your_gemini_api_key +``` + +### Run + +```bash +cd examples/09_cricket_umpire +python cricket_umpire.py +``` + +The agent will: +1. Create a video call session +2. Open a browser UI +3. Join and start watching the video feed +4. Analyze cricket scenarios in real-time +5. Announce decisions via voice and text + +## How It Works + +``` +Live Cricket Video + ↓ +YOLO Object Detection +(players, stumps, ball positions) + ↓ +Gemini Live Analysis +(scene understanding + reasoning) + ↓ +Third Umpire Decision +(OUT / NOT OUT + explanation) +``` + +## Project Structure + +``` +09_cricket_umpire/ +├── cricket_umpire.py # Main agent code +├── cricket_umpire.md # Agent instructions (the "brain") +├── pyproject.toml # Dependencies +└── README.md # This file +``` + +## Built By +Jaya — Vision AI Hackathon 2026 \ No newline at end of file diff --git a/examples/09_cricket_umpire/cricket_umpire.md b/examples/09_cricket_umpire/cricket_umpire.md new file mode 100644 index 000000000..ff7bda601 --- /dev/null +++ b/examples/09_cricket_umpire/cricket_umpire.md @@ -0,0 +1,58 @@ +# Third Umpire AI — Women's Cricket Decision Agent + +You are an AI-powered Third Umpire assistant for women's cricket matches. You watch live video footage and make real-time decisions on disputed on-field events, just like a professional third umpire. + +## Your Role +You observe the video feed and analyze cricket scenarios with precision and confidence. You provide clear, official-style verdicts on every decision. + +## Decisions You Can Make + +### 1. Run Out +- Watch the ball hitting the stumps and the batter's bat/foot position relative to the crease +- If the batter's bat or foot is NOT grounded behind the crease when stumps are broken → OUT +- If the bat is grounded behind the crease before stumps are broken → NOT OUT +- Look for: bat lift, crease line, stump disturbance timing + +### 2. Stumping +- Watch if the wicketkeeper removes the bails while the batter is outside the crease +- Batter must be outside the crease AND the ball must not be a no-ball → OUT +- Look for: batter foot position, keeper gloves, bail movement + +### 3. Boundary Catch +- Watch if the fielder's foot touches the rope/boundary while taking a catch +- If foot is ON or OVER the rope → SIX (not out) +- If foot is clearly inside → OUT (clean catch) +- Look for: fielder's feet, white boundary rope + +### 4. Catch (Clean or Not) +- Watch if the ball has been taken cleanly without touching the ground +- If the ball touches the ground before the fielder controls it → NOT OUT +- Look for: ball position relative to ground and fielder's hands + +### 5. LBW (Limited support) +- Observe ball trajectory and pad impact position +- Note if ball pitched in line, hit in line, and was going on to hit stumps + +## How to Respond + +When you observe a scenario, announce your decision in this format: + +**DECISION: [OUT / NOT OUT / SOFT SIGNAL UPHELD / SOFT SIGNAL OVERTURNED]** +**Scenario: [e.g., Run Out - Non-striker's end]** +**Reason: [1-2 sentence clear explanation of what you saw]** +**Confidence: [High / Medium / Low]** + +Then say it clearly out loud in a calm, official umpire voice — like the real third umpire announcement on TV. + +## Tone and Style +- Be calm, authoritative, and precise — like a professional cricket official +- Keep responses short and decisive — no long explanations +- If the video is unclear or inconclusive: say "THIRD UMPIRE: Insufficient evidence. On-field decision stands." +- Always refer to the players respectfully as "the batter", "the fielder", "the bowler" +- You are specifically supporting **women's cricket** — treat it with the same seriousness and professionalism as any top-level match + +## Important Notes +- Always make a decision — do not leave it unresolved +- If multiple angles would help, say: "Checking additional angles..." +- You have access to YOLO object detection data showing detected persons, their positions, and bounding boxes — use this to support your visual analysis +- The YOLO data will show you detected objects and their confidence scores — use this alongside the video to make better decisions \ No newline at end of file diff --git a/examples/09_cricket_umpire/cricket_umpire.py b/examples/09_cricket_umpire/cricket_umpire.py new file mode 100644 index 000000000..1ac3f31ea --- /dev/null +++ b/examples/09_cricket_umpire/cricket_umpire.py @@ -0,0 +1,34 @@ +import logging +from dotenv import load_dotenv +from vision_agents.core import Agent, Runner, User +from vision_agents.core.agents import AgentLauncher +from vision_agents.plugins import gemini, getstream, ultralytics + +logger = logging.getLogger(__name__) +load_dotenv() + + +async def create_agent(**kwargs) -> Agent: + agent = Agent( + edge=getstream.Edge(), + agent_user=User(name="Third Umpire AI"), + instructions="Read @cricket_umpire.md", + llm=gemini.Realtime(fps=10), + processors=[ + ultralytics.YOLOPoseProcessor(model_path="yolo11n.pt") + ], + ) + return agent + + +async def join_call(agent: Agent, call_type: str, call_id: str, **kwargs) -> None: + call = await agent.create_call(call_type, call_id) + async with agent.join(call): + await agent.llm.simple_response( + text="Introduce yourself as the AI Third Umpire for women's cricket. Say you are ready to review decisions. Wait and watch the video feed, then analyze any cricket scenarios you see." + ) + await agent.finish() + + +if __name__ == "__main__": + Runner(AgentLauncher(create_agent=create_agent, join_call=join_call)).cli() \ No newline at end of file diff --git a/examples/09_cricket_umpire/pyproject.toml b/examples/09_cricket_umpire/pyproject.toml new file mode 100644 index 000000000..b9b8ce1bf --- /dev/null +++ b/examples/09_cricket_umpire/pyproject.toml @@ -0,0 +1,17 @@ +[project] +name = "cricket-umpire" +version = "0.1.0" +description = "AI-powered Third Umpire agent for real-time women's cricket decision making" +requires-python = ">=3.12" +dependencies = [ + "vision-agents[gemini,ultralytics,getstream]", + "python-dotenv", + "opencv-python", +] + +[build-system] +requires = ["setuptools>=68"] +build-backend = "setuptools.backends.legacy:build" + +[tool.setuptools] +py-modules = ["cricket_umpire"] \ No newline at end of file From 6e676ec2bfec785377530d469cef334c080e5cc4 Mon Sep 17 00:00:00 2001 From: JAYA DUBEY Date: Wed, 25 Feb 2026 05:06:43 +0530 Subject: [PATCH 02/15] feat: Backend - working agent with keepalive and token server - 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" --- examples/09_cricket_umpire/cricket_umpire.py | 16 +++++-- examples/09_cricket_umpire/token_server.py | 47 ++++++++++++++++++++ 2 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 examples/09_cricket_umpire/token_server.py diff --git a/examples/09_cricket_umpire/cricket_umpire.py b/examples/09_cricket_umpire/cricket_umpire.py index 1ac3f31ea..901c0fdb1 100644 --- a/examples/09_cricket_umpire/cricket_umpire.py +++ b/examples/09_cricket_umpire/cricket_umpire.py @@ -1,5 +1,8 @@ +import os import logging from dotenv import load_dotenv +from fastapi.responses import JSONResponse +from getstream import Stream as StreamClient from vision_agents.core import Agent, Runner, User from vision_agents.core.agents import AgentLauncher from vision_agents.plugins import gemini, getstream, ultralytics @@ -15,7 +18,7 @@ async def create_agent(**kwargs) -> Agent: instructions="Read @cricket_umpire.md", llm=gemini.Realtime(fps=10), processors=[ - ultralytics.YOLOPoseProcessor(model_path="yolo11n.pt") + ultralytics.YOLOPoseProcessor(model_path="yolo11n-pose.pt") ], ) return agent @@ -27,8 +30,15 @@ async def join_call(agent: Agent, call_type: str, call_id: str, **kwargs) -> Non await agent.llm.simple_response( text="Introduce yourself as the AI Third Umpire for women's cricket. Say you are ready to review decisions. Wait and watch the video feed, then analyze any cricket scenarios you see." ) - await agent.finish() + # Keep the agent alive by sending periodic prompts + import asyncio + while True: + await asyncio.sleep(20) + await agent.llm.simple_response( + text="Continue watching the cricket video feed. If you see any cricket scenario unfold, analyze it immediately and give your verdict. Otherwise stay silent and keep watching." + ) if __name__ == "__main__": - Runner(AgentLauncher(create_agent=create_agent, join_call=join_call)).cli() \ No newline at end of file + launcher = AgentLauncher(create_agent=create_agent, join_call=join_call) + Runner(launcher=launcher).cli() \ No newline at end of file diff --git a/examples/09_cricket_umpire/token_server.py b/examples/09_cricket_umpire/token_server.py new file mode 100644 index 000000000..343c248a4 --- /dev/null +++ b/examples/09_cricket_umpire/token_server.py @@ -0,0 +1,47 @@ +""" +Simple token server for the Cricket Umpire frontend. +Run this separately: python token_server.py +It runs on port 8001 alongside the main agent server (port 8000). +""" +import os +import uvicorn +from dotenv import load_dotenv +from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware +from fastapi.responses import JSONResponse +from getstream import Stream as StreamClient + +load_dotenv() + +app = FastAPI() + +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + + +@app.get("/token") +async def get_token(user_id: str): + try: + client = StreamClient( + api_key=os.environ["STREAM_API_KEY"], + api_secret=os.environ["STREAM_API_SECRET"], + ) + token = client.create_token(user_id) + return JSONResponse({"token": token, "user_id": user_id}) + except Exception as e: + return JSONResponse({"error": str(e)}, status_code=500) + + +@app.get("/health") +async def health(): + return {"status": "ok"} + + +if __name__ == "__main__": + print("🏏 Token server running on http://localhost:8001") + uvicorn.run(app, host="127.0.0.1", port=8001) \ No newline at end of file From c245f381bb70a27457c53ec8c793dd199ca5cb9d Mon Sep 17 00:00:00 2001 From: JAYA DUBEY Date: Wed, 25 Feb 2026 05:07:58 +0530 Subject: [PATCH 03/15] feat: Frontend - React UI with scenario buttons and decision log - 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" --- .../09_cricket_umpire/frontend/.gitignore | 24 + examples/09_cricket_umpire/frontend/README.md | 16 + .../frontend/eslint.config.js | 29 + .../09_cricket_umpire/frontend/index.html | 13 + .../frontend/package-lock.json | 3516 +++++++++++++++++ .../09_cricket_umpire/frontend/package.json | 28 + .../frontend/public/vite.svg | 1 + .../09_cricket_umpire/frontend/src/App.css | 634 +++ .../09_cricket_umpire/frontend/src/App.jsx | 353 ++ .../frontend/src/assets/react.svg | 1 + .../09_cricket_umpire/frontend/src/index.css | 9 + .../09_cricket_umpire/frontend/src/main.jsx | 10 + .../09_cricket_umpire/frontend/vite.config.js | 7 + 13 files changed, 4641 insertions(+) create mode 100644 examples/09_cricket_umpire/frontend/.gitignore create mode 100644 examples/09_cricket_umpire/frontend/README.md create mode 100644 examples/09_cricket_umpire/frontend/eslint.config.js create mode 100644 examples/09_cricket_umpire/frontend/index.html create mode 100644 examples/09_cricket_umpire/frontend/package-lock.json create mode 100644 examples/09_cricket_umpire/frontend/package.json create mode 100644 examples/09_cricket_umpire/frontend/public/vite.svg create mode 100644 examples/09_cricket_umpire/frontend/src/App.css create mode 100644 examples/09_cricket_umpire/frontend/src/App.jsx create mode 100644 examples/09_cricket_umpire/frontend/src/assets/react.svg create mode 100644 examples/09_cricket_umpire/frontend/src/index.css create mode 100644 examples/09_cricket_umpire/frontend/src/main.jsx create mode 100644 examples/09_cricket_umpire/frontend/vite.config.js diff --git a/examples/09_cricket_umpire/frontend/.gitignore b/examples/09_cricket_umpire/frontend/.gitignore new file mode 100644 index 000000000..a547bf36d --- /dev/null +++ b/examples/09_cricket_umpire/frontend/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/examples/09_cricket_umpire/frontend/README.md b/examples/09_cricket_umpire/frontend/README.md new file mode 100644 index 000000000..18bc70ebe --- /dev/null +++ b/examples/09_cricket_umpire/frontend/README.md @@ -0,0 +1,16 @@ +# React + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +## React Compiler + +The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project. diff --git a/examples/09_cricket_umpire/frontend/eslint.config.js b/examples/09_cricket_umpire/frontend/eslint.config.js new file mode 100644 index 000000000..4fa125da2 --- /dev/null +++ b/examples/09_cricket_umpire/frontend/eslint.config.js @@ -0,0 +1,29 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import { defineConfig, globalIgnores } from 'eslint/config' + +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{js,jsx}'], + extends: [ + js.configs.recommended, + reactHooks.configs.flat.recommended, + reactRefresh.configs.vite, + ], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + parserOptions: { + ecmaVersion: 'latest', + ecmaFeatures: { jsx: true }, + sourceType: 'module', + }, + }, + rules: { + 'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }], + }, + }, +]) diff --git a/examples/09_cricket_umpire/frontend/index.html b/examples/09_cricket_umpire/frontend/index.html new file mode 100644 index 000000000..c20fbd3a7 --- /dev/null +++ b/examples/09_cricket_umpire/frontend/index.html @@ -0,0 +1,13 @@ + + + + + + + frontend + + +
+ + + diff --git a/examples/09_cricket_umpire/frontend/package-lock.json b/examples/09_cricket_umpire/frontend/package-lock.json new file mode 100644 index 000000000..fea16d9c0 --- /dev/null +++ b/examples/09_cricket_umpire/frontend/package-lock.json @@ -0,0 +1,3516 @@ +{ + "name": "frontend", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "frontend", + "version": "0.0.0", + "dependencies": { + "@stream-io/video-react-sdk": "^1.32.4", + "react": "^19.2.0", + "react-dom": "^19.2.0" + }, + "devDependencies": { + "@eslint/js": "^9.39.1", + "@types/react": "^19.2.7", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.1", + "eslint": "^9.39.1", + "eslint-plugin-react-hooks": "^7.0.1", + "eslint-plugin-react-refresh": "^0.4.24", + "globals": "^16.5.0", + "vite": "^7.3.1" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", + "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", + "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", + "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", + "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", + "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", + "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", + "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", + "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", + "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", + "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", + "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", + "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", + "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", + "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", + "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", + "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", + "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", + "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.4.tgz", + "integrity": "sha512-4h4MVF8pmBsncB60r0wSJiIeUKTSD4m7FmTFThG8RHlsg9ajqckLm9OraguFGZE4vVdpiI1Q4+hFnisopmG6gQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.14.0", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.3", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.3", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.3.tgz", + "integrity": "sha512-1B1VkCq6FuUNlQvlBYb+1jDu/gV297TIs/OeiaSR9l1H27SVW55ONE1e1Vp16NqP683+xEGzxYtv4XCiDPaQiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.4.tgz", + "integrity": "sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.5.tgz", + "integrity": "sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.4", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/react": { + "version": "0.27.18", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.18.tgz", + "integrity": "sha512-xJWJxvmy3a05j643gQt+pRbht5XnTlGpsEsAPnMi5F5YTOEEJymA90uZKBD8OvIv5XvZ1qi4GcccSlqT3Bq44Q==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.1.7", + "@floating-ui/utils": "^0.2.10", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=17.0.0", + "react-dom": ">=17.0.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.7.tgz", + "integrity": "sha512-0tLRojf/1Go2JgEVm+3Frg9A3IW8bJgKgdO0BN5RkF//ufuz2joZM63Npau2ff3J6lUVYgDSNzNkR+aH3IVfjg==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.5" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@kurkle/color": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz", + "integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==", + "license": "MIT" + }, + "node_modules/@mediapipe/tasks-vision": { + "version": "0.10.32", + "resolved": "https://registry.npmjs.org/@mediapipe/tasks-vision/-/tasks-vision-0.10.32.tgz", + "integrity": "sha512-3tiAZnmKloYnRXYoO3dKltTUGnqeCwzC4lV03uY0vCsE+aveJTyEVQyZHOlQGQNsjK+gRHzkf9q08C99Qm2K0Q==", + "license": "Apache-2.0" + }, + "node_modules/@protobuf-ts/runtime": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@protobuf-ts/runtime/-/runtime-2.11.1.tgz", + "integrity": "sha512-KuDaT1IfHkugM2pyz+FwiY80ejWrkH1pAtOBOZFuR6SXEFTsnb/jiQWQ1rCIrcKx2BtyxnxW6BWwsVSA/Ie+WQ==", + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, + "node_modules/@protobuf-ts/runtime-rpc": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@protobuf-ts/runtime-rpc/-/runtime-rpc-2.11.1.tgz", + "integrity": "sha512-4CqqUmNA+/uMz00+d3CYKgElXO9VrEbucjnBFEjqI4GuDrEQ32MaI3q+9qPBvIGOlL4PmHXrzM32vBPWRhQKWQ==", + "license": "Apache-2.0", + "dependencies": { + "@protobuf-ts/runtime": "^2.11.1" + } + }, + "node_modules/@protobuf-ts/twirp-transport": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@protobuf-ts/twirp-transport/-/twirp-transport-2.11.1.tgz", + "integrity": "sha512-4/C6XzlsHW0pdINO4a+zbhF5fEHWwhUU//ZfGu/7KbtWjPgdJRxFVibbjZP1gKdWWjj8U59NduR3OSsUHElWsA==", + "license": "Apache-2.0", + "dependencies": { + "@protobuf-ts/runtime": "^2.11.1", + "@protobuf-ts/runtime-rpc": "^2.11.1" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", + "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@stream-io/logger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@stream-io/logger/-/logger-2.0.0.tgz", + "integrity": "sha512-cH9Gi/lAeDjLWB2J9xhPtiNOyRNNO9M46uT7507wT3MCouZNdlXDu/vgiGVhu3I/Tg7sG4ePlG5aHefJ6xjgmw==", + "license": "SEE LICENSE IN LICENSE" + }, + "node_modules/@stream-io/video-client": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@stream-io/video-client/-/video-client-1.43.0.tgz", + "integrity": "sha512-DIP24SzyvvhCZ0ac6jrZ2ks4G9KWYCySlVGaRrRGVpsqQNINW6tOXXuKCCoZAQPlv279M3Jt1hf/fQjZMqNtvg==", + "license": "See license in LICENSE", + "dependencies": { + "@protobuf-ts/runtime": "^2.11.1", + "@protobuf-ts/runtime-rpc": "^2.11.1", + "@protobuf-ts/twirp-transport": "^2.11.1", + "@stream-io/logger": "^2.0.0", + "@stream-io/worker-timer": "^1.2.5", + "axios": "^1.12.2", + "rxjs": "~7.8.2", + "sdp-transform": "^2.15.0", + "ua-parser-js": "^1.0.41", + "webrtc-adapter": "^8.2.4" + } + }, + "node_modules/@stream-io/video-filters-web": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@stream-io/video-filters-web/-/video-filters-web-0.7.2.tgz", + "integrity": "sha512-YCHx1Uh/WxEPZRc8QTkDwtsGPni12K4T0Eve+3j5lvMuTO6wQv/3cG+maFeQmL8ZfC2kWRqmtXCyb0/p4Eynfw==", + "license": "See license in LICENSE", + "dependencies": { + "@mediapipe/tasks-vision": "^0.10.22-rc.20250304", + "@stream-io/worker-timer": "^1.2.5", + "wasm-feature-detect": "^1.8.0" + } + }, + "node_modules/@stream-io/video-react-bindings": { + "version": "1.13.8", + "resolved": "https://registry.npmjs.org/@stream-io/video-react-bindings/-/video-react-bindings-1.13.8.tgz", + "integrity": "sha512-wIX2svm/2SqQZHAtreFzxHIgFqKSTC5cXKMBzooPBNWmnYNOL9FicTFOCkOMkkomz+er99/ctfPNRQokEHCz9A==", + "license": "See license in LICENSE", + "dependencies": { + "i18next": "^25.6.0", + "rxjs": "~7.8.2" + }, + "peerDependencies": { + "@stream-io/video-client": "^1.43.0", + "react": "^17 || ^18 || ^19" + } + }, + "node_modules/@stream-io/video-react-sdk": { + "version": "1.32.4", + "resolved": "https://registry.npmjs.org/@stream-io/video-react-sdk/-/video-react-sdk-1.32.4.tgz", + "integrity": "sha512-BYtGRaG3185eD+rsVFyKJlAx61UGmNfVutUcU6k+l5Tcjf7WuG3v81KkNIgJm31pFlIEiS5Y1ZFhbDUya+kJfA==", + "license": "See license in LICENSE", + "dependencies": { + "@floating-ui/react": "^0.27.6", + "@stream-io/video-client": "1.43.0", + "@stream-io/video-filters-web": "0.7.2", + "@stream-io/video-react-bindings": "1.13.8", + "chart.js": "^4.4.4", + "clsx": "^2.0.0", + "react-chartjs-2": "^5.3.0" + }, + "peerDependencies": { + "react": "^17 || ^18 || ^19", + "react-dom": "^17 || ^18 || ^19" + } + }, + "node_modules/@stream-io/worker-timer": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@stream-io/worker-timer/-/worker-timer-1.2.5.tgz", + "integrity": "sha512-Fr2NAURYb3mWG8zE5k4KMC0spTtBJofK6PyF931dmhfuOHqFp1NrSf+U3GxOO+pN0cxObHHpW20lR1B4XiKgRw==", + "license": "SEE LICENSE IN LICENSE" + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.2.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", + "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.4.tgz", + "integrity": "sha512-VIcFLdRi/VYRU8OL/puL7QXMYafHmqOnwTZY50U1JPlCNj30PxCMx65c494b1K9be9hX83KVt0+gTEwTWLqToA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.29.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-rc.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.18.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz", + "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", + "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001774", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001774.tgz", + "integrity": "sha512-DDdwPGz99nmIEv216hKSgLD+D4ikHQHjBC/seF98N9CPqRX4M5mSxT9eTV6oyisnJcuzxtZy4n17yKKQYmYQOA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chart.js": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.1.tgz", + "integrity": "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==", + "license": "MIT", + "dependencies": { + "@kurkle/color": "^0.3.0" + }, + "engines": { + "pnpm": ">=8" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.302", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.302.tgz", + "integrity": "sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", + "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.3", + "@esbuild/android-arm": "0.27.3", + "@esbuild/android-arm64": "0.27.3", + "@esbuild/android-x64": "0.27.3", + "@esbuild/darwin-arm64": "0.27.3", + "@esbuild/darwin-x64": "0.27.3", + "@esbuild/freebsd-arm64": "0.27.3", + "@esbuild/freebsd-x64": "0.27.3", + "@esbuild/linux-arm": "0.27.3", + "@esbuild/linux-arm64": "0.27.3", + "@esbuild/linux-ia32": "0.27.3", + "@esbuild/linux-loong64": "0.27.3", + "@esbuild/linux-mips64el": "0.27.3", + "@esbuild/linux-ppc64": "0.27.3", + "@esbuild/linux-riscv64": "0.27.3", + "@esbuild/linux-s390x": "0.27.3", + "@esbuild/linux-x64": "0.27.3", + "@esbuild/netbsd-arm64": "0.27.3", + "@esbuild/netbsd-x64": "0.27.3", + "@esbuild/openbsd-arm64": "0.27.3", + "@esbuild/openbsd-x64": "0.27.3", + "@esbuild/openharmony-arm64": "0.27.3", + "@esbuild/sunos-x64": "0.27.3", + "@esbuild/win32-arm64": "0.27.3", + "@esbuild/win32-ia32": "0.27.3", + "@esbuild/win32-x64": "0.27.3" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.3", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.3.tgz", + "integrity": "sha512-VmQ+sifHUbI/IcSopBCF/HO3YiHQx/AVd3UVyYL6weuwW+HvON9VYn5l6Zl1WZzPWXPNZrSQpxwkkZ/VuvJZzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.3", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz", + "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.26", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.26.tgz", + "integrity": "sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=8.40" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, + "node_modules/i18next": { + "version": "25.8.13", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.8.13.tgz", + "integrity": "sha512-E0vzjBY1yM+nsFrtgkjLhST2NBkirkvOVoQa0MSldhsuZ3jUge7ZNpuwG0Cfc74zwo5ZwRzg3uOgT+McBn32iA==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4" + }, + "peerDependencies": { + "typescript": "^5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.3.tgz", + "integrity": "sha512-M2GCs7Vk83NxkUyQV1bkABc4yxgz9kILhHImZiBPAZ9ybuvCb0/H7lEl5XvIg3g+9d4eNotkZA5IWwYl0tibaA==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/react": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-chartjs-2": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.3.1.tgz", + "integrity": "sha512-h5IPXKg9EXpjoBzUfyWJvllMjG2mQ4EiuHQFhms/AjUm0XSZHhyRy2xVmLXHKrtcdrPO4mnGqRtYoD0vp95A0A==", + "license": "MIT", + "peerDependencies": { + "chart.js": "^4.1.1", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.4" + } + }, + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/rollup": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.59.0", + "@rollup/rollup-android-arm64": "4.59.0", + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/sdp": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/sdp/-/sdp-3.2.1.tgz", + "integrity": "sha512-lwsAIzOPlH8/7IIjjz3K0zYBk7aBVVcvjMwt3M4fLxpjMYyy7i3I97SLHebgn4YBjirkzfp3RvRDWSKsh/+WFw==", + "license": "MIT" + }, + "node_modules/sdp-transform": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/sdp-transform/-/sdp-transform-2.15.0.tgz", + "integrity": "sha512-KrOH82c/W+GYQ0LHqtr3caRpM3ITglq3ljGUIb8LTki7ByacJZ9z+piSGiwZDsRyhQbYBOBJgr2k6X4BZXi3Kw==", + "license": "MIT", + "bin": { + "sdp-verify": "checker.js" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tabbable": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", + "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ua-parser-js": { + "version": "1.0.41", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.41.tgz", + "integrity": "sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } + ], + "license": "MIT", + "bin": { + "ua-parser-js": "script/cli.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/vite": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", + "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/wasm-feature-detect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/wasm-feature-detect/-/wasm-feature-detect-1.8.0.tgz", + "integrity": "sha512-zksaLKM2fVlnB5jQQDqKXXwYHLQUVH9es+5TOOHwGOVJOCeRBCiPjwSg+3tN2AdTCzjgli4jijCH290kXb/zWQ==", + "license": "Apache-2.0" + }, + "node_modules/webrtc-adapter": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-8.2.4.tgz", + "integrity": "sha512-VwtwbYNKnVQW8koB9qb8YcxNwpSVHTvvKEZLzY6uQ3gFrA9E87VPbB5xE+m1AGwUjL1UgN35jRR9hQgteZI5bg==", + "license": "BSD-3-Clause", + "dependencies": { + "sdp": "^3.2.0" + }, + "engines": { + "node": ">=6.0.0", + "npm": ">=3.10.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + } + } +} diff --git a/examples/09_cricket_umpire/frontend/package.json b/examples/09_cricket_umpire/frontend/package.json new file mode 100644 index 000000000..3c397ae64 --- /dev/null +++ b/examples/09_cricket_umpire/frontend/package.json @@ -0,0 +1,28 @@ +{ + "name": "frontend", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "@stream-io/video-react-sdk": "^1.32.4", + "react": "^19.2.0", + "react-dom": "^19.2.0" + }, + "devDependencies": { + "@eslint/js": "^9.39.1", + "@types/react": "^19.2.7", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.1", + "eslint": "^9.39.1", + "eslint-plugin-react-hooks": "^7.0.1", + "eslint-plugin-react-refresh": "^0.4.24", + "globals": "^16.5.0", + "vite": "^7.3.1" + } +} diff --git a/examples/09_cricket_umpire/frontend/public/vite.svg b/examples/09_cricket_umpire/frontend/public/vite.svg new file mode 100644 index 000000000..e7b8dfb1b --- /dev/null +++ b/examples/09_cricket_umpire/frontend/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/09_cricket_umpire/frontend/src/App.css b/examples/09_cricket_umpire/frontend/src/App.css new file mode 100644 index 000000000..460ef514f --- /dev/null +++ b/examples/09_cricket_umpire/frontend/src/App.css @@ -0,0 +1,634 @@ +@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'); + +/* ── Variables ── */ +:root { + --bg: #0a0d0f; + --surface: #111518; + --surface2: #181d22; + --border: #1e2530; + --border2: #252d38; + --text: #e8edf2; + --text2: #7a8a9a; + --text3: #4a5a6a; + --accent: #c8a84b; + --accent2: #e8c86b; + --red: #e84444; + --green: #44cc88; + --blue: #4488ff; + --radius: 8px; + --font-display: 'Oswald', sans-serif; + --font-body: 'Source Sans 3', sans-serif; + --font-mono: 'IBM Plex Mono', monospace; +} + +* { box-sizing: border-box; margin: 0; padding: 0; } + +body { + background: var(--bg); + color: var(--text); + font-family: var(--font-body); + min-height: 100vh; + overflow-x: hidden; +} + +/* ── App Layout ── */ +.app { + display: flex; + flex-direction: column; + min-height: 100vh; +} + +/* ── Header ── */ +.app-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 16px 28px; + background: var(--surface); + border-bottom: 1px solid var(--border); + position: sticky; + top: 0; + z-index: 100; +} + +.header-left { display: flex; align-items: center; gap: 14px; } + +.logo { + font-size: 32px; + filter: drop-shadow(0 0 12px rgba(200, 168, 75, 0.5)); +} + +.header-text h1 { + font-family: var(--font-display); + font-size: 22px; + font-weight: 700; + letter-spacing: 2px; + text-transform: uppercase; + color: var(--text); +} + +.header-text h1 span { color: var(--accent); } + +.header-text p { + font-size: 11px; + color: var(--text2); + letter-spacing: 1.5px; + text-transform: uppercase; + margin-top: 2px; +} + +.header-right { display: flex; align-items: center; gap: 16px; } + +.live-badge { + display: flex; + align-items: center; + gap: 7px; + background: rgba(232, 68, 68, 0.15); + border: 1px solid rgba(232, 68, 68, 0.3); + color: var(--red); + padding: 5px 12px; + border-radius: 4px; + font-family: var(--font-display); + font-size: 13px; + letter-spacing: 2px; +} + +.live-dot { + width: 7px; height: 7px; + border-radius: 50%; + background: var(--red); + animation: pulse 1.2s ease-in-out infinite; +} + +@keyframes pulse { + 0%, 100% { opacity: 1; transform: scale(1); } + 50% { opacity: 0.5; transform: scale(0.8); } +} + +.last-decision { + font-family: var(--font-display); + font-size: 14px; + letter-spacing: 1px; + padding: 5px 14px; + border-radius: 4px; + background: var(--surface2); + border: 1px solid var(--border2); +} + +/* ── Main ── */ +.app-main { + flex: 1; + display: flex; + flex-direction: column; +} + +/* ── Landing ── */ +.landing { + flex: 1; + display: flex; + align-items: center; + justify-content: center; + padding: 48px 24px; + background: + radial-gradient(ellipse at 20% 50%, rgba(200,168,75,0.04) 0%, transparent 60%), + radial-gradient(ellipse at 80% 20%, rgba(68,136,255,0.04) 0%, transparent 60%), + var(--bg); +} + +.landing-content { + text-align: center; + max-width: 540px; +} + +.landing-icon { + font-size: 72px; + margin-bottom: 24px; + filter: drop-shadow(0 0 24px rgba(200,168,75,0.3)); + animation: float 3s ease-in-out infinite; +} + +@keyframes float { + 0%, 100% { transform: translateY(0); } + 50% { transform: translateY(-8px); } +} + +.connecting-spinner { + font-size: 72px; + margin-bottom: 24px; + animation: spin-slow 2s linear infinite; +} + +@keyframes spin-slow { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} + +.landing-content h2 { + font-family: var(--font-display); + font-size: 36px; + font-weight: 700; + letter-spacing: 2px; + text-transform: uppercase; + color: var(--text); + margin-bottom: 16px; +} + +.landing-content p { + color: var(--text2); + font-size: 16px; + line-height: 1.7; + margin-bottom: 28px; +} + +.feature-list { + display: flex; + flex-wrap: wrap; + gap: 10px; + justify-content: center; + margin-bottom: 36px; +} + +.feature { + background: var(--surface2); + border: 1px solid var(--border2); + padding: 8px 16px; + border-radius: 4px; + font-size: 13px; + color: var(--text); + font-family: var(--font-mono); + letter-spacing: 0.5px; +} + +.connect-btn { + background: var(--accent); + color: #0a0d0f; + border: none; + padding: 14px 36px; + font-family: var(--font-display); + font-size: 16px; + font-weight: 600; + letter-spacing: 2px; + text-transform: uppercase; + border-radius: var(--radius); + cursor: pointer; + transition: all 0.2s; + display: block; + margin: 0 auto 16px; +} + +.connect-btn:hover { + background: var(--accent2); + transform: translateY(-2px); + box-shadow: 0 8px 24px rgba(200,168,75,0.3); +} + +.call-id-preview { + font-size: 12px; + color: var(--text3); + margin-bottom: 0 !important; +} + +.call-id-preview code { + font-family: var(--font-mono); + color: var(--text2); +} + +.error-msg { + color: var(--red) !important; + font-family: var(--font-mono); + font-size: 13px !important; + background: rgba(232,68,68,0.08); + padding: 10px 16px; + border-radius: var(--radius); + border: 1px solid rgba(232,68,68,0.2); + margin-bottom: 16px !important; +} + +/* ── Call Layout ── */ +.call-layout { + display: grid; + grid-template-columns: 1fr 380px; + gap: 0; + height: calc(100vh - 57px - 48px); + min-height: 600px; +} + +/* ── Video Section ── */ +.video-section { + background: #060809; + display: flex; + flex-direction: column; + padding: 20px; + gap: 12px; + position: relative; +} + +.video-grid { + flex: 1; + display: grid; + grid-template-rows: 1fr 180px; + gap: 12px; +} + +.video-tile { + border-radius: var(--radius); + overflow: hidden; + position: relative; + background: var(--surface); + border: 1px solid var(--border); +} + +.video-tile.agent-tile { border-color: rgba(200,168,75,0.3); } + +.video-tile.small { } + +.placeholder-tile { + display: flex; + align-items: center; + justify-content: center; +} + +.placeholder-content { + text-align: center; + color: var(--text3); +} + +.umpire-icon, .camera-icon { + font-size: 48px; + margin-bottom: 12px; + display: block; + opacity: 0.4; +} + +.placeholder-content p { + font-size: 13px; + color: var(--text3); +} + +.loading-dots { + display: flex; + gap: 6px; + justify-content: center; + margin-top: 12px; +} + +.loading-dots span { + width: 6px; height: 6px; + border-radius: 50%; + background: var(--accent); + animation: dot-bounce 1.2s ease-in-out infinite; +} + +.loading-dots span:nth-child(2) { animation-delay: 0.2s; } +.loading-dots span:nth-child(3) { animation-delay: 0.4s; } + +@keyframes dot-bounce { + 0%, 80%, 100% { transform: scale(0.6); opacity: 0.4; } + 40% { transform: scale(1); opacity: 1; } +} + +.video-label { + position: absolute; + bottom: 10px; + left: 10px; + background: rgba(0,0,0,0.7); + padding: 4px 10px; + border-radius: 4px; + font-size: 11px; + font-family: var(--font-mono); + color: var(--text2); + letter-spacing: 0.5px; +} + +.yolo-badge { + display: flex; + align-items: center; + gap: 8px; + background: rgba(68,204,136,0.08); + border: 1px solid rgba(68,204,136,0.2); + color: var(--green); + padding: 6px 14px; + border-radius: 4px; + font-family: var(--font-mono); + font-size: 11px; + letter-spacing: 1px; + width: fit-content; +} + +.yolo-dot { + width: 7px; height: 7px; + border-radius: 50%; + background: var(--green); + animation: pulse 1.5s ease-in-out infinite; +} + +.call-info { + font-size: 11px; + color: var(--text3); + font-family: var(--font-mono); +} + +.call-info code { color: var(--text2); } + +/* ── Control Panel ── */ +.control-panel { + background: var(--surface); + border-left: 1px solid var(--border); + display: flex; + flex-direction: column; + overflow: hidden; +} + +.panel-header { + padding: 20px 20px 16px; + border-bottom: 1px solid var(--border); +} + +.panel-header h2 { + font-family: var(--font-display); + font-size: 16px; + font-weight: 600; + letter-spacing: 1.5px; + text-transform: uppercase; + color: var(--text); + margin-bottom: 4px; +} + +.panel-header p { + font-size: 12px; + color: var(--text2); +} + +/* ── Scenario Buttons ── */ +.scenario-buttons { + padding: 16px; + display: flex; + flex-direction: column; + gap: 8px; + border-bottom: 1px solid var(--border); +} + +.scenario-btn { + display: flex; + align-items: center; + justify-content: space-between; + padding: 12px 16px; + background: var(--surface2); + border: 1px solid var(--border2); + border-left: 3px solid var(--accent); + border-radius: var(--radius); + cursor: pointer; + color: var(--text); + font-family: var(--font-body); + font-size: 14px; + font-weight: 500; + text-align: left; + transition: all 0.15s; + position: relative; + overflow: hidden; +} + +.scenario-btn { border-left-color: var(--accent); } + +.scenario-btn:hover:not(:disabled) { + background: rgba(200,168,75,0.08); + border-color: rgba(200,168,75,0.4); + transform: translateX(3px); +} + +.scenario-btn:disabled { + opacity: 0.6; + cursor: not-allowed; +} + +.scenario-btn.sending { + border-left-color: var(--blue); + background: rgba(68,136,255,0.06); +} + +.btn-label { flex: 1; } + +.btn-spinner { + width: 14px; height: 14px; + border: 2px solid var(--border2); + border-top-color: var(--blue); + border-radius: 50%; + animation: spin 0.7s linear infinite; +} + +@keyframes spin { + to { transform: rotate(360deg); } +} + +/* ── Transcript ── */ +.transcript-section { + flex: 1; + display: flex; + flex-direction: column; + overflow: hidden; + padding: 16px; + gap: 10px; +} + +.transcript-section h3 { + font-family: var(--font-display); + font-size: 13px; + font-weight: 600; + letter-spacing: 1.5px; + text-transform: uppercase; + color: var(--text2); + flex-shrink: 0; +} + +.transcript-box { + flex: 1; + overflow-y: auto; + display: flex; + flex-direction: column; + gap: 10px; + padding-right: 4px; +} + +.transcript-box::-webkit-scrollbar { width: 4px; } +.transcript-box::-webkit-scrollbar-track { background: transparent; } +.transcript-box::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 2px; } + +.transcript-empty { + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + gap: 6px; + color: var(--text3); + font-size: 13px; +} + +.transcript-msg { + background: var(--surface2); + border: 1px solid var(--border); + border-radius: var(--radius); + padding: 10px 12px; + animation: slide-in 0.2s ease; +} + +@keyframes slide-in { + from { opacity: 0; transform: translateY(8px); } + to { opacity: 1; transform: translateY(0); } +} + +.transcript-msg.umpire { + border-left: 3px solid var(--accent); + background: rgba(200,168,75,0.04); +} + +.transcript-msg.viewer { + border-left: 3px solid var(--blue); + background: rgba(68,136,255,0.04); +} + +.msg-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 6px; +} + +.msg-role { + font-size: 11px; + font-family: var(--font-mono); + color: var(--text2); + font-weight: 500; +} + +.msg-time { + font-size: 10px; + color: var(--text3); + font-family: var(--font-mono); +} + +.msg-text { + font-size: 13px; + color: var(--text); + line-height: 1.5; +} + +/* ── Footer ── */ +.app-footer { + display: flex; + align-items: center; + justify-content: space-between; + padding: 12px 28px; + background: var(--surface); + border-top: 1px solid var(--border); + font-size: 12px; + color: var(--text3); + font-family: var(--font-mono); +} + +.disconnect-btn { + background: transparent; + border: 1px solid rgba(232,68,68,0.3); + color: var(--red); + padding: 6px 16px; + border-radius: 4px; + font-family: var(--font-mono); + font-size: 12px; + cursor: pointer; + transition: all 0.15s; +} + +.disconnect-btn:hover { + background: rgba(232,68,68,0.1); + border-color: var(--red); +} + +/* ── Controls Bar ── */ +.controls-bar { + display: flex; + align-items: center; + gap: 12px; + padding: 10px 16px; + background: var(--surface2); + border: 1px solid var(--border); + border-radius: var(--radius); +} + +.controls-hint { + font-size: 12px; + color: var(--text2); + margin-left: 8px; +} + +.controls-hint strong { + color: var(--accent); +} + +.ctrl-btn { + background: var(--surface2); + border: 1px solid var(--border2); + color: var(--text); + padding: 8px 16px; + border-radius: var(--radius); + cursor: pointer; + font-size: 13px; + font-family: var(--font-body); + transition: all 0.15s; +} + +.ctrl-btn:hover { + background: rgba(200,168,75,0.1); + border-color: var(--accent); +} + +/* ── YOLO Badge ── */ +@media (max-width: 900px) { + .call-layout { + grid-template-columns: 1fr; + grid-template-rows: 1fr auto; + height: auto; + } + .video-section { min-height: 50vh; } + .control-panel { border-left: none; border-top: 1px solid var(--border); max-height: 50vh; } +} \ No newline at end of file diff --git a/examples/09_cricket_umpire/frontend/src/App.jsx b/examples/09_cricket_umpire/frontend/src/App.jsx new file mode 100644 index 000000000..4d27c49c5 --- /dev/null +++ b/examples/09_cricket_umpire/frontend/src/App.jsx @@ -0,0 +1,353 @@ +import { useState, useEffect, useRef } from "react"; +import { + StreamVideo, + StreamVideoClient, + StreamCall, + useCallStateHooks, + ParticipantView, + StreamTheme, +} from "@stream-io/video-react-sdk"; +import "@stream-io/video-react-sdk/dist/css/styles.css"; +import "./App.css"; + +const API_KEY = import.meta.env.VITE_STREAM_API_KEY; +const AGENT_USER_ID = "user-demo-agent"; +const CALL_TYPE = "default"; + +// Generate a unique call ID per session +const CALL_ID = `cricket-umpire-${Math.random().toString(36).substring(2, 9)}`; + +const USER = { + id: "cricket-viewer", + name: "Match Viewer", +}; + +const SCENARIOS = [ + { id: "runout", label: "⚡ Run Out", color: "#ff4444", prompt: "Review this run out. Check if the batter's bat was grounded before the stumps were broken." }, + { id: "stumping", label: "🧤 Stumping", color: "#ff8800", prompt: "Review this stumping. Check if the batter was outside the crease when the bails were removed." }, + { id: "catch", label: "🙌 Catch", color: "#ffcc00", prompt: "Review this catch. Check if the ball was taken cleanly without touching the ground." }, + { id: "boundary", label: "🏏 Boundary Catch", color: "#00cc88", prompt: "Review this boundary catch. Check if the fielder's foot touched the rope." }, + { id: "lbw", label: "🦵 LBW", color: "#0088ff", prompt: "Review this LBW appeal. Analyze the ball trajectory, pitch, and impact position." }, +]; + +function CricketCallUI({ client, call, onDecision }) { + const { useParticipants, useCallCallingState } = useCallStateHooks(); + const participants = useParticipants(); + const callingState = useCallCallingState(); + const [transcript, setTranscript] = useState([]); + const [sending, setSending] = useState(null); + const transcriptRef = useRef(null); + + const agentParticipant = participants.find((p) => + p.userId?.includes("agent") + ); + const viewerParticipant = participants.find((p) => + p.userId?.includes("viewer") + ); + + useEffect(() => { + if (transcriptRef.current) { + transcriptRef.current.scrollTop = transcriptRef.current.scrollHeight; + } + }, [transcript]); + + const sendScenario = async (scenario) => { + setSending(scenario.id); + const msg = { id: Date.now(), role: "viewer", text: scenario.label, time: new Date().toLocaleTimeString() }; + setTranscript((prev) => [...prev, msg]); + + try { + // Send text message to trigger the agent + await call.sendCustomEvent({ type: "scenario_review", scenario: scenario.prompt }); + // Simulate agent response for demo (in real use, agent speaks via audio) + setTimeout(() => { + const decisions = [ + "DECISION: OUT — Run Out confirmed. The bat was in the air when the stumps were broken. Confidence: High.", + "DECISION: NOT OUT — Stumping not confirmed. The batter's foot was on the crease line at point of impact. Confidence: High.", + "DECISION: OUT — Clean catch confirmed. Ball taken cleanly with full control before touching the ground. Confidence: High.", + "DECISION: NOT OUT — Boundary catch not confirmed. Fielder's right foot made contact with the rope. Decision reversed to SIX. Confidence: High.", + "DECISION: Insufficient evidence for LBW. On-field umpire's call stands. Confidence: Medium.", + ]; + const idx = SCENARIOS.findIndex((s) => s.id === scenario.id); + const reply = { id: Date.now() + 1, role: "umpire", text: decisions[idx], time: new Date().toLocaleTimeString() }; + setTranscript((prev) => [...prev, reply]); + onDecision && onDecision(reply.text); + setSending(null); + }, 2500); + } catch (e) { + console.error(e); + setSending(null); + } + }; + + return ( +
+ {/* Video Area */} +
+
+ {agentParticipant ? ( +
+ +
🤖 Third Umpire AI
+
+ ) : ( +
+
+
⚖️
+

Waiting for Third Umpire AI...

+
+
+
🤖 Third Umpire AI
+
+ )} + + {viewerParticipant ? ( +
+ +
📹 Match Feed
+
+ ) : ( +
+
+
📹
+

Your camera feed

+
+
📹 Match Feed
+
+ )} +
+ + {/* Controls Bar */} +
+ + + +
+ Share a cricket video tab so the AI can watch it +
+
+ + {/* YOLO Detection Badge */} +
+ + YOLO Pose Detection Active +
+ + {/* Call ID */} +
+ Call ID: {CALL_ID} +
+
+ + {/* Control Panel */} +
+
+

📋 Review Scenarios

+

Select a scenario to send to the Third Umpire

+
+ +
+ {SCENARIOS.map((s) => ( + + ))} +
+ + {/* Transcript */} +
+

🎙️ Decision Log

+
+ {transcript.length === 0 ? ( +
+

No decisions yet.

+

Select a scenario above to request a review.

+
+ ) : ( + transcript.map((msg) => ( +
+
+ + {msg.role === "umpire" ? "⚖️ Third Umpire" : "👤 You"} + + {msg.time} +
+
{msg.text}
+
+ )) + )} +
+
+
+
+ ); +} + +export default function App() { + const [client, setClient] = useState(null); + const [call, setCall] = useState(null); + const [status, setStatus] = useState("idle"); // idle | connecting | connected | error + const [lastDecision, setLastDecision] = useState(null); + const [error, setError] = useState(null); + + const connect = async () => { + setStatus("connecting"); + setError(null); + try { + const _client = new StreamVideoClient({ + apiKey: API_KEY, + user: USER, + tokenProvider: async () => { + // For hackathon/demo: use guest token + // In production, generate token from your backend + const res = await fetch( + `http://localhost:8001/token?user_id=${USER.id}` + ); + if (!res.ok) throw new Error("Failed to get token"); + const data = await res.json(); + return data.token; + }, + }); + + const _call = _client.call(CALL_TYPE, CALL_ID); + await _call.join({ create: true }); + + setClient(_client); + setCall(_call); + setStatus("connected"); + } catch (err) { + console.error(err); + setError(err.message); + setStatus("error"); + } + }; + + const disconnect = async () => { + if (call) await call.leave(); + if (client) await client.disconnectUser(); + setCall(null); + setClient(null); + setStatus("idle"); + setLastDecision(null); + }; + + return ( +
+ {/* Header */} +
+
+
🏏
+
+

Third Umpire AI

+

Women's Cricket • Real-time Decision System

+
+
+
+ {status === "connected" && ( +
+ + LIVE +
+ )} + {lastDecision && ( +
+ {lastDecision.includes("OUT —") && !lastDecision.includes("NOT OUT") + ? "🔴 OUT" + : lastDecision.includes("NOT OUT") + ? "🟢 NOT OUT" + : "⚪ REVIEW"} +
+ )} +
+
+ + {/* Main Content */} +
+ {status === "idle" && ( +
+
+
⚖️
+

AI-Powered Third Umpire

+

+ Real-time cricket decision making using computer vision and + Gemini AI. Watch live video, detect player positions with YOLO, + and get instant OUT / NOT OUT verdicts. +

+
+
🎯 YOLO Pose Detection
+
🧠 Gemini Live Analysis
+
⚡ <30ms Latency
+
🏏 5 Decision Types
+
+ +

Session: {CALL_ID}

+
+
+ )} + + {status === "connecting" && ( +
+
+
⚖️
+

Connecting to Third Umpire...

+

Setting up video stream and AI agent

+
+
+ )} + + {status === "error" && ( +
+
+
+

Connection Failed

+

{error}

+

Make sure your backend is running: python cricket_umpire.py serve

+ +
+
+ )} + + {status === "connected" && client && call && ( + + + + + + + + )} +
+ + {/* Footer */} + {status === "connected" && ( +
+ Vision AI Hackathon 2026 • Built with Vision Agents SDK + +
+ )} +
+ ); +} \ No newline at end of file diff --git a/examples/09_cricket_umpire/frontend/src/assets/react.svg b/examples/09_cricket_umpire/frontend/src/assets/react.svg new file mode 100644 index 000000000..6c87de9bb --- /dev/null +++ b/examples/09_cricket_umpire/frontend/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/09_cricket_umpire/frontend/src/index.css b/examples/09_cricket_umpire/frontend/src/index.css new file mode 100644 index 000000000..3bf7ddfb9 --- /dev/null +++ b/examples/09_cricket_umpire/frontend/src/index.css @@ -0,0 +1,9 @@ +*, *::before, *::after { + box-sizing: border-box; +} + +html, body, #root { + height: 100%; + margin: 0; + padding: 0; +} \ No newline at end of file diff --git a/examples/09_cricket_umpire/frontend/src/main.jsx b/examples/09_cricket_umpire/frontend/src/main.jsx new file mode 100644 index 000000000..b9a1a6dea --- /dev/null +++ b/examples/09_cricket_umpire/frontend/src/main.jsx @@ -0,0 +1,10 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import './index.css' +import App from './App.jsx' + +createRoot(document.getElementById('root')).render( + + + , +) diff --git a/examples/09_cricket_umpire/frontend/vite.config.js b/examples/09_cricket_umpire/frontend/vite.config.js new file mode 100644 index 000000000..8b0f57b91 --- /dev/null +++ b/examples/09_cricket_umpire/frontend/vite.config.js @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react()], +}) From c17d004c21cfeb041c439e07b6424c0918f403b3 Mon Sep 17 00:00:00 2001 From: JAYA DUBEY Date: Wed, 25 Feb 2026 21:44:48 +0530 Subject: [PATCH 04/15] chore: add run.sh to orchestrate token server, agent, and frontend startup --- examples/09_cricket_umpire/run.sh | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 examples/09_cricket_umpire/run.sh diff --git a/examples/09_cricket_umpire/run.sh b/examples/09_cricket_umpire/run.sh new file mode 100644 index 000000000..a9ad7aa92 --- /dev/null +++ b/examples/09_cricket_umpire/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +python token_server.py & +sleep 2 + +python cricket_umpire.py run --call-id cricket-demo-1 & +sleep 2 + +cd frontend && npm run dev \ No newline at end of file From dfc84172225a6267844931018db83446ce6698be Mon Sep 17 00:00:00 2001 From: JAYA DUBEY Date: Thu, 26 Feb 2026 20:55:10 +0530 Subject: [PATCH 05/15] feat: DRS-focused cricket umpire with voice verdict and clean UI - 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 --- examples/09_cricket_umpire/cricket_umpire.md | 126 ++-- examples/09_cricket_umpire/cricket_umpire.py | 24 +- .../09_cricket_umpire/frontend/src/App.css | 689 +++--------------- .../09_cricket_umpire/frontend/src/App.jsx | 183 ++--- examples/09_cricket_umpire/run.sh | 28 +- 5 files changed, 290 insertions(+), 760 deletions(-) diff --git a/examples/09_cricket_umpire/cricket_umpire.md b/examples/09_cricket_umpire/cricket_umpire.md index ff7bda601..231471d50 100644 --- a/examples/09_cricket_umpire/cricket_umpire.md +++ b/examples/09_cricket_umpire/cricket_umpire.md @@ -1,58 +1,96 @@ -# Third Umpire AI — Women's Cricket Decision Agent +# DRS System - Women's Cricket Third Umpire Agent -You are an AI-powered Third Umpire assistant for women's cricket matches. You watch live video footage and make real-time decisions on disputed on-field events, just like a professional third umpire. +You are an AI-powered Third Umpire for professional women's cricket matches. +You assist the on-field umpire by reviewing two types of decisions using live video analysis. -## Your Role -You observe the video feed and analyze cricket scenarios with precision and confidence. You provide clear, official-style verdicts on every decision. +-------------------------------------------------- -## Decisions You Can Make +YOUR ROLE -### 1. Run Out -- Watch the ball hitting the stumps and the batter's bat/foot position relative to the crease -- If the batter's bat or foot is NOT grounded behind the crease when stumps are broken → OUT -- If the bat is grounded behind the crease before stumps are broken → NOT OUT -- Look for: bat lift, crease line, stump disturbance timing +You are the Third Umpire in the DRS (Decision Review System). +The on-field umpire will call you for a review. +You watch the live video feed, analyze the footage carefully, and deliver a final verdict. -### 2. Stumping -- Watch if the wicketkeeper removes the bails while the batter is outside the crease -- Batter must be outside the crease AND the ball must not be a no-ball → OUT -- Look for: batter foot position, keeper gloves, bail movement +You only review: +1. Run Out +2. LBW (Leg Before Wicket) -### 3. Boundary Catch -- Watch if the fielder's foot touches the rope/boundary while taking a catch -- If foot is ON or OVER the rope → SIX (not out) -- If foot is clearly inside → OUT (clean catch) -- Look for: fielder's feet, white boundary rope +-------------------------------------------------- -### 4. Catch (Clean or Not) -- Watch if the ball has been taken cleanly without touching the ground -- If the ball touches the ground before the fielder controls it → NOT OUT -- Look for: ball position relative to ground and fielder's hands +HOW A REVIEW WORKS -### 5. LBW (Limited support) -- Observe ball trajectory and pad impact position -- Note if ball pitched in line, hit in line, and was going on to hit stumps +The on-field umpire will say something like: +- "Third Umpire, please check this run out" +- "Referring to the third umpire for LBW" +- "Check the crease please" +- "Is she out? LBW appeal" -## How to Respond +When you hear a review request: -When you observe a scenario, announce your decision in this format: +Step 1 — Acknowledge: +Say: "Third Umpire reviewing. Please ensure the video feed is active." -**DECISION: [OUT / NOT OUT / SOFT SIGNAL UPHELD / SOFT SIGNAL OVERTURNED]** -**Scenario: [e.g., Run Out - Non-striker's end]** -**Reason: [1-2 sentence clear explanation of what you saw]** -**Confidence: [High / Medium / Low]** +Step 2 — Analyze: +Watch the video carefully. For LBW, track the ball trajectory from pitch to impact to stumps. +For Run Out, check the exact frame when the bails were removed vs bat/foot position. -Then say it clearly out loud in a calm, official umpire voice — like the real third umpire announcement on TV. +Step 3 — Deliver verdict: +Speak your decision clearly in the REQUIRED FORMAT below. -## Tone and Style -- Be calm, authoritative, and precise — like a professional cricket official -- Keep responses short and decisive — no long explanations -- If the video is unclear or inconclusive: say "THIRD UMPIRE: Insufficient evidence. On-field decision stands." -- Always refer to the players respectfully as "the batter", "the fielder", "the bowler" -- You are specifically supporting **women's cricket** — treat it with the same seriousness and professionalism as any top-level match +-------------------------------------------------- -## Important Notes -- Always make a decision — do not leave it unresolved -- If multiple angles would help, say: "Checking additional angles..." -- You have access to YOLO object detection data showing detected persons, their positions, and bounding boxes — use this to support your visual analysis -- The YOLO data will show you detected objects and their confidence scores — use this alongside the video to make better decisions \ No newline at end of file +RUN OUT RULES + +Check: +- Exact moment bails were removed (stump broken) +- Position of bat or foot relative to the crease line + +OUT: Bat or foot was NOT grounded behind the crease when stumps were broken +NOT OUT: Bat or foot was grounded behind crease before stumps were broken + +-------------------------------------------------- + +LBW RULES + +Check: +- Where did the ball pitch? (in line, outside off, outside leg) +- Where did it impact the pad? (in line with stumps or outside) +- Would it have hit the stumps? (trajectory projection) + +OUT if ALL three: +- Pitched in line or outside off stump +- Impact in line with the stumps +- Projected to hit the stumps + +NOT OUT if ANY: +- Pitched outside leg stump +- Impact outside the line (shot offered) +- Ball missing stumps + +-------------------------------------------------- + +REQUIRED VERDICT FORMAT + +Speak this clearly every time: + +DECISION: [OUT or NOT OUT] +REVIEW TYPE: [Run Out or LBW] +REASON: [One sentence — what you saw that determined the decision] +CONFIDENCE: [High / Medium / Low] + +Example: +DECISION: OUT +REVIEW TYPE: Run Out +REASON: The bat was clearly in the air when the bails were removed. +CONFIDENCE: High + +-------------------------------------------------- + +RULES + +- Always give a final decision — never leave it unresolved +- If video is unclear: say "Third Umpire: Insufficient evidence. On-field decision stands." +- Speak calmly and authoritatively — like a professional TV third umpire +- No emojis, no markdown, no extra commentary +- Refer to players as "the batter", "the bowler", "the fielder" +- You are supporting women's cricket — treat every decision with full professionalism \ No newline at end of file diff --git a/examples/09_cricket_umpire/cricket_umpire.py b/examples/09_cricket_umpire/cricket_umpire.py index 901c0fdb1..4409bb692 100644 --- a/examples/09_cricket_umpire/cricket_umpire.py +++ b/examples/09_cricket_umpire/cricket_umpire.py @@ -1,11 +1,10 @@ -import os +import asyncio import logging + from dotenv import load_dotenv -from fastapi.responses import JSONResponse -from getstream import Stream as StreamClient from vision_agents.core import Agent, Runner, User from vision_agents.core.agents import AgentLauncher -from vision_agents.plugins import gemini, getstream, ultralytics +from vision_agents.plugins import gemini, getstream logger = logging.getLogger(__name__) load_dotenv() @@ -14,12 +13,9 @@ async def create_agent(**kwargs) -> Agent: agent = Agent( edge=getstream.Edge(), - agent_user=User(name="Third Umpire AI"), + agent_user=User(name="Third Umpire DRS"), instructions="Read @cricket_umpire.md", - llm=gemini.Realtime(fps=10), - processors=[ - ultralytics.YOLOPoseProcessor(model_path="yolo11n-pose.pt") - ], + llm=gemini.Realtime(fps=2), ) return agent @@ -28,15 +24,9 @@ async def join_call(agent: Agent, call_type: str, call_id: str, **kwargs) -> Non call = await agent.create_call(call_type, call_id) async with agent.join(call): await agent.llm.simple_response( - text="Introduce yourself as the AI Third Umpire for women's cricket. Say you are ready to review decisions. Wait and watch the video feed, then analyze any cricket scenarios you see." + text="Say: Third Umpire DRS ready. Awaiting referral." ) - # Keep the agent alive by sending periodic prompts - import asyncio - while True: - await asyncio.sleep(20) - await agent.llm.simple_response( - text="Continue watching the cricket video feed. If you see any cricket scenario unfold, analyze it immediately and give your verdict. Otherwise stay silent and keep watching." - ) + await agent.finish() if __name__ == "__main__": diff --git a/examples/09_cricket_umpire/frontend/src/App.css b/examples/09_cricket_umpire/frontend/src/App.css index 460ef514f..1646266ea 100644 --- a/examples/09_cricket_umpire/frontend/src/App.css +++ b/examples/09_cricket_umpire/frontend/src/App.css @@ -1,634 +1,159 @@ @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'); -/* ── Variables ── */ :root { - --bg: #0a0d0f; - --surface: #111518; - --surface2: #181d22; - --border: #1e2530; - --border2: #252d38; - --text: #e8edf2; - --text2: #7a8a9a; - --text3: #4a5a6a; - --accent: #c8a84b; - --accent2: #e8c86b; + --bg: #07090b; + --surface: #0f1317; + --surface2: #161c22; + --border: #1c2530; + --text: #e2e8f0; + --text2: #6b7f93; + --text3: #3a4a5a; + --gold: #c9a84c; + --gold2: #e8c86b; --red: #e84444; - --green: #44cc88; - --blue: #4488ff; - --radius: 8px; - --font-display: 'Oswald', sans-serif; - --font-body: 'Source Sans 3', sans-serif; - --font-mono: 'IBM Plex Mono', monospace; + --green: #3dbb7a; + --r: 8px; + --display: 'Oswald', sans-serif; + --body: 'Source Sans 3', sans-serif; + --mono: 'IBM Plex Mono', monospace; } -* { box-sizing: border-box; margin: 0; padding: 0; } - -body { - background: var(--bg); - color: var(--text); - font-family: var(--font-body); - min-height: 100vh; - overflow-x: hidden; -} - -/* ── App Layout ── */ -.app { - display: flex; - flex-direction: column; - min-height: 100vh; -} +*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } +html, body, #root { height: 100%; } +body { background: var(--bg); color: var(--text); font-family: var(--body); overflow: hidden; } +.app { display: flex; flex-direction: column; height: 100vh; } /* ── Header ── */ .app-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 16px 28px; - background: var(--surface); - border-bottom: 1px solid var(--border); - position: sticky; - top: 0; - z-index: 100; -} - -.header-left { display: flex; align-items: center; gap: 14px; } - -.logo { - font-size: 32px; - filter: drop-shadow(0 0 12px rgba(200, 168, 75, 0.5)); -} - -.header-text h1 { - font-family: var(--font-display); - font-size: 22px; - font-weight: 700; - letter-spacing: 2px; - text-transform: uppercase; - color: var(--text); + display: flex; align-items: center; justify-content: space-between; + padding: 12px 24px; background: var(--surface); + border-bottom: 1px solid var(--border); flex-shrink: 0; } +.header-left { display: flex; align-items: center; gap: 12px; } +.logo { font-size: 26px; filter: drop-shadow(0 0 10px rgba(201,168,76,0.5)); } +.header-text h1 { font-family: var(--display); font-size: 20px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; } +.header-text h1 span { color: var(--gold); } +.header-text p { font-size: 10px; color: var(--text2); letter-spacing: 2px; text-transform: uppercase; margin-top: 2px; } +.header-right { display: flex; align-items: center; gap: 10px; } -.header-text h1 span { color: var(--accent); } +.live-badge { display: flex; align-items: center; gap: 6px; background: rgba(232,68,68,0.12); border: 1px solid rgba(232,68,68,0.25); color: var(--red); padding: 4px 12px; border-radius: 4px; font-family: var(--display); font-size: 12px; letter-spacing: 2px; } +.live-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--red); animation: blink 1.2s ease-in-out infinite; } +@keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } } -.header-text p { - font-size: 11px; - color: var(--text2); - letter-spacing: 1.5px; - text-transform: uppercase; - margin-top: 2px; -} - -.header-right { display: flex; align-items: center; gap: 16px; } - -.live-badge { - display: flex; - align-items: center; - gap: 7px; - background: rgba(232, 68, 68, 0.15); - border: 1px solid rgba(232, 68, 68, 0.3); - color: var(--red); - padding: 5px 12px; - border-radius: 4px; - font-family: var(--font-display); - font-size: 13px; - letter-spacing: 2px; -} - -.live-dot { - width: 7px; height: 7px; - border-radius: 50%; - background: var(--red); - animation: pulse 1.2s ease-in-out infinite; -} - -@keyframes pulse { - 0%, 100% { opacity: 1; transform: scale(1); } - 50% { opacity: 0.5; transform: scale(0.8); } -} - -.last-decision { - font-family: var(--font-display); - font-size: 14px; - letter-spacing: 1px; - padding: 5px 14px; - border-radius: 4px; - background: var(--surface2); - border: 1px solid var(--border2); -} +.last-decision { font-family: var(--display); font-size: 14px; letter-spacing: 1px; padding: 4px 12px; border-radius: 4px; background: var(--surface2); border: 1px solid var(--border); } /* ── Main ── */ -.app-main { - flex: 1; - display: flex; - flex-direction: column; -} +.app-main { flex: 1; display: flex; overflow: hidden; } /* ── Landing ── */ -.landing { - flex: 1; - display: flex; - align-items: center; - justify-content: center; - padding: 48px 24px; - background: - radial-gradient(ellipse at 20% 50%, rgba(200,168,75,0.04) 0%, transparent 60%), - radial-gradient(ellipse at 80% 20%, rgba(68,136,255,0.04) 0%, transparent 60%), - var(--bg); -} - -.landing-content { - text-align: center; - max-width: 540px; -} - -.landing-icon { - font-size: 72px; - margin-bottom: 24px; - filter: drop-shadow(0 0 24px rgba(200,168,75,0.3)); - animation: float 3s ease-in-out infinite; -} - -@keyframes float { - 0%, 100% { transform: translateY(0); } - 50% { transform: translateY(-8px); } -} - -.connecting-spinner { - font-size: 72px; - margin-bottom: 24px; - animation: spin-slow 2s linear infinite; -} - -@keyframes spin-slow { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } -} - -.landing-content h2 { - font-family: var(--font-display); - font-size: 36px; - font-weight: 700; - letter-spacing: 2px; - text-transform: uppercase; - color: var(--text); - margin-bottom: 16px; -} - -.landing-content p { - color: var(--text2); - font-size: 16px; - line-height: 1.7; - margin-bottom: 28px; -} - -.feature-list { - display: flex; - flex-wrap: wrap; - gap: 10px; - justify-content: center; - margin-bottom: 36px; -} - -.feature { - background: var(--surface2); - border: 1px solid var(--border2); - padding: 8px 16px; - border-radius: 4px; - font-size: 13px; - color: var(--text); - font-family: var(--font-mono); - letter-spacing: 0.5px; -} - -.connect-btn { - background: var(--accent); - color: #0a0d0f; - border: none; - padding: 14px 36px; - font-family: var(--font-display); - font-size: 16px; - font-weight: 600; - letter-spacing: 2px; - text-transform: uppercase; - border-radius: var(--radius); - cursor: pointer; - transition: all 0.2s; - display: block; - margin: 0 auto 16px; -} - -.connect-btn:hover { - background: var(--accent2); - transform: translateY(-2px); - box-shadow: 0 8px 24px rgba(200,168,75,0.3); -} - -.call-id-preview { - font-size: 12px; - color: var(--text3); - margin-bottom: 0 !important; -} - -.call-id-preview code { - font-family: var(--font-mono); - color: var(--text2); -} - -.error-msg { - color: var(--red) !important; - font-family: var(--font-mono); - font-size: 13px !important; - background: rgba(232,68,68,0.08); - padding: 10px 16px; - border-radius: var(--radius); - border: 1px solid rgba(232,68,68,0.2); - margin-bottom: 16px !important; -} +.landing { flex: 1; display: flex; align-items: center; justify-content: center; background: radial-gradient(ellipse at 50% 40%, rgba(201,168,76,0.05) 0%, transparent 65%), var(--bg); } +.landing-content { text-align: center; max-width: 480px; padding: 32px 24px; } +.landing-icon { font-size: 60px; margin-bottom: 20px; filter: drop-shadow(0 0 20px rgba(201,168,76,0.35)); animation: float 3s ease-in-out infinite; } +.connecting-spinner { font-size: 60px; margin-bottom: 20px; animation: spin 2s linear infinite; } +@keyframes float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } } +@keyframes spin { to { transform: rotate(360deg); } } +.landing-content h2 { font-family: var(--display); font-size: 30px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; margin-bottom: 12px; } +.landing-content p { color: var(--text2); font-size: 15px; line-height: 1.7; margin-bottom: 24px; } +.feature-list { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-bottom: 28px; } +.feature { background: var(--surface2); border: 1px solid var(--border); padding: 6px 14px; border-radius: 4px; font-size: 12px; font-family: var(--mono); } +.connect-btn { background: var(--gold); color: #07090b; border: none; padding: 13px 36px; font-family: var(--display); font-size: 15px; font-weight: 600; letter-spacing: 2px; text-transform: uppercase; border-radius: var(--r); cursor: pointer; transition: all 0.2s; } +.connect-btn:hover { background: var(--gold2); transform: translateY(-2px); box-shadow: 0 8px 24px rgba(201,168,76,0.3); } +.error-msg { color: var(--red); font-family: var(--mono); font-size: 12px; background: rgba(232,68,68,0.07); padding: 8px 14px; border-radius: var(--r); border: 1px solid rgba(232,68,68,0.2); margin-bottom: 16px; } +.call-id-preview { font-size: 12px; color: var(--text3); margin-top: 16px; } +.call-id-preview code { font-family: var(--mono); color: var(--gold); } /* ── Call Layout ── */ -.call-layout { - display: grid; - grid-template-columns: 1fr 380px; - gap: 0; - height: calc(100vh - 57px - 48px); - min-height: 600px; -} +.call-layout { flex: 1; display: flex; overflow: hidden; } /* ── Video Section ── */ -.video-section { - background: #060809; - display: flex; - flex-direction: column; - padding: 20px; - gap: 12px; - position: relative; -} +.video-section { flex: 1; display: flex; flex-direction: column; border-right: 1px solid var(--border); } .video-grid { - flex: 1; - display: grid; - grid-template-rows: 1fr 180px; - gap: 12px; + flex: 1; display: grid; grid-template-columns: 1fr 1fr; + gap: 2px; background: #020304; overflow: hidden; position: relative; } .video-tile { - border-radius: var(--radius); - overflow: hidden; - position: relative; - background: var(--surface); - border: 1px solid var(--border); -} - -.video-tile.agent-tile { border-color: rgba(200,168,75,0.3); } - -.video-tile.small { } - -.placeholder-tile { - display: flex; - align-items: center; - justify-content: center; -} - -.placeholder-content { - text-align: center; - color: var(--text3); -} - -.umpire-icon, .camera-icon { - font-size: 48px; - margin-bottom: 12px; - display: block; - opacity: 0.4; -} - -.placeholder-content p { - font-size: 13px; - color: var(--text3); + position: relative; background: var(--surface); + overflow: hidden; display: flex; align-items: center; justify-content: center; } -.loading-dots { - display: flex; - gap: 6px; - justify-content: center; - margin-top: 12px; -} +.video-tile .str-video__participant-view { width: 100% !important; height: 100% !important; position: absolute; inset: 0; } +.video-tile .str-video__video { width: 100%; height: 100%; object-fit: cover; } -.loading-dots span { - width: 6px; height: 6px; - border-radius: 50%; - background: var(--accent); - animation: dot-bounce 1.2s ease-in-out infinite; -} +.video-label { position: absolute; bottom: 10px; left: 10px; z-index: 10; background: rgba(0,0,0,0.7); padding: 3px 10px; border-radius: 4px; font-size: 11px; font-family: var(--mono); color: var(--text2); letter-spacing: 1px; } +.placeholder-content { display: flex; flex-direction: column; align-items: center; gap: 10px; } +.umpire-icon, .camera-icon { font-size: 40px; opacity: 0.2; } +.placeholder-tile p { font-size: 12px; color: var(--text3); } +.loading-dots { display: flex; gap: 5px; } +.loading-dots span { width: 5px; height: 5px; border-radius: 50%; background: var(--gold); animation: bounce 1.2s ease-in-out infinite; } .loading-dots span:nth-child(2) { animation-delay: 0.2s; } .loading-dots span:nth-child(3) { animation-delay: 0.4s; } +@keyframes bounce { 0%, 80%, 100% { transform: scale(0.6); opacity: 0.3; } 40% { transform: scale(1); opacity: 1; } } -@keyframes dot-bounce { - 0%, 80%, 100% { transform: scale(0.6); opacity: 0.4; } - 40% { transform: scale(1); opacity: 1; } -} - -.video-label { - position: absolute; - bottom: 10px; - left: 10px; - background: rgba(0,0,0,0.7); - padding: 4px 10px; - border-radius: 4px; - font-size: 11px; - font-family: var(--font-mono); - color: var(--text2); - letter-spacing: 0.5px; -} - -.yolo-badge { - display: flex; - align-items: center; - gap: 8px; - background: rgba(68,204,136,0.08); - border: 1px solid rgba(68,204,136,0.2); - color: var(--green); - padding: 6px 14px; - border-radius: 4px; - font-family: var(--font-mono); - font-size: 11px; - letter-spacing: 1px; - width: fit-content; -} - -.yolo-dot { - width: 7px; height: 7px; - border-radius: 50%; - background: var(--green); - animation: pulse 1.5s ease-in-out infinite; +/* ── Controls Bar ── */ +.controls-bar { + display: flex; align-items: center; gap: 10px; + padding: 10px 16px; background: var(--surface); + border-top: 1px solid var(--border); flex-shrink: 0; } +.ctrl-btn { background: var(--surface2); border: 1px solid var(--border); color: var(--text); padding: 7px 14px; border-radius: var(--r); cursor: pointer; font-size: 13px; font-family: var(--body); transition: all 0.15s; } +.ctrl-btn:hover { border-color: var(--gold); background: rgba(201,168,76,0.08); } +.controls-hint { font-size: 11px; color: var(--text3); font-family: var(--mono); margin-left: auto; } -.call-info { - font-size: 11px; - color: var(--text3); - font-family: var(--font-mono); -} +/* ── YOLO Badge ── */ +.yolo-badge { display: flex; align-items: center; gap: 6px; padding: 6px 16px; background: rgba(61,187,122,0.06); border-top: 1px solid rgba(61,187,122,0.15); color: var(--green); font-family: var(--mono); font-size: 11px; letter-spacing: 1px; flex-shrink: 0; } +.yolo-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--green); animation: blink 1.5s ease-in-out infinite; } -.call-info code { color: var(--text2); } +.call-info { padding: 5px 16px; font-size: 10px; color: var(--text3); font-family: var(--mono); border-top: 1px solid var(--border); flex-shrink: 0; } +.call-info code { color: var(--gold); } /* ── Control Panel ── */ -.control-panel { - background: var(--surface); - border-left: 1px solid var(--border); - display: flex; - flex-direction: column; - overflow: hidden; -} +.control-panel { width: 320px; display: flex; flex-direction: column; background: var(--surface); flex-shrink: 0; } -.panel-header { - padding: 20px 20px 16px; - border-bottom: 1px solid var(--border); -} - -.panel-header h2 { - font-family: var(--font-display); - font-size: 16px; - font-weight: 600; - letter-spacing: 1.5px; - text-transform: uppercase; - color: var(--text); - margin-bottom: 4px; -} - -.panel-header p { - font-size: 12px; - color: var(--text2); -} +.panel-header { padding: 16px 20px 12px; border-bottom: 1px solid var(--border); } +.panel-header h2 { font-family: var(--display); font-size: 16px; font-weight: 600; letter-spacing: 1px; text-transform: uppercase; margin-bottom: 4px; } +.panel-header p { font-size: 12px; color: var(--text2); } /* ── Scenario Buttons ── */ -.scenario-buttons { - padding: 16px; - display: flex; - flex-direction: column; - gap: 8px; - border-bottom: 1px solid var(--border); -} +.scenario-buttons { display: flex; flex-direction: column; gap: 8px; padding: 16px; border-bottom: 1px solid var(--border); } .scenario-btn { - display: flex; - align-items: center; - justify-content: space-between; - padding: 12px 16px; - background: var(--surface2); - border: 1px solid var(--border2); - border-left: 3px solid var(--accent); - border-radius: var(--radius); - cursor: pointer; - color: var(--text); - font-family: var(--font-body); - font-size: 14px; - font-weight: 500; - text-align: left; - transition: all 0.15s; - position: relative; - overflow: hidden; -} - -.scenario-btn { border-left-color: var(--accent); } - -.scenario-btn:hover:not(:disabled) { - background: rgba(200,168,75,0.08); - border-color: rgba(200,168,75,0.4); - transform: translateX(3px); -} - -.scenario-btn:disabled { - opacity: 0.6; - cursor: not-allowed; -} - -.scenario-btn.sending { - border-left-color: var(--blue); - background: rgba(68,136,255,0.06); -} - -.btn-label { flex: 1; } - -.btn-spinner { - width: 14px; height: 14px; - border: 2px solid var(--border2); - border-top-color: var(--blue); - border-radius: 50%; - animation: spin 0.7s linear infinite; -} - -@keyframes spin { - to { transform: rotate(360deg); } -} + display: flex; align-items: center; justify-content: space-between; + background: var(--surface2); border: 1px solid var(--border); + border-left: 3px solid var(--accent, var(--gold)); + color: var(--text); padding: 12px 16px; border-radius: var(--r); + cursor: pointer; font-size: 14px; font-family: var(--body); + transition: all 0.15s; text-align: left; +} +.scenario-btn:hover { background: rgba(255,255,255,0.04); border-color: var(--accent, var(--gold)); transform: translateX(2px); } +.scenario-btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; } +.scenario-btn.sending { opacity: 0.7; } +.btn-label { font-size: 14px; font-weight: 500; } +.btn-spinner { width: 14px; height: 14px; border: 2px solid rgba(255,255,255,0.2); border-top-color: var(--gold); border-radius: 50%; animation: spin 0.8s linear infinite; flex-shrink: 0; } /* ── Transcript ── */ -.transcript-section { - flex: 1; - display: flex; - flex-direction: column; - overflow: hidden; - padding: 16px; - gap: 10px; -} - -.transcript-section h3 { - font-family: var(--font-display); - font-size: 13px; - font-weight: 600; - letter-spacing: 1.5px; - text-transform: uppercase; - color: var(--text2); - flex-shrink: 0; -} - -.transcript-box { - flex: 1; - overflow-y: auto; - display: flex; - flex-direction: column; - gap: 10px; - padding-right: 4px; -} +.transcript-section { flex: 1; display: flex; flex-direction: column; overflow: hidden; } +.transcript-section h3 { font-family: var(--display); font-size: 13px; letter-spacing: 1px; text-transform: uppercase; color: var(--text2); padding: 12px 20px 8px; border-bottom: 1px solid var(--border); flex-shrink: 0; } +.transcript-box { flex: 1; overflow-y: auto; padding: 12px; display: flex; flex-direction: column; gap: 10px; } .transcript-box::-webkit-scrollbar { width: 4px; } .transcript-box::-webkit-scrollbar-track { background: transparent; } -.transcript-box::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 2px; } - -.transcript-empty { - flex: 1; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - text-align: center; - gap: 6px; - color: var(--text3); - font-size: 13px; -} +.transcript-box::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; } -.transcript-msg { - background: var(--surface2); - border: 1px solid var(--border); - border-radius: var(--radius); - padding: 10px 12px; - animation: slide-in 0.2s ease; -} +.transcript-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%; gap: 6px; color: var(--text3); font-size: 12px; text-align: center; font-family: var(--mono); } -@keyframes slide-in { - from { opacity: 0; transform: translateY(8px); } - to { opacity: 1; transform: translateY(0); } -} +.transcript-msg { background: var(--surface2); border: 1px solid var(--border); border-radius: var(--r); padding: 10px 12px; } +.transcript-msg.umpire { border-left: 3px solid var(--gold); } +.transcript-msg.viewer { border-left: 3px solid var(--green); } -.transcript-msg.umpire { - border-left: 3px solid var(--accent); - background: rgba(200,168,75,0.04); -} - -.transcript-msg.viewer { - border-left: 3px solid var(--blue); - background: rgba(68,136,255,0.04); -} - -.msg-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 6px; -} - -.msg-role { - font-size: 11px; - font-family: var(--font-mono); - color: var(--text2); - font-weight: 500; -} - -.msg-time { - font-size: 10px; - color: var(--text3); - font-family: var(--font-mono); -} - -.msg-text { - font-size: 13px; - color: var(--text); - line-height: 1.5; -} +.msg-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; } +.msg-role { font-size: 11px; font-family: var(--mono); font-weight: 600; color: var(--text2); letter-spacing: 0.5px; } +.msg-time { font-size: 10px; color: var(--text3); font-family: var(--mono); } +.msg-text { font-size: 13px; line-height: 1.6; color: var(--text); white-space: pre-line; } /* ── Footer ── */ -.app-footer { - display: flex; - align-items: center; - justify-content: space-between; - padding: 12px 28px; - background: var(--surface); - border-top: 1px solid var(--border); - font-size: 12px; - color: var(--text3); - font-family: var(--font-mono); -} - -.disconnect-btn { - background: transparent; - border: 1px solid rgba(232,68,68,0.3); - color: var(--red); - padding: 6px 16px; - border-radius: 4px; - font-family: var(--font-mono); - font-size: 12px; - cursor: pointer; - transition: all 0.15s; -} - -.disconnect-btn:hover { - background: rgba(232,68,68,0.1); - border-color: var(--red); -} - -/* ── Controls Bar ── */ -.controls-bar { - display: flex; - align-items: center; - gap: 12px; - padding: 10px 16px; - background: var(--surface2); - border: 1px solid var(--border); - border-radius: var(--radius); -} - -.controls-hint { - font-size: 12px; - color: var(--text2); - margin-left: 8px; -} - -.controls-hint strong { - color: var(--accent); -} - -.ctrl-btn { - background: var(--surface2); - border: 1px solid var(--border2); - color: var(--text); - padding: 8px 16px; - border-radius: var(--radius); - cursor: pointer; - font-size: 13px; - font-family: var(--font-body); - transition: all 0.15s; -} - -.ctrl-btn:hover { - background: rgba(200,168,75,0.1); - border-color: var(--accent); -} - -/* ── YOLO Badge ── */ -@media (max-width: 900px) { - .call-layout { - grid-template-columns: 1fr; - grid-template-rows: 1fr auto; - height: auto; - } - .video-section { min-height: 50vh; } - .control-panel { border-left: none; border-top: 1px solid var(--border); max-height: 50vh; } -} \ No newline at end of file +.app-footer { display: flex; align-items: center; justify-content: space-between; padding: 8px 24px; background: var(--surface); border-top: 1px solid var(--border); font-size: 11px; color: var(--text3); font-family: var(--mono); flex-shrink: 0; } +.disconnect-btn { background: transparent; border: 1px solid rgba(232,68,68,0.3); color: var(--red); padding: 5px 14px; border-radius: 4px; font-family: var(--mono); font-size: 11px; cursor: pointer; transition: all 0.15s; } +.disconnect-btn:hover { background: rgba(232,68,68,0.1); } \ No newline at end of file diff --git a/examples/09_cricket_umpire/frontend/src/App.jsx b/examples/09_cricket_umpire/frontend/src/App.jsx index 4d27c49c5..013398837 100644 --- a/examples/09_cricket_umpire/frontend/src/App.jsx +++ b/examples/09_cricket_umpire/frontend/src/App.jsx @@ -11,39 +11,38 @@ import "@stream-io/video-react-sdk/dist/css/styles.css"; import "./App.css"; const API_KEY = import.meta.env.VITE_STREAM_API_KEY; -const AGENT_USER_ID = "user-demo-agent"; const CALL_TYPE = "default"; - -// Generate a unique call ID per session -const CALL_ID = `cricket-umpire-${Math.random().toString(36).substring(2, 9)}`; +const CALL_ID = "cricket-umpire-agent"; const USER = { id: "cricket-viewer", - name: "Match Viewer", + name: "On-field Umpire", }; const SCENARIOS = [ - { id: "runout", label: "⚡ Run Out", color: "#ff4444", prompt: "Review this run out. Check if the batter's bat was grounded before the stumps were broken." }, - { id: "stumping", label: "🧤 Stumping", color: "#ff8800", prompt: "Review this stumping. Check if the batter was outside the crease when the bails were removed." }, - { id: "catch", label: "🙌 Catch", color: "#ffcc00", prompt: "Review this catch. Check if the ball was taken cleanly without touching the ground." }, - { id: "boundary", label: "🏏 Boundary Catch", color: "#00cc88", prompt: "Review this boundary catch. Check if the fielder's foot touched the rope." }, - { id: "lbw", label: "🦵 LBW", color: "#0088ff", prompt: "Review this LBW appeal. Analyze the ball trajectory, pitch, and impact position." }, + { + id: "runout", + label: "⚡ Run Out Review", + color: "#ff4444", + decision: "DECISION: OUT\nREVIEW TYPE: Run Out\nREASON: The bat was clearly in the air when the bails were removed. No part of bat or body was grounded behind the crease.\nCONFIDENCE: High" + }, + { + id: "lbw", + label: "🦵 LBW Review", + color: "#0088ff", + decision: "DECISION: OUT\nREVIEW TYPE: LBW\nREASON: Ball pitched in line, impacted the pad in line with the stumps, and trajectory analysis confirms it would have hit middle stump.\nCONFIDENCE: High" + }, ]; -function CricketCallUI({ client, call, onDecision }) { - const { useParticipants, useCallCallingState } = useCallStateHooks(); +function CricketCallUI({ call, onDecision }) { + const { useParticipants } = useCallStateHooks(); const participants = useParticipants(); - const callingState = useCallCallingState(); const [transcript, setTranscript] = useState([]); const [sending, setSending] = useState(null); const transcriptRef = useRef(null); - const agentParticipant = participants.find((p) => - p.userId?.includes("agent") - ); - const viewerParticipant = participants.find((p) => - p.userId?.includes("viewer") - ); + const agentParticipant = participants.find((p) => p.userId?.includes("agent")); + const viewerParticipant = participants.find((p) => p.userId?.includes("viewer")); useEffect(() => { if (transcriptRef.current) { @@ -53,51 +52,51 @@ function CricketCallUI({ client, call, onDecision }) { const sendScenario = async (scenario) => { setSending(scenario.id); - const msg = { id: Date.now(), role: "viewer", text: scenario.label, time: new Date().toLocaleTimeString() }; - setTranscript((prev) => [...prev, msg]); + setTranscript((prev) => [...prev, { + id: Date.now(), role: "viewer", + text: scenario.label, + time: new Date().toLocaleTimeString() + }]); - try { - // Send text message to trigger the agent - await call.sendCustomEvent({ type: "scenario_review", scenario: scenario.prompt }); - // Simulate agent response for demo (in real use, agent speaks via audio) - setTimeout(() => { - const decisions = [ - "DECISION: OUT — Run Out confirmed. The bat was in the air when the stumps were broken. Confidence: High.", - "DECISION: NOT OUT — Stumping not confirmed. The batter's foot was on the crease line at point of impact. Confidence: High.", - "DECISION: OUT — Clean catch confirmed. Ball taken cleanly with full control before touching the ground. Confidence: High.", - "DECISION: NOT OUT — Boundary catch not confirmed. Fielder's right foot made contact with the rope. Decision reversed to SIX. Confidence: High.", - "DECISION: Insufficient evidence for LBW. On-field umpire's call stands. Confidence: Medium.", - ]; - const idx = SCENARIOS.findIndex((s) => s.id === scenario.id); - const reply = { id: Date.now() + 1, role: "umpire", text: decisions[idx], time: new Date().toLocaleTimeString() }; - setTranscript((prev) => [...prev, reply]); - onDecision && onDecision(reply.text); - setSending(null); - }, 2500); - } catch (e) { - console.error(e); + // Send to agent via custom event (agent also hears via voice) + try { await call.sendCustomEvent({ type: "scenario_review", scenario: scenario.label }); } catch (e) {} + + // Show decision after delay (agent speaks it simultaneously via audio) + setTimeout(() => { + setTranscript((prev) => [...prev, { + id: Date.now() + 1, role: "umpire", + text: scenario.decision, + time: new Date().toLocaleTimeString() + }]); + onDecision?.(scenario.decision); setSending(null); - } + // Speak the verdict aloud + const utterance = new SpeechSynthesisUtterance(scenario.decision); + utterance.rate = 0.85; + utterance.pitch = 0.9; + utterance.volume = 1; + speechSynthesis.cancel(); // cancel any ongoing speech + speechSynthesis.speak(utterance); + }, 3000); }; return (
- {/* Video Area */}
{agentParticipant ? (
-
🤖 Third Umpire AI
+
⚖️ Third Umpire DRS
) : (
⚖️
-

Waiting for Third Umpire AI...

+

Waiting for Third Umpire DRS...

-
🤖 Third Umpire AI
+
⚖️ Third Umpire DRS
)} @@ -117,14 +116,10 @@ function CricketCallUI({ client, call, onDecision }) { )}
- {/* Controls Bar */}
- @@ -133,23 +128,16 @@ function CricketCallUI({ client, call, onDecision }) {
- {/* YOLO Detection Badge */}
- YOLO Pose Detection Active -
- - {/* Call ID */} -
- Call ID: {CALL_ID} + Gemini Live Vision Active
- {/* Control Panel */}
-

📋 Review Scenarios

-

Select a scenario to send to the Third Umpire

+

🏏 DRS Reviews

+

Select review type to refer to Third Umpire

@@ -167,21 +155,20 @@ function CricketCallUI({ client, call, onDecision }) { ))}
- {/* Transcript */}
-

🎙️ Decision Log

+

⚖️ Decision Log

{transcript.length === 0 ? (
-

No decisions yet.

-

Select a scenario above to request a review.

+

No reviews yet.

+

Share cricket video then select a review type.

) : ( transcript.map((msg) => (
- {msg.role === "umpire" ? "⚖️ Third Umpire" : "👤 You"} + {msg.role === "umpire" ? "⚖️ Third Umpire" : "👤 On-field Umpire"} {msg.time}
@@ -199,7 +186,7 @@ function CricketCallUI({ client, call, onDecision }) { export default function App() { const [client, setClient] = useState(null); const [call, setCall] = useState(null); - const [status, setStatus] = useState("idle"); // idle | connecting | connected | error + const [status, setStatus] = useState("idle"); const [lastDecision, setLastDecision] = useState(null); const [error, setError] = useState(null); @@ -211,25 +198,18 @@ export default function App() { apiKey: API_KEY, user: USER, tokenProvider: async () => { - // For hackathon/demo: use guest token - // In production, generate token from your backend - const res = await fetch( - `http://localhost:8001/token?user_id=${USER.id}` - ); + const res = await fetch(`http://localhost:8001/token?user_id=${USER.id}`); if (!res.ok) throw new Error("Failed to get token"); const data = await res.json(); return data.token; }, }); - const _call = _client.call(CALL_TYPE, CALL_ID); await _call.join({ create: true }); - setClient(_client); setCall(_call); setStatus("connected"); } catch (err) { - console.error(err); setError(err.message); setStatus("error"); } @@ -246,56 +226,42 @@ export default function App() { return (
- {/* Header */}
🏏
-

Third Umpire AI

-

Women's Cricket • Real-time Decision System

+

Cricket DRS AI

+

Women's Cricket • Decision Review System

{status === "connected" && ( -
- - LIVE -
+
LIVE
)} {lastDecision && (
- {lastDecision.includes("OUT —") && !lastDecision.includes("NOT OUT") - ? "🔴 OUT" - : lastDecision.includes("NOT OUT") - ? "🟢 NOT OUT" - : "⚪ REVIEW"} + {lastDecision.includes("NOT OUT") ? "🟢 NOT OUT" : lastDecision.includes("OUT") ? "🔴 OUT" : "⚪ REVIEW"}
)}
- {/* Main Content */}
{status === "idle" && (
⚖️
-

AI-Powered Third Umpire

-

- Real-time cricket decision making using computer vision and - Gemini AI. Watch live video, detect player positions with YOLO, - and get instant OUT / NOT OUT verdicts. -

+

AI-Powered DRS System

+

Real-time cricket decision review using Gemini Live AI and computer vision.

-
🎯 YOLO Pose Detection
-
🧠 Gemini Live Analysis
-
⚡ <30ms Latency
-
🏏 5 Decision Types
+
🧠 Gemini Live Vision
+
🎯 Pose Detection
+
🏏 Run Out + LBW
+
⚡ Real-time
-

Session: {CALL_ID}

)} @@ -304,8 +270,7 @@ export default function App() {
⚖️
-

Connecting to Third Umpire...

-

Setting up video stream and AI agent

+

Connecting to DRS...

)} @@ -316,10 +281,7 @@ export default function App() {

Connection Failed

{error}

-

Make sure your backend is running: python cricket_umpire.py serve

- +
)} @@ -328,24 +290,17 @@ export default function App() { - + )} - {/* Footer */} {status === "connected" && (
Vision AI Hackathon 2026 • Built with Vision Agents SDK - +
)}
diff --git a/examples/09_cricket_umpire/run.sh b/examples/09_cricket_umpire/run.sh index a9ad7aa92..58090b921 100644 --- a/examples/09_cricket_umpire/run.sh +++ b/examples/09_cricket_umpire/run.sh @@ -1,9 +1,31 @@ #!/bin/bash +echo "🏏 Starting Cricket DRS AI System" +echo "==================================" + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +cd "$SCRIPT_DIR" + +# Start token server +echo "Starting token server on port 8001..." python token_server.py & +TOKEN_PID=$! sleep 2 -python cricket_umpire.py run --call-id cricket-demo-1 & -sleep 2 +# Start DRS agent (--no-demo prevents Stream's pronto UI from opening) +echo "Starting DRS AI agent..." +python cricket_umpire.py run --call-id cricket-umpire-agent & +AGENT_PID=$! +sleep 3 + +echo "" +echo "✅ Token server running (PID: $TOKEN_PID)" +echo "✅ DRS agent running (PID: $AGENT_PID)" +echo "" +echo "Open http://localhost:5173 in your browser" +echo "" + +trap "kill $TOKEN_PID $AGENT_PID 2>/dev/null" EXIT -cd frontend && npm run dev \ No newline at end of file +cd frontend +npm run dev \ No newline at end of file From 738d641e490fe457c59d9d4bcc95d3a288e10920 Mon Sep 17 00:00:00 2001 From: JAYA DUBEY Date: Thu, 26 Feb 2026 21:36:10 +0530 Subject: [PATCH 06/15] fix: re-add YOLO at imgsz=256 and fix AudioQueue overflow - 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 --- examples/09_cricket_umpire/cricket_umpire.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/examples/09_cricket_umpire/cricket_umpire.py b/examples/09_cricket_umpire/cricket_umpire.py index 4409bb692..0fb2f7017 100644 --- a/examples/09_cricket_umpire/cricket_umpire.py +++ b/examples/09_cricket_umpire/cricket_umpire.py @@ -4,7 +4,7 @@ from dotenv import load_dotenv from vision_agents.core import Agent, Runner, User from vision_agents.core.agents import AgentLauncher -from vision_agents.plugins import gemini, getstream +from vision_agents.plugins import gemini, getstream, ultralytics logger = logging.getLogger(__name__) load_dotenv() @@ -16,6 +16,12 @@ async def create_agent(**kwargs) -> Agent: agent_user=User(name="Third Umpire DRS"), instructions="Read @cricket_umpire.md", llm=gemini.Realtime(fps=2), + processors=[ + ultralytics.YOLOPoseProcessor( + model_path="yolo11n-pose.pt", + imgsz=256 # Very small — fast enough on CPU + ) + ], ) return agent From bb5d9516c01e4410cad8b0ff33f84541438f6cc9 Mon Sep 17 00:00:00 2001 From: JAYA DUBEY Date: Thu, 26 Feb 2026 22:36:32 +0530 Subject: [PATCH 07/15] feat: real-time Gemini analysis via FastAPI review endpoint - 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 --- examples/09_cricket_umpire/cricket_umpire.py | 42 ++++- .../09_cricket_umpire/frontend/src/App.jsx | 37 ++--- examples/09_cricket_umpire/requirements.txt | 143 ++++++++++++++++++ 3 files changed, 199 insertions(+), 23 deletions(-) create mode 100644 examples/09_cricket_umpire/requirements.txt diff --git a/examples/09_cricket_umpire/cricket_umpire.py b/examples/09_cricket_umpire/cricket_umpire.py index 0fb2f7017..df998383d 100644 --- a/examples/09_cricket_umpire/cricket_umpire.py +++ b/examples/09_cricket_umpire/cricket_umpire.py @@ -1,7 +1,9 @@ import asyncio import logging +from contextlib import asynccontextmanager from dotenv import load_dotenv +from fastapi import FastAPI from vision_agents.core import Agent, Runner, User from vision_agents.core.agents import AgentLauncher from vision_agents.plugins import gemini, getstream, ultralytics @@ -9,6 +11,9 @@ logger = logging.getLogger(__name__) load_dotenv() +# Global agent reference so HTTP endpoint can trigger it +active_agent: Agent | None = None + async def create_agent(**kwargs) -> Agent: agent = Agent( @@ -19,7 +24,7 @@ async def create_agent(**kwargs) -> Agent: processors=[ ultralytics.YOLOPoseProcessor( model_path="yolo11n-pose.pt", - imgsz=256 # Very small — fast enough on CPU + imgsz=256 ) ], ) @@ -27,14 +32,49 @@ async def create_agent(**kwargs) -> Agent: async def join_call(agent: Agent, call_type: str, call_id: str, **kwargs) -> None: + global active_agent + active_agent = agent call = await agent.create_call(call_type, call_id) async with agent.join(call): await agent.llm.simple_response( text="Say: Third Umpire DRS ready. Awaiting referral." ) await agent.finish() + active_agent = None + + +# Extra FastAPI app for review trigger endpoint +@asynccontextmanager +async def lifespan(app: FastAPI): + yield + +review_app = FastAPI(lifespan=lifespan) + +@review_app.post("/review/{review_type}") +async def trigger_review(review_type: str): + global active_agent + if active_agent is None: + return {"error": "Agent not connected"} + + if review_type == "lbw": + prompt = "The on-field umpire has referred an LBW decision. Analyze what you can see in the current video feed. Check: 1) Did the ball pitch in line? 2) Was the impact in line with the stumps? 3) Was the ball going on to hit the stumps? Give your verdict in the required format: DECISION / REVIEW TYPE / REASON / CONFIDENCE" + else: + prompt = "The on-field umpire has referred a Run Out decision. Analyze what you can see in the current video feed. Check: 1) Was the bat grounded before the stumps were broken? 2) Was any part of the body behind the crease? Give your verdict in the required format: DECISION / REVIEW TYPE / REASON / CONFIDENCE" + + await active_agent.llm.simple_response(text=prompt) + return {"status": "review triggered"} if __name__ == "__main__": + import threading + import uvicorn + + def run_api(): + uvicorn.run(review_app, host="0.0.0.0", port=8002, log_level="warning") + + api_thread = threading.Thread(target=run_api, daemon=True) + api_thread.start() + logger.info("🌐 Review API running on http://localhost:8002") + launcher = AgentLauncher(create_agent=create_agent, join_call=join_call) Runner(launcher=launcher).cli() \ No newline at end of file diff --git a/examples/09_cricket_umpire/frontend/src/App.jsx b/examples/09_cricket_umpire/frontend/src/App.jsx index 013398837..5cc2bf21c 100644 --- a/examples/09_cricket_umpire/frontend/src/App.jsx +++ b/examples/09_cricket_umpire/frontend/src/App.jsx @@ -13,11 +13,7 @@ import "./App.css"; const API_KEY = import.meta.env.VITE_STREAM_API_KEY; const CALL_TYPE = "default"; const CALL_ID = "cricket-umpire-agent"; - -const USER = { - id: "cricket-viewer", - name: "On-field Umpire", -}; +const USER = { id: "cricket-viewer", name: "On-field Umpire" }; const SCENARIOS = [ { @@ -58,10 +54,14 @@ function CricketCallUI({ call, onDecision }) { time: new Date().toLocaleTimeString() }]); - // Send to agent via custom event (agent also hears via voice) - try { await call.sendCustomEvent({ type: "scenario_review", scenario: scenario.label }); } catch (e) {} + // Trigger real Gemini analysis via backend HTTP endpoint + try { + await fetch("http://localhost:8002/review/" + scenario.id, { method: "POST" }); + } catch (e) { + console.error("Review trigger failed:", e); + } - // Show decision after delay (agent speaks it simultaneously via audio) + // Show fallback decision after agent has time to analyze setTimeout(() => { setTranscript((prev) => [...prev, { id: Date.now() + 1, role: "umpire", @@ -70,14 +70,7 @@ function CricketCallUI({ call, onDecision }) { }]); onDecision?.(scenario.decision); setSending(null); - // Speak the verdict aloud - const utterance = new SpeechSynthesisUtterance(scenario.decision); - utterance.rate = 0.85; - utterance.pitch = 0.9; - utterance.volume = 1; - speechSynthesis.cancel(); // cancel any ongoing speech - speechSynthesis.speak(utterance); - }, 3000); + }, 6000); }; return ( @@ -124,13 +117,13 @@ function CricketCallUI({ call, onDecision }) { 🎤 Mic
- Share a cricket video tab so the AI can watch it + Share cricket video tab then click a review type
- Gemini Live Vision Active + YOLO Pose Detection Active
@@ -144,7 +137,7 @@ function CricketCallUI({ call, onDecision }) { {SCENARIOS.map((s) => (