This view is limited to 50 files because it contains too many changes. See the raw diff here.
.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
.github/workflows/deploy.yml DELETED
@@ -1,119 +0,0 @@
1
- name: 🚀 Deploy GOD AGENT OS v11
2
-
3
- on:
4
- push:
5
- branches: [ master, main, genspark_ai_developer ]
6
- workflow_dispatch:
7
-
8
- env:
9
- HF_SPACE: PYAE1994/autonomous-coding-system
10
- HF_USER: PYAE1994
11
-
12
- jobs:
13
-
14
- # ── 1. Deploy Backend to HuggingFace Space ──────────────────────────────────
15
- deploy-hf-backend:
16
- name: 🤗 Deploy Backend to HF Space
17
- runs-on: ubuntu-latest
18
- steps:
19
- - uses: actions/checkout@v4
20
- with:
21
- fetch-depth: 0
22
-
23
- - name: 🐍 Setup Python
24
- uses: actions/setup-python@v5
25
- with:
26
- python-version: '3.11'
27
-
28
- - name: 📦 Install HF Hub
29
- run: pip install huggingface_hub
30
-
31
- - name: 🔐 Push HF Space Secrets
32
- env:
33
- HF_TOKEN: ${{ secrets.HF_TOKEN }}
34
- GEMINI_KEY: ${{ secrets.GEMINI_KEY }}
35
- SAMBANOVA_KEY: ${{ secrets.SAMBANOVA_KEY }}
36
- GITHUB_KEY: ${{ secrets.GITHUB_KEY }}
37
- run: |
38
- python3 - <<'EOF'
39
- import os
40
- try:
41
- from huggingface_hub import HfApi
42
- token = os.environ.get("HF_TOKEN", "")
43
- if not token:
44
- print("No HF_TOKEN — skipping secret push")
45
- exit(0)
46
- api = HfApi(token=token)
47
- repo_id = "PYAE1994/autonomous-coding-system"
48
- secrets = {
49
- "GEMINI_KEY": os.environ.get("GEMINI_KEY", ""),
50
- "SAMBANOVA_KEY": os.environ.get("SAMBANOVA_KEY", ""),
51
- "GITHUB_KEY": os.environ.get("GITHUB_KEY", ""),
52
- "DB_PATH": "/data/god_agent_v11.db",
53
- "WORKSPACE_DIR": "/tmp/god_workspace",
54
- }
55
- for k, v in secrets.items():
56
- if v:
57
- try:
58
- api.add_space_secret(repo_id=repo_id, key=k, value=v)
59
- print(f"✓ Set secret: {k}")
60
- except Exception as e:
61
- print(f"⚠ Secret {k}: {e}")
62
- except Exception as e:
63
- print(f"HF secrets error: {e}")
64
- EOF
65
-
66
- - name: 🚀 Push Backend to HF Space
67
- env:
68
- HF_TOKEN: ${{ secrets.HF_TOKEN }}
69
- run: |
70
- git config --global user.email "ci@godagentos.ai"
71
- git config --global user.name "God Agent OS CI"
72
-
73
- # Clone HF space
74
- git clone https://${{ env.HF_USER }}:${HF_TOKEN}@huggingface.co/spaces/${{ env.HF_SPACE }} /tmp/hf-space || true
75
-
76
- # Copy backend files
77
- rsync -av --exclude='.git' --exclude='__pycache__' --exclude='*.pyc' \
78
- backend/ /tmp/hf-space/ 2>/dev/null || cp -rf backend/. /tmp/hf-space/ || true
79
-
80
- cd /tmp/hf-space
81
- git add -A
82
- git diff --staged --quiet || git commit -m "🚀 Deploy God Agent OS v11 - $(date '+%Y-%m-%d %H:%M')"
83
- git push https://${{ env.HF_USER }}:${HF_TOKEN}@huggingface.co/spaces/${{ env.HF_SPACE }} HEAD:main || true
84
- echo "✅ HF Space deployment triggered"
85
-
86
- # ── 2. Deploy Frontend to Vercel ────────────────────────────────────────────
87
- deploy-vercel-frontend:
88
- name: ▲ Deploy Frontend to Vercel
89
- runs-on: ubuntu-latest
90
- steps:
91
- - uses: actions/checkout@v4
92
-
93
- - name: 🔧 Setup Node.js 20
94
- uses: actions/setup-node@v4
95
- with:
96
- node-version: '20'
97
-
98
- - name: 📦 Install Dependencies
99
- run: |
100
- cd frontend
101
- npm ci --legacy-peer-deps
102
-
103
- - name: 🏗️ Build Frontend
104
- env:
105
- NEXT_PUBLIC_API_URL: https://pyae1994-autonomous-coding-system.hf.space
106
- NEXT_PUBLIC_WS_URL: wss://pyae1994-autonomous-coding-system.hf.space
107
- run: |
108
- cd frontend
109
- npm run build
110
-
111
- - name: 🚀 Deploy to Vercel
112
- uses: amondnet/vercel-action@v25
113
- with:
114
- vercel-token: ${{ secrets.VERCEL_TOKEN }}
115
- vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
116
- vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
117
- working-directory: ./frontend
118
- vercel-args: '--prod'
119
- github-comment: false
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
.gitignore DELETED
@@ -1,51 +0,0 @@
1
- # Dependencies
2
- node_modules/
3
- frontend/node_modules/
4
- __pycache__/
5
- *.pyc
6
- *.pyo
7
- *.pyd
8
- .Python
9
-
10
- # Build outputs
11
- frontend/.next/
12
- frontend/out/
13
- dist/
14
- build/
15
- *.egg-info/
16
-
17
- # Environment
18
- .env
19
- .env.local
20
- .env.production
21
- *.env
22
-
23
- # Logs
24
- *.log
25
- logs/
26
-
27
- # Database
28
- *.db
29
- *.sqlite
30
-
31
- # OS
32
- .DS_Store
33
- Thumbs.db
34
-
35
- # IDE
36
- .vscode/
37
- .idea/
38
- *.swp
39
-
40
- # Temporary
41
- tmp/
42
- temp/
43
- /tmp/
44
-
45
- # Python cache
46
- backend/__pycache__/
47
- backend/**/__pycache__/
48
- backend/ai_router/__pycache__/
49
- .env.keys
50
- backend/.env.keys
51
- .vercel
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ARCHITECTURE.md DELETED
@@ -1,2 +0,0 @@
1
- # God Agent OS v9 — Space-Role Architecture
2
- Powered by Pyae Sone
 
 
 
CHANGELOG_V3.md DELETED
@@ -1,239 +0,0 @@
1
- # 🚀 GOD MODE+ v3.0 - Changelog
2
-
3
- ## Release Date: May 14, 2026
4
-
5
- ### 🎯 Major Features
6
-
7
- #### 1. Advanced AI Router with Reasoning Models ⚡
8
- - **New Reasoning Models Added:**
9
- - DeepSeek R1 - Advanced multi-step reasoning (128K context)
10
- - Qwen QwQ - Lightweight reasoning model (32K context)
11
- - OpenAI o1-mini - OpenAI's reasoning model (128K context)
12
- - Claude 3.5 Sonnet - Enhanced Claude reasoning (200K context)
13
-
14
- - **Smart Task-Based Routing:**
15
- - Automatic task type detection (reasoning, coding, chat, analysis, creative, lightweight)
16
- - Intelligent model selection based on task requirements
17
- - Optimization modes: quality, speed, cost
18
-
19
- - **Enhanced Failover Chain:**
20
- ```
21
- Reasoning Tasks: DeepSeek R1 → Qwen QwQ → o1-mini → GPT-4o → Claude 3.5
22
- Coding Tasks: GPT-4o → Claude 3.5 → DeepSeek R1 → Llama 3.3 → Mixtral
23
- Chat Tasks: Llama 3.3 (FREE) → GPT-4o → Claude 3.5 → Mixtral
24
- ```
25
-
26
- #### 2. New Agents (13 Total, +3 from v2)
27
- - **ReasoningAgent** 🧠 - Multi-step reasoning and problem decomposition
28
- - **OptimizationAgent** 📊 - Cost and latency optimization
29
- - **AnalyticsAgent** 📈 - Model performance tracking and analytics
30
-
31
- #### 3. Enhanced Backend Architecture
32
- - **New Dependencies:**
33
- - LangChain & LangGraph for advanced orchestration
34
- - Pinecone/Weaviate for vector embeddings
35
- - OpenTelemetry for distributed tracing
36
- - Prometheus for metrics collection
37
-
38
- - **Improved Memory System:**
39
- - Vector database integration for semantic search
40
- - Conversation summarization for long-term memory
41
- - Efficient context retrieval
42
-
43
- - **Better Error Handling:**
44
- - Circuit breaker pattern for API failures
45
- - Exponential backoff with jitter
46
- - Comprehensive error categorization
47
-
48
- #### 4. Frontend Modernization
49
- - **Upgraded to Next.js 15 & React 19**
50
- - Better performance with React 19 features
51
- - Improved server components
52
- - Enhanced streaming capabilities
53
-
54
- - **New UI Components:**
55
- - Model Performance Dashboard with real-time metrics
56
- - Cost tracking visualization
57
- - Agent performance analytics
58
- - Prompt engineering UI builder
59
-
60
- - **Enhanced Burmese Support:**
61
- - More comprehensive translations
62
- - Better Burmese markdown rendering
63
- - Improved keyboard shortcuts
64
-
65
- - **New Themes:**
66
- - Cyberpunk theme (neon colors)
67
- - Minimal theme (distraction-free)
68
- - Improved theme persistence
69
-
70
- #### 5. New Connectors & Integrations
71
- - **LangChain Integration** - Advanced prompt management
72
- - **LangGraph Integration** - Workflow orchestration
73
- - **Together AI** - Access to open-source models
74
- - **Replicate** - Image generation and processing
75
- - **Enhanced GitHub** - PR review automation
76
- - **Enhanced Vercel** - Analytics integration
77
-
78
- #### 6. Performance & Observability
79
- - **OpenTelemetry Integration:**
80
- - Distributed tracing across all services
81
- - Custom metrics for agent performance
82
- - Real-time system health dashboard
83
-
84
- - **Caching Strategy:**
85
- - Redis caching for frequently used models
86
- - Semantic caching for similar prompts
87
- - Response caching for cost optimization
88
-
89
- - **Monitoring:**
90
- - Real-time performance metrics
91
- - Cost tracking per request
92
- - Model success rate monitoring
93
- - Latency analytics
94
-
95
- #### 7. Security Enhancements
96
- - **RBAC (Role-Based Access Control)**
97
- - **API Key Rotation**
98
- - **Audit Logging** for all operations
99
- - **Data Encryption** at rest
100
- - **GDPR Compliance** features
101
-
102
- ### 📊 Performance Improvements
103
-
104
- | Metric | v2 | v3 | Improvement |
105
- |--------|-----|-----|-------------|
106
- | Response Time (p95) | 2-5s | <1s | 5-10x faster |
107
- | Model Options | 5 | 8+ | 60% more |
108
- | Agent Capabilities | 10 | 13 | 30% more |
109
- | Cost Optimization | Basic | Advanced | Smart routing |
110
- | Observability | Basic | Full | OpenTelemetry |
111
- | Security Score | 85/100 | 95+/100 | 10+ points |
112
-
113
- ### 🔧 Technical Changes
114
-
115
- #### Backend (Python/FastAPI)
116
- ```python
117
- # New AI Router v3
118
- from ai_router.router_v3 import AIRouterV3, TaskType
119
-
120
- router = AIRouterV3()
121
- task_type = router.detect_task_type("Explain quantum computing")
122
- model = router.select_model(task_type, optimize_for="quality")
123
- result = await router.route(message, context)
124
- ```
125
-
126
- #### Frontend (React/Next.js)
127
- ```tsx
128
- // New Model Performance Dashboard
129
- import ModelPerformanceDashboard from '@/components/dashboard/ModelPerformance';
130
-
131
- export default function Dashboard() {
132
- return <ModelPerformanceDashboard />;
133
- }
134
- ```
135
-
136
- ### 📦 Dependency Updates
137
-
138
- **Backend:**
139
- - fastapi: 0.111.0 → 0.115.0
140
- - pydantic: 2.7.1 → 2.8.0
141
- - openai: 1.30.1 → 1.35.0
142
- - anthropic: 0.26.1 → 0.30.0
143
- - langchain: NEW (0.2.0)
144
- - langgraph: NEW (0.1.0)
145
- - opentelemetry: NEW (1.25.0)
146
-
147
- **Frontend:**
148
- - next: 14.2.3 → 15.0.0
149
- - react: 18.3.1 → 19.0.0
150
- - tailwindcss: 3.4.1 → 4.0.0
151
- - framer-motion: 11.1.9 → 12.0.0
152
- - recharts: NEW (2.12.0)
153
-
154
- ### 🐛 Bug Fixes
155
- - Fixed WebSocket connection timeout issues
156
- - Improved error recovery in agent orchestration
157
- - Fixed memory leaks in long-running tasks
158
- - Better handling of concurrent requests
159
-
160
- ### ⚠️ Breaking Changes
161
- - API v1 routes remain compatible
162
- - Model selection now automatic (can be overridden)
163
- - Some environment variables renamed for clarity
164
-
165
- ### 🔄 Migration Guide
166
-
167
- **For Users:**
168
- 1. No action required - automatic upgrade
169
- 2. New reasoning models available via chat
170
- 3. Cost tracking visible in dashboard
171
- 4. Performance improvements automatic
172
-
173
- **For Developers:**
174
- 1. Update dependencies: `pip install -r requirements_v3.txt`
175
- 2. Use new AIRouterV3 for advanced routing
176
- 3. Register new agents in orchestrator
177
- 4. Update environment variables (see docs)
178
-
179
- ### 📚 Documentation
180
- - [AI Router v3 Guide](./docs/ai-router-v3.md)
181
- - [New Agents Documentation](./docs/agents-v3.md)
182
- - [Performance Dashboard Guide](./docs/dashboard.md)
183
- - [Migration Guide](./docs/migration-v3.md)
184
-
185
- ### 🎯 Next Steps (v4 Roadmap)
186
- - Multi-modal reasoning (vision + text)
187
- - Fine-tuning support for custom models
188
- - Advanced workflow automation
189
- - Mobile app support
190
- - Enterprise features (SSO, advanced RBAC)
191
-
192
- ### 🙏 Credits
193
- - Built with ❤️ by the GOD MODE+ team
194
- - Powered by OpenAI, Anthropic, DeepSeek, Qwen, and community models
195
- - Special thanks to Vercel, HuggingFace, and Groq
196
-
197
- ---
198
-
199
- ## Installation & Deployment
200
-
201
- ### Local Development
202
- ```bash
203
- # Backend
204
- cd backend
205
- pip install -r requirements_v3.txt
206
- export GROQ_API_KEY="your-key"
207
- uvicorn main:app --reload
208
-
209
- # Frontend
210
- cd frontend
211
- npm install
212
- npm run dev
213
- ```
214
-
215
- ### Production Deployment (Vercel)
216
- ```bash
217
- # Push to GitHub
218
- git add .
219
- git commit -m "🚀 GOD MODE+ v3.0 upgrade"
220
- git push origin main
221
-
222
- # Vercel auto-deploys
223
- # Check: https://vercel.com/devin-agent-v2-ui
224
- ```
225
-
226
- ### Docker
227
- ```bash
228
- # Build
229
- docker build -t god-mode-v3 .
230
-
231
- # Run
232
- docker run -p 8000:8000 -p 3000:3000 god-mode-v3
233
- ```
234
-
235
- ---
236
-
237
- **Version:** 3.0.0
238
- **Status:** 🟢 Production Ready
239
- **Last Updated:** May 14, 2026
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Dockerfile DELETED
@@ -1,28 +0,0 @@
1
- # God Agent OS — Phase 1 backend (FastAPI + E2B + SSE)
2
- FROM python:3.11-slim
3
-
4
- WORKDIR /app
5
-
6
- # System deps (curl for healthcheck, git for any sandbox-side workflows)
7
- RUN apt-get update && apt-get install -y --no-install-recommends \
8
- curl ca-certificates git \
9
- && rm -rf /var/lib/apt/lists/*
10
-
11
- # Python deps
12
- COPY requirements.txt /app/requirements.txt
13
- RUN pip install --no-cache-dir --upgrade pip \
14
- && pip install --no-cache-dir -r /app/requirements.txt
15
-
16
- # App code
17
- COPY . /app
18
-
19
- ENV PORT=7860 \
20
- PYTHONUNBUFFERED=1 \
21
- PYTHONPATH=/app
22
-
23
- EXPOSE 7860
24
-
25
- HEALTHCHECK --interval=30s --timeout=10s --start-period=20s --retries=3 \
26
- CMD curl -fsS http://localhost:7860/health || exit 1
27
-
28
- CMD ["python", "-m", "uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860", "--workers", "1", "--log-level", "info", "--no-access-log"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Dockerfile.hf DELETED
@@ -1,25 +0,0 @@
1
- # God Agent OS — Phase 1 backend for HuggingFace Spaces
2
- FROM python:3.11-slim
3
-
4
- WORKDIR /app
5
-
6
- RUN apt-get update && apt-get install -y --no-install-recommends \
7
- curl ca-certificates git \
8
- && rm -rf /var/lib/apt/lists/*
9
-
10
- COPY requirements.txt /app/requirements.txt
11
- RUN pip install --no-cache-dir --upgrade pip \
12
- && pip install --no-cache-dir -r /app/requirements.txt
13
-
14
- COPY . /app
15
-
16
- ENV PORT=7860 \
17
- PYTHONUNBUFFERED=1 \
18
- PYTHONPATH=/app
19
-
20
- EXPOSE 7860
21
-
22
- HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
23
- CMD curl -fsS http://localhost:7860/health || exit 1
24
-
25
- CMD ["python", "-m", "uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860", "--workers", "1", "--log-level", "info"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
README.md CHANGED
@@ -1,4 +1,3 @@
1
- ---
2
  title: Autonomous Coding System
3
  emoji: 🤖
4
  colorFrom: purple
@@ -41,3 +40,5 @@ Set these in HF Space secrets:
41
  - `GITHUB_TOKEN` — GitHub token for Git operations
42
  - `HF_TOKEN` — HuggingFace token
43
  - `VERCEL_TOKEN` — Vercel deploy token
 
 
 
 
1
  title: Autonomous Coding System
2
  emoji: 🤖
3
  colorFrom: purple
 
40
  - `GITHUB_TOKEN` — GitHub token for Git operations
41
  - `HF_TOKEN` — HuggingFace token
42
  - `VERCEL_TOKEN` — Vercel deploy token
43
+
44
+ Migrated from GitHub `sc8jd98v5k-lgtm/Autonomous-coding-system`.
V3_UPGRADE_PLAN.md DELETED
@@ -1,264 +0,0 @@
1
- # 🚀 GOD MODE+ v3 Upgrade Plan
2
-
3
- ## Current Status
4
- - **Version**: v2.0 (Latest deployment on Vercel)
5
- - **Agents**: 10 specialized agents (Chat, Planner, Coding, Debug, Memory, Connector, Deploy, Workflow, Sandbox, UI)
6
- - **AI Providers**: 5 (OpenAI, Groq, Cerebras, OpenRouter, Anthropic)
7
- - **Connectors**: 13 (GitHub, HuggingFace, Vercel, n8n, Telegram, Discord, Slack, Cloudflare, etc.)
8
- - **UI**: Manus-style layout + 5 themes + Burmese language support
9
-
10
- ---
11
-
12
- ## V3 Upgrade Roadmap
13
-
14
- ### Phase 1: Advanced AI Router Enhancement ⚡
15
- **Goal**: Add reasoning models and improve model selection strategy
16
-
17
- #### 1.1 Add Reasoning Models
18
- - **DeepSeek R1** - Advanced reasoning capabilities
19
- - **Qwen QwQ** - Lightweight reasoning model
20
- - **OpenAI o1-mini** - OpenAI's reasoning model
21
- - **Claude 3.5 Sonnet** - Enhanced reasoning from Anthropic
22
-
23
- #### 1.2 Implement Smart Model Router
24
- ```python
25
- # New routing logic:
26
- 1. Detect task type (reasoning, coding, chat, etc.)
27
- 2. Select optimal model based on:
28
- - Task complexity
29
- - Required latency
30
- - Cost optimization
31
- - Context length requirements
32
- 3. Fallback chain with reasoning models first for complex tasks
33
- ```
34
-
35
- #### 1.3 Update AI Router Priority Chain
36
- ```
37
- For Reasoning Tasks:
38
- DeepSeek R1 → OpenAI o1-mini → Claude 3.5 → Groq Llama
39
-
40
- For Coding Tasks:
41
- OpenAI GPT-4o → Claude 3.5 → Groq Llama 3.3 70B
42
-
43
- For Chat Tasks:
44
- Groq (FREE) → OpenAI → Claude 3.5 → Cerebras
45
-
46
- For Lightweight Tasks:
47
- Groq → OpenRouter (Free) → Cerebras
48
- ```
49
-
50
- ---
51
-
52
- ### Phase 2: Backend Enhancements 🔧
53
-
54
- #### 2.1 Update Dependencies
55
- ```
56
- # Key updates:
57
- - fastapi: 0.111.0 → 0.115.0+
58
- - pydantic: 2.7.1 → 2.8.0+
59
- - openai: 1.30.1 → 1.35.0+ (for o1 support)
60
- - anthropic: 0.26.1 → 0.30.0+ (for Claude 3.5)
61
- - langchain or similar: Add for better prompt engineering
62
- ```
63
-
64
- #### 2.2 New Agent Capabilities
65
- - **ReasoningAgent**: Dedicated agent for complex reasoning tasks
66
- - **OptimizationAgent**: Cost and latency optimization
67
- - **AnalyticsAgent**: Track model performance and costs
68
- - **KnowledgeAgent**: Long-context document processing
69
-
70
- #### 2.3 Enhanced Memory System
71
- - Add vector database support (Pinecone, Weaviate, or local embeddings)
72
- - Implement semantic search for better context retrieval
73
- - Add conversation summarization for long-term memory
74
-
75
- #### 2.4 Improved Error Handling & Self-Healing
76
- - Implement exponential backoff with jitter
77
- - Add circuit breaker pattern for API failures
78
- - Better error categorization and recovery strategies
79
-
80
- ---
81
-
82
- ### Phase 3: Frontend Modernization 🎨
83
-
84
- #### 3.1 Upgrade Dependencies
85
- ```json
86
- {
87
- "next": "14.2.3 → 15.0.0+",
88
- "react": "18.3.1 → 19.0.0+",
89
- "tailwindcss": "3.4.1 → 4.0.0+",
90
- "framer-motion": "11.1.9 → 12.0.0+"
91
- }
92
- ```
93
-
94
- #### 3.2 New UI Features
95
- - **Model Selection Dashboard**: Visual model performance metrics
96
- - **Real-time Cost Tracking**: Show API costs per request
97
- - **Advanced Analytics**: Agent performance, success rates, latency
98
- - **Prompt Engineering UI**: Visual prompt builder with templates
99
- - **Reasoning Visualization**: Show reasoning steps for complex tasks
100
-
101
- #### 3.3 Enhanced Burmese Support
102
- - Add more Burmese translations for new features
103
- - Improve Burmese markdown rendering
104
- - Add Burmese keyboard shortcuts
105
-
106
- #### 3.4 New Themes
107
- - Add "Cyberpunk" theme (requested by users)
108
- - Add "Minimal" theme for distraction-free mode
109
- - Improve theme switching with local persistence
110
-
111
- ---
112
-
113
- ### Phase 4: Connector System Expansion 🔌
114
-
115
- #### 4.1 New Connectors
116
- - **LangChain Integration**: Better prompt management
117
- - **LangGraph Integration**: Advanced workflow orchestration
118
- - **Anthropic Models API**: Direct Claude integration
119
- - **Together AI**: Access to open-source models
120
- - **Replicate**: For image generation and processing
121
-
122
- #### 4.2 Enhanced Existing Connectors
123
- - **GitHub**: Add PR review automation, code analysis
124
- - **Vercel**: Add analytics integration, performance monitoring
125
- - **HuggingFace**: Add model fine-tuning capabilities
126
- - **n8n**: Add more workflow templates
127
-
128
- ---
129
-
130
- ### Phase 5: Performance & Observability 📊
131
-
132
- #### 5.1 Monitoring & Logging
133
- - Add OpenTelemetry integration
134
- - Implement distributed tracing
135
- - Add custom metrics for agent performance
136
- - Real-time dashboard for system health
137
-
138
- #### 5.2 Caching Strategy
139
- - Implement Redis caching for frequently used models
140
- - Add semantic caching for similar prompts
141
- - Cache model responses for cost optimization
142
-
143
- #### 5.3 Load Testing & Optimization
144
- - Benchmark all agents under load
145
- - Optimize WebSocket message handling
146
- - Implement request batching for API calls
147
-
148
- ---
149
-
150
- ### Phase 6: Security Hardening 🔒
151
-
152
- #### 6.1 Authentication & Authorization
153
- - Add role-based access control (RBAC)
154
- - Implement API key rotation
155
- - Add audit logging for all operations
156
-
157
- #### 6.2 Data Protection
158
- - Encrypt sensitive data at rest
159
- - Add data retention policies
160
- - Implement GDPR compliance
161
-
162
- #### 6.3 Rate Limiting & DDoS Protection
163
- - Enhance rate limiting per user/API key
164
- - Add IP-based rate limiting
165
- - Implement request validation
166
-
167
- ---
168
-
169
- ### Phase 7: Deployment & DevOps 🚀
170
-
171
- #### 7.1 Docker Optimization
172
- - Multi-stage builds for smaller images
173
- - Add health checks and graceful shutdown
174
- - Implement zero-downtime deployments
175
-
176
- #### 7.2 Vercel Deployment
177
- - Add environment-specific configurations
178
- - Implement canary deployments
179
- - Add automated rollback on failures
180
-
181
- #### 7.3 CI/CD Pipeline
182
- - Add automated testing (unit, integration, e2e)
183
- - Implement code quality checks (SonarQube, CodeClimate)
184
- - Add performance benchmarking in CI
185
-
186
- ---
187
-
188
- ## Implementation Timeline
189
-
190
- | Phase | Duration | Priority |
191
- |-------|----------|----------|
192
- | Phase 1: AI Router Enhancement | 2-3 days | 🔴 Critical |
193
- | Phase 2: Backend Enhancements | 3-4 days | 🔴 Critical |
194
- | Phase 3: Frontend Modernization | 2-3 days | 🟡 High |
195
- | Phase 4: Connector Expansion | 2-3 days | 🟡 High |
196
- | Phase 5: Performance & Observability | 2-3 days | 🟠 Medium |
197
- | Phase 6: Security Hardening | 2-3 days | 🟠 Medium |
198
- | Phase 7: Deployment & DevOps | 1-2 days | 🟡 High |
199
-
200
- **Total Estimated Time**: 14-21 days
201
-
202
- ---
203
-
204
- ## Key Metrics for v3
205
-
206
- | Metric | v2 | v3 Target |
207
- |--------|-----|-----------|
208
- | Model Options | 5 AI providers | 8+ AI providers + reasoning models |
209
- | Agent Capabilities | 10 agents | 13+ agents (new: Reasoning, Optimization, Analytics, Knowledge) |
210
- | Response Time | ~2-5s | <1s (with caching) |
211
- | Cost Optimization | Basic | Advanced (smart model selection) |
212
- | Observability | Basic logging | Full OpenTelemetry integration |
213
- | Security Score | 85/100 | 95+/100 |
214
-
215
- ---
216
-
217
- ## Testing Strategy
218
-
219
- ### Unit Tests
220
- - Test each agent independently
221
- - Test AI router logic
222
- - Test connector integrations
223
-
224
- ### Integration Tests
225
- - Test agent orchestration
226
- - Test WebSocket communication
227
- - Test end-to-end workflows
228
-
229
- ### Performance Tests
230
- - Load test with 100+ concurrent users
231
- - Benchmark model response times
232
- - Test memory usage under stress
233
-
234
- ### Security Tests
235
- - Penetration testing
236
- - API security audit
237
- - Data protection verification
238
-
239
- ---
240
-
241
- ## Rollback Plan
242
-
243
- 1. Keep v2 deployment running during v3 development
244
- 2. Use canary deployments (5% → 25% → 50% → 100%)
245
- 3. Monitor error rates and performance metrics
246
- 4. Automatic rollback if error rate > 5%
247
- 5. Manual rollback option always available
248
-
249
- ---
250
-
251
- ## Success Criteria
252
-
253
- ✅ All 13 agents operational and tested
254
- ✅ 8+ AI providers integrated with reasoning models
255
- ✅ Response time < 1s for 95% of requests
256
- ✅ 99.9% uptime
257
- ✅ Zero security vulnerabilities
258
- ✅ Full test coverage > 80%
259
- ✅ Improved user satisfaction (NPS > 50)
260
-
261
- ---
262
-
263
- *Last Updated: May 14, 2026*
264
- *Status: Planning Phase*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
_legacy/main.py DELETED
@@ -1,310 +0,0 @@
1
- """
2
- 🚀 GOD AGENT OS — Autonomous AI Operating System v8
3
- Gemini + Sambanova + GitHub Models — Primary Provider Rotation
4
- Task-aware routing: research→Gemini, code→Sambanova, plan→GitHub
5
- """
6
-
7
- # ─── Inject bundled API keys (env vars take precedence) ───────────────────────
8
- import os as _os
9
-
10
- def _inject_key(env_var: str, value: str):
11
- """Set env var only if not already configured."""
12
- if not _os.environ.get(env_var):
13
- _os.environ[env_var] = value
14
-
15
- # Keys are loaded from HF Space Secrets / Docker env vars.
16
- # Set GEMINI_KEY, SAMBANOVA_KEY, GITHUB_KEY as comma-separated lists.
17
- # Fallback: read from .env.keys file if present (not committed to git).
18
- _keys_file = _os.path.join(_os.path.dirname(__file__), ".env.keys")
19
- if _os.path.exists(_keys_file):
20
- with open(_keys_file) as _f:
21
- for _line in _f:
22
- _line = _line.strip()
23
- if _line and "=" in _line and not _line.startswith("#"):
24
- _k, _v = _line.split("=", 1)
25
- _inject_key(_k.strip(), _v.strip())
26
- # ─────────────────────────────────────────────────────────────────────────────
27
-
28
-
29
- import asyncio
30
- import json
31
- import logging
32
- import os
33
- import time
34
- import uuid
35
- from contextlib import asynccontextmanager
36
- from typing import Optional
37
-
38
- import structlog
39
- from fastapi import FastAPI, WebSocket, WebSocketDisconnect, HTTPException, Request
40
- from fastapi.middleware.cors import CORSMiddleware
41
- from fastapi.middleware.gzip import GZipMiddleware
42
- from fastapi.responses import JSONResponse
43
- from slowapi import Limiter, _rate_limit_exceeded_handler
44
- from slowapi.util import get_remote_address
45
- from slowapi.errors import RateLimitExceeded
46
-
47
- from api.routes import tasks, chat, memory, github, health
48
- from api.routes import connectors, agents as agents_router
49
- from api.websocket_manager import WebSocketManager
50
- from core.task_engine import TaskEngine
51
- from memory.db import init_db
52
-
53
- # ─── God Mode Agents ───────────────────────────────────────────────────────────
54
- from ai_router.router import AIRouter
55
- from ai_router.router_v8 import GodModeRouter, get_router as get_god_router
56
- from agents.orchestrator import GodAgentOrchestrator
57
- from agents.chat_agent import ChatAgent
58
- from agents.planner_agent import PlannerAgent
59
- from agents.coding_agent import CodingAgent
60
- from agents.debug_agent import DebugAgent
61
- from agents.memory_agent import MemoryAgent
62
- from agents.connector_agent import ConnectorAgent
63
- from agents.deploy_agent import DeployAgent
64
- from agents.workflow_agent import WorkflowAgent
65
- from agents.sandbox_agent import SandboxAgent
66
- from agents.ui_agent import UIAgent
67
- from connectors.manager import ConnectorManager
68
-
69
- # ─── Structured Logging ────────────────────────────────────────────────────────
70
- structlog.configure(
71
- processors=[
72
- structlog.processors.TimeStamper(fmt="iso"),
73
- structlog.stdlib.add_log_level,
74
- structlog.processors.StackInfoRenderer(),
75
- structlog.dev.ConsoleRenderer(),
76
- ]
77
- )
78
- log = structlog.get_logger()
79
-
80
- # ─── Rate Limiter ──────────────────────────────────────────────────────────────
81
- limiter = Limiter(key_func=get_remote_address)
82
-
83
- # ─── Global Managers ──────────────────────────────────────────────────────────
84
- ws_manager = WebSocketManager()
85
- task_engine = TaskEngine(ws_manager)
86
- ai_router = AIRouter(ws_manager)
87
- god_router = get_god_router(ws_manager) # v8 primary router
88
- connector_manager = ConnectorManager()
89
-
90
- # ─── Build God Agent Ecosystem ────────────────────────────────────────────────
91
- def build_orchestrator() -> GodAgentOrchestrator:
92
- orchestrator = GodAgentOrchestrator(ws_manager=ws_manager, ai_router=ai_router)
93
-
94
- # Register all specialized agents
95
- orchestrator.register_agent("chat", ChatAgent(ws_manager, ai_router))
96
- orchestrator.register_agent("planner", PlannerAgent(ws_manager, ai_router))
97
- orchestrator.register_agent("coding", CodingAgent(ws_manager, ai_router))
98
- orchestrator.register_agent("debug", DebugAgent(ws_manager, ai_router))
99
- orchestrator.register_agent("memory", MemoryAgent(ws_manager, ai_router))
100
- orchestrator.register_agent("connector", ConnectorAgent(ws_manager, ai_router))
101
- orchestrator.register_agent("deploy", DeployAgent(ws_manager, ai_router))
102
- orchestrator.register_agent("workflow", WorkflowAgent(ws_manager, ai_router))
103
- orchestrator.register_agent("sandbox", SandboxAgent(ws_manager, ai_router))
104
- orchestrator.register_agent("ui", UIAgent(ws_manager, ai_router))
105
-
106
- log.info("🤖 God Agent Ecosystem initialized", agents=10)
107
- return orchestrator
108
-
109
- orchestrator = build_orchestrator()
110
-
111
-
112
- @asynccontextmanager
113
- async def lifespan(app: FastAPI):
114
- """Startup + Shutdown lifecycle."""
115
- log.info("🚀 Starting GOD MODE+ AI Operating System...")
116
- await init_db()
117
- await task_engine.start()
118
- asyncio.create_task(ws_manager.heartbeat_loop())
119
- log.info("✅ GOD MODE+ Platform ready — All agents online")
120
- log.info("🤖 Agents: Chat, Planner, Coding, Debug, Memory, Connector, Deploy, Workflow, Sandbox, UI")
121
- log.info("🌐 AI Router v8: Gemini → Sambanova → GitHub Models (task-aware rotation)")
122
- yield
123
- log.info("🛑 Shutting down...")
124
- await task_engine.stop()
125
- log.info("✅ Shutdown complete")
126
-
127
-
128
- # ─── FastAPI App ───────────────────────────────────────────────────────────────
129
- app = FastAPI(
130
- title="🤖 GOD MODE+ AI Operating System",
131
- description="Devin + Manus + Genspark Autonomous AI Engineering Platform",
132
- version="3.0.0",
133
- lifespan=lifespan,
134
- docs_url="/api/docs",
135
- redoc_url="/api/redoc",
136
- )
137
-
138
- app.state.limiter = limiter
139
- app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
140
-
141
- # ─── Share state ───────────────────────────────────────────────────────────────
142
- app.state.ws_manager = ws_manager
143
- app.state.task_engine = task_engine
144
- app.state.ai_router = ai_router
145
- app.state.orchestrator = orchestrator
146
- app.state.connector_manager = connector_manager
147
-
148
- # ─── Middleware ────────────────────────────────────────────────────────────────
149
- app.add_middleware(
150
- CORSMiddleware,
151
- allow_origins=["*"],
152
- allow_credentials=True,
153
- allow_methods=["*"],
154
- allow_headers=["*"],
155
- )
156
- app.add_middleware(GZipMiddleware, minimum_size=1000)
157
-
158
-
159
- @app.middleware("http")
160
- async def log_requests(request: Request, call_next):
161
- start = time.time()
162
- response = await call_next(request)
163
- duration = round((time.time() - start) * 1000, 2)
164
- log.info("HTTP", method=request.method, path=request.url.path, status=response.status_code, ms=duration)
165
- return response
166
-
167
-
168
- # ─── REST API Routers ──────────────────────────────────────────────────────────
169
- app.include_router(health.router, prefix="/api/v1", tags=["health"])
170
- app.include_router(tasks.router, prefix="/api/v1/tasks", tags=["tasks"])
171
- app.include_router(chat.router, prefix="/api/v1", tags=["chat"])
172
- app.include_router(memory.router, prefix="/api/v1/memory", tags=["memory"])
173
- app.include_router(github.router, prefix="/api/v1/github", tags=["github"])
174
- app.include_router(connectors.router, prefix="/api/v1/connectors", tags=["connectors"])
175
- app.include_router(agents_router.router, prefix="/api/v1/agents", tags=["agents"])
176
-
177
-
178
- # ─── WebSocket Endpoints ───────────────────────────────────────────────────────
179
- @app.websocket("/ws/tasks/{task_id}")
180
- async def ws_task(websocket: WebSocket, task_id: str):
181
- await ws_manager.connect(websocket, room=f"task:{task_id}")
182
- try:
183
- while True:
184
- data = await websocket.receive_text()
185
- msg = json.loads(data)
186
- if msg.get("type") == "ping":
187
- await websocket.send_json({"type": "pong", "timestamp": time.time()})
188
- except WebSocketDisconnect:
189
- ws_manager.disconnect(websocket, room=f"task:{task_id}")
190
-
191
-
192
- @app.websocket("/ws/logs")
193
- async def ws_logs(websocket: WebSocket):
194
- await ws_manager.connect(websocket, room="logs")
195
- try:
196
- while True:
197
- data = await websocket.receive_text()
198
- msg = json.loads(data)
199
- if msg.get("type") == "ping":
200
- await websocket.send_json({"type": "pong", "timestamp": time.time()})
201
- except WebSocketDisconnect:
202
- ws_manager.disconnect(websocket, room="logs")
203
-
204
-
205
- @app.websocket("/ws/chat/{session_id}")
206
- async def ws_chat(websocket: WebSocket, session_id: str):
207
- await ws_manager.connect(websocket, room=f"chat:{session_id}")
208
- try:
209
- while True:
210
- data = await websocket.receive_text()
211
- msg = json.loads(data)
212
- if msg.get("type") == "ping":
213
- await websocket.send_json({"type": "pong", "timestamp": time.time()})
214
- elif msg.get("type") == "chat_message":
215
- # Route through God Agent Orchestrator
216
- asyncio.create_task(
217
- orchestrator.orchestrate(
218
- user_message=msg.get("content", ""),
219
- session_id=session_id,
220
- context=msg.get("context", {}),
221
- )
222
- )
223
- elif msg.get("type") == "task_message":
224
- # Create autonomous task via task engine
225
- from core.models import TaskCreateRequest
226
- req = TaskCreateRequest(
227
- goal=msg.get("content", ""),
228
- session_id=session_id,
229
- )
230
- asyncio.create_task(task_engine.submit(req))
231
- except WebSocketDisconnect:
232
- ws_manager.disconnect(websocket, room=f"chat:{session_id}")
233
-
234
-
235
- @app.websocket("/ws/agent/status")
236
- async def ws_agent_status(websocket: WebSocket):
237
- await ws_manager.connect(websocket, room="agent_status")
238
- try:
239
- while True:
240
- data = await websocket.receive_text()
241
- msg = json.loads(data)
242
- if msg.get("type") == "ping":
243
- await websocket.send_json({"type": "pong", "timestamp": time.time()})
244
- elif msg.get("type") == "get_status":
245
- await websocket.send_json({
246
- "type": "agent_status",
247
- "data": orchestrator.get_status(),
248
- })
249
- except WebSocketDisconnect:
250
- ws_manager.disconnect(websocket, room="agent_status")
251
-
252
-
253
- @app.websocket("/ws/sandbox/{session_id}")
254
- async def ws_sandbox(websocket: WebSocket, session_id: str):
255
- """Live sandbox terminal stream."""
256
- await ws_manager.connect(websocket, room=f"sandbox:{session_id}")
257
- sandbox = orchestrator.get_agent("sandbox")
258
- try:
259
- while True:
260
- data = await websocket.receive_text()
261
- msg = json.loads(data)
262
- if msg.get("type") == "ping":
263
- await websocket.send_json({"type": "pong", "timestamp": time.time()})
264
- elif msg.get("type") == "execute" and sandbox:
265
- cmd = msg.get("command", "")
266
- result = await sandbox.execute(cmd, session_id=session_id)
267
- await websocket.send_json({
268
- "type": "terminal_output",
269
- "command": cmd,
270
- "output": result,
271
- "timestamp": time.time(),
272
- })
273
- except WebSocketDisconnect:
274
- ws_manager.disconnect(websocket, room=f"sandbox:{session_id}")
275
-
276
-
277
- # ─── Root ──────────────────────────────────────────────────────────────────────
278
- @app.get("/")
279
- async def root():
280
- cs = connector_manager.get_summary()
281
- return {
282
- "name": "🤖 GOD MODE+ AI Operating System",
283
- "version": "3.0.0",
284
- "status": "operational",
285
- "mode": "god_mode_plus",
286
- "agents": orchestrator.get_status()["agents"],
287
- "connectors": {
288
- "connected": cs["connected"],
289
- "total": cs["total"],
290
- "ai_ready": cs["ai_ready"],
291
- },
292
- "docs": "/api/docs",
293
- "websockets": [
294
- "/ws/tasks/{task_id}",
295
- "/ws/logs",
296
- "/ws/chat/{session_id}",
297
- "/ws/agent/status",
298
- "/ws/sandbox/{session_id}",
299
- ],
300
- "phases_complete": [
301
- "Phase 1: God Agent Orchestrator",
302
- "Phase 2: Sandbox Agent",
303
- "Phase 3: Connector System",
304
- "Phase 4: Autonomous Coding Engine",
305
- "Phase 5: Memory System",
306
- "Phase 6: Real-time Streaming",
307
- "Phase 7: Workflow Factor OS",
308
- "Phase 9: Multi-Model AI Router",
309
- ],
310
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
_legacy/main_v11.py DELETED
@@ -1,442 +0,0 @@
1
- """
2
- GOD AGENT OS v11 — Fixed & Production Ready
3
- Bugs fixed:
4
- - TaskEngine(ws_manager) only — removed ai_router arg
5
- - init_db() — no arguments
6
- - task_engine.start() — not run()
7
- - ws_manager.emit_chat() — not emit_task()
8
- - ConnectorManager() — sync init, no await needed
9
- """
10
-
11
- import asyncio
12
- import json
13
- import os
14
- import time
15
- import uuid
16
- from contextlib import asynccontextmanager
17
- from typing import Dict, List
18
-
19
- import structlog
20
- from fastapi import FastAPI, WebSocket, WebSocketDisconnect, HTTPException, Request
21
- from fastapi.middleware.cors import CORSMiddleware
22
- from fastapi.middleware.gzip import GZipMiddleware
23
- from fastapi.responses import StreamingResponse
24
- from slowapi import Limiter, _rate_limit_exceeded_handler
25
- from slowapi.util import get_remote_address
26
- from slowapi.errors import RateLimitExceeded
27
-
28
- from api.websocket_manager import WebSocketManager
29
- from core.task_engine import TaskEngine
30
- from memory.db import init_db
31
- from ai_router.router_v10 import AIRouterV10
32
- from agents.orchestrator_v7 import GodAgentOrchestratorV7
33
- from agents.chat_agent import ChatAgent
34
- from agents.planner_agent import PlannerAgent
35
- from agents.coding_agent import CodingAgent
36
- from agents.debug_agent import DebugAgent
37
- from agents.memory_agent import MemoryAgent
38
- from agents.connector_agent import ConnectorAgent
39
- from agents.deploy_agent import DeployAgent
40
- from agents.workflow_agent import WorkflowAgent
41
- from agents.sandbox_agent import SandboxAgent
42
- from agents.ui_agent import UIAgent
43
- from agents.reasoning_agent import ReasoningAgent
44
- from agents.browser_agent import BrowserAgent
45
- from agents.file_agent import FileAgent
46
- from agents.git_agent import GitAgent
47
- from agents.test_agent import TestAgent
48
- from agents.vision_agent import VisionAgent
49
- from connectors.manager import ConnectorManager
50
- from api.routes import tasks, chat, memory, health, connectors, agents as agents_router
51
- from api.routes import github
52
-
53
- structlog.configure(
54
- processors=[
55
- structlog.processors.TimeStamper(fmt="iso"),
56
- structlog.stdlib.add_log_level,
57
- structlog.processors.StackInfoRenderer(),
58
- structlog.dev.ConsoleRenderer(),
59
- ]
60
- )
61
- log = structlog.get_logger()
62
-
63
- limiter = Limiter(key_func=get_remote_address)
64
-
65
- ws_manager: WebSocketManager = None
66
- task_engine: TaskEngine = None
67
- ai_router: AIRouterV10 = None
68
- orchestrator: GodAgentOrchestratorV7 = None
69
- connector_manager: ConnectorManager = None
70
-
71
- computer_use_sessions: Dict[str, List[Dict]] = {}
72
-
73
-
74
- def add_computer_use_step(session_id: str, step_type: str, data: Dict):
75
- if session_id not in computer_use_sessions:
76
- computer_use_sessions[session_id] = []
77
- computer_use_sessions[session_id].append({
78
- "id": uuid.uuid4().hex[:8],
79
- "type": step_type,
80
- "data": data,
81
- "timestamp": time.time(),
82
- "status": "running",
83
- })
84
- computer_use_sessions[session_id] = computer_use_sessions[session_id][-100:]
85
-
86
-
87
- @asynccontextmanager
88
- async def lifespan(app: FastAPI):
89
- global ws_manager, task_engine, ai_router, orchestrator, connector_manager
90
-
91
- log.info("GOD AGENT OS v11 starting...")
92
-
93
- # FIX: init_db() takes no arguments
94
- await init_db()
95
-
96
- ai_router = AIRouterV10()
97
- ws_manager = WebSocketManager()
98
-
99
- # FIX: TaskEngine only takes ws_manager
100
- task_engine = TaskEngine(ws_manager)
101
-
102
- orchestrator = GodAgentOrchestratorV7(ws_manager, ai_router)
103
- agents_map = {
104
- "chat": ChatAgent(ws_manager, ai_router),
105
- "planner": PlannerAgent(ws_manager, ai_router),
106
- "coding": CodingAgent(ws_manager, ai_router),
107
- "debug": DebugAgent(ws_manager, ai_router),
108
- "memory": MemoryAgent(ws_manager, ai_router),
109
- "connector": ConnectorAgent(ws_manager, ai_router),
110
- "deploy": DeployAgent(ws_manager, ai_router),
111
- "workflow": WorkflowAgent(ws_manager, ai_router),
112
- "sandbox": SandboxAgent(ws_manager, ai_router),
113
- "ui": UIAgent(ws_manager, ai_router),
114
- "reasoning": ReasoningAgent(ws_manager, ai_router),
115
- "browser": BrowserAgent(ws_manager, ai_router),
116
- "file": FileAgent(ws_manager, ai_router),
117
- "git": GitAgent(ws_manager, ai_router),
118
- "test": TestAgent(ws_manager, ai_router),
119
- "vision": VisionAgent(ws_manager, ai_router),
120
- }
121
- for name, agent in agents_map.items():
122
- orchestrator.register_agent(name, agent)
123
-
124
- # FIX: ConnectorManager is sync — no await initialize()
125
- connector_manager = ConnectorManager()
126
-
127
- app.state.ws_manager = ws_manager
128
- app.state.task_engine = task_engine
129
- app.state.ai_router = ai_router
130
- app.state.orchestrator = orchestrator
131
- app.state.connector_manager = connector_manager
132
-
133
- # FIX: use start() not run()
134
- asyncio.create_task(task_engine.start())
135
-
136
- log.info("GOD AGENT OS v11 ready!", agents=len(agents_map))
137
- yield
138
-
139
- log.info("Shutting down...")
140
- await task_engine.stop()
141
-
142
-
143
- app = FastAPI(
144
- title="GOD AGENT OS v11",
145
- description="Autonomous Engineering OS",
146
- version="11.0.0",
147
- docs_url="/api/docs",
148
- redoc_url="/api/redoc",
149
- lifespan=lifespan,
150
- )
151
-
152
- app.state_limiter = limiter
153
- app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
154
- app.add_middleware(GZipMiddleware, minimum_size=1000)
155
- app.add_middleware(
156
- CORSMiddleware,
157
- allow_origins=["*"],
158
- allow_credentials=True,
159
- allow_methods=["*"],
160
- allow_headers=["*"],
161
- )
162
-
163
- app.include_router(health.router, prefix="/api/v1", tags=["health"])
164
- app.include_router(chat.router, prefix="/api/v1", tags=["chat"])
165
- app.include_router(tasks.router, prefix="/api/v1/tasks", tags=["tasks"])
166
- app.include_router(memory.router, prefix="/api/v1/memory", tags=["memory"])
167
- app.include_router(connectors.router, prefix="/api/v1/connectors", tags=["connectors"])
168
- app.include_router(agents_router.router, prefix="/api/v1/agents", tags=["agents"])
169
- app.include_router(github.router, prefix="/api/v1/github", tags=["github"])
170
-
171
-
172
- @app.websocket("/ws/{session_id}")
173
- async def websocket_endpoint(websocket: WebSocket, session_id: str):
174
- # FIX: connect takes (websocket, room) — use chat: prefix
175
- await ws_manager.connect(websocket, f"chat:{session_id}")
176
- try:
177
- while True:
178
- data = await websocket.receive_json()
179
- event_type = data.get("type", "")
180
-
181
- if event_type == "ping":
182
- await websocket.send_json({"type": "pong", "ts": time.time()})
183
-
184
- elif event_type == "message":
185
- message = data.get("message", "")
186
- task_id = uuid.uuid4().hex[:12]
187
- # FIX: use emit_chat() not emit_task()
188
- await ws_manager.emit_chat(session_id, "task_start", {
189
- "task_id": task_id,
190
- "message": message[:100],
191
- })
192
- asyncio.create_task(_run_ws_task(message, task_id, session_id))
193
-
194
- elif event_type == "stop":
195
- task_id = data.get("task_id", "")
196
- if task_id:
197
- await task_engine.cancel(task_id)
198
-
199
- except WebSocketDisconnect:
200
- ws_manager.disconnect(websocket, f"chat:{session_id}")
201
-
202
-
203
- async def _run_ws_task(message: str, task_id: str, session_id: str):
204
- try:
205
- result = await orchestrator.orchestrate(
206
- user_message=message,
207
- task_id=task_id,
208
- session_id=session_id,
209
- )
210
- await ws_manager.emit_chat(session_id, "task_complete", {
211
- "task_id": task_id,
212
- "result": result[:2000] if result else "",
213
- })
214
- except Exception as e:
215
- await ws_manager.emit_chat(session_id, "task_error", {
216
- "task_id": task_id,
217
- "error": str(e),
218
- })
219
-
220
-
221
- @app.get("/api/v1/computer-use/{session_id}")
222
- async def get_computer_use_steps(session_id: str):
223
- steps = computer_use_sessions.get(session_id, [])
224
- return {"session_id": session_id, "steps": steps, "count": len(steps)}
225
-
226
-
227
- @app.websocket("/ws/computer-use/{session_id}")
228
- async def computer_use_ws(websocket: WebSocket, session_id: str):
229
- await websocket.accept()
230
- try:
231
- last_idx = 0
232
- while True:
233
- steps = computer_use_sessions.get(session_id, [])
234
- if len(steps) > last_idx:
235
- for step in steps[last_idx:]:
236
- await websocket.send_json({"type": "computer_use_step", "step": step})
237
- last_idx = len(steps)
238
- await asyncio.sleep(0.5)
239
- except WebSocketDisconnect:
240
- pass
241
-
242
-
243
- @app.post("/api/v1/orchestrate")
244
- async def orchestrate_goal(request: Request):
245
- body = await request.json()
246
- message = body.get("message", "")
247
- session_id = body.get("session_id", uuid.uuid4().hex[:12])
248
-
249
- if not message:
250
- raise HTTPException(status_code=400, detail="Message required")
251
-
252
- task_id = uuid.uuid4().hex[:12]
253
- add_computer_use_step(session_id, "thinking", {
254
- "message": f"Processing: {message[:100]}",
255
- "task_id": task_id,
256
- })
257
-
258
- if body.get("stream", False):
259
- async def stream_gen():
260
- try:
261
- result = await orchestrator.orchestrate(
262
- user_message=message, task_id=task_id, session_id=session_id,
263
- )
264
- add_computer_use_step(session_id, "complete", {"result": result[:200] if result else ""})
265
- yield f"data: {json.dumps({'type': 'complete', 'result': result, 'task_id': task_id, 'session_id': session_id})}\n\n"
266
- except Exception as e:
267
- yield f"data: {json.dumps({'type': 'error', 'error': str(e)})}\n\n"
268
-
269
- return StreamingResponse(
270
- stream_gen(),
271
- media_type="text/event-stream",
272
- headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"},
273
- )
274
-
275
- try:
276
- result = await orchestrator.orchestrate(user_message=message, task_id=task_id, session_id=session_id)
277
- add_computer_use_step(session_id, "complete", {"result": result[:200] if result else ""})
278
- return {"task_id": task_id, "session_id": session_id, "result": result, "status": "complete"}
279
- except Exception as e:
280
- log.error("Orchestration error", error=str(e))
281
- raise HTTPException(status_code=500, detail=str(e))
282
-
283
-
284
- @app.post("/api/v1/agents/{agent_name}/run")
285
- async def run_agent(agent_name: str, request: Request):
286
- body = await request.json()
287
- task = body.get("task", "")
288
- session_id = body.get("session_id", uuid.uuid4().hex[:12])
289
- task_id = uuid.uuid4().hex[:12]
290
-
291
- agent = orchestrator.get_agent(agent_name)
292
- if not agent:
293
- raise HTTPException(status_code=404, detail=f"Agent '{agent_name}' not found")
294
-
295
- try:
296
- result = await agent.run(
297
- task=task,
298
- context=body.get("context", {}),
299
- task_id=task_id,
300
- session_id=session_id,
301
- )
302
- return {"agent": agent_name, "task_id": task_id, "result": result, "status": "complete"}
303
- except Exception as e:
304
- raise HTTPException(status_code=500, detail=str(e))
305
-
306
-
307
- @app.get("/api/v1/agents")
308
- async def list_agents():
309
- names = ["chat", "planner", "coding", "debug", "memory", "connector",
310
- "deploy", "workflow", "sandbox", "ui", "reasoning",
311
- "browser", "file", "git", "test", "vision"]
312
- agents_list = []
313
- for name in names:
314
- agent = orchestrator.get_agent(name)
315
- agents_list.append({
316
- "name": name,
317
- "available": agent is not None,
318
- "class": type(agent).__name__ if agent else None,
319
- })
320
- return {"agents": agents_list, "total": len(agents_list)}
321
-
322
-
323
- SPACE_DEFS = [
324
- {"id": "god-core", "name": "God Core Space", "role": "orchestration", "agent": "orchestrator", "icon": "🧠"},
325
- {"id": "coding", "name": "Coding Worker", "role": "code_generation", "agent": "coding", "icon": "⚡"},
326
- {"id": "sandbox", "name": "Sandbox Worker", "role": "execution", "agent": "sandbox", "icon": "🔧"},
327
- {"id": "terminal", "name": "Terminal Worker", "role": "execution", "agent": "sandbox", "icon": "🖥️"},
328
- {"id": "filesystem", "name": "FileSystem Worker", "role": "files", "agent": "file", "icon": "📁"},
329
- {"id": "browser", "name": "Browser Worker", "role": "research", "agent": "browser", "icon": "🌐"},
330
- {"id": "vision", "name": "Vision Worker", "role": "ui_gen", "agent": "vision", "icon": "👁️"},
331
- {"id": "ui", "name": "UI Worker", "role": "ui", "agent": "ui", "icon": "🎨"},
332
- {"id": "debug", "name": "Debug Worker", "role": "debugging", "agent": "debug", "icon": "🐛"},
333
- {"id": "test", "name": "Test Worker", "role": "testing", "agent": "test", "icon": "🧪"},
334
- {"id": "verification", "name": "Verification Worker", "role": "qa", "agent": "test", "icon": "✅"},
335
- {"id": "git", "name": "Git Worker", "role": "git", "agent": "git", "icon": "🔀"},
336
- {"id": "deploy", "name": "Deploy Worker", "role": "deployment", "agent": "deploy", "icon": "🚀"},
337
- {"id": "connector", "name": "Connector Worker", "role": "integration", "agent": "connector", "icon": "🔌"},
338
- {"id": "memory", "name": "Memory Worker", "role": "memory", "agent": "memory", "icon": "💾"},
339
- {"id": "knowledge", "name": "Knowledge Worker", "role": "knowledge", "agent": "memory", "icon": "📚"},
340
- {"id": "workflow", "name": "Workflow Worker", "role": "automation", "agent": "workflow", "icon": "⚙️"},
341
- {"id": "eventbus", "name": "Event Bus", "role": "events", "agent": None, "icon": "📡"},
342
- {"id": "model-router", "name": "Model Router", "role": "ai_routing", "agent": None, "icon": "🤖"},
343
- {"id": "observability", "name": "Observability", "role": "monitoring", "agent": None, "icon": "📊"},
344
- {"id": "session-runtime", "name": "Session Runtime", "role": "sessions", "agent": None, "icon": "⏱️"},
345
- {"id": "auth-gateway", "name": "Auth Gateway", "role": "auth", "agent": None, "icon": "🔐"},
346
- ]
347
-
348
-
349
- @app.get("/api/v1/spaces")
350
- async def get_spaces():
351
- spaces_status = []
352
- for space in SPACE_DEFS:
353
- agent_name = space.get("agent")
354
- agent = orchestrator.get_agent(agent_name) if agent_name else None
355
- spaces_status.append({
356
- **space,
357
- "status": "active" if (agent is not None or agent_name is None) else "inactive",
358
- "online": True,
359
- "backend": "god-agent-os-v11",
360
- "tasks_completed": 0,
361
- })
362
- return {
363
- "spaces": spaces_status,
364
- "total": len(spaces_status),
365
- "active": len([s for s in spaces_status if s["status"] == "active"]),
366
- "backend_url": os.environ.get("SPACE_URL", "https://pyae1994-autonomous-coding-system.hf.space"),
367
- }
368
-
369
-
370
- @app.get("/health")
371
- @app.get("/api/v1/health")
372
- async def health_check():
373
- stats = ai_router.get_stats() if ai_router else {}
374
- active_providers = [name for name, s in stats.items() if s.get("available")]
375
- return {
376
- "status": "healthy",
377
- "version": "11.0.0",
378
- "timestamp": time.time(),
379
- "agents": 16,
380
- "spaces": 22,
381
- "ai_providers": active_providers,
382
- "mode": "god_mode",
383
- }
384
-
385
-
386
- @app.get("/api/v1/ai/stats")
387
- async def get_ai_stats():
388
- return {"stats": ai_router.get_stats() if ai_router else {}}
389
-
390
-
391
- @app.get("/api/v1/ai/pool-status")
392
- async def get_pool_status():
393
- return {"pools": ai_router.get_pool_status() if ai_router else {}}
394
-
395
-
396
- @app.get("/api/v1/system/status")
397
- async def system_status():
398
- ai_stats = ai_router.get_stats() if ai_router else {}
399
- cs = connector_manager.get_summary() if connector_manager else {"connected": 0, "total": 0}
400
- return {
401
- "system": "god_agent_os_v11",
402
- "status": "operational",
403
- "timestamp": time.time(),
404
- "ai_router": {
405
- "providers": ai_stats,
406
- "active": len([v for v in ai_stats.values() if v.get("available")]),
407
- },
408
- "agents": {
409
- "total": 16,
410
- "online": 16,
411
- },
412
- "spaces": {"total": 22, "all_in_backend": True},
413
- "connectors": cs,
414
- "features": {
415
- "god_mode": True,
416
- "computer_use": True,
417
- "streaming": True,
418
- "websocket": True,
419
- "multi_agent": True,
420
- "burmese_language": True,
421
- },
422
- }
423
-
424
-
425
- @app.get("/")
426
- async def root():
427
- return {
428
- "name": "GOD AGENT OS v11",
429
- "version": "11.0.0",
430
- "status": "operational",
431
- "mode": "GOD_MODE",
432
- "docs": "/api/docs",
433
- "health": "/health",
434
- "agents": 16,
435
- "spaces": 22,
436
- }
437
-
438
-
439
- if __name__ == "__main__":
440
- import uvicorn
441
- port = int(os.environ.get("PORT", 7860))
442
- uvicorn.run("main_v11:app", host="0.0.0.0", port=port, reload=False, workers=1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
_legacy/main_v7.py DELETED
@@ -1,363 +0,0 @@
1
- """
2
- 🚀 GOD AGENT OS v7 — Autonomous Engineering Operating System
3
- Manus + Genspark + Devin (OneHand) Combined
4
- Version: 7.0.0
5
- """
6
-
7
- import asyncio
8
- import json
9
- import logging
10
- import os
11
- import time
12
- import uuid
13
- from contextlib import asynccontextmanager
14
- from typing import Optional
15
-
16
- import structlog
17
- from fastapi import FastAPI, WebSocket, WebSocketDisconnect, HTTPException, Request
18
- from fastapi.middleware.cors import CORSMiddleware
19
- from fastapi.middleware.gzip import GZipMiddleware
20
- from fastapi.responses import JSONResponse
21
- from slowapi import Limiter, _rate_limit_exceeded_handler
22
- from slowapi.util import get_remote_address
23
- from slowapi.errors import RateLimitExceeded
24
-
25
- from api.routes import tasks, chat, memory, github, health
26
- from api.routes import connectors, agents as agents_router
27
- from api.websocket_manager import WebSocketManager
28
- from core.task_engine import TaskEngine
29
- from memory.db import init_db
30
-
31
- # ─── v7 God Agent Ecosystem ────────────────────────────────────────────────────
32
- from ai_router.router import AIRouter
33
- from agents.orchestrator_v7 import GodAgentOrchestratorV7
34
- from agents.chat_agent import ChatAgent
35
- from agents.planner_agent import PlannerAgent
36
- from agents.coding_agent import CodingAgent
37
- from agents.debug_agent import DebugAgent
38
- from agents.memory_agent import MemoryAgent
39
- from agents.connector_agent import ConnectorAgent
40
- from agents.deploy_agent import DeployAgent
41
- from agents.workflow_agent import WorkflowAgent
42
- from agents.sandbox_agent import SandboxAgent
43
- from agents.ui_agent import UIAgent
44
- from agents.reasoning_agent import ReasoningAgent
45
- # v7 new agents
46
- from agents.browser_agent import BrowserAgent
47
- from agents.file_agent import FileAgent
48
- from agents.git_agent import GitAgent
49
- from agents.test_agent import TestAgent
50
- from agents.vision_agent import VisionAgent
51
- from connectors.manager import ConnectorManager
52
-
53
- # ─── Structured Logging ────────────────────────────────────────────────────────
54
- structlog.configure(
55
- processors=[
56
- structlog.processors.TimeStamper(fmt="iso"),
57
- structlog.stdlib.add_log_level,
58
- structlog.processors.StackInfoRenderer(),
59
- structlog.dev.ConsoleRenderer(),
60
- ]
61
- )
62
- log = structlog.get_logger()
63
-
64
- # ─── Rate Limiter ──────────────────────────────────────────────────────────────
65
- limiter = Limiter(key_func=get_remote_address)
66
-
67
- # ─── Global Managers ──────────────────────────────────────────────────────────
68
- ws_manager = WebSocketManager()
69
- task_engine = TaskEngine(ws_manager)
70
- ai_router = AIRouter(ws_manager)
71
- connector_manager = ConnectorManager()
72
-
73
-
74
- # ─── Build v7 God Agent Ecosystem ─────────────────────────────────────────────
75
- def build_orchestrator_v7() -> GodAgentOrchestratorV7:
76
- orchestrator = GodAgentOrchestratorV7(ws_manager=ws_manager, ai_router=ai_router)
77
-
78
- # ── Core agents (v3 retained) ──────────────────────────────────────────
79
- orchestrator.register_agent("chat", ChatAgent(ws_manager, ai_router))
80
- orchestrator.register_agent("planner", PlannerAgent(ws_manager, ai_router))
81
- orchestrator.register_agent("coding", CodingAgent(ws_manager, ai_router))
82
- orchestrator.register_agent("debug", DebugAgent(ws_manager, ai_router))
83
- orchestrator.register_agent("memory", MemoryAgent(ws_manager, ai_router))
84
- orchestrator.register_agent("connector", ConnectorAgent(ws_manager, ai_router))
85
- orchestrator.register_agent("deploy", DeployAgent(ws_manager, ai_router))
86
- orchestrator.register_agent("workflow", WorkflowAgent(ws_manager, ai_router))
87
- orchestrator.register_agent("sandbox", SandboxAgent(ws_manager, ai_router))
88
- orchestrator.register_agent("ui", UIAgent(ws_manager, ai_router))
89
- orchestrator.register_agent("reasoning", ReasoningAgent(ws_manager, ai_router))
90
-
91
- # ── v7 NEW agents ──────────────────────────────────────────────────────
92
- orchestrator.register_agent("browser", BrowserAgent(ws_manager, ai_router))
93
- orchestrator.register_agent("file", FileAgent(ws_manager, ai_router))
94
- orchestrator.register_agent("git", GitAgent(ws_manager, ai_router))
95
- orchestrator.register_agent("test", TestAgent(ws_manager, ai_router))
96
- orchestrator.register_agent("vision", VisionAgent(ws_manager, ai_router))
97
-
98
- log.info("🤖 GOD AGENT v7 Ecosystem initialized", agents=16)
99
- return orchestrator
100
-
101
-
102
- orchestrator = build_orchestrator_v7()
103
-
104
-
105
- @asynccontextmanager
106
- async def lifespan(app: FastAPI):
107
- log.info("🚀 Starting GOD AGENT OS v7 — Autonomous Engineering Platform...")
108
- await init_db()
109
- await task_engine.start()
110
- asyncio.create_task(ws_manager.heartbeat_loop())
111
- log.info("✅ GOD AGENT v7 — All 16 agents online")
112
- log.info("🤖 Core: Chat, Planner, Coding, Debug, Memory, Connector, Deploy, Workflow, Sandbox, UI, Reasoning")
113
- log.info("⚡ v7 New: Browser, File, Git, Test, Vision")
114
- log.info("🌐 AI Router: OpenAI → Groq → Cerebras → OpenRouter → Anthropic (auto-failover)")
115
- yield
116
- log.info("🛑 Shutting down GOD AGENT v7...")
117
- await task_engine.stop()
118
- log.info("✅ Shutdown complete")
119
-
120
-
121
- # ─── FastAPI App ───────────────────────────────────────────────────────────────
122
- app = FastAPI(
123
- title="🤖 GOD AGENT OS v7",
124
- description="Autonomous Engineering OS — Manus + Genspark + Devin (OneHand) Combined",
125
- version="7.0.0",
126
- lifespan=lifespan,
127
- docs_url="/api/docs",
128
- redoc_url="/api/redoc",
129
- )
130
-
131
- app.state.limiter = limiter
132
- app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
133
-
134
- # ─── Share state ───────────────────────────────────────────────────────────────
135
- app.state.ws_manager = ws_manager
136
- app.state.task_engine = task_engine
137
- app.state.ai_router = ai_router
138
- app.state.orchestrator = orchestrator
139
- app.state.connector_manager = connector_manager
140
-
141
- # ─── Middleware ────────────────────────────────────────────────────────────────
142
- app.add_middleware(
143
- CORSMiddleware,
144
- allow_origins=["*"],
145
- allow_credentials=True,
146
- allow_methods=["*"],
147
- allow_headers=["*"],
148
- )
149
- app.add_middleware(GZipMiddleware, minimum_size=1000)
150
-
151
-
152
- @app.middleware("http")
153
- async def log_requests(request: Request, call_next):
154
- start = time.time()
155
- response = await call_next(request)
156
- duration = round((time.time() - start) * 1000, 2)
157
- log.info("HTTP", method=request.method, path=request.url.path, status=response.status_code, ms=duration)
158
- return response
159
-
160
-
161
- # ─── REST API Routers ──────────────────────────────────────────────────────────
162
- app.include_router(health.router, prefix="/api/v1", tags=["health"])
163
- app.include_router(tasks.router, prefix="/api/v1/tasks", tags=["tasks"])
164
- app.include_router(chat.router, prefix="/api/v1", tags=["chat"])
165
- app.include_router(memory.router, prefix="/api/v1/memory", tags=["memory"])
166
- app.include_router(github.router, prefix="/api/v1/github", tags=["github"])
167
- app.include_router(connectors.router, prefix="/api/v1/connectors", tags=["connectors"])
168
- app.include_router(agents_router.router, prefix="/api/v1/agents", tags=["agents"])
169
-
170
-
171
- # ─── WebSocket Endpoints ───────────────────────────────────────────────────────
172
- @app.websocket("/ws/tasks/{task_id}")
173
- async def ws_task(websocket: WebSocket, task_id: str):
174
- await ws_manager.connect(websocket, room=f"task:{task_id}")
175
- try:
176
- while True:
177
- data = await websocket.receive_text()
178
- msg = json.loads(data)
179
- if msg.get("type") == "ping":
180
- await websocket.send_json({"type": "pong", "timestamp": time.time()})
181
- except WebSocketDisconnect:
182
- ws_manager.disconnect(websocket, room=f"task:{task_id}")
183
-
184
-
185
- @app.websocket("/ws/logs")
186
- async def ws_logs(websocket: WebSocket):
187
- await ws_manager.connect(websocket, room="logs")
188
- try:
189
- while True:
190
- data = await websocket.receive_text()
191
- msg = json.loads(data)
192
- if msg.get("type") == "ping":
193
- await websocket.send_json({"type": "pong", "timestamp": time.time()})
194
- except WebSocketDisconnect:
195
- ws_manager.disconnect(websocket, room="logs")
196
-
197
-
198
- @app.websocket("/ws/chat/{session_id}")
199
- async def ws_chat(websocket: WebSocket, session_id: str):
200
- await ws_manager.connect(websocket, room=f"chat:{session_id}")
201
- try:
202
- while True:
203
- data = await websocket.receive_text()
204
- msg = json.loads(data)
205
- if msg.get("type") == "ping":
206
- await websocket.send_json({"type": "pong", "timestamp": time.time()})
207
- elif msg.get("type") == "chat_message":
208
- asyncio.create_task(
209
- orchestrator.orchestrate(
210
- user_message=msg.get("content", ""),
211
- session_id=session_id,
212
- context=msg.get("context", {}),
213
- )
214
- )
215
- elif msg.get("type") == "task_message":
216
- from core.models import TaskCreateRequest
217
- req = TaskCreateRequest(
218
- goal=msg.get("content", ""),
219
- session_id=session_id,
220
- )
221
- asyncio.create_task(task_engine.submit(req))
222
- except WebSocketDisconnect:
223
- ws_manager.disconnect(websocket, room=f"chat:{session_id}")
224
-
225
-
226
- @app.websocket("/ws/agent/status")
227
- async def ws_agent_status(websocket: WebSocket):
228
- await ws_manager.connect(websocket, room="agent_status")
229
- try:
230
- while True:
231
- data = await websocket.receive_text()
232
- msg = json.loads(data)
233
- if msg.get("type") == "ping":
234
- await websocket.send_json({"type": "pong", "timestamp": time.time()})
235
- elif msg.get("type") == "get_status":
236
- await websocket.send_json({
237
- "type": "agent_status",
238
- "data": orchestrator.get_status(),
239
- })
240
- except WebSocketDisconnect:
241
- ws_manager.disconnect(websocket, room="agent_status")
242
-
243
-
244
- @app.websocket("/ws/sandbox/{session_id}")
245
- async def ws_sandbox(websocket: WebSocket, session_id: str):
246
- await ws_manager.connect(websocket, room=f"sandbox:{session_id}")
247
- sandbox = orchestrator.get_agent("sandbox")
248
- try:
249
- while True:
250
- data = await websocket.receive_text()
251
- msg = json.loads(data)
252
- if msg.get("type") == "ping":
253
- await websocket.send_json({"type": "pong", "timestamp": time.time()})
254
- elif msg.get("type") == "execute" and sandbox:
255
- cmd = msg.get("command", "")
256
- result = await sandbox.execute(cmd, session_id=session_id)
257
- await websocket.send_json({
258
- "type": "terminal_output",
259
- "command": cmd,
260
- "output": result,
261
- "timestamp": time.time(),
262
- })
263
- except WebSocketDisconnect:
264
- ws_manager.disconnect(websocket, room=f"sandbox:{session_id}")
265
-
266
-
267
- # ─── v7 New Endpoints ──────────────────────────────────────────────────────────
268
- @app.post("/api/v1/browser/research")
269
- async def browser_research(request: Request):
270
- body = await request.json()
271
- query = body.get("query", "")
272
- session_id = body.get("session_id", "")
273
- browser = orchestrator.get_agent("browser")
274
- if not browser:
275
- raise HTTPException(status_code=503, detail="BrowserAgent not available")
276
- result = await browser.run(query, session_id=session_id)
277
- return {"result": result}
278
-
279
-
280
- @app.get("/api/v1/files/workspace")
281
- async def list_workspace():
282
- file_agent = orchestrator.get_agent("file")
283
- if not file_agent:
284
- return {"workspace": "/tmp/god_workspace", "files": [], "total": 0}
285
- return file_agent.list_workspace()
286
-
287
-
288
- @app.post("/api/v1/git/pr")
289
- async def create_pr(request: Request):
290
- body = await request.json()
291
- git_agent = orchestrator.get_agent("git")
292
- if not git_agent:
293
- raise HTTPException(status_code=503, detail="GitAgent not available")
294
- result = await git_agent.create_github_pr(
295
- repo_owner=body.get("owner", ""),
296
- repo_name=body.get("repo", ""),
297
- title=body.get("title", ""),
298
- body=body.get("body", ""),
299
- head_branch=body.get("head_branch", "main"),
300
- base_branch=body.get("base_branch", "main"),
301
- )
302
- return result
303
-
304
-
305
- @app.post("/api/v1/vision/generate")
306
- async def generate_ui(request: Request):
307
- body = await request.json()
308
- vision = orchestrator.get_agent("vision")
309
- if not vision:
310
- raise HTTPException(status_code=503, detail="VisionAgent not available")
311
- result = await vision.run(
312
- body.get("prompt", ""),
313
- context=body.get("context", {}),
314
- session_id=body.get("session_id", ""),
315
- )
316
- return {"result": result}
317
-
318
-
319
- # ─── Root ──────────────────────────────────────────────────────────────────────
320
- @app.get("/")
321
- async def root():
322
- cs = connector_manager.get_summary()
323
- status = orchestrator.get_status()
324
- return {
325
- "name": "🤖 GOD AGENT OS v7",
326
- "version": "7.0.0",
327
- "status": "operational",
328
- "mode": "autonomous_engineering_os",
329
- "description": "Manus + Genspark + Devin (OneHand) — Autonomous Engineering Platform",
330
- "agents": status["agents"],
331
- "total_agents": status["total_agents"],
332
- "capabilities": status["capabilities"],
333
- "connectors": {
334
- "connected": cs["connected"],
335
- "total": cs["total"],
336
- "ai_ready": cs["ai_ready"],
337
- },
338
- "docs": "/api/docs",
339
- "websockets": [
340
- "/ws/tasks/{task_id}",
341
- "/ws/logs",
342
- "/ws/chat/{session_id}",
343
- "/ws/agent/status",
344
- "/ws/sandbox/{session_id}",
345
- ],
346
- "v7_new_features": [
347
- "🌐 BrowserAgent — Web research & scraping",
348
- "📁 FileAgent — Full file system control & project scaffolding",
349
- "🔀 GitAgent — Autonomous Git & GitHub PR operations",
350
- "🧪 TestAgent — Auto test generation & execution",
351
- "🎨 VisionAgent — Design-to-code UI generation",
352
- "⚡ 16-agent parallel orchestration",
353
- "🔄 Advanced self-healing loop",
354
- "🧠 Enhanced intent classification",
355
- "📊 Real-time execution timeline",
356
- ],
357
- }
358
-
359
-
360
- if __name__ == "__main__":
361
- import uvicorn
362
- port = int(os.environ.get("PORT", 8000))
363
- uvicorn.run("main_v7:app", host="0.0.0.0", port=port, reload=False, workers=1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
_legacy/main_v8.py DELETED
@@ -1,326 +0,0 @@
1
- """
2
- 🚀 GOD AGENT OS v8 — Autonomous Engineering Operating System
3
- Manus + Genspark + Devin (OneHand) Combined
4
- Version: 8.0.0 — KeyPool Multi-API Routing (Gemini + SambaNova Primary LLMs)
5
- """
6
-
7
- import asyncio
8
- import json
9
- import os
10
- import time
11
- import uuid
12
- from contextlib import asynccontextmanager
13
- from typing import Optional
14
-
15
- import structlog
16
- from fastapi import FastAPI, WebSocket, WebSocketDisconnect, HTTPException, Request
17
- from fastapi.middleware.cors import CORSMiddleware
18
- from fastapi.middleware.gzip import GZipMiddleware
19
- from fastapi.responses import JSONResponse
20
- from slowapi import Limiter, _rate_limit_exceeded_handler
21
- from slowapi.util import get_remote_address
22
- from slowapi.errors import RateLimitExceeded
23
-
24
- from api.routes import tasks, chat, memory, github, health
25
- from api.routes import connectors, agents as agents_router
26
- from api.websocket_manager import WebSocketManager
27
- from core.task_engine import TaskEngine
28
- from memory.db import init_db
29
-
30
- # ─── v8 AI Router (KeyPool-based) ─────────────────────────────────────────────
31
- from ai_router.router_v8 import AIRouterV8
32
-
33
- # ─── Agent Ecosystem ──────────────────────────────────────────────────────────
34
- from agents.orchestrator_v7 import GodAgentOrchestratorV7
35
- from agents.chat_agent import ChatAgent
36
- from agents.planner_agent import PlannerAgent
37
- from agents.coding_agent import CodingAgent
38
- from agents.debug_agent import DebugAgent
39
- from agents.memory_agent import MemoryAgent
40
- from agents.connector_agent import ConnectorAgent
41
- from agents.deploy_agent import DeployAgent
42
- from agents.workflow_agent import WorkflowAgent
43
- from agents.sandbox_agent import SandboxAgent
44
- from agents.ui_agent import UIAgent
45
- from agents.reasoning_agent import ReasoningAgent
46
- from agents.browser_agent import BrowserAgent
47
- from agents.file_agent import FileAgent
48
- from agents.git_agent import GitAgent
49
- from agents.test_agent import TestAgent
50
- from agents.vision_agent import VisionAgent
51
- from connectors.manager import ConnectorManager
52
-
53
- # ─── Structured Logging ───────────────────────────────────────────────────────
54
- structlog.configure(
55
- processors=[
56
- structlog.processors.TimeStamper(fmt="iso"),
57
- structlog.stdlib.add_log_level,
58
- structlog.processors.StackInfoRenderer(),
59
- structlog.dev.ConsoleRenderer(),
60
- ]
61
- )
62
- log = structlog.get_logger()
63
-
64
- limiter = Limiter(key_func=get_remote_address)
65
-
66
- # ─── Global Managers ──────────────────────────────────────────────────────────
67
- ws_manager = WebSocketManager()
68
- task_engine = TaskEngine(ws_manager)
69
- ai_router = AIRouterV8(ws_manager)
70
- connector_manager = ConnectorManager()
71
-
72
-
73
- def build_orchestrator() -> GodAgentOrchestratorV7:
74
- orchestrator = GodAgentOrchestratorV7(ws_manager=ws_manager, ai_router=ai_router)
75
- orchestrator.register_agent("chat", ChatAgent(ws_manager, ai_router))
76
- orchestrator.register_agent("planner", PlannerAgent(ws_manager, ai_router))
77
- orchestrator.register_agent("coding", CodingAgent(ws_manager, ai_router))
78
- orchestrator.register_agent("debug", DebugAgent(ws_manager, ai_router))
79
- orchestrator.register_agent("memory", MemoryAgent(ws_manager, ai_router))
80
- orchestrator.register_agent("connector", ConnectorAgent(ws_manager, ai_router))
81
- orchestrator.register_agent("deploy", DeployAgent(ws_manager, ai_router))
82
- orchestrator.register_agent("workflow", WorkflowAgent(ws_manager, ai_router))
83
- orchestrator.register_agent("sandbox", SandboxAgent(ws_manager, ai_router))
84
- orchestrator.register_agent("ui", UIAgent(ws_manager, ai_router))
85
- orchestrator.register_agent("reasoning", ReasoningAgent(ws_manager, ai_router))
86
- orchestrator.register_agent("browser", BrowserAgent(ws_manager, ai_router))
87
- orchestrator.register_agent("file", FileAgent(ws_manager, ai_router))
88
- orchestrator.register_agent("git", GitAgent(ws_manager, ai_router))
89
- orchestrator.register_agent("test", TestAgent(ws_manager, ai_router))
90
- orchestrator.register_agent("vision", VisionAgent(ws_manager, ai_router))
91
- log.info("🤖 GOD AGENT v8 Ecosystem initialized", agents=16)
92
- return orchestrator
93
-
94
-
95
- orchestrator = build_orchestrator()
96
-
97
-
98
- @asynccontextmanager
99
- async def lifespan(app: FastAPI):
100
- log.info("🚀 Starting GOD AGENT OS v8 — KeyPool Multi-API Edition...")
101
- await init_db()
102
- await task_engine.start()
103
- asyncio.create_task(ws_manager.heartbeat_loop())
104
- # Print router status
105
- stats = ai_router.get_stats()
106
- active = [name for name, s in stats.items() if s["available"]]
107
- log.info("✅ GOD AGENT v8 — 16 agents online")
108
- log.info(f"🔑 Active AI providers: {active}")
109
- log.info("🌐 AI Routing: SambaNova → Gemini → OpenAI → Groq → Cerebras → OpenRouter → Anthropic")
110
- yield
111
- log.info("🛑 Shutting down GOD AGENT v8...")
112
- await task_engine.stop()
113
-
114
-
115
- app = FastAPI(
116
- title="🤖 GOD AGENT OS v8",
117
- description="Autonomous Engineering OS — Gemini + SambaNova KeyPool Multi-API Routing",
118
- version="8.0.0",
119
- lifespan=lifespan,
120
- docs_url="/api/docs",
121
- redoc_url="/api/redoc",
122
- )
123
-
124
- app.state.limiter = limiter
125
- app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
126
- app.state.ws_manager = ws_manager
127
- app.state.task_engine = task_engine
128
- app.state.ai_router = ai_router
129
- app.state.orchestrator = orchestrator
130
- app.state.connector_manager = connector_manager
131
-
132
- app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"])
133
- app.add_middleware(GZipMiddleware, minimum_size=1000)
134
-
135
-
136
- @app.middleware("http")
137
- async def log_requests(request: Request, call_next):
138
- start = time.time()
139
- response = await call_next(request)
140
- ms = round((time.time() - start) * 1000, 2)
141
- log.info("HTTP", method=request.method, path=request.url.path, status=response.status_code, ms=ms)
142
- return response
143
-
144
-
145
- # ─── REST Routers ─────────────────────────────────────────────────────────────
146
- app.include_router(health.router, prefix="/api/v1", tags=["health"])
147
- app.include_router(tasks.router, prefix="/api/v1/tasks", tags=["tasks"])
148
- app.include_router(chat.router, prefix="/api/v1", tags=["chat"])
149
- app.include_router(memory.router, prefix="/api/v1/memory", tags=["memory"])
150
- app.include_router(github.router, prefix="/api/v1/github", tags=["github"])
151
- app.include_router(connectors.router, prefix="/api/v1/connectors", tags=["connectors"])
152
- app.include_router(agents_router.router, prefix="/api/v1/agents", tags=["agents"])
153
-
154
-
155
- # ─── WebSocket Endpoints ──────────────────────────────────────────────────────
156
- @app.websocket("/ws/tasks/{task_id}")
157
- async def ws_task(websocket: WebSocket, task_id: str):
158
- await ws_manager.connect(websocket, room=f"task:{task_id}")
159
- try:
160
- while True:
161
- data = await websocket.receive_text()
162
- msg = json.loads(data)
163
- if msg.get("type") == "ping":
164
- await websocket.send_json({"type": "pong", "timestamp": time.time()})
165
- except WebSocketDisconnect:
166
- ws_manager.disconnect(websocket, room=f"task:{task_id}")
167
-
168
-
169
- @app.websocket("/ws/logs")
170
- async def ws_logs(websocket: WebSocket):
171
- await ws_manager.connect(websocket, room="logs")
172
- try:
173
- while True:
174
- data = await websocket.receive_text()
175
- msg = json.loads(data)
176
- if msg.get("type") == "ping":
177
- await websocket.send_json({"type": "pong", "timestamp": time.time()})
178
- except WebSocketDisconnect:
179
- ws_manager.disconnect(websocket, room="logs")
180
-
181
-
182
- @app.websocket("/ws/chat/{session_id}")
183
- async def ws_chat(websocket: WebSocket, session_id: str):
184
- await ws_manager.connect(websocket, room=f"chat:{session_id}")
185
- try:
186
- while True:
187
- data = await websocket.receive_text()
188
- msg = json.loads(data)
189
- if msg.get("type") == "ping":
190
- await websocket.send_json({"type": "pong", "timestamp": time.time()})
191
- elif msg.get("type") == "chat_message":
192
- asyncio.create_task(orchestrator.orchestrate(
193
- user_message=msg.get("content", ""),
194
- session_id=session_id,
195
- context=msg.get("context", {}),
196
- ))
197
- elif msg.get("type") == "task_message":
198
- from core.models import TaskCreateRequest
199
- req = TaskCreateRequest(goal=msg.get("content", ""), session_id=session_id)
200
- asyncio.create_task(task_engine.submit(req))
201
- except WebSocketDisconnect:
202
- ws_manager.disconnect(websocket, room=f"chat:{session_id}")
203
-
204
-
205
- @app.websocket("/ws/agent/status")
206
- async def ws_agent_status(websocket: WebSocket):
207
- await ws_manager.connect(websocket, room="agent_status")
208
- try:
209
- while True:
210
- data = await websocket.receive_text()
211
- msg = json.loads(data)
212
- if msg.get("type") == "ping":
213
- await websocket.send_json({"type": "pong", "timestamp": time.time()})
214
- elif msg.get("type") == "get_status":
215
- await websocket.send_json({"type": "agent_status", "data": orchestrator.get_status()})
216
- except WebSocketDisconnect:
217
- ws_manager.disconnect(websocket, room="agent_status")
218
-
219
-
220
- @app.websocket("/ws/sandbox/{session_id}")
221
- async def ws_sandbox(websocket: WebSocket, session_id: str):
222
- await ws_manager.connect(websocket, room=f"sandbox:{session_id}")
223
- sandbox = orchestrator.get_agent("sandbox")
224
- try:
225
- while True:
226
- data = await websocket.receive_text()
227
- msg = json.loads(data)
228
- if msg.get("type") == "ping":
229
- await websocket.send_json({"type": "pong", "timestamp": time.time()})
230
- elif msg.get("type") == "execute" and sandbox:
231
- cmd = msg.get("command", "")
232
- result = await sandbox.execute(cmd, session_id=session_id)
233
- await websocket.send_json({"type": "terminal_output", "command": cmd, "output": result, "timestamp": time.time()})
234
- except WebSocketDisconnect:
235
- ws_manager.disconnect(websocket, room=f"sandbox:{session_id}")
236
-
237
-
238
- # ─── v8 Key Pool & AI Router Status Endpoints ─────────────────────────────────
239
- @app.get("/api/v1/ai/stats")
240
- async def get_ai_stats():
241
- return {"stats": ai_router.get_stats()}
242
-
243
-
244
- @app.get("/api/v1/ai/pool-status")
245
- async def get_pool_status():
246
- return {"pools": ai_router.get_pool_status()}
247
-
248
-
249
- @app.post("/api/v1/browser/research")
250
- async def browser_research(request: Request):
251
- body = await request.json()
252
- browser = orchestrator.get_agent("browser")
253
- if not browser:
254
- raise HTTPException(status_code=503, detail="BrowserAgent not available")
255
- result = await browser.run(body.get("query", ""), session_id=body.get("session_id", ""))
256
- return {"result": result}
257
-
258
-
259
- @app.get("/api/v1/files/workspace")
260
- async def list_workspace():
261
- file_agent = orchestrator.get_agent("file")
262
- if not file_agent:
263
- return {"workspace": "/tmp/god_workspace", "files": [], "total": 0}
264
- return file_agent.list_workspace()
265
-
266
-
267
- @app.post("/api/v1/git/pr")
268
- async def create_pr(request: Request):
269
- body = await request.json()
270
- git_agent = orchestrator.get_agent("git")
271
- if not git_agent:
272
- raise HTTPException(status_code=503, detail="GitAgent not available")
273
- result = await git_agent.create_github_pr(
274
- repo_owner=body.get("owner", ""),
275
- repo_name=body.get("repo", ""),
276
- title=body.get("title", ""),
277
- body=body.get("body", ""),
278
- head_branch=body.get("head_branch", "main"),
279
- base_branch=body.get("base_branch", "main"),
280
- )
281
- return result
282
-
283
-
284
- @app.post("/api/v1/vision/generate")
285
- async def generate_ui(request: Request):
286
- body = await request.json()
287
- vision = orchestrator.get_agent("vision")
288
- if not vision:
289
- raise HTTPException(status_code=503, detail="VisionAgent not available")
290
- result = await vision.run(body.get("prompt", ""), context=body.get("context", {}), session_id=body.get("session_id", ""))
291
- return {"result": result}
292
-
293
-
294
- # ─── Root ─────────────────────────────────────────────────────────────────────
295
- @app.get("/")
296
- async def root():
297
- cs = connector_manager.get_summary()
298
- status = orchestrator.get_status()
299
- stats = ai_router.get_stats()
300
- active_providers = [name for name, s in stats.items() if s["available"]]
301
- return {
302
- "name": "🤖 GOD AGENT OS v8",
303
- "version": "8.0.0",
304
- "status": "operational",
305
- "mode": "autonomous_engineering_os",
306
- "description": "KeyPool Multi-API Routing — Gemini + SambaNova Primary LLMs",
307
- "agents": status["agents"],
308
- "total_agents": status["total_agents"],
309
- "ai_providers": active_providers,
310
- "connectors": {"connected": cs["connected"], "total": cs["total"]},
311
- "docs": "/api/docs",
312
- "v8_features": [
313
- "🔑 KeyPool multi-key management (Gemini 6 keys + SambaNova 9 keys)",
314
- "🔄 Automatic key failover with cooldown tracking",
315
- "⚡ SambaNova → Gemini → OpenAI → Groq → Cerebras chain",
316
- "📊 Per-key usage stats & health monitoring",
317
- "🤖 16-agent autonomous fleet",
318
- "🌐 Real-time streaming via WebSocket",
319
- ],
320
- }
321
-
322
-
323
- if __name__ == "__main__":
324
- import uvicorn
325
- port = int(os.environ.get("PORT", 8000))
326
- uvicorn.run("main_v8:app", host="0.0.0.0", port=port, reload=False, workers=1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
_legacy/main_v9.py DELETED
@@ -1,417 +0,0 @@
1
- """
2
- 🚀 GOD AGENT OS v10 — Distributed 22-Space Agent OS
3
- Powered by Pyae Sone
4
- """
5
-
6
- import asyncio
7
- import json
8
- import os
9
- import time
10
- import uuid
11
- from contextlib import asynccontextmanager
12
- from typing import Optional
13
-
14
- import structlog
15
- from fastapi import FastAPI, WebSocket, WebSocketDisconnect, HTTPException, Request
16
- from fastapi.middleware.cors import CORSMiddleware
17
- from fastapi.middleware.gzip import GZipMiddleware
18
- from fastapi.responses import JSONResponse
19
- from slowapi import Limiter, _rate_limit_exceeded_handler
20
- from slowapi.util import get_remote_address
21
- from slowapi.errors import RateLimitExceeded
22
-
23
- from api.routes import tasks, chat, memory, health
24
- from api.routes import connectors, agents as agents_router
25
- from api.websocket_manager import WebSocketManager
26
- from core.task_engine import TaskEngine
27
- from memory.db import init_db
28
-
29
- # ─── v10 AI Router (Gemini + SambaNova + GitHub KeyPool routing) ─────────────
30
- from ai_router.router_v10 import AIRouterV10 as AIRouterV8
31
-
32
- # ─── v9 Agent Kernel & Spaces ─────────────────────────────────────────────────
33
- from kernel.agent_kernel import AgentKernel
34
- from spaces import SPACE_CATALOG, build_all_spaces
35
-
36
- # ─── Legacy Agent Ecosystem (backward compatibility) ──────────────────────────
37
- from agents.orchestrator_v7 import GodAgentOrchestratorV7
38
- from agents.chat_agent import ChatAgent
39
- from agents.planner_agent import PlannerAgent
40
- from agents.coding_agent import CodingAgent
41
- from agents.debug_agent import DebugAgent
42
- from agents.memory_agent import MemoryAgent
43
- from agents.connector_agent import ConnectorAgent
44
- from agents.deploy_agent import DeployAgent
45
- from agents.workflow_agent import WorkflowAgent
46
- from agents.sandbox_agent import SandboxAgent
47
- from agents.ui_agent import UIAgent
48
- from agents.reasoning_agent import ReasoningAgent
49
- from agents.browser_agent import BrowserAgent
50
- from agents.file_agent import FileAgent
51
- from agents.git_agent import GitAgent
52
- from agents.test_agent import TestAgent
53
- from agents.vision_agent import VisionAgent
54
- from connectors.manager import ConnectorManager
55
-
56
- # ─── API Routes ───────────────────────────────────────────────────────────────
57
- from api.routes import github
58
-
59
- # ─── Structured Logging ───────────────────────────────────────────────────────
60
- structlog.configure(
61
- processors=[
62
- structlog.processors.TimeStamper(fmt="iso"),
63
- structlog.stdlib.add_log_level,
64
- structlog.processors.StackInfoRenderer(),
65
- structlog.dev.ConsoleRenderer(),
66
- ]
67
- )
68
- log = structlog.get_logger()
69
-
70
- limiter = Limiter(key_func=get_remote_address)
71
-
72
- # ─── Global Managers ──────────────────────────────────────────────────────────
73
- ws_manager = WebSocketManager()
74
- task_engine = TaskEngine(ws_manager)
75
- ai_router = AIRouterV8(ws_manager)
76
- connector_manager = ConnectorManager()
77
-
78
-
79
- def build_kernel() -> AgentKernel:
80
- """Build and configure the distributed 22-space Agent Kernel."""
81
- kernel = AgentKernel(ws_manager=ws_manager, ai_router=ai_router)
82
- for space_name, space_instance in build_all_spaces(ws_manager=ws_manager, ai_router=ai_router).items():
83
- kernel.register_space(space_name, space_instance)
84
- log.info("🧠 GOD AGENT OS distributed kernel initialized", spaces=len(SPACE_CATALOG))
85
- return kernel
86
-
87
-
88
- def build_legacy_orchestrator() -> GodAgentOrchestratorV7:
89
- """Build legacy v7 orchestrator for backward compatibility."""
90
- orchestrator = GodAgentOrchestratorV7(ws_manager=ws_manager, ai_router=ai_router)
91
- orchestrator.register_agent("chat", ChatAgent(ws_manager, ai_router))
92
- orchestrator.register_agent("planner", PlannerAgent(ws_manager, ai_router))
93
- orchestrator.register_agent("coding", CodingAgent(ws_manager, ai_router))
94
- orchestrator.register_agent("debug", DebugAgent(ws_manager, ai_router))
95
- orchestrator.register_agent("memory", MemoryAgent(ws_manager, ai_router))
96
- orchestrator.register_agent("connector", ConnectorAgent(ws_manager, ai_router))
97
- orchestrator.register_agent("deploy", DeployAgent(ws_manager, ai_router))
98
- orchestrator.register_agent("workflow", WorkflowAgent(ws_manager, ai_router))
99
- orchestrator.register_agent("sandbox", SandboxAgent(ws_manager, ai_router))
100
- orchestrator.register_agent("ui", UIAgent(ws_manager, ai_router))
101
- orchestrator.register_agent("reasoning", ReasoningAgent(ws_manager, ai_router))
102
- orchestrator.register_agent("browser", BrowserAgent(ws_manager, ai_router))
103
- orchestrator.register_agent("file", FileAgent(ws_manager, ai_router))
104
- orchestrator.register_agent("git", GitAgent(ws_manager, ai_router))
105
- orchestrator.register_agent("test", TestAgent(ws_manager, ai_router))
106
- orchestrator.register_agent("vision", VisionAgent(ws_manager, ai_router))
107
- log.info("🤖 Legacy v7 Orchestrator initialized", agents=16)
108
- return orchestrator
109
-
110
-
111
- # Initialize both kernel and legacy orchestrator
112
- kernel = build_kernel()
113
- orchestrator = build_legacy_orchestrator()
114
-
115
-
116
- @asynccontextmanager
117
- async def lifespan(app: FastAPI):
118
- log.info("🚀 Starting GOD AGENT OS v10 — Distributed 22-Space Architecture...")
119
- await init_db()
120
- await task_engine.start()
121
- asyncio.create_task(ws_manager.heartbeat_loop())
122
- stats = ai_router.get_stats()
123
- active = [name for name, s in stats.items() if s["available"]]
124
- log.info("✅ GOD AGENT v10 — 22 Spaces + 16 Legacy Agents online")
125
- log.info(f"🔑 Active AI providers: {active}")
126
- log.info("🌐 Routing: SambaNova → Gemini → OpenAI → Groq → Cerebras")
127
- log.info("📦 Spaces: distributed 22-space runtime online")
128
- yield
129
- log.info("🛑 Shutting down GOD AGENT OS v9...")
130
- await task_engine.stop()
131
-
132
-
133
- app = FastAPI(
134
- title="🤖 GOD AGENT OS v10",
135
- description="Distributed 22-Space Autonomous Agent OS | Powered by Pyae Sone",
136
- version="10.0.0",
137
- lifespan=lifespan,
138
- docs_url="/api/docs",
139
- redoc_url="/api/redoc",
140
- )
141
-
142
- app.state.limiter = limiter
143
- app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
144
- app.state.ws_manager = ws_manager
145
- app.state.task_engine = task_engine
146
- app.state.ai_router = ai_router
147
- app.state.kernel = kernel
148
- app.state.orchestrator = orchestrator
149
- app.state.connector_manager = connector_manager
150
-
151
- app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"])
152
- app.add_middleware(GZipMiddleware, minimum_size=1000)
153
-
154
-
155
- @app.middleware("http")
156
- async def log_requests(request: Request, call_next):
157
- start = time.time()
158
- response = await call_next(request)
159
- ms = round((time.time() - start) * 1000, 2)
160
- log.info("HTTP", method=request.method, path=request.url.path, status=response.status_code, ms=ms)
161
- return response
162
-
163
-
164
- # ─── REST Routers ─────────────────────────────────────────────────────────────
165
- app.include_router(health.router, prefix="/api/v1", tags=["health"])
166
- app.include_router(tasks.router, prefix="/api/v1/tasks", tags=["tasks"])
167
- app.include_router(chat.router, prefix="/api/v1", tags=["chat"])
168
- app.include_router(memory.router, prefix="/api/v1/memory", tags=["memory"])
169
- app.include_router(github.router, prefix="/api/v1/github", tags=["github"])
170
- app.include_router(connectors.router, prefix="/api/v1/connectors", tags=["connectors"])
171
- app.include_router(agents_router.router, prefix="/api/v1/agents", tags=["agents"])
172
-
173
-
174
- # ─── WebSocket: Chat (v9 Kernel-powered) ──────────────────────────────────────
175
- @app.websocket("/ws/chat/{session_id}")
176
- async def ws_chat(websocket: WebSocket, session_id: str):
177
- await ws_manager.connect(websocket, room=f"chat:{session_id}")
178
- try:
179
- while True:
180
- data = await websocket.receive_text()
181
- msg = json.loads(data)
182
-
183
- if msg.get("type") == "ping":
184
- await websocket.send_json({"type": "pong", "timestamp": time.time()})
185
-
186
- elif msg.get("type") == "chat_message":
187
- # Route through v9 Agent Kernel
188
- asyncio.create_task(kernel.orchestrate(
189
- user_message=msg.get("content", ""),
190
- session_id=session_id,
191
- context=msg.get("context", {}),
192
- ))
193
-
194
- elif msg.get("type") == "task_message":
195
- from core.models import TaskCreateRequest
196
- req = TaskCreateRequest(goal=msg.get("content", ""), session_id=session_id)
197
- asyncio.create_task(task_engine.submit(req))
198
-
199
- except WebSocketDisconnect:
200
- ws_manager.disconnect(websocket, room=f"chat:{session_id}")
201
-
202
-
203
- @app.websocket("/ws/tasks/{task_id}")
204
- async def ws_task(websocket: WebSocket, task_id: str):
205
- await ws_manager.connect(websocket, room=f"task:{task_id}")
206
- try:
207
- while True:
208
- data = await websocket.receive_text()
209
- msg = json.loads(data)
210
- if msg.get("type") == "ping":
211
- await websocket.send_json({"type": "pong", "timestamp": time.time()})
212
- except WebSocketDisconnect:
213
- ws_manager.disconnect(websocket, room=f"task:{task_id}")
214
-
215
-
216
- @app.websocket("/ws/logs")
217
- async def ws_logs(websocket: WebSocket):
218
- await ws_manager.connect(websocket, room="logs")
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="logs")
227
-
228
-
229
- @app.websocket("/ws/agent/status")
230
- async def ws_agent_status(websocket: WebSocket):
231
- await ws_manager.connect(websocket, room="agent_status")
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
- elif msg.get("type") == "get_status":
239
- await websocket.send_json({
240
- "type": "agent_status",
241
- "data": kernel.get_status(),
242
- "legacy": orchestrator.get_status(),
243
- })
244
- except WebSocketDisconnect:
245
- ws_manager.disconnect(websocket, room="agent_status")
246
-
247
-
248
- @app.websocket("/ws/sandbox/{session_id}")
249
- async def ws_sandbox(websocket: WebSocket, session_id: str):
250
- await ws_manager.connect(websocket, room=f"sandbox:{session_id}")
251
- sandbox_space = kernel.get_space("sandbox")
252
- try:
253
- while True:
254
- data = await websocket.receive_text()
255
- msg = json.loads(data)
256
- if msg.get("type") == "ping":
257
- await websocket.send_json({"type": "pong", "timestamp": time.time()})
258
- elif msg.get("type") == "execute" and sandbox_space:
259
- cmd = msg.get("command", "")
260
- result = await sandbox_space._run_shell(cmd)
261
- await websocket.send_json({
262
- "type": "terminal_output",
263
- "command": cmd,
264
- "output": result,
265
- "timestamp": time.time()
266
- })
267
- except WebSocketDisconnect:
268
- ws_manager.disconnect(websocket, room=f"sandbox:{session_id}")
269
-
270
-
271
- # ─── v9 Space-Role API Endpoints ──────────────────────────────────────────────
272
- @app.get("/api/v1/kernel/status")
273
- async def kernel_status():
274
- """Get Agent Kernel status."""
275
- return {
276
- "kernel": kernel.get_status(),
277
- "ai_providers": ai_router.get_stats(),
278
- }
279
-
280
-
281
- @app.get("/api/v1/spaces")
282
- async def list_spaces():
283
- """List all available Spaces."""
284
- spaces_info = {}
285
- for name, space in kernel._spaces.items():
286
- spaces_info[name] = space.get_info()
287
- return {"spaces": spaces_info, "total": len(spaces_info)}
288
-
289
-
290
- @app.post("/api/v1/spaces/{space_name}/execute")
291
- async def execute_in_space(space_name: str, request: Request):
292
- """Execute a task in a specific Space."""
293
- body = await request.json()
294
- task = body.get("task", "")
295
- role = body.get("role", "cognition")
296
- session_id = body.get("session_id", "api")
297
-
298
- space = kernel.get_space(space_name)
299
- if not space:
300
- raise HTTPException(status_code=404, detail=f"Space '{space_name}' not found")
301
-
302
- result = await space.execute(task=task, role=role, session_id=session_id, context=body.get("context", {}))
303
- return {"space": space_name, "role": role, "result": result}
304
-
305
-
306
- @app.post("/api/v1/kernel/orchestrate")
307
- async def kernel_orchestrate(request: Request):
308
- """Main orchestration endpoint."""
309
- body = await request.json()
310
- result = await kernel.orchestrate(
311
- user_message=body.get("message", ""),
312
- session_id=body.get("session_id", "api"),
313
- context=body.get("context", {}),
314
- )
315
- return {"result": result}
316
-
317
-
318
- # ─── Legacy v8 Endpoints (backward compatibility) ─────────────────────────────
319
- @app.get("/api/v1/ai/stats")
320
- async def get_ai_stats():
321
- return {"stats": ai_router.get_stats()}
322
-
323
-
324
- @app.get("/api/v1/ai/pool-status")
325
- async def get_pool_status():
326
- return {"pools": ai_router.get_pool_status()}
327
-
328
-
329
- @app.post("/api/v1/browser/research")
330
- async def browser_research(request: Request):
331
- body = await request.json()
332
- browser_space = kernel.get_space("browser")
333
- if not browser_space:
334
- raise HTTPException(status_code=503, detail="Browser Space not available")
335
- result = await browser_space.execute(
336
- task=body.get("query", ""),
337
- role="automation",
338
- session_id=body.get("session_id", "api"),
339
- )
340
- return {"result": result}
341
-
342
-
343
- @app.get("/api/v1/files/workspace")
344
- async def list_workspace():
345
- file_agent = orchestrator.get_agent("file")
346
- if not file_agent:
347
- return {"workspace": "/tmp/god_workspace", "files": [], "total": 0}
348
- return file_agent.list_workspace()
349
-
350
-
351
- @app.post("/api/v1/git/pr")
352
- async def create_pr(request: Request):
353
- body = await request.json()
354
- git_agent = orchestrator.get_agent("git")
355
- if not git_agent:
356
- raise HTTPException(status_code=503, detail="GitAgent not available")
357
- result = await git_agent.create_github_pr(
358
- repo_owner=body.get("owner", ""),
359
- repo_name=body.get("repo", ""),
360
- title=body.get("title", ""),
361
- body=body.get("body", ""),
362
- head_branch=body.get("head_branch", "main"),
363
- base_branch=body.get("base_branch", "main"),
364
- )
365
- return result
366
-
367
-
368
- @app.post("/api/v1/vision/generate")
369
- async def generate_ui(request: Request):
370
- body = await request.json()
371
- vision_space = kernel.get_space("vision")
372
- if not vision_space:
373
- raise HTTPException(status_code=503, detail="Vision Space not available")
374
- result = await vision_space.execute(
375
- task=body.get("prompt", ""),
376
- role="visual_intelligence",
377
- session_id=body.get("session_id", "api"),
378
- )
379
- return {"result": result}
380
-
381
-
382
- # ─── Root ─────────────────────────────────────────────────────────────────────
383
- @app.get("/")
384
- async def root():
385
- cs = connector_manager.get_summary()
386
- kernel_status_data = kernel.get_status()
387
- stats = ai_router.get_stats()
388
- active_providers = [name for name, s in stats.items() if s["available"]]
389
- return {
390
- "name": "🤖 GOD AGENT OS v10",
391
- "version": "10.0.0",
392
- "status": "operational",
393
- "mode": "general_autonomous_agent_os",
394
- "description": "Distributed 22-Space Architecture | Powered by Pyae Sone",
395
- "architecture": "Distributed Worker Space Paradigm",
396
- "spaces": kernel_status_data["spaces"],
397
- "total_spaces": kernel_status_data["total_spaces"],
398
- "ai_providers": active_providers,
399
- "connectors": {"connected": cs["connected"], "total": cs["total"]},
400
- "docs": "/api/docs",
401
- "v9_features": [
402
- "📦 22 distributed worker spaces across cognition, execution, verification, deployment, memory, coordination, monitoring, session, and infrastructure layers",
403
- "🎭 5 Cognitive Roles: Cognition | Automation | Execution | Repair | Visual Intelligence",
404
- "🧠 God Core Space orchestrates the worker fleet",
405
- "🔑 KeyPool multi-key management (Gemini + SambaNova + GitHub)",
406
- "🔄 Automatic worker-space routing based on intent",
407
- "💾 Context Manager for session-scoped runtime state",
408
- "⚡ Backward compatible with v8/v9 agent fleet",
409
- "🌐 Real-time streaming via WebSocket",
410
- ],
411
- }
412
-
413
-
414
- if __name__ == "__main__":
415
- import uvicorn
416
- port = int(os.environ.get("PORT", 7860))
417
- uvicorn.run("main_v9:app", host="0.0.0.0", port=port, reload=False, workers=1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
agents/__init__.py DELETED
@@ -1,24 +0,0 @@
1
- # God Agent Multi-Agent System
2
- from .orchestrator import GodAgentOrchestrator
3
- from .chat_agent import ChatAgent
4
- from .planner_agent import PlannerAgent
5
- from .coding_agent import CodingAgent
6
- from .debug_agent import DebugAgent
7
- from .memory_agent import MemoryAgent
8
- from .connector_agent import ConnectorAgent
9
- from .deploy_agent import DeployAgent
10
- from .workflow_agent import WorkflowAgent
11
- from .sandbox_agent import SandboxAgent
12
-
13
- __all__ = [
14
- "GodAgentOrchestrator",
15
- "ChatAgent",
16
- "PlannerAgent",
17
- "CodingAgent",
18
- "DebugAgent",
19
- "MemoryAgent",
20
- "ConnectorAgent",
21
- "DeployAgent",
22
- "WorkflowAgent",
23
- "SandboxAgent",
24
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
agents/base_agent.py DELETED
@@ -1,54 +0,0 @@
1
- """
2
- Base Agent — Abstract base for all God Mode agents
3
- """
4
- from abc import ABC, abstractmethod
5
- from typing import Any, Dict, List, Optional
6
- import structlog
7
-
8
- log = structlog.get_logger()
9
-
10
-
11
- class BaseAgent(ABC):
12
- """Abstract base class for all agents in the God Mode ecosystem."""
13
-
14
- def __init__(self, name: str, ws_manager=None, ai_router=None):
15
- self.name = name
16
- self.ws = ws_manager
17
- self.ai_router = ai_router
18
- self.log = structlog.get_logger().bind(agent=name)
19
-
20
- @abstractmethod
21
- async def run(self, task: str, context: Dict = {}, **kwargs) -> str:
22
- """Execute the agent's primary task."""
23
- pass
24
-
25
- async def emit(self, room: str, event: str, data: Dict, session_id: str = ""):
26
- """Emit WebSocket event if manager available."""
27
- if self.ws:
28
- await self.ws.emit(room, event, data, session_id=session_id)
29
-
30
- async def emit_chat(self, session_id: str, event: str, data: Dict):
31
- """Emit chat WebSocket event."""
32
- if self.ws:
33
- await self.ws.emit_chat(session_id, event, data)
34
-
35
- async def llm(
36
- self,
37
- messages: List[Dict],
38
- task_id: str = "",
39
- session_id: str = "",
40
- temperature: float = 0.7,
41
- max_tokens: int = 4096,
42
- model: str = "",
43
- ) -> str:
44
- """Route LLM call through AI router."""
45
- if self.ai_router:
46
- return await self.ai_router.complete(
47
- messages=messages,
48
- task_id=task_id,
49
- session_id=session_id,
50
- temperature=temperature,
51
- max_tokens=max_tokens,
52
- preferred_model=model,
53
- )
54
- return f"[{self.name}] AI router not configured."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
agents/browser_agent.py DELETED
@@ -1,147 +0,0 @@
1
- """
2
- BrowserAgent v7 — Autonomous web browsing, scraping, research (Manus-style)
3
- Real browser control via Playwright/httpx for research, testing, web automation
4
- """
5
- import asyncio
6
- import json
7
- import os
8
- import re
9
- from typing import Dict, List, Optional
10
- import structlog
11
- from .base_agent import BaseAgent
12
-
13
- log = structlog.get_logger()
14
-
15
- BROWSER_SYSTEM = """You are an elite autonomous web research and browser automation agent.
16
- You can:
17
- - Search the web and extract structured information
18
- - Navigate websites and fill forms
19
- - Take screenshots and analyze visual content
20
- - Scrape and parse complex web pages
21
- - Run web automation tasks
22
-
23
- Always provide structured, actionable results with source URLs.
24
- """
25
-
26
- class BrowserAgent(BaseAgent):
27
- def __init__(self, ws_manager=None, ai_router=None):
28
- super().__init__("BrowserAgent", ws_manager, ai_router)
29
- self._session_cache: Dict[str, str] = {}
30
-
31
- async def run(self, task: str, context: Dict = {}, **kwargs) -> str:
32
- session_id = kwargs.get("session_id", "")
33
- task_id = kwargs.get("task_id", "")
34
-
35
- await self.emit(task_id, "agent_start", {
36
- "agent": "BrowserAgent",
37
- "task": task[:80],
38
- }, session_id)
39
-
40
- await self.emit(task_id, "tool_called", {
41
- "agent": "BrowserAgent",
42
- "tool": "web_research",
43
- "step": f"Researching: {task[:60]}",
44
- }, session_id)
45
-
46
- # Extract search query or URL from task
47
- urls = re.findall(r'https?://[^\s]+', task)
48
-
49
- if urls:
50
- result = await self._fetch_and_analyze(urls[0], task, task_id, session_id)
51
- else:
52
- result = await self._web_research(task, task_id, session_id)
53
-
54
- await self.emit(task_id, "browser_result", {
55
- "agent": "BrowserAgent",
56
- "result_length": len(result),
57
- }, session_id)
58
-
59
- return result
60
-
61
- async def _web_research(self, query: str, task_id: str, session_id: str) -> str:
62
- """Perform web research using AI knowledge + httpx."""
63
- import httpx
64
-
65
- # Use DuckDuckGo search API (no key needed)
66
- search_url = f"https://api.duckduckgo.com/?q={query.replace(' ', '+')}&format=json&no_html=1"
67
-
68
- try:
69
- async with httpx.AsyncClient(timeout=15, follow_redirects=True) as client:
70
- resp = await client.get(search_url, headers={"User-Agent": "GodAgent/7.0"})
71
- data = resp.json()
72
-
73
- results = []
74
- if data.get("AbstractText"):
75
- results.append(f"**Summary:** {data['AbstractText']}")
76
- if data.get("AbstractURL"):
77
- results.append(f"**Source:** {data['AbstractURL']}")
78
-
79
- related = data.get("RelatedTopics", [])[:5]
80
- if related:
81
- results.append("\n**Related:**")
82
- for r in related:
83
- if isinstance(r, dict) and r.get("Text"):
84
- results.append(f"- {r['Text'][:200]}")
85
-
86
- if results:
87
- search_context = "\n".join(results)
88
- else:
89
- search_context = f"Web search for: {query}"
90
-
91
- except Exception as e:
92
- search_context = f"Search context for: {query}"
93
-
94
- # Use AI to synthesize research
95
- messages = [
96
- {"role": "system", "content": BROWSER_SYSTEM},
97
- {"role": "user", "content": (
98
- f"Research task: {query}\n\n"
99
- f"Search context:\n{search_context}\n\n"
100
- f"Provide a comprehensive, structured research report with key findings, "
101
- f"actionable insights, and relevant sources. Format with headers and bullet points."
102
- )},
103
- ]
104
- return await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.3, max_tokens=4096)
105
-
106
- async def _fetch_and_analyze(self, url: str, task: str, task_id: str, session_id: str) -> str:
107
- """Fetch a URL and analyze its content."""
108
- import httpx
109
-
110
- try:
111
- async with httpx.AsyncClient(timeout=20, follow_redirects=True) as client:
112
- resp = await client.get(url, headers={
113
- "User-Agent": "Mozilla/5.0 GodAgent/7.0",
114
- "Accept": "text/html,application/json,*/*",
115
- })
116
- content_type = resp.headers.get("content-type", "")
117
-
118
- if "json" in content_type:
119
- page_content = json.dumps(resp.json(), indent=2)[:3000]
120
- else:
121
- # Strip HTML tags
122
- html = resp.text
123
- text = re.sub(r'<[^>]+>', ' ', html)
124
- text = re.sub(r'\s+', ' ', text).strip()
125
- page_content = text[:3000]
126
-
127
- except Exception as e:
128
- page_content = f"Could not fetch {url}: {str(e)}"
129
-
130
- messages = [
131
- {"role": "system", "content": BROWSER_SYSTEM},
132
- {"role": "user", "content": (
133
- f"Analyze this web page content for the task: {task}\n\n"
134
- f"URL: {url}\n\n"
135
- f"Page Content:\n{page_content}\n\n"
136
- f"Provide a structured analysis with key information extracted."
137
- )},
138
- ]
139
- return await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.3, max_tokens=4096)
140
-
141
- async def screenshot_analyze(self, url: str, task_id: str = "", session_id: str = "") -> str:
142
- """Describe what a webpage looks like (AI-powered visual analysis)."""
143
- messages = [
144
- {"role": "system", "content": BROWSER_SYSTEM},
145
- {"role": "user", "content": f"Describe the visual layout and UI elements you'd expect at: {url}. Provide a detailed visual analysis."},
146
- ]
147
- return await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.5)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
agents/chat_agent.py DELETED
@@ -1,44 +0,0 @@
1
- """
2
- ChatAgent — Conversational interface with streaming, Burmese support
3
- """
4
- from typing import Dict
5
- import structlog
6
- from .base_agent import BaseAgent
7
-
8
- log = structlog.get_logger()
9
-
10
- CHAT_SYSTEM = """You are God Agent — an elite autonomous AI operating system.
11
- You support both English and Burmese (မြန်မာဘာသာ) languages.
12
- Be helpful, precise, and autonomous.
13
- When users write in Burmese, respond in Burmese.
14
- When discussing code, provide production-quality examples.
15
- """
16
-
17
-
18
- class ChatAgent(BaseAgent):
19
- def __init__(self, ws_manager=None, ai_router=None):
20
- super().__init__("ChatAgent", ws_manager, ai_router)
21
-
22
- async def run(self, task: str, context: Dict = {}, **kwargs) -> str:
23
- session_id = kwargs.get("session_id", "")
24
- task_id = kwargs.get("task_id", "")
25
-
26
- history = context.get("history", [])
27
- messages = [{"role": "system", "content": CHAT_SYSTEM}]
28
-
29
- for h in history[-10:]:
30
- messages.append({"role": h.get("role", "user"), "content": h.get("content", "")})
31
-
32
- messages.append({"role": "user", "content": task})
33
-
34
- await self.emit_chat(session_id, "stream_start", {"agent": "ChatAgent", "status": "generating"})
35
-
36
- response = await self.llm(messages, task_id=task_id, session_id=session_id)
37
-
38
- await self.emit_chat(session_id, "stream_end", {
39
- "agent": "ChatAgent",
40
- "full_response": response,
41
- "status": "complete",
42
- })
43
-
44
- return response
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
agents/coding_agent.py DELETED
@@ -1,191 +0,0 @@
1
- """
2
- CodingAgent — Autonomous code generation, editing, refactoring (Devin/Genspark style)
3
- """
4
- import json
5
- import os
6
- import re
7
- from typing import Dict, List
8
- import structlog
9
- from .base_agent import BaseAgent
10
-
11
- log = structlog.get_logger()
12
-
13
- CODING_SYSTEM = """You are an elite autonomous software engineer — like Devin combined with Genspark.
14
- You write production-quality code that is:
15
- - Clean, readable, well-structured
16
- - Properly typed (TypeScript/Python type hints)
17
- - Error-handled and resilient
18
- - Documented with clear comments
19
- - Following best practices for the language/framework
20
-
21
- When generating code:
22
- 1. Think about the full architecture first
23
- 2. Write complete, runnable code (not snippets)
24
- 3. Include proper imports
25
- 4. Add error handling
26
- 5. Include brief usage examples in comments
27
-
28
- Support: Python, TypeScript, JavaScript, Go, Rust, SQL, Shell, YAML, JSON
29
- """
30
-
31
-
32
- class CodingAgent(BaseAgent):
33
- def __init__(self, ws_manager=None, ai_router=None):
34
- super().__init__("CodingAgent", ws_manager, ai_router)
35
-
36
- async def run(self, task: str, context: Dict = {}, **kwargs) -> str:
37
- session_id = kwargs.get("session_id", "")
38
- task_id = kwargs.get("task_id", "")
39
-
40
- await self.emit(task_id, "agent_start", {
41
- "agent": "CodingAgent",
42
- "task": task[:80],
43
- }, session_id)
44
-
45
- # Build context-aware messages
46
- prev_results = context.get("previous_results", [])
47
- project_ctx = context.get("project_context", "")
48
- plan = context.get("plan", "")
49
-
50
- system_content = CODING_SYSTEM
51
- if project_ctx:
52
- system_content += f"\n\nProject Context:\n{project_ctx[:1000]}"
53
-
54
- user_content = f"Task: {task}"
55
- if plan:
56
- user_content += f"\n\nExecution Plan:\n{plan[:500]}"
57
- if prev_results:
58
- user_content += f"\n\nPrevious results:\n" + "\n".join(str(r)[:200] for r in prev_results[-3:])
59
-
60
- messages = [
61
- {"role": "system", "content": system_content},
62
- {"role": "user", "content": user_content},
63
- ]
64
-
65
- await self.emit(task_id, "tool_called", {
66
- "agent": "CodingAgent",
67
- "tool": "code_generation",
68
- "step": task[:60],
69
- }, session_id)
70
-
71
- result = await self.llm(
72
- messages,
73
- task_id=task_id,
74
- session_id=session_id,
75
- temperature=0.2,
76
- max_tokens=8192,
77
- )
78
-
79
- # Extract code blocks for display
80
- code_blocks = self._extract_code_blocks(result)
81
- await self.emit(task_id, "code_generated", {
82
- "agent": "CodingAgent",
83
- "code_blocks": len(code_blocks),
84
- "total_lines": sum(len(b.split("\n")) for b in code_blocks),
85
- "languages": list(set(self._detect_language(b) for b in code_blocks)),
86
- }, session_id)
87
-
88
- return result
89
-
90
- async def generate_file(
91
- self,
92
- filename: str,
93
- description: str,
94
- task_id: str = "",
95
- session_id: str = "",
96
- context: Dict = {},
97
- ) -> str:
98
- """Generate a complete file with proper structure."""
99
- messages = [
100
- {"role": "system", "content": CODING_SYSTEM},
101
- {"role": "user", "content": (
102
- f"Generate a complete, production-ready file.\n"
103
- f"Filename: {filename}\n"
104
- f"Description: {description}\n"
105
- f"Context: {json.dumps(context)[:500]}\n\n"
106
- f"Return ONLY the file content, no explanation."
107
- )},
108
- ]
109
- content = await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.1, max_tokens=8192)
110
-
111
- # Strip markdown code fences if present
112
- content = self._strip_code_fences(content)
113
-
114
- # Write to workspace
115
- workspace = os.environ.get("WORKSPACE_DIR", "/tmp/god_workspace")
116
- filepath = os.path.join(workspace, filename)
117
- os.makedirs(os.path.dirname(filepath), exist_ok=True)
118
- with open(filepath, "w") as f:
119
- f.write(content)
120
-
121
- await self.emit(task_id, "file_written", {
122
- "filename": filename,
123
- "size": len(content),
124
- "lines": len(content.split("\n")),
125
- }, session_id)
126
-
127
- return content
128
-
129
- async def refactor(
130
- self,
131
- code: str,
132
- instructions: str,
133
- task_id: str = "",
134
- session_id: str = "",
135
- ) -> str:
136
- """Refactor existing code based on instructions."""
137
- messages = [
138
- {"role": "system", "content": CODING_SYSTEM},
139
- {"role": "user", "content": (
140
- f"Refactor this code based on these instructions:\n"
141
- f"Instructions: {instructions}\n\n"
142
- f"Original code:\n```\n{code}\n```\n\n"
143
- f"Return ONLY the refactored code."
144
- )},
145
- ]
146
- return await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.1, max_tokens=8192)
147
-
148
- async def scan_repository(self, repo_path: str) -> Dict:
149
- """Scan repository and build project intelligence graph."""
150
- import subprocess
151
- try:
152
- result = subprocess.run(
153
- ["find", repo_path, "-type", "f", "-name", "*.py", "-o",
154
- "-name", "*.ts", "-o", "-name", "*.js", "-o", "-name", "*.go"],
155
- capture_output=True, text=True, timeout=10
156
- )
157
- files = result.stdout.strip().split("\n")[:50]
158
-
159
- # Read key files
160
- key_files = {}
161
- for f in ["package.json", "requirements.txt", "tsconfig.json", "pyproject.toml", "go.mod"]:
162
- path = os.path.join(repo_path, f)
163
- if os.path.exists(path):
164
- with open(path) as fp:
165
- key_files[f] = fp.read()[:1000]
166
-
167
- return {
168
- "files": files,
169
- "key_configs": key_files,
170
- "total_files": len(files),
171
- }
172
- except Exception as e:
173
- return {"error": str(e), "files": [], "key_configs": {}}
174
-
175
- def _extract_code_blocks(self, text: str) -> List[str]:
176
- pattern = r"```[\w]*\n(.*?)```"
177
- return re.findall(pattern, text, re.DOTALL)
178
-
179
- def _strip_code_fences(self, text: str) -> str:
180
- text = re.sub(r"^```[\w]*\n", "", text.strip())
181
- text = re.sub(r"\n```$", "", text)
182
- return text
183
-
184
- def _detect_language(self, code: str) -> str:
185
- if "def " in code and "import " in code:
186
- return "python"
187
- if "function " in code or "const " in code or "interface " in code:
188
- return "typescript"
189
- if "package main" in code:
190
- return "go"
191
- return "unknown"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
agents/connector_agent.py DELETED
@@ -1,186 +0,0 @@
1
- """
2
- ConnectorAgent — GitHub, HuggingFace, Vercel, n8n, Telegram, Discord integrations
3
- """
4
- import json
5
- import os
6
- from typing import Dict, List, Optional
7
- import httpx
8
- import structlog
9
- from .base_agent import BaseAgent
10
-
11
- log = structlog.get_logger()
12
-
13
-
14
- class ConnectorAgent(BaseAgent):
15
- def __init__(self, ws_manager=None, ai_router=None):
16
- super().__init__("ConnectorAgent", ws_manager, ai_router)
17
-
18
- async def run(self, task: str, context: Dict = {}, **kwargs) -> str:
19
- session_id = kwargs.get("session_id", "")
20
- task_id = kwargs.get("task_id", "")
21
-
22
- task_lower = task.lower()
23
-
24
- if "github" in task_lower:
25
- return await self.github_operation(task, task_id=task_id, session_id=session_id)
26
- elif "huggingface" in task_lower or "hf" in task_lower:
27
- return await self.hf_operation(task, task_id=task_id, session_id=session_id)
28
- elif "vercel" in task_lower:
29
- return await self.vercel_operation(task, task_id=task_id, session_id=session_id)
30
- else:
31
- return await self._generic_connector(task, task_id=task_id, session_id=session_id)
32
-
33
- # ─── GitHub ───────────────────────────────────────────────────────────────
34
-
35
- async def github_operation(self, task: str, task_id: str = "", session_id: str = "") -> str:
36
- token = os.environ.get("GITHUB_TOKEN", "")
37
- if not token:
38
- return "⚠️ GITHUB_TOKEN not set. Please add it to environment variables."
39
-
40
- headers = {
41
- "Authorization": f"token {token}",
42
- "Accept": "application/vnd.github.v3+json",
43
- }
44
-
45
- task_lower = task.lower()
46
-
47
- try:
48
- async with httpx.AsyncClient(timeout=30) as client:
49
- if "create repo" in task_lower or "new repo" in task_lower:
50
- return await self._github_create_repo(client, headers, task, task_id, session_id)
51
- elif "list repo" in task_lower:
52
- return await self._github_list_repos(client, headers, task_id, session_id)
53
- elif "commit" in task_lower:
54
- return f"✅ GitHub commit operation noted. Use SandboxAgent for actual commits."
55
- elif "issue" in task_lower:
56
- return await self._github_create_issue(client, headers, task, task_id, session_id)
57
- else:
58
- return await self._github_user_info(client, headers, task_id, session_id)
59
- except Exception as e:
60
- return f"❌ GitHub error: {str(e)}"
61
-
62
- async def _github_user_info(self, client, headers, task_id, session_id) -> str:
63
- resp = await client.get("https://api.github.com/user", headers=headers)
64
- if resp.status_code == 200:
65
- data = resp.json()
66
- await self.emit(task_id, "connector_result", {
67
- "connector": "github",
68
- "action": "user_info",
69
- "user": data.get("login"),
70
- }, session_id)
71
- return f"✅ GitHub connected as **{data.get('login')}** ({data.get('public_repos')} repos)"
72
- return f"❌ GitHub auth failed: {resp.status_code}"
73
-
74
- async def _github_create_repo(self, client, headers, task, task_id, session_id) -> str:
75
- # Extract repo name from task using simple heuristic
76
- words = task.split()
77
- name_candidates = [w for w in words if w.replace("-", "").replace("_", "").isalnum() and len(w) > 3]
78
- repo_name = name_candidates[-1] if name_candidates else "god-agent-project"
79
-
80
- payload = {
81
- "name": repo_name,
82
- "description": "Created by God Agent Platform",
83
- "private": False,
84
- "auto_init": True,
85
- }
86
- resp = await client.post("https://api.github.com/user/repos", headers=headers, json=payload)
87
- if resp.status_code == 201:
88
- data = resp.json()
89
- await self.emit(task_id, "connector_result", {
90
- "connector": "github",
91
- "action": "repo_created",
92
- "repo": data.get("full_name"),
93
- "url": data.get("html_url"),
94
- }, session_id)
95
- return f"✅ GitHub repo created: [{data.get('full_name')}]({data.get('html_url')})"
96
- return f"❌ Failed to create repo: {resp.status_code} — {resp.text[:200]}"
97
-
98
- async def _github_list_repos(self, client, headers, task_id, session_id) -> str:
99
- resp = await client.get("https://api.github.com/user/repos?per_page=10&sort=updated", headers=headers)
100
- if resp.status_code == 200:
101
- repos = resp.json()
102
- lines = [f"- [{r['full_name']}]({r['html_url']}) ⭐{r['stargazers_count']}" for r in repos[:10]]
103
- return "📦 **Your GitHub Repos:**\n\n" + "\n".join(lines)
104
- return f"❌ Failed to list repos: {resp.status_code}"
105
-
106
- async def _github_create_issue(self, client, headers, task, task_id, session_id) -> str:
107
- return "✅ GitHub issue creation requires repo context. Specify: 'create issue in owner/repo: title'"
108
-
109
- # ─── HuggingFace ──────────────────────────────────────────────────────────
110
-
111
- async def hf_operation(self, task: str, task_id: str = "", session_id: str = "") -> str:
112
- token = os.environ.get("HF_TOKEN", "")
113
- if not token:
114
- return "⚠️ HF_TOKEN not set. Add HuggingFace token to environment."
115
-
116
- headers = {"Authorization": f"Bearer {token}"}
117
- try:
118
- async with httpx.AsyncClient(timeout=30) as client:
119
- resp = await client.get("https://huggingface.co/api/whoami", headers=headers)
120
- if resp.status_code == 200:
121
- data = resp.json()
122
- await self.emit(task_id, "connector_result", {
123
- "connector": "huggingface",
124
- "user": data.get("name"),
125
- }, session_id)
126
- return f"✅ HuggingFace connected as **{data.get('name')}**"
127
- return f"❌ HF auth failed: {resp.status_code}"
128
- except Exception as e:
129
- return f"❌ HuggingFace error: {str(e)}"
130
-
131
- # ─── Vercel ───────────────────────────────────────────────────────────────
132
-
133
- async def vercel_operation(self, task: str, task_id: str = "", session_id: str = "") -> str:
134
- token = os.environ.get("VERCEL_TOKEN", "")
135
- if not token:
136
- return "⚠️ VERCEL_TOKEN not set. Add Vercel token to environment."
137
-
138
- headers = {"Authorization": f"Bearer {token}"}
139
- try:
140
- async with httpx.AsyncClient(timeout=30) as client:
141
- resp = await client.get("https://api.vercel.com/v2/user", headers=headers)
142
- if resp.status_code == 200:
143
- data = resp.json()
144
- user = data.get("user", {})
145
- await self.emit(task_id, "connector_result", {
146
- "connector": "vercel",
147
- "user": user.get("username"),
148
- }, session_id)
149
- return f"✅ Vercel connected as **{user.get('username')}** ({user.get('email')})"
150
- return f"❌ Vercel auth failed: {resp.status_code}"
151
- except Exception as e:
152
- return f"❌ Vercel error: {str(e)}"
153
-
154
- async def _generic_connector(self, task: str, task_id: str = "", session_id: str = "") -> str:
155
- return (
156
- "🔌 **Available Connectors:**\n\n"
157
- "| Connector | Status | Env Var |\n"
158
- "|-----------|--------|---------||\n"
159
- f"| GitHub | {'✅' if os.environ.get('GITHUB_TOKEN') else '❌'} | GITHUB_TOKEN |\n"
160
- f"| HuggingFace | {'✅' if os.environ.get('HF_TOKEN') else '❌'} | HF_TOKEN |\n"
161
- f"| Vercel | {'✅' if os.environ.get('VERCEL_TOKEN') else '❌'} | VERCEL_TOKEN |\n"
162
- f"| OpenAI | {'✅' if os.environ.get('OPENAI_API_KEY') else '❌'} | OPENAI_API_KEY |\n"
163
- f"| Groq | {'✅' if os.environ.get('GROQ_API_KEY') else '❌'} | GROQ_API_KEY |\n"
164
- f"| OpenRouter | {'✅' if os.environ.get('OPENROUTER_API_KEY') else '❌'} | OPENROUTER_API_KEY |\n"
165
- )
166
-
167
- def get_connector_status(self) -> Dict:
168
- """Return status of all connectors."""
169
- connectors = {
170
- "github": bool(os.environ.get("GITHUB_TOKEN")),
171
- "huggingface": bool(os.environ.get("HF_TOKEN")),
172
- "vercel": bool(os.environ.get("VERCEL_TOKEN")),
173
- "openai": bool(os.environ.get("OPENAI_API_KEY")),
174
- "groq": bool(os.environ.get("GROQ_API_KEY")),
175
- "cerebras": bool(os.environ.get("CEREBRAS_API_KEY")),
176
- "openrouter": bool(os.environ.get("OPENROUTER_API_KEY")),
177
- "anthropic": bool(os.environ.get("ANTHROPIC_API_KEY")),
178
- "n8n": bool(os.environ.get("N8N_URL")),
179
- "telegram": bool(os.environ.get("TELEGRAM_BOT_TOKEN")),
180
- "discord": bool(os.environ.get("DISCORD_BOT_TOKEN")),
181
- }
182
- return {
183
- "connectors": connectors,
184
- "connected_count": sum(connectors.values()),
185
- "total": len(connectors),
186
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
agents/debug_agent.py DELETED
@@ -1,158 +0,0 @@
1
- """
2
- DebugAgent — Autonomous error detection, self-healing, retry loops
3
- """
4
- import json
5
- import re
6
- from typing import Dict, List
7
- import structlog
8
- from .base_agent import BaseAgent
9
-
10
- log = structlog.get_logger()
11
-
12
- DEBUG_SYSTEM = """You are an expert debugging engineer with deep knowledge of:
13
- - Python, TypeScript, JavaScript, Go, Rust errors
14
- - Runtime exceptions, import errors, type errors
15
- - API errors, network failures, auth issues
16
- - Build failures, dependency conflicts
17
- - Database errors, query optimization
18
-
19
- When given an error:
20
- 1. Identify the root cause precisely
21
- 2. Provide the EXACT fix (code patch or config change)
22
- 3. Explain WHY it failed
23
- 4. Suggest prevention strategies
24
-
25
- Always return actionable fixes, not just explanations.
26
- """
27
-
28
-
29
- class DebugAgent(BaseAgent):
30
- def __init__(self, ws_manager=None, ai_router=None):
31
- super().__init__("DebugAgent", ws_manager, ai_router)
32
-
33
- async def run(self, task: str, context: Dict = {}, **kwargs) -> str:
34
- session_id = kwargs.get("session_id", "")
35
- task_id = kwargs.get("task_id", "")
36
- attempt = context.get("attempt", 1)
37
-
38
- await self.emit(task_id, "agent_start", {
39
- "agent": "DebugAgent",
40
- "attempt": attempt,
41
- "error": task[:100],
42
- }, session_id)
43
-
44
- messages = [
45
- {"role": "system", "content": DEBUG_SYSTEM},
46
- {"role": "user", "content": (
47
- "Debug and fix this issue (attempt " + str(attempt) + "):\n\n"
48
- + task + "\n\n"
49
- "Provide:\n"
50
- "1. Root cause analysis\n"
51
- "2. Exact fix (code/config)\n"
52
- "3. Prevention strategy"
53
- )},
54
- ]
55
-
56
- result = await self.llm(
57
- messages,
58
- task_id=task_id,
59
- session_id=session_id,
60
- temperature=0.1,
61
- max_tokens=4096,
62
- )
63
-
64
- await self.emit(task_id, "debug_complete", {
65
- "agent": "DebugAgent",
66
- "has_fix": "```" in result or "fix" in result.lower(),
67
- "attempt": attempt,
68
- }, session_id)
69
-
70
- return result
71
-
72
- async def analyze_error(self, error_output: str, source_code: str = "", task_id: str = "", session_id: str = "") -> Dict:
73
- """Deep error analysis with structured output."""
74
- if source_code:
75
- source_section = "Source Code:\n```\n" + source_code[:1000] + "\n```"
76
- else:
77
- source_section = ""
78
-
79
- messages = [
80
- {"role": "system", "content": DEBUG_SYSTEM},
81
- {"role": "user", "content": (
82
- "Analyze this error and provide structured diagnosis:\n\n"
83
- "Error:\n" + error_output[:2000] + "\n\n"
84
- + source_section + "\n\n"
85
- "Respond with JSON:\n"
86
- '{"error_type": "...", "root_cause": "...", "fix": "...", "prevention": "...", "severity": "low|medium|high|critical"}'
87
- )},
88
- ]
89
- raw = await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.1, max_tokens=1000)
90
- try:
91
- start = raw.find("{")
92
- end = raw.rfind("}") + 1
93
- return json.loads(raw[start:end])
94
- except Exception:
95
- return {"error_type": "unknown", "root_cause": error_output[:200], "fix": raw[:500], "severity": "medium"}
96
-
97
- async def self_heal_loop(
98
- self,
99
- code: str,
100
- error: str,
101
- max_retries: int = 3,
102
- task_id: str = "",
103
- session_id: str = "",
104
- ) -> str:
105
- """Self-healing loop — generate fix, validate, retry."""
106
- current_code = code
107
- current_error = error
108
-
109
- for attempt in range(1, max_retries + 1):
110
- await self.emit(task_id, "self_heal_attempt", {
111
- "attempt": attempt,
112
- "max_retries": max_retries,
113
- "error_snippet": current_error[:100],
114
- }, session_id)
115
-
116
- messages = [
117
- {"role": "system", "content": DEBUG_SYSTEM},
118
- {"role": "user", "content": (
119
- "Fix attempt " + str(attempt) + "/" + str(max_retries) + ":\n\n"
120
- "Error: " + current_error + "\n\n"
121
- "Code:\n```\n" + current_code[:3000] + "\n```\n\n"
122
- "Return ONLY the fixed code."
123
- )},
124
- ]
125
-
126
- fixed = await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.1, max_tokens=8192)
127
- fixed = self._strip_fences(fixed)
128
-
129
- # Validate syntax for Python
130
- validation = await self._validate_python(fixed)
131
- if validation["valid"]:
132
- await self.emit(task_id, "self_heal_success", {
133
- "attempt": attempt,
134
- "code_lines": len(fixed.split("\n")),
135
- }, session_id)
136
- return fixed
137
- else:
138
- current_code = fixed
139
- current_error = validation["error"]
140
- log.warning("Self-heal attempt failed", attempt=attempt, error=current_error[:100])
141
-
142
- await self.emit(task_id, "self_heal_failed", {"attempts": max_retries}, session_id)
143
- return current_code # Return best attempt
144
-
145
- async def _validate_python(self, code: str) -> Dict:
146
- """Quick Python syntax validation."""
147
- try:
148
- compile(code, "<string>", "exec")
149
- return {"valid": True, "error": ""}
150
- except SyntaxError as e:
151
- return {"valid": False, "error": "SyntaxError: " + str(e)}
152
- except Exception as e:
153
- return {"valid": False, "error": str(e)}
154
-
155
- def _strip_fences(self, text: str) -> str:
156
- text = re.sub(r"^```[\w]*\n", "", text.strip())
157
- text = re.sub(r"\n```$", "", text)
158
- return text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
agents/deploy_agent.py DELETED
@@ -1,101 +0,0 @@
1
- """
2
- DeployAgent — Automated deployments to Vercel, HF Spaces, GitHub Pages
3
- """
4
- import json
5
- import os
6
- from typing import Dict
7
- import httpx
8
- import structlog
9
- from .base_agent import BaseAgent
10
-
11
- log = structlog.get_logger()
12
-
13
- DEPLOY_SYSTEM = """You are a deployment engineer expert in:
14
- - Vercel deployments (Next.js, React, API routes)
15
- - HuggingFace Spaces (Docker, Gradio, Streamlit)
16
- - GitHub Pages (static sites)
17
- - Docker containerization
18
- - Environment variable management
19
-
20
- Generate precise deployment configs and commands.
21
- """
22
-
23
-
24
- class DeployAgent(BaseAgent):
25
- def __init__(self, ws_manager=None, ai_router=None):
26
- super().__init__("DeployAgent", ws_manager, ai_router)
27
-
28
- async def run(self, task: str, context: Dict = {}, **kwargs) -> str:
29
- session_id = kwargs.get("session_id", "")
30
- task_id = kwargs.get("task_id", "")
31
-
32
- await self.emit(task_id, "agent_start", {"agent": "DeployAgent", "task": task[:80]}, session_id)
33
-
34
- task_lower = task.lower()
35
- if "vercel" in task_lower:
36
- return await self._deploy_vercel_guide(task, task_id, session_id)
37
- elif "huggingface" in task_lower or "hf" in task_lower or "space" in task_lower:
38
- return await self._deploy_hf_guide(task, task_id, session_id)
39
- elif "docker" in task_lower:
40
- return await self._generate_dockerfile(task, task_id, session_id)
41
- else:
42
- return await self._deploy_general(task, task_id, session_id)
43
-
44
- async def _deploy_vercel_guide(self, task: str, task_id: str, session_id: str) -> str:
45
- messages = [
46
- {"role": "system", "content": DEPLOY_SYSTEM},
47
- {"role": "user", "content": (
48
- f"Generate complete Vercel deployment guide for: {task}\n\n"
49
- f"Include:\n1. vercel.json config\n2. Environment variables needed\n"
50
- f"3. Build commands\n4. Step-by-step deployment instructions"
51
- )},
52
- ]
53
- result = await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.2)
54
- await self.emit(task_id, "deploy_plan_ready", {"platform": "vercel"}, session_id)
55
- return result
56
-
57
- async def _deploy_hf_guide(self, task: str, task_id: str, session_id: str) -> str:
58
- messages = [
59
- {"role": "system", "content": DEPLOY_SYSTEM},
60
- {"role": "user", "content": (
61
- f"Generate HuggingFace Space deployment for: {task}\n\n"
62
- f"Include:\n1. Dockerfile\n2. README.md with YAML header\n"
63
- f"3. Requirements/dependencies\n4. Space configuration"
64
- )},
65
- ]
66
- result = await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.2)
67
- await self.emit(task_id, "deploy_plan_ready", {"platform": "huggingface"}, session_id)
68
- return result
69
-
70
- async def _generate_dockerfile(self, task: str, task_id: str, session_id: str) -> str:
71
- messages = [
72
- {"role": "system", "content": DEPLOY_SYSTEM},
73
- {"role": "user", "content": f"Generate production Dockerfile for: {task}\nInclude multi-stage build, security best practices, health check."},
74
- ]
75
- return await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.1)
76
-
77
- async def _deploy_general(self, task: str, task_id: str, session_id: str) -> str:
78
- messages = [
79
- {"role": "system", "content": DEPLOY_SYSTEM},
80
- {"role": "user", "content": f"Create deployment plan for: {task}\n\nInclude platform recommendation, config files, and step-by-step guide."},
81
- ]
82
- return await self.llm(messages, task_id=task_id, session_id=session_id)
83
-
84
- async def check_vercel_deployments(self) -> str:
85
- """Check recent Vercel deployments."""
86
- token = os.environ.get("VERCEL_TOKEN", "")
87
- if not token:
88
- return "⚠️ VERCEL_TOKEN not set."
89
- try:
90
- async with httpx.AsyncClient(timeout=15) as client:
91
- resp = await client.get(
92
- "https://api.vercel.com/v6/deployments?limit=5",
93
- headers={"Authorization": f"Bearer {token}"}
94
- )
95
- if resp.status_code == 200:
96
- deps = resp.json().get("deployments", [])
97
- lines = [f"- {d.get('name')} → {d.get('state')} ({d.get('url', '')})" for d in deps[:5]]
98
- return "🚀 **Recent Vercel Deployments:**\n\n" + "\n".join(lines)
99
- except Exception as e:
100
- return f"❌ Vercel error: {e}"
101
- return "No deployments found."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
agents/file_agent.py DELETED
@@ -1,227 +0,0 @@
1
- """
2
- FileAgent v7 — Autonomous file system management, code editing, project scaffolding
3
- Like Devin's file browser + OneHand's file manipulation
4
- """
5
- import asyncio
6
- import json
7
- import os
8
- import re
9
- import shutil
10
- from pathlib import Path
11
- from typing import Dict, List, Optional
12
- import structlog
13
- from .base_agent import BaseAgent
14
-
15
- log = structlog.get_logger()
16
-
17
- FILE_SYSTEM = """You are an elite file system and project management agent.
18
- You can:
19
- - Create, read, edit, delete files and directories
20
- - Scaffold complete project structures
21
- - Analyze codebases and suggest improvements
22
- - Generate file trees and project maps
23
- - Apply patches and diffs to code files
24
- - Manage project configuration files
25
-
26
- Always provide complete, runnable file content.
27
- """
28
-
29
- WORKSPACE = os.environ.get("WORKSPACE_DIR", "/tmp/god_workspace")
30
-
31
- class FileAgent(BaseAgent):
32
- def __init__(self, ws_manager=None, ai_router=None):
33
- super().__init__("FileAgent", ws_manager, ai_router)
34
- os.makedirs(WORKSPACE, exist_ok=True)
35
-
36
- async def run(self, task: str, context: Dict = {}, **kwargs) -> str:
37
- session_id = kwargs.get("session_id", "")
38
- task_id = kwargs.get("task_id", "")
39
-
40
- await self.emit(task_id, "agent_start", {"agent": "FileAgent", "task": task[:80]}, session_id)
41
-
42
- task_lower = task.lower()
43
- if any(k in task_lower for k in ["create", "scaffold", "generate", "new project", "init"]):
44
- result = await self._scaffold_project(task, context, task_id, session_id)
45
- elif any(k in task_lower for k in ["read", "show", "view", "list", "tree"]):
46
- result = await self._read_or_list(task, task_id, session_id)
47
- elif any(k in task_lower for k in ["edit", "modify", "update", "change", "fix", "patch"]):
48
- result = await self._edit_file(task, context, task_id, session_id)
49
- elif any(k in task_lower for k in ["delete", "remove", "clean"]):
50
- result = await self._delete_files(task, task_id, session_id)
51
- else:
52
- result = await self._ai_file_task(task, context, task_id, session_id)
53
-
54
- return result
55
-
56
- async def _scaffold_project(self, task: str, context: Dict, task_id: str, session_id: str) -> str:
57
- """Scaffold a complete project structure."""
58
- await self.emit(task_id, "tool_called", {
59
- "agent": "FileAgent", "tool": "scaffold_project", "step": "Generating project structure"
60
- }, session_id)
61
-
62
- messages = [
63
- {"role": "system", "content": FILE_SYSTEM},
64
- {"role": "user", "content": (
65
- f"Task: {task}\n\n"
66
- "Generate a complete project scaffold. Return a JSON object with this structure:\n"
67
- "{\n"
68
- ' "project_name": "name",\n'
69
- ' "files": [\n'
70
- ' {"path": "relative/path/file.ext", "content": "full file content here"}\n'
71
- " ],\n"
72
- ' "description": "what was created",\n'
73
- ' "run_commands": ["npm install", "npm run dev"]\n'
74
- "}\n"
75
- "Include all necessary files for a working project."
76
- )},
77
- ]
78
- response = await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.2, max_tokens=8192)
79
-
80
- # Parse JSON and create files
81
- created_files = []
82
- try:
83
- start = response.find("{")
84
- end = response.rfind("}") + 1
85
- if start >= 0 and end > start:
86
- data = json.loads(response[start:end])
87
- project_name = data.get("project_name", "project")
88
- project_path = os.path.join(WORKSPACE, project_name)
89
- os.makedirs(project_path, exist_ok=True)
90
-
91
- for f in data.get("files", []):
92
- filepath = os.path.join(project_path, f["path"])
93
- os.makedirs(os.path.dirname(filepath), exist_ok=True)
94
- with open(filepath, "w") as fp:
95
- fp.write(f["content"])
96
- created_files.append(f["path"])
97
- await self.emit(task_id, "file_written", {
98
- "path": f["path"], "size": len(f["content"])
99
- }, session_id)
100
-
101
- result = (
102
- f"✅ **Project Scaffolded**: `{project_name}`\n\n"
103
- f"**Files Created** ({len(created_files)}):\n"
104
- + "\n".join(f"- `{f}`" for f in created_files)
105
- + f"\n\n**Description:** {data.get('description', '')}\n\n"
106
- + "**Run Commands:**\n"
107
- + "\n".join(f"```\n{cmd}\n```" for cmd in data.get("run_commands", []))
108
- )
109
- return result
110
- except Exception as e:
111
- log.warning("Failed to parse project scaffold JSON", error=str(e))
112
-
113
- return response
114
-
115
- async def _read_or_list(self, task: str, task_id: str, session_id: str) -> str:
116
- """Read files or list directory structure."""
117
- await self.emit(task_id, "tool_called", {
118
- "agent": "FileAgent", "tool": "read_files", "step": "Reading file system"
119
- }, session_id)
120
-
121
- # Extract path from task
122
- path_match = re.search(r'["\']([^"\']+)["\']|(\S+\.\w+)', task)
123
- target_path = path_match.group(1) or path_match.group(2) if path_match else WORKSPACE
124
-
125
- if not os.path.isabs(target_path):
126
- target_path = os.path.join(WORKSPACE, target_path)
127
-
128
- if os.path.isdir(target_path):
129
- tree = self._get_tree(target_path)
130
- return f"**Directory Tree:** `{target_path}`\n\n```\n{tree}\n```"
131
- elif os.path.isfile(target_path):
132
- with open(target_path) as f:
133
- content = f.read()
134
- return f"**File:** `{target_path}`\n\n```\n{content[:4000]}\n```"
135
- else:
136
- # List workspace
137
- tree = self._get_tree(WORKSPACE, max_depth=3)
138
- return f"**Workspace:** `{WORKSPACE}`\n\n```\n{tree}\n```"
139
-
140
- async def _edit_file(self, task: str, context: Dict, task_id: str, session_id: str) -> str:
141
- """Edit a file based on instructions."""
142
- await self.emit(task_id, "tool_called", {
143
- "agent": "FileAgent", "tool": "edit_file", "step": "Editing file"
144
- }, session_id)
145
-
146
- messages = [
147
- {"role": "system", "content": FILE_SYSTEM},
148
- {"role": "user", "content": (
149
- f"Task: {task}\n\n"
150
- f"Context: {json.dumps(context)[:500]}\n\n"
151
- "Return a JSON with: {\"filepath\": \"path\", \"content\": \"full new file content\", \"explanation\": \"what changed\"}"
152
- )},
153
- ]
154
- response = await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.1, max_tokens=8192)
155
-
156
- try:
157
- start = response.find("{")
158
- end = response.rfind("}") + 1
159
- if start >= 0 and end > start:
160
- data = json.loads(response[start:end])
161
- filepath = os.path.join(WORKSPACE, data.get("filepath", "output.txt"))
162
- os.makedirs(os.path.dirname(filepath), exist_ok=True)
163
- with open(filepath, "w") as f:
164
- f.write(data.get("content", ""))
165
- await self.emit(task_id, "file_written", {"path": data.get("filepath"), "edited": True}, session_id)
166
- return f"✅ **File Edited:** `{data.get('filepath')}`\n\n{data.get('explanation', '')}"
167
- except Exception:
168
- pass
169
- return response
170
-
171
- async def _delete_files(self, task: str, task_id: str, session_id: str) -> str:
172
- """Delete files or directories safely."""
173
- path_match = re.search(r'["\']([^"\']+)["\']', task)
174
- if path_match:
175
- target = os.path.join(WORKSPACE, path_match.group(1))
176
- if os.path.exists(target) and WORKSPACE in target:
177
- if os.path.isdir(target):
178
- shutil.rmtree(target)
179
- else:
180
- os.remove(target)
181
- await self.emit(task_id, "file_deleted", {"path": path_match.group(1)}, session_id)
182
- return f"✅ Deleted: `{path_match.group(1)}`"
183
- return "❌ Could not find file/directory to delete. Please specify the path in quotes."
184
-
185
- async def _ai_file_task(self, task: str, context: Dict, task_id: str, session_id: str) -> str:
186
- """Handle generic file tasks via AI."""
187
- messages = [
188
- {"role": "system", "content": FILE_SYSTEM},
189
- {"role": "user", "content": f"Task: {task}\n\nWorkspace: {WORKSPACE}\n\nContext: {json.dumps(context)[:300]}"},
190
- ]
191
- return await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.3, max_tokens=4096)
192
-
193
- def _get_tree(self, path: str, prefix: str = "", max_depth: int = 4, depth: int = 0) -> str:
194
- """Generate a directory tree string."""
195
- if depth > max_depth:
196
- return ""
197
- try:
198
- entries = sorted(os.scandir(path), key=lambda e: (e.is_file(), e.name))
199
- except PermissionError:
200
- return ""
201
- lines = []
202
- for i, entry in enumerate(entries):
203
- if entry.name.startswith(".") and entry.name not in [".env", ".gitignore"]:
204
- continue
205
- connector = "└── " if i == len(entries) - 1 else "├── "
206
- lines.append(f"{prefix}{connector}{entry.name}")
207
- if entry.is_dir() and depth < max_depth:
208
- extension = " " if i == len(entries) - 1 else "│ "
209
- subtree = self._get_tree(entry.path, prefix + extension, max_depth, depth + 1)
210
- if subtree:
211
- lines.append(subtree)
212
- return "\n".join(lines)
213
-
214
- def list_workspace(self) -> Dict:
215
- """List all workspace files."""
216
- files = []
217
- for root, dirs, filenames in os.walk(WORKSPACE):
218
- dirs[:] = [d for d in dirs if not d.startswith(".") and d != "node_modules"]
219
- for f in filenames:
220
- full_path = os.path.join(root, f)
221
- rel_path = os.path.relpath(full_path, WORKSPACE)
222
- try:
223
- size = os.path.getsize(full_path)
224
- files.append({"path": rel_path, "size": size})
225
- except Exception:
226
- pass
227
- return {"workspace": WORKSPACE, "files": files, "total": len(files)}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
agents/git_agent.py DELETED
@@ -1,120 +0,0 @@
1
- """
2
- GitAgent v7 — Autonomous Git operations, PR creation, code review
3
- Full GitHub integration like Manus/Genspark autonomous coding
4
- """
5
- import asyncio
6
- import json
7
- import os
8
- import re
9
- from typing import Dict, List
10
- import structlog
11
- from .base_agent import BaseAgent
12
-
13
- log = structlog.get_logger()
14
-
15
- GIT_SYSTEM = """You are an elite autonomous Git and GitHub operations agent.
16
- You can clone, commit, push, pull, create branches, PRs, review code,
17
- generate commit messages, manage workflows, and handle merge conflicts.
18
- Always write clear, conventional commit messages (feat/fix/chore/docs/refactor).
19
- """
20
-
21
-
22
- class GitAgent(BaseAgent):
23
- def __init__(self, ws_manager=None, ai_router=None):
24
- super().__init__("GitAgent", ws_manager, ai_router)
25
- self.workspace = os.environ.get("WORKSPACE_DIR", "/tmp/god_workspace")
26
-
27
- async def run(self, task: str, context: Dict = {}, **kwargs) -> str:
28
- session_id = kwargs.get("session_id", "")
29
- task_id = kwargs.get("task_id", "")
30
- await self.emit(task_id, "agent_start", {"agent": "GitAgent", "task": task[:80]}, session_id)
31
-
32
- t = task.lower()
33
- if any(k in t for k in ["clone", "checkout"]):
34
- return await self._clone_repo(task, context, task_id, session_id)
35
- if any(k in t for k in ["commit", "push", "pull request", " pr "]):
36
- return await self._commit_and_push(task, context, task_id, session_id)
37
- if any(k in t for k in ["review", "analyze code", "audit"]):
38
- return await self._code_review(task, context, task_id, session_id)
39
- return await self._git_ai_task(task, context, task_id, session_id)
40
-
41
- async def _clone_repo(self, task: str, context: Dict, task_id: str, session_id: str) -> str:
42
- urls = re.findall(r'https?://github\.com/[^\s]+', task)
43
- if not urls:
44
- return "❌ No GitHub URL found in task."
45
- url = urls[0]
46
- repo_name = url.rstrip("/").split("/")[-1].replace(".git", "")
47
- dest = os.path.join(self.workspace, repo_name)
48
- await self.emit(task_id, "tool_called", {"agent": "GitAgent", "tool": "git_clone", "step": f"Cloning {repo_name}"}, session_id)
49
- token = os.environ.get("GITHUB_TOKEN", "")
50
- auth_url = url.replace("https://", f"https://{token}@") if token else url
51
- r = await self._run_cmd(["git", "clone", auth_url, dest])
52
- if r["returncode"] == 0:
53
- await self.emit(task_id, "git_cloned", {"repo": repo_name, "path": dest}, session_id)
54
- return f"✅ **Cloned** `{repo_name}` → `{dest}`\n```\n{r['stdout'][:500]}\n```"
55
- return f"❌ Clone failed:\n```\n{r['stderr'][:500]}\n```"
56
-
57
- async def _commit_and_push(self, task: str, context: Dict, task_id: str, session_id: str) -> str:
58
- repo_path = context.get("repo_path", self.workspace)
59
- await self.emit(task_id, "tool_called", {"agent": "GitAgent", "tool": "git_commit", "step": "Committing"}, session_id)
60
- msgs = [
61
- {"role": "system", "content": "Generate a conventional commit message. Return ONLY the one-line message."},
62
- {"role": "user", "content": f"Task: {task}\nContext: {json.dumps(context)[:200]}"},
63
- ]
64
- commit_msg = (await self.llm(msgs, task_id=task_id, session_id=session_id, temperature=0.3, max_tokens=80)).strip().split("\n")[0][:100]
65
- results = []
66
- for cmd in [["git", "add", "-A"], ["git", "commit", "-m", commit_msg]]:
67
- r = await self._run_cmd(cmd, cwd=repo_path)
68
- results.append(f"$ {' '.join(cmd)}\n{r['stdout']}{r['stderr']}")
69
- branch = context.get("branch", "main")
70
- r = await self._run_cmd(["git", "push", "origin", branch], cwd=repo_path)
71
- results.append(f"$ git push\n{r['stdout']}{r['stderr']}")
72
- return f"✅ **Committed:** `{commit_msg}`\n\n```\n" + "\n".join(results) + "\n```"
73
-
74
- async def _code_review(self, task: str, context: Dict, task_id: str, session_id: str) -> str:
75
- repo_path = context.get("repo_path", self.workspace)
76
- diff = await self._run_cmd(["git", "diff", "HEAD~1"], cwd=repo_path)
77
- msgs = [
78
- {"role": "system", "content": GIT_SYSTEM},
79
- {"role": "user", "content": f"Task: {task}\n\nDiff:\n{diff['stdout'][:2500]}\n\nProvide code review: summary, issues, suggestions, score (1-10)."},
80
- ]
81
- return await self.llm(msgs, task_id=task_id, session_id=session_id, temperature=0.3, max_tokens=4096)
82
-
83
- async def _git_ai_task(self, task: str, context: Dict, task_id: str, session_id: str) -> str:
84
- msgs = [
85
- {"role": "system", "content": GIT_SYSTEM},
86
- {"role": "user", "content": f"Task: {task}\nWorkspace: {self.workspace}\nContext: {json.dumps(context)[:300]}"},
87
- ]
88
- return await self.llm(msgs, task_id=task_id, session_id=session_id, temperature=0.3, max_tokens=4096)
89
-
90
- async def create_github_pr(self, repo_owner: str, repo_name: str, title: str, body: str,
91
- head_branch: str, base_branch: str = "main",
92
- task_id: str = "", session_id: str = "") -> Dict:
93
- import httpx
94
- token = os.environ.get("GITHUB_TOKEN", "")
95
- if not token:
96
- return {"error": "GITHUB_TOKEN not set"}
97
- async with httpx.AsyncClient(timeout=30) as client:
98
- resp = await client.post(
99
- f"https://api.github.com/repos/{repo_owner}/{repo_name}/pulls",
100
- headers={"Authorization": f"token {token}", "Accept": "application/vnd.github.v3+json"},
101
- json={"title": title, "body": body, "head": head_branch, "base": base_branch},
102
- )
103
- data = resp.json()
104
- if resp.status_code == 201:
105
- await self.emit(task_id, "pr_created", {"url": data.get("html_url")}, session_id)
106
- return {"success": True, "url": data.get("html_url")}
107
- return {"error": data.get("message", "Failed"), "status": resp.status_code}
108
-
109
- async def _run_cmd(self, cmd: List[str], cwd: str = None, timeout: int = 60) -> Dict:
110
- try:
111
- proc = await asyncio.create_subprocess_exec(
112
- *cmd, cwd=cwd or self.workspace,
113
- stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,
114
- )
115
- stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=timeout)
116
- return {"returncode": proc.returncode,
117
- "stdout": stdout.decode("utf-8", errors="replace"),
118
- "stderr": stderr.decode("utf-8", errors="replace")}
119
- except Exception as e:
120
- return {"returncode": -1, "stdout": "", "stderr": str(e)}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
agents/memory_agent.py DELETED
@@ -1,130 +0,0 @@
1
- """
2
- MemoryAgent — Persistent long-term memory system (Phase 5)
3
- SQLite-backed with semantic search simulation
4
- """
5
- import json
6
- import time
7
- from typing import Dict, List, Optional
8
- import structlog
9
- from .base_agent import BaseAgent
10
- from memory.db import save_memory, search_memory, get_history, get_project_memory
11
-
12
- log = structlog.get_logger()
13
-
14
-
15
- class MemoryAgent(BaseAgent):
16
- def __init__(self, ws_manager=None, ai_router=None):
17
- super().__init__("MemoryAgent", ws_manager, ai_router)
18
-
19
- async def run(self, task: str, context: Dict = {}, **kwargs) -> str:
20
- session_id = kwargs.get("session_id", "")
21
- task_id = kwargs.get("task_id", "")
22
-
23
- # Determine if retrieve or save
24
- task_lower = task.lower()
25
- if any(k in task_lower for k in ["remember", "save", "store", "record"]):
26
- content = context.get("content", task)
27
- await self.save(content, session_id=session_id, memory_type="user_directive")
28
- return f"✅ Saved to memory: {content[:100]}"
29
- else:
30
- results = await self.retrieve(task, session_id=session_id)
31
- if results:
32
- return "📚 **Memory Retrieved:**\n\n" + "\n".join(f"- {r['content'][:200]}" for r in results[:5])
33
- return "No relevant memories found."
34
-
35
- async def save(
36
- self,
37
- content: str,
38
- session_id: str = "",
39
- project_id: str = "",
40
- memory_type: str = "general",
41
- key: str = "",
42
- metadata: Dict = {},
43
- ):
44
- """Save content to persistent memory."""
45
- await save_memory(
46
- content=content,
47
- memory_type=memory_type,
48
- session_id=session_id,
49
- project_id=project_id,
50
- key=key,
51
- metadata=metadata,
52
- )
53
-
54
- async def retrieve(
55
- self,
56
- query: str,
57
- session_id: str = "",
58
- project_id: str = "",
59
- limit: int = 10,
60
- ) -> List[Dict]:
61
- """Retrieve relevant memories."""
62
- return await search_memory(query[:100], session_id=session_id, project_id=project_id, limit=limit)
63
-
64
- async def get_conversation_history(self, session_id: str, limit: int = 20) -> List[Dict]:
65
- """Get conversation history for a session."""
66
- return await get_history(session_id, limit=limit)
67
-
68
- async def save_interaction(
69
- self,
70
- user_message: str,
71
- assistant_response: str,
72
- session_id: str = "",
73
- intent: Dict = {},
74
- ):
75
- """Save a full interaction to memory."""
76
- await save_memory(
77
- content=user_message,
78
- memory_type="conversation",
79
- session_id=session_id,
80
- key="user_message",
81
- metadata={"intent": intent.get("intent", ""), "timestamp": time.time()},
82
- )
83
- await save_memory(
84
- content=assistant_response,
85
- memory_type="conversation",
86
- session_id=session_id,
87
- key="assistant_response",
88
- metadata={"agent": intent.get("primary_agent", "chat"), "timestamp": time.time()},
89
- )
90
-
91
- async def save_coding_style(self, style_notes: str, session_id: str = ""):
92
- """Remember user's coding preferences."""
93
- await save_memory(
94
- content=style_notes,
95
- memory_type="user_preference",
96
- session_id=session_id,
97
- key="coding_style",
98
- metadata={"category": "coding_style"},
99
- )
100
-
101
- async def save_project_context(self, project_id: str, context: Dict):
102
- """Save project-specific context."""
103
- await save_memory(
104
- content=json.dumps(context),
105
- memory_type="project_context",
106
- project_id=project_id,
107
- key="project_context",
108
- metadata={"timestamp": time.time()},
109
- )
110
-
111
- async def get_project_context(self, project_id: str) -> Optional[Dict]:
112
- """Get project context."""
113
- results = await get_project_memory(project_id, memory_type="project_context", limit=1)
114
- if results:
115
- try:
116
- return json.loads(results[0]["content"])
117
- except Exception:
118
- return {"raw": results[0]["content"]}
119
- return None
120
-
121
- async def build_context_for_agent(self, session_id: str, query: str) -> Dict:
122
- """Build rich context dict for agents from memory."""
123
- history = await self.get_conversation_history(session_id, limit=10)
124
- relevant = await self.retrieve(query, session_id=session_id, limit=5)
125
-
126
- return {
127
- "history": [{"role": "user" if i % 2 == 0 else "assistant", "content": h["content"]} for i, h in enumerate(reversed(history))],
128
- "relevant_memories": [r["content"][:200] for r in relevant],
129
- "session_id": session_id,
130
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
agents/orchestrator.py DELETED
@@ -1,248 +0,0 @@
1
- """
2
- God Agent Orchestrator — Central Brain (Manus-style)
3
- Routes user intent → correct agent → merges results
4
- """
5
-
6
- import asyncio
7
- import json
8
- import time
9
- import uuid
10
- from typing import Any, Dict, List, Optional
11
-
12
- import structlog
13
-
14
- log = structlog.get_logger()
15
-
16
- SYSTEM_PROMPT = """You are GOD AGENT — an elite autonomous AI operating system combining:
17
- - Manus-style orchestration and planning
18
- - Devin-style autonomous coding and debugging
19
- - Genspark-style repo engineering
20
-
21
- You coordinate multiple specialized agents:
22
- - ChatAgent: Conversation and clarification
23
- - PlannerAgent: Break goals into executable task graphs
24
- - CodingAgent: Generate, edit, refactor, fix code
25
- - DebugAgent: Detect and auto-fix errors (self-healing)
26
- - MemoryAgent: Persistent long-term memory
27
- - ConnectorAgent: GitHub/HF/Vercel/n8n integrations
28
- - DeployAgent: Automated deployments
29
- - WorkflowAgent: n8n workflow generation
30
- - SandboxAgent: VS Code sandbox execution
31
-
32
- You respond in Burmese or English based on user preference.
33
- Always think step-by-step. Be autonomous, decisive, and thorough.
34
- """
35
-
36
-
37
- class GodAgentOrchestrator:
38
- """
39
- Central orchestrator — routes tasks to specialized agents,
40
- merges results, manages agent collaboration.
41
- """
42
-
43
- def __init__(self, ws_manager=None, ai_router=None):
44
- self.ws = ws_manager
45
- self.ai_router = ai_router
46
- self._agents: Dict[str, Any] = {}
47
- self._active_tasks: Dict[str, Dict] = {}
48
-
49
- def register_agent(self, name: str, agent):
50
- self._agents[name] = agent
51
- log.info("Agent registered", agent=name)
52
-
53
- def get_agent(self, name: str):
54
- return self._agents.get(name)
55
-
56
- # ─── Intent Classification ────────────────────────────────────────────────
57
-
58
- async def classify_intent(self, user_message: str) -> Dict:
59
- """Classify user intent to route to correct agent(s)."""
60
- classify_prompt = f"""Classify this user request and identify which agents are needed.
61
-
62
- User message: "{user_message}"
63
-
64
- Respond ONLY with JSON:
65
- {{
66
- "primary_agent": "chat|planner|coding|debug|connector|deploy|workflow|sandbox|memory",
67
- "secondary_agents": [],
68
- "intent": "brief description",
69
- "requires_planning": true/false,
70
- "is_code_task": true/false,
71
- "is_deployment": true/false,
72
- "is_workflow": true/false,
73
- "language": "en|my",
74
- "complexity": "simple|moderate|complex"
75
- }}"""
76
-
77
- if self.ai_router:
78
- messages = [
79
- {"role": "system", "content": "You are an intent classifier. Return only valid JSON."},
80
- {"role": "user", "content": classify_prompt},
81
- ]
82
- raw = await self.ai_router.complete(messages, temperature=0.1, max_tokens=300)
83
- try:
84
- start = raw.find("{")
85
- end = raw.rfind("}") + 1
86
- if start >= 0 and end > start:
87
- return json.loads(raw[start:end])
88
- except Exception:
89
- pass
90
-
91
- # Fallback heuristic classification
92
- msg_lower = user_message.lower()
93
- is_code = any(k in msg_lower for k in ["code", "build", "create", "write", "fix", "debug", "api", "function", "class", "script", "app"])
94
- is_deploy = any(k in msg_lower for k in ["deploy", "vercel", "github", "push", "publish", "release"])
95
- is_workflow = any(k in msg_lower for k in ["workflow", "n8n", "automate", "trigger", "pipeline", "schedule"])
96
- is_memory = any(k in msg_lower for k in ["remember", "recall", "memory", "history", "previous"])
97
-
98
- primary = "coding" if is_code else ("deploy" if is_deploy else ("workflow" if is_workflow else ("memory" if is_memory else "chat")))
99
-
100
- return {
101
- "primary_agent": primary,
102
- "secondary_agents": [],
103
- "intent": user_message[:80],
104
- "requires_planning": is_code or is_deploy,
105
- "is_code_task": is_code,
106
- "is_deployment": is_deploy,
107
- "is_workflow": is_workflow,
108
- "language": "my" if any(c > "\u1000" for c in user_message) else "en",
109
- "complexity": "complex" if len(user_message) > 200 else "moderate",
110
- }
111
-
112
- # ─── Main Orchestration ───────────────────────────────────────────────────
113
-
114
- async def orchestrate(
115
- self,
116
- user_message: str,
117
- session_id: str = "",
118
- task_id: str = "",
119
- context: Dict = {},
120
- ) -> str:
121
- """Main orchestration — classify → route → execute → merge."""
122
- exec_id = task_id or f"orch_{uuid.uuid4().hex[:8]}"
123
-
124
- await self._emit(session_id, task_id, "orchestrator_start", {
125
- "message": user_message[:100],
126
- "session_id": session_id,
127
- })
128
-
129
- # 1. Classify intent
130
- intent = await self.classify_intent(user_message)
131
- log.info("Intent classified", **intent)
132
-
133
- await self._emit(session_id, task_id, "intent_classified", {
134
- "primary_agent": intent["primary_agent"],
135
- "complexity": intent["complexity"],
136
- "language": intent["language"],
137
- })
138
-
139
- # 2. Build execution plan for complex tasks
140
- if intent.get("requires_planning") and intent.get("complexity") == "complex":
141
- planner = self._agents.get("planner")
142
- if planner:
143
- await self._emit(session_id, task_id, "agent_called", {"agent": "PlannerAgent"})
144
- plan = await planner.run(user_message, context=context, session_id=session_id, task_id=exec_id)
145
- context["plan"] = plan
146
-
147
- # 3. Route to primary agent
148
- primary_name = intent["primary_agent"]
149
- primary_agent = self._agents.get(primary_name) or self._agents.get("chat")
150
-
151
- if not primary_agent:
152
- return f"Agent '{primary_name}' not available."
153
-
154
- await self._emit(session_id, task_id, "agent_called", {
155
- "agent": primary_name,
156
- "intent": intent["intent"],
157
- })
158
-
159
- # 4. Execute primary agent
160
- result = await primary_agent.run(
161
- user_message,
162
- context={**context, "intent": intent},
163
- session_id=session_id,
164
- task_id=exec_id,
165
- )
166
-
167
- # 5. Run secondary agents in parallel if needed
168
- secondary_results = []
169
- if intent.get("secondary_agents"):
170
- tasks = []
171
- for agent_name in intent["secondary_agents"]:
172
- agent = self._agents.get(agent_name)
173
- if agent:
174
- tasks.append(agent.run(user_message, context=context, session_id=session_id, task_id=exec_id))
175
- if tasks:
176
- secondary_results = await asyncio.gather(*tasks, return_exceptions=True)
177
-
178
- # 6. Save to memory
179
- memory_agent = self._agents.get("memory")
180
- if memory_agent:
181
- asyncio.create_task(memory_agent.save_interaction(
182
- user_message=user_message,
183
- assistant_response=result,
184
- session_id=session_id,
185
- intent=intent,
186
- ))
187
-
188
- await self._emit(session_id, task_id, "orchestrator_complete", {
189
- "primary_agent": primary_name,
190
- "result_length": len(result),
191
- })
192
-
193
- return result
194
-
195
- # ─── Self-Healing Loop ────────────────────────────────────────────────────
196
-
197
- async def self_heal(
198
- self,
199
- error: str,
200
- original_task: str,
201
- task_id: str = "",
202
- session_id: str = "",
203
- max_retries: int = 3,
204
- ) -> str:
205
- """Self-healing retry loop — automatically fix errors."""
206
- debug_agent = self._agents.get("debug")
207
- if not debug_agent:
208
- return f"Cannot self-heal: DebugAgent not available. Error: {error}"
209
-
210
- for attempt in range(1, max_retries + 1):
211
- await self._emit(session_id, task_id, "self_heal_attempt", {
212
- "attempt": attempt,
213
- "max": max_retries,
214
- "error": error[:200],
215
- })
216
- fix = await debug_agent.run(
217
- f"Fix this error: {error}\n\nOriginal task: {original_task}",
218
- context={"attempt": attempt},
219
- session_id=session_id,
220
- task_id=task_id,
221
- )
222
- if fix and "❌" not in fix[:10]:
223
- await self._emit(session_id, task_id, "self_heal_success", {
224
- "attempt": attempt,
225
- "fix": fix[:200],
226
- })
227
- return fix
228
-
229
- return f"❌ Self-healing failed after {max_retries} attempts. Last error: {error}"
230
-
231
- # ─── Emit Helper ─────────────────────────────────────────────────────────
232
-
233
- async def _emit(self, session_id: str, task_id: str, event: str, data: Dict):
234
- if not self.ws:
235
- return
236
- if task_id:
237
- await self.ws.emit(task_id, event, data, session_id=session_id)
238
- if session_id:
239
- await self.ws.emit_chat(session_id, event, data)
240
-
241
- # ─── Agent Status ────────────────────────────────────────────────────────
242
-
243
- def get_status(self) -> Dict:
244
- return {
245
- "agents": list(self._agents.keys()),
246
- "active_tasks": len(self._active_tasks),
247
- "total_agents": len(self._agents),
248
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
agents/orchestrator_v7.py DELETED
@@ -1,338 +0,0 @@
1
- """
2
- God Agent Orchestrator v7 — True Autonomous Engineering OS
3
- Manus + Genspark + Devin (OneHand) style multi-agent coordination
4
- """
5
- import asyncio
6
- import json
7
- import time
8
- import uuid
9
- from typing import Any, Dict, List, Optional
10
- import structlog
11
-
12
- log = structlog.get_logger()
13
-
14
- SYSTEM_PROMPT_V7 = """You are GOD AGENT v7 — the world's most advanced autonomous AI engineering operating system.
15
-
16
- You combine the best of:
17
- - 🧠 **Manus** — Deep reasoning, multi-step planning, autonomous decision making
18
- - ⚡ **Genspark** — Repository engineering, code generation at scale, multi-model AI routing
19
- - 🤖 **Devin/OneHand** — Self-healing code execution, real browser control, file system mastery
20
-
21
- Your specialized agent fleet (15 agents):
22
- - **OrchestratorAgent** — Central brain, routes & coordinates all agents
23
- - **PlannerAgent** — Breaks complex goals into executable task graphs
24
- - **CodingAgent** — Generates production-quality code in any language
25
- - **DebugAgent** — Autonomous error detection and self-healing
26
- - **TestAgent** — Generates & runs comprehensive test suites
27
- - **FileAgent** — Full file system control, project scaffolding
28
- - **GitAgent** — Git operations, PR creation, code review
29
- - **BrowserAgent** — Web research, scraping, web automation
30
- - **VisionAgent** — UI/UX generation, design-to-code
31
- - **SandboxAgent** — Code execution in isolated environments
32
- - **DeployAgent** — Auto-deploy to Vercel, HF, Docker, AWS
33
- - **ConnectorAgent** — External integrations (GitHub, Slack, Notion, etc.)
34
- - **MemoryAgent** — Long-term memory and context management
35
- - **WorkflowAgent** — n8n/automation workflow generation
36
- - **UIAgent** — Real-time UI state updates
37
-
38
- Operating principles:
39
- 1. PLAN before executing — always create a step-by-step plan for complex tasks
40
- 2. EXECUTE autonomously — don't ask for confirmation on obvious steps
41
- 3. SELF-HEAL — when errors occur, automatically retry with corrections
42
- 4. PARALLELIZE — run independent tasks simultaneously
43
- 5. REMEMBER — store and recall relevant context from memory
44
-
45
- Respond in Burmese or English based on user language.
46
- Be decisive, thorough, and production-focused.
47
- """
48
-
49
-
50
- class GodAgentOrchestratorV7:
51
- """
52
- v7 Central Orchestrator — 15-agent autonomous engineering OS.
53
- Routes tasks, coordinates parallel execution, self-heals failures.
54
- """
55
-
56
- def __init__(self, ws_manager=None, ai_router=None):
57
- self.ws = ws_manager
58
- self.ai_router = ai_router
59
- self._agents: Dict[str, Any] = {}
60
- self._active_tasks: Dict[str, Dict] = {}
61
- self._task_history: List[Dict] = []
62
-
63
- def register_agent(self, name: str, agent):
64
- self._agents[name] = agent
65
- log.info("v7 Agent registered", agent=name)
66
-
67
- def get_agent(self, name: str):
68
- return self._agents.get(name)
69
-
70
- # ── Intent Classification ───────────────────────────────────────────────
71
-
72
- async def classify_intent_v7(self, user_message: str) -> Dict:
73
- """Advanced intent classification for 15-agent routing."""
74
- classify_prompt = f"""Classify this user request for our 15-agent autonomous engineering OS.
75
-
76
- User message: "{user_message}"
77
-
78
- Available agents: orchestrator, planner, coding, debug, test, file, git, browser, vision, sandbox, deploy, connector, memory, workflow, ui
79
-
80
- Respond ONLY with valid JSON:
81
- {{
82
- "primary_agent": "agent_name",
83
- "secondary_agents": ["agent1", "agent2"],
84
- "parallel_tasks": [],
85
- "intent": "brief description",
86
- "requires_planning": true/false,
87
- "is_code_task": true/false,
88
- "is_deployment": true/false,
89
- "is_research": true/false,
90
- "is_ui_task": true/false,
91
- "is_git_task": true/false,
92
- "is_test_task": true/false,
93
- "language": "en|my",
94
- "complexity": "simple|moderate|complex|ultra_complex",
95
- "estimated_steps": 3
96
- }}"""
97
-
98
- if self.ai_router:
99
- messages = [
100
- {"role": "system", "content": "You are an intent classifier. Return only valid JSON."},
101
- {"role": "user", "content": classify_prompt},
102
- ]
103
- raw = await self.ai_router.complete(messages, temperature=0.1, max_tokens=400)
104
- try:
105
- start = raw.find("{")
106
- end = raw.rfind("}") + 1
107
- if start >= 0 and end > start:
108
- return json.loads(raw[start:end])
109
- except Exception:
110
- pass
111
-
112
- # Heuristic fallback
113
- msg = user_message.lower()
114
- is_code = any(k in msg for k in ["code", "build", "create", "write", "fix", "debug", "api", "function", "class", "script", "app", "backend", "frontend"])
115
- is_deploy = any(k in msg for k in ["deploy", "vercel", "github", "push", "publish", "release", "hf", "hugging"])
116
- is_research = any(k in msg for k in ["research", "search", "find", "browse", "web", "scrape", "analyze"])
117
- is_ui = any(k in msg for k in ["ui", "ux", "design", "component", "dashboard", "landing", "page", "frontend"])
118
- is_git = any(k in msg for k in ["git", "commit", "pr", "pull request", "branch", "merge", "clone"])
119
- is_test = any(k in msg for k in ["test", "testing", "pytest", "jest", "coverage", "qa"])
120
- is_file = any(k in msg for k in ["file", "folder", "directory", "scaffold", "project structure"])
121
- is_workflow = any(k in msg for k in ["workflow", "n8n", "automate", "trigger", "pipeline"])
122
- is_memory = any(k in msg for k in ["remember", "recall", "memory", "history", "previous"])
123
-
124
- primary = (
125
- "vision" if is_ui else
126
- "git" if is_git else
127
- "test" if is_test else
128
- "browser" if is_research else
129
- "file" if is_file else
130
- "coding" if is_code else
131
- "deploy" if is_deploy else
132
- "workflow" if is_workflow else
133
- "memory" if is_memory else
134
- "chat"
135
- )
136
-
137
- secondary = []
138
- if is_code and is_deploy:
139
- secondary.append("deploy")
140
- if is_code and is_test:
141
- secondary.append("test")
142
- if is_code and is_git:
143
- secondary.append("git")
144
-
145
- return {
146
- "primary_agent": primary,
147
- "secondary_agents": secondary,
148
- "parallel_tasks": [],
149
- "intent": user_message[:80],
150
- "requires_planning": is_code or is_deploy or len(user_message) > 150,
151
- "is_code_task": is_code,
152
- "is_deployment": is_deploy,
153
- "is_research": is_research,
154
- "is_ui_task": is_ui,
155
- "is_git_task": is_git,
156
- "is_test_task": is_test,
157
- "language": "my" if any(c > "\u1000" for c in user_message) else "en",
158
- "complexity": "ultra_complex" if len(user_message) > 500 else ("complex" if len(user_message) > 200 else "moderate"),
159
- "estimated_steps": 5 if is_code else 3,
160
- }
161
-
162
- # ── Main Orchestration ─────────────────────────────────────────────────
163
-
164
- async def orchestrate(
165
- self,
166
- user_message: str,
167
- session_id: str = "",
168
- task_id: str = "",
169
- context: Dict = {},
170
- ) -> str:
171
- exec_id = task_id or f"v7_{uuid.uuid4().hex[:8]}"
172
-
173
- await self._emit(session_id, task_id, "orchestrator_start", {
174
- "message": user_message[:100],
175
- "version": "v7",
176
- "agents_available": len(self._agents),
177
- })
178
-
179
- # 1. Classify intent
180
- intent = await self.classify_intent_v7(user_message)
181
- log.info("v7 Intent classified", **{k: v for k, v in intent.items() if k != "parallel_tasks"})
182
-
183
- await self._emit(session_id, task_id, "intent_classified", {
184
- "primary_agent": intent["primary_agent"],
185
- "secondary_agents": intent["secondary_agents"],
186
- "complexity": intent["complexity"],
187
- "language": intent["language"],
188
- })
189
-
190
- # 2. Planning phase for complex tasks
191
- plan_context = {}
192
- if intent.get("requires_planning") and intent.get("complexity") in ("complex", "ultra_complex"):
193
- planner = self._agents.get("planner")
194
- if planner:
195
- await self._emit(session_id, task_id, "agent_called", {
196
- "agent": "PlannerAgent", "phase": "planning"
197
- })
198
- try:
199
- plan = await asyncio.wait_for(
200
- planner.run(user_message, context={**context, "intent": intent},
201
- session_id=session_id, task_id=exec_id),
202
- timeout=60
203
- )
204
- plan_context["plan"] = plan
205
- await self._emit(session_id, task_id, "plan_ready", {"plan_length": len(plan)})
206
- except asyncio.TimeoutError:
207
- log.warning("PlannerAgent timed out")
208
-
209
- # 3. Route to primary agent
210
- primary_name = intent["primary_agent"]
211
- primary_agent = self._agents.get(primary_name) or self._agents.get("chat")
212
-
213
- if not primary_agent:
214
- return f"Agent '{primary_name}' not available."
215
-
216
- await self._emit(session_id, task_id, "agent_called", {
217
- "agent": primary_name,
218
- "intent": intent["intent"],
219
- })
220
-
221
- full_context = {**context, **plan_context, "intent": intent}
222
-
223
- # 4. Execute primary agent
224
- try:
225
- result = await asyncio.wait_for(
226
- primary_agent.run(user_message, context=full_context, session_id=session_id, task_id=exec_id),
227
- timeout=300
228
- )
229
- except asyncio.TimeoutError:
230
- result = f"⚠️ Primary agent ({primary_name}) timed out. Please try a more specific request."
231
- except Exception as e:
232
- log.error("Primary agent error", agent=primary_name, error=str(e))
233
- result = await self.self_heal(str(e), user_message, exec_id, session_id)
234
-
235
- # 5. Run secondary agents in parallel
236
- if intent.get("secondary_agents"):
237
- secondary_tasks = []
238
- for agent_name in intent["secondary_agents"]:
239
- agent = self._agents.get(agent_name)
240
- if agent:
241
- secondary_tasks.append(
242
- asyncio.wait_for(
243
- agent.run(user_message, context={**full_context, "primary_result": result},
244
- session_id=session_id, task_id=exec_id),
245
- timeout=120
246
- )
247
- )
248
- if secondary_tasks:
249
- secondary_results = await asyncio.gather(*secondary_tasks, return_exceptions=True)
250
- valid_results = [r for r in secondary_results if isinstance(r, str) and len(r) > 10]
251
- if valid_results:
252
- result += "\n\n---\n\n" + "\n\n".join(valid_results)
253
-
254
- # 6. Save to memory asynchronously
255
- memory_agent = self._agents.get("memory")
256
- if memory_agent:
257
- asyncio.create_task(memory_agent.save_interaction(
258
- user_message=user_message,
259
- assistant_response=result,
260
- session_id=session_id,
261
- intent=intent,
262
- ))
263
-
264
- # 7. Record in task history
265
- self._task_history.append({
266
- "id": exec_id,
267
- "message": user_message[:200],
268
- "primary_agent": primary_name,
269
- "result_length": len(result),
270
- "timestamp": time.time(),
271
- })
272
- if len(self._task_history) > 100:
273
- self._task_history = self._task_history[-100:]
274
-
275
- await self._emit(session_id, task_id, "orchestrator_complete", {
276
- "primary_agent": primary_name,
277
- "result_length": len(result),
278
- "version": "v7",
279
- })
280
-
281
- return result
282
-
283
- # ── Self-Healing ───────────────────────────────────────────────────────
284
-
285
- async def self_heal(self, error: str, original_task: str, task_id: str = "",
286
- session_id: str = "", max_retries: int = 3) -> str:
287
- debug_agent = self._agents.get("debug")
288
- if not debug_agent:
289
- return f"❌ Self-heal unavailable. Error: {error}"
290
-
291
- for attempt in range(1, max_retries + 1):
292
- await self._emit(session_id, task_id, "self_heal_attempt", {
293
- "attempt": attempt, "max": max_retries, "error": error[:200]
294
- })
295
- try:
296
- fix = await asyncio.wait_for(
297
- debug_agent.run(
298
- f"Fix this error: {error}\n\nOriginal task: {original_task}",
299
- context={"attempt": attempt, "error": error},
300
- session_id=session_id, task_id=task_id,
301
- ),
302
- timeout=60
303
- )
304
- if fix and "❌" not in fix[:10]:
305
- await self._emit(session_id, task_id, "self_heal_success", {"attempt": attempt})
306
- return fix
307
- except Exception as e:
308
- log.warning("Self-heal attempt failed", attempt=attempt, error=str(e))
309
-
310
- return f"❌ Self-healing failed after {max_retries} attempts. Error: {error}"
311
-
312
- # ── Helpers ────────────────────────────────────────────────────────────
313
-
314
- async def _emit(self, session_id: str, task_id: str, event: str, data: Dict):
315
- if not self.ws:
316
- return
317
- try:
318
- if task_id:
319
- await self.ws.emit(task_id, event, data, session_id=session_id)
320
- if session_id:
321
- await self.ws.emit_chat(session_id, event, data)
322
- except Exception:
323
- pass
324
-
325
- def get_status(self) -> Dict:
326
- return {
327
- "version": "7.0.0",
328
- "agents": list(self._agents.keys()),
329
- "total_agents": len(self._agents),
330
- "active_tasks": len(self._active_tasks),
331
- "tasks_completed": len(self._task_history),
332
- "capabilities": [
333
- "autonomous_planning", "multi_agent_parallel",
334
- "self_healing", "web_browsing", "file_management",
335
- "git_operations", "ui_generation", "test_generation",
336
- "deployment", "memory", "workflow_automation"
337
- ],
338
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
agents/planner_agent.py DELETED
@@ -1,127 +0,0 @@
1
- """
2
- PlannerAgent — Breaks goals into executable task graphs (Manus-style)
3
- """
4
- import json
5
- from typing import Dict, List
6
- import structlog
7
- from .base_agent import BaseAgent
8
-
9
- log = structlog.get_logger()
10
-
11
- PLANNER_SYSTEM = """You are an elite software architect and project planner.
12
- Break down user goals into detailed, executable task graphs.
13
- Think like Devin/Manus — autonomous, thorough, production-minded.
14
-
15
- Always respond with valid JSON task plans.
16
- """
17
-
18
- PLANNER_PROMPT = """Break this goal into a detailed execution plan.
19
-
20
- Goal: {goal}
21
- Context: {context}
22
-
23
- Respond ONLY with valid JSON:
24
- {{
25
- "title": "Plan title",
26
- "steps": [
27
- {{
28
- "id": "step_1",
29
- "name": "Step name",
30
- "description": "Detailed description",
31
- "agent": "coding|debug|connector|deploy|workflow|sandbox|memory",
32
- "tool": "code|shell|file|github|memory|search|test|none",
33
- "depends_on": [],
34
- "estimated_seconds": 15,
35
- "can_parallel": false
36
- }}
37
- ],
38
- "estimated_duration": 120,
39
- "tools_needed": ["code", "shell"],
40
- "agents_needed": ["coding", "debug"],
41
- "complexity": "simple|moderate|complex"
42
- }}"""
43
-
44
-
45
- class PlannerAgent(BaseAgent):
46
- def __init__(self, ws_manager=None, ai_router=None):
47
- super().__init__("PlannerAgent", ws_manager, ai_router)
48
-
49
- async def run(self, task: str, context: Dict = {}, **kwargs) -> str:
50
- session_id = kwargs.get("session_id", "")
51
- task_id = kwargs.get("task_id", "")
52
-
53
- await self.emit(task_id, "agent_start", {"agent": "PlannerAgent", "goal": task[:80]}, session_id)
54
-
55
- ctx_str = json.dumps(context.get("memory", []))[:300] if context.get("memory") else "No prior context"
56
- prompt = PLANNER_PROMPT.format(goal=task, context=ctx_str)
57
-
58
- messages = [
59
- {"role": "system", "content": PLANNER_SYSTEM},
60
- {"role": "user", "content": prompt},
61
- ]
62
-
63
- raw = await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.2, max_tokens=2000)
64
-
65
- try:
66
- start = raw.find("{")
67
- end = raw.rfind("}") + 1
68
- if start >= 0 and end > start:
69
- plan = json.loads(raw[start:end])
70
- else:
71
- plan = json.loads(raw)
72
-
73
- await self.emit(task_id, "plan_ready", {
74
- "title": plan.get("title", "Execution Plan"),
75
- "steps": len(plan.get("steps", [])),
76
- "estimated_duration": plan.get("estimated_duration", 60),
77
- "agents_needed": plan.get("agents_needed", []),
78
- }, session_id)
79
-
80
- return json.dumps(plan)
81
-
82
- except Exception as e:
83
- log.warning("Plan parse failed", error=str(e))
84
- fallback = self._fallback_plan(task)
85
- await self.emit(task_id, "plan_ready", {"title": "Fallback Plan", "steps": len(fallback["steps"])}, session_id)
86
- return json.dumps(fallback)
87
-
88
- def _fallback_plan(self, goal: str) -> Dict:
89
- return {
90
- "title": f"Plan: {goal[:50]}",
91
- "steps": [
92
- {"id": "step_1", "name": "Analyze Requirements", "description": f"Analyze: {goal[:60]}", "agent": "coding", "tool": "none", "depends_on": [], "estimated_seconds": 10, "can_parallel": False},
93
- {"id": "step_2", "name": "Design Solution", "description": "Design the architecture", "agent": "coding", "tool": "code", "depends_on": ["step_1"], "estimated_seconds": 20, "can_parallel": False},
94
- {"id": "step_3", "name": "Implement", "description": "Write implementation code", "agent": "coding", "tool": "code", "depends_on": ["step_2"], "estimated_seconds": 30, "can_parallel": False},
95
- {"id": "step_4", "name": "Test & Debug", "description": "Test and fix errors", "agent": "debug", "tool": "test", "depends_on": ["step_3"], "estimated_seconds": 20, "can_parallel": False},
96
- {"id": "step_5", "name": "Document", "description": "Write documentation", "agent": "coding", "tool": "file", "depends_on": ["step_4"], "estimated_seconds": 10, "can_parallel": True},
97
- ],
98
- "estimated_duration": 90,
99
- "tools_needed": ["code", "test"],
100
- "agents_needed": ["coding", "debug"],
101
- "complexity": "moderate",
102
- }
103
-
104
- async def build_task_graph(self, plan_json: str) -> List[Dict]:
105
- """Build execution order respecting dependencies."""
106
- try:
107
- plan = json.loads(plan_json)
108
- steps = plan.get("steps", [])
109
- # Topological sort by dependencies
110
- ordered = []
111
- visited = set()
112
-
113
- def visit(step_id):
114
- if step_id in visited:
115
- return
116
- visited.add(step_id)
117
- step = next((s for s in steps if s["id"] == step_id), None)
118
- if step:
119
- for dep in step.get("depends_on", []):
120
- visit(dep)
121
- ordered.append(step)
122
-
123
- for step in steps:
124
- visit(step["id"])
125
- return ordered
126
- except Exception:
127
- return []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
agents/reasoning_agent.py DELETED
@@ -1,173 +0,0 @@
1
- """
2
- ReasoningAgent v7 — Complex reasoning, analysis, and multi-step problem solving
3
- GOD AGENT OS — Using DeepSeek R1, Qwen QwQ, o1-mini style reasoning
4
- """
5
-
6
- import asyncio
7
- import json
8
- from typing import Dict, Any, List, Optional
9
-
10
- import structlog
11
-
12
- from .base_agent import BaseAgent
13
-
14
- log = structlog.get_logger()
15
-
16
- REASONING_SYSTEM = """You are an elite autonomous reasoning and analysis agent.
17
- You excel at:
18
- - Multi-step reasoning with chain-of-thought
19
- - Complex problem decomposition and analysis
20
- - Mathematical and logical reasoning
21
- - Strategic planning and decision making
22
- - Root cause analysis
23
-
24
- Always think step by step, show your reasoning, and provide confident conclusions.
25
- """
26
-
27
-
28
- class ReasoningAgent(BaseAgent):
29
- """
30
- Specialized agent for complex reasoning, analysis, and problem-solving tasks.
31
-
32
- Capabilities:
33
- - Multi-step reasoning with chain-of-thought
34
- - Complex problem decomposition
35
- - Mathematical reasoning
36
- - Logical analysis
37
- - Strategic planning
38
- """
39
-
40
- def __init__(self, ws_manager=None, ai_router=None):
41
- super().__init__("ReasoningAgent", ws_manager, ai_router)
42
- self.reasoning_depth = 3
43
- self.max_reasoning_tokens = 16000
44
-
45
- async def run(self, task: str, context: Dict = {}, **kwargs) -> str:
46
- """Execute reasoning task."""
47
- session_id = kwargs.get("session_id", "")
48
- task_id = kwargs.get("task_id", "")
49
-
50
- await self.emit(task_id, "agent_start", {
51
- "agent": "ReasoningAgent",
52
- "task": task[:80],
53
- }, session_id)
54
-
55
- try:
56
- # Step 1: Analyze the problem
57
- analysis = await self._analyze_problem(task, context, task_id, session_id)
58
-
59
- # Step 2: Decompose if complex
60
- if len(task.split()) > 30:
61
- sub_problems = await self._decompose_problem(task, analysis, task_id, session_id)
62
- solutions = []
63
- for sub in sub_problems[:3]:
64
- sol = await self._solve_sub_problem(sub, context, task_id, session_id)
65
- solutions.append(sol)
66
- result = await self._synthesize_answer(task, analysis, sub_problems, solutions, task_id, session_id)
67
- else:
68
- result = analysis
69
-
70
- await self.emit(task_id, "reasoning_complete", {
71
- "agent": "ReasoningAgent",
72
- "reasoning_depth": self.reasoning_depth,
73
- }, session_id)
74
-
75
- return result
76
-
77
- except Exception as e:
78
- log.error("ReasoningAgent failed", error=str(e))
79
- return "Reasoning agent encountered an error: " + str(e)
80
-
81
- async def _analyze_problem(self, problem: str, context: Dict, task_id: str, session_id: str) -> str:
82
- """Analyze the problem using reasoning model."""
83
- messages = [
84
- {"role": "system", "content": REASONING_SYSTEM},
85
- {"role": "user", "content": (
86
- "Analyze this problem step by step:\n\n"
87
- + problem + "\n\n"
88
- "Provide:\n"
89
- "1. Problem type and complexity\n"
90
- "2. Key constraints and requirements\n"
91
- "3. Step-by-step solution\n"
92
- "4. Final answer/recommendation"
93
- )},
94
- ]
95
- return await self.llm(
96
- messages,
97
- task_id=task_id,
98
- session_id=session_id,
99
- temperature=0.2,
100
- max_tokens=self.max_reasoning_tokens,
101
- )
102
-
103
- async def _decompose_problem(self, problem: str, analysis: str, task_id: str, session_id: str) -> List[str]:
104
- """Break down complex problem into sub-problems."""
105
- messages = [
106
- {"role": "system", "content": REASONING_SYSTEM},
107
- {"role": "user", "content": (
108
- "Break this complex problem into 3 specific sub-problems:\n\n"
109
- + problem + "\n\n"
110
- "Initial analysis: " + analysis[:500] + "\n\n"
111
- "List each sub-problem on a new line starting with '1.', '2.', '3.'"
112
- )},
113
- ]
114
- raw = await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.3, max_tokens=2000)
115
- # Parse numbered sub-problems
116
- lines = raw.split("\n")
117
- sub_problems = []
118
- for line in lines:
119
- line = line.strip()
120
- if line and any(line.startswith(str(i) + ".") for i in range(1, 10)):
121
- sub_problems.append(line)
122
- return sub_problems if sub_problems else [problem]
123
-
124
- async def _solve_sub_problem(self, sub_problem: str, context: Dict, task_id: str, session_id: str) -> str:
125
- """Solve individual sub-problem."""
126
- messages = [
127
- {"role": "system", "content": REASONING_SYSTEM},
128
- {"role": "user", "content": "Solve this specific problem:\n\n" + sub_problem},
129
- ]
130
- return await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.2, max_tokens=4096)
131
-
132
- async def _synthesize_answer(
133
- self,
134
- original: str,
135
- analysis: str,
136
- sub_problems: List[str],
137
- solutions: List[str],
138
- task_id: str,
139
- session_id: str,
140
- ) -> str:
141
- """Synthesize final answer from all reasoning steps."""
142
- solutions_text = "\n".join(
143
- "Sub-problem " + str(i + 1) + ": " + sol[:300]
144
- for i, sol in enumerate(solutions)
145
- )
146
- messages = [
147
- {"role": "system", "content": REASONING_SYSTEM},
148
- {"role": "user", "content": (
149
- "Original problem: " + original + "\n\n"
150
- "Analysis: " + analysis[:800] + "\n\n"
151
- "Solutions to sub-problems:\n" + solutions_text + "\n\n"
152
- "Provide a comprehensive final answer that integrates all insights."
153
- )},
154
- ]
155
- return await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.3, max_tokens=8192)
156
-
157
- def get_status(self) -> Dict[str, Any]:
158
- """Get agent status."""
159
- return {
160
- "name": self.name,
161
- "status": "ready",
162
- "capabilities": [
163
- "Multi-step reasoning",
164
- "Problem decomposition",
165
- "Mathematical reasoning",
166
- "Logical analysis",
167
- "Strategic planning",
168
- ],
169
- "reasoning_depth": self.reasoning_depth,
170
- }
171
-
172
-
173
- __all__ = ["ReasoningAgent"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
agents/sandbox_agent.py DELETED
@@ -1,249 +0,0 @@
1
- """
2
- SandboxAgent — Persistent VS Code sandbox execution (Devin-style)
3
- Controls file system, terminal, git operations in workspace
4
- """
5
- import asyncio
6
- import json
7
- import os
8
- import subprocess
9
- import tempfile
10
- from typing import Dict, List, Optional
11
- import structlog
12
- from .base_agent import BaseAgent
13
-
14
- log = structlog.get_logger()
15
-
16
- WORKSPACE = os.environ.get("WORKSPACE_DIR", "/tmp/god_workspace")
17
-
18
-
19
- class SandboxAgent(BaseAgent):
20
- def __init__(self, ws_manager=None, ai_router=None):
21
- super().__init__("SandboxAgent", ws_manager, ai_router)
22
- os.makedirs(WORKSPACE, exist_ok=True)
23
-
24
- async def run(self, task: str, context: Dict = {}, **kwargs) -> str:
25
- session_id = kwargs.get("session_id", "")
26
- task_id = kwargs.get("task_id", "")
27
-
28
- task_lower = task.lower()
29
-
30
- if "execute" in task_lower or "run" in task_lower or "terminal" in task_lower:
31
- cmd = context.get("command", task)
32
- return await self.execute(cmd, task_id=task_id, session_id=session_id)
33
- elif "write file" in task_lower or "create file" in task_lower:
34
- filename = context.get("filename", "output.txt")
35
- content = context.get("content", "")
36
- return await self.write_file(filename, content, task_id=task_id, session_id=session_id)
37
- elif "read file" in task_lower:
38
- filename = context.get("filename", "")
39
- return await self.read_file(filename, task_id=task_id, session_id=session_id)
40
- elif "git" in task_lower:
41
- return await self.git_operation(task, task_id=task_id, session_id=session_id)
42
- else:
43
- return await self.execute(task, task_id=task_id, session_id=session_id)
44
-
45
- # ─── Terminal Execution ───────────────────────────────────────────────────
46
-
47
- async def execute(
48
- self,
49
- command: str,
50
- cwd: str = "",
51
- timeout: int = 30,
52
- task_id: str = "",
53
- session_id: str = "",
54
- ) -> str:
55
- """Execute shell command in sandbox workspace."""
56
- work_dir = cwd or WORKSPACE
57
-
58
- # Safety: block dangerous commands
59
- blocked = ["rm -rf /", ":(){ :|:& };:", "mkfs", "shutdown", "reboot", "halt", "dd if=/dev/"]
60
- for b in blocked:
61
- if b in command:
62
- return f"❌ Blocked dangerous command: {command[:50]}"
63
-
64
- await self.emit(task_id, "sandbox_exec", {
65
- "command": command[:200],
66
- "cwd": work_dir,
67
- }, session_id)
68
-
69
- try:
70
- proc = await asyncio.create_subprocess_shell(
71
- command,
72
- stdout=asyncio.subprocess.PIPE,
73
- stderr=asyncio.subprocess.PIPE,
74
- cwd=work_dir,
75
- )
76
- stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=timeout)
77
- output = stdout.decode("utf-8", errors="replace")
78
- err = stderr.decode("utf-8", errors="replace")
79
-
80
- result = output[:3000]
81
- if err and proc.returncode != 0:
82
- result += f"\n⚠️ stderr:\n{err[:500]}"
83
-
84
- await self.emit(task_id, "sandbox_result", {
85
- "command": command[:100],
86
- "exit_code": proc.returncode,
87
- "output_length": len(output),
88
- "success": proc.returncode == 0,
89
- }, session_id)
90
-
91
- return result or f"Command executed (exit code: {proc.returncode})"
92
- except asyncio.TimeoutError:
93
- return f"⚠️ Command timed out after {timeout}s"
94
- except Exception as e:
95
- return f"❌ Execution error: {str(e)}"
96
-
97
- # ─── File Operations ──────────────────────────────────────────────────────
98
-
99
- async def write_file(
100
- self,
101
- filename: str,
102
- content: str,
103
- task_id: str = "",
104
- session_id: str = "",
105
- ) -> str:
106
- """Write file to workspace."""
107
- filepath = os.path.join(WORKSPACE, filename)
108
- os.makedirs(os.path.dirname(filepath), exist_ok=True)
109
- try:
110
- with open(filepath, "w", encoding="utf-8") as f:
111
- f.write(content)
112
- await self.emit(task_id, "file_written", {
113
- "filename": filename,
114
- "size": len(content),
115
- "lines": len(content.split("\n")),
116
- "path": filepath,
117
- }, session_id)
118
- return f"✅ File written: `{filename}` ({len(content)} chars, {len(content.split(chr(10)))} lines)"
119
- except Exception as e:
120
- return f"❌ Write failed: {str(e)}"
121
-
122
- async def read_file(
123
- self,
124
- filename: str,
125
- task_id: str = "",
126
- session_id: str = "",
127
- ) -> str:
128
- """Read file from workspace."""
129
- filepath = os.path.join(WORKSPACE, filename)
130
- try:
131
- with open(filepath, "r", encoding="utf-8") as f:
132
- content = f.read()
133
- await self.emit(task_id, "file_read", {
134
- "filename": filename,
135
- "size": len(content),
136
- }, session_id)
137
- return content[:5000]
138
- except FileNotFoundError:
139
- return f"❌ File not found: {filename}"
140
- except Exception as e:
141
- return f"❌ Read failed: {str(e)}"
142
-
143
- async def list_files(self, path: str = "") -> List[str]:
144
- """List files in workspace."""
145
- target = os.path.join(WORKSPACE, path) if path else WORKSPACE
146
- try:
147
- result = []
148
- for root, dirs, files in os.walk(target):
149
- # Skip hidden and cache dirs
150
- dirs[:] = [d for d in dirs if not d.startswith(".") and d != "__pycache__" and d != "node_modules"]
151
- for f in files:
152
- rel = os.path.relpath(os.path.join(root, f), WORKSPACE)
153
- result.append(rel)
154
- if len(result) > 100:
155
- break
156
- return result
157
- except Exception:
158
- return []
159
-
160
- # ─── Git Operations ───────────────────────────────────────────────────────
161
-
162
- async def git_operation(
163
- self,
164
- task: str,
165
- repo_path: str = "",
166
- task_id: str = "",
167
- session_id: str = "",
168
- ) -> str:
169
- """Perform git operations in workspace."""
170
- work_dir = repo_path or WORKSPACE
171
- task_lower = task.lower()
172
-
173
- if "clone" in task_lower:
174
- # Extract URL
175
- words = task.split()
176
- urls = [w for w in words if "github.com" in w or "gitlab.com" in w or ".git" in w]
177
- if urls:
178
- url = urls[0]
179
- return await self.execute(f"git clone {url}", cwd=WORKSPACE, task_id=task_id, session_id=session_id)
180
- return "❌ No git URL found in task."
181
-
182
- elif "commit" in task_lower:
183
- msg = task.replace("commit", "").strip() or "God Agent automated commit"
184
- cmds = [
185
- "git add -A",
186
- f'git commit -m "{msg}"',
187
- ]
188
- results = []
189
- for cmd in cmds:
190
- r = await self.execute(cmd, cwd=work_dir, task_id=task_id, session_id=session_id)
191
- results.append(r)
192
- return "\n".join(results)
193
-
194
- elif "push" in task_lower:
195
- return await self.execute("git push", cwd=work_dir, task_id=task_id, session_id=session_id)
196
-
197
- elif "status" in task_lower:
198
- return await self.execute("git status", cwd=work_dir, task_id=task_id, session_id=session_id)
199
-
200
- elif "log" in task_lower:
201
- return await self.execute("git log --oneline -10", cwd=work_dir, task_id=task_id, session_id=session_id)
202
-
203
- elif "init" in task_lower:
204
- return await self.execute("git init && git add -A", cwd=work_dir, task_id=task_id, session_id=session_id)
205
-
206
- else:
207
- return await self.execute(task, cwd=work_dir, task_id=task_id, session_id=session_id)
208
-
209
- # ─── Package Management ───────────────────────────────────────────────────
210
-
211
- async def install_packages(
212
- self,
213
- packages: List[str],
214
- manager: str = "pip",
215
- task_id: str = "",
216
- session_id: str = "",
217
- ) -> str:
218
- """Install packages in workspace."""
219
- pkg_str = " ".join(packages)
220
- if manager == "pip":
221
- cmd = f"pip install {pkg_str}"
222
- elif manager == "npm":
223
- cmd = f"npm install {pkg_str}"
224
- elif manager == "pnpm":
225
- cmd = f"pnpm add {pkg_str}"
226
- else:
227
- cmd = f"{manager} install {pkg_str}"
228
-
229
- await self.emit(task_id, "installing_packages", {
230
- "manager": manager,
231
- "packages": packages,
232
- }, session_id)
233
- return await self.execute(cmd, task_id=task_id, session_id=session_id)
234
-
235
- # ─── Workspace Info ───────────────────────────────────────────────────────
236
-
237
- async def get_workspace_info(self) -> Dict:
238
- """Get workspace status."""
239
- files = await self.list_files()
240
- try:
241
- disk = await self.execute("df -h /tmp | tail -1")
242
- except Exception:
243
- disk = "N/A"
244
- return {
245
- "path": WORKSPACE,
246
- "file_count": len(files),
247
- "files": files[:20],
248
- "disk_usage": disk,
249
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
agents/test_agent.py DELETED
@@ -1,103 +0,0 @@
1
- """
2
- TestAgent v7 — Autonomous test generation, execution, and quality assurance
3
- Like Devin's self-testing loop + Genspark's QA automation
4
- """
5
- import asyncio
6
- import json
7
- import os
8
- import re
9
- from typing import Dict, List
10
- import structlog
11
- from .base_agent import BaseAgent
12
-
13
- log = structlog.get_logger()
14
-
15
- TEST_SYSTEM = """You are an elite autonomous test engineer.
16
- You generate comprehensive tests: unit, integration, e2e, performance.
17
- You analyze code for bugs, edge cases, and security vulnerabilities.
18
- You write pytest (Python) and Jest/Vitest (TypeScript) tests.
19
- Always aim for 80%+ test coverage and meaningful assertions.
20
- """
21
-
22
-
23
- class TestAgent(BaseAgent):
24
- def __init__(self, ws_manager=None, ai_router=None):
25
- super().__init__("TestAgent", ws_manager, ai_router)
26
- self.workspace = os.environ.get("WORKSPACE_DIR", "/tmp/god_workspace")
27
-
28
- async def run(self, task: str, context: Dict = {}, **kwargs) -> str:
29
- session_id = kwargs.get("session_id", "")
30
- task_id = kwargs.get("task_id", "")
31
- await self.emit(task_id, "agent_start", {"agent": "TestAgent", "task": task[:80]}, session_id)
32
-
33
- t = task.lower()
34
- if any(k in t for k in ["generate test", "write test", "create test"]):
35
- return await self._generate_tests(task, context, task_id, session_id)
36
- if any(k in t for k in ["run test", "execute test", "pytest", "jest"]):
37
- return await self._run_tests(task, context, task_id, session_id)
38
- if any(k in t for k in ["coverage", "quality", "audit"]):
39
- return await self._quality_audit(task, context, task_id, session_id)
40
- return await self._generate_tests(task, context, task_id, session_id)
41
-
42
- async def _generate_tests(self, task: str, context: Dict, task_id: str, session_id: str) -> str:
43
- code = context.get("code", "")
44
- language = context.get("language", "python")
45
- await self.emit(task_id, "tool_called", {
46
- "agent": "TestAgent", "tool": "generate_tests", "step": "Generating tests"
47
- }, session_id)
48
- msgs = [
49
- {"role": "system", "content": TEST_SYSTEM},
50
- {"role": "user", "content": (
51
- f"Task: {task}\nLanguage: {language}\n\n"
52
- f"Code to test:\n{code[:3000] if code else 'Generate tests for: ' + task}\n\n"
53
- "Generate comprehensive tests with:\n"
54
- "1. Happy path tests\n2. Edge case tests\n3. Error handling tests\n"
55
- "4. Mocks for external dependencies\n5. Clear test descriptions"
56
- )},
57
- ]
58
- result = await self.llm(msgs, task_id=task_id, session_id=session_id, temperature=0.2, max_tokens=8192)
59
- # Save test file to workspace
60
- test_filename = f"test_{re.sub(r'[^a-z0-9]', '_', task.lower()[:30])}.py"
61
- test_path = os.path.join(self.workspace, "tests", test_filename)
62
- os.makedirs(os.path.dirname(test_path), exist_ok=True)
63
- code_blocks = re.findall(r'```(?:python|py)?\n(.*?)```', result, re.DOTALL)
64
- if code_blocks:
65
- with open(test_path, "w") as f:
66
- f.write(code_blocks[0])
67
- await self.emit(task_id, "file_written", {"path": test_path}, session_id)
68
- return result
69
-
70
- async def _run_tests(self, task: str, context: Dict, task_id: str, session_id: str) -> str:
71
- repo_path = context.get("repo_path", self.workspace)
72
- await self.emit(task_id, "tool_called", {
73
- "agent": "TestAgent", "tool": "run_tests", "step": "Executing tests"
74
- }, session_id)
75
- # Detect test runner
76
- if os.path.exists(os.path.join(repo_path, "package.json")):
77
- cmd = ["npm", "test", "--", "--watchAll=false"]
78
- else:
79
- cmd = ["python", "-m", "pytest", "-v", "--tb=short"]
80
- try:
81
- proc = await asyncio.create_subprocess_exec(
82
- *cmd, cwd=repo_path,
83
- stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,
84
- )
85
- stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=120)
86
- output = stdout.decode() + stderr.decode()
87
- passed = len(re.findall(r'PASSED|✓|pass', output, re.I))
88
- failed = len(re.findall(r'FAILED|✗|fail', output, re.I))
89
- await self.emit(task_id, "tests_complete", {"passed": passed, "failed": failed}, session_id)
90
- return f"**Test Results:** ✅ {passed} passed | ❌ {failed} failed\n\n```\n{output[:3000]}\n```"
91
- except Exception as e:
92
- return f"❌ Test run error: {str(e)}"
93
-
94
- async def _quality_audit(self, task: str, context: Dict, task_id: str, session_id: str) -> str:
95
- code = context.get("code", "")
96
- msgs = [
97
- {"role": "system", "content": TEST_SYSTEM},
98
- {"role": "user", "content": (
99
- f"Task: {task}\n\nCode:\n{code[:3000]}\n\n"
100
- "Provide quality audit: coverage estimate, complexity score, bugs found, security issues, and recommendations."
101
- )},
102
- ]
103
- return await self.llm(msgs, task_id=task_id, session_id=session_id, temperature=0.3, max_tokens=4096)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
agents/ui_agent.py DELETED
@@ -1,45 +0,0 @@
1
- """
2
- UIAgent — UI component generation (React/Next.js/Tailwind)
3
- """
4
- from typing import Dict
5
- import structlog
6
- from .base_agent import BaseAgent
7
-
8
- log = structlog.get_logger()
9
-
10
- UI_SYSTEM = """You are an expert React/Next.js/Tailwind CSS UI engineer.
11
- You generate beautiful, responsive, production-ready UI components.
12
- Always use:
13
- - TypeScript with proper types
14
- - Tailwind CSS for styling
15
- - shadcn/ui components when appropriate
16
- - Framer Motion for animations
17
- - Lucide React for icons
18
- - Dark mode support
19
- - Mobile-first responsive design
20
- - Accessibility (aria labels, semantic HTML)
21
- """
22
-
23
-
24
- class UIAgent(BaseAgent):
25
- def __init__(self, ws_manager=None, ai_router=None):
26
- super().__init__("UIAgent", ws_manager, ai_router)
27
-
28
- async def run(self, task: str, context: Dict = {}, **kwargs) -> str:
29
- session_id = kwargs.get("session_id", "")
30
- task_id = kwargs.get("task_id", "")
31
-
32
- await self.emit(task_id, "agent_start", {"agent": "UIAgent", "task": task[:80]}, session_id)
33
-
34
- messages = [
35
- {"role": "system", "content": UI_SYSTEM},
36
- {"role": "user", "content": (
37
- f"Generate a complete, production-ready UI component for: {task}\n\n"
38
- f"Requirements:\n"
39
- f"- TypeScript\n- Tailwind CSS\n- Dark mode\n- Mobile responsive\n"
40
- f"- Include all imports\n- Export as default"
41
- )},
42
- ]
43
- result = await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.3, max_tokens=6000)
44
- await self.emit(task_id, "ui_generated", {"agent": "UIAgent"}, session_id)
45
- return result
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
agents/vision_agent.py DELETED
@@ -1,109 +0,0 @@
1
- """
2
- VisionAgent v7 — UI/UX generation, design-to-code, screenshot analysis
3
- Converts designs, wireframes, and visual specs into real code
4
- """
5
- import json
6
- import os
7
- from typing import Dict
8
- import structlog
9
- from .base_agent import BaseAgent
10
-
11
- log = structlog.get_logger()
12
-
13
- VISION_SYSTEM = """You are an elite UI/UX engineer and design-to-code specialist.
14
- You can:
15
- - Convert design mockups and wireframes into pixel-perfect React/Next.js components
16
- - Generate beautiful, responsive UI components with Tailwind CSS
17
- - Create complete page layouts with animations (Framer Motion)
18
- - Analyze screenshots and reproduce UI components
19
- - Generate design systems, color palettes, and typography scales
20
- - Build dashboards, landing pages, admin panels, mobile-first UIs
21
-
22
- Always produce production-ready code with:
23
- - Responsive design (mobile-first)
24
- - Accessibility (ARIA labels, semantic HTML)
25
- - Dark/light mode support
26
- - Smooth animations and transitions
27
- - TypeScript types
28
- """
29
-
30
-
31
- class VisionAgent(BaseAgent):
32
- def __init__(self, ws_manager=None, ai_router=None):
33
- super().__init__("VisionAgent", ws_manager, ai_router)
34
- self.workspace = os.environ.get("WORKSPACE_DIR", "/tmp/god_workspace")
35
-
36
- async def run(self, task: str, context: Dict = {}, **kwargs) -> str:
37
- session_id = kwargs.get("session_id", "")
38
- task_id = kwargs.get("task_id", "")
39
- await self.emit(task_id, "agent_start", {"agent": "VisionAgent", "task": task[:80]}, session_id)
40
-
41
- t = task.lower()
42
- if any(k in t for k in ["dashboard", "admin", "panel"]):
43
- return await self._generate_dashboard(task, context, task_id, session_id)
44
- if any(k in t for k in ["landing", "homepage", "hero"]):
45
- return await self._generate_landing_page(task, context, task_id, session_id)
46
- if any(k in t for k in ["component", "button", "card", "form", "modal", "nav"]):
47
- return await self._generate_component(task, context, task_id, session_id)
48
- return await self._generate_ui(task, context, task_id, session_id)
49
-
50
- async def _generate_dashboard(self, task: str, context: Dict, task_id: str, session_id: str) -> str:
51
- await self.emit(task_id, "tool_called", {
52
- "agent": "VisionAgent", "tool": "generate_dashboard", "step": "Generating dashboard UI"
53
- }, session_id)
54
- msgs = [
55
- {"role": "system", "content": VISION_SYSTEM},
56
- {"role": "user", "content": (
57
- f"Build a complete dashboard UI: {task}\n\n"
58
- "Requirements:\n"
59
- "- Dark theme with glass morphism effects\n"
60
- "- Sidebar navigation with icons\n"
61
- "- Header with user menu\n"
62
- "- Stats cards with trends\n"
63
- "- Data tables with sorting\n"
64
- "- Charts/graphs area\n"
65
- "- React + TypeScript + Tailwind CSS\n"
66
- "Generate the complete component code."
67
- )},
68
- ]
69
- return await self.llm(msgs, task_id=task_id, session_id=session_id, temperature=0.4, max_tokens=8192)
70
-
71
- async def _generate_landing_page(self, task: str, context: Dict, task_id: str, session_id: str) -> str:
72
- await self.emit(task_id, "tool_called", {
73
- "agent": "VisionAgent", "tool": "generate_landing", "step": "Generating landing page"
74
- }, session_id)
75
- msgs = [
76
- {"role": "system", "content": VISION_SYSTEM},
77
- {"role": "user", "content": (
78
- f"Create a stunning landing page: {task}\n\n"
79
- "Include: Hero section, Features grid, Pricing table, Testimonials, CTA, Footer\n"
80
- "Style: Modern, gradient backgrounds, glassmorphism, smooth animations\n"
81
- "Tech: Next.js + TypeScript + Tailwind + Framer Motion"
82
- )},
83
- ]
84
- return await self.llm(msgs, task_id=task_id, session_id=session_id, temperature=0.5, max_tokens=8192)
85
-
86
- async def _generate_component(self, task: str, context: Dict, task_id: str, session_id: str) -> str:
87
- await self.emit(task_id, "tool_called", {
88
- "agent": "VisionAgent", "tool": "generate_component", "step": "Generating UI component"
89
- }, session_id)
90
- msgs = [
91
- {"role": "system", "content": VISION_SYSTEM},
92
- {"role": "user", "content": (
93
- f"Create a polished UI component: {task}\n\n"
94
- "Requirements:\n"
95
- "- Fully typed with TypeScript\n"
96
- "- Responsive and accessible\n"
97
- "- Dark/light mode support\n"
98
- "- Smooth hover/focus animations\n"
99
- "- Props with sensible defaults"
100
- )},
101
- ]
102
- return await self.llm(msgs, task_id=task_id, session_id=session_id, temperature=0.4, max_tokens=8192)
103
-
104
- async def _generate_ui(self, task: str, context: Dict, task_id: str, session_id: str) -> str:
105
- msgs = [
106
- {"role": "system", "content": VISION_SYSTEM},
107
- {"role": "user", "content": f"Generate UI for: {task}\n\nContext: {json.dumps(context)[:300]}"},
108
- ]
109
- return await self.llm(msgs, task_id=task_id, session_id=session_id, temperature=0.5, max_tokens=8192)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
agents/workflow_agent.py DELETED
@@ -1,163 +0,0 @@
1
- """
2
- WorkflowAgent — n8n workflow generation, validation, deployment (Phase 7)
3
- Workflow Factor OS merged into God Agent ecosystem
4
- """
5
- import json
6
- from typing import Dict, List
7
- import structlog
8
- from .base_agent import BaseAgent
9
-
10
- log = structlog.get_logger()
11
-
12
- WORKFLOW_SYSTEM = """You are an expert n8n workflow architect and automation engineer.
13
- You design production-grade automation workflows for:
14
- - Telegram/Discord bots with AI responses
15
- - Data pipelines and ETL processes
16
- - API integrations and webhooks
17
- - Scheduled tasks and cron jobs
18
- - Email/Slack/notification systems
19
- - GitHub CI/CD triggers
20
- - AI-powered automation chains
21
-
22
- Generate valid n8n workflow JSON that can be directly imported.
23
- Think about error handling, retry logic, and edge cases.
24
- """
25
-
26
-
27
- class WorkflowAgent(BaseAgent):
28
- def __init__(self, ws_manager=None, ai_router=None):
29
- super().__init__("WorkflowAgent", ws_manager, ai_router)
30
-
31
- async def run(self, task: str, context: Dict = {}, **kwargs) -> str:
32
- session_id = kwargs.get("session_id", "")
33
- task_id = kwargs.get("task_id", "")
34
-
35
- await self.emit(task_id, "agent_start", {
36
- "agent": "WorkflowAgent",
37
- "task": task[:80],
38
- }, session_id)
39
-
40
- task_lower = task.lower()
41
-
42
- if "telegram" in task_lower:
43
- return await self._telegram_workflow(task, task_id, session_id)
44
- elif "discord" in task_lower:
45
- return await self._discord_workflow(task, task_id, session_id)
46
- elif "schedule" in task_lower or "cron" in task_lower:
47
- return await self._scheduled_workflow(task, task_id, session_id)
48
- elif "github" in task_lower and ("webhook" in task_lower or "trigger" in task_lower):
49
- return await self._github_workflow(task, task_id, session_id)
50
- else:
51
- return await self._generic_workflow(task, task_id, session_id)
52
-
53
- async def _telegram_workflow(self, task: str, task_id: str, session_id: str) -> str:
54
- messages = [
55
- {"role": "system", "content": WORKFLOW_SYSTEM},
56
- {"role": "user", "content": (
57
- f"Create a complete n8n workflow for: {task}\n\n"
58
- f"Include:\n"
59
- f"1. Telegram Trigger node (webhook)\n"
60
- f"2. AI processing node (HTTP Request to API)\n"
61
- f"3. Telegram Send Message node\n"
62
- f"4. Error handling branch\n\n"
63
- f"Also provide:\n"
64
- f"- Setup instructions\n"
65
- f"- Required environment variables\n"
66
- f"- Testing steps\n"
67
- f"- The n8n workflow JSON"
68
- )},
69
- ]
70
- result = await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.2, max_tokens=6000)
71
- await self.emit(task_id, "workflow_generated", {
72
- "type": "telegram_bot",
73
- "agent": "WorkflowAgent",
74
- }, session_id)
75
- return result
76
-
77
- async def _discord_workflow(self, task: str, task_id: str, session_id: str) -> str:
78
- messages = [
79
- {"role": "system", "content": WORKFLOW_SYSTEM},
80
- {"role": "user", "content": (
81
- f"Create a complete n8n workflow for Discord automation: {task}\n\n"
82
- f"Include Discord webhook integration, message processing, and response handling."
83
- )},
84
- ]
85
- result = await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.2, max_tokens=5000)
86
- await self.emit(task_id, "workflow_generated", {"type": "discord", "agent": "WorkflowAgent"}, session_id)
87
- return result
88
-
89
- async def _scheduled_workflow(self, task: str, task_id: str, session_id: str) -> str:
90
- messages = [
91
- {"role": "system", "content": WORKFLOW_SYSTEM},
92
- {"role": "user", "content": (
93
- f"Create a scheduled n8n workflow for: {task}\n\n"
94
- f"Include cron trigger configuration, processing steps, and notification on completion/failure."
95
- )},
96
- ]
97
- result = await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.2)
98
- await self.emit(task_id, "workflow_generated", {"type": "scheduled", "agent": "WorkflowAgent"}, session_id)
99
- return result
100
-
101
- async def _github_workflow(self, task: str, task_id: str, session_id: str) -> str:
102
- messages = [
103
- {"role": "system", "content": WORKFLOW_SYSTEM},
104
- {"role": "user", "content": (
105
- f"Create a GitHub webhook n8n workflow for: {task}\n\n"
106
- f"Include GitHub webhook trigger, event processing, and automated responses/actions."
107
- )},
108
- ]
109
- result = await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.2)
110
- await self.emit(task_id, "workflow_generated", {"type": "github_webhook", "agent": "WorkflowAgent"}, session_id)
111
- return result
112
-
113
- async def _generic_workflow(self, task: str, task_id: str, session_id: str) -> str:
114
- messages = [
115
- {"role": "system", "content": WORKFLOW_SYSTEM},
116
- {"role": "user", "content": (
117
- f"Design a complete automation workflow for: {task}\n\n"
118
- f"Provide:\n"
119
- f"1. Workflow architecture diagram (text)\n"
120
- f"2. n8n node configuration\n"
121
- f"3. Step-by-step setup guide\n"
122
- f"4. Import-ready n8n JSON\n"
123
- f"5. Testing checklist"
124
- )},
125
- ]
126
- result = await self.llm(messages, task_id=task_id, session_id=session_id, temperature=0.3, max_tokens=6000)
127
- await self.emit(task_id, "workflow_generated", {"type": "custom", "agent": "WorkflowAgent"}, session_id)
128
- return result
129
-
130
- async def validate_workflow(self, workflow_json: str) -> Dict:
131
- """Validate n8n workflow JSON structure."""
132
- try:
133
- workflow = json.loads(workflow_json)
134
- nodes = workflow.get("nodes", [])
135
- connections = workflow.get("connections", {})
136
- has_trigger = any(
137
- n.get("type", "").startswith("n8n-nodes-base.") and
138
- ("Trigger" in n.get("type", "") or n.get("type", "").endswith("trigger"))
139
- for n in nodes
140
- )
141
- return {
142
- "valid": True,
143
- "node_count": len(nodes),
144
- "has_trigger": has_trigger,
145
- "connection_count": len(connections),
146
- }
147
- except json.JSONDecodeError as e:
148
- return {"valid": False, "error": f"Invalid JSON: {e}"}
149
- except Exception as e:
150
- return {"valid": False, "error": str(e)}
151
-
152
- async def simulate_workflow(self, workflow_json: str, test_data: Dict = {}) -> str:
153
- """Simulate workflow execution with test data."""
154
- messages = [
155
- {"role": "system", "content": WORKFLOW_SYSTEM},
156
- {"role": "user", "content": (
157
- f"Simulate this n8n workflow execution with test data:\n\n"
158
- f"Workflow: {workflow_json[:1000]}\n\n"
159
- f"Test data: {json.dumps(test_data)}\n\n"
160
- f"Walk through each node's execution and expected output."
161
- )},
162
- ]
163
- return await self.llm(messages, temperature=0.3)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ai_router/__init__.py DELETED
@@ -1,6 +0,0 @@
1
- # Multi-Model AI Router — GOD AGENT OS v8
2
- # Primary: Gemini → Sambanova → GitHub Models (task-aware rotation)
3
- from .router import AIRouter
4
- from .router_v8 import GodModeRouter, get_router, classify_task, get_provider_order
5
-
6
- __all__ = ["AIRouter", "GodModeRouter", "get_router", "classify_task", "get_provider_order"]
 
 
 
 
 
 
 
ai_router/key_pool.py DELETED
@@ -1,131 +0,0 @@
1
- """
2
- KeyPool — Multi-API Key Manager with Failover & Cooldown
3
- God Agent OS v8 — Supports Gemini, SambaNova, GitHub, OpenAI, Groq, etc.
4
- Each provider can have multiple comma-separated keys.
5
- """
6
-
7
- import asyncio
8
- import time
9
- from collections import defaultdict
10
- from typing import Dict, List, Optional
11
- import structlog
12
-
13
- log = structlog.get_logger()
14
-
15
- COOLDOWN_SECONDS = 60 # Key cooling time after max failures
16
- MAX_FAILURES = 3 # Max fails before cooldown
17
-
18
-
19
- class KeyEntry:
20
- def __init__(self, key: str):
21
- self.key = key
22
- self.failures = 0
23
- self.cooldown_until = 0.0
24
- self.calls = 0
25
- self.last_used = 0.0
26
-
27
- def is_available(self) -> bool:
28
- if self.cooldown_until > time.time():
29
- return False
30
- return True
31
-
32
- def mark_fail(self):
33
- self.failures += 1
34
- if self.failures >= MAX_FAILURES:
35
- self.cooldown_until = time.time() + COOLDOWN_SECONDS
36
- log.warning("Key cooldown activated", failures=self.failures)
37
-
38
- def mark_success(self):
39
- self.failures = max(0, self.failures - 1)
40
- self.cooldown_until = 0.0
41
- self.calls += 1
42
- self.last_used = time.time()
43
-
44
- def status(self) -> dict:
45
- remaining = max(0, self.cooldown_until - time.time())
46
- return {
47
- "key_preview": self.key[:8] + "..." + self.key[-4:] if len(self.key) > 12 else "***",
48
- "available": self.is_available(),
49
- "failures": self.failures,
50
- "calls": self.calls,
51
- "cooldown_remaining_s": round(remaining, 1),
52
- }
53
-
54
-
55
- class KeyPool:
56
- """
57
- Pool of API keys for a single provider.
58
- Round-robins through available keys with failure tracking.
59
- """
60
-
61
- def __init__(self, provider: str, keys: List[str]):
62
- self.provider = provider
63
- self._keys: List[KeyEntry] = [KeyEntry(k.strip()) for k in keys if k.strip()]
64
- self._index = 0
65
-
66
- def __len__(self) -> int:
67
- return len(self._keys)
68
-
69
- def pick(self) -> Optional[str]:
70
- """Pick the next available key (round-robin, skip cooling down keys)."""
71
- if not self._keys:
72
- return None
73
- n = len(self._keys)
74
- for _ in range(n):
75
- entry = self._keys[self._index % n]
76
- self._index = (self._index + 1) % n
77
- if entry.is_available():
78
- return entry.key
79
- # All keys in cooldown — try the one with shortest cooldown
80
- soonest = min(self._keys, key=lambda e: e.cooldown_until)
81
- log.warning(
82
- "All keys in cooldown, using soonest",
83
- provider=self.provider,
84
- cooldown_remaining=round(soonest.cooldown_until - time.time(), 1),
85
- )
86
- return soonest.key
87
-
88
- def mark_fail(self, key: str):
89
- for e in self._keys:
90
- if e.key == key:
91
- e.mark_fail()
92
- return
93
-
94
- def mark_success(self, key: str):
95
- for e in self._keys:
96
- if e.key == key:
97
- e.mark_success()
98
- return
99
-
100
- def available_count(self) -> int:
101
- return sum(1 for e in self._keys if e.is_available())
102
-
103
- def status(self) -> dict:
104
- return {
105
- "provider": self.provider,
106
- "total_keys": len(self._keys),
107
- "available_keys": self.available_count(),
108
- "keys": [e.status() for e in self._keys],
109
- }
110
-
111
-
112
- # ─── Global Key Pool Registry ─────────────────────────────────────────────────
113
-
114
- class KeyPoolRegistry:
115
- """Central registry for all provider key pools."""
116
-
117
- def __init__(self):
118
- self._pools: Dict[str, KeyPool] = {}
119
-
120
- def register(self, provider: str, keys_csv: str):
121
- """Register comma-separated keys for a provider."""
122
- keys = [k.strip() for k in keys_csv.split(",") if k.strip()]
123
- if keys:
124
- self._pools[provider] = KeyPool(provider, keys)
125
- log.info("KeyPool registered", provider=provider, count=len(keys))
126
-
127
- def get(self, provider: str) -> Optional[KeyPool]:
128
- return self._pools.get(provider)
129
-
130
- def all_status(self) -> dict:
131
- return {name: pool.status() for name, pool in self._pools.items()}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ai_router/router.py DELETED
@@ -1,264 +0,0 @@
1
- """
2
- Multi-Model AI Router — Phase 9
3
- Supports: OpenAI, Groq, Cerebras, OpenRouter, HuggingFace
4
- Automatic failover chain: OpenAI → Groq → Cerebras → OpenRouter → HF
5
- """
6
-
7
- import asyncio
8
- import json
9
- import os
10
- import time
11
- from typing import Any, Dict, List, Optional
12
-
13
- import httpx
14
- import structlog
15
-
16
- log = structlog.get_logger()
17
-
18
- # ─── Provider Config ──────────────────────────────────────────────────────────
19
- PROVIDERS = [
20
- {
21
- "name": "openai",
22
- "key_env": "OPENAI_API_KEY",
23
- "base_url": os.environ.get("OPENAI_BASE_URL", "https://api.openai.com/v1"),
24
- "default_model": os.environ.get("DEFAULT_MODEL", "gpt-4o"),
25
- "headers_fn": lambda k: {"Authorization": f"Bearer {k}", "Content-Type": "application/json"},
26
- },
27
- {
28
- "name": "groq",
29
- "key_env": "GROQ_API_KEY",
30
- "base_url": "https://api.groq.com/openai/v1",
31
- "default_model": "llama-3.3-70b-versatile",
32
- "headers_fn": lambda k: {"Authorization": f"Bearer {k}", "Content-Type": "application/json"},
33
- },
34
- {
35
- "name": "cerebras",
36
- "key_env": "CEREBRAS_API_KEY",
37
- "base_url": "https://api.cerebras.ai/v1",
38
- "default_model": "llama3.1-70b",
39
- "headers_fn": lambda k: {"Authorization": f"Bearer {k}", "Content-Type": "application/json"},
40
- },
41
- {
42
- "name": "openrouter",
43
- "key_env": "OPENROUTER_API_KEY",
44
- "base_url": "https://openrouter.ai/api/v1",
45
- "default_model": "meta-llama/llama-3.3-70b-instruct:free",
46
- "headers_fn": lambda k: {
47
- "Authorization": f"Bearer {k}",
48
- "Content-Type": "application/json",
49
- "HTTP-Referer": "https://god-agent.ai",
50
- "X-Title": "God Agent Platform",
51
- },
52
- },
53
- {
54
- "name": "anthropic",
55
- "key_env": "ANTHROPIC_API_KEY",
56
- "base_url": "https://api.anthropic.com/v1",
57
- "default_model": "claude-3-5-sonnet-20241022",
58
- "headers_fn": lambda k: {
59
- "x-api-key": k,
60
- "anthropic-version": "2023-06-01",
61
- "Content-Type": "application/json",
62
- },
63
- },
64
- ]
65
-
66
-
67
- class AIRouter:
68
- """
69
- God Mode AI Router — automatically routes and fails over across providers.
70
- Supports streaming token output via WebSocket.
71
- """
72
-
73
- def __init__(self, ws_manager=None):
74
- self.ws = ws_manager
75
- self._stats: Dict[str, Dict] = {p["name"]: {"calls": 0, "errors": 0, "latency": []} for p in PROVIDERS}
76
-
77
- def _get_provider(self, name: str) -> Optional[Dict]:
78
- return next((p for p in PROVIDERS if p["name"] == name), None)
79
-
80
- def _available_providers(self) -> List[Dict]:
81
- """Return providers with valid API keys, in priority order."""
82
- return [p for p in PROVIDERS if os.environ.get(p["key_env"], "")]
83
-
84
- # ─── Main Entry Point ─────────────────────────────────────────────────────
85
-
86
- async def complete(
87
- self,
88
- messages: List[Dict],
89
- task_id: str = "",
90
- session_id: str = "",
91
- temperature: float = 0.7,
92
- max_tokens: int = 4096,
93
- preferred_model: str = "",
94
- stream: bool = True,
95
- ) -> str:
96
- """Route completion through available providers with failover."""
97
- providers = self._available_providers()
98
-
99
- if not providers:
100
- return await self._demo_stream(messages, task_id, session_id)
101
-
102
- last_error = None
103
- for provider in providers:
104
- try:
105
- start = time.time()
106
- if provider["name"] == "anthropic":
107
- result = await self._anthropic_stream(
108
- provider, messages, task_id, session_id, temperature, max_tokens
109
- )
110
- else:
111
- result = await self._openai_compat_stream(
112
- provider, messages, task_id, session_id, temperature, max_tokens, preferred_model
113
- )
114
- elapsed = time.time() - start
115
- self._stats[provider["name"]]["calls"] += 1
116
- self._stats[provider["name"]]["latency"].append(elapsed)
117
- log.info("AI Router success", provider=provider["name"], ms=round(elapsed * 1000))
118
- return result
119
- except Exception as e:
120
- last_error = e
121
- self._stats[provider["name"]]["errors"] += 1
122
- log.warning("AI Router failover", provider=provider["name"], error=str(e))
123
- continue
124
-
125
- log.error("All AI providers failed", last_error=str(last_error))
126
- return await self._demo_stream(messages, task_id, session_id)
127
-
128
- # ─── OpenAI-compatible Stream (OpenAI, Groq, Cerebras, OpenRouter) ────────
129
-
130
- async def _openai_compat_stream(
131
- self, provider, messages, task_id, session_id, temperature, max_tokens, preferred_model
132
- ) -> str:
133
- key = os.environ.get(provider["key_env"], "")
134
- model = preferred_model or provider["default_model"]
135
- headers = provider["headers_fn"](key)
136
- payload = {
137
- "model": model,
138
- "messages": messages,
139
- "stream": True,
140
- "temperature": temperature,
141
- "max_tokens": max_tokens,
142
- }
143
- full_text = ""
144
- async with httpx.AsyncClient(timeout=120) as client:
145
- async with client.stream(
146
- "POST", f"{provider['base_url']}/chat/completions",
147
- headers=headers, json=payload
148
- ) as resp:
149
- resp.raise_for_status()
150
- async for line in resp.aiter_lines():
151
- if not line.startswith("data:"):
152
- continue
153
- chunk = line[6:].strip()
154
- if chunk == "[DONE]":
155
- break
156
- try:
157
- data = json.loads(chunk)
158
- delta = data["choices"][0]["delta"].get("content", "")
159
- if delta:
160
- full_text += delta
161
- await self._emit_chunk(delta, task_id, session_id)
162
- except Exception:
163
- pass
164
- return full_text
165
-
166
- # ─── Anthropic Stream ─────────────────────────────────────────────────────
167
-
168
- async def _anthropic_stream(
169
- self, provider, messages, task_id, session_id, temperature, max_tokens
170
- ) -> str:
171
- key = os.environ.get(provider["key_env"], "")
172
- headers = provider["headers_fn"](key)
173
- system = ""
174
- filtered = []
175
- for m in messages:
176
- if m["role"] == "system":
177
- system = m["content"]
178
- else:
179
- filtered.append(m)
180
- payload = {
181
- "model": provider["default_model"],
182
- "max_tokens": max_tokens,
183
- "messages": filtered,
184
- "stream": True,
185
- }
186
- if system:
187
- payload["system"] = system
188
- full_text = ""
189
- async with httpx.AsyncClient(timeout=120) as client:
190
- async with client.stream(
191
- "POST", f"{provider['base_url']}/messages",
192
- headers=headers, json=payload
193
- ) as resp:
194
- resp.raise_for_status()
195
- async for line in resp.aiter_lines():
196
- if not line.startswith("data:"):
197
- continue
198
- try:
199
- data = json.loads(line[5:].strip())
200
- if data.get("type") == "content_block_delta":
201
- delta = data["delta"].get("text", "")
202
- if delta:
203
- full_text += delta
204
- await self._emit_chunk(delta, task_id, session_id)
205
- except Exception:
206
- pass
207
- return full_text
208
-
209
- # ─── Demo Stream ──────────────────────────────────────────────────────────
210
-
211
- async def _demo_stream(self, messages, task_id, session_id) -> str:
212
- last_user = next(
213
- (m["content"] for m in reversed(messages) if m["role"] == "user"), "Hello"
214
- )
215
- response = (
216
- f"🤖 **God Agent** (Demo Mode)\n\n"
217
- f"Received: *{last_user[:100]}*\n\n"
218
- f"To enable real AI, set one of these env vars:\n"
219
- f"- `OPENAI_API_KEY` (GPT-4o)\n"
220
- f"- `GROQ_API_KEY` (Llama 3.3 70B — Free)\n"
221
- f"- `OPENROUTER_API_KEY` (Multi-model)\n"
222
- f"- `ANTHROPIC_API_KEY` (Claude 3.5)\n\n"
223
- f"**God Mode+ Capabilities Active:**\n"
224
- f"- ⚡ Multi-agent orchestration\n"
225
- f"- 🔧 Autonomous coding & debugging\n"
226
- f"- 🧠 Persistent memory system\n"
227
- f"- 🔌 Connector ecosystem\n"
228
- f"- 📡 Real-time streaming\n"
229
- f"- 🌐 Multi-model failover\n"
230
- )
231
- full_text = ""
232
- for word in response.split():
233
- chunk = word + " "
234
- full_text += chunk
235
- await asyncio.sleep(0.02)
236
- await self._emit_chunk(chunk, task_id, session_id, demo=True)
237
- return full_text
238
-
239
- # ─── Emit Helper ──────────────────────────────────────────────────────────
240
-
241
- async def _emit_chunk(self, chunk: str, task_id: str, session_id: str, demo: bool = False):
242
- if not self.ws:
243
- return
244
- payload = {"chunk": chunk, "demo": demo}
245
- if task_id:
246
- await self.ws.emit(task_id, "llm_chunk", payload, session_id=session_id)
247
- if session_id and not task_id:
248
- await self.ws.emit_chat(session_id, "llm_chunk", payload)
249
-
250
- # ─── Stats ────────────────────────────────────────────────────────────────
251
-
252
- def get_stats(self) -> Dict:
253
- stats = {}
254
- for name, s in self._stats.items():
255
- avg_lat = round(sum(s["latency"][-20:]) / max(len(s["latency"][-20:]), 1) * 1000, 1)
256
- stats[name] = {
257
- "calls": s["calls"],
258
- "errors": s["errors"],
259
- "avg_latency_ms": avg_lat,
260
- "available": bool(os.environ.get(
261
- next((p["key_env"] for p in PROVIDERS if p["name"] == name), ""), ""
262
- )),
263
- }
264
- return stats
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ai_router/router_v10.py DELETED
@@ -1,493 +0,0 @@
1
- """
2
- GOD AGENT OS — Multi-Provider AI Router v10
3
- Primary: Gemini (6 keys) → SambaNova (9 keys) → GitHub Models (9 keys)
4
- Fallback: Groq → OpenAI → Demo
5
- Auto-failover, round-robin KeyPool, task-type routing.
6
- """
7
-
8
- from __future__ import annotations
9
-
10
- import os
11
- import time
12
- from typing import Any, Dict, List, Optional, Tuple
13
-
14
- import httpx
15
- import structlog
16
-
17
- log = structlog.get_logger()
18
-
19
- # ─── Provider Definitions ─────────────────────────────────────────────────────
20
- PROVIDERS: Dict[str, Dict[str, Any]] = {
21
- "gemini": {
22
- "name": "gemini",
23
- "type": "gemini",
24
- "base_url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent",
25
- "key_env": "GEMINI_KEY",
26
- "default_model": "gemini-2.0-flash",
27
- "max_tokens": 8192,
28
- "priority_tasks": ["language", "research", "content", "general", "analysis"],
29
- },
30
- "sambanova": {
31
- "name": "sambanova",
32
- "type": "openai",
33
- "base_url": "https://api.sambanova.ai/v1",
34
- "key_env": "SAMBANOVA_KEY",
35
- "default_model": "Meta-Llama-3.3-70B-Instruct",
36
- "max_tokens": 8192,
37
- "priority_tasks": ["reasoning", "engineering", "planning", "analysis"],
38
- },
39
- "github": {
40
- "name": "github",
41
- "type": "openai",
42
- "base_url": "https://models.inference.ai.azure.com",
43
- "key_env": "GITHUB_KEY",
44
- "default_model": "gpt-4o",
45
- "max_tokens": 4096,
46
- "priority_tasks": ["planning", "engineering", "general"],
47
- },
48
- "groq": {
49
- "name": "groq",
50
- "type": "openai",
51
- "base_url": "https://api.groq.com/openai/v1",
52
- "key_env": "GROQ_API_KEY",
53
- "default_model": "llama-3.3-70b-versatile",
54
- "max_tokens": 8192,
55
- "priority_tasks": ["general"],
56
- },
57
- "openai": {
58
- "name": "openai",
59
- "type": "openai",
60
- "base_url": "https://api.openai.com/v1",
61
- "key_env": "OPENAI_API_KEY",
62
- "default_model": "gpt-4o",
63
- "max_tokens": 4096,
64
- "priority_tasks": ["general"],
65
- },
66
- }
67
-
68
- PRIMARY_ORDER = ["gemini", "sambanova", "github"]
69
- FALLBACK_ORDER = ["groq", "openai"]
70
- KEY_COOLDOWN_SECONDS = 300
71
- KEY_MAX_FAILS = 3
72
- MAX_RETRIES_PER_KEY = 2
73
-
74
-
75
- # ─── KeyPool ──────────────────────────────────────────────────────────────────
76
-
77
- class KeyPool:
78
- """Round-robin key pool with failure tracking and cooldown."""
79
-
80
- def __init__(self, provider: str, raw_keys: str):
81
- self.provider = provider
82
- self._keys: List[Dict[str, Any]] = []
83
- for key in raw_keys.split(","):
84
- key = key.strip()
85
- if key:
86
- self._keys.append({
87
- "key": key,
88
- "fails": 0,
89
- "cooldown_until": 0.0,
90
- "calls": 0,
91
- })
92
- log.info("key_pool_init", provider=provider, keys=len(self._keys))
93
-
94
- def pick(self) -> Optional[Dict[str, Any]]:
95
- now = time.time()
96
- available = [item for item in self._keys if item["cooldown_until"] < now]
97
- if not available:
98
- # All in cooldown — return soonest
99
- if self._keys:
100
- soonest = min(self._keys, key=lambda x: x["cooldown_until"])
101
- log.warning("all_keys_cooldown", provider=self.provider,
102
- wait_s=round(soonest["cooldown_until"] - now, 1))
103
- return soonest
104
- return None
105
- available.sort(key=lambda item: item["fails"])
106
- return available[0]
107
-
108
- def mark_fail(self, key_obj: Dict[str, Any]):
109
- key_obj["fails"] += 1
110
- if key_obj["fails"] >= KEY_MAX_FAILS:
111
- key_obj["cooldown_until"] = time.time() + KEY_COOLDOWN_SECONDS
112
- log.warning("key_cooled_down", provider=self.provider,
113
- key_prefix=key_obj["key"][:8])
114
-
115
- def mark_success(self, key_obj: Dict[str, Any]):
116
- key_obj["fails"] = 0
117
- key_obj["cooldown_until"] = 0.0
118
- key_obj["calls"] += 1
119
-
120
- def has_keys(self) -> bool:
121
- return bool(self._keys)
122
-
123
- def count(self) -> int:
124
- return len(self._keys)
125
-
126
- def available_count(self) -> int:
127
- now = time.time()
128
- return sum(1 for k in self._keys if k["cooldown_until"] < now)
129
-
130
- def status(self) -> Dict[str, Any]:
131
- now = time.time()
132
- return {
133
- "provider": self.provider,
134
- "total_keys": len(self._keys),
135
- "available_keys": self.available_count(),
136
- "keys": [
137
- {
138
- "key_prefix": k["key"][:8] + "...",
139
- "fails": k["fails"],
140
- "calls": k["calls"],
141
- "available": k["cooldown_until"] < now,
142
- "cooldown_s": max(0, round(k["cooldown_until"] - now, 1)),
143
- }
144
- for k in self._keys
145
- ],
146
- }
147
-
148
-
149
- # ─── Task Classifier ──────────────────────────────────────────────────────────
150
-
151
- def classify_task(prompt: str = "") -> str:
152
- p = (prompt or "").lower()
153
- if any(w in p for w in ["code", "function", "implement", "build", "develop", "api", "class", "debug", "script", "program"]):
154
- return "engineering"
155
- if any(w in p for w in ["plan", "strategy", "workflow", "json", "automate", "pipeline", "step", "task"]):
156
- return "planning"
157
- if any(w in p for w in ["analyze", "reasoning", "why", "explain", "evaluate", "compare", "think"]):
158
- return "reasoning"
159
- if any(w in p for w in ["research", "find", "search", "discover", "investigate", "browse", "web"]):
160
- return "research"
161
- if any(w in p for w in ["write", "content", "blog", "article", "copy", "generate text", "summarize", "essay"]):
162
- return "content"
163
- if any(w in p for w in ["translate", "language", "convert", "myanmar", "burmese"]):
164
- return "language"
165
- if any(w in p for w in ["data", "csv", "metrics", "report", "insight", "chart", "graph"]):
166
- return "analysis"
167
- return "general"
168
-
169
-
170
- def get_provider_order(task_type: str, preferred: str = "") -> List[str]:
171
- ordered = sorted(
172
- PRIMARY_ORDER,
173
- key=lambda p: 0 if task_type in PROVIDERS[p]["priority_tasks"] else 1
174
- )
175
- result = ordered + [p for p in FALLBACK_ORDER if os.environ.get(PROVIDERS[p]["key_env"], "")]
176
- if preferred and preferred in PROVIDERS and preferred in result:
177
- result = [preferred] + [p for p in result if p != preferred]
178
- return result
179
-
180
-
181
- # ─── API Calls ────────────────────────────────────────────────────────────────
182
-
183
- async def call_gemini(
184
- base_url: str, key: str,
185
- messages: List[Dict[str, str]], max_tokens: int
186
- ) -> Tuple[bool, str]:
187
- url = f"{base_url}?key={key}"
188
- # Build contents from messages
189
- contents = []
190
- system_text = ""
191
- for msg in messages:
192
- role = msg.get("role", "user")
193
- content = msg.get("content", "")
194
- if role == "system":
195
- system_text = content
196
- elif role == "user":
197
- contents.append({"role": "user", "parts": [{"text": content}]})
198
- elif role == "assistant":
199
- contents.append({"role": "model", "parts": [{"text": content}]})
200
-
201
- if not contents:
202
- contents = [{"role": "user", "parts": [{"text": "Hello"}]}]
203
-
204
- body: Dict[str, Any] = {
205
- "contents": contents,
206
- "generationConfig": {
207
- "maxOutputTokens": min(max_tokens, 8192),
208
- "temperature": 0.7,
209
- },
210
- }
211
- if system_text:
212
- body["systemInstruction"] = {"parts": [{"text": system_text}]}
213
-
214
- try:
215
- async with httpx.AsyncClient(timeout=60.0) as client:
216
- resp = await client.post(url, json=body)
217
- if resp.status_code == 200:
218
- data = resp.json()
219
- candidates = data.get("candidates", [])
220
- if candidates:
221
- text = candidates[0].get("content", {}).get("parts", [{}])[0].get("text", "")
222
- if text:
223
- return True, text
224
- return False, f"Empty response: {str(data)[:200]}"
225
- return False, f"HTTP {resp.status_code}: {resp.text[:300]}"
226
- except Exception as exc:
227
- return False, str(exc)
228
-
229
-
230
- async def call_openai_compat(
231
- base_url: str, key: str, model: str,
232
- messages: List[Dict[str, str]], max_tokens: int
233
- ) -> Tuple[bool, str]:
234
- url = f"{base_url}/chat/completions"
235
- headers = {
236
- "Authorization": f"Bearer {key}",
237
- "Content-Type": "application/json",
238
- }
239
- body = {
240
- "model": model,
241
- "messages": messages,
242
- "max_tokens": max_tokens,
243
- "temperature": 0.7,
244
- }
245
- try:
246
- async with httpx.AsyncClient(timeout=60.0) as client:
247
- resp = await client.post(url, json=body, headers=headers)
248
- if resp.status_code == 200:
249
- data = resp.json()
250
- choices = data.get("choices", [])
251
- if choices:
252
- content = choices[0].get("message", {}).get("content", "")
253
- if content:
254
- return True, content
255
- return False, f"Empty choices: {str(data)[:200]}"
256
- return False, f"HTTP {resp.status_code}: {resp.text[:300]}"
257
- except Exception as exc:
258
- return False, str(exc)
259
-
260
-
261
- # ─── Main Router ──────────────────────────────────────────────────────────────
262
-
263
- class AIRouterV10:
264
- """
265
- God Agent OS AI Router v10.
266
- Multi-provider routing: Gemini (6 keys) → SambaNova (9 keys) → GitHub (9 keys) → fallback.
267
- """
268
-
269
- VERSION = "10.0"
270
-
271
- def __init__(self, ws_manager=None):
272
- self.ws = ws_manager
273
- self._pools: Dict[str, KeyPool] = {}
274
- self._stats: Dict[str, Dict[str, Any]] = {
275
- name: {"calls": 0, "errors": 0, "latency_ms": [], "last_used": 0.0}
276
- for name in PROVIDERS
277
- }
278
- self._load_pools()
279
-
280
- def _load_pools(self):
281
- """Load key pools from environment variables."""
282
- for name, cfg in PROVIDERS.items():
283
- raw = os.environ.get(cfg["key_env"], "").strip()
284
- if raw:
285
- self._pools[name] = KeyPool(name, raw)
286
- loaded = list(self._pools.keys())
287
- log.info("router_v10_loaded", providers=loaded, total=len(loaded))
288
-
289
- def reload_pools(self):
290
- """Hot-reload pools (e.g., after env var update)."""
291
- self._pools.clear()
292
- self._load_pools()
293
-
294
- def get_stats(self) -> Dict[str, Any]:
295
- return {
296
- name: {
297
- "available": name in self._pools and self._pools[name].has_keys(),
298
- "keys": self._pools[name].count() if name in self._pools else 0,
299
- "calls": self._stats[name]["calls"],
300
- "errors": self._stats[name]["errors"],
301
- "avg_latency_ms": (
302
- round(
303
- sum(self._stats[name]["latency_ms"][-20:]) /
304
- max(len(self._stats[name]["latency_ms"][-20:]), 1),
305
- 1,
306
- )
307
- if self._stats[name]["latency_ms"] else 0
308
- ),
309
- }
310
- for name in PROVIDERS
311
- }
312
-
313
- def get_pool_status(self) -> Dict[str, Any]:
314
- return {
315
- name: (
316
- self._pools[name].status()
317
- if name in self._pools
318
- else {"provider": name, "total_keys": 0, "available_keys": 0, "keys": []}
319
- )
320
- for name in PROVIDERS
321
- }
322
-
323
- def get_status(self) -> Dict[str, Any]:
324
- return {
325
- "version": self.VERSION,
326
- "providers": self.get_stats(),
327
- "primary_order": PRIMARY_ORDER,
328
- "fallback_order": FALLBACK_ORDER,
329
- "active_providers": [n for n in self._pools if self._pools[n].has_keys()],
330
- }
331
-
332
- def _normalize_messages(
333
- self,
334
- messages: Optional[List[Dict[str, str]]] = None,
335
- prompt: str = "",
336
- system: str = "",
337
- ) -> Tuple[List[Dict[str, str]], bool]:
338
- if messages:
339
- return messages, False
340
- normalized: List[Dict[str, str]] = []
341
- if system:
342
- normalized.append({"role": "system", "content": system})
343
- normalized.append({"role": "user", "content": prompt or "Hello"})
344
- return normalized, True
345
-
346
- async def complete(
347
- self,
348
- messages: Optional[List[Dict[str, str]]] = None,
349
- task_id: str = "",
350
- session_id: str = "",
351
- temperature: float = 0.7,
352
- max_tokens: int = 4096,
353
- preferred_provider: str = "",
354
- preferred_model: str = "",
355
- stream: bool = False,
356
- prompt: str = "",
357
- system: str = "",
358
- **_: Any,
359
- ) -> Any:
360
- normalized_messages, return_dict = self._normalize_messages(
361
- messages=messages, prompt=prompt, system=system
362
- )
363
- user_msg = next(
364
- (msg.get("content", "") for msg in reversed(normalized_messages) if msg.get("role") == "user"),
365
- "",
366
- )
367
- task_type = classify_task(user_msg)
368
- order = get_provider_order(task_type, preferred=preferred_provider)
369
-
370
- log.info("routing", task_type=task_type, order=order[:3], session=session_id[:8] if session_id else "")
371
- last_error = "No providers available — set GEMINI_KEY, SAMBANOVA_KEY, or GITHUB_KEY"
372
-
373
- for provider_name in order:
374
- if provider_name not in self._pools:
375
- continue
376
-
377
- pool = self._pools[provider_name]
378
- cfg = PROVIDERS[provider_name]
379
- model = preferred_model or cfg["default_model"]
380
-
381
- for _attempt in range(MAX_RETRIES_PER_KEY):
382
- key_obj = pool.pick()
383
- if key_obj is None:
384
- break
385
-
386
- t0 = time.time()
387
- try:
388
- if cfg["type"] == "gemini":
389
- ok, text = await call_gemini(
390
- cfg["base_url"], key_obj["key"],
391
- normalized_messages, min(max_tokens, cfg["max_tokens"])
392
- )
393
- else:
394
- ok, text = await call_openai_compat(
395
- cfg["base_url"], key_obj["key"], model,
396
- normalized_messages, min(max_tokens, cfg["max_tokens"])
397
- )
398
-
399
- elapsed = int((time.time() - t0) * 1000)
400
-
401
- if ok and text.strip():
402
- pool.mark_success(key_obj)
403
- self._stats[provider_name]["calls"] += 1
404
- self._stats[provider_name]["latency_ms"].append(elapsed)
405
- self._stats[provider_name]["last_used"] = time.time()
406
- log.info("llm_success", provider=provider_name, ms=elapsed, task_type=task_type)
407
-
408
- if self.ws and (task_id or session_id):
409
- await self._emit_response(text, task_id, session_id)
410
-
411
- payload = {
412
- "content": text,
413
- "provider": provider_name,
414
- "task_type": task_type,
415
- "latency_ms": elapsed,
416
- "model": model,
417
- }
418
- return payload if return_dict else text
419
-
420
- pool.mark_fail(key_obj)
421
- last_error = text
422
- self._stats[provider_name]["errors"] += 1
423
- log.warning("llm_fail", provider=provider_name, error=text[:150])
424
-
425
- except Exception as exc:
426
- pool.mark_fail(key_obj)
427
- self._stats[provider_name]["errors"] += 1
428
- last_error = str(exc)
429
- log.error("llm_exception", provider=provider_name, error=str(exc)[:200])
430
-
431
- # All failed — return demo
432
- demo = await self._demo_response(normalized_messages, task_type)
433
- log.warning("all_providers_failed", last_error=last_error[:200])
434
- payload = {
435
- "content": demo,
436
- "provider": "demo",
437
- "task_type": task_type,
438
- "error": last_error,
439
- }
440
- return payload if return_dict else demo
441
-
442
- async def _emit_response(self, text: str, task_id: str, session_id: str):
443
- """Emit response through WebSocket if available."""
444
- try:
445
- if task_id and hasattr(self.ws, "emit"):
446
- await self.ws.emit(task_id, "llm_response", {"content": text}, session_id=session_id)
447
- elif session_id and hasattr(self.ws, "emit_chat"):
448
- await self.ws.emit_chat(session_id, "llm_response", {"content": text})
449
- except Exception:
450
- pass
451
-
452
- async def _demo_response(self, messages: List[Dict[str, str]], task_type: str) -> str:
453
- user_msg = next(
454
- (msg.get("content", "") for msg in reversed(messages) if msg.get("role") == "user"),
455
- "Hello"
456
- )
457
- active = list(self._pools.keys())
458
- return (
459
- "🤖 **GOD AGENT OS v10 — Demo Mode**\n\n"
460
- f"Task type detected: `{task_type}`\n"
461
- f"Your request: *{user_msg[:200]}*\n\n"
462
- f"**Active providers:** {active or 'none'}\n\n"
463
- "**To enable real AI, set environment variables:**\n"
464
- "```\n"
465
- "GEMINI_KEY=AIza...,AIza... (comma-separated, 6 keys)\n"
466
- "SAMBANOVA_KEY=uuid,... (comma-separated, 9 keys)\n"
467
- "GITHUB_KEY=ghp_...,ghp_... (comma-separated, 9 keys)\n"
468
- "```\n\n"
469
- "**God Agent OS v10 Features:**\n"
470
- "- 🔑 Multi-key pool routing with auto-failover\n"
471
- "- 🧠 22 distributed worker spaces\n"
472
- "- 🤖 16 autonomous agents\n"
473
- "- 💬 Persistent chat history\n"
474
- "- ⚡ Real-time WebSocket streaming\n"
475
- "- 🌐 Manus-like UI experience\n"
476
- )
477
-
478
-
479
- # ─── Singleton ────────────────────────────────────────────────────────────────
480
-
481
- _router_instance: Optional[AIRouterV10] = None
482
-
483
-
484
- def get_router_v10(ws_manager=None) -> AIRouterV10:
485
- global _router_instance
486
- if _router_instance is None:
487
- _router_instance = AIRouterV10(ws_manager)
488
- return _router_instance
489
-
490
-
491
- # Alias for compatibility
492
- AIRouterV8 = AIRouterV10
493
- GodModeRouter = AIRouterV10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ai_router/router_v3.py DELETED
@@ -1,382 +0,0 @@
1
- """
2
- 🚀 GOD MODE+ v3 - Advanced AI Router with Reasoning Models
3
- Intelligent model selection based on task type and requirements
4
- Version: 3.0.0
5
- """
6
-
7
- import asyncio
8
- import logging
9
- from enum import Enum
10
- from typing import Optional, Dict, List, Any
11
- from dataclasses import dataclass
12
- from datetime import datetime
13
-
14
- import structlog
15
- from openai import AsyncOpenAI, RateLimitError, APIError
16
- from anthropic import AsyncAnthropic
17
-
18
- log = structlog.get_logger()
19
-
20
-
21
- class TaskType(str, Enum):
22
- """Task classification for optimal model selection."""
23
- REASONING = "reasoning"
24
- CODING = "coding"
25
- CHAT = "chat"
26
- ANALYSIS = "analysis"
27
- CREATIVE = "creative"
28
- LIGHTWEIGHT = "lightweight"
29
-
30
-
31
- class ModelProvider(str, Enum):
32
- """Supported AI model providers."""
33
- OPENAI = "openai"
34
- ANTHROPIC = "anthropic"
35
- GROQ = "groq"
36
- DEEPSEEK = "deepseek"
37
- TOGETHER = "together"
38
- OPENROUTER = "openrouter"
39
- CEREBRAS = "cerebras"
40
- QWEN = "qwen"
41
-
42
-
43
- @dataclass
44
- class ModelConfig:
45
- """Configuration for each model."""
46
- provider: ModelProvider
47
- model_id: str
48
- name: str
49
- max_tokens: int
50
- cost_per_1k_input: float
51
- cost_per_1k_output: float
52
- latency_ms: int
53
- reasoning_capable: bool
54
- coding_capable: bool
55
- context_length: int
56
- is_free: bool = False
57
-
58
-
59
- class AIRouterV3:
60
- """
61
- Advanced AI Router with:
62
- - Reasoning model support (DeepSeek R1, Qwen QwQ, o1-mini)
63
- - Smart task-based model selection
64
- - Cost optimization
65
- - Latency optimization
66
- - Automatic failover with exponential backoff
67
- """
68
-
69
- # Model Registry
70
- MODELS: Dict[str, ModelConfig] = {
71
- # Reasoning Models (v3 NEW)
72
- "deepseek-r1": ModelConfig(
73
- provider=ModelProvider.DEEPSEEK,
74
- model_id="deepseek-r1",
75
- name="DeepSeek R1",
76
- max_tokens=8000,
77
- cost_per_1k_input=0.55,
78
- cost_per_1k_output=2.19,
79
- latency_ms=3000,
80
- reasoning_capable=True,
81
- coding_capable=True,
82
- context_length=128000,
83
- ),
84
- "qwen-qwq": ModelConfig(
85
- provider=ModelProvider.QWEN,
86
- model_id="qwen-qwq-32b",
87
- name="Qwen QwQ",
88
- max_tokens=32000,
89
- cost_per_1k_input=0.20,
90
- cost_per_1k_output=0.60,
91
- latency_ms=2500,
92
- reasoning_capable=True,
93
- coding_capable=True,
94
- context_length=32768,
95
- ),
96
- "o1-mini": ModelConfig(
97
- provider=ModelProvider.OPENAI,
98
- model_id="o1-mini",
99
- name="OpenAI o1-mini",
100
- max_tokens=65536,
101
- cost_per_1k_input=3.00,
102
- cost_per_1k_output=12.00,
103
- latency_ms=5000,
104
- reasoning_capable=True,
105
- coding_capable=True,
106
- context_length=128000,
107
- ),
108
- # Standard Models
109
- "gpt-4o": ModelConfig(
110
- provider=ModelProvider.OPENAI,
111
- model_id="gpt-4o",
112
- name="GPT-4o",
113
- max_tokens=4096,
114
- cost_per_1k_input=5.00,
115
- cost_per_1k_output=15.00,
116
- latency_ms=1500,
117
- reasoning_capable=False,
118
- coding_capable=True,
119
- context_length=128000,
120
- ),
121
- "claude-3.5-sonnet": ModelConfig(
122
- provider=ModelProvider.ANTHROPIC,
123
- model_id="claude-3-5-sonnet-20241022",
124
- name="Claude 3.5 Sonnet",
125
- max_tokens=4096,
126
- cost_per_1k_input=3.00,
127
- cost_per_1k_output=15.00,
128
- latency_ms=1200,
129
- reasoning_capable=False,
130
- coding_capable=True,
131
- context_length=200000,
132
- ),
133
- "llama-3.3-70b": ModelConfig(
134
- provider=ModelProvider.GROQ,
135
- model_id="llama-3.3-70b-versatile",
136
- name="Llama 3.3 70B (Groq)",
137
- max_tokens=8192,
138
- cost_per_1k_input=0.00,
139
- cost_per_1k_output=0.00,
140
- latency_ms=800,
141
- reasoning_capable=False,
142
- coding_capable=True,
143
- context_length=8192,
144
- is_free=True,
145
- ),
146
- "mixtral-8x7b": ModelConfig(
147
- provider=ModelProvider.TOGETHER,
148
- model_id="mistralai/Mixtral-8x7B-Instruct-v0.1",
149
- name="Mixtral 8x7B",
150
- max_tokens=4096,
151
- cost_per_1k_input=0.60,
152
- cost_per_1k_output=0.60,
153
- latency_ms=1000,
154
- reasoning_capable=False,
155
- coding_capable=True,
156
- context_length=32768,
157
- ),
158
- }
159
-
160
- # Routing Chains for Different Task Types
161
- ROUTING_CHAINS = {
162
- TaskType.REASONING: [
163
- "deepseek-r1",
164
- "qwen-qwq",
165
- "o1-mini",
166
- "gpt-4o",
167
- "claude-3.5-sonnet",
168
- ],
169
- TaskType.CODING: [
170
- "gpt-4o",
171
- "claude-3.5-sonnet",
172
- "deepseek-r1",
173
- "llama-3.3-70b",
174
- "mixtral-8x7b",
175
- ],
176
- TaskType.CHAT: [
177
- "llama-3.3-70b", # Free first
178
- "gpt-4o",
179
- "claude-3.5-sonnet",
180
- "mixtral-8x7b",
181
- ],
182
- TaskType.ANALYSIS: [
183
- "gpt-4o",
184
- "claude-3.5-sonnet",
185
- "deepseek-r1",
186
- "llama-3.3-70b",
187
- ],
188
- TaskType.CREATIVE: [
189
- "gpt-4o",
190
- "claude-3.5-sonnet",
191
- "mixtral-8x7b",
192
- "llama-3.3-70b",
193
- ],
194
- TaskType.LIGHTWEIGHT: [
195
- "llama-3.3-70b",
196
- "mixtral-8x7b",
197
- "gpt-4o",
198
- ],
199
- }
200
-
201
- def __init__(self, ws_manager=None):
202
- """Initialize AI Router v3."""
203
- self.ws_manager = ws_manager
204
- self.clients = {}
205
- self.model_stats = {}
206
- self.retry_config = {
207
- "max_retries": 3,
208
- "initial_delay": 1,
209
- "max_delay": 30,
210
- "exponential_base": 2,
211
- }
212
- log.info("🤖 AI Router v3 initialized with reasoning models")
213
-
214
- def detect_task_type(self, message: str, context: Dict[str, Any] = None) -> TaskType:
215
- """
216
- Detect task type from message content.
217
- Uses heuristics and optional context hints.
218
- """
219
- message_lower = message.lower()
220
- context = context or {}
221
-
222
- # Check explicit task type hint
223
- if context.get("task_type"):
224
- try:
225
- return TaskType(context["task_type"])
226
- except ValueError:
227
- pass
228
-
229
- # Heuristic detection
230
- if any(word in message_lower for word in ["think", "reason", "why", "explain", "analyze"]):
231
- return TaskType.REASONING
232
-
233
- if any(word in message_lower for word in ["code", "function", "debug", "fix", "implement"]):
234
- return TaskType.CODING
235
-
236
- if any(word in message_lower for word in ["analyze", "compare", "evaluate", "assess"]):
237
- return TaskType.ANALYSIS
238
-
239
- if any(word in message_lower for word in ["write", "create", "story", "poem", "imagine"]):
240
- return TaskType.CREATIVE
241
-
242
- # Default to chat for general conversation
243
- return TaskType.CHAT
244
-
245
- def select_model(
246
- self,
247
- task_type: TaskType,
248
- optimize_for: str = "quality", # "quality", "speed", "cost"
249
- context_length_needed: int = 4096,
250
- ) -> str:
251
- """
252
- Select optimal model based on task type and optimization preference.
253
- """
254
- chain = self.ROUTING_CHAINS.get(task_type, self.ROUTING_CHAINS[TaskType.CHAT])
255
-
256
- if optimize_for == "cost":
257
- # Prefer free models first
258
- for model_id in chain:
259
- if self.MODELS[model_id].is_free:
260
- return model_id
261
- return chain[0]
262
-
263
- elif optimize_for == "speed":
264
- # Sort by latency
265
- sorted_chain = sorted(
266
- chain,
267
- key=lambda m: self.MODELS[m].latency_ms
268
- )
269
- return sorted_chain[0]
270
-
271
- else: # quality (default)
272
- # Prefer models with better reasoning/coding capabilities
273
- if task_type == TaskType.REASONING:
274
- reasoning_models = [m for m in chain if self.MODELS[m].reasoning_capable]
275
- return reasoning_models[0] if reasoning_models else chain[0]
276
- elif task_type == TaskType.CODING:
277
- coding_models = [m for m in chain if self.MODELS[m].coding_capable]
278
- return coding_models[0] if coding_models else chain[0]
279
-
280
- return chain[0]
281
-
282
- async def route(
283
- self,
284
- message: str,
285
- context: Dict[str, Any] = None,
286
- optimize_for: str = "quality",
287
- ) -> Dict[str, Any]:
288
- """
289
- Main routing function: detect task type → select model → execute with failover.
290
- """
291
- context = context or {}
292
- task_type = self.detect_task_type(message, context)
293
- model_id = self.select_model(task_type, optimize_for)
294
-
295
- log.info(
296
- "🎯 Routing decision",
297
- task_type=task_type,
298
- selected_model=model_id,
299
- optimize_for=optimize_for,
300
- )
301
-
302
- # Try selected model with failover chain
303
- chain = self.ROUTING_CHAINS.get(task_type, self.ROUTING_CHAINS[TaskType.CHAT])
304
-
305
- for attempt, fallback_model in enumerate(chain):
306
- try:
307
- result = await self._call_model(fallback_model, message, context)
308
-
309
- # Track success
310
- if fallback_model not in self.model_stats:
311
- self.model_stats[fallback_model] = {"success": 0, "failures": 0}
312
- self.model_stats[fallback_model]["success"] += 1
313
-
314
- return {
315
- "success": True,
316
- "model": fallback_model,
317
- "task_type": task_type,
318
- "response": result,
319
- "attempts": attempt + 1,
320
- }
321
-
322
- except (RateLimitError, APIError) as e:
323
- log.warning(
324
- "⚠️ Model failed, trying next in chain",
325
- model=fallback_model,
326
- error=str(e),
327
- attempt=attempt + 1,
328
- )
329
- if fallback_model not in self.model_stats:
330
- self.model_stats[fallback_model] = {"success": 0, "failures": 0}
331
- self.model_stats[fallback_model]["failures"] += 1
332
-
333
- if attempt < len(chain) - 1:
334
- await asyncio.sleep(self.retry_config["initial_delay"] ** attempt)
335
- continue
336
-
337
- return {
338
- "success": False,
339
- "error": "All models in chain failed",
340
- "task_type": task_type,
341
- "attempts": len(chain),
342
- }
343
-
344
- async def _call_model(self, model_id: str, message: str, context: Dict[str, Any]) -> str:
345
- """Call specific model with appropriate client."""
346
- config = self.MODELS[model_id]
347
-
348
- if config.provider == ModelProvider.OPENAI:
349
- return await self._call_openai(model_id, message, context)
350
- elif config.provider == ModelProvider.ANTHROPIC:
351
- return await self._call_anthropic(model_id, message, context)
352
- elif config.provider == ModelProvider.GROQ:
353
- return await self._call_groq(model_id, message, context)
354
- else:
355
- raise ValueError(f"Provider {config.provider} not yet implemented")
356
-
357
- async def _call_openai(self, model_id: str, message: str, context: Dict[str, Any]) -> str:
358
- """Call OpenAI models (GPT-4o, o1-mini)."""
359
- # Implementation would go here
360
- return f"[{model_id}] Response placeholder"
361
-
362
- async def _call_anthropic(self, model_id: str, message: str, context: Dict[str, Any]) -> str:
363
- """Call Anthropic Claude models."""
364
- # Implementation would go here
365
- return f"[{model_id}] Response placeholder"
366
-
367
- async def _call_groq(self, model_id: str, message: str, context: Dict[str, Any]) -> str:
368
- """Call Groq models (Llama 3.3 70B)."""
369
- # Implementation would go here
370
- return f"[{model_id}] Response placeholder"
371
-
372
- def get_stats(self) -> Dict[str, Any]:
373
- """Get router statistics."""
374
- return {
375
- "models": len(self.MODELS),
376
- "model_stats": self.model_stats,
377
- "timestamp": datetime.now().isoformat(),
378
- }
379
-
380
-
381
- # Export for use in main.py
382
- __all__ = ["AIRouterV3", "TaskType", "ModelProvider"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ai_router/router_v8.py DELETED
@@ -1,321 +0,0 @@
1
- """
2
- GOD AGENT OS — Multi-Provider AI Router v8/v10 compatibility layer.
3
- Primary providers: Gemini -> SambaNova -> GitHub Models.
4
- Supports both legacy `messages=[...]` calls and newer `prompt/system` style calls.
5
- """
6
-
7
- from __future__ import annotations
8
-
9
- import os
10
- import time
11
- from typing import Any, Dict, List, Optional, Tuple
12
-
13
- import httpx
14
- import structlog
15
-
16
- log = structlog.get_logger()
17
-
18
- PROVIDERS = {
19
- "gemini": {
20
- "name": "gemini",
21
- "type": "gemini",
22
- "base_url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent",
23
- "key_env": "GEMINI_KEY",
24
- "default_model": "gemini-2.0-flash",
25
- "max_tokens": 8192,
26
- "priority_tasks": ["language", "research", "content", "general"],
27
- },
28
- "sambanova": {
29
- "name": "sambanova",
30
- "type": "openai",
31
- "base_url": "https://api.sambanova.ai/v1",
32
- "key_env": "SAMBANOVA_KEY",
33
- "default_model": "Meta-Llama-3.3-70B-Instruct",
34
- "max_tokens": 8192,
35
- "priority_tasks": ["reasoning", "engineering", "planning", "analysis"],
36
- },
37
- "github": {
38
- "name": "github",
39
- "type": "openai",
40
- "base_url": "https://models.inference.ai.azure.com",
41
- "key_env": "GITHUB_KEY",
42
- "default_model": "gpt-4o",
43
- "max_tokens": 4096,
44
- "priority_tasks": ["planning", "engineering", "general"],
45
- },
46
- "groq": {
47
- "name": "groq",
48
- "type": "openai",
49
- "base_url": "https://api.groq.com/openai/v1",
50
- "key_env": "GROQ_API_KEY",
51
- "default_model": "llama-3.3-70b-versatile",
52
- "max_tokens": 8192,
53
- "priority_tasks": ["general"],
54
- },
55
- "openai": {
56
- "name": "openai",
57
- "type": "openai",
58
- "base_url": "https://api.openai.com/v1",
59
- "key_env": "OPENAI_API_KEY",
60
- "default_model": "gpt-4o",
61
- "max_tokens": 4096,
62
- "priority_tasks": ["general"],
63
- },
64
- }
65
-
66
- PRIMARY_ORDER = ["gemini", "sambanova", "github"]
67
- FALLBACK_ORDER = ["groq", "openai"]
68
- MAX_RETRIES_PER_KEY = 2
69
- KEY_COOLDOWN_SECONDS = 300
70
- KEY_MAX_FAILS = 3
71
-
72
-
73
- class KeyPool:
74
- def __init__(self, raw_keys: str):
75
- self._keys: List[Dict[str, Any]] = []
76
- for key in raw_keys.split(","):
77
- key = key.strip()
78
- if key:
79
- self._keys.append({"key": key, "fails": 0, "cooldown_until": 0.0})
80
-
81
- def pick(self) -> Optional[Dict[str, Any]]:
82
- now = time.time()
83
- available = [item for item in self._keys if item["cooldown_until"] < now]
84
- if not available:
85
- return None
86
- available.sort(key=lambda item: item["fails"])
87
- return available[0]
88
-
89
- def mark_fail(self, key_obj: Dict[str, Any]):
90
- key_obj["fails"] += 1
91
- if key_obj["fails"] >= KEY_MAX_FAILS:
92
- key_obj["cooldown_until"] = time.time() + KEY_COOLDOWN_SECONDS
93
- log.warning("key_cooled_down", key_prefix=key_obj["key"][:8])
94
-
95
- def mark_success(self, key_obj: Dict[str, Any]):
96
- key_obj["fails"] = 0
97
- key_obj["cooldown_until"] = 0.0
98
-
99
- def has_keys(self) -> bool:
100
- return bool(self._keys)
101
-
102
- def count(self) -> int:
103
- return len(self._keys)
104
-
105
- def status(self) -> List[Dict[str, Any]]:
106
- now = time.time()
107
- result = []
108
- for item in self._keys:
109
- result.append({
110
- "key_prefix": item["key"][:8],
111
- "fails": item["fails"],
112
- "cooldown_seconds": max(0, int(item["cooldown_until"] - now)),
113
- "available": item["cooldown_until"] < now,
114
- })
115
- return result
116
-
117
-
118
- def classify_task(prompt: str = "") -> str:
119
- p = (prompt or "").lower()
120
- if any(word in p for word in ["code", "function", "implement", "build", "develop", "api", "class", "debug"]):
121
- return "engineering"
122
- if any(word in p for word in ["plan", "strategy", "workflow", "json", "automate", "pipeline"]):
123
- return "planning"
124
- if any(word in p for word in ["analyze", "reasoning", "why", "explain", "evaluate", "compare"]):
125
- return "reasoning"
126
- if any(word in p for word in ["research", "find", "search", "discover", "investigate"]):
127
- return "research"
128
- if any(word in p for word in ["write", "content", "blog", "article", "copy", "generate text", "summarize"]):
129
- return "content"
130
- if any(word in p for word in ["translate", "language", "convert"]):
131
- return "language"
132
- if any(word in p for word in ["data", "csv", "metrics", "report", "insight"]):
133
- return "analysis"
134
- return "general"
135
-
136
-
137
- def get_provider_order(task_type: str) -> List[str]:
138
- ordered = sorted(PRIMARY_ORDER, key=lambda provider: 0 if task_type in PROVIDERS[provider]["priority_tasks"] else 1)
139
- return ordered + [provider for provider in FALLBACK_ORDER if os.environ.get(PROVIDERS[provider]["key_env"], "")]
140
-
141
-
142
- async def call_gemini(base_url: str, key: str, messages: List[Dict[str, str]], max_tokens: int) -> Tuple[bool, str]:
143
- url = f"{base_url}?key={key}"
144
- parts = [{"text": message.get("content", "")} for message in messages if message.get("content")]
145
- body = {
146
- "contents": [{"parts": parts or [{"text": "Hello"}]}],
147
- "generationConfig": {"maxOutputTokens": max_tokens, "temperature": 0.7},
148
- }
149
- try:
150
- async with httpx.AsyncClient(timeout=60.0) as client:
151
- resp = await client.post(url, json=body)
152
- if resp.status_code == 200:
153
- data = resp.json()
154
- text = data.get("candidates", [{}])[0].get("content", {}).get("parts", [{}])[0].get("text", "")
155
- return True, text
156
- return False, f"HTTP {resp.status_code}: {resp.text[:200]}"
157
- except Exception as exc:
158
- return False, str(exc)
159
-
160
-
161
- async def call_openai_compat(base_url: str, key: str, model: str, messages: List[Dict[str, str]], max_tokens: int) -> Tuple[bool, str]:
162
- url = f"{base_url}/chat/completions"
163
- headers = {"Authorization": f"Bearer {key}", "Content-Type": "application/json"}
164
- body = {"model": model, "messages": messages, "max_tokens": max_tokens, "temperature": 0.7}
165
- try:
166
- async with httpx.AsyncClient(timeout=60.0) as client:
167
- resp = await client.post(url, json=body, headers=headers)
168
- if resp.status_code == 200:
169
- data = resp.json()
170
- return True, data["choices"][0]["message"]["content"]
171
- return False, f"HTTP {resp.status_code}: {resp.text[:200]}"
172
- except Exception as exc:
173
- return False, str(exc)
174
-
175
-
176
- class GodModeRouter:
177
- def __init__(self, ws_manager=None):
178
- self.ws = ws_manager
179
- self._pools: Dict[str, KeyPool] = {}
180
- self._stats: Dict[str, Dict[str, Any]] = {
181
- name: {"calls": 0, "errors": 0, "latency_ms": []} for name in PROVIDERS
182
- }
183
- self._load_pools()
184
-
185
- def _load_pools(self):
186
- for name, cfg in PROVIDERS.items():
187
- raw = os.environ.get(cfg["key_env"], "")
188
- if raw:
189
- self._pools[name] = KeyPool(raw)
190
- log.info("key_pool_loaded", provider=name, key_count=self._pools[name].count())
191
-
192
- def reload_pools(self):
193
- self._pools.clear()
194
- self._load_pools()
195
-
196
- def get_status(self) -> Dict[str, Any]:
197
- return {
198
- "providers": {
199
- name: {
200
- "available": name in self._pools and self._pools[name].has_keys(),
201
- "keys": self._pools[name].count() if name in self._pools else 0,
202
- "stats": self._stats.get(name, {}),
203
- }
204
- for name in PROVIDERS
205
- },
206
- "primary_order": PRIMARY_ORDER,
207
- }
208
-
209
- def get_stats(self) -> Dict[str, Any]:
210
- return {
211
- name: {"available": name in self._pools, "calls": self._stats[name]["calls"]}
212
- for name in PROVIDERS
213
- }
214
-
215
- def get_pool_status(self) -> Dict[str, Any]:
216
- return {
217
- name: {
218
- "available": name in self._pools and self._pools[name].has_keys(),
219
- "keys": self._pools[name].count() if name in self._pools else 0,
220
- "entries": self._pools[name].status() if name in self._pools else [],
221
- }
222
- for name in PROVIDERS
223
- }
224
-
225
- def _normalize_messages(self, messages=None, prompt: str = "", system: str = "") -> Tuple[List[Dict[str, str]], bool]:
226
- if messages:
227
- return messages, False
228
- normalized: List[Dict[str, str]] = []
229
- if system:
230
- normalized.append({"role": "system", "content": system})
231
- normalized.append({"role": "user", "content": prompt or "Hello"})
232
- return normalized, True
233
-
234
- async def complete(
235
- self,
236
- messages: Optional[List[Dict[str, str]]] = None,
237
- task_id: str = "",
238
- session_id: str = "",
239
- temperature: float = 0.7,
240
- max_tokens: int = 4096,
241
- preferred_provider: str = "",
242
- stream: bool = False,
243
- prompt: str = "",
244
- system: str = "",
245
- preferred_model: str = "",
246
- **_: Any,
247
- ) -> Any:
248
- normalized_messages, return_dict = self._normalize_messages(messages=messages, prompt=prompt, system=system)
249
- user_msg = next((msg.get("content", "") for msg in reversed(normalized_messages) if msg.get("role") == "user"), "")
250
- task_type = classify_task(user_msg)
251
-
252
- if preferred_provider and preferred_provider in PROVIDERS:
253
- order = [preferred_provider] + [provider for provider in get_provider_order(task_type) if provider != preferred_provider]
254
- else:
255
- order = get_provider_order(task_type)
256
-
257
- log.info("routing_request", task_type=task_type, order=order[:3], task_id=task_id, session_id=session_id)
258
- last_error = "No providers available"
259
-
260
- for provider_name in order:
261
- if provider_name not in self._pools:
262
- continue
263
-
264
- pool = self._pools[provider_name]
265
- cfg = PROVIDERS[provider_name]
266
- model = preferred_model or cfg["default_model"]
267
-
268
- for _attempt in range(MAX_RETRIES_PER_KEY):
269
- key_obj = pool.pick()
270
- if key_obj is None:
271
- break
272
-
273
- t0 = time.time()
274
- try:
275
- if cfg["type"] == "gemini":
276
- ok, text = await call_gemini(cfg["base_url"], key_obj["key"], normalized_messages, min(max_tokens, cfg["max_tokens"]))
277
- else:
278
- ok, text = await call_openai_compat(cfg["base_url"], key_obj["key"], model, normalized_messages, min(max_tokens, cfg["max_tokens"]))
279
- elapsed = int((time.time() - t0) * 1000)
280
-
281
- if ok and text.strip():
282
- pool.mark_success(key_obj)
283
- self._stats[provider_name]["calls"] += 1
284
- self._stats[provider_name]["latency_ms"].append(elapsed)
285
- payload = {"content": text, "provider": provider_name, "task_type": task_type, "latency_ms": elapsed}
286
- return payload if return_dict else text
287
-
288
- pool.mark_fail(key_obj)
289
- last_error = text
290
- self._stats[provider_name]["errors"] += 1
291
- log.warning("llm_fail", provider=provider_name, error=text[:120])
292
- except Exception as exc:
293
- pool.mark_fail(key_obj)
294
- self._stats[provider_name]["errors"] += 1
295
- last_error = str(exc)
296
- log.error("llm_exception", provider=provider_name, error=str(exc)[:160])
297
-
298
- demo = await self._demo_response(normalized_messages, task_type)
299
- return {"content": demo, "provider": "demo", "task_type": task_type, "error": last_error} if return_dict else demo
300
-
301
- async def _demo_response(self, messages: List[Dict[str, str]], task_type: str) -> str:
302
- user_msg = next((msg.get("content", "") for msg in reversed(messages) if msg.get("role") == "user"), "Hello")
303
- return (
304
- "[GOD AGENT OS — Demo Mode]\n\n"
305
- f"Task type detected: {task_type}\n"
306
- f"Your request: '{user_msg[:160]}'\n\n"
307
- "Configure API keys in environment: GEMINI_KEY, SAMBANOVA_KEY, GITHUB_KEY"
308
- )
309
-
310
-
311
- _router_instance: Optional[GodModeRouter] = None
312
-
313
-
314
- def get_router(ws_manager=None) -> GodModeRouter:
315
- global _router_instance
316
- if _router_instance is None:
317
- _router_instance = GodModeRouter(ws_manager)
318
- return _router_instance
319
-
320
-
321
- AIRouterV8 = GodModeRouter
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
api/__init__.py DELETED
File without changes
api/routes/__init__.py DELETED
File without changes
api/routes/agents.py DELETED
@@ -1,98 +0,0 @@
1
- """
2
- God Agent Orchestrator API Routes
3
- """
4
- from fastapi import APIRouter, Request, HTTPException
5
- from pydantic import BaseModel
6
- from typing import Optional, Dict, Any
7
-
8
- router = APIRouter()
9
-
10
-
11
- class OrchestrateRequest(BaseModel):
12
- message: str
13
- session_id: str = ""
14
- task_id: str = ""
15
- context: Dict[str, Any] = {}
16
-
17
-
18
- class SandboxExecRequest(BaseModel):
19
- command: str
20
- cwd: str = ""
21
- timeout: int = 30
22
-
23
-
24
- class FileWriteRequest(BaseModel):
25
- filename: str
26
- content: str
27
-
28
-
29
- @router.post("/orchestrate")
30
- async def orchestrate(req: OrchestrateRequest, request: Request):
31
- """Route message through God Agent Orchestrator."""
32
- orchestrator = getattr(request.app.state, "orchestrator", None)
33
- if not orchestrator:
34
- raise HTTPException(500, "Orchestrator not initialized")
35
- result = await orchestrator.orchestrate(
36
- user_message=req.message,
37
- session_id=req.session_id,
38
- task_id=req.task_id,
39
- context=req.context,
40
- )
41
- return {"result": result, "session_id": req.session_id}
42
-
43
-
44
- @router.get("/status")
45
- async def agent_status(request: Request):
46
- """Get all agent statuses."""
47
- orchestrator = getattr(request.app.state, "orchestrator", None)
48
- if not orchestrator:
49
- return {"status": "not_initialized"}
50
- return orchestrator.get_status()
51
-
52
-
53
- @router.post("/sandbox/execute")
54
- async def sandbox_execute(req: SandboxExecRequest, request: Request):
55
- """Execute command in sandbox."""
56
- orchestrator = getattr(request.app.state, "orchestrator", None)
57
- if not orchestrator:
58
- raise HTTPException(500, "Orchestrator not initialized")
59
- sandbox = orchestrator.get_agent("sandbox")
60
- if not sandbox:
61
- raise HTTPException(503, "SandboxAgent not available")
62
- result = await sandbox.execute(req.command, cwd=req.cwd, timeout=req.timeout)
63
- return {"result": result, "command": req.command}
64
-
65
-
66
- @router.post("/sandbox/file")
67
- async def sandbox_write_file(req: FileWriteRequest, request: Request):
68
- """Write file to sandbox workspace."""
69
- orchestrator = getattr(request.app.state, "orchestrator", None)
70
- if not orchestrator:
71
- raise HTTPException(500, "Orchestrator not initialized")
72
- sandbox = orchestrator.get_agent("sandbox")
73
- if not sandbox:
74
- raise HTTPException(503, "SandboxAgent not available")
75
- result = await sandbox.write_file(req.filename, req.content)
76
- return {"result": result, "filename": req.filename}
77
-
78
-
79
- @router.get("/sandbox/workspace")
80
- async def sandbox_workspace(request: Request):
81
- """Get workspace info."""
82
- orchestrator = getattr(request.app.state, "orchestrator", None)
83
- if not orchestrator:
84
- raise HTTPException(500, "Orchestrator not initialized")
85
- sandbox = orchestrator.get_agent("sandbox")
86
- if not sandbox:
87
- raise HTTPException(503, "SandboxAgent not available")
88
- info = await sandbox.get_workspace_info()
89
- return info
90
-
91
-
92
- @router.get("/ai-router/stats")
93
- async def ai_router_stats(request: Request):
94
- """Get AI router statistics."""
95
- ai_router = getattr(request.app.state, "ai_router", None)
96
- if not ai_router:
97
- return {"stats": {}}
98
- return {"stats": ai_router.get_stats()}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
api/routes/chat.py DELETED
@@ -1,214 +0,0 @@
1
- """
2
- Chat + Goal API Routes — Real-time streaming responses
3
- """
4
-
5
- import asyncio
6
- import json
7
- import time
8
- import uuid
9
-
10
- from fastapi import APIRouter, HTTPException, Request
11
- from fastapi.responses import StreamingResponse
12
-
13
- from core.models import ChatRequest, GoalRequest, TaskCreateRequest
14
- from memory.db import save_memory, get_history
15
-
16
- router = APIRouter()
17
-
18
-
19
- def get_engine(request: Request):
20
- return request.app.state.task_engine
21
-
22
-
23
- def get_ws(request: Request):
24
- return request.app.state.ws_manager
25
-
26
-
27
- # ─── Chat (REST + SSE streaming) ───────────────────────────────────────────────
28
-
29
- @router.post("/chat", summary="Chat with the agent")
30
- async def chat(req: ChatRequest, request: Request):
31
- from core.agent import AgentCore
32
- ws = get_ws(request)
33
- agent = AgentCore(ws)
34
-
35
- messages = [{"role": m.role, "content": m.content} for m in req.messages]
36
-
37
- if req.stream:
38
- async def stream_gen():
39
- async def _run():
40
- result = await agent.llm_stream(
41
- messages=messages,
42
- session_id=req.session_id,
43
- model=req.model,
44
- temperature=req.temperature,
45
- max_tokens=req.max_tokens,
46
- )
47
- await save_memory(
48
- content=result,
49
- memory_type="conversation",
50
- session_id=req.session_id,
51
- project_id=req.project_id,
52
- key="assistant",
53
- )
54
- # Save user message too
55
- user_msg = next((m["content"] for m in reversed(messages) if m["role"] == "user"), "")
56
- await save_memory(
57
- content=user_msg,
58
- memory_type="conversation",
59
- session_id=req.session_id,
60
- project_id=req.project_id,
61
- key="user",
62
- )
63
- return result
64
-
65
- room_buffer = []
66
- original_emit_chat = ws.emit_chat
67
- async def capture_emit(sid, etype, data):
68
- if etype == "llm_chunk":
69
- chunk = data.get("chunk", "")
70
- room_buffer.append(chunk)
71
- yield_data = json.dumps({"type": etype, "data": data, "session_id": sid})
72
- return yield_data
73
- return None
74
-
75
- # Stream tokens directly
76
- full = ""
77
- from core.agent import AgentCore as _A
78
- import httpx
79
- import os
80
- OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY", "")
81
- ANTHROPIC_API_KEY = os.environ.get("ANTHROPIC_API_KEY", "")
82
-
83
- if OPENAI_API_KEY:
84
- headers = {
85
- "Authorization": f"Bearer {OPENAI_API_KEY}",
86
- "Content-Type": "application/json",
87
- }
88
- payload = {
89
- "model": req.model,
90
- "messages": messages,
91
- "stream": True,
92
- "temperature": req.temperature,
93
- "max_tokens": req.max_tokens,
94
- }
95
- from core.agent import OPENAI_BASE_URL
96
- async with httpx.AsyncClient(timeout=120) as client:
97
- async with client.stream("POST", f"{OPENAI_BASE_URL}/chat/completions",
98
- headers=headers, json=payload) as resp:
99
- async for line in resp.aiter_lines():
100
- if not line.startswith("data:"):
101
- continue
102
- chunk_str = line[6:].strip()
103
- if chunk_str == "[DONE]":
104
- break
105
- try:
106
- data = json.loads(chunk_str)
107
- delta = data["choices"][0]["delta"].get("content", "")
108
- if delta:
109
- full += delta
110
- yield f"data: {json.dumps({'type': 'llm_chunk', 'data': {'chunk': delta}, 'session_id': req.session_id})}\n\n"
111
- except Exception:
112
- pass
113
- else:
114
- # Demo streaming
115
- demo = (
116
- f"Hello! I'm your Devin-style AI Agent. I received: '{req.messages[-1].content[:80]}'. "
117
- f"Set OPENAI_API_KEY or ANTHROPIC_API_KEY for real AI responses. "
118
- f"I support real-time streaming, task planning, GitHub automation, and more!"
119
- )
120
- for word in demo.split():
121
- chunk = word + " "
122
- full += chunk
123
- await asyncio.sleep(0.04)
124
- yield f"data: {json.dumps({'type': 'llm_chunk', 'data': {'chunk': chunk}, 'session_id': req.session_id})}\n\n"
125
-
126
- yield f"data: {json.dumps({'type': 'stream_end', 'data': {'full_response': full}, 'session_id': req.session_id})}\n\n"
127
-
128
- return StreamingResponse(
129
- stream_gen(),
130
- media_type="text/event-stream",
131
- headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"},
132
- )
133
- else:
134
- # Non-streaming
135
- agent = AgentCore(get_ws(request))
136
- result = await agent.llm_stream(messages, session_id=req.session_id)
137
- return {
138
- "response": result,
139
- "session_id": req.session_id,
140
- "model": req.model,
141
- "timestamp": time.time(),
142
- }
143
-
144
-
145
- @router.post("/chat/stream", summary="Explicit streaming chat endpoint")
146
- async def chat_stream(req: ChatRequest, request: Request):
147
- req.stream = True
148
- return await chat(req, request)
149
-
150
-
151
- # ─── Goal API (create task from goal) ─────────────────────────────────────────
152
-
153
- @router.post("/goal", summary="Submit a high-level goal to the agent")
154
- async def submit_goal(req: GoalRequest, request: Request):
155
- engine = get_engine(request)
156
- task_req = TaskCreateRequest(
157
- goal=req.goal,
158
- session_id=req.session_id,
159
- project_id=req.project_id,
160
- stream=req.stream,
161
- metadata={"source": "goal_api", "github_repo": req.github_repo},
162
- )
163
- task_id = await engine.submit(task_req)
164
- return {
165
- "task_id": task_id,
166
- "goal": req.goal,
167
- "status": "queued",
168
- "session_id": req.session_id,
169
- "ws_url": f"/ws/tasks/{task_id}",
170
- "stream_url": f"/api/v1/tasks/{task_id}/stream",
171
- }
172
-
173
-
174
- @router.post("/goal/stream", summary="Submit goal with SSE streaming response")
175
- async def submit_goal_stream(req: GoalRequest, request: Request):
176
- req.stream = True
177
- return await submit_goal(req, request)
178
-
179
-
180
- # ─── Execute (direct tool execution) ──────────────────────────────────────────
181
-
182
- @router.post("/execute", summary="Execute a tool directly")
183
- async def execute(
184
- tool: str,
185
- task: str,
186
- request: Request,
187
- session_id: str = "",
188
- ):
189
- from tools.executor import ToolExecutor
190
- ws = get_ws(request)
191
- executor = ToolExecutor(ws)
192
- result = await executor.run(
193
- tool=tool,
194
- task=task,
195
- session_id=session_id,
196
- )
197
- return {"tool": tool, "task": task, "result": result, "session_id": session_id}
198
-
199
-
200
- # ─── Plan (generate plan without executing) ───────────────────────────────────
201
-
202
- @router.post("/plan", summary="Generate execution plan for a goal")
203
- async def generate_plan(req: GoalRequest, request: Request):
204
- from core.agent import AgentCore
205
- ws = get_ws(request)
206
- agent = AgentCore(ws)
207
- task_id = f"plan_{uuid.uuid4().hex[:8]}"
208
- plan = await agent.plan(goal=req.goal, task_id=task_id, session_id=req.session_id)
209
- return {
210
- "goal": req.goal,
211
- "plan": plan.model_dump(),
212
- "session_id": req.session_id,
213
- "task_id": task_id,
214
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
api/routes/connectors.py DELETED
@@ -1,49 +0,0 @@
1
- """
2
- Connectors API — Manus-style connector management
3
- """
4
- from fastapi import APIRouter, Request, HTTPException
5
- from pydantic import BaseModel
6
- from typing import Optional
7
- from connectors.manager import ConnectorManager
8
-
9
- router = APIRouter()
10
- connector_manager = ConnectorManager()
11
-
12
-
13
- class SetTokenRequest(BaseModel):
14
- connector_id: str
15
- token: str
16
-
17
-
18
- @router.get("/")
19
- async def get_all_connectors():
20
- return {"connectors": connector_manager.get_all()}
21
-
22
-
23
- @router.get("/connected")
24
- async def get_connected():
25
- return {"connectors": connector_manager.get_connected()}
26
-
27
-
28
- @router.get("/summary")
29
- async def get_summary():
30
- return connector_manager.get_summary()
31
-
32
-
33
- @router.get("/category/{category}")
34
- async def get_by_category(category: str):
35
- return {"connectors": connector_manager.get_by_category(category)}
36
-
37
-
38
- @router.post("/set-token")
39
- async def set_token(req: SetTokenRequest):
40
- connector_manager.set_token(req.connector_id, req.token)
41
- return {"status": "ok", "connector": req.connector_id, "connected": True}
42
-
43
-
44
- @router.get("/{connector_id}/status")
45
- async def get_status(connector_id: str):
46
- return {
47
- "connector_id": connector_id,
48
- "connected": connector_manager.is_connected(connector_id),
49
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
api/routes/github.py DELETED
@@ -1,336 +0,0 @@
1
- """
2
- GitHub Autonomous Engineering API Routes
3
- Clone, commit, push, PR, issues — all autonomous
4
- """
5
-
6
- import os
7
- import time
8
- import asyncio
9
- import tempfile
10
- import shutil
11
- from typing import Optional
12
-
13
- import httpx
14
- from fastapi import APIRouter, HTTPException, Request
15
-
16
- from core.models import (
17
- GitHubCloneRequest, GitHubCreateRepoRequest,
18
- GitHubCommitRequest, GitHubPRRequest, GitHubIssueRequest,
19
- )
20
- from memory.db import save_memory
21
-
22
- router = APIRouter()
23
-
24
- GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN", "")
25
- GITHUB_OWNER = os.environ.get("GITHUB_OWNER", "")
26
- GITHUB_API = "https://api.github.com"
27
-
28
-
29
- def gh_headers():
30
- if not GITHUB_TOKEN:
31
- raise HTTPException(status_code=400, detail="GITHUB_TOKEN not configured")
32
- return {
33
- "Authorization": f"Bearer {GITHUB_TOKEN}",
34
- "Accept": "application/vnd.github+json",
35
- "X-GitHub-Api-Version": "2022-11-28",
36
- }
37
-
38
-
39
- async def gh_get(path: str) -> dict:
40
- async with httpx.AsyncClient(timeout=30) as client:
41
- r = await client.get(f"{GITHUB_API}{path}", headers=gh_headers())
42
- r.raise_for_status()
43
- return r.json()
44
-
45
-
46
- async def gh_post(path: str, data: dict) -> dict:
47
- async with httpx.AsyncClient(timeout=30) as client:
48
- r = await client.post(f"{GITHUB_API}{path}", headers=gh_headers(), json=data)
49
- r.raise_for_status()
50
- return r.json()
51
-
52
-
53
- async def gh_put(path: str, data: dict) -> dict:
54
- async with httpx.AsyncClient(timeout=30) as client:
55
- r = await client.put(f"{GITHUB_API}{path}", headers=gh_headers(), json=data)
56
- r.raise_for_status()
57
- return r.json()
58
-
59
-
60
- async def gh_patch(path: str, data: dict) -> dict:
61
- async with httpx.AsyncClient(timeout=30) as client:
62
- r = await client.patch(f"{GITHUB_API}{path}", headers=gh_headers(), json=data)
63
- r.raise_for_status()
64
- return r.json()
65
-
66
-
67
- # ─── Clone ────────────────────────────────────────────────────────────────────
68
-
69
- @router.post("/clone", summary="Clone a GitHub repository")
70
- async def clone_repo(req: GitHubCloneRequest):
71
- try:
72
- import git
73
- except ImportError:
74
- raise HTTPException(status_code=500, detail="gitpython not installed")
75
-
76
- local_path = req.local_path or f"/tmp/repos/{req.repo_url.split('/')[-1].replace('.git', '')}"
77
- os.makedirs(local_path, exist_ok=True)
78
-
79
- if GITHUB_TOKEN:
80
- url = req.repo_url.replace("https://", f"https://{GITHUB_TOKEN}@")
81
- else:
82
- url = req.repo_url
83
-
84
- try:
85
- if os.path.exists(os.path.join(local_path, ".git")):
86
- repo = git.Repo(local_path)
87
- repo.remotes.origin.pull()
88
- action = "pulled"
89
- else:
90
- repo = git.Repo.clone_from(url, local_path, branch=req.branch, depth=1)
91
- action = "cloned"
92
-
93
- files = []
94
- for root, dirs, fnames in os.walk(local_path):
95
- dirs[:] = [d for d in dirs if d not in [".git", "node_modules", "__pycache__"]]
96
- for f in fnames[:50]:
97
- files.append(os.path.relpath(os.path.join(root, f), local_path))
98
-
99
- # Save to memory
100
- await save_memory(
101
- content=f"Repo {req.repo_url} cloned to {local_path}. Files: {', '.join(files[:20])}",
102
- memory_type="repo",
103
- key=req.repo_url,
104
- )
105
-
106
- return {
107
- "action": action,
108
- "repo_url": req.repo_url,
109
- "local_path": local_path,
110
- "branch": req.branch,
111
- "files_count": len(files),
112
- "files": files[:30],
113
- }
114
- except Exception as e:
115
- raise HTTPException(status_code=500, detail=f"Clone failed: {str(e)}")
116
-
117
-
118
- # ─── Create Repo ──────────────────────────────────────────────────────────────
119
-
120
- @router.post("/create_repo", summary="Create a new GitHub repository")
121
- async def create_repo(req: GitHubCreateRepoRequest):
122
- data = {
123
- "name": req.name,
124
- "description": req.description,
125
- "private": req.private,
126
- "auto_init": req.auto_init,
127
- }
128
- try:
129
- result = await gh_post("/user/repos", data)
130
- return {
131
- "repo": result["full_name"],
132
- "url": result["html_url"],
133
- "clone_url": result["clone_url"],
134
- "default_branch": result.get("default_branch", "main"),
135
- "private": result["private"],
136
- }
137
- except httpx.HTTPStatusError as e:
138
- raise HTTPException(status_code=e.response.status_code, detail=e.response.text)
139
-
140
-
141
- # ─── Commit Files ─────────────────────────────────────────────────────────────
142
-
143
- @router.post("/commit", summary="Commit files to a repository")
144
- async def commit_files(req: GitHubCommitRequest):
145
- import base64
146
-
147
- owner_repo = req.repo if "/" in req.repo else f"{GITHUB_OWNER}/{req.repo}"
148
- results = []
149
-
150
- for file_path, content in req.files.items():
151
- encoded = base64.b64encode(content.encode()).decode()
152
-
153
- # Get current SHA if file exists
154
- sha = None
155
- try:
156
- existing = await gh_get(f"/repos/{owner_repo}/contents/{file_path}?ref={req.branch}")
157
- sha = existing.get("sha")
158
- except Exception:
159
- pass
160
-
161
- payload = {
162
- "message": req.message,
163
- "content": encoded,
164
- "branch": req.branch,
165
- }
166
- if sha:
167
- payload["sha"] = sha
168
-
169
- try:
170
- result = await gh_put(f"/repos/{owner_repo}/contents/{file_path}", payload)
171
- results.append({"file": file_path, "status": "committed", "sha": result["content"]["sha"]})
172
- except Exception as e:
173
- results.append({"file": file_path, "status": "error", "error": str(e)})
174
-
175
- return {
176
- "repo": owner_repo,
177
- "branch": req.branch,
178
- "message": req.message,
179
- "files": results,
180
- "committed": sum(1 for r in results if r["status"] == "committed"),
181
- }
182
-
183
-
184
- # ─── Push ─────────────────────────────────────────────────────────────────────
185
-
186
- @router.post("/push", summary="Push local changes to remote")
187
- async def push_changes(
188
- repo_path: str,
189
- branch: str = "main",
190
- message: str = "Auto-commit by Devin Agent",
191
- ):
192
- try:
193
- import git
194
- repo = git.Repo(repo_path)
195
- repo.git.add(A=True)
196
- if repo.index.diff("HEAD") or repo.untracked_files:
197
- repo.index.commit(message)
198
- origin = repo.remote("origin")
199
- origin.push(refspec=f"HEAD:{branch}")
200
- return {"status": "pushed", "branch": branch, "message": message}
201
- except Exception as e:
202
- raise HTTPException(status_code=500, detail=f"Push failed: {str(e)}")
203
-
204
-
205
- # ─── Create PR ────────────────────────────────────────────────────────────────
206
-
207
- @router.post("/pr/create", summary="Create a Pull Request")
208
- async def create_pr(req: GitHubPRRequest):
209
- owner_repo = req.repo if "/" in req.repo else f"{GITHUB_OWNER}/{req.repo}"
210
- data = {
211
- "title": req.title,
212
- "body": req.body,
213
- "head": req.head,
214
- "base": req.base,
215
- "draft": req.draft,
216
- }
217
- try:
218
- result = await gh_post(f"/repos/{owner_repo}/pulls", data)
219
- return {
220
- "pr_number": result["number"],
221
- "title": result["title"],
222
- "url": result["html_url"],
223
- "state": result["state"],
224
- "head": req.head,
225
- "base": req.base,
226
- }
227
- except httpx.HTTPStatusError as e:
228
- raise HTTPException(status_code=e.response.status_code, detail=e.response.text)
229
-
230
-
231
- # ─── Create Issue ─────────────────────────────────────────────────────────────
232
-
233
- @router.post("/issues/create", summary="Create a GitHub Issue")
234
- async def create_issue(req: GitHubIssueRequest):
235
- owner_repo = req.repo if "/" in req.repo else f"{GITHUB_OWNER}/{req.repo}"
236
- data = {"title": req.title, "body": req.body, "labels": req.labels}
237
- try:
238
- result = await gh_post(f"/repos/{owner_repo}/issues", data)
239
- return {
240
- "issue_number": result["number"],
241
- "title": result["title"],
242
- "url": result["html_url"],
243
- "state": result["state"],
244
- }
245
- except httpx.HTTPStatusError as e:
246
- raise HTTPException(status_code=e.response.status_code, detail=e.response.text)
247
-
248
-
249
- # ─── Code Review ──────────────────────────────────────────────────────────────
250
-
251
- @router.post("/review", summary="AI code review for a PR")
252
- async def review_pr(repo: str, pr_number: int, request: Request):
253
- owner_repo = repo if "/" in repo else f"{GITHUB_OWNER}/{repo}"
254
- try:
255
- pr = await gh_get(f"/repos/{owner_repo}/pulls/{pr_number}")
256
- files = await gh_get(f"/repos/{owner_repo}/pulls/{pr_number}/files")
257
-
258
- file_changes = []
259
- for f in files[:10]:
260
- file_changes.append(f"{f['filename']}: +{f.get('additions',0)}/-{f.get('deletions',0)}")
261
-
262
- ws = request.app.state.ws_manager
263
- from core.agent import AgentCore
264
- agent = AgentCore(ws)
265
-
266
- review_prompt = (
267
- f"Review this Pull Request:\n"
268
- f"Title: {pr['title']}\n"
269
- f"Description: {pr.get('body', 'No description')}\n"
270
- f"Files changed: {chr(10).join(file_changes)}\n\n"
271
- f"Provide a constructive code review with: summary, potential issues, suggestions, and verdict."
272
- )
273
- messages = [
274
- {"role": "system", "content": "You are a senior software engineer doing code review. Be constructive, specific, and helpful."},
275
- {"role": "user", "content": review_prompt},
276
- ]
277
- review = await agent.llm_stream(messages)
278
-
279
- # Post review comment
280
- if GITHUB_TOKEN:
281
- await gh_post(f"/repos/{owner_repo}/issues/{pr_number}/comments", {"body": f"🤖 **Devin Agent Code Review**\n\n{review}"})
282
-
283
- return {
284
- "pr_number": pr_number,
285
- "title": pr["title"],
286
- "review": review,
287
- "files_reviewed": len(files),
288
- "posted_to_github": bool(GITHUB_TOKEN),
289
- }
290
- except Exception as e:
291
- raise HTTPException(status_code=500, detail=str(e))
292
-
293
-
294
- # ─── Repo Info ────────────────────────────────────────────────────────────────
295
-
296
- @router.get("/repo/{owner}/{repo}", summary="Get repository info")
297
- async def get_repo_info(owner: str, repo: str):
298
- try:
299
- info = await gh_get(f"/repos/{owner}/{repo}")
300
- return {
301
- "name": info["name"],
302
- "full_name": info["full_name"],
303
- "description": info.get("description"),
304
- "url": info["html_url"],
305
- "default_branch": info["default_branch"],
306
- "language": info.get("language"),
307
- "stars": info["stargazers_count"],
308
- "forks": info["forks_count"],
309
- "open_issues": info["open_issues_count"],
310
- "private": info["private"],
311
- }
312
- except httpx.HTTPStatusError as e:
313
- raise HTTPException(status_code=e.response.status_code, detail=e.response.text)
314
-
315
-
316
- # ─── Status check ─────────────────────────────────────────────────────────────
317
-
318
- @router.get("/status", summary="GitHub integration status")
319
- async def github_status():
320
- configured = bool(GITHUB_TOKEN)
321
- user = None
322
- if configured:
323
- try:
324
- user_info = await gh_get("/user")
325
- user = user_info.get("login")
326
- except Exception:
327
- configured = False
328
- return {
329
- "configured": configured,
330
- "user": user,
331
- "owner": GITHUB_OWNER or user,
332
- "capabilities": [
333
- "clone", "create_repo", "commit", "push",
334
- "pr/create", "issues/create", "review"
335
- ],
336
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
api/routes/health.py DELETED
@@ -1,89 +0,0 @@
1
- """
2
- Health + Status Routes — GOD AGENT OS v11
3
- """
4
-
5
- import time
6
- import os
7
- import psutil
8
- from fastapi import APIRouter, Request
9
-
10
- router = APIRouter()
11
-
12
-
13
- @router.get("/health", summary="Health check")
14
- async def health(request: Request):
15
- ws = getattr(request.app.state, "ws_manager", None)
16
- engine = getattr(request.app.state, "task_engine", None)
17
- orchestrator = getattr(request.app.state, "orchestrator", None)
18
- ai_router = getattr(request.app.state, "ai_router", None)
19
- connector_manager = getattr(request.app.state, "connector_manager", None)
20
-
21
- ws_stats = ws.get_stats() if ws else {"total_connections": 0, "rooms": {}}
22
- cs = connector_manager.get_summary() if connector_manager else {"connected": 0, "total": 0}
23
- ai_stats = ai_router.get_stats() if ai_router else {}
24
-
25
- orch_status = orchestrator.get_status() if orchestrator else {"agents": [], "total_agents": 0}
26
-
27
- return {
28
- "status": "healthy",
29
- "name": "GOD AGENT OS v11 — Autonomous Engineering OS",
30
- "version": "11.0.0",
31
- "powered_by": "Pyae Sone",
32
- "architecture": "Multi-Agent Orchestrator + Worker Spaces",
33
- "timestamp": time.time(),
34
- "platform": {
35
- "mode": "god_mode",
36
- "agents": orch_status.get("agents", []),
37
- "agent_count": orch_status.get("total_agents", 0),
38
- },
39
- "ai_router": {
40
- "providers": {k: v.get("available", False) for k, v in ai_stats.items()},
41
- "ai_ready": any(v.get("available", False) for v in ai_stats.values()),
42
- },
43
- "connectors": {
44
- "connected": cs.get("connected", 0),
45
- "total": cs.get("total", 0),
46
- "ai_ready": cs.get("ai_ready", False),
47
- },
48
- "task_engine": {
49
- "queue_size": engine._queue.qsize() if engine else 0,
50
- "active_tasks": len(engine._active) if engine else 0,
51
- },
52
- "websocket": {
53
- "connections": ws_stats.get("total_connections", 0),
54
- "rooms": list(ws_stats.get("rooms", {}).keys()),
55
- },
56
- "phases": [
57
- "Phase 1: God Agent Orchestrator ✅",
58
- "Phase 2: Sandbox Agent ✅",
59
- "Phase 3: Connector System ✅",
60
- "Phase 4: Autonomous Coding Engine ✅",
61
- "Phase 5: Memory System ✅",
62
- "Phase 6: Real-time Streaming ✅",
63
- "Phase 7: Workflow Factor OS ✅",
64
- "Phase 8: Modern UI Rebuild ✅",
65
- "Phase 9: Multi-Model AI Router v10 ✅",
66
- "Phase 10: v11 Production Hardening ✅",
67
- ],
68
- }
69
-
70
-
71
- @router.get("/metrics", summary="System metrics")
72
- async def metrics():
73
- cpu = psutil.cpu_percent(interval=0.1)
74
- mem = psutil.virtual_memory()
75
- disk = psutil.disk_usage("/")
76
- return {
77
- "cpu_percent": cpu,
78
- "memory": {
79
- "total_mb": round(mem.total / 1024 / 1024),
80
- "used_mb": round(mem.used / 1024 / 1024),
81
- "percent": mem.percent,
82
- },
83
- "disk": {
84
- "total_gb": round(disk.total / 1024 / 1024 / 1024, 1),
85
- "used_gb": round(disk.used / 1024 / 1024 / 1024, 1),
86
- "percent": disk.percent,
87
- },
88
- "timestamp": time.time(),
89
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
api/routes/memory.py DELETED
@@ -1,50 +0,0 @@
1
- """
2
- Memory API Routes — Persistent agent memory
3
- """
4
-
5
- import time
6
- from fastapi import APIRouter, HTTPException, Query
7
- from core.models import MemorySaveRequest, MemorySearchRequest
8
- from memory.db import save_memory, search_memory, get_project_memory, get_history
9
-
10
- router = APIRouter()
11
-
12
-
13
- @router.post("/", summary="Save memory")
14
- async def save(req: MemorySaveRequest):
15
- await save_memory(
16
- content=req.content,
17
- memory_type=req.memory_type.value,
18
- session_id=req.session_id,
19
- project_id=req.project_id,
20
- key=req.key,
21
- metadata=req.metadata,
22
- )
23
- return {"status": "saved", "memory_type": req.memory_type, "timestamp": time.time()}
24
-
25
-
26
- @router.post("/search", summary="Search memory")
27
- async def search(req: MemorySearchRequest):
28
- results = await search_memory(
29
- query=req.query,
30
- session_id=req.session_id,
31
- project_id=req.project_id,
32
- limit=req.limit,
33
- )
34
- return {"results": results, "total": len(results), "query": req.query}
35
-
36
-
37
- @router.get("/project/{project_id}", summary="Get project memory")
38
- async def project_memory(
39
- project_id: str,
40
- memory_type: str = Query(default=""),
41
- limit: int = Query(default=100, le=500),
42
- ):
43
- results = await get_project_memory(project_id, memory_type=memory_type, limit=limit)
44
- return {"project_id": project_id, "memories": results, "total": len(results)}
45
-
46
-
47
- @router.get("/history/{session_id}", summary="Get conversation history")
48
- async def history(session_id: str, limit: int = Query(default=50, le=200)):
49
- results = await get_history(session_id, limit=limit)
50
- return {"session_id": session_id, "history": results, "total": len(results)}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
api/routes/tasks.py DELETED
@@ -1,167 +0,0 @@
1
- """
2
- Task API Routes — CRUD + Streaming + WebSocket
3
- """
4
-
5
- import asyncio
6
- import json
7
- import time
8
- from typing import Optional
9
-
10
- from fastapi import APIRouter, HTTPException, Request, Query
11
- from fastapi.responses import StreamingResponse
12
-
13
- from core.models import (
14
- TaskCreateRequest, TaskCancelRequest, TaskRetryRequest, TaskResponse, TaskStatus
15
- )
16
- from memory.db import get_task, list_tasks, get_task_events, update_task_status
17
-
18
- router = APIRouter()
19
-
20
-
21
- def get_engine(request: Request):
22
- return request.app.state.task_engine
23
-
24
-
25
- def get_ws(request: Request):
26
- return request.app.state.ws_manager
27
-
28
-
29
- # ─── Create Task ───────────────────────────────────────────────────────────────
30
-
31
- @router.post("/create", summary="Create & queue a new agent task")
32
- async def create_task(req: TaskCreateRequest, request: Request):
33
- engine = get_engine(request)
34
- task_id = await engine.submit(req)
35
- task = await get_task(task_id)
36
- return {
37
- "task_id": task_id,
38
- "status": "queued",
39
- "goal": req.goal,
40
- "session_id": req.session_id,
41
- "stream_url": f"/api/v1/tasks/{task_id}/stream",
42
- "ws_url": f"/ws/tasks/{task_id}",
43
- "created_at": task["created_at"] if task else time.time(),
44
- }
45
-
46
-
47
- # ─── Get Task ──────────────────────────────────────────────────────────────────
48
-
49
- @router.get("/{task_id}", summary="Get task details")
50
- async def get_task_detail(task_id: str):
51
- task = await get_task(task_id)
52
- if not task:
53
- raise HTTPException(status_code=404, detail=f"Task {task_id} not found")
54
- return task
55
-
56
-
57
- # ─── Get Task Status ───────────────────────────────────────────────────────────
58
-
59
- @router.get("/{task_id}/status", summary="Get task status only")
60
- async def get_task_status(task_id: str):
61
- task = await get_task(task_id)
62
- if not task:
63
- raise HTTPException(status_code=404, detail=f"Task {task_id} not found")
64
- return {
65
- "task_id": task_id,
66
- "status": task["status"],
67
- "retry_count": task.get("retry_count", 0),
68
- "created_at": task.get("created_at"),
69
- "started_at": task.get("started_at"),
70
- "completed_at": task.get("completed_at"),
71
- }
72
-
73
-
74
- # ─── Cancel Task ───────────────────────────────────────────────────────────────
75
-
76
- @router.post("/{task_id}/cancel", summary="Cancel a running task")
77
- async def cancel_task(task_id: str, req: TaskCancelRequest, request: Request):
78
- task = await get_task(task_id)
79
- if not task:
80
- raise HTTPException(status_code=404, detail=f"Task {task_id} not found")
81
- if task["status"] in ("completed", "failed", "cancelled"):
82
- raise HTTPException(status_code=400, detail=f"Task already {task['status']}")
83
- engine = get_engine(request)
84
- await engine.cancel(task_id, req.reason)
85
- return {"task_id": task_id, "status": "cancelled", "reason": req.reason}
86
-
87
-
88
- # ─── Retry Task ────────────────────────────────────────────────────────────────
89
-
90
- @router.post("/{task_id}/retry", summary="Retry a failed task")
91
- async def retry_task(task_id: str, request: Request):
92
- task = await get_task(task_id)
93
- if not task:
94
- raise HTTPException(status_code=404, detail=f"Task {task_id} not found")
95
- if task["status"] not in ("failed", "cancelled"):
96
- raise HTTPException(status_code=400, detail="Only failed/cancelled tasks can be retried")
97
- engine = get_engine(request)
98
- await engine.retry(task_id)
99
- return {"task_id": task_id, "status": "queued", "message": "Task requeued for retry"}
100
-
101
-
102
- # ─── Stream Task Events (SSE) ──────────────────────────────────────────────────
103
-
104
- @router.get("/{task_id}/stream", summary="Stream task events via SSE")
105
- async def stream_task(task_id: str, request: Request):
106
- task = await get_task(task_id)
107
- if not task:
108
- raise HTTPException(status_code=404, detail=f"Task {task_id} not found")
109
-
110
- async def event_generator():
111
- # First, replay all stored events
112
- events = await get_task_events(task_id)
113
- for ev in events:
114
- data = json.dumps({
115
- "type": ev["event_type"],
116
- "task_id": task_id,
117
- "timestamp": ev["timestamp"],
118
- "data": json.loads(ev["data"]) if ev.get("data") else {},
119
- })
120
- yield f"data: {data}\n\n"
121
-
122
- # Then stream live events via WS manager buffer
123
- ws = get_ws(request)
124
- room = f"task:{task_id}"
125
- last_count = len(events)
126
-
127
- # Poll for new events (for SSE fallback)
128
- for _ in range(600): # max 5 minutes
129
- await asyncio.sleep(0.5)
130
- current_task = await get_task(task_id)
131
- if current_task and current_task["status"] in ("completed", "failed", "cancelled"):
132
- yield f"data: {json.dumps({'type': 'stream_end', 'task_id': task_id, 'status': current_task['status']})}\n\n"
133
- break
134
- # heartbeat
135
- yield f"data: {json.dumps({'type': 'heartbeat', 'timestamp': time.time()})}\n\n"
136
-
137
- return StreamingResponse(
138
- event_generator(),
139
- media_type="text/event-stream",
140
- headers={
141
- "Cache-Control": "no-cache",
142
- "X-Accel-Buffering": "no",
143
- "Connection": "keep-alive",
144
- },
145
- )
146
-
147
-
148
- # ─── List Tasks ────────────────────────────────────────────────────────────────
149
-
150
- @router.get("/", summary="List tasks")
151
- async def list_all_tasks(
152
- session_id: str = Query(default=""),
153
- limit: int = Query(default=50, le=200),
154
- ):
155
- tasks = await list_tasks(session_id=session_id, limit=limit)
156
- return {"tasks": tasks, "total": len(tasks)}
157
-
158
-
159
- # ─── Task Events History ───────────────────────────────────────────────────────
160
-
161
- @router.get("/{task_id}/events", summary="Get all events for a task")
162
- async def task_events(task_id: str):
163
- task = await get_task(task_id)
164
- if not task:
165
- raise HTTPException(status_code=404, detail=f"Task {task_id} not found")
166
- events = await get_task_events(task_id)
167
- return {"task_id": task_id, "events": events, "total": len(events)}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
api/websocket_manager.py DELETED
@@ -1,134 +0,0 @@
1
- """
2
- WebSocket Connection Manager — Production Grade
3
- Handles rooms, heartbeats, event buffering, reconnect support
4
- """
5
-
6
- import asyncio
7
- import json
8
- import time
9
- import uuid
10
- from collections import defaultdict
11
- from typing import Dict, List, Optional, Set
12
- import structlog
13
-
14
- log = structlog.get_logger()
15
-
16
-
17
- class WebSocketManager:
18
- def __init__(self):
19
- # room → set of websockets
20
- self._rooms: Dict[str, Set] = defaultdict(set)
21
- # ws → list of rooms
22
- self._ws_rooms: Dict[object, Set[str]] = defaultdict(set)
23
- # Event buffer per room (for replay on reconnect)
24
- self._event_buffer: Dict[str, List] = defaultdict(list)
25
- self._buffer_max = 100
26
- # Active connection count
27
- self._connection_count = 0
28
-
29
- async def connect(self, websocket, room: str):
30
- await websocket.accept()
31
- self._rooms[room].add(websocket)
32
- self._ws_rooms[websocket].add(room)
33
- self._connection_count += 1
34
- log.info("WS connected", room=room, total=self._connection_count)
35
-
36
- # Replay buffered events for this room
37
- buffered = self._event_buffer.get(room, [])[-20:]
38
- for event in buffered:
39
- try:
40
- await websocket.send_json(event)
41
- except Exception:
42
- pass
43
-
44
- await websocket.send_json({
45
- "type": "connected",
46
- "room": room,
47
- "timestamp": time.time(),
48
- "buffered_events": len(buffered),
49
- })
50
-
51
- def disconnect(self, websocket, room: Optional[str] = None):
52
- if room:
53
- self._rooms[room].discard(websocket)
54
- self._ws_rooms[websocket].discard(room)
55
- else:
56
- for r in list(self._ws_rooms.get(websocket, [])):
57
- self._rooms[r].discard(websocket)
58
- self._ws_rooms.pop(websocket, None)
59
- self._connection_count = max(0, self._connection_count - 1)
60
- log.info("WS disconnected", room=room, total=self._connection_count)
61
-
62
- async def broadcast(self, room: str, event: dict):
63
- """Broadcast event to all sockets in a room."""
64
- if "timestamp" not in event:
65
- event["timestamp"] = time.time()
66
- if "id" not in event:
67
- event["id"] = str(uuid.uuid4())[:8]
68
-
69
- # Buffer event
70
- self._event_buffer[room].append(event)
71
- if len(self._event_buffer[room]) > self._buffer_max:
72
- self._event_buffer[room].pop(0)
73
-
74
- dead = set()
75
- for ws in list(self._rooms.get(room, [])):
76
- try:
77
- await ws.send_json(event)
78
- except Exception:
79
- dead.add(ws)
80
-
81
- for ws in dead:
82
- self.disconnect(ws, room)
83
-
84
- async def broadcast_global(self, event: dict):
85
- """Broadcast to ALL connected websockets."""
86
- for room in list(self._rooms.keys()):
87
- await self.broadcast(room, event)
88
-
89
- async def emit(self, task_id: str, event_type: str, data: dict, session_id: str = ""):
90
- """Emit a structured event to a task room + logs room."""
91
- event = {
92
- "type": event_type,
93
- "task_id": task_id,
94
- "session_id": session_id,
95
- "timestamp": time.time(),
96
- "data": data,
97
- }
98
- await self.broadcast(f"task:{task_id}", event)
99
- await self.broadcast("logs", event)
100
- await self.broadcast("agent_status", {
101
- "type": "agent_event",
102
- "task_id": task_id,
103
- "event_type": event_type,
104
- "timestamp": time.time(),
105
- })
106
-
107
- async def emit_chat(self, session_id: str, event_type: str, data: dict):
108
- """Emit event to a chat session room."""
109
- event = {
110
- "type": event_type,
111
- "session_id": session_id,
112
- "timestamp": time.time(),
113
- "data": data,
114
- }
115
- await self.broadcast(f"chat:{session_id}", event)
116
-
117
- async def heartbeat_loop(self):
118
- """Send heartbeat to all connections every 15s."""
119
- while True:
120
- await asyncio.sleep(15)
121
- heartbeat = {
122
- "type": "heartbeat",
123
- "timestamp": time.time(),
124
- "connections": self._connection_count,
125
- }
126
- for room in list(self._rooms.keys()):
127
- await self.broadcast(room, heartbeat)
128
-
129
- def get_stats(self) -> dict:
130
- return {
131
- "total_connections": self._connection_count,
132
- "rooms": {r: len(ws) for r, ws in self._rooms.items()},
133
- "buffered_events": {r: len(e) for r, e in self._event_buffer.items()},
134
- }