dominus-sdk-python 2.12.0__tar.gz → 2.13.0__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.
Files changed (52) hide show
  1. dominus_sdk_python-2.13.0/PKG-INFO +179 -0
  2. dominus_sdk_python-2.13.0/README.md +137 -0
  3. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/__init__.py +12 -1
  4. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/helpers/core.py +14 -29
  5. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/__init__.py +9 -1
  6. dominus_sdk_python-2.13.0/dominus/namespaces/artifacts.py +150 -0
  7. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/auth.py +65 -1
  8. dominus_sdk_python-2.13.0/dominus/namespaces/jobs.py +190 -0
  9. dominus_sdk_python-2.13.0/dominus/namespaces/processor.py +99 -0
  10. dominus_sdk_python-2.13.0/dominus/namespaces/sync.py +72 -0
  11. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/workflow.py +74 -69
  12. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/start.py +20 -5
  13. dominus_sdk_python-2.13.0/dominus_sdk_python.egg-info/PKG-INFO +179 -0
  14. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus_sdk_python.egg-info/SOURCES.txt +4 -0
  15. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/pyproject.toml +1 -1
  16. dominus_sdk_python-2.12.0/PKG-INFO +0 -92
  17. dominus_sdk_python-2.12.0/README.md +0 -50
  18. dominus_sdk_python-2.12.0/dominus_sdk_python.egg-info/PKG-INFO +0 -92
  19. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/config/__init__.py +0 -0
  20. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/config/endpoints.py +0 -0
  21. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/errors.py +0 -0
  22. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/helpers/__init__.py +0 -0
  23. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/helpers/auth.py +0 -0
  24. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/helpers/cache.py +0 -0
  25. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/helpers/console_capture.py +0 -0
  26. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/helpers/crypto.py +0 -0
  27. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/helpers/sse.py +0 -0
  28. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/admin.py +0 -0
  29. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/ai.py +0 -0
  30. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/courier.py +0 -0
  31. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/db.py +0 -0
  32. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/ddl.py +0 -0
  33. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/fastapi.py +0 -0
  34. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/files.py +0 -0
  35. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/health.py +0 -0
  36. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/logs.py +0 -0
  37. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/open.py +0 -0
  38. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/oracle/__init__.py +0 -0
  39. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/oracle/audio_capture.py +0 -0
  40. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/oracle/oracle_websocket.py +0 -0
  41. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/oracle/session.py +0 -0
  42. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/oracle/types.py +0 -0
  43. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/oracle/vad_gate.py +0 -0
  44. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/portal.py +0 -0
  45. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/redis.py +0 -0
  46. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/secrets.py +0 -0
  47. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/namespaces/secure.py +0 -0
  48. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus/services/__init__.py +0 -0
  49. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus_sdk_python.egg-info/dependency_links.txt +0 -0
  50. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus_sdk_python.egg-info/requires.txt +0 -0
  51. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/dominus_sdk_python.egg-info/top_level.txt +0 -0
  52. {dominus_sdk_python-2.12.0 → dominus_sdk_python-2.13.0}/setup.cfg +0 -0
@@ -0,0 +1,179 @@
1
+ Metadata-Version: 2.4
2
+ Name: dominus-sdk-python
3
+ Version: 2.13.0
4
+ Summary: Python SDK for the Dominus Orchestrator Platform
5
+ Author-email: CareBridge Systems <dev@carebridge.io>
6
+ License: Proprietary
7
+ Project-URL: Homepage, https://github.com/carebridgesystems/dominus-sdk-python
8
+ Project-URL: Repository, https://github.com/carebridgesystems/dominus-sdk-python
9
+ Keywords: dominus,carebridge,sdk,orchestrator,api,async
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: Other/Proprietary License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Classifier: Framework :: AsyncIO
21
+ Requires-Python: >=3.9
22
+ Description-Content-Type: text/markdown
23
+ Requires-Dist: httpx>=0.24.0
24
+ Requires-Dist: bcrypt>=4.0.0
25
+ Requires-Dist: cryptography>=41.0.0
26
+ Provides-Extra: jwt
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"
33
+ Provides-Extra: dev
34
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
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"
42
+
43
+ # Dominus SDK for Python
44
+
45
+ Async Python SDK for CareBridge Dominus platform services. Routes calls through the Dominus Gateway with JWT-based authentication, base64 wire encoding, retries, and circuit breaking.
46
+
47
+ ## What This Is
48
+
49
+ - Server-side, asyncio-first Python SDK (3.9+)
50
+ - Namespace API with root-level shortcuts for common operations
51
+ - Targets production Cloudflare Workers (gateway, JWT, logs) and Cloud Run (orchestrator)
52
+ - Version: 2.12.0
53
+
54
+ ## Quick Start
55
+
56
+ ```python
57
+ import os
58
+ from dominus import dominus
59
+
60
+ os.environ["DOMINUS_TOKEN"] = "your-psk-token"
61
+
62
+ # Secrets
63
+ value = await dominus.secrets.get("DB_URL")
64
+ await dominus.secrets.upsert("API_KEY", "secret_value")
65
+
66
+ # Database CRUD
67
+ users = await dominus.db.query("users", filters={"status": "active"})
68
+ await dominus.db.insert("users", {"name": "John", "email": "john@example.com"})
69
+
70
+ # Redis caching
71
+ await dominus.redis.set("session:123", {"user": "john"}, ttl=3600)
72
+ value = await dominus.redis.get("session:123")
73
+
74
+ # File storage
75
+ result = await dominus.files.upload(data=buf, filename="report.pdf", category="reports")
76
+
77
+ # AI agent execution
78
+ result = await dominus.ai.run_agent(
79
+ conversation_id="conv-123",
80
+ system_prompt="You are helpful.",
81
+ user_prompt="Hello!"
82
+ )
83
+
84
+ # Streaming AI
85
+ async for chunk in dominus.ai.stream_agent(
86
+ conversation_id="conv-123",
87
+ system_prompt="You are helpful.",
88
+ user_prompt="Tell me a story"
89
+ ):
90
+ print(chunk.get("content", ""), end="", flush=True)
91
+
92
+ # Workflow execution
93
+ result = await dominus.workflow.execute(workflow_id, context={"key": "value"})
94
+ ```
95
+
96
+ ## Architecture (SDK View)
97
+
98
+ ```
99
+ DOMINUS_TOKEN (PSK) --> Gateway /jwt/mint --> JWT cached (14min TTL)
100
+ |
101
+ v
102
+ Gateway /svc/* (AI, workflow, logs)
103
+ or
104
+ Orchestrator /api/* (all other services)
105
+ ```
106
+
107
+ - JSON requests/responses are base64-encoded for auth-required routes
108
+ - GET requests send no body; parameters go in the path or query string
109
+ - Gateway routing (`/api/*` -> `/svc/*`) is used by AI, workflow, and logs namespaces
110
+ - Orchestrator handles secrets, db, auth, ddl, files, redis, portal, courier, open, health, admin
111
+
112
+ ## Namespaces
113
+
114
+ | Namespace | Service | Description |
115
+ |-----------|---------|-------------|
116
+ | `secrets` | Warden | Secrets CRUD |
117
+ | `db` | Scribe | Database CRUD with optional secure-table audit |
118
+ | `secure` / `db_secure` | Scribe | Audit-logged data access (requires reason/actor) |
119
+ | `redis` | Whisperer | Cache, locks, counters, hashes |
120
+ | `files` | Archivist | Object storage with compliance mode |
121
+ | `auth` | Guardian | Users, roles, scopes, tenants, clients, pages, nav, subtypes, secure tables (147 methods) |
122
+ | `ddl` | Smith | Schema DDL, migrations, tenant provisioning, schema builder |
123
+ | `logs` | Logs Worker | Structured logging with callsite capture |
124
+ | `portal` | Portal | Login, sessions, profile, preferences, navigation, registration |
125
+ | `courier` | Courier | Postmark email delivery |
126
+ | `open` | Scribe Open | Raw SQL / DSN retrieval |
127
+ | `health` | Orchestrator | Health/ping/warmup |
128
+ | `admin` | Admin | Reseed/reset admin category |
129
+ | `ai` | Agent Runtime | Agent execution, LLM completions, RAG, artifacts, results, orchestration, STT/TTS |
130
+ | `workflow` | Workflow Manager | Workflow CRUD, categories/pipelines, templates, execution |
131
+ | `oracle` / `stt` | Oracle | Real-time streaming STT with VAD (WebSocket, requires `oracle` extras) |
132
+ | `fastapi` | Local | FastAPI route auth decorators (`@jwt`, `@psk`, `@scopes`) |
133
+
134
+ ## Configuration
135
+
136
+ **Required:**
137
+ - `DOMINUS_TOKEN` -- PSK token for gateway authentication
138
+
139
+ **Optional:**
140
+ - `DOMINUS_GATEWAY_URL` -- Override gateway URL (default: `https://gateway.getdominus.app`)
141
+ - `DOMINUS_JWT_URL` -- Override JWT worker URL (default: `https://jwt.getdominus.app`)
142
+ - `DOMINUS_LOGS_URL` -- Override logs worker URL (default: `https://logs.getdominus.app`)
143
+ - `DOMINUS_BASE_URL` -- Override orchestrator URL (default: production Cloud Run)
144
+ - `DOMINUS_HTTP_PROXY` / `DOMINUS_HTTPS_PROXY` -- httpx proxy configuration
145
+ - `DOMINUS_CAPTURE_CONSOLE` -- Set to `"true"` to auto-forward `print()` and `logging.*` to Logs Worker
146
+
147
+ ## Installation
148
+
149
+ ```bash
150
+ pip install dominus-sdk-python
151
+
152
+ # With optional extras
153
+ pip install dominus-sdk-python[jwt] # Local JWT verification
154
+ pip install dominus-sdk-python[oracle] # WebSocket STT (websockets, numpy, sounddevice, webrtcvad)
155
+ pip install dominus-sdk-python[all] # Everything
156
+ ```
157
+
158
+ ## Console Capture
159
+
160
+ Forward `print()` and `logging.*` to the Dominus Logs Worker:
161
+
162
+ ```python
163
+ # Automatic (via env var, before importing SDK):
164
+ os.environ["DOMINUS_CAPTURE_CONSOLE"] = "true"
165
+
166
+ # Manual:
167
+ dominus.capture_console() # start capturing
168
+ dominus.release_console() # stop capturing
169
+ ```
170
+
171
+ ## Documentation
172
+
173
+ - [Architecture](docs/architecture.md) -- Request flow, resilience, JWT verification
174
+ - [Services Reference](docs/services.md) -- Complete namespace and method inventory
175
+ - [Development](docs/development.md) -- Setup, testing, adding APIs
176
+
177
+ ## License
178
+
179
+ Proprietary - CareBridge Systems
@@ -0,0 +1,137 @@
1
+ # Dominus SDK for Python
2
+
3
+ Async Python SDK for CareBridge Dominus platform services. Routes calls through the Dominus Gateway with JWT-based authentication, base64 wire encoding, retries, and circuit breaking.
4
+
5
+ ## What This Is
6
+
7
+ - Server-side, asyncio-first Python SDK (3.9+)
8
+ - Namespace API with root-level shortcuts for common operations
9
+ - Targets production Cloudflare Workers (gateway, JWT, logs) and Cloud Run (orchestrator)
10
+ - Version: 2.12.0
11
+
12
+ ## Quick Start
13
+
14
+ ```python
15
+ import os
16
+ from dominus import dominus
17
+
18
+ os.environ["DOMINUS_TOKEN"] = "your-psk-token"
19
+
20
+ # Secrets
21
+ value = await dominus.secrets.get("DB_URL")
22
+ await dominus.secrets.upsert("API_KEY", "secret_value")
23
+
24
+ # Database CRUD
25
+ users = await dominus.db.query("users", filters={"status": "active"})
26
+ await dominus.db.insert("users", {"name": "John", "email": "john@example.com"})
27
+
28
+ # Redis caching
29
+ await dominus.redis.set("session:123", {"user": "john"}, ttl=3600)
30
+ value = await dominus.redis.get("session:123")
31
+
32
+ # File storage
33
+ result = await dominus.files.upload(data=buf, filename="report.pdf", category="reports")
34
+
35
+ # AI agent execution
36
+ result = await dominus.ai.run_agent(
37
+ conversation_id="conv-123",
38
+ system_prompt="You are helpful.",
39
+ user_prompt="Hello!"
40
+ )
41
+
42
+ # Streaming AI
43
+ async for chunk in dominus.ai.stream_agent(
44
+ conversation_id="conv-123",
45
+ system_prompt="You are helpful.",
46
+ user_prompt="Tell me a story"
47
+ ):
48
+ print(chunk.get("content", ""), end="", flush=True)
49
+
50
+ # Workflow execution
51
+ result = await dominus.workflow.execute(workflow_id, context={"key": "value"})
52
+ ```
53
+
54
+ ## Architecture (SDK View)
55
+
56
+ ```
57
+ DOMINUS_TOKEN (PSK) --> Gateway /jwt/mint --> JWT cached (14min TTL)
58
+ |
59
+ v
60
+ Gateway /svc/* (AI, workflow, logs)
61
+ or
62
+ Orchestrator /api/* (all other services)
63
+ ```
64
+
65
+ - JSON requests/responses are base64-encoded for auth-required routes
66
+ - GET requests send no body; parameters go in the path or query string
67
+ - Gateway routing (`/api/*` -> `/svc/*`) is used by AI, workflow, and logs namespaces
68
+ - Orchestrator handles secrets, db, auth, ddl, files, redis, portal, courier, open, health, admin
69
+
70
+ ## Namespaces
71
+
72
+ | Namespace | Service | Description |
73
+ |-----------|---------|-------------|
74
+ | `secrets` | Warden | Secrets CRUD |
75
+ | `db` | Scribe | Database CRUD with optional secure-table audit |
76
+ | `secure` / `db_secure` | Scribe | Audit-logged data access (requires reason/actor) |
77
+ | `redis` | Whisperer | Cache, locks, counters, hashes |
78
+ | `files` | Archivist | Object storage with compliance mode |
79
+ | `auth` | Guardian | Users, roles, scopes, tenants, clients, pages, nav, subtypes, secure tables (147 methods) |
80
+ | `ddl` | Smith | Schema DDL, migrations, tenant provisioning, schema builder |
81
+ | `logs` | Logs Worker | Structured logging with callsite capture |
82
+ | `portal` | Portal | Login, sessions, profile, preferences, navigation, registration |
83
+ | `courier` | Courier | Postmark email delivery |
84
+ | `open` | Scribe Open | Raw SQL / DSN retrieval |
85
+ | `health` | Orchestrator | Health/ping/warmup |
86
+ | `admin` | Admin | Reseed/reset admin category |
87
+ | `ai` | Agent Runtime | Agent execution, LLM completions, RAG, artifacts, results, orchestration, STT/TTS |
88
+ | `workflow` | Workflow Manager | Workflow CRUD, categories/pipelines, templates, execution |
89
+ | `oracle` / `stt` | Oracle | Real-time streaming STT with VAD (WebSocket, requires `oracle` extras) |
90
+ | `fastapi` | Local | FastAPI route auth decorators (`@jwt`, `@psk`, `@scopes`) |
91
+
92
+ ## Configuration
93
+
94
+ **Required:**
95
+ - `DOMINUS_TOKEN` -- PSK token for gateway authentication
96
+
97
+ **Optional:**
98
+ - `DOMINUS_GATEWAY_URL` -- Override gateway URL (default: `https://gateway.getdominus.app`)
99
+ - `DOMINUS_JWT_URL` -- Override JWT worker URL (default: `https://jwt.getdominus.app`)
100
+ - `DOMINUS_LOGS_URL` -- Override logs worker URL (default: `https://logs.getdominus.app`)
101
+ - `DOMINUS_BASE_URL` -- Override orchestrator URL (default: production Cloud Run)
102
+ - `DOMINUS_HTTP_PROXY` / `DOMINUS_HTTPS_PROXY` -- httpx proxy configuration
103
+ - `DOMINUS_CAPTURE_CONSOLE` -- Set to `"true"` to auto-forward `print()` and `logging.*` to Logs Worker
104
+
105
+ ## Installation
106
+
107
+ ```bash
108
+ pip install dominus-sdk-python
109
+
110
+ # With optional extras
111
+ pip install dominus-sdk-python[jwt] # Local JWT verification
112
+ pip install dominus-sdk-python[oracle] # WebSocket STT (websockets, numpy, sounddevice, webrtcvad)
113
+ pip install dominus-sdk-python[all] # Everything
114
+ ```
115
+
116
+ ## Console Capture
117
+
118
+ Forward `print()` and `logging.*` to the Dominus Logs Worker:
119
+
120
+ ```python
121
+ # Automatic (via env var, before importing SDK):
122
+ os.environ["DOMINUS_CAPTURE_CONSOLE"] = "true"
123
+
124
+ # Manual:
125
+ dominus.capture_console() # start capturing
126
+ dominus.release_console() # stop capturing
127
+ ```
128
+
129
+ ## Documentation
130
+
131
+ - [Architecture](docs/architecture.md) -- Request flow, resilience, JWT verification
132
+ - [Services Reference](docs/services.md) -- Complete namespace and method inventory
133
+ - [Development](docs/development.md) -- Setup, testing, adding APIs
134
+
135
+ ## License
136
+
137
+ Proprietary - CareBridge Systems
@@ -100,6 +100,12 @@ from .namespaces.courier import CourierNamespace
100
100
  from .namespaces.health import HealthNamespace
101
101
  from .namespaces.open import OpenNamespace
102
102
 
103
+ # Export new namespaces (Node.js SDK parity)
104
+ from .namespaces.artifacts import ArtifactsNamespace
105
+ from .namespaces.jobs import JobsNamespace
106
+ from .namespaces.processor import ProcessorNamespace
107
+ from .namespaces.sync import SyncNamespace
108
+
103
109
  # Export Oracle namespace for speech-to-text
104
110
  from .namespaces.oracle import (
105
111
  OracleNamespace,
@@ -146,7 +152,7 @@ from .errors import (
146
152
  TimeoutError as DominusTimeoutError,
147
153
  )
148
154
 
149
- __version__ = "2.10.0"
155
+ __version__ = "2.13.0"
150
156
  __all__ = [
151
157
  # Main SDK instance
152
158
  "dominus",
@@ -175,6 +181,11 @@ __all__ = [
175
181
  "CourierNamespace",
176
182
  "HealthNamespace",
177
183
  "OpenNamespace",
184
+ # New namespaces (Node.js SDK parity)
185
+ "ArtifactsNamespace",
186
+ "JobsNamespace",
187
+ "ProcessorNamespace",
188
+ "SyncNamespace",
178
189
  # Oracle namespace for speech-to-text
179
190
  "OracleNamespace",
180
191
  "OracleSession",
@@ -611,41 +611,26 @@ def verify_token_format(token: str) -> bool:
611
611
 
612
612
  async def health_check_all(base_url: str) -> dict:
613
613
  """
614
- Check health of orchestrator services.
614
+ Validate SDK readiness.
615
+
616
+ Previously checked orchestrator health via /api/health, but orchestrator
617
+ health is no longer a gate for SDK operations. Services route through
618
+ the gateway, and each service handles its own health independently.
619
+
620
+ Now just validates the base URL is set and returns healthy.
621
+ Orchestrator health checks are only relevant for courier/oracle
622
+ which will be refactored separately.
615
623
 
616
624
  Args:
617
- base_url: Orchestrator base URL
625
+ base_url: Gateway/orchestrator base URL
618
626
 
619
627
  Returns:
620
- Health status dict with service results
628
+ Health status dict (always healthy if base_url is set)
621
629
  """
622
- from ..config.endpoints import get_proxy_config
623
- proxy_config = get_proxy_config()
624
-
625
- results = {}
626
-
627
- # Check orchestrator via /api/health
628
- # Timeout: 15s to handle cold starts on Cloud Run
629
- try:
630
- start = time.time()
631
- async with httpx.AsyncClient(base_url=base_url, timeout=15.0, proxies=proxy_config) as client:
632
- response = await client.get("/api/health")
633
- response.raise_for_status()
634
-
635
- # Parse response (may be JSON string or dict)
636
- health_data = response.json() if response.headers.get("content-type", "").startswith("application/json") else {"status": "ok"}
637
-
638
- latency = int((time.time() - start) * 1000)
639
- results["orchestrator"] = {
640
- "status": health_data.get("status", "healthy"),
641
- "latency_ms": latency,
642
- **health_data
643
- }
644
- except Exception as e:
645
- results["orchestrator"] = {"status": "unhealthy", "error": str(e)}
646
- return {"status": "unhealthy", "services": results, "message": "Orchestrator unhealthy"}
630
+ if not base_url:
631
+ return {"status": "unhealthy", "services": {}, "message": "No base URL configured"}
647
632
 
648
- return {"status": "healthy", "services": results, "message": "All services healthy"}
633
+ return {"status": "healthy", "services": {}, "message": "SDK ready"}
649
634
 
650
635
 
651
636
  async def get_service_url(service_name: str, token: str, sovereign_url: str) -> str:
@@ -1,4 +1,4 @@
1
- """Dominus SDK Namespaces v2.8"""
1
+ """Dominus SDK Namespaces v2.9"""
2
2
  from .secrets import SecretsNamespace
3
3
  from .db import DbNamespace
4
4
  from .redis import RedisNamespace
@@ -11,6 +11,10 @@ from .health import HealthNamespace
11
11
  from .portal import PortalNamespace
12
12
  from .courier import CourierNamespace
13
13
  from .workflow import WorkflowNamespace
14
+ from .artifacts import ArtifactsNamespace
15
+ from .jobs import JobsNamespace
16
+ from .processor import ProcessorNamespace
17
+ from .sync import SyncNamespace
14
18
  from .ai import (
15
19
  AiNamespace,
16
20
  RagSubNamespace,
@@ -32,6 +36,10 @@ __all__ = [
32
36
  "PortalNamespace",
33
37
  "CourierNamespace",
34
38
  "WorkflowNamespace",
39
+ "ArtifactsNamespace",
40
+ "JobsNamespace",
41
+ "ProcessorNamespace",
42
+ "SyncNamespace",
35
43
  "AiNamespace",
36
44
  "RagSubNamespace",
37
45
  "ArtifactsSubNamespace",
@@ -0,0 +1,150 @@
1
+ """
2
+ Artifacts Namespace - Temporary artifact storage.
3
+
4
+ Provides auto-tiered artifact storage (Redis < 1MB, B2 >= 1MB)
5
+ with TTL-based expiration. Routes through gateway to artifact-worker.
6
+
7
+ Usage:
8
+ from dominus import dominus
9
+
10
+ # Store
11
+ result = await dominus.artifacts.store(data="base64data...", ttl_seconds=7200)
12
+
13
+ # Retrieve
14
+ artifact = await dominus.artifacts.retrieve(result["key"])
15
+
16
+ # List
17
+ items = await dominus.artifacts.list(category="reports")
18
+
19
+ # Delete
20
+ await dominus.artifacts.delete(result["key"])
21
+ """
22
+ from typing import Any, Dict, List, Optional, TYPE_CHECKING
23
+
24
+ if TYPE_CHECKING:
25
+ from ..start import Dominus
26
+
27
+
28
+ class ArtifactsNamespace:
29
+ """
30
+ Artifact storage namespace.
31
+
32
+ Auto-tiered: data < 1MB stored in Redis, >= 1MB in Backblaze B2.
33
+ All operations route through gateway to artifact-worker.
34
+ """
35
+
36
+ def __init__(self, client: "Dominus"):
37
+ self._client = client
38
+
39
+ async def _api(
40
+ self,
41
+ endpoint: str,
42
+ method: str = "POST",
43
+ body: Optional[Dict[str, Any]] = None,
44
+ timeout: float = 30.0,
45
+ ) -> Dict[str, Any]:
46
+ """Make gateway-routed request to artifact-worker."""
47
+ return await self._client._request(
48
+ endpoint=endpoint,
49
+ method=method,
50
+ body=body,
51
+ use_gateway=True,
52
+ timeout=timeout,
53
+ )
54
+
55
+ async def list(
56
+ self,
57
+ limit: int = 100,
58
+ category: Optional[str] = None,
59
+ ) -> Dict[str, Any]:
60
+ """
61
+ List artifacts for the current project/environment.
62
+
63
+ Args:
64
+ limit: Max items to return (default 100, max 500)
65
+ category: Optional category filter
66
+
67
+ Returns:
68
+ {artifacts: [...], count: int, total_size_bytes: int}
69
+ """
70
+ body: Dict[str, Any] = {"limit": limit}
71
+ if category:
72
+ body["category"] = category
73
+ return await self._api("/api/artifact/list", body=body)
74
+
75
+ async def get_health(self) -> Dict[str, Any]:
76
+ """Check artifact worker health."""
77
+ return await self._api("/api/artifact/health", method="GET")
78
+
79
+ async def store(
80
+ self,
81
+ data: str,
82
+ key: Optional[str] = None,
83
+ ttl_seconds: int = 3600,
84
+ category: Optional[str] = None,
85
+ ) -> Dict[str, Any]:
86
+ """
87
+ Store an artifact.
88
+
89
+ Args:
90
+ data: Base64-encoded data
91
+ key: Optional caller-provided key (UUID generated if not provided)
92
+ ttl_seconds: Time-to-live in seconds (default 3600)
93
+ category: Optional category for organization
94
+
95
+ Returns:
96
+ {key, ref, storage_type, size_bytes, expires_at}
97
+ """
98
+ body: Dict[str, Any] = {
99
+ "data": data,
100
+ "ttl_seconds": ttl_seconds,
101
+ }
102
+ if key:
103
+ body["key"] = key
104
+ if category:
105
+ body["category"] = category
106
+ return await self._api("/api/artifact/store", body=body)
107
+
108
+ async def retrieve(self, key: str) -> Dict[str, Any]:
109
+ """
110
+ Retrieve an artifact by key.
111
+
112
+ Args:
113
+ key: Artifact key
114
+
115
+ Returns:
116
+ {key, data, storage_type, size_bytes, expires_at}
117
+ """
118
+ return await self._api("/api/artifact/retrieve", body={"key": key})
119
+
120
+ async def delete(self, key: str) -> Dict[str, Any]:
121
+ """
122
+ Delete an artifact by key.
123
+
124
+ Args:
125
+ key: Artifact key
126
+
127
+ Returns:
128
+ {deleted: bool, key: str}
129
+ """
130
+ return await self._api("/api/artifact/delete", body={"key": key})
131
+
132
+ async def cleanup(
133
+ self,
134
+ force: bool = False,
135
+ limit: int = 100,
136
+ ) -> Dict[str, Any]:
137
+ """
138
+ Cleanup expired artifacts (admin only).
139
+
140
+ Args:
141
+ force: Skip throttle check
142
+ limit: Max items to clean (default 100)
143
+
144
+ Returns:
145
+ {cleaned: int, skipped: bool}
146
+ """
147
+ body: Dict[str, Any] = {"limit": limit}
148
+ if force:
149
+ body["force"] = True
150
+ return await self._api("/api/artifact/cleanup", body=body)
@@ -153,6 +153,63 @@ class AuthNamespace:
153
153
  body={"password": password}
154
154
  )
155
155
 
156
+ # User profiles
157
+ async def get_user_profile(self, user_id: str) -> Optional[Dict[str, Any]]:
158
+ """Get user profile by user_id. Returns None if no profile exists."""
159
+ result = await self._client._request(
160
+ endpoint=f"/api/guardian/user-profiles?user_id={user_id}&limit=1",
161
+ method="GET"
162
+ )
163
+ items = result if isinstance(result, list) else (result.get("data", []) if isinstance(result, dict) else [])
164
+ return items[0] if items else None
165
+
166
+ async def create_user_profile(
167
+ self,
168
+ user_id: str,
169
+ first_name: Optional[str] = None,
170
+ last_name: Optional[str] = None,
171
+ display_name: Optional[str] = None,
172
+ avatar_url: Optional[str] = None,
173
+ ) -> Dict[str, Any]:
174
+ """Create a user profile."""
175
+ body: Dict[str, Any] = {"user_id": user_id}
176
+ if first_name is not None:
177
+ body["first_name"] = first_name
178
+ if last_name is not None:
179
+ body["last_name"] = last_name
180
+ if display_name is not None:
181
+ body["display_name"] = display_name
182
+ if avatar_url is not None:
183
+ body["avatar_url"] = avatar_url
184
+ return await self._client._request(
185
+ endpoint="/api/guardian/user-profiles",
186
+ body=body
187
+ )
188
+
189
+ async def update_user_profile(
190
+ self,
191
+ profile_id: str,
192
+ first_name: Optional[str] = None,
193
+ last_name: Optional[str] = None,
194
+ display_name: Optional[str] = None,
195
+ avatar_url: Optional[str] = None,
196
+ ) -> Dict[str, Any]:
197
+ """Update a user profile."""
198
+ body: Dict[str, Any] = {}
199
+ if first_name is not None:
200
+ body["first_name"] = first_name
201
+ if last_name is not None:
202
+ body["last_name"] = last_name
203
+ if display_name is not None:
204
+ body["display_name"] = display_name
205
+ if avatar_url is not None:
206
+ body["avatar_url"] = avatar_url
207
+ return await self._client._request(
208
+ endpoint=f"/api/guardian/user-profiles/{profile_id}",
209
+ method="PUT",
210
+ body=body
211
+ )
212
+
156
213
  # User junction tables
157
214
  async def get_user_roles(self, user_id: str) -> List[Dict[str, Any]]:
158
215
  """Get roles assigned to user."""
@@ -722,6 +779,7 @@ class AuthNamespace:
722
779
  self,
723
780
  status: Optional[str] = None,
724
781
  category_id: Optional[str] = None,
782
+ include_system: bool = False,
725
783
  limit: int = 100,
726
784
  offset: int = 0
727
785
  ) -> Dict[str, Any]:
@@ -731,6 +789,8 @@ class AuthNamespace:
731
789
  params += f"&status={status}"
732
790
  if category_id:
733
791
  params += f"&category_id={category_id}"
792
+ if include_system:
793
+ params += "&include_system=true"
734
794
 
735
795
  return await self._client._request(
736
796
  endpoint=f"/api/guardian/tenants{params}",
@@ -796,12 +856,16 @@ class AuthNamespace:
796
856
 
797
857
  async def list_tenant_categories(
798
858
  self,
859
+ include_system: bool = False,
799
860
  limit: int = 100,
800
861
  offset: int = 0
801
862
  ) -> Dict[str, Any]:
802
863
  """List all tenant categories."""
864
+ params = f"?limit={limit}&offset={offset}"
865
+ if include_system:
866
+ params += "&include_system=true"
803
867
  return await self._client._request(
804
- endpoint=f"/api/guardian/tenant-categories?limit={limit}&offset={offset}",
868
+ endpoint=f"/api/guardian/tenant-categories{params}",
805
869
  method="GET"
806
870
  )
807
871