Skip to main content

yapi_types/
models.rs

1//! `models.json`: custom providers, models and overrides.
2//!
3//! Mirrors the TypeBox schema in `packages/coding-agent/src/core/model-config.ts` in
4//! pi `v1.0.0`. pi reads this file but never writes it. Provider `compat` options
5//! stay raw JSON until the wire APIs that use them exist.
6#![allow(
7    missing_docs,
8    reason = "fields mirror pi's TypeScript types; contracts are noted where they differ from the name"
9)]
10
11use indexmap::IndexMap;
12use serde::{Deserialize, Serialize};
13use serde_json::{Map, Value};
14
15#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
16pub struct ModelsConfig {
17    pub providers: IndexMap<String, ProviderConfig>,
18}
19
20/// A new provider, or overrides for a built-in one. `apiKey` and header values use
21/// the same `$VAR` and `!command` forms as `auth.json`.
22#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
23#[serde(rename_all = "camelCase")]
24pub struct ProviderConfig {
25    #[serde(default, skip_serializing_if = "Option::is_none")]
26    pub name: Option<String>,
27    #[serde(default, skip_serializing_if = "Option::is_none")]
28    pub base_url: Option<String>,
29    #[serde(default, skip_serializing_if = "Option::is_none")]
30    pub api_key: Option<String>,
31    #[serde(default, skip_serializing_if = "Option::is_none")]
32    pub api: Option<String>,
33    /// Only `"radius"`.
34    #[serde(default, skip_serializing_if = "Option::is_none")]
35    pub oauth: Option<String>,
36    #[serde(default, skip_serializing_if = "Option::is_none")]
37    pub headers: Option<IndexMap<String, String>>,
38    #[serde(default, skip_serializing_if = "Option::is_none")]
39    pub compat: Option<Map<String, Value>>,
40    #[serde(default, skip_serializing_if = "Option::is_none")]
41    pub auth_header: Option<bool>,
42    #[serde(default, skip_serializing_if = "Option::is_none")]
43    pub models: Option<Vec<ModelDefinition>>,
44    #[serde(default, skip_serializing_if = "Option::is_none")]
45    pub model_overrides: Option<IndexMap<String, ModelOverride>>,
46}
47
48#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
49#[serde(rename_all = "camelCase")]
50pub struct ModelDefinition {
51    pub id: String,
52    #[serde(default, skip_serializing_if = "Option::is_none")]
53    pub name: Option<String>,
54    #[serde(default, skip_serializing_if = "Option::is_none")]
55    pub api: Option<String>,
56    #[serde(default, skip_serializing_if = "Option::is_none")]
57    pub base_url: Option<String>,
58    #[serde(flatten)]
59    pub options: ModelOptions,
60}
61
62/// Fields shared by model definitions and overrides.
63#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
64#[serde(rename_all = "camelCase")]
65pub struct ModelOptions {
66    #[serde(default, skip_serializing_if = "Option::is_none")]
67    pub reasoning: Option<bool>,
68    /// pi thinking level to provider value; `None` marks the level unsupported.
69    #[serde(default, skip_serializing_if = "Option::is_none")]
70    pub thinking_level_map: Option<IndexMap<String, Option<String>>>,
71    #[serde(default, skip_serializing_if = "Option::is_none")]
72    pub input: Option<Vec<InputKind>>,
73    #[serde(default, skip_serializing_if = "Option::is_none")]
74    pub input_limits: Option<InputLimits>,
75    #[serde(default, skip_serializing_if = "Option::is_none")]
76    pub prompt_cache: Option<PromptCache>,
77    #[serde(default, skip_serializing_if = "Option::is_none")]
78    pub context_window: Option<u64>,
79    #[serde(default, skip_serializing_if = "Option::is_none")]
80    pub max_tokens: Option<u64>,
81    #[serde(default, skip_serializing_if = "Option::is_none")]
82    pub sampling_params: Option<Map<String, Value>>,
83    #[serde(default, skip_serializing_if = "Option::is_none")]
84    pub headers: Option<IndexMap<String, String>>,
85    #[serde(default, skip_serializing_if = "Option::is_none")]
86    pub compat: Option<Map<String, Value>>,
87    /// Required rates in a definition; any subset in an override.
88    #[serde(default, skip_serializing_if = "Option::is_none")]
89    pub cost: Option<ModelCost>,
90}
91
92/// Changes to a built-in model; every field is optional.
93#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
94pub struct ModelOverride {
95    #[serde(default, skip_serializing_if = "Option::is_none")]
96    pub name: Option<String>,
97    #[serde(flatten)]
98    pub options: ModelOptions,
99}
100
101#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
102#[serde(rename_all = "lowercase")]
103pub enum InputKind {
104    Text,
105    Image,
106}
107
108#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
109#[serde(rename_all = "camelCase")]
110pub struct InputLimits {
111    #[serde(default, skip_serializing_if = "Option::is_none")]
112    pub max_request_bytes: Option<u64>,
113    #[serde(default, skip_serializing_if = "Option::is_none")]
114    pub images: Option<ImageLimits>,
115}
116
117#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
118#[serde(rename_all = "camelCase")]
119pub struct ImageLimits {
120    #[serde(default, skip_serializing_if = "Option::is_none")]
121    pub resize: Option<ImageResize>,
122    #[serde(default, skip_serializing_if = "Option::is_none")]
123    pub max_per_message: Option<u32>,
124    #[serde(default, skip_serializing_if = "Option::is_none")]
125    pub max_per_request: Option<u32>,
126}
127
128#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
129#[serde(rename_all = "camelCase")]
130pub struct ImageResize {
131    #[serde(default, skip_serializing_if = "Option::is_none")]
132    pub max_width: Option<u32>,
133    #[serde(default, skip_serializing_if = "Option::is_none")]
134    pub max_height: Option<u32>,
135    #[serde(default, skip_serializing_if = "Option::is_none")]
136    pub max_bytes: Option<u64>,
137    /// 1 to 100.
138    #[serde(default, skip_serializing_if = "Option::is_none")]
139    pub jpeg_quality: Option<u8>,
140}
141
142/// Prompt cache retention, in seconds.
143#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
144pub struct PromptCache {
145    #[serde(default, skip_serializing_if = "Option::is_none")]
146    pub short: Option<f64>,
147    #[serde(default, skip_serializing_if = "Option::is_none")]
148    pub long: Option<f64>,
149}
150
151/// US dollars per million tokens.
152#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
153#[serde(rename_all = "camelCase")]
154pub struct ModelCost {
155    #[serde(default, skip_serializing_if = "Option::is_none")]
156    pub input: Option<f64>,
157    #[serde(default, skip_serializing_if = "Option::is_none")]
158    pub output: Option<f64>,
159    #[serde(default, skip_serializing_if = "Option::is_none")]
160    pub cache_read: Option<f64>,
161    #[serde(default, skip_serializing_if = "Option::is_none")]
162    pub cache_write: Option<f64>,
163    /// Higher rates above an input size.
164    #[serde(default, skip_serializing_if = "Option::is_none")]
165    pub tiers: Option<Vec<CostTier>>,
166}
167
168#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
169#[serde(rename_all = "camelCase")]
170pub struct CostTier {
171    pub input_tokens_above: u64,
172    pub input: f64,
173    pub output: f64,
174    pub cache_read: f64,
175    pub cache_write: f64,
176}