Spaces:
Runtime error
Runtime error
Remove demo page and all demo-related files
Browse files- Removed DemoLive page component
- Removed demo route from App.tsx
- Deleted demo automation scripts and folder
- Removed demo data and documentation
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
- DEMO_SCRIPT.md +0 -216
- demo-automation/.gitignore +0 -25
- demo-automation/README.md +0 -132
- demo-automation/demo-debug.png +0 -0
- demo-automation/demo-leptospirosis.js +0 -258
- demo-automation/demo.js +0 -532
- demo-automation/fix-chrome.sh +0 -38
- demo-automation/package-lock.json +0 -1128
- demo-automation/package.json +0 -14
- demo-automation/run-demo.sh +0 -33
- demo-automation/setup.sh +0 -38
- frontend/src/App.tsx +0 -2
- frontend/src/data/demoData.ts +0 -351
- frontend/src/pages/DemoLive.tsx +0 -236
DEMO_SCRIPT.md
DELETED
|
@@ -1,216 +0,0 @@
|
|
| 1 |
-
# Clinical Mind - Hackathon Demo Script
|
| 2 |
-
|
| 3 |
-
## 🎬 PRIVATE DEMO INSTRUCTIONS (Not shown to judges)
|
| 4 |
-
|
| 5 |
-
### Demo URL: `http://localhost:3000/demo`
|
| 6 |
-
|
| 7 |
-
---
|
| 8 |
-
|
| 9 |
-
## DEMO 1: ACUTE MI (Heart Attack) - 8-10 minutes
|
| 10 |
-
|
| 11 |
-
### Step 1: Student Profile Selection
|
| 12 |
-
**What to Enter:**
|
| 13 |
-
- Name: `Demo Student` (or your name)
|
| 14 |
-
- Level: Select **"Intern"** ← IMPORTANT!
|
| 15 |
-
|
| 16 |
-
### Step 2: Case Selection
|
| 17 |
-
**Select:** The first case - "Severe crushing chest pain for 2 hours"
|
| 18 |
-
|
| 19 |
-
### Step 3: Wait for Agent Initialization
|
| 20 |
-
- Takes 2-3 minutes
|
| 21 |
-
- Explain to judges: "5 AI agents are learning this case in parallel using Claude Opus 4.1"
|
| 22 |
-
- Point out the animated loading screen showing each agent preparing
|
| 23 |
-
|
| 24 |
-
### Step 4: Initial Messages
|
| 25 |
-
- You'll see messages from Patient, Family, Nurse Priya, and Dr. Sharma
|
| 26 |
-
- Let them read the Hinglish messages
|
| 27 |
-
|
| 28 |
-
### Step 5: Conversation Script
|
| 29 |
-
|
| 30 |
-
**Question 1 - Talk to Patient:**
|
| 31 |
-
```
|
| 32 |
-
Can you describe your chest pain?
|
| 33 |
-
```
|
| 34 |
-
*Expected: Patient describes crushing chest pain in Hinglish*
|
| 35 |
-
|
| 36 |
-
**Question 2 - Ask Nurse:**
|
| 37 |
-
```
|
| 38 |
-
What are the current vital signs?
|
| 39 |
-
```
|
| 40 |
-
*Expected: Nurse reports critical vitals, BP dropping*
|
| 41 |
-
|
| 42 |
-
**Question 3 - Order Investigation:**
|
| 43 |
-
```
|
| 44 |
-
ECG stat
|
| 45 |
-
```
|
| 46 |
-
*Expected: ECG ordered urgently*
|
| 47 |
-
|
| 48 |
-
**Question 4 - Consult Senior:**
|
| 49 |
-
```
|
| 50 |
-
ECG shows ST elevation, should we activate cath lab?
|
| 51 |
-
```
|
| 52 |
-
*Expected: Dr. Sharma confirms STEMI, educational feedback*
|
| 53 |
-
|
| 54 |
-
**Question 5 - Order Treatment:**
|
| 55 |
-
```
|
| 56 |
-
Aspirin 325mg stat, prepare for PCI
|
| 57 |
-
```
|
| 58 |
-
*Expected: Treatment initiated*
|
| 59 |
-
|
| 60 |
-
**Question 6 - Team Huddle:**
|
| 61 |
-
```
|
| 62 |
-
STEMI protocol activated
|
| 63 |
-
```
|
| 64 |
-
*Expected: ALL 5 agents respond - shows orchestration!*
|
| 65 |
-
|
| 66 |
-
### Step 6: Make Diagnosis
|
| 67 |
-
Click "Make Diagnosis" button when it appears
|
| 68 |
-
Enter: `Acute ST-elevation myocardial infarction`
|
| 69 |
-
|
| 70 |
-
### Key Points to Emphasize:
|
| 71 |
-
- Live vitals updating every 5 seconds (point to the numbers changing)
|
| 72 |
-
- Urgency indicators (red/amber/green colors)
|
| 73 |
-
- Multiple agents responding naturally
|
| 74 |
-
- Hinglish authenticity in patient/family responses
|
| 75 |
-
|
| 76 |
-
---
|
| 77 |
-
|
| 78 |
-
## DEMO 2: DENGUE FEVER - 10-12 minutes
|
| 79 |
-
|
| 80 |
-
### Step 1: Student Profile Selection
|
| 81 |
-
**What to Enter:**
|
| 82 |
-
- Name: `Demo Student`
|
| 83 |
-
- Level: Select **"MBBS 3rd Year"** ← IMPORTANT!
|
| 84 |
-
|
| 85 |
-
### Step 2: Case Selection
|
| 86 |
-
**Select:** The second case - "High fever with body aches for 4 days"
|
| 87 |
-
|
| 88 |
-
### Step 3: Wait for Initialization
|
| 89 |
-
- Same 2-3 minute wait
|
| 90 |
-
- Explain parallel agent learning
|
| 91 |
-
|
| 92 |
-
### Step 4: Conversation Script
|
| 93 |
-
|
| 94 |
-
**Question 1 - Talk to Patient:**
|
| 95 |
-
```
|
| 96 |
-
Kab se bukhar hai? Any bleeding from anywhere?
|
| 97 |
-
```
|
| 98 |
-
*Expected: Patient responds in Hinglish about 4-day fever*
|
| 99 |
-
|
| 100 |
-
**Question 2 - Talk to Family:**
|
| 101 |
-
```
|
| 102 |
-
Kya khaya piya hai? Any mosquito bites?
|
| 103 |
-
```
|
| 104 |
-
*Expected: Family provides context in Hinglish*
|
| 105 |
-
|
| 106 |
-
**Question 3 - Examine Patient:**
|
| 107 |
-
```
|
| 108 |
-
Tourniquet test
|
| 109 |
-
```
|
| 110 |
-
*Expected: Physical exam findings*
|
| 111 |
-
|
| 112 |
-
**Question 4 - Order Investigation:**
|
| 113 |
-
```
|
| 114 |
-
CBC with platelet count, Dengue NS1
|
| 115 |
-
```
|
| 116 |
-
*Expected: Labs ordered*
|
| 117 |
-
|
| 118 |
-
**Question 5 - Ask Lab Tech:**
|
| 119 |
-
```
|
| 120 |
-
Platelet count kya hai?
|
| 121 |
-
```
|
| 122 |
-
*Expected: Lab Tech Ramesh reports falling platelets*
|
| 123 |
-
|
| 124 |
-
**Question 6 - Order Treatment:**
|
| 125 |
-
```
|
| 126 |
-
IV fluids NS 100ml/hr, monitor platelets
|
| 127 |
-
```
|
| 128 |
-
*Expected: Supportive care started*
|
| 129 |
-
|
| 130 |
-
**Question 7 - Consult Senior:**
|
| 131 |
-
```
|
| 132 |
-
Warning signs present, should we admit?
|
| 133 |
-
```
|
| 134 |
-
*Expected: Dr. Sharma provides teaching on dengue management*
|
| 135 |
-
|
| 136 |
-
### Step 5: Make Diagnosis
|
| 137 |
-
Enter: `Dengue fever with warning signs`
|
| 138 |
-
|
| 139 |
-
---
|
| 140 |
-
|
| 141 |
-
## 📹 RECORDING TIPS
|
| 142 |
-
|
| 143 |
-
1. **Browser Setup:**
|
| 144 |
-
- Use Chrome in incognito mode
|
| 145 |
-
- Window size: 1920x1080
|
| 146 |
-
- Hide bookmarks bar
|
| 147 |
-
- Close all other tabs
|
| 148 |
-
|
| 149 |
-
2. **Before Recording:**
|
| 150 |
-
- Clear browser cache
|
| 151 |
-
- Restart backend if needed
|
| 152 |
-
- Test one message first
|
| 153 |
-
|
| 154 |
-
3. **During Recording:**
|
| 155 |
-
- Speak clearly about what's happening
|
| 156 |
-
- Point out live vitals updates
|
| 157 |
-
- Emphasize multi-agent responses
|
| 158 |
-
- Show the loading animation
|
| 159 |
-
|
| 160 |
-
---
|
| 161 |
-
|
| 162 |
-
## 🎯 KEY TALKING POINTS
|
| 163 |
-
|
| 164 |
-
### Technical Excellence:
|
| 165 |
-
- "Real-time API calls to Claude Opus 4.1"
|
| 166 |
-
- "5 specialized agents learning in parallel"
|
| 167 |
-
- "432 real medical cases in vector database"
|
| 168 |
-
- "Authentic Indian hospital simulation"
|
| 169 |
-
|
| 170 |
-
### Educational Value:
|
| 171 |
-
- "Personalized to student level"
|
| 172 |
-
- "Active learning through conversation"
|
| 173 |
-
- "Immediate feedback from senior doctor"
|
| 174 |
-
- "Safe environment to practice"
|
| 175 |
-
|
| 176 |
-
### Multi-Agent Orchestration:
|
| 177 |
-
- "Notice how each agent has their own personality"
|
| 178 |
-
- "Family speaks in Hinglish naturally"
|
| 179 |
-
- "Agents coordinate without explicit programming"
|
| 180 |
-
- "Seamless handoffs between agents"
|
| 181 |
-
|
| 182 |
-
### Live Features:
|
| 183 |
-
- "Watch the vitals - they update every 5 seconds"
|
| 184 |
-
- "Color coding shows urgency levels"
|
| 185 |
-
- "Suggested questions guide clinical reasoning"
|
| 186 |
-
- "Real-time case progression"
|
| 187 |
-
|
| 188 |
-
---
|
| 189 |
-
|
| 190 |
-
## ⚠️ TROUBLESHOOTING
|
| 191 |
-
|
| 192 |
-
**If agents take too long to initialize:**
|
| 193 |
-
- Say: "Complex cases require more learning time"
|
| 194 |
-
- Explain the parallel processing happening
|
| 195 |
-
|
| 196 |
-
**If an unexpected response:**
|
| 197 |
-
- Say: "The AI is contextually aware and may vary responses"
|
| 198 |
-
- Continue with the script
|
| 199 |
-
|
| 200 |
-
**If vitals don't update:**
|
| 201 |
-
- Continue normally - they update in background
|
| 202 |
-
- Focus on the conversation flow
|
| 203 |
-
|
| 204 |
-
---
|
| 205 |
-
|
| 206 |
-
## 🏆 CLOSING STATEMENT
|
| 207 |
-
|
| 208 |
-
"Clinical Mind transforms medical education by providing authentic, AI-powered clinical simulations. With 5 specialized agents working together, students experience real hospital dynamics while learning at their own pace. The system uses cutting-edge Claude Opus 4.1 API with parallel processing and a knowledge base of 432 real cases, creating an immersive learning environment that bridges the gap between textbooks and clinical practice."
|
| 209 |
-
|
| 210 |
-
---
|
| 211 |
-
|
| 212 |
-
**Remember:**
|
| 213 |
-
- The demo page looks EXACTLY like the real app
|
| 214 |
-
- No special labeling or "demo mode" indicators
|
| 215 |
-
- Everything is real API calls
|
| 216 |
-
- Just follow this script for optimal presentation
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
demo-automation/.gitignore
DELETED
|
@@ -1,25 +0,0 @@
|
|
| 1 |
-
# Dependencies
|
| 2 |
-
node_modules/
|
| 3 |
-
|
| 4 |
-
# Logs
|
| 5 |
-
*.log
|
| 6 |
-
npm-debug.log*
|
| 7 |
-
|
| 8 |
-
# Recording outputs (if saved here)
|
| 9 |
-
*.mp4
|
| 10 |
-
*.mov
|
| 11 |
-
*.avi
|
| 12 |
-
*.webm
|
| 13 |
-
recordings/
|
| 14 |
-
|
| 15 |
-
# OS files
|
| 16 |
-
.DS_Store
|
| 17 |
-
Thumbs.db
|
| 18 |
-
|
| 19 |
-
# IDE
|
| 20 |
-
.vscode/
|
| 21 |
-
.idea/
|
| 22 |
-
|
| 23 |
-
# Temp files
|
| 24 |
-
*.tmp
|
| 25 |
-
*.swp
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
demo-automation/README.md
DELETED
|
@@ -1,132 +0,0 @@
|
|
| 1 |
-
# Clinical Mind - Automated Demo
|
| 2 |
-
|
| 3 |
-
**Separate automation for hackathon demo recording**
|
| 4 |
-
|
| 5 |
-
This is a standalone Puppeteer script that runs the Clinical Mind demo autonomously while you record your screen. Perfect for hackathon presentations where you need a smooth, professional demo without fumbling with medical terminology.
|
| 6 |
-
|
| 7 |
-
## 🎯 Why Automated Demo?
|
| 8 |
-
|
| 9 |
-
- **Industry Standard**: Most winning hackathon teams use scripted demos
|
| 10 |
-
- **Consistent**: Same perfect flow every time
|
| 11 |
-
- **Professional**: No typos, no confusion, smooth pacing
|
| 12 |
-
- **Separate**: Doesn't interfere with main project code
|
| 13 |
-
- **Judges can still test**: Main app at `/simulation` works independently
|
| 14 |
-
|
| 15 |
-
## 🚀 Quick Start
|
| 16 |
-
|
| 17 |
-
### 1. Setup (One Time)
|
| 18 |
-
```bash
|
| 19 |
-
cd demo-automation
|
| 20 |
-
npm install
|
| 21 |
-
```
|
| 22 |
-
|
| 23 |
-
### 2. Ensure App is Running
|
| 24 |
-
```bash
|
| 25 |
-
# Terminal 1 - Backend
|
| 26 |
-
cd ../backend
|
| 27 |
-
source venv/bin/activate # or venv\Scripts\activate on Windows
|
| 28 |
-
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
|
| 29 |
-
|
| 30 |
-
# Terminal 2 - Frontend
|
| 31 |
-
cd ../frontend
|
| 32 |
-
npm start
|
| 33 |
-
```
|
| 34 |
-
|
| 35 |
-
### 3. Run Demo
|
| 36 |
-
```bash
|
| 37 |
-
# Terminal 3 - Demo
|
| 38 |
-
cd demo-automation
|
| 39 |
-
npm run demo
|
| 40 |
-
```
|
| 41 |
-
|
| 42 |
-
### 4. Record Your Screen
|
| 43 |
-
- Start recording when you see "📹 Start your screen recording software now!"
|
| 44 |
-
- The script will:
|
| 45 |
-
- Open browser automatically
|
| 46 |
-
- Navigate through the entire case
|
| 47 |
-
- Type messages with realistic speed
|
| 48 |
-
- Click buttons at the right time
|
| 49 |
-
- Show all features systematically
|
| 50 |
-
- Stop recording when you see "✅ Demo completed successfully!"
|
| 51 |
-
|
| 52 |
-
## 📝 Available Scripts
|
| 53 |
-
|
| 54 |
-
- `npm run demo` - Runs demo using /demo page (predictable)
|
| 55 |
-
- `npm run demo:leptos` - Runs full simulation with Leptospirosis
|
| 56 |
-
- `npm run demo:nmosd` - Runs NMOSD case demo (if needed)
|
| 57 |
-
|
| 58 |
-
## 🎬 What Gets Demonstrated
|
| 59 |
-
|
| 60 |
-
1. **Multi-Agent System** - All 5 agents responding
|
| 61 |
-
2. **Hinglish Authenticity** - Patient/family speaking naturally
|
| 62 |
-
3. **Clinical Workflow** - History → Examination → Investigation → Diagnosis
|
| 63 |
-
4. **Real-time Vitals** - Shows critical values updating
|
| 64 |
-
5. **Team Collaboration** - Huddle feature with all agents
|
| 65 |
-
6. **Educational Value** - Senior doctor providing guidance
|
| 66 |
-
7. **Investigation System** - Ordering and checking lab results
|
| 67 |
-
8. **Treatment Management** - Starting appropriate therapy
|
| 68 |
-
9. **Patient Deterioration** - Urgency indicators
|
| 69 |
-
|
| 70 |
-
## ⚙️ Customization
|
| 71 |
-
|
| 72 |
-
Edit timing in `demo.js`:
|
| 73 |
-
```javascript
|
| 74 |
-
const TYPING_DELAY = 70; // Speed of typing (ms)
|
| 75 |
-
const READ_DELAY = 2500; // Time to "read" responses
|
| 76 |
-
const SHORT_PAUSE = 1000; // Between actions
|
| 77 |
-
const LONG_PAUSE = 3500; // After important moments
|
| 78 |
-
```
|
| 79 |
-
|
| 80 |
-
## 🔧 Troubleshooting
|
| 81 |
-
|
| 82 |
-
**Browser doesn't open:**
|
| 83 |
-
- Install Chrome/Chromium: `npx puppeteer browsers install chrome`
|
| 84 |
-
|
| 85 |
-
**Selectors not found:**
|
| 86 |
-
- Check if UI changed: Update selectors in demo.js
|
| 87 |
-
- Add more wait time: Increase timeouts
|
| 88 |
-
|
| 89 |
-
**Too fast/slow:**
|
| 90 |
-
- Adjust timing constants at top of demo.js
|
| 91 |
-
|
| 92 |
-
**Want different case flow:**
|
| 93 |
-
- Edit the messages array in demo.js
|
| 94 |
-
- Change the sequence of actions
|
| 95 |
-
|
| 96 |
-
## 📂 Structure
|
| 97 |
-
|
| 98 |
-
```
|
| 99 |
-
demo-automation/ # Separate from main project
|
| 100 |
-
├── package.json # Dependencies
|
| 101 |
-
├── demo.js # Main demo script (uses /demo)
|
| 102 |
-
├── demo-leptospirosis.js # Alternative full simulation
|
| 103 |
-
└── README.md # This file
|
| 104 |
-
```
|
| 105 |
-
|
| 106 |
-
## 🚫 Not Included in Main Project
|
| 107 |
-
|
| 108 |
-
This folder is completely separate and can be:
|
| 109 |
-
- Deleted after hackathon
|
| 110 |
-
- Kept for future demos
|
| 111 |
-
- Not committed to main repo
|
| 112 |
-
|
| 113 |
-
The main Clinical Mind app works independently without this automation.
|
| 114 |
-
|
| 115 |
-
## 🏆 Tips for Recording
|
| 116 |
-
|
| 117 |
-
1. **Clean Desktop** - Hide personal files/apps
|
| 118 |
-
2. **Full Screen Browser** - F11 for professional look
|
| 119 |
-
3. **Good Internet** - For smooth API responses
|
| 120 |
-
4. **Multiple Takes** - Record 2-3 times, pick best
|
| 121 |
-
5. **Add Voiceover** - Explain features while it runs
|
| 122 |
-
|
| 123 |
-
## 📹 Recommended Recording Software
|
| 124 |
-
|
| 125 |
-
- **OBS Studio** (Free, all platforms)
|
| 126 |
-
- **QuickTime** (Mac built-in)
|
| 127 |
-
- **Windows Game Bar** (Win+G)
|
| 128 |
-
- **Loom** (Free tier available)
|
| 129 |
-
|
| 130 |
-
---
|
| 131 |
-
|
| 132 |
-
**Note:** This is for demo purposes only. Judges can test the real app at `localhost:3000/simulation`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
demo-automation/demo-debug.png
DELETED
|
Binary file (42.1 kB)
|
|
|
demo-automation/demo-leptospirosis.js
DELETED
|
@@ -1,258 +0,0 @@
|
|
| 1 |
-
/**
|
| 2 |
-
* Clinical Mind - Automated Demo Script
|
| 3 |
-
* Case: Leptospirosis (Weil's Disease)
|
| 4 |
-
*
|
| 5 |
-
* This script runs autonomously to demonstrate all features of Clinical Mind
|
| 6 |
-
* Perfect for hackathon presentations - consistent, professional, no fumbling
|
| 7 |
-
*/
|
| 8 |
-
|
| 9 |
-
const puppeteer = require('puppeteer');
|
| 10 |
-
|
| 11 |
-
// Timing constants (adjust for pacing)
|
| 12 |
-
const TYPING_DELAY = 80; // ms between keystrokes (looks natural)
|
| 13 |
-
const READ_DELAY = 3000; // Time to "read" responses
|
| 14 |
-
const SHORT_PAUSE = 1500; // Between actions
|
| 15 |
-
const LONG_PAUSE = 4000; // After important moments
|
| 16 |
-
|
| 17 |
-
async function sleep(ms) {
|
| 18 |
-
return new Promise(resolve => setTimeout(resolve, ms));
|
| 19 |
-
}
|
| 20 |
-
|
| 21 |
-
async function typeMessage(page, message) {
|
| 22 |
-
// Click the input field
|
| 23 |
-
await page.click('textarea[placeholder*="Type your message"]');
|
| 24 |
-
await sleep(500);
|
| 25 |
-
|
| 26 |
-
// Clear any existing text
|
| 27 |
-
await page.keyboard.down('Control');
|
| 28 |
-
await page.keyboard.press('A');
|
| 29 |
-
await page.keyboard.up('Control');
|
| 30 |
-
|
| 31 |
-
// Type the message with realistic speed
|
| 32 |
-
await page.type('textarea[placeholder*="Type your message"]', message, { delay: TYPING_DELAY });
|
| 33 |
-
await sleep(500);
|
| 34 |
-
|
| 35 |
-
// Press Enter to send
|
| 36 |
-
await page.keyboard.press('Enter');
|
| 37 |
-
}
|
| 38 |
-
|
| 39 |
-
async function waitForResponse(page, timeout = 30000) {
|
| 40 |
-
// Wait for loading to complete (no loading states visible)
|
| 41 |
-
await page.waitForFunction(
|
| 42 |
-
() => !document.querySelector('.animate-pulse'),
|
| 43 |
-
{ timeout }
|
| 44 |
-
);
|
| 45 |
-
await sleep(READ_DELAY);
|
| 46 |
-
}
|
| 47 |
-
|
| 48 |
-
async function scrollToBottom(page) {
|
| 49 |
-
await page.evaluate(() => {
|
| 50 |
-
const chatContainer = document.querySelector('[class*="overflow-y-auto"]');
|
| 51 |
-
if (chatContainer) {
|
| 52 |
-
chatContainer.scrollTop = chatContainer.scrollHeight;
|
| 53 |
-
}
|
| 54 |
-
});
|
| 55 |
-
}
|
| 56 |
-
|
| 57 |
-
async function clickActionButton(page, buttonText) {
|
| 58 |
-
// Find and click action button by text
|
| 59 |
-
await page.evaluate((text) => {
|
| 60 |
-
const buttons = Array.from(document.querySelectorAll('button'));
|
| 61 |
-
const button = buttons.find(btn => btn.textContent.includes(text));
|
| 62 |
-
if (button) button.click();
|
| 63 |
-
}, buttonText);
|
| 64 |
-
}
|
| 65 |
-
|
| 66 |
-
async function runDemo() {
|
| 67 |
-
console.log('🚀 Starting Clinical Mind Demo - Leptospirosis Case');
|
| 68 |
-
console.log('📹 Please start screen recording now...\n');
|
| 69 |
-
|
| 70 |
-
// Launch browser
|
| 71 |
-
const browser = await puppeteer.launch({
|
| 72 |
-
headless: false, // Shows the browser
|
| 73 |
-
defaultViewport: { width: 1920, height: 1080 },
|
| 74 |
-
args: [
|
| 75 |
-
'--window-size=1920,1080',
|
| 76 |
-
'--no-sandbox',
|
| 77 |
-
'--disable-setuid-sandbox',
|
| 78 |
-
'--disable-blink-features=AutomationControlled'
|
| 79 |
-
]
|
| 80 |
-
});
|
| 81 |
-
|
| 82 |
-
const page = await browser.newPage();
|
| 83 |
-
|
| 84 |
-
try {
|
| 85 |
-
// 1. Navigate to main page (NOT demo page - showing real app)
|
| 86 |
-
console.log('📍 Step 1: Opening Clinical Mind...');
|
| 87 |
-
await page.goto('http://localhost:3000', { waitUntil: 'networkidle2' });
|
| 88 |
-
await sleep(LONG_PAUSE);
|
| 89 |
-
|
| 90 |
-
// 2. Click "Start Simulation" on landing page
|
| 91 |
-
console.log('📍 Step 2: Starting simulation...');
|
| 92 |
-
await page.click('a[href="/simulation"]');
|
| 93 |
-
await page.waitForNavigation({ waitUntil: 'networkidle2' });
|
| 94 |
-
await sleep(SHORT_PAUSE);
|
| 95 |
-
|
| 96 |
-
// 3. Select difficulty level (Intermediate)
|
| 97 |
-
console.log('📍 Step 3: Selecting difficulty - Intermediate...');
|
| 98 |
-
await page.waitForSelector('button:has-text("Intermediate")', { timeout: 10000 });
|
| 99 |
-
await page.click('button:has-text("Intermediate")');
|
| 100 |
-
await sleep(SHORT_PAUSE);
|
| 101 |
-
|
| 102 |
-
// 4. Wait for case generation (shows loading state)
|
| 103 |
-
console.log('📍 Step 4: Generating case...');
|
| 104 |
-
await sleep(5000); // Generation time
|
| 105 |
-
|
| 106 |
-
// 5. Wait for agent initialization
|
| 107 |
-
console.log('📍 Step 5: Initializing medical team (this takes 2-3 minutes)...');
|
| 108 |
-
console.log(' - Building patient knowledge...');
|
| 109 |
-
console.log(' - Building nurse knowledge...');
|
| 110 |
-
console.log(' - Building family knowledge...');
|
| 111 |
-
console.log(' - Building lab tech knowledge...');
|
| 112 |
-
console.log(' - Building senior doctor knowledge...');
|
| 113 |
-
|
| 114 |
-
// Wait for chat interface to appear (agents ready)
|
| 115 |
-
await page.waitForSelector('textarea[placeholder*="Type your message"]', { timeout: 240000 });
|
| 116 |
-
console.log('✅ Medical team ready!\n');
|
| 117 |
-
await sleep(LONG_PAUSE);
|
| 118 |
-
|
| 119 |
-
// Scroll to see initial messages
|
| 120 |
-
await scrollToBottom(page);
|
| 121 |
-
await sleep(READ_DELAY);
|
| 122 |
-
|
| 123 |
-
// === DEMO CONVERSATION BEGINS ===
|
| 124 |
-
console.log('🎬 Starting medical consultation...\n');
|
| 125 |
-
|
| 126 |
-
// 6. Initial patient interaction
|
| 127 |
-
console.log('👨⚕️ Doctor: Asking about symptoms...');
|
| 128 |
-
await typeMessage(page, "Namaste, can you tell me what brought you to the hospital today?");
|
| 129 |
-
await waitForResponse(page);
|
| 130 |
-
await scrollToBottom(page);
|
| 131 |
-
await sleep(READ_DELAY);
|
| 132 |
-
|
| 133 |
-
// 7. Ask about fever pattern
|
| 134 |
-
console.log('👨⚕️ Doctor: Inquiring about fever...');
|
| 135 |
-
await typeMessage(page, "Tell me more about your fever. When did it start?");
|
| 136 |
-
await waitForResponse(page);
|
| 137 |
-
await scrollToBottom(page);
|
| 138 |
-
await sleep(READ_DELAY);
|
| 139 |
-
|
| 140 |
-
// 8. Check vitals
|
| 141 |
-
console.log('👨⚕️ Doctor: Checking vital signs...');
|
| 142 |
-
await clickActionButton(page, "Ask Nurse");
|
| 143 |
-
await sleep(SHORT_PAUSE);
|
| 144 |
-
await typeMessage(page, "Nurse Priya, what are the current vital signs?");
|
| 145 |
-
await waitForResponse(page);
|
| 146 |
-
await scrollToBottom(page);
|
| 147 |
-
await sleep(READ_DELAY);
|
| 148 |
-
|
| 149 |
-
// Show vitals panel changes (highlighting critical values)
|
| 150 |
-
console.log('📊 Vitals: BP 85/50 (LOW), HR 132 (HIGH), Temp 39.2°C');
|
| 151 |
-
await sleep(LONG_PAUSE);
|
| 152 |
-
|
| 153 |
-
// 9. Physical examination
|
| 154 |
-
console.log('👨⚕️ Doctor: Performing physical examination...');
|
| 155 |
-
await clickActionButton(page, "Examine Patient");
|
| 156 |
-
await sleep(SHORT_PAUSE);
|
| 157 |
-
await typeMessage(page, "Let me examine your abdomen for tenderness");
|
| 158 |
-
await waitForResponse(page);
|
| 159 |
-
await scrollToBottom(page);
|
| 160 |
-
|
| 161 |
-
// Examination modal should appear
|
| 162 |
-
await sleep(READ_DELAY);
|
| 163 |
-
|
| 164 |
-
// 10. Talk to family
|
| 165 |
-
console.log('👨⚕️ Doctor: Gathering history from family...');
|
| 166 |
-
await clickActionButton(page, "Talk to Family");
|
| 167 |
-
await sleep(SHORT_PAUSE);
|
| 168 |
-
await typeMessage(page, "Can you tell me about his work and recent activities?");
|
| 169 |
-
await waitForResponse(page);
|
| 170 |
-
await scrollToBottom(page);
|
| 171 |
-
await sleep(READ_DELAY);
|
| 172 |
-
|
| 173 |
-
// 11. Order investigations
|
| 174 |
-
console.log('👨⚕️ Doctor: Ordering blood tests...');
|
| 175 |
-
await clickActionButton(page, "Order Investigation");
|
| 176 |
-
await sleep(SHORT_PAUSE);
|
| 177 |
-
await typeMessage(page, "Order CBC, LFT, RFT, and Leptospira IgM ELISA urgently");
|
| 178 |
-
await waitForResponse(page);
|
| 179 |
-
await scrollToBottom(page);
|
| 180 |
-
await sleep(READ_DELAY);
|
| 181 |
-
|
| 182 |
-
// 12. Team huddle for differential diagnosis
|
| 183 |
-
console.log('👨⚕️ Doctor: Calling team huddle...');
|
| 184 |
-
await clickActionButton(page, "Team Huddle");
|
| 185 |
-
await sleep(SHORT_PAUSE);
|
| 186 |
-
await typeMessage(page, "Let's discuss the differential diagnosis. Patient has fever, jaundice, and kidney involvement.");
|
| 187 |
-
await waitForResponse(page);
|
| 188 |
-
await scrollToBottom(page);
|
| 189 |
-
await sleep(LONG_PAUSE);
|
| 190 |
-
|
| 191 |
-
// 13. Check investigation results (after time passes)
|
| 192 |
-
console.log('⏰ Waiting for lab results...');
|
| 193 |
-
await sleep(5000);
|
| 194 |
-
|
| 195 |
-
console.log('👨⚕️ Doctor: Checking lab results...');
|
| 196 |
-
await clickActionButton(page, "Ask Lab Tech");
|
| 197 |
-
await sleep(SHORT_PAUSE);
|
| 198 |
-
await typeMessage(page, "Ramesh, are the urgent lab results ready?");
|
| 199 |
-
await waitForResponse(page);
|
| 200 |
-
await scrollToBottom(page);
|
| 201 |
-
await sleep(READ_DELAY);
|
| 202 |
-
|
| 203 |
-
// 14. Start treatment
|
| 204 |
-
console.log('👨⚕️ Doctor: Initiating treatment...');
|
| 205 |
-
await clickActionButton(page, "Order Treatment");
|
| 206 |
-
await sleep(SHORT_PAUSE);
|
| 207 |
-
await typeMessage(page, "Start IV Crystalline Penicillin 1.5 MU Q6H and aggressive fluid resuscitation");
|
| 208 |
-
await waitForResponse(page);
|
| 209 |
-
await scrollToBottom(page);
|
| 210 |
-
await sleep(READ_DELAY);
|
| 211 |
-
|
| 212 |
-
// 15. Consult senior doctor for guidance
|
| 213 |
-
console.log('👨⚕️ Doctor: Consulting senior physician...');
|
| 214 |
-
await clickActionButton(page, "Consult Senior");
|
| 215 |
-
await sleep(SHORT_PAUSE);
|
| 216 |
-
await typeMessage(page, "Dr. Sharma, patient has confirmed leptospirosis with multi-organ involvement. What else should we monitor?");
|
| 217 |
-
await waitForResponse(page);
|
| 218 |
-
await scrollToBottom(page);
|
| 219 |
-
await sleep(LONG_PAUSE);
|
| 220 |
-
|
| 221 |
-
// 16. Show deterioration and urgency
|
| 222 |
-
console.log('⚠️ Patient deteriorating - demonstrating urgency features...');
|
| 223 |
-
await sleep(3000);
|
| 224 |
-
|
| 225 |
-
// 17. Final diagnosis
|
| 226 |
-
console.log('👨⚕️ Doctor: Confirming diagnosis...');
|
| 227 |
-
await typeMessage(page, "Based on clinical findings and lab results, diagnosis is Weil's disease - severe leptospirosis with hepatorenal syndrome");
|
| 228 |
-
await waitForResponse(page);
|
| 229 |
-
await scrollToBottom(page);
|
| 230 |
-
await sleep(LONG_PAUSE);
|
| 231 |
-
|
| 232 |
-
// === END OF DEMO ===
|
| 233 |
-
console.log('\n✅ Demo completed successfully!');
|
| 234 |
-
console.log('📹 You can stop recording now.');
|
| 235 |
-
console.log('\n🎯 Key Features Demonstrated:');
|
| 236 |
-
console.log(' ✓ Multi-agent interactions (5 agents)');
|
| 237 |
-
console.log(' ✓ Hinglish patient responses');
|
| 238 |
-
console.log(' ✓ Real-time vital signs monitoring');
|
| 239 |
-
console.log(' ✓ Physical examination system');
|
| 240 |
-
console.log(' ✓ Investigation ordering & results');
|
| 241 |
-
console.log(' ✓ Treatment management');
|
| 242 |
-
console.log(' ✓ Team collaboration (huddle)');
|
| 243 |
-
console.log(' ✓ Educational guidance from senior doctor');
|
| 244 |
-
console.log(' ✓ Patient deterioration mechanics');
|
| 245 |
-
console.log(' ✓ Context-aware suggested questions');
|
| 246 |
-
|
| 247 |
-
// Keep browser open for 10 seconds to show final state
|
| 248 |
-
await sleep(10000);
|
| 249 |
-
|
| 250 |
-
} catch (error) {
|
| 251 |
-
console.error('❌ Demo error:', error);
|
| 252 |
-
} finally {
|
| 253 |
-
await browser.close();
|
| 254 |
-
}
|
| 255 |
-
}
|
| 256 |
-
|
| 257 |
-
// Run the demo
|
| 258 |
-
runDemo().catch(console.error);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
demo-automation/demo.js
DELETED
|
@@ -1,532 +0,0 @@
|
|
| 1 |
-
/**
|
| 2 |
-
* Clinical Mind - Automated Demo Script (Medical Student Version)
|
| 3 |
-
*
|
| 4 |
-
* Showcases the educational medical simulation with 5 AI agents
|
| 5 |
-
* Perfect for hackathon recording - demonstrates multi-agent orchestration
|
| 6 |
-
*/
|
| 7 |
-
|
| 8 |
-
const puppeteer = require('puppeteer');
|
| 9 |
-
|
| 10 |
-
// Timing constants
|
| 11 |
-
const TYPING_DELAY = 70;
|
| 12 |
-
const READ_DELAY = 3000;
|
| 13 |
-
const SHORT_PAUSE = 1500;
|
| 14 |
-
const LONG_PAUSE = 4000;
|
| 15 |
-
|
| 16 |
-
async function sleep(ms) {
|
| 17 |
-
return new Promise(resolve => setTimeout(resolve, ms));
|
| 18 |
-
}
|
| 19 |
-
|
| 20 |
-
async function typeMessage(page, message) {
|
| 21 |
-
// Try multiple selectors for the input field
|
| 22 |
-
const inputSelectors = [
|
| 23 |
-
'input[type="text"][placeholder]',
|
| 24 |
-
'textarea[placeholder]',
|
| 25 |
-
'.flex-1.p-2\\.5.rounded-lg',
|
| 26 |
-
'input.flex-1',
|
| 27 |
-
'[role="textbox"]'
|
| 28 |
-
];
|
| 29 |
-
|
| 30 |
-
let inputFound = false;
|
| 31 |
-
let activeSelector = null;
|
| 32 |
-
|
| 33 |
-
// Find which selector works
|
| 34 |
-
for (const selector of inputSelectors) {
|
| 35 |
-
try {
|
| 36 |
-
await page.waitForSelector(selector, { timeout: 2000, visible: true });
|
| 37 |
-
const isVisible = await page.evaluate((sel) => {
|
| 38 |
-
const el = document.querySelector(sel);
|
| 39 |
-
return el && el.offsetParent !== null;
|
| 40 |
-
}, selector);
|
| 41 |
-
|
| 42 |
-
if (isVisible) {
|
| 43 |
-
activeSelector = selector;
|
| 44 |
-
inputFound = true;
|
| 45 |
-
break;
|
| 46 |
-
}
|
| 47 |
-
} catch {
|
| 48 |
-
continue;
|
| 49 |
-
}
|
| 50 |
-
}
|
| 51 |
-
|
| 52 |
-
if (!inputFound) {
|
| 53 |
-
console.log('⚠️ Could not find input field, skipping message');
|
| 54 |
-
return;
|
| 55 |
-
}
|
| 56 |
-
|
| 57 |
-
// Click to focus
|
| 58 |
-
await page.click(activeSelector);
|
| 59 |
-
await sleep(300);
|
| 60 |
-
|
| 61 |
-
// Clear any existing text
|
| 62 |
-
await page.evaluate((selector) => {
|
| 63 |
-
const input = document.querySelector(selector);
|
| 64 |
-
if (input) {
|
| 65 |
-
input.value = '';
|
| 66 |
-
input.textContent = '';
|
| 67 |
-
}
|
| 68 |
-
}, activeSelector);
|
| 69 |
-
|
| 70 |
-
// Type message
|
| 71 |
-
await page.type(activeSelector, message, { delay: TYPING_DELAY });
|
| 72 |
-
await sleep(300);
|
| 73 |
-
|
| 74 |
-
// Send message (try Enter, then look for Send button)
|
| 75 |
-
await page.keyboard.press('Enter');
|
| 76 |
-
|
| 77 |
-
// Alternative: click Send button if Enter doesn't work
|
| 78 |
-
const sendClicked = await page.evaluate(() => {
|
| 79 |
-
const buttons = Array.from(document.querySelectorAll('button'));
|
| 80 |
-
const sendBtn = buttons.find(btn =>
|
| 81 |
-
btn.textContent.toLowerCase() === 'send' &&
|
| 82 |
-
!btn.disabled
|
| 83 |
-
);
|
| 84 |
-
if (sendBtn) {
|
| 85 |
-
sendBtn.click();
|
| 86 |
-
return true;
|
| 87 |
-
}
|
| 88 |
-
return false;
|
| 89 |
-
});
|
| 90 |
-
|
| 91 |
-
if (sendClicked) {
|
| 92 |
-
console.log(' (Used Send button)');
|
| 93 |
-
}
|
| 94 |
-
}
|
| 95 |
-
|
| 96 |
-
async function waitForResponse(page, timeout = 30000) {
|
| 97 |
-
// Wait for typing indicator to disappear
|
| 98 |
-
try {
|
| 99 |
-
await page.waitForFunction(
|
| 100 |
-
() => {
|
| 101 |
-
const typingElements = document.querySelectorAll('[class*="typing"], [class*="loading"], .animate-pulse');
|
| 102 |
-
return typingElements.length === 0;
|
| 103 |
-
},
|
| 104 |
-
{ timeout }
|
| 105 |
-
);
|
| 106 |
-
} catch (e) {
|
| 107 |
-
console.log('Response timeout - continuing...');
|
| 108 |
-
}
|
| 109 |
-
await sleep(READ_DELAY);
|
| 110 |
-
}
|
| 111 |
-
|
| 112 |
-
async function scrollChat(page) {
|
| 113 |
-
await page.evaluate(() => {
|
| 114 |
-
const chatContainers = document.querySelectorAll('[class*="overflow-y-auto"]');
|
| 115 |
-
chatContainers.forEach(container => {
|
| 116 |
-
container.scrollTop = container.scrollHeight;
|
| 117 |
-
});
|
| 118 |
-
});
|
| 119 |
-
}
|
| 120 |
-
|
| 121 |
-
async function clickButton(page, buttonText) {
|
| 122 |
-
await page.evaluate((text) => {
|
| 123 |
-
const buttons = Array.from(document.querySelectorAll('button'));
|
| 124 |
-
const button = buttons.find(btn =>
|
| 125 |
-
btn.textContent.toLowerCase().includes(text.toLowerCase())
|
| 126 |
-
);
|
| 127 |
-
if (button) {
|
| 128 |
-
button.click();
|
| 129 |
-
return true;
|
| 130 |
-
}
|
| 131 |
-
return false;
|
| 132 |
-
}, buttonText);
|
| 133 |
-
}
|
| 134 |
-
|
| 135 |
-
async function clickActionTab(page, actionName) {
|
| 136 |
-
// Try to click the action tab/button
|
| 137 |
-
const clicked = await page.evaluate((name) => {
|
| 138 |
-
// First try exact match in small action buttons
|
| 139 |
-
const actionButtons = document.querySelectorAll('.flex.flex-wrap.gap-1 button');
|
| 140 |
-
for (const btn of actionButtons) {
|
| 141 |
-
if (btn.textContent.trim() === name || btn.textContent.includes(name)) {
|
| 142 |
-
btn.click();
|
| 143 |
-
console.log(`Clicked action tab: ${name}`);
|
| 144 |
-
return true;
|
| 145 |
-
}
|
| 146 |
-
}
|
| 147 |
-
|
| 148 |
-
// Then try any button with matching text
|
| 149 |
-
const allButtons = Array.from(document.querySelectorAll('button'));
|
| 150 |
-
const button = allButtons.find(btn =>
|
| 151 |
-
btn.textContent === name || btn.textContent.includes(name)
|
| 152 |
-
);
|
| 153 |
-
if (button) {
|
| 154 |
-
button.click();
|
| 155 |
-
console.log(`Clicked button: ${name}`);
|
| 156 |
-
return true;
|
| 157 |
-
}
|
| 158 |
-
|
| 159 |
-
console.log(`Could not find action: ${name}`);
|
| 160 |
-
return false;
|
| 161 |
-
}, actionName);
|
| 162 |
-
|
| 163 |
-
if (!clicked) {
|
| 164 |
-
console.log(`⚠️ Could not click action tab: ${actionName}`);
|
| 165 |
-
}
|
| 166 |
-
|
| 167 |
-
await sleep(SHORT_PAUSE);
|
| 168 |
-
}
|
| 169 |
-
|
| 170 |
-
async function runDemo() {
|
| 171 |
-
console.log('🚀 Starting Clinical Mind Automated Demo');
|
| 172 |
-
console.log('📹 Start your screen recording software now!');
|
| 173 |
-
console.log('⏰ Starting in 5 seconds...\n');
|
| 174 |
-
await sleep(5000);
|
| 175 |
-
|
| 176 |
-
let browser;
|
| 177 |
-
let retries = 3;
|
| 178 |
-
|
| 179 |
-
// Retry logic for browser launch
|
| 180 |
-
while (retries > 0) {
|
| 181 |
-
try {
|
| 182 |
-
browser = await puppeteer.launch({
|
| 183 |
-
headless: false,
|
| 184 |
-
defaultViewport: { width: 1920, height: 1080 },
|
| 185 |
-
args: [
|
| 186 |
-
'--window-size=1920,1080',
|
| 187 |
-
'--no-sandbox',
|
| 188 |
-
'--disable-setuid-sandbox',
|
| 189 |
-
'--disable-dev-shm-usage',
|
| 190 |
-
'--disable-accelerated-2d-canvas',
|
| 191 |
-
'--no-first-run',
|
| 192 |
-
'--no-zygote',
|
| 193 |
-
'--disable-gpu',
|
| 194 |
-
'--disable-web-security',
|
| 195 |
-
'--disable-features=IsolateOrigins,site-per-process'
|
| 196 |
-
],
|
| 197 |
-
ignoreHTTPSErrors: true,
|
| 198 |
-
dumpio: false,
|
| 199 |
-
timeout: 60000,
|
| 200 |
-
protocolTimeout: 60000
|
| 201 |
-
});
|
| 202 |
-
|
| 203 |
-
// If browser launched successfully, break the retry loop
|
| 204 |
-
console.log('✅ Browser launched successfully');
|
| 205 |
-
break;
|
| 206 |
-
} catch (error) {
|
| 207 |
-
retries--;
|
| 208 |
-
console.log(`⚠️ Browser launch failed. Retries remaining: ${retries}`);
|
| 209 |
-
if (retries === 0) {
|
| 210 |
-
throw new Error('Failed to launch browser after 3 attempts: ' + error.message);
|
| 211 |
-
}
|
| 212 |
-
// Wait before retrying
|
| 213 |
-
await sleep(2000);
|
| 214 |
-
}
|
| 215 |
-
}
|
| 216 |
-
|
| 217 |
-
const page = await browser.newPage();
|
| 218 |
-
|
| 219 |
-
try {
|
| 220 |
-
// 1. Navigate to demo page
|
| 221 |
-
console.log('📍 Opening Clinical Mind Demo...');
|
| 222 |
-
await page.goto('http://localhost:3000/demo', { waitUntil: 'networkidle2' });
|
| 223 |
-
await sleep(LONG_PAUSE);
|
| 224 |
-
|
| 225 |
-
// 2. Fill Student Profile
|
| 226 |
-
console.log('📍 Setting up medical student profile...');
|
| 227 |
-
|
| 228 |
-
// Enter student name
|
| 229 |
-
await page.waitForSelector('input[placeholder*="Enter your name"]', { timeout: 10000 });
|
| 230 |
-
await page.type('input[placeholder*="Enter your name"]', 'Arjun Sharma', { delay: TYPING_DELAY });
|
| 231 |
-
await sleep(SHORT_PAUSE);
|
| 232 |
-
|
| 233 |
-
// Select MBBS Final Year (advanced student)
|
| 234 |
-
console.log(' Selecting: MBBS Final Year');
|
| 235 |
-
await page.evaluate(() => {
|
| 236 |
-
const buttons = Array.from(document.querySelectorAll('button'));
|
| 237 |
-
const finalYearBtn = buttons.find(btn => btn.textContent.includes('MBBS Final Year'));
|
| 238 |
-
if (finalYearBtn) finalYearBtn.click();
|
| 239 |
-
});
|
| 240 |
-
await sleep(SHORT_PAUSE);
|
| 241 |
-
|
| 242 |
-
// Click Continue to Cases
|
| 243 |
-
await clickButton(page, 'Continue to Cases');
|
| 244 |
-
await sleep(LONG_PAUSE);
|
| 245 |
-
|
| 246 |
-
// 3. Select Case
|
| 247 |
-
console.log('📍 Selecting case: Dengue Fever (Infectious Disease)...');
|
| 248 |
-
await page.waitForSelector('.grid', { timeout: 10000 });
|
| 249 |
-
await sleep(SHORT_PAUSE); // Let the page stabilize
|
| 250 |
-
|
| 251 |
-
// Click on the "Start This Case" button in the second card
|
| 252 |
-
const caseSelected = await page.evaluate(() => {
|
| 253 |
-
const cards = document.querySelectorAll('[class*="Card"]');
|
| 254 |
-
console.log(`Found ${cards.length} case cards`);
|
| 255 |
-
|
| 256 |
-
if (cards.length >= 2) {
|
| 257 |
-
const secondCard = cards[1];
|
| 258 |
-
// Look for the "Start This Case" button within the card
|
| 259 |
-
const button = secondCard.querySelector('button');
|
| 260 |
-
if (button && button.textContent.includes('Start This Case')) {
|
| 261 |
-
console.log('Clicking "Start This Case" button');
|
| 262 |
-
button.click();
|
| 263 |
-
return true;
|
| 264 |
-
} else {
|
| 265 |
-
// Fallback: click the card itself
|
| 266 |
-
console.log('Clicking card directly');
|
| 267 |
-
secondCard.click();
|
| 268 |
-
return true;
|
| 269 |
-
}
|
| 270 |
-
}
|
| 271 |
-
return false;
|
| 272 |
-
});
|
| 273 |
-
|
| 274 |
-
if (!caseSelected) {
|
| 275 |
-
console.log('⚠️ Could not find case cards, trying alternative selector...');
|
| 276 |
-
// Alternative: click by text content
|
| 277 |
-
await clickButton(page, 'Start This Case');
|
| 278 |
-
}
|
| 279 |
-
|
| 280 |
-
// 4. Wait for navigation to case interface
|
| 281 |
-
console.log('📍 Loading case interface...');
|
| 282 |
-
|
| 283 |
-
// Wait for URL change or new page content
|
| 284 |
-
await Promise.race([
|
| 285 |
-
page.waitForNavigation({ waitUntil: 'networkidle0', timeout: 30000 }),
|
| 286 |
-
page.waitForSelector('[class*="Hospital Ward"]', { timeout: 30000 }),
|
| 287 |
-
sleep(5000) // Fallback timeout
|
| 288 |
-
]).catch(() => {
|
| 289 |
-
console.log('Navigation completed or timed out, continuing...');
|
| 290 |
-
});
|
| 291 |
-
|
| 292 |
-
await sleep(LONG_PAUSE);
|
| 293 |
-
|
| 294 |
-
// 5. Wait for agents to initialize
|
| 295 |
-
console.log('⏳ Initializing medical team (2-3 minutes)...');
|
| 296 |
-
console.log(' 🏥 5 AI agents are learning about this case:');
|
| 297 |
-
console.log(' - Patient (with symptoms)');
|
| 298 |
-
console.log(' - Family member (Hindi/English responses)');
|
| 299 |
-
console.log(' - Nurse Priya (vitals monitoring)');
|
| 300 |
-
console.log(' - Lab Tech Ramesh (investigations)');
|
| 301 |
-
console.log(' - Dr. Sharma (senior guidance)');
|
| 302 |
-
|
| 303 |
-
// Wait for initialization to complete (checking multiple indicators)
|
| 304 |
-
console.log(' Waiting for agents to be ready...');
|
| 305 |
-
|
| 306 |
-
// First check if there's an initialization overlay
|
| 307 |
-
const hasInitOverlay = await page.evaluate(() => {
|
| 308 |
-
const overlay = document.querySelector('.absolute.inset-0.bg-cream-white');
|
| 309 |
-
const loadingText = document.querySelector('[class*="Preparing Hospital Ward"]');
|
| 310 |
-
return !!(overlay || loadingText);
|
| 311 |
-
});
|
| 312 |
-
|
| 313 |
-
if (hasInitOverlay) {
|
| 314 |
-
console.log(' Initialization overlay detected, waiting for completion...');
|
| 315 |
-
// Wait for the overlay to disappear
|
| 316 |
-
await page.waitForFunction(
|
| 317 |
-
() => {
|
| 318 |
-
const loadingOverlay = document.querySelector('[class*="Preparing Hospital Ward"]');
|
| 319 |
-
const initOverlay = document.querySelector('.absolute.inset-0.bg-cream-white');
|
| 320 |
-
const spinners = document.querySelectorAll('.animate-pulse, .animate-spin');
|
| 321 |
-
return !loadingOverlay && !initOverlay && spinners.length === 0;
|
| 322 |
-
},
|
| 323 |
-
{ timeout: 240000 } // 4 minutes max
|
| 324 |
-
).catch(() => {
|
| 325 |
-
console.log(' Initialization timeout, proceeding anyway...');
|
| 326 |
-
});
|
| 327 |
-
} else {
|
| 328 |
-
console.log(' No initialization overlay, agents might be pre-loaded for demo');
|
| 329 |
-
await sleep(5000); // Give it some time anyway
|
| 330 |
-
}
|
| 331 |
-
|
| 332 |
-
// Wait for chat input to be ready (with multiple selectors)
|
| 333 |
-
console.log(' Looking for chat interface...');
|
| 334 |
-
const inputFound = await Promise.race([
|
| 335 |
-
page.waitForSelector('input[type="text"][placeholder]', {
|
| 336 |
-
visible: true,
|
| 337 |
-
timeout: 30000
|
| 338 |
-
}).then(() => true),
|
| 339 |
-
page.waitForSelector('textarea[placeholder]', {
|
| 340 |
-
visible: true,
|
| 341 |
-
timeout: 30000
|
| 342 |
-
}).then(() => true),
|
| 343 |
-
page.waitForSelector('.flex-1.p-2\\.5.rounded-lg', {
|
| 344 |
-
visible: true,
|
| 345 |
-
timeout: 30000
|
| 346 |
-
}).then(() => true)
|
| 347 |
-
]).catch(() => false);
|
| 348 |
-
|
| 349 |
-
if (!inputFound) {
|
| 350 |
-
console.log('⚠️ Chat input not found, but continuing with demo...');
|
| 351 |
-
// Take a screenshot to debug
|
| 352 |
-
await page.screenshot({ path: 'demo-debug.png' });
|
| 353 |
-
console.log(' Screenshot saved as demo-debug.png');
|
| 354 |
-
}
|
| 355 |
-
|
| 356 |
-
console.log('✅ Medical team ready!\n');
|
| 357 |
-
await sleep(LONG_PAUSE);
|
| 358 |
-
await scrollChat(page);
|
| 359 |
-
|
| 360 |
-
// === MEDICAL STUDENT CONSULTATION FLOW ===
|
| 361 |
-
console.log('🎬 Beginning medical consultation as MBBS student...\n');
|
| 362 |
-
|
| 363 |
-
// 1. Initial greeting to patient
|
| 364 |
-
console.log('🧑🎓 [1/18] Greeting patient...');
|
| 365 |
-
await clickActionTab(page, 'Patient');
|
| 366 |
-
await typeMessage(page, "Hello, I'm Arjun, a final year medical student. What brought you to the hospital today?");
|
| 367 |
-
await waitForResponse(page);
|
| 368 |
-
await scrollChat(page);
|
| 369 |
-
|
| 370 |
-
// 2. History taking
|
| 371 |
-
console.log('🧑🎓 [2/18] Taking detailed history...');
|
| 372 |
-
await typeMessage(page, "When did the fever start? Any other symptoms like headache or body pain?");
|
| 373 |
-
await waitForResponse(page);
|
| 374 |
-
await scrollChat(page);
|
| 375 |
-
|
| 376 |
-
// 3. Ask about rash
|
| 377 |
-
console.log('🧑🎓 [3/18] Checking for specific symptoms...');
|
| 378 |
-
await typeMessage(page, "Have you noticed any rash on your body? Any bleeding from gums or nose?");
|
| 379 |
-
await waitForResponse(page);
|
| 380 |
-
await scrollChat(page);
|
| 381 |
-
|
| 382 |
-
// 4. Talk to family for context
|
| 383 |
-
console.log('🧑🎓 [4/18] Getting history from family...');
|
| 384 |
-
await clickActionTab(page, 'Family');
|
| 385 |
-
await typeMessage(page, "Can you tell me about the patient's symptoms over the past few days?");
|
| 386 |
-
await waitForResponse(page);
|
| 387 |
-
await scrollChat(page);
|
| 388 |
-
|
| 389 |
-
// 5. Check vitals with nurse
|
| 390 |
-
console.log('🧑🎓 [5/18] Checking vital signs...');
|
| 391 |
-
await clickActionTab(page, 'Nurse');
|
| 392 |
-
await typeMessage(page, "Nurse Priya, can you please report the current vital signs?");
|
| 393 |
-
await waitForResponse(page);
|
| 394 |
-
await scrollChat(page);
|
| 395 |
-
|
| 396 |
-
console.log(' 📊 Analyzing vitals...');
|
| 397 |
-
await sleep(SHORT_PAUSE);
|
| 398 |
-
|
| 399 |
-
// 6. Consult senior for guidance
|
| 400 |
-
console.log('🧑🎓 [6/18] Consulting senior doctor...');
|
| 401 |
-
await clickActionTab(page, 'Dr. Sharma');
|
| 402 |
-
await typeMessage(page, "Dr. Sharma, patient has high fever with body aches for 4 days. What should I look for?");
|
| 403 |
-
await waitForResponse(page);
|
| 404 |
-
await scrollChat(page);
|
| 405 |
-
|
| 406 |
-
// 7. Physical examination
|
| 407 |
-
console.log('🧑🎓 [7/18] Performing physical examination...');
|
| 408 |
-
await clickActionTab(page, 'Examine');
|
| 409 |
-
await typeMessage(page, "I want to examine for petechial rash and check tourniquet test");
|
| 410 |
-
await waitForResponse(page);
|
| 411 |
-
await scrollChat(page);
|
| 412 |
-
|
| 413 |
-
// 8. Order basic investigations
|
| 414 |
-
console.log('🧑🎓 [8/18] Ordering investigations...');
|
| 415 |
-
await clickActionTab(page, 'Investigate');
|
| 416 |
-
await typeMessage(page, "Please order CBC with platelet count, NS1 antigen test, and dengue serology");
|
| 417 |
-
await waitForResponse(page);
|
| 418 |
-
await scrollChat(page);
|
| 419 |
-
|
| 420 |
-
// 9. Team huddle for differential
|
| 421 |
-
console.log('🧑🎓 [9/18] Team discussion...');
|
| 422 |
-
await clickActionTab(page, 'Huddle');
|
| 423 |
-
await typeMessage(page, "Team, let's discuss the differential diagnosis. Could this be dengue fever?");
|
| 424 |
-
await waitForResponse(page);
|
| 425 |
-
await scrollChat(page);
|
| 426 |
-
|
| 427 |
-
// 10. Check investigation status
|
| 428 |
-
console.log('🧑🎓 [10/18] Checking lab results...');
|
| 429 |
-
await clickActionTab(page, 'Lab');
|
| 430 |
-
await typeMessage(page, "Ramesh, are the CBC and dengue test results ready?");
|
| 431 |
-
await waitForResponse(page);
|
| 432 |
-
await scrollChat(page);
|
| 433 |
-
|
| 434 |
-
// 11. Monitor patient condition
|
| 435 |
-
console.log('🧑🎓 [11/18] Monitoring patient...');
|
| 436 |
-
await clickActionTab(page, 'Nurse');
|
| 437 |
-
await typeMessage(page, "Please monitor urine output and watch for warning signs of dengue");
|
| 438 |
-
await waitForResponse(page);
|
| 439 |
-
await scrollChat(page);
|
| 440 |
-
|
| 441 |
-
// 12. Start treatment
|
| 442 |
-
console.log('🧑🎓 [12/18] Initiating treatment...');
|
| 443 |
-
await clickActionTab(page, 'Treat');
|
| 444 |
-
await typeMessage(page, "Start IV fluids - NS 500ml over 4 hours, and paracetamol for fever");
|
| 445 |
-
await waitForResponse(page);
|
| 446 |
-
await scrollChat(page);
|
| 447 |
-
|
| 448 |
-
// 13. Reassess with patient
|
| 449 |
-
console.log('🧑🎓 [13/18] Reassessing patient...');
|
| 450 |
-
await clickActionTab(page, 'Patient');
|
| 451 |
-
await typeMessage(page, "How are you feeling now? Any abdominal pain or vomiting?");
|
| 452 |
-
await waitForResponse(page);
|
| 453 |
-
await scrollChat(page);
|
| 454 |
-
|
| 455 |
-
// 14. Check vitals trend
|
| 456 |
-
console.log('🧑🎓 [14/18] Checking vitals trend...');
|
| 457 |
-
await clickActionTab(page, 'Nurse');
|
| 458 |
-
await typeMessage(page, "What's the trend of blood pressure and platelet count?");
|
| 459 |
-
await waitForResponse(page);
|
| 460 |
-
await scrollChat(page);
|
| 461 |
-
|
| 462 |
-
// 15. Discuss management with senior
|
| 463 |
-
console.log('🧑🎓 [15/18] Discussing management plan...');
|
| 464 |
-
await clickActionTab(page, 'Dr. Sharma');
|
| 465 |
-
await typeMessage(page, "Dr. Sharma, platelets are dropping. Should we admit for monitoring?");
|
| 466 |
-
await waitForResponse(page);
|
| 467 |
-
await scrollChat(page);
|
| 468 |
-
|
| 469 |
-
// 16. Patient education
|
| 470 |
-
console.log('🧑🎓 [16/18] Educating patient...');
|
| 471 |
-
await clickActionTab(page, 'Patient');
|
| 472 |
-
await typeMessage(page, "You have dengue fever. We'll monitor you closely. Stay hydrated and rest.");
|
| 473 |
-
await waitForResponse(page);
|
| 474 |
-
await scrollChat(page);
|
| 475 |
-
|
| 476 |
-
// 17. Family counseling
|
| 477 |
-
console.log('🧑🎓 [17/18] Counseling family...');
|
| 478 |
-
await clickActionTab(page, 'Family');
|
| 479 |
-
await typeMessage(page, "Please ensure mosquito protection at home. Bring patient back if warning signs appear.");
|
| 480 |
-
await waitForResponse(page);
|
| 481 |
-
await scrollChat(page);
|
| 482 |
-
|
| 483 |
-
// 18. Final assessment
|
| 484 |
-
console.log('🧑🎓 [18/18] Final clinical reasoning...');
|
| 485 |
-
await clickActionTab(page, 'Dr. Sharma');
|
| 486 |
-
await typeMessage(page, "Based on clinical findings and low platelets, diagnosis is dengue fever with warning signs");
|
| 487 |
-
await waitForResponse(page);
|
| 488 |
-
await scrollChat(page);
|
| 489 |
-
|
| 490 |
-
console.log('\n✅ Demo completed successfully!');
|
| 491 |
-
console.log('📹 Recording complete - you can stop now.\n');
|
| 492 |
-
|
| 493 |
-
console.log('🎯 Features Demonstrated:');
|
| 494 |
-
console.log(' ✓ Student profile & level selection');
|
| 495 |
-
console.log(' ✓ 5 AI agents with specialized roles');
|
| 496 |
-
console.log(' ✓ Authentic Hindi/English patient responses');
|
| 497 |
-
console.log(' ✓ Real-time vital signs monitoring');
|
| 498 |
-
console.log(' ✓ Complete clinical workflow');
|
| 499 |
-
console.log(' ✓ Educational guidance from senior doctor');
|
| 500 |
-
console.log(' ✓ Clinical reasoning & critical thinking');
|
| 501 |
-
console.log(' ✓ Multi-agent orchestration');
|
| 502 |
-
console.log(' ✓ Investigation & treatment management');
|
| 503 |
-
console.log(' ✓ Patient & family counseling');
|
| 504 |
-
|
| 505 |
-
// Keep browser open
|
| 506 |
-
await sleep(10000);
|
| 507 |
-
|
| 508 |
-
} catch (error) {
|
| 509 |
-
console.error('❌ Error during demo:', error.message);
|
| 510 |
-
console.log('💡 Tips:');
|
| 511 |
-
console.log(' 1. Make sure the app is running on localhost:3000');
|
| 512 |
-
console.log(' 2. Check that /demo page is accessible');
|
| 513 |
-
console.log(' 3. Ensure all components are loaded');
|
| 514 |
-
} finally {
|
| 515 |
-
console.log('\n🔚 Closing browser...');
|
| 516 |
-
await browser.close();
|
| 517 |
-
}
|
| 518 |
-
}
|
| 519 |
-
|
| 520 |
-
// Run demo with better error handling
|
| 521 |
-
runDemo().catch((error) => {
|
| 522 |
-
console.error('❌ Error during demo:', error.message);
|
| 523 |
-
if (error.message.includes('WebSocket') || error.message.includes('socket hang up')) {
|
| 524 |
-
console.log('\n💡 WebSocket Connection Error - Troubleshooting tips:');
|
| 525 |
-
console.log(' 1. Try running the demo again (WebSocket errors are often temporary)');
|
| 526 |
-
console.log(' 2. Make sure no other Chrome/Chromium processes are running');
|
| 527 |
-
console.log(' 3. Kill any zombie Chrome processes: killall "Google Chrome"');
|
| 528 |
-
console.log(' 4. Clear Puppeteer cache: rm -rf ~/.cache/puppeteer');
|
| 529 |
-
console.log(' 5. Re-run setup: ./setup.sh');
|
| 530 |
-
}
|
| 531 |
-
process.exit(1);
|
| 532 |
-
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
demo-automation/fix-chrome.sh
DELETED
|
@@ -1,38 +0,0 @@
|
|
| 1 |
-
#!/bin/bash
|
| 2 |
-
|
| 3 |
-
echo "🔧 Chrome/Puppeteer Fix Script"
|
| 4 |
-
echo "================================"
|
| 5 |
-
|
| 6 |
-
# Kill any existing Chrome processes
|
| 7 |
-
echo "📍 Killing any existing Chrome processes..."
|
| 8 |
-
pkill -f "Google Chrome"
|
| 9 |
-
pkill -f "chrome"
|
| 10 |
-
pkill -f "Chromium"
|
| 11 |
-
sleep 1
|
| 12 |
-
|
| 13 |
-
# Check if processes are killed
|
| 14 |
-
if pgrep -f "Chrome" > /dev/null; then
|
| 15 |
-
echo "⚠️ Some Chrome processes still running. Using force kill..."
|
| 16 |
-
pkill -9 -f "Chrome"
|
| 17 |
-
sleep 1
|
| 18 |
-
fi
|
| 19 |
-
|
| 20 |
-
# Clear Puppeteer cache
|
| 21 |
-
echo "📍 Clearing Puppeteer cache..."
|
| 22 |
-
rm -rf ~/.cache/puppeteer
|
| 23 |
-
|
| 24 |
-
# Reinstall Puppeteer browser
|
| 25 |
-
echo "📍 Reinstalling Puppeteer browser..."
|
| 26 |
-
cd "$(dirname "$0")"
|
| 27 |
-
npx puppeteer browsers install chrome
|
| 28 |
-
|
| 29 |
-
echo ""
|
| 30 |
-
echo "✅ Chrome fix complete!"
|
| 31 |
-
echo ""
|
| 32 |
-
echo "📝 Now try running the demo again:"
|
| 33 |
-
echo " npm run demo"
|
| 34 |
-
echo ""
|
| 35 |
-
echo "💡 Additional tips if issues persist:"
|
| 36 |
-
echo " - Close all Chrome browser windows manually"
|
| 37 |
-
echo " - Restart your terminal"
|
| 38 |
-
echo " - Run: npm install puppeteer@latest"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
demo-automation/package-lock.json
DELETED
|
@@ -1,1128 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"name": "clinical-mind-demo",
|
| 3 |
-
"version": "1.0.0",
|
| 4 |
-
"lockfileVersion": 3,
|
| 5 |
-
"requires": true,
|
| 6 |
-
"packages": {
|
| 7 |
-
"": {
|
| 8 |
-
"name": "clinical-mind-demo",
|
| 9 |
-
"version": "1.0.0",
|
| 10 |
-
"dependencies": {
|
| 11 |
-
"puppeteer": "^24.37.3"
|
| 12 |
-
},
|
| 13 |
-
"devDependencies": {}
|
| 14 |
-
},
|
| 15 |
-
"node_modules/@puppeteer/browsers": {
|
| 16 |
-
"version": "2.12.1",
|
| 17 |
-
"resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.12.1.tgz",
|
| 18 |
-
"integrity": "sha512-fXa6uXLxfslBlus3MEpW8S6S9fe5RwmAE5Gd8u3krqOwnkZJV3/lQJiY3LaFdTctLLqJtyMgEUGkbDnRNf6vbQ==",
|
| 19 |
-
"license": "Apache-2.0",
|
| 20 |
-
"dependencies": {
|
| 21 |
-
"debug": "^4.4.3",
|
| 22 |
-
"extract-zip": "^2.0.1",
|
| 23 |
-
"progress": "^2.0.3",
|
| 24 |
-
"proxy-agent": "^6.5.0",
|
| 25 |
-
"semver": "^7.7.4",
|
| 26 |
-
"tar-fs": "^3.1.1",
|
| 27 |
-
"yargs": "^17.7.2"
|
| 28 |
-
},
|
| 29 |
-
"bin": {
|
| 30 |
-
"browsers": "lib/cjs/main-cli.js"
|
| 31 |
-
},
|
| 32 |
-
"engines": {
|
| 33 |
-
"node": ">=18"
|
| 34 |
-
}
|
| 35 |
-
},
|
| 36 |
-
"node_modules/@tootallnate/quickjs-emscripten": {
|
| 37 |
-
"version": "0.23.0",
|
| 38 |
-
"resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
|
| 39 |
-
"integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==",
|
| 40 |
-
"license": "MIT"
|
| 41 |
-
},
|
| 42 |
-
"node_modules/@types/node": {
|
| 43 |
-
"version": "25.2.3",
|
| 44 |
-
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.3.tgz",
|
| 45 |
-
"integrity": "sha512-m0jEgYlYz+mDJZ2+F4v8D1AyQb+QzsNqRuI7xg1VQX/KlKS0qT9r1Mo16yo5F/MtifXFgaofIFsdFMox2SxIbQ==",
|
| 46 |
-
"license": "MIT",
|
| 47 |
-
"optional": true,
|
| 48 |
-
"dependencies": {
|
| 49 |
-
"undici-types": "~7.16.0"
|
| 50 |
-
}
|
| 51 |
-
},
|
| 52 |
-
"node_modules/@types/yauzl": {
|
| 53 |
-
"version": "2.10.3",
|
| 54 |
-
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
|
| 55 |
-
"integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
|
| 56 |
-
"license": "MIT",
|
| 57 |
-
"optional": true,
|
| 58 |
-
"dependencies": {
|
| 59 |
-
"@types/node": "*"
|
| 60 |
-
}
|
| 61 |
-
},
|
| 62 |
-
"node_modules/agent-base": {
|
| 63 |
-
"version": "7.1.4",
|
| 64 |
-
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
|
| 65 |
-
"integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
|
| 66 |
-
"license": "MIT",
|
| 67 |
-
"engines": {
|
| 68 |
-
"node": ">= 14"
|
| 69 |
-
}
|
| 70 |
-
},
|
| 71 |
-
"node_modules/ansi-regex": {
|
| 72 |
-
"version": "5.0.1",
|
| 73 |
-
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
| 74 |
-
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
| 75 |
-
"license": "MIT",
|
| 76 |
-
"engines": {
|
| 77 |
-
"node": ">=8"
|
| 78 |
-
}
|
| 79 |
-
},
|
| 80 |
-
"node_modules/ansi-styles": {
|
| 81 |
-
"version": "4.3.0",
|
| 82 |
-
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
| 83 |
-
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
| 84 |
-
"license": "MIT",
|
| 85 |
-
"dependencies": {
|
| 86 |
-
"color-convert": "^2.0.1"
|
| 87 |
-
},
|
| 88 |
-
"engines": {
|
| 89 |
-
"node": ">=8"
|
| 90 |
-
},
|
| 91 |
-
"funding": {
|
| 92 |
-
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
| 93 |
-
}
|
| 94 |
-
},
|
| 95 |
-
"node_modules/argparse": {
|
| 96 |
-
"version": "2.0.1",
|
| 97 |
-
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
| 98 |
-
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
| 99 |
-
"license": "Python-2.0"
|
| 100 |
-
},
|
| 101 |
-
"node_modules/ast-types": {
|
| 102 |
-
"version": "0.13.4",
|
| 103 |
-
"resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
|
| 104 |
-
"integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==",
|
| 105 |
-
"license": "MIT",
|
| 106 |
-
"dependencies": {
|
| 107 |
-
"tslib": "^2.0.1"
|
| 108 |
-
},
|
| 109 |
-
"engines": {
|
| 110 |
-
"node": ">=4"
|
| 111 |
-
}
|
| 112 |
-
},
|
| 113 |
-
"node_modules/b4a": {
|
| 114 |
-
"version": "1.7.4",
|
| 115 |
-
"resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.4.tgz",
|
| 116 |
-
"integrity": "sha512-u20zJLDaSWpxaZ+zaAkEIB2dZZ1o+DF4T/MRbmsvGp9nletHOyiai19OzX1fF8xUBYsO1bPXxODvcd0978pnug==",
|
| 117 |
-
"license": "Apache-2.0",
|
| 118 |
-
"peerDependencies": {
|
| 119 |
-
"react-native-b4a": "*"
|
| 120 |
-
},
|
| 121 |
-
"peerDependenciesMeta": {
|
| 122 |
-
"react-native-b4a": {
|
| 123 |
-
"optional": true
|
| 124 |
-
}
|
| 125 |
-
}
|
| 126 |
-
},
|
| 127 |
-
"node_modules/bare-events": {
|
| 128 |
-
"version": "2.8.2",
|
| 129 |
-
"resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz",
|
| 130 |
-
"integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==",
|
| 131 |
-
"license": "Apache-2.0",
|
| 132 |
-
"peerDependencies": {
|
| 133 |
-
"bare-abort-controller": "*"
|
| 134 |
-
},
|
| 135 |
-
"peerDependenciesMeta": {
|
| 136 |
-
"bare-abort-controller": {
|
| 137 |
-
"optional": true
|
| 138 |
-
}
|
| 139 |
-
}
|
| 140 |
-
},
|
| 141 |
-
"node_modules/bare-fs": {
|
| 142 |
-
"version": "4.5.4",
|
| 143 |
-
"resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.5.4.tgz",
|
| 144 |
-
"integrity": "sha512-POK4oplfA7P7gqvetNmCs4CNtm9fNsx+IAh7jH7GgU0OJdge2rso0R20TNWVq6VoWcCvsTdlNDaleLHGaKx8CA==",
|
| 145 |
-
"license": "Apache-2.0",
|
| 146 |
-
"optional": true,
|
| 147 |
-
"dependencies": {
|
| 148 |
-
"bare-events": "^2.5.4",
|
| 149 |
-
"bare-path": "^3.0.0",
|
| 150 |
-
"bare-stream": "^2.6.4",
|
| 151 |
-
"bare-url": "^2.2.2",
|
| 152 |
-
"fast-fifo": "^1.3.2"
|
| 153 |
-
},
|
| 154 |
-
"engines": {
|
| 155 |
-
"bare": ">=1.16.0"
|
| 156 |
-
},
|
| 157 |
-
"peerDependencies": {
|
| 158 |
-
"bare-buffer": "*"
|
| 159 |
-
},
|
| 160 |
-
"peerDependenciesMeta": {
|
| 161 |
-
"bare-buffer": {
|
| 162 |
-
"optional": true
|
| 163 |
-
}
|
| 164 |
-
}
|
| 165 |
-
},
|
| 166 |
-
"node_modules/bare-os": {
|
| 167 |
-
"version": "3.6.2",
|
| 168 |
-
"resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.2.tgz",
|
| 169 |
-
"integrity": "sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A==",
|
| 170 |
-
"license": "Apache-2.0",
|
| 171 |
-
"optional": true,
|
| 172 |
-
"engines": {
|
| 173 |
-
"bare": ">=1.14.0"
|
| 174 |
-
}
|
| 175 |
-
},
|
| 176 |
-
"node_modules/bare-path": {
|
| 177 |
-
"version": "3.0.0",
|
| 178 |
-
"resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz",
|
| 179 |
-
"integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==",
|
| 180 |
-
"license": "Apache-2.0",
|
| 181 |
-
"optional": true,
|
| 182 |
-
"dependencies": {
|
| 183 |
-
"bare-os": "^3.0.1"
|
| 184 |
-
}
|
| 185 |
-
},
|
| 186 |
-
"node_modules/bare-stream": {
|
| 187 |
-
"version": "2.7.0",
|
| 188 |
-
"resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.7.0.tgz",
|
| 189 |
-
"integrity": "sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A==",
|
| 190 |
-
"license": "Apache-2.0",
|
| 191 |
-
"optional": true,
|
| 192 |
-
"dependencies": {
|
| 193 |
-
"streamx": "^2.21.0"
|
| 194 |
-
},
|
| 195 |
-
"peerDependencies": {
|
| 196 |
-
"bare-buffer": "*",
|
| 197 |
-
"bare-events": "*"
|
| 198 |
-
},
|
| 199 |
-
"peerDependenciesMeta": {
|
| 200 |
-
"bare-buffer": {
|
| 201 |
-
"optional": true
|
| 202 |
-
},
|
| 203 |
-
"bare-events": {
|
| 204 |
-
"optional": true
|
| 205 |
-
}
|
| 206 |
-
}
|
| 207 |
-
},
|
| 208 |
-
"node_modules/bare-url": {
|
| 209 |
-
"version": "2.3.2",
|
| 210 |
-
"resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.3.2.tgz",
|
| 211 |
-
"integrity": "sha512-ZMq4gd9ngV5aTMa5p9+UfY0b3skwhHELaDkhEHetMdX0LRkW9kzaym4oo/Eh+Ghm0CCDuMTsRIGM/ytUc1ZYmw==",
|
| 212 |
-
"license": "Apache-2.0",
|
| 213 |
-
"optional": true,
|
| 214 |
-
"dependencies": {
|
| 215 |
-
"bare-path": "^3.0.0"
|
| 216 |
-
}
|
| 217 |
-
},
|
| 218 |
-
"node_modules/basic-ftp": {
|
| 219 |
-
"version": "5.1.0",
|
| 220 |
-
"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.1.0.tgz",
|
| 221 |
-
"integrity": "sha512-RkaJzeJKDbaDWTIPiJwubyljaEPwpVWkm9Rt5h9Nd6h7tEXTJ3VB4qxdZBioV7JO5yLUaOKwz7vDOzlncUsegw==",
|
| 222 |
-
"license": "MIT",
|
| 223 |
-
"engines": {
|
| 224 |
-
"node": ">=10.0.0"
|
| 225 |
-
}
|
| 226 |
-
},
|
| 227 |
-
"node_modules/buffer-crc32": {
|
| 228 |
-
"version": "0.2.13",
|
| 229 |
-
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
|
| 230 |
-
"integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
|
| 231 |
-
"license": "MIT",
|
| 232 |
-
"engines": {
|
| 233 |
-
"node": "*"
|
| 234 |
-
}
|
| 235 |
-
},
|
| 236 |
-
"node_modules/callsites": {
|
| 237 |
-
"version": "3.1.0",
|
| 238 |
-
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
| 239 |
-
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
|
| 240 |
-
"license": "MIT",
|
| 241 |
-
"engines": {
|
| 242 |
-
"node": ">=6"
|
| 243 |
-
}
|
| 244 |
-
},
|
| 245 |
-
"node_modules/chromium-bidi": {
|
| 246 |
-
"version": "14.0.0",
|
| 247 |
-
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-14.0.0.tgz",
|
| 248 |
-
"integrity": "sha512-9gYlLtS6tStdRWzrtXaTMnqcM4dudNegMXJxkR0I/CXObHalYeYcAMPrL19eroNZHtJ8DQmu1E+ZNOYu/IXMXw==",
|
| 249 |
-
"license": "Apache-2.0",
|
| 250 |
-
"dependencies": {
|
| 251 |
-
"mitt": "^3.0.1",
|
| 252 |
-
"zod": "^3.24.1"
|
| 253 |
-
},
|
| 254 |
-
"peerDependencies": {
|
| 255 |
-
"devtools-protocol": "*"
|
| 256 |
-
}
|
| 257 |
-
},
|
| 258 |
-
"node_modules/cliui": {
|
| 259 |
-
"version": "8.0.1",
|
| 260 |
-
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
| 261 |
-
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
|
| 262 |
-
"license": "ISC",
|
| 263 |
-
"dependencies": {
|
| 264 |
-
"string-width": "^4.2.0",
|
| 265 |
-
"strip-ansi": "^6.0.1",
|
| 266 |
-
"wrap-ansi": "^7.0.0"
|
| 267 |
-
},
|
| 268 |
-
"engines": {
|
| 269 |
-
"node": ">=12"
|
| 270 |
-
}
|
| 271 |
-
},
|
| 272 |
-
"node_modules/color-convert": {
|
| 273 |
-
"version": "2.0.1",
|
| 274 |
-
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
| 275 |
-
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
| 276 |
-
"license": "MIT",
|
| 277 |
-
"dependencies": {
|
| 278 |
-
"color-name": "~1.1.4"
|
| 279 |
-
},
|
| 280 |
-
"engines": {
|
| 281 |
-
"node": ">=7.0.0"
|
| 282 |
-
}
|
| 283 |
-
},
|
| 284 |
-
"node_modules/color-name": {
|
| 285 |
-
"version": "1.1.4",
|
| 286 |
-
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
| 287 |
-
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
| 288 |
-
"license": "MIT"
|
| 289 |
-
},
|
| 290 |
-
"node_modules/cosmiconfig": {
|
| 291 |
-
"version": "9.0.0",
|
| 292 |
-
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz",
|
| 293 |
-
"integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==",
|
| 294 |
-
"license": "MIT",
|
| 295 |
-
"dependencies": {
|
| 296 |
-
"env-paths": "^2.2.1",
|
| 297 |
-
"import-fresh": "^3.3.0",
|
| 298 |
-
"js-yaml": "^4.1.0",
|
| 299 |
-
"parse-json": "^5.2.0"
|
| 300 |
-
},
|
| 301 |
-
"engines": {
|
| 302 |
-
"node": ">=14"
|
| 303 |
-
},
|
| 304 |
-
"funding": {
|
| 305 |
-
"url": "https://github.com/sponsors/d-fischer"
|
| 306 |
-
},
|
| 307 |
-
"peerDependencies": {
|
| 308 |
-
"typescript": ">=4.9.5"
|
| 309 |
-
},
|
| 310 |
-
"peerDependenciesMeta": {
|
| 311 |
-
"typescript": {
|
| 312 |
-
"optional": true
|
| 313 |
-
}
|
| 314 |
-
}
|
| 315 |
-
},
|
| 316 |
-
"node_modules/cosmiconfig/node_modules/js-yaml": {
|
| 317 |
-
"version": "4.1.1",
|
| 318 |
-
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
|
| 319 |
-
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
|
| 320 |
-
"license": "MIT",
|
| 321 |
-
"dependencies": {
|
| 322 |
-
"argparse": "^2.0.1"
|
| 323 |
-
},
|
| 324 |
-
"bin": {
|
| 325 |
-
"js-yaml": "bin/js-yaml.js"
|
| 326 |
-
}
|
| 327 |
-
},
|
| 328 |
-
"node_modules/data-uri-to-buffer": {
|
| 329 |
-
"version": "6.0.2",
|
| 330 |
-
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz",
|
| 331 |
-
"integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==",
|
| 332 |
-
"license": "MIT",
|
| 333 |
-
"engines": {
|
| 334 |
-
"node": ">= 14"
|
| 335 |
-
}
|
| 336 |
-
},
|
| 337 |
-
"node_modules/debug": {
|
| 338 |
-
"version": "4.4.3",
|
| 339 |
-
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
| 340 |
-
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
| 341 |
-
"license": "MIT",
|
| 342 |
-
"dependencies": {
|
| 343 |
-
"ms": "^2.1.3"
|
| 344 |
-
},
|
| 345 |
-
"engines": {
|
| 346 |
-
"node": ">=6.0"
|
| 347 |
-
},
|
| 348 |
-
"peerDependenciesMeta": {
|
| 349 |
-
"supports-color": {
|
| 350 |
-
"optional": true
|
| 351 |
-
}
|
| 352 |
-
}
|
| 353 |
-
},
|
| 354 |
-
"node_modules/degenerator": {
|
| 355 |
-
"version": "5.0.1",
|
| 356 |
-
"resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz",
|
| 357 |
-
"integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==",
|
| 358 |
-
"license": "MIT",
|
| 359 |
-
"dependencies": {
|
| 360 |
-
"ast-types": "^0.13.4",
|
| 361 |
-
"escodegen": "^2.1.0",
|
| 362 |
-
"esprima": "^4.0.1"
|
| 363 |
-
},
|
| 364 |
-
"engines": {
|
| 365 |
-
"node": ">= 14"
|
| 366 |
-
}
|
| 367 |
-
},
|
| 368 |
-
"node_modules/devtools-protocol": {
|
| 369 |
-
"version": "0.0.1566079",
|
| 370 |
-
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1566079.tgz",
|
| 371 |
-
"integrity": "sha512-MJfAEA1UfVhSs7fbSQOG4czavUp1ajfg6prlAN0+cmfa2zNjaIbvq8VneP7do1WAQQIvgNJWSMeP6UyI90gIlQ==",
|
| 372 |
-
"license": "BSD-3-Clause",
|
| 373 |
-
"peer": true
|
| 374 |
-
},
|
| 375 |
-
"node_modules/emoji-regex": {
|
| 376 |
-
"version": "8.0.0",
|
| 377 |
-
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
| 378 |
-
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
| 379 |
-
"license": "MIT"
|
| 380 |
-
},
|
| 381 |
-
"node_modules/end-of-stream": {
|
| 382 |
-
"version": "1.4.5",
|
| 383 |
-
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
|
| 384 |
-
"integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
|
| 385 |
-
"license": "MIT",
|
| 386 |
-
"dependencies": {
|
| 387 |
-
"once": "^1.4.0"
|
| 388 |
-
}
|
| 389 |
-
},
|
| 390 |
-
"node_modules/env-paths": {
|
| 391 |
-
"version": "2.2.1",
|
| 392 |
-
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
|
| 393 |
-
"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
|
| 394 |
-
"license": "MIT",
|
| 395 |
-
"engines": {
|
| 396 |
-
"node": ">=6"
|
| 397 |
-
}
|
| 398 |
-
},
|
| 399 |
-
"node_modules/error-ex": {
|
| 400 |
-
"version": "1.3.4",
|
| 401 |
-
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
|
| 402 |
-
"integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
|
| 403 |
-
"license": "MIT",
|
| 404 |
-
"dependencies": {
|
| 405 |
-
"is-arrayish": "^0.2.1"
|
| 406 |
-
}
|
| 407 |
-
},
|
| 408 |
-
"node_modules/escalade": {
|
| 409 |
-
"version": "3.2.0",
|
| 410 |
-
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
|
| 411 |
-
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
|
| 412 |
-
"license": "MIT",
|
| 413 |
-
"engines": {
|
| 414 |
-
"node": ">=6"
|
| 415 |
-
}
|
| 416 |
-
},
|
| 417 |
-
"node_modules/escodegen": {
|
| 418 |
-
"version": "2.1.0",
|
| 419 |
-
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
|
| 420 |
-
"integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
|
| 421 |
-
"license": "BSD-2-Clause",
|
| 422 |
-
"dependencies": {
|
| 423 |
-
"esprima": "^4.0.1",
|
| 424 |
-
"estraverse": "^5.2.0",
|
| 425 |
-
"esutils": "^2.0.2"
|
| 426 |
-
},
|
| 427 |
-
"bin": {
|
| 428 |
-
"escodegen": "bin/escodegen.js",
|
| 429 |
-
"esgenerate": "bin/esgenerate.js"
|
| 430 |
-
},
|
| 431 |
-
"engines": {
|
| 432 |
-
"node": ">=6.0"
|
| 433 |
-
},
|
| 434 |
-
"optionalDependencies": {
|
| 435 |
-
"source-map": "~0.6.1"
|
| 436 |
-
}
|
| 437 |
-
},
|
| 438 |
-
"node_modules/esprima": {
|
| 439 |
-
"version": "4.0.1",
|
| 440 |
-
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
| 441 |
-
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
| 442 |
-
"license": "BSD-2-Clause",
|
| 443 |
-
"bin": {
|
| 444 |
-
"esparse": "bin/esparse.js",
|
| 445 |
-
"esvalidate": "bin/esvalidate.js"
|
| 446 |
-
},
|
| 447 |
-
"engines": {
|
| 448 |
-
"node": ">=4"
|
| 449 |
-
}
|
| 450 |
-
},
|
| 451 |
-
"node_modules/estraverse": {
|
| 452 |
-
"version": "5.3.0",
|
| 453 |
-
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
|
| 454 |
-
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
|
| 455 |
-
"license": "BSD-2-Clause",
|
| 456 |
-
"engines": {
|
| 457 |
-
"node": ">=4.0"
|
| 458 |
-
}
|
| 459 |
-
},
|
| 460 |
-
"node_modules/esutils": {
|
| 461 |
-
"version": "2.0.3",
|
| 462 |
-
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
| 463 |
-
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
|
| 464 |
-
"license": "BSD-2-Clause",
|
| 465 |
-
"engines": {
|
| 466 |
-
"node": ">=0.10.0"
|
| 467 |
-
}
|
| 468 |
-
},
|
| 469 |
-
"node_modules/events-universal": {
|
| 470 |
-
"version": "1.0.1",
|
| 471 |
-
"resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz",
|
| 472 |
-
"integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==",
|
| 473 |
-
"license": "Apache-2.0",
|
| 474 |
-
"dependencies": {
|
| 475 |
-
"bare-events": "^2.7.0"
|
| 476 |
-
}
|
| 477 |
-
},
|
| 478 |
-
"node_modules/extract-zip": {
|
| 479 |
-
"version": "2.0.1",
|
| 480 |
-
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
|
| 481 |
-
"integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
|
| 482 |
-
"license": "BSD-2-Clause",
|
| 483 |
-
"dependencies": {
|
| 484 |
-
"debug": "^4.1.1",
|
| 485 |
-
"get-stream": "^5.1.0",
|
| 486 |
-
"yauzl": "^2.10.0"
|
| 487 |
-
},
|
| 488 |
-
"bin": {
|
| 489 |
-
"extract-zip": "cli.js"
|
| 490 |
-
},
|
| 491 |
-
"engines": {
|
| 492 |
-
"node": ">= 10.17.0"
|
| 493 |
-
},
|
| 494 |
-
"optionalDependencies": {
|
| 495 |
-
"@types/yauzl": "^2.9.1"
|
| 496 |
-
}
|
| 497 |
-
},
|
| 498 |
-
"node_modules/fast-fifo": {
|
| 499 |
-
"version": "1.3.2",
|
| 500 |
-
"resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
|
| 501 |
-
"integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==",
|
| 502 |
-
"license": "MIT"
|
| 503 |
-
},
|
| 504 |
-
"node_modules/fd-slicer": {
|
| 505 |
-
"version": "1.1.0",
|
| 506 |
-
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
|
| 507 |
-
"integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
|
| 508 |
-
"license": "MIT",
|
| 509 |
-
"dependencies": {
|
| 510 |
-
"pend": "~1.2.0"
|
| 511 |
-
}
|
| 512 |
-
},
|
| 513 |
-
"node_modules/get-caller-file": {
|
| 514 |
-
"version": "2.0.5",
|
| 515 |
-
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
| 516 |
-
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
| 517 |
-
"license": "ISC",
|
| 518 |
-
"engines": {
|
| 519 |
-
"node": "6.* || 8.* || >= 10.*"
|
| 520 |
-
}
|
| 521 |
-
},
|
| 522 |
-
"node_modules/get-stream": {
|
| 523 |
-
"version": "5.2.0",
|
| 524 |
-
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
|
| 525 |
-
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
|
| 526 |
-
"license": "MIT",
|
| 527 |
-
"dependencies": {
|
| 528 |
-
"pump": "^3.0.0"
|
| 529 |
-
},
|
| 530 |
-
"engines": {
|
| 531 |
-
"node": ">=8"
|
| 532 |
-
},
|
| 533 |
-
"funding": {
|
| 534 |
-
"url": "https://github.com/sponsors/sindresorhus"
|
| 535 |
-
}
|
| 536 |
-
},
|
| 537 |
-
"node_modules/get-uri": {
|
| 538 |
-
"version": "6.0.5",
|
| 539 |
-
"resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz",
|
| 540 |
-
"integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==",
|
| 541 |
-
"license": "MIT",
|
| 542 |
-
"dependencies": {
|
| 543 |
-
"basic-ftp": "^5.0.2",
|
| 544 |
-
"data-uri-to-buffer": "^6.0.2",
|
| 545 |
-
"debug": "^4.3.4"
|
| 546 |
-
},
|
| 547 |
-
"engines": {
|
| 548 |
-
"node": ">= 14"
|
| 549 |
-
}
|
| 550 |
-
},
|
| 551 |
-
"node_modules/http-proxy-agent": {
|
| 552 |
-
"version": "7.0.2",
|
| 553 |
-
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
|
| 554 |
-
"integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
|
| 555 |
-
"license": "MIT",
|
| 556 |
-
"dependencies": {
|
| 557 |
-
"agent-base": "^7.1.0",
|
| 558 |
-
"debug": "^4.3.4"
|
| 559 |
-
},
|
| 560 |
-
"engines": {
|
| 561 |
-
"node": ">= 14"
|
| 562 |
-
}
|
| 563 |
-
},
|
| 564 |
-
"node_modules/https-proxy-agent": {
|
| 565 |
-
"version": "7.0.6",
|
| 566 |
-
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
|
| 567 |
-
"integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
|
| 568 |
-
"license": "MIT",
|
| 569 |
-
"dependencies": {
|
| 570 |
-
"agent-base": "^7.1.2",
|
| 571 |
-
"debug": "4"
|
| 572 |
-
},
|
| 573 |
-
"engines": {
|
| 574 |
-
"node": ">= 14"
|
| 575 |
-
}
|
| 576 |
-
},
|
| 577 |
-
"node_modules/import-fresh": {
|
| 578 |
-
"version": "3.3.1",
|
| 579 |
-
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
|
| 580 |
-
"integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
|
| 581 |
-
"license": "MIT",
|
| 582 |
-
"dependencies": {
|
| 583 |
-
"parent-module": "^1.0.0",
|
| 584 |
-
"resolve-from": "^4.0.0"
|
| 585 |
-
},
|
| 586 |
-
"engines": {
|
| 587 |
-
"node": ">=6"
|
| 588 |
-
},
|
| 589 |
-
"funding": {
|
| 590 |
-
"url": "https://github.com/sponsors/sindresorhus"
|
| 591 |
-
}
|
| 592 |
-
},
|
| 593 |
-
"node_modules/ip-address": {
|
| 594 |
-
"version": "10.1.0",
|
| 595 |
-
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz",
|
| 596 |
-
"integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==",
|
| 597 |
-
"license": "MIT",
|
| 598 |
-
"engines": {
|
| 599 |
-
"node": ">= 12"
|
| 600 |
-
}
|
| 601 |
-
},
|
| 602 |
-
"node_modules/is-arrayish": {
|
| 603 |
-
"version": "0.2.1",
|
| 604 |
-
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
|
| 605 |
-
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
|
| 606 |
-
"license": "MIT"
|
| 607 |
-
},
|
| 608 |
-
"node_modules/is-fullwidth-code-point": {
|
| 609 |
-
"version": "3.0.0",
|
| 610 |
-
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
| 611 |
-
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
| 612 |
-
"license": "MIT",
|
| 613 |
-
"engines": {
|
| 614 |
-
"node": ">=8"
|
| 615 |
-
}
|
| 616 |
-
},
|
| 617 |
-
"node_modules/js-tokens": {
|
| 618 |
-
"version": "4.0.0",
|
| 619 |
-
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
| 620 |
-
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
| 621 |
-
"license": "MIT"
|
| 622 |
-
},
|
| 623 |
-
"node_modules/json-parse-even-better-errors": {
|
| 624 |
-
"version": "2.3.1",
|
| 625 |
-
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
|
| 626 |
-
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
|
| 627 |
-
"license": "MIT"
|
| 628 |
-
},
|
| 629 |
-
"node_modules/lru-cache": {
|
| 630 |
-
"version": "7.18.3",
|
| 631 |
-
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
|
| 632 |
-
"integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
|
| 633 |
-
"license": "ISC",
|
| 634 |
-
"engines": {
|
| 635 |
-
"node": ">=12"
|
| 636 |
-
}
|
| 637 |
-
},
|
| 638 |
-
"node_modules/mitt": {
|
| 639 |
-
"version": "3.0.1",
|
| 640 |
-
"resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
|
| 641 |
-
"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
|
| 642 |
-
"license": "MIT"
|
| 643 |
-
},
|
| 644 |
-
"node_modules/ms": {
|
| 645 |
-
"version": "2.1.3",
|
| 646 |
-
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
| 647 |
-
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
| 648 |
-
"license": "MIT"
|
| 649 |
-
},
|
| 650 |
-
"node_modules/netmask": {
|
| 651 |
-
"version": "2.0.2",
|
| 652 |
-
"resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz",
|
| 653 |
-
"integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==",
|
| 654 |
-
"license": "MIT",
|
| 655 |
-
"engines": {
|
| 656 |
-
"node": ">= 0.4.0"
|
| 657 |
-
}
|
| 658 |
-
},
|
| 659 |
-
"node_modules/once": {
|
| 660 |
-
"version": "1.4.0",
|
| 661 |
-
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
| 662 |
-
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
| 663 |
-
"license": "ISC",
|
| 664 |
-
"dependencies": {
|
| 665 |
-
"wrappy": "1"
|
| 666 |
-
}
|
| 667 |
-
},
|
| 668 |
-
"node_modules/pac-proxy-agent": {
|
| 669 |
-
"version": "7.2.0",
|
| 670 |
-
"resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz",
|
| 671 |
-
"integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==",
|
| 672 |
-
"license": "MIT",
|
| 673 |
-
"dependencies": {
|
| 674 |
-
"@tootallnate/quickjs-emscripten": "^0.23.0",
|
| 675 |
-
"agent-base": "^7.1.2",
|
| 676 |
-
"debug": "^4.3.4",
|
| 677 |
-
"get-uri": "^6.0.1",
|
| 678 |
-
"http-proxy-agent": "^7.0.0",
|
| 679 |
-
"https-proxy-agent": "^7.0.6",
|
| 680 |
-
"pac-resolver": "^7.0.1",
|
| 681 |
-
"socks-proxy-agent": "^8.0.5"
|
| 682 |
-
},
|
| 683 |
-
"engines": {
|
| 684 |
-
"node": ">= 14"
|
| 685 |
-
}
|
| 686 |
-
},
|
| 687 |
-
"node_modules/pac-resolver": {
|
| 688 |
-
"version": "7.0.1",
|
| 689 |
-
"resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz",
|
| 690 |
-
"integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==",
|
| 691 |
-
"license": "MIT",
|
| 692 |
-
"dependencies": {
|
| 693 |
-
"degenerator": "^5.0.0",
|
| 694 |
-
"netmask": "^2.0.2"
|
| 695 |
-
},
|
| 696 |
-
"engines": {
|
| 697 |
-
"node": ">= 14"
|
| 698 |
-
}
|
| 699 |
-
},
|
| 700 |
-
"node_modules/parent-module": {
|
| 701 |
-
"version": "1.0.1",
|
| 702 |
-
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
| 703 |
-
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
|
| 704 |
-
"license": "MIT",
|
| 705 |
-
"dependencies": {
|
| 706 |
-
"callsites": "^3.0.0"
|
| 707 |
-
},
|
| 708 |
-
"engines": {
|
| 709 |
-
"node": ">=6"
|
| 710 |
-
}
|
| 711 |
-
},
|
| 712 |
-
"node_modules/parse-json": {
|
| 713 |
-
"version": "5.2.0",
|
| 714 |
-
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
|
| 715 |
-
"integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
|
| 716 |
-
"license": "MIT",
|
| 717 |
-
"dependencies": {
|
| 718 |
-
"@babel/code-frame": "^7.0.0",
|
| 719 |
-
"error-ex": "^1.3.1",
|
| 720 |
-
"json-parse-even-better-errors": "^2.3.0",
|
| 721 |
-
"lines-and-columns": "^1.1.6"
|
| 722 |
-
},
|
| 723 |
-
"engines": {
|
| 724 |
-
"node": ">=8"
|
| 725 |
-
},
|
| 726 |
-
"funding": {
|
| 727 |
-
"url": "https://github.com/sponsors/sindresorhus"
|
| 728 |
-
}
|
| 729 |
-
},
|
| 730 |
-
"node_modules/parse-json/node_modules/@babel/code-frame": {
|
| 731 |
-
"version": "7.29.0",
|
| 732 |
-
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
|
| 733 |
-
"integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
|
| 734 |
-
"license": "MIT",
|
| 735 |
-
"dependencies": {
|
| 736 |
-
"@babel/helper-validator-identifier": "^7.28.5",
|
| 737 |
-
"js-tokens": "^4.0.0",
|
| 738 |
-
"picocolors": "^1.1.1"
|
| 739 |
-
},
|
| 740 |
-
"engines": {
|
| 741 |
-
"node": ">=6.9.0"
|
| 742 |
-
}
|
| 743 |
-
},
|
| 744 |
-
"node_modules/parse-json/node_modules/@babel/helper-validator-identifier": {
|
| 745 |
-
"version": "7.28.5",
|
| 746 |
-
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
|
| 747 |
-
"integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
|
| 748 |
-
"license": "MIT",
|
| 749 |
-
"engines": {
|
| 750 |
-
"node": ">=6.9.0"
|
| 751 |
-
}
|
| 752 |
-
},
|
| 753 |
-
"node_modules/parse-json/node_modules/lines-and-columns": {
|
| 754 |
-
"version": "1.2.4",
|
| 755 |
-
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
| 756 |
-
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
|
| 757 |
-
"license": "MIT"
|
| 758 |
-
},
|
| 759 |
-
"node_modules/pend": {
|
| 760 |
-
"version": "1.2.0",
|
| 761 |
-
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
|
| 762 |
-
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
|
| 763 |
-
"license": "MIT"
|
| 764 |
-
},
|
| 765 |
-
"node_modules/picocolors": {
|
| 766 |
-
"version": "1.1.1",
|
| 767 |
-
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
| 768 |
-
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
|
| 769 |
-
"license": "ISC"
|
| 770 |
-
},
|
| 771 |
-
"node_modules/progress": {
|
| 772 |
-
"version": "2.0.3",
|
| 773 |
-
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
|
| 774 |
-
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
|
| 775 |
-
"license": "MIT",
|
| 776 |
-
"engines": {
|
| 777 |
-
"node": ">=0.4.0"
|
| 778 |
-
}
|
| 779 |
-
},
|
| 780 |
-
"node_modules/proxy-agent": {
|
| 781 |
-
"version": "6.5.0",
|
| 782 |
-
"resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz",
|
| 783 |
-
"integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==",
|
| 784 |
-
"license": "MIT",
|
| 785 |
-
"dependencies": {
|
| 786 |
-
"agent-base": "^7.1.2",
|
| 787 |
-
"debug": "^4.3.4",
|
| 788 |
-
"http-proxy-agent": "^7.0.1",
|
| 789 |
-
"https-proxy-agent": "^7.0.6",
|
| 790 |
-
"lru-cache": "^7.14.1",
|
| 791 |
-
"pac-proxy-agent": "^7.1.0",
|
| 792 |
-
"proxy-from-env": "^1.1.0",
|
| 793 |
-
"socks-proxy-agent": "^8.0.5"
|
| 794 |
-
},
|
| 795 |
-
"engines": {
|
| 796 |
-
"node": ">= 14"
|
| 797 |
-
}
|
| 798 |
-
},
|
| 799 |
-
"node_modules/proxy-from-env": {
|
| 800 |
-
"version": "1.1.0",
|
| 801 |
-
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
| 802 |
-
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
| 803 |
-
"license": "MIT"
|
| 804 |
-
},
|
| 805 |
-
"node_modules/pump": {
|
| 806 |
-
"version": "3.0.3",
|
| 807 |
-
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
|
| 808 |
-
"integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==",
|
| 809 |
-
"license": "MIT",
|
| 810 |
-
"dependencies": {
|
| 811 |
-
"end-of-stream": "^1.1.0",
|
| 812 |
-
"once": "^1.3.1"
|
| 813 |
-
}
|
| 814 |
-
},
|
| 815 |
-
"node_modules/puppeteer": {
|
| 816 |
-
"version": "24.37.3",
|
| 817 |
-
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.37.3.tgz",
|
| 818 |
-
"integrity": "sha512-AUGGWq0BhPM+IOS2U9A+ZREH3HDFkV1Y5HERYGDg5cbGXjoGsTCT7/A6VZRfNU0UJJdCclyEimZICkZW6pqJyw==",
|
| 819 |
-
"hasInstallScript": true,
|
| 820 |
-
"license": "Apache-2.0",
|
| 821 |
-
"dependencies": {
|
| 822 |
-
"@puppeteer/browsers": "2.12.1",
|
| 823 |
-
"chromium-bidi": "14.0.0",
|
| 824 |
-
"cosmiconfig": "^9.0.0",
|
| 825 |
-
"devtools-protocol": "0.0.1566079",
|
| 826 |
-
"puppeteer-core": "24.37.3",
|
| 827 |
-
"typed-query-selector": "^2.12.0"
|
| 828 |
-
},
|
| 829 |
-
"bin": {
|
| 830 |
-
"puppeteer": "lib/cjs/puppeteer/node/cli.js"
|
| 831 |
-
},
|
| 832 |
-
"engines": {
|
| 833 |
-
"node": ">=18"
|
| 834 |
-
}
|
| 835 |
-
},
|
| 836 |
-
"node_modules/puppeteer-core": {
|
| 837 |
-
"version": "24.37.3",
|
| 838 |
-
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.37.3.tgz",
|
| 839 |
-
"integrity": "sha512-fokQ8gv+hNgsRWqVuP5rUjGp+wzV5aMTP3fcm8ekNabmLGlJdFHas1OdMscAH9Gzq4Qcf7cfI/Pe6wEcAqQhqg==",
|
| 840 |
-
"license": "Apache-2.0",
|
| 841 |
-
"dependencies": {
|
| 842 |
-
"@puppeteer/browsers": "2.12.1",
|
| 843 |
-
"chromium-bidi": "14.0.0",
|
| 844 |
-
"debug": "^4.4.3",
|
| 845 |
-
"devtools-protocol": "0.0.1566079",
|
| 846 |
-
"typed-query-selector": "^2.12.0",
|
| 847 |
-
"webdriver-bidi-protocol": "0.4.1",
|
| 848 |
-
"ws": "^8.19.0"
|
| 849 |
-
},
|
| 850 |
-
"engines": {
|
| 851 |
-
"node": ">=18"
|
| 852 |
-
}
|
| 853 |
-
},
|
| 854 |
-
"node_modules/require-directory": {
|
| 855 |
-
"version": "2.1.1",
|
| 856 |
-
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
| 857 |
-
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
|
| 858 |
-
"license": "MIT",
|
| 859 |
-
"engines": {
|
| 860 |
-
"node": ">=0.10.0"
|
| 861 |
-
}
|
| 862 |
-
},
|
| 863 |
-
"node_modules/resolve-from": {
|
| 864 |
-
"version": "4.0.0",
|
| 865 |
-
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
|
| 866 |
-
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
|
| 867 |
-
"license": "MIT",
|
| 868 |
-
"engines": {
|
| 869 |
-
"node": ">=4"
|
| 870 |
-
}
|
| 871 |
-
},
|
| 872 |
-
"node_modules/semver": {
|
| 873 |
-
"version": "7.7.4",
|
| 874 |
-
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
|
| 875 |
-
"integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
|
| 876 |
-
"license": "ISC",
|
| 877 |
-
"bin": {
|
| 878 |
-
"semver": "bin/semver.js"
|
| 879 |
-
},
|
| 880 |
-
"engines": {
|
| 881 |
-
"node": ">=10"
|
| 882 |
-
}
|
| 883 |
-
},
|
| 884 |
-
"node_modules/smart-buffer": {
|
| 885 |
-
"version": "4.2.0",
|
| 886 |
-
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
|
| 887 |
-
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
|
| 888 |
-
"license": "MIT",
|
| 889 |
-
"engines": {
|
| 890 |
-
"node": ">= 6.0.0",
|
| 891 |
-
"npm": ">= 3.0.0"
|
| 892 |
-
}
|
| 893 |
-
},
|
| 894 |
-
"node_modules/socks": {
|
| 895 |
-
"version": "2.8.7",
|
| 896 |
-
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz",
|
| 897 |
-
"integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==",
|
| 898 |
-
"license": "MIT",
|
| 899 |
-
"dependencies": {
|
| 900 |
-
"ip-address": "^10.0.1",
|
| 901 |
-
"smart-buffer": "^4.2.0"
|
| 902 |
-
},
|
| 903 |
-
"engines": {
|
| 904 |
-
"node": ">= 10.0.0",
|
| 905 |
-
"npm": ">= 3.0.0"
|
| 906 |
-
}
|
| 907 |
-
},
|
| 908 |
-
"node_modules/socks-proxy-agent": {
|
| 909 |
-
"version": "8.0.5",
|
| 910 |
-
"resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz",
|
| 911 |
-
"integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==",
|
| 912 |
-
"license": "MIT",
|
| 913 |
-
"dependencies": {
|
| 914 |
-
"agent-base": "^7.1.2",
|
| 915 |
-
"debug": "^4.3.4",
|
| 916 |
-
"socks": "^2.8.3"
|
| 917 |
-
},
|
| 918 |
-
"engines": {
|
| 919 |
-
"node": ">= 14"
|
| 920 |
-
}
|
| 921 |
-
},
|
| 922 |
-
"node_modules/source-map": {
|
| 923 |
-
"version": "0.6.1",
|
| 924 |
-
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
| 925 |
-
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
| 926 |
-
"license": "BSD-3-Clause",
|
| 927 |
-
"optional": true,
|
| 928 |
-
"engines": {
|
| 929 |
-
"node": ">=0.10.0"
|
| 930 |
-
}
|
| 931 |
-
},
|
| 932 |
-
"node_modules/streamx": {
|
| 933 |
-
"version": "2.23.0",
|
| 934 |
-
"resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz",
|
| 935 |
-
"integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==",
|
| 936 |
-
"license": "MIT",
|
| 937 |
-
"dependencies": {
|
| 938 |
-
"events-universal": "^1.0.0",
|
| 939 |
-
"fast-fifo": "^1.3.2",
|
| 940 |
-
"text-decoder": "^1.1.0"
|
| 941 |
-
}
|
| 942 |
-
},
|
| 943 |
-
"node_modules/string-width": {
|
| 944 |
-
"version": "4.2.3",
|
| 945 |
-
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
| 946 |
-
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
| 947 |
-
"license": "MIT",
|
| 948 |
-
"dependencies": {
|
| 949 |
-
"emoji-regex": "^8.0.0",
|
| 950 |
-
"is-fullwidth-code-point": "^3.0.0",
|
| 951 |
-
"strip-ansi": "^6.0.1"
|
| 952 |
-
},
|
| 953 |
-
"engines": {
|
| 954 |
-
"node": ">=8"
|
| 955 |
-
}
|
| 956 |
-
},
|
| 957 |
-
"node_modules/strip-ansi": {
|
| 958 |
-
"version": "6.0.1",
|
| 959 |
-
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
| 960 |
-
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
| 961 |
-
"license": "MIT",
|
| 962 |
-
"dependencies": {
|
| 963 |
-
"ansi-regex": "^5.0.1"
|
| 964 |
-
},
|
| 965 |
-
"engines": {
|
| 966 |
-
"node": ">=8"
|
| 967 |
-
}
|
| 968 |
-
},
|
| 969 |
-
"node_modules/tar-fs": {
|
| 970 |
-
"version": "3.1.1",
|
| 971 |
-
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz",
|
| 972 |
-
"integrity": "sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==",
|
| 973 |
-
"license": "MIT",
|
| 974 |
-
"dependencies": {
|
| 975 |
-
"pump": "^3.0.0",
|
| 976 |
-
"tar-stream": "^3.1.5"
|
| 977 |
-
},
|
| 978 |
-
"optionalDependencies": {
|
| 979 |
-
"bare-fs": "^4.0.1",
|
| 980 |
-
"bare-path": "^3.0.0"
|
| 981 |
-
}
|
| 982 |
-
},
|
| 983 |
-
"node_modules/tar-stream": {
|
| 984 |
-
"version": "3.1.7",
|
| 985 |
-
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz",
|
| 986 |
-
"integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==",
|
| 987 |
-
"license": "MIT",
|
| 988 |
-
"dependencies": {
|
| 989 |
-
"b4a": "^1.6.4",
|
| 990 |
-
"fast-fifo": "^1.2.0",
|
| 991 |
-
"streamx": "^2.15.0"
|
| 992 |
-
}
|
| 993 |
-
},
|
| 994 |
-
"node_modules/text-decoder": {
|
| 995 |
-
"version": "1.2.6",
|
| 996 |
-
"resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.6.tgz",
|
| 997 |
-
"integrity": "sha512-27FeW5GQFDfw0FpwMQhMagB7BztOOlmjcSRi97t2oplhKVTZtp0DZbSegSaXS5IIC6mxMvBG4AR1Sgc6BX3CQg==",
|
| 998 |
-
"license": "Apache-2.0",
|
| 999 |
-
"dependencies": {
|
| 1000 |
-
"b4a": "^1.6.4"
|
| 1001 |
-
}
|
| 1002 |
-
},
|
| 1003 |
-
"node_modules/tslib": {
|
| 1004 |
-
"version": "2.8.1",
|
| 1005 |
-
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
| 1006 |
-
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
| 1007 |
-
"license": "0BSD"
|
| 1008 |
-
},
|
| 1009 |
-
"node_modules/typed-query-selector": {
|
| 1010 |
-
"version": "2.12.0",
|
| 1011 |
-
"resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz",
|
| 1012 |
-
"integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==",
|
| 1013 |
-
"license": "MIT"
|
| 1014 |
-
},
|
| 1015 |
-
"node_modules/undici-types": {
|
| 1016 |
-
"version": "7.16.0",
|
| 1017 |
-
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
|
| 1018 |
-
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
|
| 1019 |
-
"license": "MIT",
|
| 1020 |
-
"optional": true
|
| 1021 |
-
},
|
| 1022 |
-
"node_modules/webdriver-bidi-protocol": {
|
| 1023 |
-
"version": "0.4.1",
|
| 1024 |
-
"resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.4.1.tgz",
|
| 1025 |
-
"integrity": "sha512-ARrjNjtWRRs2w4Tk7nqrf2gBI0QXWuOmMCx2hU+1jUt6d00MjMxURrhxhGbrsoiZKJrhTSTzbIrc554iKI10qw==",
|
| 1026 |
-
"license": "Apache-2.0"
|
| 1027 |
-
},
|
| 1028 |
-
"node_modules/wrap-ansi": {
|
| 1029 |
-
"version": "7.0.0",
|
| 1030 |
-
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
| 1031 |
-
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
| 1032 |
-
"license": "MIT",
|
| 1033 |
-
"dependencies": {
|
| 1034 |
-
"ansi-styles": "^4.0.0",
|
| 1035 |
-
"string-width": "^4.1.0",
|
| 1036 |
-
"strip-ansi": "^6.0.0"
|
| 1037 |
-
},
|
| 1038 |
-
"engines": {
|
| 1039 |
-
"node": ">=10"
|
| 1040 |
-
},
|
| 1041 |
-
"funding": {
|
| 1042 |
-
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
| 1043 |
-
}
|
| 1044 |
-
},
|
| 1045 |
-
"node_modules/wrappy": {
|
| 1046 |
-
"version": "1.0.2",
|
| 1047 |
-
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
| 1048 |
-
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
| 1049 |
-
"license": "ISC"
|
| 1050 |
-
},
|
| 1051 |
-
"node_modules/ws": {
|
| 1052 |
-
"version": "8.19.0",
|
| 1053 |
-
"resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
|
| 1054 |
-
"integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
|
| 1055 |
-
"license": "MIT",
|
| 1056 |
-
"engines": {
|
| 1057 |
-
"node": ">=10.0.0"
|
| 1058 |
-
},
|
| 1059 |
-
"peerDependencies": {
|
| 1060 |
-
"bufferutil": "^4.0.1",
|
| 1061 |
-
"utf-8-validate": ">=5.0.2"
|
| 1062 |
-
},
|
| 1063 |
-
"peerDependenciesMeta": {
|
| 1064 |
-
"bufferutil": {
|
| 1065 |
-
"optional": true
|
| 1066 |
-
},
|
| 1067 |
-
"utf-8-validate": {
|
| 1068 |
-
"optional": true
|
| 1069 |
-
}
|
| 1070 |
-
}
|
| 1071 |
-
},
|
| 1072 |
-
"node_modules/y18n": {
|
| 1073 |
-
"version": "5.0.8",
|
| 1074 |
-
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
| 1075 |
-
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
|
| 1076 |
-
"license": "ISC",
|
| 1077 |
-
"engines": {
|
| 1078 |
-
"node": ">=10"
|
| 1079 |
-
}
|
| 1080 |
-
},
|
| 1081 |
-
"node_modules/yargs": {
|
| 1082 |
-
"version": "17.7.2",
|
| 1083 |
-
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
|
| 1084 |
-
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
|
| 1085 |
-
"license": "MIT",
|
| 1086 |
-
"dependencies": {
|
| 1087 |
-
"cliui": "^8.0.1",
|
| 1088 |
-
"escalade": "^3.1.1",
|
| 1089 |
-
"get-caller-file": "^2.0.5",
|
| 1090 |
-
"require-directory": "^2.1.1",
|
| 1091 |
-
"string-width": "^4.2.3",
|
| 1092 |
-
"y18n": "^5.0.5",
|
| 1093 |
-
"yargs-parser": "^21.1.1"
|
| 1094 |
-
},
|
| 1095 |
-
"engines": {
|
| 1096 |
-
"node": ">=12"
|
| 1097 |
-
}
|
| 1098 |
-
},
|
| 1099 |
-
"node_modules/yargs-parser": {
|
| 1100 |
-
"version": "21.1.1",
|
| 1101 |
-
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
|
| 1102 |
-
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
|
| 1103 |
-
"license": "ISC",
|
| 1104 |
-
"engines": {
|
| 1105 |
-
"node": ">=12"
|
| 1106 |
-
}
|
| 1107 |
-
},
|
| 1108 |
-
"node_modules/yauzl": {
|
| 1109 |
-
"version": "2.10.0",
|
| 1110 |
-
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
|
| 1111 |
-
"integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
|
| 1112 |
-
"license": "MIT",
|
| 1113 |
-
"dependencies": {
|
| 1114 |
-
"buffer-crc32": "~0.2.3",
|
| 1115 |
-
"fd-slicer": "~1.1.0"
|
| 1116 |
-
}
|
| 1117 |
-
},
|
| 1118 |
-
"node_modules/zod": {
|
| 1119 |
-
"version": "3.25.76",
|
| 1120 |
-
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
| 1121 |
-
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
|
| 1122 |
-
"license": "MIT",
|
| 1123 |
-
"funding": {
|
| 1124 |
-
"url": "https://github.com/sponsors/colinhacks"
|
| 1125 |
-
}
|
| 1126 |
-
}
|
| 1127 |
-
}
|
| 1128 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
demo-automation/package.json
DELETED
|
@@ -1,14 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"name": "clinical-mind-demo",
|
| 3 |
-
"version": "1.0.0",
|
| 4 |
-
"description": "Automated demo for Clinical Mind hackathon presentation",
|
| 5 |
-
"main": "demo.js",
|
| 6 |
-
"scripts": {
|
| 7 |
-
"demo": "node demo.js",
|
| 8 |
-
"demo:leptos": "node demo-leptospirosis.js",
|
| 9 |
-
"demo:nmosd": "node demo-nmosd.js"
|
| 10 |
-
},
|
| 11 |
-
"dependencies": {
|
| 12 |
-
"puppeteer": "^24.37.3"
|
| 13 |
-
}
|
| 14 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
demo-automation/run-demo.sh
DELETED
|
@@ -1,33 +0,0 @@
|
|
| 1 |
-
#!/bin/bash
|
| 2 |
-
|
| 3 |
-
echo "🚀 Clinical Mind Demo Runner"
|
| 4 |
-
echo "============================="
|
| 5 |
-
echo ""
|
| 6 |
-
|
| 7 |
-
# Check if localhost:3000 is accessible
|
| 8 |
-
echo "📍 Checking if app is running on localhost:3000..."
|
| 9 |
-
if curl -s -o /dev/null -w "%{http_code}" http://localhost:3000 | grep -q "200"; then
|
| 10 |
-
echo "✅ App is running!"
|
| 11 |
-
else
|
| 12 |
-
echo "⚠️ Warning: Cannot reach localhost:3000"
|
| 13 |
-
echo " Make sure the Clinical Mind app is running before proceeding."
|
| 14 |
-
echo ""
|
| 15 |
-
read -p "Continue anyway? (y/n) " -n 1 -r
|
| 16 |
-
echo ""
|
| 17 |
-
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
| 18 |
-
exit 1
|
| 19 |
-
fi
|
| 20 |
-
fi
|
| 21 |
-
|
| 22 |
-
# Kill any existing Chrome processes
|
| 23 |
-
echo ""
|
| 24 |
-
echo "📍 Cleaning up Chrome processes..."
|
| 25 |
-
pkill -f "Google Chrome for Testing" 2>/dev/null
|
| 26 |
-
pkill -f "chrome" 2>/dev/null
|
| 27 |
-
sleep 1
|
| 28 |
-
|
| 29 |
-
# Run the demo
|
| 30 |
-
echo ""
|
| 31 |
-
echo "📍 Starting demo..."
|
| 32 |
-
echo ""
|
| 33 |
-
npm run demo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
demo-automation/setup.sh
DELETED
|
@@ -1,38 +0,0 @@
|
|
| 1 |
-
#!/bin/bash
|
| 2 |
-
|
| 3 |
-
echo "🚀 Clinical Mind - Demo Automation Setup"
|
| 4 |
-
echo "========================================="
|
| 5 |
-
echo ""
|
| 6 |
-
|
| 7 |
-
# Check if npm is installed
|
| 8 |
-
if ! command -v npm &> /dev/null; then
|
| 9 |
-
echo "❌ npm is not installed. Please install Node.js first."
|
| 10 |
-
echo " Visit: https://nodejs.org/"
|
| 11 |
-
exit 1
|
| 12 |
-
fi
|
| 13 |
-
|
| 14 |
-
# Install dependencies
|
| 15 |
-
echo "📦 Installing Puppeteer..."
|
| 16 |
-
npm install
|
| 17 |
-
|
| 18 |
-
# Check if Chrome/Chromium is available
|
| 19 |
-
echo ""
|
| 20 |
-
echo "🌐 Checking browser..."
|
| 21 |
-
npx puppeteer browsers install chrome
|
| 22 |
-
|
| 23 |
-
echo ""
|
| 24 |
-
echo "✅ Setup complete!"
|
| 25 |
-
echo ""
|
| 26 |
-
echo "📝 How to use:"
|
| 27 |
-
echo "1. Make sure the app is running on localhost:3000"
|
| 28 |
-
echo "2. Start your screen recorder"
|
| 29 |
-
echo "3. Run: npm run demo"
|
| 30 |
-
echo "4. Sit back and let it run!"
|
| 31 |
-
echo ""
|
| 32 |
-
echo "💡 The demo will:"
|
| 33 |
-
echo " - Open browser automatically"
|
| 34 |
-
echo " - Navigate through the case"
|
| 35 |
-
echo " - Type messages naturally"
|
| 36 |
-
echo " - Demonstrate all features"
|
| 37 |
-
echo ""
|
| 38 |
-
echo "Ready to record your hackathon demo! 🎬"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
frontend/src/App.tsx
CHANGED
|
@@ -6,7 +6,6 @@ import { CaseBrowser } from './pages/CaseBrowser';
|
|
| 6 |
import { CaseInterface } from './pages/CaseInterface';
|
| 7 |
import { Dashboard } from './pages/Dashboard';
|
| 8 |
import { KnowledgeGraphPage } from './pages/KnowledgeGraph';
|
| 9 |
-
import { DemoLive } from './pages/DemoLive';
|
| 10 |
|
| 11 |
function App() {
|
| 12 |
return (
|
|
@@ -18,7 +17,6 @@ function App() {
|
|
| 18 |
<Route path="/case/:id" element={<CaseInterface />} />
|
| 19 |
<Route path="/dashboard" element={<Dashboard />} />
|
| 20 |
<Route path="/knowledge-graph" element={<KnowledgeGraphPage />} />
|
| 21 |
-
<Route path="/demo" element={<DemoLive />} />
|
| 22 |
</Routes>
|
| 23 |
</Layout>
|
| 24 |
</Router>
|
|
|
|
| 6 |
import { CaseInterface } from './pages/CaseInterface';
|
| 7 |
import { Dashboard } from './pages/Dashboard';
|
| 8 |
import { KnowledgeGraphPage } from './pages/KnowledgeGraph';
|
|
|
|
| 9 |
|
| 10 |
function App() {
|
| 11 |
return (
|
|
|
|
| 17 |
<Route path="/case/:id" element={<CaseInterface />} />
|
| 18 |
<Route path="/dashboard" element={<Dashboard />} />
|
| 19 |
<Route path="/knowledge-graph" element={<KnowledgeGraphPage />} />
|
|
|
|
| 20 |
</Routes>
|
| 21 |
</Layout>
|
| 22 |
</Router>
|
frontend/src/data/demoData.ts
DELETED
|
@@ -1,351 +0,0 @@
|
|
| 1 |
-
import { type AgentMessageData } from '../components/case';
|
| 2 |
-
|
| 3 |
-
export interface DemoCase {
|
| 4 |
-
id: string;
|
| 5 |
-
title: string;
|
| 6 |
-
description: string;
|
| 7 |
-
specialty: string;
|
| 8 |
-
difficulty: string;
|
| 9 |
-
patient: {
|
| 10 |
-
age: number;
|
| 11 |
-
gender: string;
|
| 12 |
-
location: string;
|
| 13 |
-
};
|
| 14 |
-
chief_complaint: string;
|
| 15 |
-
initial_presentation: string;
|
| 16 |
-
vital_signs: {
|
| 17 |
-
bp: string;
|
| 18 |
-
hr: number;
|
| 19 |
-
rr: number;
|
| 20 |
-
temp: number;
|
| 21 |
-
spo2: number;
|
| 22 |
-
};
|
| 23 |
-
stages: Array<{
|
| 24 |
-
stage: string;
|
| 25 |
-
info: string;
|
| 26 |
-
}>;
|
| 27 |
-
diagnosis: string;
|
| 28 |
-
learning_points: string[];
|
| 29 |
-
script: {
|
| 30 |
-
questions: string[];
|
| 31 |
-
initialMessages: AgentMessageData[];
|
| 32 |
-
responses: Record<string, AgentMessageData[]>;
|
| 33 |
-
};
|
| 34 |
-
}
|
| 35 |
-
|
| 36 |
-
// Case 1: Acute Myocardial Infarction (Classic presentation for demo)
|
| 37 |
-
const miCase: DemoCase = {
|
| 38 |
-
id: 'demo-mi-001',
|
| 39 |
-
title: 'Acute ST-Elevation Myocardial Infarction',
|
| 40 |
-
description: 'Classic heart attack presentation - perfect for demonstrating critical decision making',
|
| 41 |
-
specialty: 'Cardiology',
|
| 42 |
-
difficulty: 'intermediate',
|
| 43 |
-
patient: {
|
| 44 |
-
age: 55,
|
| 45 |
-
gender: 'Male',
|
| 46 |
-
location: 'Mumbai',
|
| 47 |
-
},
|
| 48 |
-
chief_complaint: 'Severe chest pain for 2 hours',
|
| 49 |
-
initial_presentation: '55-year-old male businessman presents with crushing central chest pain radiating to left arm, started 2 hours ago while climbing stairs. Associated with profuse sweating, nausea. Known diabetic, smoker.',
|
| 50 |
-
vital_signs: {
|
| 51 |
-
bp: '90/60',
|
| 52 |
-
hr: 110,
|
| 53 |
-
rr: 24,
|
| 54 |
-
temp: 37.2,
|
| 55 |
-
spo2: 94,
|
| 56 |
-
},
|
| 57 |
-
stages: [
|
| 58 |
-
{
|
| 59 |
-
stage: 'history',
|
| 60 |
-
info: 'Pain started suddenly 2 hours ago, 9/10 severity, crushing/squeezing nature. Radiates to left arm and jaw. Associated with profuse sweating, nausea, feeling of impending doom. History of diabetes (10 years), hypertension (5 years), smoking (20 pack-years). Father died of heart attack at 60. Takes metformin, amlodipine irregularly.',
|
| 61 |
-
},
|
| 62 |
-
{
|
| 63 |
-
stage: 'physical_exam',
|
| 64 |
-
info: 'Patient appears anxious, diaphoretic. Cardiovascular: S1 S2 present, no murmurs. Chest: Clear bilaterally. JVP not elevated. No pedal edema. Cold, clammy extremities.',
|
| 65 |
-
},
|
| 66 |
-
{
|
| 67 |
-
stage: 'labs',
|
| 68 |
-
info: 'ECG: ST elevation in leads II, III, aVF (inferior wall MI). Troponin-I: Elevated at 2.5 ng/mL. CPK-MB: Elevated. Blood sugar: 280 mg/dL. Lipid profile: Total cholesterol 240, LDL 160, HDL 35.',
|
| 69 |
-
},
|
| 70 |
-
],
|
| 71 |
-
diagnosis: 'Acute ST-elevation myocardial infarction (STEMI) - Inferior wall',
|
| 72 |
-
learning_points: [
|
| 73 |
-
'Time is muscle - Door to balloon time critical in STEMI',
|
| 74 |
-
'Classic presentation: Crushing chest pain, radiation, diaphoresis',
|
| 75 |
-
'ECG is diagnostic - ST elevation in contiguous leads',
|
| 76 |
-
'Immediate dual antiplatelet therapy (Aspirin + Clopidogrel)',
|
| 77 |
-
'Primary PCI is treatment of choice if available within 90 minutes',
|
| 78 |
-
],
|
| 79 |
-
script: {
|
| 80 |
-
questions: [
|
| 81 |
-
"Can you describe your chest pain?",
|
| 82 |
-
"What are the current vital signs?",
|
| 83 |
-
"Let's do an ECG immediately",
|
| 84 |
-
"Start oxygen and give aspirin 325mg stat",
|
| 85 |
-
"We need to activate the cath lab - this is a STEMI",
|
| 86 |
-
],
|
| 87 |
-
initialMessages: [
|
| 88 |
-
{
|
| 89 |
-
id: 'demo-init-1',
|
| 90 |
-
agent_type: 'nurse',
|
| 91 |
-
display_name: 'Nurse Priya',
|
| 92 |
-
content: 'Doctor, urgent case! 55-year-old male with severe chest pain. BP is dropping - 90/60, pulse 110. Patient is sweating profusely. I\'ve started IV access and put him on monitor.',
|
| 93 |
-
urgency_level: 'critical',
|
| 94 |
-
timestamp: new Date(),
|
| 95 |
-
},
|
| 96 |
-
{
|
| 97 |
-
id: 'demo-init-2',
|
| 98 |
-
agent_type: 'patient',
|
| 99 |
-
display_name: 'Patient',
|
| 100 |
-
content: 'Doctor sahab... bahut dard ho raha hai... chest mein... jaise koi dabaa raha ho... haath tak jaa raha hai... (groaning in pain) Please kuch karo!',
|
| 101 |
-
distress_level: 'critical',
|
| 102 |
-
timestamp: new Date(),
|
| 103 |
-
},
|
| 104 |
-
{
|
| 105 |
-
id: 'demo-init-3',
|
| 106 |
-
agent_type: 'family',
|
| 107 |
-
display_name: "Patient's Wife",
|
| 108 |
-
content: 'Doctor please bachaa lo inko! Stairs chadhte waqt achanak gir gaye... bahut pasina aa raha tha... kabhi aisa nahi hua! Yeh BP aur sugar ki dawai lete hain par irregular. Please jaldi kuch karo!',
|
| 109 |
-
timestamp: new Date(),
|
| 110 |
-
},
|
| 111 |
-
{
|
| 112 |
-
id: 'demo-init-4',
|
| 113 |
-
agent_type: 'senior_doctor',
|
| 114 |
-
display_name: 'Dr. Sharma',
|
| 115 |
-
content: 'This looks concerning. The presentation is classic - what\'s your immediate assessment? Think about the most life-threatening causes of chest pain. Time is critical here.',
|
| 116 |
-
is_teaching: true,
|
| 117 |
-
timestamp: new Date(),
|
| 118 |
-
},
|
| 119 |
-
],
|
| 120 |
-
responses: {
|
| 121 |
-
"Can you describe your chest pain?": [
|
| 122 |
-
{
|
| 123 |
-
id: 'resp-1',
|
| 124 |
-
agent_type: 'patient',
|
| 125 |
-
display_name: 'Patient',
|
| 126 |
-
content: 'Doctor... bahut tez dard... jaise pathhar rakha ho chest pe... 2 ghante se ho raha hai... left haath mein bhi jaa raha hai... saans lene mein bhi dikkat... (sweating profusely)',
|
| 127 |
-
distress_level: 'critical',
|
| 128 |
-
timestamp: new Date(),
|
| 129 |
-
},
|
| 130 |
-
],
|
| 131 |
-
"What are the current vital signs?": [
|
| 132 |
-
{
|
| 133 |
-
id: 'resp-2',
|
| 134 |
-
agent_type: 'nurse',
|
| 135 |
-
display_name: 'Nurse Priya',
|
| 136 |
-
content: 'Doctor, vitals are worrying - BP 90/60 and dropping, pulse 110 irregular, RR 24, SpO2 94% on room air, patient is diaphoretic. ECG machine is ready.',
|
| 137 |
-
urgency_level: 'critical',
|
| 138 |
-
timestamp: new Date(),
|
| 139 |
-
},
|
| 140 |
-
],
|
| 141 |
-
"Let's do an ECG immediately": [
|
| 142 |
-
{
|
| 143 |
-
id: 'resp-3',
|
| 144 |
-
agent_type: 'nurse',
|
| 145 |
-
display_name: 'Nurse Priya',
|
| 146 |
-
content: 'ECG done doctor - showing ST elevation in leads II, III, and aVF. This looks like an inferior wall MI!',
|
| 147 |
-
urgency_level: 'critical',
|
| 148 |
-
timestamp: new Date(),
|
| 149 |
-
},
|
| 150 |
-
{
|
| 151 |
-
id: 'resp-4',
|
| 152 |
-
agent_type: 'senior_doctor',
|
| 153 |
-
display_name: 'Dr. Sharma',
|
| 154 |
-
content: 'Excellent! You\'ve identified a STEMI. Now every minute counts. What\'s your immediate management? Remember - Time is muscle!',
|
| 155 |
-
is_teaching: true,
|
| 156 |
-
timestamp: new Date(),
|
| 157 |
-
},
|
| 158 |
-
],
|
| 159 |
-
"Start oxygen and give aspirin 325mg stat": [
|
| 160 |
-
{
|
| 161 |
-
id: 'resp-5',
|
| 162 |
-
agent_type: 'nurse',
|
| 163 |
-
display_name: 'Nurse Priya',
|
| 164 |
-
content: 'Oxygen started at 4L/min via nasal cannula. Aspirin 325mg chewable given. Also giving Clopidogrel 300mg loading dose. Should I prepare for thrombolysis or are we going for primary PCI?',
|
| 165 |
-
timestamp: new Date(),
|
| 166 |
-
},
|
| 167 |
-
],
|
| 168 |
-
"We need to activate the cath lab - this is a STEMI": [
|
| 169 |
-
{
|
| 170 |
-
id: 'resp-6',
|
| 171 |
-
agent_type: 'senior_doctor',
|
| 172 |
-
display_name: 'Dr. Sharma',
|
| 173 |
-
content: 'Perfect management! You\'ve correctly identified and managed an acute STEMI. Door-to-balloon time is critical. The cath lab team is being activated. Remember the mnemonic MONA - Morphine, Oxygen, Nitrates, Aspirin. Excellent work!',
|
| 174 |
-
is_teaching: true,
|
| 175 |
-
timestamp: new Date(),
|
| 176 |
-
},
|
| 177 |
-
{
|
| 178 |
-
id: 'resp-7',
|
| 179 |
-
agent_type: 'patient',
|
| 180 |
-
display_name: 'Patient',
|
| 181 |
-
content: 'Doctor... thoda better lag raha hai oxygen ke baad... thank you... (still in pain but slightly relieved)',
|
| 182 |
-
distress_level: 'high',
|
| 183 |
-
timestamp: new Date(),
|
| 184 |
-
},
|
| 185 |
-
],
|
| 186 |
-
},
|
| 187 |
-
},
|
| 188 |
-
};
|
| 189 |
-
|
| 190 |
-
// Case 2: Dengue Fever (Common tropical disease for demo)
|
| 191 |
-
const dengueCase: DemoCase = {
|
| 192 |
-
id: 'demo-dengue-001',
|
| 193 |
-
title: 'Dengue Fever with Warning Signs',
|
| 194 |
-
description: 'Common tropical disease showing importance of monitoring and supportive care',
|
| 195 |
-
specialty: 'Infectious Disease',
|
| 196 |
-
difficulty: 'beginner',
|
| 197 |
-
patient: {
|
| 198 |
-
age: 28,
|
| 199 |
-
gender: 'Female',
|
| 200 |
-
location: 'Delhi',
|
| 201 |
-
},
|
| 202 |
-
chief_complaint: 'High fever with body aches for 4 days',
|
| 203 |
-
initial_presentation: '28-year-old female teacher presents with high-grade fever for 4 days, severe body aches, headache behind eyes, and new-onset skin rash. No appetite, mild abdominal pain.',
|
| 204 |
-
vital_signs: {
|
| 205 |
-
bp: '100/70',
|
| 206 |
-
hr: 95,
|
| 207 |
-
rr: 18,
|
| 208 |
-
temp: 39.2,
|
| 209 |
-
spo2: 98,
|
| 210 |
-
},
|
| 211 |
-
stages: [
|
| 212 |
-
{
|
| 213 |
-
stage: 'history',
|
| 214 |
-
info: 'Fever started 4 days ago, initially 103°F, now 102°F. Severe retro-orbital headache, myalgia, arthralgia (breakbone fever). Developed rash today - red, patchy. Mild abdominal pain, nausea, decreased appetite. No bleeding manifestations. Multiple mosquito bites last week. Neighbor also had dengue recently.',
|
| 215 |
-
},
|
| 216 |
-
{
|
| 217 |
-
stage: 'physical_exam',
|
| 218 |
-
info: 'Patient appears tired but alert. Positive tourniquet test. Petechial rash on arms and trunk. Mild right hypochondrial tenderness. No hepatosplenomegaly. No signs of plasma leakage.',
|
| 219 |
-
},
|
| 220 |
-
{
|
| 221 |
-
stage: 'labs',
|
| 222 |
-
info: 'CBC: Platelets 80,000 (falling trend), WBC 3,500, Hct 42% (baseline 38%). Dengue NS1 Antigen: Positive. Dengue IgM: Positive. LFT: Mild transaminitis (AST 120, ALT 100).',
|
| 223 |
-
},
|
| 224 |
-
],
|
| 225 |
-
diagnosis: 'Dengue fever with warning signs',
|
| 226 |
-
learning_points: [
|
| 227 |
-
'Dengue has three phases: Febrile, Critical (day 3-7), Recovery',
|
| 228 |
-
'Warning signs: Abdominal pain, persistent vomiting, clinical fluid accumulation',
|
| 229 |
-
'Monitor platelet count and hematocrit daily',
|
| 230 |
-
'IV fluids crucial if warning signs present',
|
| 231 |
-
'Avoid NSAIDs and IM injections due to bleeding risk',
|
| 232 |
-
],
|
| 233 |
-
script: {
|
| 234 |
-
questions: [
|
| 235 |
-
"How long have you had this fever?",
|
| 236 |
-
"Any bleeding from anywhere?",
|
| 237 |
-
"What's the platelet count?",
|
| 238 |
-
"Let's start IV fluids and monitor closely",
|
| 239 |
-
"This looks like dengue - we need daily platelet monitoring",
|
| 240 |
-
],
|
| 241 |
-
initialMessages: [
|
| 242 |
-
{
|
| 243 |
-
id: 'demo-init-d1',
|
| 244 |
-
agent_type: 'nurse',
|
| 245 |
-
display_name: 'Nurse Priya',
|
| 246 |
-
content: 'Doctor, 28-year-old female with high fever for 4 days. She looks weak. Today morning she developed a rash all over. Platelet count from yesterday was 1.2 lakh, today it\'s 80,000.',
|
| 247 |
-
urgency_level: 'urgent',
|
| 248 |
-
timestamp: new Date(),
|
| 249 |
-
},
|
| 250 |
-
{
|
| 251 |
-
id: 'demo-init-d2',
|
| 252 |
-
agent_type: 'patient',
|
| 253 |
-
display_name: 'Patient',
|
| 254 |
-
content: 'Doctor, bahut weakness ho rahi hai... sar mein aur aankhon ke peeche bahut dard... pura badan dukh raha hai jaise haddiyan toot rahi hon... bukhar 4 din se hai...',
|
| 255 |
-
distress_level: 'moderate',
|
| 256 |
-
timestamp: new Date(),
|
| 257 |
-
},
|
| 258 |
-
{
|
| 259 |
-
id: 'demo-init-d3',
|
| 260 |
-
agent_type: 'family',
|
| 261 |
-
display_name: "Patient's Mother",
|
| 262 |
-
content: 'Doctor ji, kal se kuch bhi nahi khaya hai... bas paani pi rahi hai... aaj subah se yeh red red spots aa gaye hain... mohalle mein kaafi logon ko dengue hua hai. Please check kar lijiye!',
|
| 263 |
-
timestamp: new Date(),
|
| 264 |
-
},
|
| 265 |
-
{
|
| 266 |
-
id: 'demo-init-d4',
|
| 267 |
-
agent_type: 'senior_doctor',
|
| 268 |
-
display_name: 'Dr. Sharma',
|
| 269 |
-
content: 'Classic presentation in dengue season. Note the timing - day 4 of illness. What phase of dengue is this? What warning signs should we monitor for?',
|
| 270 |
-
is_teaching: true,
|
| 271 |
-
timestamp: new Date(),
|
| 272 |
-
},
|
| 273 |
-
],
|
| 274 |
-
responses: {
|
| 275 |
-
"How long have you had this fever?": [
|
| 276 |
-
{
|
| 277 |
-
id: 'resp-d1',
|
| 278 |
-
agent_type: 'patient',
|
| 279 |
-
display_name: 'Patient',
|
| 280 |
-
content: 'Doctor, Monday se fever hai... pehle 103 tak jaata tha, ab thoda kam hai par body pain bahut zyada hai... aankhon ke peeche specially dard karta hai...',
|
| 281 |
-
timestamp: new Date(),
|
| 282 |
-
},
|
| 283 |
-
],
|
| 284 |
-
"Any bleeding from anywhere?": [
|
| 285 |
-
{
|
| 286 |
-
id: 'resp-d2',
|
| 287 |
-
agent_type: 'patient',
|
| 288 |
-
display_name: 'Patient',
|
| 289 |
-
content: 'Nahi doctor, bleeding toh nahi hai... par aaj brush karte time gums se thoda sa blood aaya tha... normally nahi hota...',
|
| 290 |
-
timestamp: new Date(),
|
| 291 |
-
},
|
| 292 |
-
{
|
| 293 |
-
id: 'resp-d2b',
|
| 294 |
-
agent_type: 'family',
|
| 295 |
-
display_name: "Patient's Mother",
|
| 296 |
-
content: 'Doctor, kal nose se bhi ek baar thoda blood aaya tha, par humne socha garmi ki wajah se hoga...',
|
| 297 |
-
timestamp: new Date(),
|
| 298 |
-
},
|
| 299 |
-
],
|
| 300 |
-
"What's the platelet count?": [
|
| 301 |
-
{
|
| 302 |
-
id: 'resp-d3',
|
| 303 |
-
agent_type: 'nurse',
|
| 304 |
-
display_name: 'Nurse Priya',
|
| 305 |
-
content: 'Latest platelet count is 80,000 doctor. It was 1.2 lakh yesterday, and 1.5 lakh two days ago. Clear falling trend. Hematocrit is 42% (was 38% at baseline). Should we repeat in evening?',
|
| 306 |
-
urgency_level: 'urgent',
|
| 307 |
-
timestamp: new Date(),
|
| 308 |
-
},
|
| 309 |
-
{
|
| 310 |
-
id: 'resp-d3b',
|
| 311 |
-
agent_type: 'lab_tech',
|
| 312 |
-
display_name: 'Lab Tech Ramesh',
|
| 313 |
-
content: 'Doctor, Dengue NS1 positive hai. IgM bhi positive. LFT mein mild elevation hai - AST 120, ALT 100. Platelet ka repeat 6 ghante mein karenge?',
|
| 314 |
-
timestamp: new Date(),
|
| 315 |
-
},
|
| 316 |
-
],
|
| 317 |
-
"Let's start IV fluids and monitor closely": [
|
| 318 |
-
{
|
| 319 |
-
id: 'resp-d4',
|
| 320 |
-
agent_type: 'nurse',
|
| 321 |
-
display_name: 'Nurse Priya',
|
| 322 |
-
content: 'IV line secured, starting NS at 100ml/hr as ordered. Will monitor intake-output strictly. Vital signs every 4 hours. Should I give paracetamol for fever?',
|
| 323 |
-
timestamp: new Date(),
|
| 324 |
-
},
|
| 325 |
-
],
|
| 326 |
-
"This looks like dengue - we need daily platelet monitoring": [
|
| 327 |
-
{
|
| 328 |
-
id: 'resp-d5',
|
| 329 |
-
agent_type: 'senior_doctor',
|
| 330 |
-
display_name: 'Dr. Sharma',
|
| 331 |
-
content: 'Excellent! You\'ve identified dengue with warning signs - falling platelets and mild bleeding. This is the critical phase (days 3-7). Key is supportive care - IV fluids, monitoring for plasma leakage. No aspirin or NSAIDs! Well managed!',
|
| 332 |
-
is_teaching: true,
|
| 333 |
-
timestamp: new Date(),
|
| 334 |
-
},
|
| 335 |
-
{
|
| 336 |
-
id: 'resp-d6',
|
| 337 |
-
agent_type: 'family',
|
| 338 |
-
display_name: "Patient's Mother",
|
| 339 |
-
content: 'Thank you doctor... kitne din mein theek ho jayegi? Ghar le ja sakte hain ya admit karna padega?',
|
| 340 |
-
timestamp: new Date(),
|
| 341 |
-
},
|
| 342 |
-
],
|
| 343 |
-
},
|
| 344 |
-
},
|
| 345 |
-
};
|
| 346 |
-
|
| 347 |
-
export const DEMO_CASES = [miCase, dengueCase];
|
| 348 |
-
|
| 349 |
-
export const getDemoCase = (id: string): DemoCase | undefined => {
|
| 350 |
-
return DEMO_CASES.find(c => c.id === id);
|
| 351 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
frontend/src/pages/DemoLive.tsx
DELETED
|
@@ -1,236 +0,0 @@
|
|
| 1 |
-
import React, { useState } from 'react';
|
| 2 |
-
import { useNavigate } from 'react-router-dom';
|
| 3 |
-
import { Button, Card, Badge } from '../components/ui';
|
| 4 |
-
|
| 5 |
-
// Same student levels as main app
|
| 6 |
-
const STUDENT_LEVELS = [
|
| 7 |
-
{ value: 'mbbs_1st', label: 'MBBS 1st Year', description: 'Basic anatomy and physiology' },
|
| 8 |
-
{ value: 'mbbs_2nd', label: 'MBBS 2nd Year', description: 'Pathology and pharmacology' },
|
| 9 |
-
{ value: 'mbbs_3rd', label: 'MBBS 3rd Year', description: 'Clinical subjects introduction' },
|
| 10 |
-
{ value: 'mbbs_final', label: 'MBBS Final Year', description: 'Advanced clinical medicine' },
|
| 11 |
-
{ value: 'intern', label: 'Intern', description: 'Hands-on clinical training' },
|
| 12 |
-
{ value: 'resident', label: 'Resident', description: 'Specialized practice' },
|
| 13 |
-
];
|
| 14 |
-
|
| 15 |
-
// Only 2 curated cases for demo
|
| 16 |
-
const DEMO_CASES = [
|
| 17 |
-
{
|
| 18 |
-
id: 'demo-case-001',
|
| 19 |
-
chief_complaint: 'Severe crushing chest pain for 2 hours',
|
| 20 |
-
specialty: 'cardiology',
|
| 21 |
-
difficulty: 'intermediate',
|
| 22 |
-
patient: {
|
| 23 |
-
age: 55,
|
| 24 |
-
gender: 'Male',
|
| 25 |
-
location: 'Mumbai',
|
| 26 |
-
},
|
| 27 |
-
presentation: '55-year-old businessman presents with severe central chest pain radiating to left arm, started while climbing stairs. Associated with profuse sweating and nausea.',
|
| 28 |
-
initial_vitals: {
|
| 29 |
-
bp: '90/60',
|
| 30 |
-
hr: 110,
|
| 31 |
-
rr: 24,
|
| 32 |
-
temp: 37.2,
|
| 33 |
-
spo2: 94,
|
| 34 |
-
},
|
| 35 |
-
},
|
| 36 |
-
{
|
| 37 |
-
id: 'demo-case-002',
|
| 38 |
-
chief_complaint: 'High fever with body aches for 4 days',
|
| 39 |
-
specialty: 'infectious_disease',
|
| 40 |
-
difficulty: 'beginner',
|
| 41 |
-
patient: {
|
| 42 |
-
age: 28,
|
| 43 |
-
gender: 'Female',
|
| 44 |
-
location: 'Delhi',
|
| 45 |
-
},
|
| 46 |
-
presentation: '28-year-old teacher with high-grade fever, severe retro-orbital headache, myalgia. Developed petechial rash today. Multiple mosquito bites last week.',
|
| 47 |
-
initial_vitals: {
|
| 48 |
-
bp: '100/70',
|
| 49 |
-
hr: 95,
|
| 50 |
-
rr: 18,
|
| 51 |
-
temp: 39.2,
|
| 52 |
-
spo2: 98,
|
| 53 |
-
},
|
| 54 |
-
},
|
| 55 |
-
];
|
| 56 |
-
|
| 57 |
-
export const DemoLive: React.FC = () => {
|
| 58 |
-
const navigate = useNavigate();
|
| 59 |
-
const [studentName, setStudentName] = useState('');
|
| 60 |
-
const [studentLevel, setStudentLevel] = useState('');
|
| 61 |
-
const [showCases, setShowCases] = useState(false);
|
| 62 |
-
|
| 63 |
-
const handleStudentSubmit = () => {
|
| 64 |
-
if (!studentName.trim() || !studentLevel) return;
|
| 65 |
-
|
| 66 |
-
// Store student info
|
| 67 |
-
localStorage.setItem('studentName', studentName);
|
| 68 |
-
localStorage.setItem('studentLevel', studentLevel);
|
| 69 |
-
|
| 70 |
-
setShowCases(true);
|
| 71 |
-
};
|
| 72 |
-
|
| 73 |
-
const handleSelectCase = (caseData: typeof DEMO_CASES[0]) => {
|
| 74 |
-
// Navigate to case interface with parameters
|
| 75 |
-
const params = new URLSearchParams({
|
| 76 |
-
specialty: caseData.specialty,
|
| 77 |
-
difficulty: caseData.difficulty,
|
| 78 |
-
level: studentLevel,
|
| 79 |
-
});
|
| 80 |
-
|
| 81 |
-
navigate(`/case/new?${params.toString()}`);
|
| 82 |
-
};
|
| 83 |
-
|
| 84 |
-
// Student Profile Form (same as main app)
|
| 85 |
-
if (!showCases) {
|
| 86 |
-
return (
|
| 87 |
-
<div className="max-w-4xl mx-auto px-6 py-20">
|
| 88 |
-
<div className="text-center mb-12">
|
| 89 |
-
<div className="w-20 h-20 bg-forest-green/10 rounded-2xl flex items-center justify-center mx-auto mb-4">
|
| 90 |
-
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="#2D5C3F" strokeWidth="2">
|
| 91 |
-
<path d="M12 2L2 7L12 12L22 7L12 2Z" />
|
| 92 |
-
<path d="M2 17L12 22L22 17" />
|
| 93 |
-
<path d="M2 12L12 17L22 12" />
|
| 94 |
-
</svg>
|
| 95 |
-
</div>
|
| 96 |
-
<h1 className="text-4xl font-bold text-text-primary mb-4">
|
| 97 |
-
Clinical<span className="text-forest-green">Mind</span>
|
| 98 |
-
</h1>
|
| 99 |
-
<p className="text-lg text-text-secondary">
|
| 100 |
-
AI-powered medical simulation for clinical education
|
| 101 |
-
</p>
|
| 102 |
-
</div>
|
| 103 |
-
|
| 104 |
-
<Card padding="lg" className="max-w-md mx-auto">
|
| 105 |
-
<h2 className="text-xl font-semibold text-text-primary mb-6">Student Profile</h2>
|
| 106 |
-
|
| 107 |
-
<div className="space-y-4">
|
| 108 |
-
<div>
|
| 109 |
-
<label className="block text-sm font-medium text-text-secondary mb-2">
|
| 110 |
-
Your Name
|
| 111 |
-
</label>
|
| 112 |
-
<input
|
| 113 |
-
type="text"
|
| 114 |
-
value={studentName}
|
| 115 |
-
onChange={(e) => setStudentName(e.target.value)}
|
| 116 |
-
placeholder="Enter your name..."
|
| 117 |
-
className="w-full p-3 rounded-lg border-[1.5px] border-warm-gray-100 bg-cream-white text-text-primary placeholder:text-text-tertiary focus:outline-none focus:border-forest-green transition-colors"
|
| 118 |
-
/>
|
| 119 |
-
</div>
|
| 120 |
-
|
| 121 |
-
<div>
|
| 122 |
-
<label className="block text-sm font-medium text-text-secondary mb-2">
|
| 123 |
-
Academic Level
|
| 124 |
-
</label>
|
| 125 |
-
<div className="space-y-2">
|
| 126 |
-
{STUDENT_LEVELS.map((level) => (
|
| 127 |
-
<button
|
| 128 |
-
key={level.value}
|
| 129 |
-
onClick={() => setStudentLevel(level.value)}
|
| 130 |
-
className={`w-full text-left p-3 rounded-lg border-[1.5px] transition-all ${
|
| 131 |
-
studentLevel === level.value
|
| 132 |
-
? 'border-forest-green bg-forest-green/5'
|
| 133 |
-
: 'border-warm-gray-100 hover:border-forest-green/30'
|
| 134 |
-
}`}
|
| 135 |
-
>
|
| 136 |
-
<div className="font-medium text-text-primary">{level.label}</div>
|
| 137 |
-
<div className="text-xs text-text-tertiary mt-0.5">{level.description}</div>
|
| 138 |
-
</button>
|
| 139 |
-
))}
|
| 140 |
-
</div>
|
| 141 |
-
</div>
|
| 142 |
-
|
| 143 |
-
<Button
|
| 144 |
-
className="w-full"
|
| 145 |
-
disabled={!studentName.trim() || !studentLevel}
|
| 146 |
-
onClick={handleStudentSubmit}
|
| 147 |
-
>
|
| 148 |
-
Continue to Cases
|
| 149 |
-
</Button>
|
| 150 |
-
</div>
|
| 151 |
-
</Card>
|
| 152 |
-
|
| 153 |
-
<div className="text-center mt-8">
|
| 154 |
-
<p className="text-sm text-text-tertiary">
|
| 155 |
-
Your progress will be tracked throughout the simulation
|
| 156 |
-
</p>
|
| 157 |
-
</div>
|
| 158 |
-
</div>
|
| 159 |
-
);
|
| 160 |
-
}
|
| 161 |
-
|
| 162 |
-
// Case Selection (limited to 2 demo cases)
|
| 163 |
-
return (
|
| 164 |
-
<div className="max-w-7xl mx-auto px-6 py-12">
|
| 165 |
-
<div className="mb-8">
|
| 166 |
-
<h1 className="text-3xl font-bold text-text-primary mb-2">Select a Case</h1>
|
| 167 |
-
<p className="text-lg text-text-secondary">
|
| 168 |
-
Choose a clinical case to begin your simulation
|
| 169 |
-
</p>
|
| 170 |
-
</div>
|
| 171 |
-
|
| 172 |
-
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
| 173 |
-
{DEMO_CASES.map((caseData) => (
|
| 174 |
-
<Card
|
| 175 |
-
key={caseData.id}
|
| 176 |
-
padding="lg"
|
| 177 |
-
className="hover:shadow-xl transition-shadow cursor-pointer"
|
| 178 |
-
onClick={() => handleSelectCase(caseData)}
|
| 179 |
-
>
|
| 180 |
-
<div className="flex items-start justify-between mb-4">
|
| 181 |
-
<div>
|
| 182 |
-
<Badge variant={caseData.difficulty === 'beginner' ? 'success' : 'warning'}>
|
| 183 |
-
{caseData.difficulty.charAt(0).toUpperCase() + caseData.difficulty.slice(1)}
|
| 184 |
-
</Badge>
|
| 185 |
-
<span className="ml-2">
|
| 186 |
-
<Badge variant="info">
|
| 187 |
-
{caseData.specialty.replace('_', ' ').charAt(0).toUpperCase() + caseData.specialty.replace('_', ' ').slice(1)}
|
| 188 |
-
</Badge>
|
| 189 |
-
</span>
|
| 190 |
-
</div>
|
| 191 |
-
</div>
|
| 192 |
-
|
| 193 |
-
<h3 className="text-lg font-semibold text-text-primary mb-3">
|
| 194 |
-
{caseData.chief_complaint}
|
| 195 |
-
</h3>
|
| 196 |
-
|
| 197 |
-
<div className="space-y-2 mb-4">
|
| 198 |
-
<div className="flex items-center gap-2 text-sm text-text-secondary">
|
| 199 |
-
<span className="font-medium">Patient:</span>
|
| 200 |
-
<span>{caseData.patient.age}y {caseData.patient.gender}, {caseData.patient.location}</span>
|
| 201 |
-
</div>
|
| 202 |
-
<p className="text-sm text-text-secondary">
|
| 203 |
-
{caseData.presentation}
|
| 204 |
-
</p>
|
| 205 |
-
</div>
|
| 206 |
-
|
| 207 |
-
<div className="border-t border-warm-gray-100 pt-3">
|
| 208 |
-
<div className="text-xs text-text-tertiary">
|
| 209 |
-
<span className="font-medium">Initial Vitals:</span>
|
| 210 |
-
<div className="flex flex-wrap gap-2 mt-1">
|
| 211 |
-
<span>BP: {caseData.initial_vitals.bp}</span>
|
| 212 |
-
<span>•</span>
|
| 213 |
-
<span>HR: {caseData.initial_vitals.hr}</span>
|
| 214 |
-
<span>•</span>
|
| 215 |
-
<span>Temp: {caseData.initial_vitals.temp}°C</span>
|
| 216 |
-
<span>•</span>
|
| 217 |
-
<span>SpO2: {caseData.initial_vitals.spo2}%</span>
|
| 218 |
-
</div>
|
| 219 |
-
</div>
|
| 220 |
-
</div>
|
| 221 |
-
|
| 222 |
-
<Button variant="secondary" className="w-full mt-4">
|
| 223 |
-
Start This Case
|
| 224 |
-
</Button>
|
| 225 |
-
</Card>
|
| 226 |
-
))}
|
| 227 |
-
</div>
|
| 228 |
-
|
| 229 |
-
<div className="mt-8 text-center">
|
| 230 |
-
<Button variant="tertiary" onClick={() => setShowCases(false)}>
|
| 231 |
-
Back to Profile
|
| 232 |
-
</Button>
|
| 233 |
-
</div>
|
| 234 |
-
</div>
|
| 235 |
-
);
|
| 236 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|