Skip to main content

VendorFrames

Struct VendorFrames 

Source
pub struct VendorFrames { /* private fields */ }
Expand description

Surfaces vendor frames: stream frames of a type an adapter does not model.

Endpoints and proxies add frames to standard streams: a named SSE event (event: search_results), an NDJSON line of a type the API does not define. An adapter never decodes them as its own and never drops them: surface turns each one into events, as it arrives, and finish completes them when the response ends.

§Events

  • The first frame of a type is preceded by one Warning (WarningKind::Other, Subject::Response, with the provider name).
  • Each frame yields a ResponseProviderData event under the adapter’s namespace and the frame type, holding that frame’s payload alone, as a one-element array: a live consumer sees each payload once, as it arrives, in constant work per frame.
  • finish, called by the decoder just before its ResponseStop, yields one more ResponseProviderData event holding the whole array, in arrival order, of every type that arrived more than once. ProviderData::merge replaces a value by key, so a collector that merges the events ends with every payload of every type: the collected response’s provider data holds the full arrays.

Before 2026-10-07 each event carried the whole array so far, which made a stream with a vendor frame per chunk quadratic in time and in what a recording holds. An adapter that forgets finish keeps only the last payload of a repeated type in its collected response.

A vendor frame never starts the response. Yield the returned events as they come, also before ResponseStart: Prepared::finish_stream holds them until the start (start_first). allama_conformance::stream_frames::assert_unknown_stream_frames_surfaced checks the result.

use allama::{StreamEvent, WarningKind};
use allama_http::framing::VendorFrames;

let mut frames = VendorFrames::new("demo", "openai-compat:demo");
let first = frames.surface("search_results", r#"{"url":"https://a"}"#);
assert!(matches!(
    &first[0],
    StreamEvent::Warning { warning, .. } if warning.kind == WarningKind::Other
));
let second = frames.surface("search_results", "not json");
let StreamEvent::ResponseProviderData { provider_data, .. } = &second[0] else {
    panic!("{second:?}")
};
assert_eq!(
    provider_data.get_raw("openai-compat:demo", "search_results"),
    Some(&serde_json::json!(["not json"])),
);

// Before `ResponseStop`: the whole array of each repeated type.
let Some(StreamEvent::ResponseProviderData { provider_data, .. }) = frames.finish() else {
    panic!()
};
assert_eq!(
    provider_data.get_raw("openai-compat:demo", "search_results"),
    Some(&serde_json::json!([{"url": "https://a"}, "not json"])),
);

Implementations§

Source§

impl VendorFrames

Source

pub fn new( provider: impl Into<Cow<'static, str>>, namespace: impl Into<Cow<'static, str>>, ) -> Self

Vendor frames of a provider (for the warnings), surfaced under its namespace.

Source

pub fn surface(&mut self, event: &str, data: &str) -> Vec<StreamEvent>

Surface the raw data of a frame of type event: kept as JSON when it parses, as the trimmed text otherwise. Empty data surfaces nothing.

Source

pub fn surface_payload( &mut self, event: &str, payload: Value, ) -> Vec<StreamEvent>

Surface a payload already decoded, for a frame whose type arrives inside its data (an NDJSON line’s type, an SSE event’s JSON type) rather than as an SSE event name.

Source

pub fn finish(&mut self) -> Option<StreamEvent>

The event that completes the surfaced frames, for the decoder to yield just before its ResponseStop: one ResponseProviderData holding the whole array of every type that arrived more than once, which replaces the single payloads a collector merged. None when no type repeated (the events already carry every payload). The frames are taken: a second call yields nothing.

Trait Implementations§

Source§

impl Clone for VendorFrames

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for VendorFrames

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more