Merge commit 'd803bfe2b1fe7f5e219e50ac20d6801a0a58ac75' as 'vendor/ruvector'

This commit is contained in:
ruv
2026-02-28 14:39:40 -05:00
7854 changed files with 3522914 additions and 0 deletions

View File

@@ -0,0 +1,33 @@
[package.metadata.wasm-pack.profile.release]
wasm-opt = false
[package]
name = "ruvector-graph-transformer-wasm"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
authors.workspace = true
repository.workspace = true
description = "WASM bindings for ruvector-graph-transformer: proof-gated graph attention in the browser"
readme = "README.md"
keywords = ["wasm", "graph-transformer", "attention", "verified", "webassembly"]
categories = ["wasm", "science", "mathematics"]
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
wasm-bindgen = "0.2"
serde-wasm-bindgen = "0.6"
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
js-sys = "0.3"
[dev-dependencies]
wasm-bindgen-test = "0.3"
[profile.release]
opt-level = "s"
lto = true
codegen-units = 1

View File

@@ -0,0 +1,181 @@
# ruvector-graph-transformer-wasm
[![Crates.io](https://img.shields.io/crates/v/ruvector-graph-transformer-wasm.svg)](https://crates.io/crates/ruvector-graph-transformer-wasm)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
**WebAssembly bindings for RuVector Graph Transformer — proof-gated graph attention, verified training, and 8 specialized graph layers running client-side in the browser.**
Run the full graph transformer in any browser tab — no server, no API calls, no data leaving the device. Every graph mutation is formally verified client-side, so your users get the same mathematical safety guarantees as the Rust version. The WASM binary is size-optimized and loads in milliseconds.
## Install
```bash
# With wasm-pack (recommended)
wasm-pack build crates/ruvector-graph-transformer-wasm --target web
# Or from npm (when published)
npm install ruvector-graph-transformer-wasm
```
## Quick Start
```javascript
import init, { JsGraphTransformer } from "ruvector-graph-transformer-wasm";
await init();
const gt = new JsGraphTransformer();
console.log(gt.version()); // "2.0.4"
// Proof-gated mutation
const gate = gt.create_proof_gate(128);
const proof = gt.prove_dimension(128, 128);
console.log(proof.verified); // true
// 82-byte attestation for RVF witness chains
const attestation = gt.create_attestation(proof.proof_id);
console.log(attestation.length); // 82
// Sublinear attention — O(n log n)
const result = gt.sublinear_attention(
new Float32Array([0.1, 0.2, 0.3, 0.4]),
[{ src: 0, tgt: 1 }, { src: 0, tgt: 2 }],
4, 2
);
// Verified training step with certificate
const step = gt.verified_training_step(
[1.0, 2.0], [0.1, 0.2], 0.01
);
console.log(step.weights, step.certificate);
// Physics: symplectic integration
const state = gt.hamiltonian_step([1.0, 0.0], [0.0, 1.0], 0.01);
console.log(state.energy);
// Biological: spiking attention
const spikes = gt.spiking_attention(
[0.5, 1.5, 0.3], [[1], [0, 2], [1]], 1.0
);
// Manifold: mixed-curvature distance
const d = gt.product_manifold_distance(
[1, 0, 0, 1], [0, 1, 1, 0], [0.0, -1.0]
);
// Temporal: causal masking
const scores = gt.causal_attention(
[1.0, 0.0],
[[1.0, 0.0], [0.0, 1.0]],
[1.0, 2.0]
);
// Economic: Nash equilibrium
const nash = gt.game_theoretic_attention(
[1.0, 0.5, 0.8],
[{ src: 0, tgt: 1 }, { src: 1, tgt: 2 }]
);
console.log(nash.converged);
// Stats
console.log(gt.stats());
```
## API
### Proof-Gated Operations
| Method | Returns | Description |
|--------|---------|-------------|
| `new JsGraphTransformer(config?)` | `JsGraphTransformer` | Create transformer instance |
| `version()` | `string` | Crate version |
| `create_proof_gate(dim)` | `object` | Create proof gate for dimension |
| `prove_dimension(expected, actual)` | `object` | Prove dimension equality |
| `create_attestation(proof_id)` | `Uint8Array` | 82-byte proof attestation |
| `verify_attestation(bytes)` | `boolean` | Verify attestation from bytes |
| `compose_proofs(stages)` | `object` | Type-checked pipeline composition |
### Sublinear Attention
| Method | Returns | Description |
|--------|---------|-------------|
| `sublinear_attention(q, edges, dim, k)` | `object` | Graph-sparse top-k attention |
| `ppr_scores(source, adj, alpha)` | `Float64Array` | Personalized PageRank scores |
### Physics-Informed
| Method | Returns | Description |
|--------|---------|-------------|
| `hamiltonian_step(positions, momenta, dt)` | `object` | Symplectic leapfrog step |
| `verify_energy_conservation(before, after, tol)` | `object` | Energy conservation proof |
### Biological
| Method | Returns | Description |
|--------|---------|-------------|
| `spiking_attention(spikes, edges, threshold)` | `Float64Array` | Event-driven spiking attention |
| `hebbian_update(pre, post, weights, lr)` | `Float64Array` | Hebbian weight update |
| `spiking_step(features, adjacency)` | `object` | Full spiking step over feature matrix |
### Verified Training
| Method | Returns | Description |
|--------|---------|-------------|
| `verified_step(weights, gradients, lr)` | `object` | SGD step + proof receipt |
| `verified_training_step(features, targets, weights)` | `object` | Training step + certificate |
### Manifold
| Method | Returns | Description |
|--------|---------|-------------|
| `product_manifold_distance(a, b, curvatures)` | `number` | Mixed-curvature distance |
| `product_manifold_attention(features, edges)` | `object` | Product manifold attention |
### Temporal-Causal
| Method | Returns | Description |
|--------|---------|-------------|
| `causal_attention(query, keys, timestamps)` | `Float64Array` | Temporally masked attention |
| `causal_attention_graph(features, timestamps, edges)` | `Float64Array` | Causal graph attention |
| `granger_extract(history, num_nodes, num_steps)` | `object` | Granger causality DAG |
### Economic
| Method | Returns | Description |
|--------|---------|-------------|
| `game_theoretic_attention(features, edges)` | `object` | Nash equilibrium attention |
### Meta
| Method | Returns | Description |
|--------|---------|-------------|
| `stats()` | `object` | Aggregate proof/attestation statistics |
| `reset()` | `void` | Reset all internal state |
## Building
```bash
# Web target (recommended for browsers)
wasm-pack build crates/ruvector-graph-transformer-wasm --target web
# Node.js target
wasm-pack build crates/ruvector-graph-transformer-wasm --target nodejs
# Cargo check
cargo check -p ruvector-graph-transformer-wasm
```
## Bundle Size
The WASM binary is optimized for size with `opt-level = "s"`, LTO, and single codegen unit.
## Related Packages
| Package | Description |
|---------|-------------|
| [`ruvector-graph-transformer`](../ruvector-graph-transformer) | Core Rust crate (186 tests) |
| [`@ruvector/graph-transformer`](../ruvector-graph-transformer-node) | Node.js NAPI-RS bindings |
| [`ruvector-verified-wasm`](../ruvector-verified-wasm) | Formal verification WASM bindings |
## License
MIT

View File

@@ -0,0 +1,181 @@
# ruvector-graph-transformer-wasm
[![Crates.io](https://img.shields.io/crates/v/ruvector-graph-transformer-wasm.svg)](https://crates.io/crates/ruvector-graph-transformer-wasm)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
**WebAssembly bindings for RuVector Graph Transformer — proof-gated graph attention, verified training, and 8 specialized graph layers running client-side in the browser.**
Run the full graph transformer in any browser tab — no server, no API calls, no data leaving the device. Every graph mutation is formally verified client-side, so your users get the same mathematical safety guarantees as the Rust version. The WASM binary is size-optimized and loads in milliseconds.
## Install
```bash
# With wasm-pack (recommended)
wasm-pack build crates/ruvector-graph-transformer-wasm --target web
# Or from npm (when published)
npm install ruvector-graph-transformer-wasm
```
## Quick Start
```javascript
import init, { JsGraphTransformer } from "ruvector-graph-transformer-wasm";
await init();
const gt = new JsGraphTransformer();
console.log(gt.version()); // "2.0.4"
// Proof-gated mutation
const gate = gt.create_proof_gate(128);
const proof = gt.prove_dimension(128, 128);
console.log(proof.verified); // true
// 82-byte attestation for RVF witness chains
const attestation = gt.create_attestation(proof.proof_id);
console.log(attestation.length); // 82
// Sublinear attention — O(n log n)
const result = gt.sublinear_attention(
new Float32Array([0.1, 0.2, 0.3, 0.4]),
[{ src: 0, tgt: 1 }, { src: 0, tgt: 2 }],
4, 2
);
// Verified training step with certificate
const step = gt.verified_training_step(
[1.0, 2.0], [0.1, 0.2], 0.01
);
console.log(step.weights, step.certificate);
// Physics: symplectic integration
const state = gt.hamiltonian_step([1.0, 0.0], [0.0, 1.0], 0.01);
console.log(state.energy);
// Biological: spiking attention
const spikes = gt.spiking_attention(
[0.5, 1.5, 0.3], [[1], [0, 2], [1]], 1.0
);
// Manifold: mixed-curvature distance
const d = gt.product_manifold_distance(
[1, 0, 0, 1], [0, 1, 1, 0], [0.0, -1.0]
);
// Temporal: causal masking
const scores = gt.causal_attention(
[1.0, 0.0],
[[1.0, 0.0], [0.0, 1.0]],
[1.0, 2.0]
);
// Economic: Nash equilibrium
const nash = gt.game_theoretic_attention(
[1.0, 0.5, 0.8],
[{ src: 0, tgt: 1 }, { src: 1, tgt: 2 }]
);
console.log(nash.converged);
// Stats
console.log(gt.stats());
```
## API
### Proof-Gated Operations
| Method | Returns | Description |
|--------|---------|-------------|
| `new JsGraphTransformer(config?)` | `JsGraphTransformer` | Create transformer instance |
| `version()` | `string` | Crate version |
| `create_proof_gate(dim)` | `object` | Create proof gate for dimension |
| `prove_dimension(expected, actual)` | `object` | Prove dimension equality |
| `create_attestation(proof_id)` | `Uint8Array` | 82-byte proof attestation |
| `verify_attestation(bytes)` | `boolean` | Verify attestation from bytes |
| `compose_proofs(stages)` | `object` | Type-checked pipeline composition |
### Sublinear Attention
| Method | Returns | Description |
|--------|---------|-------------|
| `sublinear_attention(q, edges, dim, k)` | `object` | Graph-sparse top-k attention |
| `ppr_scores(source, adj, alpha)` | `Float64Array` | Personalized PageRank scores |
### Physics-Informed
| Method | Returns | Description |
|--------|---------|-------------|
| `hamiltonian_step(positions, momenta, dt)` | `object` | Symplectic leapfrog step |
| `verify_energy_conservation(before, after, tol)` | `object` | Energy conservation proof |
### Biological
| Method | Returns | Description |
|--------|---------|-------------|
| `spiking_attention(spikes, edges, threshold)` | `Float64Array` | Event-driven spiking attention |
| `hebbian_update(pre, post, weights, lr)` | `Float64Array` | Hebbian weight update |
| `spiking_step(features, adjacency)` | `object` | Full spiking step over feature matrix |
### Verified Training
| Method | Returns | Description |
|--------|---------|-------------|
| `verified_step(weights, gradients, lr)` | `object` | SGD step + proof receipt |
| `verified_training_step(features, targets, weights)` | `object` | Training step + certificate |
### Manifold
| Method | Returns | Description |
|--------|---------|-------------|
| `product_manifold_distance(a, b, curvatures)` | `number` | Mixed-curvature distance |
| `product_manifold_attention(features, edges)` | `object` | Product manifold attention |
### Temporal-Causal
| Method | Returns | Description |
|--------|---------|-------------|
| `causal_attention(query, keys, timestamps)` | `Float64Array` | Temporally masked attention |
| `causal_attention_graph(features, timestamps, edges)` | `Float64Array` | Causal graph attention |
| `granger_extract(history, num_nodes, num_steps)` | `object` | Granger causality DAG |
### Economic
| Method | Returns | Description |
|--------|---------|-------------|
| `game_theoretic_attention(features, edges)` | `object` | Nash equilibrium attention |
### Meta
| Method | Returns | Description |
|--------|---------|-------------|
| `stats()` | `object` | Aggregate proof/attestation statistics |
| `reset()` | `void` | Reset all internal state |
## Building
```bash
# Web target (recommended for browsers)
wasm-pack build crates/ruvector-graph-transformer-wasm --target web
# Node.js target
wasm-pack build crates/ruvector-graph-transformer-wasm --target nodejs
# Cargo check
cargo check -p ruvector-graph-transformer-wasm
```
## Bundle Size
The WASM binary is optimized for size with `opt-level = "s"`, LTO, and single codegen unit.
## Related Packages
| Package | Description |
|---------|-------------|
| [`ruvector-graph-transformer`](../ruvector-graph-transformer) | Core Rust crate (186 tests) |
| [`@ruvector/graph-transformer`](../ruvector-graph-transformer-node) | Node.js NAPI-RS bindings |
| [`ruvector-verified-wasm`](../ruvector-verified-wasm) | Formal verification WASM bindings |
## License
MIT

View File

@@ -0,0 +1,31 @@
{
"name": "ruvector-graph-transformer-wasm",
"type": "module",
"collaborators": [
"Ruvector Team"
],
"description": "WASM bindings for ruvector-graph-transformer: proof-gated graph attention in the browser",
"version": "2.0.5",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/ruvnet/ruvector"
},
"files": [
"ruvector_graph_transformer_wasm_bg.wasm",
"ruvector_graph_transformer_wasm.js",
"ruvector_graph_transformer_wasm.d.ts"
],
"main": "ruvector_graph_transformer_wasm.js",
"types": "ruvector_graph_transformer_wasm.d.ts",
"sideEffects": [
"./snippets/*"
],
"keywords": [
"wasm",
"graph-transformer",
"attention",
"verified",
"webassembly"
]
}

View File

@@ -0,0 +1,225 @@
/* tslint:disable */
/* eslint-disable */
/**
* Graph transformer for the browser.
*
* Wraps the core `CoreGraphTransformer` and exposes proof-gated, sublinear,
* physics, biological, verified-training, manifold, temporal, and economic
* operations via wasm_bindgen.
*/
export class JsGraphTransformer {
free(): void;
[Symbol.dispose](): void;
/**
* Causal attention with temporal ordering over graph edges.
*
* `features` is a Float64Array, `timestamps` is a Float64Array,
* `edges` is `[{ src, tgt }, ...]`.
* Returns attention-weighted output features.
*/
causal_attention(features: any, timestamps: any, edges: any): any;
/**
* Compose a chain of pipeline stages, verifying type compatibility.
*
* `stages` is a JS array of `{ name, input_type_id, output_type_id }`.
* Returns a composed proof with the overall input/output types.
*/
compose_proofs(stages: any): any;
/**
* Create a proof attestation for a given proof ID.
*
* Returns the attestation as a byte buffer (82 bytes).
*/
create_attestation(proof_id: number): Uint8Array;
/**
* Create a proof gate for the given embedding dimension.
*
* Returns a serialized `ProofGate` object.
*/
create_proof_gate(dim: number): any;
/**
* Game-theoretic attention: computes Nash equilibrium allocations.
*
* `features` is a Float64Array, `edges` is `[{ src, tgt }, ...]`.
* Returns `{ allocations, utilities, nash_gap, converged }`.
*/
game_theoretic_attention(features: any, edges: any): any;
/**
* Extract Granger causality DAG from attention history.
*
* `attention_history` is a flat Float64Array (T x N row-major).
* Returns `{ edges: [{ source, target, f_statistic, is_causal }], num_nodes }`.
*/
granger_extract(attention_history: any, num_nodes: number, num_steps: number): any;
/**
* Symplectic integrator step (leapfrog / Stormer-Verlet).
*
* `positions` and `momenta` are Float64Arrays, `edges` is
* `[{ src, tgt }, ...]`. Returns `{ positions, momenta, energy,
* energy_conserved }`.
*/
hamiltonian_step(positions: any, momenta: any, edges: any): any;
/**
* Hebbian weight update.
*
* `pre`, `post`, `weights` are Float64Arrays. Returns updated weights.
*/
hebbian_update(pre: any, post: any, weights: any): any;
/**
* Create a new graph transformer.
*
* `config` is an optional JS object (reserved for future use).
*/
constructor(config: any);
/**
* Compute personalized PageRank scores from a source node.
*
* Returns array of PPR scores, one per node.
*/
ppr_scores(source: number, adjacency: any, alpha: number): any;
/**
* Product manifold attention with mixed curvatures.
*
* `features` is a Float64Array, `edges` is `[{ src, tgt }, ...]`.
* Optional `curvatures` (defaults to `[0.0, -1.0]`).
* Returns `{ output, curvatures, distances }`.
*/
product_manifold_attention(features: any, edges: any): any;
/**
* Product manifold distance between two points.
*
* `a` and `b` are Float64Arrays, `curvatures` is `[number, ...]`.
*/
product_manifold_distance(a: any, b: any, curvatures: any): number;
/**
* Prove that two dimensions are equal.
*
* Returns `{ proof_id, expected, actual, verified }`.
*/
prove_dimension(expected: number, actual: number): any;
/**
* Reset all internal state (caches, counters, gates).
*/
reset(): void;
/**
* Spiking neural attention step over 2D features with adjacency.
*
* `features` is `[[f64, ...], ...]`, `adjacency` is a flat row-major
* Float64Array (n x n). Returns `{ features, spikes, weights }`.
*/
spiking_step(features: any, adjacency: any): any;
/**
* Return transformer statistics.
*
* Returns `{ proofs_constructed, proofs_verified, cache_hits,
* cache_misses, attention_ops, physics_ops, bio_ops, training_steps }`.
*/
stats(): any;
/**
* Sublinear graph attention using personalized PageRank sparsification.
*
* `query` is a Float64Array, `edges` is `[[u32, ...], ...]`.
* Returns `{ scores, top_k_indices, sparsity_ratio }`.
*/
sublinear_attention(query: any, edges: any, dim: number, k: number): any;
/**
* A single verified SGD step (raw weights + gradients).
*
* Returns `{ weights, proof_id, loss_before, loss_after, gradient_norm }`.
*/
verified_step(weights: any, gradients: any, lr: number): any;
/**
* Verified training step with features, targets, and weights.
*
* `features`, `targets`, `weights` are Float64Arrays.
* Returns `{ weights, certificate_id, loss, loss_monotonic,
* lipschitz_satisfied }`.
*/
verified_training_step(features: any, targets: any, weights: any): any;
/**
* Verify an attestation from its byte representation.
*
* Returns `true` if the attestation is structurally valid.
*/
verify_attestation(bytes: Uint8Array): boolean;
/**
* Verify energy conservation between two states.
*
* Returns `{ conserved, delta, relative_error }`.
*/
verify_energy_conservation(before: number, after: number, tolerance: number): any;
/**
* Get the library version string.
*/
version(): string;
}
/**
* Called automatically when the WASM module is loaded.
*/
export function init(): void;
/**
* Return the crate version.
*/
export function version(): string;
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
export interface InitOutput {
readonly memory: WebAssembly.Memory;
readonly __wbg_jsgraphtransformer_free: (a: number, b: number) => void;
readonly init: () => void;
readonly jsgraphtransformer_causal_attention: (a: number, b: number, c: number, d: number, e: number) => void;
readonly jsgraphtransformer_compose_proofs: (a: number, b: number, c: number) => void;
readonly jsgraphtransformer_create_attestation: (a: number, b: number, c: number) => void;
readonly jsgraphtransformer_create_proof_gate: (a: number, b: number, c: number) => void;
readonly jsgraphtransformer_game_theoretic_attention: (a: number, b: number, c: number, d: number) => void;
readonly jsgraphtransformer_granger_extract: (a: number, b: number, c: number, d: number, e: number) => void;
readonly jsgraphtransformer_hamiltonian_step: (a: number, b: number, c: number, d: number, e: number) => void;
readonly jsgraphtransformer_hebbian_update: (a: number, b: number, c: number, d: number, e: number) => void;
readonly jsgraphtransformer_new: (a: number, b: number) => void;
readonly jsgraphtransformer_ppr_scores: (a: number, b: number, c: number, d: number, e: number) => void;
readonly jsgraphtransformer_product_manifold_attention: (a: number, b: number, c: number, d: number) => void;
readonly jsgraphtransformer_product_manifold_distance: (a: number, b: number, c: number, d: number, e: number) => void;
readonly jsgraphtransformer_prove_dimension: (a: number, b: number, c: number, d: number) => void;
readonly jsgraphtransformer_reset: (a: number) => void;
readonly jsgraphtransformer_spiking_step: (a: number, b: number, c: number, d: number) => void;
readonly jsgraphtransformer_stats: (a: number, b: number) => void;
readonly jsgraphtransformer_sublinear_attention: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
readonly jsgraphtransformer_verified_step: (a: number, b: number, c: number, d: number, e: number) => void;
readonly jsgraphtransformer_verified_training_step: (a: number, b: number, c: number, d: number, e: number) => void;
readonly jsgraphtransformer_verify_attestation: (a: number, b: number, c: number) => number;
readonly jsgraphtransformer_verify_energy_conservation: (a: number, b: number, c: number, d: number, e: number) => void;
readonly jsgraphtransformer_version: (a: number, b: number) => void;
readonly version: (a: number) => void;
readonly __wbindgen_export: (a: number, b: number) => number;
readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
readonly __wbindgen_export3: (a: number) => void;
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
readonly __wbindgen_export4: (a: number, b: number, c: number) => void;
readonly __wbindgen_start: () => void;
}
export type SyncInitInput = BufferSource | WebAssembly.Module;
/**
* Instantiates the given `module`, which can either be bytes or
* a precompiled `WebAssembly.Module`.
*
* @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
*
* @returns {InitOutput}
*/
export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
/**
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
* for everything else, calls `WebAssembly.instantiate` directly.
*
* @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
*
* @returns {Promise<InitOutput>}
*/
export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
/* tslint:disable */
/* eslint-disable */
export const memory: WebAssembly.Memory;
export const __wbg_jsgraphtransformer_free: (a: number, b: number) => void;
export const init: () => void;
export const jsgraphtransformer_causal_attention: (a: number, b: number, c: number, d: number, e: number) => void;
export const jsgraphtransformer_compose_proofs: (a: number, b: number, c: number) => void;
export const jsgraphtransformer_create_attestation: (a: number, b: number, c: number) => void;
export const jsgraphtransformer_create_proof_gate: (a: number, b: number, c: number) => void;
export const jsgraphtransformer_game_theoretic_attention: (a: number, b: number, c: number, d: number) => void;
export const jsgraphtransformer_granger_extract: (a: number, b: number, c: number, d: number, e: number) => void;
export const jsgraphtransformer_hamiltonian_step: (a: number, b: number, c: number, d: number, e: number) => void;
export const jsgraphtransformer_hebbian_update: (a: number, b: number, c: number, d: number, e: number) => void;
export const jsgraphtransformer_new: (a: number, b: number) => void;
export const jsgraphtransformer_ppr_scores: (a: number, b: number, c: number, d: number, e: number) => void;
export const jsgraphtransformer_product_manifold_attention: (a: number, b: number, c: number, d: number) => void;
export const jsgraphtransformer_product_manifold_distance: (a: number, b: number, c: number, d: number, e: number) => void;
export const jsgraphtransformer_prove_dimension: (a: number, b: number, c: number, d: number) => void;
export const jsgraphtransformer_reset: (a: number) => void;
export const jsgraphtransformer_spiking_step: (a: number, b: number, c: number, d: number) => void;
export const jsgraphtransformer_stats: (a: number, b: number) => void;
export const jsgraphtransformer_sublinear_attention: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
export const jsgraphtransformer_verified_step: (a: number, b: number, c: number, d: number, e: number) => void;
export const jsgraphtransformer_verified_training_step: (a: number, b: number, c: number, d: number, e: number) => void;
export const jsgraphtransformer_verify_attestation: (a: number, b: number, c: number) => number;
export const jsgraphtransformer_verify_energy_conservation: (a: number, b: number, c: number, d: number, e: number) => void;
export const jsgraphtransformer_version: (a: number, b: number) => void;
export const version: (a: number) => void;
export const __wbindgen_export: (a: number, b: number) => number;
export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
export const __wbindgen_export3: (a: number) => void;
export const __wbindgen_add_to_stack_pointer: (a: number) => number;
export const __wbindgen_export4: (a: number, b: number, c: number) => void;
export const __wbindgen_start: () => void;

View File

@@ -0,0 +1,460 @@
//! WASM bindings for `ruvector-graph-transformer`: proof-gated graph attention
//! in the browser.
//!
//! # Quick Start (JavaScript)
//!
//! ```js
//! import init, { JsGraphTransformer } from "ruvector-graph-transformer-wasm";
//!
//! await init();
//! const gt = new JsGraphTransformer();
//!
//! // Create a proof gate and prove dimensions
//! const gate = gt.createProofGate(128);
//! const proof = gt.proveDimension(128, 128);
//!
//! // Sublinear attention
//! const result = gt.sublinearAttention(
//! new Float64Array([0.1, 0.2]),
//! [[1, 2], [0, 2], [0, 1]],
//! 2, 2,
//! );
//!
//! // Physics: Hamiltonian step with graph edges
//! const state = gt.hamiltonianStep([1.0, 0.0], [0.0, 1.0], [{ src: 0, tgt: 1 }]);
//!
//! // Biological: spiking step
//! const spikes = gt.spikingStep([[0.8, 0.6], [0.1, 0.2]], [0, 0.5, 0.3, 0]);
//!
//! // Temporal: causal attention
//! const attn = gt.causalAttention([1.0, 0.0], [1.0, 2.0, 3.0], [{ src: 0, tgt: 1 }]);
//!
//! // Manifold: product manifold attention
//! const manifold = gt.productManifoldAttention([1.0, 0.5], [{ src: 0, tgt: 1 }]);
//!
//! // Verified training
//! const training = gt.verifiedTrainingStep([1.0, 2.0], [0.5, 1.0], [0.5, 0.5]);
//!
//! // Economic: game-theoretic attention
//! const eqm = gt.gameTheoreticAttention([1.0, 0.5, 0.8], [{ src: 0, tgt: 1 }]);
//!
//! // Stats
//! console.log(gt.stats());
//! ```
mod transformer;
mod utils;
use transformer::{CoreGraphTransformer, Edge, PipelineStage as CorePipelineStage};
use wasm_bindgen::prelude::*;
// ---------------------------------------------------------------------------
// Module init
// ---------------------------------------------------------------------------
/// Called automatically when the WASM module is loaded.
#[wasm_bindgen(start)]
pub fn init() {
utils::set_panic_hook();
}
/// Return the crate version.
#[wasm_bindgen]
pub fn version() -> String {
env!("CARGO_PKG_VERSION").to_string()
}
// ---------------------------------------------------------------------------
// JsGraphTransformer -- main entry point
// ---------------------------------------------------------------------------
/// Graph transformer for the browser.
///
/// Wraps the core `CoreGraphTransformer` and exposes proof-gated, sublinear,
/// physics, biological, verified-training, manifold, temporal, and economic
/// operations via wasm_bindgen.
#[wasm_bindgen]
pub struct JsGraphTransformer {
inner: CoreGraphTransformer,
}
#[wasm_bindgen]
impl JsGraphTransformer {
/// Create a new graph transformer.
///
/// `config` is an optional JS object (reserved for future use).
#[wasm_bindgen(constructor)]
pub fn new(config: JsValue) -> Result<JsGraphTransformer, JsError> {
let _ = config; // reserved for future configuration
Ok(Self {
inner: CoreGraphTransformer::new(),
})
}
/// Get the library version string.
#[wasm_bindgen]
pub fn version(&self) -> String {
self.inner.version()
}
// ===================================================================
// Proof-Gated Operations
// ===================================================================
/// Create a proof gate for the given embedding dimension.
///
/// Returns a serialized `ProofGate` object.
pub fn create_proof_gate(&mut self, dim: u32) -> Result<JsValue, JsError> {
let gate = self.inner.create_proof_gate(dim);
serde_wasm_bindgen::to_value(&gate).map_err(|e| JsError::new(&e.to_string()))
}
/// Prove that two dimensions are equal.
///
/// Returns `{ proof_id, expected, actual, verified }`.
pub fn prove_dimension(&mut self, expected: u32, actual: u32) -> Result<JsValue, JsError> {
let result = self
.inner
.prove_dimension(expected, actual)
.map_err(|e| JsError::new(&format!("{e}")))?;
serde_wasm_bindgen::to_value(&result).map_err(|e| JsError::new(&e.to_string()))
}
/// Create a proof attestation for a given proof ID.
///
/// Returns the attestation as a byte buffer (82 bytes).
pub fn create_attestation(&self, proof_id: u32) -> Result<Vec<u8>, JsError> {
let att = self.inner.create_attestation(proof_id);
Ok(att.to_bytes())
}
/// Verify an attestation from its byte representation.
///
/// Returns `true` if the attestation is structurally valid.
pub fn verify_attestation(&self, bytes: &[u8]) -> bool {
self.inner.verify_attestation(bytes)
}
/// Compose a chain of pipeline stages, verifying type compatibility.
///
/// `stages` is a JS array of `{ name, input_type_id, output_type_id }`.
/// Returns a composed proof with the overall input/output types.
pub fn compose_proofs(&mut self, stages: JsValue) -> Result<JsValue, JsError> {
let rust_stages: Vec<CorePipelineStage> = serde_wasm_bindgen::from_value(stages)
.map_err(|e| JsError::new(&format!("invalid stages: {e}")))?;
let result = self
.inner
.compose_proofs(&rust_stages)
.map_err(|e| JsError::new(&format!("{e}")))?;
serde_wasm_bindgen::to_value(&result).map_err(|e| JsError::new(&e.to_string()))
}
// ===================================================================
// Sublinear Attention
// ===================================================================
/// Sublinear graph attention using personalized PageRank sparsification.
///
/// `query` is a Float64Array, `edges` is `[[u32, ...], ...]`.
/// Returns `{ scores, top_k_indices, sparsity_ratio }`.
pub fn sublinear_attention(
&mut self,
query: JsValue,
edges: JsValue,
dim: u32,
k: u32,
) -> Result<JsValue, JsError> {
let q: Vec<f64> = serde_wasm_bindgen::from_value(query)
.map_err(|e| JsError::new(&format!("invalid query: {e}")))?;
let ed: Vec<Vec<u32>> = serde_wasm_bindgen::from_value(edges)
.map_err(|e| JsError::new(&format!("invalid edges: {e}")))?;
let result = self
.inner
.sublinear_attention(&q, &ed, dim, k)
.map_err(|e| JsError::new(&format!("{e}")))?;
serde_wasm_bindgen::to_value(&result).map_err(|e| JsError::new(&e.to_string()))
}
/// Compute personalized PageRank scores from a source node.
///
/// Returns array of PPR scores, one per node.
pub fn ppr_scores(
&mut self,
source: u32,
adjacency: JsValue,
alpha: f64,
) -> Result<JsValue, JsError> {
let adj: Vec<Vec<u32>> = serde_wasm_bindgen::from_value(adjacency)
.map_err(|e| JsError::new(&format!("invalid adjacency: {e}")))?;
let scores = self.inner.ppr_scores(source, &adj, alpha);
serde_wasm_bindgen::to_value(&scores).map_err(|e| JsError::new(&e.to_string()))
}
// ===================================================================
// Physics-Informed Layers
// ===================================================================
/// Symplectic integrator step (leapfrog / Stormer-Verlet).
///
/// `positions` and `momenta` are Float64Arrays, `edges` is
/// `[{ src, tgt }, ...]`. Returns `{ positions, momenta, energy,
/// energy_conserved }`.
pub fn hamiltonian_step(
&mut self,
positions: JsValue,
momenta: JsValue,
edges: JsValue,
) -> Result<JsValue, JsError> {
let pos: Vec<f64> = serde_wasm_bindgen::from_value(positions)
.map_err(|e| JsError::new(&format!("invalid positions: {e}")))?;
let mom: Vec<f64> = serde_wasm_bindgen::from_value(momenta)
.map_err(|e| JsError::new(&format!("invalid momenta: {e}")))?;
let ed: Vec<Edge> = serde_wasm_bindgen::from_value(edges)
.map_err(|e| JsError::new(&format!("invalid edges: {e}")))?;
let result = self
.inner
.hamiltonian_step_graph(&pos, &mom, &ed, 0.01)
.map_err(|e| JsError::new(&format!("{e}")))?;
serde_wasm_bindgen::to_value(&result).map_err(|e| JsError::new(&e.to_string()))
}
/// Verify energy conservation between two states.
///
/// Returns `{ conserved, delta, relative_error }`.
pub fn verify_energy_conservation(
&self,
before: f64,
after: f64,
tolerance: f64,
) -> Result<JsValue, JsError> {
let v = self
.inner
.verify_energy_conservation(before, after, tolerance);
serde_wasm_bindgen::to_value(&v).map_err(|e| JsError::new(&e.to_string()))
}
// ===================================================================
// Biological-Inspired
// ===================================================================
/// Spiking neural attention step over 2D features with adjacency.
///
/// `features` is `[[f64, ...], ...]`, `adjacency` is a flat row-major
/// Float64Array (n x n). Returns `{ features, spikes, weights }`.
pub fn spiking_step(
&mut self,
features: JsValue,
adjacency: JsValue,
) -> Result<JsValue, JsError> {
let feats: Vec<Vec<f64>> = serde_wasm_bindgen::from_value(features)
.map_err(|e| JsError::new(&format!("invalid features: {e}")))?;
let adj: Vec<f64> = serde_wasm_bindgen::from_value(adjacency)
.map_err(|e| JsError::new(&format!("invalid adjacency: {e}")))?;
let result = self.inner.spiking_step(&feats, &adj, 1.0);
serde_wasm_bindgen::to_value(&result).map_err(|e| JsError::new(&e.to_string()))
}
/// Hebbian weight update.
///
/// `pre`, `post`, `weights` are Float64Arrays. Returns updated weights.
pub fn hebbian_update(
&mut self,
pre: JsValue,
post: JsValue,
weights: JsValue,
) -> Result<JsValue, JsError> {
let pre_v: Vec<f64> = serde_wasm_bindgen::from_value(pre)
.map_err(|e| JsError::new(&format!("invalid pre: {e}")))?;
let post_v: Vec<f64> = serde_wasm_bindgen::from_value(post)
.map_err(|e| JsError::new(&format!("invalid post: {e}")))?;
let w: Vec<f64> = serde_wasm_bindgen::from_value(weights)
.map_err(|e| JsError::new(&format!("invalid weights: {e}")))?;
let result = self.inner.hebbian_update(&pre_v, &post_v, &w, 0.01);
serde_wasm_bindgen::to_value(&result).map_err(|e| JsError::new(&e.to_string()))
}
// ===================================================================
// Temporal
// ===================================================================
/// Causal attention with temporal ordering over graph edges.
///
/// `features` is a Float64Array, `timestamps` is a Float64Array,
/// `edges` is `[{ src, tgt }, ...]`.
/// Returns attention-weighted output features.
pub fn causal_attention(
&mut self,
features: JsValue,
timestamps: JsValue,
edges: JsValue,
) -> Result<JsValue, JsError> {
let feats: Vec<f64> = serde_wasm_bindgen::from_value(features)
.map_err(|e| JsError::new(&format!("invalid features: {e}")))?;
let ts: Vec<f64> = serde_wasm_bindgen::from_value(timestamps)
.map_err(|e| JsError::new(&format!("invalid timestamps: {e}")))?;
let ed: Vec<Edge> = serde_wasm_bindgen::from_value(edges)
.map_err(|e| JsError::new(&format!("invalid edges: {e}")))?;
let result = self.inner.causal_attention_graph(&feats, &ts, &ed);
serde_wasm_bindgen::to_value(&result).map_err(|e| JsError::new(&e.to_string()))
}
/// Extract Granger causality DAG from attention history.
///
/// `attention_history` is a flat Float64Array (T x N row-major).
/// Returns `{ edges: [{ source, target, f_statistic, is_causal }], num_nodes }`.
pub fn granger_extract(
&mut self,
attention_history: JsValue,
num_nodes: u32,
num_steps: u32,
) -> Result<JsValue, JsError> {
let hist: Vec<f64> = serde_wasm_bindgen::from_value(attention_history)
.map_err(|e| JsError::new(&format!("invalid attention_history: {e}")))?;
let dag = self.inner.granger_extract(&hist, num_nodes, num_steps);
serde_wasm_bindgen::to_value(&dag).map_err(|e| JsError::new(&e.to_string()))
}
// ===================================================================
// Manifold
// ===================================================================
/// Product manifold attention with mixed curvatures.
///
/// `features` is a Float64Array, `edges` is `[{ src, tgt }, ...]`.
/// Optional `curvatures` (defaults to `[0.0, -1.0]`).
/// Returns `{ output, curvatures, distances }`.
pub fn product_manifold_attention(
&mut self,
features: JsValue,
edges: JsValue,
) -> Result<JsValue, JsError> {
let feats: Vec<f64> = serde_wasm_bindgen::from_value(features)
.map_err(|e| JsError::new(&format!("invalid features: {e}")))?;
let ed: Vec<Edge> = serde_wasm_bindgen::from_value(edges)
.map_err(|e| JsError::new(&format!("invalid edges: {e}")))?;
let curvatures = vec![0.0, -1.0]; // default mixed curvatures
let result = self
.inner
.product_manifold_attention(&feats, &ed, &curvatures);
serde_wasm_bindgen::to_value(&result).map_err(|e| JsError::new(&e.to_string()))
}
/// Product manifold distance between two points.
///
/// `a` and `b` are Float64Arrays, `curvatures` is `[number, ...]`.
pub fn product_manifold_distance(
&self,
a: JsValue,
b: JsValue,
curvatures: JsValue,
) -> Result<f64, JsError> {
let av: Vec<f64> = serde_wasm_bindgen::from_value(a)
.map_err(|e| JsError::new(&format!("invalid a: {e}")))?;
let bv: Vec<f64> = serde_wasm_bindgen::from_value(b)
.map_err(|e| JsError::new(&format!("invalid b: {e}")))?;
let cv: Vec<f64> = serde_wasm_bindgen::from_value(curvatures)
.map_err(|e| JsError::new(&format!("invalid curvatures: {e}")))?;
Ok(self.inner.product_manifold_distance(&av, &bv, &cv))
}
// ===================================================================
// Verified Training
// ===================================================================
/// Verified training step with features, targets, and weights.
///
/// `features`, `targets`, `weights` are Float64Arrays.
/// Returns `{ weights, certificate_id, loss, loss_monotonic,
/// lipschitz_satisfied }`.
pub fn verified_training_step(
&mut self,
features: JsValue,
targets: JsValue,
weights: JsValue,
) -> Result<JsValue, JsError> {
let f: Vec<f64> = serde_wasm_bindgen::from_value(features)
.map_err(|e| JsError::new(&format!("invalid features: {e}")))?;
let t: Vec<f64> = serde_wasm_bindgen::from_value(targets)
.map_err(|e| JsError::new(&format!("invalid targets: {e}")))?;
let w: Vec<f64> = serde_wasm_bindgen::from_value(weights)
.map_err(|e| JsError::new(&format!("invalid weights: {e}")))?;
let result = self
.inner
.verified_training_step(&f, &t, &w, 0.001)
.map_err(|e| JsError::new(&format!("{e}")))?;
serde_wasm_bindgen::to_value(&result).map_err(|e| JsError::new(&e.to_string()))
}
/// A single verified SGD step (raw weights + gradients).
///
/// Returns `{ weights, proof_id, loss_before, loss_after, gradient_norm }`.
pub fn verified_step(
&mut self,
weights: JsValue,
gradients: JsValue,
lr: f64,
) -> Result<JsValue, JsError> {
let w: Vec<f64> = serde_wasm_bindgen::from_value(weights)
.map_err(|e| JsError::new(&format!("invalid weights: {e}")))?;
let g: Vec<f64> = serde_wasm_bindgen::from_value(gradients)
.map_err(|e| JsError::new(&format!("invalid gradients: {e}")))?;
let result = self
.inner
.verified_step(&w, &g, lr)
.map_err(|e| JsError::new(&format!("{e}")))?;
serde_wasm_bindgen::to_value(&result).map_err(|e| JsError::new(&e.to_string()))
}
// ===================================================================
// Economic / Game-Theoretic
// ===================================================================
/// Game-theoretic attention: computes Nash equilibrium allocations.
///
/// `features` is a Float64Array, `edges` is `[{ src, tgt }, ...]`.
/// Returns `{ allocations, utilities, nash_gap, converged }`.
pub fn game_theoretic_attention(
&mut self,
features: JsValue,
edges: JsValue,
) -> Result<JsValue, JsError> {
let feats: Vec<f64> = serde_wasm_bindgen::from_value(features)
.map_err(|e| JsError::new(&format!("invalid features: {e}")))?;
let ed: Vec<Edge> = serde_wasm_bindgen::from_value(edges)
.map_err(|e| JsError::new(&format!("invalid edges: {e}")))?;
let result = self.inner.game_theoretic_attention(&feats, &ed);
serde_wasm_bindgen::to_value(&result).map_err(|e| JsError::new(&e.to_string()))
}
// ===================================================================
// Stats & Reset
// ===================================================================
/// Return transformer statistics.
///
/// Returns `{ proofs_constructed, proofs_verified, cache_hits,
/// cache_misses, attention_ops, physics_ops, bio_ops, training_steps }`.
pub fn stats(&self) -> Result<JsValue, JsError> {
let s = self.inner.stats();
serde_wasm_bindgen::to_value(&s).map_err(|e| JsError::new(&e.to_string()))
}
/// Reset all internal state (caches, counters, gates).
pub fn reset(&mut self) {
self.inner.reset();
}
}
// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_version_nonempty() {
assert!(!version().is_empty());
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
//! WASM utility helpers.
/// Set panic hook for better panic messages in the browser.
///
/// No-op; add `console_error_panic_hook` as an optional dependency for
/// improved browser diagnostics.
pub fn set_panic_hook() {
// Intentional no-op. In production, wire up console_error_panic_hook.
}

View File

@@ -0,0 +1,60 @@
//! WASM integration tests (run with wasm-pack test --headless --chrome).
#![cfg(target_arch = "wasm32")]
use wasm_bindgen::JsValue;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test]
fn test_version() {
let v = ruvector_graph_transformer_wasm::version();
assert!(!v.is_empty());
}
#[wasm_bindgen_test]
fn test_proof_gate_roundtrip() {
let mut gt = ruvector_graph_transformer_wasm::JsGraphTransformer::new(JsValue::NULL)
.expect("default config should work");
// Create gate
let gate = gt.create_proof_gate(64).expect("create_proof_gate");
// Prove with some data
let data: Vec<f32> = vec![0.5; 64];
let att = gt.prove_and_mutate(gate, &data).expect("prove_and_mutate");
assert!(!att.is_undefined());
assert!(!att.is_null());
}
#[wasm_bindgen_test]
fn test_sublinear_attention() {
let gt = ruvector_graph_transformer_wasm::JsGraphTransformer::new(JsValue::NULL)
.expect("default config");
let query: Vec<f32> = vec![0.1; 8];
let edges = serde_wasm_bindgen::to_value(&vec![
serde_json::json!({"src": 0, "tgt": 1}),
serde_json::json!({"src": 0, "tgt": 2}),
serde_json::json!({"src": 1, "tgt": 3}),
])
.unwrap();
let scores = gt
.sublinear_attention(&query, edges, 8, 2)
.expect("sublinear_attention");
assert_eq!(scores.len(), 2);
}
#[wasm_bindgen_test]
fn test_stats() {
let gt = ruvector_graph_transformer_wasm::JsGraphTransformer::new(JsValue::NULL)
.expect("default config");
let stats = gt.stats().expect("stats");
assert!(!stats.is_undefined());
assert!(!stats.is_null());
}