File size: 3,458 Bytes
5e0b58b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
"""Typed data contracts for the Brain-5D embodiment layer."""

from __future__ import annotations

from dataclasses import dataclass
from enum import StrEnum

JSONScalar = str | int | float | bool | None
JSONValue = JSONScalar | list["JSONValue"] | dict[str, "JSONValue"]


class EnvironmentKind(StrEnum):
    """Supported environment categories."""

    SIMULATED = "simulated"
    PHYSICAL = "physical"
    DIGITAL = "digital"
    HYBRID = "hybrid"


@dataclass(frozen=True, slots=True)
class SensorFrame:
    """One timestamped sensor observation."""

    sensor_id: str
    tick: int
    modality: str
    payload: JSONValue


@dataclass(frozen=True, slots=True)
class ActionCommand:
    """One typed command produced for an actuator or environment."""

    actuator_id: str
    tick: int
    action: str
    payload: JSONValue = None


@dataclass(frozen=True, slots=True)
class ActuatorResult:
    """Result returned by one actuator invocation."""

    accepted: bool
    message: str = ""


@dataclass(frozen=True, slots=True)
class ActionReceipt:
    """Execution receipt separating acceptance from observed environment effect."""

    command_id: str
    accepted: bool
    started: bool
    completed: bool
    failed: bool
    latency: int | None = None
    error: str | None = None
    safety_clamp: str | None = None
    effect_observed: bool | None = None

    def to_json(self) -> dict[str, JSONValue]:
        return {
            "command_id": self.command_id,
            "accepted": self.accepted,
            "started": self.started,
            "completed": self.completed,
            "failed": self.failed,
            "latency": self.latency,
            "error": self.error,
            "safety_clamp": self.safety_clamp,
            "effect_observed": self.effect_observed,
        }


@dataclass(frozen=True, slots=True)
class EnvironmentObservation:
    """Observation returned by an environment after reset or action."""

    tick: int
    state: dict[str, JSONValue]
    reward: float = 0.0
    terminated: bool = False
    truncated: bool = False


@dataclass(frozen=True, slots=True)
class EmbodimentMetrics:
    """Read-only operating metrics for dashboard publication."""

    environment_kind: str = "unconfigured"
    active_sensors: int = 0
    active_actuators: int = 0
    episode: int = 0
    episode_reward: float = 0.0
    last_reward: float = 0.0
    last_action: str = ""
    last_text_input: str = ""
    last_observation_state: dict[str, JSONValue] | None = None
    last_observation_tick: int | None = None
    last_observation_terminated: bool | None = None
    last_observation_truncated: bool | None = None

    def to_json(self) -> dict[str, JSONValue]:
        """Return a JSON-ready representation."""

        return {
            "environment_kind": self.environment_kind,
            "active_sensors": self.active_sensors,
            "active_actuators": self.active_actuators,
            "episode": self.episode,
            "episode_reward": self.episode_reward,
            "last_reward": self.last_reward,
            "last_action": self.last_action,
            "last_text_input": self.last_text_input,
            "last_observation_state": self.last_observation_state,
            "last_observation_tick": self.last_observation_tick,
            "last_observation_terminated": self.last_observation_terminated,
            "last_observation_truncated": self.last_observation_truncated,
        }