Implement Layer 2: AI Memory with interpretation and priority scoring
Add AI interpretation and priority scoring capabilities to the memory system.
Simple, efficient implementation following the principle: "AI judges, tool records."
## Core Changes
### Memory struct (src/core/memory.rs)
- Added `ai_interpretation: Option<String>` - AI's creative interpretation
- Added `priority_score: Option<f32>` - Priority from 0.0 to 1.0
- New constructor: `Memory::new_ai()` for Layer 2
- Helper methods: `set_ai_interpretation()`, `set_priority_score()`
- Comprehensive tests for all new functionality
### SQLite storage (src/core/store.rs)
- Extended schema with `ai_interpretation` and `priority_score` columns
- Automatic migration for existing databases
- Added index on `priority_score` for future sorting
- Updated all queries to include new fields
- Search now includes `ai_interpretation` in results
### MCP Server (src/mcp/base.rs)
- New tool: `create_ai_memory` with optional interpretation and score
- Updated all existing tools to return Layer 2 fields
- Backward compatible: `create_memory` still works (Layer 1)
## Design Philosophy
**"AI judges, tool records"**
- Tool provides simple storage, no complex logic
- AI (Claude) decides interpretation and importance
- Both fields are optional for flexibility
- Natural integration: interpretation + evaluation happen together
## Usage Example
```javascript
// Layer 1: Simple storage (still works)
create_memory({ content: "Tokyo weather is sunny" })
// Layer 2: AI-enhanced storage
create_ai_memory({
content: "Tokyo weather is sunny",
ai_interpretation: "User planning outdoor activities in Tokyo. Weather info important for travel decisions.",
priority_score: 0.75
})
```
## Backward Compatibility
- Layer 1 functionality unchanged
- Existing databases auto-migrate
- All Layer 2 fields are Optional<T>
- Old tools continue to work
## Testing
- All unit tests passing
- Schema migration tested
- Score clamping (0.0-1.0) tested
- Optional fields tested
Version: 0.2.0 (Layer 2)
Status: Implementation complete, ready for local testing
This commit is contained in:
@@ -11,6 +11,14 @@ pub struct Memory {
|
|||||||
/// The actual content of the memory
|
/// The actual content of the memory
|
||||||
pub content: String,
|
pub content: String,
|
||||||
|
|
||||||
|
/// AI's creative interpretation of the content (Layer 2)
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub ai_interpretation: Option<String>,
|
||||||
|
|
||||||
|
/// Priority score evaluated by AI: 0.0 (low) to 1.0 (high) (Layer 2)
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub priority_score: Option<f32>,
|
||||||
|
|
||||||
/// When this memory was created
|
/// When this memory was created
|
||||||
pub created_at: DateTime<Utc>,
|
pub created_at: DateTime<Utc>,
|
||||||
|
|
||||||
@@ -19,7 +27,7 @@ pub struct Memory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Memory {
|
impl Memory {
|
||||||
/// Create a new memory with generated ULID
|
/// Create a new memory with generated ULID (Layer 1)
|
||||||
pub fn new(content: String) -> Self {
|
pub fn new(content: String) -> Self {
|
||||||
let now = Utc::now();
|
let now = Utc::now();
|
||||||
let id = Ulid::new().to_string();
|
let id = Ulid::new().to_string();
|
||||||
@@ -27,6 +35,27 @@ impl Memory {
|
|||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
content,
|
content,
|
||||||
|
ai_interpretation: None,
|
||||||
|
priority_score: None,
|
||||||
|
created_at: now,
|
||||||
|
updated_at: now,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new AI-interpreted memory (Layer 2)
|
||||||
|
pub fn new_ai(
|
||||||
|
content: String,
|
||||||
|
ai_interpretation: Option<String>,
|
||||||
|
priority_score: Option<f32>,
|
||||||
|
) -> Self {
|
||||||
|
let now = Utc::now();
|
||||||
|
let id = Ulid::new().to_string();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
id,
|
||||||
|
content,
|
||||||
|
ai_interpretation,
|
||||||
|
priority_score,
|
||||||
created_at: now,
|
created_at: now,
|
||||||
updated_at: now,
|
updated_at: now,
|
||||||
}
|
}
|
||||||
@@ -37,6 +66,18 @@ impl Memory {
|
|||||||
self.content = content;
|
self.content = content;
|
||||||
self.updated_at = Utc::now();
|
self.updated_at = Utc::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set or update AI interpretation
|
||||||
|
pub fn set_ai_interpretation(&mut self, interpretation: String) {
|
||||||
|
self.ai_interpretation = Some(interpretation);
|
||||||
|
self.updated_at = Utc::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set or update priority score
|
||||||
|
pub fn set_priority_score(&mut self, score: f32) {
|
||||||
|
self.priority_score = Some(score.clamp(0.0, 1.0));
|
||||||
|
self.updated_at = Utc::now();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -48,6 +89,20 @@ mod tests {
|
|||||||
let memory = Memory::new("Test content".to_string());
|
let memory = Memory::new("Test content".to_string());
|
||||||
assert_eq!(memory.content, "Test content");
|
assert_eq!(memory.content, "Test content");
|
||||||
assert!(!memory.id.is_empty());
|
assert!(!memory.id.is_empty());
|
||||||
|
assert!(memory.ai_interpretation.is_none());
|
||||||
|
assert!(memory.priority_score.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_new_ai_memory() {
|
||||||
|
let memory = Memory::new_ai(
|
||||||
|
"Test content".to_string(),
|
||||||
|
Some("AI interpretation".to_string()),
|
||||||
|
Some(0.75),
|
||||||
|
);
|
||||||
|
assert_eq!(memory.content, "Test content");
|
||||||
|
assert_eq!(memory.ai_interpretation, Some("AI interpretation".to_string()));
|
||||||
|
assert_eq!(memory.priority_score, Some(0.75));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -61,4 +116,25 @@ mod tests {
|
|||||||
assert_eq!(memory.content, "Updated");
|
assert_eq!(memory.content, "Updated");
|
||||||
assert!(memory.updated_at > original_time);
|
assert!(memory.updated_at > original_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_set_ai_interpretation() {
|
||||||
|
let mut memory = Memory::new("Test".to_string());
|
||||||
|
memory.set_ai_interpretation("Interpretation".to_string());
|
||||||
|
assert_eq!(memory.ai_interpretation, Some("Interpretation".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_set_priority_score() {
|
||||||
|
let mut memory = Memory::new("Test".to_string());
|
||||||
|
memory.set_priority_score(0.8);
|
||||||
|
assert_eq!(memory.priority_score, Some(0.8));
|
||||||
|
|
||||||
|
// Test clamping
|
||||||
|
memory.set_priority_score(1.5);
|
||||||
|
assert_eq!(memory.priority_score, Some(1.0));
|
||||||
|
|
||||||
|
memory.set_priority_score(-0.5);
|
||||||
|
assert_eq!(memory.priority_score, Some(0.0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,12 +25,26 @@ impl MemoryStore {
|
|||||||
"CREATE TABLE IF NOT EXISTS memories (
|
"CREATE TABLE IF NOT EXISTS memories (
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
content TEXT NOT NULL,
|
content TEXT NOT NULL,
|
||||||
|
ai_interpretation TEXT,
|
||||||
|
priority_score REAL,
|
||||||
created_at TEXT NOT NULL,
|
created_at TEXT NOT NULL,
|
||||||
updated_at TEXT NOT NULL
|
updated_at TEXT NOT NULL
|
||||||
)",
|
)",
|
||||||
[],
|
[],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
// Migrate existing tables (add columns if they don't exist)
|
||||||
|
// SQLite doesn't have "IF NOT EXISTS" for columns, so we check first
|
||||||
|
let has_ai_interpretation: bool = conn
|
||||||
|
.prepare("SELECT COUNT(*) FROM pragma_table_info('memories') WHERE name='ai_interpretation'")?
|
||||||
|
.query_row([], |row| row.get(0))
|
||||||
|
.map(|count: i32| count > 0)?;
|
||||||
|
|
||||||
|
if !has_ai_interpretation {
|
||||||
|
conn.execute("ALTER TABLE memories ADD COLUMN ai_interpretation TEXT", [])?;
|
||||||
|
conn.execute("ALTER TABLE memories ADD COLUMN priority_score REAL", [])?;
|
||||||
|
}
|
||||||
|
|
||||||
// Create indexes for better query performance
|
// Create indexes for better query performance
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"CREATE INDEX IF NOT EXISTS idx_created_at ON memories(created_at)",
|
"CREATE INDEX IF NOT EXISTS idx_created_at ON memories(created_at)",
|
||||||
@@ -42,6 +56,11 @@ impl MemoryStore {
|
|||||||
[],
|
[],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
conn.execute(
|
||||||
|
"CREATE INDEX IF NOT EXISTS idx_priority_score ON memories(priority_score)",
|
||||||
|
[],
|
||||||
|
)?;
|
||||||
|
|
||||||
Ok(Self { conn })
|
Ok(Self { conn })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,10 +79,13 @@ impl MemoryStore {
|
|||||||
/// Insert a new memory
|
/// Insert a new memory
|
||||||
pub fn create(&self, memory: &Memory) -> Result<()> {
|
pub fn create(&self, memory: &Memory) -> Result<()> {
|
||||||
self.conn.execute(
|
self.conn.execute(
|
||||||
"INSERT INTO memories (id, content, created_at, updated_at) VALUES (?1, ?2, ?3, ?4)",
|
"INSERT INTO memories (id, content, ai_interpretation, priority_score, created_at, updated_at)
|
||||||
|
VALUES (?1, ?2, ?3, ?4, ?5, ?6)",
|
||||||
params![
|
params![
|
||||||
&memory.id,
|
&memory.id,
|
||||||
&memory.content,
|
&memory.content,
|
||||||
|
&memory.ai_interpretation,
|
||||||
|
&memory.priority_score,
|
||||||
memory.created_at.to_rfc3339(),
|
memory.created_at.to_rfc3339(),
|
||||||
memory.updated_at.to_rfc3339(),
|
memory.updated_at.to_rfc3339(),
|
||||||
],
|
],
|
||||||
@@ -75,26 +97,29 @@ impl MemoryStore {
|
|||||||
pub fn get(&self, id: &str) -> Result<Memory> {
|
pub fn get(&self, id: &str) -> Result<Memory> {
|
||||||
let mut stmt = self
|
let mut stmt = self
|
||||||
.conn
|
.conn
|
||||||
.prepare("SELECT id, content, created_at, updated_at FROM memories WHERE id = ?1")?;
|
.prepare("SELECT id, content, ai_interpretation, priority_score, created_at, updated_at
|
||||||
|
FROM memories WHERE id = ?1")?;
|
||||||
|
|
||||||
let memory = stmt.query_row(params![id], |row| {
|
let memory = stmt.query_row(params![id], |row| {
|
||||||
let created_at: String = row.get(2)?;
|
let created_at: String = row.get(4)?;
|
||||||
let updated_at: String = row.get(3)?;
|
let updated_at: String = row.get(5)?;
|
||||||
|
|
||||||
Ok(Memory {
|
Ok(Memory {
|
||||||
id: row.get(0)?,
|
id: row.get(0)?,
|
||||||
content: row.get(1)?,
|
content: row.get(1)?,
|
||||||
|
ai_interpretation: row.get(2)?,
|
||||||
|
priority_score: row.get(3)?,
|
||||||
created_at: DateTime::parse_from_rfc3339(&created_at)
|
created_at: DateTime::parse_from_rfc3339(&created_at)
|
||||||
.map(|dt| dt.with_timezone(&Utc))
|
.map(|dt| dt.with_timezone(&Utc))
|
||||||
.map_err(|e| rusqlite::Error::FromSqlConversionFailure(
|
.map_err(|e| rusqlite::Error::FromSqlConversionFailure(
|
||||||
2,
|
4,
|
||||||
rusqlite::types::Type::Text,
|
rusqlite::types::Type::Text,
|
||||||
Box::new(e),
|
Box::new(e),
|
||||||
))?,
|
))?,
|
||||||
updated_at: DateTime::parse_from_rfc3339(&updated_at)
|
updated_at: DateTime::parse_from_rfc3339(&updated_at)
|
||||||
.map(|dt| dt.with_timezone(&Utc))
|
.map(|dt| dt.with_timezone(&Utc))
|
||||||
.map_err(|e| rusqlite::Error::FromSqlConversionFailure(
|
.map_err(|e| rusqlite::Error::FromSqlConversionFailure(
|
||||||
3,
|
5,
|
||||||
rusqlite::types::Type::Text,
|
rusqlite::types::Type::Text,
|
||||||
Box::new(e),
|
Box::new(e),
|
||||||
))?,
|
))?,
|
||||||
@@ -107,9 +132,12 @@ impl MemoryStore {
|
|||||||
/// Update an existing memory
|
/// Update an existing memory
|
||||||
pub fn update(&self, memory: &Memory) -> Result<()> {
|
pub fn update(&self, memory: &Memory) -> Result<()> {
|
||||||
let rows_affected = self.conn.execute(
|
let rows_affected = self.conn.execute(
|
||||||
"UPDATE memories SET content = ?1, updated_at = ?2 WHERE id = ?3",
|
"UPDATE memories SET content = ?1, ai_interpretation = ?2, priority_score = ?3, updated_at = ?4
|
||||||
|
WHERE id = ?5",
|
||||||
params![
|
params![
|
||||||
&memory.content,
|
&memory.content,
|
||||||
|
&memory.ai_interpretation,
|
||||||
|
&memory.priority_score,
|
||||||
memory.updated_at.to_rfc3339(),
|
memory.updated_at.to_rfc3339(),
|
||||||
&memory.id,
|
&memory.id,
|
||||||
],
|
],
|
||||||
@@ -138,28 +166,31 @@ impl MemoryStore {
|
|||||||
/// List all memories, ordered by creation time (newest first)
|
/// List all memories, ordered by creation time (newest first)
|
||||||
pub fn list(&self) -> Result<Vec<Memory>> {
|
pub fn list(&self) -> Result<Vec<Memory>> {
|
||||||
let mut stmt = self.conn.prepare(
|
let mut stmt = self.conn.prepare(
|
||||||
"SELECT id, content, created_at, updated_at FROM memories ORDER BY created_at DESC",
|
"SELECT id, content, ai_interpretation, priority_score, created_at, updated_at
|
||||||
|
FROM memories ORDER BY created_at DESC",
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let memories = stmt
|
let memories = stmt
|
||||||
.query_map([], |row| {
|
.query_map([], |row| {
|
||||||
let created_at: String = row.get(2)?;
|
let created_at: String = row.get(4)?;
|
||||||
let updated_at: String = row.get(3)?;
|
let updated_at: String = row.get(5)?;
|
||||||
|
|
||||||
Ok(Memory {
|
Ok(Memory {
|
||||||
id: row.get(0)?,
|
id: row.get(0)?,
|
||||||
content: row.get(1)?,
|
content: row.get(1)?,
|
||||||
|
ai_interpretation: row.get(2)?,
|
||||||
|
priority_score: row.get(3)?,
|
||||||
created_at: DateTime::parse_from_rfc3339(&created_at)
|
created_at: DateTime::parse_from_rfc3339(&created_at)
|
||||||
.map(|dt| dt.with_timezone(&Utc))
|
.map(|dt| dt.with_timezone(&Utc))
|
||||||
.map_err(|e| rusqlite::Error::FromSqlConversionFailure(
|
.map_err(|e| rusqlite::Error::FromSqlConversionFailure(
|
||||||
2,
|
4,
|
||||||
rusqlite::types::Type::Text,
|
rusqlite::types::Type::Text,
|
||||||
Box::new(e),
|
Box::new(e),
|
||||||
))?,
|
))?,
|
||||||
updated_at: DateTime::parse_from_rfc3339(&updated_at)
|
updated_at: DateTime::parse_from_rfc3339(&updated_at)
|
||||||
.map(|dt| dt.with_timezone(&Utc))
|
.map(|dt| dt.with_timezone(&Utc))
|
||||||
.map_err(|e| rusqlite::Error::FromSqlConversionFailure(
|
.map_err(|e| rusqlite::Error::FromSqlConversionFailure(
|
||||||
3,
|
5,
|
||||||
rusqlite::types::Type::Text,
|
rusqlite::types::Type::Text,
|
||||||
Box::new(e),
|
Box::new(e),
|
||||||
))?,
|
))?,
|
||||||
@@ -170,34 +201,37 @@ impl MemoryStore {
|
|||||||
Ok(memories)
|
Ok(memories)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Search memories by content (case-insensitive)
|
/// Search memories by content or AI interpretation (case-insensitive)
|
||||||
pub fn search(&self, query: &str) -> Result<Vec<Memory>> {
|
pub fn search(&self, query: &str) -> Result<Vec<Memory>> {
|
||||||
let mut stmt = self.conn.prepare(
|
let mut stmt = self.conn.prepare(
|
||||||
"SELECT id, content, created_at, updated_at FROM memories
|
"SELECT id, content, ai_interpretation, priority_score, created_at, updated_at
|
||||||
WHERE content LIKE ?1
|
FROM memories
|
||||||
|
WHERE content LIKE ?1 OR ai_interpretation LIKE ?1
|
||||||
ORDER BY created_at DESC",
|
ORDER BY created_at DESC",
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let search_pattern = format!("%{}%", query);
|
let search_pattern = format!("%{}%", query);
|
||||||
let memories = stmt
|
let memories = stmt
|
||||||
.query_map(params![search_pattern], |row| {
|
.query_map(params![search_pattern], |row| {
|
||||||
let created_at: String = row.get(2)?;
|
let created_at: String = row.get(4)?;
|
||||||
let updated_at: String = row.get(3)?;
|
let updated_at: String = row.get(5)?;
|
||||||
|
|
||||||
Ok(Memory {
|
Ok(Memory {
|
||||||
id: row.get(0)?,
|
id: row.get(0)?,
|
||||||
content: row.get(1)?,
|
content: row.get(1)?,
|
||||||
|
ai_interpretation: row.get(2)?,
|
||||||
|
priority_score: row.get(3)?,
|
||||||
created_at: DateTime::parse_from_rfc3339(&created_at)
|
created_at: DateTime::parse_from_rfc3339(&created_at)
|
||||||
.map(|dt| dt.with_timezone(&Utc))
|
.map(|dt| dt.with_timezone(&Utc))
|
||||||
.map_err(|e| rusqlite::Error::FromSqlConversionFailure(
|
.map_err(|e| rusqlite::Error::FromSqlConversionFailure(
|
||||||
2,
|
4,
|
||||||
rusqlite::types::Type::Text,
|
rusqlite::types::Type::Text,
|
||||||
Box::new(e),
|
Box::new(e),
|
||||||
))?,
|
))?,
|
||||||
updated_at: DateTime::parse_from_rfc3339(&updated_at)
|
updated_at: DateTime::parse_from_rfc3339(&updated_at)
|
||||||
.map(|dt| dt.with_timezone(&Utc))
|
.map(|dt| dt.with_timezone(&Utc))
|
||||||
.map_err(|e| rusqlite::Error::FromSqlConversionFailure(
|
.map_err(|e| rusqlite::Error::FromSqlConversionFailure(
|
||||||
3,
|
5,
|
||||||
rusqlite::types::Type::Text,
|
rusqlite::types::Type::Text,
|
||||||
Box::new(e),
|
Box::new(e),
|
||||||
))?,
|
))?,
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ impl BaseMCPServer {
|
|||||||
vec![
|
vec![
|
||||||
json!({
|
json!({
|
||||||
"name": "create_memory",
|
"name": "create_memory",
|
||||||
"description": "Create a new memory entry",
|
"description": "Create a new memory entry (Layer 1: simple storage)",
|
||||||
"inputSchema": {
|
"inputSchema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -100,6 +100,30 @@ impl BaseMCPServer {
|
|||||||
"required": ["content"]
|
"required": ["content"]
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
json!({
|
||||||
|
"name": "create_ai_memory",
|
||||||
|
"description": "Create a memory with AI interpretation and priority score (Layer 2)",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"content": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Original content of the memory"
|
||||||
|
},
|
||||||
|
"ai_interpretation": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "AI's creative interpretation of the content (optional)"
|
||||||
|
},
|
||||||
|
"priority_score": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Priority score from 0.0 (low) to 1.0 (high) (optional)",
|
||||||
|
"minimum": 0.0,
|
||||||
|
"maximum": 1.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["content"]
|
||||||
|
}
|
||||||
|
}),
|
||||||
json!({
|
json!({
|
||||||
"name": "get_memory",
|
"name": "get_memory",
|
||||||
"description": "Get a memory by ID",
|
"description": "Get a memory by ID",
|
||||||
@@ -192,6 +216,7 @@ impl BaseMCPServer {
|
|||||||
fn execute_tool(&self, tool_name: &str, arguments: &Value) -> Value {
|
fn execute_tool(&self, tool_name: &str, arguments: &Value) -> Value {
|
||||||
match tool_name {
|
match tool_name {
|
||||||
"create_memory" => self.tool_create_memory(arguments),
|
"create_memory" => self.tool_create_memory(arguments),
|
||||||
|
"create_ai_memory" => self.tool_create_ai_memory(arguments),
|
||||||
"get_memory" => self.tool_get_memory(arguments),
|
"get_memory" => self.tool_get_memory(arguments),
|
||||||
"search_memories" => self.tool_search_memories(arguments),
|
"search_memories" => self.tool_search_memories(arguments),
|
||||||
"list_memories" => self.tool_list_memories(),
|
"list_memories" => self.tool_list_memories(),
|
||||||
@@ -221,6 +246,30 @@ impl BaseMCPServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn tool_create_ai_memory(&self, arguments: &Value) -> Value {
|
||||||
|
let content = arguments["content"].as_str().unwrap_or("");
|
||||||
|
let ai_interpretation = arguments["ai_interpretation"]
|
||||||
|
.as_str()
|
||||||
|
.map(|s| s.to_string());
|
||||||
|
let priority_score = arguments["priority_score"].as_f64().map(|f| f as f32);
|
||||||
|
|
||||||
|
let memory = Memory::new_ai(content.to_string(), ai_interpretation, priority_score);
|
||||||
|
|
||||||
|
match self.store.create(&memory) {
|
||||||
|
Ok(()) => json!({
|
||||||
|
"success": true,
|
||||||
|
"id": memory.id,
|
||||||
|
"message": "AI memory created successfully",
|
||||||
|
"has_interpretation": memory.ai_interpretation.is_some(),
|
||||||
|
"has_score": memory.priority_score.is_some()
|
||||||
|
}),
|
||||||
|
Err(e) => json!({
|
||||||
|
"success": false,
|
||||||
|
"error": e.to_string()
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn tool_get_memory(&self, arguments: &Value) -> Value {
|
fn tool_get_memory(&self, arguments: &Value) -> Value {
|
||||||
let id = arguments["id"].as_str().unwrap_or("");
|
let id = arguments["id"].as_str().unwrap_or("");
|
||||||
|
|
||||||
@@ -230,6 +279,8 @@ impl BaseMCPServer {
|
|||||||
"memory": {
|
"memory": {
|
||||||
"id": memory.id,
|
"id": memory.id,
|
||||||
"content": memory.content,
|
"content": memory.content,
|
||||||
|
"ai_interpretation": memory.ai_interpretation,
|
||||||
|
"priority_score": memory.priority_score,
|
||||||
"created_at": memory.created_at,
|
"created_at": memory.created_at,
|
||||||
"updated_at": memory.updated_at
|
"updated_at": memory.updated_at
|
||||||
}
|
}
|
||||||
@@ -250,6 +301,8 @@ impl BaseMCPServer {
|
|||||||
"memories": memories.into_iter().map(|m| json!({
|
"memories": memories.into_iter().map(|m| json!({
|
||||||
"id": m.id,
|
"id": m.id,
|
||||||
"content": m.content,
|
"content": m.content,
|
||||||
|
"ai_interpretation": m.ai_interpretation,
|
||||||
|
"priority_score": m.priority_score,
|
||||||
"created_at": m.created_at,
|
"created_at": m.created_at,
|
||||||
"updated_at": m.updated_at
|
"updated_at": m.updated_at
|
||||||
})).collect::<Vec<_>>()
|
})).collect::<Vec<_>>()
|
||||||
@@ -268,6 +321,8 @@ impl BaseMCPServer {
|
|||||||
"memories": memories.into_iter().map(|m| json!({
|
"memories": memories.into_iter().map(|m| json!({
|
||||||
"id": m.id,
|
"id": m.id,
|
||||||
"content": m.content,
|
"content": m.content,
|
||||||
|
"ai_interpretation": m.ai_interpretation,
|
||||||
|
"priority_score": m.priority_score,
|
||||||
"created_at": m.created_at,
|
"created_at": m.created_at,
|
||||||
"updated_at": m.updated_at
|
"updated_at": m.updated_at
|
||||||
})).collect::<Vec<_>>()
|
})).collect::<Vec<_>>()
|
||||||
|
|||||||
Reference in New Issue
Block a user