Skip to main content

entelix_core/ir/
warning.rs

1//! `ModelWarning` — non-fatal codec advisories (invariant 6).
2//!
3//! When a codec drops or coerces information that the IR carried, it must
4//! emit a `LossyEncode` here. Silent loss is an invariant violation.
5
6use serde::{Deserialize, Serialize};
7
8/// One non-fatal advisory from a codec or transport. Carried in
9/// `ModelResponse::warnings` and surfaced via observability.
10#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
11#[serde(tag = "kind", rename_all = "snake_case")]
12#[non_exhaustive]
13pub enum ModelWarning {
14    /// The codec could not preserve every IR field on the wire. The vendor
15    /// will not see (or will see a coerced version of) the named field.
16    LossyEncode {
17        /// IR field that was dropped or coerced (e.g. `messages[2].content[0]`).
18        field: String,
19        /// Why the loss happened.
20        detail: String,
21    },
22    /// The provider returned a stop reason this codec does not yet model;
23    /// the IR carries it as `StopReason::Other`.
24    UnknownStopReason {
25        /// Raw vendor reason string.
26        raw: String,
27    },
28    /// The IR requested a feature the model doesn't support (e.g. tools on a
29    /// vision-only model). The codec proceeded with a degraded request.
30    UnsupportedCapability {
31        /// Capability name (e.g. `streaming`, `prompt_caching`).
32        capability: String,
33        /// Detail of what fallback was applied.
34        detail: String,
35    },
36    /// The IR carries a [`ProviderExtensions`](crate::ir::ProviderExtensions)
37    /// entry for a vendor different from the active codec — the
38    /// codec ignored the foreign knobs because the wire format
39    /// cannot express them. Operators that route the same request
40    /// across multiple codecs see one of these warnings per inactive
41    /// vendor that had ext set.
42    ProviderExtensionIgnored {
43        /// Vendor identifier matching the inactive ext field name
44        /// (`anthropic`, `openai_chat`, `openai_responses`, `gemini`,
45        /// `bedrock`).
46        vendor: String,
47    },
48}