Add event-payload context resolver

This commit is contained in:
2026-06-18 14:01:11 +02:00
parent b84e474ac5
commit 0554014083
5 changed files with 351 additions and 4 deletions

View File

@@ -11,6 +11,7 @@ activities that need DB access.
from __future__ import annotations
import json
import uuid
from datetime import datetime, timezone
from typing import Any
@@ -65,6 +66,24 @@ def _bind_resolver_result(bind_key: str, result: Any) -> Any:
return result
def _parse_event_envelope(event_envelope_json: str | None) -> dict[str, Any] | None:
"""Parse an event envelope JSON string for context resolvers."""
if not event_envelope_json:
return None
try:
payload = json.loads(event_envelope_json)
except (TypeError, json.JSONDecodeError) as exc:
activity.logger.warning("Invalid event envelope JSON - %s", exc)
return None
if not isinstance(payload, dict):
activity.logger.warning(
"Invalid event envelope JSON - expected object, got %s",
type(payload).__name__,
)
return None
return payload
# ── Activities ─────────────────────────────────────────────────────────────────
@activity.defn
@@ -124,6 +143,7 @@ async def resolve_context(
from activity_core.context_resolvers.base import CONTEXT_RESOLVER_REGISTRY
snapshot: dict = {}
event_envelope = _parse_event_envelope(event_envelope_json)
for source in context_sources:
source_type = source.get("type", "")
query = source.get("query", "")
@@ -152,7 +172,7 @@ async def resolve_context(
continue
try:
resolved = resolver_cls().resolve(query, None, params)
resolved = resolver_cls().resolve(query, event_envelope, params)
snapshot[bind_key] = _bind_resolver_result(bind_key, resolved)
except Exception as exc:
if required:

View File

@@ -1 +1,7 @@
from activity_core.context_resolvers import kaizen, ops_inventory, repo_scoping, state_hub # noqa: F401
from activity_core.context_resolvers import ( # noqa: F401
event_payload,
kaizen,
ops_inventory,
repo_scoping,
state_hub,
)

View File

@@ -0,0 +1,51 @@
"""Event payload context adapter.
Registered as source type ``event-payload``. It exposes the triggering
EventEnvelope attributes to event-triggered ActivityDefinitions without
requiring an external context service call.
"""
from __future__ import annotations
from typing import Any
from activity_core.context_resolvers.base import CONTEXT_RESOLVER_REGISTRY, ContextResolver
class EventPayloadContextResolver(ContextResolver):
"""Resolve context from the triggering event envelope attributes."""
def resolve(self, query: str, event: Any, params: dict[str, Any]) -> Any:
attributes = _event_attributes(event)
if query in {"", "attributes"}:
return attributes
if query.startswith("attributes."):
return _resolve_path(attributes, query.removeprefix("attributes."))
return _resolve_path(attributes, query)
def _event_attributes(event: Any) -> dict[str, Any]:
if not isinstance(event, dict):
raise RuntimeError("event-payload source requires an event envelope")
attributes = event.get("attributes")
if not isinstance(attributes, dict):
raise RuntimeError("event-payload source requires envelope attributes")
return attributes
def _resolve_path(root: dict[str, Any], path: str) -> Any:
if not path:
return root
current: Any = root
for part in path.split("."):
if not part:
return {}
if not isinstance(current, dict):
return {}
current = current.get(part)
if current is None:
return {}
return current
CONTEXT_RESOLVER_REGISTRY["event-payload"] = EventPayloadContextResolver