vektor-slipstream 1.4.2 → 1.4.4

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 (4) hide show
  1. package/README.md +179 -114
  2. package/package.json +2 -2
  3. package/vektor-cli.js +221 -444
  4. package/vektor-setup.js +270 -266
package/vektor-cli.js CHANGED
@@ -1,482 +1,259 @@
1
- #!/usr/bin/env node
1
+ /**
2
+ * vektor-cli.js (v1.5.x patch)
3
+ * VEKTOR Slipstream
4
+ * CLI router — drop-in replacement for the v1.4.x router.
5
+ *
6
+ * New commands added in v1.5.x:
7
+ * npx vektor agent --tools full tool suite
8
+ * npx vektor watch filesystem watcher
9
+ * npx vektor sync P2P memory sync
10
+ * npx vektor swarm multi-agent coordination
11
+ *
12
+ * All existing v1.4.x commands (chat, remember, ask, agent) are preserved.
13
+ */
14
+
2
15
  'use strict';
3
16
 
4
- const path = require('path');
5
- const os = require('os');
6
- const fs = require('fs');
7
- const PKG = require('./package.json');
8
- const loader = require('./vektor-banner-loader');
9
-
10
- const command = process.argv[2] || 'help';
11
-
12
- // ── Colours ───────────────────────────────────────────────────────────────────
13
-
14
- const C = {
15
- reset: '\x1b[0m',
16
- cyan: '\x1b[36m',
17
- green: '\x1b[32m',
18
- yellow: '\x1b[33m',
19
- red: '\x1b[31m',
20
- dim: '\x1b[2m',
21
- bold: '\x1b[1m',
22
- orange: '\x1b[38;5;214m',
17
+ const path = require('path');
18
+
19
+ // ─── Command registry ─────────────────────────────────────────────────────────
20
+
21
+ const COMMANDS = {
22
+ // ── v1.4.x (existing) ──────────────────────────────────────────────────
23
+ chat: () => require('./vektor-cli-chat.js').runChat,
24
+ remember: () => require('./vektor-cli-chat.js').runRemember,
25
+ ask: () => require('./vektor-cli-chat.js').runAsk,
26
+
27
+ // ── v1.5.x (new) ───────────────────────────────────────────────────────
28
+
29
+ /**
30
+ * npx vektor agent [goal] [--tools web,fs,code] [--continue]
31
+ * Autonomous agent with web search, file system, code execution.
32
+ */
33
+ agent: () => async (argv) => {
34
+ const { default: runAgent, main } = (() => {
35
+ try { return require('./vektor-agent.js'); } catch { return require('../vektor-agent.js'); }
36
+ })();
37
+ // Delegate to vektor-agent CLI main — it reads process.argv
38
+ await main?.() ?? runAgent({
39
+ goal: argv.filter(a => !a.startsWith('-')).join(' '),
40
+ tools: ['web', 'fs', 'code', 'memory'],
41
+ provider: process.env.VEKTOR_PROVIDER || 'ollama',
42
+ });
43
+ },
44
+
45
+ /**
46
+ * npx vektor watch [path] [--ext js,ts] [--no-llm]
47
+ * Filesystem watcher — auto-stores change summaries into MAGMA.
48
+ */
49
+ watch: () => async (_argv) => {
50
+ const { startWatch, parseArgs } = (() => {
51
+ try { return require('./vektor-watch.js'); } catch { return require('../vektor-watch.js'); }
52
+ })();
53
+ const opts = parseArgs(process.argv);
54
+ await startWatch(opts);
55
+ },
56
+
57
+ /**
58
+ * npx vektor sync --host [--pin X]
59
+ * npx vektor sync --connect <ip> [--pin X]
60
+ * Encrypted P2P memory sync between machines.
61
+ */
62
+ sync: () => async (_argv) => {
63
+ const { main } = (() => {
64
+ try { return require('./vektor-sync.js'); } catch { return require('../vektor-sync.js'); }
65
+ })();
66
+ await main?.();
67
+ },
68
+
69
+ /**
70
+ * npx vektor swarm "goal" [--agents 3] [--roles r1,r2,r3]
71
+ * Multi-agent swarm coordination.
72
+ */
73
+ swarm: () => async (_argv) => {
74
+ const { main } = (() => {
75
+ try { return require('./vektor-swarm.js'); } catch { return require('../vektor-swarm.js'); }
76
+ })();
77
+ await main?.();
78
+ },
79
+
80
+ // ── Utility ────────────────────────────────────────────────────────────
81
+
82
+ providers: () => async (_argv) => {
83
+ await checkProviders();
84
+ },
85
+
86
+ version: () => async (_argv) => {
87
+ const pkg = safeRequirePackageJson();
88
+ console.log(`VEKTOR Slipstream v${pkg.version || '1.5.0'}`);
89
+ },
90
+
91
+ help: () => async (_argv) => {
92
+ printHelp();
93
+ },
23
94
  };
24
- const cyan = s => C.cyan + s + C.reset;
25
- const green = s => C.green + s + C.reset;
26
- const yellow = s => C.yellow + s + C.reset;
27
- const red = s => C.red + s + C.reset;
28
- const dim = s => C.dim + s + C.reset;
29
- const bold = s => C.bold + s + C.reset;
30
- const orange = s => C.orange + s + C.reset;
31
-
32
- // Banner is printed automatically by vektor-banner-loader on require
33
-
34
- function printBox() {
35
- loader.complete('Ready');
36
- console.log(cyan(' +------------------------------------------------------+'));
37
- console.log(cyan(' |') + bold(' VEKTOR SLIPSTREAM CLI ') + cyan('|'));
38
- console.log(cyan(' +------------------------------------------------------+'));
39
- console.log(dim(' v' + PKG.version + ' . vektormemory.com'));
40
- console.log('');
41
- }
42
95
 
43
- // ── Help ──────────────────────────────────────────────────────────────────────
96
+ // ─── Provider checker ─────────────────────────────────────────────────────────
44
97
 
45
- async function cmdHelp() {
46
- printBox();
47
- console.log(bold(' MEMORY COMMANDS\n'));
98
+ async function checkProviders() {
99
+ const C = { green: '\x1b[32m', red: '\x1b[31m', dim: '\x1b[2m', reset: '\x1b[0m', bold: '\x1b[1m' };
100
+ console.log(`\n${C.bold}VEKTOR Provider Status${C.reset}\n`);
48
101
 
49
- const memoryCmds = [
50
- ['chat', 'Persistent memory chat all conversations stored in MAGMA graph'],
51
- ['remember', 'Store a fact instantly: npx vektor remember "I prefer TypeScript"'],
52
- ['ask', 'Ask a question using your memory: npx vektor ask "what stack am I using?"'],
53
- ['agent', 'Autonomous goal executor: npx vektor agent "research X and summarise"'],
54
- ['briefing', 'Generate a morning briefing from recent memories'],
55
- ['rem', 'Run the REM dream cycle — compress and consolidate memories'],
56
- ['tui', 'Launch the interactive memory browser (terminal UI)'],
102
+ const checks = [
103
+ { name: 'Claude (Anthropic)', key: 'ANTHROPIC_API_KEY', test: () => testClaude() },
104
+ { name: 'OpenAI', key: 'OPENAI_API_KEY', test: () => testOpenAI() },
105
+ { name: 'Groq', key: 'GROQ_API_KEY', test: () => testGroq() },
106
+ { name: 'Google Gemini', key: 'GEMINI_API_KEY', test: () => testGemini() },
107
+ { name: 'Ollama (local)', key: null, test: () => testOllama() },
57
108
  ];
58
109
 
59
- memoryCmds.forEach(([cmd, desc]) => {
60
- console.log(' ' + cyan(('npx vektor ' + cmd).padEnd(26)) + dim(desc));
61
- });
62
-
63
- console.log('');
64
- console.log(bold(' SYSTEM COMMANDS\n'));
65
-
66
- const sysCmds = [
67
- ['setup', 'First-run wizard — activate licence, test memory, configure integrations'],
68
- ['activate', 'Activate your licence key on this machine'],
69
- ['deactivate', "Free up this machine's activation slot"],
70
- ['status', 'Show licence status, memory stats, and system info'],
71
- ['test', 'Run a quick memory test (remember + recall + briefing)'],
72
- ['mcp', 'Start the Claude MCP server (for Claude Desktop)'],
73
- ['help', 'Show this help message'],
74
- ];
75
-
76
- sysCmds.forEach(([cmd, desc]) => {
77
- console.log(' ' + cyan(('npx vektor ' + cmd).padEnd(26)) + dim(desc));
78
- });
79
-
80
- console.log('');
81
- console.log(bold(' CHAT PROVIDERS\n'));
82
- console.log(' ' + cyan('--provider claude ') + ' ' + dim('Anthropic Claude (ANTHROPIC_API_KEY)'));
83
- console.log(' ' + cyan('--provider openai ') + ' ' + dim('OpenAI GPT (OPENAI_API_KEY)'));
84
- console.log(' ' + cyan('--provider groq ') + ' ' + dim('Groq LLaMA (GROQ_API_KEY)'));
85
- console.log(' ' + cyan('--provider gemini ') + ' ' + dim('Google Gemini (GEMINI_API_KEY)'));
86
- console.log(' ' + cyan('--provider ollama ') + ' ' + dim('Local Ollama (free, ollama serve)'));
87
-
88
- console.log('');
89
- console.log(bold(' ENVIRONMENT\n'));
90
- console.log(' ' + cyan('VEKTOR_LICENCE_KEY') + ' ' + dim('Your Polar licence key'));
91
- console.log(' ' + cyan('VEKTOR_DB_PATH ') + ' ' + dim('Path to memory database (default: ~/vektor-slipstream-memory.db)'));
92
- console.log(' ' + cyan('VEKTOR_PROVIDER ') + ' ' + dim('Default LLM provider (default: ollama)'));
93
- console.log(' ' + cyan('VEKTOR_AGENT_ID ') + ' ' + dim('Agent identifier (default: vektor-cli)'));
94
- console.log('');
95
- console.log(bold(' EXAMPLES\n'));
96
- console.log(dim(' # Start chatting with persistent memory (uses Ollama by default)'));
97
- console.log(' npx vektor chat\n');
98
- console.log(dim(' # Chat with Claude'));
99
- console.log(' npx vektor chat --provider claude\n');
100
- console.log(dim(' # Store a fact instantly'));
101
- console.log(' npx vektor remember "Client deadline is April 20th" --importance 5\n');
102
- console.log(dim(' # Ask your memory a question'));
103
- console.log(' npx vektor ask "what projects am I working on?"\n');
104
- console.log(dim(' # Run an autonomous research agent'));
105
- console.log(' npx vektor agent "research VEKTOR competitors and summarise findings"\n');
106
- console.log(dim(' # Pipe content into memory'));
107
- console.log(' cat README.md | npx vektor remember\n');
108
- console.log(dim(' # Connect to Claude Desktop'));
109
- console.log(' npx vektor mcp\n');
110
- console.log(' ' + dim('Purchase at: https://vektormemory.com/product#pricing'));
111
- console.log('');
112
- }
113
-
114
- // ── Status ────────────────────────────────────────────────────────────────────
115
-
116
- async function cmdStatus() {
117
- printBox();
118
- console.log(bold(' SYSTEM STATUS\n'));
119
-
120
- const nodeVer = parseInt(process.version.slice(1));
121
- const nodeOk = nodeVer >= 18;
122
- console.log(' Node.js ' + (nodeOk ? green('✓ ' + process.version) : red('✗ ' + process.version + ' (requires >=18)')));
123
-
124
- const cacheFile = path.join(os.homedir(), '.vektor', 'licence.json');
125
- const hasCache = fs.existsSync(cacheFile);
126
- console.log(' Licence cache ' + (hasCache ? green('✓ found') : yellow('– not found')) + dim(' (' + cacheFile + ')'));
127
-
128
- const envKey = process.env.VEKTOR_LICENCE_KEY;
129
- console.log(' Licence env ' + (envKey ? green('✓ VEKTOR_LICENCE_KEY set') : dim('– not set')));
130
-
131
- const dbPath = process.env.VEKTOR_DB_PATH ||
132
- path.join(os.homedir(), 'vektor-slipstream-memory.db');
133
- const hasDb = fs.existsSync(dbPath);
134
- console.log(' Memory DB ' + (hasDb ? green('✓ ' + dbPath) : dim('– not found (run: npx vektor test)')));
135
-
136
- const vaultFile = path.join(os.homedir(), '.vektor', 'vault.enc');
137
- console.log(' Cloak vault ' + (fs.existsSync(vaultFile) ? green('✓ found') : dim('– not initialised')));
138
-
139
- let hasPw = false;
140
- try { require('playwright'); hasPw = true; } catch (_) {}
141
- console.log(' Playwright ' + (hasPw ? green('✓ installed') : yellow('– optional (npx playwright install chromium)')));
142
-
143
- let hasOnnx = false;
144
- try { require('onnxruntime-node'); hasOnnx = true; } catch (_) {}
145
- console.log(' ONNX runtime ' + (hasOnnx ? green('✓ installed') : red('✗ missing (npm install onnxruntime-node)')));
146
-
147
- // Provider check
148
- const provider = process.env.VEKTOR_PROVIDER || 'ollama';
149
- console.log(' LLM provider ' + cyan(provider));
150
- if (provider === 'ollama') {
110
+ for (const check of checks) {
111
+ const hasKey = check.key ? !!process.env[check.key] : true;
112
+ if (!hasKey) {
113
+ console.log(` ${C.red}✗${C.reset} ${check.name} ${C.dim}(${check.key} not set)${C.reset}`);
114
+ continue;
115
+ }
116
+ process.stdout.write(` ⏳ ${check.name}…`);
151
117
  try {
152
- const res = await fetch('http://localhost:11434/api/tags', { signal: AbortSignal.timeout(2000) });
153
- const data = await res.json();
154
- const models = data.models?.map(m => m.name).join(', ') || 'none';
155
- console.log(' Ollama models ' + green('✓ running') + dim(' — ' + models));
156
- } catch {
157
- console.log(' Ollama ' + yellow('– not running (start with: ollama serve)'));
118
+ const model = await check.test();
119
+ process.stdout.write(`\r ${C.green}✓${C.reset} ${check.name} ${C.dim}${model}${C.reset}\n`);
120
+ } catch (err) {
121
+ process.stdout.write(`\r ${C.red}✗${C.reset} ${check.name} ${C.dim}${err.message}${C.reset}\n`);
158
122
  }
159
123
  }
160
-
161
- console.log('\n ' + cyan('vektor-slipstream') + ' ' + dim('v' + PKG.version));
162
124
  console.log('');
163
125
  }
164
126
 
165
- // ── Activate ──────────────────────────────────────────────────────────────────
166
-
167
- async function cmdActivate() {
168
- printBox();
169
- console.log(' Activating licence...\n');
170
- try {
171
- const { resolveAndValidateLicence } = require('./vektor-licence-prompt');
172
- const { validateLicence } = require('./vektor-licence');
173
- await resolveAndValidateLicence(validateLicence);
174
- console.log(green(' ✓ Licence activated successfully.'));
175
- console.log(dim(' Run: npx vektor status'));
176
- } catch (e) {
177
- console.error(red(' ✗ Activation failed: ') + e.message);
178
- process.exit(1);
179
- }
180
- console.log('');
127
+ async function testClaude() {
128
+ const res = await fetchTimeout('https://api.anthropic.com/v1/models', {
129
+ headers: { 'x-api-key': process.env.ANTHROPIC_API_KEY, 'anthropic-version': '2023-06-01' },
130
+ }, 5000);
131
+ const j = await res.json();
132
+ const m = j.data?.[0]?.id || 'connected';
133
+ return m;
181
134
  }
182
-
183
- // ── Deactivate ────────────────────────────────────────────────────────────────
184
-
185
- async function cmdDeactivate() {
186
- printBox();
187
- const key = process.env.VEKTOR_LICENCE_KEY;
188
- if (!key) {
189
- console.error(red(' ✗ VEKTOR_LICENCE_KEY not set.'));
190
- console.log(dim(' Set it: set VEKTOR_LICENCE_KEY=YOUR-KEY (Windows) or export VEKTOR_LICENCE_KEY=YOUR-KEY (Unix)'));
191
- process.exit(1);
192
- }
193
- try {
194
- const { deactivateMachine } = require('./vektor-licence');
195
- await deactivateMachine(key);
196
- console.log(green(' ✓ Machine deactivated. Activation slot freed.'));
197
- } catch (e) {
198
- console.error(red(' ✗ Deactivation error: ') + e.message);
199
- process.exit(1);
200
- }
201
- console.log('');
135
+ async function testOpenAI() {
136
+ const res = await fetchTimeout('https://api.openai.com/v1/models', {
137
+ headers: { Authorization: `Bearer ${process.env.OPENAI_API_KEY}` },
138
+ }, 5000);
139
+ const j = await res.json();
140
+ return j.data?.[0]?.id || 'connected';
202
141
  }
203
-
204
- // ── Test ──────────────────────────────────────────────────────────────────────
205
-
206
- async function cmdTest() {
207
- printBox();
208
- console.log(' Running memory test...\n');
209
-
210
- const steps = ['Boot engine', 'Store memory', 'Recall memory', 'Briefing', 'Cleanup'];
211
- let step = 0;
212
-
213
- const bar = (label) => {
214
- const pct = Math.round((step / steps.length) * 100);
215
- const filled = Math.round((step / steps.length) * 30);
216
- const b = '[' + '#'.repeat(filled) + '-'.repeat(30 - filled) + ']';
217
- process.stdout.write('\r ' + cyan(b) + ' ' + String(pct).padStart(3) + '% ' + dim(label || steps[step] || 'Done') + ' ');
218
- };
219
-
220
- bar();
221
-
222
- try {
223
- const { createMemory } = require('./slipstream-core');
224
- const testDb = path.join(os.tmpdir(), 'vektor-test-' + Date.now() + '.db');
225
-
226
- const memory = await createMemory({
227
- agentId: 'vektor-cli-test',
228
- dbPath: testDb,
229
- silent: true,
230
- licenceKey: process.env.VEKTOR_LICENCE_KEY,
231
- });
232
- step++; bar(); process.stdout.write('\n'); console.log(green(' ✓ Memory engine booted'));
233
-
234
- const { id } = await memory.remember('VEKTOR CLI test — memory is working correctly', { importance: 3 });
235
- step++; bar(); process.stdout.write('\n'); console.log(green(' ✓ Stored memory (id: ' + id + ')'));
236
-
237
- const results = await memory.recall('CLI test memory working', 3);
238
- step++; bar(); process.stdout.write('\n');
239
- if (results.length > 0) {
240
- console.log(green(' ✓ Recalled ' + results.length + ' result(s) — top score: ' + results[0].score.toFixed(4)));
241
- } else {
242
- console.log(yellow(' ⚠ Recall returned 0 results'));
243
- }
244
-
245
- try {
246
- await memory.briefing();
247
- step++; bar(); process.stdout.write('\n'); console.log(green(' ✓ Briefing generated'));
248
- } catch (_) {
249
- step++; bar(); process.stdout.write('\n'); console.log(dim(' – Briefing skipped (not enough memories)'));
250
- }
251
-
252
- try { if (memory.db) memory.db.close(); } catch (_) {}
253
- await new Promise(r => setTimeout(r, 200));
254
- try { fs.unlinkSync(testDb); } catch (_) {}
255
- step++; bar('Done'); process.stdout.write('\n'); console.log(green(' ✓ Test database cleaned up'));
256
-
257
- console.log('\n' + green(' ✓ All tests passed. VEKTOR is working correctly.\n'));
258
- } catch (e) {
259
- process.stdout.write('\n');
260
- console.error(red('\n ✗ Test failed: ') + e.message);
261
- if (e.message.includes('better-sqlite3')) {
262
- console.log(yellow(' Fix: npm rebuild better-sqlite3'));
263
- }
264
- if (e.message.includes('licence')) {
265
- console.log(yellow(' Fix: npx vektor activate'));
266
- }
267
- process.exit(1);
268
- }
142
+ async function testGroq() {
143
+ const res = await fetchTimeout('https://api.groq.com/openai/v1/models', {
144
+ headers: { Authorization: `Bearer ${process.env.GROQ_API_KEY}` },
145
+ }, 5000);
146
+ const j = await res.json();
147
+ return j.data?.[0]?.id || 'connected';
148
+ }
149
+ async function testGemini() {
150
+ const res = await fetchTimeout(`https://generativelanguage.googleapis.com/v1beta/models?key=${process.env.GEMINI_API_KEY}`, {}, 5000);
151
+ const j = await res.json();
152
+ return j.models?.[0]?.name || 'connected';
153
+ }
154
+ async function testOllama() {
155
+ const res = await fetchTimeout('http://localhost:11434/api/tags', {}, 3000);
156
+ const j = await res.json();
157
+ const models = j.models?.map(m => m.name) || [];
158
+ if (!models.length) throw new Error('No models installed. Run: ollama pull qwen3');
159
+ return models.join(', ');
269
160
  }
270
161
 
271
- // ── MCP ───────────────────────────────────────────────────────────────────────
162
+ function fetchTimeout(url, opts, ms) {
163
+ const ctrl = new AbortController();
164
+ const t = setTimeout(() => ctrl.abort(), ms);
165
+ return fetch(url, { ...opts, signal: ctrl.signal }).finally(() => clearTimeout(t));
166
+ }
272
167
 
273
- async function cmdMcp() {
274
- const mcpScript = path.join(__dirname, 'examples', 'example-claude-mcp.js');
275
- if (!fs.existsSync(mcpScript)) {
276
- console.error(red(' MCP server not found: ') + mcpScript);
277
- process.exit(1);
278
- }
279
- process.argv = ['node', mcpScript, '--mcp'];
280
- require(mcpScript);
168
+ // ─── Help ─────────────────────────────────────────────────────────────────────
169
+
170
+ function printHelp() {
171
+ const C = { bold: '\x1b[1m', dim: '\x1b[2m', cyan: '\x1b[36m', green: '\x1b[32m', reset: '\x1b[0m' };
172
+ console.log(`
173
+ ${C.bold}VEKTOR Slipstream CLI${C.reset}
174
+
175
+ ${C.bold}Memory:${C.reset}
176
+ ${C.cyan}npx vektor remember${C.reset} "text" Store a fact into MAGMA
177
+ ${C.cyan}npx vektor ask${C.reset} "question" Recall + LLM answer
178
+ ${C.cyan}npx vektor chat${C.reset} Interactive persistent-memory chat
179
+
180
+ ${C.bold}Agent (v1.5):${C.reset}
181
+ ${C.cyan}npx vektor agent${C.reset} "goal" Basic autonomous agent
182
+ ${C.cyan}npx vektor agent${C.reset} "goal" ${C.dim}--tools${C.reset} Full tool suite (web+fs+code)
183
+ ${C.cyan}npx vektor agent${C.reset} "goal" ${C.dim}--continue${C.reset} Resume last session
184
+ ${C.cyan}npx vektor agent${C.reset} "goal" ${C.dim}--tools web,fs,code${C.reset}
185
+
186
+ ${C.bold}Watch (v1.5):${C.reset}
187
+ ${C.cyan}npx vektor watch${C.reset} [path] Watch filesystem, auto-store changes
188
+ ${C.cyan}npx vektor watch${C.reset} src/ ${C.dim}--ext ts,tsx${C.reset}
189
+ ${C.cyan}npx vektor watch${C.reset} ${C.dim}--no-llm${C.reset} Heuristic summaries only
190
+
191
+ ${C.bold}Sync (v1.5):${C.reset}
192
+ ${C.cyan}npx vektor sync${C.reset} --host Listen for incoming sync
193
+ ${C.cyan}npx vektor sync${C.reset} --connect <ip> Sync with host machine
194
+ ${C.cyan}npx vektor sync${C.reset} --host ${C.dim}--pin 123456${C.reset}
195
+
196
+ ${C.bold}Swarm (v1.5):${C.reset}
197
+ ${C.cyan}npx vektor swarm${C.reset} "goal" Multi-agent coordination
198
+ ${C.cyan}npx vektor swarm${C.reset} "goal" ${C.dim}--agents 4${C.reset}
199
+ ${C.cyan}npx vektor swarm${C.reset} "goal" ${C.dim}--roles researcher,coder,reviewer${C.reset}
200
+
201
+ ${C.bold}Utilities:${C.reset}
202
+ ${C.cyan}npx vektor providers${C.reset} Test all API key connections
203
+ ${C.cyan}npx vektor version${C.reset} Show version
204
+ ${C.cyan}npx vektor help${C.reset} Show this help
205
+
206
+ ${C.bold}Providers:${C.reset} ${C.dim}--provider claude|openai|groq|gemini|ollama${C.reset}
207
+ `);
281
208
  }
282
209
 
283
- // ── TUI ───────────────────────────────────────────────────────────────────────
210
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
284
211
 
285
- async function cmdTui() {
286
- const tuiScript = path.join(__dirname, 'vektor-tui.js');
287
- if (!fs.existsSync(tuiScript)) {
288
- console.error(red(' TUI not found: ') + tuiScript);
289
- process.exit(1);
212
+ function safeRequirePackageJson() {
213
+ const candidates = [
214
+ path.join(__dirname, 'package.json'),
215
+ path.join(__dirname, '..', 'package.json'),
216
+ ];
217
+ for (const c of candidates) {
218
+ try { return require(c); } catch { /* skip */ }
290
219
  }
291
- loader.complete('Launching TUI');
292
- require(tuiScript);
220
+ return {};
293
221
  }
294
222
 
295
- // ── REM ───────────────────────────────────────────────────────────────────────
296
-
297
- async function cmdRem() {
298
- printBox();
299
- console.log(' Running REM dream cycle...\n');
300
- try {
301
- const { createMemory } = require('./boot-patch');
302
- const dbPath = process.env.VEKTOR_DB_PATH ||
303
- path.join(os.homedir(), 'vektor-slipstream-memory.db');
304
-
305
- if (!fs.existsSync(dbPath)) {
306
- console.error(yellow(' ⚠ No memory database found at: ' + dbPath));
307
- console.log(dim(' Run: npx vektor test to create one'));
308
- process.exit(1);
309
- }
310
-
311
- const memory = await createMemory({
312
- agentId: process.env.VEKTOR_AGENT_ID || 'default',
313
- dbPath,
314
- silent: true,
315
- licenceKey: process.env.VEKTOR_LICENCE_KEY,
316
- });
317
-
318
- console.log(' ' + dim('┌─ Phase 1/4 Auditing memory graph...'));
319
- const stats = await memory.stats();
320
- const total = stats.total || 0;
321
- console.log(dim(' │ Total nodes: ' + total));
223
+ // ─── CLI dispatcher ───────────────────────────────────────────────────────────
322
224
 
323
- if (total === 0) {
324
- console.log(green(' └─ Memory graph is empty — nothing to consolidate\n'));
325
- return;
326
- }
327
-
328
- console.log(' ' + dim('├─ Phase 2/4 Scanning recent activity...'));
329
- const recent = await memory.recent(20);
330
- console.log(dim(' │ Recent nodes scanned: ' + (recent ? recent.length : 0)));
331
-
332
- console.log(' ' + dim('├─ Phase 3/4 Pruning noise nodes...'));
333
- let pruned = 0;
334
- const NOISE = [
335
- 'cloak warmup probe',
336
- 'VEKTOR CLI test — memory is working correctly',
337
- ];
338
- for (const pattern of NOISE) {
339
- try {
340
- const nodes = await memory.recall(pattern, 10);
341
- if (!nodes || !nodes.length) continue;
342
- for (const node of nodes) {
343
- if (node.content && NOISE.some(n => node.content.includes(n))) {
344
- if (node.id) { await memory.remove(node.id); pruned++; }
345
- }
346
- }
347
- } catch { /* non-fatal */ }
348
- }
349
- console.log(dim(' │ Noise nodes pruned: ' + pruned));
225
+ async function main() {
226
+ const argv = process.argv.slice(2);
227
+ const cmd = argv[0];
350
228
 
351
- console.log(' ' + dim('├─ Phase 4/4 Generating consolidation summary...'));
352
- let briefSnippet = '';
353
- try {
354
- const brief = await memory.briefing();
355
- if (brief) briefSnippet = brief.slice(0, 120) + (brief.length > 120 ? '...' : '');
356
- } catch { /* non-fatal */ }
357
-
358
- const statsAfter = await memory.stats();
359
- const totalAfter = statsAfter.total || 0;
360
- const delta = total - totalAfter;
361
-
362
- console.log(green(' └─ REM cycle complete\n'));
363
- console.log(' ' + dim('Before:') + ' ' + total + ' nodes');
364
- console.log(' ' + dim('After: ') + ' ' + totalAfter + ' nodes');
365
- console.log(' ' + dim('Pruned:') + ' ' + pruned + ' noise nodes');
366
- if (delta > pruned) {
367
- console.log(' ' + dim('AUDN: ') + ' ' + (delta - pruned) + ' duplicates resolved');
368
- }
369
- if (briefSnippet) {
370
- console.log('\n ' + dim('Briefing: ') + briefSnippet);
371
- }
229
+ if (!cmd || cmd === '--help' || cmd === '-h') {
230
+ printHelp();
231
+ return;
232
+ }
233
+ if (cmd === '--version' || cmd === '-v') {
234
+ const pkg = safeRequirePackageJson();
235
+ console.log(`v${pkg.version || '1.5.0'}`);
236
+ return;
237
+ }
372
238
 
373
- } catch (e) {
374
- console.error(red(' REM error: ') + e.message);
239
+ const factory = COMMANDS[cmd];
240
+ if (!factory) {
241
+ console.error(`Unknown command: ${cmd}\nRun 'npx vektor help' for usage.`);
375
242
  process.exit(1);
376
243
  }
377
- console.log('');
378
- }
379
-
380
- // ── Briefing ──────────────────────────────────────────────────────────────────
381
244
 
382
- async function cmdBriefing() {
383
- printBox();
384
- console.log(' Generating memory briefing...\n');
385
245
  try {
386
- const { createMemory } = require('./slipstream-core');
387
- const dbPath = process.env.VEKTOR_DB_PATH ||
388
- path.join(os.homedir(), 'vektor-slipstream-memory.db');
389
-
390
- if (!fs.existsSync(dbPath)) {
391
- console.error(yellow(' ⚠ No memory database found at: ' + dbPath));
392
- console.log(dim(' Run: npx vektor test to create one'));
393
- process.exit(1);
394
- }
395
-
396
- const memory = await createMemory({
397
- agentId: process.env.VEKTOR_AGENT_ID || 'default',
398
- dbPath,
399
- silent: true,
400
- licenceKey: process.env.VEKTOR_LICENCE_KEY,
401
- });
402
-
403
- const brief = await memory.briefing();
404
- if (brief) {
405
- console.log(bold(' ── MEMORY BRIEFING ──────────────────────────────────\n'));
406
- console.log(' ' + brief.split('\n').join('\n '));
407
- console.log('\n ' + dim('─────────────────────────────────────────────────────'));
408
- } else {
409
- console.log(dim(' No briefing available — add more memories first.'));
410
- console.log(dim(' Try: npx vektor chat or npx vektor remember "some fact"'));
411
- }
412
- } catch (e) {
413
- console.error(red(' ✗ Briefing error: ') + e.message);
246
+ const handler = factory();
247
+ await handler(argv.slice(1));
248
+ } catch (err) {
249
+ console.error(`Error in '${cmd}': ${err.message}`);
250
+ if (process.env.DEBUG) console.error(err);
414
251
  process.exit(1);
415
252
  }
416
- console.log('');
417
- }
418
-
419
- // ── Setup ─────────────────────────────────────────────────────────────────────
420
-
421
- async function cmdSetup() {
422
- require('./vektor-setup');
423
- }
424
-
425
- // ── Chat / Remember / Ask / Agent — from vektor-cli-chat.js ──────────────────
426
-
427
- async function cmdChat() { const { cmdChat } = require('./vektor-cli-chat'); await cmdChat(process.argv); }
428
- async function cmdRemember() { const { cmdRemember } = require('./vektor-cli-chat'); await cmdRemember(process.argv); }
429
- async function cmdAsk() { const { cmdAsk } = require('./vektor-cli-chat'); await cmdAsk(process.argv); }
430
- async function cmdAgent() { const { cmdAgent } = require('./vektor-cli-chat'); await cmdAgent(process.argv); }
431
-
432
- // ── Pipe support — cat file.txt | npx vektor remember ────────────────────────
433
- async function handlePipe() {
434
- if (process.stdin.isTTY) return false;
435
- const chunks = [];
436
- for await (const chunk of process.stdin) chunks.push(chunk);
437
- const piped = chunks.join('').trim();
438
- if (!piped) return false;
439
- // Inject piped content as the text argument
440
- process.argv.push(piped);
441
- return true;
442
253
  }
443
254
 
444
- // ── Router ────────────────────────────────────────────────────────────────────
445
-
446
- const commands = {
447
- help: cmdHelp,
448
- status: cmdStatus,
449
- activate: cmdActivate,
450
- deactivate: cmdDeactivate,
451
- test: cmdTest,
452
- mcp: cmdMcp,
453
- tui: cmdTui,
454
- rem: cmdRem,
455
- briefing: cmdBriefing,
456
- setup: cmdSetup,
457
- // New commands
458
- chat: cmdChat,
459
- remember: cmdRemember,
460
- ask: cmdAsk,
461
- agent: cmdAgent,
462
- };
463
-
464
- const fn = commands[command];
465
- if (!fn) {
466
- console.error(red('\n ✗ Unknown command: ') + bold(command));
467
- console.log(dim(' Run: npx vektor help\n'));
468
- process.exit(1);
255
+ if (require.main === module) {
256
+ main();
469
257
  }
470
258
 
471
- // Handle pipe for remember command
472
- if (command === 'remember') {
473
- handlePipe().then(() => fn()).catch(e => {
474
- console.error(red('\n ✗ Error: ') + e.message);
475
- process.exit(1);
476
- });
477
- } else {
478
- fn().catch(e => {
479
- console.error(red('\n ✗ Error: ') + e.message);
480
- process.exit(1);
481
- });
482
- }
259
+ module.exports = { COMMANDS, main };