soothe-client-python 0.9.8__tar.gz → 0.9.9__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.
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/PKG-INFO +1 -1
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/daemon_session.py +20 -4
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/turn_boundary.py +14 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/.gitignore +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/LICENSE +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/README.md +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/pyproject.toml +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/__init__.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/__init__.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/attachments.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/broadcaster.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/chunk_filter.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/classifier.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/events.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/managed_client.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/observability.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/pool.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/query_gate.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/session_store.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/thinking_step.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/turn.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/turn_runner.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/errors.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/helpers.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/intent_hints.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/protocol_params.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/py.typed +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/schemas.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/session.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/stream_terminal.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/websocket.py +0 -0
- {soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/ws_command_client.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: soothe-client-python
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.9
|
|
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
|
{soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/daemon_session.py
RENAMED
|
@@ -23,7 +23,7 @@ from soothe_client.stream_terminal import (
|
|
|
23
23
|
is_turn_end_custom_data,
|
|
24
24
|
is_turn_progress_chunk,
|
|
25
25
|
)
|
|
26
|
-
from soothe_client.turn_boundary import frame_seq, frame_turn_id
|
|
26
|
+
from soothe_client.turn_boundary import frame_seq, frame_turn_id, parse_turn_generation
|
|
27
27
|
from soothe_client.websocket import WebSocketClient
|
|
28
28
|
|
|
29
29
|
logger = logging.getLogger(__name__)
|
|
@@ -392,13 +392,19 @@ class DaemonSession:
|
|
|
392
392
|
if ev_seq is not None and last_end_seq > 0 and ev_seq <= last_end_seq:
|
|
393
393
|
continue
|
|
394
394
|
|
|
395
|
-
#
|
|
395
|
+
# Drop mismatched turn_id once bound — except status=running,
|
|
396
|
+
# which may rebind to a newer generation (pre-admit early
|
|
397
|
+
# running can briefly carry a stale or empty turn_id).
|
|
396
398
|
ev_turn_id = frame_turn_id(event)
|
|
399
|
+
is_running_status = (
|
|
400
|
+
event_type == "status" and str(event.get("state") or "") == "running"
|
|
401
|
+
)
|
|
397
402
|
if (
|
|
398
403
|
expected_turn_id
|
|
399
404
|
and ev_turn_id
|
|
400
405
|
and ev_turn_id != expected_turn_id
|
|
401
406
|
and event_type in {"event", "status"}
|
|
407
|
+
and not is_running_status
|
|
402
408
|
):
|
|
403
409
|
logger.debug(
|
|
404
410
|
"Ignoring mismatched turn_id frame type=%s got=%s expected=%s",
|
|
@@ -426,8 +432,18 @@ class DaemonSession:
|
|
|
426
432
|
progress_seen = True
|
|
427
433
|
status_turn = frame_turn_id(event)
|
|
428
434
|
if status_turn:
|
|
429
|
-
|
|
430
|
-
|
|
435
|
+
new_gen = parse_turn_generation(status_turn)
|
|
436
|
+
old_gen = parse_turn_generation(expected_turn_id)
|
|
437
|
+
if expected_turn_id is None or (
|
|
438
|
+
new_gen is not None and (old_gen is None or new_gen >= old_gen)
|
|
439
|
+
):
|
|
440
|
+
if expected_turn_id and status_turn != expected_turn_id:
|
|
441
|
+
# Successor turn admitted while this reader
|
|
442
|
+
# still held a stale/early binding.
|
|
443
|
+
stream_payload_seen = False
|
|
444
|
+
turn_progress_seen = False
|
|
445
|
+
expected_turn_id = status_turn
|
|
446
|
+
self._expected_turn_id = status_turn
|
|
431
447
|
elif query_started and state == "stopped":
|
|
432
448
|
self.last_turn_end_state = state
|
|
433
449
|
if ev_seq is not None:
|
{soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/turn_boundary.py
RENAMED
|
@@ -18,6 +18,19 @@ def format_turn_id(loop_id: str, generation: int) -> str:
|
|
|
18
18
|
return f"{lid}:{gen}"
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
def parse_turn_generation(turn_id: str | None) -> int | None:
|
|
22
|
+
"""Extract generation int from ``turn_id``, or None if malformed."""
|
|
23
|
+
raw = str(turn_id or "").strip()
|
|
24
|
+
if not raw or ":" not in raw:
|
|
25
|
+
return None
|
|
26
|
+
suffix = raw.rsplit(":", 1)[-1]
|
|
27
|
+
try:
|
|
28
|
+
gen = int(suffix)
|
|
29
|
+
except ValueError:
|
|
30
|
+
return None
|
|
31
|
+
return gen if gen > 0 else None
|
|
32
|
+
|
|
33
|
+
|
|
21
34
|
def frame_turn_id(frame: dict[str, Any] | None) -> str | None:
|
|
22
35
|
"""Return ``turn_id`` from a status/event frame or nested custom data."""
|
|
23
36
|
if not isinstance(frame, dict):
|
|
@@ -51,4 +64,5 @@ __all__ = [
|
|
|
51
64
|
"format_turn_id",
|
|
52
65
|
"frame_seq",
|
|
53
66
|
"frame_turn_id",
|
|
67
|
+
"parse_turn_generation",
|
|
54
68
|
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/__init__.py
RENAMED
|
File without changes
|
{soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/attachments.py
RENAMED
|
File without changes
|
{soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/broadcaster.py
RENAMED
|
File without changes
|
{soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/chunk_filter.py
RENAMED
|
File without changes
|
{soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/classifier.py
RENAMED
|
File without changes
|
{soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/events.py
RENAMED
|
File without changes
|
{soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/managed_client.py
RENAMED
|
File without changes
|
{soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/observability.py
RENAMED
|
File without changes
|
|
File without changes
|
{soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/query_gate.py
RENAMED
|
File without changes
|
{soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/session_store.py
RENAMED
|
File without changes
|
{soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/thinking_step.py
RENAMED
|
File without changes
|
|
File without changes
|
{soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/appkit/turn_runner.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/protocol_params.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/stream_terminal.py
RENAMED
|
File without changes
|
|
File without changes
|
{soothe_client_python-0.9.8 → soothe_client_python-0.9.9}/src/soothe_client/ws_command_client.py
RENAMED
|
File without changes
|