use serde::{Deserialize, Serialize};
pub mod defaults {
pub const COMPACTION_ENABLED: bool = true;
pub const COMPACTION_RESERVE_TOKENS: u64 = 16_384;
pub const COMPACTION_KEEP_RECENT_TOKENS: u64 = 20_000;
pub const BRANCH_SUMMARY_RESERVE_TOKENS: u64 = 16_384;
pub const BRANCH_SUMMARY_SKIP_PROMPT: bool = false;
pub const RETRY_ENABLED: bool = true;
pub const RETRY_MAX_RETRIES: u64 = 3;
pub const RETRY_BASE_DELAY_MS: u64 = 2_000;
pub const RETRY_MAX_AGENT_DELAY_MS: u64 = 60_000;
pub const RETRY_PROVIDER_MAX_RETRY_DELAY_MS: u64 = 60_000;
pub const HTTP_IDLE_TIMEOUT_MS: u64 = 300_000;
pub const SHOW_CACHE_MISS_NOTICES: bool = false;
pub const ENABLE_SKILL_COMMANDS: bool = true;
pub const IMAGES_AUTO_RESIZE: bool = true;
pub const IMAGES_BLOCK_IMAGES: bool = false;
pub const THINKING_LEVEL: oino_ai::ThinkingLevel = oino_ai::ThinkingLevel::Medium;
pub const SERVE_BIND: &str = "127.0.0.1:7420";
pub const SERVE_TLS: bool = true;
pub const SERVE_ALLOW_REMOTE: bool = false;
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum QueueMode {
#[serde(rename = "all")]
All,
#[default]
#[serde(rename = "one-at-a-time")]
OneAtATime,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum CacheWarmingMode {
Off,
#[default]
Streaming,
Idle,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ProjectTrustDefault {
#[default]
Ask,
Always,
Never,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum UiDensity {
Simple,
#[default]
Regular,
Advanced,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CompactionSettings {
pub enabled: bool,
pub reserve_tokens: u64,
pub keep_recent_tokens: u64,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BranchSummarySettings {
pub reserve_tokens: u64,
pub skip_prompt: bool,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RetrySettings {
pub enabled: bool,
pub max_retries: u64,
pub base_delay_ms: u64,
pub max_agent_delay_ms: u64,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ProviderRetrySettings {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub timeout_ms: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub max_retries: Option<u64>,
pub max_retry_delay_ms: u64,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ImageSettings {
pub auto_resize: bool,
pub block_images: bool,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ServeSettings {
pub bind: String,
pub tls: bool,
pub allow_remote: bool,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum PackageSource {
Source(String),
Filtered(FilteredPackageSource),
}
impl PackageSource {
#[must_use]
pub fn source(&self) -> &str {
match self {
Self::Source(source) => source,
Self::Filtered(filtered) => &filtered.source,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct FilteredPackageSource {
pub source: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub autoload: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub skills: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub prompts: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub themes: Option<Vec<String>>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ResourceKind {
Extensions,
Skills,
Prompts,
Themes,
}
impl ResourceKind {
pub const ALL: [Self; 4] = [Self::Extensions, Self::Skills, Self::Prompts, Self::Themes];
#[must_use]
pub const fn key(self) -> &'static str {
match self {
Self::Extensions => "extensions",
Self::Skills => "skills",
Self::Prompts => "prompts",
Self::Themes => "themes",
}
}
}
pub(crate) fn parse_enum<T: serde::de::DeserializeOwned>(value: &serde_json::Value) -> Option<T> {
value
.is_string()
.then(|| serde_json::from_value(value.clone()).ok())
.flatten()
}