Coverage for src / harness_utils / types.py: 100%
17 statements
« prev ^ index » next coverage.py v7.13.2, created at 2026-01-31 13:47 -0600
« prev ^ index » next coverage.py v7.13.2, created at 2026-01-31 13:47 -0600
1"""Protocol definitions for harness-utils.
3This module defines the interfaces that applications must implement
4to integrate with harness-utils.
5"""
7from typing import Any, Protocol, runtime_checkable
10@runtime_checkable
11class LLMClient(Protocol):
12 """Protocol for LLM client implementations.
14 Applications must provide an implementation of this protocol to enable
15 LLM-powered summarization (Tier 3 compaction).
17 This is a callback-based design where the application owns the LLM client
18 and the library requests LLM operations through this interface.
19 """
21 def invoke(
22 self,
23 messages: list[dict[str, Any]],
24 system: list[str] | None = None,
25 model: str | None = None,
26 ) -> dict[str, Any]:
27 """Invoke the LLM with the given messages.
29 Args:
30 messages: List of messages in model format (role, content)
31 system: Optional system prompt parts
32 model: Optional model identifier to use
34 Returns:
35 Dictionary containing:
36 - content: The LLM response text
37 - usage: Token usage information (input, output, cache, reasoning)
38 - model: The model that was used
39 """
40 ...
43@runtime_checkable
44class StorageBackend(Protocol):
45 """Protocol for storage backend implementations.
47 The library provides default implementations (filesystem, in-memory),
48 but applications can provide custom implementations for different
49 storage strategies (e.g., cloud storage, databases).
50 """
52 def save_conversation(self, conversation_id: str, data: dict[str, Any]) -> None:
53 """Save conversation metadata.
55 Args:
56 conversation_id: Unique conversation identifier
57 data: Conversation data to save
58 """
59 ...
61 def load_conversation(self, conversation_id: str) -> dict[str, Any]:
62 """Load conversation metadata.
64 Args:
65 conversation_id: Unique conversation identifier
67 Returns:
68 Conversation data
70 Raises:
71 FileNotFoundError: If conversation doesn't exist
72 """
73 ...
75 def save_message(
76 self,
77 conversation_id: str,
78 message_id: str,
79 data: dict[str, Any]
80 ) -> None:
81 """Save message metadata.
83 Args:
84 conversation_id: Conversation the message belongs to
85 message_id: Unique message identifier
86 data: Message data to save
87 """
88 ...
90 def load_message(
91 self,
92 conversation_id: str,
93 message_id: str
94 ) -> dict[str, Any]:
95 """Load message metadata.
97 Args:
98 conversation_id: Conversation the message belongs to
99 message_id: Unique message identifier
101 Returns:
102 Message data
104 Raises:
105 FileNotFoundError: If message doesn't exist
106 """
107 ...
109 def list_messages(self, conversation_id: str) -> list[str]:
110 """List all message IDs for a conversation.
112 Args:
113 conversation_id: Conversation to list messages for
115 Returns:
116 List of message IDs in chronological order
117 """
118 ...
120 def save_part(
121 self,
122 message_id: str,
123 part_id: str,
124 data: dict[str, Any]
125 ) -> None:
126 """Save message part.
128 Args:
129 message_id: Message the part belongs to
130 part_id: Unique part identifier
131 data: Part data to save
132 """
133 ...
135 def load_part(self, message_id: str, part_id: str) -> dict[str, Any]:
136 """Load message part.
138 Args:
139 message_id: Message the part belongs to
140 part_id: Unique part identifier
142 Returns:
143 Part data
145 Raises:
146 FileNotFoundError: If part doesn't exist
147 """
148 ...
150 def list_parts(self, message_id: str) -> list[str]:
151 """List all part IDs for a message.
153 Args:
154 message_id: Message to list parts for
156 Returns:
157 List of part IDs in order
158 """
159 ...
161 def save_truncated_output(self, output_id: str, content: str) -> None:
162 """Save full output that was truncated.
164 Args:
165 output_id: Unique output identifier
166 content: Full output content
167 """
168 ...
170 def load_truncated_output(self, output_id: str) -> str:
171 """Load full truncated output.
173 Args:
174 output_id: Unique output identifier
176 Returns:
177 Full output content
179 Raises:
180 FileNotFoundError: If output doesn't exist
181 """
182 ...
184 def cleanup_old_outputs(self, retention_days: int) -> int:
185 """Clean up truncated outputs older than retention period.
187 Args:
188 retention_days: Number of days to retain outputs
190 Returns:
191 Number of outputs deleted
192 """
193 ...