npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@stateset/nsr

v0.2.0

Published

Node.js bindings for the NSR (Neuro-Symbolic Recursive) AI framework

Readme

@stateset/nsr

Node.js bindings for the NSR (Neuro-Symbolic Recursive) AI framework.

NSR is a state-of-the-art hybrid AI framework that combines neural network pattern recognition with symbolic logical reasoning for robust, explainable AI systems. These native bindings provide high-performance access to the NSR Machine from Node.js and TypeScript applications.

Installation

npm install @stateset/nsr

Requirements

  • Node.js >= 16
  • Supported platforms:
    • macOS (x64, ARM64)
    • Linux (x64, ARM64, glibc and musl)
    • Windows (x64, ARM64)

Quick Start

import { NSRMachine, GroundedInput, SemanticValue, TrainingExample } from '@stateset/nsr';

// Create a machine using the SCAN preset (compositional generalization)
const machine = scanMachine();

// Or create with custom configuration
const customMachine = new NSRMachineBuilder()
  .embeddingDim(64)
  .hiddenSize(128)
  .addSymbol('walk')
  .addSymbol('run')
  .addSymbol('jump')
  .build();

// Create training examples
const examples = [
  TrainingExample.fromText('walk', SemanticValue.actions(['WALK'])),
  TrainingExample.fromText('run', SemanticValue.actions(['RUN'])),
  TrainingExample.fromText('jump', SemanticValue.actions(['JUMP'])),
  TrainingExample.fromText('walk twice', SemanticValue.actions(['WALK', 'WALK'])),
];

// Train the machine
const stats = machine.train(examples);
console.log(`Trained on ${stats.totalExamples} examples in ${stats.trainingTimeMs}ms`);

// Run inference
const result = machine.infer([GroundedInput.text('jump twice')]);
console.log(`Output: ${result.output()}`);
console.log(`Confidence: ${result.confidence()}`);

Features

  • Grounded Symbol System (GSS): Unified representation combining perception, syntax, and semantics
  • Neural Perception: Maps raw inputs (text, numbers, images) to symbol probabilities
  • Program Synthesis: Learns functional programs for semantic computation
  • Compositional Generalization: Achieves near-perfect accuracy on SCAN, PCFG, HINT, and COGS benchmarks
  • TypeScript Support: Full type definitions included

API Reference

Input Types

GroundedInput

Raw input to the NSR system.

// Create different input types
const text = GroundedInput.text('hello world');
const num = GroundedInput.number(42.0);
const img = GroundedInput.image(pixelData, width, height, channels);
const emb = GroundedInput.embedding([0.1, 0.2, 0.3, ...]);
const nil = GroundedInput.nil();

// Check input type
text.isText();    // true
text.isNumber();  // false
text.isNil();     // false

// Get value
text.asText();    // 'hello world'
num.asNumber();   // 42.0

Output Types

SemanticValue

Computed semantic output from NSR inference.

// Create different output types
const int = SemanticValue.integer(42);
const float = SemanticValue.float(3.14);
const bool = SemanticValue.boolean(true);
const str = SemanticValue.string('result');
const sym = SemanticValue.symbol('WALK');
const actions = SemanticValue.actions(['WALK', 'TURN_LEFT', 'WALK']);
const list = SemanticValue.list([SemanticValue.integer(1), SemanticValue.integer(2)]);
const nil = SemanticValue.null();

// Get values
int.asInteger();      // 42
float.asFloat();      // 3.14
str.asString();       // 'result'
actions.asActions();  // ['WALK', 'TURN_LEFT', 'WALK']

// Check type
nil.isNull();   // true
nil.isError();  // false

Program Types

Primitive

Built-in primitive operations for program synthesis.

// Arithmetic
Primitive.add();  // Addition
Primitive.sub();  // Subtraction
Primitive.mul();  // Multiplication
Primitive.div();  // Division

// Comparison
Primitive.eq();   // Equality
Primitive.lt();   // Less than
Primitive.gt();   // Greater than

// Logic
Primitive.and();  // Logical AND
Primitive.or();   // Logical OR
Primitive.not();  // Logical NOT

// List operations
Primitive.cons(); // List construction
Primitive.car();  // First element
Primitive.cdr();  // Rest of list

// Utility
Primitive.identity();  // Identity function

// Get info
const add = Primitive.add();
add.arity();  // 2
add.name();   // 'add'

Program

Functional programs for computing semantics.

// Constant program
const constProg = Program.constant(SemanticValue.integer(42));

// Variable reference (for lambda bodies)
const varProg = Program.var(0);

// Child reference (access child nodes in GSS)
const childProg = Program.child(0);

// Primitive application
const addProg = Program.primitive(Primitive.add(), [
  Program.child(0),
  Program.child(1)
]);

// Lambda abstraction
const lambdaProg = Program.lambda(2, addProg);

// Function application
const applyProg = Program.apply(lambdaProg, [
  Program.constant(SemanticValue.integer(1)),
  Program.constant(SemanticValue.integer(2))
]);

// Conditional
const condProg = Program.ifThenElse(
  Program.child(0),
  Program.constant(SemanticValue.string('yes')),
  Program.constant(SemanticValue.string('no'))
);

// Program metrics
constProg.depth();       // 1
constProg.size();        // 1
constProg.isConstant();  // true

Training

TrainingExample

A single training example for the NSR machine.

// Create from inputs and output
const example = new TrainingExample(
  [GroundedInput.text('walk'), GroundedInput.text('twice')],
  SemanticValue.actions(['WALK', 'WALK']),
  0.5  // optional difficulty (0.0 - 1.0)
);

// Convenience constructors
const textExample = TrainingExample.fromText('hello', SemanticValue.string('HELLO'));
const tokenExample = TrainingExample.fromTokens(['walk', 'left'], SemanticValue.actions(['TURN_LEFT', 'WALK']));

// Properties
example.difficulty;   // 0.5
example.inputCount;   // 2

TrainingStats

Statistics returned from training.

interface TrainingStats {
  totalExamples: number;       // Number of examples trained on
  successfulAbductions: number; // Successful program inductions
  trainingTimeMs: number;       // Training duration in milliseconds
}

Machine Configuration

NSRConfig

Configuration options for the NSR machine.

interface NSRConfig {
  embeddingDim: number;     // Embedding vector dimension (default: 64)
  hiddenSize: number;       // Hidden layer size (default: 128)
  maxSeqLen: number;        // Maximum sequence length (default: 64)
  beamWidth: number;        // Beam search width (default: 5)
  enableSynthesis: boolean; // Enable program synthesis (default: true)
  maxProgramDepth: number;  // Maximum program depth (default: 6)
}

NSRMachine

The main neuro-symbolic reasoning machine.

Construction

// Default machine
const machine = new NSRMachine();

// With configuration
const configuredMachine = NSRMachine.withConfig({
  embeddingDim: 128,
  hiddenSize: 256,
  maxSeqLen: 128,
  beamWidth: 10,
  enableSynthesis: true,
  maxProgramDepth: 8
});

// Using builder (recommended)
const builtMachine = new NSRMachineBuilder()
  .embeddingDim(64)
  .hiddenSize(128)
  .maxSeqLen(64)
  .beamWidth(5)
  .addSymbol('walk')
  .addSymbol('run')
  .enableSynthesis(true)
  .withExplainability()
  .build();

Inference

const result = machine.infer([GroundedInput.text('walk twice')]);

result.output();         // Output value as string
result.confidence();     // Confidence score (0.0 - 1.0)
result.symbols();        // Predicted symbol sequence
result.nodeCount();      // Number of GSS nodes
result.logProbability(); // Log probability of prediction

Training

const examples = [
  TrainingExample.fromText('a', SemanticValue.integer(1)),
  TrainingExample.fromText('b', SemanticValue.integer(2)),
];

const stats = machine.train(examples);
// stats.totalExamples: 2
// stats.successfulAbductions: 2
// stats.trainingTimeMs: 15

Evaluation

const testExamples = [
  TrainingExample.fromText('a', SemanticValue.integer(1)),
  TrainingExample.fromText('c', SemanticValue.integer(3)),
];

const result = machine.evaluate(testExamples);
// result.accuracy: 0.5
// result.correct: 1
// result.total: 2

Symbol Management

// Add symbols
const walkId = machine.addSymbol('walk');
const ids = machine.addSymbols(['run', 'jump', 'turn']);

// Query symbols
machine.getSymbolName(0);      // 'walk'
machine.getSymbolId('walk');   // 0
machine.getAllSymbols();       // ['walk', 'run', 'jump', 'turn']
machine.vocabularySize;        // 4

Statistics

const stats = machine.statistics;
// stats.trainingExamples: 100
// stats.successfulInferences: 95
// stats.programsLearned: 12
// stats.vocabularySize: 20

Preset Machines

Pre-configured machines for standard benchmarks:

import { scanMachine, pcfgMachine, hintMachine, cogsMachine } from '@stateset/nsr';

// SCAN: Compositional command interpretation
// "walk twice" -> ['WALK', 'WALK']
const scan = scanMachine();

// PCFG: Probabilistic context-free grammar tasks
// Character-level sequence transduction
const pcfg = pcfgMachine();

// HINT: Hierarchical arithmetic expressions
// "( 2 + 3 ) * 4" -> 20
const hint = hintMachine();

// COGS: Compositional generalization challenge
// Semantic parsing with systematic generalization
const cogs = cogsMachine();

Utility Functions

import { version } from '@stateset/nsr';

// Get library version
console.log(version()); // '0.2.0'

Examples

SCAN-style Command Learning

import { scanMachine, GroundedInput, SemanticValue, TrainingExample } from '@stateset/nsr';

const machine = scanMachine();

// Train on primitive commands
const trainData = [
  TrainingExample.fromText('walk', SemanticValue.actions(['WALK'])),
  TrainingExample.fromText('run', SemanticValue.actions(['RUN'])),
  TrainingExample.fromText('jump', SemanticValue.actions(['JUMP'])),
  TrainingExample.fromText('turn left', SemanticValue.actions(['TURN_LEFT'])),
  TrainingExample.fromText('turn right', SemanticValue.actions(['TURN_RIGHT'])),
  // Compositional examples
  TrainingExample.fromText('walk twice', SemanticValue.actions(['WALK', 'WALK'])),
  TrainingExample.fromText('jump and walk', SemanticValue.actions(['JUMP', 'WALK'])),
];

machine.train(trainData);

// Test compositional generalization
const result = machine.infer([GroundedInput.text('run twice and turn left')]);
console.log(result.output()); // ['RUN', 'RUN', 'TURN_LEFT']

Arithmetic Expression Evaluation

import { hintMachine, GroundedInput, SemanticValue, TrainingExample } from '@stateset/nsr';

const machine = hintMachine();

// Train on arithmetic examples
const trainData = [
  TrainingExample.fromText('1 + 2', SemanticValue.integer(3)),
  TrainingExample.fromText('3 * 4', SemanticValue.integer(12)),
  TrainingExample.fromText('( 2 + 3 ) * 2', SemanticValue.integer(10)),
];

machine.train(trainData);

// Evaluate new expressions
const result = machine.infer([GroundedInput.text('( 1 + 2 ) * 3')]);
console.log(result.output()); // 9

Custom Symbol Vocabulary

import { NSRMachineBuilder, GroundedInput, SemanticValue, TrainingExample } from '@stateset/nsr';

// Build a machine for sentiment analysis
const machine = new NSRMachineBuilder()
  .embeddingDim(128)
  .hiddenSize(256)
  .addSymbol('positive')
  .addSymbol('negative')
  .addSymbol('neutral')
  .enableSynthesis(false)  // Classification only
  .build();

const trainData = [
  TrainingExample.fromText('great product', SemanticValue.symbol('positive')),
  TrainingExample.fromText('terrible experience', SemanticValue.symbol('negative')),
  TrainingExample.fromText('it was okay', SemanticValue.symbol('neutral')),
];

machine.train(trainData);

const result = machine.infer([GroundedInput.text('amazing quality')]);
console.log(result.output()); // 'positive'
console.log(result.confidence()); // 0.92

Building from Source

Prerequisites

  • Rust 1.75+
  • Node.js 16+
  • npm or yarn

Build Steps

# Clone the repository
git clone https://github.com/stateset/stateset-nsr
cd stateset-nsr/nodejs

# Install dependencies
npm install

# Build native addon (release)
npm run build

# Build native addon (debug)
npm run build:debug

# Run tests
npm test

Cross-compilation

The package uses NAPI-RS for cross-platform native addons. Pre-built binaries are provided for common platforms. To build for other platforms:

# Build for all platforms
npm run artifacts

# Build universal binary (macOS)
npm run universal

Platform Support

| Platform | Architecture | libc | Status | |----------|--------------|------|--------| | macOS | x64 | - | Supported | | macOS | ARM64 | - | Supported | | Linux | x64 | glibc | Supported | | Linux | x64 | musl | Supported | | Linux | ARM64 | glibc | Supported | | Linux | ARM64 | musl | Supported | | Windows | x64 | MSVC | Supported | | Windows | ARM64 | MSVC | Supported |

Performance

The Node.js bindings provide near-native performance by using NAPI-RS to call directly into the Rust implementation. Key performance characteristics:

  • Inference latency: < 1ms for typical inputs
  • Training throughput: ~10,000 examples/second (CPU)
  • Memory efficient: Rust memory management with zero-copy where possible

Error Handling

All methods that can fail throw JavaScript Error objects with descriptive messages:

try {
  const result = machine.infer([GroundedInput.text('invalid input')]);
} catch (error) {
  console.error('Inference failed:', error.message);
}

TypeScript Support

Full TypeScript definitions are included. Import types directly:

import type {
  NSRConfig,
  TrainingStats,
  EvaluationResult,
  NSRStats
} from '@stateset/nsr';

Related Packages

  • Rust crate: stateset-nsr - Core Rust implementation
  • Python package: nsr - Python bindings

License

Business Source License 1.1 (BSL-1.1)

The license converts to Apache 2.0 on December 8, 2028.

Links

Contributing

Contributions are welcome! Please see the contributing guidelines for more information.