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 +30 -1
- package/bin/cli.js +332 -7
- package/bin/mcp-server.js +269 -3
- package/package.json +1 -1
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
|
|
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').
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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.
|
|
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':
|
|
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.
|
|
3790
|
+
version: '0.2.4'
|
|
3525
3791
|
}));
|
|
3526
3792
|
|
|
3527
3793
|
} else {
|