Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions hc_agent/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""hc_agent package."""
10 changes: 10 additions & 0 deletions hc_agent/core/__init__.py
Original file line number Diff line number Diff line change
@@ -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",
]
48 changes: 48 additions & 0 deletions hc_agent/core/contracts.py
Original file line number Diff line number Diff line change
@@ -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]