ruvector 0.2.2 → 0.2.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.
package/README.md CHANGED
@@ -56,7 +56,7 @@ npx ruvector hooks init --pretrain --build-agents quality
56
56
 
57
57
  ### MCP Server Integration
58
58
 
59
- RuVector includes an MCP server for Claude Code with 30+ tools:
59
+ RuVector includes an MCP server for Claude Code with 103 tools:
60
60
 
61
61
  ```bash
62
62
  # Add to Claude Code
@@ -72,6 +72,35 @@ claude mcp add ruvector -- npx ruvector mcp start
72
72
  - `hooks_security_scan` — Vulnerability detection
73
73
  - `hooks_rag_context` — Semantic context retrieval
74
74
  - `hooks_attention_info`, `hooks_gnn_info` — Neural capabilities
75
+ - `brain_search`, `brain_share`, `brain_status` — Shared brain knowledge
76
+ - `brain_agi_status`, `brain_sona_stats`, `brain_temporal`, `brain_explore` — AGI diagnostics
77
+ - `brain_midstream`, `brain_flags` — Midstream platform + feature flags
78
+ - `midstream_status`, `midstream_attractor`, `midstream_scheduler` — Streaming analysis
79
+ - `midstream_benchmark`, `midstream_search`, `midstream_health` — Latency benchmarks + health
80
+
81
+ ### Brain AGI Commands
82
+
83
+ Access all 8 AGI subsystems deployed at π.ruv.io:
84
+
85
+ ```bash
86
+ npx ruvector brain agi status # Combined AGI + midstream diagnostics
87
+ npx ruvector brain agi sona # SONA patterns, trajectories, ticks
88
+ npx ruvector brain agi temporal # Knowledge evolution velocity
89
+ npx ruvector brain agi explore # Meta-learning curiosity & regret
90
+ npx ruvector brain agi midstream # Scheduler, attractor, solver, strange-loop
91
+ npx ruvector brain agi flags # Feature flag state
92
+ ```
93
+
94
+ ### Midstream Commands
95
+
96
+ Real-time streaming analysis platform:
97
+
98
+ ```bash
99
+ npx ruvector midstream status # Platform overview
100
+ npx ruvector midstream attractor # Lyapunov attractor analysis
101
+ npx ruvector midstream scheduler # Nanosecond scheduler metrics
102
+ npx ruvector midstream benchmark # Latency benchmark (p50/p90/p99)
103
+ ```
75
104
 
76
105
  ---
77
106
 
package/bin/cli.js CHANGED
@@ -4106,7 +4106,7 @@ hooksCmd.command('suggest-context').description('Suggest relevant context').acti
4106
4106
  console.log(`RuVector Intelligence: ${stats.total_patterns} learned patterns, ${stats.total_errors} error fixes available. Use 'ruvector hooks route' for agent suggestions.`);
4107
4107
  });
4108
4108
 
4109
- hooksCmd.command('remember').description('Store in memory').requiredOption('-t, --type <type>', 'Memory type').option('--silent', 'Suppress output').option('--semantic', 'Use ONNX semantic embeddings (slower, better quality)').argument('<content...>', 'Content').action(async (content, opts) => {
4109
+ hooksCmd.command('remember').description('Store in memory').option('-t, --type <type>', 'Memory type', 'general').option('--silent', 'Suppress output').option('--semantic', 'Use ONNX semantic embeddings (slower, better quality)').argument('<content...>', 'Content').action(async (content, opts) => {
4110
4110
  const intel = new Intelligence();
4111
4111
  let id;
4112
4112
  if (opts.semantic) {
@@ -7880,6 +7880,7 @@ brainCmd.command('search <query>')
7880
7880
  .option('--url <url>', 'Brain server URL')
7881
7881
  .option('--key <key>', 'Pi key')
7882
7882
  .option('--json', 'Output as JSON')
7883
+ .option('--verbose', 'Show detailed scoring and metadata per result')
7883
7884
  .action(async (query, opts) => {
7884
7885
  const piBrain = await requirePiBrain();
7885
7886
  const config = getBrainConfig(opts);
@@ -7893,6 +7894,14 @@ brainCmd.command('search <query>')
7893
7894
  console.log(` ${chalk.yellow(i + 1 + '.')} ${chalk.bold(r.title || r.id)}`);
7894
7895
  if (r.category) console.log(` ${chalk.dim('Category:')} ${r.category}`);
7895
7896
  if (r.score) console.log(` ${chalk.dim('Score:')} ${r.score.toFixed(3)}`);
7897
+ if (opts.verbose) {
7898
+ if (r.quality_score !== undefined) console.log(` ${chalk.dim('Quality:')} ${typeof r.quality_score === 'number' ? r.quality_score.toFixed(3) : r.quality_score}`);
7899
+ if (r.votes_up !== undefined || r.votes_down !== undefined) console.log(` ${chalk.dim('Votes:')} ${r.votes_up || 0}↑ ${r.votes_down || 0}↓`);
7900
+ if (r.witness_hash) console.log(` ${chalk.dim('Witness:')} ${r.witness_hash.slice(0, 12)}...`);
7901
+ if (r.contributor_id) console.log(` ${chalk.dim('Contributor:')} ${r.contributor_id}`);
7902
+ if (r.created_at) console.log(` ${chalk.dim('Created:')} ${r.created_at}`);
7903
+ if (r.tags && r.tags.length) console.log(` ${chalk.dim('Tags:')} ${r.tags.join(', ')}`);
7904
+ }
7896
7905
  console.log();
7897
7906
  });
7898
7907
  } catch (e) { console.error(chalk.red(`Error: ${e.message}`)); process.exit(1); }
@@ -8003,6 +8012,20 @@ brainCmd.command('status')
8003
8012
  Object.entries(status).forEach(([k, v]) => {
8004
8013
  console.log(` ${chalk.bold(k + ':')} ${v}`);
8005
8014
  });
8015
+ // AGI subsystem fields
8016
+ if (status.sona_patterns !== undefined) {
8017
+ console.log(chalk.bold('\n AGI Subsystems'));
8018
+ if (status.sona_patterns !== undefined) console.log(` ${chalk.dim('SONA Patterns:')} ${status.sona_patterns} ${chalk.dim('Trajectories:')} ${status.sona_trajectories || 0}`);
8019
+ if (status.gwt_workspace_load !== undefined) console.log(` ${chalk.dim('GWT Load:')} ${status.gwt_workspace_load} ${chalk.dim('Avg Salience:')} ${status.gwt_avg_salience || 0}`);
8020
+ if (status.knowledge_velocity !== undefined) console.log(` ${chalk.dim('Temporal Velocity:')} ${status.knowledge_velocity}/hr ${chalk.dim('Deltas:')} ${status.temporal_deltas || 0}`);
8021
+ if (status.meta_avg_regret !== undefined) console.log(` ${chalk.dim('Meta Regret:')} ${status.meta_avg_regret} ${chalk.dim('Plateau:')} ${status.meta_plateau_status || 'unknown'}`);
8022
+ }
8023
+ if (status.midstream_scheduler_ticks !== undefined) {
8024
+ console.log(chalk.bold('\n Midstream'));
8025
+ console.log(` ${chalk.dim('Scheduler Ticks:')} ${status.midstream_scheduler_ticks}`);
8026
+ console.log(` ${chalk.dim('Attractor Categories:')} ${status.midstream_attractor_categories || 0}`);
8027
+ console.log(` ${chalk.dim('Strange-Loop:')} v${status.midstream_strange_loop_version || '?'}`);
8028
+ }
8006
8029
  console.log();
8007
8030
  } catch (e) { console.error(chalk.red(`Error: ${e.message}`)); process.exit(1); }
8008
8031
  });
@@ -8173,6 +8196,299 @@ brainCmd.command('node <action> [args...]')
8173
8196
  } catch (e) { console.error(chalk.red(`Error: ${e.message}`)); process.exit(1); }
8174
8197
  });
8175
8198
 
8199
+ // ── Brain AGI Subcommands ── AGI subsystem diagnostics ──────────────────
8200
+ const agiCmd = brainCmd.command('agi').description('AGI subsystem diagnostics — SONA, GWT, temporal, meta-learning, midstream');
8201
+
8202
+ async function fetchBrainEndpoint(config, endpoint) {
8203
+ const url = (config.url || 'https://pi.ruv.io') + endpoint;
8204
+ const headers = {};
8205
+ if (config.key) headers['Authorization'] = `Bearer ${config.key}`;
8206
+ const resp = await fetch(url, { headers });
8207
+ if (!resp.ok) throw new Error(`${resp.status} ${resp.statusText}`);
8208
+ return resp.json();
8209
+ }
8210
+
8211
+ agiCmd.command('status')
8212
+ .description('Combined AGI + midstream diagnostics from π.ruv.io')
8213
+ .option('--url <url>', 'Brain server URL')
8214
+ .option('--key <key>', 'Pi key')
8215
+ .option('--json', 'Output as JSON')
8216
+ .action(async (opts) => {
8217
+ const config = getBrainConfig(opts);
8218
+ try {
8219
+ const status = await fetchBrainEndpoint(config, '/v1/status');
8220
+ if (opts.json || !process.stdout.isTTY) { console.log(JSON.stringify(status, null, 2)); return; }
8221
+ console.log(chalk.bold.cyan('\n π.ruv.io AGI Diagnostics\n'));
8222
+ console.log(chalk.bold(' SONA'));
8223
+ console.log(` Patterns: ${status.sona_patterns || 0} Trajectories: ${status.sona_trajectories || 0}`);
8224
+ console.log(` Background ticks: ${status.sona_background_ticks || 0}`);
8225
+ console.log(chalk.bold('\n GWT Attention'));
8226
+ console.log(` Workspace load: ${status.gwt_workspace_load || 0}`);
8227
+ console.log(` Avg salience: ${status.gwt_avg_salience || 0}`);
8228
+ console.log(chalk.bold('\n Temporal'));
8229
+ console.log(` Total deltas: ${status.temporal_deltas || 0}`);
8230
+ console.log(` Velocity: ${status.knowledge_velocity || 0}/hr`);
8231
+ console.log(` Trend: ${status.temporal_trend || 'unknown'}`);
8232
+ console.log(chalk.bold('\n Meta-Learning'));
8233
+ console.log(` Avg regret: ${status.meta_avg_regret || 0}`);
8234
+ console.log(` Plateau: ${status.meta_plateau_status || 'unknown'}`);
8235
+ console.log(chalk.bold('\n Midstream'));
8236
+ console.log(` Scheduler ticks: ${status.midstream_scheduler_ticks || 0}`);
8237
+ console.log(` Attractor categories: ${status.midstream_attractor_categories || 0}`);
8238
+ console.log(` Strange-loop: v${status.midstream_strange_loop_version || '?'}`);
8239
+ console.log();
8240
+ } catch (e) { console.error(chalk.red(`Error: ${e.message}`)); process.exit(1); }
8241
+ });
8242
+
8243
+ agiCmd.command('sona')
8244
+ .description('SONA learning engine — patterns, trajectories, background ticks')
8245
+ .option('--url <url>', 'Brain server URL')
8246
+ .option('--key <key>', 'Pi key')
8247
+ .option('--json', 'Output as JSON')
8248
+ .action(async (opts) => {
8249
+ const config = getBrainConfig(opts);
8250
+ try {
8251
+ const data = await fetchBrainEndpoint(config, '/v1/sona/stats');
8252
+ if (opts.json || !process.stdout.isTTY) { console.log(JSON.stringify(data, null, 2)); return; }
8253
+ console.log(chalk.bold.cyan('\n SONA Learning Engine\n'));
8254
+ Object.entries(data).forEach(([k, v]) => console.log(` ${chalk.bold(k + ':')} ${v}`));
8255
+ console.log();
8256
+ } catch (e) { console.error(chalk.red(`Error: ${e.message}`)); process.exit(1); }
8257
+ });
8258
+
8259
+ agiCmd.command('temporal')
8260
+ .description('Temporal delta tracking — velocity, trend, total deltas')
8261
+ .option('--url <url>', 'Brain server URL')
8262
+ .option('--key <key>', 'Pi key')
8263
+ .option('--json', 'Output as JSON')
8264
+ .action(async (opts) => {
8265
+ const config = getBrainConfig(opts);
8266
+ try {
8267
+ const data = await fetchBrainEndpoint(config, '/v1/temporal');
8268
+ if (opts.json || !process.stdout.isTTY) { console.log(JSON.stringify(data, null, 2)); return; }
8269
+ console.log(chalk.bold.cyan('\n Temporal Delta Tracking\n'));
8270
+ Object.entries(data).forEach(([k, v]) => console.log(` ${chalk.bold(k + ':')} ${v}`));
8271
+ console.log();
8272
+ } catch (e) { console.error(chalk.red(`Error: ${e.message}`)); process.exit(1); }
8273
+ });
8274
+
8275
+ agiCmd.command('explore')
8276
+ .description('Meta-learning exploration — curiosity, regret, plateau, Pareto')
8277
+ .option('--url <url>', 'Brain server URL')
8278
+ .option('--key <key>', 'Pi key')
8279
+ .option('--json', 'Output as JSON')
8280
+ .action(async (opts) => {
8281
+ const config = getBrainConfig(opts);
8282
+ try {
8283
+ const data = await fetchBrainEndpoint(config, '/v1/explore');
8284
+ if (opts.json || !process.stdout.isTTY) { console.log(JSON.stringify(data, null, 2)); return; }
8285
+ console.log(chalk.bold.cyan('\n Meta-Learning Exploration\n'));
8286
+ Object.entries(data).forEach(([k, v]) => console.log(` ${chalk.bold(k + ':')} ${v}`));
8287
+ console.log();
8288
+ } catch (e) { console.error(chalk.red(`Error: ${e.message}`)); process.exit(1); }
8289
+ });
8290
+
8291
+ agiCmd.command('midstream')
8292
+ .description('Midstream platform — scheduler, attractor, solver, strange-loop')
8293
+ .option('--url <url>', 'Brain server URL')
8294
+ .option('--key <key>', 'Pi key')
8295
+ .option('--json', 'Output as JSON')
8296
+ .action(async (opts) => {
8297
+ const config = getBrainConfig(opts);
8298
+ try {
8299
+ const data = await fetchBrainEndpoint(config, '/v1/midstream');
8300
+ if (opts.json || !process.stdout.isTTY) { console.log(JSON.stringify(data, null, 2)); return; }
8301
+ console.log(chalk.bold.cyan('\n Midstream Platform\n'));
8302
+ Object.entries(data).forEach(([k, v]) => {
8303
+ if (typeof v === 'object' && v !== null) {
8304
+ console.log(` ${chalk.bold(k + ':')}`);
8305
+ Object.entries(v).forEach(([sk, sv]) => console.log(` ${chalk.dim(sk + ':')} ${sv}`));
8306
+ } else {
8307
+ console.log(` ${chalk.bold(k + ':')} ${v}`);
8308
+ }
8309
+ });
8310
+ console.log();
8311
+ } catch (e) { console.error(chalk.red(`Error: ${e.message}`)); process.exit(1); }
8312
+ });
8313
+
8314
+ agiCmd.command('flags')
8315
+ .description('Show feature flag state from backend')
8316
+ .option('--url <url>', 'Brain server URL')
8317
+ .option('--key <key>', 'Pi key')
8318
+ .option('--json', 'Output as JSON')
8319
+ .action(async (opts) => {
8320
+ const config = getBrainConfig(opts);
8321
+ try {
8322
+ const status = await fetchBrainEndpoint(config, '/v1/status');
8323
+ const flags = {};
8324
+ for (const [k, v] of Object.entries(status)) {
8325
+ if (typeof v === 'boolean' || k.startsWith('rvf_') || k.endsWith('_enabled')) {
8326
+ flags[k] = v;
8327
+ }
8328
+ }
8329
+ if (opts.json || !process.stdout.isTTY) { console.log(JSON.stringify(flags, null, 2)); return; }
8330
+ console.log(chalk.bold.cyan('\n Feature Flags\n'));
8331
+ Object.entries(flags).forEach(([k, v]) => {
8332
+ const icon = v ? chalk.green('●') : chalk.red('○');
8333
+ console.log(` ${icon} ${chalk.bold(k)}: ${v}`);
8334
+ });
8335
+ console.log();
8336
+ } catch (e) { console.error(chalk.red(`Error: ${e.message}`)); process.exit(1); }
8337
+ });
8338
+
8339
+ // ============================================================================
8340
+ // Midstream Commands — Real-time streaming analysis platform
8341
+ // ============================================================================
8342
+
8343
+ const midstreamCmd = program.command('midstream').description('Real-time streaming analysis — attractor, scheduler, benchmark');
8344
+
8345
+ midstreamCmd.command('status')
8346
+ .description('Midstream platform overview')
8347
+ .option('--url <url>', 'Brain server URL')
8348
+ .option('--key <key>', 'Pi key')
8349
+ .option('--json', 'Output as JSON')
8350
+ .action(async (opts) => {
8351
+ const config = getBrainConfig(opts);
8352
+ try {
8353
+ const data = await fetchBrainEndpoint(config, '/v1/midstream');
8354
+ if (opts.json || !process.stdout.isTTY) { console.log(JSON.stringify(data, null, 2)); return; }
8355
+ console.log(chalk.bold.cyan('\n Midstream Platform Status\n'));
8356
+ Object.entries(data).forEach(([k, v]) => {
8357
+ if (typeof v === 'object' && v !== null) {
8358
+ console.log(` ${chalk.bold(k + ':')}`);
8359
+ Object.entries(v).forEach(([sk, sv]) => console.log(` ${chalk.dim(sk + ':')} ${sv}`));
8360
+ } else {
8361
+ console.log(` ${chalk.bold(k + ':')} ${v}`);
8362
+ }
8363
+ });
8364
+ console.log();
8365
+ } catch (e) { console.error(chalk.red(`Error: ${e.message}`)); process.exit(1); }
8366
+ });
8367
+
8368
+ midstreamCmd.command('attractor [category]')
8369
+ .description('Lyapunov attractor analysis per category')
8370
+ .option('--url <url>', 'Brain server URL')
8371
+ .option('--key <key>', 'Pi key')
8372
+ .option('--json', 'Output as JSON')
8373
+ .action(async (category, opts) => {
8374
+ const config = getBrainConfig(opts);
8375
+ try {
8376
+ const data = await fetchBrainEndpoint(config, '/v1/midstream');
8377
+ const attractors = data.attractor_categories || data.attractors || {};
8378
+ if (category) {
8379
+ const entry = typeof attractors === 'object' ? attractors[category] : null;
8380
+ if (opts.json || !process.stdout.isTTY) { console.log(JSON.stringify(entry || { error: 'Category not found' }, null, 2)); return; }
8381
+ if (!entry) { console.log(chalk.yellow(` No attractor data for category: ${category}`)); return; }
8382
+ console.log(chalk.bold.cyan(`\n Attractor: ${category}\n`));
8383
+ Object.entries(entry).forEach(([k, v]) => console.log(` ${chalk.bold(k + ':')} ${v}`));
8384
+ } else {
8385
+ if (opts.json || !process.stdout.isTTY) { console.log(JSON.stringify(attractors, null, 2)); return; }
8386
+ console.log(chalk.bold.cyan('\n Attractor Categories\n'));
8387
+ if (typeof attractors === 'object' && Object.keys(attractors).length > 0) {
8388
+ Object.entries(attractors).forEach(([cat, info]) => {
8389
+ console.log(` ${chalk.yellow(cat + ':')} ${typeof info === 'object' ? JSON.stringify(info) : info}`);
8390
+ });
8391
+ } else {
8392
+ console.log(chalk.dim(` ${typeof attractors === 'number' ? attractors + ' categories tracked' : 'No attractor data available'}`));
8393
+ }
8394
+ }
8395
+ console.log();
8396
+ } catch (e) { console.error(chalk.red(`Error: ${e.message}`)); process.exit(1); }
8397
+ });
8398
+
8399
+ midstreamCmd.command('scheduler')
8400
+ .description('Nanosecond scheduler performance metrics')
8401
+ .option('--url <url>', 'Brain server URL')
8402
+ .option('--key <key>', 'Pi key')
8403
+ .option('--json', 'Output as JSON')
8404
+ .action(async (opts) => {
8405
+ const config = getBrainConfig(opts);
8406
+ try {
8407
+ const data = await fetchBrainEndpoint(config, '/v1/midstream');
8408
+ const sched = data.scheduler || { ticks: data.scheduler_ticks || 0 };
8409
+ if (opts.json || !process.stdout.isTTY) { console.log(JSON.stringify(sched, null, 2)); return; }
8410
+ console.log(chalk.bold.cyan('\n Nanosecond Scheduler\n'));
8411
+ if (typeof sched === 'object') {
8412
+ Object.entries(sched).forEach(([k, v]) => console.log(` ${chalk.bold(k + ':')} ${v}`));
8413
+ } else {
8414
+ console.log(` ${chalk.bold('Ticks:')} ${sched}`);
8415
+ }
8416
+ console.log();
8417
+ } catch (e) { console.error(chalk.red(`Error: ${e.message}`)); process.exit(1); }
8418
+ });
8419
+
8420
+ midstreamCmd.command('benchmark')
8421
+ .description('Run latency benchmark against brain backend')
8422
+ .option('--url <url>', 'Brain server URL')
8423
+ .option('--key <key>', 'Pi key')
8424
+ .option('-n, --concurrent <n>', 'Concurrent search requests', '20')
8425
+ .option('--json', 'Output as JSON')
8426
+ .action(async (opts) => {
8427
+ const config = getBrainConfig(opts);
8428
+ const baseUrl = config.url || 'https://pi.ruv.io';
8429
+ const headers = {};
8430
+ if (config.key) headers['Authorization'] = `Bearer ${config.key}`;
8431
+ const concurrentN = Math.min(parseInt(opts.concurrent) || 20, 100);
8432
+
8433
+ async function timeRequest(url, label) {
8434
+ const start = performance.now();
8435
+ const resp = await fetch(url, { headers });
8436
+ const elapsed = performance.now() - start;
8437
+ return { label, status: resp.status, elapsed };
8438
+ }
8439
+
8440
+ function percentile(sorted, p) {
8441
+ const idx = Math.ceil(sorted.length * p / 100) - 1;
8442
+ return sorted[Math.max(0, idx)];
8443
+ }
8444
+
8445
+ try {
8446
+ if (!opts.json && process.stdout.isTTY) console.log(chalk.bold.cyan('\n Midstream Benchmark\n'));
8447
+
8448
+ // Sequential tests (3 each)
8449
+ const endpoints = [
8450
+ { path: '/v1/health', label: 'health' },
8451
+ { path: '/v1/status', label: 'status' },
8452
+ { path: '/v1/memories/search?q=test&limit=3', label: 'search' },
8453
+ { path: '/v1/midstream', label: 'midstream' },
8454
+ ];
8455
+
8456
+ const sequential = {};
8457
+ for (const ep of endpoints) {
8458
+ const times = [];
8459
+ for (let i = 0; i < 3; i++) {
8460
+ const r = await timeRequest(baseUrl + ep.path, ep.label);
8461
+ times.push(r.elapsed);
8462
+ }
8463
+ sequential[ep.label] = { avg: times.reduce((a, b) => a + b, 0) / times.length, min: Math.min(...times), max: Math.max(...times) };
8464
+ }
8465
+
8466
+ // Concurrent search test
8467
+ const concurrentTimes = [];
8468
+ const promises = [];
8469
+ for (let i = 0; i < concurrentN; i++) {
8470
+ promises.push(timeRequest(baseUrl + '/v1/memories/search?q=test&limit=3', 'concurrent'));
8471
+ }
8472
+ const results = await Promise.all(promises);
8473
+ const sorted = results.map(r => r.elapsed).sort((a, b) => a - b);
8474
+ const p50 = percentile(sorted, 50);
8475
+ const p90 = percentile(sorted, 90);
8476
+ const p99 = percentile(sorted, 99);
8477
+
8478
+ const benchResult = { sequential, concurrent: { count: concurrentN, p50, p90, p99 } };
8479
+
8480
+ if (opts.json || !process.stdout.isTTY) { console.log(JSON.stringify(benchResult, null, 2)); return; }
8481
+
8482
+ console.log(chalk.bold(' Sequential (3 rounds each):'));
8483
+ for (const [label, data] of Object.entries(sequential)) {
8484
+ console.log(` ${chalk.yellow(label.padEnd(12))} avg: ${data.avg.toFixed(1)}ms min: ${data.min.toFixed(1)}ms max: ${data.max.toFixed(1)}ms`);
8485
+ }
8486
+ console.log(chalk.bold(`\n Concurrent (${concurrentN}x search):`));
8487
+ console.log(` p50: ${p50.toFixed(1)}ms p90: ${p90.toFixed(1)}ms p99: ${p99.toFixed(1)}ms`);
8488
+ console.log();
8489
+ } catch (e) { console.error(chalk.red(`Error: ${e.message}`)); process.exit(1); }
8490
+ });
8491
+
8176
8492
  // ============================================================================
8177
8493
  // Edge Commands — Distributed compute via @ruvector/edge-net
8178
8494
  // ============================================================================
@@ -8219,7 +8535,9 @@ edgeCmd.command('balance')
8219
8535
  const piKey = process.env.PI;
8220
8536
  if (!piKey) { console.error(chalk.red('Set PI environment variable first.')); process.exit(1); }
8221
8537
  try {
8222
- const resp = await fetch(`${EDGE_GENESIS}/balance/${piKey}`, { headers: { 'Authorization': `Bearer ${piKey}` } });
8538
+ const pseudonym = require('crypto').createHash('shake256', { outputLength: 16 }).update(piKey).digest('hex');
8539
+ const resp = await fetch(`${EDGE_GENESIS}/balance/${pseudonym}`, { headers: { 'Authorization': `Bearer ${piKey}` } });
8540
+ if (!resp.ok) { console.error(chalk.red(`Edge network returned ${resp.status} ${resp.statusText}`)); process.exit(1); }
8223
8541
  const data = await resp.json();
8224
8542
  if (opts.json || !process.stdout.isTTY) { console.log(JSON.stringify(data, null, 2)); return; }
8225
8543
  console.log(chalk.bold.cyan('\nrUv Balance\n'));
@@ -8437,13 +8755,20 @@ function loadSona() {
8437
8755
  }
8438
8756
  }
8439
8757
 
8758
+ const SONA_DEFAULT_DIM = 128;
8759
+ function createSonaEngine(sona) {
8760
+ if (sona.SonaEngine) return new sona.SonaEngine(SONA_DEFAULT_DIM);
8761
+ if (sona.SonaCoordinator) return new sona.SonaCoordinator(SONA_DEFAULT_DIM);
8762
+ throw new Error('No SONA engine class found');
8763
+ }
8764
+
8440
8765
  sonaCmd.command('status')
8441
8766
  .description('Show SONA learning engine status')
8442
8767
  .option('--json', 'Output as JSON')
8443
8768
  .action((opts) => {
8444
8769
  const sona = loadSona();
8445
8770
  try {
8446
- const engine = sona.SonaEngine ? new sona.SonaEngine() : new sona.SonaCoordinator();
8771
+ const engine = createSonaEngine(sona);
8447
8772
  const status = engine.getStatus ? engine.getStatus() : { ready: true };
8448
8773
  if (opts.json || !process.stdout.isTTY) { console.log(JSON.stringify(status, null, 2)); return; }
8449
8774
  console.log(chalk.bold.cyan('\nSONA Status\n'));
@@ -8459,7 +8784,7 @@ sonaCmd.command('patterns <query>')
8459
8784
  .action((query, opts) => {
8460
8785
  const sona = loadSona();
8461
8786
  try {
8462
- const engine = sona.SonaEngine ? new sona.SonaEngine() : new sona.SonaCoordinator();
8787
+ const engine = createSonaEngine(sona);
8463
8788
  const patterns = engine.findPatterns ? engine.findPatterns(query, { threshold: parseFloat(opts.threshold) }) : [];
8464
8789
  if (opts.json || !process.stdout.isTTY) { console.log(JSON.stringify(patterns, null, 2)); return; }
8465
8790
  console.log(chalk.bold.cyan('\nLearned Patterns\n'));
@@ -8475,7 +8800,7 @@ sonaCmd.command('train <data>')
8475
8800
  .action((data, opts) => {
8476
8801
  const sona = loadSona();
8477
8802
  try {
8478
- const engine = sona.SonaEngine ? new sona.SonaEngine() : new sona.SonaCoordinator();
8803
+ const engine = createSonaEngine(sona);
8479
8804
  if (engine.recordTrajectory) { engine.recordTrajectory(data, opts.outcome); }
8480
8805
  else if (engine.train) { engine.train(data); }
8481
8806
  console.log(chalk.green('Training trajectory recorded.'));
@@ -8488,7 +8813,7 @@ sonaCmd.command('export')
8488
8813
  .action((opts) => {
8489
8814
  const sona = loadSona();
8490
8815
  try {
8491
- const engine = sona.SonaEngine ? new sona.SonaEngine() : new sona.SonaCoordinator();
8816
+ const engine = createSonaEngine(sona);
8492
8817
  const weights = engine.exportWeights ? engine.exportWeights() : engine.export ? engine.export() : {};
8493
8818
  fs.writeFileSync(opts.output, JSON.stringify(weights, null, 2));
8494
8819
  console.log(chalk.green(`Exported to ${opts.output}`));
@@ -8501,7 +8826,7 @@ sonaCmd.command('stats')
8501
8826
  .action((opts) => {
8502
8827
  const sona = loadSona();
8503
8828
  try {
8504
- const engine = sona.SonaEngine ? new sona.SonaEngine() : new sona.SonaCoordinator();
8829
+ const engine = createSonaEngine(sona);
8505
8830
  const stats = engine.getStats ? engine.getStats() : engine.stats ? engine.stats() : {};
8506
8831
  if (opts.json || !process.stdout.isTTY) { console.log(JSON.stringify(stats, null, 2)); return; }
8507
8832
  console.log(chalk.bold.cyan('\nSONA Statistics\n'));
package/bin/mcp-server.js CHANGED
@@ -363,7 +363,7 @@ class Intelligence {
363
363
  const server = new Server(
364
364
  {
365
365
  name: 'ruvector',
366
- version: '0.2.2',
366
+ version: '0.2.4',
367
367
  },
368
368
  {
369
369
  capabilities: {
@@ -1396,6 +1396,85 @@ const TOOLS = [
1396
1396
  }
1397
1397
  }
1398
1398
  },
1399
+ // ── Brain AGI Tools (6) ── AGI subsystem diagnostics via direct fetch ──
1400
+ {
1401
+ name: 'brain_agi_status',
1402
+ description: 'Combined AGI subsystem diagnostics — SONA, GWT, temporal, meta-learning, midstream',
1403
+ inputSchema: { type: 'object', properties: {} }
1404
+ },
1405
+ {
1406
+ name: 'brain_sona_stats',
1407
+ description: 'SONA learning engine stats — patterns, trajectories, background ticks',
1408
+ inputSchema: { type: 'object', properties: {} }
1409
+ },
1410
+ {
1411
+ name: 'brain_temporal',
1412
+ description: 'Temporal delta tracking — velocity, trend, total deltas',
1413
+ inputSchema: { type: 'object', properties: {} }
1414
+ },
1415
+ {
1416
+ name: 'brain_explore',
1417
+ description: 'Meta-learning exploration — curiosity, regret, plateau status, Pareto frontier',
1418
+ inputSchema: { type: 'object', properties: {} }
1419
+ },
1420
+ {
1421
+ name: 'brain_midstream',
1422
+ description: 'Midstream platform diagnostics — scheduler, attractor, solver, strange-loop',
1423
+ inputSchema: { type: 'object', properties: {} }
1424
+ },
1425
+ {
1426
+ name: 'brain_flags',
1427
+ description: 'Show backend feature flag state (RVF, AGI, midstream flags)',
1428
+ inputSchema: { type: 'object', properties: {} }
1429
+ },
1430
+ // ── Midstream Tools (6) ── Real-time streaming analysis platform ──
1431
+ {
1432
+ name: 'midstream_status',
1433
+ description: 'Full midstream platform diagnostics — scheduler, attractor, solver, strange-loop',
1434
+ inputSchema: { type: 'object', properties: {} }
1435
+ },
1436
+ {
1437
+ name: 'midstream_attractor',
1438
+ description: 'Attractor categories with Lyapunov exponent analysis',
1439
+ inputSchema: {
1440
+ type: 'object',
1441
+ properties: {
1442
+ category: { type: 'string', description: 'Optional category to filter (e.g., pattern, solution)' }
1443
+ }
1444
+ }
1445
+ },
1446
+ {
1447
+ name: 'midstream_scheduler',
1448
+ description: 'Nanosecond scheduler performance metrics — ticks, tasks/sec',
1449
+ inputSchema: { type: 'object', properties: {} }
1450
+ },
1451
+ {
1452
+ name: 'midstream_benchmark',
1453
+ description: 'Run sequential + concurrent latency benchmark against brain backend',
1454
+ inputSchema: {
1455
+ type: 'object',
1456
+ properties: {
1457
+ concurrent_count: { type: 'number', description: 'Number of concurrent search requests (default 20, max 100)' }
1458
+ }
1459
+ }
1460
+ },
1461
+ {
1462
+ name: 'midstream_search',
1463
+ description: 'Semantic search with midstream scoring metadata in response',
1464
+ inputSchema: {
1465
+ type: 'object',
1466
+ properties: {
1467
+ query: { type: 'string', description: 'Search query' },
1468
+ limit: { type: 'number', description: 'Max results (default 10)' }
1469
+ },
1470
+ required: ['query']
1471
+ }
1472
+ },
1473
+ {
1474
+ name: 'midstream_health',
1475
+ description: 'Combined health + midstream subsystem check',
1476
+ inputSchema: { type: 'object', properties: {} }
1477
+ },
1399
1478
  // ── Edge Tools (4) ── Distributed compute via @ruvector/edge-net ──
1400
1479
  {
1401
1480
  name: 'edge_status',
@@ -3239,6 +3318,189 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
3239
3318
  }
3240
3319
  }
3241
3320
 
3321
+ // ── Brain AGI Tool Handlers ────────────────────────────────────────────
3322
+ case 'brain_agi_status':
3323
+ case 'brain_sona_stats':
3324
+ case 'brain_temporal':
3325
+ case 'brain_explore':
3326
+ case 'brain_midstream':
3327
+ case 'brain_flags': {
3328
+ try {
3329
+ const brainUrl = process.env.BRAIN_URL || 'https://pi.ruv.io';
3330
+ const brainKey = process.env.PI;
3331
+ const hdrs = { 'Content-Type': 'application/json' };
3332
+ if (brainKey) hdrs['Authorization'] = `Bearer ${brainKey}`;
3333
+
3334
+ const endpointMap = {
3335
+ brain_agi_status: '/v1/status',
3336
+ brain_sona_stats: '/v1/sona/stats',
3337
+ brain_temporal: '/v1/temporal',
3338
+ brain_explore: '/v1/explore',
3339
+ brain_midstream: '/v1/midstream',
3340
+ brain_flags: '/v1/status',
3341
+ };
3342
+ const endpoint = endpointMap[name];
3343
+ const resp = await fetch(`${brainUrl}${endpoint}`, { headers: hdrs });
3344
+ if (!resp.ok) {
3345
+ const errText = await resp.text().catch(() => resp.statusText);
3346
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: `${resp.status} ${errText}` }, null, 2) }], isError: true };
3347
+ }
3348
+ let data = await resp.json();
3349
+
3350
+ // For brain_flags, extract only flag-related fields
3351
+ if (name === 'brain_flags') {
3352
+ const flags = {};
3353
+ for (const [k, v] of Object.entries(data)) {
3354
+ if (typeof v === 'boolean' || k.startsWith('rvf_') || k.endsWith('_enabled') || (k.startsWith('midstream_') && typeof v === 'boolean')) {
3355
+ flags[k] = v;
3356
+ }
3357
+ }
3358
+ data = flags;
3359
+ }
3360
+
3361
+ // For brain_agi_status, extract AGI-specific fields
3362
+ if (name === 'brain_agi_status') {
3363
+ const agiFields = {};
3364
+ const agiKeys = ['sona_patterns', 'sona_trajectories', 'sona_background_ticks', 'gwt_workspace_load', 'gwt_avg_salience', 'knowledge_velocity', 'temporal_deltas', 'temporal_trend', 'meta_avg_regret', 'meta_plateau_status', 'midstream_scheduler_ticks', 'midstream_attractor_categories', 'midstream_strange_loop_version'];
3365
+ for (const k of agiKeys) {
3366
+ if (data[k] !== undefined) agiFields[k] = data[k];
3367
+ }
3368
+ data = Object.keys(agiFields).length > 0 ? agiFields : data;
3369
+ }
3370
+
3371
+ return { content: [{ type: 'text', text: JSON.stringify({ success: true, ...data }, null, 2) }] };
3372
+ } catch (e) {
3373
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: e.message }, null, 2) }], isError: true };
3374
+ }
3375
+ }
3376
+
3377
+ // ── Midstream Tool Handlers ────────────────────────────────────────────
3378
+ case 'midstream_status':
3379
+ case 'midstream_attractor':
3380
+ case 'midstream_scheduler': {
3381
+ try {
3382
+ const brainUrl = process.env.BRAIN_URL || 'https://pi.ruv.io';
3383
+ const brainKey = process.env.PI;
3384
+ const hdrs = { 'Content-Type': 'application/json' };
3385
+ if (brainKey) hdrs['Authorization'] = `Bearer ${brainKey}`;
3386
+
3387
+ const resp = await fetch(`${brainUrl}/v1/midstream`, { headers: hdrs });
3388
+ if (!resp.ok) {
3389
+ const errText = await resp.text().catch(() => resp.statusText);
3390
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: `${resp.status} ${errText}` }, null, 2) }], isError: true };
3391
+ }
3392
+ let data = await resp.json();
3393
+
3394
+ if (name === 'midstream_attractor') {
3395
+ data = data.attractor_categories || data.attractors || data;
3396
+ if (args.category && typeof data === 'object') data = data[args.category] || { error: `Category '${args.category}' not found` };
3397
+ } else if (name === 'midstream_scheduler') {
3398
+ data = data.scheduler || { ticks: data.scheduler_ticks || 0 };
3399
+ }
3400
+
3401
+ return { content: [{ type: 'text', text: JSON.stringify({ success: true, ...data }, null, 2) }] };
3402
+ } catch (e) {
3403
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: e.message }, null, 2) }], isError: true };
3404
+ }
3405
+ }
3406
+
3407
+ case 'midstream_benchmark': {
3408
+ try {
3409
+ const brainUrl = process.env.BRAIN_URL || 'https://pi.ruv.io';
3410
+ const brainKey = process.env.PI;
3411
+ const hdrs = { 'Content-Type': 'application/json' };
3412
+ if (brainKey) hdrs['Authorization'] = `Bearer ${brainKey}`;
3413
+ const concurrentN = Math.min(args.concurrent_count || 20, 100);
3414
+
3415
+ async function timeFetch(url) {
3416
+ const start = performance.now();
3417
+ const resp = await fetch(url, { headers: hdrs });
3418
+ return { status: resp.status, elapsed: performance.now() - start };
3419
+ }
3420
+
3421
+ // Sequential tests
3422
+ const endpoints = [
3423
+ { path: '/v1/health', label: 'health' },
3424
+ { path: '/v1/status', label: 'status' },
3425
+ { path: '/v1/memories/search?q=test&limit=3', label: 'search' },
3426
+ { path: '/v1/midstream', label: 'midstream' },
3427
+ ];
3428
+
3429
+ const sequential = {};
3430
+ for (const ep of endpoints) {
3431
+ const times = [];
3432
+ for (let i = 0; i < 3; i++) {
3433
+ const r = await timeFetch(brainUrl + ep.path);
3434
+ times.push(r.elapsed);
3435
+ }
3436
+ sequential[ep.label] = {
3437
+ avg_ms: +(times.reduce((a, b) => a + b, 0) / times.length).toFixed(1),
3438
+ min_ms: +Math.min(...times).toFixed(1),
3439
+ max_ms: +Math.max(...times).toFixed(1)
3440
+ };
3441
+ }
3442
+
3443
+ // Concurrent search
3444
+ const promises = [];
3445
+ for (let i = 0; i < concurrentN; i++) {
3446
+ promises.push(timeFetch(brainUrl + '/v1/memories/search?q=test&limit=3'));
3447
+ }
3448
+ const results = await Promise.all(promises);
3449
+ const sorted = results.map(r => r.elapsed).sort((a, b) => a - b);
3450
+ const pct = (p) => +(sorted[Math.max(0, Math.ceil(sorted.length * p / 100) - 1)]).toFixed(1);
3451
+
3452
+ return { content: [{ type: 'text', text: JSON.stringify({
3453
+ success: true,
3454
+ sequential,
3455
+ concurrent: { count: concurrentN, p50_ms: pct(50), p90_ms: pct(90), p99_ms: pct(99) }
3456
+ }, null, 2) }] };
3457
+ } catch (e) {
3458
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: e.message }, null, 2) }], isError: true };
3459
+ }
3460
+ }
3461
+
3462
+ case 'midstream_search': {
3463
+ try {
3464
+ const brainUrl = process.env.BRAIN_URL || 'https://pi.ruv.io';
3465
+ const brainKey = process.env.PI;
3466
+ const hdrs = { 'Content-Type': 'application/json' };
3467
+ if (brainKey) hdrs['Authorization'] = `Bearer ${brainKey}`;
3468
+ const limit = Math.min(Math.max(parseInt(args.limit) || 10, 1), 100);
3469
+ const q = encodeURIComponent(args.query);
3470
+ const resp = await fetch(`${brainUrl}/v1/memories/search?q=${q}&limit=${limit}`, { headers: hdrs });
3471
+ if (!resp.ok) {
3472
+ const errText = await resp.text().catch(() => resp.statusText);
3473
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: `${resp.status} ${errText}` }, null, 2) }], isError: true };
3474
+ }
3475
+ const data = await resp.json();
3476
+ return { content: [{ type: 'text', text: JSON.stringify({ success: true, results: data, count: Array.isArray(data) ? data.length : 0 }, null, 2) }] };
3477
+ } catch (e) {
3478
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: e.message }, null, 2) }], isError: true };
3479
+ }
3480
+ }
3481
+
3482
+ case 'midstream_health': {
3483
+ try {
3484
+ const brainUrl = process.env.BRAIN_URL || 'https://pi.ruv.io';
3485
+ const brainKey = process.env.PI;
3486
+ const hdrs = { 'Content-Type': 'application/json' };
3487
+ if (brainKey) hdrs['Authorization'] = `Bearer ${brainKey}`;
3488
+
3489
+ const [healthResp, midResp] = await Promise.all([
3490
+ fetch(`${brainUrl}/v1/health`, { headers: hdrs }).then(r => r.json()).catch(e => ({ error: e.message })),
3491
+ fetch(`${brainUrl}/v1/midstream`, { headers: hdrs }).then(r => r.json()).catch(e => ({ error: e.message })),
3492
+ ]);
3493
+
3494
+ return { content: [{ type: 'text', text: JSON.stringify({
3495
+ success: true,
3496
+ health: healthResp,
3497
+ midstream: midResp
3498
+ }, null, 2) }] };
3499
+ } catch (e) {
3500
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: e.message }, null, 2) }], isError: true };
3501
+ }
3502
+ }
3503
+
3242
3504
  // ── Edge Tool Handlers ───────────────────────────────────────────────
3243
3505
  case 'edge_status':
3244
3506
  case 'edge_join':
@@ -3251,7 +3513,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
3251
3513
  switch (subCmd) {
3252
3514
  case 'status': endpoint = '/status'; break;
3253
3515
  case 'join': endpoint = '/join'; method = 'POST'; body = JSON.stringify({ contribution: args.contribution || 0.3, pi_key: process.env.PI }); break;
3254
- case 'balance': endpoint = `/balance/${process.env.PI || 'anonymous'}`; break;
3516
+ case 'balance': { const ps = process.env.PI ? require('crypto').createHash('shake256', { outputLength: 16 }).update(process.env.PI).digest('hex') : 'anonymous'; endpoint = `/balance/${ps}`; break; }
3255
3517
  case 'tasks': endpoint = `/tasks?limit=${args.limit || 20}`; break;
3256
3518
  }
3257
3519
  const resp = await fetch(`${genesisUrl}${endpoint}`, {
@@ -3259,6 +3521,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
3259
3521
  headers: { 'Content-Type': 'application/json', ...(process.env.PI ? { 'Authorization': `Bearer ${process.env.PI}` } : {}) },
3260
3522
  ...(body ? { body } : {})
3261
3523
  });
3524
+ if (!resp.ok) {
3525
+ const errText = await resp.text().catch(() => resp.statusText);
3526
+ return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: `${resp.status} ${errText}` }, null, 2) }], isError: true };
3527
+ }
3262
3528
  const data = await resp.json();
3263
3529
  return { content: [{ type: 'text', text: JSON.stringify({ success: true, ...data }, null, 2) }] };
3264
3530
  } catch (e) {
@@ -3521,7 +3787,7 @@ async function main() {
3521
3787
  transport: 'sse',
3522
3788
  sessions: sessions.size,
3523
3789
  tools: 91,
3524
- version: '0.2.2'
3790
+ version: '0.2.4'
3525
3791
  }));
3526
3792
 
3527
3793
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ruvector",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "High-performance vector database for Node.js with automatic native/WASM fallback",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",