kagi_api/
config.rs

1use std::{collections::HashMap, path::PathBuf};
2
3use const_format::concatcp;
4
5use crate::{KagiError, KagiResult};
6
7/// The environment variable prefix giving way to the variables
8///
9/// - `KAGI_API_KEY`
10/// - `KAGI_API_BASE`
11/// - `KAGI_API_LOGDIR`
12pub const ENV_PREFIX: &str = "KAGI_API";
13
14pub const DEFAULT_API_BASE: &str = "https://kagi.com/api";
15
16pub const REPLAY_LOG: &str = "kagi-results.json";
17
18/// When the record/replay feature is enabled, determine if recording or replaying.
19///
20/// FIXME: Add third option to flexibly record or replay, depending on presence of query in log.
21///
22/// This would need to support in [rvcr] crate; currently replaying non-existing query panics.
23#[derive(Debug, Default, Copy, Clone)]
24pub enum RecordReplayMode {
25    #[default]
26    Record,
27    Replay,
28}
29
30impl From<RecordReplayMode> for rvcr::VCRMode {
31    fn from(value: RecordReplayMode) -> Self {
32        match value {
33            RecordReplayMode::Record => rvcr::VCRMode::Record,
34            RecordReplayMode::Replay => rvcr::VCRMode::Replay,
35        }
36    }
37}
38
39#[derive(Debug, Clone)]
40pub struct KagiConfig {
41    pub api_key: String,
42    pub api_base: String,
43    pub logdir: Option<PathBuf>,
44}
45
46impl KagiConfig {
47    pub fn with_api_key(api_key: &str) -> Self {
48        Self {
49            api_key: String::from(api_key),
50            api_base: String::from(DEFAULT_API_BASE),
51            logdir: None,
52        }
53    }
54
55    pub fn from_env() -> KagiResult<KagiConfig> {
56        let config_builder =
57            config::Config::builder().add_source(config::Environment::with_prefix(ENV_PREFIX));
58        let config = config_builder.build().map_err(KagiError::ConfigError)?;
59        let config_map = config
60            .try_deserialize::<HashMap<String, String>>()
61            .map_err(KagiError::ConfigError)?;
62
63        let Some(api_key) = config_map.get("key").map(|api_key| api_key.to_owned()) else {
64            return Err(KagiError::EnvError(concatcp!(
65                "Couldn't find the ",
66                ENV_PREFIX,
67                "_KEY",
68                " environment variable containing the Kagi API key",
69            )));
70        };
71
72        let api_base = config_map
73            .get("base")
74            .unwrap_or(&String::from(DEFAULT_API_BASE))
75            .to_owned();
76
77        let logdir = config_map.get("logdir").map(PathBuf::from);
78
79        let config = KagiConfig {
80            api_key,
81            api_base,
82            logdir,
83        };
84
85        Ok(config)
86    }
87}