- agent_runner: local directory + cloud agent orchestration via Redis - 5 domain agents: filesystem, task, note, project, timeline - integrations: Gmail, MS Graph (Outlook + Teams) - journey: guided chatbot conversation to build prompt_template - routes: REST endpoints (catalog, can-create, trigger) - redis_consumer: subscribes to batch:request:* pattern - ws_context: Redis-based execute_on_client for tool round-trip - Dockerfile with 300s timeout for long-running batch jobs
111 lines
3.1 KiB
Python
111 lines
3.1 KiB
Python
"""Project agent — full lifecycle management.
|
|
|
|
Adapted for Batch Agent Service: import from app.ws_context.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from langchain_core.tools import tool
|
|
|
|
from app.ws_context import execute_on_client
|
|
|
|
|
|
@tool
|
|
async def list_projects(client_id: str = "", include_archived: int = 0) -> str:
|
|
"""List projects, optionally filtered by client_id."""
|
|
result = await execute_on_client(
|
|
action="select",
|
|
table="projects",
|
|
filters={
|
|
"clientId": client_id or None,
|
|
"includeArchived": bool(include_archived),
|
|
},
|
|
)
|
|
rows = result.get("rows", [])
|
|
if not rows:
|
|
return "No projects found."
|
|
lines = [f"- {r['name']} (status: {r['status']}, id: {r['id']})" for r in rows]
|
|
return f"Found {len(rows)} project(s):\n" + "\n".join(lines)
|
|
|
|
|
|
@tool
|
|
async def list_all_projects() -> str:
|
|
"""List every project regardless of client or status."""
|
|
result = await execute_on_client(action="select", table="projects")
|
|
rows = result.get("rows", [])
|
|
if not rows:
|
|
return "No projects found."
|
|
lines = [f"- {r['name']} (status: {r['status']}, id: {r['id']})" for r in rows]
|
|
return f"All projects ({len(rows)}):\n" + "\n".join(lines)
|
|
|
|
|
|
@tool
|
|
async def get_project(project_id: str) -> str:
|
|
"""Fetch a single project by its UUID."""
|
|
result = await execute_on_client(action="get", table="projects", data={"id": project_id})
|
|
row = result.get("row")
|
|
if not row:
|
|
return f"Project {project_id} not found."
|
|
return (
|
|
f"Project: '{row['name']}' (id: {row['id']}, status: {row['status']}, "
|
|
f"clientId: {row.get('clientId', 'none')})"
|
|
)
|
|
|
|
|
|
@tool
|
|
async def create_project(name: str, client_id: str = "") -> str:
|
|
"""Create a new project."""
|
|
result = await execute_on_client(
|
|
action="insert",
|
|
table="projects",
|
|
data={"name": name, "clientId": client_id or None},
|
|
)
|
|
row = result["row"]
|
|
return f"Project created: '{row['name']}' (id: {row['id']})"
|
|
|
|
|
|
@tool
|
|
async def update_project(
|
|
project_id: str,
|
|
name: str = "",
|
|
client_id: str = "",
|
|
status: str = "",
|
|
ai_summary: str = "",
|
|
) -> str:
|
|
"""Update a project. Only pass fields that should change."""
|
|
updates: dict[str, Any] = {}
|
|
if name:
|
|
updates["name"] = name
|
|
if client_id:
|
|
updates["clientId"] = client_id
|
|
if status:
|
|
updates["status"] = status
|
|
if ai_summary:
|
|
updates["aiSummary"] = ai_summary
|
|
result = await execute_on_client(
|
|
action="update",
|
|
table="projects",
|
|
data={"id": project_id, "updates": updates},
|
|
)
|
|
row = result["row"]
|
|
return f"Project updated: '{row['name']}' (id: {row['id']}, status: {row['status']})"
|
|
|
|
|
|
@tool
|
|
async def delete_project(project_id: str) -> str:
|
|
"""Permanently delete a project."""
|
|
await execute_on_client(action="delete", table="projects", data={"id": project_id})
|
|
return f"Project {project_id} permanently deleted."
|
|
|
|
|
|
PROJECT_TOOLS: list[Any] = [
|
|
list_projects,
|
|
list_all_projects,
|
|
get_project,
|
|
create_project,
|
|
update_project,
|
|
delete_project,
|
|
]
|