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

@acetrumtech/rag-chatbot-pro

v0.1.1

Published

Pro RAG chatbot plugin — DOCX/TXT/MD/CSV + website crawl, client dashboard, citations, semantic cache. Requires a paid license key (acetrum.com) to function; degrades to a free-tier subset without one.

Readme

@acetrumtech/rag-chatbot-pro

Pro version of rag-chatbot-plugin — imports/extends the free package, gated by a license check against our own license-server.

Published to public npm as @acetrumtech/rag-chatbot-pro — publicly installable, but proprietary (see LICENSE.md) and non-functional without a valid, paid license key. npm run publish:pro builds + obfuscates + publishes in one step.

What's here (Step 3 — skeleton)

  • src/license.js — the license-check module: 24h local cache, live POST /verify against the license server, HMAC signature + freshness verification, 7-day grace period if the server is unreachable. Never throws — an invalid/unreachable license degrades to free mode, never crashes the client's site.
  • src/hmac.js — same signing scheme as license-server/app/src/hmac.js, so a server response can be independently re-verified here.
  • src/config.jsloadProConfig(): wraps the free package's loadConfig(), adds a pro config section, runs the license check, and sets cfg.pro.isPro.
  • src/index.js — re-exports the entire free package's API + the pro pieces above.

No pro-only features/routes exist yet — those land in later roadmap phases (Client Dashboard is next, Phase 1). This step is purely the license-gating foundation everything else will check against.

Config

In chatbot.config.js (or via env vars):

export default {
  // ...all the usual free config...
  pro: {
    licenseKey: 'XYZC-XXXXXXXXXXXX',       // the only thing a client actually types in
    // domain: NOT set here — auto-detected from the first request's Host
    // header (as `https://<host>/`), see note below. Only set this explicitly
    // for an unusual case (e.g. running behind a domain the Host header won't
    // reflect correctly, like some proxy setups).
    // licenseServerUrl is NOT set here either — see note below.
    // Step 9 — semantic cache. Off by default. Answers repeated/near-duplicate
    // visitor questions from a cache instead of a fresh RAG search + LLM call —
    // see src/semantic-cache.js for the full design notes (threshold tradeoffs,
    // the "matches on latest question text only" scoping decision, and the
    // enquiry-bypass heuristic that keeps it from swallowing real leads).
    semanticCache: {
      enabled: true,
      threshold: 0.93,   // cosine similarity cutoff — raise for stricter matching, lower for more hits
      maxEntries: 500,   // oldest entries pruned once exceeded
      ttlHours: 168       // 7 days; entries older than this are treated as a miss
    }
  }
};

A client only ever needs to set licenseKey. Everything else about licensing is either infrastructure we own or something the plugin figures out itself:

  • licenseServerUrl is a build-time constant, not client config. It's our infrastructure, the same for every client. build.js inlines it (alongside LICENSE_HMAC_SECRET) as a build-time constant via esbuild's define — a distributed/obfuscated install never needs LICENSE_SERVER_URL set anywhere, and a client's .env never sees our VPS address. (Still overridable per-install via pro.licenseServerUrl in chatbot.config.js if we ever need to point one specific install at a different server.)
  • domain is auto-detected, not typed in. loadProConfig() leaves it unresolved at startup if not explicitly set; handler.ts derives it from the first real request's Host header (as https://<host>/) and runs the actual /verify check then, on whichever request arrives first — same fire-once, memoized-in-flight pattern already used for the RAG index build. This is why the license check log line (license OK (valid) — domain: ...) shows up after the first request hits the server, not at cold start. Still overridable via pro.domain/LICENSE_DOMAIN for the rare case where auto-detection isn't right (e.g. behind a proxy that rewrites Host). Caveat: the license server does a literal string match on domain, not a normalized one — a license created via the admin dashboard with a different string format (bare clientsite.com instead of https://clientsite.com/) won't match auto-detection's reconstructed format. Create licenses with the https://domain/ format to match what auto-detection actually sends.

LICENSE_SERVER_URL/LICENSE_HMAC_SECRET env var equivalents exist only for source/lib/ dev (see Local dev below) — there are no env var equivalents for licenseKey/domain at all; both are code-level (a config prop / request Host header), never env. Semantic cache env equivalents: SEMANTIC_CACHE_ENABLED (true/false), SEMANTIC_CACHE_THRESHOLD, SEMANTIC_CACHE_MAX_ENTRIES, SEMANTIC_CACHE_TTL_HOURS.

The Client Dashboard's /admin page shows a "Cache hits (saved AI calls)" stat once enabled. Cache is automatically cleared on POST /reindex (new/changed docs could make old cached answers stale).

Dashboard URL note: /admin is relative to your configured server.basePath (default /api/chatbot), so the actual URL is <your-api-url>/admin — e.g. https://yoursite.com/api/chatbot/admin, not bare /admin. All of the dashboard's own internal nav/links account for this automatically now (fixed 2026-08-06 — they used to be hardcoded to bare /admin/..., which 404'd on every real (non-root-basePath) deployment the moment you clicked anything inside the dashboard, even though the dashboard's own landing page loaded fine at its correct URL).

Usage

import { loadProConfig, createProCoreHandler } from '@acetrumtech/rag-chatbot-pro';

const cfg = await loadProConfig();
console.log(cfg.pro.isPro ? `Pro (${cfg.pro.plan})` : 'Free mode');

const handle = createProCoreHandler(cfg);

TypeScript

Source is TypeScript (src/**/*.ts), compiled by tsc to lib/ (type-checked, with .d.ts output — this is what main/exports in package.json point at, and what devtest//test/ run against). npm run build runs tsc then a small postbuild step (strips a synthetic export {} from the compiled widget so it stays valid as a classic <script> tag — see src/widget/widget.ts's comment).

The distributable tarball (what actually ships to paying clients) is a separate, further step: npm run bundle (build.js, esbuild) minifies + obfuscates lib/ into dist/, inlining LICENSE_HMAC_SECRET and LICENSE_SERVER_URL at build time. npm run pack:pro runs both (buildbundlenpm pack).

npm run build      # tsc -> lib/ (compile + type-check)
npm run watch       # tsc --watch, for local dev — restart devtest/run.js to pick up changes
npm run bundle      # lib/ -> dist/ (obfuscated tarball build, needs LICENSE_HMAC_SECRET + LICENSE_SERVER_URL)

Local dev / testing against the real license-server

cp .env.example .env   # fill in LICENSE_HMAC_SECRET (must match license-server's .env) + LICENSE_SERVER_URL
npm install
npm test              # builds (tsc) then exercises all license branches against localhost:4000
npm run test:cache    # builds then runs the semantic-cache unit tests (no live API needed)

Requires license-server running locally (docker compose up -d in that repo) with at least one test license created via its /admin dashboard.