ruvector 0.1.96 → 0.1.98
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 +182 -1
- package/bin/cli.js +292 -1
- package/bin/mcp-server.js +464 -22
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -0
- 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 +4 -1
package/README.md
CHANGED
|
@@ -60,7 +60,7 @@ RuVector includes an MCP server for Claude Code with 30+ tools:
|
|
|
60
60
|
|
|
61
61
|
```bash
|
|
62
62
|
# Add to Claude Code
|
|
63
|
-
claude mcp add ruvector
|
|
63
|
+
claude mcp add ruvector -- npx ruvector mcp start
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
**Available MCP Tools:**
|
|
@@ -1940,6 +1940,9 @@ npm test
|
|
|
1940
1940
|
- **[ruvector-core](https://www.npmjs.com/package/ruvector-core)** - Core native bindings (lower-level API)
|
|
1941
1941
|
- **[ruvector-wasm](https://www.npmjs.com/package/ruvector-wasm)** - WebAssembly implementation for browsers
|
|
1942
1942
|
- **[ruvector-cli](https://www.npmjs.com/package/ruvector-cli)** - Standalone CLI tools
|
|
1943
|
+
- **[@ruvector/rvf](https://www.npmjs.com/package/@ruvector/rvf)** - RVF cognitive container SDK
|
|
1944
|
+
- **[@ruvector/rvf-wasm](https://www.npmjs.com/package/@ruvector/rvf-wasm)** - RVF WASM build for browsers, Deno, and edge
|
|
1945
|
+
- **[rvlite](https://www.npmjs.com/package/rvlite)** - Lightweight vector database with SQL, SPARQL, and Cypher
|
|
1943
1946
|
|
|
1944
1947
|
### Platform-Specific Packages (auto-installed)
|
|
1945
1948
|
|
|
@@ -1949,6 +1952,184 @@ npm test
|
|
|
1949
1952
|
- **[ruvector-core-darwin-arm64](https://www.npmjs.com/package/ruvector-core-darwin-arm64)**
|
|
1950
1953
|
- **[ruvector-core-win32-x64-msvc](https://www.npmjs.com/package/ruvector-core-win32-x64-msvc)**
|
|
1951
1954
|
|
|
1955
|
+
---
|
|
1956
|
+
|
|
1957
|
+
## RVF Cognitive Containers
|
|
1958
|
+
|
|
1959
|
+
Ruvector integrates with [RVF (RuVector Format)](https://github.com/ruvnet/ruvector/tree/main/crates/rvf) — a universal binary substrate that stores vectors, models, graphs, compute kernels, and attestation in a single `.rvf` file.
|
|
1960
|
+
|
|
1961
|
+
### Enable RVF Backend
|
|
1962
|
+
|
|
1963
|
+
```bash
|
|
1964
|
+
# Install the optional RVF package
|
|
1965
|
+
npm install @ruvector/rvf
|
|
1966
|
+
|
|
1967
|
+
# Set backend via environment variable
|
|
1968
|
+
export RUVECTOR_BACKEND=rvf
|
|
1969
|
+
|
|
1970
|
+
# Or detect automatically (native -> rvf -> wasm fallback)
|
|
1971
|
+
npx ruvector info
|
|
1972
|
+
```
|
|
1973
|
+
|
|
1974
|
+
```typescript
|
|
1975
|
+
import { getImplementationType, isRvf } from 'ruvector';
|
|
1976
|
+
|
|
1977
|
+
console.log(getImplementationType()); // 'native' | 'rvf' | 'wasm'
|
|
1978
|
+
console.log(isRvf()); // true if RVF backend is active
|
|
1979
|
+
```
|
|
1980
|
+
|
|
1981
|
+
### RVF CLI Commands
|
|
1982
|
+
|
|
1983
|
+
8 RVF-specific subcommands are available through the ruvector CLI:
|
|
1984
|
+
|
|
1985
|
+
```bash
|
|
1986
|
+
# Create an RVF store
|
|
1987
|
+
npx ruvector rvf create mydb.rvf -d 384 --metric cosine
|
|
1988
|
+
|
|
1989
|
+
# Ingest vectors from JSON
|
|
1990
|
+
npx ruvector rvf ingest mydb.rvf --input vectors.json --format json
|
|
1991
|
+
|
|
1992
|
+
# Query nearest neighbors
|
|
1993
|
+
npx ruvector rvf query mydb.rvf --vector "[0.1,0.2,...]" --k 10
|
|
1994
|
+
|
|
1995
|
+
# File status and segment listing
|
|
1996
|
+
npx ruvector rvf status mydb.rvf
|
|
1997
|
+
npx ruvector rvf segments mydb.rvf
|
|
1998
|
+
|
|
1999
|
+
# COW branching — derive a child file
|
|
2000
|
+
npx ruvector rvf derive mydb.rvf --output child.rvf
|
|
2001
|
+
|
|
2002
|
+
# Compact and reclaim space
|
|
2003
|
+
npx ruvector rvf compact mydb.rvf
|
|
2004
|
+
|
|
2005
|
+
# Export to JSON
|
|
2006
|
+
npx ruvector rvf export mydb.rvf --output dump.json
|
|
2007
|
+
```
|
|
2008
|
+
|
|
2009
|
+
### RVF Platform Support
|
|
2010
|
+
|
|
2011
|
+
| Platform | Runtime | Backend |
|
|
2012
|
+
|----------|---------|---------|
|
|
2013
|
+
| Linux x86_64 / aarch64 | Node.js 18+ | Native (N-API) |
|
|
2014
|
+
| macOS x86_64 / arm64 | Node.js 18+ | Native (N-API) |
|
|
2015
|
+
| Windows x86_64 | Node.js 18+ | Native (N-API) |
|
|
2016
|
+
| Any | Deno | WASM (`@ruvector/rvf-wasm`) |
|
|
2017
|
+
| Any | Browser | WASM (`@ruvector/rvf-wasm`) |
|
|
2018
|
+
| Any | Cloudflare Workers | WASM (`@ruvector/rvf-wasm`) |
|
|
2019
|
+
|
|
2020
|
+
### Download Example .rvf Files
|
|
2021
|
+
|
|
2022
|
+
45 pre-built example files are available (~11 MB total):
|
|
2023
|
+
|
|
2024
|
+
```bash
|
|
2025
|
+
# Download a specific example
|
|
2026
|
+
curl -LO https://raw.githubusercontent.com/ruvnet/ruvector/main/examples/rvf/output/basic_store.rvf
|
|
2027
|
+
|
|
2028
|
+
# Popular examples:
|
|
2029
|
+
# basic_store.rvf (152 KB) — 1,000 vectors, dim 128
|
|
2030
|
+
# semantic_search.rvf (755 KB) — Semantic search with HNSW
|
|
2031
|
+
# rag_pipeline.rvf (303 KB) — RAG pipeline embeddings
|
|
2032
|
+
# agent_memory.rvf (32 KB) — AI agent memory store
|
|
2033
|
+
# self_booting.rvf (31 KB) — Self-booting with kernel
|
|
2034
|
+
# progressive_index.rvf (2.5 MB) — Large-scale HNSW index
|
|
2035
|
+
|
|
2036
|
+
# Generate all examples locally
|
|
2037
|
+
cd crates/rvf && cargo run --example generate_all
|
|
2038
|
+
```
|
|
2039
|
+
|
|
2040
|
+
Full catalog: [examples/rvf/output/](https://github.com/ruvnet/ruvector/tree/main/examples/rvf/output)
|
|
2041
|
+
|
|
2042
|
+
### Working Examples: Cognitive Containers
|
|
2043
|
+
|
|
2044
|
+
#### Self-Booting Microservice
|
|
2045
|
+
|
|
2046
|
+
A single `.rvf` file that contains vectors AND a bootable Linux kernel:
|
|
2047
|
+
|
|
2048
|
+
```bash
|
|
2049
|
+
# Build and run the self-booting example
|
|
2050
|
+
cd crates/rvf && cargo run --example self_booting
|
|
2051
|
+
# Output:
|
|
2052
|
+
# Ingested 50 vectors (128 dims)
|
|
2053
|
+
# Pre-kernel query: top-5 results OK (nearest ID=25)
|
|
2054
|
+
# Kernel: 4,640 bytes embedded (x86_64, Hermit)
|
|
2055
|
+
# Witness chain: 5 entries, all verified
|
|
2056
|
+
# File: bootable.rvf (31 KB) — data + runtime in one file
|
|
2057
|
+
```
|
|
2058
|
+
|
|
2059
|
+
```rust
|
|
2060
|
+
// The pattern: vectors + kernel + witness in one file
|
|
2061
|
+
let mut store = RvfStore::create("bootable.rvf", options)?;
|
|
2062
|
+
store.ingest_batch(&vectors, &ids, None)?;
|
|
2063
|
+
store.embed_kernel(KernelArch::X86_64 as u8, KernelType::Hermit as u8,
|
|
2064
|
+
0x0018, &kernel_image, 8080, Some("console=ttyS0 quiet"))?;
|
|
2065
|
+
// Result: drop on a VM and it boots as a query service
|
|
2066
|
+
```
|
|
2067
|
+
|
|
2068
|
+
#### Linux Microkernel Distribution
|
|
2069
|
+
|
|
2070
|
+
20-package Linux distro with SSH keys and kernel in a single file:
|
|
2071
|
+
|
|
2072
|
+
```bash
|
|
2073
|
+
cd crates/rvf && cargo run --example linux_microkernel
|
|
2074
|
+
# Output:
|
|
2075
|
+
# Installed 20 packages as vector embeddings
|
|
2076
|
+
# Kernel embedded: Linux x86_64 (4,640 bytes)
|
|
2077
|
+
# SSH keys: Ed25519, signed and verified
|
|
2078
|
+
# Witness chain: 22 entries (1 per package + kernel + SSH)
|
|
2079
|
+
# File: microkernel.rvf (14 KB) — immutable bootable system
|
|
2080
|
+
```
|
|
2081
|
+
|
|
2082
|
+
Features: package search by embedding similarity, Ed25519 signed SSH keys, witness-audited installs, COW-derived child images for atomic updates.
|
|
2083
|
+
|
|
2084
|
+
#### Claude Code AI Appliance
|
|
2085
|
+
|
|
2086
|
+
A sealed, bootable AI development environment:
|
|
2087
|
+
|
|
2088
|
+
```bash
|
|
2089
|
+
cd crates/rvf && cargo run --example claude_code_appliance
|
|
2090
|
+
# Output:
|
|
2091
|
+
# 20 dev packages (rust, node, python, docker, ...)
|
|
2092
|
+
# Kernel: Linux x86_64 with SSH on port 2222
|
|
2093
|
+
# eBPF: XDP distance program for fast-path lookups
|
|
2094
|
+
# Witness chain: 6 entries, all verified
|
|
2095
|
+
# Crypto: Ed25519 signature
|
|
2096
|
+
# File: claude_code_appliance.rvf (17 KB)
|
|
2097
|
+
```
|
|
2098
|
+
|
|
2099
|
+
#### CLI Full Lifecycle
|
|
2100
|
+
|
|
2101
|
+
```bash
|
|
2102
|
+
# Create → Ingest → Query → Derive → Inspect
|
|
2103
|
+
rvf create vectors.rvf --dimension 384
|
|
2104
|
+
rvf ingest vectors.rvf --input data.json --format json
|
|
2105
|
+
rvf query vectors.rvf --vector "0.1,0.2,..." --k 10
|
|
2106
|
+
rvf derive vectors.rvf child.rvf --type filter
|
|
2107
|
+
rvf inspect vectors.rvf
|
|
2108
|
+
|
|
2109
|
+
# Embed kernel and launch as microVM
|
|
2110
|
+
rvf embed-kernel vectors.rvf --image bzImage
|
|
2111
|
+
rvf launch vectors.rvf --port 8080
|
|
2112
|
+
|
|
2113
|
+
# Verify tamper-evident witness chain
|
|
2114
|
+
rvf verify-witness vectors.rvf
|
|
2115
|
+
rvf verify-attestation vectors.rvf
|
|
2116
|
+
```
|
|
2117
|
+
|
|
2118
|
+
#### Integration Tests (46 passing)
|
|
2119
|
+
|
|
2120
|
+
```bash
|
|
2121
|
+
cd crates/rvf
|
|
2122
|
+
cargo test --workspace
|
|
2123
|
+
# attestation .............. 6 passed
|
|
2124
|
+
# crypto ................... 10 passed
|
|
2125
|
+
# computational_container .. 8 passed
|
|
2126
|
+
# cow_branching ............ 8 passed
|
|
2127
|
+
# cross_platform ........... 6 passed
|
|
2128
|
+
# lineage .................. 4 passed
|
|
2129
|
+
# smoke .................... 4 passed
|
|
2130
|
+
# Total: 46/46 passed
|
|
2131
|
+
```
|
|
2132
|
+
|
|
1952
2133
|
## 🐛 Troubleshooting
|
|
1953
2134
|
|
|
1954
2135
|
### Native Module Not Loading
|
package/bin/cli.js
CHANGED
|
@@ -7007,6 +7007,280 @@ nativeCmd.command('compare')
|
|
|
7007
7007
|
}
|
|
7008
7008
|
});
|
|
7009
7009
|
|
|
7010
|
+
// RVF (RuVector Format) commands
|
|
7011
|
+
const rvfCmd = program.command('rvf').description('RuVector Format (.rvf) cognitive container operations');
|
|
7012
|
+
|
|
7013
|
+
rvfCmd.command('create <path>')
|
|
7014
|
+
.description('Create a new .rvf store')
|
|
7015
|
+
.requiredOption('-d, --dimension <n>', 'Vector dimension', parseInt)
|
|
7016
|
+
.option('-m, --metric <metric>', 'Distance metric (l2, cosine, dotproduct)', 'cosine')
|
|
7017
|
+
.action(async (storePath, opts) => {
|
|
7018
|
+
try {
|
|
7019
|
+
const { createRvfStore, rvfClose } = require('../dist/core/rvf-wrapper.js');
|
|
7020
|
+
const store = await createRvfStore(storePath, { dimensions: opts.dimension, metric: opts.metric });
|
|
7021
|
+
await rvfClose(store);
|
|
7022
|
+
console.log(chalk.green(`Created ${storePath} (dim=${opts.dimension}, metric=${opts.metric})`));
|
|
7023
|
+
} catch (e) { console.error(chalk.red(e.message)); process.exit(1); }
|
|
7024
|
+
});
|
|
7025
|
+
|
|
7026
|
+
rvfCmd.command('ingest <path>')
|
|
7027
|
+
.description('Ingest vectors into an .rvf store')
|
|
7028
|
+
.requiredOption('-i, --input <file>', 'Input file (JSON array of {id, vector})')
|
|
7029
|
+
.option('-f, --format <fmt>', 'Input format (json)', 'json')
|
|
7030
|
+
.action(async (storePath, opts) => {
|
|
7031
|
+
try {
|
|
7032
|
+
const { openRvfStore, rvfIngest, rvfClose } = require('../dist/core/rvf-wrapper.js');
|
|
7033
|
+
const store = await openRvfStore(storePath);
|
|
7034
|
+
const data = JSON.parse(fs.readFileSync(opts.input, 'utf8'));
|
|
7035
|
+
const result = await rvfIngest(store, data);
|
|
7036
|
+
await rvfClose(store);
|
|
7037
|
+
console.log(chalk.green(`Ingested ${result.accepted} vectors (${result.rejected} rejected)`));
|
|
7038
|
+
} catch (e) { console.error(chalk.red(e.message)); process.exit(1); }
|
|
7039
|
+
});
|
|
7040
|
+
|
|
7041
|
+
rvfCmd.command('query <path>')
|
|
7042
|
+
.description('Query nearest neighbors')
|
|
7043
|
+
.requiredOption('-v, --vector <values>', 'Comma-separated vector values')
|
|
7044
|
+
.option('-k, --k <n>', 'Number of results', parseInt, 10)
|
|
7045
|
+
.action(async (storePath, opts) => {
|
|
7046
|
+
try {
|
|
7047
|
+
const { openRvfStore, rvfQuery, rvfClose } = require('../dist/core/rvf-wrapper.js');
|
|
7048
|
+
const store = await openRvfStore(storePath);
|
|
7049
|
+
const vector = opts.vector.split(',').map(Number);
|
|
7050
|
+
const results = await rvfQuery(store, vector, opts.k);
|
|
7051
|
+
await rvfClose(store);
|
|
7052
|
+
results.forEach((r, i) => console.log(chalk.dim(` ${i+1}. id=${r.id} dist=${r.distance.toFixed(6)}`)));
|
|
7053
|
+
console.log(chalk.green(`${results.length} results`));
|
|
7054
|
+
} catch (e) { console.error(chalk.red(e.message)); process.exit(1); }
|
|
7055
|
+
});
|
|
7056
|
+
|
|
7057
|
+
rvfCmd.command('status <path>')
|
|
7058
|
+
.description('Show store statistics')
|
|
7059
|
+
.action(async (storePath) => {
|
|
7060
|
+
try {
|
|
7061
|
+
const { openRvfStore, rvfStatus, rvfClose } = require('../dist/core/rvf-wrapper.js');
|
|
7062
|
+
const store = await openRvfStore(storePath);
|
|
7063
|
+
const s = await rvfStatus(store);
|
|
7064
|
+
await rvfClose(store);
|
|
7065
|
+
console.log(chalk.cyan('RVF Store Status'));
|
|
7066
|
+
Object.entries(s).forEach(([k, v]) => console.log(chalk.dim(` ${k}: ${v}`)));
|
|
7067
|
+
} catch (e) { console.error(chalk.red(e.message)); process.exit(1); }
|
|
7068
|
+
});
|
|
7069
|
+
|
|
7070
|
+
rvfCmd.command('segments <path>')
|
|
7071
|
+
.description('List all segments in an .rvf file')
|
|
7072
|
+
.action(async (storePath) => {
|
|
7073
|
+
try {
|
|
7074
|
+
const { openRvfStore, rvfClose } = require('../dist/core/rvf-wrapper.js');
|
|
7075
|
+
const store = await openRvfStore(storePath);
|
|
7076
|
+
const segs = await store.segments();
|
|
7077
|
+
await rvfClose(store);
|
|
7078
|
+
segs.forEach((seg, i) => console.log(chalk.dim(` [${i}] type=0x${seg.type.toString(16)} size=${seg.size}`)));
|
|
7079
|
+
console.log(chalk.green(`${segs.length} segments`));
|
|
7080
|
+
} catch (e) { console.error(chalk.red(e.message)); process.exit(1); }
|
|
7081
|
+
});
|
|
7082
|
+
|
|
7083
|
+
rvfCmd.command('derive <parent> <child>')
|
|
7084
|
+
.description('Create a derived store with lineage tracking')
|
|
7085
|
+
.action(async (parentPath, childPath) => {
|
|
7086
|
+
try {
|
|
7087
|
+
const { openRvfStore, rvfDerive, rvfClose } = require('../dist/core/rvf-wrapper.js');
|
|
7088
|
+
const store = await openRvfStore(parentPath);
|
|
7089
|
+
await rvfDerive(store, childPath);
|
|
7090
|
+
await rvfClose(store);
|
|
7091
|
+
console.log(chalk.green(`Derived ${childPath} from ${parentPath}`));
|
|
7092
|
+
} catch (e) { console.error(chalk.red(e.message)); process.exit(1); }
|
|
7093
|
+
});
|
|
7094
|
+
|
|
7095
|
+
rvfCmd.command('compact <path>')
|
|
7096
|
+
.description('Compact store, reclaim deleted space')
|
|
7097
|
+
.action(async (storePath) => {
|
|
7098
|
+
try {
|
|
7099
|
+
const { openRvfStore, rvfCompact, rvfClose } = require('../dist/core/rvf-wrapper.js');
|
|
7100
|
+
const store = await openRvfStore(storePath);
|
|
7101
|
+
const result = await rvfCompact(store);
|
|
7102
|
+
await rvfClose(store);
|
|
7103
|
+
console.log(chalk.green(`Compacted: ${result.segmentsCompacted} segments, ${result.bytesReclaimed} bytes reclaimed`));
|
|
7104
|
+
} catch (e) { console.error(chalk.red(e.message)); process.exit(1); }
|
|
7105
|
+
});
|
|
7106
|
+
|
|
7107
|
+
rvfCmd.command('export <path>')
|
|
7108
|
+
.description('Export store data')
|
|
7109
|
+
.option('-o, --output <file>', 'Output file')
|
|
7110
|
+
.action(async (storePath, opts) => {
|
|
7111
|
+
try {
|
|
7112
|
+
const { openRvfStore, rvfStatus, rvfClose } = require('../dist/core/rvf-wrapper.js');
|
|
7113
|
+
const store = await openRvfStore(storePath);
|
|
7114
|
+
const status = await rvfStatus(store);
|
|
7115
|
+
const segs = await store.segments();
|
|
7116
|
+
await rvfClose(store);
|
|
7117
|
+
const data = JSON.stringify({ status, segments: segs }, null, 2);
|
|
7118
|
+
if (opts.output) { fs.writeFileSync(opts.output, data); console.log(chalk.green(`Exported to ${opts.output}`)); }
|
|
7119
|
+
else { console.log(data); }
|
|
7120
|
+
} catch (e) { console.error(chalk.red(e.message)); process.exit(1); }
|
|
7121
|
+
});
|
|
7122
|
+
|
|
7123
|
+
// RVF example download/list commands
|
|
7124
|
+
const RVF_EXAMPLES = [
|
|
7125
|
+
{ name: 'basic_store', size: '152 KB', desc: '1,000 vectors, dim 128, cosine metric' },
|
|
7126
|
+
{ name: 'semantic_search', size: '755 KB', desc: 'Semantic search with HNSW index' },
|
|
7127
|
+
{ name: 'rag_pipeline', size: '303 KB', desc: 'RAG pipeline with embeddings' },
|
|
7128
|
+
{ name: 'embedding_cache', size: '755 KB', desc: 'Cached embedding store' },
|
|
7129
|
+
{ name: 'quantization', size: '1.5 MB', desc: 'PQ-compressed vectors' },
|
|
7130
|
+
{ name: 'progressive_index', size: '2.5 MB', desc: 'Large-scale progressive HNSW index' },
|
|
7131
|
+
{ name: 'filtered_search', size: '255 KB', desc: 'Metadata-filtered vector search' },
|
|
7132
|
+
{ name: 'recommendation', size: '102 KB', desc: 'Recommendation engine vectors' },
|
|
7133
|
+
{ name: 'agent_memory', size: '32 KB', desc: 'AI agent episodic memory' },
|
|
7134
|
+
{ name: 'swarm_knowledge', size: '86 KB', desc: 'Multi-agent shared knowledge base' },
|
|
7135
|
+
{ name: 'experience_replay', size: '27 KB', desc: 'RL experience replay buffer' },
|
|
7136
|
+
{ name: 'tool_cache', size: '26 KB', desc: 'MCP tool call cache' },
|
|
7137
|
+
{ name: 'mcp_in_rvf', size: '32 KB', desc: 'MCP server embedded in RVF' },
|
|
7138
|
+
{ name: 'ruvbot', size: '51 KB', desc: 'Chatbot knowledge store' },
|
|
7139
|
+
{ name: 'claude_code_appliance', size: '17 KB', desc: 'Claude Code cognitive appliance' },
|
|
7140
|
+
{ name: 'lineage_parent', size: '52 KB', desc: 'COW parent file' },
|
|
7141
|
+
{ name: 'lineage_child', size: '26 KB', desc: 'COW child (derived) file' },
|
|
7142
|
+
{ name: 'self_booting', size: '31 KB', desc: 'Self-booting with KERNEL_SEG' },
|
|
7143
|
+
{ name: 'linux_microkernel', size: '15 KB', desc: 'Embedded Linux microkernel' },
|
|
7144
|
+
{ name: 'ebpf_accelerator', size: '153 KB', desc: 'eBPF distance accelerator' },
|
|
7145
|
+
{ name: 'browser_wasm', size: '14 KB', desc: 'Browser WASM module embedded' },
|
|
7146
|
+
{ name: 'tee_attestation', size: '102 KB', desc: 'TEE attestation with witnesses' },
|
|
7147
|
+
{ name: 'zero_knowledge', size: '52 KB', desc: 'ZK-proof witness chain' },
|
|
7148
|
+
{ name: 'sealed_engine', size: '208 KB', desc: 'Sealed inference engine' },
|
|
7149
|
+
{ name: 'access_control', size: '77 KB', desc: 'Permission-gated vectors' },
|
|
7150
|
+
{ name: 'financial_signals', size: '202 KB', desc: 'Financial signal vectors' },
|
|
7151
|
+
{ name: 'medical_imaging', size: '302 KB', desc: 'Medical imaging embeddings' },
|
|
7152
|
+
{ name: 'legal_discovery', size: '903 KB', desc: 'Legal document discovery' },
|
|
7153
|
+
{ name: 'multimodal_fusion', size: '804 KB', desc: 'Multi-modal embedding fusion' },
|
|
7154
|
+
{ name: 'hyperbolic_taxonomy', size: '23 KB', desc: 'Hyperbolic space taxonomy' },
|
|
7155
|
+
{ name: 'network_telemetry', size: '16 KB', desc: 'Network telemetry vectors' },
|
|
7156
|
+
{ name: 'postgres_bridge', size: '152 KB', desc: 'PostgreSQL bridge vectors' },
|
|
7157
|
+
{ name: 'ruvllm_inference', size: '133 KB', desc: 'RuvLLM inference cache' },
|
|
7158
|
+
{ name: 'serverless', size: '509 KB', desc: 'Serverless deployment bundle' },
|
|
7159
|
+
{ name: 'edge_iot', size: '27 KB', desc: 'Edge/IoT lightweight store' },
|
|
7160
|
+
{ name: 'dedup_detector', size: '153 KB', desc: 'Deduplication detector' },
|
|
7161
|
+
{ name: 'compacted', size: '77 KB', desc: 'Post-compaction example' },
|
|
7162
|
+
{ name: 'posix_fileops', size: '52 KB', desc: 'POSIX file operations test' },
|
|
7163
|
+
{ name: 'network_sync_a', size: '52 KB', desc: 'Network sync peer A' },
|
|
7164
|
+
{ name: 'network_sync_b', size: '52 KB', desc: 'Network sync peer B' },
|
|
7165
|
+
{ name: 'agent_handoff_a', size: '31 KB', desc: 'Agent handoff source' },
|
|
7166
|
+
{ name: 'agent_handoff_b', size: '11 KB', desc: 'Agent handoff target' },
|
|
7167
|
+
{ name: 'reasoning_parent', size: '5.6 KB', desc: 'Reasoning chain parent' },
|
|
7168
|
+
{ name: 'reasoning_child', size: '8.1 KB', desc: 'Reasoning chain child' },
|
|
7169
|
+
{ name: 'reasoning_grandchild', size: '162 B', desc: 'Minimal derived file' },
|
|
7170
|
+
];
|
|
7171
|
+
|
|
7172
|
+
const RVF_BASE_URL = 'https://raw.githubusercontent.com/ruvnet/ruvector/main/examples/rvf/output';
|
|
7173
|
+
|
|
7174
|
+
rvfCmd.command('examples')
|
|
7175
|
+
.description('List available example .rvf files')
|
|
7176
|
+
.option('--json', 'Output as JSON')
|
|
7177
|
+
.action((opts) => {
|
|
7178
|
+
if (opts.json) {
|
|
7179
|
+
console.log(JSON.stringify(RVF_EXAMPLES, null, 2));
|
|
7180
|
+
return;
|
|
7181
|
+
}
|
|
7182
|
+
console.log(chalk.bold.cyan('\nAvailable RVF Example Files (45 total)\n'));
|
|
7183
|
+
console.log(chalk.dim(`Download: npx ruvector rvf download <name>\n`));
|
|
7184
|
+
const maxName = Math.max(...RVF_EXAMPLES.map(e => e.name.length));
|
|
7185
|
+
const maxSize = Math.max(...RVF_EXAMPLES.map(e => e.size.length));
|
|
7186
|
+
for (const ex of RVF_EXAMPLES) {
|
|
7187
|
+
const name = chalk.green(ex.name.padEnd(maxName));
|
|
7188
|
+
const size = chalk.yellow(ex.size.padStart(maxSize));
|
|
7189
|
+
console.log(` ${name} ${size} ${chalk.dim(ex.desc)}`);
|
|
7190
|
+
}
|
|
7191
|
+
console.log(chalk.dim(`\nFull catalog: https://github.com/ruvnet/ruvector/tree/main/examples/rvf/output\n`));
|
|
7192
|
+
});
|
|
7193
|
+
|
|
7194
|
+
rvfCmd.command('download [names...]')
|
|
7195
|
+
.description('Download example .rvf files from GitHub')
|
|
7196
|
+
.option('-a, --all', 'Download all 45 examples (~11 MB)')
|
|
7197
|
+
.option('-o, --output <dir>', 'Output directory', '.')
|
|
7198
|
+
.action(async (names, opts) => {
|
|
7199
|
+
const https = require('https');
|
|
7200
|
+
const ALLOWED_REDIRECT_HOSTS = ['raw.githubusercontent.com', 'objects.githubusercontent.com', 'github.com'];
|
|
7201
|
+
const sanitizeFileName = (name) => {
|
|
7202
|
+
// Strip path separators and parent directory references
|
|
7203
|
+
const base = path.basename(name);
|
|
7204
|
+
// Only allow alphanumeric, underscores, hyphens, dots
|
|
7205
|
+
if (!/^[\w\-.]+$/.test(base)) throw new Error(`Invalid filename: ${base}`);
|
|
7206
|
+
return base;
|
|
7207
|
+
};
|
|
7208
|
+
const downloadFile = (url, dest) => new Promise((resolve, reject) => {
|
|
7209
|
+
const file = fs.createWriteStream(dest);
|
|
7210
|
+
https.get(url, (res) => {
|
|
7211
|
+
if (res.statusCode === 302 || res.statusCode === 301) {
|
|
7212
|
+
const redirectUrl = res.headers.location;
|
|
7213
|
+
try {
|
|
7214
|
+
const redirectHost = new URL(redirectUrl).hostname;
|
|
7215
|
+
if (!ALLOWED_REDIRECT_HOSTS.includes(redirectHost)) {
|
|
7216
|
+
file.close();
|
|
7217
|
+
reject(new Error(`Redirect to untrusted host: ${redirectHost}`));
|
|
7218
|
+
return;
|
|
7219
|
+
}
|
|
7220
|
+
} catch { file.close(); reject(new Error('Invalid redirect URL')); return; }
|
|
7221
|
+
https.get(redirectUrl, (res2) => { res2.pipe(file); file.on('finish', () => { file.close(); resolve(); }); }).on('error', reject);
|
|
7222
|
+
return;
|
|
7223
|
+
}
|
|
7224
|
+
if (res.statusCode !== 200) { file.close(); fs.unlinkSync(dest); reject(new Error(`HTTP ${res.statusCode}`)); return; }
|
|
7225
|
+
res.pipe(file);
|
|
7226
|
+
file.on('finish', () => { file.close(); resolve(); });
|
|
7227
|
+
}).on('error', reject);
|
|
7228
|
+
});
|
|
7229
|
+
|
|
7230
|
+
let toDownload = [];
|
|
7231
|
+
if (opts.all) {
|
|
7232
|
+
toDownload = RVF_EXAMPLES.map(e => e.name);
|
|
7233
|
+
} else if (names && names.length > 0) {
|
|
7234
|
+
toDownload = names;
|
|
7235
|
+
} else {
|
|
7236
|
+
console.error(chalk.red('Specify example names or use --all. Run `npx ruvector rvf examples` to list.'));
|
|
7237
|
+
process.exit(1);
|
|
7238
|
+
}
|
|
7239
|
+
|
|
7240
|
+
const outDir = path.resolve(opts.output);
|
|
7241
|
+
if (!fs.existsSync(outDir)) fs.mkdirSync(outDir, { recursive: true });
|
|
7242
|
+
|
|
7243
|
+
console.log(chalk.bold.cyan(`\nDownloading ${toDownload.length} .rvf file(s) to ${outDir}\n`));
|
|
7244
|
+
let ok = 0, fail = 0;
|
|
7245
|
+
for (const name of toDownload) {
|
|
7246
|
+
const rawName = name.endsWith('.rvf') ? name : `${name}.rvf`;
|
|
7247
|
+
let fileName;
|
|
7248
|
+
try { fileName = sanitizeFileName(rawName); } catch (e) {
|
|
7249
|
+
console.log(chalk.red(`SKIPPED: ${e.message}`));
|
|
7250
|
+
fail++;
|
|
7251
|
+
continue;
|
|
7252
|
+
}
|
|
7253
|
+
// Validate against known examples when not using --all
|
|
7254
|
+
if (!opts.all) {
|
|
7255
|
+
const baseName = fileName.replace(/\.rvf$/, '');
|
|
7256
|
+
if (!RVF_EXAMPLES.some(e => e.name === baseName)) {
|
|
7257
|
+
console.log(chalk.red(`SKIPPED: Unknown example '${baseName}'. Run 'npx ruvector rvf examples' to list.`));
|
|
7258
|
+
fail++;
|
|
7259
|
+
continue;
|
|
7260
|
+
}
|
|
7261
|
+
}
|
|
7262
|
+
const url = `${RVF_BASE_URL}/${encodeURIComponent(fileName)}`;
|
|
7263
|
+
const dest = path.join(outDir, fileName);
|
|
7264
|
+
// Path containment check
|
|
7265
|
+
if (!path.resolve(dest).startsWith(path.resolve(outDir) + path.sep) && path.resolve(dest) !== path.resolve(outDir)) {
|
|
7266
|
+
console.log(chalk.red(`SKIPPED: Path traversal detected for '${fileName}'`));
|
|
7267
|
+
fail++;
|
|
7268
|
+
continue;
|
|
7269
|
+
}
|
|
7270
|
+
try {
|
|
7271
|
+
process.stdout.write(chalk.dim(` ${fileName} ... `));
|
|
7272
|
+
await downloadFile(url, dest);
|
|
7273
|
+
const stat = fs.statSync(dest);
|
|
7274
|
+
console.log(chalk.green(`OK (${(stat.size / 1024).toFixed(0)} KB)`));
|
|
7275
|
+
ok++;
|
|
7276
|
+
} catch (e) {
|
|
7277
|
+
console.log(chalk.red(`FAILED: ${e.message}`));
|
|
7278
|
+
fail++;
|
|
7279
|
+
}
|
|
7280
|
+
}
|
|
7281
|
+
console.log(chalk.bold(`\nDone: ${ok} downloaded, ${fail} failed\n`));
|
|
7282
|
+
});
|
|
7283
|
+
|
|
7010
7284
|
// MCP Server command
|
|
7011
7285
|
const mcpCmd = program.command('mcp').description('MCP (Model Context Protocol) server for Claude Code integration');
|
|
7012
7286
|
|
|
@@ -7029,7 +7303,7 @@ mcpCmd.command('info')
|
|
|
7029
7303
|
console.log(chalk.white('The RuVector MCP server provides self-learning intelligence'));
|
|
7030
7304
|
console.log(chalk.white('tools to Claude Code via the Model Context Protocol.\n'));
|
|
7031
7305
|
|
|
7032
|
-
console.log(chalk.bold('
|
|
7306
|
+
console.log(chalk.bold('Hooks Tools:'));
|
|
7033
7307
|
console.log(chalk.dim(' hooks_stats - Get intelligence statistics'));
|
|
7034
7308
|
console.log(chalk.dim(' hooks_route - Route task to best agent'));
|
|
7035
7309
|
console.log(chalk.dim(' hooks_remember - Store context in vector memory'));
|
|
@@ -7041,6 +7315,23 @@ mcpCmd.command('info')
|
|
|
7041
7315
|
console.log(chalk.dim(' hooks_doctor - Diagnose setup issues'));
|
|
7042
7316
|
console.log(chalk.dim(' hooks_export - Export intelligence data'));
|
|
7043
7317
|
|
|
7318
|
+
console.log(chalk.bold('\nRVF Vector Store Tools:'));
|
|
7319
|
+
console.log(chalk.dim(' rvf_create - Create new .rvf vector store'));
|
|
7320
|
+
console.log(chalk.dim(' rvf_open - Open existing .rvf store'));
|
|
7321
|
+
console.log(chalk.dim(' rvf_ingest - Insert vectors into store'));
|
|
7322
|
+
console.log(chalk.dim(' rvf_query - Query nearest neighbors'));
|
|
7323
|
+
console.log(chalk.dim(' rvf_delete - Delete vectors by ID'));
|
|
7324
|
+
console.log(chalk.dim(' rvf_status - Get store status'));
|
|
7325
|
+
console.log(chalk.dim(' rvf_compact - Compact store'));
|
|
7326
|
+
console.log(chalk.dim(' rvf_derive - COW-branch to child store'));
|
|
7327
|
+
console.log(chalk.dim(' rvf_segments - List file segments'));
|
|
7328
|
+
console.log(chalk.dim(' rvf_examples - List example .rvf files'));
|
|
7329
|
+
|
|
7330
|
+
console.log(chalk.bold('\nrvlite Query Tools:'));
|
|
7331
|
+
console.log(chalk.dim(' rvlite_sql - Execute SQL query over rvlite vector DB'));
|
|
7332
|
+
console.log(chalk.dim(' rvlite_cypher - Execute Cypher graph query'));
|
|
7333
|
+
console.log(chalk.dim(' rvlite_sparql - Execute SPARQL RDF query'));
|
|
7334
|
+
|
|
7044
7335
|
console.log(chalk.bold('\n📦 Resources:'));
|
|
7045
7336
|
console.log(chalk.dim(' ruvector://intelligence/stats - Current statistics'));
|
|
7046
7337
|
console.log(chalk.dim(' ruvector://intelligence/patterns - Learned patterns'));
|