vektor-slipstream 1.3.9 → 1.4.1
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/examples/example-claude-mcp.js +173 -609
- package/examples/example-langchain-researcher.js +71 -105
- package/examples/example-openai-assistant.js +56 -167
- package/package.json +2 -2
- package/vektor-cli.js +94 -26
- package/vektor-slipstream.dxt +0 -0
|
@@ -1,656 +1,220 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
2
|
/**
|
|
4
|
-
*
|
|
3
|
+
* example-claude-mcp.js — VEKTOR Slipstream + Claude
|
|
4
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
5
|
+
* Auto-memory: every conversation turn is stored in the MAGMA graph.
|
|
6
|
+
* Claude recalls relevant context before every response.
|
|
7
|
+
* No setup required — memory just works.
|
|
5
8
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* Cloak: cloak_fetch, cloak_render, cloak_diff, cloak_diff_text,
|
|
9
|
-
* cloak_passport, tokens_saved, cloak_fetch_smart,
|
|
10
|
-
* cloak_detect_captcha, cloak_solve_captcha,
|
|
11
|
-
* cloak_identity_create, cloak_identity_use, cloak_identity_list,
|
|
12
|
-
* turbo_quant_stats, turbo_quant_compress
|
|
13
|
-
* Warmup: cloak_warmup_session, cloak_warmup_stats
|
|
14
|
-
* Behav: cloak_inject_behaviour, cloak_behaviour_stats, cloak_load_pattern
|
|
15
|
-
* Pattern: cloak_pattern_stats, cloak_pattern_list, cloak_pattern_prune, cloak_pattern_seed
|
|
9
|
+
* Usage (MCP server for Claude Desktop):
|
|
10
|
+
* node example-claude-mcp.js --mcp
|
|
16
11
|
*
|
|
17
|
-
*
|
|
12
|
+
* Usage (direct chat):
|
|
13
|
+
* ANTHROPIC_API_KEY=sk-ant-... VEKTOR_LICENCE_KEY=... node example-claude-mcp.js
|
|
18
14
|
*/
|
|
19
15
|
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
const IS_MCP = process.argv.includes('--mcp');
|
|
24
|
-
if (!IS_MCP) { require('./example-claude-direct'); return; }
|
|
25
|
-
|
|
26
|
-
// ── Tool definitions ───────────────────────────────────────────────────────────
|
|
27
|
-
|
|
28
|
-
const TOOLS = [
|
|
29
|
-
|
|
30
|
-
// ── Memory tools ──────────────────────────────────────────────────────────────
|
|
31
|
-
{
|
|
32
|
-
name: 'vektor_recall',
|
|
33
|
-
description: 'Search persistent memory. Call before answering anything that might have prior context.',
|
|
34
|
-
inputSchema: {
|
|
35
|
-
type: 'object',
|
|
36
|
-
properties: {
|
|
37
|
-
query: { type: 'string', description: 'What to search for.' },
|
|
38
|
-
top_k: { type: 'integer', description: 'Number of results (default 5).', default: 5 },
|
|
39
|
-
},
|
|
40
|
-
required: ['query'],
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
name: 'vektor_store',
|
|
45
|
-
description: 'Store a fact, preference, or decision in persistent memory.',
|
|
46
|
-
inputSchema: {
|
|
47
|
-
type: 'object',
|
|
48
|
-
properties: {
|
|
49
|
-
content: { type: 'string', description: 'What to remember.' },
|
|
50
|
-
importance: { type: 'number', description: 'Importance 1-5 (default 3).', default: 3 },
|
|
51
|
-
},
|
|
52
|
-
required: ['content'],
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
name: 'vektor_graph',
|
|
57
|
-
description: 'Traverse the memory graph from a concept.',
|
|
58
|
-
inputSchema: {
|
|
59
|
-
type: 'object',
|
|
60
|
-
properties: {
|
|
61
|
-
concept: { type: 'string', description: 'Concept to traverse from.' },
|
|
62
|
-
hops: { type: 'integer', description: 'Graph depth (default 2).', default: 2 },
|
|
63
|
-
},
|
|
64
|
-
required: ['concept'],
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
name: 'vektor_delta',
|
|
69
|
-
description: 'See what changed in memory on a topic.',
|
|
70
|
-
inputSchema: {
|
|
71
|
-
type: 'object',
|
|
72
|
-
properties: {
|
|
73
|
-
topic: { type: 'string', description: 'Topic to check.' },
|
|
74
|
-
days: { type: 'integer', description: 'How many days back (default 7).', default: 7 },
|
|
75
|
-
},
|
|
76
|
-
required: ['topic'],
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
|
|
80
|
-
// ── v1.1 Cloak tools ──────────────────────────────────────────────────────────
|
|
81
|
-
{
|
|
82
|
-
name: 'cloak_fetch',
|
|
83
|
-
description: 'Fetch a URL using stealth headless browser. Returns clean compressed text. Saves tokens vs raw HTML.',
|
|
84
|
-
inputSchema: {
|
|
85
|
-
type: 'object',
|
|
86
|
-
properties: {
|
|
87
|
-
url: { type: 'string' },
|
|
88
|
-
force: { type: 'boolean' },
|
|
89
|
-
limit: { type: 'integer', description: 'Max characters to return' },
|
|
90
|
-
},
|
|
91
|
-
required: ['url'],
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
name: 'cloak_render',
|
|
96
|
-
description: 'Render a page and return computed CSS layout, fonts, and gap analysis.',
|
|
97
|
-
inputSchema: {
|
|
98
|
-
type: 'object',
|
|
99
|
-
properties: {
|
|
100
|
-
url: { type: 'string' },
|
|
101
|
-
selectors: { type: 'array', items: { type: 'string' } },
|
|
102
|
-
mobile: { type: 'boolean' },
|
|
103
|
-
},
|
|
104
|
-
required: ['url'],
|
|
105
|
-
},
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
name: 'cloak_diff',
|
|
109
|
-
description: 'Return what semantically changed on a URL since last fetch.',
|
|
110
|
-
inputSchema: {
|
|
111
|
-
type: 'object',
|
|
112
|
-
properties: { url: { type: 'string' } },
|
|
113
|
-
required: ['url'],
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
name: 'cloak_diff_text',
|
|
118
|
-
description: 'Diff two text strings and return a semantic change summary.',
|
|
119
|
-
inputSchema: {
|
|
120
|
-
type: 'object',
|
|
121
|
-
properties: {
|
|
122
|
-
a: { type: 'string', description: 'Original text' },
|
|
123
|
-
b: { type: 'string', description: 'New text' },
|
|
124
|
-
},
|
|
125
|
-
required: ['a', 'b'],
|
|
126
|
-
},
|
|
127
|
-
},
|
|
128
|
-
{
|
|
129
|
-
name: 'cloak_passport',
|
|
130
|
-
description: 'Read/write to AES-256 encrypted credential vault. Omit value to read.',
|
|
131
|
-
inputSchema: {
|
|
132
|
-
type: 'object',
|
|
133
|
-
properties: {
|
|
134
|
-
key: { type: 'string' },
|
|
135
|
-
value: { type: 'string' },
|
|
136
|
-
},
|
|
137
|
-
required: ['key'],
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
{
|
|
141
|
-
name: 'tokens_saved',
|
|
142
|
-
description: 'Calculate token savings and ROI for a session.',
|
|
143
|
-
inputSchema: {
|
|
144
|
-
type: 'object',
|
|
145
|
-
properties: {
|
|
146
|
-
raw_tokens: { type: 'number' },
|
|
147
|
-
actual_tokens: { type: 'number' },
|
|
148
|
-
agent_id: { type: 'string' },
|
|
149
|
-
provider: { type: 'string' },
|
|
150
|
-
cost_per_1m: { type: 'number' },
|
|
151
|
-
},
|
|
152
|
-
required: ['raw_tokens', 'actual_tokens'],
|
|
153
|
-
},
|
|
154
|
-
},
|
|
155
|
-
|
|
156
|
-
// ── v1.2 Cloak tools ──────────────────────────────────────────────────────────
|
|
157
|
-
{
|
|
158
|
-
name: 'cloak_fetch_smart',
|
|
159
|
-
description: 'Smart fetch — checks llms.txt first, falls back to stealth browser.',
|
|
160
|
-
inputSchema: {
|
|
161
|
-
type: 'object',
|
|
162
|
-
properties: {
|
|
163
|
-
url: { type: 'string' },
|
|
164
|
-
force: { type: 'boolean' },
|
|
165
|
-
skipLlmsCheck: { type: 'boolean' },
|
|
166
|
-
},
|
|
167
|
-
required: ['url'],
|
|
168
|
-
},
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
name: 'cloak_detect_captcha',
|
|
172
|
-
description: 'Navigate to a URL and detect if a CAPTCHA is present.',
|
|
173
|
-
inputSchema: {
|
|
174
|
-
type: 'object',
|
|
175
|
-
properties: { url: { type: 'string' } },
|
|
176
|
-
required: ['url'],
|
|
177
|
-
},
|
|
178
|
-
},
|
|
179
|
-
{
|
|
180
|
-
name: 'cloak_solve_captcha',
|
|
181
|
-
description: 'Detect and solve any CAPTCHA using vision AI. Injects solution automatically.',
|
|
182
|
-
inputSchema: {
|
|
183
|
-
type: 'object',
|
|
184
|
-
properties: {
|
|
185
|
-
url: { type: 'string' },
|
|
186
|
-
provider: { type: 'string', description: '"claude" (default) or "openai"' },
|
|
187
|
-
},
|
|
188
|
-
required: ['url'],
|
|
189
|
-
},
|
|
190
|
-
},
|
|
191
|
-
{
|
|
192
|
-
name: 'cloak_identity_create',
|
|
193
|
-
description: 'Create a persistent browser identity with full fingerprint.',
|
|
194
|
-
inputSchema: {
|
|
195
|
-
type: 'object',
|
|
196
|
-
properties: {
|
|
197
|
-
name: { type: 'string' },
|
|
198
|
-
seed: { type: 'string' },
|
|
199
|
-
},
|
|
200
|
-
required: ['name'],
|
|
201
|
-
},
|
|
202
|
-
},
|
|
203
|
-
{
|
|
204
|
-
name: 'cloak_identity_use',
|
|
205
|
-
description: 'Browse a URL using a saved identity. Maintains cookies across sessions.',
|
|
206
|
-
inputSchema: {
|
|
207
|
-
type: 'object',
|
|
208
|
-
properties: {
|
|
209
|
-
name: { type: 'string' },
|
|
210
|
-
url: { type: 'string' },
|
|
211
|
-
},
|
|
212
|
-
required: ['name', 'url'],
|
|
213
|
-
},
|
|
214
|
-
},
|
|
215
|
-
{
|
|
216
|
-
name: 'cloak_identity_list',
|
|
217
|
-
description: 'List all saved browser identities.',
|
|
218
|
-
inputSchema: { type: 'object', properties: {} },
|
|
219
|
-
},
|
|
220
|
-
{
|
|
221
|
-
name: 'turbo_quant_stats',
|
|
222
|
-
description: 'Show TurboQuant 3-bit compression stats.',
|
|
223
|
-
inputSchema: { type: 'object', properties: {} },
|
|
224
|
-
},
|
|
225
|
-
{
|
|
226
|
-
name: 'turbo_quant_compress',
|
|
227
|
-
description: 'Migrate memory database to TurboQuant 3-bit compressed storage. ~10x size reduction.',
|
|
228
|
-
inputSchema: {
|
|
229
|
-
type: 'object',
|
|
230
|
-
properties: {
|
|
231
|
-
dbPath: { type: 'string' },
|
|
232
|
-
},
|
|
233
|
-
},
|
|
234
|
-
},
|
|
235
|
-
|
|
236
|
-
// ── v1.3 Warmup & Behaviour tools ─────────────────────────────────────────────
|
|
237
|
-
{
|
|
238
|
-
name: 'cloak_warmup_session',
|
|
239
|
-
description: 'Run a session warmup before navigating to a bot-protected URL. Primes reCAPTCHA trust score.',
|
|
240
|
-
inputSchema: {
|
|
241
|
-
type: 'object',
|
|
242
|
-
properties: {
|
|
243
|
-
targetUrl: { type: 'string' },
|
|
244
|
-
identityName: { type: 'string' },
|
|
245
|
-
sites: { type: 'integer', default: 3 },
|
|
246
|
-
dwellMs: { type: 'integer', default: 2500 },
|
|
247
|
-
primeGoogle: { type: 'boolean', default: true },
|
|
248
|
-
visitRoot: { type: 'boolean', default: true },
|
|
249
|
-
customSites: { type: 'array', items: { type: 'string' } },
|
|
250
|
-
},
|
|
251
|
-
required: ['targetUrl'],
|
|
252
|
-
},
|
|
253
|
-
},
|
|
254
|
-
{
|
|
255
|
-
name: 'cloak_warmup_stats',
|
|
256
|
-
description: 'Show warmup strategy details — trust signals, referrer chains, timing.',
|
|
257
|
-
inputSchema: { type: 'object', properties: {} },
|
|
258
|
-
},
|
|
259
|
-
{
|
|
260
|
-
name: 'cloak_inject_behaviour',
|
|
261
|
-
description: 'Inject human-realistic mouse/scroll behaviour into a browser session.',
|
|
262
|
-
inputSchema: {
|
|
263
|
-
type: 'object',
|
|
264
|
-
properties: {
|
|
265
|
-
url: { type: 'string' },
|
|
266
|
-
category: { type: 'string', enum: ['reading', 'form', 'shopping', 'login', 'idle'] },
|
|
267
|
-
patternName: { type: 'string' },
|
|
268
|
-
speedFactor: { type: 'number' },
|
|
269
|
-
synthetic: { type: 'boolean' },
|
|
270
|
-
durationMs: { type: 'integer' },
|
|
271
|
-
},
|
|
272
|
-
required: ['url'],
|
|
273
|
-
},
|
|
274
|
-
},
|
|
275
|
-
{
|
|
276
|
-
name: 'cloak_behaviour_stats',
|
|
277
|
-
description: 'List available behaviour patterns and categories.',
|
|
278
|
-
inputSchema: { type: 'object', properties: {} },
|
|
279
|
-
},
|
|
280
|
-
{
|
|
281
|
-
name: 'cloak_load_pattern',
|
|
282
|
-
description: 'Load a custom behaviour pattern recorded with cloak-recorder-snippet.js.',
|
|
283
|
-
inputSchema: {
|
|
284
|
-
type: 'object',
|
|
285
|
-
properties: {
|
|
286
|
-
name: { type: 'string' },
|
|
287
|
-
pattern: { type: 'string', description: 'JSON string from recorder' },
|
|
288
|
-
save: { type: 'boolean' },
|
|
289
|
-
},
|
|
290
|
-
required: ['name', 'pattern'],
|
|
291
|
-
},
|
|
292
|
-
},
|
|
293
|
-
|
|
294
|
-
// ── v1.4 Pattern store tools ──────────────────────────────────────────────────
|
|
295
|
-
{
|
|
296
|
-
name: 'cloak_pattern_stats',
|
|
297
|
-
description: 'Show self-improving pattern store stats — tier breakdown, win/loss rates.',
|
|
298
|
-
inputSchema: { type: 'object', properties: {} },
|
|
299
|
-
},
|
|
300
|
-
{
|
|
301
|
-
name: 'cloak_pattern_list',
|
|
302
|
-
description: 'List all behaviour patterns with score, tier, wins, and losses.',
|
|
303
|
-
inputSchema: {
|
|
304
|
-
type: 'object',
|
|
305
|
-
properties: {
|
|
306
|
-
tier: { type: 'string', enum: ['elite', 'active', 'probation'] },
|
|
307
|
-
},
|
|
308
|
-
},
|
|
309
|
-
},
|
|
310
|
-
{
|
|
311
|
-
name: 'cloak_pattern_prune',
|
|
312
|
-
description: 'Force prune the pattern store — removes stale and low-scoring patterns.',
|
|
313
|
-
inputSchema: { type: 'object', properties: {} },
|
|
314
|
-
},
|
|
315
|
-
{
|
|
316
|
-
name: 'cloak_pattern_seed',
|
|
317
|
-
description: 'Seed the store with built-in patterns (only runs if store is empty).',
|
|
318
|
-
inputSchema: { type: 'object', properties: {} },
|
|
319
|
-
},
|
|
320
|
-
];
|
|
321
|
-
|
|
322
|
-
// ── Lazy loaders ──────────────────────────────────────────────────────────────
|
|
16
|
+
const { createMemory } = require('vektor-slipstream');
|
|
17
|
+
const readline = require('readline');
|
|
323
18
|
|
|
19
|
+
// ── Memory init ───────────────────────────────────────────────────────────────
|
|
324
20
|
let _memory = null;
|
|
325
21
|
async function getMemory() {
|
|
326
22
|
if (_memory) return _memory;
|
|
327
|
-
const { createMemory } = require('vektor-slipstream');
|
|
328
|
-
const dbPath = process.env.VEKTOR_DB_PATH ||
|
|
329
|
-
path.join(os.homedir(), 'vektor-slipstream-memory.db');
|
|
330
23
|
_memory = await createMemory({
|
|
331
|
-
agentId: 'claude-
|
|
332
|
-
dbPath,
|
|
333
|
-
silent: true,
|
|
24
|
+
agentId: process.env.SLIPSTREAM_AGENT_ID || 'claude-vektor',
|
|
334
25
|
licenceKey: process.env.VEKTOR_LICENCE_KEY,
|
|
26
|
+
dbPath: process.env.VEKTOR_DB_PATH,
|
|
27
|
+
silent: true,
|
|
335
28
|
});
|
|
336
29
|
return _memory;
|
|
337
30
|
}
|
|
338
31
|
|
|
339
|
-
|
|
340
|
-
function
|
|
341
|
-
if
|
|
342
|
-
|
|
343
|
-
|
|
32
|
+
// ── Auto-store: extract memorable facts from a conversation turn ──────────────
|
|
33
|
+
async function autoStore(memory, userMsg, assistantResponse) {
|
|
34
|
+
// Store the user message if it contains memorable content
|
|
35
|
+
const memorable = isMemorableContent(userMsg);
|
|
36
|
+
if (memorable) {
|
|
37
|
+
await memory.remember(userMsg, { importance: memorable.importance }).catch(() => {});
|
|
38
|
+
}
|
|
344
39
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
return _warmup;
|
|
40
|
+
// Store a condensed version of the exchange
|
|
41
|
+
const exchange = `User: ${userMsg.slice(0, 200)} | Assistant: ${assistantResponse.slice(0, 300)}`;
|
|
42
|
+
await memory.remember(exchange, { importance: 2 }).catch(() => {});
|
|
349
43
|
}
|
|
350
44
|
|
|
351
|
-
|
|
352
|
-
function
|
|
353
|
-
|
|
354
|
-
return _behaviour;
|
|
355
|
-
}
|
|
45
|
+
// ── Heuristic: is this content worth storing? ─────────────────────────────────
|
|
46
|
+
function isMemorableContent(text) {
|
|
47
|
+
const t = text.toLowerCase();
|
|
356
48
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
49
|
+
// High importance — preferences, decisions, critical facts
|
|
50
|
+
if (/prefer|always|never|hate|love|my name|i am|i'm a|i work|my project|deadline|important|remember/.test(t)) {
|
|
51
|
+
return { importance: 4 };
|
|
52
|
+
}
|
|
53
|
+
// Medium importance — project details, tech choices, context
|
|
54
|
+
if (/project|build|using|stack|version|deploy|api|database|language|framework|decided|going with/.test(t)) {
|
|
55
|
+
return { importance: 3 };
|
|
56
|
+
}
|
|
57
|
+
// Low importance — general context worth keeping
|
|
58
|
+
if (text.length > 80) {
|
|
59
|
+
return { importance: 2 };
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
361
62
|
}
|
|
362
63
|
|
|
363
|
-
// ──
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
case 'cloak_diff': {
|
|
402
|
-
return await getCloak().cloak_diff(input.url);
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
case 'cloak_diff_text': {
|
|
406
|
-
return getCloak().cloak_diff_text(input.a, input.b);
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
case 'cloak_passport': {
|
|
410
|
-
return { result: getCloak().cloak_passport(input.key, input.value) || null };
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
case 'tokens_saved': {
|
|
414
|
-
return getCloak().tokens_saved({
|
|
415
|
-
raw_tokens: input.raw_tokens,
|
|
416
|
-
actual_tokens: input.actual_tokens,
|
|
417
|
-
agent_id: input.agent_id,
|
|
418
|
-
provider: input.provider,
|
|
419
|
-
cost_per_1m: input.cost_per_1m,
|
|
420
|
-
});
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
case 'cloak_fetch_smart': {
|
|
424
|
-
const result = await getCloak().cloak_fetch_smart(input.url, {
|
|
425
|
-
force: input.force, skipLlmsCheck: input.skipLlmsCheck,
|
|
426
|
-
});
|
|
427
|
-
return { text: result.text, tokens_saved: result.tokensSaved, from_cache: result.fromCache, source: result.source, llms_friendly: result.llmsFriendly };
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
case 'cloak_detect_captcha': {
|
|
431
|
-
const { captcha } = getCloak();
|
|
432
|
-
const { chromium } = require('playwright');
|
|
433
|
-
let browser;
|
|
434
|
-
try {
|
|
435
|
-
browser = await chromium.launch({ headless: true });
|
|
436
|
-
const page = await browser.newPage();
|
|
437
|
-
await page.goto(input.url, { waitUntil: 'domcontentloaded', timeout: 20000 });
|
|
438
|
-
const detected = await captcha.detectCaptcha(page);
|
|
439
|
-
return detected || { found: false };
|
|
440
|
-
} finally {
|
|
441
|
-
if (browser) await browser.close().catch(() => {});
|
|
64
|
+
// ── MCP Server mode ───────────────────────────────────────────────────────────
|
|
65
|
+
if (process.argv.includes('--mcp')) {
|
|
66
|
+
const TOOLS = [
|
|
67
|
+
{
|
|
68
|
+
name: 'vektor_recall',
|
|
69
|
+
description: 'Search persistent memory for relevant context. Call before answering anything that might have prior context.',
|
|
70
|
+
inputSchema: { type: 'object', properties: { query: { type: 'string' }, top_k: { type: 'integer', default: 5 } }, required: ['query'] },
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: 'vektor_store',
|
|
74
|
+
description: 'Store a fact, preference, decision, or context in persistent memory.',
|
|
75
|
+
inputSchema: { type: 'object', properties: { content: { type: 'string' }, importance: { type: 'integer', default: 3 } }, required: ['content'] },
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: 'vektor_graph',
|
|
79
|
+
description: 'Traverse the associative memory graph to find connected memories.',
|
|
80
|
+
inputSchema: { type: 'object', properties: { topic: { type: 'string' }, depth: { type: 'integer', default: 2 } }, required: ['topic'] },
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: 'vektor_delta',
|
|
84
|
+
description: 'See what changed in memory on a topic recently.',
|
|
85
|
+
inputSchema: { type: 'object', properties: { topic: { type: 'string' }, days: { type: 'integer', default: 7 } }, required: ['topic'] },
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: 'vektor_briefing',
|
|
89
|
+
description: 'Generate a briefing summary from recent memories.',
|
|
90
|
+
inputSchema: { type: 'object', properties: {} },
|
|
91
|
+
},
|
|
92
|
+
];
|
|
93
|
+
|
|
94
|
+
async function runTool(name, input) {
|
|
95
|
+
const mem = await getMemory();
|
|
96
|
+
switch (name) {
|
|
97
|
+
case 'vektor_recall': {
|
|
98
|
+
const results = await mem.recall(input.query, input.top_k || 5);
|
|
99
|
+
return { results: (results || []).map(r => ({ id: r.id, content: r.content, score: r.score })) };
|
|
442
100
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
const { captcha } = getCloak();
|
|
447
|
-
const { chromium } = require('playwright');
|
|
448
|
-
let browser;
|
|
449
|
-
try {
|
|
450
|
-
browser = await chromium.launch({ headless: true });
|
|
451
|
-
const page = await browser.newPage();
|
|
452
|
-
await page.goto(input.url, { waitUntil: 'domcontentloaded', timeout: 20000 });
|
|
453
|
-
const detected = await captcha.detectCaptcha(page);
|
|
454
|
-
if (!detected) return { solved: false, reason: 'No CAPTCHA detected' };
|
|
455
|
-
const token = await captcha.solveCaptcha(page, detected, {
|
|
456
|
-
provider: input.provider || 'claude',
|
|
457
|
-
anthropicKey: process.env.ANTHROPIC_API_KEY,
|
|
458
|
-
});
|
|
459
|
-
if (token) {
|
|
460
|
-
await captcha.injectCaptchaSolution(page, detected, token);
|
|
461
|
-
return { solved: true, type: detected.type, token: token.slice ? token.slice(0, 20) + '...' : token };
|
|
462
|
-
}
|
|
463
|
-
return { solved: false, type: detected.type, reason: 'Vision model returned no selection' };
|
|
464
|
-
} finally {
|
|
465
|
-
if (browser) await browser.close().catch(() => {});
|
|
101
|
+
case 'vektor_store': {
|
|
102
|
+
const { id } = await mem.remember(input.content, { importance: input.importance || 3 });
|
|
103
|
+
return { id, stored: true };
|
|
466
104
|
}
|
|
105
|
+
case 'vektor_graph': return await mem.graph(input.topic, input.depth || 2);
|
|
106
|
+
case 'vektor_delta': return await mem.delta(input.topic, input.days || 7);
|
|
107
|
+
case 'vektor_briefing': return { briefing: await mem.briefing() };
|
|
108
|
+
default: throw new Error(`Unknown tool: ${name}`);
|
|
467
109
|
}
|
|
110
|
+
}
|
|
468
111
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
browser = await chromium.launch({ headless: true });
|
|
484
|
-
const context = await browser.newContext({
|
|
485
|
-
viewport: id.profile.viewport, userAgent: id.profile.userAgent,
|
|
486
|
-
timezoneId: id.profile.timezone, locale: id.profile.language,
|
|
487
|
-
});
|
|
488
|
-
await id.applyToContext(context);
|
|
489
|
-
const page = await context.newPage();
|
|
490
|
-
await page.goto(input.url, { waitUntil: 'domcontentloaded', timeout: 30000 });
|
|
491
|
-
const text = await page.evaluate(() => {
|
|
492
|
-
document.querySelectorAll('script,style,nav,footer').forEach(el => el.remove());
|
|
493
|
-
return document.body?.innerText || '';
|
|
494
|
-
});
|
|
495
|
-
await id.saveCookiesFromContext(context);
|
|
496
|
-
id.recordVisit(input.url);
|
|
497
|
-
id.save();
|
|
498
|
-
return { text: text.slice(0, 8000), identity: id.summary, url: input.url };
|
|
499
|
-
} finally {
|
|
500
|
-
if (browser) await browser.close().catch(() => {});
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
case 'cloak_identity_list': {
|
|
505
|
-
const { CloakIdentity } = getCloak();
|
|
506
|
-
return CloakIdentity.list().map(n => CloakIdentity.load(n)?.summary).filter(Boolean);
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
case 'turbo_quant_stats': {
|
|
510
|
-
return getCloak().turboQuant.compressionStats(384);
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
case 'turbo_quant_compress': {
|
|
514
|
-
const { turboQuant } = getCloak();
|
|
515
|
-
const dbPath = input.dbPath || process.env.VEKTOR_DB_PATH ||
|
|
516
|
-
path.join(os.homedir(), 'vektor-slipstream-memory.db');
|
|
517
|
-
const Database = require('better-sqlite3');
|
|
518
|
-
const db = new Database(dbPath);
|
|
519
|
-
const result = turboQuant.migrateDatabase(db);
|
|
520
|
-
db.close();
|
|
521
|
-
return { ...result, dbPath };
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
case 'cloak_warmup_session': {
|
|
525
|
-
const { quickWarmup } = getWarmup();
|
|
526
|
-
let identityProfile = null;
|
|
527
|
-
if (input.identityName) {
|
|
528
|
-
try {
|
|
529
|
-
const { CloakIdentity } = getCloak();
|
|
530
|
-
const id = CloakIdentity.load(input.identityName);
|
|
531
|
-
if (id) identityProfile = id.profile;
|
|
532
|
-
} catch (_) {}
|
|
112
|
+
process.stdin.setEncoding('utf8');
|
|
113
|
+
let buffer = '';
|
|
114
|
+
const send = obj => process.stdout.write(JSON.stringify(obj) + '\n');
|
|
115
|
+
|
|
116
|
+
process.stdin.on('data', async chunk => {
|
|
117
|
+
buffer += chunk;
|
|
118
|
+
const lines = buffer.split('\n');
|
|
119
|
+
buffer = lines.pop();
|
|
120
|
+
for (const line of lines) {
|
|
121
|
+
if (!line.trim()) continue;
|
|
122
|
+
let req;
|
|
123
|
+
try { req = JSON.parse(line); } catch {
|
|
124
|
+
send({ jsonrpc: '2.0', id: null, error: { code: -32700, message: 'Parse error' } });
|
|
125
|
+
continue;
|
|
533
126
|
}
|
|
534
|
-
|
|
535
|
-
sites: input.sites ?? 3, dwellMs: input.dwellMs ?? 2500,
|
|
536
|
-
primeGoogle: input.primeGoogle ?? true, visitRoot: input.visitRoot ?? true,
|
|
537
|
-
customSites: input.customSites || null,
|
|
538
|
-
});
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
case 'cloak_warmup_stats': {
|
|
542
|
-
return getWarmup().warmupStats();
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
case 'cloak_inject_behaviour': {
|
|
546
|
-
const { injectBehaviour, replayPattern, syntheticBrowse } = getBehaviour();
|
|
547
|
-
const { chromium } = require('playwright');
|
|
548
|
-
let browser;
|
|
127
|
+
if (req.method?.startsWith('notifications/')) continue;
|
|
549
128
|
try {
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
129
|
+
switch (req.method) {
|
|
130
|
+
case 'initialize':
|
|
131
|
+
send({ jsonrpc: '2.0', id: req.id, result: {
|
|
132
|
+
protocolVersion: '2024-11-05',
|
|
133
|
+
serverInfo: { name: 'vektor-slipstream', version: '1.3.9' },
|
|
134
|
+
capabilities: { tools: { listChanged: false } },
|
|
135
|
+
}});
|
|
136
|
+
break;
|
|
137
|
+
case 'tools/list':
|
|
138
|
+
send({ jsonrpc: '2.0', id: req.id, result: { tools: TOOLS } });
|
|
139
|
+
break;
|
|
140
|
+
case 'tools/call': {
|
|
141
|
+
const { name, arguments: args } = req.params;
|
|
142
|
+
const result = await runTool(name, args || {});
|
|
143
|
+
send({ jsonrpc: '2.0', id: req.id, result: {
|
|
144
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
145
|
+
isError: false,
|
|
146
|
+
}});
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
default:
|
|
150
|
+
send({ jsonrpc: '2.0', id: req.id, error: { code: -32601, message: `Method not found: ${req.method}` }});
|
|
560
151
|
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
if (browser) await browser.close().catch(() => {});
|
|
152
|
+
} catch(e) {
|
|
153
|
+
send({ jsonrpc: '2.0', id: req.id, error: { code: -32603, message: e.message }});
|
|
564
154
|
}
|
|
565
155
|
}
|
|
156
|
+
});
|
|
157
|
+
process.stdin.on('end', () => process.exit(0));
|
|
158
|
+
process.on('uncaughtException', e => process.stderr.write('[vektor-mcp] ' + e.message + '\n'));
|
|
566
159
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
160
|
+
} else {
|
|
161
|
+
// ── Direct chat mode with auto-memory ───────────────────────────────────────
|
|
162
|
+
const Anthropic = require('@anthropic-ai/sdk');
|
|
570
163
|
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
const result = loadCustomPattern(input.name, data);
|
|
576
|
-
if (input.save !== false) { try { saveCustomPattern(input.name); } catch (_) {} }
|
|
577
|
-
return result;
|
|
578
|
-
}
|
|
164
|
+
async function main() {
|
|
165
|
+
const memory = await getMemory();
|
|
166
|
+
const client = new Anthropic();
|
|
167
|
+
const messages = [];
|
|
579
168
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
ps.seedBuiltins();
|
|
583
|
-
return ps.storeStats();
|
|
584
|
-
}
|
|
169
|
+
// Morning briefing
|
|
170
|
+
const brief = await memory.briefing().catch(() => '');
|
|
585
171
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
172
|
+
const systemPrompt = [
|
|
173
|
+
'You are a helpful assistant with persistent memory via VEKTOR Slipstream.',
|
|
174
|
+
'Your memory persists across all sessions — you remember everything.',
|
|
175
|
+
brief ? `\nMEMORY BRIEFING (last 24h):\n${brief}` : '',
|
|
176
|
+
'\nWhen the user shares preferences, decisions, or important facts — they are automatically remembered.',
|
|
177
|
+
'Recall relevant context before answering. Store important new facts as they arise.',
|
|
178
|
+
].filter(Boolean).join('\n');
|
|
589
179
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
}
|
|
180
|
+
console.log('\n🧠 VEKTOR Memory active — all conversations stored in MAGMA graph');
|
|
181
|
+
console.log('Type your message (Ctrl+C to exit)\n');
|
|
593
182
|
|
|
594
|
-
|
|
595
|
-
return getPatternStore().seedBuiltins();
|
|
596
|
-
}
|
|
183
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
597
184
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
}
|
|
601
|
-
}
|
|
185
|
+
const ask = () => rl.question('You: ', async userInput => {
|
|
186
|
+
if (!userInput.trim()) return ask();
|
|
602
187
|
|
|
603
|
-
//
|
|
188
|
+
// Auto-recall before responding
|
|
189
|
+
const recalled = await memory.recall(userInput, 5).catch(() => []);
|
|
190
|
+
const context = recalled.length
|
|
191
|
+
? '\n\nRELEVANT MEMORY:\n' + recalled.map(r => `- ${r.content} (score: ${r.score?.toFixed(2)})`).join('\n')
|
|
192
|
+
: '';
|
|
604
193
|
|
|
605
|
-
|
|
606
|
-
let buf = '';
|
|
194
|
+
messages.push({ role: 'user', content: userInput + context });
|
|
607
195
|
|
|
608
|
-
|
|
196
|
+
try {
|
|
197
|
+
const res = await client.messages.create({
|
|
198
|
+
model: 'claude-opus-4-5',
|
|
199
|
+
max_tokens: 1024,
|
|
200
|
+
system: systemPrompt,
|
|
201
|
+
messages,
|
|
202
|
+
});
|
|
609
203
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
buf = lines.pop();
|
|
204
|
+
const reply = res.content[0].text;
|
|
205
|
+
console.log(`\nClaude: ${reply}\n`);
|
|
206
|
+
messages.push({ role: 'assistant', content: reply });
|
|
614
207
|
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
let req;
|
|
618
|
-
try { req = JSON.parse(line); } catch {
|
|
619
|
-
send({ jsonrpc: '2.0', id: null, error: { code: -32700, message: 'Parse error' } });
|
|
620
|
-
continue;
|
|
621
|
-
}
|
|
622
|
-
if (!req || typeof req.method !== 'string') continue;
|
|
623
|
-
if (req.method.startsWith('notifications/')) continue;
|
|
624
|
-
if (!('id' in req)) continue;
|
|
208
|
+
// Auto-store the exchange into MAGMA graph
|
|
209
|
+
await autoStore(memory, userInput, reply);
|
|
625
210
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
send({ jsonrpc: '2.0', id: req.id, result: {
|
|
629
|
-
protocolVersion: '2025-11-25',
|
|
630
|
-
serverInfo: { name: 'vektor-slipstream', version: '1.2.0' },
|
|
631
|
-
capabilities: { tools: {} },
|
|
632
|
-
}});
|
|
633
|
-
getMemory().catch(e => process.stderr.write('[vektor-mcp] Memory init: ' + e.message + '\n'));
|
|
634
|
-
continue;
|
|
211
|
+
} catch (err) {
|
|
212
|
+
console.error('API error:', err.message);
|
|
635
213
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
}
|
|
640
|
-
if (req.method === 'tools/call') {
|
|
641
|
-
const { name, arguments: args } = req.params;
|
|
642
|
-
const result = await runTool(name, args || {});
|
|
643
|
-
send({ jsonrpc: '2.0', id: req.id, result: {
|
|
644
|
-
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }]
|
|
645
|
-
}});
|
|
646
|
-
continue;
|
|
647
|
-
}
|
|
648
|
-
send({ jsonrpc: '2.0', id: req.id, error: { code: -32601, message: 'Method not found' } });
|
|
649
|
-
} catch (e) {
|
|
650
|
-
process.stderr.write('[vektor-mcp] Error: ' + e.message + '\n');
|
|
651
|
-
send({ jsonrpc: '2.0', id: req.id, error: { code: -32603, message: e.message } });
|
|
652
|
-
}
|
|
214
|
+
|
|
215
|
+
ask();
|
|
216
|
+
});
|
|
653
217
|
}
|
|
654
|
-
});
|
|
655
218
|
|
|
656
|
-
|
|
219
|
+
main().catch(console.error);
|
|
220
|
+
}
|