//! Non-scene protocol types: metadata, LLM lifecycle, engine catalog, config. //! //! Scene ops live in `op.rs`; push events in `events.rs`. Per-route request //! DTOs (multipart import, pipeline start) live in `koharu-rpc/src/routes/`. use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use utoipa::ToSchema; use crate::google_fonts::FontSource; // --------------------------------------------------------------------------- // Meta / fonts // --------------------------------------------------------------------------- #[derive( Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, JsonSchema, ToSchema, )] #[serde(rename_all = "camelCase")] pub struct FontFaceInfo { pub family_name: String, pub post_script_name: String, pub source: FontSource, #[serde(skip_serializing_if = "Option::is_none")] pub category: Option, pub cached: bool, } #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)] #[serde(rename_all = "camelCase")] pub struct MetaInfo { pub version: String, pub ml_device: String, } // --------------------------------------------------------------------------- // Region (generic pixel rectangle) // --------------------------------------------------------------------------- #[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, ToSchema)] #[serde(rename_all = "camelCase")] pub struct Region { pub x: u32, pub y: u32, pub width: u32, pub height: u32, } // --------------------------------------------------------------------------- // LLM lifecycle // --------------------------------------------------------------------------- #[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, ToSchema)] #[serde(rename_all = "snake_case")] pub enum LlmStateStatus { Empty, Loading, Ready, Failed, } #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)] #[serde(rename_all = "camelCase")] pub struct LlmState { pub status: LlmStateStatus, pub target: Option, pub error: Option, } #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)] #[serde(rename_all = "camelCase")] pub struct LlmGenerationOptions { pub temperature: Option, pub max_tokens: Option, pub custom_system_prompt: Option, } #[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)] #[serde(rename_all = "snake_case")] pub enum LlmTargetKind { Local, Provider, } #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct LlmTarget { pub kind: LlmTargetKind, pub model_id: String, pub provider_id: Option, } #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)] #[serde(rename_all = "camelCase")] pub struct LlmLoadRequest { pub target: LlmTarget, #[serde(default, skip_serializing_if = "Option::is_none")] pub options: Option, } #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)] #[serde(rename_all = "camelCase")] pub struct LlmCatalogModel { pub target: LlmTarget, pub name: String, pub languages: Vec, } #[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, ToSchema)] #[serde(rename_all = "snake_case")] pub enum LlmProviderCatalogStatus { Ready, MissingConfiguration, DiscoveryFailed, } #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)] #[serde(rename_all = "camelCase")] pub struct LlmProviderCatalog { pub id: String, pub name: String, pub requires_api_key: bool, pub requires_base_url: bool, pub has_api_key: bool, pub base_url: Option, pub status: LlmProviderCatalogStatus, pub error: Option, pub models: Vec, } #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)] #[serde(rename_all = "camelCase")] pub struct LlmCatalog { pub local_models: Vec, pub providers: Vec, } // --------------------------------------------------------------------------- // Pipeline request shapes // --------------------------------------------------------------------------- #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)] #[serde(rename_all = "camelCase")] pub struct PipelineLlmRequest { pub target: LlmTarget, #[serde(default, skip_serializing_if = "Option::is_none")] pub options: Option, } // --------------------------------------------------------------------------- // Engine catalog // --------------------------------------------------------------------------- #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)] #[serde(rename_all = "camelCase")] pub struct EngineCatalogEntry { pub id: String, pub name: String, pub produces: Vec, } #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)] #[serde(rename_all = "camelCase")] pub struct EngineCatalog { pub detectors: Vec, pub font_detectors: Vec, pub segmenters: Vec, pub bubble_segmenters: Vec, pub ocr: Vec, pub translators: Vec, pub inpainters: Vec, pub renderers: Vec, } // --------------------------------------------------------------------------- // Config // --------------------------------------------------------------------------- /// Sparse patch for `koharu_app::AppConfig`. Missing fields mean "leave /// as-is". The `providers` field, if present, replaces the whole provider /// list — we do not merge by id because ordering is meaningful. #[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, ToSchema)] #[serde(rename_all = "camelCase")] pub struct ConfigPatch { #[serde(default)] pub data: Option, #[serde(default)] pub http: Option, #[serde(default)] pub pipeline: Option, /// If present, replaces the entire list. Api_key values of `"[REDACTED]"` /// are interpreted as "leave the existing secret alone". #[serde(default)] pub providers: Option>, } #[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, ToSchema)] #[serde(rename_all = "camelCase")] pub struct DataConfigPatch { pub path: Option, } #[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, ToSchema)] #[serde(rename_all = "camelCase")] pub struct HttpConfigPatch { pub connect_timeout: Option, pub read_timeout: Option, pub max_retries: Option, } #[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, ToSchema)] #[serde(rename_all = "camelCase")] pub struct PipelineConfigPatch { pub detector: Option, pub font_detector: Option, pub segmenter: Option, pub bubble_segmenter: Option, pub ocr: Option, pub translator: Option, pub inpainter: Option, pub renderer: Option, } #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)] #[serde(rename_all = "camelCase")] pub struct ProviderPatch { pub id: String, pub base_url: Option, /// `"[REDACTED]"` → keep existing keyring secret; empty → clear; otherwise save. pub api_key: Option, }