chore: import upstream snapshot with attribution
Validate YAML Workflows / Validate YAML Configuration Files (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:37:51 +08:00
commit d0e4308def
614 changed files with 74458 additions and 0 deletions
+10
View File
@@ -0,0 +1,10 @@
"""Public helpers for edge payload processors."""
from .base import EdgePayloadProcessor, ProcessorFactoryContext
from .registry import build_edge_processor
__all__ = [
"EdgePayloadProcessor",
"ProcessorFactoryContext",
"build_edge_processor",
]
+50
View File
@@ -0,0 +1,50 @@
"""Base classes for payload processors applied on edges."""
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Any, Generic, TypeVar
from entity.messages import Message
from runtime.node.executor import ExecutionContext
from utils.log_manager import LogManager
from utils.function_manager import FunctionManager
TConfig = TypeVar("TConfig")
@dataclass(slots=True)
class ProcessorFactoryContext:
"""Context passed to processor implementations."""
function_manager: "FunctionManager | None" = None
log_manager: "LogManager | None" = None
class EdgePayloadProcessor(Generic[TConfig], ABC):
"""Base payload processor API."""
label: str | None = None
metadata: dict[str, Any] | None = None
def __init__(self, config: TConfig, ctx: ProcessorFactoryContext) -> None:
self.config = config
self.ctx = ctx
@abstractmethod
def transform(
self,
payload: Message,
*,
source_result: Message,
from_node: Any,
edge_link: Any,
log_manager: LogManager,
context: ExecutionContext,
) -> Message | None:
"""Return transformed payload or None to drop the message."""
def _clone(self, payload: Message) -> Message:
return payload.clone()
def _text(self, payload: Message) -> str:
return payload.text_content()
+23
View File
@@ -0,0 +1,23 @@
"""Register built-in edge payload processors."""
from entity.configs.edge.edge_processor import (
RegexEdgeProcessorConfig,
FunctionEdgeProcessorConfig,
)
from .registry import register_edge_processor
from .regex_processor import RegexEdgePayloadProcessor
from .function_processor import FunctionEdgePayloadProcessor
register_edge_processor(
"regex_extract",
processor_cls=RegexEdgePayloadProcessor,
summary="Extract payload fragments via Python regular expressions.",
config_cls=RegexEdgeProcessorConfig,
)
register_edge_processor(
"function",
processor_cls=FunctionEdgePayloadProcessor,
summary="Delegate message transformation to Python functions in functions/edge_processor.",
config_cls=FunctionEdgeProcessorConfig,
)
+76
View File
@@ -0,0 +1,76 @@
"""Payload processor that delegates to Python functions."""
from typing import Any, Callable, Mapping
from entity.messages import Message
from utils.log_manager import LogManager
from utils.structured_logger import get_server_logger
from .base import EdgePayloadProcessor, ProcessorFactoryContext
from entity.configs.edge.edge_processor import FunctionEdgeProcessorConfig
from runtime.node.executor import ExecutionContext
class FunctionEdgePayloadProcessor(EdgePayloadProcessor[FunctionEdgeProcessorConfig]):
def __init__(self, config: FunctionEdgeProcessorConfig, ctx: ProcessorFactoryContext) -> None:
super().__init__(config, ctx)
self._name = config.name
self.label = f"function({self._name})"
self.metadata = {"function": self._name}
self._callable = self._resolve()
def transform(
self,
payload: Message,
*,
source_result: Message,
from_node,
edge_link,
log_manager: LogManager,
context: ExecutionContext,
) -> Message | None:
if self._callable is None:
log_manager.warning(
f"Processor function '{self._name}' not found. Falling back to passthrough."
)
return payload
try:
result = self._callable(payload.text_content(), context.global_state)
except Exception as exc: # pragma: no cover - defensive logging
error_msg = f"Processor function '{self._name}' failed: {exc}"
log_manager.error(error_msg)
server_logger = get_server_logger()
server_logger.log_exception(exc, error_msg, processor_name=self._name)
return payload
if result is None:
return None
return self._coerce_result(payload, result)
def _resolve(self) -> Callable[[str, dict[str, Any]], Any] | None:
manager = self.ctx.function_manager if self.ctx else None
if not manager:
return None
func = manager.get_function(self._name)
if func is None:
return None
return func
def _coerce_result(self, payload: Message, result: Any) -> Message | None:
if isinstance(result, Message):
return result
cloned = payload.clone()
if isinstance(result, str):
cloned.content = result
return cloned
if isinstance(result, Mapping):
if result.get("drop"):
return None
if "content" in result:
cloned.content = result["content"]
metadata = dict(cloned.metadata)
metadata.update(result.get("metadata") or {})
cloned.metadata = metadata
return cloned
cloned.content = str(result)
return cloned
+92
View File
@@ -0,0 +1,92 @@
"""Regex-based payload processor."""
import re
from typing import List
from entity.messages import Message
from utils.log_manager import LogManager
from .base import EdgePayloadProcessor, ProcessorFactoryContext
from entity.configs.edge.edge_processor import RegexEdgeProcessorConfig
from runtime.node.executor import ExecutionContext
class RegexEdgePayloadProcessor(EdgePayloadProcessor[RegexEdgeProcessorConfig]):
def __init__(self, config: RegexEdgeProcessorConfig, ctx: ProcessorFactoryContext) -> None:
super().__init__(config, ctx)
flags = 0
if not config.case_sensitive:
flags |= re.IGNORECASE
if config.multiline:
flags |= re.MULTILINE
if config.dotall:
flags |= re.DOTALL
self._pattern = re.compile(config.pattern, flags)
self.label = f"regex({config.pattern})"
self.metadata = {
"pattern": config.pattern,
"group": config.group,
"multiple": config.multiple,
}
def transform(
self,
payload: Message,
*,
source_result: Message,
from_node,
edge_link,
log_manager: LogManager,
context: ExecutionContext,
) -> Message | None:
matches = list(self._pattern.finditer(self._text(payload)))
if not matches:
return self._handle_no_match(payload, log_manager, from_node.id, edge_link.target.id)
extracted = self._extract_values(matches)
if not extracted:
return self._handle_no_match(payload, log_manager, from_node.id, edge_link.target.id)
cloned = payload.clone()
if self.config.multiple:
cloned.content = "\n".join(extracted)
else:
cloned.content = extracted[0]
return cloned
def _extract_values(self, matches: List[re.Match]) -> List[str]:
values: List[str] = []
for match in matches:
group = self.config.group
if group is None:
value = match.group(0)
else:
value = match.group(group)
if value is None:
continue
if self.config.template:
value = self.config.template.replace("{match}", value)
values.append(value)
if not self.config.multiple:
break
return values
def _handle_no_match(
self,
payload: Message,
log_manager: LogManager,
from_node_id: str,
to_node_id: str,
) -> Message | None:
behavior = self.config.on_no_match
if behavior == "drop":
log_manager.debug(
f"Regex processor dropped payload for {from_node_id}->{to_node_id} (no match)"
)
return None
if behavior == "default":
default_value = self.config.default_value or ""
cloned = payload.clone()
cloned.content = default_value
return cloned
return payload
+81
View File
@@ -0,0 +1,81 @@
"""Registry helpers for edge payload processors."""
from dataclasses import dataclass
from importlib import import_module
from typing import Any, Dict, Type
from schema_registry import register_edge_processor_schema
from utils.registry import Registry, RegistryEntry, RegistryError
from entity.configs.edge.edge_processor import EdgeProcessorConfig, EdgeProcessorTypeConfig
from .base import EdgePayloadProcessor, ProcessorFactoryContext
@dataclass(slots=True)
class EdgeProcessorRegistration:
name: str
config_cls: Type["EdgeProcessorTypeConfig"]
processor_cls: Type["EdgePayloadProcessor[Any]"]
summary: str | None = None
edge_processor_registry = Registry("edge_processor_type")
_BUILTINS_LOADED = False
def _ensure_builtins_loaded() -> None:
global _BUILTINS_LOADED
if not _BUILTINS_LOADED:
import_module("runtime.edge.processors.builtin_types")
_BUILTINS_LOADED = True
def register_edge_processor(
name: str,
*,
config_cls: Type["EdgeProcessorTypeConfig"],
processor_cls: Type["EdgePayloadProcessor[Any]"],
summary: str | None = None,
) -> None:
if name in edge_processor_registry.names():
raise RegistryError(f"Edge processor type '{name}' already registered")
entry = EdgeProcessorRegistration(
name=name,
config_cls=config_cls,
processor_cls=processor_cls,
summary=summary,
)
edge_processor_registry.register(name, target=entry)
register_edge_processor_schema(name, config_cls=config_cls, summary=summary)
def get_edge_processor_registration(name: str) -> EdgeProcessorRegistration:
_ensure_builtins_loaded()
entry: RegistryEntry = edge_processor_registry.get(name)
registration = entry.load()
if not isinstance(registration, EdgeProcessorRegistration):
raise RegistryError(f"Entry '{name}' is not an EdgeProcessorRegistration")
return registration
def iter_edge_processor_registrations() -> Dict[str, EdgeProcessorRegistration]:
_ensure_builtins_loaded()
return {name: entry.load() for name, entry in edge_processor_registry.items()}
def build_edge_processor(
processor_config: "EdgeProcessorConfig",
context: ProcessorFactoryContext,
) -> "EdgePayloadProcessor[Any]":
registration = get_edge_processor_registration(processor_config.type)
processor_cls = registration.processor_cls
if not processor_cls:
raise RegistryError(f"Edge processor type '{processor_config.type}' does not provide an implementation")
return processor_cls(processor_config.config, context)
__all__ = [
"register_edge_processor",
"get_edge_processor_registration",
"iter_edge_processor_registrations",
"build_edge_processor",
]