digitalkin 0.4.2.dev1__tar.gz → 1.0.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 (231) hide show
  1. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/PKG-INFO +25 -41
  2. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/README.md +10 -24
  3. digitalkin-1.0.0.dev1/examples/bench_module/echo_module.py +54 -0
  4. digitalkin-1.0.0.dev1/examples/bench_module/models/__init__.py +1 -0
  5. digitalkin-1.0.0.dev1/examples/bench_module/models/input.py +20 -0
  6. digitalkin-1.0.0.dev1/examples/bench_module/models/output.py +20 -0
  7. digitalkin-1.0.0.dev1/examples/bench_module/models/secret.py +10 -0
  8. digitalkin-1.0.0.dev1/examples/bench_module/models/setup.py +18 -0
  9. digitalkin-1.0.0.dev1/examples/bench_module/server.py +76 -0
  10. digitalkin-1.0.0.dev1/examples/bench_module/triggers/__init__.py +1 -0
  11. digitalkin-1.0.0.dev1/examples/bench_module/triggers/message_trigger.py +63 -0
  12. digitalkin-1.0.0.dev1/examples/redis_demo/client.py +690 -0
  13. digitalkin-1.0.0.dev1/examples/redis_demo/echo_module.py +51 -0
  14. digitalkin-1.0.0.dev1/examples/redis_demo/models/__init__.py +1 -0
  15. digitalkin-1.0.0.dev1/examples/redis_demo/models/input.py +19 -0
  16. digitalkin-1.0.0.dev1/examples/redis_demo/models/output.py +19 -0
  17. digitalkin-1.0.0.dev1/examples/redis_demo/models/secret.py +10 -0
  18. digitalkin-1.0.0.dev1/examples/redis_demo/models/setup.py +17 -0
  19. digitalkin-1.0.0.dev1/examples/redis_demo/server.py +70 -0
  20. digitalkin-1.0.0.dev1/examples/redis_demo/triggers/__init__.py +1 -0
  21. digitalkin-1.0.0.dev1/examples/redis_demo/triggers/message_trigger.py +63 -0
  22. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/pyproject.toml +80 -68
  23. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/__init__.py +12 -0
  24. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/__version__.py +1 -1
  25. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/community/agno/agno_adapter.py +84 -332
  26. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/community/agno/agui_tools.py +1 -1
  27. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/community/agno/hitl.py +2 -9
  28. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/core/common/factories.py +10 -1
  29. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/core/job_manager/base_job_manager.py +6 -3
  30. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/core/job_manager/single_job_manager.py +119 -33
  31. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/core/profiling/__init__.py +1 -2
  32. digitalkin-1.0.0.dev1/src/digitalkin/core/profiling/step_timer.py +59 -0
  33. digitalkin-1.0.0.dev1/src/digitalkin/core/resilience/__init__.py +22 -0
  34. digitalkin-1.0.0.dev1/src/digitalkin/core/resilience/bulkhead.py +140 -0
  35. digitalkin-1.0.0.dev1/src/digitalkin/core/resilience/graceful_shutdown.py +206 -0
  36. digitalkin-1.0.0.dev1/src/digitalkin/core/resilience/session_reaper.py +117 -0
  37. digitalkin-1.0.0.dev1/src/digitalkin/core/resilience/watchdog.py +166 -0
  38. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/core/task_manager/base_task_manager.py +4 -4
  39. digitalkin-1.0.0.dev1/src/digitalkin/core/task_manager/module_runner.py +170 -0
  40. digitalkin-1.0.0.dev1/src/digitalkin/core/task_manager/redis/__init__.py +33 -0
  41. digitalkin-1.0.0.dev1/src/digitalkin/core/task_manager/redis/instrumented.py +296 -0
  42. digitalkin-1.0.0.dev1/src/digitalkin/core/task_manager/redis/proto_streams.py +400 -0
  43. digitalkin-1.0.0.dev1/src/digitalkin/core/task_manager/redis/redis_checkpoint.py +150 -0
  44. digitalkin-1.0.0.dev1/src/digitalkin/core/task_manager/redis/redis_client.py +432 -0
  45. digitalkin-1.0.0.dev1/src/digitalkin/core/task_manager/redis/redis_idempotency.py +92 -0
  46. digitalkin-1.0.0.dev1/src/digitalkin/core/task_manager/redis/redis_signal.py +427 -0
  47. digitalkin-1.0.0.dev1/src/digitalkin/core/task_manager/redis/redis_state.py +149 -0
  48. digitalkin-1.0.0.dev1/src/digitalkin/core/task_manager/redis/redis_streams.py +331 -0
  49. digitalkin-1.0.0.dev1/src/digitalkin/core/task_manager/redis/shadow.py +194 -0
  50. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/core/task_manager/remote_task_manager.py +1 -1
  51. digitalkin-1.0.0.dev1/src/digitalkin/core/task_manager/task_executor.py +95 -0
  52. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/core/task_manager/task_session.py +74 -8
  53. digitalkin-1.0.0.dev1/src/digitalkin/core/task_manager/task_wrapper.py +97 -0
  54. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/grpc_servers/_base_server.py +55 -46
  55. digitalkin-1.0.0.dev1/src/digitalkin/grpc_servers/gateway_constants.py +149 -0
  56. digitalkin-1.0.0.dev1/src/digitalkin/grpc_servers/gateway_servicer.py +754 -0
  57. digitalkin-1.0.0.dev1/src/digitalkin/grpc_servers/interceptors/__init__.py +1 -0
  58. digitalkin-1.0.0.dev1/src/digitalkin/grpc_servers/interceptors/circuit_breaker_interceptor.py +70 -0
  59. digitalkin-1.0.0.dev1/src/digitalkin/grpc_servers/module_server.py +318 -0
  60. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/grpc_servers/module_servicer.py +107 -24
  61. digitalkin-1.0.0.dev1/src/digitalkin/grpc_servers/stream_error_codes.py +22 -0
  62. digitalkin-1.0.0.dev1/src/digitalkin/grpc_servers/stream_registry.py +261 -0
  63. digitalkin-1.0.0.dev1/src/digitalkin/grpc_servers/stream_session.py +124 -0
  64. digitalkin-1.0.0.dev1/src/digitalkin/grpc_servers/utils/circuit_breaker.py +171 -0
  65. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/grpc_servers/utils/grpc_client_wrapper.py +66 -26
  66. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/logger.py +16 -2
  67. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/mixins/agui_mixin.py +31 -68
  68. digitalkin-1.0.0.dev1/src/digitalkin/models/core/job_manager_models.py +11 -0
  69. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/events/__init__.py +0 -2
  70. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/events/agent_events.py +0 -14
  71. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/module/module_context.py +30 -28
  72. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/module/setup_types.py +8 -0
  73. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/module/utility.py +4 -7
  74. digitalkin-1.0.0.dev1/src/digitalkin/models/settings/consumer.py +48 -0
  75. digitalkin-1.0.0.dev1/src/digitalkin/models/settings/gateway.py +78 -0
  76. digitalkin-1.0.0.dev1/src/digitalkin/models/settings/profiling.py +18 -0
  77. digitalkin-1.0.0.dev1/src/digitalkin/models/settings/redis.py +60 -0
  78. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/settings/server/grpc.py +14 -4
  79. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/settings/server/server.py +4 -0
  80. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/modules/_base_module.py +48 -24
  81. digitalkin-1.0.0.dev1/src/digitalkin/py.typed +0 -0
  82. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/__init__.py +0 -6
  83. digitalkin-1.0.0.dev1/src/digitalkin/services/communication/__init__.py +27 -0
  84. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/communication/communication_strategy.py +3 -2
  85. digitalkin-1.0.0.dev1/src/digitalkin/services/communication/gateway_consumer.py +388 -0
  86. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/communication/grpc_communication.py +82 -38
  87. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/cost/grpc_cost.py +2 -2
  88. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/filesystem/grpc_filesystem.py +2 -2
  89. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/registry/default_registry.py +11 -0
  90. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/registry/grpc_registry.py +25 -1
  91. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/services_config.py +15 -25
  92. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/services_models.py +1 -5
  93. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/setup/grpc_setup.py +2 -2
  94. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/storage/grpc_storage.py +2 -2
  95. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/task_manager/__init__.py +2 -1
  96. digitalkin-1.0.0.dev1/src/digitalkin/services/task_manager/redis_task_manager.py +94 -0
  97. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/user_profile/grpc_user_profile.py +2 -2
  98. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/utils/conditional_schema.py +3 -2
  99. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin.egg-info/PKG-INFO +25 -41
  100. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin.egg-info/SOURCES.txt +52 -12
  101. digitalkin-1.0.0.dev1/src/digitalkin.egg-info/requires.txt +17 -0
  102. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin.egg-info/top_level.txt +2 -0
  103. digitalkin-0.4.2.dev1/src/digitalkin/core/job_manager/taskiq_broker.py +0 -514
  104. digitalkin-0.4.2.dev1/src/digitalkin/core/job_manager/taskiq_job_manager.py +0 -659
  105. digitalkin-0.4.2.dev1/src/digitalkin/core/profiling/asyncio_monitor.py +0 -48
  106. digitalkin-0.4.2.dev1/src/digitalkin/core/task_manager/task_executor.py +0 -256
  107. digitalkin-0.4.2.dev1/src/digitalkin/grpc_servers/module_server.py +0 -241
  108. digitalkin-0.4.2.dev1/src/digitalkin/mixins/callback_mixin.py +0 -38
  109. digitalkin-0.4.2.dev1/src/digitalkin/mixins/chat_history_mixin.py +0 -192
  110. digitalkin-0.4.2.dev1/src/digitalkin/models/core/job_manager_models.py +0 -48
  111. digitalkin-0.4.2.dev1/src/digitalkin/services/agent/__init__.py +0 -6
  112. digitalkin-0.4.2.dev1/src/digitalkin/services/agent/agent_strategy.py +0 -19
  113. digitalkin-0.4.2.dev1/src/digitalkin/services/agent/default_agent.py +0 -13
  114. digitalkin-0.4.2.dev1/src/digitalkin/services/communication/__init__.py +0 -7
  115. digitalkin-0.4.2.dev1/src/digitalkin/services/snapshot/__init__.py +0 -6
  116. digitalkin-0.4.2.dev1/src/digitalkin/services/snapshot/default_snapshot.py +0 -39
  117. digitalkin-0.4.2.dev1/src/digitalkin/services/snapshot/snapshot_strategy.py +0 -30
  118. digitalkin-0.4.2.dev1/src/digitalkin/services/task_manager/grpc_task_manager.py +0 -675
  119. digitalkin-0.4.2.dev1/src/digitalkin.egg-info/requires.txt +0 -19
  120. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/LICENSE +0 -0
  121. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/examples/base_server/__init__.py +0 -0
  122. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/examples/base_server/mock/__init__.py +0 -0
  123. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/examples/base_server/mock/mock_pb2.py +0 -0
  124. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/examples/base_server/mock/mock_pb2_grpc.py +0 -0
  125. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/examples/base_server/server_async_insecure.py +0 -0
  126. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/examples/base_server/server_async_secure.py +0 -0
  127. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/examples/base_server/server_sync_insecure.py +0 -0
  128. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/examples/base_server/server_sync_secure.py +0 -0
  129. {digitalkin-0.4.2.dev1/examples/modules → digitalkin-1.0.0.dev1/examples/bench_module}/__init__.py +0 -0
  130. /digitalkin-0.4.2.dev1/src/digitalkin/py.typed → /digitalkin-1.0.0.dev1/examples/modules/__init__.py +0 -0
  131. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/examples/modules/archetype_with_tools_module.py +0 -0
  132. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/examples/modules/cpu_intensive_module.py +0 -0
  133. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/examples/modules/dynamic_setup_module.py +0 -0
  134. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/examples/modules/minimal_llm_module.py +0 -0
  135. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/examples/modules/text_transform_module.py +0 -0
  136. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/examples/monitoring/digitalkin_observability/__init__.py +0 -0
  137. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/examples/monitoring/digitalkin_observability/http_server.py +0 -0
  138. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/examples/monitoring/digitalkin_observability/interceptors.py +0 -0
  139. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/examples/monitoring/digitalkin_observability/metrics.py +0 -0
  140. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/examples/monitoring/digitalkin_observability/prometheus.py +0 -0
  141. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/examples/monitoring/tests/test_metrics.py +0 -0
  142. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/examples/services/filesystem_module.py +0 -0
  143. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/examples/services/storage_module.py +0 -0
  144. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/setup.cfg +0 -0
  145. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/community/__init__.py +0 -0
  146. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/community/agno/__init__.py +0 -0
  147. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/core/__init__.py +0 -0
  148. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/core/common/__init__.py +0 -0
  149. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/core/job_manager/__init__.py +0 -0
  150. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/core/profiling/task_profiler.py +0 -0
  151. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/core/task_manager/__init__.py +0 -0
  152. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/core/task_manager/local_task_manager.py +0 -0
  153. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/grpc_servers/__init__.py +0 -0
  154. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/grpc_servers/utils/__init__.py +0 -0
  155. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/grpc_servers/utils/exceptions.py +0 -0
  156. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/grpc_servers/utils/grpc_error_handler.py +0 -0
  157. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/grpc_servers/utils/utility_schema_extender.py +0 -0
  158. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/mixins/__init__.py +0 -0
  159. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/mixins/base_mixin.py +0 -0
  160. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/mixins/cost_mixin.py +0 -0
  161. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/mixins/file_history_mixin.py +0 -0
  162. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/mixins/filesystem_mixin.py +0 -0
  163. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/mixins/logger_mixin.py +0 -0
  164. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/mixins/storage_mixin.py +0 -0
  165. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/__init__.py +0 -0
  166. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/core/__init__.py +0 -0
  167. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/core/task_monitor.py +0 -0
  168. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/grpc_servers/__init__.py +0 -0
  169. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/grpc_servers/models.py +0 -0
  170. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/grpc_servers/types.py +0 -0
  171. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/module/__init__.py +0 -0
  172. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/module/ag_ui.py +0 -0
  173. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/module/base_types.py +0 -0
  174. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/module/module.py +0 -0
  175. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/module/module_types.py +0 -0
  176. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/module/request_metadata.py +0 -0
  177. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/module/select_schema.py +0 -0
  178. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/module/tool_cache.py +0 -0
  179. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/module/tool_reference.py +0 -0
  180. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/services/__init__.py +0 -0
  181. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/services/cost.py +0 -0
  182. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/services/registry.py +0 -0
  183. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/services/storage.py +0 -0
  184. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/settings/__init__.py +0 -0
  185. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/settings/server/__init__.py +0 -0
  186. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/settings/server/channel.py +0 -0
  187. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/settings/utils/__init__.py +0 -0
  188. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/models/settings/utils/channel.py +0 -0
  189. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/modules/__init__.py +0 -0
  190. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/modules/archetype_module.py +0 -0
  191. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/modules/tool_module.py +0 -0
  192. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/modules/trigger_handler.py +0 -0
  193. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/modules/triggers/__init__.py +0 -0
  194. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/modules/triggers/healthcheck_ping_trigger.py +0 -0
  195. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/modules/triggers/healthcheck_services_trigger.py +0 -0
  196. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/modules/triggers/healthcheck_status_trigger.py +0 -0
  197. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/base_strategy.py +0 -0
  198. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/communication/default_communication.py +0 -0
  199. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/cost/__init__.py +0 -0
  200. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/cost/cost_strategy.py +0 -0
  201. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/cost/default_cost.py +0 -0
  202. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/filesystem/__init__.py +0 -0
  203. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/filesystem/default_filesystem.py +0 -0
  204. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/filesystem/filesystem_strategy.py +0 -0
  205. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/identity/__init__.py +0 -0
  206. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/identity/default_identity.py +0 -0
  207. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/identity/identity_strategy.py +0 -0
  208. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/registry/__init__.py +0 -0
  209. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/registry/exceptions.py +0 -0
  210. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/registry/registry_models.py +0 -0
  211. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/registry/registry_strategy.py +0 -0
  212. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/setup/__init__.py +0 -0
  213. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/setup/default_setup.py +0 -0
  214. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/setup/setup_strategy.py +0 -0
  215. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/storage/__init__.py +0 -0
  216. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/storage/default_storage.py +0 -0
  217. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/storage/storage_strategy.py +0 -0
  218. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/task_manager/default_task_manager.py +0 -0
  219. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/task_manager/task_manager_strategy.py +0 -0
  220. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/user_profile/__init__.py +0 -0
  221. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/user_profile/default_user_profile.py +0 -0
  222. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/services/user_profile/user_profile_strategy.py +0 -0
  223. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/utils/__init__.py +0 -0
  224. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/utils/arg_parser.py +0 -0
  225. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/utils/development_mode_action.py +0 -0
  226. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/utils/dynamic_schema.py +0 -0
  227. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/utils/llm_ready_schema.py +0 -0
  228. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/utils/package_discover.py +0 -0
  229. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/utils/proto_utils.py +0 -0
  230. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin/utils/schema_splitter.py +0 -0
  231. {digitalkin-0.4.2.dev1 → digitalkin-1.0.0.dev1}/src/digitalkin.egg-info/dependency_links.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: digitalkin
3
- Version: 0.4.2.dev1
3
+ Version: 1.0.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
@@ -452,23 +452,21 @@ Classifier: Topic :: Software Development :: Libraries
452
452
  Requires-Python: >=3.10
453
453
  Description-Content-Type: text/markdown
454
454
  License-File: LICENSE
455
- Requires-Dist: ag-ui-protocol>=0.1.14
456
- Requires-Dist: agentic-mesh-protocol==0.2.3
457
- Requires-Dist: anyio==4.13.0
458
- Requires-Dist: grpcio-health-checking==1.78.0
459
- Requires-Dist: grpcio-reflection==1.78.0
460
- Requires-Dist: grpcio-status==1.78.0
461
- Requires-Dist: pydantic==2.12.5
455
+ Requires-Dist: ag-ui-protocol>=0.1.18
456
+ Requires-Dist: agentic-mesh-protocol==1.0.0.dev1
457
+ Requires-Dist: anyio>=4.13.0
458
+ Requires-Dist: grpcio-health-checking==1.80.0
459
+ Requires-Dist: grpcio-reflection==1.80.0
460
+ Requires-Dist: grpcio-status==1.80.0
461
+ Requires-Dist: pydantic>=2.12.5
462
+ Requires-Dist: pydantic-settings>=2.14.0
463
+ Requires-Dist: redis[hiredis]<8,>=7.4.0
464
+ Provides-Extra: performance
465
+ Requires-Dist: uvloop>=0.21; extra == "performance"
462
466
  Provides-Extra: profiling
463
- Requires-Dist: asyncio-inspector==0.1.0; extra == "profiling"
464
- Requires-Dist: pyinstrument==5.1.2; extra == "profiling"
465
- Requires-Dist: viztracer==1.1.1; extra == "profiling"
466
- Requires-Dist: yappi==1.7.6; extra == "profiling"
467
- Provides-Extra: taskiq
468
- Requires-Dist: rstream==1.0.0; extra == "taskiq"
469
- Requires-Dist: taskiq-aio-pika==0.6.0; extra == "taskiq"
470
- Requires-Dist: taskiq-redis==1.2.2; extra == "taskiq"
471
- Requires-Dist: taskiq[reload]==0.12.1; extra == "taskiq"
467
+ Requires-Dist: pyinstrument>=5.1.2; extra == "profiling"
468
+ Requires-Dist: viztracer>=1.1.1; extra == "profiling"
469
+ Requires-Dist: yappi>=1.7.6; extra == "profiling"
472
470
  Dynamic: license-file
473
471
 
474
472
  # DigitalKin Python SDK
@@ -499,8 +497,7 @@ communicate over gRPC, register with a service mesh, and scale independently.
499
497
  - **Profiling** — optional `[profiling]` extra with asyncio-inspector,
500
498
  pyinstrument, viztracer, and yappi
501
499
  - **Batched history writes** — efficient storage writes for conversation history
502
- - **TaskIQ integration** — optional distributed task execution backed by
503
- RabbitMQ and Redis (`[taskiq]` extra)
500
+ - **Redis Streams** — durable message passing, crash recovery, and reconnection
504
501
 
505
502
  ## Installation
506
503
 
@@ -515,11 +512,11 @@ pip install digitalkin
515
512
  **Optional extras:**
516
513
 
517
514
  ```bash
518
- # Distributed task execution (RabbitMQ + Redis)
519
- uv add "digitalkin[taskiq]"
520
-
521
515
  # Async profiling tools
522
516
  uv add "digitalkin[profiling]"
517
+
518
+ # uvloop for faster event loop
519
+ uv add "digitalkin[performance]"
523
520
  ```
524
521
 
525
522
  ## Quick Start
@@ -597,26 +594,15 @@ async def main() -> None:
597
594
  asyncio.run(main())
598
595
  ```
599
596
 
600
- ## TaskIQ with RabbitMQ
601
-
602
- TaskIQ integration allows the module to scale for heavy CPU tasks by
603
- distributing requests to stateless worker instances.
597
+ ## Redis Gateway
604
598
 
605
- - **Decoupled Scalability**: RabbitMQ brokers messages, letting producers and
606
- consumers scale independently.
607
- - **Reliability**: Durable queues, acknowledgements, and dead-lettering ensure
608
- tasks aren't lost.
609
- - **Concurrency Control**: TaskIQ's worker pool manages parallel execution
610
- without custom schedulers.
611
- - **Flexibility**: Built-in retries, exponential backoff, and Redis
612
- result-backend for resilient workflows.
599
+ The embedded gateway enables real-time bidirectional communication between
600
+ modules via Redis Streams, with crash recovery and horizontal scaling.
613
601
 
614
- To enable RabbitMQ streaming:
602
+ - **Durable Streaming**: Output persisted to Redis Streams — reconnection via `from_seq`.
603
+ - **Zero-Copy Proto**: Binary proto serialization to Redis — no JSON intermediary.
604
+ - **Horizontal Scaling**: Each module instance embeds its own gateway. Scale by adding replicas behind a load balancer.
615
605
 
616
- ```bash
617
- sudo rabbitmq-plugins enable rabbitmq_stream
618
- task start-taskiq
619
- ```
620
606
 
621
607
  ## Development
622
608
 
@@ -649,8 +635,6 @@ task docs-serve # Serve docs locally (mkdocs)
649
635
  task docs-build # Build docs
650
636
 
651
637
  task generate-certificates # Generate mTLS certs for gRPC
652
- task start-taskiq # Start TaskIQ worker
653
-
654
638
  task clean # Remove build artifacts + __pycache__
655
639
  task clean-all # Above + remove .venv
656
640
  ```
@@ -26,8 +26,7 @@ communicate over gRPC, register with a service mesh, and scale independently.
26
26
  - **Profiling** — optional `[profiling]` extra with asyncio-inspector,
27
27
  pyinstrument, viztracer, and yappi
28
28
  - **Batched history writes** — efficient storage writes for conversation history
29
- - **TaskIQ integration** — optional distributed task execution backed by
30
- RabbitMQ and Redis (`[taskiq]` extra)
29
+ - **Redis Streams** — durable message passing, crash recovery, and reconnection
31
30
 
32
31
  ## Installation
33
32
 
@@ -42,11 +41,11 @@ pip install digitalkin
42
41
  **Optional extras:**
43
42
 
44
43
  ```bash
45
- # Distributed task execution (RabbitMQ + Redis)
46
- uv add "digitalkin[taskiq]"
47
-
48
44
  # Async profiling tools
49
45
  uv add "digitalkin[profiling]"
46
+
47
+ # uvloop for faster event loop
48
+ uv add "digitalkin[performance]"
50
49
  ```
51
50
 
52
51
  ## Quick Start
@@ -124,26 +123,15 @@ async def main() -> None:
124
123
  asyncio.run(main())
125
124
  ```
126
125
 
127
- ## TaskIQ with RabbitMQ
128
-
129
- TaskIQ integration allows the module to scale for heavy CPU tasks by
130
- distributing requests to stateless worker instances.
126
+ ## Redis Gateway
131
127
 
132
- - **Decoupled Scalability**: RabbitMQ brokers messages, letting producers and
133
- consumers scale independently.
134
- - **Reliability**: Durable queues, acknowledgements, and dead-lettering ensure
135
- tasks aren't lost.
136
- - **Concurrency Control**: TaskIQ's worker pool manages parallel execution
137
- without custom schedulers.
138
- - **Flexibility**: Built-in retries, exponential backoff, and Redis
139
- result-backend for resilient workflows.
128
+ The embedded gateway enables real-time bidirectional communication between
129
+ modules via Redis Streams, with crash recovery and horizontal scaling.
140
130
 
141
- To enable RabbitMQ streaming:
131
+ - **Durable Streaming**: Output persisted to Redis Streams — reconnection via `from_seq`.
132
+ - **Zero-Copy Proto**: Binary proto serialization to Redis — no JSON intermediary.
133
+ - **Horizontal Scaling**: Each module instance embeds its own gateway. Scale by adding replicas behind a load balancer.
142
134
 
143
- ```bash
144
- sudo rabbitmq-plugins enable rabbitmq_stream
145
- task start-taskiq
146
- ```
147
135
 
148
136
  ## Development
149
137
 
@@ -176,8 +164,6 @@ task docs-serve # Serve docs locally (mkdocs)
176
164
  task docs-build # Build docs
177
165
 
178
166
  task generate-certificates # Generate mTLS certs for gRPC
179
- task start-taskiq # Start TaskIQ worker
180
-
181
167
  task clean # Remove build artifacts + __pycache__
182
168
  task clean-all # Above + remove .venv
183
169
  ```
@@ -0,0 +1,54 @@
1
+ """EchoModule — a simple tool module that echoes transformed text.
2
+
3
+ Mirrors the template-tool pattern: ToolModule with TriggerHandler,
4
+ DataTrigger models, and ModuleServer with embedded gateway.
5
+ """
6
+
7
+ from typing import Any, ClassVar
8
+
9
+ from models.input import EchoInput
10
+ from models.output import EchoOutput
11
+ from models.secret import EchoSecret
12
+ from models.setup import EchoSetup
13
+
14
+ from digitalkin.models.module import ModuleContext
15
+ from digitalkin.modules.tool_module import ToolModule
16
+ from digitalkin.utils.package_discover import ModuleDiscoverer
17
+
18
+
19
+ class EchoToolModule(ToolModule[EchoInput, EchoOutput, EchoSetup, EchoSecret]):
20
+ """A tool module that echoes transformed text with streaming output."""
21
+
22
+ name = "EchoToolModule"
23
+ description = "Echoes input text with optional transforms (uppercase, prefix, reverse, repeat)."
24
+
25
+ input_format = EchoInput
26
+ output_format = EchoOutput
27
+ setup_format = EchoSetup
28
+ secret_format = EchoSecret
29
+
30
+ metadata: ClassVar[dict[str, str | list[str]]] = {
31
+ "name": "EchoToolModule",
32
+ "description": "Echoes input text with transforms.",
33
+ "version": "1.0.0",
34
+ "tags": ["echo", "tool", "demo"],
35
+ }
36
+
37
+ services_config_strategies: ClassVar[dict[str, Any]] = {}
38
+ services_config_params: ClassVar[dict[str, Any]] = {
39
+ "storage": {"config": {}},
40
+ "cost": {"config": {}},
41
+ }
42
+
43
+ triggers_discoverer = ModuleDiscoverer(packages=["triggers"])
44
+
45
+ async def initialize(self, context: ModuleContext, setup_data: EchoSetup) -> None:
46
+ """Initialize module.
47
+
48
+ Args:
49
+ context: The module context.
50
+ setup_data: The setup configuration.
51
+ """
52
+
53
+ async def cleanup(self) -> None:
54
+ """Clean up resources."""
@@ -0,0 +1 @@
1
+ """Data models for the EchoModule."""
@@ -0,0 +1,20 @@
1
+ """Input models for the EchoModule."""
2
+
3
+ from typing import Literal
4
+
5
+ from pydantic import Field
6
+
7
+ from digitalkin.models.module import DataModel, DataTrigger
8
+
9
+
10
+ class MessageInputPayload(DataTrigger):
11
+ """Input payload for message protocol."""
12
+
13
+ protocol: Literal["message"] = "message"
14
+ user_prompt: str = Field(..., description="The user's input prompt")
15
+
16
+
17
+ class EchoInput(DataModel[MessageInputPayload]):
18
+ """Unified input model for the EchoModule."""
19
+
20
+ root: MessageInputPayload = Field(..., discriminator="protocol")
@@ -0,0 +1,20 @@
1
+ """Output models for the EchoModule."""
2
+
3
+ from typing import Literal
4
+
5
+ from pydantic import Field
6
+
7
+ from digitalkin.models.module import DataModel, DataTrigger
8
+
9
+
10
+ class MessageOutputPayload(DataTrigger):
11
+ """Output payload for message protocol."""
12
+
13
+ protocol: Literal["message"] = "message"
14
+ response: str = Field(..., description="The response message")
15
+
16
+
17
+ class EchoOutput(DataModel[MessageOutputPayload]):
18
+ """Unified output model for the EchoModule."""
19
+
20
+ root: MessageOutputPayload = Field(..., discriminator="protocol")
@@ -0,0 +1,10 @@
1
+ """Secret model for the EchoModule."""
2
+
3
+ from pydantic import BaseModel
4
+
5
+
6
+ class EchoSecret(BaseModel):
7
+ """Secret model for the EchoModule.
8
+
9
+ This module has no secrets.
10
+ """
@@ -0,0 +1,18 @@
1
+ """Setup model for the EchoModule."""
2
+
3
+ from pydantic import Field
4
+
5
+ from digitalkin.models.module import SetupModel
6
+
7
+
8
+ class EchoSetup(SetupModel):
9
+ """Configuration model for the EchoModule.
10
+
11
+ Controls how input text is transformed before streaming back.
12
+ """
13
+
14
+ uppercase: bool = Field(default=False, description="Convert output to uppercase")
15
+ repeat: int = Field(default=1, description="Number of output chunks per input")
16
+ delay_ms: int = Field(default=0, description="Milliseconds between chunks")
17
+ prefix: str = Field(default="", description="Prepend to each output chunk")
18
+ reverse: bool = Field(default=False, description="Reverse the text")
@@ -0,0 +1,76 @@
1
+ """Benchmark module server — EchoModule with embedded Gateway.
2
+
3
+ Pre-registers a default setup so LOCAL mode works without external services.
4
+ Server config comes from env vars via ServerSettings (pydantic-settings).
5
+ Gateway auto-enables via DIGITALKIN_REDIS_URL env var.
6
+ """
7
+
8
+ import asyncio
9
+ import logging
10
+ import sys
11
+
12
+ sys.path.insert(0, "/app/bench_module")
13
+
14
+ import datetime
15
+
16
+ from echo_module import EchoToolModule
17
+
18
+ from digitalkin.grpc_servers.module_server import ModuleServer
19
+
20
+
21
+ async def main_async() -> int:
22
+ """Run the benchmark module server.
23
+
24
+ Returns:
25
+ Exit code.
26
+ """
27
+ module_server = None
28
+ try:
29
+ module_server = ModuleServer(EchoToolModule)
30
+ await module_server.start_async()
31
+
32
+ # Pre-register default setup so LOCAL mode can resolve setup_id
33
+ if module_server.module_servicer is not None:
34
+ setup = module_server.module_servicer.setup
35
+ now = datetime.datetime.now(datetime.timezone.utc)
36
+ await setup.create_setup({
37
+ "setup_id": "setups:echo_bench",
38
+ "data": {
39
+ "id": "setups:echo_bench",
40
+ "name": "Echo Benchmark",
41
+ "organisation_id": "org:bench",
42
+ "owner_id": "user:bench",
43
+ "module_id": "modules:echo_bench",
44
+ "current_setup_version": {
45
+ "id": "v1",
46
+ "setup_id": "setups:echo_bench",
47
+ "version": "1.0.0",
48
+ "content": {"enabled": True},
49
+ "creation_date": now.isoformat(),
50
+ },
51
+ },
52
+ })
53
+ await setup.create_setup_version({
54
+ "setup_id": "setups:echo_bench",
55
+ "data": {
56
+ "id": "v1",
57
+ "setup_id": "setups:echo_bench",
58
+ "version": "1.0.0",
59
+ "content": {"enabled": True},
60
+ "creation_date": now.isoformat(),
61
+ },
62
+ })
63
+ logging.info("Pre-registered setup: setups:echo_bench")
64
+
65
+ logging.info("Bench module server started on 0.0.0.0:50055")
66
+ await module_server.await_termination()
67
+ except KeyboardInterrupt:
68
+ pass
69
+ finally:
70
+ if module_server is not None and module_server.server is not None:
71
+ await module_server.stop_async()
72
+ return 0
73
+
74
+
75
+ if __name__ == "__main__":
76
+ sys.exit(asyncio.run(main_async()))
@@ -0,0 +1 @@
1
+ """Trigger handlers for the EchoModule."""
@@ -0,0 +1,63 @@
1
+ """Message trigger handler for the EchoModule."""
2
+
3
+ import asyncio
4
+ from typing import ClassVar, Literal
5
+
6
+ from echo_module import EchoToolModule
7
+ from models.input import MessageInputPayload
8
+ from models.output import MessageOutputPayload
9
+ from models.setup import EchoSetup
10
+
11
+ from digitalkin.models.module import ModuleContext
12
+ from digitalkin.modules.trigger_handler import TriggerHandler
13
+
14
+
15
+ @EchoToolModule.register
16
+ class MessageTrigger(TriggerHandler):
17
+ """Handles message protocol inputs — transforms and streams output chunks."""
18
+
19
+ protocol: Literal["message"] = "message"
20
+ description: ClassVar[str] = "Echo input text with optional transforms (uppercase, prefix, reverse, repeat)."
21
+ input_format = MessageInputPayload
22
+ output_format = MessageOutputPayload
23
+
24
+ def __init__(self, context: ModuleContext) -> None:
25
+ """Initialize the message trigger.
26
+
27
+ Args:
28
+ context: The module context.
29
+ """
30
+ self.enable_log = True
31
+
32
+ async def handle(
33
+ self,
34
+ input_data: MessageInputPayload,
35
+ setup_data: EchoSetup,
36
+ context: ModuleContext,
37
+ ) -> None:
38
+ """Transform input and stream output chunks.
39
+
40
+ Args:
41
+ input_data: The input data payload.
42
+ setup_data: The setup configuration.
43
+ context: The module context.
44
+ """
45
+ text = input_data.user_prompt
46
+ repeat = setup_data.repeat
47
+ delay_s = setup_data.delay_ms / 1000
48
+
49
+ for i in range(repeat):
50
+ result = text
51
+ if setup_data.reverse:
52
+ result = result[::-1]
53
+ if setup_data.uppercase:
54
+ result = result.upper()
55
+ if setup_data.prefix:
56
+ result = f"{setup_data.prefix}{result}"
57
+ chunk = f"[{i + 1}/{repeat}] {result}"
58
+
59
+ output = MessageOutputPayload(response=chunk)
60
+ await self.send_message(context, output)
61
+
62
+ if i < repeat - 1 and delay_s > 0:
63
+ await asyncio.sleep(delay_s)