Skip to main content

kaizen/collect/tail/
mod.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2pub mod claude;
3pub mod claude_code;
4pub mod codex;
5pub mod codex_desktop;
6mod codex_desktop_event;
7pub mod copilot_cli;
8pub mod copilot_vscode;
9pub mod cursor;
10pub mod goose;
11pub mod openclaw;
12pub mod opencode;
13pub mod vibe;
14
15use std::path::Path;
16
17/// Earliest mtime (ms) of `.jsonl` files in `dir`. Returns 0 on failure.
18pub fn dir_mtime_ms(dir: &Path) -> u64 {
19    std::fs::read_dir(dir)
20        .ok()
21        .into_iter()
22        .flatten()
23        .filter_map(|e| e.ok())
24        .filter(|e| e.path().extension().map(|x| x == "jsonl").unwrap_or(false))
25        .filter_map(|e| e.metadata().ok()?.modified().ok())
26        .map(|t| {
27            t.duration_since(std::time::UNIX_EPOCH)
28                .unwrap_or_default()
29                .as_millis() as u64
30        })
31        .min()
32        .unwrap_or(0)
33}
34
35pub fn epoch_ms(t: u64) -> u64 {
36    if t < 1_000_000_000_000 {
37        t.saturating_mul(1000)
38    } else {
39        t
40    }
41}
42
43pub fn value_ts_ms(v: &serde_json::Value) -> Option<u64> {
44    v.as_u64()
45        .map(epoch_ms)
46        .or_else(|| v.as_str().and_then(rfc3339_ms))
47}
48
49fn rfc3339_ms(s: &str) -> Option<u64> {
50    let dt = time::OffsetDateTime::parse(s, &time::format_description::well_known::Rfc3339).ok()?;
51    u64::try_from(dt.unix_timestamp_nanos() / 1_000_000).ok()
52}