Skip to main content

mermaid_cli/models/
capabilities.rs

1//! Per-model capability metadata.
2//!
3//! Adapters expose `ModelCapabilities` via `Model::capabilities()` so the
4//! rest of the codebase can ask facts like "does this model support tool
5//! calls?" or "what reasoning levels does it accept?" without per-provider
6//! string matching scattered through the codebase. This is the same
7//! pattern Roo Code uses on its `ModelInfo` struct (`supports_reasoning_*`
8//! flags) and Codex CLI uses on `ModelPreset.supported_reasoning_efforts`.
9//!
10//! For Step 1 the values are hardcoded conservative defaults. A future
11//! step can add per-model lookup (similar to https://models.dev) or
12//! runtime probing (Ollama `/api/show`).
13
14use super::reasoning::ReasoningCapability;
15
16/// Capability flags advertised by a model adapter.
17#[derive(Debug, Clone)]
18pub struct ModelCapabilities {
19    /// Model accepts tool/function-calling requests in the chat API.
20    pub supports_tools: bool,
21    /// Model accepts image inputs in messages (vision-capable).
22    pub supports_vision: bool,
23    /// Reasoning controls the model exposes — see `ReasoningCapability`.
24    pub supports_reasoning: ReasoningCapability,
25    /// Maximum context window in tokens, if known.
26    pub max_context_tokens: Option<usize>,
27}
28
29impl ModelCapabilities {
30    /// Conservative defaults for an Ollama-served model. We assume tool
31    /// calling (every modern Ollama-supported model the project targets
32    /// has it), assume no vision (the safer default — vision support is
33    /// detected via response errors at runtime in `loop_coordinator.rs`),
34    /// and treat reasoning as binary on/off (matches the `think: bool`
35    /// semantics for everything except gpt-oss).
36    pub fn ollama_default() -> Self {
37        Self {
38            supports_tools: true,
39            supports_vision: false,
40            supports_reasoning: ReasoningCapability::Binary,
41            max_context_tokens: None,
42        }
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49
50    #[test]
51    fn ollama_default_is_conservative() {
52        let caps = ModelCapabilities::ollama_default();
53        assert!(caps.supports_tools);
54        assert!(!caps.supports_vision);
55        assert_eq!(caps.supports_reasoning, ReasoningCapability::Binary);
56        assert!(caps.max_context_tokens.is_none());
57    }
58
59    #[test]
60    fn capabilities_are_cloneable() {
61        let caps = ModelCapabilities::ollama_default();
62        let cloned = caps.clone();
63        assert_eq!(cloned.supports_tools, caps.supports_tools);
64    }
65}