dominus-sdk-python 2.7.0__tar.gz → 2.7.2__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.7.0 → dominus_sdk_python-2.7.2}/PKG-INFO +1 -1
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/__init__.py +1 -1
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/ai.py +226 -94
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/start.py +43 -11
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus_sdk_python.egg-info/PKG-INFO +1 -1
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/pyproject.toml +1 -1
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/README.md +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/config/__init__.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/config/endpoints.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/errors.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/helpers/__init__.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/helpers/auth.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/helpers/cache.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/helpers/core.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/helpers/crypto.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/helpers/sse.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/__init__.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/admin.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/auth.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/courier.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/db.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/ddl.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/fastapi.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/files.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/health.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/logs.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/open.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/oracle/__init__.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/oracle/audio_capture.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/oracle/oracle_websocket.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/oracle/session.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/oracle/types.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/oracle/vad_gate.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/portal.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/redis.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/secrets.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/secure.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/services/__init__.py +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus_sdk_python.egg-info/SOURCES.txt +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus_sdk_python.egg-info/dependency_links.txt +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus_sdk_python.egg-info/requires.txt +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus_sdk_python.egg-info/top_level.txt +0 -0
- {dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/setup.cfg +0 -0
|
@@ -49,11 +49,90 @@ if TYPE_CHECKING:
|
|
|
49
49
|
from ..start import Dominus
|
|
50
50
|
|
|
51
51
|
|
|
52
|
+
# ========================================
|
|
53
|
+
# Gateway-routed API helper
|
|
54
|
+
# ========================================
|
|
55
|
+
|
|
56
|
+
class GatewayMixin:
|
|
57
|
+
"""
|
|
58
|
+
Mixin that provides gateway-routed API calls.
|
|
59
|
+
|
|
60
|
+
All AI namespace methods route through the gateway's /svc/* endpoints
|
|
61
|
+
which proxy to agent-runtime's /api/* endpoints.
|
|
62
|
+
"""
|
|
63
|
+
_client: "Dominus"
|
|
64
|
+
|
|
65
|
+
async def _api(
|
|
66
|
+
self,
|
|
67
|
+
endpoint: str,
|
|
68
|
+
method: str = "POST",
|
|
69
|
+
body: Optional[Dict[str, Any]] = None
|
|
70
|
+
) -> Dict[str, Any]:
|
|
71
|
+
"""Make gateway-routed API request."""
|
|
72
|
+
return await self._client._request(
|
|
73
|
+
endpoint=endpoint,
|
|
74
|
+
method=method,
|
|
75
|
+
body=body,
|
|
76
|
+
use_gateway=True
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
async def _api_stream(
|
|
80
|
+
self,
|
|
81
|
+
endpoint: str,
|
|
82
|
+
body: Optional[Dict[str, Any]] = None,
|
|
83
|
+
on_chunk: Optional[Any] = None,
|
|
84
|
+
timeout: float = 300.0
|
|
85
|
+
):
|
|
86
|
+
"""Make gateway-routed streaming request."""
|
|
87
|
+
async for chunk in self._client._stream_request(
|
|
88
|
+
endpoint=endpoint,
|
|
89
|
+
body=body,
|
|
90
|
+
on_chunk=on_chunk,
|
|
91
|
+
timeout=timeout,
|
|
92
|
+
use_gateway=True
|
|
93
|
+
):
|
|
94
|
+
yield chunk
|
|
95
|
+
|
|
96
|
+
async def _api_upload(
|
|
97
|
+
self,
|
|
98
|
+
endpoint: str,
|
|
99
|
+
file_bytes: bytes,
|
|
100
|
+
filename: str,
|
|
101
|
+
content_type: str = "application/octet-stream",
|
|
102
|
+
additional_fields: Optional[Dict[str, str]] = None,
|
|
103
|
+
timeout: float = 60.0
|
|
104
|
+
) -> Dict[str, Any]:
|
|
105
|
+
"""Make gateway-routed binary upload."""
|
|
106
|
+
return await self._client._binary_upload(
|
|
107
|
+
endpoint=endpoint,
|
|
108
|
+
file_bytes=file_bytes,
|
|
109
|
+
filename=filename,
|
|
110
|
+
content_type=content_type,
|
|
111
|
+
additional_fields=additional_fields,
|
|
112
|
+
timeout=timeout,
|
|
113
|
+
use_gateway=True
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
async def _api_download(
|
|
117
|
+
self,
|
|
118
|
+
endpoint: str,
|
|
119
|
+
body: Optional[Dict[str, Any]] = None,
|
|
120
|
+
timeout: float = 60.0
|
|
121
|
+
) -> bytes:
|
|
122
|
+
"""Make gateway-routed binary download."""
|
|
123
|
+
return await self._client._binary_download(
|
|
124
|
+
endpoint=endpoint,
|
|
125
|
+
body=body,
|
|
126
|
+
timeout=timeout,
|
|
127
|
+
use_gateway=True
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
|
|
52
131
|
# ========================================
|
|
53
132
|
# RAG Sub-namespace
|
|
54
133
|
# ========================================
|
|
55
134
|
|
|
56
|
-
class RagSubNamespace:
|
|
135
|
+
class RagSubNamespace(GatewayMixin):
|
|
57
136
|
"""
|
|
58
137
|
RAG corpus management sub-namespace.
|
|
59
138
|
|
|
@@ -65,7 +144,7 @@ class RagSubNamespace:
|
|
|
65
144
|
|
|
66
145
|
async def list(self) -> List[Dict[str, Any]]:
|
|
67
146
|
"""List all corpora."""
|
|
68
|
-
result = await self.
|
|
147
|
+
result = await self._api(
|
|
69
148
|
endpoint="/api/rag",
|
|
70
149
|
method="GET"
|
|
71
150
|
)
|
|
@@ -91,21 +170,21 @@ class RagSubNamespace:
|
|
|
91
170
|
if embedding_model:
|
|
92
171
|
body["embedding_model"] = embedding_model
|
|
93
172
|
|
|
94
|
-
return await self.
|
|
173
|
+
return await self._api(
|
|
95
174
|
endpoint=f"/api/rag/{slug}/ensure",
|
|
96
175
|
body=body if body else {}
|
|
97
176
|
)
|
|
98
177
|
|
|
99
178
|
async def stats(self, slug: str) -> Dict[str, Any]:
|
|
100
179
|
"""Get corpus statistics."""
|
|
101
|
-
return await self.
|
|
180
|
+
return await self._api(
|
|
102
181
|
endpoint=f"/api/rag/{slug}/stats",
|
|
103
182
|
method="GET"
|
|
104
183
|
)
|
|
105
184
|
|
|
106
185
|
async def drop(self, slug: str) -> Dict[str, Any]:
|
|
107
186
|
"""Drop/delete a corpus."""
|
|
108
|
-
return await self.
|
|
187
|
+
return await self._api(
|
|
109
188
|
endpoint=f"/api/rag/{slug}",
|
|
110
189
|
method="DELETE"
|
|
111
190
|
)
|
|
@@ -122,7 +201,7 @@ class RagSubNamespace:
|
|
|
122
201
|
if category:
|
|
123
202
|
body["category"] = category
|
|
124
203
|
|
|
125
|
-
return await self.
|
|
204
|
+
return await self._api(
|
|
126
205
|
endpoint=f"/api/rag/{slug}/entries",
|
|
127
206
|
body=body
|
|
128
207
|
)
|
|
@@ -132,7 +211,11 @@ class RagSubNamespace:
|
|
|
132
211
|
slug: str,
|
|
133
212
|
identifier: str,
|
|
134
213
|
content: str,
|
|
214
|
+
name: Optional[str] = None,
|
|
215
|
+
description: Optional[str] = None,
|
|
135
216
|
category: Optional[str] = None,
|
|
217
|
+
subcategory: Optional[str] = None,
|
|
218
|
+
source_reference: Optional[Dict[str, Any]] = None,
|
|
136
219
|
metadata: Optional[Dict[str, Any]] = None
|
|
137
220
|
) -> Dict[str, Any]:
|
|
138
221
|
"""
|
|
@@ -141,17 +224,29 @@ class RagSubNamespace:
|
|
|
141
224
|
Args:
|
|
142
225
|
slug: Corpus identifier
|
|
143
226
|
identifier: Entry identifier (unique within corpus)
|
|
144
|
-
content: Text content to embed
|
|
227
|
+
content: Text content to embed (stored as content_markdown)
|
|
228
|
+
name: Optional human-readable name
|
|
229
|
+
description: Optional brief description
|
|
145
230
|
category: Optional category for filtering
|
|
231
|
+
subcategory: Optional subcategory
|
|
232
|
+
source_reference: Optional source attribution
|
|
146
233
|
metadata: Optional metadata dict
|
|
147
234
|
"""
|
|
148
|
-
body: Dict[str, Any] = {"
|
|
235
|
+
body: Dict[str, Any] = {"content_markdown": content}
|
|
236
|
+
if name:
|
|
237
|
+
body["name"] = name
|
|
238
|
+
if description:
|
|
239
|
+
body["description"] = description
|
|
149
240
|
if category:
|
|
150
241
|
body["category"] = category
|
|
242
|
+
if subcategory:
|
|
243
|
+
body["subcategory"] = subcategory
|
|
244
|
+
if source_reference:
|
|
245
|
+
body["source_reference"] = source_reference
|
|
151
246
|
if metadata:
|
|
152
247
|
body["metadata"] = metadata
|
|
153
248
|
|
|
154
|
-
return await self.
|
|
249
|
+
return await self._api(
|
|
155
250
|
endpoint=f"/api/rag/{slug}/{identifier}",
|
|
156
251
|
method="PUT",
|
|
157
252
|
body=body
|
|
@@ -159,14 +254,14 @@ class RagSubNamespace:
|
|
|
159
254
|
|
|
160
255
|
async def get(self, slug: str, identifier: str) -> Dict[str, Any]:
|
|
161
256
|
"""Get a specific entry."""
|
|
162
|
-
return await self.
|
|
257
|
+
return await self._api(
|
|
163
258
|
endpoint=f"/api/rag/{slug}/{identifier}",
|
|
164
259
|
method="GET"
|
|
165
260
|
)
|
|
166
261
|
|
|
167
262
|
async def delete(self, slug: str, identifier: str) -> Dict[str, Any]:
|
|
168
263
|
"""Delete an entry."""
|
|
169
|
-
return await self.
|
|
264
|
+
return await self._api(
|
|
170
265
|
endpoint=f"/api/rag/{slug}/{identifier}",
|
|
171
266
|
method="DELETE"
|
|
172
267
|
)
|
|
@@ -181,11 +276,30 @@ class RagSubNamespace:
|
|
|
181
276
|
|
|
182
277
|
Args:
|
|
183
278
|
slug: Corpus identifier
|
|
184
|
-
entries: List of
|
|
279
|
+
entries: List of entry dicts with:
|
|
280
|
+
- identifier: string (required)
|
|
281
|
+
- content: string (required) - Will be sent as content_markdown
|
|
282
|
+
- name: string (optional)
|
|
283
|
+
- description: string (optional)
|
|
284
|
+
- category: string (optional)
|
|
285
|
+
- subcategory: string (optional)
|
|
286
|
+
- source_reference: dict (optional)
|
|
287
|
+
- metadata: dict (optional)
|
|
288
|
+
|
|
289
|
+
Returns:
|
|
290
|
+
Dict with "processed", "failed", "errors" counts
|
|
185
291
|
"""
|
|
186
|
-
|
|
292
|
+
# Transform 'content' to 'content_markdown' for API compatibility
|
|
293
|
+
transformed = []
|
|
294
|
+
for entry in entries:
|
|
295
|
+
e = dict(entry)
|
|
296
|
+
if "content" in e and "content_markdown" not in e:
|
|
297
|
+
e["content_markdown"] = e.pop("content")
|
|
298
|
+
transformed.append(e)
|
|
299
|
+
|
|
300
|
+
return await self._api(
|
|
187
301
|
endpoint=f"/api/rag/{slug}/bulk",
|
|
188
|
-
body={"entries":
|
|
302
|
+
body={"entries": transformed}
|
|
189
303
|
)
|
|
190
304
|
|
|
191
305
|
async def search(
|
|
@@ -222,7 +336,7 @@ class RagSubNamespace:
|
|
|
222
336
|
if filters:
|
|
223
337
|
body["filters"] = filters
|
|
224
338
|
|
|
225
|
-
result = await self.
|
|
339
|
+
result = await self._api(
|
|
226
340
|
endpoint=f"/api/rag/{slug}/search",
|
|
227
341
|
body=body
|
|
228
342
|
)
|
|
@@ -251,7 +365,7 @@ class RagSubNamespace:
|
|
|
251
365
|
if rerank_model:
|
|
252
366
|
body["rerank_model"] = rerank_model
|
|
253
367
|
|
|
254
|
-
result = await self.
|
|
368
|
+
result = await self._api(
|
|
255
369
|
endpoint=f"/api/rag/{slug}/search/rerank",
|
|
256
370
|
body=body
|
|
257
371
|
)
|
|
@@ -277,7 +391,7 @@ class RagSubNamespace:
|
|
|
277
391
|
chunk_size: Chunk size for splitting (default: 1000 chars)
|
|
278
392
|
chunk_overlap: Overlap between chunks (default: 200 chars)
|
|
279
393
|
"""
|
|
280
|
-
return await self.
|
|
394
|
+
return await self._api_upload(
|
|
281
395
|
endpoint=f"/api/rag/{slug}/ingest",
|
|
282
396
|
file_bytes=content,
|
|
283
397
|
filename=filename,
|
|
@@ -290,7 +404,7 @@ class RagSubNamespace:
|
|
|
290
404
|
|
|
291
405
|
async def delete_document(self, slug: str, document_id: str) -> Dict[str, Any]:
|
|
292
406
|
"""Delete a document and all its chunks."""
|
|
293
|
-
return await self.
|
|
407
|
+
return await self._api(
|
|
294
408
|
endpoint=f"/api/rag/{slug}/document/{document_id}",
|
|
295
409
|
method="DELETE"
|
|
296
410
|
)
|
|
@@ -300,7 +414,7 @@ class RagSubNamespace:
|
|
|
300
414
|
# Artifacts Sub-namespace
|
|
301
415
|
# ========================================
|
|
302
416
|
|
|
303
|
-
class ArtifactsSubNamespace:
|
|
417
|
+
class ArtifactsSubNamespace(GatewayMixin):
|
|
304
418
|
"""
|
|
305
419
|
Artifacts sub-namespace for conversation artifact management.
|
|
306
420
|
"""
|
|
@@ -311,16 +425,12 @@ class ArtifactsSubNamespace:
|
|
|
311
425
|
async def get(
|
|
312
426
|
self,
|
|
313
427
|
artifact_id: str,
|
|
314
|
-
conversation_id:
|
|
428
|
+
conversation_id: str
|
|
315
429
|
) -> Dict[str, Any]:
|
|
316
430
|
"""Get artifact by ID."""
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
return await self._client._request(
|
|
322
|
-
endpoint=f"/api/agent/artifacts/{artifact_id}",
|
|
323
|
-
body=body
|
|
431
|
+
return await self._api(
|
|
432
|
+
endpoint=f"/api/agent/artifacts/{artifact_id}?conversation_id={conversation_id}",
|
|
433
|
+
method="GET"
|
|
324
434
|
)
|
|
325
435
|
|
|
326
436
|
async def create(
|
|
@@ -328,67 +438,54 @@ class ArtifactsSubNamespace:
|
|
|
328
438
|
name: str,
|
|
329
439
|
content: str,
|
|
330
440
|
conversation_id: str,
|
|
331
|
-
artifact_type: str = "text",
|
|
441
|
+
artifact_type: str = "text/plain",
|
|
442
|
+
is_base64: bool = False,
|
|
332
443
|
metadata: Optional[Dict[str, Any]] = None
|
|
333
444
|
) -> Dict[str, Any]:
|
|
334
445
|
"""
|
|
335
446
|
Create a new artifact.
|
|
336
447
|
|
|
337
448
|
Args:
|
|
338
|
-
name: Artifact
|
|
339
|
-
content: Artifact content (text or base64 for binary)
|
|
449
|
+
name: Artifact key/filename
|
|
450
|
+
content: Artifact content (text or base64-encoded for binary)
|
|
340
451
|
conversation_id: Associated conversation ID
|
|
341
|
-
artifact_type:
|
|
342
|
-
|
|
452
|
+
artifact_type: MIME content type (e.g., "text/plain", "text/html", "image/png")
|
|
453
|
+
is_base64: If True, content is base64-encoded binary
|
|
454
|
+
metadata: Optional metadata dict (not stored, for SDK use)
|
|
343
455
|
"""
|
|
344
456
|
body: Dict[str, Any] = {
|
|
345
|
-
"
|
|
457
|
+
"key": name,
|
|
346
458
|
"content": content,
|
|
347
459
|
"conversation_id": conversation_id,
|
|
348
|
-
"
|
|
460
|
+
"content_type": artifact_type,
|
|
461
|
+
"is_base64": is_base64
|
|
349
462
|
}
|
|
350
|
-
if metadata:
|
|
351
|
-
body["metadata"] = metadata
|
|
352
463
|
|
|
353
|
-
return await self.
|
|
464
|
+
return await self._api(
|
|
354
465
|
endpoint="/api/agent/artifacts",
|
|
355
466
|
body=body
|
|
356
467
|
)
|
|
357
468
|
|
|
358
469
|
async def list(
|
|
359
470
|
self,
|
|
360
|
-
conversation_id: str
|
|
361
|
-
limit: int = 100,
|
|
362
|
-
offset: int = 0
|
|
471
|
+
conversation_id: str
|
|
363
472
|
) -> List[Dict[str, Any]]:
|
|
364
473
|
"""List artifacts for a conversation."""
|
|
365
|
-
|
|
366
|
-
"conversation_id"
|
|
367
|
-
"
|
|
368
|
-
"offset": offset
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
result = await self._client._request(
|
|
372
|
-
endpoint="/api/agent/artifacts",
|
|
373
|
-
method="GET",
|
|
374
|
-
body=body
|
|
474
|
+
result = await self._api(
|
|
475
|
+
endpoint=f"/api/agent/artifacts?conversation_id={conversation_id}",
|
|
476
|
+
method="GET"
|
|
375
477
|
)
|
|
376
478
|
return result.get("artifacts", result) if isinstance(result, dict) else result
|
|
377
479
|
|
|
378
480
|
async def delete(
|
|
379
481
|
self,
|
|
380
482
|
artifact_id: str,
|
|
381
|
-
conversation_id:
|
|
483
|
+
conversation_id: str
|
|
382
484
|
) -> Dict[str, Any]:
|
|
383
485
|
"""Delete an artifact."""
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
return await self._client._request(
|
|
389
|
-
endpoint=f"/api/agent/artifacts/{artifact_id}",
|
|
390
|
-
method="DELETE",
|
|
391
|
-
body=body if body else None
|
|
486
|
+
return await self._api(
|
|
487
|
+
endpoint=f"/api/agent/artifacts/{artifact_id}?conversation_id={conversation_id}",
|
|
488
|
+
method="DELETE"
|
|
392
489
|
)
|
|
393
490
|
|
|
394
491
|
|
|
@@ -396,7 +493,7 @@ class ArtifactsSubNamespace:
|
|
|
396
493
|
# Results Sub-namespace
|
|
397
494
|
# ========================================
|
|
398
495
|
|
|
399
|
-
class ResultsSubNamespace:
|
|
496
|
+
class ResultsSubNamespace(GatewayMixin):
|
|
400
497
|
"""
|
|
401
498
|
Async results sub-namespace for polling async operation results.
|
|
402
499
|
"""
|
|
@@ -415,7 +512,7 @@ class ResultsSubNamespace:
|
|
|
415
512
|
Dict with "status" (pending|running|completed|failed),
|
|
416
513
|
"result" (if completed), "error" (if failed)
|
|
417
514
|
"""
|
|
418
|
-
return await self.
|
|
515
|
+
return await self._api(
|
|
419
516
|
endpoint=f"/api/results/{result_key}",
|
|
420
517
|
method="GET"
|
|
421
518
|
)
|
|
@@ -460,7 +557,7 @@ class ResultsSubNamespace:
|
|
|
460
557
|
# Workflow Sub-namespace
|
|
461
558
|
# ========================================
|
|
462
559
|
|
|
463
|
-
class WorkflowSubNamespace:
|
|
560
|
+
class WorkflowSubNamespace(GatewayMixin):
|
|
464
561
|
"""
|
|
465
562
|
Multi-agent workflow orchestration sub-namespace.
|
|
466
563
|
"""
|
|
@@ -499,7 +596,7 @@ class WorkflowSubNamespace:
|
|
|
499
596
|
if webhook_url:
|
|
500
597
|
body["webhook_url"] = webhook_url
|
|
501
598
|
|
|
502
|
-
return await self.
|
|
599
|
+
return await self._api(
|
|
503
600
|
endpoint="/api/orchestration/execute",
|
|
504
601
|
body=body
|
|
505
602
|
)
|
|
@@ -517,7 +614,7 @@ class WorkflowSubNamespace:
|
|
|
517
614
|
Returns:
|
|
518
615
|
Dict with "valid", "errors" (if invalid)
|
|
519
616
|
"""
|
|
520
|
-
return await self.
|
|
617
|
+
return await self._api(
|
|
521
618
|
endpoint="/api/orchestration/validate",
|
|
522
619
|
body={"definition": workflow_definition}
|
|
523
620
|
)
|
|
@@ -529,7 +626,7 @@ class WorkflowSubNamespace:
|
|
|
529
626
|
offset: int = 0
|
|
530
627
|
) -> List[Dict[str, Any]]:
|
|
531
628
|
"""Get messages from an execution."""
|
|
532
|
-
result = await self.
|
|
629
|
+
result = await self._api(
|
|
533
630
|
endpoint=f"/api/orchestration/messages/{execution_id}",
|
|
534
631
|
body={"limit": limit, "offset": offset}
|
|
535
632
|
)
|
|
@@ -545,7 +642,7 @@ class WorkflowSubNamespace:
|
|
|
545
642
|
if from_timestamp:
|
|
546
643
|
body["from"] = from_timestamp
|
|
547
644
|
|
|
548
|
-
result = await self.
|
|
645
|
+
result = await self._api(
|
|
549
646
|
endpoint=f"/api/orchestration/events/{execution_id}",
|
|
550
647
|
body=body if body else None
|
|
551
648
|
)
|
|
@@ -553,14 +650,14 @@ class WorkflowSubNamespace:
|
|
|
553
650
|
|
|
554
651
|
async def status(self, execution_id: str) -> Dict[str, Any]:
|
|
555
652
|
"""Get execution status."""
|
|
556
|
-
return await self.
|
|
653
|
+
return await self._api(
|
|
557
654
|
endpoint=f"/api/orchestration/status/{execution_id}",
|
|
558
655
|
method="GET"
|
|
559
656
|
)
|
|
560
657
|
|
|
561
658
|
async def output(self, execution_id: str) -> Dict[str, Any]:
|
|
562
659
|
"""Get final execution output."""
|
|
563
|
-
return await self.
|
|
660
|
+
return await self._api(
|
|
564
661
|
endpoint=f"/api/orchestration/output/{execution_id}",
|
|
565
662
|
method="GET"
|
|
566
663
|
)
|
|
@@ -570,7 +667,7 @@ class WorkflowSubNamespace:
|
|
|
570
667
|
# Main AI Namespace
|
|
571
668
|
# ========================================
|
|
572
669
|
|
|
573
|
-
class AiNamespace:
|
|
670
|
+
class AiNamespace(GatewayMixin):
|
|
574
671
|
"""
|
|
575
672
|
Unified AI namespace for agent-runtime operations.
|
|
576
673
|
|
|
@@ -656,7 +753,7 @@ class AiNamespace:
|
|
|
656
753
|
if tool_endpoint:
|
|
657
754
|
body["tool_endpoint"] = tool_endpoint
|
|
658
755
|
|
|
659
|
-
return await self.
|
|
756
|
+
return await self._api(
|
|
660
757
|
endpoint="/api/agent/run",
|
|
661
758
|
body=body
|
|
662
759
|
)
|
|
@@ -722,7 +819,7 @@ class AiNamespace:
|
|
|
722
819
|
if tool_endpoint:
|
|
723
820
|
body["tool_endpoint"] = tool_endpoint
|
|
724
821
|
|
|
725
|
-
async for chunk in self.
|
|
822
|
+
async for chunk in self._api_stream(
|
|
726
823
|
endpoint="/api/agent/stream",
|
|
727
824
|
body=body,
|
|
728
825
|
on_chunk=on_chunk,
|
|
@@ -796,7 +893,7 @@ class AiNamespace:
|
|
|
796
893
|
if webhook_url:
|
|
797
894
|
body["webhook_url"] = webhook_url
|
|
798
895
|
|
|
799
|
-
return await self.
|
|
896
|
+
return await self._api(
|
|
800
897
|
endpoint="/api/agent/run-async",
|
|
801
898
|
body=body
|
|
802
899
|
)
|
|
@@ -820,11 +917,11 @@ class AiNamespace:
|
|
|
820
917
|
Returns:
|
|
821
918
|
List of history messages
|
|
822
919
|
"""
|
|
823
|
-
result = await self.
|
|
824
|
-
endpoint=f"/api/agent/history/{conversation_id}",
|
|
825
|
-
|
|
920
|
+
result = await self._api(
|
|
921
|
+
endpoint=f"/api/agent/history/{conversation_id}?limit={limit}",
|
|
922
|
+
method="GET"
|
|
826
923
|
)
|
|
827
|
-
return result.get("
|
|
924
|
+
return result.get("messages", result) if isinstance(result, dict) else result
|
|
828
925
|
|
|
829
926
|
# ========================================
|
|
830
927
|
# LLM Completions
|
|
@@ -832,58 +929,79 @@ class AiNamespace:
|
|
|
832
929
|
|
|
833
930
|
async def complete(
|
|
834
931
|
self,
|
|
835
|
-
messages: List[Dict[str, Any]],
|
|
932
|
+
messages: Optional[List[Dict[str, Any]]] = None,
|
|
836
933
|
provider: str = "claude",
|
|
837
934
|
model: str = "claude-sonnet-4-5",
|
|
838
935
|
conversation_id: Optional[str] = None,
|
|
839
936
|
temperature: float = 0.7,
|
|
840
937
|
max_tokens: Optional[int] = None,
|
|
841
938
|
system_prompt: Optional[str] = None,
|
|
939
|
+
user_prompt: Optional[str] = None,
|
|
842
940
|
timeout: float = 120.0
|
|
843
941
|
) -> Dict[str, Any]:
|
|
844
942
|
"""
|
|
845
943
|
Blocking LLM completion.
|
|
846
944
|
|
|
847
945
|
Args:
|
|
848
|
-
messages: List of message dicts with "role" and "content"
|
|
946
|
+
messages: List of message dicts with "role" and "content" (optional)
|
|
849
947
|
provider: LLM provider ("claude" or "openai")
|
|
850
948
|
model: Model identifier
|
|
851
949
|
conversation_id: Optional conversation ID
|
|
852
950
|
temperature: Temperature (0-2, default: 0.7)
|
|
853
951
|
max_tokens: Maximum tokens to generate
|
|
854
|
-
system_prompt:
|
|
952
|
+
system_prompt: System prompt (required if messages not provided)
|
|
953
|
+
user_prompt: User prompt (required if messages not provided)
|
|
855
954
|
timeout: Request timeout in seconds
|
|
856
955
|
|
|
857
956
|
Returns:
|
|
858
957
|
Dict with "content", "model", "usage", etc.
|
|
958
|
+
|
|
959
|
+
Note:
|
|
960
|
+
Either provide `messages` OR both `system_prompt` and `user_prompt`.
|
|
961
|
+
If messages provided, the last user message becomes user_prompt,
|
|
962
|
+
and system messages become system_prompt.
|
|
859
963
|
"""
|
|
964
|
+
# Convert messages to system_prompt/user_prompt if needed
|
|
965
|
+
if messages and not user_prompt:
|
|
966
|
+
for msg in messages:
|
|
967
|
+
if msg.get("role") == "system":
|
|
968
|
+
system_prompt = msg.get("content", system_prompt)
|
|
969
|
+
elif msg.get("role") == "user":
|
|
970
|
+
user_prompt = msg.get("content")
|
|
971
|
+
|
|
972
|
+
if not system_prompt:
|
|
973
|
+
system_prompt = "You are a helpful assistant."
|
|
974
|
+
|
|
975
|
+
if not user_prompt:
|
|
976
|
+
raise ValueError("Either 'messages' with a user message or 'user_prompt' is required")
|
|
977
|
+
|
|
860
978
|
body: Dict[str, Any] = {
|
|
861
|
-
"messages": messages,
|
|
862
979
|
"provider": provider,
|
|
863
980
|
"model": model,
|
|
981
|
+
"system_prompt": system_prompt,
|
|
982
|
+
"user_prompt": user_prompt,
|
|
864
983
|
"temperature": temperature
|
|
865
984
|
}
|
|
866
985
|
if conversation_id:
|
|
867
986
|
body["conversation_id"] = conversation_id
|
|
868
987
|
if max_tokens:
|
|
869
988
|
body["max_tokens"] = max_tokens
|
|
870
|
-
if system_prompt:
|
|
871
|
-
body["system_prompt"] = system_prompt
|
|
872
989
|
|
|
873
|
-
return await self.
|
|
990
|
+
return await self._api(
|
|
874
991
|
endpoint="/api/llm/complete",
|
|
875
992
|
body=body
|
|
876
993
|
)
|
|
877
994
|
|
|
878
995
|
async def complete_stream(
|
|
879
996
|
self,
|
|
880
|
-
messages: List[Dict[str, Any]],
|
|
997
|
+
messages: Optional[List[Dict[str, Any]]] = None,
|
|
881
998
|
provider: str = "claude",
|
|
882
999
|
model: str = "claude-sonnet-4-5",
|
|
883
1000
|
conversation_id: Optional[str] = None,
|
|
884
1001
|
temperature: float = 0.7,
|
|
885
1002
|
max_tokens: Optional[int] = None,
|
|
886
1003
|
system_prompt: Optional[str] = None,
|
|
1004
|
+
user_prompt: Optional[str] = None,
|
|
887
1005
|
on_chunk: Optional[Callable[[Dict[str, Any]], None]] = None,
|
|
888
1006
|
timeout: float = 120.0
|
|
889
1007
|
) -> AsyncGenerator[Dict[str, Any], None]:
|
|
@@ -891,33 +1009,47 @@ class AiNamespace:
|
|
|
891
1009
|
Streaming LLM completion.
|
|
892
1010
|
|
|
893
1011
|
Args:
|
|
894
|
-
messages: List of message dicts
|
|
1012
|
+
messages: List of message dicts (optional)
|
|
895
1013
|
provider: LLM provider
|
|
896
1014
|
model: Model identifier
|
|
897
1015
|
conversation_id: Optional conversation ID
|
|
898
1016
|
temperature: Temperature (0-2)
|
|
899
1017
|
max_tokens: Maximum tokens
|
|
900
|
-
system_prompt:
|
|
1018
|
+
system_prompt: System prompt (required if messages not provided)
|
|
1019
|
+
user_prompt: User prompt (required if messages not provided)
|
|
901
1020
|
on_chunk: Optional callback for each chunk
|
|
902
1021
|
timeout: Request timeout
|
|
903
1022
|
|
|
904
1023
|
Yields:
|
|
905
1024
|
Streaming chunks with "content" delta
|
|
906
1025
|
"""
|
|
1026
|
+
# Convert messages to system_prompt/user_prompt if needed
|
|
1027
|
+
if messages and not user_prompt:
|
|
1028
|
+
for msg in messages:
|
|
1029
|
+
if msg.get("role") == "system":
|
|
1030
|
+
system_prompt = msg.get("content", system_prompt)
|
|
1031
|
+
elif msg.get("role") == "user":
|
|
1032
|
+
user_prompt = msg.get("content")
|
|
1033
|
+
|
|
1034
|
+
if not system_prompt:
|
|
1035
|
+
system_prompt = "You are a helpful assistant."
|
|
1036
|
+
|
|
1037
|
+
if not user_prompt:
|
|
1038
|
+
raise ValueError("Either 'messages' with a user message or 'user_prompt' is required")
|
|
1039
|
+
|
|
907
1040
|
body: Dict[str, Any] = {
|
|
908
|
-
"messages": messages,
|
|
909
1041
|
"provider": provider,
|
|
910
1042
|
"model": model,
|
|
1043
|
+
"system_prompt": system_prompt,
|
|
1044
|
+
"user_prompt": user_prompt,
|
|
911
1045
|
"temperature": temperature
|
|
912
1046
|
}
|
|
913
1047
|
if conversation_id:
|
|
914
1048
|
body["conversation_id"] = conversation_id
|
|
915
1049
|
if max_tokens:
|
|
916
1050
|
body["max_tokens"] = max_tokens
|
|
917
|
-
if system_prompt:
|
|
918
|
-
body["system_prompt"] = system_prompt
|
|
919
1051
|
|
|
920
|
-
async for chunk in self.
|
|
1052
|
+
async for chunk in self._api_stream(
|
|
921
1053
|
endpoint="/api/llm/stream",
|
|
922
1054
|
body=body,
|
|
923
1055
|
on_chunk=on_chunk,
|
|
@@ -970,7 +1102,7 @@ class AiNamespace:
|
|
|
970
1102
|
if webhook_url:
|
|
971
1103
|
body["webhook_url"] = webhook_url
|
|
972
1104
|
|
|
973
|
-
return await self.
|
|
1105
|
+
return await self._api(
|
|
974
1106
|
endpoint="/api/llm/complete-async",
|
|
975
1107
|
body=body
|
|
976
1108
|
)
|
|
@@ -996,7 +1128,7 @@ class AiNamespace:
|
|
|
996
1128
|
Returns:
|
|
997
1129
|
Dict with "text", "confidence", "language", "duration"
|
|
998
1130
|
"""
|
|
999
|
-
return await self.
|
|
1131
|
+
return await self._api_upload(
|
|
1000
1132
|
endpoint="/api/agent/stt",
|
|
1001
1133
|
file_bytes=audio,
|
|
1002
1134
|
filename=f"audio.{format}",
|
|
@@ -1023,7 +1155,7 @@ class AiNamespace:
|
|
|
1023
1155
|
Returns:
|
|
1024
1156
|
Raw audio bytes (NOT base64 encoded)
|
|
1025
1157
|
"""
|
|
1026
|
-
return await self.
|
|
1158
|
+
return await self._api_download(
|
|
1027
1159
|
endpoint="/api/agent/tts",
|
|
1028
1160
|
body={
|
|
1029
1161
|
"text": text,
|
|
@@ -1070,7 +1202,7 @@ class AiNamespace:
|
|
|
1070
1202
|
if context:
|
|
1071
1203
|
body["context"] = context
|
|
1072
1204
|
|
|
1073
|
-
return await self.
|
|
1205
|
+
return await self._api(
|
|
1074
1206
|
endpoint="/api/session/setup",
|
|
1075
1207
|
body=body
|
|
1076
1208
|
)
|
|
@@ -59,15 +59,17 @@ from typing import Optional, Any, Dict, List
|
|
|
59
59
|
_VALIDATED = False
|
|
60
60
|
_TOKEN: Optional[str] = None
|
|
61
61
|
_BASE_URL: Optional[str] = None
|
|
62
|
+
_GATEWAY_URL: Optional[str] = None
|
|
62
63
|
_VALIDATION_ERROR: Optional[str] = None
|
|
63
64
|
|
|
64
65
|
|
|
65
66
|
# === MODULE-LEVEL INITIALIZATION ===
|
|
66
67
|
from .helpers.auth import _resolve_token
|
|
67
|
-
from .config.endpoints import BASE_URL
|
|
68
|
+
from .config.endpoints import BASE_URL, GATEWAY_URL
|
|
68
69
|
|
|
69
70
|
_TOKEN = _resolve_token()
|
|
70
71
|
_BASE_URL = BASE_URL
|
|
72
|
+
_GATEWAY_URL = GATEWAY_URL
|
|
71
73
|
|
|
72
74
|
# Initialize cache encryption
|
|
73
75
|
from .helpers.cache import dominus_cache
|
|
@@ -365,10 +367,11 @@ class Dominus:
|
|
|
365
367
|
endpoint: str,
|
|
366
368
|
method: str = "POST",
|
|
367
369
|
body: Optional[Dict[str, Any]] = None,
|
|
368
|
-
user_token: Optional[str] = None
|
|
370
|
+
user_token: Optional[str] = None,
|
|
371
|
+
use_gateway: bool = False
|
|
369
372
|
) -> Dict[str, Any]:
|
|
370
373
|
"""
|
|
371
|
-
Make an HTTP request to the orchestrator.
|
|
374
|
+
Make an HTTP request to the orchestrator or gateway.
|
|
372
375
|
|
|
373
376
|
If user_token is provided, uses that JWT directly (for user-authenticated requests).
|
|
374
377
|
Otherwise, uses the service token flow (PSK -> JWT).
|
|
@@ -378,6 +381,7 @@ class Dominus:
|
|
|
378
381
|
method: HTTP method (GET, POST, PUT, DELETE)
|
|
379
382
|
body: Request body (will be base64-encoded)
|
|
380
383
|
user_token: Optional user JWT for user-authenticated requests
|
|
384
|
+
use_gateway: If True, route through gateway (/api/* -> /svc/*)
|
|
381
385
|
|
|
382
386
|
Returns:
|
|
383
387
|
Response data dict
|
|
@@ -391,6 +395,10 @@ class Dominus:
|
|
|
391
395
|
def _b64_decode(s: str) -> dict:
|
|
392
396
|
return json.loads(base64.b64decode(s.encode('utf-8')).decode('utf-8'))
|
|
393
397
|
|
|
398
|
+
# Transform endpoint for gateway routing
|
|
399
|
+
if use_gateway and endpoint.startswith("/api/"):
|
|
400
|
+
endpoint = "/svc/" + endpoint[5:] # /api/llm/complete -> /svc/llm/complete
|
|
401
|
+
|
|
394
402
|
# Determine which JWT to use
|
|
395
403
|
if user_token:
|
|
396
404
|
# Use the provided user JWT directly (no validation needed - orchestrator validates it)
|
|
@@ -426,8 +434,11 @@ class Dominus:
|
|
|
426
434
|
# Prepare body
|
|
427
435
|
body_b64 = _b64_encode(body or {})
|
|
428
436
|
|
|
437
|
+
# Select base URL
|
|
438
|
+
base_url = _GATEWAY_URL if use_gateway else _BASE_URL
|
|
439
|
+
|
|
429
440
|
# Make request
|
|
430
|
-
async with httpx.AsyncClient(base_url=
|
|
441
|
+
async with httpx.AsyncClient(base_url=base_url, headers=headers, timeout=30.0) as client:
|
|
431
442
|
if method == "GET":
|
|
432
443
|
response = await client.get(endpoint)
|
|
433
444
|
elif method == "DELETE":
|
|
@@ -454,16 +465,18 @@ class Dominus:
|
|
|
454
465
|
endpoint: str,
|
|
455
466
|
body: Optional[Dict[str, Any]] = None,
|
|
456
467
|
on_chunk: Optional[Any] = None,
|
|
457
|
-
timeout: float = 300.0
|
|
468
|
+
timeout: float = 300.0,
|
|
469
|
+
use_gateway: bool = False
|
|
458
470
|
):
|
|
459
471
|
"""
|
|
460
|
-
Make an SSE streaming request to the orchestrator.
|
|
472
|
+
Make an SSE streaming request to the orchestrator or gateway.
|
|
461
473
|
|
|
462
474
|
Args:
|
|
463
475
|
endpoint: API endpoint path (e.g., "/api/agent/stream")
|
|
464
476
|
body: Request body (will be base64-encoded)
|
|
465
477
|
on_chunk: Optional callback for each chunk
|
|
466
478
|
timeout: Request timeout in seconds (default: 300s for long operations)
|
|
479
|
+
use_gateway: If True, route through gateway (/api/* -> /svc/*)
|
|
467
480
|
|
|
468
481
|
Yields:
|
|
469
482
|
Parsed JSON chunks from SSE stream
|
|
@@ -474,6 +487,10 @@ class Dominus:
|
|
|
474
487
|
def _b64_encode(d: dict) -> str:
|
|
475
488
|
return base64.b64encode(json.dumps(d).encode()).decode()
|
|
476
489
|
|
|
490
|
+
# Transform endpoint for gateway routing
|
|
491
|
+
if use_gateway and endpoint.startswith("/api/"):
|
|
492
|
+
endpoint = "/svc/" + endpoint[5:]
|
|
493
|
+
|
|
477
494
|
# Validate and get JWT
|
|
478
495
|
if _VALIDATION_ERROR:
|
|
479
496
|
raise RuntimeError(_VALIDATION_ERROR)
|
|
@@ -499,7 +516,8 @@ class Dominus:
|
|
|
499
516
|
|
|
500
517
|
from .helpers.sse import stream_sse
|
|
501
518
|
|
|
502
|
-
|
|
519
|
+
base_url = _GATEWAY_URL if use_gateway else _BASE_URL
|
|
520
|
+
async with httpx.AsyncClient(base_url=base_url, timeout=timeout) as client:
|
|
503
521
|
async with client.stream("POST", endpoint, content=body_b64, headers=headers) as response:
|
|
504
522
|
response.raise_for_status()
|
|
505
523
|
async for chunk in stream_sse(response, on_chunk):
|
|
@@ -512,7 +530,8 @@ class Dominus:
|
|
|
512
530
|
filename: str,
|
|
513
531
|
content_type: str = "application/octet-stream",
|
|
514
532
|
additional_fields: Optional[Dict[str, str]] = None,
|
|
515
|
-
timeout: float = 60.0
|
|
533
|
+
timeout: float = 60.0,
|
|
534
|
+
use_gateway: bool = False
|
|
516
535
|
) -> Dict[str, Any]:
|
|
517
536
|
"""
|
|
518
537
|
Upload binary file via multipart/form-data (no base64 encoding).
|
|
@@ -526,6 +545,7 @@ class Dominus:
|
|
|
526
545
|
content_type: MIME type (default: application/octet-stream)
|
|
527
546
|
additional_fields: Optional additional form fields
|
|
528
547
|
timeout: Request timeout in seconds
|
|
548
|
+
use_gateway: If True, route through gateway (/api/* -> /svc/*)
|
|
529
549
|
|
|
530
550
|
Returns:
|
|
531
551
|
Response data dict
|
|
@@ -535,6 +555,10 @@ class Dominus:
|
|
|
535
555
|
def _b64_decode(s: str) -> dict:
|
|
536
556
|
return json.loads(base64.b64decode(s.encode('utf-8')).decode('utf-8'))
|
|
537
557
|
|
|
558
|
+
# Transform endpoint for gateway routing
|
|
559
|
+
if use_gateway and endpoint.startswith("/api/"):
|
|
560
|
+
endpoint = "/svc/" + endpoint[5:]
|
|
561
|
+
|
|
538
562
|
if _VALIDATION_ERROR:
|
|
539
563
|
raise RuntimeError(_VALIDATION_ERROR)
|
|
540
564
|
|
|
@@ -557,7 +581,8 @@ class Dominus:
|
|
|
557
581
|
files = {"file": (filename, file_bytes, content_type)}
|
|
558
582
|
data = additional_fields or {}
|
|
559
583
|
|
|
560
|
-
|
|
584
|
+
base_url = _GATEWAY_URL if use_gateway else _BASE_URL
|
|
585
|
+
async with httpx.AsyncClient(base_url=base_url, headers=headers, timeout=timeout) as client:
|
|
561
586
|
response = await client.post(endpoint, files=files, data=data)
|
|
562
587
|
|
|
563
588
|
response.raise_for_status()
|
|
@@ -578,7 +603,8 @@ class Dominus:
|
|
|
578
603
|
self,
|
|
579
604
|
endpoint: str,
|
|
580
605
|
body: Optional[Dict[str, Any]] = None,
|
|
581
|
-
timeout: float = 60.0
|
|
606
|
+
timeout: float = 60.0,
|
|
607
|
+
use_gateway: bool = False
|
|
582
608
|
) -> bytes:
|
|
583
609
|
"""
|
|
584
610
|
Download binary content (no base64 encoding in response).
|
|
@@ -589,6 +615,7 @@ class Dominus:
|
|
|
589
615
|
endpoint: API endpoint path (e.g., "/api/agent/tts")
|
|
590
616
|
body: Request body (will be base64-encoded for auth)
|
|
591
617
|
timeout: Request timeout in seconds
|
|
618
|
+
use_gateway: If True, route through gateway (/api/* -> /svc/*)
|
|
592
619
|
|
|
593
620
|
Returns:
|
|
594
621
|
Raw binary bytes
|
|
@@ -598,6 +625,10 @@ class Dominus:
|
|
|
598
625
|
def _b64_encode(d: dict) -> str:
|
|
599
626
|
return base64.b64encode(json.dumps(d).encode()).decode()
|
|
600
627
|
|
|
628
|
+
# Transform endpoint for gateway routing
|
|
629
|
+
if use_gateway and endpoint.startswith("/api/"):
|
|
630
|
+
endpoint = "/svc/" + endpoint[5:]
|
|
631
|
+
|
|
601
632
|
if _VALIDATION_ERROR:
|
|
602
633
|
raise RuntimeError(_VALIDATION_ERROR)
|
|
603
634
|
|
|
@@ -620,7 +651,8 @@ class Dominus:
|
|
|
620
651
|
|
|
621
652
|
body_b64 = _b64_encode(body or {})
|
|
622
653
|
|
|
623
|
-
|
|
654
|
+
base_url = _GATEWAY_URL if use_gateway else _BASE_URL
|
|
655
|
+
async with httpx.AsyncClient(base_url=base_url, headers=headers, timeout=timeout) as client:
|
|
624
656
|
response = await client.post(endpoint, content=body_b64)
|
|
625
657
|
|
|
626
658
|
response.raise_for_status()
|
|
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.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/oracle/audio_capture.py
RENAMED
|
File without changes
|
{dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus/namespaces/oracle/oracle_websocket.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
|
{dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus_sdk_python.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus_sdk_python.egg-info/requires.txt
RENAMED
|
File without changes
|
{dominus_sdk_python-2.7.0 → dominus_sdk_python-2.7.2}/dominus_sdk_python.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|