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.
Files changed (161) hide show
  1. omnibase_infra/__init__.py +1 -1
  2. omnibase_infra/adapters/adapter_onex_tool_execution.py +451 -0
  3. omnibase_infra/capabilities/__init__.py +15 -0
  4. omnibase_infra/capabilities/capability_inference_rules.py +211 -0
  5. omnibase_infra/capabilities/contract_capability_extractor.py +221 -0
  6. omnibase_infra/capabilities/intent_type_extractor.py +160 -0
  7. omnibase_infra/cli/commands.py +1 -1
  8. omnibase_infra/configs/widget_mapping.yaml +176 -0
  9. omnibase_infra/contracts/handlers/filesystem/handler_contract.yaml +5 -2
  10. omnibase_infra/contracts/handlers/mcp/handler_contract.yaml +5 -2
  11. omnibase_infra/enums/__init__.py +6 -0
  12. omnibase_infra/enums/enum_handler_error_type.py +10 -0
  13. omnibase_infra/enums/enum_handler_source_mode.py +72 -0
  14. omnibase_infra/enums/enum_kafka_acks.py +99 -0
  15. omnibase_infra/errors/error_compute_registry.py +4 -1
  16. omnibase_infra/errors/error_event_bus_registry.py +4 -1
  17. omnibase_infra/errors/error_infra.py +3 -1
  18. omnibase_infra/errors/error_policy_registry.py +4 -1
  19. omnibase_infra/event_bus/event_bus_kafka.py +1 -1
  20. omnibase_infra/event_bus/models/config/model_kafka_event_bus_config.py +59 -10
  21. omnibase_infra/handlers/__init__.py +8 -1
  22. omnibase_infra/handlers/handler_consul.py +7 -1
  23. omnibase_infra/handlers/handler_db.py +10 -3
  24. omnibase_infra/handlers/handler_graph.py +10 -5
  25. omnibase_infra/handlers/handler_http.py +8 -2
  26. omnibase_infra/handlers/handler_intent.py +387 -0
  27. omnibase_infra/handlers/handler_mcp.py +745 -63
  28. omnibase_infra/handlers/handler_vault.py +11 -5
  29. omnibase_infra/handlers/mixins/mixin_consul_kv.py +4 -3
  30. omnibase_infra/handlers/mixins/mixin_consul_service.py +2 -1
  31. omnibase_infra/handlers/registration_storage/handler_registration_storage_postgres.py +7 -0
  32. omnibase_infra/handlers/service_discovery/handler_service_discovery_consul.py +308 -4
  33. omnibase_infra/handlers/service_discovery/models/model_service_info.py +10 -0
  34. omnibase_infra/mixins/mixin_async_circuit_breaker.py +3 -2
  35. omnibase_infra/mixins/mixin_node_introspection.py +42 -7
  36. omnibase_infra/mixins/mixin_retry_execution.py +1 -1
  37. omnibase_infra/models/discovery/model_introspection_config.py +11 -0
  38. omnibase_infra/models/handlers/__init__.py +48 -5
  39. omnibase_infra/models/handlers/model_bootstrap_handler_descriptor.py +162 -0
  40. omnibase_infra/models/handlers/model_contract_discovery_result.py +6 -4
  41. omnibase_infra/models/handlers/model_handler_descriptor.py +15 -0
  42. omnibase_infra/models/handlers/model_handler_source_config.py +220 -0
  43. omnibase_infra/models/mcp/__init__.py +15 -0
  44. omnibase_infra/models/mcp/model_mcp_contract_config.py +80 -0
  45. omnibase_infra/models/mcp/model_mcp_server_config.py +67 -0
  46. omnibase_infra/models/mcp/model_mcp_tool_definition.py +73 -0
  47. omnibase_infra/models/mcp/model_mcp_tool_parameter.py +35 -0
  48. omnibase_infra/models/registration/model_node_capabilities.py +11 -0
  49. omnibase_infra/models/registration/model_node_introspection_event.py +9 -0
  50. omnibase_infra/models/runtime/model_handler_contract.py +25 -9
  51. omnibase_infra/models/runtime/model_loaded_handler.py +9 -0
  52. omnibase_infra/nodes/architecture_validator/contract_architecture_validator.yaml +0 -5
  53. omnibase_infra/nodes/architecture_validator/registry/registry_infra_architecture_validator.py +17 -10
  54. omnibase_infra/nodes/effects/contract.yaml +0 -5
  55. omnibase_infra/nodes/node_registration_orchestrator/contract.yaml +7 -0
  56. omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_introspected.py +86 -1
  57. omnibase_infra/nodes/node_registration_orchestrator/introspection_event_router.py +3 -3
  58. omnibase_infra/nodes/node_registration_orchestrator/plugin.py +1 -1
  59. omnibase_infra/nodes/node_registration_orchestrator/registry/registry_infra_node_registration_orchestrator.py +9 -8
  60. omnibase_infra/nodes/node_registration_orchestrator/timeout_coordinator.py +4 -3
  61. omnibase_infra/nodes/node_registration_orchestrator/wiring.py +14 -13
  62. omnibase_infra/nodes/node_registration_storage_effect/contract.yaml +0 -5
  63. omnibase_infra/nodes/node_registration_storage_effect/node.py +4 -1
  64. omnibase_infra/nodes/node_registration_storage_effect/registry/registry_infra_registration_storage.py +47 -26
  65. omnibase_infra/nodes/node_registry_effect/contract.yaml +0 -5
  66. omnibase_infra/nodes/node_registry_effect/handlers/handler_partial_retry.py +2 -1
  67. omnibase_infra/nodes/node_service_discovery_effect/registry/registry_infra_service_discovery.py +28 -20
  68. omnibase_infra/plugins/examples/plugin_json_normalizer.py +2 -2
  69. omnibase_infra/plugins/examples/plugin_json_normalizer_error_handling.py +2 -2
  70. omnibase_infra/plugins/plugin_compute_base.py +16 -2
  71. omnibase_infra/protocols/__init__.py +2 -0
  72. omnibase_infra/protocols/protocol_container_aware.py +200 -0
  73. omnibase_infra/protocols/protocol_event_projector.py +1 -1
  74. omnibase_infra/runtime/__init__.py +90 -1
  75. omnibase_infra/runtime/binding_config_resolver.py +102 -37
  76. omnibase_infra/runtime/constants_notification.py +75 -0
  77. omnibase_infra/runtime/contract_handler_discovery.py +6 -1
  78. omnibase_infra/runtime/handler_bootstrap_source.py +507 -0
  79. omnibase_infra/runtime/handler_contract_config_loader.py +603 -0
  80. omnibase_infra/runtime/handler_contract_source.py +267 -186
  81. omnibase_infra/runtime/handler_identity.py +81 -0
  82. omnibase_infra/runtime/handler_plugin_loader.py +19 -2
  83. omnibase_infra/runtime/handler_registry.py +11 -3
  84. omnibase_infra/runtime/handler_source_resolver.py +326 -0
  85. omnibase_infra/runtime/mixin_semver_cache.py +25 -1
  86. omnibase_infra/runtime/mixins/__init__.py +7 -0
  87. omnibase_infra/runtime/mixins/mixin_projector_notification_publishing.py +566 -0
  88. omnibase_infra/runtime/mixins/mixin_projector_sql_operations.py +31 -10
  89. omnibase_infra/runtime/models/__init__.py +24 -0
  90. omnibase_infra/runtime/models/model_health_check_result.py +2 -1
  91. omnibase_infra/runtime/models/model_projector_notification_config.py +171 -0
  92. omnibase_infra/runtime/models/model_transition_notification_outbox_config.py +112 -0
  93. omnibase_infra/runtime/models/model_transition_notification_outbox_metrics.py +140 -0
  94. omnibase_infra/runtime/models/model_transition_notification_publisher_metrics.py +357 -0
  95. omnibase_infra/runtime/projector_plugin_loader.py +1 -1
  96. omnibase_infra/runtime/projector_shell.py +229 -1
  97. omnibase_infra/runtime/protocol_lifecycle_executor.py +6 -6
  98. omnibase_infra/runtime/protocols/__init__.py +10 -0
  99. omnibase_infra/runtime/registry/registry_protocol_binding.py +16 -15
  100. omnibase_infra/runtime/registry_contract_source.py +693 -0
  101. omnibase_infra/runtime/registry_policy.py +9 -326
  102. omnibase_infra/runtime/secret_resolver.py +4 -2
  103. omnibase_infra/runtime/service_kernel.py +11 -3
  104. omnibase_infra/runtime/service_message_dispatch_engine.py +4 -2
  105. omnibase_infra/runtime/service_runtime_host_process.py +589 -106
  106. omnibase_infra/runtime/transition_notification_outbox.py +1190 -0
  107. omnibase_infra/runtime/transition_notification_publisher.py +764 -0
  108. omnibase_infra/runtime/util_container_wiring.py +6 -5
  109. omnibase_infra/runtime/util_wiring.py +17 -4
  110. omnibase_infra/schemas/schema_transition_notification_outbox.sql +245 -0
  111. omnibase_infra/services/__init__.py +21 -0
  112. omnibase_infra/services/corpus_capture.py +7 -1
  113. omnibase_infra/services/mcp/__init__.py +31 -0
  114. omnibase_infra/services/mcp/mcp_server_lifecycle.py +449 -0
  115. omnibase_infra/services/mcp/service_mcp_tool_discovery.py +411 -0
  116. omnibase_infra/services/mcp/service_mcp_tool_registry.py +329 -0
  117. omnibase_infra/services/mcp/service_mcp_tool_sync.py +547 -0
  118. omnibase_infra/services/registry_api/__init__.py +40 -0
  119. omnibase_infra/services/registry_api/main.py +261 -0
  120. omnibase_infra/services/registry_api/models/__init__.py +66 -0
  121. omnibase_infra/services/registry_api/models/model_capability_widget_mapping.py +38 -0
  122. omnibase_infra/services/registry_api/models/model_pagination_info.py +48 -0
  123. omnibase_infra/services/registry_api/models/model_registry_discovery_response.py +73 -0
  124. omnibase_infra/services/registry_api/models/model_registry_health_response.py +49 -0
  125. omnibase_infra/services/registry_api/models/model_registry_instance_view.py +88 -0
  126. omnibase_infra/services/registry_api/models/model_registry_node_view.py +88 -0
  127. omnibase_infra/services/registry_api/models/model_registry_summary.py +60 -0
  128. omnibase_infra/services/registry_api/models/model_response_list_instances.py +43 -0
  129. omnibase_infra/services/registry_api/models/model_response_list_nodes.py +51 -0
  130. omnibase_infra/services/registry_api/models/model_warning.py +49 -0
  131. omnibase_infra/services/registry_api/models/model_widget_defaults.py +28 -0
  132. omnibase_infra/services/registry_api/models/model_widget_mapping.py +51 -0
  133. omnibase_infra/services/registry_api/routes.py +371 -0
  134. omnibase_infra/services/registry_api/service.py +837 -0
  135. omnibase_infra/services/service_capability_query.py +4 -4
  136. omnibase_infra/services/service_health.py +3 -2
  137. omnibase_infra/services/service_timeout_emitter.py +20 -3
  138. omnibase_infra/services/service_timeout_scanner.py +7 -3
  139. omnibase_infra/services/session/__init__.py +56 -0
  140. omnibase_infra/services/session/config_consumer.py +120 -0
  141. omnibase_infra/services/session/config_store.py +139 -0
  142. omnibase_infra/services/session/consumer.py +1007 -0
  143. omnibase_infra/services/session/protocol_session_aggregator.py +117 -0
  144. omnibase_infra/services/session/store.py +997 -0
  145. omnibase_infra/utils/__init__.py +19 -0
  146. omnibase_infra/utils/util_atomic_file.py +261 -0
  147. omnibase_infra/utils/util_db_transaction.py +239 -0
  148. omnibase_infra/utils/util_dsn_validation.py +1 -1
  149. omnibase_infra/utils/util_retry_optimistic.py +281 -0
  150. omnibase_infra/validation/__init__.py +3 -19
  151. omnibase_infra/validation/contracts/security.validation.yaml +114 -0
  152. omnibase_infra/validation/infra_validators.py +35 -24
  153. omnibase_infra/validation/validation_exemptions.yaml +140 -9
  154. omnibase_infra/validation/validator_chain_propagation.py +2 -2
  155. omnibase_infra/validation/validator_runtime_shape.py +1 -1
  156. omnibase_infra/validation/validator_security.py +473 -370
  157. {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.3.dist-info}/METADATA +3 -3
  158. {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.3.dist-info}/RECORD +161 -98
  159. {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.3.dist-info}/WHEEL +0 -0
  160. {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.3.dist-info}/entry_points.txt +0 -0
  161. {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
@@ -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
- # ModelModuleImportResult uses has_circular_imports property
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
- version: "1.0.0"
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
- handler_kind: effect
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
- version: "1.0.0"
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
- handler_kind: effect
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.
@@ -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"