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.
@@ -1,656 +1,220 @@
1
1
  'use strict';
2
-
3
2
  /**
4
- * VEKTOR SLIPSTREAM Claude Desktop MCP Server v1.4
3
+ * example-claude-mcp.jsVEKTOR 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
- * Tools:
7
- * Memory: vektor_recall, vektor_store, vektor_graph, vektor_delta
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
- * Windows-safe: no shebang line (breaks Windows Node.js when invoked directly)
12
+ * Usage (direct chat):
13
+ * ANTHROPIC_API_KEY=sk-ant-... VEKTOR_LICENCE_KEY=... node example-claude-mcp.js
18
14
  */
19
15
 
20
- const path = require('path');
21
- const os = require('os');
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-mcp',
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
- let _cloak = null;
340
- function getCloak() {
341
- if (!_cloak) _cloak = require('vektor-slipstream/cloak');
342
- return _cloak;
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
- let _warmup = null;
346
- function getWarmup() {
347
- if (!_warmup) _warmup = require('vektor-slipstream/cloak-warmup');
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
- let _behaviour = null;
352
- function getBehaviour() {
353
- if (!_behaviour) _behaviour = require('vektor-slipstream/cloak-behaviour');
354
- return _behaviour;
355
- }
45
+ // ── Heuristic: is this content worth storing? ─────────────────────────────────
46
+ function isMemorableContent(text) {
47
+ const t = text.toLowerCase();
356
48
 
357
- let _patternStore = null;
358
- function getPatternStore() {
359
- if (!_patternStore) _patternStore = require('vektor-slipstream/cloak-pattern-store');
360
- return _patternStore;
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
- // ── Tool runner ───────────────────────────────────────────────────────────────
364
-
365
- async function runTool(name, input) {
366
- switch (name) {
367
-
368
- case 'vektor_recall': {
369
- const mem = await getMemory();
370
- const results = await mem.recall(input.query, input.top_k || 5);
371
- return { found: results.length, memories: results.map(r => ({ content: r.content, score: r.score, id: r.id })) };
372
- }
373
-
374
- case 'vektor_store': {
375
- const mem = await getMemory();
376
- const { id } = await mem.remember(input.content, { importance: input.importance || 3 });
377
- return { stored: true, id, content: input.content };
378
- }
379
-
380
- case 'vektor_graph': {
381
- const mem = await getMemory();
382
- const { nodes, edges } = await mem.graph(input.concept, { hops: input.hops || 2 });
383
- return { nodes: nodes.slice(0, 10).map(n => ({ id: n.id, content: n.content })), edge_count: edges.length };
384
- }
385
-
386
- case 'vektor_delta': {
387
- const mem = await getMemory();
388
- const changes = await mem.delta(input.topic, input.days || 7);
389
- return { topic: input.topic, changes: changes.slice(0, 10) };
390
- }
391
-
392
- case 'cloak_fetch': {
393
- const r = await getCloak().cloak_fetch(input.url, { force: input.force, limit: input.limit });
394
- return { text: r.text, tokens_saved: r.tokensSaved, from_cache: r.fromCache };
395
- }
396
-
397
- case 'cloak_render': {
398
- return await getCloak().cloak_render(input.url, input.selectors || [], { mobile: input.mobile });
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
- case 'cloak_solve_captcha': {
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
- case 'cloak_identity_create': {
470
- const { CloakIdentity } = getCloak();
471
- const id = CloakIdentity.create(input.name, input.seed || null);
472
- id.save();
473
- return { created: true, ...id.summary };
474
- }
475
-
476
- case 'cloak_identity_use': {
477
- const { CloakIdentity } = getCloak();
478
- const { chromium } = require('playwright');
479
- const id = CloakIdentity.load(input.name);
480
- if (!id) return { error: `Identity "${input.name}" not found. Create with cloak_identity_create first.` };
481
- let browser;
482
- try {
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
- return await quickWarmup(input.targetUrl, identityProfile, {
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
- browser = await chromium.launch({ headless: true });
551
- const page = await (await browser.newContext()).newPage();
552
- await page.goto(input.url, { waitUntil: 'domcontentloaded', timeout: 30000 });
553
- let result;
554
- if (input.synthetic) {
555
- result = await syntheticBrowse(page, { durationMs: input.durationMs ?? 5000, scrollDepth: 0.6, pauseCount: 3 });
556
- } else if (input.patternName) {
557
- result = await replayPattern(page, input.patternName, { speedFactor: input.speedFactor ?? 1.0 });
558
- } else {
559
- result = await injectBehaviour(page, input.category || 'reading', { speedFactor: input.speedFactor ?? 1.0 });
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
- return { injected: true, url: input.url, ...result };
562
- } finally {
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
- case 'cloak_behaviour_stats': {
568
- return getBehaviour().behaviourStats();
569
- }
160
+ } else {
161
+ // ── Direct chat mode with auto-memory ───────────────────────────────────────
162
+ const Anthropic = require('@anthropic-ai/sdk');
570
163
 
571
- case 'cloak_load_pattern': {
572
- const { loadCustomPattern, saveCustomPattern } = getBehaviour();
573
- let data;
574
- try { data = JSON.parse(input.pattern); } catch (e) { return { error: 'Invalid JSON: ' + e.message }; }
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
- case 'cloak_pattern_stats': {
581
- const ps = getPatternStore();
582
- ps.seedBuiltins();
583
- return ps.storeStats();
584
- }
169
+ // Morning briefing
170
+ const brief = await memory.briefing().catch(() => '');
585
171
 
586
- case 'cloak_pattern_list': {
587
- return getPatternStore().listPatterns(input.tier || null);
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
- case 'cloak_pattern_prune': {
591
- return getPatternStore().pruneNow();
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
- case 'cloak_pattern_seed': {
595
- return getPatternStore().seedBuiltins();
596
- }
183
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
597
184
 
598
- default:
599
- return { error: `Unknown tool: ${name}` };
600
- }
601
- }
185
+ const ask = () => rl.question('You: ', async userInput => {
186
+ if (!userInput.trim()) return ask();
602
187
 
603
- // ── MCP stdio server ──────────────────────────────────────────────────────────
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
- process.stdin.setEncoding('utf8');
606
- let buf = '';
194
+ messages.push({ role: 'user', content: userInput + context });
607
195
 
608
- function send(obj) { process.stdout.write(JSON.stringify(obj) + '\n'); }
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
- process.stdin.on('data', async chunk => {
611
- buf += chunk;
612
- const lines = buf.split('\n');
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
- for (const line of lines) {
616
- if (!line.trim()) continue;
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
- try {
627
- if (req.method === 'initialize') {
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
- if (req.method === 'tools/list') {
637
- send({ jsonrpc: '2.0', id: req.id, result: { tools: TOOLS } });
638
- continue;
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
- process.stdin.resume();
219
+ main().catch(console.error);
220
+ }