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

chatsee-sdk

v2.2.0

Published

Production-grade tracker for LLM conversations, tool calls, errors, PII redaction, and closed-loop remediation for the Chatsee platform

Readme

Chatsee SDK (JavaScript / TypeScript)

Production-grade tracker for LLM conversations, tool calls, errors, local PII redaction, and closed-loop remediation for the Chatsee platform.

Feature parity with the Python chatsee-ai SDK.

Installation

npm install chatsee-sdk
# Optional — only needed for closed-loop remediation (MCP) calls:
npm install @modelcontextprotocol/sdk

Environments

Select the environment by setting api_base_url to an alias or a full URL.

| Alias | URL | |-------|-----| | dev | https://dev.chatsee.ai/api | | qa | https://qa.chatsee.ai/api | | demo | https://gcp-demo.chatsee.ai/api | | poc | https://app.chatsee.ai/api |

Defaults to qa. Any full URL is also accepted (e.g. https://my-host.com/api).

Usage (tracking)

import { ChatseeTracker } from 'chatsee-sdk';

const tracker = new ChatseeTracker({
  agent_id: '<agent_id>',
  tenant_id: '<tenant_id>',      // 24-char hex ObjectId
  user_id: 'user-42',            // optional, but see "Identifying the user"
  api_base_url: 'dev',           // or "qa" / "demo" / "poc"
  redaction_enabled: true,       // optional: locally redact before sending
});

tracker.startTurn('My email is [email protected]', { any: 'metadata' });
tracker.logToolCall('search', { query: 'weather' }, { temp: 21 });
await tracker.endTurn('It is 21°C.');

// Signal the last turn of a conversation (flushed immediately downstream):
await tracker.endTurn('Goodbye!', /* isFinalTurn */ true);

All network methods (endTurn, sendBatch, redact, and the remediation calls) are async and return Promises.

Identifying the user

user_id is optional. Without it the backend stamps an anonymous, per-session identifier, which is fine for volume but cannot tell you that the same person came back tomorrow or failed the same tool three times. Pass a real id and the Chatsee UI can filter traces down to one user.

One tracker serving many users can override it per turn instead:

tracker.startTurn('Where is my order?', {}, undefined, 'user-99');

Precedence is turn-level, then the tracker default, then metadata.user_id.

Durations

Turn duration is measured automatically: the clock starts at startTurn and the elapsed milliseconds ship with endTurn as duration_ms.

Tool calls are only timed if you ask. Wrap the call and the SDK measures it, logging failures (and re-throwing) as well as successes:

const weather = await tracker.trackToolCall('search', { query: 'weather' },
  () => lookupWeather('weather'));

Or pass a duration you measured yourself:

tracker.logToolCall('search', { query: 'weather' }, result, undefined, 143);

An untimed tool call simply omits duration_ms — it is never reported as zero, so a missing measurement is never mistaken for an instant one.

Token usage

The SDK never sees your model calls, so it cannot count tokens for you — hand it the usage object the provider already returned, once per call:

const resp = await client.chat.completions.create({ model, messages });
tracker.logModelCall({ model, provider: 'openai', usage: resp.usage });

Field names are mapped for you, so the object goes in as it comes out: resp.usage for OpenAI and Anthropic, resp.usage_metadata for Gemini. Pass the numbers directly instead if you already have them:

tracker.logModelCall({ model, prompt_tokens: 1180, completion_tokens: 240 });

Log every call the turn made — a retry, a router call, a summarizer — and ChatSee reports the turn's total from the sum. It also reports how many of those calls reported usage at all, which is what stops an unmeasured turn being read as a cheap one: a turn where nothing reported is shown as unavailable, not as zero tokens. cost_usd is accepted but never inferred; omit it unless the provider priced the call.

Batch

await tracker.sendBatch([
  { user_message: 'hi', bot_message: 'hello' },
  { user_message: 'bye', bot_message: 'goodbye', system_prompt: '...' },
]);

Usage (redaction)

Module-level helper (does not send anything to Chatsee):

import { redact } from 'chatsee-sdk';

const clean = await redact(
  { message: 'Card 4111 1111 1111 1111', email: '[email protected]' },
  { api_base_url: 'qa', fields_to_redact: '*', verify_ssl: false }
);

Tracker instance:

const clean = await tracker.redact({ user_message: 'call 9876543210' }, ['user_message']);

Closed-loop remediation (MCP)

Requires @modelcontextprotocol/sdk and MCP credentials.

const tracker = new ChatseeTracker({
  agent_id: '<agent_id>',
  tenant_id: '<tenant_id>',
  api_base_url: 'dev',
  mcp_server_url: 'https://<host>/mcp/',
  mcp_api_key: '<mcp_api_key>',
});

const pending = await tracker.fetchRemediations('pending');
// ... inject pending.skills_markdown into your system prompt ...
await tracker.acknowledgeRemediations(pending.failure_memory_ids as string[], 'injected');

Available: fetchRemediations, acknowledgeRemediations, rejectRemediations, getRemediationStatus.

Tenant encryption (optional)

EncryptDecryptUtil provides per-tenant Fernet encryption, interoperable with the Chatsee backend's crypto_utils.py (same master key + tenant id). It is a no-op unless a master key is set via the masterKeyB64 argument or the CHATSEE_CRYPTO_SECRET_KEY / CRYPTO_SECRET_KEY env var.

import { EncryptDecryptUtil } from 'chatsee-sdk';

const token = EncryptDecryptUtil.encryptJson('<tenant_id>', { pan: 'ABCDE1234F' });
const back = EncryptDecryptUtil.decryptJson('<tenant_id>', token);

Keys are derived with PBKDF2-HMAC-SHA256(master, salt=tenant_id, 100k iters), so each tenant gets a distinct key from a shared master secret.

Configuration

| Option | Type | Default | Description | |--------|------|---------|-------------| | agent_id | string | (required) | Agent identifier. | | tenant_id | string | (required) | Tenant identifier (24-char hex ObjectId). | | session_id | string | auto | Conversation session ID. Assigned by the API if omitted. | | user_id | string | anon | End-user identifier. Anonymous per-session id if omitted. | | timeout | number | 10 | HTTP timeout in seconds. | | verify_ssl | boolean | false | Verify SSL certificates. | | api_base_url | string | "qa" | Environment alias or full URL. | | mcp_server_url | string | — | chatsee-mcp Streamable HTTP endpoint. | | mcp_api_key | string | — | Bearer token for the MCP server. | | redaction_enabled | boolean | false | Locally redact tracked turns before sending. | | redaction_fields_to_redact | Set/Array/"*" | {user_message, bot_message, interactions} | Fields to redact. | | redaction_cache_ttl_seconds | number | 300 | Classifier cache TTL. | | redaction_timeout_seconds | number | 5.0 | Classifier fetch timeout. | | redaction_classifiers_url | string | — | Override the classifiers endpoint. |

Notes

  • No API key is required for tracking (parity with the Python SDK).
  • The SDK sets Node's insecureHTTPParser on its HTTP client so it can read the Chatsee gateways' multi-line CSP response header, which Node's strict parser otherwise rejects.

License

MIT