digitalkin 0.2.18__tar.gz → 0.2.19__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.2.18 → digitalkin-0.2.19}/PKG-INFO +11 -11
- {digitalkin-0.2.18 → digitalkin-0.2.19}/pyproject.toml +12 -12
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/__version__.py +1 -1
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/module_servicer.py +7 -7
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/models/module/__init__.py +6 -6
- digitalkin-0.2.19/src/digitalkin/models/module/module_types.py +105 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/_base_module.py +54 -45
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/archetype_module.py +0 -2
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/job_manager/base_job_manager.py +2 -5
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/job_manager/single_job_manager.py +7 -7
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/job_manager/taskiq_broker.py +0 -2
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/job_manager/taskiq_job_manager.py +3 -5
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/tool_module.py +1 -2
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/storage/grpc_storage.py +4 -4
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/utils/package_discover.py +2 -2
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin.egg-info/PKG-INFO +11 -11
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin.egg-info/requires.txt +10 -10
- digitalkin-0.2.18/src/digitalkin/models/module/module_types.py +0 -43
- {digitalkin-0.2.18 → digitalkin-0.2.19}/LICENSE +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/README.md +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/base_server/__init__.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/base_server/mock/__init__.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/base_server/mock/mock_pb2.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/base_server/mock/mock_pb2_grpc.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/base_server/server_async_insecure.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/base_server/server_async_secure.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/base_server/server_sync_insecure.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/base_server/server_sync_secure.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/modules/__init__.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/modules/cpu_intensive_module.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/modules/minimal_llm_module.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/modules/text_transform_module.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/services/filesystem_module.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/services/storage_module.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/setup.cfg +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/__init__.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/__init__.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/_base_server.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/module_server.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/registry_server.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/registry_servicer.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/utils/exceptions.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/utils/factory.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/utils/grpc_client_wrapper.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/utils/models.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/utils/types.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/logger.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/models/__init__.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/models/module/module.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/models/module/module_context.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/models/services/__init__.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/models/services/cost.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/models/services/storage.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/__init__.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/job_manager/job_manager_models.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/trigger_handler.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/py.typed +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/__init__.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/agent/__init__.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/agent/agent_strategy.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/agent/default_agent.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/base_strategy.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/cost/__init__.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/cost/cost_strategy.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/cost/default_cost.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/cost/grpc_cost.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/filesystem/__init__.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/filesystem/default_filesystem.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/filesystem/filesystem_strategy.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/filesystem/grpc_filesystem.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/identity/__init__.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/identity/default_identity.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/identity/identity_strategy.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/registry/__init__.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/registry/default_registry.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/registry/registry_strategy.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/services_config.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/services_models.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/setup/__init__.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/setup/default_setup.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/setup/grpc_setup.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/setup/setup_strategy.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/snapshot/__init__.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/snapshot/default_snapshot.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/snapshot/snapshot_strategy.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/storage/__init__.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/storage/default_storage.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/storage/storage_strategy.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/utils/__init__.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/utils/arg_parser.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/utils/development_mode_action.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/utils/llm_ready_schema.py +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin.egg-info/SOURCES.txt +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin.egg-info/dependency_links.txt +0 -0
- {digitalkin-0.2.18 → digitalkin-0.2.19}/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: 0.2.
|
|
3
|
+
Version: 0.2.19
|
|
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
|
|
@@ -458,30 +458,30 @@ Requires-Dist: grpcio-reflection>=1.71.0
|
|
|
458
458
|
Requires-Dist: grpcio-status>=1.71.0
|
|
459
459
|
Requires-Dist: pydantic>=2.11.5
|
|
460
460
|
Provides-Extra: dev
|
|
461
|
-
Requires-Dist: typos>=1.
|
|
462
|
-
Requires-Dist: ruff>=0.
|
|
463
|
-
Requires-Dist: mypy>=1.
|
|
464
|
-
Requires-Dist: pyright>=1.1.
|
|
461
|
+
Requires-Dist: typos>=1.34.0; extra == "dev"
|
|
462
|
+
Requires-Dist: ruff>=0.12.5; extra == "dev"
|
|
463
|
+
Requires-Dist: mypy>=1.17.0; extra == "dev"
|
|
464
|
+
Requires-Dist: pyright>=1.1.403; extra == "dev"
|
|
465
465
|
Requires-Dist: pre-commit>=4.2.0; extra == "dev"
|
|
466
466
|
Requires-Dist: bump2version>=1.0.1; extra == "dev"
|
|
467
467
|
Requires-Dist: build>=1.2.2; extra == "dev"
|
|
468
468
|
Requires-Dist: twine>=6.1.0; extra == "dev"
|
|
469
|
-
Requires-Dist: cryptography>=45.0.
|
|
469
|
+
Requires-Dist: cryptography>=45.0.5; extra == "dev"
|
|
470
470
|
Provides-Extra: examples
|
|
471
471
|
Requires-Dist: openai>=1.75.0; extra == "examples"
|
|
472
472
|
Provides-Extra: tests
|
|
473
|
-
Requires-Dist: freezegun>=1.5.
|
|
473
|
+
Requires-Dist: freezegun>=1.5.3; extra == "tests"
|
|
474
474
|
Requires-Dist: hdrhistogram>=0.10.3; extra == "tests"
|
|
475
475
|
Requires-Dist: grpcio-testing>=1.71.0; extra == "tests"
|
|
476
476
|
Requires-Dist: psutil>=7.0.0; extra == "tests"
|
|
477
477
|
Requires-Dist: pytest>=8.4.0; extra == "tests"
|
|
478
|
-
Requires-Dist: pytest-asyncio>=1.
|
|
478
|
+
Requires-Dist: pytest-asyncio>=1.1.0; extra == "tests"
|
|
479
479
|
Requires-Dist: pytest-cov>=6.1.0; extra == "tests"
|
|
480
480
|
Provides-Extra: taskiq
|
|
481
481
|
Requires-Dist: rstream>=0.30.0; extra == "taskiq"
|
|
482
|
-
Requires-Dist: taskiq-aio-pika>=0.4.
|
|
483
|
-
Requires-Dist: taskiq-redis>=1.0
|
|
484
|
-
Requires-Dist: taskiq[reload]>=0.11.
|
|
482
|
+
Requires-Dist: taskiq-aio-pika>=0.4.3; extra == "taskiq"
|
|
483
|
+
Requires-Dist: taskiq-redis>=1.1.0; extra == "taskiq"
|
|
484
|
+
Requires-Dist: taskiq[reload]>=0.11.18; extra == "taskiq"
|
|
485
485
|
Dynamic: license-file
|
|
486
486
|
|
|
487
487
|
# DigitalKin Python SDK
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
keywords = [ "digitalkin", "kin", "agent", "gprc", "sdk" ]
|
|
14
14
|
# Version of the package automatically updated by bump2version (that is why it is separated)
|
|
15
|
-
version = "0.2.
|
|
15
|
+
version = "0.2.19"
|
|
16
16
|
|
|
17
17
|
classifiers = [
|
|
18
18
|
"Development Status :: 3 - Alpha",
|
|
@@ -34,35 +34,35 @@
|
|
|
34
34
|
"grpcio-reflection>=1.71.0",
|
|
35
35
|
"grpcio-status>=1.71.0",
|
|
36
36
|
"pydantic>=2.11.5",
|
|
37
|
-
]
|
|
37
|
+
]
|
|
38
38
|
|
|
39
39
|
[project.optional-dependencies]
|
|
40
40
|
dev = [
|
|
41
|
-
"typos>=1.
|
|
42
|
-
"ruff>=0.
|
|
43
|
-
"mypy>=1.
|
|
44
|
-
"pyright>=1.1.
|
|
41
|
+
"typos>=1.34.0",
|
|
42
|
+
"ruff>=0.12.5",
|
|
43
|
+
"mypy>=1.17.0",
|
|
44
|
+
"pyright>=1.1.403",
|
|
45
45
|
"pre-commit>=4.2.0",
|
|
46
46
|
"bump2version>=1.0.1",
|
|
47
47
|
"build>=1.2.2",
|
|
48
48
|
"twine>=6.1.0",
|
|
49
|
-
"cryptography>=45.0.
|
|
49
|
+
"cryptography>=45.0.5",
|
|
50
50
|
]
|
|
51
51
|
examples = [ "openai>=1.75.0" ]
|
|
52
52
|
tests = [
|
|
53
|
-
"freezegun>=1.5.
|
|
53
|
+
"freezegun>=1.5.3",
|
|
54
54
|
"hdrhistogram>=0.10.3",
|
|
55
55
|
"grpcio-testing>=1.71.0",
|
|
56
56
|
"psutil>=7.0.0",
|
|
57
57
|
"pytest>=8.4.0",
|
|
58
|
-
"pytest-asyncio>=1.
|
|
58
|
+
"pytest-asyncio>=1.1.0",
|
|
59
59
|
"pytest-cov>=6.1.0",
|
|
60
60
|
]
|
|
61
61
|
taskiq = [
|
|
62
62
|
"rstream>=0.30.0",
|
|
63
|
-
"taskiq-aio-pika>=0.4.
|
|
64
|
-
"taskiq-redis>=1.0
|
|
65
|
-
"taskiq[reload]>=0.11.
|
|
63
|
+
"taskiq-aio-pika>=0.4.3",
|
|
64
|
+
"taskiq-redis>=1.1.0",
|
|
65
|
+
"taskiq[reload]>=0.11.18",
|
|
66
66
|
]
|
|
67
67
|
|
|
68
68
|
[project.urls]
|
|
@@ -105,7 +105,8 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer, ArgParser):
|
|
|
105
105
|
setup_version = request.setup_version
|
|
106
106
|
config_setup_data = self.module_class.create_config_setup_model(json_format.MessageToDict(request.content))
|
|
107
107
|
setup_version_data = self.module_class.create_setup_model(
|
|
108
|
-
json_format.MessageToDict(request.setup_version.content)
|
|
108
|
+
json_format.MessageToDict(request.setup_version.content),
|
|
109
|
+
config_fields=True,
|
|
109
110
|
)
|
|
110
111
|
|
|
111
112
|
if not setup_version_data:
|
|
@@ -119,7 +120,6 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer, ArgParser):
|
|
|
119
120
|
# create a task to run the module in background
|
|
120
121
|
job_id = await self.job_manager.create_config_setup_instance_job(
|
|
121
122
|
config_setup_data,
|
|
122
|
-
setup_version_data,
|
|
123
123
|
request.mission_id,
|
|
124
124
|
setup_version.id,
|
|
125
125
|
)
|
|
@@ -333,7 +333,7 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer, ArgParser):
|
|
|
333
333
|
except NotImplementedError as e:
|
|
334
334
|
logger.warning(e)
|
|
335
335
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
336
|
-
context.set_details(e)
|
|
336
|
+
context.set_details(str(e))
|
|
337
337
|
return information_pb2.GetModuleInputResponse()
|
|
338
338
|
|
|
339
339
|
return information_pb2.GetModuleInputResponse(
|
|
@@ -369,7 +369,7 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer, ArgParser):
|
|
|
369
369
|
except NotImplementedError as e:
|
|
370
370
|
logger.warning(e)
|
|
371
371
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
372
|
-
context.set_details(e)
|
|
372
|
+
context.set_details(str(e))
|
|
373
373
|
return information_pb2.GetModuleOutputResponse()
|
|
374
374
|
|
|
375
375
|
return information_pb2.GetModuleOutputResponse(
|
|
@@ -405,7 +405,7 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer, ArgParser):
|
|
|
405
405
|
except NotImplementedError as e:
|
|
406
406
|
logger.warning(e)
|
|
407
407
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
408
|
-
context.set_details(e)
|
|
408
|
+
context.set_details(str(e))
|
|
409
409
|
return information_pb2.GetModuleSetupResponse()
|
|
410
410
|
|
|
411
411
|
return information_pb2.GetModuleSetupResponse(
|
|
@@ -441,7 +441,7 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer, ArgParser):
|
|
|
441
441
|
except NotImplementedError as e:
|
|
442
442
|
logger.warning(e)
|
|
443
443
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
444
|
-
context.set_details(e)
|
|
444
|
+
context.set_details(str(e))
|
|
445
445
|
return information_pb2.GetModuleSecretResponse()
|
|
446
446
|
|
|
447
447
|
return information_pb2.GetModuleSecretResponse(
|
|
@@ -477,7 +477,7 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer, ArgParser):
|
|
|
477
477
|
except NotImplementedError as e:
|
|
478
478
|
logger.warning(e)
|
|
479
479
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
480
|
-
context.set_details(e)
|
|
480
|
+
context.set_details(str(e))
|
|
481
481
|
return information_pb2.GetConfigSetupModuleResponse()
|
|
482
482
|
|
|
483
483
|
return information_pb2.GetConfigSetupModuleResponse(
|
|
@@ -3,24 +3,24 @@
|
|
|
3
3
|
from digitalkin.models.module.module import Module, ModuleStatus
|
|
4
4
|
from digitalkin.models.module.module_context import ModuleContext
|
|
5
5
|
from digitalkin.models.module.module_types import (
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
DataModel,
|
|
7
|
+
DataTrigger,
|
|
8
8
|
InputModelT,
|
|
9
|
-
InputTrigger,
|
|
10
9
|
OutputModelT,
|
|
11
10
|
SecretModelT,
|
|
11
|
+
SetupModel,
|
|
12
12
|
SetupModelT,
|
|
13
13
|
)
|
|
14
14
|
|
|
15
15
|
__all__ = [
|
|
16
|
-
"
|
|
17
|
-
"
|
|
16
|
+
"DataModel",
|
|
17
|
+
"DataTrigger",
|
|
18
18
|
"InputModelT",
|
|
19
|
-
"InputTrigger",
|
|
20
19
|
"Module",
|
|
21
20
|
"ModuleContext",
|
|
22
21
|
"ModuleStatus",
|
|
23
22
|
"OutputModelT",
|
|
24
23
|
"SecretModelT",
|
|
24
|
+
"SetupModel",
|
|
25
25
|
"SetupModelT",
|
|
26
26
|
]
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""Types for module models."""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime, timezone
|
|
4
|
+
from typing import Any, ClassVar, Generic, TypeVar, cast
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, ConfigDict, Field, create_model
|
|
7
|
+
|
|
8
|
+
from digitalkin.logger import logger
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class DataTrigger(BaseModel):
|
|
12
|
+
"""Defines the root input model exposing the protocol.
|
|
13
|
+
|
|
14
|
+
The mandatory protocol is important to define the module beahvior following the user or agent input.
|
|
15
|
+
|
|
16
|
+
Example:
|
|
17
|
+
class MyInput(DataModel):
|
|
18
|
+
root: DataTrigger
|
|
19
|
+
user_define_data: Any
|
|
20
|
+
|
|
21
|
+
# Usage
|
|
22
|
+
my_input = MyInput(root=DataTrigger(protocol="message"))
|
|
23
|
+
print(my_input.root.protocol) # Output: message
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
protocol: ClassVar[str]
|
|
27
|
+
created_at: str = datetime.now(tz=timezone.utc).isoformat()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
DataTriggerT = TypeVar("DataTriggerT", bound=DataTrigger)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class DataModel(BaseModel, Generic[DataTriggerT]):
|
|
34
|
+
"""Base definition of input model showing mandatory root fields.
|
|
35
|
+
|
|
36
|
+
The Model define the Module Input, usually referring to multiple input type defined by an union.
|
|
37
|
+
|
|
38
|
+
Example:
|
|
39
|
+
class ModuleInput(DataModel):
|
|
40
|
+
root: FileInput | MessageInput
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
root: DataTriggerT
|
|
44
|
+
annotations: dict[str, str] = Field(
|
|
45
|
+
default={},
|
|
46
|
+
title="Annotations",
|
|
47
|
+
description="Additional metadata or annotations related to the output. ex {'role': 'user'}",
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
InputModelT = TypeVar("InputModelT", bound=DataModel)
|
|
52
|
+
OutputModelT = TypeVar("OutputModelT", bound=DataModel)
|
|
53
|
+
SecretModelT = TypeVar("SecretModelT", bound=BaseModel)
|
|
54
|
+
SetupModelT = TypeVar("SetupModelT", bound="SetupModel")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class SetupModel(BaseModel):
|
|
58
|
+
"""Base definition of setup model showing mandatory root fields.
|
|
59
|
+
|
|
60
|
+
Optionally, the setup model can define a config option in json_schema_extra to be used to initialize the Kin.
|
|
61
|
+
|
|
62
|
+
Example:
|
|
63
|
+
class MySetup(SetupModel):
|
|
64
|
+
name: str = Field()
|
|
65
|
+
number: int = Field(..., json_schema_extra={"config": True})
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
@classmethod
|
|
69
|
+
def get_clean_model(cls, *, config_fields: bool, hidden_fields: bool) -> type[SetupModelT]: # type: ignore
|
|
70
|
+
"""Dynamically builds and returns a new BaseModel subclass.
|
|
71
|
+
|
|
72
|
+
containing only those fields where json_schema_extra["config"] == True.
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
Type[BaseModel]: A new BaseModel subclass with the filtered fields.
|
|
76
|
+
|
|
77
|
+
Raises:
|
|
78
|
+
ValueError: If both config_fields and hidden_fields are set to True.
|
|
79
|
+
"""
|
|
80
|
+
clean_fields: dict[str, Any] = {}
|
|
81
|
+
for name, field_info in cls.model_fields.items():
|
|
82
|
+
extra = getattr(field_info, "json_schema_extra", {}) or {}
|
|
83
|
+
is_config = bool(extra.get("config", False))
|
|
84
|
+
is_hidden = bool(extra.get("hidden", False))
|
|
85
|
+
|
|
86
|
+
# Skip config unless explicitly included
|
|
87
|
+
if is_config and not config_fields:
|
|
88
|
+
logger.debug("Skipping '%s' (config-only)", name)
|
|
89
|
+
continue
|
|
90
|
+
|
|
91
|
+
# Skip hidden unless explicitly included
|
|
92
|
+
if is_hidden and not hidden_fields:
|
|
93
|
+
logger.debug("Skipping '%s' (hidden-only)", name)
|
|
94
|
+
continue
|
|
95
|
+
|
|
96
|
+
clean_fields[name] = (field_info.annotation, field_info)
|
|
97
|
+
|
|
98
|
+
# Dynamically create a model e.g. "SetupModel"
|
|
99
|
+
m = create_model(
|
|
100
|
+
f"{cls.__name__}",
|
|
101
|
+
__base__=BaseModel,
|
|
102
|
+
__config__=ConfigDict(arbitrary_types_allowed=True),
|
|
103
|
+
**clean_fields,
|
|
104
|
+
)
|
|
105
|
+
return cast("type[SetupModelT]", m)
|
|
@@ -9,10 +9,8 @@ from typing import Any, ClassVar, Generic
|
|
|
9
9
|
|
|
10
10
|
from pydantic import BaseModel
|
|
11
11
|
|
|
12
|
-
from digitalkin.grpc_servers.utils.exceptions import OptionalFeatureNotImplementedError
|
|
13
12
|
from digitalkin.logger import logger
|
|
14
13
|
from digitalkin.models.module import (
|
|
15
|
-
ConfigSetupModelT,
|
|
16
14
|
InputModelT,
|
|
17
15
|
ModuleStatus,
|
|
18
16
|
OutputModelT,
|
|
@@ -33,11 +31,11 @@ from digitalkin.utils.llm_ready_schema import llm_ready_schema
|
|
|
33
31
|
from digitalkin.utils.package_discover import ModuleDiscoverer
|
|
34
32
|
|
|
35
33
|
|
|
36
|
-
class
|
|
34
|
+
class ModuleCodeModel(BaseModel):
|
|
37
35
|
"""typed error/code model."""
|
|
38
36
|
|
|
39
37
|
code: str
|
|
40
|
-
|
|
38
|
+
message: str
|
|
41
39
|
short_description: str
|
|
42
40
|
|
|
43
41
|
|
|
@@ -48,7 +46,6 @@ class BaseModule( # noqa: PLR0904
|
|
|
48
46
|
OutputModelT,
|
|
49
47
|
SetupModelT,
|
|
50
48
|
SecretModelT,
|
|
51
|
-
ConfigSetupModelT,
|
|
52
49
|
],
|
|
53
50
|
):
|
|
54
51
|
"""BaseModule is the abstract base for all modules in the DigitalKin SDK."""
|
|
@@ -56,10 +53,10 @@ class BaseModule( # noqa: PLR0904
|
|
|
56
53
|
name: str
|
|
57
54
|
description: str
|
|
58
55
|
|
|
59
|
-
|
|
56
|
+
setup_format: type[SetupModelT]
|
|
57
|
+
|
|
60
58
|
input_format: type[InputModelT]
|
|
61
59
|
output_format: type[OutputModelT]
|
|
62
|
-
setup_format: type[SetupModelT]
|
|
63
60
|
secret_format: type[SecretModelT]
|
|
64
61
|
metadata: ClassVar[dict[str, Any]]
|
|
65
62
|
|
|
@@ -172,20 +169,22 @@ class BaseModule( # noqa: PLR0904
|
|
|
172
169
|
def get_config_setup_format(cls, *, llm_format: bool) -> str:
|
|
173
170
|
"""Gets the JSON schema of the config setup format model.
|
|
174
171
|
|
|
172
|
+
The config setup format is used only to initialize the module with configuration data.
|
|
173
|
+
The setup format is used to initialize an run the module with setup data.
|
|
174
|
+
|
|
175
175
|
Raises:
|
|
176
|
-
|
|
176
|
+
NotImplementedError: If the `setup_format` is not defined.
|
|
177
177
|
|
|
178
178
|
Returns:
|
|
179
179
|
The JSON schema of the config setup format as a string.
|
|
180
180
|
"""
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
if config_setup_format is not None:
|
|
181
|
+
if cls.setup_format is not None:
|
|
182
|
+
setup_format = cls.setup_format.get_clean_model(config_fields=True, hidden_fields=False)
|
|
184
183
|
if llm_format:
|
|
185
|
-
return json.dumps(llm_ready_schema(
|
|
186
|
-
return json.dumps(
|
|
184
|
+
return json.dumps(llm_ready_schema(setup_format), indent=2)
|
|
185
|
+
return json.dumps(setup_format.model_json_schema(), indent=2)
|
|
187
186
|
msg = "'%s' class does not define an 'config_setup_format'."
|
|
188
|
-
raise
|
|
187
|
+
raise NotImplementedError(msg)
|
|
189
188
|
|
|
190
189
|
@classmethod
|
|
191
190
|
def get_setup_format(cls, *, llm_format: bool) -> str:
|
|
@@ -198,14 +197,15 @@ class BaseModule( # noqa: PLR0904
|
|
|
198
197
|
The JSON schema of the setup format as a string.
|
|
199
198
|
"""
|
|
200
199
|
if cls.setup_format is not None:
|
|
200
|
+
setup_format = cls.setup_format.get_clean_model(config_fields=False, hidden_fields=True)
|
|
201
201
|
if llm_format:
|
|
202
|
-
return json.dumps(llm_ready_schema(
|
|
203
|
-
return json.dumps(
|
|
202
|
+
return json.dumps(llm_ready_schema(setup_format), indent=2)
|
|
203
|
+
return json.dumps(setup_format.model_json_schema(), indent=2)
|
|
204
204
|
msg = "'%s' class does not define an 'setup_format'."
|
|
205
205
|
raise NotImplementedError(msg)
|
|
206
206
|
|
|
207
207
|
@classmethod
|
|
208
|
-
def create_config_setup_model(cls, config_setup_data: dict[str, Any]) ->
|
|
208
|
+
def create_config_setup_model(cls, config_setup_data: dict[str, Any]) -> SetupModelT:
|
|
209
209
|
"""Create the setup model from the setup data.
|
|
210
210
|
|
|
211
211
|
Args:
|
|
@@ -214,7 +214,7 @@ class BaseModule( # noqa: PLR0904
|
|
|
214
214
|
Returns:
|
|
215
215
|
The setup model.
|
|
216
216
|
"""
|
|
217
|
-
return cls.
|
|
217
|
+
return cls.setup_format(**config_setup_data)
|
|
218
218
|
|
|
219
219
|
@classmethod
|
|
220
220
|
def create_input_model(cls, input_data: dict[str, Any]) -> InputModelT:
|
|
@@ -229,16 +229,17 @@ class BaseModule( # noqa: PLR0904
|
|
|
229
229
|
return cls.input_format(**input_data)
|
|
230
230
|
|
|
231
231
|
@classmethod
|
|
232
|
-
def create_setup_model(cls, setup_data: dict[str, Any]) -> SetupModelT:
|
|
232
|
+
def create_setup_model(cls, setup_data: dict[str, Any], *, config_fields: bool = False) -> SetupModelT:
|
|
233
233
|
"""Create the setup model from the setup data.
|
|
234
234
|
|
|
235
235
|
Args:
|
|
236
236
|
setup_data: The setup data to create the model from.
|
|
237
|
+
config_fields: If True, include only fields with json_schema_extra["config"] == True.
|
|
237
238
|
|
|
238
239
|
Returns:
|
|
239
240
|
The setup model.
|
|
240
241
|
"""
|
|
241
|
-
return cls.setup_format(**setup_data)
|
|
242
|
+
return cls.setup_format.get_clean_model(config_fields=config_fields, hidden_fields=True)(**setup_data)
|
|
242
243
|
|
|
243
244
|
@classmethod
|
|
244
245
|
def create_secret_model(cls, secret_data: dict[str, Any]) -> SecretModelT:
|
|
@@ -290,20 +291,20 @@ class BaseModule( # noqa: PLR0904
|
|
|
290
291
|
"""
|
|
291
292
|
return cls.triggers_discoverer.register_trigger(handler_cls)
|
|
292
293
|
|
|
293
|
-
|
|
294
|
-
async def run_config_setup(
|
|
295
|
-
self,
|
|
296
|
-
config_setup_data: ConfigSetupModelT,
|
|
297
|
-
setup_data: SetupModelT,
|
|
298
|
-
callback: Callable,
|
|
299
|
-
) -> None:
|
|
294
|
+
async def run_config_setup(self, config_setup_data: SetupModelT) -> SetupModelT: # noqa: PLR6301
|
|
300
295
|
"""Run config setup the module.
|
|
301
296
|
|
|
302
|
-
|
|
303
|
-
|
|
297
|
+
The config setup is used to initialize the setup with configuration data.
|
|
298
|
+
This method is typically used to set up the module with necessary configuration before running it,
|
|
299
|
+
especially for processing data like files.
|
|
300
|
+
The function needs to save the setup in the storage.
|
|
301
|
+
The module will be initialize with the setup and not the config setup.
|
|
302
|
+
This method is optional, the config setup and setup can be the same.
|
|
303
|
+
|
|
304
|
+
Returns:
|
|
305
|
+
The updated setup model after running the config setup.
|
|
304
306
|
"""
|
|
305
|
-
|
|
306
|
-
raise OptionalFeatureNotImplementedError(msg)
|
|
307
|
+
return config_setup_data
|
|
307
308
|
|
|
308
309
|
@abstractmethod
|
|
309
310
|
async def initialize(self, setup_data: SetupModelT) -> None:
|
|
@@ -364,9 +365,9 @@ class BaseModule( # noqa: PLR0904
|
|
|
364
365
|
asyncio.CancelledError: If the module is cancelled
|
|
365
366
|
"""
|
|
366
367
|
try:
|
|
367
|
-
logger.
|
|
368
|
+
logger.info("Starting module %s", self.name)
|
|
368
369
|
await self.run(input_data, setup_data, callback)
|
|
369
|
-
logger.
|
|
370
|
+
logger.info("Module %s finished", self.name)
|
|
370
371
|
except asyncio.CancelledError:
|
|
371
372
|
self._status = ModuleStatus.CANCELLED
|
|
372
373
|
logger.error(f"Module {self.name} cancelled")
|
|
@@ -374,7 +375,7 @@ class BaseModule( # noqa: PLR0904
|
|
|
374
375
|
self._status = ModuleStatus.FAILED
|
|
375
376
|
logger.exception("Error inside module %s", self.name)
|
|
376
377
|
else:
|
|
377
|
-
self._status = ModuleStatus.
|
|
378
|
+
self._status = ModuleStatus.STOPPING
|
|
378
379
|
finally:
|
|
379
380
|
await self.stop()
|
|
380
381
|
|
|
@@ -382,22 +383,22 @@ class BaseModule( # noqa: PLR0904
|
|
|
382
383
|
self,
|
|
383
384
|
input_data: InputModelT,
|
|
384
385
|
setup_data: SetupModelT,
|
|
385
|
-
callback: Callable[[OutputModelT |
|
|
386
|
+
callback: Callable[[OutputModelT | ModuleCodeModel], Coroutine[Any, Any, None]],
|
|
386
387
|
done_callback: Callable | None = None,
|
|
387
388
|
) -> None:
|
|
388
389
|
"""Start the module."""
|
|
389
390
|
try:
|
|
390
|
-
logger.
|
|
391
|
+
logger.debug("Inititalize module")
|
|
391
392
|
await self.initialize(setup_data=setup_data)
|
|
392
393
|
except Exception as e:
|
|
393
394
|
self._status = ModuleStatus.FAILED
|
|
394
395
|
short_description = "Error initializing module"
|
|
395
396
|
logger.exception("%s: %s", short_description, e)
|
|
396
397
|
await callback(
|
|
397
|
-
|
|
398
|
+
ModuleCodeModel(
|
|
398
399
|
code=str(self._status),
|
|
399
400
|
short_description=short_description,
|
|
400
|
-
|
|
401
|
+
message=str(e),
|
|
401
402
|
)
|
|
402
403
|
)
|
|
403
404
|
if done_callback is not None:
|
|
@@ -406,9 +407,9 @@ class BaseModule( # noqa: PLR0904
|
|
|
406
407
|
return
|
|
407
408
|
|
|
408
409
|
try:
|
|
409
|
-
logger.
|
|
410
|
+
logger.debug("Init the discovered input handlers.")
|
|
410
411
|
self.triggers_discoverer.init_handlers(self.context)
|
|
411
|
-
logger.
|
|
412
|
+
logger.debug("Run lifecycle")
|
|
412
413
|
self._status = ModuleStatus.RUNNING
|
|
413
414
|
self._task = asyncio.create_task(
|
|
414
415
|
self._run_lifecycle(input_data, setup_data, callback),
|
|
@@ -422,7 +423,8 @@ class BaseModule( # noqa: PLR0904
|
|
|
422
423
|
|
|
423
424
|
async def stop(self) -> None:
|
|
424
425
|
"""Stop the module."""
|
|
425
|
-
|
|
426
|
+
logger.info("Stopping module %s with status %s", self.name, self._status)
|
|
427
|
+
if self._status not in {ModuleStatus.RUNNING, ModuleStatus.STOPPING}:
|
|
426
428
|
return
|
|
427
429
|
|
|
428
430
|
try:
|
|
@@ -431,22 +433,29 @@ class BaseModule( # noqa: PLR0904
|
|
|
431
433
|
self._task.cancel()
|
|
432
434
|
with contextlib.suppress(asyncio.CancelledError):
|
|
433
435
|
await self._task
|
|
436
|
+
logger.debug("Module %s stopped", self.name)
|
|
434
437
|
await self.cleanup()
|
|
438
|
+
self._status = ModuleStatus.STOPPED
|
|
439
|
+
logger.debug("Module %s cleaned", self.name)
|
|
435
440
|
except Exception:
|
|
436
441
|
self._status = ModuleStatus.FAILED
|
|
437
442
|
logger.exception("Error stopping module")
|
|
438
443
|
|
|
439
444
|
async def start_config_setup(
|
|
440
445
|
self,
|
|
441
|
-
config_setup_data:
|
|
442
|
-
|
|
443
|
-
callback: Callable[[OutputModelT | ModuleErrorModel], Coroutine[Any, Any, None]],
|
|
446
|
+
config_setup_data: SetupModelT,
|
|
447
|
+
callback: Callable[[SetupModelT | ModuleCodeModel], Coroutine[Any, Any, None]],
|
|
444
448
|
) -> None:
|
|
445
449
|
"""Start the module."""
|
|
446
450
|
try:
|
|
447
451
|
logger.info("Run Config Setup lifecycle")
|
|
448
452
|
self._status = ModuleStatus.RUNNING
|
|
449
|
-
await self.run_config_setup(config_setup_data
|
|
453
|
+
content = await self.run_config_setup(config_setup_data)
|
|
454
|
+
|
|
455
|
+
wrapper = config_setup_data.model_dump()
|
|
456
|
+
wrapper["content"] = content.model_dump()
|
|
457
|
+
await callback(self.create_setup_model(wrapper))
|
|
458
|
+
self._status = ModuleStatus.STOPPING
|
|
450
459
|
except Exception:
|
|
451
460
|
self._status = ModuleStatus.FAILED
|
|
452
461
|
logger.exception("Error during module lifecyle")
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
from abc import ABC
|
|
4
4
|
|
|
5
5
|
from digitalkin.models.module import InputModelT, OutputModelT, SecretModelT, SetupModelT
|
|
6
|
-
from digitalkin.models.module.module_types import ConfigSetupModelT
|
|
7
6
|
from digitalkin.modules._base_module import BaseModule
|
|
8
7
|
|
|
9
8
|
|
|
@@ -13,7 +12,6 @@ class ArchetypeModule(
|
|
|
13
12
|
OutputModelT,
|
|
14
13
|
SetupModelT,
|
|
15
14
|
SecretModelT,
|
|
16
|
-
ConfigSetupModelT,
|
|
17
15
|
],
|
|
18
16
|
ABC,
|
|
19
17
|
):
|
{digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/job_manager/base_job_manager.py
RENAMED
|
@@ -7,13 +7,12 @@ from typing import Any, Generic
|
|
|
7
7
|
|
|
8
8
|
from digitalkin.models import ModuleStatus
|
|
9
9
|
from digitalkin.models.module import InputModelT, OutputModelT, SetupModelT
|
|
10
|
-
from digitalkin.models.module.module_types import ConfigSetupModelT
|
|
11
10
|
from digitalkin.modules._base_module import BaseModule
|
|
12
11
|
from digitalkin.services.services_config import ServicesConfig
|
|
13
12
|
from digitalkin.services.services_models import ServicesMode
|
|
14
13
|
|
|
15
14
|
|
|
16
|
-
class BaseJobManager(abc.ABC, Generic[InputModelT, SetupModelT
|
|
15
|
+
class BaseJobManager(abc.ABC, Generic[InputModelT, SetupModelT]):
|
|
17
16
|
"""Abstract base class for managing background module jobs."""
|
|
18
17
|
|
|
19
18
|
async def _start(self) -> None:
|
|
@@ -120,8 +119,7 @@ class BaseJobManager(abc.ABC, Generic[InputModelT, SetupModelT, ConfigSetupModel
|
|
|
120
119
|
@abc.abstractmethod
|
|
121
120
|
async def create_config_setup_instance_job(
|
|
122
121
|
self,
|
|
123
|
-
config_setup_data:
|
|
124
|
-
setup_data: SetupModelT,
|
|
122
|
+
config_setup_data: SetupModelT,
|
|
125
123
|
mission_id: str,
|
|
126
124
|
setup_version_id: str,
|
|
127
125
|
) -> str:
|
|
@@ -132,7 +130,6 @@ class BaseJobManager(abc.ABC, Generic[InputModelT, SetupModelT, ConfigSetupModel
|
|
|
132
130
|
|
|
133
131
|
Args:
|
|
134
132
|
config_setup_data: The input data required to start the job.
|
|
135
|
-
setup_data: The setup configuration for the module.
|
|
136
133
|
mission_id: The mission ID associated with the job.
|
|
137
134
|
setup_version_id: The setup ID.
|
|
138
135
|
|
{digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/job_manager/single_job_manager.py
RENAMED
|
@@ -10,13 +10,14 @@ import grpc
|
|
|
10
10
|
|
|
11
11
|
from digitalkin.logger import logger
|
|
12
12
|
from digitalkin.models import ModuleStatus
|
|
13
|
-
from digitalkin.models.module import
|
|
13
|
+
from digitalkin.models.module import InputModelT, OutputModelT, SetupModelT
|
|
14
14
|
from digitalkin.modules._base_module import BaseModule
|
|
15
15
|
from digitalkin.modules.job_manager.base_job_manager import BaseJobManager
|
|
16
|
+
from digitalkin.modules.job_manager.job_manager_models import StreamCodeModel
|
|
16
17
|
from digitalkin.services.services_models import ServicesMode
|
|
17
18
|
|
|
18
19
|
|
|
19
|
-
class SingleJobManager(BaseJobManager, Generic[InputModelT, SetupModelT
|
|
20
|
+
class SingleJobManager(BaseJobManager, Generic[InputModelT, SetupModelT]):
|
|
20
21
|
"""Manages a single instance of a module job.
|
|
21
22
|
|
|
22
23
|
This class ensures that only one instance of a module job is active at a time.
|
|
@@ -68,8 +69,7 @@ class SingleJobManager(BaseJobManager, Generic[InputModelT, SetupModelT, ConfigS
|
|
|
68
69
|
|
|
69
70
|
async def create_config_setup_instance_job(
|
|
70
71
|
self,
|
|
71
|
-
config_setup_data:
|
|
72
|
-
setup_data: SetupModelT,
|
|
72
|
+
config_setup_data: SetupModelT,
|
|
73
73
|
mission_id: str,
|
|
74
74
|
setup_version_id: str,
|
|
75
75
|
) -> str:
|
|
@@ -99,7 +99,6 @@ class SingleJobManager(BaseJobManager, Generic[InputModelT, SetupModelT, ConfigS
|
|
|
99
99
|
try:
|
|
100
100
|
await module.start_config_setup(
|
|
101
101
|
config_setup_data,
|
|
102
|
-
setup_data,
|
|
103
102
|
await self.job_specific_callback(self.add_to_queue, job_id),
|
|
104
103
|
)
|
|
105
104
|
logger.debug("Module %s (%s) started successfully", job_id, module.name)
|
|
@@ -166,7 +165,6 @@ class SingleJobManager(BaseJobManager, Generic[InputModelT, SetupModelT, ConfigS
|
|
|
166
165
|
):
|
|
167
166
|
logger.info(f"{job_id=}: {module.status=}")
|
|
168
167
|
yield await self.queues[job_id].get()
|
|
169
|
-
logger.info(f"{job_id=}: {module.status=} | {self.queues[job_id].empty()}")
|
|
170
168
|
|
|
171
169
|
finally:
|
|
172
170
|
del self.queues[job_id]
|
|
@@ -202,12 +200,14 @@ class SingleJobManager(BaseJobManager, Generic[InputModelT, SetupModelT, ConfigS
|
|
|
202
200
|
module = self.module_class(job_id, mission_id=mission_id, setup_version_id=setup_version_id)
|
|
203
201
|
self.modules[job_id] = module
|
|
204
202
|
self.queues[job_id] = asyncio.Queue()
|
|
203
|
+
callback = await self.job_specific_callback(self.add_to_queue, job_id)
|
|
205
204
|
|
|
206
205
|
try:
|
|
207
206
|
await module.start(
|
|
208
207
|
input_data,
|
|
209
208
|
setup_data,
|
|
210
|
-
|
|
209
|
+
callback,
|
|
210
|
+
done_callback=lambda _: asyncio.create_task(callback(StreamCodeModel(code="__END_OF_STREAM__"))),
|
|
211
211
|
)
|
|
212
212
|
logger.debug("Module %s (%s) started successfully", job_id, module.name)
|
|
213
213
|
except Exception:
|
|
@@ -180,7 +180,6 @@ async def run_config_module(
|
|
|
180
180
|
module_class: type[BaseModule],
|
|
181
181
|
services_mode: ServicesMode,
|
|
182
182
|
config_setup_data: dict,
|
|
183
|
-
setup_data: dict,
|
|
184
183
|
context: Context = TaskiqDepends(),
|
|
185
184
|
) -> None:
|
|
186
185
|
"""TaskIQ task allowing a module to compute in the background asynchronously.
|
|
@@ -209,6 +208,5 @@ async def run_config_module(
|
|
|
209
208
|
|
|
210
209
|
await module.start_config_setup(
|
|
211
210
|
module_class.create_config_setup_model(config_setup_data),
|
|
212
|
-
module_class.create_setup_model(setup_data),
|
|
213
211
|
callback,
|
|
214
212
|
)
|
{digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/job_manager/taskiq_job_manager.py
RENAMED
|
@@ -18,7 +18,7 @@ from typing import TYPE_CHECKING, Any, Generic
|
|
|
18
18
|
from rstream import Consumer, ConsumerOffsetSpecification, MessageContext, OffsetType
|
|
19
19
|
|
|
20
20
|
from digitalkin.logger import logger
|
|
21
|
-
from digitalkin.models.module import
|
|
21
|
+
from digitalkin.models.module import InputModelT, SetupModelT
|
|
22
22
|
from digitalkin.models.module.module import ModuleStatus
|
|
23
23
|
from digitalkin.modules._base_module import BaseModule
|
|
24
24
|
from digitalkin.modules.job_manager.base_job_manager import BaseJobManager
|
|
@@ -29,7 +29,7 @@ if TYPE_CHECKING:
|
|
|
29
29
|
from taskiq.task import AsyncTaskiqTask
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
class TaskiqJobManager(BaseJobManager, Generic[InputModelT, SetupModelT
|
|
32
|
+
class TaskiqJobManager(BaseJobManager, Generic[InputModelT, SetupModelT]):
|
|
33
33
|
"""Taskiq job manager for running modules in Taskiq tasks."""
|
|
34
34
|
|
|
35
35
|
services_mode: ServicesMode
|
|
@@ -134,8 +134,7 @@ class TaskiqJobManager(BaseJobManager, Generic[InputModelT, SetupModelT, ConfigS
|
|
|
134
134
|
|
|
135
135
|
async def create_config_setup_instance_job(
|
|
136
136
|
self,
|
|
137
|
-
config_setup_data:
|
|
138
|
-
setup_data: SetupModelT,
|
|
137
|
+
config_setup_data: SetupModelT,
|
|
139
138
|
mission_id: str,
|
|
140
139
|
setup_version_id: str,
|
|
141
140
|
) -> str:
|
|
@@ -173,7 +172,6 @@ class TaskiqJobManager(BaseJobManager, Generic[InputModelT, SetupModelT, ConfigS
|
|
|
173
172
|
self.module_class,
|
|
174
173
|
self.services_mode,
|
|
175
174
|
config_setup_data.model_dump(), # type: ignore
|
|
176
|
-
setup_data.model_dump(),
|
|
177
175
|
)
|
|
178
176
|
|
|
179
177
|
job_id = running_task.task_id
|
|
@@ -3,9 +3,8 @@
|
|
|
3
3
|
from abc import ABC
|
|
4
4
|
|
|
5
5
|
from digitalkin.models.module import InputModelT, OutputModelT, SecretModelT, SetupModelT
|
|
6
|
-
from digitalkin.models.module.module_types import ConfigSetupModelT
|
|
7
6
|
from digitalkin.modules._base_module import BaseModule # type: ignore
|
|
8
7
|
|
|
9
8
|
|
|
10
|
-
class ToolModule(BaseModule[InputModelT, OutputModelT, SetupModelT, SecretModelT,
|
|
9
|
+
class ToolModule(BaseModule[InputModelT, OutputModelT, SetupModelT, SecretModelT,], ABC):
|
|
11
10
|
"""ToolModule extends BaseModule to implement specific module types."""
|
|
@@ -97,7 +97,7 @@ class GrpcStorage(StorageStrategy, GrpcClientWrapper):
|
|
|
97
97
|
resp = self.exec_grpc_query("ReadRecord", req)
|
|
98
98
|
return self._build_record_from_proto(resp.stored_data)
|
|
99
99
|
except Exception:
|
|
100
|
-
logger.
|
|
100
|
+
logger.warning("gRPC ReadRecord failed for %s:%s", collection, record_id)
|
|
101
101
|
return None
|
|
102
102
|
|
|
103
103
|
def _update(
|
|
@@ -149,7 +149,7 @@ class GrpcStorage(StorageStrategy, GrpcClientWrapper):
|
|
|
149
149
|
)
|
|
150
150
|
self.exec_grpc_query("RemoveRecord", req)
|
|
151
151
|
except Exception:
|
|
152
|
-
logger.
|
|
152
|
+
logger.warning(
|
|
153
153
|
"gRPC RemoveRecord failed for %s:%s",
|
|
154
154
|
collection,
|
|
155
155
|
record_id,
|
|
@@ -174,7 +174,7 @@ class GrpcStorage(StorageStrategy, GrpcClientWrapper):
|
|
|
174
174
|
resp = self.exec_grpc_query("ListRecords", req)
|
|
175
175
|
return [self._build_record_from_proto(r) for r in resp.records]
|
|
176
176
|
except Exception:
|
|
177
|
-
logger.
|
|
177
|
+
logger.warning("gRPC ListRecords failed for %s", collection)
|
|
178
178
|
return []
|
|
179
179
|
|
|
180
180
|
def _remove_collection(self, collection: str) -> bool:
|
|
@@ -193,7 +193,7 @@ class GrpcStorage(StorageStrategy, GrpcClientWrapper):
|
|
|
193
193
|
)
|
|
194
194
|
self.exec_grpc_query("RemoveCollection", req)
|
|
195
195
|
except Exception:
|
|
196
|
-
logger.
|
|
196
|
+
logger.warning("gRPC RemoveCollection failed for %s", collection)
|
|
197
197
|
return False
|
|
198
198
|
return True
|
|
199
199
|
|
|
@@ -10,7 +10,7 @@ from pathlib import Path
|
|
|
10
10
|
from typing import ClassVar
|
|
11
11
|
|
|
12
12
|
from digitalkin.models.module.module_context import ModuleContext
|
|
13
|
-
from digitalkin.models.module.module_types import
|
|
13
|
+
from digitalkin.models.module.module_types import DataTrigger
|
|
14
14
|
from digitalkin.modules.trigger_handler import TriggerHandler
|
|
15
15
|
|
|
16
16
|
logger = logging.getLogger(__name__)
|
|
@@ -329,7 +329,7 @@ class ModuleDiscoverer:
|
|
|
329
329
|
for protocol, handlers_cls in self._trigger_handlers_cls.items():
|
|
330
330
|
self.trigger_handlers[protocol] = tuple(handler_cls(context) for handler_cls in set(handlers_cls))
|
|
331
331
|
|
|
332
|
-
def get_trigger(self, protocol: str, input_instance:
|
|
332
|
+
def get_trigger(self, protocol: str, input_instance: DataTrigger) -> TriggerHandler:
|
|
333
333
|
"""Retrieve a trigger handler instance based on the provided protocol and input instance type.
|
|
334
334
|
|
|
335
335
|
Args:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: digitalkin
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.19
|
|
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
|
|
@@ -458,30 +458,30 @@ Requires-Dist: grpcio-reflection>=1.71.0
|
|
|
458
458
|
Requires-Dist: grpcio-status>=1.71.0
|
|
459
459
|
Requires-Dist: pydantic>=2.11.5
|
|
460
460
|
Provides-Extra: dev
|
|
461
|
-
Requires-Dist: typos>=1.
|
|
462
|
-
Requires-Dist: ruff>=0.
|
|
463
|
-
Requires-Dist: mypy>=1.
|
|
464
|
-
Requires-Dist: pyright>=1.1.
|
|
461
|
+
Requires-Dist: typos>=1.34.0; extra == "dev"
|
|
462
|
+
Requires-Dist: ruff>=0.12.5; extra == "dev"
|
|
463
|
+
Requires-Dist: mypy>=1.17.0; extra == "dev"
|
|
464
|
+
Requires-Dist: pyright>=1.1.403; extra == "dev"
|
|
465
465
|
Requires-Dist: pre-commit>=4.2.0; extra == "dev"
|
|
466
466
|
Requires-Dist: bump2version>=1.0.1; extra == "dev"
|
|
467
467
|
Requires-Dist: build>=1.2.2; extra == "dev"
|
|
468
468
|
Requires-Dist: twine>=6.1.0; extra == "dev"
|
|
469
|
-
Requires-Dist: cryptography>=45.0.
|
|
469
|
+
Requires-Dist: cryptography>=45.0.5; extra == "dev"
|
|
470
470
|
Provides-Extra: examples
|
|
471
471
|
Requires-Dist: openai>=1.75.0; extra == "examples"
|
|
472
472
|
Provides-Extra: tests
|
|
473
|
-
Requires-Dist: freezegun>=1.5.
|
|
473
|
+
Requires-Dist: freezegun>=1.5.3; extra == "tests"
|
|
474
474
|
Requires-Dist: hdrhistogram>=0.10.3; extra == "tests"
|
|
475
475
|
Requires-Dist: grpcio-testing>=1.71.0; extra == "tests"
|
|
476
476
|
Requires-Dist: psutil>=7.0.0; extra == "tests"
|
|
477
477
|
Requires-Dist: pytest>=8.4.0; extra == "tests"
|
|
478
|
-
Requires-Dist: pytest-asyncio>=1.
|
|
478
|
+
Requires-Dist: pytest-asyncio>=1.1.0; extra == "tests"
|
|
479
479
|
Requires-Dist: pytest-cov>=6.1.0; extra == "tests"
|
|
480
480
|
Provides-Extra: taskiq
|
|
481
481
|
Requires-Dist: rstream>=0.30.0; extra == "taskiq"
|
|
482
|
-
Requires-Dist: taskiq-aio-pika>=0.4.
|
|
483
|
-
Requires-Dist: taskiq-redis>=1.0
|
|
484
|
-
Requires-Dist: taskiq[reload]>=0.11.
|
|
482
|
+
Requires-Dist: taskiq-aio-pika>=0.4.3; extra == "taskiq"
|
|
483
|
+
Requires-Dist: taskiq-redis>=1.1.0; extra == "taskiq"
|
|
484
|
+
Requires-Dist: taskiq[reload]>=0.11.18; extra == "taskiq"
|
|
485
485
|
Dynamic: license-file
|
|
486
486
|
|
|
487
487
|
# DigitalKin Python SDK
|
|
@@ -5,30 +5,30 @@ grpcio-status>=1.71.0
|
|
|
5
5
|
pydantic>=2.11.5
|
|
6
6
|
|
|
7
7
|
[dev]
|
|
8
|
-
typos>=1.
|
|
9
|
-
ruff>=0.
|
|
10
|
-
mypy>=1.
|
|
11
|
-
pyright>=1.1.
|
|
8
|
+
typos>=1.34.0
|
|
9
|
+
ruff>=0.12.5
|
|
10
|
+
mypy>=1.17.0
|
|
11
|
+
pyright>=1.1.403
|
|
12
12
|
pre-commit>=4.2.0
|
|
13
13
|
bump2version>=1.0.1
|
|
14
14
|
build>=1.2.2
|
|
15
15
|
twine>=6.1.0
|
|
16
|
-
cryptography>=45.0.
|
|
16
|
+
cryptography>=45.0.5
|
|
17
17
|
|
|
18
18
|
[examples]
|
|
19
19
|
openai>=1.75.0
|
|
20
20
|
|
|
21
21
|
[taskiq]
|
|
22
22
|
rstream>=0.30.0
|
|
23
|
-
taskiq-aio-pika>=0.4.
|
|
24
|
-
taskiq-redis>=1.0
|
|
25
|
-
taskiq[reload]>=0.11.
|
|
23
|
+
taskiq-aio-pika>=0.4.3
|
|
24
|
+
taskiq-redis>=1.1.0
|
|
25
|
+
taskiq[reload]>=0.11.18
|
|
26
26
|
|
|
27
27
|
[tests]
|
|
28
|
-
freezegun>=1.5.
|
|
28
|
+
freezegun>=1.5.3
|
|
29
29
|
hdrhistogram>=0.10.3
|
|
30
30
|
grpcio-testing>=1.71.0
|
|
31
31
|
psutil>=7.0.0
|
|
32
32
|
pytest>=8.4.0
|
|
33
|
-
pytest-asyncio>=1.
|
|
33
|
+
pytest-asyncio>=1.1.0
|
|
34
34
|
pytest-cov>=6.1.0
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
"""Types for module models."""
|
|
2
|
-
|
|
3
|
-
from typing import TypeVar
|
|
4
|
-
|
|
5
|
-
from pydantic import BaseModel
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class InputTrigger(BaseModel):
|
|
9
|
-
"""Defines the root input model exposing the protocol.
|
|
10
|
-
|
|
11
|
-
The mandatory protocol is important to define the module beahvior following the user or agent input.
|
|
12
|
-
|
|
13
|
-
Example:
|
|
14
|
-
class MyInput(InputModel):
|
|
15
|
-
root: InputTrigger
|
|
16
|
-
user_define_data: Any
|
|
17
|
-
|
|
18
|
-
# Usage
|
|
19
|
-
my_input = MyInput(root=InputTrigger(protocol="message"))
|
|
20
|
-
print(my_input.root.protocol) # Output: message
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
protocol: str
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
class InputModel(BaseModel):
|
|
27
|
-
"""Base definition of input model showing mandatory root fields.
|
|
28
|
-
|
|
29
|
-
The Model define the Module Input, usually referring to multiple input type defined by an union.
|
|
30
|
-
|
|
31
|
-
Example:
|
|
32
|
-
class ModuleInput(InputModel):
|
|
33
|
-
root: FileInput | MessageInput
|
|
34
|
-
"""
|
|
35
|
-
|
|
36
|
-
root: InputTrigger
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
ConfigSetupModelT = TypeVar("ConfigSetupModelT", bound=BaseModel | None)
|
|
40
|
-
InputModelT = TypeVar("InputModelT", bound=InputModel)
|
|
41
|
-
OutputModelT = TypeVar("OutputModelT", bound=BaseModel)
|
|
42
|
-
SetupModelT = TypeVar("SetupModelT", bound=BaseModel)
|
|
43
|
-
SecretModelT = TypeVar("SecretModelT", bound=BaseModel)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/utils/grpc_client_wrapper.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/job_manager/job_manager_models.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/filesystem/default_filesystem.py
RENAMED
|
File without changes
|
{digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/filesystem/filesystem_strategy.py
RENAMED
|
File without changes
|
{digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/filesystem/grpc_filesystem.py
RENAMED
|
File without changes
|
|
File without changes
|
{digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/identity/default_identity.py
RENAMED
|
File without changes
|
{digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/identity/identity_strategy.py
RENAMED
|
File without changes
|
|
File without changes
|
{digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/registry/default_registry.py
RENAMED
|
File without changes
|
{digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/registry/registry_strategy.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/snapshot/default_snapshot.py
RENAMED
|
File without changes
|
{digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/snapshot/snapshot_strategy.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|