Files
HackWeasel b9dfb86260 GT AI OS Community Edition v2.0.33
Security hardening release addressing CodeQL and Dependabot alerts:

- Fix stack trace exposure in error responses
- Add SSRF protection with DNS resolution checking
- Implement proper URL hostname validation (replaces substring matching)
- Add centralized path sanitization to prevent path traversal
- Fix ReDoS vulnerability in email validation regex
- Improve HTML sanitization in validation utilities
- Fix capability wildcard matching in auth utilities
- Update glob dependency to address CVE
- Add CodeQL suppression comments for verified false positives

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 17:04:45 -05:00

185 lines
6.9 KiB
Python

"""
GT 2.0 Agent Model - Service-Based Architecture
Pydantic models for agent entities using the PostgreSQL + PGVector backend.
Complete migration - all assistant terminology has been replaced with agent.
"""
from datetime import datetime
from typing import Optional, Dict, Any, List
from enum import Enum
from pydantic import Field, ConfigDict, field_validator
from app.models.base import BaseServiceModel, BaseCreateModel, BaseUpdateModel, BaseResponseModel
class AgentStatus(str, Enum):
"""Agent status enumeration"""
ACTIVE = "active"
INACTIVE = "inactive"
ARCHIVED = "archived"
class AgentVisibility(str, Enum):
"""Agent visibility levels"""
INDIVIDUAL = "individual"
TEAM = "team"
ORGANIZATION = "organization"
class Agent(BaseServiceModel):
"""
Agent model for GT 2.0 service-based architecture.
Represents an AI agent configuration with capabilities, model settings,
and access control for perfect tenant isolation.
"""
# Core agent properties
name: str = Field(..., min_length=1, max_length=255, description="Agent display name")
description: Optional[str] = Field(None, max_length=1000, description="Agent description")
instructions: Optional[str] = Field(None, description="System instructions for the agent")
# Model configuration
model_provider: str = Field(default="groq", description="AI model provider")
model_name: str = Field(default="llama3-groq-8b-8192-tool-use-preview", description="Model identifier")
model_settings: Optional[Dict[str, Any]] = Field(default_factory=dict, description="Model-specific configuration")
# Capabilities and tools
capabilities: Optional[List[str]] = Field(default_factory=list, description="Agent capabilities")
tools: Optional[List[str]] = Field(default_factory=list, description="Available tools")
# MCP (Model Context Protocol) tool configuration
mcp_servers: Optional[List[str]] = Field(default_factory=list, description="MCP servers this agent can access")
rag_enabled: bool = Field(default=False, description="Whether agent can access RAG tools")
# Access control
owner_id: str = Field(..., description="User ID of the agent owner")
access_group: str = Field(default="individual", description="Access group for sharing")
visibility: AgentVisibility = Field(default=AgentVisibility.INDIVIDUAL, description="Agent visibility level")
# Status and metadata
status: AgentStatus = Field(default=AgentStatus.ACTIVE, description="Agent status")
featured: bool = Field(default=False, description="Whether agent is featured")
tags: Optional[List[str]] = Field(default_factory=list, description="Agent tags for categorization")
category: Optional[str] = Field(None, max_length=100, description="Agent category")
# Usage statistics
conversation_count: int = Field(default=0, description="Number of conversations")
last_used_at: Optional[datetime] = Field(None, description="Last usage timestamp")
# UI/UX Enhancement Fields
disclaimer: Optional[str] = Field(None, max_length=500, description="Disclaimer text shown in chat")
easy_prompts: Optional[List[str]] = Field(default_factory=list, max_length=10, description="Quick-access preset prompts (max 10)")
@field_validator('disclaimer')
@classmethod
def validate_disclaimer(cls, v):
"""Validate disclaimer length"""
if v and len(v) > 500:
raise ValueError('Disclaimer must be 500 characters or less')
return v
@field_validator('easy_prompts')
@classmethod
def validate_easy_prompts(cls, v):
"""Validate easy prompts count"""
if v and len(v) > 10:
raise ValueError('Maximum 10 easy prompts allowed')
return v
# Model configuration
model_config = ConfigDict(
protected_namespaces=(), # Allow model_ fields
json_encoders={
datetime: lambda v: v.isoformat() if v else None
}
)
@classmethod
def get_table_name(cls) -> str:
"""Get the database table name"""
return "agents"
def increment_usage(self):
"""Increment usage statistics"""
self.conversation_count += 1
self.last_used_at = datetime.utcnow()
self.update_timestamp()
class AgentCreate(BaseCreateModel):
"""Model for creating new agents"""
name: str = Field(..., min_length=1, max_length=255)
description: Optional[str] = Field(None, max_length=1000)
instructions: Optional[str] = None
model_provider: str = Field(default="groq")
model_name: str = Field(default="llama3-groq-8b-8192-tool-use-preview")
model_settings: Optional[Dict[str, Any]] = Field(default_factory=dict)
capabilities: Optional[List[str]] = Field(default_factory=list)
tools: Optional[List[str]] = Field(default_factory=list)
mcp_servers: Optional[List[str]] = Field(default_factory=list)
rag_enabled: bool = Field(default=False)
owner_id: str
access_group: str = Field(default="individual")
visibility: AgentVisibility = Field(default=AgentVisibility.INDIVIDUAL)
tags: Optional[List[str]] = Field(default_factory=list)
category: Optional[str] = None
disclaimer: Optional[str] = Field(None, max_length=500)
easy_prompts: Optional[List[str]] = Field(default_factory=list)
model_config = ConfigDict(protected_namespaces=())
class AgentUpdate(BaseUpdateModel):
"""Model for updating agents"""
name: Optional[str] = Field(None, min_length=1, max_length=255)
description: Optional[str] = Field(None, max_length=1000)
instructions: Optional[str] = None
model_provider: Optional[str] = None
model_name: Optional[str] = None
model_settings: Optional[Dict[str, Any]] = None
capabilities: Optional[List[str]] = None
tools: Optional[List[str]] = None
access_group: Optional[str] = None
visibility: Optional[AgentVisibility] = None
status: Optional[AgentStatus] = None
featured: Optional[bool] = None
tags: Optional[List[str]] = None
category: Optional[str] = None
disclaimer: Optional[str] = None
easy_prompts: Optional[List[str]] = None
model_config = ConfigDict(protected_namespaces=())
class AgentResponse(BaseResponseModel):
"""Model for agent API responses"""
id: str
name: str
description: Optional[str]
instructions: Optional[str]
model_provider: str
model_name: str
model_settings: Dict[str, Any]
capabilities: List[str]
tools: List[str]
owner_id: str
access_group: str
visibility: AgentVisibility
status: AgentStatus
featured: bool
tags: List[str]
category: Optional[str]
conversation_count: int
usage_count: int = 0 # Alias for conversation_count for frontend compatibility
last_used_at: Optional[datetime]
disclaimer: Optional[str]
easy_prompts: List[str]
created_at: datetime
updated_at: datetime
model_config = ConfigDict(protected_namespaces=())