Skip to content

Commit cd89483

Browse files
authored
Merge pull request #215 from ruvnet/claude/research-openfang-jpAtV
fix(ruvector-gnn): replace panic with Result + OpenFang RVF example
2 parents de9b508 + ec9a611 commit cd89483

File tree

31 files changed

+2904
-1041
lines changed

31 files changed

+2904
-1041
lines changed

Cargo.lock

Lines changed: 1061 additions & 793 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ members = [
115115
resolver = "2"
116116

117117
[workspace.package]
118-
version = "2.0.4"
118+
version = "2.0.5"
119119
edition = "2021"
120120
rust-version = "1.77"
121121
license = "MIT"

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ Most vector databases are static — they store embeddings and search them. That
113113
| 44 | **Drop into Postgres** | pgvector-compatible extension with SIMD acceleration |
114114
| 45 | **MCP integration** | Model Context Protocol server for AI assistant tools |
115115
| 46 | **Cloud deployment** | One-click deploy to Cloud Run, Kubernetes |
116-
| 47 | **13 Rust crates + 4 npm packages** | [RVF SDK](./crates/rvf/README.md) published on [crates.io](https://crates.io/crates/rvf-runtime) and [npm](https://www.npmjs.com/package/@ruvector/rvf) |
116+
| 47 | **22 Rust crates + 4 npm packages** | [RVF SDK](./crates/rvf/README.md) published on [crates.io](https://crates.io/crates/rvf-runtime) and [npm](https://www.npmjs.com/package/@ruvector/rvf) |
117117

118118
**Self-Learning & Adaptation**
119119
| # | Capability | What It Does |
@@ -238,7 +238,7 @@ npx @ruvector/rvf-mcp-server --transport stdio # MCP server for AI agents
238238
| DNA-style lineage | Parent/child derivation chains with cryptographic verification |
239239
| 24 segment types | VEC, INDEX, KERNEL, EBPF, WASM, COW_MAP, WITNESS, CRYPTO, and 16 more |
240240

241-
**Rust crates** (13): [`rvf-types`](https://crates.io/crates/rvf-types) `rvf-wire` `rvf-manifest` `rvf-quant` `rvf-index` `rvf-crypto` [`rvf-runtime`](https://crates.io/crates/rvf-runtime) `rvf-kernel` `rvf-ebpf` `rvf-launch` `rvf-server` `rvf-import` [`rvf-cli`](https://crates.io/crates/rvf-cli)
241+
**Rust crates** (22): [`rvf-types`](https://crates.io/crates/rvf-types) `rvf-wire` `rvf-manifest` `rvf-quant` `rvf-index` `rvf-crypto` [`rvf-runtime`](https://crates.io/crates/rvf-runtime) `rvf-kernel` `rvf-ebpf` `rvf-launch` `rvf-server` `rvf-import` [`rvf-cli`](https://crates.io/crates/rvf-cli) `rvf-wasm` `rvf-solver-wasm` `rvf-node` + 6 adapters (claude-flow, agentdb, ospipe, agentic-flow, rvlite, sona)
242242

243243
**npm packages** (4): [`@ruvector/rvf`](https://www.npmjs.com/package/@ruvector/rvf) [`@ruvector/rvf-node`](https://www.npmjs.com/package/@ruvector/rvf-node) [`@ruvector/rvf-wasm`](https://www.npmjs.com/package/@ruvector/rvf-wasm) [`@ruvector/rvf-mcp-server`](https://www.npmjs.com/package/@ruvector/rvf-mcp-server)
244244

@@ -247,7 +247,7 @@ npx @ruvector/rvf-mcp-server --transport stdio # MCP server for AI agents
247247
- **ADR-030**: [Cognitive Container Architecture](./docs/adr/ADR-030-rvf-cognitive-container.md)
248248
- **ADR-031**: [COW Branching & Real Containers](./docs/adr/ADR-031-rvcow-branching-and-real-cognitive-containers.md)
249249
- **ADR-042**: [Security RVF — AIDefence + TEE](./docs/adr/ADR-042-Security-RVF-AIDefence-TEE.md)
250-
- **46 runnable examples**: [examples/rvf/examples/](./examples/rvf/examples/)
250+
- **56 runnable examples**: [examples/rvf/examples/](./examples/rvf/examples/)
251251

252252
</details>
253253

@@ -355,7 +355,7 @@ npx ruvector
355355
| **Self-Learning (GNN)** ||||||
356356
| **Runtime Adaptation (SONA)** | ✅ LoRA+EWC++ |||||
357357
| **AI Agent Routing** | ✅ Tiny Dancer |||||
358-
| **Attention Mechanisms** |40 types |||||
358+
| **Attention Mechanisms** |46 types |||||
359359
| **Coherence Gate** | ✅ Prime-Radiant |||||
360360
| **Hyperbolic Embeddings** | ✅ Poincaré+Lorentz |||||
361361
| **Local Embeddings** | ✅ 8+ models |||||
@@ -518,7 +518,7 @@ npx @ruvector/cli hooks install # Configure for Claude Code
518518

519519
| Feature | What It Does | Why It Matters |
520520
|---------|--------------|----------------|
521-
| **40 Mechanisms** | Dot-product, multi-head, flash, linear, sparse, cross-attention, CGT sheaf | Cover all transformer and GNN use cases |
521+
| **46 Mechanisms** | Dot-product, multi-head, flash, linear, sparse, cross-attention, CGT sheaf | Cover all transformer and GNN use cases |
522522
| **Graph Attention** | RoPE, edge-featured, local-global, neighborhood | Purpose-built for graph neural networks |
523523
| **Hyperbolic Attention** | Poincaré ball operations, curved-space math | Better embeddings for hierarchical data |
524524
| **SIMD Optimized** | Native Rust with AVX2/NEON acceleration | 2-10x faster than pure JS |
@@ -1187,7 +1187,7 @@ await dag.execute();
11871187
|---------|-------------|---------|-----------|
11881188
| [@ruvector/tiny-dancer](https://www.npmjs.com/package/@ruvector/tiny-dancer) | FastGRNN neural routing | [![npm](https://img.shields.io/npm/v/@ruvector/tiny-dancer.svg)](https://www.npmjs.com/package/@ruvector/tiny-dancer) | [![downloads](https://img.shields.io/npm/dt/@ruvector/tiny-dancer.svg)](https://www.npmjs.com/package/@ruvector/tiny-dancer) |
11891189
| [@ruvector/router](https://www.npmjs.com/package/@ruvector/router) | Semantic router + HNSW | [![npm](https://img.shields.io/npm/v/@ruvector/router.svg)](https://www.npmjs.com/package/@ruvector/router) | [![downloads](https://img.shields.io/npm/dt/@ruvector/router.svg)](https://www.npmjs.com/package/@ruvector/router) |
1190-
| [@ruvector/attention](https://www.npmjs.com/package/@ruvector/attention) | 40+ attention mechanisms | [![npm](https://img.shields.io/npm/v/@ruvector/attention.svg)](https://www.npmjs.com/package/@ruvector/attention) | [![downloads](https://img.shields.io/npm/dt/@ruvector/attention.svg)](https://www.npmjs.com/package/@ruvector/attention) |
1190+
| [@ruvector/attention](https://www.npmjs.com/package/@ruvector/attention) | 46 attention mechanisms | [![npm](https://img.shields.io/npm/v/@ruvector/attention.svg)](https://www.npmjs.com/package/@ruvector/attention) | [![downloads](https://img.shields.io/npm/dt/@ruvector/attention.svg)](https://www.npmjs.com/package/@ruvector/attention) |
11911191

11921192
#### Learning & Neural
11931193

@@ -1260,7 +1260,7 @@ await dag.execute();
12601260
| [@ruvector/wasm-unified](https://www.npmjs.com/package/@ruvector/wasm-unified) | Unified TypeScript API | [![npm](https://img.shields.io/npm/v/@ruvector/wasm-unified.svg)](https://www.npmjs.com/package/@ruvector/wasm-unified) | [![downloads](https://img.shields.io/npm/dt/@ruvector/wasm-unified.svg)](https://www.npmjs.com/package/@ruvector/wasm-unified) |
12611261
| [@ruvector/gnn-wasm](https://www.npmjs.com/package/@ruvector/gnn-wasm) | GNN WASM bindings | [![npm](https://img.shields.io/npm/v/@ruvector/gnn-wasm.svg)](https://www.npmjs.com/package/@ruvector/gnn-wasm) | [![downloads](https://img.shields.io/npm/dt/@ruvector/gnn-wasm.svg)](https://www.npmjs.com/package/@ruvector/gnn-wasm) |
12621262
| [@ruvector/attention-wasm](https://www.npmjs.com/package/@ruvector/attention-wasm) | Attention WASM bindings | [![npm](https://img.shields.io/npm/v/@ruvector/attention-wasm.svg)](https://www.npmjs.com/package/@ruvector/attention-wasm) | [![downloads](https://img.shields.io/npm/dt/@ruvector/attention-wasm.svg)](https://www.npmjs.com/package/@ruvector/attention-wasm) |
1263-
| [@ruvector/attention-unified-wasm](https://www.npmjs.com/package/@ruvector/attention-unified-wasm) | All 40+ attention mechanisms | [![npm](https://img.shields.io/npm/v/@ruvector/attention-unified-wasm.svg)](https://www.npmjs.com/package/@ruvector/attention-unified-wasm) | [![downloads](https://img.shields.io/npm/dt/@ruvector/attention-unified-wasm.svg)](https://www.npmjs.com/package/@ruvector/attention-unified-wasm) |
1263+
| [@ruvector/attention-unified-wasm](https://www.npmjs.com/package/@ruvector/attention-unified-wasm) | All 46 attention mechanisms | [![npm](https://img.shields.io/npm/v/@ruvector/attention-unified-wasm.svg)](https://www.npmjs.com/package/@ruvector/attention-unified-wasm) | [![downloads](https://img.shields.io/npm/dt/@ruvector/attention-unified-wasm.svg)](https://www.npmjs.com/package/@ruvector/attention-unified-wasm) |
12641264
| [@ruvector/tiny-dancer-wasm](https://www.npmjs.com/package/@ruvector/tiny-dancer-wasm) | AI routing WASM | [![npm](https://img.shields.io/npm/v/@ruvector/tiny-dancer-wasm.svg)](https://www.npmjs.com/package/@ruvector/tiny-dancer-wasm) | [![downloads](https://img.shields.io/npm/dt/@ruvector/tiny-dancer-wasm.svg)](https://www.npmjs.com/package/@ruvector/tiny-dancer-wasm) |
12651265
| [@ruvector/router-wasm](https://www.npmjs.com/package/@ruvector/router-wasm) | Semantic router WASM | [![npm](https://img.shields.io/npm/v/@ruvector/router-wasm.svg)](https://www.npmjs.com/package/@ruvector/router-wasm) | [![downloads](https://img.shields.io/npm/dt/@ruvector/router-wasm.svg)](https://www.npmjs.com/package/@ruvector/router-wasm) |
12661266
| [@ruvector/learning-wasm](https://www.npmjs.com/package/@ruvector/learning-wasm) | Learning module WASM | [![npm](https://img.shields.io/npm/v/@ruvector/learning-wasm.svg)](https://www.npmjs.com/package/@ruvector/learning-wasm) | [![downloads](https://img.shields.io/npm/dt/@ruvector/learning-wasm.svg)](https://www.npmjs.com/package/@ruvector/learning-wasm) |
@@ -1305,7 +1305,7 @@ All crates are published to [crates.io](https://crates.io) under the `ruvector-*
13051305

13061306
| Crate | Description | crates.io |
13071307
|-------|-------------|-----------|
1308-
| [ruvector-attention](./crates/ruvector-attention) | 40+ attention mechanisms (Flash, Hyperbolic, MoE, Graph) | [![crates.io](https://img.shields.io/crates/v/ruvector-attention.svg)](https://crates.io/crates/ruvector-attention) |
1308+
| [ruvector-attention](./crates/ruvector-attention) | 46 attention mechanisms (Flash, Hyperbolic, MoE, Graph) | [![crates.io](https://img.shields.io/crates/v/ruvector-attention.svg)](https://crates.io/crates/ruvector-attention) |
13091309
| [ruvector-attention-node](./crates/ruvector-attention-node) | Node.js bindings for attention mechanisms | [![crates.io](https://img.shields.io/crates/v/ruvector-attention-node.svg)](https://crates.io/crates/ruvector-attention-node) |
13101310
| [ruvector-attention-wasm](./crates/ruvector-attention-wasm) | WASM bindings for browser attention | [![crates.io](https://img.shields.io/crates/v/ruvector-attention-wasm.svg)](https://crates.io/crates/ruvector-attention-wasm) |
13111311
| [ruvector-attention-cli](./crates/ruvector-attention-cli) | CLI for attention testing and benchmarking | [![crates.io](https://img.shields.io/crates/v/ruvector-attention-cli.svg)](https://crates.io/crates/ruvector-attention-cli) |

crates/ruvector-attention-unified-wasm/src/graph.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,10 @@ impl WasmGNNLayer {
4343
heads: usize,
4444
dropout: f32,
4545
) -> Result<WasmGNNLayer, JsError> {
46-
if dropout < 0.0 || dropout > 1.0 {
47-
return Err(JsError::new("Dropout must be between 0.0 and 1.0"));
48-
}
46+
let inner = RuvectorLayer::new(input_dim, hidden_dim, heads, dropout)
47+
.map_err(|e| JsError::new(&e.to_string()))?;
4948

50-
Ok(WasmGNNLayer {
51-
inner: RuvectorLayer::new(input_dim, hidden_dim, heads, dropout),
52-
hidden_dim,
53-
})
49+
Ok(WasmGNNLayer { inner, hidden_dim })
5450
}
5551

5652
/// Forward pass through the GNN layer
@@ -378,6 +374,12 @@ mod tests {
378374
assert!(layer.is_err());
379375
}
380376

377+
#[wasm_bindgen_test]
378+
fn test_gnn_layer_invalid_heads() {
379+
let layer = WasmGNNLayer::new(4, 7, 3, 0.1);
380+
assert!(layer.is_err());
381+
}
382+
381383
#[wasm_bindgen_test]
382384
fn test_tensor_compress_creation() {
383385
let compressor = WasmTensorCompress::new();

crates/ruvector-cli/src/mcp/gnn_cache.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,8 @@ impl GnnCache {
189189
}
190190

191191
// Create new layer
192-
let layer = RuvectorLayer::new(input_dim, hidden_dim, heads, dropout);
192+
let layer = RuvectorLayer::new(input_dim, hidden_dim, heads, dropout)
193+
.expect("GNN layer cache: invalid layer configuration");
193194

194195
// Cache it
195196
{

crates/ruvector-cli/tests/gnn_performance_test.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ mod gnn_cache_tests {
2525
#[test]
2626
fn test_layer_creation_latency() {
2727
let start = Instant::now();
28-
let _layer = RuvectorLayer::new(128, 256, 4, 0.1);
28+
let _layer = RuvectorLayer::new(128, 256, 4, 0.1).unwrap();
2929
let elapsed = start.elapsed();
3030

3131
// Layer creation: 100ms in release, ~2000ms in debug
@@ -48,7 +48,7 @@ mod gnn_cache_tests {
4848
/// Test that forward pass has acceptable latency
4949
#[test]
5050
fn test_forward_pass_latency() {
51-
let layer = RuvectorLayer::new(128, 256, 4, 0.1);
51+
let layer = RuvectorLayer::new(128, 256, 4, 0.1).unwrap();
5252
let node = vec![0.5f32; 128];
5353
let neighbors = vec![vec![0.3f32; 128], vec![0.7f32; 128]];
5454
let weights = vec![0.5f32, 0.5f32];
@@ -83,7 +83,7 @@ mod gnn_cache_tests {
8383
/// Test batch operations performance
8484
#[test]
8585
fn test_batch_operations_performance() {
86-
let layer = RuvectorLayer::new(64, 128, 2, 0.1);
86+
let layer = RuvectorLayer::new(64, 128, 2, 0.1).unwrap();
8787

8888
// Create batch of operations
8989
let batch_size = 100;
@@ -139,7 +139,7 @@ mod gnn_cache_tests {
139139
for (input, hidden, heads) in sizes {
140140
// Measure creation
141141
let start = Instant::now();
142-
let layer = RuvectorLayer::new(input, hidden, heads, 0.1);
142+
let layer = RuvectorLayer::new(input, hidden, heads, 0.1).unwrap();
143143
let create_ms = start.elapsed().as_secs_f64() * 1000.0;
144144

145145
// Measure forward
@@ -216,7 +216,7 @@ mod gnn_cache_integration {
216216

217217
// First: measure time including layer creation
218218
let start_cold = Instant::now();
219-
let layer = RuvectorLayer::new(128, 256, 4, 0.1);
219+
let layer = RuvectorLayer::new(128, 256, 4, 0.1).unwrap();
220220
let node = vec![0.5f32; 128];
221221
let neighbors = vec![vec![0.3f32; 128], vec![0.7f32; 128]];
222222
let weights = vec![0.5f32, 0.5f32];
@@ -262,7 +262,7 @@ mod gnn_cache_integration {
262262

263263
// Create layer once
264264
let start = Instant::now();
265-
let layer = RuvectorLayer::new(64, 128, 2, 0.1);
265+
let layer = RuvectorLayer::new(64, 128, 2, 0.1).unwrap();
266266
let creation_time = start.elapsed();
267267

268268
let node = vec![0.5f32; 64];

crates/ruvector-crv/src/stage_iii.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ impl StageIIIEncoder {
3131
pub fn new(config: &CrvConfig) -> Self {
3232
let dim = config.dimensions;
3333
// Single GNN layer: input_dim -> hidden_dim, 1 head
34-
let gnn_layer = RuvectorLayer::new(dim, dim, 1, 0.0);
34+
// heads=1 always divides any dim, and dropout=0.0 is always valid
35+
let gnn_layer = RuvectorLayer::new(dim, dim, 1, 0.0)
36+
.expect("dim is always divisible by 1 head");
3537

3638
Self { dim, gnn_layer }
3739
}

crates/ruvector-gnn-node/npm/darwin-arm64/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@ruvector/gnn-darwin-arm64",
3-
"version": "0.1.24",
3+
"version": "0.1.25",
44
"os": [
55
"darwin"
66
],

crates/ruvector-gnn-node/npm/darwin-x64/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@ruvector/gnn-darwin-x64",
3-
"version": "0.1.24",
3+
"version": "0.1.25",
44
"os": [
55
"darwin"
66
],

crates/ruvector-gnn-node/npm/linux-arm64-gnu/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@ruvector/gnn-linux-arm64-gnu",
3-
"version": "0.1.24",
3+
"version": "0.1.25",
44
"os": [
55
"linux"
66
],

0 commit comments

Comments
 (0)