digitalkin 0.2.4__py3-none-any.whl → 0.2.5__py3-none-any.whl

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/__version__.py CHANGED
@@ -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.4"
8
+ __version__ = "0.2.5"
@@ -1,6 +1,7 @@
1
1
  """Module gRPC server implementation for DigitalKin."""
2
2
 
3
3
  import logging
4
+ from pathlib import Path
4
5
  import uuid
5
6
 
6
7
  import grpc
@@ -8,7 +9,11 @@ import grpc
8
9
  from digitalkin.grpc_servers._base_server import BaseServer
9
10
  from digitalkin.grpc_servers.module_servicer import ModuleServicer
10
11
  from digitalkin.grpc_servers.utils.exceptions import ServerError
11
- from digitalkin.grpc_servers.utils.models import ModuleServerConfig, SecurityMode
12
+ from digitalkin.grpc_servers.utils.models import (
13
+ ClientConfig,
14
+ ModuleServerConfig,
15
+ SecurityMode,
16
+ )
12
17
  from digitalkin.modules._base_module import BaseModule
13
18
 
14
19
  from digitalkin_proto.digitalkin.module.v2 import (
@@ -32,14 +37,16 @@ class ModuleServer(BaseServer):
32
37
 
33
38
  Attributes:
34
39
  module: The module instance being served.
35
- config: Server configuration.
40
+ server_config: Server configuration.
41
+ client_config: Setup client configuration.
36
42
  module_servicer: The gRPC servicer handling module requests.
37
43
  """
38
44
 
39
45
  def __init__(
40
46
  self,
41
47
  module_class: type[BaseModule],
42
- config: ModuleServerConfig,
48
+ server_config: ModuleServerConfig,
49
+ client_config: ClientConfig | None = None,
43
50
  ) -> None:
44
51
  """Initialize the module server.
45
52
 
@@ -47,9 +54,10 @@ class ModuleServer(BaseServer):
47
54
  module_class: The module instance to be served.
48
55
  config: Server configuration including registry address if auto-registration is desired.
49
56
  """
50
- super().__init__(config)
57
+ super().__init__(server_config)
51
58
  self.module_class = module_class
52
- self.config = config
59
+ self.server_config = server_config
60
+ self.client_config = client_config
53
61
  self.module_servicer: ModuleServicer | None = None
54
62
 
55
63
  def _register_servicers(self) -> None:
@@ -73,34 +81,46 @@ class ModuleServer(BaseServer):
73
81
 
74
82
  def start(self) -> None:
75
83
  """Start the module server and register with the registry if configured."""
76
- logger.critical(self.config)
84
+ logger.critical(self.server_config)
77
85
  super().start()
78
86
 
79
- logger.critical(self.config)
87
+ logger.critical(self.server_config)
80
88
  # If a registry address is provided, register the module
81
- if self.config.registry_address:
89
+ if self.server_config.registry_address:
82
90
  try:
83
91
  self._register_with_registry()
84
92
  except Exception:
85
93
  logger.exception("Failed to register with registry")
86
94
 
95
+ if self.module_servicer is not None:
96
+ logger.critical(
97
+ "Setup post init started with config: %s", self.client_config
98
+ )
99
+ self.module_servicer.setup.__post_init__(self.client_config)
100
+
87
101
  async def start_async(self) -> None:
88
102
  """Start the module server and register with the registry if configured."""
89
- logger.critical(self.config)
103
+ logger.critical(self.server_config)
90
104
  await super().start_async()
91
105
 
92
- logger.critical(self.config)
106
+ logger.critical(self.server_config)
93
107
  # If a registry address is provided, register the module
94
- if self.config.registry_address:
108
+ if self.server_config.registry_address:
95
109
  try:
96
110
  self._register_with_registry()
97
111
  except Exception:
98
112
  logger.exception("Failed to register with registry")
99
113
 
114
+ if self.module_servicer is not None:
115
+ logger.critical(
116
+ "Setup post init started with config: %s", self.client_config
117
+ )
118
+ self.module_servicer.setup.__post_init__(self.client_config)
119
+
100
120
  def stop(self, grace: float | None = None) -> None:
101
121
  """Stop the module server and deregister from the registry if needed."""
102
122
  # If registered with a registry, deregister
103
- if self.config.registry_address:
123
+ if self.server_config.registry_address:
104
124
  try:
105
125
  self._deregister_from_registry()
106
126
  except ServerError:
@@ -115,7 +135,8 @@ class ModuleServer(BaseServer):
115
135
  ServerError: If communication with the registry server fails.
116
136
  """
117
137
  logger.info(
118
- "Registering module with registry at %s", self.config.registry_address
138
+ "Registering module with registry at %s",
139
+ self.server_config.registry_address,
119
140
  )
120
141
 
121
142
  # Create appropriate channel based on security mode
@@ -145,7 +166,7 @@ class ModuleServer(BaseServer):
145
166
  module_id=self.module_class.metadata["module_id"],
146
167
  version=self.module_class.metadata["version"],
147
168
  module_type=module_type,
148
- address=self.config.address,
169
+ address=self.server_config.address,
149
170
  metadata=metadata,
150
171
  )
151
172
 
@@ -173,7 +194,8 @@ class ModuleServer(BaseServer):
173
194
  ServerError: If communication with the registry server fails.
174
195
  """
175
196
  logger.info(
176
- "Deregistering module from registry at %s", self.config.registry_address
197
+ "Deregistering module from registry at %s",
198
+ self.server_config.registry_address,
177
199
  )
178
200
 
179
201
  # Create appropriate channel based on security mode
@@ -208,29 +230,42 @@ class ModuleServer(BaseServer):
208
230
  Raises:
209
231
  ValueError: If credentials are required but not provided.
210
232
  """
211
- if self.config.security == SecurityMode.SECURE and self.config.credentials:
233
+ if (
234
+ self.client_config is not None
235
+ and self.client_config.security == SecurityMode.SECURE
236
+ and self.client_config.credentials
237
+ ):
212
238
  # Secure channel
213
- """TODO: use Path(self.config.credentials.server_cert_path).read_bytes()"""
214
- with open(self.config.credentials.server_cert_path, "rb") as cert_file: # noqa: FURB101
215
- certificate_chain = cert_file.read()
216
-
217
- root_certificates = None
218
- if self.config.credentials.root_cert_path:
219
- with open(
220
- self.config.credentials.root_cert_path, "rb"
221
- ) as root_cert_file: # noqa: FURB101
222
- root_certificates = root_cert_file.read()
239
+ # Secure channel
240
+ root_certificates = Path(
241
+ self.client_config.credentials.root_cert_path
242
+ ).read_bytes()
243
+
244
+ # mTLS channel
245
+ private_key = None
246
+ certificate_chain = None
247
+ if (
248
+ self.client_config.credentials.client_cert_path is not None
249
+ and self.client_config.credentials.client_key_path is not None
250
+ ):
251
+ private_key = Path(
252
+ self.client_config.credentials.client_key_path
253
+ ).read_bytes()
254
+ certificate_chain = Path(
255
+ self.client_config.credentials.client_cert_path
256
+ ).read_bytes()
223
257
 
224
258
  # Create channel credentials
225
259
  channel_credentials = grpc.ssl_channel_credentials(
226
- root_certificates=root_certificates or certificate_chain
260
+ root_certificates=root_certificates,
261
+ certificate_chain=certificate_chain,
262
+ private_key=private_key,
227
263
  )
228
-
229
264
  return grpc.secure_channel(
230
- self.config.registry_address, channel_credentials
265
+ self.server_config.registry_address, channel_credentials
231
266
  )
232
267
  # Insecure channel
233
- return grpc.insecure_channel(self.config.registry_address)
268
+ return grpc.insecure_channel(self.server_config.registry_address)
234
269
 
235
270
  def _determine_module_type(self) -> str:
236
271
  """Determine the module type based on its class.
@@ -102,7 +102,8 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer):
102
102
 
103
103
  while module.status == ModuleStatus.RUNNING or not self.queue.empty():
104
104
  output_data: dict = await self.queue.get()
105
- if job_id not in output_data or output_data[job_id] not in self.job_manager.modules:
105
+
106
+ if job_id not in output_data or job_id not in self.job_manager.modules:
106
107
  message = f"Job {job_id} not found"
107
108
  logger.warning(message)
108
109
  context.set_code(grpc.StatusCode.NOT_FOUND)
@@ -1,12 +1,13 @@
1
1
  """Client wrapper to ease channel creation with specific ServerConfig."""
2
2
 
3
3
  import logging
4
+ from pathlib import Path
4
5
  from typing import Any
5
6
 
6
7
  import grpc
7
8
 
8
9
  from digitalkin.grpc_servers.utils.exceptions import ServerError
9
- from digitalkin.grpc_servers.utils.models import SecurityMode, ServerConfig
10
+ from digitalkin.grpc_servers.utils.models import ClientConfig, SecurityMode
10
11
 
11
12
  logger = logging.getLogger(__name__)
12
13
 
@@ -17,7 +18,7 @@ class GrpcClientWrapper:
17
18
  stub: Any
18
19
 
19
20
  @staticmethod
20
- def _init_channel(config: ServerConfig) -> grpc.Channel:
21
+ def _init_channel(config: ClientConfig) -> grpc.Channel:
21
22
  """Create an appropriate channel to the registry server.
22
23
 
23
24
  Returns:
@@ -26,22 +27,27 @@ class GrpcClientWrapper:
26
27
  Raises:
27
28
  ValueError: If credentials are required but not provided.
28
29
  """
29
- if config.security == SecurityMode.SECURE and config.credentials:
30
+ if config.security == SecurityMode.SECURE and config.credentials is not None:
30
31
  # Secure channel
31
- with open(config.credentials.server_cert_path, "rb") as cert_file: # noqa: FURB101
32
- certificate_chain = cert_file.read()
32
+ root_certificates = Path(config.credentials.root_cert_path).read_bytes()
33
33
 
34
- root_certificates = None
35
- if config.credentials.root_cert_path:
36
- with open(config.credentials.root_cert_path, "rb") as root_cert_file: # noqa: FURB101
37
- root_certificates = root_cert_file.read()
34
+ # mTLS channel
35
+ private_key = None
36
+ certificate_chain = None
37
+ if config.credentials.client_cert_path is not None and config.credentials.client_key_path is not None:
38
+ private_key = Path(config.credentials.client_key_path).read_bytes()
39
+ certificate_chain = Path(config.credentials.client_cert_path).read_bytes()
38
40
 
39
41
  # Create channel credentials
40
- channel_credentials = grpc.ssl_channel_credentials(root_certificates=root_certificates or certificate_chain)
42
+ channel_credentials = grpc.ssl_channel_credentials(
43
+ root_certificates=root_certificates,
44
+ certificate_chain=certificate_chain,
45
+ private_key=private_key,
46
+ )
41
47
 
42
- return grpc.secure_channel(f"{config.host}:{config.port}", channel_credentials)
48
+ return grpc.secure_channel(config.address, channel_credentials)
43
49
  # Insecure channel
44
- return grpc.insecure_channel(f"{config.host}:{config.port}")
50
+ return grpc.insecure_channel(config.address)
45
51
 
46
52
  def exec_grpc_query(self, query_endpoint: str, request: Any) -> Any: # noqa: ANN401
47
53
  """Execute a gRPC query with from the query's rpc endpoint name.
@@ -65,29 +65,18 @@ class ServerCredentials(BaseModel):
65
65
  return v
66
66
 
67
67
 
68
- class ServerConfig(BaseModel):
69
- """Base configuration for gRPC servers.
68
+ class ClientCredentials(BaseModel):
69
+ """Model for client credentials in secure mode.
70
70
 
71
71
  Attributes:
72
- host: Host address to bind the server to
73
- port: Port to listen on
74
- max_workers: Maximum number of workers for sync mode
75
- mode: Server operation mode (sync/async)
76
- security: Security mode (secure/insecure)
77
- credentials: Server credentials for secure mode
78
- server_options: Additional server options
79
- enable_reflection: Enable reflection for the server
72
+ root_cert_path: path to the root certificate
73
+ client_key_path: Path to the client private key
74
+ client_cert_path: Path to the client certificate
80
75
  """
81
76
 
82
- host: str = Field("0.0.0.0", description="Host address to bind the server to") # noqa: S104
83
- port: int = Field(50051, description="Port to listen on")
84
- max_workers: int = Field(10, description="Maximum number of workers for sync mode")
85
- mode: ServerMode = Field(ServerMode.SYNC, description="Server operation mode (sync/async)")
86
- security: SecurityMode = Field(SecurityMode.INSECURE, description="Security mode (secure/insecure)")
87
- credentials: ServerCredentials | None = Field(None, description="Server credentials for secure mode")
88
- server_options: list[tuple[str, Any]] = Field(default_factory=list, description="Additional server options")
89
- enable_reflection: bool = Field(default=True, description="Enable reflection for the server")
90
- enable_health_check: bool = Field(default=True, description="Enable health check service")
77
+ root_cert_path: Path = Field(..., description="Path to the root certificate")
78
+ client_key_path: Path | None = Field(None, description="Path to the client private key | mTLS enable")
79
+ client_cert_path: Path | None = Field(None, description="Path to the client certificate | mTLS enable")
91
80
 
92
81
  # Enable __slots__ for memory efficiency
93
82
  model_config = {
@@ -95,31 +84,53 @@ class ServerConfig(BaseModel):
95
84
  "arbitrary_types_allowed": True,
96
85
  "validate_assignment": True,
97
86
  "use_enum_values": True,
87
+ "frozen": True, # Make immutable
98
88
  }
99
89
 
100
- @field_validator("credentials")
90
+ @field_validator("client_key_path", "client_cert_path", "root_cert_path")
101
91
  @classmethod
102
- def validate_credentials(cls, v: ServerCredentials | None, info: ValidationInfo) -> ServerCredentials | None:
103
- """Validate that credentials are provided when in secure mode.
92
+ def check_path_exists(cls, v: Path | None) -> Path | None:
93
+ """Validate that the file path exists.
104
94
 
105
95
  Args:
106
- v: The credentials value
107
- info: ValidationInfo containing other field values
96
+ v: Path to validate
108
97
 
109
98
  Returns:
110
- The validated credentials
99
+ The validated path
111
100
 
112
101
  Raises:
113
- ConfigurationError: If credentials are missing in secure mode
102
+ SecurityError: If the path does not exist
114
103
  """
115
- # Access security mode from the info.data dictionary
116
- security = info.data.get("security")
117
-
118
- if security == SecurityMode.SECURE and v is None:
119
- msg = "Credentials must be provided when using secure mode"
120
- raise ConfigurationError(msg)
104
+ if v is not None and not v.exists():
105
+ msg = f"File not found: {v}"
106
+ raise SecurityError(msg)
121
107
  return v
122
108
 
109
+
110
+ class ChannelConfig(BaseModel):
111
+ """Base configuration for gRPC channels.
112
+
113
+ Attributes:
114
+ host: Host address
115
+ port: Port to listen on
116
+ mode: communication operation mode (sync/async)
117
+ security: Security mode (secure/insecure)
118
+ credentials: Client credentials for secure mode
119
+ """
120
+
121
+ host: str = Field("0.0.0.0", description="Host address to bind the client to") # noqa: S104
122
+ port: int = Field(50051, description="Port to listen on")
123
+ mode: ServerMode = Field(ServerMode.SYNC, description="Client operation mode (sync/async)")
124
+ security: SecurityMode = Field(SecurityMode.INSECURE, description="Security mode (secure/insecure)")
125
+
126
+ # Enable __slots__ for memory efficiency
127
+ model_config = {
128
+ "extra": "forbid",
129
+ "arbitrary_types_allowed": True,
130
+ "validate_assignment": True,
131
+ "use_enum_values": True,
132
+ }
133
+
123
134
  @field_validator("port")
124
135
  @classmethod
125
136
  def validate_port(cls, v: int) -> int:
@@ -149,6 +160,87 @@ class ServerConfig(BaseModel):
149
160
  return f"{self.host}:{self.port}"
150
161
 
151
162
 
163
+ class ClientConfig(ChannelConfig):
164
+ """Base configuration for gRPC clients.
165
+
166
+ Attributes:
167
+ host: Host address to bind the client to
168
+ port: Port to listen on
169
+ mode: Client operation mode (sync/async)
170
+ security: Security mode (secure/insecure)
171
+ credentials: Client credentials for secure mode
172
+ """
173
+
174
+ credentials: ClientCredentials | None = Field(None, description="Client credentials for secure mode")
175
+
176
+ @field_validator("credentials")
177
+ @classmethod
178
+ def validate_credentials(cls, v: ClientCredentials | None, info: ValidationInfo) -> ClientCredentials | None:
179
+ """Validate that credentials are provided when in secure mode.
180
+
181
+ Args:
182
+ v: The credentials value
183
+ info: ValidationInfo containing other field values
184
+
185
+ Returns:
186
+ The validated credentials
187
+
188
+ Raises:
189
+ ConfigurationError: If credentials are missing in secure mode
190
+ """
191
+ # Access security mode from the info.data dictionary
192
+ security = info.data.get("security")
193
+
194
+ if security == SecurityMode.SECURE and v is None:
195
+ msg = "Credentials must be provided when using secure mode"
196
+ raise ConfigurationError(msg)
197
+ return v
198
+
199
+
200
+ class ServerConfig(ChannelConfig):
201
+ """Base configuration for gRPC servers.
202
+
203
+ Attributes:
204
+ host: Host address to bind the server to
205
+ port: Port to listen on
206
+ max_workers: Maximum number of workers for sync mode
207
+ mode: Server operation mode (sync/async)
208
+ security: Security mode (secure/insecure)
209
+ credentials: Server credentials for secure mode
210
+ server_options: Additional server options
211
+ enable_reflection: Enable reflection for the server
212
+ """
213
+
214
+ max_workers: int = Field(10, description="Maximum number of workers for sync mode")
215
+ credentials: ServerCredentials | None = Field(None, description="Server credentials for secure mode")
216
+ server_options: list[tuple[str, Any]] = Field(default_factory=list, description="Additional server options")
217
+ enable_reflection: bool = Field(default=True, description="Enable reflection for the server")
218
+ enable_health_check: bool = Field(default=True, description="Enable health check service")
219
+
220
+ @field_validator("credentials")
221
+ @classmethod
222
+ def validate_credentials(cls, v: ServerCredentials | None, info: ValidationInfo) -> ServerCredentials | None:
223
+ """Validate that credentials are provided when in secure mode.
224
+
225
+ Args:
226
+ v: The credentials value
227
+ info: ValidationInfo containing other field values
228
+
229
+ Returns:
230
+ The validated credentials
231
+
232
+ Raises:
233
+ ConfigurationError: If credentials are missing in secure mode
234
+ """
235
+ # Access security mode from the info.data dictionary
236
+ security = info.data.get("security")
237
+
238
+ if security == SecurityMode.SECURE and v is None:
239
+ msg = "Credentials must be provided when using secure mode"
240
+ raise ConfigurationError(msg)
241
+ return v
242
+
243
+
152
244
  class ModuleServerConfig(ServerConfig):
153
245
  """Configuration for Module gRPC server.
154
246
 
@@ -16,7 +16,7 @@ from pydantic import ValidationError
16
16
 
17
17
  from digitalkin.grpc_servers.utils.exceptions import ServerError
18
18
  from digitalkin.grpc_servers.utils.grpc_client_wrapper import GrpcClientWrapper
19
- from digitalkin.grpc_servers.utils.models import ServerConfig
19
+ from digitalkin.grpc_servers.utils.models import ClientConfig
20
20
  from digitalkin.services.setup.setup_strategy import SetupData, SetupServiceError, SetupStrategy, SetupVersionData
21
21
 
22
22
  logger = logging.getLogger(__name__)
@@ -25,7 +25,7 @@ logger = logging.getLogger(__name__)
25
25
  class GrpcSetup(SetupStrategy, GrpcClientWrapper):
26
26
  """This class implements the gRPC setup service."""
27
27
 
28
- def __post_init__(self, config: ServerConfig) -> None:
28
+ def __post_init__(self, config: ClientConfig) -> None:
29
29
  """Init the channel from a config file.
30
30
 
31
31
  Need to be call if the user register a gRPC channel.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: digitalkin
3
- Version: 0.2.4
3
+ Version: 0.2.5
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
@@ -456,6 +456,7 @@ Requires-Dist: digitalkin-proto>=0.1.7
456
456
  Requires-Dist: grpcio-health-checking>=1.71.0
457
457
  Requires-Dist: grpcio-reflection>=1.71.0
458
458
  Requires-Dist: grpcio-status>=1.71.0
459
+ Requires-Dist: openai>=1.70.0
459
460
  Requires-Dist: pydantic>=2.11.3
460
461
  Provides-Extra: dev
461
462
  Requires-Dist: pytest>=8.3.4; extra == "dev"
@@ -7,19 +7,19 @@ base_server/mock/__init__.py,sha256=YZFT-F1l_TpvJYuIPX-7kTeE1CfOjhx9YmNRXVoi-jQ,
7
7
  base_server/mock/mock_pb2.py,sha256=sETakcS3PAAm4E-hTCV1jIVaQTPEAIoVVHupB8Z_k7Y,1843
8
8
  base_server/mock/mock_pb2_grpc.py,sha256=BbOT70H6q3laKgkHfOx1QdfmCS_HxCY4wCOX84YAdG4,3180
9
9
  digitalkin/__init__.py,sha256=7LLBAba0th-3SGqcpqFO-lopWdUkVLKzLZiMtB-mW3M,162
10
- digitalkin/__version__.py,sha256=mR_bGYOQA3eO6IjqeeDDhhBptzMqVTzT6k-jTNiddLY,190
10
+ digitalkin/__version__.py,sha256=rNDXhMY4crjuy0nWOXRh9ypmALKFI7DzYaHCTDZkRl8,190
11
11
  digitalkin/logger.py,sha256=9cDgyJV2QXXT8F--xRODFlZyDgjuTTXNdpCU3GdqCsk,382
12
12
  digitalkin/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  digitalkin/grpc_servers/__init__.py,sha256=0cJBlwipSmFdXkyH3T0i6OJ1WpAtNsZgYX7JaSnkbtg,804
14
14
  digitalkin/grpc_servers/_base_server.py,sha256=ec4xmgAuOMVg45a63O_PEa2T7mI4tJ6boxcXauFyZ5g,18649
15
- digitalkin/grpc_servers/module_server.py,sha256=23Q6F9mSO9bCu2MmsLqM9WeviIzwfhDiBFrVspy0PCI,9065
16
- digitalkin/grpc_servers/module_servicer.py,sha256=FMzB2E1dQZck34vGWf9OXNXEIfu_KhTdZ_Kn79XEowc,12306
15
+ digitalkin/grpc_servers/module_server.py,sha256=0jC5MN-H4MGA9O9J87gnlM8EHcbrkb0chuCm8yZh7gI,10232
16
+ digitalkin/grpc_servers/module_servicer.py,sha256=byqRpp9m8HS3NUUtKBWFXOncpUWGDW_xsyddA2qwaW4,12294
17
17
  digitalkin/grpc_servers/registry_server.py,sha256=PmWaH4Xmg5Sj7NtFVLBNTOzkOfqo7dw_qyVBnaW4jy4,2238
18
18
  digitalkin/grpc_servers/registry_servicer.py,sha256=mCAjNhdMq5DozZMEPsJK__DIxePEYxSWV-gAq-Xctk4,16469
19
19
  digitalkin/grpc_servers/utils/exceptions.py,sha256=I00OM8p8up20He4dU1fiHsvdLj1DymjR_UmoeUm2MSA,785
20
20
  digitalkin/grpc_servers/utils/factory.py,sha256=jm6rFjiqmtSv7BIHNAOxsG9xXtSvWpx9TfzSQiX97MQ,5899
21
- digitalkin/grpc_servers/utils/grpc_client_wrapper.py,sha256=y9zGzmeESAhrzzQcekA8rE_P9gyPvOjxWwnZAc3fpx4,2435
22
- digitalkin/grpc_servers/utils/models.py,sha256=AXv4FQ3RRmcr5sZaaZc72ED1LtGJEaxmFIZP0Xlo-PY,5483
21
+ digitalkin/grpc_servers/utils/grpc_client_wrapper.py,sha256=6gj98T2_siZNlsamfz2Qkg89ebv4rS8Gm_X2FpE6Iow,2613
22
+ digitalkin/grpc_servers/utils/models.py,sha256=80F5oHiv8MOqMoDZJBXmJSRoVYJRyhaVcijQ2LinAig,8428
23
23
  digitalkin/grpc_servers/utils/types.py,sha256=rQ78s4nAet2jy-NIDj_PUWriT0kuGHr_w6ELjmjgBao,539
24
24
  digitalkin/models/__init__.py,sha256=hDHtUfswaNh8wo4NZaBItg9JqC0uNSRqXArNWSrGynY,163
25
25
  digitalkin/models/module/__init__.py,sha256=ihvRlemJuFvU4armZIL-Vq-zaJx9UrjDoJAVPbEG8jw,345
@@ -56,7 +56,7 @@ digitalkin/services/registry/__init__.py,sha256=Zl4QAkCe9tOmmKGBWVuLQVFepdZiL0ec
56
56
  digitalkin/services/registry/default_registry.py,sha256=VnWkF6nHpFxUKuUbZLPqzXqdA6oXmyV_ySpeuOCf_ko,277
57
57
  digitalkin/services/registry/registry_strategy.py,sha256=uBXgZIv25jeXbeVO8vWvlNPxxNYu7_KiCw2PoE6AWr8,423
58
58
  digitalkin/services/setup/default_setup.py,sha256=x1J6trXhyLC7V2OTe5pRY5mIFkQ4oyi3-aG50a1G1U4,8253
59
- digitalkin/services/setup/grpc_setup.py,sha256=Bo84gLZSK8DKqHAVSVFOQdtZQkfpp78eNgjJnGhXQfU,12449
59
+ digitalkin/services/setup/grpc_setup.py,sha256=4rLra3Ao0cwVX1L380VYwmGactoIk8gmcNHGlkrpEo8,12449
60
60
  digitalkin/services/setup/setup_strategy.py,sha256=ZnJ_HwWCkHCPrqKekSD5L9y3p8wMwfjQ8sj2hLZq6go,4004
61
61
  digitalkin/services/snapshot/__init__.py,sha256=Uzlnzo0CYlSpVsdiI37hW7xQk8hu3YA1fOI6O6MSzB0,270
62
62
  digitalkin/services/snapshot/default_snapshot.py,sha256=Mb8QwWRsHh9I_tN0ln_ZiFa1QCZxOVWmuVLemQOTWpc,1058
@@ -67,12 +67,12 @@ digitalkin/services/storage/grpc_storage.py,sha256=BqWLK9w_03BEjlJCVbdrlbMvh2szG
67
67
  digitalkin/services/storage/storage_strategy.py,sha256=vGo4aYkEp_GZV11m7vd-xY_Z3gVa5K0gMTzbj2Au_3o,6600
68
68
  digitalkin/utils/__init__.py,sha256=sJnY-ZUgsjMfojAjONC1VN14mhgIDnzyOlGkw21rRnM,28
69
69
  digitalkin/utils/arg_parser.py,sha256=3YyI6oZhhrlTmPTrzlwpQzbCNWDFAT3pggcLxNtJoc0,4388
70
- digitalkin-0.2.4.dist-info/licenses/LICENSE,sha256=Ies4HFv2r2hzDRakJYxk3Y60uDFLiG-orIgeTpstnIo,20327
70
+ digitalkin-0.2.5.dist-info/licenses/LICENSE,sha256=Ies4HFv2r2hzDRakJYxk3Y60uDFLiG-orIgeTpstnIo,20327
71
71
  modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
72
72
  modules/minimal_llm_module.py,sha256=i9KTbv8w1ekzRYWDiRsxD6xLCoZ3uDjD_hWgfY2PRys,5637
73
73
  modules/storage_module.py,sha256=bu52lW4RFcWB8VFDhrpBFfCaTSkVL6so3zrkfW4LO9E,6270
74
74
  modules/text_transform_module.py,sha256=fAC6r_Ujca1Tz1qdWL4hTPZFn3gFWIVNj5-rytQMObE,7191
75
- digitalkin-0.2.4.dist-info/METADATA,sha256=h_9hJnMdGTJZwkr0b5IZwSEO5l70sbtJmd5PNZhY0VI,29095
76
- digitalkin-0.2.4.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
77
- digitalkin-0.2.4.dist-info/top_level.txt,sha256=5_5e35inSM5YfWNZE21p5wGBojiVtQQML_WzbEk4BRU,31
78
- digitalkin-0.2.4.dist-info/RECORD,,
75
+ digitalkin-0.2.5.dist-info/METADATA,sha256=GLLOO0md8f6VLKykUxBJwZ2wTh3NEpBcKdi-V5wKvx8,29125
76
+ digitalkin-0.2.5.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
77
+ digitalkin-0.2.5.dist-info/top_level.txt,sha256=5_5e35inSM5YfWNZE21p5wGBojiVtQQML_WzbEk4BRU,31
78
+ digitalkin-0.2.5.dist-info/RECORD,,