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

@assistiv/sdk

v0.2.0

Published

Official JavaScript SDK for the Assistiv AI Gateway. Inference, end-user management, billing, MCP, webhooks — one client.

Readme

@assistiv/sdk

Official TypeScript / JavaScript SDK for the Assistiv AI Gateway. One client, OpenAI-compatible, with per-user wallets, budgets, rate limits, tool calls, and webhooks built in.

npm install @assistiv/sdk
import { Assistiv } from "@assistiv/sdk";

const platform = new Assistiv({ apiKey: process.env.ASSISTIV_PLATFORM_KEY! });

// Provision one of your end-users (idempotent).
const { endUserId, apiKey } = await platform.bootstrap({
  platformId: process.env.ASSISTIV_PLATFORM_ID!,
  externalId: "user_42",
  defaultBudget: { max_usd: 5, period: "monthly" },
});

// Use the returned sk-eu_* key to run inference for that user.
const assistiv = new Assistiv({ apiKey });
const reply = await assistiv.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [{ role: "user", content: "Say hi" }],
});
console.log(reply.choices[0].message.content);

What this gives you in three sentences: every popular LLM (OpenAI, Anthropic, Google, xAI) behind one endpoint that speaks the OpenAI schema; per-end-user spend caps, rate limits, and audit logs without building any of that yourself; and an MCP-compatible tool layer so agents can hit GitHub / Slack / Zoho / Zendesk through the same key.

For AI agents reading this file — this README is the canonical integration doc. Hit https://www.assistiv.ai/llms-sdk.txt for the machine-friendly feed if you want every per-feature snippet in one blob. The patterns below are sufficient for adding Assistiv to any product.


Auth model

Assistiv has two key types. Use the right one for the call:

| Key prefix | Lives where | What it can do | |----------------|-----------------------|-------------------------------------------------------------------------------------------------| | sk-plat_* | Your server only | Provision end-users, mint per-user keys, manage budgets, read logs, register MCP configs. | | sk-eu_* | Server OR browser | Run inference (chat, responses, models), call tools, read own budget / rate-limit / logs. |

// Server (Node 18+ / Bun / Deno / serverless)
import { Assistiv } from "@assistiv/sdk";
const platform = new Assistiv({ apiKey: process.env.ASSISTIV_PLATFORM_KEY! });

// Browser / mobile / Electron
import { Assistiv } from "@assistiv/sdk/browser";
const assistiv = new Assistiv({ apiKey: endUserKey }); // sk-eu_* only

The browser entry refuses any sk-plat_* key at construction time. Never ship a platform key to a client.


Provisioning end-users — bootstrap()

Most platforms do one operation when a new user signs up: create the end-user record, mint their key, seed a budget, optionally set a rate limit. bootstrap() is the one-call version of that flow.

const { endUserId, apiKey, budget, rateLimit } = await platform.bootstrap({
  platformId: process.env.ASSISTIV_PLATFORM_ID!,
  externalId: "user_42",                            // your stable user id
  displayName: "Jane Smith",                        // optional
  metadata: { plan: "pro" },                        // optional, opaque JSON

  defaultBudget: { max_usd: 5, period: "monthly" }, // optional
  defaultRateLimit: { rpm_limit: 60, tpm_limit: 50_000 }, // optional
});

// Persist `apiKey` immediately — the raw key is shown ONCE.
// Recommended: store alongside your user row, encrypted at rest.
await db.users.update(user.id, { assistiv_key: apiKey, assistiv_end_user_id: endUserId });

Idempotent on externalId — repeat calls with the same id return the existing user and mint a fresh key. This is for retry safety, not key retrieval. Store the key once and reuse it.


Inference

OpenAI-compatible. Anything openai.chat.completions.create accepts works here, with the same response shape.

Non-streaming

const reply = await assistiv.chat.completions.create({
  model: "gpt-4o-mini",            // or claude-sonnet-4-6, gemini-2.0-flash, grok-2, …
  messages: [
    { role: "system", content: "You are a helpful assistant." },
    { role: "user", content: "Plan a 3-day trip to Tokyo." },
  ],
  temperature: 0.7,
  max_tokens: 800,
});

Streaming

const stream = await assistiv.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [{ role: "user", content: "Count to 10, one number per line." }],
  stream: true,
});
for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}

Tool calling

const reply = await assistiv.chat.completions.create({
  model: "gpt-4o-mini",
  messages,
  tools: [{
    type: "function",
    function: {
      name: "get_weather",
      description: "Get the current weather in a city.",
      parameters: { type: "object", properties: { city: { type: "string" } } },
    },
  }],
});

Responses API (stateful alt)

const res = await assistiv.responses.create({
  model: "gpt-4o-mini",
  input: "Plan a trip",
});

Listing available models

const { data: models } = await assistiv.models.list();
// Only models your platform has configured providers for.

Engine-native escape hatch

Anything OpenAI's npm client supports, you can do too:

const openai = Assistiv.openai(assistiv);
const parsed = await openai.beta.chat.completions.parse({ /* ... */ });

Per-end-user state

From the platform side (sk-plat_*)

// Budgets — per-user spend caps with idempotent topups
await platform.budgets(platformId).create(endUserId, {
  max_usd: 10,
  period: "monthly",
  auto_replenish: true,
  replenish_amount: 10,
  low_balance_threshold: 1,
});

await platform.budgets(platformId).topup(
  endUserId,
  { amount_usd: 5, reason: "promo_grant" },
  { idempotencyKey: "promo-2026-q2" }, // safe to retry the same call
);

// Per-user rate-limit overrides (higher than platform default)
await platform.rateLimits(platformId).setForEndUser(endUserId, {
  rpm_limit: 600,
  tpm_limit: 250_000,
});

// Logs — what did this user do
const logs = await platform.logs(platformId).search({
  end_user_id: endUserId,
  since: new Date(Date.now() - 86_400_000).toISOString(),
});

From the end-user side (sk-eu_* — used by your app frontend)

const me = await assistiv.me.budget();           // { max_usd, used_usd, remaining_usd, period }
const limits = await assistiv.me.rateLimits();   // current effective limits
const ledger = await assistiv.me.budgetTransactions({ limit: 100 });
const myLogs = await assistiv.me.logs();

MCP tools (GitHub, Slack, Zoho, Zendesk, …)

Two-step model: you activate an app for your platform in the dashboard (OAuth secret never leaves the Assistiv UI), then your end-users connect their own account via OAuth from your product.

// Read which apps your platform has activated — to render
// "Connect GitHub" / "Connect Slack" UI in your product.
const { data: apps } = await platform.mcp(platformId).listApps();

// For your end-users at runtime: the agent connects directly to
// the MCP protocol endpoint with their sk-eu_* key.
//   POST https://mcp.assistiv.ai/mcp
//   Authorization: Bearer sk-eu_...
//   { "jsonrpc": "2.0", "id": 1, "method": "tools/list" }

Activating, editing, and rotating OAuth credentials for an MCP app is a dashboard task — there is no SDK or REST API for it (write-once secrets should not round-trip through your code).


Webhooks

Assistiv pushes real-time events when budgets and wallets change. Six event types you can subscribe to:

  • budget.topped_up — credit added to an end-user's budget
  • budget.debited — any debit (inference call, manual debit, etc.)
  • budget.low_balance — crossed your low-balance threshold
  • budget.suspended — explicit suspension
  • budget.unsuspended — reactivated
  • wallet.low_balance — platform-wallet warning

Register endpoint URLs in Dashboard → Outbound Webhooks and copy the signing secret into your server. Verify every payload:

import express from "express";
import { verifyWebhook } from "@assistiv/sdk";

const app = express();

app.post(
  "/assistiv-events",
  express.raw({ type: "application/json" }),
  (req, res) => {
    const ok = verifyWebhook(
      req.body,
      req.headers,
      process.env.ASSISTIV_WEBHOOK_SECRET!,
    );
    if (!ok) return res.status(400).end();

    const event = JSON.parse(req.body.toString());
    switch (event.event_type) {
      case "budget.low_balance":
        // notify the user, top up, or pause
        break;
      case "wallet.low_balance":
        // top up the platform wallet
        break;
    }
    res.status(200).end();
  },
);

Failed deliveries retry automatically. Use the Svix portal in the dashboard to inspect or replay any event.


Errors

The SDK throws a small typed hierarchy. Catch specifically — never just catch (e) without inspecting.

import {
  AssistivAuthError,            // 401 — bad / missing key
  AssistivPaymentRequiredError, // 402 — wallet OR budget exhausted
  AssistivForbiddenError,       // 403 — key-type or scope violation
  AssistivNotFoundError,        // 404 — resource missing
  AssistivConflictError,        // 409 — idempotency clash
  AssistivRateLimitError,       // 429 — has `.retryAfter` seconds
  AssistivServerError,          // 5xx — Assistiv-side
  AssistivError,                // base class for everything above
} from "@assistiv/sdk";

402 branching — what's actually wrong

On a 402 from chat.completions.create, branch on error.code:

try {
  await assistiv.chat.completions.create({ /* … */ });
} catch (e) {
  if (e instanceof AssistivPaymentRequiredError) {
    switch (e.code) {
      case "wallet_insufficient":
        // The platform wallet is empty. Surface to platform admin;
        // top up the wallet in the Assistiv dashboard.
        break;
      case "budget_exhausted":
        // This end-user's per-user budget is empty.
        // Top up with platform.budgets(pid).topup(...).
        break;
      case "budget_suspended":
        // is_suspended=true on this user. Unsuspend manually.
        break;
    }
  }
}

Rate-limit handling

try {
  await assistiv.chat.completions.create({ /* … */ });
} catch (e) {
  if (e instanceof AssistivRateLimitError) {
    await new Promise((r) => setTimeout(r, (e.retryAfter ?? 1) * 1000));
    // retry…
  }
}

Every error carries .status, .code, .message, and .requestId so you can report incidents back to Assistiv with one click.


What this SDK does NOT do

Everything below is dashboard-only (Supabase auth, not an API key) and is intentionally absent from the SDK. The dashboard URL points to the right form:

| Operation | Where | |----------------------------------------|--------------------------------------------------| | Top up the platform wallet (Stripe) | assistiv.ai/dashboard/settings | | Add OpenAI / Anthropic / Google keys | assistiv.ai/dashboard/llm-configs | | Register outbound webhook endpoints | assistiv.ai/dashboard/outbound-webhooks | | Invite teammates | assistiv.ai/dashboard/team | | Activate an MCP app (OAuth secrets) | assistiv.ai/dashboard/mcp | | Upload a private skill | assistiv.ai/dashboard/skills | | Provision a new platform | Email [email protected] (not self-serve) |

These are write-once secret operations or one-time setup steps. Putting them in the SDK would mean those secrets round-tripping through your code, which adds an unnecessary handling surface.


Versions

  • SDK semver: strict semver from 1.0.0 onward. Pre-1.0 minor bumps may include breaking changes; check the CHANGELOG.
  • API version: v0.1.0 (the URL prefix /v1 is stable; the underlying schema version ships in X-Assistiv-Api-Version).
  • Provenance: each npm release ships a Sigstore SLSA v1 attestation linked to its source commit. npm install --foreground-scripts @assistiv/sdk shows the verification badge.

References

  • Docs site: https://www.assistiv.ai/docs
  • Per-feature feed for AI agents:
    • https://www.assistiv.ai/llms-sdk.txt — SDK-flavoured (this surface)
    • https://www.assistiv.ai/llms-api.txt — raw HTTP / curl flavoured
    • https://www.assistiv.ai/llms-full.txt — everything
  • API status: https://status.assistiv.ai
  • Support: [email protected]

License

MIT — see LICENSE.