1use serde::{Deserialize, Serialize};
4
5pub mod defaults {
7 pub const COMPACTION_ENABLED: bool = true;
9 pub const COMPACTION_RESERVE_TOKENS: u64 = 16_384;
11 pub const COMPACTION_KEEP_RECENT_TOKENS: u64 = 20_000;
13 pub const BRANCH_SUMMARY_RESERVE_TOKENS: u64 = 16_384;
15 pub const BRANCH_SUMMARY_SKIP_PROMPT: bool = false;
17 pub const RETRY_ENABLED: bool = true;
19 pub const RETRY_MAX_RETRIES: u64 = 3;
21 pub const RETRY_BASE_DELAY_MS: u64 = 2_000;
23 pub const RETRY_MAX_AGENT_DELAY_MS: u64 = 60_000;
25 pub const RETRY_PROVIDER_MAX_RETRY_DELAY_MS: u64 = 60_000;
27 pub const HTTP_IDLE_TIMEOUT_MS: u64 = 300_000;
29 pub const SHOW_CACHE_MISS_NOTICES: bool = false;
31 pub const ENABLE_SKILL_COMMANDS: bool = true;
33 pub const IMAGES_AUTO_RESIZE: bool = true;
35 pub const IMAGES_BLOCK_IMAGES: bool = false;
37 pub const THINKING_LEVEL: oino_ai::ThinkingLevel = oino_ai::ThinkingLevel::Medium;
39 pub const SERVE_BIND: &str = "127.0.0.1:7420";
41 pub const SERVE_TLS: bool = true;
43 pub const SERVE_ALLOW_REMOTE: bool = false;
45}
46
47#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
49pub enum QueueMode {
50 #[serde(rename = "all")]
52 All,
53 #[default]
55 #[serde(rename = "one-at-a-time")]
56 OneAtATime,
57}
58
59#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
61#[serde(rename_all = "lowercase")]
62pub enum CacheWarmingMode {
63 Off,
65 #[default]
67 Streaming,
68 Idle,
70}
71
72#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
74#[serde(rename_all = "lowercase")]
75pub enum ProjectTrustDefault {
76 #[default]
78 Ask,
79 Always,
81 Never,
83}
84
85#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
87#[serde(rename_all = "lowercase")]
88pub enum UiDensity {
89 Simple,
91 #[default]
93 Regular,
94 Advanced,
96}
97
98#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
100#[serde(rename_all = "camelCase")]
101pub struct CompactionSettings {
102 pub enabled: bool,
104 pub reserve_tokens: u64,
106 pub keep_recent_tokens: u64,
108}
109
110#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
112#[serde(rename_all = "camelCase")]
113pub struct BranchSummarySettings {
114 pub reserve_tokens: u64,
116 pub skip_prompt: bool,
118}
119
120#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
122#[serde(rename_all = "camelCase")]
123pub struct RetrySettings {
124 pub enabled: bool,
126 pub max_retries: u64,
128 pub base_delay_ms: u64,
130 pub max_agent_delay_ms: u64,
132}
133
134#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
136#[serde(rename_all = "camelCase")]
137pub struct ProviderRetrySettings {
138 #[serde(default, skip_serializing_if = "Option::is_none")]
140 pub timeout_ms: Option<u64>,
141 #[serde(default, skip_serializing_if = "Option::is_none")]
143 pub max_retries: Option<u64>,
144 pub max_retry_delay_ms: u64,
146}
147
148#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
150#[serde(rename_all = "camelCase")]
151pub struct ImageSettings {
152 pub auto_resize: bool,
154 pub block_images: bool,
156}
157
158#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
160#[serde(rename_all = "camelCase")]
161pub struct ServeSettings {
162 pub bind: String,
164 pub tls: bool,
166 pub allow_remote: bool,
168}
169
170#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
172#[serde(untagged)]
173pub enum PackageSource {
174 Source(String),
176 Filtered(FilteredPackageSource),
178}
179
180impl PackageSource {
181 #[must_use]
183 pub fn source(&self) -> &str {
184 match self {
185 Self::Source(source) => source,
186 Self::Filtered(filtered) => &filtered.source,
187 }
188 }
189}
190
191#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
193pub struct FilteredPackageSource {
194 pub source: String,
196 #[serde(default, skip_serializing_if = "Option::is_none")]
198 pub autoload: Option<bool>,
199 #[serde(default, skip_serializing_if = "Option::is_none")]
201 pub extensions: Option<Vec<String>>,
202 #[serde(default, skip_serializing_if = "Option::is_none")]
204 pub skills: Option<Vec<String>>,
205 #[serde(default, skip_serializing_if = "Option::is_none")]
207 pub prompts: Option<Vec<String>>,
208 #[serde(default, skip_serializing_if = "Option::is_none")]
210 pub themes: Option<Vec<String>>,
211}
212
213#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
215#[serde(rename_all = "lowercase")]
216pub enum ResourceKind {
217 Extensions,
219 Skills,
221 Prompts,
223 Themes,
225}
226
227impl ResourceKind {
228 pub const ALL: [Self; 4] = [Self::Extensions, Self::Skills, Self::Prompts, Self::Themes];
230
231 #[must_use]
233 pub const fn key(self) -> &'static str {
234 match self {
235 Self::Extensions => "extensions",
236 Self::Skills => "skills",
237 Self::Prompts => "prompts",
238 Self::Themes => "themes",
239 }
240 }
241}
242
243pub(crate) fn parse_enum<T: serde::de::DeserializeOwned>(value: &serde_json::Value) -> Option<T> {
245 value
246 .is_string()
247 .then(|| serde_json::from_value(value.clone()).ok())
248 .flatten()
249}