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.
Files changed (95) hide show
  1. {digitalkin-0.2.18 → digitalkin-0.2.19}/PKG-INFO +11 -11
  2. {digitalkin-0.2.18 → digitalkin-0.2.19}/pyproject.toml +12 -12
  3. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/__version__.py +1 -1
  4. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/module_servicer.py +7 -7
  5. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/models/module/__init__.py +6 -6
  6. digitalkin-0.2.19/src/digitalkin/models/module/module_types.py +105 -0
  7. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/_base_module.py +54 -45
  8. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/archetype_module.py +0 -2
  9. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/job_manager/base_job_manager.py +2 -5
  10. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/job_manager/single_job_manager.py +7 -7
  11. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/job_manager/taskiq_broker.py +0 -2
  12. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/job_manager/taskiq_job_manager.py +3 -5
  13. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/tool_module.py +1 -2
  14. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/storage/grpc_storage.py +4 -4
  15. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/utils/package_discover.py +2 -2
  16. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin.egg-info/PKG-INFO +11 -11
  17. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin.egg-info/requires.txt +10 -10
  18. digitalkin-0.2.18/src/digitalkin/models/module/module_types.py +0 -43
  19. {digitalkin-0.2.18 → digitalkin-0.2.19}/LICENSE +0 -0
  20. {digitalkin-0.2.18 → digitalkin-0.2.19}/README.md +0 -0
  21. {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/base_server/__init__.py +0 -0
  22. {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/base_server/mock/__init__.py +0 -0
  23. {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/base_server/mock/mock_pb2.py +0 -0
  24. {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/base_server/mock/mock_pb2_grpc.py +0 -0
  25. {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/base_server/server_async_insecure.py +0 -0
  26. {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/base_server/server_async_secure.py +0 -0
  27. {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/base_server/server_sync_insecure.py +0 -0
  28. {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/base_server/server_sync_secure.py +0 -0
  29. {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/modules/__init__.py +0 -0
  30. {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/modules/cpu_intensive_module.py +0 -0
  31. {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/modules/minimal_llm_module.py +0 -0
  32. {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/modules/text_transform_module.py +0 -0
  33. {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/services/filesystem_module.py +0 -0
  34. {digitalkin-0.2.18 → digitalkin-0.2.19}/examples/services/storage_module.py +0 -0
  35. {digitalkin-0.2.18 → digitalkin-0.2.19}/setup.cfg +0 -0
  36. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/__init__.py +0 -0
  37. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/__init__.py +0 -0
  38. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/_base_server.py +0 -0
  39. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/module_server.py +0 -0
  40. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/registry_server.py +0 -0
  41. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/registry_servicer.py +0 -0
  42. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/utils/exceptions.py +0 -0
  43. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/utils/factory.py +0 -0
  44. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/utils/grpc_client_wrapper.py +0 -0
  45. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/utils/models.py +0 -0
  46. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/grpc_servers/utils/types.py +0 -0
  47. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/logger.py +0 -0
  48. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/models/__init__.py +0 -0
  49. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/models/module/module.py +0 -0
  50. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/models/module/module_context.py +0 -0
  51. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/models/services/__init__.py +0 -0
  52. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/models/services/cost.py +0 -0
  53. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/models/services/storage.py +0 -0
  54. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/__init__.py +0 -0
  55. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/job_manager/job_manager_models.py +0 -0
  56. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/modules/trigger_handler.py +0 -0
  57. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/py.typed +0 -0
  58. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/__init__.py +0 -0
  59. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/agent/__init__.py +0 -0
  60. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/agent/agent_strategy.py +0 -0
  61. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/agent/default_agent.py +0 -0
  62. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/base_strategy.py +0 -0
  63. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/cost/__init__.py +0 -0
  64. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/cost/cost_strategy.py +0 -0
  65. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/cost/default_cost.py +0 -0
  66. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/cost/grpc_cost.py +0 -0
  67. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/filesystem/__init__.py +0 -0
  68. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/filesystem/default_filesystem.py +0 -0
  69. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/filesystem/filesystem_strategy.py +0 -0
  70. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/filesystem/grpc_filesystem.py +0 -0
  71. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/identity/__init__.py +0 -0
  72. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/identity/default_identity.py +0 -0
  73. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/identity/identity_strategy.py +0 -0
  74. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/registry/__init__.py +0 -0
  75. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/registry/default_registry.py +0 -0
  76. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/registry/registry_strategy.py +0 -0
  77. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/services_config.py +0 -0
  78. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/services_models.py +0 -0
  79. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/setup/__init__.py +0 -0
  80. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/setup/default_setup.py +0 -0
  81. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/setup/grpc_setup.py +0 -0
  82. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/setup/setup_strategy.py +0 -0
  83. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/snapshot/__init__.py +0 -0
  84. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/snapshot/default_snapshot.py +0 -0
  85. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/snapshot/snapshot_strategy.py +0 -0
  86. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/storage/__init__.py +0 -0
  87. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/storage/default_storage.py +0 -0
  88. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/services/storage/storage_strategy.py +0 -0
  89. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/utils/__init__.py +0 -0
  90. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/utils/arg_parser.py +0 -0
  91. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/utils/development_mode_action.py +0 -0
  92. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin/utils/llm_ready_schema.py +0 -0
  93. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin.egg-info/SOURCES.txt +0 -0
  94. {digitalkin-0.2.18 → digitalkin-0.2.19}/src/digitalkin.egg-info/dependency_links.txt +0 -0
  95. {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.18
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.33.1; extra == "dev"
462
- Requires-Dist: ruff>=0.11.13; extra == "dev"
463
- Requires-Dist: mypy>=1.16.0; extra == "dev"
464
- Requires-Dist: pyright>=1.1.401; extra == "dev"
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.4; extra == "dev"
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.2; extra == "tests"
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.0.0; extra == "tests"
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.2; extra == "taskiq"
483
- Requires-Dist: taskiq-redis>=1.0.9; extra == "taskiq"
484
- Requires-Dist: taskiq[reload]>=0.11.17; extra == "taskiq"
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.18"
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.33.1",
42
- "ruff>=0.11.13",
43
- "mypy>=1.16.0",
44
- "pyright>=1.1.401",
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.4",
49
+ "cryptography>=45.0.5",
50
50
  ]
51
51
  examples = [ "openai>=1.75.0" ]
52
52
  tests = [
53
- "freezegun>=1.5.2",
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.0.0",
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.2",
64
- "taskiq-redis>=1.0.9",
65
- "taskiq[reload]>=0.11.17",
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]
@@ -5,4 +5,4 @@ from importlib.metadata import PackageNotFoundError, version
5
5
  try:
6
6
  __version__ = version("digitalkin")
7
7
  except PackageNotFoundError:
8
- __version__ = "0.2.18"
8
+ __version__ = "0.2.19"
@@ -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
- ConfigSetupModelT,
7
- InputModel,
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
- "ConfigSetupModelT",
17
- "InputModel",
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 ModuleErrorModel(BaseModel):
34
+ class ModuleCodeModel(BaseModel):
37
35
  """typed error/code model."""
38
36
 
39
37
  code: str
40
- exception: str
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
- config_setup_format: type[ConfigSetupModelT]
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
- OptionalFeatureNotImplementedError: If the `config_setup_format` is not defined.
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
- config_setup_format = getattr(cls, "config_setup_format", None)
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(config_setup_format), indent=2)
186
- return json.dumps(config_setup_format.model_json_schema(), indent=2)
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 OptionalFeatureNotImplementedError(msg)
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(cls.setup_format), indent=2)
203
- return json.dumps(cls.setup_format.model_json_schema(), indent=2)
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]) -> ConfigSetupModelT:
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.config_setup_format(**config_setup_data)
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
- @abstractmethod
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
- Raises:
303
- OptionalFeatureNotImplementedError: If the config setup feature is not implemented.
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
- msg = f"'{self}' class does not define an optional 'run_config_setup' attribute."
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.warning("Starting module %s", self.name)
368
+ logger.info("Starting module %s", self.name)
368
369
  await self.run(input_data, setup_data, callback)
369
- logger.warning("Module %s finished", self.name)
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.STOPPED
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 | ModuleErrorModel], Coroutine[Any, Any, None]],
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.info("Inititalize module")
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
- ModuleErrorModel(
398
+ ModuleCodeModel(
398
399
  code=str(self._status),
399
400
  short_description=short_description,
400
- exception=str(e),
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.info("Init the discod input handlers.")
410
+ logger.debug("Init the discovered input handlers.")
410
411
  self.triggers_discoverer.init_handlers(self.context)
411
- logger.info("Run lifecycle")
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
- if self._status != ModuleStatus.RUNNING:
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: ConfigSetupModelT,
442
- setup_data: SetupModelT,
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, setup_data, callback)
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
  ):
@@ -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, ConfigSetupModelT]):
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: ConfigSetupModelT,
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
 
@@ -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 ConfigSetupModelT, InputModelT, OutputModelT, SetupModelT
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, ConfigSetupModelT]):
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: ConfigSetupModelT,
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
- await self.job_specific_callback(self.add_to_queue, job_id),
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
  )
@@ -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 ConfigSetupModelT, InputModelT, SetupModelT
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, ConfigSetupModelT]):
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: ConfigSetupModelT,
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,ConfigSetupModelT,], ABC):
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.exception("gRPC ReadRecord failed for %s:%s", collection, record_id)
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.exception(
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.exception("gRPC ListRecords failed for %s", collection)
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.exception("gRPC RemoveCollection failed for %s", collection)
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 InputTrigger
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: InputTrigger) -> TriggerHandler:
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.18
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.33.1; extra == "dev"
462
- Requires-Dist: ruff>=0.11.13; extra == "dev"
463
- Requires-Dist: mypy>=1.16.0; extra == "dev"
464
- Requires-Dist: pyright>=1.1.401; extra == "dev"
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.4; extra == "dev"
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.2; extra == "tests"
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.0.0; extra == "tests"
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.2; extra == "taskiq"
483
- Requires-Dist: taskiq-redis>=1.0.9; extra == "taskiq"
484
- Requires-Dist: taskiq[reload]>=0.11.17; extra == "taskiq"
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.33.1
9
- ruff>=0.11.13
10
- mypy>=1.16.0
11
- pyright>=1.1.401
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.4
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.2
24
- taskiq-redis>=1.0.9
25
- taskiq[reload]>=0.11.17
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.2
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.0.0
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