Coverage for src / harnessutils / types.py: 100%
17 statements
« prev ^ index » next coverage.py v7.13.2, created at 2026-02-01 13:12 -0600
« prev ^ index » next coverage.py v7.13.2, created at 2026-02-01 13:12 -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(self, conversation_id: str, message_id: str, data: dict[str, Any]) -> None:
76 """Save message metadata.
78 Args:
79 conversation_id: Conversation the message belongs to
80 message_id: Unique message identifier
81 data: Message data to save
82 """
83 ...
85 def load_message(self, conversation_id: str, message_id: str) -> dict[str, Any]:
86 """Load message metadata.
88 Args:
89 conversation_id: Conversation the message belongs to
90 message_id: Unique message identifier
92 Returns:
93 Message data
95 Raises:
96 FileNotFoundError: If message doesn't exist
97 """
98 ...
100 def list_messages(self, conversation_id: str) -> list[str]:
101 """List all message IDs for a conversation.
103 Args:
104 conversation_id: Conversation to list messages for
106 Returns:
107 List of message IDs in chronological order
108 """
109 ...
111 def save_part(self, message_id: str, part_id: str, data: dict[str, Any]) -> None:
112 """Save message part.
114 Args:
115 message_id: Message the part belongs to
116 part_id: Unique part identifier
117 data: Part data to save
118 """
119 ...
121 def load_part(self, message_id: str, part_id: str) -> dict[str, Any]:
122 """Load message part.
124 Args:
125 message_id: Message the part belongs to
126 part_id: Unique part identifier
128 Returns:
129 Part data
131 Raises:
132 FileNotFoundError: If part doesn't exist
133 """
134 ...
136 def list_parts(self, message_id: str) -> list[str]:
137 """List all part IDs for a message.
139 Args:
140 message_id: Message to list parts for
142 Returns:
143 List of part IDs in order
144 """
145 ...
147 def save_truncated_output(self, output_id: str, content: str) -> None:
148 """Save full output that was truncated.
150 Args:
151 output_id: Unique output identifier
152 content: Full output content
153 """
154 ...
156 def load_truncated_output(self, output_id: str) -> str:
157 """Load full truncated output.
159 Args:
160 output_id: Unique output identifier
162 Returns:
163 Full output content
165 Raises:
166 FileNotFoundError: If output doesn't exist
167 """
168 ...
170 def cleanup_old_outputs(self, retention_days: int) -> int:
171 """Clean up truncated outputs older than retention period.
173 Args:
174 retention_days: Number of days to retain outputs
176 Returns:
177 Number of outputs deleted
178 """
179 ...