diff --git a/src-tauri/src/commands/workspace.rs b/src-tauri/src/commands/workspace.rs index c8405419a..172deceb3 100644 --- a/src-tauri/src/commands/workspace.rs +++ b/src-tauri/src/commands/workspace.rs @@ -1,5 +1,7 @@ use regex::Regex; use std::sync::LazyLock; +use tauri::AppHandle; +use tauri_plugin_opener::OpenerExt; use crate::config::write_text_file; use crate::openclaw_config::get_openclaw_dir; @@ -336,3 +338,25 @@ pub async fn write_workspace_file(filename: String, content: String) -> Result<( write_text_file(&path, &content) .map_err(|e| format!("Failed to write workspace file {filename}: {e}")) } + +/// Open the workspace or memory directory in the system file manager. +/// `subdir`: "workspace" opens `~/.openclaw/workspace/`, +/// "memory" opens `~/.openclaw/workspace/memory/`. +#[tauri::command] +pub async fn open_workspace_directory(handle: AppHandle, subdir: String) -> Result { + let dir = match subdir.as_str() { + "memory" => get_openclaw_dir().join("workspace").join("memory"), + _ => get_openclaw_dir().join("workspace"), + }; + + if !dir.exists() { + std::fs::create_dir_all(&dir).map_err(|e| format!("Failed to create directory: {e}"))?; + } + + handle + .opener() + .open_path(dir.to_string_lossy().to_string(), None::) + .map_err(|e| format!("Failed to open directory: {e}"))?; + + Ok(true) +} diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 0fbb1bb93..e2cefc38c 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1052,6 +1052,7 @@ pub fn run() { commands::write_daily_memory_file, commands::delete_daily_memory_file, commands::search_daily_memory_files, + commands::open_workspace_directory, ]); let app = builder diff --git a/src/components/workspace/DailyMemoryPanel.tsx b/src/components/workspace/DailyMemoryPanel.tsx index f81295b77..8b2008c6a 100644 --- a/src/components/workspace/DailyMemoryPanel.tsx +++ b/src/components/workspace/DailyMemoryPanel.tsx @@ -7,7 +7,7 @@ import React, { } from "react"; import { useTranslation } from "react-i18next"; import { toast } from "sonner"; -import { Calendar, Trash2, Plus, Search, X } from "lucide-react"; +import { Calendar, Trash2, Plus, Search, X, FolderOpen } from "lucide-react"; import { AnimatePresence, motion } from "framer-motion"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; @@ -352,8 +352,13 @@ const DailyMemoryPanel: React.FC = ({
{/* Header with path, search, and create button */}
-

+

workspaceApi.openDirectory("memory")} + title={t("workspace.openDirectory")} + > ~/.openclaw/workspace/memory/ +