Spaces:
Running
feat: redesign Dashboard and Settings with proper layout
Browse filesDashboard:
- Add structured input bar with URL, instruction, task type
- Add left sidebar with accordions (Agents, MCPs, Skills, APIs, Vision)
- Add center area with stats header, main visualization, logs terminal
- Add right sidebar with memory stats, extracted data, recent actions
- Add popup modals for model/agent/plugin selection
- Add task complexity selector (Low/Medium/High)
Settings:
- Add left sidebar navigation with sections
- Add Budget & Limits section (disabled by default)
- Add Appearance and Notifications settings
- Add proper section-based layout
App:
- Add Docs tab in navigation
- Remove footer, use full height layout
- Compact navbar design
Docs:
- Add USER_GUIDE.md documentation
- Add DocsPage component with react-markdown
- Include agents, plugins, memory, API reference docs
Types:
- Add autoSave and debugMode to SystemSettings
- Add AgentOption and ModelOption interfaces
- docs/USER_GUIDE.md +385 -0
- frontend/package-lock.json +1533 -79
- frontend/package.json +3 -1
- frontend/src/App.tsx +16 -36
- frontend/src/components/Dashboard.tsx +872 -146
- frontend/src/components/DocsPage.tsx +625 -0
- frontend/src/components/Settings.tsx +387 -90
- frontend/src/types/index.ts +2 -0
- frontend/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,385 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ScrapeRL Documentation
|
| 2 |
+
|
| 3 |
+
Welcome to ScrapeRL - an advanced Reinforcement Learning-powered web scraping environment. This documentation covers all aspects of using and configuring ScrapeRL.
|
| 4 |
+
|
| 5 |
+
---
|
| 6 |
+
|
| 7 |
+
## Table of Contents
|
| 8 |
+
|
| 9 |
+
1. [Getting Started](#getting-started)
|
| 10 |
+
2. [Dashboard Overview](#dashboard-overview)
|
| 11 |
+
3. [Agents](#agents)
|
| 12 |
+
4. [Plugins](#plugins)
|
| 13 |
+
5. [Memory System](#memory-system)
|
| 14 |
+
6. [Models & Providers](#models--providers)
|
| 15 |
+
7. [Settings](#settings)
|
| 16 |
+
8. [API Reference](#api-reference)
|
| 17 |
+
9. [Troubleshooting](#troubleshooting)
|
| 18 |
+
|
| 19 |
+
---
|
| 20 |
+
|
| 21 |
+
## Getting Started
|
| 22 |
+
|
| 23 |
+
### What is ScrapeRL?
|
| 24 |
+
|
| 25 |
+
ScrapeRL is an intelligent web scraping system that uses Reinforcement Learning (RL) to learn and adapt scraping strategies. Unlike traditional scrapers, ScrapeRL can:
|
| 26 |
+
|
| 27 |
+
- **Learn from experience** - Improve scraping strategies over time
|
| 28 |
+
- **Adapt to changes** - Handle website structure changes automatically
|
| 29 |
+
- **Multi-agent coordination** - Use specialized agents for different tasks
|
| 30 |
+
- **Memory-enhanced** - Remember patterns and optimize future runs
|
| 31 |
+
|
| 32 |
+
### Quick Start
|
| 33 |
+
|
| 34 |
+
1. **Enter a Target URL** - Provide the webpage you want to scrape
|
| 35 |
+
2. **Write an Instruction** - Describe what data you want to extract
|
| 36 |
+
3. **Configure Options** - Select model, agents, and plugins
|
| 37 |
+
4. **Start Episode** - Click Start and watch the magic happen!
|
| 38 |
+
|
| 39 |
+
### Example Task
|
| 40 |
+
|
| 41 |
+
```
|
| 42 |
+
URL: https://example.com/products
|
| 43 |
+
Instruction: Extract all product names, prices, and descriptions
|
| 44 |
+
Task Type: Medium
|
| 45 |
+
```
|
| 46 |
+
|
| 47 |
+
---
|
| 48 |
+
|
| 49 |
+
## Dashboard Overview
|
| 50 |
+
|
| 51 |
+
The dashboard is your command center for monitoring and controlling scraping operations.
|
| 52 |
+
|
| 53 |
+
### Layout Structure
|
| 54 |
+
|
| 55 |
+
| Section | Description |
|
| 56 |
+
|---------|-------------|
|
| 57 |
+
| **Input Bar** | Enter URL, instruction, and configure task |
|
| 58 |
+
| **Left Sidebar** | View active agents, MCPs, skills, and tools |
|
| 59 |
+
| **Center Area** | Main visualization and current observation |
|
| 60 |
+
| **Right Sidebar** | Memory stats, extracted data, recent actions |
|
| 61 |
+
| **Bottom Logs** | Real-time terminal-style log output |
|
| 62 |
+
|
| 63 |
+
### Stats Header
|
| 64 |
+
|
| 65 |
+
The header shows key metrics with expandable details:
|
| 66 |
+
|
| 67 |
+
- **Episodes** - Total scraping sessions completed
|
| 68 |
+
- **Steps** - Actions taken in current/total sessions
|
| 69 |
+
- **Reward** - Performance score (higher is better)
|
| 70 |
+
- **Time** - Current time and session duration
|
| 71 |
+
|
| 72 |
+
Click the **⋯** icon on any stat to see detailed statistics (min, max, average).
|
| 73 |
+
|
| 74 |
+
### Task Configuration
|
| 75 |
+
|
| 76 |
+
#### Task Types
|
| 77 |
+
|
| 78 |
+
| Type | Description | Use Case |
|
| 79 |
+
|------|-------------|----------|
|
| 80 |
+
| 🟢 **Low** | Simple single-page scraping | Product page, article text |
|
| 81 |
+
| 🟡 **Medium** | Multi-page with navigation | Search results, listings |
|
| 82 |
+
| 🔴 **High** | Complex interactive tasks | Login-required, forms |
|
| 83 |
+
|
| 84 |
+
---
|
| 85 |
+
|
| 86 |
+
## Agents
|
| 87 |
+
|
| 88 |
+
ScrapeRL uses a multi-agent architecture where specialized agents handle different aspects of scraping.
|
| 89 |
+
|
| 90 |
+
### Available Agents
|
| 91 |
+
|
| 92 |
+
| Agent | Role | Description |
|
| 93 |
+
|-------|------|-------------|
|
| 94 |
+
| **Coordinator** | 🎯 Orchestrator | Manages all other agents, decides strategy |
|
| 95 |
+
| **Scraper** | 📄 Extractor | Extracts data from page content |
|
| 96 |
+
| **Navigator** | 🧭 Navigation | Handles page navigation, clicking, scrolling |
|
| 97 |
+
| **Analyzer** | 🔍 Analysis | Analyzes extracted data for patterns |
|
| 98 |
+
| **Validator** | ✅ Validation | Validates data quality and completeness |
|
| 99 |
+
|
| 100 |
+
### Agent Selection
|
| 101 |
+
|
| 102 |
+
1. Click the **Agents** button in the input bar
|
| 103 |
+
2. Select agents you want to enable
|
| 104 |
+
3. Active agents appear in the left sidebar accordion
|
| 105 |
+
4. Monitor agent activity in real-time
|
| 106 |
+
|
| 107 |
+
### Agent Status Indicators
|
| 108 |
+
|
| 109 |
+
- 🟢 **Active** - Currently processing
|
| 110 |
+
- 🔵 **Ready** - Waiting for task
|
| 111 |
+
- 🟡 **Idle** - Not currently in use
|
| 112 |
+
- 🔴 **Error** - Encountered an issue
|
| 113 |
+
|
| 114 |
+
---
|
| 115 |
+
|
| 116 |
+
## Plugins
|
| 117 |
+
|
| 118 |
+
Extend ScrapeRL's capabilities with plugins organized by category.
|
| 119 |
+
|
| 120 |
+
### Plugin Categories
|
| 121 |
+
|
| 122 |
+
#### 🔧 MCPs (Model Context Protocols)
|
| 123 |
+
|
| 124 |
+
Tools that provide browser automation and page interaction:
|
| 125 |
+
|
| 126 |
+
| Plugin | Description |
|
| 127 |
+
|--------|-------------|
|
| 128 |
+
| Browser Use | AI-powered browser automation |
|
| 129 |
+
| Puppeteer MCP | Headless Chrome control |
|
| 130 |
+
| Playwright MCP | Cross-browser automation |
|
| 131 |
+
|
| 132 |
+
#### ⚡ Skills
|
| 133 |
+
|
| 134 |
+
Specialized capabilities for specific tasks:
|
| 135 |
+
|
| 136 |
+
| Plugin | Description |
|
| 137 |
+
|--------|-------------|
|
| 138 |
+
| Web Scraping | Core extraction algorithms |
|
| 139 |
+
| Data Extraction | Structured data parsing |
|
| 140 |
+
| Form Filling | Automated form completion |
|
| 141 |
+
|
| 142 |
+
#### 🔌 APIs
|
| 143 |
+
|
| 144 |
+
External service integrations:
|
| 145 |
+
|
| 146 |
+
| Plugin | Description |
|
| 147 |
+
|--------|-------------|
|
| 148 |
+
| Firecrawl | High-performance web crawler |
|
| 149 |
+
| Jina Reader | Content reader API |
|
| 150 |
+
| Serper | Search engine results API |
|
| 151 |
+
|
| 152 |
+
#### 👁️ Vision
|
| 153 |
+
|
| 154 |
+
Visual understanding capabilities:
|
| 155 |
+
|
| 156 |
+
| Plugin | Description |
|
| 157 |
+
|--------|-------------|
|
| 158 |
+
| GPT-4 Vision | OpenAI visual analysis |
|
| 159 |
+
| Gemini Vision | Google visual AI |
|
| 160 |
+
| Claude Vision | Anthropic visual models |
|
| 161 |
+
|
| 162 |
+
### Managing Plugins
|
| 163 |
+
|
| 164 |
+
1. Go to **Plugins** tab
|
| 165 |
+
2. Browse by category
|
| 166 |
+
3. Click **Install** to add a plugin
|
| 167 |
+
4. Enable plugins in Dashboard via the Plugins popup
|
| 168 |
+
|
| 169 |
+
---
|
| 170 |
+
|
| 171 |
+
## Memory System
|
| 172 |
+
|
| 173 |
+
ScrapeRL uses a hierarchical memory system for context retention.
|
| 174 |
+
|
| 175 |
+
### Memory Layers
|
| 176 |
+
|
| 177 |
+
| Layer | Purpose | Retention |
|
| 178 |
+
|-------|---------|-----------|
|
| 179 |
+
| **Working** | Current task context | Session |
|
| 180 |
+
| **Episodic** | Experience records | Persistent |
|
| 181 |
+
| **Semantic** | Learned patterns | Persistent |
|
| 182 |
+
| **Procedural** | Action sequences | Persistent |
|
| 183 |
+
|
| 184 |
+
### Memory Features
|
| 185 |
+
|
| 186 |
+
- **Auto-consolidation** - Promotes important data between layers
|
| 187 |
+
- **Similarity search** - Find related memories quickly
|
| 188 |
+
- **Pattern recognition** - Learn from past experiences
|
| 189 |
+
|
| 190 |
+
---
|
| 191 |
+
|
| 192 |
+
## Models & Providers
|
| 193 |
+
|
| 194 |
+
### Supported Providers
|
| 195 |
+
|
| 196 |
+
| Provider | Models | Best For |
|
| 197 |
+
|----------|--------|----------|
|
| 198 |
+
| **Groq** | GPT-OSS 120B | Fast inference, default |
|
| 199 |
+
| **Google** | Gemini 2.5 Flash | Balanced performance |
|
| 200 |
+
| **OpenAI** | GPT-4 Turbo | High accuracy |
|
| 201 |
+
| **Anthropic** | Claude 3 Opus | Complex reasoning |
|
| 202 |
+
|
| 203 |
+
### Model Selection
|
| 204 |
+
|
| 205 |
+
1. Click **Model** button in input bar
|
| 206 |
+
2. Select from available models
|
| 207 |
+
3. Models require appropriate API keys
|
| 208 |
+
|
| 209 |
+
### API Keys
|
| 210 |
+
|
| 211 |
+
Configure API keys in **Settings > API Keys**:
|
| 212 |
+
|
| 213 |
+
1. Select provider
|
| 214 |
+
2. Enter your API key
|
| 215 |
+
3. Click Save
|
| 216 |
+
4. Key status shows as "Active" when configured
|
| 217 |
+
|
| 218 |
+
---
|
| 219 |
+
|
| 220 |
+
## Settings
|
| 221 |
+
|
| 222 |
+
### General Settings
|
| 223 |
+
|
| 224 |
+
| Setting | Description |
|
| 225 |
+
|---------|-------------|
|
| 226 |
+
| WebSocket Updates | Enable real-time updates |
|
| 227 |
+
| Memory Persistence | Save memory across sessions |
|
| 228 |
+
| Auto-save Episodes | Automatically save completed episodes |
|
| 229 |
+
| Debug Mode | Enable verbose logging |
|
| 230 |
+
|
| 231 |
+
### Budget & Limits
|
| 232 |
+
|
| 233 |
+
Control API usage costs:
|
| 234 |
+
|
| 235 |
+
- **Daily Limit** - Maximum spend per day
|
| 236 |
+
- **Monthly Limit** - Maximum spend per month
|
| 237 |
+
- **Max Tokens** - Token limit per request
|
| 238 |
+
- **Alert Threshold** - Warning at 80% usage
|
| 239 |
+
|
| 240 |
+
> 💡 Budget limits are disabled by default. Enable in Settings to control spending.
|
| 241 |
+
|
| 242 |
+
### Appearance
|
| 243 |
+
|
| 244 |
+
- **Theme** - Dark (default), Light, Auto
|
| 245 |
+
- **Compact Mode** - Reduce UI spacing
|
| 246 |
+
- **Animations** - Enable/disable transitions
|
| 247 |
+
|
| 248 |
+
---
|
| 249 |
+
|
| 250 |
+
## API Reference
|
| 251 |
+
|
| 252 |
+
### Health Check
|
| 253 |
+
|
| 254 |
+
```bash
|
| 255 |
+
GET /api/health
|
| 256 |
+
```
|
| 257 |
+
|
| 258 |
+
Response:
|
| 259 |
+
```json
|
| 260 |
+
{
|
| 261 |
+
"status": "healthy",
|
| 262 |
+
"version": "0.1.0",
|
| 263 |
+
"timestamp": "2026-03-28T00:00:00Z"
|
| 264 |
+
}
|
| 265 |
+
```
|
| 266 |
+
|
| 267 |
+
### Episode Management
|
| 268 |
+
|
| 269 |
+
```bash
|
| 270 |
+
# Start new episode
|
| 271 |
+
POST /api/episode/reset
|
| 272 |
+
{
|
| 273 |
+
"task_id": "scrape-products",
|
| 274 |
+
"config": { ... }
|
| 275 |
+
}
|
| 276 |
+
|
| 277 |
+
# Take action
|
| 278 |
+
POST /api/episode/step
|
| 279 |
+
{
|
| 280 |
+
"action": "navigate",
|
| 281 |
+
"params": { "url": "..." }
|
| 282 |
+
}
|
| 283 |
+
|
| 284 |
+
# Get current state
|
| 285 |
+
GET /api/episode/state
|
| 286 |
+
```
|
| 287 |
+
|
| 288 |
+
### Memory API
|
| 289 |
+
|
| 290 |
+
```bash
|
| 291 |
+
# Store entry
|
| 292 |
+
POST /api/memory/store
|
| 293 |
+
{
|
| 294 |
+
"content": "...",
|
| 295 |
+
"memory_type": "working",
|
| 296 |
+
"metadata": { ... }
|
| 297 |
+
}
|
| 298 |
+
|
| 299 |
+
# Query memories
|
| 300 |
+
POST /api/memory/query
|
| 301 |
+
{
|
| 302 |
+
"query": "product prices",
|
| 303 |
+
"memory_type": "semantic",
|
| 304 |
+
"limit": 10
|
| 305 |
+
}
|
| 306 |
+
```
|
| 307 |
+
|
| 308 |
+
### Plugins API
|
| 309 |
+
|
| 310 |
+
```bash
|
| 311 |
+
# List plugins
|
| 312 |
+
GET /api/plugins/
|
| 313 |
+
|
| 314 |
+
# Install plugin
|
| 315 |
+
POST /api/plugins/install
|
| 316 |
+
{ "plugin_id": "firecrawl" }
|
| 317 |
+
|
| 318 |
+
# Uninstall plugin
|
| 319 |
+
POST /api/plugins/uninstall
|
| 320 |
+
{ "plugin_id": "firecrawl" }
|
| 321 |
+
```
|
| 322 |
+
|
| 323 |
+
---
|
| 324 |
+
|
| 325 |
+
## Troubleshooting
|
| 326 |
+
|
| 327 |
+
### Common Issues
|
| 328 |
+
|
| 329 |
+
#### "API Key Required" Error
|
| 330 |
+
|
| 331 |
+
**Solution:** Configure at least one API key in Settings > API Keys
|
| 332 |
+
|
| 333 |
+
#### Episode Not Starting
|
| 334 |
+
|
| 335 |
+
**Checklist:**
|
| 336 |
+
- [ ] Valid URL entered
|
| 337 |
+
- [ ] At least one agent selected
|
| 338 |
+
- [ ] API key configured
|
| 339 |
+
- [ ] System status shows "Online"
|
| 340 |
+
|
| 341 |
+
#### Slow Performance
|
| 342 |
+
|
| 343 |
+
**Tips:**
|
| 344 |
+
- Use Groq for faster inference
|
| 345 |
+
- Reduce enabled plugins
|
| 346 |
+
- Lower task complexity if possible
|
| 347 |
+
|
| 348 |
+
#### Memory Full
|
| 349 |
+
|
| 350 |
+
**Solution:** Clear memory layers in Settings > Advanced > Clear Cache
|
| 351 |
+
|
| 352 |
+
### Getting Help
|
| 353 |
+
|
| 354 |
+
- Check the logs panel for error details
|
| 355 |
+
- View episode history for past issues
|
| 356 |
+
- Report bugs on GitHub
|
| 357 |
+
|
| 358 |
+
---
|
| 359 |
+
|
| 360 |
+
## Keyboard Shortcuts
|
| 361 |
+
|
| 362 |
+
| Shortcut | Action |
|
| 363 |
+
|----------|--------|
|
| 364 |
+
| `Ctrl + Enter` | Start/Stop episode |
|
| 365 |
+
| `Ctrl + L` | Clear logs |
|
| 366 |
+
| `Ctrl + ,` | Open settings |
|
| 367 |
+
| `Escape` | Close popups |
|
| 368 |
+
|
| 369 |
+
---
|
| 370 |
+
|
| 371 |
+
## Version History
|
| 372 |
+
|
| 373 |
+
### v0.1.0 (Current)
|
| 374 |
+
|
| 375 |
+
- Initial release
|
| 376 |
+
- Multi-agent architecture
|
| 377 |
+
- Plugin system
|
| 378 |
+
- Memory layers
|
| 379 |
+
- Dashboard with real-time monitoring
|
| 380 |
+
|
| 381 |
+
---
|
| 382 |
+
|
| 383 |
+
*Documentation last updated: March 2026*
|
| 384 |
+
|
| 385 |
+
*Built with ❤️ by NeerajCodz*
|
|
@@ -12,8 +12,10 @@
|
|
| 12 |
"lucide-react": "^0.460.0",
|
| 13 |
"react": "^18.3.1",
|
| 14 |
"react-dom": "^18.3.1",
|
|
|
|
| 15 |
"react-router-dom": "^6.28.0",
|
| 16 |
-
"recharts": "^2.13.3"
|
|
|
|
| 17 |
},
|
| 18 |
"devDependencies": {
|
| 19 |
"@eslint/js": "^9.13.0",
|
|
@@ -2249,6 +2251,15 @@
|
|
| 2249 |
"integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==",
|
| 2250 |
"license": "MIT"
|
| 2251 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2252 |
"node_modules/@types/deep-eql": {
|
| 2253 |
"version": "4.0.2",
|
| 2254 |
"resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz",
|
|
@@ -2260,9 +2271,26 @@
|
|
| 2260 |
"version": "1.0.8",
|
| 2261 |
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
| 2262 |
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
|
| 2263 |
-
"dev": true,
|
| 2264 |
"license": "MIT"
|
| 2265 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2266 |
"node_modules/@types/json-schema": {
|
| 2267 |
"version": "7.0.15",
|
| 2268 |
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
|
@@ -2270,18 +2298,31 @@
|
|
| 2270 |
"dev": true,
|
| 2271 |
"license": "MIT"
|
| 2272 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2273 |
"node_modules/@types/prop-types": {
|
| 2274 |
"version": "15.7.15",
|
| 2275 |
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
|
| 2276 |
"integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==",
|
| 2277 |
-
"dev": true,
|
| 2278 |
"license": "MIT"
|
| 2279 |
},
|
| 2280 |
"node_modules/@types/react": {
|
| 2281 |
"version": "18.3.28",
|
| 2282 |
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz",
|
| 2283 |
"integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==",
|
| 2284 |
-
"dev": true,
|
| 2285 |
"license": "MIT",
|
| 2286 |
"peer": true,
|
| 2287 |
"dependencies": {
|
|
@@ -2300,6 +2341,12 @@
|
|
| 2300 |
"@types/react": "^18.0.0"
|
| 2301 |
}
|
| 2302 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2303 |
"node_modules/@typescript-eslint/eslint-plugin": {
|
| 2304 |
"version": "8.57.2",
|
| 2305 |
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.57.2.tgz",
|
|
@@ -2596,6 +2643,12 @@
|
|
| 2596 |
"url": "https://opencollective.com/eslint"
|
| 2597 |
}
|
| 2598 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2599 |
"node_modules/@vitejs/plugin-react": {
|
| 2600 |
"version": "4.7.0",
|
| 2601 |
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz",
|
|
@@ -2862,6 +2915,16 @@
|
|
| 2862 |
"postcss": "^8.1.0"
|
| 2863 |
}
|
| 2864 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2865 |
"node_modules/balanced-match": {
|
| 2866 |
"version": "1.0.2",
|
| 2867 |
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
|
@@ -3005,6 +3068,16 @@
|
|
| 3005 |
],
|
| 3006 |
"license": "CC-BY-4.0"
|
| 3007 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3008 |
"node_modules/chai": {
|
| 3009 |
"version": "6.2.2",
|
| 3010 |
"resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz",
|
|
@@ -3032,6 +3105,46 @@
|
|
| 3032 |
"url": "https://github.com/chalk/chalk?sponsor=1"
|
| 3033 |
}
|
| 3034 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3035 |
"node_modules/chokidar": {
|
| 3036 |
"version": "3.6.0",
|
| 3037 |
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
|
@@ -3099,6 +3212,16 @@
|
|
| 3099 |
"dev": true,
|
| 3100 |
"license": "MIT"
|
| 3101 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3102 |
"node_modules/commander": {
|
| 3103 |
"version": "4.1.1",
|
| 3104 |
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
|
|
@@ -3317,7 +3440,6 @@
|
|
| 3317 |
"version": "4.4.3",
|
| 3318 |
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
| 3319 |
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
| 3320 |
-
"dev": true,
|
| 3321 |
"license": "MIT",
|
| 3322 |
"dependencies": {
|
| 3323 |
"ms": "^2.1.3"
|
|
@@ -3344,6 +3466,19 @@
|
|
| 3344 |
"integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==",
|
| 3345 |
"license": "MIT"
|
| 3346 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3347 |
"node_modules/deep-is": {
|
| 3348 |
"version": "0.1.4",
|
| 3349 |
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
|
@@ -3355,7 +3490,6 @@
|
|
| 3355 |
"version": "2.0.3",
|
| 3356 |
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
|
| 3357 |
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
|
| 3358 |
-
"dev": true,
|
| 3359 |
"license": "MIT",
|
| 3360 |
"engines": {
|
| 3361 |
"node": ">=6"
|
|
@@ -3371,6 +3505,19 @@
|
|
| 3371 |
"node": ">=8"
|
| 3372 |
}
|
| 3373 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3374 |
"node_modules/didyoumean": {
|
| 3375 |
"version": "1.2.2",
|
| 3376 |
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
|
|
@@ -3659,6 +3806,16 @@
|
|
| 3659 |
"node": ">=4.0"
|
| 3660 |
}
|
| 3661 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3662 |
"node_modules/estree-walker": {
|
| 3663 |
"version": "3.0.3",
|
| 3664 |
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
|
|
@@ -3695,6 +3852,12 @@
|
|
| 3695 |
"node": ">=12.0.0"
|
| 3696 |
}
|
| 3697 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3698 |
"node_modules/fast-deep-equal": {
|
| 3699 |
"version": "3.1.3",
|
| 3700 |
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
|
@@ -3927,6 +4090,46 @@
|
|
| 3927 |
"node": ">= 0.4"
|
| 3928 |
}
|
| 3929 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3930 |
"node_modules/html-encoding-sniffer": {
|
| 3931 |
"version": "6.0.0",
|
| 3932 |
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz",
|
|
@@ -3940,6 +4143,16 @@
|
|
| 3940 |
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
| 3941 |
}
|
| 3942 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3943 |
"node_modules/ignore": {
|
| 3944 |
"version": "5.3.2",
|
| 3945 |
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
|
@@ -3987,6 +4200,12 @@
|
|
| 3987 |
"node": ">=8"
|
| 3988 |
}
|
| 3989 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3990 |
"node_modules/internmap": {
|
| 3991 |
"version": "2.0.3",
|
| 3992 |
"resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
|
|
@@ -3996,6 +4215,30 @@
|
|
| 3996 |
"node": ">=12"
|
| 3997 |
}
|
| 3998 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3999 |
"node_modules/is-binary-path": {
|
| 4000 |
"version": "2.1.0",
|
| 4001 |
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
|
@@ -4025,6 +4268,16 @@
|
|
| 4025 |
"url": "https://github.com/sponsors/ljharb"
|
| 4026 |
}
|
| 4027 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4028 |
"node_modules/is-extglob": {
|
| 4029 |
"version": "2.1.1",
|
| 4030 |
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
|
@@ -4048,6 +4301,16 @@
|
|
| 4048 |
"node": ">=0.10.0"
|
| 4049 |
}
|
| 4050 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4051 |
"node_modules/is-number": {
|
| 4052 |
"version": "7.0.0",
|
| 4053 |
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
|
@@ -4058,6 +4321,18 @@
|
|
| 4058 |
"node": ">=0.12.0"
|
| 4059 |
}
|
| 4060 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4061 |
"node_modules/is-potential-custom-element-name": {
|
| 4062 |
"version": "1.0.1",
|
| 4063 |
"resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
|
|
@@ -4535,6 +4810,16 @@
|
|
| 4535 |
"dev": true,
|
| 4536 |
"license": "MIT"
|
| 4537 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4538 |
"node_modules/loose-envify": {
|
| 4539 |
"version": "1.4.0",
|
| 4540 |
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
|
@@ -4586,102 +4871,956 @@
|
|
| 4586 |
"@jridgewell/sourcemap-codec": "^1.5.5"
|
| 4587 |
}
|
| 4588 |
},
|
| 4589 |
-
"node_modules/
|
| 4590 |
-
"version": "
|
| 4591 |
-
"resolved": "https://registry.npmjs.org/
|
| 4592 |
-
"integrity": "sha512-
|
| 4593 |
-
"dev": true,
|
| 4594 |
-
"license": "CC0-1.0"
|
| 4595 |
-
},
|
| 4596 |
-
"node_modules/merge2": {
|
| 4597 |
-
"version": "1.4.1",
|
| 4598 |
-
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
| 4599 |
-
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
|
| 4600 |
-
"dev": true,
|
| 4601 |
"license": "MIT",
|
| 4602 |
-
"
|
| 4603 |
-
"
|
|
|
|
| 4604 |
}
|
| 4605 |
},
|
| 4606 |
-
"node_modules/
|
| 4607 |
-
"version": "
|
| 4608 |
-
"resolved": "https://registry.npmjs.org/
|
| 4609 |
-
"integrity": "sha512-
|
| 4610 |
-
"dev": true,
|
| 4611 |
"license": "MIT",
|
| 4612 |
"dependencies": {
|
| 4613 |
-
"
|
| 4614 |
-
"
|
|
|
|
|
|
|
| 4615 |
},
|
| 4616 |
-
"
|
| 4617 |
-
"
|
|
|
|
| 4618 |
}
|
| 4619 |
},
|
| 4620 |
-
"node_modules/
|
| 4621 |
-
"version": "
|
| 4622 |
-
"resolved": "https://registry.npmjs.org/
|
| 4623 |
-
"integrity": "sha512-
|
| 4624 |
-
"dev": true,
|
| 4625 |
"license": "MIT",
|
| 4626 |
"engines": {
|
| 4627 |
-
"node": ">=
|
|
|
|
|
|
|
|
|
|
| 4628 |
}
|
| 4629 |
},
|
| 4630 |
-
"node_modules/
|
| 4631 |
-
"version": "
|
| 4632 |
-
"resolved": "https://registry.npmjs.org/
|
| 4633 |
-
"integrity": "sha512-
|
| 4634 |
-
"
|
| 4635 |
-
"
|
| 4636 |
-
|
| 4637 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4638 |
},
|
| 4639 |
-
"
|
| 4640 |
-
"
|
|
|
|
| 4641 |
}
|
| 4642 |
},
|
| 4643 |
-
"node_modules/
|
| 4644 |
-
"version": "
|
| 4645 |
-
"resolved": "https://registry.npmjs.org/
|
| 4646 |
-
"integrity": "sha512-
|
| 4647 |
-
"dev": true,
|
| 4648 |
-
"license": "MIT"
|
| 4649 |
-
},
|
| 4650 |
-
"node_modules/mz": {
|
| 4651 |
-
"version": "2.7.0",
|
| 4652 |
-
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
|
| 4653 |
-
"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
|
| 4654 |
-
"dev": true,
|
| 4655 |
"license": "MIT",
|
| 4656 |
"dependencies": {
|
| 4657 |
-
"
|
| 4658 |
-
"
|
| 4659 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4660 |
}
|
| 4661 |
},
|
| 4662 |
-
"node_modules/
|
| 4663 |
-
"version": "
|
| 4664 |
-
"resolved": "https://registry.npmjs.org/
|
| 4665 |
-
"integrity": "sha512-
|
| 4666 |
-
"dev": true,
|
| 4667 |
-
"funding": [
|
| 4668 |
-
{
|
| 4669 |
-
"type": "github",
|
| 4670 |
-
"url": "https://github.com/sponsors/ai"
|
| 4671 |
-
}
|
| 4672 |
-
],
|
| 4673 |
"license": "MIT",
|
| 4674 |
-
"
|
| 4675 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4676 |
},
|
| 4677 |
-
"
|
| 4678 |
-
"
|
|
|
|
| 4679 |
}
|
| 4680 |
},
|
| 4681 |
-
"node_modules/
|
| 4682 |
-
"version": "1.
|
| 4683 |
-
"resolved": "https://registry.npmjs.org/
|
| 4684 |
-
"integrity": "sha512-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4685 |
"dev": true,
|
| 4686 |
"license": "MIT"
|
| 4687 |
},
|
|
@@ -4795,6 +5934,31 @@
|
|
| 4795 |
"node": ">=6"
|
| 4796 |
}
|
| 4797 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4798 |
"node_modules/parse5": {
|
| 4799 |
"version": "8.0.0",
|
| 4800 |
"resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz",
|
|
@@ -5101,6 +6265,16 @@
|
|
| 5101 |
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
| 5102 |
"license": "MIT"
|
| 5103 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5104 |
"node_modules/punycode": {
|
| 5105 |
"version": "2.3.1",
|
| 5106 |
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
|
@@ -5166,6 +6340,33 @@
|
|
| 5166 |
"dev": true,
|
| 5167 |
"license": "MIT"
|
| 5168 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5169 |
"node_modules/react-refresh": {
|
| 5170 |
"version": "0.17.0",
|
| 5171 |
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
|
|
@@ -5314,6 +6515,72 @@
|
|
| 5314 |
"node": ">=8"
|
| 5315 |
}
|
| 5316 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5317 |
"node_modules/require-from-string": {
|
| 5318 |
"version": "2.0.2",
|
| 5319 |
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
|
@@ -5548,6 +6815,16 @@
|
|
| 5548 |
"node": ">=0.10.0"
|
| 5549 |
}
|
| 5550 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5551 |
"node_modules/stackback": {
|
| 5552 |
"version": "0.0.2",
|
| 5553 |
"resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
|
|
@@ -5562,6 +6839,20 @@
|
|
| 5562 |
"dev": true,
|
| 5563 |
"license": "MIT"
|
| 5564 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5565 |
"node_modules/strip-indent": {
|
| 5566 |
"version": "3.0.0",
|
| 5567 |
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
|
|
@@ -5588,6 +6879,24 @@
|
|
| 5588 |
"url": "https://github.com/sponsors/sindresorhus"
|
| 5589 |
}
|
| 5590 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5591 |
"node_modules/sucrase": {
|
| 5592 |
"version": "3.35.1",
|
| 5593 |
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz",
|
|
@@ -5846,6 +7155,26 @@
|
|
| 5846 |
"node": ">=20"
|
| 5847 |
}
|
| 5848 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5849 |
"node_modules/ts-api-utils": {
|
| 5850 |
"version": "2.5.0",
|
| 5851 |
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz",
|
|
@@ -5936,6 +7265,93 @@
|
|
| 5936 |
"node": ">=20.18.1"
|
| 5937 |
}
|
| 5938 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5939 |
"node_modules/update-browserslist-db": {
|
| 5940 |
"version": "1.2.3",
|
| 5941 |
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
|
|
@@ -5984,6 +7400,34 @@
|
|
| 5984 |
"dev": true,
|
| 5985 |
"license": "MIT"
|
| 5986 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5987 |
"node_modules/victory-vendor": {
|
| 5988 |
"version": "36.9.2",
|
| 5989 |
"resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz",
|
|
@@ -6830,6 +8274,16 @@
|
|
| 6830 |
"funding": {
|
| 6831 |
"url": "https://github.com/sponsors/sindresorhus"
|
| 6832 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6833 |
}
|
| 6834 |
}
|
| 6835 |
}
|
|
|
|
| 12 |
"lucide-react": "^0.460.0",
|
| 13 |
"react": "^18.3.1",
|
| 14 |
"react-dom": "^18.3.1",
|
| 15 |
+
"react-markdown": "^10.1.0",
|
| 16 |
"react-router-dom": "^6.28.0",
|
| 17 |
+
"recharts": "^2.13.3",
|
| 18 |
+
"remark-gfm": "^4.0.1"
|
| 19 |
},
|
| 20 |
"devDependencies": {
|
| 21 |
"@eslint/js": "^9.13.0",
|
|
|
|
| 2251 |
"integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==",
|
| 2252 |
"license": "MIT"
|
| 2253 |
},
|
| 2254 |
+
"node_modules/@types/debug": {
|
| 2255 |
+
"version": "4.1.13",
|
| 2256 |
+
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz",
|
| 2257 |
+
"integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==",
|
| 2258 |
+
"license": "MIT",
|
| 2259 |
+
"dependencies": {
|
| 2260 |
+
"@types/ms": "*"
|
| 2261 |
+
}
|
| 2262 |
+
},
|
| 2263 |
"node_modules/@types/deep-eql": {
|
| 2264 |
"version": "4.0.2",
|
| 2265 |
"resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz",
|
|
|
|
| 2271 |
"version": "1.0.8",
|
| 2272 |
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
| 2273 |
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
|
|
|
|
| 2274 |
"license": "MIT"
|
| 2275 |
},
|
| 2276 |
+
"node_modules/@types/estree-jsx": {
|
| 2277 |
+
"version": "1.0.5",
|
| 2278 |
+
"resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz",
|
| 2279 |
+
"integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==",
|
| 2280 |
+
"license": "MIT",
|
| 2281 |
+
"dependencies": {
|
| 2282 |
+
"@types/estree": "*"
|
| 2283 |
+
}
|
| 2284 |
+
},
|
| 2285 |
+
"node_modules/@types/hast": {
|
| 2286 |
+
"version": "3.0.4",
|
| 2287 |
+
"resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
|
| 2288 |
+
"integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==",
|
| 2289 |
+
"license": "MIT",
|
| 2290 |
+
"dependencies": {
|
| 2291 |
+
"@types/unist": "*"
|
| 2292 |
+
}
|
| 2293 |
+
},
|
| 2294 |
"node_modules/@types/json-schema": {
|
| 2295 |
"version": "7.0.15",
|
| 2296 |
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
|
|
|
| 2298 |
"dev": true,
|
| 2299 |
"license": "MIT"
|
| 2300 |
},
|
| 2301 |
+
"node_modules/@types/mdast": {
|
| 2302 |
+
"version": "4.0.4",
|
| 2303 |
+
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
|
| 2304 |
+
"integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==",
|
| 2305 |
+
"license": "MIT",
|
| 2306 |
+
"dependencies": {
|
| 2307 |
+
"@types/unist": "*"
|
| 2308 |
+
}
|
| 2309 |
+
},
|
| 2310 |
+
"node_modules/@types/ms": {
|
| 2311 |
+
"version": "2.1.0",
|
| 2312 |
+
"resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
|
| 2313 |
+
"integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==",
|
| 2314 |
+
"license": "MIT"
|
| 2315 |
+
},
|
| 2316 |
"node_modules/@types/prop-types": {
|
| 2317 |
"version": "15.7.15",
|
| 2318 |
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
|
| 2319 |
"integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==",
|
|
|
|
| 2320 |
"license": "MIT"
|
| 2321 |
},
|
| 2322 |
"node_modules/@types/react": {
|
| 2323 |
"version": "18.3.28",
|
| 2324 |
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz",
|
| 2325 |
"integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==",
|
|
|
|
| 2326 |
"license": "MIT",
|
| 2327 |
"peer": true,
|
| 2328 |
"dependencies": {
|
|
|
|
| 2341 |
"@types/react": "^18.0.0"
|
| 2342 |
}
|
| 2343 |
},
|
| 2344 |
+
"node_modules/@types/unist": {
|
| 2345 |
+
"version": "3.0.3",
|
| 2346 |
+
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
|
| 2347 |
+
"integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
|
| 2348 |
+
"license": "MIT"
|
| 2349 |
+
},
|
| 2350 |
"node_modules/@typescript-eslint/eslint-plugin": {
|
| 2351 |
"version": "8.57.2",
|
| 2352 |
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.57.2.tgz",
|
|
|
|
| 2643 |
"url": "https://opencollective.com/eslint"
|
| 2644 |
}
|
| 2645 |
},
|
| 2646 |
+
"node_modules/@ungap/structured-clone": {
|
| 2647 |
+
"version": "1.3.0",
|
| 2648 |
+
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
|
| 2649 |
+
"integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
|
| 2650 |
+
"license": "ISC"
|
| 2651 |
+
},
|
| 2652 |
"node_modules/@vitejs/plugin-react": {
|
| 2653 |
"version": "4.7.0",
|
| 2654 |
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz",
|
|
|
|
| 2915 |
"postcss": "^8.1.0"
|
| 2916 |
}
|
| 2917 |
},
|
| 2918 |
+
"node_modules/bail": {
|
| 2919 |
+
"version": "2.0.2",
|
| 2920 |
+
"resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
|
| 2921 |
+
"integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==",
|
| 2922 |
+
"license": "MIT",
|
| 2923 |
+
"funding": {
|
| 2924 |
+
"type": "github",
|
| 2925 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 2926 |
+
}
|
| 2927 |
+
},
|
| 2928 |
"node_modules/balanced-match": {
|
| 2929 |
"version": "1.0.2",
|
| 2930 |
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
|
|
|
| 3068 |
],
|
| 3069 |
"license": "CC-BY-4.0"
|
| 3070 |
},
|
| 3071 |
+
"node_modules/ccount": {
|
| 3072 |
+
"version": "2.0.1",
|
| 3073 |
+
"resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
|
| 3074 |
+
"integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==",
|
| 3075 |
+
"license": "MIT",
|
| 3076 |
+
"funding": {
|
| 3077 |
+
"type": "github",
|
| 3078 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 3079 |
+
}
|
| 3080 |
+
},
|
| 3081 |
"node_modules/chai": {
|
| 3082 |
"version": "6.2.2",
|
| 3083 |
"resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz",
|
|
|
|
| 3105 |
"url": "https://github.com/chalk/chalk?sponsor=1"
|
| 3106 |
}
|
| 3107 |
},
|
| 3108 |
+
"node_modules/character-entities": {
|
| 3109 |
+
"version": "2.0.2",
|
| 3110 |
+
"resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz",
|
| 3111 |
+
"integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==",
|
| 3112 |
+
"license": "MIT",
|
| 3113 |
+
"funding": {
|
| 3114 |
+
"type": "github",
|
| 3115 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 3116 |
+
}
|
| 3117 |
+
},
|
| 3118 |
+
"node_modules/character-entities-html4": {
|
| 3119 |
+
"version": "2.1.0",
|
| 3120 |
+
"resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz",
|
| 3121 |
+
"integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==",
|
| 3122 |
+
"license": "MIT",
|
| 3123 |
+
"funding": {
|
| 3124 |
+
"type": "github",
|
| 3125 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 3126 |
+
}
|
| 3127 |
+
},
|
| 3128 |
+
"node_modules/character-entities-legacy": {
|
| 3129 |
+
"version": "3.0.0",
|
| 3130 |
+
"resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz",
|
| 3131 |
+
"integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==",
|
| 3132 |
+
"license": "MIT",
|
| 3133 |
+
"funding": {
|
| 3134 |
+
"type": "github",
|
| 3135 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 3136 |
+
}
|
| 3137 |
+
},
|
| 3138 |
+
"node_modules/character-reference-invalid": {
|
| 3139 |
+
"version": "2.0.1",
|
| 3140 |
+
"resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz",
|
| 3141 |
+
"integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==",
|
| 3142 |
+
"license": "MIT",
|
| 3143 |
+
"funding": {
|
| 3144 |
+
"type": "github",
|
| 3145 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 3146 |
+
}
|
| 3147 |
+
},
|
| 3148 |
"node_modules/chokidar": {
|
| 3149 |
"version": "3.6.0",
|
| 3150 |
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
|
|
|
| 3212 |
"dev": true,
|
| 3213 |
"license": "MIT"
|
| 3214 |
},
|
| 3215 |
+
"node_modules/comma-separated-tokens": {
|
| 3216 |
+
"version": "2.0.3",
|
| 3217 |
+
"resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
|
| 3218 |
+
"integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==",
|
| 3219 |
+
"license": "MIT",
|
| 3220 |
+
"funding": {
|
| 3221 |
+
"type": "github",
|
| 3222 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 3223 |
+
}
|
| 3224 |
+
},
|
| 3225 |
"node_modules/commander": {
|
| 3226 |
"version": "4.1.1",
|
| 3227 |
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
|
|
|
|
| 3440 |
"version": "4.4.3",
|
| 3441 |
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
| 3442 |
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
|
|
|
| 3443 |
"license": "MIT",
|
| 3444 |
"dependencies": {
|
| 3445 |
"ms": "^2.1.3"
|
|
|
|
| 3466 |
"integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==",
|
| 3467 |
"license": "MIT"
|
| 3468 |
},
|
| 3469 |
+
"node_modules/decode-named-character-reference": {
|
| 3470 |
+
"version": "1.3.0",
|
| 3471 |
+
"resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz",
|
| 3472 |
+
"integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==",
|
| 3473 |
+
"license": "MIT",
|
| 3474 |
+
"dependencies": {
|
| 3475 |
+
"character-entities": "^2.0.0"
|
| 3476 |
+
},
|
| 3477 |
+
"funding": {
|
| 3478 |
+
"type": "github",
|
| 3479 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 3480 |
+
}
|
| 3481 |
+
},
|
| 3482 |
"node_modules/deep-is": {
|
| 3483 |
"version": "0.1.4",
|
| 3484 |
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
|
|
|
| 3490 |
"version": "2.0.3",
|
| 3491 |
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
|
| 3492 |
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
|
|
|
|
| 3493 |
"license": "MIT",
|
| 3494 |
"engines": {
|
| 3495 |
"node": ">=6"
|
|
|
|
| 3505 |
"node": ">=8"
|
| 3506 |
}
|
| 3507 |
},
|
| 3508 |
+
"node_modules/devlop": {
|
| 3509 |
+
"version": "1.1.0",
|
| 3510 |
+
"resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
|
| 3511 |
+
"integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==",
|
| 3512 |
+
"license": "MIT",
|
| 3513 |
+
"dependencies": {
|
| 3514 |
+
"dequal": "^2.0.0"
|
| 3515 |
+
},
|
| 3516 |
+
"funding": {
|
| 3517 |
+
"type": "github",
|
| 3518 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 3519 |
+
}
|
| 3520 |
+
},
|
| 3521 |
"node_modules/didyoumean": {
|
| 3522 |
"version": "1.2.2",
|
| 3523 |
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
|
|
|
|
| 3806 |
"node": ">=4.0"
|
| 3807 |
}
|
| 3808 |
},
|
| 3809 |
+
"node_modules/estree-util-is-identifier-name": {
|
| 3810 |
+
"version": "3.0.0",
|
| 3811 |
+
"resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz",
|
| 3812 |
+
"integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==",
|
| 3813 |
+
"license": "MIT",
|
| 3814 |
+
"funding": {
|
| 3815 |
+
"type": "opencollective",
|
| 3816 |
+
"url": "https://opencollective.com/unified"
|
| 3817 |
+
}
|
| 3818 |
+
},
|
| 3819 |
"node_modules/estree-walker": {
|
| 3820 |
"version": "3.0.3",
|
| 3821 |
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
|
|
|
|
| 3852 |
"node": ">=12.0.0"
|
| 3853 |
}
|
| 3854 |
},
|
| 3855 |
+
"node_modules/extend": {
|
| 3856 |
+
"version": "3.0.2",
|
| 3857 |
+
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
| 3858 |
+
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
|
| 3859 |
+
"license": "MIT"
|
| 3860 |
+
},
|
| 3861 |
"node_modules/fast-deep-equal": {
|
| 3862 |
"version": "3.1.3",
|
| 3863 |
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
|
|
|
| 4090 |
"node": ">= 0.4"
|
| 4091 |
}
|
| 4092 |
},
|
| 4093 |
+
"node_modules/hast-util-to-jsx-runtime": {
|
| 4094 |
+
"version": "2.3.6",
|
| 4095 |
+
"resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz",
|
| 4096 |
+
"integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==",
|
| 4097 |
+
"license": "MIT",
|
| 4098 |
+
"dependencies": {
|
| 4099 |
+
"@types/estree": "^1.0.0",
|
| 4100 |
+
"@types/hast": "^3.0.0",
|
| 4101 |
+
"@types/unist": "^3.0.0",
|
| 4102 |
+
"comma-separated-tokens": "^2.0.0",
|
| 4103 |
+
"devlop": "^1.0.0",
|
| 4104 |
+
"estree-util-is-identifier-name": "^3.0.0",
|
| 4105 |
+
"hast-util-whitespace": "^3.0.0",
|
| 4106 |
+
"mdast-util-mdx-expression": "^2.0.0",
|
| 4107 |
+
"mdast-util-mdx-jsx": "^3.0.0",
|
| 4108 |
+
"mdast-util-mdxjs-esm": "^2.0.0",
|
| 4109 |
+
"property-information": "^7.0.0",
|
| 4110 |
+
"space-separated-tokens": "^2.0.0",
|
| 4111 |
+
"style-to-js": "^1.0.0",
|
| 4112 |
+
"unist-util-position": "^5.0.0",
|
| 4113 |
+
"vfile-message": "^4.0.0"
|
| 4114 |
+
},
|
| 4115 |
+
"funding": {
|
| 4116 |
+
"type": "opencollective",
|
| 4117 |
+
"url": "https://opencollective.com/unified"
|
| 4118 |
+
}
|
| 4119 |
+
},
|
| 4120 |
+
"node_modules/hast-util-whitespace": {
|
| 4121 |
+
"version": "3.0.0",
|
| 4122 |
+
"resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz",
|
| 4123 |
+
"integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==",
|
| 4124 |
+
"license": "MIT",
|
| 4125 |
+
"dependencies": {
|
| 4126 |
+
"@types/hast": "^3.0.0"
|
| 4127 |
+
},
|
| 4128 |
+
"funding": {
|
| 4129 |
+
"type": "opencollective",
|
| 4130 |
+
"url": "https://opencollective.com/unified"
|
| 4131 |
+
}
|
| 4132 |
+
},
|
| 4133 |
"node_modules/html-encoding-sniffer": {
|
| 4134 |
"version": "6.0.0",
|
| 4135 |
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz",
|
|
|
|
| 4143 |
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
| 4144 |
}
|
| 4145 |
},
|
| 4146 |
+
"node_modules/html-url-attributes": {
|
| 4147 |
+
"version": "3.0.1",
|
| 4148 |
+
"resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz",
|
| 4149 |
+
"integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==",
|
| 4150 |
+
"license": "MIT",
|
| 4151 |
+
"funding": {
|
| 4152 |
+
"type": "opencollective",
|
| 4153 |
+
"url": "https://opencollective.com/unified"
|
| 4154 |
+
}
|
| 4155 |
+
},
|
| 4156 |
"node_modules/ignore": {
|
| 4157 |
"version": "5.3.2",
|
| 4158 |
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
|
|
|
| 4200 |
"node": ">=8"
|
| 4201 |
}
|
| 4202 |
},
|
| 4203 |
+
"node_modules/inline-style-parser": {
|
| 4204 |
+
"version": "0.2.7",
|
| 4205 |
+
"resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz",
|
| 4206 |
+
"integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==",
|
| 4207 |
+
"license": "MIT"
|
| 4208 |
+
},
|
| 4209 |
"node_modules/internmap": {
|
| 4210 |
"version": "2.0.3",
|
| 4211 |
"resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
|
|
|
|
| 4215 |
"node": ">=12"
|
| 4216 |
}
|
| 4217 |
},
|
| 4218 |
+
"node_modules/is-alphabetical": {
|
| 4219 |
+
"version": "2.0.1",
|
| 4220 |
+
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
|
| 4221 |
+
"integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==",
|
| 4222 |
+
"license": "MIT",
|
| 4223 |
+
"funding": {
|
| 4224 |
+
"type": "github",
|
| 4225 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 4226 |
+
}
|
| 4227 |
+
},
|
| 4228 |
+
"node_modules/is-alphanumerical": {
|
| 4229 |
+
"version": "2.0.1",
|
| 4230 |
+
"resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz",
|
| 4231 |
+
"integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==",
|
| 4232 |
+
"license": "MIT",
|
| 4233 |
+
"dependencies": {
|
| 4234 |
+
"is-alphabetical": "^2.0.0",
|
| 4235 |
+
"is-decimal": "^2.0.0"
|
| 4236 |
+
},
|
| 4237 |
+
"funding": {
|
| 4238 |
+
"type": "github",
|
| 4239 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 4240 |
+
}
|
| 4241 |
+
},
|
| 4242 |
"node_modules/is-binary-path": {
|
| 4243 |
"version": "2.1.0",
|
| 4244 |
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
|
|
|
| 4268 |
"url": "https://github.com/sponsors/ljharb"
|
| 4269 |
}
|
| 4270 |
},
|
| 4271 |
+
"node_modules/is-decimal": {
|
| 4272 |
+
"version": "2.0.1",
|
| 4273 |
+
"resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz",
|
| 4274 |
+
"integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==",
|
| 4275 |
+
"license": "MIT",
|
| 4276 |
+
"funding": {
|
| 4277 |
+
"type": "github",
|
| 4278 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 4279 |
+
}
|
| 4280 |
+
},
|
| 4281 |
"node_modules/is-extglob": {
|
| 4282 |
"version": "2.1.1",
|
| 4283 |
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
|
|
|
| 4301 |
"node": ">=0.10.0"
|
| 4302 |
}
|
| 4303 |
},
|
| 4304 |
+
"node_modules/is-hexadecimal": {
|
| 4305 |
+
"version": "2.0.1",
|
| 4306 |
+
"resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz",
|
| 4307 |
+
"integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==",
|
| 4308 |
+
"license": "MIT",
|
| 4309 |
+
"funding": {
|
| 4310 |
+
"type": "github",
|
| 4311 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 4312 |
+
}
|
| 4313 |
+
},
|
| 4314 |
"node_modules/is-number": {
|
| 4315 |
"version": "7.0.0",
|
| 4316 |
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
|
|
|
| 4321 |
"node": ">=0.12.0"
|
| 4322 |
}
|
| 4323 |
},
|
| 4324 |
+
"node_modules/is-plain-obj": {
|
| 4325 |
+
"version": "4.1.0",
|
| 4326 |
+
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
|
| 4327 |
+
"integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
|
| 4328 |
+
"license": "MIT",
|
| 4329 |
+
"engines": {
|
| 4330 |
+
"node": ">=12"
|
| 4331 |
+
},
|
| 4332 |
+
"funding": {
|
| 4333 |
+
"url": "https://github.com/sponsors/sindresorhus"
|
| 4334 |
+
}
|
| 4335 |
+
},
|
| 4336 |
"node_modules/is-potential-custom-element-name": {
|
| 4337 |
"version": "1.0.1",
|
| 4338 |
"resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
|
|
|
|
| 4810 |
"dev": true,
|
| 4811 |
"license": "MIT"
|
| 4812 |
},
|
| 4813 |
+
"node_modules/longest-streak": {
|
| 4814 |
+
"version": "3.1.0",
|
| 4815 |
+
"resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz",
|
| 4816 |
+
"integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==",
|
| 4817 |
+
"license": "MIT",
|
| 4818 |
+
"funding": {
|
| 4819 |
+
"type": "github",
|
| 4820 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 4821 |
+
}
|
| 4822 |
+
},
|
| 4823 |
"node_modules/loose-envify": {
|
| 4824 |
"version": "1.4.0",
|
| 4825 |
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
|
|
|
| 4871 |
"@jridgewell/sourcemap-codec": "^1.5.5"
|
| 4872 |
}
|
| 4873 |
},
|
| 4874 |
+
"node_modules/markdown-table": {
|
| 4875 |
+
"version": "3.0.4",
|
| 4876 |
+
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz",
|
| 4877 |
+
"integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4878 |
"license": "MIT",
|
| 4879 |
+
"funding": {
|
| 4880 |
+
"type": "github",
|
| 4881 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 4882 |
}
|
| 4883 |
},
|
| 4884 |
+
"node_modules/mdast-util-find-and-replace": {
|
| 4885 |
+
"version": "3.0.2",
|
| 4886 |
+
"resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz",
|
| 4887 |
+
"integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==",
|
|
|
|
| 4888 |
"license": "MIT",
|
| 4889 |
"dependencies": {
|
| 4890 |
+
"@types/mdast": "^4.0.0",
|
| 4891 |
+
"escape-string-regexp": "^5.0.0",
|
| 4892 |
+
"unist-util-is": "^6.0.0",
|
| 4893 |
+
"unist-util-visit-parents": "^6.0.0"
|
| 4894 |
},
|
| 4895 |
+
"funding": {
|
| 4896 |
+
"type": "opencollective",
|
| 4897 |
+
"url": "https://opencollective.com/unified"
|
| 4898 |
}
|
| 4899 |
},
|
| 4900 |
+
"node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": {
|
| 4901 |
+
"version": "5.0.0",
|
| 4902 |
+
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
|
| 4903 |
+
"integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
|
|
|
|
| 4904 |
"license": "MIT",
|
| 4905 |
"engines": {
|
| 4906 |
+
"node": ">=12"
|
| 4907 |
+
},
|
| 4908 |
+
"funding": {
|
| 4909 |
+
"url": "https://github.com/sponsors/sindresorhus"
|
| 4910 |
}
|
| 4911 |
},
|
| 4912 |
+
"node_modules/mdast-util-from-markdown": {
|
| 4913 |
+
"version": "2.0.3",
|
| 4914 |
+
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz",
|
| 4915 |
+
"integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==",
|
| 4916 |
+
"license": "MIT",
|
| 4917 |
+
"dependencies": {
|
| 4918 |
+
"@types/mdast": "^4.0.0",
|
| 4919 |
+
"@types/unist": "^3.0.0",
|
| 4920 |
+
"decode-named-character-reference": "^1.0.0",
|
| 4921 |
+
"devlop": "^1.0.0",
|
| 4922 |
+
"mdast-util-to-string": "^4.0.0",
|
| 4923 |
+
"micromark": "^4.0.0",
|
| 4924 |
+
"micromark-util-decode-numeric-character-reference": "^2.0.0",
|
| 4925 |
+
"micromark-util-decode-string": "^2.0.0",
|
| 4926 |
+
"micromark-util-normalize-identifier": "^2.0.0",
|
| 4927 |
+
"micromark-util-symbol": "^2.0.0",
|
| 4928 |
+
"micromark-util-types": "^2.0.0",
|
| 4929 |
+
"unist-util-stringify-position": "^4.0.0"
|
| 4930 |
},
|
| 4931 |
+
"funding": {
|
| 4932 |
+
"type": "opencollective",
|
| 4933 |
+
"url": "https://opencollective.com/unified"
|
| 4934 |
}
|
| 4935 |
},
|
| 4936 |
+
"node_modules/mdast-util-gfm": {
|
| 4937 |
+
"version": "3.1.0",
|
| 4938 |
+
"resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz",
|
| 4939 |
+
"integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4940 |
"license": "MIT",
|
| 4941 |
"dependencies": {
|
| 4942 |
+
"mdast-util-from-markdown": "^2.0.0",
|
| 4943 |
+
"mdast-util-gfm-autolink-literal": "^2.0.0",
|
| 4944 |
+
"mdast-util-gfm-footnote": "^2.0.0",
|
| 4945 |
+
"mdast-util-gfm-strikethrough": "^2.0.0",
|
| 4946 |
+
"mdast-util-gfm-table": "^2.0.0",
|
| 4947 |
+
"mdast-util-gfm-task-list-item": "^2.0.0",
|
| 4948 |
+
"mdast-util-to-markdown": "^2.0.0"
|
| 4949 |
+
},
|
| 4950 |
+
"funding": {
|
| 4951 |
+
"type": "opencollective",
|
| 4952 |
+
"url": "https://opencollective.com/unified"
|
| 4953 |
}
|
| 4954 |
},
|
| 4955 |
+
"node_modules/mdast-util-gfm-autolink-literal": {
|
| 4956 |
+
"version": "2.0.1",
|
| 4957 |
+
"resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz",
|
| 4958 |
+
"integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4959 |
"license": "MIT",
|
| 4960 |
+
"dependencies": {
|
| 4961 |
+
"@types/mdast": "^4.0.0",
|
| 4962 |
+
"ccount": "^2.0.0",
|
| 4963 |
+
"devlop": "^1.0.0",
|
| 4964 |
+
"mdast-util-find-and-replace": "^3.0.0",
|
| 4965 |
+
"micromark-util-character": "^2.0.0"
|
| 4966 |
},
|
| 4967 |
+
"funding": {
|
| 4968 |
+
"type": "opencollective",
|
| 4969 |
+
"url": "https://opencollective.com/unified"
|
| 4970 |
}
|
| 4971 |
},
|
| 4972 |
+
"node_modules/mdast-util-gfm-footnote": {
|
| 4973 |
+
"version": "2.1.0",
|
| 4974 |
+
"resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz",
|
| 4975 |
+
"integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==",
|
| 4976 |
+
"license": "MIT",
|
| 4977 |
+
"dependencies": {
|
| 4978 |
+
"@types/mdast": "^4.0.0",
|
| 4979 |
+
"devlop": "^1.1.0",
|
| 4980 |
+
"mdast-util-from-markdown": "^2.0.0",
|
| 4981 |
+
"mdast-util-to-markdown": "^2.0.0",
|
| 4982 |
+
"micromark-util-normalize-identifier": "^2.0.0"
|
| 4983 |
+
},
|
| 4984 |
+
"funding": {
|
| 4985 |
+
"type": "opencollective",
|
| 4986 |
+
"url": "https://opencollective.com/unified"
|
| 4987 |
+
}
|
| 4988 |
+
},
|
| 4989 |
+
"node_modules/mdast-util-gfm-strikethrough": {
|
| 4990 |
+
"version": "2.0.0",
|
| 4991 |
+
"resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz",
|
| 4992 |
+
"integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==",
|
| 4993 |
+
"license": "MIT",
|
| 4994 |
+
"dependencies": {
|
| 4995 |
+
"@types/mdast": "^4.0.0",
|
| 4996 |
+
"mdast-util-from-markdown": "^2.0.0",
|
| 4997 |
+
"mdast-util-to-markdown": "^2.0.0"
|
| 4998 |
+
},
|
| 4999 |
+
"funding": {
|
| 5000 |
+
"type": "opencollective",
|
| 5001 |
+
"url": "https://opencollective.com/unified"
|
| 5002 |
+
}
|
| 5003 |
+
},
|
| 5004 |
+
"node_modules/mdast-util-gfm-table": {
|
| 5005 |
+
"version": "2.0.0",
|
| 5006 |
+
"resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz",
|
| 5007 |
+
"integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==",
|
| 5008 |
+
"license": "MIT",
|
| 5009 |
+
"dependencies": {
|
| 5010 |
+
"@types/mdast": "^4.0.0",
|
| 5011 |
+
"devlop": "^1.0.0",
|
| 5012 |
+
"markdown-table": "^3.0.0",
|
| 5013 |
+
"mdast-util-from-markdown": "^2.0.0",
|
| 5014 |
+
"mdast-util-to-markdown": "^2.0.0"
|
| 5015 |
+
},
|
| 5016 |
+
"funding": {
|
| 5017 |
+
"type": "opencollective",
|
| 5018 |
+
"url": "https://opencollective.com/unified"
|
| 5019 |
+
}
|
| 5020 |
+
},
|
| 5021 |
+
"node_modules/mdast-util-gfm-task-list-item": {
|
| 5022 |
+
"version": "2.0.0",
|
| 5023 |
+
"resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz",
|
| 5024 |
+
"integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==",
|
| 5025 |
+
"license": "MIT",
|
| 5026 |
+
"dependencies": {
|
| 5027 |
+
"@types/mdast": "^4.0.0",
|
| 5028 |
+
"devlop": "^1.0.0",
|
| 5029 |
+
"mdast-util-from-markdown": "^2.0.0",
|
| 5030 |
+
"mdast-util-to-markdown": "^2.0.0"
|
| 5031 |
+
},
|
| 5032 |
+
"funding": {
|
| 5033 |
+
"type": "opencollective",
|
| 5034 |
+
"url": "https://opencollective.com/unified"
|
| 5035 |
+
}
|
| 5036 |
+
},
|
| 5037 |
+
"node_modules/mdast-util-mdx-expression": {
|
| 5038 |
+
"version": "2.0.1",
|
| 5039 |
+
"resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz",
|
| 5040 |
+
"integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==",
|
| 5041 |
+
"license": "MIT",
|
| 5042 |
+
"dependencies": {
|
| 5043 |
+
"@types/estree-jsx": "^1.0.0",
|
| 5044 |
+
"@types/hast": "^3.0.0",
|
| 5045 |
+
"@types/mdast": "^4.0.0",
|
| 5046 |
+
"devlop": "^1.0.0",
|
| 5047 |
+
"mdast-util-from-markdown": "^2.0.0",
|
| 5048 |
+
"mdast-util-to-markdown": "^2.0.0"
|
| 5049 |
+
},
|
| 5050 |
+
"funding": {
|
| 5051 |
+
"type": "opencollective",
|
| 5052 |
+
"url": "https://opencollective.com/unified"
|
| 5053 |
+
}
|
| 5054 |
+
},
|
| 5055 |
+
"node_modules/mdast-util-mdx-jsx": {
|
| 5056 |
+
"version": "3.2.0",
|
| 5057 |
+
"resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz",
|
| 5058 |
+
"integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==",
|
| 5059 |
+
"license": "MIT",
|
| 5060 |
+
"dependencies": {
|
| 5061 |
+
"@types/estree-jsx": "^1.0.0",
|
| 5062 |
+
"@types/hast": "^3.0.0",
|
| 5063 |
+
"@types/mdast": "^4.0.0",
|
| 5064 |
+
"@types/unist": "^3.0.0",
|
| 5065 |
+
"ccount": "^2.0.0",
|
| 5066 |
+
"devlop": "^1.1.0",
|
| 5067 |
+
"mdast-util-from-markdown": "^2.0.0",
|
| 5068 |
+
"mdast-util-to-markdown": "^2.0.0",
|
| 5069 |
+
"parse-entities": "^4.0.0",
|
| 5070 |
+
"stringify-entities": "^4.0.0",
|
| 5071 |
+
"unist-util-stringify-position": "^4.0.0",
|
| 5072 |
+
"vfile-message": "^4.0.0"
|
| 5073 |
+
},
|
| 5074 |
+
"funding": {
|
| 5075 |
+
"type": "opencollective",
|
| 5076 |
+
"url": "https://opencollective.com/unified"
|
| 5077 |
+
}
|
| 5078 |
+
},
|
| 5079 |
+
"node_modules/mdast-util-mdxjs-esm": {
|
| 5080 |
+
"version": "2.0.1",
|
| 5081 |
+
"resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz",
|
| 5082 |
+
"integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==",
|
| 5083 |
+
"license": "MIT",
|
| 5084 |
+
"dependencies": {
|
| 5085 |
+
"@types/estree-jsx": "^1.0.0",
|
| 5086 |
+
"@types/hast": "^3.0.0",
|
| 5087 |
+
"@types/mdast": "^4.0.0",
|
| 5088 |
+
"devlop": "^1.0.0",
|
| 5089 |
+
"mdast-util-from-markdown": "^2.0.0",
|
| 5090 |
+
"mdast-util-to-markdown": "^2.0.0"
|
| 5091 |
+
},
|
| 5092 |
+
"funding": {
|
| 5093 |
+
"type": "opencollective",
|
| 5094 |
+
"url": "https://opencollective.com/unified"
|
| 5095 |
+
}
|
| 5096 |
+
},
|
| 5097 |
+
"node_modules/mdast-util-phrasing": {
|
| 5098 |
+
"version": "4.1.0",
|
| 5099 |
+
"resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz",
|
| 5100 |
+
"integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==",
|
| 5101 |
+
"license": "MIT",
|
| 5102 |
+
"dependencies": {
|
| 5103 |
+
"@types/mdast": "^4.0.0",
|
| 5104 |
+
"unist-util-is": "^6.0.0"
|
| 5105 |
+
},
|
| 5106 |
+
"funding": {
|
| 5107 |
+
"type": "opencollective",
|
| 5108 |
+
"url": "https://opencollective.com/unified"
|
| 5109 |
+
}
|
| 5110 |
+
},
|
| 5111 |
+
"node_modules/mdast-util-to-hast": {
|
| 5112 |
+
"version": "13.2.1",
|
| 5113 |
+
"resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz",
|
| 5114 |
+
"integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==",
|
| 5115 |
+
"license": "MIT",
|
| 5116 |
+
"dependencies": {
|
| 5117 |
+
"@types/hast": "^3.0.0",
|
| 5118 |
+
"@types/mdast": "^4.0.0",
|
| 5119 |
+
"@ungap/structured-clone": "^1.0.0",
|
| 5120 |
+
"devlop": "^1.0.0",
|
| 5121 |
+
"micromark-util-sanitize-uri": "^2.0.0",
|
| 5122 |
+
"trim-lines": "^3.0.0",
|
| 5123 |
+
"unist-util-position": "^5.0.0",
|
| 5124 |
+
"unist-util-visit": "^5.0.0",
|
| 5125 |
+
"vfile": "^6.0.0"
|
| 5126 |
+
},
|
| 5127 |
+
"funding": {
|
| 5128 |
+
"type": "opencollective",
|
| 5129 |
+
"url": "https://opencollective.com/unified"
|
| 5130 |
+
}
|
| 5131 |
+
},
|
| 5132 |
+
"node_modules/mdast-util-to-markdown": {
|
| 5133 |
+
"version": "2.1.2",
|
| 5134 |
+
"resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz",
|
| 5135 |
+
"integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==",
|
| 5136 |
+
"license": "MIT",
|
| 5137 |
+
"dependencies": {
|
| 5138 |
+
"@types/mdast": "^4.0.0",
|
| 5139 |
+
"@types/unist": "^3.0.0",
|
| 5140 |
+
"longest-streak": "^3.0.0",
|
| 5141 |
+
"mdast-util-phrasing": "^4.0.0",
|
| 5142 |
+
"mdast-util-to-string": "^4.0.0",
|
| 5143 |
+
"micromark-util-classify-character": "^2.0.0",
|
| 5144 |
+
"micromark-util-decode-string": "^2.0.0",
|
| 5145 |
+
"unist-util-visit": "^5.0.0",
|
| 5146 |
+
"zwitch": "^2.0.0"
|
| 5147 |
+
},
|
| 5148 |
+
"funding": {
|
| 5149 |
+
"type": "opencollective",
|
| 5150 |
+
"url": "https://opencollective.com/unified"
|
| 5151 |
+
}
|
| 5152 |
+
},
|
| 5153 |
+
"node_modules/mdast-util-to-string": {
|
| 5154 |
+
"version": "4.0.0",
|
| 5155 |
+
"resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz",
|
| 5156 |
+
"integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==",
|
| 5157 |
+
"license": "MIT",
|
| 5158 |
+
"dependencies": {
|
| 5159 |
+
"@types/mdast": "^4.0.0"
|
| 5160 |
+
},
|
| 5161 |
+
"funding": {
|
| 5162 |
+
"type": "opencollective",
|
| 5163 |
+
"url": "https://opencollective.com/unified"
|
| 5164 |
+
}
|
| 5165 |
+
},
|
| 5166 |
+
"node_modules/mdn-data": {
|
| 5167 |
+
"version": "2.27.1",
|
| 5168 |
+
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz",
|
| 5169 |
+
"integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==",
|
| 5170 |
+
"dev": true,
|
| 5171 |
+
"license": "CC0-1.0"
|
| 5172 |
+
},
|
| 5173 |
+
"node_modules/merge2": {
|
| 5174 |
+
"version": "1.4.1",
|
| 5175 |
+
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
| 5176 |
+
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
|
| 5177 |
+
"dev": true,
|
| 5178 |
+
"license": "MIT",
|
| 5179 |
+
"engines": {
|
| 5180 |
+
"node": ">= 8"
|
| 5181 |
+
}
|
| 5182 |
+
},
|
| 5183 |
+
"node_modules/micromark": {
|
| 5184 |
+
"version": "4.0.2",
|
| 5185 |
+
"resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz",
|
| 5186 |
+
"integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==",
|
| 5187 |
+
"funding": [
|
| 5188 |
+
{
|
| 5189 |
+
"type": "GitHub Sponsors",
|
| 5190 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5191 |
+
},
|
| 5192 |
+
{
|
| 5193 |
+
"type": "OpenCollective",
|
| 5194 |
+
"url": "https://opencollective.com/unified"
|
| 5195 |
+
}
|
| 5196 |
+
],
|
| 5197 |
+
"license": "MIT",
|
| 5198 |
+
"dependencies": {
|
| 5199 |
+
"@types/debug": "^4.0.0",
|
| 5200 |
+
"debug": "^4.0.0",
|
| 5201 |
+
"decode-named-character-reference": "^1.0.0",
|
| 5202 |
+
"devlop": "^1.0.0",
|
| 5203 |
+
"micromark-core-commonmark": "^2.0.0",
|
| 5204 |
+
"micromark-factory-space": "^2.0.0",
|
| 5205 |
+
"micromark-util-character": "^2.0.0",
|
| 5206 |
+
"micromark-util-chunked": "^2.0.0",
|
| 5207 |
+
"micromark-util-combine-extensions": "^2.0.0",
|
| 5208 |
+
"micromark-util-decode-numeric-character-reference": "^2.0.0",
|
| 5209 |
+
"micromark-util-encode": "^2.0.0",
|
| 5210 |
+
"micromark-util-normalize-identifier": "^2.0.0",
|
| 5211 |
+
"micromark-util-resolve-all": "^2.0.0",
|
| 5212 |
+
"micromark-util-sanitize-uri": "^2.0.0",
|
| 5213 |
+
"micromark-util-subtokenize": "^2.0.0",
|
| 5214 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5215 |
+
"micromark-util-types": "^2.0.0"
|
| 5216 |
+
}
|
| 5217 |
+
},
|
| 5218 |
+
"node_modules/micromark-core-commonmark": {
|
| 5219 |
+
"version": "2.0.3",
|
| 5220 |
+
"resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz",
|
| 5221 |
+
"integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==",
|
| 5222 |
+
"funding": [
|
| 5223 |
+
{
|
| 5224 |
+
"type": "GitHub Sponsors",
|
| 5225 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5226 |
+
},
|
| 5227 |
+
{
|
| 5228 |
+
"type": "OpenCollective",
|
| 5229 |
+
"url": "https://opencollective.com/unified"
|
| 5230 |
+
}
|
| 5231 |
+
],
|
| 5232 |
+
"license": "MIT",
|
| 5233 |
+
"dependencies": {
|
| 5234 |
+
"decode-named-character-reference": "^1.0.0",
|
| 5235 |
+
"devlop": "^1.0.0",
|
| 5236 |
+
"micromark-factory-destination": "^2.0.0",
|
| 5237 |
+
"micromark-factory-label": "^2.0.0",
|
| 5238 |
+
"micromark-factory-space": "^2.0.0",
|
| 5239 |
+
"micromark-factory-title": "^2.0.0",
|
| 5240 |
+
"micromark-factory-whitespace": "^2.0.0",
|
| 5241 |
+
"micromark-util-character": "^2.0.0",
|
| 5242 |
+
"micromark-util-chunked": "^2.0.0",
|
| 5243 |
+
"micromark-util-classify-character": "^2.0.0",
|
| 5244 |
+
"micromark-util-html-tag-name": "^2.0.0",
|
| 5245 |
+
"micromark-util-normalize-identifier": "^2.0.0",
|
| 5246 |
+
"micromark-util-resolve-all": "^2.0.0",
|
| 5247 |
+
"micromark-util-subtokenize": "^2.0.0",
|
| 5248 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5249 |
+
"micromark-util-types": "^2.0.0"
|
| 5250 |
+
}
|
| 5251 |
+
},
|
| 5252 |
+
"node_modules/micromark-extension-gfm": {
|
| 5253 |
+
"version": "3.0.0",
|
| 5254 |
+
"resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz",
|
| 5255 |
+
"integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==",
|
| 5256 |
+
"license": "MIT",
|
| 5257 |
+
"dependencies": {
|
| 5258 |
+
"micromark-extension-gfm-autolink-literal": "^2.0.0",
|
| 5259 |
+
"micromark-extension-gfm-footnote": "^2.0.0",
|
| 5260 |
+
"micromark-extension-gfm-strikethrough": "^2.0.0",
|
| 5261 |
+
"micromark-extension-gfm-table": "^2.0.0",
|
| 5262 |
+
"micromark-extension-gfm-tagfilter": "^2.0.0",
|
| 5263 |
+
"micromark-extension-gfm-task-list-item": "^2.0.0",
|
| 5264 |
+
"micromark-util-combine-extensions": "^2.0.0",
|
| 5265 |
+
"micromark-util-types": "^2.0.0"
|
| 5266 |
+
},
|
| 5267 |
+
"funding": {
|
| 5268 |
+
"type": "opencollective",
|
| 5269 |
+
"url": "https://opencollective.com/unified"
|
| 5270 |
+
}
|
| 5271 |
+
},
|
| 5272 |
+
"node_modules/micromark-extension-gfm-autolink-literal": {
|
| 5273 |
+
"version": "2.1.0",
|
| 5274 |
+
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz",
|
| 5275 |
+
"integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==",
|
| 5276 |
+
"license": "MIT",
|
| 5277 |
+
"dependencies": {
|
| 5278 |
+
"micromark-util-character": "^2.0.0",
|
| 5279 |
+
"micromark-util-sanitize-uri": "^2.0.0",
|
| 5280 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5281 |
+
"micromark-util-types": "^2.0.0"
|
| 5282 |
+
},
|
| 5283 |
+
"funding": {
|
| 5284 |
+
"type": "opencollective",
|
| 5285 |
+
"url": "https://opencollective.com/unified"
|
| 5286 |
+
}
|
| 5287 |
+
},
|
| 5288 |
+
"node_modules/micromark-extension-gfm-footnote": {
|
| 5289 |
+
"version": "2.1.0",
|
| 5290 |
+
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz",
|
| 5291 |
+
"integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==",
|
| 5292 |
+
"license": "MIT",
|
| 5293 |
+
"dependencies": {
|
| 5294 |
+
"devlop": "^1.0.0",
|
| 5295 |
+
"micromark-core-commonmark": "^2.0.0",
|
| 5296 |
+
"micromark-factory-space": "^2.0.0",
|
| 5297 |
+
"micromark-util-character": "^2.0.0",
|
| 5298 |
+
"micromark-util-normalize-identifier": "^2.0.0",
|
| 5299 |
+
"micromark-util-sanitize-uri": "^2.0.0",
|
| 5300 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5301 |
+
"micromark-util-types": "^2.0.0"
|
| 5302 |
+
},
|
| 5303 |
+
"funding": {
|
| 5304 |
+
"type": "opencollective",
|
| 5305 |
+
"url": "https://opencollective.com/unified"
|
| 5306 |
+
}
|
| 5307 |
+
},
|
| 5308 |
+
"node_modules/micromark-extension-gfm-strikethrough": {
|
| 5309 |
+
"version": "2.1.0",
|
| 5310 |
+
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz",
|
| 5311 |
+
"integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==",
|
| 5312 |
+
"license": "MIT",
|
| 5313 |
+
"dependencies": {
|
| 5314 |
+
"devlop": "^1.0.0",
|
| 5315 |
+
"micromark-util-chunked": "^2.0.0",
|
| 5316 |
+
"micromark-util-classify-character": "^2.0.0",
|
| 5317 |
+
"micromark-util-resolve-all": "^2.0.0",
|
| 5318 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5319 |
+
"micromark-util-types": "^2.0.0"
|
| 5320 |
+
},
|
| 5321 |
+
"funding": {
|
| 5322 |
+
"type": "opencollective",
|
| 5323 |
+
"url": "https://opencollective.com/unified"
|
| 5324 |
+
}
|
| 5325 |
+
},
|
| 5326 |
+
"node_modules/micromark-extension-gfm-table": {
|
| 5327 |
+
"version": "2.1.1",
|
| 5328 |
+
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz",
|
| 5329 |
+
"integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==",
|
| 5330 |
+
"license": "MIT",
|
| 5331 |
+
"dependencies": {
|
| 5332 |
+
"devlop": "^1.0.0",
|
| 5333 |
+
"micromark-factory-space": "^2.0.0",
|
| 5334 |
+
"micromark-util-character": "^2.0.0",
|
| 5335 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5336 |
+
"micromark-util-types": "^2.0.0"
|
| 5337 |
+
},
|
| 5338 |
+
"funding": {
|
| 5339 |
+
"type": "opencollective",
|
| 5340 |
+
"url": "https://opencollective.com/unified"
|
| 5341 |
+
}
|
| 5342 |
+
},
|
| 5343 |
+
"node_modules/micromark-extension-gfm-tagfilter": {
|
| 5344 |
+
"version": "2.0.0",
|
| 5345 |
+
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz",
|
| 5346 |
+
"integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==",
|
| 5347 |
+
"license": "MIT",
|
| 5348 |
+
"dependencies": {
|
| 5349 |
+
"micromark-util-types": "^2.0.0"
|
| 5350 |
+
},
|
| 5351 |
+
"funding": {
|
| 5352 |
+
"type": "opencollective",
|
| 5353 |
+
"url": "https://opencollective.com/unified"
|
| 5354 |
+
}
|
| 5355 |
+
},
|
| 5356 |
+
"node_modules/micromark-extension-gfm-task-list-item": {
|
| 5357 |
+
"version": "2.1.0",
|
| 5358 |
+
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz",
|
| 5359 |
+
"integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==",
|
| 5360 |
+
"license": "MIT",
|
| 5361 |
+
"dependencies": {
|
| 5362 |
+
"devlop": "^1.0.0",
|
| 5363 |
+
"micromark-factory-space": "^2.0.0",
|
| 5364 |
+
"micromark-util-character": "^2.0.0",
|
| 5365 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5366 |
+
"micromark-util-types": "^2.0.0"
|
| 5367 |
+
},
|
| 5368 |
+
"funding": {
|
| 5369 |
+
"type": "opencollective",
|
| 5370 |
+
"url": "https://opencollective.com/unified"
|
| 5371 |
+
}
|
| 5372 |
+
},
|
| 5373 |
+
"node_modules/micromark-factory-destination": {
|
| 5374 |
+
"version": "2.0.1",
|
| 5375 |
+
"resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz",
|
| 5376 |
+
"integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==",
|
| 5377 |
+
"funding": [
|
| 5378 |
+
{
|
| 5379 |
+
"type": "GitHub Sponsors",
|
| 5380 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5381 |
+
},
|
| 5382 |
+
{
|
| 5383 |
+
"type": "OpenCollective",
|
| 5384 |
+
"url": "https://opencollective.com/unified"
|
| 5385 |
+
}
|
| 5386 |
+
],
|
| 5387 |
+
"license": "MIT",
|
| 5388 |
+
"dependencies": {
|
| 5389 |
+
"micromark-util-character": "^2.0.0",
|
| 5390 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5391 |
+
"micromark-util-types": "^2.0.0"
|
| 5392 |
+
}
|
| 5393 |
+
},
|
| 5394 |
+
"node_modules/micromark-factory-label": {
|
| 5395 |
+
"version": "2.0.1",
|
| 5396 |
+
"resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz",
|
| 5397 |
+
"integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==",
|
| 5398 |
+
"funding": [
|
| 5399 |
+
{
|
| 5400 |
+
"type": "GitHub Sponsors",
|
| 5401 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5402 |
+
},
|
| 5403 |
+
{
|
| 5404 |
+
"type": "OpenCollective",
|
| 5405 |
+
"url": "https://opencollective.com/unified"
|
| 5406 |
+
}
|
| 5407 |
+
],
|
| 5408 |
+
"license": "MIT",
|
| 5409 |
+
"dependencies": {
|
| 5410 |
+
"devlop": "^1.0.0",
|
| 5411 |
+
"micromark-util-character": "^2.0.0",
|
| 5412 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5413 |
+
"micromark-util-types": "^2.0.0"
|
| 5414 |
+
}
|
| 5415 |
+
},
|
| 5416 |
+
"node_modules/micromark-factory-space": {
|
| 5417 |
+
"version": "2.0.1",
|
| 5418 |
+
"resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz",
|
| 5419 |
+
"integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==",
|
| 5420 |
+
"funding": [
|
| 5421 |
+
{
|
| 5422 |
+
"type": "GitHub Sponsors",
|
| 5423 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5424 |
+
},
|
| 5425 |
+
{
|
| 5426 |
+
"type": "OpenCollective",
|
| 5427 |
+
"url": "https://opencollective.com/unified"
|
| 5428 |
+
}
|
| 5429 |
+
],
|
| 5430 |
+
"license": "MIT",
|
| 5431 |
+
"dependencies": {
|
| 5432 |
+
"micromark-util-character": "^2.0.0",
|
| 5433 |
+
"micromark-util-types": "^2.0.0"
|
| 5434 |
+
}
|
| 5435 |
+
},
|
| 5436 |
+
"node_modules/micromark-factory-title": {
|
| 5437 |
+
"version": "2.0.1",
|
| 5438 |
+
"resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz",
|
| 5439 |
+
"integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==",
|
| 5440 |
+
"funding": [
|
| 5441 |
+
{
|
| 5442 |
+
"type": "GitHub Sponsors",
|
| 5443 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5444 |
+
},
|
| 5445 |
+
{
|
| 5446 |
+
"type": "OpenCollective",
|
| 5447 |
+
"url": "https://opencollective.com/unified"
|
| 5448 |
+
}
|
| 5449 |
+
],
|
| 5450 |
+
"license": "MIT",
|
| 5451 |
+
"dependencies": {
|
| 5452 |
+
"micromark-factory-space": "^2.0.0",
|
| 5453 |
+
"micromark-util-character": "^2.0.0",
|
| 5454 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5455 |
+
"micromark-util-types": "^2.0.0"
|
| 5456 |
+
}
|
| 5457 |
+
},
|
| 5458 |
+
"node_modules/micromark-factory-whitespace": {
|
| 5459 |
+
"version": "2.0.1",
|
| 5460 |
+
"resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz",
|
| 5461 |
+
"integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==",
|
| 5462 |
+
"funding": [
|
| 5463 |
+
{
|
| 5464 |
+
"type": "GitHub Sponsors",
|
| 5465 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5466 |
+
},
|
| 5467 |
+
{
|
| 5468 |
+
"type": "OpenCollective",
|
| 5469 |
+
"url": "https://opencollective.com/unified"
|
| 5470 |
+
}
|
| 5471 |
+
],
|
| 5472 |
+
"license": "MIT",
|
| 5473 |
+
"dependencies": {
|
| 5474 |
+
"micromark-factory-space": "^2.0.0",
|
| 5475 |
+
"micromark-util-character": "^2.0.0",
|
| 5476 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5477 |
+
"micromark-util-types": "^2.0.0"
|
| 5478 |
+
}
|
| 5479 |
+
},
|
| 5480 |
+
"node_modules/micromark-util-character": {
|
| 5481 |
+
"version": "2.1.1",
|
| 5482 |
+
"resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz",
|
| 5483 |
+
"integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==",
|
| 5484 |
+
"funding": [
|
| 5485 |
+
{
|
| 5486 |
+
"type": "GitHub Sponsors",
|
| 5487 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5488 |
+
},
|
| 5489 |
+
{
|
| 5490 |
+
"type": "OpenCollective",
|
| 5491 |
+
"url": "https://opencollective.com/unified"
|
| 5492 |
+
}
|
| 5493 |
+
],
|
| 5494 |
+
"license": "MIT",
|
| 5495 |
+
"dependencies": {
|
| 5496 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5497 |
+
"micromark-util-types": "^2.0.0"
|
| 5498 |
+
}
|
| 5499 |
+
},
|
| 5500 |
+
"node_modules/micromark-util-chunked": {
|
| 5501 |
+
"version": "2.0.1",
|
| 5502 |
+
"resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz",
|
| 5503 |
+
"integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==",
|
| 5504 |
+
"funding": [
|
| 5505 |
+
{
|
| 5506 |
+
"type": "GitHub Sponsors",
|
| 5507 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5508 |
+
},
|
| 5509 |
+
{
|
| 5510 |
+
"type": "OpenCollective",
|
| 5511 |
+
"url": "https://opencollective.com/unified"
|
| 5512 |
+
}
|
| 5513 |
+
],
|
| 5514 |
+
"license": "MIT",
|
| 5515 |
+
"dependencies": {
|
| 5516 |
+
"micromark-util-symbol": "^2.0.0"
|
| 5517 |
+
}
|
| 5518 |
+
},
|
| 5519 |
+
"node_modules/micromark-util-classify-character": {
|
| 5520 |
+
"version": "2.0.1",
|
| 5521 |
+
"resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz",
|
| 5522 |
+
"integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==",
|
| 5523 |
+
"funding": [
|
| 5524 |
+
{
|
| 5525 |
+
"type": "GitHub Sponsors",
|
| 5526 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5527 |
+
},
|
| 5528 |
+
{
|
| 5529 |
+
"type": "OpenCollective",
|
| 5530 |
+
"url": "https://opencollective.com/unified"
|
| 5531 |
+
}
|
| 5532 |
+
],
|
| 5533 |
+
"license": "MIT",
|
| 5534 |
+
"dependencies": {
|
| 5535 |
+
"micromark-util-character": "^2.0.0",
|
| 5536 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5537 |
+
"micromark-util-types": "^2.0.0"
|
| 5538 |
+
}
|
| 5539 |
+
},
|
| 5540 |
+
"node_modules/micromark-util-combine-extensions": {
|
| 5541 |
+
"version": "2.0.1",
|
| 5542 |
+
"resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz",
|
| 5543 |
+
"integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==",
|
| 5544 |
+
"funding": [
|
| 5545 |
+
{
|
| 5546 |
+
"type": "GitHub Sponsors",
|
| 5547 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5548 |
+
},
|
| 5549 |
+
{
|
| 5550 |
+
"type": "OpenCollective",
|
| 5551 |
+
"url": "https://opencollective.com/unified"
|
| 5552 |
+
}
|
| 5553 |
+
],
|
| 5554 |
+
"license": "MIT",
|
| 5555 |
+
"dependencies": {
|
| 5556 |
+
"micromark-util-chunked": "^2.0.0",
|
| 5557 |
+
"micromark-util-types": "^2.0.0"
|
| 5558 |
+
}
|
| 5559 |
+
},
|
| 5560 |
+
"node_modules/micromark-util-decode-numeric-character-reference": {
|
| 5561 |
+
"version": "2.0.2",
|
| 5562 |
+
"resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz",
|
| 5563 |
+
"integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==",
|
| 5564 |
+
"funding": [
|
| 5565 |
+
{
|
| 5566 |
+
"type": "GitHub Sponsors",
|
| 5567 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5568 |
+
},
|
| 5569 |
+
{
|
| 5570 |
+
"type": "OpenCollective",
|
| 5571 |
+
"url": "https://opencollective.com/unified"
|
| 5572 |
+
}
|
| 5573 |
+
],
|
| 5574 |
+
"license": "MIT",
|
| 5575 |
+
"dependencies": {
|
| 5576 |
+
"micromark-util-symbol": "^2.0.0"
|
| 5577 |
+
}
|
| 5578 |
+
},
|
| 5579 |
+
"node_modules/micromark-util-decode-string": {
|
| 5580 |
+
"version": "2.0.1",
|
| 5581 |
+
"resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz",
|
| 5582 |
+
"integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==",
|
| 5583 |
+
"funding": [
|
| 5584 |
+
{
|
| 5585 |
+
"type": "GitHub Sponsors",
|
| 5586 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5587 |
+
},
|
| 5588 |
+
{
|
| 5589 |
+
"type": "OpenCollective",
|
| 5590 |
+
"url": "https://opencollective.com/unified"
|
| 5591 |
+
}
|
| 5592 |
+
],
|
| 5593 |
+
"license": "MIT",
|
| 5594 |
+
"dependencies": {
|
| 5595 |
+
"decode-named-character-reference": "^1.0.0",
|
| 5596 |
+
"micromark-util-character": "^2.0.0",
|
| 5597 |
+
"micromark-util-decode-numeric-character-reference": "^2.0.0",
|
| 5598 |
+
"micromark-util-symbol": "^2.0.0"
|
| 5599 |
+
}
|
| 5600 |
+
},
|
| 5601 |
+
"node_modules/micromark-util-encode": {
|
| 5602 |
+
"version": "2.0.1",
|
| 5603 |
+
"resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz",
|
| 5604 |
+
"integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==",
|
| 5605 |
+
"funding": [
|
| 5606 |
+
{
|
| 5607 |
+
"type": "GitHub Sponsors",
|
| 5608 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5609 |
+
},
|
| 5610 |
+
{
|
| 5611 |
+
"type": "OpenCollective",
|
| 5612 |
+
"url": "https://opencollective.com/unified"
|
| 5613 |
+
}
|
| 5614 |
+
],
|
| 5615 |
+
"license": "MIT"
|
| 5616 |
+
},
|
| 5617 |
+
"node_modules/micromark-util-html-tag-name": {
|
| 5618 |
+
"version": "2.0.1",
|
| 5619 |
+
"resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz",
|
| 5620 |
+
"integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==",
|
| 5621 |
+
"funding": [
|
| 5622 |
+
{
|
| 5623 |
+
"type": "GitHub Sponsors",
|
| 5624 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5625 |
+
},
|
| 5626 |
+
{
|
| 5627 |
+
"type": "OpenCollective",
|
| 5628 |
+
"url": "https://opencollective.com/unified"
|
| 5629 |
+
}
|
| 5630 |
+
],
|
| 5631 |
+
"license": "MIT"
|
| 5632 |
+
},
|
| 5633 |
+
"node_modules/micromark-util-normalize-identifier": {
|
| 5634 |
+
"version": "2.0.1",
|
| 5635 |
+
"resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz",
|
| 5636 |
+
"integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==",
|
| 5637 |
+
"funding": [
|
| 5638 |
+
{
|
| 5639 |
+
"type": "GitHub Sponsors",
|
| 5640 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5641 |
+
},
|
| 5642 |
+
{
|
| 5643 |
+
"type": "OpenCollective",
|
| 5644 |
+
"url": "https://opencollective.com/unified"
|
| 5645 |
+
}
|
| 5646 |
+
],
|
| 5647 |
+
"license": "MIT",
|
| 5648 |
+
"dependencies": {
|
| 5649 |
+
"micromark-util-symbol": "^2.0.0"
|
| 5650 |
+
}
|
| 5651 |
+
},
|
| 5652 |
+
"node_modules/micromark-util-resolve-all": {
|
| 5653 |
+
"version": "2.0.1",
|
| 5654 |
+
"resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz",
|
| 5655 |
+
"integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==",
|
| 5656 |
+
"funding": [
|
| 5657 |
+
{
|
| 5658 |
+
"type": "GitHub Sponsors",
|
| 5659 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5660 |
+
},
|
| 5661 |
+
{
|
| 5662 |
+
"type": "OpenCollective",
|
| 5663 |
+
"url": "https://opencollective.com/unified"
|
| 5664 |
+
}
|
| 5665 |
+
],
|
| 5666 |
+
"license": "MIT",
|
| 5667 |
+
"dependencies": {
|
| 5668 |
+
"micromark-util-types": "^2.0.0"
|
| 5669 |
+
}
|
| 5670 |
+
},
|
| 5671 |
+
"node_modules/micromark-util-sanitize-uri": {
|
| 5672 |
+
"version": "2.0.1",
|
| 5673 |
+
"resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz",
|
| 5674 |
+
"integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==",
|
| 5675 |
+
"funding": [
|
| 5676 |
+
{
|
| 5677 |
+
"type": "GitHub Sponsors",
|
| 5678 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5679 |
+
},
|
| 5680 |
+
{
|
| 5681 |
+
"type": "OpenCollective",
|
| 5682 |
+
"url": "https://opencollective.com/unified"
|
| 5683 |
+
}
|
| 5684 |
+
],
|
| 5685 |
+
"license": "MIT",
|
| 5686 |
+
"dependencies": {
|
| 5687 |
+
"micromark-util-character": "^2.0.0",
|
| 5688 |
+
"micromark-util-encode": "^2.0.0",
|
| 5689 |
+
"micromark-util-symbol": "^2.0.0"
|
| 5690 |
+
}
|
| 5691 |
+
},
|
| 5692 |
+
"node_modules/micromark-util-subtokenize": {
|
| 5693 |
+
"version": "2.1.0",
|
| 5694 |
+
"resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz",
|
| 5695 |
+
"integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==",
|
| 5696 |
+
"funding": [
|
| 5697 |
+
{
|
| 5698 |
+
"type": "GitHub Sponsors",
|
| 5699 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5700 |
+
},
|
| 5701 |
+
{
|
| 5702 |
+
"type": "OpenCollective",
|
| 5703 |
+
"url": "https://opencollective.com/unified"
|
| 5704 |
+
}
|
| 5705 |
+
],
|
| 5706 |
+
"license": "MIT",
|
| 5707 |
+
"dependencies": {
|
| 5708 |
+
"devlop": "^1.0.0",
|
| 5709 |
+
"micromark-util-chunked": "^2.0.0",
|
| 5710 |
+
"micromark-util-symbol": "^2.0.0",
|
| 5711 |
+
"micromark-util-types": "^2.0.0"
|
| 5712 |
+
}
|
| 5713 |
+
},
|
| 5714 |
+
"node_modules/micromark-util-symbol": {
|
| 5715 |
+
"version": "2.0.1",
|
| 5716 |
+
"resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz",
|
| 5717 |
+
"integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==",
|
| 5718 |
+
"funding": [
|
| 5719 |
+
{
|
| 5720 |
+
"type": "GitHub Sponsors",
|
| 5721 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5722 |
+
},
|
| 5723 |
+
{
|
| 5724 |
+
"type": "OpenCollective",
|
| 5725 |
+
"url": "https://opencollective.com/unified"
|
| 5726 |
+
}
|
| 5727 |
+
],
|
| 5728 |
+
"license": "MIT"
|
| 5729 |
+
},
|
| 5730 |
+
"node_modules/micromark-util-types": {
|
| 5731 |
+
"version": "2.0.2",
|
| 5732 |
+
"resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz",
|
| 5733 |
+
"integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==",
|
| 5734 |
+
"funding": [
|
| 5735 |
+
{
|
| 5736 |
+
"type": "GitHub Sponsors",
|
| 5737 |
+
"url": "https://github.com/sponsors/unifiedjs"
|
| 5738 |
+
},
|
| 5739 |
+
{
|
| 5740 |
+
"type": "OpenCollective",
|
| 5741 |
+
"url": "https://opencollective.com/unified"
|
| 5742 |
+
}
|
| 5743 |
+
],
|
| 5744 |
+
"license": "MIT"
|
| 5745 |
+
},
|
| 5746 |
+
"node_modules/micromatch": {
|
| 5747 |
+
"version": "4.0.8",
|
| 5748 |
+
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
| 5749 |
+
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
| 5750 |
+
"dev": true,
|
| 5751 |
+
"license": "MIT",
|
| 5752 |
+
"dependencies": {
|
| 5753 |
+
"braces": "^3.0.3",
|
| 5754 |
+
"picomatch": "^2.3.1"
|
| 5755 |
+
},
|
| 5756 |
+
"engines": {
|
| 5757 |
+
"node": ">=8.6"
|
| 5758 |
+
}
|
| 5759 |
+
},
|
| 5760 |
+
"node_modules/min-indent": {
|
| 5761 |
+
"version": "1.0.1",
|
| 5762 |
+
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
|
| 5763 |
+
"integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
|
| 5764 |
+
"dev": true,
|
| 5765 |
+
"license": "MIT",
|
| 5766 |
+
"engines": {
|
| 5767 |
+
"node": ">=4"
|
| 5768 |
+
}
|
| 5769 |
+
},
|
| 5770 |
+
"node_modules/minimatch": {
|
| 5771 |
+
"version": "3.1.5",
|
| 5772 |
+
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
| 5773 |
+
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
| 5774 |
+
"dev": true,
|
| 5775 |
+
"license": "ISC",
|
| 5776 |
+
"dependencies": {
|
| 5777 |
+
"brace-expansion": "^1.1.7"
|
| 5778 |
+
},
|
| 5779 |
+
"engines": {
|
| 5780 |
+
"node": "*"
|
| 5781 |
+
}
|
| 5782 |
+
},
|
| 5783 |
+
"node_modules/ms": {
|
| 5784 |
+
"version": "2.1.3",
|
| 5785 |
+
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
| 5786 |
+
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
| 5787 |
+
"license": "MIT"
|
| 5788 |
+
},
|
| 5789 |
+
"node_modules/mz": {
|
| 5790 |
+
"version": "2.7.0",
|
| 5791 |
+
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
|
| 5792 |
+
"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
|
| 5793 |
+
"dev": true,
|
| 5794 |
+
"license": "MIT",
|
| 5795 |
+
"dependencies": {
|
| 5796 |
+
"any-promise": "^1.0.0",
|
| 5797 |
+
"object-assign": "^4.0.1",
|
| 5798 |
+
"thenify-all": "^1.0.0"
|
| 5799 |
+
}
|
| 5800 |
+
},
|
| 5801 |
+
"node_modules/nanoid": {
|
| 5802 |
+
"version": "3.3.11",
|
| 5803 |
+
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
| 5804 |
+
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
|
| 5805 |
+
"dev": true,
|
| 5806 |
+
"funding": [
|
| 5807 |
+
{
|
| 5808 |
+
"type": "github",
|
| 5809 |
+
"url": "https://github.com/sponsors/ai"
|
| 5810 |
+
}
|
| 5811 |
+
],
|
| 5812 |
+
"license": "MIT",
|
| 5813 |
+
"bin": {
|
| 5814 |
+
"nanoid": "bin/nanoid.cjs"
|
| 5815 |
+
},
|
| 5816 |
+
"engines": {
|
| 5817 |
+
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
| 5818 |
+
}
|
| 5819 |
+
},
|
| 5820 |
+
"node_modules/natural-compare": {
|
| 5821 |
+
"version": "1.4.0",
|
| 5822 |
+
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
| 5823 |
+
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
|
| 5824 |
"dev": true,
|
| 5825 |
"license": "MIT"
|
| 5826 |
},
|
|
|
|
| 5934 |
"node": ">=6"
|
| 5935 |
}
|
| 5936 |
},
|
| 5937 |
+
"node_modules/parse-entities": {
|
| 5938 |
+
"version": "4.0.2",
|
| 5939 |
+
"resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz",
|
| 5940 |
+
"integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==",
|
| 5941 |
+
"license": "MIT",
|
| 5942 |
+
"dependencies": {
|
| 5943 |
+
"@types/unist": "^2.0.0",
|
| 5944 |
+
"character-entities-legacy": "^3.0.0",
|
| 5945 |
+
"character-reference-invalid": "^2.0.0",
|
| 5946 |
+
"decode-named-character-reference": "^1.0.0",
|
| 5947 |
+
"is-alphanumerical": "^2.0.0",
|
| 5948 |
+
"is-decimal": "^2.0.0",
|
| 5949 |
+
"is-hexadecimal": "^2.0.0"
|
| 5950 |
+
},
|
| 5951 |
+
"funding": {
|
| 5952 |
+
"type": "github",
|
| 5953 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 5954 |
+
}
|
| 5955 |
+
},
|
| 5956 |
+
"node_modules/parse-entities/node_modules/@types/unist": {
|
| 5957 |
+
"version": "2.0.11",
|
| 5958 |
+
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
|
| 5959 |
+
"integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
|
| 5960 |
+
"license": "MIT"
|
| 5961 |
+
},
|
| 5962 |
"node_modules/parse5": {
|
| 5963 |
"version": "8.0.0",
|
| 5964 |
"resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz",
|
|
|
|
| 6265 |
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
| 6266 |
"license": "MIT"
|
| 6267 |
},
|
| 6268 |
+
"node_modules/property-information": {
|
| 6269 |
+
"version": "7.1.0",
|
| 6270 |
+
"resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz",
|
| 6271 |
+
"integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==",
|
| 6272 |
+
"license": "MIT",
|
| 6273 |
+
"funding": {
|
| 6274 |
+
"type": "github",
|
| 6275 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 6276 |
+
}
|
| 6277 |
+
},
|
| 6278 |
"node_modules/punycode": {
|
| 6279 |
"version": "2.3.1",
|
| 6280 |
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
|
|
|
| 6340 |
"dev": true,
|
| 6341 |
"license": "MIT"
|
| 6342 |
},
|
| 6343 |
+
"node_modules/react-markdown": {
|
| 6344 |
+
"version": "10.1.0",
|
| 6345 |
+
"resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz",
|
| 6346 |
+
"integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==",
|
| 6347 |
+
"license": "MIT",
|
| 6348 |
+
"dependencies": {
|
| 6349 |
+
"@types/hast": "^3.0.0",
|
| 6350 |
+
"@types/mdast": "^4.0.0",
|
| 6351 |
+
"devlop": "^1.0.0",
|
| 6352 |
+
"hast-util-to-jsx-runtime": "^2.0.0",
|
| 6353 |
+
"html-url-attributes": "^3.0.0",
|
| 6354 |
+
"mdast-util-to-hast": "^13.0.0",
|
| 6355 |
+
"remark-parse": "^11.0.0",
|
| 6356 |
+
"remark-rehype": "^11.0.0",
|
| 6357 |
+
"unified": "^11.0.0",
|
| 6358 |
+
"unist-util-visit": "^5.0.0",
|
| 6359 |
+
"vfile": "^6.0.0"
|
| 6360 |
+
},
|
| 6361 |
+
"funding": {
|
| 6362 |
+
"type": "opencollective",
|
| 6363 |
+
"url": "https://opencollective.com/unified"
|
| 6364 |
+
},
|
| 6365 |
+
"peerDependencies": {
|
| 6366 |
+
"@types/react": ">=18",
|
| 6367 |
+
"react": ">=18"
|
| 6368 |
+
}
|
| 6369 |
+
},
|
| 6370 |
"node_modules/react-refresh": {
|
| 6371 |
"version": "0.17.0",
|
| 6372 |
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
|
|
|
|
| 6515 |
"node": ">=8"
|
| 6516 |
}
|
| 6517 |
},
|
| 6518 |
+
"node_modules/remark-gfm": {
|
| 6519 |
+
"version": "4.0.1",
|
| 6520 |
+
"resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz",
|
| 6521 |
+
"integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==",
|
| 6522 |
+
"license": "MIT",
|
| 6523 |
+
"dependencies": {
|
| 6524 |
+
"@types/mdast": "^4.0.0",
|
| 6525 |
+
"mdast-util-gfm": "^3.0.0",
|
| 6526 |
+
"micromark-extension-gfm": "^3.0.0",
|
| 6527 |
+
"remark-parse": "^11.0.0",
|
| 6528 |
+
"remark-stringify": "^11.0.0",
|
| 6529 |
+
"unified": "^11.0.0"
|
| 6530 |
+
},
|
| 6531 |
+
"funding": {
|
| 6532 |
+
"type": "opencollective",
|
| 6533 |
+
"url": "https://opencollective.com/unified"
|
| 6534 |
+
}
|
| 6535 |
+
},
|
| 6536 |
+
"node_modules/remark-parse": {
|
| 6537 |
+
"version": "11.0.0",
|
| 6538 |
+
"resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz",
|
| 6539 |
+
"integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==",
|
| 6540 |
+
"license": "MIT",
|
| 6541 |
+
"dependencies": {
|
| 6542 |
+
"@types/mdast": "^4.0.0",
|
| 6543 |
+
"mdast-util-from-markdown": "^2.0.0",
|
| 6544 |
+
"micromark-util-types": "^2.0.0",
|
| 6545 |
+
"unified": "^11.0.0"
|
| 6546 |
+
},
|
| 6547 |
+
"funding": {
|
| 6548 |
+
"type": "opencollective",
|
| 6549 |
+
"url": "https://opencollective.com/unified"
|
| 6550 |
+
}
|
| 6551 |
+
},
|
| 6552 |
+
"node_modules/remark-rehype": {
|
| 6553 |
+
"version": "11.1.2",
|
| 6554 |
+
"resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz",
|
| 6555 |
+
"integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==",
|
| 6556 |
+
"license": "MIT",
|
| 6557 |
+
"dependencies": {
|
| 6558 |
+
"@types/hast": "^3.0.0",
|
| 6559 |
+
"@types/mdast": "^4.0.0",
|
| 6560 |
+
"mdast-util-to-hast": "^13.0.0",
|
| 6561 |
+
"unified": "^11.0.0",
|
| 6562 |
+
"vfile": "^6.0.0"
|
| 6563 |
+
},
|
| 6564 |
+
"funding": {
|
| 6565 |
+
"type": "opencollective",
|
| 6566 |
+
"url": "https://opencollective.com/unified"
|
| 6567 |
+
}
|
| 6568 |
+
},
|
| 6569 |
+
"node_modules/remark-stringify": {
|
| 6570 |
+
"version": "11.0.0",
|
| 6571 |
+
"resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz",
|
| 6572 |
+
"integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==",
|
| 6573 |
+
"license": "MIT",
|
| 6574 |
+
"dependencies": {
|
| 6575 |
+
"@types/mdast": "^4.0.0",
|
| 6576 |
+
"mdast-util-to-markdown": "^2.0.0",
|
| 6577 |
+
"unified": "^11.0.0"
|
| 6578 |
+
},
|
| 6579 |
+
"funding": {
|
| 6580 |
+
"type": "opencollective",
|
| 6581 |
+
"url": "https://opencollective.com/unified"
|
| 6582 |
+
}
|
| 6583 |
+
},
|
| 6584 |
"node_modules/require-from-string": {
|
| 6585 |
"version": "2.0.2",
|
| 6586 |
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
|
|
|
| 6815 |
"node": ">=0.10.0"
|
| 6816 |
}
|
| 6817 |
},
|
| 6818 |
+
"node_modules/space-separated-tokens": {
|
| 6819 |
+
"version": "2.0.2",
|
| 6820 |
+
"resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz",
|
| 6821 |
+
"integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==",
|
| 6822 |
+
"license": "MIT",
|
| 6823 |
+
"funding": {
|
| 6824 |
+
"type": "github",
|
| 6825 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 6826 |
+
}
|
| 6827 |
+
},
|
| 6828 |
"node_modules/stackback": {
|
| 6829 |
"version": "0.0.2",
|
| 6830 |
"resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
|
|
|
|
| 6839 |
"dev": true,
|
| 6840 |
"license": "MIT"
|
| 6841 |
},
|
| 6842 |
+
"node_modules/stringify-entities": {
|
| 6843 |
+
"version": "4.0.4",
|
| 6844 |
+
"resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz",
|
| 6845 |
+
"integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==",
|
| 6846 |
+
"license": "MIT",
|
| 6847 |
+
"dependencies": {
|
| 6848 |
+
"character-entities-html4": "^2.0.0",
|
| 6849 |
+
"character-entities-legacy": "^3.0.0"
|
| 6850 |
+
},
|
| 6851 |
+
"funding": {
|
| 6852 |
+
"type": "github",
|
| 6853 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 6854 |
+
}
|
| 6855 |
+
},
|
| 6856 |
"node_modules/strip-indent": {
|
| 6857 |
"version": "3.0.0",
|
| 6858 |
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
|
|
|
|
| 6879 |
"url": "https://github.com/sponsors/sindresorhus"
|
| 6880 |
}
|
| 6881 |
},
|
| 6882 |
+
"node_modules/style-to-js": {
|
| 6883 |
+
"version": "1.1.21",
|
| 6884 |
+
"resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz",
|
| 6885 |
+
"integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==",
|
| 6886 |
+
"license": "MIT",
|
| 6887 |
+
"dependencies": {
|
| 6888 |
+
"style-to-object": "1.0.14"
|
| 6889 |
+
}
|
| 6890 |
+
},
|
| 6891 |
+
"node_modules/style-to-object": {
|
| 6892 |
+
"version": "1.0.14",
|
| 6893 |
+
"resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz",
|
| 6894 |
+
"integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==",
|
| 6895 |
+
"license": "MIT",
|
| 6896 |
+
"dependencies": {
|
| 6897 |
+
"inline-style-parser": "0.2.7"
|
| 6898 |
+
}
|
| 6899 |
+
},
|
| 6900 |
"node_modules/sucrase": {
|
| 6901 |
"version": "3.35.1",
|
| 6902 |
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz",
|
|
|
|
| 7155 |
"node": ">=20"
|
| 7156 |
}
|
| 7157 |
},
|
| 7158 |
+
"node_modules/trim-lines": {
|
| 7159 |
+
"version": "3.0.1",
|
| 7160 |
+
"resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
|
| 7161 |
+
"integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==",
|
| 7162 |
+
"license": "MIT",
|
| 7163 |
+
"funding": {
|
| 7164 |
+
"type": "github",
|
| 7165 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 7166 |
+
}
|
| 7167 |
+
},
|
| 7168 |
+
"node_modules/trough": {
|
| 7169 |
+
"version": "2.2.0",
|
| 7170 |
+
"resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz",
|
| 7171 |
+
"integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==",
|
| 7172 |
+
"license": "MIT",
|
| 7173 |
+
"funding": {
|
| 7174 |
+
"type": "github",
|
| 7175 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 7176 |
+
}
|
| 7177 |
+
},
|
| 7178 |
"node_modules/ts-api-utils": {
|
| 7179 |
"version": "2.5.0",
|
| 7180 |
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz",
|
|
|
|
| 7265 |
"node": ">=20.18.1"
|
| 7266 |
}
|
| 7267 |
},
|
| 7268 |
+
"node_modules/unified": {
|
| 7269 |
+
"version": "11.0.5",
|
| 7270 |
+
"resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz",
|
| 7271 |
+
"integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==",
|
| 7272 |
+
"license": "MIT",
|
| 7273 |
+
"dependencies": {
|
| 7274 |
+
"@types/unist": "^3.0.0",
|
| 7275 |
+
"bail": "^2.0.0",
|
| 7276 |
+
"devlop": "^1.0.0",
|
| 7277 |
+
"extend": "^3.0.0",
|
| 7278 |
+
"is-plain-obj": "^4.0.0",
|
| 7279 |
+
"trough": "^2.0.0",
|
| 7280 |
+
"vfile": "^6.0.0"
|
| 7281 |
+
},
|
| 7282 |
+
"funding": {
|
| 7283 |
+
"type": "opencollective",
|
| 7284 |
+
"url": "https://opencollective.com/unified"
|
| 7285 |
+
}
|
| 7286 |
+
},
|
| 7287 |
+
"node_modules/unist-util-is": {
|
| 7288 |
+
"version": "6.0.1",
|
| 7289 |
+
"resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz",
|
| 7290 |
+
"integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==",
|
| 7291 |
+
"license": "MIT",
|
| 7292 |
+
"dependencies": {
|
| 7293 |
+
"@types/unist": "^3.0.0"
|
| 7294 |
+
},
|
| 7295 |
+
"funding": {
|
| 7296 |
+
"type": "opencollective",
|
| 7297 |
+
"url": "https://opencollective.com/unified"
|
| 7298 |
+
}
|
| 7299 |
+
},
|
| 7300 |
+
"node_modules/unist-util-position": {
|
| 7301 |
+
"version": "5.0.0",
|
| 7302 |
+
"resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz",
|
| 7303 |
+
"integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==",
|
| 7304 |
+
"license": "MIT",
|
| 7305 |
+
"dependencies": {
|
| 7306 |
+
"@types/unist": "^3.0.0"
|
| 7307 |
+
},
|
| 7308 |
+
"funding": {
|
| 7309 |
+
"type": "opencollective",
|
| 7310 |
+
"url": "https://opencollective.com/unified"
|
| 7311 |
+
}
|
| 7312 |
+
},
|
| 7313 |
+
"node_modules/unist-util-stringify-position": {
|
| 7314 |
+
"version": "4.0.0",
|
| 7315 |
+
"resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz",
|
| 7316 |
+
"integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==",
|
| 7317 |
+
"license": "MIT",
|
| 7318 |
+
"dependencies": {
|
| 7319 |
+
"@types/unist": "^3.0.0"
|
| 7320 |
+
},
|
| 7321 |
+
"funding": {
|
| 7322 |
+
"type": "opencollective",
|
| 7323 |
+
"url": "https://opencollective.com/unified"
|
| 7324 |
+
}
|
| 7325 |
+
},
|
| 7326 |
+
"node_modules/unist-util-visit": {
|
| 7327 |
+
"version": "5.1.0",
|
| 7328 |
+
"resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz",
|
| 7329 |
+
"integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==",
|
| 7330 |
+
"license": "MIT",
|
| 7331 |
+
"dependencies": {
|
| 7332 |
+
"@types/unist": "^3.0.0",
|
| 7333 |
+
"unist-util-is": "^6.0.0",
|
| 7334 |
+
"unist-util-visit-parents": "^6.0.0"
|
| 7335 |
+
},
|
| 7336 |
+
"funding": {
|
| 7337 |
+
"type": "opencollective",
|
| 7338 |
+
"url": "https://opencollective.com/unified"
|
| 7339 |
+
}
|
| 7340 |
+
},
|
| 7341 |
+
"node_modules/unist-util-visit-parents": {
|
| 7342 |
+
"version": "6.0.2",
|
| 7343 |
+
"resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz",
|
| 7344 |
+
"integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==",
|
| 7345 |
+
"license": "MIT",
|
| 7346 |
+
"dependencies": {
|
| 7347 |
+
"@types/unist": "^3.0.0",
|
| 7348 |
+
"unist-util-is": "^6.0.0"
|
| 7349 |
+
},
|
| 7350 |
+
"funding": {
|
| 7351 |
+
"type": "opencollective",
|
| 7352 |
+
"url": "https://opencollective.com/unified"
|
| 7353 |
+
}
|
| 7354 |
+
},
|
| 7355 |
"node_modules/update-browserslist-db": {
|
| 7356 |
"version": "1.2.3",
|
| 7357 |
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
|
|
|
|
| 7400 |
"dev": true,
|
| 7401 |
"license": "MIT"
|
| 7402 |
},
|
| 7403 |
+
"node_modules/vfile": {
|
| 7404 |
+
"version": "6.0.3",
|
| 7405 |
+
"resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
|
| 7406 |
+
"integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==",
|
| 7407 |
+
"license": "MIT",
|
| 7408 |
+
"dependencies": {
|
| 7409 |
+
"@types/unist": "^3.0.0",
|
| 7410 |
+
"vfile-message": "^4.0.0"
|
| 7411 |
+
},
|
| 7412 |
+
"funding": {
|
| 7413 |
+
"type": "opencollective",
|
| 7414 |
+
"url": "https://opencollective.com/unified"
|
| 7415 |
+
}
|
| 7416 |
+
},
|
| 7417 |
+
"node_modules/vfile-message": {
|
| 7418 |
+
"version": "4.0.3",
|
| 7419 |
+
"resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz",
|
| 7420 |
+
"integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==",
|
| 7421 |
+
"license": "MIT",
|
| 7422 |
+
"dependencies": {
|
| 7423 |
+
"@types/unist": "^3.0.0",
|
| 7424 |
+
"unist-util-stringify-position": "^4.0.0"
|
| 7425 |
+
},
|
| 7426 |
+
"funding": {
|
| 7427 |
+
"type": "opencollective",
|
| 7428 |
+
"url": "https://opencollective.com/unified"
|
| 7429 |
+
}
|
| 7430 |
+
},
|
| 7431 |
"node_modules/victory-vendor": {
|
| 7432 |
"version": "36.9.2",
|
| 7433 |
"resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz",
|
|
|
|
| 8274 |
"funding": {
|
| 8275 |
"url": "https://github.com/sponsors/sindresorhus"
|
| 8276 |
}
|
| 8277 |
+
},
|
| 8278 |
+
"node_modules/zwitch": {
|
| 8279 |
+
"version": "2.0.4",
|
| 8280 |
+
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
|
| 8281 |
+
"integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==",
|
| 8282 |
+
"license": "MIT",
|
| 8283 |
+
"funding": {
|
| 8284 |
+
"type": "github",
|
| 8285 |
+
"url": "https://github.com/sponsors/wooorm"
|
| 8286 |
+
}
|
| 8287 |
}
|
| 8288 |
}
|
| 8289 |
}
|
|
@@ -16,8 +16,10 @@
|
|
| 16 |
"lucide-react": "^0.460.0",
|
| 17 |
"react": "^18.3.1",
|
| 18 |
"react-dom": "^18.3.1",
|
|
|
|
| 19 |
"react-router-dom": "^6.28.0",
|
| 20 |
-
"recharts": "^2.13.3"
|
|
|
|
| 21 |
},
|
| 22 |
"devDependencies": {
|
| 23 |
"@eslint/js": "^9.13.0",
|
|
|
|
| 16 |
"lucide-react": "^0.460.0",
|
| 17 |
"react": "^18.3.1",
|
| 18 |
"react-dom": "^18.3.1",
|
| 19 |
+
"react-markdown": "^10.1.0",
|
| 20 |
"react-router-dom": "^6.28.0",
|
| 21 |
+
"recharts": "^2.13.3",
|
| 22 |
+
"remark-gfm": "^4.0.1"
|
| 23 |
},
|
| 24 |
"devDependencies": {
|
| 25 |
"@eslint/js": "^9.13.0",
|
|
@@ -1,9 +1,10 @@
|
|
| 1 |
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
| 2 |
import { BrowserRouter, Routes, Route, Link, useLocation } from 'react-router-dom';
|
| 3 |
-
import { Home, Settings as SettingsIcon, Package,
|
| 4 |
import Dashboard from './components/Dashboard';
|
| 5 |
import Settings from './components/Settings';
|
| 6 |
import PluginsPage from './components/PluginsPage';
|
|
|
|
| 7 |
import { classNames } from './utils/helpers';
|
| 8 |
|
| 9 |
const queryClient = new QueryClient({
|
|
@@ -21,39 +22,40 @@ function NavBar() {
|
|
| 21 |
const navItems = [
|
| 22 |
{ path: '/', label: 'Dashboard', icon: Home },
|
| 23 |
{ path: '/plugins', label: 'Plugins', icon: Package },
|
|
|
|
| 24 |
{ path: '/settings', label: 'Settings', icon: SettingsIcon },
|
| 25 |
];
|
| 26 |
|
| 27 |
return (
|
| 28 |
<nav className="bg-gradient-to-r from-gray-900 via-gray-900 to-gray-800 border-b border-gray-700/50 shadow-lg">
|
| 29 |
-
<div className="
|
| 30 |
-
<div className="flex items-center justify-between h-
|
| 31 |
{/* Logo */}
|
| 32 |
<div className="flex items-center gap-3">
|
| 33 |
<div className="relative">
|
| 34 |
-
<div className="w-
|
| 35 |
-
<Brain className="w-
|
| 36 |
</div>
|
| 37 |
-
<div className="absolute -top-
|
| 38 |
</div>
|
| 39 |
<div className="flex flex-col">
|
| 40 |
-
<span className="text-
|
| 41 |
ScrapeRL
|
| 42 |
</span>
|
| 43 |
-
<span className="text-[
|
| 44 |
RL-POWERED SCRAPING
|
| 45 |
</span>
|
| 46 |
</div>
|
| 47 |
</div>
|
| 48 |
|
| 49 |
{/* Navigation */}
|
| 50 |
-
<div className="flex items-center gap-
|
| 51 |
{navItems.map(({ path, label, icon: Icon }) => (
|
| 52 |
<Link
|
| 53 |
key={path}
|
| 54 |
to={path}
|
| 55 |
className={classNames(
|
| 56 |
-
'flex items-center gap-2 px-
|
| 57 |
location.pathname === path
|
| 58 |
? 'bg-gradient-to-r from-emerald-500/20 to-cyan-500/20 text-emerald-400 shadow-lg shadow-emerald-500/10 border border-emerald-500/30'
|
| 59 |
: 'text-gray-400 hover:text-gray-200 hover:bg-gray-800/50'
|
|
@@ -90,38 +92,16 @@ function App() {
|
|
| 90 |
return (
|
| 91 |
<QueryClientProvider client={queryClient}>
|
| 92 |
<BrowserRouter>
|
| 93 |
-
<div className="min-h-screen bg-gradient-to-br from-gray-950 via-gray-900 to-gray-950 text-gray-100">
|
| 94 |
<NavBar />
|
| 95 |
-
<main className="
|
| 96 |
<Routes>
|
| 97 |
<Route path="/" element={<Dashboard />} />
|
| 98 |
-
<Route path="/plugins" element={<PluginsPage />} />
|
|
|
|
| 99 |
<Route path="/settings" element={<Settings />} />
|
| 100 |
</Routes>
|
| 101 |
</main>
|
| 102 |
-
|
| 103 |
-
{/* Footer */}
|
| 104 |
-
<footer className="border-t border-gray-800/50 bg-gray-900/30">
|
| 105 |
-
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
|
| 106 |
-
<div className="flex flex-col sm:flex-row items-center justify-between gap-2 text-xs text-gray-500">
|
| 107 |
-
<div className="flex items-center gap-2">
|
| 108 |
-
<Activity className="w-3.5 h-3.5 text-emerald-500" />
|
| 109 |
-
<span>ScrapeRL v0.1.0 • Reinforcement Learning Web Scraping</span>
|
| 110 |
-
</div>
|
| 111 |
-
<div className="flex items-center gap-4">
|
| 112 |
-
<span>Built with FastAPI + React</span>
|
| 113 |
-
<a
|
| 114 |
-
href="https://huggingface.co/spaces/NeerajCodz/scrapeRL"
|
| 115 |
-
target="_blank"
|
| 116 |
-
rel="noopener noreferrer"
|
| 117 |
-
className="text-cyan-500 hover:text-cyan-400 transition-colors"
|
| 118 |
-
>
|
| 119 |
-
🤗 HuggingFace
|
| 120 |
-
</a>
|
| 121 |
-
</div>
|
| 122 |
-
</div>
|
| 123 |
-
</div>
|
| 124 |
-
</footer>
|
| 125 |
</div>
|
| 126 |
</BrowserRouter>
|
| 127 |
</QueryClientProvider>
|
|
|
|
| 1 |
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
| 2 |
import { BrowserRouter, Routes, Route, Link, useLocation } from 'react-router-dom';
|
| 3 |
+
import { Home, Settings as SettingsIcon, Package, Zap, Brain, Github, Book } from 'lucide-react';
|
| 4 |
import Dashboard from './components/Dashboard';
|
| 5 |
import Settings from './components/Settings';
|
| 6 |
import PluginsPage from './components/PluginsPage';
|
| 7 |
+
import DocsPage from './components/DocsPage';
|
| 8 |
import { classNames } from './utils/helpers';
|
| 9 |
|
| 10 |
const queryClient = new QueryClient({
|
|
|
|
| 22 |
const navItems = [
|
| 23 |
{ path: '/', label: 'Dashboard', icon: Home },
|
| 24 |
{ path: '/plugins', label: 'Plugins', icon: Package },
|
| 25 |
+
{ path: '/docs', label: 'Docs', icon: Book },
|
| 26 |
{ path: '/settings', label: 'Settings', icon: SettingsIcon },
|
| 27 |
];
|
| 28 |
|
| 29 |
return (
|
| 30 |
<nav className="bg-gradient-to-r from-gray-900 via-gray-900 to-gray-800 border-b border-gray-700/50 shadow-lg">
|
| 31 |
+
<div className="px-4 sm:px-6 lg:px-8">
|
| 32 |
+
<div className="flex items-center justify-between h-14">
|
| 33 |
{/* Logo */}
|
| 34 |
<div className="flex items-center gap-3">
|
| 35 |
<div className="relative">
|
| 36 |
+
<div className="w-9 h-9 bg-gradient-to-br from-emerald-500 via-cyan-500 to-blue-500 rounded-lg flex items-center justify-center shadow-lg shadow-emerald-500/20">
|
| 37 |
+
<Brain className="w-5 h-5 text-white" />
|
| 38 |
</div>
|
| 39 |
+
<div className="absolute -top-0.5 -right-0.5 w-2.5 h-2.5 bg-emerald-400 rounded-full animate-pulse" />
|
| 40 |
</div>
|
| 41 |
<div className="flex flex-col">
|
| 42 |
+
<span className="text-lg font-bold bg-gradient-to-r from-emerald-400 via-cyan-400 to-blue-400 bg-clip-text text-transparent">
|
| 43 |
ScrapeRL
|
| 44 |
</span>
|
| 45 |
+
<span className="text-[9px] text-gray-500 font-medium tracking-wider -mt-0.5">
|
| 46 |
RL-POWERED SCRAPING
|
| 47 |
</span>
|
| 48 |
</div>
|
| 49 |
</div>
|
| 50 |
|
| 51 |
{/* Navigation */}
|
| 52 |
+
<div className="flex items-center gap-1">
|
| 53 |
{navItems.map(({ path, label, icon: Icon }) => (
|
| 54 |
<Link
|
| 55 |
key={path}
|
| 56 |
to={path}
|
| 57 |
className={classNames(
|
| 58 |
+
'flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-medium transition-all duration-200',
|
| 59 |
location.pathname === path
|
| 60 |
? 'bg-gradient-to-r from-emerald-500/20 to-cyan-500/20 text-emerald-400 shadow-lg shadow-emerald-500/10 border border-emerald-500/30'
|
| 61 |
: 'text-gray-400 hover:text-gray-200 hover:bg-gray-800/50'
|
|
|
|
| 92 |
return (
|
| 93 |
<QueryClientProvider client={queryClient}>
|
| 94 |
<BrowserRouter>
|
| 95 |
+
<div className="min-h-screen bg-gradient-to-br from-gray-950 via-gray-900 to-gray-950 text-gray-100 flex flex-col">
|
| 96 |
<NavBar />
|
| 97 |
+
<main className="flex-1">
|
| 98 |
<Routes>
|
| 99 |
<Route path="/" element={<Dashboard />} />
|
| 100 |
+
<Route path="/plugins" element={<PluginsPage className="p-6" />} />
|
| 101 |
+
<Route path="/docs" element={<DocsPage />} />
|
| 102 |
<Route path="/settings" element={<Settings />} />
|
| 103 |
</Routes>
|
| 104 |
</main>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 105 |
</div>
|
| 106 |
</BrowserRouter>
|
| 107 |
</QueryClientProvider>
|
|
@@ -1,8 +1,8 @@
|
|
| 1 |
-
import React from 'react';
|
|
|
|
| 2 |
import {
|
| 3 |
Activity,
|
| 4 |
Zap,
|
| 5 |
-
Brain,
|
| 6 |
Target,
|
| 7 |
Clock,
|
| 8 |
TrendingUp,
|
|
@@ -10,181 +10,907 @@ import {
|
|
| 10 |
Cpu,
|
| 11 |
Globe,
|
| 12 |
Play,
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
} from 'lucide-react';
|
| 15 |
-
import {
|
| 16 |
-
import {
|
| 17 |
-
import {
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
value: string | number;
|
| 28 |
-
change?: string;
|
| 29 |
-
color: 'emerald' | 'cyan' | 'purple' | 'amber';
|
| 30 |
}
|
| 31 |
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
return (
|
| 41 |
-
<div className=
|
| 42 |
-
<div className="
|
| 43 |
-
<div className=
|
| 44 |
-
<
|
|
|
|
|
|
|
|
|
|
| 45 |
</div>
|
| 46 |
-
|
| 47 |
-
<span className="text-xs text-emerald-400 flex items-center gap-1">
|
| 48 |
-
<TrendingUp className="w-3 h-3" />
|
| 49 |
-
{change}
|
| 50 |
-
</span>
|
| 51 |
-
)}
|
| 52 |
</div>
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
</div>
|
| 57 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
);
|
| 59 |
};
|
| 60 |
|
|
|
|
| 61 |
export const Dashboard: React.FC = () => {
|
| 62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
|
| 64 |
return (
|
| 65 |
-
<div className="
|
| 66 |
-
{/*
|
| 67 |
-
<div className="flex
|
| 68 |
-
<div>
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
<
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
<
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
<
|
| 83 |
-
|
| 84 |
-
<
|
| 85 |
-
|
| 86 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
</div>
|
| 88 |
</div>
|
| 89 |
|
| 90 |
-
{/*
|
| 91 |
-
<div className="
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
</div>
|
| 118 |
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
<
|
| 137 |
-
</
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
</div>
|
| 139 |
|
| 140 |
-
{/* Center
|
| 141 |
-
<div className="
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
</div>
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
<
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 165 |
</div>
|
| 166 |
</div>
|
| 167 |
</div>
|
| 168 |
|
| 169 |
-
{/* Right
|
| 170 |
-
<div className="
|
| 171 |
-
|
| 172 |
-
|
|
|
|
| 173 |
<Database className="w-4 h-4 text-pink-400" />
|
| 174 |
-
|
| 175 |
-
</
|
| 176 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 177 |
</div>
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 185 |
</div>
|
| 186 |
</div>
|
| 187 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 188 |
</div>
|
| 189 |
);
|
| 190 |
};
|
|
|
|
| 1 |
+
import React, { useState } from 'react';
|
| 2 |
+
import { useQuery } from '@tanstack/react-query';
|
| 3 |
import {
|
| 4 |
Activity,
|
| 5 |
Zap,
|
|
|
|
| 6 |
Target,
|
| 7 |
Clock,
|
| 8 |
TrendingUp,
|
|
|
|
| 10 |
Cpu,
|
| 11 |
Globe,
|
| 12 |
Play,
|
| 13 |
+
Pause,
|
| 14 |
+
ChevronDown,
|
| 15 |
+
ChevronRight,
|
| 16 |
+
MoreHorizontal,
|
| 17 |
+
Terminal,
|
| 18 |
+
Settings,
|
| 19 |
+
Wrench,
|
| 20 |
+
Plug,
|
| 21 |
+
Eye,
|
| 22 |
+
Bot,
|
| 23 |
+
X,
|
| 24 |
+
Check,
|
| 25 |
+
Layers,
|
| 26 |
+
FileText,
|
| 27 |
+
List,
|
| 28 |
} from 'lucide-react';
|
| 29 |
+
import { Badge } from '@/components/ui/Badge';
|
| 30 |
+
import { classNames } from '@/utils/helpers';
|
| 31 |
+
import { apiClient } from '@/api/client';
|
| 32 |
+
|
| 33 |
+
// Types
|
| 34 |
+
interface TaskInput {
|
| 35 |
+
url: string;
|
| 36 |
+
instruction: string;
|
| 37 |
+
taskType: 'low' | 'medium' | 'high';
|
| 38 |
+
selectedModel: string;
|
| 39 |
+
selectedAgents: string[];
|
| 40 |
+
enabledPlugins: string[];
|
|
|
|
|
|
|
|
|
|
| 41 |
}
|
| 42 |
|
| 43 |
+
interface LogEntry {
|
| 44 |
+
id: string;
|
| 45 |
+
timestamp: string;
|
| 46 |
+
level: 'info' | 'warn' | 'error' | 'debug';
|
| 47 |
+
message: string;
|
| 48 |
+
source?: string;
|
| 49 |
+
}
|
| 50 |
|
| 51 |
+
interface EpisodeStats {
|
| 52 |
+
total: number;
|
| 53 |
+
min: number;
|
| 54 |
+
max: number;
|
| 55 |
+
avg: number;
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
interface AgentOption {
|
| 59 |
+
id: string;
|
| 60 |
+
name: string;
|
| 61 |
+
description: string;
|
| 62 |
+
active?: boolean;
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
interface ModelOption {
|
| 66 |
+
provider: string;
|
| 67 |
+
model: string;
|
| 68 |
+
name: string;
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
// Popup Components
|
| 72 |
+
interface PopupProps {
|
| 73 |
+
title: string;
|
| 74 |
+
isOpen: boolean;
|
| 75 |
+
onClose: () => void;
|
| 76 |
+
children: React.ReactNode;
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
const Popup: React.FC<PopupProps> = ({ title, isOpen, onClose, children }) => {
|
| 80 |
+
if (!isOpen) return null;
|
| 81 |
return (
|
| 82 |
+
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm">
|
| 83 |
+
<div className="bg-gray-800 border border-gray-700 rounded-xl shadow-2xl w-full max-w-lg max-h-[80vh] overflow-hidden">
|
| 84 |
+
<div className="flex items-center justify-between px-4 py-3 border-b border-gray-700">
|
| 85 |
+
<h3 className="font-semibold text-white">{title}</h3>
|
| 86 |
+
<button onClick={onClose} className="p-1 text-gray-400 hover:text-white transition-colors">
|
| 87 |
+
<X className="w-5 h-5" />
|
| 88 |
+
</button>
|
| 89 |
</div>
|
| 90 |
+
<div className="p-4 overflow-y-auto max-h-[60vh]">{children}</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
</div>
|
| 92 |
+
</div>
|
| 93 |
+
);
|
| 94 |
+
};
|
| 95 |
+
|
| 96 |
+
// Stats Popup
|
| 97 |
+
const StatsPopup: React.FC<{ isOpen: boolean; onClose: () => void; stats: EpisodeStats; title: string }> = ({
|
| 98 |
+
isOpen,
|
| 99 |
+
onClose,
|
| 100 |
+
stats,
|
| 101 |
+
title,
|
| 102 |
+
}) => (
|
| 103 |
+
<Popup title={title} isOpen={isOpen} onClose={onClose}>
|
| 104 |
+
<div className="grid grid-cols-2 gap-4">
|
| 105 |
+
<div className="p-4 bg-gray-900/50 rounded-lg text-center">
|
| 106 |
+
<p className="text-2xl font-bold text-emerald-400">{stats.total}</p>
|
| 107 |
+
<p className="text-xs text-gray-400">Total</p>
|
| 108 |
+
</div>
|
| 109 |
+
<div className="p-4 bg-gray-900/50 rounded-lg text-center">
|
| 110 |
+
<p className="text-2xl font-bold text-cyan-400">{stats.avg.toFixed(2)}</p>
|
| 111 |
+
<p className="text-xs text-gray-400">Average</p>
|
| 112 |
+
</div>
|
| 113 |
+
<div className="p-4 bg-gray-900/50 rounded-lg text-center">
|
| 114 |
+
<p className="text-2xl font-bold text-amber-400">{stats.min.toFixed(2)}</p>
|
| 115 |
+
<p className="text-xs text-gray-400">Minimum</p>
|
| 116 |
+
</div>
|
| 117 |
+
<div className="p-4 bg-gray-900/50 rounded-lg text-center">
|
| 118 |
+
<p className="text-2xl font-bold text-purple-400">{stats.max.toFixed(2)}</p>
|
| 119 |
+
<p className="text-xs text-gray-400">Maximum</p>
|
| 120 |
</div>
|
| 121 |
</div>
|
| 122 |
+
</Popup>
|
| 123 |
+
);
|
| 124 |
+
|
| 125 |
+
// Accordion Component
|
| 126 |
+
interface AccordionProps {
|
| 127 |
+
title: string;
|
| 128 |
+
icon: React.ElementType;
|
| 129 |
+
badge?: string | number;
|
| 130 |
+
color: string;
|
| 131 |
+
children: React.ReactNode;
|
| 132 |
+
defaultOpen?: boolean;
|
| 133 |
+
}
|
| 134 |
+
|
| 135 |
+
const Accordion: React.FC<AccordionProps> = ({ title, icon: Icon, badge, color, children, defaultOpen = false }) => {
|
| 136 |
+
const [isOpen, setIsOpen] = useState(defaultOpen);
|
| 137 |
+
|
| 138 |
+
return (
|
| 139 |
+
<div className="border border-gray-700/50 rounded-lg overflow-hidden">
|
| 140 |
+
<button
|
| 141 |
+
onClick={() => setIsOpen(!isOpen)}
|
| 142 |
+
className="w-full flex items-center justify-between px-3 py-2.5 bg-gray-800/50 hover:bg-gray-800 transition-colors"
|
| 143 |
+
>
|
| 144 |
+
<div className="flex items-center gap-2">
|
| 145 |
+
<Icon className={`w-4 h-4 ${color}`} />
|
| 146 |
+
<span className="text-sm font-medium text-white">{title}</span>
|
| 147 |
+
{badge !== undefined && (
|
| 148 |
+
<Badge variant="neutral" size="sm">{badge}</Badge>
|
| 149 |
+
)}
|
| 150 |
+
</div>
|
| 151 |
+
{isOpen ? <ChevronDown className="w-4 h-4 text-gray-400" /> : <ChevronRight className="w-4 h-4 text-gray-400" />}
|
| 152 |
+
</button>
|
| 153 |
+
{isOpen && <div className="p-3 bg-gray-900/30 border-t border-gray-700/50">{children}</div>}
|
| 154 |
+
</div>
|
| 155 |
);
|
| 156 |
};
|
| 157 |
|
| 158 |
+
// Main Dashboard Component
|
| 159 |
export const Dashboard: React.FC = () => {
|
| 160 |
+
// State
|
| 161 |
+
const [taskInput, setTaskInput] = useState<TaskInput>({
|
| 162 |
+
url: '',
|
| 163 |
+
instruction: '',
|
| 164 |
+
taskType: 'medium',
|
| 165 |
+
selectedModel: 'groq/gpt-oss-120b',
|
| 166 |
+
selectedAgents: ['coordinator', 'scraper'],
|
| 167 |
+
enabledPlugins: ['browser-use', 'firecrawl'],
|
| 168 |
+
});
|
| 169 |
+
const [logs, setLogs] = useState<LogEntry[]>([
|
| 170 |
+
{ id: '1', timestamp: new Date().toISOString(), level: 'info', message: 'System initialized', source: 'system' },
|
| 171 |
+
{ id: '2', timestamp: new Date().toISOString(), level: 'info', message: 'Ready to start episode', source: 'coordinator' },
|
| 172 |
+
]);
|
| 173 |
+
const [isRunning, setIsRunning] = useState(false);
|
| 174 |
+
const [showModelPopup, setShowModelPopup] = useState(false);
|
| 175 |
+
const [showAgentPopup, setShowAgentPopup] = useState(false);
|
| 176 |
+
const [showPluginPopup, setShowPluginPopup] = useState(false);
|
| 177 |
+
const [showTaskTypePopup, setShowTaskTypePopup] = useState(false);
|
| 178 |
+
const [showStatsPopup, setShowStatsPopup] = useState<'episodes' | 'steps' | 'reward' | null>(null);
|
| 179 |
+
|
| 180 |
+
// API Queries
|
| 181 |
+
const { data: health } = useQuery({
|
| 182 |
+
queryKey: ['health'],
|
| 183 |
+
queryFn: () => apiClient.healthCheck(),
|
| 184 |
+
refetchInterval: 5000,
|
| 185 |
+
});
|
| 186 |
+
|
| 187 |
+
const { data: agentsData } = useQuery({
|
| 188 |
+
queryKey: ['agents'],
|
| 189 |
+
queryFn: async () => {
|
| 190 |
+
const res = await fetch('/api/agents/');
|
| 191 |
+
return res.json();
|
| 192 |
+
},
|
| 193 |
+
});
|
| 194 |
+
|
| 195 |
+
useQuery({
|
| 196 |
+
queryKey: ['plugins'],
|
| 197 |
+
queryFn: async () => {
|
| 198 |
+
const res = await fetch('/api/plugins/');
|
| 199 |
+
return res.json();
|
| 200 |
+
},
|
| 201 |
+
});
|
| 202 |
+
|
| 203 |
+
const { data: memoryData } = useQuery({
|
| 204 |
+
queryKey: ['memory-stats'],
|
| 205 |
+
queryFn: async () => {
|
| 206 |
+
const res = await fetch('/api/memory/stats/overview');
|
| 207 |
+
return res.json();
|
| 208 |
+
},
|
| 209 |
+
refetchInterval: 3000,
|
| 210 |
+
});
|
| 211 |
+
|
| 212 |
+
const { data: settingsData } = useQuery({
|
| 213 |
+
queryKey: ['client-settings'],
|
| 214 |
+
queryFn: async () => {
|
| 215 |
+
const res = await fetch('/api/settings/');
|
| 216 |
+
return res.json();
|
| 217 |
+
},
|
| 218 |
+
});
|
| 219 |
+
|
| 220 |
+
// Episode Stats (mock data for now)
|
| 221 |
+
const episodeStats: EpisodeStats = { total: 12, min: 3, max: 47, avg: 18.5 };
|
| 222 |
+
const stepStats: EpisodeStats = { total: 156, min: 5, max: 89, avg: 23.4 };
|
| 223 |
+
const rewardStats: EpisodeStats = { total: 847.5, min: -12.3, max: 98.7, avg: 70.6 };
|
| 224 |
+
|
| 225 |
+
// Available options
|
| 226 |
+
const availableModels: ModelOption[] = settingsData?.available_models ?? [
|
| 227 |
+
{ provider: 'groq', model: 'gpt-oss-120b', name: 'GPT-OSS 120B (Groq)' },
|
| 228 |
+
{ provider: 'google', model: 'gemini-2.5-flash', name: 'Gemini 2.5 Flash' },
|
| 229 |
+
{ provider: 'openai', model: 'gpt-4-turbo', name: 'GPT-4 Turbo' },
|
| 230 |
+
{ provider: 'anthropic', model: 'claude-3-opus', name: 'Claude 3 Opus' },
|
| 231 |
+
];
|
| 232 |
+
|
| 233 |
+
const availableAgents: AgentOption[] = agentsData?.agents ?? [
|
| 234 |
+
{ id: 'coordinator', name: 'Coordinator', description: 'Orchestrates all agents', active: true },
|
| 235 |
+
{ id: 'scraper', name: 'Scraper', description: 'Extracts data from pages', active: true },
|
| 236 |
+
{ id: 'navigator', name: 'Navigator', description: 'Handles page navigation', active: false },
|
| 237 |
+
{ id: 'analyzer', name: 'Analyzer', description: 'Analyzes extracted data', active: false },
|
| 238 |
+
{ id: 'validator', name: 'Validator', description: 'Validates data quality', active: false },
|
| 239 |
+
];
|
| 240 |
+
|
| 241 |
+
const pluginCategories = {
|
| 242 |
+
mcps: [
|
| 243 |
+
{ id: 'browser-use', name: 'Browser Use', enabled: true, status: 'active' },
|
| 244 |
+
{ id: 'puppeteer-mcp', name: 'Puppeteer MCP', enabled: false, status: 'idle' },
|
| 245 |
+
{ id: 'playwright-mcp', name: 'Playwright MCP', enabled: false, status: 'idle' },
|
| 246 |
+
],
|
| 247 |
+
skills: [
|
| 248 |
+
{ id: 'web-scraping', name: 'Web Scraping', enabled: true, status: 'active' },
|
| 249 |
+
{ id: 'data-extraction', name: 'Data Extraction', enabled: true, status: 'active' },
|
| 250 |
+
{ id: 'form-filling', name: 'Form Filling', enabled: false, status: 'idle' },
|
| 251 |
+
],
|
| 252 |
+
apis: [
|
| 253 |
+
{ id: 'firecrawl', name: 'Firecrawl', enabled: true, status: 'active' },
|
| 254 |
+
{ id: 'jina-reader', name: 'Jina Reader', enabled: false, status: 'idle' },
|
| 255 |
+
{ id: 'serper', name: 'Serper API', enabled: false, status: 'idle' },
|
| 256 |
+
],
|
| 257 |
+
vision: [
|
| 258 |
+
{ id: 'gpt4-vision', name: 'GPT-4 Vision', enabled: false, status: 'idle' },
|
| 259 |
+
{ id: 'gemini-vision', name: 'Gemini Vision', enabled: false, status: 'idle' },
|
| 260 |
+
{ id: 'claude-vision', name: 'Claude Vision', enabled: false, status: 'idle' },
|
| 261 |
+
],
|
| 262 |
+
};
|
| 263 |
+
|
| 264 |
+
const taskTypes = [
|
| 265 |
+
{ id: 'low', name: 'Low Complexity', description: 'Simple single-page scraping', color: 'emerald' },
|
| 266 |
+
{ id: 'medium', name: 'Medium Complexity', description: 'Multi-page with navigation', color: 'amber' },
|
| 267 |
+
{ id: 'high', name: 'High Complexity', description: 'Complex interactive tasks', color: 'red' },
|
| 268 |
+
];
|
| 269 |
+
|
| 270 |
+
const handleStart = () => {
|
| 271 |
+
setIsRunning(true);
|
| 272 |
+
const newLog: LogEntry = {
|
| 273 |
+
id: Date.now().toString(),
|
| 274 |
+
timestamp: new Date().toISOString(),
|
| 275 |
+
level: 'info',
|
| 276 |
+
message: `Starting episode with URL: ${taskInput.url}`,
|
| 277 |
+
source: 'coordinator',
|
| 278 |
+
};
|
| 279 |
+
setLogs((prev) => [...prev, newLog]);
|
| 280 |
+
};
|
| 281 |
+
|
| 282 |
+
const handleStop = () => {
|
| 283 |
+
setIsRunning(false);
|
| 284 |
+
const newLog: LogEntry = {
|
| 285 |
+
id: Date.now().toString(),
|
| 286 |
+
timestamp: new Date().toISOString(),
|
| 287 |
+
level: 'warn',
|
| 288 |
+
message: 'Episode stopped by user',
|
| 289 |
+
source: 'system',
|
| 290 |
+
};
|
| 291 |
+
setLogs((prev) => [...prev, newLog]);
|
| 292 |
+
};
|
| 293 |
+
|
| 294 |
+
const formatTime = (isoString: string) => {
|
| 295 |
+
return new Date(isoString).toLocaleTimeString('en-US', { hour12: false });
|
| 296 |
+
};
|
| 297 |
+
|
| 298 |
+
const getLogLevelColor = (level: LogEntry['level']) => {
|
| 299 |
+
const colors = {
|
| 300 |
+
info: 'text-cyan-400',
|
| 301 |
+
warn: 'text-amber-400',
|
| 302 |
+
error: 'text-red-400',
|
| 303 |
+
debug: 'text-gray-400',
|
| 304 |
+
};
|
| 305 |
+
return colors[level];
|
| 306 |
+
};
|
| 307 |
|
| 308 |
return (
|
| 309 |
+
<div className="h-[calc(100vh-80px)] flex flex-col">
|
| 310 |
+
{/* Input Section */}
|
| 311 |
+
<div className="flex-shrink-0 p-4 bg-gray-800/50 border-b border-gray-700/50">
|
| 312 |
+
<div className="flex flex-wrap items-end gap-4">
|
| 313 |
+
{/* URL Input */}
|
| 314 |
+
<div className="flex-1 min-w-[300px]">
|
| 315 |
+
<label className="text-xs text-gray-400 mb-1 block">Target URL</label>
|
| 316 |
+
<input
|
| 317 |
+
type="url"
|
| 318 |
+
placeholder="https://example.com/page-to-scrape"
|
| 319 |
+
value={taskInput.url}
|
| 320 |
+
onChange={(e) => setTaskInput((p) => ({ ...p, url: e.target.value }))}
|
| 321 |
+
className="w-full px-3 py-2 bg-gray-900/50 border border-gray-700/50 rounded-lg text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-emerald-500/50 focus:border-emerald-500/50"
|
| 322 |
+
/>
|
| 323 |
+
</div>
|
| 324 |
+
|
| 325 |
+
{/* Instruction */}
|
| 326 |
+
<div className="flex-1 min-w-[300px]">
|
| 327 |
+
<label className="text-xs text-gray-400 mb-1 block">Instruction</label>
|
| 328 |
+
<input
|
| 329 |
+
type="text"
|
| 330 |
+
placeholder="Extract all product prices and names..."
|
| 331 |
+
value={taskInput.instruction}
|
| 332 |
+
onChange={(e) => setTaskInput((p) => ({ ...p, instruction: e.target.value }))}
|
| 333 |
+
className="w-full px-3 py-2 bg-gray-900/50 border border-gray-700/50 rounded-lg text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-emerald-500/50 focus:border-emerald-500/50"
|
| 334 |
+
/>
|
| 335 |
+
</div>
|
| 336 |
+
|
| 337 |
+
{/* Selection Buttons */}
|
| 338 |
+
<div className="flex items-center gap-2">
|
| 339 |
+
<button
|
| 340 |
+
onClick={() => setShowModelPopup(true)}
|
| 341 |
+
className="px-3 py-2 bg-cyan-500/10 hover:bg-cyan-500/20 border border-cyan-500/30 text-cyan-400 rounded-lg text-sm font-medium transition-colors flex items-center gap-2"
|
| 342 |
+
>
|
| 343 |
+
<Cpu className="w-4 h-4" />
|
| 344 |
+
Model
|
| 345 |
+
</button>
|
| 346 |
+
<button
|
| 347 |
+
onClick={() => setShowAgentPopup(true)}
|
| 348 |
+
className="px-3 py-2 bg-purple-500/10 hover:bg-purple-500/20 border border-purple-500/30 text-purple-400 rounded-lg text-sm font-medium transition-colors flex items-center gap-2"
|
| 349 |
+
>
|
| 350 |
+
<Bot className="w-4 h-4" />
|
| 351 |
+
Agents
|
| 352 |
+
</button>
|
| 353 |
+
<button
|
| 354 |
+
onClick={() => setShowPluginPopup(true)}
|
| 355 |
+
className="px-3 py-2 bg-amber-500/10 hover:bg-amber-500/20 border border-amber-500/30 text-amber-400 rounded-lg text-sm font-medium transition-colors flex items-center gap-2"
|
| 356 |
+
>
|
| 357 |
+
<Plug className="w-4 h-4" />
|
| 358 |
+
Plugins
|
| 359 |
+
</button>
|
| 360 |
+
<button
|
| 361 |
+
onClick={() => setShowTaskTypePopup(true)}
|
| 362 |
+
className={classNames(
|
| 363 |
+
'px-3 py-2 border rounded-lg text-sm font-medium transition-colors flex items-center gap-2',
|
| 364 |
+
taskInput.taskType === 'low' && 'bg-emerald-500/10 border-emerald-500/30 text-emerald-400',
|
| 365 |
+
taskInput.taskType === 'medium' && 'bg-amber-500/10 border-amber-500/30 text-amber-400',
|
| 366 |
+
taskInput.taskType === 'high' && 'bg-red-500/10 border-red-500/30 text-red-400'
|
| 367 |
+
)}
|
| 368 |
+
>
|
| 369 |
+
<Target className="w-4 h-4" />
|
| 370 |
+
{taskInput.taskType.charAt(0).toUpperCase() + taskInput.taskType.slice(1)}
|
| 371 |
+
</button>
|
| 372 |
+
</div>
|
| 373 |
+
|
| 374 |
+
{/* Start/Stop Button */}
|
| 375 |
+
{isRunning ? (
|
| 376 |
+
<button
|
| 377 |
+
onClick={handleStop}
|
| 378 |
+
className="px-5 py-2 bg-red-500 hover:bg-red-600 text-white rounded-lg font-medium transition-colors flex items-center gap-2 shadow-lg shadow-red-500/20"
|
| 379 |
+
>
|
| 380 |
+
<Pause className="w-4 h-4" />
|
| 381 |
+
Stop
|
| 382 |
+
</button>
|
| 383 |
+
) : (
|
| 384 |
+
<button
|
| 385 |
+
onClick={handleStart}
|
| 386 |
+
disabled={!taskInput.url}
|
| 387 |
+
className="px-5 py-2 bg-emerald-500 hover:bg-emerald-600 disabled:bg-gray-600 disabled:cursor-not-allowed text-white rounded-lg font-medium transition-colors flex items-center gap-2 shadow-lg shadow-emerald-500/20"
|
| 388 |
+
>
|
| 389 |
+
<Play className="w-4 h-4" />
|
| 390 |
+
Start
|
| 391 |
+
</button>
|
| 392 |
+
)}
|
| 393 |
</div>
|
| 394 |
</div>
|
| 395 |
|
| 396 |
+
{/* Main Content - 3 Column Layout */}
|
| 397 |
+
<div className="flex-1 flex overflow-hidden">
|
| 398 |
+
{/* Left Sidebar - Accordions */}
|
| 399 |
+
<div className="w-64 flex-shrink-0 bg-gray-800/30 border-r border-gray-700/50 overflow-y-auto p-3 space-y-2">
|
| 400 |
+
{/* Agents Accordion */}
|
| 401 |
+
<Accordion title="Agents" icon={Bot} badge={taskInput.selectedAgents.length} color="text-purple-400" defaultOpen>
|
| 402 |
+
<div className="space-y-2">
|
| 403 |
+
{availableAgents.map((agent) => {
|
| 404 |
+
const isActive = taskInput.selectedAgents.includes(agent.id);
|
| 405 |
+
return (
|
| 406 |
+
<div
|
| 407 |
+
key={agent.id}
|
| 408 |
+
className={classNames(
|
| 409 |
+
'flex items-center justify-between p-2 rounded-lg transition-colors',
|
| 410 |
+
isActive ? 'bg-purple-500/10 border border-purple-500/30' : 'bg-gray-800/50'
|
| 411 |
+
)}
|
| 412 |
+
>
|
| 413 |
+
<div className="flex items-center gap-2">
|
| 414 |
+
<div className={classNames('w-2 h-2 rounded-full', isActive ? 'bg-emerald-400' : 'bg-gray-500')} />
|
| 415 |
+
<span className="text-xs text-white">{agent.name}</span>
|
| 416 |
+
</div>
|
| 417 |
+
{isActive && <Clock className="w-3 h-3 text-gray-400" />}
|
| 418 |
+
</div>
|
| 419 |
+
);
|
| 420 |
+
})}
|
| 421 |
+
</div>
|
| 422 |
+
</Accordion>
|
|
|
|
| 423 |
|
| 424 |
+
{/* MCPs Accordion */}
|
| 425 |
+
<Accordion title="MCPs" icon={Wrench} badge={pluginCategories.mcps.filter(p => p.enabled).length} color="text-amber-400">
|
| 426 |
+
<div className="space-y-2">
|
| 427 |
+
{pluginCategories.mcps.map((plugin) => (
|
| 428 |
+
<div
|
| 429 |
+
key={plugin.id}
|
| 430 |
+
className={classNames(
|
| 431 |
+
'flex items-center justify-between p-2 rounded-lg',
|
| 432 |
+
plugin.enabled ? 'bg-amber-500/10 border border-amber-500/30' : 'bg-gray-800/50'
|
| 433 |
+
)}
|
| 434 |
+
>
|
| 435 |
+
<span className="text-xs text-white">{plugin.name}</span>
|
| 436 |
+
<Badge variant={plugin.status === 'active' ? 'success' : 'neutral'} size="sm">
|
| 437 |
+
{plugin.status}
|
| 438 |
+
</Badge>
|
| 439 |
+
</div>
|
| 440 |
+
))}
|
| 441 |
+
</div>
|
| 442 |
+
</Accordion>
|
| 443 |
+
|
| 444 |
+
{/* Skills Accordion */}
|
| 445 |
+
<Accordion title="Skills" icon={Zap} badge={pluginCategories.skills.filter(p => p.enabled).length} color="text-cyan-400">
|
| 446 |
+
<div className="space-y-2">
|
| 447 |
+
{pluginCategories.skills.map((plugin) => (
|
| 448 |
+
<div
|
| 449 |
+
key={plugin.id}
|
| 450 |
+
className={classNames(
|
| 451 |
+
'flex items-center justify-between p-2 rounded-lg',
|
| 452 |
+
plugin.enabled ? 'bg-cyan-500/10 border border-cyan-500/30' : 'bg-gray-800/50'
|
| 453 |
+
)}
|
| 454 |
+
>
|
| 455 |
+
<span className="text-xs text-white">{plugin.name}</span>
|
| 456 |
+
<Badge variant={plugin.status === 'active' ? 'success' : 'neutral'} size="sm">
|
| 457 |
+
{plugin.status}
|
| 458 |
+
</Badge>
|
| 459 |
+
</div>
|
| 460 |
+
))}
|
| 461 |
+
</div>
|
| 462 |
+
</Accordion>
|
| 463 |
+
|
| 464 |
+
{/* APIs Accordion */}
|
| 465 |
+
<Accordion title="APIs" icon={Plug} badge={pluginCategories.apis.filter(p => p.enabled).length} color="text-emerald-400">
|
| 466 |
+
<div className="space-y-2">
|
| 467 |
+
{pluginCategories.apis.map((plugin) => (
|
| 468 |
+
<div
|
| 469 |
+
key={plugin.id}
|
| 470 |
+
className={classNames(
|
| 471 |
+
'flex items-center justify-between p-2 rounded-lg',
|
| 472 |
+
plugin.enabled ? 'bg-emerald-500/10 border border-emerald-500/30' : 'bg-gray-800/50'
|
| 473 |
+
)}
|
| 474 |
+
>
|
| 475 |
+
<span className="text-xs text-white">{plugin.name}</span>
|
| 476 |
+
<Badge variant={plugin.status === 'active' ? 'success' : 'neutral'} size="sm">
|
| 477 |
+
{plugin.status}
|
| 478 |
+
</Badge>
|
| 479 |
+
</div>
|
| 480 |
+
))}
|
| 481 |
+
</div>
|
| 482 |
+
</Accordion>
|
| 483 |
+
|
| 484 |
+
{/* Vision Accordion */}
|
| 485 |
+
<Accordion title="Vision" icon={Eye} badge={pluginCategories.vision.filter(p => p.enabled).length} color="text-pink-400">
|
| 486 |
+
<div className="space-y-2">
|
| 487 |
+
{pluginCategories.vision.map((plugin) => (
|
| 488 |
+
<div
|
| 489 |
+
key={plugin.id}
|
| 490 |
+
className={classNames(
|
| 491 |
+
'flex items-center justify-between p-2 rounded-lg',
|
| 492 |
+
plugin.enabled ? 'bg-pink-500/10 border border-pink-500/30' : 'bg-gray-800/50'
|
| 493 |
+
)}
|
| 494 |
+
>
|
| 495 |
+
<span className="text-xs text-white">{plugin.name}</span>
|
| 496 |
+
<Badge variant={plugin.status === 'active' ? 'success' : 'neutral'} size="sm">
|
| 497 |
+
{plugin.status}
|
| 498 |
+
</Badge>
|
| 499 |
+
</div>
|
| 500 |
+
))}
|
| 501 |
+
</div>
|
| 502 |
+
</Accordion>
|
| 503 |
+
|
| 504 |
+
{/* Tools Accordion */}
|
| 505 |
+
<Accordion title="Tools" icon={Wrench} color="text-blue-400">
|
| 506 |
+
<div className="space-y-2 text-xs text-gray-400">
|
| 507 |
+
<div className="flex items-center justify-between p-2 bg-gray-800/50 rounded-lg">
|
| 508 |
+
<span>HTTP Client</span>
|
| 509 |
+
<Badge variant="success" size="sm">ready</Badge>
|
| 510 |
+
</div>
|
| 511 |
+
<div className="flex items-center justify-between p-2 bg-gray-800/50 rounded-lg">
|
| 512 |
+
<span>HTML Parser</span>
|
| 513 |
+
<Badge variant="success" size="sm">ready</Badge>
|
| 514 |
+
</div>
|
| 515 |
+
<div className="flex items-center justify-between p-2 bg-gray-800/50 rounded-lg">
|
| 516 |
+
<span>JSON Extractor</span>
|
| 517 |
+
<Badge variant="success" size="sm">ready</Badge>
|
| 518 |
+
</div>
|
| 519 |
+
</div>
|
| 520 |
+
</Accordion>
|
| 521 |
</div>
|
| 522 |
|
| 523 |
+
{/* Center Content */}
|
| 524 |
+
<div className="flex-1 flex flex-col overflow-hidden">
|
| 525 |
+
{/* Stats Header */}
|
| 526 |
+
<div className="flex-shrink-0 p-3 bg-gray-800/30 border-b border-gray-700/50">
|
| 527 |
+
<div className="flex items-center justify-between">
|
| 528 |
+
<div className="flex items-center gap-4">
|
| 529 |
+
{/* Episodes */}
|
| 530 |
+
<div className="flex items-center gap-2">
|
| 531 |
+
<div className="p-1.5 bg-emerald-500/20 rounded">
|
| 532 |
+
<Layers className="w-4 h-4 text-emerald-400" />
|
| 533 |
+
</div>
|
| 534 |
+
<div>
|
| 535 |
+
<p className="text-lg font-bold text-white">{episodeStats.total}</p>
|
| 536 |
+
<p className="text-[10px] text-gray-500">Episodes</p>
|
| 537 |
+
</div>
|
| 538 |
+
<button
|
| 539 |
+
onClick={() => setShowStatsPopup('episodes')}
|
| 540 |
+
className="p-1 text-gray-500 hover:text-gray-300"
|
| 541 |
+
>
|
| 542 |
+
<MoreHorizontal className="w-4 h-4" />
|
| 543 |
+
</button>
|
| 544 |
+
</div>
|
| 545 |
+
|
| 546 |
+
{/* Steps */}
|
| 547 |
+
<div className="flex items-center gap-2">
|
| 548 |
+
<div className="p-1.5 bg-cyan-500/20 rounded">
|
| 549 |
+
<Target className="w-4 h-4 text-cyan-400" />
|
| 550 |
+
</div>
|
| 551 |
+
<div>
|
| 552 |
+
<p className="text-lg font-bold text-white">{stepStats.total}</p>
|
| 553 |
+
<p className="text-[10px] text-gray-500">Steps</p>
|
| 554 |
+
</div>
|
| 555 |
+
<button
|
| 556 |
+
onClick={() => setShowStatsPopup('steps')}
|
| 557 |
+
className="p-1 text-gray-500 hover:text-gray-300"
|
| 558 |
+
>
|
| 559 |
+
<MoreHorizontal className="w-4 h-4" />
|
| 560 |
+
</button>
|
| 561 |
+
</div>
|
| 562 |
+
|
| 563 |
+
{/* Reward */}
|
| 564 |
+
<div className="flex items-center gap-2">
|
| 565 |
+
<div className="p-1.5 bg-purple-500/20 rounded">
|
| 566 |
+
<TrendingUp className="w-4 h-4 text-purple-400" />
|
| 567 |
+
</div>
|
| 568 |
+
<div>
|
| 569 |
+
<p className="text-lg font-bold text-white">{rewardStats.avg.toFixed(1)}</p>
|
| 570 |
+
<p className="text-[10px] text-gray-500">Avg Reward</p>
|
| 571 |
+
</div>
|
| 572 |
+
<button
|
| 573 |
+
onClick={() => setShowStatsPopup('reward')}
|
| 574 |
+
className="p-1 text-gray-500 hover:text-gray-300"
|
| 575 |
+
>
|
| 576 |
+
<MoreHorizontal className="w-4 h-4" />
|
| 577 |
+
</button>
|
| 578 |
+
</div>
|
| 579 |
+
</div>
|
| 580 |
+
|
| 581 |
+
{/* Time & Status */}
|
| 582 |
+
<div className="flex items-center gap-4">
|
| 583 |
+
<div className="text-right">
|
| 584 |
+
<p className="text-sm font-mono text-white">{new Date().toLocaleTimeString()}</p>
|
| 585 |
+
<p className="text-[10px] text-gray-500">Current Time</p>
|
| 586 |
+
</div>
|
| 587 |
+
<div className={classNames('px-3 py-1.5 rounded-lg flex items-center gap-2', isRunning ? 'bg-emerald-500/20' : 'bg-gray-700/50')}>
|
| 588 |
+
<div className={classNames('w-2 h-2 rounded-full', isRunning ? 'bg-emerald-400 animate-pulse' : 'bg-gray-500')} />
|
| 589 |
+
<span className={classNames('text-sm font-medium', isRunning ? 'text-emerald-400' : 'text-gray-400')}>
|
| 590 |
+
{isRunning ? 'Running' : 'Idle'}
|
| 591 |
+
</span>
|
| 592 |
+
</div>
|
| 593 |
+
</div>
|
| 594 |
+
</div>
|
| 595 |
+
</div>
|
| 596 |
+
|
| 597 |
+
{/* Main Visualization Area */}
|
| 598 |
+
<div className="flex-1 overflow-y-auto p-4">
|
| 599 |
+
<div className="h-full bg-gray-900/50 border border-gray-700/50 rounded-xl p-4">
|
| 600 |
+
{isRunning ? (
|
| 601 |
+
<div className="h-full flex flex-col">
|
| 602 |
+
{/* Current Action */}
|
| 603 |
+
<div className="flex-shrink-0 mb-4">
|
| 604 |
+
<div className="flex items-center gap-2 mb-2">
|
| 605 |
+
<Activity className="w-4 h-4 text-emerald-400 animate-pulse" />
|
| 606 |
+
<span className="text-sm font-medium text-white">Current Action</span>
|
| 607 |
+
</div>
|
| 608 |
+
<div className="p-3 bg-gray-800/50 rounded-lg">
|
| 609 |
+
<p className="text-sm text-gray-300">Navigating to: {taskInput.url}</p>
|
| 610 |
+
<p className="text-xs text-gray-500 mt-1">Agent: Scraper | Step: 1/10</p>
|
| 611 |
+
</div>
|
| 612 |
+
</div>
|
| 613 |
+
|
| 614 |
+
{/* Observation Preview */}
|
| 615 |
+
<div className="flex-1 overflow-auto">
|
| 616 |
+
<div className="flex items-center gap-2 mb-2">
|
| 617 |
+
<Globe className="w-4 h-4 text-cyan-400" />
|
| 618 |
+
<span className="text-sm font-medium text-white">Page Observation</span>
|
| 619 |
+
</div>
|
| 620 |
+
<div className="p-3 bg-gray-800/50 rounded-lg min-h-[200px]">
|
| 621 |
+
<pre className="text-xs text-gray-400 font-mono whitespace-pre-wrap">
|
| 622 |
+
{`{
|
| 623 |
+
"url": "${taskInput.url || 'N/A'}",
|
| 624 |
+
"title": "Loading...",
|
| 625 |
+
"elements": [],
|
| 626 |
+
"links": [],
|
| 627 |
+
"text_content": "..."
|
| 628 |
+
}`}
|
| 629 |
+
</pre>
|
| 630 |
+
</div>
|
| 631 |
+
</div>
|
| 632 |
+
</div>
|
| 633 |
+
) : (
|
| 634 |
+
<div className="h-full flex flex-col items-center justify-center text-center">
|
| 635 |
+
<div className="w-16 h-16 bg-gray-800/50 rounded-full flex items-center justify-center mb-4">
|
| 636 |
+
<Play className="w-8 h-8 text-gray-500" />
|
| 637 |
+
</div>
|
| 638 |
+
<h3 className="text-lg font-medium text-gray-300 mb-2">Ready to Start</h3>
|
| 639 |
+
<p className="text-sm text-gray-500 max-w-md">
|
| 640 |
+
Enter a URL and instruction above, configure your agents and plugins, then click Start to begin scraping.
|
| 641 |
+
</p>
|
| 642 |
+
</div>
|
| 643 |
+
)}
|
| 644 |
+
</div>
|
| 645 |
</div>
|
| 646 |
+
|
| 647 |
+
{/* Logs Terminal */}
|
| 648 |
+
<div className="flex-shrink-0 h-36 bg-gray-900 border-t border-gray-700/50">
|
| 649 |
+
<div className="flex items-center justify-between px-3 py-1.5 border-b border-gray-800">
|
| 650 |
+
<div className="flex items-center gap-2">
|
| 651 |
+
<Terminal className="w-4 h-4 text-gray-500" />
|
| 652 |
+
<span className="text-xs font-medium text-gray-400">Logs</span>
|
| 653 |
+
</div>
|
| 654 |
+
<button
|
| 655 |
+
onClick={() => setLogs([])}
|
| 656 |
+
className="text-xs text-gray-500 hover:text-gray-300"
|
| 657 |
+
>
|
| 658 |
+
Clear
|
| 659 |
+
</button>
|
| 660 |
+
</div>
|
| 661 |
+
<div className="h-[calc(100%-28px)] overflow-y-auto p-2 font-mono text-xs">
|
| 662 |
+
{logs.map((log) => (
|
| 663 |
+
<div key={log.id} className="flex items-start gap-2 py-0.5">
|
| 664 |
+
<span className="text-gray-600">[{formatTime(log.timestamp)}]</span>
|
| 665 |
+
<span className={getLogLevelColor(log.level)}>[{log.level.toUpperCase()}]</span>
|
| 666 |
+
{log.source && <span className="text-purple-400">[{log.source}]</span>}
|
| 667 |
+
<span className="text-gray-300">{log.message}</span>
|
| 668 |
+
</div>
|
| 669 |
+
))}
|
| 670 |
</div>
|
| 671 |
</div>
|
| 672 |
</div>
|
| 673 |
|
| 674 |
+
{/* Right Sidebar - Memory & Data */}
|
| 675 |
+
<div className="w-72 flex-shrink-0 bg-gray-800/30 border-l border-gray-700/50 overflow-y-auto p-3 space-y-3">
|
| 676 |
+
{/* Memory Stats */}
|
| 677 |
+
<div className="bg-gray-900/50 border border-gray-700/50 rounded-lg p-3">
|
| 678 |
+
<div className="flex items-center gap-2 mb-3">
|
| 679 |
<Database className="w-4 h-4 text-pink-400" />
|
| 680 |
+
<span className="text-sm font-medium text-white">Memory</span>
|
| 681 |
+
</div>
|
| 682 |
+
<div className="grid grid-cols-2 gap-2">
|
| 683 |
+
<div className="p-2 bg-gray-800/50 rounded text-center">
|
| 684 |
+
<p className="text-lg font-bold text-emerald-400">{memoryData?.working?.count || 0}</p>
|
| 685 |
+
<p className="text-[10px] text-gray-500">Working</p>
|
| 686 |
+
</div>
|
| 687 |
+
<div className="p-2 bg-gray-800/50 rounded text-center">
|
| 688 |
+
<p className="text-lg font-bold text-cyan-400">{memoryData?.episodic?.count || 0}</p>
|
| 689 |
+
<p className="text-[10px] text-gray-500">Episodic</p>
|
| 690 |
+
</div>
|
| 691 |
+
<div className="p-2 bg-gray-800/50 rounded text-center">
|
| 692 |
+
<p className="text-lg font-bold text-purple-400">{memoryData?.semantic?.count || 0}</p>
|
| 693 |
+
<p className="text-[10px] text-gray-500">Semantic</p>
|
| 694 |
+
</div>
|
| 695 |
+
<div className="p-2 bg-gray-800/50 rounded text-center">
|
| 696 |
+
<p className="text-lg font-bold text-amber-400">{memoryData?.procedural?.count || 0}</p>
|
| 697 |
+
<p className="text-[10px] text-gray-500">Procedural</p>
|
| 698 |
+
</div>
|
| 699 |
+
</div>
|
| 700 |
</div>
|
| 701 |
+
|
| 702 |
+
{/* Extracted Data */}
|
| 703 |
+
<div className="bg-gray-900/50 border border-gray-700/50 rounded-lg p-3">
|
| 704 |
+
<div className="flex items-center justify-between mb-3">
|
| 705 |
+
<div className="flex items-center gap-2">
|
| 706 |
+
<FileText className="w-4 h-4 text-cyan-400" />
|
| 707 |
+
<span className="text-sm font-medium text-white">Extracted Data</span>
|
| 708 |
+
</div>
|
| 709 |
+
<Badge variant="neutral" size="sm">0 items</Badge>
|
| 710 |
+
</div>
|
| 711 |
+
<div className="text-center py-6 text-gray-500 text-xs">
|
| 712 |
+
No data extracted yet.<br />Start an episode to begin.
|
| 713 |
+
</div>
|
| 714 |
+
</div>
|
| 715 |
+
|
| 716 |
+
{/* Recent Actions */}
|
| 717 |
+
<div className="bg-gray-900/50 border border-gray-700/50 rounded-lg p-3">
|
| 718 |
+
<div className="flex items-center gap-2 mb-3">
|
| 719 |
+
<List className="w-4 h-4 text-amber-400" />
|
| 720 |
+
<span className="text-sm font-medium text-white">Recent Actions</span>
|
| 721 |
+
</div>
|
| 722 |
+
<div className="space-y-2">
|
| 723 |
+
{isRunning ? (
|
| 724 |
+
<>
|
| 725 |
+
<div className="flex items-center gap-2 p-2 bg-emerald-500/10 rounded">
|
| 726 |
+
<Check className="w-3 h-3 text-emerald-400" />
|
| 727 |
+
<span className="text-xs text-gray-300">Navigate to URL</span>
|
| 728 |
+
</div>
|
| 729 |
+
<div className="flex items-center gap-2 p-2 bg-gray-800/50 rounded">
|
| 730 |
+
<Activity className="w-3 h-3 text-cyan-400 animate-pulse" />
|
| 731 |
+
<span className="text-xs text-gray-300">Loading page...</span>
|
| 732 |
+
</div>
|
| 733 |
+
</>
|
| 734 |
+
) : (
|
| 735 |
+
<div className="text-center py-4 text-gray-500 text-xs">
|
| 736 |
+
No recent actions
|
| 737 |
+
</div>
|
| 738 |
+
)}
|
| 739 |
+
</div>
|
| 740 |
+
</div>
|
| 741 |
+
|
| 742 |
+
{/* System Info */}
|
| 743 |
+
<div className="bg-gray-900/50 border border-gray-700/50 rounded-lg p-3">
|
| 744 |
+
<div className="flex items-center gap-2 mb-3">
|
| 745 |
+
<Settings className="w-4 h-4 text-gray-400" />
|
| 746 |
+
<span className="text-sm font-medium text-white">System</span>
|
| 747 |
+
</div>
|
| 748 |
+
<div className="space-y-2 text-xs">
|
| 749 |
+
<div className="flex items-center justify-between">
|
| 750 |
+
<span className="text-gray-500">Status</span>
|
| 751 |
+
<Badge variant={health?.status === 'ok' ? 'success' : 'error'} size="sm">
|
| 752 |
+
{health?.status === 'ok' ? 'Online' : 'Offline'}
|
| 753 |
+
</Badge>
|
| 754 |
+
</div>
|
| 755 |
+
<div className="flex items-center justify-between">
|
| 756 |
+
<span className="text-gray-500">Model</span>
|
| 757 |
+
<span className="text-gray-300">{taskInput.selectedModel.split('/')[1]}</span>
|
| 758 |
+
</div>
|
| 759 |
+
<div className="flex items-center justify-between">
|
| 760 |
+
<span className="text-gray-500">Version</span>
|
| 761 |
+
<span className="text-gray-300">{health?.version || 'v0.1.0'}</span>
|
| 762 |
+
</div>
|
| 763 |
+
</div>
|
| 764 |
</div>
|
| 765 |
</div>
|
| 766 |
</div>
|
| 767 |
+
|
| 768 |
+
{/* Popups */}
|
| 769 |
+
{/* Model Selection Popup */}
|
| 770 |
+
<Popup title="Select Model" isOpen={showModelPopup} onClose={() => setShowModelPopup(false)}>
|
| 771 |
+
<div className="space-y-2">
|
| 772 |
+
{availableModels.map((model: { provider: string; model: string; name: string }) => (
|
| 773 |
+
<button
|
| 774 |
+
key={`${model.provider}/${model.model}`}
|
| 775 |
+
onClick={() => {
|
| 776 |
+
setTaskInput((p) => ({ ...p, selectedModel: `${model.provider}/${model.model}` }));
|
| 777 |
+
setShowModelPopup(false);
|
| 778 |
+
}}
|
| 779 |
+
className={classNames(
|
| 780 |
+
'w-full flex items-center justify-between p-3 rounded-lg transition-colors text-left',
|
| 781 |
+
taskInput.selectedModel === `${model.provider}/${model.model}`
|
| 782 |
+
? 'bg-emerald-500/20 border border-emerald-500/30'
|
| 783 |
+
: 'bg-gray-900/50 hover:bg-gray-800'
|
| 784 |
+
)}
|
| 785 |
+
>
|
| 786 |
+
<div>
|
| 787 |
+
<p className="text-sm font-medium text-white">{model.name}</p>
|
| 788 |
+
<p className="text-xs text-gray-500">{model.provider}</p>
|
| 789 |
+
</div>
|
| 790 |
+
{taskInput.selectedModel === `${model.provider}/${model.model}` && (
|
| 791 |
+
<Check className="w-5 h-5 text-emerald-400" />
|
| 792 |
+
)}
|
| 793 |
+
</button>
|
| 794 |
+
))}
|
| 795 |
+
</div>
|
| 796 |
+
</Popup>
|
| 797 |
+
|
| 798 |
+
{/* Agent Selection Popup */}
|
| 799 |
+
<Popup title="Select Agents" isOpen={showAgentPopup} onClose={() => setShowAgentPopup(false)}>
|
| 800 |
+
<div className="space-y-2">
|
| 801 |
+
{availableAgents.map((agent: { id: string; name: string; description: string }) => {
|
| 802 |
+
const isSelected = taskInput.selectedAgents.includes(agent.id);
|
| 803 |
+
return (
|
| 804 |
+
<button
|
| 805 |
+
key={agent.id}
|
| 806 |
+
onClick={() => {
|
| 807 |
+
setTaskInput((p) => ({
|
| 808 |
+
...p,
|
| 809 |
+
selectedAgents: isSelected
|
| 810 |
+
? p.selectedAgents.filter((a) => a !== agent.id)
|
| 811 |
+
: [...p.selectedAgents, agent.id],
|
| 812 |
+
}));
|
| 813 |
+
}}
|
| 814 |
+
className={classNames(
|
| 815 |
+
'w-full flex items-center justify-between p-3 rounded-lg transition-colors text-left',
|
| 816 |
+
isSelected ? 'bg-purple-500/20 border border-purple-500/30' : 'bg-gray-900/50 hover:bg-gray-800'
|
| 817 |
+
)}
|
| 818 |
+
>
|
| 819 |
+
<div>
|
| 820 |
+
<p className="text-sm font-medium text-white">{agent.name}</p>
|
| 821 |
+
<p className="text-xs text-gray-500">{agent.description}</p>
|
| 822 |
+
</div>
|
| 823 |
+
{isSelected && <Check className="w-5 h-5 text-purple-400" />}
|
| 824 |
+
</button>
|
| 825 |
+
);
|
| 826 |
+
})}
|
| 827 |
+
</div>
|
| 828 |
+
</Popup>
|
| 829 |
+
|
| 830 |
+
{/* Plugin Selection Popup */}
|
| 831 |
+
<Popup title="Enable Plugins" isOpen={showPluginPopup} onClose={() => setShowPluginPopup(false)}>
|
| 832 |
+
<div className="space-y-4">
|
| 833 |
+
{Object.entries(pluginCategories).map(([category, plugins]) => (
|
| 834 |
+
<div key={category}>
|
| 835 |
+
<h4 className="text-xs font-medium text-gray-400 uppercase mb-2">{category}</h4>
|
| 836 |
+
<div className="space-y-1">
|
| 837 |
+
{plugins.map((plugin) => {
|
| 838 |
+
const isEnabled = taskInput.enabledPlugins.includes(plugin.id);
|
| 839 |
+
return (
|
| 840 |
+
<button
|
| 841 |
+
key={plugin.id}
|
| 842 |
+
onClick={() => {
|
| 843 |
+
setTaskInput((p) => ({
|
| 844 |
+
...p,
|
| 845 |
+
enabledPlugins: isEnabled
|
| 846 |
+
? p.enabledPlugins.filter((a) => a !== plugin.id)
|
| 847 |
+
: [...p.enabledPlugins, plugin.id],
|
| 848 |
+
}));
|
| 849 |
+
}}
|
| 850 |
+
className={classNames(
|
| 851 |
+
'w-full flex items-center justify-between p-2 rounded-lg transition-colors text-left',
|
| 852 |
+
isEnabled ? 'bg-amber-500/20 border border-amber-500/30' : 'bg-gray-900/50 hover:bg-gray-800'
|
| 853 |
+
)}
|
| 854 |
+
>
|
| 855 |
+
<span className="text-sm text-white">{plugin.name}</span>
|
| 856 |
+
{isEnabled && <Check className="w-4 h-4 text-amber-400" />}
|
| 857 |
+
</button>
|
| 858 |
+
);
|
| 859 |
+
})}
|
| 860 |
+
</div>
|
| 861 |
+
</div>
|
| 862 |
+
))}
|
| 863 |
+
</div>
|
| 864 |
+
</Popup>
|
| 865 |
+
|
| 866 |
+
{/* Task Type Popup */}
|
| 867 |
+
<Popup title="Select Task Complexity" isOpen={showTaskTypePopup} onClose={() => setShowTaskTypePopup(false)}>
|
| 868 |
+
<div className="space-y-2">
|
| 869 |
+
{taskTypes.map((type) => (
|
| 870 |
+
<button
|
| 871 |
+
key={type.id}
|
| 872 |
+
onClick={() => {
|
| 873 |
+
setTaskInput((p) => ({ ...p, taskType: type.id as 'low' | 'medium' | 'high' }));
|
| 874 |
+
setShowTaskTypePopup(false);
|
| 875 |
+
}}
|
| 876 |
+
className={classNames(
|
| 877 |
+
'w-full flex items-center justify-between p-3 rounded-lg transition-colors text-left',
|
| 878 |
+
taskInput.taskType === type.id
|
| 879 |
+
? `bg-${type.color}-500/20 border border-${type.color}-500/30`
|
| 880 |
+
: 'bg-gray-900/50 hover:bg-gray-800'
|
| 881 |
+
)}
|
| 882 |
+
>
|
| 883 |
+
<div>
|
| 884 |
+
<p className="text-sm font-medium text-white">{type.name}</p>
|
| 885 |
+
<p className="text-xs text-gray-500">{type.description}</p>
|
| 886 |
+
</div>
|
| 887 |
+
{taskInput.taskType === type.id && (
|
| 888 |
+
<Check className={`w-5 h-5 text-${type.color}-400`} />
|
| 889 |
+
)}
|
| 890 |
+
</button>
|
| 891 |
+
))}
|
| 892 |
+
</div>
|
| 893 |
+
</Popup>
|
| 894 |
+
|
| 895 |
+
{/* Stats Popups */}
|
| 896 |
+
<StatsPopup
|
| 897 |
+
isOpen={showStatsPopup === 'episodes'}
|
| 898 |
+
onClose={() => setShowStatsPopup(null)}
|
| 899 |
+
stats={episodeStats}
|
| 900 |
+
title="Episode Statistics"
|
| 901 |
+
/>
|
| 902 |
+
<StatsPopup
|
| 903 |
+
isOpen={showStatsPopup === 'steps'}
|
| 904 |
+
onClose={() => setShowStatsPopup(null)}
|
| 905 |
+
stats={stepStats}
|
| 906 |
+
title="Step Statistics"
|
| 907 |
+
/>
|
| 908 |
+
<StatsPopup
|
| 909 |
+
isOpen={showStatsPopup === 'reward'}
|
| 910 |
+
onClose={() => setShowStatsPopup(null)}
|
| 911 |
+
stats={rewardStats}
|
| 912 |
+
title="Reward Statistics"
|
| 913 |
+
/>
|
| 914 |
</div>
|
| 915 |
);
|
| 916 |
};
|
|
@@ -0,0 +1,625 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React, { useState } from 'react';
|
| 2 |
+
import ReactMarkdown from 'react-markdown';
|
| 3 |
+
import remarkGfm from 'remark-gfm';
|
| 4 |
+
import {
|
| 5 |
+
Book,
|
| 6 |
+
Search,
|
| 7 |
+
ExternalLink,
|
| 8 |
+
Home,
|
| 9 |
+
Cpu,
|
| 10 |
+
Plug,
|
| 11 |
+
Database,
|
| 12 |
+
Terminal,
|
| 13 |
+
} from 'lucide-react';
|
| 14 |
+
import { classNames } from '@/utils/helpers';
|
| 15 |
+
|
| 16 |
+
interface DocsPageProps {
|
| 17 |
+
className?: string;
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
interface DocSection {
|
| 21 |
+
id: string;
|
| 22 |
+
title: string;
|
| 23 |
+
icon: React.ElementType;
|
| 24 |
+
content: string;
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
// Documentation content
|
| 28 |
+
const userGuideContent = `
|
| 29 |
+
# ScrapeRL Documentation
|
| 30 |
+
|
| 31 |
+
Welcome to ScrapeRL - an advanced Reinforcement Learning-powered web scraping environment.
|
| 32 |
+
|
| 33 |
+
---
|
| 34 |
+
|
| 35 |
+
## Getting Started
|
| 36 |
+
|
| 37 |
+
### What is ScrapeRL?
|
| 38 |
+
|
| 39 |
+
ScrapeRL is an intelligent web scraping system that uses Reinforcement Learning (RL) to learn and adapt scraping strategies. Unlike traditional scrapers, ScrapeRL can:
|
| 40 |
+
|
| 41 |
+
- **Learn from experience** - Improve scraping strategies over time
|
| 42 |
+
- **Adapt to changes** - Handle website structure changes automatically
|
| 43 |
+
- **Multi-agent coordination** - Use specialized agents for different tasks
|
| 44 |
+
- **Memory-enhanced** - Remember patterns and optimize future runs
|
| 45 |
+
|
| 46 |
+
### Quick Start
|
| 47 |
+
|
| 48 |
+
1. **Enter a Target URL** - Provide the webpage you want to scrape
|
| 49 |
+
2. **Write an Instruction** - Describe what data you want to extract
|
| 50 |
+
3. **Configure Options** - Select model, agents, and plugins
|
| 51 |
+
4. **Start Episode** - Click Start and watch the magic happen!
|
| 52 |
+
|
| 53 |
+
### Example Task
|
| 54 |
+
|
| 55 |
+
\`\`\`
|
| 56 |
+
URL: https://example.com/products
|
| 57 |
+
Instruction: Extract all product names, prices, and descriptions
|
| 58 |
+
Task Type: Medium
|
| 59 |
+
\`\`\`
|
| 60 |
+
|
| 61 |
+
---
|
| 62 |
+
|
| 63 |
+
## Dashboard Overview
|
| 64 |
+
|
| 65 |
+
The dashboard is your command center for monitoring and controlling scraping operations.
|
| 66 |
+
|
| 67 |
+
### Layout Structure
|
| 68 |
+
|
| 69 |
+
| Section | Description |
|
| 70 |
+
|---------|-------------|
|
| 71 |
+
| **Input Bar** | Enter URL, instruction, and configure task |
|
| 72 |
+
| **Left Sidebar** | View active agents, MCPs, skills, and tools |
|
| 73 |
+
| **Center Area** | Main visualization and current observation |
|
| 74 |
+
| **Right Sidebar** | Memory stats, extracted data, recent actions |
|
| 75 |
+
| **Bottom Logs** | Real-time terminal-style log output |
|
| 76 |
+
|
| 77 |
+
### Task Types
|
| 78 |
+
|
| 79 |
+
| Type | Description | Use Case |
|
| 80 |
+
|------|-------------|----------|
|
| 81 |
+
| 🟢 **Low** | Simple single-page scraping | Product page, article text |
|
| 82 |
+
| 🟡 **Medium** | Multi-page with navigation | Search results, listings |
|
| 83 |
+
| 🔴 **High** | Complex interactive tasks | Login-required, forms |
|
| 84 |
+
|
| 85 |
+
---
|
| 86 |
+
|
| 87 |
+
## Agents
|
| 88 |
+
|
| 89 |
+
ScrapeRL uses a multi-agent architecture where specialized agents handle different aspects of scraping.
|
| 90 |
+
|
| 91 |
+
### Available Agents
|
| 92 |
+
|
| 93 |
+
| Agent | Role | Description |
|
| 94 |
+
|-------|------|-------------|
|
| 95 |
+
| **Coordinator** | 🎯 Orchestrator | Manages all other agents |
|
| 96 |
+
| **Scraper** | 📄 Extractor | Extracts data from content |
|
| 97 |
+
| **Navigator** | 🧭 Navigation | Handles page navigation |
|
| 98 |
+
| **Analyzer** | 🔍 Analysis | Analyzes data patterns |
|
| 99 |
+
| **Validator** | ✅ Validation | Validates data quality |
|
| 100 |
+
|
| 101 |
+
---
|
| 102 |
+
|
| 103 |
+
## Plugins
|
| 104 |
+
|
| 105 |
+
Extend ScrapeRL's capabilities with plugins.
|
| 106 |
+
|
| 107 |
+
### Categories
|
| 108 |
+
|
| 109 |
+
- **MCPs** - Browser automation (Browser Use, Puppeteer, Playwright)
|
| 110 |
+
- **Skills** - Task capabilities (Web Scraping, Data Extraction)
|
| 111 |
+
- **APIs** - External services (Firecrawl, Jina Reader, Serper)
|
| 112 |
+
- **Vision** - Visual AI (GPT-4V, Gemini Vision, Claude Vision)
|
| 113 |
+
|
| 114 |
+
---
|
| 115 |
+
|
| 116 |
+
## Memory System
|
| 117 |
+
|
| 118 |
+
| Layer | Purpose | Retention |
|
| 119 |
+
|-------|---------|-----------|
|
| 120 |
+
| **Working** | Current task | Session |
|
| 121 |
+
| **Episodic** | Experiences | Persistent |
|
| 122 |
+
| **Semantic** | Patterns | Persistent |
|
| 123 |
+
| **Procedural** | Actions | Persistent |
|
| 124 |
+
|
| 125 |
+
---
|
| 126 |
+
|
| 127 |
+
## API Keys
|
| 128 |
+
|
| 129 |
+
Configure in **Settings > API Keys**:
|
| 130 |
+
|
| 131 |
+
| Provider | Models |
|
| 132 |
+
|----------|--------|
|
| 133 |
+
| Groq | GPT-OSS 120B (Default) |
|
| 134 |
+
| Google | Gemini 2.5 Flash |
|
| 135 |
+
| OpenAI | GPT-4 Turbo |
|
| 136 |
+
| Anthropic | Claude 3 Opus |
|
| 137 |
+
|
| 138 |
+
---
|
| 139 |
+
|
| 140 |
+
## Keyboard Shortcuts
|
| 141 |
+
|
| 142 |
+
| Shortcut | Action |
|
| 143 |
+
|----------|--------|
|
| 144 |
+
| \`Ctrl + Enter\` | Start/Stop episode |
|
| 145 |
+
| \`Ctrl + L\` | Clear logs |
|
| 146 |
+
| \`Escape\` | Close popups |
|
| 147 |
+
`;
|
| 148 |
+
|
| 149 |
+
const agentsContent = `
|
| 150 |
+
# Agents Documentation
|
| 151 |
+
|
| 152 |
+
## Multi-Agent Architecture
|
| 153 |
+
|
| 154 |
+
ScrapeRL employs a sophisticated multi-agent system where each agent specializes in specific tasks.
|
| 155 |
+
|
| 156 |
+
### Coordinator Agent
|
| 157 |
+
|
| 158 |
+
The brain of the operation. It:
|
| 159 |
+
- Decides which agents to activate
|
| 160 |
+
- Plans the scraping strategy
|
| 161 |
+
- Handles error recovery
|
| 162 |
+
- Optimizes resource usage
|
| 163 |
+
|
| 164 |
+
### Scraper Agent
|
| 165 |
+
|
| 166 |
+
Responsible for data extraction:
|
| 167 |
+
- HTML parsing and element selection
|
| 168 |
+
- Text content extraction
|
| 169 |
+
- Structured data identification
|
| 170 |
+
- Pattern recognition
|
| 171 |
+
|
| 172 |
+
### Navigator Agent
|
| 173 |
+
|
| 174 |
+
Handles all page interactions:
|
| 175 |
+
- URL navigation
|
| 176 |
+
- Link clicking
|
| 177 |
+
- Form submissions
|
| 178 |
+
- Pagination handling
|
| 179 |
+
|
| 180 |
+
### Analyzer Agent
|
| 181 |
+
|
| 182 |
+
Processes and analyzes data:
|
| 183 |
+
- Data validation
|
| 184 |
+
- Pattern detection
|
| 185 |
+
- Quality assessment
|
| 186 |
+
- Anomaly detection
|
| 187 |
+
|
| 188 |
+
### Validator Agent
|
| 189 |
+
|
| 190 |
+
Ensures data quality:
|
| 191 |
+
- Schema validation
|
| 192 |
+
- Completeness checks
|
| 193 |
+
- Duplicate detection
|
| 194 |
+
- Format verification
|
| 195 |
+
|
| 196 |
+
## Agent Communication
|
| 197 |
+
|
| 198 |
+
Agents communicate through a shared memory system:
|
| 199 |
+
|
| 200 |
+
\`\`\`
|
| 201 |
+
Coordinator -> Scraper: "Extract product data"
|
| 202 |
+
Scraper -> Memory: "Store extracted items"
|
| 203 |
+
Memory -> Analyzer: "New data available"
|
| 204 |
+
Analyzer -> Validator: "Validate these records"
|
| 205 |
+
Validator -> Coordinator: "Validation complete"
|
| 206 |
+
\`\`\`
|
| 207 |
+
`;
|
| 208 |
+
|
| 209 |
+
const pluginsContent = `
|
| 210 |
+
# Plugins Documentation
|
| 211 |
+
|
| 212 |
+
## Plugin Categories
|
| 213 |
+
|
| 214 |
+
### MCPs (Model Context Protocols)
|
| 215 |
+
|
| 216 |
+
Browser automation tools that integrate with AI models.
|
| 217 |
+
|
| 218 |
+
#### Browser Use
|
| 219 |
+
- AI-powered browser control
|
| 220 |
+
- Natural language commands
|
| 221 |
+
- Visual understanding
|
| 222 |
+
- Automatic element detection
|
| 223 |
+
|
| 224 |
+
#### Puppeteer MCP
|
| 225 |
+
- Headless Chrome automation
|
| 226 |
+
- Screenshot capture
|
| 227 |
+
- PDF generation
|
| 228 |
+
- Network interception
|
| 229 |
+
|
| 230 |
+
#### Playwright MCP
|
| 231 |
+
- Cross-browser support
|
| 232 |
+
- Mobile emulation
|
| 233 |
+
- Video recording
|
| 234 |
+
- Trace viewer
|
| 235 |
+
|
| 236 |
+
### Skills
|
| 237 |
+
|
| 238 |
+
Specialized capabilities for specific tasks.
|
| 239 |
+
|
| 240 |
+
#### Web Scraping
|
| 241 |
+
- CSS/XPath selectors
|
| 242 |
+
- Data extraction patterns
|
| 243 |
+
- Pagination handling
|
| 244 |
+
- Rate limiting
|
| 245 |
+
|
| 246 |
+
#### Data Extraction
|
| 247 |
+
- JSON/XML parsing
|
| 248 |
+
- Table extraction
|
| 249 |
+
- List processing
|
| 250 |
+
- Content classification
|
| 251 |
+
|
| 252 |
+
### APIs
|
| 253 |
+
|
| 254 |
+
External service integrations.
|
| 255 |
+
|
| 256 |
+
#### Firecrawl
|
| 257 |
+
- High-performance crawling
|
| 258 |
+
- JavaScript rendering
|
| 259 |
+
- Proxy rotation
|
| 260 |
+
- Rate limiting
|
| 261 |
+
|
| 262 |
+
#### Jina Reader
|
| 263 |
+
- Content extraction API
|
| 264 |
+
- Clean text output
|
| 265 |
+
- Structured data
|
| 266 |
+
- Multi-format support
|
| 267 |
+
|
| 268 |
+
### Vision Models
|
| 269 |
+
|
| 270 |
+
Visual understanding capabilities.
|
| 271 |
+
|
| 272 |
+
#### GPT-4 Vision
|
| 273 |
+
- Image analysis
|
| 274 |
+
- Screenshot understanding
|
| 275 |
+
- UI element detection
|
| 276 |
+
- Text extraction from images
|
| 277 |
+
|
| 278 |
+
## Installing Plugins
|
| 279 |
+
|
| 280 |
+
1. Navigate to Plugins page
|
| 281 |
+
2. Browse categories
|
| 282 |
+
3. Click Install on desired plugin
|
| 283 |
+
4. Configure API keys if required
|
| 284 |
+
`;
|
| 285 |
+
|
| 286 |
+
const memoryContent = `
|
| 287 |
+
# Memory System Documentation
|
| 288 |
+
|
| 289 |
+
## Hierarchical Memory Architecture
|
| 290 |
+
|
| 291 |
+
ScrapeRL uses a four-layer memory system inspired by human cognitive architecture.
|
| 292 |
+
|
| 293 |
+
### Working Memory
|
| 294 |
+
|
| 295 |
+
**Purpose:** Active task context
|
| 296 |
+
|
| 297 |
+
- Current URL and page state
|
| 298 |
+
- Active extraction targets
|
| 299 |
+
- Temporary calculations
|
| 300 |
+
- Session-specific data
|
| 301 |
+
|
| 302 |
+
**Retention:** Cleared after each episode
|
| 303 |
+
|
| 304 |
+
### Episodic Memory
|
| 305 |
+
|
| 306 |
+
**Purpose:** Experience records
|
| 307 |
+
|
| 308 |
+
- Past scraping sessions
|
| 309 |
+
- Success/failure patterns
|
| 310 |
+
- Timing data
|
| 311 |
+
- Action sequences
|
| 312 |
+
|
| 313 |
+
**Retention:** Persistent across sessions
|
| 314 |
+
|
| 315 |
+
### Semantic Memory
|
| 316 |
+
|
| 317 |
+
**Purpose:** Learned knowledge
|
| 318 |
+
|
| 319 |
+
- Website patterns
|
| 320 |
+
- Extraction rules
|
| 321 |
+
- Domain knowledge
|
| 322 |
+
- Best practices
|
| 323 |
+
|
| 324 |
+
**Retention:** Long-term persistent
|
| 325 |
+
|
| 326 |
+
### Procedural Memory
|
| 327 |
+
|
| 328 |
+
**Purpose:** Action sequences
|
| 329 |
+
|
| 330 |
+
- Navigation patterns
|
| 331 |
+
- Interaction sequences
|
| 332 |
+
- Recovery procedures
|
| 333 |
+
- Optimization strategies
|
| 334 |
+
|
| 335 |
+
**Retention:** Long-term persistent
|
| 336 |
+
|
| 337 |
+
## Memory Operations
|
| 338 |
+
|
| 339 |
+
### Store
|
| 340 |
+
\`\`\`json
|
| 341 |
+
{
|
| 342 |
+
"content": "Product prices on example.com follow pattern...",
|
| 343 |
+
"memory_type": "semantic",
|
| 344 |
+
"metadata": {
|
| 345 |
+
"domain": "example.com",
|
| 346 |
+
"confidence": 0.95
|
| 347 |
+
}
|
| 348 |
+
}
|
| 349 |
+
\`\`\`
|
| 350 |
+
|
| 351 |
+
### Query
|
| 352 |
+
\`\`\`json
|
| 353 |
+
{
|
| 354 |
+
"query": "price extraction patterns",
|
| 355 |
+
"memory_type": "semantic",
|
| 356 |
+
"limit": 10
|
| 357 |
+
}
|
| 358 |
+
\`\`\`
|
| 359 |
+
|
| 360 |
+
### Consolidation
|
| 361 |
+
|
| 362 |
+
Automatic promotion of important memories:
|
| 363 |
+
- Working → Episodic: At episode end
|
| 364 |
+
- Episodic → Semantic: Pattern detection
|
| 365 |
+
- Episodic → Procedural: Action sequences
|
| 366 |
+
`;
|
| 367 |
+
|
| 368 |
+
const apiContent = `
|
| 369 |
+
# API Reference
|
| 370 |
+
|
| 371 |
+
## Base URL
|
| 372 |
+
|
| 373 |
+
\`\`\`
|
| 374 |
+
http://localhost:7860/api
|
| 375 |
+
\`\`\`
|
| 376 |
+
|
| 377 |
+
## Health Check
|
| 378 |
+
|
| 379 |
+
### GET /health
|
| 380 |
+
|
| 381 |
+
Check system status.
|
| 382 |
+
|
| 383 |
+
**Response:**
|
| 384 |
+
\`\`\`json
|
| 385 |
+
{
|
| 386 |
+
"status": "healthy",
|
| 387 |
+
"version": "0.1.0",
|
| 388 |
+
"timestamp": "2026-03-28T00:00:00Z"
|
| 389 |
+
}
|
| 390 |
+
\`\`\`
|
| 391 |
+
|
| 392 |
+
## Episode Endpoints
|
| 393 |
+
|
| 394 |
+
### POST /episode/reset
|
| 395 |
+
|
| 396 |
+
Start a new episode.
|
| 397 |
+
|
| 398 |
+
**Request:**
|
| 399 |
+
\`\`\`json
|
| 400 |
+
{
|
| 401 |
+
"task_id": "scrape-products"
|
| 402 |
+
}
|
| 403 |
+
\`\`\`
|
| 404 |
+
|
| 405 |
+
### POST /episode/step
|
| 406 |
+
|
| 407 |
+
Execute an action.
|
| 408 |
+
|
| 409 |
+
**Request:**
|
| 410 |
+
\`\`\`json
|
| 411 |
+
{
|
| 412 |
+
"action": "navigate",
|
| 413 |
+
"params": { "url": "https://example.com" }
|
| 414 |
+
}
|
| 415 |
+
\`\`\`
|
| 416 |
+
|
| 417 |
+
### GET /episode/state
|
| 418 |
+
|
| 419 |
+
Get current state.
|
| 420 |
+
|
| 421 |
+
## Memory Endpoints
|
| 422 |
+
|
| 423 |
+
### POST /memory/store
|
| 424 |
+
|
| 425 |
+
Store a memory entry.
|
| 426 |
+
|
| 427 |
+
### POST /memory/query
|
| 428 |
+
|
| 429 |
+
Query memories.
|
| 430 |
+
|
| 431 |
+
### GET /memory/stats/overview
|
| 432 |
+
|
| 433 |
+
Get memory statistics.
|
| 434 |
+
|
| 435 |
+
## Plugin Endpoints
|
| 436 |
+
|
| 437 |
+
### GET /plugins/
|
| 438 |
+
|
| 439 |
+
List all plugins.
|
| 440 |
+
|
| 441 |
+
### POST /plugins/install
|
| 442 |
+
|
| 443 |
+
Install a plugin.
|
| 444 |
+
|
| 445 |
+
### POST /plugins/uninstall
|
| 446 |
+
|
| 447 |
+
Uninstall a plugin.
|
| 448 |
+
|
| 449 |
+
## Settings Endpoints
|
| 450 |
+
|
| 451 |
+
### GET /settings/
|
| 452 |
+
|
| 453 |
+
Get current settings.
|
| 454 |
+
|
| 455 |
+
### POST /settings/api-key
|
| 456 |
+
|
| 457 |
+
Update API key.
|
| 458 |
+
|
| 459 |
+
### POST /settings/model
|
| 460 |
+
|
| 461 |
+
Select active model.
|
| 462 |
+
`;
|
| 463 |
+
|
| 464 |
+
const docs: DocSection[] = [
|
| 465 |
+
{ id: 'guide', title: 'User Guide', icon: Home, content: userGuideContent },
|
| 466 |
+
{ id: 'agents', title: 'Agents', icon: Cpu, content: agentsContent },
|
| 467 |
+
{ id: 'plugins', title: 'Plugins', icon: Plug, content: pluginsContent },
|
| 468 |
+
{ id: 'memory', title: 'Memory System', icon: Database, content: memoryContent },
|
| 469 |
+
{ id: 'api', title: 'API Reference', icon: Terminal, content: apiContent },
|
| 470 |
+
];
|
| 471 |
+
|
| 472 |
+
export const DocsPage: React.FC<DocsPageProps> = ({ className }) => {
|
| 473 |
+
const [activeDoc, setActiveDoc] = useState<string>('guide');
|
| 474 |
+
const [searchQuery, setSearchQuery] = useState('');
|
| 475 |
+
|
| 476 |
+
const currentDoc = docs.find((d) => d.id === activeDoc) || docs[0];
|
| 477 |
+
|
| 478 |
+
return (
|
| 479 |
+
<div className={classNames('flex h-[calc(100vh-120px)]', className)}>
|
| 480 |
+
{/* Left Sidebar - Navigation */}
|
| 481 |
+
<div className="w-64 flex-shrink-0 bg-gray-800/30 border-r border-gray-700/50 flex flex-col">
|
| 482 |
+
<div className="p-4 border-b border-gray-700/50">
|
| 483 |
+
<h2 className="text-lg font-semibold text-white flex items-center gap-2">
|
| 484 |
+
<Book className="w-5 h-5 text-cyan-400" />
|
| 485 |
+
Documentation
|
| 486 |
+
</h2>
|
| 487 |
+
<p className="text-xs text-gray-500 mt-1">Learn how to use ScrapeRL</p>
|
| 488 |
+
</div>
|
| 489 |
+
|
| 490 |
+
{/* Search */}
|
| 491 |
+
<div className="p-3 border-b border-gray-700/50">
|
| 492 |
+
<div className="relative">
|
| 493 |
+
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-500" />
|
| 494 |
+
<input
|
| 495 |
+
type="text"
|
| 496 |
+
placeholder="Search docs..."
|
| 497 |
+
value={searchQuery}
|
| 498 |
+
onChange={(e) => setSearchQuery(e.target.value)}
|
| 499 |
+
className="w-full pl-9 pr-3 py-2 bg-gray-900/50 border border-gray-700/50 rounded-lg text-sm text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/50"
|
| 500 |
+
/>
|
| 501 |
+
</div>
|
| 502 |
+
</div>
|
| 503 |
+
|
| 504 |
+
{/* Navigation */}
|
| 505 |
+
<nav className="flex-1 p-3 space-y-1 overflow-y-auto">
|
| 506 |
+
{docs.map((doc) => {
|
| 507 |
+
const Icon = doc.icon;
|
| 508 |
+
const isActive = activeDoc === doc.id;
|
| 509 |
+
return (
|
| 510 |
+
<button
|
| 511 |
+
key={doc.id}
|
| 512 |
+
onClick={() => setActiveDoc(doc.id)}
|
| 513 |
+
className={classNames(
|
| 514 |
+
'w-full flex items-center gap-3 px-3 py-2.5 rounded-lg text-left transition-all',
|
| 515 |
+
isActive
|
| 516 |
+
? 'bg-cyan-500/20 border border-cyan-500/30 text-cyan-400'
|
| 517 |
+
: 'hover:bg-gray-700/50 text-gray-400 hover:text-gray-200'
|
| 518 |
+
)}
|
| 519 |
+
>
|
| 520 |
+
<Icon className={classNames('w-4 h-4', isActive ? 'text-cyan-400' : 'text-gray-500')} />
|
| 521 |
+
<span className="text-sm font-medium">{doc.title}</span>
|
| 522 |
+
</button>
|
| 523 |
+
);
|
| 524 |
+
})}
|
| 525 |
+
</nav>
|
| 526 |
+
|
| 527 |
+
{/* Footer */}
|
| 528 |
+
<div className="p-4 border-t border-gray-700/50">
|
| 529 |
+
<a
|
| 530 |
+
href="https://github.com/NeerajCodz/scrapeRL"
|
| 531 |
+
target="_blank"
|
| 532 |
+
rel="noopener noreferrer"
|
| 533 |
+
className="flex items-center gap-2 text-xs text-gray-500 hover:text-gray-300 transition-colors"
|
| 534 |
+
>
|
| 535 |
+
<ExternalLink className="w-3 h-3" />
|
| 536 |
+
View on GitHub
|
| 537 |
+
</a>
|
| 538 |
+
</div>
|
| 539 |
+
</div>
|
| 540 |
+
|
| 541 |
+
{/* Main Content - Markdown Viewer */}
|
| 542 |
+
<div className="flex-1 overflow-y-auto">
|
| 543 |
+
<div className="max-w-4xl mx-auto p-8">
|
| 544 |
+
<article className="prose prose-invert prose-sm max-w-none">
|
| 545 |
+
<ReactMarkdown
|
| 546 |
+
remarkPlugins={[remarkGfm]}
|
| 547 |
+
components={{
|
| 548 |
+
h1: ({ children }) => (
|
| 549 |
+
<h1 className="text-3xl font-bold text-white mb-6 pb-4 border-b border-gray-700/50">
|
| 550 |
+
{children}
|
| 551 |
+
</h1>
|
| 552 |
+
),
|
| 553 |
+
h2: ({ children }) => (
|
| 554 |
+
<h2 className="text-2xl font-semibold text-white mt-8 mb-4">{children}</h2>
|
| 555 |
+
),
|
| 556 |
+
h3: ({ children }) => (
|
| 557 |
+
<h3 className="text-xl font-semibold text-gray-200 mt-6 mb-3">{children}</h3>
|
| 558 |
+
),
|
| 559 |
+
h4: ({ children }) => (
|
| 560 |
+
<h4 className="text-lg font-medium text-gray-300 mt-4 mb-2">{children}</h4>
|
| 561 |
+
),
|
| 562 |
+
p: ({ children }) => <p className="text-gray-400 mb-4 leading-relaxed">{children}</p>,
|
| 563 |
+
ul: ({ children }) => <ul className="list-disc list-inside text-gray-400 mb-4 space-y-1">{children}</ul>,
|
| 564 |
+
ol: ({ children }) => <ol className="list-decimal list-inside text-gray-400 mb-4 space-y-1">{children}</ol>,
|
| 565 |
+
li: ({ children }) => <li className="text-gray-400">{children}</li>,
|
| 566 |
+
strong: ({ children }) => <strong className="text-white font-semibold">{children}</strong>,
|
| 567 |
+
em: ({ children }) => <em className="text-gray-300">{children}</em>,
|
| 568 |
+
code: ({ children, className }) => {
|
| 569 |
+
const isBlock = className?.includes('language-');
|
| 570 |
+
if (isBlock) {
|
| 571 |
+
return (
|
| 572 |
+
<code className="block bg-gray-900 rounded-lg p-4 text-sm font-mono text-gray-300 overflow-x-auto">
|
| 573 |
+
{children}
|
| 574 |
+
</code>
|
| 575 |
+
);
|
| 576 |
+
}
|
| 577 |
+
return (
|
| 578 |
+
<code className="bg-gray-800 text-cyan-400 px-1.5 py-0.5 rounded text-sm font-mono">
|
| 579 |
+
{children}
|
| 580 |
+
</code>
|
| 581 |
+
);
|
| 582 |
+
},
|
| 583 |
+
pre: ({ children }) => <pre className="mb-4">{children}</pre>,
|
| 584 |
+
blockquote: ({ children }) => (
|
| 585 |
+
<blockquote className="border-l-4 border-cyan-500/50 pl-4 italic text-gray-400 my-4">
|
| 586 |
+
{children}
|
| 587 |
+
</blockquote>
|
| 588 |
+
),
|
| 589 |
+
table: ({ children }) => (
|
| 590 |
+
<div className="overflow-x-auto mb-4">
|
| 591 |
+
<table className="w-full border-collapse">{children}</table>
|
| 592 |
+
</div>
|
| 593 |
+
),
|
| 594 |
+
thead: ({ children }) => <thead className="bg-gray-800/50">{children}</thead>,
|
| 595 |
+
th: ({ children }) => (
|
| 596 |
+
<th className="px-4 py-2 text-left text-xs font-semibold text-gray-300 border-b border-gray-700">
|
| 597 |
+
{children}
|
| 598 |
+
</th>
|
| 599 |
+
),
|
| 600 |
+
td: ({ children }) => (
|
| 601 |
+
<td className="px-4 py-2 text-sm text-gray-400 border-b border-gray-800">{children}</td>
|
| 602 |
+
),
|
| 603 |
+
hr: () => <hr className="border-gray-700/50 my-8" />,
|
| 604 |
+
a: ({ href, children }) => (
|
| 605 |
+
<a
|
| 606 |
+
href={href}
|
| 607 |
+
className="text-cyan-400 hover:text-cyan-300 underline underline-offset-2"
|
| 608 |
+
target="_blank"
|
| 609 |
+
rel="noopener noreferrer"
|
| 610 |
+
>
|
| 611 |
+
{children}
|
| 612 |
+
</a>
|
| 613 |
+
),
|
| 614 |
+
}}
|
| 615 |
+
>
|
| 616 |
+
{currentDoc.content}
|
| 617 |
+
</ReactMarkdown>
|
| 618 |
+
</article>
|
| 619 |
+
</div>
|
| 620 |
+
</div>
|
| 621 |
+
</div>
|
| 622 |
+
);
|
| 623 |
+
};
|
| 624 |
+
|
| 625 |
+
export default DocsPage;
|
|
@@ -9,6 +9,13 @@ import {
|
|
| 9 |
EyeOff,
|
| 10 |
Zap,
|
| 11 |
Server,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
} from 'lucide-react';
|
| 13 |
import { Button } from '@/components/ui/Button';
|
| 14 |
import { Input } from '@/components/ui/Input';
|
|
@@ -16,6 +23,7 @@ import { Select, Toggle } from '@/components/ui/Select';
|
|
| 16 |
import { Badge } from '@/components/ui/Badge';
|
| 17 |
import { apiClient } from '@/api/client';
|
| 18 |
import type { SystemSettings } from '@/types';
|
|
|
|
| 19 |
|
| 20 |
interface SettingsProps {
|
| 21 |
className?: string;
|
|
@@ -43,10 +51,24 @@ interface SettingsData {
|
|
| 43 |
plugins_installed: string[];
|
| 44 |
}
|
| 45 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
export const Settings: React.FC<SettingsProps> = ({ className }) => {
|
| 47 |
const queryClient = useQueryClient();
|
|
|
|
| 48 |
const [localSettings, setLocalSettings] = useState<Partial<SystemSettings>>({});
|
| 49 |
const [showKeys, setShowKeys] = useState<Record<string, boolean>>({});
|
|
|
|
| 50 |
const [apiKeys, setApiKeys] = useState<ApiKeyState>({
|
| 51 |
openai: '',
|
| 52 |
anthropic: '',
|
|
@@ -143,37 +165,16 @@ export const Settings: React.FC<SettingsProps> = ({ className }) => {
|
|
| 143 |
? `${settingsData.selected_model.provider}/${settingsData.selected_model.model}`
|
| 144 |
: 'groq/gpt-oss-120b';
|
| 145 |
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
<
|
| 154 |
</div>
|
| 155 |
-
Settings
|
| 156 |
-
</h1>
|
| 157 |
-
<p className="text-gray-400 mt-1">Configure your ScrapeRL environment</p>
|
| 158 |
-
</div>
|
| 159 |
-
{health && (
|
| 160 |
-
<Badge variant={health.status === 'ok' ? 'success' : 'error'} dot>
|
| 161 |
-
{health.status === 'ok' ? 'Connected' : 'Disconnected'}
|
| 162 |
-
</Badge>
|
| 163 |
-
)}
|
| 164 |
-
</div>
|
| 165 |
|
| 166 |
-
{settingsLoading ? (
|
| 167 |
-
<div className="flex items-center justify-center py-16">
|
| 168 |
-
<div className="flex flex-col items-center gap-3">
|
| 169 |
-
<SettingsIcon className="w-8 h-8 text-gray-500 animate-spin" />
|
| 170 |
-
<p className="text-gray-400">Loading settings...</p>
|
| 171 |
-
</div>
|
| 172 |
-
</div>
|
| 173 |
-
) : (
|
| 174 |
-
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
| 175 |
-
{/* Left Column */}
|
| 176 |
-
<div className="space-y-6">
|
| 177 |
{/* API Key Required Warning */}
|
| 178 |
{keyRequired?.required && (
|
| 179 |
<div className="flex items-center gap-3 p-4 bg-amber-500/10 border border-amber-500/30 rounded-xl">
|
|
@@ -185,64 +186,68 @@ export const Settings: React.FC<SettingsProps> = ({ className }) => {
|
|
| 185 |
</div>
|
| 186 |
)}
|
| 187 |
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 200 |
/>
|
| 201 |
-
{selectModelMutation.isPending && (
|
| 202 |
-
<p className="text-xs text-gray-400 mt-2">Switching model...</p>
|
| 203 |
-
)}
|
| 204 |
-
<p className="text-xs text-gray-500 mt-3">
|
| 205 |
-
Select the AI model to use for scraping tasks. Different models have different capabilities and costs.
|
| 206 |
-
</p>
|
| 207 |
</div>
|
| 208 |
|
| 209 |
-
{/*
|
| 210 |
-
<div className="
|
| 211 |
-
<
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
|
| 228 |
-
|
| 229 |
-
setLocalSettings((prev) => ({ ...prev, memoryPersistence: checked }));
|
| 230 |
-
}}
|
| 231 |
-
/>
|
| 232 |
</div>
|
| 233 |
</div>
|
| 234 |
</div>
|
|
|
|
| 235 |
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
API Keys
|
|
|
|
|
|
|
|
|
|
| 241 |
</div>
|
| 242 |
-
|
| 243 |
-
Configure your API keys. Server keys are used by default, but you can override them here.
|
| 244 |
-
</p>
|
| 245 |
-
|
| 246 |
<div className="space-y-4">
|
| 247 |
{providers.map((provider) => {
|
| 248 |
const isConfigured = settingsData?.api_keys_configured?.[provider.id] ?? false;
|
|
@@ -252,9 +257,7 @@ export const Settings: React.FC<SettingsProps> = ({ className }) => {
|
|
| 252 |
<div className="flex items-center gap-3">
|
| 253 |
<span className="text-2xl">{provider.icon}</span>
|
| 254 |
<div>
|
| 255 |
-
<span className="text-sm font-medium text-white">
|
| 256 |
-
{provider.name}
|
| 257 |
-
</span>
|
| 258 |
<p className="text-xs text-gray-500">{provider.description}</p>
|
| 259 |
</div>
|
| 260 |
</div>
|
|
@@ -281,11 +284,7 @@ export const Settings: React.FC<SettingsProps> = ({ className }) => {
|
|
| 281 |
onClick={() => toggleShowKey(provider.id)}
|
| 282 |
className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-500 hover:text-gray-300 transition-colors"
|
| 283 |
>
|
| 284 |
-
{showKeys[provider.id] ?
|
| 285 |
-
<EyeOff className="w-4 h-4" />
|
| 286 |
-
) : (
|
| 287 |
-
<Eye className="w-4 h-4" />
|
| 288 |
-
)}
|
| 289 |
</button>
|
| 290 |
</div>
|
| 291 |
<Button
|
|
@@ -302,16 +301,314 @@ export const Settings: React.FC<SettingsProps> = ({ className }) => {
|
|
| 302 |
})}
|
| 303 |
</div>
|
| 304 |
|
| 305 |
-
{/* Status Messages */}
|
| 306 |
{updateApiKeyMutation.isSuccess && (
|
| 307 |
-
<div className="flex items-center gap-2
|
| 308 |
<CheckCircle className="w-4 h-4 text-emerald-400" />
|
| 309 |
<span className="text-sm text-emerald-400">API key saved successfully</span>
|
| 310 |
</div>
|
| 311 |
)}
|
| 312 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 313 |
</div>
|
| 314 |
-
|
| 315 |
</div>
|
| 316 |
);
|
| 317 |
};
|
|
|
|
| 9 |
EyeOff,
|
| 10 |
Zap,
|
| 11 |
Server,
|
| 12 |
+
Palette,
|
| 13 |
+
Bell,
|
| 14 |
+
Shield,
|
| 15 |
+
Cpu,
|
| 16 |
+
Globe,
|
| 17 |
+
Wallet,
|
| 18 |
+
ChevronRight,
|
| 19 |
} from 'lucide-react';
|
| 20 |
import { Button } from '@/components/ui/Button';
|
| 21 |
import { Input } from '@/components/ui/Input';
|
|
|
|
| 23 |
import { Badge } from '@/components/ui/Badge';
|
| 24 |
import { apiClient } from '@/api/client';
|
| 25 |
import type { SystemSettings } from '@/types';
|
| 26 |
+
import { classNames } from '@/utils/helpers';
|
| 27 |
|
| 28 |
interface SettingsProps {
|
| 29 |
className?: string;
|
|
|
|
| 51 |
plugins_installed: string[];
|
| 52 |
}
|
| 53 |
|
| 54 |
+
type SettingsSection = 'general' | 'api-keys' | 'models' | 'budget' | 'appearance' | 'notifications' | 'advanced';
|
| 55 |
+
|
| 56 |
+
const sectionConfig: { id: SettingsSection; label: string; icon: React.ElementType; description: string }[] = [
|
| 57 |
+
{ id: 'general', label: 'General', icon: SettingsIcon, description: 'Basic application settings' },
|
| 58 |
+
{ id: 'api-keys', label: 'API Keys', icon: Key, description: 'Configure provider API keys' },
|
| 59 |
+
{ id: 'models', label: 'Models', icon: Cpu, description: 'AI model selection' },
|
| 60 |
+
{ id: 'budget', label: 'Budget & Limits', icon: Wallet, description: 'API usage limits' },
|
| 61 |
+
{ id: 'appearance', label: 'Appearance', icon: Palette, description: 'UI customization' },
|
| 62 |
+
{ id: 'notifications', label: 'Notifications', icon: Bell, description: 'Alert preferences' },
|
| 63 |
+
{ id: 'advanced', label: 'Advanced', icon: Shield, description: 'Advanced settings' },
|
| 64 |
+
];
|
| 65 |
+
|
| 66 |
export const Settings: React.FC<SettingsProps> = ({ className }) => {
|
| 67 |
const queryClient = useQueryClient();
|
| 68 |
+
const [activeSection, setActiveSection] = useState<SettingsSection>('general');
|
| 69 |
const [localSettings, setLocalSettings] = useState<Partial<SystemSettings>>({});
|
| 70 |
const [showKeys, setShowKeys] = useState<Record<string, boolean>>({});
|
| 71 |
+
const [budgetEnabled, setBudgetEnabled] = useState(false);
|
| 72 |
const [apiKeys, setApiKeys] = useState<ApiKeyState>({
|
| 73 |
openai: '',
|
| 74 |
anthropic: '',
|
|
|
|
| 165 |
? `${settingsData.selected_model.provider}/${settingsData.selected_model.model}`
|
| 166 |
: 'groq/gpt-oss-120b';
|
| 167 |
|
| 168 |
+
const renderSectionContent = () => {
|
| 169 |
+
switch (activeSection) {
|
| 170 |
+
case 'general':
|
| 171 |
+
return (
|
| 172 |
+
<div className="space-y-6">
|
| 173 |
+
<div>
|
| 174 |
+
<h3 className="text-lg font-semibold text-white mb-1">General Settings</h3>
|
| 175 |
+
<p className="text-sm text-gray-400">Configure basic application behavior</p>
|
| 176 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 177 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 178 |
{/* API Key Required Warning */}
|
| 179 |
{keyRequired?.required && (
|
| 180 |
<div className="flex items-center gap-3 p-4 bg-amber-500/10 border border-amber-500/30 rounded-xl">
|
|
|
|
| 186 |
</div>
|
| 187 |
)}
|
| 188 |
|
| 189 |
+
<div className="space-y-4">
|
| 190 |
+
<Toggle
|
| 191 |
+
label="WebSocket Updates"
|
| 192 |
+
description="Enable real-time episode updates via WebSocket connection"
|
| 193 |
+
checked={localSettings.enableWebSocket ?? true}
|
| 194 |
+
onChange={(checked) => setLocalSettings((prev) => ({ ...prev, enableWebSocket: checked }))}
|
| 195 |
+
/>
|
| 196 |
+
<Toggle
|
| 197 |
+
label="Memory Persistence"
|
| 198 |
+
description="Persist memory data across episodes for better context retention"
|
| 199 |
+
checked={localSettings.memoryPersistence ?? false}
|
| 200 |
+
onChange={(checked) => setLocalSettings((prev) => ({ ...prev, memoryPersistence: checked }))}
|
| 201 |
+
/>
|
| 202 |
+
<Toggle
|
| 203 |
+
label="Auto-save Episodes"
|
| 204 |
+
description="Automatically save episode data when completed"
|
| 205 |
+
checked={localSettings.autoSave ?? true}
|
| 206 |
+
onChange={(checked) => setLocalSettings((prev) => ({ ...prev, autoSave: checked }))}
|
| 207 |
+
/>
|
| 208 |
+
<Toggle
|
| 209 |
+
label="Debug Mode"
|
| 210 |
+
description="Enable verbose logging and debugging information"
|
| 211 |
+
checked={localSettings.debugMode ?? false}
|
| 212 |
+
onChange={(checked) => setLocalSettings((prev) => ({ ...prev, debugMode: checked }))}
|
| 213 |
/>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 214 |
</div>
|
| 215 |
|
| 216 |
+
{/* System Status */}
|
| 217 |
+
<div className="pt-4 border-t border-gray-700/50">
|
| 218 |
+
<h4 className="text-sm font-medium text-gray-300 mb-3">System Status</h4>
|
| 219 |
+
<div className="grid grid-cols-2 gap-3">
|
| 220 |
+
<div className="p-3 bg-gray-900/50 rounded-lg">
|
| 221 |
+
<div className="flex items-center gap-2">
|
| 222 |
+
<Server className="w-4 h-4 text-emerald-400" />
|
| 223 |
+
<span className="text-xs text-gray-400">Backend</span>
|
| 224 |
+
</div>
|
| 225 |
+
<p className="text-sm font-medium text-white mt-1">
|
| 226 |
+
{health?.status === 'ok' ? 'Connected' : 'Disconnected'}
|
| 227 |
+
</p>
|
| 228 |
+
</div>
|
| 229 |
+
<div className="p-3 bg-gray-900/50 rounded-lg">
|
| 230 |
+
<div className="flex items-center gap-2">
|
| 231 |
+
<Globe className="w-4 h-4 text-cyan-400" />
|
| 232 |
+
<span className="text-xs text-gray-400">Version</span>
|
| 233 |
+
</div>
|
| 234 |
+
<p className="text-sm font-medium text-white mt-1">{health?.version || 'v0.1.0'}</p>
|
| 235 |
+
</div>
|
|
|
|
|
|
|
|
|
|
| 236 |
</div>
|
| 237 |
</div>
|
| 238 |
</div>
|
| 239 |
+
);
|
| 240 |
|
| 241 |
+
case 'api-keys':
|
| 242 |
+
return (
|
| 243 |
+
<div className="space-y-6">
|
| 244 |
+
<div>
|
| 245 |
+
<h3 className="text-lg font-semibold text-white mb-1">API Keys</h3>
|
| 246 |
+
<p className="text-sm text-gray-400">
|
| 247 |
+
Configure your provider API keys. Server keys are used by default, but you can override them here.
|
| 248 |
+
</p>
|
| 249 |
</div>
|
| 250 |
+
|
|
|
|
|
|
|
|
|
|
| 251 |
<div className="space-y-4">
|
| 252 |
{providers.map((provider) => {
|
| 253 |
const isConfigured = settingsData?.api_keys_configured?.[provider.id] ?? false;
|
|
|
|
| 257 |
<div className="flex items-center gap-3">
|
| 258 |
<span className="text-2xl">{provider.icon}</span>
|
| 259 |
<div>
|
| 260 |
+
<span className="text-sm font-medium text-white">{provider.name}</span>
|
|
|
|
|
|
|
| 261 |
<p className="text-xs text-gray-500">{provider.description}</p>
|
| 262 |
</div>
|
| 263 |
</div>
|
|
|
|
| 284 |
onClick={() => toggleShowKey(provider.id)}
|
| 285 |
className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-500 hover:text-gray-300 transition-colors"
|
| 286 |
>
|
| 287 |
+
{showKeys[provider.id] ? <EyeOff className="w-4 h-4" /> : <Eye className="w-4 h-4" />}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 288 |
</button>
|
| 289 |
</div>
|
| 290 |
<Button
|
|
|
|
| 301 |
})}
|
| 302 |
</div>
|
| 303 |
|
|
|
|
| 304 |
{updateApiKeyMutation.isSuccess && (
|
| 305 |
+
<div className="flex items-center gap-2 p-3 bg-emerald-500/10 border border-emerald-500/30 rounded-lg">
|
| 306 |
<CheckCircle className="w-4 h-4 text-emerald-400" />
|
| 307 |
<span className="text-sm text-emerald-400">API key saved successfully</span>
|
| 308 |
</div>
|
| 309 |
)}
|
| 310 |
</div>
|
| 311 |
+
);
|
| 312 |
+
|
| 313 |
+
case 'models':
|
| 314 |
+
return (
|
| 315 |
+
<div className="space-y-6">
|
| 316 |
+
<div>
|
| 317 |
+
<h3 className="text-lg font-semibold text-white mb-1">AI Models</h3>
|
| 318 |
+
<p className="text-sm text-gray-400">Select the AI model to use for scraping tasks</p>
|
| 319 |
+
</div>
|
| 320 |
+
|
| 321 |
+
<div className="p-4 bg-gray-900/50 border border-gray-700/30 rounded-xl">
|
| 322 |
+
<div className="flex items-center gap-2 text-sm font-medium text-white mb-3">
|
| 323 |
+
<Zap className="w-4 h-4 text-emerald-400" />
|
| 324 |
+
Active Model
|
| 325 |
+
</div>
|
| 326 |
+
<Select
|
| 327 |
+
label=""
|
| 328 |
+
options={modelOptions}
|
| 329 |
+
value={currentModel}
|
| 330 |
+
onChange={(e) => handleModelChange(e.target.value)}
|
| 331 |
+
placeholder="Select model"
|
| 332 |
+
/>
|
| 333 |
+
{selectModelMutation.isPending && (
|
| 334 |
+
<p className="text-xs text-gray-400 mt-2">Switching model...</p>
|
| 335 |
+
)}
|
| 336 |
+
</div>
|
| 337 |
+
|
| 338 |
+
{/* Model Categories */}
|
| 339 |
+
<div className="grid grid-cols-2 gap-3">
|
| 340 |
+
<div className="p-4 bg-cyan-500/10 border border-cyan-500/30 rounded-xl">
|
| 341 |
+
<h4 className="text-sm font-medium text-cyan-400 mb-2">Text Models</h4>
|
| 342 |
+
<p className="text-xs text-gray-400">GPT-4, Claude, Gemini for text generation</p>
|
| 343 |
+
</div>
|
| 344 |
+
<div className="p-4 bg-purple-500/10 border border-purple-500/30 rounded-xl">
|
| 345 |
+
<h4 className="text-sm font-medium text-purple-400 mb-2">Vision Models</h4>
|
| 346 |
+
<p className="text-xs text-gray-400">GPT-4V, Gemini Pro Vision for image analysis</p>
|
| 347 |
+
</div>
|
| 348 |
+
<div className="p-4 bg-amber-500/10 border border-amber-500/30 rounded-xl">
|
| 349 |
+
<h4 className="text-sm font-medium text-amber-400 mb-2">Embedding Models</h4>
|
| 350 |
+
<p className="text-xs text-gray-400">Text embeddings for semantic search</p>
|
| 351 |
+
</div>
|
| 352 |
+
<div className="p-4 bg-emerald-500/10 border border-emerald-500/30 rounded-xl">
|
| 353 |
+
<h4 className="text-sm font-medium text-emerald-400 mb-2">Fast Models</h4>
|
| 354 |
+
<p className="text-xs text-gray-400">Groq, Mistral for fast inference</p>
|
| 355 |
+
</div>
|
| 356 |
+
</div>
|
| 357 |
+
</div>
|
| 358 |
+
);
|
| 359 |
+
|
| 360 |
+
case 'budget':
|
| 361 |
+
return (
|
| 362 |
+
<div className="space-y-6">
|
| 363 |
+
<div>
|
| 364 |
+
<h3 className="text-lg font-semibold text-white mb-1">Budget & Limits</h3>
|
| 365 |
+
<p className="text-sm text-gray-400">Configure API usage limits and budget controls</p>
|
| 366 |
+
</div>
|
| 367 |
+
|
| 368 |
+
<div className="p-4 bg-gray-900/50 border border-gray-700/30 rounded-xl">
|
| 369 |
+
<div className="flex items-center justify-between mb-4">
|
| 370 |
+
<div className="flex items-center gap-3">
|
| 371 |
+
<Wallet className="w-5 h-5 text-amber-400" />
|
| 372 |
+
<div>
|
| 373 |
+
<h4 className="text-sm font-medium text-white">Enable Budget Limits</h4>
|
| 374 |
+
<p className="text-xs text-gray-500">Control API spending with usage limits</p>
|
| 375 |
+
</div>
|
| 376 |
+
</div>
|
| 377 |
+
<button
|
| 378 |
+
onClick={() => setBudgetEnabled(!budgetEnabled)}
|
| 379 |
+
className={classNames(
|
| 380 |
+
'relative w-12 h-6 rounded-full transition-colors',
|
| 381 |
+
budgetEnabled ? 'bg-emerald-500' : 'bg-gray-600'
|
| 382 |
+
)}
|
| 383 |
+
>
|
| 384 |
+
<span
|
| 385 |
+
className={classNames(
|
| 386 |
+
'absolute top-1 w-4 h-4 bg-white rounded-full transition-transform',
|
| 387 |
+
budgetEnabled ? 'translate-x-7' : 'translate-x-1'
|
| 388 |
+
)}
|
| 389 |
+
/>
|
| 390 |
+
</button>
|
| 391 |
+
</div>
|
| 392 |
+
|
| 393 |
+
{budgetEnabled ? (
|
| 394 |
+
<div className="space-y-4 pt-4 border-t border-gray-700/50">
|
| 395 |
+
<div>
|
| 396 |
+
<label className="text-xs text-gray-400 mb-2 block">Daily Limit ($)</label>
|
| 397 |
+
<Input type="number" placeholder="10.00" className="bg-gray-800/50" />
|
| 398 |
+
</div>
|
| 399 |
+
<div>
|
| 400 |
+
<label className="text-xs text-gray-400 mb-2 block">Monthly Limit ($)</label>
|
| 401 |
+
<Input type="number" placeholder="100.00" className="bg-gray-800/50" />
|
| 402 |
+
</div>
|
| 403 |
+
<div>
|
| 404 |
+
<label className="text-xs text-gray-400 mb-2 block">Max Tokens per Request</label>
|
| 405 |
+
<Input type="number" placeholder="4096" className="bg-gray-800/50" />
|
| 406 |
+
</div>
|
| 407 |
+
<Toggle
|
| 408 |
+
label="Alert at 80% usage"
|
| 409 |
+
description="Receive notification when approaching limit"
|
| 410 |
+
checked={true}
|
| 411 |
+
onChange={() => {}}
|
| 412 |
+
/>
|
| 413 |
+
</div>
|
| 414 |
+
) : (
|
| 415 |
+
<div className="pt-4 border-t border-gray-700/50">
|
| 416 |
+
<p className="text-sm text-gray-500 text-center py-4">
|
| 417 |
+
Budget limits are disabled. Enable to control API spending.
|
| 418 |
+
</p>
|
| 419 |
+
</div>
|
| 420 |
+
)}
|
| 421 |
+
</div>
|
| 422 |
+
</div>
|
| 423 |
+
);
|
| 424 |
+
|
| 425 |
+
case 'appearance':
|
| 426 |
+
return (
|
| 427 |
+
<div className="space-y-6">
|
| 428 |
+
<div>
|
| 429 |
+
<h3 className="text-lg font-semibold text-white mb-1">Appearance</h3>
|
| 430 |
+
<p className="text-sm text-gray-400">Customize the look and feel of ScrapeRL</p>
|
| 431 |
+
</div>
|
| 432 |
+
|
| 433 |
+
<div className="space-y-4">
|
| 434 |
+
<div className="p-4 bg-gray-900/50 border border-gray-700/30 rounded-xl">
|
| 435 |
+
<h4 className="text-sm font-medium text-white mb-3">Theme</h4>
|
| 436 |
+
<div className="grid grid-cols-3 gap-3">
|
| 437 |
+
<button className="p-3 bg-gray-800 border-2 border-emerald-500 rounded-lg text-center">
|
| 438 |
+
<div className="w-8 h-8 bg-gray-900 rounded mx-auto mb-2" />
|
| 439 |
+
<span className="text-xs text-white">Dark</span>
|
| 440 |
+
</button>
|
| 441 |
+
<button className="p-3 bg-gray-800 border border-gray-600 rounded-lg text-center opacity-50">
|
| 442 |
+
<div className="w-8 h-8 bg-white rounded mx-auto mb-2" />
|
| 443 |
+
<span className="text-xs text-gray-400">Light</span>
|
| 444 |
+
</button>
|
| 445 |
+
<button className="p-3 bg-gray-800 border border-gray-600 rounded-lg text-center opacity-50">
|
| 446 |
+
<div className="w-8 h-8 bg-gradient-to-b from-white to-gray-900 rounded mx-auto mb-2" />
|
| 447 |
+
<span className="text-xs text-gray-400">Auto</span>
|
| 448 |
+
</button>
|
| 449 |
+
</div>
|
| 450 |
+
</div>
|
| 451 |
+
|
| 452 |
+
<Toggle
|
| 453 |
+
label="Compact Mode"
|
| 454 |
+
description="Reduce padding and spacing for more content"
|
| 455 |
+
checked={false}
|
| 456 |
+
onChange={() => {}}
|
| 457 |
+
/>
|
| 458 |
+
<Toggle
|
| 459 |
+
label="Show Animations"
|
| 460 |
+
description="Enable UI animations and transitions"
|
| 461 |
+
checked={true}
|
| 462 |
+
onChange={() => {}}
|
| 463 |
+
/>
|
| 464 |
+
</div>
|
| 465 |
+
</div>
|
| 466 |
+
);
|
| 467 |
+
|
| 468 |
+
case 'notifications':
|
| 469 |
+
return (
|
| 470 |
+
<div className="space-y-6">
|
| 471 |
+
<div>
|
| 472 |
+
<h3 className="text-lg font-semibold text-white mb-1">Notifications</h3>
|
| 473 |
+
<p className="text-sm text-gray-400">Configure when and how you receive alerts</p>
|
| 474 |
+
</div>
|
| 475 |
+
|
| 476 |
+
<div className="space-y-4">
|
| 477 |
+
<Toggle
|
| 478 |
+
label="Episode Completion"
|
| 479 |
+
description="Notify when an episode finishes"
|
| 480 |
+
checked={true}
|
| 481 |
+
onChange={() => {}}
|
| 482 |
+
/>
|
| 483 |
+
<Toggle
|
| 484 |
+
label="Error Alerts"
|
| 485 |
+
description="Alert on scraping errors"
|
| 486 |
+
checked={true}
|
| 487 |
+
onChange={() => {}}
|
| 488 |
+
/>
|
| 489 |
+
<Toggle
|
| 490 |
+
label="Budget Warnings"
|
| 491 |
+
description="Warn when approaching budget limits"
|
| 492 |
+
checked={true}
|
| 493 |
+
onChange={() => {}}
|
| 494 |
+
/>
|
| 495 |
+
<Toggle
|
| 496 |
+
label="System Updates"
|
| 497 |
+
description="Notify about new features and updates"
|
| 498 |
+
checked={false}
|
| 499 |
+
onChange={() => {}}
|
| 500 |
+
/>
|
| 501 |
+
</div>
|
| 502 |
+
</div>
|
| 503 |
+
);
|
| 504 |
+
|
| 505 |
+
case 'advanced':
|
| 506 |
+
return (
|
| 507 |
+
<div className="space-y-6">
|
| 508 |
+
<div>
|
| 509 |
+
<h3 className="text-lg font-semibold text-white mb-1">Advanced Settings</h3>
|
| 510 |
+
<p className="text-sm text-gray-400">For power users and developers</p>
|
| 511 |
+
</div>
|
| 512 |
+
|
| 513 |
+
<div className="space-y-4">
|
| 514 |
+
<Toggle
|
| 515 |
+
label="Developer Mode"
|
| 516 |
+
description="Enable advanced debugging tools"
|
| 517 |
+
checked={false}
|
| 518 |
+
onChange={() => {}}
|
| 519 |
+
/>
|
| 520 |
+
<Toggle
|
| 521 |
+
label="Experimental Features"
|
| 522 |
+
description="Try new features before release"
|
| 523 |
+
checked={false}
|
| 524 |
+
onChange={() => {}}
|
| 525 |
+
/>
|
| 526 |
+
<Toggle
|
| 527 |
+
label="Verbose Logging"
|
| 528 |
+
description="Log all API requests and responses"
|
| 529 |
+
checked={false}
|
| 530 |
+
onChange={() => {}}
|
| 531 |
+
/>
|
| 532 |
+
|
| 533 |
+
<div className="pt-4 border-t border-gray-700/50">
|
| 534 |
+
<h4 className="text-sm font-medium text-white mb-3">Data Management</h4>
|
| 535 |
+
<div className="flex gap-3">
|
| 536 |
+
<Button variant="secondary" size="sm">
|
| 537 |
+
Export Data
|
| 538 |
+
</Button>
|
| 539 |
+
<Button variant="ghost" size="sm" className="text-red-400 hover:text-red-300">
|
| 540 |
+
Clear Cache
|
| 541 |
+
</Button>
|
| 542 |
+
</div>
|
| 543 |
+
</div>
|
| 544 |
+
</div>
|
| 545 |
+
</div>
|
| 546 |
+
);
|
| 547 |
+
|
| 548 |
+
default:
|
| 549 |
+
return null;
|
| 550 |
+
}
|
| 551 |
+
};
|
| 552 |
+
|
| 553 |
+
return (
|
| 554 |
+
<div className={classNames('flex h-[calc(100vh-120px)]', className)}>
|
| 555 |
+
{/* Left Sidebar */}
|
| 556 |
+
<div className="w-64 bg-gray-800/30 border-r border-gray-700/50 flex flex-col">
|
| 557 |
+
<div className="p-4 border-b border-gray-700/50">
|
| 558 |
+
<h2 className="text-lg font-semibold text-white flex items-center gap-2">
|
| 559 |
+
<SettingsIcon className="w-5 h-5 text-purple-400" />
|
| 560 |
+
Settings
|
| 561 |
+
</h2>
|
| 562 |
+
<p className="text-xs text-gray-500 mt-1">Configure your environment</p>
|
| 563 |
+
</div>
|
| 564 |
+
|
| 565 |
+
<nav className="flex-1 p-3 space-y-1 overflow-y-auto">
|
| 566 |
+
{sectionConfig.map((section) => {
|
| 567 |
+
const Icon = section.icon;
|
| 568 |
+
const isActive = activeSection === section.id;
|
| 569 |
+
return (
|
| 570 |
+
<button
|
| 571 |
+
key={section.id}
|
| 572 |
+
onClick={() => setActiveSection(section.id)}
|
| 573 |
+
className={classNames(
|
| 574 |
+
'w-full flex items-center gap-3 px-3 py-2.5 rounded-lg text-left transition-all group',
|
| 575 |
+
isActive
|
| 576 |
+
? 'bg-emerald-500/20 border border-emerald-500/30 text-emerald-400'
|
| 577 |
+
: 'hover:bg-gray-700/50 text-gray-400 hover:text-gray-200'
|
| 578 |
+
)}
|
| 579 |
+
>
|
| 580 |
+
<Icon className={classNames('w-4 h-4', isActive ? 'text-emerald-400' : 'text-gray-500 group-hover:text-gray-300')} />
|
| 581 |
+
<span className="text-sm font-medium">{section.label}</span>
|
| 582 |
+
<ChevronRight className={classNames('w-4 h-4 ml-auto transition-transform', isActive ? 'rotate-90' : '')} />
|
| 583 |
+
</button>
|
| 584 |
+
);
|
| 585 |
+
})}
|
| 586 |
+
</nav>
|
| 587 |
+
|
| 588 |
+
{/* Status Footer */}
|
| 589 |
+
<div className="p-4 border-t border-gray-700/50">
|
| 590 |
+
<div className="flex items-center gap-2">
|
| 591 |
+
<div className={classNames('w-2 h-2 rounded-full', health?.status === 'ok' ? 'bg-emerald-400' : 'bg-red-400')} />
|
| 592 |
+
<span className="text-xs text-gray-400">{health?.status === 'ok' ? 'System Online' : 'System Offline'}</span>
|
| 593 |
+
</div>
|
| 594 |
+
</div>
|
| 595 |
+
</div>
|
| 596 |
+
|
| 597 |
+
{/* Main Content */}
|
| 598 |
+
<div className="flex-1 overflow-y-auto">
|
| 599 |
+
<div className="p-6">
|
| 600 |
+
{settingsLoading ? (
|
| 601 |
+
<div className="flex items-center justify-center py-16">
|
| 602 |
+
<div className="flex flex-col items-center gap-3">
|
| 603 |
+
<SettingsIcon className="w-8 h-8 text-gray-500 animate-spin" />
|
| 604 |
+
<p className="text-gray-400">Loading settings...</p>
|
| 605 |
+
</div>
|
| 606 |
+
</div>
|
| 607 |
+
) : (
|
| 608 |
+
renderSectionContent()
|
| 609 |
+
)}
|
| 610 |
</div>
|
| 611 |
+
</div>
|
| 612 |
</div>
|
| 613 |
);
|
| 614 |
};
|
|
@@ -200,6 +200,8 @@ export interface SystemSettings {
|
|
| 200 |
logLevel: 'debug' | 'info' | 'warn' | 'error';
|
| 201 |
screenshotQuality: number;
|
| 202 |
memoryPersistence: boolean;
|
|
|
|
|
|
|
| 203 |
}
|
| 204 |
|
| 205 |
export interface WebSocketMessage {
|
|
|
|
| 200 |
logLevel: 'debug' | 'info' | 'warn' | 'error';
|
| 201 |
screenshotQuality: number;
|
| 202 |
memoryPersistence: boolean;
|
| 203 |
+
autoSave: boolean;
|
| 204 |
+
debugMode: boolean;
|
| 205 |
}
|
| 206 |
|
| 207 |
export interface WebSocketMessage {
|
|
@@ -1 +1 @@
|
|
| 1 |
-
{"root":["./src/app.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/api/client.ts","./src/components/actionpanel.tsx","./src/components/agentview.tsx","./src/components/dashboard.tsx","./src/components/episodepanel.tsx","./src/components/memorypanel.tsx","./src/components/observationview.tsx","./src/components/pluginspage.tsx","./src/components/rewardchart.tsx","./src/components/settings.tsx","./src/components/toolregistry.tsx","./src/components/ui/badge.tsx","./src/components/ui/button.tsx","./src/components/ui/card.tsx","./src/components/ui/input.tsx","./src/components/ui/select.tsx","./src/hooks/useagents.ts","./src/hooks/useepisode.ts","./src/hooks/usememory.ts","./src/hooks/usewebsocket.ts","./src/test/components.test.tsx","./src/test/helpers.test.ts","./src/test/setup.ts","./src/types/index.ts","./src/utils/helpers.ts"],"version":"5.6.3"}
|
|
|
|
| 1 |
+
{"root":["./src/app.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/api/client.ts","./src/components/actionpanel.tsx","./src/components/agentview.tsx","./src/components/dashboard.tsx","./src/components/docspage.tsx","./src/components/episodepanel.tsx","./src/components/memorypanel.tsx","./src/components/observationview.tsx","./src/components/pluginspage.tsx","./src/components/rewardchart.tsx","./src/components/settings.tsx","./src/components/toolregistry.tsx","./src/components/ui/badge.tsx","./src/components/ui/button.tsx","./src/components/ui/card.tsx","./src/components/ui/input.tsx","./src/components/ui/select.tsx","./src/hooks/useagents.ts","./src/hooks/useepisode.ts","./src/hooks/usememory.ts","./src/hooks/usewebsocket.ts","./src/test/components.test.tsx","./src/test/helpers.test.ts","./src/test/setup.ts","./src/types/index.ts","./src/utils/helpers.ts"],"version":"5.6.3"}
|