1"""Passthrough upstream response carrier.
2
3:class:`RelayPassthroughResult` is the verbatim-bytes response carrier
4used by every passthrough wire path: JSON responses additionally expose
5their decoded object on ``payload``, while non-JSON responses ride in
6``body`` uninterpreted.
7"""
8
9from __future__ import annotations
10
11from collections.abc import AsyncIterator, Mapping
12from dataclasses import dataclass
13
14from lexigram.contracts.ai.relay import (
15 JsonValue,
16 RelayGatewayMetadata,
17 RelayGatewayResult,
18 RelayWireEvent,
19)
20
21__all__ = ["RelayPassthroughResult"]
22
23
24@dataclass(frozen=True, slots=True, init=False)
25class RelayPassthroughResult(RelayGatewayResult):
26 """One passthrough upstream response, decoded when JSON, verbatim otherwise.
27
28 Extends the gateway result carrier with the two fields the passthrough
29 wire paths need: the upstream body and its content type. JSON
30 responses keep their decoded object on ``payload`` (byte-for-byte the
31 Plan J shape) and additionally populate ``body`` with the serialized
32 bytes; non-JSON responses carry the raw bytes in ``body`` with
33 ``payload`` left ``None``. Callers read ``body`` regardless of the
34 response shape; the constructor is ``(body, content_type,
35 status_code)`` with the inherited gateway fields (headers, payload)
36 as optional keywords so existing relay route code keeps compiling.
37
38 Attributes:
39 body: The response body bytes (serialized JSON for JSON
40 responses, the upstream bytes verbatim otherwise).
41 content_type: The upstream ``content-type`` header value.
42 """
43
44 body: bytes = b""
45 content_type: str = ""
46
47 def __init__(
48 self,
49 body: bytes = b"",
50 content_type: str = "",
51 status_code: int = 200,
52 *,
53 headers: Mapping[str, str] | None = None,
54 payload: Mapping[str, JsonValue] | None = None,
55 stream: AsyncIterator[RelayWireEvent] | None = None,
56 metadata: RelayGatewayMetadata | None = None,
57 ) -> None:
58 """Bind the passthrough result fields.
59
60 Args:
61 body: The response body bytes.
62 content_type: The upstream content-type header.
63 status_code: The upstream HTTP status code.
64 headers: Response headers to relay; defaults to empty.
65 payload: Decoded JSON object for JSON responses; ``None``
66 for raw bodies.
67 stream: Never used by passthrough; always ``None``.
68 metadata: Never used by passthrough; always ``None``.
69 """
70 object.__setattr__(self, "body", body)
71 object.__setattr__(self, "content_type", content_type)
72 object.__setattr__(self, "status_code", status_code)
73 object.__setattr__(self, "headers", headers if headers is not None else {})
74 object.__setattr__(self, "payload", payload)
75 object.__setattr__(self, "stream", stream)
76 object.__setattr__(self, "metadata", metadata)