soothe-client-python 1.0.2__py3-none-any.whl → 1.0.4__py3-none-any.whl

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.
@@ -82,9 +82,21 @@ class DaemonSession:
82
82
  self.last_turn_cancellation_seen: bool = False
83
83
  self.last_turn_error_message: str | None = None
84
84
  # Last completed turn's seq floor (drop stale prior-turn frames).
85
+ # Scoped to the current peer seq namespace: reset on reconnect / loop
86
+ # change — daemon seq is per-process and restarts after daemon restart.
85
87
  self._last_turn_end_seq: int = 0
86
88
  self._expected_turn_id: str | None = None
87
89
 
90
+ def _reset_turn_seq_floor(self) -> None:
91
+ """Clear seq/turn filters when the peer seq namespace may have restarted.
92
+
93
+ Keep-TUI reconnect after a daemon restart (or subscribe to a different
94
+ loop) would otherwise drop all low-seq frames — including
95
+ ``status=running`` — leaving ``query_started=False`` and a silent TUI.
96
+ """
97
+ self._last_turn_end_seq = 0
98
+ self._expected_turn_id = None
99
+
88
100
  @property
89
101
  def client(self) -> WebSocketClient:
90
102
  """Subscribed stream WebSocket (loop events)."""
@@ -131,6 +143,7 @@ class DaemonSession:
131
143
  return await self._bootstrap_loop(resume_loop_id=resume_loop_id)
132
144
 
133
145
  async def _bootstrap_loop(self, *, resume_loop_id: str | None = None) -> dict[str, Any]:
146
+ prev_loop_id = self._loop_id
134
147
  status_event = await bootstrap_loop_session(
135
148
  self._client,
136
149
  resume_loop_id=resume_loop_id,
@@ -140,6 +153,9 @@ class DaemonSession:
140
153
  if status_event.get("type") == "error":
141
154
  raise RuntimeError(str(status_event.get("message", "daemon bootstrap failed")))
142
155
  self._loop_id = status_event.get("loop_id")
156
+ # New/changed loop has an independent seq counter on the daemon.
157
+ if prev_loop_id != self._loop_id:
158
+ self._reset_turn_seq_floor()
143
159
  return status_event
144
160
 
145
161
  async def new_loop(self) -> dict[str, Any]:
@@ -179,6 +195,10 @@ class DaemonSession:
179
195
  await self._client.close()
180
196
  await connect_websocket_with_retries(self._client)
181
197
 
198
+ # Peer seq is process-local; daemon restart restarts counters at 1 while
199
+ # this session may still hold a high floor from before the disconnect.
200
+ self._reset_turn_seq_floor()
201
+
182
202
  if resume_loop_id:
183
203
  reattach = getattr(self._client, "reattach_and_probe", None)
184
204
  if callable(reattach):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: soothe-client-python
3
- Version: 1.0.2
3
+ Version: 1.0.4
4
4
  Summary: WebSocket client + appkit for soothe-daemon (Python)
5
5
  Project-URL: Homepage, https://github.com/mirasoth/soothe-client-python
6
6
  Project-URL: Documentation, https://soothe.readthedocs.io
@@ -21,7 +21,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
21
  Requires-Python: <3.15,>=3.11
22
22
  Requires-Dist: pillow<12.0.0,>=10.0.0
23
23
  Requires-Dist: pydantic<3.0.0,>=2.0.0
24
- Requires-Dist: soothe-sdk<2.0.0,>=1.0.0
24
+ Requires-Dist: soothe-sdk<2.0.0,>=1.0.2
25
25
  Requires-Dist: websockets>=12.0
26
26
  Provides-Extra: dev
27
27
  Requires-Dist: mypy>=1.0.0; extra == 'dev'
@@ -15,7 +15,7 @@ soothe_client/appkit/attachments.py,sha256=hD2FsXeR8TqO3hzIYT49DUedsv9r2yFEuIYDB
15
15
  soothe_client/appkit/broadcaster.py,sha256=wcWQUOy7HjFgNaXDk1Ec71CGi7mZmb-zXZZbuOon9OY,3529
16
16
  soothe_client/appkit/chunk_filter.py,sha256=UoC4kbS_65UNEJIjbyufqxGBLwvamwvQ26BqZ_gkDTg,3134
17
17
  soothe_client/appkit/classifier.py,sha256=0meCKR9CnTDg9rfkFwv-2rz6T-vWGntcXVGybx8NOv0,18727
18
- soothe_client/appkit/daemon_session.py,sha256=nMcAsjwb3DB707u9VSkg-ZLXqxopka0Mqq-AOlhg5RE,32970
18
+ soothe_client/appkit/daemon_session.py,sha256=9f-39YQQ2Au420hMxs7Z6mhcwsQzeigm-IXJkLp3bbA,33964
19
19
  soothe_client/appkit/events.py,sha256=p7uZmSx_kYdiR7DQY84rvgyHE6RQ6Orbq2KT-WCNsiM,2290
20
20
  soothe_client/appkit/managed_client.py,sha256=QZhXA-zbx2v8IJpU_YFyUcwHRmNEziEGR6euPSvadfY,7183
21
21
  soothe_client/appkit/observability.py,sha256=9maW5oyEK0PZBjU7x8tHupoRBvAxApkHFQavRzkr7SM,650
@@ -26,7 +26,7 @@ soothe_client/appkit/thinking_step.py,sha256=dB1L1ERPkisLh2y3KIgd4f6EmN8GmF5B0h6
26
26
  soothe_client/appkit/turn.py,sha256=gtQyz3gGw8nkg8tfzpGZzNgRmJ48vJnj2Ll95W_BX4w,12479
27
27
  soothe_client/appkit/turn_boundary.py,sha256=9MM4Xbu-ctZ-04BYRdGABYdeWBoIZW71K0IiTVW7sgw,4054
28
28
  soothe_client/appkit/turn_runner.py,sha256=mvb3pquxbVh29048HQKltgm0EzwhzW0ducAKTQiHi6I,21691
29
- soothe_client_python-1.0.2.dist-info/METADATA,sha256=0CabV3XomWRELTruWq0OvyxTvZnhz2Ofe3IvkY4k0go,2993
30
- soothe_client_python-1.0.2.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
31
- soothe_client_python-1.0.2.dist-info/licenses/LICENSE,sha256=WbXjnHkSCPG_f4TfOdS_mGrbkQAYykAdfIqVDj9O-IY,1068
32
- soothe_client_python-1.0.2.dist-info/RECORD,,
29
+ soothe_client_python-1.0.4.dist-info/METADATA,sha256=U74gXP1D-nOGkNHiK1p0XoqdBW8V-NpVLucQwyLet3M,2993
30
+ soothe_client_python-1.0.4.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
31
+ soothe_client_python-1.0.4.dist-info/licenses/LICENSE,sha256=WbXjnHkSCPG_f4TfOdS_mGrbkQAYykAdfIqVDj9O-IY,1068
32
+ soothe_client_python-1.0.4.dist-info/RECORD,,