@@ -9,16 +9,18 @@ import (
99 "time"
1010
1111 distillmath "github.com/Siddhant-K-code/distill/pkg/math"
12+ "github.com/Siddhant-K-code/distill/pkg/sensitivity"
1213 _ "modernc.org/sqlite"
1314)
1415
1516// SQLiteStore implements Store using SQLite for local persistent storage.
1617// Uses a single connection (SetMaxOpenConns(1)) so SQLite's internal
1718// serialization handles concurrency. No application-level mutex needed.
1819type SQLiteStore struct {
19- db * sql.DB
20- cfg Config
21- handlers []MemoryEventHandler
20+ db * sql.DB
21+ cfg Config
22+ handlers []MemoryEventHandler
23+ classifier * sensitivity.Classifier
2224}
2325
2426// NewSQLiteStore creates a new SQLite-backed memory store.
@@ -49,7 +51,11 @@ func NewSQLiteStore(dsn string, cfg Config) (*SQLiteStore, error) {
4951 return nil , fmt .Errorf ("enable foreign keys: %w" , err )
5052 }
5153
52- s := & SQLiteStore {db : db , cfg : cfg }
54+ s := & SQLiteStore {
55+ db : db ,
56+ cfg : cfg ,
57+ classifier : sensitivity .New (sensitivity .DefaultConfig ()),
58+ }
5359 if err := s .migrate (); err != nil {
5460 _ = db .Close ()
5561 return nil , fmt .Errorf ("migrate: %w" , err )
@@ -68,6 +74,7 @@ func (s *SQLiteStore) migrate() error {
6874 session_id TEXT DEFAULT '',
6975 metadata TEXT DEFAULT '{}',
7076 decay_level INTEGER DEFAULT 0,
77+ sensitivity INTEGER DEFAULT 0,
7178 created_at TEXT NOT NULL,
7279 last_referenced TEXT NOT NULL,
7380 access_count INTEGER DEFAULT 0,
@@ -98,6 +105,7 @@ func (s *SQLiteStore) migrate() error {
98105 {"expired_at" , "TEXT DEFAULT ''" },
99106 {"superseded_by" , "TEXT DEFAULT ''" },
100107 {"expires_at" , "TEXT DEFAULT ''" },
108+ {"sensitivity" , "INTEGER DEFAULT 0" },
101109 } {
102110 _ , _ = s .db .Exec ("ALTER TABLE memories ADD COLUMN " + col .name + " " + col .def )
103111 }
@@ -149,10 +157,19 @@ func (s *SQLiteStore) Store(ctx context.Context, req StoreRequest) (*StoreResult
149157 expiresAt = entry .ExpiresAt .UTC ().Format (time .RFC3339Nano )
150158 }
151159
160+ // Determine sensitivity level
161+ sens := entry .Sensitivity
162+ if entry .AutoClassify {
163+ classified := s .classifier .Classify (entry .Text )
164+ if classified .Level > sens {
165+ sens = classified .Level
166+ }
167+ }
168+
152169 _ , err := s .db .ExecContext (ctx ,
153- `INSERT INTO memories (id, text, embedding, source, session_id, metadata, decay_level, created_at, last_referenced, access_count, expires_at)
154- VALUES (?, ?, ?, ?, ?, ?, 0, ?, ?, 0, ?)` ,
155- id , entry .Text , embBlob , entry .Source , sessionID , string (metaJSON ), now , now , expiresAt ,
170+ `INSERT INTO memories (id, text, embedding, source, session_id, metadata, decay_level, sensitivity, created_at, last_referenced, access_count, expires_at)
171+ VALUES (?, ?, ?, ?, ?, ?, 0, ?, ?, ?, 0, ?)` ,
172+ id , entry .Text , embBlob , entry .Source , sessionID , string (metaJSON ), int ( sens ), now , now , expiresAt ,
156173 )
157174 if err != nil {
158175 return nil , fmt .Errorf ("insert memory: %w" , err )
@@ -237,7 +254,7 @@ func (s *SQLiteStore) Recall(ctx context.Context, req RecallRequest) (*RecallRes
237254 }
238255
239256 // Build query with optional tag filter and expiry exclusion
240- query := "SELECT m.id, m.text, m.embedding, m.source, m.decay_level, m.last_referenced FROM memories m"
257+ query := "SELECT m.id, m.text, m.embedding, m.source, m.decay_level, m.sensitivity, m. last_referenced FROM memories m"
241258 var args []interface {}
242259 var conditions []string
243260
@@ -273,11 +290,12 @@ func (s *SQLiteStore) Recall(ctx context.Context, req RecallRequest) (*RecallRes
273290 id , text , source , refStr string
274291 embBlob []byte
275292 decayLevel int
293+ sensitivity int
276294 }
277295 var rawRows []rawRow
278296 for rows .Next () {
279297 var r rawRow
280- if err := rows .Scan (& r .id , & r .text , & r .embBlob , & r .source , & r .decayLevel , & r .refStr ); err != nil {
298+ if err := rows .Scan (& r .id , & r .text , & r .embBlob , & r .source , & r .decayLevel , & r .sensitivity , & r . refStr ); err != nil {
281299 _ = rows .Close ()
282300 return nil , err
283301 }
@@ -323,6 +341,7 @@ func (s *SQLiteStore) Recall(ctx context.Context, req RecallRequest) (*RecallRes
323341 Tags : tags ,
324342 Relevance : relevance ,
325343 DecayLevel : DecayLevel (r .decayLevel ),
344+ Sensitivity : sensitivity .Level (r .sensitivity ),
326345 LastReferenced : lastRef ,
327346 },
328347 relevance : relevance ,
@@ -360,6 +379,9 @@ func (s *SQLiteStore) Recall(ctx context.Context, req RecallRequest) (*RecallRes
360379 // Entries with relevance >= 0.7 are considered stable candidates.
361380 hint := buildCacheBoundaryHint (results )
362381
382+ // Build sensitivity metadata from returned memories.
383+ maxSens , sensitiveChunks := buildSensitivityMetadata (results )
384+
363385 return & RecallResult {
364386 Memories : results ,
365387 Stats : RecallStats {
@@ -368,7 +390,9 @@ func (s *SQLiteStore) Recall(ctx context.Context, req RecallRequest) (*RecallRes
368390 Returned : len (results ),
369391 TokenCount : tokenCount ,
370392 },
371- CacheHint : hint ,
393+ CacheHint : hint ,
394+ MaxSensitivity : maxSens ,
395+ SensitiveChunks : sensitiveChunks ,
372396 }, nil
373397}
374398
@@ -395,6 +419,25 @@ func buildCacheBoundaryHint(memories []RecalledMemory) *CacheBoundaryHint {
395419 }
396420}
397421
422+ // buildSensitivityMetadata derives MaxSensitivity and SensitiveChunks from
423+ // the recalled memories. Only entries with non-zero sensitivity are included.
424+ func buildSensitivityMetadata (memories []RecalledMemory ) (sensitivity.Level , []SensitiveChunk ) {
425+ var maxSens sensitivity.Level
426+ var chunks []SensitiveChunk
427+ for _ , m := range memories {
428+ if m .Sensitivity > maxSens {
429+ maxSens = m .Sensitivity
430+ }
431+ if m .Sensitivity > sensitivity .None {
432+ chunks = append (chunks , SensitiveChunk {
433+ ChunkID : m .ID ,
434+ Sensitivity : m .Sensitivity ,
435+ })
436+ }
437+ }
438+ return maxSens , chunks
439+ }
440+
398441// Forget removes memories matching the given criteria.
399442func (s * SQLiteStore ) Forget (ctx context.Context , req ForgetRequest ) (* ForgetResult , error ) {
400443
0 commit comments