Skip to main content

zeph_config/providers/
thinking.rs

1// SPDX-FileCopyrightText: 2026 Andrei G <bug-ops>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4//! Thinking, reasoning-effort, and prompt-cache config enums shared across providers.
5//!
6//! These types model provider-specific reasoning controls (Claude extended/adaptive
7//! thinking, Gemini thinking levels) and the Anthropic prompt-cache TTL. They are
8//! embedded in [`super::ProviderEntry`] and serialized into `[[llm.providers]]` entries.
9
10use serde::{Deserialize, Serialize};
11
12#[non_exhaustive]
13/// Extended or adaptive thinking mode for Claude.
14///
15/// Serializes with `mode` as tag:
16/// `{ "mode": "extended", "budget_tokens": 10000 }` or `{ "mode": "adaptive" }`.
17#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
18#[serde(tag = "mode", rename_all = "snake_case")]
19pub enum ThinkingConfig {
20    /// Extended thinking with an explicit token budget.
21    Extended {
22        /// Maximum thinking tokens to allocate.
23        budget_tokens: u32,
24    },
25    /// Adaptive thinking that selects effort automatically.
26    Adaptive {
27        /// Explicit effort hint when provided; model-chosen when `None`.
28        #[serde(default, skip_serializing_if = "Option::is_none")]
29        effort: Option<ThinkingEffort>,
30    },
31}
32
33/// Effort level for adaptive thinking.
34#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default, PartialEq, Eq)]
35#[serde(rename_all = "lowercase")]
36#[non_exhaustive]
37pub enum ThinkingEffort {
38    /// Minimal thinking; fastest responses.
39    Low,
40    /// Balanced thinking depth. This is the default.
41    #[default]
42    Medium,
43    /// Maximum thinking depth; slowest responses.
44    High,
45}
46
47#[non_exhaustive]
48/// Prompt-cache TTL variant for the Anthropic API.
49///
50/// When used as a TOML config value the accepted strings are `"ephemeral"` and `"1h"`.
51/// On the wire (Anthropic API), `OneHour` serializes as `"1h"` inside the `cache_control.ttl`
52/// field.
53#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Default)]
54#[serde(rename_all = "snake_case")]
55pub enum CacheTtl {
56    /// Default ephemeral TTL (~5 minutes). No beta header required.
57    #[default]
58    Ephemeral,
59    /// Extended 1-hour TTL. Requires the `extended-cache-ttl-2025-04-25` beta header.
60    /// Cache writes cost approximately 2× more than `Ephemeral`.
61    #[serde(rename = "1h")]
62    OneHour,
63}
64
65impl CacheTtl {
66    /// Returns `true` when this TTL variant requires the `extended-cache-ttl-2025-04-25` beta
67    /// header to be sent with each request.
68    #[must_use]
69    pub fn requires_beta(self) -> bool {
70        match self {
71            Self::OneHour => true,
72            Self::Ephemeral => false,
73        }
74    }
75}
76
77/// Thinking level for Gemini models that support extended reasoning.
78///
79/// Maps to `generationConfig.thinkingConfig.thinkingLevel` in the Gemini API.
80/// Valid for Gemini 3+ models. For Gemini 2.5, use `thinking_budget` instead.
81#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
82#[serde(rename_all = "lowercase")]
83#[non_exhaustive]
84pub enum GeminiThinkingLevel {
85    /// Minimal reasoning pass.
86    Minimal,
87    /// Low reasoning depth.
88    Low,
89    /// Medium reasoning depth.
90    Medium,
91    /// Full reasoning depth.
92    High,
93}