Skip to main content

switchyard_protocol/
envelope.rs

1// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4//! The request/response envelope: the normalized [`LlmRequest`]/[`LlmResponse`] paired
5//! with the original provider payload and correlation [`Metadata`].
6
7use crate::{LlmRequest, LlmResponse, Metadata, ModelId};
8
9/// A request an algorithm routes: the normalized [`LlmRequest`] plus optional
10/// host-owned raw data and correlation [`Metadata`].
11#[derive(Clone, Default)]
12pub struct Request {
13    /// The normalized request an algorithm routes.
14    pub llm_request: LlmRequest,
15    /// An optional whole request body retained by the host. libsy and the translation
16    /// codecs do not read it. Exact same-format codec replay instead uses
17    /// [`LlmRequest::preservation`].
18    pub raw_request: Option<serde_json::Value>,
19    /// Correlation metadata carried through the request.
20    pub metadata: Option<Metadata>,
21}
22
23impl Request {
24    /// Returns the model currently carried by the request, when present.
25    ///
26    /// On ingress this is the name supplied by the client. Before an offloaded model call, the
27    /// routing driver replaces it with the selected target.
28    pub fn model_id(&self) -> Option<ModelId> {
29        self.llm_request.model.as_deref().map(ModelId::from)
30    }
31}
32
33/// A response an algorithm returns: the [`LlmResponse`] (streamed or aggregate) plus
34/// optional correlation [`Metadata`].
35///
36/// Not `Clone` — `llm_response` may own a live stream.
37pub struct Response {
38    /// The neutral model response — a chunk stream or the buffered aggregate.
39    pub llm_response: LlmResponse,
40    /// Correlation metadata carried through the response.
41    pub metadata: Option<Metadata>,
42}
43
44impl Response {
45    /// Returns the model recorded by a buffered response.
46    ///
47    /// Returns `None` for a live stream because inspecting its `MessageStart`
48    /// event would require consuming the stream.
49    pub fn selected_model(&self) -> Option<&str> {
50        self.llm_response.selected_model()
51    }
52}