Spaces:
Sleeping
Sleeping
Initial commit - AmkyawDev Coder Backend
Browse files- Dockerfile +24 -0
- README.md +38 -10
- backend/.env +21 -0
- backend/requirements.txt +44 -0
- backend/src/__init__.py +0 -0
- backend/src/api/__init__.py +0 -0
- backend/src/api/agents/__init__.py +0 -0
- backend/src/api/agents/long-chain/__init__.py +0 -0
- backend/src/api/agents/long-chain/router.py +0 -0
- backend/src/api/agents/script/__init__.py +0 -0
- backend/src/api/agents/script/router.py +0 -0
- backend/src/api/agents/skill/__init__.py +0 -0
- backend/src/api/agents/skill/orchestrator.py +39 -0
- backend/src/api/agents/skill/router.py +79 -0
- backend/src/api/core/__init__.py +0 -0
- backend/src/api/core/logger.py +15 -0
- backend/src/api/systems/__init__.py +0 -0
- backend/src/api/systems/deploy/__init__.py +0 -0
- backend/src/api/systems/deploy/providers/__init__.py +0 -0
- backend/src/api/systems/deploy/router.py +0 -0
- backend/src/api/systems/memory/__init__.py +0 -0
- backend/src/api/systems/memory/router.py +0 -0
- backend/src/api/systems/zip/__init__.py +0 -0
- backend/src/api/systems/zip/router.py +0 -0
- backend/src/app.py +86 -0
- backend/src/config/__init__.py +0 -0
- backend/src/config/settings.py +58 -0
- backend/src/middleware/__init__.py +0 -0
- backend/src/middleware/auth.py +20 -0
- backend/src/middleware/rate_limit.py +15 -0
- backend/src/models/__init__.py +0 -0
- backend/src/models/agent_models.py +69 -0
- backend/src/services/__init__.py +0 -0
- backend/src/services/groq_service.py +82 -0
- backend/src/utils/__init__.py +0 -0
Dockerfile
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.11-slim
|
| 2 |
+
|
| 3 |
+
WORKDIR /app
|
| 4 |
+
|
| 5 |
+
# Install system dependencies
|
| 6 |
+
RUN apt-get update && apt-get install -y \
|
| 7 |
+
gcc \
|
| 8 |
+
git \
|
| 9 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 10 |
+
|
| 11 |
+
# Copy requirements first for caching
|
| 12 |
+
COPY backend/requirements.txt .
|
| 13 |
+
|
| 14 |
+
# Install Python dependencies
|
| 15 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
| 16 |
+
|
| 17 |
+
# Copy application code
|
| 18 |
+
COPY backend/ .
|
| 19 |
+
|
| 20 |
+
# Expose port
|
| 21 |
+
EXPOSE 7860
|
| 22 |
+
|
| 23 |
+
# Run the application
|
| 24 |
+
CMD ["uvicorn", "src.app:app", "--host", "0.0.0.0", "--port", "7860"]
|
README.md
CHANGED
|
@@ -1,10 +1,38 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
--
|
| 9 |
-
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# AmkyawDev Coder Backend
|
| 2 |
+
|
| 3 |
+
AI-Powered Development Platform Backend built with FastAPI.
|
| 4 |
+
|
| 5 |
+
## Features
|
| 6 |
+
|
| 7 |
+
- 🤖 **Skill Agent** - Execute specialized AI skills
|
| 8 |
+
- 🔗 **Long Chain Agent** - Orchestrate complex workflows
|
| 9 |
+
- 💻 **Script Agent** - Generate and optimize code
|
| 10 |
+
- 📦 **Zip System** - Compile and compress files
|
| 11 |
+
- 🚀 **Deploy System** - Deploy to multiple cloud providers
|
| 12 |
+
- 🧠 **Memory System** - AI-powered memory management
|
| 13 |
+
|
| 14 |
+
## API Endpoints
|
| 15 |
+
|
| 16 |
+
### Agents
|
| 17 |
+
- `POST /api/agents/skill/execute` - Execute skill agent
|
| 18 |
+
- `POST /api/agents/long-chain/execute` - Execute long chain workflow
|
| 19 |
+
- `POST /api/agents/script/generate` - Generate code
|
| 20 |
+
|
| 21 |
+
### Systems
|
| 22 |
+
- `POST /api/systems/zip/compile` - Compile files to zip
|
| 23 |
+
- `POST /api/systems/deploy/deploy` - Deploy to cloud
|
| 24 |
+
- `POST /api/systems/memory/search` - Search memory
|
| 25 |
+
|
| 26 |
+
## Setup
|
| 27 |
+
|
| 28 |
+
1. Create `.env` file with your API keys
|
| 29 |
+
2. Run `pip install -r requirements.txt`
|
| 30 |
+
3. Run `uvicorn src.app:app --reload`
|
| 31 |
+
|
| 32 |
+
## Environment Variables
|
| 33 |
+
|
| 34 |
+
```
|
| 35 |
+
GROQ_API_KEY=your_groq_api_key
|
| 36 |
+
HUGGINGFACE_API_KEY=your_hf_api_key
|
| 37 |
+
FIREBASE_CREDENTIALS_PATH=path/to/credentials.json
|
| 38 |
+
```
|
backend/.env
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Application
|
| 2 |
+
APP_NAME=AmkyawDev Coder Backend
|
| 3 |
+
ENVIRONMENT=production
|
| 4 |
+
DEBUG=false
|
| 5 |
+
|
| 6 |
+
# Groq API
|
| 7 |
+
GROQ_API_KEY=
|
| 8 |
+
GROQ_MODEL=llama-3.1-70b-versatile
|
| 9 |
+
|
| 10 |
+
# Hugging Face
|
| 11 |
+
HUGGINGFACE_API_KEY=
|
| 12 |
+
|
| 13 |
+
# Firebase
|
| 14 |
+
FIREBASE_CREDENTIALS_PATH=
|
| 15 |
+
FIREBASE_DATABASE_URL=
|
| 16 |
+
|
| 17 |
+
# Deployment
|
| 18 |
+
VERCEL_TOKEN=
|
| 19 |
+
NETLIFY_TOKEN=
|
| 20 |
+
AWS_ACCESS_KEY_ID=
|
| 21 |
+
AWS_SECRET_ACCESS_KEY=
|
backend/requirements.txt
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# FastAPI & Server
|
| 2 |
+
fastapi==0.115.0
|
| 3 |
+
uvicorn[standard]==0.30.6
|
| 4 |
+
python-multipart==0.0.12
|
| 5 |
+
|
| 6 |
+
# AI Services
|
| 7 |
+
groq==0.8.0
|
| 8 |
+
huggingface_hub==0.26.2
|
| 9 |
+
|
| 10 |
+
# Database & Vector
|
| 11 |
+
chromadb==0.5.5
|
| 12 |
+
qdrant-client==1.12.1
|
| 13 |
+
firebase-admin==6.5.0
|
| 14 |
+
|
| 15 |
+
# Deployment
|
| 16 |
+
boto3==1.35.36
|
| 17 |
+
python-gitlab==1.18.0
|
| 18 |
+
|
| 19 |
+
# Utilities
|
| 20 |
+
pydantic==2.9.2
|
| 21 |
+
pydantic-settings==2.5.2
|
| 22 |
+
python-dotenv==1.0.1
|
| 23 |
+
httpx==0.27.2
|
| 24 |
+
tenacity==9.0.0
|
| 25 |
+
tiktoken==0.7.0
|
| 26 |
+
|
| 27 |
+
# Zip & File handling
|
| 28 |
+
zipfile36==0.1.3
|
| 29 |
+
python-magic==0.4.27
|
| 30 |
+
|
| 31 |
+
# Security
|
| 32 |
+
rate-limit==0.7.1
|
| 33 |
+
slowapi==0.1.9
|
| 34 |
+
|
| 35 |
+
# Testing
|
| 36 |
+
pytest==8.3.3
|
| 37 |
+
pytest-asyncio==0.24.0
|
| 38 |
+
pytest-cov==5.0.0
|
| 39 |
+
httpx==0.27.2
|
| 40 |
+
|
| 41 |
+
# Development
|
| 42 |
+
black==24.8.0
|
| 43 |
+
ruff==0.6.9
|
| 44 |
+
mypy==1.11.2
|
backend/src/__init__.py
ADDED
|
File without changes
|
backend/src/api/__init__.py
ADDED
|
File without changes
|
backend/src/api/agents/__init__.py
ADDED
|
File without changes
|
backend/src/api/agents/long-chain/__init__.py
ADDED
|
File without changes
|
backend/src/api/agents/long-chain/router.py
ADDED
|
File without changes
|
backend/src/api/agents/script/__init__.py
ADDED
|
File without changes
|
backend/src/api/agents/script/router.py
ADDED
|
File without changes
|
backend/src/api/agents/skill/__init__.py
ADDED
|
File without changes
|
backend/src/api/agents/skill/orchestrator.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Skill Agent Orchestrator"""
|
| 2 |
+
from typing import Dict, Any, List, Optional
|
| 3 |
+
from src.services.groq_service import generate_response
|
| 4 |
+
from src.api.core.logger import logger
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
class SkillOrchestrator:
|
| 8 |
+
def __init__(self):
|
| 9 |
+
self.available_skills = {
|
| 10 |
+
"code_review": "Review code for bugs, security issues, and best practices",
|
| 11 |
+
"bug_detection": "Find and analyze bugs in code",
|
| 12 |
+
"documentation": "Generate documentation for code",
|
| 13 |
+
"refactoring": "Suggest code improvements and refactoring",
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
async def execute(
|
| 17 |
+
self,
|
| 18 |
+
prompt: str,
|
| 19 |
+
skill_type: str,
|
| 20 |
+
context: Optional[Dict[str, Any]] = None,
|
| 21 |
+
tools: Optional[List[str]] = None,
|
| 22 |
+
) -> Dict[str, Any]:
|
| 23 |
+
if skill_type not in self.available_skills:
|
| 24 |
+
raise ValueError(f"Unknown skill type: {skill_type}")
|
| 25 |
+
|
| 26 |
+
messages = [
|
| 27 |
+
{
|
| 28 |
+
"role": "system",
|
| 29 |
+
"content": f"You are a skilled {skill_type} expert. {self.available_skills[skill_type]}"
|
| 30 |
+
},
|
| 31 |
+
{"role": "user", "content": prompt}
|
| 32 |
+
]
|
| 33 |
+
|
| 34 |
+
try:
|
| 35 |
+
result = await generate_response(messages)
|
| 36 |
+
return {"skill_type": skill_type, "result": result, "status": "success"}
|
| 37 |
+
except Exception as e:
|
| 38 |
+
logger.error(f"Skill execution failed: {e}")
|
| 39 |
+
raise
|
backend/src/api/agents/skill/router.py
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Skill Agent Router - API Endpoints
|
| 3 |
+
"""
|
| 4 |
+
from fastapi import APIRouter, HTTPException
|
| 5 |
+
from typing import Dict, Any
|
| 6 |
+
from src.models.agent_models import SkillRequest, SkillResponse, TaskStatus
|
| 7 |
+
from src.api.agents.skill.orchestrator import SkillOrchestrator
|
| 8 |
+
from src.api.core.logger import logger
|
| 9 |
+
import time
|
| 10 |
+
|
| 11 |
+
router = APIRouter()
|
| 12 |
+
orchestrator = SkillOrchestrator()
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
@router.post("/execute", response_model=SkillResponse)
|
| 16 |
+
async def execute_skill(request: SkillRequest) -> SkillResponse:
|
| 17 |
+
"""
|
| 18 |
+
Execute a skill agent task
|
| 19 |
+
|
| 20 |
+
- **prompt**: The task description
|
| 21 |
+
- **skill_type**: Type of skill (code_review, bug_detection, documentation, etc.)
|
| 22 |
+
- **context**: Optional context data
|
| 23 |
+
- **tools**: Optional list of available tools
|
| 24 |
+
"""
|
| 25 |
+
start_time = time.time()
|
| 26 |
+
|
| 27 |
+
try:
|
| 28 |
+
logger.info(f"Executing skill: {request.skill_type}")
|
| 29 |
+
|
| 30 |
+
result = await orchestrator.execute(
|
| 31 |
+
prompt=request.prompt,
|
| 32 |
+
skill_type=request.skill_type,
|
| 33 |
+
context=request.context,
|
| 34 |
+
tools=request.tools,
|
| 35 |
+
)
|
| 36 |
+
|
| 37 |
+
execution_time = time.time() - start_time
|
| 38 |
+
|
| 39 |
+
return SkillResponse(
|
| 40 |
+
status=TaskStatus.COMPLETED,
|
| 41 |
+
result=result,
|
| 42 |
+
execution_time=execution_time,
|
| 43 |
+
)
|
| 44 |
+
|
| 45 |
+
except Exception as e:
|
| 46 |
+
logger.error(f"Skill execution error: {str(e)}")
|
| 47 |
+
execution_time = time.time() - start_time
|
| 48 |
+
|
| 49 |
+
return SkillResponse(
|
| 50 |
+
status=TaskStatus.FAILED,
|
| 51 |
+
error=str(e),
|
| 52 |
+
execution_time=execution_time,
|
| 53 |
+
)
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
@router.get("/types")
|
| 57 |
+
async def get_skill_types() -> Dict[str, Any]:
|
| 58 |
+
"""Get available skill types"""
|
| 59 |
+
return {
|
| 60 |
+
"skills": [
|
| 61 |
+
{"id": "code_review", "name": "Code Review", "description": "Review code for issues"},
|
| 62 |
+
{"id": "bug_detection", "name": "Bug Detection", "description": "Find bugs in code"},
|
| 63 |
+
{"id": "documentation", "name": "Documentation", "description": "Generate documentation"},
|
| 64 |
+
{"id": "refactoring", "name": "Refactoring", "description": "Refactor code for better quality"},
|
| 65 |
+
]
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
@router.get("/tools")
|
| 70 |
+
async def get_available_tools() -> Dict[str, Any]:
|
| 71 |
+
"""Get available tools for skill execution"""
|
| 72 |
+
return {
|
| 73 |
+
"tools": [
|
| 74 |
+
{"id": "file_reader", "name": "File Reader", "description": "Read files from workspace"},
|
| 75 |
+
{"id": "file_writer", "name": "File Writer", "description": "Write files to workspace"},
|
| 76 |
+
{"id": "search", "name": "Search", "description": "Search in files"},
|
| 77 |
+
{"id": "git", "name": "Git", "description": "Git operations"},
|
| 78 |
+
]
|
| 79 |
+
}
|
backend/src/api/core/__init__.py
ADDED
|
File without changes
|
backend/src/api/core/logger.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Logger Configuration
|
| 3 |
+
"""
|
| 4 |
+
import logging
|
| 5 |
+
import sys
|
| 6 |
+
|
| 7 |
+
logging.basicConfig(
|
| 8 |
+
level=logging.INFO,
|
| 9 |
+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
| 10 |
+
handlers=[
|
| 11 |
+
logging.StreamHandler(sys.stdout)
|
| 12 |
+
]
|
| 13 |
+
)
|
| 14 |
+
|
| 15 |
+
logger = logging.getLogger("amkyawdev")
|
backend/src/api/systems/__init__.py
ADDED
|
File without changes
|
backend/src/api/systems/deploy/__init__.py
ADDED
|
File without changes
|
backend/src/api/systems/deploy/providers/__init__.py
ADDED
|
File without changes
|
backend/src/api/systems/deploy/router.py
ADDED
|
File without changes
|
backend/src/api/systems/memory/__init__.py
ADDED
|
File without changes
|
backend/src/api/systems/memory/router.py
ADDED
|
File without changes
|
backend/src/api/systems/zip/__init__.py
ADDED
|
File without changes
|
backend/src/api/systems/zip/router.py
ADDED
|
File without changes
|
backend/src/app.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
AmkyawDev Coder Backend - FastAPI Application Entry Point
|
| 3 |
+
"""
|
| 4 |
+
from fastapi import FastAPI
|
| 5 |
+
from fastapi.middleware.cors import CORSMiddleware
|
| 6 |
+
from contextlib import asynccontextmanager
|
| 7 |
+
|
| 8 |
+
from src.api.agents.skill.router import router as skill_router
|
| 9 |
+
from src.api.agents.long_chain.router import router as long_chain_router
|
| 10 |
+
from src.api.agents.script.router import router as script_router
|
| 11 |
+
from src.api.systems.zip.router import router as zip_router
|
| 12 |
+
from src.api.systems.deploy.router import router as deploy_router
|
| 13 |
+
from src.api.systems.memory.router import router as memory_router
|
| 14 |
+
from src.middleware.auth import AuthMiddleware
|
| 15 |
+
from src.middleware.rate_limit import RateLimitMiddleware
|
| 16 |
+
from src.config.settings import settings
|
| 17 |
+
from src.api.core.logger import logger
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
@asynccontextmanager
|
| 21 |
+
async def lifespan(app: FastAPI):
|
| 22 |
+
"""Application lifespan events"""
|
| 23 |
+
logger.info("Starting AmkyawDev Coder Backend...")
|
| 24 |
+
logger.info(f"Environment: {settings.ENVIRONMENT}")
|
| 25 |
+
yield
|
| 26 |
+
logger.info("Shutting down AmkyawDev Coder Backend...")
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
app = FastAPI(
|
| 30 |
+
title="AmkyawDev Coder Backend",
|
| 31 |
+
description="AI-Powered Development Platform Backend",
|
| 32 |
+
version="1.0.0",
|
| 33 |
+
lifespan=lifespan,
|
| 34 |
+
)
|
| 35 |
+
|
| 36 |
+
# CORS Configuration
|
| 37 |
+
app.add_middleware(
|
| 38 |
+
CORSMiddleware,
|
| 39 |
+
allow_origins=settings.CORS_ORIGINS,
|
| 40 |
+
allow_credentials=True,
|
| 41 |
+
allow_methods=["*"],
|
| 42 |
+
allow_headers=["*"],
|
| 43 |
+
)
|
| 44 |
+
|
| 45 |
+
# Custom Middleware
|
| 46 |
+
app.add_middleware(AuthMiddleware)
|
| 47 |
+
app.add_middleware(RateLimitMiddleware)
|
| 48 |
+
|
| 49 |
+
# Include Routers
|
| 50 |
+
app.include_router(skill_router, prefix="/api/agents/skill", tags=["Skill Agent"])
|
| 51 |
+
app.include_router(long_chain_router, prefix="/api/agents/long-chain", tags=["Long Chain Agent"])
|
| 52 |
+
app.include_router(script_router, prefix="/api/agents/script", tags=["Script Agent"])
|
| 53 |
+
app.include_router(zip_router, prefix="/api/systems/zip", tags=["Zip System"])
|
| 54 |
+
app.include_router(deploy_router, prefix="/api/systems/deploy", tags=["Deploy System"])
|
| 55 |
+
app.include_router(memory_router, prefix="/api/systems/memory", tags=["Memory System"])
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
@app.get("/")
|
| 59 |
+
async def root():
|
| 60 |
+
"""Health check endpoint"""
|
| 61 |
+
return {
|
| 62 |
+
"status": "healthy",
|
| 63 |
+
"service": "AmkyawDev Coder Backend",
|
| 64 |
+
"version": "1.0.0"
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
@app.get("/api/health")
|
| 69 |
+
async def health_check():
|
| 70 |
+
"""Detailed health check"""
|
| 71 |
+
return {
|
| 72 |
+
"status": "healthy",
|
| 73 |
+
"environment": settings.ENVIRONMENT,
|
| 74 |
+
"groq_configured": bool(settings.GROQ_API_KEY),
|
| 75 |
+
"hf_configured": bool(settings.HUGGINGFACE_API_KEY),
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
if __name__ == "__main__":
|
| 80 |
+
import uvicorn
|
| 81 |
+
uvicorn.run(
|
| 82 |
+
"src.app:app",
|
| 83 |
+
host="0.0.0.0",
|
| 84 |
+
port=8000,
|
| 85 |
+
reload=settings.ENVIRONMENT == "development"
|
| 86 |
+
)
|
backend/src/config/__init__.py
ADDED
|
File without changes
|
backend/src/config/settings.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Application Settings - Environment Configuration
|
| 3 |
+
"""
|
| 4 |
+
from pydantic_settings import BaseSettings
|
| 5 |
+
from typing import List
|
| 6 |
+
from functools import lru_cache
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class Settings(BaseSettings):
|
| 10 |
+
# Application
|
| 11 |
+
APP_NAME: str = "AmkyawDev Coder Backend"
|
| 12 |
+
ENVIRONMENT: str = "development"
|
| 13 |
+
DEBUG: bool = True
|
| 14 |
+
|
| 15 |
+
# CORS
|
| 16 |
+
CORS_ORIGINS: List[str] = ["*"]
|
| 17 |
+
|
| 18 |
+
# Groq API
|
| 19 |
+
GROQ_API_KEY: str = ""
|
| 20 |
+
GROQ_MODEL: str = "llama-3.1-70b-versatile"
|
| 21 |
+
GROQ_BASE_URL: str = "https://api.groq.com/openai/v1"
|
| 22 |
+
|
| 23 |
+
# Hugging Face
|
| 24 |
+
HUGGINGFACE_API_KEY: str = ""
|
| 25 |
+
HF_INFERENCE_ENDPOINT: str = ""
|
| 26 |
+
|
| 27 |
+
# Firebase
|
| 28 |
+
FIREBASE_CREDENTIALS_PATH: str = ""
|
| 29 |
+
FIREBASE_DATABASE_URL: str = ""
|
| 30 |
+
|
| 31 |
+
# Vector Database
|
| 32 |
+
CHROMA_HOST: str = "localhost"
|
| 33 |
+
CHROMA_PORT: int = 8000
|
| 34 |
+
|
| 35 |
+
# Deployment
|
| 36 |
+
VERCEL_TOKEN: str = ""
|
| 37 |
+
NETLIFY_TOKEN: str = ""
|
| 38 |
+
AWS_ACCESS_KEY_ID: str = ""
|
| 39 |
+
AWS_SECRET_ACCESS_KEY: str = ""
|
| 40 |
+
|
| 41 |
+
# Rate Limiting
|
| 42 |
+
RATE_LIMIT_PER_MINUTE: int = 60
|
| 43 |
+
|
| 44 |
+
# Memory
|
| 45 |
+
MEMORY_MAX_TOKENS: int = 4096
|
| 46 |
+
MEMORY_VECTOR_DIMENSION: int = 768
|
| 47 |
+
|
| 48 |
+
class Config:
|
| 49 |
+
env_file = ".env"
|
| 50 |
+
case_sensitive = True
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
@lru_cache()
|
| 54 |
+
def get_settings() -> Settings:
|
| 55 |
+
return Settings()
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
settings = get_settings()
|
backend/src/middleware/__init__.py
ADDED
|
File without changes
|
backend/src/middleware/auth.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Authentication Middleware
|
| 3 |
+
"""
|
| 4 |
+
from fastapi import Request, HTTPException
|
| 5 |
+
from starlette.middleware.base import BaseHTTPMiddleware
|
| 6 |
+
from src.api.core.logger import logger
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class AuthMiddleware(BaseHTTPMiddleware):
|
| 10 |
+
"""Simple authentication middleware"""
|
| 11 |
+
|
| 12 |
+
async def dispatch(self, request: Request, call_next):
|
| 13 |
+
# Skip auth for health endpoints
|
| 14 |
+
if request.url.path in ["/", "/api/health"]:
|
| 15 |
+
return await call_next(request)
|
| 16 |
+
|
| 17 |
+
# TODO: Implement Firebase auth token verification
|
| 18 |
+
# For now, allow all requests
|
| 19 |
+
response = await call_next(request)
|
| 20 |
+
return response
|
backend/src/middleware/rate_limit.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Rate Limiting Middleware
|
| 3 |
+
"""
|
| 4 |
+
from fastapi import Request
|
| 5 |
+
from slowapi import Limiter
|
| 6 |
+
from slowapi.util import get_remote_address
|
| 7 |
+
from slowapi.middleware import SlowAPIMiddleware
|
| 8 |
+
from src.config.settings import settings
|
| 9 |
+
|
| 10 |
+
limiter = Limiter(key_func=get_remote_address)
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class RateLimitMiddleware(SlowAPIMiddleware):
|
| 14 |
+
"""Rate limiting middleware"""
|
| 15 |
+
pass
|
backend/src/models/__init__.py
ADDED
|
File without changes
|
backend/src/models/agent_models.py
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Agent Models - Pydantic Models for Agents
|
| 3 |
+
"""
|
| 4 |
+
from pydantic import BaseModel, Field
|
| 5 |
+
from typing import Optional, List, Dict, Any
|
| 6 |
+
from enum import Enum
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class AgentType(str, Enum):
|
| 10 |
+
SKILL = "skill"
|
| 11 |
+
LONG_CHAIN = "long_chain"
|
| 12 |
+
SCRIPT = "script"
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
class TaskStatus(str, Enum):
|
| 16 |
+
PENDING = "pending"
|
| 17 |
+
RUNNING = "running"
|
| 18 |
+
COMPLETED = "completed"
|
| 19 |
+
FAILED = "failed"
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
class SkillRequest(BaseModel):
|
| 23 |
+
"""Request model for Skill Agent"""
|
| 24 |
+
prompt: str = Field(..., description="The task prompt")
|
| 25 |
+
skill_type: str = Field(..., description="Type of skill to execute")
|
| 26 |
+
context: Optional[Dict[str, Any]] = Field(default=None, description="Additional context")
|
| 27 |
+
tools: Optional[List[str]] = Field(default=None, description="Available tools")
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
class SkillResponse(BaseModel):
|
| 31 |
+
"""Response model for Skill Agent"""
|
| 32 |
+
status: TaskStatus
|
| 33 |
+
result: Optional[Dict[str, Any]] = None
|
| 34 |
+
error: Optional[str] = None
|
| 35 |
+
execution_time: float = 0.0
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
class ChainRequest(BaseModel):
|
| 39 |
+
"""Request model for Long Chain Agent"""
|
| 40 |
+
workflow: str = Field(..., description="Workflow name or definition")
|
| 41 |
+
input_data: Dict[str, Any] = Field(..., description="Input data for workflow")
|
| 42 |
+
steps: Optional[List[str]] = Field(default=None, description="Specific steps to execute")
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
class ChainResponse(BaseModel):
|
| 46 |
+
"""Response model for Long Chain Agent"""
|
| 47 |
+
status: TaskStatus
|
| 48 |
+
workflow: str
|
| 49 |
+
steps_completed: List[Dict[str, Any]] = []
|
| 50 |
+
final_result: Optional[Dict[str, Any]] = None
|
| 51 |
+
error: Optional[str] = None
|
| 52 |
+
total_time: float = 0.0
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
class ScriptRequest(BaseModel):
|
| 56 |
+
"""Request model for Script Agent"""
|
| 57 |
+
language: str = Field(default="python", description="Programming language")
|
| 58 |
+
prompt: str = Field(..., description="Code generation prompt")
|
| 59 |
+
template: Optional[str] = Field(default=None, description="Code template to use")
|
| 60 |
+
optimize: bool = Field(default=False, description="Whether to optimize the code")
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
class ScriptResponse(BaseModel):
|
| 64 |
+
"""Response model for Script Agent"""
|
| 65 |
+
status: TaskStatus
|
| 66 |
+
code: Optional[str] = None
|
| 67 |
+
language: str
|
| 68 |
+
explanation: Optional[str] = None
|
| 69 |
+
error: Optional[str] = None
|
backend/src/services/__init__.py
ADDED
|
File without changes
|
backend/src/services/groq_service.py
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Groq API Service - LLM Integration
|
| 3 |
+
"""
|
| 4 |
+
from groq import Groq
|
| 5 |
+
from typing import Optional, List, Dict, Any
|
| 6 |
+
from src.config.settings import settings
|
| 7 |
+
from src.api.core.logger import logger
|
| 8 |
+
|
| 9 |
+
client: Optional[Groq] = None
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def get_groq_client() -> Groq:
|
| 13 |
+
"""Get or create Groq client instance"""
|
| 14 |
+
global client
|
| 15 |
+
if client is None:
|
| 16 |
+
client = Groq(api_key=settings.GROQ_API_KEY)
|
| 17 |
+
return client
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
async def generate_response(
|
| 21 |
+
messages: List[Dict[str, str]],
|
| 22 |
+
model: str = None,
|
| 23 |
+
temperature: float = 0.7,
|
| 24 |
+
max_tokens: int = 4096,
|
| 25 |
+
) -> str:
|
| 26 |
+
"""
|
| 27 |
+
Generate response using Groq API
|
| 28 |
+
|
| 29 |
+
Args:
|
| 30 |
+
messages: List of message dicts with 'role' and 'content'
|
| 31 |
+
model: Model name (defaults to settings.GROQ_MODEL)
|
| 32 |
+
temperature: Sampling temperature
|
| 33 |
+
max_tokens: Maximum tokens to generate
|
| 34 |
+
|
| 35 |
+
Returns:
|
| 36 |
+
Generated response string
|
| 37 |
+
"""
|
| 38 |
+
try:
|
| 39 |
+
groq_client = get_groq_client()
|
| 40 |
+
model = model or settings.GROQ_MODEL
|
| 41 |
+
|
| 42 |
+
response = groq_client.chat.completions.create(
|
| 43 |
+
model=model,
|
| 44 |
+
messages=messages,
|
| 45 |
+
temperature=temperature,
|
| 46 |
+
max_tokens=max_tokens,
|
| 47 |
+
)
|
| 48 |
+
|
| 49 |
+
return response.choices[0].message.content
|
| 50 |
+
|
| 51 |
+
except Exception as e:
|
| 52 |
+
logger.error(f"Groq API error: {str(e)}")
|
| 53 |
+
raise
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
async def stream_response(
|
| 57 |
+
messages: List[Dict[str, str]],
|
| 58 |
+
model: str = None,
|
| 59 |
+
temperature: float = 0.7,
|
| 60 |
+
) -> str:
|
| 61 |
+
"""Stream response from Groq API"""
|
| 62 |
+
try:
|
| 63 |
+
groq_client = get_groq_client()
|
| 64 |
+
model = model or settings.GROQ_MODEL
|
| 65 |
+
|
| 66 |
+
stream = groq_client.chat.completions.create(
|
| 67 |
+
model=model,
|
| 68 |
+
messages=messages,
|
| 69 |
+
temperature=temperature,
|
| 70 |
+
stream=True,
|
| 71 |
+
)
|
| 72 |
+
|
| 73 |
+
full_response = ""
|
| 74 |
+
for chunk in stream:
|
| 75 |
+
if chunk.choices[0].delta.content:
|
| 76 |
+
full_response += chunk.choices[0].delta.content
|
| 77 |
+
|
| 78 |
+
return full_response
|
| 79 |
+
|
| 80 |
+
except Exception as e:
|
| 81 |
+
logger.error(f"Groq streaming error: {str(e)}")
|
| 82 |
+
raise
|
backend/src/utils/__init__.py
ADDED
|
File without changes
|