vektor-slipstream 1.4.4 → 2.0.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/README.md +67 -306
- package/package.json +14 -146
- package/CHANGELOG.md +0 -139
- package/LICENSE +0 -33
- package/TENETS.md +0 -189
- package/audn-log.js +0 -143
- package/axon.js +0 -389
- package/boot-patch.js +0 -33
- package/boot-screen.html +0 -210
- package/briefing.js +0 -150
- package/cerebellum.js +0 -439
- package/cloak-behaviour.js +0 -596
- package/cloak-captcha.js +0 -541
- package/cloak-core.js +0 -499
- package/cloak-identity.js +0 -484
- package/cloak-index.js +0 -261
- package/cloak-llms.js +0 -163
- package/cloak-pattern-store.js +0 -471
- package/cloak-recorder-auto.js +0 -297
- package/cloak-recorder-snippet.js +0 -119
- package/cloak-turbo-quant.js +0 -357
- package/cloak-warmup.js +0 -240
- package/cortex.js +0 -221
- package/detect-hardware.js +0 -181
- package/entity-resolver.js +0 -298
- package/errors.js +0 -66
- package/examples/example-claude-mcp.js +0 -220
- package/examples/example-langchain-researcher.js +0 -82
- package/examples/example-openai-assistant.js +0 -84
- package/examples/examples-README.md +0 -161
- package/export-import.js +0 -221
- package/forget.js +0 -148
- package/inspect.js +0 -199
- package/mistral/README-mistral.md +0 -123
- package/mistral/mistral-bridge.js +0 -218
- package/mistral/mistral-setup.js +0 -220
- package/mistral/vektor-tool-manifest.json +0 -41
- package/models/model_quantized.onnx +0 -0
- package/models/vocab.json +0 -1
- package/namespace.js +0 -186
- package/pin.js +0 -91
- package/slipstream-core-extended.js +0 -134
- package/slipstream-core.js +0 -1
- package/slipstream-db.js +0 -140
- package/slipstream-embedder.js +0 -338
- package/sovereign.js +0 -142
- package/token.js +0 -322
- package/types/index.d.ts +0 -269
- package/vektor-banner-loader.js +0 -109
- package/vektor-cli.js +0 -259
- package/vektor-licence-prompt.js +0 -128
- package/vektor-licence.js +0 -192
- package/vektor-setup.js +0 -270
- package/vektor-slipstream.dxt +0 -0
- package/vektor-tui.js +0 -373
- package/visualize.js +0 -235
package/export-import.js
DELETED
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* VEKTOR memory.export() / memory.import() — v1.3.7
|
|
3
|
-
* Full graph serialisation — backup, migration, agent sharing.
|
|
4
|
-
*
|
|
5
|
-
* Gemini review fixes applied (round 2):
|
|
6
|
-
* Fix 1 — SQL subqueries replace IN (...memIds) — no more 32,766 param limit crash
|
|
7
|
-
* Fix 2 — O(N) loop in replace mode → bulk subquery deletes
|
|
8
|
-
* Fix 3 — Checksum hashes full memories payload, not just IDs
|
|
9
|
-
* Fix 4 — Dangling edge guard — edges only inserted if both endpoints exist
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { createHash } from 'crypto';
|
|
13
|
-
import { VektorError, ERR } from './errors.js';
|
|
14
|
-
|
|
15
|
-
const EXPORT_VERSION = '1.3.7';
|
|
16
|
-
|
|
17
|
-
function resolveSinceTs(since) {
|
|
18
|
-
if (!since) return null;
|
|
19
|
-
if (typeof since === 'number') {
|
|
20
|
-
return since > 9_999_999_999 ? Math.floor(since / 1000) : since;
|
|
21
|
-
}
|
|
22
|
-
const rel = String(since).match(/^(\d+)(d|h|m)$/);
|
|
23
|
-
if (rel) {
|
|
24
|
-
const n = parseInt(rel[1]);
|
|
25
|
-
const mult = rel[2] === 'd' ? 86400 : rel[2] === 'h' ? 3600 : 60;
|
|
26
|
-
return Math.floor(Date.now() / 1000) - n * mult;
|
|
27
|
-
}
|
|
28
|
-
const ts = Date.parse(since);
|
|
29
|
-
if (!isNaN(ts)) return Math.floor(ts / 1000);
|
|
30
|
-
throw new VektorError(ERR.EXPORT_FAILED, `Invalid since value: "${since}"`);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function exportMemory(db, agentId, namespace, opts = {}) {
|
|
34
|
-
const { includeEmbeddings = false, since = null } = opts;
|
|
35
|
-
const sinceTs = resolveSinceTs(since);
|
|
36
|
-
const sinceSQL = sinceTs ? `AND created_at >= ${sinceTs}` : '';
|
|
37
|
-
const embedCol = includeEmbeddings ? ', embedding' : '';
|
|
38
|
-
|
|
39
|
-
const memories = db.prepare(`
|
|
40
|
-
SELECT id, content, summary, importance, pinned,
|
|
41
|
-
namespace, created_at, updated_at${embedCol}
|
|
42
|
-
FROM memories
|
|
43
|
-
WHERE agent_id = ? AND namespace = ? ${sinceSQL}
|
|
44
|
-
ORDER BY created_at ASC
|
|
45
|
-
`).all(agentId, namespace);
|
|
46
|
-
|
|
47
|
-
if (memories.length === 0) {
|
|
48
|
-
throw new VektorError(ERR.EXPORT_FAILED,
|
|
49
|
-
`No memories found for agent "${agentId}" in namespace "${namespace}"`);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Fix 1 — subquery replaces IN (...memIds) placeholders
|
|
53
|
-
// SQLite hard limit is 32,766 bound params — a 16,500 memory export would crash the old code
|
|
54
|
-
const edges = db.prepare(`
|
|
55
|
-
SELECT id, source_id, target_id, edge_type, weight, created_at
|
|
56
|
-
FROM graph_edges
|
|
57
|
-
WHERE source_id IN (SELECT id FROM memories WHERE agent_id = ? AND namespace = ? ${sinceSQL})
|
|
58
|
-
OR target_id IN (SELECT id FROM memories WHERE agent_id = ? AND namespace = ? ${sinceSQL})
|
|
59
|
-
`).all(agentId, namespace, agentId, namespace);
|
|
60
|
-
|
|
61
|
-
let entityMentions = [], entities = [];
|
|
62
|
-
try {
|
|
63
|
-
entityMentions = db.prepare(`
|
|
64
|
-
SELECT memory_id, entity_id FROM entity_mentions
|
|
65
|
-
WHERE memory_id IN (SELECT id FROM memories WHERE agent_id = ? AND namespace = ? ${sinceSQL})
|
|
66
|
-
`).all(agentId, namespace);
|
|
67
|
-
entities = db.prepare(`SELECT * FROM entities`).all();
|
|
68
|
-
} catch { /* entity tables may not exist */ }
|
|
69
|
-
|
|
70
|
-
let audnLog = [];
|
|
71
|
-
try {
|
|
72
|
-
audnLog = db.prepare(`
|
|
73
|
-
SELECT action, memory_id, content, reason, similarity, ran_at
|
|
74
|
-
FROM audn_log WHERE agent_id = ? AND namespace = ?
|
|
75
|
-
ORDER BY ran_at DESC LIMIT 1000
|
|
76
|
-
`).all(agentId, namespace);
|
|
77
|
-
} catch { /* audn_log may not exist */ }
|
|
78
|
-
|
|
79
|
-
// Fix 3 — hash full memories payload, not just IDs
|
|
80
|
-
// Previously content tampering went undetected — only IDs were hashed
|
|
81
|
-
const checksum = createHash('sha256')
|
|
82
|
-
.update(JSON.stringify(memories))
|
|
83
|
-
.digest('hex')
|
|
84
|
-
.slice(0, 16);
|
|
85
|
-
|
|
86
|
-
return {
|
|
87
|
-
_vektor: { version: EXPORT_VERSION, exported_at: new Date().toISOString(),
|
|
88
|
-
agent_id: agentId, namespace, checksum,
|
|
89
|
-
counts: { memories: memories.length, edges: edges.length, entities: entities.length } },
|
|
90
|
-
memories, edges, entities, entityMentions, audnLog
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export function importMemory(db, agentId, bundle, opts = {}) {
|
|
95
|
-
const { namespace = null, mode = 'merge', dryRun = false } = opts;
|
|
96
|
-
|
|
97
|
-
if (!bundle?._vektor?.version) {
|
|
98
|
-
throw new VektorError(ERR.IMPORT_SCHEMA_MISMATCH, 'Invalid export bundle — missing _vektor header');
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const targetNamespace = namespace || bundle._vektor.namespace;
|
|
102
|
-
if (!targetNamespace) throw new VektorError(ERR.IMPORT_FAILED, 'No target namespace specified');
|
|
103
|
-
if (!Array.isArray(bundle.memories) || bundle.memories.length === 0) {
|
|
104
|
-
throw new VektorError(ERR.IMPORT_FAILED, 'Bundle contains no memories');
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Fix 3 — verify full-payload checksum (same serialisation as export)
|
|
108
|
-
const checksum = createHash('sha256')
|
|
109
|
-
.update(JSON.stringify(bundle.memories))
|
|
110
|
-
.digest('hex')
|
|
111
|
-
.slice(0, 16);
|
|
112
|
-
|
|
113
|
-
if (checksum !== bundle._vektor.checksum) {
|
|
114
|
-
throw new VektorError(ERR.IMPORT_SCHEMA_MISMATCH,
|
|
115
|
-
`Checksum mismatch — bundle may be corrupted or tampered.\n` +
|
|
116
|
-
`Expected: ${bundle._vektor.checksum} Got: ${checksum}`);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (dryRun) {
|
|
120
|
-
return { dryRun: true, would_import: bundle.memories.length,
|
|
121
|
-
would_add_edges: bundle.edges?.length ?? 0,
|
|
122
|
-
target_namespace: targetNamespace,
|
|
123
|
-
source_version: bundle._vektor.version, checksum_valid: true };
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const doImport = db.transaction(() => {
|
|
127
|
-
let imported = 0, skipped = 0, edgesAdded = 0, edgesSkipped = 0;
|
|
128
|
-
|
|
129
|
-
// Fix 2 — replace mode: bulk subquery deletes, not O(N) JS loop
|
|
130
|
-
if (mode === 'replace') {
|
|
131
|
-
db.prepare(`
|
|
132
|
-
DELETE FROM graph_edges
|
|
133
|
-
WHERE source_id IN (SELECT id FROM memories WHERE agent_id = ? AND namespace = ?)
|
|
134
|
-
OR target_id IN (SELECT id FROM memories WHERE agent_id = ? AND namespace = ?)
|
|
135
|
-
`).run(agentId, targetNamespace, agentId, targetNamespace);
|
|
136
|
-
|
|
137
|
-
db.prepare(`
|
|
138
|
-
DELETE FROM entity_mentions
|
|
139
|
-
WHERE memory_id IN (SELECT id FROM memories WHERE agent_id = ? AND namespace = ?)
|
|
140
|
-
`).run(agentId, targetNamespace);
|
|
141
|
-
|
|
142
|
-
db.prepare(`DELETE FROM memories WHERE agent_id = ? AND namespace = ?`)
|
|
143
|
-
.run(agentId, targetNamespace);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const insertMem = db.prepare(`
|
|
147
|
-
INSERT INTO memories
|
|
148
|
-
(id, agent_id, namespace, content, summary, importance, pinned, created_at, updated_at)
|
|
149
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
150
|
-
ON CONFLICT(id) DO NOTHING
|
|
151
|
-
`);
|
|
152
|
-
|
|
153
|
-
for (const m of bundle.memories) {
|
|
154
|
-
const r = insertMem.run(
|
|
155
|
-
m.id, agentId, targetNamespace,
|
|
156
|
-
m.content, m.summary ?? null, m.importance ?? 0.5, m.pinned ?? 0,
|
|
157
|
-
m.created_at, m.updated_at ?? null
|
|
158
|
-
);
|
|
159
|
-
if (r.changes > 0) imported++; else skipped++;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Fix 4 — dangling edge guard
|
|
163
|
-
// Partial exports (since: '7d') may reference memories older than the export window.
|
|
164
|
-
// INSERT ... SELECT ... WHERE EXISTS ensures we never write an edge pointing to a ghost node.
|
|
165
|
-
const insertEdge = db.prepare(`
|
|
166
|
-
INSERT INTO graph_edges (id, source_id, target_id, edge_type, weight, created_at)
|
|
167
|
-
SELECT ?, ?, ?, ?, ?, ?
|
|
168
|
-
WHERE EXISTS (SELECT 1 FROM memories WHERE id = ?)
|
|
169
|
-
AND EXISTS (SELECT 1 FROM memories WHERE id = ?)
|
|
170
|
-
ON CONFLICT(id) DO NOTHING
|
|
171
|
-
`);
|
|
172
|
-
|
|
173
|
-
for (const e of bundle.edges ?? []) {
|
|
174
|
-
const r = insertEdge.run(
|
|
175
|
-
e.id, e.source_id, e.target_id, e.edge_type, e.weight, e.created_at,
|
|
176
|
-
e.source_id, e.target_id
|
|
177
|
-
);
|
|
178
|
-
if (r.changes > 0) edgesAdded++; else edgesSkipped++;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
if (bundle.entities?.length) {
|
|
182
|
-
const insertEntity = db.prepare(`
|
|
183
|
-
INSERT INTO entities (id, canonical, type, confidence, created_at)
|
|
184
|
-
VALUES (?, ?, ?, ?, ?)
|
|
185
|
-
ON CONFLICT(id) DO NOTHING
|
|
186
|
-
`);
|
|
187
|
-
for (const e of bundle.entities) {
|
|
188
|
-
try { insertEntity.run(e.id, e.canonical, e.type ?? 'unknown', e.confidence ?? 1.0, e.created_at); }
|
|
189
|
-
catch { /* entity table may not exist */ }
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return { imported, skipped, edgesAdded, edgesSkipped };
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
const result = doImport();
|
|
197
|
-
|
|
198
|
-
if (result.edgesSkipped > 0) {
|
|
199
|
-
console.warn(
|
|
200
|
-
`[VEKTOR] import: ${result.edgesSkipped} edges skipped — ` +
|
|
201
|
-
`endpoints missing in destination (expected for partial exports).`
|
|
202
|
-
);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
return result;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Usage:
|
|
210
|
-
* const bundle = memory.export();
|
|
211
|
-
* fs.writeFileSync('backup.vektor.json', JSON.stringify(bundle, null, 2));
|
|
212
|
-
*
|
|
213
|
-
* memory.import(bundle);
|
|
214
|
-
* // → { imported: 244, skipped: 3, edgesAdded: 7100, edgesSkipped: 0 }
|
|
215
|
-
*
|
|
216
|
-
* memory.import(bundle, { dryRun: true });
|
|
217
|
-
* // → { dryRun: true, checksum_valid: true, ... }
|
|
218
|
-
*
|
|
219
|
-
* memory.import(bundle, { mode: 'replace' });
|
|
220
|
-
* memory.import(bundle, { namespace: 'restored-2026-01' });
|
|
221
|
-
*/
|
package/forget.js
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* VEKTOR memory.forget() — v1.3.7
|
|
3
|
-
* Deletes a memory node and cascades to all graph edges.
|
|
4
|
-
* Add this method to your core Memory class.
|
|
5
|
-
*
|
|
6
|
-
* Schema assumptions (existing vektor tables):
|
|
7
|
-
* memories(id, content, summary, importance, embedding, namespace, pinned, agent_id, created_at)
|
|
8
|
-
* graph_edges(id, source_id, target_id, edge_type, weight)
|
|
9
|
-
* entity_mentions(memory_id, entity_id) -- if entity resolver is active
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { VektorError, ERR } from './errors.js';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* forget(id)
|
|
16
|
-
* Hard-deletes a single memory and all associated graph edges.
|
|
17
|
-
*
|
|
18
|
-
* @param {object} db - better-sqlite3 db instance
|
|
19
|
-
* @param {string} agentId - current agent scope
|
|
20
|
-
* @param {string} namespace - current namespace scope
|
|
21
|
-
* @param {string} id - memory id to delete
|
|
22
|
-
* @returns {{ deleted: boolean, edgesRemoved: number }}
|
|
23
|
-
*/
|
|
24
|
-
export function forget(db, agentId, namespace, id) {
|
|
25
|
-
const memory = db
|
|
26
|
-
.prepare(`SELECT id, pinned FROM memories WHERE id = ? AND agent_id = ? AND namespace = ?`)
|
|
27
|
-
.get(id, agentId, namespace);
|
|
28
|
-
|
|
29
|
-
if (!memory) {
|
|
30
|
-
throw new VektorError(
|
|
31
|
-
ERR.MEMORY_NOT_FOUND,
|
|
32
|
-
`Memory ${id} not found for agent ${agentId} in namespace ${namespace}`
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (memory.pinned) {
|
|
37
|
-
throw new VektorError(
|
|
38
|
-
ERR.MEMORY_DELETE_FAILED,
|
|
39
|
-
`Memory ${id} is pinned — unpin it first with memory.unpin(id)`
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Count edges before delete for return value
|
|
44
|
-
const edgeCount = db
|
|
45
|
-
.prepare(`SELECT COUNT(*) as n FROM graph_edges WHERE source_id = ? OR target_id = ?`)
|
|
46
|
-
.get(id, id).n;
|
|
47
|
-
|
|
48
|
-
// Fix 3 (Gemini round 3) — pinned edge orphan guard
|
|
49
|
-
// If this memory shares an edge with a pinned memory, deleting it would
|
|
50
|
-
// leave a dangling edge in the MAGMA graph pointing to a ghost node,
|
|
51
|
-
// silently corrupting traversal. Block the delete and surface the conflict.
|
|
52
|
-
const linkedPinned = db.prepare(`
|
|
53
|
-
SELECT m.id, m.content FROM graph_edges ge
|
|
54
|
-
JOIN memories m ON (ge.source_id = m.id OR ge.target_id = m.id)
|
|
55
|
-
WHERE (ge.source_id = ? OR ge.target_id = ?)
|
|
56
|
-
AND m.id != ?
|
|
57
|
-
AND m.pinned = 1
|
|
58
|
-
LIMIT 1
|
|
59
|
-
`).get(id, id, id);
|
|
60
|
-
|
|
61
|
-
if (linkedPinned) {
|
|
62
|
-
throw new VektorError(
|
|
63
|
-
ERR.MEMORY_DELETE_FAILED,
|
|
64
|
-
`Cannot delete memory ${id} — it is linked to pinned memory "${linkedPinned.id}". ` +
|
|
65
|
-
`Unpin that memory first, or use forgetWhere() to review the connection.`
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Run as transaction — all or nothing
|
|
70
|
-
const deleteAll = db.transaction(() => {
|
|
71
|
-
db.prepare(`DELETE FROM graph_edges WHERE source_id = ? OR target_id = ?`).run(id, id);
|
|
72
|
-
db.prepare(`DELETE FROM entity_mentions WHERE memory_id = ?`).run(id);
|
|
73
|
-
db.prepare(`DELETE FROM memories WHERE id = ? AND agent_id = ? AND namespace = ?`)
|
|
74
|
-
.run(id, agentId, namespace);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
deleteAll();
|
|
78
|
-
|
|
79
|
-
return { deleted: true, edgesRemoved: edgeCount };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* forgetWhere(query)
|
|
84
|
-
* Bulk-delete memories matching a semantic query above a threshold.
|
|
85
|
-
* Useful for: "forget everything about Project X"
|
|
86
|
-
*
|
|
87
|
-
* @param {object} db
|
|
88
|
-
* @param {string} agentId
|
|
89
|
-
* @param {string} namespace
|
|
90
|
-
* @param {Function} recallFn - memory.recall() reference
|
|
91
|
-
* @param {string} query - natural language query
|
|
92
|
-
* @param {object} opts
|
|
93
|
-
* @param {number} opts.limit - max memories to delete (default 10, safety cap)
|
|
94
|
-
* @param {number} opts.minScore - min similarity score (default 0.85)
|
|
95
|
-
* @param {boolean} opts.dryRun - if true, returns candidates without deleting
|
|
96
|
-
* @returns {{ deleted: number, candidates: object[] }}
|
|
97
|
-
*/
|
|
98
|
-
export async function forgetWhere(db, agentId, namespace, recallFn, query, opts = {}) {
|
|
99
|
-
const { limit = 10, minScore = 0.85, dryRun = false } = opts;
|
|
100
|
-
|
|
101
|
-
const candidates = await recallFn(query, limit);
|
|
102
|
-
const toDelete = candidates.filter(c => c.score >= minScore && !c.pinned);
|
|
103
|
-
|
|
104
|
-
if (dryRun) {
|
|
105
|
-
return { deleted: 0, candidates: toDelete };
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
let deleted = 0;
|
|
109
|
-
for (const mem of toDelete) {
|
|
110
|
-
try {
|
|
111
|
-
forget(db, agentId, namespace, mem.id);
|
|
112
|
-
deleted++;
|
|
113
|
-
} catch (e) {
|
|
114
|
-
// Only swallow expected skips — pinned memories or already-deleted IDs
|
|
115
|
-
// Re-throw anything infrastructure-level (SQLITE_BUSY, disk full, etc.)
|
|
116
|
-
if (e instanceof VektorError &&
|
|
117
|
-
(e.code === ERR.MEMORY_DELETE_FAILED || e.code === ERR.MEMORY_NOT_FOUND)) {
|
|
118
|
-
// expected skip — continue loop
|
|
119
|
-
} else {
|
|
120
|
-
throw e;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return { deleted, candidates: toDelete };
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Integration into Memory class:
|
|
130
|
-
*
|
|
131
|
-
* async forget(id) {
|
|
132
|
-
* return forget(this.db, this.agentId, this.namespace, id);
|
|
133
|
-
* }
|
|
134
|
-
*
|
|
135
|
-
* async forgetWhere(query, opts = {}) {
|
|
136
|
-
* return forgetWhere(this.db, this.agentId, this.namespace, this.recall.bind(this), query, opts);
|
|
137
|
-
* }
|
|
138
|
-
*
|
|
139
|
-
* Usage:
|
|
140
|
-
* await memory.forget('mem_abc123');
|
|
141
|
-
* // → { deleted: true, edgesRemoved: 4 }
|
|
142
|
-
*
|
|
143
|
-
* await memory.forgetWhere('Project Atlas decisions', { dryRun: true });
|
|
144
|
-
* // → { deleted: 0, candidates: [...] } -- preview first
|
|
145
|
-
*
|
|
146
|
-
* await memory.forgetWhere('Project Atlas decisions', { minScore: 0.9, limit: 5 });
|
|
147
|
-
* // → { deleted: 3, candidates: [...] }
|
|
148
|
-
*/
|
package/inspect.js
DELETED
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* VEKTOR memory.inspect() — v1.3.7
|
|
3
|
-
* Returns a full diagnostic snapshot of the memory graph.
|
|
4
|
-
* No more raw SQLite queries to debug state.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* inspect()
|
|
9
|
-
* @param {object} db
|
|
10
|
-
* @param {string} agentId
|
|
11
|
-
* @param {string} namespace
|
|
12
|
-
* @returns {object} full diagnostic snapshot
|
|
13
|
-
*/
|
|
14
|
-
export function inspect(db, agentId, namespace) {
|
|
15
|
-
const scope = { agent_id: agentId, namespace };
|
|
16
|
-
|
|
17
|
-
// Core counts
|
|
18
|
-
const memoryCount = db.prepare(
|
|
19
|
-
`SELECT COUNT(*) as n FROM memories WHERE agent_id = ? AND namespace = ?`
|
|
20
|
-
).get(agentId, namespace).n;
|
|
21
|
-
|
|
22
|
-
const pinnedCount = db.prepare(
|
|
23
|
-
`SELECT COUNT(*) as n FROM memories WHERE agent_id = ? AND namespace = ? AND pinned = 1`
|
|
24
|
-
).get(agentId, namespace).n;
|
|
25
|
-
|
|
26
|
-
const edgeCount = db.prepare(
|
|
27
|
-
`SELECT COUNT(*) as n FROM graph_edges ge
|
|
28
|
-
JOIN memories m ON ge.source_id = m.id
|
|
29
|
-
WHERE m.agent_id = ? AND m.namespace = ?`
|
|
30
|
-
).get(agentId, namespace).n;
|
|
31
|
-
|
|
32
|
-
// Edge type breakdown
|
|
33
|
-
const edgeTypes = db.prepare(
|
|
34
|
-
`SELECT ge.edge_type, COUNT(*) as n FROM graph_edges ge
|
|
35
|
-
JOIN memories m ON ge.source_id = m.id
|
|
36
|
-
WHERE m.agent_id = ? AND m.namespace = ?
|
|
37
|
-
GROUP BY ge.edge_type ORDER BY n DESC`
|
|
38
|
-
).all(agentId, namespace);
|
|
39
|
-
|
|
40
|
-
// Top nodes by edge count (most connected memories)
|
|
41
|
-
const topNodes = db.prepare(
|
|
42
|
-
`SELECT m.id, m.content, m.summary, m.importance, m.pinned,
|
|
43
|
-
COUNT(ge.id) as connections
|
|
44
|
-
FROM memories m
|
|
45
|
-
LEFT JOIN graph_edges ge ON ge.source_id = m.id OR ge.target_id = m.id
|
|
46
|
-
WHERE m.agent_id = ? AND m.namespace = ?
|
|
47
|
-
GROUP BY m.id
|
|
48
|
-
ORDER BY connections DESC, m.importance DESC
|
|
49
|
-
LIMIT 5`
|
|
50
|
-
).all(agentId, namespace);
|
|
51
|
-
|
|
52
|
-
// Recent memories
|
|
53
|
-
const recentMemories = db.prepare(
|
|
54
|
-
`SELECT id, content, summary, importance, pinned, created_at
|
|
55
|
-
FROM memories
|
|
56
|
-
WHERE agent_id = ? AND namespace = ?
|
|
57
|
-
ORDER BY created_at DESC LIMIT 5`
|
|
58
|
-
).all(agentId, namespace);
|
|
59
|
-
|
|
60
|
-
// Importance distribution
|
|
61
|
-
const importanceBuckets = db.prepare(
|
|
62
|
-
`SELECT
|
|
63
|
-
ROUND(importance, 1) as bucket,
|
|
64
|
-
COUNT(*) as n
|
|
65
|
-
FROM memories
|
|
66
|
-
WHERE agent_id = ? AND namespace = ?
|
|
67
|
-
GROUP BY bucket ORDER BY bucket DESC`
|
|
68
|
-
).all(agentId, namespace);
|
|
69
|
-
|
|
70
|
-
// REM stats
|
|
71
|
-
const remStats = (() => {
|
|
72
|
-
try {
|
|
73
|
-
return db.prepare(
|
|
74
|
-
`SELECT COUNT(*) as dreams,
|
|
75
|
-
MAX(ran_at) as last_run,
|
|
76
|
-
SUM(fragments_in) as total_fragments_in,
|
|
77
|
-
SUM(fragments_out) as total_fragments_out
|
|
78
|
-
FROM rem_log WHERE agent_id = ? AND namespace = ?`
|
|
79
|
-
).get(agentId, namespace);
|
|
80
|
-
} catch {
|
|
81
|
-
return { dreams: 0, last_run: null, total_fragments_in: 0, total_fragments_out: 0 };
|
|
82
|
-
}
|
|
83
|
-
})();
|
|
84
|
-
|
|
85
|
-
// AUDN stats
|
|
86
|
-
const audnStats = (() => {
|
|
87
|
-
try {
|
|
88
|
-
return db.prepare(
|
|
89
|
-
`SELECT
|
|
90
|
-
IFNULL(SUM(CASE WHEN action='ADD' THEN 1 ELSE 0 END), 0) as added,
|
|
91
|
-
IFNULL(SUM(CASE WHEN action='UPDATE' THEN 1 ELSE 0 END), 0) as updated,
|
|
92
|
-
IFNULL(SUM(CASE WHEN action='DELETE' THEN 1 ELSE 0 END), 0) as deleted,
|
|
93
|
-
IFNULL(SUM(CASE WHEN action='NO_OP' THEN 1 ELSE 0 END), 0) as skipped
|
|
94
|
-
FROM audn_log WHERE agent_id = ? AND namespace = ?`
|
|
95
|
-
).get(agentId, namespace);
|
|
96
|
-
} catch {
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
})();
|
|
100
|
-
|
|
101
|
-
// Namespace list (across all agents — useful for multi-namespace setups)
|
|
102
|
-
const namespaces = db.prepare(
|
|
103
|
-
`SELECT namespace, COUNT(*) as memories
|
|
104
|
-
FROM memories WHERE agent_id = ?
|
|
105
|
-
GROUP BY namespace ORDER BY memories DESC`
|
|
106
|
-
).all(agentId);
|
|
107
|
-
|
|
108
|
-
// Oldest and newest memory
|
|
109
|
-
const oldest = db.prepare(
|
|
110
|
-
`SELECT id, content, created_at FROM memories
|
|
111
|
-
WHERE agent_id = ? AND namespace = ? ORDER BY created_at ASC LIMIT 1`
|
|
112
|
-
).get(agentId, namespace);
|
|
113
|
-
|
|
114
|
-
const newest = db.prepare(
|
|
115
|
-
`SELECT id, content, created_at FROM memories
|
|
116
|
-
WHERE agent_id = ? AND namespace = ? ORDER BY created_at DESC LIMIT 1`
|
|
117
|
-
).get(agentId, namespace);
|
|
118
|
-
|
|
119
|
-
// Health score — simple heuristic
|
|
120
|
-
const compressionRatio = remStats?.total_fragments_in > 0
|
|
121
|
-
? (remStats.total_fragments_out / remStats.total_fragments_in).toFixed(2)
|
|
122
|
-
: null;
|
|
123
|
-
|
|
124
|
-
const avgImportance = db.prepare(
|
|
125
|
-
`SELECT AVG(importance) as avg FROM memories WHERE agent_id = ? AND namespace = ?`
|
|
126
|
-
).get(agentId, namespace).avg;
|
|
127
|
-
|
|
128
|
-
return {
|
|
129
|
-
agent_id: agentId,
|
|
130
|
-
namespace,
|
|
131
|
-
snapshot_at: new Date().toISOString(),
|
|
132
|
-
|
|
133
|
-
counts: {
|
|
134
|
-
memories: memoryCount,
|
|
135
|
-
pinned: pinnedCount,
|
|
136
|
-
edges: edgeCount,
|
|
137
|
-
namespaces: namespaces.length
|
|
138
|
-
},
|
|
139
|
-
|
|
140
|
-
graph: {
|
|
141
|
-
edgeTypes,
|
|
142
|
-
topNodes: topNodes.map(n => ({
|
|
143
|
-
id: n.id,
|
|
144
|
-
preview: (n.summary || n.content || '').slice(0, 80),
|
|
145
|
-
importance: n.importance,
|
|
146
|
-
connections: n.connections,
|
|
147
|
-
pinned: !!n.pinned
|
|
148
|
-
}))
|
|
149
|
-
},
|
|
150
|
-
|
|
151
|
-
timeline: {
|
|
152
|
-
oldest: oldest ? { id: oldest.id, preview: oldest.content?.slice(0, 60), at: oldest.created_at } : null,
|
|
153
|
-
newest: newest ? { id: newest.id, preview: newest.content?.slice(0, 60), at: newest.created_at } : null
|
|
154
|
-
},
|
|
155
|
-
|
|
156
|
-
recent: recentMemories.map(m => ({
|
|
157
|
-
id: m.id,
|
|
158
|
-
preview: (m.summary || m.content || '').slice(0, 80),
|
|
159
|
-
importance: m.importance,
|
|
160
|
-
pinned: !!m.pinned,
|
|
161
|
-
at: m.created_at
|
|
162
|
-
})),
|
|
163
|
-
|
|
164
|
-
importance: {
|
|
165
|
-
avg: avgImportance ? parseFloat(avgImportance.toFixed(3)) : null,
|
|
166
|
-
distribution: importanceBuckets
|
|
167
|
-
},
|
|
168
|
-
|
|
169
|
-
rem: {
|
|
170
|
-
totalDreams: remStats?.dreams || 0,
|
|
171
|
-
lastRun: remStats?.last_run || null,
|
|
172
|
-
compressionRatio,
|
|
173
|
-
fragmentsProcessed: remStats?.total_fragments_in || 0
|
|
174
|
-
},
|
|
175
|
-
|
|
176
|
-
audn: audnStats,
|
|
177
|
-
|
|
178
|
-
namespaces
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Integration into Memory class:
|
|
184
|
-
*
|
|
185
|
-
* inspect() {
|
|
186
|
-
* return inspect(this.db, this.agentId, this.namespace);
|
|
187
|
-
* }
|
|
188
|
-
*
|
|
189
|
-
* Usage:
|
|
190
|
-
* const state = memory.inspect();
|
|
191
|
-
* console.log(state.counts);
|
|
192
|
-
* // → { memories: 247, pinned: 3, edges: 7180, namespaces: 2 }
|
|
193
|
-
*
|
|
194
|
-
* console.log(state.rem.compressionRatio);
|
|
195
|
-
* // → "0.06" (50:1 means ~0.02, 10:1 means 0.1)
|
|
196
|
-
*
|
|
197
|
-
* console.log(state.graph.topNodes[0]);
|
|
198
|
-
* // → { id, preview, importance, connections: 42, pinned: false }
|
|
199
|
-
*/
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
# VEKTOR Slipstream — Mistral Integration
|
|
2
|
-
|
|
3
|
-
Connect Mistral agents (Le Chat, Mistral API, La Plateforme) to persistent
|
|
4
|
-
local memory. Your memory graph runs on your machine — nothing leaves it.
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## How it works
|
|
9
|
-
|
|
10
|
-
```
|
|
11
|
-
Mistral agent
|
|
12
|
-
↓ tool call
|
|
13
|
-
mistral-bridge.js (http://localhost:3847)
|
|
14
|
-
↓ memory ops
|
|
15
|
-
your-agent.db (local SQLite — your machine only)
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
The bridge is a lightweight HTTP server that runs locally. Mistral calls
|
|
19
|
-
`localhost:3847` — your memory never touches any external server.
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
## Setup (60 seconds)
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
# From your project root (after npm install vektor-slipstream):
|
|
27
|
-
node node_modules/vektor-slipstream/mistral/mistral-setup.js
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
The setup script will:
|
|
31
|
-
1. Ask for your Vektor licence key
|
|
32
|
-
2. Validate it against Polar
|
|
33
|
-
3. Save config to `~/.vektor/mistral.config.json`
|
|
34
|
-
4. Start the bridge on port 3847
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
## Add to your Mistral agent
|
|
39
|
-
|
|
40
|
-
After setup, add the tool manifest to your Mistral agent or La Plateforme project.
|
|
41
|
-
The manifest is at:
|
|
42
|
-
|
|
43
|
-
```
|
|
44
|
-
node_modules/vektor-slipstream/mistral/vektor-tool-manifest.json
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
The bridge endpoint is:
|
|
48
|
-
```
|
|
49
|
-
http://localhost:3847/api/v1/mistral/vektor_memoire
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
---
|
|
53
|
-
|
|
54
|
-
## Tool usage
|
|
55
|
-
|
|
56
|
-
**Recall memories:**
|
|
57
|
-
```json
|
|
58
|
-
{
|
|
59
|
-
"action": "recall",
|
|
60
|
-
"query": "user coding preferences",
|
|
61
|
-
"key": "YOUR_LICENCE_KEY",
|
|
62
|
-
"limit": 5
|
|
63
|
-
}
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
**Store a memory:**
|
|
67
|
-
```json
|
|
68
|
-
{
|
|
69
|
-
"action": "remember",
|
|
70
|
-
"content": "User prefers TypeScript over JavaScript",
|
|
71
|
-
"key": "YOUR_LICENCE_KEY"
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
**Response (recall):**
|
|
76
|
-
```json
|
|
77
|
-
{
|
|
78
|
-
"action": "recall",
|
|
79
|
-
"query": "coding preferences",
|
|
80
|
-
"memory_fragments": [
|
|
81
|
-
{ "content": "User prefers TypeScript over JavaScript", "relevance": 0.97, "importance": 2, "id": 1 }
|
|
82
|
-
],
|
|
83
|
-
"count": 1,
|
|
84
|
-
"metadata": { "engine": "VEKTOR_MAGMA_v1.0.5", "auth": "VERIFIED", "local": true }
|
|
85
|
-
}
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
---
|
|
89
|
-
|
|
90
|
-
## Start/stop the bridge
|
|
91
|
-
|
|
92
|
-
```bash
|
|
93
|
-
# Start (foreground — logs visible):
|
|
94
|
-
node node_modules/vektor-slipstream/mistral/mistral-setup.js --start
|
|
95
|
-
|
|
96
|
-
# Start (background):
|
|
97
|
-
# Run setup and choose 'Y' when asked about background mode
|
|
98
|
-
|
|
99
|
-
# Health check:
|
|
100
|
-
curl http://localhost:3847/health
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
---
|
|
104
|
-
|
|
105
|
-
## Environment variables
|
|
106
|
-
|
|
107
|
-
| Variable | Default | Description |
|
|
108
|
-
|---|---|---|
|
|
109
|
-
| `VEKTOR_LICENCE_KEY` | — | Your licence key (alternative to setup prompt) |
|
|
110
|
-
| `VEKTOR_MISTRAL_PORT` | 3847 | Port for the bridge server |
|
|
111
|
-
|
|
112
|
-
---
|
|
113
|
-
|
|
114
|
-
## Separate from other agents
|
|
115
|
-
|
|
116
|
-
Each agent gets its own memory database. The Mistral bridge uses whichever
|
|
117
|
-
`dbPath` you set during setup — completely separate from any LangChain or
|
|
118
|
-
OpenAI agent databases.
|
|
119
|
-
|
|
120
|
-
```js
|
|
121
|
-
// Other agents are unaffected:
|
|
122
|
-
const memory = await createMemory({ agentId: 'my-other-agent', dbPath: './other.db' });
|
|
123
|
-
```
|