Skip to main content

code_kb_core/
lib.rs

1pub mod db;
2pub mod edit_check;
3pub mod formatters;
4pub mod models;
5pub mod ops;
6pub mod queries;
7pub mod reference_report;
8pub mod slicer;
9pub mod sync;
10pub mod telemetry;
11pub mod test_commands;
12pub mod text_scan;
13pub mod watcher;
14pub mod workspace;
15
16pub use db::{
17    Connection, DbError, ensure_fts_index, ensure_fts_index_path, open_read_only, open_read_write,
18};
19pub use edit_check::{
20    BaseRequest, BaseSource, EditCheck, EditCheckError, EditLimits, EditSite, PendingCheck,
21    SessionLock, SessionState, ShapeChange, head_commit, is_session_id, latest_session_base,
22    lock_session, prune_sessions, read_session, record_session_base, write_session,
23};
24pub use formatters::{
25    format_blast_radius, format_context_slice, format_context_slices, format_edit_check,
26    format_fact_categories, format_file_skeleton, format_find_symbol_results,
27    format_import_summary, format_no_facts, format_reference_report, format_references,
28    format_search_results, format_stop_reason, format_structural_facts, format_symbol_bodies,
29    format_symbol_body, no_facts_heading,
30};
31pub use models::{
32    BlastRadiusResult, CallingTest, ConstructionSite, ContextSlice, FileFact, ImpactedSymbol,
33    LabeledSite, LiteralFact, OverrideRow, ReferenceCounts, ReferenceReport, ReferenceSite,
34    ReferenceTarget, Registration, SearchExplain, SiteLabel, StructuralFact, Symbol,
35    SymbolSearchResult, TestTarget, TextOnlyLines, TextScanSummary, TypeFact, VariantUse,
36};
37pub use ops::{
38    OpError, SymbolLookup, SymbolSelector, blast_radius_op, blast_radius_selected_op,
39    codebase_outline_op, edit_check_op, edit_check_session_diff, edit_check_session_op,
40    edit_check_with, file_skeleton_op, get_context_slice_op, get_context_slice_selected_op,
41    get_context_slices_selected_op, get_symbol_bodies_selected_op, get_symbol_body_op,
42    get_symbol_body_selected_op, lookup_symbols_op, render_symbol_lookup, resolve_symbol_op,
43};
44pub use queries::{
45    QueryError, compute_blast_radius, compute_blast_radius_scoped,
46    compute_blast_radius_scoped_with_ids, count_file_symbols, file_sizes_for_paths,
47    find_callee_signatures, find_literals, find_literals_scoped, find_references,
48    find_references_ext, find_references_for_symbol, find_references_for_symbol_ext,
49    find_references_scoped, find_related_tests, find_structural_facts,
50    find_structural_facts_scoped, find_type_facts, fts_search_symbols_explained,
51    fts_search_symbols_scoped, get_file, get_symbol_by_id, get_symbol_by_name,
52    get_symbol_by_name_exact, get_symbol_overloads, import_sites, is_category_alias, is_test_path,
53    list_structural_fact_categories, list_structural_fact_categories_scoped, load_file_symbols,
54    load_scoped_outline_symbols, normalize_kind, qualify_members, sanitize_fts5_query,
55    search_symbols, search_symbols_scoped, suggest_file_paths, suggest_symbol_names,
56    workspace_name,
57};
58pub use reference_report::{reference_report, reference_report_for_edit, select_reference_target};
59pub use slicer::{SliceError, slice_symbol, slice_symbol_body};
60pub use sync::{
61    PINNED_JULIE_VERSION, ReconcileReport, SyncError, create_index, delete_file, ensure_fresh_file,
62    ensure_index_matches_extractor, find_julie_extract_binary, index_written_by_other_extractor,
63    installed_extractor_version, reconcile_offline_edits, scan_workspace, update_file,
64};
65pub use telemetry::{
66    BugReportBundle, IndexFacts, TelemetryErrorRecord, TelemetryFilter, TelemetrySummary,
67    TimeWindow, ToolInvocation, ToolStat, format_telemetry_summary, generate_bug_report,
68    get_global_telemetry_dir, get_telemetry_summary, open_global_telemetry_db, open_telemetry_db,
69    record_tool_call, record_tool_call_conn,
70};
71pub use text_scan::{WordHits, scan_word};
72pub use watcher::{WatcherError, WatcherHandle, start_watcher};
73pub use workspace::{
74    Workspace, WorkspaceError, is_hard_excluded, is_project_root, normalize_path, parse_file_uri,
75    strip_prefix_lossy, to_forward_slash,
76};
77
78/// Creates a temporary directory in a safe location, prioritizing `CARGO_TARGET_TMPDIR`,
79/// `TMPDIR`, and workspace `./target/tmp` over `/tmp` to avoid tmpfs quota limits.
80pub fn safe_tempdir() -> tempfile::TempDir {
81    if let Ok(target_tmp) = std::env::var("CARGO_TARGET_TMPDIR") {
82        let path = std::path::PathBuf::from(&target_tmp);
83        if (path.exists() || std::fs::create_dir_all(&path).is_ok())
84            && let Ok(dir) = tempfile::TempDir::new_in(&path)
85        {
86            return dir;
87        }
88    }
89    if let Ok(tmp) = std::env::var("TMPDIR") {
90        let path = std::path::PathBuf::from(tmp);
91        if (path.exists() || std::fs::create_dir_all(&path).is_ok())
92            && let Ok(dir) = tempfile::TempDir::new_in(&path)
93        {
94            return dir;
95        }
96    }
97
98    // Search ancestors of CARGO_MANIFEST_DIR or current_dir for workspace target/tmp
99    let mut search_dirs = Vec::new();
100    if let Ok(manifest_dir) = std::env::var("CARGO_MANIFEST_DIR") {
101        search_dirs.push(std::path::PathBuf::from(manifest_dir));
102    }
103    if let Ok(cwd) = std::env::current_dir() {
104        search_dirs.push(cwd);
105    }
106    for base in search_dirs {
107        let mut cur = base;
108        loop {
109            let candidate = cur.join("target/tmp");
110            if (cur.join("Cargo.toml").exists() || cur.join(".git").exists())
111                && (candidate.exists() || std::fs::create_dir_all(&candidate).is_ok())
112                && let Ok(dir) = tempfile::TempDir::new_in(&candidate)
113            {
114                return dir;
115            }
116            if !cur.pop() {
117                break;
118            }
119        }
120    }
121
122    tempfile::tempdir().expect("failed to create temporary directory")
123}