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