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