Skip to main content

lean_ctx/tools/
ctx_smart_read.rs

1use crate::core::auto_mode_resolver::{self, AutoModeContext};
2use crate::core::cache::SessionCache;
3use crate::core::tokens::count_tokens;
4use crate::tools::CrpMode;
5
6pub fn select_mode(cache: &SessionCache, path: &str) -> String {
7    select_mode_with_task(cache, path, None)
8}
9
10/// Delegates to the unified `auto_mode_resolver::resolve()`.
11pub fn select_mode_with_task(cache: &SessionCache, path: &str, task: Option<&str>) -> String {
12    if let Ok(meta) = std::fs::metadata(path) {
13        let cap = crate::core::limits::max_read_bytes() as u64;
14        if meta.len() > cap {
15            return "full".to_string();
16        }
17    }
18
19    // Avoid a redundant disk read: ctx_read::handle re-reads the file anyway.
20    // For files already in the session cache (the common agent-loop case of
21    // re-reading a file), reuse the stored token count instead of reading from
22    // disk a second time just to pick a mode.
23    let token_count = cache
24        .get(path)
25        .filter(|e| !crate::core::cache::is_cache_entry_stale(path, e.stored_mtime))
26        .map(|e| e.original_tokens)
27        .filter(|t| *t > 0)
28        .unwrap_or_else(|| std::fs::read_to_string(path).map_or(0, |c| count_tokens(&c)));
29
30    let ctx = AutoModeContext {
31        path,
32        token_count,
33        line_count: None,
34        task,
35        cache: Some(cache),
36    };
37    auto_mode_resolver::resolve(&ctx).mode
38}
39
40pub fn handle(cache: &mut SessionCache, path: &str, crp_mode: CrpMode) -> String {
41    crate::tools::ctx_read::handle(cache, path, "auto", crp_mode)
42}
43
44pub fn is_code_ext(ext: &str) -> bool {
45    matches!(
46        ext,
47        "rs" | "ts"
48            | "tsx"
49            | "js"
50            | "jsx"
51            | "py"
52            | "go"
53            | "java"
54            | "c"
55            | "cpp"
56            | "cc"
57            | "h"
58            | "hpp"
59            | "rb"
60            | "cs"
61            | "kt"
62            | "swift"
63            | "php"
64            | "zig"
65            | "ex"
66            | "exs"
67            | "scala"
68            | "sc"
69            | "dart"
70            | "sh"
71            | "bash"
72            | "svelte"
73            | "vue"
74    )
75}
76
77#[cfg(test)]
78mod tests {
79    use super::*;
80
81    #[test]
82    fn test_code_detection() {
83        assert!(is_code_ext("rs"));
84        assert!(is_code_ext("py"));
85        assert!(is_code_ext("tsx"));
86        assert!(!is_code_ext("json"));
87    }
88}