soothe-client-python 0.9.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.
- soothe_client/__init__.py +171 -0
- soothe_client/appkit/__init__.py +138 -0
- soothe_client/appkit/attachments.py +118 -0
- soothe_client/appkit/broadcaster.py +116 -0
- soothe_client/appkit/chunk_filter.py +99 -0
- soothe_client/appkit/classifier.py +498 -0
- soothe_client/appkit/daemon_session.py +657 -0
- soothe_client/appkit/events.py +63 -0
- soothe_client/appkit/managed_client.py +163 -0
- soothe_client/appkit/observability.py +29 -0
- soothe_client/appkit/pool.py +258 -0
- soothe_client/appkit/query_gate.py +93 -0
- soothe_client/appkit/session_store.py +100 -0
- soothe_client/appkit/thinking_step.py +147 -0
- soothe_client/appkit/turn.py +362 -0
- soothe_client/appkit/turn_runner.py +565 -0
- soothe_client/errors.py +65 -0
- soothe_client/helpers.py +404 -0
- soothe_client/intent_hints.py +43 -0
- soothe_client/protocol_params.py +604 -0
- soothe_client/schemas.py +55 -0
- soothe_client/session.py +199 -0
- soothe_client/websocket.py +1626 -0
- soothe_client/ws_command_client.py +633 -0
- soothe_client_python-0.9.4.dist-info/METADATA +131 -0
- soothe_client_python-0.9.4.dist-info/RECORD +28 -0
- soothe_client_python-0.9.4.dist-info/WHEEL +4 -0
- soothe_client_python-0.9.4.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
"""Client-side protocol-1 params validation models (RFC-450 §6.5).
|
|
2
|
+
|
|
3
|
+
These Pydantic models mirror the daemon's PARAMS_REGISTRY and allow clients
|
|
4
|
+
to validate params before sending, catching errors early and reducing
|
|
5
|
+
daemon-side error round-trips.
|
|
6
|
+
|
|
7
|
+
Design notes
|
|
8
|
+
------------
|
|
9
|
+
- All models allow extra fields (``model_config = {"extra": "allow"}``) for
|
|
10
|
+
forward compatibility.
|
|
11
|
+
- Required string identifiers (``loop_id``, ``skill``, ``cmd``, ``content``)
|
|
12
|
+
use ``min_length=1`` to catch empty strings client-side.
|
|
13
|
+
- Optional fields are permissive — the daemon is the authority on domain
|
|
14
|
+
semantics (e.g. whether ``autonomous`` is honoured for a specific method).
|
|
15
|
+
|
|
16
|
+
Public API
|
|
17
|
+
----------
|
|
18
|
+
Each model is named after the method it validates (e.g. ``LoopGetParams``,
|
|
19
|
+
``LoopInputParams``, ``SubscribeParams``). Use with the ``WebSocketClient``
|
|
20
|
+
request/notify/subscribe methods to validate params before sending:
|
|
21
|
+
|
|
22
|
+
params = LoopInputParams(loop_id="abc123", content="Hello")
|
|
23
|
+
await client.notify("loop_input", params.model_dump())
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from __future__ import annotations
|
|
27
|
+
|
|
28
|
+
from typing import Any, Literal
|
|
29
|
+
|
|
30
|
+
from pydantic import BaseModel, Field
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
# Loop RPC params
|
|
34
|
+
"LoopGetParams",
|
|
35
|
+
"LoopListParams",
|
|
36
|
+
"LoopTreeParams",
|
|
37
|
+
"LoopPruneParams",
|
|
38
|
+
"LoopDeleteParams",
|
|
39
|
+
"LoopNewParams",
|
|
40
|
+
"LoopReattachParams",
|
|
41
|
+
"LoopInputParams",
|
|
42
|
+
"LoopMessagesParams",
|
|
43
|
+
"LoopStateGetParams",
|
|
44
|
+
"LoopStateUpdateParams",
|
|
45
|
+
"LoopCardsFetchParams",
|
|
46
|
+
"LoopDetachParams",
|
|
47
|
+
# Subscription params
|
|
48
|
+
"SubscribeParams",
|
|
49
|
+
"AutopilotSubscribeParams",
|
|
50
|
+
# Job RPC params
|
|
51
|
+
"JobCreateParams",
|
|
52
|
+
"JobStatusParams",
|
|
53
|
+
"JobPauseParams",
|
|
54
|
+
"JobResumeParams",
|
|
55
|
+
"JobCancelParams",
|
|
56
|
+
"JobDagParams",
|
|
57
|
+
"JobGuidanceParams",
|
|
58
|
+
# Cron RPC params
|
|
59
|
+
"CronAddParams",
|
|
60
|
+
"CronListParams",
|
|
61
|
+
"CronShowParams",
|
|
62
|
+
"CronCancelParams",
|
|
63
|
+
# Daemon & config params
|
|
64
|
+
"DaemonStatusParams",
|
|
65
|
+
"DaemonShutdownParams",
|
|
66
|
+
"ConfigGetParams",
|
|
67
|
+
"ConfigReloadParams",
|
|
68
|
+
# Skills & models params
|
|
69
|
+
"SkillsListParams",
|
|
70
|
+
"ModelsListParams",
|
|
71
|
+
"InvokeSkillParams",
|
|
72
|
+
"McpStatusParams",
|
|
73
|
+
# Auth params
|
|
74
|
+
"AuthParams",
|
|
75
|
+
"AuthRefreshParams",
|
|
76
|
+
# Command params
|
|
77
|
+
"SlashCommandParams",
|
|
78
|
+
"RpcCommandParams",
|
|
79
|
+
# Connection params
|
|
80
|
+
"ConnectionInitParams", # re-exported from wire.py
|
|
81
|
+
"DisconnectParams",
|
|
82
|
+
]
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class ParamsBase(BaseModel):
|
|
86
|
+
"""Base for all client-side param models — allows extra fields for forward compat.
|
|
87
|
+
|
|
88
|
+
The protocol envelope carries ``proto``, ``type``, ``method``, and ``id``
|
|
89
|
+
alongside the operation-specific fields. All models validate against the
|
|
90
|
+
``params`` dict so extra keys must be tolerated.
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
model_config = {"extra": "allow"}
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class EmptyParams(ParamsBase):
|
|
97
|
+
"""Params model for methods that carry no required fields."""
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
# ---------------------------------------------------------------------------
|
|
101
|
+
# Loop RPC params (RFC-450 §9.2)
|
|
102
|
+
# ---------------------------------------------------------------------------
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class LoopGetParams(ParamsBase):
|
|
106
|
+
"""Params for ``method=loop_get`` (RFC-450 §9.2).
|
|
107
|
+
|
|
108
|
+
Attributes:
|
|
109
|
+
loop_id: Loop identifier (required, non-empty).
|
|
110
|
+
verbose: Include verbose details.
|
|
111
|
+
tree: Include checkpoint tree.
|
|
112
|
+
"""
|
|
113
|
+
|
|
114
|
+
loop_id: str = Field(..., min_length=1, description="Loop identifier")
|
|
115
|
+
verbose: bool = Field(default=False, description="Include verbose details")
|
|
116
|
+
tree: bool = Field(default=False, description="Include checkpoint tree")
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class LoopListParams(ParamsBase):
|
|
120
|
+
"""Params for ``method=loop_list`` (RFC-450 §9.2).
|
|
121
|
+
|
|
122
|
+
Attributes:
|
|
123
|
+
status: Optional status filter.
|
|
124
|
+
limit: Maximum number of results.
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
status: str | None = Field(default=None, description="Filter by loop status")
|
|
128
|
+
limit: int | None = Field(default=None, ge=1, description="Maximum results")
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class LoopTreeParams(ParamsBase):
|
|
132
|
+
"""Params for ``method=loop_tree`` (RFC-450 §9.2).
|
|
133
|
+
|
|
134
|
+
Attributes:
|
|
135
|
+
loop_id: Loop identifier (required).
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
loop_id: str = Field(..., min_length=1, description="Loop identifier")
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class LoopPruneParams(ParamsBase):
|
|
142
|
+
"""Params for ``method=loop_prune`` (RFC-450 §9.2).
|
|
143
|
+
|
|
144
|
+
Attributes:
|
|
145
|
+
loop_id: Loop identifier (required).
|
|
146
|
+
keep_latest: Number of recent branches to keep (default 1).
|
|
147
|
+
"""
|
|
148
|
+
|
|
149
|
+
loop_id: str = Field(..., min_length=1)
|
|
150
|
+
keep_latest: int = Field(default=1, ge=1)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class LoopDeleteParams(ParamsBase):
|
|
154
|
+
"""Params for ``method=loop_delete`` (RFC-450 §9.2).
|
|
155
|
+
|
|
156
|
+
Attributes:
|
|
157
|
+
loop_id: Loop identifier (required).
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
loop_id: str = Field(..., min_length=1)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class LoopNewParams(ParamsBase):
|
|
164
|
+
"""Params for ``method=loop_new`` (RFC-450 §9.2).
|
|
165
|
+
|
|
166
|
+
Attributes:
|
|
167
|
+
workspace: Optional client workspace path.
|
|
168
|
+
user_id: Optional user identifier.
|
|
169
|
+
client_workspace_id: Optional stable workspace scope.
|
|
170
|
+
is_ephemeral: Create ephemeral loop.
|
|
171
|
+
"""
|
|
172
|
+
|
|
173
|
+
workspace: str | None = None
|
|
174
|
+
user_id: str | None = None
|
|
175
|
+
client_workspace_id: str | None = None
|
|
176
|
+
is_ephemeral: bool = False
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
class LoopReattachParams(ParamsBase):
|
|
180
|
+
"""Params for ``method=loop_reattach`` (RFC-450 §9.2).
|
|
181
|
+
|
|
182
|
+
Attributes:
|
|
183
|
+
loop_id: Loop to reattach (required).
|
|
184
|
+
"""
|
|
185
|
+
|
|
186
|
+
loop_id: str = Field(..., min_length=1)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
class LoopDetachParams(ParamsBase):
|
|
190
|
+
"""Params for ``method=loop_detach`` (request mode, RFC-450 §9.2).
|
|
191
|
+
|
|
192
|
+
Attributes:
|
|
193
|
+
loop_id: Loop to detach from (required).
|
|
194
|
+
"""
|
|
195
|
+
|
|
196
|
+
loop_id: str = Field(..., min_length=1)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
class LoopInputParams(ParamsBase):
|
|
200
|
+
"""Params for ``method=loop_input`` (request or notification, RFC-450 §9.2).
|
|
201
|
+
|
|
202
|
+
Attributes:
|
|
203
|
+
loop_id: Loop identifier (required).
|
|
204
|
+
content: User input text or structured content (required).
|
|
205
|
+
autonomous: Enable autonomous mode.
|
|
206
|
+
max_iterations: Max iterations for autonomous mode.
|
|
207
|
+
preferred_subagent: Routing hint.
|
|
208
|
+
model: Provider:model override.
|
|
209
|
+
model_params: Additional model parameters.
|
|
210
|
+
router_profile: Named ``router_profiles`` overlay for chat roles this turn.
|
|
211
|
+
attachments: Image attachments.
|
|
212
|
+
intent_hint: Daemon direct-model hint (text_completion, image_to_text, ocr, embed).
|
|
213
|
+
response_schema: Structured output schema.
|
|
214
|
+
response_schema_name: Schema name for logging.
|
|
215
|
+
response_schema_strict: Enable strict schema validation.
|
|
216
|
+
clarification_mode: RFC-622 clarification relay mode.
|
|
217
|
+
clarification_answer: Mark as answer to pending clarification.
|
|
218
|
+
clarification_answers: Per-question answers for multi-question clarification.
|
|
219
|
+
"""
|
|
220
|
+
|
|
221
|
+
loop_id: str = Field(..., min_length=1)
|
|
222
|
+
content: str | dict[str, Any] = Field(..., description="User input text or structured content")
|
|
223
|
+
autonomous: bool = False
|
|
224
|
+
max_iterations: int | None = Field(default=None, gt=0)
|
|
225
|
+
preferred_subagent: str | None = None
|
|
226
|
+
model: str | None = None
|
|
227
|
+
model_params: dict[str, Any] | None = None
|
|
228
|
+
router_profile: str | None = None
|
|
229
|
+
attachments: list[dict[str, str]] | None = None
|
|
230
|
+
intent_hint: str | None = None
|
|
231
|
+
response_schema: dict[str, Any] | None = None
|
|
232
|
+
response_schema_name: str | None = None
|
|
233
|
+
response_schema_strict: bool | None = None
|
|
234
|
+
clarification_mode: str | None = Field(default=None, pattern=r"^(auto|manual)$")
|
|
235
|
+
clarification_answer: bool = False
|
|
236
|
+
clarification_answers: list[str] | None = None
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
class LoopMessagesParams(ParamsBase):
|
|
240
|
+
"""Params for ``method=loop_messages`` (RFC-450 §9.2).
|
|
241
|
+
|
|
242
|
+
Attributes:
|
|
243
|
+
loop_id: Loop identifier (required).
|
|
244
|
+
limit: Maximum messages (default 100).
|
|
245
|
+
offset: Pagination offset.
|
|
246
|
+
include_events: Include tool events.
|
|
247
|
+
"""
|
|
248
|
+
|
|
249
|
+
loop_id: str = Field(..., min_length=1)
|
|
250
|
+
limit: int = Field(default=100, ge=1)
|
|
251
|
+
offset: int = Field(default=0, ge=0)
|
|
252
|
+
include_events: bool = False
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
class LoopStateGetParams(ParamsBase):
|
|
256
|
+
"""Params for ``method=loop_state_get`` (RFC-450 §9.2).
|
|
257
|
+
|
|
258
|
+
Attributes:
|
|
259
|
+
loop_id: Loop identifier (required).
|
|
260
|
+
keys: Specific channel keys to fetch.
|
|
261
|
+
"""
|
|
262
|
+
|
|
263
|
+
loop_id: str = Field(..., min_length=1)
|
|
264
|
+
keys: list[str] | None = None
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
class LoopStateUpdateParams(ParamsBase):
|
|
268
|
+
"""Params for ``method=loop_state_update`` (RFC-450 §9.2).
|
|
269
|
+
|
|
270
|
+
Attributes:
|
|
271
|
+
loop_id: Loop identifier (required).
|
|
272
|
+
values: Channel values to apply (required).
|
|
273
|
+
as_node: Node to apply update as.
|
|
274
|
+
"""
|
|
275
|
+
|
|
276
|
+
loop_id: str = Field(..., min_length=1)
|
|
277
|
+
values: dict[str, Any]
|
|
278
|
+
as_node: str | None = None
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
class LoopCardsFetchParams(ParamsBase):
|
|
282
|
+
"""Params for ``method=loop_cards_fetch`` (RFC-450 §9.2).
|
|
283
|
+
|
|
284
|
+
Attributes:
|
|
285
|
+
loop_id: Loop identifier (required).
|
|
286
|
+
since: Fetch cards after this sequence.
|
|
287
|
+
"""
|
|
288
|
+
|
|
289
|
+
loop_id: str = Field(..., min_length=1)
|
|
290
|
+
since: str | None = None
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
class LoopHistoryFetchParams(ParamsBase):
|
|
294
|
+
"""Params for ``method=loop_history_fetch`` (RFC-631).
|
|
295
|
+
|
|
296
|
+
Attributes:
|
|
297
|
+
loop_id: Loop identifier (required).
|
|
298
|
+
"""
|
|
299
|
+
|
|
300
|
+
loop_id: str = Field(..., min_length=1)
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
# ---------------------------------------------------------------------------
|
|
304
|
+
# Subscription params (RFC-450 §9.2)
|
|
305
|
+
# ---------------------------------------------------------------------------
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
class SubscribeParams(ParamsBase):
|
|
309
|
+
"""Params for ``method=loop_events`` subscription (RFC-450 §9.2).
|
|
310
|
+
|
|
311
|
+
Attributes:
|
|
312
|
+
loop_id: Loop to subscribe to (required).
|
|
313
|
+
stream_delivery: Delivery mode (batch/adaptive/streaming).
|
|
314
|
+
wire_tier: Wire filter tier (full/compact).
|
|
315
|
+
"""
|
|
316
|
+
|
|
317
|
+
loop_id: str = Field(..., min_length=1)
|
|
318
|
+
stream_delivery: Literal["batch", "adaptive", "streaming"] = "adaptive"
|
|
319
|
+
wire_tier: Literal["full", "compact"] = "full"
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
class AutopilotSubscribeParams(ParamsBase):
|
|
323
|
+
"""Params for ``method=autopilot_events`` subscription (RFC-450 §9.2).
|
|
324
|
+
|
|
325
|
+
Attributes:
|
|
326
|
+
job_id: Optional job filter.
|
|
327
|
+
filters: Event filter criteria.
|
|
328
|
+
"""
|
|
329
|
+
|
|
330
|
+
job_id: str | None = None
|
|
331
|
+
filters: dict[str, Any] | None = None
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
# ---------------------------------------------------------------------------
|
|
335
|
+
# Job RPC params (RFC-450 §9.2)
|
|
336
|
+
# ---------------------------------------------------------------------------
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
class JobCreateParams(ParamsBase):
|
|
340
|
+
"""Params for ``method=job_create`` (RFC-450 §9.2).
|
|
341
|
+
|
|
342
|
+
Attributes:
|
|
343
|
+
goal: Root goal description (required).
|
|
344
|
+
workspace: Optional workspace path.
|
|
345
|
+
user_id: Optional user identifier.
|
|
346
|
+
autonomous: Enable autonomous mode.
|
|
347
|
+
max_iterations: Max iterations.
|
|
348
|
+
guidance: Initial guidance.
|
|
349
|
+
intent_hint: Daemon direct-model hint (text_completion, image_to_text, ocr, embed).
|
|
350
|
+
"""
|
|
351
|
+
|
|
352
|
+
goal: str = Field(..., min_length=1, description="Root goal text")
|
|
353
|
+
workspace: str | None = None
|
|
354
|
+
user_id: str | None = None
|
|
355
|
+
autonomous: bool = False
|
|
356
|
+
max_iterations: int | None = Field(default=None, gt=0)
|
|
357
|
+
guidance: str | None = None
|
|
358
|
+
intent_hint: str | None = None
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
class JobStatusParams(ParamsBase):
|
|
362
|
+
"""Params for ``method=job_status`` (RFC-450 §9.2).
|
|
363
|
+
|
|
364
|
+
Attributes:
|
|
365
|
+
job_id: Job identifier (required).
|
|
366
|
+
"""
|
|
367
|
+
|
|
368
|
+
job_id: str = Field(..., min_length=1)
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
class JobPauseParams(ParamsBase):
|
|
372
|
+
"""Params for ``method=job_pause`` (RFC-450 §9.2).
|
|
373
|
+
|
|
374
|
+
Attributes:
|
|
375
|
+
job_id: Job to pause (required).
|
|
376
|
+
"""
|
|
377
|
+
|
|
378
|
+
job_id: str = Field(..., min_length=1)
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
class JobResumeParams(ParamsBase):
|
|
382
|
+
"""Params for ``method=job_resume`` (RFC-450 §9.2).
|
|
383
|
+
|
|
384
|
+
Attributes:
|
|
385
|
+
job_id: Job to resume (required).
|
|
386
|
+
"""
|
|
387
|
+
|
|
388
|
+
job_id: str = Field(..., min_length=1)
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
class JobCancelParams(ParamsBase):
|
|
392
|
+
"""Params for ``method=job_cancel`` (RFC-450 §9.2).
|
|
393
|
+
|
|
394
|
+
Attributes:
|
|
395
|
+
job_id: Job to cancel (required).
|
|
396
|
+
"""
|
|
397
|
+
|
|
398
|
+
job_id: str = Field(..., min_length=1)
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
class JobDagParams(ParamsBase):
|
|
402
|
+
"""Params for ``method=job_dag`` (RFC-450 §9.2).
|
|
403
|
+
|
|
404
|
+
Attributes:
|
|
405
|
+
job_id: Job identifier (required).
|
|
406
|
+
"""
|
|
407
|
+
|
|
408
|
+
job_id: str = Field(..., min_length=1)
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
class JobGuidanceParams(ParamsBase):
|
|
412
|
+
"""Params for ``method=job_guidance`` (RFC-450 §9.2).
|
|
413
|
+
|
|
414
|
+
Attributes:
|
|
415
|
+
job_id: Target job (required).
|
|
416
|
+
content: Guidance text (canonical, required).
|
|
417
|
+
goal_id: Optional specific goal target.
|
|
418
|
+
"""
|
|
419
|
+
|
|
420
|
+
job_id: str = Field(..., min_length=1)
|
|
421
|
+
content: str = Field(..., min_length=1, description="Guidance text (canonical)")
|
|
422
|
+
goal_id: str | None = None
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
# ---------------------------------------------------------------------------
|
|
426
|
+
# Cron RPC params (RFC-229)
|
|
427
|
+
# ---------------------------------------------------------------------------
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
class CronAddParams(ParamsBase):
|
|
431
|
+
"""Params for ``method=cron_add`` (RFC-229).
|
|
432
|
+
|
|
433
|
+
Attributes:
|
|
434
|
+
text: Natural language scheduling request (required).
|
|
435
|
+
priority: Optional job priority (1-100).
|
|
436
|
+
"""
|
|
437
|
+
|
|
438
|
+
text: str = Field(..., min_length=1, description="Natural language scheduling request")
|
|
439
|
+
priority: int | None = Field(default=None, ge=1, le=100)
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
class CronListParams(ParamsBase):
|
|
443
|
+
"""Params for ``method=cron_list`` (RFC-229).
|
|
444
|
+
|
|
445
|
+
Attributes:
|
|
446
|
+
status: Optional status filter.
|
|
447
|
+
"""
|
|
448
|
+
|
|
449
|
+
status: str | None = None
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
class CronShowParams(ParamsBase):
|
|
453
|
+
"""Params for ``method=cron_show`` (RFC-229).
|
|
454
|
+
|
|
455
|
+
Attributes:
|
|
456
|
+
job_id: Cron job identifier (required).
|
|
457
|
+
"""
|
|
458
|
+
|
|
459
|
+
job_id: str = Field(..., min_length=1)
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
class CronCancelParams(ParamsBase):
|
|
463
|
+
"""Params for ``method=cron_cancel`` (RFC-229).
|
|
464
|
+
|
|
465
|
+
Attributes:
|
|
466
|
+
job_id: Cron job to cancel (required).
|
|
467
|
+
"""
|
|
468
|
+
|
|
469
|
+
job_id: str = Field(..., min_length=1)
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
# ---------------------------------------------------------------------------
|
|
473
|
+
# Daemon & config params (RFC-450 §9.2)
|
|
474
|
+
# ---------------------------------------------------------------------------
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
class DaemonStatusParams(EmptyParams):
|
|
478
|
+
"""Params for ``method=daemon_status`` — no required fields."""
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
class DaemonShutdownParams(EmptyParams):
|
|
482
|
+
"""Params for ``method=daemon_shutdown`` — no required fields."""
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
class ConfigGetParams(ParamsBase):
|
|
486
|
+
"""Params for ``method=config_get`` (RFC-450 §9.2).
|
|
487
|
+
|
|
488
|
+
Attributes:
|
|
489
|
+
section: Config section to fetch.
|
|
490
|
+
"""
|
|
491
|
+
|
|
492
|
+
section: str | None = None
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
class ConfigReloadParams(EmptyParams):
|
|
496
|
+
"""Params for ``method=config_reload`` — no required fields."""
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
# ---------------------------------------------------------------------------
|
|
500
|
+
# Skills & models params (RFC-450 §9.2)
|
|
501
|
+
# ---------------------------------------------------------------------------
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
class SkillsListParams(EmptyParams):
|
|
505
|
+
"""Params for ``method=skills_list`` — no required fields."""
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
class ModelsListParams(EmptyParams):
|
|
509
|
+
"""Params for ``method=models_list`` — no required fields."""
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
class InvokeSkillParams(ParamsBase):
|
|
513
|
+
"""Params for ``method=invoke_skill`` (RFC-450 §9.2).
|
|
514
|
+
|
|
515
|
+
Attributes:
|
|
516
|
+
skill: Skill name (required).
|
|
517
|
+
args: Skill arguments.
|
|
518
|
+
clarification_mode: RFC-622 clarification relay mode.
|
|
519
|
+
"""
|
|
520
|
+
|
|
521
|
+
skill: str = Field(..., min_length=1)
|
|
522
|
+
args: str = ""
|
|
523
|
+
clarification_mode: str | None = Field(default=None, pattern=r"^(auto|manual)$")
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
class McpStatusParams(EmptyParams):
|
|
527
|
+
"""Params for ``method=mcp_status`` — no required fields."""
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
# ---------------------------------------------------------------------------
|
|
531
|
+
# Auth params (RFC-450 §9.2)
|
|
532
|
+
# ---------------------------------------------------------------------------
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
class AuthParams(ParamsBase):
|
|
536
|
+
"""Params for ``method=auth`` (RFC-450 §9.2).
|
|
537
|
+
|
|
538
|
+
Attributes:
|
|
539
|
+
access_key: Access key credential.
|
|
540
|
+
secret_key: Secret key credential.
|
|
541
|
+
"""
|
|
542
|
+
|
|
543
|
+
access_key: str = ""
|
|
544
|
+
secret_key: str = ""
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
class AuthRefreshParams(ParamsBase):
|
|
548
|
+
"""Params for ``method=auth_refresh`` (RFC-450 §9.2).
|
|
549
|
+
|
|
550
|
+
Attributes:
|
|
551
|
+
refresh_token: Token to refresh.
|
|
552
|
+
"""
|
|
553
|
+
|
|
554
|
+
refresh_token: str = ""
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
# ---------------------------------------------------------------------------
|
|
558
|
+
# Command params (RFC-450 §9.4)
|
|
559
|
+
# ---------------------------------------------------------------------------
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
class SlashCommandParams(ParamsBase):
|
|
563
|
+
"""Params for ``method=slash_command`` notification (RFC-450 §9.4).
|
|
564
|
+
|
|
565
|
+
Attributes:
|
|
566
|
+
cmd: Slash command string (e.g. ``/exit``, ``/cancel``).
|
|
567
|
+
"""
|
|
568
|
+
|
|
569
|
+
cmd: str = Field(..., min_length=1)
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
class RpcCommandParams(ParamsBase):
|
|
573
|
+
"""Params for ``method=rpc_command`` request (RFC-450 §9.4).
|
|
574
|
+
|
|
575
|
+
Attributes:
|
|
576
|
+
command: RPC command name.
|
|
577
|
+
payload: Command payload.
|
|
578
|
+
"""
|
|
579
|
+
|
|
580
|
+
command: str | None = None
|
|
581
|
+
payload: dict[str, Any] | None = None
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
# ---------------------------------------------------------------------------
|
|
585
|
+
# Connection params (RFC-450 §8.2)
|
|
586
|
+
# ---------------------------------------------------------------------------
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
# Re-export ConnectionInitParams from wire.py so callers have one import path.
|
|
590
|
+
# The wire.py version carries the full handshake structure (client_version,
|
|
591
|
+
# client_name, accept_proto, capabilities) and is used by the actual
|
|
592
|
+
# connection_init envelope — see WireEnvelope/ConnectionInitEnvelope there.
|
|
593
|
+
from soothe_sdk.wire.codec import ConnectionInitParams # noqa: E402,F401
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
class DisconnectParams(EmptyParams):
|
|
597
|
+
"""Params for ``method=disconnect`` notification — no required fields."""
|
|
598
|
+
|
|
599
|
+
|
|
600
|
+
class DeliveryAckParams(ParamsBase):
|
|
601
|
+
"""Params for ``method=delivery_ack`` notification (stream termination drain)."""
|
|
602
|
+
|
|
603
|
+
loop_id: str = Field(..., min_length=1)
|
|
604
|
+
seq: int = Field(..., ge=0)
|
soothe_client/schemas.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Wire-safe protocol schemas for WebSocket communication.
|
|
2
|
+
|
|
3
|
+
These schemas are used in daemon-CLI communication via WebSocket protocol.
|
|
4
|
+
They're defined in SDK so both daemon and CLI can use them without daemon
|
|
5
|
+
runtime dependency in CLI.
|
|
6
|
+
|
|
7
|
+
This module is part of Phase 1 of IG-174: CLI import violations fix.
|
|
8
|
+
|
|
9
|
+
Note: These are simplified wire-safe versions. Full protocol implementations
|
|
10
|
+
are in soothe.protocols.planner (daemon-side).
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from pydantic import BaseModel, Field
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class PlanStep(BaseModel):
|
|
17
|
+
"""Wire-safe plan step schema for WebSocket protocol."""
|
|
18
|
+
|
|
19
|
+
step_id: str = Field(description="Unique identifier for this step")
|
|
20
|
+
description: str = Field(description="Human-readable step description")
|
|
21
|
+
status: str = Field(
|
|
22
|
+
default="pending", description="Step status: pending/running/completed/failed"
|
|
23
|
+
)
|
|
24
|
+
result: str | None = Field(default=None, description="Step execution result")
|
|
25
|
+
error: str | None = Field(default=None, description="Error message if failed")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class Plan(BaseModel):
|
|
29
|
+
"""Wire-safe plan schema for WebSocket protocol."""
|
|
30
|
+
|
|
31
|
+
plan_id: str = Field(description="Unique identifier for this plan")
|
|
32
|
+
goal: str = Field(description="The goal this plan addresses")
|
|
33
|
+
steps: list[PlanStep] = Field(default_factory=list, description="Ordered list of steps")
|
|
34
|
+
status: str = Field(
|
|
35
|
+
default="created", description="Plan status: created/executing/completed/failed"
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ToolOutput(BaseModel):
|
|
40
|
+
"""Wire-safe tool output schema for WebSocket protocol.
|
|
41
|
+
|
|
42
|
+
Used to structure tool results for rendering in CLI.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
tool_name: str = Field(description="Name of the tool that produced output")
|
|
46
|
+
output: str = Field(description="Tool output content")
|
|
47
|
+
error: str | None = Field(default=None, description="Error if tool failed")
|
|
48
|
+
metadata: dict = Field(default_factory=dict, description="Additional metadata")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
__all__ = [
|
|
52
|
+
"Plan",
|
|
53
|
+
"PlanStep",
|
|
54
|
+
"ToolOutput",
|
|
55
|
+
]
|