digitalkin 0.3.2.dev22__py3-none-any.whl → 0.3.2.dev23__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.dev22"
8
+ __version__ = "0.3.2.dev23"
@@ -14,7 +14,7 @@ from digitalkin.models.module.tool_cache import (
14
14
  )
15
15
  from digitalkin.models.module.tool_reference import (
16
16
  ToolReference,
17
- ToolReferenceInput,
17
+ tool_reference_input,
18
18
  )
19
19
  from digitalkin.models.module.utility import (
20
20
  EndOfStreamOutput,
@@ -35,7 +35,7 @@ __all__ = [
35
35
  "ToolModuleInfo",
36
36
  "ToolParameter",
37
37
  "ToolReference",
38
- "ToolReferenceInput",
39
38
  "UtilityProtocol",
40
39
  "UtilityRegistry",
40
+ "tool_reference_input",
41
41
  ]
@@ -2,8 +2,9 @@
2
2
 
3
3
  from typing import Annotated
4
4
 
5
- from pydantic import BaseModel, BeforeValidator, Field
6
- from pydantic.json_schema import GetJsonSchemaHandler, JsonSchemaValue
5
+ from pydantic import AfterValidator, BaseModel, BeforeValidator, Field
6
+ from pydantic.annotated_handlers import GetJsonSchemaHandler
7
+ from pydantic.json_schema import JsonSchemaValue
7
8
  from pydantic_core import CoreSchema
8
9
 
9
10
  from digitalkin.models.module.tool_cache import (
@@ -16,20 +17,14 @@ from digitalkin.services.registry import RegistryStrategy
16
17
 
17
18
 
18
19
  class ToolReference(BaseModel):
19
- """Tool selection configuration and reference.
20
-
21
- The mode determines validation requirements and resolution behavior:
22
- - FIXED: Requires setup_id, resolves to exact tool
23
- - MODULE: Requires module_id, returns constraint for frontend selection
24
- - TAG: Requires tag, returns constraint for frontend selection
25
- - DISCOVERABLE: Optional module_id/tag constraints, returns constraint info
26
- """
20
+ """Tool selection configuration and reference."""
27
21
 
28
22
  selected_tools: list[SelectedTool] = Field(default=[], description="Tools selected by the user.")
29
23
  setup_ids: list[str] = Field(default=[], description="Setup IDs for the user to choose from.")
30
24
  module_ids: list[str] = Field(default=[], description="Module IDs for the user to choose from.")
31
25
  tags: list[str] = Field(default=[], description="Tags for the user to choose from.")
32
26
  max_tools: int = Field(default=0, description="Maximum tools to select. 0 for unlimited.")
27
+ min_tools: int = Field(default=0, description="Minimum tools to select. 0 for no minimum.")
33
28
 
34
29
  async def resolve(self, registry: RegistryStrategy, communication: CommunicationStrategy) -> list[ToolModuleInfo]:
35
30
  """Resolve this reference using the registry.
@@ -55,25 +50,25 @@ class ToolReference(BaseModel):
55
50
  return resolved
56
51
 
57
52
 
58
- def _convert_to_tool_reference(v: object) -> "ToolReference | object":
59
- """Convert list of setup IDs to ToolReference.
60
-
61
- Args:
62
- v: Input value, either a list of setup IDs or passthrough.
63
-
64
- Returns:
65
- ToolReference if input is list, otherwise original value.
66
- """
67
- if isinstance(v, list):
68
- return ToolReference(selected_tools=[SelectedTool(setup_id=sid, slug=sid) for sid in v])
69
- return v
70
-
71
-
72
53
  class _ToolReferenceInputSchema:
73
- """Custom JSON schema generator that wraps ToolReference in anyOf with array option."""
54
+ """Custom JSON schema generator with configurable maxItems and ui:options."""
55
+
56
+ def __init__(
57
+ self,
58
+ setup_ids: list[str],
59
+ module_ids: list[str],
60
+ tags: list[str],
61
+ max_tools: int = 0,
62
+ min_tools: int = 0,
63
+ ) -> None:
64
+ self.setup_ids = setup_ids
65
+ self.module_ids = module_ids
66
+ self.tags = tags
67
+ self.max_tools = max_tools
68
+ self.min_tools = min_tools
74
69
 
75
- @staticmethod
76
70
  def __get_pydantic_json_schema__( # noqa: PLW3201
71
+ self,
77
72
  schema: CoreSchema,
78
73
  handler: GetJsonSchemaHandler,
79
74
  ) -> JsonSchemaValue:
@@ -84,20 +79,95 @@ class _ToolReferenceInputSchema:
84
79
  handler: Handler to generate JSON schema from core schema.
85
80
 
86
81
  Returns:
87
- JSON schema with anyOf accepting array or ToolReference.
82
+ JSON schema with anyOf accepting array or ToolReference, plus ui:options.
88
83
  """
89
84
  json_schema = handler(schema)
85
+
86
+ array_option: dict[str, object] = {"type": "array", "items": {"type": "string"}}
87
+ if self.max_tools > 0 and self.max_tools >= self.min_tools:
88
+ array_option["maxItems"] = self.max_tools
89
+ if self.min_tools > 0 and self.min_tools <= self.max_tools:
90
+ array_option["minItems"] = self.min_tools
91
+
90
92
  return {
91
93
  "anyOf": [
92
- {"type": "array", "items": {"type": "string"}},
94
+ array_option,
93
95
  json_schema,
94
- ]
96
+ ],
97
+ "ui:options": {
98
+ "setup_ids": self.setup_ids,
99
+ "module_ids": self.module_ids,
100
+ "tags": self.tags,
101
+ "max_tools": self.max_tools,
102
+ "min_tools": self.min_tools,
103
+ },
95
104
  }
96
105
 
97
106
 
98
- ToolReferenceInput = Annotated[
99
- ToolReference,
100
- BeforeValidator(_convert_to_tool_reference),
101
- _ToolReferenceInputSchema,
102
- ]
103
- """Type alias for ToolReference fields that accept list[str] input from frontend."""
107
+ def tool_reference_input(
108
+ setup_ids: list[str] = [],
109
+ module_ids: list[str] = [],
110
+ tags: list[str] = [],
111
+ max_tools: int = 0,
112
+ min_tools: int = 0,
113
+ ) -> type[ToolReference]:
114
+ """Create ToolReferenceInput type with schema options and validation.
115
+
116
+ Args:
117
+ setup_ids: Setup IDs for the user to choose from.
118
+ module_ids: Module IDs for the user to choose from.
119
+ tags: Tags for the user to choose from.
120
+ max_tools: Maximum tools allowed. 0 for unlimited.
121
+ min_tools: Minimum tools required. 0 for no minimum.
122
+
123
+ Returns:
124
+ Annotated type for use in Pydantic models.
125
+ """
126
+
127
+ def convert_to_tool_reference(v: object) -> ToolReference | object:
128
+ """Convert list of setup IDs to ToolReference with config preserved.
129
+
130
+ Returns:
131
+ ToolReference if input is list, otherwise original value.
132
+ """
133
+ if isinstance(v, list):
134
+ return ToolReference(
135
+ selected_tools=[SelectedTool(setup_id=sid, slug=sid) for sid in v],
136
+ setup_ids=setup_ids,
137
+ module_ids=module_ids,
138
+ tags=tags,
139
+ max_tools=max_tools,
140
+ min_tools=min_tools,
141
+ )
142
+ return v
143
+
144
+ def validate_tools_count(v: ToolReference) -> ToolReference:
145
+ """Validate selected_tools count against min/max constraints.
146
+
147
+ Returns:
148
+ The validated ToolReference.
149
+
150
+ Raises:
151
+ ValueError: If count is below min_tools or above max_tools.
152
+ """
153
+ count = len(v.selected_tools)
154
+ if min_tools > 0 and count < min_tools:
155
+ msg = f"At least {min_tools} tools required, got {count}"
156
+ raise ValueError(msg)
157
+ if max_tools > 0 and count > max_tools:
158
+ msg = f"At most {max_tools} tools allowed, got {count}"
159
+ raise ValueError(msg)
160
+ return v
161
+
162
+ return Annotated[ # type: ignore[return-value]
163
+ ToolReference,
164
+ BeforeValidator(convert_to_tool_reference),
165
+ AfterValidator(validate_tools_count),
166
+ _ToolReferenceInputSchema(
167
+ setup_ids=setup_ids,
168
+ module_ids=module_ids,
169
+ tags=tags,
170
+ max_tools=max_tools,
171
+ min_tools=min_tools,
172
+ ),
173
+ ]
@@ -30,7 +30,7 @@ class SchemaSplitter:
30
30
  return json_schema, ui_schema
31
31
 
32
32
  @classmethod
33
- def _extract_ui_properties(
33
+ def _extract_ui_properties( # noqa: C901, PLR0912
34
34
  cls,
35
35
  source: dict[str, Any],
36
36
  ui_target: dict[str, Any],
@@ -64,12 +64,11 @@ class SchemaSplitter:
64
64
  cls._extract_ui_properties(item, ui_target, defs)
65
65
  elif key in {"if", "then", "else"} and isinstance(value, dict):
66
66
  cls._extract_ui_properties(value, ui_target, defs)
67
- elif key == "$ref" and isinstance(value, str) and defs is not None:
67
+ elif key == "$ref" and isinstance(value, str) and defs is not None and value.startswith("#/$defs/"):
68
68
  # Resolve $ref and extract UI properties from the referenced definition
69
- if value.startswith("#/$defs/"):
70
- def_name = value[8:]
71
- if def_name in defs:
72
- cls._extract_ui_properties(defs[def_name], ui_target, defs)
69
+ def_name = value[8:]
70
+ if def_name in defs:
71
+ cls._extract_ui_properties(defs[def_name], ui_target, defs)
73
72
 
74
73
  @classmethod
75
74
  def _process_object( # noqa: C901, PLR0912
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: digitalkin
3
- Version: 0.3.2.dev22
3
+ Version: 0.3.2.dev23
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
@@ -437,18 +437,18 @@ License: Attribution-NonCommercial-ShareAlike 4.0 International
437
437
  Project-URL: Homepage, https://github.com/DigitalKin-ai/digitalkin
438
438
  Project-URL: Documentation, https://github.com/DigitalKin-ai/digitalkin
439
439
  Project-URL: Issues, https://github.com/DigitalKin-ai/digitalkin/issues
440
- Keywords: digitalkin,kin,agent,gprc,sdk
440
+ Keywords: agent,digitalkin,gprc,kin,sdk
441
441
  Classifier: Development Status :: 3 - Alpha
442
442
  Classifier: Intended Audience :: Developers
443
+ Classifier: License :: Other/Proprietary License
443
444
  Classifier: Operating System :: OS Independent
444
- Classifier: Topic :: Software Development :: Libraries
445
- Classifier: Programming Language :: Python
445
+ Classifier: Programming Language :: Python :: 3 :: Only
446
446
  Classifier: Programming Language :: Python :: 3.10
447
447
  Classifier: Programming Language :: Python :: 3.11
448
448
  Classifier: Programming Language :: Python :: 3.12
449
449
  Classifier: Programming Language :: Python :: 3.13
450
- Classifier: Programming Language :: Python :: 3 :: Only
451
- Classifier: License :: Other/Proprietary License
450
+ Classifier: Programming Language :: Python
451
+ Classifier: Topic :: Software Development :: Libraries
452
452
  Requires-Python: >=3.10
453
453
  Description-Content-Type: text/markdown
454
454
  License-File: LICENSE
@@ -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=dZgyJRHQFh_03su8ZElZY21agbb3n1gwA2QNWlIpunk,196
10
+ digitalkin/__version__.py,sha256=RHumdYZFrCYmC-fgDaLplg-14r7IrUPHKS70yI19O3w,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
@@ -50,14 +50,14 @@ digitalkin/models/core/task_monitor.py,sha256=CW-jydSgXMV464W0pqfar0HpgqlSxqdujm
50
50
  digitalkin/models/grpc_servers/__init__.py,sha256=0tA71nPSXgRrh9DoLvx-TSwZXdYIRUEItoadpTL1cTo,42
51
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
- digitalkin/models/module/__init__.py,sha256=XlFlLGmLUYPV4ZOgBxfGclq9wupGDXNUyWB4EB6iTXA,909
53
+ digitalkin/models/module/__init__.py,sha256=YDOsaX-4fYaZR6Cs3ksTr6pa0LSzo7lvSzWftLZJuwU,913
54
54
  digitalkin/models/module/base_types.py,sha256=oIylVNqo0idTFj4dRgCt7P19daNZ-AlvgCPpL9TJvto,1850
55
55
  digitalkin/models/module/module.py,sha256=k0W8vfJJFth8XdDzkHm32SyTuSf3h2qF0hSrxAfGF1s,956
56
56
  digitalkin/models/module/module_context.py,sha256=kwaAobsA82Du6L0XH9Is9u6Qj1rEjhYqVk00FonMaw4,12087
57
57
  digitalkin/models/module/module_types.py,sha256=C9azCNBk76xMa-Mww8_6AiwQR8MLAsEyUOvBYxytovI,739
58
58
  digitalkin/models/module/setup_types.py,sha256=8xEI6DvCYBHSOsuoeuZjtBL5rPsR_7DwWFxQnn2bo3c,19249
59
59
  digitalkin/models/module/tool_cache.py,sha256=xAMSyY73aduYGPz6C54g0YMAa2OnXPN6QRS-W4TK_js,6568
60
- digitalkin/models/module/tool_reference.py,sha256=rdkke5ydAgXcFfu34yxiHyaiRGcclnNGwPJK-01B2t8,3829
60
+ digitalkin/models/module/tool_reference.py,sha256=DjumRWlH18SzJLrGlsdsY1opDR7M1UfhI3Eyjj1iTu4,6176
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
@@ -122,8 +122,8 @@ digitalkin/utils/development_mode_action.py,sha256=2hznh0ajW_4ZTysfoc0Y49161f_PQ
122
122
  digitalkin/utils/dynamic_schema.py,sha256=y5csxjuqVHjWDpnTUzxbcUuI_wou9-ibRVHQlBs_btY,15275
123
123
  digitalkin/utils/llm_ready_schema.py,sha256=JjMug_lrQllqFoanaC091VgOqwAd-_YzcpqFlS7p778,2375
124
124
  digitalkin/utils/package_discover.py,sha256=sa6Zp5Kape1Zr4iYiNrnZxiHDnqM06ODk6yfWHom53w,13465
125
- digitalkin/utils/schema_splitter.py,sha256=6PeDrEBGEFyVEPgzGnwcCZuwxLobThmuPwJhGlRpU_0,11137
126
- digitalkin-0.3.2.dev22.dist-info/licenses/LICENSE,sha256=Ies4HFv2r2hzDRakJYxk3Y60uDFLiG-orIgeTpstnIo,20327
125
+ digitalkin/utils/schema_splitter.py,sha256=f1RGzs0wSRPn8oydO9Ojo8mYTF4TFDkRFeGUt5jbPt4,11132
126
+ digitalkin-0.3.2.dev23.dist-info/licenses/LICENSE,sha256=Ies4HFv2r2hzDRakJYxk3Y60uDFLiG-orIgeTpstnIo,20327
127
127
  modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
128
128
  modules/archetype_with_tools_module.py,sha256=kJkVhAFWG0aDDqzupOXOnV3l8j3z5bEdWos_6Z9rUP8,7303
129
129
  modules/cpu_intensive_module.py,sha256=GZlirQDZdYuXrI46sv1q4RNAHZjL4EptHVQTvgK9zz8,8363
@@ -138,7 +138,7 @@ monitoring/digitalkin_observability/prometheus.py,sha256=gDmM9ySaVwPAe7Yg84pLxmE
138
138
  monitoring/tests/test_metrics.py,sha256=ugnYfAwqBPO6zA8z4afKTlyBWECTivacYSN-URQCn2E,5856
139
139
  services/filesystem_module.py,sha256=U4dgqtuDadaXz8PJ1d_uQ_1EPncBqudAQCLUICF9yL4,7421
140
140
  services/storage_module.py,sha256=Wz2MzLvqs2D_bnBBgtnujYcAKK2V2KFMk8K21RoepSE,6972
141
- digitalkin-0.3.2.dev22.dist-info/METADATA,sha256=6Zn0jPPta8ZRH7ohcui_18g4PsaoCBO6bSi59U4kg9o,29725
142
- digitalkin-0.3.2.dev22.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
143
- digitalkin-0.3.2.dev22.dist-info/top_level.txt,sha256=AYVIesKrO0jnedQ-Muog9JBehG81WeTCNeOFoJgwsgE,51
144
- digitalkin-0.3.2.dev22.dist-info/RECORD,,
141
+ digitalkin-0.3.2.dev23.dist-info/METADATA,sha256=GpeeavGsy23lR_dj41wBw2nXaLUD8Jhph0dIB1lhu-U,29725
142
+ digitalkin-0.3.2.dev23.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
143
+ digitalkin-0.3.2.dev23.dist-info/top_level.txt,sha256=AYVIesKrO0jnedQ-Muog9JBehG81WeTCNeOFoJgwsgE,51
144
+ digitalkin-0.3.2.dev23.dist-info/RECORD,,