Skip to content

MrScripty/Pumas-Library

Repository files navigation

Pumas Library

License Rust Electron Platform Bindings

Available as a desktop GUI for end-users, and as a headless Rust crate with language bindings for embeddable API use.

Pumas Library is an easy to use AI model library that downloads, organizes, and serves AI model weights and metadata to other apps. Instead of having models duplicated or scattered across applications, Pumas Library provides a standardized central source that is automatically maintained. When integrated into other software via the Rust crate, it eliminates the need for a slew of file, network, and remote API boilerplate and smart logic.

Features

Core Library

  • Single portable model library with rich metadata and full-text search (SQLite FTS5)
  • HuggingFace integration — search, download with progress tracking, metadata lookup, cached search (24hr TTL)
  • Model import with automatic type detection and dual-hash verification (SHA256 + BLAKE3)
  • Model mapping — symlink/hardlink models into app directories with health tracking
  • Instance convergence — multiple processes share a single primary via local TCP IPC
  • Cross-process library discovery via global SQLite registry
  • Resilient networking — per-domain circuit breaker, exponential backoff, rate limit handling
  • Library merging with hash-based deduplication
  • Torch inference server — Python backend for running models with GPU slot management

Supported Model Types: LLM, Reranker, Diffusion, Embedding, Audio, Vision Supported Subtypes: Checkpoints, LoRAs, VAE, ControlNet, Embeddings, Upscale, CLIP, T5 Compatible Engines: Ollama, llama.cpp, Candle, Transformers, Diffusers, ONNX Runtime, TensorRT

Desktop GUI (Electron)

  • Link your apps to your library, no manual setup required
  • System and per-app resource monitoring
  • Install and run different app versions (currently ComfyUI, Ollama, Torch)
  • Smart system shortcuts that don't require the launcher to work
  • Plugin system for JSON-based app definitions

Architecture

Core Library

The Rust crate (pumas-library) operates in one of two transparent modes:

  • Primary — owns the full state and runs a local IPC server. Holds all subsystems: model library, network manager, process manager, HuggingFace client, model importer, model mapper, IPC server, and registry.
  • Client — discovers a running primary via the global registry and proxies calls over TCP IPC. The public API is identical in both modes.

Key internals:

  • Registry: SQLite database at ~/.config/pumas/registry.db for cross-process library and instance discovery
  • IPC Protocol: JSON-RPC 2.0 over length-prefixed TCP frames on localhost
  • Search Index: SQLite FTS5 for model metadata full-text search
  • Best-effort design: registry and IPC failures never block API initialization
  • Feature flags: full (default), hf-client, process-manager, gpu-monitor, uniffi

Desktop Application

  • Frontend: React 19 + Vite (rendered in Electron's Chromium)
  • Desktop Shell: Electron 38+ (with native Wayland support on Linux)
  • Backend: Rust pumas-rpc binary running as a sidecar (Axum HTTP server, JSON-RPC)
  • IPC: JSON-RPC communication between Electron and the Rust backend

Quick Start (Rust Crate)

Add the dependency:

[dependencies]
pumas-library = { path = "rust/crates/pumas-core" }

# Or with specific features only
pumas-library = { path = "rust/crates/pumas-core", features = ["hf-client"] }

Basic usage:

use pumas_library::PumasApi;

#[tokio::main]
async fn main() -> pumas_library::Result<()> {
    // Standard initialization
    let api = PumasApi::new("/path/to/pumas").await?;

    // Or use the builder for more control
    let api = PumasApi::builder("./my-models")
        .auto_create_dirs(true)
        .with_hf_client(false)
        .build()
        .await?;

    // Or discover an existing instance from the global registry
    let api = PumasApi::discover().await?;

    // List models in the library
    let models = api.list_models().await?;
    println!("Found {} models", models.len());

    // Search for models
    let search = api.search_models("llama", 10, 0).await?;
    println!("Search found {} results", search.total_count);

    Ok(())
}

Library Refresh and Partial Downloads

Use full reconciliation when the on-disk library and SQLite index drift (for example after interrupted downloads):

cd rust
cargo run --package pumas-library --example repair_library_integrity -- /path/to/shared-resources/models

This maintenance flow performs duplicate cleanup, reclassification, and index rebuild in one pass. Migration reports now distinguish:

  • metadata-backed index rows
  • partial-download index rows
  • stale index rows

Partial downloads (.part files) remain resumable and are tracked as partial rows until completed. Migration execution can now safely relocate partial-download directories to canonical paths by pausing tracked downloads, moving the directory, updating persistence/index paths, and resuming when appropriate.

HuggingFace Download Retry Tuning

HuggingFace file downloads automatically retry transient network failures with resume support.

  • Default max attempts: unlimited (0)
  • Default max retry elapsed budget per file: 43200 seconds (12 hours)
  • Override with environment variables:
    • PUMAS_HF_DOWNLOAD_MAX_RETRIES (0 = unlimited)
    • PUMAS_HF_DOWNLOAD_MAX_RETRY_ELAPSED_SECS (0 = disable elapsed cap)

Supported Platforms

Platform Status Notes
Linux (x64) Full support Debian/Ubuntu recommended, AppImage and .deb packages
Windows (x64) Full support NSIS installer and portable versions
macOS (ARM) Best-effort ARM builds via CI, not regularly tested

Installation

System Requirements

Linux

  • Operating System: Linux (Debian/Ubuntu-based distros recommended)
  • Rust: 1.75+
  • Node.js: 22+ LTS

Windows

  • Operating System: Windows 11 (x64)
  • Rust: 1.75+ (install via rustup)
  • Node.js: 22+ LTS (install via nodejs.org)
  • Build Tools: Visual Studio Build Tools with C++ workload

Linux Installation

Launcher Setup (Recommended)

Use the root launcher script:

chmod +x launcher.sh
./launcher.sh --install
./launcher.sh --build-release
./launcher.sh --run

The launcher-managed flow:

  1. Verifies local tool/runtime dependencies (cargo, node, npm, workspace node_modules)
  2. Builds Rust backend + frontend + Electron artifacts
  3. Starts Electron with the Rust sidecar backend

Manual Installation (Linux)

  1. Install system dependencies (Debian/Ubuntu):

    sudo apt update
    sudo apt install nodejs npm cargo
  2. Build Rust backend:

    cd rust
    cargo build --release
    cd ..
  3. Install and build frontend:

    cd frontend
    npm ci
    npm run build
    cd ..
  4. Install Electron dependencies:

    cd electron
    npm ci
    npm run build
    cd ..
  5. Make launcher executable (should already be executable):

    chmod +x launcher.sh

Optional: Add to PATH (Linux)

For system-wide access:

ln -s $(pwd)/launcher.sh ~/.local/bin/pumas-library

Then run from anywhere:

pumas-library --help

Windows Installation

Prerequisites

  1. Install Rust via rustup:

    • Download and run rustup-init.exe
    • Follow the prompts to install
  2. Install Node.js from nodejs.org:

    • Download the LTS version (22+)
    • Run the installer
  3. Install Visual Studio Build Tools (if not already installed):

Manual Installation (Windows)

Open PowerShell and run:

  1. Build Rust backend:

    cd rust
    cargo build --release
    cd ..
  2. Install and build frontend:

    cd frontend
    npm ci
    npm run build
    cd ..
  3. Install and build Electron:

    cd electron
    npm ci
    npm run build
    cd ..
  4. Run the application:

    cd electron
    npm start

Building Windows Installer

To create a distributable Windows installer:

cd electron
npm run package:win

This creates:

  • NSIS installer (.exe) in electron/release/
  • Portable version (.exe) in electron/release/

Usage

Linux Launcher Commands

Run the launcher with different modes:

Command Description
./launcher.sh --install Install launcher dependencies (cargo/node/npm + workspace deps)
./launcher.sh --build Build debug backend + frontend + electron
./launcher.sh --build-release Build release backend + frontend + electron
./launcher.sh --run Run Electron in development mode
./launcher.sh --run -- --devtools Run development mode with app flags
./launcher.sh --run-release Run packaged artifacts directly
./launcher.sh --help Display usage information

Note: --run currently expects the release Rust backend binary (rust/target/release/pumas-rpc), so run ./launcher.sh --build-release first.

Windows Commands

On Windows, use npm scripts directly:

Command Description
npm start (in electron/) Launch the application
npm run dev (in electron/) Launch with developer tools
npm run package:win (in electron/) Package for Windows distribution

Building from Source

All Platforms

# Build Rust backend
cd rust
cargo build --release

# Build frontend
cd ../frontend
npm ci
npm run build

# Build and run Electron
cd ../electron
npm ci
npm run build
npm start

Creating Distribution Packages

Platform Command Output
Linux npm run package:linux AppImage, .deb
Windows npm run package:win NSIS installer, portable
macOS npm run package:mac DMG

Release Validation

Before cutting a release, run:

cd rust
cargo test --workspace --exclude pumas_rustler
cargo clippy --workspace --exclude pumas_rustler -- -D warnings
cargo build --workspace --exclude pumas_rustler
cd ..
npm run -w frontend test:run
npm run -w frontend check:types
npm run -w frontend build
npm run -w electron validate
npm run -w electron build

For pumas_rustler, run tests separately on a machine with Erlang/OTP installed.


Development

Project Structure

Pumas-Library/
├── rust/                       # Rust workspace
│   └── crates/
│       ├── pumas-core/         # Core headless library (model library, IPC, registry, networking)
│       ├── pumas-app-manager/  # App version and extension management (ComfyUI, Ollama, Torch)
│       ├── pumas-rpc/          # Axum JSON-RPC server (Electron backend)
│       ├── pumas-uniffi/       # Python, C#, Kotlin, Swift, Ruby bindings (UniFFI)
│       └── pumas-rustler/      # Elixir/Erlang NIFs (Rustler)
├── frontend/                   # React 19 + Vite frontend
├── electron/                   # Electron 38+ shell
├── bindings/                   # Generated language bindings and artifacts
└── .github/workflows/          # CI/CD

Platform-Specific Code

All platform-specific code is centralized in rust/crates/pumas-core/src/platform/:

  • paths.rs - Platform-specific directories
  • permissions.rs - File permission handling
  • process.rs - Process management

Managed Applications

Process management, version installation, and model mapping are supported for:

ComfyUI, Ollama, and Torch.

Additional apps can be defined via the JSON plugin system without code changes.


Language Bindings

Pumas Library's core Rust crate can be used from other languages via cross-language bindings. Two binding systems are available:

  • UniFFI (Python, C#, Kotlin, Swift, Ruby) — Mozilla's cross-language bindings generator
  • Rustler (Elixir/Erlang) — Native Implemented Functions for the BEAM VM

Generating Bindings

Use the standalone script:

./scripts/generate-bindings.sh python
./scripts/generate-bindings.sh csharp
./scripts/generate-bindings.sh elixir
./scripts/generate-bindings.sh all

Generated bindings are written to bindings/ and can be regenerated with scripts/generate-bindings.sh.

Prerequisites

Language Tool Install Command
Python uniffi-bindgen cargo install uniffi-bindgen-cli
C# uniffi-bindgen-cs cargo install uniffi-bindgen-cs --git https://github.com/NordSecurity/uniffi-bindgen-cs --tag v0.9.0+v0.28.3
Elixir Rustler Add {:rustler, "~> 0.34"} to mix.exs

Python

After generating, the bindings are in bindings/python/. The native shared library is copied alongside the Python module.

import sys
sys.path.insert(0, "bindings/python")
from pumas_uniffi import version
print(version())

C#

After generating, add the .cs files from bindings/csharp/ to your .NET project and ensure the native library (libpumas_uniffi.so / .dll / .dylib) is in the output directory.

using PumasUniFFI;
Console.WriteLine(PumasUniffiMethods.Version());

Elixir

Elixir bindings use Rustler, which compiles the NIF as part of the Mix build rather than generating source files. Add Rustler as a dependency and create a NIF module:

# mix.exs
defp deps do
  [{:rustler, "~> 0.34"}]
end
# lib/pumas/native.ex
defmodule Pumas.Native do
  use Rustler, otp_app: :pumas, crate: "pumas_rustler"

  def version(), do: :erlang.nif_error(:nif_not_loaded)
  def parse_model_type(_type), do: :erlang.nif_error(:nif_not_loaded)
  def validate_json(_json), do: :erlang.nif_error(:nif_not_loaded)
end

UniFFI Feature Flag

The uniffi feature on pumas-core is optional and only adds derive annotations. It has zero overhead when disabled:

# Use pumas-core without FFI (default)
pumas-library = { path = "rust/crates/pumas-core" }

# Use pumas-core with UniFFI derives enabled
pumas-library = { path = "rust/crates/pumas-core", features = ["uniffi"] }

About

Local AI model management library, with optional GUI. Cross platform & language bindings.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages