Coverage for src / harnessutils / models / conversation.py: 100%
41 statements
« prev ^ index » next coverage.py v7.13.2, created at 2026-02-18 08:30 -0600
« prev ^ index » next coverage.py v7.13.2, created at 2026-02-18 08:30 -0600
1"""Conversation model."""
3from __future__ import annotations
5from dataclasses import dataclass, field
6from typing import TYPE_CHECKING, Any
8from harnessutils.models.velocity import ConversationVelocity
10if TYPE_CHECKING:
11 from harnessutils.quality import QualityHistory, QualitySnapshot
14@dataclass
15class Conversation:
16 """A conversation containing multiple messages.
18 Conversations track the overall context and metadata for a series
19 of messages between user and assistant.
20 """
22 id: str
23 project_id: str | None = None
24 created: int | None = None # Unix timestamp in milliseconds
25 updated: int | None = None # Unix timestamp in milliseconds
26 pending_summarization: bool = False
27 metadata: dict[str, Any] = field(default_factory=dict)
29 def get_velocity(self) -> ConversationVelocity | None:
30 """Get velocity tracker from metadata.
32 Returns:
33 ConversationVelocity instance or None if not tracked
34 """
35 velocity_data = self.metadata.get("velocity")
36 if velocity_data is None:
37 return None
39 return ConversationVelocity.from_dict(velocity_data)
41 def update_velocity(self, tokens_added: int) -> None:
42 """Update velocity tracker with new token delta.
44 Args:
45 tokens_added: Tokens added in this turn
46 """
47 velocity = self.get_velocity()
48 if velocity is None:
49 velocity = ConversationVelocity()
51 velocity.add_delta(tokens_added)
52 self.metadata["velocity"] = velocity.to_dict()
54 def get_quality_history(self) -> QualityHistory | None:
55 """Get quality history from metadata.
57 Returns:
58 QualityHistory instance or None if not tracked
59 """
60 from harnessutils.quality import QualityHistory
62 history_data = self.metadata.get("quality_history")
63 if history_data is None:
64 return None
66 return QualityHistory.from_dict(history_data)
68 def update_quality_history(self, snapshot: QualitySnapshot) -> None:
69 """Add quality snapshot to history.
71 Args:
72 snapshot: Quality snapshot to add
73 """
74 from harnessutils.quality import QualityHistory
76 history = self.get_quality_history()
77 if history is None:
78 history = QualityHistory()
80 history.add_snapshot(snapshot)
81 self.metadata["quality_history"] = history.to_dict()
83 def to_dict(self) -> dict[str, Any]:
84 """Convert conversation to dictionary for storage.
86 Returns:
87 Dictionary representation
88 """
89 return {
90 "id": self.id,
91 "project_id": self.project_id,
92 "created": self.created,
93 "updated": self.updated,
94 "pending_summarization": self.pending_summarization,
95 "metadata": self.metadata,
96 }
98 @classmethod
99 def from_dict(cls, data: dict[str, Any]) -> Conversation:
100 """Create conversation from dictionary.
102 Args:
103 data: Dictionary representation
105 Returns:
106 Conversation instance
107 """
108 return cls(
109 id=data["id"],
110 project_id=data.get("project_id"),
111 created=data.get("created"),
112 updated=data.get("updated"),
113 pending_summarization=data.get("pending_summarization", False),
114 metadata=data.get("metadata", {}),
115 )