diff --git a/Cargo.toml b/Cargo.toml index f6d57aa..252c9fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ chrono = { version = "0.4", features = ["serde"] } rig-core = "0.31" # HTTP client -reqwest = { version = "0.12", features = ["json"] } +reqwest = { version = "0.12", features = ["json", "rustls-tls"], default-features = false } # Logging tracing = "0.1" diff --git a/README.md b/README.md index fc38227..a1ab939 100644 --- a/README.md +++ b/README.md @@ -428,7 +428,7 @@ The benchmark uses a professional memory system evaluation framework located in - **Professional Metrics**: Recall@K, Precision@K, MRR, NDCG, and answer quality metrics - **Enhanced Dataset**: 50 conversations with 150 questions covering various scenarios - **Statistical Analysis**: 95% confidence intervals, standard deviation, and category-based statistics -- **Multi-System Support**: Supports comparison between Cortex Memory, LangMem, and Simple RAG baselines +- **Cortex-Only Evaluation**: Dedicated evaluation workflow for Cortex Memory using the LoCoMo methodology For more details on running the evaluation, see the [lomoco-evaluation README](examples/lomoco-evaluation/README.md). diff --git a/README_zh.md b/README_zh.md index a54f532..b511c92 100644 --- a/README_zh.md +++ b/README_zh.md @@ -429,7 +429,7 @@ Cortex Memory已使用**LOCOMO数据集**(50个对话,150个问题)通过 - **专业指标**:Recall@K、Precision@K、MRR、NDCG和答案质量指标 - **增强数据集**:50个对话,150个问题,涵盖各种场景 - **统计分析**:95%置信区间、标准差和基于类别的统计 -- **多系统支持**:支持Cortex Memory、LangMem和简单RAG基线之间的比较 +- **Cortex 专用评测**:基于 LoCoMo 方法的 Cortex Memory 专用评测流程 有关运行评估的更多详细信息,请参阅[lomoco-evaluation README](examples/lomoco-evaluation/README.md)。 diff --git a/cortex-mem-cli/src/main.rs b/cortex-mem-cli/src/main.rs index 6e77563..ea712d5 100644 --- a/cortex-mem-cli/src/main.rs +++ b/cortex-mem-cli/src/main.rs @@ -205,7 +205,26 @@ async fn main() -> Result<()> { })?; // Determine data directory - let data_dir = config.cortex.data_dir(); + // Priority: + // 1. data_dir specified in config file (supports relative path to config file location) + // 2. CORTEX_DATA_DIR environment variable + // 3. Directory containing config.toml (the workspace root) + let config_dir = cli.config.parent().map(|p| p.to_path_buf()).unwrap_or_default(); + + let data_dir = if let Some(ref dir) = config.cortex.data_dir { + // If data_dir is a relative path, resolve it relative to config file location + let dir_path = std::path::Path::new(dir); + if dir_path.is_relative() { + config_dir.join(dir_path).to_string_lossy().to_string() + } else { + dir.clone() + } + } else if let Ok(env_dir) = std::env::var("CORTEX_DATA_DIR") { + env_dir + } else { + // Use the directory containing config.toml as the workspace root + config_dir.to_string_lossy().to_string() + }; // Handle tenant list command early (doesn't need MemoryOperations) if let Commands::Tenant { action } = cli.command { diff --git a/cortex-mem-config/src/lib.rs b/cortex-mem-config/src/lib.rs index 359e0a8..e63e736 100644 --- a/cortex-mem-config/src/lib.rs +++ b/cortex-mem-config/src/lib.rs @@ -44,6 +44,8 @@ fn default_enable_intent_analysis() -> bool { impl CortexConfig { /// Get the effective data directory + /// Returns the configured data_dir, or falls back to default behavior. + /// Note: Callers should handle the None case appropriately based on their context. pub fn data_dir(&self) -> String { self.data_dir.clone().unwrap_or_else(|| { Self::default_data_dir() @@ -51,22 +53,13 @@ impl CortexConfig { } /// Get the default data directory + /// Priority: + /// 1. Environment variable CORTEX_DATA_DIR + /// 2. Current directory "." fn default_data_dir() -> String { - // 优先级: - // 1. 环境变量 CORTEX_DATA_DIR - // 2. 应用数据目录/cortex (TARS 应用) - // 3. 当前目录 ./.cortex std::env::var("CORTEX_DATA_DIR") .ok() - .or_else(|| { - // 尝试使用应用数据目录(TARS 默认路径) - directories::ProjectDirs::from("com", "cortex-mem", "tars") - .map(|dirs| { - let cortex_dir = dirs.data_dir().join("cortex"); - cortex_dir.to_string_lossy().to_string() - }) - }) - .unwrap_or_else(|| "./.cortex".to_string()) + .unwrap_or_else(|| ".".to_string()) } } diff --git a/cortex-mem-insights/src/lib/api.ts b/cortex-mem-insights/src/lib/api.ts index c0903ad..7402ef9 100644 --- a/cortex-mem-insights/src/lib/api.ts +++ b/cortex-mem-insights/src/lib/api.ts @@ -72,7 +72,10 @@ class ApiClient { // Filesystem endpoints async listDirectory(path: string): Promise { - return this.request(`/filesystem/list?uri=${encodeURIComponent(path)}`); + const response = await this.request<{ uri: string; total: number; entries: FileEntryResponse[] }>( + `/filesystem/list?uri=${encodeURIComponent(path)}` + ); + return response.entries; } async readFile(path: string): Promise { diff --git a/cortex-mem-insights/src/lib/types.ts b/cortex-mem-insights/src/lib/types.ts index e42bfb4..33f5a83 100644 --- a/cortex-mem-insights/src/lib/types.ts +++ b/cortex-mem-insights/src/lib/types.ts @@ -15,6 +15,12 @@ export interface FileEntryResponse { modified: string; } +export interface LsResponse { + uri: string; + total: number; + entries: FileEntryResponse[]; +} + export interface SessionInfo { thread_id: string; status: string; diff --git a/cortex-mem-mcp/src/main.rs b/cortex-mem-mcp/src/main.rs index 289a2a6..95c038f 100644 --- a/cortex-mem-mcp/src/main.rs +++ b/cortex-mem-mcp/src/main.rs @@ -48,16 +48,35 @@ struct Cli { /// Disable auto-trigger feature #[arg(long, default_value = "false")] no_auto_trigger: bool, + + /// Path to log file. If specified, logs will be written to this file. + /// If not specified, logging is disabled (MCP protocol uses stdio). + #[arg(long)] + log_file: Option, } #[tokio::main] async fn main() -> Result<()> { let cli = Cli::parse(); - // Initialize logging - tracing_subscriber::fmt() - .with_max_level(tracing::Level::INFO) - .init(); + // Initialize logging only if --log-file is specified + // MCP protocol uses stdio for JSON-RPC, so we avoid console output by default + if let Some(ref log_file) = cli.log_file { + // Create parent directory if needed + if let Some(parent) = log_file.parent() { + std::fs::create_dir_all(parent)?; + } + + let file = std::fs::OpenOptions::new() + .create(true) + .append(true) + .open(log_file)?; + + tracing_subscriber::fmt() + .with_writer(std::sync::Arc::new(file)) + .with_max_level(tracing::Level::INFO) + .init(); + } info!("Starting Cortex Memory MCP Server"); info!("Using configuration file: {:?}", cli.config); diff --git a/cortex-mem-service/src/handlers/filesystem.rs b/cortex-mem-service/src/handlers/filesystem.rs index 3122934..788862a 100644 --- a/cortex-mem-service/src/handlers/filesystem.rs +++ b/cortex-mem-service/src/handlers/filesystem.rs @@ -1,52 +1,87 @@ use axum::{ - extract::{Path, Query, State}, - Json, + extract::{Path, Query, State, Json}, + Json as JsonExtractor, }; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use std::sync::Arc; use crate::{ error::{Result, AppError}, - models::{ApiResponse, FileEntryResponse}, + models::{ApiResponse, FileEntryResponse, LsRequest, LsResponse, ExploreRequest, ExploreResponse, ExplorationPathItem, SearchResultResponse}, state::AppState, }; use chrono::{DateTime, Utc}; -#[derive(Debug, Deserialize)] -pub struct ListQuery { - uri: String, -} +// ==================== List Directory ==================== -/// List directory contents +/// List directory contents with optional recursive and abstracts pub async fn list_directory( State(state): State>, - Query(params): Query, -) -> Result>>> { + Query(params): Query, +) -> Result>> { // Get tenant root if set let tenant_root = state.current_tenant_root.read().await.clone(); - // Build the path + // Build the base path let base_path = if let Some(root) = tenant_root { let uri_path = params.uri.trim_start_matches("cortex://"); root.join(uri_path) } else { - let cortex_dir = state.data_dir.join("cortex"); + // 直接使用 data_dir 作为根目录(不再添加 cortex 子目录) let uri_path = params.uri.trim_start_matches("cortex://"); - cortex_dir.join(uri_path) + state.data_dir.join(uri_path) }; - tracing::debug!("Listing directory: {:?}", base_path); + tracing::debug!("Listing directory: {:?} (recursive={}, include_abstracts={})", + base_path, params.recursive, params.include_abstracts); if !base_path.exists() { - return Ok(Json(ApiResponse::success(vec![]))); + return Ok(Json(ApiResponse::success(LsResponse { + uri: params.uri, + total: 0, + entries: vec![], + }))); + } + + let uri = params.uri.clone(); + let recursive = params.recursive; + let include_abstracts = params.include_abstracts; + + // Use spawn_blocking to avoid blocking the async runtime + let entries = tokio::task::spawn_blocking(move || { + let mut entries = Vec::new(); + list_directory_recursive(&base_path, &uri, recursive, include_abstracts, &mut entries); + entries + }) + .await + .map_err(|e| AppError::Internal(format!("Failed to list directory: {}", e)))?; + + let total = entries.len(); + Ok(Json(ApiResponse::success(LsResponse { + uri: params.uri, + total, + entries, + }))) +} + +/// Recursively list directory contents (synchronous, runs in spawn_blocking) +fn list_directory_recursive( + base_path: &std::path::Path, + base_uri: &str, + recursive: bool, + include_abstracts: bool, + entries: &mut Vec, +) { + if !base_path.exists() || !base_path.is_dir() { + return; } - let mut entries = Vec::new(); - if let Ok(dir) = std::fs::read_dir(&base_path) { + if let Ok(dir) = std::fs::read_dir(base_path) { for entry in dir.flatten() { let name = entry.file_name().to_string_lossy().to_string(); - // Skip hidden files except .abstract.md and .overview.md - if name.starts_with('.') && name != ".abstract.md" && name != ".overview.md" { + + // Skip hidden files (layer files are accessed via dedicated endpoints) + if name.starts_with('.') { continue; } @@ -57,22 +92,38 @@ pub async fn list_directory( .map(|t| DateTime::::from(t)) .unwrap_or_else(|_| Utc::now()); - let entry_uri = format!("{}/{}", params.uri.trim_end_matches('/'), name); + let entry_uri = format!("{}/{}", base_uri.trim_end_matches('/'), name); + + // Load abstract if requested and this is a file + // All files in the same directory share the directory-level abstract + let abstract_text = if include_abstracts && !is_dir { + let abstract_path = base_path.join(".abstract.md"); + std::fs::read_to_string(&abstract_path).ok() + } else { + None + }; entries.push(FileEntryResponse { - uri: entry_uri, - name, + uri: entry_uri.clone(), + name: name.clone(), is_directory: is_dir, size, modified, + abstract_text, }); + + // Recurse into subdirectories if requested + if recursive && is_dir { + let sub_path = base_path.join(&name); + list_directory_recursive(&sub_path, &entry_uri, true, include_abstracts, entries); + } } } } - - Ok(Json(ApiResponse::success(entries))) } +// ==================== Read/Write File ==================== + /// Read file content pub async fn read_file( State(state): State>, @@ -86,9 +137,9 @@ pub async fn read_file( let uri_path = path.trim_start_matches("cortex://"); root.join(uri_path) } else { - let cortex_dir = state.data_dir.join("cortex"); + // 直接使用 data_dir 作为根目录(不再添加 cortex 子目录) let uri_path = path.trim_start_matches("cortex://"); - cortex_dir.join(uri_path) + state.data_dir.join(uri_path) }; tracing::debug!("Reading file: {:?}", base_path); @@ -103,7 +154,7 @@ pub async fn read_file( /// Write file content pub async fn write_file( State(state): State>, - Json(req): Json, + JsonExtractor(req): JsonExtractor, ) -> Result>> { // Get tenant root if set let tenant_root = state.current_tenant_root.read().await.clone(); @@ -113,9 +164,9 @@ pub async fn write_file( let uri_path = req.path.trim_start_matches("cortex://"); root.join(uri_path) } else { - let cortex_dir = state.data_dir.join("cortex"); + // 直接使用 data_dir 作为根目录(不再添加 cortex 子目录) let uri_path = req.path.trim_start_matches("cortex://"); - cortex_dir.join(uri_path) + state.data_dir.join(uri_path) }; tracing::debug!("Writing file: {:?}", base_path); @@ -134,6 +185,8 @@ pub async fn write_file( Ok(Json(ApiResponse::success(base_path.to_string_lossy().to_string()))) } +// ==================== Directory Stats ==================== + /// Get directory stats (recursive) pub async fn get_directory_stats( State(state): State>, @@ -147,19 +200,24 @@ pub async fn get_directory_stats( let uri_path = params.uri.trim_start_matches("cortex://"); root.join(uri_path) } else { - let cortex_dir = state.data_dir.join("cortex"); + // 直接使用 data_dir 作为根目录(不再添加 cortex 子目录) let uri_path = params.uri.trim_start_matches("cortex://"); - cortex_dir.join(uri_path) + state.data_dir.join(uri_path) }; tracing::debug!("Getting stats for: {:?}", base_path); - let (file_count, total_size) = count_files_recursive(&base_path) - .map_err(|e| AppError::Internal(e.to_string()))?; + // Use spawn_blocking for potentially slow recursive file counting + let stats = tokio::task::spawn_blocking(move || { + count_files_recursive(&base_path) + }) + .await + .map_err(|e| AppError::Internal(format!("Failed to get stats: {}", e)))? + .map_err(|e| AppError::Internal(e.to_string()))?; Ok(Json(ApiResponse::success(DirectoryStats { - file_count, - total_size, + file_count: stats.0, + total_size: stats.1, }))) } @@ -224,3 +282,297 @@ pub struct DirectoryStats { file_count: u64, total_size: u64, } + +// ==================== Layered Access ==================== + +/// Query for layered access endpoints +#[derive(Debug, Deserialize)] +pub struct LayerQuery { + uri: String, +} + +/// Response for layered access endpoints +#[derive(Debug, Serialize)] +pub struct LayerResponse { + pub uri: String, + pub content: String, + pub layer: String, + pub token_count: usize, +} + +/// Get L0 abstract layer (~100 tokens) for quick relevance checking +pub async fn get_abstract( + State(state): State>, + Query(params): Query, +) -> Result>> { + let (_base_path, layer_path) = resolve_layer_path(&state, ¶ms.uri, "abstract").await?; + + tracing::debug!("Reading abstract layer: {:?}", layer_path); + + let content = tokio::fs::read_to_string(&layer_path) + .await + .map_err(|e| AppError::Internal(format!("Abstract not found for '{}': {}", params.uri, e)))?; + + let token_count = content.split_whitespace().count(); + + Ok(Json(ApiResponse::success(LayerResponse { + uri: params.uri, + content, + layer: "L0".to_string(), + token_count, + }))) +} + +/// Get L1 overview layer (~2000 tokens) for understanding core information +pub async fn get_overview( + State(state): State>, + Query(params): Query, +) -> Result>> { + let (_base_path, layer_path) = resolve_layer_path(&state, ¶ms.uri, "overview").await?; + + tracing::debug!("Reading overview layer: {:?}", layer_path); + + let content = tokio::fs::read_to_string(&layer_path) + .await + .map_err(|e| AppError::Internal(format!("Overview not found for '{}': {}", params.uri, e)))?; + + let token_count = content.split_whitespace().count(); + + Ok(Json(ApiResponse::success(LayerResponse { + uri: params.uri, + content, + layer: "L1".to_string(), + token_count, + }))) +} + +/// Get L2 full content layer - complete original content +pub async fn get_content( + State(state): State>, + Query(params): Query, +) -> Result>> { + // Get tenant root if set + let tenant_root = state.current_tenant_root.read().await.clone(); + + // Build the path + let base_path = if let Some(root) = tenant_root { + let uri_path = params.uri.trim_start_matches("cortex://"); + root.join(uri_path) + } else { + // 直接使用 data_dir 作为根目录(不再添加 cortex 子目录) + let uri_path = params.uri.trim_start_matches("cortex://"); + state.data_dir.join(uri_path) + }; + + tracing::debug!("Reading content layer: {:?}", base_path); + + let content = tokio::fs::read_to_string(&base_path) + .await + .map_err(|e| AppError::Internal(format!("Content not found for '{}': {}", params.uri, e)))?; + + let token_count = content.split_whitespace().count(); + + Ok(Json(ApiResponse::success(LayerResponse { + uri: params.uri, + content, + layer: "L2".to_string(), + token_count, + }))) +} + +/// Resolve the path to a layer file (abstract or overview) +/// +/// For file URIs (ending with .md): layer file is in the same directory +/// For directory URIs: layer file is directly in that directory +async fn resolve_layer_path( + state: &AppState, + uri: &str, + layer_type: &str, +) -> Result<(std::path::PathBuf, std::path::PathBuf)> { + // Get tenant root if set + let tenant_root = state.current_tenant_root.read().await.clone(); + + // Determine if URI points to a file (ends with .md) or directory + let is_file = uri.ends_with(".md"); + + // Get the directory path + let dir_uri = if is_file { + uri.rsplit_once('/').map(|(dir, _)| dir).unwrap_or(uri) + } else { + uri + }; + + // Build the base path + let base_path = if let Some(root) = tenant_root { + let uri_path = dir_uri.trim_start_matches("cortex://"); + root.join(uri_path) + } else { + // 直接使用 data_dir 作为根目录(不再添加 cortex 子目录) + let uri_path = dir_uri.trim_start_matches("cortex://"); + state.data_dir.join(uri_path) + }; + + // Layer file name + let layer_file = format!(".{}.md", layer_type); + let layer_path = base_path.join(&layer_file); + + Ok((base_path, layer_path)) +} + +// ==================== Layer Loading Helper ==================== + +/// Load additional layers (L1 overview, L2 content) for a URI +/// Returns (overview, content, updated_layers) +pub async fn load_layers_for_uri( + base_dir: &std::path::Path, + uri: &str, + return_layers: &[String], +) -> (Option, Option, Vec) { + let mut overview = None; + let mut content = None; + let mut layers = vec!["L0".to_string()]; + + let is_file = uri.ends_with(".md"); + let uri_path = uri.trim_start_matches("cortex://"); + let file_path = base_dir.join(uri_path); + + let dir_path = if is_file { + file_path.parent().unwrap_or(&file_path).to_path_buf() + } else { + file_path.clone() + }; + + // Load L1 overview if requested + if return_layers.contains(&"L1".to_string()) { + let overview_path = dir_path.join(".overview.md"); + // Direct read without exists() check - single I/O operation + if let Ok(content) = tokio::fs::read_to_string(&overview_path).await { + overview = Some(content); + layers.push("L1".to_string()); + } + } + + // Load L2 content if requested + if return_layers.contains(&"L2".to_string()) && is_file { + // Direct read without exists() check - single I/O operation + if let Ok(file_content) = tokio::fs::read_to_string(&file_path).await { + content = Some(file_content); + layers.push("L2".to_string()); + } + } + + (overview, content, layers) +} + +/// Load abstract for a URI (single I/O operation) +pub async fn load_abstract_for_uri(base_dir: &std::path::Path, uri: &str) -> Option { + let is_file = uri.ends_with(".md"); + let uri_path = uri.trim_start_matches("cortex://"); + let file_path = base_dir.join(uri_path); + + let dir_path = if is_file { + file_path.parent()? + } else { + &file_path + }; + + let abstract_path = dir_path.join(".abstract.md"); + // Direct read without exists() check - single I/O operation + tokio::fs::read_to_string(&abstract_path).await.ok() +} + +// ==================== Explore ==================== + +/// Smart exploration of memory space, combining search and browsing +pub async fn explore( + State(state): State>, + JsonExtractor(req): JsonExtractor, +) -> Result>> { + use cortex_mem_core::SearchOptions; + + // Check if vector engine is available + let vector_engine_lock = state.vector_engine.read().await; + let vector_engine = vector_engine_lock.as_ref().ok_or_else(|| { + AppError::BadRequest("Vector search not available. Qdrant and Embedding service must be configured.".to_string()) + })?; + + // Get tenant root + let tenant_root = state.current_tenant_root.read().await.clone(); + let base_dir = if let Some(ref root) = tenant_root { + root.clone() + } else { + // 直接使用 data_dir 作为根目录(不再添加 cortex 子目录) + state.data_dir.clone() + }; + + // Perform search within the start_uri scope + let options = SearchOptions { + limit: 20, + threshold: 0.3, // Lower threshold for exploration + root_uri: Some(req.start_uri.clone()), + recursive: true, + }; + + let search_results = vector_engine + .layered_semantic_search(&req.query, &options) + .await + .map_err(|e| AppError::Internal(format!("Explore search failed: {}", e)))?; + + // Build exploration path and matches + let mut exploration_path = Vec::new(); + let mut matches = Vec::new(); + let mut explored_uris = std::collections::HashSet::new(); + + for result in search_results { + // Add to exploration path + if !explored_uris.contains(&result.uri) { + // For files: use snippet as abstract (it's already a relevant excerpt) + // For directories: load the directory's .abstract.md + let abstract_text = if result.uri.ends_with(".md") { + // File-level result: snippet is the relevant content excerpt + Some(result.snippet.clone()) + } else { + // Directory-level result: load directory's abstract + load_abstract_for_uri(&base_dir, &result.uri).await + }; + + exploration_path.push(ExplorationPathItem { + uri: result.uri.clone(), + relevance_score: result.score, + abstract_text, + }); + explored_uris.insert(result.uri.clone()); + } + + // Build match result with requested layers + let snippet = if result.snippet.len() > 200 { + format!("{}...", &result.snippet.chars().take(200).collect::()) + } else { + result.snippet + }; + + // Use shared helper to load layers + let (overview, content, layers) = load_layers_for_uri(&base_dir, &result.uri, &req.return_layers).await; + + matches.push(SearchResultResponse { + uri: result.uri, + score: result.score, + snippet, + overview, + content, + source: "explore".to_string(), + layers, + }); + } + + let total_explored = exploration_path.len(); + let total_matches = matches.len(); + + Ok(Json(ApiResponse::success(ExploreResponse { + query: req.query, + exploration_path, + matches, + total_explored, + total_matches, + }))) +} \ No newline at end of file diff --git a/cortex-mem-service/src/handlers/search.rs b/cortex-mem-service/src/handlers/search.rs index b6d525a..f06be8d 100644 --- a/cortex-mem-service/src/handlers/search.rs +++ b/cortex-mem-service/src/handlers/search.rs @@ -6,6 +6,7 @@ use crate::{ models::{ApiResponse, SearchRequest, SearchResultResponse}, state::AppState, }; +use crate::handlers::filesystem::load_layers_for_uri; /// Search endpoint using layered vector search (L0/L1/L2) pub async fn search( @@ -14,8 +15,16 @@ pub async fn search( ) -> Result>>> { let limit = req.limit.unwrap_or(10); let min_score = req.min_score.unwrap_or(0.6); + let return_layers = req.return_layers.clone(); - let results = search_layered(&state, &req.query, req.thread.as_deref(), limit, min_score).await?; + let results = search_layered( + &state, + &req.query, + req.thread.as_deref(), + limit, + min_score, + &return_layers, + ).await?; Ok(Json(ApiResponse::success(results))) } @@ -30,6 +39,7 @@ async fn search_layered( thread: Option<&str>, limit: usize, min_score: f32, + return_layers: &[String], ) -> Result> { use cortex_mem_core::SearchOptions; @@ -58,25 +68,37 @@ async fn search_layered( .await .map_err(|e| AppError::Internal(format!("Layered search failed: {}", e)))?; - // Convert to response format - let results: Vec = search_results - .into_iter() - .map(|result| { - let snippet = if result.snippet.len() > 200 { - format!("{}...", &result.snippet.chars().take(200).collect::()) - } else { - result.snippet - }; + // Get tenant root for layer loading + let tenant_root = state.current_tenant_root.read().await.clone(); + let base_dir = if let Some(ref root) = tenant_root { + root.clone() + } else { + // 直接使用 data_dir 作为根目录(不再添加 cortex 子目录) + state.data_dir.clone() + }; + + // Convert to response format with requested layers + let mut results = Vec::new(); + for result in search_results { + let snippet = if result.snippet.len() > 200 { + format!("{}...", &result.snippet.chars().take(200).collect::()) + } else { + result.snippet + }; - SearchResultResponse { - uri: result.uri, - score: result.score, - snippet, - content: result.content, - source: "layered_vector".to_string(), - } - }) - .collect(); + // Use shared helper to load layers + let (overview, content, layers) = load_layers_for_uri(&base_dir, &result.uri, return_layers).await; + + results.push(SearchResultResponse { + uri: result.uri, + score: result.score, + snippet, + overview, + content, + source: "layered_vector".to_string(), + layers, + }); + } Ok(results) -} +} \ No newline at end of file diff --git a/cortex-mem-service/src/handlers/sessions.rs b/cortex-mem-service/src/handlers/sessions.rs index de3e39b..5826cd6 100644 --- a/cortex-mem-service/src/handlers/sessions.rs +++ b/cortex-mem-service/src/handlers/sessions.rs @@ -64,7 +64,8 @@ pub async fn list_sessions( let session_path = if let Some(root) = tenant_root { root.join("session") } else { - state.data_dir.join("cortex").join("session") + // 直接使用 data_dir 作为根目录(不再添加 cortex 子目录) + state.data_dir.join("session") }; tracing::debug!("Listing sessions from: {:?}", session_path); diff --git a/cortex-mem-service/src/main.rs b/cortex-mem-service/src/main.rs index d98b24c..65fee8d 100644 --- a/cortex-mem-service/src/main.rs +++ b/cortex-mem-service/src/main.rs @@ -1,7 +1,9 @@ use axum::{Router, routing::get}; use clap::Parser; +use std::fs::File; use std::net::SocketAddr; -use std::sync::Arc; +use std::path::PathBuf; +use std::sync::{Arc, Mutex}; use tower_http::cors::CorsLayer; use tower_http::trace::TraceLayer; use tracing::{info, level_filters::LevelFilter}; @@ -35,6 +37,10 @@ struct Cli { /// Enable verbose logging #[arg(short, long)] verbose: bool, + + /// Log file path. When specified, logs will be written to both file and stdout + #[arg(long, value_name = "PATH")] + log_file: Option, } #[tokio::main] @@ -48,14 +54,41 @@ async fn main() -> anyhow::Result<()> { LevelFilter::INFO }; - tracing_subscriber::registry() - .with( - tracing_subscriber::fmt::layer() - .with_target(false) - .with_level(true), - ) - .with(log_level) - .init(); + // Setup logging layers + let stdout_layer = tracing_subscriber::fmt::layer() + .with_target(false) + .with_level(true); + + if let Some(ref log_path) = cli.log_file { + // Ensure parent directory exists + if let Some(parent) = log_path.parent() { + std::fs::create_dir_all(parent)?; + } + + // Create log file + let log_file = File::create(log_path)?; + let file_writer = Mutex::new(log_file); + + // File layer (no colors, includes target for debugging) + let file_layer = tracing_subscriber::fmt::layer() + .with_target(true) + .with_level(true) + .with_ansi(false) + .with_writer(file_writer); + + tracing_subscriber::registry() + .with(stdout_layer) + .with(file_layer) + .with(log_level) + .init(); + + info!("Logging to file: {}", log_path.display()); + } else { + tracing_subscriber::registry() + .with(stdout_layer) + .with(log_level) + .init(); + } info!("Starting Cortex Memory Service"); info!("Data directory: {}", cli.data_dir); diff --git a/cortex-mem-service/src/models.rs b/cortex-mem-service/src/models.rs index 5e11200..19e0792 100644 --- a/cortex-mem-service/src/models.rs +++ b/cortex-mem-service/src/models.rs @@ -29,6 +29,9 @@ pub struct FileEntryResponse { pub is_directory: bool, pub size: u64, pub modified: DateTime, + /// L0 abstract text (only included when include_abstracts=true) + #[serde(skip_serializing_if = "Option::is_none")] + pub abstract_text: Option, } impl From for FileEntryResponse { @@ -39,6 +42,7 @@ impl From for FileEntryResponse { is_directory: entry.is_directory, size: entry.size, modified: entry.modified, + abstract_text: None, } } } @@ -58,6 +62,12 @@ pub struct SessionResponse { pub struct AddMessageRequest { pub role: String, pub content: String, + /// Optional metadata (tags, importance, etc.) + /// Note: Currently accepted but not processed by the backend. + /// Reserved for future enhancement. + #[serde(default)] + #[allow(dead_code)] + pub metadata: Option, } /// Search request @@ -67,6 +77,14 @@ pub struct SearchRequest { pub thread: Option, pub limit: Option, pub min_score: Option, + /// Which layers to return: ["L0"], ["L0","L1"], ["L0","L1","L2"] + /// Default: ["L0"] (only snippets) + #[serde(default = "default_return_layers")] + pub return_layers: Vec, +} + +fn default_return_layers() -> Vec { + vec!["L0".to_string()] } /// Search result response @@ -74,7 +92,79 @@ pub struct SearchRequest { pub struct SearchResultResponse { pub uri: String, pub score: f32, + /// L0 abstract/snippet pub snippet: String, + /// L1 overview text (only when return_layers contains "L1") + #[serde(skip_serializing_if = "Option::is_none")] + pub overview: Option, + /// L2 full content (only when return_layers contains "L2") + #[serde(skip_serializing_if = "Option::is_none")] pub content: Option, pub source: String, + /// Which layers are included in this result + pub layers: Vec, +} + +/// List directory request +#[derive(Debug, Deserialize)] +pub struct LsRequest { + /// Directory URI to list + #[serde(default = "default_uri")] + pub uri: String, + /// Whether to recursively list subdirectories + #[serde(default)] + pub recursive: bool, + /// Whether to include L0 abstracts for files + #[serde(default)] + pub include_abstracts: bool, +} + +fn default_uri() -> String { + "cortex://session".to_string() +} + +/// List directory response +#[derive(Debug, Serialize)] +pub struct LsResponse { + pub uri: String, + pub total: usize, + pub entries: Vec, +} + +/// Explore request +#[derive(Debug, Deserialize)] +pub struct ExploreRequest { + pub query: String, + /// Starting URI for exploration + #[serde(default = "default_explore_start")] + pub start_uri: String, + /// Which layers to return in matches + #[serde(default = "default_return_layers")] + pub return_layers: Vec, +} + +fn default_explore_start() -> String { + "cortex://session".to_string() +} + +/// Explore response +#[derive(Debug, Serialize)] +pub struct ExploreResponse { + pub query: String, + /// Path taken during exploration + pub exploration_path: Vec, + /// Matching results found + pub matches: Vec, + /// Total items explored + pub total_explored: usize, + /// Total matches found + pub total_matches: usize, +} + +/// Item in exploration path +#[derive(Debug, Serialize)] +pub struct ExplorationPathItem { + pub uri: String, + pub relevance_score: f32, + pub abstract_text: Option, } diff --git a/cortex-mem-service/src/routes/filesystem.rs b/cortex-mem-service/src/routes/filesystem.rs index d458f84..84fee69 100644 --- a/cortex-mem-service/src/routes/filesystem.rs +++ b/cortex-mem-service/src/routes/filesystem.rs @@ -11,4 +11,10 @@ pub fn routes() -> Router> { .route("/read/*path", get(crate::handlers::filesystem::read_file)) .route("/write", post(crate::handlers::filesystem::write_file)) .route("/stats", get(crate::handlers::filesystem::get_directory_stats)) + // Layered access routes (L0/L1/L2) + .route("/abstract", get(crate::handlers::filesystem::get_abstract)) + .route("/overview", get(crate::handlers::filesystem::get_overview)) + .route("/content", get(crate::handlers::filesystem::get_content)) + // Smart exploration + .route("/explore", post(crate::handlers::filesystem::explore)) } diff --git a/cortex-mem-service/src/state.rs b/cortex-mem-service/src/state.rs index 6e1383b..790a305 100644 --- a/cortex-mem-service/src/state.rs +++ b/cortex-mem-service/src/state.rs @@ -50,7 +50,8 @@ impl AppState { // 使用Cortex MemoryBuilder统一初始化 tracing::info!("Initializing Cortex Memory with unified automation..."); - let cortex_dir = data_dir.join("cortex"); + // 直接使用 data_dir 作为根目录(不再添加 cortex 子目录) + let cortex_dir = data_dir.clone(); // 获取配置(优先从config.toml,否则从环境变量) let (llm_client, embedding_config, qdrant_config) = Self::load_configs()?; @@ -275,20 +276,15 @@ impl AppState { /// List all available tenants pub async fn list_tenants(&self) -> Vec { - // Try both possible tenant locations - let possible_paths = vec![ - self.data_dir.join("tenants"), - self.data_dir.join("cortex").join("tenants"), - ]; + // 租户目录位于 data_dir/tenants/ + let tenants_path = self.data_dir.join("tenants"); let mut tenants = vec![]; - for tenants_path in possible_paths { - if tenants_path.exists() { - if let Ok(entries) = std::fs::read_dir(&tenants_path) { - for entry in entries.flatten() { - if entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false) { - tenants.push(entry.file_name().to_string_lossy().to_string()); - } + if tenants_path.exists() { + if let Ok(entries) = std::fs::read_dir(&tenants_path) { + for entry in entries.flatten() { + if entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false) { + tenants.push(entry.file_name().to_string_lossy().to_string()); } } } @@ -300,33 +296,20 @@ impl AppState { /// Switch to a different tenant /// Recreates VectorSearchEngine with tenant-specific collection pub async fn switch_tenant(&self, tenant_id: &str) -> anyhow::Result<()> { - // Try both possible tenant locations - let possible_paths = vec![ - self.data_dir.join("tenants").join(tenant_id), - self.data_dir.join("cortex").join("tenants").join(tenant_id), - ]; - - let mut tenant_root = None; - for path in possible_paths { - if path.exists() { - tenant_root = Some(path); - break; - } - } + // 租户目录直接位于 data_dir/tenants/{tenant_id} + let tenant_root_path = self.data_dir.join("tenants").join(tenant_id); - // Auto-provision: if tenant doesn't exist, create it under cortex/tenants/ - let tenant_root = match tenant_root { - Some(p) => p, - None => { - let new_tenant_root = self.data_dir.join("cortex").join("tenants").join(tenant_id); - tracing::info!("Tenant {} not found, auto-provisioning at {:?}", tenant_id, new_tenant_root); - for subdir in &["agent", "resources", "session", "user"] { - std::fs::create_dir_all(new_tenant_root.join(subdir)) - .map_err(|e| anyhow::anyhow!("Failed to create tenant dir: {}", e))?; - } - tracing::info!("✅ Tenant {} auto-provisioned successfully", tenant_id); - new_tenant_root + let tenant_root = if tenant_root_path.exists() { + tenant_root_path + } else { + // Auto-provision: 如果租户不存在,在 data_dir/tenants/ 下创建 + tracing::info!("Tenant {} not found, auto-provisioning at {:?}", tenant_id, tenant_root_path); + for subdir in &["agent", "resources", "session", "user"] { + std::fs::create_dir_all(tenant_root_path.join(subdir)) + .map_err(|e| anyhow::anyhow!("Failed to create tenant dir: {}", e))?; } + tracing::info!("✅ Tenant {} auto-provisioned successfully", tenant_id); + tenant_root_path }; // Update current tenant root diff --git a/examples/@memclaw/bin-darwin-arm64/bin/cortex-mem-cli b/examples/@memclaw/bin-darwin-arm64/bin/cortex-mem-cli index 1ce137e..62d209d 100755 --- a/examples/@memclaw/bin-darwin-arm64/bin/cortex-mem-cli +++ b/examples/@memclaw/bin-darwin-arm64/bin/cortex-mem-cli @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b15bd57c2165fb884c0cf88dd53cd737b09408fd4e7b23b07b8cf3ce4e34dd8d -size 18292816 +oid sha256:1a305c8ed4e883a2dc9840539e7dc9aa1bbaf23c3ec3c8e1133517b7d62b8358 +size 18277056 diff --git a/examples/@memclaw/bin-darwin-arm64/bin/cortex-mem-service b/examples/@memclaw/bin-darwin-arm64/bin/cortex-mem-service index fb8deea..076f725 100755 --- a/examples/@memclaw/bin-darwin-arm64/bin/cortex-mem-service +++ b/examples/@memclaw/bin-darwin-arm64/bin/cortex-mem-service @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c4bdc7455b025b170325967d559ba10a652bb09eb462443cd29cd81696264c5a -size 17431216 +oid sha256:5973dc419567ad09a59aa4c64d559a35bc6bd84286f9acb739a10963ce66c319 +size 17667392 diff --git a/examples/@memclaw/bin-darwin-arm64/package.json b/examples/@memclaw/bin-darwin-arm64/package.json index 0131c7e..d502985 100644 --- a/examples/@memclaw/bin-darwin-arm64/package.json +++ b/examples/@memclaw/bin-darwin-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@memclaw/bin-darwin-arm64", - "version": "0.1.0", + "version": "0.1.5", "description": "MemClaw binaries for macOS Apple Silicon", "publishConfig": { "access": "public" @@ -18,7 +18,7 @@ "license": "MIT", "repository": { "type": "git", - "url": "https://github.com/sopaco/cortex-mem.git", + "url": "git+https://github.com/sopaco/cortex-mem.git", "directory": "examples/@memclaw/bin-darwin-arm64" } } diff --git a/examples/@memclaw/bin-linux-x64/.gitattributes b/examples/@memclaw/bin-linux-x64/.gitattributes new file mode 100644 index 0000000..ca2fc43 --- /dev/null +++ b/examples/@memclaw/bin-linux-x64/.gitattributes @@ -0,0 +1 @@ +bin/* filter=lfs diff=lfs merge=lfs -text diff --git a/examples/@memclaw/bin-linux-x64/.gitignore b/examples/@memclaw/bin-linux-x64/.gitignore new file mode 100644 index 0000000..91cda48 --- /dev/null +++ b/examples/@memclaw/bin-linux-x64/.gitignore @@ -0,0 +1,5 @@ +# Dependencies +node_modules/ + +# Build artifacts +*.tsbuildinfo diff --git a/examples/@memclaw/bin-linux-x64/bin/README.md b/examples/@memclaw/bin-linux-x64/bin/README.md new file mode 100644 index 0000000..3c062a8 --- /dev/null +++ b/examples/@memclaw/bin-linux-x64/bin/README.md @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:be1f882d79722f7ec7a2f43dac9e0d62377c508046503c4432f71840ca3dc684 +size 722 diff --git a/examples/@memclaw/bin-linux-x64/bin/cortex-mem-cli b/examples/@memclaw/bin-linux-x64/bin/cortex-mem-cli new file mode 100755 index 0000000..cca4221 --- /dev/null +++ b/examples/@memclaw/bin-linux-x64/bin/cortex-mem-cli @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bcfdb31c32dd8472f6b9a58af4f97ade4de693b0b5ebdc4f508928a249f5a75d +size 21696936 diff --git a/examples/@memclaw/bin-linux-x64/bin/cortex-mem-service b/examples/@memclaw/bin-linux-x64/bin/cortex-mem-service new file mode 100755 index 0000000..39afd1e --- /dev/null +++ b/examples/@memclaw/bin-linux-x64/bin/cortex-mem-service @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e6f7192f4b4cc1a556df88709265bdf54dc96b41fce86cb0cf2ee1bdeab011b +size 20962176 diff --git a/examples/@memclaw/bin-linux-x64/bin/qdrant b/examples/@memclaw/bin-linux-x64/bin/qdrant new file mode 100755 index 0000000..19d7bad --- /dev/null +++ b/examples/@memclaw/bin-linux-x64/bin/qdrant @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:81a2f53592b6561bd1399ee219d1b853a528448fbe2be0515d2ebad1c953ef45 +size 78777440 diff --git a/examples/@memclaw/bin-linux-x64/package.json b/examples/@memclaw/bin-linux-x64/package.json new file mode 100644 index 0000000..5d2e725 --- /dev/null +++ b/examples/@memclaw/bin-linux-x64/package.json @@ -0,0 +1,24 @@ +{ + "name": "@memclaw/bin-linux-x64", + "version": "0.1.5", + "description": "MemClaw binaries for Linux x64", + "publishConfig": { + "access": "public" + }, + "os": [ + "linux" + ], + "cpu": [ + "x64" + ], + "files": [ + "bin/" + ], + "author": "Sopaco", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/sopaco/cortex-mem.git", + "directory": "examples/@memclaw/bin-linux-x64" + } +} diff --git a/examples/@memclaw/bin-win-x64/package.json b/examples/@memclaw/bin-win-x64/package.json index 9619c88..e7e38ab 100644 --- a/examples/@memclaw/bin-win-x64/package.json +++ b/examples/@memclaw/bin-win-x64/package.json @@ -18,7 +18,7 @@ "license": "MIT", "repository": { "type": "git", - "url": "https://github.com/sopaco/cortex-mem.git", + "url": "git+https://github.com/sopaco/cortex-mem.git", "directory": "examples/@memclaw/bin-win-x64" } } diff --git a/examples/@memclaw/plugin/README.md b/examples/@memclaw/plugin/README.md index af76132..0b2b40c 100644 --- a/examples/@memclaw/plugin/README.md +++ b/examples/@memclaw/plugin/README.md @@ -16,7 +16,7 @@ MemClaw is an OpenClaw plugin that provides advanced semantic memory capabilitie - **Session Management**: Create, list, and close memory sessions - **Migration Support**: One-click migration from OpenClaw native memory - **Easy Configuration**: Configure LLM/Embedding directly through OpenClaw plugin settings -- **Cross-Platform**: Supports Windows x64 and macOS Apple Silicon +- **Cross-Platform**: Supports Windows x64, macOS Apple Silicon, and Linux x64 ## Architecture @@ -35,12 +35,17 @@ The search engine queries all three layers internally and returns unified result ``` OpenClaw + MemClaw Plugin │ - ├── cortex_search → Search memories - ├── cortex_recall → Recall with context - ├── cortex_add_memory → Store memories - ├── cortex_list_sessions → List sessions - ├── cortex_close_session → Close & extract - └── cortex_migrate → Migrate existing memory + ├── cortex_search → Layered semantic search + ├── cortex_recall → Recall with context + ├── cortex_add_memory → Store memories + ├── cortex_commit_session → Commit & extract + ├── cortex_migrate → Migrate existing memory + ├── cortex_maintenance → Periodic maintenance + ├── cortex_ls → Browse memory filesystem + ├── cortex_get_abstract → L0 quick preview + ├── cortex_get_overview → L1 moderate detail + ├── cortex_get_content → L2 full content + └── cortex_explore → Smart exploration │ ▼ cortex-mem-service (port 8085) @@ -55,7 +60,7 @@ OpenClaw + MemClaw Plugin | Requirement | Details | |-------------|---------| -| **Platforms** | Windows x64, macOS Apple Silicon | +| **Platforms** | Windows x64, macOS Apple Silicon, Linux x64 | | **Node.js** | ≥ 20.0.0 | | **OpenClaw** | Installed and configured | @@ -185,16 +190,22 @@ You can also configure the plugin through OpenClaw UI: ### cortex_search -Semantic search across all memories using L0/L1/L2 tiered retrieval. +Layered semantic search with fine-grained control over returned content. + +**Key Parameters:** +- `return_layers`: `["L0"]` (default, ~100 tokens), `["L0","L1"]` (~2100 tokens), `["L0","L1","L2"]` (full) ```json { "query": "database architecture decisions", "limit": 5, - "min_score": 0.6 + "min_score": 0.6, + "return_layers": ["L0"] } ``` +For more context, use `return_layers: ["L0","L1"]`. For full content, use `["L0","L1","L2"]`. + ### cortex_recall Recall memories with more context (snippet + full content). @@ -208,23 +219,31 @@ Recall memories with more context (snippet + full content). ### cortex_add_memory -Store a message for future retrieval. +Store a message for future retrieval with optional metadata. ```json { "content": "User prefers TypeScript with strict mode", "role": "assistant", - "session_id": "default" + "session_id": "default", + "metadata": { + "tags": ["preference", "typescript"], + "importance": "high" + } } ``` -### cortex_list_sessions +**Parameters:** +- `content`: The message content (required) +- `role`: `"user"`, `"assistant"`, or `"system"` (default: user) +- `session_id`: Session/thread ID (uses default if not specified) +- `metadata`: Optional metadata like tags, importance, or custom fields -List all memory sessions with status and message count. -### cortex_close_session -Close a session and trigger memory extraction pipeline (takes 30-60 seconds). +### cortex_commit_session + +Commit a session and trigger memory extraction pipeline (takes 30-60 seconds). ```json { @@ -234,6 +253,79 @@ Close a session and trigger memory extraction pipeline (takes 30-60 seconds). > **Important**: Call this tool proactively at natural checkpoints, not just when the conversation ends. Ideal timing: after completing important tasks, topic transitions, or accumulating enough conversation content. +### cortex_ls + +List directory contents to browse the memory space like a virtual filesystem. + +```json +{ + "uri": "cortex://session", + "recursive": false, + "include_abstracts": false +} +``` + +**Parameters:** +- `uri`: Directory URI to list (default: `cortex://session`) +- `recursive`: List all subdirectories recursively +- `include_abstracts`: Show L0 abstracts for quick preview + +**Common URIs:** +- `cortex://session` - List all sessions +- `cortex://session/{session_id}` - Browse a specific session +- `cortex://session/{session_id}/timeline` - View timeline messages +- `cortex://session/{session_id}/memories` - View extracted memories + +### cortex_get_abstract + +Get L0 abstract layer (~100 tokens) for quick relevance checking. + +```json +{ + "uri": "cortex://session/abc123/timeline/2024-01-15_001.md" +} +``` + +Use this to quickly determine if content is relevant before reading more. + +### cortex_get_overview + +Get L1 overview layer (~2000 tokens) with core information and context. + +```json +{ + "uri": "cortex://session/abc123/timeline/2024-01-15_001.md" +} +``` + +Use when you need more detail than the abstract but not the full content. + +### cortex_get_content + +Get L2 full content layer - the complete original content. + +```json +{ + "uri": "cortex://session/abc123/timeline/2024-01-15_001.md" +} +``` + +Use only when you need the complete, unprocessed content. + +### cortex_explore + +Smart exploration combining search and browsing for guided discovery. + +```json +{ + "query": "authentication flow", + "start_uri": "cortex://session", + "return_layers": ["L0"] +} +``` + +Returns an exploration path with relevance scores and matching results. + ### cortex_migrate Migrate from OpenClaw native memory to MemClaw. Run once during initial setup. @@ -242,15 +334,54 @@ Migrate from OpenClaw native memory to MemClaw. Run once during initial setup. Perform periodic maintenance on MemClaw data (prune, reindex, ensure-all layers). +```json +{ + "dryRun": false, + "commands": ["prune", "reindex", "ensure-all"] +} +``` + +**Parameters:** +- `dryRun`: Preview changes without executing (default: false) +- `commands`: Which maintenance commands to run (default: all) + +This tool runs automatically every 3 hours. Call manually when search results seem incomplete or stale. + ## Quick Decision Flow +``` +┌─────────────────────────────────────────────────────────────────┐ +│ How to Access Memories │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Do you know WHERE the information is? │ +│ │ │ +│ ├── YES ──► Use Direct Tiered Access │ +│ │ cortex_ls → cortex_get_abstract/overview/content│ +│ │ │ +│ └── NO ──► Do you know WHAT you're looking for? │ +│ │ │ +│ ├── YES ──► Use Semantic Search │ +│ │ cortex_search │ +│ │ │ +│ └── NO ──► Use Exploration │ +│ cortex_explore │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + | Scenario | Tool | |----------|------| -| Need to find information | `cortex_search` | -| Need more context | `cortex_recall` | +| Find information across all sessions | `cortex_search` | +| Browse memory structure | `cortex_ls` | +| Quick relevance check for URI | `cortex_get_abstract` | +| Get more details on relevant URI | `cortex_get_overview` | +| Need exact full content | `cortex_get_content` | +| Explore with purpose | `cortex_explore` | | Save important information | `cortex_add_memory` | -| Complete a task/topic | `cortex_close_session` | +| Complete a task/topic | `cortex_commit_session` | | First-time use with existing memories | `cortex_migrate` | +| Data maintenance | `cortex_maintenance` | For detailed guidance on tool selection, session lifecycle, and best practices, see the [Skills Documentation](skills/memclaw/SKILL.md). @@ -258,22 +389,12 @@ For detailed guidance on tool selection, session lifecycle, and best practices, ### Plugin Not Working -1. **Check Configuration**: Open OpenClaw settings and verify MemClaw plugin configuration, especially LLM and Embedding settings -2. **Restart OpenClaw Gateway**: Configuration changes require a gateway restart to take effect -3. **Verify Services**: Run `cortex_list_sessions` to check if the service is responding - ### Services Won't Start 1. Check that ports 6333, 6334, 8085 are available 2. Verify LLM and Embedding credentials are configured correctly 3. Run `openclaw skills` to check plugin status -### Search Returns No Results - -1. Run `cortex_list_sessions` to verify sessions exist -2. Lower `min_score` threshold (default: 0.6) -3. Ensure memories have been stored (run `cortex_close_session` to extract memories) - ### Migration Fails 1. Ensure OpenClaw workspace exists at `~/.openclaw/workspace` diff --git a/examples/@memclaw/plugin/README_zh.md b/examples/@memclaw/plugin/README_zh.md index 5ba1a03..fe42619 100644 --- a/examples/@memclaw/plugin/README_zh.md +++ b/examples/@memclaw/plugin/README_zh.md @@ -16,7 +16,7 @@ MemClaw 是一个 OpenClaw 插件,利用 Cortex Memory 的分层记忆架构 - **会话管理**:创建、列出和关闭记忆会话 - **迁移支持**:一键从 OpenClaw 原生记忆迁移 - **便捷配置**:直接通过 OpenClaw 插件设置配置 LLM/Embedding -- **跨平台**:支持 Windows x64 和 macOS Apple Silicon +- **跨平台**:支持 Windows x64、macOS Apple Silicon 和 Linux x64 ## 架构 @@ -35,12 +35,17 @@ MemClaw 是一个 OpenClaw 插件,利用 Cortex Memory 的分层记忆架构 ``` OpenClaw + MemClaw Plugin │ - ├── cortex_search → 搜索记忆 - ├── cortex_recall → 召回上下文 - ├── cortex_add_memory → 存储记忆 - ├── cortex_list_sessions → 列出会话 - ├── cortex_close_session → 关闭并提取 - └── cortex_migrate → 迁移现有记忆 + ├── cortex_search → 分层语义搜索 + ├── cortex_recall → 召回上下文 + ├── cortex_add_memory → 存储记忆 + ├── cortex_commit_session → 提交并提取 + ├── cortex_migrate → 迁移现有记忆 + ├── cortex_maintenance → 定期维护 + ├── cortex_ls → 浏览记忆文件系统 + ├── cortex_get_abstract → L0 快速预览 + ├── cortex_get_overview → L1 中等详情 + ├── cortex_get_content → L2 完整内容 + └── cortex_explore → 智能探索 │ ▼ cortex-mem-service (端口 8085) @@ -185,16 +190,22 @@ ln -sf "$(pwd)" ~/.openclaw/extensions/memclaw ### cortex_search -使用 L0/L1/L2 三层检索在所有记忆中进行语义搜索。 +分层语义搜索,支持精细控制返回内容。 + +**关键参数:** +- `return_layers`: `["L0"]` (默认,约 100 tokens), `["L0","L1"]` (约 2100 tokens), `["L0","L1","L2"]` (完整内容) ```json { "query": "数据库架构决策", "limit": 5, - "min_score": 0.6 + "min_score": 0.6, + "return_layers": ["L0"] } ``` +如需更多上下文,使用 `return_layers: ["L0","L1"]`。如需完整内容,使用 `["L0","L1","L2"]`。 + ### cortex_recall 召回带有更多上下文的记忆(摘要 + 完整内容)。 @@ -208,23 +219,29 @@ ln -sf "$(pwd)" ~/.openclaw/extensions/memclaw ### cortex_add_memory -存储消息以供后续检索。 +存储消息以供后续检索,支持可选的元数据。 ```json { "content": "用户偏好 TypeScript 严格模式", "role": "assistant", - "session_id": "default" + "session_id": "default", + "metadata": { + "tags": ["preference", "typescript"], + "importance": "high" + } } ``` -### cortex_list_sessions +**参数说明:** +- `content`: 消息内容(必填) +- `role`: `"user"`、`"assistant"` 或 `"system"`(默认:user) +- `session_id`: 会话/线程 ID(不指定则使用默认值) +- `metadata`: 可选元数据,如标签、重要性或自定义字段 -列出所有记忆会话及其状态和消息数量。 +### cortex_commit_session -### cortex_close_session - -关闭会话并触发记忆提取管道(耗时 30-60 秒)。 +提交会话并触发记忆提取管道(耗时 30-60 秒)。 ```json { @@ -234,6 +251,79 @@ ln -sf "$(pwd)" ~/.openclaw/extensions/memclaw > **重要提示**:请在自然的检查点主动调用此工具,不要等到对话结束。理想时机:完成重要任务后、话题转换时、或积累足够对话内容后。 +### cortex_ls + +列出目录内容,像浏览虚拟文件系统一样浏览记忆空间。 + +```json +{ + "uri": "cortex://session", + "recursive": false, + "include_abstracts": false +} +``` + +**参数说明:** +- `uri`: 要列出的目录 URI(默认:`cortex://session`) +- `recursive`: 是否递归列出子目录 +- `include_abstracts`: 是否显示 L0 摘要以快速预览 + +**常用 URI:** +- `cortex://session` - 列出所有会话 +- `cortex://session/{session_id}` - 浏览特定会话 +- `cortex://session/{session_id}/timeline` - 查看时间线消息 +- `cortex://session/{session_id}/memories` - 查看提取的记忆 + +### cortex_get_abstract + +获取 L0 摘要层(约 100 tokens),用于快速相关性检查。 + +```json +{ + "uri": "cortex://session/abc123/timeline/2024-01-15_001.md" +} +``` + +用于在阅读更多内容前快速判断内容是否相关。 + +### cortex_get_overview + +获取 L1 概览层(约 2000 tokens),包含核心信息和上下文。 + +```json +{ + "uri": "cortex://session/abc123/timeline/2024-01-15_001.md" +} +``` + +当摘要不够详细但不需要完整内容时使用。 + +### cortex_get_content + +获取 L2 完整内容层 - 完整的原始内容。 + +```json +{ + "uri": "cortex://session/abc123/timeline/2024-01-15_001.md" +} +``` + +仅在需要完整、未处理的内容时使用。 + +### cortex_explore + +智能探索,结合搜索和浏览进行引导式发现。 + +```json +{ + "query": "认证流程", + "start_uri": "cortex://session", + "return_layers": ["L0"] +} +``` + +返回带有相关性分数的探索路径和匹配结果。 + ### cortex_migrate 从 OpenClaw 原生记忆迁移到 MemClaw。初始设置时运行一次即可。 @@ -242,15 +332,54 @@ ln -sf "$(pwd)" ~/.openclaw/extensions/memclaw 对 MemClaw 数据执行定期维护(清理、重建索引、确保所有层级生成)。 +```json +{ + "dryRun": false, + "commands": ["prune", "reindex", "ensure-all"] +} +``` + +**参数说明:** +- `dryRun`: 预览更改但不执行(默认:false) +- `commands`: 要运行的维护命令(默认:全部) + +此工具每 3 小时自动运行一次。当搜索结果不完整或过时时可手动调用。 + ## 快速决策流程 +``` +┌─────────────────────────────────────────────────────────────────┐ +│ 如何访问记忆 │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ 你知道信息在哪里吗? │ +│ │ │ +│ ├── 是 ──► 使用直接分层访问 │ +│ │ cortex_ls → cortex_get_abstract/overview/content│ +│ │ │ +│ └── 否 ──► 你知道在找什么吗? │ +│ │ │ +│ ├── 是 ──► 使用语义搜索 │ +│ │ cortex_search │ +│ │ │ +│ └── 否 ──► 使用智能探索 │ +│ cortex_explore │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + | 场景 | 工具 | |------|------| -| 需要查找信息 | `cortex_search` | -| 需要更多上下文 | `cortex_recall` | +| 跨所有会话查找信息 | `cortex_search` | +| 浏览记忆结构 | `cortex_ls` | +| 快速检查 URI 相关性 | `cortex_get_abstract` | +| 获取相关 URI 的更多详情 | `cortex_get_overview` | +| 需要完整原始内容 | `cortex_get_content` | +| 有目的地探索 | `cortex_explore` | | 保存重要信息 | `cortex_add_memory` | -| 完成任务/话题 | `cortex_close_session` | +| 完成任务/话题 | `cortex_commit_session` | | 首次使用且有现有记忆 | `cortex_migrate` | +| 数据维护 | `cortex_maintenance` | 更多关于工具选择、会话生命周期和最佳实践的详细指南,请参阅 [技能文档](skills/memclaw/SKILL.md)。 @@ -258,22 +387,12 @@ ln -sf "$(pwd)" ~/.openclaw/extensions/memclaw ### 插件无法工作 -1. **检查配置**:打开 OpenClaw 设置,验证 MemClaw 插件配置,特别是 LLM 和 Embedding 设置 -2. **重启 OpenClaw Gateway**:配置更改需要重启网关才能生效 -3. **验证服务**:运行 `cortex_list_sessions` 检查服务是否响应 - ### 服务无法启动 1. 检查端口 6333、6334、8085 是否可用 2. 验证 LLM 和 Embedding 凭证是否正确配置 3. 运行 `openclaw skills` 检查插件状态 -### 搜索无结果 - -1. 运行 `cortex_list_sessions` 验证会话是否存在 -2. 降低 `min_score` 阈值(默认:0.6) -3. 确保已存储记忆(运行 `cortex_close_session` 提取记忆) - ### 迁移失败 1. 确保 OpenClaw 工作区存在于 `~/.openclaw/workspace` diff --git a/examples/@memclaw/plugin/dist/index.js b/examples/@memclaw/plugin/dist/index.js index 34b5dbe..5b833eb 100644 --- a/examples/@memclaw/plugin/dist/index.js +++ b/examples/@memclaw/plugin/dist/index.js @@ -1,4 +1,4 @@ -'use strict'; +"use strict"; /** * MemClaw - Layered Semantic Memory for OpenClaw * @@ -26,33 +26,33 @@ * } * } */ -Object.defineProperty(exports, '__esModule', { value: true }); +Object.defineProperty(exports, "__esModule", { value: true }); exports.plugin = void 0; exports.default = memclawPlugin; -const plugin_impl_js_1 = require('./plugin-impl.js'); +const plugin_impl_js_1 = require("./plugin-impl.js"); // Default export - main plugin function function memclawPlugin(api) { - return (0, plugin_impl_js_1.createPlugin)(api); + return (0, plugin_impl_js_1.createPlugin)(api); } // Named export - object style registration exports.plugin = { - id: 'memclaw', - name: 'MemClaw', - version: '0.9.17', - configSchema: { - type: 'object', - properties: { - serviceUrl: { type: 'string', default: 'http://localhost:8085' }, - defaultSessionId: { type: 'string', default: 'default' }, - searchLimit: { type: 'integer', default: 10 }, - minScore: { type: 'number', default: 0.6 }, - tenantId: { type: 'string', default: 'tenant_claw' }, - autoStartServices: { type: 'boolean', default: true } - }, - required: [] - }, - register(api) { - return (0, plugin_impl_js_1.createPlugin)(api); - } + id: 'memclaw', + name: 'MemClaw', + version: '0.9.27', + configSchema: { + type: 'object', + properties: { + serviceUrl: { type: 'string', default: 'http://localhost:8085' }, + defaultSessionId: { type: 'string', default: 'default' }, + searchLimit: { type: 'integer', default: 10 }, + minScore: { type: 'number', default: 0.6 }, + tenantId: { type: 'string', default: 'tenant_claw' }, + autoStartServices: { type: 'boolean', default: true } + }, + required: [] + }, + register(api) { + return (0, plugin_impl_js_1.createPlugin)(api); + } }; -//# sourceMappingURL=index.js.map +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/examples/@memclaw/plugin/dist/plugin-impl.d.ts b/examples/@memclaw/plugin/dist/plugin-impl.d.ts index 4dcab87..436c697 100644 --- a/examples/@memclaw/plugin/dist/plugin-impl.d.ts +++ b/examples/@memclaw/plugin/dist/plugin-impl.d.ts @@ -3,7 +3,10 @@ * * Provides layered semantic memory for OpenClaw with: * - Automatic service startup - * - Memory tools (search, recall, add, list, close) + * - Memory tools (search, recall, add, close) + * - Tiered access (L0/L1/L2) + * - Filesystem browsing + * - Smart exploration * - Migration from OpenClaw native memory */ interface PluginLogger { diff --git a/examples/@memclaw/plugin/dist/plugin-impl.d.ts.map b/examples/@memclaw/plugin/dist/plugin-impl.d.ts.map index 10821d9..f7ae54c 100644 --- a/examples/@memclaw/plugin/dist/plugin-impl.d.ts.map +++ b/examples/@memclaw/plugin/dist/plugin-impl.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"plugin-impl.d.ts","sourceRoot":"","sources":["../plugin-impl.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA0CH,UAAU,YAAY;IACrB,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAClD,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAChD,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAChD,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACjD;AAED,UAAU,SAAS;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,YAAY,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACxE,eAAe,CAAC,OAAO,EAAE;QACxB,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;KAC1B,GAAG,IAAI,CAAC;IACT,MAAM,EAAE,YAAY,CAAC;CACrB;AAED,UAAU,cAAc;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5E,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AA+MD,wBAAgB,YAAY,CAAC,GAAG,EAAE,SAAS;;;;EA4d1C"} \ No newline at end of file +{"version":3,"file":"plugin-impl.d.ts","sourceRoot":"","sources":["../plugin-impl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA0CH,UAAU,YAAY;IACrB,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAClD,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAChD,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAChD,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACjD;AAED,UAAU,SAAS;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,YAAY,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACxE,eAAe,CAAC,OAAO,EAAE;QACxB,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;KAC1B,GAAG,IAAI,CAAC;IACT,MAAM,EAAE,YAAY,CAAC;CACrB;AAED,UAAU,cAAc;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5E,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAoXD,wBAAgB,YAAY,CAAC,GAAG,EAAE,SAAS;;;;EAmpB1C"} \ No newline at end of file diff --git a/examples/@memclaw/plugin/dist/plugin-impl.js b/examples/@memclaw/plugin/dist/plugin-impl.js index 44dec01..c87e939 100644 --- a/examples/@memclaw/plugin/dist/plugin-impl.js +++ b/examples/@memclaw/plugin/dist/plugin-impl.js @@ -4,7 +4,10 @@ * * Provides layered semantic memory for OpenClaw with: * - Automatic service startup - * - Memory tools (search, recall, add, list, close) + * - Memory tools (search, recall, add, close) + * - Tiered access (L0/L1/L2) + * - Filesystem browsing + * - Smart exploration * - Migration from OpenClaw native memory */ Object.defineProperty(exports, "__esModule", { value: true }); @@ -18,12 +21,18 @@ const toolSchemas = { cortex_search: { name: 'cortex_search', description: `Layered semantic search across memory using L0/L1/L2 tiered retrieval. -Returns relevant memories ranked by relevance score. -Use this tool when you need to: -- Find past conversations or decisions -- Search for specific information across all sessions -- Discover related memories by semantic similarity`, +**Key Features:** +- Tiered retrieval: L0 (abstract) -> L1 (overview) -> L2 (full content) +- Token-efficient: Control exactly which layers to return + +**Parameters:** +- return_layers: ["L0"] (default, ~100 tokens), ["L0","L1"] (~2100 tokens), ["L0","L1","L2"] (full) + +**When to use:** +- Finding past conversations or decisions +- Searching across all sessions +- Discovering related memories by semantic similarity`, inputSchema: { type: 'object', properties: { @@ -44,6 +53,15 @@ Use this tool when you need to: type: 'number', description: 'Minimum relevance score threshold (0-1, default: 0.6)', default: 0.6 + }, + return_layers: { + type: 'array', + items: { + type: 'string', + enum: ['L0', 'L1', 'L2'] + }, + description: 'Which layers to return. Default: ["L0"]. Use ["L0","L1"] for more context, ["L0","L1","L2"] for full content.', + default: ['L0'] } }, required: ['query'] @@ -51,16 +69,10 @@ Use this tool when you need to: }, cortex_recall: { name: 'cortex_recall', - description: `Recall memories using L0/L1/L2 tiered retrieval. - -The search engine internally performs tiered retrieval: -- L0 (Abstract): Quick filtering by summary -- L1 (Overview): Context refinement -- L2 (Full): Precise matching with full content + description: `Recall memories with full context (L0 snippet + L2 content). -Returns results with snippet (summary) and content (if available). - -Use this when you need memories with more context than a simple search.`, +This is a convenience wrapper that returns both abstract and full content. +Use cortex_search with return_layers=["L0","L2"] for more control.`, inputSchema: { type: 'object', properties: { @@ -84,10 +96,14 @@ Use this when you need memories with more context than a simple search.`, cortex_add_memory: { name: 'cortex_add_memory', description: `Add a message to memory for a specific session. + This stores the message and automatically triggers: - Vector embedding for semantic search - L0/L1 layer generation (async) +**Metadata support:** +You can attach metadata like tags, importance, or custom fields. + Use this to persist important information that should be searchable later.`, inputSchema: { type: 'object', @@ -105,27 +121,23 @@ Use this to persist important information that should be searchable later.`, session_id: { type: 'string', description: 'Session/thread ID (uses default if not specified)' + }, + metadata: { + type: 'object', + description: 'Optional metadata (tags, importance, custom fields)', + additionalProperties: true } }, required: ['content'] } }, - cortex_list_sessions: { - name: 'cortex_list_sessions', - description: `List all memory sessions with their status. -Shows session IDs, message counts, and creation/update times.`, - inputSchema: { - type: 'object', - properties: {} - } - }, - cortex_close_session: { - name: 'cortex_close_session', - description: `Trigger memory extraction and archival for accumulated conversation content. + cortex_commit_session: { + name: 'cortex_commit_session', + description: `Commit accumulated conversation content and trigger memory extraction. **IMPORTANT - Call this tool proactively and periodically, NOT just at conversation end.** -This triggers the complete memory processing pipeline: +This commits the session and triggers the complete memory processing pipeline: 1. Extracts structured memories (user preferences, entities, decisions) 2. Generates complete L0/L1 layer summaries 3. Indexes all extracted memories into the vector database @@ -149,11 +161,159 @@ This triggers the complete memory processing pipeline: properties: { session_id: { type: 'string', - description: 'Session/thread ID to process (uses default if not specified)' + description: 'Session/thread ID to commit (uses default if not specified)' } } } }, + // ==================== Filesystem Tools ==================== + cortex_ls: { + name: 'cortex_ls', + description: `List directory contents to browse the memory space like a virtual filesystem. + +This allows you to explore the hierarchical structure of memories: +- cortex://session - List all sessions +- cortex://session/{session_id} - Browse a specific session's contents +- cortex://session/{session_id}/timeline - View timeline messages +- cortex://session/{session_id}/memories - View extracted memories + +**Parameters:** +- recursive: List all subdirectories recursively +- include_abstracts: Show L0 abstracts for each file (for quick preview) + +Use this when: +- Semantic search doesn't find what you need +- You want to understand the overall memory layout +- You need to manually navigate to find specific information`, + inputSchema: { + type: 'object', + properties: { + uri: { + type: 'string', + description: 'Directory URI to list (default: cortex://session)', + default: 'cortex://session' + }, + recursive: { + type: 'boolean', + description: 'Whether to recursively list subdirectories', + default: false + }, + include_abstracts: { + type: 'boolean', + description: 'Whether to include L0 abstracts for each file', + default: false + } + } + } + }, + // ==================== Tiered Access Tools ==================== + cortex_get_abstract: { + name: 'cortex_get_abstract', + description: `Get L0 abstract layer (~100 tokens) for quick relevance checking. + +Abstracts are short summaries ideal for quickly determining if content is relevant +before committing to reading more. Use this to minimize token consumption. + +Use when: +- You found a URI from cortex_ls and want to quickly check relevance +- You need to filter many candidates before deep reading +- You want the most token-efficient preview`, + inputSchema: { + type: 'object', + properties: { + uri: { + type: 'string', + description: 'Content URI (file or directory)' + } + }, + required: ['uri'] + } + }, + cortex_get_overview: { + name: 'cortex_get_overview', + description: `Get L1 overview layer (~2000 tokens) with core information and context. + +Overviews contain key points and contextual information. Use this when: +- The abstract was relevant but you need more details +- You want to understand the gist without full content +- You need moderate detail for decision making`, + inputSchema: { + type: 'object', + properties: { + uri: { + type: 'string', + description: 'Content URI (file or directory)' + } + }, + required: ['uri'] + } + }, + cortex_get_content: { + name: 'cortex_get_content', + description: `Get L2 full content layer - the complete original content. + +Use this ONLY when you need the complete, unprocessed content. +This returns the full content which may be large. + +Use when: +- You need exact details or quotes +- Abstract and overview don't provide enough information +- You need to see the original, unsummarized content`, + inputSchema: { + type: 'object', + properties: { + uri: { + type: 'string', + description: 'Content URI (file only)' + } + }, + required: ['uri'] + } + }, + // ==================== Exploration Tool ==================== + cortex_explore: { + name: 'cortex_explore', + description: `Smart exploration of memory space, combining search and browsing. + +This tool performs a guided exploration: +1. Searches within a specified scope (start_uri) +2. Returns an exploration path showing relevance scores +3. Returns matching results with requested layers + +**When to use:** +- When you need to "wander" through memories with a purpose +- When you want to discover related content in a specific area +- When combining keyword hints with semantic discovery + +**Parameters:** +- start_uri: Where to begin exploration (default: cortex://session) +- return_layers: Which layers to include in matches`, + inputSchema: { + type: 'object', + properties: { + query: { + type: 'string', + description: 'Exploration query - what to look for' + }, + start_uri: { + type: 'string', + description: 'Starting URI for exploration', + default: 'cortex://session' + }, + return_layers: { + type: 'array', + items: { + type: 'string', + enum: ['L0', 'L1', 'L2'] + }, + description: 'Which layers to return in matches', + default: ['L0'] + } + }, + required: ['query'] + } + }, + // ==================== Migration & Maintenance ==================== cortex_migrate: { name: 'cortex_migrate', description: `Migrate memories from OpenClaw's native memory system to MemClaw. @@ -229,8 +389,8 @@ function createPlugin(api) { log(`Created configuration file: ${configPath}`); log('Opening configuration file for editing...'); (0, config_js_1.openConfigFile)(configPath).catch((err) => { - api.logger.warn(`Could not open config file: ${err}`); - api.logger.warn(`Please manually edit: ${configPath}`); + api.logger.warn(`[memclaw] Could not open config file: ${err}`); + api.logger.warn(`[memclaw] Please manually edit: ${configPath}`); }); api.logger.info(` ╔══════════════════════════════════════════════════════════╗ @@ -286,8 +446,8 @@ function createPlugin(api) { const mergedConfig = (0, config_js_1.mergeConfigWithPlugin)(fileConfig, pluginProvidedConfig); const validation = (0, config_js_1.validateConfig)(mergedConfig); if (!validation.valid) { - api.logger.warn(`Configuration incomplete: ${validation.errors.join(', ')}`); - api.logger.warn(`Please configure LLM/Embedding API keys in OpenClaw plugin settings or edit: ${configPath}`); + api.logger.warn(`[memclaw] Configuration incomplete: ${validation.errors.join(', ')}`); + api.logger.warn(`[memclaw] Please configure LLM/Embedding API keys in OpenClaw plugin settings or edit: ${configPath}`); return; } // Start services @@ -303,7 +463,7 @@ function createPlugin(api) { maintenanceTimer = setInterval(async () => { try { log('Running scheduled maintenance...'); - const configPath = (0, config_js_1.getConfigPath)(); + const currentConfigPath = (0, config_js_1.getConfigPath)(); // Run maintenance commands const commands = [ ['vector', 'prune'], @@ -311,7 +471,7 @@ function createPlugin(api) { ['layers', 'ensure-all'] ]; for (const cmd of commands) { - const result = await (0, binaries_js_1.executeCliCommand)(cmd, configPath, tenantId, 300000); + const result = await (0, binaries_js_1.executeCliCommand)(cmd, currentConfigPath, tenantId, 300000); if (!result.success) { log(`Maintenance command '${cmd.join(' ')}' failed: ${result.stderr}`); } @@ -325,8 +485,8 @@ function createPlugin(api) { log('Maintenance timer started (runs every 3 hours)'); } catch (err) { - api.logger.error(`Failed to start services: ${err}`); - api.logger.warn('Memory features may not work correctly'); + api.logger.error(`[memclaw] Failed to start services: ${err}`); + api.logger.warn('[memclaw] Memory features may not work correctly'); } }, stop: async () => { @@ -349,7 +509,7 @@ function createPlugin(api) { } } }; - // Register tools + // ==================== Register Tools ==================== // cortex_search api.registerTool({ name: toolSchemas.cortex_search.name, @@ -363,24 +523,40 @@ function createPlugin(api) { query: input.query, thread: input.scope, limit: input.limit ?? searchLimit, - min_score: input.min_score ?? minScore + min_score: input.min_score ?? minScore, + return_layers: input.return_layers ?? ['L0'] }); const formatted = results - .map((r, i) => `${i + 1}. [Score: ${r.score.toFixed(2)}] ${r.snippet}\n URI: ${r.uri}`) - .join('\n\n'); + .map((r, i) => { + let content = `${i + 1}. [Score: ${r.score.toFixed(2)}] URI: ${r.uri}\n`; + content += ` Layers: ${r.layers.join(', ')}\n`; + content += ` Snippet: ${r.snippet}\n`; + if (r.overview) { + content += ` Overview: ${r.overview.substring(0, 200)}...\n`; + } + if (r.content) { + const preview = r.content.length > 200 ? r.content.substring(0, 200) + '...' : r.content; + content += ` Content: ${preview}\n`; + } + return content; + }) + .join('\n'); return { content: `Found ${results.length} results for "${input.query}":\n\n${formatted}`, results: results.map((r) => ({ uri: r.uri, score: r.score, - snippet: r.snippet + snippet: r.snippet, + overview: r.overview, + content: r.content, + layers: r.layers })), total: results.length }; } catch (error) { const message = error instanceof Error ? error.message : String(error); - api.logger.error(`cortex_search failed: ${message}`); + api.logger.error(`[memclaw] cortex_search failed: ${message}`); return { error: `Search failed: ${message}` }; } } @@ -414,7 +590,7 @@ function createPlugin(api) { } catch (error) { const message = error instanceof Error ? error.message : String(error); - api.logger.error(`cortex_recall failed: ${message}`); + api.logger.error(`[memclaw] cortex_recall failed: ${message}`); return { error: `Recall failed: ${message}` }; } } @@ -431,7 +607,8 @@ function createPlugin(api) { const sessionId = input.session_id ?? defaultSessionId; const result = await client.addMessage(sessionId, { role: (input.role ?? 'user'), - content: input.content + content: input.content, + metadata: input.metadata }); return { content: `Memory stored successfully in session "${sessionId}".\nResult: ${result}`, @@ -441,71 +618,213 @@ function createPlugin(api) { } catch (error) { const message = error instanceof Error ? error.message : String(error); - api.logger.error(`cortex_add_memory failed: ${message}`); + api.logger.error(`[memclaw] cortex_add_memory failed: ${message}`); return { error: `Failed to add memory: ${message}` }; } } }); - // cortex_list_sessions + // cortex_commit_session api.registerTool({ - name: toolSchemas.cortex_list_sessions.name, - description: toolSchemas.cortex_list_sessions.description, - parameters: toolSchemas.cortex_list_sessions.inputSchema, - execute: async (_id, _params) => { + name: toolSchemas.cortex_commit_session.name, + description: toolSchemas.cortex_commit_session.description, + parameters: toolSchemas.cortex_commit_session.inputSchema, + execute: async (_id, params) => { + const input = params; + try { + await ensureServicesReady(); + const sessionId = input.session_id ?? defaultSessionId; + const result = await client.commitSession(sessionId); + return { + content: `Session "${sessionId}" committed successfully.\nStatus: ${result.status}, Messages: ${result.message_count}\n\nMemory extraction pipeline triggered.`, + success: true, + session: { + thread_id: result.thread_id, + status: result.status, + message_count: result.message_count + } + }; + } + catch (error) { + const message = error instanceof Error ? error.message : String(error); + api.logger.error(`[memclaw] cortex_commit_session failed: ${message}`); + return { error: `Failed to commit session: ${message}` }; + } + } + }); + // cortex_ls + api.registerTool({ + name: toolSchemas.cortex_ls.name, + description: toolSchemas.cortex_ls.description, + parameters: toolSchemas.cortex_ls.inputSchema, + execute: async (_id, params) => { + const input = params; try { await ensureServicesReady(); - const sessions = await client.listSessions(); - if (sessions.length === 0) { - return { content: 'No sessions found.' }; + const result = await client.ls({ + uri: input.uri ?? 'cortex://session', + recursive: input.recursive ?? false, + include_abstracts: input.include_abstracts ?? false + }); + if (result.entries.length === 0) { + return { content: `Directory "${result.uri}" is empty or does not exist.` }; } - const formatted = sessions - .map((s, i) => { - const created = new Date(s.created_at).toLocaleDateString(); - return `${i + 1}. ${s.thread_id} (${s.status}, ${s.message_count} messages, created ${created})`; + const formatted = result.entries + .map((e, i) => { + let content = `${i + 1}. ${e.is_directory ? '📁' : '📄'} ${e.name}\n`; + content += ` URI: ${e.uri}\n`; + if (e.is_directory) { + content += ` Type: Directory\n`; + } + else { + content += ` Size: ${e.size} bytes\n`; + } + if (e.abstract_text) { + const preview = e.abstract_text.length > 100 + ? e.abstract_text.substring(0, 100) + '...' + : e.abstract_text; + content += ` Abstract: ${preview}\n`; + } + return content; }) .join('\n'); return { - content: `Found ${sessions.length} sessions:\n\n${formatted}`, - sessions: sessions.map((s) => ({ - thread_id: s.thread_id, - status: s.status, - message_count: s.message_count, - created_at: s.created_at - })) + content: `Directory "${result.uri}" (${result.total} entries):\n\n${formatted}`, + entries: result.entries, + total: result.total }; } catch (error) { const message = error instanceof Error ? error.message : String(error); - api.logger.error(`cortex_list_sessions failed: ${message}`); - return { error: `Failed to list sessions: ${message}` }; + api.logger.error(`[memclaw] cortex_ls failed: ${message}`); + return { error: `List directory failed: ${message}` }; } } }); - // cortex_close_session + // cortex_get_abstract api.registerTool({ - name: toolSchemas.cortex_close_session.name, - description: toolSchemas.cortex_close_session.description, - parameters: toolSchemas.cortex_close_session.inputSchema, + name: toolSchemas.cortex_get_abstract.name, + description: toolSchemas.cortex_get_abstract.description, + parameters: toolSchemas.cortex_get_abstract.inputSchema, execute: async (_id, params) => { const input = params; try { await ensureServicesReady(); - const sessionId = input.session_id ?? defaultSessionId; - const result = await client.closeSession(sessionId); + const result = await client.getAbstract(input.uri); return { - content: `Session "${sessionId}" closed successfully.\nStatus: ${result.status}, Messages: ${result.message_count}\n\nMemory extraction pipeline triggered.`, - success: true, - session: { - thread_id: result.thread_id, - status: result.status, - message_count: result.message_count + content: `L0 Abstract for "${result.uri}" (~${result.token_count} tokens):\n\n${result.content}`, + uri: result.uri, + abstract: result.content, + token_count: result.token_count, + layer: result.layer + }; + } + catch (error) { + const message = error instanceof Error ? error.message : String(error); + api.logger.error(`[memclaw] cortex_get_abstract failed: ${message}`); + return { error: `Get abstract failed: ${message}` }; + } + } + }); + // cortex_get_overview + api.registerTool({ + name: toolSchemas.cortex_get_overview.name, + description: toolSchemas.cortex_get_overview.description, + parameters: toolSchemas.cortex_get_overview.inputSchema, + execute: async (_id, params) => { + const input = params; + try { + await ensureServicesReady(); + const result = await client.getOverview(input.uri); + return { + content: `L1 Overview for "${result.uri}" (~${result.token_count} tokens):\n\n${result.content}`, + uri: result.uri, + overview: result.content, + token_count: result.token_count, + layer: result.layer + }; + } + catch (error) { + const message = error instanceof Error ? error.message : String(error); + api.logger.error(`[memclaw] cortex_get_overview failed: ${message}`); + return { error: `Get overview failed: ${message}` }; + } + } + }); + // cortex_get_content + api.registerTool({ + name: toolSchemas.cortex_get_content.name, + description: toolSchemas.cortex_get_content.description, + parameters: toolSchemas.cortex_get_content.inputSchema, + execute: async (_id, params) => { + const input = params; + try { + await ensureServicesReady(); + const result = await client.getContent(input.uri); + return { + content: `L2 Full Content for "${result.uri}" (~${result.token_count} tokens):\n\n${result.content}`, + uri: result.uri, + full_content: result.content, + token_count: result.token_count, + layer: result.layer + }; + } + catch (error) { + const message = error instanceof Error ? error.message : String(error); + api.logger.error(`[memclaw] cortex_get_content failed: ${message}`); + return { error: `Get content failed: ${message}` }; + } + } + }); + // cortex_explore + api.registerTool({ + name: toolSchemas.cortex_explore.name, + description: toolSchemas.cortex_explore.description, + parameters: toolSchemas.cortex_explore.inputSchema, + execute: async (_id, params) => { + const input = params; + try { + await ensureServicesReady(); + const result = await client.explore({ + query: input.query, + start_uri: input.start_uri ?? 'cortex://session', + return_layers: input.return_layers ?? ['L0'] + }); + // Format exploration path + const pathFormatted = result.exploration_path + .map((item, i) => { + let content = `${i + 1}. [${item.relevance_score.toFixed(2)}] ${item.uri}\n`; + if (item.abstract_text) { + const preview = item.abstract_text.length > 80 + ? item.abstract_text.substring(0, 80) + '...' + : item.abstract_text; + content += ` Abstract: ${preview}\n`; } + return content; + }) + .join('\n'); + // Format matches + const matchesFormatted = result.matches + .map((m, i) => { + let content = `${i + 1}. [${m.score.toFixed(2)}] ${m.uri}\n`; + content += ` Layers: ${m.layers.join(', ')}\n`; + content += ` Snippet: ${m.snippet}\n`; + return content; + }) + .join('\n'); + return { + content: `Exploration for "${input.query}" starting from "${input.start_uri ?? 'cortex://session'}":\n\n` + + `**Exploration Path** (${result.total_explored} items):\n${pathFormatted}\n\n` + + `**Matches** (${result.total_matches} found):\n${matchesFormatted}`, + exploration_path: result.exploration_path, + matches: result.matches, + total_explored: result.total_explored, + total_matches: result.total_matches }; } catch (error) { const message = error instanceof Error ? error.message : String(error); - api.logger.error(`cortex_close_session failed: ${message}`); - return { error: `Failed to close session: ${message}` }; + api.logger.error(`[memclaw] cortex_explore failed: ${message}`); + return { error: `Explore failed: ${message}` }; } } }); @@ -577,7 +896,7 @@ function createPlugin(api) { output: result.stdout || result.stderr }); if (!result.success) { - api.logger.warn(`[maintenance] ${description} failed: ${result.stderr}`); + api.logger.warn(`[memclaw] [maintenance] ${description} failed: ${result.stderr}`); } } catch (error) { diff --git a/examples/@memclaw/plugin/dist/plugin-impl.js.map b/examples/@memclaw/plugin/dist/plugin-impl.js.map index 5f7bfdd..16ef539 100644 --- a/examples/@memclaw/plugin/dist/plugin-impl.js.map +++ b/examples/@memclaw/plugin/dist/plugin-impl.js.map @@ -1 +1 @@ -{"version":3,"file":"plugin-impl.js","sourceRoot":"","sources":["../plugin-impl.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"plugin-impl.js","sourceRoot":"","sources":["../plugin-impl.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/examples/@memclaw/plugin/dist/src/binaries.d.ts b/examples/@memclaw/plugin/dist/src/binaries.d.ts index 6108307..294157e 100644 --- a/examples/@memclaw/plugin/dist/src/binaries.d.ts +++ b/examples/@memclaw/plugin/dist/src/binaries.d.ts @@ -4,10 +4,11 @@ * Binaries are bundled in platform-specific npm packages: * - @memclaw/bin-darwin-arm64 (macOS Apple Silicon) * - @memclaw/bin-win-x64 (Windows x64) + * - @memclaw/bin-linux-x64 (Linux x64) * * The correct package is installed automatically via optionalDependencies. */ -type SupportedPlatform = 'darwin-arm64' | 'win-x64'; +type SupportedPlatform = 'darwin-arm64' | 'win-x64' | 'linux-x64'; export declare function getPlatform(): SupportedPlatform | null; export declare function isPlatformSupported(): boolean; export declare function getUnsupportedPlatformMessage(): string; diff --git a/examples/@memclaw/plugin/dist/src/binaries.d.ts.map b/examples/@memclaw/plugin/dist/src/binaries.d.ts.map index 7d2d4c3..7f42172 100644 --- a/examples/@memclaw/plugin/dist/src/binaries.d.ts.map +++ b/examples/@memclaw/plugin/dist/src/binaries.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"binaries.d.ts","sourceRoot":"","sources":["../../src/binaries.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH,KAAK,iBAAiB,GAAG,cAAc,GAAG,SAAS,CAAC;AAGpD,wBAAgB,WAAW,IAAI,iBAAiB,GAAG,IAAI,CAWtD;AAGD,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAGD,wBAAgB,6BAA6B,IAAI,MAAM,CAWtD;AA0BD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAe3D;AAGD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEzD;AAGD,wBAAgB,0BAA0B,IAAI,OAAO,CAEpD;AAGD,wBAAgB,sBAAsB,IAAI,MAAM,CAgB/C;AAED,MAAM,WAAW,aAAa;IAC7B,MAAM,EAAE,OAAO,CAAC;IAChB,gBAAgB,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,aAAa,CAAC,CAKjE;AAsCD,wBAAsB,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CA+F5E;AAED,wBAAsB,qBAAqB,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAsEtF;AAED,wBAAgB,eAAe,IAAI,IAAI,CAUtC;AAED,wBAAsB,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,CAwB3F;AAGD,wBAAgB,UAAU,IAAI,MAAM,GAAG,IAAI,CAE1C;AAGD,MAAM,WAAW,SAAS;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,wBAAsB,iBAAiB,CACtC,IAAI,EAAE,MAAM,EAAE,EACd,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,MAAe,GACtB,OAAO,CAAC,SAAS,CAAC,CA+DpB"} \ No newline at end of file +{"version":3,"file":"binaries.d.ts","sourceRoot":"","sources":["../../src/binaries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAWH,KAAK,iBAAiB,GAAG,cAAc,GAAG,SAAS,GAAG,WAAW,CAAC;AAGlE,wBAAgB,WAAW,IAAI,iBAAiB,GAAG,IAAI,CAatD;AAGD,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAGD,wBAAgB,6BAA6B,IAAI,MAAM,CAYtD;AA0BD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAe3D;AAGD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEzD;AAGD,wBAAgB,0BAA0B,IAAI,OAAO,CAEpD;AAGD,wBAAgB,sBAAsB,IAAI,MAAM,CAgB/C;AAED,MAAM,WAAW,aAAa;IAC7B,MAAM,EAAE,OAAO,CAAC;IAChB,gBAAgB,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,aAAa,CAAC,CAKjE;AAsCD,wBAAsB,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CA+F5E;AAED,wBAAsB,qBAAqB,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CA4EtF;AAED,wBAAgB,eAAe,IAAI,IAAI,CAUtC;AAED,wBAAsB,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,CAwB3F;AAGD,wBAAgB,UAAU,IAAI,MAAM,GAAG,IAAI,CAE1C;AAGD,MAAM,WAAW,SAAS;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,wBAAsB,iBAAiB,CACtC,IAAI,EAAE,MAAM,EAAE,EACd,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,MAAe,GACtB,OAAO,CAAC,SAAS,CAAC,CA+DpB"} \ No newline at end of file diff --git a/examples/@memclaw/plugin/dist/src/binaries.js b/examples/@memclaw/plugin/dist/src/binaries.js index 86c34cd..438e477 100644 --- a/examples/@memclaw/plugin/dist/src/binaries.js +++ b/examples/@memclaw/plugin/dist/src/binaries.js @@ -5,6 +5,7 @@ * Binaries are bundled in platform-specific npm packages: * - @memclaw/bin-darwin-arm64 (macOS Apple Silicon) * - @memclaw/bin-win-x64 (Windows x64) + * - @memclaw/bin-linux-x64 (Linux x64) * * The correct package is installed automatically via optionalDependencies. */ @@ -70,6 +71,9 @@ function getPlatform() { else if (platform === 'win32' && arch === 'x64') { return 'win-x64'; } + else if (platform === 'linux' && arch === 'x64') { + return 'linux-x64'; + } return null; } // Check if current platform is supported @@ -84,6 +88,7 @@ function getUnsupportedPlatformMessage() { MemClaw is only supported on: - macOS Apple Silicon (darwin-arm64) - Windows x64 (win-x64) + - Linux x64 (linux-x64) Current platform: ${platform}-${arch} is not supported. `; @@ -281,11 +286,16 @@ async function startCortexMemService(log) { log?.(`Warning: Could not set execute permission on binary: ${err}`); } const dataDir = (0, config_js_1.getDataDir)(); + // Prepare log file path + const logsDir = path.join(dataDir, 'logs'); + fs.mkdirSync(logsDir, { recursive: true }); + const logFilePath = path.join(logsDir, 'memclaw-cortex-mem-service.log'); log?.(`Starting cortex-mem-service with data-dir ${dataDir}...`); log?.(`Binary path: ${binaryPath}`); + log?.(`Log file: ${logFilePath}`); // cortex-mem-service reads config.toml from current working directory // Set cwd to dataDir so it can find the config file - const proc = (0, child_process_1.spawn)(binaryPath, ['--data-dir', dataDir], { + const proc = (0, child_process_1.spawn)(binaryPath, ['--data-dir', dataDir, '--log-file', logFilePath], { stdio: ['ignore', 'pipe', 'pipe'], detached: true, cwd: dataDir // Set working directory so config.toml can be found diff --git a/examples/@memclaw/plugin/dist/src/binaries.js.map b/examples/@memclaw/plugin/dist/src/binaries.js.map index b686f69..f27aed8 100644 --- a/examples/@memclaw/plugin/dist/src/binaries.js.map +++ b/examples/@memclaw/plugin/dist/src/binaries.js.map @@ -1 +1 @@ -{"version":3,"file":"binaries.js","sourceRoot":"","sources":["../../src/binaries.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"binaries.js","sourceRoot":"","sources":["../../src/binaries.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/examples/@memclaw/plugin/dist/src/client.d.ts b/examples/@memclaw/plugin/dist/src/client.d.ts index 79f5397..85de93b 100644 --- a/examples/@memclaw/plugin/dist/src/client.d.ts +++ b/examples/@memclaw/plugin/dist/src/client.d.ts @@ -1,88 +1,131 @@ /** - * Cortex Memory API Client + * Cortex Mem Client * - * HTTP client for cortex-mem-service REST API + * HTTP client for cortex-mem-service REST API. */ -export interface SearchRequest { +/** Layer types */ +export type Layer = 'L0' | 'L1' | 'L2'; +export interface SearchOptions { query: string; thread?: string; limit?: number; min_score?: number; + /** Which layers to return: ["L0"], ["L0","L1"], ["L0","L1","L2"] */ + return_layers?: Layer[]; } export interface SearchResult { uri: string; score: number; snippet: string; + overview?: string; content?: string; source: string; + layers: Layer[]; } -export interface SessionResponse { +export interface LsOptions { + uri?: string; + recursive?: boolean; + include_abstracts?: boolean; +} +export interface LsEntry { + uri: string; + name: string; + is_directory: boolean; + size: number; + modified: string; + abstract_text?: string; +} +export interface LsResponse { + uri: string; + total: number; + entries: LsEntry[]; +} +export interface ExploreOptions { + query: string; + start_uri?: string; + return_layers?: Layer[]; +} +export interface ExploreResponse { + query: string; + exploration_path: ExplorationPathItem[]; + matches: SearchResult[]; + total_explored: number; + total_matches: number; +} +export interface ExplorationPathItem { + uri: string; + relevance_score: number; + abstract_text?: string; +} +export interface LayerResponse { + uri: string; + content: string; + layer: Layer; + token_count: number; +} +export interface SessionInfo { thread_id: string; status: string; message_count: number; created_at: string; updated_at: string; } -export interface CreateSessionRequest { - thread_id?: string; - title?: string; - user_id?: string; - agent_id?: string; -} -export interface AddMessageRequest { - role: "user" | "assistant" | "system"; +export interface AddMessageOptions { content: string; + role?: 'user' | 'assistant' | 'system'; + metadata?: Record; } -/** - * Cortex Memory API Client - */ export declare class CortexMemClient { private baseUrl; constructor(baseUrl?: string); /** - * Layered semantic search (L0 -> L1 -> L2 tiered retrieval) + * Layered semantic search with L0/L1/L2 tiered retrieval */ - search(request: SearchRequest): Promise; + search(options: SearchOptions): Promise; /** - * Quick search returning only L0 abstracts + * Recall memories with more context (L0 + L2) */ - find(query: string, scope?: string, limit?: number): Promise; + recall(query: string, thread?: string, limit?: number): Promise; /** - * Layered recall - uses L0/L1/L2 tiered search internally - * - * The search engine performs tiered retrieval (L0→L1→L2) internally, - * but returns unified results with snippet and content. - * - * @param query - Search query - * @param scope - Optional session/thread scope - * @param limit - Maximum results + * List directory contents */ - recall(query: string, scope?: string, limit?: number): Promise; + ls(options?: LsOptions): Promise; /** - * List all sessions + * Smart exploration combining search and browsing */ - listSessions(): Promise; + explore(options: ExploreOptions): Promise; /** - * Create a new session + * Get L0 abstract (~100 tokens) for quick relevance check */ - createSession(request?: CreateSessionRequest): Promise; + getAbstract(uri: string): Promise; /** - * Add a message to a session + * Get L1 overview (~2000 tokens) for core information */ - addMessage(threadId: string, message: AddMessageRequest): Promise; + getOverview(uri: string): Promise; /** - * Close a session + * Get L2 full content */ - closeSession(threadId: string): Promise; + getContent(uri: string): Promise; /** - * Switch tenant + * List all sessions */ - switchTenant(tenantId: string): Promise; + listSessions(): Promise; /** - * Health check + * Add a message to a session + */ + addMessage(threadId: string, message: AddMessageOptions): Promise; + /** + * Commit a session and trigger memory extraction */ - healthCheck(): Promise; - private get; - private post; + commitSession(threadId: string): Promise<{ + thread_id: string; + status: string; + message_count: number; + }>; + /** + * Switch tenant context + */ + switchTenant(tenantId: string): Promise; + private fetchJson; } //# sourceMappingURL=client.d.ts.map \ No newline at end of file diff --git a/examples/@memclaw/plugin/dist/src/client.d.ts.map b/examples/@memclaw/plugin/dist/src/client.d.ts.map index 67d831f..d085852 100644 --- a/examples/@memclaw/plugin/dist/src/client.d.ts.map +++ b/examples/@memclaw/plugin/dist/src/client.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAGD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,GAAE,MAAgC;IAIrD;;OAEG;IACG,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAK7D;;OAEG;IACG,IAAI,CACR,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,MAAM,EACd,KAAK,GAAE,MAAU,GAChB,OAAO,CAAC,YAAY,EAAE,CAAC;IAS1B;;;;;;;;;OASG;IACG,MAAM,CACV,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,MAAM,EACd,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,YAAY,EAAE,CAAC;IAS1B;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAKhD;;OAEG;IACG,aAAa,CACjB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,eAAe,CAAC;IAQ3B;;OAEG;IACG,UAAU,CACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,MAAM,CAAC;IAQlB;;OAEG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAQ9D;;OAEG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAInD;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;YAUvB,GAAG;YAYH,IAAI;CAoBnB"} \ No newline at end of file +{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/examples/@memclaw/plugin/dist/src/client.js b/examples/@memclaw/plugin/dist/src/client.js index 6cbdccf..4967aa0 100644 --- a/examples/@memclaw/plugin/dist/src/client.js +++ b/examples/@memclaw/plugin/dist/src/client.js @@ -1,130 +1,187 @@ "use strict"; /** - * Cortex Memory API Client + * Cortex Mem Client * - * HTTP client for cortex-mem-service REST API + * HTTP client for cortex-mem-service REST API. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.CortexMemClient = void 0; -/** - * Cortex Memory API Client - */ class CortexMemClient { baseUrl; - constructor(baseUrl = "http://localhost:8085") { - this.baseUrl = baseUrl.replace(/\/$/, ""); + constructor(baseUrl = 'http://localhost:8085') { + this.baseUrl = baseUrl; } + // ==================== Search ==================== /** - * Layered semantic search (L0 -> L1 -> L2 tiered retrieval) + * Layered semantic search with L0/L1/L2 tiered retrieval */ - async search(request) { - const response = await this.post("/api/v2/search", request); - return response; + async search(options) { + const response = await this.fetchJson('/api/v2/search', { + method: 'POST', + body: JSON.stringify({ + query: options.query, + thread: options.thread, + limit: options.limit ?? 10, + min_score: options.min_score ?? 0.6, + return_layers: options.return_layers ?? ['L0'] + }) + }); + if (!response.success || !response.data) { + throw new Error(response.error ?? 'Search failed'); + } + return response.data; } /** - * Quick search returning only L0 abstracts + * Recall memories with more context (L0 + L2) */ - async find(query, scope, limit = 5) { + async recall(query, thread, limit = 10) { return this.search({ query, - thread: scope, + thread, limit, - min_score: 0.5, + return_layers: ['L0', 'L2'] }); } + // ==================== Filesystem ==================== /** - * Layered recall - uses L0/L1/L2 tiered search internally - * - * The search engine performs tiered retrieval (L0→L1→L2) internally, - * but returns unified results with snippet and content. - * - * @param query - Search query - * @param scope - Optional session/thread scope - * @param limit - Maximum results + * List directory contents */ - async recall(query, scope, limit = 10) { - return this.search({ - query, - thread: scope, - limit, - min_score: 0.5, - }); + async ls(options = {}) { + const params = new URLSearchParams(); + params.set('uri', options.uri ?? 'cortex://session'); + if (options.recursive) + params.set('recursive', 'true'); + if (options.include_abstracts) + params.set('include_abstracts', 'true'); + const response = await this.fetchJson(`/api/v2/filesystem/list?${params.toString()}`); + if (!response.success || !response.data) { + throw new Error(response.error ?? 'List directory failed'); + } + return response.data; } /** - * List all sessions + * Smart exploration combining search and browsing */ - async listSessions() { - const response = await this.get("/api/v2/sessions"); - return response; + async explore(options) { + const response = await this.fetchJson('/api/v2/filesystem/explore', { + method: 'POST', + body: JSON.stringify({ + query: options.query, + start_uri: options.start_uri ?? 'cortex://session', + return_layers: options.return_layers ?? ['L0'] + }) + }); + if (!response.success || !response.data) { + throw new Error(response.error ?? 'Explore failed'); + } + return response.data; } + // ==================== Tiered Access ==================== /** - * Create a new session + * Get L0 abstract (~100 tokens) for quick relevance check */ - async createSession(request = {}) { - const response = await this.post("/api/v2/sessions", request); - return response; + async getAbstract(uri) { + const params = new URLSearchParams(); + params.set('uri', uri); + const response = await this.fetchJson(`/api/v2/filesystem/abstract?${params.toString()}`); + if (!response.success || !response.data) { + throw new Error(response.error ?? 'Get abstract failed'); + } + return response.data; } /** - * Add a message to a session + * Get L1 overview (~2000 tokens) for core information */ - async addMessage(threadId, message) { - const response = await this.post(`/api/v2/sessions/${threadId}/messages`, message); - return response; + async getOverview(uri) { + const params = new URLSearchParams(); + params.set('uri', uri); + const response = await this.fetchJson(`/api/v2/filesystem/overview?${params.toString()}`); + if (!response.success || !response.data) { + throw new Error(response.error ?? 'Get overview failed'); + } + return response.data; } /** - * Close a session + * Get L2 full content */ - async closeSession(threadId) { - const response = await this.post(`/api/v2/sessions/${threadId}/close`, {}); - return response; + async getContent(uri) { + const params = new URLSearchParams(); + params.set('uri', uri); + const response = await this.fetchJson(`/api/v2/filesystem/content?${params.toString()}`); + if (!response.success || !response.data) { + throw new Error(response.error ?? 'Get content failed'); + } + return response.data; } + // ==================== Session Management ==================== /** - * Switch tenant + * List all sessions */ - async switchTenant(tenantId) { - await this.post("/api/v2/tenants/switch", { tenant_id: tenantId }); + async listSessions() { + const response = await this.fetchJson('/api/v2/sessions'); + if (!response.success || !response.data) { + throw new Error(response.error ?? 'List sessions failed'); + } + return response.data; } /** - * Health check + * Add a message to a session */ - async healthCheck() { - try { - const response = await fetch(`${this.baseUrl}/health`); - return response.ok; - } - catch { - return false; + async addMessage(threadId, message) { + const response = await this.fetchJson(`/api/v2/sessions/${threadId}/messages`, { + method: 'POST', + body: JSON.stringify({ + role: message.role ?? 'user', + content: message.content, + metadata: message.metadata + }) + }); + if (!response.success || !response.data) { + throw new Error(response.error ?? 'Add message failed'); } + return response.data; } - // Private helpers - async get(path) { - const response = await fetch(`${this.baseUrl}${path}`); - if (!response.ok) { - throw new Error(`API error: ${response.status} ${response.statusText}`); + /** + * Commit a session and trigger memory extraction + */ + async commitSession(threadId) { + const response = await this.fetchJson(`/api/v2/sessions/${threadId}/close`, { + method: 'POST', + body: JSON.stringify({}) + }); + if (!response.success || !response.data) { + throw new Error(response.error ?? 'Commit session failed'); } - const data = (await response.json()); - if (!data.success) { - throw new Error(data.error || "API request failed"); + return response.data; + } + // ==================== Tenant ==================== + /** + * Switch tenant context + */ + async switchTenant(tenantId) { + const response = await this.fetchJson('/api/v2/tenants/switch', { + method: 'POST', + body: JSON.stringify({ tenant_id: tenantId }) + }); + if (!response.success) { + throw new Error(response.error ?? 'Switch tenant failed'); } - return data.data; } - async post(path, body) { - const response = await fetch(`${this.baseUrl}${path}`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(body), + // ==================== Internal ==================== + async fetchJson(path, options = {}) { + const url = `${this.baseUrl}${path}`; + const headers = { + 'Content-Type': 'application/json', + ...(options.headers || {}) + }; + const response = await fetch(url, { + ...options, + headers }); if (!response.ok) { - const errorText = await response.text(); - throw new Error(`API error: ${response.status} ${response.statusText} - ${errorText}`); - } - const data = (await response.json()); - if (!data.success) { - throw new Error(data.error || "API request failed"); + throw new Error(`HTTP ${response.status}: ${response.statusText}`); } - return data.data; + return response.json(); } } exports.CortexMemClient = CortexMemClient; diff --git a/examples/@memclaw/plugin/dist/src/client.js.map b/examples/@memclaw/plugin/dist/src/client.js.map index f370917..5b58796 100644 --- a/examples/@memclaw/plugin/dist/src/client.js.map +++ b/examples/@memclaw/plugin/dist/src/client.js.map @@ -1 +1 @@ -{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/examples/@memclaw/plugin/dist/src/config.d.ts.map b/examples/@memclaw/plugin/dist/src/config.d.ts.map index d89a476..bfe4454 100644 --- a/examples/@memclaw/plugin/dist/src/config.d.ts.map +++ b/examples/@memclaw/plugin/dist/src/config.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,wBAAgB,UAAU,IAAI,MAAM,CAanC;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,MAAM,WAAW,aAAa;IAC7B,MAAM,EAAE;QACP,GAAG,EAAE,MAAM,CAAC;QACZ,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,GAAG,EAAE;QACJ,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,EAAE,MAAM,CAAC;QAChB,eAAe,EAAE,MAAM,CAAC;QACxB,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,SAAS,EAAE;QACV,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,MAAM,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACb,CAAC;IACF,OAAO,EAAE;QACR,OAAO,EAAE,OAAO,CAAC;QACjB,aAAa,EAAE,MAAM,CAAC;QACtB,KAAK,EAAE,MAAM,CAAC;KACd,CAAC;IACF,MAAM,EAAE;QACP,sBAAsB,EAAE,OAAO,CAAC;KAChC,CAAC;CACF;AAED,wBAAgB,sBAAsB,IAAI,MAAM,CA2C/C;AAED,wBAAgB,kBAAkB,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAevE;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBhE;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,CAkF7D;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG;IACtD,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CACjB,CAoBA;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,oBAAoB,GAAG;IAC3E,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACb,CAgFA;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACpC,UAAU,EAAE,aAAa,EACzB,YAAY,EAAE,oBAAoB,GAChC,aAAa,CAgBf"} \ No newline at end of file +{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,wBAAgB,UAAU,IAAI,MAAM,CAanC;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,MAAM,WAAW,aAAa;IAC7B,MAAM,EAAE;QACP,GAAG,EAAE,MAAM,CAAC;QACZ,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,GAAG,EAAE;QACJ,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,EAAE,MAAM,CAAC;QAChB,eAAe,EAAE,MAAM,CAAC;QACxB,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,SAAS,EAAE;QACV,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,MAAM,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACb,CAAC;IACF,OAAO,EAAE;QACR,OAAO,EAAE,OAAO,CAAC;QACjB,aAAa,EAAE,MAAM,CAAC;QACtB,KAAK,EAAE,MAAM,CAAC;KACd,CAAC;IACF,MAAM,EAAE;QACP,sBAAsB,EAAE,OAAO,CAAC;KAChC,CAAC;CACF;AAED,wBAAgB,sBAAsB,IAAI,MAAM,CA4C/C;AAED,wBAAgB,kBAAkB,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAevE;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBhE;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,CAkF7D;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG;IACtD,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CACjB,CAoBA;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,oBAAoB,GAAG;IAC3E,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACb,CAgFA;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACpC,UAAU,EAAE,aAAa,EACzB,YAAY,EAAE,oBAAoB,GAChC,aAAa,CAgBf"} \ No newline at end of file diff --git a/examples/@memclaw/plugin/dist/src/config.js b/examples/@memclaw/plugin/dist/src/config.js index 1ea32ba..2afc9d3 100644 --- a/examples/@memclaw/plugin/dist/src/config.js +++ b/examples/@memclaw/plugin/dist/src/config.js @@ -1,63 +1,44 @@ -'use strict'; +"use strict"; /** * Configuration management for MemClaw * * Handles platform-specific config paths, config file generation, * and auto-opening config files for user editing. */ -var __createBinding = - (this && this.__createBinding) || - (Object.create - ? function (o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ('get' in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { - enumerable: true, - get: function () { - return m[k]; - } - }; - } - Object.defineProperty(o, k2, desc); - } - : function (o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; - }); -var __setModuleDefault = - (this && this.__setModuleDefault) || - (Object.create - ? function (o, v) { - Object.defineProperty(o, 'default', { enumerable: true, value: v }); - } - : function (o, v) { - o['default'] = v; - }); -var __importStar = - (this && this.__importStar) || - (function () { - var ownKeys = function (o) { - ownKeys = - Object.getOwnPropertyNames || - function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) - for (var k = ownKeys(mod), i = 0; i < k.length; i++) - if (k[i] !== 'default') __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; - })(); -Object.defineProperty(exports, '__esModule', { value: true }); +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); exports.getDataDir = getDataDir; exports.getConfigPath = getConfigPath; exports.generateConfigTemplate = generateConfigTemplate; @@ -67,29 +48,28 @@ exports.parseConfig = parseConfig; exports.validateConfig = validateConfig; exports.updateConfigFromPlugin = updateConfigFromPlugin; exports.mergeConfigWithPlugin = mergeConfigWithPlugin; -const fs = __importStar(require('fs')); -const path = __importStar(require('path')); -const os = __importStar(require('os')); -const child_process_1 = require('child_process'); +const fs = __importStar(require("fs")); +const path = __importStar(require("path")); +const os = __importStar(require("os")); +const child_process_1 = require("child_process"); // Platform-specific paths function getDataDir() { - const platform = process.platform; - if (platform === 'win32') { - return path.join( - process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local'), - 'memclaw' - ); - } else if (platform === 'darwin') { - return path.join(os.homedir(), 'Library', 'Application Support', 'memclaw'); - } else { - return path.join(os.homedir(), '.local', 'share', 'memclaw'); - } + const platform = process.platform; + if (platform === 'win32') { + return path.join(process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local'), 'memclaw'); + } + else if (platform === 'darwin') { + return path.join(os.homedir(), 'Library', 'Application Support', 'memclaw'); + } + else { + return path.join(os.homedir(), '.local', 'share', 'memclaw'); + } } function getConfigPath() { - return path.join(getDataDir(), 'config.toml'); + return path.join(getDataDir(), 'config.toml'); } function generateConfigTemplate() { - return `# MemClaw Configuration + return `# MemClaw Configuration # # This file was auto-generated. Please fill in the required values below. # All sections are required - missing sections will cause config to be ignored. @@ -134,222 +114,230 @@ enable_intent_analysis = false `; } function ensureConfigExists() { - const dataDir = getDataDir(); - const configPath = getConfigPath(); - if (!fs.existsSync(dataDir)) { - fs.mkdirSync(dataDir, { recursive: true }); - } - if (!fs.existsSync(configPath)) { - const template = generateConfigTemplate(); - fs.writeFileSync(configPath, template, 'utf-8'); - return { created: true, path: configPath }; - } - return { created: false, path: configPath }; + const dataDir = getDataDir(); + const configPath = getConfigPath(); + if (!fs.existsSync(dataDir)) { + fs.mkdirSync(dataDir, { recursive: true }); + } + if (!fs.existsSync(configPath)) { + const template = generateConfigTemplate(); + fs.writeFileSync(configPath, template, 'utf-8'); + return { created: true, path: configPath }; + } + return { created: false, path: configPath }; } function openConfigFile(configPath) { - return new Promise((resolve, reject) => { - const platform = process.platform; - let command; - let args = []; - if (platform === 'win32') { - command = 'cmd'; - args = ['/c', 'start', '""', configPath]; - } else if (platform === 'darwin') { - command = 'open'; - args = [configPath]; - } else { - command = 'xdg-open'; - args = [configPath]; - } - const proc = (0, child_process_1.spawn)(command, args, { detached: true, stdio: 'ignore' }); - proc.on('error', (err) => { - reject(err); - }); - proc.unref(); - resolve(); - }); + return new Promise((resolve, reject) => { + const platform = process.platform; + let command; + let args = []; + if (platform === 'win32') { + command = 'cmd'; + args = ['/c', 'start', '""', configPath]; + } + else if (platform === 'darwin') { + command = 'open'; + args = [configPath]; + } + else { + command = 'xdg-open'; + args = [configPath]; + } + const proc = (0, child_process_1.spawn)(command, args, { detached: true, stdio: 'ignore' }); + proc.on('error', (err) => { + reject(err); + }); + proc.unref(); + resolve(); + }); } function parseConfig(configPath) { - const content = fs.readFileSync(configPath, 'utf-8'); - const config = {}; - let currentSection = ''; - for (const line of content.split('\n')) { - const trimmed = line.trim(); - // Skip comments and empty lines - if (trimmed.startsWith('#') || trimmed === '') continue; - // Section header - const sectionMatch = trimmed.match(/^\[(\w+)\]$/); - if (sectionMatch) { - currentSection = sectionMatch[1]; - config[currentSection] = {}; - continue; - } - // Key-value pair - const kvMatch = - trimmed.match(/^(\w+)\s*=\s*"([^"]*)"(?:\s*$|\s*#)/) || - trimmed.match(/^(\w+)\s*=\s*(\d+(?:\.\d+)?)(?:\s*$|\s*#)/) || - trimmed.match(/^(\w+)\s*=\s*(true|false)(?:\s*$|\s*#)/); - if (kvMatch && currentSection) { - const key = kvMatch[1]; - let value = kvMatch[2]; - // Convert to appropriate type - if (value === 'true') value = true; - else if (value === 'false') value = false; - else if (/^\d+$/.test(value)) value = parseInt(value, 10); - else if (/^\d+\.\d+$/.test(value)) value = parseFloat(value); - config[currentSection] = config[currentSection] || {}; - config[currentSection][key] = value; - } - } - // Apply defaults - return { - qdrant: { - url: 'http://localhost:6334', - collection_name: 'memclaw', - timeout_secs: 30, - ...(config.qdrant || {}) - }, - llm: { - api_base_url: 'https://api.openai.com/v1', - api_key: '', - model_efficient: 'gpt-5-mini', - temperature: 0.1, - max_tokens: 4096, - ...(config.llm || {}) - }, - embedding: { - api_base_url: 'https://api.openai.com/v1', - api_key: '', - model_name: 'text-embedding-3-small', - batch_size: 10, - timeout_secs: 30, - ...(config.embedding || {}) - }, - server: { - host: 'localhost', - port: 8085, - ...(config.server || {}) - }, - logging: { - enabled: false, - log_directory: 'logs', - level: 'info', - ...(config.logging || {}) - }, - cortex: { - enable_intent_analysis: false, - ...(config.cortex || {}) - } - }; + const content = fs.readFileSync(configPath, 'utf-8'); + const config = {}; + let currentSection = ''; + for (const line of content.split('\n')) { + const trimmed = line.trim(); + // Skip comments and empty lines + if (trimmed.startsWith('#') || trimmed === '') + continue; + // Section header + const sectionMatch = trimmed.match(/^\[(\w+)\]$/); + if (sectionMatch) { + currentSection = sectionMatch[1]; + config[currentSection] = {}; + continue; + } + // Key-value pair + const kvMatch = trimmed.match(/^(\w+)\s*=\s*"([^"]*)"(?:\s*$|\s*#)/) || + trimmed.match(/^(\w+)\s*=\s*(\d+(?:\.\d+)?)(?:\s*$|\s*#)/) || + trimmed.match(/^(\w+)\s*=\s*(true|false)(?:\s*$|\s*#)/); + if (kvMatch && currentSection) { + const key = kvMatch[1]; + let value = kvMatch[2]; + // Convert to appropriate type + if (value === 'true') + value = true; + else if (value === 'false') + value = false; + else if (/^\d+$/.test(value)) + value = parseInt(value, 10); + else if (/^\d+\.\d+$/.test(value)) + value = parseFloat(value); + config[currentSection] = config[currentSection] || {}; + config[currentSection][key] = value; + } + } + // Apply defaults + return { + qdrant: { + url: 'http://localhost:6334', + collection_name: 'memclaw', + timeout_secs: 30, + ...(config.qdrant || {}) + }, + llm: { + api_base_url: 'https://api.openai.com/v1', + api_key: '', + model_efficient: 'gpt-5-mini', + temperature: 0.1, + max_tokens: 4096, + ...(config.llm || {}) + }, + embedding: { + api_base_url: 'https://api.openai.com/v1', + api_key: '', + model_name: 'text-embedding-3-small', + batch_size: 10, + timeout_secs: 30, + ...(config.embedding || {}) + }, + server: { + host: 'localhost', + port: 8085, + ...(config.server || {}) + }, + logging: { + enabled: false, + log_directory: 'logs', + level: 'info', + ...(config.logging || {}) + }, + cortex: { + enable_intent_analysis: false, + ...(config.cortex || {}) + } + }; } function validateConfig(config) { - const errors = []; - if (!config.llm.api_key || config.llm.api_key === '') { - errors.push('llm.api_key is required'); - } - if (!config.embedding.api_key || config.embedding.api_key === '') { - // Allow using llm.api_key for embedding if not specified - if (config.llm.api_key && config.llm.api_key !== '') { - config.embedding.api_key = config.llm.api_key; - } else { - errors.push('embedding.api_key is required'); - } - } - return { - valid: errors.length === 0, - errors - }; + const errors = []; + if (!config.llm.api_key || config.llm.api_key === '') { + errors.push('llm.api_key is required'); + } + if (!config.embedding.api_key || config.embedding.api_key === '') { + // Allow using llm.api_key for embedding if not specified + if (config.llm.api_key && config.llm.api_key !== '') { + config.embedding.api_key = config.llm.api_key; + } + else { + errors.push('embedding.api_key is required'); + } + } + return { + valid: errors.length === 0, + errors + }; } /** * Update config.toml with values from OpenClaw plugin config * Only updates fields that are provided (non-empty) in pluginConfig */ function updateConfigFromPlugin(pluginConfig) { - const configPath = getConfigPath(); - // Ensure config file exists - ensureConfigExists(); - // Parse existing config - const existingConfig = parseConfig(configPath); - // Track if any changes were made - let updated = false; - // Build updated config sections - const updates = []; - // LLM config updates - if (pluginConfig.llmApiKey && pluginConfig.llmApiKey !== '') { - updates.push({ section: 'llm', key: 'api_key', value: pluginConfig.llmApiKey }); - updated = true; - } - if (pluginConfig.llmApiBaseUrl && pluginConfig.llmApiBaseUrl !== '') { - updates.push({ section: 'llm', key: 'api_base_url', value: pluginConfig.llmApiBaseUrl }); - updated = true; - } - if (pluginConfig.llmModel && pluginConfig.llmModel !== '') { - updates.push({ section: 'llm', key: 'model_efficient', value: pluginConfig.llmModel }); - updated = true; - } - // Embedding config updates - if (pluginConfig.embeddingApiKey && pluginConfig.embeddingApiKey !== '') { - updates.push({ section: 'embedding', key: 'api_key', value: pluginConfig.embeddingApiKey }); - updated = true; - } - if (pluginConfig.embeddingApiBaseUrl && pluginConfig.embeddingApiBaseUrl !== '') { - updates.push({ - section: 'embedding', - key: 'api_base_url', - value: pluginConfig.embeddingApiBaseUrl - }); - updated = true; - } - if (pluginConfig.embeddingModel && pluginConfig.embeddingModel !== '') { - updates.push({ section: 'embedding', key: 'model_name', value: pluginConfig.embeddingModel }); - updated = true; - } - if (!updated) { - return { updated: false, path: configPath }; - } - // Read current content - let content = fs.readFileSync(configPath, 'utf-8'); - // Apply each update - for (const { section, key, value } of updates) { - // Escape value for TOML string - const escapedValue = value.replace(/\\/g, '\\\\').replace(/"/g, '\\"'); - // Pattern to match the key in the correct section - // This handles both existing keys and missing keys - const sectionPattern = new RegExp(`(\\[${section}\\][^\\[]*?)(${key}\\s*=\\s*)"[^"]*"`, 's'); - const keyExistsInSection = sectionPattern.test(content); - if (keyExistsInSection) { - // Update existing key - content = content.replace(sectionPattern, `$1$2"${escapedValue}"`); - } else { - // Add key to section - const sectionStartPattern = new RegExp(`(\\[${section}\\]\\n)`, ''); - if (sectionStartPattern.test(content)) { - content = content.replace(sectionStartPattern, `$1${key} = "${escapedValue}"\n`); - } - } - } - // Write updated content - fs.writeFileSync(configPath, content, 'utf-8'); - return { updated: true, path: configPath }; + const configPath = getConfigPath(); + // Ensure config file exists + ensureConfigExists(); + // Parse existing config + const existingConfig = parseConfig(configPath); + // Track if any changes were made + let updated = false; + // Build updated config sections + const updates = []; + // LLM config updates + if (pluginConfig.llmApiKey && pluginConfig.llmApiKey !== '') { + updates.push({ section: 'llm', key: 'api_key', value: pluginConfig.llmApiKey }); + updated = true; + } + if (pluginConfig.llmApiBaseUrl && pluginConfig.llmApiBaseUrl !== '') { + updates.push({ section: 'llm', key: 'api_base_url', value: pluginConfig.llmApiBaseUrl }); + updated = true; + } + if (pluginConfig.llmModel && pluginConfig.llmModel !== '') { + updates.push({ section: 'llm', key: 'model_efficient', value: pluginConfig.llmModel }); + updated = true; + } + // Embedding config updates + if (pluginConfig.embeddingApiKey && pluginConfig.embeddingApiKey !== '') { + updates.push({ section: 'embedding', key: 'api_key', value: pluginConfig.embeddingApiKey }); + updated = true; + } + if (pluginConfig.embeddingApiBaseUrl && pluginConfig.embeddingApiBaseUrl !== '') { + updates.push({ + section: 'embedding', + key: 'api_base_url', + value: pluginConfig.embeddingApiBaseUrl + }); + updated = true; + } + if (pluginConfig.embeddingModel && pluginConfig.embeddingModel !== '') { + updates.push({ section: 'embedding', key: 'model_name', value: pluginConfig.embeddingModel }); + updated = true; + } + if (!updated) { + return { updated: false, path: configPath }; + } + // Read current content + let content = fs.readFileSync(configPath, 'utf-8'); + // Apply each update + for (const { section, key, value } of updates) { + // Escape value for TOML string + const escapedValue = value.replace(/\\/g, '\\\\').replace(/"/g, '\\"'); + // Pattern to match the key in the correct section + // This handles both existing keys and missing keys + const sectionPattern = new RegExp(`(\\[${section}\\][^\\[]*?)(${key}\\s*=\\s*)"[^"]*"`, 's'); + const keyExistsInSection = sectionPattern.test(content); + if (keyExistsInSection) { + // Update existing key + content = content.replace(sectionPattern, `$1$2"${escapedValue}"`); + } + else { + // Add key to section + const sectionStartPattern = new RegExp(`(\\[${section}\\]\\n)`, ''); + if (sectionStartPattern.test(content)) { + content = content.replace(sectionStartPattern, `$1${key} = "${escapedValue}"\n`); + } + } + } + // Write updated content + fs.writeFileSync(configPath, content, 'utf-8'); + return { updated: true, path: configPath }; } /** * Merge plugin config with file config, preferring plugin config values */ function mergeConfigWithPlugin(fileConfig, pluginConfig) { - return { - ...fileConfig, - llm: { - ...fileConfig.llm, - api_base_url: pluginConfig.llmApiBaseUrl || fileConfig.llm.api_base_url, - api_key: pluginConfig.llmApiKey || fileConfig.llm.api_key, - model_efficient: pluginConfig.llmModel || fileConfig.llm.model_efficient - }, - embedding: { - ...fileConfig.embedding, - api_base_url: pluginConfig.embeddingApiBaseUrl || fileConfig.embedding.api_base_url, - api_key: pluginConfig.embeddingApiKey || fileConfig.embedding.api_key, - model_name: pluginConfig.embeddingModel || fileConfig.embedding.model_name - } - }; + return { + ...fileConfig, + llm: { + ...fileConfig.llm, + api_base_url: pluginConfig.llmApiBaseUrl || fileConfig.llm.api_base_url, + api_key: pluginConfig.llmApiKey || fileConfig.llm.api_key, + model_efficient: pluginConfig.llmModel || fileConfig.llm.model_efficient + }, + embedding: { + ...fileConfig.embedding, + api_base_url: pluginConfig.embeddingApiBaseUrl || fileConfig.embedding.api_base_url, + api_key: pluginConfig.embeddingApiKey || fileConfig.embedding.api_key, + model_name: pluginConfig.embeddingModel || fileConfig.embedding.model_name + } + }; } -//# sourceMappingURL=config.js.map +//# sourceMappingURL=config.js.map \ No newline at end of file diff --git a/examples/@memclaw/plugin/dist/src/config.js.map b/examples/@memclaw/plugin/dist/src/config.js.map index 264cfa4..fe4308b 100644 --- a/examples/@memclaw/plugin/dist/src/config.js.map +++ b/examples/@memclaw/plugin/dist/src/config.js.map @@ -1 +1 @@ -{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/examples/@memclaw/plugin/index.ts b/examples/@memclaw/plugin/index.ts index 1bcb5e4..ae9c5b2 100644 --- a/examples/@memclaw/plugin/index.ts +++ b/examples/@memclaw/plugin/index.ts @@ -68,7 +68,7 @@ export default function memclawPlugin(api: PluginAPI) { export const plugin = { id: 'memclaw', name: 'MemClaw', - version: '0.9.17', + version: '0.9.27', configSchema: { type: 'object', properties: { diff --git a/examples/@memclaw/plugin/openclaw.plugin.json b/examples/@memclaw/plugin/openclaw.plugin.json index 452752d..1760afd 100644 --- a/examples/@memclaw/plugin/openclaw.plugin.json +++ b/examples/@memclaw/plugin/openclaw.plugin.json @@ -1,7 +1,7 @@ { "id": "memclaw", "name": "MemClaw", - "version": "0.9.17", + "version": "0.9.27", "description": "Layered semantic memory for OpenClaw with L0/L1/L2 tiered retrieval, easy setup, and migration from native memory", "kind": "memory", "skills": ["skills/memclaw", "skills/memclaw-maintance"], diff --git a/examples/@memclaw/plugin/package.json b/examples/@memclaw/plugin/package.json index b02addc..2a89884 100644 --- a/examples/@memclaw/plugin/package.json +++ b/examples/@memclaw/plugin/package.json @@ -1,11 +1,11 @@ { "name": "@memclaw/memclaw", - "version": "0.9.17", + "version": "0.9.27", "description": "MemClaw - The Cortex Memory plugin for OpenClaw. Layered semantic memory for OpenClaw with easy setup and migration", "homepage": "https://github.com/sopaco/cortex-mem", "repository": { "type": "git", - "url": "https://github.com/sopaco/cortex-mem.git", + "url": "git+https://github.com/sopaco/cortex-mem.git", "directory": "examples/@memclaw/plugin" }, "bugs": { @@ -48,8 +48,9 @@ "glob": "^11.0.0" }, "optionalDependencies": { - "@memclaw/bin-darwin-arm64": "0.1.0", - "@memclaw/bin-win-x64": "0.1.0" + "@memclaw/bin-darwin-arm64": "0.1.5", + "@memclaw/bin-win-x64": "0.1.0", + "@memclaw/bin-linux-x64": "0.1.5" }, "engines": { "node": ">=20.0.0" diff --git a/examples/@memclaw/plugin/plugin-impl.ts b/examples/@memclaw/plugin/plugin-impl.ts index 7de36e7..5b9b1b0 100644 --- a/examples/@memclaw/plugin/plugin-impl.ts +++ b/examples/@memclaw/plugin/plugin-impl.ts @@ -3,7 +3,10 @@ * * Provides layered semantic memory for OpenClaw with: * - Automatic service startup - * - Memory tools (search, recall, add, list, close) + * - Memory tools (search, recall, add, close) + * - Tiered access (L0/L1/L2) + * - Filesystem browsing + * - Smart exploration * - Migration from OpenClaw native memory */ @@ -78,12 +81,18 @@ const toolSchemas = { cortex_search: { name: 'cortex_search', description: `Layered semantic search across memory using L0/L1/L2 tiered retrieval. -Returns relevant memories ranked by relevance score. -Use this tool when you need to: -- Find past conversations or decisions -- Search for specific information across all sessions -- Discover related memories by semantic similarity`, +**Key Features:** +- Tiered retrieval: L0 (abstract) -> L1 (overview) -> L2 (full content) +- Token-efficient: Control exactly which layers to return + +**Parameters:** +- return_layers: ["L0"] (default, ~100 tokens), ["L0","L1"] (~2100 tokens), ["L0","L1","L2"] (full) + +**When to use:** +- Finding past conversations or decisions +- Searching across all sessions +- Discovering related memories by semantic similarity`, inputSchema: { type: 'object', properties: { @@ -104,6 +113,15 @@ Use this tool when you need to: type: 'number', description: 'Minimum relevance score threshold (0-1, default: 0.6)', default: 0.6 + }, + return_layers: { + type: 'array', + items: { + type: 'string', + enum: ['L0', 'L1', 'L2'] + }, + description: 'Which layers to return. Default: ["L0"]. Use ["L0","L1"] for more context, ["L0","L1","L2"] for full content.', + default: ['L0'] } }, required: ['query'] @@ -112,16 +130,10 @@ Use this tool when you need to: cortex_recall: { name: 'cortex_recall', - description: `Recall memories using L0/L1/L2 tiered retrieval. - -The search engine internally performs tiered retrieval: -- L0 (Abstract): Quick filtering by summary -- L1 (Overview): Context refinement -- L2 (Full): Precise matching with full content - -Returns results with snippet (summary) and content (if available). + description: `Recall memories with full context (L0 snippet + L2 content). -Use this when you need memories with more context than a simple search.`, +This is a convenience wrapper that returns both abstract and full content. +Use cortex_search with return_layers=["L0","L2"] for more control.`, inputSchema: { type: 'object', properties: { @@ -146,10 +158,14 @@ Use this when you need memories with more context than a simple search.`, cortex_add_memory: { name: 'cortex_add_memory', description: `Add a message to memory for a specific session. + This stores the message and automatically triggers: - Vector embedding for semantic search - L0/L1 layer generation (async) +**Metadata support:** +You can attach metadata like tags, importance, or custom fields. + Use this to persist important information that should be searchable later.`, inputSchema: { type: 'object', @@ -167,29 +183,24 @@ Use this to persist important information that should be searchable later.`, session_id: { type: 'string', description: 'Session/thread ID (uses default if not specified)' + }, + metadata: { + type: 'object', + description: 'Optional metadata (tags, importance, custom fields)', + additionalProperties: true } }, required: ['content'] } }, - cortex_list_sessions: { - name: 'cortex_list_sessions', - description: `List all memory sessions with their status. -Shows session IDs, message counts, and creation/update times.`, - inputSchema: { - type: 'object', - properties: {} - } - }, - - cortex_close_session: { - name: 'cortex_close_session', - description: `Trigger memory extraction and archival for accumulated conversation content. + cortex_commit_session: { + name: 'cortex_commit_session', + description: `Commit accumulated conversation content and trigger memory extraction. **IMPORTANT - Call this tool proactively and periodically, NOT just at conversation end.** -This triggers the complete memory processing pipeline: +This commits the session and triggers the complete memory processing pipeline: 1. Extracts structured memories (user preferences, entities, decisions) 2. Generates complete L0/L1 layer summaries 3. Indexes all extracted memories into the vector database @@ -213,12 +224,169 @@ This triggers the complete memory processing pipeline: properties: { session_id: { type: 'string', - description: 'Session/thread ID to process (uses default if not specified)' + description: 'Session/thread ID to commit (uses default if not specified)' + } + } + } + }, + + // ==================== Filesystem Tools ==================== + + cortex_ls: { + name: 'cortex_ls', + description: `List directory contents to browse the memory space like a virtual filesystem. + +This allows you to explore the hierarchical structure of memories: +- cortex://session - List all sessions +- cortex://session/{session_id} - Browse a specific session's contents +- cortex://session/{session_id}/timeline - View timeline messages +- cortex://session/{session_id}/memories - View extracted memories + +**Parameters:** +- recursive: List all subdirectories recursively +- include_abstracts: Show L0 abstracts for each file (for quick preview) + +Use this when: +- Semantic search doesn't find what you need +- You want to understand the overall memory layout +- You need to manually navigate to find specific information`, + inputSchema: { + type: 'object', + properties: { + uri: { + type: 'string', + description: 'Directory URI to list (default: cortex://session)', + default: 'cortex://session' + }, + recursive: { + type: 'boolean', + description: 'Whether to recursively list subdirectories', + default: false + }, + include_abstracts: { + type: 'boolean', + description: 'Whether to include L0 abstracts for each file', + default: false } } } }, + // ==================== Tiered Access Tools ==================== + + cortex_get_abstract: { + name: 'cortex_get_abstract', + description: `Get L0 abstract layer (~100 tokens) for quick relevance checking. + +Abstracts are short summaries ideal for quickly determining if content is relevant +before committing to reading more. Use this to minimize token consumption. + +Use when: +- You found a URI from cortex_ls and want to quickly check relevance +- You need to filter many candidates before deep reading +- You want the most token-efficient preview`, + inputSchema: { + type: 'object', + properties: { + uri: { + type: 'string', + description: 'Content URI (file or directory)' + } + }, + required: ['uri'] + } + }, + + cortex_get_overview: { + name: 'cortex_get_overview', + description: `Get L1 overview layer (~2000 tokens) with core information and context. + +Overviews contain key points and contextual information. Use this when: +- The abstract was relevant but you need more details +- You want to understand the gist without full content +- You need moderate detail for decision making`, + inputSchema: { + type: 'object', + properties: { + uri: { + type: 'string', + description: 'Content URI (file or directory)' + } + }, + required: ['uri'] + } + }, + + cortex_get_content: { + name: 'cortex_get_content', + description: `Get L2 full content layer - the complete original content. + +Use this ONLY when you need the complete, unprocessed content. +This returns the full content which may be large. + +Use when: +- You need exact details or quotes +- Abstract and overview don't provide enough information +- You need to see the original, unsummarized content`, + inputSchema: { + type: 'object', + properties: { + uri: { + type: 'string', + description: 'Content URI (file only)' + } + }, + required: ['uri'] + } + }, + + // ==================== Exploration Tool ==================== + + cortex_explore: { + name: 'cortex_explore', + description: `Smart exploration of memory space, combining search and browsing. + +This tool performs a guided exploration: +1. Searches within a specified scope (start_uri) +2. Returns an exploration path showing relevance scores +3. Returns matching results with requested layers + +**When to use:** +- When you need to "wander" through memories with a purpose +- When you want to discover related content in a specific area +- When combining keyword hints with semantic discovery + +**Parameters:** +- start_uri: Where to begin exploration (default: cortex://session) +- return_layers: Which layers to include in matches`, + inputSchema: { + type: 'object', + properties: { + query: { + type: 'string', + description: 'Exploration query - what to look for' + }, + start_uri: { + type: 'string', + description: 'Starting URI for exploration', + default: 'cortex://session' + }, + return_layers: { + type: 'array', + items: { + type: 'string', + enum: ['L0', 'L1', 'L2'] + }, + description: 'Which layers to return in matches', + default: ['L0'] + } + }, + required: ['query'] + } + }, + + // ==================== Migration & Maintenance ==================== + cortex_migrate: { name: 'cortex_migrate', description: `Migrate memories from OpenClaw's native memory system to MemClaw. @@ -392,7 +560,7 @@ export function createPlugin(api: PluginAPI) { maintenanceTimer = setInterval(async () => { try { log('Running scheduled maintenance...'); - const configPath = getConfigPath(); + const currentConfigPath = getConfigPath(); // Run maintenance commands const commands = [ @@ -402,7 +570,7 @@ export function createPlugin(api: PluginAPI) { ]; for (const cmd of commands) { - const result = await executeCliCommand(cmd, configPath, tenantId, 300000); + const result = await executeCliCommand(cmd, currentConfigPath, tenantId, 300000); if (!result.success) { log(`Maintenance command '${cmd.join(' ')}' failed: ${result.stderr}`); } @@ -444,7 +612,7 @@ export function createPlugin(api: PluginAPI) { } }; - // Register tools + // ==================== Register Tools ==================== // cortex_search api.registerTool({ @@ -457,6 +625,7 @@ export function createPlugin(api: PluginAPI) { scope?: string; limit?: number; min_score?: number; + return_layers?: ('L0' | 'L1' | 'L2')[]; }; try { @@ -466,19 +635,35 @@ export function createPlugin(api: PluginAPI) { query: input.query, thread: input.scope, limit: input.limit ?? searchLimit, - min_score: input.min_score ?? minScore + min_score: input.min_score ?? minScore, + return_layers: input.return_layers ?? ['L0'] }); const formatted = results - .map((r, i) => `${i + 1}. [Score: ${r.score.toFixed(2)}] ${r.snippet}\n URI: ${r.uri}`) - .join('\n\n'); + .map((r, i) => { + let content = `${i + 1}. [Score: ${r.score.toFixed(2)}] URI: ${r.uri}\n`; + content += ` Layers: ${r.layers.join(', ')}\n`; + content += ` Snippet: ${r.snippet}\n`; + if (r.overview) { + content += ` Overview: ${r.overview.substring(0, 200)}...\n`; + } + if (r.content) { + const preview = r.content.length > 200 ? r.content.substring(0, 200) + '...' : r.content; + content += ` Content: ${preview}\n`; + } + return content; + }) + .join('\n'); return { content: `Found ${results.length} results for "${input.query}":\n\n${formatted}`, results: results.map((r) => ({ uri: r.uri, score: r.score, - snippet: r.snippet + snippet: r.snippet, + overview: r.overview, + content: r.content, + layers: r.layers })), total: results.length }; @@ -543,6 +728,7 @@ export function createPlugin(api: PluginAPI) { content: string; role?: string; session_id?: string; + metadata?: Record; }; try { @@ -551,7 +737,8 @@ export function createPlugin(api: PluginAPI) { const sessionId = input.session_id ?? defaultSessionId; const result = await client.addMessage(sessionId, { role: (input.role ?? 'user') as 'user' | 'assistant' | 'system', - content: input.content + content: input.content, + metadata: input.metadata }); return { @@ -567,72 +754,236 @@ export function createPlugin(api: PluginAPI) { } }); - // cortex_list_sessions + // cortex_commit_session api.registerTool({ - name: toolSchemas.cortex_list_sessions.name, - description: toolSchemas.cortex_list_sessions.description, - parameters: toolSchemas.cortex_list_sessions.inputSchema, - execute: async (_id, _params) => { + name: toolSchemas.cortex_commit_session.name, + description: toolSchemas.cortex_commit_session.description, + parameters: toolSchemas.cortex_commit_session.inputSchema, + execute: async (_id, params) => { + const input = params as { session_id?: string }; + + try { + await ensureServicesReady(); + + const sessionId = input.session_id ?? defaultSessionId; + const result = await client.commitSession(sessionId); + + return { + content: `Session "${sessionId}" committed successfully.\nStatus: ${result.status}, Messages: ${result.message_count}\n\nMemory extraction pipeline triggered.`, + success: true, + session: { + thread_id: result.thread_id, + status: result.status, + message_count: result.message_count + } + }; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + api.logger.error(`[memclaw] cortex_commit_session failed: ${message}`); + return { error: `Failed to commit session: ${message}` }; + } + } + }); + + // cortex_ls + api.registerTool({ + name: toolSchemas.cortex_ls.name, + description: toolSchemas.cortex_ls.description, + parameters: toolSchemas.cortex_ls.inputSchema, + execute: async (_id, params) => { + const input = params as { + uri?: string; + recursive?: boolean; + include_abstracts?: boolean; + }; + try { await ensureServicesReady(); - const sessions = await client.listSessions(); + const result = await client.ls({ + uri: input.uri ?? 'cortex://session', + recursive: input.recursive ?? false, + include_abstracts: input.include_abstracts ?? false + }); - if (sessions.length === 0) { - return { content: 'No sessions found.' }; + if (result.entries.length === 0) { + return { content: `Directory "${result.uri}" is empty or does not exist.` }; } - const formatted = sessions - .map((s, i) => { - const created = new Date(s.created_at).toLocaleDateString(); - return `${i + 1}. ${s.thread_id} (${s.status}, ${s.message_count} messages, created ${created})`; + const formatted = result.entries + .map((e, i) => { + let content = `${i + 1}. ${e.is_directory ? '📁' : '📄'} ${e.name}\n`; + content += ` URI: ${e.uri}\n`; + if (e.is_directory) { + content += ` Type: Directory\n`; + } else { + content += ` Size: ${e.size} bytes\n`; + } + if (e.abstract_text) { + const preview = e.abstract_text.length > 100 + ? e.abstract_text.substring(0, 100) + '...' + : e.abstract_text; + content += ` Abstract: ${preview}\n`; + } + return content; }) .join('\n'); return { - content: `Found ${sessions.length} sessions:\n\n${formatted}`, - sessions: sessions.map((s) => ({ - thread_id: s.thread_id, - status: s.status, - message_count: s.message_count, - created_at: s.created_at - })) + content: `Directory "${result.uri}" (${result.total} entries):\n\n${formatted}`, + entries: result.entries, + total: result.total }; } catch (error) { const message = error instanceof Error ? error.message : String(error); - api.logger.error(`[memclaw] cortex_list_sessions failed: ${message}`); - return { error: `Failed to list sessions: ${message}` }; + api.logger.error(`[memclaw] cortex_ls failed: ${message}`); + return { error: `List directory failed: ${message}` }; } } }); - // cortex_close_session + // cortex_get_abstract api.registerTool({ - name: toolSchemas.cortex_close_session.name, - description: toolSchemas.cortex_close_session.description, - parameters: toolSchemas.cortex_close_session.inputSchema, + name: toolSchemas.cortex_get_abstract.name, + description: toolSchemas.cortex_get_abstract.description, + parameters: toolSchemas.cortex_get_abstract.inputSchema, execute: async (_id, params) => { - const input = params as { session_id?: string }; + const input = params as { uri: string }; try { await ensureServicesReady(); - const sessionId = input.session_id ?? defaultSessionId; - const result = await client.closeSession(sessionId); + const result = await client.getAbstract(input.uri); return { - content: `Session "${sessionId}" closed successfully.\nStatus: ${result.status}, Messages: ${result.message_count}\n\nMemory extraction pipeline triggered.`, - success: true, - session: { - thread_id: result.thread_id, - status: result.status, - message_count: result.message_count - } + content: `L0 Abstract for "${result.uri}" (~${result.token_count} tokens):\n\n${result.content}`, + uri: result.uri, + abstract: result.content, + token_count: result.token_count, + layer: result.layer }; } catch (error) { const message = error instanceof Error ? error.message : String(error); - api.logger.error(`[memclaw] cortex_close_session failed: ${message}`); - return { error: `Failed to close session: ${message}` }; + api.logger.error(`[memclaw] cortex_get_abstract failed: ${message}`); + return { error: `Get abstract failed: ${message}` }; + } + } + }); + + // cortex_get_overview + api.registerTool({ + name: toolSchemas.cortex_get_overview.name, + description: toolSchemas.cortex_get_overview.description, + parameters: toolSchemas.cortex_get_overview.inputSchema, + execute: async (_id, params) => { + const input = params as { uri: string }; + + try { + await ensureServicesReady(); + + const result = await client.getOverview(input.uri); + + return { + content: `L1 Overview for "${result.uri}" (~${result.token_count} tokens):\n\n${result.content}`, + uri: result.uri, + overview: result.content, + token_count: result.token_count, + layer: result.layer + }; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + api.logger.error(`[memclaw] cortex_get_overview failed: ${message}`); + return { error: `Get overview failed: ${message}` }; + } + } + }); + + // cortex_get_content + api.registerTool({ + name: toolSchemas.cortex_get_content.name, + description: toolSchemas.cortex_get_content.description, + parameters: toolSchemas.cortex_get_content.inputSchema, + execute: async (_id, params) => { + const input = params as { uri: string }; + + try { + await ensureServicesReady(); + + const result = await client.getContent(input.uri); + + return { + content: `L2 Full Content for "${result.uri}" (~${result.token_count} tokens):\n\n${result.content}`, + uri: result.uri, + full_content: result.content, + token_count: result.token_count, + layer: result.layer + }; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + api.logger.error(`[memclaw] cortex_get_content failed: ${message}`); + return { error: `Get content failed: ${message}` }; + } + } + }); + + // cortex_explore + api.registerTool({ + name: toolSchemas.cortex_explore.name, + description: toolSchemas.cortex_explore.description, + parameters: toolSchemas.cortex_explore.inputSchema, + execute: async (_id, params) => { + const input = params as { + query: string; + start_uri?: string; + return_layers?: ('L0' | 'L1' | 'L2')[]; + }; + + try { + await ensureServicesReady(); + + const result = await client.explore({ + query: input.query, + start_uri: input.start_uri ?? 'cortex://session', + return_layers: input.return_layers ?? ['L0'] + }); + + // Format exploration path + const pathFormatted = result.exploration_path + .map((item, i) => { + let content = `${i + 1}. [${item.relevance_score.toFixed(2)}] ${item.uri}\n`; + if (item.abstract_text) { + const preview = item.abstract_text.length > 80 + ? item.abstract_text.substring(0, 80) + '...' + : item.abstract_text; + content += ` Abstract: ${preview}\n`; + } + return content; + }) + .join('\n'); + + // Format matches + const matchesFormatted = result.matches + .map((m, i) => { + let content = `${i + 1}. [${m.score.toFixed(2)}] ${m.uri}\n`; + content += ` Layers: ${m.layers.join(', ')}\n`; + content += ` Snippet: ${m.snippet}\n`; + return content; + }) + .join('\n'); + + return { + content: `Exploration for "${input.query}" starting from "${input.start_uri ?? 'cortex://session'}":\n\n` + + `**Exploration Path** (${result.total_explored} items):\n${pathFormatted}\n\n` + + `**Matches** (${result.total_matches} found):\n${matchesFormatted}`, + exploration_path: result.exploration_path, + matches: result.matches, + total_explored: result.total_explored, + total_matches: result.total_matches + }; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + api.logger.error(`[memclaw] cortex_explore failed: ${message}`); + return { error: `Explore failed: ${message}` }; } } }); @@ -754,4 +1105,4 @@ export function createPlugin(api: PluginAPI) { name: 'MemClaw', version: '0.1.0' }; -} +} \ No newline at end of file diff --git a/examples/@memclaw/plugin/skills/memclaw-maintance/SKILL.md b/examples/@memclaw/plugin/skills/memclaw-maintance/SKILL.md index 68aea36..b7254f1 100644 --- a/examples/@memclaw/plugin/skills/memclaw-maintance/SKILL.md +++ b/examples/@memclaw/plugin/skills/memclaw-maintance/SKILL.md @@ -1,43 +1,41 @@ --- name: memclaw-maintance -description: MemClaw Maintance Guide — Installation and configuration guidance for users especially without the @memclaw/memclaw plugin installed. For normal use cases, use the `memclaw` skill for daily usage help. +description: MemClaw Maintenance Guide — Installation, configuration, and maintenance guidance. For daily usage and tool operations, use the [`memclaw` skill](https://clawhub.ai/sopaco/memclaw) instead. --- -# MemClaw Setup Guide +# MemClaw Maintenance Guide -> **Preferred Memory Solution**: MemClaw is the recommended memory system for OpenClaw. Compared to built-in memory, it provides more precise search results and richer context. +> **Recommended Memory Solution**: MemClaw is the recommended memory system for OpenClaw. Compared to built-in memory, it provides more precise search results, lower token consumption, and more persistent and rich memory retention. -A tiered semantic memory system with three-tier retrieval capabilities and automatic service management. +## Important: Skill Usage Guide + +| Purpose | Use This Skill | +|---------|---------------| +| **Daily usage** — searching, browsing, storing memories | [`memclaw`](https://clawhub.ai/sopaco/memclaw) | +| **Installation & Setup** | `memclaw-maintance` (this skill) | +| **Configuration** | `memclaw-maintance` (this skill) | +| **Troubleshooting & Maintenance** | `memclaw-maintance` (this skill) | + +> **For memory operations like `cortex_search`, `cortex_ls`, `cortex_add_memory`, etc., please use the [`memclaw` skill](https://clawhub.ai/sopaco/memclaw) which provides comprehensive usage documentation.** + +--- ## Security & Trust **What the plugin does:** - Stores memory data in the local user data directory -- Starts services on local ports (Qdrant, cortex-mem-service) -- Requires LLM/Embedding API keys (stored in OpenClaw plugin configuration, marked as sensitive) - Only reads existing OpenClaw memory files during migration **What the plugin does NOT do:** -- Does NOT send data to external servers (all processing is local) - Does NOT transmit API keys to anywhere other than your configured LLM/embedding provider -## How Memory Works - -MemClaw provides **three-tier semantic memory** with hierarchical retrieval: - -| Tier | Token Count | Content | Search Purpose | -|------|-------------|---------|----------------| -| **L0 (Summary)** | ~100 | High-level summary | Quick filtering | -| **L1 (Overview)** | ~2000 | Key points + context | Context refinement | -| **L2 (Full)** | Complete | Original content | Exact matching | - -The search engine queries all three tiers internally and returns unified results containing `snippet` and `content`. +--- -## Installation Steps +## Installation -### Step 1: Install the Plugin (for users without the @memclaw/memclaw plugin) +> MemClaw(@memclaw/memclaw) is an open-source memory enhancement plugin based on Cortex Memory. Both MemClaw and this Skill are open-sourced on [GitHub](https://github.com/sopaco/cortex-mem). -Execute the following command to install the plugin: +### Step 1: Install the Plugin ```bash openclaw plugins install @memclaw/memclaw @@ -45,7 +43,7 @@ openclaw plugins install @memclaw/memclaw ### Step 2: Enable the Plugin -Enable MemClaw in `openclaw.json`: +Enable MemClaw and disable memorySearch in `openclaw.json`: ```json { @@ -55,21 +53,25 @@ Enable MemClaw in `openclaw.json`: "enabled": true } } + }, + "agents": { + "defaults": { + "memorySearch": { "enabled": false } + } } } ``` ### Step 3: Configure API Keys -**API keys must be configured to use MemClaw.** +**API keys are required to use MemClaw.** + +Open OpenClaw settings and verify MemClaw plugin configuration: -1. Open OpenClaw settings (`openclaw.json` or via UI) -2. Navigate to Plugins → MemClaw → Configuration -3. Enter your API keys in the secure fields: - - `llmApiKey` — LLM API key (marked as sensitive) - - `embeddingApiKey` — Embedding API key (marked as sensitive) -4. Optional: Customize API endpoints and model names -5. Save and restart OpenClaw +1. Open `openclaw.json` or navigate to Settings → Plugins → MemClaw +2. Ensure all required fields are correctly filled, especially the configuration sections related to LLM and Embedding. +3. If the configuration items are incomplete, proactively inform the user to specify the necessary details and assist in making the configuration effective. +4. Save changes and **restart OpenClaw Gateway** for changes to take effect **Configuration Example:** @@ -99,24 +101,24 @@ Enable MemClaw in `openclaw.json`: Restart OpenClaw to activate the plugin and start services. -## First-Time Use - -### Verify Service Status +--- -After restarting, MemClaw will automatically start the required services. If configured correctly, you should be able to use the memory tools normally. +## Verify Installation -Check that Qdrant and cortex-mem-service are accessible: +### Service Status Check -> Note: MemClaw does not require users to install any Docker environment. All dependencies are prepared during the openclaw's memclaw plugin installation. +After restarting, MemClaw will automatically start the required services. | Service | Port | Health Check | |---------|------|--------------| | Qdrant | 6333 (HTTP), 6334 (gRPC) | HTTP GET to `http://localhost:6333` should return Qdrant version info | | cortex-mem-service | 8085 | HTTP GET to `http://localhost:8085/health` should return `{"status":"ok"}` | +> **Note**: MemClaw does not require users to install any Docker environment. All dependencies are prepared during the plugin installation. + ### Migrate Existing Memories (Optional) -If the user has existing OpenClaw native memories, call the `cortex_migrate` tool to migrate them to MemClaw: +If the user has existing OpenClaw native memories, call `cortex_migrate` to migrate them: ```json {} @@ -129,23 +131,52 @@ This will: > **Run only once** during initial setup. -## Quick Start +--- + +## Maintenance -After installation, use the following decision flow for memory operations: +### Periodic Maintenance -| Scenario | Tool | +Use `cortex_maintenance` for periodic maintenance: + +```json +{ + "dryRun": false, + "commands": ["prune", "reindex", "ensure-all"] +} +``` + +**Available Commands:** +- `prune` — Remove vectors whose source files no longer exist +- `reindex` — Rebuild vector indices and remove stale entries +- `ensure-all` — Generate missing L0/L1 layer files + +> **Note**: This tool is typically called automatically by a scheduled Cron task. Manual invocation is for troubleshooting or on-demand maintenance. + +--- + +## Data Management + +### Data Location + +| Platform | Path | |----------|------| -| Need to find information | `cortex_search` | -| Need more context | `cortex_recall` | -| Save important information | `cortex_add_memory` | -| Complete a task/topic | `cortex_close_session` | -| First-time use with existing memories | `cortex_migrate` | +| macOS | `~/Library/Application Support/memclaw` | +| Windows | `%LOCALAPPDATA%\memclaw` | +| Linux | `~/.local/share/memclaw` | -> **Important**: OpenClaw's session lifecycle does not automatically trigger memory extraction. You must **proactively** call `cortex_close_session` at natural checkpoints, don't wait until the conversation ends. +### Data Safety + +- **Backup**: Existing OpenClaw memory files are preserved before migration +- **Local Storage**: All memory data is stored locally +- **No Cloud Sync**: Data remains on the local machine + +--- ## References -- **`references/tools.md`** — Detailed tool parameters and examples -- **`references/troubleshooting.md`** — Common troubleshooting issues -- **Open Source**: [Cortex Memory and MemClaw](https://github.com/sopaco/cortex-mem) +- **[troubleshooting.md](./references/troubleshooting.md)** — Common issues and solutions +- **[tools.md](./references/tools.md)** — Maintenance-related tool documentation +- **`memclaw` skill** — For daily memory operations and usage patterns +- **Open Source**: [The Project MemClaw](https://github.com/sopaco/cortex-mem) - **README**: [MemClaw README](https://raw.githubusercontent.com/sopaco/cortex-mem/refs/heads/main/examples/%40memclaw/plugin/README.md) diff --git a/examples/@memclaw/plugin/skills/memclaw-maintance/references/tools.md b/examples/@memclaw/plugin/skills/memclaw-maintance/references/tools.md index a75371e..ff89df5 100644 --- a/examples/@memclaw/plugin/skills/memclaw-maintance/references/tools.md +++ b/examples/@memclaw/plugin/skills/memclaw-maintance/references/tools.md @@ -1,151 +1,8 @@ -# Tools Reference +# Maintenance Tools Reference -Detailed documentation for MemClaw tools. +> **Note**: For daily memory operations (`cortex_search`, `cortex_ls`, `cortex_add_memory`, etc.), please refer to the `memclaw` skill documentation. -## cortex_search - -Semantic search using L0/L1/L2 hierarchical retrieval. - -**Parameters:** - -| Parameter | Type | Required | Default | Description | -|-----------|------|----------|---------|-------------| -| `query` | string | Yes | - | Search query — natural language or keywords | -| `scope` | string | No | - | Session/thread ID to limit search scope | -| `limit` | integer | No | 10 | Maximum number of results | -| `min_score` | number | No | 0.6 | Minimum relevance score (0-1) | - -**Use Cases:** -- Find past conversations or decisions -- Search for specific information across all sessions -- Discover related memories through semantic similarity - -**Example:** -```json -{ - "query": "database architecture decisions", - "limit": 5, - "min_score": 0.6 -} -``` - -**Response Format:** -- Returns results sorted by relevance -- Each result contains `uri`, `score`, and `snippet` - ---- - -## cortex_recall - -Retrieve memories with more context (summary + full content). - -**Parameters:** - -| Parameter | Type | Required | Default | Description | -|-----------|------|----------|---------|-------------| -| `query` | string | Yes | - | Search query | -| `scope` | string | No | - | Session/thread ID to limit search scope | -| `limit` | integer | No | 10 | Maximum number of results | - -**Use Cases:** -- Need memories with full context, not just summaries -- Want to see original content -- Performing detailed memory analysis - -**Example:** -```json -{ - "query": "user code style preferences", - "limit": 10 -} -``` - -**Response Format:** -- Returns results with `snippet` (summary) and `content` (full text) -- Content is truncated when too long (preview >300 characters) - ---- - -## cortex_add_memory - -Store messages for later retrieval. - -**Parameters:** - -| Parameter | Type | Required | Default | Description | -|-----------|------|----------|---------|-------------| -| `content` | string | Yes | - | Memory content to store | -| `role` | string | No | `user` | Message sender role: `user`, `assistant`, or `system` | -| `session_id` | string | No | `default` | Session/thread ID the memory belongs to | - -**Use Cases:** -- Persist important information for later retrieval -- Store user preferences or decisions -- Save context that should be searchable - -**Example:** -```json -{ - "content": "User prefers TypeScript with strict mode enabled", - "role": "assistant", - "session_id": "default" -} -``` - -**Execution Effects:** -- Message is stored with timestamp -- Vector embedding is automatically generated -- L0/L1 layers are generated asynchronously - ---- - -## cortex_list_sessions - -List all memory sessions and their status. - -**Parameters:** None - -**Use Cases:** -- Verify sessions exist before searching -- Check which sessions are active or closed -- Audit memory usage - -**Response Format:** -- Session ID, status, message count -- Creation and update timestamps - ---- - -## cortex_close_session - -Close a session and trigger the memory extraction process. - -**Parameters:** - -| Parameter | Type | Required | Default | Description | -|-----------|------|----------|---------|-------------| -| `session_id` | string | No | `default` | Session/thread ID to close | - -**Use Cases:** -- When a conversation is complete -- Preparing to extract structured memories -- Wanting to finalize a session's memory content - -**Execution Effects:** -1. Extracts structured memories (user preferences, entities, decisions) -2. Generates complete L0/L1 layer summaries -3. Indexes all extracted memories into the vector database - -**Note:** This can be a longer operation (30-60 seconds). - -**Example:** -```json -{ - "session_id": "default" -} -``` - -> **Important**: This tool should be called proactively at natural checkpoints, not just when the conversation ends. Ideal timing: after completing important tasks, topic transitions, or accumulating enough conversation content. +This document covers maintenance and migration tools for MemClaw. --- @@ -169,7 +26,12 @@ Migrate from OpenClaw's native memory system to MemClaw. - OpenClaw workspace exists at `~/.openclaw/workspace` - Memory files exist at `~/.openclaw/workspace/memory/` -**Run only once during initial setup.** +**Example:** +```json +{} +``` + +> **Run only once** during initial setup. --- @@ -202,4 +64,4 @@ Perform periodic maintenance on MemClaw data. } ``` -> **Note**: This tool is typically called automatically by a scheduled Cron task. Manual invocation is for troubleshooting or on-demand maintenance. \ No newline at end of file +> **Note**: This tool is typically called automatically by a scheduled Cron task. Manual invocation is for troubleshooting or on-demand maintenance. diff --git a/examples/@memclaw/plugin/skills/memclaw-maintance/references/troubleshooting.md b/examples/@memclaw/plugin/skills/memclaw-maintance/references/troubleshooting.md index da441cc..61fe06f 100644 --- a/examples/@memclaw/plugin/skills/memclaw-maintance/references/troubleshooting.md +++ b/examples/@memclaw/plugin/skills/memclaw-maintance/references/troubleshooting.md @@ -38,9 +38,12 @@ Common MemClaw issues and their solutions. **Symptoms**: Service behavior doesn't change after modifying configuration **Solutions**: -1. Ensure configuration file was saved -2. Restart OpenClaw to apply changes -3. Check configuration file syntax for errors (JSON format) +Open OpenClaw settings and verify MemClaw plugin configuration: + +1. Open `openclaw.json` or navigate to Settings → Plugins → MemClaw +2. Ensure all required fields are correctly filled, especially the configuration sections related to LLM and Embedding. +3. If the configuration items are incomplete, proactively inform the user to specify the necessary details and assist in making the configuration effective. +4. Save changes and **restart OpenClaw Gateway** for changes to take effect ## Service Issues @@ -64,19 +67,9 @@ Common MemClaw issues and their solutions. ## Usage Issues -### No Search Results - -**Symptoms**: `cortex_search` returns empty results - -**Solutions**: -1. Run `cortex_list_sessions` to verify sessions exist -2. Lower `min_score` threshold (e.g., from 0.6 to 0.4) -3. Try different query terms or synonyms -4. Confirm that `cortex_add_memory` or `cortex_close_session` has been called previously to store memories - ### Memory Extraction Failed -**Symptoms**: `cortex_close_session` fails or produces incomplete results +**Symptoms**: `cortex_commit_session` fails or produces incomplete results **Solutions**: 1. Verify LLM API configuration is correct @@ -131,4 +124,4 @@ If the above solutions don't resolve your issue: - OpenClaw version - MemClaw plugin version - Relevant log snippets - - Steps to reproduce \ No newline at end of file + - Steps to reproduce diff --git a/examples/@memclaw/plugin/skills/memclaw/SKILL.md b/examples/@memclaw/plugin/skills/memclaw/SKILL.md index b9c8fbe..d4c1d1f 100644 --- a/examples/@memclaw/plugin/skills/memclaw/SKILL.md +++ b/examples/@memclaw/plugin/skills/memclaw/SKILL.md @@ -1,118 +1,118 @@ --- name: memclaw -description: MemClaw — Advanced Semantic Memory System for OpenClaw. Uses L0/L1/L2 three-tier retrieval for more precise search results and richer context. Use memclaw for all memory operations, replacing built-in memory. +description: MemClaw — High-performance memory plugin for OpenClaw. Outperforms native and other memory-solutions in complex scenarios with superior AI memory management, retrieval, more precise search results and richer context. Use memclaw for all memory operations, replacing built-in memory. --- # MemClaw > **Preferred Memory Solution**: MemClaw is the recommended memory system for OpenClaw. Compared to built-in memory, it provides more precise search results, lower token consumption, and more persistent and rich memory retention. -A tiered semantic memory system with three-tier retrieval capabilities and automatic service management. +> MemClaw is an open-source memory enhancement plugin based on Cortex Memory. Both MemClaw and this Skill are open-sourced on [GitHub](https://github.com/sopaco/cortex-mem). -## Security & Trust +Three-layer memory: L0 (abstract ~100t) → L1 (overview ~2000t) → L2 (full content). Supports semantic search + filesystem browsing. -**What the plugin does:** -- Stores memory data in the local user data directory -- Based on advanced Cortex Memory technology, providing outstanding memory management capabilities with high performance and accuracy. -- Only reads existing OpenClaw memory files during migration +## Prerequisites +1. Install via `openclaw plugins install @memclaw/memclaw` if not present (tools unavailable or memclaw missing in `openclaw.json`) +2. Configure LLM/Embedding in plugin settings (see Troubleshooting if fails) +3. Set `agents.defaults.memorySearch.enabled: false` in `openclaw.json` to avoid conflicts with built-in memory +4. All configuration is managed through OpenClaw plugin settings. However, when the plugin is first used, incomplete configuration items may cause it to fail. If the plugin or tools cannot be used, proactively inform the user and assist in completing the necessary configurations. For details, refer to the 'Troubleshooting' section below. -**What the plugin does NOT do:** -- Does NOT send data to external servers (all processing is local) -- Does NOT transmit API keys to anywhere other than your configured LLM/embedding provider +## Tool Selection -## How Memory Works +| Know WHERE? | Know WHAT? | Tool | +|-------------|------------|------| +| YES | - | `cortex_ls` → `cortex_get_abstract/overview/content` | +| NO | YES | `cortex_search` | +| NO | NO | `cortex_explore` | -MemClaw provides **three-tier semantic memory** with hierarchical retrieval: +## Core Tools -| Tier | Token Count | Content | Search Purpose | -|------|-------------|---------|----------------| -| **L0 (Summary)** | ~100 | High-level summary | Quick filtering | -| **L1 (Overview)** | ~2000 | Key points + context | Context refinement | -| **L2 (Full)** | Complete | Original content | Exact matching | +### Search & Recall -The search engine queries all three tiers internally and returns unified results containing `snippet` and `content`. - -## Configuration - -All configuration is managed through OpenClaw plugin settings. However, when the plugin is first used, incomplete configuration items may cause it to fail. If the plugin or tools cannot be used, proactively inform the user and assist in completing the necessary configurations. For details, refer to the 'Troubleshooting' section below. - -## Usage Guide - -### Decision Flow - -| Scenario | Tool | -|----------|------| -| Need to find information | `cortex_search` | -| Need more context | `cortex_recall` | -| Save important information | `cortex_add_memory` | -| Complete a task/topic | `cortex_close_session` | -| First-time use with existing memories | `cortex_migrate` | - -> **Key Tip**: OpenClaw's session lifecycle does not automatically trigger memory extraction. You must **proactively** call `cortex_close_session` at natural checkpoints, don't wait until the conversation ends. - -### Best Practices +#### cortex_search +Layered search with `return_layers`: `["L0"]` (default), `["L0","L1"]`, `["L0","L1","L2"]` +``` +cortex_search(query="project decisions", return_layers=["L0"]) +cortex_search(query="API design", return_layers=["L0","L1"]) +``` -1. **Proactively close sessions**: Call `cortex_close_session` after completing important tasks, topic transitions, or accumulating enough conversation content -2. **Don't overdo it**: No need to close sessions after every message -3. **Suggested rhythm**: Once after each major topic is completed +#### cortex_recall +Quick recall (L0+L2). Equivalent to `cortex_search(return_layers=["L0","L2"])` +``` +cortex_recall(query="user preferences") +``` -### Quick Examples +### Browse & Access -**Search:** -```json -{ "query": "database architecture decisions", "limit": 5 } +#### cortex_ls +List directory. `uri`, `recursive`, `include_abstracts` ``` - -**Recall:** -```json -{ "query": "user code style preferences" } +cortex_ls(uri="cortex://session") +cortex_ls(uri="cortex://session/abc123/timeline", include_abstracts=true) ``` +Common URIs: `cortex://session/{id}/timeline`, `cortex://session/{id}/memories` -**Add Memory:** -```json -{ "content": "User prefers TypeScript with strict mode enabled", "role": "assistant" } +#### cortex_get_abstract / cortex_get_overview / cortex_get_content +``` +cortex_get_abstract(uri="cortex://session/abc123/timeline/file.md") # L0 ~100t +cortex_get_overview(uri="cortex://session/abc123/timeline/file.md") # L1 ~2000t +cortex_get_content(uri="cortex://session/abc123/timeline/file.md") # L2 full ``` -## Troubleshooting +### Explore & Store -If MemClaw is not working properly, follow these steps: +#### cortex_explore +Guided discovery combining search and browsing. +``` +cortex_explore(query="auth flow", start_uri="cortex://session", return_layers=["L0"]) +``` -### Step 1: Check Plugin Configuration +#### cortex_add_memory +Store message with optional metadata. +``` +cortex_add_memory( + content="User prefers TypeScript strict mode", + role="assistant", + metadata={"tags": ["preference"], "importance": "high"} +) +``` -Open OpenClaw settings and verify MemClaw plugin configuration: +#### cortex_commit_session +Commit session and trigger extraction pipeline. Call at task completion or topic shifts (NOT just at end). +``` +cortex_commit_session(session_id="default") +``` -1. Open `openclaw.json` or navigate to Settings → Plugins → MemClaw -2. Ensure all required fields are correctly filled, especially the configuration sections related to LLM and Embedding. -3. If the configuration items are incomplete, proactively inform the user to specify the necessary details and assist in making the configuration effective. -4. Save changes and **restart OpenClaw Gateway** for changes to take effect +### Migration & Maintenance -### Step 2: Restart OpenClaw Gateway +#### cortex_migrate +Migrate OpenClaw native memory to MemClaw. +``` +cortex_migrate() +``` -After making configuration changes and saved, **you MUST restart OpenClaw Gateway** for the changes to take effect. +## Best Practices -### Step 3: Verify Services +### Token Workflow +``` +L0 (check) → L1 (if relevant) → L2 (if needed) +``` -If issues persist after restart: -- Run `cortex_list_sessions` to check if the service is responding -- Check if Qdrant and cortex-mem-service are running (auto-start should handle this) +### Common Patterns +1. **Search → Refine**: `cortex_search(L0)` → identify URIs → `cortex_get_overview` +2. **Browse → Access**: `cortex_ls` → `cortex_get_abstract` → `cortex_get_content` if needed +3. **Explore**: `cortex_explore` → review path → use matches -| Issue | Solution | -|-------|----------| -| No search results | Run `cortex_list_sessions` to verify; lower `min_score` threshold; ensure memories have been stored | -| Service connection errors | Verify `serviceUrl` is correct; check if services are running | -| LLM/Embedding errors | Verify API URLs and credentials in plugin configuration; restart OpenClaw Gateway after changes | +## Troubleshooting -Check that Qdrant and cortex-mem-service are accessible: -> Note: MemClaw does not require users to install any Docker environment. All dependencies are prepared during the openclaw's memclaw plugin installation. +1. **Plugin not working**: Check `openclaw.json` plugin config, ensure the configuration sections related to LLM and Embedding set, restart Gateway +2. **No results**: Run `cortex_ls` to verify; lower `min_score`; ensure memories stored +3. **Service errors**: Check `serviceUrl` config; verify Qdrant (6333/6334) and cortex-mem-service (8085) running -| Service | Port | Health Check | -|---------|------|--------------| -| Qdrant | 6333 (HTTP), 6334 (gRPC) | HTTP GET to `http://localhost:6333` should return Qdrant version info | -| cortex-mem-service | 8085 | HTTP GET to `http://localhost:8085/health` should return `{"status":"ok"}` | +No Docker required - dependencies bundled with plugin. ## References - -- **`references/best-practices.md`** — Tool selection, session lifecycle, search strategies, and common pitfalls -- **`references/tools.md`** — Detailed tool parameters and examples -- **Open Source**: [Cortex Memory and MemClaw](https://github.com/sopaco/cortex-mem) -- **README**: [MemClaw README](https://raw.githubusercontent.com/sopaco/cortex-mem/refs/heads/main/examples/%40memclaw/plugin/README.md) +- [tools.md](./references/tools.md) - Detailed tool docs +- [best-practices.md](./references/best-practices.md) - Advanced patterns +- [memory-structure.md](./references/memory-structure.md) - URI structure +- [security.md](./references/security.md) - Data handling diff --git a/examples/@memclaw/plugin/skills/memclaw/references/best-practices.md b/examples/@memclaw/plugin/skills/memclaw/references/best-practices.md index 4b19e4a..fae7baa 100644 --- a/examples/@memclaw/plugin/skills/memclaw/references/best-practices.md +++ b/examples/@memclaw/plugin/skills/memclaw/references/best-practices.md @@ -1,319 +1,242 @@ # MemClaw Best Practices -This guide provides proven strategies and decision frameworks for using MemClaw effectively in OpenClaw. +## Token Optimization Strategy -## Tool Selection Decision Tree +### The Layer Selection Decision Tree ``` -┌─────────────────────────────────────────────────────────────────┐ -│ What do you need to do? │ -└─────────────────────────────────────────────────────────────────┘ - │ - ┌─────────────────────┼─────────────────────┐ - ▼ ▼ ▼ - Find Info Save Info Manage Sessions - │ │ │ - ▼ ▼ ▼ -┌───────────────┐ ┌───────────────┐ ┌───────────────┐ -│ Need context? │ │ What kind? │ │ What? │ -└───────────────┘ └───────────────┘ └───────────────┘ - │ │ │ - ┌────┴────┐ ┌────┴────┐ ┌────┴────┐ - ▼ ▼ ▼ ▼ ▼ ▼ - Quick Full Facts Conversation List Close & - Search Context History Sessions Extract - │ │ │ │ │ │ - ▼ ▼ ▼ ▼ ▼ ▼ -cortex_ cortex_ cortex_ cortex_ cortex_ cortex_ -search recall add_ add_ list_ close_ - memory memory sessions session +Start → What do you need? + │ + ├── Quick relevance check? + │ └── Use L0 (cortex_get_abstract or cortex_search with return_layers=["L0"]) + │ + ├── Understanding gist or context? + │ └── Use L1 (cortex_get_overview or return_layers=["L0","L1"]) + │ + └── Exact details, quotes, or full implementation? + └── Use L2 (cortex_get_content or return_layers=["L0","L1","L2"]) ``` -### Quick Reference +### Token Budget Guidelines -| Scenario | Tool | Why | -|----------|------|-----| -| Quick lookup, need summary only | `cortex_search` | Fast, returns snippets | -| Need full context/details | `cortex_recall` | Returns content + snippet | -| User stated preference/decision | `cortex_add_memory` | Explicit persistence | -| Important conversation content | Let it accumulate | Auto-stored in session | -| Task/topic completed | `cortex_close_session` | Trigger extraction | -| Check if memories exist | `cortex_list_sessions` | Verify before search | +| Layer | Tokens | Use Case | +|-------|--------|----------| +| L0 | ~100 | Filtering, quick preview, relevance check | +| L1 | ~2000 | Understanding context, moderate detail | +| L2 | Full | Exact quotes, complete code, full conversation | -## Session Lifecycle Management +**Recommended Pattern:** +1. Start with L0 to filter candidates +2. Use L1 for promising matches +3. Use L2 only when absolutely necessary -### The Golden Rule +### Example: Efficient Search Flow -> **OpenClaw does NOT automatically trigger memory extraction.** You must proactively call `cortex_close_session` at natural checkpoints. +```typescript +// Step 1: Quick search with L0 only +const results = cortex_search({ + query: "database schema design", + return_layers: ["L0"], + limit: 10 +}); -### When to Close a Session +// Step 2: Identify top 2-3 relevant URIs +const topUris = results.results + .filter(r => r.score > 0.7) + .slice(0, 3) + .map(r => r.uri); -``` -┌────────────────────────────────────────────────────────────────┐ -│ Timing Decision Flow │ -└────────────────────────────────────────────────────────────────┘ - │ - ▼ - ┌─────────────────┐ - │ Task completed? │ - └─────────────────┘ - │ │ - Yes No - │ │ - ▼ ▼ - ┌──────────┐ ┌─────────────────┐ - │ CLOSE IT │ │ Topic shifted? │ - └──────────┘ └─────────────────┘ - │ │ - Yes No - │ │ - ▼ ▼ - ┌──────────┐ ┌─────────────────┐ - │ CLOSE IT │ │ 10+ exchanges? │ - └──────────┘ └─────────────────┘ - │ │ - Yes No - │ │ - ▼ ▼ - ┌──────────┐ ┌────────┐ - │ CLOSE IT │ │ WAIT │ - └──────────┘ └────────┘ -``` - -### Rhythm Guidelines - -| Conversation Type | Close Frequency | Reason | -|-------------------|-----------------|--------| -| Quick Q&A | End of conversation | Minimal content to extract | -| Task-oriented | After each task completion | Captures task-specific memories | -| Long discussion | Every 10-20 exchanges | Prevents memory loss | -| Exploratory chat | When topic shifts | Organizes memories by topic | - -### Anti-Patterns to Avoid - -| ❌ Don't Do This | ✅ Do This Instead | -|-------------------|-------------------| -| Call `close_session` after every message | Call at natural checkpoints | -| Wait until conversation ends (user may forget) | Proactively close during conversation | -| Close without accumulating content | Let 5-10 exchanges happen first | -| Never close sessions | Establish a rhythm | - -## Memory Storage Strategy - -### What to Explicitly Store - -Use `cortex_add_memory` for: - -1. **Explicit User Preferences** - ``` - "User prefers dark theme in all editors" - "User wants commit messages in conventional format" - ``` - -2. **Important Decisions** - ``` - "Decided to use PostgreSQL instead of MySQL for this project" - "User chose React over Vue for the frontend" - ``` - -3. **Key Information That May Be Lost** - ``` - "User's timezone is UTC+8" - "Project deadline: March 30, 2026" - ``` - -### What to Let Accumulate - -Don't use `cortex_add_memory` for: - -- Regular conversation content (auto-stored in session) -- Contextual information (captured on close_session) -- Temporary preferences (not worth persisting) +// Step 3: Get L1 overview for top candidates +for (const uri of topUris) { + const overview = cortex_get_overview({ uri }); + // Process overview... +} -### Role Parameter Usage - -| Role | When to Use | -|------|-------------| -| `user` | User's statements, preferences, questions (default) | -| `assistant` | Your responses, explanations, code you wrote | -| `system` | Important context, rules, constraints | - -## Search Strategies - -### Query Formulation - -``` -┌────────────────────────────────────────────────────────────────┐ -│ Query Formulation Tips │ -└────────────────────────────────────────────────────────────────┘ - -BAD: "it" — Too vague -GOOD: "database choice" — Specific topic - -BAD: "the user said something" — Unfocused -GOOD: "user preference for testing" — Clear intent - -BAD: "code" — Too broad -GOOD: "authentication implementation" — Specific domain +// Step 4: If needed, get L2 for the most relevant +const fullContent = cortex_get_content({ uri: mostRelevantUri }); ``` -### Score Threshold Guidelines - -| Score | Use Case | -|-------|----------| -| 0.8+ | Need high-confidence matches only | -| 0.6 (default) | Balanced precision/recall | -| 0.4-0.5 | Exploratory search, finding related items | -| <0.4 | Usually too noisy, not recommended | +## Tool Selection Patterns -### Scope Parameter Usage +### Pattern 1: Discovery (Don't know where information is) ``` -# Search across all sessions (default) -{ "query": "database decisions" } - -# Search within specific session -{ "query": "preferences", "scope": "project-alpha" } +cortex_search(query="...", return_layers=["L0"]) + ↓ +Identify relevant URIs + ↓ +cortex_get_overview(uri="...") for more context + ↓ +cortex_get_content(uri="...") if needed ``` -Use `scope` when: -- You know the relevant session ID -- Working within a specific project context -- Want to limit noise from other sessions - -## Common Pitfalls - -### 1. Memory Not Found After Close - -**Symptom:** You closed a session but search returns nothing. - -**Cause:** Memory extraction is asynchronous and may take 30-60 seconds. +### Pattern 2: Browsing (Know the structure) -**Solution:** Wait briefly after close_session before searching, or: ``` -1. Close session -2. Continue with other work -3. Memory will be indexed automatically +cortex_ls(uri="cortex://session") + ↓ +cortex_ls(uri="cortex://session/{id}", include_abstracts=true) + ↓ +cortex_get_abstract(uri="...") for quick check + ↓ +cortex_get_content(uri="...") for details ``` -### 2. Duplicate Memories +### Pattern 3: Guided Exploration -**Symptom:** Same information appears multiple times. - -**Cause:** Both explicit `add_memory` and `close_session` extraction captured the same content. - -**Solution:** Use `add_memory` only for information that: -- Won't naturally be captured in conversation -- Needs explicit emphasis -- Is a correction or override of previous information - -### 3. Irrelevant Search Results - -**Symptom:** Search returns unrelated content. - -**Cause:** Query too vague or score threshold too low. - -**Solution:** -- Make queries more specific -- Increase `min_score` threshold -- Use `scope` to limit search range - -### 4. Lost Session Content - -**Symptom:** Important conversation not in memory. - -**Cause:** Session was never closed. - -**Solution:** Establish a habit of closing sessions at checkpoints. If you realize too late, the raw messages may still exist in the session - close it now. - -### 5. Configuration Issues - -**Symptom:** Tools return errors about service/API. - -**Cause:** LLM/Embedding credentials not configured. - -**Solution:** See SKILL.md → Troubleshooting section. - -## Workflow Examples - -### Example 1: New Project Discussion - -``` -1. User starts discussing a new project - → Just listen and respond naturally - -2. User makes architecture decisions - → Optionally: cortex_add_memory for explicit decisions - -3. Discussion shifts to another topic - → cortex_close_session (captures project discussion memories) - -4. Continue with new topic - → Fresh start, memories from step 3 are now searchable ``` - -### Example 2: Finding Previous Context - +cortex_explore(query="...", start_uri="...", return_layers=["L0"]) + ↓ +Review exploration_path for relevance scores + ↓ +Use matches with higher return_layers if needed ``` -1. User asks: "What did we decide about auth?" -2. cortex_search({ query: "authentication decision" }) +## Session Management Best Practices -3. If results show snippets but need details: - cortex_recall({ query: "authentication implementation details" }) +### When to Close Sessions -4. Summarize findings to user -``` +**DO close sessions:** +- ✅ After completing a significant task or topic +- ✅ After user shares important preferences/decisions +- ✅ When conversation topic shifts significantly +- ✅ Every 10-20 exchanges during long conversations -### Example 3: User States Preference +**DON'T close sessions:** +- ❌ After every message (too frequent) +- ❌ Only at the very end (user might forget) -``` -1. User: "I always want TypeScript strict mode" +### Memory Metadata -2. cortex_add_memory({ - content: "User requires TypeScript strict mode in all projects", - role: "user" - }) +Use metadata to enrich stored memories: -3. Acknowledge and remember for future +```typescript +cortex_add_memory({ + content: "User prefers functional programming style over OOP", + role: "assistant", + metadata: { + tags: ["preference", "programming-style"], + importance: "high", + category: "technical-preference" + } +}) ``` -## Memory Architecture Reference +**Recommended metadata fields:** +- `tags`: Array of searchable tags +- `importance`: "high", "medium", "low" +- `category`: Custom categorization +- `source`: Where the information came from -### L0/L1/L2 Tier System +## Common Workflows -| Tier | Content | Size | Purpose | Search Role | -|------|---------|------|---------|-------------| -| L0 | Abstract summary | ~100 tokens | Quick filtering | First pass | -| L1 | Key points + context | ~2000 tokens | Context refinement | Second pass | -| L2 | Full original content | Complete | Exact matching | Final retrieval | +### Finding User Preferences -### How Search Works Internally +```typescript +// 1. Search for preference-related content +const results = cortex_search({ + query: "user preferences settings configuration", + return_layers: ["L0"], + limit: 10 +}); +// 2. Get overviews for relevant results +for (const result of results.results.slice(0, 3)) { + if (result.snippet.includes("preference")) { + const overview = cortex_get_overview({ uri: result.uri }); + // Extract preferences from overview + } +} ``` -Query → L0 Filter → L1 Refine → L2 Retrieve → Ranked Results - │ │ │ - ▼ ▼ ▼ - Quick scan Contextual Full content - by summary refinement for precision -``` - -### Automatic Processes -| Process | Trigger | Duration | -|---------|---------|----------| -| Vector embedding | On `add_memory` | Seconds | -| L0/L1 generation | On `add_memory` (async) | Seconds | -| Full extraction | On `close_session` | 30-60s | -| Maintenance | Every 3 hours (auto) | Minutes | +### Error Context Retrieval -## Summary Checklist +```typescript +// Search for error-related content +const results = cortex_search({ + query: "TypeError: Cannot read property", + return_layers: ["L0"] +}); -Before ending a conversation or topic transition, ask yourself: +// If not found, try broader semantic search +if (results.results.length === 0) { + const broader = cortex_search({ + query: "property access error undefined object", + return_layers: ["L0", "L1"] + }); +} +``` -- [ ] Have we accumulated meaningful content? -- [ ] Did the user share important preferences or decisions? -- [ ] Is this a natural checkpoint? -- [ ] Should I close the session now? +### Timeline Reconstruction -If yes to any, call `cortex_close_session`. +```typescript +// 1. List timeline directory +const timeline = cortex_ls({ + uri: "cortex://session/{session_id}/timeline", + recursive: true, + include_abstracts: true +}); + +// 2. Sort by modified date (entries already sorted) +// 3. Get full content for key moments +for (const entry of timeline.entries) { + if (entry.abstract_text?.includes("important decision")) { + const content = cortex_get_content({ uri: entry.uri }); + // Process important moment + } +} +``` + +## Performance Tips + +### Minimize API Calls + +Instead of: +```typescript +// Bad: Multiple L2 calls +for (const uri of uris) { + cortex_get_content({ uri }); +} +``` + +Do: +```typescript +// Good: Batch with search +cortex_search({ + query: "specific topic", + scope: session_id, + return_layers: ["L0", "L1", "L2"] +}); +``` + +### Use Scope Effectively + +```typescript +// Faster: Search within known session +cortex_search({ + query: "authentication", + scope: "project-x-session", + return_layers: ["L0"] +}); + +// Slower: Search all sessions +cortex_search({ + query: "authentication", + return_layers: ["L0"] +}); +``` + +### Leverage Abstracts for Filtering + +```typescript +// Get abstracts while browsing +const entries = cortex_ls({ + uri: "cortex://session", + include_abstracts: true +}); + +// Filter based on abstracts without additional calls +const relevantEntries = entries.entries.filter(e => + e.abstract_text?.includes("relevant keyword") +); +``` \ No newline at end of file diff --git a/examples/@memclaw/plugin/skills/memclaw/references/memory-structure.md b/examples/@memclaw/plugin/skills/memclaw/references/memory-structure.md new file mode 100644 index 0000000..4541319 --- /dev/null +++ b/examples/@memclaw/plugin/skills/memclaw/references/memory-structure.md @@ -0,0 +1,160 @@ +# Memory Structure + +MemClaw organizes memory using a multi-dimensional structure with three-tier retrieval layers. + +## URI Structure + +All memory resources are addressed using the `cortex://` URI scheme: + +``` +cortex:// +├── resources/{resource_name}/ # General resources (facts, knowledge) +├── user/ +│ ├── preferences/{name}.md # User preferences +│ ├── entities/{name}.md # People, projects, concepts +│ ├── events/{name}.md # Decisions, milestones +│ └── profile/{name}.md # User profile info +├── agent/ +│ ├── cases/{name}.md # Problem-solution cases +│ ├── skills/{name}.md # Acquired skills +│ └── instructions/{name}.md # Instructions learned +└── session/{session_id}/ + ├── timeline/ + │ ├── {YYYY-MM}/ # Year-month directory + │ │ ├── {DD}/ # Day directory + │ │ │ ├── {HH_MM_SS}_{id}.md # L2: Original message + │ │ │ ├── .abstract.md # L0: ~100 token summary + │ │ │ └── .overview.md # L1: ~2000 token overview + │ │ └── .abstract.md # Day-level L0 summary + │ └── .abstract.md # Session-level L0 summary + │ └── .overview.md # Session-level L1 overview + └── .session.json # Session metadata +``` + +## Dimensions + +| Dimension | Purpose | Examples | +|-----------|---------|----------| +| `resources` | General knowledge, facts | Documentation, reference materials | +| `user` | User-specific memories | Preferences, entities, events, profile | +| `agent` | Agent-specific memories | Cases, skills, instructions | +| `session` | Conversation memories | Timeline messages, session context | + +## Three-Layer Architecture + +Each memory resource can have three representation layers: + +| Layer | Filename | Tokens | Purpose | +|-------|----------|--------|---------| +| **L0 (Abstract)** | `.abstract.md` | ~100 | Quick relevance check, filtering | +| **L1 (Overview)** | `.overview.md` | ~2000 | Understanding gist, moderate detail | +| **L2 (Detail)** | `{name}.md` | Full | Exact quotes, complete implementation | + +**Layer Resolution:** +- For files: `cortex://user/preferences/typescript.md` → layers are `.abstract.md` and `.overview.md` in same directory +- For directories: `cortex://session/default/timeline` → layers are `.abstract.md` and `.overview.md` in that directory + +**Access Pattern:** +``` +1. Start with L0 (quick relevance check) +2. Use L1 if L0 is relevant (more context) +3. Use L2 only when necessary (full detail) +``` + +## Session Memory + +### session_id Configuration + +`{session_id}` is a memory isolation identifier for separating different conversation contexts: + +| Configuration Location | Field Name | Default Value | +|-----------------------|------------|---------------| +| OpenClaw plugin config | `defaultSessionId` | `"default"` | + +**Configuration Example** (`openclaw.json`): +```json +{ + "plugins": { + "entries": { + "memclaw": { + "config": { + "defaultSessionId": "my-project" + } + } + } + } +} +``` + +**Usage Rules:** +- `session_id` parameter in tools is optional; defaults to configured value +- Different session_ids provide memory isolation for multi-project/multi-topic management +- Replace `{session_id}` in URIs with actual value, e.g., `cortex://session/default/timeline` + +### Timeline Organization + +Timeline messages are organized hierarchically by date: + +``` +session/{session_id}/timeline/ +├── 2024-03/ # Year-Month +│ ├── 15/ # Day +│ │ ├── 10_30_45_abc123.md # Message at 10:30:45 +│ │ ├── .abstract.md # Day-level L0 +│ │ └── 16/ +│ │ └── ... +│ └── .abstract.md # Month-level L0 +├── .abstract.md # Session-level L0 +└── .overview.md # Session-level L1 +``` + +**Message File Format:** `{HH_MM_SS}_{random_id}.md` + +## User Memory Categories + +| Category | Description | URI Pattern | +|----------|-------------|-------------| +| `preferences` | User preferences by topic | `cortex://user/preferences/{name}.md` | +| `entities` | People, projects, concepts | `cortex://user/entities/{name}.md` | +| `events` | Decisions, milestones | `cortex://user/events/{name}.md` | +| `profile` | User profile information | `cortex://user/profile/{name}.md` | + +## Agent Memory Categories + +| Category | Description | URI Pattern | +|----------|-------------|-------------| +| `cases` | Problem-solution pairs | `cortex://agent/cases/{name}.md` | +| `skills` | Acquired skills | `cortex://agent/skills/{name}.md` | +| `instructions` | Learned instructions | `cortex://agent/instructions/{name}.md` | + +## Session Metadata + +Each session has a `.session.json` file containing: + +```json +{ + "thread_id": "session_id", + "status": "active|closed|archived", + "created_at": "2024-03-15T10:30:00Z", + "updated_at": "2024-03-15T12:45:00Z", + "closed_at": null, + "message_count": 25, + "participants": ["user_001", "agent_001"], + "tags": ["typescript", "api-design"], + "title": "Optional session title", + "description": "Optional description" +} +``` + +## Layer Generation + +Layers are generated **asynchronously** to avoid blocking agent responses: + +1. **L2 (Detail)**: Created immediately when memory is added +2. **L0/L1**: Generated when `cortex_commit_session` is called or via background maintenance + +**When to call `cortex_commit_session`:** +- After completing a significant task +- After user shares important preferences +- When conversation topic shifts +- Every 10-20 exchanges diff --git a/examples/@memclaw/plugin/skills/memclaw/references/security.md b/examples/@memclaw/plugin/skills/memclaw/references/security.md new file mode 100644 index 0000000..62d3611 --- /dev/null +++ b/examples/@memclaw/plugin/skills/memclaw/references/security.md @@ -0,0 +1,31 @@ +# Security & Trust + +MemClaw is designed with user privacy and data security as top priorities. + +## What the Plugin Does + +- **Local Data Storage**: All memory data is stored in the local user data directory +- **Local Processing**: Based on advanced Cortex Memory technology, providing outstanding memory management capabilities with high performance and accuracy +- **Migration Safety**: Only reads existing OpenClaw memory files during migration + +## What the Plugin Does NOT Do + +- **No External Data Transmission**: Does NOT send data to external servers (all processing is local) +- **No API Key Leakage**: Does NOT transmit API keys to anywhere other than your configured LLM/embedding provider + +## Data Storage Location + +| Platform | Path | +|----------|------| +| macOS | `~/Library/Application Support/memclaw` | +| Windows | `%LOCALAPPDATA%\memclaw` | +| Linux | `~/.local/share/memclaw` | + +## API Key Security + +API keys are configured through OpenClaw plugin settings and are marked as sensitive fields. OpenClaw handles secure storage of these credentials. + +**Best Practices:** +- Never share your `openclaw.json` configuration file publicly +- Use environment-specific API keys when possible +- Rotate API keys periodically according to your provider's recommendations diff --git a/examples/@memclaw/plugin/skills/memclaw/references/tools.md b/examples/@memclaw/plugin/skills/memclaw/references/tools.md index a75371e..67e3504 100644 --- a/examples/@memclaw/plugin/skills/memclaw/references/tools.md +++ b/examples/@memclaw/plugin/skills/memclaw/references/tools.md @@ -1,205 +1,326 @@ -# Tools Reference +# MemClaw Tools Reference -Detailed documentation for MemClaw tools. +Complete reference for all MemClaw tools. -## cortex_search +## Search Tools -Semantic search using L0/L1/L2 hierarchical retrieval. +### cortex_search -**Parameters:** +Layered semantic search with L0/L1/L2 tiered retrieval. -| Parameter | Type | Required | Default | Description | -|-----------|------|----------|---------|-------------| -| `query` | string | Yes | - | Search query — natural language or keywords | -| `scope` | string | No | - | Session/thread ID to limit search scope | -| `limit` | integer | No | 10 | Maximum number of results | -| `min_score` | number | No | 0.6 | Minimum relevance score (0-1) | +**Parameters:** -**Use Cases:** -- Find past conversations or decisions -- Search for specific information across all sessions -- Discover related memories through semantic similarity +| Name | Type | Required | Default | Description | +|------|------|----------|---------|-------------| +| query | string | Yes | - | Search query (natural language or keywords) | +| scope | string | No | - | Session/thread ID to limit search scope | +| limit | integer | No | 10 | Maximum number of results | +| min_score | number | No | 0.6 | Minimum relevance score (0-1) | +| return_layers | ("L0" \| "L1" \| "L2")[] | No | ["L0"] | Which layers to return | -**Example:** +**Response:** ```json { - "query": "database architecture decisions", - "limit": 5, - "min_score": 0.6 + "results": [ + { + "uri": "cortex://session/abc123/timeline/...", + "score": 0.85, + "snippet": "L0 abstract text...", + "overview": "L1 overview text (if requested)...", + "content": "L2 full content (if requested)...", + "layers": ["L0", "L1"], + "source": "layered_vector" + } + ], + "total": 5 } ``` -**Response Format:** -- Returns results sorted by relevance -- Each result contains `uri`, `score`, and `snippet` +**Example:** +```typescript +// Minimal tokens - just abstracts +cortex_search({ query: "API design", return_layers: ["L0"] }) + +// More context needed +cortex_search({ query: "authentication flow", return_layers: ["L0", "L1"] }) + +// Full content retrieval +cortex_search({ query: "exact error message", return_layers: ["L0", "L1", "L2"] }) +``` --- -## cortex_recall +### cortex_recall -Retrieve memories with more context (summary + full content). +Convenience wrapper returning L0 + L2 content. **Parameters:** -| Parameter | Type | Required | Default | Description | -|-----------|------|----------|---------|-------------| -| `query` | string | Yes | - | Search query | -| `scope` | string | No | - | Session/thread ID to limit search scope | -| `limit` | integer | No | 10 | Maximum number of results | +| Name | Type | Required | Default | Description | +|------|------|----------|---------|-------------| +| query | string | Yes | - | Search query | +| scope | string | No | - | Session/thread ID to limit scope | +| limit | integer | No | 10 | Maximum number of results | -**Use Cases:** -- Need memories with full context, not just summaries -- Want to see original content -- Performing detailed memory analysis +**Response:** Same as `cortex_search` with `return_layers: ["L0", "L2"]` -**Example:** +--- + +## Filesystem Tools + +### cortex_ls + +List directory contents to browse memory structure. + +**Parameters:** + +| Name | Type | Required | Default | Description | +|------|------|----------|---------|-------------| +| uri | string | No | "cortex://session" | Directory URI to list | +| recursive | boolean | No | false | Recursively list subdirectories | +| include_abstracts | boolean | No | false | Include L0 abstracts for files | + +**Response:** ```json { - "query": "user code style preferences", - "limit": 10 + "uri": "cortex://session", + "total": 3, + "entries": [ + { + "uri": "cortex://session/abc123", + "name": "abc123", + "is_directory": true, + "size": 0, + "modified": "2024-01-15T10:30:00Z" + }, + { + "uri": "cortex://session/xyz789", + "name": "xyz789", + "is_directory": true, + "size": 0, + "modified": "2024-01-14T15:00:00Z", + "abstract_text": "Discussion about API design..." + } + ] } ``` -**Response Format:** -- Returns results with `snippet` (summary) and `content` (full text) -- Content is truncated when too long (preview >300 characters) +**Example:** +```typescript +// List all sessions +cortex_ls({ uri: "cortex://session" }) + +// Browse with abstracts +cortex_ls({ + uri: "cortex://session/abc123/timeline", + include_abstracts: true +}) + +// Recursive listing +cortex_ls({ + uri: "cortex://session/abc123", + recursive: true +}) +``` --- -## cortex_add_memory +### cortex_explore -Store messages for later retrieval. +Smart exploration combining search and browsing. **Parameters:** -| Parameter | Type | Required | Default | Description | -|-----------|------|----------|---------|-------------| -| `content` | string | Yes | - | Memory content to store | -| `role` | string | No | `user` | Message sender role: `user`, `assistant`, or `system` | -| `session_id` | string | No | `default` | Session/thread ID the memory belongs to | - -**Use Cases:** -- Persist important information for later retrieval -- Store user preferences or decisions -- Save context that should be searchable +| Name | Type | Required | Default | Description | +|------|------|----------|---------|-------------| +| query | string | Yes | - | Exploration query | +| start_uri | string | No | "cortex://session" | Starting URI | +| return_layers | ("L0" \| "L1" \| "L2")[] | No | ["L0"] | Layers to return in matches | -**Example:** +**Response:** ```json { - "content": "User prefers TypeScript with strict mode enabled", - "role": "assistant", - "session_id": "default" + "query": "authentication", + "exploration_path": [ + { + "uri": "cortex://session/abc123/timeline", + "relevance_score": 0.92, + "abstract_text": "Discussion about OAuth..." + } + ], + "matches": [ + { + "uri": "cortex://session/abc123/timeline/...", + "score": 0.88, + "snippet": "OAuth implementation...", + "layers": ["L0"] + } + ], + "total_explored": 5, + "total_matches": 2 } ``` -**Execution Effects:** -- Message is stored with timestamp -- Vector embedding is automatically generated -- L0/L1 layers are generated asynchronously +--- + +## Tiered Access Tools + +### cortex_get_abstract (L0) + +Get ~100 token summary for quick relevance check. + +**Parameters:** + +| Name | Type | Required | Description | +|------|------|----------|-------------| +| uri | string | Yes | Content URI | + +**Response:** +```json +{ + "uri": "cortex://session/abc123/timeline/...", + "content": "Short abstract...", + "layer": "L0", + "token_count": 95 +} +``` --- -## cortex_list_sessions +### cortex_get_overview (L1) -List all memory sessions and their status. +Get ~2000 token overview with key information. -**Parameters:** None +**Parameters:** -**Use Cases:** -- Verify sessions exist before searching -- Check which sessions are active or closed -- Audit memory usage +| Name | Type | Required | Description | +|------|------|----------|-------------| +| uri | string | Yes | Content URI | -**Response Format:** -- Session ID, status, message count -- Creation and update timestamps +**Response:** +```json +{ + "uri": "cortex://session/abc123/timeline/...", + "content": "Detailed overview...", + "layer": "L1", + "token_count": 1850 +} +``` --- -## cortex_close_session +### cortex_get_content (L2) -Close a session and trigger the memory extraction process. +Get full original content. **Parameters:** -| Parameter | Type | Required | Default | Description | -|-----------|------|----------|---------|-------------| -| `session_id` | string | No | `default` | Session/thread ID to close | +| Name | Type | Required | Description | +|------|------|----------|-------------| +| uri | string | Yes | Content URI (file only) | -**Use Cases:** -- When a conversation is complete -- Preparing to extract structured memories -- Wanting to finalize a session's memory content +**Response:** +```json +{ + "uri": "cortex://session/abc123/timeline/...", + "content": "Full original content...", + "layer": "L2", + "token_count": 5420 +} +``` -**Execution Effects:** -1. Extracts structured memories (user preferences, entities, decisions) -2. Generates complete L0/L1 layer summaries -3. Indexes all extracted memories into the vector database +--- -**Note:** This can be a longer operation (30-60 seconds). +## Storage Tools -**Example:** +### cortex_add_memory + +Store a message in memory. + +**Parameters:** + +| Name | Type | Required | Default | Description | +|------|------|----------|---------|-------------| +| content | string | Yes | - | Message content | +| role | string | No | "user" | Message role: "user", "assistant", "system" | +| session_id | string | No | default | Session/thread ID | +| metadata | object | No | - | Optional metadata (tags, importance, etc.) | + +**Response:** ```json { - "session_id": "default" + "success": true, + "message_uri": "cortex://session/default/timeline/2024-01/15/10_30_00_abc123.md" } ``` -> **Important**: This tool should be called proactively at natural checkpoints, not just when the conversation ends. Ideal timing: after completing important tasks, topic transitions, or accumulating enough conversation content. +**Example:** +```typescript +cortex_add_memory({ + content: "User prefers dark mode in all applications", + role: "assistant", + metadata: { + tags: ["preference", "ui"], + importance: "medium" + } +}) +``` --- -## cortex_migrate - -Migrate from OpenClaw's native memory system to MemClaw. +### cortex_commit_session -**Parameters:** None +Commit session and trigger memory extraction pipeline. -**Use Cases:** -- First-time use with existing OpenClaw memories -- Want to preserve previous conversation history -- Switching from built-in memory to MemClaw +**Parameters:** -**Execution Effects:** -1. Finds OpenClaw memory files (`memory/*.md` and `MEMORY.md`) -2. Converts to MemClaw's L2 format -3. Generates L0/L1 layers and vector indices +| Name | Type | Required | Description | +|------|------|----------|-------------| +| session_id | string | No | Session/thread ID (uses default if not specified) | -**Prerequisites:** -- OpenClaw workspace exists at `~/.openclaw/workspace` -- Memory files exist at `~/.openclaw/workspace/memory/` +**Response:** +```json +{ + "success": true, + "session": { + "thread_id": "abc123", + "status": "closed", + "message_count": 42 + } +} +``` -**Run only once during initial setup.** +**Important:** Call this periodically, not just at conversation end. --- -## cortex_maintenance +## Maintenance Tools -Perform periodic maintenance on MemClaw data. +### cortex_maintenance + +Perform periodic maintenance. **Parameters:** -| Parameter | Type | Required | Default | Description | -|-----------|------|----------|---------|-------------| -| `dryRun` | boolean | No | false | Preview changes without executing | -| `commands` | array | No | `["prune", "reindex", "ensure-all"]` | Maintenance commands to execute | +| Name | Type | Required | Default | Description | +|------|------|----------|---------|-------------| +| dryRun | boolean | No | false | Preview changes without executing | +| commands | string[] | No | ["prune", "reindex", "ensure-all"] | Commands to run | + +--- -**Use Cases:** -- Search results are incomplete or outdated -- Recovering from crash or data corruption -- Need to clean up disk space +### cortex_migrate -**Available Commands:** -- `prune` — Remove vectors whose source files no longer exist -- `reindex` — Rebuild vector indices and remove stale entries -- `ensure-all` — Generate missing L0/L1 layer files +Migrate from OpenClaw native memory. -**Example:** +**Parameters:** None + +**Response:** ```json { - "dryRun": false, - "commands": ["prune", "reindex", "ensure-all"] + "dailyLogsMigrated": 15, + "memoryMdMigrated": true, + "sessionsCreated": ["migrated_2024-01-15"], + "errors": [] } -``` - -> **Note**: This tool is typically called automatically by a scheduled Cron task. Manual invocation is for troubleshooting or on-demand maintenance. \ No newline at end of file +``` \ No newline at end of file diff --git a/examples/@memclaw/plugin/src/binaries.ts b/examples/@memclaw/plugin/src/binaries.ts index 8568580..9da57af 100644 --- a/examples/@memclaw/plugin/src/binaries.ts +++ b/examples/@memclaw/plugin/src/binaries.ts @@ -4,6 +4,7 @@ * Binaries are bundled in platform-specific npm packages: * - @memclaw/bin-darwin-arm64 (macOS Apple Silicon) * - @memclaw/bin-win-x64 (Windows x64) + * - @memclaw/bin-linux-x64 (Linux x64) * * The correct package is installed automatically via optionalDependencies. */ @@ -17,7 +18,7 @@ import { getDataDir } from './config.js'; type BinaryName = 'qdrant' | 'cortex-mem-service' | 'cortex-mem-cli'; // Supported platforms -type SupportedPlatform = 'darwin-arm64' | 'win-x64'; +type SupportedPlatform = 'darwin-arm64' | 'win-x64' | 'linux-x64'; // Platform detection export function getPlatform(): SupportedPlatform | null { @@ -28,6 +29,8 @@ export function getPlatform(): SupportedPlatform | null { return 'darwin-arm64'; } else if (platform === 'win32' && arch === 'x64') { return 'win-x64'; + } else if (platform === 'linux' && arch === 'x64') { + return 'linux-x64'; } return null; @@ -47,6 +50,7 @@ export function getUnsupportedPlatformMessage(): string { MemClaw is only supported on: - macOS Apple Silicon (darwin-arm64) - Windows x64 (win-x64) + - Linux x64 (linux-x64) Current platform: ${platform}-${arch} is not supported. `; @@ -288,12 +292,18 @@ export async function startCortexMemService(log?: (msg: string) => void): Promis const dataDir = getDataDir(); + // Prepare log file path + const logsDir = path.join(dataDir, 'logs'); + fs.mkdirSync(logsDir, { recursive: true }); + const logFilePath = path.join(logsDir, 'memclaw-cortex-mem-service.log'); + log?.(`Starting cortex-mem-service with data-dir ${dataDir}...`); log?.(`Binary path: ${binaryPath}`); + log?.(`Log file: ${logFilePath}`); // cortex-mem-service reads config.toml from current working directory // Set cwd to dataDir so it can find the config file - const proc = spawn(binaryPath, ['--data-dir', dataDir], { + const proc = spawn(binaryPath, ['--data-dir', dataDir, '--log-file', logFilePath], { stdio: ['ignore', 'pipe', 'pipe'], detached: true, cwd: dataDir // Set working directory so config.toml can be found diff --git a/examples/@memclaw/plugin/src/client.ts b/examples/@memclaw/plugin/src/client.ts index 7af2f76..c461b86 100644 --- a/examples/@memclaw/plugin/src/client.ts +++ b/examples/@memclaw/plugin/src/client.ts @@ -1,207 +1,365 @@ /** - * Cortex Memory API Client + * Cortex Mem Client * - * HTTP client for cortex-mem-service REST API + * HTTP client for cortex-mem-service REST API. */ -// Response types -interface ApiResponse { - success: boolean; - data?: T; - error?: string; - timestamp: string; -} +/** Layer types */ +export type Layer = 'L0' | 'L1' | 'L2'; -// Search types -export interface SearchRequest { - query: string; - thread?: string; - limit?: number; - min_score?: number; +export interface SearchOptions { + query: string; + thread?: string; + limit?: number; + min_score?: number; + /** Which layers to return: ["L0"], ["L0","L1"], ["L0","L1","L2"] */ + return_layers?: Layer[]; } export interface SearchResult { - uri: string; - score: number; - snippet: string; - content?: string; - source: string; + uri: string; + score: number; + snippet: string; + overview?: string; + content?: string; + source: string; + layers: Layer[]; } -// Session types -export interface SessionResponse { - thread_id: string; - status: string; - message_count: number; - created_at: string; - updated_at: string; +export interface LsOptions { + uri?: string; + recursive?: boolean; + include_abstracts?: boolean; } -export interface CreateSessionRequest { - thread_id?: string; - title?: string; - user_id?: string; - agent_id?: string; +export interface LsEntry { + uri: string; + name: string; + is_directory: boolean; + size: number; + modified: string; + abstract_text?: string; } -export interface AddMessageRequest { - role: "user" | "assistant" | "system"; - content: string; +export interface LsResponse { + uri: string; + total: number; + entries: LsEntry[]; +} + +export interface ExploreOptions { + query: string; + start_uri?: string; + return_layers?: Layer[]; +} + +export interface ExploreResponse { + query: string; + exploration_path: ExplorationPathItem[]; + matches: SearchResult[]; + total_explored: number; + total_matches: number; +} + +export interface ExplorationPathItem { + uri: string; + relevance_score: number; + abstract_text?: string; +} + +export interface LayerResponse { + uri: string; + content: string; + layer: Layer; + token_count: number; +} + +export interface SessionInfo { + thread_id: string; + status: string; + message_count: number; + created_at: string; + updated_at: string; +} + +export interface AddMessageOptions { + content: string; + role?: 'user' | 'assistant' | 'system'; + metadata?: Record; } -/** - * Cortex Memory API Client - */ export class CortexMemClient { - private baseUrl: string; - - constructor(baseUrl: string = "http://localhost:8085") { - this.baseUrl = baseUrl.replace(/\/$/, ""); - } - - /** - * Layered semantic search (L0 -> L1 -> L2 tiered retrieval) - */ - async search(request: SearchRequest): Promise { - const response = await this.post("/api/v2/search", request); - return response; - } - - /** - * Quick search returning only L0 abstracts - */ - async find( - query: string, - scope?: string, - limit: number = 5, - ): Promise { - return this.search({ - query, - thread: scope, - limit, - min_score: 0.5, - }); - } - - /** - * Layered recall - uses L0/L1/L2 tiered search internally - * - * The search engine performs tiered retrieval (L0→L1→L2) internally, - * but returns unified results with snippet and content. - * - * @param query - Search query - * @param scope - Optional session/thread scope - * @param limit - Maximum results - */ - async recall( - query: string, - scope?: string, - limit: number = 10, - ): Promise { - return this.search({ - query, - thread: scope, - limit, - min_score: 0.5, - }); - } - - /** - * List all sessions - */ - async listSessions(): Promise { - const response = await this.get("/api/v2/sessions"); - return response; - } - - /** - * Create a new session - */ - async createSession( - request: CreateSessionRequest = {}, - ): Promise { - const response = await this.post( - "/api/v2/sessions", - request, - ); - return response; - } - - /** - * Add a message to a session - */ - async addMessage( - threadId: string, - message: AddMessageRequest, - ): Promise { - const response = await this.post( - `/api/v2/sessions/${threadId}/messages`, - message, - ); - return response; - } - - /** - * Close a session - */ - async closeSession(threadId: string): Promise { - const response = await this.post( - `/api/v2/sessions/${threadId}/close`, - {}, - ); - return response; - } - - /** - * Switch tenant - */ - async switchTenant(tenantId: string): Promise { - await this.post("/api/v2/tenants/switch", { tenant_id: tenantId }); - } - - /** - * Health check - */ - async healthCheck(): Promise { - try { - const response = await fetch(`${this.baseUrl}/health`); - return response.ok; - } catch { - return false; - } - } - - // Private helpers - private async get(path: string): Promise { - const response = await fetch(`${this.baseUrl}${path}`); - if (!response.ok) { - throw new Error(`API error: ${response.status} ${response.statusText}`); - } - const data = (await response.json()) as ApiResponse; - if (!data.success) { - throw new Error(data.error || "API request failed"); - } - return data.data!; - } - - private async post(path: string, body: object): Promise { - const response = await fetch(`${this.baseUrl}${path}`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(body), - }); - if (!response.ok) { - const errorText = await response.text(); - throw new Error( - `API error: ${response.status} ${response.statusText} - ${errorText}`, - ); - } - const data = (await response.json()) as ApiResponse; - if (!data.success) { - throw new Error(data.error || "API request failed"); - } - return data.data!; - } + private baseUrl: string; + + constructor(baseUrl: string = 'http://localhost:8085') { + this.baseUrl = baseUrl; + } + + // ==================== Search ==================== + + /** + * Layered semantic search with L0/L1/L2 tiered retrieval + */ + async search(options: SearchOptions): Promise { + const response = await this.fetchJson<{ + success: boolean; + data?: SearchResult[]; + error?: string; + }>('/api/v2/search', { + method: 'POST', + body: JSON.stringify({ + query: options.query, + thread: options.thread, + limit: options.limit ?? 10, + min_score: options.min_score ?? 0.6, + return_layers: options.return_layers ?? ['L0'] + }) + }); + + if (!response.success || !response.data) { + throw new Error(response.error ?? 'Search failed'); + } + + return response.data; + } + + /** + * Recall memories with more context (L0 + L2) + */ + async recall( + query: string, + thread?: string, + limit: number = 10 + ): Promise { + return this.search({ + query, + thread, + limit, + return_layers: ['L0', 'L2'] + }); + } + + // ==================== Filesystem ==================== + + /** + * List directory contents + */ + async ls(options: LsOptions = {}): Promise { + const params = new URLSearchParams(); + params.set('uri', options.uri ?? 'cortex://session'); + if (options.recursive) params.set('recursive', 'true'); + if (options.include_abstracts) params.set('include_abstracts', 'true'); + + const response = await this.fetchJson<{ + success: boolean; + data?: LsResponse; + error?: string; + }>(`/api/v2/filesystem/list?${params.toString()}`); + + if (!response.success || !response.data) { + throw new Error(response.error ?? 'List directory failed'); + } + + return response.data; + } + + /** + * Smart exploration combining search and browsing + */ + async explore(options: ExploreOptions): Promise { + const response = await this.fetchJson<{ + success: boolean; + data?: ExploreResponse; + error?: string; + }>('/api/v2/filesystem/explore', { + method: 'POST', + body: JSON.stringify({ + query: options.query, + start_uri: options.start_uri ?? 'cortex://session', + return_layers: options.return_layers ?? ['L0'] + }) + }); + + if (!response.success || !response.data) { + throw new Error(response.error ?? 'Explore failed'); + } + + return response.data; + } + + // ==================== Tiered Access ==================== + + /** + * Get L0 abstract (~100 tokens) for quick relevance check + */ + async getAbstract(uri: string): Promise { + const params = new URLSearchParams(); + params.set('uri', uri); + + const response = await this.fetchJson<{ + success: boolean; + data?: LayerResponse; + error?: string; + }>(`/api/v2/filesystem/abstract?${params.toString()}`); + + if (!response.success || !response.data) { + throw new Error(response.error ?? 'Get abstract failed'); + } + + return response.data; + } + + /** + * Get L1 overview (~2000 tokens) for core information + */ + async getOverview(uri: string): Promise { + const params = new URLSearchParams(); + params.set('uri', uri); + + const response = await this.fetchJson<{ + success: boolean; + data?: LayerResponse; + error?: string; + }>(`/api/v2/filesystem/overview?${params.toString()}`); + + if (!response.success || !response.data) { + throw new Error(response.error ?? 'Get overview failed'); + } + + return response.data; + } + + /** + * Get L2 full content + */ + async getContent(uri: string): Promise { + const params = new URLSearchParams(); + params.set('uri', uri); + + const response = await this.fetchJson<{ + success: boolean; + data?: LayerResponse; + error?: string; + }>(`/api/v2/filesystem/content?${params.toString()}`); + + if (!response.success || !response.data) { + throw new Error(response.error ?? 'Get content failed'); + } + + return response.data; + } + + // ==================== Session Management ==================== + + /** + * List all sessions + */ + async listSessions(): Promise { + const response = await this.fetchJson<{ + success: boolean; + data?: SessionInfo[]; + error?: string; + }>('/api/v2/sessions'); + + if (!response.success || !response.data) { + throw new Error(response.error ?? 'List sessions failed'); + } + + return response.data; + } + + /** + * Add a message to a session + */ + async addMessage(threadId: string, message: AddMessageOptions): Promise { + const response = await this.fetchJson<{ + success: boolean; + data?: string; + error?: string; + }>(`/api/v2/sessions/${threadId}/messages`, { + method: 'POST', + body: JSON.stringify({ + role: message.role ?? 'user', + content: message.content, + metadata: message.metadata + }) + }); + + if (!response.success || !response.data) { + throw new Error(response.error ?? 'Add message failed'); + } + + return response.data; + } + + /** + * Commit a session and trigger memory extraction + */ + async commitSession(threadId: string): Promise<{ + thread_id: string; + status: string; + message_count: number; + }> { + const response = await this.fetchJson<{ + success: boolean; + data?: { + thread_id: string; + status: string; + message_count: number; + }; + error?: string; + }>(`/api/v2/sessions/${threadId}/close`, { + method: 'POST', + body: JSON.stringify({}) + }); + + if (!response.success || !response.data) { + throw new Error(response.error ?? 'Commit session failed'); + } + + return response.data; + } + + // ==================== Tenant ==================== + + /** + * Switch tenant context + */ + async switchTenant(tenantId: string): Promise { + const response = await this.fetchJson<{ + success: boolean; + error?: string; + }>('/api/v2/tenants/switch', { + method: 'POST', + body: JSON.stringify({ tenant_id: tenantId }) + }); + + if (!response.success) { + throw new Error(response.error ?? 'Switch tenant failed'); + } + } + + // ==================== Internal ==================== + + private async fetchJson( + path: string, + options: RequestInit = {} + ): Promise { + const url = `${this.baseUrl}${path}`; + const headers = { + 'Content-Type': 'application/json', + ...(options.headers || {}) + }; + + const response = await fetch(url, { + ...options, + headers + }); + + if (!response.ok) { + throw new Error(`HTTP ${response.status}: ${response.statusText}`); + } + + return response.json() as Promise; + } } diff --git a/examples/cortex-mem-tars/src/config.rs b/examples/cortex-mem-tars/src/config.rs index db4da29..8db494a 100644 --- a/examples/cortex-mem-tars/src/config.rs +++ b/examples/cortex-mem-tars/src/config.rs @@ -58,13 +58,29 @@ impl ConfigManager { log::info!("机器人配置文件: {:?}", bots_file); log::info!("Cortex 配置文件: {:?}", cortex_config_file); + // TARS 数据目录:直接使用应用数据目录(与框架底层保持统一) + // 框架会自动在此目录下创建 tenants/{tenant_id}/ 结构 + let tars_data_dir_str = config_dir.to_string_lossy().to_string(); + // 加载或创建 cortex-mem 配置 let cortex_config = if cortex_config_file.exists() { - let config = + let mut config = CortexConfig::load(&cortex_config_file).context("无法加载 cortex-mem 配置")?; + + // 如果 data_dir 未设置(配置文件中缺少此项),强制使用应用数据目录 + // 这是 TARS 演示程序的规则:记忆文件必须存储在系统应用数据目录 + let needs_save = config.cortex.data_dir.is_none(); + if needs_save { + config.cortex.data_dir = Some(tars_data_dir_str.clone()); + let content = toml::to_string_pretty(&config).context("无法序列化配置")?; + fs::write(&cortex_config_file, content).context("无法更新配置文件")?; + log::info!("已补充 data_dir 配置: {:?}", tars_data_dir_str); + } + log::info!( - "已加载配置: embedding_dim={:?}", - config.qdrant.embedding_dim + "已加载配置: embedding_dim={:?}, data_dir={:?}", + config.qdrant.embedding_dim, + config.cortex.data_dir ); config } else { @@ -91,7 +107,10 @@ impl ConfigManager { cors_origins: vec!["*".to_string()], }, logging: cortex_mem_config::LoggingConfig::default(), - cortex: cortex_mem_config::CortexConfig::default(), + cortex: cortex_mem_config::CortexConfig { + data_dir: Some(tars_data_dir_str.clone()), + enable_intent_analysis: true, + }, }; let content = toml::to_string_pretty(&default_config).context("无法序列化默认配置")?; fs::write(&cortex_config_file, content).context("无法写入默认配置文件")?;