dominus-sdk-python 4.6.0__py3-none-any.whl → 4.6.2__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.
- dominus/__init__.py +3 -1
- dominus/namespaces/__init__.py +2 -0
- dominus/namespaces/browser.py +24 -3
- dominus/namespaces/recipes.py +188 -0
- dominus/start.py +4 -0
- {dominus_sdk_python-4.6.0.dist-info → dominus_sdk_python-4.6.2.dist-info}/METADATA +1 -1
- {dominus_sdk_python-4.6.0.dist-info → dominus_sdk_python-4.6.2.dist-info}/RECORD +9 -8
- {dominus_sdk_python-4.6.0.dist-info → dominus_sdk_python-4.6.2.dist-info}/WHEEL +0 -0
- {dominus_sdk_python-4.6.0.dist-info → dominus_sdk_python-4.6.2.dist-info}/top_level.txt +0 -0
dominus/__init__.py
CHANGED
|
@@ -112,6 +112,7 @@ from .namespaces.processor import ProcessorNamespace
|
|
|
112
112
|
from .namespaces.sync import SyncNamespace
|
|
113
113
|
from .namespaces.authority import AuthorityNamespace
|
|
114
114
|
from .namespaces.browser import BrowserNamespace
|
|
115
|
+
from .namespaces.recipes import RecipesNamespace
|
|
115
116
|
from .namespaces.deployer import DeployerNamespace
|
|
116
117
|
from .namespaces.warden import WardenNamespace
|
|
117
118
|
|
|
@@ -164,7 +165,7 @@ from .errors import (
|
|
|
164
165
|
TimeoutError as DominusTimeoutError,
|
|
165
166
|
)
|
|
166
167
|
|
|
167
|
-
__version__ = "4.6.
|
|
168
|
+
__version__ = "4.6.2"
|
|
168
169
|
__all__ = [
|
|
169
170
|
# Main SDK instance
|
|
170
171
|
"dominus",
|
|
@@ -215,6 +216,7 @@ __all__ = [
|
|
|
215
216
|
"SyncNamespace",
|
|
216
217
|
"AuthorityNamespace",
|
|
217
218
|
"BrowserNamespace",
|
|
219
|
+
"RecipesNamespace",
|
|
218
220
|
"DeployerNamespace",
|
|
219
221
|
"WardenNamespace",
|
|
220
222
|
# AI namespace for agent-runtime operations
|
dominus/namespaces/__init__.py
CHANGED
|
@@ -16,6 +16,7 @@ from .processor import ProcessorNamespace
|
|
|
16
16
|
from .sync import SyncNamespace
|
|
17
17
|
from .authority import AuthorityNamespace
|
|
18
18
|
from .browser import BrowserNamespace
|
|
19
|
+
from .recipes import RecipesNamespace
|
|
19
20
|
from .deployer import DeployerNamespace
|
|
20
21
|
from .warden import WardenNamespace
|
|
21
22
|
from .ai import (
|
|
@@ -44,6 +45,7 @@ __all__ = [
|
|
|
44
45
|
"SyncNamespace",
|
|
45
46
|
"AuthorityNamespace",
|
|
46
47
|
"BrowserNamespace",
|
|
48
|
+
"RecipesNamespace",
|
|
47
49
|
"DeployerNamespace",
|
|
48
50
|
"WardenNamespace",
|
|
49
51
|
"AiNamespace",
|
dominus/namespaces/browser.py
CHANGED
|
@@ -77,7 +77,7 @@ class BrowserNamespace:
|
|
|
77
77
|
async def ensure_run(
|
|
78
78
|
self,
|
|
79
79
|
*,
|
|
80
|
-
target: Dict[str, Any],
|
|
80
|
+
target: Optional[Dict[str, Any]] = None,
|
|
81
81
|
idempotency_key: Optional[str] = None,
|
|
82
82
|
run_kind: Optional[str] = None,
|
|
83
83
|
route_label: Optional[str] = None,
|
|
@@ -92,11 +92,29 @@ class BrowserNamespace:
|
|
|
92
92
|
org_id: Optional[str] = None,
|
|
93
93
|
app_slug: Optional[str] = None,
|
|
94
94
|
env: Optional[str] = None,
|
|
95
|
+
recipe_ref: Optional[str] = None,
|
|
96
|
+
recipe: Optional[Any] = None,
|
|
97
|
+
recipe_inputs: Optional[Dict[str, Any]] = None,
|
|
95
98
|
timeout: float = 30.0,
|
|
96
99
|
) -> Dict[str, Any]:
|
|
97
100
|
"""
|
|
98
101
|
Ensure a browser run. ``POST /api/browser/runs/ensure``.
|
|
99
102
|
|
|
103
|
+
``target`` shorthand, ``recipe_ref``, or inline ``recipe`` must be
|
|
104
|
+
present. When ``recipe_ref`` is set, the worker resolves the
|
|
105
|
+
recipe through the recipe-worker, parses it, resolves variables, and
|
|
106
|
+
runs it through the recipe executor — supporting multi-step flows
|
|
107
|
+
including clicks, fills, assertions, extracts, and stash-backed
|
|
108
|
+
credential fills.
|
|
109
|
+
|
|
110
|
+
``recipe`` may be an inline YAML string or JSON object for one-off
|
|
111
|
+
runs. Stable/shared recipes should be published and referenced via
|
|
112
|
+
``recipe_ref``. Target/assertion shorthand runs are synthesized into a
|
|
113
|
+
``browser-recipe-v1`` recipe internally; there is no separate runner path.
|
|
114
|
+
|
|
115
|
+
``recipe_inputs`` supplies scalar values consumed by ``recipe-input://``
|
|
116
|
+
variable refs declared in the recipe's vars map.
|
|
117
|
+
|
|
100
118
|
Browser run metadata remains browser-worker runtime state. Artifact V2
|
|
101
119
|
is used for sanitized `browser-run` result payloads and, when opted-in
|
|
102
120
|
via ``capture_policy["storage_state"] = "always"`` plus
|
|
@@ -109,8 +127,8 @@ class BrowserNamespace:
|
|
|
109
127
|
lookup, returns no storage_state on first call) or an explicit
|
|
110
128
|
``session_artifact_ref`` (hard-error if the ref does not exist).
|
|
111
129
|
"""
|
|
112
|
-
if not target:
|
|
113
|
-
raise ValueError("target is required")
|
|
130
|
+
if not target and not recipe_ref and recipe is None:
|
|
131
|
+
raise ValueError("target, recipe_ref, or recipe is required")
|
|
114
132
|
body = _compact({
|
|
115
133
|
"idempotency_key": idempotency_key,
|
|
116
134
|
"run_kind": run_kind,
|
|
@@ -127,6 +145,9 @@ class BrowserNamespace:
|
|
|
127
145
|
"org_id": org_id,
|
|
128
146
|
"app_slug": app_slug,
|
|
129
147
|
"env": env,
|
|
148
|
+
"recipe_ref": recipe_ref,
|
|
149
|
+
"recipe": recipe,
|
|
150
|
+
"recipe_inputs": recipe_inputs,
|
|
130
151
|
})
|
|
131
152
|
return await self._post("/api/browser/runs/ensure", body, timeout=timeout)
|
|
132
153
|
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Recipes Namespace - kernel-tier recipe protocol.
|
|
3
|
+
|
|
4
|
+
Routes through ``/svc/recipe/*`` on the Dominus gateway. The recipe worker
|
|
5
|
+
owns the type registry, JSON-Schema-based publish validation, three-tier
|
|
6
|
+
resolution (project -> group -> platform), and B2-backed durable storage.
|
|
7
|
+
|
|
8
|
+
Recipe types currently registered:
|
|
9
|
+
- browser-recipe (owned by dominus-browser-worker; body version is browser-recipe-v1)
|
|
10
|
+
|
|
11
|
+
Refs follow ``recipe://{type}/{name}[@v{N}][?tier={tier}]``.
|
|
12
|
+
"""
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from typing import Any, Dict, List, Optional, TYPE_CHECKING
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from ..start import Dominus
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _compact(payload: Dict[str, Any]) -> Dict[str, Any]:
|
|
22
|
+
return {k: v for k, v in payload.items() if v is not None and v != ""}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class RecipesNamespace:
|
|
26
|
+
"""
|
|
27
|
+
Recipe worker namespace.
|
|
28
|
+
|
|
29
|
+
Usage::
|
|
30
|
+
|
|
31
|
+
types = await dominus.recipes.list_types()
|
|
32
|
+
await dominus.recipes.publish(
|
|
33
|
+
type="browser-recipe",
|
|
34
|
+
tier="platform",
|
|
35
|
+
name="health-check",
|
|
36
|
+
body="version: browser-recipe-v1\\nsteps:\\n - kind: goto\\n url: https://x/\\n",
|
|
37
|
+
)
|
|
38
|
+
recipe = await dominus.recipes.get(type="browser-recipe", name="health-check")
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(self, client: "Dominus"):
|
|
42
|
+
self._client = client
|
|
43
|
+
|
|
44
|
+
async def _post(self, endpoint: str, body: Optional[Dict[str, Any]] = None, *, timeout: float = 30.0) -> Dict[str, Any]:
|
|
45
|
+
return await self._client._request(
|
|
46
|
+
endpoint=endpoint,
|
|
47
|
+
method="POST",
|
|
48
|
+
body=body or {},
|
|
49
|
+
use_gateway=True,
|
|
50
|
+
timeout=timeout,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
async def _get(self, endpoint: str, *, timeout: float = 30.0) -> Dict[str, Any]:
|
|
54
|
+
return await self._client._request(
|
|
55
|
+
endpoint=endpoint,
|
|
56
|
+
method="GET",
|
|
57
|
+
use_gateway=True,
|
|
58
|
+
timeout=timeout,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
async def list_types(self, *, owning_worker: Optional[str] = None, timeout: float = 15.0) -> Dict[str, Any]:
|
|
62
|
+
"""List registered recipe types. ``GET /api/recipe/types``."""
|
|
63
|
+
query = f"?owning_worker={owning_worker}" if owning_worker else ""
|
|
64
|
+
return await self._get(f"/api/recipe/types{query}", timeout=timeout)
|
|
65
|
+
|
|
66
|
+
async def get_type(self, name: str, *, timeout: float = 15.0) -> Dict[str, Any]:
|
|
67
|
+
"""Fetch a registered recipe type's schema. ``GET /api/recipe/types/{name}``."""
|
|
68
|
+
return await self._get(f"/api/recipe/types/{name}", timeout=timeout)
|
|
69
|
+
|
|
70
|
+
async def publish(
|
|
71
|
+
self,
|
|
72
|
+
*,
|
|
73
|
+
type: str,
|
|
74
|
+
tier: str,
|
|
75
|
+
name: str,
|
|
76
|
+
body: str,
|
|
77
|
+
description: Optional[str] = None,
|
|
78
|
+
timeout: float = 30.0,
|
|
79
|
+
) -> Dict[str, Any]:
|
|
80
|
+
"""Publish a recipe. ``POST /api/recipe/recipes/publish``."""
|
|
81
|
+
return await self._post(
|
|
82
|
+
"/api/recipe/recipes/publish",
|
|
83
|
+
_compact({
|
|
84
|
+
"type": type,
|
|
85
|
+
"tier": tier,
|
|
86
|
+
"name": name,
|
|
87
|
+
"body": body,
|
|
88
|
+
"description": description,
|
|
89
|
+
}),
|
|
90
|
+
timeout=timeout,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
async def validate(
|
|
94
|
+
self,
|
|
95
|
+
*,
|
|
96
|
+
type: str,
|
|
97
|
+
body: str,
|
|
98
|
+
timeout: float = 15.0,
|
|
99
|
+
) -> Dict[str, Any]:
|
|
100
|
+
"""Validate a recipe body against its type schema. ``POST /api/recipe/recipes/validate``."""
|
|
101
|
+
return await self._post(
|
|
102
|
+
"/api/recipe/recipes/validate",
|
|
103
|
+
{"type": type, "body": body},
|
|
104
|
+
timeout=timeout,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
async def deprecate(
|
|
108
|
+
self,
|
|
109
|
+
*,
|
|
110
|
+
type: str,
|
|
111
|
+
tier: str,
|
|
112
|
+
name: str,
|
|
113
|
+
version: int,
|
|
114
|
+
reason: Optional[str] = None,
|
|
115
|
+
timeout: float = 30.0,
|
|
116
|
+
) -> Dict[str, Any]:
|
|
117
|
+
"""Mark the current head recipe version deprecated. ``POST /api/recipe/recipes/deprecate``."""
|
|
118
|
+
return await self._post(
|
|
119
|
+
"/api/recipe/recipes/deprecate",
|
|
120
|
+
_compact({
|
|
121
|
+
"type": type,
|
|
122
|
+
"tier": tier,
|
|
123
|
+
"name": name,
|
|
124
|
+
"version": version,
|
|
125
|
+
"reason": reason,
|
|
126
|
+
}),
|
|
127
|
+
timeout=timeout,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
async def list(
|
|
131
|
+
self,
|
|
132
|
+
*,
|
|
133
|
+
type: Optional[str] = None,
|
|
134
|
+
tier: Optional[str] = None,
|
|
135
|
+
name_prefix: Optional[str] = None,
|
|
136
|
+
timeout: float = 15.0,
|
|
137
|
+
) -> Dict[str, Any]:
|
|
138
|
+
"""List recipes filtered by type/tier/name. ``GET /api/recipe/recipes/list``."""
|
|
139
|
+
params: List[str] = []
|
|
140
|
+
if type:
|
|
141
|
+
params.append(f"type={type}")
|
|
142
|
+
if tier:
|
|
143
|
+
params.append(f"tier={tier}")
|
|
144
|
+
if name_prefix:
|
|
145
|
+
params.append(f"name_prefix={name_prefix}")
|
|
146
|
+
query = ("?" + "&".join(params)) if params else ""
|
|
147
|
+
return await self._get(f"/api/recipe/recipes/list{query}", timeout=timeout)
|
|
148
|
+
|
|
149
|
+
async def get(
|
|
150
|
+
self,
|
|
151
|
+
*,
|
|
152
|
+
type: str,
|
|
153
|
+
name: str,
|
|
154
|
+
version: Optional[int] = None,
|
|
155
|
+
tier: Optional[str] = None,
|
|
156
|
+
timeout: float = 15.0,
|
|
157
|
+
) -> Dict[str, Any]:
|
|
158
|
+
"""Resolve a recipe through the three-tier chain. ``GET /api/recipe/recipes/{type}/{name}[@v{N}]``."""
|
|
159
|
+
path = f"/api/recipe/recipes/{type}/{name}"
|
|
160
|
+
if version is not None:
|
|
161
|
+
path += f"@v{version}"
|
|
162
|
+
if tier:
|
|
163
|
+
path += f"?tier={tier}"
|
|
164
|
+
return await self._get(path, timeout=timeout)
|
|
165
|
+
|
|
166
|
+
async def register_type(
|
|
167
|
+
self,
|
|
168
|
+
*,
|
|
169
|
+
name: str,
|
|
170
|
+
owning_worker: str,
|
|
171
|
+
schema_version: int,
|
|
172
|
+
json_schema: Dict[str, Any],
|
|
173
|
+
timeout: float = 15.0,
|
|
174
|
+
) -> Dict[str, Any]:
|
|
175
|
+
"""Register a recipe type. ``POST /api/recipe/types/register``.
|
|
176
|
+
|
|
177
|
+
Owning workers do this on cold start. Normal callers should not need it.
|
|
178
|
+
"""
|
|
179
|
+
return await self._post(
|
|
180
|
+
"/api/recipe/types/register",
|
|
181
|
+
{
|
|
182
|
+
"name": name,
|
|
183
|
+
"owning_worker": owning_worker,
|
|
184
|
+
"schema_version": schema_version,
|
|
185
|
+
"json_schema": json_schema,
|
|
186
|
+
},
|
|
187
|
+
timeout=timeout,
|
|
188
|
+
)
|
dominus/start.py
CHANGED
|
@@ -186,6 +186,10 @@ class Dominus:
|
|
|
186
186
|
from .namespaces.stash import StashNamespace
|
|
187
187
|
self.stash = StashNamespace(self)
|
|
188
188
|
|
|
189
|
+
# Recipe worker (kernel-tier; hosts browser-recipe today, workflow + envoy + others later)
|
|
190
|
+
from .namespaces.recipes import RecipesNamespace
|
|
191
|
+
self.recipes = RecipesNamespace(self)
|
|
192
|
+
|
|
189
193
|
# Cache for JWT public key
|
|
190
194
|
self._public_key_cache = None
|
|
191
195
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
dominus/__init__.py,sha256=
|
|
1
|
+
dominus/__init__.py,sha256=fXMmrG8nn-vuCCSCbWfUYjZTWuTgPPgSlBERSxiba5s,7070
|
|
2
2
|
dominus/errors.py,sha256=NthcR-o1Q1nQsE3ZSHStcW_RdZ8LQ06mPDSenY1txgM,8547
|
|
3
|
-
dominus/start.py,sha256=
|
|
3
|
+
dominus/start.py,sha256=Dn6uN2z0KkiJmM8rOLU20JlslZ-xhOLQb2hcJOzHEYo,49839
|
|
4
4
|
dominus/config/__init__.py,sha256=nvLLNh4dM_MCqcfF3XFS2NnVn44q0RYHEfAPP-2G5To,434
|
|
5
5
|
dominus/config/endpoints.py,sha256=IFioVY3jQ5Mqy65L6rNbEXyPUfYTaXRQkfyGdKv33A8,4140
|
|
6
6
|
dominus/helpers/__init__.py,sha256=cyoBvw1QJugtGt0gYitIz1yxOaMmBa-wMXqbh-fi4PU,61
|
|
@@ -11,13 +11,13 @@ dominus/helpers/core.py,sha256=stpagEgsRpsXFP9_L2M-gJVo3ioSsyZm7zr8zWIyfmA,37991
|
|
|
11
11
|
dominus/helpers/crypto.py,sha256=R1yZittVykTQzGVJdb_uMQuF3Y1uGuQRJHZ1BTWT9lU,3014
|
|
12
12
|
dominus/helpers/sse.py,sha256=8cuQbonEbroho8sZhZ8kmu_IQY2lD_xNLm7FLaREwgU,5325
|
|
13
13
|
dominus/helpers/trace.py,sha256=i0dRYR4Y46LAnQr0Cm5htbyZ0VA4UQCLMx-q2CQQXSc,2686
|
|
14
|
-
dominus/namespaces/__init__.py,sha256=
|
|
14
|
+
dominus/namespaces/__init__.py,sha256=4zOayF2IoRHPCVpm41vBF15eoVsScIXv_BVTLsjU3bU,1494
|
|
15
15
|
dominus/namespaces/admin.py,sha256=qkGoteAJ6cqdNub4zL1mtyxAQtsM3-nUplRSgw2fMZY,1640
|
|
16
16
|
dominus/namespaces/ai.py,sha256=Kr_eY-SkEfC-b1fhVVv40pXn_GHkxRzMGD47WoTgu9M,48555
|
|
17
17
|
dominus/namespaces/artifacts.py,sha256=MgjkjSmUP_5XGTAFU2UQ1VU3Vju3kVuvDqxChosP2J0,22246
|
|
18
18
|
dominus/namespaces/auth.py,sha256=YA61WjeRewatrz6BTPhRC95jDgYk3b2QDlH0xdGUceg,67795
|
|
19
19
|
dominus/namespaces/authority.py,sha256=vfXNc6A-eAeOzSuyMpBmkWjUvFVXvuelrn3O9YcIY9E,76874
|
|
20
|
-
dominus/namespaces/browser.py,sha256=
|
|
20
|
+
dominus/namespaces/browser.py,sha256=mFxQCvwFy5XmSVIXwwOP2B5WpDnm62U-n-nDlCVn_e8,9042
|
|
21
21
|
dominus/namespaces/courier.py,sha256=7ZuwTWzVGBPTnqPV1VqPdme6PkPyhQOddwaI1wxrlE8,8324
|
|
22
22
|
dominus/namespaces/db.py,sha256=dv4IZACziub7OE8i_4q_Z31uVYJglE12TFkFIbFnYjw,15157
|
|
23
23
|
dominus/namespaces/ddl.py,sha256=NTpd3V3595qcBheUZfFq4tQiAZsyYH9O8GR9OZ_czK8,25844
|
|
@@ -29,6 +29,7 @@ dominus/namespaces/jobs.py,sha256=YdiTzajUWtpdhk_jJhOlF0EeFegaRQFiszGSsFLs-Dc,54
|
|
|
29
29
|
dominus/namespaces/logs.py,sha256=uM3yDU2YsqEqOt9eg1I9JyHZdHrFxSQahbknTLhmw_U,22102
|
|
30
30
|
dominus/namespaces/portal.py,sha256=vf0Vu_12yS4_fto7sVCau5vQtghml7Wh7J2-XJnO2zA,15595
|
|
31
31
|
dominus/namespaces/processor.py,sha256=gk-vvWfBTU9LkV34OaB4VdftArhTE67tfhlUtY0YglI,2678
|
|
32
|
+
dominus/namespaces/recipes.py,sha256=xqvm-aKjLy4RrFZFUc_cvr0Q7QelHd7r0OowcU_yny4,6051
|
|
32
33
|
dominus/namespaces/redis.py,sha256=1joYhewLGdN4-OCYJu5rvhsF5yORUUfVtBrgjzLKAzs,19337
|
|
33
34
|
dominus/namespaces/secrets.py,sha256=od8AKgENwW6U-kVfIX3DSphXKeJA6XC-SxbGqsxhhUk,6253
|
|
34
35
|
dominus/namespaces/secure.py,sha256=9idGY5R6k7b-JM1SAF_1Gt-YV5OempyxFBflgLJieLo,7168
|
|
@@ -37,7 +38,7 @@ dominus/namespaces/sync.py,sha256=mGwMNwc_iWoKgS94n1staPdsKBHNvliMG7omokl7Qmk,21
|
|
|
37
38
|
dominus/namespaces/warden.py,sha256=ebbCeBJJwK9uALEj2aDbvWJ5HTlOXOpXJOwzokH1cso,1139
|
|
38
39
|
dominus/namespaces/workflow.py,sha256=1LMzlYoVImtdpnuenJDtpx7dB2wdNVE3tSBFn-ZAyJA,47204
|
|
39
40
|
dominus/services/__init__.py,sha256=LQl5sx6DHhX1xCN3MRoUgffxqwm3Mfm525hijyFods8,43
|
|
40
|
-
dominus_sdk_python-4.6.
|
|
41
|
-
dominus_sdk_python-4.6.
|
|
42
|
-
dominus_sdk_python-4.6.
|
|
43
|
-
dominus_sdk_python-4.6.
|
|
41
|
+
dominus_sdk_python-4.6.2.dist-info/METADATA,sha256=nfp-o802nj5qms1_1exjBlmGebXLKAwYiOSiHKO4_zM,8900
|
|
42
|
+
dominus_sdk_python-4.6.2.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
43
|
+
dominus_sdk_python-4.6.2.dist-info/top_level.txt,sha256=515zxMIbX0DpheRbjvNqKIt_AFqdFjX41jtyp_SqLf4,8
|
|
44
|
+
dominus_sdk_python-4.6.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|