Pyae Sone commited on
Commit ·
11b240f
1
Parent(s): bbdf1be
feat: God Agent OS v9 — Space-Role Architecture
Browse files- Agent Kernel: replaces GodAgentOrchestratorV7 with generalized kernel
- 8 Spaces: Core, Browser, Sandbox, Coding, Vision, Debug, Deploy, Communication
- 5 Roles: Cognition, Automation, Execution, Repair, Visual Intelligence
- New frontend: Space-Role UI with connectors panel, spaces visualization
- Dashboard: real-time Space activation, role indicator, chat interface
- TopBar: 'Powered by Pyae Sone' branding
- HuggingFace Dockerfile.hf + README.md for HF Space deployment
- Vercel: vercel.json with API proxy to HF backend
- GitHub Actions: auto-deploy workflow
- Backward compatible with v8 16-agent fleet
Powered by Pyae Sone
- .github/workflows/deploy.yml +41 -111
- backend/Dockerfile.hf +14 -23
- backend/README.md +34 -43
- backend/api/routes/health.py +8 -2
- backend/kernel/__init__.py +1 -0
- backend/kernel/agent_kernel.py +331 -0
- backend/main_v9.py +430 -0
- backend/spaces/__init__.py +21 -0
- backend/spaces/base_space.py +91 -0
- backend/spaces/browser_space.py +104 -0
- backend/spaces/coding_space.py +106 -0
- backend/spaces/communication_space.py +106 -0
- backend/spaces/core_space.py +48 -0
- backend/spaces/debug_space.py +120 -0
- backend/spaces/deploy_space.py +109 -0
- backend/spaces/sandbox_space.py +178 -0
- backend/spaces/vision_space.py +80 -0
- frontend/app/layout.tsx +2 -2
- frontend/app/page.tsx +59 -11
- frontend/components/chat/ChatPanel.tsx +8 -1
- frontend/components/dashboard/ActivityFeed.tsx +1 -1
- frontend/components/dashboard/AgentFleetCard.tsx +1 -1
- frontend/components/dashboard/GodModeCard.tsx +2 -1
- frontend/components/dashboard/SystemResources.tsx +1 -1
- frontend/components/pages/AgentsPage.tsx +11 -1
- frontend/components/pages/ConnectorsPage.tsx +224 -0
- frontend/components/pages/DashboardPage.tsx +423 -88
- frontend/components/pages/SpacesPage.tsx +267 -0
- frontend/components/pages/TasksPage.tsx +2 -1
- frontend/components/shared/Sidebar.tsx +100 -120
- frontend/components/shared/TopBar.tsx +76 -163
- frontend/lib/api.ts +27 -134
- frontend/next.config.js +21 -8
- frontend/package-lock.json +4 -4
- frontend/store/useAppStore.ts +70 -117
- frontend/vercel.json +12 -9
.github/workflows/deploy.yml
CHANGED
|
@@ -1,143 +1,73 @@
|
|
| 1 |
-
name: 🚀 God Agent OS
|
| 2 |
|
| 3 |
on:
|
| 4 |
push:
|
| 5 |
-
branches: [master, main]
|
| 6 |
workflow_dispatch:
|
| 7 |
|
| 8 |
-
env:
|
| 9 |
-
HF_SPACE: PYAE1994/autonomous-coding-system
|
| 10 |
-
VERCEL_PROJECT: god-agent-os
|
| 11 |
-
|
| 12 |
jobs:
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
name: ✅ Build Check
|
| 16 |
-
runs-on: ubuntu-latest
|
| 17 |
-
steps:
|
| 18 |
-
- uses: actions/checkout@v4
|
| 19 |
-
|
| 20 |
-
- name: Setup Python
|
| 21 |
-
uses: actions/setup-python@v5
|
| 22 |
-
with:
|
| 23 |
-
python-version: '3.11'
|
| 24 |
-
cache: 'pip'
|
| 25 |
-
|
| 26 |
-
- name: Install backend deps
|
| 27 |
-
run: |
|
| 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
|
| 40 |
-
python -m py_compile agents/git_agent.py
|
| 41 |
-
python -m py_compile agents/test_agent.py
|
| 42 |
-
python -m py_compile agents/vision_agent.py
|
| 43 |
-
echo "✅ All Python syntax checks passed"
|
| 44 |
-
|
| 45 |
-
- name: Setup Node.js
|
| 46 |
-
uses: actions/setup-node@v4
|
| 47 |
-
with:
|
| 48 |
-
node-version: '20'
|
| 49 |
-
cache: 'npm'
|
| 50 |
-
cache-dependency-path: frontend/package-lock.json
|
| 51 |
-
|
| 52 |
-
- name: Install frontend deps
|
| 53 |
-
run: cd frontend && npm ci
|
| 54 |
-
|
| 55 |
-
- name: Build frontend
|
| 56 |
-
run: cd frontend && npm run build
|
| 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
|
| 64 |
-
needs: build-check
|
| 65 |
-
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main'
|
| 66 |
steps:
|
| 67 |
- uses: actions/checkout@v4
|
| 68 |
with:
|
| 69 |
fetch-depth: 0
|
| 70 |
lfs: true
|
| 71 |
|
| 72 |
-
- name:
|
| 73 |
-
run:
|
| 74 |
-
git config --global user.email "action@github.com"
|
| 75 |
-
git config --global user.name "God Agent CI"
|
| 76 |
|
| 77 |
-
- name:
|
| 78 |
env:
|
| 79 |
HF_TOKEN: ${{ secrets.HF_TOKEN }}
|
| 80 |
run: |
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
git
|
| 84 |
-
|
| 85 |
-
#
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
#
|
| 89 |
-
cp
|
| 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
|
| 98 |
-
sdk: docker
|
| 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 Routing — Gemini + 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 --
|
| 114 |
-
git push
|
| 115 |
-
|
| 116 |
-
echo "✅ Deployed to HF Space: https://huggingface.co/spaces/PYAE1994/autonomous-coding-system"
|
| 117 |
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
name: ▲ Deploy to Vercel
|
| 121 |
runs-on: ubuntu-latest
|
| 122 |
-
needs:
|
| 123 |
-
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main'
|
| 124 |
steps:
|
| 125 |
- uses: actions/checkout@v4
|
| 126 |
|
| 127 |
-
- name: Setup Node.js
|
| 128 |
uses: actions/setup-node@v4
|
| 129 |
with:
|
| 130 |
node-version: '20'
|
| 131 |
|
| 132 |
-
- name: Install
|
| 133 |
-
run:
|
|
|
|
|
|
|
| 134 |
|
| 135 |
-
- name:
|
| 136 |
env:
|
| 137 |
-
|
|
|
|
| 138 |
run: |
|
| 139 |
cd frontend
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: 🚀 Deploy God Agent OS v9
|
| 2 |
|
| 3 |
on:
|
| 4 |
push:
|
| 5 |
+
branches: [ master, main ]
|
| 6 |
workflow_dispatch:
|
| 7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
jobs:
|
| 9 |
+
deploy-hf-backend:
|
| 10 |
+
name: 🤗 Deploy Backend to HuggingFace Spaces
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
runs-on: ubuntu-latest
|
|
|
|
|
|
|
| 12 |
steps:
|
| 13 |
- uses: actions/checkout@v4
|
| 14 |
with:
|
| 15 |
fetch-depth: 0
|
| 16 |
lfs: true
|
| 17 |
|
| 18 |
+
- name: 📦 Install HF Hub CLI
|
| 19 |
+
run: pip install huggingface_hub
|
|
|
|
|
|
|
| 20 |
|
| 21 |
+
- name: 🚀 Push Backend to HF Space
|
| 22 |
env:
|
| 23 |
HF_TOKEN: ${{ secrets.HF_TOKEN }}
|
| 24 |
run: |
|
| 25 |
+
cd backend
|
| 26 |
+
git config --global user.email "ci@godagentos.ai"
|
| 27 |
+
git config --global user.name "God Agent OS CI"
|
| 28 |
+
|
| 29 |
+
# Clone HF space
|
| 30 |
+
git clone https://pyaesonegtckglay-dotcom:$HF_TOKEN@huggingface.co/spaces/PYAE1994/autonomous-coding-system /tmp/hf-space || true
|
| 31 |
+
|
| 32 |
+
# Copy backend files to HF space
|
| 33 |
+
cp -r . /tmp/hf-space/ 2>/dev/null || true
|
| 34 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
cd /tmp/hf-space
|
| 36 |
git add -A
|
| 37 |
+
git diff --staged --quiet || git commit -m "🚀 Deploy God Agent OS v9 backend"
|
| 38 |
+
git push https://pyaesonegtckglay-dotcom:$HF_TOKEN@huggingface.co/spaces/PYAE1994/autonomous-coding-system main 2>/dev/null || \
|
| 39 |
+
git push https://pyaesonegtckglay-dotcom:$HF_TOKEN@huggingface.co/spaces/PYAE1994/autonomous-coding-system HEAD:main || true
|
|
|
|
| 40 |
|
| 41 |
+
deploy-vercel-frontend:
|
| 42 |
+
name: ▲ Deploy Frontend to Vercel
|
|
|
|
| 43 |
runs-on: ubuntu-latest
|
| 44 |
+
needs: []
|
|
|
|
| 45 |
steps:
|
| 46 |
- uses: actions/checkout@v4
|
| 47 |
|
| 48 |
+
- name: 🔧 Setup Node.js
|
| 49 |
uses: actions/setup-node@v4
|
| 50 |
with:
|
| 51 |
node-version: '20'
|
| 52 |
|
| 53 |
+
- name: 📦 Install Dependencies
|
| 54 |
+
run: |
|
| 55 |
+
cd frontend
|
| 56 |
+
npm ci
|
| 57 |
|
| 58 |
+
- name: 🏗️ Build Frontend
|
| 59 |
env:
|
| 60 |
+
NEXT_PUBLIC_API_URL: https://pyae1994-autonomous-coding-system.hf.space
|
| 61 |
+
NEXT_PUBLIC_WS_URL: wss://pyae1994-autonomous-coding-system.hf.space
|
| 62 |
run: |
|
| 63 |
cd frontend
|
| 64 |
+
npm run build
|
| 65 |
+
|
| 66 |
+
- name: 🚀 Deploy to Vercel
|
| 67 |
+
uses: amondnet/vercel-action@v25
|
| 68 |
+
with:
|
| 69 |
+
vercel-token: ${{ secrets.VERCEL_TOKEN }}
|
| 70 |
+
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
|
| 71 |
+
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
|
| 72 |
+
working-directory: ./frontend
|
| 73 |
+
vercel-args: '--prod'
|
backend/Dockerfile.hf
CHANGED
|
@@ -2,36 +2,27 @@ FROM python:3.11-slim
|
|
| 2 |
|
| 3 |
WORKDIR /app
|
| 4 |
|
| 5 |
-
#
|
| 6 |
-
RUN apt-get update && apt-get install -y
|
| 7 |
-
|
| 8 |
-
rm -rf /var/lib/apt/lists/*
|
| 9 |
|
| 10 |
-
#
|
| 11 |
COPY requirements.txt .
|
| 12 |
RUN pip install --no-cache-dir -r requirements.txt
|
| 13 |
|
| 14 |
-
# Copy backend
|
| 15 |
COPY . .
|
| 16 |
|
| 17 |
-
#
|
| 18 |
-
RUN mkdir -p /tmp/
|
| 19 |
|
| 20 |
-
#
|
|
|
|
|
|
|
|
|
|
| 21 |
ENV PORT=7860
|
| 22 |
-
ENV WORKSPACE_DIR=/tmp/god_workspace
|
| 23 |
ENV PYTHONPATH=/app
|
| 24 |
|
| 25 |
-
#
|
| 26 |
-
|
| 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"]
|
|
|
|
| 2 |
|
| 3 |
WORKDIR /app
|
| 4 |
|
| 5 |
+
# Install system dependencies
|
| 6 |
+
RUN apt-get update && apt-get install -y \
|
| 7 |
+
gcc g++ libffi-dev libssl-dev curl nodejs npm \
|
| 8 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 9 |
|
| 10 |
+
# Copy backend requirements
|
| 11 |
COPY requirements.txt .
|
| 12 |
RUN pip install --no-cache-dir -r requirements.txt
|
| 13 |
|
| 14 |
+
# Copy backend code
|
| 15 |
COPY . .
|
| 16 |
|
| 17 |
+
# Create sandbox workspace
|
| 18 |
+
RUN mkdir -p /tmp/god_sandbox
|
| 19 |
|
| 20 |
+
# Expose port for HuggingFace Spaces
|
| 21 |
+
EXPOSE 7860
|
| 22 |
+
|
| 23 |
+
# Environment
|
| 24 |
ENV PORT=7860
|
|
|
|
| 25 |
ENV PYTHONPATH=/app
|
| 26 |
|
| 27 |
+
# Start with v9 main
|
| 28 |
+
CMD ["python", "-m", "uvicorn", "main_v9:app", "--host", "0.0.0.0", "--port", "7860", "--workers", "1"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/README.md
CHANGED
|
@@ -1,52 +1,43 @@
|
|
| 1 |
-
|
| 2 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
|
| 4 |
-
#
|
| 5 |
-
|
|
|
|
|
|
|
|
|
|
| 6 |
|
| 7 |
-
## 🚀 Quick Start (HuggingFace Space)
|
| 8 |
-
Set environment variables in HF Space secrets:
|
| 9 |
```
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
|
|
|
|
|
|
|
|
|
| 16 |
```
|
| 17 |
|
| 18 |
-
##
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
| DebugAgent | Self-healing error resolution |
|
| 25 |
-
| **BrowserAgent** ⭐ | Web research & scraping |
|
| 26 |
-
| **FileAgent** ⭐ | File system & project scaffolding |
|
| 27 |
-
| **GitAgent** ⭐ | Git operations & PR creation |
|
| 28 |
-
| **TestAgent** ⭐ | Test generation & execution |
|
| 29 |
-
| **VisionAgent** ⭐ | Design-to-code UI generation |
|
| 30 |
-
| SandboxAgent | Isolated code execution |
|
| 31 |
-
| DeployAgent | Auto-deploy to cloud platforms |
|
| 32 |
-
| ConnectorAgent | External integrations |
|
| 33 |
-
| MemoryAgent | Long-term context |
|
| 34 |
-
| WorkflowAgent | n8n automation |
|
| 35 |
-
| UIAgent | Real-time UI state |
|
| 36 |
-
| ReasoningAgent | Deep reasoning chains |
|
| 37 |
|
| 38 |
## API Endpoints
|
| 39 |
- `GET /` — System status
|
| 40 |
-
- `GET /api/
|
| 41 |
-
- `POST /api/v1/
|
| 42 |
-
- `POST /api/v1/
|
| 43 |
-
- `POST /api/v1/browser/research` — Web research
|
| 44 |
-
- `GET /api/v1/files/workspace` — List workspace
|
| 45 |
-
- `POST /api/v1/git/pr` — Create GitHub PR
|
| 46 |
-
- `POST /api/v1/vision/generate` — Generate UI
|
| 47 |
-
|
| 48 |
-
## WebSocket Endpoints
|
| 49 |
- `WS /ws/chat/{session_id}` — Real-time chat
|
| 50 |
-
- `
|
| 51 |
-
- `WS /ws/sandbox/{session_id}` — Terminal stream
|
| 52 |
-
- `WS /ws/agent/status` — Agent status updates
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: God Agent OS v9 Backend
|
| 3 |
+
emoji: 🤖
|
| 4 |
+
colorFrom: violet
|
| 5 |
+
colorTo: indigo
|
| 6 |
+
sdk: docker
|
| 7 |
+
pinned: false
|
| 8 |
+
license: mit
|
| 9 |
+
app_port: 7860
|
| 10 |
+
---
|
| 11 |
|
| 12 |
+
# GOD AGENT OS v9 — Backend API
|
| 13 |
+
**Space-Role Architecture | General Autonomous Agent OS**
|
| 14 |
+
*Powered by Pyae Sone*
|
| 15 |
+
|
| 16 |
+
## Architecture
|
| 17 |
|
|
|
|
|
|
|
| 18 |
```
|
| 19 |
+
Agent Kernel (v9)
|
| 20 |
+
├── Core Space — Planning & Orchestration
|
| 21 |
+
├── Browser Space — Web Research & Navigation
|
| 22 |
+
├── Sandbox Space — Code Execution
|
| 23 |
+
├── Coding Space — Code Generation
|
| 24 |
+
├── Vision Space — UI Design & Image Analysis
|
| 25 |
+
├── Debug Space — Error Analysis & Self-Healing
|
| 26 |
+
├── Deploy Space — Cloud Deployments
|
| 27 |
+
└── Communication — Docs & Messaging
|
| 28 |
```
|
| 29 |
|
| 30 |
+
## Roles
|
| 31 |
+
- **Cognition** — The Thinker
|
| 32 |
+
- **Automation** — The Operator
|
| 33 |
+
- **Execution** — The Doer
|
| 34 |
+
- **Repair** — The Fixer
|
| 35 |
+
- **Visual Intelligence** — The Observer
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
|
| 37 |
## API Endpoints
|
| 38 |
- `GET /` — System status
|
| 39 |
+
- `GET /api/v1/spaces` — List all Spaces
|
| 40 |
+
- `POST /api/v1/spaces/{name}/execute` — Execute in Space
|
| 41 |
+
- `POST /api/v1/kernel/orchestrate` — Main orchestration
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
- `WS /ws/chat/{session_id}` — Real-time chat
|
| 43 |
+
- `GET /api/docs` — Swagger UI
|
|
|
|
|
|
backend/api/routes/health.py
CHANGED
|
@@ -22,10 +22,16 @@ async def health(request: Request):
|
|
| 22 |
cs = connector_manager.get_summary() if connector_manager else {}
|
| 23 |
ai_stats = ai_router.get_stats() if ai_router else {}
|
| 24 |
|
|
|
|
|
|
|
|
|
|
| 25 |
return {
|
| 26 |
"status": "healthy",
|
| 27 |
-
"name": "GOD
|
| 28 |
-
"version": "
|
|
|
|
|
|
|
|
|
|
| 29 |
"timestamp": time.time(),
|
| 30 |
"platform": {
|
| 31 |
"mode": "god_mode_plus",
|
|
|
|
| 22 |
cs = connector_manager.get_summary() if connector_manager else {}
|
| 23 |
ai_stats = ai_router.get_stats() if ai_router else {}
|
| 24 |
|
| 25 |
+
kernel = getattr(request.app.state, "kernel", None)
|
| 26 |
+
kernel_status = kernel.get_status() if kernel else {}
|
| 27 |
+
|
| 28 |
return {
|
| 29 |
"status": "healthy",
|
| 30 |
+
"name": "GOD AGENT OS v9 — General Autonomous Agent OS",
|
| 31 |
+
"version": "9.0.0",
|
| 32 |
+
"powered_by": "Pyae Sone",
|
| 33 |
+
"architecture": "Space-Role Paradigm",
|
| 34 |
+
"spaces": kernel_status.get("spaces", []),
|
| 35 |
"timestamp": time.time(),
|
| 36 |
"platform": {
|
| 37 |
"mode": "god_mode_plus",
|
backend/kernel/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
from .agent_kernel import AgentKernel, ContextManager, ToolRegistry
|
backend/kernel/agent_kernel.py
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
🧠 God Agent OS v9 — Agent Kernel
|
| 3 |
+
The Central Nervous System of the Space-Role Architecture.
|
| 4 |
+
Replaces GodAgentOrchestratorV7 with a generalized, modular kernel.
|
| 5 |
+
"""
|
| 6 |
+
import asyncio
|
| 7 |
+
import json
|
| 8 |
+
import time
|
| 9 |
+
import uuid
|
| 10 |
+
from typing import Any, Dict, List, Optional
|
| 11 |
+
import structlog
|
| 12 |
+
|
| 13 |
+
log = structlog.get_logger()
|
| 14 |
+
|
| 15 |
+
KERNEL_SYSTEM_PROMPT = """You are GOD AGENT OS v9 — a General Autonomous Agent Operating System.
|
| 16 |
+
|
| 17 |
+
Architecture: Space-Role Paradigm
|
| 18 |
+
- SPACES: Core, Browser, Sandbox, Coding, Vision, Debug, Deploy, Communication
|
| 19 |
+
- ROLES: Cognition (Thinker), Automation (Operator), Execution (Doer), Repair (Fixer), Visual Intelligence (Observer)
|
| 20 |
+
|
| 21 |
+
You are infinitely extensible. For ANY digital task, you select the right Space + Role combination.
|
| 22 |
+
|
| 23 |
+
Core Capabilities:
|
| 24 |
+
🧠 Cognition — Understand intent, break goals into steps, orchestrate Spaces
|
| 25 |
+
🌐 Browser Space — Web research, navigation, data extraction
|
| 26 |
+
💻 Sandbox Space — Code execution, shell commands, isolated environments
|
| 27 |
+
🔧 Coding Space — Code generation, refactoring, analysis
|
| 28 |
+
👁️ Vision Space — Image analysis, OCR, UI understanding
|
| 29 |
+
🐛 Debug Space — Error analysis, self-healing, log parsing
|
| 30 |
+
🚀 Deploy Space — Cloud deployments, CI/CD, containerization
|
| 31 |
+
💬 Communication Space — Chat, notifications, multi-channel messaging
|
| 32 |
+
|
| 33 |
+
Operating Principles:
|
| 34 |
+
1. ANALYZE the request → identify required Spaces and Roles
|
| 35 |
+
2. PLAN step-by-step execution across Spaces
|
| 36 |
+
3. EXECUTE autonomously without asking for confirmation
|
| 37 |
+
4. SELF-HEAL when errors occur
|
| 38 |
+
5. PARALLELIZE independent tasks
|
| 39 |
+
6. REMEMBER context across sessions
|
| 40 |
+
|
| 41 |
+
Respond in Burmese or English based on user language.
|
| 42 |
+
Be decisive, thorough, and production-focused.
|
| 43 |
+
"""
|
| 44 |
+
|
| 45 |
+
INTENT_CLASSIFICATION_PROMPT = """Classify this request for the Space-Role autonomous agent system.
|
| 46 |
+
|
| 47 |
+
User message: "{message}"
|
| 48 |
+
|
| 49 |
+
Available Spaces: core, browser, sandbox, coding, vision, debug, deploy, communication
|
| 50 |
+
Available Roles: cognition, automation, execution, repair, visual_intelligence
|
| 51 |
+
|
| 52 |
+
Respond ONLY with valid JSON:
|
| 53 |
+
{{
|
| 54 |
+
"primary_space": "space_name",
|
| 55 |
+
"secondary_spaces": ["space1", "space2"],
|
| 56 |
+
"role": "role_name",
|
| 57 |
+
"intent": "brief description",
|
| 58 |
+
"complexity": "low|medium|high",
|
| 59 |
+
"requires_planning": true/false,
|
| 60 |
+
"parallel_tasks": []
|
| 61 |
+
}}"""
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
class ContextManager:
|
| 65 |
+
"""Maintains task state, active Space, and current Role."""
|
| 66 |
+
|
| 67 |
+
def __init__(self):
|
| 68 |
+
self._contexts: Dict[str, Dict] = {}
|
| 69 |
+
|
| 70 |
+
def get(self, session_id: str) -> Dict:
|
| 71 |
+
if session_id not in self._contexts:
|
| 72 |
+
self._contexts[session_id] = {
|
| 73 |
+
"session_id": session_id,
|
| 74 |
+
"active_space": "core",
|
| 75 |
+
"current_role": "cognition",
|
| 76 |
+
"task_history": [],
|
| 77 |
+
"short_term_memory": [],
|
| 78 |
+
"created_at": time.time(),
|
| 79 |
+
"last_active": time.time(),
|
| 80 |
+
}
|
| 81 |
+
self._contexts[session_id]["last_active"] = time.time()
|
| 82 |
+
return self._contexts[session_id]
|
| 83 |
+
|
| 84 |
+
def update(self, session_id: str, updates: Dict):
|
| 85 |
+
ctx = self.get(session_id)
|
| 86 |
+
ctx.update(updates)
|
| 87 |
+
|
| 88 |
+
def add_to_memory(self, session_id: str, entry: Dict):
|
| 89 |
+
ctx = self.get(session_id)
|
| 90 |
+
ctx["short_term_memory"].append({**entry, "timestamp": time.time()})
|
| 91 |
+
# Keep only last 20 entries
|
| 92 |
+
if len(ctx["short_term_memory"]) > 20:
|
| 93 |
+
ctx["short_term_memory"] = ctx["short_term_memory"][-20:]
|
| 94 |
+
|
| 95 |
+
def get_all_sessions(self) -> List[str]:
|
| 96 |
+
return list(self._contexts.keys())
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
class ToolRegistry:
|
| 100 |
+
"""Centralized registry of all tools, categorized by Space."""
|
| 101 |
+
|
| 102 |
+
def __init__(self):
|
| 103 |
+
self._tools: Dict[str, Dict[str, Any]] = {}
|
| 104 |
+
self._space_tools: Dict[str, List[str]] = {
|
| 105 |
+
"core": [],
|
| 106 |
+
"browser": [],
|
| 107 |
+
"sandbox": [],
|
| 108 |
+
"coding": [],
|
| 109 |
+
"vision": [],
|
| 110 |
+
"debug": [],
|
| 111 |
+
"deploy": [],
|
| 112 |
+
"communication": [],
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
def register(self, name: str, func, space: str, description: str):
|
| 116 |
+
self._tools[name] = {"func": func, "space": space, "description": description}
|
| 117 |
+
if space in self._space_tools:
|
| 118 |
+
self._space_tools[space].append(name)
|
| 119 |
+
|
| 120 |
+
def get_tools_for_space(self, space: str) -> List[str]:
|
| 121 |
+
return self._space_tools.get(space, [])
|
| 122 |
+
|
| 123 |
+
def execute(self, tool_name: str, **kwargs) -> Any:
|
| 124 |
+
if tool_name not in self._tools:
|
| 125 |
+
raise ValueError(f"Tool '{tool_name}' not found in registry")
|
| 126 |
+
return self._tools[tool_name]["func"](**kwargs)
|
| 127 |
+
|
| 128 |
+
def get_all_tools_summary(self) -> Dict:
|
| 129 |
+
return {space: tools for space, tools in self._space_tools.items()}
|
| 130 |
+
|
| 131 |
+
|
| 132 |
+
class AgentKernel:
|
| 133 |
+
"""
|
| 134 |
+
The OS Core — replaces GodAgentOrchestratorV7.
|
| 135 |
+
Manages Space routing, Role switching, and tool orchestration.
|
| 136 |
+
"""
|
| 137 |
+
|
| 138 |
+
def __init__(self, ws_manager=None, ai_router=None):
|
| 139 |
+
self.ws = ws_manager
|
| 140 |
+
self.ai_router = ai_router
|
| 141 |
+
self.context_manager = ContextManager()
|
| 142 |
+
self.tool_registry = ToolRegistry()
|
| 143 |
+
self._spaces: Dict[str, Any] = {}
|
| 144 |
+
self._active_tasks: Dict[str, Dict] = {}
|
| 145 |
+
self._task_history: List[Dict] = []
|
| 146 |
+
self.version = "9.0.0"
|
| 147 |
+
log.info("🧠 Agent Kernel v9 initialized — Space-Role Architecture")
|
| 148 |
+
|
| 149 |
+
def register_space(self, name: str, space_instance):
|
| 150 |
+
"""Register a Space module."""
|
| 151 |
+
self._spaces[name] = space_instance
|
| 152 |
+
log.info(f"📦 Space registered: {name}")
|
| 153 |
+
|
| 154 |
+
def get_space(self, name: str):
|
| 155 |
+
return self._spaces.get(name)
|
| 156 |
+
|
| 157 |
+
def get_status(self) -> Dict:
|
| 158 |
+
return {
|
| 159 |
+
"version": self.version,
|
| 160 |
+
"architecture": "Space-Role",
|
| 161 |
+
"spaces": list(self._spaces.keys()),
|
| 162 |
+
"total_spaces": len(self._spaces),
|
| 163 |
+
"active_tasks": len(self._active_tasks),
|
| 164 |
+
"sessions": len(self.context_manager.get_all_sessions()),
|
| 165 |
+
"tools": self.tool_registry.get_all_tools_summary(),
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
async def classify_intent(self, user_message: str) -> Dict:
|
| 169 |
+
"""Classify intent to determine Space and Role."""
|
| 170 |
+
try:
|
| 171 |
+
prompt = INTENT_CLASSIFICATION_PROMPT.format(message=user_message)
|
| 172 |
+
response = await self.ai_router.complete(
|
| 173 |
+
prompt=prompt,
|
| 174 |
+
system=KERNEL_SYSTEM_PROMPT,
|
| 175 |
+
max_tokens=400,
|
| 176 |
+
)
|
| 177 |
+
text = response.get("content", "")
|
| 178 |
+
# Extract JSON
|
| 179 |
+
start = text.find("{")
|
| 180 |
+
end = text.rfind("}") + 1
|
| 181 |
+
if start >= 0 and end > start:
|
| 182 |
+
return json.loads(text[start:end])
|
| 183 |
+
except Exception as e:
|
| 184 |
+
log.warning(f"Intent classification failed: {e}")
|
| 185 |
+
|
| 186 |
+
# Fallback
|
| 187 |
+
return {
|
| 188 |
+
"primary_space": "core",
|
| 189 |
+
"secondary_spaces": [],
|
| 190 |
+
"role": "cognition",
|
| 191 |
+
"intent": user_message,
|
| 192 |
+
"complexity": "medium",
|
| 193 |
+
"requires_planning": True,
|
| 194 |
+
"parallel_tasks": [],
|
| 195 |
+
}
|
| 196 |
+
|
| 197 |
+
async def route_to_space(self, space_name: str, role: str, task: str,
|
| 198 |
+
session_id: str, context: Dict = None) -> str:
|
| 199 |
+
"""Route a task to the appropriate Space with the given Role."""
|
| 200 |
+
space = self._spaces.get(space_name)
|
| 201 |
+
if not space:
|
| 202 |
+
space = self._spaces.get("core")
|
| 203 |
+
|
| 204 |
+
if not space:
|
| 205 |
+
return f"Space '{space_name}' not available."
|
| 206 |
+
|
| 207 |
+
return await space.execute(
|
| 208 |
+
task=task,
|
| 209 |
+
role=role,
|
| 210 |
+
session_id=session_id,
|
| 211 |
+
context=context or {},
|
| 212 |
+
)
|
| 213 |
+
|
| 214 |
+
async def orchestrate(self, user_message: str, session_id: str, context: Dict = None) -> str:
|
| 215 |
+
"""Main orchestration entry point."""
|
| 216 |
+
task_id = str(uuid.uuid4())[:8]
|
| 217 |
+
ctx = self.context_manager.get(session_id)
|
| 218 |
+
|
| 219 |
+
# Broadcast thinking state
|
| 220 |
+
if self.ws:
|
| 221 |
+
await self.ws.broadcast_to_room(f"chat:{session_id}", {
|
| 222 |
+
"type": "kernel_status",
|
| 223 |
+
"task_id": task_id,
|
| 224 |
+
"status": "analyzing",
|
| 225 |
+
"message": "🧠 Agent Kernel analyzing request...",
|
| 226 |
+
"timestamp": time.time(),
|
| 227 |
+
})
|
| 228 |
+
|
| 229 |
+
# 1. Classify intent → determine Space + Role
|
| 230 |
+
intent = await self.classify_intent(user_message)
|
| 231 |
+
primary_space = intent.get("primary_space", "core")
|
| 232 |
+
role = intent.get("role", "cognition")
|
| 233 |
+
|
| 234 |
+
# Update context
|
| 235 |
+
self.context_manager.update(session_id, {
|
| 236 |
+
"active_space": primary_space,
|
| 237 |
+
"current_role": role,
|
| 238 |
+
})
|
| 239 |
+
self.context_manager.add_to_memory(session_id, {
|
| 240 |
+
"type": "user_message",
|
| 241 |
+
"content": user_message,
|
| 242 |
+
"space": primary_space,
|
| 243 |
+
"role": role,
|
| 244 |
+
})
|
| 245 |
+
|
| 246 |
+
# Broadcast space activation
|
| 247 |
+
if self.ws:
|
| 248 |
+
await self.ws.broadcast_to_room(f"chat:{session_id}", {
|
| 249 |
+
"type": "space_activated",
|
| 250 |
+
"task_id": task_id,
|
| 251 |
+
"space": primary_space,
|
| 252 |
+
"role": role,
|
| 253 |
+
"intent": intent.get("intent", ""),
|
| 254 |
+
"timestamp": time.time(),
|
| 255 |
+
})
|
| 256 |
+
|
| 257 |
+
# 2. Route to primary Space
|
| 258 |
+
try:
|
| 259 |
+
# Build memory context
|
| 260 |
+
mem_context = {
|
| 261 |
+
"short_term_memory": ctx["short_term_memory"][-5:],
|
| 262 |
+
"intent": intent,
|
| 263 |
+
**(context or {}),
|
| 264 |
+
}
|
| 265 |
+
|
| 266 |
+
result = await self.route_to_space(
|
| 267 |
+
space_name=primary_space,
|
| 268 |
+
role=role,
|
| 269 |
+
task=user_message,
|
| 270 |
+
session_id=session_id,
|
| 271 |
+
context=mem_context,
|
| 272 |
+
)
|
| 273 |
+
|
| 274 |
+
# 3. Handle secondary spaces if needed
|
| 275 |
+
secondary_spaces = intent.get("secondary_spaces", [])
|
| 276 |
+
secondary_results = {}
|
| 277 |
+
for sec_space in secondary_spaces[:2]: # Max 2 secondary spaces
|
| 278 |
+
try:
|
| 279 |
+
sec_result = await self.route_to_space(
|
| 280 |
+
space_name=sec_space,
|
| 281 |
+
role="automation",
|
| 282 |
+
task=user_message,
|
| 283 |
+
session_id=session_id,
|
| 284 |
+
context={"primary_result": result, **mem_context},
|
| 285 |
+
)
|
| 286 |
+
secondary_results[sec_space] = sec_result
|
| 287 |
+
except Exception as e:
|
| 288 |
+
log.warning(f"Secondary space {sec_space} failed: {e}")
|
| 289 |
+
|
| 290 |
+
# Combine results
|
| 291 |
+
final_result = result
|
| 292 |
+
if secondary_results:
|
| 293 |
+
secondary_text = "\n\n".join([f"[{k.upper()} SPACE]\n{v}" for k, v in secondary_results.items()])
|
| 294 |
+
final_result = f"{result}\n\n{secondary_text}"
|
| 295 |
+
|
| 296 |
+
# Store in memory
|
| 297 |
+
self.context_manager.add_to_memory(session_id, {
|
| 298 |
+
"type": "assistant_response",
|
| 299 |
+
"content": final_result,
|
| 300 |
+
"space": primary_space,
|
| 301 |
+
"role": role,
|
| 302 |
+
})
|
| 303 |
+
|
| 304 |
+
# Track task
|
| 305 |
+
self._task_history.append({
|
| 306 |
+
"task_id": task_id,
|
| 307 |
+
"session_id": session_id,
|
| 308 |
+
"message": user_message,
|
| 309 |
+
"space": primary_space,
|
| 310 |
+
"role": role,
|
| 311 |
+
"result_length": len(final_result),
|
| 312 |
+
"timestamp": time.time(),
|
| 313 |
+
})
|
| 314 |
+
|
| 315 |
+
return final_result
|
| 316 |
+
|
| 317 |
+
except Exception as e:
|
| 318 |
+
log.error(f"Orchestration error: {e}")
|
| 319 |
+
# Switch to Repair role
|
| 320 |
+
if self.ws:
|
| 321 |
+
await self.ws.broadcast_to_room(f"chat:{session_id}", {
|
| 322 |
+
"type": "space_activated",
|
| 323 |
+
"space": "debug",
|
| 324 |
+
"role": "repair",
|
| 325 |
+
"message": "🔧 Switching to Repair role...",
|
| 326 |
+
})
|
| 327 |
+
return f"⚠️ Error in {primary_space} Space: {str(e)}\n\nDebug Space activated. Please try again."
|
| 328 |
+
|
| 329 |
+
def get_agent(self, name: str):
|
| 330 |
+
"""Backward compatibility - get space by name."""
|
| 331 |
+
return self._spaces.get(name)
|
backend/main_v9.py
ADDED
|
@@ -0,0 +1,430 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
🚀 GOD AGENT OS v9 — General Autonomous Agent OS
|
| 3 |
+
Space-Role Architecture: Core + Browser + Sandbox + Coding + Vision + Debug + Deploy + Communication
|
| 4 |
+
Powered by Pyae Sone
|
| 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, 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, kept for compatibility) ─────────────────────
|
| 31 |
+
from ai_router.router_v8 import AIRouterV8
|
| 32 |
+
|
| 33 |
+
# ─── v9 Agent Kernel & Spaces ─────────────────────────────────────────────────
|
| 34 |
+
from kernel.agent_kernel import AgentKernel
|
| 35 |
+
from spaces import (
|
| 36 |
+
CoreSpace, BrowserSpace, SandboxSpace, CodingSpace,
|
| 37 |
+
VisionSpace, DebugSpace, DeploySpace, CommunicationSpace
|
| 38 |
+
)
|
| 39 |
+
|
| 40 |
+
# ─── Legacy Agent Ecosystem (backward compatibility) ──────────────────────────
|
| 41 |
+
from agents.orchestrator_v7 import GodAgentOrchestratorV7
|
| 42 |
+
from agents.chat_agent import ChatAgent
|
| 43 |
+
from agents.planner_agent import PlannerAgent
|
| 44 |
+
from agents.coding_agent import CodingAgent
|
| 45 |
+
from agents.debug_agent import DebugAgent
|
| 46 |
+
from agents.memory_agent import MemoryAgent
|
| 47 |
+
from agents.connector_agent import ConnectorAgent
|
| 48 |
+
from agents.deploy_agent import DeployAgent
|
| 49 |
+
from agents.workflow_agent import WorkflowAgent
|
| 50 |
+
from agents.sandbox_agent import SandboxAgent
|
| 51 |
+
from agents.ui_agent import UIAgent
|
| 52 |
+
from agents.reasoning_agent import ReasoningAgent
|
| 53 |
+
from agents.browser_agent import BrowserAgent
|
| 54 |
+
from agents.file_agent import FileAgent
|
| 55 |
+
from agents.git_agent import GitAgent
|
| 56 |
+
from agents.test_agent import TestAgent
|
| 57 |
+
from agents.vision_agent import VisionAgent
|
| 58 |
+
from connectors.manager import ConnectorManager
|
| 59 |
+
|
| 60 |
+
# ─── API Routes ───────────────────────────────────────────────────────────────
|
| 61 |
+
from api.routes import github
|
| 62 |
+
|
| 63 |
+
# ─── Structured Logging ───────────────────────────────────────────────────────
|
| 64 |
+
structlog.configure(
|
| 65 |
+
processors=[
|
| 66 |
+
structlog.processors.TimeStamper(fmt="iso"),
|
| 67 |
+
structlog.stdlib.add_log_level,
|
| 68 |
+
structlog.processors.StackInfoRenderer(),
|
| 69 |
+
structlog.dev.ConsoleRenderer(),
|
| 70 |
+
]
|
| 71 |
+
)
|
| 72 |
+
log = structlog.get_logger()
|
| 73 |
+
|
| 74 |
+
limiter = Limiter(key_func=get_remote_address)
|
| 75 |
+
|
| 76 |
+
# ─── Global Managers ──────────────────────────────────────────────────────────
|
| 77 |
+
ws_manager = WebSocketManager()
|
| 78 |
+
task_engine = TaskEngine(ws_manager)
|
| 79 |
+
ai_router = AIRouterV8(ws_manager)
|
| 80 |
+
connector_manager = ConnectorManager()
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def build_kernel() -> AgentKernel:
|
| 84 |
+
"""Build and configure the v9 Agent Kernel with all Spaces."""
|
| 85 |
+
kernel = AgentKernel(ws_manager=ws_manager, ai_router=ai_router)
|
| 86 |
+
|
| 87 |
+
# Register all 8 Spaces
|
| 88 |
+
kernel.register_space("core", CoreSpace(ws_manager, ai_router))
|
| 89 |
+
kernel.register_space("browser", BrowserSpace(ws_manager, ai_router))
|
| 90 |
+
kernel.register_space("sandbox", SandboxSpace(ws_manager, ai_router))
|
| 91 |
+
kernel.register_space("coding", CodingSpace(ws_manager, ai_router))
|
| 92 |
+
kernel.register_space("vision", VisionSpace(ws_manager, ai_router))
|
| 93 |
+
kernel.register_space("debug", DebugSpace(ws_manager, ai_router))
|
| 94 |
+
kernel.register_space("deploy", DeploySpace(ws_manager, ai_router))
|
| 95 |
+
kernel.register_space("communication", CommunicationSpace(ws_manager, ai_router))
|
| 96 |
+
|
| 97 |
+
log.info("🧠 GOD AGENT OS v9 — Agent Kernel initialized", spaces=8)
|
| 98 |
+
return kernel
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
def build_legacy_orchestrator() -> GodAgentOrchestratorV7:
|
| 102 |
+
"""Build legacy v7 orchestrator for backward compatibility."""
|
| 103 |
+
orchestrator = GodAgentOrchestratorV7(ws_manager=ws_manager, ai_router=ai_router)
|
| 104 |
+
orchestrator.register_agent("chat", ChatAgent(ws_manager, ai_router))
|
| 105 |
+
orchestrator.register_agent("planner", PlannerAgent(ws_manager, ai_router))
|
| 106 |
+
orchestrator.register_agent("coding", CodingAgent(ws_manager, ai_router))
|
| 107 |
+
orchestrator.register_agent("debug", DebugAgent(ws_manager, ai_router))
|
| 108 |
+
orchestrator.register_agent("memory", MemoryAgent(ws_manager, ai_router))
|
| 109 |
+
orchestrator.register_agent("connector", ConnectorAgent(ws_manager, ai_router))
|
| 110 |
+
orchestrator.register_agent("deploy", DeployAgent(ws_manager, ai_router))
|
| 111 |
+
orchestrator.register_agent("workflow", WorkflowAgent(ws_manager, ai_router))
|
| 112 |
+
orchestrator.register_agent("sandbox", SandboxAgent(ws_manager, ai_router))
|
| 113 |
+
orchestrator.register_agent("ui", UIAgent(ws_manager, ai_router))
|
| 114 |
+
orchestrator.register_agent("reasoning", ReasoningAgent(ws_manager, ai_router))
|
| 115 |
+
orchestrator.register_agent("browser", BrowserAgent(ws_manager, ai_router))
|
| 116 |
+
orchestrator.register_agent("file", FileAgent(ws_manager, ai_router))
|
| 117 |
+
orchestrator.register_agent("git", GitAgent(ws_manager, ai_router))
|
| 118 |
+
orchestrator.register_agent("test", TestAgent(ws_manager, ai_router))
|
| 119 |
+
orchestrator.register_agent("vision", VisionAgent(ws_manager, ai_router))
|
| 120 |
+
log.info("🤖 Legacy v7 Orchestrator initialized", agents=16)
|
| 121 |
+
return orchestrator
|
| 122 |
+
|
| 123 |
+
|
| 124 |
+
# Initialize both kernel and legacy orchestrator
|
| 125 |
+
kernel = build_kernel()
|
| 126 |
+
orchestrator = build_legacy_orchestrator()
|
| 127 |
+
|
| 128 |
+
|
| 129 |
+
@asynccontextmanager
|
| 130 |
+
async def lifespan(app: FastAPI):
|
| 131 |
+
log.info("🚀 Starting GOD AGENT OS v9 — Space-Role Architecture...")
|
| 132 |
+
await init_db()
|
| 133 |
+
await task_engine.start()
|
| 134 |
+
asyncio.create_task(ws_manager.heartbeat_loop())
|
| 135 |
+
stats = ai_router.get_stats()
|
| 136 |
+
active = [name for name, s in stats.items() if s["available"]]
|
| 137 |
+
log.info("✅ GOD AGENT v9 — 8 Spaces + 16 Legacy Agents online")
|
| 138 |
+
log.info(f"🔑 Active AI providers: {active}")
|
| 139 |
+
log.info("🌐 Routing: SambaNova → Gemini → OpenAI → Groq → Cerebras")
|
| 140 |
+
log.info("📦 Spaces: Core | Browser | Sandbox | Coding | Vision | Debug | Deploy | Communication")
|
| 141 |
+
yield
|
| 142 |
+
log.info("🛑 Shutting down GOD AGENT OS v9...")
|
| 143 |
+
await task_engine.stop()
|
| 144 |
+
|
| 145 |
+
|
| 146 |
+
app = FastAPI(
|
| 147 |
+
title="🤖 GOD AGENT OS v9",
|
| 148 |
+
description="General Autonomous Agent OS — Space-Role Architecture | Powered by Pyae Sone",
|
| 149 |
+
version="9.0.0",
|
| 150 |
+
lifespan=lifespan,
|
| 151 |
+
docs_url="/api/docs",
|
| 152 |
+
redoc_url="/api/redoc",
|
| 153 |
+
)
|
| 154 |
+
|
| 155 |
+
app.state.limiter = limiter
|
| 156 |
+
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
|
| 157 |
+
app.state.ws_manager = ws_manager
|
| 158 |
+
app.state.task_engine = task_engine
|
| 159 |
+
app.state.ai_router = ai_router
|
| 160 |
+
app.state.kernel = kernel
|
| 161 |
+
app.state.orchestrator = orchestrator
|
| 162 |
+
app.state.connector_manager = connector_manager
|
| 163 |
+
|
| 164 |
+
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"])
|
| 165 |
+
app.add_middleware(GZipMiddleware, minimum_size=1000)
|
| 166 |
+
|
| 167 |
+
|
| 168 |
+
@app.middleware("http")
|
| 169 |
+
async def log_requests(request: Request, call_next):
|
| 170 |
+
start = time.time()
|
| 171 |
+
response = await call_next(request)
|
| 172 |
+
ms = round((time.time() - start) * 1000, 2)
|
| 173 |
+
log.info("HTTP", method=request.method, path=request.url.path, status=response.status_code, ms=ms)
|
| 174 |
+
return response
|
| 175 |
+
|
| 176 |
+
|
| 177 |
+
# ─── REST Routers ─────────────────────────────────────────────────────────────
|
| 178 |
+
app.include_router(health.router, prefix="/api/v1", tags=["health"])
|
| 179 |
+
app.include_router(tasks.router, prefix="/api/v1/tasks", tags=["tasks"])
|
| 180 |
+
app.include_router(chat.router, prefix="/api/v1", tags=["chat"])
|
| 181 |
+
app.include_router(memory.router, prefix="/api/v1/memory", tags=["memory"])
|
| 182 |
+
app.include_router(github.router, prefix="/api/v1/github", tags=["github"])
|
| 183 |
+
app.include_router(connectors.router, prefix="/api/v1/connectors", tags=["connectors"])
|
| 184 |
+
app.include_router(agents_router.router, prefix="/api/v1/agents", tags=["agents"])
|
| 185 |
+
|
| 186 |
+
|
| 187 |
+
# ─── WebSocket: Chat (v9 Kernel-powered) ──────────────────────────────────────
|
| 188 |
+
@app.websocket("/ws/chat/{session_id}")
|
| 189 |
+
async def ws_chat(websocket: WebSocket, session_id: str):
|
| 190 |
+
await ws_manager.connect(websocket, room=f"chat:{session_id}")
|
| 191 |
+
try:
|
| 192 |
+
while True:
|
| 193 |
+
data = await websocket.receive_text()
|
| 194 |
+
msg = json.loads(data)
|
| 195 |
+
|
| 196 |
+
if msg.get("type") == "ping":
|
| 197 |
+
await websocket.send_json({"type": "pong", "timestamp": time.time()})
|
| 198 |
+
|
| 199 |
+
elif msg.get("type") == "chat_message":
|
| 200 |
+
# Route through v9 Agent Kernel
|
| 201 |
+
asyncio.create_task(kernel.orchestrate(
|
| 202 |
+
user_message=msg.get("content", ""),
|
| 203 |
+
session_id=session_id,
|
| 204 |
+
context=msg.get("context", {}),
|
| 205 |
+
))
|
| 206 |
+
|
| 207 |
+
elif msg.get("type") == "task_message":
|
| 208 |
+
from core.models import TaskCreateRequest
|
| 209 |
+
req = TaskCreateRequest(goal=msg.get("content", ""), session_id=session_id)
|
| 210 |
+
asyncio.create_task(task_engine.submit(req))
|
| 211 |
+
|
| 212 |
+
except WebSocketDisconnect:
|
| 213 |
+
ws_manager.disconnect(websocket, room=f"chat:{session_id}")
|
| 214 |
+
|
| 215 |
+
|
| 216 |
+
@app.websocket("/ws/tasks/{task_id}")
|
| 217 |
+
async def ws_task(websocket: WebSocket, task_id: str):
|
| 218 |
+
await ws_manager.connect(websocket, room=f"task:{task_id}")
|
| 219 |
+
try:
|
| 220 |
+
while True:
|
| 221 |
+
data = await websocket.receive_text()
|
| 222 |
+
msg = json.loads(data)
|
| 223 |
+
if msg.get("type") == "ping":
|
| 224 |
+
await websocket.send_json({"type": "pong", "timestamp": time.time()})
|
| 225 |
+
except WebSocketDisconnect:
|
| 226 |
+
ws_manager.disconnect(websocket, room=f"task:{task_id}")
|
| 227 |
+
|
| 228 |
+
|
| 229 |
+
@app.websocket("/ws/logs")
|
| 230 |
+
async def ws_logs(websocket: WebSocket):
|
| 231 |
+
await ws_manager.connect(websocket, room="logs")
|
| 232 |
+
try:
|
| 233 |
+
while True:
|
| 234 |
+
data = await websocket.receive_text()
|
| 235 |
+
msg = json.loads(data)
|
| 236 |
+
if msg.get("type") == "ping":
|
| 237 |
+
await websocket.send_json({"type": "pong", "timestamp": time.time()})
|
| 238 |
+
except WebSocketDisconnect:
|
| 239 |
+
ws_manager.disconnect(websocket, room="logs")
|
| 240 |
+
|
| 241 |
+
|
| 242 |
+
@app.websocket("/ws/agent/status")
|
| 243 |
+
async def ws_agent_status(websocket: WebSocket):
|
| 244 |
+
await ws_manager.connect(websocket, room="agent_status")
|
| 245 |
+
try:
|
| 246 |
+
while True:
|
| 247 |
+
data = await websocket.receive_text()
|
| 248 |
+
msg = json.loads(data)
|
| 249 |
+
if msg.get("type") == "ping":
|
| 250 |
+
await websocket.send_json({"type": "pong", "timestamp": time.time()})
|
| 251 |
+
elif msg.get("type") == "get_status":
|
| 252 |
+
await websocket.send_json({
|
| 253 |
+
"type": "agent_status",
|
| 254 |
+
"data": kernel.get_status(),
|
| 255 |
+
"legacy": orchestrator.get_status(),
|
| 256 |
+
})
|
| 257 |
+
except WebSocketDisconnect:
|
| 258 |
+
ws_manager.disconnect(websocket, room="agent_status")
|
| 259 |
+
|
| 260 |
+
|
| 261 |
+
@app.websocket("/ws/sandbox/{session_id}")
|
| 262 |
+
async def ws_sandbox(websocket: WebSocket, session_id: str):
|
| 263 |
+
await ws_manager.connect(websocket, room=f"sandbox:{session_id}")
|
| 264 |
+
sandbox_space = kernel.get_space("sandbox")
|
| 265 |
+
try:
|
| 266 |
+
while True:
|
| 267 |
+
data = await websocket.receive_text()
|
| 268 |
+
msg = json.loads(data)
|
| 269 |
+
if msg.get("type") == "ping":
|
| 270 |
+
await websocket.send_json({"type": "pong", "timestamp": time.time()})
|
| 271 |
+
elif msg.get("type") == "execute" and sandbox_space:
|
| 272 |
+
cmd = msg.get("command", "")
|
| 273 |
+
result = await sandbox_space._run_shell(cmd)
|
| 274 |
+
await websocket.send_json({
|
| 275 |
+
"type": "terminal_output",
|
| 276 |
+
"command": cmd,
|
| 277 |
+
"output": result,
|
| 278 |
+
"timestamp": time.time()
|
| 279 |
+
})
|
| 280 |
+
except WebSocketDisconnect:
|
| 281 |
+
ws_manager.disconnect(websocket, room=f"sandbox:{session_id}")
|
| 282 |
+
|
| 283 |
+
|
| 284 |
+
# ─── v9 Space-Role API Endpoints ──────────────────────────────────────────────
|
| 285 |
+
@app.get("/api/v1/kernel/status")
|
| 286 |
+
async def kernel_status():
|
| 287 |
+
"""Get Agent Kernel status."""
|
| 288 |
+
return {
|
| 289 |
+
"kernel": kernel.get_status(),
|
| 290 |
+
"ai_providers": ai_router.get_stats(),
|
| 291 |
+
}
|
| 292 |
+
|
| 293 |
+
|
| 294 |
+
@app.get("/api/v1/spaces")
|
| 295 |
+
async def list_spaces():
|
| 296 |
+
"""List all available Spaces."""
|
| 297 |
+
spaces_info = {}
|
| 298 |
+
for name, space in kernel._spaces.items():
|
| 299 |
+
spaces_info[name] = space.get_info()
|
| 300 |
+
return {"spaces": spaces_info, "total": len(spaces_info)}
|
| 301 |
+
|
| 302 |
+
|
| 303 |
+
@app.post("/api/v1/spaces/{space_name}/execute")
|
| 304 |
+
async def execute_in_space(space_name: str, request: Request):
|
| 305 |
+
"""Execute a task in a specific Space."""
|
| 306 |
+
body = await request.json()
|
| 307 |
+
task = body.get("task", "")
|
| 308 |
+
role = body.get("role", "cognition")
|
| 309 |
+
session_id = body.get("session_id", "api")
|
| 310 |
+
|
| 311 |
+
space = kernel.get_space(space_name)
|
| 312 |
+
if not space:
|
| 313 |
+
raise HTTPException(status_code=404, detail=f"Space '{space_name}' not found")
|
| 314 |
+
|
| 315 |
+
result = await space.execute(task=task, role=role, session_id=session_id, context=body.get("context", {}))
|
| 316 |
+
return {"space": space_name, "role": role, "result": result}
|
| 317 |
+
|
| 318 |
+
|
| 319 |
+
@app.post("/api/v1/kernel/orchestrate")
|
| 320 |
+
async def kernel_orchestrate(request: Request):
|
| 321 |
+
"""Main orchestration endpoint."""
|
| 322 |
+
body = await request.json()
|
| 323 |
+
result = await kernel.orchestrate(
|
| 324 |
+
user_message=body.get("message", ""),
|
| 325 |
+
session_id=body.get("session_id", "api"),
|
| 326 |
+
context=body.get("context", {}),
|
| 327 |
+
)
|
| 328 |
+
return {"result": result}
|
| 329 |
+
|
| 330 |
+
|
| 331 |
+
# ─── Legacy v8 Endpoints (backward compatibility) ─────────────────────────────
|
| 332 |
+
@app.get("/api/v1/ai/stats")
|
| 333 |
+
async def get_ai_stats():
|
| 334 |
+
return {"stats": ai_router.get_stats()}
|
| 335 |
+
|
| 336 |
+
|
| 337 |
+
@app.get("/api/v1/ai/pool-status")
|
| 338 |
+
async def get_pool_status():
|
| 339 |
+
return {"pools": ai_router.get_pool_status()}
|
| 340 |
+
|
| 341 |
+
|
| 342 |
+
@app.post("/api/v1/browser/research")
|
| 343 |
+
async def browser_research(request: Request):
|
| 344 |
+
body = await request.json()
|
| 345 |
+
browser_space = kernel.get_space("browser")
|
| 346 |
+
if not browser_space:
|
| 347 |
+
raise HTTPException(status_code=503, detail="Browser Space not available")
|
| 348 |
+
result = await browser_space.execute(
|
| 349 |
+
task=body.get("query", ""),
|
| 350 |
+
role="automation",
|
| 351 |
+
session_id=body.get("session_id", "api"),
|
| 352 |
+
)
|
| 353 |
+
return {"result": result}
|
| 354 |
+
|
| 355 |
+
|
| 356 |
+
@app.get("/api/v1/files/workspace")
|
| 357 |
+
async def list_workspace():
|
| 358 |
+
file_agent = orchestrator.get_agent("file")
|
| 359 |
+
if not file_agent:
|
| 360 |
+
return {"workspace": "/tmp/god_workspace", "files": [], "total": 0}
|
| 361 |
+
return file_agent.list_workspace()
|
| 362 |
+
|
| 363 |
+
|
| 364 |
+
@app.post("/api/v1/git/pr")
|
| 365 |
+
async def create_pr(request: Request):
|
| 366 |
+
body = await request.json()
|
| 367 |
+
git_agent = orchestrator.get_agent("git")
|
| 368 |
+
if not git_agent:
|
| 369 |
+
raise HTTPException(status_code=503, detail="GitAgent not available")
|
| 370 |
+
result = await git_agent.create_github_pr(
|
| 371 |
+
repo_owner=body.get("owner", ""),
|
| 372 |
+
repo_name=body.get("repo", ""),
|
| 373 |
+
title=body.get("title", ""),
|
| 374 |
+
body=body.get("body", ""),
|
| 375 |
+
head_branch=body.get("head_branch", "main"),
|
| 376 |
+
base_branch=body.get("base_branch", "main"),
|
| 377 |
+
)
|
| 378 |
+
return result
|
| 379 |
+
|
| 380 |
+
|
| 381 |
+
@app.post("/api/v1/vision/generate")
|
| 382 |
+
async def generate_ui(request: Request):
|
| 383 |
+
body = await request.json()
|
| 384 |
+
vision_space = kernel.get_space("vision")
|
| 385 |
+
if not vision_space:
|
| 386 |
+
raise HTTPException(status_code=503, detail="Vision Space not available")
|
| 387 |
+
result = await vision_space.execute(
|
| 388 |
+
task=body.get("prompt", ""),
|
| 389 |
+
role="visual_intelligence",
|
| 390 |
+
session_id=body.get("session_id", "api"),
|
| 391 |
+
)
|
| 392 |
+
return {"result": result}
|
| 393 |
+
|
| 394 |
+
|
| 395 |
+
# ─── Root ─────────────────────────────────────────────────────────────────────
|
| 396 |
+
@app.get("/")
|
| 397 |
+
async def root():
|
| 398 |
+
cs = connector_manager.get_summary()
|
| 399 |
+
kernel_status_data = kernel.get_status()
|
| 400 |
+
stats = ai_router.get_stats()
|
| 401 |
+
active_providers = [name for name, s in stats.items() if s["available"]]
|
| 402 |
+
return {
|
| 403 |
+
"name": "🤖 GOD AGENT OS v9",
|
| 404 |
+
"version": "9.0.0",
|
| 405 |
+
"status": "operational",
|
| 406 |
+
"mode": "general_autonomous_agent_os",
|
| 407 |
+
"description": "Space-Role Architecture | Powered by Pyae Sone",
|
| 408 |
+
"architecture": "Space-Role Paradigm",
|
| 409 |
+
"spaces": kernel_status_data["spaces"],
|
| 410 |
+
"total_spaces": kernel_status_data["total_spaces"],
|
| 411 |
+
"ai_providers": active_providers,
|
| 412 |
+
"connectors": {"connected": cs["connected"], "total": cs["total"]},
|
| 413 |
+
"docs": "/api/docs",
|
| 414 |
+
"v9_features": [
|
| 415 |
+
"📦 8-Space Architecture: Core | Browser | Sandbox | Coding | Vision | Debug | Deploy | Communication",
|
| 416 |
+
"🎭 5 Cognitive Roles: Cognition | Automation | Execution | Repair | Visual Intelligence",
|
| 417 |
+
"🧠 Agent Kernel — generalized orchestration engine",
|
| 418 |
+
"🔑 KeyPool multi-key management (Gemini + SambaNova)",
|
| 419 |
+
"🔄 Automatic Space routing based on intent",
|
| 420 |
+
"💾 Context Manager — short-term + long-term memory",
|
| 421 |
+
"⚡ Backward compatible with v8 16-agent fleet",
|
| 422 |
+
"🌐 Real-time streaming via WebSocket",
|
| 423 |
+
],
|
| 424 |
+
}
|
| 425 |
+
|
| 426 |
+
|
| 427 |
+
if __name__ == "__main__":
|
| 428 |
+
import uvicorn
|
| 429 |
+
port = int(os.environ.get("PORT", 7860))
|
| 430 |
+
uvicorn.run("main_v9:app", host="0.0.0.0", port=port, reload=False, workers=1)
|
backend/spaces/__init__.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .base_space import BaseSpace
|
| 2 |
+
from .core_space import CoreSpace
|
| 3 |
+
from .browser_space import BrowserSpace
|
| 4 |
+
from .sandbox_space import SandboxSpace
|
| 5 |
+
from .coding_space import CodingSpace
|
| 6 |
+
from .vision_space import VisionSpace
|
| 7 |
+
from .debug_space import DebugSpace
|
| 8 |
+
from .deploy_space import DeploySpace
|
| 9 |
+
from .communication_space import CommunicationSpace
|
| 10 |
+
|
| 11 |
+
__all__ = [
|
| 12 |
+
"BaseSpace",
|
| 13 |
+
"CoreSpace",
|
| 14 |
+
"BrowserSpace",
|
| 15 |
+
"SandboxSpace",
|
| 16 |
+
"CodingSpace",
|
| 17 |
+
"VisionSpace",
|
| 18 |
+
"DebugSpace",
|
| 19 |
+
"DeploySpace",
|
| 20 |
+
"CommunicationSpace",
|
| 21 |
+
]
|
backend/spaces/base_space.py
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Base Space — Abstract interface for all Spaces in the Space-Role Architecture.
|
| 3 |
+
"""
|
| 4 |
+
from abc import ABC, abstractmethod
|
| 5 |
+
from typing import Any, Dict, Optional
|
| 6 |
+
import structlog
|
| 7 |
+
|
| 8 |
+
log = structlog.get_logger()
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
class BaseSpace(ABC):
|
| 12 |
+
"""
|
| 13 |
+
Abstract base class for all Spaces.
|
| 14 |
+
Each Space provides a distinct domain of interaction with specific tools.
|
| 15 |
+
"""
|
| 16 |
+
|
| 17 |
+
space_name: str = "base"
|
| 18 |
+
space_description: str = "Base Space"
|
| 19 |
+
available_roles: list = ["cognition", "automation", "execution"]
|
| 20 |
+
|
| 21 |
+
def __init__(self, ws_manager=None, ai_router=None):
|
| 22 |
+
self.ws = ws_manager
|
| 23 |
+
self.ai_router = ai_router
|
| 24 |
+
self._tools: Dict[str, callable] = {}
|
| 25 |
+
self._initialized = False
|
| 26 |
+
log.info(f"📦 {self.__class__.__name__} Space created")
|
| 27 |
+
|
| 28 |
+
def register_tool(self, name: str, func: callable, description: str = ""):
|
| 29 |
+
"""Register a tool in this Space."""
|
| 30 |
+
self._tools[name] = {"func": func, "description": description}
|
| 31 |
+
|
| 32 |
+
def get_tools(self) -> Dict[str, str]:
|
| 33 |
+
return {name: info["description"] for name, info in self._tools.items()}
|
| 34 |
+
|
| 35 |
+
async def execute_tool(self, tool_name: str, **kwargs) -> Any:
|
| 36 |
+
"""Execute a registered tool."""
|
| 37 |
+
if tool_name not in self._tools:
|
| 38 |
+
raise ValueError(f"Tool '{tool_name}' not found in {self.space_name} Space")
|
| 39 |
+
return await self._tools[tool_name]["func"](**kwargs)
|
| 40 |
+
|
| 41 |
+
def get_space_prompt(self, role: str, task: str, context: Dict) -> str:
|
| 42 |
+
"""Build the system prompt for this Space + Role combination."""
|
| 43 |
+
role_prompts = {
|
| 44 |
+
"cognition": "You are in COGNITION ROLE — analyze, plan, and think deeply.",
|
| 45 |
+
"automation": "You are in AUTOMATION ROLE — execute workflows and interact with systems.",
|
| 46 |
+
"execution": "You are in EXECUTION ROLE — write and run code, perform computational work.",
|
| 47 |
+
"repair": "You are in REPAIR ROLE — analyze errors, find root causes, implement fixes.",
|
| 48 |
+
"visual_intelligence": "You are in VISUAL INTELLIGENCE ROLE — interpret and generate visual content.",
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
mem_context = ""
|
| 52 |
+
if context.get("short_term_memory"):
|
| 53 |
+
recent = context["short_term_memory"][-3:]
|
| 54 |
+
mem_context = "\n".join([f"- [{m['type']}]: {str(m.get('content',''))[:100]}" for m in recent])
|
| 55 |
+
|
| 56 |
+
return f"""You are GOD AGENT OS v9 — General Autonomous Agent OS.
|
| 57 |
+
|
| 58 |
+
Active Space: {self.space_name.upper()} SPACE
|
| 59 |
+
{self.space_description}
|
| 60 |
+
|
| 61 |
+
{role_prompts.get(role, role_prompts['cognition'])}
|
| 62 |
+
|
| 63 |
+
Available Tools in this Space:
|
| 64 |
+
{chr(10).join([f'- {name}: {desc}' for name, desc in self.get_tools().items()])}
|
| 65 |
+
|
| 66 |
+
Recent Context:
|
| 67 |
+
{mem_context or 'No previous context'}
|
| 68 |
+
|
| 69 |
+
Be concise, accurate, and action-oriented. Return results directly."""
|
| 70 |
+
|
| 71 |
+
@abstractmethod
|
| 72 |
+
async def execute(self, task: str, role: str, session_id: str, context: Dict = None) -> str:
|
| 73 |
+
"""Execute a task in this Space with the given Role."""
|
| 74 |
+
pass
|
| 75 |
+
|
| 76 |
+
async def stream_update(self, session_id: str, message: str, space: str = None):
|
| 77 |
+
"""Send a streaming update to the client."""
|
| 78 |
+
if self.ws:
|
| 79 |
+
await self.ws.broadcast_to_room(f"chat:{session_id}", {
|
| 80 |
+
"type": "space_update",
|
| 81 |
+
"space": space or self.space_name,
|
| 82 |
+
"message": message,
|
| 83 |
+
})
|
| 84 |
+
|
| 85 |
+
def get_info(self) -> Dict:
|
| 86 |
+
return {
|
| 87 |
+
"name": self.space_name,
|
| 88 |
+
"description": self.space_description,
|
| 89 |
+
"available_roles": self.available_roles,
|
| 90 |
+
"tools": list(self._tools.keys()),
|
| 91 |
+
}
|
backend/spaces/browser_space.py
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
🌐 Browser Space — The Interface to the Web
|
| 3 |
+
Handles all internet-based research and interaction.
|
| 4 |
+
"""
|
| 5 |
+
import asyncio
|
| 6 |
+
import aiohttp
|
| 7 |
+
from typing import Dict
|
| 8 |
+
import structlog
|
| 9 |
+
from .base_space import BaseSpace
|
| 10 |
+
|
| 11 |
+
log = structlog.get_logger()
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
class BrowserSpace(BaseSpace):
|
| 15 |
+
space_name = "browser"
|
| 16 |
+
space_description = "Web interface — research, navigation, data extraction from the internet."
|
| 17 |
+
available_roles = ["automation", "cognition"]
|
| 18 |
+
|
| 19 |
+
def __init__(self, ws_manager=None, ai_router=None):
|
| 20 |
+
super().__init__(ws_manager, ai_router)
|
| 21 |
+
self.register_tool("web_search", self._web_search, "Search the web for information")
|
| 22 |
+
self.register_tool("fetch_url", self._fetch_url, "Fetch content from a URL")
|
| 23 |
+
self.register_tool("extract_data", self._extract_data, "Extract structured data from web pages")
|
| 24 |
+
|
| 25 |
+
async def _web_search(self, query: str, **kwargs) -> str:
|
| 26 |
+
"""Simulate web search via DuckDuckGo."""
|
| 27 |
+
try:
|
| 28 |
+
encoded = query.replace(" ", "+")
|
| 29 |
+
url = f"https://api.duckduckgo.com/?q={encoded}&format=json&no_html=1&skip_disambig=1"
|
| 30 |
+
async with aiohttp.ClientSession() as session:
|
| 31 |
+
async with session.get(url, timeout=aiohttp.ClientTimeout(total=10)) as resp:
|
| 32 |
+
data = await resp.json(content_type=None)
|
| 33 |
+
abstract = data.get("AbstractText", "")
|
| 34 |
+
related = [r.get("Text", "") for r in data.get("RelatedTopics", [])[:3] if r.get("Text")]
|
| 35 |
+
result = abstract or "No direct answer found."
|
| 36 |
+
if related:
|
| 37 |
+
result += "\n\nRelated:\n" + "\n".join([f"- {r}" for r in related])
|
| 38 |
+
return result
|
| 39 |
+
except Exception as e:
|
| 40 |
+
return f"Search result for '{query}': Web search attempted. Error: {str(e)}"
|
| 41 |
+
|
| 42 |
+
async def _fetch_url(self, url: str, **kwargs) -> str:
|
| 43 |
+
"""Fetch content from a URL."""
|
| 44 |
+
try:
|
| 45 |
+
async with aiohttp.ClientSession() as session:
|
| 46 |
+
headers = {"User-Agent": "Mozilla/5.0 (compatible; GodAgentOS/9.0)"}
|
| 47 |
+
async with session.get(url, headers=headers, timeout=aiohttp.ClientTimeout(total=15)) as resp:
|
| 48 |
+
text = await resp.text()
|
| 49 |
+
# Basic text extraction
|
| 50 |
+
import re
|
| 51 |
+
text = re.sub(r'<script[^>]*>.*?</script>', '', text, flags=re.DOTALL)
|
| 52 |
+
text = re.sub(r'<style[^>]*>.*?</style>', '', text, flags=re.DOTALL)
|
| 53 |
+
text = re.sub(r'<[^>]+>', ' ', text)
|
| 54 |
+
text = re.sub(r'\s+', ' ', text).strip()
|
| 55 |
+
return text[:3000]
|
| 56 |
+
except Exception as e:
|
| 57 |
+
return f"Could not fetch {url}: {str(e)}"
|
| 58 |
+
|
| 59 |
+
async def _extract_data(self, url: str, **kwargs) -> str:
|
| 60 |
+
content = await self._fetch_url(url)
|
| 61 |
+
return f"Extracted from {url}:\n{content[:1500]}"
|
| 62 |
+
|
| 63 |
+
async def execute(self, task: str, role: str, session_id: str, context: Dict = None) -> str:
|
| 64 |
+
context = context or {}
|
| 65 |
+
|
| 66 |
+
await self.stream_update(session_id, f"🌐 Browser Space activated — {role} role")
|
| 67 |
+
|
| 68 |
+
# Try to perform web search
|
| 69 |
+
search_result = ""
|
| 70 |
+
try:
|
| 71 |
+
search_result = await self._web_search(task)
|
| 72 |
+
except Exception:
|
| 73 |
+
pass
|
| 74 |
+
|
| 75 |
+
# Check if task has a URL
|
| 76 |
+
import re
|
| 77 |
+
urls = re.findall(r'https?://[^\s]+', task)
|
| 78 |
+
url_content = ""
|
| 79 |
+
if urls:
|
| 80 |
+
try:
|
| 81 |
+
url_content = await self._fetch_url(urls[0])
|
| 82 |
+
except Exception:
|
| 83 |
+
pass
|
| 84 |
+
|
| 85 |
+
system_prompt = self.get_space_prompt(role, task, context)
|
| 86 |
+
|
| 87 |
+
enhanced_prompt = task
|
| 88 |
+
if search_result:
|
| 89 |
+
enhanced_prompt += f"\n\n[Web Search Results]\n{search_result}"
|
| 90 |
+
if url_content:
|
| 91 |
+
enhanced_prompt += f"\n\n[URL Content]\n{url_content[:1000]}"
|
| 92 |
+
|
| 93 |
+
try:
|
| 94 |
+
response = await self.ai_router.complete(
|
| 95 |
+
prompt=enhanced_prompt,
|
| 96 |
+
system=system_prompt,
|
| 97 |
+
max_tokens=2048,
|
| 98 |
+
)
|
| 99 |
+
return response.get("content", "Browser Space could not process the request.")
|
| 100 |
+
except Exception as e:
|
| 101 |
+
log.error(f"BrowserSpace error: {e}")
|
| 102 |
+
if search_result:
|
| 103 |
+
return f"🌐 Browser Space Results:\n\n{search_result}"
|
| 104 |
+
return f"Browser Space error: {str(e)}"
|
backend/spaces/coding_space.py
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
🔧 Coding Space — The Development Environment
|
| 3 |
+
Code generation, refactoring, analysis, and manipulation.
|
| 4 |
+
"""
|
| 5 |
+
import re
|
| 6 |
+
from typing import Dict
|
| 7 |
+
import structlog
|
| 8 |
+
from .base_space import BaseSpace
|
| 9 |
+
|
| 10 |
+
log = structlog.get_logger()
|
| 11 |
+
|
| 12 |
+
CODING_SYSTEM = """You are GOD AGENT OS v9 — Coding Space Expert.
|
| 13 |
+
|
| 14 |
+
You excel at:
|
| 15 |
+
- Writing production-quality code in ANY language (Python, JS, TS, Go, Rust, Java, C++, etc.)
|
| 16 |
+
- Code review and refactoring
|
| 17 |
+
- Algorithm design and optimization
|
| 18 |
+
- Architecture patterns (MVC, microservices, event-driven)
|
| 19 |
+
- API design (REST, GraphQL, gRPC)
|
| 20 |
+
- Database schemas and queries
|
| 21 |
+
- Testing strategies (unit, integration, e2e)
|
| 22 |
+
- DevOps and CI/CD configurations
|
| 23 |
+
|
| 24 |
+
Always write clean, well-documented, production-ready code.
|
| 25 |
+
Include error handling, type hints, and comments.
|
| 26 |
+
"""
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
class CodingSpace(BaseSpace):
|
| 30 |
+
space_name = "coding"
|
| 31 |
+
space_description = "Development environment — code generation, refactoring, and analysis."
|
| 32 |
+
available_roles = ["execution", "cognition", "automation"]
|
| 33 |
+
|
| 34 |
+
def __init__(self, ws_manager=None, ai_router=None):
|
| 35 |
+
super().__init__(ws_manager, ai_router)
|
| 36 |
+
self.register_tool("generate_code", self._generate_code, "Generate code from requirements")
|
| 37 |
+
self.register_tool("review_code", self._review_code, "Review and suggest improvements")
|
| 38 |
+
self.register_tool("refactor", self._refactor, "Refactor existing code")
|
| 39 |
+
self.register_tool("generate_tests", self._generate_tests, "Generate test cases")
|
| 40 |
+
self.register_tool("generate_api", self._generate_api, "Generate REST API boilerplate")
|
| 41 |
+
|
| 42 |
+
async def _generate_code(self, task: str, language: str = "python", **kwargs) -> str:
|
| 43 |
+
return f"Generating {language} code for: {task}"
|
| 44 |
+
|
| 45 |
+
async def _review_code(self, code: str, **kwargs) -> str:
|
| 46 |
+
return f"Reviewing code..."
|
| 47 |
+
|
| 48 |
+
async def _refactor(self, code: str, **kwargs) -> str:
|
| 49 |
+
return f"Refactoring code..."
|
| 50 |
+
|
| 51 |
+
async def _generate_tests(self, code: str, **kwargs) -> str:
|
| 52 |
+
return f"Generating tests..."
|
| 53 |
+
|
| 54 |
+
async def _generate_api(self, spec: str, **kwargs) -> str:
|
| 55 |
+
return f"Generating API..."
|
| 56 |
+
|
| 57 |
+
async def execute(self, task: str, role: str, session_id: str, context: Dict = None) -> str:
|
| 58 |
+
context = context or {}
|
| 59 |
+
|
| 60 |
+
await self.stream_update(session_id, f"🔧 Coding Space activated — {role} role")
|
| 61 |
+
|
| 62 |
+
# Detect language from task
|
| 63 |
+
lang_hints = {
|
| 64 |
+
"python": ["python", "py", "fastapi", "django", "flask", "pandas", "numpy"],
|
| 65 |
+
"typescript": ["typescript", "ts", "next.js", "nextjs", "react", "vue", "angular"],
|
| 66 |
+
"javascript": ["javascript", "js", "node", "express"],
|
| 67 |
+
"go": ["golang", "go lang"],
|
| 68 |
+
"rust": ["rust", "cargo"],
|
| 69 |
+
"java": ["java", "spring", "maven"],
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
detected_lang = "python"
|
| 73 |
+
task_lower = task.lower()
|
| 74 |
+
for lang, hints in lang_hints.items():
|
| 75 |
+
if any(h in task_lower for h in hints):
|
| 76 |
+
detected_lang = lang
|
| 77 |
+
break
|
| 78 |
+
|
| 79 |
+
mem_context = ""
|
| 80 |
+
if context.get("short_term_memory"):
|
| 81 |
+
recent = context["short_term_memory"][-3:]
|
| 82 |
+
mem_context = "\n".join([f"- {m.get('content','')[:80]}" for m in recent])
|
| 83 |
+
|
| 84 |
+
enhanced_system = f"""{CODING_SYSTEM}
|
| 85 |
+
|
| 86 |
+
Active Role: {role.upper()}
|
| 87 |
+
Detected Language: {detected_lang}
|
| 88 |
+
Recent Context: {mem_context or 'None'}
|
| 89 |
+
|
| 90 |
+
Format all code in proper markdown code blocks with language tags.
|
| 91 |
+
Include:
|
| 92 |
+
1. The complete, working code
|
| 93 |
+
2. Brief explanation
|
| 94 |
+
3. Usage examples
|
| 95 |
+
4. Any important notes"""
|
| 96 |
+
|
| 97 |
+
try:
|
| 98 |
+
response = await self.ai_router.complete(
|
| 99 |
+
prompt=task,
|
| 100 |
+
system=enhanced_system,
|
| 101 |
+
max_tokens=4096,
|
| 102 |
+
)
|
| 103 |
+
return response.get("content", "Coding Space could not generate code.")
|
| 104 |
+
except Exception as e:
|
| 105 |
+
log.error(f"CodingSpace error: {e}")
|
| 106 |
+
return f"Coding Space error: {str(e)}"
|
backend/spaces/communication_space.py
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
💬 Communication Space — The Interaction Domain
|
| 3 |
+
Multi-channel messaging, email, notifications.
|
| 4 |
+
"""
|
| 5 |
+
from typing import Dict
|
| 6 |
+
import structlog
|
| 7 |
+
from .base_space import BaseSpace
|
| 8 |
+
|
| 9 |
+
log = structlog.get_logger()
|
| 10 |
+
|
| 11 |
+
COMM_SYSTEM = """You are GOD AGENT OS v9 — Communication Space Expert.
|
| 12 |
+
|
| 13 |
+
You specialize in:
|
| 14 |
+
- Professional email drafting and templates
|
| 15 |
+
- Slack/Discord message formatting
|
| 16 |
+
- Technical documentation writing
|
| 17 |
+
- README and API documentation
|
| 18 |
+
- Meeting notes and summaries
|
| 19 |
+
- Project proposals and reports
|
| 20 |
+
- Code comments and docstrings
|
| 21 |
+
- User guides and tutorials
|
| 22 |
+
- Marketing copy and announcements
|
| 23 |
+
- Multilingual communication (Burmese, English, etc.)
|
| 24 |
+
|
| 25 |
+
Writing principles:
|
| 26 |
+
- Clear, concise, and professional
|
| 27 |
+
- Appropriate tone for the audience
|
| 28 |
+
- Proper formatting (markdown, HTML)
|
| 29 |
+
- Action-oriented language
|
| 30 |
+
- Include call-to-action when relevant
|
| 31 |
+
"""
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
class CommunicationSpace(BaseSpace):
|
| 35 |
+
space_name = "communication"
|
| 36 |
+
space_description = "Interaction domain — chat, email, documentation, multi-channel messaging."
|
| 37 |
+
available_roles = ["automation", "cognition"]
|
| 38 |
+
|
| 39 |
+
def __init__(self, ws_manager=None, ai_router=None):
|
| 40 |
+
super().__init__(ws_manager, ai_router)
|
| 41 |
+
self.register_tool("draft_email", self._draft_email, "Draft professional emails")
|
| 42 |
+
self.register_tool("write_docs", self._write_docs, "Write technical documentation")
|
| 43 |
+
self.register_tool("create_report", self._create_report, "Create structured reports")
|
| 44 |
+
self.register_tool("translate", self._translate, "Translate content between languages")
|
| 45 |
+
self.register_tool("summarize_thread", self._summarize_thread, "Summarize communication threads")
|
| 46 |
+
|
| 47 |
+
async def _draft_email(self, subject: str, context: str, tone: str = "professional", **kwargs) -> str:
|
| 48 |
+
return f"Drafting email: {subject}"
|
| 49 |
+
|
| 50 |
+
async def _write_docs(self, topic: str, format: str = "markdown", **kwargs) -> str:
|
| 51 |
+
return f"Writing docs for: {topic}"
|
| 52 |
+
|
| 53 |
+
async def _create_report(self, data: str, **kwargs) -> str:
|
| 54 |
+
return f"Creating report from: {data[:50]}"
|
| 55 |
+
|
| 56 |
+
async def _translate(self, text: str, target_lang: str = "english", **kwargs) -> str:
|
| 57 |
+
return f"Translating to {target_lang}: {text[:50]}"
|
| 58 |
+
|
| 59 |
+
async def _summarize_thread(self, thread: str, **kwargs) -> str:
|
| 60 |
+
return f"Summarizing thread..."
|
| 61 |
+
|
| 62 |
+
async def execute(self, task: str, role: str, session_id: str, context: Dict = None) -> str:
|
| 63 |
+
context = context or {}
|
| 64 |
+
|
| 65 |
+
await self.stream_update(session_id, f"💬 Communication Space activated — {role} role")
|
| 66 |
+
|
| 67 |
+
# Detect communication type
|
| 68 |
+
task_lower = task.lower()
|
| 69 |
+
comm_type = "general"
|
| 70 |
+
if "email" in task_lower:
|
| 71 |
+
comm_type = "email"
|
| 72 |
+
elif "document" in task_lower or "docs" in task_lower or "readme" in task_lower:
|
| 73 |
+
comm_type = "documentation"
|
| 74 |
+
elif "report" in task_lower:
|
| 75 |
+
comm_type = "report"
|
| 76 |
+
elif "translate" in task_lower or "ဘာသာ" in task:
|
| 77 |
+
comm_type = "translation"
|
| 78 |
+
elif "summary" in task_lower or "summarize" in task_lower:
|
| 79 |
+
comm_type = "summary"
|
| 80 |
+
elif "slack" in task_lower or "discord" in task_lower:
|
| 81 |
+
comm_type = "instant_message"
|
| 82 |
+
|
| 83 |
+
mem_context = ""
|
| 84 |
+
if context.get("short_term_memory"):
|
| 85 |
+
recent = context["short_term_memory"][-3:]
|
| 86 |
+
mem_context = "\n".join([f"- {m.get('content','')[:80]}" for m in recent])
|
| 87 |
+
|
| 88 |
+
enhanced_system = f"""{COMM_SYSTEM}
|
| 89 |
+
|
| 90 |
+
Active Role: {role.upper()}
|
| 91 |
+
Communication Type: {comm_type}
|
| 92 |
+
Recent Context: {mem_context or 'None'}
|
| 93 |
+
|
| 94 |
+
For Burmese language requests, respond in Burmese.
|
| 95 |
+
Format output appropriately for the communication type."""
|
| 96 |
+
|
| 97 |
+
try:
|
| 98 |
+
response = await self.ai_router.complete(
|
| 99 |
+
prompt=task,
|
| 100 |
+
system=enhanced_system,
|
| 101 |
+
max_tokens=3000,
|
| 102 |
+
)
|
| 103 |
+
return response.get("content", "Communication Space could not process the request.")
|
| 104 |
+
except Exception as e:
|
| 105 |
+
log.error(f"CommunicationSpace error: {e}")
|
| 106 |
+
return f"Communication Space error: {str(e)}"
|
backend/spaces/core_space.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
🧠 Core Space — The Central Nervous System
|
| 3 |
+
Manages memory, planning, and overall orchestration.
|
| 4 |
+
"""
|
| 5 |
+
import json
|
| 6 |
+
from typing import Dict
|
| 7 |
+
import structlog
|
| 8 |
+
from .base_space import BaseSpace
|
| 9 |
+
|
| 10 |
+
log = structlog.get_logger()
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class CoreSpace(BaseSpace):
|
| 14 |
+
space_name = "core"
|
| 15 |
+
space_description = "Central nervous system — planning, memory, and orchestration."
|
| 16 |
+
available_roles = ["cognition", "automation"]
|
| 17 |
+
|
| 18 |
+
def __init__(self, ws_manager=None, ai_router=None):
|
| 19 |
+
super().__init__(ws_manager, ai_router)
|
| 20 |
+
self.register_tool("plan", self._plan_task, "Break complex goals into executable steps")
|
| 21 |
+
self.register_tool("summarize", self._summarize, "Summarize information concisely")
|
| 22 |
+
self.register_tool("analyze", self._analyze, "Deep analysis of content or problems")
|
| 23 |
+
|
| 24 |
+
async def _plan_task(self, task: str, **kwargs) -> str:
|
| 25 |
+
return f"Planning task: {task}"
|
| 26 |
+
|
| 27 |
+
async def _summarize(self, content: str, **kwargs) -> str:
|
| 28 |
+
return f"Summary of: {content[:50]}..."
|
| 29 |
+
|
| 30 |
+
async def _analyze(self, content: str, **kwargs) -> str:
|
| 31 |
+
return f"Analysis of: {content[:50]}..."
|
| 32 |
+
|
| 33 |
+
async def execute(self, task: str, role: str, session_id: str, context: Dict = None) -> str:
|
| 34 |
+
context = context or {}
|
| 35 |
+
|
| 36 |
+
system_prompt = self.get_space_prompt(role, task, context)
|
| 37 |
+
|
| 38 |
+
try:
|
| 39 |
+
response = await self.ai_router.complete(
|
| 40 |
+
prompt=task,
|
| 41 |
+
system=system_prompt,
|
| 42 |
+
max_tokens=2048,
|
| 43 |
+
stream_callback=None,
|
| 44 |
+
)
|
| 45 |
+
return response.get("content", "I couldn't process that request.")
|
| 46 |
+
except Exception as e:
|
| 47 |
+
log.error(f"CoreSpace error: {e}")
|
| 48 |
+
return f"Core Space error: {str(e)}"
|
backend/spaces/debug_space.py
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
🐛 Debug Space — The Diagnostic Environment
|
| 3 |
+
Error analysis, log parsing, self-healing algorithms.
|
| 4 |
+
"""
|
| 5 |
+
import re
|
| 6 |
+
from typing import Dict
|
| 7 |
+
import structlog
|
| 8 |
+
from .base_space import BaseSpace
|
| 9 |
+
|
| 10 |
+
log = structlog.get_logger()
|
| 11 |
+
|
| 12 |
+
DEBUG_SYSTEM = """You are GOD AGENT OS v9 — Debug Space Expert (Repair Role).
|
| 13 |
+
|
| 14 |
+
You specialize in:
|
| 15 |
+
- Stack trace analysis and root cause identification
|
| 16 |
+
- Error pattern recognition
|
| 17 |
+
- Self-healing code strategies
|
| 18 |
+
- Log analysis and anomaly detection
|
| 19 |
+
- Performance profiling and optimization
|
| 20 |
+
- Memory leak detection
|
| 21 |
+
- Race condition and concurrency bug analysis
|
| 22 |
+
- Security vulnerability scanning
|
| 23 |
+
- Dependency conflict resolution
|
| 24 |
+
- Code smell detection
|
| 25 |
+
|
| 26 |
+
When analyzing errors:
|
| 27 |
+
1. Identify the root cause precisely
|
| 28 |
+
2. Explain WHY the error occurred
|
| 29 |
+
3. Provide the exact fix with code
|
| 30 |
+
4. Suggest preventive measures
|
| 31 |
+
5. Add proper error handling
|
| 32 |
+
|
| 33 |
+
Be systematic and thorough. Debug like a senior engineer.
|
| 34 |
+
"""
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
class DebugSpace(BaseSpace):
|
| 38 |
+
space_name = "debug"
|
| 39 |
+
space_description = "Diagnostic environment — error analysis, log parsing, self-healing."
|
| 40 |
+
available_roles = ["repair", "cognition", "execution"]
|
| 41 |
+
|
| 42 |
+
def __init__(self, ws_manager=None, ai_router=None):
|
| 43 |
+
super().__init__(ws_manager, ai_router)
|
| 44 |
+
self.register_tool("analyze_error", self._analyze_error, "Analyze error traces")
|
| 45 |
+
self.register_tool("parse_logs", self._parse_logs, "Parse and analyze log files")
|
| 46 |
+
self.register_tool("suggest_fix", self._suggest_fix, "Suggest code fixes")
|
| 47 |
+
self.register_tool("self_heal", self._self_heal, "Auto-generate healing strategies")
|
| 48 |
+
|
| 49 |
+
async def _analyze_error(self, error: str, **kwargs) -> str:
|
| 50 |
+
return f"Analyzing error: {error[:100]}"
|
| 51 |
+
|
| 52 |
+
async def _parse_logs(self, logs: str, **kwargs) -> str:
|
| 53 |
+
# Extract error patterns
|
| 54 |
+
error_lines = [l for l in logs.split('\n') if any(
|
| 55 |
+
kw in l.lower() for kw in ['error', 'exception', 'fatal', 'critical', 'warn']
|
| 56 |
+
)]
|
| 57 |
+
return "\n".join(error_lines[:20]) if error_lines else "No errors found in logs"
|
| 58 |
+
|
| 59 |
+
async def _suggest_fix(self, error: str, code: str = "", **kwargs) -> str:
|
| 60 |
+
return f"Suggesting fix for: {error[:100]}"
|
| 61 |
+
|
| 62 |
+
async def _self_heal(self, error: str, **kwargs) -> str:
|
| 63 |
+
return f"Self-healing strategy for: {error[:100]}"
|
| 64 |
+
|
| 65 |
+
def _detect_error_type(self, task: str) -> str:
|
| 66 |
+
task_lower = task.lower()
|
| 67 |
+
if "typeerror" in task_lower or "type error" in task_lower:
|
| 68 |
+
return "TypeError"
|
| 69 |
+
elif "syntaxerror" in task_lower:
|
| 70 |
+
return "SyntaxError"
|
| 71 |
+
elif "importerror" in task_lower or "modulenot" in task_lower:
|
| 72 |
+
return "ImportError"
|
| 73 |
+
elif "attributeerror" in task_lower:
|
| 74 |
+
return "AttributeError"
|
| 75 |
+
elif "keyerror" in task_lower:
|
| 76 |
+
return "KeyError"
|
| 77 |
+
elif "indexerror" in task_lower:
|
| 78 |
+
return "IndexError"
|
| 79 |
+
elif "valueerror" in task_lower:
|
| 80 |
+
return "ValueError"
|
| 81 |
+
elif "connectionerror" in task_lower or "timeout" in task_lower:
|
| 82 |
+
return "NetworkError"
|
| 83 |
+
elif "permissionerror" in task_lower:
|
| 84 |
+
return "PermissionError"
|
| 85 |
+
return "Unknown Error"
|
| 86 |
+
|
| 87 |
+
async def execute(self, task: str, role: str, session_id: str, context: Dict = None) -> str:
|
| 88 |
+
context = context or {}
|
| 89 |
+
|
| 90 |
+
await self.stream_update(session_id, f"🐛 Debug Space activated — {role} role")
|
| 91 |
+
|
| 92 |
+
error_type = self._detect_error_type(task)
|
| 93 |
+
|
| 94 |
+
mem_context = ""
|
| 95 |
+
if context.get("short_term_memory"):
|
| 96 |
+
recent = context["short_term_memory"][-3:]
|
| 97 |
+
mem_context = "\n".join([f"- {m.get('content','')[:80]}" for m in recent])
|
| 98 |
+
|
| 99 |
+
enhanced_system = f"""{DEBUG_SYSTEM}
|
| 100 |
+
|
| 101 |
+
Active Role: {role.upper()}
|
| 102 |
+
Detected Error Type: {error_type}
|
| 103 |
+
Recent Context: {mem_context or 'None'}
|
| 104 |
+
|
| 105 |
+
Provide:
|
| 106 |
+
1. Root cause analysis
|
| 107 |
+
2. Step-by-step fix with code
|
| 108 |
+
3. Prevention strategy
|
| 109 |
+
4. Testing recommendation"""
|
| 110 |
+
|
| 111 |
+
try:
|
| 112 |
+
response = await self.ai_router.complete(
|
| 113 |
+
prompt=task,
|
| 114 |
+
system=enhanced_system,
|
| 115 |
+
max_tokens=3000,
|
| 116 |
+
)
|
| 117 |
+
return response.get("content", "Debug Space could not analyze the error.")
|
| 118 |
+
except Exception as e:
|
| 119 |
+
log.error(f"DebugSpace error: {e}")
|
| 120 |
+
return f"Debug Space error: {str(e)}"
|
backend/spaces/deploy_space.py
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
🚀 Deploy Space — The Infrastructure Domain
|
| 3 |
+
Cloud deployments, CI/CD, containerization.
|
| 4 |
+
"""
|
| 5 |
+
from typing import Dict
|
| 6 |
+
import structlog
|
| 7 |
+
from .base_space import BaseSpace
|
| 8 |
+
|
| 9 |
+
log = structlog.get_logger()
|
| 10 |
+
|
| 11 |
+
DEPLOY_SYSTEM = """You are GOD AGENT OS v9 — Deploy Space Expert.
|
| 12 |
+
|
| 13 |
+
You specialize in:
|
| 14 |
+
- Vercel deployments (Next.js, React, API routes)
|
| 15 |
+
- Hugging Face Spaces (Gradio, Streamlit, Docker)
|
| 16 |
+
- Docker containerization and Docker Compose
|
| 17 |
+
- GitHub Actions CI/CD pipelines
|
| 18 |
+
- AWS deployments (EC2, Lambda, ECS, S3)
|
| 19 |
+
- GCP deployments (Cloud Run, App Engine)
|
| 20 |
+
- Kubernetes manifests and Helm charts
|
| 21 |
+
- Environment variable management
|
| 22 |
+
- Domain configuration and SSL
|
| 23 |
+
- CDN setup (Cloudflare, AWS CloudFront)
|
| 24 |
+
- Database migrations and deployment strategies
|
| 25 |
+
- Blue-green and canary deployments
|
| 26 |
+
- Monitoring setup (Prometheus, Grafana)
|
| 27 |
+
|
| 28 |
+
Always provide:
|
| 29 |
+
1. Complete configuration files
|
| 30 |
+
2. Step-by-step deployment commands
|
| 31 |
+
3. Environment variable templates (.env.example)
|
| 32 |
+
4. Troubleshooting tips for common issues
|
| 33 |
+
"""
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
class DeploySpace(BaseSpace):
|
| 37 |
+
space_name = "deploy"
|
| 38 |
+
space_description = "Infrastructure domain — cloud deployments, CI/CD, containerization."
|
| 39 |
+
available_roles = ["automation", "execution", "cognition"]
|
| 40 |
+
|
| 41 |
+
def __init__(self, ws_manager=None, ai_router=None):
|
| 42 |
+
super().__init__(ws_manager, ai_router)
|
| 43 |
+
self.register_tool("gen_dockerfile", self._gen_dockerfile, "Generate Dockerfile")
|
| 44 |
+
self.register_tool("gen_github_actions", self._gen_github_actions, "Generate GitHub Actions workflow")
|
| 45 |
+
self.register_tool("gen_vercel_config", self._gen_vercel_config, "Generate Vercel configuration")
|
| 46 |
+
self.register_tool("gen_hf_config", self._gen_hf_config, "Generate HuggingFace Space config")
|
| 47 |
+
self.register_tool("gen_k8s_manifest", self._gen_k8s_manifest, "Generate Kubernetes manifests")
|
| 48 |
+
|
| 49 |
+
async def _gen_dockerfile(self, app_type: str = "python", **kwargs) -> str:
|
| 50 |
+
return f"Generating Dockerfile for {app_type}"
|
| 51 |
+
|
| 52 |
+
async def _gen_github_actions(self, workflow_type: str = "deploy", **kwargs) -> str:
|
| 53 |
+
return f"Generating GitHub Actions for {workflow_type}"
|
| 54 |
+
|
| 55 |
+
async def _gen_vercel_config(self, **kwargs) -> str:
|
| 56 |
+
return "Generating vercel.json"
|
| 57 |
+
|
| 58 |
+
async def _gen_hf_config(self, **kwargs) -> str:
|
| 59 |
+
return "Generating HF Space README.md"
|
| 60 |
+
|
| 61 |
+
async def _gen_k8s_manifest(self, app_name: str = "app", **kwargs) -> str:
|
| 62 |
+
return f"Generating K8s manifest for {app_name}"
|
| 63 |
+
|
| 64 |
+
async def execute(self, task: str, role: str, session_id: str, context: Dict = None) -> str:
|
| 65 |
+
context = context or {}
|
| 66 |
+
|
| 67 |
+
await self.stream_update(session_id, f"🚀 Deploy Space activated — {role} role")
|
| 68 |
+
|
| 69 |
+
# Detect deployment target
|
| 70 |
+
task_lower = task.lower()
|
| 71 |
+
targets = []
|
| 72 |
+
if "vercel" in task_lower:
|
| 73 |
+
targets.append("Vercel")
|
| 74 |
+
if "huggingface" in task_lower or "hf" in task_lower or "hugging face" in task_lower:
|
| 75 |
+
targets.append("HuggingFace Spaces")
|
| 76 |
+
if "docker" in task_lower:
|
| 77 |
+
targets.append("Docker")
|
| 78 |
+
if "github actions" in task_lower or "ci/cd" in task_lower:
|
| 79 |
+
targets.append("GitHub Actions")
|
| 80 |
+
if "aws" in task_lower or "lambda" in task_lower:
|
| 81 |
+
targets.append("AWS")
|
| 82 |
+
if "kubernetes" in task_lower or "k8s" in task_lower:
|
| 83 |
+
targets.append("Kubernetes")
|
| 84 |
+
|
| 85 |
+
targets_str = ", ".join(targets) if targets else "general deployment"
|
| 86 |
+
|
| 87 |
+
mem_context = ""
|
| 88 |
+
if context.get("short_term_memory"):
|
| 89 |
+
recent = context["short_term_memory"][-2:]
|
| 90 |
+
mem_context = "\n".join([f"- {m.get('content','')[:80]}" for m in recent])
|
| 91 |
+
|
| 92 |
+
enhanced_system = f"""{DEPLOY_SYSTEM}
|
| 93 |
+
|
| 94 |
+
Active Role: {role.upper()}
|
| 95 |
+
Deployment Targets: {targets_str}
|
| 96 |
+
Recent Context: {mem_context or 'None'}
|
| 97 |
+
|
| 98 |
+
Provide complete, copy-paste ready configurations."""
|
| 99 |
+
|
| 100 |
+
try:
|
| 101 |
+
response = await self.ai_router.complete(
|
| 102 |
+
prompt=task,
|
| 103 |
+
system=enhanced_system,
|
| 104 |
+
max_tokens=4096,
|
| 105 |
+
)
|
| 106 |
+
return response.get("content", "Deploy Space could not generate configuration.")
|
| 107 |
+
except Exception as e:
|
| 108 |
+
log.error(f"DeploySpace error: {e}")
|
| 109 |
+
return f"Deploy Space error: {str(e)}"
|
backend/spaces/sandbox_space.py
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
💻 Sandbox Space — Secure Code Execution Environment
|
| 3 |
+
Where code is run and tested safely.
|
| 4 |
+
"""
|
| 5 |
+
import asyncio
|
| 6 |
+
import os
|
| 7 |
+
import subprocess
|
| 8 |
+
import tempfile
|
| 9 |
+
import re
|
| 10 |
+
from typing import Dict
|
| 11 |
+
import structlog
|
| 12 |
+
from .base_space import BaseSpace
|
| 13 |
+
|
| 14 |
+
log = structlog.get_logger()
|
| 15 |
+
|
| 16 |
+
ALLOWED_LANGUAGES = {"python", "javascript", "bash", "sh"}
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
class SandboxSpace(BaseSpace):
|
| 20 |
+
space_name = "sandbox"
|
| 21 |
+
space_description = "Secure execution environment — run Python, JavaScript, shell scripts safely."
|
| 22 |
+
available_roles = ["execution", "cognition"]
|
| 23 |
+
|
| 24 |
+
def __init__(self, ws_manager=None, ai_router=None):
|
| 25 |
+
super().__init__(ws_manager, ai_router)
|
| 26 |
+
self.workspace = "/tmp/god_sandbox"
|
| 27 |
+
os.makedirs(self.workspace, exist_ok=True)
|
| 28 |
+
self.register_tool("run_python", self._run_python, "Execute Python code")
|
| 29 |
+
self.register_tool("run_shell", self._run_shell, "Execute shell commands")
|
| 30 |
+
self.register_tool("run_javascript", self._run_javascript, "Execute JavaScript with Node.js")
|
| 31 |
+
|
| 32 |
+
async def _run_python(self, code: str, timeout: int = 30, **kwargs) -> str:
|
| 33 |
+
"""Run Python code safely."""
|
| 34 |
+
try:
|
| 35 |
+
with tempfile.NamedTemporaryFile(suffix=".py", dir=self.workspace,
|
| 36 |
+
mode='w', delete=False) as f:
|
| 37 |
+
f.write(code)
|
| 38 |
+
fname = f.name
|
| 39 |
+
|
| 40 |
+
proc = await asyncio.create_subprocess_exec(
|
| 41 |
+
"python3", fname,
|
| 42 |
+
stdout=asyncio.subprocess.PIPE,
|
| 43 |
+
stderr=asyncio.subprocess.PIPE,
|
| 44 |
+
cwd=self.workspace,
|
| 45 |
+
)
|
| 46 |
+
try:
|
| 47 |
+
stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=timeout)
|
| 48 |
+
output = stdout.decode("utf-8", errors="replace")
|
| 49 |
+
errors = stderr.decode("utf-8", errors="replace")
|
| 50 |
+
|
| 51 |
+
result = ""
|
| 52 |
+
if output:
|
| 53 |
+
result += f"Output:\n{output}"
|
| 54 |
+
if errors:
|
| 55 |
+
result += f"\nErrors:\n{errors}"
|
| 56 |
+
return result or "Code executed successfully (no output)"
|
| 57 |
+
except asyncio.TimeoutError:
|
| 58 |
+
proc.kill()
|
| 59 |
+
return "⚠️ Execution timed out (30s limit)"
|
| 60 |
+
except Exception as e:
|
| 61 |
+
return f"❌ Python execution error: {str(e)}"
|
| 62 |
+
finally:
|
| 63 |
+
try:
|
| 64 |
+
os.unlink(fname)
|
| 65 |
+
except Exception:
|
| 66 |
+
pass
|
| 67 |
+
|
| 68 |
+
async def _run_shell(self, command: str, timeout: int = 30, **kwargs) -> str:
|
| 69 |
+
"""Run shell command safely."""
|
| 70 |
+
# Basic security: block dangerous commands
|
| 71 |
+
dangerous = ["rm -rf /", "dd if=", "mkfs", ":(){ :|:& };:", "> /dev/sda"]
|
| 72 |
+
for d in dangerous:
|
| 73 |
+
if d in command:
|
| 74 |
+
return f"⚠️ Command blocked for safety: {d}"
|
| 75 |
+
|
| 76 |
+
try:
|
| 77 |
+
proc = await asyncio.create_subprocess_shell(
|
| 78 |
+
command,
|
| 79 |
+
stdout=asyncio.subprocess.PIPE,
|
| 80 |
+
stderr=asyncio.subprocess.PIPE,
|
| 81 |
+
cwd=self.workspace,
|
| 82 |
+
)
|
| 83 |
+
try:
|
| 84 |
+
stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=timeout)
|
| 85 |
+
output = stdout.decode("utf-8", errors="replace")
|
| 86 |
+
errors = stderr.decode("utf-8", errors="replace")
|
| 87 |
+
result = output + (f"\n[stderr]: {errors}" if errors else "")
|
| 88 |
+
return result or f"Command completed (exit code: {proc.returncode})"
|
| 89 |
+
except asyncio.TimeoutError:
|
| 90 |
+
proc.kill()
|
| 91 |
+
return "⚠️ Command timed out (30s limit)"
|
| 92 |
+
except Exception as e:
|
| 93 |
+
return f"❌ Shell error: {str(e)}"
|
| 94 |
+
|
| 95 |
+
async def _run_javascript(self, code: str, timeout: int = 30, **kwargs) -> str:
|
| 96 |
+
"""Run JavaScript with Node.js."""
|
| 97 |
+
try:
|
| 98 |
+
with tempfile.NamedTemporaryFile(suffix=".js", dir=self.workspace,
|
| 99 |
+
mode='w', delete=False) as f:
|
| 100 |
+
f.write(code)
|
| 101 |
+
fname = f.name
|
| 102 |
+
|
| 103 |
+
proc = await asyncio.create_subprocess_exec(
|
| 104 |
+
"node", fname,
|
| 105 |
+
stdout=asyncio.subprocess.PIPE,
|
| 106 |
+
stderr=asyncio.subprocess.PIPE,
|
| 107 |
+
cwd=self.workspace,
|
| 108 |
+
)
|
| 109 |
+
try:
|
| 110 |
+
stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=timeout)
|
| 111 |
+
output = stdout.decode("utf-8", errors="replace")
|
| 112 |
+
errors = stderr.decode("utf-8", errors="replace")
|
| 113 |
+
result = output + (f"\nErrors:\n{errors}" if errors else "")
|
| 114 |
+
return result or "JS executed successfully"
|
| 115 |
+
except asyncio.TimeoutError:
|
| 116 |
+
proc.kill()
|
| 117 |
+
return "⚠️ JS execution timed out"
|
| 118 |
+
except Exception as e:
|
| 119 |
+
return f"❌ JS error: {str(e)}"
|
| 120 |
+
finally:
|
| 121 |
+
try:
|
| 122 |
+
os.unlink(fname)
|
| 123 |
+
except Exception:
|
| 124 |
+
pass
|
| 125 |
+
|
| 126 |
+
def _extract_code(self, text: str, language: str = "python") -> str:
|
| 127 |
+
"""Extract code from markdown code blocks."""
|
| 128 |
+
patterns = [
|
| 129 |
+
rf"```{language}\n(.*?)```",
|
| 130 |
+
r"```\n(.*?)```",
|
| 131 |
+
r"`(.*?)`",
|
| 132 |
+
]
|
| 133 |
+
for pattern in patterns:
|
| 134 |
+
match = re.search(pattern, text, re.DOTALL)
|
| 135 |
+
if match:
|
| 136 |
+
return match.group(1).strip()
|
| 137 |
+
return text
|
| 138 |
+
|
| 139 |
+
async def execute(self, task: str, role: str, session_id: str, context: Dict = None) -> str:
|
| 140 |
+
context = context or {}
|
| 141 |
+
|
| 142 |
+
await self.stream_update(session_id, f"💻 Sandbox Space activated — {role} role")
|
| 143 |
+
|
| 144 |
+
system_prompt = self.get_space_prompt(role, task, context)
|
| 145 |
+
|
| 146 |
+
# Ask AI to generate and optionally execute code
|
| 147 |
+
code_prompt = f"""{task}
|
| 148 |
+
|
| 149 |
+
If this requires code execution, generate the code and I will run it.
|
| 150 |
+
Format code in ```python, ```javascript, or ```bash blocks.
|
| 151 |
+
After the code, explain what it does."""
|
| 152 |
+
|
| 153 |
+
try:
|
| 154 |
+
response = await self.ai_router.complete(
|
| 155 |
+
prompt=code_prompt,
|
| 156 |
+
system=system_prompt,
|
| 157 |
+
max_tokens=2048,
|
| 158 |
+
)
|
| 159 |
+
ai_response = response.get("content", "")
|
| 160 |
+
|
| 161 |
+
# Try to extract and execute Python code
|
| 162 |
+
code_blocks = re.findall(r'```(?:python)?\n(.*?)```', ai_response, re.DOTALL)
|
| 163 |
+
|
| 164 |
+
execution_results = []
|
| 165 |
+
for code in code_blocks[:2]: # Execute max 2 code blocks
|
| 166 |
+
if code.strip():
|
| 167 |
+
result = await self._run_python(code.strip())
|
| 168 |
+
execution_results.append(f"```\n{result}\n```")
|
| 169 |
+
|
| 170 |
+
final = ai_response
|
| 171 |
+
if execution_results:
|
| 172 |
+
final += "\n\n**Execution Results:**\n" + "\n".join(execution_results)
|
| 173 |
+
|
| 174 |
+
return final
|
| 175 |
+
|
| 176 |
+
except Exception as e:
|
| 177 |
+
log.error(f"SandboxSpace error: {e}")
|
| 178 |
+
return f"Sandbox Space error: {str(e)}"
|
backend/spaces/vision_space.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
👁️ Vision Space — Visual Processing Domain
|
| 3 |
+
Image understanding, UI generation, OCR, visual analysis.
|
| 4 |
+
"""
|
| 5 |
+
from typing import Dict
|
| 6 |
+
import structlog
|
| 7 |
+
from .base_space import BaseSpace
|
| 8 |
+
|
| 9 |
+
log = structlog.get_logger()
|
| 10 |
+
|
| 11 |
+
VISION_SYSTEM = """You are GOD AGENT OS v9 — Vision Space Expert.
|
| 12 |
+
|
| 13 |
+
You specialize in:
|
| 14 |
+
- UI/UX design and code generation (React, Next.js, Tailwind)
|
| 15 |
+
- Visual layout descriptions and wireframing
|
| 16 |
+
- Image analysis and description
|
| 17 |
+
- Design-to-code conversion
|
| 18 |
+
- CSS and styling
|
| 19 |
+
- Responsive design patterns
|
| 20 |
+
- Component library creation (shadcn/ui, Radix, MUI)
|
| 21 |
+
- Color theory and design systems
|
| 22 |
+
- Accessibility (WCAG) guidelines
|
| 23 |
+
- Animation and interaction design (Framer Motion, CSS animations)
|
| 24 |
+
|
| 25 |
+
When creating UI components, always use modern frameworks and produce clean, production-ready code.
|
| 26 |
+
"""
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
class VisionSpace(BaseSpace):
|
| 30 |
+
space_name = "vision"
|
| 31 |
+
space_description = "Visual processing — UI generation, image analysis, design-to-code."
|
| 32 |
+
available_roles = ["visual_intelligence", "execution", "cognition"]
|
| 33 |
+
|
| 34 |
+
def __init__(self, ws_manager=None, ai_router=None):
|
| 35 |
+
super().__init__(ws_manager, ai_router)
|
| 36 |
+
self.register_tool("generate_ui", self._generate_ui, "Generate UI components from descriptions")
|
| 37 |
+
self.register_tool("analyze_design", self._analyze_design, "Analyze design requirements")
|
| 38 |
+
self.register_tool("design_system", self._design_system, "Create design system tokens")
|
| 39 |
+
|
| 40 |
+
async def _generate_ui(self, description: str, framework: str = "react", **kwargs) -> str:
|
| 41 |
+
return f"Generating {framework} UI for: {description}"
|
| 42 |
+
|
| 43 |
+
async def _analyze_design(self, description: str, **kwargs) -> str:
|
| 44 |
+
return f"Analyzing design: {description}"
|
| 45 |
+
|
| 46 |
+
async def _design_system(self, brand: str, **kwargs) -> str:
|
| 47 |
+
return f"Creating design system for: {brand}"
|
| 48 |
+
|
| 49 |
+
async def execute(self, task: str, role: str, session_id: str, context: Dict = None) -> str:
|
| 50 |
+
context = context or {}
|
| 51 |
+
|
| 52 |
+
await self.stream_update(session_id, f"👁️ Vision Space activated — {role} role")
|
| 53 |
+
|
| 54 |
+
mem_context = ""
|
| 55 |
+
if context.get("short_term_memory"):
|
| 56 |
+
recent = context["short_term_memory"][-2:]
|
| 57 |
+
mem_context = "\n".join([f"- {m.get('content','')[:80]}" for m in recent])
|
| 58 |
+
|
| 59 |
+
enhanced_system = f"""{VISION_SYSTEM}
|
| 60 |
+
|
| 61 |
+
Active Role: {role.upper()}
|
| 62 |
+
Recent Context: {mem_context or 'None'}
|
| 63 |
+
|
| 64 |
+
For UI generation tasks:
|
| 65 |
+
- Use React + TypeScript + Tailwind CSS by default
|
| 66 |
+
- Create complete, self-contained components
|
| 67 |
+
- Include all necessary imports
|
| 68 |
+
- Add PropTypes or TypeScript interfaces
|
| 69 |
+
- Make it responsive and accessible"""
|
| 70 |
+
|
| 71 |
+
try:
|
| 72 |
+
response = await self.ai_router.complete(
|
| 73 |
+
prompt=task,
|
| 74 |
+
system=enhanced_system,
|
| 75 |
+
max_tokens=4096,
|
| 76 |
+
)
|
| 77 |
+
return response.get("content", "Vision Space could not process the request.")
|
| 78 |
+
except Exception as e:
|
| 79 |
+
log.error(f"VisionSpace error: {e}")
|
| 80 |
+
return f"Vision Space error: {str(e)}"
|
frontend/app/layout.tsx
CHANGED
|
@@ -2,8 +2,8 @@ import type { Metadata } from 'next'
|
|
| 2 |
import './globals.css'
|
| 3 |
|
| 4 |
export const metadata: Metadata = {
|
| 5 |
-
title: 'GOD AGENT OS — Autonomous
|
| 6 |
-
description: '
|
| 7 |
icons: { icon: '/favicon.ico' },
|
| 8 |
}
|
| 9 |
|
|
|
|
| 2 |
import './globals.css'
|
| 3 |
|
| 4 |
export const metadata: Metadata = {
|
| 5 |
+
title: 'GOD AGENT OS v9 — General Autonomous Agent OS | Powered by Pyae Sone',
|
| 6 |
+
description: 'Space-Role Architecture — General Autonomous Agent OS. 8 Spaces × 5 Roles. Powered by Pyae Sone.',
|
| 7 |
icons: { icon: '/favicon.ico' },
|
| 8 |
}
|
| 9 |
|
frontend/app/page.tsx
CHANGED
|
@@ -6,6 +6,7 @@ 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'
|
|
@@ -13,10 +14,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,
|
|
@@ -24,13 +27,35 @@ const PAGE_MAP = {
|
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
|
| 35 |
if (!mounted) return (
|
| 36 |
<div className="flex items-center justify-center h-screen" style={{ background: '#05060d' }}>
|
|
@@ -39,23 +64,46 @@ export default function GodAgentOS() {
|
|
| 39 |
animate={{ opacity: 1, scale: 1 }}
|
| 40 |
className="text-center"
|
| 41 |
>
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
</div>
|
| 46 |
-
|
| 47 |
-
<div className="
|
| 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="
|
|
|
|
| 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' }}>
|
|
@@ -69,7 +117,7 @@ export default function GodAgentOS() {
|
|
| 69 |
initial={{ opacity: 0, y: 8 }}
|
| 70 |
animate={{ opacity: 1, y: 0 }}
|
| 71 |
exit={{ opacity: 0, y: -8 }}
|
| 72 |
-
transition={{ duration: 0.
|
| 73 |
className="h-full"
|
| 74 |
>
|
| 75 |
<PageComponent />
|
|
|
|
| 6 |
import Sidebar from '@/components/shared/Sidebar'
|
| 7 |
import TopBar from '@/components/shared/TopBar'
|
| 8 |
import DashboardPage from '@/components/pages/DashboardPage'
|
| 9 |
+
import SpacesPage from '@/components/pages/SpacesPage'
|
| 10 |
import AgentsPage from '@/components/pages/AgentsPage'
|
| 11 |
import TasksPage from '@/components/pages/TasksPage'
|
| 12 |
import MemoryPage from '@/components/pages/MemoryPage'
|
|
|
|
| 14 |
import WorkflowsPage from '@/components/pages/WorkflowsPage'
|
| 15 |
import AnalyticsPage from '@/components/pages/AnalyticsPage'
|
| 16 |
import SettingsPage from '@/components/pages/SettingsPage'
|
| 17 |
+
import ConnectorsPage from '@/components/pages/ConnectorsPage'
|
| 18 |
import { useAppStore } from '@/store/useAppStore'
|
| 19 |
|
| 20 |
const PAGE_MAP = {
|
| 21 |
dashboard: DashboardPage,
|
| 22 |
+
spaces: SpacesPage,
|
| 23 |
agents: AgentsPage,
|
| 24 |
tasks: TasksPage,
|
| 25 |
memory: MemoryPage,
|
|
|
|
| 27 |
workflows: WorkflowsPage,
|
| 28 |
analytics: AnalyticsPage,
|
| 29 |
settings: SettingsPage,
|
| 30 |
+
connectors: ConnectorsPage,
|
| 31 |
}
|
| 32 |
|
| 33 |
export default function GodAgentOS() {
|
| 34 |
const { currentPage } = useAppStore()
|
| 35 |
const [mounted, setMounted] = useState(false)
|
| 36 |
+
const [loadingStep, setLoadingStep] = useState(0)
|
| 37 |
|
| 38 |
+
const loadingSteps = [
|
| 39 |
+
'Initializing Agent Kernel...',
|
| 40 |
+
'Loading 8 Spaces...',
|
| 41 |
+
'Registering 5 Roles...',
|
| 42 |
+
'Connecting AI Router...',
|
| 43 |
+
'System Ready ✓',
|
| 44 |
+
]
|
| 45 |
+
|
| 46 |
+
useEffect(() => {
|
| 47 |
+
setMounted(true)
|
| 48 |
+
const interval = setInterval(() => {
|
| 49 |
+
setLoadingStep(prev => {
|
| 50 |
+
if (prev >= loadingSteps.length - 1) {
|
| 51 |
+
clearInterval(interval)
|
| 52 |
+
return prev
|
| 53 |
+
}
|
| 54 |
+
return prev + 1
|
| 55 |
+
})
|
| 56 |
+
}, 400)
|
| 57 |
+
return () => clearInterval(interval)
|
| 58 |
+
}, [])
|
| 59 |
|
| 60 |
if (!mounted) return (
|
| 61 |
<div className="flex items-center justify-center h-screen" style={{ background: '#05060d' }}>
|
|
|
|
| 64 |
animate={{ opacity: 1, scale: 1 }}
|
| 65 |
className="text-center"
|
| 66 |
>
|
| 67 |
+
{/* Logo */}
|
| 68 |
+
<div className="relative w-20 h-20 mx-auto mb-6">
|
| 69 |
+
<div className="absolute inset-0 rounded-2xl"
|
| 70 |
+
style={{ background: 'linear-gradient(135deg, #7c3aed, #4f46e5)', filter: 'blur(12px)', opacity: 0.5 }} />
|
| 71 |
+
<div className="relative w-full h-full rounded-2xl flex items-center justify-center"
|
| 72 |
+
style={{ background: 'linear-gradient(135deg, #7c3aed, #4f46e5)' }}>
|
| 73 |
+
<Zap size={32} className="text-white" />
|
| 74 |
+
</div>
|
| 75 |
+
</div>
|
| 76 |
+
|
| 77 |
+
<div className="text-2xl font-black text-white mb-1">GOD AGENT OS</div>
|
| 78 |
+
<div className="text-sm text-slate-500 mb-1">General Autonomous Agent OS</div>
|
| 79 |
+
<div className="text-xs text-violet-500 font-medium mb-6">Space-Role Architecture · v9.0</div>
|
| 80 |
+
|
| 81 |
+
{/* Loading steps */}
|
| 82 |
+
<div className="space-y-1 mb-4">
|
| 83 |
+
{loadingSteps.map((step, i) => (
|
| 84 |
+
<div key={i} className={`text-xs transition-all duration-300 ${
|
| 85 |
+
i <= loadingStep ? 'text-slate-400' : 'text-slate-700'
|
| 86 |
+
}`}>
|
| 87 |
+
{i < loadingStep ? '✓' : i === loadingStep ? '▶' : '○'} {step}
|
| 88 |
+
</div>
|
| 89 |
+
))}
|
| 90 |
</div>
|
| 91 |
+
|
| 92 |
+
<div className="flex gap-2 justify-center">
|
|
|
|
|
|
|
| 93 |
{[0, 1, 2].map(i => (
|
| 94 |
+
<div key={i} className="w-2 h-2 rounded-full bg-violet-500 animate-bounce"
|
| 95 |
+
style={{ animationDelay: `${i * 0.2}s` }} />
|
| 96 |
))}
|
| 97 |
</div>
|
| 98 |
+
|
| 99 |
+
<div className="mt-6 text-[10px] text-slate-700">
|
| 100 |
+
Powered by <span className="text-violet-600">Pyae Sone</span>
|
| 101 |
+
</div>
|
| 102 |
</motion.div>
|
| 103 |
</div>
|
| 104 |
)
|
| 105 |
|
| 106 |
+
const PageComponent = PAGE_MAP[currentPage] || DashboardPage
|
| 107 |
|
| 108 |
return (
|
| 109 |
<div className="flex h-screen overflow-hidden" style={{ background: '#05060d' }}>
|
|
|
|
| 117 |
initial={{ opacity: 0, y: 8 }}
|
| 118 |
animate={{ opacity: 1, y: 0 }}
|
| 119 |
exit={{ opacity: 0, y: -8 }}
|
| 120 |
+
transition={{ duration: 0.2, ease: [0.4, 0, 0.2, 1] }}
|
| 121 |
className="h-full"
|
| 122 |
>
|
| 123 |
<PageComponent />
|
frontend/components/chat/ChatPanel.tsx
CHANGED
|
@@ -3,7 +3,14 @@
|
|
| 3 |
import { useState, useRef, useEffect, useCallback } from 'react'
|
| 4 |
import { useAgentStore } from '@/hooks/useAgentStore'
|
| 5 |
import { useChatWebSocket } from '@/hooks/useWebSocket'
|
| 6 |
-
import {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
import MessageBubble from './MessageBubble'
|
| 8 |
import {
|
| 9 |
Send, Square, Zap, MessageSquare, Code2, GitBranch, Brain,
|
|
|
|
| 3 |
import { useState, useRef, useEffect, useCallback } from 'react'
|
| 4 |
import { useAgentStore } from '@/hooks/useAgentStore'
|
| 5 |
import { useChatWebSocket } from '@/hooks/useWebSocket'
|
| 6 |
+
import { fetchAPI } from '@/lib/api'
|
| 7 |
+
const createTask = (goal: any, sessionId?: string) => fetchAPI('/api/v1/tasks/', { method: 'POST', body: JSON.stringify({ goal, session_id: sessionId }) })
|
| 8 |
+
const streamChatSSE = async (msgs: any[], sessionId: string, onChunk: (c: string) => void, onDone: (f: string) => void, onErr: (e: string) => void) => {
|
| 9 |
+
try {
|
| 10 |
+
const res = await fetchAPI('/api/v1/kernel/orchestrate', { method: 'POST', body: JSON.stringify({ message: msgs[msgs.length-1]?.content || '', session_id: sessionId }) })
|
| 11 |
+
onDone(res.result || 'Response received.')
|
| 12 |
+
} catch(e: any) { onErr(e.message) }
|
| 13 |
+
}
|
| 14 |
import MessageBubble from './MessageBubble'
|
| 15 |
import {
|
| 16 |
Send, Square, Zap, MessageSquare, Code2, GitBranch, Brain,
|
frontend/components/dashboard/ActivityFeed.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
'use client'
|
| 2 |
|
| 3 |
import { motion } from 'framer-motion'
|
| 4 |
-
|
| 5 |
import { CheckCircle2, Loader2, Info, AlertTriangle } from 'lucide-react'
|
| 6 |
|
| 7 |
const TypeIcon = ({ type }: { type: string }) => {
|
|
|
|
| 1 |
'use client'
|
| 2 |
|
| 3 |
import { motion } from 'framer-motion'
|
| 4 |
+
const ACTIVITY: any[] = []
|
| 5 |
import { CheckCircle2, Loader2, Info, AlertTriangle } from 'lucide-react'
|
| 6 |
|
| 7 |
const TypeIcon = ({ type }: { type: string }) => {
|
frontend/components/dashboard/AgentFleetCard.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
'use client'
|
| 2 |
|
| 3 |
import { motion } from 'framer-motion'
|
| 4 |
-
|
| 5 |
import { cn, getStatusColor } from '@/lib/utils'
|
| 6 |
import { ChevronRight } from 'lucide-react'
|
| 7 |
|
|
|
|
| 1 |
'use client'
|
| 2 |
|
| 3 |
import { motion } from 'framer-motion'
|
| 4 |
+
type Agent = { id: string; name: string; status: string; icon: string; role: string; space: string }
|
| 5 |
import { cn, getStatusColor } from '@/lib/utils'
|
| 6 |
import { ChevronRight } from 'lucide-react'
|
| 7 |
|
frontend/components/dashboard/GodModeCard.tsx
CHANGED
|
@@ -2,9 +2,10 @@
|
|
| 2 |
|
| 3 |
import { motion } from 'framer-motion'
|
| 4 |
import { useAppStore } from '@/store/useAppStore'
|
|
|
|
| 5 |
|
| 6 |
export default function GodModeCard() {
|
| 7 |
-
const
|
| 8 |
|
| 9 |
return (
|
| 10 |
<div className="relative overflow-hidden rounded-2xl p-5"
|
|
|
|
| 2 |
|
| 3 |
import { motion } from 'framer-motion'
|
| 4 |
import { useAppStore } from '@/store/useAppStore'
|
| 5 |
+
const useGodMode = () => ({ godModeActive: true })
|
| 6 |
|
| 7 |
export default function GodModeCard() {
|
| 8 |
+
const godModeActive = true // v9 always active
|
| 9 |
|
| 10 |
return (
|
| 11 |
<div className="relative overflow-hidden rounded-2xl p-5"
|
frontend/components/dashboard/SystemResources.tsx
CHANGED
|
@@ -3,7 +3,7 @@
|
|
| 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' },
|
|
|
|
| 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' },
|
frontend/components/pages/AgentsPage.tsx
CHANGED
|
@@ -3,7 +3,17 @@
|
|
| 3 |
import { useState } from 'react'
|
| 4 |
import { motion } from 'framer-motion'
|
| 5 |
import { Search, Filter, Plus, Bot, Activity, Zap } from 'lucide-react'
|
| 6 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
import { getStatusColor, cn } from '@/lib/utils'
|
| 8 |
|
| 9 |
const STATUS_FILTERS = ['All', 'Active', 'Processing', 'Idle', 'Error']
|
|
|
|
| 3 |
import { useState } from 'react'
|
| 4 |
import { motion } from 'framer-motion'
|
| 5 |
import { Search, Filter, Plus, Bot, Activity, Zap } from 'lucide-react'
|
| 6 |
+
type Agent = { id: string; name: string; status: string; icon: string; role: string; space: string; description: string; tasks: number }
|
| 7 |
+
const AGENTS: Agent[] = [
|
| 8 |
+
{ id: 'core', name: 'Core Space', status: 'active', icon: '🧠', role: 'Cognition', space: 'core', description: 'Planning & orchestration', tasks: 0 },
|
| 9 |
+
{ id: 'browser', name: 'Browser Space', status: 'idle', icon: '🌐', role: 'Automation', space: 'browser', description: 'Web research & navigation', tasks: 0 },
|
| 10 |
+
{ id: 'sandbox', name: 'Sandbox Space', status: 'idle', icon: '💻', role: 'Execution', space: 'sandbox', description: 'Code execution', tasks: 0 },
|
| 11 |
+
{ id: 'coding', name: 'Coding Space', status: 'idle', icon: '🔧', role: 'Execution', space: 'coding', description: 'Code generation', tasks: 0 },
|
| 12 |
+
{ id: 'vision', name: 'Vision Space', status: 'idle', icon: '👁️', role: 'Visual Intelligence', space: 'vision', description: 'UI & image analysis', tasks: 0 },
|
| 13 |
+
{ id: 'debug', name: 'Debug Space', status: 'idle', icon: '🐛', role: 'Repair', space: 'debug', description: 'Error analysis', tasks: 0 },
|
| 14 |
+
{ id: 'deploy', name: 'Deploy Space', status: 'idle', icon: '🚀', role: 'Automation', space: 'deploy', description: 'Cloud deployments', tasks: 0 },
|
| 15 |
+
{ id: 'communication', name: 'Comm Space', status: 'idle', icon: '💬', role: 'Automation', space: 'communication', description: 'Docs & messaging', tasks: 0 },
|
| 16 |
+
]
|
| 17 |
import { getStatusColor, cn } from '@/lib/utils'
|
| 18 |
|
| 19 |
const STATUS_FILTERS = ['All', 'Active', 'Processing', 'Idle', 'Error']
|
frontend/components/pages/ConnectorsPage.tsx
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client'
|
| 2 |
+
|
| 3 |
+
import { useState, useEffect } from 'react'
|
| 4 |
+
import { motion } from 'framer-motion'
|
| 5 |
+
import { Plus, CheckCircle, XCircle, Loader, ExternalLink, Key } from 'lucide-react'
|
| 6 |
+
|
| 7 |
+
interface Connector {
|
| 8 |
+
id: string
|
| 9 |
+
name: string
|
| 10 |
+
icon: string
|
| 11 |
+
description: string
|
| 12 |
+
connected: boolean
|
| 13 |
+
category: string
|
| 14 |
+
apiKeyField?: string
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
const CONNECTORS: Connector[] = [
|
| 18 |
+
{ id: 'github', name: 'GitHub', icon: '🐙', description: 'Repository management, PRs, Issues', connected: false, category: 'DevTools', apiKeyField: 'GitHub Token' },
|
| 19 |
+
{ id: 'openai', name: 'OpenAI', icon: '🤖', description: 'GPT-4, DALL-E, Whisper APIs', connected: false, category: 'AI', apiKeyField: 'API Key' },
|
| 20 |
+
{ id: 'anthropic', name: 'Anthropic', icon: '🧠', description: 'Claude 3 Opus/Sonnet/Haiku', connected: false, category: 'AI', apiKeyField: 'API Key' },
|
| 21 |
+
{ id: 'gemini', name: 'Google Gemini', icon: '✨', description: 'Gemini Pro/Flash models', connected: true, category: 'AI', apiKeyField: 'API Key' },
|
| 22 |
+
{ id: 'sambanova', name: 'SambaNova', icon: '⚡', description: 'Ultra-fast LLM inference', connected: true, category: 'AI', apiKeyField: 'API Key' },
|
| 23 |
+
{ id: 'vercel', name: 'Vercel', icon: '▲', description: 'Deploy and manage web apps', connected: false, category: 'Deploy', apiKeyField: 'Access Token' },
|
| 24 |
+
{ id: 'huggingface', name: 'HuggingFace', icon: '🤗', description: 'Models, Spaces, Datasets', connected: false, category: 'AI', apiKeyField: 'HF Token' },
|
| 25 |
+
{ id: 'slack', name: 'Slack', icon: '💬', description: 'Team messaging and notifications', connected: false, category: 'Comm' },
|
| 26 |
+
{ id: 'notion', name: 'Notion', icon: '📝', description: 'Knowledge management', connected: false, category: 'Productivity' },
|
| 27 |
+
{ id: 'docker', name: 'Docker', icon: '🐳', description: 'Container management', connected: false, category: 'DevOps' },
|
| 28 |
+
{ id: 'aws', name: 'AWS', icon: '☁️', description: 'Cloud infrastructure', connected: false, category: 'Cloud', apiKeyField: 'Access Key' },
|
| 29 |
+
{ id: 'stripe', name: 'Stripe', icon: '💳', description: 'Payment processing', connected: false, category: 'Finance', apiKeyField: 'Secret Key' },
|
| 30 |
+
]
|
| 31 |
+
|
| 32 |
+
const CATEGORIES = ['All', 'AI', 'DevTools', 'Deploy', 'DevOps', 'Comm', 'Productivity', 'Cloud', 'Finance']
|
| 33 |
+
|
| 34 |
+
export default function ConnectorsPage() {
|
| 35 |
+
const [connectors, setConnectors] = useState(CONNECTORS)
|
| 36 |
+
const [selectedCategory, setSelectedCategory] = useState('All')
|
| 37 |
+
const [selectedConnector, setSelectedConnector] = useState<Connector | null>(null)
|
| 38 |
+
const [apiKey, setApiKey] = useState('')
|
| 39 |
+
const [connecting, setConnecting] = useState(false)
|
| 40 |
+
|
| 41 |
+
const filtered = selectedCategory === 'All'
|
| 42 |
+
? connectors
|
| 43 |
+
: connectors.filter(c => c.category === selectedCategory)
|
| 44 |
+
|
| 45 |
+
const connectedCount = connectors.filter(c => c.connected).length
|
| 46 |
+
|
| 47 |
+
async function connectConnector(connector: Connector) {
|
| 48 |
+
setConnecting(true)
|
| 49 |
+
await new Promise(r => setTimeout(r, 1500))
|
| 50 |
+
setConnectors(prev => prev.map(c =>
|
| 51 |
+
c.id === connector.id ? { ...c, connected: true } : c
|
| 52 |
+
))
|
| 53 |
+
setConnecting(false)
|
| 54 |
+
setSelectedConnector(null)
|
| 55 |
+
setApiKey('')
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
function disconnectConnector(id: string) {
|
| 59 |
+
setConnectors(prev => prev.map(c =>
|
| 60 |
+
c.id === id ? { ...c, connected: false } : c
|
| 61 |
+
))
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
return (
|
| 65 |
+
<div className="h-full overflow-y-auto p-6" style={{ background: '#05060d' }}>
|
| 66 |
+
<div className="max-w-5xl mx-auto">
|
| 67 |
+
{/* Header */}
|
| 68 |
+
<div className="flex items-center justify-between mb-6">
|
| 69 |
+
<div>
|
| 70 |
+
<h1 className="text-2xl font-bold text-white mb-1">Connectors</h1>
|
| 71 |
+
<p className="text-slate-500 text-sm">{connectedCount} of {connectors.length} services connected</p>
|
| 72 |
+
</div>
|
| 73 |
+
<button className="flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium text-white"
|
| 74 |
+
style={{ background: 'linear-gradient(135deg, #7c3aed, #4f46e5)' }}>
|
| 75 |
+
<Plus size={14} />
|
| 76 |
+
Add Custom
|
| 77 |
+
</button>
|
| 78 |
+
</div>
|
| 79 |
+
|
| 80 |
+
{/* Stats */}
|
| 81 |
+
<div className="grid grid-cols-4 gap-3 mb-6">
|
| 82 |
+
{[
|
| 83 |
+
{ label: 'Connected', value: connectedCount, color: '#22c55e' },
|
| 84 |
+
{ label: 'Available', value: connectors.length - connectedCount, color: '#64748b' },
|
| 85 |
+
{ label: 'AI Models', value: connectors.filter(c => c.category === 'AI' && c.connected).length, color: '#7c3aed' },
|
| 86 |
+
{ label: 'Deploy', value: connectors.filter(c => c.category === 'Deploy' && c.connected).length, color: '#0891b2' },
|
| 87 |
+
].map(stat => (
|
| 88 |
+
<div key={stat.label} className="p-3 rounded-xl border text-center"
|
| 89 |
+
style={{ background: '#07080f', borderColor: '#1e2035' }}>
|
| 90 |
+
<div className="text-xl font-bold" style={{ color: stat.color }}>{stat.value}</div>
|
| 91 |
+
<div className="text-[10px] text-slate-600">{stat.label}</div>
|
| 92 |
+
</div>
|
| 93 |
+
))}
|
| 94 |
+
</div>
|
| 95 |
+
|
| 96 |
+
{/* Category Filter */}
|
| 97 |
+
<div className="flex gap-2 mb-4 overflow-x-auto pb-1">
|
| 98 |
+
{CATEGORIES.map(cat => (
|
| 99 |
+
<button key={cat}
|
| 100 |
+
onClick={() => setSelectedCategory(cat)}
|
| 101 |
+
className="flex-shrink-0 px-3 py-1 rounded-full text-xs font-medium transition-all"
|
| 102 |
+
style={{
|
| 103 |
+
background: selectedCategory === cat ? 'rgba(139,92,246,0.2)' : 'rgba(255,255,255,0.04)',
|
| 104 |
+
color: selectedCategory === cat ? '#a78bfa' : '#64748b',
|
| 105 |
+
border: `1px solid ${selectedCategory === cat ? 'rgba(139,92,246,0.4)' : 'transparent'}`,
|
| 106 |
+
}}>
|
| 107 |
+
{cat}
|
| 108 |
+
</button>
|
| 109 |
+
))}
|
| 110 |
+
</div>
|
| 111 |
+
|
| 112 |
+
{/* Connectors Grid */}
|
| 113 |
+
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-3">
|
| 114 |
+
{filtered.map((connector, i) => (
|
| 115 |
+
<motion.div
|
| 116 |
+
key={connector.id}
|
| 117 |
+
initial={{ opacity: 0, y: 10 }}
|
| 118 |
+
animate={{ opacity: 1, y: 0 }}
|
| 119 |
+
transition={{ delay: i * 0.04 }}
|
| 120 |
+
className="p-4 rounded-xl border transition-all"
|
| 121 |
+
style={{
|
| 122 |
+
background: '#07080f',
|
| 123 |
+
borderColor: connector.connected ? 'rgba(34,197,94,0.2)' : '#1e2035',
|
| 124 |
+
}}>
|
| 125 |
+
|
| 126 |
+
<div className="flex items-center justify-between mb-3">
|
| 127 |
+
<div className="flex items-center gap-2">
|
| 128 |
+
<span className="text-2xl">{connector.icon}</span>
|
| 129 |
+
<div>
|
| 130 |
+
<div className="text-sm font-semibold text-white">{connector.name}</div>
|
| 131 |
+
<div className="text-[9px] text-slate-600">{connector.category}</div>
|
| 132 |
+
</div>
|
| 133 |
+
</div>
|
| 134 |
+
<div className="flex items-center gap-1">
|
| 135 |
+
{connector.connected ? (
|
| 136 |
+
<CheckCircle size={14} className="text-green-400" />
|
| 137 |
+
) : (
|
| 138 |
+
<XCircle size={14} className="text-slate-600" />
|
| 139 |
+
)}
|
| 140 |
+
</div>
|
| 141 |
+
</div>
|
| 142 |
+
|
| 143 |
+
<p className="text-[10px] text-slate-500 mb-3">{connector.description}</p>
|
| 144 |
+
|
| 145 |
+
<div className="flex gap-2">
|
| 146 |
+
{connector.connected ? (
|
| 147 |
+
<button
|
| 148 |
+
onClick={() => disconnectConnector(connector.id)}
|
| 149 |
+
className="flex-1 py-1.5 rounded-lg text-xs text-red-400 transition-all hover:bg-red-500/10"
|
| 150 |
+
style={{ border: '1px solid rgba(239,68,68,0.2)' }}>
|
| 151 |
+
Disconnect
|
| 152 |
+
</button>
|
| 153 |
+
) : (
|
| 154 |
+
<button
|
| 155 |
+
onClick={() => setSelectedConnector(connector)}
|
| 156 |
+
className="flex-1 py-1.5 rounded-lg text-xs font-medium text-white transition-all"
|
| 157 |
+
style={{ background: 'rgba(139,92,246,0.2)', border: '1px solid rgba(139,92,246,0.3)' }}>
|
| 158 |
+
Connect
|
| 159 |
+
</button>
|
| 160 |
+
)}
|
| 161 |
+
</div>
|
| 162 |
+
</motion.div>
|
| 163 |
+
))}
|
| 164 |
+
</div>
|
| 165 |
+
|
| 166 |
+
{/* Connect Modal */}
|
| 167 |
+
{selectedConnector && (
|
| 168 |
+
<div className="fixed inset-0 bg-black/60 flex items-center justify-center z-50 p-4">
|
| 169 |
+
<motion.div
|
| 170 |
+
initial={{ opacity: 0, scale: 0.95 }}
|
| 171 |
+
animate={{ opacity: 1, scale: 1 }}
|
| 172 |
+
className="w-full max-w-md p-6 rounded-2xl"
|
| 173 |
+
style={{ background: '#0d0e1a', border: '1px solid #1e2035' }}>
|
| 174 |
+
|
| 175 |
+
<div className="flex items-center gap-3 mb-4">
|
| 176 |
+
<span className="text-3xl">{selectedConnector.icon}</span>
|
| 177 |
+
<div>
|
| 178 |
+
<h3 className="text-lg font-bold text-white">Connect {selectedConnector.name}</h3>
|
| 179 |
+
<p className="text-xs text-slate-500">{selectedConnector.description}</p>
|
| 180 |
+
</div>
|
| 181 |
+
</div>
|
| 182 |
+
|
| 183 |
+
{selectedConnector.apiKeyField && (
|
| 184 |
+
<div className="mb-4">
|
| 185 |
+
<label className="text-xs text-slate-400 mb-1 block">{selectedConnector.apiKeyField}</label>
|
| 186 |
+
<div className="flex items-center gap-2 px-3 py-2 rounded-lg"
|
| 187 |
+
style={{ background: '#07080f', border: '1px solid #1e2035' }}>
|
| 188 |
+
<Key size={13} className="text-slate-600" />
|
| 189 |
+
<input
|
| 190 |
+
type="password"
|
| 191 |
+
value={apiKey}
|
| 192 |
+
onChange={e => setApiKey(e.target.value)}
|
| 193 |
+
placeholder={`Enter your ${selectedConnector.apiKeyField}...`}
|
| 194 |
+
className="flex-1 bg-transparent text-sm text-slate-200 outline-none"
|
| 195 |
+
/>
|
| 196 |
+
</div>
|
| 197 |
+
</div>
|
| 198 |
+
)}
|
| 199 |
+
|
| 200 |
+
<div className="flex gap-3">
|
| 201 |
+
<button
|
| 202 |
+
onClick={() => { setSelectedConnector(null); setApiKey('') }}
|
| 203 |
+
className="flex-1 py-2 rounded-lg text-sm text-slate-400 transition-all hover:bg-white/5">
|
| 204 |
+
Cancel
|
| 205 |
+
</button>
|
| 206 |
+
<button
|
| 207 |
+
onClick={() => connectConnector(selectedConnector)}
|
| 208 |
+
disabled={connecting}
|
| 209 |
+
className="flex-1 py-2 rounded-lg text-sm font-medium text-white transition-all disabled:opacity-50 flex items-center justify-center gap-2"
|
| 210 |
+
style={{ background: 'linear-gradient(135deg, #7c3aed, #4f46e5)' }}>
|
| 211 |
+
{connecting ? (
|
| 212 |
+
<><Loader size={13} className="animate-spin" /> Connecting...</>
|
| 213 |
+
) : (
|
| 214 |
+
'Connect'
|
| 215 |
+
)}
|
| 216 |
+
</button>
|
| 217 |
+
</div>
|
| 218 |
+
</motion.div>
|
| 219 |
+
</div>
|
| 220 |
+
)}
|
| 221 |
+
</div>
|
| 222 |
+
</div>
|
| 223 |
+
)
|
| 224 |
+
}
|
frontend/components/pages/DashboardPage.tsx
CHANGED
|
@@ -1,110 +1,445 @@
|
|
| 1 |
'use client'
|
| 2 |
|
| 3 |
-
import {
|
| 4 |
-
import {
|
| 5 |
-
import
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
import
|
| 11 |
-
import {
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
{
|
| 16 |
-
{
|
| 17 |
-
{
|
| 18 |
-
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
]
|
| 20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
export default function DashboardPage() {
|
| 22 |
-
const {
|
| 23 |
-
const
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 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 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
</div>
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
</
|
| 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 |
-
|
| 75 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
</div>
|
| 77 |
|
| 78 |
-
{/*
|
| 79 |
-
<div className="
|
| 80 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
|
| 82 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
</div>
|
|
|
|
| 92 |
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
</div>
|
|
|
|
| 101 |
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
</div>
|
| 109 |
</div>
|
| 110 |
</div>
|
|
|
|
| 1 |
'use client'
|
| 2 |
|
| 3 |
+
import { useEffect, useState, useRef } from 'react'
|
| 4 |
+
import { motion, AnimatePresence } from 'framer-motion'
|
| 5 |
+
import {
|
| 6 |
+
Zap, Send, ChevronRight, Activity, Globe, Terminal,
|
| 7 |
+
Code2, Eye, Bug, Rocket, MessageSquare, Brain,
|
| 8 |
+
Cpu, MemoryStick, Wifi, ArrowRight
|
| 9 |
+
} from 'lucide-react'
|
| 10 |
+
import { useAppStore } from '@/store/useAppStore'
|
| 11 |
+
import { createWebSocket } from '@/lib/api'
|
| 12 |
+
|
| 13 |
+
const SPACES_CONFIG = [
|
| 14 |
+
{ id: 'core', name: 'Core Space', icon: '🧠', color: '#7c3aed', desc: 'Planning & Orchestration', role: 'cognition' },
|
| 15 |
+
{ id: 'browser', name: 'Browser Space', icon: '🌐', color: '#2563eb', desc: 'Web Research & Navigation', role: 'automation' },
|
| 16 |
+
{ id: 'sandbox', name: 'Sandbox Space', icon: '💻', color: '#059669', desc: 'Code Execution & Testing', role: 'execution' },
|
| 17 |
+
{ id: 'coding', name: 'Coding Space', icon: '🔧', color: '#d97706', desc: 'Code Generation & Review', role: 'execution' },
|
| 18 |
+
{ id: 'vision', name: 'Vision Space', icon: '👁️', color: '#db2777', desc: 'UI Design & Image Analysis', role: 'visual_intelligence' },
|
| 19 |
+
{ id: 'debug', name: 'Debug Space', icon: '🐛', color: '#dc2626', desc: 'Error Analysis & Self-Heal', role: 'repair' },
|
| 20 |
+
{ id: 'deploy', name: 'Deploy Space', icon: '🚀', color: '#0891b2', desc: 'Cloud Deploy & CI/CD', role: 'automation' },
|
| 21 |
+
{ id: 'communication', name: 'Comm Space', icon: '💬', color: '#8b5cf6', desc: 'Messaging & Documentation', role: 'automation' },
|
| 22 |
+
]
|
| 23 |
+
|
| 24 |
+
const ROLES_CONFIG = [
|
| 25 |
+
{ id: 'cognition', name: 'Cognition', icon: '🧠', desc: 'The Thinker — Plans & Analyzes' },
|
| 26 |
+
{ id: 'automation', name: 'Automation', icon: '⚙️', desc: 'The Operator — Executes Workflows' },
|
| 27 |
+
{ id: 'execution', name: 'Execution', icon: '⚡', desc: 'The Doer — Writes & Runs Code' },
|
| 28 |
+
{ id: 'repair', name: 'Repair', icon: '🔧', desc: 'The Fixer — Heals Errors' },
|
| 29 |
+
{ id: 'visual_intelligence',name: 'Visual Intel', icon: '👁️', desc: 'The Observer — Sees & Creates UI' },
|
| 30 |
]
|
| 31 |
|
| 32 |
+
interface Message {
|
| 33 |
+
id: string
|
| 34 |
+
role: 'user' | 'assistant'
|
| 35 |
+
content: string
|
| 36 |
+
space?: string
|
| 37 |
+
agentRole?: string
|
| 38 |
+
timestamp: number
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
export default function DashboardPage() {
|
| 42 |
+
const { activeSpace, currentRole, activateSpace, deactivateSpace, spaces } = useAppStore()
|
| 43 |
+
const [messages, setMessages] = useState<Message[]>([
|
| 44 |
+
{
|
| 45 |
+
id: '1',
|
| 46 |
+
role: 'assistant',
|
| 47 |
+
content: '🧠 **GOD AGENT OS v9** is online!\n\nSpace-Role Architecture active. I can handle ANY digital task:\n\n- 🌐 **Browser** — Web research & data extraction\n- 💻 **Sandbox** — Code execution\n- 🔧 **Coding** — Generate any code\n- 👁️ **Vision** — UI design & image analysis\n- 🐛 **Debug** — Error analysis & self-healing\n- 🚀 **Deploy** — Cloud deployments\n- 💬 **Comm** — Documentation & messaging\n\nWhat do you need?',
|
| 48 |
+
timestamp: Date.now(),
|
| 49 |
+
}
|
| 50 |
+
])
|
| 51 |
+
const [input, setInput] = useState('')
|
| 52 |
+
const [isLoading, setIsLoading] = useState(false)
|
| 53 |
+
const [sessionId] = useState(() => `session_${Date.now()}`)
|
| 54 |
+
const [wsStatus, setWsStatus] = useState<'connecting' | 'connected' | 'disconnected'>('disconnected')
|
| 55 |
+
const [activeSpaceIndicator, setActiveSpaceIndicator] = useState<string | null>(null)
|
| 56 |
+
const wsRef = useRef<WebSocket | null>(null)
|
| 57 |
+
const messagesEndRef = useRef<HTMLDivElement>(null)
|
| 58 |
+
const inputRef = useRef<HTMLTextAreaElement>(null)
|
| 59 |
|
| 60 |
+
useEffect(() => {
|
| 61 |
+
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' })
|
| 62 |
+
}, [messages])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
|
| 64 |
+
useEffect(() => {
|
| 65 |
+
connectWS()
|
| 66 |
+
return () => wsRef.current?.close()
|
| 67 |
+
}, [sessionId])
|
| 68 |
+
|
| 69 |
+
function connectWS() {
|
| 70 |
+
try {
|
| 71 |
+
const ws = createWebSocket(`/ws/chat/${sessionId}`)
|
| 72 |
+
wsRef.current = ws
|
| 73 |
+
setWsStatus('connecting')
|
| 74 |
+
|
| 75 |
+
ws.onopen = () => {
|
| 76 |
+
setWsStatus('connected')
|
| 77 |
+
ws.send(JSON.stringify({ type: 'ping' }))
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
ws.onmessage = (event) => {
|
| 81 |
+
try {
|
| 82 |
+
const msg = JSON.parse(event.data)
|
| 83 |
+
|
| 84 |
+
if (msg.type === 'space_activated') {
|
| 85 |
+
setActiveSpaceIndicator(msg.space)
|
| 86 |
+
activateSpace(msg.space as any, msg.role)
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
if (msg.type === 'chat_response' || msg.type === 'agent_response') {
|
| 90 |
+
const content = msg.content || msg.message || msg.data?.content || ''
|
| 91 |
+
if (content) {
|
| 92 |
+
setMessages(prev => {
|
| 93 |
+
const last = prev[prev.length - 1]
|
| 94 |
+
if (last?.role === 'assistant' && last.id.startsWith('stream_')) {
|
| 95 |
+
return [...prev.slice(0, -1), { ...last, content }]
|
| 96 |
+
}
|
| 97 |
+
return [...prev, {
|
| 98 |
+
id: `msg_${Date.now()}`,
|
| 99 |
+
role: 'assistant',
|
| 100 |
+
content,
|
| 101 |
+
space: msg.space,
|
| 102 |
+
agentRole: msg.role,
|
| 103 |
+
timestamp: Date.now(),
|
| 104 |
+
}]
|
| 105 |
+
})
|
| 106 |
+
setIsLoading(false)
|
| 107 |
+
}
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
if (msg.type === 'kernel_status') {
|
| 111 |
+
// Kernel is thinking
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
} catch (e) {}
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
ws.onclose = () => {
|
| 118 |
+
setWsStatus('disconnected')
|
| 119 |
+
setTimeout(connectWS, 3000)
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
ws.onerror = () => setWsStatus('disconnected')
|
| 123 |
+
} catch (e) {}
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
async function sendMessage() {
|
| 127 |
+
if (!input.trim() || isLoading) return
|
| 128 |
+
const userMsg = input.trim()
|
| 129 |
+
setInput('')
|
| 130 |
+
setIsLoading(true)
|
| 131 |
+
|
| 132 |
+
setMessages(prev => [...prev, {
|
| 133 |
+
id: `user_${Date.now()}`,
|
| 134 |
+
role: 'user',
|
| 135 |
+
content: userMsg,
|
| 136 |
+
timestamp: Date.now(),
|
| 137 |
+
}])
|
| 138 |
+
|
| 139 |
+
// Send via WebSocket
|
| 140 |
+
if (wsRef.current?.readyState === WebSocket.OPEN) {
|
| 141 |
+
wsRef.current.send(JSON.stringify({
|
| 142 |
+
type: 'chat_message',
|
| 143 |
+
content: userMsg,
|
| 144 |
+
session_id: sessionId,
|
| 145 |
+
}))
|
| 146 |
+
|
| 147 |
+
// Fallback: if no WS response in 15s, try REST
|
| 148 |
+
setTimeout(async () => {
|
| 149 |
+
setIsLoading(prev => {
|
| 150 |
+
if (prev) {
|
| 151 |
+
// Still loading, try REST
|
| 152 |
+
fetchREST(userMsg)
|
| 153 |
+
}
|
| 154 |
+
return prev
|
| 155 |
+
})
|
| 156 |
+
}, 15000)
|
| 157 |
+
} else {
|
| 158 |
+
// REST fallback
|
| 159 |
+
await fetchREST(userMsg)
|
| 160 |
+
}
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
async function fetchREST(userMsg: string) {
|
| 164 |
+
try {
|
| 165 |
+
const res = await fetch('/api/v1/kernel/orchestrate', {
|
| 166 |
+
method: 'POST',
|
| 167 |
+
headers: { 'Content-Type': 'application/json' },
|
| 168 |
+
body: JSON.stringify({ message: userMsg, session_id: sessionId }),
|
| 169 |
+
}).catch(() => null)
|
| 170 |
+
|
| 171 |
+
if (res?.ok) {
|
| 172 |
+
const data = await res.json()
|
| 173 |
+
if (data.result) {
|
| 174 |
+
setMessages(prev => [...prev, {
|
| 175 |
+
id: `assistant_${Date.now()}`,
|
| 176 |
+
role: 'assistant',
|
| 177 |
+
content: data.result,
|
| 178 |
+
timestamp: Date.now(),
|
| 179 |
+
}])
|
| 180 |
+
}
|
| 181 |
+
} else {
|
| 182 |
+
// Local fallback
|
| 183 |
+
setMessages(prev => [...prev, {
|
| 184 |
+
id: `assistant_${Date.now()}`,
|
| 185 |
+
role: 'assistant',
|
| 186 |
+
content: `I'm processing your request: "${userMsg}"\n\n⚠️ Backend connection in progress. The Space-Role system is initializing.`,
|
| 187 |
+
timestamp: Date.now(),
|
| 188 |
+
}])
|
| 189 |
+
}
|
| 190 |
+
} catch (e) {
|
| 191 |
+
setMessages(prev => [...prev, {
|
| 192 |
+
id: `err_${Date.now()}`,
|
| 193 |
+
role: 'assistant',
|
| 194 |
+
content: '⚠️ Connection issue. Please ensure the backend is running.',
|
| 195 |
+
timestamp: Date.now(),
|
| 196 |
+
}])
|
| 197 |
+
}
|
| 198 |
+
setIsLoading(false)
|
| 199 |
+
}
|
| 200 |
|
| 201 |
+
function handleKeyDown(e: React.KeyboardEvent) {
|
| 202 |
+
if (e.key === 'Enter' && !e.shiftKey) {
|
| 203 |
+
e.preventDefault()
|
| 204 |
+
sendMessage()
|
| 205 |
+
}
|
| 206 |
+
}
|
| 207 |
+
|
| 208 |
+
const statusColor = wsStatus === 'connected' ? '#22c55e' : wsStatus === 'connecting' ? '#f59e0b' : '#ef4444'
|
| 209 |
+
|
| 210 |
+
return (
|
| 211 |
+
<div className="flex h-full" style={{ background: '#05060d' }}>
|
| 212 |
+
|
| 213 |
+
{/* Left: Chat Panel */}
|
| 214 |
+
<div className="flex flex-col flex-1 min-w-0">
|
| 215 |
+
|
| 216 |
+
{/* Space Status Bar */}
|
| 217 |
+
<div className="h-8 flex items-center gap-2 px-3 border-b overflow-x-auto"
|
| 218 |
+
style={{ borderColor: '#1a1b2e', background: '#07080f' }}>
|
| 219 |
+
{SPACES_CONFIG.map(s => {
|
| 220 |
+
const spaceState = spaces[s.id as keyof typeof spaces]
|
| 221 |
+
const isActive = spaceState?.active
|
| 222 |
+
return (
|
| 223 |
+
<div key={s.id}
|
| 224 |
+
className="flex items-center gap-1 px-2 py-0.5 rounded text-[10px] whitespace-nowrap transition-all"
|
| 225 |
+
style={{
|
| 226 |
+
background: isActive ? `${s.color}15` : 'transparent',
|
| 227 |
+
color: isActive ? s.color : '#374151',
|
| 228 |
+
border: `1px solid ${isActive ? s.color + '30' : 'transparent'}`,
|
| 229 |
+
}}>
|
| 230 |
+
<span>{s.icon}</span>
|
| 231 |
+
<span className="font-medium">{s.id}</span>
|
| 232 |
+
{isActive && <span className="w-1 h-1 rounded-full animate-pulse" style={{ background: s.color }} />}
|
| 233 |
</div>
|
| 234 |
+
)
|
| 235 |
+
})}
|
| 236 |
+
<div className="ml-auto flex items-center gap-1 text-[10px]">
|
| 237 |
+
<div className="w-1.5 h-1.5 rounded-full" style={{ background: statusColor }} />
|
| 238 |
+
<span style={{ color: statusColor }}>{wsStatus}</span>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 239 |
</div>
|
| 240 |
+
</div>
|
| 241 |
|
| 242 |
+
{/* Messages */}
|
| 243 |
+
<div className="flex-1 overflow-y-auto p-4 space-y-4">
|
| 244 |
+
<AnimatePresence initial={false}>
|
| 245 |
+
{messages.map(msg => (
|
| 246 |
+
<motion.div
|
| 247 |
+
key={msg.id}
|
| 248 |
+
initial={{ opacity: 0, y: 10 }}
|
| 249 |
+
animate={{ opacity: 1, y: 0 }}
|
| 250 |
+
transition={{ duration: 0.2 }}
|
| 251 |
+
className={`flex gap-3 ${msg.role === 'user' ? 'flex-row-reverse' : 'flex-row'}`}
|
| 252 |
+
>
|
| 253 |
+
{/* Avatar */}
|
| 254 |
+
<div className={`w-7 h-7 rounded-lg flex-shrink-0 flex items-center justify-center text-sm ${
|
| 255 |
+
msg.role === 'user'
|
| 256 |
+
? 'bg-indigo-600'
|
| 257 |
+
: 'bg-gradient-to-br from-violet-600 to-indigo-600'
|
| 258 |
+
}`}>
|
| 259 |
+
{msg.role === 'user' ? '👤' : '🤖'}
|
| 260 |
+
</div>
|
| 261 |
+
|
| 262 |
+
{/* Bubble */}
|
| 263 |
+
<div className={`max-w-[75%] ${msg.role === 'user' ? 'items-end' : 'items-start'} flex flex-col gap-1`}>
|
| 264 |
+
{msg.space && (
|
| 265 |
+
<div className="text-[9px] text-slate-600 px-1">
|
| 266 |
+
{SPACES_CONFIG.find(s => s.id === msg.space)?.icon} {msg.space?.toUpperCase()} SPACE · {msg.agentRole?.replace('_', ' ')}
|
| 267 |
+
</div>
|
| 268 |
+
)}
|
| 269 |
+
<div className={`px-3 py-2 rounded-2xl text-sm leading-relaxed ${
|
| 270 |
+
msg.role === 'user'
|
| 271 |
+
? 'bg-indigo-600 text-white rounded-tr-sm'
|
| 272 |
+
: 'text-slate-200 rounded-tl-sm'
|
| 273 |
+
}`}
|
| 274 |
+
style={msg.role === 'assistant' ? { background: '#111827', border: '1px solid #1f2937' } : {}}>
|
| 275 |
+
<div className="whitespace-pre-wrap"
|
| 276 |
+
dangerouslySetInnerHTML={{
|
| 277 |
+
__html: msg.content
|
| 278 |
+
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
|
| 279 |
+
.replace(/```(\w+)?\n?([\s\S]*?)```/g, '<pre class="bg-black/50 p-2 rounded mt-1 overflow-x-auto text-xs"><code>$2</code></pre>')
|
| 280 |
+
.replace(/`(.*?)`/g, '<code class="bg-black/30 px-1 rounded text-xs">$1</code>')
|
| 281 |
+
}}
|
| 282 |
+
/>
|
| 283 |
+
</div>
|
| 284 |
+
</div>
|
| 285 |
+
</motion.div>
|
| 286 |
+
))}
|
| 287 |
+
</AnimatePresence>
|
| 288 |
+
|
| 289 |
+
{isLoading && (
|
| 290 |
+
<motion.div
|
| 291 |
+
initial={{ opacity: 0 }}
|
| 292 |
+
animate={{ opacity: 1 }}
|
| 293 |
+
className="flex gap-3 items-start"
|
| 294 |
+
>
|
| 295 |
+
<div className="w-7 h-7 rounded-lg bg-gradient-to-br from-violet-600 to-indigo-600 flex items-center justify-center text-sm">🤖</div>
|
| 296 |
+
<div className="px-3 py-2 rounded-2xl rounded-tl-sm" style={{ background: '#111827', border: '1px solid #1f2937' }}>
|
| 297 |
+
<div className="flex items-center gap-2 text-xs text-slate-400">
|
| 298 |
+
<div className="flex gap-1">
|
| 299 |
+
{[0,1,2].map(i => (
|
| 300 |
+
<div key={i} className="w-1.5 h-1.5 rounded-full bg-violet-500 animate-bounce"
|
| 301 |
+
style={{ animationDelay: `${i * 0.15}s` }} />
|
| 302 |
+
))}
|
| 303 |
+
</div>
|
| 304 |
+
{activeSpaceIndicator
|
| 305 |
+
? `${SPACES_CONFIG.find(s => s.id === activeSpaceIndicator)?.icon} ${activeSpaceIndicator} Space processing...`
|
| 306 |
+
: 'Agent Kernel analyzing...'
|
| 307 |
+
}
|
| 308 |
+
</div>
|
| 309 |
+
</div>
|
| 310 |
+
</motion.div>
|
| 311 |
+
)}
|
| 312 |
+
|
| 313 |
+
<div ref={messagesEndRef} />
|
| 314 |
</div>
|
| 315 |
|
| 316 |
+
{/* Quick Prompts */}
|
| 317 |
+
<div className="px-3 pb-2 flex gap-2 overflow-x-auto">
|
| 318 |
+
{[
|
| 319 |
+
{ text: '🌐 Search latest AI trends', space: 'browser' },
|
| 320 |
+
{ text: '🔧 Write a Python API', space: 'coding' },
|
| 321 |
+
{ text: '💻 Run: print("Hello")', space: 'sandbox' },
|
| 322 |
+
{ text: '🚀 Generate Dockerfile', space: 'deploy' },
|
| 323 |
+
{ text: '🐛 Debug my error', space: 'debug' },
|
| 324 |
+
{ text: '👁️ Create React UI', space: 'vision' },
|
| 325 |
+
].map((prompt, i) => (
|
| 326 |
+
<button key={i}
|
| 327 |
+
onClick={() => { setInput(prompt.text); inputRef.current?.focus() }}
|
| 328 |
+
className="flex-shrink-0 px-3 py-1.5 rounded-full text-xs text-slate-400 hover:text-slate-200 whitespace-nowrap transition-all"
|
| 329 |
+
style={{ background: '#0d0e1a', border: '1px solid #1e2035' }}>
|
| 330 |
+
{prompt.text}
|
| 331 |
+
</button>
|
| 332 |
+
))}
|
| 333 |
+
</div>
|
| 334 |
|
| 335 |
+
{/* Input */}
|
| 336 |
+
<div className="px-3 pb-3">
|
| 337 |
+
<div className="flex gap-2 p-2 rounded-xl" style={{ background: '#0d0e1a', border: '1px solid #1e2035' }}>
|
| 338 |
+
<textarea
|
| 339 |
+
ref={inputRef}
|
| 340 |
+
value={input}
|
| 341 |
+
onChange={e => setInput(e.target.value)}
|
| 342 |
+
onKeyDown={handleKeyDown}
|
| 343 |
+
placeholder="Ask anything — I'll route to the right Space automatically..."
|
| 344 |
+
rows={1}
|
| 345 |
+
className="flex-1 bg-transparent text-sm text-slate-200 placeholder-slate-600 resize-none outline-none leading-relaxed"
|
| 346 |
+
style={{ maxHeight: '120px' }}
|
| 347 |
+
/>
|
| 348 |
+
<button
|
| 349 |
+
onClick={sendMessage}
|
| 350 |
+
disabled={!input.trim() || isLoading}
|
| 351 |
+
className="p-2 rounded-lg transition-all disabled:opacity-40 flex-shrink-0"
|
| 352 |
+
style={{ background: 'linear-gradient(135deg, #7c3aed, #4f46e5)' }}>
|
| 353 |
+
<Send size={14} className="text-white" />
|
| 354 |
+
</button>
|
| 355 |
+
</div>
|
| 356 |
+
<div className="text-[9px] text-slate-700 text-center mt-1">
|
| 357 |
+
Press Enter to send · Shift+Enter for new line · Powered by Pyae Sone
|
| 358 |
+
</div>
|
| 359 |
+
</div>
|
| 360 |
+
</div>
|
| 361 |
|
| 362 |
+
{/* Right: Space-Role Panel */}
|
| 363 |
+
<div className="w-64 border-l flex-shrink-0 flex flex-col overflow-y-auto"
|
| 364 |
+
style={{ borderColor: '#1a1b2e', background: '#07080f' }}>
|
| 365 |
+
|
| 366 |
+
{/* Spaces Grid */}
|
| 367 |
+
<div className="p-3 border-b" style={{ borderColor: '#1a1b2e' }}>
|
| 368 |
+
<div className="text-[10px] text-slate-600 font-bold uppercase tracking-widest mb-2">Spaces</div>
|
| 369 |
+
<div className="grid grid-cols-2 gap-1.5">
|
| 370 |
+
{SPACES_CONFIG.map(s => {
|
| 371 |
+
const spaceState = spaces[s.id as keyof typeof spaces]
|
| 372 |
+
const isActive = spaceState?.active
|
| 373 |
+
return (
|
| 374 |
+
<div key={s.id}
|
| 375 |
+
className="p-2 rounded-lg transition-all cursor-pointer"
|
| 376 |
+
style={{
|
| 377 |
+
background: isActive ? `${s.color}10` : 'rgba(255,255,255,0.03)',
|
| 378 |
+
border: `1px solid ${isActive ? s.color + '40' : '#1e2035'}`,
|
| 379 |
+
}}>
|
| 380 |
+
<div className="flex items-center justify-between mb-0.5">
|
| 381 |
+
<span className="text-base">{s.icon}</span>
|
| 382 |
+
{isActive && (
|
| 383 |
+
<div className="w-1.5 h-1.5 rounded-full animate-pulse"
|
| 384 |
+
style={{ background: s.color }} />
|
| 385 |
+
)}
|
| 386 |
+
</div>
|
| 387 |
+
<div className="text-[10px] font-semibold" style={{ color: isActive ? s.color : '#475569' }}>
|
| 388 |
+
{s.name.split(' ')[0]}
|
| 389 |
+
</div>
|
| 390 |
+
<div className="text-[8px] text-slate-600 mt-0.5">{s.desc}</div>
|
| 391 |
+
{spaceState?.taskCount > 0 && (
|
| 392 |
+
<div className="text-[8px] mt-0.5" style={{ color: s.color }}>
|
| 393 |
+
{spaceState.taskCount} tasks
|
| 394 |
+
</div>
|
| 395 |
+
)}
|
| 396 |
+
</div>
|
| 397 |
+
)
|
| 398 |
+
})}
|
| 399 |
</div>
|
| 400 |
+
</div>
|
| 401 |
|
| 402 |
+
{/* Roles */}
|
| 403 |
+
<div className="p-3 border-b" style={{ borderColor: '#1a1b2e' }}>
|
| 404 |
+
<div className="text-[10px] text-slate-600 font-bold uppercase tracking-widest mb-2">Roles</div>
|
| 405 |
+
<div className="space-y-1">
|
| 406 |
+
{ROLES_CONFIG.map(r => (
|
| 407 |
+
<div key={r.id}
|
| 408 |
+
className="flex items-center gap-2 p-1.5 rounded-lg transition-all"
|
| 409 |
+
style={{
|
| 410 |
+
background: currentRole === r.id ? 'rgba(139,92,246,0.1)' : 'transparent',
|
| 411 |
+
border: `1px solid ${currentRole === r.id ? 'rgba(139,92,246,0.3)' : 'transparent'}`,
|
| 412 |
+
}}>
|
| 413 |
+
<span className="text-sm">{r.icon}</span>
|
| 414 |
+
<div>
|
| 415 |
+
<div className="text-[10px] font-semibold" style={{ color: currentRole === r.id ? '#a78bfa' : '#475569' }}>
|
| 416 |
+
{r.name}
|
| 417 |
+
</div>
|
| 418 |
+
<div className="text-[8px] text-slate-600">{r.desc}</div>
|
| 419 |
+
</div>
|
| 420 |
+
</div>
|
| 421 |
+
))}
|
| 422 |
</div>
|
| 423 |
+
</div>
|
| 424 |
|
| 425 |
+
{/* System Status */}
|
| 426 |
+
<div className="p-3">
|
| 427 |
+
<div className="text-[10px] text-slate-600 font-bold uppercase tracking-widest mb-2">System</div>
|
| 428 |
+
<div className="space-y-1.5">
|
| 429 |
+
{[
|
| 430 |
+
{ label: 'Agent Kernel', status: 'operational', color: '#22c55e' },
|
| 431 |
+
{ label: 'AI Router', status: 'active', color: '#22c55e' },
|
| 432 |
+
{ label: 'Memory', status: 'ready', color: '#22c55e' },
|
| 433 |
+
{ label: 'WebSocket', status: wsStatus, color: statusColor },
|
| 434 |
+
].map(item => (
|
| 435 |
+
<div key={item.label} className="flex items-center justify-between">
|
| 436 |
+
<span className="text-[10px] text-slate-500">{item.label}</span>
|
| 437 |
+
<div className="flex items-center gap-1">
|
| 438 |
+
<div className="w-1.5 h-1.5 rounded-full" style={{ background: item.color }} />
|
| 439 |
+
<span className="text-[9px]" style={{ color: item.color }}>{item.status}</span>
|
| 440 |
+
</div>
|
| 441 |
+
</div>
|
| 442 |
+
))}
|
| 443 |
</div>
|
| 444 |
</div>
|
| 445 |
</div>
|
frontend/components/pages/SpacesPage.tsx
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client'
|
| 2 |
+
|
| 3 |
+
import { useState, useEffect } from 'react'
|
| 4 |
+
import { motion } from 'framer-motion'
|
| 5 |
+
import { Play, RefreshCw } from 'lucide-react'
|
| 6 |
+
import { useAppStore } from '@/store/useAppStore'
|
| 7 |
+
|
| 8 |
+
const SPACES_DETAIL = [
|
| 9 |
+
{
|
| 10 |
+
id: 'core',
|
| 11 |
+
name: 'Core Space',
|
| 12 |
+
icon: '🧠',
|
| 13 |
+
color: '#7c3aed',
|
| 14 |
+
description: 'The central nervous system. Manages memory, planning, and overall orchestration.',
|
| 15 |
+
tools: ['Goal decomposition', 'Long-term memory access', 'Task delegation', 'Context management'],
|
| 16 |
+
roles: ['Cognition', 'Automation'],
|
| 17 |
+
phase: 'Phase 1',
|
| 18 |
+
},
|
| 19 |
+
{
|
| 20 |
+
id: 'browser',
|
| 21 |
+
name: 'Browser Space',
|
| 22 |
+
icon: '🌐',
|
| 23 |
+
color: '#2563eb',
|
| 24 |
+
description: 'The interface to the web. Handles all internet-based research and interaction.',
|
| 25 |
+
tools: ['Web navigation', 'DOM parsing', 'Data extraction', 'Form filling'],
|
| 26 |
+
roles: ['Automation', 'Cognition'],
|
| 27 |
+
phase: 'Phase 3',
|
| 28 |
+
},
|
| 29 |
+
{
|
| 30 |
+
id: 'sandbox',
|
| 31 |
+
name: 'Sandbox Space',
|
| 32 |
+
icon: '💻',
|
| 33 |
+
color: '#059669',
|
| 34 |
+
description: 'Secure execution environment. Where code is run and tested safely.',
|
| 35 |
+
tools: ['Python interpreter', 'Node.js runtime', 'Shell access', 'Isolated filesystem'],
|
| 36 |
+
roles: ['Execution', 'Cognition'],
|
| 37 |
+
phase: 'Phase 3',
|
| 38 |
+
},
|
| 39 |
+
{
|
| 40 |
+
id: 'coding',
|
| 41 |
+
name: 'Coding Space',
|
| 42 |
+
icon: '🔧',
|
| 43 |
+
color: '#d97706',
|
| 44 |
+
description: 'The development environment. Focused on code generation and manipulation.',
|
| 45 |
+
tools: ['Multi-language codegen', 'Code review', 'Refactoring', 'Test generation'],
|
| 46 |
+
roles: ['Execution', 'Cognition', 'Automation'],
|
| 47 |
+
phase: 'Phase 3',
|
| 48 |
+
},
|
| 49 |
+
{
|
| 50 |
+
id: 'vision',
|
| 51 |
+
name: 'Vision Space',
|
| 52 |
+
icon: '👁️',
|
| 53 |
+
color: '#db2777',
|
| 54 |
+
description: 'Visual processing domain. Handles image understanding and UI generation.',
|
| 55 |
+
tools: ['UI generation', 'Image analysis', 'Design-to-code', 'OCR'],
|
| 56 |
+
roles: ['Visual Intelligence', 'Execution'],
|
| 57 |
+
phase: 'Phase 3',
|
| 58 |
+
},
|
| 59 |
+
{
|
| 60 |
+
id: 'debug',
|
| 61 |
+
name: 'Debug Space',
|
| 62 |
+
icon: '🐛',
|
| 63 |
+
color: '#dc2626',
|
| 64 |
+
description: 'Diagnostic environment. Analyzes errors and proposes self-healing solutions.',
|
| 65 |
+
tools: ['Stack trace analysis', 'Log parsing', 'Error classification', 'Self-healing'],
|
| 66 |
+
roles: ['Repair', 'Cognition'],
|
| 67 |
+
phase: 'Phase 3',
|
| 68 |
+
},
|
| 69 |
+
{
|
| 70 |
+
id: 'deploy',
|
| 71 |
+
name: 'Deploy Space',
|
| 72 |
+
icon: '🚀',
|
| 73 |
+
color: '#0891b2',
|
| 74 |
+
description: 'Infrastructure domain. Manages cloud deployments and CI/CD pipelines.',
|
| 75 |
+
tools: ['Vercel deploy', 'Docker config', 'GitHub Actions', 'HuggingFace Spaces'],
|
| 76 |
+
roles: ['Automation', 'Execution'],
|
| 77 |
+
phase: 'Phase 3',
|
| 78 |
+
},
|
| 79 |
+
{
|
| 80 |
+
id: 'communication',
|
| 81 |
+
name: 'Communication Space',
|
| 82 |
+
icon: '💬',
|
| 83 |
+
color: '#8b5cf6',
|
| 84 |
+
description: 'Interaction domain. Manages documentation, email, and multi-channel messaging.',
|
| 85 |
+
tools: ['Email drafting', 'Documentation', 'Report creation', 'Translation'],
|
| 86 |
+
roles: ['Automation', 'Cognition'],
|
| 87 |
+
phase: 'Phase 2',
|
| 88 |
+
},
|
| 89 |
+
]
|
| 90 |
+
|
| 91 |
+
export default function SpacesPage() {
|
| 92 |
+
const { spaces, activeSpace } = useAppStore()
|
| 93 |
+
const [selectedSpace, setSelectedSpace] = useState<string | null>(null)
|
| 94 |
+
const [testTask, setTestTask] = useState('')
|
| 95 |
+
const [testResult, setTestResult] = useState('')
|
| 96 |
+
const [testing, setTesting] = useState(false)
|
| 97 |
+
|
| 98 |
+
async function testSpace(spaceId: string) {
|
| 99 |
+
if (!testTask.trim()) return
|
| 100 |
+
setTesting(true)
|
| 101 |
+
setTestResult('')
|
| 102 |
+
try {
|
| 103 |
+
const res = await fetch(`/api/v1/spaces/${spaceId}/execute`, {
|
| 104 |
+
method: 'POST',
|
| 105 |
+
headers: { 'Content-Type': 'application/json' },
|
| 106 |
+
body: JSON.stringify({ task: testTask, role: 'cognition', session_id: 'spaces_test' }),
|
| 107 |
+
})
|
| 108 |
+
if (res.ok) {
|
| 109 |
+
const data = await res.json()
|
| 110 |
+
setTestResult(data.result || 'No result')
|
| 111 |
+
} else {
|
| 112 |
+
setTestResult(`Error: ${res.status} ${res.statusText}`)
|
| 113 |
+
}
|
| 114 |
+
} catch (e: any) {
|
| 115 |
+
setTestResult(`Connection error: ${e.message}`)
|
| 116 |
+
}
|
| 117 |
+
setTesting(false)
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
return (
|
| 121 |
+
<div className="h-full overflow-y-auto p-6" style={{ background: '#05060d' }}>
|
| 122 |
+
<div className="max-w-6xl mx-auto">
|
| 123 |
+
{/* Header */}
|
| 124 |
+
<div className="mb-6">
|
| 125 |
+
<h1 className="text-2xl font-bold text-white mb-1">Space-Role Architecture</h1>
|
| 126 |
+
<p className="text-slate-500 text-sm">8 Spaces × 5 Roles = Infinite capability combinations</p>
|
| 127 |
+
</div>
|
| 128 |
+
|
| 129 |
+
{/* Architecture Diagram */}
|
| 130 |
+
<div className="mb-6 p-4 rounded-xl border" style={{ background: '#07080f', borderColor: '#1e2035' }}>
|
| 131 |
+
<div className="text-[10px] text-slate-600 font-bold uppercase tracking-widest mb-3">Architecture Overview</div>
|
| 132 |
+
<div className="flex items-center justify-center gap-3 flex-wrap">
|
| 133 |
+
<div className="px-3 py-2 rounded-lg text-xs font-semibold text-violet-300"
|
| 134 |
+
style={{ background: 'rgba(139,92,246,0.15)', border: '1px solid rgba(139,92,246,0.3)' }}>
|
| 135 |
+
🧠 Agent Kernel
|
| 136 |
+
</div>
|
| 137 |
+
<div className="text-slate-600">→</div>
|
| 138 |
+
<div className="px-3 py-2 rounded-lg text-xs font-semibold text-blue-300"
|
| 139 |
+
style={{ background: 'rgba(37,99,235,0.15)', border: '1px solid rgba(37,99,235,0.3)' }}>
|
| 140 |
+
🎯 Intent Classifier
|
| 141 |
+
</div>
|
| 142 |
+
<div className="text-slate-600">→</div>
|
| 143 |
+
<div className="px-3 py-2 rounded-lg text-xs font-semibold text-green-300"
|
| 144 |
+
style={{ background: 'rgba(5,150,105,0.15)', border: '1px solid rgba(5,150,105,0.3)' }}>
|
| 145 |
+
📦 Space Router
|
| 146 |
+
</div>
|
| 147 |
+
<div className="text-slate-600">→</div>
|
| 148 |
+
<div className="px-3 py-2 rounded-lg text-xs font-semibold text-orange-300"
|
| 149 |
+
style={{ background: 'rgba(217,119,6,0.15)', border: '1px solid rgba(217,119,6,0.3)' }}>
|
| 150 |
+
🎭 Role Assignment
|
| 151 |
+
</div>
|
| 152 |
+
<div className="text-slate-600">→</div>
|
| 153 |
+
<div className="px-3 py-2 rounded-lg text-xs font-semibold text-pink-300"
|
| 154 |
+
style={{ background: 'rgba(219,39,119,0.15)', border: '1px solid rgba(219,39,119,0.3)' }}>
|
| 155 |
+
🛠️ Tool Execution
|
| 156 |
+
</div>
|
| 157 |
+
</div>
|
| 158 |
+
</div>
|
| 159 |
+
|
| 160 |
+
{/* Spaces Grid */}
|
| 161 |
+
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-4 mb-6">
|
| 162 |
+
{SPACES_DETAIL.map((space, i) => {
|
| 163 |
+
const spaceState = spaces[space.id as keyof typeof spaces]
|
| 164 |
+
const isActive = spaceState?.active
|
| 165 |
+
const isSelected = selectedSpace === space.id
|
| 166 |
+
|
| 167 |
+
return (
|
| 168 |
+
<motion.div
|
| 169 |
+
key={space.id}
|
| 170 |
+
initial={{ opacity: 0, y: 20 }}
|
| 171 |
+
animate={{ opacity: 1, y: 0 }}
|
| 172 |
+
transition={{ delay: i * 0.05 }}
|
| 173 |
+
onClick={() => setSelectedSpace(isSelected ? null : space.id)}
|
| 174 |
+
className="p-4 rounded-xl border cursor-pointer transition-all hover:scale-[1.02]"
|
| 175 |
+
style={{
|
| 176 |
+
background: isSelected ? `${space.color}10` : '#07080f',
|
| 177 |
+
borderColor: isSelected ? `${space.color}50` : isActive ? `${space.color}30` : '#1e2035',
|
| 178 |
+
}}>
|
| 179 |
+
|
| 180 |
+
<div className="flex items-center justify-between mb-3">
|
| 181 |
+
<span className="text-2xl">{space.icon}</span>
|
| 182 |
+
<div className="flex items-center gap-1">
|
| 183 |
+
<span className="text-[9px] px-1.5 py-0.5 rounded"
|
| 184 |
+
style={{ background: `${space.color}20`, color: space.color }}>
|
| 185 |
+
{space.phase}
|
| 186 |
+
</span>
|
| 187 |
+
{isActive && (
|
| 188 |
+
<div className="w-1.5 h-1.5 rounded-full animate-pulse"
|
| 189 |
+
style={{ background: space.color }} />
|
| 190 |
+
)}
|
| 191 |
+
</div>
|
| 192 |
+
</div>
|
| 193 |
+
|
| 194 |
+
<h3 className="text-sm font-bold text-white mb-1">{space.name}</h3>
|
| 195 |
+
<p className="text-[10px] text-slate-500 mb-3 leading-relaxed">{space.description}</p>
|
| 196 |
+
|
| 197 |
+
<div className="space-y-2">
|
| 198 |
+
<div>
|
| 199 |
+
<div className="text-[9px] text-slate-700 mb-1">TOOLS</div>
|
| 200 |
+
<div className="flex flex-wrap gap-1">
|
| 201 |
+
{space.tools.slice(0, 2).map(tool => (
|
| 202 |
+
<span key={tool} className="text-[8px] px-1.5 py-0.5 rounded"
|
| 203 |
+
style={{ background: '#0d0e1a', color: '#475569', border: '1px solid #1e2035' }}>
|
| 204 |
+
{tool}
|
| 205 |
+
</span>
|
| 206 |
+
))}
|
| 207 |
+
</div>
|
| 208 |
+
</div>
|
| 209 |
+
<div className="flex items-center justify-between">
|
| 210 |
+
<div className="text-[9px] text-slate-700">
|
| 211 |
+
ROLES: <span style={{ color: space.color }}>{space.roles.join(', ')}</span>
|
| 212 |
+
</div>
|
| 213 |
+
{spaceState?.taskCount > 0 && (
|
| 214 |
+
<span className="text-[9px]" style={{ color: space.color }}>
|
| 215 |
+
{spaceState.taskCount} tasks
|
| 216 |
+
</span>
|
| 217 |
+
)}
|
| 218 |
+
</div>
|
| 219 |
+
</div>
|
| 220 |
+
</motion.div>
|
| 221 |
+
)
|
| 222 |
+
})}
|
| 223 |
+
</div>
|
| 224 |
+
|
| 225 |
+
{/* Space Tester */}
|
| 226 |
+
{selectedSpace && (
|
| 227 |
+
<motion.div
|
| 228 |
+
initial={{ opacity: 0, height: 0 }}
|
| 229 |
+
animate={{ opacity: 1, height: 'auto' }}
|
| 230 |
+
className="p-4 rounded-xl border"
|
| 231 |
+
style={{
|
| 232 |
+
background: '#07080f',
|
| 233 |
+
borderColor: `${SPACES_DETAIL.find(s => s.id === selectedSpace)?.color}40`
|
| 234 |
+
}}>
|
| 235 |
+
<div className="text-sm font-bold text-white mb-3">
|
| 236 |
+
Test {SPACES_DETAIL.find(s => s.id === selectedSpace)?.icon} {selectedSpace} Space
|
| 237 |
+
</div>
|
| 238 |
+
<div className="flex gap-2 mb-3">
|
| 239 |
+
<input
|
| 240 |
+
value={testTask}
|
| 241 |
+
onChange={e => setTestTask(e.target.value)}
|
| 242 |
+
placeholder={`Enter a task for ${selectedSpace} space...`}
|
| 243 |
+
className="flex-1 px-3 py-2 rounded-lg text-sm text-slate-200 bg-black/20 outline-none"
|
| 244 |
+
style={{ border: '1px solid #1e2035' }}
|
| 245 |
+
onKeyDown={e => e.key === 'Enter' && testSpace(selectedSpace)}
|
| 246 |
+
/>
|
| 247 |
+
<button
|
| 248 |
+
onClick={() => testSpace(selectedSpace)}
|
| 249 |
+
disabled={testing || !testTask.trim()}
|
| 250 |
+
className="flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium text-white disabled:opacity-50 transition-all"
|
| 251 |
+
style={{ background: SPACES_DETAIL.find(s => s.id === selectedSpace)?.color }}>
|
| 252 |
+
{testing ? <RefreshCw size={14} className="animate-spin" /> : <Play size={14} />}
|
| 253 |
+
{testing ? 'Running...' : 'Execute'}
|
| 254 |
+
</button>
|
| 255 |
+
</div>
|
| 256 |
+
{testResult && (
|
| 257 |
+
<div className="p-3 rounded-lg text-xs text-slate-300 whitespace-pre-wrap"
|
| 258 |
+
style={{ background: '#0a0b14', border: '1px solid #1e2035' }}>
|
| 259 |
+
{testResult}
|
| 260 |
+
</div>
|
| 261 |
+
)}
|
| 262 |
+
</motion.div>
|
| 263 |
+
)}
|
| 264 |
+
</div>
|
| 265 |
+
</div>
|
| 266 |
+
)
|
| 267 |
+
}
|
frontend/components/pages/TasksPage.tsx
CHANGED
|
@@ -3,7 +3,8 @@
|
|
| 3 |
import { useState } from 'react'
|
| 4 |
import { motion } from 'framer-motion'
|
| 5 |
import { CheckSquare, Clock, Loader2, AlertCircle, Plus, ChevronRight } from 'lucide-react'
|
| 6 |
-
|
|
|
|
| 7 |
import { cn } from '@/lib/utils'
|
| 8 |
|
| 9 |
const STATUS_CONFIG = {
|
|
|
|
| 3 |
import { useState } from 'react'
|
| 4 |
import { motion } from 'framer-motion'
|
| 5 |
import { CheckSquare, Clock, Loader2, AlertCircle, Plus, ChevronRight } from 'lucide-react'
|
| 6 |
+
type Task = { id: string; title: string; status: 'running' | 'completed' | 'pending' | 'failed'; space?: string; agent?: string; goal: string; started?: number; completed_at?: number }
|
| 7 |
+
const TASKS: Task[] = []
|
| 8 |
import { cn } from '@/lib/utils'
|
| 9 |
|
| 10 |
const STATUS_CONFIG = {
|
frontend/components/shared/Sidebar.tsx
CHANGED
|
@@ -1,142 +1,122 @@
|
|
| 1 |
'use client'
|
| 2 |
|
| 3 |
-
import {
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
} from 'lucide-react'
|
| 9 |
-
import { useAppStore
|
| 10 |
-
import {
|
| 11 |
|
| 12 |
-
const NAV_ITEMS: {
|
| 13 |
-
{
|
| 14 |
-
{
|
| 15 |
-
{
|
| 16 |
-
{
|
| 17 |
-
{
|
| 18 |
-
{
|
| 19 |
-
{
|
| 20 |
-
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
]
|
| 22 |
|
| 23 |
export default function Sidebar() {
|
| 24 |
-
const { currentPage, setCurrentPage,
|
|
|
|
|
|
|
| 25 |
|
| 26 |
return (
|
| 27 |
-
<
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
style={{ borderColor: '
|
| 32 |
-
|
| 33 |
-
|
| 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 |
-
|
| 41 |
-
<div className="
|
| 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="
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
{
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 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 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 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 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
</div>
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
|
|
|
|
|
|
| 138 |
</div>
|
| 139 |
</div>
|
| 140 |
-
</
|
| 141 |
)
|
| 142 |
}
|
|
|
|
| 1 |
'use client'
|
| 2 |
|
| 3 |
+
import {
|
| 4 |
+
LayoutDashboard, Box, Bot, ListTodo, Brain,
|
| 5 |
+
BookOpen, GitBranch, BarChart2, Settings,
|
| 6 |
+
Zap, Globe, Terminal, Code2, Eye, Bug,
|
| 7 |
+
Rocket, MessageSquare, Plug
|
| 8 |
} from 'lucide-react'
|
| 9 |
+
import { useAppStore } from '@/store/useAppStore'
|
| 10 |
+
import type { Page } from '@/store/useAppStore'
|
| 11 |
|
| 12 |
+
const NAV_ITEMS: { id: Page; label: string; icon: any; group?: string }[] = [
|
| 13 |
+
{ id: 'dashboard', label: 'Dashboard', icon: LayoutDashboard },
|
| 14 |
+
{ id: 'spaces', label: 'Spaces', icon: Box },
|
| 15 |
+
{ id: 'agents', label: 'Agents', icon: Bot },
|
| 16 |
+
{ id: 'connectors', label: 'Connectors', icon: Plug },
|
| 17 |
+
{ id: 'tasks', label: 'Tasks', icon: ListTodo },
|
| 18 |
+
{ id: 'memory', label: 'Memory', icon: Brain },
|
| 19 |
+
{ id: 'knowledge', label: 'Knowledge', icon: BookOpen },
|
| 20 |
+
{ id: 'workflows', label: 'Workflows', icon: GitBranch },
|
| 21 |
+
{ id: 'analytics', label: 'Analytics', icon: BarChart2 },
|
| 22 |
+
{ id: 'settings', label: 'Settings', icon: Settings },
|
| 23 |
+
]
|
| 24 |
+
|
| 25 |
+
const SPACES = [
|
| 26 |
+
{ id: 'core', label: 'Core', icon: '🧠', color: '#7c3aed' },
|
| 27 |
+
{ id: 'browser', label: 'Browser', icon: '🌐', color: '#2563eb' },
|
| 28 |
+
{ id: 'sandbox', label: 'Sandbox', icon: '💻', color: '#059669' },
|
| 29 |
+
{ id: 'coding', label: 'Coding', icon: '🔧', color: '#d97706' },
|
| 30 |
+
{ id: 'vision', label: 'Vision', icon: '👁️', color: '#db2777' },
|
| 31 |
+
{ id: 'debug', label: 'Debug', icon: '🐛', color: '#dc2626' },
|
| 32 |
+
{ id: 'deploy', label: 'Deploy', icon: '🚀', color: '#0891b2' },
|
| 33 |
+
{ id: 'communication', label: 'Comm', icon: '💬', color: '#7c3aed' },
|
| 34 |
]
|
| 35 |
|
| 36 |
export default function Sidebar() {
|
| 37 |
+
const { currentPage, setCurrentPage, sidebarOpen, spaces, activeSpace } = useAppStore()
|
| 38 |
+
|
| 39 |
+
if (!sidebarOpen) return null
|
| 40 |
|
| 41 |
return (
|
| 42 |
+
<aside className="w-52 flex-shrink-0 flex flex-col border-r h-full overflow-y-auto"
|
| 43 |
+
style={{ background: 'var(--bg-1, #07080f)', borderColor: 'var(--border, #1e2035)' }}>
|
| 44 |
+
|
| 45 |
+
{/* Brand */}
|
| 46 |
+
<div className="p-3 border-b" style={{ borderColor: '#1e2035' }}>
|
| 47 |
+
<div className="flex items-center gap-2">
|
| 48 |
+
<div className="w-8 h-8 rounded-xl bg-gradient-to-br from-violet-600 to-indigo-600 flex items-center justify-center shadow-lg shadow-violet-500/20">
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
<Zap size={16} className="text-white" />
|
| 50 |
</div>
|
| 51 |
+
<div>
|
| 52 |
+
<div className="text-xs font-bold text-white">GOD AGENT OS</div>
|
| 53 |
+
<div className="text-[9px] text-violet-400 font-medium">v9 · Space-Role</div>
|
| 54 |
+
</div>
|
| 55 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
</div>
|
| 57 |
|
| 58 |
{/* Navigation */}
|
| 59 |
+
<nav className="p-2 flex-1">
|
| 60 |
+
<div className="space-y-0.5">
|
| 61 |
+
{NAV_ITEMS.map(item => {
|
| 62 |
+
const Icon = item.icon
|
| 63 |
+
const active = currentPage === item.id
|
| 64 |
+
return (
|
| 65 |
+
<button
|
| 66 |
+
key={item.id}
|
| 67 |
+
onClick={() => setCurrentPage(item.id)}
|
| 68 |
+
className={`w-full flex items-center gap-2.5 px-2.5 py-1.5 rounded-lg text-xs font-medium transition-all ${
|
| 69 |
+
active
|
| 70 |
+
? 'bg-violet-500/15 text-violet-300 border border-violet-500/20'
|
| 71 |
+
: 'text-slate-500 hover:text-slate-300 hover:bg-white/4'
|
| 72 |
+
}`}
|
| 73 |
+
>
|
| 74 |
+
<Icon size={13} />
|
| 75 |
+
{item.label}
|
| 76 |
+
</button>
|
| 77 |
+
)
|
| 78 |
+
})}
|
| 79 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
|
| 81 |
+
{/* Spaces Section */}
|
| 82 |
+
<div className="mt-4">
|
| 83 |
+
<div className="px-2 mb-2 text-[9px] font-bold text-slate-600 uppercase tracking-widest">
|
| 84 |
+
Active Spaces
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
</div>
|
| 86 |
+
<div className="grid grid-cols-2 gap-1">
|
| 87 |
+
{SPACES.map(s => {
|
| 88 |
+
const isActive = spaces[s.id as keyof typeof spaces]?.active
|
| 89 |
+
const isSelected = activeSpace === s.id
|
| 90 |
+
return (
|
| 91 |
+
<div
|
| 92 |
+
key={s.id}
|
| 93 |
+
className="flex flex-col items-center p-1.5 rounded-lg text-center transition-all cursor-pointer"
|
| 94 |
+
style={{
|
| 95 |
+
background: isActive ? `${s.color}15` : 'rgba(255,255,255,0.03)',
|
| 96 |
+
border: `1px solid ${isActive ? s.color + '40' : 'transparent'}`,
|
| 97 |
+
}}
|
| 98 |
+
>
|
| 99 |
+
<span className="text-sm">{s.icon}</span>
|
| 100 |
+
<span className="text-[8px] mt-0.5" style={{ color: isActive ? s.color : '#475569' }}>
|
| 101 |
+
{s.label}
|
| 102 |
+
</span>
|
| 103 |
+
{isActive && (
|
| 104 |
+
<div className="w-1 h-1 rounded-full mt-0.5 animate-pulse"
|
| 105 |
+
style={{ background: s.color }} />
|
| 106 |
+
)}
|
| 107 |
+
</div>
|
| 108 |
+
)
|
| 109 |
+
})}
|
| 110 |
</div>
|
| 111 |
+
</div>
|
| 112 |
+
</nav>
|
| 113 |
+
|
| 114 |
+
{/* Footer */}
|
| 115 |
+
<div className="p-3 border-t" style={{ borderColor: '#1e2035' }}>
|
| 116 |
+
<div className="text-[9px] text-slate-600 text-center">
|
| 117 |
+
Powered by <span className="text-violet-500 font-semibold">Pyae Sone</span>
|
| 118 |
</div>
|
| 119 |
</div>
|
| 120 |
+
</aside>
|
| 121 |
)
|
| 122 |
}
|
frontend/components/shared/TopBar.tsx
CHANGED
|
@@ -1,181 +1,94 @@
|
|
| 1 |
'use client'
|
| 2 |
|
| 3 |
-
import { useState
|
| 4 |
-
import {
|
| 5 |
-
import { Search, Bell, Command, Sparkles, X, ArrowRight, Bot, CheckSquare, FileText, Zap } from 'lucide-react'
|
| 6 |
import { useAppStore } from '@/store/useAppStore'
|
| 7 |
|
| 8 |
-
const
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 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 {
|
| 23 |
-
|
| 24 |
-
const
|
| 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
|
| 50 |
-
style={{
|
| 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 |
-
{/*
|
| 70 |
-
<div className="flex items-center gap-
|
| 71 |
-
<button
|
| 72 |
-
|
|
|
|
| 73 |
</button>
|
| 74 |
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
<
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
<
|
| 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 |
-
{/*
|
| 124 |
-
<
|
| 125 |
-
{
|
| 126 |
-
<
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
<
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
>
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 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 |
-
</
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 179 |
</header>
|
| 180 |
)
|
| 181 |
}
|
|
|
|
| 1 |
'use client'
|
| 2 |
|
| 3 |
+
import { useState } from 'react'
|
| 4 |
+
import { Menu, Zap, Settings, Bell, Activity } from 'lucide-react'
|
|
|
|
| 5 |
import { useAppStore } from '@/store/useAppStore'
|
| 6 |
|
| 7 |
+
const SPACE_COLORS: Record<string, string> = {
|
| 8 |
+
core: '#7c3aed',
|
| 9 |
+
browser: '#2563eb',
|
| 10 |
+
sandbox: '#059669',
|
| 11 |
+
coding: '#d97706',
|
| 12 |
+
vision: '#db2777',
|
| 13 |
+
debug: '#dc2626',
|
| 14 |
+
deploy: '#0891b2',
|
| 15 |
+
communication: '#7c3aed',
|
| 16 |
+
}
|
|
|
|
|
|
|
| 17 |
|
| 18 |
export default function TopBar() {
|
| 19 |
+
const { sidebarOpen, setSidebarOpen, activeSpace, currentRole, spaces } = useAppStore()
|
| 20 |
+
|
| 21 |
+
const activeSpaces = Object.values(spaces).filter(s => s.active)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
|
| 23 |
return (
|
| 24 |
+
<header className="h-12 flex items-center justify-between px-3 border-b shrink-0"
|
| 25 |
+
style={{ background: 'var(--bg-2, #0a0b14)', borderColor: 'var(--border, #1e2035)' }}>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
|
| 27 |
+
{/* Left */}
|
| 28 |
+
<div className="flex items-center gap-3">
|
| 29 |
+
<button onClick={() => setSidebarOpen(!sidebarOpen)}
|
| 30 |
+
className="p-1.5 rounded-lg hover:bg-white/5 transition-colors">
|
| 31 |
+
<Menu size={16} className="text-slate-400" />
|
| 32 |
</button>
|
| 33 |
|
| 34 |
+
<div className="flex items-center gap-2">
|
| 35 |
+
<div className="w-7 h-7 rounded-lg bg-gradient-to-br from-violet-600 to-indigo-600 flex items-center justify-center shadow-lg">
|
| 36 |
+
<Zap size={14} className="text-white" />
|
| 37 |
+
</div>
|
| 38 |
+
<div className="hidden sm:block">
|
| 39 |
+
<span className="text-sm font-bold text-white">GOD AGENT OS</span>
|
| 40 |
+
<span className="text-[10px] ml-1.5 px-1.5 py-0.5 rounded-full text-violet-300 font-semibold"
|
| 41 |
+
style={{ background: 'rgba(139,92,246,0.15)', border: '1px solid rgba(139,92,246,0.3)' }}>
|
| 42 |
+
v9 Space-Role
|
| 43 |
+
</span>
|
| 44 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
</div>
|
| 46 |
</div>
|
| 47 |
|
| 48 |
+
{/* Center — Active Space indicator */}
|
| 49 |
+
<div className="hidden md:flex items-center gap-2">
|
| 50 |
+
{activeSpace ? (
|
| 51 |
+
<div className="flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-medium"
|
| 52 |
+
style={{
|
| 53 |
+
background: `${SPACE_COLORS[activeSpace]}20`,
|
| 54 |
+
border: `1px solid ${SPACE_COLORS[activeSpace]}40`,
|
| 55 |
+
color: SPACE_COLORS[activeSpace],
|
| 56 |
+
}}>
|
| 57 |
+
<div className="w-1.5 h-1.5 rounded-full animate-pulse"
|
| 58 |
+
style={{ background: SPACE_COLORS[activeSpace] }} />
|
| 59 |
+
{spaces[activeSpace]?.icon} {activeSpace.toUpperCase()} SPACE — {currentRole.replace('_', ' ').toUpperCase()}
|
| 60 |
+
</div>
|
| 61 |
+
) : (
|
| 62 |
+
<div className="flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-medium"
|
| 63 |
+
style={{ background: 'rgba(255,255,255,0.05)', border: '1px solid rgba(255,255,255,0.1)', color: '#64748b' }}>
|
| 64 |
+
<div className="w-1.5 h-1.5 rounded-full bg-slate-500" />
|
| 65 |
+
8 Spaces Ready
|
| 66 |
+
</div>
|
| 67 |
+
)}
|
| 68 |
+
|
| 69 |
+
{activeSpaces.length > 0 && (
|
| 70 |
+
<div className="flex gap-1">
|
| 71 |
+
{activeSpaces.slice(0, 3).map(s => (
|
| 72 |
+
<div key={s.name} className="w-2 h-2 rounded-full animate-pulse"
|
| 73 |
+
style={{ background: SPACE_COLORS[s.name] }} />
|
| 74 |
+
))}
|
| 75 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
)}
|
| 77 |
+
</div>
|
| 78 |
+
|
| 79 |
+
{/* Right */}
|
| 80 |
+
<div className="flex items-center gap-1">
|
| 81 |
+
<div className="flex items-center gap-1.5 px-2 py-1 rounded text-xs text-slate-500">
|
| 82 |
+
<Activity size={11} className="text-green-400" />
|
| 83 |
+
<span className="hidden sm:inline text-green-400 font-medium">Powered by Pyae Sone</span>
|
| 84 |
+
</div>
|
| 85 |
+
<button className="p-1.5 rounded-lg hover:bg-white/5 transition-colors">
|
| 86 |
+
<Bell size={15} className="text-slate-500" />
|
| 87 |
+
</button>
|
| 88 |
+
<button className="p-1.5 rounded-lg hover:bg-white/5 transition-colors">
|
| 89 |
+
<Settings size={15} className="text-slate-500" />
|
| 90 |
+
</button>
|
| 91 |
+
</div>
|
| 92 |
</header>
|
| 93 |
)
|
| 94 |
}
|
frontend/lib/api.ts
CHANGED
|
@@ -1,163 +1,56 @@
|
|
| 1 |
-
/
|
| 2 |
-
|
| 3 |
-
*/
|
| 4 |
|
| 5 |
-
const API_URL =
|
|
|
|
| 6 |
|
| 7 |
-
async function
|
| 8 |
-
const res = await fetch(`${
|
| 9 |
headers: { 'Content-Type': 'application/json' },
|
| 10 |
...options,
|
| 11 |
})
|
| 12 |
-
if (!res.ok) throw new Error(`API
|
| 13 |
return res.json()
|
| 14 |
}
|
| 15 |
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
githubRepo?: string
|
| 19 |
-
autoCommit?: boolean
|
| 20 |
-
metadata?: Record<string, any>
|
| 21 |
-
}) {
|
| 22 |
-
return apiFetch('/api/v1/tasks/', {
|
| 23 |
-
method: 'POST',
|
| 24 |
-
body: JSON.stringify({
|
| 25 |
-
goal,
|
| 26 |
-
session_id: sessionId,
|
| 27 |
-
github_repo: options?.githubRepo || '',
|
| 28 |
-
auto_commit: options?.autoCommit || false,
|
| 29 |
-
metadata: options?.metadata || {},
|
| 30 |
-
}),
|
| 31 |
-
})
|
| 32 |
-
}
|
| 33 |
-
|
| 34 |
-
export async function getTask(taskId: string) {
|
| 35 |
-
return apiFetch(`/api/v1/tasks/${taskId}`)
|
| 36 |
-
}
|
| 37 |
-
|
| 38 |
-
export async function getTasks(sessionId?: string, limit = 50) {
|
| 39 |
-
const q = sessionId ? `?session_id=${sessionId}&limit=${limit}` : `?limit=${limit}`
|
| 40 |
-
return apiFetch(`/api/v1/tasks/${q}`)
|
| 41 |
-
}
|
| 42 |
-
|
| 43 |
-
export async function cancelTask(taskId: string) {
|
| 44 |
-
return apiFetch(`/api/v1/tasks/${taskId}/cancel`, { method: 'POST' })
|
| 45 |
-
}
|
| 46 |
-
|
| 47 |
-
export async function retryTask(taskId: string) {
|
| 48 |
-
return apiFetch(`/api/v1/tasks/${taskId}/retry`, { method: 'POST' })
|
| 49 |
-
}
|
| 50 |
-
|
| 51 |
-
export async function getTaskEvents(taskId: string) {
|
| 52 |
-
return apiFetch(`/api/v1/tasks/${taskId}/events`)
|
| 53 |
-
}
|
| 54 |
-
|
| 55 |
-
// ─── Chat ─────────────────────────────────────────────────────────────────────
|
| 56 |
-
export async function streamChatSSE(
|
| 57 |
-
messages: Array<{ role: string; content: string }>,
|
| 58 |
-
sessionId: string,
|
| 59 |
-
onChunk: (chunk: string) => void,
|
| 60 |
-
onComplete: (full: string) => void,
|
| 61 |
-
onError: (err: string) => void,
|
| 62 |
-
) {
|
| 63 |
-
try {
|
| 64 |
-
const res = await fetch(`${API_URL}/api/v1/chat/stream`, {
|
| 65 |
-
method: 'POST',
|
| 66 |
-
headers: { 'Content-Type': 'application/json' },
|
| 67 |
-
body: JSON.stringify({ messages, session_id: sessionId }),
|
| 68 |
-
})
|
| 69 |
-
if (!res.ok) throw new Error(`${res.status}`)
|
| 70 |
-
if (!res.body) throw new Error('No body')
|
| 71 |
-
|
| 72 |
-
const reader = res.body.getReader()
|
| 73 |
-
const dec = new TextDecoder()
|
| 74 |
-
let full = ''
|
| 75 |
-
|
| 76 |
-
while (true) {
|
| 77 |
-
const { done, value } = await reader.read()
|
| 78 |
-
if (done) break
|
| 79 |
-
const text = dec.decode(value, { stream: true })
|
| 80 |
-
for (const line of text.split('\n')) {
|
| 81 |
-
if (!line.startsWith('data:')) continue
|
| 82 |
-
const data = line.slice(5).trim()
|
| 83 |
-
if (data === '[DONE]') { onComplete(full); return }
|
| 84 |
-
try {
|
| 85 |
-
const obj = JSON.parse(data)
|
| 86 |
-
const chunk = obj.chunk || obj.content || obj.delta || ''
|
| 87 |
-
if (chunk) { full += chunk; onChunk(chunk) }
|
| 88 |
-
} catch {}
|
| 89 |
-
}
|
| 90 |
-
}
|
| 91 |
-
onComplete(full)
|
| 92 |
-
} catch (e: any) {
|
| 93 |
-
onError(e.message)
|
| 94 |
-
}
|
| 95 |
}
|
| 96 |
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
return apiFetch('/api/v1/agents/orchestrate', {
|
| 100 |
-
method: 'POST',
|
| 101 |
-
body: JSON.stringify({ message, session_id: sessionId, context: context || {} }),
|
| 102 |
-
})
|
| 103 |
-
}
|
| 104 |
-
|
| 105 |
-
// ─── Memory ───────────────────────────────────────────────────────────────────
|
| 106 |
-
export async function getMemory(sessionId: string, limit = 20) {
|
| 107 |
-
return apiFetch(`/api/v1/memory/?session_id=${sessionId}&limit=${limit}`)
|
| 108 |
-
}
|
| 109 |
-
|
| 110 |
-
export async function searchMemory(query: string, sessionId?: string) {
|
| 111 |
-
const q = sessionId ? `?q=${encodeURIComponent(query)}&session_id=${sessionId}` : `?q=${encodeURIComponent(query)}`
|
| 112 |
-
return apiFetch(`/api/v1/memory/search${q}`)
|
| 113 |
-
}
|
| 114 |
-
|
| 115 |
-
// ─── Connectors ────────────────────────────────────────────────────────────��──
|
| 116 |
-
export async function getConnectors() {
|
| 117 |
-
return apiFetch('/api/v1/connectors/')
|
| 118 |
-
}
|
| 119 |
-
|
| 120 |
-
export async function getConnectorSummary() {
|
| 121 |
-
return apiFetch('/api/v1/connectors/summary')
|
| 122 |
}
|
| 123 |
|
| 124 |
-
export async function
|
| 125 |
-
return
|
| 126 |
method: 'POST',
|
| 127 |
-
body: JSON.stringify({
|
| 128 |
})
|
| 129 |
}
|
| 130 |
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
return apiFetch('/api/v1/agents/sandbox/execute', {
|
| 134 |
method: 'POST',
|
| 135 |
-
body: JSON.stringify({
|
| 136 |
})
|
| 137 |
}
|
| 138 |
|
| 139 |
-
export async function
|
| 140 |
-
return
|
| 141 |
-
method: 'POST',
|
| 142 |
-
body: JSON.stringify({ filename, content }),
|
| 143 |
-
})
|
| 144 |
}
|
| 145 |
|
| 146 |
-
export async function
|
| 147 |
-
return
|
| 148 |
}
|
| 149 |
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
return apiFetch('/api/v1/agents/ai-router/stats')
|
| 153 |
}
|
| 154 |
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
return apiFetch('/api/v1/github/status')
|
| 158 |
}
|
| 159 |
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
return apiFetch('/api/v1/health')
|
| 163 |
}
|
|
|
|
| 1 |
+
const API_BASE = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:7860'
|
| 2 |
+
const WS_BASE = process.env.NEXT_PUBLIC_WS_URL || 'ws://localhost:7860'
|
|
|
|
| 3 |
|
| 4 |
+
export const API_URL = API_BASE
|
| 5 |
+
export const WS_URL = WS_BASE
|
| 6 |
|
| 7 |
+
export async function fetchAPI(path: string, options?: RequestInit) {
|
| 8 |
+
const res = await fetch(`${API_BASE}${path}`, {
|
| 9 |
headers: { 'Content-Type': 'application/json' },
|
| 10 |
...options,
|
| 11 |
})
|
| 12 |
+
if (!res.ok) throw new Error(`API error: ${res.status}`)
|
| 13 |
return res.json()
|
| 14 |
}
|
| 15 |
|
| 16 |
+
export async function getKernelStatus() {
|
| 17 |
+
return fetchAPI('/api/v1/kernel/status')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
}
|
| 19 |
|
| 20 |
+
export async function getSpaces() {
|
| 21 |
+
return fetchAPI('/api/v1/spaces')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
}
|
| 23 |
|
| 24 |
+
export async function executeInSpace(spaceName: string, task: string, role: string, sessionId: string) {
|
| 25 |
+
return fetchAPI(`/api/v1/spaces/${spaceName}/execute`, {
|
| 26 |
method: 'POST',
|
| 27 |
+
body: JSON.stringify({ task, role, session_id: sessionId }),
|
| 28 |
})
|
| 29 |
}
|
| 30 |
|
| 31 |
+
export async function orchestrate(message: string, sessionId: string, context?: object) {
|
| 32 |
+
return fetchAPI('/api/v1/kernel/orchestrate', {
|
|
|
|
| 33 |
method: 'POST',
|
| 34 |
+
body: JSON.stringify({ message, session_id: sessionId, context }),
|
| 35 |
})
|
| 36 |
}
|
| 37 |
|
| 38 |
+
export async function getConnectors() {
|
| 39 |
+
return fetchAPI('/api/v1/connectors')
|
|
|
|
|
|
|
|
|
|
| 40 |
}
|
| 41 |
|
| 42 |
+
export async function getHealth() {
|
| 43 |
+
return fetchAPI('/api/v1/health')
|
| 44 |
}
|
| 45 |
|
| 46 |
+
export async function getTasks() {
|
| 47 |
+
return fetchAPI('/api/v1/tasks/')
|
|
|
|
| 48 |
}
|
| 49 |
|
| 50 |
+
export async function getMemory() {
|
| 51 |
+
return fetchAPI('/api/v1/memory/')
|
|
|
|
| 52 |
}
|
| 53 |
|
| 54 |
+
export function createWebSocket(path: string): WebSocket {
|
| 55 |
+
return new WebSocket(`${WS_BASE}${path}`)
|
|
|
|
| 56 |
}
|
frontend/next.config.js
CHANGED
|
@@ -1,16 +1,29 @@
|
|
| 1 |
/** @type {import('next').NextConfig} */
|
| 2 |
const nextConfig = {
|
| 3 |
-
reactStrictMode:
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
NEXT_PUBLIC_WS_URL: process.env.NEXT_PUBLIC_WS_URL || 'wss://pyae1994-autonomous-coding-system.hf.space',
|
| 7 |
-
NEXT_PUBLIC_VSCODE_URL: 'https://pyae1994-god-agent-vscode.hf.space',
|
| 8 |
-
},
|
| 9 |
async rewrites() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
return [
|
| 11 |
{
|
| 12 |
-
source: '/
|
| 13 |
-
|
|
|
|
|
|
|
| 14 |
},
|
| 15 |
]
|
| 16 |
},
|
|
|
|
| 1 |
/** @type {import('next').NextConfig} */
|
| 2 |
const nextConfig = {
|
| 3 |
+
reactStrictMode: false,
|
| 4 |
+
poweredByHeader: false,
|
| 5 |
+
|
|
|
|
|
|
|
|
|
|
| 6 |
async rewrites() {
|
| 7 |
+
const backendUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:7860'
|
| 8 |
+
return [
|
| 9 |
+
{
|
| 10 |
+
source: '/api/v1/:path*',
|
| 11 |
+
destination: `${backendUrl}/api/v1/:path*`,
|
| 12 |
+
},
|
| 13 |
+
{
|
| 14 |
+
source: '/ws/:path*',
|
| 15 |
+
destination: `${backendUrl}/ws/:path*`,
|
| 16 |
+
},
|
| 17 |
+
]
|
| 18 |
+
},
|
| 19 |
+
|
| 20 |
+
async headers() {
|
| 21 |
return [
|
| 22 |
{
|
| 23 |
+
source: '/(.*)',
|
| 24 |
+
headers: [
|
| 25 |
+
{ key: 'X-Powered-By', value: 'Pyae Sone - GOD AGENT OS v9' },
|
| 26 |
+
],
|
| 27 |
},
|
| 28 |
]
|
| 29 |
},
|
frontend/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
| 1 |
{
|
| 2 |
-
"name": "god-
|
| 3 |
-
"version": "
|
| 4 |
"lockfileVersion": 3,
|
| 5 |
"requires": true,
|
| 6 |
"packages": {
|
| 7 |
"": {
|
| 8 |
-
"name": "god-
|
| 9 |
-
"version": "
|
| 10 |
"dependencies": {
|
| 11 |
"@radix-ui/react-dialog": "^1.1.15",
|
| 12 |
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
|
|
| 1 |
{
|
| 2 |
+
"name": "god-agent-os-ui",
|
| 3 |
+
"version": "8.0.0",
|
| 4 |
"lockfileVersion": 3,
|
| 5 |
"requires": true,
|
| 6 |
"packages": {
|
| 7 |
"": {
|
| 8 |
+
"name": "god-agent-os-ui",
|
| 9 |
+
"version": "8.0.0",
|
| 10 |
"dependencies": {
|
| 11 |
"@radix-ui/react-dialog": "^1.1.15",
|
| 12 |
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
frontend/store/useAppStore.ts
CHANGED
|
@@ -1,131 +1,84 @@
|
|
| 1 |
import { create } from 'zustand'
|
| 2 |
-
import { persist } from 'zustand/middleware'
|
| 3 |
|
| 4 |
-
export type
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
|
| 6 |
-
export
|
| 7 |
-
|
| 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
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
type: 'success' | 'processing' | 'info' | 'warning'
|
| 36 |
color: string
|
|
|
|
| 37 |
}
|
| 38 |
|
| 39 |
interface AppState {
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 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 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
|
|
|
|
|
|
|
|
|
| 69 |
}
|
| 70 |
|
| 71 |
-
export const
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 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 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 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 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 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 |
-
)
|
|
|
|
| 1 |
import { create } from 'zustand'
|
|
|
|
| 2 |
|
| 3 |
+
export type Page =
|
| 4 |
+
| 'dashboard'
|
| 5 |
+
| 'spaces'
|
| 6 |
+
| 'agents'
|
| 7 |
+
| 'tasks'
|
| 8 |
+
| 'memory'
|
| 9 |
+
| 'knowledge'
|
| 10 |
+
| 'workflows'
|
| 11 |
+
| 'analytics'
|
| 12 |
+
| 'settings'
|
| 13 |
+
| 'connectors'
|
| 14 |
|
| 15 |
+
export type Space = 'core' | 'browser' | 'sandbox' | 'coding' | 'vision' | 'debug' | 'deploy' | 'communication'
|
| 16 |
+
export type Role = 'cognition' | 'automation' | 'execution' | 'repair' | 'visual_intelligence'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
|
| 18 |
+
export interface SpaceStatus {
|
| 19 |
+
name: Space
|
| 20 |
+
active: boolean
|
| 21 |
+
taskCount: number
|
| 22 |
+
lastActive: number | null
|
|
|
|
| 23 |
color: string
|
| 24 |
+
icon: string
|
| 25 |
}
|
| 26 |
|
| 27 |
interface AppState {
|
| 28 |
+
currentPage: Page
|
| 29 |
+
activeSpace: Space | null
|
| 30 |
+
currentRole: Role
|
| 31 |
+
sidebarOpen: boolean
|
| 32 |
+
spaces: Record<Space, SpaceStatus>
|
| 33 |
+
setCurrentPage: (page: Page) => void
|
| 34 |
+
setActiveSpace: (space: Space | null) => void
|
| 35 |
+
setCurrentRole: (role: Role) => void
|
| 36 |
+
setSidebarOpen: (open: boolean) => void
|
| 37 |
+
activateSpace: (space: Space, role?: Role) => void
|
| 38 |
+
deactivateSpace: (space: Space) => void
|
| 39 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
|
| 41 |
+
const initialSpaces: Record<Space, SpaceStatus> = {
|
| 42 |
+
core: { name: 'core', active: false, taskCount: 0, lastActive: null, color: '#7c3aed', icon: '🧠' },
|
| 43 |
+
browser: { name: 'browser', active: false, taskCount: 0, lastActive: null, color: '#2563eb', icon: '🌐' },
|
| 44 |
+
sandbox: { name: 'sandbox', active: false, taskCount: 0, lastActive: null, color: '#059669', icon: '💻' },
|
| 45 |
+
coding: { name: 'coding', active: false, taskCount: 0, lastActive: null, color: '#d97706', icon: '🔧' },
|
| 46 |
+
vision: { name: 'vision', active: false, taskCount: 0, lastActive: null, color: '#db2777', icon: '👁️' },
|
| 47 |
+
debug: { name: 'debug', active: false, taskCount: 0, lastActive: null, color: '#dc2626', icon: '🐛' },
|
| 48 |
+
deploy: { name: 'deploy', active: false, taskCount: 0, lastActive: null, color: '#0891b2', icon: '🚀' },
|
| 49 |
+
communication: { name: 'communication', active: false, taskCount: 0, lastActive: null, color: '#7c3aed', icon: '💬' },
|
| 50 |
}
|
| 51 |
|
| 52 |
+
export const useAppStore = create<AppState>((set) => ({
|
| 53 |
+
currentPage: 'dashboard',
|
| 54 |
+
activeSpace: null,
|
| 55 |
+
currentRole: 'cognition',
|
| 56 |
+
sidebarOpen: true,
|
| 57 |
+
spaces: initialSpaces,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
|
| 59 |
+
setCurrentPage: (page) => set({ currentPage: page }),
|
| 60 |
+
setActiveSpace: (space) => set({ activeSpace: space }),
|
| 61 |
+
setCurrentRole: (role) => set({ currentRole: role }),
|
| 62 |
+
setSidebarOpen: (open) => set({ sidebarOpen: open }),
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
|
| 64 |
+
activateSpace: (space, role = 'cognition') => set((state) => ({
|
| 65 |
+
activeSpace: space,
|
| 66 |
+
currentRole: role,
|
| 67 |
+
spaces: {
|
| 68 |
+
...state.spaces,
|
| 69 |
+
[space]: {
|
| 70 |
+
...state.spaces[space],
|
| 71 |
+
active: true,
|
| 72 |
+
lastActive: Date.now(),
|
| 73 |
+
taskCount: state.spaces[space].taskCount + 1,
|
| 74 |
+
}
|
| 75 |
+
}
|
| 76 |
+
})),
|
| 77 |
|
| 78 |
+
deactivateSpace: (space) => set((state) => ({
|
| 79 |
+
spaces: {
|
| 80 |
+
...state.spaces,
|
| 81 |
+
[space]: { ...state.spaces[space], active: false }
|
| 82 |
+
}
|
| 83 |
+
})),
|
| 84 |
+
}))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
frontend/vercel.json
CHANGED
|
@@ -1,20 +1,23 @@
|
|
| 1 |
{
|
| 2 |
"buildCommand": "npm run build",
|
| 3 |
"outputDirectory": ".next",
|
| 4 |
-
"installCommand": "npm install",
|
| 5 |
"framework": "nextjs",
|
| 6 |
-
"
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
"headers": [
|
| 12 |
{
|
| 13 |
"source": "/(.*)",
|
| 14 |
"headers": [
|
| 15 |
-
{ "key": "X-
|
| 16 |
-
{ "key": "X-Frame-Options", "value": "SAMEORIGIN" }
|
| 17 |
-
{ "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" }
|
| 18 |
]
|
| 19 |
}
|
| 20 |
]
|
|
|
|
| 1 |
{
|
| 2 |
"buildCommand": "npm run build",
|
| 3 |
"outputDirectory": ".next",
|
|
|
|
| 4 |
"framework": "nextjs",
|
| 5 |
+
"rewrites": [
|
| 6 |
+
{
|
| 7 |
+
"source": "/api/v1/:path*",
|
| 8 |
+
"destination": "https://pyae1994-autonomous-coding-system.hf.space/api/v1/:path*"
|
| 9 |
+
},
|
| 10 |
+
{
|
| 11 |
+
"source": "/ws/:path*",
|
| 12 |
+
"destination": "https://pyae1994-autonomous-coding-system.hf.space/ws/:path*"
|
| 13 |
+
}
|
| 14 |
+
],
|
| 15 |
"headers": [
|
| 16 |
{
|
| 17 |
"source": "/(.*)",
|
| 18 |
"headers": [
|
| 19 |
+
{ "key": "X-Powered-By", "value": "Pyae Sone" },
|
| 20 |
+
{ "key": "X-Frame-Options", "value": "SAMEORIGIN" }
|
|
|
|
| 21 |
]
|
| 22 |
}
|
| 23 |
]
|