forked from diqierjia/StrataGate-AgentMemory
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbasic.ts
More file actions
87 lines (78 loc) · 2.92 KB
/
Copy pathbasic.ts
File metadata and controls
87 lines (78 loc) · 2.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import {
StrataGate,
type BlockSummarizer,
type ElementProjector,
type EventExtractor,
} from '../src/index.js';
const summarize: BlockSummarizer = async (messages) => ({
l0Title: 'API design discussion',
l0Tags: ['api', 'decision'],
l1Summary: 'The team chose cursor pagination for the public API.',
l2Keypoints: messages.map((message) => message.content),
shouldExtract: true,
});
const extract: EventExtractor = async ({ target }) => ({
shouldExtract: true,
reason: 'A durable technical decision was made.',
events: [{
title: 'Use cursor pagination',
summary: 'The public API should use cursor pagination instead of page numbers.',
sourceMessageIds: target.l5Raw.filter((message) => message.role === 'user').map((message) => message.id),
sourceBlockId: target.id,
tags: ['api', 'pagination'],
temporal: { status: 'occurred', eventType: 'decision' },
}],
});
// Element cards are a separately retryable materialized view. The callback may
// call any model provider; StrataGate validates every proposed source event ID.
const projectElements: ElementProjector = async ({ events }) => ({
reason: 'Update the current project view from the new immutable event.',
changes: events.map((event) => ({
element: { name: 'Public API', type: 'project' },
operation: 'set_state',
key: 'pagination',
mode: 'state',
value: 'cursor pagination',
sourceEventIds: [event.id],
confidence: 1,
})),
});
const memory = await StrataGate.open({
database: './stratagate-example.db',
namespace: 'example:basic',
blockTurnSize: 1,
summarizer: summarize,
extractor: extract,
elementProjector: projectElements,
});
await memory.appendTurn({
user: 'Let us use cursor pagination for the public API.',
assistant: 'Agreed. I will treat that as the current API decision.',
});
// Extraction waits until the following block exists, so it can use both
// earlier and later context without taking quotes from neighboring blocks.
await memory.appendTurn({
user: 'Now define the response envelope.',
assistant: 'I will keep the pagination decision in mind.',
});
const results = await memory.searchEvents('How should the API paginate?');
const elementFacts = await memory.searchElements('current API pagination', { type: 'project' });
const evidence = new Set([
...results.map(({ event }) => event.id),
...elementFacts.map(({ id }) => id),
]);
const assessment = memory.assessRetrieval({
verdict: 'sufficient',
evidence_refs: [...evidence],
fit: 'The event card records the chosen pagination strategy.',
missing: '',
next_strategy: 'answer',
}, evidence);
if (assessment.verdict === 'sufficient') {
await memory.recordMemoryUse({
eventIds: results.map(({ event }) => event.id),
elementIds: [...new Set(elementFacts.map(({ elementId }) => elementId))],
}, { receiptId: 'example:answer:1' });
console.log(elementFacts[0]?.fact.value ?? results[0]?.event.summary);
}
await memory.close();