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
78pub 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 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}