From b48028dd91dd9a7ca669f482bb7f7ab2f94b0646 Mon Sep 17 00:00:00 2001 From: Eric Jungbauer Date: Mon, 13 Apr 2026 14:24:27 +0000 Subject: [PATCH] Fix Run Now: mount agents in container, install deps, fix datetime bug --- dashboard/Dockerfile | 2 +- dashboard/app.py | 31 ++++++++++++++++++------------- docker-compose.yml | 1 + 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/dashboard/Dockerfile b/dashboard/Dockerfile index 868fe8a..9be95d6 100644 --- a/dashboard/Dockerfile +++ b/dashboard/Dockerfile @@ -2,7 +2,7 @@ FROM python:3.12-slim WORKDIR /app -RUN pip install --no-cache-dir fastapi uvicorn sqlalchemy +RUN pip install --no-cache-dir fastapi uvicorn sqlalchemy caldav icalendar recurring-ical-events requests COPY . . diff --git a/dashboard/app.py b/dashboard/app.py index 78a7c8c..e0d343e 100644 --- a/dashboard/app.py +++ b/dashboard/app.py @@ -461,24 +461,28 @@ def trigger_instance(instance_id: int, user: dict = Depends(require_auth), db: S catalog_id = inst.catalog_id u = db.query(User).filter(User.id == user["user_id"]).first() + import subprocess + agent_dir = "/app/agents" + env = {**dict(os.environ), "PYTHONPATH": agent_dir} + if catalog_id == "daily-briefing": - # Find the user's briefing wrapper script or use the generic engine - import subprocess - env = {**dict(os.environ), f"{u.username.upper().replace('.','_')}_INSTANCE_ID": str(instance_id)} - # Check for user-specific script - script_map = { - "eric": "eric_briefing.py", - "angela": "angela_briefing.py", - } + script_map = {"eric": "eric_briefing.py", "angela": "angela_briefing.py"} script = script_map.get(u.username, None) + env_key = f"{u.username.upper().replace('.', '_')}_INSTANCE_ID" + env[env_key] = str(instance_id) if script: - cmd = f"cd /opt/agent-dashboard/agents && {u.username.upper().replace('.','_')}_INSTANCE_ID={instance_id} python3 {script}" + cmd = ["python3", f"{agent_dir}/{script}"] else: - cmd = f"cd /opt/agent-dashboard/agents && python3 -c \"from daily_briefing import run; run({{'person': '{u.display_name}', 'agent_id': '{catalog_id}', 'instance_id': {instance_id}, 'wiki_parent_doc_id': '', 'location': {{}}}})\"" - subprocess.Popen(cmd, shell=True, env=env) + # Generic: run the engine directly with instance config + cmd = ["python3", "-c", + f"import sys; sys.path.insert(0, '{agent_dir}'); " + f"from daily_briefing import run; " + f"run({{'person': '{u.display_name}', 'agent_id': '{catalog_id}', " + f"'instance_id': {instance_id}, 'wiki_parent_doc_id': '', 'location': {{}}}})"] + subprocess.Popen(cmd, env=env, cwd=agent_dir) return {"status": "triggered", "message": f"Running {catalog_id} for {u.display_name}"} - return {"status": "error", "message": f"Manual trigger not supported for {catalog_id} yet"} + return {"status": "error", "message": f"Manual trigger not yet supported for {catalog_id}"} # --- Internal endpoints (no auth, for agent scripts) --- @@ -756,7 +760,8 @@ def get_my_bridge(user: dict = Depends(require_auth), db: Session = Depends(get_ return {"connected": False} # Mark offline if no heartbeat in 10 minutes if bridge.last_heartbeat: - age = (datetime.now(timezone.utc) - bridge.last_heartbeat).total_seconds() + hb = bridge.last_heartbeat.replace(tzinfo=timezone.utc) if bridge.last_heartbeat.tzinfo is None else bridge.last_heartbeat + age = (datetime.now(timezone.utc) - hb).total_seconds() if age > 600: bridge.status = "offline" db.commit() diff --git a/docker-compose.yml b/docker-compose.yml index 8a830f2..aff90ad 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,6 +6,7 @@ services: - "8550:8550" volumes: - ./data:/app/data + - ./agents:/app/agents environment: - DB_PATH=/app/data/agents.db restart: unless-stopped