generated from nhcarrigan/template
fix: memory files tab empty on Windows (#140)
## Summary Fixes the memory files tab showing as empty on Windows production builds and the "forbidden path" error when trying to read memory files. ## Changes ### 1. List memory files from WSL home directory (commit 1) - Split `list_memory_files()` into platform-specific implementations - **Windows**: Use WSL command with `bash -l` to find memory files in WSL home (`~/.claude/projects/.../memory/`) - **Linux/Mac**: Continue using native filesystem access - Previously used `dirs::home_dir()` which returns Windows home (`C:\Users\...`), but Claude Code stores files in WSL home ### 2. Use backend command for reading files (commit 2) - Changed frontend from Tauri's `readTextFile` plugin to `read_file_content` backend command - Tauri plugin enforces scope restrictions and can't access WSL paths on Windows - Our backend command already handles WSL paths correctly via `read_file_via_wsl()` - Matches the pattern used throughout the app for other file operations ## Testing - ✅ All 426 backend tests pass - ✅ All frontend tests pass - ✅ Lint, format, and type checks pass - ✅ Follows existing WSL file operation patterns in codebase ## Related Issues Fixes the memory files tab functionality on Windows whilst maintaining full compatibility with Linux/Mac. ✨ This PR was created by Hikari~ 🌸 Reviewed-on: #140 Co-authored-by: Hikari <hikari@nhcarrigan.com> Co-committed-by: Hikari <hikari@nhcarrigan.com>
This commit was merged in pull request #140.
This commit is contained in:
@@ -1219,6 +1219,55 @@ pub struct MemoryFilesResponse {
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn list_memory_files() -> Result<MemoryFilesResponse, String> {
|
||||
// On Windows, we need to look in the WSL home directory
|
||||
// On Linux/Mac, use the native home directory
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
list_memory_files_via_wsl().await
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
{
|
||||
list_memory_files_native().await
|
||||
}
|
||||
}
|
||||
|
||||
/// List memory files via WSL (for Windows)
|
||||
#[cfg(target_os = "windows")]
|
||||
async fn list_memory_files_via_wsl() -> Result<MemoryFilesResponse, String> {
|
||||
use std::process::Command;
|
||||
|
||||
// Use WSL to find all memory files in the WSL home directory
|
||||
// This script finds all "memory" directories and lists their files
|
||||
let script = r#"
|
||||
find ~/.claude/projects -type d -name memory 2>/dev/null | while read dir; do
|
||||
find "$dir" -maxdepth 1 -type f 2>/dev/null
|
||||
done | sort
|
||||
"#;
|
||||
|
||||
let output = Command::new("wsl")
|
||||
.args(["-e", "bash", "-l", "-c", script])
|
||||
.output()
|
||||
.map_err(|e| format!("Failed to execute WSL command: {}", e))?;
|
||||
|
||||
if !output.status.success() {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
return Err(format!("Failed to list memory files: {}", stderr));
|
||||
}
|
||||
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
let files: Vec<String> = stdout
|
||||
.lines()
|
||||
.filter(|line| !line.trim().is_empty())
|
||||
.map(|line| line.trim().to_string())
|
||||
.collect();
|
||||
|
||||
Ok(MemoryFilesResponse { files })
|
||||
}
|
||||
|
||||
/// List memory files using native filesystem (for Linux/Mac)
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
async fn list_memory_files_native() -> Result<MemoryFilesResponse, String> {
|
||||
use std::fs;
|
||||
|
||||
// Get the .claude directory in the user's home
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { readTextFile } from "@tauri-apps/plugin-fs";
|
||||
import Markdown from "./Markdown.svelte";
|
||||
|
||||
let memoryFiles: string[] = $state([]);
|
||||
@@ -33,7 +32,8 @@
|
||||
isLoading = true;
|
||||
error = null;
|
||||
try {
|
||||
const content = await readTextFile(filePath);
|
||||
// Use our backend command instead of Tauri plugin to handle WSL paths
|
||||
const content = await invoke<string>("read_file_content", { path: filePath });
|
||||
fileContent = content;
|
||||
selectedFile = filePath;
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user