Skip to content

Commit dc0dae5

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 9aa29a9 commit dc0dae5

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.
@@ -863,4 +908,33 @@ mod tests {
863908
assert_eq!(err.exit_code(), 2);
864909
assert!(err.to_string().contains("--only requires a value"));
865910
}
911+
912+
#[test]
913+
fn try_set_ort_dylib_path_finds_cached_library() {
914+
use std::sync::Mutex;
915+
static LOCK: Mutex<()> = Mutex::new(());
916+
let _guard = LOCK.lock().unwrap();
917+
std::env::remove_var("ORT_DYLIB_PATH");
918+
919+
let temp = tempfile::tempdir().unwrap();
920+
let lib_name = if cfg!(target_os = "macos") {
921+
"libonnxruntime.dylib"
922+
} else if cfg!(target_os = "windows") {
923+
"onnxruntime.dll"
924+
} else {
925+
"libonnxruntime.so"
926+
};
927+
let ort_dir = temp.path().join("onnxruntime").join("1.24.4");
928+
std::fs::create_dir_all(&ort_dir).unwrap();
929+
let lib_path = ort_dir.join(lib_name);
930+
std::fs::write(&lib_path, b"fake").unwrap();
931+
932+
try_set_ort_dylib_path(temp.path());
933+
934+
assert_eq!(
935+
std::env::var_os("ORT_DYLIB_PATH"),
936+
Some(lib_path.as_os_str().to_owned())
937+
);
938+
std::env::remove_var("ORT_DYLIB_PATH");
939+
}
866940
}

crates/aft/src/search_index.rs

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1696,15 +1696,42 @@ pub fn resolve_cache_dir(project_root: &Path, storage_dir: Option<&Path>) -> Pat
16961696
if let Some(dir) = storage_dir {
16971697
return dir.join("index").join(artifact_cache_key(project_root));
16981698
}
1699-
// Fallback to ~/.cache/aft/ (legacy, for standalone binary usage).
1700-
// On Windows `HOME` is typically unset, so try `USERPROFILE` next.
1699+
// Fallback mirrors resolveCortexKitStorageRoot() from the TS plugin
1700+
// (packages/opencode-plugin/src/shared/storage-paths.ts).
1701+
if let Some(dir) = std::env::var_os("XDG_DATA_HOME") {
1702+
return PathBuf::from(dir)
1703+
.join("cortexkit")
1704+
.join("aft")
1705+
.join("index")
1706+
.join(artifact_cache_key(project_root));
1707+
}
1708+
if cfg!(target_os = "windows") {
1709+
if let Some(dir) = std::env::var_os("LOCALAPPDATA")
1710+
.or_else(|| std::env::var_os("APPDATA"))
1711+
{
1712+
return PathBuf::from(dir)
1713+
.join("cortexkit")
1714+
.join("aft")
1715+
.join("index")
1716+
.join(artifact_cache_key(project_root));
1717+
}
1718+
}
1719+
// On Windows prefer `USERPROFILE`; fall back to `HOME`.
17011720
// If neither is set, fall back to a temp directory rather than `"."`
17021721
// because the search-index code reads/writes absolute paths.
1703-
let home = std::env::var_os("HOME")
1704-
.or_else(|| std::env::var_os("USERPROFILE"))
1705-
.map(PathBuf::from)
1706-
.unwrap_or_else(std::env::temp_dir);
1707-
home.join(".cache")
1722+
let home = if cfg!(target_os = "windows") {
1723+
std::env::var_os("USERPROFILE").or_else(|| std::env::var_os("HOME"))
1724+
} else {
1725+
std::env::var_os("HOME")
1726+
}
1727+
.map(PathBuf::from)
1728+
.unwrap_or_else(std::env::temp_dir);
1729+
let root = if cfg!(target_os = "windows") {
1730+
home.join("AppData").join("Local")
1731+
} else {
1732+
home.join(".local").join("share")
1733+
};
1734+
root.join("cortexkit")
17081735
.join("aft")
17091736
.join("index")
17101737
.join(artifact_cache_key(project_root))

0 commit comments

Comments
 (0)