digitalkin 0.3.5.dev12__tar.gz → 0.4.0.dev1__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 (174) hide show
  1. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/PKG-INFO +3 -3
  2. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/examples/modules/archetype_with_tools_module.py +3 -2
  3. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/pyproject.toml +12 -12
  4. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/__version__.py +1 -1
  5. digitalkin-0.4.0.dev1/src/digitalkin/community/agno/agno_adapter.py +548 -0
  6. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/core/job_manager/base_job_manager.py +6 -0
  7. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/core/job_manager/single_job_manager.py +1 -4
  8. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/core/job_manager/taskiq_broker.py +211 -13
  9. digitalkin-0.4.0.dev1/src/digitalkin/core/job_manager/taskiq_job_manager.py +659 -0
  10. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/core/task_manager/task_session.py +2 -0
  11. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/grpc_servers/_base_server.py +56 -48
  12. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/grpc_servers/module_server.py +37 -12
  13. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/grpc_servers/module_servicer.py +42 -3
  14. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/grpc_servers/utils/grpc_client_wrapper.py +35 -10
  15. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/mixins/__init__.py +0 -4
  16. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/mixins/agui_mixin.py +3 -3
  17. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/mixins/base_mixin.py +2 -2
  18. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/mixins/callback_mixin.py +19 -5
  19. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/mixins/chat_history_mixin.py +14 -8
  20. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/grpc_servers/models.py +2 -138
  21. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/module/__init__.py +0 -2
  22. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/module/module_context.py +2 -18
  23. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/module/setup_types.py +124 -13
  24. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/module/tool_cache.py +51 -45
  25. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/module/tool_reference.py +17 -9
  26. digitalkin-0.4.0.dev1/src/digitalkin/models/settings/__init__.py +1 -0
  27. digitalkin-0.4.0.dev1/src/digitalkin/models/settings/server/__init__.py +1 -0
  28. digitalkin-0.4.0.dev1/src/digitalkin/models/settings/server/channel.py +36 -0
  29. digitalkin-0.4.0.dev1/src/digitalkin/models/settings/server/grpc.py +99 -0
  30. digitalkin-0.4.0.dev1/src/digitalkin/models/settings/server/server.py +47 -0
  31. digitalkin-0.4.0.dev1/src/digitalkin/models/settings/utils/__init__.py +1 -0
  32. digitalkin-0.4.0.dev1/src/digitalkin/models/settings/utils/channel.py +148 -0
  33. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/modules/_base_module.py +38 -15
  34. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/modules/triggers/healthcheck_ping_trigger.py +1 -1
  35. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/modules/triggers/healthcheck_services_trigger.py +2 -2
  36. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/modules/triggers/healthcheck_status_trigger.py +1 -1
  37. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/registry/registry_strategy.py +12 -0
  38. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/utils/conditional_schema.py +2 -3
  39. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin.egg-info/PKG-INFO +3 -3
  40. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin.egg-info/SOURCES.txt +7 -0
  41. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin.egg-info/requires.txt +2 -2
  42. digitalkin-0.3.5.dev12/src/digitalkin/community/agno/agno_adapter.py +0 -496
  43. digitalkin-0.3.5.dev12/src/digitalkin/core/job_manager/taskiq_job_manager.py +0 -477
  44. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/LICENSE +0 -0
  45. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/README.md +0 -0
  46. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/examples/base_server/__init__.py +0 -0
  47. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/examples/base_server/mock/__init__.py +0 -0
  48. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/examples/base_server/mock/mock_pb2.py +0 -0
  49. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/examples/base_server/mock/mock_pb2_grpc.py +0 -0
  50. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/examples/base_server/server_async_insecure.py +0 -0
  51. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/examples/base_server/server_async_secure.py +0 -0
  52. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/examples/base_server/server_sync_insecure.py +0 -0
  53. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/examples/base_server/server_sync_secure.py +0 -0
  54. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/examples/modules/__init__.py +0 -0
  55. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/examples/modules/cpu_intensive_module.py +0 -0
  56. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/examples/modules/dynamic_setup_module.py +0 -0
  57. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/examples/modules/minimal_llm_module.py +0 -0
  58. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/examples/modules/text_transform_module.py +0 -0
  59. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/examples/monitoring/digitalkin_observability/__init__.py +0 -0
  60. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/examples/monitoring/digitalkin_observability/http_server.py +0 -0
  61. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/examples/monitoring/digitalkin_observability/interceptors.py +0 -0
  62. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/examples/monitoring/digitalkin_observability/metrics.py +0 -0
  63. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/examples/monitoring/digitalkin_observability/prometheus.py +0 -0
  64. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/examples/monitoring/tests/test_metrics.py +0 -0
  65. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/examples/services/filesystem_module.py +0 -0
  66. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/examples/services/storage_module.py +0 -0
  67. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/setup.cfg +0 -0
  68. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/__init__.py +0 -0
  69. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/community/__init__.py +0 -0
  70. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/community/agno/__init__.py +0 -0
  71. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/core/__init__.py +0 -0
  72. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/core/common/__init__.py +0 -0
  73. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/core/common/factories.py +0 -0
  74. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/core/job_manager/__init__.py +0 -0
  75. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/core/profiling/__init__.py +0 -0
  76. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/core/profiling/asyncio_monitor.py +0 -0
  77. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/core/profiling/task_profiler.py +0 -0
  78. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/core/task_manager/__init__.py +0 -0
  79. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/core/task_manager/base_task_manager.py +0 -0
  80. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/core/task_manager/local_task_manager.py +0 -0
  81. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/core/task_manager/remote_task_manager.py +0 -0
  82. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/core/task_manager/task_executor.py +0 -0
  83. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/grpc_servers/__init__.py +0 -0
  84. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/grpc_servers/utils/__init__.py +0 -0
  85. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/grpc_servers/utils/exceptions.py +0 -0
  86. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/grpc_servers/utils/grpc_error_handler.py +0 -0
  87. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/grpc_servers/utils/utility_schema_extender.py +0 -0
  88. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/logger.py +0 -0
  89. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/mixins/cost_mixin.py +0 -0
  90. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/mixins/file_history_mixin.py +0 -0
  91. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/mixins/filesystem_mixin.py +0 -0
  92. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/mixins/logger_mixin.py +0 -0
  93. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/mixins/storage_mixin.py +0 -0
  94. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/__init__.py +0 -0
  95. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/core/__init__.py +0 -0
  96. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/core/job_manager_models.py +0 -0
  97. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/core/task_monitor.py +0 -0
  98. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/events/__init__.py +0 -0
  99. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/events/agent_events.py +0 -0
  100. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/grpc_servers/__init__.py +0 -0
  101. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/grpc_servers/types.py +0 -0
  102. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/module/ag_ui.py +0 -0
  103. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/module/base_types.py +0 -0
  104. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/module/module.py +0 -0
  105. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/module/module_types.py +0 -0
  106. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/module/request_metadata.py +0 -0
  107. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/module/select_schema.py +0 -0
  108. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/module/utility.py +0 -0
  109. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/services/__init__.py +0 -0
  110. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/services/cost.py +0 -0
  111. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/services/registry.py +0 -0
  112. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/models/services/storage.py +0 -0
  113. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/modules/__init__.py +0 -0
  114. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/modules/archetype_module.py +0 -0
  115. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/modules/tool_module.py +0 -0
  116. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/modules/trigger_handler.py +0 -0
  117. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/modules/triggers/__init__.py +0 -0
  118. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/py.typed +0 -0
  119. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/__init__.py +0 -0
  120. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/agent/__init__.py +0 -0
  121. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/agent/agent_strategy.py +0 -0
  122. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/agent/default_agent.py +0 -0
  123. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/base_strategy.py +0 -0
  124. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/communication/__init__.py +0 -0
  125. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/communication/communication_strategy.py +0 -0
  126. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/communication/default_communication.py +0 -0
  127. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/communication/grpc_communication.py +0 -0
  128. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/cost/__init__.py +0 -0
  129. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/cost/cost_strategy.py +0 -0
  130. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/cost/default_cost.py +0 -0
  131. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/cost/grpc_cost.py +0 -0
  132. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/filesystem/__init__.py +0 -0
  133. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/filesystem/default_filesystem.py +0 -0
  134. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/filesystem/filesystem_strategy.py +0 -0
  135. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/filesystem/grpc_filesystem.py +0 -0
  136. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/identity/__init__.py +0 -0
  137. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/identity/default_identity.py +0 -0
  138. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/identity/identity_strategy.py +0 -0
  139. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/registry/__init__.py +0 -0
  140. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/registry/default_registry.py +0 -0
  141. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/registry/exceptions.py +0 -0
  142. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/registry/grpc_registry.py +0 -0
  143. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/registry/registry_models.py +0 -0
  144. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/services_config.py +0 -0
  145. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/services_models.py +0 -0
  146. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/setup/__init__.py +0 -0
  147. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/setup/default_setup.py +0 -0
  148. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/setup/grpc_setup.py +0 -0
  149. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/setup/setup_strategy.py +0 -0
  150. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/snapshot/__init__.py +0 -0
  151. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/snapshot/default_snapshot.py +0 -0
  152. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/snapshot/snapshot_strategy.py +0 -0
  153. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/storage/__init__.py +0 -0
  154. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/storage/default_storage.py +0 -0
  155. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/storage/grpc_storage.py +0 -0
  156. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/storage/storage_strategy.py +0 -0
  157. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/task_manager/__init__.py +0 -0
  158. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/task_manager/default_task_manager.py +0 -0
  159. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/task_manager/grpc_task_manager.py +0 -0
  160. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/task_manager/task_manager_strategy.py +0 -0
  161. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/user_profile/__init__.py +0 -0
  162. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/user_profile/default_user_profile.py +0 -0
  163. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/user_profile/grpc_user_profile.py +0 -0
  164. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/services/user_profile/user_profile_strategy.py +0 -0
  165. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/utils/__init__.py +0 -0
  166. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/utils/arg_parser.py +0 -0
  167. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/utils/development_mode_action.py +0 -0
  168. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/utils/dynamic_schema.py +0 -0
  169. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/utils/llm_ready_schema.py +0 -0
  170. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/utils/package_discover.py +0 -0
  171. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/utils/proto_utils.py +0 -0
  172. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin/utils/schema_splitter.py +0 -0
  173. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/src/digitalkin.egg-info/dependency_links.txt +0 -0
  174. {digitalkin-0.3.5.dev12 → digitalkin-0.4.0.dev1}/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: 0.3.5.dev12
3
+ Version: 0.4.0.dev1
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
@@ -454,7 +454,7 @@ Description-Content-Type: text/markdown
454
454
  License-File: LICENSE
455
455
  Requires-Dist: ag-ui-protocol>=0.1.14
456
456
  Requires-Dist: agentic-mesh-protocol==0.2.3
457
- Requires-Dist: anyio==4.12.1
457
+ Requires-Dist: anyio==4.13.0
458
458
  Requires-Dist: grpcio-health-checking==1.78.0
459
459
  Requires-Dist: grpcio-reflection==1.78.0
460
460
  Requires-Dist: grpcio-status==1.78.0
@@ -463,7 +463,7 @@ Provides-Extra: profiling
463
463
  Requires-Dist: asyncio-inspector==0.1.0; extra == "profiling"
464
464
  Requires-Dist: pyinstrument==5.1.2; extra == "profiling"
465
465
  Requires-Dist: viztracer==1.1.1; extra == "profiling"
466
- Requires-Dist: yappi==1.7.3; extra == "profiling"
466
+ Requires-Dist: yappi==1.7.6; extra == "profiling"
467
467
  Provides-Extra: taskiq
468
468
  Requires-Dist: rstream==1.0.0; extra == "taskiq"
469
469
  Requires-Dist: taskiq-aio-pika==0.6.0; extra == "taskiq"
@@ -5,10 +5,11 @@ from typing import Any, ClassVar, Literal
5
5
 
6
6
  from pydantic import BaseModel, Field
7
7
 
8
- from digitalkin.models.grpc_servers.models import ClientConfig, SecurityMode, ServerMode
8
+ from digitalkin.models.grpc_servers.models import ClientConfig
9
9
  from digitalkin.models.module.module_context import ModuleContext
10
10
  from digitalkin.models.module.setup_types import SetupModel
11
11
  from digitalkin.models.module.tool_reference import ToolReference
12
+ from digitalkin.models.settings.utils.channel import ControlFlow, SecurityMode
12
13
  from digitalkin.modules._base_module import BaseModule # noqa: PLC2701
13
14
  from digitalkin.services.services_models import ServicesStrategy
14
15
 
@@ -98,7 +99,7 @@ class ArchetypeSecret(BaseModel):
98
99
  client_config = ClientConfig(
99
100
  host="[::]",
100
101
  port=50152,
101
- mode=ServerMode.ASYNC,
102
+ mode=ControlFlow.ASYNC,
102
103
  security=SecurityMode.INSECURE,
103
104
  credentials=None,
104
105
  )
@@ -29,20 +29,20 @@
29
29
  dependencies = [
30
30
  "ag-ui-protocol>=0.1.14",
31
31
  "agentic-mesh-protocol==0.2.3",
32
- "anyio==4.12.1",
32
+ "anyio==4.13.0",
33
33
  "grpcio-health-checking==1.78.0",
34
34
  "grpcio-reflection==1.78.0",
35
35
  "grpcio-status==1.78.0",
36
36
  "pydantic==2.12.5",
37
- ]
38
- version = "0.3.5.dev12"
37
+ ]
38
+ version = "0.4.0.dev1"
39
39
 
40
40
  [project.optional-dependencies]
41
41
  profiling = [
42
42
  "asyncio-inspector==0.1.0",
43
43
  "pyinstrument==5.1.2",
44
44
  "viztracer==1.1.1",
45
- "yappi==1.7.3",
45
+ "yappi==1.7.6",
46
46
  ]
47
47
  taskiq = [
48
48
  "rstream==1.0.0",
@@ -61,13 +61,13 @@
61
61
 
62
62
  [dependency-groups]
63
63
  dev = [
64
- "build==1.4.0",
64
+ "build==1.4.2",
65
65
  "bump-my-version==1.2.7",
66
- "cryptography==46.0.5",
66
+ "cryptography==46.0.6",
67
67
  "mypy==1.19.1",
68
68
  "pre-commit==4.5.1",
69
69
  "pyright==1.1.408",
70
- "ruff==0.15.5",
70
+ "ruff==0.15.8",
71
71
  "twine==6.2.0",
72
72
  "types-grpcio-health-checking==1.0.0.20250506",
73
73
  "types-grpcio-reflection==1.0.0.20250506",
@@ -87,17 +87,17 @@
87
87
  "mkdocs-git-revision-date-localized-plugin==1.5.1",
88
88
  "mkdocs-glightbox==0.5.2",
89
89
  "mkdocs-include-markdown-plugin==7.2.1",
90
- "mkdocs-literate-nav==0.6.2",
90
+ "mkdocs-literate-nav==0.6.3",
91
91
  "mkdocs-llmstxt==0.5.0",
92
- "mkdocs-material[imaging]==9.7.5",
92
+ "mkdocs-material[imaging]==9.7.6",
93
93
  "mkdocs-minify-plugin==0.8.0",
94
94
  "mkdocs-open-in-new-tab==1.0.8",
95
95
  "mkdocs-redirects==1.2.2",
96
- "mkdocs-section-index==0.3.10",
96
+ "mkdocs-section-index==0.3.11",
97
97
  "mkdocs==1.6.1",
98
98
  "mkdocstrings-python==2.0.3",
99
99
  "mkdocstrings==1.0.3",
100
- "tomli==2.4.0",
100
+ "tomli==2.4.1",
101
101
  ]
102
102
  tests = [
103
103
  "freezegun==1.5.5",
@@ -105,7 +105,7 @@
105
105
  "hdrhistogram==0.10.3",
106
106
  "psutil==7.2.2",
107
107
  "pytest-asyncio==1.3.0",
108
- "pytest-cov==7.0.0",
108
+ "pytest-cov==7.1.0",
109
109
  "pytest-html==4.2.0",
110
110
  "pytest-json-report==1.5.0",
111
111
  "pytest-timeout==2.4.0",
@@ -5,4 +5,4 @@ from importlib.metadata import PackageNotFoundError, version
5
5
  try:
6
6
  __version__ = version("digitalkin")
7
7
  except PackageNotFoundError:
8
- __version__ = "0.3.5.dev12"
8
+ __version__ = "0.4.0.dev1"
@@ -0,0 +1,548 @@
1
+ """Adapter to convert Agno events to DigitalKin framework-agnostic events.
2
+
3
+ This adapter bridges Agno-specific events to the DigitalKin event model,
4
+ allowing the core DigitalKin SDK to remain independent of Agno.
5
+
6
+ The adapter owns ALL state management: tracking reasoning/content lifecycle,
7
+ generating message_id and reasoning_id on each phase start, and emitting
8
+ proper start/completed events for text message and reasoning sequences.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import logging
14
+ import uuid
15
+ from typing import TYPE_CHECKING, Any
16
+
17
+ if TYPE_CHECKING:
18
+ from collections.abc import Callable
19
+
20
+ from digitalkin.models.events import (
21
+ AgentRunEvent,
22
+ BaseAgentRunEvent,
23
+ ReasoningCompletedEvent,
24
+ ReasoningContentDeltaEvent,
25
+ ReasoningStartedEvent,
26
+ ReasoningStepEvent,
27
+ RunCompletedEvent,
28
+ RunContentEvent,
29
+ RunErrorEvent,
30
+ RunStartedEvent,
31
+ TextMessageCompletedEvent,
32
+ TextMessageStartedEvent,
33
+ ToolCallCompletedEvent,
34
+ ToolCallErrorEvent,
35
+ ToolCallStartedEvent,
36
+ ToolInfo,
37
+ )
38
+
39
+ logger = logging.getLogger(__name__)
40
+
41
+
42
+ class AgnoStreamAdapter:
43
+ """Stateful converter: Agno streaming events -> DigitalKin events.
44
+
45
+ Tracks reasoning and content state so that events arriving on
46
+ ``RunEvent.run_content`` are automatically wrapped in proper
47
+ lifecycle events (TextMessageStarted/Completed, ReasoningStarted/Completed).
48
+
49
+ Usage::
50
+
51
+ adapter = AgnoStreamAdapter()
52
+ async for raw_event in agent.arun(..., stream=True, stream_events=True):
53
+ for event in adapter.to_digitalkin_events(raw_event):
54
+ await send(event)
55
+ for event in adapter.flush():
56
+ await send(event)
57
+ """
58
+
59
+ def __init__(self) -> None:
60
+ """Initialize the AgnoStreamAdapter."""
61
+ self._reasoning_active: bool = False
62
+ self._current_reasoning_id: str | None = None
63
+
64
+ self._content_active: bool = False
65
+ self._current_message_id: str | None = None
66
+
67
+ self._closed_tool_call_ids: set[str] = set()
68
+
69
+ self._active_run_id: str | None = None
70
+ self._completed_run_ids: set[str] = set()
71
+
72
+ self._dispatch: dict[Any, Callable[[Any, Any], list[BaseAgentRunEvent]]] | None = None
73
+
74
+ def to_digitalkin_events(self, agno_event: Any) -> list[BaseAgentRunEvent]:
75
+ """Convert one Agno event into one or more DigitalKin events.
76
+
77
+ Args:
78
+ agno_event: Event from Agno's streaming API.
79
+
80
+ Returns:
81
+ List of corresponding DigitalKin events (may be empty).
82
+
83
+ Raises:
84
+ ImportError: If the optional 'agno' dependency is not installed.
85
+ """
86
+ if self._dispatch is None:
87
+ try:
88
+ from agno.run.agent import RunEvent # pylint: disable=C0415 # pyright: ignore[reportMissingImports]
89
+ except ImportError as exc:
90
+ message = "The 'agno' package is required to use AgnoStreamAdapter. Install it with: pip install agno"
91
+ raise ImportError(message) from exc
92
+
93
+ self._dispatch = {
94
+ RunEvent.run_started: self._handle_run_started,
95
+ RunEvent.run_content: self._handle_run_content,
96
+ RunEvent.run_completed: self._handle_run_completed,
97
+ RunEvent.run_error: self._handle_run_error,
98
+ RunEvent.reasoning_started: self._handle_reasoning_started,
99
+ RunEvent.reasoning_content_delta: self._handle_reasoning_content_delta,
100
+ RunEvent.reasoning_step: self._handle_reasoning_step,
101
+ RunEvent.reasoning_completed: self._handle_reasoning_completed,
102
+ RunEvent.tool_call_started: self._handle_tool_call_started,
103
+ RunEvent.tool_call_completed: self._handle_tool_call_completed,
104
+ RunEvent.tool_call_error: self._handle_tool_call_error,
105
+ }
106
+
107
+ event_type = agno_event.event
108
+ logger.debug("Converting Agno event: %s", event_type)
109
+
110
+ handler = self._dispatch.get(event_type)
111
+ if handler is None:
112
+ logger.debug("Skipping unhandled Agno event type: %s", event_type)
113
+ return []
114
+
115
+ return handler(agno_event, getattr(agno_event, "timestamp", None))
116
+
117
+ # ── Run Lifecycle Handlers ───────────────────────────────────────────
118
+
119
+ def _handle_run_started(self, agno_event: Any, timestamp: Any) -> list[BaseAgentRunEvent]:
120
+ """Handle RunEvent.run_started.
121
+
122
+ Returns:
123
+ List containing a RunStartedEvent, or empty for duplicates.
124
+ """
125
+ run_id = getattr(agno_event, "run_id", None)
126
+
127
+ if run_id and run_id == self._active_run_id:
128
+ logger.debug("Skipping duplicate RunStarted for run_id=%s", run_id)
129
+ return []
130
+
131
+ self._active_run_id = run_id
132
+ return [
133
+ RunStartedEvent(
134
+ event=AgentRunEvent.RUN_STARTED,
135
+ run_id=run_id,
136
+ thread_id=getattr(agno_event, "thread_id", None),
137
+ timestamp=timestamp,
138
+ metadata=None,
139
+ )
140
+ ]
141
+
142
+ def _handle_run_completed(self, agno_event: Any, timestamp: Any) -> list[BaseAgentRunEvent]:
143
+ """Handle RunEvent.run_completed.
144
+
145
+ Returns:
146
+ List of closing events followed by a RunCompletedEvent.
147
+ """
148
+ run_id = getattr(agno_event, "run_id", None)
149
+
150
+ if run_id and run_id in self._completed_run_ids and run_id != self._active_run_id:
151
+ logger.debug("Skipping duplicate RunCompleted for run_id=%s", run_id)
152
+ return []
153
+
154
+ events: list[BaseAgentRunEvent] = []
155
+
156
+ if self._content_active:
157
+ events.extend(self._close_content(timestamp))
158
+ if self._reasoning_active:
159
+ events.extend(self._close_reasoning(timestamp))
160
+
161
+ if run_id:
162
+ self._completed_run_ids.add(run_id)
163
+ self._active_run_id = None
164
+
165
+ events.append(
166
+ RunCompletedEvent(
167
+ event=AgentRunEvent.RUN_COMPLETED,
168
+ run_id=run_id,
169
+ final_content=str(agno_event.content) if getattr(agno_event, "content", None) else None,
170
+ usage=None,
171
+ message_id=None,
172
+ timestamp=timestamp,
173
+ metadata=None,
174
+ )
175
+ )
176
+ return events
177
+
178
+ def _handle_run_error( # noqa: PLR6301
179
+ self,
180
+ agno_event: Any,
181
+ timestamp: Any,
182
+ ) -> list[BaseAgentRunEvent]:
183
+ """Handle RunEvent.run_error.
184
+
185
+ Returns:
186
+ List containing a RunErrorEvent.
187
+ """
188
+ return [
189
+ RunErrorEvent(
190
+ event=AgentRunEvent.RUN_ERROR,
191
+ error_type=getattr(agno_event, "error_type", None),
192
+ content=str(agno_event.content) if getattr(agno_event, "content", None) else None,
193
+ error_details=None,
194
+ timestamp=timestamp,
195
+ metadata=None,
196
+ )
197
+ ]
198
+
199
+ # ── Reasoning Handlers (native Agno reasoning models) ───────────────
200
+
201
+ def _handle_reasoning_started(self, agno_event: Any, timestamp: Any) -> list[BaseAgentRunEvent]:
202
+ """Handle RunEvent.reasoning_started.
203
+
204
+ Returns:
205
+ List with an optional TextMessageCompletedEvent and a ReasoningStartedEvent.
206
+ """
207
+ _ = agno_event
208
+ events: list[BaseAgentRunEvent] = []
209
+
210
+ if self._content_active:
211
+ events.extend(self._close_content(timestamp))
212
+
213
+ self._current_reasoning_id = str(uuid.uuid4())
214
+ self._reasoning_active = True
215
+ logger.debug("Reasoning started, id=%s", self._current_reasoning_id)
216
+ events.append(
217
+ ReasoningStartedEvent(
218
+ event=AgentRunEvent.REASONING_STARTED,
219
+ reasoning_id=self._current_reasoning_id,
220
+ timestamp=timestamp,
221
+ metadata=None,
222
+ )
223
+ )
224
+ return events
225
+
226
+ def _handle_reasoning_content_delta(self, agno_event: Any, timestamp: Any) -> list[BaseAgentRunEvent]:
227
+ """Handle RunEvent.reasoning_content_delta.
228
+
229
+ Returns:
230
+ List containing a ReasoningContentDeltaEvent.
231
+ """
232
+ return [
233
+ ReasoningContentDeltaEvent(
234
+ event=AgentRunEvent.REASONING_CONTENT_DELTA,
235
+ delta=getattr(agno_event, "reasoning_content", ""),
236
+ reasoning_id=self._current_reasoning_id,
237
+ timestamp=timestamp,
238
+ metadata=None,
239
+ )
240
+ ]
241
+
242
+ def _handle_reasoning_step(self, agno_event: Any, timestamp: Any) -> list[BaseAgentRunEvent]:
243
+ """Handle RunEvent.reasoning_step.
244
+
245
+ Returns:
246
+ List containing a ReasoningStepEvent.
247
+ """
248
+ return [
249
+ ReasoningStepEvent(
250
+ event=AgentRunEvent.REASONING_STEP,
251
+ delta=getattr(agno_event, "reasoning_content", ""),
252
+ reasoning_id=self._current_reasoning_id,
253
+ timestamp=timestamp,
254
+ metadata=None,
255
+ )
256
+ ]
257
+
258
+ def _handle_reasoning_completed(self, agno_event: Any, timestamp: Any) -> list[BaseAgentRunEvent]:
259
+ """Handle RunEvent.reasoning_completed.
260
+
261
+ Returns:
262
+ List containing a ReasoningCompletedEvent if reasoning was active.
263
+ """
264
+ _ = agno_event
265
+ logger.debug("Reasoning completed")
266
+ return self._close_reasoning(timestamp)
267
+
268
+ # ── Tool Call Handlers ──────────────────────────────────────────────
269
+
270
+ def _handle_tool_call_started(self, agno_event: Any, timestamp: Any) -> list[BaseAgentRunEvent]:
271
+ """Handle RunEvent.tool_call_started.
272
+
273
+ Returns:
274
+ List of any needed closing events and a ToolCallStartedEvent.
275
+ """
276
+ events: list[BaseAgentRunEvent] = []
277
+
278
+ if self._reasoning_active:
279
+ logger.debug("Reasoning auto-completed (tool call started)")
280
+ events.extend(self._close_reasoning(timestamp))
281
+ if self._content_active:
282
+ events.extend(self._close_content(timestamp))
283
+
284
+ tool = getattr(agno_event, "tool", None)
285
+ tool_info = None
286
+ if tool:
287
+ tool_info = ToolInfo(
288
+ tool_call_id=getattr(tool, "tool_call_id", None),
289
+ tool_name=getattr(tool, "tool_name", None),
290
+ tool_args=getattr(tool, "tool_args", None),
291
+ result=None,
292
+ )
293
+ events.append(
294
+ ToolCallStartedEvent(
295
+ event=AgentRunEvent.TOOL_CALL_STARTED,
296
+ tool=tool_info,
297
+ timestamp=timestamp,
298
+ metadata=None,
299
+ )
300
+ )
301
+ return events
302
+
303
+ def _handle_tool_call_completed(self, agno_event: Any, timestamp: Any) -> list[BaseAgentRunEvent]:
304
+ """Handle RunEvent.tool_call_completed.
305
+
306
+ Returns:
307
+ List containing a ToolCallCompletedEvent.
308
+ """
309
+ tool = getattr(agno_event, "tool", None)
310
+ tool_info = None
311
+ tool_call_id = None
312
+ if tool:
313
+ tool_call_id = getattr(tool, "tool_call_id", None)
314
+ tool_info = ToolInfo(
315
+ tool_call_id=tool_call_id,
316
+ tool_name=getattr(tool, "tool_name", None),
317
+ tool_args=getattr(tool, "tool_args", None),
318
+ result=getattr(tool, "result", None),
319
+ )
320
+
321
+ if tool_call_id:
322
+ self._closed_tool_call_ids.add(tool_call_id)
323
+
324
+ return [
325
+ ToolCallCompletedEvent(
326
+ event=AgentRunEvent.TOOL_CALL_COMPLETED,
327
+ tool=tool_info,
328
+ content=str(agno_event.content) if getattr(agno_event, "content", None) else None,
329
+ timestamp=timestamp,
330
+ metadata=None,
331
+ )
332
+ ]
333
+
334
+ def _handle_tool_call_error(self, agno_event: Any, timestamp: Any) -> list[BaseAgentRunEvent]:
335
+ """Handle RunEvent.tool_call_error.
336
+
337
+ Returns:
338
+ List containing a ToolCallErrorEvent, or empty if already closed.
339
+ """
340
+ tool = getattr(agno_event, "tool", None)
341
+ tool_call_id = getattr(tool, "tool_call_id", None) if tool else None
342
+
343
+ if tool_call_id and tool_call_id in self._closed_tool_call_ids:
344
+ logger.debug("Skipping duplicate ToolCallError for tool %s", tool_call_id)
345
+ return []
346
+
347
+ tool_info = None
348
+ if tool:
349
+ tool_info = ToolInfo(
350
+ tool_call_id=tool_call_id,
351
+ tool_name=getattr(tool, "tool_name", None),
352
+ tool_args=None,
353
+ result=None,
354
+ )
355
+
356
+ if tool_call_id:
357
+ self._closed_tool_call_ids.add(tool_call_id)
358
+
359
+ return [
360
+ ToolCallErrorEvent(
361
+ event=AgentRunEvent.TOOL_CALL_ERROR,
362
+ tool=tool_info,
363
+ error_message=str(agno_event.content) if getattr(agno_event, "content", None) else None,
364
+ timestamp=timestamp,
365
+ metadata=None,
366
+ )
367
+ ]
368
+
369
+ def flush(self) -> list[BaseAgentRunEvent]:
370
+ """Emit closing events for any active sequences at end of stream.
371
+
372
+ Returns:
373
+ List of closing events (empty if nothing is active).
374
+ """
375
+ events: list[BaseAgentRunEvent] = []
376
+ if self._content_active:
377
+ logger.debug("Flushing active content sequence")
378
+ events.extend(self._close_content(None))
379
+ if self._reasoning_active:
380
+ logger.debug("Flushing active reasoning sequence")
381
+ events.extend(self._close_reasoning(None))
382
+ return events
383
+
384
+ # ── Private Helpers ──────────────────────────────────────────────────
385
+
386
+ def _close_reasoning(self, timestamp: Any) -> list[BaseAgentRunEvent]:
387
+ """Close active reasoning sequence.
388
+
389
+ Returns:
390
+ List of closing events (empty if reasoning is not active).
391
+ """
392
+ if not self._reasoning_active:
393
+ return []
394
+
395
+ events: list[BaseAgentRunEvent] = [
396
+ ReasoningCompletedEvent(
397
+ event=AgentRunEvent.REASONING_COMPLETED,
398
+ reasoning_id=self._current_reasoning_id,
399
+ timestamp=timestamp,
400
+ metadata=None,
401
+ )
402
+ ]
403
+ self._reasoning_active = False
404
+ self._current_reasoning_id = None
405
+ return events
406
+
407
+ def _close_content(self, timestamp: Any) -> list[BaseAgentRunEvent]:
408
+ """Close active text message sequence.
409
+
410
+ Returns:
411
+ List of closing events (empty if content is not active).
412
+ """
413
+ if not self._content_active:
414
+ return []
415
+
416
+ events: list[BaseAgentRunEvent] = [
417
+ TextMessageCompletedEvent(
418
+ event=AgentRunEvent.TEXT_MESSAGE_COMPLETED,
419
+ message_id=self._current_message_id or "",
420
+ timestamp=timestamp,
421
+ metadata=None,
422
+ )
423
+ ]
424
+ self._content_active = False
425
+ self._current_message_id = None
426
+ return events
427
+
428
+ def _handle_run_content(self, agno_event: Any, timestamp: Any) -> list[BaseAgentRunEvent]:
429
+ """Handle RunEvent.run_content — the core state machine.
430
+
431
+ Rules:
432
+ - reasoning_content non-empty: reasoning data (close content if transitioning)
433
+ - content non-empty: text data (close reasoning if transitioning)
434
+ - reasoning_content == "": close reasoning if active
435
+ - content == "": close content if active
436
+ - None values: ignored
437
+
438
+ Returns:
439
+ List of DigitalKin events for this run_content chunk.
440
+ """
441
+ events: list[BaseAgentRunEvent] = []
442
+
443
+ reasoning_content = getattr(agno_event, "reasoning_content", None)
444
+ content = agno_event.content
445
+
446
+ # ── Reasoning content handling ──
447
+ if reasoning_content is not None:
448
+ events.extend(self._process_reasoning_content(reasoning_content, timestamp))
449
+
450
+ # ── Text content handling ──
451
+ if content is not None:
452
+ events.extend(self._process_text_content(content, timestamp))
453
+
454
+ # Edge case: neither reasoning_content nor content
455
+ if reasoning_content is None and content is None:
456
+ logger.debug("run_content with no content, skipping")
457
+
458
+ return events
459
+
460
+ def _process_reasoning_content(self, reasoning_content: str, timestamp: Any) -> list[BaseAgentRunEvent]:
461
+ """Process reasoning_content from a run_content event.
462
+
463
+ Returns:
464
+ List of reasoning lifecycle and content events.
465
+ """
466
+ events: list[BaseAgentRunEvent] = []
467
+
468
+ if not reasoning_content:
469
+ # Empty string "" → signal to close reasoning
470
+ if self._reasoning_active:
471
+ events.extend(self._close_reasoning(timestamp))
472
+ return events
473
+
474
+ # Non-empty string → reasoning data
475
+ # Close text message if transitioning from content to reasoning
476
+ if self._content_active:
477
+ events.extend(self._close_content(timestamp))
478
+
479
+ # Auto-open reasoning on first chunk
480
+ if not self._reasoning_active:
481
+ self._current_reasoning_id = str(uuid.uuid4())
482
+ logger.debug("Reasoning auto-started, id=%s", self._current_reasoning_id)
483
+ events.append(
484
+ ReasoningStartedEvent(
485
+ event=AgentRunEvent.REASONING_STARTED,
486
+ reasoning_id=self._current_reasoning_id,
487
+ timestamp=timestamp,
488
+ metadata=None,
489
+ )
490
+ )
491
+ self._reasoning_active = True
492
+
493
+ events.append(
494
+ ReasoningContentDeltaEvent(
495
+ event=AgentRunEvent.REASONING_CONTENT_DELTA,
496
+ delta=reasoning_content,
497
+ reasoning_id=self._current_reasoning_id,
498
+ timestamp=timestamp,
499
+ metadata=None,
500
+ )
501
+ )
502
+ return events
503
+
504
+ def _process_text_content(self, content: str, timestamp: Any) -> list[BaseAgentRunEvent]:
505
+ """Process text content from a run_content event.
506
+
507
+ Returns:
508
+ List of text message lifecycle and content events.
509
+ """
510
+ events: list[BaseAgentRunEvent] = []
511
+
512
+ if not content:
513
+ # Empty string "" → signal to close text message
514
+ if self._content_active:
515
+ events.extend(self._close_content(timestamp))
516
+ return events
517
+
518
+ # Non-empty string → text data
519
+ # Close reasoning if transitioning from reasoning to content
520
+ if self._reasoning_active:
521
+ logger.debug("Reasoning auto-completed (text content arrived)")
522
+ events.extend(self._close_reasoning(timestamp))
523
+
524
+ # Auto-open text message on first chunk
525
+ if not self._content_active:
526
+ self._current_message_id = str(uuid.uuid4())
527
+ events.append(
528
+ TextMessageStartedEvent(
529
+ event=AgentRunEvent.TEXT_MESSAGE_STARTED,
530
+ message_id=self._current_message_id,
531
+ timestamp=timestamp,
532
+ metadata=None,
533
+ )
534
+ )
535
+ self._content_active = True
536
+
537
+ events.append(
538
+ RunContentEvent(
539
+ event=AgentRunEvent.RUN_CONTENT,
540
+ content=str(content),
541
+ message_id=self._current_message_id,
542
+ reasoning_content=None,
543
+ content_type=None,
544
+ timestamp=timestamp,
545
+ metadata=None,
546
+ )
547
+ )
548
+ return events
@@ -130,6 +130,12 @@ class BaseJobManager(abc.ABC, Generic[InputModelT, OutputModelT, SetupModelT]):
130
130
  required for the job manager to function.
131
131
  """
132
132
 
133
+ async def stop(self) -> None:
134
+ """Stop the job manager and clean up resources.
135
+
136
+ Default no-op. Subclasses with external connections override.
137
+ """
138
+
133
139
  @staticmethod
134
140
  async def job_specific_callback(
135
141
  callback: Callable[[str, DataModel | ModuleCodeModel], Coroutine[Any, Any, None]],