Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,15 @@ It renders an abtop-style dashboard with VibeMode quota windows, warning
alerts, reset timers, remaining credits/requests, and optional local
Codex/Claude agent context from `abtop --status-json`.

API cache behavior:

- Successful live `/v1/me` responses are cached for 30 seconds by default.
- Set `cache_ttl_secs = 120` in `config.toml` to change the cache TTL.
- `--no-cache` always performs a live fetch and does not read or write the API
cache, including stale fallback.
- In monitor mode, pressing `r` clears the current account/endpoint cache entry
before forcing the next refresh.

Desktop notifications:

```bash
Expand Down
9 changes: 9 additions & 0 deletions README.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,15 @@ vimit --monitor --threshold 5h=80:95,7d=90
vimit --fail-on warning --threshold 24h=85:98
```

Поведение API cache:

- Успешные live-ответы `/v1/me` кэшируются на 30 секунд по умолчанию.
- В `config.toml` можно задать `cache_ttl_secs = 120`.
- `--no-cache` всегда делает live-запрос и не читает/не пишет API cache,
включая stale fallback.
- В monitor mode клавиша `r` очищает cache entry текущего аккаунта/endpoint и
затем запускает refresh.

Desktop-уведомления:

```bash
Expand Down
10 changes: 10 additions & 0 deletions src/cli/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ pub struct Args {
pub vpn: bool,
pub auto_failover: bool,
pub no_cache: bool,
pub cache_ttl_secs: u64,
pub trend: bool,
pub trend_days: u64,
pub update: bool,
Expand Down Expand Up @@ -95,6 +96,7 @@ where
vpn: false,
auto_failover: true,
no_cache: false,
cache_ttl_secs: super::cache::DEFAULT_TTL_SECS,
trend: false,
trend_days: 30,
update: false,
Expand Down Expand Up @@ -338,6 +340,7 @@ OPTIONS:
--api-key-env <NAME> API key environment variable [default: VIBEMODE_API_KEY]
--vpn Switch to fallback endpoint (r-api.vibemod.pro)
--no-failover Disable automatic api/r-api endpoint failover
--no-cache Always fetch live data; do not read or write API cache
-V, --version Print version
-h, --help Print help

Expand Down Expand Up @@ -384,6 +387,13 @@ mod tests {
assert!(!args.auto_failover);
}

#[test]
fn no_cache_flag_is_parsed() {
let args = parse_args(["--no-cache".to_string()]).unwrap();
assert!(args.no_cache);
assert_eq!(args.cache_ttl_secs, crate::cli::cache::DEFAULT_TTL_SECS);
}

#[test]
fn demo_and_mock_are_mutually_exclusive() {
let error = parse_args([
Expand Down
6 changes: 2 additions & 4 deletions src/cli/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::path::PathBuf;
use std::time::{Duration, Instant};

const TABLE: TableDefinition<&[u8], &[u8]> = TableDefinition::new("api_cache");
const DEFAULT_TTL_SECS: u64 = 30;
pub const DEFAULT_TTL_SECS: u64 = 30;

pub struct CacheEntry {
pub cache_key: String,
Expand Down Expand Up @@ -43,7 +43,6 @@ impl CacheStore {
}))
}

#[allow(dead_code)]
pub fn set_ttl(&mut self, secs: u64) {
self.ttl = Duration::from_secs(secs);
}
Expand All @@ -62,7 +61,7 @@ impl CacheStore {
.map(|d| d.as_secs())
.unwrap_or(0);
let age_secs = now_secs.saturating_sub(cached_at_secs);
if Duration::from_secs(age_secs) > self.ttl {
if self.ttl.is_zero() || Duration::from_secs(age_secs) > self.ttl {
return None;
}
let payload = parsed.get("payload")?.clone();
Expand Down Expand Up @@ -116,7 +115,6 @@ impl CacheStore {
tx.commit().map_err(|e| format!("cache commit failed: {e}"))
}

#[allow(dead_code)]
pub fn ttl(&self) -> Duration {
self.ttl
}
Expand Down
8 changes: 8 additions & 0 deletions src/cli/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub struct Config {
pub danger: Option<f64>,
pub threshold: Option<String>,
pub auto_failover: Option<bool>,
pub cache_ttl_secs: Option<u64>,
}

impl Config {
Expand Down Expand Up @@ -120,6 +121,9 @@ impl Config {
danger_threshold: self.danger(),
window_thresholds: self.window_thresholds()?,
auto_failover: self.auto_failover.unwrap_or(true),
cache_ttl_secs: self
.cache_ttl_secs
.unwrap_or(super::cache::DEFAULT_TTL_SECS),
})
}
}
Expand All @@ -141,6 +145,7 @@ pub struct MergedConfig {
pub danger_threshold: f64,
pub window_thresholds: HashMap<String, (f64, f64)>,
pub auto_failover: bool,
pub cache_ttl_secs: u64,
}

fn default_config_path() -> Option<PathBuf> {
Expand Down Expand Up @@ -194,6 +199,7 @@ mod tests {
preset = "compact"
notify = true
fail_on = "warning"
cache_ttl_secs = 120
"#;
let config: Config = toml::from_str(toml_str).unwrap();
assert_eq!(config.theme(), Theme::Dracula);
Expand All @@ -204,6 +210,7 @@ mod tests {
assert!(matches!(config.preset(), Preset::Compact));
assert_eq!(config.notify, Some(true));
assert_eq!(config.fail_on(), FailOn::Warning);
assert_eq!(config.cache_ttl_secs, Some(120));
}

#[test]
Expand Down Expand Up @@ -246,6 +253,7 @@ mod tests {
assert!(!merged.demo);
assert!(!merged.monitor);
assert!(merged.auto_failover);
assert_eq!(merged.cache_ttl_secs, super::super::cache::DEFAULT_TTL_SECS);
}

#[test]
Expand Down
3 changes: 3 additions & 0 deletions src/cli/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ pub fn run_init() -> Result<i32, String> {

# Poll interval in seconds (0 = single run)
# watch = 0

# API cache TTL in seconds; set to 0 to expire cached responses immediately.
# cache_ttl_secs = 30
"#;
print!(" creating config.toml... ");
io::stdout().flush().unwrap();
Expand Down
1 change: 1 addition & 0 deletions src/cli/mcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ impl VimitMcpServer {
vpn: false,
auto_failover: true,
no_cache,
cache_ttl_secs: cli::cache::DEFAULT_TTL_SECS,
trend: false,
trend_days: 30,
update: false,
Expand Down
11 changes: 8 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,11 @@ fn real_main() -> Result<i32, String> {
}

let trends = TrendStore::open()?;
let cache = CacheStore::open()?;
let mut cache = CacheStore::open()?;
if let Some(store) = cache.as_mut() {
store.set_ttl(args.cache_ttl_secs);
}
let cache_ref = if args.no_cache { None } else { cache.as_ref() };
let mut notifier = Notifier::new(args.notify);
let http = ng::HttpClient::new(ng::USER_AGENT)?;
let mut router = ng::Router::new(
Expand Down Expand Up @@ -213,7 +217,7 @@ fn real_main() -> Result<i32, String> {
&account_configs,
initial_idx,
trends.as_ref(),
cache.as_ref(),
cache_ref,
);
}

Expand All @@ -225,7 +229,7 @@ fn real_main() -> Result<i32, String> {
&mut notifier,
&http,
trends.as_ref(),
cache.as_ref(),
cache_ref,
Some(&mut router),
)?;
if args.watch == 0 {
Expand Down Expand Up @@ -320,6 +324,7 @@ fn merge_args_with_config(args: Args, merged: &MergedConfig) -> Args {
vpn: args.vpn,
auto_failover: args.auto_failover && merged.auto_failover,
no_cache: args.no_cache,
cache_ttl_secs: merged.cache_ttl_secs,
trend: args.trend,
trend_days: args.trend_days,
update: args.update,
Expand Down
Loading