digitalkin 0.2.23__py3-none-any.whl → 0.3.1.dev2__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.
Files changed (78) hide show
  1. digitalkin/__version__.py +1 -1
  2. digitalkin/core/__init__.py +1 -0
  3. digitalkin/core/common/__init__.py +9 -0
  4. digitalkin/core/common/factories.py +156 -0
  5. digitalkin/core/job_manager/__init__.py +1 -0
  6. digitalkin/{modules → core}/job_manager/base_job_manager.py +137 -31
  7. digitalkin/core/job_manager/single_job_manager.py +354 -0
  8. digitalkin/{modules → core}/job_manager/taskiq_broker.py +116 -22
  9. digitalkin/core/job_manager/taskiq_job_manager.py +541 -0
  10. digitalkin/core/task_manager/__init__.py +1 -0
  11. digitalkin/core/task_manager/base_task_manager.py +539 -0
  12. digitalkin/core/task_manager/local_task_manager.py +108 -0
  13. digitalkin/core/task_manager/remote_task_manager.py +87 -0
  14. digitalkin/core/task_manager/surrealdb_repository.py +266 -0
  15. digitalkin/core/task_manager/task_executor.py +249 -0
  16. digitalkin/core/task_manager/task_session.py +406 -0
  17. digitalkin/grpc_servers/__init__.py +1 -19
  18. digitalkin/grpc_servers/_base_server.py +3 -3
  19. digitalkin/grpc_servers/module_server.py +27 -43
  20. digitalkin/grpc_servers/module_servicer.py +51 -36
  21. digitalkin/grpc_servers/registry_server.py +2 -2
  22. digitalkin/grpc_servers/registry_servicer.py +4 -4
  23. digitalkin/grpc_servers/utils/__init__.py +1 -0
  24. digitalkin/grpc_servers/utils/exceptions.py +0 -8
  25. digitalkin/grpc_servers/utils/grpc_client_wrapper.py +4 -4
  26. digitalkin/grpc_servers/utils/grpc_error_handler.py +53 -0
  27. digitalkin/logger.py +73 -24
  28. digitalkin/mixins/__init__.py +19 -0
  29. digitalkin/mixins/base_mixin.py +10 -0
  30. digitalkin/mixins/callback_mixin.py +24 -0
  31. digitalkin/mixins/chat_history_mixin.py +110 -0
  32. digitalkin/mixins/cost_mixin.py +76 -0
  33. digitalkin/mixins/file_history_mixin.py +93 -0
  34. digitalkin/mixins/filesystem_mixin.py +46 -0
  35. digitalkin/mixins/logger_mixin.py +51 -0
  36. digitalkin/mixins/storage_mixin.py +79 -0
  37. digitalkin/models/core/__init__.py +1 -0
  38. digitalkin/{modules/job_manager → models/core}/job_manager_models.py +3 -3
  39. digitalkin/models/core/task_monitor.py +70 -0
  40. digitalkin/models/grpc_servers/__init__.py +1 -0
  41. digitalkin/{grpc_servers/utils → models/grpc_servers}/models.py +5 -5
  42. digitalkin/models/module/__init__.py +2 -0
  43. digitalkin/models/module/module.py +9 -1
  44. digitalkin/models/module/module_context.py +122 -6
  45. digitalkin/models/module/module_types.py +307 -19
  46. digitalkin/models/services/__init__.py +9 -0
  47. digitalkin/models/services/cost.py +1 -0
  48. digitalkin/models/services/storage.py +39 -5
  49. digitalkin/modules/_base_module.py +123 -118
  50. digitalkin/modules/tool_module.py +10 -2
  51. digitalkin/modules/trigger_handler.py +7 -6
  52. digitalkin/services/cost/__init__.py +9 -2
  53. digitalkin/services/cost/grpc_cost.py +9 -42
  54. digitalkin/services/filesystem/default_filesystem.py +0 -2
  55. digitalkin/services/filesystem/grpc_filesystem.py +10 -39
  56. digitalkin/services/setup/default_setup.py +5 -6
  57. digitalkin/services/setup/grpc_setup.py +52 -15
  58. digitalkin/services/storage/grpc_storage.py +4 -4
  59. digitalkin/services/user_profile/__init__.py +1 -0
  60. digitalkin/services/user_profile/default_user_profile.py +55 -0
  61. digitalkin/services/user_profile/grpc_user_profile.py +69 -0
  62. digitalkin/services/user_profile/user_profile_strategy.py +40 -0
  63. digitalkin/utils/__init__.py +28 -0
  64. digitalkin/utils/arg_parser.py +1 -1
  65. digitalkin/utils/development_mode_action.py +2 -2
  66. digitalkin/utils/dynamic_schema.py +483 -0
  67. digitalkin/utils/package_discover.py +1 -2
  68. {digitalkin-0.2.23.dist-info → digitalkin-0.3.1.dev2.dist-info}/METADATA +11 -30
  69. digitalkin-0.3.1.dev2.dist-info/RECORD +119 -0
  70. modules/dynamic_setup_module.py +362 -0
  71. digitalkin/grpc_servers/utils/factory.py +0 -180
  72. digitalkin/modules/job_manager/single_job_manager.py +0 -294
  73. digitalkin/modules/job_manager/taskiq_job_manager.py +0 -290
  74. digitalkin-0.2.23.dist-info/RECORD +0 -89
  75. /digitalkin/{grpc_servers/utils → models/grpc_servers}/types.py +0 -0
  76. {digitalkin-0.2.23.dist-info → digitalkin-0.3.1.dev2.dist-info}/WHEEL +0 -0
  77. {digitalkin-0.2.23.dist-info → digitalkin-0.3.1.dev2.dist-info}/licenses/LICENSE +0 -0
  78. {digitalkin-0.2.23.dist-info → digitalkin-0.3.1.dev2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,483 @@
1
+ """Dynamic schema utilities for runtime value refresh in Pydantic models.
2
+
3
+ This module provides a clean way to mark fields as dynamic using Annotated metadata,
4
+ allowing their schema values to be refreshed at runtime via sync or async fetchers.
5
+
6
+ Example:
7
+ from typing import Annotated
8
+ from digitalkin.utils import DynamicField
9
+
10
+ class AgentSetup(SetupModel):
11
+ model_name: Annotated[str, DynamicField(enum=fetch_models)] = Field(default="gpt-4")
12
+
13
+ See Also:
14
+ - Documentation: docs/api/dynamic_schema.md
15
+ - Tests: tests/utils/test_dynamic_schema.py
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import asyncio
21
+ import time
22
+ import traceback
23
+ from collections.abc import Awaitable, Callable
24
+ from dataclasses import dataclass, field
25
+ from itertools import starmap
26
+ from typing import TYPE_CHECKING, Any, TypeVar
27
+
28
+ from digitalkin.logger import logger
29
+
30
+ if TYPE_CHECKING:
31
+ from pydantic.fields import FieldInfo
32
+
33
+ T = TypeVar("T")
34
+
35
+ # Fetcher callable type: sync or async function with no arguments
36
+ Fetcher = Callable[[], T | Awaitable[T]]
37
+
38
+ # Default timeout for fetcher resolution (None = no timeout)
39
+ DEFAULT_TIMEOUT: float | None = None
40
+
41
+
42
+ @dataclass
43
+ class ResolveResult:
44
+ """Result of resolving dynamic fetchers.
45
+
46
+ Provides structured access to resolved values and any errors that occurred.
47
+ This allows callers to handle partial failures gracefully.
48
+
49
+ Attributes:
50
+ values: Dict mapping key names to successfully resolved values.
51
+ errors: Dict mapping key names to exceptions that occurred during resolution.
52
+ """
53
+
54
+ values: dict[str, Any] = field(default_factory=dict)
55
+ errors: dict[str, Exception] = field(default_factory=dict)
56
+
57
+ @property
58
+ def success(self) -> bool:
59
+ """Check if all fetchers resolved successfully.
60
+
61
+ Returns:
62
+ True if no errors occurred, False otherwise.
63
+ """
64
+ return len(self.errors) == 0
65
+
66
+ @property
67
+ def partial(self) -> bool:
68
+ """Check if some but not all fetchers succeeded.
69
+
70
+ Returns:
71
+ True if there are both values and errors, False otherwise.
72
+ """
73
+ return len(self.values) > 0 and len(self.errors) > 0
74
+
75
+ def get(self, key: str, default: T | None = None) -> T | None:
76
+ """Get a resolved value by key.
77
+
78
+ Args:
79
+ key: The fetcher key name.
80
+ default: Default value if key not found or errored.
81
+
82
+ Returns:
83
+ The resolved value or default.
84
+ """
85
+ return self.values.get(key, default) # type: ignore[return-value]
86
+
87
+
88
+ class DynamicField:
89
+ """Metadata class for Annotated fields with dynamic fetchers.
90
+
91
+ Use with typing.Annotated to mark fields that need runtime value resolution.
92
+ Fetchers are callables (sync or async) that return values at runtime.
93
+
94
+ Args:
95
+ **fetchers: Mapping of key names to fetcher callables.
96
+ Each fetcher is a function (sync or async) that takes no arguments
97
+ and returns the value for that key (e.g., enum values, defaults).
98
+
99
+ Example:
100
+ from typing import Annotated
101
+
102
+ async def fetch_models() -> list[str]:
103
+ return await api.get_models()
104
+
105
+ class Setup(SetupModel):
106
+ model: Annotated[str, DynamicField(enum=fetch_models)] = Field(default="gpt-4")
107
+ """
108
+
109
+ __slots__ = ("fetchers",)
110
+
111
+ def __init__(self, **fetchers: Fetcher[Any]) -> None:
112
+ """Initialize with fetcher callables."""
113
+ self.fetchers: dict[str, Fetcher[Any]] = fetchers
114
+
115
+ def __repr__(self) -> str:
116
+ """Return string representation."""
117
+ keys = ", ".join(self.fetchers.keys())
118
+ return f"DynamicField({keys})"
119
+
120
+ def __eq__(self, other: object) -> bool:
121
+ """Check equality based on fetchers.
122
+
123
+ Returns:
124
+ True if fetchers are equal, NotImplemented for non-DynamicField types.
125
+ """
126
+ if not isinstance(other, DynamicField):
127
+ return NotImplemented
128
+ return self.fetchers == other.fetchers
129
+
130
+ def __hash__(self) -> int:
131
+ """Hash based on fetcher keys (fetchers themselves aren't hashable).
132
+
133
+ Returns:
134
+ Hash value based on sorted fetcher keys.
135
+ """
136
+ return hash(tuple(sorted(self.fetchers.keys())))
137
+
138
+
139
+ def get_dynamic_metadata(field_info: FieldInfo) -> DynamicField | None:
140
+ """Extract DynamicField metadata from a FieldInfo's metadata list.
141
+
142
+ Args:
143
+ field_info: The Pydantic FieldInfo object to inspect.
144
+
145
+ Returns:
146
+ The DynamicField metadata instance if found, None otherwise.
147
+ """
148
+ for meta in field_info.metadata:
149
+ if isinstance(meta, DynamicField):
150
+ return meta
151
+ return None
152
+
153
+
154
+ def has_dynamic(field_info: FieldInfo) -> bool:
155
+ """Check if a field has DynamicField metadata.
156
+
157
+ Args:
158
+ field_info: The Pydantic FieldInfo object to check.
159
+
160
+ Returns:
161
+ True if the field has DynamicField metadata, False otherwise.
162
+ """
163
+ return get_dynamic_metadata(field_info) is not None
164
+
165
+
166
+ def get_fetchers(field_info: FieldInfo) -> dict[str, Fetcher[Any]]:
167
+ """Extract fetchers from a field's DynamicField metadata.
168
+
169
+ Args:
170
+ field_info: The Pydantic FieldInfo object to extract from.
171
+
172
+ Returns:
173
+ Dict mapping key names to fetcher callables, empty if no DynamicField metadata.
174
+ """
175
+ meta = get_dynamic_metadata(field_info)
176
+ if meta is None:
177
+ return {}
178
+ return meta.fetchers
179
+
180
+
181
+ def _get_fetcher_info(fetcher: Fetcher[Any]) -> str:
182
+ """Get descriptive info about a fetcher for logging.
183
+
184
+ Args:
185
+ fetcher: The fetcher callable.
186
+
187
+ Returns:
188
+ A string describing the fetcher (module.name or repr).
189
+ """
190
+ if hasattr(fetcher, "__module__") and hasattr(fetcher, "__qualname__"):
191
+ return f"{fetcher.__module__}.{fetcher.__qualname__}"
192
+ if hasattr(fetcher, "__name__"):
193
+ return fetcher.__name__
194
+ return repr(fetcher)
195
+
196
+
197
+ async def _resolve_one(key: str, fetcher: Fetcher[Any]) -> tuple[str, Any]:
198
+ """Resolve a single fetcher.
199
+
200
+ Args:
201
+ key: The fetcher key name.
202
+ fetcher: The fetcher callable.
203
+
204
+ Returns:
205
+ Tuple of (key, resolved_value).
206
+
207
+ Raises:
208
+ Exception: If the fetcher raises an exception.
209
+ """
210
+ fetcher_info = _get_fetcher_info(fetcher)
211
+ logger.debug(
212
+ "Resolving fetcher '%s' using %s",
213
+ key,
214
+ fetcher_info,
215
+ extra={"fetcher_key": key, "fetcher": fetcher_info},
216
+ )
217
+
218
+ start_time = time.perf_counter()
219
+
220
+ try:
221
+ result = fetcher()
222
+ is_async = asyncio.iscoroutine(result)
223
+
224
+ if is_async:
225
+ logger.debug(
226
+ "Fetcher '%s' returned coroutine, awaiting...",
227
+ key,
228
+ extra={"fetcher_key": key, "is_async": True},
229
+ )
230
+ result = await result
231
+
232
+ except Exception as e:
233
+ elapsed_ms = (time.perf_counter() - start_time) * 1000
234
+ logger.error(
235
+ "Fetcher '%s' (%s) failed after %.2fms: %s: %s",
236
+ key,
237
+ fetcher_info,
238
+ elapsed_ms,
239
+ type(e).__name__,
240
+ str(e) or "(no message)",
241
+ extra={
242
+ "fetcher_key": key,
243
+ "fetcher": fetcher_info,
244
+ "elapsed_ms": elapsed_ms,
245
+ "error_type": type(e).__name__,
246
+ "error_message": str(e),
247
+ "traceback": traceback.format_exc(),
248
+ },
249
+ )
250
+ raise
251
+
252
+ elapsed_ms = (time.perf_counter() - start_time) * 1000
253
+
254
+ logger.debug(
255
+ "Fetcher '%s' resolved successfully in %.2fms, result type: %s",
256
+ key,
257
+ elapsed_ms,
258
+ type(result).__name__,
259
+ extra={
260
+ "fetcher_key": key,
261
+ "elapsed_ms": elapsed_ms,
262
+ "result_type": type(result).__name__,
263
+ },
264
+ )
265
+
266
+ return key, result
267
+
268
+
269
+ async def resolve(
270
+ fetchers: dict[str, Fetcher[Any]],
271
+ *,
272
+ timeout: float | None = DEFAULT_TIMEOUT,
273
+ ) -> dict[str, Any]:
274
+ """Resolve all dynamic fetchers to their actual values in parallel.
275
+
276
+ Fetchers are executed concurrently using asyncio.gather() for better
277
+ performance when multiple async fetchers are involved.
278
+
279
+ Args:
280
+ fetchers: Dict mapping key names to fetcher callables.
281
+ timeout: Optional timeout in seconds for all fetchers combined.
282
+ If None (default), no timeout is applied.
283
+
284
+ Returns:
285
+ Dict mapping key names to resolved values.
286
+
287
+ Raises:
288
+ asyncio.TimeoutError: If timeout is exceeded.
289
+ Exception: If any fetcher raises an exception, it is propagated.
290
+
291
+ Example:
292
+ fetchers = {"enum": fetch_models, "default": get_default}
293
+ resolved = await resolve(fetchers, timeout=5.0)
294
+ # resolved = {"enum": ["gpt-4", "gpt-3.5"], "default": "gpt-4"}
295
+ """
296
+ if not fetchers:
297
+ logger.debug("resolve() called with empty fetchers, returning {}")
298
+ return {}
299
+
300
+ fetcher_keys = list(fetchers.keys())
301
+ fetcher_infos = {k: _get_fetcher_info(f) for k, f in fetchers.items()}
302
+
303
+ logger.info(
304
+ "resolve() starting parallel resolution of %d fetcher(s): %s",
305
+ len(fetchers),
306
+ fetcher_keys,
307
+ extra={
308
+ "fetcher_count": len(fetchers),
309
+ "fetcher_keys": fetcher_keys,
310
+ "fetcher_infos": fetcher_infos,
311
+ "timeout": timeout,
312
+ },
313
+ )
314
+
315
+ start_time = time.perf_counter()
316
+
317
+ # Create tasks for parallel execution
318
+ tasks = list(starmap(_resolve_one, fetchers.items()))
319
+
320
+ # Execute with optional timeout
321
+ try:
322
+ if timeout is not None:
323
+ results = await asyncio.wait_for(asyncio.gather(*tasks), timeout=timeout)
324
+ else:
325
+ results = await asyncio.gather(*tasks)
326
+ except asyncio.TimeoutError:
327
+ elapsed_ms = (time.perf_counter() - start_time) * 1000
328
+ logger.error(
329
+ "resolve() timed out after %.2fms (timeout=%.2fs)",
330
+ elapsed_ms,
331
+ timeout,
332
+ extra={"elapsed_ms": elapsed_ms, "timeout": timeout},
333
+ )
334
+ raise
335
+
336
+ elapsed_ms = (time.perf_counter() - start_time) * 1000
337
+ logger.info(
338
+ "resolve() completed successfully in %.2fms, resolved %d fetcher(s)",
339
+ elapsed_ms,
340
+ len(results),
341
+ extra={"elapsed_ms": elapsed_ms, "resolved_count": len(results)},
342
+ )
343
+
344
+ return dict(results)
345
+
346
+
347
+ async def resolve_safe(
348
+ fetchers: dict[str, Fetcher[Any]],
349
+ *,
350
+ timeout: float | None = DEFAULT_TIMEOUT,
351
+ ) -> ResolveResult:
352
+ """Resolve fetchers with structured error handling.
353
+
354
+ Unlike `resolve()`, this function catches individual fetcher errors
355
+ and returns them in a structured result, allowing partial success.
356
+
357
+ Args:
358
+ fetchers: Dict mapping key names to fetcher callables.
359
+ timeout: Optional timeout in seconds for all fetchers combined.
360
+ If None (default), no timeout is applied. Note: timeout applies
361
+ to the entire operation, not individual fetchers.
362
+
363
+ Returns:
364
+ ResolveResult with values and any errors that occurred.
365
+
366
+ Example:
367
+ result = await resolve_safe(fetchers, timeout=5.0)
368
+ if result.success:
369
+ print("All resolved:", result.values)
370
+ elif result.partial:
371
+ print("Partial success:", result.values)
372
+ print("Errors:", result.errors)
373
+ else:
374
+ print("All failed:", result.errors)
375
+ """
376
+ if not fetchers:
377
+ logger.debug("resolve_safe() called with empty fetchers, returning empty ResolveResult")
378
+ return ResolveResult()
379
+
380
+ fetcher_keys = list(fetchers.keys())
381
+ fetcher_infos = {k: _get_fetcher_info(f) for k, f in fetchers.items()}
382
+
383
+ logger.info(
384
+ "resolve_safe() starting parallel resolution of %d fetcher(s): %s",
385
+ len(fetchers),
386
+ fetcher_keys,
387
+ extra={
388
+ "fetcher_count": len(fetchers),
389
+ "fetcher_keys": fetcher_keys,
390
+ "fetcher_infos": fetcher_infos,
391
+ "timeout": timeout,
392
+ },
393
+ )
394
+
395
+ start_time = time.perf_counter()
396
+ result = ResolveResult()
397
+
398
+ async def safe_resolve_one(key: str, fetcher: Fetcher[Any]) -> None:
399
+ """Resolve one fetcher, capturing errors."""
400
+ try:
401
+ _, value = await _resolve_one(key, fetcher)
402
+ result.values[key] = value
403
+ except Exception as e:
404
+ # Error already logged in _resolve_one, just capture it
405
+ result.errors[key] = e
406
+
407
+ # Create tasks for parallel execution
408
+ tasks = list(starmap(safe_resolve_one, fetchers.items()))
409
+
410
+ try:
411
+ if timeout is not None:
412
+ await asyncio.wait_for(asyncio.gather(*tasks), timeout=timeout)
413
+ else:
414
+ await asyncio.gather(*tasks)
415
+ except asyncio.TimeoutError as e:
416
+ elapsed_ms = (time.perf_counter() - start_time) * 1000
417
+ # Add timeout error for any keys that didn't complete
418
+ resolved_keys = set(result.values.keys()) | set(result.errors.keys())
419
+ timed_out_keys = [key for key in fetchers if key not in resolved_keys]
420
+ for key in timed_out_keys:
421
+ result.errors[key] = e
422
+
423
+ logger.error(
424
+ "resolve_safe() timed out after %.2fms (timeout=%.2fs), %d succeeded, %d failed, %d timed out",
425
+ elapsed_ms,
426
+ timeout,
427
+ len(result.values),
428
+ len(result.errors) - len(timed_out_keys),
429
+ len(timed_out_keys),
430
+ extra={
431
+ "elapsed_ms": elapsed_ms,
432
+ "timeout": timeout,
433
+ "succeeded_keys": list(result.values.keys()),
434
+ "failed_keys": [k for k in result.errors if k not in timed_out_keys],
435
+ "timed_out_keys": timed_out_keys,
436
+ },
437
+ )
438
+
439
+ elapsed_ms = (time.perf_counter() - start_time) * 1000
440
+
441
+ # Log summary
442
+ if result.success:
443
+ logger.info(
444
+ "resolve_safe() completed successfully in %.2fms, all %d fetcher(s) resolved",
445
+ elapsed_ms,
446
+ len(result.values),
447
+ extra={
448
+ "elapsed_ms": elapsed_ms,
449
+ "success": True,
450
+ "resolved_count": len(result.values),
451
+ },
452
+ )
453
+ elif result.partial:
454
+ logger.warning(
455
+ "resolve_safe() completed with partial success in %.2fms: %d succeeded, %d failed",
456
+ elapsed_ms,
457
+ len(result.values),
458
+ len(result.errors),
459
+ extra={
460
+ "elapsed_ms": elapsed_ms,
461
+ "success": False,
462
+ "partial": True,
463
+ "resolved_count": len(result.values),
464
+ "error_count": len(result.errors),
465
+ "succeeded_keys": list(result.values.keys()),
466
+ "failed_keys": list(result.errors.keys()),
467
+ },
468
+ )
469
+ else:
470
+ logger.error(
471
+ "resolve_safe() completed with all failures in %.2fms: %d failed",
472
+ elapsed_ms,
473
+ len(result.errors),
474
+ extra={
475
+ "elapsed_ms": elapsed_ms,
476
+ "success": False,
477
+ "partial": False,
478
+ "error_count": len(result.errors),
479
+ "failed_keys": list(result.errors.keys()),
480
+ },
481
+ )
482
+
483
+ return result
@@ -1,4 +1,4 @@
1
- """."""
1
+ """Secure module discovery and import utility for trigger handlers."""
2
2
 
3
3
  import importlib
4
4
  import importlib.util
@@ -276,7 +276,6 @@ class ModuleDiscoverer:
276
276
  Args:
277
277
  packages: List of package names to scan.
278
278
  file_pattern: Glob pattern for matching modules.
279
- safe_mode: If True, blocks modules with forbidden names.
280
279
  max_file_size: Limit for module file sizes in bytes.
281
280
  """
282
281
  self.packages = packages
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: digitalkin
3
- Version: 0.2.23
3
+ Version: 0.3.1.dev2
4
4
  Summary: SDK to build kin used in DigitalKin
5
5
  Author-email: "DigitalKin.ai" <contact@digitalkin.ai>
6
6
  License: Attribution-NonCommercial-ShareAlike 4.0 International
@@ -452,36 +452,17 @@ Classifier: License :: Other/Proprietary License
452
452
  Requires-Python: >=3.10
453
453
  Description-Content-Type: text/markdown
454
454
  License-File: LICENSE
455
- Requires-Dist: digitalkin-proto>=0.1.16
456
- Requires-Dist: grpcio-health-checking>=1.71.0
457
- Requires-Dist: grpcio-reflection>=1.71.0
458
- Requires-Dist: grpcio-status>=1.71.0
459
- Requires-Dist: pydantic>=2.11.5
460
- Provides-Extra: dev
461
- Requires-Dist: typos>=1.34.0; extra == "dev"
462
- Requires-Dist: ruff>=0.12.5; extra == "dev"
463
- Requires-Dist: mypy>=1.17.0; extra == "dev"
464
- Requires-Dist: pyright>=1.1.403; extra == "dev"
465
- Requires-Dist: pre-commit>=4.3.0; extra == "dev"
466
- Requires-Dist: bump2version>=1.0.1; extra == "dev"
467
- Requires-Dist: build>=1.3.0; extra == "dev"
468
- Requires-Dist: twine>=6.1.0; extra == "dev"
469
- Requires-Dist: cryptography>=45.0.5; extra == "dev"
470
- Provides-Extra: examples
471
- Requires-Dist: openai>=1.75.0; extra == "examples"
472
- Provides-Extra: tests
473
- Requires-Dist: freezegun>=1.5.3; extra == "tests"
474
- Requires-Dist: hdrhistogram>=0.10.3; extra == "tests"
475
- Requires-Dist: grpcio-testing>=1.71.0; extra == "tests"
476
- Requires-Dist: psutil>=7.0.0; extra == "tests"
477
- Requires-Dist: pytest>=8.4.0; extra == "tests"
478
- Requires-Dist: pytest-asyncio>=1.1.0; extra == "tests"
479
- Requires-Dist: pytest-cov>=6.1.0; extra == "tests"
455
+ Requires-Dist: digitalkin-proto==0.2.0.dev5
456
+ Requires-Dist: grpcio-health-checking>=1.76.0
457
+ Requires-Dist: grpcio-reflection>=1.76.0
458
+ Requires-Dist: grpcio-status>=1.76.0
459
+ Requires-Dist: pydantic>=2.12.5
460
+ Requires-Dist: surrealdb>=1.0.6
480
461
  Provides-Extra: taskiq
481
- Requires-Dist: rstream>=0.30.0; extra == "taskiq"
482
- Requires-Dist: taskiq-aio-pika>=0.4.3; extra == "taskiq"
483
- Requires-Dist: taskiq-redis>=1.1.0; extra == "taskiq"
484
- Requires-Dist: taskiq[reload]>=0.11.18; extra == "taskiq"
462
+ Requires-Dist: rstream>=0.40.0; extra == "taskiq"
463
+ Requires-Dist: taskiq-aio-pika>=0.5.0; extra == "taskiq"
464
+ Requires-Dist: taskiq-redis>=1.1.2; extra == "taskiq"
465
+ Requires-Dist: taskiq[reload]>=0.12.0; extra == "taskiq"
485
466
  Dynamic: license-file
486
467
 
487
468
  # DigitalKin Python SDK
@@ -0,0 +1,119 @@
1
+ base_server/__init__.py,sha256=gs8t9Dg0dNVHRdYYbEQY8bn8tzEUv2zE6eBhKNPG3kU,88
2
+ base_server/server_async_insecure.py,sha256=Rvj5Xj8tDMglAj6aOGlQdMeD-FL97_OBEhHYHxxQrVo,3887
3
+ base_server/server_async_secure.py,sha256=SV_CqEmD6YNHHP2Y369T2PLPJ-9JG3bvXytchX_Ensk,4684
4
+ base_server/server_sync_insecure.py,sha256=VgSH8YghagK3fiwHhc7d6__zjN6lj_FgBUponFbOoxM,3127
5
+ base_server/server_sync_secure.py,sha256=MMkq67vAZNiDLJSySjoXtHIEIK1pAlRz57n75Egnndk,3939
6
+ base_server/mock/__init__.py,sha256=YZFT-F1l_TpvJYuIPX-7kTeE1CfOjhx9YmNRXVoi-jQ,143
7
+ base_server/mock/mock_pb2.py,sha256=sETakcS3PAAm4E-hTCV1jIVaQTPEAIoVVHupB8Z_k7Y,1843
8
+ base_server/mock/mock_pb2_grpc.py,sha256=BbOT70H6q3laKgkHfOx1QdfmCS_HxCY4wCOX84YAdG4,3180
9
+ digitalkin/__init__.py,sha256=7LLBAba0th-3SGqcpqFO-lopWdUkVLKzLZiMtB-mW3M,162
10
+ digitalkin/__version__.py,sha256=rxdfBPxh61wYhnALMkZQcAZXlglrXOhzea_oGgV1Was,195
11
+ digitalkin/logger.py,sha256=8ze_tjt2G6mDTuQcsf7-UTXWP3UHZ7LZVSs_iqF4rX4,4685
12
+ digitalkin/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ digitalkin/core/__init__.py,sha256=FJRcJ-B1Viyn-38L8XpOpZ8KOnf1I7PCDOAmKXLQhqc,71
14
+ digitalkin/core/common/__init__.py,sha256=Gh2eJAJRnrUE93jSEfG7r0nb01Xh1kSkNL6nEpfzK_s,218
15
+ digitalkin/core/common/factories.py,sha256=mV6SmXXrZxzIQ7DLdDtPdjapSDZt5Ua-nBIDsozs_Vk,5047
16
+ digitalkin/core/job_manager/__init__.py,sha256=gGtgQpE6vbBHxAj1SYMbcpj45Q6x8IcsqnyQPfyZZ-8,25
17
+ digitalkin/core/job_manager/base_job_manager.py,sha256=yVaakJNIEPWc6ND1bWrUgBA-8r1yEEQZ_iNP1RnK0jY,10076
18
+ digitalkin/core/job_manager/single_job_manager.py,sha256=7MkttI7pP0aZUHgz8apQf3kXHNI3Mbh8F5LfKwLhRpo,13789
19
+ digitalkin/core/job_manager/taskiq_broker.py,sha256=ti-wb9yNsspQEDOCbL0OhUwsvcA447lLKywjvKHgVQA,11406
20
+ digitalkin/core/job_manager/taskiq_job_manager.py,sha256=IQ2g34mA_AsbIHNiSpzxxT6KzoOEUVb_67659LgBT_4,21251
21
+ digitalkin/core/task_manager/__init__.py,sha256=k9i-qIoee_1yXogyQolaVFDUQBIZU3ENbYKtjrCNmTQ,31
22
+ digitalkin/core/task_manager/base_task_manager.py,sha256=ahkflSul07hMAWRX22CoJf9FxpQhWzi_oKZz3YAN6lc,19416
23
+ digitalkin/core/task_manager/local_task_manager.py,sha256=Z1gv4dCGD32LBSfMZJ4dGyYDe80lZRAyowTgGC6E4Vk,3534
24
+ digitalkin/core/task_manager/remote_task_manager.py,sha256=zgccmnwwtB0nyeIZlL5Ji8SY1J89z_vjA4JD9ur7HzY,3082
25
+ digitalkin/core/task_manager/surrealdb_repository.py,sha256=eNOVrYhTiIM0jd8j46fsKDr_THbGdK3xrog2jeqSQyA,9671
26
+ digitalkin/core/task_manager/task_executor.py,sha256=8xh5_1zuRAaGZIH_gWyNsA4T7YYaF0sl51dLS8a6aAk,10981
27
+ digitalkin/core/task_manager/task_session.py,sha256=ZU2GqtWAZidG7M7K_6GgEemBKRZ_RP2pW-3ODQSqP84,13665
28
+ digitalkin/grpc_servers/__init__.py,sha256=ZIRMJ1Lcas8yQ106GCup6hn2UBOsx1sNk8ap0lpEDnY,72
29
+ digitalkin/grpc_servers/_base_server.py,sha256=ZVeCDwI7w7fFbPTXPkeJb_SOuLfd2T7za3T4oCu2UWY,18680
30
+ digitalkin/grpc_servers/module_server.py,sha256=fJncoCQ-nHK4rs1PFM99Ds0U1Axjxj1X4ILeud96AvM,10235
31
+ digitalkin/grpc_servers/module_servicer.py,sha256=V8rlOUKGF4wq27dBtCpqvYUd0WVgXRDBB7jaGtofTck,19724
32
+ digitalkin/grpc_servers/registry_server.py,sha256=v4pFpkcnWHL3Sm4CHw8wTKbSAvppEYgg_ikgdirmazc,2235
33
+ digitalkin/grpc_servers/registry_servicer.py,sha256=5AaGacM875fHCiOmMRuqx4Q3ZsR5yvdfjuRsV4xhRcA,16485
34
+ digitalkin/grpc_servers/utils/__init__.py,sha256=ZnAIb_F8z4NhtPypqkdmzgRSzolKnJTk3oZx5GfWH5Y,38
35
+ digitalkin/grpc_servers/utils/exceptions.py,sha256=LtaDtlqXCeT6iqApogs4pbtezotOVeg4fhnFzGBvFsY,692
36
+ digitalkin/grpc_servers/utils/grpc_client_wrapper.py,sha256=a4xeulweovugI-IUVBrSZ-CswZHrBdeh9r-yzP8dl1w,2753
37
+ digitalkin/grpc_servers/utils/grpc_error_handler.py,sha256=0wPEU4713_ZlgIilaeXJV2bi90tHwYO1myDrSLeenKk,1848
38
+ digitalkin/mixins/__init__.py,sha256=d6ljaoyJZJT9XxOrXZG5FVNvbLURb3_CZrkp4GPZWYM,590
39
+ digitalkin/mixins/base_mixin.py,sha256=uLkg6MbDtVc9DysjdfNIGKahxQLnnjuL3DYpuyNLbk8,486
40
+ digitalkin/mixins/callback_mixin.py,sha256=90nHm9-pbKT14GAy3CB3fsBtpYu5IH0woOQdNLM2e_Y,836
41
+ digitalkin/mixins/chat_history_mixin.py,sha256=SqCmnh6Ybed3TQoQbvUjbzwKs_evvfW_lr4j_Uncg0A,4231
42
+ digitalkin/mixins/cost_mixin.py,sha256=nFqhLsRHdXAt3GOH6qI8sqX9KW3leTPW3gaclensBVw,2274
43
+ digitalkin/mixins/file_history_mixin.py,sha256=5MgxglccVe11M7YnoeuXbJYXNEwVZdiGd5Fl8sytcTM,3504
44
+ digitalkin/mixins/filesystem_mixin.py,sha256=Q1sEY_dKZVi2Sa21fypwpsz9h7uQ7ggVqzpuVgheF_o,1510
45
+ digitalkin/mixins/logger_mixin.py,sha256=l-SK3qACIzRfyHgj7KhzvW3ZhmVa-W1JB9tmppgpqg4,1842
46
+ digitalkin/mixins/storage_mixin.py,sha256=ptZ4a2bydIa48q0V9e395vWHTu7yw4A6rI4jwKY6gwI,2392
47
+ digitalkin/models/__init__.py,sha256=hDHtUfswaNh8wo4NZaBItg9JqC0uNSRqXArNWSrGynY,163
48
+ digitalkin/models/core/__init__.py,sha256=jOMDmPX0uSfGA9zUi0u_kOvYJ46VdIssoIhVYvNSeew,19
49
+ digitalkin/models/core/job_manager_models.py,sha256=RCrW20HCTQ7l2D1JtNgEKefZpMzoN-uAXK8bPorIqqA,1120
50
+ digitalkin/models/core/task_monitor.py,sha256=XNYCxhN9QqJZhuO2LoiWEHZwhA35dsupyfYvek_pgE8,2295
51
+ digitalkin/models/grpc_servers/__init__.py,sha256=0tA71nPSXgRrh9DoLvx-TSwZXdYIRUEItoadpTL1cTo,42
52
+ digitalkin/models/grpc_servers/models.py,sha256=unV1Wo0u3Efm7ddgYyYZZYUC_W6F0S5BQYH3xsOmXjw,8965
53
+ digitalkin/models/grpc_servers/types.py,sha256=rQ78s4nAet2jy-NIDj_PUWriT0kuGHr_w6ELjmjgBao,539
54
+ digitalkin/models/module/__init__.py,sha256=nFPHp0JcAZq9ISkcSu1y2zeNyXH3V4j10oMjHzMBYBU,599
55
+ digitalkin/models/module/module.py,sha256=k0W8vfJJFth8XdDzkHm32SyTuSf3h2qF0hSrxAfGF1s,956
56
+ digitalkin/models/module/module_context.py,sha256=0sKIvLYt0KHR4oF0MUQ4RQZDBrPjmOSaIHNMcl7vUmI,4649
57
+ digitalkin/models/module/module_types.py,sha256=Z46NPBCf8yDot4ZT_iJfBMo8J-IhpYiJJlKJsXxe6vA,14445
58
+ digitalkin/models/services/__init__.py,sha256=jhfVw6egq0OcHmos_fypH9XFehbHTBw09wluVFVFEyw,226
59
+ digitalkin/models/services/cost.py,sha256=9PXvd5RrIk9vCrRjcUGQ9ZyAokEbwLg4s0RfnE-aLP4,1616
60
+ digitalkin/models/services/storage.py,sha256=wp7F-AvTsU46ujGPcguqM5kUKRZx4399D4EGAAJt2zs,1143
61
+ digitalkin/modules/__init__.py,sha256=VwVbKok81NGyPIBZgEj_SR-59G8tTlSb4eBJI9W6Vx4,281
62
+ digitalkin/modules/_base_module.py,sha256=g9QhgZAkTOei7_eB76Yg6WX87noN2G8V016FF6guTEk,18359
63
+ digitalkin/modules/archetype_module.py,sha256=lOe3yYufwfylZR_VGy1w-zqdqVaMI_JANfKkbH9eODE,471
64
+ digitalkin/modules/tool_module.py,sha256=rLJfdYMWddiUgPLBDGG_UcHnRCHEeaqX6Fdp4DOUaCs,472
65
+ digitalkin/modules/trigger_handler.py,sha256=qPNMi-8NHqscOxciHeaXtpwjXApT3YzjMF23zQAjaZY,1770
66
+ digitalkin/services/__init__.py,sha256=LqGk_5DJy8Bzz62ajIq9jCeYNKQUIgtSCpafZk15FLc,910
67
+ digitalkin/services/base_strategy.py,sha256=yA9KUJGRKuuaxA6l3GcMv8zKfWoIsW03UxJT80Yea2I,766
68
+ digitalkin/services/services_config.py,sha256=JnyzZcG7OYBelwgn-wdVgY2n3yFTEkwLPHRZB8Tjw10,7468
69
+ digitalkin/services/services_models.py,sha256=5zXkWcfKnXGwQi9sN4OAL3XrgqOcmsTl8ai5Mi4RPsw,1668
70
+ digitalkin/services/agent/__init__.py,sha256=vJc8JN0pdtA8ecypLBeHrwAUIW6H2C8NyW-dk24rTpk,244
71
+ digitalkin/services/agent/agent_strategy.py,sha256=42Q9RciHX6tg3CgDQkbrlIx4h_TX0WIuSpLmCjitVmA,492
72
+ digitalkin/services/agent/default_agent.py,sha256=4N_E_eQxJGOx1KVUUg5jNOje-3ncMxF3ePB-uDuGrJc,345
73
+ digitalkin/services/cost/__init__.py,sha256=sD_a5LrnLluASOC5m5vgIqjaco-MzZJd6XhillIBHr0,400
74
+ digitalkin/services/cost/cost_strategy.py,sha256=MpPX33P_S5b2by6F4zT-rcyeRuh2V4NYPZe05VpDOGQ,2649
75
+ digitalkin/services/cost/default_cost.py,sha256=XE7kNFde8NmbulU9m1lc3mi-vHFkbaJf0XHUc0D4UHE,3945
76
+ digitalkin/services/cost/grpc_cost.py,sha256=B4HlrpsOpeq7jLSDyympOXvl6uXAzq_Ifk4t1EGjCpI,5289
77
+ digitalkin/services/filesystem/__init__.py,sha256=BhwMl_BUvM0d65fmglkp0SVwn3RfYiUOKJgIMnOCaGM,381
78
+ digitalkin/services/filesystem/default_filesystem.py,sha256=WQbU-Bsi9r-28VqhKbrplce3otzjSKS-5iqKEpGWdQU,15117
79
+ digitalkin/services/filesystem/filesystem_strategy.py,sha256=zibVLvX_IBQ-kgh-KYzHdszDeiHFPEAZszu_k99x1GQ,9487
80
+ digitalkin/services/filesystem/grpc_filesystem.py,sha256=TSj70so3YxeuTXSvSFJrA6LHwM07HNZ9kDdqCBAbC70,12154
81
+ digitalkin/services/identity/__init__.py,sha256=InkeyLgFYYwItx8mePA8HpfacOMWZwwuc0G4pWtKq9s,270
82
+ digitalkin/services/identity/default_identity.py,sha256=Y2auZHrGSZTIN5D8HyjLvLcNbYFM1CNUE23x7p5VIGw,386
83
+ digitalkin/services/identity/identity_strategy.py,sha256=skappBbds1_qa0Gr24FGrNX1N0_OYhYT1Lh7dUaAirE,429
84
+ digitalkin/services/registry/__init__.py,sha256=Zl4QAkCe9tOmmKGBWVuLQVFepdZiL0ec3VDj27IeyYM,270
85
+ digitalkin/services/registry/default_registry.py,sha256=VnWkF6nHpFxUKuUbZLPqzXqdA6oXmyV_ySpeuOCf_ko,277
86
+ digitalkin/services/registry/registry_strategy.py,sha256=uBXgZIv25jeXbeVO8vWvlNPxxNYu7_KiCw2PoE6AWr8,423
87
+ digitalkin/services/setup/__init__.py,sha256=t6xcvEWqTbcRZstBFK9cESEqaZKvpW14VtYygxIqfYQ,65
88
+ digitalkin/services/setup/default_setup.py,sha256=fnLSCMFQt5bYxbiOLM6wgP0ElIf1j9hf8whhogvl6Sg,8239
89
+ digitalkin/services/setup/grpc_setup.py,sha256=52nRFWLxnDSAWRacve04nRguiIQZAWMM-gcoiwxJ8Mo,13942
90
+ digitalkin/services/setup/setup_strategy.py,sha256=ZnJ_HwWCkHCPrqKekSD5L9y3p8wMwfjQ8sj2hLZq6go,4004
91
+ digitalkin/services/snapshot/__init__.py,sha256=Uzlnzo0CYlSpVsdiI37hW7xQk8hu3YA1fOI6O6MSzB0,270
92
+ digitalkin/services/snapshot/default_snapshot.py,sha256=Mb8QwWRsHh9I_tN0ln_ZiFa1QCZxOVWmuVLemQOTWpc,1058
93
+ digitalkin/services/snapshot/snapshot_strategy.py,sha256=B1TU3V_k9A-OdqBkdyc41-ihnrW5Btcwd1KyQdHT46A,898
94
+ digitalkin/services/storage/__init__.py,sha256=T-ocYLLphudkQgzvG47jBOm5GQsRFRIGA88y7Ur4akg,341
95
+ digitalkin/services/storage/default_storage.py,sha256=D8e-UYUkb2GvDEHMWcN3EkcIKXWA8DrsaQsXVjoXAYQ,7975
96
+ digitalkin/services/storage/grpc_storage.py,sha256=fFg83gvwJZW1a7f2AwSrxJFx949-KbNwpakPaCuGEvo,7217
97
+ digitalkin/services/storage/storage_strategy.py,sha256=sERF5tIJnzpb1iNqTXic9xRkGaXMifo6kb709ubB-Yo,8848
98
+ digitalkin/services/user_profile/__init__.py,sha256=zwD91Q6Q8iL6RXFB5GmtE6ldFQXU6_OVir6dVXAGKqI,35
99
+ digitalkin/services/user_profile/default_user_profile.py,sha256=46DH_VBCHKXJVyagVcc8kH5sLwRK54Fe_0ahqYJ1maA,1847
100
+ digitalkin/services/user_profile/grpc_user_profile.py,sha256=VBjXTySGBJO7cQ_hMsdYSUUyk3KFykeQqed82LlTihk,2811
101
+ digitalkin/services/user_profile/user_profile_strategy.py,sha256=luzpPvm2f4xXajWAbRGSk5YCIPBUrn5EOrXSz8NL1So,1148
102
+ digitalkin/utils/__init__.py,sha256=gDoEk5CP8tiBmIq-38aPhIMlnDUiqRrduuVXhpSPQnc,541
103
+ digitalkin/utils/arg_parser.py,sha256=wzscRlE1Qp1gGl-lAJlkkwnbU1O2oezj6BwK_BZFBIk,3158
104
+ digitalkin/utils/development_mode_action.py,sha256=2hznh0ajW_4ZTysfoc0Y49161f_PQPATRgNk8NAn1_o,1623
105
+ digitalkin/utils/dynamic_schema.py,sha256=5-B3dBGlCYYv6uRJkgudtc0ZpBOTYxl0yKedDGsteZQ,15184
106
+ digitalkin/utils/llm_ready_schema.py,sha256=JjMug_lrQllqFoanaC091VgOqwAd-_YzcpqFlS7p778,2375
107
+ digitalkin/utils/package_discover.py,sha256=sa6Zp5Kape1Zr4iYiNrnZxiHDnqM06ODk6yfWHom53w,13465
108
+ digitalkin-0.3.1.dev2.dist-info/licenses/LICENSE,sha256=Ies4HFv2r2hzDRakJYxk3Y60uDFLiG-orIgeTpstnIo,20327
109
+ modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
110
+ modules/cpu_intensive_module.py,sha256=ejB9XPnFfA0uCuFUQbM3fy5UYfqqAlF36rv_P5Ri8ho,8363
111
+ modules/dynamic_setup_module.py,sha256=GPJwfaPZUkcOlMX9d_sYUDzT8aPrfjrCCQ4OyPtulD8,12507
112
+ modules/minimal_llm_module.py,sha256=Ijld__ZnhzfLwpXD1XVkLZ7jyKZKyOFZczOpiPttJZc,11216
113
+ modules/text_transform_module.py,sha256=bwPSnEUthZQyfLwcTLo52iAxItAoknkLh8Y3m5aywaY,7251
114
+ services/filesystem_module.py,sha256=71Mcja8jCQqiqFHPdsIXplFIHTvgkxRhp0TRXuCfgkk,7430
115
+ services/storage_module.py,sha256=ybTMqmvGaTrR8PqJ4FU0cwxaDjT36TskVrGoetTGmno,6955
116
+ digitalkin-0.3.1.dev2.dist-info/METADATA,sha256=KoDE-dtTv3fG6XGdSBsCcwlyQhcJMb3hnESKNKP3LaY,29719
117
+ digitalkin-0.3.1.dev2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
118
+ digitalkin-0.3.1.dev2.dist-info/top_level.txt,sha256=gcjqlyrZuLjIyxrOIavCQM_olpr6ND5kPKkZd2j0xGo,40
119
+ digitalkin-0.3.1.dev2.dist-info/RECORD,,