Major refactor of the message pump architecture: - Replace bus.py with stream_pump.py using aiostream for composable stream processing with natural fan-out via flatmap - Add to_id field to MessageState for explicit routing - Fix routing to use to_id.class format (e.g., "greeter.greeting") - Generate XSD schemas from xmlified payload classes - Fix xmlable imports (absolute -> relative) and parse_element ctx New features: - handlers/hello.py: Sample Greeting/GreetingResponse handler - config/organism.yaml: Sample organism configuration - 41 tests (31 unit + 10 integration) all passing Schema changes: - envelope.xsd: Allow any namespace payloads (##other -> ##any) Dependencies added to pyproject.toml: - aiostream>=0.5 (core dependency) - pyhumps, termcolor (for xmlable) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
48 lines
No EOL
1.6 KiB
Python
48 lines
No EOL
1.6 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
from typing import Any, TYPE_CHECKING
|
|
|
|
if TYPE_CHECKING:
|
|
from lxml.etree import _Element as Element
|
|
else:
|
|
Element = Any # Runtime: don't need the actual type
|
|
|
|
"""
|
|
default_listener_steps = [
|
|
repair_step, # raw bytes → repaired bytes
|
|
c14n_step, # bytes → lxml Element
|
|
envelope_validation_step, # Element → validated Element
|
|
payload_extraction_step, # Element → payload Element
|
|
xsd_validation_step, # payload Element + cached XSD → validated
|
|
deserialization_step, # payload Element → dataclass instance
|
|
routing_resolution_step, # attaches target_listeners (or error)
|
|
]
|
|
"""
|
|
|
|
@dataclass
|
|
class HandlerMetadata:
|
|
"""Trustworthy context passed to every handler."""
|
|
thread_id: str
|
|
from_id: str
|
|
own_name: str | None = None # Only for agent: true listeners
|
|
is_self_call: bool = False # Convenience flag
|
|
|
|
|
|
@dataclass
|
|
class MessageState:
|
|
"""Universal intermediate representation flowing through all pipelines."""
|
|
raw_bytes: bytes | None = None
|
|
envelope_tree: Element | None = None
|
|
payload_tree: Element | None = None
|
|
payload: Any | None = None # Deserialized @xmlify instance
|
|
|
|
thread_id: str | None = None
|
|
from_id: str | None = None
|
|
to_id: str | None = None # Target listener name for routing
|
|
|
|
target_listeners: list['Listener'] | None = None # Forward reference
|
|
|
|
error: str | None = None
|
|
|
|
metadata: dict[str, Any] = field(default_factory=dict) # Extension point |