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