omnibase_infra 0.2.1__py3-none-any.whl → 0.2.3__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.
- omnibase_infra/__init__.py +1 -1
- omnibase_infra/adapters/adapter_onex_tool_execution.py +451 -0
- omnibase_infra/capabilities/__init__.py +15 -0
- omnibase_infra/capabilities/capability_inference_rules.py +211 -0
- omnibase_infra/capabilities/contract_capability_extractor.py +221 -0
- omnibase_infra/capabilities/intent_type_extractor.py +160 -0
- omnibase_infra/cli/commands.py +1 -1
- omnibase_infra/configs/widget_mapping.yaml +176 -0
- omnibase_infra/contracts/handlers/filesystem/handler_contract.yaml +5 -2
- omnibase_infra/contracts/handlers/mcp/handler_contract.yaml +5 -2
- omnibase_infra/enums/__init__.py +6 -0
- omnibase_infra/enums/enum_handler_error_type.py +10 -0
- omnibase_infra/enums/enum_handler_source_mode.py +72 -0
- omnibase_infra/enums/enum_kafka_acks.py +99 -0
- omnibase_infra/errors/error_compute_registry.py +4 -1
- omnibase_infra/errors/error_event_bus_registry.py +4 -1
- omnibase_infra/errors/error_infra.py +3 -1
- omnibase_infra/errors/error_policy_registry.py +4 -1
- omnibase_infra/event_bus/event_bus_kafka.py +1 -1
- omnibase_infra/event_bus/models/config/model_kafka_event_bus_config.py +59 -10
- omnibase_infra/handlers/__init__.py +8 -1
- omnibase_infra/handlers/handler_consul.py +7 -1
- omnibase_infra/handlers/handler_db.py +10 -3
- omnibase_infra/handlers/handler_graph.py +10 -5
- omnibase_infra/handlers/handler_http.py +8 -2
- omnibase_infra/handlers/handler_intent.py +387 -0
- omnibase_infra/handlers/handler_mcp.py +745 -63
- omnibase_infra/handlers/handler_vault.py +11 -5
- omnibase_infra/handlers/mixins/mixin_consul_kv.py +4 -3
- omnibase_infra/handlers/mixins/mixin_consul_service.py +2 -1
- omnibase_infra/handlers/registration_storage/handler_registration_storage_postgres.py +7 -0
- omnibase_infra/handlers/service_discovery/handler_service_discovery_consul.py +308 -4
- omnibase_infra/handlers/service_discovery/models/model_service_info.py +10 -0
- omnibase_infra/mixins/mixin_async_circuit_breaker.py +3 -2
- omnibase_infra/mixins/mixin_node_introspection.py +42 -7
- omnibase_infra/mixins/mixin_retry_execution.py +1 -1
- omnibase_infra/models/discovery/model_introspection_config.py +11 -0
- omnibase_infra/models/handlers/__init__.py +48 -5
- omnibase_infra/models/handlers/model_bootstrap_handler_descriptor.py +162 -0
- omnibase_infra/models/handlers/model_contract_discovery_result.py +6 -4
- omnibase_infra/models/handlers/model_handler_descriptor.py +15 -0
- omnibase_infra/models/handlers/model_handler_source_config.py +220 -0
- omnibase_infra/models/mcp/__init__.py +15 -0
- omnibase_infra/models/mcp/model_mcp_contract_config.py +80 -0
- omnibase_infra/models/mcp/model_mcp_server_config.py +67 -0
- omnibase_infra/models/mcp/model_mcp_tool_definition.py +73 -0
- omnibase_infra/models/mcp/model_mcp_tool_parameter.py +35 -0
- omnibase_infra/models/registration/model_node_capabilities.py +11 -0
- omnibase_infra/models/registration/model_node_introspection_event.py +9 -0
- omnibase_infra/models/runtime/model_handler_contract.py +25 -9
- omnibase_infra/models/runtime/model_loaded_handler.py +9 -0
- omnibase_infra/nodes/architecture_validator/contract_architecture_validator.yaml +0 -5
- omnibase_infra/nodes/architecture_validator/registry/registry_infra_architecture_validator.py +17 -10
- omnibase_infra/nodes/effects/contract.yaml +0 -5
- omnibase_infra/nodes/node_registration_orchestrator/contract.yaml +7 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_introspected.py +86 -1
- omnibase_infra/nodes/node_registration_orchestrator/introspection_event_router.py +3 -3
- omnibase_infra/nodes/node_registration_orchestrator/plugin.py +1 -1
- omnibase_infra/nodes/node_registration_orchestrator/registry/registry_infra_node_registration_orchestrator.py +9 -8
- omnibase_infra/nodes/node_registration_orchestrator/timeout_coordinator.py +4 -3
- omnibase_infra/nodes/node_registration_orchestrator/wiring.py +14 -13
- omnibase_infra/nodes/node_registration_storage_effect/contract.yaml +0 -5
- omnibase_infra/nodes/node_registration_storage_effect/node.py +4 -1
- omnibase_infra/nodes/node_registration_storage_effect/registry/registry_infra_registration_storage.py +47 -26
- omnibase_infra/nodes/node_registry_effect/contract.yaml +0 -5
- omnibase_infra/nodes/node_registry_effect/handlers/handler_partial_retry.py +2 -1
- omnibase_infra/nodes/node_service_discovery_effect/registry/registry_infra_service_discovery.py +28 -20
- omnibase_infra/plugins/examples/plugin_json_normalizer.py +2 -2
- omnibase_infra/plugins/examples/plugin_json_normalizer_error_handling.py +2 -2
- omnibase_infra/plugins/plugin_compute_base.py +16 -2
- omnibase_infra/protocols/__init__.py +2 -0
- omnibase_infra/protocols/protocol_container_aware.py +200 -0
- omnibase_infra/protocols/protocol_event_projector.py +1 -1
- omnibase_infra/runtime/__init__.py +90 -1
- omnibase_infra/runtime/binding_config_resolver.py +102 -37
- omnibase_infra/runtime/constants_notification.py +75 -0
- omnibase_infra/runtime/contract_handler_discovery.py +6 -1
- omnibase_infra/runtime/handler_bootstrap_source.py +507 -0
- omnibase_infra/runtime/handler_contract_config_loader.py +603 -0
- omnibase_infra/runtime/handler_contract_source.py +267 -186
- omnibase_infra/runtime/handler_identity.py +81 -0
- omnibase_infra/runtime/handler_plugin_loader.py +19 -2
- omnibase_infra/runtime/handler_registry.py +11 -3
- omnibase_infra/runtime/handler_source_resolver.py +326 -0
- omnibase_infra/runtime/mixin_semver_cache.py +25 -1
- omnibase_infra/runtime/mixins/__init__.py +7 -0
- omnibase_infra/runtime/mixins/mixin_projector_notification_publishing.py +566 -0
- omnibase_infra/runtime/mixins/mixin_projector_sql_operations.py +31 -10
- omnibase_infra/runtime/models/__init__.py +24 -0
- omnibase_infra/runtime/models/model_health_check_result.py +2 -1
- omnibase_infra/runtime/models/model_projector_notification_config.py +171 -0
- omnibase_infra/runtime/models/model_transition_notification_outbox_config.py +112 -0
- omnibase_infra/runtime/models/model_transition_notification_outbox_metrics.py +140 -0
- omnibase_infra/runtime/models/model_transition_notification_publisher_metrics.py +357 -0
- omnibase_infra/runtime/projector_plugin_loader.py +1 -1
- omnibase_infra/runtime/projector_shell.py +229 -1
- omnibase_infra/runtime/protocol_lifecycle_executor.py +6 -6
- omnibase_infra/runtime/protocols/__init__.py +10 -0
- omnibase_infra/runtime/registry/registry_protocol_binding.py +16 -15
- omnibase_infra/runtime/registry_contract_source.py +693 -0
- omnibase_infra/runtime/registry_policy.py +9 -326
- omnibase_infra/runtime/secret_resolver.py +4 -2
- omnibase_infra/runtime/service_kernel.py +11 -3
- omnibase_infra/runtime/service_message_dispatch_engine.py +4 -2
- omnibase_infra/runtime/service_runtime_host_process.py +589 -106
- omnibase_infra/runtime/transition_notification_outbox.py +1190 -0
- omnibase_infra/runtime/transition_notification_publisher.py +764 -0
- omnibase_infra/runtime/util_container_wiring.py +6 -5
- omnibase_infra/runtime/util_wiring.py +17 -4
- omnibase_infra/schemas/schema_transition_notification_outbox.sql +245 -0
- omnibase_infra/services/__init__.py +21 -0
- omnibase_infra/services/corpus_capture.py +7 -1
- omnibase_infra/services/mcp/__init__.py +31 -0
- omnibase_infra/services/mcp/mcp_server_lifecycle.py +449 -0
- omnibase_infra/services/mcp/service_mcp_tool_discovery.py +411 -0
- omnibase_infra/services/mcp/service_mcp_tool_registry.py +329 -0
- omnibase_infra/services/mcp/service_mcp_tool_sync.py +547 -0
- omnibase_infra/services/registry_api/__init__.py +40 -0
- omnibase_infra/services/registry_api/main.py +261 -0
- omnibase_infra/services/registry_api/models/__init__.py +66 -0
- omnibase_infra/services/registry_api/models/model_capability_widget_mapping.py +38 -0
- omnibase_infra/services/registry_api/models/model_pagination_info.py +48 -0
- omnibase_infra/services/registry_api/models/model_registry_discovery_response.py +73 -0
- omnibase_infra/services/registry_api/models/model_registry_health_response.py +49 -0
- omnibase_infra/services/registry_api/models/model_registry_instance_view.py +88 -0
- omnibase_infra/services/registry_api/models/model_registry_node_view.py +88 -0
- omnibase_infra/services/registry_api/models/model_registry_summary.py +60 -0
- omnibase_infra/services/registry_api/models/model_response_list_instances.py +43 -0
- omnibase_infra/services/registry_api/models/model_response_list_nodes.py +51 -0
- omnibase_infra/services/registry_api/models/model_warning.py +49 -0
- omnibase_infra/services/registry_api/models/model_widget_defaults.py +28 -0
- omnibase_infra/services/registry_api/models/model_widget_mapping.py +51 -0
- omnibase_infra/services/registry_api/routes.py +371 -0
- omnibase_infra/services/registry_api/service.py +837 -0
- omnibase_infra/services/service_capability_query.py +4 -4
- omnibase_infra/services/service_health.py +3 -2
- omnibase_infra/services/service_timeout_emitter.py +20 -3
- omnibase_infra/services/service_timeout_scanner.py +7 -3
- omnibase_infra/services/session/__init__.py +56 -0
- omnibase_infra/services/session/config_consumer.py +120 -0
- omnibase_infra/services/session/config_store.py +139 -0
- omnibase_infra/services/session/consumer.py +1007 -0
- omnibase_infra/services/session/protocol_session_aggregator.py +117 -0
- omnibase_infra/services/session/store.py +997 -0
- omnibase_infra/utils/__init__.py +19 -0
- omnibase_infra/utils/util_atomic_file.py +261 -0
- omnibase_infra/utils/util_db_transaction.py +239 -0
- omnibase_infra/utils/util_dsn_validation.py +1 -1
- omnibase_infra/utils/util_retry_optimistic.py +281 -0
- omnibase_infra/validation/__init__.py +3 -19
- omnibase_infra/validation/contracts/security.validation.yaml +114 -0
- omnibase_infra/validation/infra_validators.py +35 -24
- omnibase_infra/validation/validation_exemptions.yaml +140 -9
- omnibase_infra/validation/validator_chain_propagation.py +2 -2
- omnibase_infra/validation/validator_runtime_shape.py +1 -1
- omnibase_infra/validation/validator_security.py +473 -370
- {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.3.dist-info}/METADATA +3 -3
- {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.3.dist-info}/RECORD +161 -98
- {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.3.dist-info}/WHEEL +0 -0
- {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.3.dist-info}/entry_points.txt +0 -0
- {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -17,6 +17,12 @@ Related:
|
|
|
17
17
|
- NodeRegistrationStorageEffect: Effect node that uses these dependencies
|
|
18
18
|
- ProtocolRegistrationPersistence: Protocol for storage backends
|
|
19
19
|
- ModelONEXContainer: ONEX dependency injection container
|
|
20
|
+
|
|
21
|
+
Note:
|
|
22
|
+
This registry uses a module-level dict for handler storage because the
|
|
23
|
+
ServiceRegistry in omnibase_core v1.0 doesn't support dict-style access
|
|
24
|
+
or string-keyed multi-handler routing. The handlers are still validated
|
|
25
|
+
against the protocol but stored separately.
|
|
20
26
|
"""
|
|
21
27
|
|
|
22
28
|
from __future__ import annotations
|
|
@@ -31,6 +37,12 @@ if TYPE_CHECKING:
|
|
|
31
37
|
|
|
32
38
|
__all__ = ["RegistryInfraRegistrationStorage"]
|
|
33
39
|
|
|
40
|
+
# Module-level storage for handlers and metadata
|
|
41
|
+
# ServiceRegistry in v1.0 doesn't support dict-style access needed for
|
|
42
|
+
# multi-handler routing (e.g., "postgresql", "mock" handler types)
|
|
43
|
+
_HANDLER_STORAGE: dict[str, object] = {}
|
|
44
|
+
_PROTOCOL_METADATA: dict[str, dict[str, object]] = {}
|
|
45
|
+
|
|
34
46
|
|
|
35
47
|
class RegistryInfraRegistrationStorage:
|
|
36
48
|
"""Registry for registration storage node dependencies.
|
|
@@ -72,14 +84,18 @@ class RegistryInfraRegistrationStorage:
|
|
|
72
84
|
DEFAULT_HANDLER_TYPE = "postgresql"
|
|
73
85
|
|
|
74
86
|
@staticmethod
|
|
75
|
-
def register(
|
|
87
|
+
def register(_container: ModelONEXContainer) -> None:
|
|
76
88
|
"""Register registration storage dependencies with the container.
|
|
77
89
|
|
|
78
90
|
Registers the protocol key for later handler binding. This method
|
|
79
91
|
sets up the infrastructure but does not bind a specific handler.
|
|
80
92
|
|
|
81
93
|
Args:
|
|
82
|
-
|
|
94
|
+
_container: ONEX dependency injection container. Currently unused
|
|
95
|
+
because ServiceRegistry v1.0 doesn't support dict-style access
|
|
96
|
+
for multi-handler routing. The parameter is retained for API
|
|
97
|
+
consistency with other registry methods and future migration
|
|
98
|
+
when ServiceRegistry supports the required access patterns.
|
|
83
99
|
|
|
84
100
|
Example:
|
|
85
101
|
>>> from omnibase_core.models.container import ModelONEXContainer
|
|
@@ -88,20 +104,19 @@ class RegistryInfraRegistrationStorage:
|
|
|
88
104
|
"""
|
|
89
105
|
# Register protocol metadata for discovery
|
|
90
106
|
# Actual handler binding happens via register_handler()
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
107
|
+
# Note: Uses module-level storage since ServiceRegistry v1.0 doesn't
|
|
108
|
+
# support dict-style access for multi-handler routing
|
|
109
|
+
_PROTOCOL_METADATA[RegistryInfraRegistrationStorage.PROTOCOL_KEY] = {
|
|
110
|
+
"protocol": "ProtocolRegistrationPersistence",
|
|
111
|
+
"module": "omnibase_infra.nodes.node_registration_storage_effect.protocols",
|
|
112
|
+
"description": "Protocol for registration storage backends",
|
|
113
|
+
"pluggable": True,
|
|
114
|
+
"implementations": ["postgresql", "mock"],
|
|
115
|
+
}
|
|
101
116
|
|
|
102
117
|
@staticmethod
|
|
103
118
|
def register_handler(
|
|
104
|
-
|
|
119
|
+
_container: ModelONEXContainer,
|
|
105
120
|
handler: ProtocolRegistrationPersistence,
|
|
106
121
|
) -> None:
|
|
107
122
|
"""Register a specific storage handler with the container.
|
|
@@ -110,7 +125,11 @@ class RegistryInfraRegistrationStorage:
|
|
|
110
125
|
The handler must implement ProtocolRegistrationPersistence.
|
|
111
126
|
|
|
112
127
|
Args:
|
|
113
|
-
|
|
128
|
+
_container: ONEX dependency injection container. Currently unused
|
|
129
|
+
because ServiceRegistry v1.0 doesn't support dict-style access
|
|
130
|
+
for multi-handler routing. The parameter is retained for API
|
|
131
|
+
consistency and future migration when ServiceRegistry supports
|
|
132
|
+
the required access patterns.
|
|
114
133
|
handler: Handler implementation to register.
|
|
115
134
|
|
|
116
135
|
Raises:
|
|
@@ -120,7 +139,7 @@ class RegistryInfraRegistrationStorage:
|
|
|
120
139
|
>>> from omnibase_infra.handlers.registration_storage import (
|
|
121
140
|
... HandlerRegistrationStoragePostgres,
|
|
122
141
|
... )
|
|
123
|
-
>>> handler = HandlerRegistrationStoragePostgres(
|
|
142
|
+
>>> handler = HandlerRegistrationStoragePostgres(container, dsn="postgresql://...")
|
|
124
143
|
>>> RegistryInfraRegistrationStorage.register_handler(container, handler)
|
|
125
144
|
"""
|
|
126
145
|
# Import at runtime for isinstance check (protocol is @runtime_checkable)
|
|
@@ -143,32 +162,35 @@ class RegistryInfraRegistrationStorage:
|
|
|
143
162
|
f"got {type(handler).__name__}"
|
|
144
163
|
)
|
|
145
164
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
165
|
+
# Note: Uses module-level storage since ServiceRegistry v1.0 doesn't
|
|
166
|
+
# support dict-style access for multi-handler routing
|
|
149
167
|
handler_key = (
|
|
150
168
|
f"{RegistryInfraRegistrationStorage.PROTOCOL_KEY}.{handler.handler_type}"
|
|
151
169
|
)
|
|
152
|
-
|
|
170
|
+
_HANDLER_STORAGE[handler_key] = handler
|
|
153
171
|
|
|
154
172
|
# Also register as default if it matches the default type
|
|
155
173
|
if (
|
|
156
174
|
handler.handler_type
|
|
157
175
|
== RegistryInfraRegistrationStorage.DEFAULT_HANDLER_TYPE
|
|
158
176
|
):
|
|
159
|
-
|
|
177
|
+
_HANDLER_STORAGE[
|
|
160
178
|
RegistryInfraRegistrationStorage.PROTOCOL_KEY + ".default"
|
|
161
179
|
] = handler
|
|
162
180
|
|
|
163
181
|
@staticmethod
|
|
164
182
|
def get_handler(
|
|
165
|
-
|
|
183
|
+
_container: ModelONEXContainer,
|
|
166
184
|
handler_type: str | None = None,
|
|
167
185
|
) -> ProtocolRegistrationPersistence | None:
|
|
168
186
|
"""Retrieve a registered storage handler from the container.
|
|
169
187
|
|
|
170
188
|
Args:
|
|
171
|
-
|
|
189
|
+
_container: ONEX dependency injection container. Currently unused
|
|
190
|
+
because ServiceRegistry v1.0 doesn't support dict-style access
|
|
191
|
+
for multi-handler routing. The parameter is retained for API
|
|
192
|
+
consistency and future migration when ServiceRegistry supports
|
|
193
|
+
the required access patterns.
|
|
172
194
|
handler_type: Specific handler type to retrieve. If None, returns default.
|
|
173
195
|
|
|
174
196
|
Returns:
|
|
@@ -180,9 +202,8 @@ class RegistryInfraRegistrationStorage:
|
|
|
180
202
|
... handler_type="postgresql",
|
|
181
203
|
... )
|
|
182
204
|
"""
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
205
|
+
# Note: Uses module-level storage since ServiceRegistry v1.0 doesn't
|
|
206
|
+
# support dict-style access for multi-handler routing
|
|
186
207
|
if handler_type is not None:
|
|
187
208
|
handler_key = (
|
|
188
209
|
f"{RegistryInfraRegistrationStorage.PROTOCOL_KEY}.{handler_type}"
|
|
@@ -190,5 +211,5 @@ class RegistryInfraRegistrationStorage:
|
|
|
190
211
|
else:
|
|
191
212
|
handler_key = RegistryInfraRegistrationStorage.PROTOCOL_KEY + ".default"
|
|
192
213
|
|
|
193
|
-
result =
|
|
214
|
+
result = _HANDLER_STORAGE.get(handler_key)
|
|
194
215
|
return cast("ProtocolRegistrationPersistence | None", result)
|
|
@@ -41,6 +41,7 @@ import time
|
|
|
41
41
|
from typing import TYPE_CHECKING, Protocol, runtime_checkable
|
|
42
42
|
from uuid import UUID
|
|
43
43
|
|
|
44
|
+
from omnibase_core.models.primitives import ModelSemVer
|
|
44
45
|
from omnibase_infra.enums import EnumBackendType
|
|
45
46
|
from omnibase_infra.errors import (
|
|
46
47
|
InfraAuthenticationError,
|
|
@@ -80,7 +81,7 @@ class ProtocolPartialRetryRequest(Protocol):
|
|
|
80
81
|
|
|
81
82
|
node_id: UUID
|
|
82
83
|
node_type: EnumNodeKind
|
|
83
|
-
node_version:
|
|
84
|
+
node_version: ModelSemVer
|
|
84
85
|
target_backend: EnumBackendType
|
|
85
86
|
idempotency_key: str | None
|
|
86
87
|
service_name: str | None
|
omnibase_infra/nodes/node_service_discovery_effect/registry/registry_infra_service_discovery.py
CHANGED
|
@@ -40,6 +40,7 @@ Related:
|
|
|
40
40
|
|
|
41
41
|
from __future__ import annotations
|
|
42
42
|
|
|
43
|
+
import logging
|
|
43
44
|
from typing import TYPE_CHECKING
|
|
44
45
|
|
|
45
46
|
from omnibase_infra.errors import ProtocolConfigurationError
|
|
@@ -50,6 +51,8 @@ if TYPE_CHECKING:
|
|
|
50
51
|
ProtocolDiscoveryOperations,
|
|
51
52
|
)
|
|
52
53
|
|
|
54
|
+
logger = logging.getLogger(__name__)
|
|
55
|
+
|
|
53
56
|
|
|
54
57
|
class RegistryInfraServiceDiscovery:
|
|
55
58
|
"""Registry for service discovery node dependencies.
|
|
@@ -59,11 +62,11 @@ class RegistryInfraServiceDiscovery:
|
|
|
59
62
|
registration and explicit handler configuration.
|
|
60
63
|
|
|
61
64
|
API Pattern Note:
|
|
62
|
-
This registry uses ``container.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
This registry uses ``container.service_registry.register_instance()``
|
|
66
|
+
for protocol-based type-safe DI resolution. This differs from
|
|
67
|
+
RegistryInfraRegistrationStorage which uses a module-level dict for
|
|
68
|
+
multi-handler routing by type string (e.g., "postgresql", "mock"),
|
|
69
|
+
as ServiceRegistry does not support dict-style indexed access.
|
|
67
70
|
|
|
68
71
|
The different patterns serve different purposes:
|
|
69
72
|
- Protocol-based registration: Single handler per protocol type
|
|
@@ -83,7 +86,10 @@ class RegistryInfraServiceDiscovery:
|
|
|
83
86
|
RegistryInfraServiceDiscovery.register(container)
|
|
84
87
|
|
|
85
88
|
# Explicit handler registration
|
|
86
|
-
consul_handler = HandlerServiceDiscoveryConsul(
|
|
89
|
+
consul_handler = HandlerServiceDiscoveryConsul(
|
|
90
|
+
container=container,
|
|
91
|
+
consul_host="localhost",
|
|
92
|
+
)
|
|
87
93
|
RegistryInfraServiceDiscovery.register_with_handler(
|
|
88
94
|
container,
|
|
89
95
|
handler=consul_handler,
|
|
@@ -113,21 +119,18 @@ class RegistryInfraServiceDiscovery:
|
|
|
113
119
|
if container.service_registry is None:
|
|
114
120
|
return
|
|
115
121
|
|
|
116
|
-
#
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
container.register_factory(
|
|
125
|
-
ProtocolDiscoveryOperations,
|
|
126
|
-
RegistryInfraServiceDiscovery._create_handler_from_config,
|
|
122
|
+
# NOTE: Factory registration (register_factory) is not implemented in
|
|
123
|
+
# omnibase_core v1.0. This method provides no-op registration for forward
|
|
124
|
+
# compatibility. Use register_with_handler() to explicitly provide a
|
|
125
|
+
# pre-configured handler instance.
|
|
126
|
+
logger.debug(
|
|
127
|
+
"Service discovery factory registration skipped - "
|
|
128
|
+
"factory registration not implemented in v1.0. "
|
|
129
|
+
"Use register_with_handler() to register an explicit handler instance."
|
|
127
130
|
)
|
|
128
131
|
|
|
129
132
|
@staticmethod
|
|
130
|
-
def register_with_handler(
|
|
133
|
+
async def register_with_handler(
|
|
131
134
|
container: ModelONEXContainer,
|
|
132
135
|
handler: ProtocolDiscoveryOperations,
|
|
133
136
|
) -> None:
|
|
@@ -146,12 +149,13 @@ class RegistryInfraServiceDiscovery:
|
|
|
146
149
|
Example:
|
|
147
150
|
>>> container = ModelONEXContainer()
|
|
148
151
|
>>> handler = HandlerServiceDiscoveryConsul(config)
|
|
149
|
-
>>> RegistryInfraServiceDiscovery.register_with_handler(
|
|
152
|
+
>>> await RegistryInfraServiceDiscovery.register_with_handler(
|
|
150
153
|
... container,
|
|
151
154
|
... handler=handler,
|
|
152
155
|
... )
|
|
153
156
|
"""
|
|
154
157
|
# Import at runtime for isinstance check (protocol is @runtime_checkable)
|
|
158
|
+
from omnibase_core.enums import EnumInjectionScope
|
|
155
159
|
from omnibase_infra.nodes.node_service_discovery_effect.protocols import (
|
|
156
160
|
ProtocolDiscoveryOperations,
|
|
157
161
|
)
|
|
@@ -174,7 +178,11 @@ class RegistryInfraServiceDiscovery:
|
|
|
174
178
|
if container.service_registry is None:
|
|
175
179
|
return
|
|
176
180
|
|
|
177
|
-
container.register_instance(
|
|
181
|
+
await container.service_registry.register_instance(
|
|
182
|
+
interface=ProtocolDiscoveryOperations, # type: ignore[type-abstract]
|
|
183
|
+
instance=handler,
|
|
184
|
+
scope=EnumInjectionScope.GLOBAL,
|
|
185
|
+
)
|
|
178
186
|
|
|
179
187
|
@staticmethod
|
|
180
188
|
def _create_handler_from_config(
|
|
@@ -75,12 +75,12 @@ class PluginJsonNormalizer(PluginComputeBase):
|
|
|
75
75
|
effective_max_depth = self.MAX_RECURSION_DEPTH
|
|
76
76
|
|
|
77
77
|
try:
|
|
78
|
-
json_data = cast(object, input_data.get("json", {}))
|
|
78
|
+
json_data = cast("object", input_data.get("json", {}))
|
|
79
79
|
normalized: object = self._sort_keys_recursively(
|
|
80
80
|
json_data, _max_depth=effective_max_depth
|
|
81
81
|
)
|
|
82
82
|
output: JsonNormalizerOutput = {"normalized": normalized}
|
|
83
|
-
return cast(ModelPluginOutputData, output)
|
|
83
|
+
return cast("ModelPluginOutputData", output)
|
|
84
84
|
|
|
85
85
|
except RecursionError as e:
|
|
86
86
|
raise OnexError(
|
|
@@ -80,14 +80,14 @@ class PluginJsonNormalizerErrorHandling(PluginComputeBase):
|
|
|
80
80
|
|
|
81
81
|
try:
|
|
82
82
|
# Retrieve JSON data with safe default
|
|
83
|
-
json_data = cast(object, input_data.get("json", {}))
|
|
83
|
+
json_data = cast("object", input_data.get("json", {}))
|
|
84
84
|
|
|
85
85
|
# Perform pure deterministic computation
|
|
86
86
|
normalized = self._sort_keys_recursively(json_data)
|
|
87
87
|
|
|
88
88
|
# Return result with correlation_id for tracing
|
|
89
89
|
return cast(
|
|
90
|
-
ModelPluginOutputData,
|
|
90
|
+
"ModelPluginOutputData",
|
|
91
91
|
{
|
|
92
92
|
"normalized": normalized,
|
|
93
93
|
"correlation_id": correlation_id,
|
|
@@ -105,9 +105,15 @@ ONEX 4-Node Architecture Integration:
|
|
|
105
105
|
|
|
106
106
|
# Step 2: Integrate with NodeComputeService (I/O wrapper)
|
|
107
107
|
class ValidationNode(NodeComputeService):
|
|
108
|
-
def __init__(self, container: ONEXContainer):
|
|
108
|
+
def __init__(self, container: ONEXContainer, plugin: ProtocolPluginCompute):
|
|
109
109
|
super().__init__(container)
|
|
110
|
-
|
|
110
|
+
# Plugin is injected via constructor (sync-friendly)
|
|
111
|
+
# Resolution from container happens at initialization time:
|
|
112
|
+
# plugin = await container.service_registry.resolve_service(
|
|
113
|
+
# ProtocolPluginCompute
|
|
114
|
+
# )
|
|
115
|
+
# node = ValidationNode(container, plugin)
|
|
116
|
+
self.plugin = plugin
|
|
111
117
|
|
|
112
118
|
async def execute(self, input_model: ModelInput) -> ModelOutput:
|
|
113
119
|
# Node handles I/O and state management
|
|
@@ -119,6 +125,14 @@ ONEX 4-Node Architecture Integration:
|
|
|
119
125
|
|
|
120
126
|
# Node handles output persistence (if needed)
|
|
121
127
|
return ModelOutput(**result)
|
|
128
|
+
|
|
129
|
+
# Complete initialization example:
|
|
130
|
+
async def create_validation_node(container: ONEXContainer) -> ValidationNode:
|
|
131
|
+
'''Factory function for creating ValidationNode with resolved plugin.'''
|
|
132
|
+
plugin = await container.service_registry.resolve_service(
|
|
133
|
+
ProtocolPluginCompute
|
|
134
|
+
)
|
|
135
|
+
return ValidationNode(container, plugin)
|
|
122
136
|
```
|
|
123
137
|
|
|
124
138
|
When to Use Plugin vs Direct Node Implementation:
|
|
@@ -62,6 +62,7 @@ from omnibase_infra.protocols.protocol_capability_projection import (
|
|
|
62
62
|
ProtocolCapabilityProjection,
|
|
63
63
|
)
|
|
64
64
|
from omnibase_infra.protocols.protocol_capability_query import ProtocolCapabilityQuery
|
|
65
|
+
from omnibase_infra.protocols.protocol_container_aware import ProtocolContainerAware
|
|
65
66
|
from omnibase_infra.protocols.protocol_event_bus_like import ProtocolEventBusLike
|
|
66
67
|
from omnibase_infra.protocols.protocol_event_projector import ProtocolEventProjector
|
|
67
68
|
from omnibase_infra.protocols.protocol_idempotency_store import (
|
|
@@ -88,6 +89,7 @@ __all__: list[str] = [
|
|
|
88
89
|
"ProtocolCapabilityQuery",
|
|
89
90
|
"ProtocolEventBusLike",
|
|
90
91
|
"ProtocolEventProjector",
|
|
92
|
+
"ProtocolContainerAware",
|
|
91
93
|
"ProtocolIdempotencyStore",
|
|
92
94
|
"ProtocolMessageDispatcher",
|
|
93
95
|
"ProtocolMessageTypeRegistry",
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2025 OmniNode Team
|
|
3
|
+
"""Protocol extension for Infrastructure Handlers with Container DI.
|
|
4
|
+
|
|
5
|
+
This module defines the ProtocolContainerAware interface, which extends the base
|
|
6
|
+
ProtocolHandler from omnibase_spi to add container-based dependency injection
|
|
7
|
+
requirements. All infrastructure handlers in omnibase_infra must implement this
|
|
8
|
+
extended protocol.
|
|
9
|
+
|
|
10
|
+
Why This Protocol Exists:
|
|
11
|
+
The base ProtocolHandler in omnibase_spi is intentionally minimal and doesn't
|
|
12
|
+
mandate a specific constructor signature. This keeps the SPI layer decoupled
|
|
13
|
+
from implementation details.
|
|
14
|
+
|
|
15
|
+
However, omnibase_infra handlers require ModelONEXContainer for:
|
|
16
|
+
- Dependency injection of shared services (connection pools, clients)
|
|
17
|
+
- Configuration access without global state
|
|
18
|
+
- Testability through container mocking
|
|
19
|
+
|
|
20
|
+
This protocol adds the __init__ signature requirement while inheriting all
|
|
21
|
+
method requirements from the base protocol.
|
|
22
|
+
|
|
23
|
+
Protocol Hierarchy:
|
|
24
|
+
omnibase_spi.ProtocolHandler (base)
|
|
25
|
+
- handler_type property
|
|
26
|
+
- initialize()
|
|
27
|
+
- shutdown()
|
|
28
|
+
- execute()
|
|
29
|
+
- describe()
|
|
30
|
+
- health_check()
|
|
31
|
+
|
|
32
|
+
omnibase_infra.ProtocolContainerAware (extension)
|
|
33
|
+
- All methods from ProtocolHandler
|
|
34
|
+
- __init__(container: ModelONEXContainer) requirement
|
|
35
|
+
|
|
36
|
+
Usage:
|
|
37
|
+
Infrastructure handlers should implement this extended protocol:
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from omnibase_core.container import ModelONEXContainer
|
|
41
|
+
from omnibase_infra.protocols import ProtocolContainerAware
|
|
42
|
+
|
|
43
|
+
class HandlerDatabase:
|
|
44
|
+
'''Database handler implementing the infra protocol.'''
|
|
45
|
+
|
|
46
|
+
def __init__(self, container: ModelONEXContainer) -> None:
|
|
47
|
+
self._container = container
|
|
48
|
+
# Access shared resources via container
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def handler_type(self) -> str:
|
|
52
|
+
return "db"
|
|
53
|
+
|
|
54
|
+
# ... implement remaining protocol methods ...
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The RuntimeHostProcess uses this protocol for type-safe handler instantiation:
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
handler_cls: type[ProtocolContainerAware] = handler_registry.get(handler_type)
|
|
61
|
+
handler_instance = handler_cls(container=container) # Type-safe
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Thread Safety:
|
|
65
|
+
Handler implementations must be thread-safe. The container provides access
|
|
66
|
+
to shared resources that may be used concurrently.
|
|
67
|
+
|
|
68
|
+
See Also:
|
|
69
|
+
- omnibase_spi.protocols.handlers.protocol_handler.ProtocolHandler
|
|
70
|
+
- omnibase_core.container.ModelONEXContainer
|
|
71
|
+
- CLAUDE.md section "Container-Based Dependency Injection"
|
|
72
|
+
- PR #186: Container DI refactoring for handlers
|
|
73
|
+
|
|
74
|
+
.. versionadded:: 0.7.1
|
|
75
|
+
Created as part of OMN-1434 container DI standardization.
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
from __future__ import annotations
|
|
79
|
+
|
|
80
|
+
from typing import TYPE_CHECKING, Protocol, runtime_checkable
|
|
81
|
+
|
|
82
|
+
from omnibase_spi.protocols.handlers.protocol_handler import (
|
|
83
|
+
ProtocolHandler as ProtocolHandlerBase,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
if TYPE_CHECKING:
|
|
87
|
+
from omnibase_core.container import ModelONEXContainer
|
|
88
|
+
|
|
89
|
+
__all__ = [
|
|
90
|
+
"ProtocolContainerAware",
|
|
91
|
+
]
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@runtime_checkable
|
|
95
|
+
class ProtocolContainerAware(ProtocolHandlerBase, Protocol):
|
|
96
|
+
"""Extended protocol for infrastructure handlers with container DI.
|
|
97
|
+
|
|
98
|
+
This protocol extends the base ProtocolHandler from omnibase_spi to require
|
|
99
|
+
a constructor that accepts ModelONEXContainer for dependency injection.
|
|
100
|
+
|
|
101
|
+
All infrastructure handlers in omnibase_infra must implement this protocol.
|
|
102
|
+
The container provides access to:
|
|
103
|
+
- Database connection pools
|
|
104
|
+
- HTTP clients
|
|
105
|
+
- Service discovery clients
|
|
106
|
+
- Configuration values
|
|
107
|
+
- Logging context
|
|
108
|
+
|
|
109
|
+
Methods inherited from ProtocolHandler:
|
|
110
|
+
handler_type: Property returning the handler type identifier.
|
|
111
|
+
initialize: Initialize clients and connection pools.
|
|
112
|
+
shutdown: Release resources and close connections.
|
|
113
|
+
execute: Execute protocol-specific operations.
|
|
114
|
+
describe: Return handler metadata and capabilities.
|
|
115
|
+
health_check: Check handler health and connectivity.
|
|
116
|
+
|
|
117
|
+
Constructor Requirement (added by this protocol):
|
|
118
|
+
__init__: Must accept container: ModelONEXContainer as first positional argument.
|
|
119
|
+
|
|
120
|
+
Example:
|
|
121
|
+
```python
|
|
122
|
+
from omnibase_core.container import ModelONEXContainer
|
|
123
|
+
|
|
124
|
+
class HandlerConsul:
|
|
125
|
+
def __init__(self, container: ModelONEXContainer) -> None:
|
|
126
|
+
self._container = container
|
|
127
|
+
self._consul_url = container.config.get("consul_url")
|
|
128
|
+
|
|
129
|
+
@property
|
|
130
|
+
def handler_type(self) -> str:
|
|
131
|
+
return "consul"
|
|
132
|
+
|
|
133
|
+
async def initialize(self, config):
|
|
134
|
+
# Use container for shared resources
|
|
135
|
+
...
|
|
136
|
+
|
|
137
|
+
# ... implement remaining methods ...
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Protocol Verification:
|
|
141
|
+
Per ONEX conventions, verify protocol compliance via duck typing:
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
handler_cls = handler_registry.get("http")
|
|
145
|
+
|
|
146
|
+
# Verify constructor signature accepts container
|
|
147
|
+
import inspect
|
|
148
|
+
sig = inspect.signature(handler_cls.__init__)
|
|
149
|
+
params = list(sig.parameters.keys())
|
|
150
|
+
assert "container" in params or len(params) > 1 # self + container
|
|
151
|
+
|
|
152
|
+
# Verify protocol methods exist
|
|
153
|
+
assert hasattr(handler_cls, "handler_type")
|
|
154
|
+
assert hasattr(handler_cls, "initialize") and callable(getattr(handler_cls, "initialize"))
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Note:
|
|
158
|
+
Method bodies in this Protocol use ``...`` (Ellipsis) rather than
|
|
159
|
+
``raise NotImplementedError()``. This is the standard Python convention
|
|
160
|
+
for ``typing.Protocol`` classes per PEP 544.
|
|
161
|
+
"""
|
|
162
|
+
|
|
163
|
+
def __init__(self, container: ModelONEXContainer) -> None:
|
|
164
|
+
"""Initialize the handler with a dependency injection container.
|
|
165
|
+
|
|
166
|
+
All infrastructure handlers receive their dependencies through the
|
|
167
|
+
container rather than as individual constructor arguments. This enables:
|
|
168
|
+
|
|
169
|
+
- Consistent initialization across all handlers
|
|
170
|
+
- Easy testing through container mocking
|
|
171
|
+
- Runtime configuration without code changes
|
|
172
|
+
- Shared resource management (connection pools, clients)
|
|
173
|
+
|
|
174
|
+
Args:
|
|
175
|
+
container: ONEX dependency injection container providing access to:
|
|
176
|
+
- Configuration values (container.config)
|
|
177
|
+
- Shared services (database pools, HTTP clients)
|
|
178
|
+
- Logging context
|
|
179
|
+
- Runtime metadata
|
|
180
|
+
|
|
181
|
+
Note:
|
|
182
|
+
Handlers should store the container reference and access dependencies
|
|
183
|
+
lazily when needed, rather than extracting all values in __init__.
|
|
184
|
+
This improves startup time and allows for late-bound configuration.
|
|
185
|
+
|
|
186
|
+
Example:
|
|
187
|
+
```python
|
|
188
|
+
def __init__(self, container: ModelONEXContainer) -> None:
|
|
189
|
+
self._container = container
|
|
190
|
+
self._client: httpx.AsyncClient | None = None # Lazy init
|
|
191
|
+
|
|
192
|
+
async def initialize(self, config):
|
|
193
|
+
# Create client during initialize(), not __init__()
|
|
194
|
+
self._client = httpx.AsyncClient(
|
|
195
|
+
base_url=self._container.config.get("base_url"),
|
|
196
|
+
timeout=config.get("timeout", 30.0),
|
|
197
|
+
)
|
|
198
|
+
```
|
|
199
|
+
"""
|
|
200
|
+
...
|
|
@@ -14,7 +14,7 @@ from typing import TYPE_CHECKING, Protocol, runtime_checkable
|
|
|
14
14
|
from uuid import UUID
|
|
15
15
|
|
|
16
16
|
if TYPE_CHECKING:
|
|
17
|
-
from omnibase_core.models.events import ModelEventEnvelope
|
|
17
|
+
from omnibase_core.models.events.model_event_envelope import ModelEventEnvelope
|
|
18
18
|
from omnibase_core.models.projectors import ModelProjectionResult
|
|
19
19
|
|
|
20
20
|
|