digitalkin 1.0.0.dev10__tar.gz → 1.0.0.dev12__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.
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/PKG-INFO +1 -1
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/pyproject.toml +4 -1
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/__version__.py +1 -1
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/community/agno/__init__.py +8 -14
- digitalkin-1.0.0.dev12/src/digitalkin/community/agno/agui_tools.py +90 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/community/agno/hitl.py +162 -158
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/job_manager/base_job_manager.py +34 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/job_manager/single_job_manager.py +2 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/task_manager/module_runner.py +5 -6
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/task_manager/redis/instrumented.py +2 -4
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/task_manager/redis/redis_client.py +21 -24
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/task_manager/redis/redis_signal.py +5 -4
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/task_manager/redis/redis_streams.py +1 -2
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/task_manager/redis/shadow.py +2 -5
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/task_manager/task_session.py +1 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/grpc_servers/_base_server.py +9 -11
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/grpc_servers/gateway_servicer.py +3 -3
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/grpc_servers/m2m_call_registry.py +1 -2
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/grpc_servers/module_server.py +15 -16
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/grpc_servers/module_servicer.py +12 -15
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/grpc_servers/utils/grpc_client_wrapper.py +1 -1
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/grpc_servers/utils/utility_schema_extender.py +2 -2
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/logger.py +84 -81
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/mixins/agui_mixin.py +65 -87
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/events/agent_events.py +28 -28
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/module/ag_ui.py +33 -33
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/module/module_context.py +1 -1
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/module/setup_types.py +20 -21
- digitalkin-1.0.0.dev12/src/digitalkin/models/module/tool_cache.py +239 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/module/tool_reference.py +38 -26
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/module/utility.py +7 -7
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/utils/dynamic_schema.py +1 -1
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/modules/_base_module.py +9 -13
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/modules/tool_module.py +1 -1
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/base_strategy.py +6 -6
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/communication/communication_strategy.py +1 -1
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/communication/grpc_communication.py +6 -12
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/cost/grpc_cost.py +4 -4
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/filesystem/default_filesystem.py +4 -4
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/registry/grpc_registry.py +22 -49
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/setup/default_setup.py +2 -2
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/setup/grpc_setup.py +5 -9
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/storage/grpc_storage.py +2 -2
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/user_profile/grpc_user_profile.py +2 -2
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/utils/__init__.py +2 -18
- digitalkin-1.0.0.dev12/src/digitalkin/utils/conditional_schema.py +197 -0
- digitalkin-1.0.0.dev12/src/digitalkin/utils/dynamic_schema.py +303 -0
- digitalkin-1.0.0.dev12/src/digitalkin/utils/llm_ready_schema.py +77 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/utils/package_discover.py +3 -3
- digitalkin-1.0.0.dev12/src/digitalkin/utils/proto_utils.py +25 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin.egg-info/PKG-INFO +1 -1
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin.egg-info/SOURCES.txt +2 -1
- digitalkin-1.0.0.dev12/tests/test_exceptions.py +106 -0
- digitalkin-1.0.0.dev10/src/digitalkin/community/agno/agui_tools.py +0 -127
- digitalkin-1.0.0.dev10/src/digitalkin/models/module/tool_cache.py +0 -259
- digitalkin-1.0.0.dev10/src/digitalkin/utils/conditional_schema.py +0 -212
- digitalkin-1.0.0.dev10/src/digitalkin/utils/dynamic_schema.py +0 -435
- digitalkin-1.0.0.dev10/src/digitalkin/utils/llm_ready_schema.py +0 -79
- digitalkin-1.0.0.dev10/src/digitalkin/utils/proto_utils.py +0 -21
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/LICENSE +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/README.md +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/base_server/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/base_server/mock/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/base_server/mock/mock_pb2.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/base_server/mock/mock_pb2_grpc.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/base_server/server_async_insecure.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/base_server/server_async_secure.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/base_server/server_sync_insecure.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/base_server/server_sync_secure.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/bench_module/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/bench_module/echo_module.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/bench_module/models/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/bench_module/models/input.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/bench_module/models/output.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/bench_module/models/secret.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/bench_module/models/setup.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/bench_module/server.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/bench_module/triggers/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/bench_module/triggers/message_trigger.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/modules/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/modules/archetype_with_tools_module.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/modules/cpu_intensive_module.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/modules/dynamic_setup_module.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/modules/minimal_llm_module.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/modules/text_transform_module.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/monitoring/digitalkin_observability/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/monitoring/digitalkin_observability/http_server.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/monitoring/digitalkin_observability/interceptors.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/monitoring/digitalkin_observability/metrics.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/monitoring/digitalkin_observability/prometheus.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/monitoring/tests/test_metrics.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/redis_demo/client.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/redis_demo/echo_module.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/redis_demo/models/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/redis_demo/models/input.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/redis_demo/models/output.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/redis_demo/models/secret.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/redis_demo/models/setup.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/redis_demo/server.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/redis_demo/triggers/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/redis_demo/triggers/message_trigger.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/services/filesystem_module.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/examples/services/storage_module.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/setup.cfg +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/community/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/community/agno/agno_adapter.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/community/agno/models.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/common/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/common/factories.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/exceptions.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/job_manager/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/profiling/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/profiling/step_timer.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/profiling/task_profiler.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/resilience/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/resilience/bulkhead.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/resilience/task_supervisor.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/task_manager/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/task_manager/base_task_manager.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/task_manager/local_task_manager.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/task_manager/redis/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/task_manager/redis/proto_streams.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/task_manager/redis/redis_checkpoint.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/task_manager/redis/redis_idempotency.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/task_manager/redis/redis_state.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/task_manager/remote_task_manager.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/task_manager/task_executor.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/exceptions.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/grpc_servers/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/grpc_servers/exceptions.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/grpc_servers/interceptors/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/grpc_servers/interceptors/circuit_breaker_interceptor.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/grpc_servers/stream_registry.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/grpc_servers/stream_session.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/grpc_servers/utils/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/grpc_servers/utils/circuit_breaker.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/grpc_servers/utils/grpc_error_handler.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/grpc_servers/utils/validators.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/mixins/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/mixins/base_mixin.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/mixins/cost_mixin.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/mixins/file_history_mixin.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/mixins/filesystem_mixin.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/mixins/logger_mixin.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/mixins/storage_mixin.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/core/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/core/job_manager_models.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/core/redis.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/core/task_monitor.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/events/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/grpc_servers/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/grpc_servers/circuit_breaker.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/grpc_servers/m2m.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/grpc_servers/models.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/grpc_servers/stream_error_codes.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/grpc_servers/types.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/module/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/module/base_types.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/module/module.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/module/module_types.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/module/request_metadata.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/module/select_schema.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/services/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/services/cost.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/services/registry.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/services/services.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/services/storage.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/settings/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/settings/consumer.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/settings/gateway.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/settings/grpc_client.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/settings/log.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/settings/module.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/settings/profiling.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/settings/queue.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/settings/redis.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/settings/resilience.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/settings/server/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/settings/server/channel.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/settings/server/grpc.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/settings/server/server.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/settings/server/servicer.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/settings/task_manager.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/settings/utils/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/settings/utils/channel.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/models/utils/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/modules/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/modules/archetype_module.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/modules/trigger_handler.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/modules/triggers/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/modules/triggers/healthcheck_ping_trigger.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/modules/triggers/healthcheck_services_trigger.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/modules/triggers/healthcheck_status_trigger.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/py.typed +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/communication/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/communication/default_communication.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/communication/exceptions.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/cost/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/cost/cost_strategy.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/cost/default_cost.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/cost/exceptions.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/filesystem/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/filesystem/exceptions.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/filesystem/filesystem_strategy.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/filesystem/grpc_filesystem.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/identity/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/identity/default_identity.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/identity/identity_strategy.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/registry/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/registry/default_registry.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/registry/exceptions.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/registry/registry_models.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/registry/registry_strategy.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/services_config.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/services_models.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/setup/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/setup/exceptions.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/setup/setup_strategy.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/storage/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/storage/default_storage.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/storage/exceptions.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/storage/storage_strategy.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/task_manager/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/task_manager/default_task_manager.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/task_manager/exceptions.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/task_manager/redis_task_manager.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/task_manager/task_manager_strategy.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/user_profile/__init__.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/user_profile/default_user_profile.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/user_profile/exceptions.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/services/user_profile/user_profile_strategy.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/utils/arg_parser.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/utils/development_mode_action.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/utils/exceptions.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/utils/schema_splitter.py +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin.egg-info/dependency_links.txt +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin.egg-info/requires.txt +0 -0
- {digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin.egg-info/top_level.txt +0 -0
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"pydantic-settings>=2.14.1",
|
|
38
38
|
"redis[hiredis]>=7.4.0,<8",
|
|
39
39
|
]
|
|
40
|
-
version = "1.0.0.
|
|
40
|
+
version = "1.0.0.dev12"
|
|
41
41
|
|
|
42
42
|
[project.optional-dependencies]
|
|
43
43
|
performance = [ "uvloop>=0.21" ]
|
|
@@ -274,6 +274,8 @@
|
|
|
274
274
|
[tool.mypy]
|
|
275
275
|
exclude = [ "examples", "tests", "scripts" ]
|
|
276
276
|
ignore_missing_imports = true
|
|
277
|
+
warn_unused_ignores = true
|
|
278
|
+
warn_redundant_casts = true
|
|
277
279
|
|
|
278
280
|
[tool.pytest.ini_options]
|
|
279
281
|
|
|
@@ -294,6 +296,7 @@
|
|
|
294
296
|
"contract: marks gRPC proto contract verification tests",
|
|
295
297
|
"e2e: marks end-to-end tests requiring full Docker Compose stack",
|
|
296
298
|
"edge_case: marks tests for boundary conditions and edge cases",
|
|
299
|
+
"flaky: marks known-flaky tests for the quarantine plugin (tests/fixtures/flakiness.py)",
|
|
297
300
|
"grpc: marks tests for gRPC service functionality",
|
|
298
301
|
"idempotency: marks tests for retry and duplicate request handling",
|
|
299
302
|
"integration: marks tests that require external service connections (deselect with '-m \"not integration\"')",
|
|
@@ -4,28 +4,24 @@ Adapters, converters, and HITL helpers for building DigitalKin modules
|
|
|
4
4
|
on top of the Agno agent framework. Exports:
|
|
5
5
|
|
|
6
6
|
- :class:`AgnoStreamAdapter` — Agno streaming events → DigitalKin events.
|
|
7
|
-
- :
|
|
8
|
-
|
|
7
|
+
- :class:`AguiTools` — register AG-UI client-side (frontend) tools as Agno
|
|
8
|
+
external Functions.
|
|
9
9
|
- :class:`AgnoHitlRunner`, :class:`PausedRunStore`, :class:`PauseInfo`,
|
|
10
10
|
:class:`PausedRunRecord`, :data:`HITL_STORAGE_CONFIG`,
|
|
11
|
-
:
|
|
12
|
-
|
|
11
|
+
:class:`HitlEvents` — human-in-the-loop (HITL) runner that persists a
|
|
12
|
+
paused Agno run via the module's
|
|
13
13
|
:class:`~digitalkin.services.storage.StorageStrategy` and resumes it
|
|
14
14
|
when the front replies with a ``ToolMessage``.
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
17
|
from digitalkin.community.agno.agno_adapter import AgnoStreamAdapter
|
|
18
|
-
from digitalkin.community.agno.agui_tools import
|
|
19
|
-
agui_tool_to_external_function,
|
|
20
|
-
make_tools_factory,
|
|
21
|
-
)
|
|
18
|
+
from digitalkin.community.agno.agui_tools import AguiTools
|
|
22
19
|
from digitalkin.community.agno.hitl import (
|
|
23
20
|
HITL_STORAGE_CONFIG,
|
|
24
21
|
AgnoHitlRunner,
|
|
22
|
+
HitlEvents,
|
|
25
23
|
PausedRunRecord,
|
|
26
24
|
PausedRunStore,
|
|
27
|
-
emit_awaiting_tool_result,
|
|
28
|
-
emit_messages_snapshot,
|
|
29
25
|
)
|
|
30
26
|
from digitalkin.community.agno.models import PauseInfo
|
|
31
27
|
|
|
@@ -33,11 +29,9 @@ __all__ = [
|
|
|
33
29
|
"HITL_STORAGE_CONFIG",
|
|
34
30
|
"AgnoHitlRunner",
|
|
35
31
|
"AgnoStreamAdapter",
|
|
32
|
+
"AguiTools",
|
|
33
|
+
"HitlEvents",
|
|
36
34
|
"PauseInfo",
|
|
37
35
|
"PausedRunRecord",
|
|
38
36
|
"PausedRunStore",
|
|
39
|
-
"agui_tool_to_external_function",
|
|
40
|
-
"emit_awaiting_tool_result",
|
|
41
|
-
"emit_messages_snapshot",
|
|
42
|
-
"make_tools_factory",
|
|
43
37
|
]
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""AG-UI frontend tools → Agno external Functions.
|
|
2
|
+
|
|
3
|
+
The AG-UI protocol lets the client declare its own tools in
|
|
4
|
+
``RunAgentInput.tools``, meant to be executed on the frontend rather than
|
|
5
|
+
by the agent process. :class:`AguiTools` exposes them to an Agno agent as
|
|
6
|
+
:class:`~agno.tools.function.Function` objects marked
|
|
7
|
+
``external_execution=True``: when the LLM "calls" one, Agno pauses the run
|
|
8
|
+
instead of executing an entrypoint, letting the caller stream the tool-call
|
|
9
|
+
events to the front and resume later.
|
|
10
|
+
|
|
11
|
+
See ``examples/`` and the :class:`~digitalkin.community.agno.AgnoHitlRunner`
|
|
12
|
+
docstring for end-to-end usage.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from typing import TYPE_CHECKING, Any
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from collections.abc import Callable
|
|
21
|
+
|
|
22
|
+
from ag_ui.core.types import Tool as AgUiTool
|
|
23
|
+
from agno.run.base import RunContext
|
|
24
|
+
from agno.tools.function import Function
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class AguiTools:
|
|
28
|
+
"""Convert AG-UI frontend tool declarations into Agno external Functions."""
|
|
29
|
+
|
|
30
|
+
@staticmethod
|
|
31
|
+
def _unreachable_entrypoint(**_: Any) -> None:
|
|
32
|
+
"""Placeholder — never invoked because ``external_execution=True`` pauses the run."""
|
|
33
|
+
|
|
34
|
+
@staticmethod
|
|
35
|
+
def agui_tool_to_external_function(tool: AgUiTool) -> Function:
|
|
36
|
+
"""Wrap an AG-UI tool definition as an Agno external ``Function``.
|
|
37
|
+
|
|
38
|
+
The resulting :class:`Function` carries the AG-UI schema as-is and is
|
|
39
|
+
marked ``external_execution=True`` so Agno emits the tool-call events
|
|
40
|
+
but skips the entrypoint and pauses the run when the LLM invokes it.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
tool: An :class:`ag_ui.core.types.Tool` from ``RunAgentInput.tools``.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
An :class:`agno.tools.function.Function` ready to plug into an agent.
|
|
47
|
+
"""
|
|
48
|
+
from agno.tools.function import Function # pyright: ignore[reportMissingImports]
|
|
49
|
+
|
|
50
|
+
parameters = tool.parameters or {"type": "object", "properties": {}, "required": []}
|
|
51
|
+
return Function(
|
|
52
|
+
name=tool.name,
|
|
53
|
+
description=tool.description,
|
|
54
|
+
parameters=parameters,
|
|
55
|
+
entrypoint=AguiTools._unreachable_entrypoint,
|
|
56
|
+
external_execution=True,
|
|
57
|
+
skip_entrypoint_processing=True,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
@staticmethod
|
|
61
|
+
def make_tools_factory(
|
|
62
|
+
base_tools: list[Any],
|
|
63
|
+
dependency_key: str = "agui_tools",
|
|
64
|
+
) -> Callable[[RunContext], list[Any]]:
|
|
65
|
+
"""Build an Agno ``tools`` factory merging base tools with per-run AG-UI tools.
|
|
66
|
+
|
|
67
|
+
The returned callable is the value passed to ``Agent(tools=...)``. On
|
|
68
|
+
every run Agno resolves it with the current ``RunContext``; the factory
|
|
69
|
+
reads ``run_context.dependencies[dependency_key]`` (the per-run AG-UI
|
|
70
|
+
tool list), converts them to external Functions, and concatenates them
|
|
71
|
+
with ``base_tools``.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
base_tools: Toolkits / Functions always available, passed through.
|
|
75
|
+
dependency_key: Key in ``run_context.dependencies`` for the per-run
|
|
76
|
+
AG-UI tool list. Defaults to ``"agui_tools"``.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
A callable for ``Agent(tools=...)``. Set ``cache_callables=False``
|
|
80
|
+
so it is re-invoked every run.
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
def factory(run_context: RunContext | None = None) -> list[Any]:
|
|
84
|
+
if run_context is None:
|
|
85
|
+
return list(base_tools)
|
|
86
|
+
deps = getattr(run_context, "dependencies", None) or {}
|
|
87
|
+
agui_tools: list[AgUiTool] = deps.get(dependency_key) or []
|
|
88
|
+
return [*base_tools, *[AguiTools.agui_tool_to_external_function(t) for t in agui_tools]]
|
|
89
|
+
|
|
90
|
+
return factory
|
|
@@ -124,169 +124,173 @@ class PausedRunStore:
|
|
|
124
124
|
await self._storage.remove(collection=self.COLLECTION, record_id=thread_id)
|
|
125
125
|
|
|
126
126
|
|
|
127
|
-
|
|
128
|
-
"""
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
127
|
+
class HitlEvents:
|
|
128
|
+
"""AG-UI message conversion and event emission for the HITL flow."""
|
|
129
|
+
|
|
130
|
+
@staticmethod
|
|
131
|
+
def agno_messages_to_agui(agno_messages: list[Any]) -> list[AgUiMessage]:
|
|
132
|
+
"""Convert Agno messages into AG-UI messages.
|
|
133
|
+
|
|
134
|
+
Drops system/developer/reasoning; reshapes assistant ``tool_calls``
|
|
135
|
+
into AG-UI :class:`~ag_ui.core.types.ToolCall` objects.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
agno_messages: Value of ``RunOutput.messages`` at pause time.
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
AG-UI :class:`~ag_ui.core.types.Message` instances.
|
|
142
|
+
"""
|
|
143
|
+
from ag_ui.core.types import (
|
|
144
|
+
AssistantMessage as AgUiAssistantMessage,
|
|
145
|
+
)
|
|
146
|
+
from ag_ui.core.types import (
|
|
147
|
+
FunctionCall as AgUiFunctionCall,
|
|
148
|
+
)
|
|
149
|
+
from ag_ui.core.types import (
|
|
150
|
+
ToolCall as AgUiToolCall,
|
|
151
|
+
)
|
|
152
|
+
from ag_ui.core.types import (
|
|
153
|
+
ToolMessage as AgUiToolMessage,
|
|
154
|
+
)
|
|
155
|
+
from ag_ui.core.types import (
|
|
156
|
+
UserMessage as AgUiUserMessage,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
result: list[AgUiMessage] = []
|
|
160
|
+
for msg in agno_messages or []:
|
|
161
|
+
role = getattr(msg, "role", None)
|
|
162
|
+
msg_id = getattr(msg, "id", None) or ""
|
|
163
|
+
content = getattr(msg, "content", None)
|
|
164
|
+
if isinstance(content, list):
|
|
165
|
+
content = " ".join(str(part) for part in content if part is not None)
|
|
166
|
+
|
|
167
|
+
if role == "user":
|
|
168
|
+
result.append(AgUiUserMessage(id=msg_id, role="user", content=content or ""))
|
|
169
|
+
elif role == "assistant":
|
|
170
|
+
raw_calls = getattr(msg, "tool_calls", None) or []
|
|
171
|
+
agui_tool_calls: list[AgUiToolCall] = []
|
|
172
|
+
for tc in raw_calls:
|
|
173
|
+
tc_id = tc.get("id") if isinstance(tc, dict) else getattr(tc, "id", None)
|
|
174
|
+
func = tc.get("function") if isinstance(tc, dict) else getattr(tc, "function", None)
|
|
175
|
+
if not tc_id or func is None:
|
|
176
|
+
continue
|
|
177
|
+
func_name = func.get("name") if isinstance(func, dict) else getattr(func, "name", None)
|
|
178
|
+
func_args = func.get("arguments") if isinstance(func, dict) else getattr(func, "arguments", None)
|
|
179
|
+
if not isinstance(func_args, str):
|
|
180
|
+
func_args = json.dumps(func_args) if func_args is not None else "{}"
|
|
181
|
+
agui_tool_calls.append(
|
|
182
|
+
AgUiToolCall(
|
|
183
|
+
id=tc_id,
|
|
184
|
+
type="function",
|
|
185
|
+
function=AgUiFunctionCall(name=func_name or "", arguments=func_args),
|
|
186
|
+
)
|
|
187
|
+
)
|
|
188
|
+
result.append(
|
|
189
|
+
AgUiAssistantMessage(
|
|
190
|
+
id=msg_id,
|
|
191
|
+
role="assistant",
|
|
192
|
+
content=content if isinstance(content, str) else None,
|
|
193
|
+
tool_calls=agui_tool_calls or None,
|
|
182
194
|
)
|
|
183
195
|
)
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
196
|
+
elif role == "tool":
|
|
197
|
+
tool_call_id = getattr(msg, "tool_call_id", None)
|
|
198
|
+
if not tool_call_id:
|
|
199
|
+
continue
|
|
200
|
+
result.append(
|
|
201
|
+
AgUiToolMessage(
|
|
202
|
+
id=msg_id,
|
|
203
|
+
role="tool",
|
|
204
|
+
tool_call_id=tool_call_id,
|
|
205
|
+
content=content if isinstance(content, str) else "",
|
|
206
|
+
)
|
|
190
207
|
)
|
|
208
|
+
return result
|
|
209
|
+
|
|
210
|
+
@staticmethod
|
|
211
|
+
async def emit_messages_snapshot(
|
|
212
|
+
context: ModuleContext,
|
|
213
|
+
messages: list[AgUiMessage],
|
|
214
|
+
) -> None:
|
|
215
|
+
"""Emit an AG-UI ``MessagesSnapshot`` event.
|
|
216
|
+
|
|
217
|
+
Typically called just before :func:`emit_awaiting_tool_result` on a
|
|
218
|
+
paused run so the front has an authoritative view of the conversation
|
|
219
|
+
(including the assistant message carrying the frontend ``tool_calls``,
|
|
220
|
+
which cannot be reconstructed from the streamed tool-call events alone).
|
|
221
|
+
|
|
222
|
+
Args:
|
|
223
|
+
context: Current module context.
|
|
224
|
+
messages: List of AG-UI messages, typically produced by
|
|
225
|
+
:func:`agno_messages_to_agui` from ``RunOutput.messages``.
|
|
226
|
+
"""
|
|
227
|
+
if not messages:
|
|
228
|
+
return
|
|
229
|
+
|
|
230
|
+
from ag_ui.core.events import MessagesSnapshotEvent as AgUiMessagesSnapshotEvent
|
|
231
|
+
|
|
232
|
+
from digitalkin.models.module.ag_ui import (
|
|
233
|
+
AgUiMessagesSnapshotOutput,
|
|
234
|
+
AgUiOutput,
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
output = AgUiOutput(
|
|
238
|
+
root=AgUiMessagesSnapshotOutput(
|
|
239
|
+
event=AgUiMessagesSnapshotEvent(messages=messages),
|
|
191
240
|
)
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
241
|
+
)
|
|
242
|
+
await context.callbacks.send_message(output)
|
|
243
|
+
logger.info("emit_messages_snapshot: sent %d message(s)", len(messages))
|
|
244
|
+
|
|
245
|
+
@staticmethod
|
|
246
|
+
async def emit_awaiting_tool_result(
|
|
247
|
+
context: ModuleContext,
|
|
248
|
+
*,
|
|
249
|
+
thread_id: str,
|
|
250
|
+
run_id: str,
|
|
251
|
+
pending_tool_call_ids: list[str],
|
|
252
|
+
) -> None:
|
|
253
|
+
"""Emit an AG-UI ``RunFinished`` with ``status="awaiting_tool_result"``.
|
|
254
|
+
|
|
255
|
+
This is the protocol signal telling the front "the run paused on a
|
|
256
|
+
client-side tool; execute it and reply with a ``ToolMessage``". It
|
|
257
|
+
goes out via ``context.callbacks.send_message`` (bypassing the
|
|
258
|
+
standard :class:`~digitalkin.mixins.agui_mixin.AgUiMixin` event
|
|
259
|
+
mapping, which has no notion of an "awaiting" status).
|
|
260
|
+
|
|
261
|
+
Args:
|
|
262
|
+
context: Current module context.
|
|
263
|
+
thread_id: AG-UI thread identifier.
|
|
264
|
+
run_id: Run identifier to echo back in the finished event.
|
|
265
|
+
pending_tool_call_ids: The ``tool_call_id`` values the front must
|
|
266
|
+
execute and resolve — echoed in ``result.pending_tool_call_ids``
|
|
267
|
+
so the front can match them.
|
|
268
|
+
"""
|
|
269
|
+
from ag_ui.core.events import RunFinishedEvent as AgUiRunFinishedEvent
|
|
270
|
+
|
|
271
|
+
from digitalkin.models.module.ag_ui import (
|
|
272
|
+
AgUiOutput,
|
|
273
|
+
AgUiRunFinishedOutput,
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
output = AgUiOutput(
|
|
277
|
+
root=AgUiRunFinishedOutput(
|
|
278
|
+
event=AgUiRunFinishedEvent(
|
|
279
|
+
thread_id=thread_id,
|
|
280
|
+
run_id=run_id,
|
|
281
|
+
result={
|
|
282
|
+
"status": _AWAITING_STATUS,
|
|
283
|
+
"pending_tool_call_ids": pending_tool_call_ids,
|
|
284
|
+
},
|
|
202
285
|
)
|
|
203
286
|
)
|
|
204
|
-
return result
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
async def emit_messages_snapshot(
|
|
208
|
-
context: ModuleContext,
|
|
209
|
-
messages: list[AgUiMessage],
|
|
210
|
-
) -> None:
|
|
211
|
-
"""Emit an AG-UI ``MessagesSnapshot`` event.
|
|
212
|
-
|
|
213
|
-
Typically called just before :func:`emit_awaiting_tool_result` on a
|
|
214
|
-
paused run so the front has an authoritative view of the conversation
|
|
215
|
-
(including the assistant message carrying the frontend ``tool_calls``,
|
|
216
|
-
which cannot be reconstructed from the streamed tool-call events alone).
|
|
217
|
-
|
|
218
|
-
Args:
|
|
219
|
-
context: Current module context.
|
|
220
|
-
messages: List of AG-UI messages, typically produced by
|
|
221
|
-
:func:`_agno_messages_to_agui` from ``RunOutput.messages``.
|
|
222
|
-
"""
|
|
223
|
-
if not messages:
|
|
224
|
-
return
|
|
225
|
-
|
|
226
|
-
from ag_ui.core.events import MessagesSnapshotEvent as AgUiMessagesSnapshotEvent
|
|
227
|
-
|
|
228
|
-
from digitalkin.models.module.ag_ui import (
|
|
229
|
-
AgUiMessagesSnapshotOutput,
|
|
230
|
-
AgUiOutput,
|
|
231
|
-
)
|
|
232
|
-
|
|
233
|
-
output = AgUiOutput(
|
|
234
|
-
root=AgUiMessagesSnapshotOutput(
|
|
235
|
-
event=AgUiMessagesSnapshotEvent(messages=messages),
|
|
236
287
|
)
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
async def emit_awaiting_tool_result(
|
|
243
|
-
context: ModuleContext,
|
|
244
|
-
*,
|
|
245
|
-
thread_id: str,
|
|
246
|
-
run_id: str,
|
|
247
|
-
pending_tool_call_ids: list[str],
|
|
248
|
-
) -> None:
|
|
249
|
-
"""Emit an AG-UI ``RunFinished`` with ``status="awaiting_tool_result"``.
|
|
250
|
-
|
|
251
|
-
This is the protocol signal telling the front "the run paused on a
|
|
252
|
-
client-side tool; execute it and reply with a ``ToolMessage``". It
|
|
253
|
-
goes out via ``context.callbacks.send_message`` (bypassing the
|
|
254
|
-
standard :class:`~digitalkin.mixins.agui_mixin.AgUiMixin` event
|
|
255
|
-
mapping, which has no notion of an "awaiting" status).
|
|
256
|
-
|
|
257
|
-
Args:
|
|
258
|
-
context: Current module context.
|
|
259
|
-
thread_id: AG-UI thread identifier.
|
|
260
|
-
run_id: Run identifier to echo back in the finished event.
|
|
261
|
-
pending_tool_call_ids: The ``tool_call_id`` values the front must
|
|
262
|
-
execute and resolve — echoed in ``result.pending_tool_call_ids``
|
|
263
|
-
so the front can match them.
|
|
264
|
-
"""
|
|
265
|
-
from ag_ui.core.events import RunFinishedEvent as AgUiRunFinishedEvent
|
|
266
|
-
|
|
267
|
-
from digitalkin.models.module.ag_ui import (
|
|
268
|
-
AgUiOutput,
|
|
269
|
-
AgUiRunFinishedOutput,
|
|
270
|
-
)
|
|
271
|
-
|
|
272
|
-
output = AgUiOutput(
|
|
273
|
-
root=AgUiRunFinishedOutput(
|
|
274
|
-
event=AgUiRunFinishedEvent(
|
|
275
|
-
thread_id=thread_id,
|
|
276
|
-
run_id=run_id,
|
|
277
|
-
result={
|
|
278
|
-
"status": _AWAITING_STATUS,
|
|
279
|
-
"pending_tool_call_ids": pending_tool_call_ids,
|
|
280
|
-
},
|
|
281
|
-
)
|
|
288
|
+
await context.callbacks.send_message(output)
|
|
289
|
+
logger.info(
|
|
290
|
+
"emit_awaiting_tool_result: thread_id=%s pending=%s",
|
|
291
|
+
thread_id,
|
|
292
|
+
pending_tool_call_ids,
|
|
282
293
|
)
|
|
283
|
-
)
|
|
284
|
-
await context.callbacks.send_message(output)
|
|
285
|
-
logger.info(
|
|
286
|
-
"emit_awaiting_tool_result: thread_id=%s pending=%s",
|
|
287
|
-
thread_id,
|
|
288
|
-
pending_tool_call_ids,
|
|
289
|
-
)
|
|
290
294
|
|
|
291
295
|
|
|
292
296
|
class AgnoHitlRunner:
|
|
@@ -559,7 +563,7 @@ class AgnoHitlRunner:
|
|
|
559
563
|
resumed, pause_info = await self.try_resume(input_data=input_data, send=send)
|
|
560
564
|
if resumed:
|
|
561
565
|
if pause_info is not None and context is not None:
|
|
562
|
-
await emit_awaiting_tool_result(
|
|
566
|
+
await HitlEvents.emit_awaiting_tool_result(
|
|
563
567
|
context,
|
|
564
568
|
thread_id=pause_info.thread_id,
|
|
565
569
|
run_id=pause_info.run_id,
|
|
@@ -586,7 +590,7 @@ class AgnoHitlRunner:
|
|
|
586
590
|
images=images,
|
|
587
591
|
)
|
|
588
592
|
if pause_info is not None and context is not None:
|
|
589
|
-
await emit_awaiting_tool_result(
|
|
593
|
+
await HitlEvents.emit_awaiting_tool_result(
|
|
590
594
|
context,
|
|
591
595
|
thread_id=pause_info.thread_id,
|
|
592
596
|
run_id=pause_info.run_id,
|
|
@@ -625,7 +629,7 @@ class AgnoHitlRunner:
|
|
|
625
629
|
if adapter.is_paused and final_run_output is not None and getattr(final_run_output, "is_paused", False):
|
|
626
630
|
pause_info = await self._store.save(run_output=final_run_output, thread_id=thread_id)
|
|
627
631
|
# Attach AG-UI-shaped messages so the front can materialise the tool_call.
|
|
628
|
-
pause_info.new_messages =
|
|
632
|
+
pause_info.new_messages = HitlEvents.agno_messages_to_agui(final_run_output.messages or [])
|
|
629
633
|
return pause_info
|
|
630
634
|
|
|
631
635
|
return None
|
|
@@ -202,3 +202,37 @@ class BaseJobManager(abc.ABC, Generic[InputModelT, OutputModelT, SetupModelT]):
|
|
|
202
202
|
Returns:
|
|
203
203
|
dict[str, dict[str, Any]]: A dictionary containing information about all modules and their statuses.
|
|
204
204
|
"""
|
|
205
|
+
|
|
206
|
+
@abc.abstractmethod
|
|
207
|
+
async def preload_instance(
|
|
208
|
+
self,
|
|
209
|
+
setup_data: SetupModelT,
|
|
210
|
+
mission_id: str,
|
|
211
|
+
setup_id: str,
|
|
212
|
+
setup_version_id: str,
|
|
213
|
+
request_metadata: dict[str, str] | None = None,
|
|
214
|
+
job_id: str | None = None,
|
|
215
|
+
tool_cache: Any = None,
|
|
216
|
+
callback: Callable | None = None,
|
|
217
|
+
) -> tuple[Any, str, Callable]:
|
|
218
|
+
"""Build a module instance and run its idempotent ``prepare()``.
|
|
219
|
+
|
|
220
|
+
Returns:
|
|
221
|
+
Tuple of (prepared module instance, job_id, output callback).
|
|
222
|
+
"""
|
|
223
|
+
|
|
224
|
+
@abc.abstractmethod
|
|
225
|
+
async def run_instance(
|
|
226
|
+
self,
|
|
227
|
+
module: Any,
|
|
228
|
+
job_id: str,
|
|
229
|
+
mission_id: str,
|
|
230
|
+
input_data: InputModelT,
|
|
231
|
+
setup_data: SetupModelT,
|
|
232
|
+
callback: Callable,
|
|
233
|
+
) -> str:
|
|
234
|
+
"""Run a pre-prepared module instance (from ``preload_instance``) with input.
|
|
235
|
+
|
|
236
|
+
Returns:
|
|
237
|
+
The job_id of the scheduled run.
|
|
238
|
+
"""
|
|
@@ -273,6 +273,8 @@ class SingleJobManager(BaseJobManager[InputModelT, OutputModelT, SetupModelT]):
|
|
|
273
273
|
timer.mark("redis_task_manager")
|
|
274
274
|
|
|
275
275
|
if callback is None:
|
|
276
|
+
if self._stream_writers is None: # safety when __init__ was bypassed (e.g. object.__new__)
|
|
277
|
+
self._stream_writers = {}
|
|
276
278
|
self._stream_writers[job_id] = RedisStreamWriter(job_id, self._redis_client)
|
|
277
279
|
callback = await self.job_specific_callback(self.add_to_queue, job_id)
|
|
278
280
|
timer.mark("default_callback")
|
{digitalkin-1.0.0.dev10 → digitalkin-1.0.0.dev12}/src/digitalkin/core/task_manager/module_runner.py
RENAMED
|
@@ -14,9 +14,7 @@ from digitalkin.core.profiling.step_timer import StepTimer
|
|
|
14
14
|
from digitalkin.core.profiling.task_profiler import TaskProfiler
|
|
15
15
|
from digitalkin.logger import logger
|
|
16
16
|
from digitalkin.models.grpc_servers.stream_error_codes import StreamErrorCode
|
|
17
|
-
from digitalkin.models.settings.profiling import ProfilerMode,
|
|
18
|
-
|
|
19
|
-
_PROFILING = ProfilingSettings()
|
|
17
|
+
from digitalkin.models.settings.profiling import ProfilerMode, get_profiling_settings
|
|
20
18
|
|
|
21
19
|
if TYPE_CHECKING:
|
|
22
20
|
from collections.abc import Awaitable, Callable
|
|
@@ -65,12 +63,13 @@ class ModuleRunner:
|
|
|
65
63
|
timer = StepTimer()
|
|
66
64
|
|
|
67
65
|
# Construct profiler outside try so finally can always stop it.
|
|
66
|
+
profiling = get_profiling_settings()
|
|
68
67
|
profiler_mode = (
|
|
69
|
-
ProfilerMode(
|
|
70
|
-
if
|
|
68
|
+
ProfilerMode(profiling.profiler)
|
|
69
|
+
if profiling.profiler in {p.value for p in ProfilerMode}
|
|
71
70
|
else ProfilerMode.NONE
|
|
72
71
|
)
|
|
73
|
-
profiler = TaskProfiler(task_id=task_id, mode=profiler_mode, output_dir=
|
|
72
|
+
profiler = TaskProfiler(task_id=task_id, mode=profiler_mode, output_dir=profiling.profile_output_dir)
|
|
74
73
|
|
|
75
74
|
try:
|
|
76
75
|
timer.mark("entry")
|
|
@@ -15,8 +15,6 @@ if TYPE_CHECKING:
|
|
|
15
15
|
|
|
16
16
|
from digitalkin.logger import logger
|
|
17
17
|
|
|
18
|
-
_MIN_KEY_PARTS_FOR_REDACTION = 2
|
|
19
|
-
|
|
20
18
|
|
|
21
19
|
class InstrumentedRedisClient: # noqa: PLR0904
|
|
22
20
|
"""Observability wrapper around RedisClient.
|
|
@@ -52,8 +50,8 @@ class InstrumentedRedisClient: # noqa: PLR0904
|
|
|
52
50
|
parts = key.split(":")
|
|
53
51
|
if len(parts) <= 1:
|
|
54
52
|
return key
|
|
55
|
-
if len(parts) >
|
|
56
|
-
return ":".join(parts[0:1] + ["*"] * (len(parts) -
|
|
53
|
+
if len(parts) > 2: # noqa: PLR2004
|
|
54
|
+
return ":".join(parts[0:1] + ["*"] * (len(parts) - 2) + parts[-1:])
|
|
57
55
|
return f"{parts[0]}:*"
|
|
58
56
|
|
|
59
57
|
async def _execute(self, command: str, key: str, coro: Any) -> Any:
|