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
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2025 OmniNode Team
|
|
3
|
+
"""Handler Source Mode Enumeration for Handler Loading Strategy.
|
|
4
|
+
|
|
5
|
+
Defines the canonical source modes for handler loading in the ONEX runtime.
|
|
6
|
+
Each mode determines where handlers are discovered and loaded from, enabling
|
|
7
|
+
flexible deployment configurations and migration strategies.
|
|
8
|
+
|
|
9
|
+
Handler loading can operate in three modes:
|
|
10
|
+
- BOOTSTRAP: Only use hardcoded bootstrap handlers.
|
|
11
|
+
Uses the legacy hardcoded handler registry. No YAML contract
|
|
12
|
+
discovery. Useful for minimal deployments or testing.
|
|
13
|
+
- CONTRACT: Only use YAML contract-discovered handlers.
|
|
14
|
+
All handlers must be defined in contract.yaml files. No
|
|
15
|
+
hardcoded handlers are loaded. Enables fully declarative
|
|
16
|
+
handler configuration.
|
|
17
|
+
- HYBRID: Per-handler resolution with contract precedence.
|
|
18
|
+
When a handler identity matches both bootstrap and contract,
|
|
19
|
+
the contract-defined handler wins. Bootstrap handlers serve
|
|
20
|
+
as fallback for handlers not defined in contracts.
|
|
21
|
+
|
|
22
|
+
The HYBRID mode supports gradual migration from hardcoded to contract-based
|
|
23
|
+
handlers by allowing both sources to coexist with deterministic resolution.
|
|
24
|
+
|
|
25
|
+
See Also:
|
|
26
|
+
- EnumHandlerSourceType: Defines validation error source types (different purpose)
|
|
27
|
+
- HandlerPluginLoader: Uses this enum to determine loading strategy
|
|
28
|
+
- ModelRuntimeConfig: Configuration model that holds the source mode setting
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from enum import Enum
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class EnumHandlerSourceMode(str, Enum):
|
|
35
|
+
"""Handler source modes for handler loading strategy selection.
|
|
36
|
+
|
|
37
|
+
These represent the different strategies for discovering and loading
|
|
38
|
+
handlers at runtime. The mode determines whether handlers come from
|
|
39
|
+
hardcoded registries, YAML contracts, or a combination of both.
|
|
40
|
+
|
|
41
|
+
Attributes:
|
|
42
|
+
BOOTSTRAP: Only use hardcoded bootstrap handlers.
|
|
43
|
+
The runtime loads handlers from the legacy hardcoded registry only.
|
|
44
|
+
No YAML contract discovery is performed. Use cases:
|
|
45
|
+
- Minimal deployments without contract infrastructure
|
|
46
|
+
- Testing with known handler set
|
|
47
|
+
- Backwards compatibility during migration
|
|
48
|
+
- Environments where contract files are not available
|
|
49
|
+
CONTRACT: Only use YAML contract-discovered handlers.
|
|
50
|
+
All handlers must be defined in contract.yaml files. The hardcoded
|
|
51
|
+
bootstrap registry is ignored. Use cases:
|
|
52
|
+
- Fully declarative handler configuration
|
|
53
|
+
- Dynamic handler deployment via contracts
|
|
54
|
+
- Environments requiring audit trail of handler changes
|
|
55
|
+
- Production deployments with contract validation
|
|
56
|
+
HYBRID: Per-handler resolution with contract precedence.
|
|
57
|
+
Both bootstrap and contract sources are used. When a handler
|
|
58
|
+
identity (module + class) matches in both sources, the contract-
|
|
59
|
+
defined handler takes precedence. Bootstrap handlers serve as
|
|
60
|
+
fallback for handlers not defined in contracts. Use cases:
|
|
61
|
+
- Gradual migration from bootstrap to contract
|
|
62
|
+
- Core handlers in bootstrap, extensions in contracts
|
|
63
|
+
- Development environments with mixed configurations
|
|
64
|
+
- A/B testing of handler implementations
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
BOOTSTRAP = "bootstrap"
|
|
68
|
+
CONTRACT = "contract"
|
|
69
|
+
HYBRID = "hybrid"
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
__all__ = ["EnumHandlerSourceMode"]
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2025 OmniNode Team
|
|
3
|
+
"""Kafka producer acknowledgment configuration enumeration.
|
|
4
|
+
|
|
5
|
+
This module defines the acknowledgment policy enumeration for Kafka producers,
|
|
6
|
+
with a conversion method to produce aiokafka-compatible types.
|
|
7
|
+
|
|
8
|
+
The `acks` configuration controls how many partition replicas must acknowledge
|
|
9
|
+
receipt before the producer considers a request complete:
|
|
10
|
+
- ALL ("all"): Wait for all in-sync replicas to acknowledge (most durable)
|
|
11
|
+
- LEADER ("1"): Wait only for the leader to acknowledge (balanced)
|
|
12
|
+
- NONE ("0"): Don't wait for any acknowledgment (fastest, least durable)
|
|
13
|
+
- ALL_REPLICAS ("-1"): Explicit numeric form of ALL (equivalent to "all")
|
|
14
|
+
|
|
15
|
+
See Also:
|
|
16
|
+
- EventBusKafka: Uses this enum for producer configuration
|
|
17
|
+
- ModelKafkaEventBusConfig: Config model that stores the acks setting
|
|
18
|
+
- https://kafka.apache.org/documentation/#producerconfigs_acks
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
from enum import Enum
|
|
24
|
+
|
|
25
|
+
# Explicit mapping for aiokafka type conversion.
|
|
26
|
+
# Defined at module level because str-based enums don't support ClassVar attributes
|
|
27
|
+
# (attribute lookup on str enum members uses string indexing, not class attribute lookup).
|
|
28
|
+
_AIOKAFKA_MAP: dict[str, int | str] = {
|
|
29
|
+
"all": "all",
|
|
30
|
+
"0": 0,
|
|
31
|
+
"1": 1,
|
|
32
|
+
"-1": -1,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class EnumKafkaAcks(str, Enum):
|
|
37
|
+
"""Kafka producer acknowledgment policy.
|
|
38
|
+
|
|
39
|
+
Defines the acknowledgment behavior for Kafka producers. The aiokafka
|
|
40
|
+
library expects specific types for the `acks` parameter:
|
|
41
|
+
- "all" must be passed as a string
|
|
42
|
+
- Numeric values (0, 1, -1) must be passed as integers
|
|
43
|
+
|
|
44
|
+
Use the `to_aiokafka()` method to get the correctly-typed value for
|
|
45
|
+
passing to AIOKafkaProducer.
|
|
46
|
+
|
|
47
|
+
Attributes:
|
|
48
|
+
ALL: Wait for all in-sync replicas (string "all")
|
|
49
|
+
NONE: Fire and forget, no acknowledgment (string "0" -> int 0)
|
|
50
|
+
LEADER: Wait for leader acknowledgment only (string "1" -> int 1)
|
|
51
|
+
ALL_REPLICAS: Explicit numeric form of ALL (string "-1" -> int -1)
|
|
52
|
+
|
|
53
|
+
Note:
|
|
54
|
+
ALL ("all") and ALL_REPLICAS (-1) are semantically equivalent in Kafka.
|
|
55
|
+
ALL_REPLICAS is provided for explicit numeric configuration compatibility
|
|
56
|
+
when migrating from systems that use the numeric form.
|
|
57
|
+
|
|
58
|
+
Example:
|
|
59
|
+
>>> acks = EnumKafkaAcks.ALL
|
|
60
|
+
>>> acks.to_aiokafka()
|
|
61
|
+
'all'
|
|
62
|
+
>>> acks = EnumKafkaAcks.LEADER
|
|
63
|
+
>>> acks.to_aiokafka()
|
|
64
|
+
1
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
ALL = "all"
|
|
68
|
+
NONE = "0"
|
|
69
|
+
LEADER = "1"
|
|
70
|
+
ALL_REPLICAS = "-1"
|
|
71
|
+
|
|
72
|
+
def to_aiokafka(self) -> int | str:
|
|
73
|
+
"""Convert to aiokafka-compatible type.
|
|
74
|
+
|
|
75
|
+
aiokafka's AIOKafkaProducer expects:
|
|
76
|
+
- The string "all" for all-replica acknowledgment
|
|
77
|
+
- Integer values (0, 1, -1) for numeric ack levels
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
The acks value in the format expected by aiokafka:
|
|
81
|
+
- "all" (str) for ALL
|
|
82
|
+
- 0 (int) for NONE
|
|
83
|
+
- 1 (int) for LEADER
|
|
84
|
+
- -1 (int) for ALL_REPLICAS
|
|
85
|
+
|
|
86
|
+
Example:
|
|
87
|
+
>>> EnumKafkaAcks.ALL.to_aiokafka()
|
|
88
|
+
'all'
|
|
89
|
+
>>> EnumKafkaAcks.NONE.to_aiokafka()
|
|
90
|
+
0
|
|
91
|
+
>>> EnumKafkaAcks.LEADER.to_aiokafka()
|
|
92
|
+
1
|
|
93
|
+
>>> EnumKafkaAcks.ALL_REPLICAS.to_aiokafka()
|
|
94
|
+
-1
|
|
95
|
+
"""
|
|
96
|
+
return _AIOKAFKA_MAP[self.value]
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
__all__: list[str] = ["EnumKafkaAcks"]
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
This module defines the ComputeRegistryError for compute registry operations.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
+
from typing import Any, cast
|
|
9
|
+
|
|
8
10
|
from omnibase_infra.errors.error_infra import RuntimeHostError
|
|
9
11
|
from omnibase_infra.models.errors.model_infra_error_context import (
|
|
10
12
|
ModelInfraErrorContext,
|
|
@@ -82,10 +84,11 @@ class ComputeRegistryError(RuntimeHostError):
|
|
|
82
84
|
if registered_plugins is not None:
|
|
83
85
|
extra_context["registered_plugins"] = registered_plugins
|
|
84
86
|
|
|
87
|
+
# NOTE: Cast required for mypy - **dict[str, object] doesn't satisfy **context: Any
|
|
85
88
|
super().__init__(
|
|
86
89
|
message=message,
|
|
87
90
|
context=context,
|
|
88
|
-
**extra_context,
|
|
91
|
+
**cast("dict[str, Any]", extra_context),
|
|
89
92
|
)
|
|
90
93
|
|
|
91
94
|
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
This module defines the EventBusRegistryError for event bus registry operations.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
+
from typing import Any, cast
|
|
9
|
+
|
|
8
10
|
from omnibase_infra.errors.error_infra import RuntimeHostError
|
|
9
11
|
from omnibase_infra.models.errors.model_infra_error_context import (
|
|
10
12
|
ModelInfraErrorContext,
|
|
@@ -92,10 +94,11 @@ class EventBusRegistryError(RuntimeHostError):
|
|
|
92
94
|
if existing_class is not None:
|
|
93
95
|
extra_context["existing_class"] = existing_class
|
|
94
96
|
|
|
97
|
+
# NOTE: Cast required for mypy - **dict[str, object] doesn't satisfy **context: Any
|
|
95
98
|
super().__init__(
|
|
96
99
|
message=message,
|
|
97
100
|
context=context,
|
|
98
|
-
**extra_context,
|
|
101
|
+
**cast("dict[str, Any]", extra_context),
|
|
99
102
|
)
|
|
100
103
|
|
|
101
104
|
|
|
@@ -68,6 +68,7 @@ NOT_FOUND Classification Patterns:
|
|
|
68
68
|
- Optional keys, cache lookups: Use discriminated union responses
|
|
69
69
|
"""
|
|
70
70
|
|
|
71
|
+
from typing import Any, cast
|
|
71
72
|
from uuid import uuid4
|
|
72
73
|
|
|
73
74
|
from omnibase_core.enums import EnumCoreErrorCode
|
|
@@ -145,11 +146,12 @@ class RuntimeHostError(ModelOnexError):
|
|
|
145
146
|
correlation_id = uuid4()
|
|
146
147
|
|
|
147
148
|
# Initialize base error with default error code
|
|
149
|
+
# NOTE: Cast required for mypy - **dict[str, object] doesn't satisfy **context: Any
|
|
148
150
|
super().__init__(
|
|
149
151
|
message=message,
|
|
150
152
|
error_code=error_code or EnumCoreErrorCode.OPERATION_FAILED,
|
|
151
153
|
correlation_id=correlation_id,
|
|
152
|
-
**structured_context,
|
|
154
|
+
**cast("dict[str, Any]", structured_context),
|
|
153
155
|
)
|
|
154
156
|
|
|
155
157
|
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
This module defines the PolicyRegistryError for policy registry operations.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
+
from typing import Any, cast
|
|
9
|
+
|
|
8
10
|
from omnibase_infra.enums import EnumPolicyType
|
|
9
11
|
from omnibase_infra.errors.error_infra import RuntimeHostError
|
|
10
12
|
from omnibase_infra.models.errors.model_infra_error_context import (
|
|
@@ -102,10 +104,11 @@ class PolicyRegistryError(RuntimeHostError):
|
|
|
102
104
|
else policy_type
|
|
103
105
|
)
|
|
104
106
|
|
|
107
|
+
# NOTE: Cast required for mypy - **dict[str, object] doesn't satisfy **context: Any
|
|
105
108
|
super().__init__(
|
|
106
109
|
message=message,
|
|
107
110
|
context=context,
|
|
108
|
-
**extra_context,
|
|
111
|
+
**cast("dict[str, Any]", extra_context),
|
|
109
112
|
)
|
|
110
113
|
|
|
111
114
|
|
|
@@ -491,7 +491,7 @@ class EventBusKafka(MixinKafkaBroadcast, MixinKafkaDlq, MixinAsyncCircuitBreaker
|
|
|
491
491
|
# Apply producer configuration from config model
|
|
492
492
|
self._producer = AIOKafkaProducer(
|
|
493
493
|
bootstrap_servers=self._bootstrap_servers,
|
|
494
|
-
acks=self._config.
|
|
494
|
+
acks=self._config.acks_aiokafka,
|
|
495
495
|
enable_idempotence=self._config.enable_idempotence,
|
|
496
496
|
)
|
|
497
497
|
|
|
@@ -106,9 +106,9 @@ from pathlib import Path
|
|
|
106
106
|
from uuid import uuid4
|
|
107
107
|
|
|
108
108
|
import yaml
|
|
109
|
-
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
109
|
+
from pydantic import BaseModel, ConfigDict, Field, computed_field, field_validator
|
|
110
110
|
|
|
111
|
-
from omnibase_infra.enums import EnumInfraTransportType
|
|
111
|
+
from omnibase_infra.enums import EnumInfraTransportType, EnumKafkaAcks
|
|
112
112
|
from omnibase_infra.errors import ModelInfraErrorContext, ProtocolConfigurationError
|
|
113
113
|
|
|
114
114
|
logger = logging.getLogger(__name__)
|
|
@@ -131,7 +131,7 @@ class ModelKafkaEventBusConfig(BaseModel):
|
|
|
131
131
|
circuit_breaker_threshold: Number of consecutive failures before circuit opens
|
|
132
132
|
circuit_breaker_reset_timeout: Seconds before circuit breaker resets to half-open
|
|
133
133
|
consumer_sleep_interval: Sleep interval in seconds for consumer loop polling
|
|
134
|
-
acks: Producer acknowledgment policy (
|
|
134
|
+
acks: Producer acknowledgment policy (EnumKafkaAcks.ALL, LEADER, NONE, ALL_REPLICAS)
|
|
135
135
|
enable_idempotence: Enable producer idempotence for exactly-once semantics
|
|
136
136
|
auto_offset_reset: Consumer offset reset policy ("earliest", "latest")
|
|
137
137
|
enable_auto_commit: Enable auto-commit for consumer offsets
|
|
@@ -216,10 +216,9 @@ class ModelKafkaEventBusConfig(BaseModel):
|
|
|
216
216
|
)
|
|
217
217
|
|
|
218
218
|
# Kafka producer settings
|
|
219
|
-
acks:
|
|
220
|
-
default=
|
|
221
|
-
description="Producer acknowledgment policy (
|
|
222
|
-
pattern=r"^(all|0|1)$",
|
|
219
|
+
acks: EnumKafkaAcks = Field(
|
|
220
|
+
default=EnumKafkaAcks.ALL,
|
|
221
|
+
description="Producer acknowledgment policy (ALL, LEADER, NONE, ALL_REPLICAS)",
|
|
223
222
|
)
|
|
224
223
|
enable_idempotence: bool = Field(
|
|
225
224
|
default=True,
|
|
@@ -248,6 +247,32 @@ class ModelKafkaEventBusConfig(BaseModel):
|
|
|
248
247
|
),
|
|
249
248
|
)
|
|
250
249
|
|
|
250
|
+
# NOTE: mypy reports "prop-decorator" error because it doesn't understand that
|
|
251
|
+
# Pydantic's @computed_field transforms the @property into a computed field.
|
|
252
|
+
# This is a known mypy/Pydantic v2 interaction - the code works correctly at runtime.
|
|
253
|
+
@computed_field # type: ignore[prop-decorator]
|
|
254
|
+
@property
|
|
255
|
+
def acks_aiokafka(self) -> int | str:
|
|
256
|
+
"""Get acks value in aiokafka-compatible format.
|
|
257
|
+
|
|
258
|
+
aiokafka's AIOKafkaProducer expects:
|
|
259
|
+
- The string "all" for all-replica acknowledgment
|
|
260
|
+
- Integer values (0, 1, -1) for numeric ack levels
|
|
261
|
+
|
|
262
|
+
Returns:
|
|
263
|
+
The acks value converted to the format expected by aiokafka:
|
|
264
|
+
- "all" (str) for EnumKafkaAcks.ALL
|
|
265
|
+
- 0 (int) for EnumKafkaAcks.NONE
|
|
266
|
+
- 1 (int) for EnumKafkaAcks.LEADER
|
|
267
|
+
- -1 (int) for EnumKafkaAcks.ALL_REPLICAS
|
|
268
|
+
|
|
269
|
+
Example:
|
|
270
|
+
>>> config = ModelKafkaEventBusConfig(acks=EnumKafkaAcks.LEADER)
|
|
271
|
+
>>> config.acks_aiokafka
|
|
272
|
+
1
|
|
273
|
+
"""
|
|
274
|
+
return self.acks.to_aiokafka()
|
|
275
|
+
|
|
251
276
|
@field_validator("bootstrap_servers", mode="before")
|
|
252
277
|
@classmethod
|
|
253
278
|
def validate_bootstrap_servers(cls, v: object) -> str:
|
|
@@ -503,10 +528,33 @@ class ModelKafkaEventBusConfig(BaseModel):
|
|
|
503
528
|
"enable_auto_commit",
|
|
504
529
|
}
|
|
505
530
|
|
|
531
|
+
# Enum fields with their valid values mapping
|
|
532
|
+
# Maps field_name -> (enum_class, value_to_enum_mapping)
|
|
533
|
+
acks_mapping = {
|
|
534
|
+
"all": EnumKafkaAcks.ALL,
|
|
535
|
+
"0": EnumKafkaAcks.NONE,
|
|
536
|
+
"1": EnumKafkaAcks.LEADER,
|
|
537
|
+
"-1": EnumKafkaAcks.ALL_REPLICAS,
|
|
538
|
+
}
|
|
539
|
+
|
|
506
540
|
for env_var, field_name in env_mappings.items():
|
|
507
541
|
env_value = os.environ.get(env_var)
|
|
508
542
|
if env_value is not None:
|
|
509
|
-
if field_name
|
|
543
|
+
if field_name == "acks":
|
|
544
|
+
# Special handling for acks enum - fail-fast on invalid values
|
|
545
|
+
if env_value in acks_mapping:
|
|
546
|
+
overrides[field_name] = acks_mapping[env_value]
|
|
547
|
+
else:
|
|
548
|
+
valid_values = ", ".join(acks_mapping.keys())
|
|
549
|
+
raise ProtocolConfigurationError(
|
|
550
|
+
f"Invalid value for environment variable {env_var}='{env_value}'. "
|
|
551
|
+
f"Valid values are: {valid_values}",
|
|
552
|
+
context=ModelInfraErrorContext.with_correlation(
|
|
553
|
+
transport_type=EnumInfraTransportType.KAFKA,
|
|
554
|
+
operation="apply_environment_overrides",
|
|
555
|
+
),
|
|
556
|
+
)
|
|
557
|
+
elif field_name in int_fields:
|
|
510
558
|
try:
|
|
511
559
|
overrides[field_name] = int(env_value)
|
|
512
560
|
except ValueError:
|
|
@@ -557,7 +605,8 @@ class ModelKafkaEventBusConfig(BaseModel):
|
|
|
557
605
|
overrides[field_name] = env_value
|
|
558
606
|
|
|
559
607
|
if overrides:
|
|
560
|
-
|
|
608
|
+
# Exclude computed field to avoid validation error
|
|
609
|
+
current_data = self.model_dump(exclude={"acks_aiokafka"})
|
|
561
610
|
current_data.update(overrides)
|
|
562
611
|
return ModelKafkaEventBusConfig(**current_data)
|
|
563
612
|
|
|
@@ -583,7 +632,7 @@ class ModelKafkaEventBusConfig(BaseModel):
|
|
|
583
632
|
circuit_breaker_threshold=5,
|
|
584
633
|
circuit_breaker_reset_timeout=30.0,
|
|
585
634
|
consumer_sleep_interval=0.1,
|
|
586
|
-
acks=
|
|
635
|
+
acks=EnumKafkaAcks.ALL,
|
|
587
636
|
enable_idempotence=True,
|
|
588
637
|
auto_offset_reset="latest",
|
|
589
638
|
enable_auto_commit=True,
|
|
@@ -18,6 +18,7 @@ Available Handlers:
|
|
|
18
18
|
- HandlerFileSystem: Filesystem handler with path whitelisting and size limits
|
|
19
19
|
- HandlerManifestPersistence: Execution manifest persistence with filesystem storage
|
|
20
20
|
- HandlerGraph: Graph database handler (Memgraph/Neo4j via Bolt protocol)
|
|
21
|
+
- HandlerIntent: Intent storage and query handler wrapping HandlerGraph (demo wiring)
|
|
21
22
|
- HandlerQdrant: Qdrant vector database handler (MVP: create, upsert, search, delete)
|
|
22
23
|
|
|
23
24
|
Response Models:
|
|
@@ -35,6 +36,10 @@ from omnibase_infra.handlers.handler_db import HandlerDb
|
|
|
35
36
|
from omnibase_infra.handlers.handler_filesystem import HandlerFileSystem
|
|
36
37
|
from omnibase_infra.handlers.handler_graph import HandlerGraph
|
|
37
38
|
from omnibase_infra.handlers.handler_http import HandlerHttpRest
|
|
39
|
+
from omnibase_infra.handlers.handler_intent import ( # DEMO: Temporary intent handler wiring (OMN-1515)
|
|
40
|
+
HANDLER_ID_INTENT,
|
|
41
|
+
HandlerIntent,
|
|
42
|
+
)
|
|
38
43
|
from omnibase_infra.handlers.handler_manifest_persistence import (
|
|
39
44
|
HandlerManifestPersistence,
|
|
40
45
|
)
|
|
@@ -56,15 +61,17 @@ from omnibase_infra.handlers.models.model_qdrant_handler_response import (
|
|
|
56
61
|
)
|
|
57
62
|
|
|
58
63
|
__all__: list[str] = [
|
|
64
|
+
"HANDLER_ID_INTENT",
|
|
59
65
|
"HandlerConsul",
|
|
60
66
|
"HandlerDb",
|
|
61
67
|
"HandlerFileSystem",
|
|
62
68
|
"HandlerGraph",
|
|
69
|
+
"HandlerHttpRest",
|
|
70
|
+
"HandlerIntent",
|
|
63
71
|
"HandlerManifestPersistence",
|
|
64
72
|
"HandlerMCP",
|
|
65
73
|
"HandlerQdrant",
|
|
66
74
|
"HandlerVault",
|
|
67
|
-
"HandlerHttpRest",
|
|
68
75
|
"ModelConsulHandlerPayload",
|
|
69
76
|
"ModelConsulHandlerResponse",
|
|
70
77
|
"ModelDbDescribeResponse",
|
|
@@ -33,6 +33,7 @@ from uuid import UUID, uuid4
|
|
|
33
33
|
|
|
34
34
|
import consul
|
|
35
35
|
|
|
36
|
+
from omnibase_core.container import ModelONEXContainer
|
|
36
37
|
from omnibase_core.models.dispatch import ModelHandlerOutput
|
|
37
38
|
from omnibase_infra.enums import (
|
|
38
39
|
EnumHandlerType,
|
|
@@ -190,13 +191,18 @@ class HandlerConsul(
|
|
|
190
191
|
target_name=f"consul.{self._config.datacenter or 'default'}"
|
|
191
192
|
"""
|
|
192
193
|
|
|
193
|
-
def __init__(self) -> None:
|
|
194
|
+
def __init__(self, container: ModelONEXContainer) -> None:
|
|
194
195
|
"""Initialize HandlerConsul in uninitialized state.
|
|
195
196
|
|
|
197
|
+
Args:
|
|
198
|
+
container: ONEX container for dependency injection. Required for
|
|
199
|
+
consistent handler initialization pattern across all handlers.
|
|
200
|
+
|
|
196
201
|
Note: Circuit breaker is initialized during initialize() call when
|
|
197
202
|
configuration is available. The mixin's _init_circuit_breaker() method
|
|
198
203
|
is called there with the actual config values.
|
|
199
204
|
"""
|
|
205
|
+
self._container = container
|
|
200
206
|
self._client: consul.Consul | None = None
|
|
201
207
|
self._config: ModelConsulHandlerConfig | None = None
|
|
202
208
|
self._initialized: bool = False
|
|
@@ -75,7 +75,9 @@ from uuid import UUID, uuid4
|
|
|
75
75
|
|
|
76
76
|
import asyncpg
|
|
77
77
|
|
|
78
|
+
from omnibase_core.container import ModelONEXContainer
|
|
78
79
|
from omnibase_core.models.dispatch import ModelHandlerOutput
|
|
80
|
+
from omnibase_core.types import JsonType
|
|
79
81
|
from omnibase_infra.enums import (
|
|
80
82
|
EnumHandlerType,
|
|
81
83
|
EnumHandlerTypeCategory,
|
|
@@ -221,8 +223,13 @@ class HandlerDb(MixinAsyncCircuitBreaker, MixinEnvelopeExtraction):
|
|
|
221
223
|
- HALF_OPEN: Testing recovery after reset timeout, limited requests allowed
|
|
222
224
|
"""
|
|
223
225
|
|
|
224
|
-
def __init__(self) -> None:
|
|
225
|
-
"""Initialize HandlerDb
|
|
226
|
+
def __init__(self, container: ModelONEXContainer) -> None:
|
|
227
|
+
"""Initialize HandlerDb with ONEX container for dependency injection.
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
container: ONEX container for dependency injection.
|
|
231
|
+
"""
|
|
232
|
+
self._container = container
|
|
226
233
|
self._pool: asyncpg.Pool | None = None
|
|
227
234
|
self._pool_size: int = _DEFAULT_POOL_SIZE
|
|
228
235
|
self._timeout: float = _DEFAULT_TIMEOUT_SECONDS
|
|
@@ -1020,7 +1027,7 @@ class HandlerDb(MixinAsyncCircuitBreaker, MixinEnvelopeExtraction):
|
|
|
1020
1027
|
- docs/architecture/HANDLER_PROTOCOL_DRIVEN_ARCHITECTURE.md
|
|
1021
1028
|
"""
|
|
1022
1029
|
# Get circuit breaker state if initialized
|
|
1023
|
-
cb_state: dict[str,
|
|
1030
|
+
cb_state: dict[str, JsonType] | None = None
|
|
1024
1031
|
if self._circuit_breaker_initialized:
|
|
1025
1032
|
cb_state = self._get_circuit_breaker_state()
|
|
1026
1033
|
|
|
@@ -464,9 +464,11 @@ class HandlerGraph(MixinAsyncCircuitBreaker, ProtocolGraphDatabaseHandler):
|
|
|
464
464
|
try:
|
|
465
465
|
for query, params in queries:
|
|
466
466
|
query_start = time.perf_counter()
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
467
|
+
tx_result = await tx.run(
|
|
468
|
+
query, dict(params) if params else {}
|
|
469
|
+
)
|
|
470
|
+
records_data = await tx_result.data()
|
|
471
|
+
summary = await tx_result.consume()
|
|
470
472
|
query_time_ms = (time.perf_counter() - query_start) * 1000
|
|
471
473
|
|
|
472
474
|
results.append(
|
|
@@ -497,8 +499,11 @@ class HandlerGraph(MixinAsyncCircuitBreaker, ProtocolGraphDatabaseHandler):
|
|
|
497
499
|
else:
|
|
498
500
|
# Execute queries individually without transaction
|
|
499
501
|
for query, params in queries:
|
|
500
|
-
|
|
501
|
-
|
|
502
|
+
# Type assertion: execute_query returns ModelGraphQueryResult in this handler
|
|
503
|
+
query_result: ModelGraphQueryResult = await self.execute_query(
|
|
504
|
+
query, params
|
|
505
|
+
) # type: ignore[assignment]
|
|
506
|
+
results.append(query_result)
|
|
502
507
|
|
|
503
508
|
return ModelGraphBatchResult(
|
|
504
509
|
results=results,
|
|
@@ -24,6 +24,7 @@ from uuid import UUID, uuid4
|
|
|
24
24
|
|
|
25
25
|
import httpx
|
|
26
26
|
|
|
27
|
+
from omnibase_core.container import ModelONEXContainer
|
|
27
28
|
from omnibase_core.models.dispatch import ModelHandlerOutput
|
|
28
29
|
from omnibase_infra.enums import (
|
|
29
30
|
EnumHandlerType,
|
|
@@ -114,8 +115,13 @@ class HandlerHttpRest(MixinEnvelopeExtraction):
|
|
|
114
115
|
- Streaming body validation for chunked transfer encoding
|
|
115
116
|
"""
|
|
116
117
|
|
|
117
|
-
def __init__(self) -> None:
|
|
118
|
-
"""Initialize HandlerHttpRest
|
|
118
|
+
def __init__(self, container: ModelONEXContainer) -> None:
|
|
119
|
+
"""Initialize HandlerHttpRest with ONEX container for dependency injection.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
container: ONEX container for dependency injection.
|
|
123
|
+
"""
|
|
124
|
+
self._container = container
|
|
119
125
|
self._client: httpx.AsyncClient | None = None
|
|
120
126
|
self._timeout: float = _DEFAULT_TIMEOUT_SECONDS
|
|
121
127
|
self._max_request_size: int = _DEFAULT_MAX_REQUEST_SIZE
|