omnibase_infra 0.2.6__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 +101 -0
- 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/__init__.py +1 -0
- omnibase_infra/cli/commands.py +216 -0
- omnibase_infra/clients/__init__.py +0 -0
- omnibase_infra/configs/widget_mapping.yaml +176 -0
- omnibase_infra/constants_topic_patterns.py +26 -0
- omnibase_infra/contracts/handlers/filesystem/handler_contract.yaml +264 -0
- omnibase_infra/contracts/handlers/mcp/handler_contract.yaml +141 -0
- omnibase_infra/decorators/__init__.py +29 -0
- omnibase_infra/decorators/allow_any.py +109 -0
- omnibase_infra/dlq/__init__.py +90 -0
- omnibase_infra/dlq/constants_dlq.py +57 -0
- omnibase_infra/dlq/models/__init__.py +26 -0
- omnibase_infra/dlq/models/enum_replay_status.py +37 -0
- omnibase_infra/dlq/models/model_dlq_replay_record.py +135 -0
- omnibase_infra/dlq/models/model_dlq_tracking_config.py +184 -0
- omnibase_infra/dlq/service_dlq_tracking.py +611 -0
- omnibase_infra/enums/__init__.py +132 -0
- omnibase_infra/enums/enum_any_type_violation.py +104 -0
- omnibase_infra/enums/enum_backend_type.py +27 -0
- omnibase_infra/enums/enum_capture_outcome.py +42 -0
- omnibase_infra/enums/enum_capture_state.py +88 -0
- omnibase_infra/enums/enum_chain_violation_type.py +119 -0
- omnibase_infra/enums/enum_circuit_state.py +51 -0
- omnibase_infra/enums/enum_confirmation_event_type.py +27 -0
- omnibase_infra/enums/enum_consumer_group_purpose.py +92 -0
- omnibase_infra/enums/enum_contract_type.py +84 -0
- omnibase_infra/enums/enum_dedupe_strategy.py +46 -0
- omnibase_infra/enums/enum_dispatch_status.py +191 -0
- omnibase_infra/enums/enum_environment.py +46 -0
- omnibase_infra/enums/enum_execution_shape_violation.py +103 -0
- omnibase_infra/enums/enum_handler_error_type.py +111 -0
- omnibase_infra/enums/enum_handler_loader_error.py +178 -0
- omnibase_infra/enums/enum_handler_source_mode.py +86 -0
- omnibase_infra/enums/enum_handler_source_type.py +87 -0
- omnibase_infra/enums/enum_handler_type.py +77 -0
- omnibase_infra/enums/enum_handler_type_category.py +61 -0
- omnibase_infra/enums/enum_infra_transport_type.py +73 -0
- omnibase_infra/enums/enum_introspection_reason.py +154 -0
- omnibase_infra/enums/enum_kafka_acks.py +99 -0
- omnibase_infra/enums/enum_message_category.py +213 -0
- omnibase_infra/enums/enum_node_archetype.py +74 -0
- omnibase_infra/enums/enum_node_output_type.py +185 -0
- omnibase_infra/enums/enum_non_retryable_error_category.py +224 -0
- omnibase_infra/enums/enum_policy_type.py +32 -0
- omnibase_infra/enums/enum_registration_state.py +261 -0
- omnibase_infra/enums/enum_registration_status.py +33 -0
- omnibase_infra/enums/enum_registry_response_status.py +28 -0
- omnibase_infra/enums/enum_response_status.py +26 -0
- omnibase_infra/enums/enum_retry_error_category.py +98 -0
- omnibase_infra/enums/enum_security_rule_id.py +103 -0
- omnibase_infra/enums/enum_selection_strategy.py +91 -0
- omnibase_infra/enums/enum_topic_standard.py +42 -0
- omnibase_infra/enums/enum_validation_severity.py +78 -0
- omnibase_infra/errors/__init__.py +160 -0
- omnibase_infra/errors/error_architecture_violation.py +152 -0
- omnibase_infra/errors/error_binding_resolution.py +128 -0
- omnibase_infra/errors/error_chain_propagation.py +188 -0
- omnibase_infra/errors/error_compute_registry.py +95 -0
- omnibase_infra/errors/error_consul.py +132 -0
- omnibase_infra/errors/error_container_wiring.py +243 -0
- omnibase_infra/errors/error_event_bus_registry.py +105 -0
- omnibase_infra/errors/error_infra.py +610 -0
- omnibase_infra/errors/error_message_type_registry.py +101 -0
- omnibase_infra/errors/error_policy_registry.py +115 -0
- omnibase_infra/errors/error_vault.py +123 -0
- omnibase_infra/event_bus/__init__.py +72 -0
- omnibase_infra/event_bus/configs/kafka_event_bus_config.yaml +84 -0
- omnibase_infra/event_bus/event_bus_inmemory.py +797 -0
- omnibase_infra/event_bus/event_bus_kafka.py +1716 -0
- omnibase_infra/event_bus/mixin_kafka_broadcast.py +180 -0
- omnibase_infra/event_bus/mixin_kafka_dlq.py +771 -0
- omnibase_infra/event_bus/models/__init__.py +29 -0
- omnibase_infra/event_bus/models/config/__init__.py +20 -0
- omnibase_infra/event_bus/models/config/model_kafka_event_bus_config.py +693 -0
- omnibase_infra/event_bus/models/model_dlq_event.py +206 -0
- omnibase_infra/event_bus/models/model_dlq_metrics.py +304 -0
- omnibase_infra/event_bus/models/model_event_headers.py +115 -0
- omnibase_infra/event_bus/models/model_event_message.py +60 -0
- omnibase_infra/event_bus/testing/__init__.py +26 -0
- omnibase_infra/event_bus/testing/adapter_protocol_event_publisher_inmemory.py +418 -0
- omnibase_infra/event_bus/testing/model_publisher_metrics.py +64 -0
- omnibase_infra/event_bus/topic_constants.py +376 -0
- omnibase_infra/handlers/__init__.py +82 -0
- omnibase_infra/handlers/filesystem/__init__.py +48 -0
- omnibase_infra/handlers/filesystem/enum_file_system_operation.py +35 -0
- omnibase_infra/handlers/filesystem/model_file_system_request.py +298 -0
- omnibase_infra/handlers/filesystem/model_file_system_result.py +166 -0
- omnibase_infra/handlers/handler_consul.py +795 -0
- omnibase_infra/handlers/handler_db.py +1046 -0
- omnibase_infra/handlers/handler_filesystem.py +1478 -0
- omnibase_infra/handlers/handler_graph.py +2015 -0
- omnibase_infra/handlers/handler_http.py +926 -0
- omnibase_infra/handlers/handler_intent.py +387 -0
- omnibase_infra/handlers/handler_manifest_persistence.contract.yaml +184 -0
- omnibase_infra/handlers/handler_manifest_persistence.py +1539 -0
- omnibase_infra/handlers/handler_mcp.py +1430 -0
- omnibase_infra/handlers/handler_qdrant.py +1076 -0
- omnibase_infra/handlers/handler_vault.py +428 -0
- omnibase_infra/handlers/mcp/__init__.py +19 -0
- omnibase_infra/handlers/mcp/adapter_onex_to_mcp.py +446 -0
- omnibase_infra/handlers/mcp/protocols.py +178 -0
- omnibase_infra/handlers/mcp/transport_streamable_http.py +352 -0
- omnibase_infra/handlers/mixins/__init__.py +47 -0
- omnibase_infra/handlers/mixins/mixin_consul_initialization.py +349 -0
- omnibase_infra/handlers/mixins/mixin_consul_kv.py +338 -0
- omnibase_infra/handlers/mixins/mixin_consul_service.py +542 -0
- omnibase_infra/handlers/mixins/mixin_consul_topic_index.py +585 -0
- omnibase_infra/handlers/mixins/mixin_vault_initialization.py +338 -0
- omnibase_infra/handlers/mixins/mixin_vault_retry.py +412 -0
- omnibase_infra/handlers/mixins/mixin_vault_secrets.py +450 -0
- omnibase_infra/handlers/mixins/mixin_vault_token.py +365 -0
- omnibase_infra/handlers/models/__init__.py +286 -0
- omnibase_infra/handlers/models/consul/__init__.py +81 -0
- omnibase_infra/handlers/models/consul/enum_consul_operation_type.py +57 -0
- omnibase_infra/handlers/models/consul/model_consul_deregister_payload.py +51 -0
- omnibase_infra/handlers/models/consul/model_consul_handler_config.py +153 -0
- omnibase_infra/handlers/models/consul/model_consul_handler_payload.py +89 -0
- omnibase_infra/handlers/models/consul/model_consul_kv_get_found_payload.py +55 -0
- omnibase_infra/handlers/models/consul/model_consul_kv_get_not_found_payload.py +49 -0
- omnibase_infra/handlers/models/consul/model_consul_kv_get_recurse_payload.py +50 -0
- omnibase_infra/handlers/models/consul/model_consul_kv_item.py +33 -0
- omnibase_infra/handlers/models/consul/model_consul_kv_put_payload.py +41 -0
- omnibase_infra/handlers/models/consul/model_consul_register_payload.py +53 -0
- omnibase_infra/handlers/models/consul/model_consul_retry_config.py +66 -0
- omnibase_infra/handlers/models/consul/model_payload_consul.py +66 -0
- omnibase_infra/handlers/models/consul/registry_payload_consul.py +214 -0
- omnibase_infra/handlers/models/graph/__init__.py +35 -0
- omnibase_infra/handlers/models/graph/enum_graph_operation_type.py +20 -0
- omnibase_infra/handlers/models/graph/model_graph_execute_payload.py +38 -0
- omnibase_infra/handlers/models/graph/model_graph_handler_config.py +54 -0
- omnibase_infra/handlers/models/graph/model_graph_handler_payload.py +44 -0
- omnibase_infra/handlers/models/graph/model_graph_query_payload.py +40 -0
- omnibase_infra/handlers/models/graph/model_graph_record.py +22 -0
- omnibase_infra/handlers/models/http/__init__.py +50 -0
- omnibase_infra/handlers/models/http/enum_http_operation_type.py +29 -0
- omnibase_infra/handlers/models/http/model_http_body_content.py +45 -0
- omnibase_infra/handlers/models/http/model_http_get_payload.py +88 -0
- omnibase_infra/handlers/models/http/model_http_handler_payload.py +90 -0
- omnibase_infra/handlers/models/http/model_http_post_payload.py +88 -0
- omnibase_infra/handlers/models/http/model_payload_http.py +66 -0
- omnibase_infra/handlers/models/http/registry_payload_http.py +212 -0
- omnibase_infra/handlers/models/mcp/__init__.py +23 -0
- omnibase_infra/handlers/models/mcp/enum_mcp_operation_type.py +24 -0
- omnibase_infra/handlers/models/mcp/model_mcp_handler_config.py +40 -0
- omnibase_infra/handlers/models/mcp/model_mcp_tool_call.py +32 -0
- omnibase_infra/handlers/models/mcp/model_mcp_tool_result.py +45 -0
- omnibase_infra/handlers/models/model_consul_handler_response.py +96 -0
- omnibase_infra/handlers/models/model_db_describe_response.py +83 -0
- omnibase_infra/handlers/models/model_db_query_payload.py +95 -0
- omnibase_infra/handlers/models/model_db_query_response.py +60 -0
- omnibase_infra/handlers/models/model_filesystem_config.py +98 -0
- omnibase_infra/handlers/models/model_filesystem_delete_payload.py +54 -0
- omnibase_infra/handlers/models/model_filesystem_delete_result.py +77 -0
- omnibase_infra/handlers/models/model_filesystem_directory_entry.py +75 -0
- omnibase_infra/handlers/models/model_filesystem_ensure_directory_payload.py +54 -0
- omnibase_infra/handlers/models/model_filesystem_ensure_directory_result.py +60 -0
- omnibase_infra/handlers/models/model_filesystem_list_directory_payload.py +60 -0
- omnibase_infra/handlers/models/model_filesystem_list_directory_result.py +68 -0
- omnibase_infra/handlers/models/model_filesystem_read_payload.py +62 -0
- omnibase_infra/handlers/models/model_filesystem_read_result.py +61 -0
- omnibase_infra/handlers/models/model_filesystem_write_payload.py +70 -0
- omnibase_infra/handlers/models/model_filesystem_write_result.py +55 -0
- omnibase_infra/handlers/models/model_graph_handler_response.py +98 -0
- omnibase_infra/handlers/models/model_handler_response.py +103 -0
- omnibase_infra/handlers/models/model_http_handler_response.py +101 -0
- omnibase_infra/handlers/models/model_manifest_metadata.py +75 -0
- omnibase_infra/handlers/models/model_manifest_persistence_config.py +62 -0
- omnibase_infra/handlers/models/model_manifest_query_payload.py +90 -0
- omnibase_infra/handlers/models/model_manifest_query_result.py +97 -0
- omnibase_infra/handlers/models/model_manifest_retrieve_payload.py +44 -0
- omnibase_infra/handlers/models/model_manifest_retrieve_result.py +98 -0
- omnibase_infra/handlers/models/model_manifest_store_payload.py +47 -0
- omnibase_infra/handlers/models/model_manifest_store_result.py +67 -0
- omnibase_infra/handlers/models/model_operation_context.py +187 -0
- omnibase_infra/handlers/models/model_qdrant_handler_response.py +98 -0
- omnibase_infra/handlers/models/model_retry_state.py +162 -0
- omnibase_infra/handlers/models/model_vault_handler_response.py +98 -0
- omnibase_infra/handlers/models/qdrant/__init__.py +44 -0
- omnibase_infra/handlers/models/qdrant/enum_qdrant_operation_type.py +26 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_collection_payload.py +42 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_delete_payload.py +36 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_handler_config.py +42 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_handler_payload.py +54 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_search_payload.py +42 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_search_result.py +30 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_upsert_payload.py +36 -0
- omnibase_infra/handlers/models/vault/__init__.py +69 -0
- omnibase_infra/handlers/models/vault/enum_vault_operation_type.py +35 -0
- omnibase_infra/handlers/models/vault/model_payload_vault.py +66 -0
- omnibase_infra/handlers/models/vault/model_vault_delete_payload.py +57 -0
- omnibase_infra/handlers/models/vault/model_vault_handler_config.py +148 -0
- omnibase_infra/handlers/models/vault/model_vault_handler_payload.py +101 -0
- omnibase_infra/handlers/models/vault/model_vault_list_payload.py +58 -0
- omnibase_infra/handlers/models/vault/model_vault_renew_token_payload.py +67 -0
- omnibase_infra/handlers/models/vault/model_vault_retry_config.py +66 -0
- omnibase_infra/handlers/models/vault/model_vault_secret_payload.py +106 -0
- omnibase_infra/handlers/models/vault/model_vault_write_payload.py +66 -0
- omnibase_infra/handlers/models/vault/registry_payload_vault.py +213 -0
- omnibase_infra/handlers/registration_storage/__init__.py +43 -0
- omnibase_infra/handlers/registration_storage/handler_registration_storage_mock.py +392 -0
- omnibase_infra/handlers/registration_storage/handler_registration_storage_postgres.py +922 -0
- omnibase_infra/handlers/registration_storage/models/__init__.py +23 -0
- omnibase_infra/handlers/registration_storage/models/model_delete_registration_request.py +58 -0
- omnibase_infra/handlers/registration_storage/models/model_update_registration_request.py +73 -0
- omnibase_infra/handlers/registration_storage/protocol_registration_persistence.py +191 -0
- omnibase_infra/handlers/service_discovery/__init__.py +43 -0
- omnibase_infra/handlers/service_discovery/handler_service_discovery_consul.py +1051 -0
- omnibase_infra/handlers/service_discovery/handler_service_discovery_mock.py +258 -0
- omnibase_infra/handlers/service_discovery/models/__init__.py +22 -0
- omnibase_infra/handlers/service_discovery/models/model_discovery_result.py +64 -0
- omnibase_infra/handlers/service_discovery/models/model_registration_result.py +138 -0
- omnibase_infra/handlers/service_discovery/models/model_service_info.py +109 -0
- omnibase_infra/handlers/service_discovery/protocol_discovery_operations.py +170 -0
- omnibase_infra/idempotency/__init__.py +94 -0
- omnibase_infra/idempotency/models/__init__.py +43 -0
- omnibase_infra/idempotency/models/model_idempotency_check_result.py +85 -0
- omnibase_infra/idempotency/models/model_idempotency_guard_config.py +130 -0
- omnibase_infra/idempotency/models/model_idempotency_record.py +86 -0
- omnibase_infra/idempotency/models/model_idempotency_store_health_check_result.py +81 -0
- omnibase_infra/idempotency/models/model_idempotency_store_metrics.py +140 -0
- omnibase_infra/idempotency/models/model_postgres_idempotency_store_config.py +299 -0
- omnibase_infra/idempotency/protocol_idempotency_store.py +184 -0
- omnibase_infra/idempotency/store_inmemory.py +265 -0
- omnibase_infra/idempotency/store_postgres.py +923 -0
- omnibase_infra/infrastructure/__init__.py +0 -0
- omnibase_infra/migrations/001_create_event_ledger.sql +166 -0
- omnibase_infra/migrations/001_drop_event_ledger.sql +18 -0
- omnibase_infra/mixins/__init__.py +71 -0
- omnibase_infra/mixins/mixin_async_circuit_breaker.py +656 -0
- omnibase_infra/mixins/mixin_dict_like_accessors.py +146 -0
- omnibase_infra/mixins/mixin_envelope_extraction.py +119 -0
- omnibase_infra/mixins/mixin_node_introspection.py +2670 -0
- omnibase_infra/mixins/mixin_retry_execution.py +386 -0
- omnibase_infra/mixins/protocol_circuit_breaker_aware.py +133 -0
- omnibase_infra/models/__init__.py +144 -0
- omnibase_infra/models/bindings/__init__.py +59 -0
- omnibase_infra/models/bindings/constants.py +144 -0
- omnibase_infra/models/bindings/model_binding_resolution_result.py +103 -0
- omnibase_infra/models/bindings/model_operation_binding.py +44 -0
- omnibase_infra/models/bindings/model_operation_bindings_subcontract.py +152 -0
- omnibase_infra/models/bindings/model_parsed_binding.py +52 -0
- omnibase_infra/models/corpus/__init__.py +17 -0
- omnibase_infra/models/corpus/model_capture_config.py +133 -0
- omnibase_infra/models/corpus/model_capture_result.py +86 -0
- omnibase_infra/models/discovery/__init__.py +42 -0
- omnibase_infra/models/discovery/model_dependency_spec.py +319 -0
- omnibase_infra/models/discovery/model_discovered_capabilities.py +50 -0
- omnibase_infra/models/discovery/model_introspection_config.py +330 -0
- omnibase_infra/models/discovery/model_introspection_performance_metrics.py +169 -0
- omnibase_infra/models/discovery/model_introspection_task_config.py +116 -0
- omnibase_infra/models/dispatch/__init__.py +155 -0
- omnibase_infra/models/dispatch/model_debug_trace_snapshot.py +114 -0
- omnibase_infra/models/dispatch/model_dispatch_context.py +439 -0
- omnibase_infra/models/dispatch/model_dispatch_error.py +336 -0
- omnibase_infra/models/dispatch/model_dispatch_log_context.py +400 -0
- omnibase_infra/models/dispatch/model_dispatch_metadata.py +228 -0
- omnibase_infra/models/dispatch/model_dispatch_metrics.py +496 -0
- omnibase_infra/models/dispatch/model_dispatch_outcome.py +317 -0
- omnibase_infra/models/dispatch/model_dispatch_outputs.py +231 -0
- omnibase_infra/models/dispatch/model_dispatch_result.py +436 -0
- omnibase_infra/models/dispatch/model_dispatch_route.py +279 -0
- omnibase_infra/models/dispatch/model_dispatcher_metrics.py +275 -0
- omnibase_infra/models/dispatch/model_dispatcher_registration.py +352 -0
- omnibase_infra/models/dispatch/model_materialized_dispatch.py +141 -0
- omnibase_infra/models/dispatch/model_parsed_topic.py +135 -0
- omnibase_infra/models/dispatch/model_topic_parser.py +725 -0
- omnibase_infra/models/dispatch/model_tracing_context.py +285 -0
- omnibase_infra/models/errors/__init__.py +45 -0
- omnibase_infra/models/errors/model_handler_validation_error.py +594 -0
- omnibase_infra/models/errors/model_infra_error_context.py +99 -0
- omnibase_infra/models/errors/model_message_type_registry_error_context.py +71 -0
- omnibase_infra/models/errors/model_timeout_error_context.py +110 -0
- omnibase_infra/models/handlers/__init__.py +80 -0
- omnibase_infra/models/handlers/model_bootstrap_handler_descriptor.py +162 -0
- omnibase_infra/models/handlers/model_contract_discovery_result.py +82 -0
- omnibase_infra/models/handlers/model_handler_descriptor.py +200 -0
- omnibase_infra/models/handlers/model_handler_identifier.py +215 -0
- omnibase_infra/models/handlers/model_handler_source_config.py +220 -0
- omnibase_infra/models/health/__init__.py +9 -0
- omnibase_infra/models/health/model_health_check_result.py +40 -0
- omnibase_infra/models/lifecycle/__init__.py +39 -0
- omnibase_infra/models/logging/__init__.py +51 -0
- omnibase_infra/models/logging/model_log_context.py +756 -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/model_node_identity.py +126 -0
- omnibase_infra/models/model_retry_error_classification.py +78 -0
- omnibase_infra/models/projection/__init__.py +43 -0
- omnibase_infra/models/projection/model_capability_fields.py +112 -0
- omnibase_infra/models/projection/model_registration_projection.py +434 -0
- omnibase_infra/models/projection/model_registration_snapshot.py +322 -0
- omnibase_infra/models/projection/model_sequence_info.py +182 -0
- omnibase_infra/models/projection/model_snapshot_topic_config.py +591 -0
- omnibase_infra/models/projectors/__init__.py +41 -0
- omnibase_infra/models/projectors/model_projector_column.py +289 -0
- omnibase_infra/models/projectors/model_projector_discovery_result.py +65 -0
- omnibase_infra/models/projectors/model_projector_index.py +270 -0
- omnibase_infra/models/projectors/model_projector_schema.py +415 -0
- omnibase_infra/models/projectors/model_projector_validation_error.py +63 -0
- omnibase_infra/models/projectors/util_sql_identifiers.py +115 -0
- omnibase_infra/models/registration/__init__.py +68 -0
- omnibase_infra/models/registration/commands/__init__.py +15 -0
- omnibase_infra/models/registration/commands/model_node_registration_acked.py +108 -0
- omnibase_infra/models/registration/events/__init__.py +56 -0
- omnibase_infra/models/registration/events/model_node_became_active.py +103 -0
- omnibase_infra/models/registration/events/model_node_liveness_expired.py +103 -0
- omnibase_infra/models/registration/events/model_node_registration_accepted.py +98 -0
- omnibase_infra/models/registration/events/model_node_registration_ack_received.py +98 -0
- omnibase_infra/models/registration/events/model_node_registration_ack_timed_out.py +112 -0
- omnibase_infra/models/registration/events/model_node_registration_initiated.py +107 -0
- omnibase_infra/models/registration/events/model_node_registration_rejected.py +104 -0
- omnibase_infra/models/registration/model_event_bus_topic_entry.py +59 -0
- omnibase_infra/models/registration/model_introspection_metrics.py +253 -0
- omnibase_infra/models/registration/model_node_capabilities.py +190 -0
- omnibase_infra/models/registration/model_node_event_bus_config.py +99 -0
- omnibase_infra/models/registration/model_node_heartbeat_event.py +126 -0
- omnibase_infra/models/registration/model_node_introspection_event.py +195 -0
- omnibase_infra/models/registration/model_node_metadata.py +79 -0
- omnibase_infra/models/registration/model_node_registration.py +162 -0
- omnibase_infra/models/registration/model_node_registration_record.py +162 -0
- omnibase_infra/models/registry/__init__.py +29 -0
- omnibase_infra/models/registry/model_domain_constraint.py +202 -0
- omnibase_infra/models/registry/model_message_type_entry.py +271 -0
- omnibase_infra/models/resilience/__init__.py +9 -0
- omnibase_infra/models/resilience/model_circuit_breaker_config.py +227 -0
- omnibase_infra/models/routing/__init__.py +25 -0
- omnibase_infra/models/routing/model_routing_entry.py +52 -0
- omnibase_infra/models/routing/model_routing_subcontract.py +70 -0
- omnibase_infra/models/runtime/__init__.py +49 -0
- omnibase_infra/models/runtime/model_contract_security_config.py +41 -0
- omnibase_infra/models/runtime/model_discovery_error.py +81 -0
- omnibase_infra/models/runtime/model_discovery_result.py +162 -0
- omnibase_infra/models/runtime/model_discovery_warning.py +74 -0
- omnibase_infra/models/runtime/model_failed_plugin_load.py +63 -0
- omnibase_infra/models/runtime/model_handler_contract.py +296 -0
- omnibase_infra/models/runtime/model_loaded_handler.py +129 -0
- omnibase_infra/models/runtime/model_plugin_load_context.py +93 -0
- omnibase_infra/models/runtime/model_plugin_load_summary.py +124 -0
- omnibase_infra/models/security/__init__.py +50 -0
- omnibase_infra/models/security/classification_levels.py +99 -0
- omnibase_infra/models/security/model_environment_policy.py +145 -0
- omnibase_infra/models/security/model_handler_security_policy.py +107 -0
- omnibase_infra/models/security/model_security_error.py +81 -0
- omnibase_infra/models/security/model_security_validation_result.py +328 -0
- omnibase_infra/models/security/model_security_warning.py +67 -0
- omnibase_infra/models/snapshot/__init__.py +27 -0
- omnibase_infra/models/snapshot/model_field_change.py +65 -0
- omnibase_infra/models/snapshot/model_snapshot.py +270 -0
- omnibase_infra/models/snapshot/model_snapshot_diff.py +203 -0
- omnibase_infra/models/snapshot/model_subject_ref.py +81 -0
- omnibase_infra/models/types/__init__.py +71 -0
- omnibase_infra/models/validation/__init__.py +89 -0
- omnibase_infra/models/validation/model_any_type_validation_result.py +118 -0
- omnibase_infra/models/validation/model_any_type_violation.py +141 -0
- omnibase_infra/models/validation/model_category_match_result.py +345 -0
- omnibase_infra/models/validation/model_chain_violation.py +166 -0
- omnibase_infra/models/validation/model_coverage_metrics.py +316 -0
- omnibase_infra/models/validation/model_execution_shape_rule.py +159 -0
- omnibase_infra/models/validation/model_execution_shape_validation.py +208 -0
- omnibase_infra/models/validation/model_execution_shape_validation_result.py +294 -0
- omnibase_infra/models/validation/model_execution_shape_violation.py +122 -0
- omnibase_infra/models/validation/model_localhandler_validation_result.py +139 -0
- omnibase_infra/models/validation/model_localhandler_violation.py +100 -0
- omnibase_infra/models/validation/model_output_validation_params.py +74 -0
- omnibase_infra/models/validation/model_validate_and_raise_params.py +84 -0
- omnibase_infra/models/validation/model_validation_error_params.py +84 -0
- omnibase_infra/models/validation/model_validation_outcome.py +287 -0
- omnibase_infra/nodes/__init__.py +57 -0
- omnibase_infra/nodes/architecture_validator/__init__.py +79 -0
- omnibase_infra/nodes/architecture_validator/contract.yaml +252 -0
- omnibase_infra/nodes/architecture_validator/contract_architecture_validator.yaml +203 -0
- omnibase_infra/nodes/architecture_validator/mixins/__init__.py +16 -0
- omnibase_infra/nodes/architecture_validator/mixins/mixin_file_path_rule.py +92 -0
- omnibase_infra/nodes/architecture_validator/models/__init__.py +36 -0
- omnibase_infra/nodes/architecture_validator/models/model_architecture_validation_request.py +56 -0
- omnibase_infra/nodes/architecture_validator/models/model_architecture_validation_result.py +311 -0
- omnibase_infra/nodes/architecture_validator/models/model_architecture_violation.py +163 -0
- omnibase_infra/nodes/architecture_validator/models/model_rule_check_result.py +265 -0
- omnibase_infra/nodes/architecture_validator/models/model_validation_request.py +105 -0
- omnibase_infra/nodes/architecture_validator/models/model_validation_result.py +314 -0
- omnibase_infra/nodes/architecture_validator/node.py +262 -0
- omnibase_infra/nodes/architecture_validator/node_architecture_validator.py +383 -0
- omnibase_infra/nodes/architecture_validator/protocols/__init__.py +9 -0
- omnibase_infra/nodes/architecture_validator/protocols/protocol_architecture_rule.py +225 -0
- omnibase_infra/nodes/architecture_validator/registry/__init__.py +28 -0
- omnibase_infra/nodes/architecture_validator/registry/registry_infra_architecture_validator.py +106 -0
- omnibase_infra/nodes/architecture_validator/validators/__init__.py +104 -0
- omnibase_infra/nodes/architecture_validator/validators/validator_no_direct_dispatch.py +422 -0
- omnibase_infra/nodes/architecture_validator/validators/validator_no_handler_publishing.py +481 -0
- omnibase_infra/nodes/architecture_validator/validators/validator_no_orchestrator_fsm.py +491 -0
- omnibase_infra/nodes/contract_registry_reducer/__init__.py +29 -0
- omnibase_infra/nodes/contract_registry_reducer/contract.yaml +255 -0
- omnibase_infra/nodes/contract_registry_reducer/models/__init__.py +38 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_contract_registry_state.py +266 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_cleanup_topic_references.py +55 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_deactivate_contract.py +58 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_mark_stale.py +49 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_update_heartbeat.py +71 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_update_topic.py +66 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_upsert_contract.py +92 -0
- omnibase_infra/nodes/contract_registry_reducer/node.py +121 -0
- omnibase_infra/nodes/contract_registry_reducer/reducer.py +784 -0
- omnibase_infra/nodes/contract_registry_reducer/registry/__init__.py +9 -0
- omnibase_infra/nodes/contract_registry_reducer/registry/registry_infra_contract_registry_reducer.py +101 -0
- omnibase_infra/nodes/effects/README.md +358 -0
- omnibase_infra/nodes/effects/__init__.py +26 -0
- omnibase_infra/nodes/effects/contract.yaml +167 -0
- omnibase_infra/nodes/effects/models/__init__.py +32 -0
- omnibase_infra/nodes/effects/models/model_backend_result.py +190 -0
- omnibase_infra/nodes/effects/models/model_effect_idempotency_config.py +92 -0
- omnibase_infra/nodes/effects/models/model_registry_request.py +132 -0
- omnibase_infra/nodes/effects/models/model_registry_response.py +263 -0
- omnibase_infra/nodes/effects/protocol_consul_client.py +89 -0
- omnibase_infra/nodes/effects/protocol_effect_idempotency_store.py +143 -0
- omnibase_infra/nodes/effects/protocol_postgres_adapter.py +96 -0
- omnibase_infra/nodes/effects/registry_effect.py +525 -0
- omnibase_infra/nodes/effects/store_effect_idempotency_inmemory.py +425 -0
- omnibase_infra/nodes/handlers/consul/contract.yaml +85 -0
- omnibase_infra/nodes/handlers/db/contract.yaml +72 -0
- omnibase_infra/nodes/handlers/graph/contract.yaml +127 -0
- omnibase_infra/nodes/handlers/http/contract.yaml +74 -0
- omnibase_infra/nodes/handlers/intent/contract.yaml +66 -0
- omnibase_infra/nodes/handlers/mcp/contract.yaml +69 -0
- omnibase_infra/nodes/handlers/vault/contract.yaml +91 -0
- omnibase_infra/nodes/node_intent_storage_effect/__init__.py +50 -0
- omnibase_infra/nodes/node_intent_storage_effect/contract.yaml +194 -0
- omnibase_infra/nodes/node_intent_storage_effect/models/__init__.py +24 -0
- omnibase_infra/nodes/node_intent_storage_effect/models/model_intent_storage_input.py +141 -0
- omnibase_infra/nodes/node_intent_storage_effect/models/model_intent_storage_output.py +130 -0
- omnibase_infra/nodes/node_intent_storage_effect/node.py +94 -0
- omnibase_infra/nodes/node_intent_storage_effect/registry/__init__.py +35 -0
- omnibase_infra/nodes/node_intent_storage_effect/registry/registry_infra_intent_storage.py +294 -0
- omnibase_infra/nodes/node_ledger_projection_compute/__init__.py +50 -0
- omnibase_infra/nodes/node_ledger_projection_compute/contract.yaml +104 -0
- omnibase_infra/nodes/node_ledger_projection_compute/node.py +284 -0
- omnibase_infra/nodes/node_ledger_projection_compute/registry/__init__.py +29 -0
- omnibase_infra/nodes/node_ledger_projection_compute/registry/registry_infra_ledger_projection.py +118 -0
- omnibase_infra/nodes/node_ledger_write_effect/__init__.py +82 -0
- omnibase_infra/nodes/node_ledger_write_effect/contract.yaml +200 -0
- omnibase_infra/nodes/node_ledger_write_effect/handlers/__init__.py +22 -0
- omnibase_infra/nodes/node_ledger_write_effect/handlers/handler_ledger_append.py +372 -0
- omnibase_infra/nodes/node_ledger_write_effect/handlers/handler_ledger_query.py +597 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/__init__.py +31 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_append_result.py +54 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_entry.py +92 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_query.py +53 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_query_result.py +41 -0
- omnibase_infra/nodes/node_ledger_write_effect/node.py +89 -0
- omnibase_infra/nodes/node_ledger_write_effect/protocols/__init__.py +13 -0
- omnibase_infra/nodes/node_ledger_write_effect/protocols/protocol_ledger_persistence.py +127 -0
- omnibase_infra/nodes/node_ledger_write_effect/registry/__init__.py +9 -0
- omnibase_infra/nodes/node_ledger_write_effect/registry/registry_infra_ledger_write.py +121 -0
- omnibase_infra/nodes/node_registration_orchestrator/README.md +542 -0
- omnibase_infra/nodes/node_registration_orchestrator/__init__.py +120 -0
- omnibase_infra/nodes/node_registration_orchestrator/contract.yaml +482 -0
- omnibase_infra/nodes/node_registration_orchestrator/dispatchers/__init__.py +53 -0
- omnibase_infra/nodes/node_registration_orchestrator/dispatchers/dispatcher_node_introspected.py +376 -0
- omnibase_infra/nodes/node_registration_orchestrator/dispatchers/dispatcher_node_registration_acked.py +376 -0
- omnibase_infra/nodes/node_registration_orchestrator/dispatchers/dispatcher_runtime_tick.py +373 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/__init__.py +62 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_heartbeat.py +376 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_introspected.py +694 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_registration_acked.py +458 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_runtime_tick.py +364 -0
- omnibase_infra/nodes/node_registration_orchestrator/introspection_event_router.py +544 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/__init__.py +75 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_consul_intent_payload.py +194 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_consul_registration_intent.py +67 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_intent_execution_result.py +50 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_node_liveness_expired.py +107 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_orchestrator_config.py +67 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_orchestrator_input.py +41 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_orchestrator_output.py +166 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_postgres_intent_payload.py +235 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_postgres_upsert_intent.py +68 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_reducer_execution_result.py +384 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_reducer_state.py +60 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_registration_intent.py +177 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_registry_intent.py +247 -0
- omnibase_infra/nodes/node_registration_orchestrator/node.py +195 -0
- omnibase_infra/nodes/node_registration_orchestrator/plugin.py +909 -0
- omnibase_infra/nodes/node_registration_orchestrator/protocols.py +439 -0
- omnibase_infra/nodes/node_registration_orchestrator/registry/__init__.py +41 -0
- omnibase_infra/nodes/node_registration_orchestrator/registry/registry_infra_node_registration_orchestrator.py +528 -0
- omnibase_infra/nodes/node_registration_orchestrator/timeout_coordinator.py +393 -0
- omnibase_infra/nodes/node_registration_orchestrator/wiring.py +743 -0
- omnibase_infra/nodes/node_registration_reducer/__init__.py +15 -0
- omnibase_infra/nodes/node_registration_reducer/contract.yaml +301 -0
- omnibase_infra/nodes/node_registration_reducer/models/__init__.py +38 -0
- omnibase_infra/nodes/node_registration_reducer/models/model_validation_result.py +113 -0
- omnibase_infra/nodes/node_registration_reducer/node.py +139 -0
- omnibase_infra/nodes/node_registration_reducer/registry/__init__.py +9 -0
- omnibase_infra/nodes/node_registration_reducer/registry/registry_infra_node_registration_reducer.py +79 -0
- omnibase_infra/nodes/node_registration_storage_effect/__init__.py +41 -0
- omnibase_infra/nodes/node_registration_storage_effect/contract.yaml +220 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/__init__.py +44 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_delete_result.py +132 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_registration_record.py +199 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_registration_update.py +155 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_health_check_details.py +123 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_health_check_result.py +117 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_query.py +100 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_result.py +136 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_upsert_result.py +127 -0
- omnibase_infra/nodes/node_registration_storage_effect/node.py +112 -0
- omnibase_infra/nodes/node_registration_storage_effect/protocols/__init__.py +22 -0
- omnibase_infra/nodes/node_registration_storage_effect/protocols/protocol_registration_persistence.py +333 -0
- omnibase_infra/nodes/node_registration_storage_effect/registry/__init__.py +23 -0
- omnibase_infra/nodes/node_registration_storage_effect/registry/registry_infra_registration_storage.py +215 -0
- omnibase_infra/nodes/node_registry_effect/__init__.py +85 -0
- omnibase_infra/nodes/node_registry_effect/contract.yaml +677 -0
- omnibase_infra/nodes/node_registry_effect/handlers/__init__.py +70 -0
- omnibase_infra/nodes/node_registry_effect/handlers/handler_consul_deregister.py +211 -0
- omnibase_infra/nodes/node_registry_effect/handlers/handler_consul_register.py +212 -0
- omnibase_infra/nodes/node_registry_effect/handlers/handler_partial_retry.py +417 -0
- omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_deactivate.py +215 -0
- omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_upsert.py +208 -0
- omnibase_infra/nodes/node_registry_effect/models/__init__.py +43 -0
- omnibase_infra/nodes/node_registry_effect/models/model_partial_retry_request.py +92 -0
- omnibase_infra/nodes/node_registry_effect/node.py +165 -0
- omnibase_infra/nodes/node_registry_effect/registry/__init__.py +27 -0
- omnibase_infra/nodes/node_registry_effect/registry/registry_infra_registry_effect.py +196 -0
- omnibase_infra/nodes/node_service_discovery_effect/__init__.py +111 -0
- omnibase_infra/nodes/node_service_discovery_effect/contract.yaml +246 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/__init__.py +67 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/enum_health_status.py +72 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/enum_service_discovery_operation.py +58 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_discovery_query.py +99 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_discovery_result.py +98 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_health_check_config.py +121 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_query_metadata.py +63 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_registration_result.py +130 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_service_discovery_health_check_details.py +111 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_service_discovery_health_check_result.py +119 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_service_info.py +106 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_service_registration.py +121 -0
- omnibase_infra/nodes/node_service_discovery_effect/node.py +111 -0
- omnibase_infra/nodes/node_service_discovery_effect/protocols/__init__.py +14 -0
- omnibase_infra/nodes/node_service_discovery_effect/protocols/protocol_discovery_operations.py +279 -0
- omnibase_infra/nodes/node_service_discovery_effect/registry/__init__.py +13 -0
- omnibase_infra/nodes/node_service_discovery_effect/registry/registry_infra_service_discovery.py +222 -0
- omnibase_infra/nodes/reducers/__init__.py +30 -0
- omnibase_infra/nodes/reducers/models/__init__.py +37 -0
- omnibase_infra/nodes/reducers/models/model_payload_consul_register.py +87 -0
- omnibase_infra/nodes/reducers/models/model_payload_ledger_append.py +133 -0
- omnibase_infra/nodes/reducers/models/model_payload_postgres_upsert_registration.py +60 -0
- omnibase_infra/nodes/reducers/models/model_registration_confirmation.py +166 -0
- omnibase_infra/nodes/reducers/models/model_registration_state.py +433 -0
- omnibase_infra/nodes/reducers/registration_reducer.py +1138 -0
- omnibase_infra/observability/__init__.py +143 -0
- omnibase_infra/observability/constants_metrics.py +91 -0
- omnibase_infra/observability/factory_observability_sink.py +525 -0
- omnibase_infra/observability/handlers/__init__.py +118 -0
- omnibase_infra/observability/handlers/handler_logging_structured.py +967 -0
- omnibase_infra/observability/handlers/handler_metrics_prometheus.py +1120 -0
- omnibase_infra/observability/handlers/model_logging_handler_config.py +71 -0
- omnibase_infra/observability/handlers/model_logging_handler_response.py +77 -0
- omnibase_infra/observability/handlers/model_metrics_handler_config.py +172 -0
- omnibase_infra/observability/handlers/model_metrics_handler_payload.py +135 -0
- omnibase_infra/observability/handlers/model_metrics_handler_response.py +101 -0
- omnibase_infra/observability/hooks/__init__.py +74 -0
- omnibase_infra/observability/hooks/hook_observability.py +1223 -0
- omnibase_infra/observability/models/__init__.py +30 -0
- omnibase_infra/observability/models/enum_required_log_context_key.py +77 -0
- omnibase_infra/observability/models/model_buffered_log_entry.py +117 -0
- omnibase_infra/observability/models/model_logging_sink_config.py +73 -0
- omnibase_infra/observability/models/model_metrics_sink_config.py +156 -0
- omnibase_infra/observability/sinks/__init__.py +69 -0
- omnibase_infra/observability/sinks/sink_logging_structured.py +809 -0
- omnibase_infra/observability/sinks/sink_metrics_prometheus.py +710 -0
- omnibase_infra/plugins/__init__.py +27 -0
- omnibase_infra/plugins/examples/__init__.py +28 -0
- omnibase_infra/plugins/examples/plugin_json_normalizer.py +271 -0
- omnibase_infra/plugins/examples/plugin_json_normalizer_error_handling.py +210 -0
- omnibase_infra/plugins/models/__init__.py +21 -0
- omnibase_infra/plugins/models/model_plugin_context.py +76 -0
- omnibase_infra/plugins/models/model_plugin_input_data.py +58 -0
- omnibase_infra/plugins/models/model_plugin_output_data.py +62 -0
- omnibase_infra/plugins/plugin_compute_base.py +449 -0
- omnibase_infra/projectors/__init__.py +30 -0
- omnibase_infra/projectors/contracts/__init__.py +63 -0
- omnibase_infra/projectors/contracts/registration_projector.yaml +370 -0
- omnibase_infra/projectors/projection_reader_registration.py +1559 -0
- omnibase_infra/projectors/snapshot_publisher_registration.py +1329 -0
- omnibase_infra/protocols/__init__.py +104 -0
- omnibase_infra/protocols/protocol_capability_projection.py +253 -0
- omnibase_infra/protocols/protocol_capability_query.py +251 -0
- omnibase_infra/protocols/protocol_container_aware.py +200 -0
- omnibase_infra/protocols/protocol_dispatch_engine.py +152 -0
- omnibase_infra/protocols/protocol_event_bus_like.py +127 -0
- omnibase_infra/protocols/protocol_event_projector.py +96 -0
- omnibase_infra/protocols/protocol_idempotency_store.py +142 -0
- omnibase_infra/protocols/protocol_message_dispatcher.py +247 -0
- omnibase_infra/protocols/protocol_message_type_registry.py +306 -0
- omnibase_infra/protocols/protocol_plugin_compute.py +368 -0
- omnibase_infra/protocols/protocol_projector_schema_validator.py +82 -0
- omnibase_infra/protocols/protocol_registry_metrics.py +215 -0
- omnibase_infra/protocols/protocol_snapshot_publisher.py +396 -0
- omnibase_infra/protocols/protocol_snapshot_store.py +567 -0
- omnibase_infra/runtime/__init__.py +445 -0
- omnibase_infra/runtime/binding_config_resolver.py +2771 -0
- omnibase_infra/runtime/binding_resolver.py +753 -0
- omnibase_infra/runtime/chain_aware_dispatch.py +467 -0
- omnibase_infra/runtime/constants_notification.py +75 -0
- omnibase_infra/runtime/constants_security.py +70 -0
- omnibase_infra/runtime/contract_handler_discovery.py +587 -0
- omnibase_infra/runtime/contract_loaders/__init__.py +51 -0
- omnibase_infra/runtime/contract_loaders/handler_routing_loader.py +464 -0
- omnibase_infra/runtime/contract_loaders/operation_bindings_loader.py +789 -0
- omnibase_infra/runtime/dispatch_context_enforcer.py +427 -0
- omnibase_infra/runtime/emit_daemon/__init__.py +97 -0
- omnibase_infra/runtime/emit_daemon/cli.py +844 -0
- omnibase_infra/runtime/emit_daemon/client.py +811 -0
- omnibase_infra/runtime/emit_daemon/config.py +535 -0
- omnibase_infra/runtime/emit_daemon/daemon.py +812 -0
- omnibase_infra/runtime/emit_daemon/event_registry.py +477 -0
- omnibase_infra/runtime/emit_daemon/model_daemon_request.py +139 -0
- omnibase_infra/runtime/emit_daemon/model_daemon_response.py +191 -0
- omnibase_infra/runtime/emit_daemon/queue.py +618 -0
- omnibase_infra/runtime/enums/__init__.py +18 -0
- omnibase_infra/runtime/enums/enum_config_ref_scheme.py +33 -0
- omnibase_infra/runtime/enums/enum_scheduler_status.py +170 -0
- omnibase_infra/runtime/envelope_validator.py +179 -0
- omnibase_infra/runtime/event_bus_subcontract_wiring.py +466 -0
- 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 +750 -0
- omnibase_infra/runtime/handler_identity.py +81 -0
- omnibase_infra/runtime/handler_plugin_loader.py +2046 -0
- omnibase_infra/runtime/handler_registry.py +329 -0
- omnibase_infra/runtime/handler_source_resolver.py +367 -0
- omnibase_infra/runtime/invocation_security_enforcer.py +427 -0
- omnibase_infra/runtime/kafka_contract_source.py +984 -0
- omnibase_infra/runtime/kernel.py +40 -0
- omnibase_infra/runtime/mixin_policy_validation.py +522 -0
- omnibase_infra/runtime/mixin_semver_cache.py +402 -0
- omnibase_infra/runtime/mixins/__init__.py +24 -0
- omnibase_infra/runtime/mixins/mixin_projector_notification_publishing.py +566 -0
- omnibase_infra/runtime/mixins/mixin_projector_sql_operations.py +778 -0
- omnibase_infra/runtime/models/__init__.py +229 -0
- omnibase_infra/runtime/models/model_batch_lifecycle_result.py +217 -0
- omnibase_infra/runtime/models/model_binding_config.py +168 -0
- omnibase_infra/runtime/models/model_binding_config_cache_stats.py +135 -0
- omnibase_infra/runtime/models/model_binding_config_resolver_config.py +329 -0
- omnibase_infra/runtime/models/model_cached_secret.py +138 -0
- omnibase_infra/runtime/models/model_compute_key.py +138 -0
- omnibase_infra/runtime/models/model_compute_registration.py +97 -0
- omnibase_infra/runtime/models/model_config_cache_entry.py +61 -0
- omnibase_infra/runtime/models/model_config_ref.py +331 -0
- omnibase_infra/runtime/models/model_config_ref_parse_result.py +125 -0
- omnibase_infra/runtime/models/model_contract_load_result.py +224 -0
- omnibase_infra/runtime/models/model_domain_plugin_config.py +92 -0
- omnibase_infra/runtime/models/model_domain_plugin_result.py +270 -0
- omnibase_infra/runtime/models/model_duplicate_response.py +54 -0
- omnibase_infra/runtime/models/model_enabled_protocols_config.py +61 -0
- omnibase_infra/runtime/models/model_event_bus_config.py +54 -0
- omnibase_infra/runtime/models/model_failed_component.py +55 -0
- omnibase_infra/runtime/models/model_health_check_response.py +168 -0
- omnibase_infra/runtime/models/model_health_check_result.py +229 -0
- omnibase_infra/runtime/models/model_lifecycle_result.py +245 -0
- omnibase_infra/runtime/models/model_logging_config.py +42 -0
- omnibase_infra/runtime/models/model_optional_correlation_id.py +167 -0
- omnibase_infra/runtime/models/model_optional_string.py +94 -0
- omnibase_infra/runtime/models/model_optional_uuid.py +110 -0
- omnibase_infra/runtime/models/model_policy_context.py +100 -0
- omnibase_infra/runtime/models/model_policy_key.py +138 -0
- omnibase_infra/runtime/models/model_policy_registration.py +139 -0
- omnibase_infra/runtime/models/model_policy_result.py +103 -0
- omnibase_infra/runtime/models/model_policy_type_filter.py +157 -0
- omnibase_infra/runtime/models/model_projector_notification_config.py +171 -0
- omnibase_infra/runtime/models/model_projector_plugin_loader_config.py +47 -0
- omnibase_infra/runtime/models/model_protocol_registration_config.py +65 -0
- omnibase_infra/runtime/models/model_retry_policy.py +105 -0
- omnibase_infra/runtime/models/model_runtime_config.py +150 -0
- omnibase_infra/runtime/models/model_runtime_contract_config.py +268 -0
- omnibase_infra/runtime/models/model_runtime_scheduler_config.py +625 -0
- omnibase_infra/runtime/models/model_runtime_scheduler_metrics.py +233 -0
- omnibase_infra/runtime/models/model_runtime_tick.py +193 -0
- omnibase_infra/runtime/models/model_secret_cache_stats.py +82 -0
- omnibase_infra/runtime/models/model_secret_mapping.py +63 -0
- omnibase_infra/runtime/models/model_secret_resolver_config.py +107 -0
- omnibase_infra/runtime/models/model_secret_resolver_metrics.py +111 -0
- omnibase_infra/runtime/models/model_secret_source_info.py +72 -0
- omnibase_infra/runtime/models/model_secret_source_spec.py +66 -0
- omnibase_infra/runtime/models/model_security_config.py +109 -0
- omnibase_infra/runtime/models/model_shutdown_batch_result.py +75 -0
- omnibase_infra/runtime/models/model_shutdown_config.py +94 -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 +1462 -0
- omnibase_infra/runtime/projector_schema_manager.py +565 -0
- omnibase_infra/runtime/projector_shell.py +1330 -0
- omnibase_infra/runtime/protocol_contract_descriptor.py +92 -0
- omnibase_infra/runtime/protocol_contract_source.py +92 -0
- omnibase_infra/runtime/protocol_domain_plugin.py +474 -0
- omnibase_infra/runtime/protocol_handler_discovery.py +221 -0
- omnibase_infra/runtime/protocol_handler_plugin_loader.py +327 -0
- omnibase_infra/runtime/protocol_lifecycle_executor.py +435 -0
- omnibase_infra/runtime/protocol_policy.py +366 -0
- omnibase_infra/runtime/protocols/__init__.py +37 -0
- omnibase_infra/runtime/protocols/protocol_runtime_scheduler.py +468 -0
- omnibase_infra/runtime/publisher_topic_scoped.py +294 -0
- omnibase_infra/runtime/registry/__init__.py +93 -0
- omnibase_infra/runtime/registry/mixin_message_type_query.py +326 -0
- omnibase_infra/runtime/registry/mixin_message_type_registration.py +354 -0
- omnibase_infra/runtime/registry/registry_event_bus_binding.py +268 -0
- omnibase_infra/runtime/registry/registry_message_type.py +542 -0
- omnibase_infra/runtime/registry/registry_protocol_binding.py +445 -0
- omnibase_infra/runtime/registry_compute.py +1143 -0
- omnibase_infra/runtime/registry_contract_source.py +693 -0
- omnibase_infra/runtime/registry_dispatcher.py +678 -0
- omnibase_infra/runtime/registry_policy.py +1185 -0
- omnibase_infra/runtime/runtime_contract_config_loader.py +406 -0
- omnibase_infra/runtime/runtime_scheduler.py +1070 -0
- omnibase_infra/runtime/secret_resolver.py +2112 -0
- omnibase_infra/runtime/security_metadata_validator.py +776 -0
- omnibase_infra/runtime/service_kernel.py +1651 -0
- omnibase_infra/runtime/service_message_dispatch_engine.py +2350 -0
- omnibase_infra/runtime/service_runtime_host_process.py +3493 -0
- omnibase_infra/runtime/transition_notification_outbox.py +1190 -0
- omnibase_infra/runtime/transition_notification_publisher.py +765 -0
- omnibase_infra/runtime/util_container_wiring.py +1124 -0
- omnibase_infra/runtime/util_validation.py +314 -0
- omnibase_infra/runtime/util_version.py +98 -0
- omnibase_infra/runtime/util_wiring.py +723 -0
- omnibase_infra/schemas/schema_registration_projection.sql +320 -0
- omnibase_infra/schemas/schema_transition_notification_outbox.sql +245 -0
- omnibase_infra/services/__init__.py +89 -0
- omnibase_infra/services/corpus_capture.py +684 -0
- 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 +565 -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 +945 -0
- omnibase_infra/services/service_health.py +898 -0
- omnibase_infra/services/service_node_selector.py +530 -0
- omnibase_infra/services/service_timeout_emitter.py +699 -0
- omnibase_infra/services/service_timeout_scanner.py +394 -0
- omnibase_infra/services/session/__init__.py +56 -0
- omnibase_infra/services/session/config_consumer.py +137 -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/services/snapshot/__init__.py +31 -0
- omnibase_infra/services/snapshot/service_snapshot.py +647 -0
- omnibase_infra/services/snapshot/store_inmemory.py +637 -0
- omnibase_infra/services/snapshot/store_postgres.py +1279 -0
- omnibase_infra/shared/__init__.py +8 -0
- omnibase_infra/testing/__init__.py +10 -0
- omnibase_infra/testing/utils.py +23 -0
- omnibase_infra/topics/__init__.py +45 -0
- omnibase_infra/topics/platform_topic_suffixes.py +140 -0
- omnibase_infra/topics/util_topic_composition.py +95 -0
- omnibase_infra/types/__init__.py +48 -0
- omnibase_infra/types/type_cache_info.py +49 -0
- omnibase_infra/types/type_dsn.py +173 -0
- omnibase_infra/types/type_infra_aliases.py +60 -0
- omnibase_infra/types/typed_dict/__init__.py +29 -0
- omnibase_infra/types/typed_dict/typed_dict_envelope_build_params.py +115 -0
- omnibase_infra/types/typed_dict/typed_dict_introspection_cache.py +128 -0
- omnibase_infra/types/typed_dict/typed_dict_performance_metrics_cache.py +140 -0
- omnibase_infra/types/typed_dict_capabilities.py +64 -0
- omnibase_infra/utils/__init__.py +117 -0
- omnibase_infra/utils/correlation.py +208 -0
- omnibase_infra/utils/util_atomic_file.py +261 -0
- omnibase_infra/utils/util_consumer_group.py +232 -0
- omnibase_infra/utils/util_datetime.py +372 -0
- omnibase_infra/utils/util_db_transaction.py +239 -0
- omnibase_infra/utils/util_dsn_validation.py +333 -0
- omnibase_infra/utils/util_env_parsing.py +264 -0
- omnibase_infra/utils/util_error_sanitization.py +457 -0
- omnibase_infra/utils/util_pydantic_validators.py +477 -0
- omnibase_infra/utils/util_retry_optimistic.py +281 -0
- omnibase_infra/utils/util_semver.py +233 -0
- omnibase_infra/validation/__init__.py +307 -0
- omnibase_infra/validation/contracts/security.validation.yaml +114 -0
- omnibase_infra/validation/enums/__init__.py +11 -0
- omnibase_infra/validation/enums/enum_contract_violation_severity.py +13 -0
- omnibase_infra/validation/infra_validators.py +1514 -0
- omnibase_infra/validation/linter_contract.py +907 -0
- omnibase_infra/validation/mixin_any_type_classification.py +120 -0
- omnibase_infra/validation/mixin_any_type_exemption.py +580 -0
- omnibase_infra/validation/mixin_any_type_reporting.py +106 -0
- omnibase_infra/validation/mixin_execution_shape_violation_checks.py +596 -0
- omnibase_infra/validation/mixin_node_archetype_detection.py +254 -0
- omnibase_infra/validation/models/__init__.py +15 -0
- omnibase_infra/validation/models/model_contract_lint_result.py +101 -0
- omnibase_infra/validation/models/model_contract_violation.py +41 -0
- omnibase_infra/validation/service_validation_aggregator.py +395 -0
- omnibase_infra/validation/validation_exemptions.yaml +2033 -0
- omnibase_infra/validation/validator_any_type.py +715 -0
- omnibase_infra/validation/validator_chain_propagation.py +839 -0
- omnibase_infra/validation/validator_execution_shape.py +465 -0
- omnibase_infra/validation/validator_localhandler.py +261 -0
- omnibase_infra/validation/validator_registration_security.py +410 -0
- omnibase_infra/validation/validator_routing_coverage.py +1020 -0
- omnibase_infra/validation/validator_runtime_shape.py +915 -0
- omnibase_infra/validation/validator_security.py +513 -0
- omnibase_infra/validation/validator_topic_category.py +1152 -0
- omnibase_infra-0.2.6.dist-info/METADATA +197 -0
- omnibase_infra-0.2.6.dist-info/RECORD +833 -0
- omnibase_infra-0.2.6.dist-info/WHEEL +4 -0
- omnibase_infra-0.2.6.dist-info/entry_points.txt +5 -0
- omnibase_infra-0.2.6.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,811 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2025 OmniNode Team
|
|
3
|
+
"""Emit Daemon Client - Python client for emitting events via the daemon.
|
|
4
|
+
|
|
5
|
+
This module provides the EmitClient class for communicating with the EmitDaemon
|
|
6
|
+
via Unix socket. It offers fire-and-forget semantics where the client returns
|
|
7
|
+
as soon as the daemon acknowledges the event has been queued.
|
|
8
|
+
|
|
9
|
+
Features:
|
|
10
|
+
- Async and sync interfaces for flexibility
|
|
11
|
+
- Automatic connection management
|
|
12
|
+
- Timeout handling with configurable limits
|
|
13
|
+
- Health check (ping) support
|
|
14
|
+
- Graceful degradation with fallback callback
|
|
15
|
+
|
|
16
|
+
Protocol:
|
|
17
|
+
Request: {"event_type": "...", "payload": {...}}\\n
|
|
18
|
+
Response: {"status": "queued", "event_id": "..."}\\n or {"status": "error", "reason": "..."}\\n
|
|
19
|
+
Ping: {"command": "ping"}\\n -> {"status": "ok", "queue_size": N, "spool_size": M}\\n
|
|
20
|
+
|
|
21
|
+
Example:
|
|
22
|
+
```python
|
|
23
|
+
from omnibase_infra.runtime.emit_daemon.client import EmitClient
|
|
24
|
+
|
|
25
|
+
# Async usage
|
|
26
|
+
async with EmitClient() as client:
|
|
27
|
+
event_id = await client.emit("prompt.submitted", {"prompt_id": "abc123"})
|
|
28
|
+
|
|
29
|
+
# Sync usage (for scripts)
|
|
30
|
+
client = EmitClient()
|
|
31
|
+
event_id = client.emit_sync("prompt.submitted", {"prompt_id": "abc123"})
|
|
32
|
+
|
|
33
|
+
# Convenience function
|
|
34
|
+
event_id = await emit_event("prompt.submitted", {"prompt_id": "abc123"})
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Related Tickets:
|
|
38
|
+
- OMN-1610: Hook Event Daemon MVP
|
|
39
|
+
|
|
40
|
+
.. versionadded:: 0.2.6
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
from __future__ import annotations
|
|
44
|
+
|
|
45
|
+
import asyncio
|
|
46
|
+
import json
|
|
47
|
+
import logging
|
|
48
|
+
from collections.abc import Awaitable, Callable, Coroutine
|
|
49
|
+
from pathlib import Path
|
|
50
|
+
from types import TracebackType
|
|
51
|
+
from typing import TypeVar
|
|
52
|
+
|
|
53
|
+
from pydantic import ValidationError
|
|
54
|
+
|
|
55
|
+
from omnibase_core.enums import EnumCoreErrorCode
|
|
56
|
+
from omnibase_core.errors import OnexError
|
|
57
|
+
from omnibase_core.types import JsonType
|
|
58
|
+
from omnibase_infra.runtime.emit_daemon.model_daemon_request import (
|
|
59
|
+
ModelDaemonEmitRequest,
|
|
60
|
+
ModelDaemonPingRequest,
|
|
61
|
+
)
|
|
62
|
+
from omnibase_infra.runtime.emit_daemon.model_daemon_response import (
|
|
63
|
+
ModelDaemonErrorResponse,
|
|
64
|
+
ModelDaemonPingResponse,
|
|
65
|
+
ModelDaemonQueuedResponse,
|
|
66
|
+
parse_daemon_response,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
logger = logging.getLogger(__name__)
|
|
70
|
+
|
|
71
|
+
# Type variable for generic async runner
|
|
72
|
+
_T = TypeVar("_T")
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class EmitClientError(OnexError):
|
|
76
|
+
"""Error communicating with emit daemon.
|
|
77
|
+
|
|
78
|
+
Raised when the client cannot connect to the daemon, the daemon rejects
|
|
79
|
+
the event, or a timeout occurs during communication.
|
|
80
|
+
|
|
81
|
+
Inherits from OnexError for consistent error handling across the ONEX platform.
|
|
82
|
+
|
|
83
|
+
Attributes:
|
|
84
|
+
reason: Optional detailed reason for the error (from daemon response).
|
|
85
|
+
|
|
86
|
+
Example:
|
|
87
|
+
```python
|
|
88
|
+
try:
|
|
89
|
+
await client.emit("event.type", {"data": "value"})
|
|
90
|
+
except EmitClientError as e:
|
|
91
|
+
print(f"Failed to emit: {e}")
|
|
92
|
+
if e.reason:
|
|
93
|
+
print(f"Reason: {e.reason}")
|
|
94
|
+
```
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
def __init__(
|
|
98
|
+
self,
|
|
99
|
+
message: str,
|
|
100
|
+
reason: str | None = None,
|
|
101
|
+
error_code: EnumCoreErrorCode = EnumCoreErrorCode.OPERATION_FAILED,
|
|
102
|
+
) -> None:
|
|
103
|
+
"""Initialize the error with a message and optional reason.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
message: Human-readable error message
|
|
107
|
+
reason: Optional detailed reason from daemon response
|
|
108
|
+
error_code: Error code from EnumCoreErrorCode, defaults to OPERATION_FAILED
|
|
109
|
+
"""
|
|
110
|
+
super().__init__(message=message, error_code=error_code)
|
|
111
|
+
self.reason = reason
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class EmitClient:
|
|
115
|
+
"""Client for emitting events via the emit daemon.
|
|
116
|
+
|
|
117
|
+
Connects to the daemon's Unix socket and sends events with fire-and-forget
|
|
118
|
+
semantics. The client returns as soon as the daemon acknowledges the event
|
|
119
|
+
has been queued for Kafka publishing.
|
|
120
|
+
|
|
121
|
+
The client supports both async context manager usage for connection pooling
|
|
122
|
+
and standalone usage where each operation creates a new connection.
|
|
123
|
+
|
|
124
|
+
Attributes:
|
|
125
|
+
socket_path: Path to the daemon's Unix socket
|
|
126
|
+
timeout: Timeout in seconds for socket operations
|
|
127
|
+
|
|
128
|
+
Example:
|
|
129
|
+
```python
|
|
130
|
+
# Context manager usage (recommended for multiple operations)
|
|
131
|
+
async with EmitClient() as client:
|
|
132
|
+
await client.emit("event.one", {"data": "1"})
|
|
133
|
+
await client.emit("event.two", {"data": "2"})
|
|
134
|
+
|
|
135
|
+
# Standalone usage (creates new connection per operation)
|
|
136
|
+
client = EmitClient()
|
|
137
|
+
await client.emit("event.single", {"data": "value"})
|
|
138
|
+
|
|
139
|
+
# Custom socket path and timeout
|
|
140
|
+
client = EmitClient(
|
|
141
|
+
socket_path=Path("/custom/emit.sock"),
|
|
142
|
+
timeout=10.0,
|
|
143
|
+
)
|
|
144
|
+
```
|
|
145
|
+
"""
|
|
146
|
+
|
|
147
|
+
# Default socket path matching daemon config default
|
|
148
|
+
# NOTE: /tmp is standard for Unix domain sockets - not a security issue
|
|
149
|
+
DEFAULT_SOCKET_PATH: Path = Path("/tmp/omniclaude-emit.sock") # noqa: S108
|
|
150
|
+
|
|
151
|
+
# Default timeout in seconds
|
|
152
|
+
DEFAULT_TIMEOUT: float = 5.0
|
|
153
|
+
|
|
154
|
+
def __init__(
|
|
155
|
+
self,
|
|
156
|
+
socket_path: Path | str = DEFAULT_SOCKET_PATH,
|
|
157
|
+
timeout: float = DEFAULT_TIMEOUT,
|
|
158
|
+
) -> None:
|
|
159
|
+
"""Initialize client with socket path and timeout.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
socket_path: Path to the daemon's Unix socket. Defaults to
|
|
163
|
+
/tmp/omniclaude-emit.sock to match daemon default.
|
|
164
|
+
timeout: Timeout in seconds for socket operations. Defaults to 5.0.
|
|
165
|
+
|
|
166
|
+
Example:
|
|
167
|
+
```python
|
|
168
|
+
# Use defaults
|
|
169
|
+
client = EmitClient()
|
|
170
|
+
|
|
171
|
+
# Custom configuration
|
|
172
|
+
client = EmitClient(
|
|
173
|
+
socket_path="/var/run/emit.sock",
|
|
174
|
+
timeout=10.0,
|
|
175
|
+
)
|
|
176
|
+
```
|
|
177
|
+
"""
|
|
178
|
+
self._socket_path = (
|
|
179
|
+
Path(socket_path) if isinstance(socket_path, str) else socket_path
|
|
180
|
+
)
|
|
181
|
+
self._timeout = timeout
|
|
182
|
+
self._reader: asyncio.StreamReader | None = None
|
|
183
|
+
self._writer: asyncio.StreamWriter | None = None
|
|
184
|
+
self._lock = asyncio.Lock()
|
|
185
|
+
|
|
186
|
+
logger.debug(
|
|
187
|
+
"EmitClient initialized",
|
|
188
|
+
extra={
|
|
189
|
+
"socket_path": str(self._socket_path),
|
|
190
|
+
"timeout": self._timeout,
|
|
191
|
+
},
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
@property
|
|
195
|
+
def socket_path(self) -> Path:
|
|
196
|
+
"""Get the socket path.
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
Path to the daemon's Unix socket.
|
|
200
|
+
"""
|
|
201
|
+
return self._socket_path
|
|
202
|
+
|
|
203
|
+
@property
|
|
204
|
+
def timeout(self) -> float:
|
|
205
|
+
"""Get the timeout value.
|
|
206
|
+
|
|
207
|
+
Returns:
|
|
208
|
+
Timeout in seconds for socket operations.
|
|
209
|
+
"""
|
|
210
|
+
return self._timeout
|
|
211
|
+
|
|
212
|
+
async def __aenter__(self) -> EmitClient:
|
|
213
|
+
"""Enter async context manager, establishing connection.
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
Self for use in async with statement.
|
|
217
|
+
|
|
218
|
+
Raises:
|
|
219
|
+
EmitClientError: If connection to daemon fails.
|
|
220
|
+
"""
|
|
221
|
+
await self._connect()
|
|
222
|
+
return self
|
|
223
|
+
|
|
224
|
+
async def __aexit__(
|
|
225
|
+
self,
|
|
226
|
+
exc_type: type[BaseException] | None,
|
|
227
|
+
exc_val: BaseException | None,
|
|
228
|
+
exc_tb: TracebackType | None,
|
|
229
|
+
) -> None:
|
|
230
|
+
"""Exit async context manager, closing connection.
|
|
231
|
+
|
|
232
|
+
Args:
|
|
233
|
+
exc_type: Exception type if an exception was raised
|
|
234
|
+
exc_val: Exception value if an exception was raised
|
|
235
|
+
exc_tb: Exception traceback if an exception was raised
|
|
236
|
+
"""
|
|
237
|
+
await self._disconnect()
|
|
238
|
+
|
|
239
|
+
async def _connect_unlocked(self) -> None:
|
|
240
|
+
"""Establish connection to daemon socket (without lock).
|
|
241
|
+
|
|
242
|
+
Internal method - caller must hold self._lock.
|
|
243
|
+
|
|
244
|
+
Raises:
|
|
245
|
+
EmitClientError: If connection fails (daemon not running, permission denied, etc.)
|
|
246
|
+
"""
|
|
247
|
+
if self._writer is not None:
|
|
248
|
+
return # Already connected
|
|
249
|
+
|
|
250
|
+
try:
|
|
251
|
+
self._reader, self._writer = await asyncio.wait_for(
|
|
252
|
+
asyncio.open_unix_connection(str(self._socket_path)),
|
|
253
|
+
timeout=self._timeout,
|
|
254
|
+
)
|
|
255
|
+
logger.debug(f"Connected to emit daemon at {self._socket_path}")
|
|
256
|
+
except FileNotFoundError as e:
|
|
257
|
+
raise EmitClientError(
|
|
258
|
+
f"Emit daemon socket not found at {self._socket_path}. "
|
|
259
|
+
"Is the daemon running?",
|
|
260
|
+
reason="socket_not_found",
|
|
261
|
+
error_code=EnumCoreErrorCode.RESOURCE_NOT_FOUND,
|
|
262
|
+
) from e
|
|
263
|
+
except PermissionError as e:
|
|
264
|
+
raise EmitClientError(
|
|
265
|
+
f"Permission denied accessing emit daemon socket at {self._socket_path}",
|
|
266
|
+
reason="permission_denied",
|
|
267
|
+
error_code=EnumCoreErrorCode.PERMISSION_DENIED,
|
|
268
|
+
) from e
|
|
269
|
+
except ConnectionRefusedError as e:
|
|
270
|
+
raise EmitClientError(
|
|
271
|
+
f"Connection refused to emit daemon at {self._socket_path}. "
|
|
272
|
+
"Is the daemon running?",
|
|
273
|
+
reason="connection_refused",
|
|
274
|
+
error_code=EnumCoreErrorCode.SERVICE_UNAVAILABLE,
|
|
275
|
+
) from e
|
|
276
|
+
except TimeoutError as e:
|
|
277
|
+
raise EmitClientError(
|
|
278
|
+
f"Timeout connecting to emit daemon at {self._socket_path}",
|
|
279
|
+
reason="connection_timeout",
|
|
280
|
+
error_code=EnumCoreErrorCode.TIMEOUT_ERROR,
|
|
281
|
+
) from e
|
|
282
|
+
except OSError as e:
|
|
283
|
+
raise EmitClientError(
|
|
284
|
+
f"Failed to connect to emit daemon: {e}",
|
|
285
|
+
reason="os_error",
|
|
286
|
+
error_code=EnumCoreErrorCode.NETWORK_ERROR,
|
|
287
|
+
) from e
|
|
288
|
+
|
|
289
|
+
async def _connect(self) -> None:
|
|
290
|
+
"""Establish connection to daemon socket.
|
|
291
|
+
|
|
292
|
+
Internal method called by context manager or lazily on first operation.
|
|
293
|
+
|
|
294
|
+
Raises:
|
|
295
|
+
EmitClientError: If connection fails (daemon not running, permission denied, etc.)
|
|
296
|
+
"""
|
|
297
|
+
async with self._lock:
|
|
298
|
+
await self._connect_unlocked()
|
|
299
|
+
|
|
300
|
+
async def _disconnect_unlocked(self) -> None:
|
|
301
|
+
"""Close connection to daemon socket (without lock).
|
|
302
|
+
|
|
303
|
+
Internal method - caller must hold self._lock.
|
|
304
|
+
Safe to call multiple times.
|
|
305
|
+
"""
|
|
306
|
+
if self._writer is not None:
|
|
307
|
+
try:
|
|
308
|
+
self._writer.close()
|
|
309
|
+
await self._writer.wait_closed()
|
|
310
|
+
except Exception as e:
|
|
311
|
+
logger.debug(f"Error during disconnect cleanup: {e}")
|
|
312
|
+
finally:
|
|
313
|
+
self._writer = None
|
|
314
|
+
self._reader = None
|
|
315
|
+
logger.debug("Disconnected from emit daemon")
|
|
316
|
+
|
|
317
|
+
async def _disconnect(self) -> None:
|
|
318
|
+
"""Close connection to daemon socket.
|
|
319
|
+
|
|
320
|
+
Internal method called by context manager or cleanup operations.
|
|
321
|
+
Safe to call multiple times.
|
|
322
|
+
"""
|
|
323
|
+
async with self._lock:
|
|
324
|
+
await self._disconnect_unlocked()
|
|
325
|
+
|
|
326
|
+
async def _send_request(self, request: JsonType) -> dict[str, object]:
|
|
327
|
+
"""Send a request and receive response.
|
|
328
|
+
|
|
329
|
+
Internal method for protocol communication. Acquires lock to ensure
|
|
330
|
+
the write-then-read sequence is atomic, preventing response mixing
|
|
331
|
+
when multiple coroutines call emit() concurrently.
|
|
332
|
+
|
|
333
|
+
Args:
|
|
334
|
+
request: Request dict to send (will be JSON-encoded)
|
|
335
|
+
|
|
336
|
+
Returns:
|
|
337
|
+
Response dict from daemon
|
|
338
|
+
|
|
339
|
+
Raises:
|
|
340
|
+
EmitClientError: If communication fails
|
|
341
|
+
"""
|
|
342
|
+
async with self._lock:
|
|
343
|
+
# Ensure we're connected (use unlocked variant since we hold the lock)
|
|
344
|
+
if self._writer is None or self._reader is None:
|
|
345
|
+
await self._connect_unlocked()
|
|
346
|
+
|
|
347
|
+
# Type guard - we just connected, so these should be set
|
|
348
|
+
if self._writer is None or self._reader is None:
|
|
349
|
+
raise EmitClientError(
|
|
350
|
+
"Failed to establish connection", reason="no_connection"
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
try:
|
|
354
|
+
# Send request
|
|
355
|
+
request_json = json.dumps(request) + "\n"
|
|
356
|
+
self._writer.write(request_json.encode("utf-8"))
|
|
357
|
+
await self._writer.drain()
|
|
358
|
+
|
|
359
|
+
# Receive response with timeout
|
|
360
|
+
response_line = await asyncio.wait_for(
|
|
361
|
+
self._reader.readline(),
|
|
362
|
+
timeout=self._timeout,
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
if not response_line:
|
|
366
|
+
# Connection closed by daemon
|
|
367
|
+
await self._disconnect_unlocked()
|
|
368
|
+
raise EmitClientError(
|
|
369
|
+
"Connection closed by emit daemon",
|
|
370
|
+
reason="connection_closed",
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
# Parse response
|
|
374
|
+
response = json.loads(response_line.decode("utf-8").strip())
|
|
375
|
+
if not isinstance(response, dict):
|
|
376
|
+
raise EmitClientError(
|
|
377
|
+
"Invalid response from daemon: expected JSON object",
|
|
378
|
+
reason="invalid_response",
|
|
379
|
+
)
|
|
380
|
+
return response
|
|
381
|
+
|
|
382
|
+
except TimeoutError as e:
|
|
383
|
+
await self._disconnect_unlocked()
|
|
384
|
+
raise EmitClientError(
|
|
385
|
+
f"Timeout waiting for daemon response (timeout={self._timeout}s)",
|
|
386
|
+
reason="response_timeout",
|
|
387
|
+
error_code=EnumCoreErrorCode.TIMEOUT_ERROR,
|
|
388
|
+
) from e
|
|
389
|
+
except json.JSONDecodeError as e:
|
|
390
|
+
await self._disconnect_unlocked()
|
|
391
|
+
raise EmitClientError(
|
|
392
|
+
f"Invalid JSON response from daemon: {e}",
|
|
393
|
+
reason="invalid_json",
|
|
394
|
+
error_code=EnumCoreErrorCode.VALIDATION_ERROR,
|
|
395
|
+
) from e
|
|
396
|
+
except ConnectionResetError as e:
|
|
397
|
+
await self._disconnect_unlocked()
|
|
398
|
+
raise EmitClientError(
|
|
399
|
+
"Connection reset by emit daemon",
|
|
400
|
+
reason="connection_reset",
|
|
401
|
+
error_code=EnumCoreErrorCode.NETWORK_ERROR,
|
|
402
|
+
) from e
|
|
403
|
+
except BrokenPipeError as e:
|
|
404
|
+
await self._disconnect_unlocked()
|
|
405
|
+
raise EmitClientError(
|
|
406
|
+
"Broken pipe to emit daemon",
|
|
407
|
+
reason="broken_pipe",
|
|
408
|
+
error_code=EnumCoreErrorCode.NETWORK_ERROR,
|
|
409
|
+
) from e
|
|
410
|
+
|
|
411
|
+
async def emit(
|
|
412
|
+
self,
|
|
413
|
+
event_type: str,
|
|
414
|
+
payload: JsonType,
|
|
415
|
+
) -> str:
|
|
416
|
+
"""Emit an event via the daemon.
|
|
417
|
+
|
|
418
|
+
Sends an event to the daemon for asynchronous publishing to Kafka.
|
|
419
|
+
Returns as soon as the daemon acknowledges the event has been queued.
|
|
420
|
+
|
|
421
|
+
Args:
|
|
422
|
+
event_type: Semantic event type (e.g., "prompt.submitted",
|
|
423
|
+
"tool.invoked"). Must be registered with the daemon's
|
|
424
|
+
EventRegistry.
|
|
425
|
+
payload: Event payload dict. Must contain required fields for
|
|
426
|
+
the event type as defined in EventRegistry.
|
|
427
|
+
|
|
428
|
+
Returns:
|
|
429
|
+
Event ID assigned by the daemon (UUID string). This can be used
|
|
430
|
+
for tracking/debugging but is not needed for normal operation.
|
|
431
|
+
|
|
432
|
+
Raises:
|
|
433
|
+
EmitClientError: If daemon is unavailable, rejects the event,
|
|
434
|
+
or a timeout occurs.
|
|
435
|
+
|
|
436
|
+
Example:
|
|
437
|
+
```python
|
|
438
|
+
event_id = await client.emit(
|
|
439
|
+
"prompt.submitted",
|
|
440
|
+
{
|
|
441
|
+
"prompt_id": "abc123",
|
|
442
|
+
"session_id": "sess-456",
|
|
443
|
+
"prompt_text": "Hello, Claude!",
|
|
444
|
+
},
|
|
445
|
+
)
|
|
446
|
+
print(f"Event queued with ID: {event_id}")
|
|
447
|
+
```
|
|
448
|
+
"""
|
|
449
|
+
# Build typed request
|
|
450
|
+
request = ModelDaemonEmitRequest(event_type=event_type, payload=payload)
|
|
451
|
+
raw_response = await self._send_request(request.model_dump())
|
|
452
|
+
|
|
453
|
+
# Parse typed response
|
|
454
|
+
try:
|
|
455
|
+
response = parse_daemon_response(raw_response)
|
|
456
|
+
except (ValueError, ValidationError) as e:
|
|
457
|
+
raise EmitClientError(
|
|
458
|
+
f"Invalid daemon response: {e}",
|
|
459
|
+
reason="invalid_response",
|
|
460
|
+
) from e
|
|
461
|
+
|
|
462
|
+
# Handle response by type
|
|
463
|
+
if isinstance(response, ModelDaemonQueuedResponse):
|
|
464
|
+
logger.debug(
|
|
465
|
+
f"Event emitted: {response.event_id}",
|
|
466
|
+
extra={
|
|
467
|
+
"event_type": event_type,
|
|
468
|
+
"event_id": response.event_id,
|
|
469
|
+
},
|
|
470
|
+
)
|
|
471
|
+
return response.event_id
|
|
472
|
+
elif isinstance(response, ModelDaemonErrorResponse):
|
|
473
|
+
raise EmitClientError(
|
|
474
|
+
f"Daemon rejected event: {response.reason}",
|
|
475
|
+
reason=response.reason,
|
|
476
|
+
)
|
|
477
|
+
elif isinstance(response, ModelDaemonPingResponse):
|
|
478
|
+
# Unexpected ping response to emit request
|
|
479
|
+
raise EmitClientError(
|
|
480
|
+
"Unexpected ping response to emit request",
|
|
481
|
+
reason="unexpected_response_type",
|
|
482
|
+
)
|
|
483
|
+
else:
|
|
484
|
+
# Should be unreachable
|
|
485
|
+
raise EmitClientError(
|
|
486
|
+
"Unexpected daemon response type",
|
|
487
|
+
reason="unexpected_status",
|
|
488
|
+
)
|
|
489
|
+
|
|
490
|
+
async def ping(self) -> ModelDaemonPingResponse:
|
|
491
|
+
"""Health check the daemon.
|
|
492
|
+
|
|
493
|
+
Sends a ping command to the daemon to verify it is running and
|
|
494
|
+
get current queue status.
|
|
495
|
+
|
|
496
|
+
Returns:
|
|
497
|
+
ModelDaemonPingResponse with:
|
|
498
|
+
- status: "ok" (always for successful ping)
|
|
499
|
+
- queue_size: Number of events in memory queue
|
|
500
|
+
- spool_size: Number of events spooled to disk
|
|
501
|
+
|
|
502
|
+
Raises:
|
|
503
|
+
EmitClientError: If daemon is unavailable or returns error.
|
|
504
|
+
|
|
505
|
+
Example:
|
|
506
|
+
```python
|
|
507
|
+
status = await client.ping()
|
|
508
|
+
print(f"Queue size: {status.queue_size}")
|
|
509
|
+
print(f"Spool size: {status.spool_size}")
|
|
510
|
+
```
|
|
511
|
+
"""
|
|
512
|
+
# Build typed request
|
|
513
|
+
request = ModelDaemonPingRequest()
|
|
514
|
+
raw_response = await self._send_request(request.model_dump())
|
|
515
|
+
|
|
516
|
+
# Parse typed response
|
|
517
|
+
try:
|
|
518
|
+
response = parse_daemon_response(raw_response)
|
|
519
|
+
except (ValueError, ValidationError) as e:
|
|
520
|
+
raise EmitClientError(
|
|
521
|
+
f"Invalid daemon response: {e}",
|
|
522
|
+
reason="invalid_response",
|
|
523
|
+
) from e
|
|
524
|
+
|
|
525
|
+
# Handle response by type
|
|
526
|
+
if isinstance(response, ModelDaemonPingResponse):
|
|
527
|
+
logger.debug(
|
|
528
|
+
"Daemon ping successful",
|
|
529
|
+
extra={
|
|
530
|
+
"queue_size": response.queue_size,
|
|
531
|
+
"spool_size": response.spool_size,
|
|
532
|
+
},
|
|
533
|
+
)
|
|
534
|
+
return response
|
|
535
|
+
elif isinstance(response, ModelDaemonErrorResponse):
|
|
536
|
+
raise EmitClientError(
|
|
537
|
+
f"Daemon ping error: {response.reason}",
|
|
538
|
+
reason=response.reason,
|
|
539
|
+
)
|
|
540
|
+
elif isinstance(response, ModelDaemonQueuedResponse):
|
|
541
|
+
# Unexpected queued response to ping request
|
|
542
|
+
raise EmitClientError(
|
|
543
|
+
"Unexpected queued response to ping request",
|
|
544
|
+
reason="unexpected_response_type",
|
|
545
|
+
)
|
|
546
|
+
else:
|
|
547
|
+
# Should be unreachable
|
|
548
|
+
raise EmitClientError(
|
|
549
|
+
"Unexpected daemon ping response type",
|
|
550
|
+
reason="unexpected_status",
|
|
551
|
+
)
|
|
552
|
+
|
|
553
|
+
async def is_daemon_running(self) -> bool:
|
|
554
|
+
"""Check if daemon is running and responsive.
|
|
555
|
+
|
|
556
|
+
Attempts to ping the daemon and returns True if successful.
|
|
557
|
+
Unlike ping(), this method does not raise exceptions - it simply
|
|
558
|
+
returns False if the daemon is unavailable.
|
|
559
|
+
|
|
560
|
+
Returns:
|
|
561
|
+
True if daemon responds to ping, False otherwise.
|
|
562
|
+
|
|
563
|
+
Example:
|
|
564
|
+
```python
|
|
565
|
+
if await client.is_daemon_running():
|
|
566
|
+
await client.emit("event.type", {"data": "value"})
|
|
567
|
+
else:
|
|
568
|
+
# Fall back to direct Kafka publish
|
|
569
|
+
await direct_publish("event.type", {"data": "value"})
|
|
570
|
+
```
|
|
571
|
+
"""
|
|
572
|
+
try:
|
|
573
|
+
await self.ping()
|
|
574
|
+
return True
|
|
575
|
+
except EmitClientError:
|
|
576
|
+
return False
|
|
577
|
+
except Exception:
|
|
578
|
+
return False
|
|
579
|
+
|
|
580
|
+
def emit_sync(
|
|
581
|
+
self,
|
|
582
|
+
event_type: str,
|
|
583
|
+
payload: JsonType,
|
|
584
|
+
) -> str:
|
|
585
|
+
"""Synchronous wrapper for emit().
|
|
586
|
+
|
|
587
|
+
Creates an event loop if needed, calls emit(), and returns the result.
|
|
588
|
+
Useful for shell scripts and non-async code.
|
|
589
|
+
|
|
590
|
+
Note: This method creates a new connection for each call. For multiple
|
|
591
|
+
operations, consider using async code with the context manager.
|
|
592
|
+
|
|
593
|
+
Args:
|
|
594
|
+
event_type: Semantic event type (e.g., "prompt.submitted")
|
|
595
|
+
payload: Event payload dict
|
|
596
|
+
|
|
597
|
+
Returns:
|
|
598
|
+
Event ID assigned by the daemon
|
|
599
|
+
|
|
600
|
+
Raises:
|
|
601
|
+
EmitClientError: If daemon is unavailable or rejects the event
|
|
602
|
+
|
|
603
|
+
Example:
|
|
604
|
+
```python
|
|
605
|
+
# In a non-async context (shell script, simple script)
|
|
606
|
+
client = EmitClient()
|
|
607
|
+
event_id = client.emit_sync("prompt.submitted", {"prompt_id": "abc"})
|
|
608
|
+
```
|
|
609
|
+
"""
|
|
610
|
+
return self._run_async(self._emit_and_disconnect(event_type, payload))
|
|
611
|
+
|
|
612
|
+
def ping_sync(self) -> ModelDaemonPingResponse:
|
|
613
|
+
"""Synchronous wrapper for ping().
|
|
614
|
+
|
|
615
|
+
Creates an event loop if needed, calls ping(), and returns the result.
|
|
616
|
+
Useful for shell scripts and health checks.
|
|
617
|
+
|
|
618
|
+
Returns:
|
|
619
|
+
ModelDaemonPingResponse with status, queue_size, spool_size
|
|
620
|
+
|
|
621
|
+
Raises:
|
|
622
|
+
EmitClientError: If daemon is unavailable
|
|
623
|
+
|
|
624
|
+
Example:
|
|
625
|
+
```python
|
|
626
|
+
status = EmitClient().ping_sync()
|
|
627
|
+
print(f"Daemon healthy, queue size: {status.queue_size}")
|
|
628
|
+
```
|
|
629
|
+
"""
|
|
630
|
+
return self._run_async(self._ping_and_disconnect())
|
|
631
|
+
|
|
632
|
+
def is_daemon_running_sync(self) -> bool:
|
|
633
|
+
"""Synchronous wrapper for is_daemon_running().
|
|
634
|
+
|
|
635
|
+
Returns:
|
|
636
|
+
True if daemon responds to ping, False otherwise.
|
|
637
|
+
"""
|
|
638
|
+
return self._run_async(self.is_daemon_running())
|
|
639
|
+
|
|
640
|
+
async def _emit_and_disconnect(
|
|
641
|
+
self,
|
|
642
|
+
event_type: str,
|
|
643
|
+
payload: JsonType,
|
|
644
|
+
) -> str:
|
|
645
|
+
"""Emit event and disconnect (for sync wrapper).
|
|
646
|
+
|
|
647
|
+
Args:
|
|
648
|
+
event_type: Event type to emit
|
|
649
|
+
payload: Event payload
|
|
650
|
+
|
|
651
|
+
Returns:
|
|
652
|
+
Event ID from daemon
|
|
653
|
+
"""
|
|
654
|
+
try:
|
|
655
|
+
return await self.emit(event_type, payload)
|
|
656
|
+
finally:
|
|
657
|
+
await self._disconnect()
|
|
658
|
+
|
|
659
|
+
async def _ping_and_disconnect(self) -> ModelDaemonPingResponse:
|
|
660
|
+
"""Ping daemon and disconnect (for sync wrapper).
|
|
661
|
+
|
|
662
|
+
Returns:
|
|
663
|
+
Typed ping response from daemon
|
|
664
|
+
"""
|
|
665
|
+
try:
|
|
666
|
+
return await self.ping()
|
|
667
|
+
finally:
|
|
668
|
+
await self._disconnect()
|
|
669
|
+
|
|
670
|
+
def _run_async(self, coro: Coroutine[object, object, _T]) -> _T:
|
|
671
|
+
"""Run an async coroutine in a sync context.
|
|
672
|
+
|
|
673
|
+
Handles event loop creation for sync wrappers.
|
|
674
|
+
|
|
675
|
+
Args:
|
|
676
|
+
coro: Coroutine to run
|
|
677
|
+
|
|
678
|
+
Returns:
|
|
679
|
+
Result from the coroutine
|
|
680
|
+
"""
|
|
681
|
+
try:
|
|
682
|
+
# Check if we're in an existing event loop
|
|
683
|
+
loop = asyncio.get_running_loop()
|
|
684
|
+
except RuntimeError:
|
|
685
|
+
# No running loop - create a new one
|
|
686
|
+
loop = None
|
|
687
|
+
|
|
688
|
+
if loop is not None:
|
|
689
|
+
# We're in an async context - use run_until_complete is not allowed
|
|
690
|
+
# Create a new event loop in a thread would be complex
|
|
691
|
+
# Instead, raise an error suggesting async usage
|
|
692
|
+
raise RuntimeError(
|
|
693
|
+
"Cannot use sync methods from an async context. "
|
|
694
|
+
"Use the async emit() or ping() methods instead."
|
|
695
|
+
)
|
|
696
|
+
|
|
697
|
+
# No running loop - safe to use asyncio.run()
|
|
698
|
+
return asyncio.run(coro)
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+
# Module-level convenience functions
|
|
702
|
+
|
|
703
|
+
|
|
704
|
+
async def emit_event(
|
|
705
|
+
event_type: str,
|
|
706
|
+
payload: JsonType,
|
|
707
|
+
socket_path: Path | str = EmitClient.DEFAULT_SOCKET_PATH,
|
|
708
|
+
timeout: float = EmitClient.DEFAULT_TIMEOUT,
|
|
709
|
+
) -> str:
|
|
710
|
+
"""Convenience function to emit a single event.
|
|
711
|
+
|
|
712
|
+
Creates a client, emits the event, and closes the connection.
|
|
713
|
+
For multiple events, use EmitClient as a context manager instead.
|
|
714
|
+
|
|
715
|
+
Args:
|
|
716
|
+
event_type: Semantic event type (e.g., "prompt.submitted")
|
|
717
|
+
payload: Event payload dict
|
|
718
|
+
socket_path: Path to daemon socket (defaults to /tmp/omniclaude-emit.sock)
|
|
719
|
+
timeout: Timeout in seconds for socket operations (defaults to 5.0)
|
|
720
|
+
|
|
721
|
+
Returns:
|
|
722
|
+
Event ID assigned by the daemon
|
|
723
|
+
|
|
724
|
+
Raises:
|
|
725
|
+
EmitClientError: If daemon is unavailable or rejects the event
|
|
726
|
+
|
|
727
|
+
Example:
|
|
728
|
+
```python
|
|
729
|
+
event_id = await emit_event(
|
|
730
|
+
"prompt.submitted",
|
|
731
|
+
{"prompt_id": "abc123", "prompt_text": "Hello!"},
|
|
732
|
+
)
|
|
733
|
+
```
|
|
734
|
+
"""
|
|
735
|
+
async with EmitClient(socket_path=socket_path, timeout=timeout) as client:
|
|
736
|
+
return await client.emit(event_type, payload)
|
|
737
|
+
|
|
738
|
+
|
|
739
|
+
async def emit_event_with_fallback(
|
|
740
|
+
event_type: str,
|
|
741
|
+
payload: JsonType,
|
|
742
|
+
socket_path: Path | str = EmitClient.DEFAULT_SOCKET_PATH,
|
|
743
|
+
timeout: float = EmitClient.DEFAULT_TIMEOUT,
|
|
744
|
+
fallback: Callable[[str, JsonType], Awaitable[str]] | None = None,
|
|
745
|
+
) -> str:
|
|
746
|
+
"""Emit event via daemon, falling back to callback if daemon unavailable.
|
|
747
|
+
|
|
748
|
+
Use this when you want graceful degradation to direct Kafka publish
|
|
749
|
+
(or other fallback mechanism) when the daemon is not running.
|
|
750
|
+
|
|
751
|
+
Args:
|
|
752
|
+
event_type: Semantic event type (e.g., "prompt.submitted")
|
|
753
|
+
payload: Event payload dict
|
|
754
|
+
socket_path: Path to daemon socket (defaults to /tmp/omniclaude-emit.sock)
|
|
755
|
+
timeout: Timeout in seconds for socket operations (defaults to 5.0)
|
|
756
|
+
fallback: Optional async callback to invoke if daemon is unavailable.
|
|
757
|
+
Receives (event_type, payload) and should return event_id string.
|
|
758
|
+
If None and daemon is unavailable, raises EmitClientError.
|
|
759
|
+
|
|
760
|
+
Returns:
|
|
761
|
+
Event ID from daemon or fallback
|
|
762
|
+
|
|
763
|
+
Raises:
|
|
764
|
+
EmitClientError: If daemon unavailable and no fallback provided,
|
|
765
|
+
or if fallback raises an exception.
|
|
766
|
+
|
|
767
|
+
Example:
|
|
768
|
+
```python
|
|
769
|
+
async def direct_kafka_publish(event_type: str, payload: dict) -> str:
|
|
770
|
+
# Direct Kafka publish implementation
|
|
771
|
+
return str(uuid4())
|
|
772
|
+
|
|
773
|
+
event_id = await emit_event_with_fallback(
|
|
774
|
+
"prompt.submitted",
|
|
775
|
+
{"prompt_id": "abc123"},
|
|
776
|
+
fallback=direct_kafka_publish,
|
|
777
|
+
)
|
|
778
|
+
```
|
|
779
|
+
"""
|
|
780
|
+
client = EmitClient(socket_path=socket_path, timeout=timeout)
|
|
781
|
+
|
|
782
|
+
try:
|
|
783
|
+
async with client:
|
|
784
|
+
return await client.emit(event_type, payload)
|
|
785
|
+
except EmitClientError as e:
|
|
786
|
+
# Check if this is a connection error (daemon not running)
|
|
787
|
+
connection_errors = {
|
|
788
|
+
"socket_not_found",
|
|
789
|
+
"connection_refused",
|
|
790
|
+
"connection_timeout",
|
|
791
|
+
"permission_denied",
|
|
792
|
+
"os_error",
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
if e.reason in connection_errors and fallback is not None:
|
|
796
|
+
logger.info(
|
|
797
|
+
f"Daemon unavailable ({e.reason}), using fallback",
|
|
798
|
+
extra={"event_type": event_type},
|
|
799
|
+
)
|
|
800
|
+
return await fallback(event_type, payload)
|
|
801
|
+
|
|
802
|
+
# Re-raise if not a connection error or no fallback
|
|
803
|
+
raise
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
__all__: list[str] = [
|
|
807
|
+
"EmitClient",
|
|
808
|
+
"EmitClientError",
|
|
809
|
+
"emit_event",
|
|
810
|
+
"emit_event_with_fallback",
|
|
811
|
+
]
|