digitalkin 0.3.2a2__tar.gz → 0.3.2.dev2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/PKG-INFO +9 -9
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/pyproject.toml +108 -108
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/__version__.py +1 -1
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/core/job_manager/single_job_manager.py +36 -78
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/core/job_manager/taskiq_job_manager.py +4 -8
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/core/task_manager/base_task_manager.py +1 -3
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/core/task_manager/surrealdb_repository.py +0 -6
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/core/task_manager/task_executor.py +10 -27
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/core/task_manager/task_session.py +99 -121
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/grpc_servers/module_server.py +43 -26
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/grpc_servers/module_servicer.py +12 -114
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/grpc_servers/utils/grpc_client_wrapper.py +4 -14
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/grpc_servers/utils/utility_schema_extender.py +4 -13
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/models/core/task_monitor.py +1 -23
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/models/grpc_servers/models.py +8 -95
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/models/module/__init__.py +2 -18
- digitalkin-0.3.2.dev2/src/digitalkin/models/module/module_context.py +149 -0
- digitalkin-0.3.2.dev2/src/digitalkin/models/module/module_types.py +393 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/models/module/utility.py +1 -22
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/models/services/cost.py +1 -22
- digitalkin-0.3.2.dev2/src/digitalkin/models/services/registry.py +42 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/modules/_base_module.py +47 -137
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/modules/triggers/__init__.py +4 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/communication/communication_strategy.py +3 -14
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/communication/default_communication.py +0 -3
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/communication/grpc_communication.py +17 -58
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/cost/cost_strategy.py +14 -36
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/cost/default_cost.py +1 -61
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/cost/grpc_cost.py +1 -97
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/filesystem/grpc_filesystem.py +1 -8
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/registry/__init__.py +1 -1
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/registry/default_registry.py +1 -22
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/registry/grpc_registry.py +1 -77
- digitalkin-0.3.2.dev2/src/digitalkin/services/registry/registry_models.py +43 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/registry/registry_strategy.py +1 -19
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/user_profile/user_profile_strategy.py +15 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/utils/__init__.py +3 -15
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/utils/dynamic_schema.py +0 -4
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin.egg-info/PKG-INFO +9 -9
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin.egg-info/SOURCES.txt +1 -14
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin.egg-info/requires.txt +2 -2
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin.egg-info/top_level.txt +0 -1
- digitalkin-0.3.2a2/examples/modules/archetype_with_tools_module.py +0 -232
- digitalkin-0.3.2a2/examples/monitoring/digitalkin_observability/__init__.py +0 -46
- digitalkin-0.3.2a2/examples/monitoring/digitalkin_observability/http_server.py +0 -150
- digitalkin-0.3.2a2/examples/monitoring/digitalkin_observability/interceptors.py +0 -176
- digitalkin-0.3.2a2/examples/monitoring/digitalkin_observability/metrics.py +0 -201
- digitalkin-0.3.2a2/examples/monitoring/digitalkin_observability/prometheus.py +0 -137
- digitalkin-0.3.2a2/examples/monitoring/tests/test_metrics.py +0 -172
- digitalkin-0.3.2a2/src/digitalkin/models/module/base_types.py +0 -61
- digitalkin-0.3.2a2/src/digitalkin/models/module/module_context.py +0 -406
- digitalkin-0.3.2a2/src/digitalkin/models/module/module_types.py +0 -29
- digitalkin-0.3.2a2/src/digitalkin/models/module/setup_types.py +0 -547
- digitalkin-0.3.2a2/src/digitalkin/models/module/tool_cache.py +0 -230
- digitalkin-0.3.2a2/src/digitalkin/models/module/tool_reference.py +0 -160
- digitalkin-0.3.2a2/src/digitalkin/models/services/registry.py +0 -77
- digitalkin-0.3.2a2/src/digitalkin/services/registry/registry_models.py +0 -15
- digitalkin-0.3.2a2/src/digitalkin/utils/conditional_schema.py +0 -260
- digitalkin-0.3.2a2/src/digitalkin/utils/schema_splitter.py +0 -290
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/LICENSE +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/README.md +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/examples/base_server/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/examples/base_server/mock/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/examples/base_server/mock/mock_pb2.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/examples/base_server/mock/mock_pb2_grpc.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/examples/base_server/server_async_insecure.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/examples/base_server/server_async_secure.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/examples/base_server/server_sync_insecure.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/examples/base_server/server_sync_secure.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/examples/modules/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/examples/modules/cpu_intensive_module.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/examples/modules/dynamic_setup_module.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/examples/modules/minimal_llm_module.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/examples/modules/text_transform_module.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/examples/services/filesystem_module.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/examples/services/storage_module.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/setup.cfg +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/core/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/core/common/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/core/common/factories.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/core/job_manager/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/core/job_manager/base_job_manager.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/core/job_manager/taskiq_broker.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/core/task_manager/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/core/task_manager/local_task_manager.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/core/task_manager/remote_task_manager.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/grpc_servers/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/grpc_servers/_base_server.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/grpc_servers/utils/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/grpc_servers/utils/exceptions.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/grpc_servers/utils/grpc_error_handler.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/logger.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/mixins/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/mixins/base_mixin.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/mixins/callback_mixin.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/mixins/chat_history_mixin.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/mixins/cost_mixin.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/mixins/file_history_mixin.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/mixins/filesystem_mixin.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/mixins/logger_mixin.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/mixins/storage_mixin.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/models/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/models/core/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/models/core/job_manager_models.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/models/grpc_servers/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/models/grpc_servers/types.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/models/module/module.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/models/services/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/models/services/storage.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/modules/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/modules/archetype_module.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/modules/tool_module.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/modules/trigger_handler.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/modules/triggers/healthcheck_ping_trigger.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/modules/triggers/healthcheck_services_trigger.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/modules/triggers/healthcheck_status_trigger.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/py.typed +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/agent/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/agent/agent_strategy.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/agent/default_agent.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/base_strategy.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/communication/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/cost/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/filesystem/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/filesystem/default_filesystem.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/filesystem/filesystem_strategy.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/identity/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/identity/default_identity.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/identity/identity_strategy.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/registry/exceptions.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/services_config.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/services_models.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/setup/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/setup/default_setup.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/setup/grpc_setup.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/setup/setup_strategy.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/snapshot/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/snapshot/default_snapshot.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/snapshot/snapshot_strategy.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/storage/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/storage/default_storage.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/storage/grpc_storage.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/storage/storage_strategy.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/user_profile/__init__.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/user_profile/default_user_profile.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/services/user_profile/grpc_user_profile.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/utils/arg_parser.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/utils/development_mode_action.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/utils/llm_ready_schema.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/utils/package_discover.py +0 -0
- {digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin.egg-info/dependency_links.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: digitalkin
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2.dev2
|
|
4
4
|
Summary: SDK to build kin used in DigitalKin
|
|
5
5
|
Author-email: "DigitalKin.ai" <contact@digitalkin.ai>
|
|
6
6
|
License: Attribution-NonCommercial-ShareAlike 4.0 International
|
|
@@ -434,32 +434,32 @@ License: Attribution-NonCommercial-ShareAlike 4.0 International
|
|
|
434
434
|
Creative Commons may be contacted at creativecommons.org.
|
|
435
435
|
https://creativecommons.org/licenses/by-nc-sa/4.0/
|
|
436
436
|
|
|
437
|
-
Project-URL: Documentation, https://github.com/DigitalKin-ai/digitalkin
|
|
438
437
|
Project-URL: Homepage, https://github.com/DigitalKin-ai/digitalkin
|
|
438
|
+
Project-URL: Documentation, https://github.com/DigitalKin-ai/digitalkin
|
|
439
439
|
Project-URL: Issues, https://github.com/DigitalKin-ai/digitalkin/issues
|
|
440
|
-
Keywords: agent,
|
|
440
|
+
Keywords: digitalkin,kin,agent,gprc,sdk
|
|
441
441
|
Classifier: Development Status :: 3 - Alpha
|
|
442
442
|
Classifier: Intended Audience :: Developers
|
|
443
|
-
Classifier: License :: Other/Proprietary License
|
|
444
443
|
Classifier: Operating System :: OS Independent
|
|
445
|
-
Classifier:
|
|
444
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
445
|
+
Classifier: Programming Language :: Python
|
|
446
446
|
Classifier: Programming Language :: Python :: 3.10
|
|
447
447
|
Classifier: Programming Language :: Python :: 3.11
|
|
448
448
|
Classifier: Programming Language :: Python :: 3.12
|
|
449
449
|
Classifier: Programming Language :: Python :: 3.13
|
|
450
|
-
Classifier: Programming Language :: Python
|
|
451
|
-
Classifier:
|
|
450
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
451
|
+
Classifier: License :: Other/Proprietary License
|
|
452
452
|
Requires-Python: >=3.10
|
|
453
453
|
Description-Content-Type: text/markdown
|
|
454
454
|
License-File: LICENSE
|
|
455
|
-
Requires-Dist: agentic-mesh-protocol==0.2.1.
|
|
455
|
+
Requires-Dist: agentic-mesh-protocol==0.2.1.dev0
|
|
456
456
|
Requires-Dist: grpcio-health-checking>=1.76.0
|
|
457
457
|
Requires-Dist: grpcio-reflection>=1.76.0
|
|
458
458
|
Requires-Dist: grpcio-status>=1.76.0
|
|
459
459
|
Requires-Dist: pydantic>=2.12.5
|
|
460
460
|
Requires-Dist: surrealdb>=1.0.7
|
|
461
461
|
Provides-Extra: taskiq
|
|
462
|
-
Requires-Dist: rstream>=0.40.
|
|
462
|
+
Requires-Dist: rstream>=0.40.0; extra == "taskiq"
|
|
463
463
|
Requires-Dist: taskiq-aio-pika>=0.5.0; extra == "taskiq"
|
|
464
464
|
Requires-Dist: taskiq-redis>=1.2.0; extra == "taskiq"
|
|
465
465
|
Requires-Dist: taskiq[reload]>=0.12.1; extra == "taskiq"
|
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
[build-system]
|
|
2
|
-
build-backend = "setuptools.build_meta"
|
|
3
2
|
requires = [ "setuptools >= 75.8.2", "wheel" ]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
|
|
7
|
-
description = "SDK to build kin used in DigitalKin"
|
|
8
|
-
license = { file = "LICENSE" }
|
|
9
7
|
name = "digitalkin"
|
|
8
|
+
description = "SDK to build kin used in DigitalKin"
|
|
10
9
|
readme = "README.md"
|
|
11
10
|
requires-python = ">=3.10"
|
|
11
|
+
license = { file = "LICENSE" }
|
|
12
12
|
|
|
13
|
-
keywords = [ "
|
|
13
|
+
keywords = [ "digitalkin", "kin", "agent", "gprc", "sdk" ]
|
|
14
14
|
|
|
15
|
+
version = "0.3.2.dev2"
|
|
15
16
|
classifiers = [
|
|
16
17
|
"Development Status :: 3 - Alpha",
|
|
17
18
|
"Intended Audience :: Developers",
|
|
18
|
-
"License :: Other/Proprietary License",
|
|
19
19
|
"Operating System :: OS Independent",
|
|
20
|
-
"
|
|
20
|
+
"Topic :: Software Development :: Libraries",
|
|
21
|
+
"Programming Language :: Python",
|
|
21
22
|
"Programming Language :: Python :: 3.10",
|
|
22
23
|
"Programming Language :: Python :: 3.11",
|
|
23
24
|
"Programming Language :: Python :: 3.12",
|
|
24
25
|
"Programming Language :: Python :: 3.13",
|
|
25
|
-
"Programming Language :: Python",
|
|
26
|
-
"
|
|
26
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
27
|
+
"License :: Other/Proprietary License",
|
|
27
28
|
]
|
|
28
|
-
version = "0.3.2.a2"
|
|
29
29
|
|
|
30
30
|
dependencies = [
|
|
31
|
-
"agentic-mesh-protocol==0.2.1.
|
|
31
|
+
"agentic-mesh-protocol==0.2.1.dev0",
|
|
32
32
|
"grpcio-health-checking>=1.76.0",
|
|
33
33
|
"grpcio-reflection>=1.76.0",
|
|
34
34
|
"grpcio-status>=1.76.0",
|
|
@@ -38,81 +38,81 @@
|
|
|
38
38
|
|
|
39
39
|
[project.optional-dependencies]
|
|
40
40
|
taskiq = [
|
|
41
|
-
"rstream>=0.40.
|
|
41
|
+
"rstream>=0.40.0",
|
|
42
42
|
"taskiq-aio-pika>=0.5.0",
|
|
43
43
|
"taskiq-redis>=1.2.0",
|
|
44
44
|
"taskiq[reload]>=0.12.1",
|
|
45
45
|
]
|
|
46
46
|
|
|
47
47
|
[project.urls]
|
|
48
|
-
Documentation = "https://github.com/DigitalKin-ai/digitalkin"
|
|
49
48
|
Homepage = "https://github.com/DigitalKin-ai/digitalkin"
|
|
49
|
+
Documentation = "https://github.com/DigitalKin-ai/digitalkin"
|
|
50
50
|
Issues = "https://github.com/DigitalKin-ai/digitalkin/issues"
|
|
51
51
|
|
|
52
52
|
[[project.authors]]
|
|
53
|
-
email = "contact@digitalkin.ai"
|
|
54
53
|
name = "DigitalKin.ai"
|
|
54
|
+
email = "contact@digitalkin.ai"
|
|
55
55
|
|
|
56
56
|
[dependency-groups]
|
|
57
|
+
dev = [
|
|
58
|
+
"typos>=1.40.0",
|
|
59
|
+
"ruff>=0.14.8",
|
|
60
|
+
"mypy>=1.19.0",
|
|
61
|
+
"pyright>=1.1.407",
|
|
62
|
+
"pre-commit>=4.5.0",
|
|
63
|
+
"bump-my-version>=1.2.4",
|
|
64
|
+
"build>=1.3.0",
|
|
65
|
+
"twine>=6.2.0",
|
|
66
|
+
"cryptography>=46.0.3",
|
|
67
|
+
]
|
|
57
68
|
tests = [
|
|
58
69
|
"freezegun>=1.5.5",
|
|
59
|
-
"grpcio-testing>=1.76.0",
|
|
60
70
|
"hdrhistogram>=0.10.3",
|
|
71
|
+
"grpcio-testing>=1.76.0",
|
|
61
72
|
"psutil>=7.1.3",
|
|
73
|
+
"pytest>=9.0.2",
|
|
62
74
|
"pytest-asyncio>=1.3.0",
|
|
63
75
|
"pytest-cov>=7.0.0",
|
|
64
|
-
"pytest-html==4.
|
|
76
|
+
"pytest-html==4.1.1",
|
|
65
77
|
"pytest-json-report==1.5.0",
|
|
66
78
|
"pytest-timeout>=2.4.0",
|
|
67
|
-
"pytest>=9.0.2",
|
|
68
|
-
]
|
|
69
|
-
dev = [
|
|
70
|
-
"build>=1.3.0",
|
|
71
|
-
"bump-my-version>=1.2.5",
|
|
72
|
-
"cryptography>=46.0.4",
|
|
73
|
-
"mypy>=1.19.1",
|
|
74
|
-
"pre-commit>=4.5.1",
|
|
75
|
-
"pyright>=1.1.407",
|
|
76
|
-
"ruff>=0.14.14",
|
|
77
|
-
"twine>=6.2.0",
|
|
78
|
-
"typos>=1.42.3",
|
|
79
79
|
]
|
|
80
80
|
docs = [
|
|
81
|
-
"
|
|
81
|
+
"mike>=2.1.3",
|
|
82
82
|
"markdown-callouts>=0.4.0",
|
|
83
83
|
"markdown-exec>=1.12.1",
|
|
84
|
-
"
|
|
84
|
+
"mkdocs>=1.6.1",
|
|
85
|
+
"mkdocs-coverage>=2.0.0",
|
|
86
|
+
"mkdocs-llmstxt>=0.5.0",
|
|
87
|
+
"mkdocs-redirects>=1.2.2",
|
|
88
|
+
"mkdocstrings>=1.0.0",
|
|
89
|
+
"griffe-inherited-docstrings>=1.1.2",
|
|
85
90
|
"mkdocs-autorefs>=1.4.3",
|
|
86
91
|
"mkdocs-awesome-pages-plugin>=2.10.1",
|
|
87
|
-
"mkdocs-coverage>=2.0.0",
|
|
88
92
|
"mkdocs-git-committers-plugin-2>=2.5.0",
|
|
89
|
-
"mkdocs-git-revision-date-localized-plugin>=1.5.
|
|
93
|
+
"mkdocs-git-revision-date-localized-plugin>=1.5.0",
|
|
90
94
|
"mkdocs-glightbox>=0.5.2",
|
|
91
|
-
"mkdocs-include-markdown-plugin>=7.2.
|
|
95
|
+
"mkdocs-include-markdown-plugin>=7.2.0",
|
|
92
96
|
"mkdocs-literate-nav>=0.6.2",
|
|
93
|
-
"mkdocs-llmstxt>=0.5.0",
|
|
94
97
|
"mkdocs-material[imaging]>=9.7.0",
|
|
95
98
|
"mkdocs-minify-plugin>=0.8.0",
|
|
96
|
-
"mkdocs-open-in-new-tab>=1.0.8",
|
|
97
|
-
"mkdocs-redirects>=1.2.2",
|
|
98
99
|
"mkdocs-section-index>=0.3.10",
|
|
99
|
-
"mkdocs>=1.6.1",
|
|
100
100
|
"mkdocstrings-python>=2.0.1",
|
|
101
|
-
"
|
|
101
|
+
"mkdocs-open-in-new-tab>=1.0.8",
|
|
102
102
|
"tomli>=2.3.0",
|
|
103
103
|
]
|
|
104
104
|
[tool.setuptools]
|
|
105
105
|
package-dir = { "" = "src" }
|
|
106
106
|
|
|
107
107
|
[tool.setuptools.packages.find]
|
|
108
|
-
where = [ "
|
|
109
|
-
[tool.ruff]
|
|
108
|
+
where = [ "src", "examples" ]
|
|
110
109
|
|
|
111
|
-
|
|
112
|
-
line-length = 120
|
|
113
|
-
show-fixes = true
|
|
110
|
+
[tool.ruff]
|
|
114
111
|
src = [ "src" ]
|
|
115
112
|
target-version = "py310"
|
|
113
|
+
line-length = 120
|
|
114
|
+
indent-width = 4
|
|
115
|
+
show-fixes = true
|
|
116
116
|
unsafe-fixes = true
|
|
117
117
|
# Enable preview features.
|
|
118
118
|
exclude = [
|
|
@@ -135,59 +135,59 @@
|
|
|
135
135
|
"buck-out",
|
|
136
136
|
"build",
|
|
137
137
|
"dist",
|
|
138
|
-
"
|
|
139
|
-
"
|
|
138
|
+
"node_modules",
|
|
139
|
+
"venv",
|
|
140
140
|
"factory.py",
|
|
141
141
|
"generate_certificates.py",
|
|
142
|
-
"
|
|
142
|
+
"examples/*",
|
|
143
143
|
"tests/*",
|
|
144
|
-
"
|
|
144
|
+
"docs/*",
|
|
145
145
|
]
|
|
146
146
|
preview = true
|
|
147
147
|
|
|
148
148
|
[tool.ruff.lint]
|
|
149
149
|
select = [
|
|
150
|
-
"A", # flake8-builtins
|
|
151
150
|
"ANN", # flake8-annotations
|
|
152
|
-
"ARG", # flake8-unused-arguments
|
|
153
151
|
"ASYNC", # flake8-async
|
|
154
|
-
"
|
|
155
|
-
"
|
|
152
|
+
"S", # flake8-bandit
|
|
153
|
+
"FBT", # flake8-boolean-trap
|
|
154
|
+
"A", # flake8-builtins
|
|
156
155
|
"COM", # flake8-commas
|
|
157
|
-
"
|
|
158
|
-
"DOC", # pydoclint
|
|
156
|
+
"C4", # flake8-comprehensions
|
|
159
157
|
"DTZ", # flake8-datetimez
|
|
160
|
-
"E", # pycodestyle-errors
|
|
161
158
|
"EM", # flake8-errmsg
|
|
162
|
-
"ERA", # eradicate
|
|
163
|
-
"F", # pyflakes
|
|
164
|
-
"FBT", # flake8-boolean-trap
|
|
165
|
-
"FLY", # flynt
|
|
166
|
-
"FURB", # Refurb
|
|
167
|
-
"G", # flake8-logging-format
|
|
168
|
-
"I", # isort
|
|
169
|
-
"ICN", # flake8-import-conventions
|
|
170
159
|
"ISC", # flake8-implicit-str-concat
|
|
160
|
+
"ICN", # flake8-import-conventions
|
|
161
|
+
"G", # flake8-logging-format
|
|
171
162
|
"LOG", # flake8-logging
|
|
172
|
-
"N", # pep8-naming
|
|
173
|
-
"PERF", # Perflint
|
|
174
163
|
"PIE", # flake8-pie
|
|
175
|
-
"
|
|
176
|
-
"PL", # Pylint
|
|
177
|
-
"PT", # flake8-pytest-style
|
|
164
|
+
"T20", # flake8-print
|
|
178
165
|
"PYI", # flake8-pyi
|
|
166
|
+
"PT", # flake8-pytest-style
|
|
179
167
|
"Q", # flake8-quotes
|
|
180
|
-
"RET", # flake8-return
|
|
181
168
|
"RSE", # flake8-raise
|
|
182
|
-
"
|
|
183
|
-
"S", # flake8-bandit
|
|
184
|
-
"SIM", # flake8-simplify
|
|
169
|
+
"RET", # flake8-return
|
|
185
170
|
"SLF", # flake8-self
|
|
186
|
-
"
|
|
171
|
+
"SIM", # flake8-simplify
|
|
187
172
|
"TC", # flake8-type-checking
|
|
173
|
+
"ARG", # flake8-unused-arguments
|
|
174
|
+
"FLY", # flynt
|
|
175
|
+
"C90", # mccabe (complex-structure)
|
|
176
|
+
"PL", # Pylint
|
|
188
177
|
"TRY", # tryceratops
|
|
189
|
-
"
|
|
178
|
+
"PERF", # Perflint
|
|
179
|
+
"E", # pycodestyle-errors
|
|
190
180
|
"W", # pycodestyle-warnings
|
|
181
|
+
"F", # pyflakes
|
|
182
|
+
"I", # isort
|
|
183
|
+
"D", # pydocstyle
|
|
184
|
+
"UP", # pyupgrade
|
|
185
|
+
"N", # pep8-naming
|
|
186
|
+
"ERA", # eradicate
|
|
187
|
+
"RUF", # Ruff-specific rules
|
|
188
|
+
"DOC", # pydoclint
|
|
189
|
+
"FURB", # Refurb
|
|
190
|
+
"PL", # Pylint
|
|
191
191
|
]
|
|
192
192
|
|
|
193
193
|
ignore = [
|
|
@@ -203,66 +203,66 @@
|
|
|
203
203
|
|
|
204
204
|
[tool.ruff.lint.per-file-ignores]
|
|
205
205
|
"tests/**/*.py" = [
|
|
206
|
+
"S101",
|
|
207
|
+
"SLF001",
|
|
208
|
+
"PLC2701",
|
|
209
|
+
"PLR6301",
|
|
210
|
+
"TRY002",
|
|
211
|
+
"FBT001",
|
|
212
|
+
"FBT002",
|
|
206
213
|
"ANN001",
|
|
207
|
-
"ANN002",
|
|
208
214
|
"ANN003",
|
|
209
|
-
"
|
|
210
|
-
"ANN401",
|
|
211
|
-
"ARG001",
|
|
215
|
+
"ANN002",
|
|
212
216
|
"ARG002",
|
|
213
|
-
"
|
|
214
|
-
"
|
|
215
|
-
"
|
|
216
|
-
"
|
|
217
|
+
"PLR0914",
|
|
218
|
+
"PLR2004",
|
|
219
|
+
"PLR0915",
|
|
220
|
+
"PLR1702",
|
|
221
|
+
"D417",
|
|
222
|
+
"ARG001",
|
|
217
223
|
"D103",
|
|
224
|
+
"D102",
|
|
225
|
+
"D101",
|
|
218
226
|
"D107",
|
|
219
|
-
"
|
|
227
|
+
"N802",
|
|
220
228
|
"DOC201",
|
|
221
229
|
"DOC501",
|
|
222
|
-
"E501",
|
|
223
|
-
"ERA001",
|
|
224
|
-
"FBT001",
|
|
225
|
-
"FBT002",
|
|
226
|
-
"G004",
|
|
227
|
-
"N802",
|
|
228
230
|
"PERF203",
|
|
229
|
-
"
|
|
231
|
+
"C901",
|
|
230
232
|
"PLR0911",
|
|
233
|
+
"G004",
|
|
234
|
+
"ERA001",
|
|
235
|
+
"E501",
|
|
236
|
+
"ANN401",
|
|
231
237
|
"PLR0912",
|
|
232
|
-
"
|
|
233
|
-
"
|
|
234
|
-
"PLR1702",
|
|
235
|
-
"PLR2004",
|
|
236
|
-
"PLR6301",
|
|
237
|
-
"S101",
|
|
238
|
-
"SLF001",
|
|
239
|
-
"TRY002",
|
|
238
|
+
"ANN201",
|
|
239
|
+
"D100",
|
|
240
240
|
]
|
|
241
241
|
|
|
242
242
|
[tool.ruff.lint.pylint]
|
|
243
243
|
max-args = 10
|
|
244
244
|
|
|
245
245
|
[tool.ruff.format]
|
|
246
|
-
|
|
246
|
+
quote-style = "double"
|
|
247
247
|
indent-style = "space"
|
|
248
248
|
line-ending = "auto"
|
|
249
|
-
|
|
249
|
+
docstring-code-format = true
|
|
250
250
|
skip-magic-trailing-comma = false
|
|
251
251
|
|
|
252
252
|
[tool.pyright]
|
|
253
|
-
exclude = [ "**/.venv", "**/__pycache__" ]
|
|
254
253
|
include = [ "src" ]
|
|
254
|
+
exclude = [ "**/.venv", "**/__pycache__" ]
|
|
255
255
|
|
|
256
256
|
[tool.mypy]
|
|
257
|
+
exclude = [ "tests", "examples" ]
|
|
257
258
|
|
|
258
|
-
exclude = [ "examples", "tests" ]
|
|
259
259
|
[tool.pytest.ini_options]
|
|
260
|
-
|
|
261
|
-
asyncio_mode = "auto"
|
|
262
|
-
python_files = "test_*.py"
|
|
263
260
|
testpaths = [ "tests" ]
|
|
264
|
-
|
|
265
|
-
|
|
261
|
+
python_files = "test_*.py"
|
|
262
|
+
asyncio_mode = "auto"
|
|
263
|
+
|
|
264
|
+
log_cli = false
|
|
265
|
+
log_level = "ERROR"
|
|
266
266
|
|
|
267
267
|
# Default timeout for tests (in seconds)
|
|
268
268
|
timeout = 10
|
|
@@ -270,10 +270,10 @@
|
|
|
270
270
|
|
|
271
271
|
# Custom markers
|
|
272
272
|
markers = [
|
|
273
|
-
"edge_case: marks tests for boundary conditions and edge cases",
|
|
274
|
-
"grpc: marks tests for gRPC service functionality",
|
|
275
273
|
"integration: marks tests that require real SurrealDB connection (deselect with '-m \"not integration\"')",
|
|
276
|
-
"
|
|
274
|
+
"grpc: marks tests for gRPC service functionality",
|
|
277
275
|
"smoke: marks critical path tests that should always pass",
|
|
276
|
+
"edge_case: marks tests for boundary conditions and edge cases",
|
|
278
277
|
"validation: marks tests for input validation and schema checking",
|
|
278
|
+
"regression: marks tests for previously fixed bugs",
|
|
279
279
|
]
|
{digitalkin-0.3.2a2 → digitalkin-0.3.2.dev2}/src/digitalkin/core/job_manager/single_job_manager.py
RENAMED
|
@@ -5,7 +5,7 @@ import datetime
|
|
|
5
5
|
import uuid
|
|
6
6
|
from collections.abc import AsyncGenerator, AsyncIterator
|
|
7
7
|
from contextlib import asynccontextmanager
|
|
8
|
-
from typing import
|
|
8
|
+
from typing import Any
|
|
9
9
|
|
|
10
10
|
import grpc
|
|
11
11
|
|
|
@@ -13,13 +13,10 @@ from digitalkin.core.common import ConnectionFactory, ModuleFactory
|
|
|
13
13
|
from digitalkin.core.job_manager.base_job_manager import BaseJobManager
|
|
14
14
|
from digitalkin.core.task_manager.local_task_manager import LocalTaskManager
|
|
15
15
|
from digitalkin.core.task_manager.task_session import TaskSession
|
|
16
|
-
|
|
17
|
-
if TYPE_CHECKING:
|
|
18
|
-
from digitalkin.core.task_manager.surrealdb_repository import SurrealDBConnection
|
|
19
16
|
from digitalkin.logger import logger
|
|
20
17
|
from digitalkin.models.core.task_monitor import TaskStatus
|
|
21
|
-
from digitalkin.models.module.base_types import InputModelT, OutputModelT, SetupModelT
|
|
22
18
|
from digitalkin.models.module.module import ModuleCodeModel
|
|
19
|
+
from digitalkin.models.module.module_types import InputModelT, OutputModelT, SetupModelT
|
|
23
20
|
from digitalkin.modules._base_module import BaseModule
|
|
24
21
|
from digitalkin.services.services_models import ServicesMode
|
|
25
22
|
|
|
@@ -32,6 +29,10 @@ class SingleJobManager(BaseJobManager[InputModelT, OutputModelT, SetupModelT]):
|
|
|
32
29
|
to handle their output data.
|
|
33
30
|
"""
|
|
34
31
|
|
|
32
|
+
async def start(self) -> None:
|
|
33
|
+
"""Start manager."""
|
|
34
|
+
self.channel = await ConnectionFactory.create_surreal_connection("task_manager", datetime.timedelta(seconds=5))
|
|
35
|
+
|
|
35
36
|
def __init__(
|
|
36
37
|
self,
|
|
37
38
|
module_class: type[BaseModule],
|
|
@@ -54,11 +55,6 @@ class SingleJobManager(BaseJobManager[InputModelT, OutputModelT, SetupModelT]):
|
|
|
54
55
|
super().__init__(module_class, services_mode, task_manager)
|
|
55
56
|
|
|
56
57
|
self._lock = asyncio.Lock()
|
|
57
|
-
self.channel: SurrealDBConnection | None = None
|
|
58
|
-
|
|
59
|
-
async def start(self) -> None:
|
|
60
|
-
"""Start manager."""
|
|
61
|
-
self.channel = await ConnectionFactory.create_surreal_connection("task_manager", datetime.timedelta(seconds=5))
|
|
62
58
|
|
|
63
59
|
async def generate_config_setup_module_response(self, job_id: str) -> SetupModelT | ModuleCodeModel:
|
|
64
60
|
"""Generate a stream consumer for a module's output data.
|
|
@@ -90,10 +86,7 @@ class SingleJobManager(BaseJobManager[InputModelT, OutputModelT, SetupModelT]):
|
|
|
90
86
|
message=f"Module {job_id} did not respond within 30 seconds",
|
|
91
87
|
)
|
|
92
88
|
finally:
|
|
93
|
-
logger.
|
|
94
|
-
"Config setup response retrieved",
|
|
95
|
-
extra={"job_id": job_id, "queue_empty": session.queue.empty()},
|
|
96
|
-
)
|
|
89
|
+
logger.info(f"{job_id=}: {session.queue.empty()}")
|
|
97
90
|
|
|
98
91
|
async def create_config_setup_instance_job(
|
|
99
92
|
self,
|
|
@@ -117,14 +110,11 @@ class SingleJobManager(BaseJobManager[InputModelT, OutputModelT, SetupModelT]):
|
|
|
117
110
|
str: The unique identifier (job ID) of the created job.
|
|
118
111
|
|
|
119
112
|
Raises:
|
|
120
|
-
RuntimeError: If start() was not called before creating jobs.
|
|
121
113
|
Exception: If the module fails to start.
|
|
122
114
|
"""
|
|
123
115
|
job_id = str(uuid.uuid4())
|
|
116
|
+
# TODO: Ensure the job_id is unique.
|
|
124
117
|
module = ModuleFactory.create_module_instance(self.module_class, job_id, mission_id, setup_id, setup_version_id)
|
|
125
|
-
if self.channel is None:
|
|
126
|
-
msg = "JobManager.start() must be called before creating jobs"
|
|
127
|
-
raise RuntimeError(msg)
|
|
128
118
|
self.tasks_sessions[job_id] = TaskSession(job_id, mission_id, self.channel, module)
|
|
129
119
|
|
|
130
120
|
try:
|
|
@@ -136,7 +126,7 @@ class SingleJobManager(BaseJobManager[InputModelT, OutputModelT, SetupModelT]):
|
|
|
136
126
|
except Exception:
|
|
137
127
|
# Remove the module from the manager in case of an error.
|
|
138
128
|
del self.tasks_sessions[job_id]
|
|
139
|
-
logger.exception("Failed to start module",
|
|
129
|
+
logger.exception("Failed to start module %s: %s", job_id)
|
|
140
130
|
raise
|
|
141
131
|
else:
|
|
142
132
|
return job_id
|
|
@@ -144,33 +134,13 @@ class SingleJobManager(BaseJobManager[InputModelT, OutputModelT, SetupModelT]):
|
|
|
144
134
|
async def add_to_queue(self, job_id: str, output_data: OutputModelT | ModuleCodeModel) -> None:
|
|
145
135
|
"""Add output data to the queue for a specific job.
|
|
146
136
|
|
|
147
|
-
|
|
148
|
-
drops the oldest message to make room for the new one.
|
|
149
|
-
Rejects writes after stream is closed to prevent message loss.
|
|
137
|
+
This method is used as a callback to handle output data generated by a module job.
|
|
150
138
|
|
|
151
139
|
Args:
|
|
152
140
|
job_id: The unique identifier of the job.
|
|
153
141
|
output_data: The output data produced by the job.
|
|
154
142
|
"""
|
|
155
|
-
|
|
156
|
-
if session is None:
|
|
157
|
-
logger.warning("Queue write rejected - session not found", extra={"job_id": job_id})
|
|
158
|
-
return
|
|
159
|
-
|
|
160
|
-
if session.stream_closed:
|
|
161
|
-
logger.debug("Queue write rejected - stream closed", extra={"job_id": job_id})
|
|
162
|
-
return
|
|
163
|
-
|
|
164
|
-
try:
|
|
165
|
-
await asyncio.wait_for(session.queue.put(output_data.model_dump()), timeout=5.0)
|
|
166
|
-
except asyncio.TimeoutError:
|
|
167
|
-
logger.warning("Queue full, dropping oldest message", extra={"job_id": job_id})
|
|
168
|
-
try:
|
|
169
|
-
session.queue.get_nowait()
|
|
170
|
-
session.queue.task_done()
|
|
171
|
-
except asyncio.QueueEmpty:
|
|
172
|
-
pass
|
|
173
|
-
session.queue.put_nowait(output_data.model_dump())
|
|
143
|
+
await self.tasks_sessions[job_id].queue.put(output_data.model_dump())
|
|
174
144
|
|
|
175
145
|
@asynccontextmanager # type: ignore
|
|
176
146
|
async def generate_stream_consumer(self, job_id: str) -> AsyncIterator[AsyncGenerator[dict[str, Any], None]]: # type: ignore
|
|
@@ -207,39 +177,42 @@ class SingleJobManager(BaseJobManager[InputModelT, OutputModelT, SetupModelT]):
|
|
|
207
177
|
logger.debug("Session: %s with Module %s", job_id, session.module)
|
|
208
178
|
|
|
209
179
|
async def _stream() -> AsyncGenerator[dict[str, Any], Any]:
|
|
210
|
-
"""Stream output data from the module with
|
|
180
|
+
"""Stream output data from the module with simple blocking pattern.
|
|
211
181
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
182
|
+
This implementation uses a simple one-item-at-a-time pattern optimized
|
|
183
|
+
for local execution where we have direct access to session status:
|
|
184
|
+
1. Block waiting for each item
|
|
185
|
+
2. Check termination conditions after each item
|
|
186
|
+
3. Clean shutdown when task completes
|
|
187
|
+
|
|
188
|
+
This pattern provides:
|
|
189
|
+
- Immediate termination when task completes
|
|
190
|
+
- Direct session status monitoring
|
|
191
|
+
- Simple, predictable behavior for local tasks
|
|
215
192
|
|
|
216
193
|
Yields:
|
|
217
194
|
dict: Output data generated by the module.
|
|
218
195
|
"""
|
|
219
196
|
while True:
|
|
220
|
-
if
|
|
221
|
-
|
|
222
|
-
break
|
|
223
|
-
|
|
224
|
-
try:
|
|
225
|
-
msg = await asyncio.wait_for(session.queue.get(), timeout=1.0)
|
|
226
|
-
except asyncio.TimeoutError:
|
|
227
|
-
continue
|
|
228
|
-
|
|
197
|
+
# Block for next item - if queue is empty but producer not finished yet
|
|
198
|
+
msg = await session.queue.get()
|
|
229
199
|
try:
|
|
230
200
|
yield msg
|
|
231
201
|
finally:
|
|
202
|
+
# Always mark task as done, even if consumer raises exception
|
|
232
203
|
session.queue.task_done()
|
|
233
204
|
|
|
205
|
+
# Check termination conditions after each message
|
|
206
|
+
# This allows immediate shutdown when the task completes
|
|
234
207
|
if (
|
|
235
|
-
session.
|
|
236
|
-
or session.is_cancelled.is_set()
|
|
208
|
+
session.is_cancelled.is_set()
|
|
237
209
|
or (session.status is TaskStatus.COMPLETED and session.queue.empty())
|
|
238
210
|
or session.status is TaskStatus.FAILED
|
|
239
211
|
):
|
|
240
212
|
logger.debug(
|
|
241
|
-
"Stream ending for job %s: status=%s, queue_empty=%s",
|
|
213
|
+
"Stream ending for job %s: cancelled=%s, status=%s, queue_empty=%s",
|
|
242
214
|
job_id,
|
|
215
|
+
session.is_cancelled.is_set(),
|
|
243
216
|
session.status,
|
|
244
217
|
session.queue.empty(),
|
|
245
218
|
)
|
|
@@ -286,18 +259,6 @@ class SingleJobManager(BaseJobManager[InputModelT, OutputModelT, SetupModelT]):
|
|
|
286
259
|
logger.info("Managed task started: '%s'", job_id, extra={"task_id": job_id})
|
|
287
260
|
return job_id
|
|
288
261
|
|
|
289
|
-
async def clean_session(self, task_id: str, mission_id: str) -> bool:
|
|
290
|
-
"""Clean a task's session.
|
|
291
|
-
|
|
292
|
-
Args:
|
|
293
|
-
task_id: Unique identifier for the task.
|
|
294
|
-
mission_id: Mission identifier.
|
|
295
|
-
|
|
296
|
-
Returns:
|
|
297
|
-
bool: True if the task was successfully cleaned, False otherwise.
|
|
298
|
-
"""
|
|
299
|
-
return await self._task_manager.clean_session(task_id, mission_id)
|
|
300
|
-
|
|
301
262
|
async def stop_module(self, job_id: str) -> bool:
|
|
302
263
|
"""Stop a running module job.
|
|
303
264
|
|
|
@@ -310,23 +271,20 @@ class SingleJobManager(BaseJobManager[InputModelT, OutputModelT, SetupModelT]):
|
|
|
310
271
|
Raises:
|
|
311
272
|
Exception: If an error occurs while stopping the module.
|
|
312
273
|
"""
|
|
313
|
-
logger.info("
|
|
274
|
+
logger.info(f"STOP required for {job_id=}")
|
|
314
275
|
|
|
315
276
|
async with self._lock:
|
|
316
277
|
session = self.tasks_sessions.get(job_id)
|
|
317
278
|
|
|
318
279
|
if not session:
|
|
319
|
-
logger.warning("
|
|
280
|
+
logger.warning(f"session with id: {job_id} not found")
|
|
320
281
|
return False
|
|
321
282
|
try:
|
|
322
283
|
await session.module.stop()
|
|
323
284
|
await self.cancel_task(job_id, session.mission_id)
|
|
324
|
-
logger.debug(
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
)
|
|
328
|
-
except Exception:
|
|
329
|
-
logger.exception("Error stopping module", extra={"job_id": job_id})
|
|
285
|
+
logger.debug(f"session {job_id} ({session.module.name}) stopped successfully")
|
|
286
|
+
except Exception as e:
|
|
287
|
+
logger.error(f"Error while stopping module {job_id}: {e}")
|
|
330
288
|
raise
|
|
331
289
|
else:
|
|
332
290
|
return True
|
|
@@ -373,7 +331,7 @@ class SingleJobManager(BaseJobManager[InputModelT, OutputModelT, SetupModelT]):
|
|
|
373
331
|
await asyncio.gather(*stop_tasks, return_exceptions=True)
|
|
374
332
|
|
|
375
333
|
# Close SurrealDB connection after stopping all modules
|
|
376
|
-
if self
|
|
334
|
+
if hasattr(self, "channel"):
|
|
377
335
|
try:
|
|
378
336
|
await self.channel.close()
|
|
379
337
|
logger.info("SingleJobManager: SurrealDB connection closed")
|