hostel-protocol-python 0.4.0__tar.gz → 0.4.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (20) hide show
  1. {hostel_protocol_python-0.4.0 → hostel_protocol_python-0.4.2}/PKG-INFO +1 -1
  2. {hostel_protocol_python-0.4.0 → hostel_protocol_python-0.4.2}/pyproject.toml +1 -1
  3. {hostel_protocol_python-0.4.0 → hostel_protocol_python-0.4.2}/src/hostel/protocol/__init__.py +17 -0
  4. {hostel_protocol_python-0.4.0 → hostel_protocol_python-0.4.2}/src/hostel/transport/__init__.py +2 -1
  5. {hostel_protocol_python-0.4.0 → hostel_protocol_python-0.4.2}/src/hostel/transport/transport.py +8 -0
  6. {hostel_protocol_python-0.4.0 → hostel_protocol_python-0.4.2}/src/hostel/transport/zeromq.py +17 -2
  7. {hostel_protocol_python-0.4.0 → hostel_protocol_python-0.4.2}/.github/workflows/ci.yml +0 -0
  8. {hostel_protocol_python-0.4.0 → hostel_protocol_python-0.4.2}/.github/workflows/publish.yml +0 -0
  9. {hostel_protocol_python-0.4.0 → hostel_protocol_python-0.4.2}/.gitignore +0 -0
  10. {hostel_protocol_python-0.4.0 → hostel_protocol_python-0.4.2}/Makefile +0 -0
  11. {hostel_protocol_python-0.4.0 → hostel_protocol_python-0.4.2}/src/hostel/client/__init__.py +0 -0
  12. {hostel_protocol_python-0.4.0 → hostel_protocol_python-0.4.2}/src/hostel/client/client.py +0 -0
  13. {hostel_protocol_python-0.4.0 → hostel_protocol_python-0.4.2}/src/hostel/protocol/converter.py +0 -0
  14. {hostel_protocol_python-0.4.0 → hostel_protocol_python-0.4.2}/src/hostel/protocol/models.py +0 -0
  15. {hostel_protocol_python-0.4.0 → hostel_protocol_python-0.4.2}/src/hostel/py.typed +0 -0
  16. {hostel_protocol_python-0.4.0 → hostel_protocol_python-0.4.2}/tests/__init__.py +0 -0
  17. {hostel_protocol_python-0.4.0 → hostel_protocol_python-0.4.2}/tests/test_client.py +0 -0
  18. {hostel_protocol_python-0.4.0 → hostel_protocol_python-0.4.2}/tests/test_converter.py +0 -0
  19. {hostel_protocol_python-0.4.0 → hostel_protocol_python-0.4.2}/tests/test_models.py +0 -0
  20. {hostel_protocol_python-0.4.0 → hostel_protocol_python-0.4.2}/tests/test_transport.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hostel-protocol-python
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: Pydantic models, transport and client for the Hostel protocol
5
5
  Requires-Python: >=3.12
6
6
  Requires-Dist: hostel-protocol>=0.4.0
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "hostel-protocol-python"
7
- version = "0.4.0"
7
+ version = "0.4.2"
8
8
  description = "Pydantic models, transport and client for the Hostel protocol"
9
9
  requires-python = ">=3.12"
10
10
  dependencies = [
@@ -10,16 +10,22 @@ from hostel.protocol.models import (
10
10
  ChatMessage,
11
11
  ChatRequest,
12
12
  ChatResponse,
13
+ ConversationMessage,
14
+ ConversationSummary,
13
15
  CreateComponentRequest,
14
16
  CreateComponentResponse,
15
17
  CreateTaskRequest,
16
18
  CreateTaskResponse,
17
19
  DeleteComponentRequest,
18
20
  DeleteComponentResponse,
21
+ DeleteConversationRequest,
22
+ DeleteConversationResponse,
19
23
  DeleteTaskRequest,
20
24
  DeleteTaskResponse,
21
25
  GetComponentRequest,
22
26
  GetComponentResponse,
27
+ GetConversationRequest,
28
+ GetConversationResponse,
23
29
  GetTaskRequest,
24
30
  GetTaskResponse,
25
31
  HostelMessage,
@@ -28,6 +34,8 @@ from hostel.protocol.models import (
28
34
  ListAgentsResponse,
29
35
  ListComponentsRequest,
30
36
  ListComponentsResponse,
37
+ ListConversationsRequest,
38
+ ListConversationsResponse,
31
39
  ListTasksRequest,
32
40
  ListTasksResponse,
33
41
  TaskData,
@@ -49,6 +57,15 @@ __all__ = [
49
57
  "ChatMessage",
50
58
  "ChatRequest",
51
59
  "ChatResponse",
60
+ # Conversation
61
+ "ConversationSummary",
62
+ "ConversationMessage",
63
+ "ListConversationsRequest",
64
+ "ListConversationsResponse",
65
+ "GetConversationRequest",
66
+ "GetConversationResponse",
67
+ "DeleteConversationRequest",
68
+ "DeleteConversationResponse",
52
69
  # Agent
53
70
  "ListAgentsRequest",
54
71
  "ListAgentsResponse",
@@ -1,8 +1,9 @@
1
1
  """hostel.transport — Transport abstractions and implementations."""
2
2
 
3
- from hostel.transport.transport import ClientId, ServerTransport, Transport
3
+ from hostel.transport.transport import ClientDisconnectedError, ClientId, ServerTransport, Transport
4
4
 
5
5
  __all__ = [
6
+ "ClientDisconnectedError",
6
7
  "ClientId",
7
8
  "Transport",
8
9
  "ServerTransport",
@@ -7,6 +7,14 @@ from hostel.protocol.models import HostelMessage
7
7
  ClientId = bytes
8
8
 
9
9
 
10
+ class ClientDisconnectedError(Exception):
11
+ """Raised when a send targets a peer that is no longer connected."""
12
+
13
+ def __init__(self, client_id: ClientId) -> None:
14
+ self.client_id = client_id
15
+ super().__init__(f"Client {client_id!r} is not connected")
16
+
17
+
10
18
  class Transport(ABC):
11
19
 
12
20
  @abstractmethod
@@ -1,5 +1,6 @@
1
1
  """ZeroMQ transport implementations for Hostel."""
2
2
 
3
+ import asyncio
3
4
  import logging
4
5
  import uuid
5
6
 
@@ -9,7 +10,7 @@ from hostel.protocol.v1 import message_pb2
9
10
 
10
11
  from hostel.protocol.converter import proto_to_pydantic, pydantic_to_proto
11
12
  from hostel.protocol.models import HostelMessage
12
- from hostel.transport.transport import ClientId, ServerTransport, Transport
13
+ from hostel.transport.transport import ClientDisconnectedError, ClientId, ServerTransport, Transport
13
14
 
14
15
  logger = logging.getLogger(__name__)
15
16
 
@@ -76,9 +77,11 @@ class ZmqRouterTransport(ServerTransport):
76
77
  endpoint: str,
77
78
  *,
78
79
  linger_ms: int = 0,
80
+ send_timeout: float = 5.0,
79
81
  ):
80
82
  self.endpoint = endpoint
81
83
  self.linger_ms = linger_ms
84
+ self.send_timeout = send_timeout
82
85
 
83
86
  self._ctx: zmq.asyncio.Context | None = None
84
87
  self._socket: zmq.asyncio.Socket | None = None
@@ -90,6 +93,7 @@ class ZmqRouterTransport(ServerTransport):
90
93
  self._ctx = zmq.asyncio.Context.instance()
91
94
  self._socket = self._ctx.socket(zmq.ROUTER)
92
95
  self._socket.setsockopt(zmq.LINGER, self.linger_ms)
96
+ self._socket.setsockopt(zmq.ROUTER_MANDATORY, 1)
93
97
  self._socket.bind(self.endpoint)
94
98
 
95
99
  async def receive(self) -> tuple[ClientId, HostelMessage]:
@@ -111,7 +115,18 @@ class ZmqRouterTransport(ServerTransport):
111
115
 
112
116
  proto = pydantic_to_proto(message)
113
117
  raw = proto.SerializeToString()
114
- await self._socket.send_multipart([client_id, b"", raw])
118
+ try:
119
+ await asyncio.wait_for(
120
+ self._socket.send_multipart([client_id, b"", raw]),
121
+ timeout=self.send_timeout,
122
+ )
123
+ except asyncio.TimeoutError:
124
+ logger.warning("send to client %r timed out after %ss", client_id, self.send_timeout)
125
+ raise
126
+ except zmq.ZMQError as exc:
127
+ if exc.errno == zmq.EHOSTUNREACH:
128
+ raise ClientDisconnectedError(client_id) from exc
129
+ raise
115
130
 
116
131
  async def close(self) -> None:
117
132
  if self._socket is not None: