dominus-sdk-python-dev 2.3.0__py3-none-any.whl → 2.5.0__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 +82 -5
- dominus/helpers/cache.py +12 -4
- dominus/namespaces/oracle/__init__.py +120 -0
- dominus/namespaces/oracle/audio_capture.py +382 -0
- dominus/namespaces/oracle/oracle_websocket.py +230 -0
- dominus/namespaces/oracle/session.py +252 -0
- dominus/namespaces/oracle/types.py +127 -0
- dominus/namespaces/oracle/vad_gate.py +276 -0
- dominus/start.py +26 -32
- {dominus_sdk_python_dev-2.3.0.dist-info → dominus_sdk_python_dev-2.5.0.dist-info}/METADATA +21 -6
- {dominus_sdk_python_dev-2.3.0.dist-info → dominus_sdk_python_dev-2.5.0.dist-info}/RECORD +13 -11
- dominus/namespaces/_deprecated_crossover.py +0 -10
- dominus/namespaces/_deprecated_sql.py +0 -1341
- dominus/services/_deprecated_architect.py +0 -323
- dominus/services/_deprecated_sovereign.py +0 -93
- {dominus_sdk_python_dev-2.3.0.dist-info → dominus_sdk_python_dev-2.5.0.dist-info}/WHEEL +0 -0
- {dominus_sdk_python_dev-2.3.0.dist-info → dominus_sdk_python_dev-2.5.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
"""
|
|
2
|
+
VADGate - Voice Activity Detection Gate (INTERNAL)
|
|
3
|
+
|
|
4
|
+
Implements a 4-state machine for VAD gating:
|
|
5
|
+
IDLE -> ARMED -> SPEAKING -> TRAILING -> IDLE
|
|
6
|
+
|
|
7
|
+
Features:
|
|
8
|
+
- Pre-roll buffer (320ms) to capture word onsets
|
|
9
|
+
- Armed confirmation (160ms) to reject false triggers
|
|
10
|
+
- Post-roll/trailing (800ms) to avoid chopped endings
|
|
11
|
+
- Circular buffer for pre-roll storage
|
|
12
|
+
|
|
13
|
+
This module is INTERNAL and should NOT be exported publicly.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import asyncio
|
|
17
|
+
import struct
|
|
18
|
+
import math
|
|
19
|
+
from typing import List, Callable, Optional
|
|
20
|
+
from dataclasses import dataclass
|
|
21
|
+
|
|
22
|
+
from .types import VADState, ResolvedOracleSessionOptions
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class VADGateConfig:
|
|
27
|
+
"""Configuration for VADGate."""
|
|
28
|
+
|
|
29
|
+
# Number of frames in pre-roll buffer
|
|
30
|
+
preroll_frames: int
|
|
31
|
+
|
|
32
|
+
# Number of frames to confirm armed state
|
|
33
|
+
armed_confirm_frames: int
|
|
34
|
+
|
|
35
|
+
# Number of consecutive silence frames to confirm trailing (hysteresis)
|
|
36
|
+
silence_confirm_frames: int
|
|
37
|
+
|
|
38
|
+
# Post-roll timeout in ms
|
|
39
|
+
postroll_ms: int
|
|
40
|
+
|
|
41
|
+
# VAD threshold (0-1)
|
|
42
|
+
threshold: float
|
|
43
|
+
|
|
44
|
+
# Energy threshold for fallback VAD
|
|
45
|
+
energy_threshold: int
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def detect_speech_by_energy(pcm_frame: bytes, threshold: int = 500) -> bool:
|
|
49
|
+
"""
|
|
50
|
+
Energy-based speech detection fallback.
|
|
51
|
+
Calculates RMS energy and compares against threshold.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
pcm_frame: Raw PCM16 audio data
|
|
55
|
+
threshold: RMS energy threshold
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
True if speech detected, False otherwise
|
|
59
|
+
"""
|
|
60
|
+
# Convert bytes to int16 samples
|
|
61
|
+
num_samples = len(pcm_frame) // 2
|
|
62
|
+
if num_samples == 0:
|
|
63
|
+
return False
|
|
64
|
+
|
|
65
|
+
samples = struct.unpack(f"<{num_samples}h", pcm_frame)
|
|
66
|
+
|
|
67
|
+
# Calculate RMS energy
|
|
68
|
+
sum_squares = sum(s * s for s in samples)
|
|
69
|
+
rms = math.sqrt(sum_squares / num_samples)
|
|
70
|
+
|
|
71
|
+
return rms > threshold
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class EnergyVAD:
|
|
75
|
+
"""
|
|
76
|
+
Energy-based VAD fallback.
|
|
77
|
+
Uses RMS energy detection when webrtcvad is unavailable.
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
def __init__(self, energy_threshold: int):
|
|
81
|
+
self.energy_threshold = energy_threshold
|
|
82
|
+
|
|
83
|
+
def is_speech(self, pcm_frame: bytes, _threshold: float) -> bool:
|
|
84
|
+
return detect_speech_by_energy(pcm_frame, self.energy_threshold)
|
|
85
|
+
|
|
86
|
+
def dispose(self) -> None:
|
|
87
|
+
pass
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class WebRTCVAD:
|
|
91
|
+
"""
|
|
92
|
+
WebRTC VAD wrapper.
|
|
93
|
+
Falls back to energy-based detection if webrtcvad is unavailable.
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
def __init__(self, threshold: float, energy_threshold: int, sample_rate: int = 16000):
|
|
97
|
+
self.threshold = threshold
|
|
98
|
+
self.sample_rate = sample_rate
|
|
99
|
+
self.fallback = EnergyVAD(energy_threshold)
|
|
100
|
+
self.vad = None
|
|
101
|
+
self.use_fallback = False
|
|
102
|
+
|
|
103
|
+
try:
|
|
104
|
+
import webrtcvad
|
|
105
|
+
self.vad = webrtcvad.Vad()
|
|
106
|
+
# Aggressiveness level 0-3 (3 = most aggressive filtering)
|
|
107
|
+
# Map threshold (0-1) to aggressiveness (0-3)
|
|
108
|
+
aggressiveness = max(0, min(3, int((1 - threshold) * 3)))
|
|
109
|
+
self.vad.set_mode(aggressiveness)
|
|
110
|
+
except ImportError:
|
|
111
|
+
print("[OracleSDK] webrtcvad not available, using energy-based fallback")
|
|
112
|
+
self.use_fallback = True
|
|
113
|
+
|
|
114
|
+
def is_speech(self, pcm_frame: bytes, threshold: float) -> bool:
|
|
115
|
+
if self.use_fallback or self.vad is None:
|
|
116
|
+
return self.fallback.is_speech(pcm_frame, threshold)
|
|
117
|
+
|
|
118
|
+
try:
|
|
119
|
+
# webrtcvad requires specific frame sizes: 10, 20, or 30 ms
|
|
120
|
+
# For 16kHz, 20ms = 320 samples = 640 bytes
|
|
121
|
+
return self.vad.is_speech(pcm_frame, self.sample_rate)
|
|
122
|
+
except Exception:
|
|
123
|
+
# Fall back to energy-based on any error
|
|
124
|
+
return self.fallback.is_speech(pcm_frame, threshold)
|
|
125
|
+
|
|
126
|
+
def dispose(self) -> None:
|
|
127
|
+
self.vad = None
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class VADGate:
|
|
131
|
+
"""
|
|
132
|
+
VADGate - 4-state Voice Activity Detection machine.
|
|
133
|
+
|
|
134
|
+
State transitions:
|
|
135
|
+
- IDLE -> ARMED: When VAD detects speech
|
|
136
|
+
- ARMED -> SPEAKING: After armed_confirm_frames of continuous speech
|
|
137
|
+
- ARMED -> IDLE: If speech stops before confirmation
|
|
138
|
+
- SPEAKING -> TRAILING: When VAD detects silence
|
|
139
|
+
- TRAILING -> SPEAKING: If speech resumes
|
|
140
|
+
- TRAILING -> IDLE: After postroll_ms timeout
|
|
141
|
+
"""
|
|
142
|
+
|
|
143
|
+
def __init__(
|
|
144
|
+
self,
|
|
145
|
+
options: ResolvedOracleSessionOptions,
|
|
146
|
+
frame_duration_ms: int = 20,
|
|
147
|
+
loop: Optional[asyncio.AbstractEventLoop] = None
|
|
148
|
+
):
|
|
149
|
+
self._state: VADState = "idle"
|
|
150
|
+
self._pre_roll_buffer: List[bytes] = []
|
|
151
|
+
self._armed_frame_count = 0
|
|
152
|
+
self._silence_frame_count = 0
|
|
153
|
+
self._trailing_task: Optional[asyncio.Task] = None
|
|
154
|
+
self._loop = loop
|
|
155
|
+
|
|
156
|
+
self._config = VADGateConfig(
|
|
157
|
+
preroll_frames=math.ceil(options.preroll_ms / frame_duration_ms),
|
|
158
|
+
armed_confirm_frames=math.ceil(options.armed_confirm_ms / frame_duration_ms),
|
|
159
|
+
silence_confirm_frames=8, # 160ms of silence before trailing
|
|
160
|
+
postroll_ms=options.postroll_ms,
|
|
161
|
+
threshold=options.vad_threshold,
|
|
162
|
+
energy_threshold=options.energy_threshold,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
# Use energy-based VAD as the primary implementation
|
|
166
|
+
self._vad_model = EnergyVAD(self._config.energy_threshold)
|
|
167
|
+
|
|
168
|
+
# Callbacks
|
|
169
|
+
self.on_send_audio: Optional[Callable[[List[bytes]], None]] = None
|
|
170
|
+
self.on_state_change: Optional[Callable[[VADState], None]] = None
|
|
171
|
+
|
|
172
|
+
@property
|
|
173
|
+
def state(self) -> VADState:
|
|
174
|
+
"""Get current VAD state."""
|
|
175
|
+
return self._state
|
|
176
|
+
|
|
177
|
+
async def initialize(self) -> None:
|
|
178
|
+
"""Initialize the VAD model (call before processing frames)."""
|
|
179
|
+
# Energy VAD doesn't need initialization
|
|
180
|
+
pass
|
|
181
|
+
|
|
182
|
+
def process_frame(self, pcm_frame: bytes) -> None:
|
|
183
|
+
"""
|
|
184
|
+
Process an audio frame through the VAD gate.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
pcm_frame: 20ms PCM16 audio frame (640 bytes)
|
|
188
|
+
"""
|
|
189
|
+
# Maintain circular pre-roll buffer
|
|
190
|
+
self._pre_roll_buffer.append(pcm_frame)
|
|
191
|
+
if len(self._pre_roll_buffer) > self._config.preroll_frames:
|
|
192
|
+
self._pre_roll_buffer.pop(0)
|
|
193
|
+
|
|
194
|
+
is_speech = self._vad_model.is_speech(pcm_frame, self._config.threshold)
|
|
195
|
+
|
|
196
|
+
if self._state == "idle":
|
|
197
|
+
if is_speech:
|
|
198
|
+
self._set_state("armed")
|
|
199
|
+
self._armed_frame_count = 1
|
|
200
|
+
|
|
201
|
+
elif self._state == "armed":
|
|
202
|
+
if is_speech:
|
|
203
|
+
self._armed_frame_count += 1
|
|
204
|
+
if self._armed_frame_count >= self._config.armed_confirm_frames:
|
|
205
|
+
# Confirmed speech - flush pre-roll buffer
|
|
206
|
+
if self.on_send_audio:
|
|
207
|
+
self.on_send_audio(list(self._pre_roll_buffer))
|
|
208
|
+
self._set_state("speaking")
|
|
209
|
+
else:
|
|
210
|
+
# False trigger - back to idle
|
|
211
|
+
self._set_state("idle")
|
|
212
|
+
self._armed_frame_count = 0
|
|
213
|
+
|
|
214
|
+
elif self._state == "speaking":
|
|
215
|
+
if self.on_send_audio:
|
|
216
|
+
self.on_send_audio([pcm_frame])
|
|
217
|
+
|
|
218
|
+
if not is_speech:
|
|
219
|
+
# Hysteresis: require multiple consecutive silence frames
|
|
220
|
+
self._silence_frame_count += 1
|
|
221
|
+
if self._silence_frame_count >= self._config.silence_confirm_frames:
|
|
222
|
+
self._set_state("trailing")
|
|
223
|
+
self._start_trailing_timer()
|
|
224
|
+
self._silence_frame_count = 0
|
|
225
|
+
else:
|
|
226
|
+
# Speech detected - reset silence counter
|
|
227
|
+
self._silence_frame_count = 0
|
|
228
|
+
|
|
229
|
+
elif self._state == "trailing":
|
|
230
|
+
if self.on_send_audio:
|
|
231
|
+
self.on_send_audio([pcm_frame])
|
|
232
|
+
|
|
233
|
+
if is_speech:
|
|
234
|
+
self._cancel_trailing_timer()
|
|
235
|
+
self._set_state("speaking")
|
|
236
|
+
|
|
237
|
+
def reset(self) -> None:
|
|
238
|
+
"""Reset VAD state to idle."""
|
|
239
|
+
self._cancel_trailing_timer()
|
|
240
|
+
self._state = "idle"
|
|
241
|
+
self._pre_roll_buffer = []
|
|
242
|
+
self._armed_frame_count = 0
|
|
243
|
+
self._silence_frame_count = 0
|
|
244
|
+
|
|
245
|
+
def dispose(self) -> None:
|
|
246
|
+
"""Clean up resources."""
|
|
247
|
+
self._cancel_trailing_timer()
|
|
248
|
+
self._vad_model.dispose()
|
|
249
|
+
self.on_send_audio = None
|
|
250
|
+
self.on_state_change = None
|
|
251
|
+
|
|
252
|
+
def _set_state(self, new_state: VADState) -> None:
|
|
253
|
+
"""Update VAD state and fire callback."""
|
|
254
|
+
if self._state != new_state:
|
|
255
|
+
self._state = new_state
|
|
256
|
+
if self.on_state_change:
|
|
257
|
+
self.on_state_change(new_state)
|
|
258
|
+
|
|
259
|
+
def _start_trailing_timer(self) -> None:
|
|
260
|
+
"""
|
|
261
|
+
Start the trailing timeout.
|
|
262
|
+
After postroll_ms, transition back to idle.
|
|
263
|
+
"""
|
|
264
|
+
async def trailing_timeout():
|
|
265
|
+
await asyncio.sleep(self._config.postroll_ms / 1000.0)
|
|
266
|
+
self._set_state("idle")
|
|
267
|
+
self._trailing_task = None
|
|
268
|
+
|
|
269
|
+
loop = self._loop or asyncio.get_event_loop()
|
|
270
|
+
self._trailing_task = loop.create_task(trailing_timeout())
|
|
271
|
+
|
|
272
|
+
def _cancel_trailing_timer(self) -> None:
|
|
273
|
+
"""Cancel the trailing timeout."""
|
|
274
|
+
if self._trailing_task is not None:
|
|
275
|
+
self._trailing_task.cancel()
|
|
276
|
+
self._trailing_task = None
|
dominus/start.py
CHANGED
|
@@ -251,31 +251,6 @@ class SecureNamespace:
|
|
|
251
251
|
)
|
|
252
252
|
|
|
253
253
|
|
|
254
|
-
class OpenNamespace:
|
|
255
|
-
"""Open user namespace - Returns DSN string for dominus_open database."""
|
|
256
|
-
|
|
257
|
-
def __init__(self, _execute_command):
|
|
258
|
-
self._execute = _execute_command
|
|
259
|
-
|
|
260
|
-
async def dsn(self) -> str:
|
|
261
|
-
"""
|
|
262
|
-
Get the full DSN connection string for open_user role.
|
|
263
|
-
|
|
264
|
-
Returns the complete PostgreSQL connection URI for the dominus_open
|
|
265
|
-
database that can be used directly by clients to connect.
|
|
266
|
-
"""
|
|
267
|
-
return await self._execute("sql.open.get_dsn")
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
class HealthNamespace:
|
|
271
|
-
"""Health check operations namespace."""
|
|
272
|
-
|
|
273
|
-
def __init__(self, _execute_command):
|
|
274
|
-
self._execute = _execute_command
|
|
275
|
-
|
|
276
|
-
async def check(self) -> Dict[str, Any]:
|
|
277
|
-
"""Check health of all services."""
|
|
278
|
-
return await self._execute("health.check")
|
|
279
254
|
|
|
280
255
|
|
|
281
256
|
class Dominus:
|
|
@@ -324,10 +299,8 @@ class Dominus:
|
|
|
324
299
|
|
|
325
300
|
self._execute = _execute_command
|
|
326
301
|
|
|
327
|
-
# Initialize
|
|
302
|
+
# Initialize legacy flat API namespaces (backward compatibility)
|
|
328
303
|
self.secure = SecureNamespace(_execute_command)
|
|
329
|
-
self.open = OpenNamespace(_execute_command)
|
|
330
|
-
self.health = HealthNamespace(_execute_command)
|
|
331
304
|
|
|
332
305
|
# Initialize portal namespace (needs client reference for _request)
|
|
333
306
|
from .namespaces.portal import PortalNamespace
|
|
@@ -337,24 +310,45 @@ class Dominus:
|
|
|
337
310
|
from .namespaces.fastapi import FastAPINamespace
|
|
338
311
|
self.fastapi = FastAPINamespace(self)
|
|
339
312
|
|
|
340
|
-
# Initialize
|
|
313
|
+
# Initialize all namespaces (matching Node.js SDK pattern)
|
|
341
314
|
from .namespaces.db import DbNamespace
|
|
342
315
|
from .namespaces.auth import AuthNamespace
|
|
343
316
|
from .namespaces.ddl import DdlNamespace
|
|
344
317
|
from .namespaces.files import FilesNamespace
|
|
345
318
|
from .namespaces.admin import AdminNamespace
|
|
346
319
|
from .namespaces.secure import SecureNamespace as SecureNS
|
|
347
|
-
|
|
320
|
+
from .namespaces.secrets import SecretsNamespace
|
|
321
|
+
from .namespaces.redis import RedisNamespace
|
|
322
|
+
from .namespaces.logs import LogsNamespace
|
|
323
|
+
from .namespaces.courier import CourierNamespace
|
|
324
|
+
from .namespaces.health import HealthNamespace
|
|
325
|
+
from .namespaces.open import OpenNamespace
|
|
326
|
+
|
|
327
|
+
# Core namespaces
|
|
348
328
|
self.db = DbNamespace(self)
|
|
349
329
|
self.auth = AuthNamespace(self)
|
|
350
330
|
self.ddl = DdlNamespace(self)
|
|
351
331
|
self.files = FilesNamespace(self)
|
|
352
332
|
self.admin = AdminNamespace(self)
|
|
353
333
|
|
|
354
|
-
#
|
|
355
|
-
|
|
334
|
+
# Additional namespaces (Node.js SDK parity)
|
|
335
|
+
self.secrets = SecretsNamespace(self)
|
|
336
|
+
self.redis = RedisNamespace(self)
|
|
337
|
+
self.logs = LogsNamespace(self)
|
|
338
|
+
self.courier = CourierNamespace(self)
|
|
339
|
+
self.health = HealthNamespace(self)
|
|
340
|
+
self.open = OpenNamespace(self)
|
|
341
|
+
|
|
342
|
+
# Secure namespace with proper audit context support
|
|
356
343
|
self.db_secure = SecureNS(self)
|
|
357
344
|
|
|
345
|
+
# Oracle namespace (Speech-to-Text streaming)
|
|
346
|
+
from .namespaces.oracle import OracleNamespace
|
|
347
|
+
self.oracle = OracleNamespace(self)
|
|
348
|
+
|
|
349
|
+
# Alias for Node.js SDK parity (stt = oracle)
|
|
350
|
+
self.stt = self.oracle
|
|
351
|
+
|
|
358
352
|
# Cache for JWT public key
|
|
359
353
|
self._public_key_cache = None
|
|
360
354
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dominus-sdk-python-dev
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.0
|
|
4
4
|
Summary: Python SDK for the Dominus Orchestrator Platform
|
|
5
5
|
Author-email: CareBridge Systems <dev@carebridge.io>
|
|
6
6
|
License: Proprietary
|
|
@@ -25,9 +25,20 @@ Requires-Dist: bcrypt>=4.0.0
|
|
|
25
25
|
Requires-Dist: cryptography>=41.0.0
|
|
26
26
|
Provides-Extra: jwt
|
|
27
27
|
Requires-Dist: PyJWT>=2.8.0; extra == "jwt"
|
|
28
|
+
Provides-Extra: oracle
|
|
29
|
+
Requires-Dist: websockets>=12.0; extra == "oracle"
|
|
30
|
+
Requires-Dist: sounddevice>=0.4.6; extra == "oracle"
|
|
31
|
+
Requires-Dist: numpy>=1.24.0; extra == "oracle"
|
|
32
|
+
Requires-Dist: webrtcvad>=2.0.10; extra == "oracle"
|
|
28
33
|
Provides-Extra: dev
|
|
29
34
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
30
35
|
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
36
|
+
Provides-Extra: all
|
|
37
|
+
Requires-Dist: PyJWT>=2.8.0; extra == "all"
|
|
38
|
+
Requires-Dist: websockets>=12.0; extra == "all"
|
|
39
|
+
Requires-Dist: sounddevice>=0.4.6; extra == "all"
|
|
40
|
+
Requires-Dist: numpy>=1.24.0; extra == "all"
|
|
41
|
+
Requires-Dist: webrtcvad>=2.0.10; extra == "all"
|
|
31
42
|
|
|
32
43
|
# CB Dominus SDK for Python
|
|
33
44
|
|
|
@@ -417,8 +428,8 @@ from dominus import (
|
|
|
417
428
|
ConflictError,
|
|
418
429
|
ServiceError,
|
|
419
430
|
SecureTableError,
|
|
420
|
-
|
|
421
|
-
|
|
431
|
+
DominusConnectionError, # Renamed to avoid shadowing built-in
|
|
432
|
+
DominusTimeoutError, # Renamed to avoid shadowing built-in
|
|
422
433
|
)
|
|
423
434
|
|
|
424
435
|
try:
|
|
@@ -445,6 +456,7 @@ except DominusError as e:
|
|
|
445
456
|
|
|
446
457
|
| Error | Status | Description |
|
|
447
458
|
|-------|--------|-------------|
|
|
459
|
+
| `DominusError` | - | Base class for all SDK errors |
|
|
448
460
|
| `AuthenticationError` | 401 | Invalid or missing token |
|
|
449
461
|
| `AuthorizationError` | 403 | Insufficient permissions |
|
|
450
462
|
| `NotFoundError` | 404 | Resource not found |
|
|
@@ -452,8 +464,8 @@ except DominusError as e:
|
|
|
452
464
|
| `ConflictError` | 409 | Duplicate or version conflict |
|
|
453
465
|
| `ServiceError` | 5xx | Backend service error |
|
|
454
466
|
| `SecureTableError` | 403 | Missing reason for secure table |
|
|
455
|
-
| `
|
|
456
|
-
| `
|
|
467
|
+
| `DominusConnectionError` | - | Network connection failed |
|
|
468
|
+
| `DominusTimeoutError` | 504 | Request timed out |
|
|
457
469
|
|
|
458
470
|
## Configuration
|
|
459
471
|
|
|
@@ -551,10 +563,13 @@ async def get_all_users(page_size: int = 100):
|
|
|
551
563
|
|
|
552
564
|
## Version
|
|
553
565
|
|
|
554
|
-
**v2.
|
|
566
|
+
**v2.4.0** - Full namespace parity with Node.js SDK
|
|
555
567
|
|
|
556
568
|
### Changelog
|
|
557
569
|
|
|
570
|
+
- **v2.4.0** - Full parity with Node.js SDK: all namespaces properly initialized, error classes exported, cache utilities exposed
|
|
571
|
+
- **v2.3.0** - Add comprehensive auth namespace with 100+ methods
|
|
572
|
+
- **v2.2.0** - Add DDL schema builder and migration methods
|
|
558
573
|
- **v2.1.6** - Fix navigation routes and add page scope methods
|
|
559
574
|
- **v2.1.5** - Add PSK-only client login
|
|
560
575
|
- **v2.1.4** - Make `tenant_id` optional in login methods
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
dominus/__init__.py,sha256
|
|
1
|
+
dominus/__init__.py,sha256=fBZgMu7J7o7DCUNH9PStQ873LW5n9IREXsuu6EsXO70,5132
|
|
2
2
|
dominus/errors.py,sha256=Sfpg_4zlraE6fprdSu7RDNmSDv0Eg5OZRcPhNUQhNGs,5761
|
|
3
|
-
dominus/start.py,sha256=
|
|
3
|
+
dominus/start.py,sha256=F_Z9qu8m5YLKk9uCeM9S2vnSfArDJVojoi6MDe8pNqE,32743
|
|
4
4
|
dominus/config/__init__.py,sha256=nvLLNh4dM_MCqcfF3XFS2NnVn44q0RYHEfAPP-2G5To,434
|
|
5
5
|
dominus/config/endpoints.py,sha256=fsV5c7vaicpJlF735o46FP4Xlu2Ap4rSvnNa4F0TOYg,1574
|
|
6
6
|
dominus/helpers/__init__.py,sha256=cyoBvw1QJugtGt0gYitIz1yxOaMmBa-wMXqbh-fi4PU,61
|
|
7
7
|
dominus/helpers/auth.py,sha256=IVZLelikaGIAZvyc-q7EoPd8fBNVlGffGXQkTP4x5Fk,633
|
|
8
|
-
dominus/helpers/cache.py,sha256=
|
|
8
|
+
dominus/helpers/cache.py,sha256=RgCTPLmHoOXGkxF-pLP9buKPkvZDYHtsLUxbTFjheJI,6028
|
|
9
9
|
dominus/helpers/core.py,sha256=DeCo2sCmXJLnitJSDzRKcQGwYXyQOw1KRvzxDI6DQsA,24174
|
|
10
10
|
dominus/helpers/crypto.py,sha256=XvP9ud5jJ9KPvIQmtAOeXZS4WUyCNb8X-RL_eOB7WNE,2890
|
|
11
11
|
dominus/namespaces/__init__.py,sha256=Kh7tw-5LmY-CpZL2BdqbHc93QLjxTOCGLUVPwAqqDnE,659
|
|
12
|
-
dominus/namespaces/_deprecated_crossover.py,sha256=NY73vatvc4CDgML9QMqmvoEjRr_t-Vq6FHtbby0M2-M,385
|
|
13
|
-
dominus/namespaces/_deprecated_sql.py,sha256=U57p5hGFbsPEcNEl12m7tYTWux7j2rcCHbCjmNMJ8oY,38318
|
|
14
12
|
dominus/namespaces/admin.py,sha256=qkGoteAJ6cqdNub4zL1mtyxAQtsM3-nUplRSgw2fMZY,1640
|
|
15
13
|
dominus/namespaces/auth.py,sha256=Nqy4EOA1qMINvVuvf2-RnKPwN6TyLiD3vmz1G4J7TQg,55462
|
|
16
14
|
dominus/namespaces/courier.py,sha256=WAhHpswhO8S_eEzn5zgBGhDqhgGxfDR_gs4i1rnotNw,6810
|
|
@@ -25,10 +23,14 @@ dominus/namespaces/portal.py,sha256=6T0ul2spnhcDORh1JN2v7zDbkdWqk0FblWKFIeUjSsA,
|
|
|
25
23
|
dominus/namespaces/redis.py,sha256=WctuQdUddifDiato6QHntv1ulvAQVVC01iq_k2WUh9A,9384
|
|
26
24
|
dominus/namespaces/secrets.py,sha256=6xhUJVeDBb5-AiwrwjozarwAc7SoiJ-2Rq6ByBAx684,3572
|
|
27
25
|
dominus/namespaces/secure.py,sha256=9idGY5R6k7b-JM1SAF_1Gt-YV5OempyxFBflgLJieLo,7168
|
|
26
|
+
dominus/namespaces/oracle/__init__.py,sha256=XiJ8P-vFln73p4r1_ZXgmNQvawkNUt5htuGD51JCoBA,4584
|
|
27
|
+
dominus/namespaces/oracle/audio_capture.py,sha256=1-QcoAHYT1idEBGAJ7g4qpu5QeKdmwiyWciB6K0WkNM,11201
|
|
28
|
+
dominus/namespaces/oracle/oracle_websocket.py,sha256=VsKKPTZmtdchoXj9bFel3hrWUVELS-5UD7LNFWlDdfg,7540
|
|
29
|
+
dominus/namespaces/oracle/session.py,sha256=1As6q-bs0Ynoz3fsNk18E7CuouPROnVadCY_HeHRTkw,7998
|
|
30
|
+
dominus/namespaces/oracle/types.py,sha256=YGwb-PfKikRGNk4af5Av2DD9YPLJpogM21Co9X4T_cU,3517
|
|
31
|
+
dominus/namespaces/oracle/vad_gate.py,sha256=Gpb5q72-MSGYm4PVK64E4w6kawx5AMb1SsJ2uOJrtFw,9010
|
|
28
32
|
dominus/services/__init__.py,sha256=LQl5sx6DHhX1xCN3MRoUgffxqwm3Mfm525hijyFods8,43
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
dominus_sdk_python_dev-2.
|
|
32
|
-
dominus_sdk_python_dev-2.
|
|
33
|
-
dominus_sdk_python_dev-2.3.0.dist-info/top_level.txt,sha256=515zxMIbX0DpheRbjvNqKIt_AFqdFjX41jtyp_SqLf4,8
|
|
34
|
-
dominus_sdk_python_dev-2.3.0.dist-info/RECORD,,
|
|
33
|
+
dominus_sdk_python_dev-2.5.0.dist-info/METADATA,sha256=j4BWCGfmmcMqgtDbt9VHq-oBzmARLshuRIdCr27G-aM,17401
|
|
34
|
+
dominus_sdk_python_dev-2.5.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
35
|
+
dominus_sdk_python_dev-2.5.0.dist-info/top_level.txt,sha256=515zxMIbX0DpheRbjvNqKIt_AFqdFjX41jtyp_SqLf4,8
|
|
36
|
+
dominus_sdk_python_dev-2.5.0.dist-info/RECORD,,
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
"""Crossover (admin) operations namespace - DEPRECATED
|
|
2
|
-
|
|
3
|
-
Note: This namespace has been removed from the SDK.
|
|
4
|
-
Provisioning and admin operations should be done via Architect's
|
|
5
|
-
/api/crossover endpoint directly, not through the SDK.
|
|
6
|
-
|
|
7
|
-
This file is kept as a placeholder to prevent import errors in
|
|
8
|
-
any code that may still reference it.
|
|
9
|
-
"""
|
|
10
|
-
# Empty file - all crossover functionality removed
|