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

@deskbell/sdk

v0.3.0

Published

Typed client for the Deskbell public API: streamed answers, conversations, feedback.

Readme

@deskbell/sdk

The typed client for the public API of a Deskbell server: streamed answers, conversation history and feedback. The Deskbell widget runs on it, so a UI of your own gets the same streaming, history and feedback behaviour.

No runtime dependencies. Works wherever fetch and ReadableStream exist: browsers, Node 18 or later, edge runtimes. MIT licensed.

Install

npm install @deskbell/sdk

Create a client

import { DeskbellClient } from "@deskbell/sdk";

const client = new DeskbellClient({
  baseUrl: "https://your-deskbell.example.com",
  projectKey: "pk_live_...",
  sessionId: () => getOrCreateVisitorId(),
});

baseUrl is the origin of your Deskbell server; leave it out when the page is served from the same origin. sessionId identifies the visitor, and possession of a session is what authorises reading and rating its conversations, so keep it per visitor and persist it. Pass a function to create it lazily on first use.

The project key is visible in page source and is not a secret. The server answers requests from the origins on the project's allowlist.

Ask a question

let answer = "";
for await (const event of client.ask({ message: "How do I install the widget?" })) {
  if (event.type === "token") answer += event.value;
  else if (event.type === "citations") render(event.citations);
  else if (event.type === "refusal") answer = "No grounded answer.";
  else if (event.type === "done") remember(event.conversationId, event.messageId);
}

Pass conversationId to continue a thread. The done event carries the ids for both. Pass an AbortSignal as client.ask(input, { signal }) to cancel. The full event list, including clarify and verification, is in the API reference.

History and feedback

const recent = await client.conversations.list();
const messages = await client.conversations.messages(recent[0].id);

await client.feedback({ messageId, feedback: "down", reason: "incorrect" });
await client.feedback({ messageId, feedback: null }); // clears the vote

Errors

Any non-2xx response throws a DeskbellError with the HTTP status and, when the server sent one, retryAfter in seconds. The client never retries.

import { DeskbellError } from "@deskbell/sdk";

try {
  for await (const event of client.ask({ message })) { /* ... */ }
} catch (error) {
  if (error instanceof DeskbellError && error.status === 429) {
    wait(error.retryAfter ?? 10);
  }
}

A 429 is a rate limit or the project's daily token budget, a 403 an origin not on the allowlist, a 404 an unknown project key.

What it does not do

No retries, no caching, no session management beyond holding the id you gave it, no React bindings. It exposes only the endpoints the server answers today.

Links