# Response

> The sequence of channel responses the server sends, what ends it, and what a finish with nothing before it means.

Canonical: https://provider.diverge.network/2.3.0/endpoints/containers-agents-run/client/run-loop/response/
Specification revision: 2.3.0

```text
[0][chunk JSON …]     zero or more, the loop
[1][error JSON …]     last, when there was no loop or it did not finish
```

- **The sequence.** Zero or more channel responses whose first byte
  is `0`, each one chunk as the proxy sent it, in order. An error,
  when the server sends one, is the last channel response: as the
  first channel response it states that no loop ran; after chunks it
  states that the loop ended without finishing. The channel response
  finish follows the last channel response. A channel response
  finish that no channel response precedes states that the proxy did
  not serve the loop.
- **The chunk.** After the byte `0`, the chunk as JSON, in the form
  the proxy's [`/agent/run`](/2.3.0/proxy/agent/run/) page defines. The
  server does not read it.
- **The error.** After the byte `1`, exactly one JSON value in the form defined on the [volumes::list response](/2.3.0/endpoints/volumes-list/response/) page.

The channel response is defined by `diverge-provider-sdk/src/shared/containers/run_loop/response/frame.rs`:

```rust
//! What an agentic loop channel carries back.

use std::fmt;

use super::AgenticLoopChunk;
use crate::decode::Decode;
use crate::encode::{Encode, Writer};
use crate::shared::error::Error;

/// A piece of the loop, or the news that there will not be one.
///
/// A payload leads with one byte saying which — `0` for
/// [`Chunk`](Self::Chunk), `1` for [`Error`](Self::Error) — and the
/// rest is that variant's own JSON.
///
/// # The tag is not decoration
///
/// [`AgenticLoopChunk`] is untagged and tells its own variants apart
/// by a `type` constant inside each one, while an [`Error`] is an
/// arbitrary JSON value — including, legitimately, an object with a
/// `type` field. Leaving the two to be distinguished by their JSON
/// would mean a provider's error text could be read as a chunk, and
/// the failure would look like output.
///
/// # This is not [`NotificationChunk`](super::NotificationChunk)
///
/// They are both failures and they are not the same failure. A
/// [`NotificationChunk`](super::NotificationChunk) with
/// [`is_fatal`](super::NotificationChunk::is_fatal) set is part of the
/// loop's OUTPUT: it arrives as a [`Chunk`](Self::Chunk) like any
/// other, and exists because a loop can fail after producing output —
/// ending the stream silently would leave a caller unable to tell a
/// partial result from a complete one. An [`Error`](Self::Error) is
/// not part of the loop. It is what a provider sends when there is no
/// loop to report on — the agent the image would not take, the
/// container gone — and it carries a bare JSON value because this
/// specification does not describe what providers can go wrong with.
#[derive(Debug, Clone, PartialEq)]
pub enum Frame {
    /// One chunk of the loop. Tag `0`.
    Chunk(AgenticLoopChunk),
    /// A failure. Tag `1`.
    ///
    /// See [`shared::error::Error`](crate::shared::error::Error) for
    /// why it says so little.
    Error(Error),
}

/// Tag for [`Frame::Chunk`]. Public, so a relay that carries a
/// chunk's JSON without reading it can frame it.
pub const CHUNK: u8 = 0;

/// Tag for [`Frame::Error`].
const ERROR: u8 = 1;

impl Encode for Frame {
    /// The ordinary JSON failure, from either half.
    type Error = serde_json::Error;

    // Spelled out rather than `Self::Error`: this enum has a variant
    // called `Error`, so the associated type is ambiguous by that name.
    fn encode(&self, out: &mut Writer<'_>) -> Result<(), serde_json::Error> {
        match self {
            Frame::Chunk(chunk) => {
                out.extend_from_slice(&[CHUNK]);
                serde_json::to_writer(out, chunk)
            }
            Frame::Error(error) => {
                out.extend_from_slice(&[ERROR]);
                error.encode(out)
            }
        }
    }
}

impl Decode<'_> for Frame {
    /// Four ways to fail, and each names which half failed.
    type Error = FrameError;

    // Spelled out for the same reason as `encode` above.
    fn decode(bytes: &[u8]) -> Result<Self, FrameError> {
        let (tag, rest) = bytes.split_first().ok_or(FrameError::Empty)?;
        match *tag {
            CHUNK => serde_json::from_slice(rest)
                .map(Frame::Chunk)
                .map_err(FrameError::Chunk),
            ERROR => {
                Error::decode(rest).map(Frame::Error).map_err(FrameError::Error)
            }
            tag => Err(FrameError::UnknownTag(tag)),
        }
    }
}

/// An agentic loop frame that could not be read.
#[derive(Debug)]
pub enum FrameError {
    /// No bytes at all, so not even a tag.
    Empty,
    /// A tag that is neither of this frame's two.
    UnknownTag(u8),
    /// The chunk did not parse.
    Chunk(serde_json::Error),
    /// The error did not parse.
    ///
    /// Which is its own small joke and its own real problem: a
    /// provider whose failure report is malformed has told a caller
    /// that something went wrong and nothing else.
    Error(serde_json::Error),
}

impl fmt::Display for FrameError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            FrameError::Empty => {
                f.write_str("agentic loop frame is empty")
            }
            FrameError::UnknownTag(tag) => {
                write!(f, "unknown agentic loop frame tag {tag}")
            }
            FrameError::Chunk(error) => {
                write!(f, "agentic loop chunk did not parse: {error}")
            }
            FrameError::Error(error) => {
                write!(f, "agentic loop error did not parse: {error}")
            }
        }
    }
}

impl std::error::Error for FrameError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            FrameError::Chunk(error) | FrameError::Error(error) => Some(error),
            FrameError::Empty | FrameError::UnknownTag(_) => None,
        }
    }
}
```
