digitalkin 0.3.2.dev17__py3-none-any.whl → 0.3.2.dev18__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.3.2.dev17"
8
+ __version__ = "0.3.2.dev18"
@@ -8,7 +8,7 @@ from typing import Any
8
8
  from zoneinfo import ZoneInfo
9
9
 
10
10
  from digitalkin.logger import logger
11
- from digitalkin.models.module.tool_cache import ToolCache, ToolDefinition, ToolParameter
11
+ from digitalkin.models.module.tool_cache import ToolCache, ToolDefinition, ToolModuleInfo, ToolParameter
12
12
  from digitalkin.services.agent.agent_strategy import AgentStrategy
13
13
  from digitalkin.services.communication.communication_strategy import CommunicationStrategy
14
14
  from digitalkin.services.cost.cost_strategy import CostStrategy
@@ -227,20 +227,20 @@ class ModuleContext:
227
227
  llm_format=llm_format,
228
228
  )
229
229
 
230
- async def create_openai_style_tools(self, tool_name: str) -> list[dict[str, Any]]:
230
+ async def create_openai_style_tools(self, module_id: str) -> list[dict[str, Any]]:
231
231
  """Create OpenAI-style function calling schemas for a tool module.
232
232
 
233
233
  Uses tool cache (fast path) with registry fallback. Returns one schema
234
234
  per ToolDefinition (protocol) in the module.
235
235
 
236
236
  Args:
237
- tool_name: Module ID to look up (checks cache first, then registry).
237
+ module_id: Module ID to look up (checks cache first, then registry).
238
238
 
239
239
  Returns:
240
240
  List of OpenAI-style tool schemas, one per protocol. Empty if not found.
241
241
  """
242
242
  tool_module_info = await self.tool_cache.get(
243
- tool_name, registry=self.registry, communication=self.communication
243
+ module_id, registry=self.registry, communication=self.communication
244
244
  )
245
245
  if not tool_module_info:
246
246
  return []
@@ -299,13 +299,11 @@ class ModuleContext:
299
299
 
300
300
  communication = self.communication
301
301
  session = self.session
302
- address = tool_module_info.address
303
- port = tool_module_info.port
304
302
 
305
303
  result = []
306
304
  for tool_def in tool_module_info.tools:
307
305
  # Capture tool_def in closure via separate method
308
- fn = ModuleContext._create_single_tool_function(communication, session, address, port, tool_def)
306
+ fn = ModuleContext._create_single_tool_function(communication, session, tool_module_info, tool_def)
309
307
  result.append((tool_def, fn))
310
308
 
311
309
  return result
@@ -314,8 +312,7 @@ class ModuleContext:
314
312
  def _create_single_tool_function(
315
313
  communication: CommunicationStrategy,
316
314
  session: Session,
317
- address: str,
318
- port: int,
315
+ tool_module_info: ToolModuleInfo,
319
316
  tool_def: ToolDefinition,
320
317
  ) -> Callable[..., AsyncGenerator[dict, None]]:
321
318
  """Create a single tool function for a specific protocol.
@@ -323,8 +320,7 @@ class ModuleContext:
323
320
  Args:
324
321
  communication: Communication strategy for gRPC calls.
325
322
  session: Current session with setup_id and mission_id.
326
- address: Module address.
327
- port: Module port.
323
+ tool_module_info: Tool module information containing address and port.
328
324
  tool_def: Tool definition with protocol name.
329
325
 
330
326
  Returns:
@@ -336,10 +332,10 @@ class ModuleContext:
336
332
  kwargs["protocol"] = protocol
337
333
  wrapped_input = {"root": kwargs}
338
334
  async for response in communication.call_module(
339
- module_address=address,
340
- module_port=port,
335
+ module_address=tool_module_info.address,
336
+ module_port=tool_module_info.port,
341
337
  input_data=wrapped_input,
342
- setup_id=session.setup_id,
338
+ setup_id=tool_module_info.setup_id,
343
339
  mission_id=session.mission_id,
344
340
  ):
345
341
  yield response
@@ -52,6 +52,7 @@ class ToolModuleInfo(ModuleInfo):
52
52
  """Module info for tool modules."""
53
53
 
54
54
  tools: list[ToolDefinition]
55
+ setup_id: str
55
56
 
56
57
 
57
58
  class ToolCache(BaseModel):
@@ -59,22 +60,22 @@ class ToolCache(BaseModel):
59
60
 
60
61
  entries: dict[str, ToolModuleInfo] = Field(default_factory=dict)
61
62
 
62
- def add(self, setup_tool_name: str, tool_module_info: ToolModuleInfo) -> None:
63
+ def add(self, setup_id: str, tool_module_info: ToolModuleInfo) -> None:
63
64
  """Add a tool to the cache.
64
65
 
65
66
  Args:
66
- setup_tool_name: Field name from SetupModel used as cache key.
67
+ setup_id: Field name from SetupModel used as cache key.
67
68
  tool_module_info: Resolved tool module information.
68
69
  """
69
- self.entries[setup_tool_name] = tool_module_info
70
+ self.entries[setup_id] = tool_module_info
70
71
  logger.debug(
71
72
  "Tool cached",
72
- extra={"setup_tool_name": setup_tool_name, "module_id": tool_module_info.module_id},
73
+ extra={"setup_id": setup_id, "module_id": tool_module_info.module_id},
73
74
  )
74
75
 
75
76
  async def get(
76
77
  self,
77
- setup_tool_name: str,
78
+ setup_id: str,
78
79
  *,
79
80
  registry: RegistryStrategy | None = None,
80
81
  communication: "CommunicationStrategy | None" = None,
@@ -82,28 +83,28 @@ class ToolCache(BaseModel):
82
83
  """Get a tool from cache, optionally querying registry on miss.
83
84
 
84
85
  Args:
85
- setup_tool_name: Field name to look up.
86
+ setup_id: Field name to look up.
86
87
  registry: Optional registry to query on cache miss.
87
88
  communication: Optional communication strategy for schema fetching.
88
89
 
89
90
  Returns:
90
91
  ToolModuleInfo if found, None otherwise.
91
92
  """
92
- cached = self.entries.get(setup_tool_name)
93
+ cached = self.entries.get(setup_id)
93
94
  if cached:
94
95
  return cached
95
96
 
96
97
  if registry and communication:
97
98
  try:
98
- setup_info = registry.get_setup(setup_tool_name)
99
+ setup_info = registry.get_setup(setup_id)
99
100
  if setup_info and setup_info.module_id:
100
101
  info = registry.discover_by_id(setup_info.module_id)
101
102
  if info:
102
- tool_info = await module_info_to_tool_module_info(info, communication)
103
- self.add(setup_tool_name, tool_info)
103
+ tool_info = await module_info_to_tool_module_info(info, setup_id, communication)
104
+ self.add(setup_id, tool_info)
104
105
  return tool_info
105
106
  except Exception:
106
- logger.exception("Registry lookup failed", extra={"setup_tool_name": setup_tool_name})
107
+ logger.exception("Registry lookup failed", extra={"setup_id": setup_id})
107
108
 
108
109
  return None
109
110
 
@@ -122,6 +123,7 @@ class ToolCache(BaseModel):
122
123
 
123
124
  async def module_info_to_tool_module_info(
124
125
  module_info: ModuleInfo,
126
+ setup_id: str,
125
127
  communication: "CommunicationStrategy",
126
128
  *,
127
129
  llm_format: bool = True,
@@ -133,6 +135,7 @@ async def module_info_to_tool_module_info(
133
135
 
134
136
  Args:
135
137
  module_info: Module info from registry.
138
+ setup_id: Setup ID from tool configuration.
136
139
  communication: Communication strategy for gRPC calls.
137
140
  llm_format: Use LLM-friendly schema format.
138
141
 
@@ -161,6 +164,7 @@ async def module_info_to_tool_module_info(
161
164
  documentation=module_info.documentation,
162
165
  status=module_info.status,
163
166
  tools=tools,
167
+ setup_id=setup_id,
164
168
  )
165
169
 
166
170
 
@@ -115,7 +115,7 @@ class ToolReference(BaseModel):
115
115
  self.config.module_id = setup.module_id
116
116
  info = registry.discover_by_id(self.config.module_id)
117
117
  if info:
118
- tool_module_info = await module_info_to_tool_module_info(info, communication)
118
+ tool_module_info = await module_info_to_tool_module_info(info, self.config.setup_id, communication)
119
119
  self._cached_info = tool_module_info
120
120
  return tool_module_info
121
121
 
@@ -126,7 +126,9 @@ class ToolReference(BaseModel):
126
126
  organization_id=self.config.organization_id,
127
127
  )
128
128
  if results:
129
- tool_module_info = await module_info_to_tool_module_info(results[0], communication)
129
+ tool_module_info = await module_info_to_tool_module_info(
130
+ results[0], self.config.setup_id, communication
131
+ )
130
132
  self._cached_info = tool_module_info
131
133
  self.config.module_id = tool_module_info.module_id
132
134
  return tool_module_info
@@ -55,6 +55,8 @@ class SchemaSplitter:
55
55
  for item in value:
56
56
  if isinstance(item, dict):
57
57
  cls._extract_ui_properties(item, ui_target)
58
+ elif key in {"if", "then", "else"} and isinstance(value, dict):
59
+ cls._extract_ui_properties(value, ui_target)
58
60
 
59
61
  @classmethod
60
62
  def _process_object( # noqa: C901, PLR0912
@@ -107,11 +109,15 @@ class SchemaSplitter:
107
109
  item_json: dict[str, Any] = {}
108
110
  cls._strip_ui_properties(item, item_json)
109
111
  json_target["allOf"].append(item_json)
112
+ # Extract UI properties from allOf item
113
+ cls._extract_ui_properties(item, ui_target)
110
114
  else:
111
115
  json_target["allOf"].append(item)
112
116
  elif key in {"if", "then", "else"} and isinstance(value, dict):
113
117
  json_target[key] = {}
114
118
  cls._strip_ui_properties(value, json_target[key])
119
+ # Extract UI properties from conditional
120
+ cls._extract_ui_properties(value, ui_target)
115
121
  else:
116
122
  json_target[key] = value
117
123
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: digitalkin
3
- Version: 0.3.2.dev17
3
+ Version: 0.3.2.dev18
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
@@ -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=Y3kvX8EPStPR7XivYOXc5tCfaRbBYw08EWY8LQ_zjgM,196
10
+ digitalkin/__version__.py,sha256=6eu1NkqoRgH4x9vy4KK1UNb25WQD1SomFTIF5afEldM,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
@@ -53,11 +53,11 @@ digitalkin/models/grpc_servers/types.py,sha256=rQ78s4nAet2jy-NIDj_PUWriT0kuGHr_w
53
53
  digitalkin/models/module/__init__.py,sha256=e2a_AUmobkpyITQKvMkDaDxvb-GOMHhDF9fn0q5_EnQ,959
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=u4yvvtYNwbSJSnV0omLasGN7wRZgaLS7trBBneeT2CI,12178
56
+ digitalkin/models/module/module_context.py,sha256=QDdjZdhIJpvU_2Tn7kkJsZ1givB4dM1-ksopdF4VySw,12176
57
57
  digitalkin/models/module/module_types.py,sha256=C9azCNBk76xMa-Mww8_6AiwQR8MLAsEyUOvBYxytovI,739
58
58
  digitalkin/models/module/setup_types.py,sha256=namyC-0iA4ryHqKCzjYsVYeFDduwMqYCYRmQSSH8414,19356
59
- digitalkin/models/module/tool_cache.py,sha256=bWZAjL2UMJIpQw0SeoOGa0S1flU6V8eKUYe09mluNog,7111
60
- digitalkin/models/module/tool_reference.py,sha256=DBOw22_ZtmOwooejl2J8QZ_gRazNkhGyeD-CvnMpHvE,4388
59
+ digitalkin/models/module/tool_cache.py,sha256=5e30A_GxT2W-w1LZFmVUqOxDjPcrZ8s_eW7p9impO64,7153
60
+ digitalkin/models/module/tool_reference.py,sha256=eIWJrT6syyEaXAWRXIlWYTst-j0XuvtU_va9m3tj_KU,4470
61
61
  digitalkin/models/module/utility.py,sha256=gnbYfWpXGbomUI0fWf7T-Qm_VvT-LXDv1OuA9zObwVg,5589
62
62
  digitalkin/models/services/__init__.py,sha256=jhfVw6egq0OcHmos_fypH9XFehbHTBw09wluVFVFEyw,226
63
63
  digitalkin/models/services/cost.py,sha256=9PXvd5RrIk9vCrRjcUGQ9ZyAokEbwLg4s0RfnE-aLP4,1616
@@ -121,8 +121,8 @@ digitalkin/utils/development_mode_action.py,sha256=2hznh0ajW_4ZTysfoc0Y49161f_PQ
121
121
  digitalkin/utils/dynamic_schema.py,sha256=y5csxjuqVHjWDpnTUzxbcUuI_wou9-ibRVHQlBs_btY,15275
122
122
  digitalkin/utils/llm_ready_schema.py,sha256=JjMug_lrQllqFoanaC091VgOqwAd-_YzcpqFlS7p778,2375
123
123
  digitalkin/utils/package_discover.py,sha256=sa6Zp5Kape1Zr4iYiNrnZxiHDnqM06ODk6yfWHom53w,13465
124
- digitalkin/utils/schema_splitter.py,sha256=KMvYRHDHlwdhh_c6FJxkWvLStZo9Kbj-jd3pIGPZfxk,9317
125
- digitalkin-0.3.2.dev17.dist-info/licenses/LICENSE,sha256=Ies4HFv2r2hzDRakJYxk3Y60uDFLiG-orIgeTpstnIo,20327
124
+ digitalkin/utils/schema_splitter.py,sha256=9PHC-bvEDQudyYZNgXyjFtp7EJlmw4C_gPCJ-JmGDk0,9704
125
+ digitalkin-0.3.2.dev18.dist-info/licenses/LICENSE,sha256=Ies4HFv2r2hzDRakJYxk3Y60uDFLiG-orIgeTpstnIo,20327
126
126
  modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
127
127
  modules/archetype_with_tools_module.py,sha256=PXTS6IXmC_OjxTmVrL_pYVI0MKwXjD5I1UJO_2xa10Q,7632
128
128
  modules/cpu_intensive_module.py,sha256=GZlirQDZdYuXrI46sv1q4RNAHZjL4EptHVQTvgK9zz8,8363
@@ -137,7 +137,7 @@ monitoring/digitalkin_observability/prometheus.py,sha256=gDmM9ySaVwPAe7Yg84pLxmE
137
137
  monitoring/tests/test_metrics.py,sha256=ugnYfAwqBPO6zA8z4afKTlyBWECTivacYSN-URQCn2E,5856
138
138
  services/filesystem_module.py,sha256=U4dgqtuDadaXz8PJ1d_uQ_1EPncBqudAQCLUICF9yL4,7421
139
139
  services/storage_module.py,sha256=Wz2MzLvqs2D_bnBBgtnujYcAKK2V2KFMk8K21RoepSE,6972
140
- digitalkin-0.3.2.dev17.dist-info/METADATA,sha256=rhqhGY-Zx3iq_pSrr0nRpsygx7UhYYsVLjUoVDzXMq8,29725
141
- digitalkin-0.3.2.dev17.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
142
- digitalkin-0.3.2.dev17.dist-info/top_level.txt,sha256=AYVIesKrO0jnedQ-Muog9JBehG81WeTCNeOFoJgwsgE,51
143
- digitalkin-0.3.2.dev17.dist-info/RECORD,,
140
+ digitalkin-0.3.2.dev18.dist-info/METADATA,sha256=sJPrEQfDsIC_mcsZfFttiA3fybX3J7KbVT7zozw3qMw,29725
141
+ digitalkin-0.3.2.dev18.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
142
+ digitalkin-0.3.2.dev18.dist-info/top_level.txt,sha256=AYVIesKrO0jnedQ-Muog9JBehG81WeTCNeOFoJgwsgE,51
143
+ digitalkin-0.3.2.dev18.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5