mirror of https://github.com/kortix-ai/suna.git
175 lines
4.7 KiB
Python
175 lines
4.7 KiB
Python
from abc import ABC, abstractmethod
|
|
from dataclasses import dataclass, field
|
|
from datetime import datetime
|
|
from typing import Dict, List, Optional, Any
|
|
from uuid import UUID, uuid4
|
|
from enum import Enum
|
|
|
|
|
|
class VersionStatus(Enum):
|
|
ACTIVE = "active"
|
|
INACTIVE = "inactive"
|
|
ARCHIVED = "archived"
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class VersionId:
|
|
value: UUID
|
|
|
|
@classmethod
|
|
def generate(cls) -> 'VersionId':
|
|
return cls(value=uuid4())
|
|
|
|
@classmethod
|
|
def from_string(cls, value: str) -> 'VersionId':
|
|
return cls(value=UUID(value))
|
|
|
|
def __str__(self) -> str:
|
|
return str(self.value)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class AgentId:
|
|
value: UUID
|
|
|
|
@classmethod
|
|
def from_string(cls, value: str) -> 'AgentId':
|
|
return cls(value=UUID(value))
|
|
|
|
def __str__(self) -> str:
|
|
return str(self.value)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class UserId:
|
|
value: UUID
|
|
|
|
@classmethod
|
|
def from_string(cls, value: str) -> 'UserId':
|
|
return cls(value=UUID(value))
|
|
|
|
def __str__(self) -> str:
|
|
return str(self.value)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class VersionNumber:
|
|
value: int
|
|
|
|
def __post_init__(self):
|
|
if self.value < 1:
|
|
raise ValueError("Version number must be positive")
|
|
|
|
def next(self) -> 'VersionNumber':
|
|
return VersionNumber(self.value + 1)
|
|
|
|
def __str__(self) -> str:
|
|
return f"v{self.value}"
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class SystemPrompt:
|
|
value: str
|
|
|
|
def __post_init__(self):
|
|
if not self.value or not self.value.strip():
|
|
raise ValueError("System prompt cannot be empty")
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class MCPConfiguration:
|
|
name: str
|
|
type: str
|
|
config: Dict[str, Any] = field(default_factory=dict)
|
|
enabled_tools: List[str] = field(default_factory=list)
|
|
|
|
def __post_init__(self):
|
|
if not self.name:
|
|
raise ValueError("MCP name cannot be empty")
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ToolConfiguration:
|
|
tools: Dict[str, Any] = field(default_factory=dict)
|
|
|
|
def is_tool_enabled(self, tool_name: str) -> bool:
|
|
tool_config = self.tools.get(tool_name, {})
|
|
if isinstance(tool_config, bool):
|
|
return tool_config
|
|
return tool_config.get('enabled', False)
|
|
|
|
def get_enabled_tools(self) -> List[str]:
|
|
return [
|
|
name for name, config in self.tools.items()
|
|
if self.is_tool_enabled(name)
|
|
]
|
|
|
|
|
|
@dataclass
|
|
class AgentVersion:
|
|
version_id: VersionId
|
|
agent_id: AgentId
|
|
version_number: VersionNumber
|
|
version_name: str
|
|
system_prompt: SystemPrompt
|
|
configured_mcps: List[MCPConfiguration]
|
|
custom_mcps: List[MCPConfiguration]
|
|
tool_configuration: ToolConfiguration
|
|
status: VersionStatus
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
created_by: UserId
|
|
change_description: Optional[str] = None
|
|
previous_version_id: Optional[VersionId] = None
|
|
|
|
@property
|
|
def is_active(self) -> bool:
|
|
return self.status == VersionStatus.ACTIVE
|
|
|
|
def activate(self) -> None:
|
|
self.status = VersionStatus.ACTIVE
|
|
self.updated_at = datetime.utcnow()
|
|
|
|
def deactivate(self) -> None:
|
|
self.status = VersionStatus.INACTIVE
|
|
self.updated_at = datetime.utcnow()
|
|
|
|
def archive(self) -> None:
|
|
self.status = VersionStatus.ARCHIVED
|
|
self.updated_at = datetime.utcnow()
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
return {
|
|
'version_id': str(self.version_id),
|
|
'agent_id': str(self.agent_id),
|
|
'version_number': self.version_number.value,
|
|
'version_name': self.version_name,
|
|
'system_prompt': self.system_prompt.value,
|
|
'configured_mcps': [
|
|
{
|
|
'name': mcp.name,
|
|
'type': mcp.type,
|
|
'config': mcp.config,
|
|
'enabled_tools': mcp.enabled_tools
|
|
}
|
|
for mcp in self.configured_mcps
|
|
],
|
|
'custom_mcps': [
|
|
{
|
|
'name': mcp.name,
|
|
'type': mcp.type,
|
|
'config': mcp.config,
|
|
'enabled_tools': mcp.enabled_tools
|
|
}
|
|
for mcp in self.custom_mcps
|
|
],
|
|
'agentpress_tools': self.tool_configuration.tools,
|
|
'is_active': self.is_active,
|
|
'status': self.status.value,
|
|
'created_at': self.created_at.isoformat(),
|
|
'updated_at': self.updated_at.isoformat(),
|
|
'created_by': str(self.created_by),
|
|
'change_description': self.change_description,
|
|
'previous_version_id': str(self.previous_version_id) if self.previous_version_id else None
|
|
}
|