- Add discipline (business category) and rating (1-5 stars) fields to agent models
- Discipline dropdown on registration form (required) and edit modals (both user and admin)
- Interactive star rating widget with immediate save via PUT /api/agents/{id}/rating
- Discipline filter and rating sort on agent management dashboard
- Purple discipline badge and gold star badge on agent cards
- CSV export/import support for discipline, rating, and total_tokens
- Initialize total_tokens on manually-created agents for consistent CSV exports
- Search agents by discipline field
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
202 lines
8.4 KiB
Python
202 lines
8.4 KiB
Python
from pydantic import BaseModel, EmailStr, Field
|
|
from typing import Optional, List
|
|
|
|
|
|
class UsageTimelineEntry(BaseModel):
|
|
date: str = Field(..., description="Date in YYYY-MM-DD format")
|
|
message_count: int = Field(..., ge=0, description="Number of messages on this date")
|
|
token_count: int = Field(0, ge=0, description="Number of tokens consumed on this date")
|
|
|
|
|
|
class AiAgent(BaseModel):
|
|
agent_id: int
|
|
agent_name: str
|
|
agent_tool: str | None = Field(default=None, title="The tool or platform where the agent operates", max_length=100)
|
|
agent_description: str | None = Field(default=None, title="The description of the agent", max_length=300)
|
|
agent_purpose: str | None = Field(default=None, title="The purpose of the agent", max_length=200)
|
|
agent_version: str | None = Field(default=None, title="The version of the agent", max_length=100)
|
|
agent_status: str | None = Field(default=None, title="The status of the agent", max_length=100, enum=['Active', 'Inactive', 'Deprecated', 'Development'])
|
|
agent_location: str | None = Field(default=None, title="The location of the agent", max_length=100)
|
|
agent_department: str | None = Field(default=None, title="The department of the agent", max_length=100)
|
|
agent_contact_person: str | None = Field(default=None, title="The contact person for the agent", max_length=100)
|
|
agent_created_at: str | None = Field(default=None, title="The creation date of the agent", max_length=100)
|
|
agent_updated_at: str | None = Field(default=None, title="The last update date of the agent", max_length=100)
|
|
agent_tags: list[str] | None = Field(default=None, title="Tags associated with the agent", max_length=100)
|
|
agent_metadata: dict[str, str] | None = Field(default=None, title="Metadata associated with the agent")
|
|
agent_userbase: list[str] | None = Field(default=None, title="Userbase associated with the agent")
|
|
agent_capabilities: list[str] | None = Field(default=None, title="Capabilities of the agent")
|
|
url: str | None = Field(default=None, title="Direct link to create a conversation with this agent")
|
|
quality_audit_status: bool | None = Field(default=False, title="Quality audit status")
|
|
quality_audit_updated_by: str | None = Field(default=None, title="Admin user ID who updated quality audit")
|
|
quality_audit_updated_at: str | None = Field(default=None, title="Quality audit last update timestamp")
|
|
quality_audit_updated_by_name: str | None = Field(default=None, title="Admin user name who updated quality audit")
|
|
risk_factor: int | None = Field(default=None, title="Risk factor rating (1-5)", ge=1, le=5)
|
|
last_edited_by: str | None = Field(default=None, title="Email of user who last edited this agent")
|
|
discipline: str | None = Field(default=None, title="Business discipline/category", max_length=100)
|
|
rating: float | None = Field(default=None, title="Star rating (1-5)", ge=1, le=5)
|
|
|
|
|
|
|
|
|
|
# User Base Model
|
|
class UserCreate(BaseModel):
|
|
email: EmailStr
|
|
password: str
|
|
full_name: Optional[str] = None
|
|
|
|
class UserLogin(BaseModel):
|
|
email: EmailStr
|
|
password: str
|
|
|
|
class UserResponse(BaseModel):
|
|
email: EmailStr
|
|
full_name: Optional[str] = None
|
|
is_active: bool
|
|
is_admin: bool
|
|
auth_provider: Optional[str] = "local"
|
|
|
|
class UserUpdate(BaseModel):
|
|
full_name: Optional[str] = None
|
|
is_active: Optional[bool] = None
|
|
is_admin: Optional[bool] = None
|
|
|
|
class Token(BaseModel):
|
|
access_token: str
|
|
token_type: str = "bearer"
|
|
|
|
# Admin user management models
|
|
class AdminUserCreate(BaseModel):
|
|
email: EmailStr
|
|
full_name: Optional[str] = None
|
|
password: str = Field(..., min_length=8)
|
|
is_admin: bool = False
|
|
|
|
class AdminPasswordReset(BaseModel):
|
|
new_password: str = Field(..., min_length=8)
|
|
|
|
class PasswordChange(BaseModel):
|
|
current_password: str
|
|
new_password: str = Field(..., min_length=8)
|
|
|
|
# Agent models for creation and response
|
|
class AiAgentCreate(BaseModel):
|
|
agent_name: str
|
|
agent_tool: str
|
|
agent_description: Optional[str] = None
|
|
agent_purpose: Optional[str] = None
|
|
agent_version: Optional[str] = None
|
|
agent_status: Optional[str] = "Development"
|
|
agent_location: Optional[str] = None
|
|
agent_department: Optional[str] = None
|
|
agent_contact_person: Optional[str] = None
|
|
agent_tags: Optional[list[str]] = None
|
|
agent_metadata: Optional[dict[str, str]] = None
|
|
agent_userbase: Optional[list[str]] = None
|
|
agent_capabilities: Optional[list[str]] = None
|
|
url: Optional[str] = None
|
|
quality_audit_status: Optional[bool] = False
|
|
quality_audit_updated_by: Optional[str] = None
|
|
quality_audit_updated_at: Optional[str] = None
|
|
quality_audit_updated_by_name: Optional[str] = None
|
|
risk_factor: Optional[int] = Field(default=None, ge=1, le=5)
|
|
last_edited_by: Optional[str] = None
|
|
discipline: Optional[str] = None
|
|
rating: Optional[float] = Field(default=None, ge=1, le=5)
|
|
|
|
class AiAgentResponse(BaseModel):
|
|
agent_id: str
|
|
agent_name: str
|
|
agent_tool: Optional[str] = None
|
|
agent_description: Optional[str] = None
|
|
agent_purpose: Optional[str] = None
|
|
agent_version: Optional[str] = None
|
|
agent_status: Optional[str] = None
|
|
agent_location: Optional[str] = None
|
|
agent_department: Optional[str] = None
|
|
agent_contact_person: Optional[str] = None
|
|
agent_created_at: Optional[str] = None
|
|
agent_updated_at: Optional[str] = None
|
|
agent_tags: Optional[list[str]] = None
|
|
agent_metadata: Optional[dict[str, str]] = None
|
|
agent_userbase: Optional[list[str]] = None
|
|
agent_capabilities: Optional[list[str]] = None
|
|
url: Optional[str] = None
|
|
quality_audit_status: Optional[bool] = None
|
|
quality_audit_updated_by: Optional[str] = None
|
|
quality_audit_updated_at: Optional[str] = None
|
|
quality_audit_updated_by_name: Optional[str] = None
|
|
risk_factor: Optional[int] = None
|
|
last_edited_by: Optional[str] = None
|
|
discipline: Optional[str] = None
|
|
rating: Optional[float] = None
|
|
created_by: str
|
|
|
|
# Usage tracking fields (new)
|
|
usage_timeline: Optional[List[dict]] = None
|
|
conversation_count: Optional[int] = None
|
|
unique_users: Optional[int] = None
|
|
total_messages: Optional[int] = None
|
|
first_used: Optional[str] = None
|
|
last_used: Optional[str] = None
|
|
total_tokens: Optional[int] = None
|
|
|
|
# Agent Collector API Models (for compatibility with agent_collector app)
|
|
class AgentCollectorCreate(BaseModel):
|
|
name: str = Field(min_length=1)
|
|
description: str = Field(min_length=1)
|
|
purpose: str = Field(min_length=1)
|
|
tool: str = Field(min_length=1)
|
|
location: Optional[str] = None
|
|
userbase: Optional[list[str]] = None
|
|
version: Optional[str] = None
|
|
creation_date: Optional[str] = None # ISO 8601 datetime string
|
|
last_updated: Optional[str] = None # ISO 8601 datetime string
|
|
capabilities: Optional[list[str]] = None
|
|
status: Optional[str] = Field(default="development", pattern="^(?i)(active|inactive|deprecated|development)$")
|
|
department: Optional[str] = None
|
|
contact_person: Optional[str] = None
|
|
tags: Optional[list[str]] = None
|
|
metadata: Optional[dict] = None
|
|
url: Optional[str] = None
|
|
discipline: Optional[str] = None
|
|
|
|
# Usage tracking fields (new)
|
|
usage_timeline: Optional[List[UsageTimelineEntry]] = None
|
|
conversation_count: Optional[int] = Field(default=None, ge=0)
|
|
unique_users: Optional[int] = Field(default=None, ge=0)
|
|
total_messages: Optional[int] = Field(default=None, ge=0)
|
|
first_used: Optional[str] = None # ISO 8601 datetime string
|
|
last_used: Optional[str] = None # ISO 8601 datetime string
|
|
total_tokens: Optional[int] = Field(default=None, ge=0)
|
|
|
|
class AgentCollectorResponse(BaseModel):
|
|
status: str = "success"
|
|
message: str = "Agent data collected successfully"
|
|
agent_id: str
|
|
|
|
class HealthCheckResponse(BaseModel):
|
|
status: str
|
|
message: str
|
|
timestamp: str
|
|
database: dict
|
|
|
|
class AgentUsageTrackingResponse(BaseModel):
|
|
status: str = "usage_logged"
|
|
message: str = "Agent already exists, usage tracked"
|
|
agent_name: str
|
|
|
|
class AgentUsageRecord(BaseModel):
|
|
agent_name: str
|
|
agent_data: dict
|
|
timestamp: str
|
|
usage_count: Optional[int] = None
|
|
|
|
class AgentUsageStatsResponse(BaseModel):
|
|
agent_name: str
|
|
total_usage_count: int
|
|
first_usage: Optional[str] = None
|
|
last_usage: Optional[str] = None
|
|
usage_by_period: dict
|
|
conversation_count: Optional[int] = None
|
|
unique_users: Optional[int] = None
|
|
total_tokens: Optional[int] = None
|