Skip to content

Commit 7e7097c

Browse files
committed
Fix Windows embedding model cache and dashboard DB path resolution
- Set explicit cacheDir for @huggingface/transformers to ~/.local/share/opencode/storage/plugin/magic-context/models/ instead of relying on the library's default .cache inside node_modules. On Windows the npm cached install path is often inaccessible, causing 'Unable to get model file path or buffer' failures. Also survives plugin updates. - Fix dashboard Rust DB path resolution on Windows: was using %APPDATA% (dirs::data_dir) but the plugin stores context.db at ~/.local/share on all platforms. Now both resolve_db_path and resolve_opencode_db_path use XDG_DATA_HOME or ~/.local/share unconditionally. Closes #10
1 parent 12dc5ba commit 7e7097c

2 files changed

Lines changed: 46 additions & 28 deletions

File tree

packages/dashboard/src-tauri/src/db.rs

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,17 @@ use std::collections::{HashMap, HashSet};
44
use std::path::PathBuf;
55

66
pub fn resolve_db_path() -> Option<PathBuf> {
7-
// The magic-context plugin uses ~/.local/share/opencode/... on macOS and Linux
8-
// (XDG-style), and %APPDATA%/opencode/... on Windows.
9-
let data_dir = if cfg!(target_os = "windows") {
10-
dirs::data_dir()?
11-
} else {
12-
// XDG_DATA_HOME or ~/.local/share (matches plugin behavior)
13-
std::env::var("XDG_DATA_HOME")
14-
.map(PathBuf::from)
15-
.unwrap_or_else(|_| {
16-
dirs::home_dir()
17-
.unwrap_or_default()
18-
.join(".local")
19-
.join("share")
20-
})
21-
};
7+
// The magic-context plugin uses XDG_DATA_HOME or ~/.local/share on ALL platforms
8+
// (see packages/plugin/src/shared/data-path.ts). On Windows this means
9+
// C:\Users\<user>\.local\share — NOT %APPDATA%.
10+
let data_dir = std::env::var("XDG_DATA_HOME")
11+
.map(PathBuf::from)
12+
.unwrap_or_else(|_| {
13+
dirs::home_dir()
14+
.unwrap_or_default()
15+
.join(".local")
16+
.join("share")
17+
});
2218
let db_path = data_dir
2319
.join("opencode")
2420
.join("storage")
@@ -33,18 +29,15 @@ pub fn resolve_db_path() -> Option<PathBuf> {
3329
}
3430

3531
pub fn resolve_opencode_db_path() -> Option<PathBuf> {
36-
let data_dir = if cfg!(target_os = "windows") {
37-
dirs::data_dir()?
38-
} else {
39-
std::env::var("XDG_DATA_HOME")
40-
.map(PathBuf::from)
41-
.unwrap_or_else(|_| {
42-
dirs::home_dir()
43-
.unwrap_or_default()
44-
.join(".local")
45-
.join("share")
46-
})
47-
};
32+
// OpenCode also uses XDG_DATA_HOME or ~/.local/share on all platforms.
33+
let data_dir = std::env::var("XDG_DATA_HOME")
34+
.map(PathBuf::from)
35+
.unwrap_or_else(|_| {
36+
dirs::home_dir()
37+
.unwrap_or_default()
38+
.join(".local")
39+
.join("share")
40+
});
4841
let db_path = data_dir.join("opencode").join("opencode.db");
4942
if db_path.exists() {
5043
Some(db_path)

packages/plugin/src/features/magic-context/memory/embedding-local.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
import { mkdirSync } from "node:fs";
2+
import { join } from "node:path";
13
import { DEFAULT_LOCAL_EMBEDDING_MODEL } from "../../../config/schema/magic-context";
4+
import { getOpenCodeStorageDir } from "../../../shared/data-path";
25
import { log } from "../../../shared/logger";
36
import type { EmbeddingProvider } from "./embedding-provider";
47

@@ -155,11 +158,33 @@ export class LocalEmbeddingProvider implements EmbeddingProvider {
155158
string,
156159
unknown
157160
>;
158-
const env = transformersModule.env as { logLevel?: unknown };
161+
const env = transformersModule.env as {
162+
logLevel?: unknown;
163+
cacheDir?: string;
164+
};
159165
const LogLevel = transformersModule.LogLevel as Record<string, unknown> | undefined;
160166
if (LogLevel && "ERROR" in LogLevel) {
161167
env.logLevel = LogLevel.ERROR;
162168
}
169+
170+
// Set a stable model cache directory outside of node_modules.
171+
// On Windows, the default .cache inside the npm cached install
172+
// (e.g. ~\.cache\opencode\packages\...\node_modules\@huggingface\transformers\.cache)
173+
// can be inaccessible or non-writable, causing "Unable to get model file path
174+
// or buffer" failures. Using our own storage dir survives plugin updates too.
175+
const modelCacheDir = join(
176+
getOpenCodeStorageDir(),
177+
"plugin",
178+
"magic-context",
179+
"models",
180+
);
181+
try {
182+
mkdirSync(modelCacheDir, { recursive: true });
183+
env.cacheDir = modelCacheDir;
184+
} catch {
185+
// Non-fatal — fall back to library default if we can't create the dir
186+
log("[magic-context] could not create model cache dir, using library default");
187+
}
163188
const createPipeline = transformersModule.pipeline as CreateEmbeddingPipeline;
164189

165190
// Retry loop absorbs transient failures seen when multiple plugin

0 commit comments

Comments
 (0)