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

@doweit/voice

v0.1.9

Published

Capability-first voice AI SDK. Register your JS functions, and Gemini Live calls them when users speak or type.

Readme

@doweit/voice

Capability-first voice AI SDK for the web. Expose your JavaScript functions, and Gemini Live decides when and how to call them based on what your users say or type.

Install

npm install @doweit/voice

Requires React 18+ (or 19). The SDK ships React components, so it is meant for React / Next.js apps.

Quick start (React / Next.js)

import { DoweitClient, DoweitWidget } from "@doweit/voice";

// 1. Create a client with your publishable key (from the Doweit dashboard).
const client = new DoweitClient({
    publicKey: "dw_pub_...",
});

// 2. Tell the AI what your app can do.
client.register({
    addToCart: {
        description: "Add an item to the shopping cart.",
        params: { itemId: { required: true }, qty: { required: true } },
        handler: async ({ itemId, qty }) => {
            await fetch(`/api/cart`, { method: "POST", body: JSON.stringify({ itemId, qty }) });
            return { status: "ok" };
        },
    },
});

// 3. Drop the widget in. It initializes itself — no useEffect, no loading flag.
export default function App() {
    return <DoweitWidget client={client} />;
}

That's it. The chat bubble appears in the bottom-right corner. <DoweitWidget> calls client.init() for you on mount, shows a "Connecting…" state while it loads, and shows a clear error inside the panel if something goes wrong.

Next.js note: the widget is a client component. Put "use client"; at the top of the file that renders it (or render it from a client component).

Core concepts

  • Capability-first: you describe what your app can do (register), and the AI decides which capability matches the user's intent. No predefined intents, no string matching.
  • Hosted backend: the SDK talks only to the Doweit backend — no setup, no URL to configure. Your publishable key is safe to ship in the browser; it never touches Google directly.
  • Manifest sync: on init, the SDK ships a snapshot of your registered actions to the Doweit dashboard so you can inspect and version them.
  • Live state: use client.bindState(() => ({ cart, page })) so the AI always sees the current UI without you injecting prompts.

Before it works: allow your domain

The SDK runs in your users' browsers and calls the Doweit backend cross-origin. For that to be permitted:

  1. Open your app in the Doweit dashboard.
  2. Add the domain(s) where you embed the widget to the domain whitelist (e.g. app.yoursite.com).
  3. localhost is always allowed, so local development works with no setup.

If your domain is not whitelisted, the widget shows "Assistant unavailable" and the browser console logs a domain/CORS error.

API

new DoweitClient(config)

  • publicKey (required): your project's publishable key (dw_pub_...).
  • baseUrl (optional): override the Doweit backend URL. Defaults to the Doweit hosted backend — you normally do not set this.
  • language (optional): ISO code, e.g. "en".

client.register(actions)

Register one or more capabilities:

client.register({
    bookTable: {
        description: "Reserve a table.",
        params: { guests: { type: "number", required: true }, time: { required: true } },
        scope: "global",          // or a route prefix like "/restaurant"
        dangerous: false,         // if true, prompts the user for confirmation
        handler: async (args) => { /* ... */ },
    },
});

client.bindState(getter)

Reactively expose current UI state to the AI:

client.bindState(() => ({ cart: getCart(), currentPage: location.pathname }));

client.setUser({ userId, email })

Identify the end-user so memory persists across sessions.

client.use((action, next) => ...)

Middleware for validation, logging, or blocking dangerous calls.

client.enableNavigation(router)

Auto-registers a navigate action wired to your router (Next.js, React Router, etc.).

<DoweitWidget client={client} />

Drop-in chat bubble UI with voice + text. It initializes the client itself. Or use the useDoweitVoice(client) hook to build your own UI.

client.init()

Optional — the widget calls this for you. Call it manually only if you want to initialize before the widget mounts. It is idempotent and safe to call multiple times.

License

MIT © Doweit