dominus-sdk-python 2.18.0__tar.gz → 2.18.1__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.
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/PKG-INFO +2 -2
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/README.md +1 -1
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/__init__.py +5 -1
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/helpers/core.py +36 -15
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/artifacts.py +84 -60
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/logs.py +35 -6
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/workflow.py +43 -101
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus_sdk_python.egg-info/PKG-INFO +2 -2
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus_sdk_python.egg-info/SOURCES.txt +1 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/pyproject.toml +1 -1
- dominus_sdk_python-2.18.1/tests/test_logs.py +65 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/tests/test_workflow_lifecycle.py +29 -89
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/tests/test_workflow_refs.py +12 -10
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/config/__init__.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/config/endpoints.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/errors.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/helpers/__init__.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/helpers/auth.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/helpers/cache.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/helpers/console_capture.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/helpers/crypto.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/helpers/sse.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/helpers/trace.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/__init__.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/admin.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/ai.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/auth.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/courier.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/db.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/ddl.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/fastapi.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/files.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/health.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/jobs.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/open.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/oracle/__init__.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/oracle/audio_capture.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/oracle/oracle_websocket.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/oracle/session.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/oracle/types.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/oracle/vad_gate.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/portal.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/processor.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/redis.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/secrets.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/secure.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/sync.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/services/__init__.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/start.py +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus_sdk_python.egg-info/dependency_links.txt +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus_sdk_python.egg-info/requires.txt +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus_sdk_python.egg-info/top_level.txt +0 -0
- {dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dominus-sdk-python
|
|
3
|
-
Version: 2.18.
|
|
3
|
+
Version: 2.18.1
|
|
4
4
|
Summary: Python SDK for the Dominus Orchestrator Platform
|
|
5
5
|
Author-email: CareBridge Systems <dev@carebridge.io>
|
|
6
6
|
License: Proprietary
|
|
@@ -49,7 +49,7 @@ Async Python SDK for CareBridge Dominus platform services. Routes calls through
|
|
|
49
49
|
- Server-side, asyncio-first Python SDK (3.9+)
|
|
50
50
|
- Namespace API with root-level shortcuts for common operations
|
|
51
51
|
- Targets production Cloudflare Workers (gateway, JWT, logs) and Cloud Run (orchestrator)
|
|
52
|
-
- Version: 2.18.
|
|
52
|
+
- Version: 2.18.1
|
|
53
53
|
|
|
54
54
|
## Quick Start
|
|
55
55
|
|
|
@@ -7,7 +7,7 @@ Async Python SDK for CareBridge Dominus platform services. Routes calls through
|
|
|
7
7
|
- Server-side, asyncio-first Python SDK (3.9+)
|
|
8
8
|
- Namespace API with root-level shortcuts for common operations
|
|
9
9
|
- Targets production Cloudflare Workers (gateway, JWT, logs) and Cloud Run (orchestrator)
|
|
10
|
-
- Version: 2.18.
|
|
10
|
+
- Version: 2.18.1
|
|
11
11
|
|
|
12
12
|
## Quick Start
|
|
13
13
|
|
|
@@ -154,6 +154,8 @@ from .helpers.cache import (
|
|
|
154
154
|
from .helpers.core import (
|
|
155
155
|
verify_jwt_locally,
|
|
156
156
|
is_jwt_valid,
|
|
157
|
+
mint_selected_project_jwt,
|
|
158
|
+
delegate_jwt,
|
|
157
159
|
)
|
|
158
160
|
|
|
159
161
|
# Export trace utilities for distributed tracing
|
|
@@ -180,7 +182,7 @@ from .errors import (
|
|
|
180
182
|
TimeoutError as DominusTimeoutError,
|
|
181
183
|
)
|
|
182
184
|
|
|
183
|
-
__version__ = "2.18.
|
|
185
|
+
__version__ = "2.18.1"
|
|
184
186
|
__all__ = [
|
|
185
187
|
# Main SDK instance
|
|
186
188
|
"dominus",
|
|
@@ -250,6 +252,8 @@ __all__ = [
|
|
|
250
252
|
# JWT verification utilities
|
|
251
253
|
"verify_jwt_locally",
|
|
252
254
|
"is_jwt_valid",
|
|
255
|
+
"mint_selected_project_jwt",
|
|
256
|
+
"delegate_jwt",
|
|
253
257
|
# Trace utilities
|
|
254
258
|
"generate_trace_id",
|
|
255
259
|
"get_current_trace_id",
|
|
@@ -521,29 +521,31 @@ async def _ensure_valid_jwt(psk_token: str, sovereign_url: str) -> str:
|
|
|
521
521
|
return jwt
|
|
522
522
|
|
|
523
523
|
|
|
524
|
-
async def
|
|
524
|
+
async def mint_selected_project_jwt(
|
|
525
525
|
psk_token: str,
|
|
526
526
|
target_project_id: str,
|
|
527
527
|
target_environment: str,
|
|
528
528
|
use_shared: bool = False
|
|
529
529
|
) -> str:
|
|
530
530
|
"""
|
|
531
|
-
Mint a
|
|
531
|
+
Mint a selected-project JWT for a target project.
|
|
532
532
|
|
|
533
|
-
This is used by admin-level services
|
|
534
|
-
|
|
533
|
+
This is used by admin-level services to act within a selected project
|
|
534
|
+
context. The compatibility route name remains `/jwt/delegate`, but
|
|
535
|
+
the canonical contract is selected-project targeting, not a separate
|
|
536
|
+
delegated token family.
|
|
535
537
|
|
|
536
538
|
Args:
|
|
537
539
|
psk_token: Admin PSK token (DOMINUS_TOKEN for admin project)
|
|
538
540
|
target_project_id: UUID of the target project
|
|
539
541
|
target_environment: Environment (development, staging, production)
|
|
540
|
-
use_shared:
|
|
542
|
+
use_shared: Deprecated compatibility flag; selected-project JWTs infer shared context from the target project
|
|
541
543
|
|
|
542
544
|
Returns:
|
|
543
|
-
|
|
545
|
+
Selected-project JWT string
|
|
544
546
|
|
|
545
547
|
Raises:
|
|
546
|
-
RuntimeError: If
|
|
548
|
+
RuntimeError: If selected-project minting fails
|
|
547
549
|
"""
|
|
548
550
|
from ..config.endpoints import get_gateway_url, get_proxy_config
|
|
549
551
|
gateway_url = get_gateway_url()
|
|
@@ -557,13 +559,11 @@ async def delegate_jwt(
|
|
|
557
559
|
"X-Parent-Span-Id": get_current_span_id(),
|
|
558
560
|
}
|
|
559
561
|
|
|
560
|
-
# Body format for /jwt/delegate endpoint
|
|
561
562
|
body_json = {
|
|
562
563
|
"target_project_id": target_project_id,
|
|
563
564
|
"target_environment": target_environment
|
|
564
565
|
}
|
|
565
|
-
|
|
566
|
-
body_json["use_shared"] = True
|
|
566
|
+
_ = use_shared
|
|
567
567
|
|
|
568
568
|
body_b64 = _b64_encode(body_json)
|
|
569
569
|
|
|
@@ -576,13 +576,13 @@ async def delegate_jwt(
|
|
|
576
576
|
result = _b64_decode(response.text)
|
|
577
577
|
|
|
578
578
|
if not result.get("success"):
|
|
579
|
-
error_msg = result.get("error", "Unknown
|
|
580
|
-
raise RuntimeError(f"
|
|
579
|
+
error_msg = result.get("error", "Unknown selected-project mint error")
|
|
580
|
+
raise RuntimeError(f"Selected-project mint error: {error_msg}")
|
|
581
581
|
|
|
582
582
|
data = result.get("data", {})
|
|
583
583
|
jwt = data.get("token") or data.get("access_token")
|
|
584
584
|
if not jwt:
|
|
585
|
-
raise RuntimeError("No JWT token in
|
|
585
|
+
raise RuntimeError("No JWT token in selected-project mint response")
|
|
586
586
|
|
|
587
587
|
return jwt
|
|
588
588
|
|
|
@@ -594,10 +594,31 @@ async def delegate_jwt(
|
|
|
594
594
|
error_detail = error_body.get("error") or str(error_body)
|
|
595
595
|
except Exception:
|
|
596
596
|
error_detail = e.response.text[:200] if e.response.text else str(e)
|
|
597
|
-
raise RuntimeError(f"
|
|
597
|
+
raise RuntimeError(f"Selected-project JWT mint failed: {error_detail}") from e
|
|
598
598
|
|
|
599
599
|
except Exception as e:
|
|
600
|
-
raise RuntimeError(f"
|
|
600
|
+
raise RuntimeError(f"Selected-project JWT mint failed: {e}") from e
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
async def delegate_jwt(
|
|
604
|
+
psk_token: str,
|
|
605
|
+
target_project_id: str,
|
|
606
|
+
target_environment: str,
|
|
607
|
+
use_shared: bool = False
|
|
608
|
+
) -> str:
|
|
609
|
+
"""
|
|
610
|
+
Compatibility alias for :func:`mint_selected_project_jwt`.
|
|
611
|
+
|
|
612
|
+
.. deprecated::
|
|
613
|
+
Prefer :func:`mint_selected_project_jwt` for new code; "delegated" naming is
|
|
614
|
+
legacy terminology only.
|
|
615
|
+
"""
|
|
616
|
+
return await mint_selected_project_jwt(
|
|
617
|
+
psk_token=psk_token,
|
|
618
|
+
target_project_id=target_project_id,
|
|
619
|
+
target_environment=target_environment,
|
|
620
|
+
use_shared=use_shared,
|
|
621
|
+
)
|
|
601
622
|
|
|
602
623
|
|
|
603
624
|
def verify_token_format(token: str) -> bool:
|
|
@@ -4,10 +4,14 @@ Artifacts Namespace - Temporary artifact storage.
|
|
|
4
4
|
Provides auto-tiered artifact storage (Redis < 1MB, B2 >= 1MB)
|
|
5
5
|
with TTL-based expiration. Routes through gateway to artifact-worker.
|
|
6
6
|
|
|
7
|
+
The artifact worker returns HTTP 410 for legacy paths (/store, /retrieve, /list, /delete).
|
|
8
|
+
This SDK only calls /api/artifact/v2/*; convenience ``store``/``retrieve``/``delete`` map
|
|
9
|
+
those shapes to V2 compatibility addressing (see ``store_v2`` for canonical addressed writes).
|
|
10
|
+
|
|
7
11
|
Usage:
|
|
8
12
|
from dominus import dominus
|
|
9
13
|
|
|
10
|
-
#
|
|
14
|
+
# Prefer store_v2 / addressed refs for new code; legacy-shaped store maps to V2 internally
|
|
11
15
|
result = await dominus.artifacts.store(data="base64data...", ttl_seconds=7200)
|
|
12
16
|
|
|
13
17
|
# Retrieve
|
|
@@ -271,6 +275,21 @@ class ArtifactsNamespace:
|
|
|
271
275
|
def __init__(self, client: "Dominus"):
|
|
272
276
|
self._client = client
|
|
273
277
|
|
|
278
|
+
async def _legacy_project_context(self) -> tuple[str, str]:
|
|
279
|
+
"""project_id and env from the cached service JWT (for V1-shaped -> V2 compat calls)."""
|
|
280
|
+
from ..helpers.core import _ensure_valid_jwt
|
|
281
|
+
from ..start import _BASE_URL, _TOKEN
|
|
282
|
+
|
|
283
|
+
jwt = await _ensure_valid_jwt(_TOKEN, _BASE_URL)
|
|
284
|
+
claims = await self._client.validate_jwt(jwt)
|
|
285
|
+
pid = _safe_string(claims.get("project_id"))
|
|
286
|
+
env = _safe_string(claims.get("env")) or "production"
|
|
287
|
+
if not pid:
|
|
288
|
+
raise RuntimeError(
|
|
289
|
+
"dominus.artifacts legacy methods require project_id on the service JWT",
|
|
290
|
+
)
|
|
291
|
+
return pid, env
|
|
292
|
+
|
|
274
293
|
async def _api(
|
|
275
294
|
self,
|
|
276
295
|
endpoint: str,
|
|
@@ -293,19 +312,27 @@ class ArtifactsNamespace:
|
|
|
293
312
|
category: Optional[str] = None,
|
|
294
313
|
) -> Dict[str, Any]:
|
|
295
314
|
"""
|
|
296
|
-
List
|
|
315
|
+
List artifact heads (V2 / legacy kind) for the service JWT project.
|
|
297
316
|
|
|
298
|
-
|
|
299
|
-
limit: Max items to return (default 100, max 500)
|
|
300
|
-
category: Optional category filter
|
|
301
|
-
|
|
302
|
-
Returns:
|
|
303
|
-
{artifacts: [...], count: int, total_size_bytes: int}
|
|
317
|
+
Category filtering is client-side when rows include ``category``.
|
|
304
318
|
"""
|
|
305
|
-
|
|
319
|
+
project_id, environment = await self._legacy_project_context()
|
|
320
|
+
lim = max(1, min(int(limit or 100), 500))
|
|
321
|
+
raw = await self.list_v2(
|
|
322
|
+
lim,
|
|
323
|
+
group="dominus",
|
|
324
|
+
owner=f"project:{project_id}",
|
|
325
|
+
environment=environment,
|
|
326
|
+
kind="legacy",
|
|
327
|
+
)
|
|
328
|
+
artifacts = list(raw.get("artifacts") or [])
|
|
306
329
|
if category:
|
|
307
|
-
|
|
308
|
-
|
|
330
|
+
artifacts = [a for a in artifacts if (a or {}).get("category") == category]
|
|
331
|
+
count = raw.get("count", len(artifacts))
|
|
332
|
+
total = raw.get("total_size_bytes")
|
|
333
|
+
if total is None:
|
|
334
|
+
total = sum(int((a or {}).get("size_bytes") or 0) for a in artifacts)
|
|
335
|
+
return {"artifacts": artifacts, "count": count, "total_size_bytes": total}
|
|
309
336
|
|
|
310
337
|
async def get_health(self) -> Dict[str, Any]:
|
|
311
338
|
"""Check artifact worker health."""
|
|
@@ -320,52 +347,56 @@ class ArtifactsNamespace:
|
|
|
320
347
|
content_type: Optional[str] = None,
|
|
321
348
|
) -> Dict[str, Any]:
|
|
322
349
|
"""
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
Args:
|
|
326
|
-
data: Base64-encoded data
|
|
327
|
-
key: Optional caller-provided key (UUID generated if not provided)
|
|
328
|
-
ttl_seconds: Time-to-live in seconds (default 3600)
|
|
329
|
-
category: Optional category for organization
|
|
330
|
-
|
|
331
|
-
Returns:
|
|
332
|
-
{key, ref, storage_type, size_bytes, expires_at}
|
|
350
|
+
Legacy-shaped store mapped to V2 (dominus / project:{id} / legacy / encoded key).
|
|
333
351
|
"""
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
352
|
+
import uuid
|
|
353
|
+
|
|
354
|
+
project_id, environment = await self._legacy_project_context()
|
|
355
|
+
use_key = key or str(uuid.uuid4())
|
|
356
|
+
v2 = await self.store_v2(
|
|
357
|
+
group="dominus",
|
|
358
|
+
owner=f"project:{project_id}",
|
|
359
|
+
environment=environment,
|
|
360
|
+
kind="legacy",
|
|
361
|
+
artifact_key=quote(use_key, safe=""),
|
|
362
|
+
data=data,
|
|
363
|
+
ttl_seconds=ttl_seconds,
|
|
364
|
+
category=category,
|
|
365
|
+
content_type=content_type,
|
|
366
|
+
)
|
|
367
|
+
disp = build_display_artifact_ref(use_key)
|
|
368
|
+
return {
|
|
369
|
+
"key": use_key,
|
|
370
|
+
"ref": v2.get("compatibility_ref") or v2.get("head_ref") or disp,
|
|
371
|
+
"storage_type": v2.get("storage_type") or "redis",
|
|
372
|
+
"size_bytes": v2.get("size_bytes", 0),
|
|
373
|
+
"expires_at": v2.get("expires_at") or "",
|
|
337
374
|
}
|
|
338
|
-
if key:
|
|
339
|
-
body["key"] = key
|
|
340
|
-
if category:
|
|
341
|
-
body["category"] = category
|
|
342
|
-
if content_type:
|
|
343
|
-
body["content_type"] = content_type
|
|
344
|
-
return await self._api("/api/artifact/store", body=body)
|
|
345
375
|
|
|
346
376
|
async def retrieve(self, key: str) -> Dict[str, Any]:
|
|
347
377
|
"""
|
|
348
|
-
Retrieve
|
|
349
|
-
|
|
350
|
-
Args:
|
|
351
|
-
key: Artifact key
|
|
352
|
-
|
|
353
|
-
Returns:
|
|
354
|
-
{key, data, storage_type, size_bytes, expires_at}
|
|
378
|
+
Retrieve by key via V2 display ref + target_project_id (compat with legacy data).
|
|
355
379
|
"""
|
|
356
|
-
|
|
380
|
+
project_id, _environment = await self._legacy_project_context()
|
|
381
|
+
return await self._api(
|
|
382
|
+
"/api/artifact/v2/retrieve",
|
|
383
|
+
body={
|
|
384
|
+
"ref": f"{DISPLAY_REF_PREFIX}{key}",
|
|
385
|
+
"target_project_id": project_id,
|
|
386
|
+
},
|
|
387
|
+
)
|
|
357
388
|
|
|
358
389
|
async def delete(self, key: str) -> Dict[str, Any]:
|
|
359
|
-
"""
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
return
|
|
390
|
+
"""Delete legacy compatibility head via V2 selector."""
|
|
391
|
+
project_id, environment = await self._legacy_project_context()
|
|
392
|
+
await self.delete_v2(
|
|
393
|
+
group="dominus",
|
|
394
|
+
owner=f"project:{project_id}",
|
|
395
|
+
environment=environment,
|
|
396
|
+
kind="legacy",
|
|
397
|
+
artifact_key=quote(key, safe=""),
|
|
398
|
+
)
|
|
399
|
+
return {"deleted": True, "key": key}
|
|
369
400
|
|
|
370
401
|
async def cleanup(
|
|
371
402
|
self,
|
|
@@ -373,19 +404,12 @@ class ArtifactsNamespace:
|
|
|
373
404
|
limit: int = 100,
|
|
374
405
|
) -> Dict[str, Any]:
|
|
375
406
|
"""
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
Args:
|
|
379
|
-
force: Skip throttle check
|
|
380
|
-
limit: Max items to clean (default 100)
|
|
407
|
+
HTTP /cleanup is not exposed on the worker; opportunistic cleanup runs after v2 store.
|
|
381
408
|
|
|
382
|
-
Returns
|
|
383
|
-
{cleaned: int, skipped: bool}
|
|
409
|
+
Returns a skipped sentinel for API compatibility.
|
|
384
410
|
"""
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
body["force"] = True
|
|
388
|
-
return await self._api("/api/artifact/cleanup", body=body)
|
|
411
|
+
del force, limit
|
|
412
|
+
return {"cleaned": 0, "skipped": True}
|
|
389
413
|
|
|
390
414
|
def _selector_body(self, options: Dict[str, Any]) -> Dict[str, Any]:
|
|
391
415
|
body: Dict[str, Any] = {}
|
|
@@ -11,6 +11,7 @@ import sys
|
|
|
11
11
|
import time
|
|
12
12
|
from datetime import datetime, timezone
|
|
13
13
|
from typing import Any, Dict, List, Optional, Tuple, TYPE_CHECKING
|
|
14
|
+
from urllib.parse import urlencode
|
|
14
15
|
|
|
15
16
|
if TYPE_CHECKING:
|
|
16
17
|
from ..start import Dominus
|
|
@@ -321,6 +322,13 @@ class LogsNamespace:
|
|
|
321
322
|
minutes: int = 10,
|
|
322
323
|
limit: int = 100,
|
|
323
324
|
trace_id: Optional[str] = None,
|
|
325
|
+
since: Optional[str] = None,
|
|
326
|
+
company: Optional[str] = None,
|
|
327
|
+
subject: Optional[str] = None,
|
|
328
|
+
run_id: Optional[str] = None,
|
|
329
|
+
deploy_id: Optional[str] = None,
|
|
330
|
+
installation_id: Optional[str] = None,
|
|
331
|
+
artifact_ref: Optional[str] = None,
|
|
324
332
|
) -> List[Dict[str, Any]]:
|
|
325
333
|
"""Tail recent logs from the Logs Worker.
|
|
326
334
|
|
|
@@ -330,18 +338,39 @@ class LogsNamespace:
|
|
|
330
338
|
minutes: Time window — 1, 10, or 60 (default: 10)
|
|
331
339
|
limit: Maximum results, 1-1000 (default: 100)
|
|
332
340
|
trace_id: Optional trace_id filter to return only events from a specific trace
|
|
341
|
+
since: Optional ISO timestamp lower bound
|
|
342
|
+
company: Optional canonical company slug filter
|
|
343
|
+
subject: Optional domain subject filter
|
|
344
|
+
run_id: Optional workflow or Authority run id filter
|
|
345
|
+
deploy_id: Optional deploy authority id filter
|
|
346
|
+
installation_id: Optional managed-client installation id filter
|
|
347
|
+
artifact_ref: Optional artifact ref filter
|
|
333
348
|
|
|
334
349
|
Returns:
|
|
335
350
|
List of log event dicts
|
|
336
351
|
"""
|
|
337
|
-
params =
|
|
352
|
+
params: Dict[str, Any] = {}
|
|
338
353
|
if minutes != 10:
|
|
339
|
-
params
|
|
354
|
+
params["minutes"] = minutes
|
|
340
355
|
if limit != 100:
|
|
341
|
-
params
|
|
356
|
+
params["limit"] = limit
|
|
342
357
|
if trace_id:
|
|
343
|
-
params
|
|
344
|
-
|
|
358
|
+
params["trace_id"] = trace_id
|
|
359
|
+
if since:
|
|
360
|
+
params["since"] = since
|
|
361
|
+
if company:
|
|
362
|
+
params["company"] = company
|
|
363
|
+
if subject:
|
|
364
|
+
params["subject"] = subject
|
|
365
|
+
if run_id:
|
|
366
|
+
params["run_id"] = run_id
|
|
367
|
+
if deploy_id:
|
|
368
|
+
params["deploy_id"] = deploy_id
|
|
369
|
+
if installation_id:
|
|
370
|
+
params["installation_id"] = installation_id
|
|
371
|
+
if artifact_ref:
|
|
372
|
+
params["artifact_ref"] = artifact_ref
|
|
373
|
+
qs = urlencode(params)
|
|
345
374
|
endpoint = f"/api/logs/tail?{qs}" if qs else "/api/logs/tail"
|
|
346
375
|
|
|
347
376
|
try:
|
|
@@ -372,7 +401,7 @@ class LogsNamespace:
|
|
|
372
401
|
Returns:
|
|
373
402
|
List of log event dicts
|
|
374
403
|
"""
|
|
375
|
-
return await self.tail(minutes=minutes, limit=limit)
|
|
404
|
+
return await self.tail(minutes=minutes, limit=limit, **kwargs)
|
|
376
405
|
|
|
377
406
|
async def batch(
|
|
378
407
|
self,
|
|
@@ -29,10 +29,15 @@ Usage:
|
|
|
29
29
|
templates = await dominus.workflow.list_templates()
|
|
30
30
|
await dominus.workflow.copy_template(template_id)
|
|
31
31
|
|
|
32
|
-
#
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
# Canonical saved-workflow launch (Authority POST /api/authority/runs/ensure)
|
|
33
|
+
execution = await dominus.workflow.ensure(
|
|
34
|
+
"my-workflow-id",
|
|
35
|
+
subject="PCM47474562",
|
|
36
|
+
company="acme",
|
|
37
|
+
inputs={"key": "value"},
|
|
38
|
+
mode="async",
|
|
39
|
+
)
|
|
40
|
+
# Legacy create_run / validate_run / start_run against /api/workflow/runs are removed.
|
|
36
41
|
"""
|
|
37
42
|
import base64
|
|
38
43
|
import json
|
|
@@ -55,6 +60,12 @@ class WorkflowNamespace:
|
|
|
55
60
|
def __init__(self, client: "Dominus"):
|
|
56
61
|
self._client = client
|
|
57
62
|
|
|
63
|
+
def _reject_legacy_runs_facade(self, method: str) -> None:
|
|
64
|
+
raise RuntimeError(
|
|
65
|
+
f"dominus.workflow.{method} was removed: /api/workflow/runs is retired. "
|
|
66
|
+
"Use ensure() with Authority fields (subject, company, inputs, context, ...) or ensure_instance()."
|
|
67
|
+
)
|
|
68
|
+
|
|
58
69
|
@staticmethod
|
|
59
70
|
def _is_workflow_ref(value: Optional[str]) -> bool:
|
|
60
71
|
return str(value or "").strip().startswith("wf://")
|
|
@@ -758,32 +769,8 @@ class WorkflowNamespace:
|
|
|
758
769
|
use_shared: Optional[bool] = None,
|
|
759
770
|
shared_project_id: Optional[str] = None,
|
|
760
771
|
) -> Dict[str, Any]:
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
Args:
|
|
765
|
-
workflow_id: Workflow UUID
|
|
766
|
-
workflow_ref: Stable workflow_ref for the saved workflow
|
|
767
|
-
"""
|
|
768
|
-
body: Dict[str, Any] = self._workflow_identifier_body(
|
|
769
|
-
workflow_id=workflow_id,
|
|
770
|
-
workflow_ref=workflow_ref,
|
|
771
|
-
)
|
|
772
|
-
if run_id:
|
|
773
|
-
body["run_id"] = run_id
|
|
774
|
-
if metadata:
|
|
775
|
-
body["metadata"] = metadata
|
|
776
|
-
if context:
|
|
777
|
-
body["context"] = context
|
|
778
|
-
if use_shared is not None:
|
|
779
|
-
body["use_shared"] = use_shared
|
|
780
|
-
if shared_project_id:
|
|
781
|
-
body["shared_project_id"] = shared_project_id
|
|
782
|
-
|
|
783
|
-
return await self._api(
|
|
784
|
-
endpoint="/api/workflow/runs",
|
|
785
|
-
body=body,
|
|
786
|
-
)
|
|
772
|
+
del workflow_id, workflow_ref, run_id, metadata, context, use_shared, shared_project_id
|
|
773
|
+
self._reject_legacy_runs_facade("create_run")
|
|
787
774
|
|
|
788
775
|
async def ensure(
|
|
789
776
|
self,
|
|
@@ -1190,18 +1177,12 @@ class WorkflowNamespace:
|
|
|
1190
1177
|
)
|
|
1191
1178
|
|
|
1192
1179
|
async def get_run(self, run_id: str) -> Dict[str, Any]:
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
endpoint=f"/api/workflow/runs/{run_id}",
|
|
1196
|
-
method="GET",
|
|
1197
|
-
)
|
|
1180
|
+
del run_id
|
|
1181
|
+
self._reject_legacy_runs_facade("get_run")
|
|
1198
1182
|
|
|
1199
1183
|
async def get_manifest(self, run_id: str) -> Dict[str, Any]:
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
endpoint=f"/api/workflow/runs/{run_id}/manifest",
|
|
1203
|
-
method="GET",
|
|
1204
|
-
)
|
|
1184
|
+
del run_id
|
|
1185
|
+
self._reject_legacy_runs_facade("get_manifest")
|
|
1205
1186
|
|
|
1206
1187
|
async def register_artifact(
|
|
1207
1188
|
self,
|
|
@@ -1223,43 +1204,26 @@ class WorkflowNamespace:
|
|
|
1223
1204
|
"""
|
|
1224
1205
|
Register a source artifact with a saved-workflow run.
|
|
1225
1206
|
"""
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
body["source_project"] = source_project
|
|
1241
|
-
if source_env:
|
|
1242
|
-
body["source_env"] = source_env
|
|
1243
|
-
if source_project_id:
|
|
1244
|
-
body["source_project_id"] = source_project_id
|
|
1245
|
-
if source_tenant:
|
|
1246
|
-
body["source_tenant"] = source_tenant
|
|
1247
|
-
if metadata:
|
|
1248
|
-
body["metadata"] = metadata
|
|
1249
|
-
if metadata_trusted is not None:
|
|
1250
|
-
body["metadata_trusted"] = metadata_trusted
|
|
1251
|
-
|
|
1252
|
-
return await self._api(
|
|
1253
|
-
endpoint=f"/api/workflow/runs/{run_id}/artifacts",
|
|
1254
|
-
body=body,
|
|
1207
|
+
del (
|
|
1208
|
+
run_id,
|
|
1209
|
+
artifact_key,
|
|
1210
|
+
artifact_id,
|
|
1211
|
+
artifact_ref,
|
|
1212
|
+
source_artifact_key,
|
|
1213
|
+
source_namespace,
|
|
1214
|
+
source_conversation_id,
|
|
1215
|
+
source_project,
|
|
1216
|
+
source_env,
|
|
1217
|
+
source_project_id,
|
|
1218
|
+
source_tenant,
|
|
1219
|
+
metadata,
|
|
1220
|
+
metadata_trusted,
|
|
1255
1221
|
)
|
|
1222
|
+
self._reject_legacy_runs_facade("register_artifact")
|
|
1256
1223
|
|
|
1257
1224
|
async def validate_run(self, run_id: str) -> Dict[str, Any]:
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
endpoint=f"/api/workflow/runs/{run_id}/validate",
|
|
1261
|
-
body={},
|
|
1262
|
-
)
|
|
1225
|
+
del run_id
|
|
1226
|
+
self._reject_legacy_runs_facade("validate_run")
|
|
1263
1227
|
|
|
1264
1228
|
async def start_run(
|
|
1265
1229
|
self,
|
|
@@ -1270,18 +1234,8 @@ class WorkflowNamespace:
|
|
|
1270
1234
|
save_events: Optional[bool] = None,
|
|
1271
1235
|
webhook_url: Optional[str] = None,
|
|
1272
1236
|
) -> Dict[str, Any]:
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
endpoint=f"/api/workflow/runs/{run_id}/start",
|
|
1276
|
-
body={
|
|
1277
|
-
"config": self._build_start_config(
|
|
1278
|
-
mode=mode,
|
|
1279
|
-
timeout_seconds=timeout_seconds,
|
|
1280
|
-
save_events=save_events,
|
|
1281
|
-
webhook_url=webhook_url,
|
|
1282
|
-
)
|
|
1283
|
-
},
|
|
1284
|
-
)
|
|
1237
|
+
del run_id, mode, timeout_seconds, save_events, webhook_url
|
|
1238
|
+
self._reject_legacy_runs_facade("start_run")
|
|
1285
1239
|
|
|
1286
1240
|
async def stream_start_run(
|
|
1287
1241
|
self,
|
|
@@ -1291,21 +1245,9 @@ class WorkflowNamespace:
|
|
|
1291
1245
|
save_events: Optional[bool] = None,
|
|
1292
1246
|
on_chunk: Optional[Any] = None,
|
|
1293
1247
|
):
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
body={
|
|
1298
|
-
"config": self._build_start_config(
|
|
1299
|
-
mode="streaming",
|
|
1300
|
-
timeout_seconds=timeout_seconds,
|
|
1301
|
-
save_events=save_events,
|
|
1302
|
-
)
|
|
1303
|
-
},
|
|
1304
|
-
on_chunk=on_chunk,
|
|
1305
|
-
timeout=float(timeout_seconds or 600),
|
|
1306
|
-
use_gateway=True,
|
|
1307
|
-
):
|
|
1308
|
-
yield chunk
|
|
1248
|
+
del run_id, timeout_seconds, save_events, on_chunk
|
|
1249
|
+
self._reject_legacy_runs_facade("stream_start_run")
|
|
1250
|
+
yield # pragma: no cover
|
|
1309
1251
|
|
|
1310
1252
|
async def status(self, execution_id: str) -> Dict[str, Any]:
|
|
1311
1253
|
"""Get saved-workflow execution status."""
|
{dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus_sdk_python.egg-info/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dominus-sdk-python
|
|
3
|
-
Version: 2.18.
|
|
3
|
+
Version: 2.18.1
|
|
4
4
|
Summary: Python SDK for the Dominus Orchestrator Platform
|
|
5
5
|
Author-email: CareBridge Systems <dev@carebridge.io>
|
|
6
6
|
License: Proprietary
|
|
@@ -49,7 +49,7 @@ Async Python SDK for CareBridge Dominus platform services. Routes calls through
|
|
|
49
49
|
- Server-side, asyncio-first Python SDK (3.9+)
|
|
50
50
|
- Namespace API with root-level shortcuts for common operations
|
|
51
51
|
- Targets production Cloudflare Workers (gateway, JWT, logs) and Cloud Run (orchestrator)
|
|
52
|
-
- Version: 2.18.
|
|
52
|
+
- Version: 2.18.1
|
|
53
53
|
|
|
54
54
|
## Quick Start
|
|
55
55
|
|
{dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus_sdk_python.egg-info/SOURCES.txt
RENAMED
|
@@ -46,5 +46,6 @@ dominus_sdk_python.egg-info/SOURCES.txt
|
|
|
46
46
|
dominus_sdk_python.egg-info/dependency_links.txt
|
|
47
47
|
dominus_sdk_python.egg-info/requires.txt
|
|
48
48
|
dominus_sdk_python.egg-info/top_level.txt
|
|
49
|
+
tests/test_logs.py
|
|
49
50
|
tests/test_workflow_lifecycle.py
|
|
50
51
|
tests/test_workflow_refs.py
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
ROOT = Path(__file__).resolve().parents[1]
|
|
8
|
+
if str(ROOT) not in sys.path:
|
|
9
|
+
sys.path.insert(0, str(ROOT))
|
|
10
|
+
|
|
11
|
+
from dominus.namespaces.logs import LogsNamespace # noqa: E402
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class FakeClient:
|
|
15
|
+
def __init__(self):
|
|
16
|
+
self.calls = []
|
|
17
|
+
|
|
18
|
+
async def _request(
|
|
19
|
+
self,
|
|
20
|
+
endpoint,
|
|
21
|
+
method="POST",
|
|
22
|
+
body=None,
|
|
23
|
+
user_token=None,
|
|
24
|
+
use_gateway=False,
|
|
25
|
+
timeout=30.0,
|
|
26
|
+
):
|
|
27
|
+
self.calls.append(
|
|
28
|
+
{
|
|
29
|
+
"endpoint": endpoint,
|
|
30
|
+
"method": method,
|
|
31
|
+
"body": body,
|
|
32
|
+
"user_token": user_token,
|
|
33
|
+
"use_gateway": use_gateway,
|
|
34
|
+
"timeout": timeout,
|
|
35
|
+
}
|
|
36
|
+
)
|
|
37
|
+
return {"events": [{"event_id": "log-1"}]}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@pytest.mark.asyncio
|
|
41
|
+
async def test_logs_tail_forwards_business_filters():
|
|
42
|
+
client = FakeClient()
|
|
43
|
+
namespace = LogsNamespace(client)
|
|
44
|
+
|
|
45
|
+
events = await namespace.tail(
|
|
46
|
+
limit=25,
|
|
47
|
+
since="2026-04-11T08:33:00Z",
|
|
48
|
+
company="carebridge-summit",
|
|
49
|
+
subject="PCM47474562",
|
|
50
|
+
run_id="run-123",
|
|
51
|
+
deploy_id="deploy-123",
|
|
52
|
+
installation_id="inst-123",
|
|
53
|
+
artifact_ref="ar://carebridge/summit/production/company/report_snapshot_current",
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
assert len(events) == 1
|
|
57
|
+
assert client.calls[0]["endpoint"] == (
|
|
58
|
+
"/api/logs/tail?"
|
|
59
|
+
"limit=25&since=2026-04-11T08%3A33%3A00Z&company=carebridge-summit"
|
|
60
|
+
"&subject=PCM47474562&run_id=run-123&deploy_id=deploy-123"
|
|
61
|
+
"&installation_id=inst-123&artifact_ref="
|
|
62
|
+
"ar%3A%2F%2Fcarebridge%2Fsummit%2Fproduction%2Fcompany%2Freport_snapshot_current"
|
|
63
|
+
)
|
|
64
|
+
assert client.calls[0]["method"] == "GET"
|
|
65
|
+
assert client.calls[0]["use_gateway"] is True
|
|
@@ -167,104 +167,44 @@ async def test_ai_workflow_two_phase_lifecycle_routes_match_node_surface():
|
|
|
167
167
|
|
|
168
168
|
|
|
169
169
|
@pytest.mark.asyncio
|
|
170
|
-
async def
|
|
170
|
+
async def test_saved_workflow_facade_legacy_chain_raises():
|
|
171
171
|
client = FakeClient(stream_chunks=[{"_event": "workflow_start"}])
|
|
172
172
|
namespace = WorkflowNamespace(client)
|
|
173
173
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
"report_ref": {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
source_tenant="tenant-a",
|
|
198
|
-
metadata={
|
|
199
|
-
"report_ref": {
|
|
200
|
-
"report_id": "report-1",
|
|
201
|
-
"accession": "acc-1",
|
|
202
|
-
"session_number": "2",
|
|
203
|
-
},
|
|
204
|
-
"freshness": {
|
|
205
|
-
"state": "fresh",
|
|
206
|
-
"age_seconds": 12,
|
|
207
|
-
},
|
|
208
|
-
},
|
|
209
|
-
metadata_trusted=True,
|
|
210
|
-
)
|
|
211
|
-
await namespace.validate_run("report-run-1")
|
|
212
|
-
await namespace.start_run("report-run-1", timeout_seconds=120)
|
|
213
|
-
streamed = [chunk async for chunk in namespace.stream_start_run("report-run-1", timeout_seconds=90)]
|
|
174
|
+
with pytest.raises(RuntimeError, match="removed"):
|
|
175
|
+
await namespace.create_run(
|
|
176
|
+
"wf-123",
|
|
177
|
+
run_id="report-run-1",
|
|
178
|
+
context={"report_ref": {"report_id": "report-1"}},
|
|
179
|
+
)
|
|
180
|
+
with pytest.raises(RuntimeError, match="removed"):
|
|
181
|
+
await namespace.register_artifact("report-run-1", "k", artifact_id="x")
|
|
182
|
+
with pytest.raises(RuntimeError, match="removed"):
|
|
183
|
+
await namespace.validate_run("report-run-1")
|
|
184
|
+
with pytest.raises(RuntimeError, match="removed"):
|
|
185
|
+
await namespace.start_run("report-run-1", timeout_seconds=120)
|
|
186
|
+
with pytest.raises(RuntimeError, match="removed"):
|
|
187
|
+
_ = [c async for c in namespace.stream_start_run("report-run-1", timeout_seconds=90)]
|
|
188
|
+
|
|
189
|
+
assert client.calls == []
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
@pytest.mark.asyncio
|
|
193
|
+
async def test_saved_workflow_execution_poll_endpoints_unchanged():
|
|
194
|
+
client = FakeClient(stream_chunks=[])
|
|
195
|
+
namespace = WorkflowNamespace(client)
|
|
196
|
+
|
|
214
197
|
await namespace.messages("exec-456", count=15)
|
|
215
198
|
await namespace.events("exec-456", from_id="evt-2", count=20)
|
|
216
199
|
await namespace.status("exec-456")
|
|
217
200
|
await namespace.output("exec-456")
|
|
218
201
|
await namespace.cancel("exec-456")
|
|
219
202
|
|
|
220
|
-
|
|
221
|
-
assert
|
|
222
|
-
assert
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
"metadata": {"source": "processor"},
|
|
226
|
-
"context": {
|
|
227
|
-
"report_ref": {
|
|
228
|
-
"report_id": "report-1",
|
|
229
|
-
"accession": "acc-1",
|
|
230
|
-
"session_number": "2",
|
|
231
|
-
}
|
|
232
|
-
},
|
|
233
|
-
"use_shared": True,
|
|
234
|
-
"shared_project_id": "fdcd5800-c735-4a45-90be-51b621bd4127",
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
register_call = client.calls[1]
|
|
238
|
-
assert register_call["endpoint"] == "/api/workflow/runs/report-run-1/artifacts"
|
|
239
|
-
assert register_call["body"] == {
|
|
240
|
-
"artifact_key": "report_snapshot_current",
|
|
241
|
-
"artifact_ref": "ar://carebridge-summit/production/company/carebridge%2Fcarebridge-summit%2Fproduction%2Freport-workflow%2Freport%2Freport-1%2Freport_snapshot_current.json",
|
|
242
|
-
"source_artifact_key": "carebridge/carebridge-summit/production/report-workflow/report/report-1/report_snapshot_current.json",
|
|
243
|
-
"source_namespace": "company",
|
|
244
|
-
"source_project": "carebridge-summit",
|
|
245
|
-
"source_env": "production",
|
|
246
|
-
"source_project_id": "project-123",
|
|
247
|
-
"source_tenant": "tenant-a",
|
|
248
|
-
"metadata": {
|
|
249
|
-
"report_ref": {
|
|
250
|
-
"report_id": "report-1",
|
|
251
|
-
"accession": "acc-1",
|
|
252
|
-
"session_number": "2",
|
|
253
|
-
},
|
|
254
|
-
"freshness": {
|
|
255
|
-
"state": "fresh",
|
|
256
|
-
"age_seconds": 12,
|
|
257
|
-
},
|
|
258
|
-
},
|
|
259
|
-
"metadata_trusted": True,
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
assert client.calls[-5]["endpoint"] == "/api/workflow/executions/exec-456/messages?count=15"
|
|
263
|
-
assert client.calls[-4]["endpoint"] == "/api/workflow/executions/exec-456/events?from_id=evt-2&count=20"
|
|
264
|
-
assert client.calls[-3]["endpoint"] == "/api/workflow/executions/exec-456/status"
|
|
265
|
-
assert client.calls[-2]["endpoint"] == "/api/workflow/executions/exec-456/output"
|
|
266
|
-
assert client.calls[-1]["endpoint"] == "/api/workflow/executions/exec-456/cancel"
|
|
267
|
-
assert streamed == [{"_event": "workflow_start"}]
|
|
203
|
+
assert client.calls[0]["endpoint"] == "/api/workflow/executions/exec-456/messages?count=15"
|
|
204
|
+
assert client.calls[1]["endpoint"] == "/api/workflow/executions/exec-456/events?from_id=evt-2&count=20"
|
|
205
|
+
assert client.calls[2]["endpoint"] == "/api/workflow/executions/exec-456/status"
|
|
206
|
+
assert client.calls[3]["endpoint"] == "/api/workflow/executions/exec-456/output"
|
|
207
|
+
assert client.calls[4]["endpoint"] == "/api/workflow/executions/exec-456/cancel"
|
|
268
208
|
|
|
269
209
|
|
|
270
210
|
@pytest.mark.asyncio
|
|
@@ -53,22 +53,24 @@ async def test_workflow_get_accepts_workflow_ref():
|
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
@pytest.mark.asyncio
|
|
56
|
-
async def
|
|
56
|
+
async def test_workflow_ensure_accepts_workflow_ref():
|
|
57
57
|
client = FakeClient()
|
|
58
58
|
namespace = WorkflowNamespace(client)
|
|
59
59
|
|
|
60
|
-
await namespace.
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
await namespace.ensure(
|
|
61
|
+
"wf://carebridge-platform/production/shared/patient-intake",
|
|
62
|
+
subject="sub-1",
|
|
63
|
+
company="co-1",
|
|
64
|
+
instance_id="run-123",
|
|
63
65
|
context={"report_ref": {"report_id": "r-1"}},
|
|
66
|
+
mode="async",
|
|
64
67
|
)
|
|
65
68
|
|
|
66
|
-
assert client.calls[0]["endpoint"] == "/api/
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
69
|
+
assert client.calls[0]["endpoint"] == "/api/authority/runs/ensure"
|
|
70
|
+
body = client.calls[0]["body"]
|
|
71
|
+
assert body["workflow_ref"] == "wf://carebridge-platform/production/shared/patient-intake"
|
|
72
|
+
assert body["instance_id"] == "run-123"
|
|
73
|
+
assert body["context"] == {"report_ref": {"report_id": "r-1"}}
|
|
72
74
|
|
|
73
75
|
|
|
74
76
|
@pytest.mark.asyncio
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/oracle/__init__.py
RENAMED
|
File without changes
|
{dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/oracle/audio_capture.py
RENAMED
|
File without changes
|
|
File without changes
|
{dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/oracle/session.py
RENAMED
|
File without changes
|
|
File without changes
|
{dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus/namespaces/oracle/vad_gate.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus_sdk_python.egg-info/requires.txt
RENAMED
|
File without changes
|
{dominus_sdk_python-2.18.0 → dominus_sdk_python-2.18.1}/dominus_sdk_python.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|