digitalkin 1.0.5.dev0__tar.gz → 1.0.5.dev2__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 (276) hide show
  1. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/PKG-INFO +2 -2
  2. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/redis_demo/client.py +155 -52
  3. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/pyproject.toml +2 -2
  4. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/__version__.py +1 -1
  5. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/agno_adapter.py +102 -4
  6. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/hitl.py +16 -1
  7. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/models.py +1 -36
  8. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/module_toolkit.py +76 -70
  9. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/toolkits/base.py +17 -0
  10. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/toolkits/chat_history.py +64 -29
  11. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/toolkits/registry/action.py +17 -57
  12. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/toolkits/registry/base.py +10 -37
  13. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/toolkits/registry/loader/action.py +1 -1
  14. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/toolkits/registry/loader/kit.py +1 -1
  15. digitalkin-1.0.5.dev2/src/digitalkin/community/agno/toolkits/registry/services/action.py +92 -0
  16. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/toolkits/registry/services/kit.py +5 -11
  17. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/job_manager/single_job_manager.py +38 -17
  18. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/profiling/task_profiler.py +3 -3
  19. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/resilience/bulkhead.py +6 -5
  20. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/task_manager/base_task_manager.py +48 -32
  21. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/task_manager/local_task_manager.py +4 -6
  22. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/task_manager/module_runner.py +100 -16
  23. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/task_manager/redis/__init__.py +1 -3
  24. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/task_manager/redis/proto_streams.py +2 -2
  25. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/task_manager/redis/redis_client.py +12 -1
  26. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/task_manager/redis/redis_idempotency.py +5 -6
  27. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/task_manager/redis/redis_signal.py +24 -17
  28. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/task_manager/remote_task_manager.py +1 -1
  29. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/task_manager/task_executor.py +58 -37
  30. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/task_manager/task_session.py +21 -118
  31. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/grpc_servers/_base_server.py +15 -15
  32. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/grpc_servers/gateway_servicer.py +173 -139
  33. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/grpc_servers/interceptors/permission.py +9 -9
  34. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/grpc_servers/interceptors/request_ids.py +1 -1
  35. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/grpc_servers/m2m_call_registry.py +5 -5
  36. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/grpc_servers/module_server.py +81 -80
  37. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/grpc_servers/module_servicer.py +156 -153
  38. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/grpc_servers/stream_registry.py +3 -19
  39. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/grpc_servers/stream_session.py +3 -5
  40. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/grpc_servers/utils/circuit_breaker.py +3 -3
  41. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/grpc_servers/utils/grpc_client_wrapper.py +61 -36
  42. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/grpc_servers/utils/grpc_error_handler.py +2 -44
  43. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/grpc_servers/utils/utility_schema_extender.py +4 -2
  44. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/grpc_servers/utils/validators.py +1 -1
  45. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/logger.py +1 -1
  46. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/mixins/agui_mixin.py +7 -6
  47. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/core/task_monitor.py +1 -5
  48. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/events/__init__.py +4 -0
  49. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/events/agent_events.py +17 -2
  50. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/grpc_servers/models.py +39 -30
  51. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/module/__init__.py +2 -0
  52. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/module/module_context.py +11 -3
  53. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/module/setup_types.py +1 -1
  54. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/module/tool_cache.py +0 -1
  55. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/module/tool_reference.py +2 -2
  56. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/module/utility.py +7 -0
  57. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/services/registry.py +13 -20
  58. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/settings/gateway.py +5 -4
  59. digitalkin-1.0.5.dev2/src/digitalkin/models/settings/grpc_client.py +127 -0
  60. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/settings/module.py +2 -17
  61. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/settings/profiling.py +1 -1
  62. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/settings/redis.py +1 -6
  63. digitalkin-1.0.5.dev2/src/digitalkin/models/settings/resilience.py +31 -0
  64. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/settings/server/channel.py +3 -23
  65. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/settings/server/grpc.py +1 -1
  66. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/settings/server/server.py +2 -6
  67. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/settings/server/servicer.py +1 -2
  68. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/settings/task_manager.py +0 -1
  69. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/settings/utils/channel.py +8 -46
  70. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/modules/_base_module.py +33 -18
  71. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/modules/trigger_handler.py +1 -1
  72. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/modules/triggers/healthcheck_ping_trigger.py +2 -2
  73. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/modules/triggers/healthcheck_services_trigger.py +3 -3
  74. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/modules/triggers/healthcheck_status_trigger.py +2 -2
  75. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/communication/communication_strategy.py +2 -7
  76. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/communication/default_communication.py +11 -12
  77. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/communication/exceptions.py +2 -6
  78. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/communication/grpc_communication.py +88 -69
  79. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/cost/cost_strategy.py +1 -1
  80. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/cost/default_cost.py +24 -17
  81. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/cost/grpc_cost.py +66 -97
  82. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/filesystem/default_filesystem.py +13 -13
  83. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/filesystem/filesystem_strategy.py +2 -2
  84. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/filesystem/grpc_filesystem.py +93 -121
  85. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/identity/default_identity.py +1 -1
  86. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/registry/__init__.py +2 -0
  87. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/registry/default_registry.py +24 -5
  88. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/registry/grpc_registry.py +126 -103
  89. digitalkin-1.0.5.dev2/src/digitalkin/services/registry/registry_models.py +15 -0
  90. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/registry/registry_strategy.py +8 -2
  91. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/secret/grpc_secret.py +10 -10
  92. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/services_config.py +14 -18
  93. digitalkin-1.0.5.dev2/src/digitalkin/services/setup/default_setup.py +239 -0
  94. digitalkin-1.0.5.dev2/src/digitalkin/services/setup/grpc_setup.py +358 -0
  95. digitalkin-1.0.5.dev2/src/digitalkin/services/setup/setup_strategy.py +155 -0
  96. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/storage/default_storage.py +6 -3
  97. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/storage/grpc_storage.py +70 -105
  98. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/storage/storage_strategy.py +23 -28
  99. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/task_manager/default_task_manager.py +4 -4
  100. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/user_profile/default_user_profile.py +3 -9
  101. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/user_profile/grpc_user_profile.py +12 -18
  102. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/user_profile/user_profile_strategy.py +3 -7
  103. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/utils/arg_parser.py +6 -6
  104. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/utils/development_mode_action.py +18 -10
  105. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/utils/llm_ready_schema.py +1 -1
  106. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/utils/package_discover.py +3 -3
  107. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/utils/schema_splitter.py +4 -4
  108. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/utils/setup_content_validator.py +0 -24
  109. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin.egg-info/PKG-INFO +2 -2
  110. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin.egg-info/SOURCES.txt +2 -11
  111. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin.egg-info/requires.txt +1 -1
  112. digitalkin-1.0.5.dev0/src/digitalkin/community/agno/toolkits/registry/services/action.py +0 -175
  113. digitalkin-1.0.5.dev0/src/digitalkin/core/task_manager/redis/redis_state.py +0 -124
  114. digitalkin-1.0.5.dev0/src/digitalkin/grpc_servers/interceptors/validation.py +0 -74
  115. digitalkin-1.0.5.dev0/src/digitalkin/models/settings/certificate.py +0 -90
  116. digitalkin-1.0.5.dev0/src/digitalkin/models/settings/client/__init__.py +0 -1
  117. digitalkin-1.0.5.dev0/src/digitalkin/models/settings/client/channel.py +0 -68
  118. digitalkin-1.0.5.dev0/src/digitalkin/models/settings/client/circuit_breaker.py +0 -19
  119. digitalkin-1.0.5.dev0/src/digitalkin/models/settings/client/client.py +0 -55
  120. digitalkin-1.0.5.dev0/src/digitalkin/models/settings/client/grpc.py +0 -148
  121. digitalkin-1.0.5.dev0/src/digitalkin/models/settings/resilience.py +0 -61
  122. digitalkin-1.0.5.dev0/src/digitalkin/services/setup/default_setup.py +0 -442
  123. digitalkin-1.0.5.dev0/src/digitalkin/services/setup/grpc_setup.py +0 -604
  124. digitalkin-1.0.5.dev0/src/digitalkin/services/setup/setup_strategy.py +0 -263
  125. digitalkin-1.0.5.dev0/src/digitalkin/utils/env_manager.py +0 -139
  126. digitalkin-1.0.5.dev0/src/digitalkin/utils/env_template.py +0 -233
  127. digitalkin-1.0.5.dev0/src/digitalkin/utils/json_structure.py +0 -169
  128. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/LICENSE +0 -0
  129. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/README.md +0 -0
  130. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/base_server/__init__.py +0 -0
  131. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/base_server/mock/__init__.py +0 -0
  132. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/base_server/mock/mock_pb2.py +0 -0
  133. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/base_server/mock/mock_pb2_grpc.py +0 -0
  134. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/base_server/server_async_insecure.py +0 -0
  135. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/base_server/server_async_secure.py +0 -0
  136. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/base_server/server_sync_insecure.py +0 -0
  137. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/base_server/server_sync_secure.py +0 -0
  138. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/bench_module/__init__.py +0 -0
  139. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/bench_module/echo_module.py +0 -0
  140. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/bench_module/models/__init__.py +0 -0
  141. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/bench_module/models/input.py +0 -0
  142. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/bench_module/models/output.py +0 -0
  143. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/bench_module/models/secret.py +0 -0
  144. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/bench_module/models/setup.py +0 -0
  145. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/bench_module/server.py +0 -0
  146. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/bench_module/triggers/__init__.py +0 -0
  147. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/bench_module/triggers/message_trigger.py +0 -0
  148. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/modules/__init__.py +0 -0
  149. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/modules/archetype_with_tools_module.py +0 -0
  150. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/modules/cpu_intensive_module.py +0 -0
  151. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/modules/dynamic_setup_module.py +0 -0
  152. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/modules/minimal_llm_module.py +0 -0
  153. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/modules/text_transform_module.py +0 -0
  154. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/monitoring/digitalkin_observability/__init__.py +0 -0
  155. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/monitoring/digitalkin_observability/http_server.py +0 -0
  156. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/monitoring/digitalkin_observability/interceptors.py +0 -0
  157. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/monitoring/digitalkin_observability/metrics.py +0 -0
  158. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/monitoring/digitalkin_observability/prometheus.py +0 -0
  159. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/monitoring/tests/test_metrics.py +0 -0
  160. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/redis_demo/echo_module.py +0 -0
  161. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/redis_demo/models/__init__.py +0 -0
  162. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/redis_demo/models/input.py +0 -0
  163. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/redis_demo/models/output.py +0 -0
  164. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/redis_demo/models/secret.py +0 -0
  165. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/redis_demo/models/setup.py +0 -0
  166. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/redis_demo/server.py +0 -0
  167. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/redis_demo/triggers/__init__.py +0 -0
  168. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/redis_demo/triggers/message_trigger.py +0 -0
  169. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/services/filesystem_module.py +0 -0
  170. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/examples/services/storage_module.py +0 -0
  171. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/setup.cfg +0 -0
  172. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/__init__.py +0 -0
  173. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/__init__.py +0 -0
  174. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/__init__.py +0 -0
  175. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/agui_tools.py +0 -0
  176. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/toolkits/__init__.py +0 -0
  177. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/toolkits/defaults.py +0 -0
  178. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/toolkits/registry/__init__.py +0 -0
  179. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/toolkits/registry/kins/__init__.py +0 -0
  180. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/toolkits/registry/kins/action.py +0 -0
  181. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/toolkits/registry/kins/kit.py +0 -0
  182. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/toolkits/registry/loader/__init__.py +0 -0
  183. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/toolkits/registry/services/__init__.py +0 -0
  184. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/toolkits/registry/tools/__init__.py +0 -0
  185. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/toolkits/registry/tools/action.py +0 -0
  186. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/toolkits/registry/tools/kit.py +0 -0
  187. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/community/agno/toolkits/user_profile.py +0 -0
  188. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/__init__.py +0 -0
  189. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/common/__init__.py +0 -0
  190. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/common/factories.py +0 -0
  191. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/exceptions.py +0 -0
  192. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/job_manager/__init__.py +0 -0
  193. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/job_manager/base_job_manager.py +0 -0
  194. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/profiling/__init__.py +0 -0
  195. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/profiling/step_timer.py +0 -0
  196. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/resilience/__init__.py +0 -0
  197. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/resilience/task_supervisor.py +0 -0
  198. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/core/task_manager/__init__.py +0 -0
  199. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/exceptions.py +0 -0
  200. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/grpc_servers/__init__.py +0 -0
  201. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/grpc_servers/exceptions.py +0 -0
  202. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/grpc_servers/interceptors/__init__.py +0 -0
  203. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/grpc_servers/utils/__init__.py +0 -0
  204. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/mixins/__init__.py +0 -0
  205. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/mixins/base_mixin.py +0 -0
  206. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/mixins/cost_mixin.py +0 -0
  207. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/mixins/file_history_mixin.py +0 -0
  208. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/mixins/filesystem_mixin.py +0 -0
  209. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/mixins/logger_mixin.py +0 -0
  210. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/mixins/storage_mixin.py +0 -0
  211. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/__init__.py +0 -0
  212. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/core/__init__.py +0 -0
  213. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/core/job_manager_models.py +0 -0
  214. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/core/redis.py +0 -0
  215. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/grpc_servers/__init__.py +0 -0
  216. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/grpc_servers/circuit_breaker.py +0 -0
  217. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/grpc_servers/m2m.py +0 -0
  218. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/grpc_servers/stream_error_codes.py +0 -0
  219. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/grpc_servers/types.py +0 -0
  220. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/module/ag_ui.py +0 -0
  221. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/module/base_types.py +0 -0
  222. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/module/loaded_tools.py +0 -0
  223. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/module/module.py +0 -0
  224. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/module/module_types.py +0 -0
  225. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/module/request_metadata.py +0 -0
  226. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/module/select_schema.py +0 -0
  227. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/services/__init__.py +0 -0
  228. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/services/cost.py +0 -0
  229. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/services/services.py +0 -0
  230. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/services/storage.py +0 -0
  231. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/settings/__init__.py +0 -0
  232. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/settings/log.py +0 -0
  233. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/settings/queue.py +0 -0
  234. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/settings/registry.py +0 -0
  235. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/settings/server/__init__.py +0 -0
  236. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/settings/utils/__init__.py +0 -0
  237. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/utils/__init__.py +0 -0
  238. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/models/utils/dynamic_schema.py +0 -0
  239. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/modules/__init__.py +0 -0
  240. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/modules/archetype_module.py +0 -0
  241. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/modules/tool_module.py +0 -0
  242. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/modules/triggers/__init__.py +0 -0
  243. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/py.typed +0 -0
  244. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/__init__.py +0 -0
  245. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/base_strategy.py +0 -0
  246. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/communication/__init__.py +0 -0
  247. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/cost/__init__.py +0 -0
  248. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/cost/exceptions.py +0 -0
  249. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/filesystem/__init__.py +0 -0
  250. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/filesystem/exceptions.py +0 -0
  251. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/identity/__init__.py +0 -0
  252. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/identity/identity_strategy.py +0 -0
  253. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/registry/exceptions.py +0 -0
  254. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/secret/__init__.py +0 -0
  255. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/secret/default_secret.py +0 -0
  256. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/secret/exceptions.py +0 -0
  257. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/secret/secret_strategy.py +0 -0
  258. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/services_models.py +0 -0
  259. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/setup/__init__.py +0 -0
  260. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/setup/exceptions.py +0 -0
  261. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/storage/__init__.py +0 -0
  262. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/storage/exceptions.py +0 -0
  263. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/task_manager/__init__.py +0 -0
  264. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/task_manager/exceptions.py +0 -0
  265. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/task_manager/redis_task_manager.py +0 -0
  266. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/task_manager/task_manager_strategy.py +0 -0
  267. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/user_profile/__init__.py +0 -0
  268. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/services/user_profile/exceptions.py +0 -0
  269. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/utils/__init__.py +0 -0
  270. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/utils/conditional_schema.py +0 -0
  271. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/utils/dynamic_schema.py +0 -0
  272. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/utils/exceptions.py +0 -0
  273. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin/utils/proto_utils.py +0 -0
  274. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin.egg-info/dependency_links.txt +0 -0
  275. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/src/digitalkin.egg-info/top_level.txt +0 -0
  276. {digitalkin-1.0.5.dev0 → digitalkin-1.0.5.dev2}/tests/test_exceptions.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: digitalkin
3
- Version: 1.0.5.dev0
3
+ Version: 1.0.5.dev2
4
4
  Summary: SDK to build kin used in DigitalKin
5
5
  Author-email: "DigitalKin.ai" <contact@digitalkin.ai>
6
6
  License: Attribution-NonCommercial-ShareAlike 4.0 International
@@ -453,7 +453,7 @@ Requires-Python: >=3.10
453
453
  Description-Content-Type: text/markdown
454
454
  License-File: LICENSE
455
455
  Requires-Dist: ag-ui-protocol==0.1.21.dev1787220377
456
- Requires-Dist: agentic-mesh-protocol==1.0.3.dev0
456
+ Requires-Dist: agentic-mesh-protocol==1.0.1
457
457
  Requires-Dist: agno<3,>=2.8.0
458
458
  Requires-Dist: anyio>=4.13.0
459
459
  Requires-Dist: grpcio-health-checking==1.82.1
@@ -2,10 +2,11 @@
2
2
  """Demo client for the Gateway gRPC service with per-endpoint testing.
3
3
 
4
4
  Subcommands:
5
- full Full pipeline: StartStream → Stream → SendSignal
5
+ full Full pipeline: StartStream → ConsumeStream → SendSignal
6
6
  start StartStream only (unary)
7
- consume Stream on existing task (requires --task-id)
8
- signal SendSignal(cancel) on existing task (requires --task-id)
7
+ consume ConsumeStream on existing task (requires --task-id)
8
+ produce StartStream + ProduceStream (act as Module A)
9
+ signal SendSignal on existing task (requires --task-id)
9
10
  inspect Dump Redis keys for a task (no gRPC)
10
11
 
11
12
  Usage:
@@ -13,7 +14,8 @@ Usage:
13
14
  python client.py full --prompt "Test" --setup '{"uppercase": true, "repeat": 5}'
14
15
  python client.py start --prompt "Hello"
15
16
  python client.py consume --task-id <uuid>
16
- python client.py signal --task-id <uuid>
17
+ python client.py produce --task-id <uuid> --chunks 3
18
+ python client.py signal --task-id <uuid> --action cancel
17
19
  python client.py inspect --task-id <uuid>
18
20
  """
19
21
 
@@ -32,7 +34,7 @@ import grpc
32
34
  import redis.asyncio as aioredis
33
35
  from google.protobuf import json_format, struct_pb2
34
36
 
35
- from agentic_mesh_protocol.gateway.v1 import gateway_dto_pb2, gateway_messages_pb2, gateway_service_pb2_grpc
37
+ from agentic_mesh_protocol.gateway.v1 import gateway_pb2, gateway_service_pb2_grpc
36
38
 
37
39
  # ── ANSI colors ─────────────────────────────────────────────────────
38
40
 
@@ -289,18 +291,29 @@ def _print_diff_report(tracker: RedisTracker, task_id: str) -> None:
289
291
  async def cmd_start(
290
292
  stub: gateway_service_pb2_grpc.GatewayServiceStub,
291
293
  task_id: str,
294
+ prompt: str,
295
+ setup: dict[str, Any] | None,
292
296
  ) -> bool:
293
297
  """StartStream — create a task session.
294
298
 
295
299
  Returns:
296
300
  True if accepted.
297
301
  """
302
+ input_struct = struct_pb2.Struct()
303
+ payload: dict[str, Any] = {
304
+ "root": {"protocol": "message", "text": prompt},
305
+ }
306
+ if setup:
307
+ payload["setup"] = setup
308
+ input_struct.update(payload)
309
+
298
310
  t0 = time.monotonic()
299
311
  resp = await stub.StartStream(
300
- gateway_dto_pb2.StartStreamRequest(
312
+ gateway_pb2.StartStreamRequest(
301
313
  task_id=task_id,
302
- setup_id="setups:demo",
303
- mission_id="missions:demo",
314
+ input=input_struct,
315
+ setup_id="demo-setup",
316
+ mission_id="demo-mission",
304
317
  ),
305
318
  )
306
319
  elapsed = (time.monotonic() - t0) * 1000
@@ -314,58 +327,112 @@ async def cmd_start(
314
327
  async def cmd_consume(
315
328
  stub: gateway_service_pb2_grpc.GatewayServiceStub,
316
329
  task_id: str,
317
- prompt: str,
318
- setup: dict[str, Any] | None,
319
330
  verbose: bool,
320
331
  ) -> list[dict[str, Any]]:
321
- """Stream — send the query, then read module output until ``stream.end``.
332
+ """ConsumeStream — read module output from Redis.
322
333
 
323
334
  Returns:
324
335
  List of received items.
325
336
  """
326
337
  received: list[dict[str, Any]] = []
327
- query: dict[str, Any] = {"root": {"protocol": "message", "text": prompt}}
328
- if setup:
329
- query["setup"] = setup
330
- query_struct = struct_pb2.Struct()
331
- query_struct.update(query)
332
338
 
333
339
  async def _requests() -> AsyncGenerator:
334
- yield gateway_messages_pb2.StreamRequest(task_id=task_id, from_seq=0, data=query_struct)
340
+ yield gateway_pb2.ConsumeStreamRequest(
341
+ init=gateway_pb2.ConsumeStreamInit(task_id=task_id, from_seq=0),
342
+ )
335
343
 
336
344
  t0 = time.monotonic()
337
- async for resp in stub.Stream(_requests()):
338
- root = json_format.MessageToDict(resp.data).get("root", {})
339
- protocol = root.get("protocol", "")
340
- if protocol == "stream.error":
341
- received.append({"seq": resp.seq, "error": root.get("message", "")})
342
- print(f" {RED}error: code={root.get('code')} msg={root.get('message')}{RESET}") # noqa: T201
343
- continue
344
- if protocol == "stream.end":
345
- received.append({"seq": resp.seq, "status": "stream.end"})
346
- print(f" {GREEN}stream.end{RESET} ({(time.monotonic() - t0) * 1000:.1f}ms total)") # noqa: T201
345
+ resp_stream = stub.ConsumeStream(_requests())
346
+ async for resp in resp_stream:
347
+ elapsed = (time.monotonic() - t0) * 1000
348
+ payload_type = resp.WhichOneof("payload")
349
+
350
+ if payload_type == "output":
351
+ data_dict = json_format.MessageToDict(resp.output.data)
352
+ text = data_dict.get("root", {}).get("text", data_dict.get("root", {}).get("protocol", ""))
353
+ received.append({"seq": resp.output.seq, "text": text})
354
+ print(f" {GREEN}seq={resp.output.seq:>2}{RESET} {text}") # noqa: T201
355
+ if verbose:
356
+ print(f" {DIM}{json.dumps(data_dict, ensure_ascii=False)}{RESET}") # noqa: T201
357
+
358
+ elif payload_type == "status":
359
+ state_name = gateway_pb2.StreamState.Name(resp.status.state)
360
+ received.append({"status": state_name})
361
+ color = GREEN if "COMPLETED" in state_name else YELLOW
362
+ print(f" {color}status: {state_name}{RESET} ({elapsed:.1f}ms total)") # noqa: T201
347
363
  break
348
- text = root.get("text", protocol)
349
- received.append({"seq": resp.seq, "text": text})
350
- print(f" {GREEN}seq={resp.seq:>2}{RESET} {text}") # noqa: T201
351
- if verbose:
352
- print(f" {DIM}{json.dumps(root, ensure_ascii=False)}{RESET}") # noqa: T201
364
+
365
+ elif payload_type == "error":
366
+ received.append({"error": resp.error.message})
367
+ print(f" {RED}error: code={resp.error.code} msg={resp.error.message}{RESET}") # noqa: T201
368
+ break
369
+
370
+ elif payload_type == "heartbeat":
371
+ if verbose:
372
+ print(f" {DIM}heartbeat{RESET}") # noqa: T201
353
373
 
354
374
  return received
355
375
 
356
376
 
377
+ async def cmd_produce(
378
+ stub: gateway_service_pb2_grpc.GatewayServiceStub,
379
+ task_id: str,
380
+ prompt: str,
381
+ num_chunks: int,
382
+ ) -> int:
383
+ """ProduceStream — act as Module A, push output chunks.
384
+
385
+ Returns:
386
+ Number of server responses.
387
+ """
388
+ async def _requests() -> AsyncGenerator:
389
+ yield gateway_pb2.ProduceStreamRequest(
390
+ init=gateway_pb2.ProduceStreamInit(task_id=task_id),
391
+ )
392
+ for i in range(num_chunks):
393
+ data = struct_pb2.Struct()
394
+ data.update({
395
+ "root": {
396
+ "protocol": "message",
397
+ "text": f"[{i + 1}/{num_chunks}] {prompt}",
398
+ },
399
+ })
400
+ yield gateway_pb2.ProduceStreamRequest(
401
+ output=gateway_pb2.ProduceStreamOutput(task_id=task_id, data=data),
402
+ )
403
+ await asyncio.sleep(0.05)
404
+
405
+ t0 = time.monotonic()
406
+ resp_stream = stub.ProduceStream(_requests())
407
+ count = 0
408
+ async for resp in resp_stream:
409
+ count += 1
410
+ payload = resp.WhichOneof("payload")
411
+ print(f" response #{count}: {payload}") # noqa: T201
412
+
413
+ elapsed = (time.monotonic() - t0) * 1000
414
+ print(f" {DIM}stream closed ({count} responses, {elapsed:.1f}ms){RESET}") # noqa: T201
415
+ return count
416
+
417
+
357
418
  async def cmd_signal(
358
419
  stub: gateway_service_pb2_grpc.GatewayServiceStub,
359
420
  task_id: str,
421
+ action: str,
360
422
  ) -> bool:
361
- """SendSignal — cancel a running task.
423
+ """SendSignal — send a control signal.
362
424
 
363
425
  Returns:
364
426
  True if accepted.
365
427
  """
428
+ action_enum = (
429
+ gateway_pb2.SIGNAL_ACTION_CANCEL if action == "cancel"
430
+ else gateway_pb2.SIGNAL_ACTION_PAUSE
431
+ )
432
+
366
433
  t0 = time.monotonic()
367
434
  resp = await stub.SendSignal(
368
- gateway_dto_pb2.SendSignalRequest(cancel=gateway_messages_pb2.CancelSignal(task_id=task_id)),
435
+ gateway_pb2.ClientSignalRequest(task_id=task_id, action=action_enum),
369
436
  )
370
437
  elapsed = (time.monotonic() - t0) * 1000
371
438
 
@@ -380,7 +447,7 @@ async def cmd_signal(
380
447
 
381
448
 
382
449
  async def run_full(args: argparse.Namespace) -> None:
383
- """Full pipeline: StartStream → Stream → SendSignal."""
450
+ """Full pipeline: StartStream → ConsumeStream → SendSignal."""
384
451
  task_id = args.task_id or str(uuid.uuid4())
385
452
  setup = json.loads(args.setup) if args.setup else None
386
453
  tracker = RedisTracker(args.redis) if args.verbose else None
@@ -400,7 +467,7 @@ async def run_full(args: argparse.Namespace) -> None:
400
467
 
401
468
  # 1. StartStream
402
469
  print(f"\n{BOLD}[1] StartStream{RESET}") # noqa: T201
403
- accepted = await cmd_start(stub, task_id)
470
+ accepted = await cmd_start(stub, task_id, args.prompt, setup)
404
471
  if not accepted:
405
472
  print(f" {RED}Server rejected the task — aborting.{RESET}") # noqa: T201
406
473
  return
@@ -409,17 +476,18 @@ async def run_full(args: argparse.Namespace) -> None:
409
476
  await asyncio.sleep(0.1)
410
477
  await tracker.snapshot("StartStream", task_id)
411
478
 
412
- # 2. Stream — send the query, read module output
413
- print(f"\n{BOLD}[2] Stream{RESET}") # noqa: T201
414
- received = await cmd_consume(stub, task_id, args.prompt, setup, args.verbose)
479
+ # 2. ConsumeStream — wait for module output
480
+ print(f"\n{BOLD}[2] ConsumeStream{RESET}") # noqa: T201
481
+ await asyncio.sleep(0.2) # let module start
482
+ received = await cmd_consume(stub, task_id, args.verbose)
415
483
 
416
484
  if tracker:
417
485
  await asyncio.sleep(0.1)
418
- await tracker.snapshot("Stream", task_id)
486
+ await tracker.snapshot("ConsumeStream", task_id)
419
487
 
420
488
  # 3. SendSignal
421
489
  print(f"\n{BOLD}[3] SendSignal (cancel){RESET}") # noqa: T201
422
- await cmd_signal(stub, task_id)
490
+ await cmd_signal(stub, task_id, "cancel")
423
491
 
424
492
  if tracker:
425
493
  await asyncio.sleep(0.1)
@@ -445,39 +513,61 @@ async def run_full(args: argparse.Namespace) -> None:
445
513
  async def run_start(args: argparse.Namespace) -> None:
446
514
  """StartStream only."""
447
515
  task_id = args.task_id or str(uuid.uuid4())
516
+ setup = json.loads(args.setup) if args.setup else None
448
517
 
449
518
  print(f"\n{BOLD}[StartStream]{RESET} gateway={args.gateway} task_id={task_id}") # noqa: T201
450
519
 
451
520
  async with grpc.aio.insecure_channel(args.gateway, options=GRPC_OPTIONS) as channel:
452
521
  stub = gateway_service_pb2_grpc.GatewayServiceStub(channel)
453
- await cmd_start(stub, task_id)
522
+ await cmd_start(stub, task_id, args.prompt, setup)
454
523
 
455
524
 
456
525
  async def run_consume(args: argparse.Namespace) -> None:
457
- """Stream on existing task."""
526
+ """ConsumeStream on existing task."""
458
527
  if not args.task_id:
459
528
  print(f"{RED}--task-id is required for consume{RESET}") # noqa: T201
460
529
  sys.exit(1)
461
530
 
531
+ print(f"\n{BOLD}[ConsumeStream]{RESET} gateway={args.gateway} task_id={args.task_id}") # noqa: T201
532
+
533
+ async with grpc.aio.insecure_channel(args.gateway, options=GRPC_OPTIONS) as channel:
534
+ stub = gateway_service_pb2_grpc.GatewayServiceStub(channel)
535
+ await cmd_consume(stub, args.task_id, args.verbose)
536
+
537
+
538
+ async def run_produce(args: argparse.Namespace) -> None:
539
+ """StartStream + ProduceStream (act as Module A)."""
540
+ task_id = args.task_id or str(uuid.uuid4())
462
541
  setup = json.loads(args.setup) if args.setup else None
463
- print(f"\n{BOLD}[Stream]{RESET} gateway={args.gateway} task_id={args.task_id}") # noqa: T201
542
+
543
+ print(f"\n{BOLD}[Produce]{RESET} gateway={args.gateway} task_id={task_id}") # noqa: T201
464
544
 
465
545
  async with grpc.aio.insecure_channel(args.gateway, options=GRPC_OPTIONS) as channel:
466
546
  stub = gateway_service_pb2_grpc.GatewayServiceStub(channel)
467
- await cmd_consume(stub, args.task_id, args.prompt, setup, args.verbose)
547
+
548
+ # StartStream first (registers the session)
549
+ print(f"\n {BOLD}StartStream{RESET}") # noqa: T201
550
+ accepted = await cmd_start(stub, task_id, args.prompt, setup)
551
+ if not accepted:
552
+ print(f" {RED}Rejected{RESET}") # noqa: T201
553
+ return
554
+
555
+ # ProduceStream (act as Module A)
556
+ print(f"\n {BOLD}ProduceStream ({args.chunks} chunks){RESET}") # noqa: T201
557
+ await cmd_produce(stub, task_id, args.prompt, args.chunks)
468
558
 
469
559
 
470
560
  async def run_signal(args: argparse.Namespace) -> None:
471
- """SendSignal(cancel) on existing task."""
561
+ """SendSignal on existing task."""
472
562
  if not args.task_id:
473
563
  print(f"{RED}--task-id is required for signal{RESET}") # noqa: T201
474
564
  sys.exit(1)
475
565
 
476
- print(f"\n{BOLD}[SendSignal]{RESET} gateway={args.gateway} task_id={args.task_id} signal=cancel") # noqa: T201
566
+ print(f"\n{BOLD}[SendSignal]{RESET} gateway={args.gateway} task_id={args.task_id} action={args.action}") # noqa: T201
477
567
 
478
568
  async with grpc.aio.insecure_channel(args.gateway, options=GRPC_OPTIONS) as channel:
479
569
  stub = gateway_service_pb2_grpc.GatewayServiceStub(channel)
480
- await cmd_signal(stub, args.task_id)
570
+ await cmd_signal(stub, args.task_id, args.action)
481
571
 
482
572
 
483
573
  async def run_inspect(args: argparse.Namespace) -> None:
@@ -523,7 +613,8 @@ examples:
523
613
  %(prog)s full --prompt "Test" --setup '{"uppercase": true, "repeat": 5}'
524
614
  %(prog)s start --prompt "Hello"
525
615
  %(prog)s consume --task-id <uuid>
526
- %(prog)s signal --task-id <uuid>
616
+ %(prog)s produce --chunks 5 --prompt "Manual"
617
+ %(prog)s signal --task-id <uuid> --action cancel
527
618
  %(prog)s inspect --task-id <uuid>
528
619
  """,
529
620
  )
@@ -540,16 +631,21 @@ examples:
540
631
  sub = p.add_subparsers(dest="command", help="Endpoint to test")
541
632
 
542
633
  # full (default)
543
- sub.add_parser("full", help="Full pipeline: StartStream -> Stream -> SendSignal")
634
+ sub.add_parser("full", help="Full pipeline: StartStream -> ConsumeStream -> SendSignal")
544
635
 
545
636
  # start
546
637
  sub.add_parser("start", help="StartStream only (unary)")
547
638
 
548
639
  # consume
549
- sub.add_parser("consume", help="Stream on existing task (requires --task-id)")
640
+ sub.add_parser("consume", help="ConsumeStream on existing task (requires --task-id)")
641
+
642
+ # produce
643
+ sp_produce = sub.add_parser("produce", help="StartStream + ProduceStream (act as Module A)")
644
+ sp_produce.add_argument("--chunks", type=int, default=3, help="Number of chunks to produce (default: 3)")
550
645
 
551
646
  # signal
552
- sub.add_parser("signal", help="SendSignal(cancel) on existing task (requires --task-id)")
647
+ sp_signal = sub.add_parser("signal", help="SendSignal on existing task (requires --task-id)")
648
+ sp_signal.add_argument("--action", choices=["cancel", "pause"], default="cancel", help="Signal action (default: cancel)")
553
649
 
554
650
  # inspect
555
651
  sub.add_parser("inspect", help="Dump Redis keys for a task (no gRPC)")
@@ -566,10 +662,17 @@ async def main() -> None:
566
662
  if not args.command:
567
663
  args.command = "full"
568
664
 
665
+ # Set defaults for subcommand-specific args
666
+ if not hasattr(args, "chunks"):
667
+ args.chunks = 3
668
+ if not hasattr(args, "action"):
669
+ args.action = "cancel"
670
+
569
671
  handlers = {
570
672
  "full": run_full,
571
673
  "start": run_start,
572
674
  "consume": run_consume,
675
+ "produce": run_produce,
573
676
  "signal": run_signal,
574
677
  "inspect": run_inspect,
575
678
  }
@@ -31,7 +31,7 @@
31
31
  # which is how a nested run's output is attributed to its author. Pinned exactly
32
32
  # because it is a dated prerelease; move to >=0.1.21 once that ships stable.
33
33
  "ag-ui-protocol==0.1.21.dev1787220377",
34
- "agentic-mesh-protocol==1.0.3.dev0",
34
+ "agentic-mesh-protocol==1.0.1",
35
35
  "agno>=2.8.0,<3",
36
36
  "anyio>=4.13.0",
37
37
  "grpcio-health-checking==1.82.1",
@@ -41,7 +41,7 @@
41
41
  "pydantic>=2.12.4",
42
42
  "redis[hiredis]>=7.4.0,<9",
43
43
  ]
44
- version = "1.0.5.dev0"
44
+ version = "1.0.5.dev2"
45
45
 
46
46
  [project.optional-dependencies]
47
47
  agno = [ "agno>=2.6" ]
@@ -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.5.dev0"
8
+ __version__ = "1.0.5.dev2"
@@ -7,6 +7,8 @@ import logging
7
7
  import uuid
8
8
  from typing import TYPE_CHECKING, Any, TypeAlias
9
9
 
10
+ from pydantic import ValidationError
11
+
10
12
  if TYPE_CHECKING:
11
13
  from collections.abc import Callable
12
14
 
@@ -54,6 +56,7 @@ if TYPE_CHECKING:
54
56
  from digitalkin.models.events import (
55
57
  AgentRunEvent,
56
58
  BaseAgentRunEvent,
59
+ CustomEvent,
57
60
  ReasoningCompletedEvent,
58
61
  ReasoningContentDeltaEvent,
59
62
  ReasoningStartedEvent,
@@ -62,6 +65,8 @@ from digitalkin.models.events import (
62
65
  RunContentEvent,
63
66
  RunErrorEvent,
64
67
  RunStartedEvent,
68
+ SourceCitation,
69
+ SourceCitationEvent,
65
70
  SubagentErrorEvent,
66
71
  SubagentFinishedEvent,
67
72
  SubagentStartedEvent,
@@ -80,7 +85,9 @@ class AgnoStreamAdapter:
80
85
  """Stateful Agno→DigitalKin event converter.
81
86
 
82
87
  Auto-wraps ``run_content`` deltas in TextMessage/Reasoning lifecycle
83
- events and tracks HITL pause state.
88
+ events and tracks HITL pause state. One adapter serves one stream: its
89
+ dedup state (citations, closed tool calls, completed runs) is reset on each
90
+ top-level ``run_started``, so it must not be shared across concurrent streams.
84
91
  """
85
92
 
86
93
  def __init__(self) -> None:
@@ -94,6 +101,8 @@ class AgnoStreamAdapter:
94
101
  self._reasonings: dict[str, tuple[str, dict[str, Any] | None]] = {}
95
102
 
96
103
  self._closed_tool_call_ids: set[str] = set()
104
+ # Providers repeat the same citations on every delta and again on completion.
105
+ self._cited_urls: set[str] = set()
97
106
 
98
107
  self._active_run_id: str | None = None
99
108
  self._completed_run_ids: set[str] = set()
@@ -206,6 +215,7 @@ class AgnoStreamAdapter:
206
215
  "tool_call_started": self._handle_tool_call_started,
207
216
  "tool_call_completed": self._handle_tool_call_completed,
208
217
  "tool_call_error": self._handle_tool_call_error,
218
+ "custom_event": self._handle_custom_event,
209
219
  }
210
220
  dispatch = {
211
221
  enum_cls[name]: handler
@@ -313,6 +323,17 @@ class AgnoStreamAdapter:
313
323
  self._active_run_id,
314
324
  self._last_metadata,
315
325
  )
326
+ # TODO(validate): ADAPTER-RESET per-run dedup state resets on each new top-level run
327
+ logger.info(
328
+ "[VALIDATE ADAPTER-RESET] run_id=%s clearing cited_urls=%d closed_tool_calls=%d completed_runs=%d",
329
+ run_id,
330
+ len(self._cited_urls),
331
+ len(self._closed_tool_call_ids),
332
+ len(self._completed_run_ids),
333
+ )
334
+ self._cited_urls.clear()
335
+ self._closed_tool_call_ids.clear()
336
+ self._completed_run_ids.clear()
316
337
  self._active_run_id = run_id
317
338
  return [
318
339
  RunStartedEvent(
@@ -337,11 +358,13 @@ class AgnoStreamAdapter:
337
358
  """
338
359
  parent_run_id = getattr(agno_event, "parent_run_id", None)
339
360
  run_id = agno_event.run_id
361
+ citations = self._citations(agno_event, timestamp)
340
362
 
341
363
  if parent_run_id:
342
364
  # Close this member's own text/reasoning bubble, then the matching step. Siblings
343
365
  # still streaming keep theirs open.
344
- events: list[BaseAgentRunEvent] = self._close_content(self._run_key, timestamp)
366
+ events: list[BaseAgentRunEvent] = citations
367
+ events.extend(self._close_content(self._run_key, timestamp))
345
368
  events.extend(self._close_reasoning(self._run_key, timestamp))
346
369
 
347
370
  subagent = self._subagents.pop(run_id, None) if run_id else None
@@ -377,7 +400,8 @@ class AgnoStreamAdapter:
377
400
 
378
401
  # AG-UI refuses RUN_FINISHED while any message, reasoning or step is still open, so
379
402
  # everything still running when the top-level run ends is force-closed here.
380
- events = self._close_all_content(timestamp)
403
+ events = citations
404
+ events.extend(self._close_all_content(timestamp))
381
405
  events.extend(self._close_all_reasoning(timestamp))
382
406
  events.extend(self._close_subagents(timestamp))
383
407
 
@@ -884,6 +908,80 @@ class AgnoStreamAdapter:
884
908
  event for run_key in reversed(list(self._messages)) for event in self._close_content(run_key, timestamp)
885
909
  ]
886
910
 
911
+ def _source_event(self, payload: Any, timestamp: Any) -> SourceCitationEvent | None:
912
+ """Validate one source payload into a ``source_citation`` event.
913
+
914
+ Args:
915
+ payload: ``{url, title?, description?}`` as received.
916
+ timestamp: Event timestamp.
917
+
918
+ Returns:
919
+ The event, or None when the payload is invalid (logged and dropped).
920
+ """
921
+ try:
922
+ citation = SourceCitation.model_validate(payload)
923
+ except ValidationError as exc:
924
+ logger.warning("Dropped source citation %r: %s", payload, exc)
925
+ return None
926
+ return SourceCitationEvent(
927
+ event=AgentRunEvent.CUSTOM,
928
+ name="source_citation",
929
+ value=citation,
930
+ subagent_run_id=self._subagent_of(self._run_key),
931
+ timestamp=timestamp,
932
+ metadata=self._last_metadata,
933
+ )
934
+
935
+ def _citations(
936
+ self, agno_event: AgnoRunContentEvent | AgnoRunCompletedEvent, timestamp: Any
937
+ ) -> list[BaseAgentRunEvent]:
938
+ """Convert the model-native ``citations.urls`` not yet emitted in this run.
939
+
940
+ Returns:
941
+ One SourceCitationEvent per new URL.
942
+ """
943
+ citations = agno_event.citations
944
+ if citations is None or not citations.urls:
945
+ return []
946
+ events: list[BaseAgentRunEvent] = []
947
+ for cite in citations.urls:
948
+ if not cite.url:
949
+ logger.warning("Dropped source citation without url: title=%r", cite.title)
950
+ continue
951
+ if cite.url in self._cited_urls:
952
+ continue
953
+ self._cited_urls.add(cite.url)
954
+ event = self._source_event({"url": cite.url, "title": cite.title}, timestamp)
955
+ if event is not None:
956
+ events.append(event)
957
+ return events
958
+
959
+ def _handle_custom_event(self, agno_event: AgnoRunEvent, timestamp: Any) -> list[BaseAgentRunEvent]:
960
+ """Handle RunEvent.custom_event — agno stores the tool's kwargs as attributes.
961
+
962
+ Returns:
963
+ A SourceCitationEvent for ``source_citation``, a generic CustomEvent otherwise,
964
+ or empty when the event is unnamed or its source is invalid.
965
+ """
966
+ data = agno_event.__dict__
967
+ name = data.get("name")
968
+ if not name:
969
+ logger.debug("Skipping unnamed agno custom event: %r", data)
970
+ return []
971
+ if name == "source_citation":
972
+ event = self._source_event(data.get("value"), timestamp)
973
+ return [event] if event is not None else []
974
+ return [
975
+ CustomEvent(
976
+ event=AgentRunEvent.CUSTOM,
977
+ name=name,
978
+ value=data.get("value"),
979
+ subagent_run_id=self._subagent_of(self._run_key),
980
+ timestamp=timestamp,
981
+ metadata=self._last_metadata,
982
+ )
983
+ ]
984
+
887
985
  def _handle_run_content(self, agno_event: AgnoRunContentEvent, timestamp: Any) -> list[BaseAgentRunEvent]:
888
986
  """Handle RunEvent.run_content — the core state machine.
889
987
 
@@ -892,7 +990,7 @@ class AgnoStreamAdapter:
892
990
  Returns:
893
991
  DigitalKin events for this chunk.
894
992
  """
895
- events: list[BaseAgentRunEvent] = []
993
+ events = self._citations(agno_event, timestamp)
896
994
 
897
995
  reasoning_content = agno_event.reasoning_content
898
996
  content = agno_event.content
@@ -85,11 +85,26 @@ class PausedRunStore:
85
85
  if tid and tid not in seen and tool.external_execution_required and tool.result is None:
86
86
  seen.add(tid)
87
87
  pending.append(tid)
88
+ payload = run_output.to_dict()
89
+ # History messages are re-fetched from the session by continue_run; events are not replayed.
90
+ messages = payload.get("messages") or []
91
+ history = [m for m in messages if m.get("from_history")]
92
+ if history:
93
+ payload["messages"] = [m for m in messages if not m.get("from_history")]
94
+ events = payload.pop("events", None) or []
95
+ # TODO(validate): HITL-TRIM paused runs stored without history messages/events still resume
96
+ logger.info(
97
+ "[VALIDATE HITL-TRIM] thread_id=%s dropped %d history message(s) %s and %d event(s)",
98
+ thread_id,
99
+ len(history),
100
+ [(m.get("id"), m.get("role")) for m in history],
101
+ len(events),
102
+ )
88
103
  record = PausedRunRecord(
89
104
  thread_id=thread_id,
90
105
  run_id=run_output.run_id or "",
91
106
  pending_tool_call_ids=pending,
92
- payload=run_output.to_dict(),
107
+ payload=payload,
93
108
  )
94
109
  await self._storage.upsert(
95
110
  collection=self.COLLECTION,