digitalkin 0.3.2.dev8__tar.gz → 0.3.2.dev11__tar.gz
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-0.3.2.dev8 → digitalkin-0.3.2.dev11}/PKG-INFO +1 -1
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/pyproject.toml +1 -1
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/__version__.py +1 -1
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/grpc_servers/utils/grpc_client_wrapper.py +2 -2
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/grpc_servers/models.py +91 -6
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/module/setup_types.py +23 -17
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/module/tool_reference.py +6 -6
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/modules/_base_module.py +11 -6
- digitalkin-0.3.2.dev11/src/digitalkin/utils/schema_splitter.py +207 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin.egg-info/PKG-INFO +1 -1
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin.egg-info/SOURCES.txt +2 -1
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/LICENSE +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/README.md +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/base_server/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/base_server/mock/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/base_server/mock/mock_pb2.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/base_server/mock/mock_pb2_grpc.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/base_server/server_async_insecure.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/base_server/server_async_secure.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/base_server/server_sync_insecure.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/base_server/server_sync_secure.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/modules/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/modules/archetype_with_tools_module.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/modules/cpu_intensive_module.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/modules/dynamic_setup_module.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/modules/minimal_llm_module.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/modules/text_transform_module.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/monitoring/digitalkin_observability/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/monitoring/digitalkin_observability/http_server.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/monitoring/digitalkin_observability/interceptors.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/monitoring/digitalkin_observability/metrics.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/monitoring/digitalkin_observability/prometheus.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/monitoring/tests/test_metrics.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/services/filesystem_module.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/services/storage_module.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/setup.cfg +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/core/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/core/common/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/core/common/factories.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/core/job_manager/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/core/job_manager/base_job_manager.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/core/job_manager/single_job_manager.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/core/job_manager/taskiq_broker.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/core/job_manager/taskiq_job_manager.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/core/task_manager/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/core/task_manager/base_task_manager.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/core/task_manager/local_task_manager.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/core/task_manager/remote_task_manager.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/core/task_manager/surrealdb_repository.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/core/task_manager/task_executor.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/core/task_manager/task_session.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/grpc_servers/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/grpc_servers/_base_server.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/grpc_servers/module_server.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/grpc_servers/module_servicer.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/grpc_servers/utils/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/grpc_servers/utils/exceptions.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/grpc_servers/utils/grpc_error_handler.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/grpc_servers/utils/utility_schema_extender.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/logger.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/mixins/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/mixins/base_mixin.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/mixins/callback_mixin.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/mixins/chat_history_mixin.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/mixins/cost_mixin.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/mixins/file_history_mixin.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/mixins/filesystem_mixin.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/mixins/logger_mixin.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/mixins/storage_mixin.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/core/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/core/job_manager_models.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/core/task_monitor.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/grpc_servers/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/grpc_servers/types.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/module/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/module/base_types.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/module/module.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/module/module_context.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/module/module_types.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/module/tool_cache.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/module/utility.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/services/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/services/cost.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/services/registry.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/services/storage.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/modules/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/modules/archetype_module.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/modules/tool_module.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/modules/trigger_handler.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/modules/triggers/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/modules/triggers/healthcheck_ping_trigger.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/modules/triggers/healthcheck_services_trigger.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/modules/triggers/healthcheck_status_trigger.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/py.typed +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/agent/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/agent/agent_strategy.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/agent/default_agent.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/base_strategy.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/communication/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/communication/communication_strategy.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/communication/default_communication.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/communication/grpc_communication.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/cost/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/cost/cost_strategy.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/cost/default_cost.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/cost/grpc_cost.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/filesystem/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/filesystem/default_filesystem.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/filesystem/filesystem_strategy.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/filesystem/grpc_filesystem.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/identity/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/identity/default_identity.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/identity/identity_strategy.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/registry/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/registry/default_registry.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/registry/exceptions.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/registry/grpc_registry.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/registry/registry_models.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/registry/registry_strategy.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/services_config.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/services_models.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/setup/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/setup/default_setup.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/setup/grpc_setup.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/setup/setup_strategy.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/snapshot/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/snapshot/default_snapshot.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/snapshot/snapshot_strategy.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/storage/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/storage/default_storage.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/storage/grpc_storage.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/storage/storage_strategy.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/user_profile/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/user_profile/default_user_profile.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/user_profile/grpc_user_profile.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/user_profile/user_profile_strategy.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/utils/__init__.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/utils/arg_parser.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/utils/development_mode_action.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/utils/dynamic_schema.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/utils/llm_ready_schema.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/utils/package_discover.py +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin.egg-info/dependency_links.txt +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin.egg-info/requires.txt +0 -0
- {digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin.egg-info/top_level.txt +0 -0
|
@@ -43,9 +43,9 @@ class GrpcClientWrapper:
|
|
|
43
43
|
private_key=private_key,
|
|
44
44
|
)
|
|
45
45
|
|
|
46
|
-
return grpc.secure_channel(config.address, channel_credentials, options=config.
|
|
46
|
+
return grpc.secure_channel(config.address, channel_credentials, options=config.grpc_options)
|
|
47
47
|
# Insecure channel
|
|
48
|
-
return grpc.insecure_channel(config.address, options=config.
|
|
48
|
+
return grpc.insecure_channel(config.address, options=config.grpc_options)
|
|
49
49
|
|
|
50
50
|
def exec_grpc_query(self, query_endpoint: str, request: Any) -> Any: # noqa: ANN401
|
|
51
51
|
"""Execute a gRPC query with from the query's rpc endpoint name.
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/grpc_servers/models.py
RENAMED
|
@@ -65,6 +65,42 @@ class ServerCredentials(BaseModel):
|
|
|
65
65
|
return v
|
|
66
66
|
|
|
67
67
|
|
|
68
|
+
class RetryPolicy(BaseModel):
|
|
69
|
+
"""gRPC retry policy configuration for resilient connections.
|
|
70
|
+
|
|
71
|
+
Attributes:
|
|
72
|
+
max_attempts: Maximum retry attempts including the original call
|
|
73
|
+
initial_backoff: Initial backoff duration (e.g., "0.1s")
|
|
74
|
+
max_backoff: Maximum backoff duration (e.g., "10s")
|
|
75
|
+
backoff_multiplier: Multiplier for exponential backoff
|
|
76
|
+
retryable_status_codes: gRPC status codes that trigger retry
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
max_attempts: int = Field(default=5, ge=1, le=10, description="Maximum retry attempts including the original call")
|
|
80
|
+
initial_backoff: str = Field(default="0.1s", description="Initial backoff duration (e.g., '0.1s')")
|
|
81
|
+
max_backoff: str = Field(default="10s", description="Maximum backoff duration (e.g., '10s')")
|
|
82
|
+
backoff_multiplier: float = Field(default=2.0, ge=1.0, description="Multiplier for exponential backoff")
|
|
83
|
+
retryable_status_codes: list[str] = Field(
|
|
84
|
+
default_factory=lambda: ["UNAVAILABLE", "RESOURCE_EXHAUSTED"],
|
|
85
|
+
description="gRPC status codes that trigger retry",
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
model_config = {"extra": "forbid", "frozen": True}
|
|
89
|
+
|
|
90
|
+
def to_service_config_json(self) -> str:
|
|
91
|
+
"""Serialize to gRPC service config JSON string.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
JSON string for grpc.service_config channel option.
|
|
95
|
+
"""
|
|
96
|
+
codes = "[" + ",".join(f'"{c}"' for c in self.retryable_status_codes) + "]"
|
|
97
|
+
return (
|
|
98
|
+
f'{{"methodConfig":[{{"name":[{{}}],"retryPolicy":{{"maxAttempts":{self.max_attempts},'
|
|
99
|
+
f'"initialBackoff":"{self.initial_backoff}","maxBackoff":"{self.max_backoff}",'
|
|
100
|
+
f'"backoffMultiplier":{self.backoff_multiplier},"retryableStatusCodes":{codes}}}}}]}}'
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
|
|
68
104
|
class ClientCredentials(BaseModel):
|
|
69
105
|
"""Model for client credentials in secure mode.
|
|
70
106
|
|
|
@@ -170,15 +206,47 @@ class ClientConfig(ChannelConfig):
|
|
|
170
206
|
security: Security mode (secure/insecure)
|
|
171
207
|
credentials: Client credentials for secure mode
|
|
172
208
|
channel_options: Additional channel options
|
|
209
|
+
retry_policy: Retry policy for failed RPCs
|
|
173
210
|
"""
|
|
174
211
|
|
|
175
212
|
credentials: ClientCredentials | None = Field(None, description="Client credentials for secure mode")
|
|
213
|
+
retry_policy: RetryPolicy = Field(default_factory=lambda: RetryPolicy(), description="Retry policy for failed RPCs") # noqa: PLW0108
|
|
176
214
|
channel_options: list[tuple[str, Any]] = Field(
|
|
177
215
|
default_factory=lambda: [
|
|
178
|
-
("grpc.max_receive_message_length", 100 * 1024 * 1024),
|
|
179
|
-
("grpc.max_send_message_length", 100 * 1024 * 1024),
|
|
216
|
+
("grpc.max_receive_message_length", 100 * 1024 * 1024),
|
|
217
|
+
("grpc.max_send_message_length", 100 * 1024 * 1024),
|
|
218
|
+
# === DNS Re-resolution (Critical for Container Environments) ===
|
|
219
|
+
# Minimum milliseconds between DNS re-resolution attempts (500 ms)
|
|
220
|
+
# When connection fails, gRPC will re-query DNS after this interval
|
|
221
|
+
# Solves: Container restarts with new IPs causing "No route to host"
|
|
222
|
+
("grpc.dns_min_time_between_resolutions_ms", 500),
|
|
223
|
+
# Initial delay before first reconnection attempt (1 second)
|
|
224
|
+
("grpc.initial_reconnect_backoff_ms", 1000),
|
|
225
|
+
# Maximum delay between reconnection attempts (10 seconds)
|
|
226
|
+
# Prevents overwhelming the network during extended outages
|
|
227
|
+
("grpc.max_reconnect_backoff_ms", 10000),
|
|
228
|
+
# Minimum delay between reconnection attempts (500ms)
|
|
229
|
+
# Ensures rapid recovery for brief network glitches
|
|
230
|
+
("grpc.min_reconnect_backoff_ms", 500),
|
|
231
|
+
# === Keepalive Settings (Detect Dead Connections) ===
|
|
232
|
+
# Send keepalive ping every 60 seconds when connection is idle
|
|
233
|
+
# Proactively detects dead connections before RPC calls fail
|
|
234
|
+
("grpc.keepalive_time_ms", 60000),
|
|
235
|
+
# Wait 20 seconds for keepalive response before declaring connection dead
|
|
236
|
+
# Triggers reconnection (with DNS re-resolution) if pong not received
|
|
237
|
+
("grpc.keepalive_timeout_ms", 20000),
|
|
238
|
+
# Send keepalive pings even when no RPCs are in flight
|
|
239
|
+
# Essential for long-lived connections that may sit idle
|
|
240
|
+
("grpc.keepalive_permit_without_calls", True),
|
|
241
|
+
# Minimum interval between HTTP/2 pings (30 seconds)
|
|
242
|
+
# Must be >= server's grpc.http2.min_ping_interval_without_data_ms (10s)
|
|
243
|
+
("grpc.http2.min_time_between_pings_ms", 30000),
|
|
244
|
+
# === Retry Configuration ===
|
|
245
|
+
# Enable automatic retry for failed RPCs (1 = enabled)
|
|
246
|
+
# Works with retryable status codes: UNAVAILABLE, RESOURCE_EXHAUSTED
|
|
247
|
+
("grpc.enable_retries", 1),
|
|
180
248
|
],
|
|
181
|
-
description="
|
|
249
|
+
description="Resilient gRPC channel options with DNS re-resolution, keepalive, and retries",
|
|
182
250
|
)
|
|
183
251
|
|
|
184
252
|
@field_validator("credentials")
|
|
@@ -204,6 +272,15 @@ class ClientConfig(ChannelConfig):
|
|
|
204
272
|
raise ConfigurationError(msg)
|
|
205
273
|
return v
|
|
206
274
|
|
|
275
|
+
@property
|
|
276
|
+
def grpc_options(self) -> list[tuple[str, Any]]:
|
|
277
|
+
"""Get channel options with retry policy service config.
|
|
278
|
+
|
|
279
|
+
Returns:
|
|
280
|
+
Full list of gRPC channel options.
|
|
281
|
+
"""
|
|
282
|
+
return [*self.channel_options, ("grpc.service_config", self.retry_policy.to_service_config_json())]
|
|
283
|
+
|
|
207
284
|
|
|
208
285
|
class ServerConfig(ChannelConfig):
|
|
209
286
|
"""Base configuration for gRPC servers.
|
|
@@ -223,10 +300,18 @@ class ServerConfig(ChannelConfig):
|
|
|
223
300
|
credentials: ServerCredentials | None = Field(None, description="Server credentials for secure mode")
|
|
224
301
|
server_options: list[tuple[str, Any]] = Field(
|
|
225
302
|
default_factory=lambda: [
|
|
226
|
-
("grpc.max_receive_message_length", 100 * 1024 * 1024),
|
|
227
|
-
("grpc.max_send_message_length", 100 * 1024 * 1024),
|
|
303
|
+
("grpc.max_receive_message_length", 100 * 1024 * 1024),
|
|
304
|
+
("grpc.max_send_message_length", 100 * 1024 * 1024),
|
|
305
|
+
# === Keepalive Permission (Required for Client Keepalive) ===
|
|
306
|
+
# Allow clients to send keepalive pings without active RPCs
|
|
307
|
+
# Without this, server rejects client keepalives with GOAWAY
|
|
308
|
+
("grpc.keepalive_permit_without_calls", True),
|
|
309
|
+
# Minimum interval server allows between client pings (10 seconds)
|
|
310
|
+
# Prevents "too_many_pings" GOAWAY errors
|
|
311
|
+
# Must match or be less than client's http2.min_time_between_pings_ms
|
|
312
|
+
("grpc.http2.min_ping_interval_without_data_ms", 10000),
|
|
228
313
|
],
|
|
229
|
-
description="
|
|
314
|
+
description="gRPC server options with keepalive support",
|
|
230
315
|
)
|
|
231
316
|
enable_reflection: bool = Field(default=True, description="Enable reflection for the server")
|
|
232
317
|
enable_health_check: bool = Field(default=True, description="Enable health check service")
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/module/setup_types.py
RENAMED
|
@@ -140,10 +140,15 @@ class SetupModel(BaseModel, Generic[SetupModelT]):
|
|
|
140
140
|
|
|
141
141
|
clean_fields[name] = (current_annotation, current_field_info)
|
|
142
142
|
|
|
143
|
+
root_extra = cls.model_config.get("json_schema_extra", {})
|
|
144
|
+
|
|
143
145
|
m = create_model(
|
|
144
146
|
f"{cls.__name__}",
|
|
145
147
|
__base__=SetupModel,
|
|
146
|
-
__config__=ConfigDict(
|
|
148
|
+
__config__=ConfigDict(
|
|
149
|
+
arbitrary_types_allowed=True,
|
|
150
|
+
json_schema_extra=copy.deepcopy(root_extra) if isinstance(root_extra, dict) else root_extra,
|
|
151
|
+
),
|
|
147
152
|
**clean_fields,
|
|
148
153
|
)
|
|
149
154
|
|
|
@@ -280,10 +285,15 @@ class SetupModel(BaseModel, Generic[SetupModelT]):
|
|
|
280
285
|
if not has_changes:
|
|
281
286
|
return model_cls
|
|
282
287
|
|
|
288
|
+
root_extra = cls.model_config.get("json_schema_extra", {})
|
|
289
|
+
|
|
283
290
|
return create_model(
|
|
284
291
|
model_cls.__name__,
|
|
285
292
|
__base__=BaseModel,
|
|
286
|
-
__config__=ConfigDict(
|
|
293
|
+
__config__=ConfigDict(
|
|
294
|
+
arbitrary_types_allowed=True,
|
|
295
|
+
json_schema_extra=copy.deepcopy(root_extra) if isinstance(root_extra, dict) else root_extra,
|
|
296
|
+
),
|
|
287
297
|
**clean_fields,
|
|
288
298
|
)
|
|
289
299
|
|
|
@@ -437,7 +447,7 @@ class SetupModel(BaseModel, Generic[SetupModelT]):
|
|
|
437
447
|
logger.info("Tool cache built: %d entries", len(cache.entries))
|
|
438
448
|
return cache
|
|
439
449
|
|
|
440
|
-
def _build_tool_cache_recursive(self, model_instance: BaseModel, cache: ToolCache) -> None: # noqa: C901
|
|
450
|
+
def _build_tool_cache_recursive(self, model_instance: BaseModel, cache: ToolCache) -> None: # noqa: C901
|
|
441
451
|
"""Recursively build tool cache and populate companion fields.
|
|
442
452
|
|
|
443
453
|
Args:
|
|
@@ -447,13 +457,16 @@ class SetupModel(BaseModel, Generic[SetupModelT]):
|
|
|
447
457
|
for field_name, field_value in model_instance.__dict__.items():
|
|
448
458
|
if field_value is None:
|
|
449
459
|
continue
|
|
450
|
-
|
|
451
|
-
if isinstance(field_value, ToolReference) and field_value.module_info:
|
|
460
|
+
if isinstance(field_value, ToolReference):
|
|
452
461
|
cache_field_name = f"{field_name}_cache"
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
462
|
+
|
|
463
|
+
cached_info = getattr(model_instance, cache_field_name, None)
|
|
464
|
+
module_info = field_value.module_info or cached_info
|
|
465
|
+
if module_info:
|
|
466
|
+
if not cached_info:
|
|
467
|
+
setattr(model_instance, cache_field_name, module_info)
|
|
468
|
+
cache.add(module_info.module_id, module_info)
|
|
469
|
+
logger.debug("Added tool to cache: %s", module_info.module_id)
|
|
457
470
|
elif isinstance(field_value, BaseModel):
|
|
458
471
|
self._build_tool_cache_recursive(field_value, cache)
|
|
459
472
|
elif isinstance(field_value, list):
|
|
@@ -473,12 +486,5 @@ class SetupModel(BaseModel, Generic[SetupModelT]):
|
|
|
473
486
|
self._build_tool_cache_recursive(item, cache)
|
|
474
487
|
|
|
475
488
|
# Update companion field with resolved infos
|
|
476
|
-
if resolved_infos
|
|
489
|
+
if resolved_infos:
|
|
477
490
|
setattr(model_instance, cache_field_name, resolved_infos)
|
|
478
|
-
elif isinstance(field_value, dict):
|
|
479
|
-
for item in field_value.values():
|
|
480
|
-
if isinstance(item, ToolReference) and item.module_info:
|
|
481
|
-
cache.add(item.module_info.module_id, item.module_info)
|
|
482
|
-
logger.debug("Added tool to cache: %s", item.module_info.module_id)
|
|
483
|
-
elif isinstance(item, BaseModel):
|
|
484
|
-
self._build_tool_cache_recursive(item, cache)
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/module/tool_reference.py
RENAMED
|
@@ -20,9 +20,9 @@ class ToolReferenceConfig(BaseModel):
|
|
|
20
20
|
"""Tool selection configuration. The module_id serves as both identifier and cache key."""
|
|
21
21
|
|
|
22
22
|
mode: ToolSelectionMode = Field(default=ToolSelectionMode.FIXED)
|
|
23
|
-
module_id: str
|
|
24
|
-
tag: str
|
|
25
|
-
organization_id: str
|
|
23
|
+
module_id: str = Field(default="")
|
|
24
|
+
tag: str = Field(default="")
|
|
25
|
+
organization_id: str = Field(default="")
|
|
26
26
|
|
|
27
27
|
@model_validator(mode="after")
|
|
28
28
|
def validate_config(self) -> "ToolReferenceConfig":
|
|
@@ -50,7 +50,7 @@ class ToolReference(BaseModel):
|
|
|
50
50
|
_cached_info: ModuleInfo | None = PrivateAttr(default=None)
|
|
51
51
|
|
|
52
52
|
@property
|
|
53
|
-
def slug(self) -> str
|
|
53
|
+
def slug(self) -> str:
|
|
54
54
|
"""Cache key (same as module_id).
|
|
55
55
|
|
|
56
56
|
Returns:
|
|
@@ -59,11 +59,11 @@ class ToolReference(BaseModel):
|
|
|
59
59
|
return self.config.module_id
|
|
60
60
|
|
|
61
61
|
@property
|
|
62
|
-
def module_id(self) -> str
|
|
62
|
+
def module_id(self) -> str:
|
|
63
63
|
"""Module identifier.
|
|
64
64
|
|
|
65
65
|
Returns:
|
|
66
|
-
Module ID or
|
|
66
|
+
Module ID or empty string if not set.
|
|
67
67
|
"""
|
|
68
68
|
return self.config.module_id
|
|
69
69
|
|
|
@@ -22,8 +22,8 @@ from digitalkin.models.module.utility import EndOfStreamOutput, ModuleStartInfoO
|
|
|
22
22
|
from digitalkin.models.services.storage import BaseRole
|
|
23
23
|
from digitalkin.modules.trigger_handler import TriggerHandler
|
|
24
24
|
from digitalkin.services.services_config import ServicesConfig, ServicesStrategy
|
|
25
|
-
from digitalkin.utils.llm_ready_schema import llm_ready_schema
|
|
26
25
|
from digitalkin.utils.package_discover import ModuleDiscoverer
|
|
26
|
+
from digitalkin.utils.schema_splitter import SchemaSplitter
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
class BaseModule( # noqa: PLR0904
|
|
@@ -137,7 +137,8 @@ class BaseModule( # noqa: PLR0904
|
|
|
137
137
|
"""
|
|
138
138
|
if cls.secret_format is not None:
|
|
139
139
|
if llm_format:
|
|
140
|
-
|
|
140
|
+
result_json, result_ui = SchemaSplitter.split(cls.secret_format.model_json_schema())
|
|
141
|
+
return json.dumps({"json_schema": result_json, "ui_schema": result_ui}, indent=2)
|
|
141
142
|
return json.dumps(cls.secret_format.model_json_schema(), indent=2)
|
|
142
143
|
msg = f"{cls.__name__}' class does not define a 'secret_format'."
|
|
143
144
|
raise NotImplementedError(msg)
|
|
@@ -163,7 +164,8 @@ class BaseModule( # noqa: PLR0904
|
|
|
163
164
|
extended_model = UtilitySchemaExtender.create_extended_input_model(cls.input_format)
|
|
164
165
|
|
|
165
166
|
if llm_format:
|
|
166
|
-
|
|
167
|
+
result_json, result_ui = SchemaSplitter.split(extended_model.model_json_schema())
|
|
168
|
+
return json.dumps({"json_schema": result_json, "ui_schema": result_ui}, indent=2)
|
|
167
169
|
return json.dumps(extended_model.model_json_schema(), indent=2)
|
|
168
170
|
|
|
169
171
|
@classmethod
|
|
@@ -187,7 +189,8 @@ class BaseModule( # noqa: PLR0904
|
|
|
187
189
|
extended_model = UtilitySchemaExtender.create_extended_output_model(cls.output_format)
|
|
188
190
|
|
|
189
191
|
if llm_format:
|
|
190
|
-
|
|
192
|
+
result_json, result_ui = SchemaSplitter.split(extended_model.model_json_schema())
|
|
193
|
+
return json.dumps({"json_schema": result_json, "ui_schema": result_ui}, indent=2)
|
|
191
194
|
return json.dumps(extended_model.model_json_schema(), indent=2)
|
|
192
195
|
|
|
193
196
|
@classmethod
|
|
@@ -215,7 +218,8 @@ class BaseModule( # noqa: PLR0904
|
|
|
215
218
|
if cls.setup_format is not None:
|
|
216
219
|
setup_format = await cls.setup_format.get_clean_model(config_fields=True, hidden_fields=False, force=True)
|
|
217
220
|
if llm_format:
|
|
218
|
-
|
|
221
|
+
result_json, result_ui = SchemaSplitter.split(setup_format.model_json_schema())
|
|
222
|
+
return json.dumps({"json_schema": result_json, "ui_schema": result_ui}, indent=2)
|
|
219
223
|
return json.dumps(setup_format.model_json_schema(), indent=2)
|
|
220
224
|
msg = "'%s' class does not define an 'config_setup_format'."
|
|
221
225
|
raise NotImplementedError(msg)
|
|
@@ -244,7 +248,8 @@ class BaseModule( # noqa: PLR0904
|
|
|
244
248
|
if cls.setup_format is not None:
|
|
245
249
|
setup_format = await cls.setup_format.get_clean_model(config_fields=False, hidden_fields=True, force=True)
|
|
246
250
|
if llm_format:
|
|
247
|
-
|
|
251
|
+
result_json, result_ui = SchemaSplitter.split(setup_format.model_json_schema())
|
|
252
|
+
return json.dumps({"json_schema": result_json, "ui_schema": result_ui}, indent=2)
|
|
248
253
|
return json.dumps(setup_format.model_json_schema(), indent=2)
|
|
249
254
|
msg = "'%s' class does not define an 'setup_format'."
|
|
250
255
|
raise NotImplementedError(msg)
|
|
@@ -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
|
|
@@ -142,4 +142,5 @@ src/digitalkin/utils/arg_parser.py
|
|
|
142
142
|
src/digitalkin/utils/development_mode_action.py
|
|
143
143
|
src/digitalkin/utils/dynamic_schema.py
|
|
144
144
|
src/digitalkin/utils/llm_ready_schema.py
|
|
145
|
-
src/digitalkin/utils/package_discover.py
|
|
145
|
+
src/digitalkin/utils/package_discover.py
|
|
146
|
+
src/digitalkin/utils/schema_splitter.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/base_server/server_async_insecure.py
RENAMED
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/base_server/server_async_secure.py
RENAMED
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/base_server/server_sync_insecure.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/examples/modules/archetype_with_tools_module.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/core/job_manager/__init__.py
RENAMED
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/core/job_manager/base_job_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/core/job_manager/taskiq_broker.py
RENAMED
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/core/task_manager/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/core/task_manager/task_executor.py
RENAMED
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/core/task_manager/task_session.py
RENAMED
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/grpc_servers/_base_server.py
RENAMED
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/grpc_servers/module_server.py
RENAMED
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/grpc_servers/module_servicer.py
RENAMED
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/grpc_servers/utils/__init__.py
RENAMED
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/grpc_servers/utils/exceptions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/mixins/chat_history_mixin.py
RENAMED
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/mixins/file_history_mixin.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/core/job_manager_models.py
RENAMED
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/grpc_servers/__init__.py
RENAMED
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/grpc_servers/types.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/module/module_context.py
RENAMED
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/models/module/module_types.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/modules/triggers/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/agent/agent_strategy.py
RENAMED
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/agent/default_agent.py
RENAMED
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/communication/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/cost/cost_strategy.py
RENAMED
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/cost/default_cost.py
RENAMED
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/filesystem/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/identity/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/registry/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/registry/exceptions.py
RENAMED
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/registry/grpc_registry.py
RENAMED
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/registry/registry_models.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/setup/default_setup.py
RENAMED
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/setup/grpc_setup.py
RENAMED
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/setup/setup_strategy.py
RENAMED
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/snapshot/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/storage/__init__.py
RENAMED
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/storage/default_storage.py
RENAMED
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/storage/grpc_storage.py
RENAMED
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/storage/storage_strategy.py
RENAMED
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/services/user_profile/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin/utils/development_mode_action.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-0.3.2.dev8 → digitalkin-0.3.2.dev11}/src/digitalkin.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|