@batalabs/virlow-mcp-core 3.19.0 → 3.68.0
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.
- package/LICENSE +8 -18
- package/README.md +1 -1
- package/dist/api.d.ts +14 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +6 -0
- package/dist/api.js.map +1 -1
- package/dist/attrs-extract.d.ts +48 -0
- package/dist/attrs-extract.d.ts.map +1 -0
- package/dist/attrs-extract.js +153 -0
- package/dist/attrs-extract.js.map +1 -0
- package/dist/attrs.d.ts +445 -0
- package/dist/attrs.d.ts.map +1 -0
- package/dist/attrs.js +604 -0
- package/dist/attrs.js.map +1 -0
- package/dist/cjs/api.d.ts +14 -0
- package/dist/cjs/api.js +6 -0
- package/dist/cjs/attrs-extract.d.ts +47 -0
- package/dist/cjs/attrs-extract.js +159 -0
- package/dist/cjs/attrs.d.ts +444 -0
- package/dist/cjs/attrs.js +635 -0
- package/dist/cjs/index.d.ts +4 -0
- package/dist/cjs/index.js +22 -1
- package/dist/cjs/memories.d.ts +79 -1
- package/dist/cjs/memories.js +249 -15
- package/dist/cjs/memory-graph.d.ts +105 -0
- package/dist/cjs/memory-graph.js +270 -0
- package/dist/cjs/memory-note.d.ts +57 -0
- package/dist/cjs/memory-note.js +174 -10
- package/dist/cjs/memory-secrets.d.ts +19 -0
- package/dist/cjs/memory-secrets.js +108 -0
- package/dist/cjs/notes.d.ts +208 -2
- package/dist/cjs/notes.js +721 -12
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/memories.d.ts +79 -1
- package/dist/memories.d.ts.map +1 -1
- package/dist/memories.js +249 -15
- package/dist/memories.js.map +1 -1
- package/dist/memory-graph.d.ts +106 -0
- package/dist/memory-graph.d.ts.map +1 -0
- package/dist/memory-graph.js +258 -0
- package/dist/memory-graph.js.map +1 -0
- package/dist/memory-note.d.ts +57 -0
- package/dist/memory-note.d.ts.map +1 -1
- package/dist/memory-note.js +170 -10
- package/dist/memory-note.js.map +1 -1
- package/dist/memory-secrets.d.ts +20 -0
- package/dist/memory-secrets.d.ts.map +1 -0
- package/dist/memory-secrets.js +103 -0
- package/dist/memory-secrets.js.map +1 -0
- package/dist/notes.d.ts +208 -2
- package/dist/notes.d.ts.map +1 -1
- package/dist/notes.js +722 -13
- package/dist/notes.js.map +1 -1
- package/dist/tools.d.ts +2 -2
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +464 -9
- package/dist/tools.js.map +1 -1
- package/package.json +15 -5
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { MemoryMeta, MemoryRelation } from './memory-note.js';
|
|
2
|
+
/**
|
|
3
|
+
* The memory graph, built from memories rather than stored beside them.
|
|
4
|
+
*
|
|
5
|
+
* A memory's frontmatter names the entities it is about (`about`) and the
|
|
6
|
+
* relations it asserts (`relations`). This module turns a set of memories
|
|
7
|
+
* into entities and edges, answers "is this still true" for a date, and
|
|
8
|
+
* ranks recall with the graph and recency as well as similarity. Pure: no
|
|
9
|
+
* network, no crypto, so every rule here is tested directly.
|
|
10
|
+
*
|
|
11
|
+
* Entities are names. Two mentions are the same entity when their names
|
|
12
|
+
* match ignoring case, spacing and a leading "the"; anything looser (Dana
|
|
13
|
+
* and Dana Whitfield) is a merge the AI or the person asks for, never a
|
|
14
|
+
* guess. See docs/memory-graph.md.
|
|
15
|
+
*/
|
|
16
|
+
export interface GraphMemory {
|
|
17
|
+
id: string;
|
|
18
|
+
label: string;
|
|
19
|
+
text: string;
|
|
20
|
+
meta: MemoryMeta;
|
|
21
|
+
namespace?: string;
|
|
22
|
+
updatedAt: string;
|
|
23
|
+
}
|
|
24
|
+
export interface Edge extends MemoryRelation {
|
|
25
|
+
/** The memory that asserted it. */
|
|
26
|
+
memoryId: string;
|
|
27
|
+
}
|
|
28
|
+
export interface Entity {
|
|
29
|
+
key: string;
|
|
30
|
+
/** The spelling most memories use. */
|
|
31
|
+
name: string;
|
|
32
|
+
memoryIds: Set<string>;
|
|
33
|
+
edges: Edge[];
|
|
34
|
+
}
|
|
35
|
+
export interface MemoryGraph {
|
|
36
|
+
entities: Map<string, Entity>;
|
|
37
|
+
edges: Edge[];
|
|
38
|
+
}
|
|
39
|
+
/** The matching key for a name: case, spacing and a leading article do not
|
|
40
|
+
* make a different entity. */
|
|
41
|
+
export declare function entityKey(name: string): string;
|
|
42
|
+
/**
|
|
43
|
+
* Predicates where one side holds one value at a time, so a new fact ends
|
|
44
|
+
* the old one. Which side matters:
|
|
45
|
+
* - one object per subject: a person works at one place, reports to one
|
|
46
|
+
* manager (Dana works_at Acme, then Dana works_at Initech);
|
|
47
|
+
* - one subject per object: a project has one lead (Dana leads Atlas, then
|
|
48
|
+
* Sam leads Atlas).
|
|
49
|
+
* Anything else accumulates (prefers, uses, knows).
|
|
50
|
+
*/
|
|
51
|
+
export declare const ONE_OBJECT_PER_SUBJECT: Set<string>;
|
|
52
|
+
export declare const ONE_SUBJECT_PER_OBJECT: Set<string>;
|
|
53
|
+
/** Either kind: a predicate that holds one value at a time. */
|
|
54
|
+
export declare const SINGLE_VALUED: Set<string>;
|
|
55
|
+
/** snake_case, so "Works at" and "works_at" are one predicate. */
|
|
56
|
+
export declare function normalizePredicate(p: string): string;
|
|
57
|
+
/** Whether a span held at `at`: started on or before it, ended after it. */
|
|
58
|
+
export declare function heldAt(from: string | undefined, to: string | undefined, at: number): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Whether a memory's fact held at `at`. It starts at `valid_from`, else the
|
|
61
|
+
* earliest date its relations give (a fact about "since January" learned
|
|
62
|
+
* today started in January), else when it was learned.
|
|
63
|
+
*/
|
|
64
|
+
export declare function memoryHeldAt(memory: GraphMemory, at: number): boolean;
|
|
65
|
+
export declare function buildGraph(memories: Iterable<GraphMemory>): MemoryGraph;
|
|
66
|
+
/** Entities named in a piece of text (a prompt, a query), longest names
|
|
67
|
+
* first so "Dana Whitfield" wins over "Dana". Whole words only. */
|
|
68
|
+
export declare function entitiesMentioned(graph: MemoryGraph, text: string): Entity[];
|
|
69
|
+
/** Entities one relation away from any of `from`. */
|
|
70
|
+
export declare function neighbours(graph: MemoryGraph, from: Entity[]): Entity[];
|
|
71
|
+
export interface RankInput {
|
|
72
|
+
memory: GraphMemory;
|
|
73
|
+
similarity: number;
|
|
74
|
+
}
|
|
75
|
+
/** How much the graph and recency move a similarity score. Small on
|
|
76
|
+
* purpose: similarity still decides, the graph breaks ties and pulls in
|
|
77
|
+
* facts that share an entity with the query but none of its words. */
|
|
78
|
+
export declare const DIRECT_BOOST = 0.15;
|
|
79
|
+
export declare const NEIGHBOUR_BOOST = 0.07;
|
|
80
|
+
export declare function rankMemories(graph: MemoryGraph, query: string, scored: RankInput[], opts: {
|
|
81
|
+
at?: number;
|
|
82
|
+
includeHistory?: boolean;
|
|
83
|
+
limit: number;
|
|
84
|
+
}): Array<RankInput & {
|
|
85
|
+
score: number;
|
|
86
|
+
}>;
|
|
87
|
+
/**
|
|
88
|
+
* Current edges a new relation replaces: same subject and single-valued
|
|
89
|
+
* predicate, a different object, still holding when the new one starts.
|
|
90
|
+
*/
|
|
91
|
+
export declare function supersededBy(graph: MemoryGraph, relation: MemoryRelation, at: number): Edge[];
|
|
92
|
+
/**
|
|
93
|
+
* Housekeeping findings for a tidy pass: memories linked to nothing, names
|
|
94
|
+
* that look like one entity spelled two ways, and single-valued predicates
|
|
95
|
+
* holding two values at once.
|
|
96
|
+
*/
|
|
97
|
+
export declare function graphHealth(graph: MemoryGraph, memories: GraphMemory[], at?: number): {
|
|
98
|
+
unlinked: string[];
|
|
99
|
+
possibleDuplicates: [string, string][];
|
|
100
|
+
contradictions: {
|
|
101
|
+
subject: string;
|
|
102
|
+
predicate: string;
|
|
103
|
+
objects: string[];
|
|
104
|
+
}[];
|
|
105
|
+
};
|
|
106
|
+
//# sourceMappingURL=memory-graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-graph.d.ts","sourceRoot":"","sources":["../src/memory-graph.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
/** The matching key for a name: case, spacing and a leading article do not
|
|
2
|
+
* make a different entity. */
|
|
3
|
+
export function entityKey(name) {
|
|
4
|
+
return name
|
|
5
|
+
.trim()
|
|
6
|
+
.toLowerCase()
|
|
7
|
+
.replace(/\s+/g, ' ')
|
|
8
|
+
.replace(/^the /, '');
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Predicates where one side holds one value at a time, so a new fact ends
|
|
12
|
+
* the old one. Which side matters:
|
|
13
|
+
* - one object per subject: a person works at one place, reports to one
|
|
14
|
+
* manager (Dana works_at Acme, then Dana works_at Initech);
|
|
15
|
+
* - one subject per object: a project has one lead (Dana leads Atlas, then
|
|
16
|
+
* Sam leads Atlas).
|
|
17
|
+
* Anything else accumulates (prefers, uses, knows).
|
|
18
|
+
*/
|
|
19
|
+
export const ONE_OBJECT_PER_SUBJECT = new Set([
|
|
20
|
+
'led_by',
|
|
21
|
+
'owned_by',
|
|
22
|
+
'managed_by',
|
|
23
|
+
'reports_to',
|
|
24
|
+
'works_at',
|
|
25
|
+
'lives_in',
|
|
26
|
+
'based_in',
|
|
27
|
+
'located_in',
|
|
28
|
+
'role',
|
|
29
|
+
'status',
|
|
30
|
+
'title',
|
|
31
|
+
]);
|
|
32
|
+
export const ONE_SUBJECT_PER_OBJECT = new Set(['leads', 'owns', 'manages']);
|
|
33
|
+
/** Either kind: a predicate that holds one value at a time. */
|
|
34
|
+
export const SINGLE_VALUED = new Set([...ONE_OBJECT_PER_SUBJECT, ...ONE_SUBJECT_PER_OBJECT]);
|
|
35
|
+
/** snake_case, so "Works at" and "works_at" are one predicate. */
|
|
36
|
+
export function normalizePredicate(p) {
|
|
37
|
+
return p
|
|
38
|
+
.trim()
|
|
39
|
+
.toLowerCase()
|
|
40
|
+
.replace(/[\s-]+/g, '_')
|
|
41
|
+
.replace(/[^a-z0-9_]/g, '');
|
|
42
|
+
}
|
|
43
|
+
/** A date or ISO timestamp as comparable milliseconds; bare dates are the
|
|
44
|
+
* start of that UTC day. */
|
|
45
|
+
function when(value) {
|
|
46
|
+
if (!value)
|
|
47
|
+
return null;
|
|
48
|
+
const t = Date.parse(value.length === 10 ? `${value}T00:00:00Z` : value);
|
|
49
|
+
return Number.isNaN(t) ? null : t;
|
|
50
|
+
}
|
|
51
|
+
/** Whether a span held at `at`: started on or before it, ended after it. */
|
|
52
|
+
export function heldAt(from, to, at) {
|
|
53
|
+
const start = when(from);
|
|
54
|
+
const end = when(to);
|
|
55
|
+
if (start !== null && start > at)
|
|
56
|
+
return false;
|
|
57
|
+
if (end !== null && end <= at)
|
|
58
|
+
return false;
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Whether a memory's fact held at `at`. It starts at `valid_from`, else the
|
|
63
|
+
* earliest date its relations give (a fact about "since January" learned
|
|
64
|
+
* today started in January), else when it was learned.
|
|
65
|
+
*/
|
|
66
|
+
export function memoryHeldAt(memory, at) {
|
|
67
|
+
const relationStarts = (memory.meta.relations ?? [])
|
|
68
|
+
.map((r) => r.from)
|
|
69
|
+
.filter((f) => !!f && when(f) !== null)
|
|
70
|
+
.sort((a, b) => when(a) - when(b));
|
|
71
|
+
const start = memory.meta.validFrom ?? relationStarts[0] ?? memory.meta.created;
|
|
72
|
+
return heldAt(start, memory.meta.validTo, at);
|
|
73
|
+
}
|
|
74
|
+
export function buildGraph(memories) {
|
|
75
|
+
const entities = new Map();
|
|
76
|
+
const spellings = new Map();
|
|
77
|
+
const edges = [];
|
|
78
|
+
const touch = (name, memoryId) => {
|
|
79
|
+
const key = entityKey(name);
|
|
80
|
+
let entity = entities.get(key);
|
|
81
|
+
if (!entity) {
|
|
82
|
+
entity = { key, name: name.trim(), memoryIds: new Set(), edges: [] };
|
|
83
|
+
entities.set(key, entity);
|
|
84
|
+
spellings.set(key, new Map());
|
|
85
|
+
}
|
|
86
|
+
entity.memoryIds.add(memoryId);
|
|
87
|
+
const counts = spellings.get(key);
|
|
88
|
+
counts.set(name.trim(), (counts.get(name.trim()) ?? 0) + 1);
|
|
89
|
+
return entity;
|
|
90
|
+
};
|
|
91
|
+
for (const memory of memories) {
|
|
92
|
+
for (const name of memory.meta.about ?? [])
|
|
93
|
+
touch(name, memory.id);
|
|
94
|
+
for (const relation of memory.meta.relations ?? []) {
|
|
95
|
+
const edge = { ...relation, p: normalizePredicate(relation.p), memoryId: memory.id };
|
|
96
|
+
edges.push(edge);
|
|
97
|
+
touch(relation.s, memory.id).edges.push(edge);
|
|
98
|
+
// The object is an entity only if something else names it as one;
|
|
99
|
+
// "async standups" as the object of prefers stays a literal.
|
|
100
|
+
const objectKey = entityKey(relation.o);
|
|
101
|
+
if (entities.has(objectKey) || isEntityLike(relation.o)) {
|
|
102
|
+
touch(relation.o, memory.id).edges.push(edge);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
for (const [key, counts] of spellings) {
|
|
107
|
+
const [best] = [...counts.entries()].sort((a, b) => b[1] - a[1]);
|
|
108
|
+
if (best)
|
|
109
|
+
entities.get(key).name = best[0];
|
|
110
|
+
}
|
|
111
|
+
return { entities, edges };
|
|
112
|
+
}
|
|
113
|
+
/** A capitalised name reads as an entity (Atlas, Dana Whitfield, Fly.io);
|
|
114
|
+
* a lower-case phrase reads as a value (async standups, dark mode). */
|
|
115
|
+
function isEntityLike(value) {
|
|
116
|
+
return /^[A-Z0-9]/.test(value.trim());
|
|
117
|
+
}
|
|
118
|
+
/** Entities named in a piece of text (a prompt, a query), longest names
|
|
119
|
+
* first so "Dana Whitfield" wins over "Dana". Whole words only. */
|
|
120
|
+
export function entitiesMentioned(graph, text) {
|
|
121
|
+
// Dots survive only inside a name (Fly.io); a full stop after a word
|
|
122
|
+
// would otherwise hide the word.
|
|
123
|
+
const haystack = ` ${text
|
|
124
|
+
.toLowerCase()
|
|
125
|
+
.replace(/[^a-z0-9.\s]/g, ' ')
|
|
126
|
+
.replace(/\.(?![a-z0-9])|(?<![a-z0-9])\./g, ' ')
|
|
127
|
+
.replace(/\s+/g, ' ')} `;
|
|
128
|
+
const found = [];
|
|
129
|
+
const byLength = [...graph.entities.values()].sort((a, b) => b.key.length - a.key.length);
|
|
130
|
+
let remaining = haystack;
|
|
131
|
+
for (const entity of byLength) {
|
|
132
|
+
const needle = ` ${entity.key} `;
|
|
133
|
+
if (entity.key.length < 2 || !remaining.includes(needle))
|
|
134
|
+
continue;
|
|
135
|
+
found.push(entity);
|
|
136
|
+
remaining = remaining.split(needle).join(' ');
|
|
137
|
+
}
|
|
138
|
+
return found;
|
|
139
|
+
}
|
|
140
|
+
/** Entities one relation away from any of `from`. */
|
|
141
|
+
export function neighbours(graph, from) {
|
|
142
|
+
const seen = new Set(from.map((e) => e.key));
|
|
143
|
+
const result = [];
|
|
144
|
+
for (const entity of from) {
|
|
145
|
+
for (const edge of entity.edges) {
|
|
146
|
+
for (const end of [edge.s, edge.o]) {
|
|
147
|
+
const key = entityKey(end);
|
|
148
|
+
const other = graph.entities.get(key);
|
|
149
|
+
if (other && !seen.has(key)) {
|
|
150
|
+
seen.add(key);
|
|
151
|
+
result.push(other);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return result;
|
|
157
|
+
}
|
|
158
|
+
/** How much the graph and recency move a similarity score. Small on
|
|
159
|
+
* purpose: similarity still decides, the graph breaks ties and pulls in
|
|
160
|
+
* facts that share an entity with the query but none of its words. */
|
|
161
|
+
export const DIRECT_BOOST = 0.15;
|
|
162
|
+
export const NEIGHBOUR_BOOST = 0.07;
|
|
163
|
+
const RECENCY_WEIGHT = 0.08;
|
|
164
|
+
const RECENCY_HORIZON_DAYS = 365;
|
|
165
|
+
export function rankMemories(graph, query, scored, opts) {
|
|
166
|
+
const at = opts.at ?? Date.now();
|
|
167
|
+
const direct = entitiesMentioned(graph, query);
|
|
168
|
+
const near = neighbours(graph, direct);
|
|
169
|
+
const directIds = new Set(direct.flatMap((e) => [...e.memoryIds]));
|
|
170
|
+
const nearIds = new Set(near.flatMap((e) => [...e.memoryIds]));
|
|
171
|
+
return scored
|
|
172
|
+
.filter(({ memory }) => opts.includeHistory || memoryHeldAt(memory, at))
|
|
173
|
+
.map((item) => {
|
|
174
|
+
let score = item.similarity;
|
|
175
|
+
if (directIds.has(item.memory.id))
|
|
176
|
+
score += DIRECT_BOOST;
|
|
177
|
+
else if (nearIds.has(item.memory.id))
|
|
178
|
+
score += NEIGHBOUR_BOOST;
|
|
179
|
+
const updated = Date.parse(item.memory.updatedAt);
|
|
180
|
+
if (!Number.isNaN(updated)) {
|
|
181
|
+
const ageDays = Math.max(0, (at - updated) / 86_400_000);
|
|
182
|
+
score -= RECENCY_WEIGHT * Math.min(1, ageDays / RECENCY_HORIZON_DAYS);
|
|
183
|
+
}
|
|
184
|
+
return { ...item, score };
|
|
185
|
+
})
|
|
186
|
+
.sort((a, b) => b.score - a.score)
|
|
187
|
+
.slice(0, opts.limit);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Current edges a new relation replaces: same subject and single-valued
|
|
191
|
+
* predicate, a different object, still holding when the new one starts.
|
|
192
|
+
*/
|
|
193
|
+
export function supersededBy(graph, relation, at) {
|
|
194
|
+
const p = normalizePredicate(relation.p);
|
|
195
|
+
const s = entityKey(relation.s);
|
|
196
|
+
const o = entityKey(relation.o);
|
|
197
|
+
const bySubject = ONE_OBJECT_PER_SUBJECT.has(p);
|
|
198
|
+
const byObject = ONE_SUBJECT_PER_OBJECT.has(p);
|
|
199
|
+
if (!bySubject && !byObject)
|
|
200
|
+
return [];
|
|
201
|
+
return graph.edges.filter((edge) => {
|
|
202
|
+
if (edge.p !== p || !heldAt(edge.from, edge.to, at))
|
|
203
|
+
return false;
|
|
204
|
+
const es = entityKey(edge.s);
|
|
205
|
+
const eo = entityKey(edge.o);
|
|
206
|
+
if (es === s && eo === o)
|
|
207
|
+
return false;
|
|
208
|
+
return bySubject ? es === s : eo === o;
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Housekeeping findings for a tidy pass: memories linked to nothing, names
|
|
213
|
+
* that look like one entity spelled two ways, and single-valued predicates
|
|
214
|
+
* holding two values at once.
|
|
215
|
+
*/
|
|
216
|
+
export function graphHealth(graph, memories, at = Date.now()) {
|
|
217
|
+
const unlinked = memories
|
|
218
|
+
.filter((m) => !(m.meta.about?.length || m.meta.relations?.length))
|
|
219
|
+
.map((m) => m.id);
|
|
220
|
+
const names = [...graph.entities.values()];
|
|
221
|
+
const possibleDuplicates = [];
|
|
222
|
+
for (let i = 0; i < names.length; i++) {
|
|
223
|
+
for (let j = i + 1; j < names.length; j++) {
|
|
224
|
+
const a = names[i].key;
|
|
225
|
+
const b = names[j].key;
|
|
226
|
+
const [short, long] = a.length <= b.length ? [a, b] : [b, a];
|
|
227
|
+
// "dana" and "dana whitfield": one name is the first word(s) of the other.
|
|
228
|
+
if (short.length >= 3 && long.startsWith(`${short} `)) {
|
|
229
|
+
possibleDuplicates.push([names[i].name, names[j].name]);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
const contradictions = [];
|
|
234
|
+
// Keyed on the side that must be unique: the subject for works_at, the
|
|
235
|
+
// object for leads. `values` are the other side.
|
|
236
|
+
const current = new Map();
|
|
237
|
+
for (const edge of graph.edges) {
|
|
238
|
+
if (!SINGLE_VALUED.has(edge.p) || !heldAt(edge.from, edge.to, at))
|
|
239
|
+
continue;
|
|
240
|
+
const bySubject = ONE_OBJECT_PER_SUBJECT.has(edge.p);
|
|
241
|
+
const anchor = bySubject ? edge.s : edge.o;
|
|
242
|
+
const key = `${entityKey(anchor)}|${edge.p}`;
|
|
243
|
+
if (!current.has(key))
|
|
244
|
+
current.set(key, { anchor, predicate: edge.p, values: new Set() });
|
|
245
|
+
current.get(key).values.add(bySubject ? edge.o : edge.s);
|
|
246
|
+
}
|
|
247
|
+
for (const [key, { anchor, predicate, values }] of current) {
|
|
248
|
+
if (values.size < 2)
|
|
249
|
+
continue;
|
|
250
|
+
contradictions.push({
|
|
251
|
+
subject: graph.entities.get(key.split('|')[0])?.name ?? anchor,
|
|
252
|
+
predicate,
|
|
253
|
+
objects: [...values],
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
return { unlinked, possibleDuplicates, contradictions };
|
|
257
|
+
}
|
|
258
|
+
//# sourceMappingURL=memory-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-graph.js","sourceRoot":"","sources":["../src/memory-graph.ts"],"names":[],"mappings":"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"}
|
package/dist/memory-note.d.ts
CHANGED
|
@@ -14,10 +14,51 @@ export interface MemoryMeta {
|
|
|
14
14
|
confidence?: string;
|
|
15
15
|
/** ISO timestamp of the first write; never overwritten by later updates. */
|
|
16
16
|
created?: string;
|
|
17
|
+
/**
|
|
18
|
+
* `html` when the fact was written in the app's rich editor, so the body
|
|
19
|
+
* after the frontmatter is TipTap HTML rather than plain text. Absent
|
|
20
|
+
* means plain text, which is what the connector always writes: AI tools
|
|
21
|
+
* read and write text, and the app renders it as paragraphs.
|
|
22
|
+
*/
|
|
23
|
+
format?: 'html';
|
|
24
|
+
/**
|
|
25
|
+
* The graph: the entities this fact is about (people, projects, places,
|
|
26
|
+
* tools), by name. Names are matched case-insensitively across memories,
|
|
27
|
+
* so every memory that says "Atlas" is about the same Atlas.
|
|
28
|
+
*/
|
|
29
|
+
about?: string[];
|
|
30
|
+
/** Typed links the fact asserts, e.g. Sam leads Atlas. A relation lives on
|
|
31
|
+
* the memory that asserted it, so every edge has a source to open, check
|
|
32
|
+
* or delete. */
|
|
33
|
+
relations?: MemoryRelation[];
|
|
34
|
+
/** When the fact became true (YYYY-MM-DD or ISO). Absent: when it was
|
|
35
|
+
* learned (`created`). */
|
|
36
|
+
validFrom?: string;
|
|
37
|
+
/** When the fact stopped being true. Facts are ended, never deleted, when
|
|
38
|
+
* they are superseded, so history stays answerable. */
|
|
39
|
+
validTo?: string;
|
|
40
|
+
/** The memory that replaced this one, when one did. */
|
|
41
|
+
supersededBy?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* One edge: subject, predicate, object. `p` is a short verb phrase in
|
|
45
|
+
* snake_case ("leads", "works_at", "prefers"); `o` is an entity name or a
|
|
46
|
+
* literal ("async standups"). `from` and `to` bound when it held.
|
|
47
|
+
*/
|
|
48
|
+
export interface MemoryRelation {
|
|
49
|
+
s: string;
|
|
50
|
+
p: string;
|
|
51
|
+
o: string;
|
|
52
|
+
from?: string;
|
|
53
|
+
to?: string;
|
|
17
54
|
}
|
|
18
55
|
export interface ParsedMemoryNote {
|
|
56
|
+
/** The fact as plain text: what AI tools read, what gets embedded. For an
|
|
57
|
+
* HTML body, its text with line breaks and list markers kept. */
|
|
19
58
|
fact: string;
|
|
20
59
|
meta: MemoryMeta;
|
|
60
|
+
/** The body as written, when `meta.format` is `html`. */
|
|
61
|
+
html?: string;
|
|
21
62
|
}
|
|
22
63
|
/**
|
|
23
64
|
* The note type a memory is written as.
|
|
@@ -36,6 +77,20 @@ export declare const MEMORY_NOTE_TYPE = "memory";
|
|
|
36
77
|
* (or a test) can build a legacy body and confirm it still reads.
|
|
37
78
|
*/
|
|
38
79
|
export declare function toCodeEnvelope(body: string): string;
|
|
80
|
+
/**
|
|
81
|
+
* A rich fact as text an AI can read: one line per paragraph, heading or
|
|
82
|
+
* list item, list items marked, code and inline marks reduced to their text.
|
|
83
|
+
* Entities are decoded, so a fact that talks about `<p>` tags reads back as
|
|
84
|
+
* exactly that.
|
|
85
|
+
*/
|
|
86
|
+
export declare function memoryHtmlToText(html: string): string;
|
|
87
|
+
/**
|
|
88
|
+
* Plain text as the rich editor's HTML: a paragraph per blank-line-separated
|
|
89
|
+
* block, single line breaks kept, everything escaped. Used to open a
|
|
90
|
+
* connector-written (plain) memory in the editor.
|
|
91
|
+
*/
|
|
92
|
+
export declare function memoryTextToHtml(text: string): string;
|
|
93
|
+
export declare function looksLikeHtml(fact: string): boolean;
|
|
39
94
|
/**
|
|
40
95
|
* Split a decrypted note body into its fact and metadata.
|
|
41
96
|
*
|
|
@@ -50,6 +105,8 @@ export declare function parseMemoryNote(decryptedContent: string): ParsedMemoryN
|
|
|
50
105
|
* there is no metadata to record.
|
|
51
106
|
*/
|
|
52
107
|
export declare function serializeMemoryBody(fact: string, meta: MemoryMeta): string;
|
|
108
|
+
/** The app's rich editor output, marked as HTML. */
|
|
109
|
+
export declare function serializeMemoryHtml(html: string, meta: MemoryMeta): string;
|
|
53
110
|
/**
|
|
54
111
|
* Metadata for an update: named keys win, unnamed keys carry forward, and
|
|
55
112
|
* `created` is pinned to the first write so an in-place dedupe merge cannot
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-note.d.ts","sourceRoot":"","sources":["../src/memory-note.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"memory-note.d.ts","sourceRoot":"","sources":["../src/memory-note.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IACzB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB;;qBAEiB;IACjB,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC;IAC7B;+BAC2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;4DACwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,gBAAgB;IAC/B;sEACkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,CAAC;IACjB,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAqDD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,WAAW,CAAC;AAEzC;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAsED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAgBrD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMrD;AAYD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD;AASD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,gBAAgB,EAAE,MAAM,GAAG,gBAAgB,CAgC1E;AAUD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,CAO1E;AAED,oDAAoD;AACpD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,CAE1E;AAkCD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,GAAG,UAAU,CAgB/E"}
|