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

@rippit/sdk

v0.2.1

Published

Rippit SDK for logging conversation data

Readme

@rippit/sdk

The official Node.js SDK for shipping conversation data to Rippit -- the platform for analyzing AI conversation quality, identifying trends, and improving your AI products.

Use this SDK to log every turn of a conversation (both user messages and assistant responses) so Rippit can provide analytics, quality scoring, and insights across your conversations.

Quickstart

npm install @rippit/sdk
export RIPPIT_API_TOKEN="rpt_pat_abc123.xyzSecretTokenValue"
import { configure, storeConversationMoment } from "@rippit/sdk";

// Pass your token here, or set the RIPPIT_API_TOKEN env var instead (see Configuration).
configure({ apiToken: process.env.RIPPIT_API_TOKEN! });

// Log the user's message
storeConversationMoment({
  message: "What's the weather like today?",
  role: "user",
  conversationId: "conv-123",
});

// Log the assistant's response
storeConversationMoment({
  message: "The weather today is sunny with a high of 75F.",
  role: "assistant",
  conversationId: "conv-123",
  attributes: { model: "gpt-4" },
});

That's it. Each call sends the data to Rippit in the background without blocking your application.

Requirements

Configuration

You must provide an API token through one of the two methods below. No other setup is needed -- just provide the token and start calling storeConversationMoment.

Environment variable (recommended for production/CI -- no setup code required):

export RIPPIT_API_TOKEN="rpt_pat_abc123.xyzSecretTokenValue"

When the env var is set, storeConversationMoment picks it up automatically. No call to configure() is needed.

Explicit in code (handy for quick testing):

import { configure } from "@rippit/sdk";

configure({ apiToken: "rpt_pat_abc123.xyzSecretTokenValue" });

configure() takes priority over the environment variable.

If neither method is used, storeConversationMoment prints a warning and returns a resolved Promise -- your application keeps running, but no data is sent.

API Reference

storeConversationMoment

Log a single conversation turn.

import { storeConversationMoment } from "@rippit/sdk";

storeConversationMoment({
  message: "Hello from support",
  role: "user",
  conversationId: "conv-456",
  attributes: {
    userId: "user-789",
    messageId: "msg-001",
    model: "gpt-4",
  },
});

Parameters

storeConversationMoment({ message, role, conversationId, attributes? })

| Parameter | Required | Description | | ---------------- | -------- | ---------------------------------------------------- | | message | Yes | The message content | | role | Yes | One of "user", "assistant", "system", "tool" | | conversationId | Yes | Identifier linking all messages in a conversation | | attributes | No | Optional object with additional fields (see below) |

Returns Promise<void> -- fire-and-forget by default, or await it if you need confirmation.

Attributes

| Attribute | Default | Description | | -------------- | --------------- | ------------------------------------------------- | | appDatasetId | "app_dataset" | Dataset to log to (see Datasets) | | messageId | "" | Unique identifier for this message | | userId | "" | Identifier for the user | | model | "" | Model name (e.g. "gpt-4") | | rawMessage | "" | Full model response payload, if available |

You can also pass any additional properties on the attributes object. These are stored alongside your log data so you can use them to segment, filter, or analyze your conversations however you like.

storeConversationMoments

Send many moments in a single call. The SDK automatically batches them into groups of 10,000 and sends each batch sequentially.

Note: All moments in a single call must target the same dataset. Specify it once via the top-level appDatasetId, or uniformly in each moment's attributes -- do not mix the two approaches.

import { storeConversationMoments } from "@rippit/sdk";

storeConversationMoments({
  moments: [
    { message: "Hello!", role: "user", conversationId: "conv-123" },
    { message: "Hi! How can I help?", role: "assistant", conversationId: "conv-123", attributes: { model: "gpt-4" } },
    // ... up to any number of moments
  ],
  appDatasetId: "support_logs", // optional, defaults to "app_dataset"
});

Parameters

| Parameter | Required | Description | | -------------- | -------- | --------------------------------------------------------------------- | | moments | Yes | Array of moment objects (same shape as storeConversationMoment input) | | appDatasetId | No | Dataset for the entire batch (see resolution rules below) |

Returns Promise<void> -- fire-and-forget by default, or await it if you need confirmation.

Each moment in the moments array accepts the same { message, role, conversationId, attributes? } shape as storeConversationMoment.

appDatasetId

Specify the dataset in one of two ways -- not both:

  1. Top-level (recommended): pass appDatasetId on the options object. All moments in the batch go to that dataset.
  2. Per-moment: set appDatasetId in each moment's attributes. Every moment must specify the same value.

If you mix the two approaches, or if per-moment values disagree with each other, the SDK drops the conflicting moments (or rejects the entire batch) with a warning.

Validation

All moments are validated before any are sent. If any moment has an invalid message, role, conversationId, or reserved field conflict, the entire batch is rejected with a warning citing the failing index.

Concepts

Datasets

The SDK automatically creates and manages datasets in Rippit. On the first call, the SDK calls /sdk/init to ensure the dataset exists, then caches the result for the lifetime of the process. No manual setup needed.

By default, all logs go to a dataset called "app_dataset". If your application has distinct areas you want to analyze separately, pass a different appDatasetId:

storeConversationMoment({ message: "...", role: "user", conversationId: "c-1", attributes: { appDatasetId: "support_logs" } });
storeConversationMoment({ message: "...", role: "user", conversationId: "c-2", attributes: { appDatasetId: "onboarding_logs" } });

The following fields are auto-generated by the SDK and do not need to be provided:

| Field | Description | | ------------- | ---------------------------------------- | | created_at | UTC timestamp when the log was created | | updated_at | UTC timestamp (same as created_at) |

Async behavior

Both storeConversationMoment and storeConversationMoments return a Promise<void>. By default this is fire-and-forget -- your application is never blocked.

If you need to wait for the send to complete (e.g. in a script or test):

await storeConversationMoment({ message: "hi", role: "user", conversationId: "c-1" });
await storeConversationMoments({ moments: [...] });

Logging

On the first successful send, the SDK prints a one-time confirmation to console.log:

[rippit] Rippit is logging your messages

After that it stays silent unless something goes wrong. Validation issues (missing fields, invalid roles, reserved field conflicts) are logged via console.warn. Network-level failures are logged via console.debug.

Error handling

The SDK is designed to never crash your application. All errors -- network failures, timeouts, server errors, missing fields, invalid roles, and reserved field conflicts -- are caught and the returned Promise resolves normally. No exceptions are ever thrown.

Framework compatibility

Zero dependencies + dual ESM/CJS means this SDK works out of the box in:

  • Express / Fastify / Koa / Hono
  • Next.js (API routes, server actions, middleware)
  • NestJS
  • Remix / SvelteKit / Nuxt server-side
  • AWS Lambda / Vercel / Cloudflare Workers
  • Bun and Deno

No special framework adapters needed.

Development Setup

cd sdks/node
npm install

Building

npm run build

Running Tests

npm test

Running the Smoke Test

export RIPPIT_API_TOKEN="rpt_pat_abc123.xyzSecretTokenValue"
npm run build
node examples/smokeTest.ts

Publishing to npm

  1. Update the version in package.json and src/version.ts.

  2. Update CHANGELOG.md with the new version and changes.

  3. Build the package:

npm run build
  1. Publish:
npm publish --access public