Skip to main content

Python FastAPI wrapper for Verlihub DC hub with native C++ core (a modified fork of Verlihub, maintained at github.com/transfix/verlihub)

Project description

Verlihub Python API

A FastAPI-based REST API and web dashboard for managing Verlihub DC hubs.

Fork notice: verlihub-py is a modified fork of Verlihub, maintained at github.com/transfix/verlihub. It is not the original project. Licensed GPL-3.0-or-later; all upstream copyrights are preserved.

Features

  • REST API - Full hub management via HTTP endpoints
  • Web Dashboard - Browser-based administration UI
  • WebSocket - Real-time hub events and log streaming
  • CLI Tools - Command-line management utilities
  • Performance Benchmarks - Load testing and performance analysis
  • Remote Client - Python client library for hub administration
  • NMDCpb Protocol Extension - Protobuf structured messaging with hub-relayed transfers, E2E encrypted PM, media sharing, channels, and voice/video signaling
  • LLM & MCP Integration - AI chat assistant with hub tool-calling, an NMDC Hub-Security bot, and a Model Context Protocol server for AI editors

Quick Start

Installation

# From PyPI (recommended)
pip install verlihub-py

# With LLM / MCP integration extras (OpenAI-compatible client + MCP server)
pip install "verlihub-py[ai]"

# From source (development)
git clone https://github.com/transfix/verlihub
cd verlihub/python
pip install -e ".[dev]"

Note: the published wheels bundle the native Verlihub C++ core (built via scikit-build-core + SWIG). A source build additionally needs CMake, SWIG, a C++17 compiler, and the hub's build dependencies.

Running the API Server

# Start the API server
verlihub-api

# Or with custom settings
verlihub-api --host 0.0.0.0 --port 8000

Using the CLI

# Check hub status
verlihub-cli status

# List online users
verlihub-cli users

# Execute a hub command
verlihub-cli command "!help"

# Login and save token
verlihub-cli login admin password123

API Endpoints

Public Endpoints

Endpoint Description
GET /health Health check
GET /api/v1/hub/stats Hub statistics
GET /api/v1/hub/info Hub information

Authenticated Endpoints

Endpoint Min Class Description
GET /api/v1/users/online 1 List online users
GET /api/v1/users/registered 3 List registered users
POST /api/v1/users/{nick}/kick 3 Kick a user
GET /api/v1/bans/ 3 List bans
POST /api/v1/bans/ 4 Create a ban
POST /api/v1/console/execute 3 Execute hub command
GET /api/v1/config/ 10 Get configuration

WebSocket Endpoints

Endpoint Description
/ws/hub Real-time hub events (joins, parts, chat)
/ws/logs Real-time log streaming

Web Dashboard

Access the dashboard at http://localhost:8000/dashboard/

Pages

  • Dashboard - Hub overview with stats and quick actions
  • Users - Online and registered user management
  • Bans - Ban list and management
  • Logs - Real-time log viewer
  • Console - Command execution interface
  • Config - Hub configuration (Master only)
  • Plugins - Plugin management (Admin only)

NMDCpb Protocol Extension

verlihub-py ships the server side of NMDCpb — a protobuf-based structured messaging layer that extends classic NMDC with six integrated features. The hub negotiates NMDCpb in $Supports, dispatches $PB/$PBR envelopes to a Python plugin, and transparently translates to legacy NMDC ($<nick>, $To:, $Search) for non-NMDCpb clients.

Extension Capability
NMDCpb Protobuf message dispatch, legacy translation, feature negotiation
HubRelay Hub-brokered relay sessions for encrypted, NAT-friendly transfers
E2EPM End-to-end encrypted private messages with key-exchange forwarding
MediaShare Media storage (filesystem/S3), HTTP upload/download API, P2P routing
Channels Channel lifecycle, membership, message routing, E2E sender keys
VoiceVideo 1:1 and group call signaling, hub streams, SFU fan-out

Admin surface

  • Chat commands (operator, class ≥ 5): +nmdcpb stats, +nmdcpb users, +nmdcpb relay, +nmdcpb channel list|create|delete|info
  • REST API under /dashboard/nmdcpb/api (admin JWT, user_class ≥ 5): GET /api/stats, GET /api/users, GET /api/relays, GET /api/relay/{id}, POST /api/relay/{id}/close, POST /api/relay/close-all, POST /api/relay/close-user/{nick}
  • Media API mounted at /api/media/ (per-user HMAC bearer tokens): POST /upload, GET /quota, GET /{id}, GET /{id}/thumb, GET /{id}/meta, DELETE /{id}
  • WebSocket /ws/relay streams relay_created / relay_closed events
  • Dashboard at /dashboard/nmdcpb/ with live stats, relay/user tables, and admin actions

Client library

A high-level Python client for these extensions (E2E-encrypted PM, hub-relayed transfers, media sharing, channels) ships in verlihub.client.nmdcpb — see NMDCpb Client Library below.

Detailed documentation

Document Contents
NMDCPB_PROTOCOL.md Wire format, envelope types, feature negotiation
NMDCPB_IMPLEMENTATION.md Hub plugin architecture, message flow, storage backends
NMDCPB_ADMIN_GUIDE.md Commands, REST/WebSocket API, dashboard, config, troubleshooting
NMDCPB_PROTOCOL_WORKFLOWS.md End-to-end sequence walkthroughs for every extension

LLM & MCP Integration

verlihub-py includes optional LLM integration that connects to any OpenAI-compatible backend (Ollama, vLLM, llama.cpp, LiteLLM, OpenRouter, or a hosted API):

  • AI Chat Assistant — a dashboard chat tab (POST /api/v1/llm/chat, streaming over /ws/llm-chat) where admins ask natural-language questions and the LLM executes hub tool-calls (list users, kick, ban, read stats) and feeds results back for a final answer.
  • NMDC Hub-Security Bot — hub users chat with an LLM-backed bot via PM or main chat, with session memory, a mood engine, web access (search/fetch/RSS), and persistent notes.
  • MCP Server — a Model Context Protocol server exposing the hub as tools/resources/prompts to AI editors (VS Code, Claude Desktop) over stdio or HTTP; ships the verlihub-mcp CLI.

Enable it in config and point base_url at your backend. See LLM_INTEGRATION.md for the full architecture, configuration reference, setup guides (Ollama/vLLM/llama.cpp), the tool-calling flow, bot features, and MCP server/client usage.

Performance Benchmarks

The benchmark suite measures API performance including latency percentiles and throughput.

Running Benchmarks

# Quick health check
verlihub-bench quick

# Full API benchmark suite
verlihub-bench api --requests 1000 --concurrency 20

# Stress test
verlihub-bench stress --requests 5000 --concurrency 50

# Detailed latency profile
verlihub-bench latency --endpoint /api/v1/hub/stats --samples 1000

# Full benchmark with all tests
verlihub-bench full --stress --websocket --output results.json

Benchmark Options

--url, -u           API base URL (default: http://localhost:8000)
--requests, -n      Requests per benchmark (default: 100)
--concurrency, -c   Concurrent connections (default: 10)
--output, -o        Output file for results (JSON)
--token, -t         Authentication token
--username          Username for auth
--password          Password for auth

Sample Output

======================================================================
Benchmark: GET /api/v1/hub/stats
======================================================================

Summary:
  Total Requests:    1,000
  Successful:        1,000 (100.0%)
  Failed:            0
  Total Time:        2.34s
  Throughput:        427.35 req/s

Latency (ms):
  Min:               1.234
  Max:               45.678
  Avg:               2.341
  Std Dev:           1.567
  p50 (median):      2.123
  p95:               4.567
  p99:               8.901
======================================================================

Programmatic Usage

import asyncio
from verlihub.benchmarks import BenchmarkRunner, BenchmarkSuite

async def run_benchmarks():
    # Create a custom benchmark suite
    suite = BenchmarkSuite("My Benchmarks")
    suite.add_endpoint("Health", "GET", "/health", num_requests=500)
    suite.add_endpoint("Stats", "GET", "/api/v1/hub/stats", num_requests=500)
    
    # Run benchmarks
    results = await suite.run(base_url="http://localhost:8000")
    
    # Print summary
    print(suite.summary())
    
    # Export to JSON
    with open("results.json", "w") as f:
        f.write(suite.to_json())

asyncio.run(run_benchmarks())

Client Library

Synchronous Client

from verlihub.client import HubClient

client = HubClient("http://localhost:8000")
client.login("admin", "password")

# Get hub stats
stats = client.get_stats()
print(f"Users online: {stats['user_count']}")

# List online users
users = client.get_online_users()
for user in users:
    print(f"  {user['nick']} - {user['share']}")

# Kick a user
client.kick_user("baduser", reason="Spamming")

Asynchronous Client

import asyncio
from verlihub.client import AsyncHubClient

async def main():
    async with AsyncHubClient("http://localhost:8000") as client:
        await client.login("admin", "password")
        stats = await client.get_stats()
        print(stats)

asyncio.run(main())

NMDC Protocol Client

from verlihub.client import NMDCClient

# Connect directly to hub via NMDC protocol
client = NMDCClient("192.168.1.100", 4111)
client.connect("BotNick", "password")

# Send a message
client.send_chat("Hello from Python!")

# Get user list
users = client.get_users()

client.disconnect()

NMDCpb Client Library (E2EPM · HubRelay · MediaShare · Channels)

Beyond the raw protocol, verlihub-py ships a high-level NMDCpb client (verlihub.client.nmdcpb) that speaks the protobuf overlay and exposes ergonomic, strongly-typed APIs for the extension features. It doubles as the reference client that validates the hub-side implementation. Requires the protobuf + cryptography extras.

from verlihub.client import NMDCpbClient  # also: WireCodec, E2EPMSession, E2EPMManager

client = NMDCpbClient("mybot", "password")
await client.connect("nmdc://hub.example.com:411")

# Structured chat / PM (protobuf)
await client.send_pb_chat("Hello from protobuf!")
await client.send_pb_pm("Alice", "Hi Alice")

End-to-end encrypted PM (E2EPM)

X25519 key exchange + ChaCha20-Poly1305, with 4-emoji verification fingerprints and Trust-On-First-Use key continuity — negotiated automatically on first use:

client.on_e2epm_established = lambda peer, fp: print(f"Secure with {peer}: {fp}")
client.on_encrypted_pm      = lambda frm, text, enc: print(f"[E2E] {frm}: {text}")

await client.send_encrypted_pm("Alice", "Secret message")

Lower-level session control is available via E2EPMManager / E2EPMSession (initiate_session, handle_key_exchange, encrypt_message, decrypt_message).

Hub-relayed transfers (HubRelay)

Hub-brokered, NAT-friendly, resumable file relay with SHA-256 verification:

from verlihub.client.nmdcpb.relay import RelayFileTransfer

relay = RelayFileTransfer(client, download_dir="/downloads")
info  = await relay.send_file("Alice", "/path/to/file.bin")   # -> TransferInfo (progress, speed, state)

# …or drive the protocol directly:
client.on_relay_request = lambda frm, token, purpose, size: None
await client.accept_relay(token)
await client.send_relay_data(relay_id, chunk, offset)
await client.close_relay(relay_id)

client.relay_only_mode = True    # privacy: force all transfers through the hub relay

Admin REST surface (dashboard, user_class ≥ 5) at /dashboard/nmdcpb/api: GET /relays, GET /relay/{id}, POST /relay/{id}/close, POST /relay/close-all, POST /relay/close-user/{nick}; live events over the /ws/relay WebSocket (relay_created / relay_closed).

Media sharing (MediaShare)

Server-side storage with per-user quota, TTL, thumbnails, and a REST surface:

from verlihub.client.nmdcpb.media_storage import MediaStorage, MediaConfig

store = MediaStorage(MediaConfig())
meta  = store.store(data, "clip.mp4", "video/mp4", uploader="mybot")   # -> MediaMeta
quota = store.get_quota("mybot")

REST API (per-user HMAC bearer tokens), mounted at /api/media:

Endpoint Description
POST /api/media/upload Upload a file (multipart)
GET /api/media/{id} Download the file
GET /api/media/{id}/thumb Download the thumbnail
GET /api/media/{id}/meta Metadata JSON
GET /api/media/quota Per-user quota
DELETE /api/media/{id} Delete (owner or admin)

Channels

Server-managed public/private channels with member roles (MEMBER/ADMIN/OWNER/READONLY), message history, and group sender-key encryption. Managed by verlihub.client.nmdcpb.channel_manager.ChannelManager (auto-creates and auto-joins #general); driven over the protobuf protocol with actions: list / create / delete / join / leave / set-topic / kick / set-role.

Protobuf message types

All wire types are importable for advanced/manual use:

from verlihub.client.nmdcpb.nmdcpb_pb2 import (
    PbEnvelope,
    PbPMKeyExchange, PbEncryptedPM, PbPMPlaintext,        # E2EPM
    PbMediaUpload, PbMediaMeta, PbMediaRef,               # MediaShare
    PbRelayRequest, PbRelayAck, PbRelayData, PbRelayClosed,  # HubRelay
    PbChannel, PbChannelList, PbChannelMemberUpdate,      # Channels
)

Configuration

Environment Variables

Variable Description Default
VH_API_HOST API bind host 0.0.0.0
VH_API_PORT API bind port 8000
VH_DB_HOST Database host localhost
VH_DB_PORT Database port 3306
VH_DB_NAME Database name verlihub
VH_DB_USER Database user verlihub
VH_DB_PASS Database password -
VH_JWT_SECRET JWT signing key (auto-generated)
VH_JWT_EXPIRE_MINUTES Token expiration 60

Database

The API supports both MySQL and SQLite:

# MySQL (production)
from verlihub.models.database import DatabaseConfig

config = DatabaseConfig(
    driver="mysql",
    host="localhost",
    port=3306,
    database="verlihub",
    username="verlihub",
    password="secret",
)

# SQLite (testing)
config = DatabaseConfig(
    driver="sqlite",
    database=":memory:",  # or path to file
)

Testing

# Run all tests
pytest

# Run with coverage
pytest --cov=verlihub --cov-report=html

# Run specific test file
pytest tests/test_api_endpoints.py -v

# Run benchmark tests
pytest tests/test_benchmarks.py -v

Test Results

Current test status: 188 passed, 21 skipped

Skipped tests require C++ SWIG bindings to be built.

Development

Project Structure

python/
├── verlihub/
│   ├── api/           # FastAPI routes and app
│   ├── dashboard/     # Web dashboard templates
│   ├── client/        # Remote client library
│   ├── models/        # SQLModel database models
│   ├── benchmarks/    # Performance testing
│   └── cli.py         # Command-line interface
├── tests/             # Test suite
└── pyproject.toml     # Project configuration

Adding New Endpoints

  1. Create route in verlihub/api/routes/
  2. Add to router in verlihub/api/__init__.py
  3. Add tests in tests/test_api_endpoints.py
  4. Update API documentation

Adding Dashboard Pages

  1. Create template in verlihub/dashboard/templates/
  2. Add route in verlihub/dashboard/routes.py
  3. Add navigation link in base.html
  4. Add tests in tests/test_dashboard.py

License

GPL-3.0-or-later - See LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

verlihub_py-1.7.0.0.tar.gz (2.2 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

verlihub_py-1.7.0.0-cp313-cp313-manylinux_2_28_x86_64.whl (16.5 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.28+ x86-64

verlihub_py-1.7.0.0-cp312-cp312-manylinux_2_28_x86_64.whl (16.5 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ x86-64

verlihub_py-1.7.0.0-cp311-cp311-manylinux_2_28_x86_64.whl (16.5 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ x86-64

verlihub_py-1.7.0.0-cp310-cp310-manylinux_2_28_x86_64.whl (16.5 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.28+ x86-64

File details

Details for the file verlihub_py-1.7.0.0.tar.gz.

File metadata

  • Download URL: verlihub_py-1.7.0.0.tar.gz
  • Upload date:
  • Size: 2.2 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for verlihub_py-1.7.0.0.tar.gz
Algorithm Hash digest
SHA256 662aa7dccc8db918332999341d01bf27ff96547657ac7645ea23b802c266a2b9
MD5 63daa94083dc0f320e4cdf4f54ff7771
BLAKE2b-256 e0670d40f90aec93081c5520b4556c1de6b0d53781c93d7604fe471bd2d418c7

See more details on using hashes here.

Provenance

The following attestation bundles were made for verlihub_py-1.7.0.0.tar.gz:

Publisher: wheels.yml on transfix/verlihub

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file verlihub_py-1.7.0.0-cp313-cp313-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for verlihub_py-1.7.0.0-cp313-cp313-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 8f3110dcf5b4de288eb07ea0a1897b3361a786c9fb6259a2c54385cdb76502a9
MD5 78b2043c4d5a8574c6858c8923dd71a4
BLAKE2b-256 2e1290990e552d05593da19896f064978f3af4e94dcc256f8b4d6c3ceaec3ee7

See more details on using hashes here.

Provenance

The following attestation bundles were made for verlihub_py-1.7.0.0-cp313-cp313-manylinux_2_28_x86_64.whl:

Publisher: wheels.yml on transfix/verlihub

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file verlihub_py-1.7.0.0-cp312-cp312-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for verlihub_py-1.7.0.0-cp312-cp312-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 d05ae59fdac30873e0a04c806148de2033e80f9d997c7700aa894316d883082a
MD5 0cb76609c625c5798b7a1dea5bce26f5
BLAKE2b-256 c546f519568809c1295e3c6d1331ccd1afd79945fe405c9ce8741994f466588f

See more details on using hashes here.

Provenance

The following attestation bundles were made for verlihub_py-1.7.0.0-cp312-cp312-manylinux_2_28_x86_64.whl:

Publisher: wheels.yml on transfix/verlihub

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file verlihub_py-1.7.0.0-cp311-cp311-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for verlihub_py-1.7.0.0-cp311-cp311-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 16dbb9af2dee97a8d109a76b57ac72ec9c1d1db599c886f038975c5066f531a9
MD5 58b71dfdad3b5432c185252005356d9a
BLAKE2b-256 96715f5dc98c56b52d12faf91535c3f24c520fb70a97a8c98f769f814e2e6570

See more details on using hashes here.

Provenance

The following attestation bundles were made for verlihub_py-1.7.0.0-cp311-cp311-manylinux_2_28_x86_64.whl:

Publisher: wheels.yml on transfix/verlihub

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file verlihub_py-1.7.0.0-cp310-cp310-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for verlihub_py-1.7.0.0-cp310-cp310-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 059ef934ea68ca4a9023a8cb11cf0228518560b65e97652a6b1d2b5bcb45df10
MD5 7ac17cfd3209bf1820e5db224b166751
BLAKE2b-256 680c92eefba5da74691556c571b0b1fdf1ab45157895623027f2824892f1f8c5

See more details on using hashes here.

Provenance

The following attestation bundles were made for verlihub_py-1.7.0.0-cp310-cp310-manylinux_2_28_x86_64.whl:

Publisher: wheels.yml on transfix/verlihub

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page