diff --git a/hc_agent/__init__.py b/hc_agent/__init__.py new file mode 100644 index 0000000000..af24bc8c23 --- /dev/null +++ b/hc_agent/__init__.py @@ -0,0 +1 @@ +"""hc_agent package.""" diff --git a/hc_agent/core/__init__.py b/hc_agent/core/__init__.py new file mode 100644 index 0000000000..8fa0a5e540 --- /dev/null +++ b/hc_agent/core/__init__.py @@ -0,0 +1,10 @@ +"""Core helpers for hc_agent.""" + +from hc_agent.core.contracts import RunSummary, RunnerEnvelope, StructuredError, build_structured_error + +__all__ = [ + "RunSummary", + "RunnerEnvelope", + "StructuredError", + "build_structured_error", +] diff --git a/hc_agent/core/contracts.py b/hc_agent/core/contracts.py new file mode 100644 index 0000000000..bb23910321 --- /dev/null +++ b/hc_agent/core/contracts.py @@ -0,0 +1,48 @@ +"""Shared contracts for runner payloads and summaries.""" + +from __future__ import annotations + +from typing import Any, Dict, Optional, TypedDict + + +class StructuredError(TypedDict, total=False): + """Structured error details used in runner payloads.""" + + type: str + message: str + details: Dict[str, Any] + + +def build_structured_error( + error_type: str, + message: str, + details: Optional[Dict[str, Any]] = None, +) -> StructuredError: + """Build a StructuredError dictionary with stable JSON field names.""" + + payload: StructuredError = { + "type": error_type, + "message": message, + } + if details is not None: + payload["details"] = details + return payload + + +class RunSummary(TypedDict, total=False): + """Summary payload for a completed run.""" + + status: str + started_at: str + finished_at: str + duration_ms: int + metadata: Dict[str, Any] + + +class RunnerEnvelope(TypedDict, total=False): + """Envelope payload for runner communication.""" + + run_id: str + summary: RunSummary + error: StructuredError + metadata: Dict[str, Any]