Skip to content

Commit f984b57

Browse files
committed
fix: align standalone storage dir fallbacks with plugin + resolve ORT_DYLIB_PATH in warmup
Three functions defaulted to ~/.cache/aft instead of the plugin's ~/.local/share/cortexkit/aft, causing standalone `aft warmup` to write to a different path than the plugin. Fallback now mirrors resolveCortexKitStorageRoot() from the TS plugin (XDG_DATA_HOME, Windows LOCALAPPDATA/APPDATA, ~/.local/share/cortexkit/aft). warmup.rs also never set ORT_DYLIB_PATH, so semantic index warmup failed with dlopen('libonnxruntime.so'). Now resolves the cached library from <storage_dir>/onnxruntime/1.24.4/ (and lib/ subdir) if ORT_DYLIB_PATH is not already set.
1 parent 929e660 commit f984b57

3 files changed

Lines changed: 143 additions & 24 deletions

File tree

crates/aft/src/bash_background/mod.rs

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -159,19 +159,37 @@ pub fn storage_dir(configured: Option<&std::path::Path>) -> PathBuf {
159159
if let Some(dir) = std::env::var_os("AFT_CACHE_DIR") {
160160
return PathBuf::from(dir).join("aft");
161161
}
162-
// Fallback to the user's home directory. On Unix this is `$HOME`; on
163-
// Windows `HOME` is typically unset, so fall back to `USERPROFILE`
164-
// (which is always set in interactive sessions and in the env that
165-
// OpenCode/Pi pass through to plugin processes). If both are missing
166-
// (rare — embedded contexts, broken shells), fall back to a temp
162+
// Fallback mirrors resolveCortexKitStorageRoot() from the TS plugin
163+
// (packages/opencode-plugin/src/shared/storage-paths.ts).
164+
if let Some(dir) = std::env::var_os("XDG_DATA_HOME") {
165+
return PathBuf::from(dir).join("cortexkit").join("aft");
166+
}
167+
if cfg!(target_os = "windows") {
168+
if let Some(dir) = std::env::var_os("LOCALAPPDATA")
169+
.or_else(|| std::env::var_os("APPDATA"))
170+
{
171+
return PathBuf::from(dir).join("cortexkit").join("aft");
172+
}
173+
}
174+
// On Unix `$HOME`; on Windows `HOME` is typically unset, so fall back to
175+
// `USERPROFILE` (which is always set in interactive sessions and in the
176+
// env that OpenCode/Pi pass through to plugin processes). If both are
177+
// missing (rare — embedded contexts, broken shells), fall back to a temp
167178
// directory rather than `"."` — a relative path makes bg-bash wrapper
168-
// commands like `move /Y .\.cache\aft\... ...` fail with "system
169-
// cannot find the path specified" once the working directory shifts.
170-
let home = std::env::var_os("HOME")
171-
.or_else(|| std::env::var_os("USERPROFILE"))
172-
.map(PathBuf::from)
173-
.unwrap_or_else(std::env::temp_dir);
174-
home.join(".cache").join("aft")
179+
// commands like `move /Y .\.cache\aft\... ...` fail with "system cannot
180+
// find the path specified" once the working directory shifts.
181+
let home = if cfg!(target_os = "windows") {
182+
std::env::var_os("USERPROFILE").or_else(|| std::env::var_os("HOME"))
183+
} else {
184+
std::env::var_os("HOME")
185+
}
186+
.map(PathBuf::from)
187+
.unwrap_or_else(std::env::temp_dir);
188+
if cfg!(target_os = "windows") {
189+
home.join("AppData").join("Local").join("cortexkit").join("aft")
190+
} else {
191+
home.join(".local").join("share").join("cortexkit").join("aft")
192+
}
175193
}
176194

177195
pub fn repair_legacy_root_tasks(storage_root: &std::path::Path, harness: crate::harness::Harness) {

crates/aft/src/cli/warmup.rs

Lines changed: 79 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ pub fn run(args: Vec<OsString>) -> Result<(), WarmupError> {
4949
);
5050
}
5151

52+
// Resolve ONNX Runtime from the plugin-managed cache so `aft warmup`
53+
// can build the semantic index without the plugin setting ORT_DYLIB_PATH.
54+
if args.areas.semantic {
55+
try_set_ort_dylib_path(&storage_dir);
56+
}
57+
5258
let ctx = AppContext::new(Box::new(TreeSitterProvider::new()), Config::default());
5359
configure(&ctx, &root, &storage_dir, args.areas, args.force)?;
5460

@@ -248,11 +254,50 @@ fn warmup_storage_dir() -> PathBuf {
248254
if let Some(value) = std::env::var_os("AFT_STORAGE_DIR") {
249255
return PathBuf::from(value);
250256
}
251-
let home = std::env::var_os("HOME")
252-
.or_else(|| std::env::var_os("USERPROFILE"))
253-
.map(PathBuf::from)
254-
.unwrap_or_else(std::env::temp_dir);
255-
home.join(".cache").join("aft")
257+
// Fallback mirrors resolveCortexKitStorageRoot() from the TS plugin.
258+
if let Some(dir) = std::env::var_os("XDG_DATA_HOME") {
259+
return PathBuf::from(dir).join("cortexkit").join("aft");
260+
}
261+
if cfg!(target_os = "windows") {
262+
if let Some(dir) = std::env::var_os("LOCALAPPDATA")
263+
.or_else(|| std::env::var_os("APPDATA"))
264+
{
265+
return PathBuf::from(dir).join("cortexkit").join("aft");
266+
}
267+
}
268+
let home = if cfg!(target_os = "windows") {
269+
std::env::var_os("USERPROFILE").or_else(|| std::env::var_os("HOME"))
270+
} else {
271+
std::env::var_os("HOME")
272+
}
273+
.map(PathBuf::from)
274+
.unwrap_or_else(std::env::temp_dir);
275+
if cfg!(target_os = "windows") {
276+
home.join("AppData").join("Local").join("cortexkit").join("aft")
277+
} else {
278+
home.join(".local").join("share").join("cortexkit").join("aft")
279+
}
280+
}
281+
282+
/// Set `ORT_DYLIB_PATH` from a cached ONNX Runtime library if not already set.
283+
fn try_set_ort_dylib_path(storage_dir: &std::path::Path) {
284+
if std::env::var_os("ORT_DYLIB_PATH").is_some() {
285+
return;
286+
}
287+
let lib_name = if cfg!(target_os = "macos") {
288+
"libonnxruntime.dylib"
289+
} else if cfg!(target_os = "windows") {
290+
"onnxruntime.dll"
291+
} else {
292+
"libonnxruntime.so"
293+
};
294+
let ort_dir = storage_dir.join("onnxruntime").join("1.24.4");
295+
for candidate in [ort_dir.join(lib_name), ort_dir.join("lib").join(lib_name)] {
296+
if candidate.is_file() {
297+
std::env::set_var("ORT_DYLIB_PATH", &candidate);
298+
break;
299+
}
300+
}
256301
}
257302

258303
/// Build the `configure` params for a warmup run.
@@ -894,4 +939,33 @@ mod tests {
894939
assert_eq!(err.exit_code(), 2);
895940
assert!(err.to_string().contains("--only requires a value"));
896941
}
942+
943+
#[test]
944+
fn try_set_ort_dylib_path_finds_cached_library() {
945+
use std::sync::Mutex;
946+
static LOCK: Mutex<()> = Mutex::new(());
947+
let _guard = LOCK.lock().unwrap();
948+
std::env::remove_var("ORT_DYLIB_PATH");
949+
950+
let temp = tempfile::tempdir().unwrap();
951+
let lib_name = if cfg!(target_os = "macos") {
952+
"libonnxruntime.dylib"
953+
} else if cfg!(target_os = "windows") {
954+
"onnxruntime.dll"
955+
} else {
956+
"libonnxruntime.so"
957+
};
958+
let ort_dir = temp.path().join("onnxruntime").join("1.24.4");
959+
std::fs::create_dir_all(&ort_dir).unwrap();
960+
let lib_path = ort_dir.join(lib_name);
961+
std::fs::write(&lib_path, b"fake").unwrap();
962+
963+
try_set_ort_dylib_path(temp.path());
964+
965+
assert_eq!(
966+
std::env::var_os("ORT_DYLIB_PATH"),
967+
Some(lib_path.as_os_str().to_owned())
968+
);
969+
std::env::remove_var("ORT_DYLIB_PATH");
970+
}
897971
}

crates/aft/src/search_index.rs

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2811,15 +2811,42 @@ pub fn resolve_cache_dir(project_root: &Path, storage_dir: Option<&Path>) -> Pat
28112811
if let Some(dir) = storage_dir {
28122812
return dir.join("index").join(artifact_cache_key(project_root));
28132813
}
2814-
// Fallback to ~/.cache/aft/ (legacy, for standalone binary usage).
2815-
// On Windows `HOME` is typically unset, so try `USERPROFILE` next.
2814+
// Fallback mirrors resolveCortexKitStorageRoot() from the TS plugin
2815+
// (packages/opencode-plugin/src/shared/storage-paths.ts).
2816+
if let Some(dir) = std::env::var_os("XDG_DATA_HOME") {
2817+
return PathBuf::from(dir)
2818+
.join("cortexkit")
2819+
.join("aft")
2820+
.join("index")
2821+
.join(artifact_cache_key(project_root));
2822+
}
2823+
if cfg!(target_os = "windows") {
2824+
if let Some(dir) = std::env::var_os("LOCALAPPDATA")
2825+
.or_else(|| std::env::var_os("APPDATA"))
2826+
{
2827+
return PathBuf::from(dir)
2828+
.join("cortexkit")
2829+
.join("aft")
2830+
.join("index")
2831+
.join(artifact_cache_key(project_root));
2832+
}
2833+
}
2834+
// On Windows prefer `USERPROFILE`; fall back to `HOME`.
28162835
// If neither is set, fall back to a temp directory rather than `"."`
28172836
// because the search-index code reads/writes absolute paths.
2818-
let home = std::env::var_os("HOME")
2819-
.or_else(|| std::env::var_os("USERPROFILE"))
2820-
.map(PathBuf::from)
2821-
.unwrap_or_else(std::env::temp_dir);
2822-
home.join(".cache")
2837+
let home = if cfg!(target_os = "windows") {
2838+
std::env::var_os("USERPROFILE").or_else(|| std::env::var_os("HOME"))
2839+
} else {
2840+
std::env::var_os("HOME")
2841+
}
2842+
.map(PathBuf::from)
2843+
.unwrap_or_else(std::env::temp_dir);
2844+
let root = if cfg!(target_os = "windows") {
2845+
home.join("AppData").join("Local")
2846+
} else {
2847+
home.join(".local").join("share")
2848+
};
2849+
root.join("cortexkit")
28232850
.join("aft")
28242851
.join("index")
28252852
.join(artifact_cache_key(project_root))

0 commit comments

Comments
 (0)