digitalkin 0.2.26__py3-none-any.whl → 0.3.0__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.
Files changed (37) hide show
  1. digitalkin/__version__.py +1 -1
  2. digitalkin/grpc_servers/module_server.py +27 -44
  3. digitalkin/grpc_servers/module_servicer.py +27 -22
  4. digitalkin/grpc_servers/utils/models.py +1 -1
  5. digitalkin/logger.py +1 -9
  6. digitalkin/mixins/__init__.py +19 -0
  7. digitalkin/mixins/base_mixin.py +10 -0
  8. digitalkin/mixins/callback_mixin.py +24 -0
  9. digitalkin/mixins/chat_history_mixin.py +108 -0
  10. digitalkin/mixins/cost_mixin.py +76 -0
  11. digitalkin/mixins/file_history_mixin.py +99 -0
  12. digitalkin/mixins/filesystem_mixin.py +47 -0
  13. digitalkin/mixins/logger_mixin.py +59 -0
  14. digitalkin/mixins/storage_mixin.py +79 -0
  15. digitalkin/models/module/__init__.py +2 -0
  16. digitalkin/models/module/module.py +9 -1
  17. digitalkin/models/module/module_context.py +90 -6
  18. digitalkin/models/module/module_types.py +6 -6
  19. digitalkin/models/module/task_monitor.py +51 -0
  20. digitalkin/models/services/__init__.py +9 -0
  21. digitalkin/models/services/storage.py +39 -5
  22. digitalkin/modules/_base_module.py +47 -68
  23. digitalkin/modules/job_manager/base_job_manager.py +12 -8
  24. digitalkin/modules/job_manager/single_job_manager.py +84 -78
  25. digitalkin/modules/job_manager/surrealdb_repository.py +225 -0
  26. digitalkin/modules/job_manager/task_manager.py +391 -0
  27. digitalkin/modules/job_manager/task_session.py +276 -0
  28. digitalkin/modules/job_manager/taskiq_job_manager.py +2 -2
  29. digitalkin/modules/tool_module.py +10 -2
  30. digitalkin/modules/trigger_handler.py +7 -6
  31. digitalkin/services/cost/__init__.py +9 -2
  32. digitalkin/services/storage/grpc_storage.py +1 -1
  33. {digitalkin-0.2.26.dist-info → digitalkin-0.3.0.dist-info}/METADATA +18 -18
  34. {digitalkin-0.2.26.dist-info → digitalkin-0.3.0.dist-info}/RECORD +37 -24
  35. {digitalkin-0.2.26.dist-info → digitalkin-0.3.0.dist-info}/WHEEL +0 -0
  36. {digitalkin-0.2.26.dist-info → digitalkin-0.3.0.dist-info}/licenses/LICENSE +0 -0
  37. {digitalkin-0.2.26.dist-info → digitalkin-0.3.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,276 @@
1
+ """."""
2
+
3
+ import asyncio
4
+ import datetime
5
+ from collections.abc import AsyncGenerator
6
+
7
+ from digitalkin.logger import logger
8
+ from digitalkin.models.module.task_monitor import HeartbeatMessage, SignalMessage, SignalType, TaskStatus
9
+ from digitalkin.modules._base_module import BaseModule
10
+ from digitalkin.modules.job_manager.surrealdb_repository import SurrealDBConnection
11
+
12
+
13
+ class TaskSession:
14
+ """Task Session with lifecycle management.
15
+
16
+ The Session defined the whole lifecycle of a task as an epheneral context.
17
+ """
18
+
19
+ db: SurrealDBConnection
20
+ module: BaseModule
21
+
22
+ status: TaskStatus
23
+ signal_queue: AsyncGenerator | None
24
+
25
+ task_id: str
26
+ signal_record_id: str | None
27
+ heartbeat_record_id: str | None
28
+
29
+ started_at: datetime.datetime | None
30
+ completed_at: datetime.datetime | None
31
+
32
+ is_cancelled: asyncio.Event
33
+ _paused: asyncio.Event
34
+ _heartbeat_interval: datetime.timedelta
35
+ _last_heartbeat: datetime.datetime
36
+
37
+ def __init__(
38
+ self,
39
+ task_id: str,
40
+ db: SurrealDBConnection,
41
+ module: BaseModule,
42
+ heartbeat_interval: datetime.timedelta = datetime.timedelta(seconds=2),
43
+ ) -> None:
44
+ """."""
45
+ self.db = db
46
+ self.module = module
47
+
48
+ self.status = TaskStatus.PENDING
49
+ self.queue: asyncio.Queue = asyncio.Queue()
50
+
51
+ self.task_id = task_id
52
+ self.heartbeat = None
53
+ self.started_at = None
54
+ self.completed_at = None
55
+
56
+ self.signal_record_id = None
57
+ self.heartbeat_record_id = None
58
+
59
+ self.is_cancelled = asyncio.Event()
60
+ self._paused = asyncio.Event()
61
+ self._heartbeat_interval = heartbeat_interval
62
+
63
+ logger.info(
64
+ "TaskContext initialized for task: '%s'",
65
+ task_id,
66
+ extra={"task_id": task_id, "heartbeat_interval": heartbeat_interval},
67
+ )
68
+
69
+ @property
70
+ def cancelled(self) -> bool:
71
+ """."""
72
+ return self.is_cancelled.is_set()
73
+
74
+ @property
75
+ def paused(self) -> bool:
76
+ """."""
77
+ return self._paused.is_set()
78
+
79
+ async def send_heartbeat(self) -> bool:
80
+ """Rate-limited heartbeat with connection resilience.
81
+
82
+ Returns:
83
+ bool: True if heartbeat was successful, False otherwise
84
+ """
85
+ heartbeat = HeartbeatMessage(
86
+ task_id=self.task_id,
87
+ timestamp=datetime.datetime.now(datetime.timezone.utc),
88
+ )
89
+
90
+ if self.heartbeat_record_id is None:
91
+ try:
92
+ success = await self.db.create("heartbeats", heartbeat.model_dump())
93
+ logger.critical(f"{success=} | {'code' not in success}")
94
+ if "code" not in success:
95
+ self.heartbeat_record_id = success.get("id") # type: ignore
96
+ self._last_heartbeat = heartbeat.timestamp
97
+ return True
98
+ except Exception as e:
99
+ logger.error(
100
+ "Heartbeat exception for task: '%s'",
101
+ self.task_id,
102
+ extra={"task_id": self.task_id, "error": str(e)},
103
+ exc_info=True,
104
+ )
105
+ logger.error(
106
+ "Initial heartbeat failed for task: '%s'",
107
+ self.task_id,
108
+ extra={"task_id": self.task_id},
109
+ )
110
+ return False
111
+
112
+ if (heartbeat.timestamp - self._last_heartbeat) < self._heartbeat_interval:
113
+ logger.debug(
114
+ "Heartbeat skipped due to rate limiting for task: '%s' | delta=%s",
115
+ self.task_id,
116
+ heartbeat.timestamp - self._last_heartbeat,
117
+ )
118
+ return True
119
+
120
+ try:
121
+ success = await self.db.merge("heartbeats", self.heartbeat_record_id, heartbeat.model_dump())
122
+ if "code" not in success:
123
+ self._last_heartbeat = heartbeat.timestamp
124
+ return True
125
+ except Exception as e:
126
+ logger.error(
127
+ "Heartbeat exception for task: '%s'",
128
+ self.task_id,
129
+ extra={"task_id": self.task_id, "error": str(e)},
130
+ exc_info=True,
131
+ )
132
+ logger.warning(
133
+ "Heartbeat failed for task: '%s'",
134
+ self.task_id,
135
+ extra={"task_id": self.task_id},
136
+ )
137
+ return False
138
+
139
+ async def generate_heartbeats(self) -> None:
140
+ """Periodic heartbeat generator with cancellation support."""
141
+ logger.critical("Heartbeat started")
142
+ while not self.cancelled:
143
+ logger.debug(f"Heartbeat tick for task: '{self.task_id}' | {self.cancelled=}")
144
+ success = await self.send_heartbeat()
145
+ if not success:
146
+ logger.error("Heartbeat failed, cancelling task: '%s'", self.task_id, extra={"task_id": self.task_id})
147
+ await self._handle_cancel()
148
+ break
149
+ await asyncio.sleep(self._heartbeat_interval.total_seconds())
150
+
151
+ async def wait_if_paused(self) -> None:
152
+ """Block execution if task is paused."""
153
+ if self._paused.is_set():
154
+ logger.info("Task paused, waiting for resume: '%s'", self.task_id, extra={"task_id": self.task_id})
155
+ await self._paused.wait()
156
+
157
+ async def listen_signals(self) -> None: # noqa: C901
158
+ """Enhanced signal listener with comprehensive handling.
159
+
160
+ Raises:
161
+ CancelledError: Asyncio when task cancelling
162
+ """
163
+ logger.info("Signal listener started for task: '%s'", self.task_id, extra={"task_id": self.task_id})
164
+ if self.signal_record_id is None:
165
+ self.signal_record_id = (await self.db.select_by_task_id("tasks", self.task_id)).get("id")
166
+
167
+ live_id, live_signals = await self.db.start_live("tasks")
168
+ try:
169
+ async for signal in live_signals:
170
+ logger.critical("Signal received for task '%s': %s", self.task_id, signal)
171
+ if self.cancelled:
172
+ break
173
+
174
+ if signal is None or signal["id"] == self.signal_record_id or "payload" not in signal:
175
+ continue
176
+
177
+ if signal["action"] == "cancel":
178
+ await self._handle_cancel()
179
+ elif signal["action"] == "pause":
180
+ await self._handle_pause()
181
+ elif signal["action"] == "resume":
182
+ await self._handle_resume()
183
+ elif signal["action"] == "status":
184
+ await self._handle_status_request()
185
+
186
+ except asyncio.CancelledError:
187
+ logger.debug("Signal listener cancelled for task: '%s'", self.task_id, extra={"task_id": self.task_id})
188
+ raise
189
+ except Exception as e:
190
+ logger.error(
191
+ "Signal listener fatal error for task: '%s'",
192
+ self.task_id,
193
+ extra={"task_id": self.task_id, "error": str(e)},
194
+ exc_info=True,
195
+ )
196
+ finally:
197
+ await self.db.stop_live(live_id)
198
+ logger.info("Signal listener stopped for task: '%s'", self.task_id, extra={"task_id": self.task_id})
199
+
200
+ async def _handle_cancel(self) -> None:
201
+ """Idempotent cancellation with acknowledgment."""
202
+ logger.critical("Handle cancel called")
203
+ if self.is_cancelled.is_set():
204
+ logger.debug(
205
+ "Cancel signal ignored - task already cancelled: '%s'", self.task_id, extra={"task_id": self.task_id}
206
+ )
207
+ return
208
+
209
+ logger.info("Cancelling task: '%s'", self.task_id, extra={"task_id": self.task_id})
210
+
211
+ self.status = TaskStatus.CANCELLED
212
+ self.is_cancelled.set()
213
+
214
+ # Resume if paused so cancellation can proceed
215
+ if self._paused.is_set():
216
+ self._paused.set()
217
+
218
+ await self.db.update(
219
+ "tasks",
220
+ self.signal_record_id, # type: ignore
221
+ SignalMessage(
222
+ task_id=self.task_id,
223
+ action=SignalType.ACK_CANCEL,
224
+ status=self.status,
225
+ ).model_dump(),
226
+ )
227
+
228
+ async def _handle_pause(self) -> None:
229
+ """Pause task execution."""
230
+ if not self._paused.is_set():
231
+ logger.info("Pausing task: '%s'", self.task_id, extra={"task_id": self.task_id})
232
+ self._paused.set()
233
+
234
+ await self.db.update(
235
+ "tasks",
236
+ self.signal_record_id, # type: ignore
237
+ SignalMessage(
238
+ task_id=self.task_id,
239
+ action=SignalType.ACK_PAUSE,
240
+ status=self.status,
241
+ ).model_dump(),
242
+ )
243
+
244
+ async def _handle_resume(self) -> None:
245
+ """Resume paused task."""
246
+ if self._paused.is_set():
247
+ logger.info("Resuming task: '%s'", self.task_id, extra={"task_id": self.task_id})
248
+ self._paused.clear()
249
+
250
+ await self.db.update(
251
+ "tasks",
252
+ self.signal_record_id, # type: ignore
253
+ SignalMessage(
254
+ task_id=self.task_id,
255
+ action=SignalType.ACK_RESUME,
256
+ status=self.status,
257
+ ).model_dump(),
258
+ )
259
+
260
+ async def _handle_status_request(self) -> None:
261
+ """Send current task status."""
262
+ await self.db.update(
263
+ "tasks",
264
+ self.signal_record_id, # type: ignore
265
+ SignalMessage(
266
+ action=SignalType.ACK_STATUS,
267
+ task_id=self.task_id,
268
+ status=self.status,
269
+ ).model_dump(),
270
+ )
271
+
272
+ logger.debug(
273
+ "Status report sent for task: '%s'",
274
+ self.task_id,
275
+ extra={"task_id": self.task_id},
276
+ )
@@ -19,7 +19,7 @@ from rstream import Consumer, ConsumerOffsetSpecification, MessageContext, Offse
19
19
 
20
20
  from digitalkin.logger import logger
21
21
  from digitalkin.models.module import InputModelT, SetupModelT
22
- from digitalkin.models.module.module import ModuleStatus
22
+ from digitalkin.models.module.task_monitor import TaskStatus
23
23
  from digitalkin.modules._base_module import BaseModule
24
24
  from digitalkin.modules.job_manager.base_job_manager import BaseJobManager
25
25
  from digitalkin.modules.job_manager.taskiq_broker import STREAM, STREAM_RETENTION, TASKIQ_BROKER
@@ -279,7 +279,7 @@ class TaskiqJobManager(BaseJobManager, Generic[InputModelT, SetupModelT]):
279
279
  msg = "stop_all_modules not implemented in TaskiqJobManager"
280
280
  raise NotImplementedError(msg)
281
281
 
282
- async def get_module_status(self, job_id: str) -> ModuleStatus | None:
282
+ async def get_module_status(self, job_id: str) -> TaskStatus:
283
283
  """Query a module status."""
284
284
  msg = "get_module_status not implemented in TaskiqJobManager"
285
285
  raise NotImplementedError(msg)
@@ -3,8 +3,16 @@
3
3
  from abc import ABC
4
4
 
5
5
  from digitalkin.models.module import InputModelT, OutputModelT, SecretModelT, SetupModelT
6
- from digitalkin.modules._base_module import BaseModule # type: ignore
6
+ from digitalkin.modules._base_module import BaseModule # type: ignore
7
7
 
8
8
 
9
- class ToolModule(BaseModule[InputModelT, OutputModelT, SetupModelT, SecretModelT,], ABC):
9
+ class ToolModule(
10
+ BaseModule[
11
+ InputModelT,
12
+ OutputModelT,
13
+ SetupModelT,
14
+ SecretModelT,
15
+ ],
16
+ ABC,
17
+ ):
10
18
  """ToolModule extends BaseModule to implement specific module types."""
@@ -1,14 +1,14 @@
1
1
  """Definition of the Trigger type."""
2
2
 
3
3
  from abc import ABC, abstractmethod
4
- from collections.abc import Callable, Coroutine
5
- from typing import Any, ClassVar, Generic
4
+ from typing import ClassVar, Generic
6
5
 
6
+ from digitalkin.mixins import BaseMixin
7
+ from digitalkin.models.module.module_context import ModuleContext
7
8
  from digitalkin.models.module.module_types import InputModelT, OutputModelT, SetupModelT
8
- from digitalkin.modules._base_module import ModuleContext
9
9
 
10
10
 
11
- class TriggerHandler(ABC, Generic[InputModelT, SetupModelT, OutputModelT]):
11
+ class TriggerHandler(ABC, BaseMixin, Generic[InputModelT, SetupModelT, OutputModelT]):
12
12
  """Base class for all input-trigger handlers.
13
13
 
14
14
  Each handler declares:
@@ -28,7 +28,6 @@ class TriggerHandler(ABC, Generic[InputModelT, SetupModelT, OutputModelT]):
28
28
  self,
29
29
  input_data: InputModelT,
30
30
  setup_data: SetupModelT,
31
- callback: Callable[[Any], Coroutine[Any, Any, None]],
32
31
  context: ModuleContext,
33
32
  ) -> None:
34
33
  """Asynchronously processes the input data specific to Handler and streams results via the provided callback.
@@ -36,12 +35,14 @@ class TriggerHandler(ABC, Generic[InputModelT, SetupModelT, OutputModelT]):
36
35
  Args:
37
36
  input_data (InputModelT): The input data to be processed by the handler.
38
37
  setup_data (SetupModelT): The setup or configuration data required for processing.
39
- callback (Callable[[Any], Coroutine[Any, Any, None]]): callback that stream results.
40
38
  context (ModuleContext): The context object containing module-specific information and resources.
41
39
 
42
40
  Returns:
43
41
  Any: The result of the processing, if applicable.
44
42
 
45
43
  Note:
44
+ self.send_message: : callback used to stream results.
45
+ (Callable[[OutputMdodelT], Coroutine[Any, Any, None]])
46
+
46
47
  The callback must be awaited to ensure results are streamed correctly during processing.
47
48
  """
@@ -1,7 +1,14 @@
1
1
  """This module is responsible for handling the cost services."""
2
2
 
3
- from digitalkin.services.cost.cost_strategy import CostStrategy
3
+ from digitalkin.services.cost.cost_strategy import CostConfig, CostData, CostStrategy, CostType
4
4
  from digitalkin.services.cost.default_cost import DefaultCost
5
5
  from digitalkin.services.cost.grpc_cost import GrpcCost
6
6
 
7
- __all__ = ["CostStrategy", "DefaultCost", "GrpcCost"]
7
+ __all__ = [
8
+ "CostConfig",
9
+ "CostData",
10
+ "CostStrategy",
11
+ "CostType",
12
+ "DefaultCost",
13
+ "GrpcCost",
14
+ ]
@@ -128,7 +128,7 @@ class GrpcStorage(StorageStrategy, GrpcClientWrapper):
128
128
  resp = self.exec_grpc_query("UpdateRecord", req)
129
129
  return self._build_record_from_proto(resp.stored_data)
130
130
  except Exception:
131
- logger.exception("gRPC UpdateRecord failed for %s:%s", collection, record_id)
131
+ logger.warning("gRPC UpdateRecord failed for %s:%s", collection, record_id)
132
132
  return None
133
133
 
134
134
  def _remove(self, collection: str, record_id: str) -> bool:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: digitalkin
3
- Version: 0.2.26
3
+ Version: 0.3.0
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,32 +456,32 @@ Requires-Dist: digitalkin-proto>=0.1.16
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: pydantic>=2.11.5
459
+ Requires-Dist: pydantic>=2.11.10
460
+ Requires-Dist: surrealdb>=1.0.6
461
+ Provides-Extra: taskiq
462
+ Requires-Dist: rstream>=0.31.0; extra == "taskiq"
463
+ Requires-Dist: taskiq-aio-pika>=0.4.3; extra == "taskiq"
464
+ Requires-Dist: taskiq-redis>=1.1.2; extra == "taskiq"
465
+ Requires-Dist: taskiq[reload]>=0.11.18; extra == "taskiq"
460
466
  Provides-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"
467
+ Requires-Dist: typos>=1.38.0; extra == "dev"
468
+ Requires-Dist: ruff>=0.13.3; extra == "dev"
469
+ Requires-Dist: mypy>=1.18.2; extra == "dev"
470
+ Requires-Dist: pyright>=1.1.406; extra == "dev"
465
471
  Requires-Dist: pre-commit>=4.3.0; extra == "dev"
466
472
  Requires-Dist: bump2version>=1.0.1; extra == "dev"
467
473
  Requires-Dist: build>=1.3.0; extra == "dev"
468
- Requires-Dist: twine>=6.1.0; extra == "dev"
469
- Requires-Dist: cryptography>=45.0.5; extra == "dev"
470
- Provides-Extra: examples
471
- Requires-Dist: openai>=1.75.0; extra == "examples"
474
+ Requires-Dist: twine>=6.2.0; extra == "dev"
475
+ Requires-Dist: cryptography>=46.0.2; extra == "dev"
472
476
  Provides-Extra: tests
473
477
  Requires-Dist: freezegun>=1.5.3; extra == "tests"
474
478
  Requires-Dist: hdrhistogram>=0.10.3; extra == "tests"
475
479
  Requires-Dist: grpcio-testing>=1.71.0; extra == "tests"
476
480
  Requires-Dist: psutil>=7.0.0; extra == "tests"
477
- Requires-Dist: pytest>=8.4.0; extra == "tests"
478
- Requires-Dist: pytest-asyncio>=1.1.0; extra == "tests"
479
- Requires-Dist: pytest-cov>=6.1.0; extra == "tests"
480
- Provides-Extra: taskiq
481
- Requires-Dist: rstream>=0.30.0; 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"
481
+ Requires-Dist: pytest>=8.4.2; extra == "tests"
482
+ Requires-Dist: pytest-asyncio>=1.2.0; extra == "tests"
483
+ Requires-Dist: pytest-cov>=7.0.0; extra == "tests"
484
+ Requires-Dist: hypothesis>=6.140.3; extra == "tests"
485
485
  Dynamic: license-file
486
486
 
487
487
  # DigitalKin Python SDK
@@ -7,38 +7,51 @@ 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=BUsHyIFlBw1wdLzO9qTJ6akGPKXQMBxDjRgtc6eTS4E,191
11
- digitalkin/logger.py,sha256=eskzs365CjEhLZe4OrhilEY77Tf377VQi7EtGVGax5c,5007
10
+ digitalkin/__version__.py,sha256=1cAQQLeheVwVxIu7yYP-6PyMVzQpLtDNXsgt9VoOgTQ,190
11
+ digitalkin/logger.py,sha256=8ze_tjt2G6mDTuQcsf7-UTXWP3UHZ7LZVSs_iqF4rX4,4685
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=32yrMCFAFE7FmdDL1WbuUlDuxRkaUJ_P7Dc-3_b40qs,18678
15
- digitalkin/grpc_servers/module_server.py,sha256=UDlUUEYquf0Fuq4tzvA9xs1L1PstlL5_9Da3UoQRzAc,10500
16
- digitalkin/grpc_servers/module_servicer.py,sha256=ZP2-HAS61rjAnosvW44bMRPCrd_ECZ5J31T_hBVgz0g,19132
15
+ digitalkin/grpc_servers/module_server.py,sha256=bi1XreL5zaPxbaDfsFN7-qtEbo0sKFNeyyLJjWdYMck,10212
16
+ digitalkin/grpc_servers/module_servicer.py,sha256=Df2mQYrGngGYHC6fPV3Othc5hCR2g8IuLxJx9IhzDAc,19345
17
17
  digitalkin/grpc_servers/registry_server.py,sha256=StY18DKYoPKQIU1SIzgito6D4_QA1aMVddZ8O2WGlHY,2223
18
18
  digitalkin/grpc_servers/registry_servicer.py,sha256=dqsKGHZ0LnaIvGt4ipaAuigd37sbJBndT4MAT029GsY,16471
19
19
  digitalkin/grpc_servers/utils/exceptions.py,sha256=SyOgvjggaUECYmSiqy8KJLHwHVt5IClSTxslHM-IZzI,931
20
20
  digitalkin/grpc_servers/utils/factory.py,sha256=jm6rFjiqmtSv7BIHNAOxsG9xXtSvWpx9TfzSQiX97MQ,5899
21
21
  digitalkin/grpc_servers/utils/grpc_client_wrapper.py,sha256=Vtt05KdePSFHq8FZUJ-bJo8l_d5vu7gdOv5UBtsgScg,2752
22
- digitalkin/grpc_servers/utils/models.py,sha256=hiwiGHy3sEBBFdOUBCoC1n_7GVeJhjRmi0sl4tCEJy0,8965
22
+ digitalkin/grpc_servers/utils/models.py,sha256=ZQ1Gk4zmLRX_ueuwFOwXgtyG9OEPSzFa_91I_CXZmZ0,8957
23
23
  digitalkin/grpc_servers/utils/types.py,sha256=rQ78s4nAet2jy-NIDj_PUWriT0kuGHr_w6ELjmjgBao,539
24
+ digitalkin/mixins/__init__.py,sha256=d6ljaoyJZJT9XxOrXZG5FVNvbLURb3_CZrkp4GPZWYM,590
25
+ digitalkin/mixins/base_mixin.py,sha256=uLkg6MbDtVc9DysjdfNIGKahxQLnnjuL3DYpuyNLbk8,486
26
+ digitalkin/mixins/callback_mixin.py,sha256=90nHm9-pbKT14GAy3CB3fsBtpYu5IH0woOQdNLM2e_Y,836
27
+ digitalkin/mixins/chat_history_mixin.py,sha256=cGLJb1KWY1WgC5akV6WQfk2a0blN-RQmU5TDs_ppUGM,4111
28
+ digitalkin/mixins/cost_mixin.py,sha256=nFqhLsRHdXAt3GOH6qI8sqX9KW3leTPW3gaclensBVw,2274
29
+ digitalkin/mixins/file_history_mixin.py,sha256=4rDpm-TVcD9ihZGPuqr73y1_4FnUzBlWUSoje-pQIIU,3759
30
+ digitalkin/mixins/filesystem_mixin.py,sha256=myCUmocdumG7XSN1acnn4hw1e1QbkngbnBtQtrVZQHU,1604
31
+ digitalkin/mixins/logger_mixin.py,sha256=FdVIlPXOQ7eo8DUlMmsygO9L8bis-Jhj_zw83RiE6wo,2150
32
+ digitalkin/mixins/storage_mixin.py,sha256=ptZ4a2bydIa48q0V9e395vWHTu7yw4A6rI4jwKY6gwI,2392
24
33
  digitalkin/models/__init__.py,sha256=hDHtUfswaNh8wo4NZaBItg9JqC0uNSRqXArNWSrGynY,163
25
- digitalkin/models/module/__init__.py,sha256=fgTVbsNmLZgM43Vy-Ea5-g0EG3pncmAmJl9nk-OQdzo,561
26
- digitalkin/models/module/module.py,sha256=NWOwCeD_NH0NL89AF_NJ0SwE7G1n-HTcRalodLCDmpM,749
27
- digitalkin/models/module/module_context.py,sha256=AL6bzwjYfYPLHb1Hu5kKBjaIOxCpBCPMvxEnapdyrX4,1003
28
- digitalkin/models/module/module_types.py,sha256=s8qpIr1dwsQSq13iP3v22u2OdZNKbj4Y6fGQXDcO124,3539
29
- digitalkin/models/services/__init__.py,sha256=HsW7MUGFPvH7Ri28WN4BHHBfEQk5dzU_9FOWAc-0lSE,56
34
+ digitalkin/models/module/__init__.py,sha256=nFPHp0JcAZq9ISkcSu1y2zeNyXH3V4j10oMjHzMBYBU,599
35
+ digitalkin/models/module/module.py,sha256=k0W8vfJJFth8XdDzkHm32SyTuSf3h2qF0hSrxAfGF1s,956
36
+ digitalkin/models/module/module_context.py,sha256=nhZ_Pw9lWcq5B2PPy-Rf3N0S7MXz9Ehh5Nb-4tEOmmM,3764
37
+ digitalkin/models/module/module_types.py,sha256=kkOst1OWeQVzLdf0P8JBlZqf2LLWj14-bQHyYvwUN8Y,3562
38
+ digitalkin/models/module/task_monitor.py,sha256=sEzpfmTg1cXC1ieD72YL3zwkSE6D5CIHWRi2CgK3GeQ,1288
39
+ digitalkin/models/services/__init__.py,sha256=jhfVw6egq0OcHmos_fypH9XFehbHTBw09wluVFVFEyw,226
30
40
  digitalkin/models/services/cost.py,sha256=QTEuFD6xz62nob0z4ksE-INJWcZ-iFiuNW5mvXhpFes,1599
31
- digitalkin/models/services/storage.py,sha256=cYTVIriGKiprF9OerhSxmc_jM6fUTVwmeon1yQCinkE,143
41
+ digitalkin/models/services/storage.py,sha256=k0lQUfTY9qP-PPxC1piuOhw-DfH7ao-yNvykRDJWdko,1145
32
42
  digitalkin/modules/__init__.py,sha256=VwVbKok81NGyPIBZgEj_SR-59G8tTlSb4eBJI9W6Vx4,281
33
- digitalkin/modules/_base_module.py,sha256=AavwuKQo-oKzJ_xEznmzV1fPeoW8P7wP3MW39_MVsMY,19098
43
+ digitalkin/modules/_base_module.py,sha256=y_Pw2twqlAcsJlUUa-8QKdITSrZv6KpiwVw2X7mNads,18392
34
44
  digitalkin/modules/archetype_module.py,sha256=lOe3yYufwfylZR_VGy1w-zqdqVaMI_JANfKkbH9eODE,471
35
- digitalkin/modules/tool_module.py,sha256=h9oo2vrFJdiBLW2qL_m79a9hEzfXV0L6bZd4KD5OSQs,422
36
- digitalkin/modules/trigger_handler.py,sha256=TpxFc_xkYia9B9rAvHkj02e818W08JOfIqssQqbsCpM,1785
37
- digitalkin/modules/job_manager/base_job_manager.py,sha256=4qrCw68ZAleZp8vnpd1qYH320aQO0ApH2cZrKM87Grk,6121
45
+ digitalkin/modules/tool_module.py,sha256=rLJfdYMWddiUgPLBDGG_UcHnRCHEeaqX6Fdp4DOUaCs,472
46
+ digitalkin/modules/trigger_handler.py,sha256=qPNMi-8NHqscOxciHeaXtpwjXApT3YzjMF23zQAjaZY,1770
47
+ digitalkin/modules/job_manager/base_job_manager.py,sha256=iDv9caispLmM7mqPgG_g7oaACMvNW7i7MTzBeSlmNp0,6355
38
48
  digitalkin/modules/job_manager/job_manager_models.py,sha256=onHy-DfInLZQveniMIWIKwTKSQjojz500JvHB54x93c,1129
39
- digitalkin/modules/job_manager/single_job_manager.py,sha256=nMC1BX6G62Ehmam7aVSAlKW9ShJDB1ntuMq7KbD_sSI,10564
49
+ digitalkin/modules/job_manager/single_job_manager.py,sha256=Fw64gGRdQuTLZO-HChBTbBlZvOPyNaeb_p-HhcQpGJE,11177
50
+ digitalkin/modules/job_manager/surrealdb_repository.py,sha256=3Kaz-PqfaMzSpX2RmbgbiO2pQcLVQ1tcspdCMPm7VTI,7712
51
+ digitalkin/modules/job_manager/task_manager.py,sha256=VpRoscXkNf8LBWw3jCE6MwPvtUb2Q8V_dGi059fVyVw,14402
52
+ digitalkin/modules/job_manager/task_session.py,sha256=rDKWgXf0sq7gBd6KODLPYjov3GIIyHAmFxAKTI-n1J0,9655
40
53
  digitalkin/modules/job_manager/taskiq_broker.py,sha256=4q3U03SNlb1ypup0VOa73KHLKJ9peuZUPCR5eFLMNAk,7498
41
- digitalkin/modules/job_manager/taskiq_job_manager.py,sha256=JxvNS95J_kEuRP08PvC3pQIO3DL8V1GRv7u6WUG59xg,10254
54
+ digitalkin/modules/job_manager/taskiq_job_manager.py,sha256=NHSGsqqKCWQQqx0FqM3c4tf011vFlqX1npHkcv0kEOU,10249
42
55
  digitalkin/services/__init__.py,sha256=LqGk_5DJy8Bzz62ajIq9jCeYNKQUIgtSCpafZk15FLc,910
43
56
  digitalkin/services/base_strategy.py,sha256=yA9KUJGRKuuaxA6l3GcMv8zKfWoIsW03UxJT80Yea2I,766
44
57
  digitalkin/services/services_config.py,sha256=JnyzZcG7OYBelwgn-wdVgY2n3yFTEkwLPHRZB8Tjw10,7468
@@ -46,7 +59,7 @@ digitalkin/services/services_models.py,sha256=5zXkWcfKnXGwQi9sN4OAL3XrgqOcmsTl8a
46
59
  digitalkin/services/agent/__init__.py,sha256=vJc8JN0pdtA8ecypLBeHrwAUIW6H2C8NyW-dk24rTpk,244
47
60
  digitalkin/services/agent/agent_strategy.py,sha256=42Q9RciHX6tg3CgDQkbrlIx4h_TX0WIuSpLmCjitVmA,492
48
61
  digitalkin/services/agent/default_agent.py,sha256=4N_E_eQxJGOx1KVUUg5jNOje-3ncMxF3ePB-uDuGrJc,345
49
- digitalkin/services/cost/__init__.py,sha256=Wi9ZB4LSXFsUYgkX-V1UJQkVXYDNDpp8q2dXccR2uRM,303
62
+ digitalkin/services/cost/__init__.py,sha256=sD_a5LrnLluASOC5m5vgIqjaco-MzZJd6XhillIBHr0,400
50
63
  digitalkin/services/cost/cost_strategy.py,sha256=MpPX33P_S5b2by6F4zT-rcyeRuh2V4NYPZe05VpDOGQ,2649
51
64
  digitalkin/services/cost/default_cost.py,sha256=XE7kNFde8NmbulU9m1lc3mi-vHFkbaJf0XHUc0D4UHE,3945
52
65
  digitalkin/services/cost/grpc_cost.py,sha256=cGtb0atPXSEEOrNIWee-o3ScfNRSAFXJGDu0vcWT6zg,6295
@@ -69,21 +82,21 @@ digitalkin/services/snapshot/default_snapshot.py,sha256=Mb8QwWRsHh9I_tN0ln_ZiFa1
69
82
  digitalkin/services/snapshot/snapshot_strategy.py,sha256=B1TU3V_k9A-OdqBkdyc41-ihnrW5Btcwd1KyQdHT46A,898
70
83
  digitalkin/services/storage/__init__.py,sha256=T-ocYLLphudkQgzvG47jBOm5GQsRFRIGA88y7Ur4akg,341
71
84
  digitalkin/services/storage/default_storage.py,sha256=D8e-UYUkb2GvDEHMWcN3EkcIKXWA8DrsaQsXVjoXAYQ,7975
72
- digitalkin/services/storage/grpc_storage.py,sha256=3ZHGq3wnbF8dZjJcYN1EGTEUXA4rur0XEGtTBwAcGB4,7206
85
+ digitalkin/services/storage/grpc_storage.py,sha256=7RPeqkjG4JdW1lhjGpKx1qF5fp_LE-sST7fp5oT6uD0,7204
73
86
  digitalkin/services/storage/storage_strategy.py,sha256=sERF5tIJnzpb1iNqTXic9xRkGaXMifo6kb709ubB-Yo,8848
74
87
  digitalkin/utils/__init__.py,sha256=sJnY-ZUgsjMfojAjONC1VN14mhgIDnzyOlGkw21rRnM,28
75
88
  digitalkin/utils/arg_parser.py,sha256=nvjI1pKDY1HfS0oGcMQPtdTQcggXLtpxXMbnMxNEKRU,3109
76
89
  digitalkin/utils/development_mode_action.py,sha256=TqRuAF_A7bDD4twRB4PnZcRoNeaiAnEdxM5kvy4aoaA,1511
77
90
  digitalkin/utils/llm_ready_schema.py,sha256=JjMug_lrQllqFoanaC091VgOqwAd-_YzcpqFlS7p778,2375
78
91
  digitalkin/utils/package_discover.py,sha256=3e9-6Vf3yAAv2VkHHVK4QVqHJBxQqg3d8uuDTsXph24,13471
79
- digitalkin-0.2.26.dist-info/licenses/LICENSE,sha256=Ies4HFv2r2hzDRakJYxk3Y60uDFLiG-orIgeTpstnIo,20327
92
+ digitalkin-0.3.0.dist-info/licenses/LICENSE,sha256=Ies4HFv2r2hzDRakJYxk3Y60uDFLiG-orIgeTpstnIo,20327
80
93
  modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
94
  modules/cpu_intensive_module.py,sha256=ejB9XPnFfA0uCuFUQbM3fy5UYfqqAlF36rv_P5Ri8ho,8363
82
95
  modules/minimal_llm_module.py,sha256=Ijld__ZnhzfLwpXD1XVkLZ7jyKZKyOFZczOpiPttJZc,11216
83
96
  modules/text_transform_module.py,sha256=bwPSnEUthZQyfLwcTLo52iAxItAoknkLh8Y3m5aywaY,7251
84
97
  services/filesystem_module.py,sha256=71Mcja8jCQqiqFHPdsIXplFIHTvgkxRhp0TRXuCfgkk,7430
85
98
  services/storage_module.py,sha256=ybTMqmvGaTrR8PqJ4FU0cwxaDjT36TskVrGoetTGmno,6955
86
- digitalkin-0.2.26.dist-info/METADATA,sha256=43WocXOsMwRLYxm4eKVI8li_OiQub-hLnlrKnfKtny0,30579
87
- digitalkin-0.2.26.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
88
- digitalkin-0.2.26.dist-info/top_level.txt,sha256=gcjqlyrZuLjIyxrOIavCQM_olpr6ND5kPKkZd2j0xGo,40
89
- digitalkin-0.2.26.dist-info/RECORD,,
99
+ digitalkin-0.3.0.dist-info/METADATA,sha256=_6KDoMRgjmgnAXmPLUVpNY1EcyN86SE5c_zvtNo-K8w,30588
100
+ digitalkin-0.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
101
+ digitalkin-0.3.0.dist-info/top_level.txt,sha256=gcjqlyrZuLjIyxrOIavCQM_olpr6ND5kPKkZd2j0xGo,40
102
+ digitalkin-0.3.0.dist-info/RECORD,,