mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-05-07 18:19:00 +00:00
135 lines
4.8 KiB
Python
135 lines
4.8 KiB
Python
"""
|
|
Fingerprint Module
|
|
|
|
This module provides functionality for generating and validating unique identifiers
|
|
for CrewAI agents. These identifiers are used for tracking, auditing, and security.
|
|
"""
|
|
|
|
import uuid
|
|
from datetime import datetime
|
|
from typing import Any, Dict, Optional
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class Fingerprint(BaseModel):
|
|
"""
|
|
A class for generating and managing unique identifiers for agents.
|
|
|
|
Each agent has dual identifiers:
|
|
- Human-readable ID: For debugging and reference (derived from role if not specified)
|
|
- Fingerprint UUID: Unique runtime identifier for tracking and auditing
|
|
|
|
Attributes:
|
|
uuid_str (str): String representation of the UUID for this fingerprint, auto-generated
|
|
created_at (datetime): When this fingerprint was created, auto-generated
|
|
metadata (Dict[str, Any]): Additional metadata associated with this fingerprint
|
|
"""
|
|
|
|
uuid_str: str = Field(default_factory=lambda: str(uuid.uuid4()), description="String representation of the UUID")
|
|
created_at: datetime = Field(default_factory=datetime.now, description="When this fingerprint was created")
|
|
metadata: Dict[str, Any] = Field(default_factory=dict, description="Additional metadata for this fingerprint")
|
|
|
|
class Config:
|
|
arbitrary_types_allowed = True
|
|
|
|
def __init__(self, **data):
|
|
"""Initialize a Fingerprint with auto-generated uuid_str and created_at."""
|
|
# Remove uuid_str and created_at from data to ensure they're auto-generated
|
|
if 'uuid_str' in data:
|
|
data.pop('uuid_str')
|
|
if 'created_at' in data:
|
|
data.pop('created_at')
|
|
|
|
# Call the parent constructor with the modified data
|
|
super().__init__(**data)
|
|
|
|
@property
|
|
def uuid(self) -> uuid.UUID:
|
|
"""Get the UUID object for this fingerprint."""
|
|
return uuid.UUID(self.uuid_str)
|
|
|
|
@classmethod
|
|
def _generate_uuid(cls, seed: str) -> str:
|
|
"""
|
|
Generate a deterministic UUID based on a seed string.
|
|
|
|
Args:
|
|
seed (str): The seed string to use for UUID generation
|
|
|
|
Returns:
|
|
str: A string representation of the UUID consistently generated from the seed
|
|
"""
|
|
# Create a deterministic UUID using v5 (SHA-1)
|
|
# This uses the DNS namespace as a base, but we could create a custom namespace
|
|
return str(uuid.uuid5(uuid.NAMESPACE_DNS, seed))
|
|
|
|
@classmethod
|
|
def generate(cls, seed: Optional[str] = None, metadata: Optional[Dict[str, Any]] = None) -> 'Fingerprint':
|
|
"""
|
|
Static factory method to create a new Fingerprint.
|
|
|
|
Args:
|
|
seed (Optional[str]): A string to use as seed for the UUID generation.
|
|
If None, a random UUID is generated.
|
|
metadata (Optional[Dict[str, Any]]): Additional metadata to store with the fingerprint.
|
|
|
|
Returns:
|
|
Fingerprint: A new Fingerprint instance
|
|
"""
|
|
fingerprint = cls(metadata=metadata or {})
|
|
if seed:
|
|
# For seed-based generation, we need to manually set the uuid_str after creation
|
|
object.__setattr__(fingerprint, 'uuid_str', cls._generate_uuid(seed))
|
|
return fingerprint
|
|
|
|
def __str__(self) -> str:
|
|
"""String representation of the fingerprint (the UUID)."""
|
|
return self.uuid_str
|
|
|
|
def __eq__(self, other) -> bool:
|
|
"""Compare fingerprints by their UUID."""
|
|
if isinstance(other, Fingerprint):
|
|
return self.uuid_str == other.uuid_str
|
|
return False
|
|
|
|
def __hash__(self) -> int:
|
|
"""Hash of the fingerprint (based on UUID)."""
|
|
return hash(self.uuid_str)
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
"""
|
|
Convert the fingerprint to a dictionary representation.
|
|
|
|
Returns:
|
|
Dict[str, Any]: Dictionary representation of the fingerprint
|
|
"""
|
|
return {
|
|
"uuid_str": self.uuid_str,
|
|
"created_at": self.created_at.isoformat(),
|
|
"metadata": self.metadata
|
|
}
|
|
|
|
@classmethod
|
|
def from_dict(cls, data: Dict[str, Any]) -> 'Fingerprint':
|
|
"""
|
|
Create a Fingerprint from a dictionary representation.
|
|
|
|
Args:
|
|
data (Dict[str, Any]): Dictionary representation of a fingerprint
|
|
|
|
Returns:
|
|
Fingerprint: A new Fingerprint instance
|
|
"""
|
|
if not data:
|
|
return cls()
|
|
|
|
fingerprint = cls(metadata=data.get("metadata", {}))
|
|
|
|
# For consistency with existing stored fingerprints, we need to manually set these
|
|
if "uuid_str" in data:
|
|
object.__setattr__(fingerprint, 'uuid_str', data["uuid_str"])
|
|
if "created_at" in data and isinstance(data["created_at"], str):
|
|
object.__setattr__(fingerprint, 'created_at', datetime.fromisoformat(data["created_at"]))
|
|
|
|
return fingerprint |