omnibase_infra 0.2.1__py3-none-any.whl → 0.2.2__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 (116) hide show
  1. omnibase_infra/__init__.py +1 -1
  2. omnibase_infra/adapters/adapter_onex_tool_execution.py +446 -0
  3. omnibase_infra/cli/commands.py +1 -1
  4. omnibase_infra/configs/widget_mapping.yaml +176 -0
  5. omnibase_infra/contracts/handlers/filesystem/handler_contract.yaml +4 -1
  6. omnibase_infra/contracts/handlers/mcp/handler_contract.yaml +4 -1
  7. omnibase_infra/errors/error_compute_registry.py +4 -1
  8. omnibase_infra/errors/error_event_bus_registry.py +4 -1
  9. omnibase_infra/errors/error_infra.py +3 -1
  10. omnibase_infra/errors/error_policy_registry.py +4 -1
  11. omnibase_infra/handlers/handler_db.py +2 -1
  12. omnibase_infra/handlers/handler_graph.py +10 -5
  13. omnibase_infra/handlers/handler_mcp.py +736 -63
  14. omnibase_infra/handlers/mixins/mixin_consul_kv.py +4 -3
  15. omnibase_infra/handlers/mixins/mixin_consul_service.py +2 -1
  16. omnibase_infra/handlers/service_discovery/handler_service_discovery_consul.py +301 -4
  17. omnibase_infra/handlers/service_discovery/models/model_service_info.py +10 -0
  18. omnibase_infra/mixins/mixin_async_circuit_breaker.py +3 -2
  19. omnibase_infra/mixins/mixin_node_introspection.py +24 -7
  20. omnibase_infra/mixins/mixin_retry_execution.py +1 -1
  21. omnibase_infra/models/handlers/__init__.py +10 -0
  22. omnibase_infra/models/handlers/model_bootstrap_handler_descriptor.py +162 -0
  23. omnibase_infra/models/handlers/model_handler_descriptor.py +15 -0
  24. omnibase_infra/models/mcp/__init__.py +15 -0
  25. omnibase_infra/models/mcp/model_mcp_contract_config.py +80 -0
  26. omnibase_infra/models/mcp/model_mcp_server_config.py +67 -0
  27. omnibase_infra/models/mcp/model_mcp_tool_definition.py +73 -0
  28. omnibase_infra/models/mcp/model_mcp_tool_parameter.py +35 -0
  29. omnibase_infra/models/registration/model_node_capabilities.py +11 -0
  30. omnibase_infra/nodes/architecture_validator/contract_architecture_validator.yaml +0 -5
  31. omnibase_infra/nodes/architecture_validator/registry/registry_infra_architecture_validator.py +17 -10
  32. omnibase_infra/nodes/effects/contract.yaml +0 -5
  33. omnibase_infra/nodes/node_registration_orchestrator/contract.yaml +7 -0
  34. omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_introspected.py +86 -1
  35. omnibase_infra/nodes/node_registration_orchestrator/introspection_event_router.py +3 -3
  36. omnibase_infra/nodes/node_registration_orchestrator/registry/registry_infra_node_registration_orchestrator.py +9 -8
  37. omnibase_infra/nodes/node_registration_orchestrator/wiring.py +14 -13
  38. omnibase_infra/nodes/node_registration_storage_effect/contract.yaml +0 -5
  39. omnibase_infra/nodes/node_registration_storage_effect/registry/registry_infra_registration_storage.py +46 -25
  40. omnibase_infra/nodes/node_registry_effect/contract.yaml +0 -5
  41. omnibase_infra/nodes/node_registry_effect/handlers/handler_partial_retry.py +2 -1
  42. omnibase_infra/nodes/node_service_discovery_effect/registry/registry_infra_service_discovery.py +24 -19
  43. omnibase_infra/plugins/examples/plugin_json_normalizer.py +2 -2
  44. omnibase_infra/plugins/examples/plugin_json_normalizer_error_handling.py +2 -2
  45. omnibase_infra/plugins/plugin_compute_base.py +16 -2
  46. omnibase_infra/protocols/protocol_event_projector.py +1 -1
  47. omnibase_infra/runtime/__init__.py +51 -1
  48. omnibase_infra/runtime/binding_config_resolver.py +102 -37
  49. omnibase_infra/runtime/constants_notification.py +75 -0
  50. omnibase_infra/runtime/contract_handler_discovery.py +6 -1
  51. omnibase_infra/runtime/handler_bootstrap_source.py +514 -0
  52. omnibase_infra/runtime/handler_contract_config_loader.py +603 -0
  53. omnibase_infra/runtime/handler_contract_source.py +289 -167
  54. omnibase_infra/runtime/handler_plugin_loader.py +4 -2
  55. omnibase_infra/runtime/mixin_semver_cache.py +25 -1
  56. omnibase_infra/runtime/mixins/__init__.py +7 -0
  57. omnibase_infra/runtime/mixins/mixin_projector_notification_publishing.py +566 -0
  58. omnibase_infra/runtime/mixins/mixin_projector_sql_operations.py +31 -10
  59. omnibase_infra/runtime/models/__init__.py +24 -0
  60. omnibase_infra/runtime/models/model_health_check_result.py +2 -1
  61. omnibase_infra/runtime/models/model_projector_notification_config.py +171 -0
  62. omnibase_infra/runtime/models/model_transition_notification_outbox_config.py +112 -0
  63. omnibase_infra/runtime/models/model_transition_notification_outbox_metrics.py +140 -0
  64. omnibase_infra/runtime/models/model_transition_notification_publisher_metrics.py +357 -0
  65. omnibase_infra/runtime/projector_plugin_loader.py +1 -1
  66. omnibase_infra/runtime/projector_shell.py +229 -1
  67. omnibase_infra/runtime/protocols/__init__.py +10 -0
  68. omnibase_infra/runtime/registry/registry_protocol_binding.py +3 -2
  69. omnibase_infra/runtime/registry_policy.py +9 -326
  70. omnibase_infra/runtime/secret_resolver.py +4 -2
  71. omnibase_infra/runtime/service_kernel.py +10 -2
  72. omnibase_infra/runtime/service_message_dispatch_engine.py +4 -2
  73. omnibase_infra/runtime/service_runtime_host_process.py +225 -15
  74. omnibase_infra/runtime/transition_notification_outbox.py +1190 -0
  75. omnibase_infra/runtime/transition_notification_publisher.py +764 -0
  76. omnibase_infra/runtime/util_container_wiring.py +6 -5
  77. omnibase_infra/runtime/util_wiring.py +5 -1
  78. omnibase_infra/schemas/schema_transition_notification_outbox.sql +245 -0
  79. omnibase_infra/services/mcp/__init__.py +31 -0
  80. omnibase_infra/services/mcp/mcp_server_lifecycle.py +443 -0
  81. omnibase_infra/services/mcp/service_mcp_tool_discovery.py +411 -0
  82. omnibase_infra/services/mcp/service_mcp_tool_registry.py +329 -0
  83. omnibase_infra/services/mcp/service_mcp_tool_sync.py +547 -0
  84. omnibase_infra/services/registry_api/__init__.py +40 -0
  85. omnibase_infra/services/registry_api/main.py +243 -0
  86. omnibase_infra/services/registry_api/models/__init__.py +66 -0
  87. omnibase_infra/services/registry_api/models/model_capability_widget_mapping.py +38 -0
  88. omnibase_infra/services/registry_api/models/model_pagination_info.py +48 -0
  89. omnibase_infra/services/registry_api/models/model_registry_discovery_response.py +73 -0
  90. omnibase_infra/services/registry_api/models/model_registry_health_response.py +49 -0
  91. omnibase_infra/services/registry_api/models/model_registry_instance_view.py +88 -0
  92. omnibase_infra/services/registry_api/models/model_registry_node_view.py +88 -0
  93. omnibase_infra/services/registry_api/models/model_registry_summary.py +60 -0
  94. omnibase_infra/services/registry_api/models/model_response_list_instances.py +43 -0
  95. omnibase_infra/services/registry_api/models/model_response_list_nodes.py +51 -0
  96. omnibase_infra/services/registry_api/models/model_warning.py +49 -0
  97. omnibase_infra/services/registry_api/models/model_widget_defaults.py +28 -0
  98. omnibase_infra/services/registry_api/models/model_widget_mapping.py +51 -0
  99. omnibase_infra/services/registry_api/routes.py +371 -0
  100. omnibase_infra/services/registry_api/service.py +846 -0
  101. omnibase_infra/services/service_capability_query.py +4 -4
  102. omnibase_infra/services/service_health.py +3 -2
  103. omnibase_infra/services/service_timeout_emitter.py +13 -2
  104. omnibase_infra/utils/util_dsn_validation.py +1 -1
  105. omnibase_infra/validation/__init__.py +3 -19
  106. omnibase_infra/validation/contracts/security.validation.yaml +114 -0
  107. omnibase_infra/validation/infra_validators.py +35 -24
  108. omnibase_infra/validation/validation_exemptions.yaml +113 -9
  109. omnibase_infra/validation/validator_chain_propagation.py +2 -2
  110. omnibase_infra/validation/validator_runtime_shape.py +1 -1
  111. omnibase_infra/validation/validator_security.py +473 -370
  112. {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.2.dist-info}/METADATA +2 -2
  113. {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.2.dist-info}/RECORD +116 -74
  114. {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.2.dist-info}/WHEEL +0 -0
  115. {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.2.dist-info}/entry_points.txt +0 -0
  116. {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.2.dist-info}/licenses/LICENSE +0 -0
@@ -76,7 +76,7 @@ See Also
76
76
  - Runtime kernel: omnibase_infra.runtime.service_kernel
77
77
  """
78
78
 
79
- __version__ = "0.2.1"
79
+ __version__ = "0.2.2"
80
80
 
81
81
  from . import (
82
82
  enums,
@@ -0,0 +1,446 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2025 OmniNode Team
3
+ """ONEX Tool Execution Adapter - Bridges MCP tool calls to ONEX orchestrator execution.
4
+
5
+ This adapter handles the execution of MCP tool invocations by:
6
+ 1. Validating input arguments against the tool's input schema
7
+ 2. Building an ONEX envelope with the input payload
8
+ 3. Dispatching to the orchestrator endpoint via HTTP
9
+ 4. Transforming the response to MCP format
10
+
11
+ Routing:
12
+ The adapter uses the tool definition's endpoint or service_id to locate
13
+ the target orchestrator. It supports both direct HTTP dispatch and
14
+ service discovery via Consul.
15
+
16
+ Timeout Handling:
17
+ Each tool definition includes a timeout_seconds value. The adapter
18
+ enforces this timeout when dispatching to the orchestrator, raising
19
+ InfraTimeoutError if exceeded.
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import asyncio
25
+ import logging
26
+ from typing import TYPE_CHECKING
27
+ from uuid import UUID, uuid4
28
+
29
+ import httpx
30
+
31
+ from omnibase_infra.enums import EnumInfraTransportType
32
+ from omnibase_infra.errors import (
33
+ InfraConnectionError,
34
+ InfraTimeoutError,
35
+ InfraUnavailableError,
36
+ ModelInfraErrorContext,
37
+ ModelTimeoutErrorContext,
38
+ )
39
+ from omnibase_infra.mixins import MixinAsyncCircuitBreaker
40
+
41
+ if TYPE_CHECKING:
42
+ from omnibase_infra.models.mcp.model_mcp_tool_definition import (
43
+ ModelMCPToolDefinition,
44
+ )
45
+
46
+ logger = logging.getLogger(__name__)
47
+
48
+
49
+ class AdapterONEXToolExecution(MixinAsyncCircuitBreaker):
50
+ """Bridges MCP tool calls to ONEX orchestrator execution.
51
+
52
+ This adapter handles the dispatch of MCP tool invocations to the
53
+ appropriate ONEX orchestrator node. It supports:
54
+ - Direct HTTP dispatch to orchestrator endpoint
55
+ - Input validation against JSON Schema
56
+ - Timeout enforcement
57
+ - Error transformation to MCP format
58
+ - Circuit breaker protection for external HTTP calls
59
+
60
+ Attributes:
61
+ _http_client: HTTP client for orchestrator dispatch.
62
+ _default_timeout: Default timeout if tool definition doesn't specify one.
63
+
64
+ Example:
65
+ >>> adapter = AdapterONEXToolExecution()
66
+ >>> result = await adapter.execute(
67
+ ... tool=tool_definition,
68
+ ... arguments={"input_data": "test"},
69
+ ... correlation_id=uuid4(),
70
+ ... )
71
+ >>> print(result["success"])
72
+ True
73
+ """
74
+
75
+ def __init__(
76
+ self,
77
+ http_client: httpx.AsyncClient | None = None,
78
+ default_timeout: float = 30.0,
79
+ circuit_breaker_threshold: int = 5,
80
+ circuit_breaker_reset_timeout: float = 60.0,
81
+ ) -> None:
82
+ """Initialize the execution adapter.
83
+
84
+ Args:
85
+ http_client: Optional HTTP client. If not provided, one will be
86
+ created during execute() calls.
87
+ default_timeout: Default timeout in seconds for orchestrator calls.
88
+ circuit_breaker_threshold: Max failures before opening circuit (default: 5).
89
+ circuit_breaker_reset_timeout: Seconds before automatic reset (default: 60.0).
90
+ """
91
+ self._http_client = http_client
92
+ self._default_timeout = default_timeout
93
+ self._owns_client = http_client is None
94
+
95
+ # Initialize circuit breaker for HTTP dispatch resilience
96
+ self._init_circuit_breaker(
97
+ threshold=circuit_breaker_threshold,
98
+ reset_timeout=circuit_breaker_reset_timeout,
99
+ service_name="onex-tool-execution",
100
+ transport_type=EnumInfraTransportType.HTTP,
101
+ )
102
+
103
+ logger.debug(
104
+ "AdapterONEXToolExecution initialized",
105
+ extra={
106
+ "default_timeout": default_timeout,
107
+ "circuit_breaker_threshold": circuit_breaker_threshold,
108
+ "circuit_breaker_reset_timeout": circuit_breaker_reset_timeout,
109
+ },
110
+ )
111
+
112
+ async def execute(
113
+ self,
114
+ tool: ModelMCPToolDefinition,
115
+ arguments: dict[str, object],
116
+ correlation_id: UUID,
117
+ ) -> dict[str, object]:
118
+ """Execute an MCP tool call by dispatching to the ONEX orchestrator.
119
+
120
+ Args:
121
+ tool: Tool definition containing endpoint, timeout, and metadata.
122
+ arguments: Input arguments from the MCP tool call.
123
+ correlation_id: Correlation ID for tracing.
124
+
125
+ Returns:
126
+ Dictionary with execution result:
127
+ - success: True if execution succeeded
128
+ - result: Orchestrator response (if successful)
129
+ - error: Error message (if failed)
130
+
131
+ Raises:
132
+ InfraUnavailableError: If tool endpoint is not configured.
133
+ InfraTimeoutError: If execution times out.
134
+ InfraConnectionError: If connection to orchestrator fails.
135
+ """
136
+ logger.info(
137
+ "Executing MCP tool",
138
+ extra={
139
+ "tool_name": tool.name,
140
+ "correlation_id": str(correlation_id),
141
+ },
142
+ )
143
+
144
+ # Validate endpoint
145
+ endpoint = tool.endpoint
146
+ if not endpoint:
147
+ ctx = ModelInfraErrorContext.with_correlation(
148
+ correlation_id=correlation_id,
149
+ transport_type=EnumInfraTransportType.HTTP,
150
+ operation="execute_tool",
151
+ target_name=tool.name,
152
+ )
153
+ raise InfraUnavailableError(
154
+ f"Tool '{tool.name}' has no endpoint configured",
155
+ context=ctx,
156
+ )
157
+
158
+ # Build envelope payload
159
+ envelope = self._build_envelope(tool, arguments, correlation_id)
160
+
161
+ # Determine timeout
162
+ timeout = tool.timeout_seconds or self._default_timeout
163
+
164
+ # Check circuit breaker before dispatch
165
+ try:
166
+ async with self._circuit_breaker_lock:
167
+ await self._check_circuit_breaker(
168
+ operation="execute_tool",
169
+ correlation_id=correlation_id,
170
+ )
171
+ except InfraUnavailableError:
172
+ logger.warning(
173
+ "MCP tool execution blocked - circuit breaker open",
174
+ extra={
175
+ "tool_name": tool.name,
176
+ "correlation_id": str(correlation_id),
177
+ },
178
+ )
179
+ return {
180
+ "success": False,
181
+ "error": "Service temporarily unavailable - circuit breaker open",
182
+ }
183
+
184
+ # Dispatch to orchestrator
185
+ try:
186
+ result = await self._http_dispatch(
187
+ endpoint=endpoint,
188
+ envelope=envelope,
189
+ timeout=timeout,
190
+ correlation_id=correlation_id,
191
+ )
192
+
193
+ # Record success to reset circuit breaker
194
+ async with self._circuit_breaker_lock:
195
+ await self._reset_circuit_breaker()
196
+
197
+ logger.info(
198
+ "MCP tool execution succeeded",
199
+ extra={
200
+ "tool_name": tool.name,
201
+ "correlation_id": str(correlation_id),
202
+ },
203
+ )
204
+
205
+ return {
206
+ "success": True,
207
+ "result": result,
208
+ }
209
+
210
+ except InfraTimeoutError:
211
+ # Record failure to potentially open circuit breaker
212
+ async with self._circuit_breaker_lock:
213
+ await self._record_circuit_failure(
214
+ operation="execute_tool",
215
+ correlation_id=correlation_id,
216
+ )
217
+ logger.warning(
218
+ "MCP tool execution timed out",
219
+ extra={
220
+ "tool_name": tool.name,
221
+ "timeout": timeout,
222
+ "correlation_id": str(correlation_id),
223
+ },
224
+ )
225
+ return {
226
+ "success": False,
227
+ "error": f"Tool execution timed out after {timeout} seconds",
228
+ }
229
+
230
+ except InfraConnectionError as e:
231
+ # Record failure to potentially open circuit breaker
232
+ async with self._circuit_breaker_lock:
233
+ await self._record_circuit_failure(
234
+ operation="execute_tool",
235
+ correlation_id=correlation_id,
236
+ )
237
+ logger.warning(
238
+ "MCP tool execution failed - connection error",
239
+ extra={
240
+ "tool_name": tool.name,
241
+ "error": str(e),
242
+ "correlation_id": str(correlation_id),
243
+ },
244
+ )
245
+ return {
246
+ "success": False,
247
+ "error": f"Connection error: {e}",
248
+ }
249
+
250
+ except Exception as e:
251
+ # Record failure to potentially open circuit breaker
252
+ async with self._circuit_breaker_lock:
253
+ await self._record_circuit_failure(
254
+ operation="execute_tool",
255
+ correlation_id=correlation_id,
256
+ )
257
+ logger.exception(
258
+ "MCP tool execution failed - unexpected error",
259
+ extra={
260
+ "tool_name": tool.name,
261
+ "error": str(e),
262
+ "correlation_id": str(correlation_id),
263
+ },
264
+ )
265
+ return {
266
+ "success": False,
267
+ "error": f"Unexpected error: {e}",
268
+ }
269
+
270
+ def _build_envelope(
271
+ self,
272
+ tool: ModelMCPToolDefinition,
273
+ arguments: dict[str, object],
274
+ correlation_id: UUID,
275
+ ) -> dict[str, object]:
276
+ """Build an ONEX envelope for the orchestrator.
277
+
278
+ Args:
279
+ tool: Tool definition.
280
+ arguments: Input arguments from MCP.
281
+ correlation_id: Correlation ID.
282
+
283
+ Returns:
284
+ Envelope dict for the orchestrator.
285
+ """
286
+ return {
287
+ "envelope_id": str(uuid4()),
288
+ "correlation_id": str(correlation_id),
289
+ "source": "mcp-adapter",
290
+ "payload": arguments,
291
+ "metadata": {
292
+ "tool_name": tool.name,
293
+ "tool_version": tool.version,
294
+ },
295
+ }
296
+
297
+ async def _http_dispatch(
298
+ self,
299
+ endpoint: str,
300
+ envelope: dict[str, object],
301
+ timeout: float,
302
+ correlation_id: UUID,
303
+ ) -> dict[str, object]:
304
+ """Dispatch envelope to orchestrator endpoint via HTTP.
305
+
306
+ Args:
307
+ endpoint: Target endpoint URL.
308
+ envelope: Request envelope.
309
+ timeout: Request timeout in seconds.
310
+ correlation_id: Correlation ID.
311
+
312
+ Returns:
313
+ Response from orchestrator.
314
+
315
+ Raises:
316
+ InfraTimeoutError: If request times out.
317
+ InfraConnectionError: If connection fails.
318
+ """
319
+ # Use provided client or create one
320
+ if self._http_client is not None:
321
+ return await self._dispatch_with_client(
322
+ self._http_client,
323
+ endpoint,
324
+ envelope,
325
+ timeout,
326
+ correlation_id,
327
+ )
328
+ else:
329
+ # Create temporary client
330
+ async with httpx.AsyncClient() as client:
331
+ return await self._dispatch_with_client(
332
+ client,
333
+ endpoint,
334
+ envelope,
335
+ timeout,
336
+ correlation_id,
337
+ )
338
+
339
+ async def _dispatch_with_client(
340
+ self,
341
+ client: httpx.AsyncClient,
342
+ endpoint: str,
343
+ envelope: dict[str, object],
344
+ timeout: float,
345
+ correlation_id: UUID,
346
+ ) -> dict[str, object]:
347
+ """Dispatch using the provided HTTP client.
348
+
349
+ Args:
350
+ client: HTTP client.
351
+ endpoint: Target endpoint URL.
352
+ envelope: Request envelope.
353
+ timeout: Request timeout in seconds.
354
+ correlation_id: Correlation ID.
355
+
356
+ Returns:
357
+ Response from orchestrator.
358
+
359
+ Raises:
360
+ InfraTimeoutError: If request times out.
361
+ InfraConnectionError: If connection fails.
362
+ """
363
+ try:
364
+ response = await asyncio.wait_for(
365
+ client.post(
366
+ endpoint,
367
+ json=envelope,
368
+ headers={
369
+ "X-Correlation-ID": str(correlation_id),
370
+ "Content-Type": "application/json",
371
+ },
372
+ timeout=timeout,
373
+ ),
374
+ timeout=timeout,
375
+ )
376
+
377
+ response.raise_for_status()
378
+ result: dict[str, object] = response.json()
379
+ return result
380
+
381
+ except TimeoutError as e:
382
+ timeout_ctx = ModelTimeoutErrorContext(
383
+ transport_type=EnumInfraTransportType.HTTP,
384
+ operation="http_dispatch",
385
+ target_name=endpoint,
386
+ correlation_id=correlation_id,
387
+ timeout_seconds=timeout,
388
+ )
389
+ raise InfraTimeoutError(
390
+ f"Timeout dispatching to {endpoint} after {timeout}s",
391
+ context=timeout_ctx,
392
+ ) from e
393
+
394
+ except httpx.ConnectError as e:
395
+ ctx = ModelInfraErrorContext.with_correlation(
396
+ correlation_id=correlation_id,
397
+ transport_type=EnumInfraTransportType.HTTP,
398
+ operation="http_dispatch",
399
+ target_name=endpoint,
400
+ )
401
+ raise InfraConnectionError(
402
+ f"Connection failed to {endpoint}: {e}",
403
+ context=ctx,
404
+ ) from e
405
+
406
+ except httpx.HTTPStatusError as e:
407
+ ctx = ModelInfraErrorContext.with_correlation(
408
+ correlation_id=correlation_id,
409
+ transport_type=EnumInfraTransportType.HTTP,
410
+ operation="http_dispatch",
411
+ target_name=endpoint,
412
+ )
413
+ raise InfraConnectionError(
414
+ f"HTTP error from {endpoint}: {e.response.status_code}",
415
+ context=ctx,
416
+ ) from e
417
+
418
+ except Exception as e:
419
+ ctx = ModelInfraErrorContext.with_correlation(
420
+ correlation_id=correlation_id,
421
+ transport_type=EnumInfraTransportType.HTTP,
422
+ operation="http_dispatch",
423
+ target_name=endpoint,
424
+ )
425
+ raise InfraConnectionError(
426
+ f"Request to {endpoint} failed: {e}",
427
+ context=ctx,
428
+ ) from e
429
+
430
+ async def close(self) -> None:
431
+ """Close the HTTP client if owned by this adapter."""
432
+ if self._owns_client and self._http_client is not None:
433
+ await self._http_client.aclose()
434
+ self._http_client = None
435
+
436
+ def describe(self) -> dict[str, object]:
437
+ """Return adapter metadata for observability."""
438
+ return {
439
+ "adapter_name": "AdapterONEXToolExecution",
440
+ "default_timeout": self._default_timeout,
441
+ "owns_client": self._owns_client,
442
+ "circuit_breaker": self._get_circuit_breaker_state(),
443
+ }
444
+
445
+
446
+ __all__ = ["AdapterONEXToolExecution"]
@@ -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,7 +1,10 @@
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
 
@@ -1,7 +1,10 @@
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
 
@@ -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