dominus-sdk-python-dev 2.1.6__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.
@@ -0,0 +1,299 @@
1
+ """
2
+ Files Namespace - Archivist object storage operations.
3
+
4
+ Provides file upload, download, and management via B2 object storage.
5
+ """
6
+ import base64
7
+ from typing import Any, Dict, List, Optional, TYPE_CHECKING
8
+
9
+ if TYPE_CHECKING:
10
+ from ..start import Dominus
11
+
12
+
13
+ class FilesNamespace:
14
+ """
15
+ Object storage namespace.
16
+
17
+ All file operations go through /api/archivist/* endpoints.
18
+ Supports compliance mode for files requiring audit trails and retention.
19
+
20
+ Usage:
21
+ # Upload a file
22
+ result = await dominus.files.upload(
23
+ data=file_bytes,
24
+ filename="report.pdf",
25
+ category="documents"
26
+ )
27
+
28
+ # Upload compliance file
29
+ result = await dominus.files.upload(
30
+ data=pdf_bytes,
31
+ filename="consent.pdf",
32
+ compliance=True,
33
+ actor=current_user_id,
34
+ retention_days=365 * 7
35
+ )
36
+
37
+ # Download file (get presigned URL)
38
+ url_info = await dominus.files.download(file_id=result["id"])
39
+
40
+ # Fetch file content directly
41
+ content = await dominus.files.fetch(file_id=result["id"])
42
+ """
43
+
44
+ def __init__(self, client: "Dominus"):
45
+ self._client = client
46
+
47
+ async def upload(
48
+ self,
49
+ data: bytes,
50
+ filename: str,
51
+ content_type: Optional[str] = None,
52
+ category: str = "general",
53
+ path: Optional[str] = None,
54
+ tags: Optional[Dict[str, str]] = None,
55
+ compliance: bool = False,
56
+ actor: Optional[str] = None,
57
+ retention_days: int = 90
58
+ ) -> Dict[str, Any]:
59
+ """
60
+ Upload a file to object storage.
61
+
62
+ Args:
63
+ data: File content as bytes
64
+ filename: Original filename
65
+ content_type: MIME type (auto-detected if not provided)
66
+ category: File category (default: "general")
67
+ path: Logical path within category (default: auto-generated)
68
+ tags: Optional metadata tags
69
+ compliance: If True, enables audit trail and retention
70
+ actor: User ID or "machine" (required if compliance=True)
71
+ retention_days: Retention period for compliance files (default: 90)
72
+
73
+ Returns:
74
+ Dict with file ID, path, size, and metadata
75
+ """
76
+ # Base64 encode the file content
77
+ file_b64 = base64.b64encode(data).decode('utf-8')
78
+
79
+ body = {
80
+ "file_content": file_b64,
81
+ "filename": filename,
82
+ "category": category,
83
+ "logical_path": path or filename
84
+ }
85
+
86
+ if content_type:
87
+ body["content_type"] = content_type
88
+ if tags:
89
+ body["tags"] = tags
90
+
91
+ # Compliance mode
92
+ if compliance:
93
+ body["is_compliance"] = True
94
+ body["retention_days"] = retention_days
95
+ if actor:
96
+ body["owner_user_id"] = actor
97
+
98
+ return await self._client._request(
99
+ endpoint="/api/archivist/upload",
100
+ body=body
101
+ )
102
+
103
+ async def download(
104
+ self,
105
+ file_id: Optional[str] = None,
106
+ category: Optional[str] = None,
107
+ path: Optional[str] = None,
108
+ actor: Optional[str] = None,
109
+ expires_seconds: int = 3600
110
+ ) -> Dict[str, Any]:
111
+ """
112
+ Get a presigned download URL for a file.
113
+
114
+ Args:
115
+ file_id: File UUID (preferred)
116
+ category: File category (alternative lookup with path)
117
+ path: Logical path (alternative lookup with category)
118
+ actor: User ID for audit (required for compliance files)
119
+ expires_seconds: URL expiration time (default: 1 hour)
120
+
121
+ Returns:
122
+ Dict with "download_url", "expires_at", and file metadata
123
+ """
124
+ body = {"expires_seconds": expires_seconds}
125
+
126
+ if file_id:
127
+ body["id"] = file_id
128
+ if category:
129
+ body["category"] = category
130
+ if path:
131
+ body["logical_path"] = path
132
+ if actor:
133
+ body["actor_user_id"] = actor
134
+
135
+ return await self._client._request(
136
+ endpoint="/api/archivist/download",
137
+ body=body
138
+ )
139
+
140
+ async def fetch(
141
+ self,
142
+ file_id: Optional[str] = None,
143
+ category: Optional[str] = None,
144
+ path: Optional[str] = None,
145
+ actor: Optional[str] = None
146
+ ) -> Dict[str, Any]:
147
+ """
148
+ Fetch file content directly.
149
+
150
+ Args:
151
+ file_id: File UUID (preferred)
152
+ category: File category (alternative lookup with path)
153
+ path: Logical path (alternative lookup with category)
154
+ actor: User ID for audit (required for compliance files)
155
+
156
+ Returns:
157
+ Dict with "data" (base64 encoded), "filename", "content_type"
158
+ """
159
+ body = {}
160
+
161
+ if file_id:
162
+ body["id"] = file_id
163
+ if category:
164
+ body["category"] = category
165
+ if path:
166
+ body["logical_path"] = path
167
+ if actor:
168
+ body["actor_user_id"] = actor
169
+
170
+ return await self._client._request(
171
+ endpoint="/api/archivist/fetch",
172
+ body=body
173
+ )
174
+
175
+ async def list(
176
+ self,
177
+ category: Optional[str] = None,
178
+ prefix: Optional[str] = None,
179
+ limit: int = 100,
180
+ cursor: Optional[str] = None
181
+ ) -> Dict[str, Any]:
182
+ """
183
+ List files with optional filtering.
184
+
185
+ Args:
186
+ category: Filter by category
187
+ prefix: Filter by path prefix
188
+ limit: Maximum files to return (default: 100)
189
+ cursor: Pagination cursor
190
+
191
+ Returns:
192
+ Dict with "objects" list, "cursor", "count"
193
+ """
194
+ body = {"limit": limit}
195
+
196
+ if category:
197
+ body["category"] = category
198
+ if prefix:
199
+ body["prefix"] = prefix
200
+ if cursor:
201
+ body["cursor"] = cursor
202
+
203
+ return await self._client._request(
204
+ endpoint="/api/archivist/list",
205
+ body=body
206
+ )
207
+
208
+ async def delete(
209
+ self,
210
+ file_id: Optional[str] = None,
211
+ category: Optional[str] = None,
212
+ path: Optional[str] = None,
213
+ actor: Optional[str] = None
214
+ ) -> Dict[str, Any]:
215
+ """
216
+ Delete a file.
217
+
218
+ Args:
219
+ file_id: File UUID (preferred)
220
+ category: File category (alternative lookup with path)
221
+ path: Logical path (alternative lookup with category)
222
+ actor: User ID for audit
223
+
224
+ Returns:
225
+ Dict with "deleted" status
226
+ """
227
+ body = {}
228
+
229
+ if file_id:
230
+ body["id"] = file_id
231
+ if category:
232
+ body["category"] = category
233
+ if path:
234
+ body["logical_path"] = path
235
+ if actor:
236
+ body["actor_user_id"] = actor
237
+
238
+ return await self._client._request(
239
+ endpoint="/api/archivist/delete",
240
+ body=body
241
+ )
242
+
243
+ async def move(
244
+ self,
245
+ file_id: str,
246
+ new_category: Optional[str] = None,
247
+ new_path: Optional[str] = None
248
+ ) -> Dict[str, Any]:
249
+ """
250
+ Move or rename a file.
251
+
252
+ Args:
253
+ file_id: File UUID
254
+ new_category: New category (optional)
255
+ new_path: New logical path (optional)
256
+
257
+ Returns:
258
+ Updated file metadata
259
+ """
260
+ body = {"id": file_id}
261
+
262
+ if new_category:
263
+ body["new_category"] = new_category
264
+ if new_path:
265
+ body["new_logical_path"] = new_path
266
+
267
+ return await self._client._request(
268
+ endpoint="/api/archivist/move",
269
+ body=body
270
+ )
271
+
272
+ async def update_meta(
273
+ self,
274
+ file_id: str,
275
+ tags: Optional[Dict[str, str]] = None,
276
+ description: Optional[str] = None
277
+ ) -> Dict[str, Any]:
278
+ """
279
+ Update file metadata.
280
+
281
+ Args:
282
+ file_id: File UUID
283
+ tags: New metadata tags (replaces existing)
284
+ description: New description
285
+
286
+ Returns:
287
+ Updated file metadata
288
+ """
289
+ body = {"id": file_id}
290
+
291
+ if tags is not None:
292
+ body["tags"] = tags
293
+ if description is not None:
294
+ body["description"] = description
295
+
296
+ return await self._client._request(
297
+ endpoint="/api/archivist/update",
298
+ body=body
299
+ )
@@ -0,0 +1,59 @@
1
+ """
2
+ Health Namespace - Service health check operations.
3
+
4
+ Provides health check endpoints for the orchestrator service.
5
+ """
6
+ from typing import Any, Dict, TYPE_CHECKING
7
+
8
+ if TYPE_CHECKING:
9
+ from ..start import Dominus
10
+
11
+
12
+ class HealthNamespace:
13
+ """
14
+ Health check namespace.
15
+
16
+ Usage:
17
+ status = await dominus.health.check()
18
+ await dominus.health.ping()
19
+ await dominus.health.warmup()
20
+ """
21
+
22
+ def __init__(self, client: "Dominus"):
23
+ self._client = client
24
+
25
+ async def check(self) -> Dict[str, Any]:
26
+ """
27
+ Perform comprehensive health check of orchestrator and dependencies.
28
+
29
+ Returns:
30
+ Dict with "status", "latency_ms", and service-specific info
31
+ """
32
+ from ..helpers.core import health_check
33
+ from ..config.endpoints import get_base_url
34
+
35
+ return await health_check(get_base_url())
36
+
37
+ async def ping(self) -> Dict[str, Any]:
38
+ """
39
+ Simple ping check (fastest response).
40
+
41
+ Returns:
42
+ Dict with "status": "ok"
43
+ """
44
+ return await self._client._request(
45
+ endpoint="/api/health/ping",
46
+ method="GET"
47
+ )
48
+
49
+ async def warmup(self) -> Dict[str, Any]:
50
+ """
51
+ Warmup request (triggers cold start if needed).
52
+
53
+ Returns:
54
+ Dict with warmup status
55
+ """
56
+ return await self._client._request(
57
+ endpoint="/api/health/warmup",
58
+ method="GET"
59
+ )