digitalkin 0.2.19__tar.gz → 0.2.20__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 (94) hide show
  1. {digitalkin-0.2.19 → digitalkin-0.2.20}/PKG-INFO +3 -3
  2. {digitalkin-0.2.19 → digitalkin-0.2.20}/pyproject.toml +3 -3
  3. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/__version__.py +1 -1
  4. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/grpc_servers/module_servicer.py +2 -0
  5. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/modules/_base_module.py +18 -2
  6. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/modules/job_manager/base_job_manager.py +6 -2
  7. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/modules/job_manager/single_job_manager.py +12 -3
  8. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/modules/job_manager/taskiq_broker.py +6 -2
  9. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/modules/job_manager/taskiq_job_manager.py +6 -0
  10. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/base_strategy.py +3 -1
  11. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/cost/cost_strategy.py +9 -2
  12. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/cost/default_cost.py +3 -2
  13. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/cost/grpc_cost.py +2 -1
  14. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/filesystem/default_filesystem.py +9 -7
  15. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/filesystem/filesystem_strategy.py +10 -3
  16. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/filesystem/grpc_filesystem.py +10 -8
  17. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/services_config.py +3 -2
  18. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/storage/default_storage.py +2 -1
  19. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/storage/grpc_storage.py +2 -1
  20. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/storage/storage_strategy.py +9 -2
  21. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin.egg-info/PKG-INFO +3 -3
  22. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin.egg-info/requires.txt +2 -2
  23. {digitalkin-0.2.19 → digitalkin-0.2.20}/LICENSE +0 -0
  24. {digitalkin-0.2.19 → digitalkin-0.2.20}/README.md +0 -0
  25. {digitalkin-0.2.19 → digitalkin-0.2.20}/examples/base_server/__init__.py +0 -0
  26. {digitalkin-0.2.19 → digitalkin-0.2.20}/examples/base_server/mock/__init__.py +0 -0
  27. {digitalkin-0.2.19 → digitalkin-0.2.20}/examples/base_server/mock/mock_pb2.py +0 -0
  28. {digitalkin-0.2.19 → digitalkin-0.2.20}/examples/base_server/mock/mock_pb2_grpc.py +0 -0
  29. {digitalkin-0.2.19 → digitalkin-0.2.20}/examples/base_server/server_async_insecure.py +0 -0
  30. {digitalkin-0.2.19 → digitalkin-0.2.20}/examples/base_server/server_async_secure.py +0 -0
  31. {digitalkin-0.2.19 → digitalkin-0.2.20}/examples/base_server/server_sync_insecure.py +0 -0
  32. {digitalkin-0.2.19 → digitalkin-0.2.20}/examples/base_server/server_sync_secure.py +0 -0
  33. {digitalkin-0.2.19 → digitalkin-0.2.20}/examples/modules/__init__.py +0 -0
  34. {digitalkin-0.2.19 → digitalkin-0.2.20}/examples/modules/cpu_intensive_module.py +0 -0
  35. {digitalkin-0.2.19 → digitalkin-0.2.20}/examples/modules/minimal_llm_module.py +0 -0
  36. {digitalkin-0.2.19 → digitalkin-0.2.20}/examples/modules/text_transform_module.py +0 -0
  37. {digitalkin-0.2.19 → digitalkin-0.2.20}/examples/services/filesystem_module.py +0 -0
  38. {digitalkin-0.2.19 → digitalkin-0.2.20}/examples/services/storage_module.py +0 -0
  39. {digitalkin-0.2.19 → digitalkin-0.2.20}/setup.cfg +0 -0
  40. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/__init__.py +0 -0
  41. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/grpc_servers/__init__.py +0 -0
  42. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/grpc_servers/_base_server.py +0 -0
  43. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/grpc_servers/module_server.py +0 -0
  44. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/grpc_servers/registry_server.py +0 -0
  45. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/grpc_servers/registry_servicer.py +0 -0
  46. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/grpc_servers/utils/exceptions.py +0 -0
  47. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/grpc_servers/utils/factory.py +0 -0
  48. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/grpc_servers/utils/grpc_client_wrapper.py +0 -0
  49. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/grpc_servers/utils/models.py +0 -0
  50. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/grpc_servers/utils/types.py +0 -0
  51. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/logger.py +0 -0
  52. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/models/__init__.py +0 -0
  53. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/models/module/__init__.py +0 -0
  54. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/models/module/module.py +0 -0
  55. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/models/module/module_context.py +0 -0
  56. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/models/module/module_types.py +0 -0
  57. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/models/services/__init__.py +0 -0
  58. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/models/services/cost.py +0 -0
  59. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/models/services/storage.py +0 -0
  60. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/modules/__init__.py +0 -0
  61. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/modules/archetype_module.py +0 -0
  62. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/modules/job_manager/job_manager_models.py +0 -0
  63. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/modules/tool_module.py +0 -0
  64. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/modules/trigger_handler.py +0 -0
  65. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/py.typed +0 -0
  66. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/__init__.py +0 -0
  67. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/agent/__init__.py +0 -0
  68. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/agent/agent_strategy.py +0 -0
  69. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/agent/default_agent.py +0 -0
  70. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/cost/__init__.py +0 -0
  71. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/filesystem/__init__.py +0 -0
  72. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/identity/__init__.py +0 -0
  73. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/identity/default_identity.py +0 -0
  74. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/identity/identity_strategy.py +0 -0
  75. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/registry/__init__.py +0 -0
  76. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/registry/default_registry.py +0 -0
  77. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/registry/registry_strategy.py +0 -0
  78. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/services_models.py +0 -0
  79. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/setup/__init__.py +0 -0
  80. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/setup/default_setup.py +0 -0
  81. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/setup/grpc_setup.py +0 -0
  82. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/setup/setup_strategy.py +0 -0
  83. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/snapshot/__init__.py +0 -0
  84. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/snapshot/default_snapshot.py +0 -0
  85. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/snapshot/snapshot_strategy.py +0 -0
  86. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/services/storage/__init__.py +0 -0
  87. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/utils/__init__.py +0 -0
  88. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/utils/arg_parser.py +0 -0
  89. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/utils/development_mode_action.py +0 -0
  90. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/utils/llm_ready_schema.py +0 -0
  91. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin/utils/package_discover.py +0 -0
  92. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin.egg-info/SOURCES.txt +0 -0
  93. {digitalkin-0.2.19 → digitalkin-0.2.20}/src/digitalkin.egg-info/dependency_links.txt +0 -0
  94. {digitalkin-0.2.19 → digitalkin-0.2.20}/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.19
3
+ Version: 0.2.20
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
@@ -462,9 +462,9 @@ Requires-Dist: typos>=1.34.0; extra == "dev"
462
462
  Requires-Dist: ruff>=0.12.5; extra == "dev"
463
463
  Requires-Dist: mypy>=1.17.0; extra == "dev"
464
464
  Requires-Dist: pyright>=1.1.403; extra == "dev"
465
- Requires-Dist: pre-commit>=4.2.0; extra == "dev"
465
+ Requires-Dist: pre-commit>=4.3.0; extra == "dev"
466
466
  Requires-Dist: bump2version>=1.0.1; extra == "dev"
467
- Requires-Dist: build>=1.2.2; extra == "dev"
467
+ Requires-Dist: build>=1.3.0; extra == "dev"
468
468
  Requires-Dist: twine>=6.1.0; extra == "dev"
469
469
  Requires-Dist: cryptography>=45.0.5; extra == "dev"
470
470
  Provides-Extra: examples
@@ -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.19"
15
+ version = "0.2.20"
16
16
 
17
17
  classifiers = [
18
18
  "Development Status :: 3 - Alpha",
@@ -42,9 +42,9 @@
42
42
  "ruff>=0.12.5",
43
43
  "mypy>=1.17.0",
44
44
  "pyright>=1.1.403",
45
- "pre-commit>=4.2.0",
45
+ "pre-commit>=4.3.0",
46
46
  "bump2version>=1.0.1",
47
- "build>=1.2.2",
47
+ "build>=1.3.0",
48
48
  "twine>=6.1.0",
49
49
  "cryptography>=45.0.5",
50
50
  ]
@@ -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.19"
8
+ __version__ = "0.2.20"
@@ -121,6 +121,7 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer, ArgParser):
121
121
  job_id = await self.job_manager.create_config_setup_instance_job(
122
122
  config_setup_data,
123
123
  request.mission_id,
124
+ setup_version.setup_id,
124
125
  setup_version.id,
125
126
  )
126
127
 
@@ -177,6 +178,7 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer, ArgParser):
177
178
  input_data,
178
179
  setup_data,
179
180
  mission_id=request.mission_id,
181
+ setup_id=setup_data_class.current_setup_version.setup_id,
180
182
  setup_version_id=setup_data_class.current_setup_version.id,
181
183
  )
182
184
 
@@ -54,7 +54,6 @@ class BaseModule( # noqa: PLR0904
54
54
  description: str
55
55
 
56
56
  setup_format: type[SetupModelT]
57
-
58
57
  input_format: type[InputModelT]
59
58
  output_format: type[OutputModelT]
60
59
  secret_format: type[SecretModelT]
@@ -77,21 +76,38 @@ class BaseModule( # noqa: PLR0904
77
76
  snapshot: SnapshotStrategy
78
77
  storage: StorageStrategy
79
78
 
79
+ # runtime params
80
+ job_id: str
81
+ mission_id: str
82
+ setup_id: str
83
+ setup_version_id: str
84
+ _status: ModuleStatus
85
+ _task: asyncio.Task | None
86
+
80
87
  def _init_strategies(self) -> None:
81
88
  """Initialize the services configuration."""
82
89
  for service_name in self.services_config.valid_strategy_names():
83
- service = self.services_config.init_strategy(service_name, self.mission_id, self.setup_version_id)
90
+ service = self.services_config.init_strategy(
91
+ service_name,
92
+ self.mission_id,
93
+ self.setup_id,
94
+ self.setup_version_id,
95
+ )
84
96
  setattr(self, service_name, service)
85
97
 
86
98
  def __init__(
87
99
  self,
88
100
  job_id: str,
89
101
  mission_id: str,
102
+ setup_id: str,
90
103
  setup_version_id: str,
91
104
  ) -> None:
92
105
  """Initialize the module."""
93
106
  self.job_id: str = job_id
94
107
  self.mission_id: str = mission_id
108
+ # Setup reference needed for the overall Kin scope as the filesystem context
109
+ self.setup_id: str = setup_id
110
+ # SetupVersion reference needed for the precise Kin scope as the cost
95
111
  self.setup_version_id: str = setup_version_id
96
112
  self._status = ModuleStatus.CREATED
97
113
  self._task: asyncio.Task | None = None
@@ -87,6 +87,7 @@ class BaseJobManager(abc.ABC, Generic[InputModelT, SetupModelT]):
87
87
  input_data: InputModelT,
88
88
  setup_data: SetupModelT,
89
89
  mission_id: str,
90
+ setup_id: str,
90
91
  setup_version_id: str,
91
92
  ) -> str:
92
93
  """Create and start a new job for the module's instance.
@@ -95,7 +96,8 @@ class BaseJobManager(abc.ABC, Generic[InputModelT, SetupModelT]):
95
96
  input_data: The input data required to start the job.
96
97
  setup_data: The setup configuration for the module.
97
98
  mission_id: The mission ID associated with the job.
98
- setup_version_id: The setup ID associated with the module.
99
+ setup_id: The setup ID.
100
+ setup_version_id: The setup version ID associated with the module.
99
101
 
100
102
  Returns:
101
103
  str: The unique identifier (job ID) of the created job.
@@ -121,6 +123,7 @@ class BaseJobManager(abc.ABC, Generic[InputModelT, SetupModelT]):
121
123
  self,
122
124
  config_setup_data: SetupModelT,
123
125
  mission_id: str,
126
+ setup_id: str,
124
127
  setup_version_id: str,
125
128
  ) -> str:
126
129
  """Create and start a new module job.
@@ -131,7 +134,8 @@ class BaseJobManager(abc.ABC, Generic[InputModelT, SetupModelT]):
131
134
  Args:
132
135
  config_setup_data: The input data required to start the job.
133
136
  mission_id: The mission ID associated with the job.
134
- setup_version_id: The setup ID.
137
+ setup_id: The setup ID.
138
+ setup_version_id: The setup version ID.
135
139
 
136
140
  Returns:
137
141
  str: The unique identifier (job ID) of the created job.
@@ -71,6 +71,7 @@ class SingleJobManager(BaseJobManager, Generic[InputModelT, SetupModelT]):
71
71
  self,
72
72
  config_setup_data: SetupModelT,
73
73
  mission_id: str,
74
+ setup_id: str,
74
75
  setup_version_id: str,
75
76
  ) -> str:
76
77
  """Create and start a new module setup configuration job.
@@ -82,6 +83,7 @@ class SingleJobManager(BaseJobManager, Generic[InputModelT, SetupModelT]):
82
83
  config_setup_data: The input data required to start the job.
83
84
  setup_data: The setup configuration for the module.
84
85
  mission_id: The mission ID associated with the job.
86
+ setup_id: The setup ID associated with the module.
85
87
  setup_version_id: The setup ID.
86
88
 
87
89
  Returns:
@@ -92,7 +94,7 @@ class SingleJobManager(BaseJobManager, Generic[InputModelT, SetupModelT]):
92
94
  """
93
95
  job_id = str(uuid.uuid4())
94
96
  # TODO: Ensure the job_id is unique.
95
- module = self.module_class(job_id, mission_id=mission_id, setup_version_id=setup_version_id)
97
+ module = self.module_class(job_id, mission_id=mission_id, setup_id=setup_id, setup_version_id=setup_version_id)
96
98
  self.modules[job_id] = module
97
99
  self.queues[job_id] = asyncio.Queue()
98
100
 
@@ -176,6 +178,7 @@ class SingleJobManager(BaseJobManager, Generic[InputModelT, SetupModelT]):
176
178
  input_data: InputModelT,
177
179
  setup_data: SetupModelT,
178
180
  mission_id: str,
181
+ setup_id: str,
179
182
  setup_version_id: str,
180
183
  ) -> str:
181
184
  """Create and start a new module job.
@@ -187,7 +190,8 @@ class SingleJobManager(BaseJobManager, Generic[InputModelT, SetupModelT]):
187
190
  input_data: The input data required to start the job.
188
191
  setup_data: The setup configuration for the module.
189
192
  mission_id: The mission ID associated with the job.
190
- setup_version_id: The setup ID associated with the module.
193
+ setup_id: The setup ID associated with the module.
194
+ setup_version_id: The setup Version ID associated with the module.
191
195
 
192
196
  Returns:
193
197
  str: The unique identifier (job ID) of the created job.
@@ -197,7 +201,12 @@ class SingleJobManager(BaseJobManager, Generic[InputModelT, SetupModelT]):
197
201
  """
198
202
  job_id = str(uuid.uuid4())
199
203
  # TODO: Ensure the job_id is unique.
200
- module = self.module_class(job_id, mission_id=mission_id, setup_version_id=setup_version_id)
204
+ module = self.module_class(
205
+ job_id,
206
+ mission_id=mission_id,
207
+ setup_id=setup_id,
208
+ setup_version_id=setup_version_id,
209
+ )
201
210
  self.modules[job_id] = module
202
211
  self.queues[job_id] = asyncio.Queue()
203
212
  callback = await self.job_specific_callback(self.add_to_queue, job_id)
@@ -132,6 +132,7 @@ async def send_message_to_stream(job_id: str, output_data: OutputModelT) -> None
132
132
  @TASKIQ_BROKER.task
133
133
  async def run_start_module(
134
134
  mission_id: str,
135
+ setup_id: str,
135
136
  setup_version_id: str,
136
137
  module_class: type[BaseModule],
137
138
  services_mode: ServicesMode,
@@ -143,6 +144,7 @@ async def run_start_module(
143
144
 
144
145
  Args:
145
146
  mission_id: str,
147
+ setup_id: The setup ID associated with the module.
146
148
  setup_version_id: The setup ID associated with the module.
147
149
  module_class: type[BaseModule],
148
150
  services_mode: ServicesMode,
@@ -161,7 +163,7 @@ async def run_start_module(
161
163
 
162
164
  job_id = context.message.task_id
163
165
  callback = await BaseJobManager.job_specific_callback(send_message_to_stream, job_id)
164
- module = module_class(job_id, mission_id=mission_id, setup_version_id=setup_version_id)
166
+ module = module_class(job_id, mission_id=mission_id, setup_id=setup_id, setup_version_id=setup_version_id)
165
167
 
166
168
  await module.start(
167
169
  input_data,
@@ -176,6 +178,7 @@ async def run_start_module(
176
178
  @TASKIQ_BROKER.task
177
179
  async def run_config_module(
178
180
  mission_id: str,
181
+ setup_id: str,
179
182
  setup_version_id: str,
180
183
  module_class: type[BaseModule],
181
184
  services_mode: ServicesMode,
@@ -186,6 +189,7 @@ async def run_config_module(
186
189
 
187
190
  Args:
188
191
  mission_id: str,
192
+ setup_id: The setup ID associated with the module.
189
193
  setup_version_id: The setup ID associated with the module.
190
194
  module_class: type[BaseModule],
191
195
  services_mode: ServicesMode,
@@ -204,7 +208,7 @@ async def run_config_module(
204
208
 
205
209
  job_id = context.message.task_id
206
210
  callback = await BaseJobManager.job_specific_callback(send_message_to_stream, job_id)
207
- module = module_class(job_id, mission_id=mission_id, setup_version_id=setup_version_id)
211
+ module = module_class(job_id, mission_id=mission_id, setup_id=setup_id, setup_version_id=setup_version_id)
208
212
 
209
213
  await module.start_config_setup(
210
214
  module_class.create_config_setup_model(config_setup_data),
@@ -136,6 +136,7 @@ class TaskiqJobManager(BaseJobManager, Generic[InputModelT, SetupModelT]):
136
136
  self,
137
137
  config_setup_data: SetupModelT,
138
138
  mission_id: str,
139
+ setup_id: str,
139
140
  setup_version_id: str,
140
141
  ) -> str:
141
142
  """Create and start a new module setup configuration job.
@@ -147,6 +148,7 @@ class TaskiqJobManager(BaseJobManager, Generic[InputModelT, SetupModelT]):
147
148
  config_setup_data: The input data required to start the job.
148
149
  setup_data: The setup configuration for the module.
149
150
  mission_id: The mission ID associated with the job.
151
+ setup_id: The setup ID associated with the module.
150
152
  setup_version_id: The setup ID.
151
153
 
152
154
  Returns:
@@ -168,6 +170,7 @@ class TaskiqJobManager(BaseJobManager, Generic[InputModelT, SetupModelT]):
168
170
 
169
171
  running_task: AsyncTaskiqTask[Any] = await task.kiq(
170
172
  mission_id,
173
+ setup_id,
171
174
  setup_version_id,
172
175
  self.module_class,
173
176
  self.services_mode,
@@ -221,6 +224,7 @@ class TaskiqJobManager(BaseJobManager, Generic[InputModelT, SetupModelT]):
221
224
  input_data: InputModelT,
222
225
  setup_data: SetupModelT,
223
226
  mission_id: str,
227
+ setup_id: str,
224
228
  setup_version_id: str,
225
229
  ) -> str:
226
230
  """Launches the module_task in Taskiq, returns the Taskiq task id as job_id.
@@ -229,6 +233,7 @@ class TaskiqJobManager(BaseJobManager, Generic[InputModelT, SetupModelT]):
229
233
  input_data: Input data for the module
230
234
  setup_data: Setup data for the module
231
235
  mission_id: Mission ID for the module
236
+ setup_id: The setup ID associated with the module.
232
237
  setup_version_id: The setup ID associated with the module.
233
238
 
234
239
  Returns:
@@ -245,6 +250,7 @@ class TaskiqJobManager(BaseJobManager, Generic[InputModelT, SetupModelT]):
245
250
 
246
251
  running_task: AsyncTaskiqTask[Any] = await task.kiq(
247
252
  mission_id,
253
+ setup_id,
248
254
  setup_version_id,
249
255
  self.module_class,
250
256
  self.services_mode,
@@ -9,12 +9,14 @@ class BaseStrategy(ABC):
9
9
  This class defines the interface for all strategies.
10
10
  """
11
11
 
12
- def __init__(self, mission_id: str, setup_version_id: str) -> None:
12
+ def __init__(self, mission_id: str, setup_id: str, setup_version_id: str) -> None:
13
13
  """Initialize the strategy.
14
14
 
15
15
  Args:
16
16
  mission_id: The ID of the mission this strategy is associated with
17
+ setup_id: The ID of the setup this strategy is associated with
17
18
  setup_version_id: The ID of the setup version this strategy is associated with
18
19
  """
19
20
  self.mission_id: str = mission_id
21
+ self.setup_id: str = setup_id
20
22
  self.setup_version_id: str = setup_version_id
@@ -57,15 +57,22 @@ class CostServiceError(Exception):
57
57
  class CostStrategy(BaseStrategy, ABC):
58
58
  """Abstract base class for cost strategies."""
59
59
 
60
- def __init__(self, mission_id: str, setup_version_id: str, config: dict[str, CostConfig]) -> None:
60
+ def __init__(
61
+ self,
62
+ mission_id: str,
63
+ setup_id: str,
64
+ setup_version_id: str,
65
+ config: dict[str, CostConfig],
66
+ ) -> None:
61
67
  """Initialize the strategy.
62
68
 
63
69
  Args:
64
70
  mission_id: The ID of the mission this strategy is associated with
71
+ setup_id: The ID of the setup
65
72
  setup_version_id: The ID of the setup version this strategy is associated with
66
73
  config: Configuration dictionary for the strategy
67
74
  """
68
- super().__init__(mission_id, setup_version_id)
75
+ super().__init__(mission_id, setup_id, setup_version_id)
69
76
  self.config = config
70
77
 
71
78
  @abstractmethod
@@ -15,15 +15,16 @@ from digitalkin.services.cost.cost_strategy import (
15
15
  class DefaultCost(CostStrategy):
16
16
  """Default cost strategy."""
17
17
 
18
- def __init__(self, mission_id: str, setup_version_id: str, config: dict[str, CostConfig]) -> None:
18
+ def __init__(self, mission_id: str, setup_id: str, setup_version_id: str, config: dict[str, CostConfig]) -> None:
19
19
  """Initialize the strategy.
20
20
 
21
21
  Args:
22
22
  mission_id: The ID of the mission this strategy is associated with
23
+ setup_id: The ID of the setup
23
24
  setup_version_id: The ID of the setup version this strategy is associated with
24
25
  config: The configuration dictionary for the cost
25
26
  """
26
- super().__init__(mission_id=mission_id, setup_version_id=setup_version_id, config=config)
27
+ super().__init__(mission_id=mission_id, setup_id=setup_id, setup_version_id=setup_version_id, config=config)
27
28
  self.db: dict[str, list[CostData]] = {}
28
29
 
29
30
  def add(
@@ -57,12 +57,13 @@ class GrpcCost(CostStrategy, GrpcClientWrapper):
57
57
  def __init__(
58
58
  self,
59
59
  mission_id: str,
60
+ setup_id: str,
60
61
  setup_version_id: str,
61
62
  config: dict[str, CostConfig],
62
63
  client_config: ClientConfig,
63
64
  ) -> None:
64
65
  """Initialize the cost."""
65
- super().__init__(mission_id=mission_id, setup_version_id=setup_version_id, config=config)
66
+ super().__init__(mission_id=mission_id, setup_id=setup_id, setup_version_id=setup_version_id, config=config)
66
67
  channel = self._init_channel(client_config)
67
68
  self.stub = cost_service_pb2_grpc.CostServiceStub(channel)
68
69
  logger.debug("Channel client 'Cost' initialized succesfully")
@@ -25,14 +25,15 @@ class DefaultFilesystem(FilesystemStrategy):
25
25
  Files are stored in a temporary directory with proper metadata tracking.
26
26
  """
27
27
 
28
- def __init__(self, mission_id: str, setup_version_id: str) -> None:
28
+ def __init__(self, mission_id: str, setup_id: str, setup_version_id: str) -> None:
29
29
  """Initialize the default filesystem strategy.
30
30
 
31
31
  Args:
32
32
  mission_id: The ID of the mission this strategy is associated with
33
+ setup_id: The ID of the setup
33
34
  setup_version_id: The ID of the setup version this strategy is associated with
34
35
  """
35
- super().__init__(mission_id, setup_version_id)
36
+ super().__init__(mission_id, setup_id, setup_version_id)
36
37
  self.temp_root: str = tempfile.mkdtemp()
37
38
  os.makedirs(self.temp_root, exist_ok=True)
38
39
  self.db: dict[str, FilesystemRecord] = {}
@@ -118,7 +119,7 @@ class DefaultFilesystem(FilesystemStrategy):
118
119
  for file in files:
119
120
  try:
120
121
  # Check if file with same name exists in the context
121
- context_dir = self._get_context_temp_dir(self.mission_id)
122
+ context_dir = self._get_context_temp_dir(self.setup_id)
122
123
  file_path = os.path.join(context_dir, file.name)
123
124
  if os.path.exists(file_path) and not file.replace_if_exists:
124
125
  msg = f"File with name {file.name} already exists."
@@ -129,7 +130,7 @@ class DefaultFilesystem(FilesystemStrategy):
129
130
  storage_uri = str(Path(file_path).resolve())
130
131
  file_data = FilesystemRecord(
131
132
  id=str(uuid.uuid4()),
132
- context=self.mission_id,
133
+ context=self.setup_id,
133
134
  name=file.name,
134
135
  file_type=file.file_type,
135
136
  content_type=file.content_type or "application/octet-stream",
@@ -138,14 +139,13 @@ class DefaultFilesystem(FilesystemStrategy):
138
139
  metadata=file.metadata,
139
140
  storage_uri=storage_uri,
140
141
  file_url=storage_uri,
141
- status=file.status if hasattr(file, "status") and file.status else "ACTIVE",
142
+ status="ACTIVE",
142
143
  )
143
144
 
144
145
  self.db[file_data.id] = file_data
145
146
  uploaded_files.append(file_data)
146
147
  total_uploaded += 1
147
148
  logger.debug("Uploaded file %s", file_data)
148
-
149
149
  except Exception as e: # noqa: PERF203
150
150
  logger.exception("Error uploading file %s: %s", file.name, e)
151
151
  total_failed += 1
@@ -199,6 +199,8 @@ class DefaultFilesystem(FilesystemStrategy):
199
199
  end_idx = start_idx + list_size
200
200
  paginated_files = filtered_files[start_idx:end_idx]
201
201
 
202
+ logger.critical(f"{filters=} | {paginated_files=}")
203
+
202
204
  if include_content:
203
205
  for file in paginated_files:
204
206
  file.content = Path(file.storage_uri).read_bytes()
@@ -306,7 +308,7 @@ class DefaultFilesystem(FilesystemStrategy):
306
308
  raise FilesystemServiceError(msg)
307
309
 
308
310
  try:
309
- context_dir = self._get_context_temp_dir(self.mission_id)
311
+ context_dir = self._get_context_temp_dir(self.setup_id)
310
312
  file_path = os.path.join(context_dir, file_id)
311
313
  existing_file = self.db[file_id]
312
314
 
@@ -90,15 +90,22 @@ class FilesystemStrategy(BaseStrategy, ABC):
90
90
  filtering, and pagination.
91
91
  """
92
92
 
93
- def __init__(self, mission_id: str, setup_version_id: str, config: dict[str, Any] | None = None) -> None:
93
+ def __init__(
94
+ self,
95
+ mission_id: str,
96
+ setup_id: str,
97
+ setup_version_id: str,
98
+ config: dict[str, Any] | None = None,
99
+ ) -> None:
94
100
  """Initialize the strategy.
95
101
 
96
102
  Args:
97
103
  mission_id: The ID of the mission this strategy is associated with
104
+ setup_id: The ID of the setup
98
105
  setup_version_id: The ID of the setup version this strategy is associated with
99
106
  config: Configuration for the filesystem strategy
100
107
  """
101
- super().__init__(mission_id, setup_version_id)
108
+ super().__init__(mission_id, setup_id, setup_version_id)
102
109
  self.config = config
103
110
 
104
111
  @abstractmethod
@@ -125,7 +132,7 @@ class FilesystemStrategy(BaseStrategy, ABC):
125
132
  file_id: str,
126
133
  *,
127
134
  include_content: bool = False,
128
- ) -> tuple[FilesystemRecord, bytes | None]:
135
+ ) -> FilesystemRecord:
129
136
  """Get a specific file by ID or name.
130
137
 
131
138
  This method fetches detailed information about a single file,
@@ -95,7 +95,7 @@ class GrpcFilesystem(FilesystemStrategy, GrpcClientWrapper):
95
95
  filesystem_pb2.FileFilter: The converted FileFilter proto message
96
96
  """
97
97
  return filesystem_pb2.FileFilter(
98
- context=self.mission_id,
98
+ context=self.setup_id,
99
99
  **filters.model_dump(exclude={"file_types", "status"}),
100
100
  file_types=[self._file_type_to_enum(file_type) for file_type in filters.file_types]
101
101
  if filters.file_types
@@ -114,7 +114,7 @@ class GrpcFilesystem(FilesystemStrategy, GrpcClientWrapper):
114
114
  """
115
115
  return FilesystemRecord(
116
116
  id=file.file_id,
117
- context=self.mission_id,
117
+ context=self.setup_id,
118
118
  name=file.name,
119
119
  file_type=filesystem_pb2.FileType.Name(file.file_type),
120
120
  content_type=file.content_type,
@@ -130,6 +130,7 @@ class GrpcFilesystem(FilesystemStrategy, GrpcClientWrapper):
130
130
  def __init__(
131
131
  self,
132
132
  mission_id: str,
133
+ setup_id: str,
133
134
  setup_version_id: str,
134
135
  client_config: ClientConfig,
135
136
  config: dict[str, Any] | None = None,
@@ -138,11 +139,12 @@ class GrpcFilesystem(FilesystemStrategy, GrpcClientWrapper):
138
139
 
139
140
  Args:
140
141
  mission_id: The ID of the mission this strategy is associated with
142
+ setup_id: The ID of the setup
141
143
  setup_version_id: The ID of the setup version this strategy is associated with
142
144
  client_config: Configuration for the gRPC client connection
143
145
  config: Configuration for the filesystem strategy
144
146
  """
145
- super().__init__(mission_id, setup_version_id, config)
147
+ super().__init__(mission_id, setup_id, setup_version_id, config)
146
148
  self.service_name = "FilesystemService"
147
149
  channel = self._init_channel(client_config)
148
150
  self.stub = filesystem_service_pb2_grpc.FilesystemServiceStub(channel)
@@ -170,7 +172,7 @@ class GrpcFilesystem(FilesystemStrategy, GrpcClientWrapper):
170
172
  metadata_struct.update(file.metadata)
171
173
  upload_files.append(
172
174
  filesystem_pb2.UploadFileData(
173
- context=self.mission_id,
175
+ context=self.setup_id,
174
176
  name=file.name,
175
177
  file_type=self._file_type_to_enum(file.file_type),
176
178
  content_type=file.content_type or "application/octet-stream",
@@ -206,7 +208,7 @@ class GrpcFilesystem(FilesystemStrategy, GrpcClientWrapper):
206
208
  """
207
209
  with GrpcFilesystem._handle_grpc_errors("GetFile"):
208
210
  request = filesystem_pb2.GetFileRequest(
209
- context=self.mission_id,
211
+ context=self.setup_id,
210
212
  file_id=file_id,
211
213
  include_content=include_content,
212
214
  )
@@ -254,7 +256,7 @@ class GrpcFilesystem(FilesystemStrategy, GrpcClientWrapper):
254
256
  """
255
257
  with GrpcFilesystem._handle_grpc_errors("UpdateFile"):
256
258
  request = filesystem_pb2.UpdateFileRequest(
257
- context=self.mission_id,
259
+ context=self.setup_id,
258
260
  file_id=file_id,
259
261
  content=content,
260
262
  file_type=self._file_type_to_enum(file_type) if file_type else None,
@@ -288,7 +290,7 @@ class GrpcFilesystem(FilesystemStrategy, GrpcClientWrapper):
288
290
  """
289
291
  with GrpcFilesystem._handle_grpc_errors("DeleteFiles"):
290
292
  request = filesystem_pb2.DeleteFilesRequest(
291
- context=self.mission_id,
293
+ context=self.setup_id,
292
294
  filters=self._filter_to_proto(filters),
293
295
  permanent=permanent,
294
296
  force=force,
@@ -320,7 +322,7 @@ class GrpcFilesystem(FilesystemStrategy, GrpcClientWrapper):
320
322
  """
321
323
  with GrpcFilesystem._handle_grpc_errors("GetFiles"):
322
324
  request = filesystem_pb2.GetFilesRequest(
323
- context=self.mission_id,
325
+ context=self.setup_id,
324
326
  filters=self._filter_to_proto(filters),
325
327
  include_content=include_content,
326
328
  list_size=list_size,
@@ -111,12 +111,13 @@ class ServicesConfig(BaseModel):
111
111
  """
112
112
  return getattr(self, f"_config_{name}", {})
113
113
 
114
- def init_strategy(self, name: str, mission_id: str, setup_version_id: str) -> ServicesStrategy:
114
+ def init_strategy(self, name: str, mission_id: str, setup_id: str, setup_version_id: str) -> ServicesStrategy:
115
115
  """Initialize a specific strategy.
116
116
 
117
117
  Args:
118
118
  name: The name of the strategy to initialize
119
119
  mission_id: The ID of the mission this strategy is associated with
120
+ setup_id: The setup ID for the strategy
120
121
  setup_version_id: The setup version ID for the strategy
121
122
 
122
123
  Returns:
@@ -131,7 +132,7 @@ class ServicesConfig(BaseModel):
131
132
  raise ValueError(msg)
132
133
 
133
134
  # Instantiate the strategy with the mission ID, setup version ID, and configuration
134
- return strategy_type(mission_id, setup_version_id, **self.get_strategy_config(name) or {})
135
+ return strategy_type(mission_id, setup_id, setup_version_id, **self.get_strategy_config(name) or {})
135
136
 
136
137
  @property
137
138
  def storage(self) -> type[StorageStrategy]:
@@ -215,13 +215,14 @@ class DefaultStorage(StorageStrategy):
215
215
  def __init__(
216
216
  self,
217
217
  mission_id: str,
218
+ setup_id: str,
218
219
  setup_version_id: str,
219
220
  config: dict[str, type[BaseModel]],
220
221
  storage_file_path: str = "local_storage",
221
222
  **kwargs, # noqa: ANN003, ARG002
222
223
  ) -> None:
223
224
  """Initialize the storage."""
224
- super().__init__(mission_id=mission_id, setup_version_id=setup_version_id, config=config)
225
+ super().__init__(mission_id=mission_id, setup_id=setup_id, setup_version_id=setup_version_id, config=config)
225
226
  self.storage_file_path = f"{self.mission_id}_{storage_file_path}.json"
226
227
  self.storage_file = Path(self.storage_file_path)
227
228
  self.storage = self._load_from_file()
@@ -200,13 +200,14 @@ class GrpcStorage(StorageStrategy, GrpcClientWrapper):
200
200
  def __init__(
201
201
  self,
202
202
  mission_id: str,
203
+ setup_id: str,
203
204
  setup_version_id: str,
204
205
  config: dict[str, type[BaseModel]],
205
206
  client_config: ClientConfig,
206
207
  **kwargs, # noqa: ANN003, ARG002
207
208
  ) -> None:
208
209
  """Initialize the storage."""
209
- super().__init__(mission_id=mission_id, setup_version_id=setup_version_id, config=config)
210
+ super().__init__(mission_id=mission_id, setup_id=setup_id, setup_version_id=setup_version_id, config=config)
210
211
 
211
212
  channel = self._init_channel(client_config)
212
213
  self.stub = storage_service_pb2_grpc.StorageServiceStub(channel)
@@ -163,15 +163,22 @@ class StorageStrategy(BaseStrategy, ABC):
163
163
  True if the deletion was successful, False otherwise
164
164
  """
165
165
 
166
- def __init__(self, mission_id: str, setup_version_id: str, config: dict[str, type[BaseModel]]) -> None:
166
+ def __init__(
167
+ self,
168
+ mission_id: str,
169
+ setup_id: str,
170
+ setup_version_id: str,
171
+ config: dict[str, type[BaseModel]],
172
+ ) -> None:
167
173
  """Initialize the storage strategy.
168
174
 
169
175
  Args:
170
176
  mission_id: The ID of the mission this strategy is associated with
177
+ setup_id: The ID of the setup
171
178
  setup_version_id: The ID of the setup version
172
179
  config: A dictionary mapping names to Pydantic model classes
173
180
  """
174
- super().__init__(mission_id, setup_version_id)
181
+ super().__init__(mission_id, setup_id, setup_version_id)
175
182
  # Schema configuration mapping keys to model classes
176
183
  self.config: dict[str, type[BaseModel]] = config
177
184
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: digitalkin
3
- Version: 0.2.19
3
+ Version: 0.2.20
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
@@ -462,9 +462,9 @@ Requires-Dist: typos>=1.34.0; extra == "dev"
462
462
  Requires-Dist: ruff>=0.12.5; extra == "dev"
463
463
  Requires-Dist: mypy>=1.17.0; extra == "dev"
464
464
  Requires-Dist: pyright>=1.1.403; extra == "dev"
465
- Requires-Dist: pre-commit>=4.2.0; extra == "dev"
465
+ Requires-Dist: pre-commit>=4.3.0; extra == "dev"
466
466
  Requires-Dist: bump2version>=1.0.1; extra == "dev"
467
- Requires-Dist: build>=1.2.2; extra == "dev"
467
+ Requires-Dist: build>=1.3.0; extra == "dev"
468
468
  Requires-Dist: twine>=6.1.0; extra == "dev"
469
469
  Requires-Dist: cryptography>=45.0.5; extra == "dev"
470
470
  Provides-Extra: examples
@@ -9,9 +9,9 @@ typos>=1.34.0
9
9
  ruff>=0.12.5
10
10
  mypy>=1.17.0
11
11
  pyright>=1.1.403
12
- pre-commit>=4.2.0
12
+ pre-commit>=4.3.0
13
13
  bump2version>=1.0.1
14
- build>=1.2.2
14
+ build>=1.3.0
15
15
  twine>=6.1.0
16
16
  cryptography>=45.0.5
17
17
 
File without changes
File without changes
File without changes