"""Background agent worker that autonomously completes tasks.""" import asyncio import random from app.database import SessionLocal from app.models import Task, TaskStatus, Project, AI_AGENT_USER_ID from app.tools.memory import complete_task async def agent_loop(): """Background loop that processes tasks for agent-enabled projects.""" print("[Agent] Worker started, waiting for initial delay...") # Initial delay to let the server start up await asyncio.sleep(10) while True: try: await process_one_task() except Exception as e: print(f"[Agent] Error: {e}") # Wait 25-35 seconds (jitter to avoid rate limit patterns) wait_time = random.uniform(25, 35) await asyncio.sleep(wait_time) async def process_one_task(): """Pick a random todo task from agent-enabled projects and complete it.""" db = SessionLocal() try: # Find projects with agent enabled projects = db.query(Project).filter(Project.agent_enabled == True).all() if not projects: return # Pick random project project = random.choice(projects) # Find a random todo task todo_tasks = db.query(Task).filter( Task.project_id == project.id, Task.status == TaskStatus.todo ).all() if not todo_tasks: return task = random.choice(todo_tasks) print(f"[Agent] Starting task: {task.title}") # Step 1: Move to in_progress task.status = TaskStatus.in_progress task.working_by = AI_AGENT_USER_ID db.commit() # Step 2: "Work" on it (small delay for realism) await asyncio.sleep(random.uniform(2, 5)) # Step 3: Complete the task result = await complete_task( task_id=task.id, project_id=project.id, user_id=AI_AGENT_USER_ID, what_i_did=f"Implemented {task.title}. {task.description or 'Completed the task as specified.'}", actor_type="agent" ) if result.get("success"): print(f"[Agent] Completed task: {task.title}") else: print(f"[Agent] Failed to complete task: {result.get('error')}") except Exception as e: print(f"[Agent] Error in process_one_task: {e}") db.rollback() finally: db.close()