digitalkin 1.0.0.dev5__tar.gz → 1.0.0.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 (243) hide show
  1. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/PKG-INFO +3 -3
  2. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/pyproject.toml +13 -13
  3. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/__init__.py +8 -10
  4. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/__version__.py +1 -1
  5. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/community/agno/__init__.py +1 -1
  6. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/community/agno/hitl.py +2 -29
  7. digitalkin-1.0.0.dev7/src/digitalkin/community/agno/models.py +28 -0
  8. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/common/factories.py +6 -5
  9. digitalkin-1.0.0.dev7/src/digitalkin/core/exceptions.py +16 -0
  10. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/job_manager/base_job_manager.py +3 -2
  11. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/job_manager/single_job_manager.py +18 -20
  12. digitalkin-1.0.0.dev7/src/digitalkin/core/profiling/__init__.py +6 -0
  13. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/profiling/step_timer.py +6 -1
  14. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/profiling/task_profiler.py +29 -72
  15. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/resilience/__init__.py +2 -1
  16. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/resilience/bulkhead.py +8 -8
  17. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/resilience/graceful_shutdown.py +10 -7
  18. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/resilience/session_reaper.py +8 -5
  19. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/resilience/task_supervisor.py +4 -2
  20. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/resilience/watchdog.py +10 -6
  21. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/task_manager/base_task_manager.py +14 -13
  22. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/task_manager/module_runner.py +50 -4
  23. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/task_manager/redis/__init__.py +2 -1
  24. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/task_manager/redis/proto_streams.py +43 -47
  25. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/task_manager/redis/redis_checkpoint.py +5 -4
  26. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/task_manager/redis/redis_client.py +4 -4
  27. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/task_manager/redis/redis_idempotency.py +7 -15
  28. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/task_manager/redis/redis_state.py +5 -4
  29. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/task_manager/redis/redis_streams.py +24 -15
  30. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/task_manager/task_executor.py +3 -3
  31. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/task_manager/task_session.py +5 -6
  32. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/task_manager/task_wrapper.py +1 -1
  33. digitalkin-1.0.0.dev7/src/digitalkin/exceptions.py +5 -0
  34. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/grpc_servers/_base_server.py +4 -2
  35. {digitalkin-1.0.0.dev5/src/digitalkin/grpc_servers/utils → digitalkin-1.0.0.dev7/src/digitalkin/grpc_servers}/exceptions.py +10 -6
  36. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/grpc_servers/gateway_servicer.py +183 -81
  37. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/grpc_servers/interceptors/circuit_breaker_interceptor.py +2 -1
  38. digitalkin-1.0.0.dev7/src/digitalkin/grpc_servers/m2m_call_registry.py +243 -0
  39. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/grpc_servers/module_server.py +12 -2
  40. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/grpc_servers/module_servicer.py +13 -9
  41. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/grpc_servers/stream_registry.py +9 -9
  42. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/grpc_servers/stream_session.py +1 -1
  43. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/grpc_servers/utils/circuit_breaker.py +13 -17
  44. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/grpc_servers/utils/grpc_client_wrapper.py +8 -38
  45. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/grpc_servers/utils/grpc_error_handler.py +1 -1
  46. digitalkin-1.0.0.dev7/src/digitalkin/grpc_servers/utils/validators.py +84 -0
  47. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/logger.py +8 -11
  48. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/mixins/file_history_mixin.py +3 -3
  49. digitalkin-1.0.0.dev7/src/digitalkin/models/core/redis.py +11 -0
  50. digitalkin-1.0.0.dev7/src/digitalkin/models/grpc_servers/circuit_breaker.py +11 -0
  51. digitalkin-1.0.0.dev7/src/digitalkin/models/grpc_servers/m2m.py +22 -0
  52. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/grpc_servers/models.py +25 -29
  53. {digitalkin-1.0.0.dev5/src/digitalkin → digitalkin-1.0.0.dev7/src/digitalkin/models}/grpc_servers/stream_error_codes.py +1 -0
  54. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/module/module_context.py +2 -2
  55. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/module/tool_reference.py +14 -5
  56. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/services/cost.py +11 -0
  57. digitalkin-1.0.0.dev7/src/digitalkin/models/services/services.py +10 -0
  58. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/services/storage.py +9 -0
  59. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/settings/gateway.py +81 -3
  60. digitalkin-1.0.0.dev7/src/digitalkin/models/settings/grpc_client.py +70 -0
  61. digitalkin-1.0.0.dev7/src/digitalkin/models/settings/log.py +24 -0
  62. digitalkin-1.0.0.dev7/src/digitalkin/models/settings/module.py +17 -0
  63. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/settings/profiling.py +12 -0
  64. digitalkin-1.0.0.dev7/src/digitalkin/models/settings/queue.py +12 -0
  65. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/settings/redis.py +15 -7
  66. digitalkin-1.0.0.dev7/src/digitalkin/models/settings/resilience.py +31 -0
  67. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/settings/server/grpc.py +13 -13
  68. digitalkin-1.0.0.dev7/src/digitalkin/models/settings/server/servicer.py +13 -0
  69. digitalkin-1.0.0.dev7/src/digitalkin/models/settings/task_manager.py +31 -0
  70. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/settings/utils/channel.py +1 -1
  71. digitalkin-1.0.0.dev7/src/digitalkin/models/utils/__init__.py +1 -0
  72. digitalkin-1.0.0.dev7/src/digitalkin/models/utils/dynamic_schema.py +54 -0
  73. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/modules/_base_module.py +25 -17
  74. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/modules/archetype_module.py +4 -0
  75. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/communication/__init__.py +8 -14
  76. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/communication/communication_strategy.py +15 -15
  77. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/communication/default_communication.py +20 -21
  78. digitalkin-1.0.0.dev7/src/digitalkin/services/communication/exceptions.py +13 -0
  79. digitalkin-1.0.0.dev7/src/digitalkin/services/communication/grpc_communication.py +479 -0
  80. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/cost/__init__.py +2 -1
  81. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/cost/cost_strategy.py +1 -17
  82. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/cost/default_cost.py +2 -3
  83. digitalkin-1.0.0.dev7/src/digitalkin/services/cost/exceptions.py +5 -0
  84. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/cost/grpc_cost.py +2 -3
  85. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/filesystem/default_filesystem.py +1 -1
  86. digitalkin-1.0.0.dev7/src/digitalkin/services/filesystem/exceptions.py +5 -0
  87. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/filesystem/filesystem_strategy.py +0 -4
  88. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/filesystem/grpc_filesystem.py +1 -1
  89. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/registry/grpc_registry.py +1 -1
  90. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/services_config.py +2 -1
  91. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/services_models.py +1 -8
  92. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/setup/default_setup.py +2 -1
  93. digitalkin-1.0.0.dev7/src/digitalkin/services/setup/exceptions.py +5 -0
  94. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/setup/grpc_setup.py +3 -3
  95. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/setup/setup_strategy.py +0 -4
  96. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/storage/default_storage.py +1 -1
  97. digitalkin-1.0.0.dev7/src/digitalkin/services/storage/exceptions.py +5 -0
  98. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/storage/grpc_storage.py +2 -2
  99. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/storage/storage_strategy.py +2 -14
  100. digitalkin-1.0.0.dev7/src/digitalkin/services/task_manager/exceptions.py +5 -0
  101. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/task_manager/task_manager_strategy.py +0 -4
  102. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/user_profile/__init__.py +2 -1
  103. digitalkin-1.0.0.dev7/src/digitalkin/services/user_profile/exceptions.py +5 -0
  104. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/user_profile/grpc_user_profile.py +2 -1
  105. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/user_profile/user_profile_strategy.py +0 -4
  106. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/utils/__init__.py +1 -1
  107. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/utils/development_mode_action.py +1 -1
  108. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/utils/dynamic_schema.py +1 -47
  109. digitalkin-1.0.0.dev7/src/digitalkin/utils/exceptions.py +9 -0
  110. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/utils/package_discover.py +16 -23
  111. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin.egg-info/PKG-INFO +3 -3
  112. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin.egg-info/SOURCES.txt +28 -4
  113. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin.egg-info/requires.txt +2 -2
  114. digitalkin-1.0.0.dev5/src/digitalkin/core/profiling/__init__.py +0 -5
  115. digitalkin-1.0.0.dev5/src/digitalkin/grpc_servers/gateway_constants.py +0 -145
  116. digitalkin-1.0.0.dev5/src/digitalkin/services/communication/gateway_consumer.py +0 -403
  117. digitalkin-1.0.0.dev5/src/digitalkin/services/communication/grpc_communication.py +0 -306
  118. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/LICENSE +0 -0
  119. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/README.md +0 -0
  120. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/base_server/__init__.py +0 -0
  121. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/base_server/mock/__init__.py +0 -0
  122. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/base_server/mock/mock_pb2.py +0 -0
  123. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/base_server/mock/mock_pb2_grpc.py +0 -0
  124. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/base_server/server_async_insecure.py +0 -0
  125. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/base_server/server_async_secure.py +0 -0
  126. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/base_server/server_sync_insecure.py +0 -0
  127. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/base_server/server_sync_secure.py +0 -0
  128. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/bench_module/__init__.py +0 -0
  129. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/bench_module/echo_module.py +0 -0
  130. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/bench_module/models/__init__.py +0 -0
  131. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/bench_module/models/input.py +0 -0
  132. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/bench_module/models/output.py +0 -0
  133. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/bench_module/models/secret.py +0 -0
  134. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/bench_module/models/setup.py +0 -0
  135. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/bench_module/server.py +0 -0
  136. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/bench_module/triggers/__init__.py +0 -0
  137. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/bench_module/triggers/message_trigger.py +0 -0
  138. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/modules/__init__.py +0 -0
  139. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/modules/archetype_with_tools_module.py +0 -0
  140. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/modules/cpu_intensive_module.py +0 -0
  141. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/modules/dynamic_setup_module.py +0 -0
  142. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/modules/minimal_llm_module.py +0 -0
  143. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/modules/text_transform_module.py +0 -0
  144. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/monitoring/digitalkin_observability/__init__.py +0 -0
  145. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/monitoring/digitalkin_observability/http_server.py +0 -0
  146. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/monitoring/digitalkin_observability/interceptors.py +0 -0
  147. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/monitoring/digitalkin_observability/metrics.py +0 -0
  148. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/monitoring/digitalkin_observability/prometheus.py +0 -0
  149. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/monitoring/tests/test_metrics.py +0 -0
  150. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/redis_demo/client.py +0 -0
  151. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/redis_demo/echo_module.py +0 -0
  152. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/redis_demo/models/__init__.py +0 -0
  153. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/redis_demo/models/input.py +0 -0
  154. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/redis_demo/models/output.py +0 -0
  155. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/redis_demo/models/secret.py +0 -0
  156. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/redis_demo/models/setup.py +0 -0
  157. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/redis_demo/server.py +0 -0
  158. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/redis_demo/triggers/__init__.py +0 -0
  159. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/redis_demo/triggers/message_trigger.py +0 -0
  160. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/services/filesystem_module.py +0 -0
  161. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/examples/services/storage_module.py +0 -0
  162. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/setup.cfg +0 -0
  163. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/community/__init__.py +0 -0
  164. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/community/agno/agno_adapter.py +0 -0
  165. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/community/agno/agui_tools.py +0 -0
  166. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/__init__.py +0 -0
  167. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/common/__init__.py +0 -0
  168. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/job_manager/__init__.py +0 -0
  169. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/task_manager/__init__.py +0 -0
  170. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/task_manager/local_task_manager.py +0 -0
  171. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/task_manager/redis/instrumented.py +0 -0
  172. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/task_manager/redis/redis_signal.py +0 -0
  173. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/task_manager/redis/shadow.py +0 -0
  174. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/core/task_manager/remote_task_manager.py +0 -0
  175. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/grpc_servers/__init__.py +0 -0
  176. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/grpc_servers/interceptors/__init__.py +0 -0
  177. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/grpc_servers/utils/__init__.py +0 -0
  178. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/grpc_servers/utils/utility_schema_extender.py +0 -0
  179. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/mixins/__init__.py +0 -0
  180. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/mixins/agui_mixin.py +0 -0
  181. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/mixins/base_mixin.py +0 -0
  182. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/mixins/cost_mixin.py +0 -0
  183. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/mixins/filesystem_mixin.py +0 -0
  184. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/mixins/logger_mixin.py +0 -0
  185. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/mixins/storage_mixin.py +0 -0
  186. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/__init__.py +0 -0
  187. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/core/__init__.py +0 -0
  188. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/core/job_manager_models.py +0 -0
  189. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/core/task_monitor.py +0 -0
  190. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/events/__init__.py +0 -0
  191. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/events/agent_events.py +0 -0
  192. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/grpc_servers/__init__.py +0 -0
  193. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/grpc_servers/types.py +0 -0
  194. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/module/__init__.py +0 -0
  195. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/module/ag_ui.py +0 -0
  196. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/module/base_types.py +0 -0
  197. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/module/module.py +0 -0
  198. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/module/module_types.py +0 -0
  199. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/module/request_metadata.py +0 -0
  200. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/module/select_schema.py +0 -0
  201. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/module/setup_types.py +0 -0
  202. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/module/tool_cache.py +0 -0
  203. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/module/utility.py +0 -0
  204. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/services/__init__.py +0 -0
  205. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/services/registry.py +0 -0
  206. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/settings/__init__.py +0 -0
  207. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/settings/consumer.py +0 -0
  208. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/settings/server/__init__.py +0 -0
  209. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/settings/server/channel.py +0 -0
  210. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/settings/server/server.py +0 -0
  211. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/models/settings/utils/__init__.py +0 -0
  212. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/modules/__init__.py +0 -0
  213. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/modules/tool_module.py +0 -0
  214. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/modules/trigger_handler.py +0 -0
  215. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/modules/triggers/__init__.py +0 -0
  216. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/modules/triggers/healthcheck_ping_trigger.py +0 -0
  217. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/modules/triggers/healthcheck_services_trigger.py +0 -0
  218. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/modules/triggers/healthcheck_status_trigger.py +0 -0
  219. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/py.typed +0 -0
  220. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/__init__.py +0 -0
  221. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/base_strategy.py +0 -0
  222. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/filesystem/__init__.py +0 -0
  223. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/identity/__init__.py +0 -0
  224. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/identity/default_identity.py +0 -0
  225. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/identity/identity_strategy.py +0 -0
  226. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/registry/__init__.py +0 -0
  227. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/registry/default_registry.py +0 -0
  228. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/registry/exceptions.py +0 -0
  229. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/registry/registry_models.py +0 -0
  230. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/registry/registry_strategy.py +0 -0
  231. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/setup/__init__.py +0 -0
  232. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/storage/__init__.py +0 -0
  233. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/task_manager/__init__.py +0 -0
  234. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/task_manager/default_task_manager.py +0 -0
  235. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/task_manager/redis_task_manager.py +0 -0
  236. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/services/user_profile/default_user_profile.py +0 -0
  237. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/utils/arg_parser.py +0 -0
  238. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/utils/conditional_schema.py +0 -0
  239. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/utils/llm_ready_schema.py +0 -0
  240. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/utils/proto_utils.py +0 -0
  241. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin/utils/schema_splitter.py +0 -0
  242. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin.egg-info/dependency_links.txt +0 -0
  243. {digitalkin-1.0.0.dev5 → digitalkin-1.0.0.dev7}/src/digitalkin.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: digitalkin
3
- Version: 1.0.0.dev5
3
+ Version: 1.0.0.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,13 +453,13 @@ 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.18
456
- Requires-Dist: agentic-mesh-protocol==1.0.0.dev1
456
+ Requires-Dist: agentic-mesh-protocol==1.0.0.dev2
457
457
  Requires-Dist: anyio>=4.13.0
458
458
  Requires-Dist: grpcio-health-checking==1.80.0
459
459
  Requires-Dist: grpcio-reflection==1.80.0
460
460
  Requires-Dist: grpcio-status==1.80.0
461
461
  Requires-Dist: pydantic>=2.12.4
462
- Requires-Dist: pydantic-settings>=2.14.0
462
+ Requires-Dist: pydantic-settings>=2.14.1
463
463
  Requires-Dist: redis[hiredis]<8,>=7.4.0
464
464
  Provides-Extra: performance
465
465
  Requires-Dist: uvloop>=0.21; extra == "performance"
@@ -28,16 +28,16 @@
28
28
 
29
29
  dependencies = [
30
30
  "ag-ui-protocol>=0.1.18",
31
- "agentic-mesh-protocol==1.0.0.dev1",
31
+ "agentic-mesh-protocol==1.0.0.dev2",
32
32
  "anyio>=4.13.0",
33
33
  "grpcio-health-checking==1.80.0",
34
34
  "grpcio-reflection==1.80.0",
35
35
  "grpcio-status==1.80.0",
36
36
  "pydantic>=2.12.4",
37
- "pydantic-settings>=2.14.0",
37
+ "pydantic-settings>=2.14.1",
38
38
  "redis[hiredis]>=7.4.0,<8",
39
39
  ]
40
- version = "1.0.0.dev5"
40
+ version = "1.0.0.dev7"
41
41
 
42
42
  [project.optional-dependencies]
43
43
  performance = [ "uvloop>=0.21" ]
@@ -60,16 +60,16 @@
60
60
  "build>=1.5.0",
61
61
  "bump-my-version>=1.3.0",
62
62
  "cryptography>=48.0.0",
63
- "mypy>=2.0.0",
63
+ "mypy>=2.1.0",
64
64
  "pre-commit>=4.6.0",
65
65
  "pyright>=1.1.409",
66
- "ruff>=0.15.12",
66
+ "ruff>=0.15.13",
67
67
  "twine>=6.2.0",
68
- "types-grpcio-health-checking>=1.0.0.20260408",
69
- "types-grpcio-reflection>=1.0.0.20260408",
70
- "types-grpcio>=1.0.0.20260408",
71
- "types-protobuf>=7.34.1.20260503",
72
- "typos>=1.46.0",
68
+ "types-grpcio-health-checking>=1.0.0.20260518",
69
+ "types-grpcio-reflection>=1.0.0.20260508",
70
+ "types-grpcio>=1.0.0.20260518",
71
+ "types-protobuf>=7.34.1.20260518",
72
+ "typos>=1.46.2",
73
73
  ]
74
74
  docs = [
75
75
  "griffe-inherited-docstrings>=1.1.3",
@@ -80,9 +80,9 @@
80
80
  "mkdocs-awesome-pages-plugin>=2.10.1",
81
81
  "mkdocs-coverage>=2.0.0",
82
82
  "mkdocs-git-committers-plugin-2>=2.5.0",
83
- "mkdocs-git-revision-date-localized-plugin>=1.5.1",
83
+ "mkdocs-git-revision-date-localized-plugin>=1.5.2",
84
84
  "mkdocs-glightbox>=0.5.2",
85
- "mkdocs-include-markdown-plugin>=7.2.2",
85
+ "mkdocs-include-markdown-plugin>=7.3.0",
86
86
  "mkdocs-literate-nav>=0.6.3",
87
87
  "mkdocs-llmstxt>=0.5.0",
88
88
  "mkdocs-material[imaging]>=9.7.6",
@@ -100,7 +100,7 @@
100
100
  "freezegun>=1.5.5",
101
101
  "grpcio-testing>=1.80.0",
102
102
  "hdrhistogram>=0.10.3",
103
- "hypothesis>=6.152.4",
103
+ "hypothesis>=6.152.8",
104
104
  "objgraph>=3.6",
105
105
  "psutil>=7.2.2",
106
106
  "pytest-asyncio>=1.3.0",
@@ -10,24 +10,22 @@ from digitalkin.modules.archetype_module import ArchetypeModule
10
10
  from digitalkin.modules.tool_module import ToolModule
11
11
  from digitalkin.modules.trigger_handler import TriggerHandler
12
12
  from digitalkin.services.communication import (
13
- ConsumerConfig,
14
- GatewayConsumer,
15
- GatewayConsumerError,
16
- StartStreamRejected,
17
- StartStreamRpcError,
13
+ GrpcCommunication,
14
+ M2MAtCapacityError,
15
+ M2MCallTimeout,
16
+ M2MTargetUnavailable,
18
17
  )
19
18
  from digitalkin.services.services_config import ServicesConfig
20
19
 
21
20
  __all__ = [
22
21
  "ArchetypeModule",
23
- "ConsumerConfig",
24
- "GatewayConsumer",
25
- "GatewayConsumerError",
22
+ "GrpcCommunication",
23
+ "M2MAtCapacityError",
24
+ "M2MCallTimeout",
25
+ "M2MTargetUnavailable",
26
26
  "ModuleContext",
27
27
  "ModuleStatus",
28
28
  "ServicesConfig",
29
- "StartStreamRejected",
30
- "StartStreamRpcError",
31
29
  "ToolModule",
32
30
  "TriggerHandler",
33
31
  "__version__",
@@ -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.0.dev5"
8
+ __version__ = "1.0.0.dev7"
@@ -24,10 +24,10 @@ from digitalkin.community.agno.hitl import (
24
24
  AgnoHitlRunner,
25
25
  PausedRunRecord,
26
26
  PausedRunStore,
27
- PauseInfo,
28
27
  emit_awaiting_tool_result,
29
28
  emit_messages_snapshot,
30
29
  )
30
+ from digitalkin.community.agno.models import PauseInfo
31
31
 
32
32
  __all__ = [
33
33
  "HITL_STORAGE_CONFIG",
@@ -66,11 +66,12 @@ from __future__ import annotations
66
66
 
67
67
  import json
68
68
  import logging
69
- from dataclasses import dataclass, field
70
69
  from typing import TYPE_CHECKING, Any, ClassVar
71
70
 
72
71
  from pydantic import BaseModel, ConfigDict, Field
73
72
 
73
+ from digitalkin.community.agno.models import PauseInfo
74
+
74
75
  if TYPE_CHECKING:
75
76
  from collections.abc import Callable, Coroutine
76
77
 
@@ -123,34 +124,6 @@ Example::
123
124
  """
124
125
 
125
126
 
126
- # ── Return type ─────────────────────────────────────────────────────────────
127
-
128
-
129
- @dataclass
130
- class PauseInfo:
131
- """Summary of a paused Agno run.
132
-
133
- Returned by :meth:`AgnoHitlRunner.run` and related methods whenever
134
- the run paused on one or more external tool calls. Callers typically
135
- use it to emit the AG-UI awaiting-tool-result event to the front.
136
-
137
- ``new_messages`` carries the AG-UI messages generated by Agno during
138
- the paused run (user echoes, the assistant message with ``tool_calls``,
139
- and any tool results emitted before the pause). It's provided because
140
- Agno does not emit stream events from which the front can reconstruct
141
- the assistant-with-tool-calls message — in particular, when the LLM
142
- goes straight from reasoning to a frontend tool call without emitting
143
- any text. Consumers typically push these messages to the front via a
144
- :class:`~ag_ui.core.events.MessagesSnapshotEvent` so the client has an
145
- authoritative view of the conversation.
146
- """
147
-
148
- thread_id: str
149
- run_id: str
150
- pending_tool_call_ids: list[str]
151
- new_messages: list[AgUiMessage] = field(default_factory=list)
152
-
153
-
154
127
  # ── Storage wrapper ─────────────────────────────────────────────────────────
155
128
 
156
129
 
@@ -0,0 +1,28 @@
1
+ """Models for the Agno community integration."""
2
+
3
+ from ag_ui.core.types import Message as AgUiMessage
4
+ from pydantic import BaseModel, Field
5
+
6
+
7
+ class PauseInfo(BaseModel):
8
+ """Summary of a paused Agno run.
9
+
10
+ Returned by :meth:`AgnoHitlRunner.run` and related methods whenever
11
+ the run paused on one or more external tool calls. Callers typically
12
+ use it to emit the AG-UI awaiting-tool-result event to the front.
13
+
14
+ ``new_messages`` carries the AG-UI messages generated by Agno during
15
+ the paused run (user echoes, the assistant message with ``tool_calls``,
16
+ and any tool results emitted before the pause). It's provided because
17
+ Agno does not emit stream events from which the front can reconstruct
18
+ the assistant-with-tool-calls message — in particular, when the LLM
19
+ goes straight from reasoning to a frontend tool call without emitting
20
+ any text. Consumers typically push these messages to the front via a
21
+ :class:`~ag_ui.core.events.MessagesSnapshotEvent` so the client has an
22
+ authoritative view of the conversation.
23
+ """
24
+
25
+ thread_id: str
26
+ run_id: str
27
+ pending_tool_call_ids: list[str]
28
+ new_messages: list[AgUiMessage] = Field(default_factory=list)
@@ -6,6 +6,7 @@ import asyncio
6
6
  from typing import TYPE_CHECKING
7
7
 
8
8
  from digitalkin.logger import logger
9
+ from digitalkin.models.settings.queue import QueueSettings
9
10
 
10
11
  if TYPE_CHECKING:
11
12
  from digitalkin.models.module.tool_cache import ToolCache
@@ -88,15 +89,13 @@ class ModuleFactory:
88
89
  class QueueFactory:
89
90
  """Factory for creating asyncio queues with consistent configuration."""
90
91
 
91
- # Default max queue size to prevent unbounded memory growth
92
- DEFAULT_MAX_QUEUE_SIZE = 1000
93
-
94
92
  @staticmethod
95
- def create_bounded_queue(maxsize: int = DEFAULT_MAX_QUEUE_SIZE) -> asyncio.Queue:
93
+ def create_bounded_queue(maxsize: int | None = None) -> asyncio.Queue:
96
94
  """Create a bounded asyncio queue with standard configuration.
97
95
 
98
96
  Args:
99
- maxsize: Maximum queue size (default 1000, 0 means unlimited)
97
+ maxsize: Maximum queue size. ``None`` uses QueueSettings.max_size
98
+ (default 1000); 0 means unlimited.
100
99
 
101
100
  Returns:
102
101
  Bounded asyncio.Queue instance
@@ -111,6 +110,8 @@ class QueueFactory:
111
110
  # unlimited queue
112
111
  queue = QueueFactory.create_bounded_queue(maxsize=0)
113
112
  """
113
+ if maxsize is None:
114
+ maxsize = QueueSettings().max_size
114
115
  if maxsize < 0:
115
116
  msg = "maxsize must be >= 0"
116
117
  raise ValueError(msg)
@@ -0,0 +1,16 @@
1
+ """Exceptions for the DigitalKin core package."""
2
+
3
+
4
+ class BackpressureTimeoutError(Exception):
5
+ """Producer's XADD throttled past the backpressure timeout.
6
+
7
+ Throttled past :data:`GatewayBackpressureSettings.backpressure_timeout_s`.
8
+ Caller (typically the module's ``_on_output`` callback) must surface
9
+ this as ``stream.error(code=BACKPRESSURE_TIMEOUT)`` via the
10
+ ``_emit_fatal_to_redis`` path so the consumer sees a typed sentinel
11
+ instead of a silent stall.
12
+ """
13
+
14
+
15
+ class BulkheadFullError(Exception):
16
+ """Raised when a bulkhead semaphore cannot be acquired within timeout."""
@@ -8,9 +8,9 @@ from digitalkin.core.task_manager.base_task_manager import BaseTaskManager
8
8
  from digitalkin.core.task_manager.task_session import TaskSession
9
9
  from digitalkin.models.module.module import ModuleCodeModel
10
10
  from digitalkin.models.module.module_types import DataModel, InputModelT, OutputModelT, SetupModelT
11
+ from digitalkin.models.services.services import ServicesMode
11
12
  from digitalkin.modules._base_module import BaseModule
12
13
  from digitalkin.services.services_config import ServicesConfig
13
- from digitalkin.services.services_models import ServicesMode
14
14
 
15
15
 
16
16
  class BaseJobManager(abc.ABC, Generic[InputModelT, OutputModelT, SetupModelT]):
@@ -58,7 +58,6 @@ class BaseJobManager(abc.ABC, Generic[InputModelT, OutputModelT, SetupModelT]):
58
58
  """Get tasks from the task manager."""
59
59
  return self._task_manager.tasks
60
60
 
61
- # Delegate task lifecycle methods to task manager
62
61
  async def create_task(
63
62
  self,
64
63
  task_id: str,
@@ -69,6 +68,8 @@ class BaseJobManager(abc.ABC, Generic[InputModelT, OutputModelT, SetupModelT]):
69
68
  ) -> None:
70
69
  """Create a task using the task manager.
71
70
 
71
+ Delegate task lifecycle methods to task manager
72
+
72
73
  Args:
73
74
  task_id: Unique identifier for the task
74
75
  mission_id: Mission identifier
@@ -9,7 +9,6 @@ the in-memory queue (for local consumers) and a Redis Stream
9
9
  from __future__ import annotations
10
10
 
11
11
  import asyncio
12
- import os
13
12
  import uuid
14
13
  from typing import TYPE_CHECKING, Any
15
14
 
@@ -17,20 +16,23 @@ import grpc
17
16
 
18
17
  from digitalkin.core.common import ModuleFactory
19
18
  from digitalkin.core.job_manager.base_job_manager import BaseJobManager
19
+ from digitalkin.core.profiling.step_timer import StepTimer
20
20
  from digitalkin.core.task_manager.local_task_manager import LocalTaskManager
21
+ from digitalkin.core.task_manager.redis.redis_streams import RedisStreamWriter
21
22
  from digitalkin.core.task_manager.task_session import TaskSession
22
23
  from digitalkin.logger import logger
23
24
  from digitalkin.models.core.job_manager_models import BackpressureStrategy
24
25
  from digitalkin.models.module.base_types import DataModel, InputModelT, OutputModelT, SetupModelT
25
26
  from digitalkin.models.module.module import ModuleCodeModel
27
+ from digitalkin.models.settings.task_manager import JobManagerSettings
28
+ from digitalkin.services.task_manager.redis_task_manager import RedisTaskManager
26
29
 
27
30
  if TYPE_CHECKING:
28
31
  from collections.abc import Callable
29
32
 
30
33
  from digitalkin.core.task_manager.redis.redis_client import RedisClient
31
- from digitalkin.core.task_manager.redis.redis_streams import RedisStreamWriter
34
+ from digitalkin.models.services.services import ServicesMode
32
35
  from digitalkin.modules._base_module import BaseModule
33
- from digitalkin.services.services_models import ServicesMode
34
36
 
35
37
 
36
38
  class SingleJobManager(BaseJobManager[InputModelT, OutputModelT, SetupModelT]):
@@ -54,7 +56,7 @@ class SingleJobManager(BaseJobManager[InputModelT, OutputModelT, SetupModelT]):
54
56
  services_mode: ServicesMode,
55
57
  redis_client: RedisClient,
56
58
  default_timeout: float = 300.0,
57
- max_concurrent_tasks: int = int(os.environ.get("DIGITALKIN_MAX_CONCURRENT_TASKS", "100")),
59
+ max_concurrent_tasks: int | None = None,
58
60
  ) -> None:
59
61
  """Initialize the job manager.
60
62
 
@@ -62,22 +64,25 @@ class SingleJobManager(BaseJobManager[InputModelT, OutputModelT, SetupModelT]):
62
64
  module_class: The class of the module to be managed.
63
65
  services_mode: The mode of operation for the services (e.g., ASYNC or SYNC).
64
66
  default_timeout: Default timeout for task operations
65
- max_concurrent_tasks: Maximum number of concurrent tasks
67
+ max_concurrent_tasks: Maximum number of concurrent tasks. ``None`` keeps
68
+ the task manager's TaskManagerSettings-derived limit.
66
69
  redis_client: Redis client for signal delivery and stream persistence.
67
70
  """
68
71
  # Create local task manager for same-process execution
69
72
  task_manager = LocalTaskManager(default_timeout)
70
- task_manager.max_concurrent_tasks = max_concurrent_tasks
73
+ if max_concurrent_tasks is not None:
74
+ task_manager.max_concurrent_tasks = max_concurrent_tasks
71
75
 
72
76
  # Initialize base job manager with task manager
73
77
  super().__init__(module_class, services_mode, task_manager)
74
78
 
79
+ jm_settings = JobManagerSettings()
75
80
  self._lock = asyncio.Lock()
76
- self._config_setup_timeout = float(os.environ.get("DIGITALKIN_CONFIG_SETUP_TIMEOUT", "30.0"))
81
+ self._config_setup_timeout = jm_settings.config_setup_timeout
77
82
 
78
83
  # Backpressure configuration
79
- self._backpressure_strategy = BackpressureStrategy(os.environ.get("DIGITALKIN_BACKPRESSURE_STRATEGY", "block"))
80
- self._backpressure_timeout = float(os.environ.get("DIGITALKIN_BACKPRESSURE_TIMEOUT", "300.0"))
84
+ self._backpressure_strategy = jm_settings.backpressure_strategy
85
+ self._backpressure_timeout = jm_settings.backpressure_timeout
81
86
 
82
87
  # Redis for signal delivery and durable output persistence
83
88
  self._redis_client = redis_client
@@ -86,8 +91,6 @@ class SingleJobManager(BaseJobManager[InputModelT, OutputModelT, SetupModelT]):
86
91
  # Pool one RedisTaskManager across all preload_instance calls.
87
92
  # The class is task-id-stateless; its `_listener` is already a
88
93
  # process-wide singleton via SharedRedisListener.get_or_create.
89
- from digitalkin.services.task_manager.redis_task_manager import RedisTaskManager
90
-
91
94
  self._task_manager_strategy = RedisTaskManager(self._redis_client)
92
95
 
93
96
  async def start(self) -> None:
@@ -198,7 +201,8 @@ class SingleJobManager(BaseJobManager[InputModelT, OutputModelT, SetupModelT]):
198
201
  logger.debug("Queue write rejected - session not found", extra={"job_id": job_id})
199
202
  return
200
203
 
201
- # Serialize outside the lock — pure computation, no contention
204
+ # Serialize outside the lock — pure computation, no contention.
205
+ # Redis stores only bytes/strings, so a JSON-compatible dump is required.
202
206
  data = output_data.model_dump(mode="json")
203
207
 
204
208
  # P1: Redis write outside lock — XADD is idempotent, safe without serialization.
@@ -256,7 +260,7 @@ class SingleJobManager(BaseJobManager[InputModelT, OutputModelT, SetupModelT]):
256
260
  tool_cache: Any = None,
257
261
  callback: Callable | None = None,
258
262
  ) -> tuple[Any, str, Callable]:
259
- """Phase 3.A: Build + warm a module instance without input.
263
+ """Build + warm a module instance without input.
260
264
 
261
265
  Calls the factory, wires the redis task manager + callback, and
262
266
  runs the module's ``prepare()`` (which is idempotent — the later
@@ -279,8 +283,6 @@ class SingleJobManager(BaseJobManager[InputModelT, OutputModelT, SetupModelT]):
279
283
  Returns:
280
284
  ``(module, job_id, callback)`` — pass to ``run_preloaded``.
281
285
  """
282
- from digitalkin.core.profiling.step_timer import StepTimer
283
-
284
286
  timer = StepTimer()
285
287
  job_id = job_id or str(uuid.uuid4())
286
288
  module = ModuleFactory.create_module_instance(
@@ -299,8 +301,6 @@ class SingleJobManager(BaseJobManager[InputModelT, OutputModelT, SetupModelT]):
299
301
  timer.mark("redis_task_manager")
300
302
 
301
303
  if callback is None:
302
- from digitalkin.core.task_manager.redis.redis_streams import RedisStreamWriter
303
-
304
304
  self._stream_writers[job_id] = RedisStreamWriter(job_id, self._redis_client)
305
305
  callback = await self.job_specific_callback(self.add_to_queue, job_id)
306
306
  timer.mark("default_callback")
@@ -319,7 +319,7 @@ class SingleJobManager(BaseJobManager[InputModelT, OutputModelT, SetupModelT]):
319
319
  setup_data: SetupModelT,
320
320
  callback: Callable,
321
321
  ) -> str:
322
- """Phase 3.A: Run a pre-prepared module instance with input.
322
+ """Run a pre-prepared module instance with input.
323
323
 
324
324
  ``module`` must come from :meth:`preload_instance`. Schedules
325
325
  the run in the task manager and returns the job_id.
@@ -335,8 +335,6 @@ class SingleJobManager(BaseJobManager[InputModelT, OutputModelT, SetupModelT]):
335
335
  Returns:
336
336
  The ``job_id`` (echoed for caller convenience).
337
337
  """
338
- from digitalkin.core.profiling.step_timer import StepTimer
339
-
340
338
  timer = StepTimer()
341
339
  await self.create_task(
342
340
  job_id,
@@ -0,0 +1,6 @@
1
+ """Profiling and monitoring tools for DigitalKin tasks and servers."""
2
+
3
+ from digitalkin.core.profiling.task_profiler import TaskProfiler
4
+ from digitalkin.models.settings.profiling import ProfilerMode
5
+
6
+ __all__ = ["ProfilerMode", "TaskProfiler"]
@@ -33,6 +33,7 @@ class StepTimer:
33
33
  __slots__ = ("_last", "_steps", "_t0")
34
34
 
35
35
  def __init__(self) -> None:
36
+ """Init start time."""
36
37
  now = time.perf_counter_ns()
37
38
  self._t0 = now
38
39
  self._last = now
@@ -55,5 +56,9 @@ class StepTimer:
55
56
  logger.info("[lat-audit] %s: %s", prefix, " ".join(parts))
56
57
 
57
58
  def total_ms(self) -> float:
58
- """Total elapsed time across all marks in milliseconds."""
59
+ """Total elapsed time across all marks in milliseconds.
60
+
61
+ Returns:
62
+ float: time elapsed in ms
63
+ """
59
64
  return (self._last - self._t0) / 1e6
@@ -2,51 +2,12 @@
2
2
 
3
3
  import datetime
4
4
  import io
5
- import logging
6
5
  import os
7
- from enum import Enum
8
6
  from pathlib import Path
9
- from typing import Any
7
+ from typing import Any, ClassVar
10
8
 
11
9
  from digitalkin.logger import logger
12
-
13
- # Phase 7.C: rotate per-task profile files to avoid unbounded growth.
14
- # Default keeps the most recent N profiles by mtime; configure via
15
- # ``DIGITALKIN_PROFILER_KEEP_N``.
16
- PROFILER_KEEP_N = int(os.environ.get("DIGITALKIN_PROFILER_KEEP_N", "100"))
17
-
18
-
19
- def _rotate_profiles(output_dir: str, keep_n: int, suffixes: tuple[str, ...]) -> None:
20
- """Trim ``output_dir`` to the most recent ``keep_n`` files by mtime.
21
-
22
- Args:
23
- output_dir: Directory containing profile files.
24
- keep_n: Number of files to keep. ``<= 0`` disables rotation.
25
- suffixes: File extensions to include in rotation (e.g. ``(".html",)``).
26
- """
27
- if keep_n <= 0:
28
- return
29
- try:
30
- candidates = [p for p in Path(output_dir).iterdir() if p.is_file() and p.suffix in suffixes]
31
- except OSError:
32
- return
33
- if len(candidates) <= keep_n:
34
- return
35
- candidates.sort(key=lambda p: p.stat().st_mtime, reverse=True)
36
- for stale in candidates[keep_n:]:
37
- try:
38
- stale.unlink()
39
- except OSError:
40
- logger.debug("Profiler rotation: could not delete %s", stale)
41
-
42
-
43
- class ProfilerMode(str, Enum):
44
- """Profiler backend selection."""
45
-
46
- NONE = "none"
47
- VIZTRACER = "viztracer"
48
- YAPPI = "yappi"
49
- PYINSTRUMENT = "pyinstrument"
10
+ from digitalkin.models.settings.profiling import ProfilerMode, ProfilingSettings
50
11
 
51
12
 
52
13
  class TaskProfiler:
@@ -59,6 +20,8 @@ class TaskProfiler:
59
20
  run concurrently, yappi stats reflect all of them.
60
21
  """
61
22
 
23
+ _settings: ClassVar[ProfilingSettings] = ProfilingSettings()
24
+
62
25
  def __init__(self, task_id: str, mode: ProfilerMode, output_dir: str) -> None:
63
26
  """Initialize the task profiler.
64
27
 
@@ -73,6 +36,30 @@ class TaskProfiler:
73
36
  self._profiler: Any = None
74
37
  self._yappi_started: bool = False
75
38
 
39
+ @staticmethod
40
+ def _rotate_profiles(output_dir: str, keep_n: int, suffixes: tuple[str, ...]) -> None:
41
+ """Trim ``output_dir`` to the most recent ``keep_n`` files by mtime.
42
+
43
+ Args:
44
+ output_dir: Directory containing profile files.
45
+ keep_n: Number of files to keep. ``<= 0`` disables rotation.
46
+ suffixes: File extensions to include in rotation (e.g. ``(".html",)``).
47
+ """
48
+ if keep_n <= 0:
49
+ return
50
+ try:
51
+ candidates = [p for p in Path(output_dir).iterdir() if p.is_file() and p.suffix in suffixes]
52
+ except OSError:
53
+ return
54
+ if len(candidates) <= keep_n:
55
+ return
56
+ candidates.sort(key=lambda p: p.stat().st_mtime, reverse=True)
57
+ for stale in candidates[keep_n:]:
58
+ try:
59
+ stale.unlink()
60
+ except OSError: # noqa: PERF203
61
+ logger.debug("Profiler rotation: could not delete %s", stale)
62
+
76
63
  def start(self) -> None:
77
64
  """Start the profiler. No-op when mode is NONE."""
78
65
  if self._mode == ProfilerMode.NONE:
@@ -150,40 +137,10 @@ class TaskProfiler:
150
137
  Path(path).write_text(self._profiler.output_html(), encoding="utf-8")
151
138
  logger.info("Pyinstrument profile saved: %s", path)
152
139
  logger.info("Pyinstrument summary:\n%s", self._profiler.output_text())
153
- _rotate_profiles(self._output_dir, PROFILER_KEEP_N, (".html",))
140
+ self._rotate_profiles(self._output_dir, self._settings.profiler_keep_n, (".html",))
154
141
 
155
142
  except Exception:
156
143
  logger.exception("Failed to stop/save profiler %s for task %s", self._mode.value, self._task_id)
157
144
  finally:
158
145
  self._profiler = None
159
146
  self._yappi_started = False
160
-
161
-
162
- class _LogWriter:
163
- """Adapter to redirect yappi print_all output to a logger."""
164
-
165
- def __init__(self, target_logger: logging.Logger, level: int) -> None:
166
- """Initialize the log writer.
167
-
168
- Args:
169
- target_logger: Logger to write to.
170
- level: Logging level for output.
171
- """
172
- self._logger = target_logger
173
- self._level = level
174
- self._buffer: list[str] = []
175
-
176
- def write(self, text: str) -> None:
177
- """Buffer text lines for logging.
178
-
179
- Args:
180
- text: Text to write.
181
- """
182
- if text and text.strip():
183
- self._buffer.append(text.rstrip())
184
-
185
- def flush(self) -> None:
186
- """Flush buffered lines to the logger."""
187
- if self._buffer:
188
- self._logger.log(self._level, "Yappi top functions:\n%s", "\n".join(self._buffer))
189
- self._buffer.clear()
@@ -7,7 +7,8 @@
7
7
  - ``StartupRestorer``: Redis checkpoint restore on startup.
8
8
  """
9
9
 
10
- from digitalkin.core.resilience.bulkhead import Bulkhead, BulkheadFullError
10
+ from digitalkin.core.exceptions import BulkheadFullError
11
+ from digitalkin.core.resilience.bulkhead import Bulkhead
11
12
  from digitalkin.core.resilience.graceful_shutdown import GracefulShutdownHandler, StartupRestorer
12
13
  from digitalkin.core.resilience.session_reaper import SessionReaper
13
14
  from digitalkin.core.resilience.watchdog import WatchdogThread
@@ -20,11 +20,8 @@ from typing import ClassVar
20
20
 
21
21
  from typing_extensions import Self
22
22
 
23
- from digitalkin.logger import logger
24
-
25
-
26
- class BulkheadFullError(Exception):
27
- """Raised when a bulkhead semaphore cannot be acquired within timeout."""
23
+ from digitalkin.core.exceptions import BulkheadFullError
24
+ from digitalkin.models.settings.resilience import BulkheadSettings
28
25
 
29
26
 
30
27
  class Bulkhead:
@@ -69,9 +66,12 @@ class Bulkhead:
69
66
  oldest = next(iter(cls._instances))
70
67
  del cls._instances[oldest]
71
68
 
72
- env_key = f"DIGITALKIN_BULKHEAD_{service_id.upper()}_MAX"
73
- default_max = int(os.environ.get(env_key, os.environ.get("DIGITALKIN_BULKHEAD_DEFAULT_MAX", "50")))
74
- default_timeout = float(os.environ.get("DIGITALKIN_BULKHEAD_TIMEOUT", "2.0"))
69
+ settings = BulkheadSettings()
70
+ # Per-service override has a dynamic env-var suffix, so it cannot be a
71
+ # static settings field — read it directly, falling back to the setting.
72
+ env_max = os.environ.get(f"DIGITALKIN_BULKHEAD_{service_id.upper()}_MAX")
73
+ default_max = int(env_max) if env_max is not None else settings.default_max
74
+ default_timeout = settings.timeout
75
75
 
76
76
  inst = cls(
77
77
  service_id=service_id,