lex-agentic-memory 0.1.31 → 0.1.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/lib/legion/extensions/agentic/memory/trace/helpers/store.rb +23 -6
- data/lib/legion/extensions/agentic/memory/version.rb +1 -1
- data/spec/legion/extensions/agentic/memory/trace/helpers/store_spec.rb +12 -0
- data/spec/legion/extensions/agentic/memory/trace/local_persistence_spec.rb +17 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 07b491ea4b919f623905cf3fe0c651c6a462e46bfe096e06e4221e9eb9e6b801
|
|
4
|
+
data.tar.gz: b92fc5808525806e2dca50c86ea4382583adcbe5b6b9e84d0dd8e1c4add0f14b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ed8eb6cff096080b1435aab249896d4c473d1aab7b11ebec1f687081aa9494bc8671c029d3d7e2e80b4144b705b477e6d58fc796c412d2a6bf75a852fa02f27e
|
|
7
|
+
data.tar.gz: 834d02319dbf0c63722d8bc8e59e5f63d6c18c42c740a71a47ac5f1c6df0c1ad9b983e73b246f751bd24a784aa4e43c5d5f508ed516dbd7f94321fea220f2cf3
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.1.32] - 2026-05-07
|
|
4
|
+
### Fixed
|
|
5
|
+
- Trace association retrieval now snapshots associated traces under the store mutex before filtering.
|
|
6
|
+
- Local trace restore preserves symbol keys for JSON fields that are consumed as symbol-keyed hashes.
|
|
7
|
+
|
|
3
8
|
## [0.1.31] - 2026-04-27
|
|
4
9
|
### Added
|
|
5
10
|
- Add a heuristic pre-compaction memory save path and synchronous pre-compaction event listeners for `chat.pre_compact`, `context.pre_compact`, and `conversation.pre_compact`.
|
|
@@ -70,11 +70,14 @@ module Legion
|
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
def retrieve_associated(trace_id, min_strength: 0.0, limit: 20)
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
associated = @mutex.synchronize do
|
|
74
|
+
trace = @traces[trace_id]
|
|
75
|
+
next [] unless trace
|
|
75
76
|
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
trace[:associated_traces].filter_map { |id| @traces[id]&.dup }
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
associated
|
|
78
81
|
.select { |t| t[:strength] >= min_strength }
|
|
79
82
|
.sort_by { |t| -t[:strength] }
|
|
80
83
|
.first(limit)
|
|
@@ -354,13 +357,27 @@ module Legion
|
|
|
354
357
|
raw
|
|
355
358
|
end
|
|
356
359
|
|
|
357
|
-
def parse_db_json(raw, field,
|
|
358
|
-
Legion::JSON.load(raw.to_s)
|
|
360
|
+
def parse_db_json(raw, field, symbolize: false, &default)
|
|
361
|
+
parsed = Legion::JSON.load(raw.to_s)
|
|
362
|
+
symbolize ? symbolize_keys(parsed) : parsed
|
|
359
363
|
rescue StandardError => e
|
|
360
364
|
log.error "[trace_persistence] deserialize_trace_from_db #{field}: #{e.message}"
|
|
361
365
|
default&.call
|
|
362
366
|
end
|
|
363
367
|
|
|
368
|
+
def symbolize_keys(value)
|
|
369
|
+
case value
|
|
370
|
+
when Hash
|
|
371
|
+
value.each_with_object({}) do |(key, nested), memo|
|
|
372
|
+
memo[key.to_sym] = symbolize_keys(nested)
|
|
373
|
+
end
|
|
374
|
+
when Array
|
|
375
|
+
value.map { |nested| symbolize_keys(nested) }
|
|
376
|
+
else
|
|
377
|
+
value
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
|
|
364
381
|
def link_traces(id_a, id_b)
|
|
365
382
|
trace_a = @traces[id_a]
|
|
366
383
|
trace_b = @traces[id_b]
|
|
@@ -95,6 +95,18 @@ RSpec.describe Legion::Extensions::Agentic::Memory::Trace::Helpers::Store do
|
|
|
95
95
|
associated = store.retrieve_associated(semantic_trace[:trace_id])
|
|
96
96
|
expect(associated.size).to eq(0)
|
|
97
97
|
end
|
|
98
|
+
|
|
99
|
+
it 'snapshots associated traces while holding the store mutex' do
|
|
100
|
+
store.store(semantic_trace)
|
|
101
|
+
store.store(episodic_trace)
|
|
102
|
+
semantic_trace[:associated_traces] << episodic_trace[:trace_id]
|
|
103
|
+
|
|
104
|
+
mutex = store.instance_variable_get(:@mutex)
|
|
105
|
+
expect(mutex).to receive(:synchronize).and_call_original
|
|
106
|
+
|
|
107
|
+
associated = store.retrieve_associated(semantic_trace[:trace_id])
|
|
108
|
+
expect(associated.map { |trace| trace[:trace_id] }).to eq([episodic_trace[:trace_id]])
|
|
109
|
+
end
|
|
98
110
|
end
|
|
99
111
|
|
|
100
112
|
describe '#all_traces' do
|
|
@@ -249,6 +249,23 @@ RSpec.describe 'lex-memory local SQLite persistence' do
|
|
|
249
249
|
expect(fresh.get(episodic_trace[:trace_id])).not_to be_nil
|
|
250
250
|
end
|
|
251
251
|
|
|
252
|
+
it 'honors symbolize parsing for JSON hash fields' do
|
|
253
|
+
trace = trace_helper.new_trace(
|
|
254
|
+
type: :semantic,
|
|
255
|
+
content_payload: { fact: 'symbolized' },
|
|
256
|
+
domain_tags: ['json'],
|
|
257
|
+
emotional_valence: { joy: 0.8 }
|
|
258
|
+
)
|
|
259
|
+
store.store(trace)
|
|
260
|
+
store.save_to_local
|
|
261
|
+
|
|
262
|
+
fresh = Legion::Extensions::Agentic::Memory::Trace::Helpers::Store.new
|
|
263
|
+
restored = fresh.get(trace[:trace_id])
|
|
264
|
+
|
|
265
|
+
expect(restored[:emotional_valence]).to include(joy: 0.8)
|
|
266
|
+
expect(restored[:emotional_valence]).not_to have_key('joy')
|
|
267
|
+
end
|
|
268
|
+
|
|
252
269
|
it 'restores associations from the database into a fresh store' do
|
|
253
270
|
store.store(semantic_trace)
|
|
254
271
|
store.store(episodic_trace)
|