digitalkin 0.3.2.dev7__py3-none-any.whl → 0.3.2.dev10__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 +1 -1
- digitalkin/grpc_servers/module_servicer.py +0 -11
- digitalkin/grpc_servers/utils/grpc_client_wrapper.py +2 -2
- digitalkin/grpc_servers/utils/utility_schema_extender.py +2 -1
- digitalkin/models/grpc_servers/models.py +91 -6
- digitalkin/models/module/module_context.py +136 -23
- digitalkin/models/module/setup_types.py +177 -260
- digitalkin/models/module/tool_cache.py +27 -187
- digitalkin/models/module/tool_reference.py +42 -45
- digitalkin/models/services/registry.py +0 -7
- digitalkin/modules/_base_module.py +85 -58
- digitalkin/services/registry/__init__.py +1 -1
- digitalkin/services/registry/default_registry.py +1 -1
- digitalkin/services/registry/grpc_registry.py +1 -1
- digitalkin/services/registry/registry_models.py +1 -29
- digitalkin/services/registry/registry_strategy.py +1 -1
- digitalkin/utils/schema_splitter.py +207 -0
- {digitalkin-0.3.2.dev7.dist-info → digitalkin-0.3.2.dev10.dist-info}/METADATA +1 -1
- {digitalkin-0.3.2.dev7.dist-info → digitalkin-0.3.2.dev10.dist-info}/RECORD +29 -22
- {digitalkin-0.3.2.dev7.dist-info → digitalkin-0.3.2.dev10.dist-info}/top_level.txt +1 -0
- modules/archetype_with_tools_module.py +244 -0
- monitoring/digitalkin_observability/__init__.py +46 -0
- monitoring/digitalkin_observability/http_server.py +150 -0
- monitoring/digitalkin_observability/interceptors.py +176 -0
- monitoring/digitalkin_observability/metrics.py +201 -0
- monitoring/digitalkin_observability/prometheus.py +137 -0
- monitoring/tests/test_metrics.py +172 -0
- digitalkin/models/module/module_helpers.py +0 -189
- {digitalkin-0.3.2.dev7.dist-info → digitalkin-0.3.2.dev10.dist-info}/WHEEL +0 -0
- {digitalkin-0.3.2.dev7.dist-info → digitalkin-0.3.2.dev10.dist-info}/licenses/LICENSE +0 -0
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
from digitalkin.models.services.registry import (
|
|
4
4
|
ModuleInfo,
|
|
5
|
-
ModuleStatusInfo,
|
|
6
5
|
RegistryModuleStatus,
|
|
7
6
|
RegistryModuleType,
|
|
8
7
|
)
|
|
@@ -12,6 +11,7 @@ from digitalkin.services.registry.exceptions import (
|
|
|
12
11
|
RegistryServiceError,
|
|
13
12
|
)
|
|
14
13
|
from digitalkin.services.registry.grpc_registry import GrpcRegistry
|
|
14
|
+
from digitalkin.services.registry.registry_models import ModuleStatusInfo
|
|
15
15
|
from digitalkin.services.registry.registry_strategy import RegistryStrategy
|
|
16
16
|
|
|
17
17
|
__all__ = [
|
|
@@ -4,11 +4,11 @@ from typing import ClassVar
|
|
|
4
4
|
|
|
5
5
|
from digitalkin.models.services.registry import (
|
|
6
6
|
ModuleInfo,
|
|
7
|
-
ModuleStatusInfo,
|
|
8
7
|
RegistryModuleStatus,
|
|
9
8
|
RegistryModuleType,
|
|
10
9
|
)
|
|
11
10
|
from digitalkin.services.registry.exceptions import RegistryModuleNotFoundError
|
|
11
|
+
from digitalkin.services.registry.registry_models import ModuleStatusInfo
|
|
12
12
|
from digitalkin.services.registry.registry_strategy import RegistryStrategy
|
|
13
13
|
|
|
14
14
|
|
|
@@ -20,7 +20,6 @@ from digitalkin.logger import logger
|
|
|
20
20
|
from digitalkin.models.grpc_servers.models import ClientConfig
|
|
21
21
|
from digitalkin.models.services.registry import (
|
|
22
22
|
ModuleInfo,
|
|
23
|
-
ModuleStatusInfo,
|
|
24
23
|
RegistryModuleStatus,
|
|
25
24
|
RegistryModuleType,
|
|
26
25
|
)
|
|
@@ -28,6 +27,7 @@ from digitalkin.services.registry.exceptions import (
|
|
|
28
27
|
RegistryModuleNotFoundError,
|
|
29
28
|
RegistryServiceError,
|
|
30
29
|
)
|
|
30
|
+
from digitalkin.services.registry.registry_models import ModuleStatusInfo
|
|
31
31
|
from digitalkin.services.registry.registry_strategy import RegistryStrategy
|
|
32
32
|
|
|
33
33
|
|
|
@@ -3,37 +3,9 @@
|
|
|
3
3
|
This module contains Pydantic models for registry service data structures.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
from enum import IntEnum
|
|
7
|
-
|
|
8
6
|
from pydantic import BaseModel
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
class RegistryModuleStatus(IntEnum):
|
|
12
|
-
"""Module status in the registry.
|
|
13
|
-
|
|
14
|
-
Maps to proto ModuleStatus enum values.
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
UNKNOWN = 0
|
|
18
|
-
READY = 1
|
|
19
|
-
ACTIVE = 2
|
|
20
|
-
OFFLINE = 3
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class ModuleInfo(BaseModel):
|
|
24
|
-
"""Complete module information from registry.
|
|
25
|
-
|
|
26
|
-
Maps to proto ModuleDescriptor message.
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
module_id: str
|
|
30
|
-
module_type: str
|
|
31
|
-
address: str
|
|
32
|
-
port: int
|
|
33
|
-
version: str
|
|
34
|
-
name: str = ""
|
|
35
|
-
documentation: str | None = None
|
|
36
|
-
status: RegistryModuleStatus | None = None
|
|
8
|
+
from digitalkin.models.services.registry import RegistryModuleStatus
|
|
37
9
|
|
|
38
10
|
|
|
39
11
|
class ModuleStatusInfo(BaseModel):
|
|
@@ -5,10 +5,10 @@ from typing import Any
|
|
|
5
5
|
|
|
6
6
|
from digitalkin.models.services.registry import (
|
|
7
7
|
ModuleInfo,
|
|
8
|
-
ModuleStatusInfo,
|
|
9
8
|
RegistryModuleStatus,
|
|
10
9
|
)
|
|
11
10
|
from digitalkin.services.base_strategy import BaseStrategy
|
|
11
|
+
from digitalkin.services.registry.registry_models import ModuleStatusInfo
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class RegistryStrategy(BaseStrategy, ABC):
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"""Schema splitter for react-jsonschema-form."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class SchemaSplitter:
|
|
7
|
+
"""Splits a combined JSON schema into jsonschema and uischema for react-jsonschema-form."""
|
|
8
|
+
|
|
9
|
+
@classmethod
|
|
10
|
+
def split(cls, combined_schema: dict[str, Any]) -> tuple[dict[str, Any], dict[str, Any]]:
|
|
11
|
+
"""Split schema into (jsonschema, uischema).
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
combined_schema: Combined JSON schema with ui:* properties.
|
|
15
|
+
|
|
16
|
+
Returns:
|
|
17
|
+
Tuple of (jsonschema, uischema).
|
|
18
|
+
"""
|
|
19
|
+
defs_ui: dict[str, dict[str, Any]] = {}
|
|
20
|
+
if "$defs" in combined_schema:
|
|
21
|
+
for def_name, def_value in combined_schema["$defs"].items():
|
|
22
|
+
if isinstance(def_value, dict):
|
|
23
|
+
defs_ui[def_name] = {}
|
|
24
|
+
cls._extract_ui_properties(def_value, defs_ui[def_name])
|
|
25
|
+
|
|
26
|
+
json_schema: dict[str, Any] = {}
|
|
27
|
+
ui_schema: dict[str, Any] = {}
|
|
28
|
+
cls._process_object(combined_schema, json_schema, ui_schema, defs_ui)
|
|
29
|
+
return json_schema, ui_schema
|
|
30
|
+
|
|
31
|
+
@classmethod
|
|
32
|
+
def _extract_ui_properties(cls, source: dict[str, Any], ui_target: dict[str, Any]) -> None: # noqa: C901
|
|
33
|
+
"""Extract ui:* properties from source into ui_target recursively.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
source: Source dict to extract from.
|
|
37
|
+
ui_target: Target dict for ui properties.
|
|
38
|
+
"""
|
|
39
|
+
for key, value in source.items():
|
|
40
|
+
if key.startswith("ui:"):
|
|
41
|
+
ui_target[key] = value
|
|
42
|
+
elif key == "properties" and isinstance(value, dict):
|
|
43
|
+
for prop_name, prop_value in value.items():
|
|
44
|
+
if isinstance(prop_value, dict):
|
|
45
|
+
prop_ui: dict[str, Any] = {}
|
|
46
|
+
cls._extract_ui_properties(prop_value, prop_ui)
|
|
47
|
+
if prop_ui:
|
|
48
|
+
ui_target[prop_name] = prop_ui
|
|
49
|
+
elif key == "items" and isinstance(value, dict):
|
|
50
|
+
items_ui: dict[str, Any] = {}
|
|
51
|
+
cls._extract_ui_properties(value, items_ui)
|
|
52
|
+
if items_ui:
|
|
53
|
+
ui_target["items"] = items_ui
|
|
54
|
+
elif key == "allOf" and isinstance(value, list):
|
|
55
|
+
for item in value:
|
|
56
|
+
if isinstance(item, dict):
|
|
57
|
+
cls._extract_ui_properties(item, ui_target)
|
|
58
|
+
|
|
59
|
+
@classmethod
|
|
60
|
+
def _process_object( # noqa: C901, PLR0912
|
|
61
|
+
cls,
|
|
62
|
+
source: dict[str, Any],
|
|
63
|
+
json_target: dict[str, Any],
|
|
64
|
+
ui_target: dict[str, Any],
|
|
65
|
+
defs_ui: dict[str, dict[str, Any]],
|
|
66
|
+
) -> None:
|
|
67
|
+
"""Process an object, splitting json and ui properties.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
source: Source object to process.
|
|
71
|
+
json_target: Target dict for json schema.
|
|
72
|
+
ui_target: Target dict for ui schema.
|
|
73
|
+
defs_ui: Pre-extracted UI properties from $defs.
|
|
74
|
+
"""
|
|
75
|
+
for key, value in source.items():
|
|
76
|
+
if key.startswith("ui:"):
|
|
77
|
+
ui_target[key] = value
|
|
78
|
+
elif key == "properties" and isinstance(value, dict):
|
|
79
|
+
json_target["properties"] = {}
|
|
80
|
+
for prop_name, prop_value in value.items():
|
|
81
|
+
if isinstance(prop_value, dict):
|
|
82
|
+
json_target["properties"][prop_name] = {}
|
|
83
|
+
prop_ui: dict[str, Any] = {}
|
|
84
|
+
cls._process_property(prop_value, json_target["properties"][prop_name], prop_ui, defs_ui)
|
|
85
|
+
if prop_ui:
|
|
86
|
+
ui_target[prop_name] = prop_ui
|
|
87
|
+
else:
|
|
88
|
+
json_target["properties"][prop_name] = prop_value
|
|
89
|
+
elif key == "$defs" and isinstance(value, dict):
|
|
90
|
+
json_target["$defs"] = {}
|
|
91
|
+
for def_name, def_value in value.items():
|
|
92
|
+
if isinstance(def_value, dict):
|
|
93
|
+
json_target["$defs"][def_name] = {}
|
|
94
|
+
cls._strip_ui_properties(def_value, json_target["$defs"][def_name])
|
|
95
|
+
else:
|
|
96
|
+
json_target["$defs"][def_name] = def_value
|
|
97
|
+
elif key == "items" and isinstance(value, dict):
|
|
98
|
+
json_target["items"] = {}
|
|
99
|
+
items_ui: dict[str, Any] = {}
|
|
100
|
+
cls._process_property(value, json_target["items"], items_ui, defs_ui)
|
|
101
|
+
if items_ui:
|
|
102
|
+
ui_target["items"] = items_ui
|
|
103
|
+
elif key == "allOf" and isinstance(value, list):
|
|
104
|
+
json_target["allOf"] = []
|
|
105
|
+
for item in value:
|
|
106
|
+
if isinstance(item, dict):
|
|
107
|
+
item_json: dict[str, Any] = {}
|
|
108
|
+
cls._strip_ui_properties(item, item_json)
|
|
109
|
+
json_target["allOf"].append(item_json)
|
|
110
|
+
else:
|
|
111
|
+
json_target["allOf"].append(item)
|
|
112
|
+
elif key in {"if", "then", "else"} and isinstance(value, dict):
|
|
113
|
+
json_target[key] = {}
|
|
114
|
+
cls._strip_ui_properties(value, json_target[key])
|
|
115
|
+
else:
|
|
116
|
+
json_target[key] = value
|
|
117
|
+
|
|
118
|
+
@classmethod
|
|
119
|
+
def _process_property( # noqa: C901, PLR0912
|
|
120
|
+
cls,
|
|
121
|
+
source: dict[str, Any],
|
|
122
|
+
json_target: dict[str, Any],
|
|
123
|
+
ui_target: dict[str, Any],
|
|
124
|
+
defs_ui: dict[str, dict[str, Any]],
|
|
125
|
+
) -> None:
|
|
126
|
+
"""Process a property, resolving $ref for UI properties.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
source: Source property dict.
|
|
130
|
+
json_target: Target dict for json schema.
|
|
131
|
+
ui_target: Target dict for ui schema.
|
|
132
|
+
defs_ui: Pre-extracted UI properties from $defs.
|
|
133
|
+
"""
|
|
134
|
+
if "$ref" in source:
|
|
135
|
+
ref_path = source["$ref"]
|
|
136
|
+
if ref_path.startswith("#/$defs/"):
|
|
137
|
+
def_name = ref_path[8:]
|
|
138
|
+
if def_name in defs_ui:
|
|
139
|
+
ui_target.update(defs_ui[def_name])
|
|
140
|
+
|
|
141
|
+
for key, value in source.items():
|
|
142
|
+
if key.startswith("ui:"):
|
|
143
|
+
ui_target[key] = value
|
|
144
|
+
elif key == "properties" and isinstance(value, dict):
|
|
145
|
+
json_target["properties"] = {}
|
|
146
|
+
for prop_name, prop_value in value.items():
|
|
147
|
+
if isinstance(prop_value, dict):
|
|
148
|
+
json_target["properties"][prop_name] = {}
|
|
149
|
+
prop_ui: dict[str, Any] = {}
|
|
150
|
+
cls._process_property(prop_value, json_target["properties"][prop_name], prop_ui, defs_ui)
|
|
151
|
+
if prop_ui:
|
|
152
|
+
ui_target[prop_name] = prop_ui
|
|
153
|
+
else:
|
|
154
|
+
json_target["properties"][prop_name] = prop_value
|
|
155
|
+
elif key == "items" and isinstance(value, dict):
|
|
156
|
+
json_target["items"] = {}
|
|
157
|
+
items_ui: dict[str, Any] = {}
|
|
158
|
+
cls._process_property(value, json_target["items"], items_ui, defs_ui)
|
|
159
|
+
if items_ui:
|
|
160
|
+
ui_target["items"] = items_ui
|
|
161
|
+
else:
|
|
162
|
+
json_target[key] = value
|
|
163
|
+
|
|
164
|
+
@classmethod
|
|
165
|
+
def _strip_ui_properties(cls, source: dict[str, Any], json_target: dict[str, Any]) -> None: # noqa: C901, PLR0912
|
|
166
|
+
"""Copy source to json_target, stripping ui:* properties.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
source: Source dict.
|
|
170
|
+
json_target: Target dict without ui:* properties.
|
|
171
|
+
"""
|
|
172
|
+
for key, value in source.items():
|
|
173
|
+
if key.startswith("ui:"):
|
|
174
|
+
continue
|
|
175
|
+
if key == "properties" and isinstance(value, dict):
|
|
176
|
+
json_target["properties"] = {}
|
|
177
|
+
for prop_name, prop_value in value.items():
|
|
178
|
+
if isinstance(prop_value, dict):
|
|
179
|
+
json_target["properties"][prop_name] = {}
|
|
180
|
+
cls._strip_ui_properties(prop_value, json_target["properties"][prop_name])
|
|
181
|
+
else:
|
|
182
|
+
json_target["properties"][prop_name] = prop_value
|
|
183
|
+
elif key == "$defs" and isinstance(value, dict):
|
|
184
|
+
json_target["$defs"] = {}
|
|
185
|
+
for def_name, def_value in value.items():
|
|
186
|
+
if isinstance(def_value, dict):
|
|
187
|
+
json_target["$defs"][def_name] = {}
|
|
188
|
+
cls._strip_ui_properties(def_value, json_target["$defs"][def_name])
|
|
189
|
+
else:
|
|
190
|
+
json_target["$defs"][def_name] = def_value
|
|
191
|
+
elif key == "items" and isinstance(value, dict):
|
|
192
|
+
json_target["items"] = {}
|
|
193
|
+
cls._strip_ui_properties(value, json_target["items"])
|
|
194
|
+
elif key == "allOf" and isinstance(value, list):
|
|
195
|
+
json_target["allOf"] = []
|
|
196
|
+
for item in value:
|
|
197
|
+
if isinstance(item, dict):
|
|
198
|
+
item_json: dict[str, Any] = {}
|
|
199
|
+
cls._strip_ui_properties(item, item_json)
|
|
200
|
+
json_target["allOf"].append(item_json)
|
|
201
|
+
else:
|
|
202
|
+
json_target["allOf"].append(item)
|
|
203
|
+
elif key in {"if", "then", "else"} and isinstance(value, dict):
|
|
204
|
+
json_target[key] = {}
|
|
205
|
+
cls._strip_ui_properties(value, json_target[key])
|
|
206
|
+
else:
|
|
207
|
+
json_target[key] = value
|
|
@@ -7,7 +7,7 @@ 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=
|
|
10
|
+
digitalkin/__version__.py,sha256=HFosF_nDLUB58s-K9x_90emrDL2e-FS3aqanQgLZcDM,196
|
|
11
11
|
digitalkin/logger.py,sha256=8ze_tjt2G6mDTuQcsf7-UTXWP3UHZ7LZVSs_iqF4rX4,4685
|
|
12
12
|
digitalkin/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
13
|
digitalkin/core/__init__.py,sha256=FJRcJ-B1Viyn-38L8XpOpZ8KOnf1I7PCDOAmKXLQhqc,71
|
|
@@ -28,12 +28,12 @@ digitalkin/core/task_manager/task_session.py,sha256=5jw21bT_SPXUzWE7tk6YG62EXqlR
|
|
|
28
28
|
digitalkin/grpc_servers/__init__.py,sha256=ZIRMJ1Lcas8yQ106GCup6hn2UBOsx1sNk8ap0lpEDnY,72
|
|
29
29
|
digitalkin/grpc_servers/_base_server.py,sha256=ZVeCDwI7w7fFbPTXPkeJb_SOuLfd2T7za3T4oCu2UWY,18680
|
|
30
30
|
digitalkin/grpc_servers/module_server.py,sha256=Ec3izzV2YpdN8rGs_cX-iVulQ00FkLR5dBflHlQ8a6Y,7849
|
|
31
|
-
digitalkin/grpc_servers/module_servicer.py,sha256=
|
|
31
|
+
digitalkin/grpc_servers/module_servicer.py,sha256=7GQOyAPYMxHVaJGplgDNiVoKr1oaAIL-zdZpyDpznTA,20530
|
|
32
32
|
digitalkin/grpc_servers/utils/__init__.py,sha256=ZnAIb_F8z4NhtPypqkdmzgRSzolKnJTk3oZx5GfWH5Y,38
|
|
33
33
|
digitalkin/grpc_servers/utils/exceptions.py,sha256=LtaDtlqXCeT6iqApogs4pbtezotOVeg4fhnFzGBvFsY,692
|
|
34
|
-
digitalkin/grpc_servers/utils/grpc_client_wrapper.py,sha256=
|
|
34
|
+
digitalkin/grpc_servers/utils/grpc_client_wrapper.py,sha256=nGG8QdKnBH0UG9qbKrlPwIvcvPgW3osw7O3cImxisPE,3279
|
|
35
35
|
digitalkin/grpc_servers/utils/grpc_error_handler.py,sha256=0wPEU4713_ZlgIilaeXJV2bi90tHwYO1myDrSLeenKk,1848
|
|
36
|
-
digitalkin/grpc_servers/utils/utility_schema_extender.py,sha256=
|
|
36
|
+
digitalkin/grpc_servers/utils/utility_schema_extender.py,sha256=UCJR5YAKA_Wg5Q9feInf4AZW6AVtSQZYRZuMsaEgZVo,3775
|
|
37
37
|
digitalkin/mixins/__init__.py,sha256=d6ljaoyJZJT9XxOrXZG5FVNvbLURb3_CZrkp4GPZWYM,590
|
|
38
38
|
digitalkin/mixins/base_mixin.py,sha256=uLkg6MbDtVc9DysjdfNIGKahxQLnnjuL3DYpuyNLbk8,486
|
|
39
39
|
digitalkin/mixins/callback_mixin.py,sha256=90nHm9-pbKT14GAy3CB3fsBtpYu5IH0woOQdNLM2e_Y,836
|
|
@@ -48,24 +48,23 @@ digitalkin/models/core/__init__.py,sha256=jOMDmPX0uSfGA9zUi0u_kOvYJ46VdIssoIhVYv
|
|
|
48
48
|
digitalkin/models/core/job_manager_models.py,sha256=wvf2dzRzAu0-zzzAXQe6XTC36cNA10sXRLt2p_TFqjk,1003
|
|
49
49
|
digitalkin/models/core/task_monitor.py,sha256=CW-jydSgXMV464W0pqfar0HpgqlSxqdujmC-f8p9EQc,2639
|
|
50
50
|
digitalkin/models/grpc_servers/__init__.py,sha256=0tA71nPSXgRrh9DoLvx-TSwZXdYIRUEItoadpTL1cTo,42
|
|
51
|
-
digitalkin/models/grpc_servers/models.py,sha256=
|
|
51
|
+
digitalkin/models/grpc_servers/models.py,sha256=gRX94eL71a5mLIie-lCOwE7a0As_AuGduxPPzTHbAe4,13797
|
|
52
52
|
digitalkin/models/grpc_servers/types.py,sha256=rQ78s4nAet2jy-NIDj_PUWriT0kuGHr_w6ELjmjgBao,539
|
|
53
53
|
digitalkin/models/module/__init__.py,sha256=N55wan3rAUVPEGLIDjXoFM_-DYY_zxvbQOZHzNDfwoY,751
|
|
54
54
|
digitalkin/models/module/base_types.py,sha256=oIylVNqo0idTFj4dRgCt7P19daNZ-AlvgCPpL9TJvto,1850
|
|
55
55
|
digitalkin/models/module/module.py,sha256=k0W8vfJJFth8XdDzkHm32SyTuSf3h2qF0hSrxAfGF1s,956
|
|
56
|
-
digitalkin/models/module/module_context.py,sha256=
|
|
57
|
-
digitalkin/models/module/module_helpers.py,sha256=n5lx25c5zRmuivcThC-HdumsjyWDv31xC6tI6NMLR7U,6438
|
|
56
|
+
digitalkin/models/module/module_context.py,sha256=qpjyMYgTCyQS0lW2RhTKZsoQKwFpv6l08FIM0sqC6DQ,10326
|
|
58
57
|
digitalkin/models/module/module_types.py,sha256=C9azCNBk76xMa-Mww8_6AiwQR8MLAsEyUOvBYxytovI,739
|
|
59
|
-
digitalkin/models/module/setup_types.py,sha256=
|
|
60
|
-
digitalkin/models/module/tool_cache.py,sha256=
|
|
61
|
-
digitalkin/models/module/tool_reference.py,sha256=
|
|
58
|
+
digitalkin/models/module/setup_types.py,sha256=XMKyDm-7n_Za9tDBv1AkgXUowlUj46SMxWANa_yg_LU,18311
|
|
59
|
+
digitalkin/models/module/tool_cache.py,sha256=RP3JwASV8dFUZEKudyALbu0_tq81lstuEc4QHMQpmvM,2073
|
|
60
|
+
digitalkin/models/module/tool_reference.py,sha256=1AyNK-8McsSTEb62aaSou5AAXkKUOJqrFtJ5YWrFbmw,3512
|
|
62
61
|
digitalkin/models/module/utility.py,sha256=gnbYfWpXGbomUI0fWf7T-Qm_VvT-LXDv1OuA9zObwVg,5589
|
|
63
62
|
digitalkin/models/services/__init__.py,sha256=jhfVw6egq0OcHmos_fypH9XFehbHTBw09wluVFVFEyw,226
|
|
64
63
|
digitalkin/models/services/cost.py,sha256=9PXvd5RrIk9vCrRjcUGQ9ZyAokEbwLg4s0RfnE-aLP4,1616
|
|
65
|
-
digitalkin/models/services/registry.py,sha256=
|
|
64
|
+
digitalkin/models/services/registry.py,sha256=hz_r03-K633XHu2fOb5HWsE59EPFusBBipy0Gz6OBvI,705
|
|
66
65
|
digitalkin/models/services/storage.py,sha256=wp7F-AvTsU46ujGPcguqM5kUKRZx4399D4EGAAJt2zs,1143
|
|
67
66
|
digitalkin/modules/__init__.py,sha256=vTQk8DWopxQSJ17BjE5dNhq247Rou55iQLJdBxoPUmo,296
|
|
68
|
-
digitalkin/modules/_base_module.py,sha256=
|
|
67
|
+
digitalkin/modules/_base_module.py,sha256=4-fS376f9ti3xSgM946yRccHcEGttdo2QYKaxdqk1kY,22451
|
|
69
68
|
digitalkin/modules/archetype_module.py,sha256=XC9tl1Yr6QlbPn_x0eov6UUZwQgwW--BYPPMYVJH_NU,505
|
|
70
69
|
digitalkin/modules/tool_module.py,sha256=GBis7bKCkvWFCYLRvaS9oZVmLBBve1w8BhVnKOU2sCc,506
|
|
71
70
|
digitalkin/modules/trigger_handler.py,sha256=qPNMi-8NHqscOxciHeaXtpwjXApT3YzjMF23zQAjaZY,1770
|
|
@@ -95,12 +94,12 @@ digitalkin/services/filesystem/grpc_filesystem.py,sha256=9Cjp4ie-mJ2EMMZ8DjCqeV6
|
|
|
95
94
|
digitalkin/services/identity/__init__.py,sha256=InkeyLgFYYwItx8mePA8HpfacOMWZwwuc0G4pWtKq9s,270
|
|
96
95
|
digitalkin/services/identity/default_identity.py,sha256=Y2auZHrGSZTIN5D8HyjLvLcNbYFM1CNUE23x7p5VIGw,386
|
|
97
96
|
digitalkin/services/identity/identity_strategy.py,sha256=skappBbds1_qa0Gr24FGrNX1N0_OYhYT1Lh7dUaAirE,429
|
|
98
|
-
digitalkin/services/registry/__init__.py,sha256=
|
|
99
|
-
digitalkin/services/registry/default_registry.py,sha256=
|
|
97
|
+
digitalkin/services/registry/__init__.py,sha256=WPGQM3U-QvMXhsaOy9BN0kVMU3QkPFwAMT3lGmTR-Ko,835
|
|
98
|
+
digitalkin/services/registry/default_registry.py,sha256=tOqw9Ve9w_BzhqrZmHuUl5Ps-J_KTEwYg3tu1gNIHmw,4258
|
|
100
99
|
digitalkin/services/registry/exceptions.py,sha256=tAcVXioCzDqfBvxB_P0uQpaK_LDLrFb0KpymROuqs-8,1371
|
|
101
|
-
digitalkin/services/registry/grpc_registry.py,sha256=
|
|
102
|
-
digitalkin/services/registry/registry_models.py,sha256=
|
|
103
|
-
digitalkin/services/registry/registry_strategy.py,sha256=
|
|
100
|
+
digitalkin/services/registry/grpc_registry.py,sha256=2_He-I9I4SXdjYA9QYxFWQrr_xBao6LIYXsgiICkeHY,10822
|
|
101
|
+
digitalkin/services/registry/registry_models.py,sha256=DJEwMJg5_BewpgHDtY8xIGWj9jA9H07iYgHLCv81giY,331
|
|
102
|
+
digitalkin/services/registry/registry_strategy.py,sha256=N6oLxMwnYkM_XVW7WDxZoSfFafjUtsFDig3F8VQZj7Q,2745
|
|
104
103
|
digitalkin/services/setup/__init__.py,sha256=t6xcvEWqTbcRZstBFK9cESEqaZKvpW14VtYygxIqfYQ,65
|
|
105
104
|
digitalkin/services/setup/default_setup.py,sha256=zTG9Nvw3Tqy9qctSEnjWE4Mlqol321AUaTlIm6Jl1k0,8195
|
|
106
105
|
digitalkin/services/setup/grpc_setup.py,sha256=aEAHiG0WSzNSQtJjn7xAGQwj70b0HrFO8GBKFXRx3aI,13925
|
|
@@ -122,15 +121,23 @@ digitalkin/utils/development_mode_action.py,sha256=2hznh0ajW_4ZTysfoc0Y49161f_PQ
|
|
|
122
121
|
digitalkin/utils/dynamic_schema.py,sha256=5-B3dBGlCYYv6uRJkgudtc0ZpBOTYxl0yKedDGsteZQ,15184
|
|
123
122
|
digitalkin/utils/llm_ready_schema.py,sha256=JjMug_lrQllqFoanaC091VgOqwAd-_YzcpqFlS7p778,2375
|
|
124
123
|
digitalkin/utils/package_discover.py,sha256=sa6Zp5Kape1Zr4iYiNrnZxiHDnqM06ODk6yfWHom53w,13465
|
|
125
|
-
digitalkin
|
|
124
|
+
digitalkin/utils/schema_splitter.py,sha256=KMvYRHDHlwdhh_c6FJxkWvLStZo9Kbj-jd3pIGPZfxk,9317
|
|
125
|
+
digitalkin-0.3.2.dev10.dist-info/licenses/LICENSE,sha256=Ies4HFv2r2hzDRakJYxk3Y60uDFLiG-orIgeTpstnIo,20327
|
|
126
126
|
modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
127
|
+
modules/archetype_with_tools_module.py,sha256=PXTS6IXmC_OjxTmVrL_pYVI0MKwXjD5I1UJO_2xa10Q,7632
|
|
127
128
|
modules/cpu_intensive_module.py,sha256=GZlirQDZdYuXrI46sv1q4RNAHZjL4EptHVQTvgK9zz8,8363
|
|
128
129
|
modules/dynamic_setup_module.py,sha256=tKvUWZdlYZkfAgKR0mLuFcLiFGKpVgpsz10LeJ6B2QI,11410
|
|
129
130
|
modules/minimal_llm_module.py,sha256=N9aIzZQI-miyH4AB4xTmGHpMvdSLnYyXNOD4Z3YFzis,11216
|
|
130
131
|
modules/text_transform_module.py,sha256=MfhI_Ki1U6qk379ne6oazNEu4PhO4R3cRezEcr0nGPw,7251
|
|
132
|
+
monitoring/digitalkin_observability/__init__.py,sha256=PXG4xbMbmiVNkIaVG899H9CHvcld7c0bSbaLHqKeDeo,1247
|
|
133
|
+
monitoring/digitalkin_observability/http_server.py,sha256=kFbWFQvaqq2VVwwqDozV0pRPe7RkAXsa9xCWruMlOyk,4527
|
|
134
|
+
monitoring/digitalkin_observability/interceptors.py,sha256=Sx6o0s8FSMfIGKVAtjVl7l-sIygP45od6eITl7DroBU,6219
|
|
135
|
+
monitoring/digitalkin_observability/metrics.py,sha256=XhVRE8y6tbzJqxIzEHa5MT3I0k3hgpxjzZf_R6SyjbQ,7553
|
|
136
|
+
monitoring/digitalkin_observability/prometheus.py,sha256=gDmM9ySaVwPAe7Yg84pLxmEKu0Cudezi8pK3RtqWs6g,5457
|
|
137
|
+
monitoring/tests/test_metrics.py,sha256=ugnYfAwqBPO6zA8z4afKTlyBWECTivacYSN-URQCn2E,5856
|
|
131
138
|
services/filesystem_module.py,sha256=U4dgqtuDadaXz8PJ1d_uQ_1EPncBqudAQCLUICF9yL4,7421
|
|
132
139
|
services/storage_module.py,sha256=Wz2MzLvqs2D_bnBBgtnujYcAKK2V2KFMk8K21RoepSE,6972
|
|
133
|
-
digitalkin-0.3.2.
|
|
134
|
-
digitalkin-0.3.2.
|
|
135
|
-
digitalkin-0.3.2.
|
|
136
|
-
digitalkin-0.3.2.
|
|
140
|
+
digitalkin-0.3.2.dev10.dist-info/METADATA,sha256=qExgKNDQPoWMU4v-k-tRwJyJ6on7nFhA83U4pqCgrwE,29725
|
|
141
|
+
digitalkin-0.3.2.dev10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
142
|
+
digitalkin-0.3.2.dev10.dist-info/top_level.txt,sha256=AYVIesKrO0jnedQ-Muog9JBehG81WeTCNeOFoJgwsgE,51
|
|
143
|
+
digitalkin-0.3.2.dev10.dist-info/RECORD,,
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
"""Example archetype module with tool cache integration."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from typing import Any, ClassVar, Literal
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
|
|
8
|
+
from digitalkin.models.grpc_servers.models import ClientConfig, SecurityMode, ServerMode
|
|
9
|
+
from digitalkin.models.module.module_context import ModuleContext
|
|
10
|
+
from digitalkin.models.module.setup_types import SetupModel
|
|
11
|
+
from digitalkin.models.module.tool_reference import (
|
|
12
|
+
ToolReference,
|
|
13
|
+
ToolReferenceConfig,
|
|
14
|
+
ToolSelectionMode,
|
|
15
|
+
)
|
|
16
|
+
from digitalkin.modules._base_module import BaseModule # noqa: PLC2701
|
|
17
|
+
from digitalkin.services.services_models import ServicesStrategy
|
|
18
|
+
|
|
19
|
+
logging.basicConfig(
|
|
20
|
+
level=logging.DEBUG,
|
|
21
|
+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
22
|
+
)
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class MessageInputPayload(BaseModel):
|
|
27
|
+
"""Message input payload."""
|
|
28
|
+
|
|
29
|
+
payload_type: Literal["message"] = "message"
|
|
30
|
+
user_prompt: str
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class ArchetypeInput(BaseModel):
|
|
34
|
+
"""Archetype input."""
|
|
35
|
+
|
|
36
|
+
payload: MessageInputPayload = Field(discriminator="payload_type")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class MessageOutputPayload(BaseModel):
|
|
40
|
+
"""Message output payload."""
|
|
41
|
+
|
|
42
|
+
payload_type: Literal["message"] = "message"
|
|
43
|
+
response: str
|
|
44
|
+
tools_used: list[str] = Field(default_factory=list)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class ArchetypeOutput(BaseModel):
|
|
48
|
+
"""Archetype output."""
|
|
49
|
+
|
|
50
|
+
payload: MessageOutputPayload = Field(discriminator="payload_type")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class ArchetypeSetup(SetupModel):
|
|
54
|
+
"""Setup with tool references resolved during config setup."""
|
|
55
|
+
|
|
56
|
+
model_name: str = Field(
|
|
57
|
+
default="gpt-4",
|
|
58
|
+
json_schema_extra={"config": True},
|
|
59
|
+
)
|
|
60
|
+
temperature: float = Field(
|
|
61
|
+
default=0.7,
|
|
62
|
+
json_schema_extra={"config": True},
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
search_tool: ToolReference = Field(
|
|
66
|
+
default_factory=lambda: ToolReference(
|
|
67
|
+
config=ToolReferenceConfig(
|
|
68
|
+
mode=ToolSelectionMode.FIXED,
|
|
69
|
+
module_id="search-tool-v1",
|
|
70
|
+
)
|
|
71
|
+
),
|
|
72
|
+
json_schema_extra={"config": True},
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
calculator_tool: ToolReference = Field(
|
|
76
|
+
default_factory=lambda: ToolReference(
|
|
77
|
+
config=ToolReferenceConfig(
|
|
78
|
+
mode=ToolSelectionMode.TAG,
|
|
79
|
+
tag="math-calculator",
|
|
80
|
+
)
|
|
81
|
+
),
|
|
82
|
+
json_schema_extra={"config": True},
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
dynamic_tool: ToolReference = Field(
|
|
86
|
+
default_factory=lambda: ToolReference(
|
|
87
|
+
config=ToolReferenceConfig(
|
|
88
|
+
mode=ToolSelectionMode.DISCOVERABLE,
|
|
89
|
+
)
|
|
90
|
+
),
|
|
91
|
+
json_schema_extra={"config": True},
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
system_prompt: str = Field(
|
|
95
|
+
default="You are a helpful assistant with access to tools.",
|
|
96
|
+
json_schema_extra={"hidden": True},
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class ArchetypeConfigSetup(BaseModel):
|
|
101
|
+
"""Config setup model."""
|
|
102
|
+
|
|
103
|
+
additional_instructions: str | None = None
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class ArchetypeSecret(BaseModel):
|
|
107
|
+
"""Secrets model."""
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
client_config = ClientConfig(
|
|
111
|
+
host="[::]",
|
|
112
|
+
port=50152,
|
|
113
|
+
mode=ServerMode.ASYNC,
|
|
114
|
+
security=SecurityMode.INSECURE,
|
|
115
|
+
credentials=None,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class ArchetypeWithToolsModule(
|
|
120
|
+
BaseModule[
|
|
121
|
+
ArchetypeInput,
|
|
122
|
+
ArchetypeOutput,
|
|
123
|
+
ArchetypeSetup,
|
|
124
|
+
ArchetypeSecret,
|
|
125
|
+
]
|
|
126
|
+
):
|
|
127
|
+
"""Archetype module demonstrating tool cache usage."""
|
|
128
|
+
|
|
129
|
+
name = "ArchetypeWithToolsModule"
|
|
130
|
+
description = "Archetype with tool cache integration"
|
|
131
|
+
|
|
132
|
+
config_setup_format = ArchetypeConfigSetup
|
|
133
|
+
input_format = ArchetypeInput
|
|
134
|
+
output_format = ArchetypeOutput
|
|
135
|
+
setup_format = ArchetypeSetup
|
|
136
|
+
secret_format = ArchetypeSecret
|
|
137
|
+
|
|
138
|
+
metadata: ClassVar[dict[str, Any]] = {
|
|
139
|
+
"name": "ArchetypeWithToolsModule",
|
|
140
|
+
"version": "1.0.0",
|
|
141
|
+
"tags": ["archetype", "tools"],
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
services_config_strategies: ClassVar[dict[str, ServicesStrategy | None]] = {}
|
|
145
|
+
services_config_params: ClassVar[dict[str, dict[str, Any | None] | None]] = {
|
|
146
|
+
"registry": {
|
|
147
|
+
"config": {},
|
|
148
|
+
"client_config": client_config,
|
|
149
|
+
},
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async def run_config_setup(
|
|
153
|
+
self,
|
|
154
|
+
context: ModuleContext, # noqa: ARG002
|
|
155
|
+
config_setup_data: ArchetypeSetup,
|
|
156
|
+
) -> ArchetypeSetup:
|
|
157
|
+
"""Custom config setup logic, runs in parallel with tool resolution.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
context: Module context with services.
|
|
161
|
+
config_setup_data: Setup data being configured.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
Configured setup data.
|
|
165
|
+
"""
|
|
166
|
+
logger.info("Running config setup for %s", self.name)
|
|
167
|
+
return config_setup_data
|
|
168
|
+
|
|
169
|
+
async def initialize(self, context: ModuleContext, setup_data: ArchetypeSetup) -> None: # noqa: ARG002
|
|
170
|
+
"""Initialize module.
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
context: Module context with services and tool cache.
|
|
174
|
+
setup_data: Setup data for the module.
|
|
175
|
+
"""
|
|
176
|
+
logger.info("Initializing %s", self.name)
|
|
177
|
+
if context.tool_cache:
|
|
178
|
+
logger.info("Available tools: %s", context.tool_cache.list_tools())
|
|
179
|
+
|
|
180
|
+
async def run(
|
|
181
|
+
self,
|
|
182
|
+
input_data: ArchetypeInput,
|
|
183
|
+
setup_data: ArchetypeSetup, # noqa: ARG002
|
|
184
|
+
) -> None:
|
|
185
|
+
"""Run module with tool cache lookups and call_module_by_id.
|
|
186
|
+
|
|
187
|
+
Args:
|
|
188
|
+
input_data: Input data to process.
|
|
189
|
+
setup_data: Setup configuration.
|
|
190
|
+
"""
|
|
191
|
+
logger.info("Running %s", self.name)
|
|
192
|
+
|
|
193
|
+
tools_used: list[str] = []
|
|
194
|
+
tool_results: list[str] = []
|
|
195
|
+
|
|
196
|
+
# Get search tool from cache and call via call_module_by_id
|
|
197
|
+
search_info = self.context.tool_cache.get("search_tool")
|
|
198
|
+
if search_info:
|
|
199
|
+
tools_used.append(f"search:{search_info.module_id}")
|
|
200
|
+
async for response in self.context.call_module_by_id(
|
|
201
|
+
module_id=search_info.module_id,
|
|
202
|
+
input_data={"query": input_data.payload.user_prompt},
|
|
203
|
+
setup_id=self.context.session.setup_id,
|
|
204
|
+
mission_id=self.context.session.mission_id,
|
|
205
|
+
):
|
|
206
|
+
tool_results.append(f"search_result: {response}")
|
|
207
|
+
|
|
208
|
+
# Get calculator tool from cache
|
|
209
|
+
calc_info = self.context.tool_cache.get("calculator_tool")
|
|
210
|
+
if calc_info:
|
|
211
|
+
tools_used.append(f"calculator:{calc_info.module_id}")
|
|
212
|
+
async for response in self.context.call_module_by_id(
|
|
213
|
+
module_id=calc_info.module_id,
|
|
214
|
+
input_data={"expression": "2 + 2"},
|
|
215
|
+
setup_id=self.context.session.setup_id,
|
|
216
|
+
mission_id=self.context.session.mission_id,
|
|
217
|
+
):
|
|
218
|
+
tool_results.append(f"calc_result: {response}")
|
|
219
|
+
|
|
220
|
+
# Dynamic discovery via registry fallback for tools not in cache
|
|
221
|
+
dynamic_info = self.context.tool_cache.get(
|
|
222
|
+
"some_dynamic_tool",
|
|
223
|
+
registry=self.context.registry,
|
|
224
|
+
)
|
|
225
|
+
if dynamic_info:
|
|
226
|
+
tools_used.append(f"dynamic:{dynamic_info.module_id}")
|
|
227
|
+
async for response in self.context.call_module_by_id(
|
|
228
|
+
module_id=dynamic_info.module_id,
|
|
229
|
+
input_data={"prompt": input_data.payload.user_prompt},
|
|
230
|
+
setup_id=self.context.session.setup_id,
|
|
231
|
+
mission_id=self.context.session.mission_id,
|
|
232
|
+
):
|
|
233
|
+
tool_results.append(f"dynamic_result: {response}")
|
|
234
|
+
|
|
235
|
+
response = MessageOutputPayload(
|
|
236
|
+
response=f"Processed: {input_data.payload.user_prompt} | Results: {len(tool_results)}",
|
|
237
|
+
tools_used=tools_used,
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
await self.context.callbacks.send_message(ArchetypeOutput(payload=response))
|
|
241
|
+
|
|
242
|
+
async def cleanup(self) -> None:
|
|
243
|
+
"""Clean up resources."""
|
|
244
|
+
logger.info("Cleaning up %s", self.name)
|