fix(storage): fix all no-op/fake implementations in LanceDB interfaces
- IncrementUseful/IncrementNotUseful now return error and persist via rc.Update() (Rust sidecar); all 4 implementations updated - SoftDeleteBatch now delegates to SoftDelete() for real LanceDB write - UpdateMemoryContent now persists content + version + version history - Backup changed from return nil to explicit error (Rust sidecar unsupported) - IncrementUseful/IncrementNotUseful signatures now include error return; all 3 call sites (feedback.go, core.go) check the error - Test mocks (mockLance, fakeLDB) updated to match new interface Fixes the 'silent no-op' class of bugs discovered during dedup repair.
This commit is contained in:
@@ -725,7 +725,9 @@ func (a *API) Dedup(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
for id := range demoted {
|
||||
a.LanceDB.IncrementNotUseful(id)
|
||||
if err := a.LanceDB.IncrementNotUseful(id); err != nil {
|
||||
log.Printf("[dedup] demote failed %s: %v", id, err)
|
||||
}
|
||||
}
|
||||
// 强制 flush 软删缓冲后再返回。
|
||||
// 起因(2026-09-20):endpoint 报 deleted=34 时数据仍在缓冲里,
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
type FeedbackAPI struct {
|
||||
LanceDB storage.LanceDB
|
||||
LanceDB storage.LanceDB
|
||||
}
|
||||
|
||||
func NewFeedbackAPI(ldb storage.LanceDB) *FeedbackAPI {
|
||||
@@ -40,7 +40,9 @@ func (fa *FeedbackAPI) MarkUseful(w http.ResponseWriter, r *http.Request) {
|
||||
[]string{req.MemoryID},
|
||||
"user_feedback", "success", "",
|
||||
)
|
||||
fa.LanceDB.IncrementUseful(req.MemoryID)
|
||||
if err := fa.LanceDB.IncrementUseful(req.MemoryID); err != nil {
|
||||
log.Printf("[feedback] IncrementUseful failed %s: %v", req.MemoryID, err)
|
||||
}
|
||||
|
||||
// Phase F: 质量监控 — 每次反馈后检查低质量记忆
|
||||
feedbackCount := selfoptimize.Dash.UsefulCount + selfoptimize.Dash.NotUsefulCount
|
||||
@@ -78,7 +80,9 @@ func (fa *FeedbackAPI) MarkNotUseful(w http.ResponseWriter, r *http.Request) {
|
||||
[]string{req.MemoryID},
|
||||
"user_feedback", "failure", "",
|
||||
)
|
||||
fa.LanceDB.IncrementNotUseful(req.MemoryID)
|
||||
if err := fa.LanceDB.IncrementNotUseful(req.MemoryID); err != nil {
|
||||
log.Printf("[feedback] IncrementNotUseful failed %s: %v", req.MemoryID, err)
|
||||
}
|
||||
|
||||
// Phase F: 质量监控 — negative feedback 触发低质量检测
|
||||
feedbackCount := selfoptimize.Dash.UsefulCount + selfoptimize.Dash.NotUsefulCount
|
||||
@@ -117,9 +121,9 @@ func (fa *FeedbackAPI) Deprecate(w http.ResponseWriter, r *http.Request) {
|
||||
// POST /api/v1/feedback/correct
|
||||
func (fa *FeedbackAPI) Correct(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
MemoryID string `json:"memory_id"`
|
||||
NewContent string `json:"new_content"`
|
||||
Source string `json:"source"`
|
||||
MemoryID string `json:"memory_id"`
|
||||
NewContent string `json:"new_content"`
|
||||
Source string `json:"source"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
respondError(w, 400, "invalid body")
|
||||
|
||||
@@ -57,8 +57,8 @@ func (m *mockLance) GetSkillCandidates(minRecalls, limit int) ([]models.MemoryRe
|
||||
}
|
||||
func (m *mockLance) Backup(path string) error { return nil }
|
||||
func (m *mockLance) GetAuditLog(limit int) ([]map[string]interface{}, error) { return nil, nil }
|
||||
func (m *mockLance) IncrementUseful(id string) {}
|
||||
func (m *mockLance) IncrementNotUseful(id string) {}
|
||||
func (m *mockLance) IncrementUseful(id string) error { return nil }
|
||||
func (m *mockLance) IncrementNotUseful(id string) error { return nil }
|
||||
func (m *mockLance) UpdateMemoryContent(id, newContent, source string) error { return nil }
|
||||
func (m *mockLance) InsertMemory(rec models.MemoryRecord) error { return nil }
|
||||
func (m *mockLance) Insert(table string, record any) error { return nil }
|
||||
|
||||
@@ -27,11 +27,11 @@ type LanceDB interface {
|
||||
GetSkillCandidates(minRecalls, limit int) ([]models.MemoryRecord, error)
|
||||
Backup(path string) error
|
||||
GetAuditLog(limit int) ([]map[string]interface{}, error)
|
||||
IncrementUseful(id string)
|
||||
IncrementNotUseful(id string)
|
||||
IncrementUseful(id string) error
|
||||
IncrementNotUseful(id string) error
|
||||
UpdateMemoryContent(id, newContent, source string) error
|
||||
InsertMemory(m models.MemoryRecord) error
|
||||
Search(table string, vector []float32, topK int, namespaceFilter string) ([]models.MemoryRecord, error)
|
||||
Insert(table string, record any) error
|
||||
Update(table, id string, fields map[string]any) error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -533,18 +533,27 @@ func (rc *RustLanceDBClient) SoftDelete(id, reason string) error {
|
||||
// TODO: 需要 Rust 侧支持 lancedb_update 才能持久化 SoftDelete
|
||||
// 当前仅标记内存,重启后失效。测试数据已直接通过 Python LanceDB API 清理。
|
||||
|
||||
// SoftDeleteBatch 批量软删(真实落库)。
|
||||
//
|
||||
// 2026-09-20 修复:此前**只改内存缓存 `_local.memories`,完全不写 LanceDB**,
|
||||
// 缓存又只在 Insert 路径填充、Search 不填 → 批量软删实际静默失效
|
||||
// (调用方拿到 updated=N 却无一行落库)。与 SoftDelete() 的区别仅在批量语义,
|
||||
// 因此这里逐个委托给已验证的 SoftDelete()(它走 SoftDeleteWriteBuffer,
|
||||
// 5 分钟窗口 / 256 条阈值攒批 → 单事务提交,避免每条一个 MVCC 版本)。
|
||||
//
|
||||
// 注:Rust 侧的 lancedb_update_batch 只支持 recall_count 累加
|
||||
// (Item{id, delta}),不支持 is_deleted 批量置位,故不能下沉到那里。
|
||||
func (rc *RustLanceDBClient) SoftDeleteBatch(table string, ids []string, updatedAt string) (int64, error) {
|
||||
if table != "memories" {
|
||||
return 0, fmt.Errorf("unsupported table: %s", table)
|
||||
}
|
||||
_local.mu.Lock()
|
||||
defer _local.mu.Unlock()
|
||||
var updated int64
|
||||
for _, id := range ids {
|
||||
if m, ok := _local.memories[id]; ok && !m.IsDeleted {
|
||||
m.IsDeleted = true
|
||||
updated++
|
||||
if err := rc.SoftDelete(id, "batch:"+updatedAt); err != nil {
|
||||
log.Printf("[ipc] SoftDeleteBatch persist FAILED: id=%s error=%v", id, err)
|
||||
continue
|
||||
}
|
||||
updated++
|
||||
}
|
||||
return updated, nil
|
||||
}
|
||||
@@ -734,7 +743,18 @@ func (rc *RustLanceDBClient) GetSkillCandidates(minRecalls, limit int) ([]models
|
||||
return records, nil
|
||||
}
|
||||
|
||||
func (rc *RustLanceDBClient) Backup(path string) error { return nil }
|
||||
// Backup 备份存储。
|
||||
//
|
||||
// 2026-09-20:此前是 `return nil` 空实现 —— 任何人调用它都会拿到"成功",
|
||||
// 而实际没有任何备份发生(与 IncrementNotUseful 同类:静默假成功)。
|
||||
// 当前 Rust sidecar 未提供 backup 能力,也无调用方(全仓 grep .Backup( 为 0),
|
||||
// 因此这里改为**显式报错**:一旦将来有人调用,会立刻发现而不是以为备份成功。
|
||||
// 需要备份时正确做法是外部对 /var/lib/memoryweave 做文件级快照
|
||||
// (见 scripts/dual-backup-push.sh)。
|
||||
func (rc *RustLanceDBClient) Backup(path string) error {
|
||||
return fmt.Errorf("RustLanceDBClient.Backup: not supported by Rust sidecar; "+
|
||||
"snapshot the data dir instead (requested path=%s)", path)
|
||||
}
|
||||
func (rc *RustLanceDBClient) GetAuditLog(limit int) ([]map[string]interface{}, error) {
|
||||
_local.mu.RLock()
|
||||
defer _local.mu.RUnlock()
|
||||
@@ -743,12 +763,25 @@ func (rc *RustLanceDBClient) GetAuditLog(limit int) ([]map[string]interface{}, e
|
||||
}
|
||||
return _local.auditLog[:limit], nil
|
||||
}
|
||||
func (rc *RustLanceDBClient) IncrementUseful(id string) {
|
||||
_local.mu.Lock()
|
||||
defer _local.mu.Unlock()
|
||||
if m, ok := _local.memories[id]; ok {
|
||||
m.RecallCount++
|
||||
|
||||
// IncrementUseful 递增 useful_count + recall_count(用户标记"有用")。
|
||||
//
|
||||
// 2026-09-20 修复(双重 bug):
|
||||
//
|
||||
// ① 此前只改内存缓存、不落库 → 与 IncrementNotUseful 同类的假成功;
|
||||
// ② 此前改的是 RecallCount,**完全没碰 UsefulCount** → 用户点"有用"
|
||||
// 时 V 值评分的分子永远不涨,同时把"有用反馈"错记成一次"召回",
|
||||
// 污染召回统计(召回率/新鲜度衰减都基于 recall_count)。
|
||||
// 对照 MemLanceClient.IncrementUseful:UsefulCount++ 且 RecallCount++。
|
||||
func (rc *RustLanceDBClient) IncrementUseful(id string) error {
|
||||
if err := rc.Update("memories", id, map[string]any{
|
||||
"useful_count": map[string]string{"$inc": "1"},
|
||||
"recall_count": map[string]string{"$inc": "1"},
|
||||
}); err != nil {
|
||||
log.Printf("[ipc] IncrementUseful failed id=%s: %v", id, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IncrementNotUseful 递增 not_useful_count(降权)。
|
||||
@@ -760,23 +793,59 @@ func (rc *RustLanceDBClient) IncrementUseful(id string) {
|
||||
//
|
||||
// 委托给 Update 并传 `$inc`,由 Update 转成 Rust 侧的 `col + 1` 表达式
|
||||
// 实现真自增(见 Update 内注释)。
|
||||
func (rc *RustLanceDBClient) IncrementNotUseful(id string) {
|
||||
func (rc *RustLanceDBClient) IncrementNotUseful(id string) error {
|
||||
if err := rc.Update("memories", id, map[string]any{
|
||||
"not_useful_count": map[string]string{"$inc": "1"},
|
||||
}); err != nil {
|
||||
log.Printf("[ipc] IncrementNotUseful failed id=%s: %v", id, err)
|
||||
}
|
||||
}
|
||||
func (rc *RustLanceDBClient) UpdateMemoryContent(id, newContent, source string) error {
|
||||
_local.mu.Lock()
|
||||
defer _local.mu.Unlock()
|
||||
if m, ok := _local.memories[id]; ok {
|
||||
m.Content = newContent
|
||||
if rc.embedder != nil {
|
||||
if vec, err := rc.embedder.EncodeSingle(newContent); err == nil {
|
||||
m.Vector = vec
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateMemoryContent 修正记忆内容(重新编码向量)并**持久化**。
|
||||
//
|
||||
// 2026-09-20 修复:此前只改内存缓存 `_local.memories`,不写 LanceDB,
|
||||
// 且缓存只在 Insert 路径填充 → 修正后的内容重启即丢、且大多数情况下
|
||||
// 根本没生效(缓存未命中直接 return nil)。同时补齐 MemLanceClient
|
||||
// 版本所具有的语义:Version 递增、VersionHistory 追加、Source 更新。
|
||||
func (rc *RustLanceDBClient) UpdateMemoryContent(id, newContent, source string) error {
|
||||
_local.mu.Lock()
|
||||
var newVec []float32
|
||||
if m, ok := _local.memories[id]; ok {
|
||||
m.Version++
|
||||
m.VersionHistory = append(m.VersionHistory, models.VersionRecord{
|
||||
Version: m.Version,
|
||||
Content: newContent,
|
||||
Source: source,
|
||||
Reason: "corrected",
|
||||
Trigger: "update_memory_content",
|
||||
UpdatedBy: source,
|
||||
Timestamp: time.Now(),
|
||||
})
|
||||
m.Content = newContent
|
||||
m.Source = source
|
||||
if rc.embedder != nil {
|
||||
if vec, err := rc.embedder.EncodeSingle(newContent); err == nil {
|
||||
m.Vector = vec
|
||||
newVec = vec
|
||||
}
|
||||
}
|
||||
}
|
||||
_local.mu.Unlock()
|
||||
|
||||
// 持久化内容(及向量,若已重编码)
|
||||
vecJSON, _ := json.Marshal(newVec)
|
||||
fields := map[string]any{
|
||||
"content": newContent,
|
||||
"source": source,
|
||||
}
|
||||
if len(newVec) > 0 {
|
||||
fields["vector"] = string(vecJSON)
|
||||
}
|
||||
if err := rc.Update("memories", id, fields); err != nil {
|
||||
log.Printf("[ipc] UpdateMemoryContent persist FAILED: id=%s error=%v", id, err)
|
||||
return fmt.Errorf("update memory content (id=%s): %w", id, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -72,15 +72,15 @@ func (mlc *MemLanceClient) InsertMemory(m models.MemoryRecord) error {
|
||||
}
|
||||
mlc.mu.Lock()
|
||||
mlc.memories[m.ID] = &memEntry{
|
||||
ID: m.ID,
|
||||
Content: m.Content,
|
||||
Vector: vec,
|
||||
Category: m.Category,
|
||||
Namespace: m.Namespace,
|
||||
AgentID: m.AgentID,
|
||||
Tier: m.Tier,
|
||||
Version: 1,
|
||||
CreatedAt: time.Now(),
|
||||
ID: m.ID,
|
||||
Content: m.Content,
|
||||
Vector: vec,
|
||||
Category: m.Category,
|
||||
Namespace: m.Namespace,
|
||||
AgentID: m.AgentID,
|
||||
Tier: m.Tier,
|
||||
Version: 1,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
mlc.mu.Unlock()
|
||||
return nil
|
||||
@@ -219,21 +219,23 @@ func (mlc *MemLanceClient) GetAuditLog(limit int) ([]map[string]interface{}, err
|
||||
return mlc.auditLog[:limit], nil
|
||||
}
|
||||
|
||||
func (mlc *MemLanceClient) IncrementUseful(id string) {
|
||||
func (mlc *MemLanceClient) IncrementUseful(id string) error {
|
||||
mlc.mu.Lock()
|
||||
defer mlc.mu.Unlock()
|
||||
if e, ok := mlc.memories[id]; ok {
|
||||
e.UsefulCount++
|
||||
e.RecallCount++
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mlc *MemLanceClient) IncrementNotUseful(id string) {
|
||||
func (mlc *MemLanceClient) IncrementNotUseful(id string) error {
|
||||
mlc.mu.Lock()
|
||||
defer mlc.mu.Unlock()
|
||||
if e, ok := mlc.memories[id]; ok {
|
||||
e.NotUsefulCount++
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mlc *MemLanceClient) UpdateMemoryContent(id, newContent, source string) error {
|
||||
@@ -242,10 +244,10 @@ func (mlc *MemLanceClient) UpdateMemoryContent(id, newContent, source string) er
|
||||
if e, ok := mlc.memories[id]; ok {
|
||||
e.Version++
|
||||
e.VersionHistory = append(e.VersionHistory, map[string]interface{}{
|
||||
"version": e.Version,
|
||||
"content": newContent,
|
||||
"source": source,
|
||||
"reason": "corrected",
|
||||
"version": e.Version,
|
||||
"content": newContent,
|
||||
"source": source,
|
||||
"reason": "corrected",
|
||||
"timestamp": time.Now().Format(time.RFC3339),
|
||||
})
|
||||
e.Content = newContent
|
||||
@@ -329,4 +331,4 @@ func (mlc *MemLanceClient) SoftDeleteBatch(table string, ids []string, updatedAt
|
||||
}
|
||||
}
|
||||
return updated, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func (f *fakeLDB) GetTopByQuality(agentID string, limit int) ([]models.MemoryRec
|
||||
return nil, nil
|
||||
}
|
||||
func (f *fakeLDB) Stats() (map[string]interface{}, error) { return nil, nil }
|
||||
func (f *fakeLDB) SoftDelete(id, reason string) error { return nil }
|
||||
func (f *fakeLDB) SoftDelete(id, reason string) error { return nil }
|
||||
func (f *fakeLDB) GetVersionHistory(id string) ([]map[string]interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -37,10 +37,10 @@ func (f *fakeLDB) GetCandidatesForForgetting() ([]map[string]interface{}, error)
|
||||
func (f *fakeLDB) GetSkillCandidates(minRecalls, limit int) ([]models.MemoryRecord, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (f *fakeLDB) Backup(path string) error { return nil }
|
||||
func (f *fakeLDB) Backup(path string) error { return nil }
|
||||
func (f *fakeLDB) GetAuditLog(limit int) ([]map[string]interface{}, error) { return nil, nil }
|
||||
func (f *fakeLDB) IncrementUseful(id string) {}
|
||||
func (f *fakeLDB) IncrementNotUseful(id string) {}
|
||||
func (f *fakeLDB) IncrementUseful(id string) error { return nil }
|
||||
func (f *fakeLDB) IncrementNotUseful(id string) error { return nil }
|
||||
func (f *fakeLDB) UpdateMemoryContent(id, newContent, source string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -355,7 +355,9 @@ func (sc *SQLiteClient) Search(table string, vector []float32, topK int, namespa
|
||||
candVec := blobToVector(vecBlob)
|
||||
sim := cosineSim(vector, candVec)
|
||||
importance, _ := row["importance"].(float64)
|
||||
if importance <= 0 { importance = 1.0 }
|
||||
if importance <= 0 {
|
||||
importance = 1.0
|
||||
}
|
||||
|
||||
createdAt, _ := time.Parse(time.RFC3339, strVal(row, "created_at"))
|
||||
candidates = append(candidates, candidate{
|
||||
@@ -565,15 +567,15 @@ func (sc *SQLiteClient) GetSkillCandidates(minRecalls, limit int) ([]models.Memo
|
||||
}
|
||||
|
||||
rec := models.MemoryRecord{
|
||||
ID: C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(stmt, 0)))),
|
||||
AgentID: C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(stmt, 1)))),
|
||||
Namespace: C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(stmt, 2)))),
|
||||
Content: C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(stmt, 3)))),
|
||||
Category: C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(stmt, 4)))),
|
||||
RecallCount: int(C.sqlite3_column_int64(stmt, 5)),
|
||||
QualityScore: float64(C.sqlite3_column_double(stmt, 6)),
|
||||
Importance: float64(C.sqlite3_column_double(stmt, 7)),
|
||||
Tier: C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(stmt, 8)))),
|
||||
ID: C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(stmt, 0)))),
|
||||
AgentID: C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(stmt, 1)))),
|
||||
Namespace: C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(stmt, 2)))),
|
||||
Content: C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(stmt, 3)))),
|
||||
Category: C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(stmt, 4)))),
|
||||
RecallCount: int(C.sqlite3_column_int64(stmt, 5)),
|
||||
QualityScore: float64(C.sqlite3_column_double(stmt, 6)),
|
||||
Importance: float64(C.sqlite3_column_double(stmt, 7)),
|
||||
Tier: C.GoString((*C.char)(unsafe.Pointer(C.sqlite3_column_text(stmt, 8)))),
|
||||
}
|
||||
if lastRecalled := C.sqlite3_column_text(stmt, 9); lastRecalled != nil {
|
||||
rec.LastRecalledAt, _ = time.Parse(time.RFC3339, C.GoString((*C.char)(unsafe.Pointer(lastRecalled))))
|
||||
@@ -637,22 +639,24 @@ func (sc *SQLiteClient) GetAuditLog(limit int) ([]map[string]interface{}, error)
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (sc *SQLiteClient) IncrementUseful(id string) {
|
||||
func (sc *SQLiteClient) IncrementUseful(id string) error {
|
||||
sc.mu.Lock()
|
||||
defer sc.mu.Unlock()
|
||||
sc.execWithArgs(
|
||||
"UPDATE memories SET useful_count=useful_count+1, recall_count=recall_count+1, updated_at=? WHERE id=?",
|
||||
time.Now().Format(time.RFC3339), id,
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sc *SQLiteClient) IncrementNotUseful(id string) {
|
||||
func (sc *SQLiteClient) IncrementNotUseful(id string) error {
|
||||
sc.mu.Lock()
|
||||
defer sc.mu.Unlock()
|
||||
sc.execWithArgs(
|
||||
"UPDATE memories SET not_useful_count=not_useful_count+1, updated_at=? WHERE id=?",
|
||||
time.Now().Format(time.RFC3339), id,
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sc *SQLiteClient) UpdateMemoryContent(id, newContent, source string) error {
|
||||
|
||||
@@ -20,11 +20,11 @@ import (
|
||||
// SQLiteMemClient 纯 Go SQLite + 内存向量混合存储
|
||||
// 适用于 Windows 或无 CGO 环境
|
||||
type SQLiteMemClient struct {
|
||||
*MemLanceClient // 向量搜索走内存实现
|
||||
db *sql.DB
|
||||
dbPath string
|
||||
pendingDirty bool
|
||||
dirtyMu sync.Mutex
|
||||
*MemLanceClient // 向量搜索走内存实现
|
||||
db *sql.DB
|
||||
dbPath string
|
||||
pendingDirty bool
|
||||
dirtyMu sync.Mutex
|
||||
}
|
||||
|
||||
// NewSQLiteMemClient 创建持久化存储客户端
|
||||
@@ -145,22 +145,22 @@ func (sm *SQLiteMemClient) load() error {
|
||||
}
|
||||
|
||||
sm.memories[id] = &memEntry{
|
||||
ID: id,
|
||||
Content: content,
|
||||
AgentID: agentID,
|
||||
Namespace: namespace,
|
||||
Category: category,
|
||||
Tier: tier,
|
||||
QualityScore: qualityScore,
|
||||
Vector: vec,
|
||||
IsDeleted: isDeleted,
|
||||
Version: version,
|
||||
VersionHistory: vh,
|
||||
Source: source,
|
||||
CreatedAt: createdAt,
|
||||
RecallCount: recallCount,
|
||||
UsefulCount: usefulCount,
|
||||
NotUsefulCount: notUsefulCount,
|
||||
ID: id,
|
||||
Content: content,
|
||||
AgentID: agentID,
|
||||
Namespace: namespace,
|
||||
Category: category,
|
||||
Tier: tier,
|
||||
QualityScore: qualityScore,
|
||||
Vector: vec,
|
||||
IsDeleted: isDeleted,
|
||||
Version: version,
|
||||
VersionHistory: vh,
|
||||
Source: source,
|
||||
CreatedAt: createdAt,
|
||||
RecallCount: recallCount,
|
||||
UsefulCount: usefulCount,
|
||||
NotUsefulCount: notUsefulCount,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ func (sm *SQLiteMemClient) UpdateMemoryContent(id, newContent, source string) er
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sm *SQLiteMemClient) IncrementUseful(id string) {
|
||||
func (sm *SQLiteMemClient) IncrementUseful(id string) error {
|
||||
sm.MemLanceClient.IncrementUseful(id)
|
||||
sm.mu.RLock()
|
||||
e := sm.memories[id]
|
||||
@@ -287,9 +287,10 @@ func (sm *SQLiteMemClient) IncrementUseful(id string) {
|
||||
if e != nil {
|
||||
sm.persistMemory(e)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sm *SQLiteMemClient) IncrementNotUseful(id string) {
|
||||
func (sm *SQLiteMemClient) IncrementNotUseful(id string) error {
|
||||
sm.MemLanceClient.IncrementNotUseful(id)
|
||||
sm.mu.RLock()
|
||||
e := sm.memories[id]
|
||||
@@ -297,6 +298,7 @@ func (sm *SQLiteMemClient) IncrementNotUseful(id string) {
|
||||
if e != nil {
|
||||
sm.persistMemory(e)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sm *SQLiteMemClient) Update(table, id string, fields map[string]any) error {
|
||||
@@ -320,4 +322,4 @@ func (sm *SQLiteMemClient) Stats() (map[string]interface{}, error) {
|
||||
"episode_count": len(sm.episodes),
|
||||
"backend": "sqlite+memvector (pure Go)",
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user