Skip to main content

kernel/records/
identifiers.rs

1//! The vocabulary types that identify a model and its runtime.
2//!
3//! `Modality`, `Capability`, `SourceKind`, and `RuntimeId` are open string sets
4//! (new values can appear without a code change), modeled as string newtypes with
5//! constructors for the well-known values. The remaining enums are closed.
6
7macro_rules! string_id {
8    (
9        $(#[$meta:meta])*
10        $name:ident { $( $ctor:ident => $value:literal ),* $(,)? }
11    ) => {
12        $(#[$meta])*
13        #[derive(
14            Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord,
15            serde::Serialize, serde::Deserialize,
16        )]
17        #[serde(transparent)]
18        pub struct $name(String);
19
20        impl $name {
21            $(
22                #[doc = concat!("The well-known `", $value, "` value.")]
23                pub fn $ctor() -> Self {
24                    Self(String::from($value))
25                }
26            )*
27
28            /// The underlying string value.
29            pub fn as_str(&self) -> &str {
30                &self.0
31            }
32        }
33
34        impl AsRef<str> for $name {
35            fn as_ref(&self) -> &str {
36                &self.0
37            }
38        }
39
40        impl From<&str> for $name {
41            fn from(value: &str) -> Self {
42                Self(value.to_owned())
43            }
44        }
45
46        impl From<String> for $name {
47            fn from(value: String) -> Self {
48                Self(value)
49            }
50        }
51
52        impl From<$name> for String {
53            fn from(value: $name) -> Self {
54                value.0
55            }
56        }
57
58        impl std::fmt::Display for $name {
59            fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60                formatter.write_str(&self.0)
61            }
62        }
63    };
64}
65
66string_id! {
67    /// A model's primary output modality.
68    Modality {
69        unknown => "unknown",
70        text => "text",
71        image => "image",
72        speech => "speech",
73        audio => "audio",
74        video => "video",
75        vision => "vision",
76        embedding => "embedding",
77    }
78}
79
80string_id! {
81    /// Something a model can be asked to do.
82    Capability {
83        chat => "chat",
84        complete => "complete",
85        embed => "embed",
86        see => "see",
87        image => "image",
88        speak => "speak",
89        transcribe => "transcribe",
90        tools => "tools",
91    }
92}
93
94string_id! {
95    /// Where a model was found or installed from.
96    SourceKind {
97        ollama => "ollama",
98        huggingface_cache => "huggingface-cache",
99        lm_studio => "lm-studio",
100        builtin => "builtin",
101        endpoint => "endpoint",
102        file => "file",
103        folder => "folder",
104    }
105}
106
107string_id! {
108    /// The identifier of a runtime adapter that can execute a model.
109    RuntimeId {
110        llama_cpp => "llama-cpp",
111        whisper_cpp => "whisper-cpp",
112        ollama => "ollama",
113        mlx_swift => "mlx-swift",
114        apple_foundation => "apple-foundation",
115        openai_endpoint => "generic:openai-server",
116        mflux => "python:mflux",
117        diffusers => "python:diffusers",
118        mlx_lm => "python:mlx-lm",
119        mlx_audio => "python:mlx-audio",
120        mlx_vlm => "python:mlx-vlm",
121        embeddings => "python:embeddings",
122        comfy_ui => "comfyui",
123        a1111 => "a1111",
124    }
125}
126
127/// How a runtime delivers a model's output.
128#[derive(
129    Debug, Clone, Copy, PartialEq, Eq, Hash, Default, serde::Serialize, serde::Deserialize,
130)]
131#[serde(rename_all = "lowercase")]
132pub enum ExecutionMode {
133    /// Tokens stream back incrementally.
134    Stream,
135    /// A long-running job produces an artifact.
136    Job,
137    /// A single synchronous request/response.
138    #[default]
139    Sync,
140}
141
142impl ExecutionMode {
143    /// The stable string form, the same one serde writes.
144    pub fn as_str(&self) -> &'static str {
145        match self {
146            ExecutionMode::Stream => "stream",
147            ExecutionMode::Job => "job",
148            ExecutionMode::Sync => "sync",
149        }
150    }
151}
152
153/// How much support a model needs before it can run.
154#[derive(
155    Debug, Clone, Copy, PartialEq, Eq, Hash, Default, serde::Serialize, serde::Deserialize,
156)]
157#[serde(rename_all = "kebab-case")]
158pub enum RunTier {
159    /// Runs directly, no extra runtime to install.
160    Native,
161    /// Runs via a managed sidecar the app provisions.
162    Managed,
163    /// Runs on a remote endpoint.
164    Remote,
165    /// Needs a runtime recipe that is not yet available.
166    #[default]
167    RecipeNeeded,
168}
169
170/// The lifecycle state of a model record.
171#[derive(
172    Debug, Clone, Copy, PartialEq, Eq, Hash, Default, serde::Serialize, serde::Deserialize,
173)]
174#[serde(rename_all = "lowercase")]
175pub enum ModelState {
176    /// Resolved to a runtime and present on disk.
177    Ready,
178    /// Not yet resolved to a runtime.
179    #[default]
180    Unresolved,
181    /// Known but its weights are no longer on disk.
182    Missing,
183}
184
185impl ModelState {
186    /// The stable string form, the same one serde writes.
187    pub fn as_str(&self) -> &'static str {
188        match self {
189            ModelState::Ready => "ready",
190            ModelState::Unresolved => "unresolved",
191            ModelState::Missing => "missing",
192        }
193    }
194}
195
196/// The bid preference numbers runtime adapters use to compete for a model. Lower
197/// wins. This is the single global ordering; adapters must not mint their own.
198pub struct BidPreference;
199
200impl BidPreference {
201    /// llama.cpp GGUF text runtime.
202    pub const LLAMA_CPP: i64 = 10;
203    /// whisper.cpp transcription runtime.
204    pub const WHISPER_CPP: i64 = 10;
205    /// OpenAI-compatible remote endpoint.
206    pub const ENDPOINT: i64 = 10;
207    /// mlx-vlm vision-language sidecar.
208    pub const MLX_VLM: i64 = 14;
209    /// in-process MLX-Swift text runtime.
210    pub const MLX_SWIFT: i64 = 15;
211    /// Apple Foundation Models.
212    pub const APPLE_FOUNDATION: i64 = 15;
213    /// Ollama daemon.
214    pub const OLLAMA: i64 = 20;
215    /// mflux FLUX image runtime.
216    pub const MFLUX: i64 = 25;
217    /// diffusers image runtime.
218    pub const DIFFUSERS: i64 = 26;
219    /// ComfyUI daemon.
220    pub const COMFY_UI: i64 = 27;
221    /// Automatic1111 daemon.
222    pub const A1111: i64 = 28;
223    /// mlx-audio speech runtime.
224    pub const MLX_AUDIO: i64 = 30;
225    /// embeddings sidecar.
226    pub const EMBEDDINGS: i64 = 32;
227    /// mlx-lm text sidecar.
228    pub const MLX_LM: i64 = 40;
229    /// Manifest-declared runtime (lowest priority).
230    pub const MANIFEST: i64 = 100;
231}