digitalkin 1.0.4.dev6__tar.gz → 1.0.4.dev7__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 (273) hide show
  1. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/PKG-INFO +2 -2
  2. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/pyproject.toml +11 -11
  3. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/__version__.py +1 -1
  4. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/resilience/bulkhead.py +5 -6
  5. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/task_manager/redis/proto_streams.py +1 -1
  6. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/grpc_servers/_base_server.py +4 -4
  7. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/grpc_servers/module_server.py +12 -3
  8. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/grpc_servers/module_servicer.py +5 -9
  9. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/grpc_servers/utils/circuit_breaker.py +3 -3
  10. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/grpc_servers/utils/grpc_client_wrapper.py +6 -6
  11. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/mixins/filesystem_mixin.py +10 -5
  12. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/grpc_servers/models.py +28 -37
  13. digitalkin-1.0.4.dev7/src/digitalkin/models/settings/certificate.py +90 -0
  14. digitalkin-1.0.4.dev7/src/digitalkin/models/settings/client/__init__.py +1 -0
  15. digitalkin-1.0.4.dev7/src/digitalkin/models/settings/client/channel.py +68 -0
  16. digitalkin-1.0.4.dev7/src/digitalkin/models/settings/client/circuit_breaker.py +19 -0
  17. digitalkin-1.0.4.dev7/src/digitalkin/models/settings/client/client.py +55 -0
  18. digitalkin-1.0.4.dev7/src/digitalkin/models/settings/client/grpc.py +148 -0
  19. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/settings/module.py +17 -2
  20. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/settings/profiling.py +1 -1
  21. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/settings/redis.py +5 -1
  22. digitalkin-1.0.4.dev7/src/digitalkin/models/settings/resilience.py +61 -0
  23. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/settings/server/channel.py +23 -3
  24. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/settings/server/grpc.py +1 -1
  25. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/settings/server/server.py +4 -2
  26. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/settings/utils/channel.py +45 -7
  27. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/filesystem/default_filesystem.py +6 -1
  28. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/services_config.py +16 -4
  29. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/utils/development_mode_action.py +10 -18
  30. digitalkin-1.0.4.dev7/src/digitalkin/utils/env_manager.py +139 -0
  31. digitalkin-1.0.4.dev7/src/digitalkin/utils/env_template.py +233 -0
  32. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin.egg-info/PKG-INFO +2 -2
  33. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin.egg-info/SOURCES.txt +8 -1
  34. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin.egg-info/requires.txt +1 -1
  35. digitalkin-1.0.4.dev6/src/digitalkin/models/settings/grpc_client.py +0 -127
  36. digitalkin-1.0.4.dev6/src/digitalkin/models/settings/resilience.py +0 -31
  37. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/LICENSE +0 -0
  38. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/README.md +0 -0
  39. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/base_server/__init__.py +0 -0
  40. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/base_server/mock/__init__.py +0 -0
  41. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/base_server/mock/mock_pb2.py +0 -0
  42. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/base_server/mock/mock_pb2_grpc.py +0 -0
  43. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/base_server/server_async_insecure.py +0 -0
  44. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/base_server/server_async_secure.py +0 -0
  45. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/base_server/server_sync_insecure.py +0 -0
  46. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/base_server/server_sync_secure.py +0 -0
  47. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/bench_module/__init__.py +0 -0
  48. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/bench_module/echo_module.py +0 -0
  49. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/bench_module/models/__init__.py +0 -0
  50. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/bench_module/models/input.py +0 -0
  51. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/bench_module/models/output.py +0 -0
  52. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/bench_module/models/secret.py +0 -0
  53. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/bench_module/models/setup.py +0 -0
  54. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/bench_module/server.py +0 -0
  55. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/bench_module/triggers/__init__.py +0 -0
  56. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/bench_module/triggers/message_trigger.py +0 -0
  57. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/modules/__init__.py +0 -0
  58. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/modules/archetype_with_tools_module.py +0 -0
  59. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/modules/cpu_intensive_module.py +0 -0
  60. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/modules/dynamic_setup_module.py +0 -0
  61. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/modules/minimal_llm_module.py +0 -0
  62. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/modules/text_transform_module.py +0 -0
  63. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/monitoring/digitalkin_observability/__init__.py +0 -0
  64. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/monitoring/digitalkin_observability/http_server.py +0 -0
  65. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/monitoring/digitalkin_observability/interceptors.py +0 -0
  66. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/monitoring/digitalkin_observability/metrics.py +0 -0
  67. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/monitoring/digitalkin_observability/prometheus.py +0 -0
  68. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/monitoring/tests/test_metrics.py +0 -0
  69. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/redis_demo/client.py +0 -0
  70. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/redis_demo/echo_module.py +0 -0
  71. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/redis_demo/models/__init__.py +0 -0
  72. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/redis_demo/models/input.py +0 -0
  73. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/redis_demo/models/output.py +0 -0
  74. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/redis_demo/models/secret.py +0 -0
  75. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/redis_demo/models/setup.py +0 -0
  76. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/redis_demo/server.py +0 -0
  77. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/redis_demo/triggers/__init__.py +0 -0
  78. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/redis_demo/triggers/message_trigger.py +0 -0
  79. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/services/filesystem_module.py +0 -0
  80. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/examples/services/storage_module.py +0 -0
  81. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/setup.cfg +0 -0
  82. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/__init__.py +0 -0
  83. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/__init__.py +0 -0
  84. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/__init__.py +0 -0
  85. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/agno_adapter.py +0 -0
  86. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/agui_tools.py +0 -0
  87. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/hitl.py +0 -0
  88. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/models.py +0 -0
  89. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/module_toolkit.py +0 -0
  90. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/toolkits/__init__.py +0 -0
  91. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/toolkits/base.py +0 -0
  92. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/toolkits/chat_history.py +0 -0
  93. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/toolkits/defaults.py +0 -0
  94. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/toolkits/registry/__init__.py +0 -0
  95. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/toolkits/registry/action.py +0 -0
  96. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/toolkits/registry/base.py +0 -0
  97. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/toolkits/registry/kins/__init__.py +0 -0
  98. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/toolkits/registry/kins/action.py +0 -0
  99. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/toolkits/registry/kins/kit.py +0 -0
  100. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/toolkits/registry/loader/__init__.py +0 -0
  101. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/toolkits/registry/loader/action.py +0 -0
  102. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/toolkits/registry/loader/kit.py +0 -0
  103. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/toolkits/registry/services/__init__.py +0 -0
  104. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/toolkits/registry/services/action.py +0 -0
  105. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/toolkits/registry/services/kit.py +0 -0
  106. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/toolkits/registry/tools/__init__.py +0 -0
  107. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/toolkits/registry/tools/action.py +0 -0
  108. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/toolkits/registry/tools/kit.py +0 -0
  109. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/community/agno/toolkits/user_profile.py +0 -0
  110. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/__init__.py +0 -0
  111. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/common/__init__.py +0 -0
  112. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/common/factories.py +0 -0
  113. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/exceptions.py +0 -0
  114. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/job_manager/__init__.py +0 -0
  115. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/job_manager/base_job_manager.py +0 -0
  116. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/job_manager/single_job_manager.py +0 -0
  117. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/profiling/__init__.py +0 -0
  118. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/profiling/step_timer.py +0 -0
  119. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/profiling/task_profiler.py +0 -0
  120. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/resilience/__init__.py +0 -0
  121. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/resilience/task_supervisor.py +0 -0
  122. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/task_manager/__init__.py +0 -0
  123. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/task_manager/base_task_manager.py +0 -0
  124. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/task_manager/local_task_manager.py +0 -0
  125. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/task_manager/module_runner.py +0 -0
  126. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/task_manager/redis/__init__.py +0 -0
  127. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/task_manager/redis/redis_client.py +0 -0
  128. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/task_manager/redis/redis_idempotency.py +0 -0
  129. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/task_manager/redis/redis_signal.py +0 -0
  130. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/task_manager/redis/redis_state.py +0 -0
  131. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/task_manager/remote_task_manager.py +0 -0
  132. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/task_manager/task_executor.py +0 -0
  133. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/core/task_manager/task_session.py +0 -0
  134. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/exceptions.py +0 -0
  135. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/grpc_servers/__init__.py +0 -0
  136. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/grpc_servers/exceptions.py +0 -0
  137. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/grpc_servers/gateway_servicer.py +0 -0
  138. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/grpc_servers/interceptors/__init__.py +0 -0
  139. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/grpc_servers/interceptors/permission.py +0 -0
  140. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/grpc_servers/interceptors/request_ids.py +0 -0
  141. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/grpc_servers/m2m_call_registry.py +0 -0
  142. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/grpc_servers/stream_registry.py +0 -0
  143. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/grpc_servers/stream_session.py +0 -0
  144. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/grpc_servers/utils/__init__.py +0 -0
  145. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/grpc_servers/utils/grpc_error_handler.py +0 -0
  146. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/grpc_servers/utils/utility_schema_extender.py +0 -0
  147. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/grpc_servers/utils/validators.py +0 -0
  148. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/logger.py +0 -0
  149. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/mixins/__init__.py +0 -0
  150. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/mixins/agui_mixin.py +0 -0
  151. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/mixins/base_mixin.py +0 -0
  152. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/mixins/cost_mixin.py +0 -0
  153. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/mixins/file_history_mixin.py +0 -0
  154. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/mixins/logger_mixin.py +0 -0
  155. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/mixins/storage_mixin.py +0 -0
  156. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/__init__.py +0 -0
  157. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/core/__init__.py +0 -0
  158. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/core/job_manager_models.py +0 -0
  159. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/core/redis.py +0 -0
  160. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/core/task_monitor.py +0 -0
  161. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/events/__init__.py +0 -0
  162. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/events/agent_events.py +0 -0
  163. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/grpc_servers/__init__.py +0 -0
  164. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/grpc_servers/circuit_breaker.py +0 -0
  165. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/grpc_servers/m2m.py +0 -0
  166. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/grpc_servers/stream_error_codes.py +0 -0
  167. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/grpc_servers/types.py +0 -0
  168. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/module/__init__.py +0 -0
  169. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/module/ag_ui.py +0 -0
  170. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/module/base_types.py +0 -0
  171. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/module/knowledge_files.py +0 -0
  172. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/module/loaded_tools.py +0 -0
  173. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/module/module.py +0 -0
  174. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/module/module_context.py +0 -0
  175. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/module/module_types.py +0 -0
  176. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/module/request_metadata.py +0 -0
  177. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/module/select_schema.py +0 -0
  178. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/module/setup_types.py +0 -0
  179. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/module/tool_cache.py +0 -0
  180. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/module/tool_reference.py +0 -0
  181. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/module/utility.py +0 -0
  182. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/services/__init__.py +0 -0
  183. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/services/cost.py +0 -0
  184. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/services/filesystem.py +0 -0
  185. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/services/registry.py +0 -0
  186. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/services/services.py +0 -0
  187. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/services/storage.py +0 -0
  188. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/settings/__init__.py +0 -0
  189. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/settings/gateway.py +0 -0
  190. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/settings/log.py +0 -0
  191. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/settings/queue.py +0 -0
  192. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/settings/registry.py +0 -0
  193. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/settings/server/__init__.py +0 -0
  194. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/settings/server/servicer.py +0 -0
  195. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/settings/task_manager.py +0 -0
  196. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/settings/utils/__init__.py +0 -0
  197. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/utils/__init__.py +0 -0
  198. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/models/utils/dynamic_schema.py +0 -0
  199. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/modules/__init__.py +0 -0
  200. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/modules/_base_module.py +0 -0
  201. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/modules/archetype_module.py +0 -0
  202. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/modules/tool_module.py +0 -0
  203. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/modules/trigger_handler.py +0 -0
  204. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/modules/triggers/__init__.py +0 -0
  205. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/modules/triggers/healthcheck_ping_trigger.py +0 -0
  206. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/modules/triggers/healthcheck_services_trigger.py +0 -0
  207. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/modules/triggers/healthcheck_status_trigger.py +0 -0
  208. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/py.typed +0 -0
  209. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/__init__.py +0 -0
  210. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/base_strategy.py +0 -0
  211. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/communication/__init__.py +0 -0
  212. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/communication/communication_strategy.py +0 -0
  213. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/communication/default_communication.py +0 -0
  214. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/communication/exceptions.py +0 -0
  215. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/communication/grpc_communication.py +0 -0
  216. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/cost/__init__.py +0 -0
  217. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/cost/cost_strategy.py +0 -0
  218. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/cost/default_cost.py +0 -0
  219. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/cost/exceptions.py +0 -0
  220. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/cost/grpc_cost.py +0 -0
  221. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/filesystem/__init__.py +0 -0
  222. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/filesystem/exceptions.py +0 -0
  223. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/filesystem/filesystem_strategy.py +0 -0
  224. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/filesystem/grpc_filesystem.py +0 -0
  225. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/identity/__init__.py +0 -0
  226. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/identity/default_identity.py +0 -0
  227. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/identity/identity_strategy.py +0 -0
  228. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/registry/__init__.py +0 -0
  229. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/registry/default_registry.py +0 -0
  230. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/registry/exceptions.py +0 -0
  231. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/registry/grpc_registry.py +0 -0
  232. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/registry/registry_models.py +0 -0
  233. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/registry/registry_strategy.py +0 -0
  234. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/secret/__init__.py +0 -0
  235. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/secret/default_secret.py +0 -0
  236. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/secret/exceptions.py +0 -0
  237. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/secret/grpc_secret.py +0 -0
  238. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/secret/secret_strategy.py +0 -0
  239. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/services_models.py +0 -0
  240. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/setup/__init__.py +0 -0
  241. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/setup/default_setup.py +0 -0
  242. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/setup/exceptions.py +0 -0
  243. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/setup/grpc_setup.py +0 -0
  244. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/setup/setup_strategy.py +0 -0
  245. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/storage/__init__.py +0 -0
  246. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/storage/default_storage.py +0 -0
  247. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/storage/exceptions.py +0 -0
  248. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/storage/grpc_storage.py +0 -0
  249. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/storage/storage_strategy.py +0 -0
  250. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/task_manager/__init__.py +0 -0
  251. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/task_manager/default_task_manager.py +0 -0
  252. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/task_manager/exceptions.py +0 -0
  253. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/task_manager/redis_task_manager.py +0 -0
  254. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/task_manager/task_manager_strategy.py +0 -0
  255. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/user_profile/__init__.py +0 -0
  256. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/user_profile/default_user_profile.py +0 -0
  257. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/user_profile/exceptions.py +0 -0
  258. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/user_profile/grpc_user_profile.py +0 -0
  259. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/services/user_profile/user_profile_strategy.py +0 -0
  260. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/utils/__init__.py +0 -0
  261. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/utils/arg_parser.py +0 -0
  262. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/utils/conditional_schema.py +0 -0
  263. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/utils/dynamic_schema.py +0 -0
  264. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/utils/exceptions.py +0 -0
  265. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/utils/json_structure.py +0 -0
  266. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/utils/llm_ready_schema.py +0 -0
  267. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/utils/package_discover.py +0 -0
  268. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/utils/proto_utils.py +0 -0
  269. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/utils/schema_splitter.py +0 -0
  270. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin/utils/setup_content_validator.py +0 -0
  271. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin.egg-info/dependency_links.txt +0 -0
  272. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/src/digitalkin.egg-info/top_level.txt +0 -0
  273. {digitalkin-1.0.4.dev6 → digitalkin-1.0.4.dev7}/tests/test_exceptions.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: digitalkin
3
- Version: 1.0.4.dev6
3
+ Version: 1.0.4.dev7
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
@@ -453,7 +453,7 @@ Requires-Python: >=3.10
453
453
  Description-Content-Type: text/markdown
454
454
  License-File: LICENSE
455
455
  Requires-Dist: ag-ui-protocol==0.1.21.dev1787220377
456
- Requires-Dist: agentic-mesh-protocol==1.0.2.dev2
456
+ Requires-Dist: agentic-mesh-protocol==1.0.2
457
457
  Requires-Dist: agno<3,>=2.8.0
458
458
  Requires-Dist: anyio>=4.13.0
459
459
  Requires-Dist: grpcio-health-checking==1.82.1
@@ -31,7 +31,7 @@
31
31
  # which is how a nested run's output is attributed to its author. Pinned exactly
32
32
  # because it is a dated prerelease; move to >=0.1.21 once that ships stable.
33
33
  "ag-ui-protocol==0.1.21.dev1787220377",
34
- "agentic-mesh-protocol==1.0.2.dev2",
34
+ "agentic-mesh-protocol==1.0.2",
35
35
  "agno>=2.8.0,<3",
36
36
  "anyio>=4.13.0",
37
37
  "grpcio-health-checking==1.82.1",
@@ -41,7 +41,7 @@
41
41
  "pydantic>=2.12.4",
42
42
  "redis[hiredis]>=7.4.0,<9",
43
43
  ]
44
- version = "1.0.4.dev6"
44
+ version = "1.0.4.dev7"
45
45
 
46
46
  [project.optional-dependencies]
47
47
  agno = [ "agno>=2.6" ]
@@ -208,15 +208,15 @@
208
208
  ]
209
209
 
210
210
  ignore = [
211
- "any-type", # Allow typing.Any — gRPC stubs, callbacks, and dynamic APIs require it
212
- "missing-trailing-comma", # Disable because of formatter incompatibility
213
- "docstring-extraneous-exception", # Allow extraneous-exception in docstring
214
- "unused-import", # Allow unused imports — used for availability checks
215
- "invalid-function-name", # Allow PascalCase methods — gRPC servicer convention
216
- "import-outside-top-level", # Allow lazy imports — needed to break circular dependencies
217
- "bad-dunder-method-name", # Allow __get_pydantic_core_schema__ — Pydantic dunder hook
218
- "hardcoded-password-string", # Hardcoded-password
219
- "suspicious-pickle-import", # Allow pickle import
211
+ "any-type", # Allow typing.Any — gRPC stubs, callbacks, and dynamic APIs require it
212
+ "missing-trailing-comma", # Disable because of formatter incompatibility
213
+ "docstring-extraneous-exception", # Allow extraneous-exception in docstring
214
+ "unused-import", # Allow unused imports — used for availability checks
215
+ "invalid-function-name", # Allow PascalCase methods — gRPC servicer convention
216
+ "import-outside-top-level", # Allow lazy imports — needed to break circular dependencies
217
+ "bad-dunder-method-name", # Allow __get_pydantic_core_schema__ — Pydantic dunder hook
218
+ "hardcoded-password-string", # Hardcoded-password
219
+ "suspicious-pickle-import", # Allow pickle import
220
220
  ]
221
221
 
222
222
  fixable = [ "ALL" ]
@@ -5,4 +5,4 @@ from importlib.metadata import PackageNotFoundError, version
5
5
  try:
6
6
  __version__ = version("digitalkin")
7
7
  except PackageNotFoundError:
8
- __version__ = "1.0.4.dev6"
8
+ __version__ = "1.0.4.dev7"
@@ -15,13 +15,12 @@ Usage in ModuleContext or service wrapper::
15
15
  from __future__ import annotations
16
16
 
17
17
  import asyncio
18
- import os
19
18
  from typing import ClassVar
20
19
 
21
20
  from typing_extensions import Self
22
21
 
23
22
  from digitalkin.core.exceptions import BulkheadFullError
24
- from digitalkin.models.settings.resilience import get_bulkhead_settings
23
+ from digitalkin.models.settings.resilience import BulkheadServiceSettings, get_bulkhead_settings
25
24
 
26
25
 
27
26
  class Bulkhead:
@@ -62,10 +61,10 @@ class Bulkhead:
62
61
  del cls._instances[oldest]
63
62
 
64
63
  settings = get_bulkhead_settings()
65
- # Per-service override has a dynamic env-var suffix, so it cannot be a
66
- # static settings field — read it directly, falling back to the setting.
67
- env_max = os.environ.get(f"DIGITALKIN_BULKHEAD_{service_id.upper()}_MAX")
68
- max_concurrent = int(env_max) if env_max is not None else settings.default_max
64
+ # The override carries the service id in the variable name; the settings
65
+ # class builds that prefix itself, so nothing here touches the environment.
66
+ override = BulkheadServiceSettings(service_id).max
67
+ max_concurrent = override if override is not None else settings.default_max
69
68
 
70
69
  inst = cls(
71
70
  service_id=service_id,
@@ -43,7 +43,7 @@ class ProtoStreamReader:
43
43
  """Initialize proto stream reader.
44
44
 
45
45
  Cursor TTL comes from ``GatewayStreamSettings.redis_cursor_ttl`` (env
46
- ``DIGITALKIN_REDIS_CURSOR_TTL``).
46
+ ``DIGITALKIN_GATEWAY_STREAM_REDIS_CURSOR_TTL``).
47
47
 
48
48
  Args:
49
49
  task_id: Unique task identifier.
@@ -35,6 +35,7 @@ from digitalkin.logger import logger
35
35
  from digitalkin.models.grpc_servers.types import GrpcServer, ServiceDescriptor, T
36
36
  from digitalkin.models.settings.server.server import get_server_settings
37
37
  from digitalkin.models.settings.utils.channel import ControlFlow, SecurityMode
38
+ from digitalkin.utils.env_manager import EnvManager
38
39
 
39
40
 
40
41
  class BaseServer(abc.ABC):
@@ -257,10 +258,9 @@ class BaseServer(abc.ABC):
257
258
  Raises:
258
259
  SecurityError: If credentials are missing or unreadable.
259
260
  """
260
- creds = get_server_settings().channel.credentials
261
- if not creds:
262
- msg = "Credentials must be provided for secure server"
263
- raise SecurityError(msg)
261
+ # Explicit SERVER_CHANNEL_CREDENTIALS__* paths, else the CERTIFICATE_CERT_VOLUME
262
+ # directory; the resolution itself raises when the key or certificate is absent.
263
+ creds = EnvManager.server_credentials()
264
264
 
265
265
  try: # ruff: ignore[too-many-statements-in-try-clause]
266
266
  if creds.key_path and creds.cert_path:
@@ -1,6 +1,5 @@
1
1
  """Module gRPC server implementation for DigitalKin."""
2
2
 
3
- import os
4
3
  from collections.abc import Sequence
5
4
  from typing import TYPE_CHECKING, Any
6
5
 
@@ -15,9 +14,12 @@ from digitalkin.grpc_servers.gateway_servicer import GatewayServicer
15
14
  from digitalkin.grpc_servers.module_servicer import ModuleServicer
16
15
  from digitalkin.logger import logger
17
16
  from digitalkin.models.grpc_servers.models import ClientConfig
17
+ from digitalkin.models.services.services import ServicesMode
18
+ from digitalkin.models.settings.redis import get_redis_settings
18
19
  from digitalkin.models.settings.server.server import get_server_settings
19
20
  from digitalkin.modules._base_module import BaseModule
20
21
  from digitalkin.services.registry import GrpcRegistry
22
+ from digitalkin.utils.env_manager import EnvManager
21
23
 
22
24
  if TYPE_CHECKING:
23
25
  from digitalkin.services.registry import RegistryStrategy
@@ -40,6 +42,11 @@ class ModuleServer(BaseServer):
40
42
  ) -> None:
41
43
  """Initialize the module server.
42
44
 
45
+ In remote mode an omitted ``client_config`` is built from the
46
+ environment, so a module no longer declares one to reach the registry
47
+ and the services provider. Local mode keeps it unset: there is no
48
+ registry to register with.
49
+
43
50
  Args:
44
51
  module_class: The module class to serve.
45
52
  client_config: Client configuration for services and registry.
@@ -49,6 +56,8 @@ class ModuleServer(BaseServer):
49
56
 
50
57
  super().__init__(interceptors=all_interceptors or None)
51
58
  self.module_class = module_class
59
+ if client_config is None and EnvManager.services_mode() == ServicesMode.REMOTE:
60
+ client_config = EnvManager.client_config()
52
61
  self.client_config = client_config
53
62
  self.registry: RegistryStrategy | None = None
54
63
  self.module_servicer: ModuleServicer | None = None
@@ -93,9 +102,9 @@ class ModuleServer(BaseServer):
93
102
  dispatcher process, queue, or Redis stream for dispatch.
94
103
 
95
104
  Raises:
96
- RuntimeError: If DIGITALKIN_REDIS_URL is not set.
105
+ RuntimeError: If DIGITALKIN_REDIS_URL resolves to an empty URL.
97
106
  """
98
- redis_url = os.environ.get("DIGITALKIN_REDIS_URL")
107
+ redis_url = get_redis_settings().pool.url.get_secret_value()
99
108
  if not redis_url:
100
109
  msg = "DIGITALKIN_REDIS_URL is required. The gateway needs Redis for stream persistence."
101
110
  raise RuntimeError(msg)
@@ -2,7 +2,6 @@
2
2
 
3
3
  import asyncio
4
4
  import json
5
- import os
6
5
  import time
7
6
  from argparse import ArgumentParser, Namespace
8
7
  from collections.abc import Awaitable, Callable
@@ -28,6 +27,7 @@ from digitalkin.models.module.module import ModuleCodeModel
28
27
  from digitalkin.models.module.setup_types import SetupModel
29
28
  from digitalkin.models.services.services import ServicesMode
30
29
  from digitalkin.models.settings.gateway import get_gateway_settings
30
+ from digitalkin.models.settings.redis import get_redis_settings
31
31
  from digitalkin.models.settings.server.servicer import get_module_servicer_settings
32
32
  from digitalkin.modules._base_module import BaseModule
33
33
  from digitalkin.services.registry import GrpcRegistry, RegistryStrategy
@@ -37,6 +37,7 @@ from digitalkin.services.setup.setup_strategy import SetupStrategy, SetupVersion
37
37
  from digitalkin.services.user_profile import DefaultUserProfile, GrpcUserProfile, UserProfileStrategy
38
38
  from digitalkin.utils.arg_parser import ArgParser
39
39
  from digitalkin.utils.development_mode_action import DevelopmentModeMappingAction
40
+ from digitalkin.utils.env_manager import EnvManager
40
41
 
41
42
 
42
43
  class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer, ArgParser):
@@ -55,9 +56,7 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer, ArgParser):
55
56
  parser.add_argument(
56
57
  "-d",
57
58
  "--dev-mode",
58
- env_var="SERVICE_MODE",
59
59
  choices=ServicesMode.__members__,
60
- default="local",
61
60
  action=DevelopmentModeMappingAction,
62
61
  dest="services_mode",
63
62
  help="Define Module Service configurations for endpoints",
@@ -70,13 +69,13 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer, ArgParser):
70
69
  module_class: The module type to serve.
71
70
 
72
71
  Raises:
73
- RuntimeError: If DIGITALKIN_REDIS_URL is not set.
72
+ RuntimeError: If DIGITALKIN_REDIS_URL resolves to an empty URL.
74
73
  """
75
74
  super().__init__()
76
75
  module_class.discover()
77
76
  self.module_class = module_class
78
77
 
79
- redis_url = os.environ.get("DIGITALKIN_REDIS_URL")
78
+ redis_url = get_redis_settings().pool.url.get_secret_value()
80
79
  if not redis_url:
81
80
  msg = "DIGITALKIN_REDIS_URL is required"
82
81
  raise RuntimeError(msg)
@@ -90,10 +89,7 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer, ArgParser):
90
89
  # Access-control client gating the setup cache. Always built, always called (fail-closed).
91
90
  if self.args.services_mode == ServicesMode.REMOTE:
92
91
  up_cfg = self.module_class.services_config_params.get("user_profile") or {}
93
- up_client_config = up_cfg.get("client_config")
94
- if not up_client_config:
95
- msg = "user_profile client_config is required for setup access control"
96
- raise RuntimeError(msg)
92
+ up_client_config = up_cfg.get("client_config") or EnvManager.client_config()
97
93
  self.user_profile = GrpcUserProfile("", "", "", up_client_config)
98
94
  else:
99
95
  self.user_profile = DefaultUserProfile("", "", "")
@@ -15,7 +15,7 @@ from typing import ClassVar
15
15
  from digitalkin.grpc_servers.exceptions import CircuitOpenError
16
16
  from digitalkin.logger import logger
17
17
  from digitalkin.models.grpc_servers.circuit_breaker import CBState
18
- from digitalkin.models.settings.grpc_client import get_circuit_breaker_settings
18
+ from digitalkin.models.settings.client.client import get_client_settings
19
19
 
20
20
 
21
21
  class CircuitBreaker:
@@ -45,7 +45,7 @@ class CircuitBreaker:
45
45
  """Get existing circuit breaker for a service or create one.
46
46
 
47
47
  Thresholds come from ``CircuitBreakerSettings`` (env
48
- ``DIGITALKIN_CB_FAIL_MAX``, ``DIGITALKIN_CB_RESET_TIMEOUT``).
48
+ ``CLIENT_CIRCUIT_BREAKER_FAIL_MAX``, ``CLIENT_CIRCUIT_BREAKER_RESET_TIMEOUT``).
49
49
 
50
50
  Args:
51
51
  service_id: Service identifier.
@@ -54,7 +54,7 @@ class CircuitBreaker:
54
54
  Circuit breaker for this service.
55
55
  """
56
56
  if service_id not in cls._instances:
57
- settings = get_circuit_breaker_settings()
57
+ settings = get_client_settings().circuit_breaker
58
58
  cls._instances[service_id] = cls(service_id, settings.fail_max, settings.reset_timeout)
59
59
  return cls._instances[service_id]
60
60
 
@@ -21,7 +21,7 @@ from digitalkin.grpc_servers.interceptors.request_ids import RequestIdClientInte
21
21
  from digitalkin.grpc_servers.utils.circuit_breaker import CircuitBreaker
22
22
  from digitalkin.logger import logger
23
23
  from digitalkin.models.grpc_servers.models import ClientConfig
24
- from digitalkin.models.settings.grpc_client import get_grpc_client_settings
24
+ from digitalkin.models.settings.client.client import get_client_settings
25
25
  from digitalkin.models.settings.utils.channel import SecurityMode
26
26
 
27
27
 
@@ -240,7 +240,7 @@ class GrpcClientWrapper:
240
240
 
241
241
  Retries on transient errors (UNAVAILABLE, INTERNAL, DEADLINE_EXCEEDED)
242
242
  with exponential backoff. Retry count and backoff base are configurable
243
- via DIGITALKIN_GRPC_QUERY_MAX_RETRIES and DIGITALKIN_GRPC_QUERY_BACKOFF_BASE_MS.
243
+ via CLIENT_MAX_RETRIES and CLIENT_BACKOFF_BASE_MS.
244
244
 
245
245
  Arguments:
246
246
  query_endpoint: rpc query name (e.g., "GetSetup", "CreateSetupVersion")
@@ -269,10 +269,10 @@ class GrpcClientWrapper:
269
269
  error_msg = f"[gRPC-client:{self.service_name}.{query_endpoint}] {e}"
270
270
  raise ServerError(error_msg) from e
271
271
 
272
- grpc_settings = get_grpc_client_settings()
273
- eff_timeout = timeout if timeout is not None else grpc_settings.timeout
274
- max_retries = grpc_settings.max_retries
275
- backoff_base_ms = grpc_settings.backoff_base_ms
272
+ client_settings = get_client_settings()
273
+ eff_timeout = timeout if timeout is not None else client_settings.timeout
274
+ max_retries = client_settings.max_retries
275
+ backoff_base_ms = client_settings.backoff_base_ms
276
276
  backoff_delays = tuple(backoff_base_ms / 1000 * (2**i) for i in range(max_retries))
277
277
  last_error: grpc.RpcError | None = None
278
278
 
@@ -71,10 +71,10 @@ class FilesystemMixin:
71
71
  )
72
72
  ])
73
73
  except Exception:
74
- logger.exception("Failed to upload file '%s' (%s)", name, content_type)
74
+ logger.exception("Failed to upload file '%s' (%s)", name, content_type, extra=context.session.current_ids())
75
75
  return None
76
76
  if failed or not records:
77
- logger.error("Upload rejected for file '%s' (%s)", name, content_type)
77
+ logger.error("Upload rejected for file '%s' (%s)", name, content_type, extra=context.session.current_ids())
78
78
  return None
79
79
  return records[0]
80
80
 
@@ -122,7 +122,7 @@ class FilesystemMixin:
122
122
  try:
123
123
  records, _total = await context.filesystem.get_files(filters, include_content=include_content)
124
124
  except Exception:
125
- logger.exception("Failed to list files")
125
+ logger.exception("Failed to list files", extra=context.session.current_ids())
126
126
  return []
127
127
  return records
128
128
 
@@ -151,7 +151,7 @@ class FilesystemMixin:
151
151
  permanent=permanent,
152
152
  )
153
153
  except Exception:
154
- logger.exception("Failed to delete file '%s'", file_id)
154
+ logger.exception("Failed to delete file '%s'", file_id, extra=context.session.current_ids())
155
155
  return False
156
156
  return results.get(file_id, False)
157
157
 
@@ -181,7 +181,12 @@ class FilesystemMixin:
181
181
  try:
182
182
  record = await context.filesystem.get_file(file.id, context=file_context, include_content=False)
183
183
  except Exception:
184
- logger.warning("Could not resolve file '%s'; keeping it as submitted", file.id, exc_info=True)
184
+ logger.warning(
185
+ "Could not resolve file '%s'; keeping it as submitted",
186
+ file.id,
187
+ exc_info=True,
188
+ extra=context.session.current_ids(),
189
+ )
185
190
  resolved.append(file)
186
191
  continue
187
192
  resolved.append(
@@ -1,43 +1,15 @@
1
1
  """Data models for gRPC server configurations."""
2
2
 
3
- from enum import Enum
4
3
  from pathlib import Path
5
4
  from typing import Any
6
5
 
7
- import grpc
8
6
  from pydantic import BaseModel, Field, ValidationInfo, field_validator
9
7
 
10
8
  from digitalkin.grpc_servers.exceptions import ConfigurationError, SecurityError
11
- from digitalkin.models.settings.grpc_client import get_grpc_channel_settings, get_grpc_retry_settings
12
- from digitalkin.models.settings.utils.channel import ControlFlow, SecurityMode
9
+ from digitalkin.models.settings.client.client import get_client_settings
10
+ from digitalkin.models.settings.utils.channel import ControlFlow, GrpcCompression, SecurityMode
13
11
 
14
-
15
- class GrpcCompression(str, Enum):
16
- """gRPC compression algorithm.
17
-
18
- Attributes:
19
- NONE: No compression
20
- GZIP: Gzip compression
21
- DEFLATE: Deflate compression
22
- """
23
-
24
- NONE = "none"
25
- GZIP = "gzip"
26
- DEFLATE = "deflate"
27
-
28
- def to_grpc(self) -> grpc.Compression:
29
- """Convert to grpc.Compression enum.
30
-
31
- Returns:
32
- The corresponding grpc.Compression value.
33
- """
34
- match self:
35
- case GrpcCompression.NONE:
36
- return grpc.Compression.NoCompression
37
- case GrpcCompression.GZIP:
38
- return grpc.Compression.Gzip
39
- case GrpcCompression.DEFLATE:
40
- return grpc.Compression.Deflate
12
+ __all__ = ["ChannelConfig", "ClientConfig", "ClientCredentials", "GrpcCompression", "RetryPolicy"]
41
13
 
42
14
 
43
15
  class RetryPolicy(BaseModel):
@@ -82,9 +54,9 @@ class RetryPolicy(BaseModel):
82
54
  """Build a retry policy with backoff values sourced from the environment.
83
55
 
84
56
  Returns:
85
- Retry policy populated from ``GrpcRetrySettings``.
57
+ Retry policy populated from ``GrpcClientRetrySettings``.
86
58
  """
87
- settings = get_grpc_retry_settings()
59
+ settings = get_client_settings().retry
88
60
  return cls(
89
61
  max_attempts=settings.max_attempts,
90
62
  initial_backoff=settings.initial_backoff,
@@ -205,9 +177,13 @@ class ChannelConfig(BaseModel):
205
177
  class ClientConfig(ChannelConfig):
206
178
  """Base configuration for gRPC clients.
207
179
 
180
+ Every default is sourced from ``ClientSettings`` (env prefixes ``CLIENT_``,
181
+ ``CLIENT_CHANNEL_``, ``CLIENT_GRPC_``), so a deployment configures its
182
+ clients through the environment and only overrides per-target values here.
183
+
208
184
  Attributes:
209
- host: Host address to bind the client to
210
- port: Port to listen on
185
+ host: Host address the client dials
186
+ port: Port the client dials
211
187
  mode: Client operation mode (sync/async)
212
188
  security: Security mode (secure/insecure)
213
189
  credentials: Client credentials for secure mode
@@ -216,13 +192,28 @@ class ClientConfig(ChannelConfig):
216
192
  compression: gRPC compression algorithm for channel-level compression
217
193
  """
218
194
 
195
+ host: str = Field(
196
+ default_factory=lambda: get_client_settings().channel.host,
197
+ description="Host address the client dials",
198
+ )
199
+ port: int = Field(default_factory=lambda: get_client_settings().channel.port, description="Port the client dials")
200
+ mode: ControlFlow = Field(
201
+ default_factory=lambda: get_client_settings().channel.communication_mode,
202
+ description="Client operation mode (sync/async)",
203
+ )
204
+ security: SecurityMode = Field(
205
+ default_factory=lambda: get_client_settings().channel.security,
206
+ description="Security mode (secure/insecure)",
207
+ )
219
208
  credentials: ClientCredentials | None = Field(None, description="Client credentials for secure mode")
220
209
  retry_policy: RetryPolicy = Field(
221
210
  default_factory=RetryPolicy.from_settings, description="Retry policy for failed RPCs"
222
211
  )
223
- compression: GrpcCompression = Field(GrpcCompression.GZIP, description="gRPC compression algorithm")
212
+ compression: GrpcCompression = Field(
213
+ default_factory=lambda: get_client_settings().grpc.compression, description="gRPC compression algorithm"
214
+ )
224
215
  channel_options: list[tuple[str, Any]] = Field(
225
- default_factory=lambda: get_grpc_channel_settings().to_channel_options(),
216
+ default_factory=lambda: get_client_settings().grpc.options,
226
217
  description="Resilient gRPC channel options with DNS re-resolution, keepalive, and retries",
227
218
  )
228
219
 
@@ -0,0 +1,90 @@
1
+ """TLS/mTLS certificate volume settings."""
2
+
3
+ from functools import lru_cache
4
+ from pathlib import Path
5
+
6
+ from pydantic import Field
7
+ from pydantic_settings import BaseSettings, SettingsConfigDict
8
+
9
+ from digitalkin.grpc_servers.exceptions import SecurityError
10
+
11
+
12
+ class CertificateSettings(BaseSettings):
13
+ """Directories holding the certificates a module serves and dials with.
14
+
15
+ Files follow the deployment convention: ``server.key`` / ``server.crt`` for
16
+ the module's own server, ``client.key`` / ``client.crt`` for its outgoing
17
+ calls, and ``ca.crt`` for the root of trust in both directories.
18
+
19
+ Attributes:
20
+ cert_volume (Path): Directory holding the module's server certificates.
21
+ services_provider_cert_volume (Path): Directory holding the client certificates
22
+ used to dial the services provider.
23
+
24
+ """
25
+
26
+ model_config = SettingsConfigDict(env_prefix="CERTIFICATE_", case_sensitive=False)
27
+
28
+ cert_volume: Path = Field(
29
+ default=Path("/certificates"),
30
+ description="Directory where the module's own server certificates are stored",
31
+ )
32
+ services_provider_cert_volume: Path = Field(
33
+ default=Path("/certificates"),
34
+ description="Directory where the services-provider client certificates are stored",
35
+ )
36
+
37
+ def get_server_certificate_paths(self, *, mtls: bool = False) -> tuple[Path, Path, Path | None]:
38
+ """Resolve the module server's key, certificate and root CA.
39
+
40
+ Args:
41
+ mtls: Return the CA certificate so incoming clients can be authenticated.
42
+
43
+ Returns:
44
+ Tuple of (server key, server certificate, root CA or None).
45
+
46
+ Raises:
47
+ SecurityError: If the server key or certificate is missing.
48
+ """
49
+ key_path = self.cert_volume / "server.key"
50
+ cert_path = self.cert_volume / "server.crt"
51
+ if not key_path.exists() or not cert_path.exists():
52
+ msg = f"Server key or certificate not found in {self.cert_volume}"
53
+ raise SecurityError(msg)
54
+ ca_path = self.cert_volume / "ca.crt"
55
+ return key_path, cert_path, (ca_path if mtls and ca_path.exists() else None)
56
+
57
+ def get_client_certificate_paths(self, *, mtls: bool = False) -> tuple[Path | None, Path | None, Path]:
58
+ """Resolve the client key, certificate and root CA used to dial the services provider.
59
+
60
+ Args:
61
+ mtls: Return the client key and certificate so the module can present them.
62
+
63
+ Returns:
64
+ Tuple of (client key or None, client certificate or None, root CA).
65
+
66
+ Raises:
67
+ SecurityError: If a required file is missing.
68
+ """
69
+ key_path = self.services_provider_cert_volume / "client.key"
70
+ cert_path = self.services_provider_cert_volume / "client.crt"
71
+ ca_path = self.services_provider_cert_volume / "ca.crt"
72
+ if mtls and (not key_path.exists() or not cert_path.exists()):
73
+ msg = f"Missing client.key or client.crt in {self.services_provider_cert_volume}"
74
+ raise SecurityError(msg)
75
+ if not ca_path.exists():
76
+ msg = f"Missing ca.crt in {self.services_provider_cert_volume}"
77
+ raise SecurityError(msg)
78
+ return (key_path if mtls else None, cert_path if mtls else None, ca_path)
79
+
80
+
81
+ @lru_cache(maxsize=1)
82
+ def get_certificate_settings() -> CertificateSettings:
83
+ """Process-wide ``CertificateSettings`` singleton.
84
+
85
+ Tests must call ``get_certificate_settings.cache_clear()`` after mutating env.
86
+
87
+ Returns:
88
+ The shared ``CertificateSettings`` instance.
89
+ """
90
+ return CertificateSettings()
@@ -0,0 +1 @@
1
+ """Package for client settings."""
@@ -0,0 +1,68 @@
1
+ """Client channel settings."""
2
+
3
+ from functools import lru_cache
4
+
5
+ from pydantic import Field, NonNegativeInt, model_validator
6
+ from pydantic_settings import SettingsConfigDict
7
+
8
+ from digitalkin.models.settings.utils.channel import BaseChannelSettings
9
+
10
+
11
+ class ClientChannelSettings(BaseChannelSettings):
12
+ """Settings for a client channel.
13
+
14
+ Overrides the bind-oriented defaults of ``BaseChannelSettings`` with dial
15
+ defaults: a client connects to a remote address instead of listening on
16
+ every interface.
17
+
18
+ Attributes:
19
+ host (str): Host address the client dials.
20
+ port (NonNegativeInt): Port the client dials.
21
+
22
+ """
23
+
24
+ model_config = SettingsConfigDict(
25
+ env_prefix="CLIENT_CHANNEL_",
26
+ env_nested_delimiter="__",
27
+ extra="forbid",
28
+ arbitrary_types_allowed=True,
29
+ validate_assignment=True,
30
+ )
31
+
32
+ host: str = Field(
33
+ default="[::]",
34
+ description="Host address the client dials (the services provider)",
35
+ json_schema_extra={"env_required": True},
36
+ )
37
+
38
+ port: NonNegativeInt = Field(
39
+ default=50051,
40
+ description="Port the client dials (the services provider)",
41
+ json_schema_extra={"env_required": True},
42
+ )
43
+
44
+ @model_validator(mode="after")
45
+ def validate_credentials(self) -> "ClientChannelSettings":
46
+ """Accept secure mode without explicit credential paths.
47
+
48
+ Unlike the server, a client falls back to the ``CERTIFICATE_`` volume:
49
+ ``EnvManager.client_config`` resolves the pair there and raises
50
+ ``SecurityError`` when the root CA is missing, so secure mode still
51
+ fails closed.
52
+
53
+ Returns:
54
+ The validated settings.
55
+ """
56
+ return self
57
+
58
+
59
+ @lru_cache(maxsize=1)
60
+ def get_client_channel_settings() -> ClientChannelSettings:
61
+ """Process-wide ``ClientChannelSettings`` singleton.
62
+
63
+ Tests must call ``get_client_channel_settings.cache_clear()`` after mutating env.
64
+
65
+ Returns:
66
+ The shared ``ClientChannelSettings`` instance.
67
+ """
68
+ return ClientChannelSettings()
@@ -0,0 +1,19 @@
1
+ """Client circuit-breaker settings."""
2
+
3
+ from pydantic import Field
4
+ from pydantic_settings import BaseSettings, SettingsConfigDict
5
+
6
+
7
+ class CircuitBreakerSettings(BaseSettings):
8
+ """Per-service circuit-breaker thresholds.
9
+
10
+ Attributes:
11
+ fail_max (int): Consecutive failures before the circuit opens.
12
+ reset_timeout (float): Seconds the circuit stays open before a half-open probe.
13
+
14
+ """
15
+
16
+ model_config = SettingsConfigDict(env_prefix="CLIENT_CIRCUIT_BREAKER_", case_sensitive=False)
17
+
18
+ fail_max: int = Field(default=5, description="Consecutive failures before the circuit opens.")
19
+ reset_timeout: float = Field(default=30.0, description="Seconds the circuit stays open before a half-open probe.")