Fixed core issues
This commit is contained in:
parent
c4d220a294
commit
03490762be
14 changed files with 190 additions and 31 deletions
|
|
@ -10,10 +10,10 @@ import asyncio
|
|||
|
||||
@shared_task
|
||||
def start_agent_task_mcp(execution_id):
|
||||
print(f"[start_agent_task_mcp] invoked with execution_id={execution_id}")
|
||||
print(f"invoked with execution_id={execution_id}")
|
||||
try:
|
||||
execution = AgentExecution.objects.get(uuid=execution_id)
|
||||
print(f"[start_agent_task_mcp] execution record loaded: agent={execution.agent.uuid}")
|
||||
print(f"execution record loaded: agent={execution.agent.uuid}")
|
||||
execution.status = 'running'
|
||||
execution.started_at = timezone.now()
|
||||
execution.save()
|
||||
|
|
@ -30,7 +30,7 @@ def start_agent_task_mcp(execution_id):
|
|||
"content": {
|
||||
"execution_id": str(execution.uuid),
|
||||
"agent_id": str(execution.agent.uuid),
|
||||
"message": "Agent execution started (via MCP)"
|
||||
"message": "Agent execution started"
|
||||
},
|
||||
"timestamp": timezone.now().isoformat()
|
||||
}
|
||||
|
|
@ -57,7 +57,7 @@ def start_agent_task_mcp(execution_id):
|
|||
)
|
||||
|
||||
result = asyncio.run(execute_remote())
|
||||
print(f"[start_agent_task_mcp] MCP result: {result.get('status')}")
|
||||
print(f"MCP result: {result.get('status')}")
|
||||
|
||||
if result.get('events'):
|
||||
for event in result['events']:
|
||||
|
|
@ -110,7 +110,7 @@ def start_agent_task_mcp(execution_id):
|
|||
except AgentExecution.DoesNotExist:
|
||||
print(f"Execution {execution_id} not found")
|
||||
except Exception as e:
|
||||
print(f"[start_agent_task_mcp] exception: {e}")
|
||||
print(f"exception: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,21 @@
|
|||
|
||||
services:
|
||||
|
||||
fyp-postgres:
|
||||
image: postgres:15-alpine
|
||||
container_name: ${POSTGRES_CONTAINER_NAME:-fyp-postgres}
|
||||
env_file:
|
||||
- ../../.env
|
||||
environment:
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-fyp}"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 5
|
||||
|
||||
fyp-redis:
|
||||
image: redis:7-alpine
|
||||
container_name: ${REDIS_CONTAINER_NAME:-fyp-redis}
|
||||
|
|
@ -41,7 +56,6 @@ services:
|
|||
- "0.0.0.0:8000:8000"
|
||||
volumes:
|
||||
- ../../:/app
|
||||
- venv:/venv
|
||||
environment:
|
||||
DJANGO_SECRET_KEY: ${DJANGO_SECRET_KEY:-dev-secret-key-change-in-production}
|
||||
DJANGO_DEBUG: "true"
|
||||
|
|
@ -49,10 +63,13 @@ services:
|
|||
DJANGO_CELERY_BROKER_URL: redis://${REDIS_CONTAINER_NAME:-fyp-redis}:6379/0
|
||||
DJANGO_CORS_ALLOWED_ORIGINS: http://localhost:5173,http://127.0.0.1:5173
|
||||
DJANGO_SETTINGS_MODULE: config.settings
|
||||
MCP_AGENT_URL: http://mcp-agent-server:8001
|
||||
env_file:
|
||||
- ../../.env
|
||||
depends_on:
|
||||
fyp-redis:
|
||||
condition: service_healthy
|
||||
fyp-postgres:
|
||||
condition: service_healthy
|
||||
web:
|
||||
condition: service_started
|
||||
mcp-agent-server:
|
||||
|
|
@ -65,16 +82,18 @@ services:
|
|||
container_name: dynavera-celery
|
||||
volumes:
|
||||
- ../../:/app
|
||||
- venv:/venv
|
||||
- ${USERPROFILE}/.cache/gpt4all:/root/.cache/gpt4all:rw
|
||||
environment:
|
||||
DJANGO_SECRET_KEY: ${DJANGO_SECRET_KEY:-dev-secret-key-change-in-production}
|
||||
DJANGO_CELERY_BROKER_URL: redis://${REDIS_CONTAINER_NAME:-fyp-redis}:6379/0
|
||||
DJANGO_SETTINGS_MODULE: config.settings
|
||||
MCP_AGENT_URL: http://mcp-agent-server:8001
|
||||
env_file:
|
||||
- ../../.env
|
||||
depends_on:
|
||||
fyp-redis:
|
||||
condition: service_healthy
|
||||
fyp-postgres:
|
||||
condition: service_healthy
|
||||
mcp-agent-server:
|
||||
condition: service_started
|
||||
|
||||
|
|
@ -94,10 +113,15 @@ services:
|
|||
DJANGO_SETTINGS_MODULE: config.settings
|
||||
PYTHONUNBUFFERED: "1"
|
||||
HOME: /root
|
||||
env_file:
|
||||
- ../../.env
|
||||
depends_on:
|
||||
fyp-redis:
|
||||
condition: service_healthy
|
||||
fyp-postgres:
|
||||
condition: service_healthy
|
||||
|
||||
volumes:
|
||||
redis_data:
|
||||
venv:
|
||||
postgres_data:
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ FROM python:3.12-bookworm
|
|||
RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||
build-essential \
|
||||
libpq-dev \
|
||||
wait-for-it \
|
||||
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
|
@ -16,4 +17,7 @@ WORKDIR /app
|
|||
COPY requirements/base.txt .
|
||||
RUN pip install --no-cache-dir --requirement base.txt
|
||||
|
||||
CMD ["daphne", "-b", "0.0.0.0", "-p", "8000", "config.asgi:application"]
|
||||
COPY ./compose/prod/start /start
|
||||
RUN sed -i 's/\r$//g' /start && chmod +x /start
|
||||
|
||||
CMD ["/start"]
|
||||
51
compose/prod/docker-compose.local.yml
Normal file
51
compose/prod/docker-compose.local.yml
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
services:
|
||||
fyp-traefik:
|
||||
image: traefik:v2.10
|
||||
restart: unless-stopped
|
||||
command:
|
||||
- "--api.insecure=true"
|
||||
- "--providers.docker=true"
|
||||
- "--providers.docker.exposedbydefault=false"
|
||||
- "--entrypoints.mcp.address=:${MCP_PORT:-58001}"
|
||||
ports:
|
||||
- "${MCP_PORT:-58001}:${MCP_PORT:-58001}"
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- "/var/run/docker.sock:/var/run/docker.sock:ro"
|
||||
networks:
|
||||
- mcp-internal
|
||||
|
||||
fyp-mcp:
|
||||
build:
|
||||
context: ../..
|
||||
dockerfile: compose/dev/mcp/Dockerfile
|
||||
container_name: dynavera-mcp-server
|
||||
restart: unless-stopped
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
env_file:
|
||||
- ../../.env
|
||||
environment:
|
||||
- MCP_HTTP_HOST=0.0.0.0
|
||||
- MCP_HTTP_PORT=8001
|
||||
command: python -m mcp_agent.mcp_server
|
||||
volumes:
|
||||
- ../../:/app
|
||||
- ${USERPROFILE}/.cache/gpt4all:/root/.cache/gpt4all:rw
|
||||
- ../../build/rag_db:/app/build/rag_db:ro
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.fyp-mcp.rule=Host(`${MCP_DOMAIN}`)"
|
||||
- "traefik.http.routers.fyp-mcp.entrypoints=mcp"
|
||||
- "traefik.http.services.fyp-mcp.loadbalancer.server.port=8001"
|
||||
- "com.centurylinklabs.watchtower.enable=true"
|
||||
- "com.centurylinklabs.watchtower.scope=fyp"
|
||||
networks:
|
||||
- mcp-internal
|
||||
|
||||
networks:
|
||||
mcp-internal:
|
||||
driver: bridge
|
||||
|
||||
|
||||
|
|
@ -1,6 +1,19 @@
|
|||
|
||||
|
||||
services:
|
||||
|
||||
fyp-postgres:
|
||||
image: postgres:15-alpine
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- ../../.env
|
||||
environment:
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
networks:
|
||||
- proxy
|
||||
|
||||
fyp-web:
|
||||
image: ${IMAGE}
|
||||
restart: unless-stopped
|
||||
|
|
@ -65,4 +78,6 @@ volumes:
|
|||
gitlab-runner-config:
|
||||
name: gitlab-runner-config
|
||||
gitlab-machine-config:
|
||||
name: gitlab-machine-config
|
||||
name: gitlab-machine-config
|
||||
postgres_data:
|
||||
name: fyp_postgres_data
|
||||
|
|
@ -4,8 +4,24 @@ set -o errexit
|
|||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
DB_HOST="${POSTGRES_HOST:-localhost}"
|
||||
DB_PORT="${POSTGRES_PORT:-5432}"
|
||||
|
||||
echo "Waiting for database at ${DB_HOST}:${DB_PORT}..."
|
||||
wait-for-it ${DB_HOST}:${DB_PORT} --timeout=30 --strict || {
|
||||
echo "Timed out waiting for database" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "Database is available, continuing startup..."
|
||||
|
||||
python manage.py makemigrations
|
||||
python manage.py migrate
|
||||
python manage.py loaddata data/site/users.json
|
||||
python manage.py migrate --noinput
|
||||
|
||||
for fixture in /app/data/site/*.json; do
|
||||
echo "Loading fixture: $fixture"
|
||||
python manage.py loaddata "$fixture"
|
||||
done
|
||||
|
||||
python manage.py collectstatic --noinput
|
||||
exec /usr/local/bin/daphne -b 0.0.0.0 -p 8000 config.asgi:application
|
||||
exec daphne -b 0.0.0.0 -p 8000 config.asgi:application
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -10,6 +10,7 @@ BUILD_DIR = os.getenv('DJANGO_BUILD_DIR', BASE_DIR / 'build')
|
|||
|
||||
SECRET_KEY = os.getenv('DJANGO_SECRET_KEY')
|
||||
DEBUG = str(os.getenv('DJANGO_DEBUG')).lower() in ('1', 'true', 'yes', 'on')
|
||||
DOMAIN_NAME = os.getenv('DOMAIN_NAME', 'localhost')
|
||||
|
||||
ALLOWED_HOSTS = [stripped_host for host in os.getenv('DJANGO_ALLOWED_HOSTS', 'localhost').split(',') if (stripped_host:=host.strip())]
|
||||
|
||||
|
|
@ -76,6 +77,8 @@ CHANNEL_LAYERS = {
|
|||
},
|
||||
}
|
||||
|
||||
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
|
|
@ -93,11 +96,11 @@ TEMPLATES = [
|
|||
|
||||
|
||||
DB_ENGINE = os.getenv('DJANGO_DB_ENGINE', 'django.db.backends.sqlite3')
|
||||
DB_NAME = os.getenv('DJANGO_DB_NAME', BASE_DIR / 'db.sqlite3')
|
||||
DB_USER = os.getenv('DJANGO_DB_USER')
|
||||
DB_PASSWORD = os.getenv('DJANGO_DB_PASSWORD')
|
||||
DB_HOST = os.getenv('DJANGO_DB_HOST')
|
||||
DB_PORT = os.getenv('DJANGO_DB_PORT', 5432)
|
||||
DB_NAME = os.getenv('POSTGRES_DB', BASE_DIR / 'db.sqlite3')
|
||||
DB_USER = os.getenv('POSTGRES_USER')
|
||||
DB_PASSWORD = os.getenv('POSTGRES_PASSWORD')
|
||||
DB_HOST = os.getenv('POSTGRES_HOST')
|
||||
DB_PORT = os.getenv('POSTGRES_PORT', 5432)
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
|
|
@ -164,14 +167,32 @@ CELERY_TIMEZONE = 'UTC'
|
|||
CELERY_TASK_TRACK_STARTED = True
|
||||
CELERY_TASK_TIME_LIMIT = 30 * 60
|
||||
|
||||
MCP_AGENT_URL = os.getenv('MCP_AGENT_URL', 'http://localhost:8001')
|
||||
MCP_AGENT_URL = os.getenv('MCP_AGENT_URL')
|
||||
|
||||
if origins:=os.getenv('DJANGO_CORS_ALLOWED_ORIGINS'):
|
||||
CORS_ALLOWED_ORIGINS = origins.split(',')
|
||||
X_FRAME_OPTIONS = 'SAMEORIGIN'
|
||||
CORS_ALLOW_CREDENTIALS = True
|
||||
CORS_ALLOWED_ORIGINS = [
|
||||
f'http://{DOMAIN_NAME}',
|
||||
f'https://{DOMAIN_NAME}',
|
||||
]
|
||||
CSRF_TRUSTED_ORIGINS = [
|
||||
f'http://{DOMAIN_NAME}',
|
||||
f'https://{DOMAIN_NAME}',
|
||||
]
|
||||
|
||||
if trusted_origins:=os.getenv('DJANGO_CSRF_TRUSTED_ORIGINS'):
|
||||
CSRF_TRUSTED_ORIGINS = [origin.strip() for origin in trusted_origins.split(',')]
|
||||
|
||||
CSRF_COOKIE_HTTPONLY = False
|
||||
CSRF_COOKIE_SECURE = not DEBUG
|
||||
CSRF_COOKIE_SAMESITE = 'Lax'
|
||||
|
||||
SESSION_COOKIE_SAMESITE = 'Lax'
|
||||
SESSION_COOKIE_HTTPONLY = True
|
||||
SESSION_COOKIE_SECURE = not DEBUG
|
||||
SESSION_COOKIE_AGE = 1209600
|
||||
SESSION_SAVE_EVERY_REQUEST = True
|
||||
|
||||
if DEBUG:
|
||||
SECURE_CROSS_ORIGIN_OPENER_POLICY = None
|
||||
CORS_ALLOWED_ORIGINS.append(f'http://{DOMAIN_NAME}:5173')
|
||||
CORS_ALLOWED_ORIGINS.append(f'http://{DOMAIN_NAME}:8000')
|
||||
CSRF_TRUSTED_ORIGINS.append(f'http://{DOMAIN_NAME}:5173')
|
||||
CSRF_TRUSTED_ORIGINS.append(f'http://{DOMAIN_NAME}:8000')
|
||||
|
|
|
|||
18
data/site/agents.json
Normal file
18
data/site/agents.json
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
[
|
||||
{
|
||||
"model": "agents.agent",
|
||||
"pk": 1,
|
||||
"fields": {
|
||||
"uuid": "bc5ec7f0-a894-420f-b85b-bc799334eca7",
|
||||
"user": 1,
|
||||
"name": "Test Agent",
|
||||
"description": "General Purpose Agent",
|
||||
"status": "idle",
|
||||
"task_id": null,
|
||||
"created_at": "2025-12-20T20:29:57.607Z",
|
||||
"updated_at": "2025-12-20T20:29:57.607Z",
|
||||
"started_at": null,
|
||||
"completed_at": null
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
"avatar_url": "",
|
||||
"is_active": true,
|
||||
"is_staff": true,
|
||||
"role": "employee",
|
||||
"role": "manager",
|
||||
"groups": [],
|
||||
"user_permissions": []
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
|
||||
<link rel="manifest" href="/site.webmanifest">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Dynavera</title>
|
||||
</head>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ logger = logging.getLogger(__name__)
|
|||
class MCPAgentClient:
|
||||
|
||||
def __init__(self, server_url: Optional[str] = None):
|
||||
self.server_url = server_url or getattr(settings, 'MCP_AGENT_URL', 'http://localhost:8001')
|
||||
self.server_url = server_url or getattr(settings, 'MCP_AGENT_URL')
|
||||
self.http_client = httpx.AsyncClient(
|
||||
timeout=httpx.Timeout(300.0),
|
||||
follow_redirects=True
|
||||
|
|
@ -114,7 +114,7 @@ async def get_mcp_client() -> MCPAgentClient:
|
|||
|
||||
async with _client_lock:
|
||||
if _mcp_client_instance is None:
|
||||
server_url = getattr(settings, 'MCP_AGENT_URL', 'http://localhost:8001')
|
||||
server_url = getattr(settings, 'MCP_AGENT_URL')
|
||||
_mcp_client_instance = MCPAgentClient(server_url=server_url)
|
||||
|
||||
return _mcp_client_instance
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ django-celery-results==2.5.1
|
|||
django-celery-beat==2.8.1
|
||||
gunicorn==23.0.0
|
||||
jinja2==3.1.6
|
||||
psycopg2-binary==2.9.10
|
||||
python-dotenv==1.2.1
|
||||
requests==2.32.5
|
||||
sqlparse==0.5.3
|
||||
|
|
|
|||
|
|
@ -8,8 +8,18 @@ class ApiClient {
|
|||
}
|
||||
|
||||
private getCsrfToken(): string {
|
||||
const match = document.cookie.match(/(?:^|; )csrftoken=([^;]+)/);
|
||||
return match ? decodeURIComponent(match[1]) : '';
|
||||
let cookieValue = '';
|
||||
if (document.cookie && document.cookie !== '') {
|
||||
const cookies = document.cookie.split(';');
|
||||
for (let i = 0; i < cookies.length; i++) {
|
||||
const cookie = cookies[i].trim();
|
||||
if (cookie.substring(0, 10) === 'csrftoken=') {
|
||||
cookieValue = decodeURIComponent(cookie.substring(10));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cookieValue;
|
||||
}
|
||||
|
||||
private withCsrf(config?: AxiosRequestConfig): AxiosRequestConfig {
|
||||
|
|
|
|||
Loading…
Reference in a new issue