# Project export: Omnyla

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 2025
- Tagline: The AI copilot that helps cancer teams turn scattered patient data into the right treatment plan in minutes.
- Devpost: https://devpost.com/software/omnyla
- GitHub: https://github.com/Vatsal2006350/berkeley-hack
- Demo: https://www.canva.com/design/DAGrFZN6vBY/hriHqX8IaRjjRzqw0acMSw/edit?utm_content=DAGrFZN6vBY&utm_campaign=designshare&utm_medium=link2&utm_source=sharebutton
- Video: https://www.youtube.com/embed/QXk-6gthDHw?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 3 GitHub contributor(s) — Vatsal Shah (8 commits), Sunny Zhou (3 commits), Mohith K (1 commits)

## Devpost submission (written by the team)

### Inspiration

Cancer is personal for us. Several teammates watched loved ones get diagnosed at a late stage: some recovered, others did not. We want oncologists, already in short supply, to move faster so families like ours get help sooner. My own (Vatsal) 125-pound weight-loss journey also had me in clinics and ICUs from childhood on, where I saw the same problem everywhere: doctors spend more time hunting for data than using it. Conversations with relatives in oncology departments validated our hypothesis: Each patient can come with 25 + files across 10 formats (MRI, pathology slides, VCFs, PDFs). Genetics labs still copy-paste for 4 hours to match every DNA variant to drugs or trials. Oncologists burn 2 hours of prep for a 15-minute tumor-board slot. A wrong pick wastes $12 000 per patient, and 80 % of reports contain at least one error. 92 % of U.S. adults never reach a clinical trial that could save or extend their lives. So we set out to build an AI copilot that turns this data maze into one clear, real-time interface.

### What it does

Omnyla is an AI copilot for cancer teams. Doctors drag in slides, scans, VCFs, & clinic notes, and Omnyla: Ingests every modality: vision, genomics, text. Triages automatically, surfacing key findings and live-matching variants against PharmGKB / OncoKB for ranked drugs and trials. Joins the tumor board meeting as a voice agent that listens, answers questions (“Which trials fit this EGFR deletion?”) and writes a plain-English summary of the most optimal treatment option chosen by the pathologists, radiologists, and oncologists so that patients can finally read a condensed report that they can understand (free from the medical jargon). Hours of prep drop to minutes, and teams leave the meeting with one data-backed plan.

### How we built it

Frontend: Next.js + Tailwind + shadcn/ui on Vercel Speech & voice: Vapi streams real-time transcription using Groq and converses in a conversational voice format to keep the tumor board conversation grounded in the right data, given at the right time. LLM orchestration: Gemini for image analysis reasoning; Claude for report generation and meeting notes Vision: Microsoft BiomedCLIP to spot lesions and stains on MRI, CT, and pathology images Genomics search: TSV file-based PharmGKB clinical annotations for drug recommendation queries Agent workflow: Pipeline exposed as a Fetch.ai agent linking Pathology, Radiology, Genomics, and Meeting modules Security: Audio processing handled through Vapi's secure infrastructure

### Challenges we ran into

Putting BioMedCLIP onto a single GPU without missing tiny lesions Wrapping a multi-step pipeline as one Fetch.ai agent without blowing context limits Streaming hundreds of PharmGKB matches in under a second so the voice never stalls Harmonizing ten file types and keeping them synchronized after every upload

### Accomplishments we're proud of

End-to-end demo: upload → variant-drug matches → live copilot in the tumor board Cut prep time to < 90 seconds per patient in testing Two oncologists told us they would “use this tomorrow” because it feels like a teammate, not another portal

### What we learned

One model per modality beats one-size-fits-all; agents are the key Plain language matters more than perfect jargon. Doctors share summaries with patients immediately Latency kills trust; every second reduced off the pipeline increases adoption

### What's next

Integrate directly with hospital FHIR / EHR feeds so uploads disappear Feed real-world outcomes back into ranking logic to keep suggestions fresh Launch a patient portal that turns board notes into an interactive care roadmap Begin FDA Software-as-a-Medical-Device clearance so Omnyla can surface full treatment recommendations, not just insights

## README (from the GitHub repository)

# Nila Genomics - AI-Powered Genomic Analysis Platform

A comprehensive genomic analysis platform featuring AI-powered pathology assistance, tumor board collaboration, and pharmacogenomic insights for precision medicine.

## Features

- **Patient Management**: Complete patient dashboard with case overview, medical history, and biomarkers
- **VCF Analysis**: Real-time pharmacogenomic analysis using PharmCAT integration
- **Medical Imaging**: Interactive image gallery with MRI and histopathology visualization
- **Tumor Board**: Collaborative workspace with multi-agent AI specialists
- **Report Generation**: Comprehensive PDF reports for patients and tumor board minutes
- **Clinical Trials**: Integration with ClinicalTrials.gov for personalized trial matching

## Production Deployment on Vercel

### Prerequisites
- Node.js 18+ 
- pnpm (recommended) or npm

### Quick Deploy

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/your-username/genomics-5y)

### Manual Deployment

1. **Clone and Install**
   ```bash
   git clone <your-repo>
   cd genomics-5y
   pnpm install
   ```

2. **Build and Test Locally**
   ```bash
   pnpm build
   pnpm start
   ```

3. **Deploy to Vercel**
   ```bash
   vercel --prod
   ```

### Environment Variables

Set these in your Vercel dashboard:

```env
# Optional: PharmCAT JAR path (if using custom installation)
PHARMCAT_JAR_PATH=/path/to/pharmcat.jar

# Production optimizations
NODE_ENV=production
NEXT_PUBLIC_APP_ENV=production
```

### Configuration for Vercel

The app is pre-configured for Vercel deployment with:
- `next.config.mjs` optimized for static builds
- Image optimization disabled for better compatibility
- TypeScript and ESLint errors ignored during build (development focus)

## Technology Stack

- **Frontend**: Next.js 15, React 19, TypeScript
- **Styling**: Tailwind CSS, Radix UI components
- **State Management**: Zustand
- **PDF Generation**: jsPDF
- **File Processing**: Node.js filesystem APIs
- **Deployment**: Vercel (recommended)

## Key Components

- `VCFAnalysisTab`: Handles genomic file upload and analysis
- `TumorBoardWorkspace`: Multi-agent AI collaboration interface  
- `PatientDashboard`: Complete patient information management
- `ImagesTab`: Medical imaging with interactive annotations
- `PDF Generator`: Patient reports and tumor board minutes

## Production Features

- Error boundaries for graceful error handling
- Input validation and file size limits
- Loading states and user feedback
- Responsive design for all screen sizes
- SEO optimization and metadata
- Professional bot avatars for AI specialists

## Development

```bash
# Start development server
pnpm dev

# Run tests
pnpm test

# Type checking
pnpm build
```

## Support

For technical support or questions about deployment, please refer to the documentation or create an issue.

---

Built with ❤️ for precision medicine and genomic research. Design

*Automatically synced with your [v0.dev](https://v0.dev) deployments*

[![Deployed on Vercel](https://img.shields.io/badge/Deployed%20on-Vercel-black?style=for-the-badge&logo=vercel)](https://vercel.com/idhubal000-gmailcoms-projects/v0-nila-genomics-design)
[![Built with v0](https://img.shields.io/badge/Built%20with-v0.dev-black?style=for-the-badge)](https://v0.dev/chat/projects/8FgDjeFRn3S)

## Overview

This repository will stay in sync with your deployed chats on [v0.dev](https://v0.dev).
Any changes you make to your deployed app will be automatically pushed to this repository from [v0.dev](https://v0.dev).

## Deployment

Your project is live at:

**[https://vercel.com/idhubal000-gmailcoms-projects/v0-nila-genomics-design](https://vercel.com/idhubal000-gmailcoms-projects/v0-nila-genomics-design)**

## Build your app

Continue building your app on:

**[https://v0.dev/chat/projects/8FgDjeFRn3S](https://v0.dev/chat/projects/8FgDjeFRn3S)**

## How It Works

1. Create and modify your project using [v0.dev](https://v0.dev)
2. Deploy your chats from the v0 interface
3. Changes are automatically pushed to this repository
4. Vercel deploys the latest version from this repository
# berkeley-hack
# berkeley-hack


## Detected evidence (automated analysis)

Indexed codebase: 142 recognized source files, 838 KB.
- Anthropic (technology) — detected in the code
- CSS (language) — detected in the code
- FastAPI (technology) — detected in the code
- Flask (technology) — detected in the code
- HTML (language) — detected in the code
- Hugging Face (technology) — detected in the code
- Next.js (technology) — detected in the code
- OpenAI (technology) — detected in the code
- Python (language) — detected in the code
- PyTorch (technology) — detected in the code
- React (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- Docker (technology) — claimed on Devpost, not found in the code
- JavaScript (language) — claimed on Devpost, not found in the code
- Vercel (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (120 of 173)

```
__tests__/board-mode.test.tsx
.DS_Store
.gitignore
.vercelignore
app/add-patient/page.tsx
app/api/analyze-vcf/route.ts
app/api/transcribe/route.ts
app/dashboard/page.tsx
app/globals.css
app/layout.tsx
app/login/page.tsx
app/page.tsx
app/signup/page.tsx
clinical_annotations.tsv
components.json
components/.DS_Store
components/board/BoardModeContext.tsx
components/board/DecisionPad.tsx
components/board/FloatingVoiceControl.tsx
components/board/SessionTimer.tsx
components/board/TumorBoardWorkspace.tsx
components/chat-interface.tsx
components/patient-dashboard.tsx
components/patient-selector.tsx
components/tabs/biomarkers-tab.tsx
components/tabs/case-overview-tab.tsx
components/tabs/images-tab.tsx
components/tabs/patient-history-tab.tsx
components/tabs/resources-tab.tsx
components/tabs/vcf-analysis-tab.tsx
components/theme-provider.tsx
components/ui/accordion.tsx
components/ui/action-card.tsx
components/ui/alert-dialog.tsx
components/ui/alert.tsx
components/ui/aspect-ratio.tsx
components/ui/avatar.tsx
components/ui/badge.tsx
components/ui/bot-avatar.tsx
components/ui/breadcrumb.tsx
components/ui/button.tsx
components/ui/calendar.tsx
components/ui/card.tsx
components/ui/carousel.tsx
components/ui/chart.tsx
components/ui/checkbox.tsx
components/ui/collapsible.tsx
components/ui/command.tsx
components/ui/context-menu.tsx
components/ui/dialog.tsx
components/ui/drawer.tsx
components/ui/dropdown-menu.tsx
components/ui/error-boundary.tsx
components/ui/form.tsx
components/ui/hover-card.tsx
components/ui/input-otp.tsx
components/ui/input.tsx
components/ui/label.tsx
components/ui/loading.tsx
components/ui/menubar.tsx
components/ui/navigation-menu.tsx
components/ui/pagination.tsx
components/ui/popover.tsx
components/ui/progress.tsx
components/ui/radio-group.tsx
components/ui/resizable.tsx
components/ui/scroll-area.tsx
components/ui/select.tsx
components/ui/separator.tsx
components/ui/sheet.tsx
components/ui/sidebar.tsx
components/ui/skeleton.tsx
components/ui/slider.tsx
components/ui/sonner.tsx
components/ui/switch.tsx
components/ui/table.tsx
components/ui/tabs.tsx
components/ui/textarea.tsx
components/ui/toast.tsx
components/ui/toaster.tsx
components/ui/toggle-group.tsx
components/ui/toggle.tsx
components/ui/tooltip.tsx
components/ui/use-mobile.tsx
components/ui/use-toast.ts
components/workflow-dashboard.tsx
docker-compose.yml
Dockerfile
env.local.new
handlers/reporting.py
handlers/scan.py
handlers/vcf.py
hooks/use-mobile.tsx
hooks/use-toast.ts
hooks/useSocket.ts
hooks/useVisionAnalysis.ts
hooks/useVisionExplain.ts
lib/api/notes.ts
lib/data.ts
lib/pdf-generator.ts
lib/transcription.ts
lib/types.ts
lib/utils.ts
lib/vcf-analysis.ts
main.py
next.config.mjs
oncology-agent/.gitignore
oncology-agent/demo_pipeline.py
oncology-agent/fetch_agent.py
oncology-agent/handlers/reporting.py
oncology-agent/handlers/scan.py
oncology-agent/handlers/vcf.py
oncology-agent/main_agent.py
oncology-agent/messages.py
oncology-agent/pipeline.py
oncology-agent/register_agent.py
oncology-agent/register.py
oncology-agent/requirements.txt
oncology-agent/send_dummy_message.py
oncology-agent/simple_rest_agent.py
[53 more files omitted for size]
```

### Dependencies

- oncology-agent/requirements.txt: agentverse, anthropic, colorama, cosmpy, Flask, json-repair, pydantic@>=2, PyYAML, requests, tqdm, uagents@==0.22.5
- package.json: @anthropic-ai/sdk@^0.54.0, @gmod/vcf@^6.0.9, @hookform/resolvers@^3.9.1, @radix-ui/react-accordion@1.2.2, @radix-ui/react-alert-dialog@1.1.4, @radix-ui/react-aspect-ratio@1.1.1, @radix-ui/react-avatar@1.1.2, @radix-ui/react-checkbox@1.1.3, @radix-ui/react-collapsible@1.1.2, @radix-ui/react-context-menu@2.2.4, @radix-ui/react-dialog@1.1.4, @radix-ui/react-dropdown-menu@2.1.4, @radix-ui/react-hover-card@1.1.4, @radix-ui/react-label@2.1.1, @radix-ui/react-menubar@1.1.4, @radix-ui/react-navigation-menu@1.2.3, @radix-ui/react-popover@1.1.4, @radix-ui/react-progress@1.1.1, @radix-ui/react-radio-group@1.2.2, @radix-ui/react-scroll-area@1.2.2, @radix-ui/react-select@2.1.4, @radix-ui/react-separator@1.1.1, @radix-ui/react-slider@1.2.2, @radix-ui/react-slot@1.1.1, @radix-ui/react-switch@1.1.2, @radix-ui/react-tabs@1.1.2, @radix-ui/react-toast@1.2.4, @radix-ui/react-toggle@1.1.1, @radix-ui/react-toggle-group@1.1.1, @radix-ui/react-tooltip@1.1.6, @react-pdf/renderer@^4.3.0, @testing-library/jest-dom@^6.6.3, @testing-library/react@^16.3.0, @turf/distance@^7.2.0, @turf/helpers@^7.2.0, @types/node@^22, @types/react@^19, @types/react-dom@^19, @types/uuid@^10.0.0, @vapi-ai/web@^2.3.6, @vitejs/plugin-react@^4.5.1, autoprefixer@^10.4.20, class-variance-authority@^0.7.1, clsx@^2.1.1, cmdk@1.0.4, date-fns@^3.6.0, embla-carousel-react@8.5.1, groq-sdk@^0.25.0, html2canvas@^1.4.1, input-otp@1.4.1, jsdom@^26.1.0, jspdf@^3.0.1, lucide-react@^0.454.0, next@15.2.4, next-themes@^0.4.4, openai@^5.1.1, postcss@^8, react@^19, react-day-picker@8.10.1, react-dom@^19, react-hook-form@^7.54.1, react-markdown@^10.1.0, react-resizable-panels@^2.1.7, recharts@2.15.0, socket.io-client@^4.8.1, sonner@^1.7.1, tailwind-merge@^2.5.5, tailwind-scrollbar@^4.0.2, tailwindcss@^3.4.17, tailwindcss-animate@^1.0.7, typescript@^5, uuid@^11.1.0, vaul@^0.9.6, vitest@^3.2.2, zod@^3.24.1, zustand@^5.0.5
- requirements.txt: anthropic, cosmpy, fastapi, pandas, pydantic@>=2, python-dotenv, python-multipart, requests, tqdm, uagents, uvicorn, vcfpy
- vision_api/requirements.txt: fastapi@>=0.104.0, google-generativeai@>=0.3.0, numpy@>=1.24.0, open_clip_torch@>=2.20.0, pillow@>=10.0.0, pydicom@>=2.4.0, python-dotenv@>=1.0.0, python-multipart@>=0.0.6, torch@>=2.0.0, transformers@>=4.30.0, uvicorn[standard]@>=0.24.0

### Recent commits (newest first)

- push
- feat: update UI for Home, Login, and Signup pages only
- style: harmonize styles of home, login, and signup pages
- vapi voice agent working
- feat: Implement Claude integration and redesign UI
- Carefully merge Frontend Ver 2 components while preserving vision analysis functionality
- vision model implemented
- Add untracked files: clinical_annotations.tsv, main.py, package-lock.json, requirements.txt
- made the login page
- Add BiomedCLIP Vision Analysis Integration
- Add voice recorder functionality with secure API key handling
- added groq
- Initial commit

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

### VISION_SETUP.md

```markdown
# BiomedCLIP Vision Integration Setup

This document explains how to set up and use the BiomedCLIP vision analysis feature in your tumor board application.

## 🏗️ Architecture

```
┌───────────────────┐    POST /predict    ┌─────────────────────────┐
│  Frontend (React  │ ──────────────────▶ │   Vision-API (FastAPI)  │
│  Images tab)      │ ◀──── JSON response │  ‣ BiomedCLIP model     │
└───────────────────┘                     │  ‣ DICOM / PNG adapter │
                                          │  ‣ Medical classification│
                                          └─────────────────────────┘
```

## 🚀 Quick Start

### Option 1: Local Development

1. **Install Python Dependencies**
   ```bash
   cd vision_api
   python -m venv .venv
   source .venv/bin/activate  # On Windows: .venv\Scripts\activate
   pip install -r requirements.txt
   ```

2. **Start Vision API**
   ```bash
   python -m vision_api.server
   # API will be available at http://localhost:8000
   ```

3. **Start Frontend** (in another terminal)
   ```bash
   pnpm dev
   # Frontend available at http://localhost:3000
   ```

### Option 2: Docker (Recommended for Demo)

1. **Build and Run with Docker Compose**
   ```bash
   docker compose up --build
   ```

   This will start both services:
   - Vision API: http://localhost:8000
   - Frontend: http://localhost:3000

## 🔧 Configuration

### Environment Variables

Add to your `.env.local`:
```bash
NEXT_PUBLIC_VISION_API_URL=http://localhost:8000
NEXT_PUBLIC_ANTHROPIC_API_KEY=your-anthropic-key
GROQ_API_KEY=your-groq-key
```

## 🖼️ How to Use

1. **Navigate to Images Tab**
   - Go to the tumor board workspace
   - Click on the "Images" tab

2. **Select an Image**
   - Click on any thumbnail to select it
   - The main viewer will show the selected image

3. **Run AI Analysis**
   - Click "Analyze" for basic classification
   - Click "With Heatmap" for analysis with attention visualization
   - Results will appear in the "BiomedCLIP Analysis" section

4. **View Results**
   - AI classification label (e.g., "glioma on brain MRI")
   - Confidence percentage
   - Color-coded confidence badges (High/Medium/Low)
   - Optional heatmap overlay showing model attention

## 🧠 Supported Medical Conditions

The BiomedCLIP model can classify:

**Brain/Neurological:**
- Brain tumor, Glioma, Meningioma
- Stroke, Hemorrhage, Ischemic stroke
- Multiple sclerosis lesions
- Alzheimer disease changes

**Chest/Pulmonary:**
- Pneumonia, COVID-19 pneumonia
- Lung cancer, Pleural effusion
- Pneumothorax, Atelectasis
- Cardiomegaly, Consolidation

**Abdominal:**
- Liver cirrhosis, Kidney stones
- Appendicitis, Bowel obstruction
- Pancreatic cancer, Gallstones

## 📊 API Endpoints

### GET /health
Health check with model information

### POST /predict
Basic image classification
- **Input:** Multipart form with image file
- **Output:** `{label: string, confidence: number}`

### POST /predict-with-heatmap
Classification with attention heatmap
- **Input:** Multipa
[truncated — 1419 more characters]
```

### VAPI_INTEGRATION_GUIDE.md

```markdown
# Vapi Voice AI Integration Guide

## Overview

Your tumor board system now supports **conversational voice AI** using Vapi! Doctors can now:

1. **Ask questions verbally** and get spoken responses from AI specialists
2. **Have natural conversations** with the AI medical team
3. **Get text-to-speech responses** for regular chat messages

## How It Works

### Voice Conversation Flow
1. Doctor clicks the **microphone button** (green) to start voice conversation
2. Vapi handles speech-to-text, sends to Claude (your existing credits!)
3. Claude responds as the appropriate specialist (Genetics, Radiology, etc.)
4. Vapi converts Claude's response to natural speech
5. Doctor hears the AI specialist speaking back

### Text-to-Speech for Regular Chat
- When you type messages and get AI responses, they'll also be spoken aloud
- Uses your existing Claude setup but adds voice capabilities

## API Keys Required

### 1. Vapi API Key (NEW - Required)
- **What it does**: Handles voice infrastructure (speech recognition, text-to-speech, real-time conversation)
- **Where to get it**: [Vapi Dashboard](https://vapi.ai)
- **Cost**: Vapi has usage-based pricing for voice minutes
- **Why needed**: Vapi orchestrates the voice conversation but delegates thinking to Claude

### 2. Your Existing Anthropic API Key (Already Have)
- **What it does**: Powers Claude for the medical expertise
- **Reused**: Your existing key and credits work perfectly
- **Why this setup**: You keep using your Claude credits, Vapi just adds voice

## Environment Variables Needed

Add these to your `.env.local` file:

```bash
# Your existing keys (keep these)
NEXT_PUBLIC_ANTHROPIC_API_KEY=your_existing_anthropic_key

# New Vapi key (get from Vapi dashboard)
NEXT_PUBLIC_VAPI_API_KEY=your_vapi_api_key_here

# New Vapi assistant ID (get from Vapi dashboard)
NEXT_PUBLIC_VAPI_ASSISTANT_ID=dfa9d209-84b2-42a9-8a36-4687851ec607
```

## Setup Steps

### 1. Get Vapi API Key
1. Go to [vapi.ai](https://vapi.ai)
2. Sign up/login
3. Go to Dashboard → API Keys
4. Create a new API key
5. Add to your `.env.local` as `NEXT_PUBLIC_VAPI_API_KEY`

### 2. Test the Integration
1. Start your development server: `npm run dev`
2. Go to the tumor board workspace
3. You'll see a green microphone button next to the send button
4. Click it to start voice conversation

### 3. Optional: Create Custom Assistant
Instead of the inline configuration, you can create a pre-configured assistant:

1. In Vapi Dashboard → Assistants → Create New
2. Configure:
   - **Model**: Anthropic Claude 3 Sonnet
   - **API Key**: Your Anthropic key
   - **System Message**: Copy from the code or customize
   - **Voice**: ElevenLabs (built into Vapi)
   - **Transcriber**: Deepgram (built into Vapi)
3. Save and copy the Assistant ID
4. Add to `.env.local` as `NEXT_PUBLIC_VAPI_ASSISTANT_ID`

## Features

### Voice Conversation Mode
- **Green microphone button**: Start/stop voice conversation
- **Real-time transcription**: See what you're saying
- **AI spe
[truncated — 2421 more characters]
```

### requirements.txt

```
fastapi
uvicorn
pandas
python-multipart
vcfpy 
uagents
cosmpy
anthropic
pydantic>=2
requests
tqdm
python-dotenv 
```

### docker-compose.yml

```yaml
version: "3.9"

services:
  vision-api:
    build: ./vision_api
    ports:
      - "8000:8000"
    environment:
      - PORT=8000
    volumes:
      - ~/.cache/biomedclip:/root/.cache/biomedclip
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  frontend:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NEXT_PUBLIC_VISION_API_URL=http://localhost:8000
      - NEXT_PUBLIC_ANTHROPIC_API_KEY=${NEXT_PUBLIC_ANTHROPIC_API_KEY}
      - GROQ_API_KEY=${GROQ_API_KEY}
    depends_on:
      - vision-api
    restart: unless-stopped 
```

### Dockerfile

```
# Use the official Node.js 18 image as the base
FROM node:18-slim

# Install Java 17 and other dependencies
RUN apt-get update && apt-get install -y \
    openjdk-17-jdk \
    curl \
    gunzip \
    && rm -rf /var/lib/apt/lists/*

# Set Java environment
ENV JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
ENV PATH=$JAVA_HOME/bin:$PATH

# Create app directory
WORKDIR /app

# Copy package files
COPY package*.json ./
COPY pnpm-lock.yaml ./

# Install pnpm and dependencies
RUN npm install -g pnpm && pnpm install

# Create pharmcat directory and download PharmCAT
RUN mkdir -p /app/pharmcat
WORKDIR /app/pharmcat

# Download PharmCAT (version 3.0.1)
RUN curl -L -O https://github.com/PharmGKB/PharmCAT/releases/download/v3.0.1/pharmcat-3.0.1-all.jar

# Download and extract preprocessor
RUN curl -L -O https://github.com/PharmGKB/PharmCAT/releases/download/v3.0.1/pharmcat-preprocessor-3.0.1.tar.gz \
    && tar -xzf pharmcat-preprocessor-3.0.1.tar.gz \
    && rm pharmcat-preprocessor-3.0.1.tar.gz

# Go back to app directory
WORKDIR /app

# Copy the rest of the application
COPY . .

# Create temp directory for VCF processing
RUN mkdir -p /app/temp

# Set permissions
RUN chmod +x /app/pharmcat/pharmcat-3.0.1-all.jar

# Build the Next.js application
RUN pnpm build

# Expose port
EXPOSE 3000

# Set environment variables
ENV PHARMCAT_JAR_PATH=/app/pharmcat/pharmcat-3.0.1-all.jar
ENV JAVA_PATH=/usr/lib/jvm/java-17-openjdk-amd64/bin/java

# Start the application
CMD ["pnpm", "start"] 
```

### package.json

```
{
  "name": "my-v0-project",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "test": "vitest",
    "test:ui": "vitest --ui"
  },
  "dependencies": {
    "@anthropic-ai/sdk": "^0.54.0",
    "@gmod/vcf": "^6.0.9",
    "@hookform/resolvers": "^3.9.1",
    "@radix-ui/react-accordion": "1.2.2",
    "@radix-ui/react-alert-dialog": "1.1.4",
    "@radix-ui/react-aspect-ratio": "1.1.1",
    "@radix-ui/react-avatar": "1.1.2",
    "@radix-ui/react-checkbox": "1.1.3",
    "@radix-ui/react-collapsible": "1.1.2",
    "@radix-ui/react-context-menu": "2.2.4",
    "@radix-ui/react-dialog": "1.1.4",
    "@radix-ui/react-dropdown-menu": "2.1.4",
    "@radix-ui/react-hover-card": "1.1.4",
    "@radix-ui/react-label": "2.1.1",
    "@radix-ui/react-menubar": "1.1.4",
    "@radix-ui/react-navigation-menu": "1.2.3",
    "@radix-ui/react-popover": "1.1.4",
    "@radix-ui/react-progress": "1.1.1",
    "@radix-ui/react-radio-group": "1.2.2",
    "@radix-ui/react-scroll-area": "1.2.2",
    "@radix-ui/react-select": "2.1.4",
    "@radix-ui/react-separator": "1.1.1",
    "@radix-ui/react-slider": "1.2.2",
    "@radix-ui/react-slot": "1.1.1",
    "@radix-ui/react-switch": "1.1.2",
    "@radix-ui/react-tabs": "1.1.2",
    "@radix-ui/react-toast": "1.2.4",
    "@radix-ui/react-toggle": "1.1.1",
    "@radix-ui/react-toggle-group": "1.1.1",
    "@radix-ui/react-tooltip": "1.1.6",
    "@react-pdf/renderer": "^4.3.0",
    "@turf/distance": "^7.2.0",
    "@turf/helpers": "^7.2.0",
    "@types/uuid": "^10.0.0",
    "@vapi-ai/web": "^2.3.6",
    "autoprefixer": "^10.4.20",
    "class-variance-authority": "^0.7.1",
    "clsx": "^2.1.1",
    "cmdk": "1.0.4",
    "date-fns": "^3.6.0",
    "embla-carousel-react": "8.5.1",
    "groq-sdk": "^0.25.0",
    "html2canvas": "^1.4.1",
    "input-otp": "1.4.1",
    "jspdf": "^3.0.1",
    "lucide-react": "^0.454.0",
    "next": "15.2.4",
    "next-themes": "^0.4.4",
    "openai": "^5.1.1",
    "react": "^19",
    "react-day-picker": "8.10.1",
    "react-dom": "^19",
    "react-hook-form": "^7.54.1",
    "react-markdown": "^10.1.0",
    "react-resizable-panels": "^2.1.7",
    "recharts": "2.15.0",
    "socket.io-client": "^4.8.1",
    "sonner": "^1.7.1",
    "tailwind-merge": "^2.5.5",
    "tailwind-scrollbar": "^4.0.2",
    "tailwindcss-animate": "^1.0.7",
    "uuid": "^11.1.0",
    "vaul": "^0.9.6",
    "zod": "^3.24.1",
    "zustand": "^5.0.5"
  },
  "devDependencies": {
    "@testing-library/jest-dom": "^6.6.3",
    "@testing-library/react": "^16.3.0",
    "@types/node": "^22",
    "@types/react": "^19",
    "@types/react-dom": "^19",
    "@vitejs/plugin-react": "^4.5.1",
    "jsdom": "^26.1.0",
    "postcss": "^8",
    "tailwindcss": "^3.4.17",
    "typescript": "^5",
    "vitest": "^3.2.2"
  }
}

```

### oncology-agent/requirements.txt

```
uagents==0.22.5
cosmpy
anthropic
pydantic>=2
requests
tqdm 
agentverse
colorama
json-repair
Flask
PyYAML 
```

### vision_api/requirements.txt

```
torch>=2.0.0
open_clip_torch>=2.20.0
pydicom>=2.4.0
pillow>=10.0.0
fastapi>=0.104.0
uvicorn[standard]>=0.24.0
numpy>=1.24.0
python-multipart>=0.0.6
transformers>=4.30.0
google-generativeai>=0.3.0
python-dotenv>=1.0.0 
```

### vision_api/Dockerfile

```
FROM python:3.10-slim

# Set working directory
WORKDIR /app

# Install system dependencies
RUN apt-get update && apt-get install -y \
    gcc \
    g++ \
    && rm -rf /var/lib/apt/lists/*

# Copy requirements and install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy application code
COPY . .

# Expose port
EXPOSE 8000

# Set environment variables
ENV PORT=8000
ENV PYTHONPATH=/app

# Run the application
CMD ["python", "-m", "vision_api.server"] 
```

### main.py

```python
import os
from fastapi import FastAPI, File, UploadFile, HTTPException
from fastapi.responses import JSONResponse
from fastapi.middleware.cors import CORSMiddleware
import pandas as pd
# import vcfpy  # Commented out due to missing dependency
from typing import List, Dict, Any

# Initialize FastAPI app
app = FastAPI(title="PharmGKB Drug Recommendation API")

# Allow CORS for local frontend testing
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Load PharmGKB clinical annotations
PHARMGKB_TSV = "clinical_annotations.tsv"  # Place this file in the same directory
if not os.path.exists(PHARMGKB_TSV):
    raise FileNotFoundError(f"PharmGKB data file '{PHARMGKB_TSV}' not found.")
try:
    pharmgkb_df = pd.read_csv(PHARMGKB_TSV, sep='\t', dtype=str).fillna("")
    # Use the actual column names from the user's file
    required_cols = [
        "Gene",                # Gene
        "Variant/Haplotypes", # Variant
        "Drug(s)",            # Drug
        "Phenotype Category", # Phenotype Category
        "Level of Evidence",  # Level of Evidence
        "Phenotype(s)"        # Annotation/Reasoning
    ]
    for col in required_cols:
        if col not in pharmgkb_df.columns:
            raise ValueError(f"Missing required column in TSV: {col}")
except Exception as e:
    raise RuntimeError(f"Failed to load PharmGKB data: {e}")

def parse_vcf_rsids(file_path: str):
    """Dummy parser: returns a hardcoded list of rsIDs for testing."""
    return ["rs123", "rs456", "rs789"]

def match_variants_to_drugs(rsids: List[str]) -> List[Dict[str, Any]]:
    """Match rsIDs to PharmGKB and extract drug recommendations."""
    matches = []
    for rsid in rsids:
        matched = pharmgkb_df[pharmgkb_df["Variant/Haplotypes"].str.contains(rsid, case=False, na=False)]
        for _, row in matched.iterrows():
            matches.append({
                "gene": row["Gene"],
                "variant": row["Variant/Haplotypes"],
                "drug": row["Drug(s)"],
                "phenotype": row["Phenotype Category"],
                "evidence": row["Level of Evidence"],
                "annotation": row["Phenotype(s)"]
            })
    return matches

@app.post("/predict_drugs")
async def predict_drugs(file: UploadFile = File(...)):
    # Validate file type
    if not file.filename.endswith(".vcf"):
        raise HTTPException(status_code=400, detail="Only .vcf files are accepted.")
    # Save uploaded file temporarily
    temp_path = f"temp_{file.filename}"
    try:
        with open(temp_path, "wb") as f:
            f.write(await file.read())
        rsids = parse_vcf_rsids(temp_path)
        predictions = match_variants_to_drugs(rsids)
        response = {
            "variants": rsids,
            "predictions": predictions
        }
        if not predictions:
            response["message"] = "No drug recommendations found for provided variants."
        return JSONResponse(content=response)
    except ValueError as ve:
        raise HTTPException(status_code=422, detail=str(ve))
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Internal server error: {e}")
    finally:
        if os.path.exists(temp_path):
            os.remove(temp_path)

# --- Suggestions for Improvements ---
# 1. Rank predictions by evidence level (A > B > C > D > E).
# 2. Integrate LLM (e.g., GPT-4) to generate patient-friendly explanations.
# 3. Add authentication for sensitive data.
# 4. Support batch VCF uploads or multiple patients.
# 5. Add logging and monitoring for production use.

# --- Run Instructions ---
# 1. Install dependencies:
#    pip install fastapi uvicorn pandas python-multipart vcfpy
# 2. Place clinical_annotations.tsv in the same directory as main.py.
# 3. Run the server:
#    uvicorn main:app --reload
# 4. Access Swagger UI for testing:
#    http://localhost:8000/docs
#
# --- Sample Frontend Fetch Request ---
# const formData = new FormData();
# formData.append('file', fileInput.files[0]);
# fetch('http://localhost:8000/predict_drugs', {
#   method: 'POST',
#   body: formData
# })
#   .then(res => res.json())
#   .then(data => console.log(data)); 
```

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