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

@cockpitify/node

v0.1.3

Published

Records each user's AI token usage and cost to your own Supabase project (Cockpitify).

Readme

@cockpitify/node

Records each user's AI token usage to ops.usage in your own Supabase project. Wrap your AI client once per request; the wrapped client behaves exactly like the original.

import OpenAI from 'npm:openai';
import { Ops } from 'npm:@cockpitify/node';

const ai = Ops.wrap(new OpenAI({ baseURL: 'https://api.deepseek.com', apiKey }), {
  userId: user.id,
  supabase, // service-role client; writes to ops.usage
});

Using an AI coding assistant? Point it at AI.md (also in node_modules/@cockpitify/node/AI.md).

Supported clients

  • OpenAI SDK and compatibles (DeepSeek, Groq, OpenRouter via baseURL)
    • chat.completions.create (streaming or not)
    • chat.completions.stream()
    • responses.create
  • Anthropic SDK
    • messages.create (streaming or not)
    • messages.stream()
    • the same two under beta.messages
  • Raw HTTP: Ops.wrapFetch(fetch, opts). Handles OpenAI-compatible chat, Responses and Anthropic, both JSON and SSE.
  • Vercel AI SDK: wrapLanguageModel({ model, middleware: Ops.middleware(opts) }).

Calls not measured in tokens

Speech-to-text, text-to-speech or image calls are recorded by hand (ops 0.17.0+):

Ops.record({ userId, supabase, provider: 'groq', model: 'whisper-large-v3', units: 742, unit: 'seconds' });
Ops.record({ userId, supabase, provider: 'elevenlabs', model: 'eleven_multilingual_v2', units: 48000, unit: 'characters', costUsd: 0.36 });

Without costUsd the row stays unpriced: ops shows the amount, not a guessed cost.

Streaming

Streaming is fully supported, and chunks reach your code unchanged and without delay.

  • OpenAI-compatible streams only report usage when stream_options.include_usage is set, so it is added for you.
    • The extra usage-only chunk it produces is hidden from your code, unless you asked for it yourself.
    • Groq is the exception: it reports usage on its own, so its requests are left untouched.
  • If a stream is cut (user left, break, abort, network error), there is no usage report from the provider. Tokens are then estimated from the prompt and the text seen so far, and the row is stored with estimated = true.

Guarantees

  • Fail-open. A recording failure never throws into your code or slows the AI call. It goes to onError, which by default logs one warning.
  • Writes outlive the response. On Supabase Edge Functions, writes run through EdgeRuntime.waitUntil. Elsewhere, call await Ops.flush() before the process exits.
  • Setup mistakes fail loudly. A missing userId, or neither supabase nor sink given, throws at wrap time.

Options

| Option | | |---|---| | userId | Required. The end user to attribute usage to. | | supabase / sink | Where rows go: ops.usage through a supabase-js client, or your own (row) => Promise. | | feature | Optional tag, e.g. 'chat', 'transcribe'. | | prices | USD per 1M tokens per model (prefix match). Without it cost_usd is null and the database prices the row. | | provider | Overrides the provider inferred from baseURL / URL. | | injectStreamUsage | Set false to never touch stream_options. | | onError | Receives recording errors. |