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/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.93',
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: 'edge_net_info',
1054
- description: 'Get Edge-Net distributed network information and capabilities',
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
- required: []
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: 'edge_net_spawn',
1063
- description: 'Spawn a distributed AI agent on the Edge-Net network. Agent types: researcher, coder, reviewer, tester, analyst, optimizer, coordinator, embedder',
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: ['type', 'task']
1110
+ required: ['path']
1077
1111
  }
1078
1112
  },
1079
1113
  {
1080
- name: 'edge_net_pool_create',
1081
- description: 'Create a distributed worker pool on Edge-Net for parallel task execution',
1114
+ name: 'rvf_ingest',
1115
+ description: 'Insert vectors into an RVF store',
1082
1116
  inputSchema: {
1083
1117
  type: 'object',
1084
1118
  properties: {
1085
- min_workers: { type: 'number', description: 'Minimum workers', default: 2 },
1086
- max_workers: { type: 'number', description: 'Maximum workers', default: 10 }
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: 'edge_net_pool_execute',
1093
- description: 'Execute a task on a distributed worker pool',
1126
+ name: 'rvf_query',
1127
+ description: 'Query nearest neighbors in an RVF store',
1094
1128
  inputSchema: {
1095
1129
  type: 'object',
1096
1130
  properties: {
1097
- task: { type: 'string', description: 'Task to execute' },
1098
- pool_id: { type: 'string', description: 'Pool ID (optional, auto-assigns if not provided)' }
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: ['task']
1135
+ required: ['path', 'vector']
1101
1136
  }
1102
1137
  },
1103
1138
  {
1104
- name: 'edge_net_workflow',
1105
- description: 'Run a multi-agent workflow on Edge-Net. Built-in workflows: code-review, feature-dev, bug-fix, optimization, research',
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
- name: {
1110
- type: 'string',
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: ['name']
1147
+ required: ['path', 'ids']
1117
1148
  }
1118
1149
  },
1119
1150
  {
1120
- name: 'edge_net_status',
1121
- description: 'Get Edge-Net network status including connected peers, capacity, active agents, and credits',
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
- required: []
1155
+ properties: {
1156
+ path: { type: 'string', description: 'Path to .rvf store' }
1157
+ },
1158
+ required: ['path']
1126
1159
  }
1127
1160
  },
1128
1161
  {
1129
- name: 'agent_execute',
1130
- description: 'REAL agent execution using local ruvllm (default, no API key), or cloud APIs (Anthropic/OpenAI). Local runs without needing any API key.',
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
- type: 'string',
1136
- description: 'Agent type',
1137
- enum: ['researcher', 'coder', 'reviewer', 'tester', 'analyst', 'optimizer', 'coordinator', 'embedder']
1138
- },
1139
- task: { type: 'string', description: 'Task for the agent to execute' },
1140
- provider: { type: 'string', enum: ['local', 'ruvllm', 'anthropic', 'openai'], default: 'local', description: 'LLM provider (local by default, no API key needed)' },
1141
- model: { type: 'string', enum: ['fast', 'balanced', 'powerful'], default: 'balanced', description: 'Model tier' },
1142
- context: { type: 'string', description: 'Additional context for the agent' },
1143
- max_tokens: { type: 'number', default: 4096, description: 'Maximum tokens in response' }
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: ['type', 'task']
1192
+ required: ['path']
1146
1193
  }
1147
1194
  },
1148
1195
  {
1149
- name: 'agent_balance',
1150
- description: 'Get rUv credit balance from relay server with multi-device sync status',
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
- relay_url: { type: 'string', description: 'Relay server URL', default: 'ws://localhost:8080' }
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 output = execSync(`npx ruvector hooks ast-analyze "${args.file}" --json`, { encoding: 'utf-8', timeout: 30000 });
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 output = execSync(`npx ruvector hooks ast-complexity ${filesArg} --threshold ${args.threshold || 10}`, { encoding: 'utf-8', timeout: 60000 });
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 output = execSync(`npx ruvector hooks diff-similar -k ${args.top_k || 5} --commits ${args.commits || 50}`, { encoding: 'utf-8', timeout: 120000 });
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 output = execSync(`npx ruvector hooks coverage-route "${args.file}"`, { encoding: 'utf-8', timeout: 15000 });
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
- let cmd = `npx ruvector hooks rag-context "${args.query}" -k ${args.top_k || 5}`;
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 output = execSync(`npx ruvector hooks git-churn --days ${args.days || 30} --top ${args.top || 10}`, { encoding: 'utf-8', timeout: 30000 });
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
- let cmd = `npx ruvector hooks route-enhanced "${args.task}"`;
1887
- if (args.file) cmd += ` --file "${args.file}"`;
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
- // EDGE-NET DISTRIBUTED AGENT/WORKER TOOLS
2583
- // ============================================
2584
-
2585
- case 'edge_net_info': {
2586
- const info = {
2587
- name: '@ruvector/edge-net',
2588
- version: '0.1.2',
2589
- description: 'Distributed AI agent and worker network',
2590
- capabilities: {
2591
- agents: ['researcher', 'coder', 'reviewer', 'tester', 'analyst', 'optimizer', 'coordinator', 'embedder'],
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 'edge_net_pool_create': {
2659
- const poolId = `pool-${Date.now()}-${Math.random().toString(36).substr(2, 6)}`;
2660
- // Input validation with bounds
2661
- const minWorkers = Math.min(Math.max(parseInt(args.min_workers) || 2, 1), 50);
2662
- const maxWorkers = Math.min(Math.max(parseInt(args.max_workers) || 10, minWorkers), 100);
2663
-
2664
- const result = {
2665
- success: true,
2666
- pool: {
2667
- id: poolId,
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 'edge_net_pool_execute': {
2685
- // Input validation
2686
- const task = typeof args.task === 'string' ? args.task.slice(0, 1000).trim() : '';
2687
- const poolId = typeof args.pool_id === 'string' ? args.pool_id.replace(/[^a-zA-Z0-9-_]/g, '').slice(0, 50) : null;
2688
-
2689
- if (!task) {
2690
- return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: 'Task is required' }, null, 2) }] };
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 'edge_net_workflow': {
2712
- // Input validation
2713
- const validWorkflows = ['code-review', 'feature-dev', 'bug-fix', 'optimization', 'research', 'custom'];
2714
- const name = validWorkflows.includes(args.name) ? args.name : 'custom';
2715
- const task = typeof args.task === 'string' ? args.task.slice(0, 1000).trim() : '';
2716
-
2717
- const workflows = {
2718
- 'code-review': {
2719
- steps: [
2720
- { agent: 'analyst', action: 'Analyze code structure' },
2721
- { agent: 'reviewer', action: 'Security and quality review' },
2722
- { agent: 'tester', action: 'Run test coverage analysis' },
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
- const workflow = workflows[name] || {
2764
- steps: [{ agent: 'coordinator', action: task || 'Custom task' }],
2765
- estimatedRuv: 20
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
- const workflowId = `workflow-${name}-${Date.now()}`;
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
- const result = {
2771
- success: true,
2772
- workflow: {
2773
- id: workflowId,
2774
- name,
2775
- status: 'initiated',
2776
- steps: workflow.steps.map((s, i) => ({
2777
- step: i + 1,
2778
- agent: s.agent,
2779
- action: s.action,
2780
- status: i === 0 ? 'in_progress' : 'pending'
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
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
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 'edge_net_status': {
2792
- const status = {
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
- network: {
2795
- status: 'online',
2796
- connectedPeers: Math.floor(Math.random() * 100) + 20,
2797
- totalCapacity: Math.floor(Math.random() * 500) + 100,
2798
- activeAgents: Math.floor(Math.random() * 15) + 2,
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
- case 'agent_execute': {
2822
- // REAL agent execution with local ruvllm by default, or cloud APIs
2823
- const validTypes = ['researcher', 'coder', 'reviewer', 'tester', 'analyst', 'optimizer', 'coordinator', 'embedder'];
2824
- const validModels = ['fast', 'balanced', 'powerful'];
2825
-
2826
- const agentType = validTypes.includes(args.type) ? args.type : 'coder';
2827
- const task = typeof args.task === 'string' ? args.task.slice(0, 10000).trim() : '';
2828
- const model = validModels.includes(args.model) ? args.model : 'balanced';
2829
- const maxTokens = Math.min(Math.max(parseInt(args.max_tokens) || 4096, 100), 8192);
2830
-
2831
- // Determine provider (local by default)
2832
- const provider = args.provider || 'local';
2833
- const isLocal = provider === 'local' || provider === 'ruvllm';
2834
-
2835
- // Check for API key (only required for cloud providers)
2836
- const apiKey = process.env.ANTHROPIC_API_KEY || process.env.OPENAI_API_KEY;
2837
- if (!isLocal && !apiKey && agentType !== 'embedder') {
2838
- return {
2839
- content: [{
2840
- type: 'text',
2841
- text: JSON.stringify({
2842
- success: false,
2843
- error: 'No API key configured for cloud provider',
2844
- message: 'Set ANTHROPIC_API_KEY or OPENAI_API_KEY, or use local provider (default)',
2845
- options: {
2846
- local: 'Use provider=local (no API key needed)',
2847
- anthropic: 'https://console.anthropic.com/',
2848
- openai: 'https://platform.openai.com/api-keys'
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
- // Try to load real-agents module
2858
- let RealAgentManager;
2855
+ let rvlite;
2859
2856
  try {
2860
- const realAgents = await import('@ruvector/edge-net/real-agents');
2861
- RealAgentManager = realAgents.RealAgentManager;
2862
- } catch (e) {
2863
- // Fallback to local path for development
2864
- const realAgentsPath = path.resolve(__dirname, '../../../../examples/edge-net/pkg/real-agents.js');
2865
- const realAgents = await import(realAgentsPath);
2866
- RealAgentManager = realAgents.RealAgentManager;
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
- // Initialize manager with selected provider
2870
- const manager = new RealAgentManager({
2871
- provider: isLocal ? 'local' : (apiKey && process.env.ANTHROPIC_API_KEY ? 'anthropic' : 'openai'),
2872
- apiKey: isLocal ? undefined : apiKey,
2873
- });
2874
- await manager.initialize();
2875
-
2876
- // Spawn and execute
2877
- const effectiveProvider = isLocal ? 'local' : (apiKey && process.env.ANTHROPIC_API_KEY ? 'anthropic' : 'openai');
2878
- const agent = await manager.spawn(agentType, { provider: effectiveProvider, model });
2879
-
2880
- const context = {
2881
- model,
2882
- additionalContext: args.context,
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 'agent_balance': {
2932
- const relayUrl = args.relay_url || 'ws://localhost:8080';
2933
-
2883
+ case 'rvlite_sparql': {
2934
2884
  try {
2935
- // Try to load real-agents module
2936
- let RelaySyncClient;
2885
+ let rvlite;
2937
2886
  try {
2938
- const realAgents = await import('@ruvector/edge-net/real-agents');
2939
- RelaySyncClient = realAgents.RelaySyncClient;
2940
- } catch (e) {
2941
- const realAgentsPath = path.resolve(__dirname, '../../../../examples/edge-net/pkg/real-agents.js');
2942
- const realAgents = await import(realAgentsPath);
2943
- RelaySyncClient = realAgents.RelaySyncClient;
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 client = new RelaySyncClient({ relayUrl });
2947
-
2948
- await Promise.race([
2949
- client.connect(),
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
- balance: client.getBalance(),
2956
- nodeId: client.nodeId,
2957
- relayUrl,
2958
- connected: true,
2959
- ledgerState: client.ledgerState
2960
- };
2961
-
2962
- client.close();
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