ruvector 0.1.95 → 0.1.97
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 +91 -1
- package/bin/cli.js +255 -783
- package/bin/mcp-server.js +381 -450
- package/dist/core/index.d.ts +1 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -4
- package/dist/core/onnx-embedder.d.ts +0 -84
- package/dist/core/onnx-embedder.d.ts.map +1 -1
- package/dist/core/onnx-embedder.js +12 -167
- package/dist/core/rvf-wrapper.d.ts +86 -0
- package/dist/core/rvf-wrapper.d.ts.map +1 -0
- package/dist/core/rvf-wrapper.js +102 -0
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +61 -28
- package/package.json +5 -3
package/bin/mcp-server.js
CHANGED
|
@@ -24,7 +24,46 @@ const {
|
|
|
24
24
|
} = require('@modelcontextprotocol/sdk/types.js');
|
|
25
25
|
const path = require('path');
|
|
26
26
|
const fs = require('fs');
|
|
27
|
-
const { execSync } = require('child_process');
|
|
27
|
+
const { execSync, execFileSync } = require('child_process');
|
|
28
|
+
|
|
29
|
+
// ── Security Helpers ────────────────────────────────────────────────────────
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Validate a file path argument for RVF operations.
|
|
33
|
+
* Prevents path traversal and restricts to safe locations.
|
|
34
|
+
*/
|
|
35
|
+
function validateRvfPath(filePath) {
|
|
36
|
+
if (typeof filePath !== 'string' || filePath.length === 0) {
|
|
37
|
+
throw new Error('Path must be a non-empty string');
|
|
38
|
+
}
|
|
39
|
+
const resolved = path.resolve(filePath);
|
|
40
|
+
// Block obvious path traversal
|
|
41
|
+
if (filePath.includes('..') || filePath.includes('\0')) {
|
|
42
|
+
throw new Error('Path traversal detected');
|
|
43
|
+
}
|
|
44
|
+
// Block sensitive system paths
|
|
45
|
+
const blocked = ['/etc', '/proc', '/sys', '/dev', '/boot', '/root', '/var/run'];
|
|
46
|
+
for (const prefix of blocked) {
|
|
47
|
+
if (resolved.startsWith(prefix)) {
|
|
48
|
+
throw new Error(`Access to ${prefix} is not allowed`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return resolved;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Sanitize a shell argument to prevent command injection.
|
|
56
|
+
* Strips shell metacharacters and limits length.
|
|
57
|
+
*/
|
|
58
|
+
function sanitizeShellArg(arg) {
|
|
59
|
+
if (typeof arg !== 'string') return '';
|
|
60
|
+
// Remove null bytes, backticks, $(), and other shell metacharacters
|
|
61
|
+
return arg
|
|
62
|
+
.replace(/\0/g, '')
|
|
63
|
+
.replace(/[`$(){}|;&<>!]/g, '')
|
|
64
|
+
.replace(/\.\./g, '')
|
|
65
|
+
.slice(0, 4096);
|
|
66
|
+
}
|
|
28
67
|
|
|
29
68
|
// Try to load the full IntelligenceEngine
|
|
30
69
|
let IntelligenceEngine = null;
|
|
@@ -294,7 +333,7 @@ class Intelligence {
|
|
|
294
333
|
const server = new Server(
|
|
295
334
|
{
|
|
296
335
|
name: 'ruvector',
|
|
297
|
-
version: '0.1.
|
|
336
|
+
version: '0.1.58',
|
|
298
337
|
},
|
|
299
338
|
{
|
|
300
339
|
capabilities: {
|
|
@@ -1046,115 +1085,160 @@ const TOOLS = [
|
|
|
1046
1085
|
required: []
|
|
1047
1086
|
}
|
|
1048
1087
|
},
|
|
1049
|
-
//
|
|
1050
|
-
// EDGE-NET DISTRIBUTED AGENT/WORKER TOOLS
|
|
1051
|
-
// ============================================
|
|
1088
|
+
// ── RVF Vector Store Tools ────────────────────────────────────────────────
|
|
1052
1089
|
{
|
|
1053
|
-
name: '
|
|
1054
|
-
description: '
|
|
1090
|
+
name: 'rvf_create',
|
|
1091
|
+
description: 'Create a new RVF vector store (.rvf file) with specified dimensions and distance metric',
|
|
1055
1092
|
inputSchema: {
|
|
1056
1093
|
type: 'object',
|
|
1057
|
-
properties: {
|
|
1058
|
-
|
|
1094
|
+
properties: {
|
|
1095
|
+
path: { type: 'string', description: 'File path for the new .rvf store' },
|
|
1096
|
+
dimension: { type: 'number', description: 'Vector dimensionality (e.g. 128, 384, 768, 1536)' },
|
|
1097
|
+
metric: { type: 'string', description: 'Distance metric: cosine, l2, or dotproduct', default: 'cosine' }
|
|
1098
|
+
},
|
|
1099
|
+
required: ['path', 'dimension']
|
|
1059
1100
|
}
|
|
1060
1101
|
},
|
|
1061
1102
|
{
|
|
1062
|
-
name: '
|
|
1063
|
-
description: '
|
|
1103
|
+
name: 'rvf_open',
|
|
1104
|
+
description: 'Open an existing RVF store for read-write operations',
|
|
1064
1105
|
inputSchema: {
|
|
1065
1106
|
type: 'object',
|
|
1066
1107
|
properties: {
|
|
1067
|
-
type:
|
|
1068
|
-
type: 'string',
|
|
1069
|
-
description: 'Agent type',
|
|
1070
|
-
enum: ['researcher', 'coder', 'reviewer', 'tester', 'analyst', 'optimizer', 'coordinator', 'embedder']
|
|
1071
|
-
},
|
|
1072
|
-
task: { type: 'string', description: 'Task for the agent to perform' },
|
|
1073
|
-
max_ruv: { type: 'number', description: 'Maximum rUv credits to spend', default: 20 },
|
|
1074
|
-
priority: { type: 'string', enum: ['low', 'medium', 'high', 'critical'], default: 'medium' }
|
|
1108
|
+
path: { type: 'string', description: 'Path to existing .rvf file' }
|
|
1075
1109
|
},
|
|
1076
|
-
required: ['
|
|
1110
|
+
required: ['path']
|
|
1077
1111
|
}
|
|
1078
1112
|
},
|
|
1079
1113
|
{
|
|
1080
|
-
name: '
|
|
1081
|
-
description: '
|
|
1114
|
+
name: 'rvf_ingest',
|
|
1115
|
+
description: 'Insert vectors into an RVF store',
|
|
1082
1116
|
inputSchema: {
|
|
1083
1117
|
type: 'object',
|
|
1084
1118
|
properties: {
|
|
1085
|
-
|
|
1086
|
-
|
|
1119
|
+
path: { type: 'string', description: 'Path to .rvf store' },
|
|
1120
|
+
entries: { type: 'array', description: 'Array of {id, vector, metadata?} objects', items: { type: 'object' } }
|
|
1087
1121
|
},
|
|
1088
|
-
required: []
|
|
1122
|
+
required: ['path', 'entries']
|
|
1089
1123
|
}
|
|
1090
1124
|
},
|
|
1091
1125
|
{
|
|
1092
|
-
name: '
|
|
1093
|
-
description: '
|
|
1126
|
+
name: 'rvf_query',
|
|
1127
|
+
description: 'Query nearest neighbors in an RVF store',
|
|
1094
1128
|
inputSchema: {
|
|
1095
1129
|
type: 'object',
|
|
1096
1130
|
properties: {
|
|
1097
|
-
|
|
1098
|
-
|
|
1131
|
+
path: { type: 'string', description: 'Path to .rvf store' },
|
|
1132
|
+
vector: { type: 'array', description: 'Query vector as array of numbers', items: { type: 'number' } },
|
|
1133
|
+
k: { type: 'number', description: 'Number of results to return', default: 10 }
|
|
1099
1134
|
},
|
|
1100
|
-
required: ['
|
|
1135
|
+
required: ['path', 'vector']
|
|
1101
1136
|
}
|
|
1102
1137
|
},
|
|
1103
1138
|
{
|
|
1104
|
-
name: '
|
|
1105
|
-
description: '
|
|
1139
|
+
name: 'rvf_delete',
|
|
1140
|
+
description: 'Delete vectors by ID from an RVF store',
|
|
1106
1141
|
inputSchema: {
|
|
1107
1142
|
type: 'object',
|
|
1108
1143
|
properties: {
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
description: 'Workflow name',
|
|
1112
|
-
enum: ['code-review', 'feature-dev', 'bug-fix', 'optimization', 'research', 'custom']
|
|
1113
|
-
},
|
|
1114
|
-
task: { type: 'string', description: 'Custom task description (for custom workflow)' }
|
|
1144
|
+
path: { type: 'string', description: 'Path to .rvf store' },
|
|
1145
|
+
ids: { type: 'array', description: 'Vector IDs to delete', items: { type: 'number' } }
|
|
1115
1146
|
},
|
|
1116
|
-
required: ['
|
|
1147
|
+
required: ['path', 'ids']
|
|
1117
1148
|
}
|
|
1118
1149
|
},
|
|
1119
1150
|
{
|
|
1120
|
-
name: '
|
|
1121
|
-
description: 'Get
|
|
1151
|
+
name: 'rvf_status',
|
|
1152
|
+
description: 'Get status of an RVF store (vector count, dimension, metric, file size)',
|
|
1122
1153
|
inputSchema: {
|
|
1123
1154
|
type: 'object',
|
|
1124
|
-
properties: {
|
|
1125
|
-
|
|
1155
|
+
properties: {
|
|
1156
|
+
path: { type: 'string', description: 'Path to .rvf store' }
|
|
1157
|
+
},
|
|
1158
|
+
required: ['path']
|
|
1126
1159
|
}
|
|
1127
1160
|
},
|
|
1128
1161
|
{
|
|
1129
|
-
name: '
|
|
1130
|
-
description: '
|
|
1162
|
+
name: 'rvf_compact',
|
|
1163
|
+
description: 'Compact an RVF store to reclaim space from deleted vectors',
|
|
1131
1164
|
inputSchema: {
|
|
1132
1165
|
type: 'object',
|
|
1133
1166
|
properties: {
|
|
1134
|
-
type:
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1167
|
+
path: { type: 'string', description: 'Path to .rvf store' }
|
|
1168
|
+
},
|
|
1169
|
+
required: ['path']
|
|
1170
|
+
}
|
|
1171
|
+
},
|
|
1172
|
+
{
|
|
1173
|
+
name: 'rvf_derive',
|
|
1174
|
+
description: 'Derive a child RVF store from a parent using copy-on-write branching',
|
|
1175
|
+
inputSchema: {
|
|
1176
|
+
type: 'object',
|
|
1177
|
+
properties: {
|
|
1178
|
+
parent_path: { type: 'string', description: 'Path to parent .rvf store' },
|
|
1179
|
+
child_path: { type: 'string', description: 'Path for the new child .rvf store' }
|
|
1180
|
+
},
|
|
1181
|
+
required: ['parent_path', 'child_path']
|
|
1182
|
+
}
|
|
1183
|
+
},
|
|
1184
|
+
{
|
|
1185
|
+
name: 'rvf_segments',
|
|
1186
|
+
description: 'List all segments in an RVF file (VEC, INDEX, KERNEL, EBPF, WITNESS, etc.)',
|
|
1187
|
+
inputSchema: {
|
|
1188
|
+
type: 'object',
|
|
1189
|
+
properties: {
|
|
1190
|
+
path: { type: 'string', description: 'Path to .rvf store' }
|
|
1144
1191
|
},
|
|
1145
|
-
required: ['
|
|
1192
|
+
required: ['path']
|
|
1146
1193
|
}
|
|
1147
1194
|
},
|
|
1148
1195
|
{
|
|
1149
|
-
name: '
|
|
1150
|
-
description: '
|
|
1196
|
+
name: 'rvf_examples',
|
|
1197
|
+
description: 'List available example .rvf files with download URLs from the ruvector repository',
|
|
1151
1198
|
inputSchema: {
|
|
1152
1199
|
type: 'object',
|
|
1153
1200
|
properties: {
|
|
1154
|
-
|
|
1201
|
+
filter: { type: 'string', description: 'Filter examples by name or description substring' }
|
|
1155
1202
|
},
|
|
1156
1203
|
required: []
|
|
1157
1204
|
}
|
|
1205
|
+
},
|
|
1206
|
+
// ── rvlite Query Tools ──────────────────────────────────────────────────
|
|
1207
|
+
{
|
|
1208
|
+
name: 'rvlite_sql',
|
|
1209
|
+
description: 'Execute SQL query over rvlite vector database with optional RVF backend',
|
|
1210
|
+
inputSchema: {
|
|
1211
|
+
type: 'object',
|
|
1212
|
+
properties: {
|
|
1213
|
+
query: { type: 'string', description: 'SQL query string (supports distance() and vec_search() functions)' },
|
|
1214
|
+
db_path: { type: 'string', description: 'Path to database file (optional)' }
|
|
1215
|
+
},
|
|
1216
|
+
required: ['query']
|
|
1217
|
+
}
|
|
1218
|
+
},
|
|
1219
|
+
{
|
|
1220
|
+
name: 'rvlite_cypher',
|
|
1221
|
+
description: 'Execute Cypher graph query over rvlite property graph',
|
|
1222
|
+
inputSchema: {
|
|
1223
|
+
type: 'object',
|
|
1224
|
+
properties: {
|
|
1225
|
+
query: { type: 'string', description: 'Cypher query string' },
|
|
1226
|
+
db_path: { type: 'string', description: 'Path to database file (optional)' }
|
|
1227
|
+
},
|
|
1228
|
+
required: ['query']
|
|
1229
|
+
}
|
|
1230
|
+
},
|
|
1231
|
+
{
|
|
1232
|
+
name: 'rvlite_sparql',
|
|
1233
|
+
description: 'Execute SPARQL query over rvlite RDF triple store',
|
|
1234
|
+
inputSchema: {
|
|
1235
|
+
type: 'object',
|
|
1236
|
+
properties: {
|
|
1237
|
+
query: { type: 'string', description: 'SPARQL query string' },
|
|
1238
|
+
db_path: { type: 'string', description: 'Path to database file (optional)' }
|
|
1239
|
+
},
|
|
1240
|
+
required: ['query']
|
|
1241
|
+
}
|
|
1158
1242
|
}
|
|
1159
1243
|
];
|
|
1160
1244
|
|
|
@@ -1764,7 +1848,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1764
1848
|
|
|
1765
1849
|
case 'hooks_ast_analyze': {
|
|
1766
1850
|
try {
|
|
1767
|
-
const
|
|
1851
|
+
const safeFile = sanitizeShellArg(args.file);
|
|
1852
|
+
const output = execSync(`npx ruvector hooks ast-analyze "${safeFile}" --json`, { encoding: 'utf-8', timeout: 30000 });
|
|
1768
1853
|
return { content: [{ type: 'text', text: output }] };
|
|
1769
1854
|
} catch (e) {
|
|
1770
1855
|
return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: e.message }, null, 2) }] };
|
|
@@ -1773,8 +1858,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1773
1858
|
|
|
1774
1859
|
case 'hooks_ast_complexity': {
|
|
1775
1860
|
try {
|
|
1776
|
-
const filesArg = args.files.map(f => `"${f}"`).join(' ');
|
|
1777
|
-
const
|
|
1861
|
+
const filesArg = args.files.map(f => `"${sanitizeShellArg(f)}"`).join(' ');
|
|
1862
|
+
const threshold = parseInt(args.threshold, 10) || 10;
|
|
1863
|
+
const output = execSync(`npx ruvector hooks ast-complexity ${filesArg} --threshold ${threshold}`, { encoding: 'utf-8', timeout: 60000 });
|
|
1778
1864
|
return { content: [{ type: 'text', text: output }] };
|
|
1779
1865
|
} catch (e) {
|
|
1780
1866
|
return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: e.message }, null, 2) }] };
|
|
@@ -1783,7 +1869,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1783
1869
|
|
|
1784
1870
|
case 'hooks_diff_analyze': {
|
|
1785
1871
|
try {
|
|
1786
|
-
const cmd = args.commit ? `npx ruvector hooks diff-analyze "${args.commit}" --json` : 'npx ruvector hooks diff-analyze --json';
|
|
1872
|
+
const cmd = args.commit ? `npx ruvector hooks diff-analyze "${sanitizeShellArg(args.commit)}" --json` : 'npx ruvector hooks diff-analyze --json';
|
|
1787
1873
|
const output = execSync(cmd, { encoding: 'utf-8', timeout: 60000 });
|
|
1788
1874
|
return { content: [{ type: 'text', text: output }] };
|
|
1789
1875
|
} catch (e) {
|
|
@@ -1793,7 +1879,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1793
1879
|
|
|
1794
1880
|
case 'hooks_diff_classify': {
|
|
1795
1881
|
try {
|
|
1796
|
-
const cmd = args.commit ? `npx ruvector hooks diff-classify "${args.commit}"` : 'npx ruvector hooks diff-classify';
|
|
1882
|
+
const cmd = args.commit ? `npx ruvector hooks diff-classify "${sanitizeShellArg(args.commit)}"` : 'npx ruvector hooks diff-classify';
|
|
1797
1883
|
const output = execSync(cmd, { encoding: 'utf-8', timeout: 30000 });
|
|
1798
1884
|
return { content: [{ type: 'text', text: output }] };
|
|
1799
1885
|
} catch (e) {
|
|
@@ -1803,7 +1889,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1803
1889
|
|
|
1804
1890
|
case 'hooks_diff_similar': {
|
|
1805
1891
|
try {
|
|
1806
|
-
const
|
|
1892
|
+
const topK = parseInt(args.top_k, 10) || 5;
|
|
1893
|
+
const commits = parseInt(args.commits, 10) || 50;
|
|
1894
|
+
const output = execSync(`npx ruvector hooks diff-similar -k ${topK} --commits ${commits}`, { encoding: 'utf-8', timeout: 120000 });
|
|
1807
1895
|
return { content: [{ type: 'text', text: output }] };
|
|
1808
1896
|
} catch (e) {
|
|
1809
1897
|
return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: e.message }, null, 2) }] };
|
|
@@ -1812,7 +1900,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1812
1900
|
|
|
1813
1901
|
case 'hooks_coverage_route': {
|
|
1814
1902
|
try {
|
|
1815
|
-
const
|
|
1903
|
+
const safeFile = sanitizeShellArg(args.file);
|
|
1904
|
+
const output = execSync(`npx ruvector hooks coverage-route "${safeFile}"`, { encoding: 'utf-8', timeout: 15000 });
|
|
1816
1905
|
return { content: [{ type: 'text', text: output }] };
|
|
1817
1906
|
} catch (e) {
|
|
1818
1907
|
return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: e.message }, null, 2) }] };
|
|
@@ -1821,7 +1910,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1821
1910
|
|
|
1822
1911
|
case 'hooks_coverage_suggest': {
|
|
1823
1912
|
try {
|
|
1824
|
-
const filesArg = args.files.map(f => `"${f}"`).join(' ');
|
|
1913
|
+
const filesArg = args.files.map(f => `"${sanitizeShellArg(f)}"`).join(' ');
|
|
1825
1914
|
const output = execSync(`npx ruvector hooks coverage-suggest ${filesArg}`, { encoding: 'utf-8', timeout: 30000 });
|
|
1826
1915
|
return { content: [{ type: 'text', text: output }] };
|
|
1827
1916
|
} catch (e) {
|
|
@@ -1831,7 +1920,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1831
1920
|
|
|
1832
1921
|
case 'hooks_graph_mincut': {
|
|
1833
1922
|
try {
|
|
1834
|
-
const filesArg = args.files.map(f => `"${f}"`).join(' ');
|
|
1923
|
+
const filesArg = args.files.map(f => `"${sanitizeShellArg(f)}"`).join(' ');
|
|
1835
1924
|
const output = execSync(`npx ruvector hooks graph-mincut ${filesArg}`, { encoding: 'utf-8', timeout: 60000 });
|
|
1836
1925
|
return { content: [{ type: 'text', text: output }] };
|
|
1837
1926
|
} catch (e) {
|
|
@@ -1841,9 +1930,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1841
1930
|
|
|
1842
1931
|
case 'hooks_graph_cluster': {
|
|
1843
1932
|
try {
|
|
1844
|
-
const filesArg = args.files.map(f => `"${f}"`).join(' ');
|
|
1845
|
-
const method = args.method || 'louvain';
|
|
1846
|
-
const clusters = args.clusters || 3;
|
|
1933
|
+
const filesArg = args.files.map(f => `"${sanitizeShellArg(f)}"`).join(' ');
|
|
1934
|
+
const method = sanitizeShellArg(args.method || 'louvain');
|
|
1935
|
+
const clusters = parseInt(args.clusters, 10) || 3;
|
|
1847
1936
|
const output = execSync(`npx ruvector hooks graph-cluster ${filesArg} --method ${method} --clusters ${clusters}`, { encoding: 'utf-8', timeout: 60000 });
|
|
1848
1937
|
return { content: [{ type: 'text', text: output }] };
|
|
1849
1938
|
} catch (e) {
|
|
@@ -1853,7 +1942,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1853
1942
|
|
|
1854
1943
|
case 'hooks_security_scan': {
|
|
1855
1944
|
try {
|
|
1856
|
-
const filesArg = args.files.map(f => `"${f}"`).join(' ');
|
|
1945
|
+
const filesArg = args.files.map(f => `"${sanitizeShellArg(f)}"`).join(' ');
|
|
1857
1946
|
const output = execSync(`npx ruvector hooks security-scan ${filesArg}`, { encoding: 'utf-8', timeout: 120000 });
|
|
1858
1947
|
return { content: [{ type: 'text', text: output }] };
|
|
1859
1948
|
} catch (e) {
|
|
@@ -1863,7 +1952,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1863
1952
|
|
|
1864
1953
|
case 'hooks_rag_context': {
|
|
1865
1954
|
try {
|
|
1866
|
-
|
|
1955
|
+
const safeQuery = sanitizeShellArg(args.query);
|
|
1956
|
+
const topK = parseInt(args.top_k, 10) || 5;
|
|
1957
|
+
let cmd = `npx ruvector hooks rag-context "${safeQuery}" -k ${topK}`;
|
|
1867
1958
|
if (args.rerank) cmd += ' --rerank';
|
|
1868
1959
|
const output = execSync(cmd, { encoding: 'utf-8', timeout: 30000 });
|
|
1869
1960
|
return { content: [{ type: 'text', text: output }] };
|
|
@@ -1874,7 +1965,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1874
1965
|
|
|
1875
1966
|
case 'hooks_git_churn': {
|
|
1876
1967
|
try {
|
|
1877
|
-
const
|
|
1968
|
+
const days = parseInt(args.days, 10) || 30;
|
|
1969
|
+
const top = parseInt(args.top, 10) || 10;
|
|
1970
|
+
const output = execSync(`npx ruvector hooks git-churn --days ${days} --top ${top}`, { encoding: 'utf-8', timeout: 30000 });
|
|
1878
1971
|
return { content: [{ type: 'text', text: output }] };
|
|
1879
1972
|
} catch (e) {
|
|
1880
1973
|
return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: e.message }, null, 2) }] };
|
|
@@ -1883,8 +1976,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1883
1976
|
|
|
1884
1977
|
case 'hooks_route_enhanced': {
|
|
1885
1978
|
try {
|
|
1886
|
-
|
|
1887
|
-
|
|
1979
|
+
const safeTask = sanitizeShellArg(args.task);
|
|
1980
|
+
let cmd = `npx ruvector hooks route-enhanced "${safeTask}"`;
|
|
1981
|
+
if (args.file) cmd += ` --file "${sanitizeShellArg(args.file)}"`;
|
|
1888
1982
|
const output = execSync(cmd, { encoding: 'utf-8', timeout: 30000 });
|
|
1889
1983
|
return { content: [{ type: 'text', text: output }] };
|
|
1890
1984
|
} catch (e) {
|
|
@@ -2309,7 +2403,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
2309
2403
|
// BACKGROUND WORKERS HANDLERS (via agentic-flow)
|
|
2310
2404
|
// ============================================
|
|
2311
2405
|
case 'workers_dispatch': {
|
|
2312
|
-
const prompt = args.prompt;
|
|
2406
|
+
const prompt = sanitizeShellArg(args.prompt);
|
|
2313
2407
|
try {
|
|
2314
2408
|
const result = execSync(`npx agentic-flow@alpha workers dispatch "${prompt.replace(/"/g, '\\"')}"`, {
|
|
2315
2409
|
encoding: 'utf-8',
|
|
@@ -2490,8 +2584,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
2490
2584
|
}
|
|
2491
2585
|
|
|
2492
2586
|
case 'workers_run': {
|
|
2493
|
-
const name = args.name;
|
|
2494
|
-
const targetPath = args.path || '.';
|
|
2587
|
+
const name = sanitizeShellArg(args.name);
|
|
2588
|
+
const targetPath = sanitizeShellArg(args.path || '.');
|
|
2495
2589
|
try {
|
|
2496
2590
|
const result = execSync(`npx agentic-flow@alpha workers run "${name}" --path "${targetPath}"`, {
|
|
2497
2591
|
encoding: 'utf-8',
|
|
@@ -2557,7 +2651,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
2557
2651
|
}
|
|
2558
2652
|
|
|
2559
2653
|
case 'workers_load_config': {
|
|
2560
|
-
const configFile = args.file || 'workers.yaml';
|
|
2654
|
+
const configFile = sanitizeShellArg(args.file || 'workers.yaml');
|
|
2561
2655
|
try {
|
|
2562
2656
|
const result = execSync(`npx agentic-flow@alpha workers load-config --file "${configFile}"`, {
|
|
2563
2657
|
encoding: 'utf-8',
|
|
@@ -2578,404 +2672,241 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
2578
2672
|
}
|
|
2579
2673
|
}
|
|
2580
2674
|
|
|
2581
|
-
//
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
workers: 'Distributed browser/node worker pools',
|
|
2593
|
-
orchestration: 'Multi-agent task workflows',
|
|
2594
|
-
credits: 'rUv (Resource Utility Vouchers) for compute'
|
|
2595
|
-
},
|
|
2596
|
-
features: [
|
|
2597
|
-
'WebRTC P2P data channels',
|
|
2598
|
-
'QDAG synchronization',
|
|
2599
|
-
'Time Crystal coordination',
|
|
2600
|
-
'Neural DAG attention',
|
|
2601
|
-
'Swarm intelligence'
|
|
2602
|
-
],
|
|
2603
|
-
install: 'npm install @ruvector/edge-net',
|
|
2604
|
-
cli: 'npx edge-net start'
|
|
2605
|
-
};
|
|
2606
|
-
return { content: [{ type: 'text', text: JSON.stringify({ success: true, ...info }, null, 2) }] };
|
|
2607
|
-
}
|
|
2608
|
-
|
|
2609
|
-
case 'edge_net_spawn': {
|
|
2610
|
-
// Input validation
|
|
2611
|
-
const validAgentTypes = ['researcher', 'coder', 'reviewer', 'tester', 'analyst', 'optimizer', 'coordinator', 'embedder'];
|
|
2612
|
-
const validPriorities = ['low', 'medium', 'high', 'critical'];
|
|
2613
|
-
|
|
2614
|
-
const agentType = validAgentTypes.includes(args.type) ? args.type : 'coder';
|
|
2615
|
-
const task = typeof args.task === 'string' ? args.task.slice(0, 1000).trim() : '';
|
|
2616
|
-
const maxRuv = Math.min(Math.max(parseInt(args.max_ruv) || 20, 1), 1000);
|
|
2617
|
-
const priority = validPriorities.includes(args.priority) ? args.priority : 'medium';
|
|
2618
|
-
|
|
2619
|
-
const agentTypes = {
|
|
2620
|
-
researcher: { name: 'Researcher', capabilities: ['search', 'analyze', 'summarize'], baseRuv: 10 },
|
|
2621
|
-
coder: { name: 'Coder', capabilities: ['code', 'refactor', 'debug'], baseRuv: 15 },
|
|
2622
|
-
reviewer: { name: 'Reviewer', capabilities: ['review', 'audit', 'validate'], baseRuv: 12 },
|
|
2623
|
-
tester: { name: 'Tester', capabilities: ['test', 'benchmark', 'validate'], baseRuv: 10 },
|
|
2624
|
-
analyst: { name: 'Analyst', capabilities: ['analyze', 'metrics', 'report'], baseRuv: 8 },
|
|
2625
|
-
optimizer: { name: 'Optimizer', capabilities: ['optimize', 'profile', 'improve'], baseRuv: 15 },
|
|
2626
|
-
coordinator: { name: 'Coordinator', capabilities: ['orchestrate', 'route', 'schedule'], baseRuv: 20 },
|
|
2627
|
-
embedder: { name: 'Embedder', capabilities: ['embed', 'vectorize', 'similarity'], baseRuv: 5 }
|
|
2628
|
-
};
|
|
2629
|
-
|
|
2630
|
-
const typeInfo = agentTypes[agentType] || agentTypes.coder;
|
|
2631
|
-
const agentId = `agent-${agentType}-${Date.now()}-${Math.random().toString(36).substr(2, 6)}`;
|
|
2632
|
-
|
|
2633
|
-
// Simulate agent spawn
|
|
2634
|
-
const result = {
|
|
2635
|
-
success: true,
|
|
2636
|
-
agent: {
|
|
2637
|
-
id: agentId,
|
|
2638
|
-
type: agentType,
|
|
2639
|
-
name: typeInfo.name,
|
|
2640
|
-
capabilities: typeInfo.capabilities,
|
|
2641
|
-
task,
|
|
2642
|
-
priority,
|
|
2643
|
-
maxRuv: parseInt(maxRuv),
|
|
2644
|
-
baseRuv: typeInfo.baseRuv,
|
|
2645
|
-
status: 'spawned',
|
|
2646
|
-
estimatedCost: Math.ceil(typeInfo.baseRuv * (task.length / 100 + 1))
|
|
2647
|
-
},
|
|
2648
|
-
network: {
|
|
2649
|
-
peers: Math.floor(Math.random() * 50) + 10,
|
|
2650
|
-
availableWorkers: Math.floor(Math.random() * 20) + 5
|
|
2651
|
-
},
|
|
2652
|
-
message: `${typeInfo.name} agent spawned on edge-net`
|
|
2653
|
-
};
|
|
2654
|
-
|
|
2655
|
-
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
2675
|
+
// ── RVF Tool Handlers ─────────────────────────────────────────────────
|
|
2676
|
+
case 'rvf_create': {
|
|
2677
|
+
try {
|
|
2678
|
+
const safePath = validateRvfPath(args.path);
|
|
2679
|
+
const { createRvfStore } = require('../dist/core/rvf-wrapper.js');
|
|
2680
|
+
const store = await createRvfStore(safePath, { dimension: args.dimension, metric: args.metric || 'cosine' });
|
|
2681
|
+
const status = store.status ? await store.status() : { dimension: args.dimension };
|
|
2682
|
+
return { content: [{ type: 'text', text: JSON.stringify({ success: true, path: safePath, ...status }, null, 2) }] };
|
|
2683
|
+
} catch (e) {
|
|
2684
|
+
return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: e.message, hint: 'Install @ruvector/rvf: npm install @ruvector/rvf' }, null, 2) }], isError: true };
|
|
2685
|
+
}
|
|
2656
2686
|
}
|
|
2657
2687
|
|
|
2658
|
-
case '
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
status: 'created',
|
|
2669
|
-
minWorkers,
|
|
2670
|
-
maxWorkers,
|
|
2671
|
-
currentWorkers: minWorkers,
|
|
2672
|
-
pendingTasks: 0
|
|
2673
|
-
},
|
|
2674
|
-
network: {
|
|
2675
|
-
connectedPeers: Math.floor(Math.random() * 30) + 10,
|
|
2676
|
-
totalCapacity: Math.floor(Math.random() * 100) + 50
|
|
2677
|
-
},
|
|
2678
|
-
message: 'Worker pool created on edge-net'
|
|
2679
|
-
};
|
|
2680
|
-
|
|
2681
|
-
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
2688
|
+
case 'rvf_open': {
|
|
2689
|
+
try {
|
|
2690
|
+
const safePath = validateRvfPath(args.path);
|
|
2691
|
+
const { openRvfStore, rvfStatus } = require('../dist/core/rvf-wrapper.js');
|
|
2692
|
+
const store = await openRvfStore(safePath);
|
|
2693
|
+
const status = await rvfStatus(store);
|
|
2694
|
+
return { content: [{ type: 'text', text: JSON.stringify({ success: true, path: safePath, ...status }, null, 2) }] };
|
|
2695
|
+
} catch (e) {
|
|
2696
|
+
return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: e.message }, null, 2) }], isError: true };
|
|
2697
|
+
}
|
|
2682
2698
|
}
|
|
2683
2699
|
|
|
2684
|
-
case '
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2700
|
+
case 'rvf_ingest': {
|
|
2701
|
+
try {
|
|
2702
|
+
const safePath = validateRvfPath(args.path);
|
|
2703
|
+
const { openRvfStore, rvfIngest, rvfClose } = require('../dist/core/rvf-wrapper.js');
|
|
2704
|
+
const store = await openRvfStore(safePath);
|
|
2705
|
+
const result = await rvfIngest(store, args.entries);
|
|
2706
|
+
await rvfClose(store);
|
|
2707
|
+
return { content: [{ type: 'text', text: JSON.stringify({ success: true, ...result }, null, 2) }] };
|
|
2708
|
+
} catch (e) {
|
|
2709
|
+
return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: e.message }, null, 2) }], isError: true };
|
|
2691
2710
|
}
|
|
2692
|
-
|
|
2693
|
-
const taskId = `task-${Date.now()}-${Math.random().toString(36).substr(2, 6)}`;
|
|
2694
|
-
const result = {
|
|
2695
|
-
success: true,
|
|
2696
|
-
execution: {
|
|
2697
|
-
taskId,
|
|
2698
|
-
task,
|
|
2699
|
-
poolId: poolId || 'auto-assigned',
|
|
2700
|
-
status: 'queued',
|
|
2701
|
-
workersAssigned: Math.floor(Math.random() * 5) + 1,
|
|
2702
|
-
estimatedDuration: `${Math.floor(Math.random() * 30) + 5}s`,
|
|
2703
|
-
estimatedRuv: Math.floor(Math.random() * 10) + 3
|
|
2704
|
-
},
|
|
2705
|
-
message: 'Task queued for distributed execution'
|
|
2706
|
-
};
|
|
2707
|
-
|
|
2708
|
-
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
2709
2711
|
}
|
|
2710
2712
|
|
|
2711
|
-
case '
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
'
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
{ agent: 'optimizer', action: 'Suggest optimizations' }
|
|
2724
|
-
],
|
|
2725
|
-
estimatedRuv: 45
|
|
2726
|
-
},
|
|
2727
|
-
'feature-dev': {
|
|
2728
|
-
steps: [
|
|
2729
|
-
{ agent: 'researcher', action: 'Research requirements' },
|
|
2730
|
-
{ agent: 'coder', action: 'Implement feature' },
|
|
2731
|
-
{ agent: 'tester', action: 'Write and run tests' },
|
|
2732
|
-
{ agent: 'reviewer', action: 'Code review' }
|
|
2733
|
-
],
|
|
2734
|
-
estimatedRuv: 60
|
|
2735
|
-
},
|
|
2736
|
-
'bug-fix': {
|
|
2737
|
-
steps: [
|
|
2738
|
-
{ agent: 'analyst', action: 'Analyze bug report' },
|
|
2739
|
-
{ agent: 'coder', action: 'Implement fix' },
|
|
2740
|
-
{ agent: 'tester', action: 'Verify fix' }
|
|
2741
|
-
],
|
|
2742
|
-
estimatedRuv: 35
|
|
2743
|
-
},
|
|
2744
|
-
'optimization': {
|
|
2745
|
-
steps: [
|
|
2746
|
-
{ agent: 'analyst', action: 'Profile performance' },
|
|
2747
|
-
{ agent: 'optimizer', action: 'Identify bottlenecks' },
|
|
2748
|
-
{ agent: 'coder', action: 'Apply optimizations' },
|
|
2749
|
-
{ agent: 'tester', action: 'Benchmark results' }
|
|
2750
|
-
],
|
|
2751
|
-
estimatedRuv: 50
|
|
2752
|
-
},
|
|
2753
|
-
'research': {
|
|
2754
|
-
steps: [
|
|
2755
|
-
{ agent: 'researcher', action: 'Deep research' },
|
|
2756
|
-
{ agent: 'analyst', action: 'Analyze findings' },
|
|
2757
|
-
{ agent: 'embedder', action: 'Create knowledge embeddings' }
|
|
2758
|
-
],
|
|
2759
|
-
estimatedRuv: 30
|
|
2760
|
-
}
|
|
2761
|
-
};
|
|
2713
|
+
case 'rvf_query': {
|
|
2714
|
+
try {
|
|
2715
|
+
const safePath = validateRvfPath(args.path);
|
|
2716
|
+
const { openRvfStore, rvfQuery, rvfClose } = require('../dist/core/rvf-wrapper.js');
|
|
2717
|
+
const store = await openRvfStore(safePath);
|
|
2718
|
+
const results = await rvfQuery(store, args.vector, args.k || 10);
|
|
2719
|
+
await rvfClose(store);
|
|
2720
|
+
return { content: [{ type: 'text', text: JSON.stringify({ success: true, results }, null, 2) }] };
|
|
2721
|
+
} catch (e) {
|
|
2722
|
+
return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: e.message }, null, 2) }], isError: true };
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2762
2725
|
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2726
|
+
case 'rvf_delete': {
|
|
2727
|
+
try {
|
|
2728
|
+
const safePath = validateRvfPath(args.path);
|
|
2729
|
+
const { openRvfStore, rvfDelete, rvfClose } = require('../dist/core/rvf-wrapper.js');
|
|
2730
|
+
const store = await openRvfStore(safePath);
|
|
2731
|
+
const result = await rvfDelete(store, args.ids);
|
|
2732
|
+
await rvfClose(store);
|
|
2733
|
+
return { content: [{ type: 'text', text: JSON.stringify({ success: true, ...result }, null, 2) }] };
|
|
2734
|
+
} catch (e) {
|
|
2735
|
+
return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: e.message }, null, 2) }], isError: true };
|
|
2736
|
+
}
|
|
2737
|
+
}
|
|
2767
2738
|
|
|
2768
|
-
|
|
2739
|
+
case 'rvf_status': {
|
|
2740
|
+
try {
|
|
2741
|
+
const safePath = validateRvfPath(args.path);
|
|
2742
|
+
const { openRvfStore, rvfStatus, rvfClose } = require('../dist/core/rvf-wrapper.js');
|
|
2743
|
+
const store = await openRvfStore(safePath);
|
|
2744
|
+
const status = await rvfStatus(store);
|
|
2745
|
+
await rvfClose(store);
|
|
2746
|
+
return { content: [{ type: 'text', text: JSON.stringify({ success: true, ...status }, null, 2) }] };
|
|
2747
|
+
} catch (e) {
|
|
2748
|
+
return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: e.message }, null, 2) }], isError: true };
|
|
2749
|
+
}
|
|
2750
|
+
}
|
|
2769
2751
|
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
totalSteps: workflow.steps.length,
|
|
2783
|
-
estimatedRuv: workflow.estimatedRuv
|
|
2784
|
-
},
|
|
2785
|
-
message: `Multi-agent workflow '${name}' initiated`
|
|
2786
|
-
};
|
|
2752
|
+
case 'rvf_compact': {
|
|
2753
|
+
try {
|
|
2754
|
+
const safePath = validateRvfPath(args.path);
|
|
2755
|
+
const { openRvfStore, rvfCompact, rvfClose } = require('../dist/core/rvf-wrapper.js');
|
|
2756
|
+
const store = await openRvfStore(safePath);
|
|
2757
|
+
const result = await rvfCompact(store);
|
|
2758
|
+
await rvfClose(store);
|
|
2759
|
+
return { content: [{ type: 'text', text: JSON.stringify({ success: true, ...result }, null, 2) }] };
|
|
2760
|
+
} catch (e) {
|
|
2761
|
+
return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: e.message }, null, 2) }], isError: true };
|
|
2762
|
+
}
|
|
2763
|
+
}
|
|
2787
2764
|
|
|
2788
|
-
|
|
2765
|
+
case 'rvf_derive': {
|
|
2766
|
+
try {
|
|
2767
|
+
const safeParent = validateRvfPath(args.parent_path);
|
|
2768
|
+
const safeChild = validateRvfPath(args.child_path);
|
|
2769
|
+
const { openRvfStore, rvfDerive, rvfClose } = require('../dist/core/rvf-wrapper.js');
|
|
2770
|
+
const store = await openRvfStore(safeParent);
|
|
2771
|
+
await rvfDerive(store, safeChild);
|
|
2772
|
+
await rvfClose(store);
|
|
2773
|
+
return { content: [{ type: 'text', text: JSON.stringify({ success: true, parent: safeParent, child: safeChild }, null, 2) }] };
|
|
2774
|
+
} catch (e) {
|
|
2775
|
+
return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: e.message }, null, 2) }], isError: true };
|
|
2776
|
+
}
|
|
2789
2777
|
}
|
|
2790
2778
|
|
|
2791
|
-
case '
|
|
2792
|
-
|
|
2779
|
+
case 'rvf_segments': {
|
|
2780
|
+
try {
|
|
2781
|
+
const safePath = validateRvfPath(args.path);
|
|
2782
|
+
const { openRvfStore, rvfClose } = require('../dist/core/rvf-wrapper.js');
|
|
2783
|
+
const store = await openRvfStore(safePath);
|
|
2784
|
+
const segs = await store.segments();
|
|
2785
|
+
await rvfClose(store);
|
|
2786
|
+
return { content: [{ type: 'text', text: JSON.stringify({ success: true, segments: segs }, null, 2) }] };
|
|
2787
|
+
} catch (e) {
|
|
2788
|
+
return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: e.message }, null, 2) }], isError: true };
|
|
2789
|
+
}
|
|
2790
|
+
}
|
|
2791
|
+
|
|
2792
|
+
case 'rvf_examples': {
|
|
2793
|
+
const BASE_URL = 'https://raw.githubusercontent.com/ruvnet/ruvector/main/examples/rvf/output';
|
|
2794
|
+
const examples = [
|
|
2795
|
+
{ name: 'basic_store', size: '152 KB', desc: '1,000 vectors, dim 128' },
|
|
2796
|
+
{ name: 'semantic_search', size: '755 KB', desc: 'Semantic search with HNSW' },
|
|
2797
|
+
{ name: 'rag_pipeline', size: '303 KB', desc: 'RAG pipeline embeddings' },
|
|
2798
|
+
{ name: 'agent_memory', size: '32 KB', desc: 'AI agent episodic memory' },
|
|
2799
|
+
{ name: 'swarm_knowledge', size: '86 KB', desc: 'Multi-agent knowledge base' },
|
|
2800
|
+
{ name: 'self_booting', size: '31 KB', desc: 'Self-booting with kernel' },
|
|
2801
|
+
{ name: 'ebpf_accelerator', size: '153 KB', desc: 'eBPF distance accelerator' },
|
|
2802
|
+
{ name: 'tee_attestation', size: '102 KB', desc: 'TEE attestation + witnesses' },
|
|
2803
|
+
{ name: 'lineage_parent', size: '52 KB', desc: 'COW parent file' },
|
|
2804
|
+
{ name: 'lineage_child', size: '26 KB', desc: 'COW child (derived)' },
|
|
2805
|
+
{ name: 'claude_code_appliance', size: '17 KB', desc: 'Claude Code appliance' },
|
|
2806
|
+
{ name: 'progressive_index', size: '2.5 MB', desc: 'Large-scale HNSW index' },
|
|
2807
|
+
];
|
|
2808
|
+
let filtered = examples;
|
|
2809
|
+
if (args.filter) {
|
|
2810
|
+
const f = args.filter.toLowerCase();
|
|
2811
|
+
filtered = examples.filter(e => e.name.includes(f) || e.desc.toLowerCase().includes(f));
|
|
2812
|
+
}
|
|
2813
|
+
return { content: [{ type: 'text', text: JSON.stringify({
|
|
2793
2814
|
success: true,
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
pendingTasks: Math.floor(Math.random() * 10),
|
|
2800
|
-
completedTasks24h: Math.floor(Math.random() * 200) + 50
|
|
2801
|
-
},
|
|
2802
|
-
credits: {
|
|
2803
|
-
balance: Math.floor(Math.random() * 1000) + 100,
|
|
2804
|
-
earned24h: Math.floor(Math.random() * 50) + 5,
|
|
2805
|
-
spent24h: Math.floor(Math.random() * 30) + 2
|
|
2806
|
-
},
|
|
2807
|
-
nodes: {
|
|
2808
|
-
genesis: 3,
|
|
2809
|
-
regions: ['us-central1', 'europe-west1', 'asia-east1'],
|
|
2810
|
-
p2pConnections: Math.floor(Math.random() * 50) + 10
|
|
2811
|
-
},
|
|
2812
|
-
webrtc: {
|
|
2813
|
-
dataChannelsActive: Math.floor(Math.random() * 20) + 5,
|
|
2814
|
-
avgLatency: `${Math.floor(Math.random() * 50) + 10}ms`
|
|
2815
|
-
}
|
|
2816
|
-
};
|
|
2817
|
-
|
|
2818
|
-
return { content: [{ type: 'text', text: JSON.stringify(status, null, 2) }] };
|
|
2815
|
+
total: 45,
|
|
2816
|
+
shown: filtered.length,
|
|
2817
|
+
examples: filtered.map(e => ({ ...e, url: `${BASE_URL}/${e.name}.rvf` })),
|
|
2818
|
+
catalog: 'https://github.com/ruvnet/ruvector/tree/main/examples/rvf/output'
|
|
2819
|
+
}, null, 2) }] };
|
|
2819
2820
|
}
|
|
2820
2821
|
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
return {
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
}
|
|
2850
|
-
}, null, 2)
|
|
2851
|
-
}],
|
|
2852
|
-
isError: true
|
|
2853
|
-
};
|
|
2822
|
+
// ── rvlite Query Tool Handlers ──────────────────────────────────────
|
|
2823
|
+
case 'rvlite_sql': {
|
|
2824
|
+
try {
|
|
2825
|
+
let rvlite;
|
|
2826
|
+
try {
|
|
2827
|
+
rvlite = require('rvlite');
|
|
2828
|
+
} catch (_e) {
|
|
2829
|
+
return { content: [{ type: 'text', text: JSON.stringify({
|
|
2830
|
+
success: false,
|
|
2831
|
+
error: 'rvlite package not installed',
|
|
2832
|
+
hint: 'Install with: npm install rvlite'
|
|
2833
|
+
}, null, 2) }] };
|
|
2834
|
+
}
|
|
2835
|
+
const safeQuery = sanitizeShellArg(args.query);
|
|
2836
|
+
const dbOpts = args.db_path ? { path: validateRvfPath(args.db_path) } : {};
|
|
2837
|
+
const db = new rvlite.Database(dbOpts);
|
|
2838
|
+
const results = db.sql(safeQuery);
|
|
2839
|
+
return { content: [{ type: 'text', text: JSON.stringify({
|
|
2840
|
+
success: true,
|
|
2841
|
+
query_type: 'sql',
|
|
2842
|
+
results,
|
|
2843
|
+
row_count: Array.isArray(results) ? results.length : 0
|
|
2844
|
+
}, null, 2) }] };
|
|
2845
|
+
} catch (e) {
|
|
2846
|
+
return { content: [{ type: 'text', text: JSON.stringify({
|
|
2847
|
+
success: false,
|
|
2848
|
+
error: e.message
|
|
2849
|
+
}, null, 2) }], isError: true };
|
|
2854
2850
|
}
|
|
2851
|
+
}
|
|
2855
2852
|
|
|
2853
|
+
case 'rvlite_cypher': {
|
|
2856
2854
|
try {
|
|
2857
|
-
|
|
2858
|
-
let RealAgentManager;
|
|
2855
|
+
let rvlite;
|
|
2859
2856
|
try {
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2857
|
+
rvlite = require('rvlite');
|
|
2858
|
+
} catch (_e) {
|
|
2859
|
+
return { content: [{ type: 'text', text: JSON.stringify({
|
|
2860
|
+
success: false,
|
|
2861
|
+
error: 'rvlite package not installed',
|
|
2862
|
+
hint: 'Install with: npm install rvlite'
|
|
2863
|
+
}, null, 2) }] };
|
|
2867
2864
|
}
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
const
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
maxTokens,
|
|
2884
|
-
};
|
|
2885
|
-
|
|
2886
|
-
const startTime = Date.now();
|
|
2887
|
-
const result = await agent.execute(task, context);
|
|
2888
|
-
const duration = Date.now() - startTime;
|
|
2889
|
-
|
|
2890
|
-
await manager.close();
|
|
2891
|
-
|
|
2892
|
-
return {
|
|
2893
|
-
content: [{
|
|
2894
|
-
type: 'text',
|
|
2895
|
-
text: JSON.stringify({
|
|
2896
|
-
success: true,
|
|
2897
|
-
real_execution: true,
|
|
2898
|
-
local_mode: isLocal,
|
|
2899
|
-
agent: {
|
|
2900
|
-
id: agent.id,
|
|
2901
|
-
type: agentType,
|
|
2902
|
-
provider: effectiveProvider,
|
|
2903
|
-
model: result.model || (isLocal ? 'ruvllm-balanced' : model)
|
|
2904
|
-
},
|
|
2905
|
-
execution: {
|
|
2906
|
-
duration_ms: duration,
|
|
2907
|
-
tokens: agent.cost,
|
|
2908
|
-
fallback: result.fallback || false
|
|
2909
|
-
},
|
|
2910
|
-
response: result.content
|
|
2911
|
-
}, null, 2)
|
|
2912
|
-
}]
|
|
2913
|
-
};
|
|
2914
|
-
|
|
2915
|
-
} catch (execError) {
|
|
2916
|
-
return {
|
|
2917
|
-
content: [{
|
|
2918
|
-
type: 'text',
|
|
2919
|
-
text: JSON.stringify({
|
|
2920
|
-
success: false,
|
|
2921
|
-
error: execError.message,
|
|
2922
|
-
real_execution: true,
|
|
2923
|
-
hint: execError.message.includes('401') ? 'Check your API key is valid' : 'Check error message for details'
|
|
2924
|
-
}, null, 2)
|
|
2925
|
-
}],
|
|
2926
|
-
isError: true
|
|
2927
|
-
};
|
|
2865
|
+
const safeQuery = sanitizeShellArg(args.query);
|
|
2866
|
+
const dbOpts = args.db_path ? { path: validateRvfPath(args.db_path) } : {};
|
|
2867
|
+
const db = new rvlite.Database(dbOpts);
|
|
2868
|
+
const results = db.cypher(safeQuery);
|
|
2869
|
+
return { content: [{ type: 'text', text: JSON.stringify({
|
|
2870
|
+
success: true,
|
|
2871
|
+
query_type: 'cypher',
|
|
2872
|
+
results,
|
|
2873
|
+
row_count: Array.isArray(results) ? results.length : 0
|
|
2874
|
+
}, null, 2) }] };
|
|
2875
|
+
} catch (e) {
|
|
2876
|
+
return { content: [{ type: 'text', text: JSON.stringify({
|
|
2877
|
+
success: false,
|
|
2878
|
+
error: e.message
|
|
2879
|
+
}, null, 2) }], isError: true };
|
|
2928
2880
|
}
|
|
2929
2881
|
}
|
|
2930
2882
|
|
|
2931
|
-
case '
|
|
2932
|
-
const relayUrl = args.relay_url || 'ws://localhost:8080';
|
|
2933
|
-
|
|
2883
|
+
case 'rvlite_sparql': {
|
|
2934
2884
|
try {
|
|
2935
|
-
|
|
2936
|
-
let RelaySyncClient;
|
|
2885
|
+
let rvlite;
|
|
2937
2886
|
try {
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2887
|
+
rvlite = require('rvlite');
|
|
2888
|
+
} catch (_e) {
|
|
2889
|
+
return { content: [{ type: 'text', text: JSON.stringify({
|
|
2890
|
+
success: false,
|
|
2891
|
+
error: 'rvlite package not installed',
|
|
2892
|
+
hint: 'Install with: npm install rvlite'
|
|
2893
|
+
}, null, 2) }] };
|
|
2944
2894
|
}
|
|
2945
|
-
|
|
2946
|
-
const
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error('Connection timeout')), 5000)),
|
|
2951
|
-
]);
|
|
2952
|
-
|
|
2953
|
-
const balance = {
|
|
2895
|
+
const safeQuery = sanitizeShellArg(args.query);
|
|
2896
|
+
const dbOpts = args.db_path ? { path: validateRvfPath(args.db_path) } : {};
|
|
2897
|
+
const db = new rvlite.Database(dbOpts);
|
|
2898
|
+
const results = db.sparql(safeQuery);
|
|
2899
|
+
return { content: [{ type: 'text', text: JSON.stringify({
|
|
2954
2900
|
success: true,
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
return { content: [{ type: 'text', text: JSON.stringify(balance, null, 2) }] };
|
|
2965
|
-
|
|
2966
|
-
} catch (connError) {
|
|
2967
|
-
return {
|
|
2968
|
-
content: [{
|
|
2969
|
-
type: 'text',
|
|
2970
|
-
text: JSON.stringify({
|
|
2971
|
-
success: false,
|
|
2972
|
-
error: connError.message,
|
|
2973
|
-
relayUrl,
|
|
2974
|
-
hint: 'Start the relay server: cd examples/edge-net/relay && node index.js'
|
|
2975
|
-
}, null, 2)
|
|
2976
|
-
}],
|
|
2977
|
-
isError: true
|
|
2978
|
-
};
|
|
2901
|
+
query_type: 'sparql',
|
|
2902
|
+
results,
|
|
2903
|
+
row_count: Array.isArray(results) ? results.length : 0
|
|
2904
|
+
}, null, 2) }] };
|
|
2905
|
+
} catch (e) {
|
|
2906
|
+
return { content: [{ type: 'text', text: JSON.stringify({
|
|
2907
|
+
success: false,
|
|
2908
|
+
error: e.message
|
|
2909
|
+
}, null, 2) }], isError: true };
|
|
2979
2910
|
}
|
|
2980
2911
|
}
|
|
2981
2912
|
|