soothe-client-python 1.0.4__tar.gz → 1.0.7__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-1.0.4 → soothe_client_python-1.0.7}/PKG-INFO +1 -1
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/__init__.py +2 -2
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/__init__.py +11 -4
- soothe_client_python-1.0.7/src/soothe_client/appkit/card_projection.py +10 -0
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/daemon_session.py +47 -59
- soothe_client_python-1.0.4/src/soothe_client/appkit/session_store.py → soothe_client_python-1.0.7/src/soothe_client/appkit/loop_session_store.py +4 -4
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/pool.py +3 -3
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/turn_runner.py +2 -2
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/helpers.py +4 -4
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/intent_hints.py +0 -2
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/protocol_params.py +6 -5
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/stream_terminal.py +11 -3
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/websocket.py +14 -8
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/.gitignore +0 -0
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/LICENSE +0 -0
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/README.md +0 -0
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/pyproject.toml +0 -0
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/attachments.py +0 -0
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/broadcaster.py +0 -0
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/chunk_filter.py +0 -0
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/classifier.py +0 -0
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/events.py +0 -0
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/managed_client.py +0 -0
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/observability.py +0 -0
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/query_gate.py +0 -0
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/thinking_step.py +0 -0
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/turn.py +0 -0
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/turn_boundary.py +0 -0
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/command_client.py +0 -0
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/errors.py +0 -0
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/py.typed +0 -0
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/schemas.py +0 -0
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/session.py +0 -0
- {soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/turn_boundary.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: soothe-client-python
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.7
|
|
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
|
|
@@ -33,7 +33,7 @@ from soothe_client.helpers import (
|
|
|
33
33
|
check_daemon_status,
|
|
34
34
|
connected_websocket,
|
|
35
35
|
fetch_config_section,
|
|
36
|
-
|
|
36
|
+
fetch_execution_state,
|
|
37
37
|
fetch_loop_history,
|
|
38
38
|
fetch_loop_messages,
|
|
39
39
|
fetch_skills_catalog,
|
|
@@ -91,8 +91,8 @@ __all__ = [
|
|
|
91
91
|
"request_daemon_shutdown",
|
|
92
92
|
"fetch_skills_catalog",
|
|
93
93
|
"fetch_config_section",
|
|
94
|
+
"fetch_execution_state",
|
|
94
95
|
"fetch_loop_history",
|
|
95
|
-
"fetch_loop_cards",
|
|
96
96
|
"fetch_loop_messages",
|
|
97
97
|
# Intent hints
|
|
98
98
|
"TEXT_COMPLETION",
|
{soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/__init__.py
RENAMED
|
@@ -7,7 +7,7 @@ Primary building blocks for agent UIs and backends:
|
|
|
7
7
|
- ``QueryGate`` — one-in-flight query per session
|
|
8
8
|
- ``EventClassifier`` — stream → deliverable mapping
|
|
9
9
|
- ``SSEBroadcaster`` — drop-on-full fan-out to subscribers
|
|
10
|
-
- ``
|
|
10
|
+
- ``LoopSessionStore`` — persistence seam (Protocol)
|
|
11
11
|
|
|
12
12
|
Advanced stream/pipeline plumbing lives in submodules
|
|
13
13
|
(``events``, ``chunk_filter``, ``turn``, ``managed_client``).
|
|
@@ -21,6 +21,7 @@ from soothe_client.appkit.attachments import (
|
|
|
21
21
|
compact_image_attachment,
|
|
22
22
|
)
|
|
23
23
|
from soothe_client.appkit.broadcaster import SSEBroadcaster, SSEEvent
|
|
24
|
+
from soothe_client.appkit.card_projection import CardProjection, parse_card_custom_payload
|
|
24
25
|
from soothe_client.appkit.classifier import (
|
|
25
26
|
EVENT_FINAL_REPORT,
|
|
26
27
|
ChatEventResult,
|
|
@@ -29,6 +30,11 @@ from soothe_client.appkit.classifier import (
|
|
|
29
30
|
EventClassifier,
|
|
30
31
|
)
|
|
31
32
|
from soothe_client.appkit.daemon_session import DaemonSession
|
|
33
|
+
from soothe_client.appkit.loop_session_store import (
|
|
34
|
+
LoopSessionEntry,
|
|
35
|
+
LoopSessionStore,
|
|
36
|
+
SessionMessage,
|
|
37
|
+
)
|
|
32
38
|
from soothe_client.appkit.pool import (
|
|
33
39
|
ConnectionPool,
|
|
34
40
|
ErrPoolExhausted,
|
|
@@ -37,7 +43,6 @@ from soothe_client.appkit.pool import (
|
|
|
37
43
|
default_pool_config,
|
|
38
44
|
)
|
|
39
45
|
from soothe_client.appkit.query_gate import ErrQueryBusy, QueryGate
|
|
40
|
-
from soothe_client.appkit.session_store import SessionEntry, SessionMessage, SessionStore
|
|
41
46
|
from soothe_client.appkit.thinking_step import (
|
|
42
47
|
DEFAULT_THINKING_STEP_EVENTS,
|
|
43
48
|
extract_thinking_step,
|
|
@@ -72,6 +77,7 @@ __all__ = [
|
|
|
72
77
|
"STREAM_CLOSE_FAIL",
|
|
73
78
|
"STREAM_CLOSE_SOFT_COMPLETE",
|
|
74
79
|
"Attachment",
|
|
80
|
+
"CardProjection",
|
|
75
81
|
"ChatEventResult",
|
|
76
82
|
"ChatEventTerminal",
|
|
77
83
|
"ClassifierConfig",
|
|
@@ -85,6 +91,8 @@ __all__ = [
|
|
|
85
91
|
"ErrQueryTimeout",
|
|
86
92
|
"EventClassifier",
|
|
87
93
|
"InputOpts",
|
|
94
|
+
"LoopSessionEntry",
|
|
95
|
+
"LoopSessionStore",
|
|
88
96
|
"OnComplete",
|
|
89
97
|
"OnError",
|
|
90
98
|
"PoolConfig",
|
|
@@ -92,9 +100,7 @@ __all__ = [
|
|
|
92
100
|
"QueryGate",
|
|
93
101
|
"SSEBroadcaster",
|
|
94
102
|
"SSEEvent",
|
|
95
|
-
"SessionEntry",
|
|
96
103
|
"SessionMessage",
|
|
97
|
-
"SessionStore",
|
|
98
104
|
"StreamClosePolicy",
|
|
99
105
|
"TURN_END_IDLE",
|
|
100
106
|
"TURN_END_STOPPED",
|
|
@@ -111,4 +117,5 @@ __all__ = [
|
|
|
111
117
|
"extract_thinking_step",
|
|
112
118
|
"idle_timeout_for_turn",
|
|
113
119
|
"input_message_for_loop",
|
|
120
|
+
"parse_card_custom_payload",
|
|
114
121
|
]
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""In-memory apply helpers for daemon ``soothe.card.*`` frames."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from soothe_sdk.display.card_wire import CardProjection, parse_card_custom_payload
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"CardProjection",
|
|
9
|
+
"parse_card_custom_payload",
|
|
10
|
+
]
|
{soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/daemon_session.py
RENAMED
|
@@ -431,7 +431,7 @@ class DaemonSession:
|
|
|
431
431
|
):
|
|
432
432
|
continue
|
|
433
433
|
|
|
434
|
-
# IG-
|
|
434
|
+
# IG-616 phase 5: drop frames at or before prior turn end seq.
|
|
435
435
|
ev_seq = frame_seq(event)
|
|
436
436
|
if ev_seq is not None and last_end_seq > 0 and ev_seq <= last_end_seq:
|
|
437
437
|
continue
|
|
@@ -526,7 +526,7 @@ class DaemonSession:
|
|
|
526
526
|
self.turn_event_stats.filtered_early += 1
|
|
527
527
|
continue
|
|
528
528
|
|
|
529
|
-
# Prefer turn_id match when present; else IG-
|
|
529
|
+
# Prefer turn_id match when present; else IG-615 progress gate.
|
|
530
530
|
if mode == "custom" and is_turn_end_custom_data(data):
|
|
531
531
|
data_turn = (
|
|
532
532
|
frame_turn_id(data if isinstance(data, dict) else None) or ev_turn_id
|
|
@@ -623,40 +623,6 @@ class DaemonSession:
|
|
|
623
623
|
await self._rpc_client.wait_for_connection_ack(ack_timeout_s=_RPC_HANDSHAKE_TIMEOUT_S)
|
|
624
624
|
self._rpc_connected = True
|
|
625
625
|
|
|
626
|
-
async def fetch_loop_cards(self, loop_id: str) -> SimpleNamespace:
|
|
627
|
-
"""Fetch bound display-card snapshot for a loop."""
|
|
628
|
-
lid = str(loop_id or "").strip()
|
|
629
|
-
if not lid:
|
|
630
|
-
return SimpleNamespace(cards=[], seq=0, success=False)
|
|
631
|
-
|
|
632
|
-
async with self._rpc_lock:
|
|
633
|
-
await self._ensure_rpc_connected()
|
|
634
|
-
try:
|
|
635
|
-
resp = await self._rpc_client.request(
|
|
636
|
-
"loop_cards_fetch",
|
|
637
|
-
{"loop_id": lid},
|
|
638
|
-
timeout=30.0,
|
|
639
|
-
)
|
|
640
|
-
except Exception:
|
|
641
|
-
logger.warning("loop_cards_fetch failed for loop %s", lid[:16], exc_info=True)
|
|
642
|
-
return SimpleNamespace(cards=[], seq=0, success=False)
|
|
643
|
-
|
|
644
|
-
raw_cards = resp.get("cards")
|
|
645
|
-
cards = list(raw_cards) if isinstance(raw_cards, list) else []
|
|
646
|
-
seq = int(resp.get("seq") or 0)
|
|
647
|
-
context_tokens_raw = resp.get("context_tokens")
|
|
648
|
-
context_tokens = (
|
|
649
|
-
context_tokens_raw
|
|
650
|
-
if isinstance(context_tokens_raw, int) and context_tokens_raw >= 0
|
|
651
|
-
else 0
|
|
652
|
-
)
|
|
653
|
-
return SimpleNamespace(
|
|
654
|
-
cards=cards,
|
|
655
|
-
seq=seq,
|
|
656
|
-
context_tokens=context_tokens,
|
|
657
|
-
success=True,
|
|
658
|
-
)
|
|
659
|
-
|
|
660
626
|
async def fetch_loop_history(self, loop_id: str) -> SimpleNamespace:
|
|
661
627
|
"""Fetch goal display snapshots plus live card tail."""
|
|
662
628
|
lid = str(loop_id or "").strip()
|
|
@@ -731,34 +697,56 @@ class DaemonSession:
|
|
|
731
697
|
values: dict[str, Any] = dict(raw) if isinstance(raw, dict) else {}
|
|
732
698
|
return SimpleNamespace(values=values)
|
|
733
699
|
|
|
734
|
-
async def
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
"""Merge partial state into the loop on the daemon host."""
|
|
700
|
+
async def fetch_execution_state(self, loop_id: str) -> SimpleNamespace:
|
|
701
|
+
"""Fetch execution-progress snapshot (plan, step_index, iteration, status).
|
|
702
|
+
|
|
703
|
+
Returns a namespace with ``plan``, ``step_index``, ``iteration``,
|
|
704
|
+
``status`` for the loop's bound checkpoint thread. On RPC failure the
|
|
705
|
+
fields degrade gracefully (``step_index=0``, ``iteration=0``,
|
|
706
|
+
``status=None``, ``plan=None``) so a resume gate can still proceed.
|
|
707
|
+
"""
|
|
743
708
|
lid = str(loop_id or "").strip()
|
|
709
|
+
empty = SimpleNamespace(
|
|
710
|
+
plan=None,
|
|
711
|
+
step_index=0,
|
|
712
|
+
iteration=0,
|
|
713
|
+
status=None,
|
|
714
|
+
loop_id=lid or None,
|
|
715
|
+
success=False,
|
|
716
|
+
)
|
|
744
717
|
if not lid:
|
|
745
|
-
return
|
|
718
|
+
return empty
|
|
746
719
|
|
|
747
720
|
async with self._rpc_lock:
|
|
748
721
|
await self._ensure_rpc_connected()
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
722
|
+
try:
|
|
723
|
+
resp = await self._rpc_client.request(
|
|
724
|
+
"loop_execution_state_fetch",
|
|
725
|
+
{"loop_id": lid},
|
|
726
|
+
timeout=30.0,
|
|
727
|
+
)
|
|
728
|
+
except Exception:
|
|
729
|
+
logger.warning(
|
|
730
|
+
"loop_execution_state_fetch failed for loop %s", lid[:16], exc_info=True
|
|
731
|
+
)
|
|
732
|
+
return empty
|
|
733
|
+
|
|
734
|
+
plan = resp.get("plan")
|
|
735
|
+
step_index_raw = resp.get("step_index")
|
|
736
|
+
step_index = step_index_raw if isinstance(step_index_raw, int) else 0
|
|
737
|
+
iteration_raw = resp.get("iteration")
|
|
738
|
+
iteration = iteration_raw if isinstance(iteration_raw, int) else 0
|
|
739
|
+
status_raw = resp.get("status")
|
|
740
|
+
status = status_raw if isinstance(status_raw, str) else None
|
|
741
|
+
success = bool(resp.get("success", True))
|
|
742
|
+
return SimpleNamespace(
|
|
743
|
+
plan=plan,
|
|
744
|
+
step_index=step_index,
|
|
745
|
+
iteration=iteration,
|
|
746
|
+
status=status,
|
|
747
|
+
loop_id=resp.get("loop_id", lid),
|
|
748
|
+
success=success,
|
|
749
|
+
)
|
|
762
750
|
|
|
763
751
|
async def fetch_conversation_log(
|
|
764
752
|
self,
|
|
@@ -5,7 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
from typing import Any, Protocol, runtime_checkable
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
class
|
|
8
|
+
class LoopSessionEntry:
|
|
9
9
|
"""Persisted mapping between an application session id and a daemon loop id."""
|
|
10
10
|
|
|
11
11
|
__slots__ = (
|
|
@@ -63,10 +63,10 @@ class SessionMessage:
|
|
|
63
63
|
|
|
64
64
|
|
|
65
65
|
@runtime_checkable
|
|
66
|
-
class
|
|
66
|
+
class LoopSessionStore(Protocol):
|
|
67
67
|
"""Persistence seam between appkit and the application's storage backend."""
|
|
68
68
|
|
|
69
|
-
async def get_session(self, session_id: str) ->
|
|
69
|
+
async def get_session(self, session_id: str) -> LoopSessionEntry | None:
|
|
70
70
|
"""Return the persisted entry for ``session_id``, or None."""
|
|
71
71
|
...
|
|
72
72
|
|
|
@@ -97,4 +97,4 @@ class SessionStore(Protocol):
|
|
|
97
97
|
...
|
|
98
98
|
|
|
99
99
|
|
|
100
|
-
__all__ = ["
|
|
100
|
+
__all__ = ["LoopSessionEntry", "SessionMessage", "LoopSessionStore"]
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Manages a pool of daemon connections, one active per session. Reuses an
|
|
4
4
|
active connection when still live, otherwise bootstraps a fresh loop or
|
|
5
5
|
reattaches an existing one. Persistence of session↔loop mappings is
|
|
6
|
-
abstracted behind ``
|
|
6
|
+
abstracted behind ``LoopSessionStore``.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
from __future__ import annotations
|
|
@@ -15,6 +15,7 @@ from collections.abc import AsyncIterator
|
|
|
15
15
|
from dataclasses import dataclass
|
|
16
16
|
from typing import Any
|
|
17
17
|
|
|
18
|
+
from soothe_client.appkit.loop_session_store import LoopSessionStore
|
|
18
19
|
from soothe_client.appkit.managed_client import (
|
|
19
20
|
BootstrapFunc,
|
|
20
21
|
ClientFactory,
|
|
@@ -22,7 +23,6 @@ from soothe_client.appkit.managed_client import (
|
|
|
22
23
|
default_bootstrap_func,
|
|
23
24
|
default_client_factory,
|
|
24
25
|
)
|
|
25
|
-
from soothe_client.appkit.session_store import SessionStore
|
|
26
26
|
from soothe_client.errors import StaleLoopError
|
|
27
27
|
|
|
28
28
|
|
|
@@ -96,7 +96,7 @@ class ConnectionPool:
|
|
|
96
96
|
def __init__(
|
|
97
97
|
self,
|
|
98
98
|
url: str,
|
|
99
|
-
store:
|
|
99
|
+
store: LoopSessionStore,
|
|
100
100
|
cfg: PoolConfig | None = None,
|
|
101
101
|
factory: ClientFactory | None = None,
|
|
102
102
|
) -> None:
|
{soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/turn_runner.py
RENAMED
|
@@ -21,9 +21,9 @@ from typing import Any
|
|
|
21
21
|
from soothe_client.appkit.attachments import CompactImageOptions, compact_attachments
|
|
22
22
|
from soothe_client.appkit.broadcaster import SSEBroadcaster, SSEEvent
|
|
23
23
|
from soothe_client.appkit.classifier import ChatEventTerminal, EventClassifier
|
|
24
|
+
from soothe_client.appkit.loop_session_store import LoopSessionStore, SessionMessage
|
|
24
25
|
from soothe_client.appkit.pool import ConnectionPool, PooledConn
|
|
25
26
|
from soothe_client.appkit.query_gate import QueryGate
|
|
26
|
-
from soothe_client.appkit.session_store import SessionMessage, SessionStore
|
|
27
27
|
from soothe_client.appkit.turn_boundary import TurnBoundary, is_daemon_turn_end_event
|
|
28
28
|
from soothe_client.intent_hints import validate_loop_input_intent_hint
|
|
29
29
|
|
|
@@ -135,7 +135,7 @@ class TurnRunner:
|
|
|
135
135
|
pool: ConnectionPool,
|
|
136
136
|
gate: QueryGate,
|
|
137
137
|
classifier: EventClassifier,
|
|
138
|
-
store:
|
|
138
|
+
store: LoopSessionStore,
|
|
139
139
|
broadcaster: SSEBroadcaster | None,
|
|
140
140
|
cfg: TurnConfig | None = None,
|
|
141
141
|
) -> None:
|
|
@@ -428,18 +428,18 @@ async def fetch_loop_history(
|
|
|
428
428
|
return await client.loop_history_fetch(lid, timeout=timeout)
|
|
429
429
|
|
|
430
430
|
|
|
431
|
-
async def
|
|
431
|
+
async def fetch_execution_state(
|
|
432
432
|
client: WebSocketClient,
|
|
433
433
|
loop_id: str,
|
|
434
434
|
*,
|
|
435
435
|
timeout: float = 30.0,
|
|
436
436
|
) -> dict[str, Any]:
|
|
437
|
-
"""Fetch
|
|
437
|
+
"""Fetch execution-progress snapshot (plan, step_index, iteration, status)."""
|
|
438
438
|
lid = str(loop_id or "").strip()
|
|
439
439
|
if not lid:
|
|
440
440
|
raise ValueError("loop_id is required")
|
|
441
441
|
await _ensure_handshake(client, timeout=timeout)
|
|
442
|
-
return await client.
|
|
442
|
+
return await client.loop_execution_state_fetch(lid, timeout=timeout)
|
|
443
443
|
|
|
444
444
|
|
|
445
445
|
async def fetch_loop_messages(
|
|
@@ -480,6 +480,6 @@ __all__ = [
|
|
|
480
480
|
"fetch_skills_catalog",
|
|
481
481
|
"fetch_config_section",
|
|
482
482
|
"fetch_loop_history",
|
|
483
|
-
"fetch_loop_cards",
|
|
484
483
|
"fetch_loop_messages",
|
|
484
|
+
"fetch_execution_state",
|
|
485
485
|
]
|
|
@@ -9,8 +9,6 @@ IMAGE_TO_TEXT: Final = "image_to_text"
|
|
|
9
9
|
OCR: Final = "ocr"
|
|
10
10
|
EMBED: Final = "embed"
|
|
11
11
|
|
|
12
|
-
REMOVED_INTENT_HINTS: frozenset[str] = frozenset({"direct_llm", "quiz", "direct_model"})
|
|
13
|
-
|
|
14
12
|
# Default deliverable phases for turn-ending replies (excludes plan_direct narration).
|
|
15
13
|
DEFAULT_DELIVERABLE_PHASES: frozenset[str] = frozenset(
|
|
16
14
|
{
|
{soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/protocol_params.py
RENAMED
|
@@ -22,7 +22,7 @@ __all__ = [
|
|
|
22
22
|
"LoopMessagesParams",
|
|
23
23
|
"LoopStateGetParams",
|
|
24
24
|
"LoopStateUpdateParams",
|
|
25
|
-
"
|
|
25
|
+
"LoopExecutionStateFetchParams",
|
|
26
26
|
"LoopDetachParams",
|
|
27
27
|
# Subscription params
|
|
28
28
|
"SubscribeParams",
|
|
@@ -269,16 +269,17 @@ class LoopStateUpdateParams(ParamsBase):
|
|
|
269
269
|
as_node: str | None = None
|
|
270
270
|
|
|
271
271
|
|
|
272
|
-
class
|
|
273
|
-
"""Params for ``method=
|
|
272
|
+
class LoopExecutionStateFetchParams(ParamsBase):
|
|
273
|
+
"""Params for ``method=loop_execution_state_fetch``.
|
|
274
|
+
|
|
275
|
+
Returns a focused execution-progress snapshot (plan, step_index,
|
|
276
|
+
iteration, status) for the loop's bound checkpoint thread.
|
|
274
277
|
|
|
275
278
|
Attributes:
|
|
276
279
|
loop_id: Loop identifier (required).
|
|
277
|
-
since: Fetch cards after this sequence.
|
|
278
280
|
"""
|
|
279
281
|
|
|
280
282
|
loop_id: str = Field(..., min_length=1)
|
|
281
|
-
since: str | None = None
|
|
282
283
|
|
|
283
284
|
|
|
284
285
|
class LoopHistoryFetchParams(ParamsBase):
|
{soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/stream_terminal.py
RENAMED
|
@@ -9,6 +9,11 @@ from __future__ import annotations
|
|
|
9
9
|
from typing import Any, TypeGuard
|
|
10
10
|
|
|
11
11
|
from soothe_sdk.core.events import (
|
|
12
|
+
CARD_CREATED,
|
|
13
|
+
CARD_FINALIZED,
|
|
14
|
+
CARD_REPLAY_BEGIN,
|
|
15
|
+
CARD_REPLAY_END,
|
|
16
|
+
CARD_UPDATED,
|
|
12
17
|
PLAN_CREATED,
|
|
13
18
|
STRANGE_LOOP_COMPLETED,
|
|
14
19
|
STRANGE_LOOP_STEP_COMPLETED,
|
|
@@ -28,6 +33,9 @@ _TURN_PROGRESS_CUSTOM_TYPES = frozenset(
|
|
|
28
33
|
STRANGE_LOOP_STEP_STARTED,
|
|
29
34
|
STRANGE_LOOP_STEP_QUEUED,
|
|
30
35
|
STRANGE_LOOP_STEP_COMPLETED,
|
|
36
|
+
CARD_CREATED,
|
|
37
|
+
CARD_UPDATED,
|
|
38
|
+
CARD_FINALIZED,
|
|
31
39
|
}
|
|
32
40
|
)
|
|
33
41
|
|
|
@@ -35,9 +43,9 @@ _TURN_PROGRESS_CUSTOM_TYPES = frozenset(
|
|
|
35
43
|
STALE_TURN_PENDING_TYPES = frozenset(
|
|
36
44
|
{
|
|
37
45
|
"connection_ack",
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
CARD_REPLAY_BEGIN,
|
|
47
|
+
CARD_REPLAY_END,
|
|
48
|
+
CARD_CREATED,
|
|
41
49
|
"complete",
|
|
42
50
|
}
|
|
43
51
|
)
|
|
@@ -1066,14 +1066,6 @@ class WebSocketClient:
|
|
|
1066
1066
|
timeout=timeout,
|
|
1067
1067
|
)
|
|
1068
1068
|
|
|
1069
|
-
async def loop_cards_fetch(self, loop_id: str, *, timeout: float = 30.0) -> dict[str, Any]:
|
|
1070
|
-
"""Fetch bound display-card snapshot (``loop_cards_fetch``)."""
|
|
1071
|
-
return await self.request(
|
|
1072
|
-
"loop_cards_fetch",
|
|
1073
|
-
{"loop_id": loop_id},
|
|
1074
|
-
timeout=timeout,
|
|
1075
|
-
)
|
|
1076
|
-
|
|
1077
1069
|
async def loop_messages(
|
|
1078
1070
|
self,
|
|
1079
1071
|
loop_id: str,
|
|
@@ -1103,6 +1095,20 @@ class WebSocketClient:
|
|
|
1103
1095
|
timeout=timeout,
|
|
1104
1096
|
)
|
|
1105
1097
|
|
|
1098
|
+
async def loop_execution_state_fetch(
|
|
1099
|
+
self, loop_id: str, *, timeout: float = 30.0
|
|
1100
|
+
) -> dict[str, Any]:
|
|
1101
|
+
"""Fetch execution-progress snapshot (``loop_execution_state_fetch``).
|
|
1102
|
+
|
|
1103
|
+
Returns ``{plan, step_index, iteration, status}`` for the loop's bound
|
|
1104
|
+
checkpoint thread.
|
|
1105
|
+
"""
|
|
1106
|
+
return await self.request(
|
|
1107
|
+
"loop_execution_state_fetch",
|
|
1108
|
+
{"loop_id": loop_id},
|
|
1109
|
+
timeout=timeout,
|
|
1110
|
+
)
|
|
1111
|
+
|
|
1106
1112
|
async def loop_state_update(
|
|
1107
1113
|
self,
|
|
1108
1114
|
loop_id: str,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/attachments.py
RENAMED
|
File without changes
|
{soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/broadcaster.py
RENAMED
|
File without changes
|
{soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/chunk_filter.py
RENAMED
|
File without changes
|
{soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/classifier.py
RENAMED
|
File without changes
|
{soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/events.py
RENAMED
|
File without changes
|
{soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/managed_client.py
RENAMED
|
File without changes
|
{soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/observability.py
RENAMED
|
File without changes
|
{soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/query_gate.py
RENAMED
|
File without changes
|
{soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/thinking_step.py
RENAMED
|
File without changes
|
|
File without changes
|
{soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/appkit/turn_boundary.py
RENAMED
|
File without changes
|
{soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/command_client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{soothe_client_python-1.0.4 → soothe_client_python-1.0.7}/src/soothe_client/turn_boundary.py
RENAMED
|
File without changes
|