God Agent OS commited on
Commit
bbdf1be
·
2 Parent(s): a65f14f527d436

Merge branch 'genspark_ai_developer'

Browse files
Files changed (39) hide show
  1. .github/workflows/deploy.yml +22 -23
  2. .gitignore +50 -0
  3. README.md +59 -35
  4. backend/Dockerfile.hf +11 -1
  5. backend/__pycache__/main.cpython-312.pyc +0 -0
  6. backend/ai_router/__init__.py +4 -2
  7. backend/ai_router/key_pool.py +131 -0
  8. backend/ai_router/router_v8.py +308 -0
  9. backend/main.py +28 -4
  10. backend/main_v8.py +326 -0
  11. frontend/app/globals.css +289 -193
  12. frontend/app/layout.tsx +9 -7
  13. frontend/app/page.tsx +60 -58
  14. frontend/components/dashboard/ActivityFeed.tsx +45 -0
  15. frontend/components/dashboard/AgentFleetCard.tsx +76 -0
  16. frontend/components/dashboard/CommandCenter.tsx +81 -0
  17. frontend/components/dashboard/GodModeCard.tsx +48 -0
  18. frontend/components/dashboard/MetricCard.tsx +48 -0
  19. frontend/components/dashboard/MissionInput.tsx +125 -0
  20. frontend/components/dashboard/SystemResources.tsx +59 -0
  21. frontend/components/layout/AIRouterPanel.tsx +268 -0
  22. frontend/components/layout/Sidebar.tsx +2 -1
  23. frontend/components/pages/AgentsPage.tsx +157 -0
  24. frontend/components/pages/AnalyticsPage.tsx +121 -0
  25. frontend/components/pages/DashboardPage.tsx +113 -0
  26. frontend/components/pages/KnowledgePage.tsx +80 -0
  27. frontend/components/pages/MemoryPage.tsx +85 -0
  28. frontend/components/pages/SettingsPage.tsx +154 -0
  29. frontend/components/pages/TasksPage.tsx +124 -0
  30. frontend/components/pages/WorkflowsPage.tsx +77 -0
  31. frontend/components/shared/Sidebar.tsx +142 -0
  32. frontend/components/shared/TopBar.tsx +181 -0
  33. frontend/hooks/useAgentStore.ts +1 -1
  34. frontend/lib/utils.ts +34 -0
  35. frontend/package-lock.json +1111 -91
  36. frontend/package.json +9 -2
  37. frontend/store/useAppStore.ts +131 -0
  38. frontend/tailwind.config.js +48 -65
  39. frontend/vercel.json +4 -2
.github/workflows/deploy.yml CHANGED
@@ -1,4 +1,4 @@
1
- name: 🚀 God Agent OS v7 — Auto Deploy
2
 
3
  on:
4
  push:
@@ -10,7 +10,7 @@ env:
10
  VERCEL_PROJECT: god-agent-os
11
 
12
  jobs:
13
- # ── Build & Test ──────────────────────────────────────────────────────────
14
  build-check:
15
  name: ✅ Build Check
16
  runs-on: ubuntu-latest
@@ -28,10 +28,12 @@ jobs:
28
  cd backend
29
  pip install -r requirements.txt
30
 
31
- - name: Syntax check backend
32
  run: |
33
  cd backend
34
- python -m py_compile main_v7.py
 
 
35
  python -m py_compile agents/orchestrator_v7.py
36
  python -m py_compile agents/browser_agent.py
37
  python -m py_compile agents/file_agent.py
@@ -55,7 +57,7 @@ jobs:
55
  env:
56
  NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL || 'https://PYAE1994-autonomous-coding-system.hf.space' }}
57
 
58
- # ── Deploy to Hugging Face Spaces ────────────────────────────────────────
59
  deploy-huggingface:
60
  name: 🤗 Deploy to HF Spaces
61
  runs-on: ubuntu-latest
@@ -72,23 +74,24 @@ jobs:
72
  git config --global user.email "action@github.com"
73
  git config --global user.name "God Agent CI"
74
 
75
- - name: Deploy backend to HF Space
76
  env:
77
  HF_TOKEN: ${{ secrets.HF_TOKEN }}
78
  run: |
79
- # Install HF CLI
80
  pip install huggingface_hub -q
81
 
82
- # Clone HF space
83
  git clone https://pyae1994:$HF_TOKEN@huggingface.co/spaces/PYAE1994/autonomous-coding-system /tmp/hf-space
84
-
85
  # Copy backend files
86
  cp -r backend/. /tmp/hf-space/
87
-
88
- # Create HF-specific README
 
 
 
89
  cat > /tmp/hf-space/README.md << 'EOF'
90
  ---
91
- title: God Agent OS v7
92
  emoji: 🤖
93
  colorFrom: indigo
94
  colorTo: purple
@@ -96,27 +99,23 @@ jobs:
96
  app_port: 7860
97
  pinned: true
98
  license: mit
99
- short_description: Autonomous Engineering OS — Manus + Genspark + Devin
100
  ---
101
 
102
- # 🤖 God Agent OS v7
103
- **Autonomous Engineering PlatformManus + Genspark + Devin (OneHand)**
104
 
105
- 16-agent system for autonomous software engineering.
106
  EOF
107
 
108
- # Use HF Dockerfile
109
- cp backend/Dockerfile.hf /tmp/hf-space/Dockerfile
110
-
111
- # Commit and push
112
  cd /tmp/hf-space
113
  git add -A
114
- git diff --cached --quiet || git commit -m "🚀 God Agent OS v7 deploy $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
115
  git push origin main || git push origin master || true
116
-
117
  echo "✅ Deployed to HF Space: https://huggingface.co/spaces/PYAE1994/autonomous-coding-system"
118
 
119
- # ── Deploy to Vercel ───────────────────────────────────────────────────────
120
  deploy-vercel:
121
  name: ▲ Deploy to Vercel
122
  runs-on: ubuntu-latest
 
1
+ name: 🚀 God Agent OS v8 — Auto Deploy
2
 
3
  on:
4
  push:
 
10
  VERCEL_PROJECT: god-agent-os
11
 
12
  jobs:
13
+ # ── Build & Syntax Check ──────────────────────────────────────────────────
14
  build-check:
15
  name: ✅ Build Check
16
  runs-on: ubuntu-latest
 
28
  cd backend
29
  pip install -r requirements.txt
30
 
31
+ - name: Syntax check backend (v8)
32
  run: |
33
  cd backend
34
+ python -m py_compile main_v8.py
35
+ python -m py_compile ai_router/router_v8.py
36
+ python -m py_compile ai_router/key_pool.py
37
  python -m py_compile agents/orchestrator_v7.py
38
  python -m py_compile agents/browser_agent.py
39
  python -m py_compile agents/file_agent.py
 
57
  env:
58
  NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL || 'https://PYAE1994-autonomous-coding-system.hf.space' }}
59
 
60
+ # ── Deploy to Hugging Face Spaces ────────────────────────────────────────
61
  deploy-huggingface:
62
  name: 🤗 Deploy to HF Spaces
63
  runs-on: ubuntu-latest
 
74
  git config --global user.email "action@github.com"
75
  git config --global user.name "God Agent CI"
76
 
77
+ - name: Deploy backend to HF Space (v8)
78
  env:
79
  HF_TOKEN: ${{ secrets.HF_TOKEN }}
80
  run: |
 
81
  pip install huggingface_hub -q
82
 
 
83
  git clone https://pyae1994:$HF_TOKEN@huggingface.co/spaces/PYAE1994/autonomous-coding-system /tmp/hf-space
84
+
85
  # Copy backend files
86
  cp -r backend/. /tmp/hf-space/
87
+
88
+ # Use v8 Dockerfile
89
+ cp backend/Dockerfile.hf /tmp/hf-space/Dockerfile
90
+
91
+ # Create HF README with v8 metadata
92
  cat > /tmp/hf-space/README.md << 'EOF'
93
  ---
94
+ title: God Agent OS v8
95
  emoji: 🤖
96
  colorFrom: indigo
97
  colorTo: purple
 
99
  app_port: 7860
100
  pinned: true
101
  license: mit
102
+ short_description: Autonomous Engineering OS v8 KeyPool Multi-API (Gemini + SambaNova)
103
  ---
104
 
105
+ # 🤖 God Agent OS v8
106
+ **KeyPool Multi-API RoutingGemini + SambaNova Primary LLMs**
107
 
108
+ 16-agent autonomous engineering OS with intelligent key pooling.
109
  EOF
110
 
 
 
 
 
111
  cd /tmp/hf-space
112
  git add -A
113
+ git diff --cached --quiet || git commit -m "🚀 God Agent OS v8 deploy $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
114
  git push origin main || git push origin master || true
115
+
116
  echo "✅ Deployed to HF Space: https://huggingface.co/spaces/PYAE1994/autonomous-coding-system"
117
 
118
+ # ── Deploy to Vercel ─────────────────────────────────────────────────────
119
  deploy-vercel:
120
  name: ▲ Deploy to Vercel
121
  runs-on: ubuntu-latest
.gitignore ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Dependencies
2
+ node_modules/
3
+ frontend/node_modules/
4
+ __pycache__/
5
+ *.pyc
6
+ *.pyo
7
+ *.pyd
8
+ .Python
9
+
10
+ # Build outputs
11
+ frontend/.next/
12
+ frontend/out/
13
+ dist/
14
+ build/
15
+ *.egg-info/
16
+
17
+ # Environment
18
+ .env
19
+ .env.local
20
+ .env.production
21
+ *.env
22
+
23
+ # Logs
24
+ *.log
25
+ logs/
26
+
27
+ # Database
28
+ *.db
29
+ *.sqlite
30
+
31
+ # OS
32
+ .DS_Store
33
+ Thumbs.db
34
+
35
+ # IDE
36
+ .vscode/
37
+ .idea/
38
+ *.swp
39
+
40
+ # Temporary
41
+ tmp/
42
+ temp/
43
+ /tmp/
44
+
45
+ # Python cache
46
+ backend/__pycache__/
47
+ backend/**/__pycache__/
48
+ backend/ai_router/__pycache__/
49
+ .env.keys
50
+ backend/.env.keys
README.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- title: God Agent OS v7
3
  emoji: 🤖
4
  colorFrom: indigo
5
  colorTo: purple
@@ -7,24 +7,39 @@ sdk: docker
7
  app_port: 7860
8
  pinned: true
9
  license: mit
10
- short_description: Autonomous Engineering OS — Manus + Genspark + Devin (OneHand)
11
  ---
12
 
13
- # 🤖 GOD AGENT OS v7
14
  **Autonomous Engineering Operating System**
15
- *Manus + Genspark + Devin (OneHand) — Combined*
16
 
17
  [![GitHub](https://img.shields.io/badge/GitHub-god--agent--os-blue?logo=github)](https://github.com/pyaesonegtckglay-dotcom/god-agent-os)
18
- [![Version](https://img.shields.io/badge/version-7.0.0-indigo)](https://github.com/pyaesonegtckglay-dotcom/god-agent-os)
 
19
 
20
- ## 🚀 What is God Agent OS?
21
 
22
- God Agent OS is a fully autonomous AI engineering platform that combines:
23
- - **Manus** — Deep reasoning, multi-step planning, autonomous orchestration
24
- - **Genspark** — Repository-scale code generation, multi-model AI routing
25
- - **Devin/OneHand** Self-healing code execution, browser control, file mastery
 
26
 
27
- ## 🤖 16-Agent Fleet (v7 NEW!)
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
  | Agent | Capability | Status |
30
  |-------|-----------|--------|
@@ -32,52 +47,61 @@ God Agent OS is a fully autonomous AI engineering platform that combines:
32
  | 📋 Planner | Task decomposition & planning | Core |
33
  | 💻 Coding | Production code generation | Core |
34
  | 🐛 Debug | Self-healing error resolution | Core |
35
- | 🌐 **Browser** | Web research & scraping | ⭐ NEW v7 |
36
- | 📁 **File** | File system & project scaffold | ⭐ NEW v7 |
37
- | 🔀 **Git** | Git ops & GitHub PR creation | ⭐ NEW v7 |
38
- | 🧪 **Test** | Auto test generation & execution | ⭐ NEW v7 |
39
- | 🎨 **Vision** | Design-to-code UI generation | ⭐ NEW v7 |
40
  | 🖥️ Sandbox | Isolated code execution | Core |
41
  | 🚀 Deploy | Auto-deploy to cloud | Core |
42
  | 🔌 Connector | External integrations | Core |
43
  | 🧠 Memory | Long-term context | Core |
44
  | ⚙️ Workflow | n8n automation | Core |
 
 
45
 
46
- ## 🔑 Required API Keys
47
 
48
- Set these in Space Settings → Variables and Secrets:
49
 
50
- | Variable | Description | Required |
51
- |----------|-------------|----------|
 
 
 
52
  | `OPENAI_API_KEY` | GPT-4o | Optional |
53
- | `GROQ_API_KEY` | Llama 3.3 70B (Free!) | Recommended |
54
- | `OPENROUTER_API_KEY` | 100+ models | Optional |
55
  | `ANTHROPIC_API_KEY` | Claude 3.5 | Optional |
56
- | `GITHUB_TOKEN` | Git operations | Optional |
57
-
58
- > **Note:** System works in demo mode without any keys. Add at least `GROQ_API_KEY` for full AI power (it's free!).
59
 
60
  ## 🌐 API Documentation
61
 
62
  - Interactive docs: `/api/docs`
63
  - Health check: `/health`
 
 
64
 
65
  ## 📦 Architecture
66
 
67
  ```
68
  god-agent-os/
69
- ├── backend/ # FastAPI backend (16 agents)
70
- │ ├─ agents/ # All 16 specialized agents
71
- │ ├── ai_router/ # Multi-model AI router (5 providers)
72
- │ ├── api/ # REST + WebSocket endpoints
73
- │ ├── core/ # Task engine & models
74
- ── memory/ # SQLite persistent memory
75
- ── connectors/ # External service connectors
76
- ── frontend/ # Next.js 14 UI (deployed on Vercel)
 
 
 
 
 
 
 
 
77
  ```
78
 
79
  ## 🔄 Auto-Deploy Pipeline
80
 
81
  GitHub Push → Build Check → HF Space Deploy + Vercel Deploy
82
-
83
- All automatic via GitHub Actions!
 
1
  ---
2
+ title: God Agent OS v8
3
  emoji: 🤖
4
  colorFrom: indigo
5
  colorTo: purple
 
7
  app_port: 7860
8
  pinned: true
9
  license: mit
10
+ short_description: Autonomous Engineering OS v8 KeyPool Multi-API (Gemini + SambaNova)
11
  ---
12
 
13
+ # 🤖 GOD AGENT OS v8
14
  **Autonomous Engineering Operating System**
15
+ *Manus + Genspark + Devin (OneHand) — KeyPool Multi-API Edition*
16
 
17
  [![GitHub](https://img.shields.io/badge/GitHub-god--agent--os-blue?logo=github)](https://github.com/pyaesonegtckglay-dotcom/god-agent-os)
18
+ [![Version](https://img.shields.io/badge/version-8.0.0-indigo)](https://github.com/pyaesonegtckglay-dotcom/god-agent-os)
19
+ [![HF Space](https://img.shields.io/badge/HF%20Space-PYAE1994-orange)](https://huggingface.co/spaces/PYAE1994/autonomous-coding-system)
20
 
21
+ ## 🚀 What is God Agent OS v8?
22
 
23
+ God Agent OS v8 is a fully autonomous AI engineering platform with **KeyPool Multi-API Routing**:
24
+ - **Gemini** (6 keys) Google Gemini 1.5 Flash primary LLM
25
+ - **SambaNova** (9 keys) Meta Llama 3.3 70B primary LLM
26
+ - **GitHub API** (9 keys) Pooled Git operations
27
+ - **Automatic failover** across 7 providers
28
 
29
+ ## 🔑 v8 KeyPool System
30
+
31
+ ```
32
+ Priority Chain:
33
+ SambaNova (9 keys) → Gemini (6 keys) → OpenAI → Groq → Cerebras → OpenRouter → Anthropic
34
+
35
+ Each key pool:
36
+ - Round-robin key selection
37
+ - Failure tracking per key
38
+ - Automatic cooldown (60s after 3 failures)
39
+ - Real-time status dashboard in UI
40
+ ```
41
+
42
+ ## 🤖 16-Agent Fleet
43
 
44
  | Agent | Capability | Status |
45
  |-------|-----------|--------|
 
47
  | 📋 Planner | Task decomposition & planning | Core |
48
  | 💻 Coding | Production code generation | Core |
49
  | 🐛 Debug | Self-healing error resolution | Core |
50
+ | 🌐 Browser | Web research & scraping | v7 |
51
+ | 📁 File | File system & project scaffold | v7 |
52
+ | 🔀 Git | Git ops & GitHub PR creation | v7 |
53
+ | 🧪 Test | Auto test generation & execution | v7 |
54
+ | 🎨 Vision | Design-to-code UI generation | v7 |
55
  | 🖥️ Sandbox | Isolated code execution | Core |
56
  | 🚀 Deploy | Auto-deploy to cloud | Core |
57
  | 🔌 Connector | External integrations | Core |
58
  | 🧠 Memory | Long-term context | Core |
59
  | ⚙️ Workflow | n8n automation | Core |
60
+ | 🔍 Reasoning | Deep reasoning & analysis | Core |
61
+ | 🎨 UI | Real-time UI state | Core |
62
 
63
+ ## 🔑 API Keys Configuration
64
 
65
+ Set these in Hugging Face Space Settings → Variables:
66
 
67
+ | Variable | Description | Keys |
68
+ |----------|-------------|------|
69
+ | `GEMINI_API_KEYS` | Google Gemini (comma-separated) | 6 keys |
70
+ | `SAMBANOVA_API_KEYS` | SambaNova (comma-separated) | 9 keys |
71
+ | `GITHUB_API_KEYS` | GitHub API (comma-separated) | 9 keys |
72
  | `OPENAI_API_KEY` | GPT-4o | Optional |
73
+ | `GROQ_API_KEY` | Llama 3.3 70B (Free) | Optional |
 
74
  | `ANTHROPIC_API_KEY` | Claude 3.5 | Optional |
 
 
 
75
 
76
  ## 🌐 API Documentation
77
 
78
  - Interactive docs: `/api/docs`
79
  - Health check: `/health`
80
+ - AI Router stats: `/api/v1/ai/stats`
81
+ - Key pool status: `/api/v1/ai/pool-status`
82
 
83
  ## 📦 Architecture
84
 
85
  ```
86
  god-agent-os/
87
+ ├── backend/
88
+ │ ├─��� agents/ # 16 specialized agents
89
+ │ ├── ai_router/
90
+ ├── key_pool.py # KeyPool multi-key manager (NEW v8)
91
+ ├── router_v8.py # AIRouterV8 with KeyPool (NEW v8)
92
+ │ └── router.py # Legacy router (retained)
93
+ ── api/ # REST + WebSocket endpoints
94
+ │ ├── core/ # Task engine & models
95
+ │ ├── memory/ # SQLite persistent memory
96
+ │ ├── connectors/ # External service connectors
97
+ │ ├── main_v8.py # v8 Entry point (NEW)
98
+ │ └── Dockerfile.hf # HF Spaces Docker
99
+ └── frontend/ # Next.js 14 UI
100
+ └── components/
101
+ └── layout/
102
+ └── AIRouterPanel.tsx # v8 Key pool status UI (NEW)
103
  ```
104
 
105
  ## 🔄 Auto-Deploy Pipeline
106
 
107
  GitHub Push → Build Check → HF Space Deploy + Vercel Deploy
 
 
backend/Dockerfile.hf CHANGED
@@ -22,6 +22,16 @@ ENV PORT=7860
22
  ENV WORKSPACE_DIR=/tmp/god_workspace
23
  ENV PYTHONPATH=/app
24
 
 
 
 
 
 
 
 
 
 
 
25
  EXPOSE 7860
26
 
27
- CMD ["uvicorn", "main_v7:app", "--host", "0.0.0.0", "--port", "7860", "--workers", "1"]
 
22
  ENV WORKSPACE_DIR=/tmp/god_workspace
23
  ENV PYTHONPATH=/app
24
 
25
+ # API Keys are configured via HF Space Secrets (Settings → Variables and Secrets)
26
+ # Set these in your HF Space:
27
+ # GEMINI_API_KEYS — comma-separated Gemini API keys
28
+ # SAMBANOVA_API_KEYS — comma-separated SambaNova API keys
29
+ # GITHUB_API_KEYS — comma-separated GitHub tokens
30
+ # GITHUB_TOKEN — primary GitHub token
31
+ # OPENAI_API_KEY — OpenAI API key (optional)
32
+ # GROQ_API_KEY — Groq API key (optional, free)
33
+ # ANTHROPIC_API_KEY — Anthropic API key (optional)
34
+
35
  EXPOSE 7860
36
 
37
+ CMD ["uvicorn", "main_v8:app", "--host", "0.0.0.0", "--port", "7860", "--workers", "1"]
backend/__pycache__/main.cpython-312.pyc DELETED
Binary file (9.42 kB)
 
backend/ai_router/__init__.py CHANGED
@@ -1,4 +1,6 @@
1
- # Multi-Model AI Router
 
2
  from .router import AIRouter
 
3
 
4
- __all__ = ["AIRouter"]
 
1
+ # Multi-Model AI Router — GOD AGENT OS v8
2
+ # Primary: Gemini → Sambanova → GitHub Models (task-aware rotation)
3
  from .router import AIRouter
4
+ from .router_v8 import GodModeRouter, get_router, classify_task, get_provider_order
5
 
6
+ __all__ = ["AIRouter", "GodModeRouter", "get_router", "classify_task", "get_provider_order"]
backend/ai_router/key_pool.py ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ KeyPool — Multi-API Key Manager with Failover & Cooldown
3
+ God Agent OS v8 — Supports Gemini, SambaNova, GitHub, OpenAI, Groq, etc.
4
+ Each provider can have multiple comma-separated keys.
5
+ """
6
+
7
+ import asyncio
8
+ import time
9
+ from collections import defaultdict
10
+ from typing import Dict, List, Optional
11
+ import structlog
12
+
13
+ log = structlog.get_logger()
14
+
15
+ COOLDOWN_SECONDS = 60 # Key cooling time after max failures
16
+ MAX_FAILURES = 3 # Max fails before cooldown
17
+
18
+
19
+ class KeyEntry:
20
+ def __init__(self, key: str):
21
+ self.key = key
22
+ self.failures = 0
23
+ self.cooldown_until = 0.0
24
+ self.calls = 0
25
+ self.last_used = 0.0
26
+
27
+ def is_available(self) -> bool:
28
+ if self.cooldown_until > time.time():
29
+ return False
30
+ return True
31
+
32
+ def mark_fail(self):
33
+ self.failures += 1
34
+ if self.failures >= MAX_FAILURES:
35
+ self.cooldown_until = time.time() + COOLDOWN_SECONDS
36
+ log.warning("Key cooldown activated", failures=self.failures)
37
+
38
+ def mark_success(self):
39
+ self.failures = max(0, self.failures - 1)
40
+ self.cooldown_until = 0.0
41
+ self.calls += 1
42
+ self.last_used = time.time()
43
+
44
+ def status(self) -> dict:
45
+ remaining = max(0, self.cooldown_until - time.time())
46
+ return {
47
+ "key_preview": self.key[:8] + "..." + self.key[-4:] if len(self.key) > 12 else "***",
48
+ "available": self.is_available(),
49
+ "failures": self.failures,
50
+ "calls": self.calls,
51
+ "cooldown_remaining_s": round(remaining, 1),
52
+ }
53
+
54
+
55
+ class KeyPool:
56
+ """
57
+ Pool of API keys for a single provider.
58
+ Round-robins through available keys with failure tracking.
59
+ """
60
+
61
+ def __init__(self, provider: str, keys: List[str]):
62
+ self.provider = provider
63
+ self._keys: List[KeyEntry] = [KeyEntry(k.strip()) for k in keys if k.strip()]
64
+ self._index = 0
65
+
66
+ def __len__(self) -> int:
67
+ return len(self._keys)
68
+
69
+ def pick(self) -> Optional[str]:
70
+ """Pick the next available key (round-robin, skip cooling down keys)."""
71
+ if not self._keys:
72
+ return None
73
+ n = len(self._keys)
74
+ for _ in range(n):
75
+ entry = self._keys[self._index % n]
76
+ self._index = (self._index + 1) % n
77
+ if entry.is_available():
78
+ return entry.key
79
+ # All keys in cooldown — try the one with shortest cooldown
80
+ soonest = min(self._keys, key=lambda e: e.cooldown_until)
81
+ log.warning(
82
+ "All keys in cooldown, using soonest",
83
+ provider=self.provider,
84
+ cooldown_remaining=round(soonest.cooldown_until - time.time(), 1),
85
+ )
86
+ return soonest.key
87
+
88
+ def mark_fail(self, key: str):
89
+ for e in self._keys:
90
+ if e.key == key:
91
+ e.mark_fail()
92
+ return
93
+
94
+ def mark_success(self, key: str):
95
+ for e in self._keys:
96
+ if e.key == key:
97
+ e.mark_success()
98
+ return
99
+
100
+ def available_count(self) -> int:
101
+ return sum(1 for e in self._keys if e.is_available())
102
+
103
+ def status(self) -> dict:
104
+ return {
105
+ "provider": self.provider,
106
+ "total_keys": len(self._keys),
107
+ "available_keys": self.available_count(),
108
+ "keys": [e.status() for e in self._keys],
109
+ }
110
+
111
+
112
+ # ─── Global Key Pool Registry ─────────────────────────────────────────────────
113
+
114
+ class KeyPoolRegistry:
115
+ """Central registry for all provider key pools."""
116
+
117
+ def __init__(self):
118
+ self._pools: Dict[str, KeyPool] = {}
119
+
120
+ def register(self, provider: str, keys_csv: str):
121
+ """Register comma-separated keys for a provider."""
122
+ keys = [k.strip() for k in keys_csv.split(",") if k.strip()]
123
+ if keys:
124
+ self._pools[provider] = KeyPool(provider, keys)
125
+ log.info("KeyPool registered", provider=provider, count=len(keys))
126
+
127
+ def get(self, provider: str) -> Optional[KeyPool]:
128
+ return self._pools.get(provider)
129
+
130
+ def all_status(self) -> dict:
131
+ return {name: pool.status() for name, pool in self._pools.items()}
backend/ai_router/router_v8.py ADDED
@@ -0,0 +1,308 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ GOD AGENT OS — Multi-Provider AI Router v8
3
+ Primary Providers (in rotation): Gemini -> Sambanova -> GitHub Models
4
+ Task-aware routing with key pool management, failover, and streaming.
5
+ """
6
+
7
+ import asyncio
8
+ import json
9
+ import os
10
+ import time
11
+ from typing import Any, Dict, List, Optional, Tuple
12
+
13
+ import httpx
14
+ import structlog
15
+
16
+ log = structlog.get_logger()
17
+
18
+ # ─── Provider Definitions ─────────────────────────────────────────────────────
19
+
20
+ PROVIDERS = {
21
+ "gemini": {
22
+ "name": "gemini",
23
+ "type": "gemini",
24
+ "base_url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent",
25
+ "key_env": "GEMINI_KEY",
26
+ "default_model": "gemini-2.0-flash",
27
+ "max_tokens": 8192,
28
+ "priority_tasks": ["language", "research", "content", "general"],
29
+ },
30
+ "sambanova": {
31
+ "name": "sambanova",
32
+ "type": "openai",
33
+ "base_url": "https://api.sambanova.ai/v1",
34
+ "key_env": "SAMBANOVA_KEY",
35
+ "default_model": "Meta-Llama-3.3-70B-Instruct",
36
+ "max_tokens": 8192,
37
+ "priority_tasks": ["reasoning", "engineering", "planning", "analysis"],
38
+ },
39
+ "github": {
40
+ "name": "github",
41
+ "type": "openai",
42
+ "base_url": "https://models.inference.ai.azure.com",
43
+ "key_env": "GITHUB_KEY",
44
+ "default_model": "gpt-4o",
45
+ "max_tokens": 4096,
46
+ "priority_tasks": ["planning", "engineering", "general"],
47
+ },
48
+ "groq": {
49
+ "name": "groq",
50
+ "type": "openai",
51
+ "base_url": "https://api.groq.com/openai/v1",
52
+ "key_env": "GROQ_API_KEY",
53
+ "default_model": "llama-3.3-70b-versatile",
54
+ "max_tokens": 8192,
55
+ "priority_tasks": ["general"],
56
+ },
57
+ "openai": {
58
+ "name": "openai",
59
+ "type": "openai",
60
+ "base_url": "https://api.openai.com/v1",
61
+ "key_env": "OPENAI_API_KEY",
62
+ "default_model": "gpt-4o",
63
+ "max_tokens": 4096,
64
+ "priority_tasks": ["general"],
65
+ },
66
+ }
67
+
68
+ PRIMARY_ORDER = ["gemini", "sambanova", "github"]
69
+ FALLBACK_ORDER = ["groq", "openai"]
70
+
71
+ MAX_RETRIES_PER_KEY = 2
72
+ KEY_COOLDOWN_SECONDS = 300
73
+ KEY_MAX_FAILS = 3
74
+
75
+
76
+ class KeyPool:
77
+ """Manages a pool of API keys with fail tracking and cooldowns."""
78
+
79
+ def __init__(self, raw_keys: str):
80
+ self._keys: List[Dict] = []
81
+ for k in raw_keys.split(","):
82
+ k = k.strip()
83
+ if k:
84
+ self._keys.append({"key": k, "fails": 0, "cooldown_until": 0.0})
85
+
86
+ def pick(self) -> Optional[Dict]:
87
+ now = time.time()
88
+ available = [k for k in self._keys if k["cooldown_until"] < now]
89
+ if not available:
90
+ return None
91
+ available.sort(key=lambda x: x["fails"])
92
+ return available[0]
93
+
94
+ def mark_fail(self, key_obj: Dict):
95
+ key_obj["fails"] += 1
96
+ if key_obj["fails"] >= KEY_MAX_FAILS:
97
+ key_obj["cooldown_until"] = time.time() + KEY_COOLDOWN_SECONDS
98
+ log.warning("Key cooled down", key_prefix=key_obj["key"][:8])
99
+
100
+ def mark_success(self, key_obj: Dict):
101
+ key_obj["fails"] = 0
102
+ key_obj["cooldown_until"] = 0.0
103
+
104
+ def has_keys(self) -> bool:
105
+ return len(self._keys) > 0
106
+
107
+ def count(self) -> int:
108
+ return len(self._keys)
109
+
110
+
111
+ def classify_task(prompt: str = "") -> str:
112
+ p = prompt.lower()
113
+ if any(w in p for w in ["code", "function", "implement", "build", "develop", "api", "class", "debug"]):
114
+ return "engineering"
115
+ if any(w in p for w in ["plan", "strategy", "workflow", "json", "automate", "pipeline"]):
116
+ return "planning"
117
+ if any(w in p for w in ["analyze", "reasoning", "why", "explain", "evaluate", "compare"]):
118
+ return "reasoning"
119
+ if any(w in p for w in ["research", "find", "search", "discover", "investigate"]):
120
+ return "research"
121
+ if any(w in p for w in ["write", "content", "blog", "article", "copy", "generate text", "summarize"]):
122
+ return "content"
123
+ if any(w in p for w in ["translate", "language", "convert"]):
124
+ return "language"
125
+ if any(w in p for w in ["data", "csv", "metrics", "report", "insight"]):
126
+ return "analysis"
127
+ return "general"
128
+
129
+
130
+ def get_provider_order(task_type: str) -> List[str]:
131
+ ordered = sorted(PRIMARY_ORDER, key=lambda p: (
132
+ 0 if task_type in PROVIDERS[p]["priority_tasks"] else 1
133
+ ))
134
+ return ordered + [f for f in FALLBACK_ORDER if os.environ.get(PROVIDERS[f]["key_env"], "")]
135
+
136
+
137
+ async def call_gemini(base_url: str, key: str, messages: List[Dict], max_tokens: int) -> Tuple[bool, str]:
138
+ url = f"{base_url}?key={key}"
139
+ parts = []
140
+ for msg in messages:
141
+ parts.append({"text": msg.get("content", "")})
142
+ body = {
143
+ "contents": [{"parts": parts}],
144
+ "generationConfig": {"maxOutputTokens": max_tokens, "temperature": 0.7},
145
+ }
146
+ try:
147
+ async with httpx.AsyncClient(timeout=60.0) as client:
148
+ resp = await client.post(url, json=body)
149
+ if resp.status_code == 200:
150
+ data = resp.json()
151
+ text = data.get("candidates", [{}])[0].get("content", {}).get("parts", [{}])[0].get("text", "")
152
+ return True, text
153
+ else:
154
+ return False, f"HTTP {resp.status_code}: {resp.text[:200]}"
155
+ except Exception as e:
156
+ return False, str(e)
157
+
158
+
159
+ async def call_openai_compat(base_url: str, key: str, model: str, messages: List[Dict], max_tokens: int) -> Tuple[bool, str]:
160
+ url = f"{base_url}/chat/completions"
161
+ headers = {"Authorization": f"Bearer {key}", "Content-Type": "application/json"}
162
+ body = {"model": model, "messages": messages, "max_tokens": max_tokens, "temperature": 0.7}
163
+ try:
164
+ async with httpx.AsyncClient(timeout=60.0) as client:
165
+ resp = await client.post(url, json=body, headers=headers)
166
+ if resp.status_code == 200:
167
+ data = resp.json()
168
+ text = data["choices"][0]["message"]["content"]
169
+ return True, text
170
+ else:
171
+ return False, f"HTTP {resp.status_code}: {resp.text[:200]}"
172
+ except Exception as e:
173
+ return False, str(e)
174
+
175
+
176
+ class GodModeRouter:
177
+ """
178
+ Task-aware multi-provider AI router.
179
+ Primary: Gemini, Sambanova, GitHub Models
180
+ Fallback: Groq, OpenAI
181
+ """
182
+
183
+ def __init__(self, ws_manager=None):
184
+ self.ws = ws_manager
185
+ self._pools: Dict[str, KeyPool] = {}
186
+ self._stats: Dict[str, Dict] = {name: {"calls": 0, "errors": 0, "latency_ms": []} for name in PROVIDERS}
187
+ self._load_pools()
188
+
189
+ def _load_pools(self):
190
+ for name, cfg in PROVIDERS.items():
191
+ raw = os.environ.get(cfg["key_env"], "")
192
+ if raw:
193
+ self._pools[name] = KeyPool(raw)
194
+ log.info("Key pool loaded", provider=name, key_count=self._pools[name].count())
195
+
196
+ def reload_pools(self):
197
+ self._pools.clear()
198
+ self._load_pools()
199
+
200
+ def get_status(self) -> Dict[str, Any]:
201
+ return {
202
+ "providers": {
203
+ name: {
204
+ "available": name in self._pools and self._pools[name].has_keys(),
205
+ "keys": self._pools[name].count() if name in self._pools else 0,
206
+ "stats": self._stats.get(name, {}),
207
+ }
208
+ for name in PROVIDERS
209
+ },
210
+ "primary_order": PRIMARY_ORDER,
211
+ }
212
+
213
+ # Keep backwards compatibility with old AIRouter interface
214
+ def get_stats(self) -> Dict[str, Any]:
215
+ return {
216
+ name: {"available": name in self._pools, "calls": self._stats[name]["calls"]}
217
+ for name in PROVIDERS
218
+ }
219
+
220
+ async def complete(
221
+ self,
222
+ messages: List[Dict],
223
+ task_id: str = "",
224
+ session_id: str = "",
225
+ temperature: float = 0.7,
226
+ max_tokens: int = 4096,
227
+ preferred_provider: str = "",
228
+ stream: bool = False,
229
+ ) -> str:
230
+ user_msg = next((m.get("content", "") for m in reversed(messages) if m.get("role") == "user"), "")
231
+ task_type = classify_task(user_msg)
232
+
233
+ if preferred_provider and preferred_provider in PROVIDERS:
234
+ order = [preferred_provider] + [p for p in get_provider_order(task_type) if p != preferred_provider]
235
+ else:
236
+ order = get_provider_order(task_type)
237
+
238
+ log.info("Routing request", task_type=task_type, order=order[:3], task_id=task_id)
239
+
240
+ last_error = "No providers available"
241
+
242
+ for provider_name in order:
243
+ if provider_name not in self._pools:
244
+ continue
245
+
246
+ pool = self._pools[provider_name]
247
+ cfg = PROVIDERS[provider_name]
248
+
249
+ for attempt in range(MAX_RETRIES_PER_KEY):
250
+ key_obj = pool.pick()
251
+ if key_obj is None:
252
+ break
253
+
254
+ t0 = time.time()
255
+ try:
256
+ if cfg["type"] == "gemini":
257
+ ok, text = await call_gemini(cfg["base_url"], key_obj["key"], messages, max_tokens)
258
+ else:
259
+ ok, text = await call_openai_compat(
260
+ cfg["base_url"], key_obj["key"],
261
+ cfg["default_model"], messages, max_tokens
262
+ )
263
+
264
+ elapsed = int((time.time() - t0) * 1000)
265
+
266
+ if ok and text.strip():
267
+ pool.mark_success(key_obj)
268
+ self._stats[provider_name]["calls"] += 1
269
+ self._stats[provider_name]["latency_ms"].append(elapsed)
270
+ log.info("LLM success", provider=provider_name, ms=elapsed, task_id=task_id)
271
+ return text
272
+ else:
273
+ pool.mark_fail(key_obj)
274
+ last_error = text
275
+ log.warning("LLM fail", provider=provider_name, error=text[:80])
276
+
277
+ except Exception as e:
278
+ pool.mark_fail(key_obj)
279
+ last_error = str(e)
280
+ self._stats[provider_name]["errors"] += 1
281
+ log.error("LLM exception", provider=provider_name, error=str(e)[:120])
282
+
283
+ log.error("All providers failed, using demo response", last_error=last_error)
284
+ return await self._demo_response(messages, task_type)
285
+
286
+ async def _demo_response(self, messages: List[Dict], task_type: str) -> str:
287
+ user_msg = next((m.get("content", "") for m in reversed(messages) if m.get("role") == "user"), "Hello")
288
+ return (
289
+ f"[GOD AGENT OS — Demo Mode]\n\n"
290
+ f"Task type detected: {task_type}\n"
291
+ f"Your request: '{user_msg[:100]}'\n\n"
292
+ f"Configure API keys in environment:\n"
293
+ f"GEMINI_KEY, SAMBANOVA_KEY, GITHUB_KEY"
294
+ )
295
+
296
+
297
+ _router_instance: Optional[GodModeRouter] = None
298
+
299
+
300
+ def get_router(ws_manager=None) -> GodModeRouter:
301
+ global _router_instance
302
+ if _router_instance is None:
303
+ _router_instance = GodModeRouter(ws_manager)
304
+ return _router_instance
305
+
306
+
307
+ # Backwards compat alias
308
+ AIRouterV8 = GodModeRouter
backend/main.py CHANGED
@@ -1,9 +1,31 @@
1
  """
2
- 🚀 GOD MODE+ Autonomous AI Operating System
3
- Devin + Manus + Genspark StyleProduction-Grade Backend
4
- Version: 3.0.0 Full God Mode Upgrade
5
  """
6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  import asyncio
8
  import json
9
  import logging
@@ -30,6 +52,7 @@ from memory.db import init_db
30
 
31
  # ─── God Mode Agents ───────────────────────────────────────────────────────────
32
  from ai_router.router import AIRouter
 
33
  from agents.orchestrator import GodAgentOrchestrator
34
  from agents.chat_agent import ChatAgent
35
  from agents.planner_agent import PlannerAgent
@@ -61,6 +84,7 @@ limiter = Limiter(key_func=get_remote_address)
61
  ws_manager = WebSocketManager()
62
  task_engine = TaskEngine(ws_manager)
63
  ai_router = AIRouter(ws_manager)
 
64
  connector_manager = ConnectorManager()
65
 
66
  # ─── Build God Agent Ecosystem ────────────────────────────────────────────────
@@ -94,7 +118,7 @@ async def lifespan(app: FastAPI):
94
  asyncio.create_task(ws_manager.heartbeat_loop())
95
  log.info("✅ GOD MODE+ Platform ready — All agents online")
96
  log.info("🤖 Agents: Chat, Planner, Coding, Debug, Memory, Connector, Deploy, Workflow, Sandbox, UI")
97
- log.info("🌐 AI Router: OpenAIGroqCerebras OpenRouter → Anthropic")
98
  yield
99
  log.info("🛑 Shutting down...")
100
  await task_engine.stop()
 
1
  """
2
+ 🚀 GOD AGENT OS — Autonomous AI Operating System v8
3
+ Gemini + Sambanova + GitHub ModelsPrimary Provider Rotation
4
+ Task-aware routing: research→Gemini, code→Sambanova, plan→GitHub
5
  """
6
 
7
+ # ─── Inject bundled API keys (env vars take precedence) ───────────────────────
8
+ import os as _os
9
+
10
+ def _inject_key(env_var: str, value: str):
11
+ """Set env var only if not already configured."""
12
+ if not _os.environ.get(env_var):
13
+ _os.environ[env_var] = value
14
+
15
+ # Keys are loaded from HF Space Secrets / Docker env vars.
16
+ # Set GEMINI_KEY, SAMBANOVA_KEY, GITHUB_KEY as comma-separated lists.
17
+ # Fallback: read from .env.keys file if present (not committed to git).
18
+ _keys_file = _os.path.join(_os.path.dirname(__file__), ".env.keys")
19
+ if _os.path.exists(_keys_file):
20
+ with open(_keys_file) as _f:
21
+ for _line in _f:
22
+ _line = _line.strip()
23
+ if _line and "=" in _line and not _line.startswith("#"):
24
+ _k, _v = _line.split("=", 1)
25
+ _inject_key(_k.strip(), _v.strip())
26
+ # ─────────────────────────────────────────────────────────────────────────────
27
+
28
+
29
  import asyncio
30
  import json
31
  import logging
 
52
 
53
  # ─── God Mode Agents ───────────────────────────────────────────────────────────
54
  from ai_router.router import AIRouter
55
+ from ai_router.router_v8 import GodModeRouter, get_router as get_god_router
56
  from agents.orchestrator import GodAgentOrchestrator
57
  from agents.chat_agent import ChatAgent
58
  from agents.planner_agent import PlannerAgent
 
84
  ws_manager = WebSocketManager()
85
  task_engine = TaskEngine(ws_manager)
86
  ai_router = AIRouter(ws_manager)
87
+ god_router = get_god_router(ws_manager) # v8 primary router
88
  connector_manager = ConnectorManager()
89
 
90
  # ─── Build God Agent Ecosystem ────────────────────────────────────────────────
 
118
  asyncio.create_task(ws_manager.heartbeat_loop())
119
  log.info("✅ GOD MODE+ Platform ready — All agents online")
120
  log.info("🤖 Agents: Chat, Planner, Coding, Debug, Memory, Connector, Deploy, Workflow, Sandbox, UI")
121
+ log.info("🌐 AI Router v8: GeminiSambanovaGitHub Models (task-aware rotation)")
122
  yield
123
  log.info("🛑 Shutting down...")
124
  await task_engine.stop()
backend/main_v8.py ADDED
@@ -0,0 +1,326 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ 🚀 GOD AGENT OS v8 — Autonomous Engineering Operating System
3
+ Manus + Genspark + Devin (OneHand) Combined
4
+ Version: 8.0.0 — KeyPool Multi-API Routing (Gemini + SambaNova Primary LLMs)
5
+ """
6
+
7
+ import asyncio
8
+ import json
9
+ import os
10
+ import time
11
+ import uuid
12
+ from contextlib import asynccontextmanager
13
+ from typing import Optional
14
+
15
+ import structlog
16
+ from fastapi import FastAPI, WebSocket, WebSocketDisconnect, HTTPException, Request
17
+ from fastapi.middleware.cors import CORSMiddleware
18
+ from fastapi.middleware.gzip import GZipMiddleware
19
+ from fastapi.responses import JSONResponse
20
+ from slowapi import Limiter, _rate_limit_exceeded_handler
21
+ from slowapi.util import get_remote_address
22
+ from slowapi.errors import RateLimitExceeded
23
+
24
+ from api.routes import tasks, chat, memory, github, health
25
+ from api.routes import connectors, agents as agents_router
26
+ from api.websocket_manager import WebSocketManager
27
+ from core.task_engine import TaskEngine
28
+ from memory.db import init_db
29
+
30
+ # ─── v8 AI Router (KeyPool-based) ─────────────────────────────────────────────
31
+ from ai_router.router_v8 import AIRouterV8
32
+
33
+ # ─── Agent Ecosystem ──────────────────────────────────────────────────────────
34
+ from agents.orchestrator_v7 import GodAgentOrchestratorV7
35
+ from agents.chat_agent import ChatAgent
36
+ from agents.planner_agent import PlannerAgent
37
+ from agents.coding_agent import CodingAgent
38
+ from agents.debug_agent import DebugAgent
39
+ from agents.memory_agent import MemoryAgent
40
+ from agents.connector_agent import ConnectorAgent
41
+ from agents.deploy_agent import DeployAgent
42
+ from agents.workflow_agent import WorkflowAgent
43
+ from agents.sandbox_agent import SandboxAgent
44
+ from agents.ui_agent import UIAgent
45
+ from agents.reasoning_agent import ReasoningAgent
46
+ from agents.browser_agent import BrowserAgent
47
+ from agents.file_agent import FileAgent
48
+ from agents.git_agent import GitAgent
49
+ from agents.test_agent import TestAgent
50
+ from agents.vision_agent import VisionAgent
51
+ from connectors.manager import ConnectorManager
52
+
53
+ # ─── Structured Logging ───────────────────────────────────────────────────────
54
+ structlog.configure(
55
+ processors=[
56
+ structlog.processors.TimeStamper(fmt="iso"),
57
+ structlog.stdlib.add_log_level,
58
+ structlog.processors.StackInfoRenderer(),
59
+ structlog.dev.ConsoleRenderer(),
60
+ ]
61
+ )
62
+ log = structlog.get_logger()
63
+
64
+ limiter = Limiter(key_func=get_remote_address)
65
+
66
+ # ─── Global Managers ──────────────────────────────────────────────────────────
67
+ ws_manager = WebSocketManager()
68
+ task_engine = TaskEngine(ws_manager)
69
+ ai_router = AIRouterV8(ws_manager)
70
+ connector_manager = ConnectorManager()
71
+
72
+
73
+ def build_orchestrator() -> GodAgentOrchestratorV7:
74
+ orchestrator = GodAgentOrchestratorV7(ws_manager=ws_manager, ai_router=ai_router)
75
+ orchestrator.register_agent("chat", ChatAgent(ws_manager, ai_router))
76
+ orchestrator.register_agent("planner", PlannerAgent(ws_manager, ai_router))
77
+ orchestrator.register_agent("coding", CodingAgent(ws_manager, ai_router))
78
+ orchestrator.register_agent("debug", DebugAgent(ws_manager, ai_router))
79
+ orchestrator.register_agent("memory", MemoryAgent(ws_manager, ai_router))
80
+ orchestrator.register_agent("connector", ConnectorAgent(ws_manager, ai_router))
81
+ orchestrator.register_agent("deploy", DeployAgent(ws_manager, ai_router))
82
+ orchestrator.register_agent("workflow", WorkflowAgent(ws_manager, ai_router))
83
+ orchestrator.register_agent("sandbox", SandboxAgent(ws_manager, ai_router))
84
+ orchestrator.register_agent("ui", UIAgent(ws_manager, ai_router))
85
+ orchestrator.register_agent("reasoning", ReasoningAgent(ws_manager, ai_router))
86
+ orchestrator.register_agent("browser", BrowserAgent(ws_manager, ai_router))
87
+ orchestrator.register_agent("file", FileAgent(ws_manager, ai_router))
88
+ orchestrator.register_agent("git", GitAgent(ws_manager, ai_router))
89
+ orchestrator.register_agent("test", TestAgent(ws_manager, ai_router))
90
+ orchestrator.register_agent("vision", VisionAgent(ws_manager, ai_router))
91
+ log.info("🤖 GOD AGENT v8 Ecosystem initialized", agents=16)
92
+ return orchestrator
93
+
94
+
95
+ orchestrator = build_orchestrator()
96
+
97
+
98
+ @asynccontextmanager
99
+ async def lifespan(app: FastAPI):
100
+ log.info("🚀 Starting GOD AGENT OS v8 — KeyPool Multi-API Edition...")
101
+ await init_db()
102
+ await task_engine.start()
103
+ asyncio.create_task(ws_manager.heartbeat_loop())
104
+ # Print router status
105
+ stats = ai_router.get_stats()
106
+ active = [name for name, s in stats.items() if s["available"]]
107
+ log.info("✅ GOD AGENT v8 — 16 agents online")
108
+ log.info(f"🔑 Active AI providers: {active}")
109
+ log.info("🌐 AI Routing: SambaNova → Gemini → OpenAI → Groq → Cerebras → OpenRouter → Anthropic")
110
+ yield
111
+ log.info("🛑 Shutting down GOD AGENT v8...")
112
+ await task_engine.stop()
113
+
114
+
115
+ app = FastAPI(
116
+ title="🤖 GOD AGENT OS v8",
117
+ description="Autonomous Engineering OS — Gemini + SambaNova KeyPool Multi-API Routing",
118
+ version="8.0.0",
119
+ lifespan=lifespan,
120
+ docs_url="/api/docs",
121
+ redoc_url="/api/redoc",
122
+ )
123
+
124
+ app.state.limiter = limiter
125
+ app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
126
+ app.state.ws_manager = ws_manager
127
+ app.state.task_engine = task_engine
128
+ app.state.ai_router = ai_router
129
+ app.state.orchestrator = orchestrator
130
+ app.state.connector_manager = connector_manager
131
+
132
+ app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"])
133
+ app.add_middleware(GZipMiddleware, minimum_size=1000)
134
+
135
+
136
+ @app.middleware("http")
137
+ async def log_requests(request: Request, call_next):
138
+ start = time.time()
139
+ response = await call_next(request)
140
+ ms = round((time.time() - start) * 1000, 2)
141
+ log.info("HTTP", method=request.method, path=request.url.path, status=response.status_code, ms=ms)
142
+ return response
143
+
144
+
145
+ # ─── REST Routers ─────────────────────────────────────────────────────────────
146
+ app.include_router(health.router, prefix="/api/v1", tags=["health"])
147
+ app.include_router(tasks.router, prefix="/api/v1/tasks", tags=["tasks"])
148
+ app.include_router(chat.router, prefix="/api/v1", tags=["chat"])
149
+ app.include_router(memory.router, prefix="/api/v1/memory", tags=["memory"])
150
+ app.include_router(github.router, prefix="/api/v1/github", tags=["github"])
151
+ app.include_router(connectors.router, prefix="/api/v1/connectors", tags=["connectors"])
152
+ app.include_router(agents_router.router, prefix="/api/v1/agents", tags=["agents"])
153
+
154
+
155
+ # ─── WebSocket Endpoints ──────────────────────────────────────────────────────
156
+ @app.websocket("/ws/tasks/{task_id}")
157
+ async def ws_task(websocket: WebSocket, task_id: str):
158
+ await ws_manager.connect(websocket, room=f"task:{task_id}")
159
+ try:
160
+ while True:
161
+ data = await websocket.receive_text()
162
+ msg = json.loads(data)
163
+ if msg.get("type") == "ping":
164
+ await websocket.send_json({"type": "pong", "timestamp": time.time()})
165
+ except WebSocketDisconnect:
166
+ ws_manager.disconnect(websocket, room=f"task:{task_id}")
167
+
168
+
169
+ @app.websocket("/ws/logs")
170
+ async def ws_logs(websocket: WebSocket):
171
+ await ws_manager.connect(websocket, room="logs")
172
+ try:
173
+ while True:
174
+ data = await websocket.receive_text()
175
+ msg = json.loads(data)
176
+ if msg.get("type") == "ping":
177
+ await websocket.send_json({"type": "pong", "timestamp": time.time()})
178
+ except WebSocketDisconnect:
179
+ ws_manager.disconnect(websocket, room="logs")
180
+
181
+
182
+ @app.websocket("/ws/chat/{session_id}")
183
+ async def ws_chat(websocket: WebSocket, session_id: str):
184
+ await ws_manager.connect(websocket, room=f"chat:{session_id}")
185
+ try:
186
+ while True:
187
+ data = await websocket.receive_text()
188
+ msg = json.loads(data)
189
+ if msg.get("type") == "ping":
190
+ await websocket.send_json({"type": "pong", "timestamp": time.time()})
191
+ elif msg.get("type") == "chat_message":
192
+ asyncio.create_task(orchestrator.orchestrate(
193
+ user_message=msg.get("content", ""),
194
+ session_id=session_id,
195
+ context=msg.get("context", {}),
196
+ ))
197
+ elif msg.get("type") == "task_message":
198
+ from core.models import TaskCreateRequest
199
+ req = TaskCreateRequest(goal=msg.get("content", ""), session_id=session_id)
200
+ asyncio.create_task(task_engine.submit(req))
201
+ except WebSocketDisconnect:
202
+ ws_manager.disconnect(websocket, room=f"chat:{session_id}")
203
+
204
+
205
+ @app.websocket("/ws/agent/status")
206
+ async def ws_agent_status(websocket: WebSocket):
207
+ await ws_manager.connect(websocket, room="agent_status")
208
+ try:
209
+ while True:
210
+ data = await websocket.receive_text()
211
+ msg = json.loads(data)
212
+ if msg.get("type") == "ping":
213
+ await websocket.send_json({"type": "pong", "timestamp": time.time()})
214
+ elif msg.get("type") == "get_status":
215
+ await websocket.send_json({"type": "agent_status", "data": orchestrator.get_status()})
216
+ except WebSocketDisconnect:
217
+ ws_manager.disconnect(websocket, room="agent_status")
218
+
219
+
220
+ @app.websocket("/ws/sandbox/{session_id}")
221
+ async def ws_sandbox(websocket: WebSocket, session_id: str):
222
+ await ws_manager.connect(websocket, room=f"sandbox:{session_id}")
223
+ sandbox = orchestrator.get_agent("sandbox")
224
+ try:
225
+ while True:
226
+ data = await websocket.receive_text()
227
+ msg = json.loads(data)
228
+ if msg.get("type") == "ping":
229
+ await websocket.send_json({"type": "pong", "timestamp": time.time()})
230
+ elif msg.get("type") == "execute" and sandbox:
231
+ cmd = msg.get("command", "")
232
+ result = await sandbox.execute(cmd, session_id=session_id)
233
+ await websocket.send_json({"type": "terminal_output", "command": cmd, "output": result, "timestamp": time.time()})
234
+ except WebSocketDisconnect:
235
+ ws_manager.disconnect(websocket, room=f"sandbox:{session_id}")
236
+
237
+
238
+ # ─── v8 Key Pool & AI Router Status Endpoints ─────────────────────────────────
239
+ @app.get("/api/v1/ai/stats")
240
+ async def get_ai_stats():
241
+ return {"stats": ai_router.get_stats()}
242
+
243
+
244
+ @app.get("/api/v1/ai/pool-status")
245
+ async def get_pool_status():
246
+ return {"pools": ai_router.get_pool_status()}
247
+
248
+
249
+ @app.post("/api/v1/browser/research")
250
+ async def browser_research(request: Request):
251
+ body = await request.json()
252
+ browser = orchestrator.get_agent("browser")
253
+ if not browser:
254
+ raise HTTPException(status_code=503, detail="BrowserAgent not available")
255
+ result = await browser.run(body.get("query", ""), session_id=body.get("session_id", ""))
256
+ return {"result": result}
257
+
258
+
259
+ @app.get("/api/v1/files/workspace")
260
+ async def list_workspace():
261
+ file_agent = orchestrator.get_agent("file")
262
+ if not file_agent:
263
+ return {"workspace": "/tmp/god_workspace", "files": [], "total": 0}
264
+ return file_agent.list_workspace()
265
+
266
+
267
+ @app.post("/api/v1/git/pr")
268
+ async def create_pr(request: Request):
269
+ body = await request.json()
270
+ git_agent = orchestrator.get_agent("git")
271
+ if not git_agent:
272
+ raise HTTPException(status_code=503, detail="GitAgent not available")
273
+ result = await git_agent.create_github_pr(
274
+ repo_owner=body.get("owner", ""),
275
+ repo_name=body.get("repo", ""),
276
+ title=body.get("title", ""),
277
+ body=body.get("body", ""),
278
+ head_branch=body.get("head_branch", "main"),
279
+ base_branch=body.get("base_branch", "main"),
280
+ )
281
+ return result
282
+
283
+
284
+ @app.post("/api/v1/vision/generate")
285
+ async def generate_ui(request: Request):
286
+ body = await request.json()
287
+ vision = orchestrator.get_agent("vision")
288
+ if not vision:
289
+ raise HTTPException(status_code=503, detail="VisionAgent not available")
290
+ result = await vision.run(body.get("prompt", ""), context=body.get("context", {}), session_id=body.get("session_id", ""))
291
+ return {"result": result}
292
+
293
+
294
+ # ─── Root ─────────────────────────────────────────────────────────────────────
295
+ @app.get("/")
296
+ async def root():
297
+ cs = connector_manager.get_summary()
298
+ status = orchestrator.get_status()
299
+ stats = ai_router.get_stats()
300
+ active_providers = [name for name, s in stats.items() if s["available"]]
301
+ return {
302
+ "name": "🤖 GOD AGENT OS v8",
303
+ "version": "8.0.0",
304
+ "status": "operational",
305
+ "mode": "autonomous_engineering_os",
306
+ "description": "KeyPool Multi-API Routing — Gemini + SambaNova Primary LLMs",
307
+ "agents": status["agents"],
308
+ "total_agents": status["total_agents"],
309
+ "ai_providers": active_providers,
310
+ "connectors": {"connected": cs["connected"], "total": cs["total"]},
311
+ "docs": "/api/docs",
312
+ "v8_features": [
313
+ "🔑 KeyPool multi-key management (Gemini 6 keys + SambaNova 9 keys)",
314
+ "🔄 Automatic key failover with cooldown tracking",
315
+ "⚡ SambaNova → Gemini → OpenAI → Groq → Cerebras chain",
316
+ "📊 Per-key usage stats & health monitoring",
317
+ "🤖 16-agent autonomous fleet",
318
+ "🌐 Real-time streaming via WebSocket",
319
+ ],
320
+ }
321
+
322
+
323
+ if __name__ == "__main__":
324
+ import uvicorn
325
+ port = int(os.environ.get("PORT", 8000))
326
+ uvicorn.run("main_v8:app", host="0.0.0.0", port=port, reload=False, workers=1)
frontend/app/globals.css CHANGED
@@ -2,235 +2,331 @@
2
  @tailwind components;
3
  @tailwind utilities;
4
 
5
- @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap');
 
6
 
7
- /* ─── CSS Variables / Themes ─────────────────────────────────────────────── */
8
  :root {
9
- --bg-0: #0a0b0f;
10
- --bg-1: #0f1017;
11
- --bg-2: #13141e;
12
- --bg-3: #1a1b26;
13
- --bg-4: #1e2035;
14
- --border: #2a2b3d;
15
- --text-primary: #e2e8f0;
16
- --text-secondary: #94a3b8;
17
- --text-muted: #475569;
18
- --brand: #6366f1;
19
- --brand-glow: rgba(99,102,241,0.3);
20
- }
21
-
22
- [data-theme="light"] {
23
- --bg-0: #f8fafc;
24
- --bg-1: #f1f5f9;
25
- --bg-2: #e2e8f0;
26
- --bg-3: #ffffff;
27
- --bg-4: #f8fafc;
28
- --border: #cbd5e1;
29
- --text-primary: #0f172a;
30
- --text-secondary: #475569;
31
- --text-muted: #94a3b8;
32
- --brand: #6366f1;
33
- --brand-glow: rgba(99,102,241,0.2);
34
- }
35
-
36
- [data-theme="amoled"] {
37
- --bg-0: #000000;
38
- --bg-1: #000000;
39
- --bg-2: #0a0a0a;
40
- --bg-3: #111111;
41
- --bg-4: #161616;
42
- --border: #222222;
43
- --text-primary: #ffffff;
44
- --text-secondary: #aaaaaa;
45
- --text-muted: #555555;
46
- --brand: #7c3aed;
47
- --brand-glow: rgba(124,58,237,0.4);
48
- }
49
-
50
- [data-theme="neon"] {
51
- --bg-0: #000510;
52
- --bg-1: #010a1a;
53
- --bg-2: #020d20;
54
- --bg-3: #031226;
55
- --bg-4: #04162c;
56
- --border: #0d3060;
57
- --text-primary: #e0f0ff;
58
- --text-secondary: #7ab8f5;
59
- --text-muted: #2a5a8a;
60
- --brand: #00d4ff;
61
- --brand-glow: rgba(0,212,255,0.4);
62
- }
63
-
64
- [data-theme="glass"] {
65
- --bg-0: #0d0d1a;
66
- --bg-1: #111122;
67
- --bg-2: #161630;
68
- --bg-3: rgba(255,255,255,0.04);
69
- --bg-4: rgba(255,255,255,0.06);
70
- --border: rgba(255,255,255,0.08);
71
- --text-primary: #f0f0ff;
72
- --text-secondary: #9090c0;
73
- --text-muted: #5050a0;
74
- --brand: #818cf8;
75
- --brand-glow: rgba(129,140,248,0.3);
76
- }
77
-
78
- /* ─── Base ────────────────────────────────────────────────────────────────── */
79
- * { box-sizing: border-box; }
80
-
81
- html { font-family: 'Inter', system-ui, sans-serif; }
82
 
83
  body {
84
- background: var(--bg-0);
85
  color: var(--text-primary);
86
- margin: 0;
87
- padding: 0;
88
  overflow: hidden;
89
  height: 100vh;
 
 
90
  }
91
 
92
  /* ─── Scrollbar ───────────────────────────────────────────────────────────── */
93
- ::-webkit-scrollbar { width: 4px; height: 4px; }
94
  ::-webkit-scrollbar-track { background: transparent; }
95
- ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }
96
- ::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }
97
 
98
- /* ─── Code / Mono ─────────────────────────────────────────────────────────── */
99
  code, pre, .font-mono { font-family: 'JetBrains Mono', 'Fira Code', monospace; }
100
 
101
- /* ─── Typing Indicator Dots ───────────────────────────────────────────────── */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  .typing-dot {
103
- width: 6px;
104
- height: 6px;
105
  border-radius: 50%;
106
- background: var(--brand);
107
  display: inline-block;
108
- animation: bounceDot 1.4s ease-in-out infinite;
109
  }
110
- .typing-dot:nth-child(2) { animation-delay: 0.16s; }
111
- .typing-dot:nth-child(3) { animation-delay: 0.32s; }
112
 
113
- @keyframes bounceDot {
114
- 0%, 80%, 100% { transform: scale(0); opacity: 0.3; }
115
- 40% { transform: scale(1); opacity: 1; }
 
 
 
 
 
 
 
116
  }
117
 
118
- /* ─── Glass Card ──────────────────────────────────────────────────────────── */
119
- .glass {
120
- background: var(--bg-3);
121
- backdrop-filter: blur(12px);
122
- -webkit-backdrop-filter: blur(12px);
123
- border: 1px solid var(--border);
124
  }
125
 
126
- .glass-hover:hover {
127
- background: var(--bg-4);
128
- border-color: var(--brand);
129
- }
130
-
131
- /* ─── Agent Badge Colors ──────────────────────────────────────────────────── */
132
- .agent-chat { color: #22d3ee; }
133
- .agent-planner { color: #a78bfa; }
134
- .agent-coding { color: #34d399; }
135
- .agent-debug { color: #f87171; }
136
- .agent-memory { color: #fbbf24; }
137
- .agent-connector { color: #60a5fa; }
138
- .agent-deploy { color: #f472b6; }
139
- .agent-workflow { color: #fb923c; }
140
- .agent-sandbox { color: #4ade80; }
141
- .agent-ui { color: #e879f9; }
142
-
143
- /* ─── Neon Glow ───────────────────────────────────────────────────────────── */
144
- .glow-brand { box-shadow: 0 0 12px var(--brand-glow); }
145
- .glow-green { box-shadow: 0 0 12px rgba(52,211,153,0.4); }
146
- .glow-red { box-shadow: 0 0 12px rgba(248,113,113,0.4); }
147
-
148
- /* ─── Shimmer Loader ──────────────────────────────────────────────────────── */
149
- .shimmer {
150
- background: linear-gradient(90deg, var(--bg-3) 25%, var(--bg-4) 50%, var(--bg-3) 75%);
151
- background-size: 200% 100%;
152
- animation: shimmer 1.5s infinite;
153
  }
154
 
155
- @keyframes shimmer {
156
- 0% { background-position: -200% 0; }
157
- 100% { background-position: 200% 0; }
 
 
158
  }
159
 
160
- /* ─── Status Pulse ────────────────────────────────────────────────────────── */
161
- .status-online { background: #22c55e; box-shadow: 0 0 8px rgba(34,197,94,0.6); }
162
- .status-busy { background: #f59e0b; box-shadow: 0 0 8px rgba(245,158,11,0.6); }
163
- .status-offline { background: #6b7280; }
164
- .status-error { background: #ef4444; box-shadow: 0 0 8px rgba(239,68,68,0.6); }
165
 
166
- /* ─── Markdown Prose (Dark) ───────────────────────────────────────────────── */
167
- .prose-god {
168
- color: var(--text-primary);
169
- line-height: 1.7;
 
 
 
 
170
  }
171
- .prose-god h1, .prose-god h2, .prose-god h3 {
 
 
172
  color: var(--text-primary);
173
- font-weight: 600;
174
- margin: 1em 0 0.5em;
175
- }
176
- .prose-god p { margin: 0.6em 0; }
177
- .prose-god ul { margin: 0.5em 0; padding-left: 1.4em; }
178
- .prose-god li { margin: 0.2em 0; }
179
- .prose-god a { color: var(--brand); text-decoration: none; }
180
- .prose-god a:hover { text-decoration: underline; }
181
- .prose-god strong { color: #fff; font-weight: 600; }
182
- .prose-god code {
183
- background: var(--bg-2);
184
- border: 1px solid var(--border);
185
- border-radius: 4px;
186
- padding: 1px 6px;
187
- font-size: 0.85em;
188
- font-family: 'JetBrains Mono', monospace;
189
  color: #a78bfa;
 
190
  }
191
- .prose-god pre {
192
- background: var(--bg-0) !important;
193
- border: 1px solid var(--border);
194
- border-radius: 8px;
195
- padding: 1rem;
196
- overflow-x: auto;
197
- margin: 0.8em 0;
198
- }
199
- .prose-god pre code {
200
- background: none;
201
- border: none;
202
- padding: 0;
203
- color: inherit;
204
- font-size: 0.8rem;
205
- }
206
- .prose-god table { width: 100%; border-collapse: collapse; margin: 0.8em 0; font-size: 0.85em; }
207
- .prose-god th { background: var(--bg-3); padding: 8px 12px; text-align: left; border: 1px solid var(--border); color: var(--text-secondary); }
208
- .prose-god td { padding: 6px 12px; border: 1px solid var(--border); }
209
- .prose-god tr:hover td { background: var(--bg-4); }
210
- .prose-god blockquote {
211
- border-left: 3px solid var(--brand);
212
- padding-left: 1em;
213
- margin: 0.8em 0;
214
- color: var(--text-secondary);
215
- font-style: italic;
216
  }
217
- .prose-god hr {
218
- border: none;
219
- border-top: 1px solid var(--border);
220
- margin: 1.2em 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  }
222
 
223
- /* ─── Mobile ──────────────────────────────────────────────────────────────── */
224
- @media (max-width: 768px) {
225
- body { overflow: auto; }
 
 
226
  }
227
 
228
- /* ─── Burmese Font ────────────────────────────────────────────────────────── */
229
- .font-burmese { font-family: 'Pyidaungsu', 'Myanmar Text', 'Noto Sans Myanmar', sans-serif; }
 
 
230
 
231
- /* ─── Animate in ──────────────────────────────────────────────────────────── */
232
- .animate-fade-in { animation: fadeIn 0.25s ease-out; }
233
- .animate-slide-up { animation: slideUp 0.3s ease-out; }
 
 
 
 
 
 
 
 
234
 
235
- @keyframes fadeIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } }
236
- @keyframes slideUp { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  @tailwind components;
3
  @tailwind utilities;
4
 
5
+ /* ─── Fonts ──────────────────────────────────────────────────────────────── */
6
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap');
7
 
8
+ /* ─── CSS Variables ───────────────────────────────────────────────────────── */
9
  :root {
10
+ --void: #05060d;
11
+ --surface-1: #0a0c16;
12
+ --surface-2: #0e1121;
13
+ --surface-3: #131729;
14
+ --surface-4: #191e32;
15
+ --surface-5: #1f263b;
16
+ --border: rgba(255,255,255,0.06);
17
+ --border-hover: rgba(255,255,255,0.12);
18
+ --text-primary: #e8eaf0;
19
+ --text-secondary: #8892a4;
20
+ --text-muted: #4a5568;
21
+ --purple: #7c3aed;
22
+ --purple-bright: #8b5cf6;
23
+ --purple-glow: rgba(124,58,237,0.25);
24
+ --blue: #3b82f6;
25
+ --blue-bright: #60a5fa;
26
+ --cyan: #22d3ee;
27
+ --green: #22c55e;
28
+ --amber: #f59e0b;
29
+ --pink: #ec4899;
30
+ --red: #ef4444;
31
+ }
32
+
33
+ /* ─── Base Reset ──────────────────────────────────────────────────────────── */
34
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
35
+
36
+ html { font-size: 16px; scroll-behavior: smooth; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
  body {
39
+ background: var(--void);
40
  color: var(--text-primary);
41
+ font-family: 'Inter', system-ui, -apple-system, sans-serif;
 
42
  overflow: hidden;
43
  height: 100vh;
44
+ -webkit-font-smoothing: antialiased;
45
+ -moz-osx-font-smoothing: grayscale;
46
  }
47
 
48
  /* ─── Scrollbar ───────────────────────────────────────────────────────────── */
49
+ ::-webkit-scrollbar { width: 3px; height: 3px; }
50
  ::-webkit-scrollbar-track { background: transparent; }
51
+ ::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.08); border-radius: 8px; }
52
+ ::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.15); }
53
 
54
+ /* ─── Mono Font ───────────────────────────────────────────────────────────── */
55
  code, pre, .font-mono { font-family: 'JetBrains Mono', 'Fira Code', monospace; }
56
 
57
+ /* ─── Glass Morphism ──────────────────────────────────────────────────────── */
58
+ .glass {
59
+ background: rgba(255,255,255,0.04);
60
+ backdrop-filter: blur(20px);
61
+ -webkit-backdrop-filter: blur(20px);
62
+ border: 1px solid rgba(255,255,255,0.07);
63
+ }
64
+
65
+ .glass-hover:hover {
66
+ background: rgba(255,255,255,0.06);
67
+ border-color: rgba(255,255,255,0.12);
68
+ }
69
+
70
+ .glass-purple {
71
+ background: rgba(124,58,237,0.08);
72
+ backdrop-filter: blur(20px);
73
+ border: 1px solid rgba(124,58,237,0.2);
74
+ }
75
+
76
+ .glass-card {
77
+ background: linear-gradient(135deg, rgba(255,255,255,0.05) 0%, rgba(255,255,255,0.02) 100%);
78
+ backdrop-filter: blur(24px);
79
+ border: 1px solid rgba(255,255,255,0.07);
80
+ border-radius: 16px;
81
+ }
82
+
83
+ /* ─── Neon Glows ──────────────────────────────────────────────────────────── */
84
+ .glow-purple { box-shadow: 0 0 20px rgba(124,58,237,0.3), 0 0 60px rgba(124,58,237,0.1); }
85
+ .glow-blue { box-shadow: 0 0 20px rgba(59,130,246,0.3), 0 0 60px rgba(59,130,246,0.1); }
86
+ .glow-cyan { box-shadow: 0 0 20px rgba(34,211,238,0.3), 0 0 60px rgba(34,211,238,0.1); }
87
+ .glow-green { box-shadow: 0 0 12px rgba(34,197,94,0.4); }
88
+
89
+ .text-glow-purple { text-shadow: 0 0 20px rgba(139,92,246,0.6); }
90
+ .text-glow-cyan { text-shadow: 0 0 20px rgba(34,211,238,0.6); }
91
+
92
+ /* ─── Gradient Text ───────────────────────────────────────────────────────── */
93
+ .gradient-text {
94
+ background: linear-gradient(135deg, #a78bfa 0%, #60a5fa 50%, #34d399 100%);
95
+ -webkit-background-clip: text;
96
+ -webkit-text-fill-color: transparent;
97
+ background-clip: text;
98
+ }
99
+
100
+ .gradient-text-purple {
101
+ background: linear-gradient(135deg, #c084fc 0%, #818cf8 100%);
102
+ -webkit-background-clip: text;
103
+ -webkit-text-fill-color: transparent;
104
+ background-clip: text;
105
+ }
106
+
107
+ /* ─── Animations ──────────────────────────────────────────────────────────── */
108
+ @keyframes fadeInUp {
109
+ from { opacity: 0; transform: translateY(12px); }
110
+ to { opacity: 1; transform: translateY(0); }
111
+ }
112
+
113
+ @keyframes fadeIn {
114
+ from { opacity: 0; }
115
+ to { opacity: 1; }
116
+ }
117
+
118
+ @keyframes slideInLeft {
119
+ from { opacity: 0; transform: translateX(-16px); }
120
+ to { opacity: 1; transform: translateX(0); }
121
+ }
122
+
123
+ @keyframes pulseGlow {
124
+ 0%, 100% { opacity: 0.6; }
125
+ 50% { opacity: 1; }
126
+ }
127
+
128
+ @keyframes spin {
129
+ from { transform: rotate(0deg); }
130
+ to { transform: rotate(360deg); }
131
+ }
132
+
133
+ @keyframes shimmer {
134
+ 0% { background-position: -200% center; }
135
+ 100% { background-position: 200% center; }
136
+ }
137
+
138
+ @keyframes typingDot {
139
+ 0%, 80%, 100% { transform: scale(0); opacity: 0.3; }
140
+ 40% { transform: scale(1); opacity: 1; }
141
+ }
142
+
143
+ @keyframes orbFloat {
144
+ 0%, 100% { transform: translateY(0px) rotate(0deg); }
145
+ 33% { transform: translateY(-8px) rotate(5deg); }
146
+ 66% { transform: translateY(4px) rotate(-3deg); }
147
+ }
148
+
149
+ @keyframes progressPulse {
150
+ 0%, 100% { opacity: 1; }
151
+ 50% { opacity: 0.7; }
152
+ }
153
+
154
+ .animate-fade-in-up { animation: fadeInUp 0.4s ease-out forwards; }
155
+ .animate-fade-in { animation: fadeIn 0.3s ease-out forwards; }
156
+ .animate-slide-left { animation: slideInLeft 0.3s ease-out forwards; }
157
+ .animate-pulse-glow { animation: pulseGlow 2s ease-in-out infinite; }
158
+ .animate-spin-slow { animation: spin 8s linear infinite; }
159
+ .animate-orb-float { animation: orbFloat 6s ease-in-out infinite; }
160
+ .animate-progress-pulse { animation: progressPulse 2s ease-in-out infinite; }
161
+
162
+ .shimmer-text {
163
+ background: linear-gradient(90deg, #a78bfa, #60a5fa, #34d399, #a78bfa);
164
+ background-size: 200% auto;
165
+ -webkit-background-clip: text;
166
+ -webkit-text-fill-color: transparent;
167
+ background-clip: text;
168
+ animation: shimmer 3s linear infinite;
169
+ }
170
+
171
  .typing-dot {
172
+ width: 6px; height: 6px;
173
+ background: var(--purple-bright);
174
  border-radius: 50%;
 
175
  display: inline-block;
176
+ animation: typingDot 1.4s ease-in-out infinite;
177
  }
 
 
178
 
179
+ /* ─── Cosmic Orb ──────────────────────────────────────────────────────────── */
180
+ .cosmic-orb {
181
+ width: 120px; height: 120px;
182
+ border-radius: 50%;
183
+ background: radial-gradient(circle at 30% 30%, #c084fc, #7c3aed, #3b82f6, #1e1b4b);
184
+ box-shadow:
185
+ 0 0 40px rgba(124,58,237,0.5),
186
+ 0 0 80px rgba(124,58,237,0.2),
187
+ inset 0 0 30px rgba(192,132,252,0.3);
188
+ animation: orbFloat 6s ease-in-out infinite;
189
  }
190
 
191
+ /* ─── Active Dot ──────────────────────────────────────────────────────────── */
192
+ .active-dot {
193
+ width: 8px; height: 8px; border-radius: 50%;
194
+ background: var(--green);
195
+ box-shadow: 0 0 8px rgba(34,197,94,0.6);
 
196
  }
197
 
198
+ .active-dot::after {
199
+ content: '';
200
+ position: absolute; top: -2px; left: -2px; right: -2px; bottom: -2px;
201
+ border-radius: 50%;
202
+ border: 2px solid rgba(34,197,94,0.3);
203
+ animation: pulse 2s ease-in-out infinite;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  }
205
 
206
+ /* ─── Progress Bar ────────────────────────────────────────────────────────── */
207
+ .progress-bar {
208
+ height: 4px; border-radius: 4px;
209
+ background: rgba(255,255,255,0.06);
210
+ overflow: hidden;
211
  }
212
 
213
+ .progress-fill {
214
+ height: 100%; border-radius: 4px;
215
+ transition: width 0.8s ease-out;
216
+ }
 
217
 
218
+ /* ─── Nav Item ────────────────────────────────────────────────────────────── */
219
+ .nav-item {
220
+ display: flex; align-items: center; gap: 10px;
221
+ padding: 8px 12px; border-radius: 10px;
222
+ font-size: 0.8125rem; font-weight: 500;
223
+ color: var(--text-secondary);
224
+ cursor: pointer; transition: all 0.2s ease;
225
+ position: relative;
226
  }
227
+
228
+ .nav-item:hover {
229
+ background: rgba(255,255,255,0.05);
230
  color: var(--text-primary);
231
+ }
232
+
233
+ .nav-item.active {
234
+ background: rgba(124,58,237,0.12);
 
 
 
 
 
 
 
 
 
 
 
 
235
  color: #a78bfa;
236
+ border: 1px solid rgba(124,58,237,0.2);
237
  }
238
+
239
+ .nav-item.active::before {
240
+ content: '';
241
+ position: absolute; left: 0; top: 50%;
242
+ transform: translateY(-50%);
243
+ width: 3px; height: 60%; min-height: 16px;
244
+ background: linear-gradient(180deg, #a78bfa, #7c3aed);
245
+ border-radius: 0 2px 2px 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
246
  }
247
+
248
+ /* ─── Command Input ───────────────────────────────────────────────────────── */
249
+ .cmd-input {
250
+ background: rgba(255,255,255,0.04);
251
+ border: 1px solid rgba(255,255,255,0.08);
252
+ border-radius: 12px;
253
+ color: var(--text-primary);
254
+ font-size: 0.9rem;
255
+ transition: all 0.2s ease;
256
+ }
257
+
258
+ .cmd-input:focus {
259
+ outline: none;
260
+ background: rgba(255,255,255,0.06);
261
+ border-color: rgba(124,58,237,0.4);
262
+ box-shadow: 0 0 0 3px rgba(124,58,237,0.1), 0 0 20px rgba(124,58,237,0.1);
263
+ }
264
+
265
+ /* ─── Card ────────────────────────────────────────────────────────────────── */
266
+ .card {
267
+ background: rgba(255,255,255,0.03);
268
+ border: 1px solid rgba(255,255,255,0.07);
269
+ border-radius: 16px;
270
+ transition: all 0.25s ease;
271
+ }
272
+
273
+ .card:hover {
274
+ background: rgba(255,255,255,0.05);
275
+ border-color: rgba(255,255,255,0.12);
276
+ transform: translateY(-1px);
277
  }
278
 
279
+ /* ─── Status Badge ────────────────────────────────────────────────────────── */
280
+ .badge {
281
+ display: inline-flex; align-items: center; gap: 5px;
282
+ padding: 2px 8px; border-radius: 20px;
283
+ font-size: 0.7rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em;
284
  }
285
 
286
+ .badge-active { background: rgba(34,197,94,0.12); color: #4ade80; }
287
+ .badge-idle { background: rgba(148,163,184,0.1); color: #94a3b8; }
288
+ .badge-processing { background: rgba(245,158,11,0.12); color: #fbbf24; }
289
+ .badge-error { background: rgba(239,68,68,0.12); color: #f87171; }
290
 
291
+ /* ─── Chip / Tag ──────────────────────────────────────────────────────────── */
292
+ .chip {
293
+ display: inline-flex; align-items: center; gap: 6px;
294
+ padding: 5px 12px; border-radius: 20px;
295
+ font-size: 0.78rem; font-weight: 500;
296
+ background: rgba(255,255,255,0.05);
297
+ border: 1px solid rgba(255,255,255,0.08);
298
+ color: var(--text-secondary);
299
+ cursor: pointer; white-space: nowrap;
300
+ transition: all 0.2s ease;
301
+ }
302
 
303
+ .chip:hover {
304
+ background: rgba(124,58,237,0.12);
305
+ border-color: rgba(124,58,237,0.3);
306
+ color: #a78bfa;
307
+ }
308
+
309
+ /* ─── Terminal / Console ───────────────────────────────────────────��──────── */
310
+ .terminal {
311
+ background: rgba(0,0,0,0.3);
312
+ border: 1px solid rgba(255,255,255,0.06);
313
+ border-radius: 12px;
314
+ font-family: 'JetBrains Mono', monospace;
315
+ font-size: 0.78rem;
316
+ }
317
+
318
+ /* ─── Stagger Delays ──────────────────────────────────────────────────────── */
319
+ .stagger-1 { animation-delay: 0.05s; }
320
+ .stagger-2 { animation-delay: 0.10s; }
321
+ .stagger-3 { animation-delay: 0.15s; }
322
+ .stagger-4 { animation-delay: 0.20s; }
323
+ .stagger-5 { animation-delay: 0.25s; }
324
+ .stagger-6 { animation-delay: 0.30s; }
325
+
326
+ /* ─── Responsive ──────────────────────────────────────────────────────────── */
327
+ @media (max-width: 1280px) {
328
+ .hide-xl { display: none; }
329
+ }
330
+ @media (max-width: 1024px) {
331
+ .hide-lg { display: none; }
332
+ }
frontend/app/layout.tsx CHANGED
@@ -2,23 +2,25 @@ import type { Metadata } from 'next'
2
  import './globals.css'
3
 
4
  export const metadata: Metadata = {
5
- title: 'God Mode+ AI OS',
6
- description: 'Devin + Manus + Genspark Autonomous AI Operating System',
7
- viewport: 'width=device-width, initial-scale=1, maximum-scale=1',
8
  }
9
 
10
  export default function RootLayout({ children }: { children: React.ReactNode }) {
11
  return (
12
- <html lang="en" data-theme="dark" suppressHydrationWarning>
13
  <head>
14
  <link rel="preconnect" href="https://fonts.googleapis.com" />
15
- <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="" />
16
  <link
17
- href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap"
18
  rel="stylesheet"
19
  />
20
  </head>
21
- <body className="antialiased">{children}</body>
 
 
22
  </html>
23
  )
24
  }
 
2
  import './globals.css'
3
 
4
  export const metadata: Metadata = {
5
+ title: 'GOD AGENT OS — Autonomous AI Operating System',
6
+ description: 'Multi-agent AI OS powered by Gemini, Sambanova & GitHub Models',
7
+ icons: { icon: '/favicon.ico' },
8
  }
9
 
10
  export default function RootLayout({ children }: { children: React.ReactNode }) {
11
  return (
12
+ <html lang="en" className="dark">
13
  <head>
14
  <link rel="preconnect" href="https://fonts.googleapis.com" />
15
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
16
  <link
17
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap"
18
  rel="stylesheet"
19
  />
20
  </head>
21
+ <body className="bg-void text-slate-100 antialiased overflow-hidden h-screen font-sans">
22
+ {children}
23
+ </body>
24
  </html>
25
  )
26
  }
frontend/app/page.tsx CHANGED
@@ -1,79 +1,81 @@
1
  'use client'
2
 
3
  import { useEffect, useState } from 'react'
4
- import { useAgentStore } from '@/hooks/useAgentStore'
5
- import { useAgentWebSocket } from '@/hooks/useWebSocket'
6
- import TopBar from '@/components/layout/TopBar'
7
- import Sidebar from '@/components/layout/Sidebar'
8
- import ChatPanel from '@/components/chat/ChatPanel'
9
- import ExecutionTimeline from '@/components/timeline/ExecutionTimeline'
10
- import TasksPanel from '@/components/layout/TasksPanel'
11
- import MemoryPanel from '@/components/layout/MemoryPanel'
12
- import ConnectorsPanel from '@/components/layout/ConnectorsPanel'
13
- import SandboxPanel from '@/components/layout/SandboxPanel'
14
- import FileExplorer from '@/components/layout/FileExplorer'
15
- import BrowserPanel from '@/components/layout/BrowserPanel'
16
  import { Zap } from 'lucide-react'
 
 
 
 
 
 
 
 
 
 
 
17
 
18
- export default function HomePage() {
19
- const { activePanel, activeTaskId, theme } = useAgentStore()
20
- const [mounted, setMounted] = useState(false)
21
-
22
- useEffect(() => {
23
- setMounted(true)
24
- document.documentElement.setAttribute('data-theme', theme)
25
- }, [])
 
 
26
 
27
- useEffect(() => {
28
- if (mounted) document.documentElement.setAttribute('data-theme', theme)
29
- }, [theme, mounted])
30
 
31
- useAgentWebSocket(undefined)
32
- useAgentWebSocket(activeTaskId || undefined)
33
 
34
  if (!mounted) return (
35
- <div className="flex items-center justify-center h-screen" style={{ background: 'var(--bg-0)' }}>
36
- <div className="text-center">
37
- <div className="w-16 h-16 rounded-2xl mx-auto mb-4 flex items-center justify-center"
38
- style={{ background: 'rgba(99,102,241,0.12)', border: '1px solid rgba(99,102,241,0.25)' }}>
39
- <Zap size={28} className="text-indigo-400" />
 
 
 
 
40
  </div>
41
- <h2 className="text-lg font-bold mb-1" style={{ color: 'var(--text-primary)' }}>GOD AGENT OS</h2>
42
- <p className="text-sm mb-1" style={{ color: 'var(--text-muted)' }}>Autonomous Engineering Platform v7.0</p>
43
- <p className="text-xs mb-4" style={{ color: 'var(--text-muted)' }}>Manus + Genspark + Devin</p>
44
- <div className="flex gap-1.5 justify-center">
45
  {[0, 1, 2].map(i => (
46
- <div key={i} className="typing-dot" style={{ animationDelay: `${i * 0.16}s` }} />
47
  ))}
48
  </div>
49
- </div>
50
  </div>
51
  )
52
 
53
- const RightPanel = () => {
54
- switch (activePanel) {
55
- case 'timeline': return <ExecutionTimeline />
56
- case 'tasks': return <TasksPanel />
57
- case 'memory': return <MemoryPanel />
58
- case 'connectors': return <ConnectorsPanel />
59
- case 'sandbox': return <SandboxPanel />
60
- case 'files': return <FileExplorer />
61
- case 'browser': return <BrowserPanel />
62
- default: return <ExecutionTimeline />
63
- }
64
- }
65
 
66
  return (
67
- <div className="flex flex-col h-screen overflow-hidden" style={{ background: 'var(--bg-0)' }}>
68
- <TopBar />
69
- <div className="flex flex-1 overflow-hidden">
70
- <Sidebar />
71
- <div className="flex-1 min-w-0 border-r" style={{ borderColor: 'var(--border)' }}>
72
- <ChatPanel />
73
- </div>
74
- <div className="w-[400px] flex-shrink-0 hidden lg:block">
75
- <RightPanel />
76
- </div>
 
 
 
 
 
 
 
 
77
  </div>
78
  </div>
79
  )
 
1
  'use client'
2
 
3
  import { useEffect, useState } from 'react'
4
+ import { motion, AnimatePresence } from 'framer-motion'
 
 
 
 
 
 
 
 
 
 
 
5
  import { Zap } from 'lucide-react'
6
+ import Sidebar from '@/components/shared/Sidebar'
7
+ import TopBar from '@/components/shared/TopBar'
8
+ import DashboardPage from '@/components/pages/DashboardPage'
9
+ import AgentsPage from '@/components/pages/AgentsPage'
10
+ import TasksPage from '@/components/pages/TasksPage'
11
+ import MemoryPage from '@/components/pages/MemoryPage'
12
+ import KnowledgePage from '@/components/pages/KnowledgePage'
13
+ import WorkflowsPage from '@/components/pages/WorkflowsPage'
14
+ import AnalyticsPage from '@/components/pages/AnalyticsPage'
15
+ import SettingsPage from '@/components/pages/SettingsPage'
16
+ import { useAppStore } from '@/store/useAppStore'
17
 
18
+ const PAGE_MAP = {
19
+ dashboard: DashboardPage,
20
+ agents: AgentsPage,
21
+ tasks: TasksPage,
22
+ memory: MemoryPage,
23
+ knowledge: KnowledgePage,
24
+ workflows: WorkflowsPage,
25
+ analytics: AnalyticsPage,
26
+ settings: SettingsPage,
27
+ }
28
 
29
+ export default function GodAgentOS() {
30
+ const { currentPage } = useAppStore()
31
+ const [mounted, setMounted] = useState(false)
32
 
33
+ useEffect(() => { setMounted(true) }, [])
 
34
 
35
  if (!mounted) return (
36
+ <div className="flex items-center justify-center h-screen" style={{ background: '#05060d' }}>
37
+ <motion.div
38
+ initial={{ opacity: 0, scale: 0.9 }}
39
+ animate={{ opacity: 1, scale: 1 }}
40
+ className="text-center"
41
+ >
42
+ <div className="w-16 h-16 rounded-2xl mx-auto mb-5 flex items-center justify-center glow-purple"
43
+ style={{ background: 'linear-gradient(135deg, #7c3aed, #4f46e5)' }}>
44
+ <Zap size={28} className="text-white" />
45
  </div>
46
+ <div className="shimmer-text text-xl font-black mb-2">GOD AGENT OS</div>
47
+ <div className="text-sm text-slate-600 mb-1">Autonomous AI Operating System</div>
48
+ <div className="text-xs text-slate-700">Gemini · Sambanova · GitHub Models</div>
49
+ <div className="flex gap-2 justify-center mt-6">
50
  {[0, 1, 2].map(i => (
51
+ <div key={i} className="typing-dot" style={{ animationDelay: `${i * 0.2}s` }} />
52
  ))}
53
  </div>
54
+ </motion.div>
55
  </div>
56
  )
57
 
58
+ const PageComponent = PAGE_MAP[currentPage]
 
 
 
 
 
 
 
 
 
 
 
59
 
60
  return (
61
+ <div className="flex h-screen overflow-hidden" style={{ background: '#05060d' }}>
62
+ <Sidebar />
63
+ <div className="flex flex-col flex-1 min-w-0 overflow-hidden">
64
+ <TopBar />
65
+ <main className="flex-1 overflow-hidden">
66
+ <AnimatePresence mode="wait">
67
+ <motion.div
68
+ key={currentPage}
69
+ initial={{ opacity: 0, y: 8 }}
70
+ animate={{ opacity: 1, y: 0 }}
71
+ exit={{ opacity: 0, y: -8 }}
72
+ transition={{ duration: 0.25, ease: [0.4, 0, 0.2, 1] }}
73
+ className="h-full"
74
+ >
75
+ <PageComponent />
76
+ </motion.div>
77
+ </AnimatePresence>
78
+ </main>
79
  </div>
80
  </div>
81
  )
frontend/components/dashboard/ActivityFeed.tsx ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client'
2
+
3
+ import { motion } from 'framer-motion'
4
+ import { ACTIVITY } from '@/store/useAppStore'
5
+ import { CheckCircle2, Loader2, Info, AlertTriangle } from 'lucide-react'
6
+
7
+ const TypeIcon = ({ type }: { type: string }) => {
8
+ const cls = 'w-3.5 h-3.5 flex-shrink-0'
9
+ switch (type) {
10
+ case 'success': return <CheckCircle2 className={cls} style={{ color: '#22c55e' }} />
11
+ case 'processing': return <Loader2 className={`${cls} animate-spin`} style={{ color: '#f59e0b' }} />
12
+ case 'warning': return <AlertTriangle className={cls} style={{ color: '#f59e0b' }} />
13
+ default: return <Info className={cls} style={{ color: '#60a5fa' }} />
14
+ }
15
+ }
16
+
17
+ export default function ActivityFeed({ max = 6 }: { max?: number }) {
18
+ const items = ACTIVITY.slice(0, max)
19
+ return (
20
+ <div className="space-y-1">
21
+ {items.map((item, i) => (
22
+ <motion.div
23
+ key={item.id}
24
+ initial={{ opacity: 0, x: 8 }}
25
+ animate={{ opacity: 1, x: 0 }}
26
+ transition={{ duration: 0.3, delay: i * 0.06 }}
27
+ className="flex items-start gap-3 px-3 py-2.5 rounded-xl hover:bg-white/[0.03] transition-colors group cursor-default"
28
+ >
29
+ <div className="w-6 h-6 rounded-lg flex items-center justify-center flex-shrink-0 mt-0.5"
30
+ style={{ background: `${item.color}15` }}>
31
+ <div className="w-2 h-2 rounded-full" style={{ background: item.color }} />
32
+ </div>
33
+ <div className="flex-1 min-w-0">
34
+ <div className="flex items-center justify-between gap-2">
35
+ <span className="text-xs font-semibold text-white truncate">{item.agent}</span>
36
+ <span className="text-xs flex-shrink-0" style={{ color: 'var(--text-muted)' }}>{item.time}</span>
37
+ </div>
38
+ <div className="text-xs mt-0.5 truncate" style={{ color: 'var(--text-secondary)' }}>{item.action}</div>
39
+ </div>
40
+ <TypeIcon type={item.type} />
41
+ </motion.div>
42
+ ))}
43
+ </div>
44
+ )
45
+ }
frontend/components/dashboard/AgentFleetCard.tsx ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client'
2
+
3
+ import { motion } from 'framer-motion'
4
+ import { Agent } from '@/store/useAppStore'
5
+ import { cn, getStatusColor } from '@/lib/utils'
6
+ import { ChevronRight } from 'lucide-react'
7
+
8
+ interface AgentFleetCardProps {
9
+ agent: Agent
10
+ delay?: number
11
+ onClick?: () => void
12
+ }
13
+
14
+ export default function AgentFleetCard({ agent, delay = 0, onClick }: AgentFleetCardProps) {
15
+ const statusColor = getStatusColor(agent.status)
16
+
17
+ return (
18
+ <motion.div
19
+ initial={{ opacity: 0, y: 12 }}
20
+ animate={{ opacity: 1, y: 0 }}
21
+ transition={{ duration: 0.35, delay, ease: [0.4, 0, 0.2, 1] }}
22
+ onClick={onClick}
23
+ className="card p-4 cursor-pointer group relative overflow-hidden"
24
+ >
25
+ {/* Accent line */}
26
+ <div className="absolute top-0 left-0 right-0 h-[2px] opacity-60 rounded-t-2xl"
27
+ style={{ background: `linear-gradient(90deg, ${agent.color}, transparent)` }} />
28
+
29
+ {/* Header */}
30
+ <div className="flex items-start justify-between mb-3">
31
+ <div className="w-10 h-10 rounded-xl flex items-center justify-center text-xl flex-shrink-0"
32
+ style={{ background: `${agent.color}15`, border: `1px solid ${agent.color}20` }}>
33
+ {agent.icon}
34
+ </div>
35
+ <div className={cn('badge', `badge-${agent.status}`)}>
36
+ <div className="w-1.5 h-1.5 rounded-full" style={{ background: statusColor }} />
37
+ {agent.status}
38
+ </div>
39
+ </div>
40
+
41
+ {/* Info */}
42
+ <div className="mb-3">
43
+ <div className="text-sm font-semibold text-white leading-snug">{agent.name}</div>
44
+ <div className="text-xs mt-0.5" style={{ color: 'var(--text-secondary)' }}>{agent.role}</div>
45
+ </div>
46
+
47
+ {/* Stats Row */}
48
+ <div className="grid grid-cols-2 gap-2 mb-3">
49
+ <div>
50
+ <div className="text-xs text-slate-500 mb-1">Efficiency</div>
51
+ <div className="progress-bar">
52
+ <div className="progress-fill"
53
+ style={{ width: `${agent.efficiency}%`, background: `linear-gradient(90deg, ${agent.color}80, ${agent.color})` }} />
54
+ </div>
55
+ <div className="text-xs font-semibold mt-1" style={{ color: agent.color }}>{agent.efficiency}%</div>
56
+ </div>
57
+ <div>
58
+ <div className="text-xs text-slate-500 mb-1">Uptime</div>
59
+ <div className="progress-bar">
60
+ <div className="progress-fill"
61
+ style={{ width: `${agent.uptime}%`, background: `linear-gradient(90deg, #22d3ee60, #22d3ee)` }} />
62
+ </div>
63
+ <div className="text-xs font-semibold mt-1 text-cyan-400">{agent.uptime}%</div>
64
+ </div>
65
+ </div>
66
+
67
+ {/* Last Action */}
68
+ <div className="flex items-center gap-1.5 text-xs text-slate-500 group-hover:text-slate-400 transition-colors">
69
+ <span className="truncate">{agent.lastAction}</span>
70
+ <span className="flex-shrink-0">· {agent.lastActionTime}</span>
71
+ </div>
72
+
73
+ <ChevronRight size={14} className="absolute right-3 bottom-3 text-slate-700 group-hover:text-purple-400 transition-colors" />
74
+ </motion.div>
75
+ )
76
+ }
frontend/components/dashboard/CommandCenter.tsx ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client'
2
+
3
+ import { useState, useRef, useEffect } from 'react'
4
+ import { motion } from 'framer-motion'
5
+ import { Terminal, Mic, Send } from 'lucide-react'
6
+
7
+ const COMMANDS = ['/new-project', '/analyze-competitors', '/generate-report', '/deploy-app', '/automate-workflow', '/research']
8
+ const LINES = [
9
+ { text: '> God Agent OS is listening...', color: '#6366f1' },
10
+ { text: '> Multi-agent system ready. Gemini · Sambanova · GitHub Models active.', color: '#22d3ee' },
11
+ { text: '> How may I assist in your divine mission?', color: 'var(--text-secondary)' },
12
+ ]
13
+
14
+ export default function CommandCenter() {
15
+ const [input, setInput] = useState('')
16
+ const [history, setHistory] = useState<string[]>([])
17
+ const inputRef = useRef<HTMLInputElement>(null)
18
+
19
+ const handleSubmit = (cmd?: string) => {
20
+ const command = cmd || input.trim()
21
+ if (!command) return
22
+ setHistory(prev => [...prev, `> ${command}`, ' Executing…'])
23
+ setInput('')
24
+ setTimeout(() => {
25
+ setHistory(prev => [...prev, ' ✓ Task dispatched to agent fleet.'])
26
+ }, 800)
27
+ }
28
+
29
+ return (
30
+ <div className="card overflow-hidden">
31
+ {/* Header */}
32
+ <div className="flex items-center justify-between px-4 py-3 border-b" style={{ borderColor: 'var(--border)' }}>
33
+ <div className="flex items-center gap-2">
34
+ <Terminal size={14} className="text-purple-400" />
35
+ <span className="text-xs font-bold text-white">Command Center</span>
36
+ <div className="w-1.5 h-1.5 rounded-full bg-green-400 animate-pulse-glow" />
37
+ </div>
38
+ <button className="flex items-center gap-1.5 text-xs px-3 py-1.5 rounded-lg font-medium transition-all hover:bg-purple-500/10"
39
+ style={{ background: 'rgba(124,58,237,0.08)', border: '1px solid rgba(124,58,237,0.2)', color: '#a78bfa' }}>
40
+ <Mic size={11} />
41
+ Voice Command
42
+ </button>
43
+ </div>
44
+
45
+ {/* Terminal */}
46
+ <div className="terminal mx-3 mt-3 mb-2 p-3 min-h-[80px]">
47
+ {LINES.map((line, i) => (
48
+ <div key={i} className="text-xs leading-relaxed" style={{ color: line.color }}>{line.text}</div>
49
+ ))}
50
+ {history.map((line, i) => (
51
+ <div key={`h${i}`} className="text-xs leading-relaxed text-slate-400">{line}</div>
52
+ ))}
53
+ </div>
54
+
55
+ {/* Command Chips */}
56
+ <div className="flex flex-wrap gap-2 px-3 pb-3">
57
+ {COMMANDS.map(cmd => (
58
+ <button key={cmd} onClick={() => handleSubmit(cmd)}
59
+ className="chip text-xs">
60
+ {cmd}
61
+ </button>
62
+ ))}
63
+ <div className="flex gap-2 ml-auto">
64
+ <input
65
+ ref={inputRef}
66
+ value={input}
67
+ onChange={e => setInput(e.target.value)}
68
+ onKeyDown={e => e.key === 'Enter' && handleSubmit()}
69
+ placeholder="Custom command…"
70
+ className="cmd-input px-3 py-1.5 text-xs w-36"
71
+ />
72
+ <button onClick={() => handleSubmit()}
73
+ className="p-1.5 rounded-lg transition-colors hover:bg-purple-500/20"
74
+ style={{ background: 'rgba(124,58,237,0.1)', border: '1px solid rgba(124,58,237,0.2)' }}>
75
+ <Send size={12} className="text-purple-400" />
76
+ </button>
77
+ </div>
78
+ </div>
79
+ </div>
80
+ )
81
+ }
frontend/components/dashboard/GodModeCard.tsx ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client'
2
+
3
+ import { motion } from 'framer-motion'
4
+ import { useAppStore } from '@/store/useAppStore'
5
+
6
+ export default function GodModeCard() {
7
+ const { godModeActive } = useAppStore()
8
+
9
+ return (
10
+ <div className="relative overflow-hidden rounded-2xl p-5"
11
+ style={{ background: 'linear-gradient(135deg, rgba(124,58,237,0.15) 0%, rgba(59,130,246,0.1) 50%, rgba(20,24,40,0.8) 100%)', border: '1px solid rgba(124,58,237,0.25)' }}>
12
+
13
+ {/* Cosmic Orb */}
14
+ <div className="flex justify-center mb-4">
15
+ <div className="cosmic-orb" style={{ width: 80, height: 80 }} />
16
+ </div>
17
+
18
+ {/* Status */}
19
+ <div className="text-center">
20
+ <div className="text-xs font-semibold uppercase tracking-widest mb-1" style={{ color: 'var(--text-secondary)' }}>GOD MODE</div>
21
+ <div className={`text-xl font-black tracking-wide mb-2 ${godModeActive ? 'gradient-text' : 'text-slate-500'}`}>
22
+ {godModeActive ? 'ACTIVE' : 'STANDBY'}
23
+ </div>
24
+ <p className="text-xs" style={{ color: 'var(--text-secondary)' }}>
25
+ {godModeActive ? 'All systems operational. You are the Architect.' : 'Enable God Mode for full autonomy.'}
26
+ </p>
27
+ </div>
28
+
29
+ {/* Glow overlay */}
30
+ {godModeActive && (
31
+ <motion.div
32
+ className="absolute inset-0 pointer-events-none rounded-2xl"
33
+ animate={{ opacity: [0.3, 0.6, 0.3] }}
34
+ transition={{ duration: 3, repeat: Infinity, ease: 'easeInOut' }}
35
+ style={{ background: 'radial-gradient(ellipse at 50% 0%, rgba(124,58,237,0.15) 0%, transparent 70%)' }}
36
+ />
37
+ )}
38
+
39
+ {/* Status dot */}
40
+ <div className="absolute top-3 right-3 flex items-center gap-1.5">
41
+ <div className={`w-2 h-2 rounded-full ${godModeActive ? 'bg-green-400 animate-pulse-glow' : 'bg-slate-600'}`} />
42
+ <span className="text-xs font-medium" style={{ color: godModeActive ? '#4ade80' : 'var(--text-muted)' }}>
43
+ {godModeActive ? 'Live' : 'Off'}
44
+ </span>
45
+ </div>
46
+ </div>
47
+ )
48
+ }
frontend/components/dashboard/MetricCard.tsx ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client'
2
+
3
+ import { motion } from 'framer-motion'
4
+ import { TrendingUp, TrendingDown } from 'lucide-react'
5
+ import { cn } from '@/lib/utils'
6
+
7
+ interface MetricCardProps {
8
+ label: string
9
+ value: string | number
10
+ unit?: string
11
+ trend?: string
12
+ trendUp?: boolean
13
+ icon: React.ReactNode
14
+ iconColor: string
15
+ delay?: number
16
+ }
17
+
18
+ export default function MetricCard({ label, value, unit, trend, trendUp = true, icon, iconColor, delay = 0 }: MetricCardProps) {
19
+ return (
20
+ <motion.div
21
+ initial={{ opacity: 0, y: 16 }}
22
+ animate={{ opacity: 1, y: 0 }}
23
+ transition={{ duration: 0.4, delay, ease: [0.4, 0, 0.2, 1] }}
24
+ className="card p-5 group cursor-default"
25
+ >
26
+ <div className="flex items-start justify-between mb-4">
27
+ <div className="w-10 h-10 rounded-xl flex items-center justify-center transition-transform group-hover:scale-110"
28
+ style={{ background: `${iconColor}15`, border: `1px solid ${iconColor}25` }}>
29
+ <div style={{ color: iconColor }}>{icon}</div>
30
+ </div>
31
+ {trend && (
32
+ <div className={cn('flex items-center gap-1 text-xs font-semibold px-2 py-1 rounded-full',
33
+ trendUp ? 'text-green-400 bg-green-400/10' : 'text-red-400 bg-red-400/10'
34
+ )}>
35
+ {trendUp ? <TrendingUp size={11} /> : <TrendingDown size={11} />}
36
+ {trend}
37
+ </div>
38
+ )}
39
+ </div>
40
+
41
+ <div className="flex items-end gap-1.5">
42
+ <span className="text-3xl font-bold text-white leading-none">{value}</span>
43
+ {unit && <span className="text-sm font-medium text-slate-400 mb-0.5">{unit}</span>}
44
+ </div>
45
+ <div className="text-xs font-medium mt-1.5" style={{ color: 'var(--text-secondary)' }}>{label}</div>
46
+ </motion.div>
47
+ )
48
+ }
frontend/components/dashboard/MissionInput.tsx ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client'
2
+
3
+ import { useState } from 'react'
4
+ import { motion, AnimatePresence } from 'framer-motion'
5
+ import { Send, Telescope, Code2, Zap, BarChart2, PenLine, MoreHorizontal, Loader2, Mic } from 'lucide-react'
6
+
7
+ const QUICK_ACTIONS = [
8
+ { icon: Telescope, label: 'Research', color: '#6366f1', prompt: 'Research the latest trends in ' },
9
+ { icon: Code2, label: 'Build', color: '#34d399', prompt: 'Build and deploy a ' },
10
+ { icon: Zap, label: 'Automate', color: '#f59e0b', prompt: 'Create an automation workflow for ' },
11
+ { icon: BarChart2, label: 'Analyze', color: '#22d3ee', prompt: 'Analyze data and generate insights for ' },
12
+ { icon: PenLine, label: 'Generate', color: '#a78bfa', prompt: 'Generate high-quality content for ' },
13
+ ]
14
+
15
+ const EXAMPLE_PROMPTS = [
16
+ 'Build a complete marketing analysis dashboard with AI insights',
17
+ 'Research competitors in the SaaS market and synthesize findings',
18
+ 'Automate my GitHub PR review workflow with AI agents',
19
+ 'Analyze Q4 performance data and generate executive summary',
20
+ ]
21
+
22
+ export default function MissionInput() {
23
+ const [prompt, setPrompt] = useState('')
24
+ const [loading, setLoading] = useState(false)
25
+ const [selectedAction, setSelectedAction] = useState<string | null>(null)
26
+
27
+ const handleAction = (actionPrompt: string, label: string) => {
28
+ setPrompt(actionPrompt)
29
+ setSelectedAction(label)
30
+ }
31
+
32
+ const handleSubmit = async () => {
33
+ if (!prompt.trim() || loading) return
34
+ setLoading(true)
35
+ await new Promise(r => setTimeout(r, 2000))
36
+ setLoading(false)
37
+ setPrompt('')
38
+ setSelectedAction(null)
39
+ }
40
+
41
+ const handleKeyDown = (e: React.KeyboardEvent) => {
42
+ if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSubmit() }
43
+ }
44
+
45
+ return (
46
+ <div className="card p-5">
47
+ {/* Header */}
48
+ <div className="flex items-start gap-3 mb-4">
49
+ <div className="w-8 h-8 rounded-xl flex items-center justify-center flex-shrink-0"
50
+ style={{ background: 'rgba(124,58,237,0.15)', border: '1px solid rgba(124,58,237,0.25)' }}>
51
+ <Zap size={15} className="text-purple-400" />
52
+ </div>
53
+ <div>
54
+ <h2 className="text-base font-semibold text-white">What shall we build today?</h2>
55
+ <p className="text-xs mt-0.5" style={{ color: 'var(--text-secondary)' }}>
56
+ Describe your mission. God Agent OS will orchestrate the rest.
57
+ </p>
58
+ </div>
59
+ </div>
60
+
61
+ {/* Input */}
62
+ <div className="relative mb-3">
63
+ <textarea
64
+ value={prompt}
65
+ onChange={e => setPrompt(e.target.value)}
66
+ onKeyDown={handleKeyDown}
67
+ placeholder="e.g., Build a complete marketing analysis dashboard with AI insights…"
68
+ rows={3}
69
+ className="cmd-input w-full px-4 py-3 pr-12 text-sm resize-none"
70
+ style={{ minHeight: 88, lineHeight: 1.6 }}
71
+ />
72
+ <div className="absolute right-3 bottom-3 flex items-center gap-2">
73
+ <button className="p-1.5 rounded-lg text-slate-600 hover:text-purple-400 transition-colors">
74
+ <Mic size={15} />
75
+ </button>
76
+ <motion.button
77
+ onClick={handleSubmit}
78
+ disabled={!prompt.trim() || loading}
79
+ whileHover={{ scale: 1.05 }}
80
+ whileTap={{ scale: 0.95 }}
81
+ className="w-8 h-8 rounded-lg flex items-center justify-center transition-all disabled:opacity-40"
82
+ style={{ background: prompt.trim() && !loading ? 'linear-gradient(135deg, #7c3aed, #4f46e5)' : 'rgba(255,255,255,0.08)' }}
83
+ >
84
+ {loading ? <Loader2 size={14} className="text-white animate-spin" /> : <Send size={14} className="text-white" />}
85
+ </motion.button>
86
+ </div>
87
+ </div>
88
+
89
+ {/* Quick Actions */}
90
+ <div className="flex flex-wrap gap-2">
91
+ {QUICK_ACTIONS.map(({ icon: Icon, label, color, prompt: p }) => (
92
+ <button
93
+ key={label}
94
+ onClick={() => handleAction(p, label)}
95
+ className={`chip transition-all ${selectedAction === label ? 'border-purple-500/40 bg-purple-500/10 text-purple-300' : ''}`}
96
+ >
97
+ <Icon size={12} style={{ color }} />
98
+ {label}
99
+ </button>
100
+ ))}
101
+ <button className="chip">
102
+ <MoreHorizontal size={12} />
103
+ More
104
+ </button>
105
+ </div>
106
+
107
+ {/* Example prompts */}
108
+ <AnimatePresence>
109
+ {!prompt && (
110
+ <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className="mt-3 pt-3 border-t" style={{ borderColor: 'var(--border)' }}>
111
+ <div className="text-xs mb-2 font-medium" style={{ color: 'var(--text-muted)' }}>Quick start:</div>
112
+ <div className="space-y-1">
113
+ {EXAMPLE_PROMPTS.slice(0, 2).map(ep => (
114
+ <button key={ep} onClick={() => setPrompt(ep)}
115
+ className="w-full text-left text-xs px-3 py-1.5 rounded-lg hover:bg-white/[0.04] text-slate-500 hover:text-slate-300 transition-colors truncate">
116
+ → {ep}
117
+ </button>
118
+ ))}
119
+ </div>
120
+ </motion.div>
121
+ )}
122
+ </AnimatePresence>
123
+ </div>
124
+ )
125
+ }
frontend/components/dashboard/SystemResources.tsx ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client'
2
+
3
+ import { useEffect, useState } from 'react'
4
+ import { motion } from 'framer-motion'
5
+ import { Cpu, MemoryStick, HardDrive, Wifi } from 'lucide-react'
6
+ import { useAppStore } from '@/store/useAppStore'
7
+
8
+ const RESOURCE_CONFIGS = [
9
+ { key: 'cpu', label: 'CPU', icon: Cpu, color: '#6366f1' },
10
+ { key: 'memory', label: 'Memory', icon: MemoryStick, color: '#22d3ee' },
11
+ { key: 'storage', label: 'Storage', icon: HardDrive, color: '#a78bfa' },
12
+ { key: 'network', label: 'Network', icon: Wifi, color: '#34d399' },
13
+ ] as const
14
+
15
+ export default function SystemResources() {
16
+ const { systemResources, updateSystemResources } = useAppStore()
17
+
18
+ // Simulate live fluctuation
19
+ useEffect(() => {
20
+ const interval = setInterval(() => {
21
+ updateSystemResources({
22
+ cpu: Math.min(95, Math.max(15, systemResources.cpu + (Math.random() - 0.5) * 6)),
23
+ memory: Math.min(90, Math.max(40, systemResources.memory + (Math.random() - 0.5) * 3)),
24
+ network: Math.min(80, Math.max(10, systemResources.network + (Math.random() - 0.5) * 8)),
25
+ })
26
+ }, 3000)
27
+ return () => clearInterval(interval)
28
+ }, [systemResources, updateSystemResources])
29
+
30
+ return (
31
+ <div className="space-y-3">
32
+ {RESOURCE_CONFIGS.map(({ key, label, icon: Icon, color }) => {
33
+ const value = Math.round(systemResources[key])
34
+ return (
35
+ <div key={key} className="flex items-center gap-3">
36
+ <div className="w-6 h-6 rounded-lg flex items-center justify-center flex-shrink-0"
37
+ style={{ background: `${color}15` }}>
38
+ <Icon size={12} style={{ color }} />
39
+ </div>
40
+ <div className="flex-1 min-w-0">
41
+ <div className="flex items-center justify-between mb-1.5">
42
+ <span className="text-xs font-medium" style={{ color: 'var(--text-secondary)' }}>{label}</span>
43
+ <span className="text-xs font-bold" style={{ color }}>{value}%</span>
44
+ </div>
45
+ <div className="progress-bar h-1.5">
46
+ <motion.div
47
+ className="progress-fill h-full rounded-full"
48
+ animate={{ width: `${value}%` }}
49
+ transition={{ duration: 0.8, ease: 'easeOut' }}
50
+ style={{ background: `linear-gradient(90deg, ${color}60, ${color})` }}
51
+ />
52
+ </div>
53
+ </div>
54
+ </div>
55
+ )
56
+ })}
57
+ </div>
58
+ )
59
+ }
frontend/components/layout/AIRouterPanel.tsx ADDED
@@ -0,0 +1,268 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client'
2
+
3
+ import { useEffect, useState } from 'react'
4
+ import { useAgentStore } from '@/hooks/useAgentStore'
5
+ import { Cpu, Key, RefreshCw, CheckCircle2, XCircle, AlertCircle, Zap, Activity } from 'lucide-react'
6
+
7
+ const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:7860'
8
+
9
+ interface ProviderStat {
10
+ calls: number
11
+ errors: number
12
+ avg_latency_ms: number
13
+ available: boolean
14
+ key_count: number
15
+ available_keys: number
16
+ priority: number
17
+ }
18
+
19
+ interface KeyInfo {
20
+ key_preview: string
21
+ available: boolean
22
+ failures: number
23
+ calls: number
24
+ cooldown_remaining_s: number
25
+ }
26
+
27
+ interface PoolStatus {
28
+ provider: string
29
+ total_keys: number
30
+ available_keys: number
31
+ keys: KeyInfo[]
32
+ }
33
+
34
+ const PROVIDER_ICONS: Record<string, string> = {
35
+ sambanova: '⚡',
36
+ gemini: '✨',
37
+ openai: '🤖',
38
+ groq: '🦙',
39
+ cerebras: '🧠',
40
+ openrouter: '🔀',
41
+ anthropic: '🪄',
42
+ }
43
+
44
+ const PROVIDER_COLORS: Record<string, string> = {
45
+ sambanova: '#f97316',
46
+ gemini: '#4285f4',
47
+ openai: '#10a37f',
48
+ groq: '#f59e0b',
49
+ cerebras: '#8b5cf6',
50
+ openrouter: '#6366f1',
51
+ anthropic: '#d97706',
52
+ }
53
+
54
+ export default function AIRouterPanel() {
55
+ const { locale } = useAgentStore()
56
+ const [stats, setStats] = useState<Record<string, ProviderStat>>({})
57
+ const [pools, setPools] = useState<Record<string, PoolStatus>>({})
58
+ const [loading, setLoading] = useState(true)
59
+ const [expandedProvider, setExpandedProvider] = useState<string | null>(null)
60
+ const [lastRefresh, setLastRefresh] = useState<Date | null>(null)
61
+
62
+ const load = async () => {
63
+ setLoading(true)
64
+ try {
65
+ const [statsRes, poolRes] = await Promise.all([
66
+ fetch(`${API_URL}/api/v1/ai/stats`).then(r => r.json()).catch(() => ({})),
67
+ fetch(`${API_URL}/api/v1/ai/pool-status`).then(r => r.json()).catch(() => ({})),
68
+ ])
69
+ setStats(statsRes.stats || {})
70
+ setPools(poolRes.pools || {})
71
+ setLastRefresh(new Date())
72
+ } catch {}
73
+ setLoading(false)
74
+ }
75
+
76
+ useEffect(() => {
77
+ load()
78
+ const interval = setInterval(load, 30000)
79
+ return () => clearInterval(interval)
80
+ }, [])
81
+
82
+ const sortedProviders = Object.entries(stats).sort(
83
+ ([, a], [, b]) => (a.priority || 99) - (b.priority || 99)
84
+ )
85
+
86
+ const activeCount = sortedProviders.filter(([, s]) => s.available).length
87
+ const totalCalls = sortedProviders.reduce((sum, [, s]) => sum + s.calls, 0)
88
+
89
+ return (
90
+ <div className="flex flex-col h-full" style={{ background: 'var(--bg-2)' }}>
91
+ {/* Header */}
92
+ <div className="flex items-center justify-between px-4 py-2.5 border-b shrink-0"
93
+ style={{ borderColor: 'var(--border)', background: 'var(--bg-3)' }}>
94
+ <div className="flex items-center gap-2">
95
+ <Cpu size={14} className="text-indigo-400" />
96
+ <span className="text-sm font-semibold" style={{ color: 'var(--text-primary)' }}>
97
+ {locale === 'my' ? 'AI Router v8' : 'AI Router v8'}
98
+ </span>
99
+ <span className="text-[10px] px-1.5 py-0.5 rounded-full"
100
+ style={{
101
+ background: activeCount > 0 ? 'rgba(34,197,94,0.15)' : 'rgba(239,68,68,0.15)',
102
+ color: activeCount > 0 ? '#4ade80' : '#f87171',
103
+ border: `1px solid ${activeCount > 0 ? 'rgba(34,197,94,0.3)' : 'rgba(239,68,68,0.3)'}`,
104
+ }}>
105
+ {activeCount} active
106
+ </span>
107
+ </div>
108
+ <button onClick={load} disabled={loading}
109
+ className="p-1.5 rounded-lg hover:bg-white/5 transition-colors" title="Refresh">
110
+ <RefreshCw size={12} style={{ color: 'var(--text-muted)' }}
111
+ className={loading ? 'animate-spin' : ''} />
112
+ </button>
113
+ </div>
114
+
115
+ {/* Summary */}
116
+ <div className="px-3 py-2 border-b flex gap-3 text-xs"
117
+ style={{ borderColor: 'var(--border)', background: 'rgba(99,102,241,0.05)' }}>
118
+ <div className="flex items-center gap-1">
119
+ <Activity size={10} className="text-indigo-400" />
120
+ <span style={{ color: 'var(--text-muted)' }}>Total calls:</span>
121
+ <span className="font-mono font-semibold" style={{ color: 'var(--text-primary)' }}>{totalCalls}</span>
122
+ </div>
123
+ <div className="flex items-center gap-1">
124
+ <Key size={10} className="text-indigo-400" />
125
+ <span style={{ color: 'var(--text-muted)' }}>Providers:</span>
126
+ <span className="font-mono font-semibold" style={{ color: 'var(--text-primary)' }}>
127
+ {activeCount}/{sortedProviders.length}
128
+ </span>
129
+ </div>
130
+ {lastRefresh && (
131
+ <div className="ml-auto text-[10px]" style={{ color: 'var(--text-muted)' }}>
132
+ {lastRefresh.toLocaleTimeString()}
133
+ </div>
134
+ )}
135
+ </div>
136
+
137
+ {/* Provider List */}
138
+ <div className="flex-1 overflow-y-auto">
139
+ {loading && sortedProviders.length === 0 ? (
140
+ <div className="flex items-center justify-center h-24">
141
+ <div className="flex gap-1">
142
+ {[0, 1, 2].map(i => (
143
+ <div key={i} className="w-1.5 h-1.5 rounded-full animate-bounce"
144
+ style={{ background: 'var(--brand)', animationDelay: `${i * 0.15}s` }} />
145
+ ))}
146
+ </div>
147
+ </div>
148
+ ) : sortedProviders.length === 0 ? (
149
+ <div className="p-4 text-center text-xs" style={{ color: 'var(--text-muted)' }}>
150
+ No providers configured
151
+ </div>
152
+ ) : (
153
+ <div className="p-2 flex flex-col gap-1.5">
154
+ {sortedProviders.map(([name, stat]) => {
155
+ const pool = pools[name]
156
+ const icon = PROVIDER_ICONS[name] || '🔌'
157
+ const color = PROVIDER_COLORS[name] || '#6366f1'
158
+ const isExpanded = expandedProvider === name
159
+ const successRate = stat.calls > 0
160
+ ? Math.round(((stat.calls - stat.errors) / stat.calls) * 100)
161
+ : 100
162
+
163
+ return (
164
+ <div key={name}
165
+ className="rounded-xl border overflow-hidden cursor-pointer hover:border-opacity-60 transition-all"
166
+ style={{
167
+ borderColor: stat.available ? `${color}40` : 'var(--border)',
168
+ background: stat.available ? `${color}08` : 'var(--bg-3)',
169
+ }}
170
+ onClick={() => setExpandedProvider(isExpanded ? null : name)}>
171
+
172
+ {/* Provider Header */}
173
+ <div className="flex items-center gap-2 px-3 py-2">
174
+ <span className="text-sm">{icon}</span>
175
+ <div className="flex-1 min-w-0">
176
+ <div className="flex items-center gap-2">
177
+ <span className="text-xs font-semibold capitalize" style={{ color: 'var(--text-primary)' }}>
178
+ {name}
179
+ </span>
180
+ {stat.priority <= 2 && (
181
+ <span className="text-[9px] px-1 py-0.5 rounded font-bold"
182
+ style={{ background: `${color}25`, color }}>
183
+ PRIMARY
184
+ </span>
185
+ )}
186
+ </div>
187
+ <div className="flex items-center gap-2 mt-0.5">
188
+ <span className="text-[10px]" style={{ color: 'var(--text-muted)' }}>
189
+ {stat.calls} calls · {stat.avg_latency_ms}ms avg
190
+ </span>
191
+ {pool && (
192
+ <span className="text-[10px]" style={{ color: 'var(--text-muted)' }}>
193
+ · {pool.available_keys}/{pool.total_keys} keys
194
+ </span>
195
+ )}
196
+ </div>
197
+ </div>
198
+ <div className="flex items-center gap-1.5">
199
+ {/* Success Rate Bar */}
200
+ {stat.calls > 0 && (
201
+ <div className="w-12 h-1.5 rounded-full overflow-hidden"
202
+ style={{ background: 'var(--bg-0)' }}>
203
+ <div className="h-full rounded-full transition-all"
204
+ style={{
205
+ width: `${successRate}%`,
206
+ background: successRate > 80 ? '#4ade80' : successRate > 50 ? '#fbbf24' : '#f87171',
207
+ }} />
208
+ </div>
209
+ )}
210
+ {stat.available ? (
211
+ <CheckCircle2 size={12} style={{ color: '#4ade80' }} />
212
+ ) : (
213
+ <XCircle size={12} style={{ color: '#f87171' }} />
214
+ )}
215
+ </div>
216
+ </div>
217
+
218
+ {/* Expanded Key Pool */}
219
+ {isExpanded && pool && pool.keys.length > 0 && (
220
+ <div className="px-3 pb-3 border-t" style={{ borderColor: 'var(--border)' }}>
221
+ <div className="pt-2 text-[10px] font-semibold mb-2" style={{ color: 'var(--text-muted)' }}>
222
+ KEY POOL ({pool.available_keys}/{pool.total_keys} available)
223
+ </div>
224
+ <div className="flex flex-col gap-1">
225
+ {pool.keys.map((k, i) => (
226
+ <div key={i} className="flex items-center gap-2 px-2 py-1 rounded-lg"
227
+ style={{ background: k.available ? 'rgba(34,197,94,0.05)' : 'rgba(239,68,68,0.05)' }}>
228
+ <Key size={9} style={{ color: k.available ? '#4ade80' : '#f87171' }} />
229
+ <span className="font-mono text-[10px] flex-1" style={{ color: 'var(--text-secondary)' }}>
230
+ {k.key_preview}
231
+ </span>
232
+ <span className="text-[9px]" style={{ color: 'var(--text-muted)' }}>
233
+ {k.calls} calls
234
+ </span>
235
+ {k.failures > 0 && (
236
+ <span className="text-[9px]" style={{ color: '#fbbf24' }}>
237
+ {k.failures} fails
238
+ </span>
239
+ )}
240
+ {!k.available && k.cooldown_remaining_s > 0 && (
241
+ <span className="text-[9px] px-1 rounded"
242
+ style={{ background: 'rgba(239,68,68,0.15)', color: '#f87171' }}>
243
+ {Math.round(k.cooldown_remaining_s)}s
244
+ </span>
245
+ )}
246
+ </div>
247
+ ))}
248
+ </div>
249
+ </div>
250
+ )}
251
+ </div>
252
+ )
253
+ })}
254
+ </div>
255
+ )}
256
+ </div>
257
+
258
+ {/* Footer Info */}
259
+ <div className="px-3 py-2 border-t text-[10px]"
260
+ style={{ borderColor: 'var(--border)', color: 'var(--text-muted)', background: 'var(--bg-3)' }}>
261
+ <div className="flex items-center gap-1">
262
+ <Zap size={9} className="text-indigo-400" />
263
+ <span>Priority: SambaNova → Gemini → OpenAI → Groq → Cerebras → Anthropic</span>
264
+ </div>
265
+ </div>
266
+ </div>
267
+ )
268
+ }
frontend/components/layout/Sidebar.tsx CHANGED
@@ -17,6 +17,7 @@ const PANELS: { id: ActivePanel; icon: React.ElementType; labelEn: string; label
17
  { id: 'browser', icon: Globe, labelEn: 'Browser', labelMy: 'ဘရောင်ဇာ', badge: 'v7' },
18
  { id: 'memory', icon: Brain, labelEn: 'Memory', labelMy: 'မှတ်ဉာဏ်' },
19
  { id: 'connectors', icon: Plug, labelEn: 'Connectors', labelMy: 'ချိတ်ဆက်မှု' },
 
20
  ]
21
 
22
  const AGENT_META: Record<string, { icon: React.ElementType; color: string; label: string; isNew?: boolean }> = {
@@ -128,7 +129,7 @@ export default function Sidebar() {
128
  <div className="flex items-center gap-2 px-2 py-1.5 rounded-lg text-[10px]"
129
  style={{ background: 'rgba(99,102,241,0.08)', border: '1px solid rgba(99,102,241,0.2)' }}>
130
  <Bot size={10} className="text-indigo-400" />
131
- <span style={{ color: 'var(--text-muted)' }}>God Agent OS v7.0</span>
132
  <div className="ml-auto w-1.5 h-1.5 rounded-full bg-green-400 animate-pulse" />
133
  </div>
134
  </div>
 
17
  { id: 'browser', icon: Globe, labelEn: 'Browser', labelMy: 'ဘရောင်ဇာ', badge: 'v7' },
18
  { id: 'memory', icon: Brain, labelEn: 'Memory', labelMy: 'မှတ်ဉာဏ်' },
19
  { id: 'connectors', icon: Plug, labelEn: 'Connectors', labelMy: 'ချိတ်ဆက်မှု' },
20
+ { id: 'ai_router', icon: Cpu, labelEn: 'AI Router', labelMy: 'AI Router', badge: 'v8' },
21
  ]
22
 
23
  const AGENT_META: Record<string, { icon: React.ElementType; color: string; label: string; isNew?: boolean }> = {
 
129
  <div className="flex items-center gap-2 px-2 py-1.5 rounded-lg text-[10px]"
130
  style={{ background: 'rgba(99,102,241,0.08)', border: '1px solid rgba(99,102,241,0.2)' }}>
131
  <Bot size={10} className="text-indigo-400" />
132
+ <span style={{ color: 'var(--text-muted)' }}>God Agent OS v8.0</span>
133
  <div className="ml-auto w-1.5 h-1.5 rounded-full bg-green-400 animate-pulse" />
134
  </div>
135
  </div>
frontend/components/pages/AgentsPage.tsx ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client'
2
+
3
+ import { useState } from 'react'
4
+ import { motion } from 'framer-motion'
5
+ import { Search, Filter, Plus, Bot, Activity, Zap } from 'lucide-react'
6
+ import { AGENTS, Agent } from '@/store/useAppStore'
7
+ import { getStatusColor, cn } from '@/lib/utils'
8
+
9
+ const STATUS_FILTERS = ['All', 'Active', 'Processing', 'Idle', 'Error']
10
+
11
+ function AgentDetailCard({ agent }: { agent: Agent }) {
12
+ const sc = getStatusColor(agent.status)
13
+ return (
14
+ <motion.div layout className="card p-5 relative overflow-hidden group">
15
+ <div className="absolute top-0 left-0 right-0 h-[2px]"
16
+ style={{ background: `linear-gradient(90deg, ${agent.color}, transparent)` }} />
17
+
18
+ <div className="flex items-start gap-4 mb-4">
19
+ <div className="w-12 h-12 rounded-2xl flex items-center justify-center text-2xl flex-shrink-0"
20
+ style={{ background: `${agent.color}15`, border: `1px solid ${agent.color}25` }}>
21
+ {agent.icon}
22
+ </div>
23
+ <div className="flex-1 min-w-0">
24
+ <div className="flex items-center gap-2">
25
+ <h3 className="font-bold text-white">{agent.name}</h3>
26
+ <div className="flex items-center gap-1.5 px-2 py-0.5 rounded-full text-xs font-semibold"
27
+ style={{ background: `${sc}15`, color: sc }}>
28
+ <div className="w-1.5 h-1.5 rounded-full" style={{ background: sc }} />
29
+ {agent.status}
30
+ </div>
31
+ </div>
32
+ <p className="text-sm mt-0.5" style={{ color: 'var(--text-secondary)' }}>{agent.role}</p>
33
+ <p className="text-xs mt-2 text-slate-500">{agent.lastAction} · {agent.lastActionTime}</p>
34
+ </div>
35
+ <div className="text-right">
36
+ <div className="text-xs text-slate-500 mb-0.5">Tasks</div>
37
+ <div className="text-xl font-bold text-white">{agent.tasks}</div>
38
+ </div>
39
+ </div>
40
+
41
+ <div className="grid grid-cols-2 gap-4">
42
+ <div>
43
+ <div className="flex items-center justify-between mb-1.5">
44
+ <span className="text-xs text-slate-500">Efficiency</span>
45
+ <span className="text-xs font-bold" style={{ color: agent.color }}>{agent.efficiency}%</span>
46
+ </div>
47
+ <div className="progress-bar">
48
+ <div className="progress-fill" style={{ width: `${agent.efficiency}%`, background: `linear-gradient(90deg, ${agent.color}60, ${agent.color})` }} />
49
+ </div>
50
+ </div>
51
+ <div>
52
+ <div className="flex items-center justify-between mb-1.5">
53
+ <span className="text-xs text-slate-500">Uptime</span>
54
+ <span className="text-xs font-bold text-cyan-400">{agent.uptime}%</span>
55
+ </div>
56
+ <div className="progress-bar">
57
+ <div className="progress-fill" style={{ width: `${agent.uptime}%`, background: 'linear-gradient(90deg, #22d3ee60, #22d3ee)' }} />
58
+ </div>
59
+ </div>
60
+ </div>
61
+
62
+ <div className="flex gap-2 mt-4">
63
+ <button className="flex-1 py-2 rounded-xl text-xs font-semibold transition-all hover:opacity-90"
64
+ style={{ background: `${agent.color}18`, border: `1px solid ${agent.color}30`, color: agent.color }}>
65
+ View Details
66
+ </button>
67
+ <button className="flex-1 py-2 rounded-xl text-xs font-semibold transition-all hover:opacity-90"
68
+ style={{ background: 'rgba(255,255,255,0.05)', border: '1px solid rgba(255,255,255,0.08)', color: 'var(--text-secondary)' }}>
69
+ Assign Task
70
+ </button>
71
+ </div>
72
+ </motion.div>
73
+ )
74
+ }
75
+
76
+ export default function AgentsPage() {
77
+ const [search, setSearch] = useState('')
78
+ const [statusFilter, setStatusFilter] = useState('All')
79
+
80
+ const filtered = AGENTS.filter(a =>
81
+ (statusFilter === 'All' || a.status === statusFilter.toLowerCase()) &&
82
+ (search === '' || a.name.toLowerCase().includes(search.toLowerCase()))
83
+ )
84
+
85
+ const activeCount = AGENTS.filter(a => a.status === 'active').length
86
+ const processingCount = AGENTS.filter(a => a.status === 'processing').length
87
+
88
+ return (
89
+ <div className="h-full overflow-y-auto p-6">
90
+ {/* Header */}
91
+ <div className="flex items-start justify-between mb-6">
92
+ <div>
93
+ <h1 className="text-xl font-bold text-white flex items-center gap-2">
94
+ <Bot size={22} className="text-purple-400" /> Agent Fleet
95
+ </h1>
96
+ <p className="text-sm mt-1 text-slate-500">
97
+ {activeCount} active · {processingCount} processing · {AGENTS.length} total agents deployed
98
+ </p>
99
+ </div>
100
+ <button className="flex items-center gap-2 px-4 py-2.5 rounded-xl text-sm font-semibold text-white transition-all hover:opacity-90"
101
+ style={{ background: 'linear-gradient(135deg, #7c3aed, #4f46e5)', boxShadow: '0 0 20px rgba(124,58,237,0.3)' }}>
102
+ <Plus size={15} /> Deploy Agent
103
+ </button>
104
+ </div>
105
+
106
+ {/* Stats */}
107
+ <div className="grid grid-cols-4 gap-4 mb-6">
108
+ {[
109
+ { label: 'Active', value: activeCount, color: '#22c55e' },
110
+ { label: 'Processing', value: processingCount, color: '#f59e0b' },
111
+ { label: 'Idle', value: AGENTS.filter(a => a.status === 'idle').length, color: '#94a3b8' },
112
+ { label: 'Total Tasks', value: AGENTS.reduce((acc, a) => acc + a.tasks, 0), color: '#6366f1' },
113
+ ].map(stat => (
114
+ <div key={stat.label} className="card p-4 text-center">
115
+ <div className="text-2xl font-bold text-white">{stat.value}</div>
116
+ <div className="text-xs mt-1 font-medium" style={{ color: stat.color }}>{stat.label}</div>
117
+ </div>
118
+ ))}
119
+ </div>
120
+
121
+ {/* Search & Filter */}
122
+ <div className="flex gap-3 mb-6">
123
+ <div className="relative flex-1 max-w-sm">
124
+ <Search size={14} className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-500" />
125
+ <input value={search} onChange={e => setSearch(e.target.value)}
126
+ placeholder="Search agents…"
127
+ className="cmd-input w-full pl-9 pr-4 py-2.5 text-sm" />
128
+ </div>
129
+ <div className="flex gap-2">
130
+ {STATUS_FILTERS.map(f => (
131
+ <button key={f} onClick={() => setStatusFilter(f)}
132
+ className={cn('px-3 py-2 rounded-xl text-xs font-semibold transition-all',
133
+ statusFilter === f
134
+ ? 'bg-purple-600/20 text-purple-300 border border-purple-500/30'
135
+ : 'text-slate-500 hover:text-slate-300 border border-transparent hover:border-white/10'
136
+ )}>
137
+ {f}
138
+ </button>
139
+ ))}
140
+ </div>
141
+ </div>
142
+
143
+ {/* Grid */}
144
+ <motion.div layout className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4">
145
+ {filtered.map((agent, i) => (
146
+ <motion.div key={agent.id} initial={{ opacity: 0, y: 16 }} animate={{ opacity: 1, y: 0 }}
147
+ transition={{ delay: i * 0.05 }}>
148
+ <AgentDetailCard agent={agent} />
149
+ </motion.div>
150
+ ))}
151
+ {filtered.length === 0 && (
152
+ <div className="col-span-3 text-center py-16 text-slate-600">No agents match the filter</div>
153
+ )}
154
+ </motion.div>
155
+ </div>
156
+ )
157
+ }
frontend/components/pages/AnalyticsPage.tsx ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client'
2
+
3
+ import { motion } from 'framer-motion'
4
+ import { BarChart3, TrendingUp, Clock, CheckSquare, Zap } from 'lucide-react'
5
+ import { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer, LineChart, Line, AreaChart, Area } from 'recharts'
6
+
7
+ const WEEKLY_DATA = [
8
+ { day: 'Mon', tasks: 28, efficiency: 91 },
9
+ { day: 'Tue', tasks: 35, efficiency: 94 },
10
+ { day: 'Wed', tasks: 42, efficiency: 96 },
11
+ { day: 'Thu', tasks: 31, efficiency: 89 },
12
+ { day: 'Fri', tasks: 55, efficiency: 98 },
13
+ { day: 'Sat', tasks: 22, efficiency: 92 },
14
+ { day: 'Sun', tasks: 34, efficiency: 97 },
15
+ ]
16
+
17
+ const AGENT_PERF = [
18
+ { name: 'Code', tasks: 62, success: 99 },
19
+ { name: 'Data', tasks: 83, success: 98 },
20
+ { name: 'Research', tasks: 47, success: 92 },
21
+ { name: 'Content', tasks: 31, success: 95 },
22
+ { name: 'Design', tasks: 24, success: 90 },
23
+ ]
24
+
25
+ const customTooltipStyle = {
26
+ background: 'rgba(14,17,33,0.95)',
27
+ border: '1px solid rgba(255,255,255,0.08)',
28
+ borderRadius: 10,
29
+ padding: '8px 12px',
30
+ fontSize: 12,
31
+ color: '#e2e8f0',
32
+ }
33
+
34
+ export default function AnalyticsPage() {
35
+ return (
36
+ <div className="h-full overflow-y-auto p-6">
37
+ <div className="mb-6">
38
+ <h1 className="text-xl font-bold text-white flex items-center gap-2">
39
+ <BarChart3 size={22} className="text-purple-400" /> Analytics
40
+ </h1>
41
+ <p className="text-sm mt-1 text-slate-500">Performance insights across all agents and tasks</p>
42
+ </div>
43
+
44
+ {/* KPI Row */}
45
+ <div className="grid grid-cols-4 gap-4 mb-6">
46
+ {[
47
+ { label: 'Tasks This Week', value: '247', delta: '+37%', color: '#6366f1', icon: CheckSquare },
48
+ { label: 'Avg Efficiency', value: '95.2%', delta: '+3.1%', color: '#22c55e', icon: TrendingUp },
49
+ { label: 'Time Saved', value: '128h', delta: '+55%', color: '#22d3ee', icon: Clock },
50
+ { label: 'Success Rate', value: '98.6%', delta: '+1.2%', color: '#a78bfa', icon: Zap },
51
+ ].map(kpi => (
52
+ <div key={kpi.label} className="card p-4">
53
+ <div className="flex items-center gap-2 mb-3">
54
+ <div className="w-7 h-7 rounded-lg flex items-center justify-center"
55
+ style={{ background: `${kpi.color}15` }}>
56
+ <kpi.icon size={13} style={{ color: kpi.color }} />
57
+ </div>
58
+ <span className="text-xs text-slate-500">{kpi.label}</span>
59
+ </div>
60
+ <div className="text-2xl font-bold text-white">{kpi.value}</div>
61
+ <div className="text-xs mt-1 font-semibold text-green-400">{kpi.delta} vs last week</div>
62
+ </div>
63
+ ))}
64
+ </div>
65
+
66
+ <div className="grid grid-cols-2 gap-4 mb-4">
67
+ {/* Tasks Chart */}
68
+ <div className="card p-5">
69
+ <h3 className="text-sm font-bold text-white mb-4">Weekly Task Completion</h3>
70
+ <ResponsiveContainer width="100%" height={180}>
71
+ <AreaChart data={WEEKLY_DATA}>
72
+ <defs>
73
+ <linearGradient id="taskGrad" x1="0" y1="0" x2="0" y2="1">
74
+ <stop offset="5%" stopColor="#7c3aed" stopOpacity={0.3} />
75
+ <stop offset="95%" stopColor="#7c3aed" stopOpacity={0} />
76
+ </linearGradient>
77
+ </defs>
78
+ <XAxis dataKey="day" tick={{ fill: '#475569', fontSize: 11 }} axisLine={false} tickLine={false} />
79
+ <YAxis tick={{ fill: '#475569', fontSize: 11 }} axisLine={false} tickLine={false} />
80
+ <Tooltip contentStyle={customTooltipStyle} />
81
+ <Area type="monotone" dataKey="tasks" stroke="#8b5cf6" strokeWidth={2} fill="url(#taskGrad)" />
82
+ </AreaChart>
83
+ </ResponsiveContainer>
84
+ </div>
85
+
86
+ {/* Efficiency Chart */}
87
+ <div className="card p-5">
88
+ <h3 className="text-sm font-bold text-white mb-4">Agent Efficiency Scores</h3>
89
+ <ResponsiveContainer width="100%" height={180}>
90
+ <BarChart data={AGENT_PERF} barSize={28}>
91
+ <XAxis dataKey="name" tick={{ fill: '#475569', fontSize: 11 }} axisLine={false} tickLine={false} />
92
+ <YAxis domain={[80, 100]} tick={{ fill: '#475569', fontSize: 11 }} axisLine={false} tickLine={false} />
93
+ <Tooltip contentStyle={customTooltipStyle} />
94
+ <Bar dataKey="success" fill="#22d3ee" radius={[4, 4, 0, 0]} />
95
+ </BarChart>
96
+ </ResponsiveContainer>
97
+ </div>
98
+ </div>
99
+
100
+ {/* Agent Performance Table */}
101
+ <div className="card p-5">
102
+ <h3 className="text-sm font-bold text-white mb-4">Agent Performance Breakdown</h3>
103
+ <div className="space-y-3">
104
+ {AGENT_PERF.map(agent => (
105
+ <div key={agent.name} className="flex items-center gap-4">
106
+ <span className="text-sm text-slate-400 w-24">{agent.name}</span>
107
+ <div className="flex-1 progress-bar">
108
+ <motion.div className="progress-fill"
109
+ initial={{ width: 0 }} animate={{ width: `${agent.success}%` }}
110
+ transition={{ duration: 1 }}
111
+ style={{ background: 'linear-gradient(90deg, #7c3aed60, #22d3ee)' }} />
112
+ </div>
113
+ <span className="text-xs font-bold text-white w-12 text-right">{agent.success}%</span>
114
+ <span className="text-xs text-slate-600 w-16 text-right">{agent.tasks} tasks</span>
115
+ </div>
116
+ ))}
117
+ </div>
118
+ </div>
119
+ </div>
120
+ )
121
+ }
frontend/components/pages/DashboardPage.tsx ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client'
2
+
3
+ import { motion } from 'framer-motion'
4
+ import { Bot, CheckSquare, Clock, TrendingUp, ChevronRight } from 'lucide-react'
5
+ import MetricCard from '@/components/dashboard/MetricCard'
6
+ import AgentFleetCard from '@/components/dashboard/AgentFleetCard'
7
+ import ActivityFeed from '@/components/dashboard/ActivityFeed'
8
+ import SystemResources from '@/components/dashboard/SystemResources'
9
+ import MissionInput from '@/components/dashboard/MissionInput'
10
+ import GodModeCard from '@/components/dashboard/GodModeCard'
11
+ import { useAppStore, AGENTS } from '@/store/useAppStore'
12
+ import CommandCenter from '@/components/dashboard/CommandCenter'
13
+
14
+ const METRICS = [
15
+ { label: 'Total Agents', value: 12, trend: '+2 this week', trendUp: true, icon: <Bot size={18} />, iconColor: '#6366f1' },
16
+ { label: 'Tasks Completed', value: 247, trend: '+37% this week', trendUp: true, icon: <CheckSquare size={18} />, iconColor: '#22c55e' },
17
+ { label: 'Time Saved', value: 128, unit: 'h', trend: '+55% this week', trendUp: true, icon: <Clock size={18} />, iconColor: '#22d3ee' },
18
+ { label: 'Success Rate', value: '98.6', unit: '%', trend: '1.2% this week', trendUp: true, icon: <TrendingUp size={18} />, iconColor: '#a78bfa' },
19
+ ]
20
+
21
+ export default function DashboardPage() {
22
+ const { setCurrentPage } = useAppStore()
23
+ const featuredAgents = AGENTS.slice(0, 6)
24
+
25
+ return (
26
+ <div className="h-full overflow-y-auto">
27
+ <div className="flex h-full">
28
+ {/* Main content */}
29
+ <div className="flex-1 min-w-0 p-6 overflow-y-auto">
30
+
31
+ {/* Welcome Header */}
32
+ <motion.div initial={{ opacity: 0, y: -8 }} animate={{ opacity: 1, y: 0 }} className="mb-6">
33
+ <h1 className="text-2xl font-bold text-white">
34
+ Welcome back, <span className="gradient-text-purple">Creator.</span>
35
+ </h1>
36
+ <p className="text-sm mt-1" style={{ color: 'var(--text-secondary)' }}>
37
+ Where Intelligence, Autonomy and Execution become{' '}
38
+ <span className="gradient-text font-semibold">Divine.</span>
39
+ </p>
40
+ </motion.div>
41
+
42
+ {/* Metrics Row */}
43
+ <div className="grid grid-cols-2 xl:grid-cols-4 gap-4 mb-6">
44
+ {METRICS.map((m, i) => (
45
+ <MetricCard key={m.label} {...m} delay={i * 0.06} />
46
+ ))}
47
+ </div>
48
+
49
+ {/* Mission Input */}
50
+ <div className="mb-6">
51
+ <MissionInput />
52
+ </div>
53
+
54
+ {/* Agent Fleet */}
55
+ <div className="mb-6">
56
+ <div className="flex items-center justify-between mb-4">
57
+ <div>
58
+ <h2 className="text-sm font-bold text-white">Agent Fleet</h2>
59
+ <p className="text-xs mt-0.5" style={{ color: 'var(--text-secondary)' }}>Manage your autonomous workforce</p>
60
+ </div>
61
+ <button onClick={() => setCurrentPage('agents')}
62
+ className="flex items-center gap-1 text-xs font-medium text-purple-400 hover:text-purple-300 transition-colors">
63
+ View all agents <ChevronRight size={13} />
64
+ </button>
65
+ </div>
66
+ <div className="grid grid-cols-2 xl:grid-cols-3 gap-3">
67
+ {featuredAgents.map((agent, i) => (
68
+ <AgentFleetCard key={agent.id} agent={agent} delay={0.1 + i * 0.05}
69
+ onClick={() => setCurrentPage('agents')} />
70
+ ))}
71
+ </div>
72
+ </div>
73
+
74
+ {/* Command Center */}
75
+ <CommandCenter />
76
+ </div>
77
+
78
+ {/* Right Panel */}
79
+ <div className="w-72 xl:w-80 flex-shrink-0 border-l p-4 space-y-4 overflow-y-auto hide-lg"
80
+ style={{ borderColor: 'var(--border)' }}>
81
+
82
+ <GodModeCard />
83
+
84
+ {/* Recent Activity */}
85
+ <div className="card p-4">
86
+ <div className="flex items-center justify-between mb-3">
87
+ <h3 className="text-sm font-bold text-white">Recent Activity</h3>
88
+ <button className="text-xs text-purple-400 hover:text-purple-300 transition-colors">View all</button>
89
+ </div>
90
+ <ActivityFeed max={5} />
91
+ </div>
92
+
93
+ {/* System Resources */}
94
+ <div className="card p-4">
95
+ <div className="flex items-center justify-between mb-4">
96
+ <h3 className="text-sm font-bold text-white">System Resources</h3>
97
+ <button className="text-xs text-purple-400 hover:text-purple-300 transition-colors">Details</button>
98
+ </div>
99
+ <SystemResources />
100
+ </div>
101
+
102
+ {/* Branding Footer */}
103
+ <div className="px-1 py-2 text-center">
104
+ <div className="text-xs font-bold text-slate-600 mb-0.5">manus + genspark</div>
105
+ <div className="text-xs" style={{ color: 'var(--text-muted)' }}>
106
+ Human Creativity × AI Capability = Divine Impact
107
+ </div>
108
+ </div>
109
+ </div>
110
+ </div>
111
+ </div>
112
+ )
113
+ }
frontend/components/pages/KnowledgePage.tsx ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client'
2
+
3
+ import { motion } from 'framer-motion'
4
+ import { BookOpen, FileText, Globe, Code2, BarChart3, Search, Plus } from 'lucide-react'
5
+
6
+ const KNOWLEDGE_BASES = [
7
+ { id: 1, name: 'Product Documentation', desc: 'Internal product specs and API docs', docs: 342, icon: FileText, color: '#6366f1', updated: '1h ago' },
8
+ { id: 2, name: 'Market Intelligence', desc: 'Industry reports and competitor analysis', docs: 87, icon: Globe, color: '#22d3ee', updated: '2h ago' },
9
+ { id: 3, name: 'Codebase Knowledge', desc: 'Source code patterns and architecture', docs: 1240, icon: Code2, color: '#34d399', updated: '30m ago' },
10
+ { id: 4, name: 'Analytics Data', desc: 'Historical metrics and performance data', docs: 512, icon: BarChart3, color: '#a78bfa', updated: '15m ago' },
11
+ { id: 5, name: 'Research Library', desc: 'Academic papers and research synthesis', docs: 234, icon: BookOpen, color: '#f59e0b', updated: '3h ago' },
12
+ ]
13
+
14
+ export default function KnowledgePage() {
15
+ return (
16
+ <div className="h-full overflow-y-auto p-6">
17
+ <div className="flex items-center justify-between mb-6">
18
+ <div>
19
+ <h1 className="text-xl font-bold text-white flex items-center gap-2">
20
+ <BookOpen size={22} className="text-purple-400" /> Knowledge Base
21
+ </h1>
22
+ <p className="text-sm mt-1 text-slate-500">2,415 documents indexed across 5 knowledge bases</p>
23
+ </div>
24
+ <div className="flex items-center gap-3">
25
+ <div className="relative">
26
+ <Search size={14} className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-500" />
27
+ <input placeholder="Search knowledge…" className="cmd-input pl-9 pr-4 py-2.5 text-sm w-56" />
28
+ </div>
29
+ <button className="flex items-center gap-2 px-4 py-2.5 rounded-xl text-sm font-semibold text-white hover:opacity-90 transition-all"
30
+ style={{ background: 'linear-gradient(135deg, #7c3aed, #4f46e5)', boxShadow: '0 0 20px rgba(124,58,237,0.3)' }}>
31
+ <Plus size={15} /> Add Source
32
+ </button>
33
+ </div>
34
+ </div>
35
+
36
+ <div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4">
37
+ {KNOWLEDGE_BASES.map((kb, i) => (
38
+ <motion.div key={kb.id} initial={{ opacity: 0, y: 12 }} animate={{ opacity: 1, y: 0 }}
39
+ transition={{ delay: i * 0.07 }} className="card p-5 cursor-pointer group relative overflow-hidden">
40
+ <div className="absolute top-0 left-0 right-0 h-[2px]"
41
+ style={{ background: `linear-gradient(90deg, ${kb.color}, transparent)` }} />
42
+
43
+ <div className="flex items-start gap-4 mb-4">
44
+ <div className="w-11 h-11 rounded-2xl flex items-center justify-center flex-shrink-0"
45
+ style={{ background: `${kb.color}15`, border: `1px solid ${kb.color}25` }}>
46
+ <kb.icon size={18} style={{ color: kb.color }} />
47
+ </div>
48
+ <div className="flex-1">
49
+ <h3 className="font-semibold text-white group-hover:text-purple-300 transition-colors">{kb.name}</h3>
50
+ <p className="text-xs mt-1 text-slate-500">{kb.desc}</p>
51
+ </div>
52
+ </div>
53
+
54
+ <div className="flex items-center justify-between mb-2">
55
+ <span className="text-xs text-slate-500">Documents</span>
56
+ <span className="text-xs font-bold text-white">{kb.docs.toLocaleString()}</span>
57
+ </div>
58
+ <div className="progress-bar mb-3">
59
+ <div className="progress-fill" style={{ width: `${Math.min(100, kb.docs / 15)}%`, background: `linear-gradient(90deg, ${kb.color}50, ${kb.color})` }} />
60
+ </div>
61
+ <div className="text-xs text-slate-600">Updated {kb.updated}</div>
62
+ </motion.div>
63
+ ))}
64
+
65
+ {/* Add Knowledge Base Card */}
66
+ <motion.div initial={{ opacity: 0, y: 12 }} animate={{ opacity: 1, y: 0 }}
67
+ transition={{ delay: KNOWLEDGE_BASES.length * 0.07 }}
68
+ className="card p-5 cursor-pointer group flex flex-col items-center justify-center min-h-[160px] border-dashed"
69
+ style={{ borderStyle: 'dashed', borderColor: 'rgba(124,58,237,0.2)', background: 'rgba(124,58,237,0.03)' }}>
70
+ <div className="w-10 h-10 rounded-xl flex items-center justify-center mb-3 group-hover:scale-110 transition-transform"
71
+ style={{ background: 'rgba(124,58,237,0.1)', border: '1px solid rgba(124,58,237,0.2)' }}>
72
+ <Plus size={18} className="text-purple-400" />
73
+ </div>
74
+ <span className="text-sm font-medium text-purple-400 group-hover:text-purple-300">Add Knowledge Base</span>
75
+ <span className="text-xs text-slate-600 mt-1">Connect a new data source</span>
76
+ </motion.div>
77
+ </div>
78
+ </div>
79
+ )
80
+ }
frontend/components/pages/MemoryPage.tsx ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client'
2
+
3
+ import { motion } from 'framer-motion'
4
+ import { Brain, Database, Clock, Search, Tag } from 'lucide-react'
5
+
6
+ const MEMORIES = [
7
+ { id: 1, title: 'Market Research — SaaS Competitors Q4', tags: ['research', 'market'], date: '2h ago', size: '48 KB', type: 'document', color: '#6366f1' },
8
+ { id: 2, title: 'API Authentication Module Design', tags: ['code', 'architecture'], date: '5h ago', size: '12 KB', type: 'code', color: '#34d399' },
9
+ { id: 3, title: 'Product Positioning Statement v3', tags: ['content', 'strategy'], date: '1d ago', size: '8 KB', type: 'text', color: '#a78bfa' },
10
+ { id: 4, title: 'Database Schema — Users & Sessions', tags: ['code', 'database'], date: '2d ago', size: '22 KB', type: 'code', color: '#22d3ee' },
11
+ { id: 5, title: 'Brand Voice Guidelines 2025', tags: ['content', 'brand'], date: '3d ago', size: '35 KB', type: 'document', color: '#f472b6' },
12
+ { id: 6, title: 'Competitor Analysis Matrix', tags: ['research', 'strategy'], date: '4d ago', size: '61 KB', type: 'document', color: '#f59e0b' },
13
+ ]
14
+
15
+ export default function MemoryPage() {
16
+ return (
17
+ <div className="h-full overflow-y-auto p-6">
18
+ <div className="flex items-center justify-between mb-6">
19
+ <div>
20
+ <h1 className="text-xl font-bold text-white flex items-center gap-2">
21
+ <Brain size={22} className="text-purple-400" /> Memory
22
+ </h1>
23
+ <p className="text-sm mt-1 text-slate-500">Persistent knowledge storage · 4,200 indexed documents</p>
24
+ </div>
25
+ <div className="flex items-center gap-2">
26
+ <div className="relative">
27
+ <Search size={14} className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-500" />
28
+ <input placeholder="Search memories…" className="cmd-input pl-9 pr-4 py-2.5 text-sm w-56" />
29
+ </div>
30
+ </div>
31
+ </div>
32
+
33
+ {/* Stats */}
34
+ <div className="grid grid-cols-3 gap-4 mb-6">
35
+ {[
36
+ { label: 'Total Memories', value: '4,200', icon: Database, color: '#6366f1' },
37
+ { label: 'Storage Used', value: '2.4 GB', icon: Database, color: '#22d3ee' },
38
+ { label: 'Last Indexed', value: '3m ago', icon: Clock, color: '#a78bfa' },
39
+ ].map(stat => (
40
+ <div key={stat.label} className="card p-4 flex items-center gap-3">
41
+ <div className="w-9 h-9 rounded-xl flex items-center justify-center flex-shrink-0"
42
+ style={{ background: `${stat.color}15` }}>
43
+ <stat.icon size={16} style={{ color: stat.color }} />
44
+ </div>
45
+ <div>
46
+ <div className="text-lg font-bold text-white">{stat.value}</div>
47
+ <div className="text-xs text-slate-500">{stat.label}</div>
48
+ </div>
49
+ </div>
50
+ ))}
51
+ </div>
52
+
53
+ {/* Memory Grid */}
54
+ <div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-3">
55
+ {MEMORIES.map((m, i) => (
56
+ <motion.div key={m.id} initial={{ opacity: 0, y: 12 }} animate={{ opacity: 1, y: 0 }}
57
+ transition={{ delay: i * 0.06 }} className="card p-4 cursor-pointer group">
58
+ <div className="flex items-start gap-3 mb-3">
59
+ <div className="w-9 h-9 rounded-xl flex items-center justify-center flex-shrink-0"
60
+ style={{ background: `${m.color}15`, border: `1px solid ${m.color}20` }}>
61
+ <Database size={14} style={{ color: m.color }} />
62
+ </div>
63
+ <div className="flex-1 min-w-0">
64
+ <h3 className="text-sm font-semibold text-white leading-snug line-clamp-2 group-hover:text-purple-300 transition-colors">
65
+ {m.title}
66
+ </h3>
67
+ <div className="flex items-center gap-2 mt-1 text-xs text-slate-600">
68
+ <Clock size={10} /> {m.date} · {m.size}
69
+ </div>
70
+ </div>
71
+ </div>
72
+ <div className="flex flex-wrap gap-1.5">
73
+ {m.tags.map(tag => (
74
+ <span key={tag} className="flex items-center gap-1 text-xs px-2 py-0.5 rounded-full"
75
+ style={{ background: `${m.color}10`, color: m.color, border: `1px solid ${m.color}20` }}>
76
+ <Tag size={9} /> {tag}
77
+ </span>
78
+ ))}
79
+ </div>
80
+ </motion.div>
81
+ ))}
82
+ </div>
83
+ </div>
84
+ )
85
+ }
frontend/components/pages/SettingsPage.tsx ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client'
2
+
3
+ import { useState } from 'react'
4
+ import { motion } from 'framer-motion'
5
+ import { Settings, Key, Zap, Bell, Shield, Cpu, ChevronRight, Check, Eye, EyeOff } from 'lucide-react'
6
+
7
+ const PROVIDER_CONFIGS = [
8
+ { name: 'Gemini', model: 'gemini-2.0-flash', status: 'active', color: '#22d3ee', keys: 6, type: 'Primary' },
9
+ { name: 'Sambanova', model: 'Meta-Llama-3.3-70B', status: 'active', color: '#a78bfa', keys: 9, type: 'Primary' },
10
+ { name: 'GitHub Models', model: 'gpt-4o', status: 'active', color: '#34d399', keys: 9, type: 'Primary' },
11
+ ]
12
+
13
+ const SETTING_SECTIONS = [
14
+ { id: 'providers', label: 'AI Providers', icon: Cpu },
15
+ { id: 'keys', label: 'API Keys', icon: Key },
16
+ { id: 'notifications', label: 'Notifications', icon: Bell },
17
+ { id: 'security', label: 'Security', icon: Shield },
18
+ ]
19
+
20
+ function ApiKeyField({ label, value, color }: { label: string; value: string; color: string }) {
21
+ const [show, setShow] = useState(false)
22
+ const display = show ? value : value.slice(0, 8) + '••••••••••••••••' + value.slice(-4)
23
+ return (
24
+ <div className="flex items-center gap-3 px-4 py-3 rounded-xl hover:bg-white/[0.02] transition-colors" style={{ border: '1px solid rgba(255,255,255,0.06)' }}>
25
+ <div className="w-2 h-2 rounded-full flex-shrink-0" style={{ background: color }} />
26
+ <span className="text-sm text-slate-400 w-28 flex-shrink-0">{label}</span>
27
+ <code className="text-xs flex-1 text-slate-300 font-mono">{display}</code>
28
+ <button onClick={() => setShow(!show)} className="text-slate-600 hover:text-slate-400 transition-colors">
29
+ {show ? <EyeOff size={14} /> : <Eye size={14} />}
30
+ </button>
31
+ </div>
32
+ )
33
+ }
34
+
35
+ export default function SettingsPage() {
36
+ const [activeSection, setActiveSection] = useState('providers')
37
+ const [godModeToggle, setGodModeToggle] = useState(true)
38
+ const [autoRotate, setAutoRotate] = useState(true)
39
+ const [streamMode, setStreamMode] = useState(true)
40
+
41
+ return (
42
+ <div className="h-full overflow-y-auto p-6">
43
+ <div className="mb-6">
44
+ <h1 className="text-xl font-bold text-white flex items-center gap-2">
45
+ <Settings size={22} className="text-purple-400" /> Settings
46
+ </h1>
47
+ <p className="text-sm mt-1 text-slate-500">Configure God Agent OS — AI providers, keys, and preferences</p>
48
+ </div>
49
+
50
+ <div className="flex gap-6">
51
+ {/* Sidebar Nav */}
52
+ <div className="w-48 flex-shrink-0 space-y-1">
53
+ {SETTING_SECTIONS.map(sec => (
54
+ <button key={sec.id} onClick={() => setActiveSection(sec.id)}
55
+ className={`nav-item w-full text-left ${activeSection === sec.id ? 'active' : ''}`}>
56
+ <sec.icon size={15} />
57
+ {sec.label}
58
+ </button>
59
+ ))}
60
+ </div>
61
+
62
+ {/* Content */}
63
+ <div className="flex-1 min-w-0 space-y-4">
64
+
65
+ {activeSection === 'providers' && (
66
+ <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }}>
67
+ <h2 className="text-sm font-bold text-white mb-4">AI Provider Configuration</h2>
68
+
69
+ <div className="space-y-3 mb-6">
70
+ {PROVIDER_CONFIGS.map(p => (
71
+ <div key={p.name} className="card p-4 flex items-center gap-4">
72
+ <div className="w-10 h-10 rounded-xl flex items-center justify-center text-lg flex-shrink-0"
73
+ style={{ background: `${p.color}15`, border: `1px solid ${p.color}25` }}>
74
+ <Cpu size={16} style={{ color: p.color }} />
75
+ </div>
76
+ <div className="flex-1">
77
+ <div className="flex items-center gap-2">
78
+ <span className="font-semibold text-white text-sm">{p.name}</span>
79
+ <span className="text-xs px-2 py-0.5 rounded-full font-semibold"
80
+ style={{ background: `${p.color}15`, color: p.color }}>{p.type}</span>
81
+ </div>
82
+ <div className="text-xs text-slate-500 mt-0.5">{p.model} · {p.keys} keys configured</div>
83
+ </div>
84
+ <div className="flex items-center gap-2">
85
+ <div className="w-2 h-2 rounded-full bg-green-400" />
86
+ <span className="text-xs text-green-400 font-medium">Active</span>
87
+ <Check size={14} className="text-green-400" />
88
+ </div>
89
+ </div>
90
+ ))}
91
+ </div>
92
+
93
+ {/* Toggle settings */}
94
+ <div className="space-y-3">
95
+ {[
96
+ { label: 'God Mode', desc: 'Full autonomous operation mode', state: godModeToggle, toggle: setGodModeToggle, color: '#a78bfa' },
97
+ { label: 'Auto-Rotate Keys', desc: 'Automatically rotate API keys on rate limit', state: autoRotate, toggle: setAutoRotate, color: '#22d3ee' },
98
+ { label: 'Stream Mode', desc: 'Real-time streaming output from all providers', state: streamMode, toggle: setStreamMode, color: '#34d399' },
99
+ ].map(item => (
100
+ <div key={item.label} className="card p-4 flex items-center gap-4">
101
+ <div className="flex-1">
102
+ <div className="text-sm font-semibold text-white">{item.label}</div>
103
+ <div className="text-xs text-slate-500 mt-0.5">{item.desc}</div>
104
+ </div>
105
+ <button onClick={() => item.toggle(!item.state)}
106
+ className="w-10 h-5.5 rounded-full relative transition-all flex-shrink-0"
107
+ style={{
108
+ background: item.state ? item.color : 'rgba(255,255,255,0.1)',
109
+ width: 44, height: 24
110
+ }}>
111
+ <div className="absolute top-0.5 w-5 h-5 rounded-full bg-white shadow transition-all"
112
+ style={{ left: item.state ? 21 : 2 }} />
113
+ </button>
114
+ </div>
115
+ ))}
116
+ </div>
117
+ </motion.div>
118
+ )}
119
+
120
+ {activeSection === 'keys' && (
121
+ <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }}>
122
+ <h2 className="text-sm font-bold text-white mb-4">API Key Management</h2>
123
+ <div className="card p-5 space-y-2">
124
+ <ApiKeyField label="Gemini Key 1" value="GEMINI_KEY_1_CONFIGURED" color="#22d3ee" />
125
+ <ApiKeyField label="Gemini Key 2" value="GEMINI_KEY_2_CONFIGURED" color="#22d3ee" />
126
+ <ApiKeyField label="Sambanova Key 1" value="SAMBANOVA_KEY_1_CONFIGURED" color="#a78bfa" />
127
+ <ApiKeyField label="GitHub Key 1" value="GITHUB_KEY_1_CONFIGURED" color="#34d399" />
128
+ </div>
129
+ <p className="text-xs text-slate-600 mt-3">Keys are stored securely in environment variables. Never commit to version control.</p>
130
+ </motion.div>
131
+ )}
132
+
133
+ {activeSection === 'notifications' && (
134
+ <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }}>
135
+ <h2 className="text-sm font-bold text-white mb-4">Notification Preferences</h2>
136
+ <div className="card p-5">
137
+ <p className="text-sm text-slate-500">Configure notification settings for agent activity, task completion, and system alerts.</p>
138
+ </div>
139
+ </motion.div>
140
+ )}
141
+
142
+ {activeSection === 'security' && (
143
+ <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }}>
144
+ <h2 className="text-sm font-bold text-white mb-4">Security Settings</h2>
145
+ <div className="card p-5">
146
+ <p className="text-sm text-slate-500">Manage authentication, access control, and audit logging.</p>
147
+ </div>
148
+ </motion.div>
149
+ )}
150
+ </div>
151
+ </div>
152
+ </div>
153
+ )
154
+ }
frontend/components/pages/TasksPage.tsx ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client'
2
+
3
+ import { useState } from 'react'
4
+ import { motion } from 'framer-motion'
5
+ import { CheckSquare, Clock, Loader2, AlertCircle, Plus, ChevronRight } from 'lucide-react'
6
+ import { TASKS, Task } from '@/store/useAppStore'
7
+ import { cn } from '@/lib/utils'
8
+
9
+ const STATUS_CONFIG = {
10
+ running: { color: '#6366f1', label: 'Running', icon: Loader2, bg: 'rgba(99,102,241,0.12)' },
11
+ completed: { color: '#22c55e', label: 'Completed', icon: CheckSquare, bg: 'rgba(34,197,94,0.12)' },
12
+ pending: { color: '#94a3b8', label: 'Pending', icon: Clock, bg: 'rgba(148,163,184,0.1)' },
13
+ failed: { color: '#ef4444', label: 'Failed', icon: AlertCircle, bg: 'rgba(239,68,68,0.12)' },
14
+ }
15
+
16
+ function TaskRow({ task, delay }: { task: Task; delay: number }) {
17
+ const cfg = STATUS_CONFIG[task.status]
18
+ const Icon = cfg.icon
19
+ const isRunning = task.status === 'running'
20
+ const agentColor = '#6366f1'
21
+
22
+ return (
23
+ <motion.div
24
+ initial={{ opacity: 0, x: -12 }} animate={{ opacity: 1, x: 0 }}
25
+ transition={{ delay, duration: 0.3 }}
26
+ className="card p-4 group hover:border-white/10 transition-all cursor-pointer"
27
+ >
28
+ <div className="flex items-center gap-4">
29
+ <div className="w-8 h-8 rounded-xl flex items-center justify-center flex-shrink-0"
30
+ style={{ background: cfg.bg }}>
31
+ <Icon size={14} style={{ color: cfg.color }} className={isRunning ? 'animate-spin' : ''} />
32
+ </div>
33
+
34
+ <div className="flex-1 min-w-0">
35
+ <div className="flex items-center gap-2 mb-1">
36
+ <span className="text-sm font-semibold text-white truncate">{task.title}</span>
37
+ <span className="text-xs px-2 py-0.5 rounded-full flex-shrink-0 font-medium"
38
+ style={{ background: cfg.bg, color: cfg.color }}>{cfg.label}</span>
39
+ </div>
40
+ <div className="flex items-center gap-3">
41
+ <span className="text-xs text-slate-500">{task.agent}</span>
42
+ <span className="text-xs text-slate-600">· {task.createdAt}</span>
43
+ {task.completedAt && <span className="text-xs text-green-500">Completed {task.completedAt}</span>}
44
+ </div>
45
+ {task.status === 'running' && (
46
+ <div className="mt-2 flex items-center gap-2">
47
+ <div className="flex-1 progress-bar">
48
+ <motion.div className="progress-fill"
49
+ initial={{ width: 0 }} animate={{ width: `${task.progress}%` }}
50
+ transition={{ duration: 1, delay: 0.2 }}
51
+ style={{ background: 'linear-gradient(90deg, #6366f160, #6366f1)' }} />
52
+ </div>
53
+ <span className="text-xs font-bold text-purple-400 w-8 text-right">{task.progress}%</span>
54
+ </div>
55
+ )}
56
+ </div>
57
+
58
+ <ChevronRight size={15} className="text-slate-700 group-hover:text-purple-400 transition-colors flex-shrink-0" />
59
+ </div>
60
+ </motion.div>
61
+ )
62
+ }
63
+
64
+ export default function TasksPage() {
65
+ const [filter, setFilter] = useState<'all' | Task['status']>('all')
66
+ const filtered = filter === 'all' ? TASKS : TASKS.filter(t => t.status === filter)
67
+
68
+ const counts = {
69
+ all: TASKS.length,
70
+ running: TASKS.filter(t => t.status === 'running').length,
71
+ completed: TASKS.filter(t => t.status === 'completed').length,
72
+ pending: TASKS.filter(t => t.status === 'pending').length,
73
+ failed: TASKS.filter(t => t.status === 'failed').length,
74
+ }
75
+
76
+ return (
77
+ <div className="h-full overflow-y-auto p-6">
78
+ <div className="flex items-center justify-between mb-6">
79
+ <div>
80
+ <h1 className="text-xl font-bold text-white flex items-center gap-2">
81
+ <CheckSquare size={22} className="text-purple-400" /> Tasks
82
+ </h1>
83
+ <p className="text-sm mt-1 text-slate-500">{counts.running} running · {counts.pending} pending · {counts.completed} completed</p>
84
+ </div>
85
+ <button className="flex items-center gap-2 px-4 py-2.5 rounded-xl text-sm font-semibold text-white hover:opacity-90 transition-all"
86
+ style={{ background: 'linear-gradient(135deg, #7c3aed, #4f46e5)', boxShadow: '0 0 20px rgba(124,58,237,0.3)' }}>
87
+ <Plus size={15} /> New Task
88
+ </button>
89
+ </div>
90
+
91
+ {/* Status Tabs */}
92
+ <div className="flex gap-2 mb-6 flex-wrap">
93
+ {(['all', 'running', 'completed', 'pending', 'failed'] as const).map(s => (
94
+ <button key={s} onClick={() => setFilter(s)}
95
+ className={cn('px-4 py-2 rounded-xl text-xs font-semibold capitalize transition-all',
96
+ filter === s
97
+ ? 'bg-purple-600/20 text-purple-300 border border-purple-500/30'
98
+ : 'text-slate-500 border border-transparent hover:border-white/10 hover:text-slate-300'
99
+ )}>
100
+ {s} ({counts[s]})
101
+ </button>
102
+ ))}
103
+ </div>
104
+
105
+ {/* Summary Stats */}
106
+ <div className="grid grid-cols-4 gap-4 mb-6">
107
+ {Object.entries(STATUS_CONFIG).map(([status, cfg]) => (
108
+ <div key={status} className="card p-4">
109
+ <div className="text-2xl font-bold text-white">{counts[status as keyof typeof counts] || 0}</div>
110
+ <div className="text-xs mt-1 font-semibold" style={{ color: cfg.color }}>{cfg.label}</div>
111
+ </div>
112
+ ))}
113
+ </div>
114
+
115
+ {/* Tasks List */}
116
+ <div className="space-y-3">
117
+ {filtered.map((task, i) => <TaskRow key={task.id} task={task} delay={i * 0.05} />)}
118
+ {filtered.length === 0 && (
119
+ <div className="text-center py-16 text-slate-600">No tasks with this filter</div>
120
+ )}
121
+ </div>
122
+ </div>
123
+ )
124
+ }
frontend/components/pages/WorkflowsPage.tsx ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client'
2
+
3
+ import { motion } from 'framer-motion'
4
+ import { GitBranch, Play, Pause, Plus, Clock, CheckCircle2, Zap } from 'lucide-react'
5
+
6
+ const WORKFLOWS = [
7
+ { id: 1, name: 'Daily Research Pipeline', desc: 'Research → Analyze → Summarize → Report', status: 'active', runs: 47, lastRun: '2h ago', color: '#6366f1', schedule: 'Daily 9:00 AM' },
8
+ { id: 2, name: 'Code Review Automation', desc: 'PR Detect → AI Review → Comment → Approve', status: 'active', runs: 23, lastRun: '1h ago', color: '#34d399', schedule: 'On PR event' },
9
+ { id: 3, name: 'Content Generation Loop', desc: 'Research → Write → Review → Publish', status: 'paused', runs: 12, lastRun: '1d ago', color: '#a78bfa', schedule: 'Weekly' },
10
+ { id: 4, name: 'Deploy Pipeline', desc: 'Build → Test → Stage → Deploy → Monitor', status: 'active', runs: 89, lastRun: '30m ago', color: '#22d3ee', schedule: 'On push to main' },
11
+ { id: 5, name: 'Market Intelligence', desc: 'Scrape → Parse → Analyze → Alert', status: 'idle', runs: 7, lastRun: '3d ago', color: '#f59e0b', schedule: 'Weekly' },
12
+ ]
13
+
14
+ const STATUS_CONFIG = {
15
+ active: { color: '#22c55e', label: 'Active' },
16
+ paused: { color: '#f59e0b', label: 'Paused' },
17
+ idle: { color: '#94a3b8', label: 'Idle' },
18
+ }
19
+
20
+ export default function WorkflowsPage() {
21
+ return (
22
+ <div className="h-full overflow-y-auto p-6">
23
+ <div className="flex items-center justify-between mb-6">
24
+ <div>
25
+ <h1 className="text-xl font-bold text-white flex items-center gap-2">
26
+ <GitBranch size={22} className="text-purple-400" /> Workflows
27
+ </h1>
28
+ <p className="text-sm mt-1 text-slate-500">Autonomous multi-agent pipelines · {WORKFLOWS.filter(w => w.status === 'active').length} running</p>
29
+ </div>
30
+ <button className="flex items-center gap-2 px-4 py-2.5 rounded-xl text-sm font-semibold text-white hover:opacity-90 transition-all"
31
+ style={{ background: 'linear-gradient(135deg, #7c3aed, #4f46e5)', boxShadow: '0 0 20px rgba(124,58,237,0.3)' }}>
32
+ <Plus size={15} /> New Workflow
33
+ </button>
34
+ </div>
35
+
36
+ <div className="space-y-3">
37
+ {WORKFLOWS.map((wf, i) => {
38
+ const sc = STATUS_CONFIG[wf.status as keyof typeof STATUS_CONFIG]
39
+ return (
40
+ <motion.div key={wf.id} initial={{ opacity: 0, x: -12 }} animate={{ opacity: 1, x: 0 }}
41
+ transition={{ delay: i * 0.07 }} className="card p-5 group cursor-pointer">
42
+ <div className="flex items-center gap-4">
43
+ <div className="w-10 h-10 rounded-xl flex items-center justify-center flex-shrink-0"
44
+ style={{ background: `${wf.color}15`, border: `1px solid ${wf.color}25` }}>
45
+ <GitBranch size={18} style={{ color: wf.color }} />
46
+ </div>
47
+
48
+ <div className="flex-1 min-w-0">
49
+ <div className="flex items-center gap-2 mb-1">
50
+ <h3 className="font-semibold text-white">{wf.name}</h3>
51
+ <span className="text-xs px-2 py-0.5 rounded-full font-medium"
52
+ style={{ background: `${sc.color}12`, color: sc.color }}>
53
+ {sc.label}
54
+ </span>
55
+ </div>
56
+ <p className="text-xs text-slate-500 font-mono">{wf.desc}</p>
57
+ <div className="flex items-center gap-4 mt-2 text-xs text-slate-600">
58
+ <span className="flex items-center gap-1"><Zap size={10} /> {wf.runs} runs</span>
59
+ <span className="flex items-center gap-1"><Clock size={10} /> {wf.lastRun}</span>
60
+ <span>{wf.schedule}</span>
61
+ </div>
62
+ </div>
63
+
64
+ <div className="flex gap-2">
65
+ <button className="w-8 h-8 rounded-xl flex items-center justify-center transition-all hover:bg-white/10"
66
+ style={{ border: '1px solid rgba(255,255,255,0.08)' }}>
67
+ {wf.status === 'active' ? <Pause size={13} className="text-slate-400" /> : <Play size={13} className="text-green-400" />}
68
+ </button>
69
+ </div>
70
+ </div>
71
+ </motion.div>
72
+ )
73
+ })}
74
+ </div>
75
+ </div>
76
+ )
77
+ }
frontend/components/shared/Sidebar.tsx ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client'
2
+
3
+ import { motion, AnimatePresence } from 'framer-motion'
4
+ import {
5
+ LayoutDashboard, Bot, CheckSquare, Brain, BookOpen,
6
+ GitBranch, BarChart3, Settings, ChevronLeft, Zap,
7
+ Activity, Menu, X
8
+ } from 'lucide-react'
9
+ import { useAppStore, NavPage } from '@/store/useAppStore'
10
+ import { cn } from '@/lib/utils'
11
+
12
+ const NAV_ITEMS: { page: NavPage; label: string; icon: React.ElementType; badge?: string }[] = [
13
+ { page: 'dashboard', label: 'Dashboard', icon: LayoutDashboard },
14
+ { page: 'agents', label: 'Agents', icon: Bot, badge: '12' },
15
+ { page: 'tasks', label: 'Tasks', icon: CheckSquare, badge: '3' },
16
+ { page: 'memory', label: 'Memory', icon: Brain },
17
+ { page: 'knowledge', label: 'Knowledge', icon: BookOpen },
18
+ { page: 'workflows', label: 'Workflows', icon: GitBranch },
19
+ { page: 'analytics', label: 'Analytics', icon: BarChart3 },
20
+ { page: 'settings', label: 'Settings', icon: Settings },
21
+ ]
22
+
23
+ export default function Sidebar() {
24
+ const { currentPage, setCurrentPage, sidebarCollapsed, toggleSidebar, godModeActive, toggleGodMode } = useAppStore()
25
+
26
+ return (
27
+ <motion.aside
28
+ animate={{ width: sidebarCollapsed ? 64 : 220 }}
29
+ transition={{ duration: 0.3, ease: [0.4, 0, 0.2, 1] }}
30
+ className="flex flex-col h-full flex-shrink-0 border-r overflow-hidden"
31
+ style={{ borderColor: 'var(--border)', background: 'rgba(10,12,22,0.95)', backdropFilter: 'blur(20px)' }}
32
+ >
33
+ {/* Logo */}
34
+ <div className="flex items-center gap-3 px-4 py-5 border-b" style={{ borderColor: 'var(--border)' }}>
35
+ <div className="relative flex-shrink-0">
36
+ <div className="w-8 h-8 rounded-xl flex items-center justify-center glow-purple"
37
+ style={{ background: 'linear-gradient(135deg, #7c3aed, #4f46e5)' }}>
38
+ <Zap size={16} className="text-white" />
39
+ </div>
40
+ {godModeActive && (
41
+ <div className="absolute -top-0.5 -right-0.5 w-2.5 h-2.5 rounded-full bg-green-400 border-2 border-[#0a0c16]" />
42
+ )}
43
+ </div>
44
+ <AnimatePresence>
45
+ {!sidebarCollapsed && (
46
+ <motion.div
47
+ initial={{ opacity: 0, x: -8 }}
48
+ animate={{ opacity: 1, x: 0 }}
49
+ exit={{ opacity: 0, x: -8 }}
50
+ transition={{ duration: 0.2 }}
51
+ className="min-w-0"
52
+ >
53
+ <div className="text-sm font-bold text-white leading-none">GOD AGENT OS</div>
54
+ <div className="text-xs mt-0.5" style={{ color: 'var(--text-muted)' }}>by manus + genspark</div>
55
+ </motion.div>
56
+ )}
57
+ </AnimatePresence>
58
+ <button
59
+ onClick={toggleSidebar}
60
+ className="ml-auto text-slate-500 hover:text-slate-300 transition-colors flex-shrink-0"
61
+ >
62
+ {sidebarCollapsed ? <Menu size={16} /> : <ChevronLeft size={16} />}
63
+ </button>
64
+ </div>
65
+
66
+ {/* Navigation */}
67
+ <nav className="flex-1 overflow-y-auto py-3 px-2 space-y-0.5">
68
+ {NAV_ITEMS.map(({ page, label, icon: Icon, badge }) => {
69
+ const isActive = currentPage === page
70
+ return (
71
+ <button
72
+ key={page}
73
+ onClick={() => setCurrentPage(page)}
74
+ className={cn(
75
+ 'nav-item w-full text-left relative group',
76
+ isActive && 'active'
77
+ )}
78
+ title={sidebarCollapsed ? label : undefined}
79
+ >
80
+ <Icon size={17} className="flex-shrink-0" style={{ color: isActive ? '#a78bfa' : undefined }} />
81
+ <AnimatePresence>
82
+ {!sidebarCollapsed && (
83
+ <motion.span
84
+ initial={{ opacity: 0 }}
85
+ animate={{ opacity: 1 }}
86
+ exit={{ opacity: 0 }}
87
+ className="flex-1 text-left"
88
+ >
89
+ {label}
90
+ </motion.span>
91
+ )}
92
+ </AnimatePresence>
93
+ {badge && !sidebarCollapsed && (
94
+ <span className="ml-auto text-xs px-1.5 py-0.5 rounded-full font-semibold"
95
+ style={{ background: isActive ? 'rgba(124,58,237,0.3)' : 'rgba(255,255,255,0.07)', color: isActive ? '#c084fc' : 'var(--text-muted)' }}>
96
+ {badge}
97
+ </span>
98
+ )}
99
+ </button>
100
+ )
101
+ })}
102
+ </nav>
103
+
104
+ {/* System Status */}
105
+ <div className="px-2 pb-2">
106
+ <div className="border-t mb-2" style={{ borderColor: 'var(--border)' }} />
107
+ {!sidebarCollapsed && (
108
+ <div className="px-2 mb-2">
109
+ <div className="flex items-center gap-2 mb-1">
110
+ <Activity size={11} className="text-green-400" />
111
+ <span className="text-xs font-medium" style={{ color: 'var(--text-secondary)' }}>System Status</span>
112
+ </div>
113
+ <div className="flex items-center gap-2">
114
+ <div className="w-1.5 h-1.5 rounded-full bg-green-400 animate-pulse-glow" />
115
+ <span className="text-xs text-green-400 font-medium">All Systems Operational</span>
116
+ </div>
117
+ </div>
118
+ )}
119
+
120
+ {/* God Mode Toggle */}
121
+ <div className={cn(
122
+ 'flex items-center gap-2 px-2 py-2 rounded-xl cursor-pointer transition-all',
123
+ sidebarCollapsed ? 'justify-center' : '',
124
+ godModeActive ? 'glass-purple' : 'glass'
125
+ )} onClick={toggleGodMode}>
126
+ <div className={cn('w-6 h-3.5 rounded-full relative transition-all flex-shrink-0',
127
+ godModeActive ? 'bg-purple-600' : 'bg-slate-700'
128
+ )}>
129
+ <div className={cn('absolute top-0.5 w-2.5 h-2.5 rounded-full transition-all',
130
+ godModeActive ? 'right-0.5 bg-white' : 'left-0.5 bg-slate-400'
131
+ )} />
132
+ </div>
133
+ {!sidebarCollapsed && (
134
+ <span className="text-xs font-semibold" style={{ color: godModeActive ? '#a78bfa' : 'var(--text-muted)' }}>
135
+ God Mode {godModeActive ? 'ON' : 'OFF'}
136
+ </span>
137
+ )}
138
+ </div>
139
+ </div>
140
+ </motion.aside>
141
+ )
142
+ }
frontend/components/shared/TopBar.tsx ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client'
2
+
3
+ import { useState, useEffect, useRef } from 'react'
4
+ import { motion, AnimatePresence } from 'framer-motion'
5
+ import { Search, Bell, Command, Sparkles, X, ArrowRight, Bot, CheckSquare, FileText, Zap } from 'lucide-react'
6
+ import { useAppStore } from '@/store/useAppStore'
7
+
8
+ const QUICK_COMMANDS = [
9
+ { icon: Bot, label: 'New Research Task', shortcut: '/research', page: 'agents' as const },
10
+ { icon: CheckSquare, label: 'View Running Tasks', shortcut: '/tasks', page: 'tasks' as const },
11
+ { icon: FileText, label: 'Generate Report', shortcut: '/report', page: 'analytics' as const },
12
+ { icon: Zap, label: 'Deploy Application', shortcut: '/deploy', page: 'workflows' as const },
13
+ ]
14
+
15
+ const NOTIFICATIONS = [
16
+ { id: '1', title: 'Code Agent', message: 'Successfully deployed production API', time: '2m ago', color: '#34d399' },
17
+ { id: '2', title: 'Research Agent', message: 'Market analysis complete — 47 insights found', time: '15m ago', color: '#6366f1' },
18
+ { id: '3', title: 'Data Agent', message: 'Processed 1.2M data points', time: '1h ago', color: '#22d3ee' },
19
+ ]
20
+
21
+ export default function TopBar() {
22
+ const { setCurrentPage, commandPaletteOpen, setCommandPaletteOpen } = useAppStore()
23
+ const [query, setQuery] = useState('')
24
+ const [notifOpen, setNotifOpen] = useState(false)
25
+ const inputRef = useRef<HTMLInputElement>(null)
26
+
27
+ useEffect(() => {
28
+ const handler = (e: KeyboardEvent) => {
29
+ if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
30
+ e.preventDefault()
31
+ setCommandPaletteOpen(true)
32
+ setTimeout(() => inputRef.current?.focus(), 50)
33
+ }
34
+ if (e.key === 'Escape') {
35
+ setCommandPaletteOpen(false)
36
+ setNotifOpen(false)
37
+ setQuery('')
38
+ }
39
+ }
40
+ window.addEventListener('keydown', handler)
41
+ return () => window.removeEventListener('keydown', handler)
42
+ }, [setCommandPaletteOpen])
43
+
44
+ const filtered = QUICK_COMMANDS.filter(c =>
45
+ query === '' || c.label.toLowerCase().includes(query.toLowerCase()) || c.shortcut.includes(query)
46
+ )
47
+
48
+ return (
49
+ <header className="flex items-center gap-4 px-4 py-3 border-b flex-shrink-0 relative z-30"
50
+ style={{ borderColor: 'var(--border)', background: 'rgba(10,12,22,0.98)', backdropFilter: 'blur(20px)' }}>
51
+
52
+ {/* Search / Command Trigger */}
53
+ <div className="flex-1 max-w-xl mx-auto">
54
+ <button
55
+ onClick={() => { setCommandPaletteOpen(true); setTimeout(() => inputRef.current?.focus(), 50) }}
56
+ className="w-full flex items-center gap-3 px-4 py-2.5 rounded-xl text-left transition-all hover:border-purple-500/30"
57
+ style={{ background: 'rgba(255,255,255,0.04)', border: '1px solid rgba(255,255,255,0.08)' }}
58
+ >
59
+ <Search size={15} className="text-slate-500 flex-shrink-0" />
60
+ <span className="flex-1 text-sm" style={{ color: 'var(--text-muted)' }}>Search agents, tasks, docs…</span>
61
+ <div className="flex items-center gap-1 text-xs px-1.5 py-0.5 rounded-md"
62
+ style={{ background: 'rgba(255,255,255,0.06)', color: 'var(--text-muted)' }}>
63
+ <Command size={10} />
64
+ <span>K</span>
65
+ </div>
66
+ </button>
67
+ </div>
68
+
69
+ {/* Right Icons */}
70
+ <div className="flex items-center gap-2">
71
+ <button className="p-2 rounded-xl text-slate-500 hover:text-slate-300 hover:bg-white/5 transition-all">
72
+ <Sparkles size={17} />
73
+ </button>
74
+
75
+ {/* Notifications */}
76
+ <div className="relative">
77
+ <button
78
+ onClick={() => setNotifOpen(!notifOpen)}
79
+ className="relative p-2 rounded-xl text-slate-500 hover:text-slate-300 hover:bg-white/5 transition-all"
80
+ >
81
+ <Bell size={17} />
82
+ <div className="absolute top-1.5 right-1.5 w-2 h-2 rounded-full bg-purple-500 border border-[#0a0c16]" />
83
+ </button>
84
+
85
+ <AnimatePresence>
86
+ {notifOpen && (
87
+ <motion.div
88
+ initial={{ opacity: 0, y: 8, scale: 0.95 }}
89
+ animate={{ opacity: 1, y: 0, scale: 1 }}
90
+ exit={{ opacity: 0, y: 8, scale: 0.95 }}
91
+ transition={{ duration: 0.2 }}
92
+ className="absolute right-0 top-full mt-2 w-80 glass-card overflow-hidden z-50"
93
+ >
94
+ <div className="flex items-center justify-between px-4 py-3 border-b" style={{ borderColor: 'var(--border)' }}>
95
+ <span className="text-sm font-semibold text-white">Notifications</span>
96
+ <button onClick={() => setNotifOpen(false)} className="text-slate-500 hover:text-slate-300">
97
+ <X size={14} />
98
+ </button>
99
+ </div>
100
+ {NOTIFICATIONS.map((n) => (
101
+ <div key={n.id} className="flex gap-3 px-4 py-3 hover:bg-white/[0.03] transition-colors cursor-pointer border-b last:border-0"
102
+ style={{ borderColor: 'var(--border)' }}>
103
+ <div className="w-2 h-2 rounded-full flex-shrink-0 mt-1.5" style={{ background: n.color }} />
104
+ <div className="min-w-0">
105
+ <div className="text-xs font-semibold text-white">{n.title}</div>
106
+ <div className="text-xs mt-0.5 text-slate-400 line-clamp-1">{n.message}</div>
107
+ <div className="text-xs mt-1 text-slate-600">{n.time}</div>
108
+ </div>
109
+ </div>
110
+ ))}
111
+ </motion.div>
112
+ )}
113
+ </AnimatePresence>
114
+ </div>
115
+
116
+ {/* Avatar */}
117
+ <div className="w-8 h-8 rounded-full overflow-hidden border-2 cursor-pointer"
118
+ style={{ borderColor: 'rgba(124,58,237,0.4)', background: 'linear-gradient(135deg, #7c3aed, #4f46e5)' }}>
119
+ <div className="w-full h-full flex items-center justify-center text-xs font-bold text-white">A</div>
120
+ </div>
121
+ </div>
122
+
123
+ {/* Command Palette Modal */}
124
+ <AnimatePresence>
125
+ {commandPaletteOpen && (
126
+ <>
127
+ <motion.div
128
+ initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}
129
+ className="fixed inset-0 bg-black/60 backdrop-blur-sm z-50"
130
+ onClick={() => { setCommandPaletteOpen(false); setQuery('') }}
131
+ />
132
+ <motion.div
133
+ initial={{ opacity: 0, scale: 0.96, y: -16 }}
134
+ animate={{ opacity: 1, scale: 1, y: 0 }}
135
+ exit={{ opacity: 0, scale: 0.96, y: -16 }}
136
+ transition={{ duration: 0.2, ease: [0.4, 0, 0.2, 1] }}
137
+ className="fixed top-[20vh] left-1/2 -translate-x-1/2 w-full max-w-lg glass-card z-50 overflow-hidden"
138
+ >
139
+ <div className="flex items-center gap-3 px-4 py-3.5 border-b" style={{ borderColor: 'var(--border)' }}>
140
+ <Search size={16} className="text-slate-500" />
141
+ <input
142
+ ref={inputRef}
143
+ value={query}
144
+ onChange={e => setQuery(e.target.value)}
145
+ placeholder="Search agents, run commands…"
146
+ className="flex-1 bg-transparent text-sm text-white placeholder:text-slate-500 outline-none"
147
+ />
148
+ <button onClick={() => { setCommandPaletteOpen(false); setQuery('') }}
149
+ className="text-slate-500 hover:text-slate-300 transition-colors">
150
+ <X size={14} />
151
+ </button>
152
+ </div>
153
+ <div className="py-2 max-h-64 overflow-y-auto">
154
+ {filtered.map(({ icon: Icon, label, shortcut, page }) => (
155
+ <button key={label}
156
+ onClick={() => { setCurrentPage(page); setCommandPaletteOpen(false); setQuery('') }}
157
+ className="w-full flex items-center gap-3 px-4 py-2.5 hover:bg-white/[0.04] transition-colors group">
158
+ <Icon size={15} className="text-purple-400 group-hover:text-purple-300" />
159
+ <span className="flex-1 text-sm text-left text-slate-300 group-hover:text-white">{label}</span>
160
+ <span className="text-xs font-mono px-2 py-0.5 rounded"
161
+ style={{ background: 'rgba(255,255,255,0.06)', color: 'var(--text-muted)' }}>{shortcut}</span>
162
+ <ArrowRight size={13} className="text-slate-600 group-hover:text-purple-400 transition-colors" />
163
+ </button>
164
+ ))}
165
+ {filtered.length === 0 && (
166
+ <div className="px-4 py-6 text-center text-sm text-slate-600">No results for "{query}"</div>
167
+ )}
168
+ </div>
169
+ <div className="px-4 py-2 border-t flex items-center gap-4 text-xs text-slate-600"
170
+ style={{ borderColor: 'var(--border)' }}>
171
+ <span>↑↓ navigate</span>
172
+ <span>↵ select</span>
173
+ <span>esc close</span>
174
+ </div>
175
+ </motion.div>
176
+ </>
177
+ )}
178
+ </AnimatePresence>
179
+ </header>
180
+ )
181
+ }
frontend/hooks/useAgentStore.ts CHANGED
@@ -9,7 +9,7 @@ import { nanoid } from './nanoid'
9
  export type Theme = 'dark' | 'light' | 'amoled' | 'neon' | 'glass'
10
  export type Locale = 'en' | 'my'
11
  export type AgentName = 'chat' | 'planner' | 'coding' | 'debug' | 'memory' | 'connector' | 'deploy' | 'workflow' | 'sandbox' | 'ui' | 'browser' | 'file' | 'git' | 'test' | 'vision' | 'reasoning'
12
- export type ActivePanel = 'timeline' | 'tasks' | 'memory' | 'connectors' | 'sandbox' | 'files' | 'browser'
13
 
14
  export interface Message {
15
  id: string
 
9
  export type Theme = 'dark' | 'light' | 'amoled' | 'neon' | 'glass'
10
  export type Locale = 'en' | 'my'
11
  export type AgentName = 'chat' | 'planner' | 'coding' | 'debug' | 'memory' | 'connector' | 'deploy' | 'workflow' | 'sandbox' | 'ui' | 'browser' | 'file' | 'git' | 'test' | 'vision' | 'reasoning'
12
+ export type ActivePanel = 'timeline' | 'tasks' | 'memory' | 'connectors' | 'sandbox' | 'files' | 'browser' | 'ai_router'
13
 
14
  export interface Message {
15
  id: string
frontend/lib/utils.ts ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { type ClassValue, clsx } from 'clsx'
2
+ import { twMerge } from 'tailwind-merge'
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs))
6
+ }
7
+
8
+ export function formatNumber(n: number): string {
9
+ if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`
10
+ if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`
11
+ return n.toString()
12
+ }
13
+
14
+ export function getStatusColor(status: string): string {
15
+ switch (status) {
16
+ case 'active': return '#22c55e'
17
+ case 'processing': return '#f59e0b'
18
+ case 'idle': return '#94a3b8'
19
+ case 'error': return '#ef4444'
20
+ case 'running': return '#6366f1'
21
+ case 'completed': return '#22c55e'
22
+ case 'pending': return '#94a3b8'
23
+ case 'failed': return '#ef4444'
24
+ default: return '#94a3b8'
25
+ }
26
+ }
27
+
28
+ export function getStatusLabel(status: string): string {
29
+ return status.charAt(0).toUpperCase() + status.slice(1)
30
+ }
31
+
32
+ export function randomBetween(min: number, max: number): number {
33
+ return Math.floor(Math.random() * (max - min + 1)) + min
34
+ }
frontend/package-lock.json CHANGED
@@ -8,6 +8,13 @@
8
  "name": "god-mode-plus-ui",
9
  "version": "3.0.0",
10
  "dependencies": {
 
 
 
 
 
 
 
11
  "clsx": "^2.1.1",
12
  "date-fns": "^3.6.0",
13
  "framer-motion": "^11.1.9",
@@ -58,6 +65,44 @@
58
  "node": ">=6.9.0"
59
  }
60
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  "node_modules/@jridgewell/gen-mapping": {
62
  "version": "0.3.13",
63
  "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
@@ -167,124 +212,948 @@
167
  "node": ">= 10"
168
  }
169
  },
170
- "node_modules/@next/swc-linux-x64-gnu": {
171
- "version": "14.2.3",
172
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.3.tgz",
173
- "integrity": "sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w==",
174
- "cpu": [
175
- "x64"
176
- ],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  "license": "MIT",
178
- "optional": true,
179
- "os": [
180
- "linux"
181
- ],
182
- "engines": {
183
- "node": ">= 10"
 
 
184
  }
185
  },
186
- "node_modules/@next/swc-linux-x64-musl": {
187
- "version": "14.2.3",
188
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.3.tgz",
189
- "integrity": "sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==",
190
- "cpu": [
191
- "x64"
192
- ],
193
  "license": "MIT",
194
- "optional": true,
195
- "os": [
196
- "linux"
197
- ],
198
- "engines": {
199
- "node": ">= 10"
 
 
 
 
 
 
200
  }
201
  },
202
- "node_modules/@next/swc-win32-arm64-msvc": {
203
- "version": "14.2.3",
204
- "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.3.tgz",
205
- "integrity": "sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==",
206
- "cpu": [
207
- "arm64"
208
- ],
209
  "license": "MIT",
210
- "optional": true,
211
- "os": [
212
- "win32"
213
- ],
214
- "engines": {
215
- "node": ">= 10"
 
 
 
 
 
216
  }
217
  },
218
- "node_modules/@next/swc-win32-ia32-msvc": {
219
- "version": "14.2.3",
220
- "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.3.tgz",
221
- "integrity": "sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw==",
222
- "cpu": [
223
- "ia32"
224
- ],
225
  "license": "MIT",
226
- "optional": true,
227
- "os": [
228
- "win32"
229
- ],
230
- "engines": {
231
- "node": ">= 10"
 
 
 
 
 
232
  }
233
  },
234
- "node_modules/@next/swc-win32-x64-msvc": {
235
- "version": "14.2.3",
236
- "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.3.tgz",
237
- "integrity": "sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA==",
238
- "cpu": [
239
- "x64"
240
- ],
241
  "license": "MIT",
242
- "optional": true,
243
- "os": [
244
- "win32"
245
- ],
246
- "engines": {
247
- "node": ">= 10"
 
 
248
  }
249
  },
250
- "node_modules/@nodelib/fs.scandir": {
251
- "version": "2.1.5",
252
- "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
253
- "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
254
- "dev": true,
255
  "license": "MIT",
256
  "dependencies": {
257
- "@nodelib/fs.stat": "2.0.5",
258
- "run-parallel": "^1.1.9"
259
  },
260
- "engines": {
261
- "node": ">= 8"
 
 
 
 
 
 
262
  }
263
  },
264
- "node_modules/@nodelib/fs.stat": {
265
- "version": "2.0.5",
266
- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
267
- "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
268
- "dev": true,
269
  "license": "MIT",
270
- "engines": {
271
- "node": ">= 8"
 
 
 
 
 
 
 
 
 
272
  }
273
  },
274
- "node_modules/@nodelib/fs.walk": {
275
- "version": "1.2.8",
276
- "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
277
- "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
278
- "dev": true,
279
  "license": "MIT",
280
  "dependencies": {
281
- "@nodelib/fs.scandir": "2.1.5",
282
- "fastq": "^1.6.0"
283
  },
284
- "engines": {
285
- "node": ">= 8"
 
 
 
 
 
 
 
 
 
 
 
286
  }
287
  },
 
 
 
 
 
 
288
  "node_modules/@reduxjs/toolkit": {
289
  "version": "2.11.2",
290
  "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.11.2.tgz",
@@ -490,7 +1359,7 @@
490
  "version": "18.3.7",
491
  "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
492
  "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
493
- "dev": true,
494
  "license": "MIT",
495
  "peerDependencies": {
496
  "@types/react": "^18.0.0"
@@ -565,6 +1434,18 @@
565
  "dev": true,
566
  "license": "MIT"
567
  },
 
 
 
 
 
 
 
 
 
 
 
 
568
  "node_modules/autoprefixer": {
569
  "version": "10.5.0",
570
  "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz",
@@ -814,6 +1695,18 @@
814
  "node": ">= 6"
815
  }
816
  },
 
 
 
 
 
 
 
 
 
 
 
 
817
  "node_modules/client-only": {
818
  "version": "0.0.1",
819
  "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
@@ -1044,6 +1937,12 @@
1044
  "node": ">=6"
1045
  }
1046
  },
 
 
 
 
 
 
1047
  "node_modules/devlop": {
1048
  "version": "1.1.0",
1049
  "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
@@ -1300,6 +2199,15 @@
1300
  "url": "https://github.com/sponsors/ljharb"
1301
  }
1302
  },
 
 
 
 
 
 
 
 
 
1303
  "node_modules/glob-parent": {
1304
  "version": "6.0.2",
1305
  "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
@@ -3182,6 +4090,75 @@
3182
  }
3183
  }
3184
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3185
  "node_modules/react-syntax-highlighter": {
3186
  "version": "15.6.6",
3187
  "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.6.6.tgz",
@@ -3986,6 +4963,49 @@
3986
  "browserslist": ">= 4.21.0"
3987
  }
3988
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3989
  "node_modules/use-sync-external-store": {
3990
  "version": "1.6.0",
3991
  "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
 
8
  "name": "god-mode-plus-ui",
9
  "version": "3.0.0",
10
  "dependencies": {
11
+ "@radix-ui/react-dialog": "^1.1.15",
12
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
13
+ "@radix-ui/react-progress": "^1.1.8",
14
+ "@radix-ui/react-separator": "^1.1.8",
15
+ "@radix-ui/react-slot": "^1.2.4",
16
+ "@radix-ui/react-tooltip": "^1.2.8",
17
+ "class-variance-authority": "^0.7.1",
18
  "clsx": "^2.1.1",
19
  "date-fns": "^3.6.0",
20
  "framer-motion": "^11.1.9",
 
65
  "node": ">=6.9.0"
66
  }
67
  },
68
+ "node_modules/@floating-ui/core": {
69
+ "version": "1.7.5",
70
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz",
71
+ "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
72
+ "license": "MIT",
73
+ "dependencies": {
74
+ "@floating-ui/utils": "^0.2.11"
75
+ }
76
+ },
77
+ "node_modules/@floating-ui/dom": {
78
+ "version": "1.7.6",
79
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz",
80
+ "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
81
+ "license": "MIT",
82
+ "dependencies": {
83
+ "@floating-ui/core": "^1.7.5",
84
+ "@floating-ui/utils": "^0.2.11"
85
+ }
86
+ },
87
+ "node_modules/@floating-ui/react-dom": {
88
+ "version": "2.1.8",
89
+ "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz",
90
+ "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==",
91
+ "license": "MIT",
92
+ "dependencies": {
93
+ "@floating-ui/dom": "^1.7.6"
94
+ },
95
+ "peerDependencies": {
96
+ "react": ">=16.8.0",
97
+ "react-dom": ">=16.8.0"
98
+ }
99
+ },
100
+ "node_modules/@floating-ui/utils": {
101
+ "version": "0.2.11",
102
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz",
103
+ "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==",
104
+ "license": "MIT"
105
+ },
106
  "node_modules/@jridgewell/gen-mapping": {
107
  "version": "0.3.13",
108
  "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
 
212
  "node": ">= 10"
213
  }
214
  },
215
+ "node_modules/@next/swc-linux-x64-gnu": {
216
+ "version": "14.2.3",
217
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.3.tgz",
218
+ "integrity": "sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w==",
219
+ "cpu": [
220
+ "x64"
221
+ ],
222
+ "license": "MIT",
223
+ "optional": true,
224
+ "os": [
225
+ "linux"
226
+ ],
227
+ "engines": {
228
+ "node": ">= 10"
229
+ }
230
+ },
231
+ "node_modules/@next/swc-linux-x64-musl": {
232
+ "version": "14.2.3",
233
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.3.tgz",
234
+ "integrity": "sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==",
235
+ "cpu": [
236
+ "x64"
237
+ ],
238
+ "license": "MIT",
239
+ "optional": true,
240
+ "os": [
241
+ "linux"
242
+ ],
243
+ "engines": {
244
+ "node": ">= 10"
245
+ }
246
+ },
247
+ "node_modules/@next/swc-win32-arm64-msvc": {
248
+ "version": "14.2.3",
249
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.3.tgz",
250
+ "integrity": "sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==",
251
+ "cpu": [
252
+ "arm64"
253
+ ],
254
+ "license": "MIT",
255
+ "optional": true,
256
+ "os": [
257
+ "win32"
258
+ ],
259
+ "engines": {
260
+ "node": ">= 10"
261
+ }
262
+ },
263
+ "node_modules/@next/swc-win32-ia32-msvc": {
264
+ "version": "14.2.3",
265
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.3.tgz",
266
+ "integrity": "sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw==",
267
+ "cpu": [
268
+ "ia32"
269
+ ],
270
+ "license": "MIT",
271
+ "optional": true,
272
+ "os": [
273
+ "win32"
274
+ ],
275
+ "engines": {
276
+ "node": ">= 10"
277
+ }
278
+ },
279
+ "node_modules/@next/swc-win32-x64-msvc": {
280
+ "version": "14.2.3",
281
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.3.tgz",
282
+ "integrity": "sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA==",
283
+ "cpu": [
284
+ "x64"
285
+ ],
286
+ "license": "MIT",
287
+ "optional": true,
288
+ "os": [
289
+ "win32"
290
+ ],
291
+ "engines": {
292
+ "node": ">= 10"
293
+ }
294
+ },
295
+ "node_modules/@nodelib/fs.scandir": {
296
+ "version": "2.1.5",
297
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
298
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
299
+ "dev": true,
300
+ "license": "MIT",
301
+ "dependencies": {
302
+ "@nodelib/fs.stat": "2.0.5",
303
+ "run-parallel": "^1.1.9"
304
+ },
305
+ "engines": {
306
+ "node": ">= 8"
307
+ }
308
+ },
309
+ "node_modules/@nodelib/fs.stat": {
310
+ "version": "2.0.5",
311
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
312
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
313
+ "dev": true,
314
+ "license": "MIT",
315
+ "engines": {
316
+ "node": ">= 8"
317
+ }
318
+ },
319
+ "node_modules/@nodelib/fs.walk": {
320
+ "version": "1.2.8",
321
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
322
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
323
+ "dev": true,
324
+ "license": "MIT",
325
+ "dependencies": {
326
+ "@nodelib/fs.scandir": "2.1.5",
327
+ "fastq": "^1.6.0"
328
+ },
329
+ "engines": {
330
+ "node": ">= 8"
331
+ }
332
+ },
333
+ "node_modules/@radix-ui/primitive": {
334
+ "version": "1.1.3",
335
+ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
336
+ "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==",
337
+ "license": "MIT"
338
+ },
339
+ "node_modules/@radix-ui/react-arrow": {
340
+ "version": "1.1.7",
341
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
342
+ "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==",
343
+ "license": "MIT",
344
+ "dependencies": {
345
+ "@radix-ui/react-primitive": "2.1.3"
346
+ },
347
+ "peerDependencies": {
348
+ "@types/react": "*",
349
+ "@types/react-dom": "*",
350
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
351
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
352
+ },
353
+ "peerDependenciesMeta": {
354
+ "@types/react": {
355
+ "optional": true
356
+ },
357
+ "@types/react-dom": {
358
+ "optional": true
359
+ }
360
+ }
361
+ },
362
+ "node_modules/@radix-ui/react-collection": {
363
+ "version": "1.1.7",
364
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz",
365
+ "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==",
366
+ "license": "MIT",
367
+ "dependencies": {
368
+ "@radix-ui/react-compose-refs": "1.1.2",
369
+ "@radix-ui/react-context": "1.1.2",
370
+ "@radix-ui/react-primitive": "2.1.3",
371
+ "@radix-ui/react-slot": "1.2.3"
372
+ },
373
+ "peerDependencies": {
374
+ "@types/react": "*",
375
+ "@types/react-dom": "*",
376
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
377
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
378
+ },
379
+ "peerDependenciesMeta": {
380
+ "@types/react": {
381
+ "optional": true
382
+ },
383
+ "@types/react-dom": {
384
+ "optional": true
385
+ }
386
+ }
387
+ },
388
+ "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": {
389
+ "version": "1.2.3",
390
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
391
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
392
+ "license": "MIT",
393
+ "dependencies": {
394
+ "@radix-ui/react-compose-refs": "1.1.2"
395
+ },
396
+ "peerDependencies": {
397
+ "@types/react": "*",
398
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
399
+ },
400
+ "peerDependenciesMeta": {
401
+ "@types/react": {
402
+ "optional": true
403
+ }
404
+ }
405
+ },
406
+ "node_modules/@radix-ui/react-compose-refs": {
407
+ "version": "1.1.2",
408
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
409
+ "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
410
+ "license": "MIT",
411
+ "peerDependencies": {
412
+ "@types/react": "*",
413
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
414
+ },
415
+ "peerDependenciesMeta": {
416
+ "@types/react": {
417
+ "optional": true
418
+ }
419
+ }
420
+ },
421
+ "node_modules/@radix-ui/react-context": {
422
+ "version": "1.1.2",
423
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
424
+ "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
425
+ "license": "MIT",
426
+ "peerDependencies": {
427
+ "@types/react": "*",
428
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
429
+ },
430
+ "peerDependenciesMeta": {
431
+ "@types/react": {
432
+ "optional": true
433
+ }
434
+ }
435
+ },
436
+ "node_modules/@radix-ui/react-dialog": {
437
+ "version": "1.1.15",
438
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz",
439
+ "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==",
440
+ "license": "MIT",
441
+ "dependencies": {
442
+ "@radix-ui/primitive": "1.1.3",
443
+ "@radix-ui/react-compose-refs": "1.1.2",
444
+ "@radix-ui/react-context": "1.1.2",
445
+ "@radix-ui/react-dismissable-layer": "1.1.11",
446
+ "@radix-ui/react-focus-guards": "1.1.3",
447
+ "@radix-ui/react-focus-scope": "1.1.7",
448
+ "@radix-ui/react-id": "1.1.1",
449
+ "@radix-ui/react-portal": "1.1.9",
450
+ "@radix-ui/react-presence": "1.1.5",
451
+ "@radix-ui/react-primitive": "2.1.3",
452
+ "@radix-ui/react-slot": "1.2.3",
453
+ "@radix-ui/react-use-controllable-state": "1.2.2",
454
+ "aria-hidden": "^1.2.4",
455
+ "react-remove-scroll": "^2.6.3"
456
+ },
457
+ "peerDependencies": {
458
+ "@types/react": "*",
459
+ "@types/react-dom": "*",
460
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
461
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
462
+ },
463
+ "peerDependenciesMeta": {
464
+ "@types/react": {
465
+ "optional": true
466
+ },
467
+ "@types/react-dom": {
468
+ "optional": true
469
+ }
470
+ }
471
+ },
472
+ "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": {
473
+ "version": "1.2.3",
474
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
475
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
476
+ "license": "MIT",
477
+ "dependencies": {
478
+ "@radix-ui/react-compose-refs": "1.1.2"
479
+ },
480
+ "peerDependencies": {
481
+ "@types/react": "*",
482
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
483
+ },
484
+ "peerDependenciesMeta": {
485
+ "@types/react": {
486
+ "optional": true
487
+ }
488
+ }
489
+ },
490
+ "node_modules/@radix-ui/react-direction": {
491
+ "version": "1.1.1",
492
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz",
493
+ "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==",
494
+ "license": "MIT",
495
+ "peerDependencies": {
496
+ "@types/react": "*",
497
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
498
+ },
499
+ "peerDependenciesMeta": {
500
+ "@types/react": {
501
+ "optional": true
502
+ }
503
+ }
504
+ },
505
+ "node_modules/@radix-ui/react-dismissable-layer": {
506
+ "version": "1.1.11",
507
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz",
508
+ "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==",
509
+ "license": "MIT",
510
+ "dependencies": {
511
+ "@radix-ui/primitive": "1.1.3",
512
+ "@radix-ui/react-compose-refs": "1.1.2",
513
+ "@radix-ui/react-primitive": "2.1.3",
514
+ "@radix-ui/react-use-callback-ref": "1.1.1",
515
+ "@radix-ui/react-use-escape-keydown": "1.1.1"
516
+ },
517
+ "peerDependencies": {
518
+ "@types/react": "*",
519
+ "@types/react-dom": "*",
520
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
521
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
522
+ },
523
+ "peerDependenciesMeta": {
524
+ "@types/react": {
525
+ "optional": true
526
+ },
527
+ "@types/react-dom": {
528
+ "optional": true
529
+ }
530
+ }
531
+ },
532
+ "node_modules/@radix-ui/react-dropdown-menu": {
533
+ "version": "2.1.16",
534
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz",
535
+ "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==",
536
+ "license": "MIT",
537
+ "dependencies": {
538
+ "@radix-ui/primitive": "1.1.3",
539
+ "@radix-ui/react-compose-refs": "1.1.2",
540
+ "@radix-ui/react-context": "1.1.2",
541
+ "@radix-ui/react-id": "1.1.1",
542
+ "@radix-ui/react-menu": "2.1.16",
543
+ "@radix-ui/react-primitive": "2.1.3",
544
+ "@radix-ui/react-use-controllable-state": "1.2.2"
545
+ },
546
+ "peerDependencies": {
547
+ "@types/react": "*",
548
+ "@types/react-dom": "*",
549
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
550
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
551
+ },
552
+ "peerDependenciesMeta": {
553
+ "@types/react": {
554
+ "optional": true
555
+ },
556
+ "@types/react-dom": {
557
+ "optional": true
558
+ }
559
+ }
560
+ },
561
+ "node_modules/@radix-ui/react-focus-guards": {
562
+ "version": "1.1.3",
563
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz",
564
+ "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==",
565
+ "license": "MIT",
566
+ "peerDependencies": {
567
+ "@types/react": "*",
568
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
569
+ },
570
+ "peerDependenciesMeta": {
571
+ "@types/react": {
572
+ "optional": true
573
+ }
574
+ }
575
+ },
576
+ "node_modules/@radix-ui/react-focus-scope": {
577
+ "version": "1.1.7",
578
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz",
579
+ "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==",
580
+ "license": "MIT",
581
+ "dependencies": {
582
+ "@radix-ui/react-compose-refs": "1.1.2",
583
+ "@radix-ui/react-primitive": "2.1.3",
584
+ "@radix-ui/react-use-callback-ref": "1.1.1"
585
+ },
586
+ "peerDependencies": {
587
+ "@types/react": "*",
588
+ "@types/react-dom": "*",
589
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
590
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
591
+ },
592
+ "peerDependenciesMeta": {
593
+ "@types/react": {
594
+ "optional": true
595
+ },
596
+ "@types/react-dom": {
597
+ "optional": true
598
+ }
599
+ }
600
+ },
601
+ "node_modules/@radix-ui/react-id": {
602
+ "version": "1.1.1",
603
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
604
+ "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
605
+ "license": "MIT",
606
+ "dependencies": {
607
+ "@radix-ui/react-use-layout-effect": "1.1.1"
608
+ },
609
+ "peerDependencies": {
610
+ "@types/react": "*",
611
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
612
+ },
613
+ "peerDependenciesMeta": {
614
+ "@types/react": {
615
+ "optional": true
616
+ }
617
+ }
618
+ },
619
+ "node_modules/@radix-ui/react-menu": {
620
+ "version": "2.1.16",
621
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz",
622
+ "integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==",
623
+ "license": "MIT",
624
+ "dependencies": {
625
+ "@radix-ui/primitive": "1.1.3",
626
+ "@radix-ui/react-collection": "1.1.7",
627
+ "@radix-ui/react-compose-refs": "1.1.2",
628
+ "@radix-ui/react-context": "1.1.2",
629
+ "@radix-ui/react-direction": "1.1.1",
630
+ "@radix-ui/react-dismissable-layer": "1.1.11",
631
+ "@radix-ui/react-focus-guards": "1.1.3",
632
+ "@radix-ui/react-focus-scope": "1.1.7",
633
+ "@radix-ui/react-id": "1.1.1",
634
+ "@radix-ui/react-popper": "1.2.8",
635
+ "@radix-ui/react-portal": "1.1.9",
636
+ "@radix-ui/react-presence": "1.1.5",
637
+ "@radix-ui/react-primitive": "2.1.3",
638
+ "@radix-ui/react-roving-focus": "1.1.11",
639
+ "@radix-ui/react-slot": "1.2.3",
640
+ "@radix-ui/react-use-callback-ref": "1.1.1",
641
+ "aria-hidden": "^1.2.4",
642
+ "react-remove-scroll": "^2.6.3"
643
+ },
644
+ "peerDependencies": {
645
+ "@types/react": "*",
646
+ "@types/react-dom": "*",
647
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
648
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
649
+ },
650
+ "peerDependenciesMeta": {
651
+ "@types/react": {
652
+ "optional": true
653
+ },
654
+ "@types/react-dom": {
655
+ "optional": true
656
+ }
657
+ }
658
+ },
659
+ "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": {
660
+ "version": "1.2.3",
661
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
662
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
663
+ "license": "MIT",
664
+ "dependencies": {
665
+ "@radix-ui/react-compose-refs": "1.1.2"
666
+ },
667
+ "peerDependencies": {
668
+ "@types/react": "*",
669
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
670
+ },
671
+ "peerDependenciesMeta": {
672
+ "@types/react": {
673
+ "optional": true
674
+ }
675
+ }
676
+ },
677
+ "node_modules/@radix-ui/react-popper": {
678
+ "version": "1.2.8",
679
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz",
680
+ "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==",
681
+ "license": "MIT",
682
+ "dependencies": {
683
+ "@floating-ui/react-dom": "^2.0.0",
684
+ "@radix-ui/react-arrow": "1.1.7",
685
+ "@radix-ui/react-compose-refs": "1.1.2",
686
+ "@radix-ui/react-context": "1.1.2",
687
+ "@radix-ui/react-primitive": "2.1.3",
688
+ "@radix-ui/react-use-callback-ref": "1.1.1",
689
+ "@radix-ui/react-use-layout-effect": "1.1.1",
690
+ "@radix-ui/react-use-rect": "1.1.1",
691
+ "@radix-ui/react-use-size": "1.1.1",
692
+ "@radix-ui/rect": "1.1.1"
693
+ },
694
+ "peerDependencies": {
695
+ "@types/react": "*",
696
+ "@types/react-dom": "*",
697
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
698
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
699
+ },
700
+ "peerDependenciesMeta": {
701
+ "@types/react": {
702
+ "optional": true
703
+ },
704
+ "@types/react-dom": {
705
+ "optional": true
706
+ }
707
+ }
708
+ },
709
+ "node_modules/@radix-ui/react-portal": {
710
+ "version": "1.1.9",
711
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
712
+ "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==",
713
+ "license": "MIT",
714
+ "dependencies": {
715
+ "@radix-ui/react-primitive": "2.1.3",
716
+ "@radix-ui/react-use-layout-effect": "1.1.1"
717
+ },
718
+ "peerDependencies": {
719
+ "@types/react": "*",
720
+ "@types/react-dom": "*",
721
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
722
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
723
+ },
724
+ "peerDependenciesMeta": {
725
+ "@types/react": {
726
+ "optional": true
727
+ },
728
+ "@types/react-dom": {
729
+ "optional": true
730
+ }
731
+ }
732
+ },
733
+ "node_modules/@radix-ui/react-presence": {
734
+ "version": "1.1.5",
735
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz",
736
+ "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==",
737
+ "license": "MIT",
738
+ "dependencies": {
739
+ "@radix-ui/react-compose-refs": "1.1.2",
740
+ "@radix-ui/react-use-layout-effect": "1.1.1"
741
+ },
742
+ "peerDependencies": {
743
+ "@types/react": "*",
744
+ "@types/react-dom": "*",
745
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
746
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
747
+ },
748
+ "peerDependenciesMeta": {
749
+ "@types/react": {
750
+ "optional": true
751
+ },
752
+ "@types/react-dom": {
753
+ "optional": true
754
+ }
755
+ }
756
+ },
757
+ "node_modules/@radix-ui/react-primitive": {
758
+ "version": "2.1.3",
759
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
760
+ "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
761
+ "license": "MIT",
762
+ "dependencies": {
763
+ "@radix-ui/react-slot": "1.2.3"
764
+ },
765
+ "peerDependencies": {
766
+ "@types/react": "*",
767
+ "@types/react-dom": "*",
768
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
769
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
770
+ },
771
+ "peerDependenciesMeta": {
772
+ "@types/react": {
773
+ "optional": true
774
+ },
775
+ "@types/react-dom": {
776
+ "optional": true
777
+ }
778
+ }
779
+ },
780
+ "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": {
781
+ "version": "1.2.3",
782
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
783
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
784
+ "license": "MIT",
785
+ "dependencies": {
786
+ "@radix-ui/react-compose-refs": "1.1.2"
787
+ },
788
+ "peerDependencies": {
789
+ "@types/react": "*",
790
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
791
+ },
792
+ "peerDependenciesMeta": {
793
+ "@types/react": {
794
+ "optional": true
795
+ }
796
+ }
797
+ },
798
+ "node_modules/@radix-ui/react-progress": {
799
+ "version": "1.1.8",
800
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.8.tgz",
801
+ "integrity": "sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA==",
802
+ "license": "MIT",
803
+ "dependencies": {
804
+ "@radix-ui/react-context": "1.1.3",
805
+ "@radix-ui/react-primitive": "2.1.4"
806
+ },
807
+ "peerDependencies": {
808
+ "@types/react": "*",
809
+ "@types/react-dom": "*",
810
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
811
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
812
+ },
813
+ "peerDependenciesMeta": {
814
+ "@types/react": {
815
+ "optional": true
816
+ },
817
+ "@types/react-dom": {
818
+ "optional": true
819
+ }
820
+ }
821
+ },
822
+ "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-context": {
823
+ "version": "1.1.3",
824
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.3.tgz",
825
+ "integrity": "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==",
826
+ "license": "MIT",
827
+ "peerDependencies": {
828
+ "@types/react": "*",
829
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
830
+ },
831
+ "peerDependenciesMeta": {
832
+ "@types/react": {
833
+ "optional": true
834
+ }
835
+ }
836
+ },
837
+ "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-primitive": {
838
+ "version": "2.1.4",
839
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz",
840
+ "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==",
841
+ "license": "MIT",
842
+ "dependencies": {
843
+ "@radix-ui/react-slot": "1.2.4"
844
+ },
845
+ "peerDependencies": {
846
+ "@types/react": "*",
847
+ "@types/react-dom": "*",
848
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
849
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
850
+ },
851
+ "peerDependenciesMeta": {
852
+ "@types/react": {
853
+ "optional": true
854
+ },
855
+ "@types/react-dom": {
856
+ "optional": true
857
+ }
858
+ }
859
+ },
860
+ "node_modules/@radix-ui/react-roving-focus": {
861
+ "version": "1.1.11",
862
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz",
863
+ "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==",
864
+ "license": "MIT",
865
+ "dependencies": {
866
+ "@radix-ui/primitive": "1.1.3",
867
+ "@radix-ui/react-collection": "1.1.7",
868
+ "@radix-ui/react-compose-refs": "1.1.2",
869
+ "@radix-ui/react-context": "1.1.2",
870
+ "@radix-ui/react-direction": "1.1.1",
871
+ "@radix-ui/react-id": "1.1.1",
872
+ "@radix-ui/react-primitive": "2.1.3",
873
+ "@radix-ui/react-use-callback-ref": "1.1.1",
874
+ "@radix-ui/react-use-controllable-state": "1.2.2"
875
+ },
876
+ "peerDependencies": {
877
+ "@types/react": "*",
878
+ "@types/react-dom": "*",
879
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
880
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
881
+ },
882
+ "peerDependenciesMeta": {
883
+ "@types/react": {
884
+ "optional": true
885
+ },
886
+ "@types/react-dom": {
887
+ "optional": true
888
+ }
889
+ }
890
+ },
891
+ "node_modules/@radix-ui/react-separator": {
892
+ "version": "1.1.8",
893
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.8.tgz",
894
+ "integrity": "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==",
895
+ "license": "MIT",
896
+ "dependencies": {
897
+ "@radix-ui/react-primitive": "2.1.4"
898
+ },
899
+ "peerDependencies": {
900
+ "@types/react": "*",
901
+ "@types/react-dom": "*",
902
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
903
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
904
+ },
905
+ "peerDependenciesMeta": {
906
+ "@types/react": {
907
+ "optional": true
908
+ },
909
+ "@types/react-dom": {
910
+ "optional": true
911
+ }
912
+ }
913
+ },
914
+ "node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive": {
915
+ "version": "2.1.4",
916
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz",
917
+ "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==",
918
+ "license": "MIT",
919
+ "dependencies": {
920
+ "@radix-ui/react-slot": "1.2.4"
921
+ },
922
+ "peerDependencies": {
923
+ "@types/react": "*",
924
+ "@types/react-dom": "*",
925
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
926
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
927
+ },
928
+ "peerDependenciesMeta": {
929
+ "@types/react": {
930
+ "optional": true
931
+ },
932
+ "@types/react-dom": {
933
+ "optional": true
934
+ }
935
+ }
936
+ },
937
+ "node_modules/@radix-ui/react-slot": {
938
+ "version": "1.2.4",
939
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz",
940
+ "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==",
941
+ "license": "MIT",
942
+ "dependencies": {
943
+ "@radix-ui/react-compose-refs": "1.1.2"
944
+ },
945
+ "peerDependencies": {
946
+ "@types/react": "*",
947
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
948
+ },
949
+ "peerDependenciesMeta": {
950
+ "@types/react": {
951
+ "optional": true
952
+ }
953
+ }
954
+ },
955
+ "node_modules/@radix-ui/react-tooltip": {
956
+ "version": "1.2.8",
957
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz",
958
+ "integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==",
959
+ "license": "MIT",
960
+ "dependencies": {
961
+ "@radix-ui/primitive": "1.1.3",
962
+ "@radix-ui/react-compose-refs": "1.1.2",
963
+ "@radix-ui/react-context": "1.1.2",
964
+ "@radix-ui/react-dismissable-layer": "1.1.11",
965
+ "@radix-ui/react-id": "1.1.1",
966
+ "@radix-ui/react-popper": "1.2.8",
967
+ "@radix-ui/react-portal": "1.1.9",
968
+ "@radix-ui/react-presence": "1.1.5",
969
+ "@radix-ui/react-primitive": "2.1.3",
970
+ "@radix-ui/react-slot": "1.2.3",
971
+ "@radix-ui/react-use-controllable-state": "1.2.2",
972
+ "@radix-ui/react-visually-hidden": "1.2.3"
973
+ },
974
+ "peerDependencies": {
975
+ "@types/react": "*",
976
+ "@types/react-dom": "*",
977
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
978
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
979
+ },
980
+ "peerDependenciesMeta": {
981
+ "@types/react": {
982
+ "optional": true
983
+ },
984
+ "@types/react-dom": {
985
+ "optional": true
986
+ }
987
+ }
988
+ },
989
+ "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": {
990
+ "version": "1.2.3",
991
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
992
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
993
+ "license": "MIT",
994
+ "dependencies": {
995
+ "@radix-ui/react-compose-refs": "1.1.2"
996
+ },
997
+ "peerDependencies": {
998
+ "@types/react": "*",
999
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1000
+ },
1001
+ "peerDependenciesMeta": {
1002
+ "@types/react": {
1003
+ "optional": true
1004
+ }
1005
+ }
1006
+ },
1007
+ "node_modules/@radix-ui/react-use-callback-ref": {
1008
+ "version": "1.1.1",
1009
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
1010
+ "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
1011
  "license": "MIT",
1012
+ "peerDependencies": {
1013
+ "@types/react": "*",
1014
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1015
+ },
1016
+ "peerDependenciesMeta": {
1017
+ "@types/react": {
1018
+ "optional": true
1019
+ }
1020
  }
1021
  },
1022
+ "node_modules/@radix-ui/react-use-controllable-state": {
1023
+ "version": "1.2.2",
1024
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
1025
+ "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
 
 
 
1026
  "license": "MIT",
1027
+ "dependencies": {
1028
+ "@radix-ui/react-use-effect-event": "0.0.2",
1029
+ "@radix-ui/react-use-layout-effect": "1.1.1"
1030
+ },
1031
+ "peerDependencies": {
1032
+ "@types/react": "*",
1033
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1034
+ },
1035
+ "peerDependenciesMeta": {
1036
+ "@types/react": {
1037
+ "optional": true
1038
+ }
1039
  }
1040
  },
1041
+ "node_modules/@radix-ui/react-use-effect-event": {
1042
+ "version": "0.0.2",
1043
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
1044
+ "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
 
 
 
1045
  "license": "MIT",
1046
+ "dependencies": {
1047
+ "@radix-ui/react-use-layout-effect": "1.1.1"
1048
+ },
1049
+ "peerDependencies": {
1050
+ "@types/react": "*",
1051
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1052
+ },
1053
+ "peerDependenciesMeta": {
1054
+ "@types/react": {
1055
+ "optional": true
1056
+ }
1057
  }
1058
  },
1059
+ "node_modules/@radix-ui/react-use-escape-keydown": {
1060
+ "version": "1.1.1",
1061
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz",
1062
+ "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==",
 
 
 
1063
  "license": "MIT",
1064
+ "dependencies": {
1065
+ "@radix-ui/react-use-callback-ref": "1.1.1"
1066
+ },
1067
+ "peerDependencies": {
1068
+ "@types/react": "*",
1069
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1070
+ },
1071
+ "peerDependenciesMeta": {
1072
+ "@types/react": {
1073
+ "optional": true
1074
+ }
1075
  }
1076
  },
1077
+ "node_modules/@radix-ui/react-use-layout-effect": {
1078
+ "version": "1.1.1",
1079
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
1080
+ "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
 
 
 
1081
  "license": "MIT",
1082
+ "peerDependencies": {
1083
+ "@types/react": "*",
1084
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1085
+ },
1086
+ "peerDependenciesMeta": {
1087
+ "@types/react": {
1088
+ "optional": true
1089
+ }
1090
  }
1091
  },
1092
+ "node_modules/@radix-ui/react-use-rect": {
1093
+ "version": "1.1.1",
1094
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz",
1095
+ "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==",
 
1096
  "license": "MIT",
1097
  "dependencies": {
1098
+ "@radix-ui/rect": "1.1.1"
 
1099
  },
1100
+ "peerDependencies": {
1101
+ "@types/react": "*",
1102
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1103
+ },
1104
+ "peerDependenciesMeta": {
1105
+ "@types/react": {
1106
+ "optional": true
1107
+ }
1108
  }
1109
  },
1110
+ "node_modules/@radix-ui/react-use-size": {
1111
+ "version": "1.1.1",
1112
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
1113
+ "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
 
1114
  "license": "MIT",
1115
+ "dependencies": {
1116
+ "@radix-ui/react-use-layout-effect": "1.1.1"
1117
+ },
1118
+ "peerDependencies": {
1119
+ "@types/react": "*",
1120
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1121
+ },
1122
+ "peerDependenciesMeta": {
1123
+ "@types/react": {
1124
+ "optional": true
1125
+ }
1126
  }
1127
  },
1128
+ "node_modules/@radix-ui/react-visually-hidden": {
1129
+ "version": "1.2.3",
1130
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz",
1131
+ "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==",
 
1132
  "license": "MIT",
1133
  "dependencies": {
1134
+ "@radix-ui/react-primitive": "2.1.3"
 
1135
  },
1136
+ "peerDependencies": {
1137
+ "@types/react": "*",
1138
+ "@types/react-dom": "*",
1139
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1140
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1141
+ },
1142
+ "peerDependenciesMeta": {
1143
+ "@types/react": {
1144
+ "optional": true
1145
+ },
1146
+ "@types/react-dom": {
1147
+ "optional": true
1148
+ }
1149
  }
1150
  },
1151
+ "node_modules/@radix-ui/rect": {
1152
+ "version": "1.1.1",
1153
+ "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz",
1154
+ "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==",
1155
+ "license": "MIT"
1156
+ },
1157
  "node_modules/@reduxjs/toolkit": {
1158
  "version": "2.11.2",
1159
  "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.11.2.tgz",
 
1359
  "version": "18.3.7",
1360
  "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
1361
  "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
1362
+ "devOptional": true,
1363
  "license": "MIT",
1364
  "peerDependencies": {
1365
  "@types/react": "^18.0.0"
 
1434
  "dev": true,
1435
  "license": "MIT"
1436
  },
1437
+ "node_modules/aria-hidden": {
1438
+ "version": "1.2.6",
1439
+ "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz",
1440
+ "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==",
1441
+ "license": "MIT",
1442
+ "dependencies": {
1443
+ "tslib": "^2.0.0"
1444
+ },
1445
+ "engines": {
1446
+ "node": ">=10"
1447
+ }
1448
+ },
1449
  "node_modules/autoprefixer": {
1450
  "version": "10.5.0",
1451
  "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz",
 
1695
  "node": ">= 6"
1696
  }
1697
  },
1698
+ "node_modules/class-variance-authority": {
1699
+ "version": "0.7.1",
1700
+ "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
1701
+ "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==",
1702
+ "license": "Apache-2.0",
1703
+ "dependencies": {
1704
+ "clsx": "^2.1.1"
1705
+ },
1706
+ "funding": {
1707
+ "url": "https://polar.sh/cva"
1708
+ }
1709
+ },
1710
  "node_modules/client-only": {
1711
  "version": "0.0.1",
1712
  "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
 
1937
  "node": ">=6"
1938
  }
1939
  },
1940
+ "node_modules/detect-node-es": {
1941
+ "version": "1.1.0",
1942
+ "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
1943
+ "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
1944
+ "license": "MIT"
1945
+ },
1946
  "node_modules/devlop": {
1947
  "version": "1.1.0",
1948
  "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
 
2199
  "url": "https://github.com/sponsors/ljharb"
2200
  }
2201
  },
2202
+ "node_modules/get-nonce": {
2203
+ "version": "1.0.1",
2204
+ "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
2205
+ "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
2206
+ "license": "MIT",
2207
+ "engines": {
2208
+ "node": ">=6"
2209
+ }
2210
+ },
2211
  "node_modules/glob-parent": {
2212
  "version": "6.0.2",
2213
  "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
 
4090
  }
4091
  }
4092
  },
4093
+ "node_modules/react-remove-scroll": {
4094
+ "version": "2.7.2",
4095
+ "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz",
4096
+ "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==",
4097
+ "license": "MIT",
4098
+ "dependencies": {
4099
+ "react-remove-scroll-bar": "^2.3.7",
4100
+ "react-style-singleton": "^2.2.3",
4101
+ "tslib": "^2.1.0",
4102
+ "use-callback-ref": "^1.3.3",
4103
+ "use-sidecar": "^1.1.3"
4104
+ },
4105
+ "engines": {
4106
+ "node": ">=10"
4107
+ },
4108
+ "peerDependencies": {
4109
+ "@types/react": "*",
4110
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
4111
+ },
4112
+ "peerDependenciesMeta": {
4113
+ "@types/react": {
4114
+ "optional": true
4115
+ }
4116
+ }
4117
+ },
4118
+ "node_modules/react-remove-scroll-bar": {
4119
+ "version": "2.3.8",
4120
+ "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
4121
+ "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
4122
+ "license": "MIT",
4123
+ "dependencies": {
4124
+ "react-style-singleton": "^2.2.2",
4125
+ "tslib": "^2.0.0"
4126
+ },
4127
+ "engines": {
4128
+ "node": ">=10"
4129
+ },
4130
+ "peerDependencies": {
4131
+ "@types/react": "*",
4132
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
4133
+ },
4134
+ "peerDependenciesMeta": {
4135
+ "@types/react": {
4136
+ "optional": true
4137
+ }
4138
+ }
4139
+ },
4140
+ "node_modules/react-style-singleton": {
4141
+ "version": "2.2.3",
4142
+ "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
4143
+ "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
4144
+ "license": "MIT",
4145
+ "dependencies": {
4146
+ "get-nonce": "^1.0.0",
4147
+ "tslib": "^2.0.0"
4148
+ },
4149
+ "engines": {
4150
+ "node": ">=10"
4151
+ },
4152
+ "peerDependencies": {
4153
+ "@types/react": "*",
4154
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
4155
+ },
4156
+ "peerDependenciesMeta": {
4157
+ "@types/react": {
4158
+ "optional": true
4159
+ }
4160
+ }
4161
+ },
4162
  "node_modules/react-syntax-highlighter": {
4163
  "version": "15.6.6",
4164
  "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.6.6.tgz",
 
4963
  "browserslist": ">= 4.21.0"
4964
  }
4965
  },
4966
+ "node_modules/use-callback-ref": {
4967
+ "version": "1.3.3",
4968
+ "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
4969
+ "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
4970
+ "license": "MIT",
4971
+ "dependencies": {
4972
+ "tslib": "^2.0.0"
4973
+ },
4974
+ "engines": {
4975
+ "node": ">=10"
4976
+ },
4977
+ "peerDependencies": {
4978
+ "@types/react": "*",
4979
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
4980
+ },
4981
+ "peerDependenciesMeta": {
4982
+ "@types/react": {
4983
+ "optional": true
4984
+ }
4985
+ }
4986
+ },
4987
+ "node_modules/use-sidecar": {
4988
+ "version": "1.1.3",
4989
+ "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
4990
+ "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
4991
+ "license": "MIT",
4992
+ "dependencies": {
4993
+ "detect-node-es": "^1.1.0",
4994
+ "tslib": "^2.0.0"
4995
+ },
4996
+ "engines": {
4997
+ "node": ">=10"
4998
+ },
4999
+ "peerDependencies": {
5000
+ "@types/react": "*",
5001
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
5002
+ },
5003
+ "peerDependenciesMeta": {
5004
+ "@types/react": {
5005
+ "optional": true
5006
+ }
5007
+ }
5008
+ },
5009
  "node_modules/use-sync-external-store": {
5010
  "version": "1.6.0",
5011
  "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
frontend/package.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
- "name": "god-mode-plus-ui",
3
- "version": "3.0.0",
4
  "private": true,
5
  "scripts": {
6
  "dev": "next dev -p 3000",
@@ -9,6 +9,13 @@
9
  "lint": "next lint"
10
  },
11
  "dependencies": {
 
 
 
 
 
 
 
12
  "clsx": "^2.1.1",
13
  "date-fns": "^3.6.0",
14
  "framer-motion": "^11.1.9",
 
1
  {
2
+ "name": "god-agent-os-ui",
3
+ "version": "8.0.0",
4
  "private": true,
5
  "scripts": {
6
  "dev": "next dev -p 3000",
 
9
  "lint": "next lint"
10
  },
11
  "dependencies": {
12
+ "@radix-ui/react-dialog": "^1.1.15",
13
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
14
+ "@radix-ui/react-progress": "^1.1.8",
15
+ "@radix-ui/react-separator": "^1.1.8",
16
+ "@radix-ui/react-slot": "^1.2.4",
17
+ "@radix-ui/react-tooltip": "^1.2.8",
18
+ "class-variance-authority": "^0.7.1",
19
  "clsx": "^2.1.1",
20
  "date-fns": "^3.6.0",
21
  "framer-motion": "^11.1.9",
frontend/store/useAppStore.ts ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { create } from 'zustand'
2
+ import { persist } from 'zustand/middleware'
3
+
4
+ export type NavPage = 'dashboard' | 'agents' | 'tasks' | 'memory' | 'knowledge' | 'workflows' | 'analytics' | 'settings'
5
+
6
+ export interface Agent {
7
+ id: string
8
+ name: string
9
+ role: string
10
+ status: 'active' | 'idle' | 'processing' | 'error'
11
+ color: string
12
+ icon: string
13
+ tasks: number
14
+ efficiency: number
15
+ uptime: number
16
+ lastAction: string
17
+ lastActionTime: string
18
+ }
19
+
20
+ export interface Task {
21
+ id: string
22
+ title: string
23
+ status: 'running' | 'completed' | 'pending' | 'failed'
24
+ agent: string
25
+ progress: number
26
+ createdAt: string
27
+ completedAt?: string
28
+ }
29
+
30
+ export interface ActivityItem {
31
+ id: string
32
+ agent: string
33
+ action: string
34
+ time: string
35
+ type: 'success' | 'processing' | 'info' | 'warning'
36
+ color: string
37
+ }
38
+
39
+ interface AppState {
40
+ // Navigation
41
+ currentPage: NavPage
42
+ sidebarCollapsed: boolean
43
+ commandPaletteOpen: boolean
44
+ godModeActive: boolean
45
+
46
+ // Data
47
+ agents: Agent[]
48
+ tasks: Task[]
49
+ activity: ActivityItem[]
50
+ metrics: {
51
+ totalAgents: number
52
+ tasksCompleted: number
53
+ timeSaved: number
54
+ successRate: number
55
+ }
56
+ systemResources: {
57
+ cpu: number
58
+ memory: number
59
+ storage: number
60
+ network: number
61
+ }
62
+
63
+ // Actions
64
+ setCurrentPage: (page: NavPage) => void
65
+ toggleSidebar: () => void
66
+ setCommandPaletteOpen: (open: boolean) => void
67
+ toggleGodMode: () => void
68
+ updateSystemResources: (resources: Partial<AppState['systemResources']>) => void
69
+ }
70
+
71
+ export const AGENTS: Agent[] = [
72
+ { id: '1', name: 'Research Agent', role: 'Web Intelligence', status: 'active', color: '#6366f1', icon: '🔬', tasks: 47, efficiency: 92, uptime: 99.8, lastAction: 'Completed market research analysis', lastActionTime: '2m ago' },
73
+ { id: '2', name: 'Data Agent', role: 'Data Processing', status: 'active', color: '#22d3ee', icon: '📊', tasks: 83, efficiency: 98, uptime: 99.5, lastAction: 'Processed 1.2M data points', lastActionTime: '12m ago' },
74
+ { id: '3', name: 'Content Agent', role: 'Content Generation', status: 'active', color: '#a78bfa', icon: '✍️', tasks: 31, efficiency: 95, uptime: 98.2, lastAction: 'Generated blog draft', lastActionTime: '25m ago' },
75
+ { id: '4', name: 'Code Agent', role: 'Software Development', status: 'active', color: '#34d399', icon: '💻', tasks: 62, efficiency: 99, uptime: 99.9, lastAction: 'Deployed production API', lastActionTime: '1h ago' },
76
+ { id: '5', name: 'Design Agent', role: 'UI/UX Design', status: 'active', color: '#f472b6', icon: '🎨', tasks: 24, efficiency: 90, uptime: 97.8, lastAction: 'Created UI/UX mockups', lastActionTime: '2h ago' },
77
+ { id: '6', name: 'Workflow Agent', role: 'Automation', status: 'processing', color: '#fb923c', icon: '⚙️', tasks: 19, efficiency: 93, uptime: 98.1, lastAction: 'Running automation pipeline', lastActionTime: 'now' },
78
+ { id: '7', name: 'Memory Agent', role: 'Knowledge Storage', status: 'idle', color: '#fbbf24', icon: '🧠', tasks: 156, efficiency: 97, uptime: 99.9, lastAction: 'Indexed 4,200 documents', lastActionTime: '3h ago' },
79
+ { id: '8', name: 'Deploy Agent', role: 'Cloud Deployment', status: 'idle', color: '#f87171', icon: '🚀', tasks: 12, efficiency: 100, uptime: 99.7, lastAction: 'Deployed to Vercel', lastActionTime: '5h ago' },
80
+ ]
81
+
82
+ export const ACTIVITY: ActivityItem[] = [
83
+ { id: '1', agent: 'Research Agent', action: 'Completed market research analysis', time: '2m ago', type: 'success', color: '#6366f1' },
84
+ { id: '2', agent: 'Data Agent', action: 'Processed 1.2M data points', time: '12m ago', type: 'processing', color: '#22d3ee' },
85
+ { id: '3', agent: 'Content Agent', action: 'Generated blog draft', time: '25m ago', type: 'success', color: '#a78bfa' },
86
+ { id: '4', agent: 'Code Agent', action: 'Deployed production API', time: '1h ago', type: 'success', color: '#34d399' },
87
+ { id: '5', agent: 'Design Agent', action: 'Created UI/UX mockups', time: '2h ago', type: 'info', color: '#f472b6' },
88
+ { id: '6', agent: 'Workflow Agent', action: 'Initiated automation pipeline', time: '3h ago', type: 'processing', color: '#fb923c' },
89
+ ]
90
+
91
+ export const TASKS: Task[] = [
92
+ { id: 't1', title: 'Analyze competitor pricing strategy', status: 'completed', agent: 'Research Agent', progress: 100, createdAt: '2h ago', completedAt: '2m ago' },
93
+ { id: 't2', title: 'Generate Q4 performance report', status: 'running', agent: 'Data Agent', progress: 67, createdAt: '30m ago' },
94
+ { id: 't3', title: 'Refactor authentication module', status: 'running', agent: 'Code Agent', progress: 45, createdAt: '1h ago' },
95
+ { id: 't4', title: 'Create landing page copy', status: 'pending', agent: 'Content Agent', progress: 0, createdAt: '5m ago' },
96
+ { id: 't5', title: 'Design system components v2', status: 'pending', agent: 'Design Agent', progress: 0, createdAt: '10m ago' },
97
+ { id: 't6', title: 'Set up CI/CD pipeline', status: 'completed', agent: 'Deploy Agent', progress: 100, createdAt: '5h ago', completedAt: '4h ago' },
98
+ ]
99
+
100
+ export const useAppStore = create<AppState>()(
101
+ persist(
102
+ (set) => ({
103
+ currentPage: 'dashboard',
104
+ sidebarCollapsed: false,
105
+ commandPaletteOpen: false,
106
+ godModeActive: true,
107
+ agents: AGENTS,
108
+ tasks: TASKS,
109
+ activity: ACTIVITY,
110
+ metrics: {
111
+ totalAgents: 12,
112
+ tasksCompleted: 247,
113
+ timeSaved: 128,
114
+ successRate: 98.6,
115
+ },
116
+ systemResources: {
117
+ cpu: 32,
118
+ memory: 68,
119
+ storage: 54,
120
+ network: 29,
121
+ },
122
+ setCurrentPage: (page) => set({ currentPage: page }),
123
+ toggleSidebar: () => set((state) => ({ sidebarCollapsed: !state.sidebarCollapsed })),
124
+ setCommandPaletteOpen: (open) => set({ commandPaletteOpen: open }),
125
+ toggleGodMode: () => set((state) => ({ godModeActive: !state.godModeActive })),
126
+ updateSystemResources: (resources) =>
127
+ set((state) => ({ systemResources: { ...state.systemResources, ...resources } })),
128
+ }),
129
+ { name: 'god-agent-os-store', partialize: (s) => ({ sidebarCollapsed: s.sidebarCollapsed, godModeActive: s.godModeActive }) }
130
+ )
131
+ )
frontend/tailwind.config.js CHANGED
@@ -5,85 +5,68 @@ module.exports = {
5
  './pages/**/*.{js,ts,jsx,tsx,mdx}',
6
  './components/**/*.{js,ts,jsx,tsx,mdx}',
7
  './app/**/*.{js,ts,jsx,tsx,mdx}',
 
8
  ],
9
  theme: {
10
  extend: {
11
  colors: {
12
- brand: {
13
- 50: '#eef2ff',
14
- 100: '#e0e7ff',
15
- 200: '#c7d2fe',
16
- 300: '#a5b4fc',
17
- 400: '#818cf8',
18
- 500: '#6366f1',
19
- 600: '#4f46e5',
20
- 700: '#4338ca',
21
- 800: '#3730a3',
22
- 900: '#312e81',
23
- },
24
  surface: {
25
- 0: '#0a0b0f',
26
- 1: '#0f1017',
27
- 2: '#13141e',
28
- 3: '#1a1b26',
29
- 4: '#1e2035',
30
- 5: '#252640',
31
- border: '#2a2b3d',
32
- hover: '#2e2f4a',
33
- },
34
- agent: {
35
- chat: '#22d3ee',
36
- planner: '#a78bfa',
37
- coding: '#34d399',
38
- debug: '#f87171',
39
- memory: '#fbbf24',
40
- connector: '#60a5fa',
41
- deploy: '#f472b6',
42
- workflow: '#fb923c',
43
- sandbox: '#4ade80',
44
- ui: '#e879f9',
45
  },
46
- neon: {
47
- green: '#00ff88',
48
- blue: '#00d4ff',
49
- purple: '#bf00ff',
50
- pink: '#ff0080',
51
  },
 
 
 
 
 
 
52
  },
53
  fontFamily: {
54
- mono: ['JetBrains Mono', 'Fira Code', 'Cascadia Code', 'monospace'],
55
  sans: ['Inter', 'system-ui', 'sans-serif'],
56
- burmese: ['Pyidaungsu', 'Myanmar Text', 'sans-serif'],
57
  },
58
- animation: {
59
- 'typing': 'typing 1.2s steps(3) infinite',
60
- 'pulse-slow': 'pulse 3s ease-in-out infinite',
61
- 'fade-in': 'fadeIn 0.3s ease-out',
62
- 'slide-up': 'slideUp 0.3s ease-out',
63
- 'slide-right': 'slideRight 0.25s ease-out',
64
- 'glow': 'glow 2s ease-in-out infinite',
65
- 'shimmer': 'shimmer 2s linear infinite',
66
- 'spin-slow': 'spin 3s linear infinite',
67
- 'bounce-dot': 'bounceDot 1.4s ease-in-out infinite',
68
  },
69
- keyframes: {
70
- typing: { '0%,100%': { opacity: '0.2' }, '50%': { opacity: '1' } },
71
- fadeIn: { from: { opacity: '0', transform: 'translateY(4px)' }, to: { opacity: '1', transform: 'translateY(0)' } },
72
- slideUp: { from: { opacity: '0', transform: 'translateY(12px)' }, to: { opacity: '1', transform: 'translateY(0)' } },
73
- slideRight: { from: { opacity: '0', transform: 'translateX(-12px)' }, to: { opacity: '1', transform: 'translateX(0)' } },
74
- glow: { '0%,100%': { boxShadow: '0 0 8px rgba(99,102,241,0.4)' }, '50%': { boxShadow: '0 0 20px rgba(99,102,241,0.8)' } },
75
- shimmer: { '0%': { backgroundPosition: '-200% 0' }, '100%': { backgroundPosition: '200% 0' } },
76
- bounceDot: { '0%,80%,100%': { transform: 'scale(0)' }, '40%': { transform: 'scale(1)' } },
77
  },
78
- backgroundImage: {
79
- 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
80
- 'gradient-conic': 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
81
- 'god-gradient': 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #a78bfa 100%)',
82
- 'neon-gradient': 'linear-gradient(90deg, #00ff88, #00d4ff, #bf00ff)',
83
- 'glass-gradient': 'linear-gradient(135deg, rgba(255,255,255,0.05) 0%, rgba(255,255,255,0.02) 100%)',
 
 
 
84
  },
85
- backdropBlur: {
86
- xs: '2px',
 
 
 
 
 
 
87
  },
88
  },
89
  },
 
5
  './pages/**/*.{js,ts,jsx,tsx,mdx}',
6
  './components/**/*.{js,ts,jsx,tsx,mdx}',
7
  './app/**/*.{js,ts,jsx,tsx,mdx}',
8
+ './store/**/*.{js,ts,jsx,tsx}',
9
  ],
10
  theme: {
11
  extend: {
12
  colors: {
13
+ void: '#05060d',
 
 
 
 
 
 
 
 
 
 
 
14
  surface: {
15
+ 1: '#0a0c16',
16
+ 2: '#0e1121',
17
+ 3: '#131729',
18
+ 4: '#191e32',
19
+ 5: '#1f263b',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  },
21
+ purple: {
22
+ DEFAULT: '#7c3aed',
23
+ bright: '#8b5cf6',
24
+ light: '#a78bfa',
25
+ dim: 'rgba(124,58,237,0.15)',
26
  },
27
+ blue: { DEFAULT: '#3b82f6', bright: '#60a5fa' },
28
+ cyan: { DEFAULT: '#22d3ee', bright: '#67e8f9' },
29
+ green: { DEFAULT: '#22c55e', bright: '#4ade80' },
30
+ amber: { DEFAULT: '#f59e0b', bright: '#fbbf24' },
31
+ pink: { DEFAULT: '#ec4899', bright: '#f472b6' },
32
+ neon: { purple: '#bf00ff', blue: '#00d4ff', green: '#00ff88' },
33
  },
34
  fontFamily: {
 
35
  sans: ['Inter', 'system-ui', 'sans-serif'],
36
+ mono: ['JetBrains Mono', 'Fira Code', 'monospace'],
37
  },
38
+ borderRadius: {
39
+ '2xl': '16px',
40
+ '3xl': '20px',
41
+ '4xl': '24px',
 
 
 
 
 
 
42
  },
43
+ backdropBlur: { xs: '2px', sm: '8px', md: '16px', lg: '24px', xl: '40px' },
44
+ boxShadow: {
45
+ 'glow-purple': '0 0 20px rgba(124,58,237,0.3), 0 0 60px rgba(124,58,237,0.1)',
46
+ 'glow-blue': '0 0 20px rgba(59,130,246,0.3)',
47
+ 'glow-cyan': '0 0 20px rgba(34,211,238,0.3)',
48
+ 'glow-green': '0 0 12px rgba(34,197,94,0.4)',
49
+ 'card': '0 4px 24px rgba(0,0,0,0.3)',
50
+ 'card-hover': '0 8px 40px rgba(0,0,0,0.4)',
51
  },
52
+ animation: {
53
+ 'fade-in-up': 'fadeInUp 0.4s ease-out forwards',
54
+ 'fade-in': 'fadeIn 0.3s ease-out forwards',
55
+ 'slide-left': 'slideInLeft 0.3s ease-out forwards',
56
+ 'pulse-glow': 'pulseGlow 2s ease-in-out infinite',
57
+ 'spin-slow': 'spin 8s linear infinite',
58
+ 'orb-float': 'orbFloat 6s ease-in-out infinite',
59
+ 'shimmer': 'shimmer 3s linear infinite',
60
+ 'typing-dot': 'typingDot 1.4s ease-in-out infinite',
61
  },
62
+ keyframes: {
63
+ fadeInUp: { from: { opacity: '0', transform: 'translateY(12px)' }, to: { opacity: '1', transform: 'translateY(0)' } },
64
+ fadeIn: { from: { opacity: '0' }, to: { opacity: '1' } },
65
+ slideInLeft: { from: { opacity: '0', transform: 'translateX(-16px)' }, to: { opacity: '1', transform: 'translateX(0)' } },
66
+ pulseGlow: { '0%,100%': { opacity: '0.6' }, '50%': { opacity: '1' } },
67
+ orbFloat: { '0%,100%': { transform: 'translateY(0px) rotate(0deg)' }, '33%': { transform: 'translateY(-8px) rotate(5deg)' }, '66%': { transform: 'translateY(4px) rotate(-3deg)' } },
68
+ shimmer: { '0%': { backgroundPosition: '-200% center' }, '100%': { backgroundPosition: '200% center' } },
69
+ typingDot: { '0%,80%,100%': { transform: 'scale(0)', opacity: '0.3' }, '40%': { transform: 'scale(1)', opacity: '1' } },
70
  },
71
  },
72
  },
frontend/vercel.json CHANGED
@@ -4,14 +4,16 @@
4
  "installCommand": "npm install",
5
  "framework": "nextjs",
6
  "env": {
7
- "NEXT_PUBLIC_API_URL": "https://PYAE1994-autonomous-coding-system.hf.space"
 
 
8
  },
9
  "headers": [
10
  {
11
  "source": "/(.*)",
12
  "headers": [
13
  { "key": "X-Content-Type-Options", "value": "nosniff" },
14
- { "key": "X-Frame-Options", "value": "DENY" },
15
  { "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" }
16
  ]
17
  }
 
4
  "installCommand": "npm install",
5
  "framework": "nextjs",
6
  "env": {
7
+ "NEXT_PUBLIC_API_URL": "https://PYAE1994-autonomous-coding-system.hf.space",
8
+ "NEXT_PUBLIC_APP_VERSION": "8.0.0",
9
+ "NEXT_PUBLIC_APP_NAME": "GOD AGENT OS"
10
  },
11
  "headers": [
12
  {
13
  "source": "/(.*)",
14
  "headers": [
15
  { "key": "X-Content-Type-Options", "value": "nosniff" },
16
+ { "key": "X-Frame-Options", "value": "SAMEORIGIN" },
17
  { "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" }
18
  ]
19
  }