Skip to main content

llmsdk_provider/
shared.rs

1//! Shared types reused by language / embedding / image models.
2//!
3//! Maps to `@ai-sdk/provider`'s `shared/v4/*`.
4// Rust guideline compliant 2026-02-21
5
6use std::collections::HashMap;
7
8use serde::{Deserialize, Serialize};
9
10use crate::json::{JsonObject, JsonValue};
11
12/// Provider-specific options, keyed by provider id.
13///
14/// Mirrors `SharedV4ProviderOptions`. Outer key is the provider name
15/// (e.g. `"openai"`), inner object is provider-defined.
16///
17/// # Examples
18///
19/// ```
20/// use llmsdk_provider::shared::ProviderOptions;
21/// use serde_json::json;
22///
23/// let mut opts = ProviderOptions::default();
24/// opts.insert(
25///     "openai".into(),
26///     json!({ "reasoningEffort": "high" }).as_object().cloned().unwrap(),
27/// );
28/// ```
29pub type ProviderOptions = HashMap<String, JsonObject>;
30
31/// Provider-specific metadata returned by a provider, keyed by provider id.
32///
33/// Mirrors `SharedV4ProviderMetadata`.
34pub type ProviderMetadata = HashMap<String, JsonObject>;
35
36/// Mapping of provider names to provider-specific file / skill identifiers.
37///
38/// Mirrors `SharedV4ProviderReference`. Lets the same logical file or skill
39/// be referenced across multiple providers without re-uploading.
40///
41/// # Examples
42///
43/// ```
44/// use llmsdk_provider::shared::ProviderReference;
45///
46/// let mut r = ProviderReference::new();
47/// r.insert("anthropic".into(), "file-abc123".into());
48/// assert_eq!(r.get("anthropic"), Some(&"file-abc123".to_owned()));
49/// ```
50pub type ProviderReference = HashMap<String, String>;
51
52/// HTTP headers attached to a request or response.
53///
54/// Mirrors `SharedV4Headers`. Value may be `None` when the caller wants the
55/// provider to drop a default header.
56pub type Headers = HashMap<String, Option<String>>;
57
58/// Provider-emitted warning about a model call.
59///
60/// Mirrors `SharedV4Warning` (ai-sdk
61/// `packages/provider/src/shared/v4/shared-v4-warning.ts`). The four
62/// variants are wire-compatible with the upstream `type` tag:
63/// `unsupported` / `compatibility` / `deprecated` / `other`.
64#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
65#[serde(tag = "type", rename_all = "kebab-case")]
66pub enum Warning {
67    /// A feature is not supported by the model — the request was sent
68    /// without it and the result may differ from the caller's intent.
69    /// Mirrors upstream `{ type: 'unsupported', feature, details? }`.
70    Unsupported {
71        /// Name of the feature / setting / tool that was unsupported.
72        /// Matches upstream `feature` field (`snake_case` wire name).
73        feature: String,
74        /// Optional human-readable details.
75        #[serde(default, skip_serializing_if = "Option::is_none")]
76        details: Option<String>,
77    },
78
79    /// A compatibility-mode feature is in use that may produce suboptimal
80    /// results (the request still went through but with a coerced or
81    /// downgraded shape). Mirrors upstream
82    /// `{ type: 'compatibility', feature, details? }`.
83    Compatibility {
84        /// Name of the feature operating in compatibility mode.
85        feature: String,
86        /// Optional human-readable details.
87        #[serde(default, skip_serializing_if = "Option::is_none")]
88        details: Option<String>,
89    },
90
91    /// A deprecated setting / feature is being used; the message explains
92    /// the recommended replacement. Mirrors upstream
93    /// `{ type: 'deprecated', setting, message }`.
94    Deprecated {
95        /// Name of the deprecated setting / feature.
96        setting: String,
97        /// Human-readable message explaining what to use instead.
98        message: String,
99    },
100
101    /// Generic warning for cases that don't fit the structured variants.
102    /// Mirrors upstream `{ type: 'other', message }`.
103    Other {
104        /// Human-readable message.
105        message: String,
106    },
107}
108
109/// File data carried in prompts or tool results.
110///
111/// Mirrors `SharedV4FileData`. A tagged union over inline bytes, URL,
112/// provider reference, or inline text.
113#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
114#[serde(tag = "type", rename_all = "kebab-case")]
115pub enum FileData {
116    /// Inline bytes (base64-encoded when serialized to JSON).
117    Data {
118        /// Raw bytes or base64 string; provider crates decide encoding on the wire.
119        data: FileBytes,
120    },
121    /// URL pointing to the file.
122    Url {
123        /// Absolute URL.
124        url: String,
125    },
126    /// Provider-specific reference, e.g. an uploaded file id.
127    Reference {
128        /// `{ providerId: id }` map.
129        reference: JsonObject,
130    },
131    /// Inline text payload.
132    Text {
133        /// Text content.
134        text: String,
135    },
136}
137
138/// Either raw bytes or a base64-encoded string.
139///
140/// Providers serialize bytes as base64 on the wire; this enum lets callers
141/// hand off whichever they have without paying a re-encode cost.
142#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
143#[serde(untagged)]
144pub enum FileBytes {
145    /// Base64-encoded string.
146    Base64(String),
147    /// Raw byte buffer.
148    Bytes(Vec<u8>),
149}
150
151/// Request metadata for telemetry / debugging.
152///
153/// Mirrors the `request` field on `*GenerateResult` / `*StreamResult`.
154#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
155pub struct RequestInfo {
156    /// HTTP body sent to the provider.
157    #[serde(default, skip_serializing_if = "Option::is_none")]
158    pub body: Option<JsonValue>,
159}
160
161/// Response metadata for telemetry / debugging.
162///
163/// Mirrors the `response` field on `*GenerateResult` / `*StreamResult`.
164#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
165pub struct ResponseInfo {
166    /// Response id reported by the provider.
167    #[serde(default, skip_serializing_if = "Option::is_none")]
168    pub id: Option<String>,
169    /// Timestamp reported by the provider (ISO-8601 string for portability).
170    #[serde(default, skip_serializing_if = "Option::is_none")]
171    pub timestamp: Option<String>,
172    /// Model id reported by the provider.
173    #[serde(default, skip_serializing_if = "Option::is_none")]
174    pub model_id: Option<String>,
175    /// Response headers.
176    #[serde(default, skip_serializing_if = "Option::is_none")]
177    pub headers: Option<Headers>,
178    /// Raw response body for debugging.
179    #[serde(default, skip_serializing_if = "Option::is_none")]
180    pub body: Option<JsonValue>,
181}