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,221 @@
|
|
|
1
|
+
"""Contract capability extractor for ONEX nodes.
|
|
2
|
+
|
|
3
|
+
Extracts ModelContractCapabilities from typed contract models.
|
|
4
|
+
No side effects, deterministic output.
|
|
5
|
+
|
|
6
|
+
OMN-1136: ContractCapabilityExtractor - Main extractor implementation.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import TYPE_CHECKING
|
|
12
|
+
|
|
13
|
+
from omnibase_core.models.capabilities import ModelContractCapabilities
|
|
14
|
+
from omnibase_core.models.primitives.model_semver import ModelSemVer
|
|
15
|
+
from omnibase_infra.capabilities.capability_inference_rules import (
|
|
16
|
+
CapabilityInferenceRules,
|
|
17
|
+
)
|
|
18
|
+
from omnibase_infra.capabilities.intent_type_extractor import IntentTypeExtractor
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from omnibase_core.models.contracts import (
|
|
22
|
+
ModelContractBase,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ContractCapabilityExtractor:
|
|
27
|
+
"""Extracts capabilities from typed contract models.
|
|
28
|
+
|
|
29
|
+
Responsibilities:
|
|
30
|
+
- Read capability-related fields from contract
|
|
31
|
+
- Apply inference rules to derive additional tags
|
|
32
|
+
- Union explicit + inferred capabilities
|
|
33
|
+
- Return deterministic, sorted output
|
|
34
|
+
|
|
35
|
+
This extractor is stateless and produces deterministic output
|
|
36
|
+
for the same contract input.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
rules: Optional custom CapabilityInferenceRules instance. If not provided,
|
|
40
|
+
uses a default instance with standard rule mappings.
|
|
41
|
+
|
|
42
|
+
Example:
|
|
43
|
+
# Use default rules
|
|
44
|
+
extractor = ContractCapabilityExtractor()
|
|
45
|
+
|
|
46
|
+
# Use custom rules
|
|
47
|
+
custom_rules = CapabilityInferenceRules(
|
|
48
|
+
intent_patterns={"redis.": "redis.caching"}
|
|
49
|
+
)
|
|
50
|
+
extractor = ContractCapabilityExtractor(rules=custom_rules)
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
def __init__(self, rules: CapabilityInferenceRules | None = None) -> None:
|
|
54
|
+
"""Initialize with optional custom inference rules.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
rules: Custom CapabilityInferenceRules instance. If None, creates
|
|
58
|
+
a default instance with standard rule mappings.
|
|
59
|
+
"""
|
|
60
|
+
self._rules = rules if rules is not None else CapabilityInferenceRules()
|
|
61
|
+
self._intent_extractor = IntentTypeExtractor()
|
|
62
|
+
|
|
63
|
+
def extract(self, contract: ModelContractBase) -> ModelContractCapabilities | None:
|
|
64
|
+
"""Extract capabilities from a contract model.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
contract: Typed contract model (Effect, Compute, Reducer, or Orchestrator)
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
ModelContractCapabilities with extracted data, or None if contract is None
|
|
71
|
+
|
|
72
|
+
Raises:
|
|
73
|
+
Any exceptions from extraction propagate (fail-fast behavior).
|
|
74
|
+
"""
|
|
75
|
+
if contract is None:
|
|
76
|
+
return None
|
|
77
|
+
|
|
78
|
+
# Extract contract type from node_type
|
|
79
|
+
contract_type = self._extract_contract_type(contract)
|
|
80
|
+
|
|
81
|
+
# Extract version
|
|
82
|
+
contract_version = self._extract_version(contract)
|
|
83
|
+
|
|
84
|
+
# Extract intent types (varies by node type)
|
|
85
|
+
intent_types = self._extract_intent_types(contract)
|
|
86
|
+
|
|
87
|
+
# Extract protocols from dependencies
|
|
88
|
+
protocols = self._extract_protocols(contract)
|
|
89
|
+
|
|
90
|
+
# Extract explicit capability tags from contract
|
|
91
|
+
explicit_tags = self._extract_explicit_tags(contract)
|
|
92
|
+
|
|
93
|
+
# Infer additional tags using rules
|
|
94
|
+
inferred_tags = self._rules.infer_all(
|
|
95
|
+
intent_types=intent_types,
|
|
96
|
+
protocols=protocols,
|
|
97
|
+
node_type=contract_type,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
# Union explicit + inferred (deterministic), filtering out invalid tags
|
|
101
|
+
combined_tags = set(explicit_tags) | set(inferred_tags)
|
|
102
|
+
all_tags = sorted(tag for tag in combined_tags if self._validate_tag(tag))
|
|
103
|
+
|
|
104
|
+
return ModelContractCapabilities(
|
|
105
|
+
contract_type=contract_type,
|
|
106
|
+
contract_version=contract_version,
|
|
107
|
+
intent_types=sorted(set(intent_types)),
|
|
108
|
+
protocols=sorted(set(protocols)),
|
|
109
|
+
capability_tags=all_tags,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
def _extract_contract_type(self, contract: ModelContractBase) -> str:
|
|
113
|
+
"""Extract normalized contract type string.
|
|
114
|
+
|
|
115
|
+
Raises:
|
|
116
|
+
ValueError: If contract does not have node_type field.
|
|
117
|
+
"""
|
|
118
|
+
node_type = getattr(contract, "node_type", None)
|
|
119
|
+
if node_type is None:
|
|
120
|
+
raise ValueError("Contract must have node_type field")
|
|
121
|
+
|
|
122
|
+
# Handle both enum and string, normalize to lowercase without _GENERIC suffix
|
|
123
|
+
type_str = node_type.value if hasattr(node_type, "value") else str(node_type)
|
|
124
|
+
return type_str.lower().replace("_generic", "")
|
|
125
|
+
|
|
126
|
+
def _extract_version(self, contract: ModelContractBase) -> ModelSemVer:
|
|
127
|
+
"""Extract contract version.
|
|
128
|
+
|
|
129
|
+
Raises:
|
|
130
|
+
ValueError: If contract_version is missing or not a ModelSemVer instance.
|
|
131
|
+
"""
|
|
132
|
+
version = getattr(contract, "contract_version", None)
|
|
133
|
+
if isinstance(version, ModelSemVer):
|
|
134
|
+
return version
|
|
135
|
+
raise ValueError(
|
|
136
|
+
f"Contract must have contract_version as ModelSemVer, "
|
|
137
|
+
f"got {type(version).__name__ if version is not None else 'None'}"
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
def _extract_intent_types(self, contract: ModelContractBase) -> list[str]:
|
|
141
|
+
"""Extract intent types based on node type.
|
|
142
|
+
|
|
143
|
+
Delegates to IntentTypeExtractor which handles extraction from
|
|
144
|
+
multiple sources based on node type.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
contract: The contract model to extract intent types from.
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
Combined list of intent types from all applicable sources.
|
|
151
|
+
"""
|
|
152
|
+
return self._intent_extractor.extract_all(contract)
|
|
153
|
+
|
|
154
|
+
def _extract_protocols(self, contract: ModelContractBase) -> list[str]:
|
|
155
|
+
"""Extract protocol names from dependencies and interfaces."""
|
|
156
|
+
protocols: list[str] = []
|
|
157
|
+
|
|
158
|
+
# From protocol_interfaces field
|
|
159
|
+
if hasattr(contract, "protocol_interfaces"):
|
|
160
|
+
protocol_interfaces = contract.protocol_interfaces
|
|
161
|
+
if protocol_interfaces:
|
|
162
|
+
for proto in protocol_interfaces:
|
|
163
|
+
if proto is not None: # Skip None values
|
|
164
|
+
protocols.append(proto)
|
|
165
|
+
|
|
166
|
+
# From dependencies where type is protocol
|
|
167
|
+
if hasattr(contract, "dependencies"):
|
|
168
|
+
dependencies = contract.dependencies
|
|
169
|
+
if dependencies:
|
|
170
|
+
for dep in dependencies:
|
|
171
|
+
# Check if it's a protocol dependency using is_protocol() method
|
|
172
|
+
if hasattr(dep, "is_protocol") and dep.is_protocol():
|
|
173
|
+
if hasattr(dep, "name") and dep.name:
|
|
174
|
+
protocols.append(dep.name)
|
|
175
|
+
# Fallback: check dependency_type directly
|
|
176
|
+
elif hasattr(dep, "dependency_type"):
|
|
177
|
+
dep_type = dep.dependency_type
|
|
178
|
+
type_str = (
|
|
179
|
+
dep_type.value
|
|
180
|
+
if hasattr(dep_type, "value")
|
|
181
|
+
else str(dep_type)
|
|
182
|
+
)
|
|
183
|
+
if type_str.upper() == "PROTOCOL":
|
|
184
|
+
if hasattr(dep, "name") and dep.name:
|
|
185
|
+
protocols.append(dep.name)
|
|
186
|
+
|
|
187
|
+
return protocols
|
|
188
|
+
|
|
189
|
+
def _validate_tag(self, tag: str | None) -> bool:
|
|
190
|
+
"""Validate a tag string.
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
tag: Tag string to validate.
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
True if the tag is valid, False otherwise.
|
|
197
|
+
Invalid tags include: None, empty strings, whitespace-only strings.
|
|
198
|
+
"""
|
|
199
|
+
if tag is None:
|
|
200
|
+
return False
|
|
201
|
+
if not isinstance(tag, str):
|
|
202
|
+
return False
|
|
203
|
+
if tag == "":
|
|
204
|
+
return False
|
|
205
|
+
if tag.strip() == "":
|
|
206
|
+
return False
|
|
207
|
+
return True
|
|
208
|
+
|
|
209
|
+
def _extract_explicit_tags(self, contract: ModelContractBase) -> list[str]:
|
|
210
|
+
"""Extract explicitly declared capability tags from contract."""
|
|
211
|
+
tags: list[str] = []
|
|
212
|
+
|
|
213
|
+
# From top-level tags field (all contracts have this)
|
|
214
|
+
if hasattr(contract, "tags"):
|
|
215
|
+
contract_tags = contract.tags
|
|
216
|
+
if contract_tags:
|
|
217
|
+
for tag in contract_tags:
|
|
218
|
+
if self._validate_tag(tag):
|
|
219
|
+
tags.append(tag)
|
|
220
|
+
|
|
221
|
+
return tags
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""Intent type extraction from ONEX contracts.
|
|
2
|
+
|
|
3
|
+
Extracts intent types from various contract structures including
|
|
4
|
+
event_type, consumed_events, published_events, and aggregation fields.
|
|
5
|
+
|
|
6
|
+
OMN-1136: Intent type extraction helper for ContractCapabilityExtractor.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import TYPE_CHECKING
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from omnibase_core.models.contracts import ModelContractBase
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class IntentTypeExtractor:
|
|
18
|
+
"""Extracts intent types from contract models.
|
|
19
|
+
|
|
20
|
+
This class handles extraction of intent types from various contract
|
|
21
|
+
structures. Different node types expose intent information in different
|
|
22
|
+
locations:
|
|
23
|
+
- Effect nodes: event_type.primary_events
|
|
24
|
+
- Orchestrator nodes: consumed_events[].event_pattern, published_events[].event_name
|
|
25
|
+
- Reducer nodes: aggregation.aggregation_functions
|
|
26
|
+
|
|
27
|
+
This extractor is stateless and produces deterministic output.
|
|
28
|
+
|
|
29
|
+
Example:
|
|
30
|
+
extractor = IntentTypeExtractor()
|
|
31
|
+
intent_types = extractor.extract_all(contract)
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def extract_all(self, contract: ModelContractBase) -> list[str]:
|
|
35
|
+
"""Extract intent types from all applicable sources.
|
|
36
|
+
|
|
37
|
+
Combines intent types from event_type, consumed_events,
|
|
38
|
+
published_events, and aggregation fields.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
contract: The contract model to extract intent types from.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
Combined list of intent types from all applicable sources.
|
|
45
|
+
"""
|
|
46
|
+
intent_types: list[str] = []
|
|
47
|
+
|
|
48
|
+
intent_types.extend(self._extract_from_event_type(contract))
|
|
49
|
+
intent_types.extend(self._extract_from_consumed_events(contract))
|
|
50
|
+
intent_types.extend(self._extract_from_published_events(contract))
|
|
51
|
+
intent_types.extend(self._extract_from_aggregation(contract))
|
|
52
|
+
|
|
53
|
+
return intent_types
|
|
54
|
+
|
|
55
|
+
def _extract_from_event_type(self, contract: ModelContractBase) -> list[str]:
|
|
56
|
+
"""Extract intent types from event_type.primary_events.
|
|
57
|
+
|
|
58
|
+
Used primarily by Effect nodes to declare the events they handle.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
contract: The contract model to extract from.
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
List of primary event types, or empty list if not present.
|
|
65
|
+
"""
|
|
66
|
+
if not hasattr(contract, "event_type"):
|
|
67
|
+
return []
|
|
68
|
+
|
|
69
|
+
event_type = contract.event_type
|
|
70
|
+
if event_type is None or not hasattr(event_type, "primary_events"):
|
|
71
|
+
return []
|
|
72
|
+
|
|
73
|
+
primary_events = event_type.primary_events
|
|
74
|
+
if not primary_events:
|
|
75
|
+
return []
|
|
76
|
+
|
|
77
|
+
return list(primary_events)
|
|
78
|
+
|
|
79
|
+
def _extract_from_consumed_events(self, contract: ModelContractBase) -> list[str]:
|
|
80
|
+
"""Extract intent types from consumed_events[].event_pattern.
|
|
81
|
+
|
|
82
|
+
Used by Orchestrator nodes to declare which events they subscribe to.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
contract: The contract model to extract from.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
List of event patterns from consumed events, or empty list if not present.
|
|
89
|
+
"""
|
|
90
|
+
if not hasattr(contract, "consumed_events"):
|
|
91
|
+
return []
|
|
92
|
+
|
|
93
|
+
consumed_events = contract.consumed_events
|
|
94
|
+
if not consumed_events:
|
|
95
|
+
return []
|
|
96
|
+
|
|
97
|
+
intent_types: list[str] = []
|
|
98
|
+
for event in consumed_events:
|
|
99
|
+
# ModelEventSubscription has event_pattern field
|
|
100
|
+
if hasattr(event, "event_pattern") and event.event_pattern:
|
|
101
|
+
intent_types.append(event.event_pattern)
|
|
102
|
+
|
|
103
|
+
return intent_types
|
|
104
|
+
|
|
105
|
+
def _extract_from_published_events(self, contract: ModelContractBase) -> list[str]:
|
|
106
|
+
"""Extract intent types from published_events[].event_name.
|
|
107
|
+
|
|
108
|
+
Used by Orchestrator nodes to declare which events they publish.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
contract: The contract model to extract from.
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
List of event names from published events, or empty list if not present.
|
|
115
|
+
"""
|
|
116
|
+
if not hasattr(contract, "published_events"):
|
|
117
|
+
return []
|
|
118
|
+
|
|
119
|
+
published_events = contract.published_events
|
|
120
|
+
if not published_events:
|
|
121
|
+
return []
|
|
122
|
+
|
|
123
|
+
intent_types: list[str] = []
|
|
124
|
+
for event in published_events:
|
|
125
|
+
# ModelEventDescriptor has event_name field
|
|
126
|
+
if hasattr(event, "event_name") and event.event_name:
|
|
127
|
+
intent_types.append(event.event_name)
|
|
128
|
+
|
|
129
|
+
return intent_types
|
|
130
|
+
|
|
131
|
+
def _extract_from_aggregation(self, contract: ModelContractBase) -> list[str]:
|
|
132
|
+
"""Extract intent types from aggregation.aggregation_functions.
|
|
133
|
+
|
|
134
|
+
Used by Reducer nodes to declare aggregation patterns based on
|
|
135
|
+
the output fields of their aggregation functions.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
contract: The contract model to extract from.
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
List of aggregation intent types (prefixed with 'aggregate.'),
|
|
142
|
+
or empty list if not present.
|
|
143
|
+
"""
|
|
144
|
+
if not hasattr(contract, "aggregation"):
|
|
145
|
+
return []
|
|
146
|
+
|
|
147
|
+
aggregation = contract.aggregation
|
|
148
|
+
if aggregation is None or not hasattr(aggregation, "aggregation_functions"):
|
|
149
|
+
return []
|
|
150
|
+
|
|
151
|
+
agg_funcs = aggregation.aggregation_functions
|
|
152
|
+
if not agg_funcs:
|
|
153
|
+
return []
|
|
154
|
+
|
|
155
|
+
intent_types: list[str] = []
|
|
156
|
+
for func in agg_funcs:
|
|
157
|
+
if hasattr(func, "output_field") and func.output_field:
|
|
158
|
+
intent_types.append(f"aggregate.{func.output_field}")
|
|
159
|
+
|
|
160
|
+
return intent_types
|
omnibase_infra/cli/commands.py
CHANGED
|
@@ -127,7 +127,7 @@ def validate_imports_cmd(directory: str) -> None:
|
|
|
127
127
|
console.print(f"[bold blue]Checking circular imports in {directory}...[/bold blue]")
|
|
128
128
|
result = validate_infra_circular_imports(directory)
|
|
129
129
|
|
|
130
|
-
#
|
|
130
|
+
# ModelImportValidationResult uses has_circular_imports property (plural)
|
|
131
131
|
if not result.has_circular_imports:
|
|
132
132
|
console.print("[bold green]Circular Imports: PASS[/bold green]")
|
|
133
133
|
raise SystemExit(0)
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2025 OmniNode Team
|
|
3
|
+
#
|
|
4
|
+
# Widget Mapping Configuration for ONEX Registry Dashboard
|
|
5
|
+
#
|
|
6
|
+
# This file defines the mapping from node capabilities and semantic roles
|
|
7
|
+
# to dashboard widget types. Used by the Registry API to inform dashboards
|
|
8
|
+
# which widget to render for each node.
|
|
9
|
+
#
|
|
10
|
+
# Related Tickets:
|
|
11
|
+
# - OMN-1278: Contract-Driven Dashboard - Registry Discovery
|
|
12
|
+
#
|
|
13
|
+
# Widget Types:
|
|
14
|
+
# - status_indicator: Shows health/state with colored indicator
|
|
15
|
+
# - event_feed: Scrolling list of recent events
|
|
16
|
+
# - metric_card: Single metric with value and optional trend
|
|
17
|
+
# - info_card: General information display
|
|
18
|
+
# - status_grid: Grid of status indicators
|
|
19
|
+
# - timeline: Time-based visualization
|
|
20
|
+
# - gauge: Circular progress/threshold indicator
|
|
21
|
+
# - table: Tabular data display
|
|
22
|
+
#
|
|
23
|
+
# Configuration Sections:
|
|
24
|
+
# - version: Schema version for compatibility checking
|
|
25
|
+
# - capability_mappings: Maps capability tags to widget configs
|
|
26
|
+
# - semantic_mappings: Maps semantic roles to widget configs
|
|
27
|
+
# - fallback: Default config when no mapping matches
|
|
28
|
+
version: "1.0.0"
|
|
29
|
+
# Capability Mappings
|
|
30
|
+
# Map specific capability tags to widget configurations.
|
|
31
|
+
# These take precedence over semantic mappings.
|
|
32
|
+
capability_mappings:
|
|
33
|
+
# Health and monitoring capabilities
|
|
34
|
+
health.check:
|
|
35
|
+
widget_type: status_indicator
|
|
36
|
+
defaults:
|
|
37
|
+
show_timestamp: true
|
|
38
|
+
refresh_interval_seconds: 10
|
|
39
|
+
health.heartbeat:
|
|
40
|
+
widget_type: status_indicator
|
|
41
|
+
defaults:
|
|
42
|
+
show_timestamp: true
|
|
43
|
+
show_last_seen: true
|
|
44
|
+
# Event-related capabilities
|
|
45
|
+
event.emit:
|
|
46
|
+
widget_type: event_feed
|
|
47
|
+
defaults:
|
|
48
|
+
max_items: 50
|
|
49
|
+
show_timestamp: true
|
|
50
|
+
auto_scroll: true
|
|
51
|
+
event.consume:
|
|
52
|
+
widget_type: event_feed
|
|
53
|
+
defaults:
|
|
54
|
+
max_items: 50
|
|
55
|
+
show_source: true
|
|
56
|
+
event.transform:
|
|
57
|
+
widget_type: timeline
|
|
58
|
+
defaults:
|
|
59
|
+
show_duration: true
|
|
60
|
+
# Kafka/messaging capabilities
|
|
61
|
+
kafka.consumer:
|
|
62
|
+
widget_type: metric_card
|
|
63
|
+
defaults:
|
|
64
|
+
refresh_interval_seconds: 5
|
|
65
|
+
show_lag: true
|
|
66
|
+
kafka.producer:
|
|
67
|
+
widget_type: metric_card
|
|
68
|
+
defaults:
|
|
69
|
+
refresh_interval_seconds: 5
|
|
70
|
+
show_throughput: true
|
|
71
|
+
kafka.stream:
|
|
72
|
+
widget_type: timeline
|
|
73
|
+
defaults:
|
|
74
|
+
show_offset: true
|
|
75
|
+
# Database capabilities
|
|
76
|
+
postgres.storage:
|
|
77
|
+
widget_type: metric_card
|
|
78
|
+
defaults:
|
|
79
|
+
show_connection_count: true
|
|
80
|
+
refresh_interval_seconds: 10
|
|
81
|
+
postgres.query:
|
|
82
|
+
widget_type: table
|
|
83
|
+
defaults:
|
|
84
|
+
show_query_time: true
|
|
85
|
+
# Service discovery
|
|
86
|
+
consul.register:
|
|
87
|
+
widget_type: status_indicator
|
|
88
|
+
defaults:
|
|
89
|
+
show_service_id: true
|
|
90
|
+
consul.discover:
|
|
91
|
+
widget_type: status_grid
|
|
92
|
+
defaults:
|
|
93
|
+
show_health: true
|
|
94
|
+
group_by: service_name
|
|
95
|
+
# Workflow capabilities
|
|
96
|
+
workflow.orchestrate:
|
|
97
|
+
widget_type: timeline
|
|
98
|
+
defaults:
|
|
99
|
+
show_steps: true
|
|
100
|
+
show_duration: true
|
|
101
|
+
workflow.reduce:
|
|
102
|
+
widget_type: gauge
|
|
103
|
+
defaults:
|
|
104
|
+
show_progress: true
|
|
105
|
+
# Compute capabilities
|
|
106
|
+
compute.transform:
|
|
107
|
+
widget_type: metric_card
|
|
108
|
+
defaults:
|
|
109
|
+
show_throughput: true
|
|
110
|
+
show_latency: true
|
|
111
|
+
compute.validate:
|
|
112
|
+
widget_type: status_indicator
|
|
113
|
+
defaults:
|
|
114
|
+
show_pass_rate: true
|
|
115
|
+
# Effect capabilities
|
|
116
|
+
effect.http:
|
|
117
|
+
widget_type: metric_card
|
|
118
|
+
defaults:
|
|
119
|
+
show_latency: true
|
|
120
|
+
show_error_rate: true
|
|
121
|
+
effect.grpc:
|
|
122
|
+
widget_type: metric_card
|
|
123
|
+
defaults:
|
|
124
|
+
show_latency: true
|
|
125
|
+
show_error_rate: true
|
|
126
|
+
# Semantic Mappings
|
|
127
|
+
# Map semantic roles/contexts to widget configurations.
|
|
128
|
+
# Used when capability_mappings don't match.
|
|
129
|
+
semantic_mappings:
|
|
130
|
+
# Node overview in dashboard
|
|
131
|
+
node_overview:
|
|
132
|
+
widget_type: info_card
|
|
133
|
+
defaults:
|
|
134
|
+
show_version: true
|
|
135
|
+
show_capabilities: true
|
|
136
|
+
show_state: true
|
|
137
|
+
# Instance health grid
|
|
138
|
+
instance_health:
|
|
139
|
+
widget_type: status_grid
|
|
140
|
+
defaults:
|
|
141
|
+
group_by: service_name
|
|
142
|
+
show_address: true
|
|
143
|
+
show_port: true
|
|
144
|
+
# Registration timeline
|
|
145
|
+
registration_timeline:
|
|
146
|
+
widget_type: timeline
|
|
147
|
+
defaults:
|
|
148
|
+
show_state_transitions: true
|
|
149
|
+
show_timestamps: true
|
|
150
|
+
# Capability matrix
|
|
151
|
+
capability_matrix:
|
|
152
|
+
widget_type: table
|
|
153
|
+
defaults:
|
|
154
|
+
group_by: node_type
|
|
155
|
+
show_capability_tags: true
|
|
156
|
+
# Summary statistics
|
|
157
|
+
summary_stats:
|
|
158
|
+
widget_type: metric_card
|
|
159
|
+
defaults:
|
|
160
|
+
show_trend: true
|
|
161
|
+
compare_to_previous: true
|
|
162
|
+
# Error monitoring
|
|
163
|
+
error_monitoring:
|
|
164
|
+
widget_type: event_feed
|
|
165
|
+
defaults:
|
|
166
|
+
filter_level: error
|
|
167
|
+
max_items: 100
|
|
168
|
+
highlight_critical: true
|
|
169
|
+
# Fallback Configuration
|
|
170
|
+
# Used when no capability or semantic mapping matches.
|
|
171
|
+
fallback:
|
|
172
|
+
widget_type: info_card
|
|
173
|
+
defaults:
|
|
174
|
+
show_name: true
|
|
175
|
+
show_state: true
|
|
176
|
+
show_type: true
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
# Handler ID follows convention: {node_type}.{domain}.handler
|
|
2
2
|
handler_id: effect.filesystem.handler
|
|
3
3
|
name: FileSystem Handler
|
|
4
|
-
|
|
4
|
+
contract_version:
|
|
5
|
+
major: 1
|
|
6
|
+
minor: 0
|
|
7
|
+
patch: 0
|
|
5
8
|
description: >
|
|
6
9
|
Effect handler for filesystem operations including read, write, list, delete, and directory management.
|
|
7
10
|
|
|
8
11
|
descriptor:
|
|
9
|
-
|
|
12
|
+
node_archetype: effect
|
|
10
13
|
purity: side_effecting
|
|
11
14
|
# Idempotent: false because write operations may append (non-idempotent).
|
|
12
15
|
# Individual operations (write w/ overwrite, mkdir w/ exist_ok) can be
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
# Handler ID follows convention: {node_type}.{domain}.handler
|
|
2
2
|
handler_id: effect.mcp.handler
|
|
3
3
|
name: MCP Handler
|
|
4
|
-
|
|
4
|
+
contract_version:
|
|
5
|
+
major: 1
|
|
6
|
+
minor: 0
|
|
7
|
+
patch: 0
|
|
5
8
|
description: >
|
|
6
9
|
Effect handler for Model Context Protocol (MCP) integration. Exposes ONEX nodes as MCP tools for AI agent integration via streamable HTTP transport.
|
|
7
10
|
|
|
8
11
|
descriptor:
|
|
9
|
-
|
|
12
|
+
node_archetype: effect
|
|
10
13
|
purity: side_effecting
|
|
11
14
|
# Idempotent: true for list_tools/describe, false for call_tool (depends on target)
|
|
12
15
|
# Overall handler is marked non-idempotent since tool execution may have side effects.
|
omnibase_infra/enums/__init__.py
CHANGED
|
@@ -23,11 +23,13 @@ Exports:
|
|
|
23
23
|
EnumHandlerErrorType: Handler error types for validation and lifecycle
|
|
24
24
|
EnumHandlerLoaderError: Handler loader error codes for plugin loading
|
|
25
25
|
EnumResponseStatus: Handler response status (SUCCESS, ERROR)
|
|
26
|
+
EnumHandlerSourceMode: Handler source modes for loading strategy (BOOTSTRAP, CONTRACT, HYBRID)
|
|
26
27
|
EnumHandlerSourceType: Handler validation error source types
|
|
27
28
|
EnumHandlerType: Handler architectural roles (INFRA_HANDLER, NODE_HANDLER)
|
|
28
29
|
EnumHandlerTypeCategory: Behavioral classification (COMPUTE, EFFECT)
|
|
29
30
|
EnumInfraTransportType: Infrastructure transport type enumeration
|
|
30
31
|
EnumIntrospectionReason: Introspection event reasons (STARTUP, SHUTDOWN, etc.)
|
|
32
|
+
EnumKafkaAcks: Kafka producer acknowledgment policy (ALL, NONE, LEADER, ALL_REPLICAS)
|
|
31
33
|
EnumMessageCategory: Message categories (EVENT, COMMAND, INTENT)
|
|
32
34
|
EnumNodeArchetype: 4-node architecture (EFFECT, COMPUTE, REDUCER, ORCHESTRATOR)
|
|
33
35
|
EnumNodeOutputType: Node output types for execution shape validation
|
|
@@ -61,11 +63,13 @@ from omnibase_infra.enums.enum_execution_shape_violation import (
|
|
|
61
63
|
)
|
|
62
64
|
from omnibase_infra.enums.enum_handler_error_type import EnumHandlerErrorType
|
|
63
65
|
from omnibase_infra.enums.enum_handler_loader_error import EnumHandlerLoaderError
|
|
66
|
+
from omnibase_infra.enums.enum_handler_source_mode import EnumHandlerSourceMode
|
|
64
67
|
from omnibase_infra.enums.enum_handler_source_type import EnumHandlerSourceType
|
|
65
68
|
from omnibase_infra.enums.enum_handler_type import EnumHandlerType
|
|
66
69
|
from omnibase_infra.enums.enum_handler_type_category import EnumHandlerTypeCategory
|
|
67
70
|
from omnibase_infra.enums.enum_infra_transport_type import EnumInfraTransportType
|
|
68
71
|
from omnibase_infra.enums.enum_introspection_reason import EnumIntrospectionReason
|
|
72
|
+
from omnibase_infra.enums.enum_kafka_acks import EnumKafkaAcks
|
|
69
73
|
from omnibase_infra.enums.enum_message_category import EnumMessageCategory
|
|
70
74
|
from omnibase_infra.enums.enum_node_archetype import EnumNodeArchetype
|
|
71
75
|
from omnibase_infra.enums.enum_node_output_type import EnumNodeOutputType
|
|
@@ -100,11 +104,13 @@ __all__: list[str] = [
|
|
|
100
104
|
"EnumExecutionShapeViolation",
|
|
101
105
|
"EnumHandlerErrorType",
|
|
102
106
|
"EnumHandlerLoaderError",
|
|
107
|
+
"EnumHandlerSourceMode",
|
|
103
108
|
"EnumHandlerSourceType",
|
|
104
109
|
"EnumHandlerType",
|
|
105
110
|
"EnumHandlerTypeCategory",
|
|
106
111
|
"EnumInfraTransportType",
|
|
107
112
|
"EnumIntrospectionReason",
|
|
113
|
+
"EnumKafkaAcks",
|
|
108
114
|
"EnumMessageCategory",
|
|
109
115
|
"EnumNodeArchetype",
|
|
110
116
|
"EnumNodeOutputType",
|
|
@@ -43,6 +43,13 @@ class EnumHandlerErrorType(str, Enum):
|
|
|
43
43
|
The parsed contract contains invalid field values or violates
|
|
44
44
|
schema constraints defined in the ONEX contract specification.
|
|
45
45
|
|
|
46
|
+
Discovery Errors:
|
|
47
|
+
DISCOVERY_ERROR: Handler discovery failed due to infrastructure issues.
|
|
48
|
+
The handler could not be discovered due to connection failures,
|
|
49
|
+
timeouts, or other infrastructure problems (e.g., Consul unavailable,
|
|
50
|
+
network errors). This is distinct from parse/validation errors which
|
|
51
|
+
occur AFTER the contract is successfully retrieved.
|
|
52
|
+
|
|
46
53
|
Validation Errors:
|
|
47
54
|
DESCRIPTOR_VALIDATION_ERROR: Handler descriptor validation failed.
|
|
48
55
|
The handler descriptor (metadata, annotations, signature) does not
|
|
@@ -80,6 +87,9 @@ class EnumHandlerErrorType(str, Enum):
|
|
|
80
87
|
CONTRACT_PARSE_ERROR = "contract_parse_error"
|
|
81
88
|
CONTRACT_VALIDATION_ERROR = "contract_validation_error"
|
|
82
89
|
|
|
90
|
+
# Discovery errors
|
|
91
|
+
DISCOVERY_ERROR = "discovery_error"
|
|
92
|
+
|
|
83
93
|
# Validation errors
|
|
84
94
|
DESCRIPTOR_VALIDATION_ERROR = "descriptor_validation_error"
|
|
85
95
|
SECURITY_VALIDATION_ERROR = "security_validation_error"
|