diff --git a/docs/docs/exosphere/Index b/docs/docs/exosphere/Index new file mode 100644 index 00000000..31121c4c --- /dev/null +++ b/docs/docs/exosphere/Index @@ -0,0 +1,67 @@ +# Exosphere Example: DataProcessorNode + +```python +import json +import logging +from enum import Enum +from pydantic import BaseModel +from exospherehost import BaseNode + +logger = logging.getLogger(__name__) + +class Operation(str, Enum): + """Supported operations the node can perform.""" + TRANSFORM = "transform" + PASSTHROUGH = "passthrough" + +class DataProcessorNode(BaseNode): + """Parse JSON input and apply a simple operation, returning a JSON string result.""" + + class Inputs(BaseModel): + """Inputs for DataProcessorNode. + + data: JSON-encoded string payload to process. + operation: one of Operation (validated). + """ + data: str + operation: Operation + + class Outputs(BaseModel): + """Outputs emitted by DataProcessorNode. + + result: JSON-encoded string payload after processing. + status: 'success' or an error message. + """ + result: str + status: str + + async def execute(self) -> Outputs: + """Execute the node: parse input JSON and perform the requested operation.""" + # Parse the input data + try: + data = json.loads(self.inputs.data) + except json.JSONDecodeError as e: + # Log for observability and return specific, helpful feedback + logger.warning("Invalid JSON in DataProcessorNode.inputs.data", exc_info=True) + return self.Outputs( + result="", + status=f"error: invalid json (line {getattr(e, 'lineno', '?')}, column {getattr(e, 'colno', '?')})" + ) + + # Process based on validated operation + if self.inputs.operation is Operation.TRANSFORM: + result_obj = {"transformed": data, "processed": True} + else: # Operation.PASSTHROUGH + result_obj = {"original": data, "processed": False} + + # Outputs.result is defined as a string; return JSON-encoded result for consistency + try: + result_json = json.dumps(result_obj) + except (TypeError, ValueError) as e: + logger.warning("Failed to serialize result", exc_info=True) + return self.Outputs( + result="", + status=f"error: serialization failed - {e}" + ) + + return self.Outputs(result=result_json, status="success")