From 18efa3c0c4beaeaa40598e3010a5adae2056c898 Mon Sep 17 00:00:00 2001 From: suyujay Date: Mon, 24 Aug 2026 22:36:55 +0800 Subject: [PATCH] fix(windows): resolve platform binary directly and inject HOME env var On Windows, Bun cannot exec a .js shim via CreateProcess, causing semantic search to silently fall back to keyword-only. Fix resolveRagBinary() to prefer the platform-specific binary (e.g. rag-cli-win32-x64/bin/rag.exe) and inject HOME env var (which Windows lacks but the Rust rag binary requires) into all Bun spawn calls. Supported platforms in rag-cli already include win32-x64 (confirmed in src/platform.js SUPPORTED_PLATFORMS). This commit aligns the plugin code with the actual platform support. --- README.md | 2 +- src/lib/rag.ts | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f55ab12..8446ed5 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ The plugin also auto-registers (OpenCode only): | **Keyword (ripgrep)** | `@vscode/ripgrep` | Exact-match + phrase lookup over files | | **Semantic (rag-cli)** | `@mathew-cf/rag-cli` | Similarity search via local embeddings | -Both are declared as **required dependencies**: installing the plugin pulls in prebuilt binaries for your platform automatically (macOS ARM64/x64, Linux x64/ARM64; ripgrep additionally covers Windows and FreeBSD). No Rust toolchain, no `brew install`, no `$PATH` plumbing. +Both are declared as **required dependencies**: installing the plugin pulls in prebuilt binaries for your platform automatically (macOS ARM64/x64, Linux x64/ARM64, Windows x64). ripgrep additionally covers Windows and FreeBSD. No Rust toolchain, no `brew install`, no `$PATH` plumbing. Pre-cache the embedding model once (~90MB) to make the first semantic search instant: diff --git a/src/lib/rag.ts b/src/lib/rag.ts index 4ed94b8..4265262 100644 --- a/src/lib/rag.ts +++ b/src/lib/rag.ts @@ -40,6 +40,25 @@ export interface RagStatus { */ export function resolveRagBinary(): string | null { try { + // Prefer the platform binary directly. On Windows, Bun cannot exec + // a .js shim via CreateProcess, so resolving the binary avoids a + // silent "Executable not found in $PATH" error. + try { + const platform = require("@mathew-cf/rag-cli/src/platform") as { + platformKey(p: string, a: string): string; + isSupported(key: string): boolean; + subpackageName(key: string): string; + binaryFilename(p: string): string; + }; + const key = platform.platformKey(process.platform, process.arch); + if (platform.isSupported(key)) { + return require.resolve( + `${platform.subpackageName(key)}/bin/${platform.binaryFilename(process.platform)}`, + ); + } + } catch { + // Fall through to the JS shim. + } return require.resolve("@mathew-cf/rag-cli/bin/rag.js"); } catch { return null; @@ -74,7 +93,7 @@ export function installGuidance(): string { "", "Usually this means one of:", " - Your host platform isn't covered by the prebuilt binaries", - " (supported: macOS ARM64/x64, Linux x64/ARM64).", + " (supported: macOS ARM64/x64, Linux x64/ARM64, Windows x64).", " - `npm install` or the equivalent plugin install skipped", " optionalDependencies.", "", @@ -104,6 +123,10 @@ export async function ragSearch(args: { if (!shim) return ""; const k = String(args.topK ?? 15); return Bun.$`${shim} search ${args.query} -i ${args.indexDir} -k ${k} --json` + .env({ + ...process.env, + HOME: process.env.HOME || process.env.USERPROFILE, + }) .text() .catch(() => ""); } @@ -125,6 +148,10 @@ export function spawnRagIndex(args: { Bun.spawn([shim, "index", args.memoryDir, "-o", args.indexDir], { stdout: "ignore", stderr: "ignore", + env: { + ...process.env, + HOME: process.env.HOME || process.env.USERPROFILE, + }, }); return true; } @@ -139,7 +166,12 @@ export async function downloadModel(): Promise { if (!shim) return installGuidance(); try { - const out = await Bun.$`${shim} download`.text(); + const out = await Bun.$`${shim} download` + .env({ + ...process.env, + HOME: process.env.HOME || process.env.USERPROFILE, + }) + .text(); return out.trim() || "Model downloaded."; } catch (err) { return `rag download failed: ${String(err)}`;