dominus-sdk-python-dev 2.4.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 +14 -1
- 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 +7 -0
- {dominus_sdk_python_dev-2.4.0.dist-info → dominus_sdk_python_dev-2.5.0.dist-info}/METADATA +12 -1
- {dominus_sdk_python_dev-2.4.0.dist-info → dominus_sdk_python_dev-2.5.0.dist-info}/RECORD +12 -10
- 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.4.0.dist-info → dominus_sdk_python_dev-2.5.0.dist-info}/WHEEL +0 -0
- {dominus_sdk_python_dev-2.4.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
|
@@ -342,6 +342,13 @@ class Dominus:
|
|
|
342
342
|
# Secure namespace with proper audit context support
|
|
343
343
|
self.db_secure = SecureNS(self)
|
|
344
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
|
+
|
|
345
352
|
# Cache for JWT public key
|
|
346
353
|
self._public_key_cache = None
|
|
347
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
|
|
|
@@ -1,6 +1,6 @@
|
|
|
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
|
|
@@ -9,8 +9,6 @@ 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.4.0.dist-info/top_level.txt,sha256=515zxMIbX0DpheRbjvNqKIt_AFqdFjX41jtyp_SqLf4,8
|
|
34
|
-
dominus_sdk_python_dev-2.4.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
|