Skip to main content

code_kb_core/
lib.rs

1pub mod db;
2pub mod edit;
3pub mod formatters;
4pub mod models;
5pub mod ops;
6pub mod queries;
7pub mod slicer;
8pub mod sync;
9pub mod syntax;
10pub mod telemetry;
11pub mod watcher;
12pub mod workspace;
13
14pub use db::{
15    Connection, DbError, ensure_fts_index, ensure_fts_index_path, open_read_only, open_read_write,
16};
17pub use edit::{
18    EditError, EditResult, MatchTier, Occurrence, TextEditResult, edit_file, replace_symbol_body,
19};
20pub use formatters::{
21    format_blast_radius, format_context_slice, format_edit_file_result, format_fact_categories,
22    format_file_skeleton, format_find_symbol_results, format_references,
23    format_replace_symbol_result, format_search_results, format_structural_facts,
24    format_symbol_body,
25};
26pub use models::{
27    BlastRadiusResult, ContextSlice, FileFact, ImpactedSymbol, LiteralFact, ReferenceSite,
28    SearchExplain, StructuralFact, Symbol, SymbolSearchResult, TestTarget, TypeFact,
29};
30pub use ops::{
31    OpError, blast_radius_op, codebase_outline_op, file_skeleton_op, get_context_slice_op,
32    get_symbol_body_op,
33};
34pub use queries::{
35    QueryError, compute_blast_radius, compute_blast_radius_scoped, count_file_symbols,
36    file_sizes_for_paths, find_callee_signatures, find_literals, find_literals_scoped,
37    find_references, find_references_ext, find_references_for_symbol, find_references_scoped,
38    find_related_tests, find_structural_facts, find_structural_facts_scoped, find_type_facts,
39    fts_search_symbols_explained, fts_search_symbols_scoped, get_file, get_symbol_by_name,
40    get_symbol_by_name_exact, is_category_alias, is_test_path, list_structural_fact_categories,
41    list_structural_fact_categories_scoped, load_file_symbols, load_scoped_outline_symbols,
42    normalize_kind, sanitize_fts5_query, search_symbols, search_symbols_scoped, suggest_file_paths,
43    suggest_symbol_names, workspace_name,
44};
45pub use slicer::{SliceError, slice_symbol, slice_symbol_body};
46pub use sync::{
47    PINNED_JULIE_VERSION, ReconcileReport, SyncError, create_index, delete_file, ensure_fresh_file,
48    ensure_index_matches_extractor, find_julie_extract_binary, installed_extractor_version,
49    reconcile_offline_edits, scan_workspace, update_file,
50};
51pub use syntax::{SyntaxError, validate_syntax};
52pub use telemetry::{
53    BugReportBundle, IndexFacts, TelemetryErrorRecord, TelemetryFilter, TelemetrySummary,
54    TimeWindow, ToolInvocation, ToolStat, format_telemetry_summary, generate_bug_report,
55    get_global_telemetry_dir, get_telemetry_summary, open_global_telemetry_db, open_telemetry_db,
56    record_tool_call, record_tool_call_conn,
57};
58pub use watcher::{WatcherError, WatcherHandle, start_watcher};
59pub use workspace::{
60    Workspace, WorkspaceError, is_hard_excluded, is_project_root, normalize_path, parse_file_uri,
61    strip_prefix_lossy, to_forward_slash,
62};
63
64/// Creates a temporary directory in a safe location, prioritizing `CARGO_TARGET_TMPDIR`,
65/// `TMPDIR`, and workspace `./target/tmp` over `/tmp` to avoid tmpfs quota limits.
66pub fn safe_tempdir() -> tempfile::TempDir {
67    if let Ok(target_tmp) = std::env::var("CARGO_TARGET_TMPDIR") {
68        let path = std::path::PathBuf::from(&target_tmp);
69        if (path.exists() || std::fs::create_dir_all(&path).is_ok())
70            && let Ok(dir) = tempfile::TempDir::new_in(&path)
71        {
72            return dir;
73        }
74    }
75    if let Ok(tmp) = std::env::var("TMPDIR") {
76        let path = std::path::PathBuf::from(tmp);
77        if (path.exists() || std::fs::create_dir_all(&path).is_ok())
78            && let Ok(dir) = tempfile::TempDir::new_in(&path)
79        {
80            return dir;
81        }
82    }
83
84    // Search ancestors of CARGO_MANIFEST_DIR or current_dir for workspace target/tmp
85    let mut search_dirs = Vec::new();
86    if let Ok(manifest_dir) = std::env::var("CARGO_MANIFEST_DIR") {
87        search_dirs.push(std::path::PathBuf::from(manifest_dir));
88    }
89    if let Ok(cwd) = std::env::current_dir() {
90        search_dirs.push(cwd);
91    }
92    for base in search_dirs {
93        let mut cur = base;
94        loop {
95            let candidate = cur.join("target/tmp");
96            if (cur.join("Cargo.toml").exists() || cur.join(".git").exists())
97                && (candidate.exists() || std::fs::create_dir_all(&candidate).is_ok())
98                && let Ok(dir) = tempfile::TempDir::new_in(&candidate)
99            {
100                return dir;
101            }
102            if !cur.pop() {
103                break;
104            }
105        }
106    }
107
108    tempfile::tempdir().expect("failed to create temporary directory")
109}