Oliver-ai-bot_2.0/backend/app/models/agent.py
Vadym Samoilenko f2b5dce63a feat: code interpreter, agent analytics/execute APIs, usage sync, RAG scoping fixes
**Phase 1 — Agent Usage Sync to AgentHub Collector**
- Add agent_usage service: per-agent stats (messages, tokens, conversations, unique users, first/last used)
- Collector sync now includes usage data in payload; sync_agent accepts optional db session
- Celery beat task runs every 6h to sync all active agents with fresh usage stats

**Phase 2 — LibreCodeInterpreter Integration**
- Add code-interpreter, redis, minio services to docker-compose.prod.yml
- CodeInterpreterTool (BaseTool): sandboxed execution via /exec, 13 languages, Python session persistence via conversation_id
- ToolContext extended with conversation_id and agent_slug
- enable_code_interpreter boolean on Agent model (migration 027), tool seeded in tool_definitions (migration 026)
- Code interpreter auto-injected into agent tools when enabled
- Frontend: CodeExecutionResult component with terminal-style stdout/stderr/files rendering

**Phase 3 — Agent API Endpoints**
- GET /api/v1/agents/{slug}/analytics — per-agent usage stats + daily time series
- POST /api/v1/agents/{slug}/execute — synchronous programmatic agent execution (non-SSE)
- Sub-routes registered before /{slug} to avoid FastAPI route conflict

**Phase 4 — Fix Department & Region RAG Scoping**
- Department filter now OR-includes global (null department) docs, matching region filter behaviour
- retriever.search_documents/retrieve_and_prepare/query accept department_ids/region_codes lists
- MatchAny used for multi-value Qdrant filters; chat.py passes full arrays from knowledge_scope
- Admin PATCH /users/{id} now validates region_code against the regions table

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 20:13:27 +01:00

66 lines
3.4 KiB
Python

"""
Agent model — configurable AI agents replacing hardcoded chat modes
"""
from sqlalchemy import Column, String, Boolean, DateTime, Float, Integer, Text, ForeignKey
from sqlalchemy.dialects.postgresql import UUID, JSONB
from sqlalchemy.orm import relationship
from app.database import Base
import uuid
from datetime import datetime
class Agent(Base):
"""
Configurable AI agent entity.
Replaces the hardcoded rag/assistant mode system.
System agents (is_system=True) are seeded from migration and cannot be
edited by anyone below super_admin.
"""
__tablename__ = "agents"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
slug = Column(String(50), unique=True, nullable=False, index=True) # url-safe: "rag", "hr-helper"
name = Column(String(100), nullable=False)
description = Column(Text, nullable=True)
icon = Column(String(50), default="bot", nullable=False) # lucide icon name
color = Column(String(20), default="primary", nullable=False) # tailwind color token
category = Column(String(50), default="general", nullable=False) # "general", "hr", "finance", "it", "operations"
# LLM Configuration
llm_provider = Column(String(20), nullable=False) # "openai" | "anthropic" | "google"
llm_model = Column(String(100), nullable=False)
temperature = Column(Float, default=0.7, nullable=False)
max_tokens = Column(Integer, nullable=True) # optional output limit
# System prompt & UX
system_prompt = Column(Text, nullable=False)
welcome_message = Column(String(500), nullable=True) # greeting shown on empty chat
suggested_prompts = Column(JSONB, default=list, nullable=False, server_default='[]')
# Capabilities & Tools
tool_ids = Column(JSONB, default=list, nullable=False, server_default='[]') # ToolDefinition names
enable_rag = Column(Boolean, default=False, nullable=False)
knowledge_scope = Column(JSONB, default=dict, nullable=False, server_default='{}')
# knowledge_scope: {"department_ids": [], "region_codes": [], "all": false}
enable_file_upload = Column(Boolean, default=True, nullable=False)
enable_code_interpreter = Column(Boolean, default=False, nullable=False, server_default='false')
capabilities = Column(JSONB, default=list, nullable=False, server_default='[]') # extensible future caps
# Visibility & Access
visibility = Column(String(20), default="public", nullable=False) # "public" | "department" | "private"
allowed_department_ids = Column(JSONB, default=list, nullable=False, server_default='[]')
is_template = Column(Boolean, default=False, nullable=False) # appears in user catalog
# Ownership & Lifecycle
created_by = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="SET NULL"), nullable=True)
status = Column(String(20), default="draft", nullable=False) # "draft" | "active" | "archived"
is_system = Column(Boolean, default=False, nullable=False) # seeded system agents
# Timestamps
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
# Relationships
creator = relationship("User", foreign_keys=[created_by])
conversations = relationship("Conversation", back_populates="agent")