# Project export: Dispatch AI

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: UC Berkeley AI Hackathon 2026
- Tagline: When seconds matter, AI sees what dispatchers can't and turns any phone camera into an intelligent first responder.
- Devpost: https://devpost.com/software/dispatch-ai-nh8txb
- GitHub: https://github.com/maiawomack/dispatchAI
- Demo: https://asi1.ai/shared-chat/e6472b3f-05ab-4cab-b7ba-b0898348543a
- Video: https://www.youtube.com/embed/5zEGGcB1sII?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 5 GitHub contributor(s) — Sirisha Pusapati (22 commits), Claude Sonnet 4.6 (18 commits), Siyona Verma (13 commits), maiawomack (6 commits), Rithika Suresh (1 commits)

## Devpost submission (written by the team)

### Inspiration

Every 911 dispatcher works blind. They hear voices — panicked, frantic, sometimes incoherent — and have to piece together what's happening from words alone. A caller screaming "there's so much blood" tells you something. But it doesn't tell you how many people are injured, whether there's fire spreading in the background, or if the scene is safe for first responders to enter. Dispatchers have always had to make life-or-death resource decisions with incomplete information. We wanted to change that. Not by replacing the dispatcher, but by giving them eyes.

### What it does

Dispatch AI turns any caller's phone into an intelligent first responder. The moment a 911 call comes in, the caller receives a link. They tap it, point their camera at the scene, and our vision agent begins analyzing the live feed every few seconds — identifying injuries, fire, smoke, hazards, number of people, and even silent distress signals. That information flows to a triage agent that reasons over the scene and produces a structured incident brief: who to dispatch, what responders need to know before they arrive, and what the scene implies that isn't immediately visible. The triage agent then contacts an EMS routing agent that returns the nearest available unit, its ETA, the closest AED drone pad, and a What3Words precision location — all within the same response. The TriageAlertAgent is discoverable and operable through ASI:One. Dispatchers can also type plain-text descriptions directly into the chat interface, and the agent parses those into the same structured pipeline.

### How we built it

Vision layer (Node.js / Express) The frontend captures video in the browser using WebRTC's captureStream() API, sampling frames every few seconds and POSTing them as base64 JPEG to our Express server. Claude Sonnet analyzes each frame and returns structured JSON across 20+ fields: people, injuries (with severity and body part), fire, smoke, hazards, visible text, object detection, and a silent_distress boolean that scans every pixel of readable text and every visible gesture for coercion signals. The server also handles a parallel audio path: it transcribes caller speech with Claude Haiku, detects distress keywords (including weapon references), runs language detection, and translates non-English audio to English in real time before merging audio signals into the frame result. Failures return a degraded result rather than breaking the capture loop — the dispatcher always sees something. Schema adaptation The vision agent returns a rich nested schema (arrays of people, arrays of injuries by person ID). The triage agent expects a flat scene format. An adapt_frame() function translates between them at the boundary — computing per-person aggregates (worst injury severity, whether anyone is unresponsive, motion status across all people), flattening the injury array into scalar estimates, and surfacing silent distress and weapon detections as top-level fields before passing the result downstream. TriageAlertAgent (Python / uAgents / Fetch.ai) The TriageAlertAgent is built on Fetch.ai's uAgents framework using the chat protocol spec, registered on testnet, and operable through ASI:One. It receives structured JSON frame-by-frame over the chat protocol and maintains an in-memory scene store (last_scene_store) that persists context across messages for the lifetime of the process. Each incoming frame goes through a two-layer change detection pipeline before any Claude call is made: Fast heuristics (no LLM): Eleven specific conditions are checked with direct comparisons — fire appearing for the first time, victim becoming unresponsive, victim stopping movement, silent distress newly detected, audio distress keywords detected, new hazards added, bleeding or injury severity increasing, people count rising, camera obstruction (confidence < 0.2), and scene resuming after obstruction. If any fast flag fires, the agent skips the LLM and returns immediately with the reason. Fast heuristics (no LLM): Eleven specific conditions are checked with direct comparisons — fire appearing for the first time, victim becoming unresponsive, victim stopping movement, silent distress newly detected, audio distress keywords detected, new hazards added, bleeding or injury severity increasing, people count rising, camera obstruction (confidence < 0.2), and scene resuming after obstruction. If any fast flag fires, the agent skips the LLM and returns immediately with the reason. Claude fallback: If no fast flag fires, Claude compares the previous and current scene JSON and decides whether the change is significant enough to alert the dispatcher. This handles ambiguous cases like a change in recommended units or an urgency shift that doesn't map neatly to a single field. Claude fallback: If no fast flag fires, Claude compares the previous and current scene JSON and decides whether the change is significant enough to alert the dispatcher. This handles ambiguous cases like a change in recommended units or an urgency shift that doesn't map neatly to a single field. When a scene change warrants an alert, Claude Sonnet generates the dispatcher brief: a status line (CRITICAL through LOW PRIORITY), dispatch recommendations, ordered responder actions, and a brief scene summary. The prompt is engineered to lead with action — what to do and what the scene implies — not to restate what the camera detected. All outputs use "recommend dispatching" language; the agent never implies a dispatch has been executed. If the computed urgency is 3 or higher, the agent simultaneously fires an EmsRequest (typed uAgents Model) to a companion EMS & AED Drone agent containing the emergency ID, address, chief complaint derived from the scene fields, and GPS coordinates. The EMS agent returns a typed EmsResult with the nearest available unit, its ETA in seconds, the closest AED drone pad, and a What3Words precision location. The EMS routing block is appended to the triage brief before it's sent back to the dispatcher. Observability The production agent is fully instrumented with Arize Phoenix OpenTelemetry tracing. Every Claude call, every fast-check evaluation, and every change detection decision is captured as a named span with scene metadata attributes, so the full decision trace is visible and evaluable in the Arize dashboard. SMS / QR delivery The system is designed to send the video link automatically via Twilio the moment a 911 call comes in. Due to carrier A2P 10DLC registration timelines, SMS approval was not completed within the hackathon window. For the demo, the link is delivered via a QR code on the dispatcher dashboard — the caller scans it and the experience is identical from that point forward. The SMS infrastructure (sms_trigger.py) is fully built and ready to activate once the number clears. Claude Claude does three different jobs in this system, not one. It reads each video frame and turns it into structured scene data: people, injuries, hazards, fire, confidence. It decides whether a change between two frames is actually significant, but only when hard-coded checks can't already tell (fire appearing or a victim going unresponsive get caught instantly, no model call needed, Claude only steps in for the ambiguous cases). And it writes the dispatcher-facing brief itself, which we spent a lot of time getting right. The triage agent also calls a second agent on Agentverse for EMS and drone routing, so Claude's output it triggers a real action and folds the result back into the response. We kept every Claude call narrow. The vision call only sees one frame at a time. The change-detection call only sees the previous and current scene, nothing else. The brief-generation call sees the current scene and why it was flagged. No call carries a growing conversation history, temporal reasoning comes from the last_scene_store dictionary holding state between messages, not from accumulating context inside the model. That separation is part of why the pipeline stays fast even with multiple model calls in the loop: each call gets exactly the data it needs, and memory lives in our code, not in the prompt. We built it this way because 911 dispatch is a real, painful, time-critical problem, and most of what's hard about it isn't model capability, it's making sure the model says the right thing at the right instance. We also used Claude Code to develop our project, with the four of us working on different pieces (vision, triage logic, the EMS integration, the dashboard) at the same time, in the same codebase. Once we established the JSON contract between the vision and triage agents, Claude Code wrote adapt_frame() to bridge them, implemented our two-layer change-detection logic from a plain-English spec, and helped iterate on the system prompts until "action-first" output actually meant something concrete. It also wired up the EMS agent integration, and when one of us hit a ctx.storage persistence bug, it diagnosed the issue and replaced it with the module-level dictionary that fixed it. Working directly against the running codebase, instead of writing in isolation and reconciling later, is a big part of why four people could move this fast in a day.

### Challenges we ran into

A2P 10DLC registration. US carriers require programmatic SMS senders to complete a multi-day registration process. We pivoted to a QR code flow that preserved the demo experience. State management across uAgents messages. The uAgents framework's built-in ctx.storage does not persist reliably between separate incoming messages when running locally, causing the agent to treat every frame as an initial assessment and alert on every input. We replaced it with a module-level last_scene_store dictionary that holds the last scene and last triage result for the lifetime of the running process, restoring correct change detection across the full frame sequence. Schema contract between agents. The vision agent and triage agent had to agree on field names and types. That contract broke multiple times during integration. We learned to define the shared schema first and build to it, rather than reconciling mismatches after the fact. The adapt_frame() function now serves as the formal boundary between the two schemas. Prompt engineering for dispatcher output. The natural tendency of a language model is to summarize what it sees. Dispatchers already have the raw feed. Getting the agent to consistently lead with what the scene implies — what risks aren't visible yet, what could change in the next 60 seconds — required many iterations of the system prompt and testing against realistic frame sequences. Real-time performance. Frame analysis had to feel fast enough to be useful. We tuned frame intervals, compressed JPEG quality, structured the fast-check layer to bypass Claude entirely for the most time-critical signals, and built the server to return degraded results rather than fail silently when a frame can't be analyzed. Accomplishments we're proud of We built a working end-to-end pipeline in a single hackathon day: phone camera → Claude vision → schema adapter → uAgents triage → EMS routing → dispatcher brief. The system requires zero buy-in from dispatch centers, zero app downloads from callers, and zero enterprise contracts. Anyone with a phone and a browser can be the data source. The two-layer change detection is the technical piece we're most proud of. The most dangerous changes — fire, unresponsiveness, silent distress, weapon keywords — are caught in microseconds through direct field comparisons with no model call. Claude only gets involved when the situation is genuinely ambiguous. A stable scene stays quiet. A deteriorating scene escalates immediately. Silent distress detection is one of our strongest features. The vision agent scans visible text in frame — phone screens and handwritten notes — and watches for coercion gestures like a raised hand with extended fingers or exaggerated eye movements. If a caller is being coerced or can't speak freely, the system can detect it even when they say nothing. The real-time audio path — transcription, language detection, translation, keyword extraction — means non-English speaking callers are not invisible to the system. Language barriers cost lives in emergency response; we built to eliminate that gap.

### What we learned

The infrastructure barrier in emergency response is real. Existing solutions require dispatch centers to sign enterprise contracts. By pushing the intelligence to the civilian side — making the caller the data source — you bypass that barrier entirely. Any center can read a plain-text incident brief. No contract required. We also learned that the bottleneck in emergency dispatch isn't data availability. It's dispatcher cognitive load. More information isn't always better. A well-reasoned summary that leads with action beats a raw feed every time. And we found that how you write instructions to an agent matters as much as the code around it. The difference between an agent that describes a scene and one that gives a dispatcher something actionable is entirely in the system prompt. We went through many iterations before it felt right.

### What's next

SMS approval and automated delivery once A2P 10DLC registration clears Expanded audio coverage: full caller transcript analysis, not just keyword spotting Integration with real CAD systems for direct alert routing Confidence scoring on dispatch recommendations so dispatchers know when to trust the AI and when to dig deeper Multi-camera support for scenes with multiple callers reporting the same incident International emergency number support (112, 999, etc.) Live Arize evaluations running against real frame sequences to continuously measure triage accuracy Our Agent https://agentverse.ai/agents/details/agent1q2fu34yahnp7k8t0kyk44kwhn2jlmhe4vl9ljr5z0e93zmh9q5kgz3fmn2v/profile Existing Agent We Used https://agentverse.ai/agents/details/agent1qw3239g4tahjmw93fwqqp24hyhelljh70ee6wh59euqgrts0kdqfv8gtdll/profile

## README (from the GitHub repository)

![tag:innovationlab](https://img.shields.io/badge/innovationlab-3D8BD3)
![tag:hackathon](https://img.shields.io/badge/hackathon-5F43F1)

🚨 Dispatch AI

Your AI-powered emergency response assistant. When a 911 call comes in, a video link is automatically sent to the caller's phone. The caller points their camera at the scene, and our multi-agent system analyzes the live feed in real time — identifying the emergency type, assessing severity, and producing a structured dispatch brief for responders. No app download required. No dispatch center integration needed.

Agent Name: Triagealertagent
Agent Address: agent1q2fu34yahnp7k8t0kyk44kwhn2jlmhe4vl9ljr5z0e93zmh9q5kgz3fmn2v
ASI1 Chat Session: https://asi1.ai/shared-chat/e6472b3f-05ab-4cab-b7ba-b0898348543a

What I Can Do

🎥 Live Video Analysis: The caller receives a link and points their camera at the scene. Frames are analyzed every few seconds by a vision agent that identifies injuries, fire, hazards, and number of people.

🧠 Intelligent Triage: Based on the visual feed, the agent determines the nature and severity of the emergency — medical, fire, violence, or other — and how urgent a response is needed.

🚒 Smart Dispatch Recommendations: The dispatch coordinator agent decides what resources are needed — how many fire trucks, whether police are required, or if an ambulance alone is sufficient.

📋 Structured Incident Brief: All findings are compiled into a CAD-compatible summary that any dispatch center can read, with zero integration required on their end.

🌐 No App, No Barrier: The civilian just taps a link. Everything else is handled by the agents on the backend.

How It Works

A 911 call comes in
The caller receives an SMS link and taps it to open the video session
They point their camera at the scene
The vision agent analyzes frames every few seconds
The triage agent converts visual data into a priority report
The dispatch coordinator produces a structured brief
The dispatcher sees the brief populate in real time — no manual input needed


Demo note: The full system is designed to send an automatic SMS to the caller's phone the moment a 911 call comes in. Due to carrier regulations, US phone number SMS approval (A2P 10DLC) requires several days of processing time and could not be completed within the hackathon window. For this demo, the SMS link is delivered via a QR code displayed on the dispatcher dashboard — the caller scans it and the experience is identical from that point on. The SMS infrastructure (sms_trigger.py) is fully built and ready to activate once the number is approved.



Agent Breakdown

AgentRoleIntake AgentSends the SMS/QR link, opens the video sessionVision AgentAnalyzes frames — tags injuries, fire, hazards, people countTriage AgentConverts visual data into a structured priority reportDispatch CoordinatorDecides resources needed and formats the final brief

Example Interaction

Caller clicks on the link and points camera at a house fire

Vision Agent detects:

fire_visible:     true
smoke_visible:    true
people_count:     2
injury_visible:   true (moderate)
hazards:          structural collapse risk
confidence:       91%

Dispatch Brief produced:

🚨 INCIDENT REPORT — AUTO-GENERATED
Type:         Structure Fire with Casualties
Severity:     HIGH
Recommended:  2x Fire Truck, 1x Ambulance, 1x Police Unit
People:       2 visible, 1 showing signs of injury
Hazards:      Smoke inhalation risk, possible structural collapse
Timestamp:    2026-06-20T18:45:00Z

What Makes This Different

Our system requires nothing from the dispatch center — the agent outputs a standard CAD-compatible summary that any center can read. The innovation is pushing intelligence to the civilian side so the infrastructure barrier disappears entirely.

Example Queries


"What is happening at the scene?"
"How many responders are needed?"
"Is this a medical emergency or a fire?"
"What hazards are present?"
"Generate a dispatch brief for this incident"


## Detected evidence (automated analysis)

Indexed codebase: 2337 recognized source files, 20669 KB.
- Anthropic (technology) — detected in the code
- C (language) — detected in the code
- C++ (language) — detected in the code
- Express (technology) — detected in the code
- Flask (technology) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- Python (language) — detected in the code
- Node.js (technology) — claimed on Devpost, not found in the code
- AI coding agent: Claude Code — evidence: commit authorship or trailers

## Codebase structure (from repository index)

### Files (120 of 3043)

```
.env.example
.gitignore
demo/capture_demo.html
live_vision/analyzeFrame.js
live_vision/package.json
live_vision/public/capture.html
live_vision/public/index.html
live_vision/server.js
my_first_agent.py
public/emergency.html
public/qr.html
README.md
sms_trigger.py
triage_alert/agent_cloud.py
triage_alert/agent1q09ckygsh9_data.json
triage_alert/mock_ems_agent.py
triage_alert/requirements.txt
triage_alert/sample_frames.json
triage_alert/sample_frames10.json
triage_alert/sample_frames25.json
triage_alert/sample_frames50.json
triage_alert/suggestor.py
triage_alert/test_sender.py
triage_alert/triage_http.py
triage_alert/triage_logic.py
venv312/bin/activate
venv312/bin/activate.csh
venv312/bin/activate.fish
venv312/bin/Activate.ps1
venv312/bin/httpx
venv312/bin/idna
venv312/bin/jsonschema
venv312/bin/normalizer
venv312/bin/pip
venv312/bin/pip3
venv312/bin/pip3.12
venv312/bin/python
venv312/bin/python3
venv312/bin/python3.12
venv312/bin/uvicorn
venv312/bin/virtualenv
venv312/lib/python3.12/site-packages/aiohappyeyeballs-2.6.2.dist-info/INSTALLER
venv312/lib/python3.12/site-packages/aiohappyeyeballs-2.6.2.dist-info/licenses/LICENSE
venv312/lib/python3.12/site-packages/aiohappyeyeballs-2.6.2.dist-info/METADATA
venv312/lib/python3.12/site-packages/aiohappyeyeballs-2.6.2.dist-info/RECORD
venv312/lib/python3.12/site-packages/aiohappyeyeballs-2.6.2.dist-info/WHEEL
venv312/lib/python3.12/site-packages/aiohappyeyeballs/__init__.py
venv312/lib/python3.12/site-packages/aiohappyeyeballs/_staggered.py
venv312/lib/python3.12/site-packages/aiohappyeyeballs/impl.py
venv312/lib/python3.12/site-packages/aiohappyeyeballs/py.typed
venv312/lib/python3.12/site-packages/aiohappyeyeballs/types.py
venv312/lib/python3.12/site-packages/aiohappyeyeballs/utils.py
venv312/lib/python3.12/site-packages/aiohttp-3.14.1.dist-info/INSTALLER
venv312/lib/python3.12/site-packages/aiohttp-3.14.1.dist-info/licenses/LICENSE.txt
venv312/lib/python3.12/site-packages/aiohttp-3.14.1.dist-info/METADATA
venv312/lib/python3.12/site-packages/aiohttp-3.14.1.dist-info/RECORD
venv312/lib/python3.12/site-packages/aiohttp-3.14.1.dist-info/top_level.txt
venv312/lib/python3.12/site-packages/aiohttp-3.14.1.dist-info/WHEEL
venv312/lib/python3.12/site-packages/aiohttp/__init__.py
venv312/lib/python3.12/site-packages/aiohttp/_cookie_helpers.py
venv312/lib/python3.12/site-packages/aiohttp/_cparser.pxd
venv312/lib/python3.12/site-packages/aiohttp/_find_header.pxd
venv312/lib/python3.12/site-packages/aiohttp/_headers.pxi
venv312/lib/python3.12/site-packages/aiohttp/_http_parser.pyx
venv312/lib/python3.12/site-packages/aiohttp/_http_writer.pyx
venv312/lib/python3.12/site-packages/aiohttp/_websocket/__init__.py
venv312/lib/python3.12/site-packages/aiohttp/_websocket/.hash/mask.pxd.hash
venv312/lib/python3.12/site-packages/aiohttp/_websocket/.hash/mask.pyx.hash
venv312/lib/python3.12/site-packages/aiohttp/_websocket/.hash/reader_c.pxd.hash
venv312/lib/python3.12/site-packages/aiohttp/_websocket/helpers.py
venv312/lib/python3.12/site-packages/aiohttp/_websocket/mask.pxd
venv312/lib/python3.12/site-packages/aiohttp/_websocket/mask.pyx
venv312/lib/python3.12/site-packages/aiohttp/_websocket/models.py
venv312/lib/python3.12/site-packages/aiohttp/_websocket/reader_c.pxd
venv312/lib/python3.12/site-packages/aiohttp/_websocket/reader_c.py
venv312/lib/python3.12/site-packages/aiohttp/_websocket/reader_py.py
venv312/lib/python3.12/site-packages/aiohttp/_websocket/reader.py
venv312/lib/python3.12/site-packages/aiohttp/_websocket/writer.py
venv312/lib/python3.12/site-packages/aiohttp/.hash/_cparser.pxd.hash
venv312/lib/python3.12/site-packages/aiohttp/.hash/_find_header.pxd.hash
venv312/lib/python3.12/site-packages/aiohttp/.hash/_http_parser.pyx.hash
venv312/lib/python3.12/site-packages/aiohttp/.hash/_http_writer.pyx.hash
venv312/lib/python3.12/site-packages/aiohttp/.hash/hdrs.py.hash
venv312/lib/python3.12/site-packages/aiohttp/abc.py
venv312/lib/python3.12/site-packages/aiohttp/base_protocol.py
venv312/lib/python3.12/site-packages/aiohttp/client_exceptions.py
venv312/lib/python3.12/site-packages/aiohttp/client_middleware_digest_auth.py
venv312/lib/python3.12/site-packages/aiohttp/client_middlewares.py
venv312/lib/python3.12/site-packages/aiohttp/client_proto.py
venv312/lib/python3.12/site-packages/aiohttp/client_reqrep.py
venv312/lib/python3.12/site-packages/aiohttp/client_ws.py
venv312/lib/python3.12/site-packages/aiohttp/client.py
venv312/lib/python3.12/site-packages/aiohttp/compression_utils.py
venv312/lib/python3.12/site-packages/aiohttp/connector.py
venv312/lib/python3.12/site-packages/aiohttp/cookiejar.py
venv312/lib/python3.12/site-packages/aiohttp/formdata.py
venv312/lib/python3.12/site-packages/aiohttp/hdrs.py
venv312/lib/python3.12/site-packages/aiohttp/helpers.py
venv312/lib/python3.12/site-packages/aiohttp/http_exceptions.py
venv312/lib/python3.12/site-packages/aiohttp/http_parser.py
venv312/lib/python3.12/site-packages/aiohttp/http_websocket.py
venv312/lib/python3.12/site-packages/aiohttp/http_writer.py
venv312/lib/python3.12/site-packages/aiohttp/http.py
venv312/lib/python3.12/site-packages/aiohttp/log.py
venv312/lib/python3.12/site-packages/aiohttp/multipart.py
venv312/lib/python3.12/site-packages/aiohttp/payload_streamer.py
venv312/lib/python3.12/site-packages/aiohttp/payload.py
venv312/lib/python3.12/site-packages/aiohttp/py.typed
venv312/lib/python3.12/site-packages/aiohttp/pytest_plugin.py
venv312/lib/python3.12/site-packages/aiohttp/resolver.py
venv312/lib/python3.12/site-packages/aiohttp/streams.py
venv312/lib/python3.12/site-packages/aiohttp/tcp_helpers.py
venv312/lib/python3.12/site-packages/aiohttp/test_utils.py
venv312/lib/python3.12/site-packages/aiohttp/tracing.py
venv312/lib/python3.12/site-packages/aiohttp/typedefs.py
venv312/lib/python3.12/site-packages/aiohttp/web_app.py
venv312/lib/python3.12/site-packages/aiohttp/web_exceptions.py
venv312/lib/python3.12/site-packages/aiohttp/web_fileresponse.py
venv312/lib/python3.12/site-packages/aiohttp/web_log.py
venv312/lib/python3.12/site-packages/aiohttp/web_middlewares.py
[2923 more files omitted for size]
```

### Dependencies

- live_vision/package.json: @anthropic-ai/sdk@^0.105.0, dotenv@^17.4.2, express@^5.2.1, localtunnel@^2.0.2
- triage_alert/requirements.txt: anthropic@==0.111.0, flask@>=3.0.0, python-dotenv@>=1.0.0, uagents@==0.25.2

### Recent commits (newest first)

- Switch frame analysis to Sonnet, remove Haiku toggle; improve weapon/school triage priority
- Load video as blob URL so captureStream() works in Chrome
- Serve demo folder from express so captureStream works (same-origin)
- Merge remote README update, preserve our demo UI changes
- Update README.md
- Merge remote-tracking branch 'origin/main'
- Demo: remove video controls, route audio from video stream, drop End Call button
- Update README.md
- Demo UI: calling screen, auto-start listening, remove clutter
- Optimize demo pipeline for speed
- Add demo video UI, cloud triage agent, and triage fixes
- Merge branch 'main' of https://github.com/maiawomack/berkelyAIhacks
- add agent chat protocol
- Force API key load with override:true and direct .env fallback
- add arize tracing fixes
- Merge branch 'main' of https://github.com/maiawomack/berkelyAIhacks
- add agent chat protocol
- Fix API key timing — read from process.env at call time not module load
- Merge branch 'main' of https://github.com/maiawomack/berkelyAIhacks
- Add sample_frames25.json for testing

## Key source files (fetched from GitHub, selected and truncated for size)

### venv312/lib/python3.12/site-packages/cosmpy-0.12.2.dist-info/licenses/AUTHORS.md

```markdown
# Authors

This is the official list of CosmPy authors (the lists are in the alphabetical order:):

### Leads

- Ali Hosseini <ali.hosseini@fetch.ai> [5A11](https://github.com/5A11)
- James Riehl <james.riehl@fetch.ai> [jrriehl](https://github.com/jrriehl)

### Primary Current and Past Contributors

- Alejandro Madrigal <alejandro.madrigal@fetch.ai> [Alejandro-Morales](https://github.com/Alejandro-Morales)
- Ed Fitzgerald <ed.fitzgerald@fetch.ai> [ejfitzgerald](https://github.com/ejfitzgerald)
- Jiri Vestfal <jiri.vestfal@fetch.ai> [MissingNO57](https://github.com/MissingNO57)
- Lokman Rahmani <lokman.rahmani@fetch.ai> [lrahmani](https://github.com/lrahmani)
- Oleg Panasevych <oleg.panasevych@n-cube.co.uk> [Panasevychol](https://github.com/panasevychol)
- Peter Bukva <peter.bukva@fetch.ai> [pbukva](https://github.com/pbukva)
- Yuri Turchenkov <yuri.turchenkov@fetch.ai> [solarw](https://github.com/solarw)

## Other Contributors

See the GitHub commit log for a list of recent contributors. We would like to thank everyone who has contributed to the project in any way.

```

### venv312/lib/python3.12/site-packages/httpx-0.28.1.dist-info/licenses/LICENSE.md

```markdown
Copyright © 2019, [Encode OSS Ltd](https://www.encode.io/).
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

```

### triage_alert/requirements.txt

```
# # 1. Create a virtual environment
# python -m venv venv

# # 2. Activate it
# .\venv\Scripts\Activate.ps1

# # 3. Install all dependencies
# pip install -r requirements.txt

# # 4. Run the agent
# python suggestor.py

uagents==0.25.2
anthropic==0.111.0
flask>=3.0.0
python-dotenv>=1.0.0
```

### live_vision/package.json

```
{
  "name": "berkelyaihacks",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node server.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/maiawomack/berkelyAIhacks.git"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "type": "commonjs",
  "bugs": {
    "url": "https://github.com/maiawomack/berkelyAIhacks/issues"
  },
  "homepage": "https://github.com/maiawomack/berkelyAIhacks#readme",
  "dependencies": {
    "@anthropic-ai/sdk": "^0.105.0",
    "dotenv": "^17.4.2",
    "express": "^5.2.1",
    "localtunnel": "^2.0.2"
  }
}

```

### live_vision/server.js

```javascript
require("dotenv").config({ path: require("path").resolve(__dirname, "../.env"), override: true });
const express = require("express");
const path = require("path");
const os = require("os");
const http = require("http");
const fs = require("fs");

// Hard fallback: read key directly from .env if dotenv didn't set it
if (!process.env.ANTHROPIC_API_KEY) {
  try {
    const raw = fs.readFileSync(path.resolve(__dirname, "../.env"), "utf8");
    const m = raw.match(/^ANTHROPIC_API_KEY=(.+)$/m);
    if (m) process.env.ANTHROPIC_API_KEY = m[1].trim();
  } catch (_) {}
}
const localtunnel = require("localtunnel");
const Anthropic = require("@anthropic-ai/sdk");

function getLocalIP() {
  for (const ifaces of Object.values(os.networkInterfaces())) {
    for (const iface of ifaces) {
      if (iface.family === "IPv4" && !iface.internal) return iface.address;
    }
  }
  return "localhost";
}
const { analyzeFrame } = require("./analyzeFrame");

const app = express();

// Non-blocking call to triage HTTP server (python triage_http.py on port 8002).
// Returns null if the server is not running — vision analysis is never blocked.
function callTriage(frameResult) {
  return new Promise((resolve) => {
    const body = JSON.stringify(frameResult);
    const req  = http.request(
      { hostname: "localhost", port: 8002, path: "/triage", method: "POST",
        headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(body) } },
      (res) => {
        let data = "";
        res.on("data", (chunk) => { data += chunk; });
        res.on("end",  () => { try { resolve(JSON.parse(data)); } catch { resolve(null); } });
      }
    );
    req.on("error", () => resolve(null));
    req.setTimeout(5000, () => { req.destroy(); resolve(null); });
    req.write(body);
    req.end();
  });
}
const PORT = 3000;
const getClient = () => new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });

app.use(express.json({ limit: "10mb" }));
app.use(express.static(path.join(__dirname, "public")));
app.use("/demo", express.static(path.join(__dirname, "../demo")));

let publicUrl = null;

app.get("/server-url", (req, res) => {
  res.json({ url: publicUrl || `http://${getLocalIP()}:${PORT}` });
});

app.post("/analyze", async (req, res) => {
  const { frame, mimeType, model, audioSignal } = req.body;

  if (!frame) {
    return res.status(400).json({ error: "Missing frame data" });
  }

  const timestamp = new Date().toISOString();
  console.log(`[${timestamp}] API key set: ${!!process.env.ANTHROPIC_API_KEY}, length: ${process.env.ANTHROPIC_API_KEY?.length}`);

  try {
    const modelId = "claude-sonnet-4-6";
    const result = await analyzeFrame(frame, mimeType || "image/jpeg", modelId);
    result.timestamp = timestamp;

    // Merge audio distress so triage server can factor it in
    const WEAPON_KEYWORDS = ["gun", "knife", "weapon", "shot", "stabbed", "shooting", "armed", "attack", "assault"];
    const hasWeapon = audioSignal?.distress_keywords_detected?.some(kw => WEAPON_KEYWORDS.includes(kw));
    if (audioSignal?.distress_keywords_detected?.length && (audioSignal.tone === "elevated" || hasWeapon)) {
      result.audio_distress = true;
      result.audio_keywords = audioSignal.distress_keywords_detected;
    }

    console.log(`[${timestamp}] frame_quality=${result.frame_quality} confidence=${result.confidence}${result.audio_distress ? " AUDIO_DISTRESS" : ""}`);

    const triage = await callTriage(result);
    if (triage?.alert) console.log(`[${timestamp}] triage alert: ${triage.reason}`);

    res.json({ ok: true, result, triage });
  } catch (err) {
    console.error(`[${timestamp}] analysis error:`, err.message);
    // Return a degraded result rather than crashing the loop
    res.json({
      ok: false,
      error: err.message,
      result: {
        frame_quality: "no_scene",
        confidence: 0,
        quality_issues: ["analysis_error"],
        notes: "Frame analysis failed",
        timestamp,
      },
    });
  }
});

app.post("/triage-audio", async (req, res) => {
  const { audioSignal, transcript } = req.body;
  if (!audioSignal) return res.status(400).json({ error: "Missing audioSignal" });

  const syntheticFrame = {
    people_count: 1,
    injury_visible: false,
    injury_severity_estimate: "none",
    injury_location: null,
    bleeding_visible: false,
    bleeding_severity_estimate: "none",
    smoke_visible: false,
    fire_visible: false,
    person_motion: "unknown",
    person_responsive: "unknown",
    silent_distress: false,
    audio_distress: true,
    audio_keywords: audioSignal.distress_keywords_detected || [],
    hazards: ["audio_distress"],
    confidence: audioSignal.confidence || 0.7,
    notes: transcript ? `CALLER TRANSCRIPT (extract location/school names for dispatch): "${transcript.slice(-400)}"` : "Audio distress detected",
    timestamp: new Date().toISOString(),
  };

  try {
    const triage = await callTriage(syntheticFrame);
    res.json(triage || { alert: false });
  } catch (err) {
    res.json({ alert: false });
  }
});

app.post("/detect-language", async (req, res) => {
  const { text } = req.body;
  if (!text) return res.status(400).json({ error: "Missing text" });

  try {
    const response = await getClient().messages.create({
      model: "claude-sonnet-4-6",
      max_tokens: 128,
      messages: [{
        role: "user",
        content: `Identify the language of the following text. Respond with ONLY valid JSON, no markdown: {"language": "<full language name in English>", "language_code": "<ISO 639-1 code>", "confidence": <0.0-1.0>}\n\nText: ${JSON.stringify(text)}`,
      }],
    });
    const raw = response.content[0].text.trim();
    const fenceMatch = raw.match(/```(?:json)?\s*([\s\S]*?)```/);
    const result = JSON.parse(fenceMatch ? fenceMatch[1].trim() : raw);
    console.log(`[detect-language] "${text.slice(0, 40)}…" → ${result.language}`);
    res.json(result);
  } catch (err) {
    console.error("[detect-language] error:", err
[truncated — 2651 more characters]
```

### venv312/lib/python3.12/site-packages/idna/cli.py

```python
"""Command-line interface for the :mod:`idna` package.

Invoked via ``python -m idna``. See :func:`main` for the entry point.
"""

import argparse
import sys
from collections.abc import Iterable
from itertools import chain
from typing import IO, Optional

from . import IDNAError, decode, encode
from .core import _alabel_prefix, _unicode_dots_re
from .package_data import __version__


def _looks_like_alabel(s: str) -> bool:
    """Return True if any label in ``s`` carries the ``xn--`` ACE prefix."""
    prefix = _alabel_prefix.decode("ascii")
    return any(label.lower().startswith(prefix) for label in _unicode_dots_re.split(s))


def _build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(
        prog="python -m idna",
        description=(
            "Convert a domain name between its Unicode (U-label) and "
            "ASCII-compatible (A-label) forms. With no mode flag, the "
            "direction is chosen from the first input — if it contains "
            "an xn-- label the stream is decoded, otherwise it is "
            "encoded — and the same mode is applied to every remaining "
            "input. UTS #46 mapping is applied by default; pass "
            "--strict to disable it. When no domains are given on the "
            "command line and stdin is piped, one domain per line is "
            "read from stdin."
        ),
    )
    mode = parser.add_mutually_exclusive_group()
    mode.add_argument(
        "-e",
        "--encode",
        dest="mode",
        action="store_const",
        const="encode",
        help="Encode the input to its ASCII A-label form.",
    )
    mode.add_argument(
        "-d",
        "--decode",
        dest="mode",
        action="store_const",
        const="decode",
        help="Decode the input from its ASCII A-label form.",
    )
    parser.add_argument(
        "--strict",
        action="store_true",
        help="Disable the default UTS #46 mapping and apply IDNA 2008 rules verbatim.",
    )
    parser.add_argument(
        "--version",
        action="version",
        version=f"idna {__version__}",
    )
    parser.add_argument(
        "domain",
        nargs="*",
        help="One or more domain names to convert. Omit to read from stdin.",
    )
    return parser


def _iter_stdin(stream: IO[str]) -> Iterable[str]:
    """Yield non-empty stripped lines from ``stream``, ignoring blanks."""
    for line in stream:
        stripped = line.strip()
        if stripped:
            yield stripped


def _convert_one(domain: str, mode: str, uts46: bool) -> bool:
    """Convert ``domain`` and write the result; return ``False`` on failure."""
    try:
        if mode == "decode":
            print(decode(domain, uts46=uts46))
        else:
            print(encode(domain, uts46=uts46).decode("ascii"))
    except IDNAError as err:
        print(f"idna: {mode} failed for {domain!r}: {err}", file=sys.stderr)
        return False
    return True


def main(argv: Optional[list[str]] = None) -> int:
    """Entry point for ``python -m idna``.

    When more than one domain is supplied (via positional arguments or
    piped stdin) and no mode flag is given, the first input determines
    the direction and that mode is applied uniformly to the rest.

    :param argv: Argument list excluding the program name. Defaults to
        :data:`sys.argv` when ``None``.
    :returns: ``0`` on success, ``1`` if any conversion fails.
    """
    parser = _build_parser()
    args = parser.parse_args(argv)
    uts46 = not args.strict

    if args.domain:
        domains: Iterable[str] = args.domain
    elif not sys.stdin.isatty():
        domains = _iter_stdin(sys.stdin)
    else:
        parser.error("a domain argument is required when stdin is a terminal")

    iterator = iter(domains)
    first = next(iterator, None)
    if first is None:
        return 0

    mode = args.mode or ("decode" if _looks_like_alabel(first) else "encode")

    results = [_convert_one(domain, mode, uts46) for domain in chain([first], iterator)]
    return 0 if all(results) else 1


if __name__ == "__main__":
    sys.exit(main())

```

### venv312/lib/python3.12/site-packages/jsonschema/cli.py

```python
"""
The ``jsonschema`` command line.
"""

from importlib import metadata
from json import JSONDecodeError
from pkgutil import resolve_name
from textwrap import dedent
import argparse
import json
import sys
import traceback
import warnings

from attrs import define, field

from jsonschema.exceptions import SchemaError
from jsonschema.validators import _RefResolver, validator_for

warnings.warn(
    (
        "The jsonschema CLI is deprecated and will be removed in a future "
        "version. Please use check-jsonschema instead, which can be installed "
        "from https://pypi.org/project/check-jsonschema/"
    ),
    DeprecationWarning,
    stacklevel=2,
)


class _CannotLoadFile(Exception):
    pass


@define
class _Outputter:

    _formatter = field()
    _stdout = field()
    _stderr = field()

    @classmethod
    def from_arguments(cls, arguments, stdout, stderr):
        if arguments["output"] == "plain":
            formatter = _PlainFormatter(arguments["error_format"])
        elif arguments["output"] == "pretty":
            formatter = _PrettyFormatter()
        return cls(formatter=formatter, stdout=stdout, stderr=stderr)

    def load(self, path):
        try:
            file = open(path)  # noqa: SIM115, PTH123
        except FileNotFoundError as error:
            self.filenotfound_error(path=path, exc_info=sys.exc_info())
            raise _CannotLoadFile() from error

        with file:
            try:
                return json.load(file)
            except JSONDecodeError as error:
                self.parsing_error(path=path, exc_info=sys.exc_info())
                raise _CannotLoadFile() from error

    def filenotfound_error(self, **kwargs):
        self._stderr.write(self._formatter.filenotfound_error(**kwargs))

    def parsing_error(self, **kwargs):
        self._stderr.write(self._formatter.parsing_error(**kwargs))

    def validation_error(self, **kwargs):
        self._stderr.write(self._formatter.validation_error(**kwargs))

    def validation_success(self, **kwargs):
        self._stdout.write(self._formatter.validation_success(**kwargs))


@define
class _PrettyFormatter:

    _ERROR_MSG = dedent(
        """\
        ===[{type}]===({path})===

        {body}
        -----------------------------
        """,
    )
    _SUCCESS_MSG = "===[SUCCESS]===({path})===\n"

    def filenotfound_error(self, path, exc_info):
        return self._ERROR_MSG.format(
            path=path,
            type="FileNotFoundError",
            body=f"{path!r} does not exist.",
        )

    def parsing_error(self, path, exc_info):
        exc_type, exc_value, exc_traceback = exc_info
        exc_lines = "".join(
            traceback.format_exception(exc_type, exc_value, exc_traceback),
        )
        return self._ERROR_MSG.format(
            path=path,
            type=exc_type.__name__,
            body=exc_lines,
        )

    def validation_error(self, instance_path, error):
        return self._ERROR_MSG.format(
            path=instance_path,
            type=error.__class__.__name__,
            body=error,
        )

    def validation_success(self, instance_path):
        return self._SUCCESS_MSG.format(path=instance_path)


@define
class _PlainFormatter:

    _error_format = field()

    def filenotfound_error(self, path, exc_info):
        return f"{path!r} does not exist.\n"

    def parsing_error(self, path, exc_info):
        return "Failed to parse {}: {}\n".format(
            "<stdin>" if path == "<stdin>" else repr(path),
            exc_info[1],
        )

    def validation_error(self, instance_path, error):
        return self._error_format.format(file_name=instance_path, error=error)

    def validation_success(self, instance_path):
        return ""


def _resolve_name_with_default(name):
    if "." not in name:
        name = "jsonschema." + name
    return resolve_name(name)


parser = argparse.ArgumentParser(
    description="JSON Schema Validation CLI",
)
parser.add_argument(
    "-i", "--instance",
    action="append",
    dest="instances",
    help="""
        a path to a JSON instance (i.e. filename.json) to validate (may
        be specified multiple times). If no instances are provided via this
        option, one will be expected on standard input.
    """,
)
parser.add_argument(
    "-F", "--error-format",
    help="""
        the format to use for each validation error message, specified
        in a form suitable for str.format. This string will be passed
        one formatted object named 'error' for each ValidationError.
        Only provide this option when using --output=plain, which is the
        default. If this argument is unprovided and --output=plain is
        used, a simple default representation will be used.
    """,
)
parser.add_argument(
    "-o", "--output",
    choices=["plain", "pretty"],
    default="plain",
    help="""
        an output format to use. 'plain' (default) will produce minimal
        text with one line for each error, while 'pretty' will produce
        more detailed human-readable output on multiple lines.
    """,
)
parser.add_argument(
    "-V", "--validator",
    type=_resolve_name_with_default,
    help="""
        the fully qualified object name of a validator to use, or, for
        validators that are registered with jsonschema, simply the name
        of the class.
    """,
)
parser.add_argument(
    "--base-uri",
    help="""
        a base URI to assign to the provided schema, even if it does not
        declare one (via e.g. $id). This option can be used if you wish to
        resolve relative references to a particular URI (or local path)
    """,
)
parser.add_argument(
    "--version",
    action="version",
    version=metadata.version("jsonschema"),
)
parser.add_argument(
    "schema",
    help="the path to a JSON Schema to validate with (i.e. schema.json)",
)


def parse_args(args):  # noqa: D103
    arguments = vars(parser.parse_args(args=args or ["--help"]))
    if arguments["o
[truncated — 2445 more characters]
```

### venv312/lib/python3.12/site-packages/uvicorn/server.py

```python
from __future__ import annotations

import asyncio
import contextlib
import functools
import logging
import os
import platform
import random
import signal
import socket
import sys
import threading
import time
from collections.abc import Generator, Sequence
from email.utils import formatdate
from types import FrameType
from typing import TYPE_CHECKING, TypeAlias

import click

from uvicorn._compat import asyncio_run
from uvicorn.config import Config

if TYPE_CHECKING:
    from uvicorn.protocols.http.h11_impl import H11Protocol
    from uvicorn.protocols.http.httptools_impl import HttpToolsProtocol
    from uvicorn.protocols.websockets.websockets_impl import WebSocketProtocol
    from uvicorn.protocols.websockets.websockets_sansio_impl import WebSocketsSansIOProtocol
    from uvicorn.protocols.websockets.wsproto_impl import WSProtocol

    Protocols: TypeAlias = H11Protocol | HttpToolsProtocol | WSProtocol | WebSocketProtocol | WebSocketsSansIOProtocol

HANDLED_SIGNALS = (
    signal.SIGINT,  # Unix signal 2. Sent by Ctrl+C.
    signal.SIGTERM,  # Unix signal 15. Sent by `kill <pid>`.
)
if sys.platform == "win32":  # pragma: py-not-win32
    HANDLED_SIGNALS += (signal.SIGBREAK,)  # Windows signal 21. Sent by Ctrl+Break.

logger = logging.getLogger("uvicorn.error")


class ServerState:
    """
    Shared servers state that is available between all protocol instances.
    """

    def __init__(self) -> None:
        self.total_requests = 0
        self.connections: set[Protocols] = set()
        self.tasks: set[asyncio.Task[None]] = set()
        self.default_headers: list[tuple[bytes, bytes]] = []


class Server:
    def __init__(self, config: Config) -> None:
        self.config = config
        self.server_state = ServerState()

        self.started = False
        self.should_exit = False
        self.force_exit = False
        self.last_notified = 0.0

        self._captured_signals: list[int] = []

    @functools.cached_property
    def limit_max_requests(self) -> int | None:
        if self.config.limit_max_requests is None:
            return None
        return self.config.limit_max_requests + random.randint(0, self.config.limit_max_requests_jitter)

    def run(self, sockets: list[socket.socket] | None = None) -> None:
        return asyncio_run(self.serve(sockets=sockets), loop_factory=self.config.get_loop_factory())

    async def serve(self, sockets: list[socket.socket] | None = None) -> None:
        with self.capture_signals():
            await self._serve(sockets)

    async def _serve(self, sockets: list[socket.socket] | None = None) -> None:
        process_id = os.getpid()

        config = self.config
        if not config.loaded:
            config.load()

        self.lifespan = config.lifespan_class(config)

        message = "Started server process [%d]"
        color_message = "Started server process [" + click.style("%d", fg="cyan") + "]"
        logger.info(message, process_id, extra={"color_message": color_message})

        await self.startup(sockets=sockets)
        if not self.should_exit:
            await self.main_loop()
        if self.started:
            await self.shutdown(sockets=sockets)

            message = "Finished server process [%d]"
            color_message = "Finished server process [" + click.style("%d", fg="cyan") + "]"
            logger.info(message, process_id, extra={"color_message": color_message})

    async def startup(self, sockets: list[socket.socket] | None = None) -> None:
        await self.lifespan.startup()
        if self.lifespan.should_exit:
            self.should_exit = True
            return

        config = self.config

        def create_protocol(
            _loop: asyncio.AbstractEventLoop | None = None,
        ) -> asyncio.Protocol:
            return config.http_protocol_class(  # type: ignore[call-arg]
                config=config,
                server_state=self.server_state,
                app_state=self.lifespan.state,
                _loop=_loop,
            )

        loop = asyncio.get_running_loop()

        listeners: Sequence[socket.SocketType]
        if sockets is not None:  # pragma: full coverage
            # Explicitly passed a list of open sockets.
            # We use this when the server is run from a Gunicorn worker.

            def _share_socket(
                sock: socket.SocketType,
            ) -> socket.SocketType:  # pragma py-not-win32
                # Windows requires the socket be explicitly shared across
                # multiple workers (processes).
                from socket import fromshare  # type: ignore[attr-defined]

                sock_data = sock.share(os.getpid())  # type: ignore[attr-defined]
                return fromshare(sock_data)

            self.servers: list[asyncio.base_events.Server] = []
            for sock in sockets:
                is_windows = platform.system() == "Windows"
                if config.workers > 1 and is_windows:  # pragma: py-not-win32
                    sock = _share_socket(sock)  # type: ignore[assignment]
                server = await loop.create_server(create_protocol, sock=sock, ssl=config.ssl, backlog=config.backlog)
                self.servers.append(server)
            listeners = sockets

        elif config.fd is not None:  # pragma: py-win32
            # Use an existing socket, from a file descriptor.
            sock = socket.fromfd(config.fd, socket.AF_UNIX, socket.SOCK_STREAM)
            server = await loop.create_server(create_protocol, sock=sock, ssl=config.ssl, backlog=config.backlog)
            assert server.sockets is not None  # mypy
            listeners = server.sockets
            self.servers = [server]

        elif config.uds is not None:  # pragma: py-win32
            # Create a socket using UNIX domain socket.
            uds_perms = 0o666
            if os.path.exists(config.uds):
                uds_perms = os.stat(config.uds).st_mode  # pragma: full coverage
            server = await loop.
[truncated — 7368 more characters]
```

### venv312/lib/python3.12/site-packages/uvicorn/main.py

```python
from __future__ import annotations

import asyncio
import logging
import os
import platform
import ssl
import sys
import warnings
from collections.abc import Callable
from configparser import RawConfigParser
from typing import IO, Any, get_args

import click

import uvicorn
from uvicorn._types import ASGIApplication
from uvicorn.config import (
    INTERFACES,
    LIFESPAN,
    LOG_LEVELS,
    LOGGING_CONFIG,
    SSL_PROTOCOL_VERSION,
    Config,
    HTTPProtocolType,
    InterfaceType,
    LifespanType,
    LoopFactoryType,
    WSProtocolType,
)
from uvicorn.server import Server
from uvicorn.supervisors import ChangeReload, Multiprocess

LEVEL_CHOICES = click.Choice(list(LOG_LEVELS.keys()))
LIFESPAN_CHOICES = click.Choice(list(LIFESPAN.keys()))
INTERFACE_CHOICES = click.Choice(INTERFACES)


def _metavar_from_type(_type: Any) -> str:
    return f"[{'|'.join(key for key in get_args(_type) if key != 'none')}]"


STARTUP_FAILURE = 3

logger = logging.getLogger("uvicorn.error")


def print_version(ctx: click.Context, param: click.Parameter, value: bool) -> None:
    if not value or ctx.resilient_parsing:
        return
    click.echo(
        "Running uvicorn {version} with {py_implementation} {py_version} on {system}".format(  # noqa: UP032
            version=uvicorn.__version__,
            py_implementation=platform.python_implementation(),
            py_version=platform.python_version(),
            system=platform.system(),
        )
    )
    ctx.exit()


@click.command(context_settings={"auto_envvar_prefix": "UVICORN"})
@click.argument("app", envvar="UVICORN_APP")
@click.option(
    "--host",
    type=str,
    default="127.0.0.1",
    help="Bind socket to this host.",
    show_default=True,
)
@click.option(
    "--port",
    type=int,
    default=8000,
    help="Bind socket to this port. If 0, an available port will be picked.",
    show_default=True,
)
@click.option("--uds", type=str, default=None, help="Bind to a UNIX domain socket.")
@click.option("--fd", type=int, default=None, help="Bind to socket from this file descriptor.")
@click.option("--reload", is_flag=True, default=False, help="Enable auto-reload.")
@click.option(
    "--reload-dir",
    "reload_dirs",
    multiple=True,
    help="Set reload directories explicitly, instead of using the current working directory.",
    type=click.Path(exists=True),
)
@click.option(
    "--reload-include",
    "reload_includes",
    multiple=True,
    help="Set glob patterns to include while watching for files. Includes '*.py' "
    "by default; these defaults can be overridden with `--reload-exclude`. "
    "This option has no effect unless watchfiles is installed.",
)
@click.option(
    "--reload-exclude",
    "reload_excludes",
    multiple=True,
    help="Set glob patterns to exclude while watching for files. Includes "
    "'.*, .py[cod], .sw.*, ~*' by default; these defaults can be overridden "
    "with `--reload-include`. This option has no effect unless watchfiles is "
    "installed.",
)
@click.option(
    "--reload-delay",
    type=float,
    default=0.25,
    show_default=True,
    help="Delay between previous and next check if application needs to be. Defaults to 0.25s.",
)
@click.option(
    "--workers",
    default=None,
    type=int,
    help="Number of worker processes. Defaults to the $WEB_CONCURRENCY environment"
    " variable if available, or 1. Not valid with --reload.",
)
@click.option(
    "--loop",
    type=str,
    metavar=_metavar_from_type(LoopFactoryType),
    default="auto",
    help="Event loop factory implementation.",
    show_default=True,
)
@click.option(
    "--http",
    type=str,
    metavar=_metavar_from_type(HTTPProtocolType),
    default="auto",
    help="HTTP protocol implementation.",
    show_default=True,
)
@click.option(
    "--ws",
    type=str,
    metavar=_metavar_from_type(WSProtocolType),
    default="auto",
    help="WebSocket protocol implementation.",
    show_default=True,
)
@click.option(
    "--ws-max-size",
    type=int,
    default=16777216,
    help="WebSocket max size message in bytes",
    show_default=True,
)
@click.option(
    "--ws-max-queue",
    type=int,
    default=32,
    help="The maximum length of the WebSocket message queue.",
    show_default=True,
)
@click.option(
    "--ws-ping-interval",
    type=float,
    default=20.0,
    help="WebSocket ping interval in seconds.",
    show_default=True,
)
@click.option(
    "--ws-ping-timeout",
    type=float,
    default=20.0,
    help="WebSocket ping timeout in seconds.",
    show_default=True,
)
@click.option(
    "--ws-per-message-deflate",
    type=bool,
    default=True,
    help="WebSocket per-message-deflate compression",
    show_default=True,
)
@click.option(
    "--lifespan",
    type=LIFESPAN_CHOICES,
    default="auto",
    help="Lifespan implementation.",
    show_default=True,
)
@click.option(
    "--interface",
    type=INTERFACE_CHOICES,
    default="auto",
    help="Select ASGI3, ASGI2, or WSGI as the application interface.",
    show_default=True,
)
@click.option(
    "--env-file",
    type=click.Path(exists=True),
    default=None,
    help="Environment configuration file.",
    show_default=True,
)
@click.option(
    "--log-config",
    type=click.Path(exists=True),
    default=None,
    help="Logging configuration file. Supported formats: .ini, .json, .yaml.",
    show_default=True,
)
@click.option(
    "--log-level",
    type=LEVEL_CHOICES,
    default=None,
    help="Log level. [default: info]",
    show_default=True,
)
@click.option(
    "--access-log/--no-access-log",
    is_flag=True,
    default=True,
    help="Enable/Disable access log.",
)
@click.option(
    "--use-colors/--no-use-colors",
    is_flag=True,
    default=None,
    help="Enable/Disable colorized logging.",
)
@click.option(
    "--proxy-headers/--no-proxy-headers",
    is_flag=True,
    default=True,
    help="Enable/Disable X-Forwarded-Proto, X-Forwarded-For to populate url scheme and remote address info.",
)
@click.option(
    "--s
[truncated — 12785 more characters]
```

### venv312/lib/python3.12/site-packages/pip/_internal/main.py

```python
from __future__ import annotations


def main(args: list[str] | None = None) -> int:
    """This is preserved for old console scripts that may still be referencing
    it.

    For additional details, see https://github.com/pypa/pip/issues/7498.
    """
    from pip._internal.utils.entrypoints import _wrapper

    return _wrapper(args)

```

[2021 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]