Skip to content
Merged

Dev #53

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions cortex-mem-core/src/memory_cleanup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,26 @@ pub struct CleanupStats {
/// 记忆清理服务
///
/// 使用方式:
/// ```rust,no_run
/// // 在 Agent 启动时创建,定期手动调用 run_cleanup,或用 tokio::spawn + interval 运行
/// let svc = MemoryCleanupService::new(index_manager, config, Some(vector_sync));
/// let stats = svc.run_cleanup(&MemoryScope::User, "alice").await?;
/// println!("Archived: {}, Deleted: {}", stats.archived, stats.deleted);
/// ```rust,ignore
/// use cortex_mem_core::{MemoryCleanupService, MemoryCleanupConfig, MemoryScope, MemoryIndexManager};
/// use std::sync::Arc;
///
/// #[tokio::main]
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// // 创建索引管理器和配置
/// let index_manager = Arc::new(MemoryIndexManager::new("./cortex-data"));
/// let config = MemoryCleanupConfig::default();
/// let vector_sync = None; // 可选的向量同步管理器
///
/// // 创建清理服务
/// let svc = MemoryCleanupService::new(index_manager, config, vector_sync);
///
/// // 执行清理
/// let stats = svc.run_cleanup(&MemoryScope::User, "alice").await?;
/// println!("Archived: {}, Deleted: {}", stats.archived, stats.deleted);
///
/// Ok(())
/// }
/// ```
pub struct MemoryCleanupService {
index_manager: Arc<MemoryIndexManager>,
Expand Down
16 changes: 14 additions & 2 deletions cortex-mem-service/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,20 @@ impl AppState {
}
}

let tenant_root =
tenant_root.ok_or_else(|| anyhow::anyhow!("Tenant {} not found", 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
}
};

// Update current tenant root
let mut current = self.current_tenant_root.write().await;
Expand Down
1 change: 1 addition & 0 deletions examples/cortex-mem-openclaw/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/
2,157 changes: 2,157 additions & 0 deletions examples/cortex-mem-openclaw/bun.lock

Large diffs are not rendered by default.

90 changes: 90 additions & 0 deletions examples/cortex-mem-openclaw/dist/client.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/**
* Cortex Memory API Client
*
* HTTP client for cortex-mem-service REST API
*/
export interface SearchRequest {
query: string;
thread?: string;
limit?: number;
min_score?: number;
}
export interface SearchResult {
uri: string;
score: number;
snippet: string;
content?: string;
source: string;
}
export interface SessionResponse {
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';
content: string;
}
export type ContextLayer = 'L0' | 'L1' | 'L2';
export interface LayeredRecallResult {
uri: string;
score: number;
abstract?: string;
overview?: string;
content?: string;
}
/**
* Cortex Memory API Client
*/
export declare class CortexMemClient {
private baseUrl;
constructor(baseUrl?: string);
/**
* Layered semantic search (L0 -> L1 -> L2 tiered retrieval)
*/
search(request: SearchRequest): Promise<SearchResult[]>;
/**
* Quick search returning only L0 abstracts
*/
find(query: string, scope?: string, limit?: number): Promise<SearchResult[]>;
/**
* Layered recall with specified detail level
*
* @param query - Search query
* @param layers - Which layers to return (L0, L1, L2)
* @param scope - Optional session/thread scope
* @param limit - Maximum results
*/
recall(query: string, layers?: ContextLayer[], scope?: string, limit?: number): Promise<LayeredRecallResult[]>;
/**
* List all sessions
*/
listSessions(): Promise<SessionResponse[]>;
/**
* Create a new session
*/
createSession(request?: CreateSessionRequest): Promise<SessionResponse>;
/**
* Add a message to a session
*/
addMessage(threadId: string, message: AddMessageRequest): Promise<string>;
/**
* Close a session
*/
closeSession(threadId: string): Promise<SessionResponse>;
/**
* Health check
*/
healthCheck(): Promise<boolean>;
private get;
private post;
}
//# sourceMappingURL=client.d.ts.map
1 change: 1 addition & 0 deletions examples/cortex-mem-openclaw/dist/client.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

132 changes: 132 additions & 0 deletions examples/cortex-mem-openclaw/dist/client.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions examples/cortex-mem-openclaw/dist/client.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

102 changes: 102 additions & 0 deletions examples/cortex-mem-openclaw/dist/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/**
* Cortex Memory Plugin for OpenClaw
*
* Provides layered semantic memory with L0/L1/L2 tiered retrieval.
*
* Installation:
* openclaw plugins install @cortex-mem/openclaw-plugin
*
* Configuration (in openclaw.json):
* {
* "plugins": {
* "entries": {
* "cortex-mem": {
* "enabled": true,
* "config": {
* "serviceUrl": "http://127.0.0.1:8085",
* "tenantId": "tenant_claw",
* "defaultSessionId": "default",
* "searchLimit": 10,
* "minScore": 0.6
* }
* }
* }
* }
* }
*/
interface PluginLogger {
debug?: (msg: string, ...args: unknown[]) => void;
info: (msg: string, ...args: unknown[]) => void;
warn: (msg: string, ...args: unknown[]) => void;
error: (msg: string, ...args: unknown[]) => void;
}
interface ToolDefinition {
name: string;
description: string;
/**
* JSON Schema for tool inputs.
* OpenClaw uses 'parameters', NOT 'inputSchema'.
*/
parameters: object;
/**
* Tool execution function.
* OpenClaw uses 'execute(_id, params)', NOT 'handler(args)'.
*/
execute: (_id: string, params: Record<string, unknown>) => Promise<unknown>;
/** Optional: mark tool as opt-in (not auto-enabled) */
optional?: boolean;
}
interface PluginAPI {
/**
* Plugin-specific configuration from openclaw.json
* Access via api.pluginConfig, NOT api.getConfig()
*/
pluginConfig?: Record<string, unknown>;
registerTool(tool: ToolDefinition, opts?: {
optional?: boolean;
}): void;
logger: PluginLogger;
}
export default function cortexMemPlugin(api: PluginAPI): {
id: string;
name: string;
version: string;
};
export declare const plugin: {
id: string;
name: string;
version: string;
configSchema: {
type: string;
properties: {
serviceUrl: {
type: string;
default: string;
};
defaultSessionId: {
type: string;
default: string;
};
searchLimit: {
type: string;
default: number;
};
minScore: {
type: string;
default: number;
};
tenantId: {
type: string;
default: string;
};
};
required: string[];
};
register(api: PluginAPI): {
id: string;
name: string;
version: string;
};
};
export {};
//# sourceMappingURL=index.d.ts.map
1 change: 1 addition & 0 deletions examples/cortex-mem-openclaw/dist/index.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading