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.
Files changed (56) hide show
  1. package/README.md +67 -306
  2. package/package.json +14 -146
  3. package/CHANGELOG.md +0 -139
  4. package/LICENSE +0 -33
  5. package/TENETS.md +0 -189
  6. package/audn-log.js +0 -143
  7. package/axon.js +0 -389
  8. package/boot-patch.js +0 -33
  9. package/boot-screen.html +0 -210
  10. package/briefing.js +0 -150
  11. package/cerebellum.js +0 -439
  12. package/cloak-behaviour.js +0 -596
  13. package/cloak-captcha.js +0 -541
  14. package/cloak-core.js +0 -499
  15. package/cloak-identity.js +0 -484
  16. package/cloak-index.js +0 -261
  17. package/cloak-llms.js +0 -163
  18. package/cloak-pattern-store.js +0 -471
  19. package/cloak-recorder-auto.js +0 -297
  20. package/cloak-recorder-snippet.js +0 -119
  21. package/cloak-turbo-quant.js +0 -357
  22. package/cloak-warmup.js +0 -240
  23. package/cortex.js +0 -221
  24. package/detect-hardware.js +0 -181
  25. package/entity-resolver.js +0 -298
  26. package/errors.js +0 -66
  27. package/examples/example-claude-mcp.js +0 -220
  28. package/examples/example-langchain-researcher.js +0 -82
  29. package/examples/example-openai-assistant.js +0 -84
  30. package/examples/examples-README.md +0 -161
  31. package/export-import.js +0 -221
  32. package/forget.js +0 -148
  33. package/inspect.js +0 -199
  34. package/mistral/README-mistral.md +0 -123
  35. package/mistral/mistral-bridge.js +0 -218
  36. package/mistral/mistral-setup.js +0 -220
  37. package/mistral/vektor-tool-manifest.json +0 -41
  38. package/models/model_quantized.onnx +0 -0
  39. package/models/vocab.json +0 -1
  40. package/namespace.js +0 -186
  41. package/pin.js +0 -91
  42. package/slipstream-core-extended.js +0 -134
  43. package/slipstream-core.js +0 -1
  44. package/slipstream-db.js +0 -140
  45. package/slipstream-embedder.js +0 -338
  46. package/sovereign.js +0 -142
  47. package/token.js +0 -322
  48. package/types/index.d.ts +0 -269
  49. package/vektor-banner-loader.js +0 -109
  50. package/vektor-cli.js +0 -259
  51. package/vektor-licence-prompt.js +0 -128
  52. package/vektor-licence.js +0 -192
  53. package/vektor-setup.js +0 -270
  54. package/vektor-slipstream.dxt +0 -0
  55. package/vektor-tui.js +0 -373
  56. package/visualize.js +0 -235
package/vektor-setup.js DELETED
@@ -1,270 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
- /**
4
- * vektor-setup.js — VEKTOR Slipstream First-Run Wizard
5
- * ─────────────────────────────────────────────────────────────────────────────
6
- * Guides the user through:
7
- * 1. Licence activation
8
- * 2. Hardware detection
9
- * 3. Memory engine test
10
- * 4. Integration setup (Claude MCP, LangChain, OpenAI, Mistral)
11
- * 5. Optional Playwright install for Cloak
12
- * ─────────────────────────────────────────────────────────────────────────────
13
- */
14
-
15
- const readline = require('readline');
16
- const { execSync, spawn } = require('child_process');
17
- const path = require('path');
18
- const os = require('os');
19
- const fs = require('fs');
20
-
21
- const PKG = require('./package.json');
22
-
23
- // ── Colours ───────────────────────────────────────────────────────────────────
24
- const C = {
25
- reset: '\x1b[0m', cyan: '\x1b[36m', green: '\x1b[32m',
26
- yellow: '\x1b[33m', red: '\x1b[31m', dim: '\x1b[2m', bold: '\x1b[1m',
27
- };
28
- const cyan = s => C.cyan + s + C.reset;
29
- const green = s => C.green + s + C.reset;
30
- const yellow = s => C.yellow + s + C.reset;
31
- const red = s => C.red + s + C.reset;
32
- const dim = s => C.dim + s + C.reset;
33
- const bold = s => C.bold + s + C.reset;
34
-
35
- function ask(question) {
36
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
37
- return new Promise(resolve => rl.question(question, ans => { rl.close(); resolve(ans.trim()); }));
38
- }
39
-
40
- function askYN(question) {
41
- return ask(question + ' [y/n] › ').then(a => a.toLowerCase().startsWith('y'));
42
- }
43
-
44
- function step(n, total, label) {
45
- console.log(`\n${cyan(`[${n}/${total}]`)} ${bold(label)}`);
46
- }
47
-
48
- function ok(msg) { console.log(green(' ✓ ') + msg); }
49
- function warn(msg) { console.log(yellow(' ⚠ ') + msg); }
50
- function info(msg) { console.log(dim(' → ') + msg); }
51
- function fail(msg) { console.log(red(' ✗ ') + msg); }
52
-
53
- // ── Main wizard ───────────────────────────────────────────────────────────────
54
-
55
- async function main() {
56
- console.log('');
57
- console.log(cyan(' ╔══════════════════════════════════════════════════════╗'));
58
- console.log(cyan(' ║') + bold(' VEKTOR SLIPSTREAM — SETUP WIZARD ') + cyan('║'));
59
- console.log(cyan(' ╚══════════════════════════════════════════════════════╝'));
60
- console.log(dim(` v${PKG.version} · vektormemory.com\n`));
61
- console.log(' Welcome. This wizard will get VEKTOR running in under 5 minutes.');
62
- console.log(dim(' Press Ctrl+C at any time to exit.\n'));
63
-
64
- const TOTAL = 5;
65
-
66
- // ── Step 1: Licence ─────────────────────────────────────────────────────────
67
- step(1, TOTAL, 'Licence Activation');
68
-
69
- let licenceKey = process.env.VEKTOR_LICENCE_KEY;
70
-
71
- if (licenceKey) {
72
- ok(`VEKTOR_LICENCE_KEY is set in environment`);
73
- } else {
74
- // Check cache
75
- const cacheFile = path.join(os.homedir(), '.vektor', 'licence.json');
76
- if (fs.existsSync(cacheFile)) {
77
- ok('Licence cache found — already activated on this machine');
78
- } else {
79
- console.log('');
80
- console.log(' Paste your licence key from your Polar purchase email.');
81
- console.log(dim(' Purchase at: https://vektormemory.com/product#pricing\n'));
82
-
83
- try {
84
- const { resolveAndValidateLicence } = require('./vektor-licence-prompt');
85
- const { validateLicence } = require('./vektor-licence');
86
- await resolveAndValidateLicence(validateLicence);
87
- ok('Licence activated and cached');
88
- } catch (e) {
89
- fail('Licence activation failed: ' + e.message);
90
- console.log(dim('\n You can retry with: npx vektor activate'));
91
- process.exit(1);
92
- }
93
- }
94
- }
95
-
96
- // ── Step 2: Hardware detection ───────────────────────────────────────────────
97
- step(2, TOTAL, 'Hardware Detection');
98
-
99
- const platform = os.platform();
100
- const arch = os.arch();
101
- info(`Platform: ${platform} / ${arch}`);
102
-
103
- let accelerator = 'CPU';
104
- if (platform === 'darwin' && arch === 'arm64') {
105
- accelerator = 'Apple Silicon (CoreML)';
106
- ok('Apple Silicon detected — CoreML acceleration available');
107
- } else {
108
- // Check for CUDA
109
- try {
110
- execSync('nvidia-smi', { stdio: 'ignore' });
111
- accelerator = 'NVIDIA CUDA';
112
- ok('NVIDIA GPU detected — CUDA acceleration available');
113
- } catch {
114
- ok(`CPU mode — embeddings will use hash-projection (<1ms) until @xenova/transformers loads`);
115
- info('For full semantic embeddings: npm install @xenova/transformers');
116
- }
117
- }
118
-
119
- // ── Step 3: Memory test ──────────────────────────────────────────────────────
120
- step(3, TOTAL, 'Memory Engine Test');
121
-
122
- try {
123
- const { createMemory } = require('./slipstream-core');
124
- info('Booting memory engine...');
125
-
126
- const memory = await createMemory({
127
- agentId: 'setup-test',
128
- dbPath: './vektor-setup-test.db',
129
- silent: true,
130
- licenceKey: process.env.VEKTOR_LICENCE_KEY,
131
- });
132
-
133
- ok('Memory engine booted');
134
-
135
- const { id } = await memory.remember('VEKTOR setup test — system is working');
136
- ok(`Memory store works (id: ${id})`);
137
-
138
- const results = await memory.recall('setup test working', 3);
139
- ok(`Memory recall works (${results.length} result${results.length === 1 ? '' : 's'})`);
140
-
141
- try { fs.unlinkSync('./vektor-setup-test.db'); } catch (_) {}
142
- ok('Test complete — memory engine is healthy');
143
-
144
- } catch (e) {
145
- fail('Memory engine error: ' + e.message);
146
- if (e.message.includes('better-sqlite3')) {
147
- warn('SQLite binary mismatch — run: npm rebuild better-sqlite3');
148
- }
149
- process.exit(1);
150
- }
151
-
152
- // ── Step 4: Integrations ─────────────────────────────────────────────────────
153
- step(4, TOTAL, 'Integration Setup');
154
-
155
- console.log('');
156
- console.log(' Which integrations do you want to set up?');
157
- console.log(dim(' (You can set these up later with: npx vektor help)\n'));
158
-
159
- // Claude MCP
160
- const setupMcp = await askYN(' Claude Desktop MCP server?');
161
- if (setupMcp) {
162
- const mcpScript = path.join(__dirname, 'examples', 'example-claude-mcp.js');
163
- const configPath = path.join(os.homedir(),
164
- process.platform === 'win32' ? 'AppData/Roaming/Claude/claude_desktop_config.json' :
165
- process.platform === 'darwin' ? 'Library/Application Support/Claude/claude_desktop_config.json' :
166
- '.config/Claude/claude_desktop_config.json'
167
- );
168
-
169
- console.log('');
170
- info('Add this to your claude_desktop_config.json:');
171
- console.log('');
172
- console.log(cyan(' {'));
173
- console.log(cyan(' "mcpServers": {'));
174
- console.log(cyan(' "slipstream": {'));
175
- console.log(cyan(' "command": "node",'));
176
- console.log(cyan(` "args": ["${mcpScript.replace(/\\/g, '/')}", "--mcp"],`));
177
- console.log(cyan(' "env": {'));
178
- console.log(cyan(` "VEKTOR_LICENCE_KEY": "${process.env.VEKTOR_LICENCE_KEY || 'YOUR-KEY-HERE'}"`));
179
- console.log(cyan(' }'));
180
- console.log(cyan(' }'));
181
- console.log(cyan(' }'));
182
- console.log(cyan(' }'));
183
- console.log('');
184
-
185
- if (fs.existsSync(configPath)) {
186
- info(`Config file found at: ${configPath}`);
187
- const autoAdd = await askYN(' Auto-add to config?');
188
- if (autoAdd) {
189
- try {
190
- let config = {};
191
- try { config = JSON.parse(fs.readFileSync(configPath, 'utf8')); } catch (_) {}
192
- if (!config.mcpServers) config.mcpServers = {};
193
- config.mcpServers.slipstream = {
194
- command: 'node',
195
- args: [mcpScript.replace(/\\/g, '/'), '--mcp'],
196
- env: { VEKTOR_LICENCE_KEY: process.env.VEKTOR_LICENCE_KEY || '' },
197
- };
198
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
199
- ok('Added to claude_desktop_config.json — restart Claude Desktop');
200
- } catch (e) {
201
- warn('Could not auto-add: ' + e.message);
202
- info('Add manually using the JSON above');
203
- }
204
- }
205
- } else {
206
- info(`Config not found at expected path — add manually`);
207
- }
208
- }
209
-
210
- // Mistral
211
- const setupMistral = await askYN(' Mistral / Le Chat integration?');
212
- if (setupMistral) {
213
- const mistralSetup = path.join(__dirname, 'mistral', 'mistral-setup.js');
214
- if (fs.existsSync(mistralSetup)) {
215
- info('Run: node ' + mistralSetup);
216
- ok('Mistral bridge is included in the package');
217
- } else {
218
- warn('Mistral setup script not found in package');
219
- }
220
- }
221
-
222
- // Playwright / Cloak
223
- const setupCloak = await askYN(' Cloak browser tools (cloak_fetch, cloak_render)?');
224
- if (setupCloak) {
225
- try {
226
- require('playwright');
227
- ok('Playwright already installed');
228
- } catch (_) {
229
- info('Installing Playwright...');
230
- try {
231
- execSync('npm install playwright', { stdio: 'inherit' });
232
- execSync('npx playwright install chromium', { stdio: 'inherit' });
233
- ok('Playwright installed — cloak_fetch and cloak_render are ready');
234
- } catch (e) {
235
- warn('Playwright install failed: ' + e.message);
236
- info('Try manually: npm install playwright && npx playwright install chromium');
237
- }
238
- }
239
- }
240
-
241
- // ── Step 5: Done ─────────────────────────────────────────────────────────────
242
- step(5, TOTAL, 'Setup Complete');
243
-
244
- console.log('');
245
- console.log(green(' VEKTOR Slipstream is ready.\n'));
246
- console.log(' Quick start:\n');
247
- console.log(dim(' const { createMemory } = require(\'vektor-slipstream\');'));
248
- console.log(dim(' const memory = await createMemory({ agentId: \'my-agent\' });'));
249
- console.log(dim(' await memory.remember(\'User prefers TypeScript\');'));
250
- console.log(dim(' const ctx = await memory.recall(\'coding preferences\');'));
251
- console.log('');
252
- console.log(' Commands:');
253
- console.log(` ${cyan('npx vektor chat')} — persistent memory chat (Claude, Ollama, GPT, Groq, Gemini)`);
254
- console.log(` ${cyan('npx vektor remember')} — store a fact: npx vektor remember "I prefer TypeScript"`);
255
- console.log(` ${cyan('npx vektor ask')} — query memory: npx vektor ask "what stack am I using?"`);
256
- console.log(` ${cyan('npx vektor agent')} — autonomous goal executor`);
257
- console.log(` ${cyan('npx vektor status')} — check system health`);
258
- console.log(` ${cyan('npx vektor test')} — run memory test`);
259
- console.log(` ${cyan('npx vektor mcp')} — start Claude MCP server`);
260
- console.log(` ${cyan('npx vektor help')} — all commands`);
261
- console.log('');
262
- console.log(dim(' Docs: https://vektormemory.com/docs'));
263
- console.log(dim(' Support: hello@vektormemory.com'));
264
- console.log('');
265
- }
266
-
267
- main().catch(e => {
268
- console.error(red('\n Setup error: ') + e.message);
269
- process.exit(1);
270
- });
Binary file
package/vektor-tui.js DELETED
@@ -1,373 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
-
4
- let blessed;
5
- try { blessed = require('blessed'); } catch(e) {
6
- require('child_process').execSync('npm install blessed --prefix ' + __dirname, {stdio:'inherit'});
7
- blessed = require('blessed');
8
- }
9
-
10
- const path = require('path');
11
- const os = require('os');
12
- let PKG; try { PKG = require('./package.json'); } catch(_) { PKG = {version:'1.1.13'}; }
13
-
14
- // ── palette — xterm-256 codes, work on Windows Terminal ──────────────────────
15
- // blessed accepts these as numbers 0-255
16
- const C = {
17
- bg: 0, // black
18
- bg2: 235, // very dark grey
19
- orange: 208, // orange
20
- amber: 214, // gold/amber
21
- cream: 223, // warm cream
22
- cream2: 180, // muted tan
23
- dim: 240, // mid grey
24
- bord: 242, // visible grey border
25
- bord2: 238, // subtle inner border
26
- green: 114, // sage green
27
- teal: 39, // bright cyan-blue
28
- coral: 203, // coral red
29
- gold: 172, // dark amber/gold
30
- white: 230, // near white cream
31
- };
32
-
33
- // type colour map
34
- function typeColor(et) {
35
- return { semantic: C.teal, causal: C.gold, temporal: C.green, entity: C.coral }[et] || C.dim;
36
- }
37
- function typeLabel(et) {
38
- return { semantic:'SEM', causal:'CAU', temporal:'TMP', entity:'ENT' }[et] || 'MEM';
39
- }
40
-
41
- // ── screen — force 256 colours ────────────────────────────────────────────────
42
- const screen = blessed.screen({
43
- smartCSR: true,
44
- fullUnicode: true,
45
- title: 'VEKTOR SLIPSTREAM',
46
- terminal: 'xterm-256color',
47
- forceUnicode: true,
48
- });
49
-
50
- // ── TOP BAR ───────────────────────────────────────────────────────────────────
51
- const topBar = blessed.box({
52
- top: 0, left: 0, width: '100%', height: 1,
53
- style: { fg: C.orange, bg: C.bg2 },
54
- content: ` ▶ VEKTOR SLIPSTREAM v${PKG.version} sovereign agent memory`,
55
- });
56
- screen.append(topBar);
57
-
58
- // ── LEFT PANEL ────────────────────────────────────────────────────────────────
59
- const leftPanel = blessed.box({
60
- top: 1, left: 0, width: '50%', height: '100%-4',
61
- border: { type: 'line' },
62
- style: {
63
- fg: C.cream, bg: C.bg,
64
- border: { fg: C.bord },
65
- },
66
- scrollable: true, alwaysScroll: true,
67
- keys: true, mouse: true,
68
- tags: false, content: '',
69
- });
70
- screen.append(leftPanel);
71
-
72
- // ── RIGHT PANEL ───────────────────────────────────────────────────────────────
73
- const rightPanel = blessed.box({
74
- top: 1, left: '50%', width: '50%', height: '100%-4',
75
- border: { type: 'line' },
76
- style: {
77
- fg: C.cream, bg: C.bg,
78
- border: { fg: C.bord },
79
- },
80
- scrollable: true, alwaysScroll: true,
81
- keys: true, mouse: true,
82
- tags: false, content: '',
83
- });
84
- screen.append(rightPanel);
85
-
86
- // ── BOTTOM BAR ────────────────────────────────────────────────────────────────
87
- const bottomBar = blessed.box({
88
- bottom: 0, left: 0, width: '100%', height: 3,
89
- border: { type: 'line' },
90
- style: { fg: C.dim, bg: C.bg2, border: { fg: C.bord2 } },
91
- tags: false, content: '',
92
- });
93
- screen.append(bottomBar);
94
-
95
- // ── helpers ───────────────────────────────────────────────────────────────────
96
- function ageLine(ts) {
97
- if (!ts) return '—';
98
- const h = Math.round((Date.now() - (ts * 1000)) / 3600000);
99
- if (h < 1) return 'just now';
100
- if (h < 24) return h + 'h ago';
101
- return Math.round(h/24) + 'd ago';
102
- }
103
- function impDots(imp) {
104
- const n = imp || 1;
105
- let s = '●';
106
- for (let i = 1; i < 5; i++) { s += '──'; s += (i < n) ? '●' : '○'; }
107
- return s;
108
- }
109
- function impBar(imp) {
110
- const n = imp || 1;
111
- return '█'.repeat(n) + '░'.repeat(5 - n);
112
- }
113
-
114
- // ── render left cards ─────────────────────────────────────────────────────────
115
- function renderLeft() {
116
- const W = Math.floor(screen.cols * 0.5) - 4;
117
- const lines = [];
118
-
119
- if (memories.length === 0) {
120
- lines.push('');
121
- lines.push(' no memories yet');
122
- lines.push(' press A to add one');
123
- leftPanel.setContent(lines.join('\n'));
124
- screen.render();
125
- return;
126
- }
127
-
128
- memories.forEach((m, i) => {
129
- const isSel = i === selected;
130
- const arrow = isSel ? '▶' : ' ';
131
- const et = m.edge_type || 'semantic';
132
- const tlabel = typeLabel(et);
133
- const age = ageLine(m.created_at);
134
- const imp = m.importance || 1;
135
- const tstr = m.created_at
136
- ? new Date(m.created_at * 1000).toLocaleTimeString([], {hour:'2-digit',minute:'2-digit'})
137
- : '--:--';
138
- const preview = m.content.replace(/\n/g,' ').slice(0, W - 14);
139
-
140
- if (i > 0) lines.push(' ' + '─'.repeat(W - 2));
141
-
142
- lines.push(`${arrow} [${tlabel}] ${preview}`);
143
- lines.push(` ${impDots(imp)} ${age.padEnd(10)} ${tstr}`);
144
- lines.push('');
145
- });
146
-
147
- leftPanel.setContent(lines.join('\n'));
148
- leftPanel.scrollTo(selected * 4);
149
- screen.render();
150
- }
151
-
152
- // ── render right detail ───────────────────────────────────────────────────────
153
- function renderRight() {
154
- const m = memories[selected];
155
- if (!m) {
156
- rightPanel.setContent('\n\n select a memory to inspect');
157
- screen.render();
158
- return;
159
- }
160
-
161
- const W = Math.floor(screen.cols * 0.5) - 4;
162
- const et = m.edge_type || 'semantic';
163
- const tlabel = typeLabel(et);
164
- const age = ageLine(m.created_at);
165
- const created = m.created_at ? new Date(m.created_at * 1000).toLocaleString() : '—';
166
- const imp = m.importance || 1;
167
- const sameType = memories.filter(x => (x.edge_type||'semantic') === et).length;
168
- const sep = '─'.repeat(W - 2);
169
-
170
- const lines = [
171
- '',
172
- ` [${tlabel}] #${m.id} ${age}`,
173
- '',
174
- ' ' + sep,
175
- '',
176
- ];
177
-
178
- // Word-wrap content
179
- const words = m.content.split(' ');
180
- let line = ' ';
181
- for (const w of words) {
182
- if ((line + w).length > W) { lines.push(line.trimEnd()); line = ' '; }
183
- line += w + ' ';
184
- }
185
- if (line.trim()) lines.push(line.trimEnd());
186
-
187
- lines.push('');
188
- lines.push(' ' + sep);
189
- lines.push('');
190
- lines.push(` IMPORTANCE ${impBar(imp)} ${imp}/5`);
191
- lines.push(` TIMELINE ${impDots(imp)}`);
192
- lines.push('');
193
- lines.push(` CREATED ${created}`);
194
- lines.push(` TYPE POOL ${sameType} of ${memories.length} memories`);
195
-
196
- if (m.tags) lines.push(` TAGS ${m.tags}`);
197
- if (m.summary) {
198
- lines.push(''); lines.push(' ' + sep); lines.push('');
199
- lines.push(' SUMMARY');
200
- const sw = m.summary.split(' ');
201
- let sl = ' ';
202
- for (const w of sw) {
203
- if ((sl+w).length > W) { lines.push(sl.trimEnd()); sl = ' '; }
204
- sl += w + ' ';
205
- }
206
- if (sl.trim()) lines.push(sl.trimEnd());
207
- }
208
-
209
- lines.push(''); lines.push(' ' + sep); lines.push('');
210
- lines.push(' D delete E importance+ B briefing');
211
-
212
- rightPanel.setContent(lines.join('\n'));
213
- screen.render();
214
- }
215
-
216
- // ── render bottom ─────────────────────────────────────────────────────────────
217
- function renderBottom(msg) {
218
- const keys = [
219
- ['↑↓','nav'],['⏎','open'],['A','add'],['D','del'],
220
- ['/','search'],['B','brief'],['T','tab'],['Q','quit'],
221
- ];
222
- const left = keys.map(([k,v]) => ` [${k}] ${v}`).join(' ');
223
- const right = msg ? ` ${msg} ` : ` v${PKG.version} `;
224
- const space = Math.max(1, screen.cols - left.length - right.length - 4);
225
- bottomBar.setContent(left + ' '.repeat(space) + right);
226
- screen.render();
227
- }
228
-
229
- // ── state ─────────────────────────────────────────────────────────────────────
230
- let memory = null, memories = [], selected = 0;
231
-
232
- // ── load ──────────────────────────────────────────────────────────────────────
233
- async function loadMemories(query = '') {
234
- try {
235
- if (query) {
236
- memories = await memory.recall(query, 100);
237
- } else {
238
- memories = memory.db.prepare(
239
- 'SELECT * FROM memories ORDER BY created_at DESC LIMIT 500'
240
- ).all();
241
- }
242
- if (selected >= memories.length) selected = Math.max(0, memories.length - 1);
243
- renderLeft(); renderRight();
244
- renderBottom(`${memories.length} memories`);
245
- } catch(e) {
246
- renderBottom('error: ' + e.message.slice(0,50));
247
- }
248
- }
249
-
250
- // ── input overlay ─────────────────────────────────────────────────────────────
251
- const inputOverlay = blessed.box({
252
- top: 'center', left: 'center', width: '50%', height: 5,
253
- hidden: true,
254
- border: { type: 'line' },
255
- style: { fg: C.cream, bg: C.bg2, border: { fg: C.amber } },
256
- tags: false,
257
- });
258
- const inputField = blessed.textbox({
259
- parent: inputOverlay,
260
- top: 1, left: 1, width: '100%-4', height: 1,
261
- style: { fg: C.orange, bg: C.bg2 },
262
- inputOnFocus: true,
263
- });
264
- screen.append(inputOverlay);
265
-
266
- function showInput(label, cb) {
267
- inputOverlay.setLabel(` ${label} `);
268
- inputField.setValue('');
269
- inputOverlay.show();
270
- screen.render();
271
- inputField.focus();
272
- let buf = '';
273
-
274
- function cleanup() {
275
- screen.removeListener('keypress', onKey);
276
- inputOverlay.hide();
277
- inputField.setValue('');
278
- buf = '';
279
- leftPanel.focus();
280
- screen.render();
281
- }
282
- function onKey(ch, key) {
283
- if (!key) return;
284
- if (key.name === 'enter' || key.name === 'return') {
285
- const val = buf.trim(); cleanup(); if (val) cb(val); return;
286
- }
287
- if (key.name === 'escape') { cleanup(); return; }
288
- if (key.name === 'backspace') {
289
- buf = buf.slice(0,-1); inputField.setValue(buf); screen.render(); return;
290
- }
291
- if (ch && !key.ctrl && !key.meta && ch.length === 1) {
292
- buf += ch; inputField.setValue(buf); screen.render();
293
- }
294
- }
295
- screen.on('keypress', onKey);
296
- }
297
-
298
- // ── actions ───────────────────────────────────────────────────────────────────
299
- async function addMemory(content) {
300
- try {
301
- await memory.remember(content, {importance:3});
302
- renderBottom('saved'); await loadMemories();
303
- } catch(e) { renderBottom('error: ' + e.message.slice(0,50)); }
304
- }
305
-
306
- async function deleteSelected() {
307
- const m = memories[selected]; if (!m) return;
308
- try {
309
- memory.db.prepare('DELETE FROM memories WHERE id=?').run(m.id);
310
- renderBottom('deleted #' + m.id); await loadMemories();
311
- } catch(e) { renderBottom('error: ' + e.message.slice(0,50)); }
312
- }
313
-
314
- async function runRem() {
315
- renderBottom('REM running...');
316
- try { throw new Error("REM not in this build — add dream() to slipstream-core"); }
317
- catch(e) { renderBottom('REM error: ' + e.message.slice(0,40)); }
318
- }
319
-
320
- async function showBriefing() {
321
- try {
322
- const brief = await memory.briefing();
323
- rightPanel.setContent('\n BRIEFING\n ' + '─'.repeat(40) + '\n\n' +
324
- brief.split('\n').map(l => ' ' + l).join('\n'));
325
- screen.render();
326
- } catch(e) { renderBottom('briefing error'); }
327
- }
328
-
329
- // ── keyboard ──────────────────────────────────────────────────────────────────
330
- screen.key(['q','C-c'], () => { screen.destroy(); process.exit(0); });
331
- screen.key(['up','k'], () => { if (selected > 0) { selected--; renderLeft(); renderRight(); }});
332
- screen.key(['down','j'], () => { if (selected < memories.length-1) { selected++; renderLeft(); renderRight(); }});
333
- screen.key(['a'], () => showInput('ADD MEMORY', addMemory));
334
- screen.key(['d'], deleteSelected);
335
- screen.key(['/'], () => showInput('SEARCH', async q => loadMemories(q)));
336
- screen.key(['l'], async () => loadMemories());
337
- screen.key(['r'], runRem);
338
- screen.key(['b'], showBriefing);
339
- screen.key(['tab','t'], () => { screen.focused === leftPanel ? rightPanel.focus() : leftPanel.focus(); screen.render(); });
340
- screen.key(['e'], () => {
341
- const m = memories[selected]; if (!m) return;
342
- m.importance = ((m.importance||1) % 5) + 1;
343
- try { memory.db.prepare('UPDATE memories SET importance=? WHERE id=?').run(m.importance, m.id); } catch(_) {}
344
- renderLeft(); renderRight();
345
- });
346
-
347
- // ── boot ──────────────────────────────────────────────────────────────────────
348
- async function boot() {
349
- const _l = console.log; const _e = console.error;
350
- console.log = console.error = () => {};
351
- renderBottom('connecting...'); renderLeft(); screen.render();
352
-
353
- try {
354
- const {createMemory} = require('./slipstream-core');
355
- const dbPath = process.env.VEKTOR_DB_PATH ||
356
- path.join(os.homedir(), 'vektor-slipstream-memory.db');
357
- memory = await createMemory({
358
- agentId: process.env.VEKTOR_AGENT_ID || 'tui',
359
- dbPath, silent: true,
360
- licenceKey: process.env.VEKTOR_LICENCE_KEY,
361
- });
362
- await loadMemories();
363
- } catch(e) {
364
- rightPanel.setContent('\n boot error: ' + e.message.slice(0,60));
365
- renderLeft(); screen.render();
366
- }
367
-
368
- console.log = _l; console.error = _e;
369
- leftPanel.focus(); screen.render();
370
- setInterval(() => { if (memory) loadMemories(); }, 30000);
371
- }
372
-
373
- boot();