1use std::{collections::HashMap, path::PathBuf};
2
3use const_format::concatcp;
4
5use crate::{KagiError, KagiResult};
6
7pub 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#[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}