mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-05 15:38:19 +08:00
feat(events): expose typed payload snapshots
This commit is contained in:
@@ -37,6 +37,21 @@ class EventErrorBehavior(StrEnum):
|
|||||||
NOTIFY = "notify"
|
NOTIFY = "notify"
|
||||||
|
|
||||||
|
|
||||||
|
class EventPayloadMode(StrEnum):
|
||||||
|
"""描述事件 payload 是运行时对象还是稳定快照。"""
|
||||||
|
|
||||||
|
RUNTIME = "runtime"
|
||||||
|
SNAPSHOT = "snapshot"
|
||||||
|
EXTENSION = "extension"
|
||||||
|
|
||||||
|
|
||||||
|
class EventValidationMode(StrEnum):
|
||||||
|
"""描述契约校验失败后的兼容策略。"""
|
||||||
|
|
||||||
|
DIAGNOSTIC = "diagnostic"
|
||||||
|
STRICT = "strict"
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True, slots=True)
|
@dataclass(frozen=True, slots=True)
|
||||||
class EventContract:
|
class EventContract:
|
||||||
"""冻结一个事件的 payload 与运行语义。"""
|
"""冻结一个事件的 payload 与运行语义。"""
|
||||||
@@ -49,6 +64,11 @@ class EventContract:
|
|||||||
delivery: EventDelivery
|
delivery: EventDelivery
|
||||||
error_behavior: EventErrorBehavior
|
error_behavior: EventErrorBehavior
|
||||||
ordering: str
|
ordering: str
|
||||||
|
input_model: type[BaseModel] | None = None
|
||||||
|
output_model: type[BaseModel] | None = None
|
||||||
|
schema_version: int = 1
|
||||||
|
payload_mode: EventPayloadMode = EventPayloadMode.RUNTIME
|
||||||
|
validation_mode: EventValidationMode = EventValidationMode.DIAGNOSTIC
|
||||||
sensitive_fields: tuple[str, ...] = ()
|
sensitive_fields: tuple[str, ...] = ()
|
||||||
legacy_reason: str | None = None
|
legacy_reason: str | None = None
|
||||||
|
|
||||||
@@ -66,13 +86,13 @@ _PAYLOAD_MODELS: dict[EventType | ChainEventType, type[BaseModel]] = {
|
|||||||
EventType.SubscribeAdded: event_schemas.SubscribeAddedEventData,
|
EventType.SubscribeAdded: event_schemas.SubscribeAddedEventData,
|
||||||
EventType.SubscribeDeleted: event_schemas.SubscribeDeletedEventData,
|
EventType.SubscribeDeleted: event_schemas.SubscribeDeletedEventData,
|
||||||
EventType.SubscribeModified: event_schemas.SubscribeModifiedEventData,
|
EventType.SubscribeModified: event_schemas.SubscribeModifiedEventData,
|
||||||
EventType.DownloadAdded: event_schemas.DownloadAddedEventData,
|
EventType.DownloadAdded: event_schemas.DownloadAddedContractData,
|
||||||
EventType.TransferComplete: event_schemas.TransferResultEventData,
|
EventType.TransferComplete: event_schemas.TransferResultContractData,
|
||||||
EventType.TransferFailed: event_schemas.TransferResultEventData,
|
EventType.TransferFailed: event_schemas.TransferResultContractData,
|
||||||
EventType.SubtitleTransferComplete: event_schemas.TransferResultEventData,
|
EventType.SubtitleTransferComplete: event_schemas.TransferResultContractData,
|
||||||
EventType.SubtitleTransferFailed: event_schemas.TransferResultEventData,
|
EventType.SubtitleTransferFailed: event_schemas.TransferResultContractData,
|
||||||
EventType.AudioTransferComplete: event_schemas.TransferResultEventData,
|
EventType.AudioTransferComplete: event_schemas.TransferResultContractData,
|
||||||
EventType.AudioTransferFailed: event_schemas.TransferResultEventData,
|
EventType.AudioTransferFailed: event_schemas.TransferResultContractData,
|
||||||
EventType.HistoryDeleted: event_schemas.HistoryDeletedEventData,
|
EventType.HistoryDeleted: event_schemas.HistoryDeletedEventData,
|
||||||
EventType.DownloadFileDeleted: event_schemas.DownloadFileDeletedEventData,
|
EventType.DownloadFileDeleted: event_schemas.DownloadFileDeletedEventData,
|
||||||
EventType.DownloadDeleted: event_schemas.DownloadDeletedEventData,
|
EventType.DownloadDeleted: event_schemas.DownloadDeletedEventData,
|
||||||
@@ -81,7 +101,7 @@ _PAYLOAD_MODELS: dict[EventType | ChainEventType, type[BaseModel]] = {
|
|||||||
EventType.NoticeMessage: event_schemas.NoticeMessageEventData,
|
EventType.NoticeMessage: event_schemas.NoticeMessageEventData,
|
||||||
EventType.SubscribeComplete: event_schemas.SubscribeCompleteEventData,
|
EventType.SubscribeComplete: event_schemas.SubscribeCompleteEventData,
|
||||||
EventType.SystemError: event_schemas.SystemErrorEventData,
|
EventType.SystemError: event_schemas.SystemErrorEventData,
|
||||||
EventType.MetadataScrape: event_schemas.MetadataScrapeEventData,
|
EventType.MetadataScrape: event_schemas.MetadataScrapeContractData,
|
||||||
EventType.ModuleReload: event_schemas.EmptyEventData,
|
EventType.ModuleReload: event_schemas.EmptyEventData,
|
||||||
EventType.MessageAction: event_schemas.MessageActionEventData,
|
EventType.MessageAction: event_schemas.MessageActionEventData,
|
||||||
EventType.WorkflowExecute: event_schemas.WorkflowExecuteEventData,
|
EventType.WorkflowExecute: event_schemas.WorkflowExecuteEventData,
|
||||||
@@ -93,15 +113,15 @@ _PAYLOAD_MODELS: dict[EventType | ChainEventType, type[BaseModel]] = {
|
|||||||
ChainEventType.TransferRenameBuild: event_schemas.TransferRenameBuildEventData,
|
ChainEventType.TransferRenameBuild: event_schemas.TransferRenameBuildEventData,
|
||||||
ChainEventType.TransferIntercept: event_schemas.TransferInterceptEventData,
|
ChainEventType.TransferIntercept: event_schemas.TransferInterceptEventData,
|
||||||
ChainEventType.TransferOverwriteCheck: event_schemas.TransferOverwriteCheckEventData,
|
ChainEventType.TransferOverwriteCheck: event_schemas.TransferOverwriteCheckEventData,
|
||||||
ChainEventType.ResourceSelection: event_schemas.ResourceSelectionEventData,
|
ChainEventType.ResourceSelection: event_schemas.ResourceSelectionContractData,
|
||||||
ChainEventType.ResourceDownload: event_schemas.ResourceDownloadEventData,
|
ChainEventType.ResourceDownload: event_schemas.ResourceDownloadContractData,
|
||||||
ChainEventType.DiscoverSource: event_schemas.DiscoverSourceEventData,
|
ChainEventType.DiscoverSource: event_schemas.DiscoverSourceEventData,
|
||||||
ChainEventType.MediaRecognizeConvert: event_schemas.MediaRecognizeConvertEventData,
|
ChainEventType.MediaRecognizeConvert: event_schemas.MediaRecognizeConvertEventData,
|
||||||
ChainEventType.RecommendSource: event_schemas.RecommendSourceEventData,
|
ChainEventType.RecommendSource: event_schemas.RecommendSourceEventData,
|
||||||
ChainEventType.StorageOperSelection: event_schemas.StorageOperSelectionEventData,
|
ChainEventType.StorageOperSelection: event_schemas.StorageOperSelectionEventData,
|
||||||
ChainEventType.AgentLLMProvider: event_schemas.AgentLLMProviderEventData,
|
ChainEventType.AgentLLMProvider: event_schemas.AgentLLMProviderEventData,
|
||||||
ChainEventType.SubscribeEpisodesRefresh: event_schemas.SubscribeEpisodesRefreshEventData,
|
ChainEventType.SubscribeEpisodesRefresh: event_schemas.SubscribeEpisodesRefreshEventData,
|
||||||
ChainEventType.SubscribeCompletionCheck: event_schemas.SubscribeCompletionCheckEventData,
|
ChainEventType.SubscribeCompletionCheck: event_schemas.SubscribeCompletionCheckContractData,
|
||||||
ChainEventType.NameRecognize: event_schemas.NameRecognizeEventData,
|
ChainEventType.NameRecognize: event_schemas.NameRecognizeEventData,
|
||||||
ChainEventType.MusicNameRecognize: event_schemas.MusicNameRecognizeEventData,
|
ChainEventType.MusicNameRecognize: event_schemas.MusicNameRecognizeEventData,
|
||||||
ChainEventType.MediaRecognize: event_schemas.MediaRecognizeEventData,
|
ChainEventType.MediaRecognize: event_schemas.MediaRecognizeEventData,
|
||||||
@@ -109,6 +129,32 @@ _PAYLOAD_MODELS: dict[EventType | ChainEventType, type[BaseModel]] = {
|
|||||||
ChainEventType.WorkflowExecution: ActionContext,
|
ChainEventType.WorkflowExecution: ActionContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_SNAPSHOT_EVENTS = {
|
||||||
|
EventType.DownloadAdded,
|
||||||
|
EventType.TransferComplete,
|
||||||
|
EventType.TransferFailed,
|
||||||
|
EventType.SubtitleTransferComplete,
|
||||||
|
EventType.SubtitleTransferFailed,
|
||||||
|
EventType.AudioTransferComplete,
|
||||||
|
EventType.AudioTransferFailed,
|
||||||
|
EventType.MetadataScrape,
|
||||||
|
ChainEventType.ResourceSelection,
|
||||||
|
ChainEventType.ResourceDownload,
|
||||||
|
ChainEventType.SubscribeCompletionCheck,
|
||||||
|
}
|
||||||
|
|
||||||
|
_INPUT_MODELS = {
|
||||||
|
ChainEventType.ResourceSelection: event_schemas.ResourceSelectionInputContractData,
|
||||||
|
ChainEventType.ResourceDownload: event_schemas.ResourceDownloadInputContractData,
|
||||||
|
ChainEventType.SubscribeCompletionCheck: event_schemas.SubscribeCompletionCheckInputContractData,
|
||||||
|
}
|
||||||
|
|
||||||
|
_OUTPUT_MODELS = {
|
||||||
|
ChainEventType.ResourceSelection: event_schemas.ResourceSelectionOutputContractData,
|
||||||
|
ChainEventType.ResourceDownload: event_schemas.ResourceDownloadOutputContractData,
|
||||||
|
ChainEventType.SubscribeCompletionCheck: event_schemas.SubscribeCompletionCheckOutputContractData,
|
||||||
|
}
|
||||||
|
|
||||||
_DURABLE_REQUIRED = {
|
_DURABLE_REQUIRED = {
|
||||||
EventType.SubscribeAdded,
|
EventType.SubscribeAdded,
|
||||||
EventType.SubscribeModified,
|
EventType.SubscribeModified,
|
||||||
@@ -150,6 +196,14 @@ def _build_contract(event_type: EventType | ChainEventType) -> EventContract:
|
|||||||
EventErrorBehavior.STOP_CHAIN if is_chain else EventErrorBehavior.NOTIFY
|
EventErrorBehavior.STOP_CHAIN if is_chain else EventErrorBehavior.NOTIFY
|
||||||
),
|
),
|
||||||
ordering="priority_serial" if is_chain else "priority_queue",
|
ordering="priority_serial" if is_chain else "priority_queue",
|
||||||
|
input_model=_INPUT_MODELS.get(event_type, payload_model),
|
||||||
|
output_model=_OUTPUT_MODELS.get(event_type),
|
||||||
|
payload_mode=(
|
||||||
|
EventPayloadMode.SNAPSHOT
|
||||||
|
if event_type in _SNAPSHOT_EVENTS
|
||||||
|
else EventPayloadMode.RUNTIME
|
||||||
|
),
|
||||||
|
validation_mode=EventValidationMode.DIAGNOSTIC,
|
||||||
sensitive_fields=_SENSITIVE_FIELDS.get(event_type, ()),
|
sensitive_fields=_SENSITIVE_FIELDS.get(event_type, ()),
|
||||||
legacy_reason=(
|
legacy_reason=(
|
||||||
None
|
None
|
||||||
@@ -195,16 +249,23 @@ def validate_event_payload(
|
|||||||
) -> tuple[str, ...]:
|
) -> tuple[str, ...]:
|
||||||
"""在发送边界诊断首批 typed payload,保持原对象和插件 dict 形状不变。"""
|
"""在发送边界诊断首批 typed payload,保持原对象和插件 dict 形状不变。"""
|
||||||
try:
|
try:
|
||||||
model = get_event_contract(event_type).payload_model
|
contract = get_event_contract(event_type)
|
||||||
|
models = tuple(
|
||||||
|
model
|
||||||
|
for model in (contract.input_model, contract.output_model)
|
||||||
|
if model is not None
|
||||||
|
)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# 动态插件在旧 ABI 下可能使用宿主枚举之外的字符串事件。
|
# 动态插件在旧 ABI 下可能使用宿主枚举之外的字符串事件。
|
||||||
return ()
|
return ()
|
||||||
if model is None or payload is None:
|
if not models or payload is None:
|
||||||
return ()
|
return ()
|
||||||
if isinstance(payload, model):
|
problems: list[str] = []
|
||||||
return ()
|
for model in models:
|
||||||
try:
|
if isinstance(payload, model):
|
||||||
model.model_validate(payload)
|
continue
|
||||||
except (ValidationError, TypeError, ValueError) as error:
|
try:
|
||||||
return (str(error),)
|
model.model_validate(payload)
|
||||||
return ()
|
except (ValidationError, TypeError, ValueError) as error:
|
||||||
|
problems.append(f"{model.__name__}: {error}")
|
||||||
|
return tuple(problems)
|
||||||
|
|||||||
@@ -0,0 +1,116 @@
|
|||||||
|
"""事件 payload 的只读契约快照访问。"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from pydantic import BaseModel, ValidationError
|
||||||
|
|
||||||
|
from app.runtime.event.contracts import get_event_contract, normalize_event_type
|
||||||
|
from app.schemas.types import ChainEventType, EventType
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True, slots=True)
|
||||||
|
class EventPayloadSnapshot:
|
||||||
|
"""保存原始 payload 及按登记契约解析出的独立快照。"""
|
||||||
|
|
||||||
|
event_type: EventType | ChainEventType | str
|
||||||
|
raw: Any
|
||||||
|
payload: BaseModel | None
|
||||||
|
input: BaseModel | None
|
||||||
|
output: BaseModel | None
|
||||||
|
known: bool
|
||||||
|
schema_version: int | None
|
||||||
|
payload_mode: str | None
|
||||||
|
validation_mode: str | None
|
||||||
|
errors: tuple[str, ...] = ()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def valid(self) -> bool:
|
||||||
|
"""返回已知事件的全部登记模型是否都通过校验。"""
|
||||||
|
return self.known and not self.errors
|
||||||
|
|
||||||
|
|
||||||
|
def _model_snapshot(
|
||||||
|
model: type[BaseModel] | None,
|
||||||
|
payload: Any,
|
||||||
|
label: str,
|
||||||
|
cache: dict[type[BaseModel], BaseModel | None],
|
||||||
|
errors: list[str],
|
||||||
|
) -> BaseModel | None:
|
||||||
|
"""按单个模型构造快照,同一模型在一次访问中只解析一次。"""
|
||||||
|
if model is None:
|
||||||
|
return None
|
||||||
|
if model in cache:
|
||||||
|
return cache[model]
|
||||||
|
if isinstance(payload, model):
|
||||||
|
cache[model] = payload.model_copy(deep=True)
|
||||||
|
return cache[model]
|
||||||
|
try:
|
||||||
|
cache[model] = model.model_validate(payload)
|
||||||
|
except (ValidationError, TypeError, ValueError) as error:
|
||||||
|
cache[model] = None
|
||||||
|
errors.append(f"{label}:{model.__name__}: {error}")
|
||||||
|
return cache[model]
|
||||||
|
|
||||||
|
|
||||||
|
def snapshot_event_data(
|
||||||
|
event_type: EventType | ChainEventType | str,
|
||||||
|
event_data: Any,
|
||||||
|
) -> EventPayloadSnapshot:
|
||||||
|
"""按事件注册契约解析 payload,未知自定义事件保持原始数据并返回未登记状态。"""
|
||||||
|
normalized = normalize_event_type(event_type)
|
||||||
|
try:
|
||||||
|
contract = get_event_contract(normalized)
|
||||||
|
except KeyError:
|
||||||
|
return EventPayloadSnapshot(
|
||||||
|
event_type=normalized,
|
||||||
|
raw=event_data,
|
||||||
|
payload=None,
|
||||||
|
input=None,
|
||||||
|
output=None,
|
||||||
|
known=False,
|
||||||
|
schema_version=None,
|
||||||
|
payload_mode=None,
|
||||||
|
validation_mode=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
errors: list[str] = []
|
||||||
|
cache: dict[type[BaseModel], BaseModel | None] = {}
|
||||||
|
payload_snapshot = _model_snapshot(
|
||||||
|
contract.payload_model,
|
||||||
|
event_data,
|
||||||
|
"payload",
|
||||||
|
cache,
|
||||||
|
errors,
|
||||||
|
)
|
||||||
|
input_snapshot = _model_snapshot(
|
||||||
|
contract.input_model,
|
||||||
|
event_data,
|
||||||
|
"input",
|
||||||
|
cache,
|
||||||
|
errors,
|
||||||
|
)
|
||||||
|
output_snapshot = _model_snapshot(
|
||||||
|
contract.output_model,
|
||||||
|
event_data,
|
||||||
|
"output",
|
||||||
|
cache,
|
||||||
|
errors,
|
||||||
|
)
|
||||||
|
return EventPayloadSnapshot(
|
||||||
|
event_type=normalized,
|
||||||
|
raw=event_data,
|
||||||
|
payload=payload_snapshot,
|
||||||
|
input=input_snapshot,
|
||||||
|
output=output_snapshot,
|
||||||
|
known=True,
|
||||||
|
schema_version=contract.schema_version,
|
||||||
|
payload_mode=contract.payload_mode.value,
|
||||||
|
validation_mode=contract.validation_mode.value,
|
||||||
|
errors=tuple(errors),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = ["EventPayloadSnapshot", "snapshot_event_data"]
|
||||||
+18
-9
@@ -7,26 +7,29 @@ import uuid
|
|||||||
from contextvars import ContextVar
|
from contextvars import ContextVar
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from queue import Empty, PriorityQueue
|
from queue import Empty, PriorityQueue
|
||||||
from typing import Callable, Dict, List, Optional, Tuple, Union, Any, Type
|
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, Type, Union
|
||||||
|
|
||||||
from app.runtime.config import global_vars
|
|
||||||
from app.runtime.thread import ThreadHelper
|
|
||||||
from app.runtime.log import logger
|
|
||||||
from app.schemas.event import ChainEventData
|
|
||||||
from app.schemas.types import ChainEventType, EventType
|
|
||||||
from app.runtime.rate import ExponentialBackoffRateLimiter
|
|
||||||
from app.foundation.singleton import Singleton
|
from app.foundation.singleton import Singleton
|
||||||
|
from app.runtime.config import global_vars
|
||||||
|
from app.runtime.correlation import get_correlation_id
|
||||||
from app.runtime.event.binding import (
|
from app.runtime.event.binding import (
|
||||||
EventBindingResolver,
|
EventBindingResolver,
|
||||||
EventHandlerBinding,
|
EventHandlerBinding,
|
||||||
HandlerInstanceResolver,
|
HandlerInstanceResolver,
|
||||||
)
|
)
|
||||||
|
from app.runtime.event.contracts import normalize_event_type, validate_event_payload
|
||||||
from app.runtime.event.dispatch import EventDispatcher
|
from app.runtime.event.dispatch import EventDispatcher
|
||||||
from app.runtime.event.errors import EventErrorNotifier, EventErrorPolicy
|
from app.runtime.event.errors import EventErrorNotifier, EventErrorPolicy
|
||||||
from app.runtime.event.registry import EventRegistry
|
from app.runtime.event.registry import EventRegistry
|
||||||
from app.runtime.event.contracts import normalize_event_type, validate_event_payload
|
from app.runtime.log import logger
|
||||||
from app.runtime.correlation import get_correlation_id
|
|
||||||
from app.runtime.observability import record_metric
|
from app.runtime.observability import record_metric
|
||||||
|
from app.runtime.rate import ExponentialBackoffRateLimiter
|
||||||
|
from app.runtime.thread import ThreadHelper
|
||||||
|
from app.schemas.event import ChainEventData
|
||||||
|
from app.schemas.types import ChainEventType, EventType
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from app.runtime.event.snapshot import EventPayloadSnapshot
|
||||||
|
|
||||||
DEFAULT_EVENT_PRIORITY = 10 # 事件的默认优先级
|
DEFAULT_EVENT_PRIORITY = 10 # 事件的默认优先级
|
||||||
MIN_EVENT_CONSUMER_THREADS = 1 # 最小事件消费者线程数
|
MIN_EVENT_CONSUMER_THREADS = 1 # 最小事件消费者线程数
|
||||||
@@ -84,6 +87,12 @@ class Event:
|
|||||||
event_name = getattr(self.event_type, "value", self.event_type)
|
event_name = getattr(self.event_type, "value", self.event_type)
|
||||||
return f"<{event_kind}: {event_name}, ID: {self.event_id}, Priority: {self.priority}>"
|
return f"<{event_kind}: {event_name}, ID: {self.event_id}, Priority: {self.priority}>"
|
||||||
|
|
||||||
|
def snapshot(self) -> "EventPayloadSnapshot":
|
||||||
|
"""返回插件可安全读取的类型化 payload 快照,原始 event_data 保持不变。"""
|
||||||
|
from app.runtime.event.snapshot import snapshot_event_data
|
||||||
|
|
||||||
|
return snapshot_event_data(self.event_type, self.event_data)
|
||||||
|
|
||||||
def __lt__(self, other):
|
def __lt__(self, other):
|
||||||
"""
|
"""
|
||||||
定义事件对象的比较规则,基于优先级比较
|
定义事件对象的比较规则,基于优先级比较
|
||||||
|
|||||||
+203
-5
@@ -1,14 +1,89 @@
|
|||||||
|
from collections.abc import Mapping as _Mapping
|
||||||
|
from enum import Enum as _Enum
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Iterable, Optional, Dict, Any, List, Set, Callable
|
from typing import Annotated as _Annotated
|
||||||
|
from typing import Any, Callable, Dict, Iterable, List, Optional, Set
|
||||||
|
from typing import Union as _Union
|
||||||
|
|
||||||
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
||||||
|
from pydantic import BeforeValidator as _BeforeValidator
|
||||||
|
|
||||||
from app.schemas.common import JsonData
|
from app.schemas.common import JsonData
|
||||||
from app.schemas.types import MediaType, NotificationChannel
|
from app.schemas.context import Context as _ContextSnapshotBase
|
||||||
|
from app.schemas.context import MediaInfo as _MediaInfoSnapshot
|
||||||
|
from app.schemas.context import MetaInfo as _MetaInfoSnapshot
|
||||||
from app.schemas.file import FileItem
|
from app.schemas.file import FileItem
|
||||||
from app.schemas.media import OptionalMediaIdentityMixin, RequiredMediaIdentityMixin
|
from app.schemas.media import OptionalMediaIdentityMixin, RequiredMediaIdentityMixin
|
||||||
|
from app.schemas.music import MusicInfo as _MusicInfoSnapshot
|
||||||
|
from app.schemas.music import MusicMeta as _MusicMetaSnapshot
|
||||||
|
from app.schemas.subscribe import Subscribe as _SubscribeSnapshot
|
||||||
from app.schemas.transfer import TransferInfo
|
from app.schemas.transfer import TransferInfo
|
||||||
from app.schemas.types import MediaSource
|
from app.schemas.types import MediaSource, MediaType, NotificationChannel
|
||||||
|
|
||||||
|
JsonValue = JsonData
|
||||||
|
"""事件扩展字段允许的 JSON 值类型。"""
|
||||||
|
|
||||||
|
|
||||||
|
def _coerce_event_snapshot(value: Any) -> Any:
|
||||||
|
"""把旧运行时对象转换为只用于契约校验的可读取快照。"""
|
||||||
|
if isinstance(value, BaseModel):
|
||||||
|
value = value.model_dump(mode="python")
|
||||||
|
elif hasattr(value, "to_dict") and callable(value.to_dict):
|
||||||
|
value = value.to_dict()
|
||||||
|
elif isinstance(value, _Enum):
|
||||||
|
return value.value
|
||||||
|
elif isinstance(value, Path):
|
||||||
|
return value.as_posix()
|
||||||
|
if isinstance(value, _Mapping):
|
||||||
|
return {str(key): _coerce_event_snapshot(item) for key, item in value.items()}
|
||||||
|
if isinstance(value, (list, tuple, set, frozenset)):
|
||||||
|
return [_coerce_event_snapshot(item) for item in value]
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
EventJsonValue = _Annotated[JsonValue, _BeforeValidator(_coerce_event_snapshot)]
|
||||||
|
MediaSnapshot = _Annotated[
|
||||||
|
_Union[_MusicInfoSnapshot, _MediaInfoSnapshot],
|
||||||
|
_BeforeValidator(_coerce_event_snapshot),
|
||||||
|
]
|
||||||
|
MetaSnapshot = _Annotated[
|
||||||
|
_Union[_MusicMetaSnapshot, _MetaInfoSnapshot],
|
||||||
|
_BeforeValidator(_coerce_event_snapshot),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class ContextSnapshot(_ContextSnapshotBase):
|
||||||
|
"""资源上下文的稳定事件快照,不替换链路中的运行时 Context。"""
|
||||||
|
|
||||||
|
allowed_episodes: Optional[Set[int]] = None
|
||||||
|
|
||||||
|
model_config = ConfigDict(
|
||||||
|
extra="allow",
|
||||||
|
from_attributes=True,
|
||||||
|
arbitrary_types_allowed=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
@model_validator(mode="before")
|
||||||
|
@classmethod
|
||||||
|
def coerce_runtime_context(cls, value: Any) -> Any:
|
||||||
|
"""允许旧 Context/dataclass 进入校验,同时保持原对象继续投递。"""
|
||||||
|
return _coerce_event_snapshot(value)
|
||||||
|
|
||||||
|
|
||||||
|
class FileContextSnapshot(BaseModel):
|
||||||
|
"""音乐批次中单个文件的元数据上下文快照。"""
|
||||||
|
|
||||||
|
path: str
|
||||||
|
meta: Optional[MetaSnapshot] = None
|
||||||
|
mediainfo: Optional[MediaSnapshot] = None
|
||||||
|
|
||||||
|
model_config = ConfigDict(extra="allow", from_attributes=True)
|
||||||
|
|
||||||
|
@model_validator(mode="before")
|
||||||
|
@classmethod
|
||||||
|
def coerce_runtime_context(cls, value: Any) -> Any:
|
||||||
|
"""把旧文件上下文对象转换成可验证的字典。"""
|
||||||
|
return _coerce_event_snapshot(value)
|
||||||
|
|
||||||
|
|
||||||
class Event(BaseModel):
|
class Event(BaseModel):
|
||||||
@@ -26,7 +101,7 @@ class BaseEventData(BaseModel):
|
|||||||
事件数据的基类,所有具体事件数据类应继承自此类
|
事件数据的基类,所有具体事件数据类应继承自此类
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
model_config = ConfigDict(from_attributes=True, arbitrary_types_allowed=True)
|
||||||
|
|
||||||
|
|
||||||
class ExtensibleEventData(BaseEventData):
|
class ExtensibleEventData(BaseEventData):
|
||||||
@@ -249,7 +324,130 @@ class ChainEventData(BaseEventData):
|
|||||||
链式事件数据的基类,所有具体事件数据类应继承自此类
|
链式事件数据的基类,所有具体事件数据类应继承自此类
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
model_config = ConfigDict(from_attributes=True, arbitrary_types_allowed=True)
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceSelectionContractData(ChainEventData):
|
||||||
|
"""ResourceSelection 的稳定输入/输出契约。"""
|
||||||
|
|
||||||
|
contexts: List[ContextSnapshot] = Field(default_factory=list)
|
||||||
|
downloader: Optional[str] = None
|
||||||
|
origin: Optional[str] = None
|
||||||
|
updated: bool = False
|
||||||
|
updated_contexts: Optional[List[ContextSnapshot]] = None
|
||||||
|
source: Optional[str] = "未知拦截源"
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceSelectionInputContractData(ChainEventData):
|
||||||
|
"""ResourceSelection 事件输入字段。"""
|
||||||
|
|
||||||
|
contexts: List[ContextSnapshot] = Field(default_factory=list)
|
||||||
|
downloader: Optional[str] = None
|
||||||
|
origin: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceSelectionOutputContractData(ChainEventData):
|
||||||
|
"""ResourceSelection 事件插件回写字段。"""
|
||||||
|
|
||||||
|
updated: bool = False
|
||||||
|
updated_contexts: Optional[List[ContextSnapshot]] = None
|
||||||
|
source: Optional[str] = "未知拦截源"
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceDownloadContractData(ChainEventData):
|
||||||
|
"""ResourceDownload 的稳定输入/输出契约。"""
|
||||||
|
|
||||||
|
context: Optional[ContextSnapshot] = None
|
||||||
|
episodes: Optional[Set[int]] = None
|
||||||
|
channel: Optional[NotificationChannel] = None
|
||||||
|
origin: Optional[str] = None
|
||||||
|
downloader: Optional[str] = None
|
||||||
|
options: Optional[Dict[str, EventJsonValue]] = None
|
||||||
|
cancel: bool = False
|
||||||
|
source: str = "未知拦截源"
|
||||||
|
reason: str = ""
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceDownloadInputContractData(ChainEventData):
|
||||||
|
"""ResourceDownload 事件输入字段。"""
|
||||||
|
|
||||||
|
context: Optional[ContextSnapshot] = None
|
||||||
|
episodes: Optional[Set[int]] = None
|
||||||
|
channel: Optional[NotificationChannel] = None
|
||||||
|
origin: Optional[str] = None
|
||||||
|
downloader: Optional[str] = None
|
||||||
|
options: Optional[Dict[str, EventJsonValue]] = None
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceDownloadOutputContractData(ChainEventData):
|
||||||
|
"""ResourceDownload 事件插件回写字段。"""
|
||||||
|
|
||||||
|
cancel: bool = False
|
||||||
|
source: str = "未知拦截源"
|
||||||
|
reason: str = ""
|
||||||
|
|
||||||
|
|
||||||
|
class DownloadAddedContractData(BaseEventData):
|
||||||
|
"""DownloadAdded 的稳定下载上下文契约。"""
|
||||||
|
|
||||||
|
hash: str
|
||||||
|
context: ContextSnapshot
|
||||||
|
username: Optional[str] = None
|
||||||
|
downloader: Optional[str] = None
|
||||||
|
episodes: List[int] = Field(default_factory=list)
|
||||||
|
source: Optional[str] = None
|
||||||
|
idempotency_key: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
|
class TransferResultContractData(BaseEventData):
|
||||||
|
"""整理结果事件的稳定媒体与元数据契约。"""
|
||||||
|
|
||||||
|
fileitem: Optional[FileItem] = None
|
||||||
|
meta: Optional[MetaSnapshot] = None
|
||||||
|
mediainfo: Optional[MediaSnapshot] = None
|
||||||
|
transferinfo: Optional[TransferInfo] = None
|
||||||
|
downloader: Optional[str] = None
|
||||||
|
download_hash: Optional[str] = None
|
||||||
|
transfer_history_id: Optional[int] = None
|
||||||
|
idempotency_key: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
|
class MetadataScrapeContractData(ExtensibleEventData):
|
||||||
|
"""MetadataScrape 的稳定媒体刮削契约。"""
|
||||||
|
|
||||||
|
fileitem: FileItem
|
||||||
|
file_list: List[str] = Field(default_factory=list)
|
||||||
|
meta: Optional[MetaSnapshot] = None
|
||||||
|
mediainfo: Optional[MediaSnapshot] = None
|
||||||
|
overwrite: bool = False
|
||||||
|
file_contexts: List[FileContextSnapshot] = Field(default_factory=list)
|
||||||
|
|
||||||
|
|
||||||
|
class SubscribeCompletionCheckContractData(ChainEventData):
|
||||||
|
"""订阅完成判定的稳定订阅、媒体和元数据契约。"""
|
||||||
|
|
||||||
|
subscribe: Optional[_SubscribeSnapshot] = None
|
||||||
|
mediainfo: Optional[MediaSnapshot] = None
|
||||||
|
meta: Optional[MetaSnapshot] = None
|
||||||
|
cancel: bool = False
|
||||||
|
source: str = "未知来源"
|
||||||
|
reason: str = ""
|
||||||
|
|
||||||
|
|
||||||
|
class SubscribeCompletionCheckInputContractData(ChainEventData):
|
||||||
|
"""SubscribeCompletionCheck 事件输入字段。"""
|
||||||
|
|
||||||
|
subscribe: Optional[_SubscribeSnapshot] = None
|
||||||
|
mediainfo: Optional[MediaSnapshot] = None
|
||||||
|
meta: Optional[MetaSnapshot] = None
|
||||||
|
|
||||||
|
|
||||||
|
class SubscribeCompletionCheckOutputContractData(ChainEventData):
|
||||||
|
"""SubscribeCompletionCheck 事件插件回写字段。"""
|
||||||
|
|
||||||
|
cancel: bool = False
|
||||||
|
source: str = "未知来源"
|
||||||
|
reason: str = ""
|
||||||
|
|
||||||
|
|
||||||
class PluginDataResetEventData(ChainEventData):
|
class PluginDataResetEventData(ChainEventData):
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ SCHEMA_EXPORTS = {
|
|||||||
'ConfigDict': ('app.schemas.workflow', 'ConfigDict'),
|
'ConfigDict': ('app.schemas.workflow', 'ConfigDict'),
|
||||||
'ContentType': ('app.schemas.message', 'ContentType'),
|
'ContentType': ('app.schemas.message', 'ContentType'),
|
||||||
'Context': ('app.schemas.workflow', 'Context'),
|
'Context': ('app.schemas.workflow', 'Context'),
|
||||||
|
'ContextSnapshot': ('app.schemas.event', 'ContextSnapshot'),
|
||||||
'ConversationMemory': ('app.schemas.agent', 'ConversationMemory'),
|
'ConversationMemory': ('app.schemas.agent', 'ConversationMemory'),
|
||||||
'CookieActionResponse': ('app.schemas.servcookie', 'CookieActionResponse'),
|
'CookieActionResponse': ('app.schemas.servcookie', 'CookieActionResponse'),
|
||||||
'CookieData': ('app.schemas.servcookie', 'CookieData'),
|
'CookieData': ('app.schemas.servcookie', 'CookieData'),
|
||||||
@@ -87,6 +88,7 @@ SCHEMA_EXPORTS = {
|
|||||||
'DiscoverMediaSource': ('app.schemas.event', 'DiscoverMediaSource'),
|
'DiscoverMediaSource': ('app.schemas.event', 'DiscoverMediaSource'),
|
||||||
'DiscoverSourceEventData': ('app.schemas.event', 'DiscoverSourceEventData'),
|
'DiscoverSourceEventData': ('app.schemas.event', 'DiscoverSourceEventData'),
|
||||||
'Discriminator': ('app.schemas.context', 'Discriminator'),
|
'Discriminator': ('app.schemas.context', 'Discriminator'),
|
||||||
|
'DownloadAddedContractData': ('app.schemas.event', 'DownloadAddedContractData'),
|
||||||
'DownloadAddedData': ('app.schemas.download', 'DownloadAddedData'),
|
'DownloadAddedData': ('app.schemas.download', 'DownloadAddedData'),
|
||||||
'DownloadAddedEventData': ('app.schemas.event', 'DownloadAddedEventData'),
|
'DownloadAddedEventData': ('app.schemas.event', 'DownloadAddedEventData'),
|
||||||
'DownloadDeletedEventData': ('app.schemas.event', 'DownloadDeletedEventData'),
|
'DownloadDeletedEventData': ('app.schemas.event', 'DownloadDeletedEventData'),
|
||||||
@@ -109,9 +111,11 @@ SCHEMA_EXPORTS = {
|
|||||||
'EpisodeFormatRule': ('app.schemas.transfer', 'EpisodeFormatRule'),
|
'EpisodeFormatRule': ('app.schemas.transfer', 'EpisodeFormatRule'),
|
||||||
'ErrorRequest': ('app.schemas.monitoring', 'ErrorRequest'),
|
'ErrorRequest': ('app.schemas.monitoring', 'ErrorRequest'),
|
||||||
'Event': ('app.schemas.event', 'Event'),
|
'Event': ('app.schemas.event', 'Event'),
|
||||||
|
'EventJsonValue': ('app.schemas.event', 'EventJsonValue'),
|
||||||
'ExistMediaInfo': ('app.schemas.mediaserver', 'ExistMediaInfo'),
|
'ExistMediaInfo': ('app.schemas.mediaserver', 'ExistMediaInfo'),
|
||||||
'ExtensibleEventData': ('app.schemas.event', 'ExtensibleEventData'),
|
'ExtensibleEventData': ('app.schemas.event', 'ExtensibleEventData'),
|
||||||
'Field': ('app.schemas.mcp', 'Field'),
|
'Field': ('app.schemas.mcp', 'Field'),
|
||||||
|
'FileContextSnapshot': ('app.schemas.event', 'FileContextSnapshot'),
|
||||||
'FileItem': ('app.schemas.workflow', 'FileItem'),
|
'FileItem': ('app.schemas.workflow', 'FileItem'),
|
||||||
'FileNameData': ('app.schemas.common', 'FileNameData'),
|
'FileNameData': ('app.schemas.common', 'FileNameData'),
|
||||||
'FileURI': ('app.schemas.file', 'FileURI'),
|
'FileURI': ('app.schemas.file', 'FileURI'),
|
||||||
@@ -125,6 +129,7 @@ SCHEMA_EXPORTS = {
|
|||||||
'JsonData': ('app.schemas.mcp', 'JsonData'),
|
'JsonData': ('app.schemas.mcp', 'JsonData'),
|
||||||
'JsonObject': ('app.schemas.common', 'JsonObject'),
|
'JsonObject': ('app.schemas.common', 'JsonObject'),
|
||||||
'JsonObjectList': ('app.schemas.common', 'JsonObjectList'),
|
'JsonObjectList': ('app.schemas.common', 'JsonObjectList'),
|
||||||
|
'JsonValue': ('app.schemas.event', 'JsonValue'),
|
||||||
'LLMAuthStatus': ('app.schemas.llm', 'LLMAuthStatus'),
|
'LLMAuthStatus': ('app.schemas.llm', 'LLMAuthStatus'),
|
||||||
'LLMModelCatalogData': ('app.schemas.llm', 'LLMModelCatalogData'),
|
'LLMModelCatalogData': ('app.schemas.llm', 'LLMModelCatalogData'),
|
||||||
'LLMModelInfo': ('app.schemas.llm', 'LLMModelInfo'),
|
'LLMModelInfo': ('app.schemas.llm', 'LLMModelInfo'),
|
||||||
@@ -196,6 +201,7 @@ SCHEMA_EXPORTS = {
|
|||||||
'MediaServerPlayData': ('app.schemas.mediaserver', 'MediaServerPlayData'),
|
'MediaServerPlayData': ('app.schemas.mediaserver', 'MediaServerPlayData'),
|
||||||
'MediaServerPlayItem': ('app.schemas.mediaserver', 'MediaServerPlayItem'),
|
'MediaServerPlayItem': ('app.schemas.mediaserver', 'MediaServerPlayItem'),
|
||||||
'MediaServerSeasonInfo': ('app.schemas.mediaserver', 'MediaServerSeasonInfo'),
|
'MediaServerSeasonInfo': ('app.schemas.mediaserver', 'MediaServerSeasonInfo'),
|
||||||
|
'MediaSnapshot': ('app.schemas.event', 'MediaSnapshot'),
|
||||||
'MediaSource': ('app.schemas.transfer', 'MediaSource'),
|
'MediaSource': ('app.schemas.transfer', 'MediaSource'),
|
||||||
'MediaSourceInfo': ('app.schemas.event', 'MediaSourceInfo'),
|
'MediaSourceInfo': ('app.schemas.event', 'MediaSourceInfo'),
|
||||||
'MediaType': ('app.schemas.subscribe', 'MediaType'),
|
'MediaType': ('app.schemas.subscribe', 'MediaType'),
|
||||||
@@ -208,6 +214,8 @@ SCHEMA_EXPORTS = {
|
|||||||
'MessageResponse': ('app.schemas.message', 'MessageResponse'),
|
'MessageResponse': ('app.schemas.message', 'MessageResponse'),
|
||||||
'MessageType': ('app.schemas.message', 'MessageType'),
|
'MessageType': ('app.schemas.message', 'MessageType'),
|
||||||
'MetaInfo': ('app.schemas.transfer', 'MetaInfo'),
|
'MetaInfo': ('app.schemas.transfer', 'MetaInfo'),
|
||||||
|
'MetaSnapshot': ('app.schemas.event', 'MetaSnapshot'),
|
||||||
|
'MetadataScrapeContractData': ('app.schemas.event', 'MetadataScrapeContractData'),
|
||||||
'MetadataScrapeEventData': ('app.schemas.event', 'MetadataScrapeEventData'),
|
'MetadataScrapeEventData': ('app.schemas.event', 'MetadataScrapeEventData'),
|
||||||
'MfaChallenge': ('app.schemas.token', 'MfaChallenge'),
|
'MfaChallenge': ('app.schemas.token', 'MfaChallenge'),
|
||||||
'MfaStatusData': ('app.schemas.mfa', 'MfaStatusData'),
|
'MfaStatusData': ('app.schemas.mfa', 'MfaStatusData'),
|
||||||
@@ -295,8 +303,14 @@ SCHEMA_EXPORTS = {
|
|||||||
'RefreshMediaItem': ('app.schemas.mediaserver', 'RefreshMediaItem'),
|
'RefreshMediaItem': ('app.schemas.mediaserver', 'RefreshMediaItem'),
|
||||||
'RequestMetrics': ('app.schemas.monitoring', 'RequestMetrics'),
|
'RequestMetrics': ('app.schemas.monitoring', 'RequestMetrics'),
|
||||||
'RequiredMediaIdentityMixin': ('app.schemas.music', 'RequiredMediaIdentityMixin'),
|
'RequiredMediaIdentityMixin': ('app.schemas.music', 'RequiredMediaIdentityMixin'),
|
||||||
|
'ResourceDownloadContractData': ('app.schemas.event', 'ResourceDownloadContractData'),
|
||||||
'ResourceDownloadEventData': ('app.schemas.event', 'ResourceDownloadEventData'),
|
'ResourceDownloadEventData': ('app.schemas.event', 'ResourceDownloadEventData'),
|
||||||
|
'ResourceDownloadInputContractData': ('app.schemas.event', 'ResourceDownloadInputContractData'),
|
||||||
|
'ResourceDownloadOutputContractData': ('app.schemas.event', 'ResourceDownloadOutputContractData'),
|
||||||
|
'ResourceSelectionContractData': ('app.schemas.event', 'ResourceSelectionContractData'),
|
||||||
'ResourceSelectionEventData': ('app.schemas.event', 'ResourceSelectionEventData'),
|
'ResourceSelectionEventData': ('app.schemas.event', 'ResourceSelectionEventData'),
|
||||||
|
'ResourceSelectionInputContractData': ('app.schemas.event', 'ResourceSelectionInputContractData'),
|
||||||
|
'ResourceSelectionOutputContractData': ('app.schemas.event', 'ResourceSelectionOutputContractData'),
|
||||||
'Response': ('app.schemas.response', 'Response'),
|
'Response': ('app.schemas.response', 'Response'),
|
||||||
'RootModel': ('app.schemas.mcp', 'RootModel'),
|
'RootModel': ('app.schemas.mcp', 'RootModel'),
|
||||||
'RuleTestData': ('app.schemas.system', 'RuleTestData'),
|
'RuleTestData': ('app.schemas.system', 'RuleTestData'),
|
||||||
@@ -349,7 +363,10 @@ SCHEMA_EXPORTS = {
|
|||||||
'Subscribe': ('app.schemas.workflow', 'Subscribe'),
|
'Subscribe': ('app.schemas.workflow', 'Subscribe'),
|
||||||
'SubscribeAddedEventData': ('app.schemas.event', 'SubscribeAddedEventData'),
|
'SubscribeAddedEventData': ('app.schemas.event', 'SubscribeAddedEventData'),
|
||||||
'SubscribeCompleteEventData': ('app.schemas.event', 'SubscribeCompleteEventData'),
|
'SubscribeCompleteEventData': ('app.schemas.event', 'SubscribeCompleteEventData'),
|
||||||
|
'SubscribeCompletionCheckContractData': ('app.schemas.event', 'SubscribeCompletionCheckContractData'),
|
||||||
'SubscribeCompletionCheckEventData': ('app.schemas.event', 'SubscribeCompletionCheckEventData'),
|
'SubscribeCompletionCheckEventData': ('app.schemas.event', 'SubscribeCompletionCheckEventData'),
|
||||||
|
'SubscribeCompletionCheckInputContractData': ('app.schemas.event', 'SubscribeCompletionCheckInputContractData'),
|
||||||
|
'SubscribeCompletionCheckOutputContractData': ('app.schemas.event', 'SubscribeCompletionCheckOutputContractData'),
|
||||||
'SubscribeDeletedEventData': ('app.schemas.event', 'SubscribeDeletedEventData'),
|
'SubscribeDeletedEventData': ('app.schemas.event', 'SubscribeDeletedEventData'),
|
||||||
'SubscribeDownloadFileInfo': ('app.schemas.subscribe', 'SubscribeDownloadFileInfo'),
|
'SubscribeDownloadFileInfo': ('app.schemas.subscribe', 'SubscribeDownloadFileInfo'),
|
||||||
'SubscribeEpisodeInfo': ('app.schemas.subscribe', 'SubscribeEpisodeInfo'),
|
'SubscribeEpisodeInfo': ('app.schemas.subscribe', 'SubscribeEpisodeInfo'),
|
||||||
@@ -396,6 +413,7 @@ SCHEMA_EXPORTS = {
|
|||||||
'TransferOverwriteCheckEventData': ('app.schemas.event', 'TransferOverwriteCheckEventData'),
|
'TransferOverwriteCheckEventData': ('app.schemas.event', 'TransferOverwriteCheckEventData'),
|
||||||
'TransferRenameBuildEventData': ('app.schemas.event', 'TransferRenameBuildEventData'),
|
'TransferRenameBuildEventData': ('app.schemas.event', 'TransferRenameBuildEventData'),
|
||||||
'TransferRenameEventData': ('app.schemas.event', 'TransferRenameEventData'),
|
'TransferRenameEventData': ('app.schemas.event', 'TransferRenameEventData'),
|
||||||
|
'TransferResultContractData': ('app.schemas.event', 'TransferResultContractData'),
|
||||||
'TransferResultEventData': ('app.schemas.event', 'TransferResultEventData'),
|
'TransferResultEventData': ('app.schemas.event', 'TransferResultEventData'),
|
||||||
'TransferTorrent': ('app.schemas.transfer', 'TransferTorrent'),
|
'TransferTorrent': ('app.schemas.transfer', 'TransferTorrent'),
|
||||||
'TypeAdapter': ('app.schemas.mcp', 'TypeAdapter'),
|
'TypeAdapter': ('app.schemas.mcp', 'TypeAdapter'),
|
||||||
|
|||||||
+42
-2
@@ -1,6 +1,46 @@
|
|||||||
"""插件事件订阅与发布接口。"""
|
"""插件事件订阅与发布接口。"""
|
||||||
|
|
||||||
|
from app.runtime.event.snapshot import EventPayloadSnapshot, snapshot_event_data
|
||||||
from app.runtime.events import Event, EventManager, eventmanager
|
from app.runtime.events import Event, EventManager, eventmanager
|
||||||
|
from app.schemas.event import (
|
||||||
|
ContextSnapshot,
|
||||||
|
DownloadAddedContractData,
|
||||||
|
FileContextSnapshot,
|
||||||
|
MediaSnapshot,
|
||||||
|
MetadataScrapeContractData,
|
||||||
|
MetaSnapshot,
|
||||||
|
ResourceDownloadContractData,
|
||||||
|
ResourceDownloadInputContractData,
|
||||||
|
ResourceDownloadOutputContractData,
|
||||||
|
ResourceSelectionContractData,
|
||||||
|
ResourceSelectionInputContractData,
|
||||||
|
ResourceSelectionOutputContractData,
|
||||||
|
SubscribeCompletionCheckContractData,
|
||||||
|
SubscribeCompletionCheckInputContractData,
|
||||||
|
SubscribeCompletionCheckOutputContractData,
|
||||||
|
TransferResultContractData,
|
||||||
|
)
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
__all__ = ["Event", "EventManager", "eventmanager"]
|
"ContextSnapshot",
|
||||||
|
"DownloadAddedContractData",
|
||||||
|
"Event",
|
||||||
|
"EventManager",
|
||||||
|
"EventPayloadSnapshot",
|
||||||
|
"FileContextSnapshot",
|
||||||
|
"MediaSnapshot",
|
||||||
|
"MetadataScrapeContractData",
|
||||||
|
"MetaSnapshot",
|
||||||
|
"ResourceDownloadContractData",
|
||||||
|
"ResourceDownloadInputContractData",
|
||||||
|
"ResourceDownloadOutputContractData",
|
||||||
|
"ResourceSelectionContractData",
|
||||||
|
"ResourceSelectionInputContractData",
|
||||||
|
"ResourceSelectionOutputContractData",
|
||||||
|
"SubscribeCompletionCheckContractData",
|
||||||
|
"SubscribeCompletionCheckInputContractData",
|
||||||
|
"SubscribeCompletionCheckOutputContractData",
|
||||||
|
"TransferResultContractData",
|
||||||
|
"eventmanager",
|
||||||
|
"snapshot_event_data",
|
||||||
|
]
|
||||||
|
|||||||
@@ -351,6 +351,19 @@ flowchart TB
|
|||||||
|
|
||||||
宿主内建 `EventType` / `ChainEventType` 均在事件注册表中绑定 typed payload。开放插件事件允许
|
宿主内建 `EventType` / `ChainEventType` 均在事件注册表中绑定 typed payload。开放插件事件允许
|
||||||
额外字段,校验只生成诊断;分发给既有插件的仍是原始 dict/model 对象,不改变事件 ABI。
|
额外字段,校验只生成诊断;分发给既有插件的仍是原始 dict/model 对象,不改变事件 ABI。
|
||||||
|
插件可通过 `app.sdk.events` 调用 `event.snapshot()` 或
|
||||||
|
`snapshot_event_data(event_type, event_data)` 获取独立的类型化快照。返回结果中的 `raw` 保留
|
||||||
|
原始对象,`payload` 是组合契约,链式事件还提供 `input` / `output` 快照;`known`、`valid` 和
|
||||||
|
`errors` 分别用于处理未知自定义事件和兼容期校验失败。快照修改不会回写原事件,如需拦截、取消
|
||||||
|
或替换链式结果,插件仍应修改原始 `event.event_data`。
|
||||||
|
|
||||||
|
```python
|
||||||
|
from app.sdk.events import snapshot_event_data
|
||||||
|
|
||||||
|
snapshot = snapshot_event_data(event.event_type, event.event_data)
|
||||||
|
if snapshot.valid and snapshot.payload.context.media_info.type == "音乐":
|
||||||
|
music_type = snapshot.payload.context.media_info.music_type
|
||||||
|
```
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
|
|||||||
@@ -536,6 +536,7 @@ Durable post-commit side effects have a separate boundary:
|
|||||||
| `app/runtime/event/binding.py` | Explicit module/plugin/host handler resolvers; unresolved classes are diagnosed and skipped, never implicitly constructed by the bus |
|
| `app/runtime/event/binding.py` | Explicit module/plugin/host handler resolvers; unresolved classes are diagnosed and skipped, never implicitly constructed by the bus |
|
||||||
| `app/runtime/event/dispatch.py` | Chain/broadcast ordering, concurrency, target-plugin filtering and isolated delivery |
|
| `app/runtime/event/dispatch.py` | Chain/broadcast ordering, concurrency, target-plugin filtering and isolated delivery |
|
||||||
| `app/runtime/event/errors.py` | Handler failure notification and non-recursive `SystemError` downgrade policy |
|
| `app/runtime/event/errors.py` | Handler failure notification and non-recursive `SystemError` downgrade policy |
|
||||||
|
| `app/runtime/event/snapshot.py` | Read-only typed payload snapshots for the plugin SDK; never mutates or replaces the event ABI |
|
||||||
| `app/runtime/extensions/module/dispatcher.py` | Plugin-first invocation, short-circuit, list merge, signature relay and sync/async execution |
|
| `app/runtime/extensions/module/dispatcher.py` | Plugin-first invocation, short-circuit, list merge, signature relay and sync/async execution |
|
||||||
| `app/runtime/extensions/module/contracts.py` | High-frequency method families and frozen legacy fallback contract |
|
| `app/runtime/extensions/module/contracts.py` | High-frequency method families and frozen legacy fallback contract |
|
||||||
| `app/application/chain/context.py` | Injectable Chain dependencies and no-argument compatibility provider |
|
| `app/application/chain/context.py` | Injectable Chain dependencies and no-argument compatibility provider |
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ from collections import defaultdict
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
|
|
||||||
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
||||||
APP_ROOT = PROJECT_ROOT / "app"
|
APP_ROOT = PROJECT_ROOT / "app"
|
||||||
BASELINE_ROOT = PROJECT_ROOT / "tests" / "fixtures" / "architecture"
|
BASELINE_ROOT = PROJECT_ROOT / "tests" / "fixtures" / "architecture"
|
||||||
@@ -988,6 +987,15 @@ def collect_event_specs() -> dict[str, Any]:
|
|||||||
return {
|
return {
|
||||||
contract.event_name: {
|
contract.event_name: {
|
||||||
"payload_contract": contract.payload_contract,
|
"payload_contract": contract.payload_contract,
|
||||||
|
"input_contract": (
|
||||||
|
contract.input_model.__name__ if contract.input_model else None
|
||||||
|
),
|
||||||
|
"output_contract": (
|
||||||
|
contract.output_model.__name__ if contract.output_model else None
|
||||||
|
),
|
||||||
|
"schema_version": contract.schema_version,
|
||||||
|
"payload_mode": contract.payload_mode.value,
|
||||||
|
"validation_mode": contract.validation_mode.value,
|
||||||
"mode": contract.mode,
|
"mode": contract.mode,
|
||||||
"visibility": contract.visibility.value,
|
"visibility": contract.visibility.value,
|
||||||
"delivery": contract.delivery.value,
|
"delivery": contract.delivery.value,
|
||||||
|
|||||||
+17
-3
@@ -13,8 +13,8 @@
|
|||||||
"runtime_to_db": [],
|
"runtime_to_db": [],
|
||||||
"workflow_to_db": []
|
"workflow_to_db": []
|
||||||
},
|
},
|
||||||
"edge_count": 6689,
|
"edge_count": 6702,
|
||||||
"edge_sha256": "764be9020b4657c344453dc801ba270c925a2b26c94c0fb43c5a9f89953a4e07",
|
"edge_sha256": "a6d5e5b0ccca6f84fe5d8aa5acb0402e7253958913da8d9624a23bd80ceab748",
|
||||||
"edges": [
|
"edges": [
|
||||||
"app -> app.runtime",
|
"app -> app.runtime",
|
||||||
"app -> app.runtime.compat",
|
"app -> app.runtime.compat",
|
||||||
@@ -5734,6 +5734,11 @@
|
|||||||
"app.runtime.event.registry -> app.runtime.log",
|
"app.runtime.event.registry -> app.runtime.log",
|
||||||
"app.runtime.event.registry -> app.schemas",
|
"app.runtime.event.registry -> app.schemas",
|
||||||
"app.runtime.event.registry -> app.schemas.types",
|
"app.runtime.event.registry -> app.schemas.types",
|
||||||
|
"app.runtime.event.snapshot -> app.runtime",
|
||||||
|
"app.runtime.event.snapshot -> app.runtime.event",
|
||||||
|
"app.runtime.event.snapshot -> app.runtime.event.contracts",
|
||||||
|
"app.runtime.event.snapshot -> app.schemas",
|
||||||
|
"app.runtime.event.snapshot -> app.schemas.types",
|
||||||
"app.runtime.events -> app.foundation",
|
"app.runtime.events -> app.foundation",
|
||||||
"app.runtime.events -> app.foundation.singleton",
|
"app.runtime.events -> app.foundation.singleton",
|
||||||
"app.runtime.events -> app.runtime",
|
"app.runtime.events -> app.runtime",
|
||||||
@@ -5745,6 +5750,7 @@
|
|||||||
"app.runtime.events -> app.runtime.event.dispatch",
|
"app.runtime.events -> app.runtime.event.dispatch",
|
||||||
"app.runtime.events -> app.runtime.event.errors",
|
"app.runtime.events -> app.runtime.event.errors",
|
||||||
"app.runtime.events -> app.runtime.event.registry",
|
"app.runtime.events -> app.runtime.event.registry",
|
||||||
|
"app.runtime.events -> app.runtime.event.snapshot",
|
||||||
"app.runtime.events -> app.runtime.log",
|
"app.runtime.events -> app.runtime.log",
|
||||||
"app.runtime.events -> app.runtime.observability",
|
"app.runtime.events -> app.runtime.observability",
|
||||||
"app.runtime.events -> app.runtime.rate",
|
"app.runtime.events -> app.runtime.rate",
|
||||||
@@ -5987,8 +5993,11 @@
|
|||||||
"app.schemas.dashboard -> app.schemas.common",
|
"app.schemas.dashboard -> app.schemas.common",
|
||||||
"app.schemas.event -> app.schemas",
|
"app.schemas.event -> app.schemas",
|
||||||
"app.schemas.event -> app.schemas.common",
|
"app.schemas.event -> app.schemas.common",
|
||||||
|
"app.schemas.event -> app.schemas.context",
|
||||||
"app.schemas.event -> app.schemas.file",
|
"app.schemas.event -> app.schemas.file",
|
||||||
"app.schemas.event -> app.schemas.media",
|
"app.schemas.event -> app.schemas.media",
|
||||||
|
"app.schemas.event -> app.schemas.music",
|
||||||
|
"app.schemas.event -> app.schemas.subscribe",
|
||||||
"app.schemas.event -> app.schemas.transfer",
|
"app.schemas.event -> app.schemas.transfer",
|
||||||
"app.schemas.event -> app.schemas.types",
|
"app.schemas.event -> app.schemas.types",
|
||||||
"app.schemas.file -> app.schemas",
|
"app.schemas.file -> app.schemas",
|
||||||
@@ -6093,7 +6102,11 @@
|
|||||||
"app.sdk.database -> app.application.backup",
|
"app.sdk.database -> app.application.backup",
|
||||||
"app.sdk.database -> app.application.database",
|
"app.sdk.database -> app.application.database",
|
||||||
"app.sdk.events -> app.runtime",
|
"app.sdk.events -> app.runtime",
|
||||||
|
"app.sdk.events -> app.runtime.event",
|
||||||
|
"app.sdk.events -> app.runtime.event.snapshot",
|
||||||
"app.sdk.events -> app.runtime.events",
|
"app.sdk.events -> app.runtime.events",
|
||||||
|
"app.sdk.events -> app.schemas",
|
||||||
|
"app.sdk.events -> app.schemas.event",
|
||||||
"app.sdk.logging -> app.runtime",
|
"app.sdk.logging -> app.runtime",
|
||||||
"app.sdk.logging -> app.runtime.log",
|
"app.sdk.logging -> app.runtime.log",
|
||||||
"app.sdk.media -> app.domain",
|
"app.sdk.media -> app.domain",
|
||||||
@@ -6706,7 +6719,7 @@
|
|||||||
"app.workflow.actions.transfer_file -> app.workflow",
|
"app.workflow.actions.transfer_file -> app.workflow",
|
||||||
"app.workflow.actions.transfer_file -> app.workflow.actions"
|
"app.workflow.actions.transfer_file -> app.workflow.actions"
|
||||||
],
|
],
|
||||||
"module_count": 823,
|
"module_count": 824,
|
||||||
"modules": [
|
"modules": [
|
||||||
"app",
|
"app",
|
||||||
"app.adapters",
|
"app.adapters",
|
||||||
@@ -7382,6 +7395,7 @@
|
|||||||
"app.runtime.event.dispatch",
|
"app.runtime.event.dispatch",
|
||||||
"app.runtime.event.errors",
|
"app.runtime.event.errors",
|
||||||
"app.runtime.event.registry",
|
"app.runtime.event.registry",
|
||||||
|
"app.runtime.event.snapshot",
|
||||||
"app.runtime.events",
|
"app.runtime.events",
|
||||||
"app.runtime.execution",
|
"app.runtime.execution",
|
||||||
"app.runtime.extensions",
|
"app.runtime.extensions",
|
||||||
|
|||||||
+366
-11
@@ -1163,539 +1163,804 @@
|
|||||||
"ChainEventType.AgentLLMProvider": {
|
"ChainEventType.AgentLLMProvider": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "stop_chain",
|
"error_behavior": "stop_chain",
|
||||||
|
"input_contract": "AgentLLMProviderEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "chain",
|
"mode": "chain",
|
||||||
"ordering": "priority_serial",
|
"ordering": "priority_serial",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "AgentLLMProviderEventData",
|
"payload_contract": "AgentLLMProviderEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [
|
"sensitive_fields": [
|
||||||
"api_key"
|
"api_key"
|
||||||
],
|
],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"ChainEventType.AuthIntercept": {
|
"ChainEventType.AuthIntercept": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "stop_chain",
|
"error_behavior": "stop_chain",
|
||||||
|
"input_contract": "AuthInterceptCredentials",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "chain",
|
"mode": "chain",
|
||||||
"ordering": "priority_serial",
|
"ordering": "priority_serial",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "AuthInterceptCredentials",
|
"payload_contract": "AuthInterceptCredentials",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [
|
"sensitive_fields": [
|
||||||
"token"
|
"token"
|
||||||
],
|
],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"ChainEventType.AuthVerification": {
|
"ChainEventType.AuthVerification": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "stop_chain",
|
"error_behavior": "stop_chain",
|
||||||
|
"input_contract": "AuthCredentials",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "chain",
|
"mode": "chain",
|
||||||
"ordering": "priority_serial",
|
"ordering": "priority_serial",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "AuthCredentials",
|
"payload_contract": "AuthCredentials",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [
|
"sensitive_fields": [
|
||||||
"password",
|
"password",
|
||||||
"token",
|
"token",
|
||||||
"mfa_code"
|
"mfa_code"
|
||||||
],
|
],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"ChainEventType.CommandRegister": {
|
"ChainEventType.CommandRegister": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "stop_chain",
|
"error_behavior": "stop_chain",
|
||||||
|
"input_contract": "CommandRegisterEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "chain",
|
"mode": "chain",
|
||||||
"ordering": "priority_serial",
|
"ordering": "priority_serial",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "CommandRegisterEventData",
|
"payload_contract": "CommandRegisterEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"ChainEventType.DiscoverSource": {
|
"ChainEventType.DiscoverSource": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "stop_chain",
|
"error_behavior": "stop_chain",
|
||||||
|
"input_contract": "DiscoverSourceEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "chain",
|
"mode": "chain",
|
||||||
"ordering": "priority_serial",
|
"ordering": "priority_serial",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "DiscoverSourceEventData",
|
"payload_contract": "DiscoverSourceEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"ChainEventType.MediaRecognize": {
|
"ChainEventType.MediaRecognize": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "stop_chain",
|
"error_behavior": "stop_chain",
|
||||||
|
"input_contract": "MediaRecognizeEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "chain",
|
"mode": "chain",
|
||||||
"ordering": "priority_serial",
|
"ordering": "priority_serial",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "MediaRecognizeEventData",
|
"payload_contract": "MediaRecognizeEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"ChainEventType.MediaRecognizeConvert": {
|
"ChainEventType.MediaRecognizeConvert": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "stop_chain",
|
"error_behavior": "stop_chain",
|
||||||
|
"input_contract": "MediaRecognizeConvertEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "chain",
|
"mode": "chain",
|
||||||
"ordering": "priority_serial",
|
"ordering": "priority_serial",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "MediaRecognizeConvertEventData",
|
"payload_contract": "MediaRecognizeConvertEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"ChainEventType.MusicMediaRecognize": {
|
"ChainEventType.MusicMediaRecognize": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "stop_chain",
|
"error_behavior": "stop_chain",
|
||||||
|
"input_contract": "MusicMediaRecognizeEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "chain",
|
"mode": "chain",
|
||||||
"ordering": "priority_serial",
|
"ordering": "priority_serial",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "MusicMediaRecognizeEventData",
|
"payload_contract": "MusicMediaRecognizeEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"ChainEventType.MusicNameRecognize": {
|
"ChainEventType.MusicNameRecognize": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "stop_chain",
|
"error_behavior": "stop_chain",
|
||||||
|
"input_contract": "MusicNameRecognizeEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "chain",
|
"mode": "chain",
|
||||||
"ordering": "priority_serial",
|
"ordering": "priority_serial",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "MusicNameRecognizeEventData",
|
"payload_contract": "MusicNameRecognizeEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"ChainEventType.NameRecognize": {
|
"ChainEventType.NameRecognize": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "stop_chain",
|
"error_behavior": "stop_chain",
|
||||||
|
"input_contract": "NameRecognizeEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "chain",
|
"mode": "chain",
|
||||||
"ordering": "priority_serial",
|
"ordering": "priority_serial",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "NameRecognizeEventData",
|
"payload_contract": "NameRecognizeEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"ChainEventType.PluginDataReset": {
|
"ChainEventType.PluginDataReset": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "stop_chain",
|
"error_behavior": "stop_chain",
|
||||||
|
"input_contract": "PluginDataResetEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "chain",
|
"mode": "chain",
|
||||||
"ordering": "priority_serial",
|
"ordering": "priority_serial",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "PluginDataResetEventData",
|
"payload_contract": "PluginDataResetEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"ChainEventType.RecommendSource": {
|
"ChainEventType.RecommendSource": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "stop_chain",
|
"error_behavior": "stop_chain",
|
||||||
|
"input_contract": "RecommendSourceEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "chain",
|
"mode": "chain",
|
||||||
"ordering": "priority_serial",
|
"ordering": "priority_serial",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "RecommendSourceEventData",
|
"payload_contract": "RecommendSourceEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"ChainEventType.ResourceDownload": {
|
"ChainEventType.ResourceDownload": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "stop_chain",
|
"error_behavior": "stop_chain",
|
||||||
|
"input_contract": "ResourceDownloadInputContractData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "chain",
|
"mode": "chain",
|
||||||
"ordering": "priority_serial",
|
"ordering": "priority_serial",
|
||||||
"payload_contract": "ResourceDownloadEventData",
|
"output_contract": "ResourceDownloadOutputContractData",
|
||||||
|
"payload_contract": "ResourceDownloadContractData",
|
||||||
|
"payload_mode": "snapshot",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"ChainEventType.ResourceSelection": {
|
"ChainEventType.ResourceSelection": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "stop_chain",
|
"error_behavior": "stop_chain",
|
||||||
|
"input_contract": "ResourceSelectionInputContractData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "chain",
|
"mode": "chain",
|
||||||
"ordering": "priority_serial",
|
"ordering": "priority_serial",
|
||||||
"payload_contract": "ResourceSelectionEventData",
|
"output_contract": "ResourceSelectionOutputContractData",
|
||||||
|
"payload_contract": "ResourceSelectionContractData",
|
||||||
|
"payload_mode": "snapshot",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"ChainEventType.StorageOperSelection": {
|
"ChainEventType.StorageOperSelection": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "stop_chain",
|
"error_behavior": "stop_chain",
|
||||||
|
"input_contract": "StorageOperSelectionEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "chain",
|
"mode": "chain",
|
||||||
"ordering": "priority_serial",
|
"ordering": "priority_serial",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "StorageOperSelectionEventData",
|
"payload_contract": "StorageOperSelectionEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"ChainEventType.SubscribeCompletionCheck": {
|
"ChainEventType.SubscribeCompletionCheck": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "stop_chain",
|
"error_behavior": "stop_chain",
|
||||||
|
"input_contract": "SubscribeCompletionCheckInputContractData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "chain",
|
"mode": "chain",
|
||||||
"ordering": "priority_serial",
|
"ordering": "priority_serial",
|
||||||
"payload_contract": "SubscribeCompletionCheckEventData",
|
"output_contract": "SubscribeCompletionCheckOutputContractData",
|
||||||
|
"payload_contract": "SubscribeCompletionCheckContractData",
|
||||||
|
"payload_mode": "snapshot",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"ChainEventType.SubscribeEpisodesRefresh": {
|
"ChainEventType.SubscribeEpisodesRefresh": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "stop_chain",
|
"error_behavior": "stop_chain",
|
||||||
|
"input_contract": "SubscribeEpisodesRefreshEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "chain",
|
"mode": "chain",
|
||||||
"ordering": "priority_serial",
|
"ordering": "priority_serial",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "SubscribeEpisodesRefreshEventData",
|
"payload_contract": "SubscribeEpisodesRefreshEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"ChainEventType.TransferIntercept": {
|
"ChainEventType.TransferIntercept": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "stop_chain",
|
"error_behavior": "stop_chain",
|
||||||
|
"input_contract": "TransferInterceptEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "chain",
|
"mode": "chain",
|
||||||
"ordering": "priority_serial",
|
"ordering": "priority_serial",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "TransferInterceptEventData",
|
"payload_contract": "TransferInterceptEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"ChainEventType.TransferOverwriteCheck": {
|
"ChainEventType.TransferOverwriteCheck": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "stop_chain",
|
"error_behavior": "stop_chain",
|
||||||
|
"input_contract": "TransferOverwriteCheckEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "chain",
|
"mode": "chain",
|
||||||
"ordering": "priority_serial",
|
"ordering": "priority_serial",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "TransferOverwriteCheckEventData",
|
"payload_contract": "TransferOverwriteCheckEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"ChainEventType.TransferRename": {
|
"ChainEventType.TransferRename": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "stop_chain",
|
"error_behavior": "stop_chain",
|
||||||
|
"input_contract": "TransferRenameEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "chain",
|
"mode": "chain",
|
||||||
"ordering": "priority_serial",
|
"ordering": "priority_serial",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "TransferRenameEventData",
|
"payload_contract": "TransferRenameEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"ChainEventType.TransferRenameBuild": {
|
"ChainEventType.TransferRenameBuild": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "stop_chain",
|
"error_behavior": "stop_chain",
|
||||||
|
"input_contract": "TransferRenameBuildEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "chain",
|
"mode": "chain",
|
||||||
"ordering": "priority_serial",
|
"ordering": "priority_serial",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "TransferRenameBuildEventData",
|
"payload_contract": "TransferRenameBuildEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"ChainEventType.WorkflowExecution": {
|
"ChainEventType.WorkflowExecution": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "stop_chain",
|
"error_behavior": "stop_chain",
|
||||||
|
"input_contract": "ActionContext",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "chain",
|
"mode": "chain",
|
||||||
"ordering": "priority_serial",
|
"ordering": "priority_serial",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "ActionContext",
|
"payload_contract": "ActionContext",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.AgentTokensUsage": {
|
"EventType.AgentTokensUsage": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "AgentTokensUsageEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "AgentTokensUsageEventData",
|
"payload_contract": "AgentTokensUsageEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.AudioTransferComplete": {
|
"EventType.AudioTransferComplete": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "TransferResultContractData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
"payload_contract": "TransferResultEventData",
|
"output_contract": null,
|
||||||
|
"payload_contract": "TransferResultContractData",
|
||||||
|
"payload_mode": "snapshot",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.AudioTransferFailed": {
|
"EventType.AudioTransferFailed": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "TransferResultContractData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
"payload_contract": "TransferResultEventData",
|
"output_contract": null,
|
||||||
|
"payload_contract": "TransferResultContractData",
|
||||||
|
"payload_mode": "snapshot",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.CommandExcute": {
|
"EventType.CommandExcute": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "CommandExecuteEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "CommandExecuteEventData",
|
"payload_contract": "CommandExecuteEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.ConfigChanged": {
|
"EventType.ConfigChanged": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "ConfigChangeEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "ConfigChangeEventData",
|
"payload_contract": "ConfigChangeEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "host_only"
|
"visibility": "host_only"
|
||||||
},
|
},
|
||||||
"EventType.DownloadAdded": {
|
"EventType.DownloadAdded": {
|
||||||
"delivery": "durable_required",
|
"delivery": "durable_required",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "DownloadAddedContractData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
"payload_contract": "DownloadAddedEventData",
|
"output_contract": null,
|
||||||
|
"payload_contract": "DownloadAddedContractData",
|
||||||
|
"payload_mode": "snapshot",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.DownloadDeleted": {
|
"EventType.DownloadDeleted": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "DownloadDeletedEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "DownloadDeletedEventData",
|
"payload_contract": "DownloadDeletedEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.DownloadFileDeleted": {
|
"EventType.DownloadFileDeleted": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "DownloadFileDeletedEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "DownloadFileDeletedEventData",
|
"payload_contract": "DownloadFileDeletedEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.HistoryDeleted": {
|
"EventType.HistoryDeleted": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "HistoryDeletedEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "HistoryDeletedEventData",
|
"payload_contract": "HistoryDeletedEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.MessageAction": {
|
"EventType.MessageAction": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "MessageActionEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "MessageActionEventData",
|
"payload_contract": "MessageActionEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.MetadataScrape": {
|
"EventType.MetadataScrape": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "MetadataScrapeContractData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
"payload_contract": "MetadataScrapeEventData",
|
"output_contract": null,
|
||||||
|
"payload_contract": "MetadataScrapeContractData",
|
||||||
|
"payload_mode": "snapshot",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.ModuleReload": {
|
"EventType.ModuleReload": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "EmptyEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "EmptyEventData",
|
"payload_contract": "EmptyEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "host_only"
|
"visibility": "host_only"
|
||||||
},
|
},
|
||||||
"EventType.NoticeMessage": {
|
"EventType.NoticeMessage": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "NoticeMessageEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "NoticeMessageEventData",
|
"payload_contract": "NoticeMessageEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.PluginAction": {
|
"EventType.PluginAction": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "PluginActionEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "PluginActionEventData",
|
"payload_contract": "PluginActionEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "target_plugin"
|
"visibility": "target_plugin"
|
||||||
},
|
},
|
||||||
"EventType.PluginReload": {
|
"EventType.PluginReload": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "PluginReloadEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "PluginReloadEventData",
|
"payload_contract": "PluginReloadEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.PluginTriggered": {
|
"EventType.PluginTriggered": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "PluginTriggeredEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "PluginTriggeredEventData",
|
"payload_contract": "PluginTriggeredEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "target_plugin"
|
"visibility": "target_plugin"
|
||||||
},
|
},
|
||||||
"EventType.SiteDeleted": {
|
"EventType.SiteDeleted": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "SiteEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "SiteEventData",
|
"payload_contract": "SiteEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.SiteRefreshed": {
|
"EventType.SiteRefreshed": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "SiteEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "SiteEventData",
|
"payload_contract": "SiteEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.SiteUpdated": {
|
"EventType.SiteUpdated": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "SiteEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "SiteEventData",
|
"payload_contract": "SiteEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.SubscribeAdded": {
|
"EventType.SubscribeAdded": {
|
||||||
"delivery": "durable_required",
|
"delivery": "durable_required",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "SubscribeAddedEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "SubscribeAddedEventData",
|
"payload_contract": "SubscribeAddedEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.SubscribeComplete": {
|
"EventType.SubscribeComplete": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "SubscribeCompleteEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "SubscribeCompleteEventData",
|
"payload_contract": "SubscribeCompleteEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.SubscribeDeleted": {
|
"EventType.SubscribeDeleted": {
|
||||||
"delivery": "durable_required",
|
"delivery": "durable_required",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "SubscribeDeletedEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "SubscribeDeletedEventData",
|
"payload_contract": "SubscribeDeletedEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.SubscribeModified": {
|
"EventType.SubscribeModified": {
|
||||||
"delivery": "durable_required",
|
"delivery": "durable_required",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "SubscribeModifiedEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "SubscribeModifiedEventData",
|
"payload_contract": "SubscribeModifiedEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.SubtitleTransferComplete": {
|
"EventType.SubtitleTransferComplete": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "TransferResultContractData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
"payload_contract": "TransferResultEventData",
|
"output_contract": null,
|
||||||
|
"payload_contract": "TransferResultContractData",
|
||||||
|
"payload_mode": "snapshot",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.SubtitleTransferFailed": {
|
"EventType.SubtitleTransferFailed": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "TransferResultContractData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
"payload_contract": "TransferResultEventData",
|
"output_contract": null,
|
||||||
|
"payload_contract": "TransferResultContractData",
|
||||||
|
"payload_mode": "snapshot",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.SystemError": {
|
"EventType.SystemError": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "SystemErrorEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "SystemErrorEventData",
|
"payload_contract": "SystemErrorEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "host_only"
|
"visibility": "host_only"
|
||||||
},
|
},
|
||||||
"EventType.TransferComplete": {
|
"EventType.TransferComplete": {
|
||||||
"delivery": "durable_required",
|
"delivery": "durable_required",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "TransferResultContractData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
"payload_contract": "TransferResultEventData",
|
"output_contract": null,
|
||||||
|
"payload_contract": "TransferResultContractData",
|
||||||
|
"payload_mode": "snapshot",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.TransferFailed": {
|
"EventType.TransferFailed": {
|
||||||
"delivery": "durable_required",
|
"delivery": "durable_required",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "TransferResultContractData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
"payload_contract": "TransferResultEventData",
|
"output_contract": null,
|
||||||
|
"payload_contract": "TransferResultContractData",
|
||||||
|
"payload_mode": "snapshot",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.UserMessage": {
|
"EventType.UserMessage": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "UserMessageEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "UserMessageEventData",
|
"payload_contract": "UserMessageEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.WebhookMessage": {
|
"EventType.WebhookMessage": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "WebhookEventInfo",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "WebhookEventInfo",
|
"payload_contract": "WebhookEventInfo",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
},
|
},
|
||||||
"EventType.WorkflowExecute": {
|
"EventType.WorkflowExecute": {
|
||||||
"delivery": "ephemeral",
|
"delivery": "ephemeral",
|
||||||
"error_behavior": "notify",
|
"error_behavior": "notify",
|
||||||
|
"input_contract": "WorkflowExecuteEventData",
|
||||||
"legacy_reason": null,
|
"legacy_reason": null,
|
||||||
"mode": "broadcast",
|
"mode": "broadcast",
|
||||||
"ordering": "priority_queue",
|
"ordering": "priority_queue",
|
||||||
|
"output_contract": null,
|
||||||
"payload_contract": "WorkflowExecuteEventData",
|
"payload_contract": "WorkflowExecuteEventData",
|
||||||
|
"payload_mode": "runtime",
|
||||||
|
"schema_version": 1,
|
||||||
"sensitive_fields": [],
|
"sensitive_fields": [],
|
||||||
|
"validation_mode": "diagnostic",
|
||||||
"visibility": "plugin_public"
|
"visibility": "plugin_public"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -8239,6 +8504,16 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"app.sdk.events": [
|
"app.sdk.events": [
|
||||||
|
{
|
||||||
|
"kind": "import",
|
||||||
|
"name": "ContextSnapshot",
|
||||||
|
"target": "app.schemas.event.ContextSnapshot"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "import",
|
||||||
|
"name": "DownloadAddedContractData",
|
||||||
|
"target": "app.schemas.event.DownloadAddedContractData"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"kind": "import",
|
"kind": "import",
|
||||||
"name": "Event",
|
"name": "Event",
|
||||||
@@ -8249,10 +8524,90 @@
|
|||||||
"name": "EventManager",
|
"name": "EventManager",
|
||||||
"target": "app.runtime.events.EventManager"
|
"target": "app.runtime.events.EventManager"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"kind": "import",
|
||||||
|
"name": "EventPayloadSnapshot",
|
||||||
|
"target": "app.runtime.event.snapshot.EventPayloadSnapshot"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "import",
|
||||||
|
"name": "FileContextSnapshot",
|
||||||
|
"target": "app.schemas.event.FileContextSnapshot"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "import",
|
||||||
|
"name": "MediaSnapshot",
|
||||||
|
"target": "app.schemas.event.MediaSnapshot"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "import",
|
||||||
|
"name": "MetaSnapshot",
|
||||||
|
"target": "app.schemas.event.MetaSnapshot"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "import",
|
||||||
|
"name": "MetadataScrapeContractData",
|
||||||
|
"target": "app.schemas.event.MetadataScrapeContractData"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "import",
|
||||||
|
"name": "ResourceDownloadContractData",
|
||||||
|
"target": "app.schemas.event.ResourceDownloadContractData"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "import",
|
||||||
|
"name": "ResourceDownloadInputContractData",
|
||||||
|
"target": "app.schemas.event.ResourceDownloadInputContractData"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "import",
|
||||||
|
"name": "ResourceDownloadOutputContractData",
|
||||||
|
"target": "app.schemas.event.ResourceDownloadOutputContractData"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "import",
|
||||||
|
"name": "ResourceSelectionContractData",
|
||||||
|
"target": "app.schemas.event.ResourceSelectionContractData"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "import",
|
||||||
|
"name": "ResourceSelectionInputContractData",
|
||||||
|
"target": "app.schemas.event.ResourceSelectionInputContractData"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "import",
|
||||||
|
"name": "ResourceSelectionOutputContractData",
|
||||||
|
"target": "app.schemas.event.ResourceSelectionOutputContractData"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "import",
|
||||||
|
"name": "SubscribeCompletionCheckContractData",
|
||||||
|
"target": "app.schemas.event.SubscribeCompletionCheckContractData"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "import",
|
||||||
|
"name": "SubscribeCompletionCheckInputContractData",
|
||||||
|
"target": "app.schemas.event.SubscribeCompletionCheckInputContractData"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "import",
|
||||||
|
"name": "SubscribeCompletionCheckOutputContractData",
|
||||||
|
"target": "app.schemas.event.SubscribeCompletionCheckOutputContractData"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "import",
|
||||||
|
"name": "TransferResultContractData",
|
||||||
|
"target": "app.schemas.event.TransferResultContractData"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"kind": "import",
|
"kind": "import",
|
||||||
"name": "eventmanager",
|
"name": "eventmanager",
|
||||||
"target": "app.runtime.events.eventmanager"
|
"target": "app.runtime.events.eventmanager"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "import",
|
||||||
|
"name": "snapshot_event_data",
|
||||||
|
"target": "app.runtime.event.snapshot.snapshot_event_data"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"app.sdk.logging": [
|
"app.sdk.logging": [
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ from app.application.outbox import (
|
|||||||
DURABLE_EVENT_TOPICS,
|
DURABLE_EVENT_TOPICS,
|
||||||
validate_durable_event_handlers,
|
validate_durable_event_handlers,
|
||||||
)
|
)
|
||||||
|
from app.domain.context import Context, MediaInfo
|
||||||
|
from app.domain.metainfo import MetaInfo
|
||||||
from app.runtime.event.contracts import (
|
from app.runtime.event.contracts import (
|
||||||
EVENT_CONTRACTS,
|
EVENT_CONTRACTS,
|
||||||
EventDelivery,
|
EventDelivery,
|
||||||
@@ -15,9 +17,13 @@ from app.runtime.event.contracts import (
|
|||||||
validate_event_payload,
|
validate_event_payload,
|
||||||
)
|
)
|
||||||
from app.runtime.events import Event
|
from app.runtime.events import Event
|
||||||
from app.domain.context import Context, MediaInfo
|
from app.schemas.event import (
|
||||||
from app.domain.metainfo import MetaInfo
|
ConfigChangeEventData,
|
||||||
from app.schemas.event import ConfigChangeEventData
|
ResourceDownloadInputContractData,
|
||||||
|
ResourceDownloadOutputContractData,
|
||||||
|
ResourceSelectionInputContractData,
|
||||||
|
ResourceSelectionOutputContractData,
|
||||||
|
)
|
||||||
from app.schemas.file import FileItem
|
from app.schemas.file import FileItem
|
||||||
from app.schemas.transfer import TransferInfo
|
from app.schemas.transfer import TransferInfo
|
||||||
from app.schemas.types import ChainEventType, EventType, MediaType
|
from app.schemas.types import ChainEventType, EventType, MediaType
|
||||||
@@ -129,6 +135,37 @@ def test_download_and_transfer_typed_contracts_accept_legacy_runtime_objects() -
|
|||||||
) == ()
|
) == ()
|
||||||
|
|
||||||
|
|
||||||
|
def test_music_runtime_objects_are_checked_as_typed_snapshots() -> None:
|
||||||
|
"""音乐运行时对象保留给插件,同时通过快照契约明确 type/music_type。"""
|
||||||
|
from app.domain.context import MusicInfo
|
||||||
|
|
||||||
|
media = MusicInfo(title="Song", artists=["Artist"], album="Album")
|
||||||
|
context = Context(media_info=media)
|
||||||
|
|
||||||
|
assert validate_event_payload(
|
||||||
|
EventType.DownloadAdded,
|
||||||
|
{"hash": "music-hash", "context": context},
|
||||||
|
) == ()
|
||||||
|
assert validate_event_payload(
|
||||||
|
EventType.TransferComplete,
|
||||||
|
{"mediainfo": media},
|
||||||
|
) == ()
|
||||||
|
|
||||||
|
|
||||||
|
def test_snapshot_contract_metadata_declares_mutable_chain_boundaries() -> None:
|
||||||
|
"""核心链式事件公开快照输入输出模型,但仍处于兼容诊断模式。"""
|
||||||
|
selection = get_event_contract(ChainEventType.ResourceSelection)
|
||||||
|
download = get_event_contract(ChainEventType.ResourceDownload)
|
||||||
|
|
||||||
|
assert selection.schema_version == 1
|
||||||
|
assert selection.payload_mode.value == "snapshot"
|
||||||
|
assert selection.input_model is ResourceSelectionInputContractData
|
||||||
|
assert selection.output_model is ResourceSelectionOutputContractData
|
||||||
|
assert download.input_model is ResourceDownloadInputContractData
|
||||||
|
assert download.output_model is ResourceDownloadOutputContractData
|
||||||
|
assert selection.validation_mode.value == "diagnostic"
|
||||||
|
|
||||||
|
|
||||||
def test_model_instance_remains_mutable_chain_payload() -> None:
|
def test_model_instance_remains_mutable_chain_payload() -> None:
|
||||||
"""链式处理器继续接收原 model 实例,确保输出字段可原地接力。"""
|
"""链式处理器继续接收原 model 实例,确保输出字段可原地接力。"""
|
||||||
payload = ConfigChangeEventData(key={"PROXY_HOST"})
|
payload = ConfigChangeEventData(key={"PROXY_HOST"})
|
||||||
|
|||||||
@@ -0,0 +1,99 @@
|
|||||||
|
"""插件 SDK 事件快照访问测试。"""
|
||||||
|
|
||||||
|
from app.domain.context import Context, MediaInfo, MusicInfo
|
||||||
|
from app.runtime.event.snapshot import (
|
||||||
|
EventPayloadSnapshot as RuntimeEventPayloadSnapshot,
|
||||||
|
)
|
||||||
|
from app.runtime.event.snapshot import snapshot_event_data as runtime_snapshot_event_data
|
||||||
|
from app.schemas.event import ResourceSelectionEventData
|
||||||
|
from app.schemas.types import ChainEventType, EventType, MediaType
|
||||||
|
from app.sdk.events import (
|
||||||
|
DownloadAddedContractData,
|
||||||
|
Event,
|
||||||
|
EventPayloadSnapshot,
|
||||||
|
ResourceSelectionInputContractData,
|
||||||
|
ResourceSelectionOutputContractData,
|
||||||
|
snapshot_event_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_sdk_exports_canonical_snapshot_interfaces() -> None:
|
||||||
|
"""SDK 只公开 canonical 快照实现,不复制事件解析逻辑。"""
|
||||||
|
assert EventPayloadSnapshot is RuntimeEventPayloadSnapshot
|
||||||
|
assert snapshot_event_data is runtime_snapshot_event_data
|
||||||
|
|
||||||
|
|
||||||
|
def test_event_snapshot_exposes_music_type_without_changing_raw_payload() -> None:
|
||||||
|
"""插件可从快照稳定识别音乐,原 Context 和 MusicInfo 继续按旧 ABI 投递。"""
|
||||||
|
media = MusicInfo(title="Song", artists=["Artist"], album="Album")
|
||||||
|
context = Context(media_info=media)
|
||||||
|
raw = {"hash": "music-hash", "context": context}
|
||||||
|
event = Event(EventType.DownloadAdded, raw)
|
||||||
|
|
||||||
|
snapshot = event.snapshot()
|
||||||
|
|
||||||
|
assert snapshot.known is True
|
||||||
|
assert snapshot.valid is True
|
||||||
|
assert snapshot.raw is raw
|
||||||
|
assert isinstance(snapshot.payload, DownloadAddedContractData)
|
||||||
|
assert snapshot.input is snapshot.payload
|
||||||
|
assert snapshot.output is None
|
||||||
|
assert snapshot.payload.context.media_info.type == MediaType.MUSIC.value
|
||||||
|
assert snapshot.payload.context.media_info.music_type == "recording"
|
||||||
|
assert event.event_data["context"] is context
|
||||||
|
|
||||||
|
snapshot.payload.context.media_info.title = "Snapshot Song"
|
||||||
|
assert media.title == "Song"
|
||||||
|
|
||||||
|
|
||||||
|
def test_chain_snapshot_separates_plugin_input_and_output_models() -> None:
|
||||||
|
"""链式事件同时提供输入和回写快照,且不替换可变运行时事件模型。"""
|
||||||
|
context = Context(
|
||||||
|
media_info=MediaInfo(type=MediaType.MOVIE, title="Movie", year="2026")
|
||||||
|
)
|
||||||
|
raw = ResourceSelectionEventData(
|
||||||
|
contexts=[context],
|
||||||
|
updated=True,
|
||||||
|
updated_contexts=[context],
|
||||||
|
source="plugin",
|
||||||
|
)
|
||||||
|
event = Event(ChainEventType.ResourceSelection, raw)
|
||||||
|
|
||||||
|
snapshot = event.snapshot()
|
||||||
|
|
||||||
|
assert snapshot.raw is raw
|
||||||
|
assert isinstance(snapshot.input, ResourceSelectionInputContractData)
|
||||||
|
assert isinstance(snapshot.output, ResourceSelectionOutputContractData)
|
||||||
|
assert snapshot.input.contexts[0].media_info.type == MediaType.MOVIE.value
|
||||||
|
assert snapshot.output.updated is True
|
||||||
|
assert snapshot.output.updated_contexts[0].media_info.title == "Movie"
|
||||||
|
assert event.event_data is raw
|
||||||
|
|
||||||
|
|
||||||
|
def test_unknown_plugin_event_returns_unregistered_snapshot_without_error() -> None:
|
||||||
|
"""插件自定义字符串事件没有宿主契约时保留原 payload,不制造假模型。"""
|
||||||
|
raw = {"plugin_owned": {"value": 1}}
|
||||||
|
|
||||||
|
snapshot = snapshot_event_data("plugin.custom.event", raw)
|
||||||
|
|
||||||
|
assert snapshot.known is False
|
||||||
|
assert snapshot.valid is False
|
||||||
|
assert snapshot.raw is raw
|
||||||
|
assert snapshot.payload is None
|
||||||
|
assert snapshot.input is None
|
||||||
|
assert snapshot.output is None
|
||||||
|
assert snapshot.errors == ()
|
||||||
|
|
||||||
|
|
||||||
|
def test_invalid_known_event_returns_validation_errors_instead_of_raising() -> None:
|
||||||
|
"""坏 payload 由 SDK 结果携带错误,插件可自行决定降级策略。"""
|
||||||
|
raw = {"context": {"media_info": {"type": "音乐"}}}
|
||||||
|
|
||||||
|
snapshot = snapshot_event_data(EventType.DownloadAdded, raw)
|
||||||
|
|
||||||
|
assert snapshot.known is True
|
||||||
|
assert snapshot.valid is False
|
||||||
|
assert snapshot.raw is raw
|
||||||
|
assert snapshot.payload is None
|
||||||
|
assert snapshot.errors
|
||||||
|
assert "DownloadAddedContractData" in snapshot.errors[0]
|
||||||
Reference in New Issue
Block a user