refactor: register event delivery contracts

This commit is contained in:
jxxghp
2026-08-21 21:29:52 +08:00
parent b9ad5220ae
commit c0b31bddb6
7 changed files with 816 additions and 3 deletions
+8 -3
View File
@@ -13,8 +13,8 @@
"runtime_to_db": [],
"workflow_to_db": []
},
"edge_count": 6204,
"edge_sha256": "9a988284502bb26fae5266321765fbf0e10b9fe608fd448c6868e67a824ea862",
"edge_count": 6208,
"edge_sha256": "a91776a358fc4820d1d6f6dc300b3432491dc6b87a0423a99acd0e6c1366526b",
"edges": [
"app -> app.runtime",
"app -> app.runtime.compat",
@@ -5345,6 +5345,9 @@
"app.runtime.event.binding -> app.runtime.event",
"app.runtime.event.binding -> app.runtime.event.registry",
"app.runtime.event.binding -> app.runtime.log",
"app.runtime.event.contracts -> app.schemas",
"app.runtime.event.contracts -> app.schemas.event",
"app.runtime.event.contracts -> app.schemas.types",
"app.runtime.event.dispatch -> app.runtime",
"app.runtime.event.dispatch -> app.runtime.event",
"app.runtime.event.dispatch -> app.runtime.event.binding",
@@ -5367,6 +5370,7 @@
"app.runtime.events -> app.runtime.config",
"app.runtime.events -> app.runtime.event",
"app.runtime.events -> app.runtime.event.binding",
"app.runtime.events -> app.runtime.event.contracts",
"app.runtime.events -> app.runtime.event.dispatch",
"app.runtime.events -> app.runtime.event.errors",
"app.runtime.events -> app.runtime.event.registry",
@@ -6221,7 +6225,7 @@
"app.workflow.actions.transfer_file -> app.workflow",
"app.workflow.actions.transfer_file -> app.workflow.actions"
],
"module_count": 771,
"module_count": 772,
"modules": [
"app",
"app.adapters",
@@ -6852,6 +6856,7 @@
"app.runtime.debounce",
"app.runtime.event",
"app.runtime.event.binding",
"app.runtime.event.contracts",
"app.runtime.event.dispatch",
"app.runtime.event.errors",
"app.runtime.event.registry",
@@ -1159,6 +1159,546 @@
"app.utils"
]
},
"event_specs": {
"ChainEventType.AgentLLMProvider": {
"delivery": "ephemeral",
"error_behavior": "stop_chain",
"legacy_reason": null,
"mode": "chain",
"ordering": "priority_serial",
"payload_contract": "AgentLLMProviderEventData",
"sensitive_fields": [
"api_key"
],
"visibility": "plugin_public"
},
"ChainEventType.AuthIntercept": {
"delivery": "ephemeral",
"error_behavior": "stop_chain",
"legacy_reason": null,
"mode": "chain",
"ordering": "priority_serial",
"payload_contract": "AuthInterceptCredentials",
"sensitive_fields": [
"token"
],
"visibility": "plugin_public"
},
"ChainEventType.AuthVerification": {
"delivery": "ephemeral",
"error_behavior": "stop_chain",
"legacy_reason": null,
"mode": "chain",
"ordering": "priority_serial",
"payload_contract": "AuthCredentials",
"sensitive_fields": [
"password",
"token",
"mfa_code"
],
"visibility": "plugin_public"
},
"ChainEventType.CommandRegister": {
"delivery": "ephemeral",
"error_behavior": "stop_chain",
"legacy_reason": null,
"mode": "chain",
"ordering": "priority_serial",
"payload_contract": "CommandRegisterEventData",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"ChainEventType.DiscoverSource": {
"delivery": "ephemeral",
"error_behavior": "stop_chain",
"legacy_reason": null,
"mode": "chain",
"ordering": "priority_serial",
"payload_contract": "DiscoverSourceEventData",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"ChainEventType.MediaRecognize": {
"delivery": "ephemeral",
"error_behavior": "stop_chain",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "chain",
"ordering": "priority_serial",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"ChainEventType.MediaRecognizeConvert": {
"delivery": "ephemeral",
"error_behavior": "stop_chain",
"legacy_reason": null,
"mode": "chain",
"ordering": "priority_serial",
"payload_contract": "MediaRecognizeConvertEventData",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"ChainEventType.MusicMediaRecognize": {
"delivery": "ephemeral",
"error_behavior": "stop_chain",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "chain",
"ordering": "priority_serial",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"ChainEventType.MusicNameRecognize": {
"delivery": "ephemeral",
"error_behavior": "stop_chain",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "chain",
"ordering": "priority_serial",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"ChainEventType.NameRecognize": {
"delivery": "ephemeral",
"error_behavior": "stop_chain",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "chain",
"ordering": "priority_serial",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"ChainEventType.PluginDataReset": {
"delivery": "ephemeral",
"error_behavior": "stop_chain",
"legacy_reason": null,
"mode": "chain",
"ordering": "priority_serial",
"payload_contract": "PluginDataResetEventData",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"ChainEventType.RecommendSource": {
"delivery": "ephemeral",
"error_behavior": "stop_chain",
"legacy_reason": null,
"mode": "chain",
"ordering": "priority_serial",
"payload_contract": "RecommendSourceEventData",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"ChainEventType.ResourceDownload": {
"delivery": "ephemeral",
"error_behavior": "stop_chain",
"legacy_reason": null,
"mode": "chain",
"ordering": "priority_serial",
"payload_contract": "ResourceDownloadEventData",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"ChainEventType.ResourceSelection": {
"delivery": "ephemeral",
"error_behavior": "stop_chain",
"legacy_reason": null,
"mode": "chain",
"ordering": "priority_serial",
"payload_contract": "ResourceSelectionEventData",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"ChainEventType.StorageOperSelection": {
"delivery": "ephemeral",
"error_behavior": "stop_chain",
"legacy_reason": null,
"mode": "chain",
"ordering": "priority_serial",
"payload_contract": "StorageOperSelectionEventData",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"ChainEventType.SubscribeCompletionCheck": {
"delivery": "ephemeral",
"error_behavior": "stop_chain",
"legacy_reason": null,
"mode": "chain",
"ordering": "priority_serial",
"payload_contract": "SubscribeCompletionCheckEventData",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"ChainEventType.SubscribeEpisodesRefresh": {
"delivery": "ephemeral",
"error_behavior": "stop_chain",
"legacy_reason": null,
"mode": "chain",
"ordering": "priority_serial",
"payload_contract": "SubscribeEpisodesRefreshEventData",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"ChainEventType.TransferIntercept": {
"delivery": "ephemeral",
"error_behavior": "stop_chain",
"legacy_reason": null,
"mode": "chain",
"ordering": "priority_serial",
"payload_contract": "TransferInterceptEventData",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"ChainEventType.TransferOverwriteCheck": {
"delivery": "ephemeral",
"error_behavior": "stop_chain",
"legacy_reason": null,
"mode": "chain",
"ordering": "priority_serial",
"payload_contract": "TransferOverwriteCheckEventData",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"ChainEventType.TransferRename": {
"delivery": "ephemeral",
"error_behavior": "stop_chain",
"legacy_reason": null,
"mode": "chain",
"ordering": "priority_serial",
"payload_contract": "TransferRenameEventData",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"ChainEventType.TransferRenameBuild": {
"delivery": "ephemeral",
"error_behavior": "stop_chain",
"legacy_reason": null,
"mode": "chain",
"ordering": "priority_serial",
"payload_contract": "TransferRenameBuildEventData",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"ChainEventType.WorkflowExecution": {
"delivery": "ephemeral",
"error_behavior": "stop_chain",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "chain",
"ordering": "priority_serial",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.AgentTokensUsage": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": null,
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "AgentTokensUsageEventData",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.AudioTransferComplete": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.AudioTransferFailed": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.CommandExcute": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.ConfigChanged": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": null,
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "ConfigChangeEventData",
"sensitive_fields": [],
"visibility": "host_only"
},
"EventType.DownloadAdded": {
"delivery": "durable_required",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.DownloadDeleted": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.DownloadFileDeleted": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.HistoryDeleted": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.MessageAction": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.MetadataScrape": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.ModuleReload": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "host_only"
},
"EventType.NoticeMessage": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.PluginAction": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "target_plugin"
},
"EventType.PluginReload": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.PluginTriggered": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "target_plugin"
},
"EventType.SiteDeleted": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.SiteRefreshed": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.SiteUpdated": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.SubscribeAdded": {
"delivery": "durable_required",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.SubscribeComplete": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.SubscribeDeleted": {
"delivery": "durable_required",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.SubscribeModified": {
"delivery": "durable_required",
"error_behavior": "notify",
"legacy_reason": null,
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "SubscribeModifiedEventData",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.SubtitleTransferComplete": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.SubtitleTransferFailed": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.SystemError": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "host_only"
},
"EventType.TransferComplete": {
"delivery": "durable_required",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.TransferFailed": {
"delivery": "durable_required",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.UserMessage": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.WebhookMessage": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
},
"EventType.WorkflowExecute": {
"delivery": "ephemeral",
"error_behavior": "notify",
"legacy_reason": "现有插件 payload 尚未收敛为稳定 model,保留原始 dict ABI",
"mode": "broadcast",
"ordering": "priority_queue",
"payload_contract": "legacy_dict",
"sensitive_fields": [],
"visibility": "plugin_public"
}
},
"events": {
"consumer_count": 15,
"dynamic_consumers": [
+69
View File
@@ -0,0 +1,69 @@
"""Event Contract Registry 完整性和兼容校验测试。"""
from unittest.mock import patch
from app.runtime.event.contracts import (
EVENT_CONTRACTS,
EventDelivery,
get_event_contract,
validate_event_payload,
)
from app.runtime.events import Event
from app.schemas.event import ConfigChangeEventData
from app.schemas.types import ChainEventType, EventType
def test_every_event_enum_has_complete_contract() -> None:
"""53 个广播/链式事件必须全部登记且 legacy 项必须解释原因。"""
expected = {*EventType, *ChainEventType}
assert set(EVENT_CONTRACTS) == expected
assert len(EVENT_CONTRACTS) == 53
for contract in EVENT_CONTRACTS.values():
assert contract.mode in {"broadcast", "chain"}
assert contract.payload_contract
if contract.payload_contract == "legacy_dict":
assert contract.legacy_reason
def test_typed_payload_is_validated_without_changing_public_shape() -> None:
"""旧 dict 通过 model 校验后仍以同一个 dict 对象投递给插件。"""
payload = {"key": "PROXY_HOST", "value": "http://proxy"}
assert validate_event_payload(EventType.ConfigChanged, payload) == ()
event = Event(EventType.ConfigChanged, payload)
assert event.event_data is payload
assert isinstance(event.event_data, dict)
def test_invalid_typed_payload_is_diagnostic_only() -> None:
"""兼容阶段坏 payload 产生诊断但不阻断既有投递。"""
payload = {"value": "missing-key"}
with patch("app.runtime.events.logger.warning") as warning:
event = Event(EventType.ConfigChanged, payload)
assert event.event_data is payload
warning.assert_called_once()
def test_selected_user_side_effects_are_marked_durable_required() -> None:
"""订阅、下载和整理完成事件必须明确暴露后续 durable pilot 要求。"""
for event_type in (
EventType.SubscribeAdded,
EventType.SubscribeModified,
EventType.SubscribeDeleted,
EventType.DownloadAdded,
EventType.TransferComplete,
EventType.TransferFailed,
):
assert get_event_contract(event_type).delivery is EventDelivery.DURABLE_REQUIRED
def test_model_instance_remains_mutable_chain_payload() -> None:
"""链式处理器继续接收原 model 实例,确保输出字段可原地接力。"""
payload = ConfigChangeEventData(key={"PROXY_HOST"})
event = Event(EventType.ConfigChanged, payload)
assert event.event_data is payload