@pcircle/memesh 4.2.10 → 4.3.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.de.md +14 -13
- package/README.es.md +14 -13
- package/README.fr.md +14 -13
- package/README.ja.md +14 -13
- package/README.ko.md +14 -13
- package/README.md +15 -14
- package/README.pt.md +14 -13
- package/README.th.md +15 -14
- package/README.vi.md +14 -13
- package/README.zh-CN.md +12 -11
- package/README.zh-TW.md +12 -11
- package/dashboard/dist/index.html +8 -8
- package/dist/cli/view.d.ts.map +1 -1
- package/dist/cli/view.js +6 -0
- package/dist/cli/view.js.map +1 -1
- package/dist/core/config.d.ts +14 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +25 -5
- package/dist/core/config.js.map +1 -1
- package/dist/core/doctor.d.ts +3 -0
- package/dist/core/doctor.d.ts.map +1 -1
- package/dist/core/doctor.js +84 -5
- package/dist/core/doctor.js.map +1 -1
- package/dist/core/dreamer.d.ts.map +1 -1
- package/dist/core/dreamer.js +26 -15
- package/dist/core/dreamer.js.map +1 -1
- package/dist/core/embedder.d.ts +6 -1
- package/dist/core/embedder.d.ts.map +1 -1
- package/dist/core/embedder.js +33 -9
- package/dist/core/embedder.js.map +1 -1
- package/dist/core/llm-validator.d.ts.map +1 -1
- package/dist/core/llm-validator.js +6 -0
- package/dist/core/llm-validator.js.map +1 -1
- package/dist/core/memory-tool.d.ts +37 -0
- package/dist/core/memory-tool.d.ts.map +1 -0
- package/dist/core/memory-tool.js +371 -0
- package/dist/core/memory-tool.js.map +1 -0
- package/dist/core/operations.d.ts +11 -5
- package/dist/core/operations.d.ts.map +1 -1
- package/dist/core/operations.js +91 -34
- package/dist/core/operations.js.map +1 -1
- package/dist/core/prompt-safety.d.ts.map +1 -1
- package/dist/core/prompt-safety.js.map +1 -1
- package/dist/core/schema-export.d.ts.map +1 -1
- package/dist/core/schema-export.js +19 -34
- package/dist/core/schema-export.js.map +1 -1
- package/dist/core/types.d.ts +5 -12
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +4 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/verifier.d.ts +3 -0
- package/dist/core/verifier.d.ts.map +1 -1
- package/dist/core/verifier.js +27 -11
- package/dist/core/verifier.js.map +1 -1
- package/dist/db.d.ts +11 -0
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +174 -35
- package/dist/db.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/knowledge-graph.d.ts +1 -2
- package/dist/knowledge-graph.d.ts.map +1 -1
- package/dist/knowledge-graph.js +94 -44
- package/dist/knowledge-graph.js.map +1 -1
- package/dist/skills-manifest.json +14 -15
- package/dist/storage/conflicts.d.ts +1 -4
- package/dist/storage/conflicts.d.ts.map +1 -1
- package/dist/storage/conflicts.js +2 -5
- package/dist/storage/conflicts.js.map +1 -1
- package/dist/storage/fts-index.d.ts +11 -0
- package/dist/storage/fts-index.d.ts.map +1 -1
- package/dist/storage/fts-index.js +58 -2
- package/dist/storage/fts-index.js.map +1 -1
- package/dist/transports/cli/cli.d.ts.map +1 -1
- package/dist/transports/cli/cli.js +96 -50
- package/dist/transports/cli/cli.js.map +1 -1
- package/dist/transports/http/retired-routes.d.ts +2 -0
- package/dist/transports/http/retired-routes.d.ts.map +1 -0
- package/dist/transports/http/retired-routes.js +4 -0
- package/dist/transports/http/retired-routes.js.map +1 -0
- package/dist/transports/http/server.d.ts.map +1 -1
- package/dist/transports/http/server.js +6 -3
- package/dist/transports/http/server.js.map +1 -1
- package/dist/transports/mcp/handlers.d.ts +4 -25
- package/dist/transports/mcp/handlers.d.ts.map +1 -1
- package/dist/transports/mcp/handlers.js +8 -28
- package/dist/transports/mcp/handlers.js.map +1 -1
- package/dist/transports/schemas.d.ts +0 -5
- package/dist/transports/schemas.d.ts.map +1 -1
- package/dist/transports/schemas.js +0 -5
- package/dist/transports/schemas.js.map +1 -1
- package/package.json +35 -6
- package/scripts/hooks/_generated/fts-index.js +58 -2
- package/scripts/hooks/_shared.js +238 -4
- package/scripts/hooks/pre-compact.js +14 -3
- package/scripts/hooks/pre-edit-recall.js +76 -9
- package/skills/memesh/SKILL.md +11 -4
- package/skills/memesh-review/SKILL.md +7 -5
- package/dist/core/consolidator.d.ts +0 -3
- package/dist/core/consolidator.d.ts.map +0 -1
- package/dist/core/consolidator.js +0 -108
- package/dist/core/consolidator.js.map +0 -1
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
import { getDatabase } from '../db.js';
|
|
2
|
+
import { KnowledgeGraph } from '../knowledge-graph.js';
|
|
3
|
+
import { removeFromFts, insertFtsRow } from '../storage/fts-index.js';
|
|
4
|
+
export const MEMORY_ROOT = '/memories';
|
|
5
|
+
const NAMESPACES = ['personal', 'team', 'global'];
|
|
6
|
+
const FILE_SUFFIX = '.md';
|
|
7
|
+
const MAX_FILE_BYTES = 256 * 1024;
|
|
8
|
+
const MAX_VIEW_CHARS = 16_000;
|
|
9
|
+
const ok = (content) => ({ content, isError: false });
|
|
10
|
+
const err = (content) => ({ content, isError: true });
|
|
11
|
+
function encodeName(name) {
|
|
12
|
+
return name.replace(/%/g, '%25').replace(/\//g, '%2F').replace(/\\/g, '%5C');
|
|
13
|
+
}
|
|
14
|
+
function decodeName(segment) {
|
|
15
|
+
return segment
|
|
16
|
+
.replace(/%2F/gi, '/')
|
|
17
|
+
.replace(/%5C/gi, '\\')
|
|
18
|
+
.replace(/%25/g, '%');
|
|
19
|
+
}
|
|
20
|
+
function parsePath(raw) {
|
|
21
|
+
if (typeof raw !== 'string' || raw.length === 0) {
|
|
22
|
+
return err('Error: `path` must be a non-empty string.');
|
|
23
|
+
}
|
|
24
|
+
if (raw.includes('\0')) {
|
|
25
|
+
return err('Error: `path` may not contain a NUL byte.');
|
|
26
|
+
}
|
|
27
|
+
if (raw !== MEMORY_ROOT && !raw.startsWith(`${MEMORY_ROOT}/`)) {
|
|
28
|
+
return err(`Error: paths must be under ${MEMORY_ROOT}. The path ${raw} is outside it.`);
|
|
29
|
+
}
|
|
30
|
+
const rest = raw.slice(MEMORY_ROOT.length).replace(/^\//, '');
|
|
31
|
+
if (rest === '')
|
|
32
|
+
return { kind: 'root' };
|
|
33
|
+
const segments = rest.split('/');
|
|
34
|
+
for (const segment of segments) {
|
|
35
|
+
if (segment === '' || segment === '.' || segment === '..') {
|
|
36
|
+
return err(`Error: the path ${raw} contains a traversal or empty segment and was refused.`);
|
|
37
|
+
}
|
|
38
|
+
if (/%2e%2e/i.test(segment) || segment.includes('\\')) {
|
|
39
|
+
return err(`Error: the path ${raw} contains a traversal sequence and was refused.`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (segments.length > 2) {
|
|
43
|
+
return err(`Error: ${MEMORY_ROOT} is two levels deep — ${MEMORY_ROOT}/<namespace>/<memory>${FILE_SUFFIX}. ` +
|
|
44
|
+
`The path ${raw} is deeper than that.`);
|
|
45
|
+
}
|
|
46
|
+
const namespace = segments[0];
|
|
47
|
+
if (!NAMESPACES.includes(namespace)) {
|
|
48
|
+
return err(`Error: "${namespace}" is not a memory namespace. Use one of: ${NAMESPACES.join(', ')}.`);
|
|
49
|
+
}
|
|
50
|
+
if (segments.length === 1) {
|
|
51
|
+
return { kind: 'namespace', namespace: namespace };
|
|
52
|
+
}
|
|
53
|
+
const file = segments[1];
|
|
54
|
+
if (!file.endsWith(FILE_SUFFIX)) {
|
|
55
|
+
return err(`Error: memory files end in ${FILE_SUFFIX}. The path ${raw} does not.`);
|
|
56
|
+
}
|
|
57
|
+
const name = decodeName(file.slice(0, -FILE_SUFFIX.length));
|
|
58
|
+
if (name === '') {
|
|
59
|
+
return err(`Error: the path ${raw} names an empty memory.`);
|
|
60
|
+
}
|
|
61
|
+
return { kind: 'entity', namespace: namespace, name };
|
|
62
|
+
}
|
|
63
|
+
const isResult = (v) => 'content' in v;
|
|
64
|
+
function entityPath(namespace, name) {
|
|
65
|
+
return `${MEMORY_ROOT}/${namespace}/${encodeName(name)}${FILE_SUFFIX}`;
|
|
66
|
+
}
|
|
67
|
+
function renderBody(entity) {
|
|
68
|
+
return entity.observations.join('\n');
|
|
69
|
+
}
|
|
70
|
+
function lineOwners(observations) {
|
|
71
|
+
const owners = [];
|
|
72
|
+
observations.forEach((observation, index) => {
|
|
73
|
+
const span = observation.split('\n').length;
|
|
74
|
+
for (let i = 0; i < span; i++)
|
|
75
|
+
owners.push(index);
|
|
76
|
+
});
|
|
77
|
+
return owners;
|
|
78
|
+
}
|
|
79
|
+
function withLineNumbers(body, from = 1) {
|
|
80
|
+
if (body === '')
|
|
81
|
+
return '';
|
|
82
|
+
return body
|
|
83
|
+
.split('\n')
|
|
84
|
+
.map((line, i) => `${String(from + i).padStart(6, ' ')}\t${line}`)
|
|
85
|
+
.join('\n');
|
|
86
|
+
}
|
|
87
|
+
function humanSize(bytes) {
|
|
88
|
+
if (bytes < 1024)
|
|
89
|
+
return `${bytes}`;
|
|
90
|
+
return `${(bytes / 1024).toFixed(1)}K`;
|
|
91
|
+
}
|
|
92
|
+
function graph() {
|
|
93
|
+
return new KnowledgeGraph(getDatabase());
|
|
94
|
+
}
|
|
95
|
+
function listNamespace(namespace) {
|
|
96
|
+
return getDatabase()
|
|
97
|
+
.prepare(`SELECT e.name AS name,
|
|
98
|
+
e.type AS type,
|
|
99
|
+
COALESCE(SUM(LENGTH(o.content)) + MAX(COUNT(o.id) - 1, 0), 0) AS bytes
|
|
100
|
+
FROM entities e
|
|
101
|
+
LEFT JOIN observations o ON o.entity_id = e.id
|
|
102
|
+
WHERE e.status = 'active' AND e.namespace = ?
|
|
103
|
+
GROUP BY e.id
|
|
104
|
+
ORDER BY e.id DESC`)
|
|
105
|
+
.all(namespace);
|
|
106
|
+
}
|
|
107
|
+
function countNamespace(namespace) {
|
|
108
|
+
return getDatabase()
|
|
109
|
+
.prepare("SELECT COUNT(*) AS n FROM entities WHERE status = 'active' AND namespace = ?")
|
|
110
|
+
.get(namespace).n;
|
|
111
|
+
}
|
|
112
|
+
function tagsOf(name) {
|
|
113
|
+
return getDatabase()
|
|
114
|
+
.prepare('SELECT tag FROM tags WHERE entity_id = (SELECT id FROM entities WHERE name = ?)')
|
|
115
|
+
.all(name).map((t) => t.tag);
|
|
116
|
+
}
|
|
117
|
+
function findEntity(kg, namespace, name) {
|
|
118
|
+
const entity = kg.getEntity(name);
|
|
119
|
+
if (!entity || entity.namespace !== namespace)
|
|
120
|
+
return null;
|
|
121
|
+
return entity;
|
|
122
|
+
}
|
|
123
|
+
function rewriteObservations(kg, entity, observations) {
|
|
124
|
+
getDatabase().transaction(() => {
|
|
125
|
+
kg.clearEntityData(entity.name);
|
|
126
|
+
kg.createEntity(entity.name, entity.type, {
|
|
127
|
+
observations,
|
|
128
|
+
tags: entity.tags,
|
|
129
|
+
namespace: entity.namespace,
|
|
130
|
+
});
|
|
131
|
+
})();
|
|
132
|
+
}
|
|
133
|
+
function tooLarge(body, path) {
|
|
134
|
+
const bytes = Buffer.byteLength(body, 'utf8');
|
|
135
|
+
if (bytes <= MAX_FILE_BYTES)
|
|
136
|
+
return null;
|
|
137
|
+
return err(`Error: ${path} would be ${humanSize(bytes)}, over the ${humanSize(MAX_FILE_BYTES)} ` +
|
|
138
|
+
`limit for one memory. Split it across several memories.`);
|
|
139
|
+
}
|
|
140
|
+
function viewRoot() {
|
|
141
|
+
const lines = [`${MEMORY_ROOT}`];
|
|
142
|
+
for (const namespace of NAMESPACES) {
|
|
143
|
+
lines.push(`${MEMORY_ROOT}/${namespace}\t${countNamespace(namespace)} memories`);
|
|
144
|
+
}
|
|
145
|
+
return ok(`Here're the files and directories up to 2 levels deep in ${MEMORY_ROOT}, ` +
|
|
146
|
+
`excluding hidden items and node_modules:\n${lines.join('\n')}`);
|
|
147
|
+
}
|
|
148
|
+
function viewNamespace(namespace) {
|
|
149
|
+
const lines = listNamespace(namespace).map((row) => {
|
|
150
|
+
const tags = tagsOf(row.name);
|
|
151
|
+
const suffix = tags.length > 0 ? ` tags: ${tags.join(', ')}` : '';
|
|
152
|
+
return `${humanSize(row.bytes)}\t${entityPath(namespace, row.name)}\t(${row.type})${suffix}`;
|
|
153
|
+
});
|
|
154
|
+
return ok(`Here're the files and directories up to 2 levels deep in ${MEMORY_ROOT}/${namespace}, ` +
|
|
155
|
+
`excluding hidden items and node_modules:\n` +
|
|
156
|
+
[`${MEMORY_ROOT}/${namespace}`, ...lines].join('\n'));
|
|
157
|
+
}
|
|
158
|
+
function viewEntity(namespace, name, range, path) {
|
|
159
|
+
const entity = findEntity(graph(), namespace, name);
|
|
160
|
+
if (!entity) {
|
|
161
|
+
return err(`The path ${path} does not exist. Please provide a valid path.`);
|
|
162
|
+
}
|
|
163
|
+
const body = renderBody(entity);
|
|
164
|
+
const lines = body === '' ? [] : body.split('\n');
|
|
165
|
+
if (range === undefined) {
|
|
166
|
+
if (body.length > MAX_VIEW_CHARS) {
|
|
167
|
+
const kept = [];
|
|
168
|
+
let used = 0;
|
|
169
|
+
for (const line of lines) {
|
|
170
|
+
if (used + line.length + 1 > MAX_VIEW_CHARS)
|
|
171
|
+
break;
|
|
172
|
+
kept.push(line);
|
|
173
|
+
used += line.length + 1;
|
|
174
|
+
}
|
|
175
|
+
return ok(`Here's the content of ${path} with line numbers:\n${withLineNumbers(kept.join('\n'))}\n` +
|
|
176
|
+
`\n[truncated at ${kept.length} of ${lines.length} lines — ` +
|
|
177
|
+
`use view_range to read from line ${kept.length + 1}]`);
|
|
178
|
+
}
|
|
179
|
+
return ok(`Here's the content of ${path} with line numbers:\n${withLineNumbers(body)}`);
|
|
180
|
+
}
|
|
181
|
+
if (!Array.isArray(range) || range.length !== 2 || !range.every((n) => Number.isInteger(n))) {
|
|
182
|
+
return err('Error: `view_range` must be a two-element array of integers, [start, end].');
|
|
183
|
+
}
|
|
184
|
+
const [start, rawEnd] = range;
|
|
185
|
+
const end = rawEnd === -1 ? lines.length : rawEnd;
|
|
186
|
+
if (start < 1 || start > Math.max(lines.length, 1) || end < start) {
|
|
187
|
+
return err(`Error: Invalid \`view_range\`: [${start}, ${rawEnd}]. ` +
|
|
188
|
+
`It should be within the range of lines of the file: [1, ${lines.length}]`);
|
|
189
|
+
}
|
|
190
|
+
const slice = lines.slice(start - 1, end).join('\n');
|
|
191
|
+
return ok(`Here's the content of ${path} with line numbers:\n${withLineNumbers(slice, start)}`);
|
|
192
|
+
}
|
|
193
|
+
function createEntityFile(namespace, name, fileText, path) {
|
|
194
|
+
if (typeof fileText !== 'string') {
|
|
195
|
+
return err('Error: `file_text` must be a string.');
|
|
196
|
+
}
|
|
197
|
+
const kg = graph();
|
|
198
|
+
const existing = findEntity(kg, namespace, name);
|
|
199
|
+
const oversize = tooLarge(fileText, path);
|
|
200
|
+
if (oversize)
|
|
201
|
+
return oversize;
|
|
202
|
+
const observations = fileText === '' ? [] : fileText.split('\n');
|
|
203
|
+
if (existing) {
|
|
204
|
+
rewriteObservations(kg, existing, observations);
|
|
205
|
+
return ok(`File created successfully at: ${path}`);
|
|
206
|
+
}
|
|
207
|
+
kg.createEntity(name, 'note', { observations, namespace });
|
|
208
|
+
return ok(`File created successfully at: ${path}`);
|
|
209
|
+
}
|
|
210
|
+
function strReplace(namespace, name, oldStr, newStr, path) {
|
|
211
|
+
if (typeof oldStr !== 'string' || oldStr === '') {
|
|
212
|
+
return err('Error: `old_str` must be a non-empty string.');
|
|
213
|
+
}
|
|
214
|
+
if (newStr !== undefined && typeof newStr !== 'string') {
|
|
215
|
+
return err('Error: `new_str` must be a string when present.');
|
|
216
|
+
}
|
|
217
|
+
const kg = graph();
|
|
218
|
+
const entity = findEntity(kg, namespace, name);
|
|
219
|
+
if (!entity) {
|
|
220
|
+
return err(`Error: The path ${path} does not exist. Please provide a valid path.`);
|
|
221
|
+
}
|
|
222
|
+
const body = renderBody(entity);
|
|
223
|
+
const first = body.indexOf(oldStr);
|
|
224
|
+
if (first === -1) {
|
|
225
|
+
return err(`No replacement was performed, old_str \`${oldStr}\` did not appear verbatim in ${path}.`);
|
|
226
|
+
}
|
|
227
|
+
if (body.indexOf(oldStr, first + 1) !== -1) {
|
|
228
|
+
const lines = [];
|
|
229
|
+
let at = first;
|
|
230
|
+
while (at !== -1) {
|
|
231
|
+
lines.push(body.slice(0, at).split('\n').length);
|
|
232
|
+
at = body.indexOf(oldStr, at + 1);
|
|
233
|
+
}
|
|
234
|
+
return err(`No replacement was performed. Multiple occurrences of old_str \`${oldStr}\` ` +
|
|
235
|
+
`in lines: ${lines.join(', ')}. Please ensure it is unique`);
|
|
236
|
+
}
|
|
237
|
+
const replaced = body.slice(0, first) + (newStr ?? '') + body.slice(first + oldStr.length);
|
|
238
|
+
const oversize = tooLarge(replaced, path);
|
|
239
|
+
if (oversize)
|
|
240
|
+
return oversize;
|
|
241
|
+
const observations = replaced === '' ? [] : replaced.split('\n');
|
|
242
|
+
rewriteObservations(kg, entity, observations);
|
|
243
|
+
const at = replaced.slice(0, first).split('\n').length;
|
|
244
|
+
const from = Math.max(1, at - 2);
|
|
245
|
+
const snippet = replaced.split('\n').slice(from - 1, at + 2).join('\n');
|
|
246
|
+
return ok(`The memory file has been edited. Here's a snippet of ${path} with line numbers:\n` +
|
|
247
|
+
withLineNumbers(snippet, from));
|
|
248
|
+
}
|
|
249
|
+
function insertLine(namespace, name, atLine, text, path) {
|
|
250
|
+
if (!Number.isInteger(atLine)) {
|
|
251
|
+
return err('Error: `insert_line` must be an integer.');
|
|
252
|
+
}
|
|
253
|
+
if (typeof text !== 'string') {
|
|
254
|
+
return err('Error: `insert_text` must be a string.');
|
|
255
|
+
}
|
|
256
|
+
const kg = graph();
|
|
257
|
+
const entity = findEntity(kg, namespace, name);
|
|
258
|
+
if (!entity)
|
|
259
|
+
return err(`Error: The path ${path} does not exist`);
|
|
260
|
+
const owners = lineOwners(entity.observations);
|
|
261
|
+
const line = atLine;
|
|
262
|
+
if (line < 0 || line > owners.length) {
|
|
263
|
+
return err(`Error: Invalid \`insert_line\` parameter: ${line}. ` +
|
|
264
|
+
`It should be within the range of lines of the file: [0, ${owners.length}]`);
|
|
265
|
+
}
|
|
266
|
+
const insertAfter = line === 0 ? -1 : owners[line - 1];
|
|
267
|
+
const observations = [...entity.observations];
|
|
268
|
+
observations.splice(insertAfter + 1, 0, text.replace(/\n$/, ''));
|
|
269
|
+
const oversize = tooLarge(observations.join('\n'), path);
|
|
270
|
+
if (oversize)
|
|
271
|
+
return oversize;
|
|
272
|
+
rewriteObservations(kg, entity, observations);
|
|
273
|
+
return ok(`The file ${path} has been edited.`);
|
|
274
|
+
}
|
|
275
|
+
function deletePath(parsed, path) {
|
|
276
|
+
if (parsed.kind === 'root') {
|
|
277
|
+
return err(`Error: ${MEMORY_ROOT} itself cannot be deleted.`);
|
|
278
|
+
}
|
|
279
|
+
if (parsed.kind === 'namespace') {
|
|
280
|
+
return err(`Error: ${path} is a namespace and cannot be deleted. Delete individual memories instead.`);
|
|
281
|
+
}
|
|
282
|
+
const kg = graph();
|
|
283
|
+
const entity = findEntity(kg, parsed.namespace, parsed.name);
|
|
284
|
+
if (!entity)
|
|
285
|
+
return err(`Error: The path ${path} does not exist`);
|
|
286
|
+
kg.archiveEntity(entity.name);
|
|
287
|
+
return ok(`Successfully deleted ${path}`);
|
|
288
|
+
}
|
|
289
|
+
function renamePath(oldRaw, newRaw) {
|
|
290
|
+
const from = parsePath(oldRaw);
|
|
291
|
+
if (isResult(from))
|
|
292
|
+
return from;
|
|
293
|
+
const to = parsePath(newRaw);
|
|
294
|
+
if (isResult(to))
|
|
295
|
+
return to;
|
|
296
|
+
if (from.kind !== 'entity' || to.kind !== 'entity') {
|
|
297
|
+
return err(`Error: rename moves one memory to another memory path. ` +
|
|
298
|
+
`${MEMORY_ROOT} and its namespaces cannot be renamed.`);
|
|
299
|
+
}
|
|
300
|
+
const kg = graph();
|
|
301
|
+
const source = findEntity(kg, from.namespace, from.name);
|
|
302
|
+
if (!source)
|
|
303
|
+
return err(`Error: The path ${String(oldRaw)} does not exist`);
|
|
304
|
+
if (findEntity(kg, to.namespace, to.name)) {
|
|
305
|
+
return err(`Error: The destination ${String(newRaw)} already exists`);
|
|
306
|
+
}
|
|
307
|
+
if (kg.getEntity(to.name)) {
|
|
308
|
+
return err(`Error: The destination ${String(newRaw)} already exists in another namespace. ` +
|
|
309
|
+
`Memory names are unique across namespaces.`);
|
|
310
|
+
}
|
|
311
|
+
const db = getDatabase();
|
|
312
|
+
const entityId = source.id;
|
|
313
|
+
const obsText = source.observations.join(' ');
|
|
314
|
+
db.transaction(() => {
|
|
315
|
+
removeFromFts(db, entityId, source.name, obsText);
|
|
316
|
+
db.prepare('UPDATE entities SET name = ?, namespace = ? WHERE id = ?')
|
|
317
|
+
.run(to.name, to.namespace, entityId);
|
|
318
|
+
insertFtsRow(db, entityId, to.name, obsText);
|
|
319
|
+
})();
|
|
320
|
+
return ok(`Successfully renamed ${String(oldRaw)} to ${String(newRaw)}`);
|
|
321
|
+
}
|
|
322
|
+
export function handleMemoryCommand(input) {
|
|
323
|
+
if (typeof input !== 'object' || input === null) {
|
|
324
|
+
return err('Error: the memory tool input must be an object.');
|
|
325
|
+
}
|
|
326
|
+
const cmd = input;
|
|
327
|
+
switch (cmd.command) {
|
|
328
|
+
case 'rename':
|
|
329
|
+
return renamePath(cmd.old_path, cmd.new_path);
|
|
330
|
+
case 'view':
|
|
331
|
+
case 'create':
|
|
332
|
+
case 'str_replace':
|
|
333
|
+
case 'insert':
|
|
334
|
+
case 'delete':
|
|
335
|
+
break;
|
|
336
|
+
case undefined:
|
|
337
|
+
return err('Error: the memory tool input has no `command`.');
|
|
338
|
+
default:
|
|
339
|
+
return err(`Error: unknown command ${String(cmd.command)}`);
|
|
340
|
+
}
|
|
341
|
+
const parsed = parsePath(cmd.path);
|
|
342
|
+
if (isResult(parsed))
|
|
343
|
+
return parsed;
|
|
344
|
+
const path = cmd.path;
|
|
345
|
+
if (cmd.command === 'delete')
|
|
346
|
+
return deletePath(parsed, path);
|
|
347
|
+
if (cmd.command === 'view') {
|
|
348
|
+
if (parsed.kind === 'root')
|
|
349
|
+
return viewRoot();
|
|
350
|
+
if (parsed.kind === 'namespace')
|
|
351
|
+
return viewNamespace(parsed.namespace);
|
|
352
|
+
return viewEntity(parsed.namespace, parsed.name, cmd.view_range, path);
|
|
353
|
+
}
|
|
354
|
+
if (parsed.kind !== 'entity') {
|
|
355
|
+
return err(`Error: ${path} is a directory. ${cmd.command} needs a memory file, ` +
|
|
356
|
+
`${MEMORY_ROOT}/<namespace>/<memory>${FILE_SUFFIX}.`);
|
|
357
|
+
}
|
|
358
|
+
switch (cmd.command) {
|
|
359
|
+
case 'create':
|
|
360
|
+
return createEntityFile(parsed.namespace, parsed.name, cmd.file_text, path);
|
|
361
|
+
case 'str_replace':
|
|
362
|
+
return strReplace(parsed.namespace, parsed.name, cmd.old_str, cmd.new_str, path);
|
|
363
|
+
case 'insert':
|
|
364
|
+
return insertLine(parsed.namespace, parsed.name, cmd.insert_line, cmd.insert_text, path);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
export const MEMORY_TOOL_DEFINITION = {
|
|
368
|
+
type: 'memory_20250818',
|
|
369
|
+
name: 'memory',
|
|
370
|
+
};
|
|
371
|
+
//# sourceMappingURL=memory-tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-tool.js","sourceRoot":"","sources":["../../src/core/memory-tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { EmbedOutcome } from './embedder.js';
|
|
1
2
|
import type { RememberInput, RememberResult, RecallInput, ForgetInput, ForgetResult, LearnInput, LearnResult, Entity } from './types.js';
|
|
2
3
|
export declare function remember(args: RememberInput): RememberResult;
|
|
3
4
|
export declare function recall(args: RecallInput): Entity[];
|
|
@@ -6,7 +7,6 @@ export declare function recallWithConflicts(args: RecallInput): Promise<{
|
|
|
6
7
|
entities: Entity[];
|
|
7
8
|
conflicts: string[];
|
|
8
9
|
}>;
|
|
9
|
-
export { consolidate } from './consolidator.js';
|
|
10
10
|
export { exportMemories, importMemories } from './serializer.js';
|
|
11
11
|
export declare function learn(args: LearnInput): LearnResult;
|
|
12
12
|
export declare function forget(args: ForgetInput): ForgetResult;
|
|
@@ -15,11 +15,17 @@ export declare function setPinned(name: string, pinned: boolean): {
|
|
|
15
15
|
pinned: boolean;
|
|
16
16
|
found: boolean;
|
|
17
17
|
};
|
|
18
|
-
export
|
|
19
|
-
namespace?: string;
|
|
20
|
-
}): Promise<{
|
|
18
|
+
export interface ReindexResult {
|
|
21
19
|
processed: number;
|
|
22
20
|
embedded: number;
|
|
23
21
|
skipped: number;
|
|
24
|
-
|
|
22
|
+
outcomes: Record<EmbedOutcome | 'entity_missing' | 'nothing_to_embed', number>;
|
|
23
|
+
failed: number;
|
|
24
|
+
missingVectors: number;
|
|
25
|
+
missingVectorsDatabaseWide: number;
|
|
26
|
+
pendingReindexCleared: boolean;
|
|
27
|
+
}
|
|
28
|
+
export declare function reindex(opts?: {
|
|
29
|
+
namespace?: string;
|
|
30
|
+
}): Promise<ReindexResult>;
|
|
25
31
|
//# sourceMappingURL=operations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../../src/core/operations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../../src/core/operations.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGlD,OAAO,KAAK,EACV,aAAa,EACb,cAAc,EACd,WAAW,EACX,WAAW,EACX,YAAY,EACZ,UAAU,EACV,WAAW,EACX,MAAM,EACP,MAAM,YAAY,CAAC;AAgDpB,wBAAgB,QAAQ,CAAC,IAAI,EAAE,aAAa,GAAG,cAAc,CAgF5D;AAUD,wBAAgB,MAAM,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,EAAE,CAGlD;AAsHD,wBAAsB,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAezE;AASD,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,WAAW;;;GAK1D;AAGD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAYjE,wBAAgB,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,WAAW,CAmBnD;AAMD,wBAAgB,MAAM,CAAC,IAAI,EAAE,WAAW,GAAG,YAAY,CAuBtD;AAYD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAe1G;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAElB,QAAQ,EAAE,MAAM,CAAC;IAEjB,OAAO,EAAE,MAAM,CAAC;IAEhB,QAAQ,EAAE,MAAM,CAAC,YAAY,GAAG,gBAAgB,GAAG,kBAAkB,EAAE,MAAM,CAAC,CAAC;IAgB/E,MAAM,EAAE,MAAM,CAAC;IAYf,cAAc,EAAE,MAAM,CAAC;IAOvB,0BAA0B,EAAE,MAAM,CAAC;IAEnC,qBAAqB,EAAE,OAAO,CAAC;CAChC;AAwCD,wBAAsB,OAAO,CAAC,IAAI,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAwInF"}
|
package/dist/core/operations.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { getDatabase, clearPendingReindexFlag } from '../db.js';
|
|
2
|
+
import { hasSearchableTerms } from '../storage/fts-index.js';
|
|
2
3
|
import { KnowledgeGraph } from '../knowledge-graph.js';
|
|
3
4
|
import { rankEntities } from './scoring.js';
|
|
4
5
|
import { getProjectName } from './paths.js';
|
|
5
6
|
import { createExplicitLesson } from './lesson-engine.js';
|
|
6
|
-
import { embedAndStore, isEmbeddingAvailable, embedText, scheduleEmbedAndStore, vectorSearch } from './embedder.js';
|
|
7
|
+
import { embedAndStore, isEmbeddingAvailable, embedText, scheduleEmbedAndStore, vectorSearch, vectorSimilarity, MAX_VECTOR_DISTANCE } from './embedder.js';
|
|
7
8
|
import { autoTagAndApply } from './auto-tagger.js';
|
|
8
9
|
import { detectCapabilities } from './config.js';
|
|
9
10
|
function buildLocalMetadata(existingMetadata, overrides) {
|
|
@@ -21,6 +22,9 @@ function buildLocalMetadata(existingMetadata, overrides) {
|
|
|
21
22
|
function recallTagFilter(args) {
|
|
22
23
|
return args.cross_project ? undefined : args.tag;
|
|
23
24
|
}
|
|
25
|
+
function buildRelevanceMap(entities) {
|
|
26
|
+
return new Map(entities.map((entity, index) => [entity.name, 1 - index / (entities.length + 1)]));
|
|
27
|
+
}
|
|
24
28
|
export function remember(args) {
|
|
25
29
|
const db = getDatabase();
|
|
26
30
|
const kg = new KnowledgeGraph(db);
|
|
@@ -84,19 +88,22 @@ export function remember(args) {
|
|
|
84
88
|
};
|
|
85
89
|
}
|
|
86
90
|
export function recall(args) {
|
|
87
|
-
const
|
|
88
|
-
|
|
91
|
+
const { entities, relevanceMap } = searchAndScore(args);
|
|
92
|
+
return rankEntities(entities, relevanceMap).slice(0, args.limit ?? 20);
|
|
93
|
+
}
|
|
94
|
+
function searchAndScore(args) {
|
|
95
|
+
const kg = new KnowledgeGraph(getDatabase());
|
|
89
96
|
const entities = kg.search(args.query, {
|
|
90
97
|
tag: recallTagFilter(args),
|
|
91
98
|
limit: args.limit,
|
|
92
99
|
includeArchived: args.include_archived,
|
|
93
100
|
namespace: args.namespace,
|
|
94
101
|
});
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
102
|
+
return {
|
|
103
|
+
kg,
|
|
104
|
+
entities,
|
|
105
|
+
relevanceMap: args.query ? buildRelevanceMap(entities) : new Map(),
|
|
106
|
+
};
|
|
100
107
|
}
|
|
101
108
|
async function supplementWithVectors(query, args, kg, merged, relevanceMap) {
|
|
102
109
|
if (!isEmbeddingAvailable())
|
|
@@ -108,7 +115,10 @@ async function supplementWithVectors(query, args, kg, merged, relevanceMap) {
|
|
|
108
115
|
const vectorHits = vectorSearch(queryEmb, args.limit ?? 20);
|
|
109
116
|
if (vectorHits.length === 0)
|
|
110
117
|
return;
|
|
111
|
-
const
|
|
118
|
+
const alreadyMerged = new Set(merged.map(e => e.id));
|
|
119
|
+
const hitIds = vectorHits.map(h => h.id).filter(id => !alreadyMerged.has(id));
|
|
120
|
+
if (hitIds.length === 0)
|
|
121
|
+
return;
|
|
112
122
|
const hitEntities = kg.getEntitiesByIds(hitIds, {
|
|
113
123
|
includeArchived: args.include_archived === true,
|
|
114
124
|
namespace: args.namespace,
|
|
@@ -119,28 +129,17 @@ async function supplementWithVectors(query, args, kg, merged, relevanceMap) {
|
|
|
119
129
|
if (existingNames.has(entity.name))
|
|
120
130
|
continue;
|
|
121
131
|
merged.push(entity);
|
|
122
|
-
const dist = vectorHits.find(h => h.id === entity.id)?.distance ??
|
|
123
|
-
relevanceMap.set(entity.name,
|
|
132
|
+
const dist = vectorHits.find(h => h.id === entity.id)?.distance ?? MAX_VECTOR_DISTANCE;
|
|
133
|
+
relevanceMap.set(entity.name, vectorSimilarity(dist));
|
|
124
134
|
}
|
|
125
135
|
}
|
|
126
136
|
catch {
|
|
127
137
|
}
|
|
128
138
|
}
|
|
129
139
|
export async function recallEnhanced(args) {
|
|
130
|
-
const
|
|
131
|
-
const kg = new KnowledgeGraph(db);
|
|
132
|
-
const entities = kg.search(args.query, {
|
|
133
|
-
tag: recallTagFilter(args),
|
|
134
|
-
limit: args.limit,
|
|
135
|
-
includeArchived: args.include_archived,
|
|
136
|
-
namespace: args.namespace,
|
|
137
|
-
});
|
|
138
|
-
const relevanceMap = new Map();
|
|
139
|
-
for (const e of entities) {
|
|
140
|
-
relevanceMap.set(e.name, args.query ? 1.0 : 0.5);
|
|
141
|
-
}
|
|
140
|
+
const { kg, entities, relevanceMap } = searchAndScore(args);
|
|
142
141
|
const mergedEntities = [...entities];
|
|
143
|
-
if (args.query) {
|
|
142
|
+
if (args.query && hasSearchableTerms(args.query)) {
|
|
144
143
|
await supplementWithVectors(args.query, args, kg, mergedEntities, relevanceMap);
|
|
145
144
|
}
|
|
146
145
|
return rankEntities(mergedEntities, relevanceMap).slice(0, args.limit ?? 20);
|
|
@@ -151,7 +150,6 @@ export async function recallWithConflicts(args) {
|
|
|
151
150
|
const conflicts = kg.findConflicts(entities.map((e) => e.name));
|
|
152
151
|
return { entities, conflicts };
|
|
153
152
|
}
|
|
154
|
-
export { consolidate } from './consolidator.js';
|
|
155
153
|
export { exportMemories, importMemories } from './serializer.js';
|
|
156
154
|
export function learn(args) {
|
|
157
155
|
const projectName = getProjectName();
|
|
@@ -200,6 +198,16 @@ export function setPinned(name, pinned) {
|
|
|
200
198
|
});
|
|
201
199
|
return { name, pinned, found: true };
|
|
202
200
|
}
|
|
201
|
+
function countMissingVectors(db, namespace) {
|
|
202
|
+
const row = db.prepare(`
|
|
203
|
+
SELECT COUNT(*) AS n FROM entities e
|
|
204
|
+
WHERE e.status = 'active'
|
|
205
|
+
${namespace ? 'AND e.namespace = ?' : ''}
|
|
206
|
+
AND EXISTS (SELECT 1 FROM observations o WHERE o.entity_id = e.id AND TRIM(o.content) <> '')
|
|
207
|
+
AND NOT EXISTS (SELECT 1 FROM entities_vec v WHERE v.rowid = e.id)
|
|
208
|
+
`).get(...(namespace ? [namespace] : []));
|
|
209
|
+
return row.n;
|
|
210
|
+
}
|
|
203
211
|
export async function reindex(opts) {
|
|
204
212
|
if (!isEmbeddingAvailable()) {
|
|
205
213
|
throw new Error('No embedding provider available. Configure OpenAI API key, Ollama, or install @huggingface/transformers.');
|
|
@@ -209,32 +217,81 @@ export async function reindex(opts) {
|
|
|
209
217
|
const namespaceFilter = opts?.namespace ? 'AND namespace = ?' : '';
|
|
210
218
|
const params = opts?.namespace ? [opts.namespace] : [];
|
|
211
219
|
const entities = db.prepare(`SELECT id, name FROM entities WHERE status = 'active' ${namespaceFilter} ORDER BY id`).all(...params);
|
|
220
|
+
const outcomes = {
|
|
221
|
+
stored: 0,
|
|
222
|
+
removed: 0,
|
|
223
|
+
no_embedding: 0,
|
|
224
|
+
dimension_mismatch: 0,
|
|
225
|
+
write_failed: 0,
|
|
226
|
+
database_closed: 0,
|
|
227
|
+
entity_missing: 0,
|
|
228
|
+
nothing_to_embed: 0,
|
|
229
|
+
};
|
|
212
230
|
let processed = 0;
|
|
213
|
-
let embedded = 0;
|
|
214
|
-
let skipped = 0;
|
|
215
231
|
process.stderr.write(`MeMesh: Reindexing ${entities.length} entities...\n`);
|
|
216
232
|
for (const entity of entities) {
|
|
217
233
|
processed++;
|
|
218
234
|
const fullEntity = kg.getEntity(entity.name);
|
|
219
235
|
if (!fullEntity) {
|
|
220
|
-
|
|
236
|
+
outcomes.entity_missing++;
|
|
221
237
|
continue;
|
|
222
238
|
}
|
|
223
239
|
const text = fullEntity.observations.join(' ');
|
|
240
|
+
if (text.trim() === '') {
|
|
241
|
+
outcomes.nothing_to_embed++;
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
224
244
|
try {
|
|
225
|
-
await embedAndStore(entity.id, text)
|
|
226
|
-
embedded++;
|
|
245
|
+
outcomes[await embedAndStore(entity.id, text)]++;
|
|
227
246
|
if (processed % 10 === 0) {
|
|
228
|
-
process.stderr.write(`MeMesh: Processed ${processed}/${entities.length}
|
|
247
|
+
process.stderr.write(`MeMesh: Processed ${processed}/${entities.length} ` +
|
|
248
|
+
`(${outcomes.stored} embedded, ${processed - outcomes.stored} skipped)\n`);
|
|
229
249
|
}
|
|
230
250
|
}
|
|
231
251
|
catch (err) {
|
|
232
|
-
|
|
252
|
+
outcomes.write_failed++;
|
|
233
253
|
process.stderr.write(`MeMesh: Failed to embed entity ${entity.name}: ${err}\n`);
|
|
234
254
|
}
|
|
235
255
|
}
|
|
256
|
+
const embedded = outcomes.stored;
|
|
257
|
+
const skipped = processed - embedded;
|
|
258
|
+
const failed = outcomes.no_embedding +
|
|
259
|
+
outcomes.dimension_mismatch +
|
|
260
|
+
outcomes.write_failed +
|
|
261
|
+
outcomes.database_closed;
|
|
262
|
+
const missingVectors = countMissingVectors(db, opts?.namespace);
|
|
263
|
+
const missingVectorsDatabaseWide = opts?.namespace
|
|
264
|
+
? countMissingVectors(db)
|
|
265
|
+
: missingVectors;
|
|
236
266
|
process.stderr.write(`MeMesh: Reindex complete. ${embedded}/${processed} entities embedded.\n`);
|
|
237
|
-
|
|
238
|
-
|
|
267
|
+
if (outcomes.dimension_mismatch > 0) {
|
|
268
|
+
process.stderr.write(`MeMesh: ${outcomes.dimension_mismatch} entities were skipped because the provider's ` +
|
|
269
|
+
`embedding dimension does not match this database's vector index. Rebuild it with ` +
|
|
270
|
+
`'memesh reindex --vectors'.\n`);
|
|
271
|
+
}
|
|
272
|
+
const pendingReindexCleared = missingVectorsDatabaseWide === 0 && failed === 0;
|
|
273
|
+
if (pendingReindexCleared) {
|
|
274
|
+
clearPendingReindexFlag();
|
|
275
|
+
}
|
|
276
|
+
else if (missingVectorsDatabaseWide > 0) {
|
|
277
|
+
process.stderr.write(`MeMesh: ${missingVectorsDatabaseWide} active memories still have no vector` +
|
|
278
|
+
`${opts?.namespace ? ' (across all namespaces)' : ''}, so the ` +
|
|
279
|
+
`reindex-needed flag was left set.\n`);
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
process.stderr.write(`MeMesh: every memory has a vector, but ${failed} could not be regenerated, ` +
|
|
283
|
+
`so those still hold their previous embedding and the reindex-needed flag ` +
|
|
284
|
+
`was left set.\n`);
|
|
285
|
+
}
|
|
286
|
+
return {
|
|
287
|
+
processed,
|
|
288
|
+
embedded,
|
|
289
|
+
skipped,
|
|
290
|
+
outcomes,
|
|
291
|
+
failed,
|
|
292
|
+
missingVectors,
|
|
293
|
+
missingVectorsDatabaseWide,
|
|
294
|
+
pendingReindexCleared,
|
|
295
|
+
};
|
|
239
296
|
}
|
|
240
297
|
//# sourceMappingURL=operations.js.map
|