Coverage for src/dataknobs_bots/registry/models.py: 88%

1"""Registration model for bot registry."""

2

3 from __future__ import annotations

4

5 from dataclasses import dataclass, field

6 from datetime import datetime, timezone

7 from typing import Any

8

9

10@dataclass

11 class Registration:

12 """Bot registration with metadata.

13

14 Stores a bot configuration along with lifecycle metadata like

15 timestamps and status. Used by registry backends to persist

16 bot configurations.

17

18 Attributes:

19 bot_id: Unique bot identifier

20 config: Bot configuration dictionary (should be portable)

21 status: Registration status (active, inactive, error)

22 created_at: When the registration was created

23 updated_at: When the registration was last updated

24 last_accessed_at: When the bot was last accessed

25

26 Example:

27 ```python

28 reg = Registration(

29 bot_id="my-bot",

30 config={"bot": {"llm": {"$resource": "default", "type": "llm_providers"}}},

31 )

32 print(f"Bot {reg.bot_id} created at {reg.created_at}")

33

34 # Serialize for storage

35 data = reg.to_dict()

36

37 # Restore from storage

38 restored = Registration.from_dict(data)

39 ```

40 """

41

42 bot_id: str

43 config: dict[str, Any]

44 status: str = "active"

45 created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))

46 updated_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))

47 last_accessed_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))

48

49 def to_dict(self) -> dict[str, Any]:

50 """Convert to dictionary for serialization.

51

52 Returns:

53 Dictionary representation with ISO format timestamps

54 """

55 return {

56 "bot_id": self.bot_id,

57 "config": self.config,

58 "status": self.status,

59 "created_at": self.created_at.isoformat() if self.created_at else None,

60 "updated_at": self.updated_at.isoformat() if self.updated_at else None,

61 "last_accessed_at": (

62 self.last_accessed_at.isoformat() if self.last_accessed_at else None

63 ),

64 }

65

66 @classmethod

67 def from_dict(cls, data: dict[str, Any]) -> Registration:

68 """Create from dictionary.

69

70 Args:

71 data: Dictionary with registration data

72

73 Returns:

74 Registration instance

75 """

76 return cls(

77 bot_id=data["bot_id"],

78 config=data["config"],

79 status=data.get("status", "active"),

80 created_at=(

81 datetime.fromisoformat(data["created_at"])

82 if data.get("created_at")

83 else datetime.now(timezone.utc)

84 ),

85 updated_at=(

86 datetime.fromisoformat(data["updated_at"])

87 if data.get("updated_at")

88 else datetime.now(timezone.utc)

89 ),

90 last_accessed_at=(

91 datetime.fromisoformat(data["last_accessed_at"])

92 if data.get("last_accessed_at")

93 else datetime.now(timezone.utc)

94 ),

95 )

96

97 def __repr__(self) -> str:

98 """String representation."""

99 return (

100 f"Registration(bot_id={self.bot_id!r}, status={self.status!r}, "

101 f"created_at={self.created_at.isoformat() if self.created_at else None})"

102 )