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

@reaatech/otel-genai-semconv-utils

v0.1.0

Published

Token counting, cost calculation, and PII redaction utilities for OTel GenAI

Readme

@reaatech/otel-genai-semconv-utils

npm version License: MIT CI

Status: Pre-1.0 — APIs may change in minor versions. Pin to a specific version in production.

Token counting, cost calculation, and PII redaction utilities for LLM observability. Provides accurate token estimation via tiktoken for OpenAI models, character-based estimation for other providers, per-request cost computation with baked-in pricing tables, and automatic detection and redaction of sensitive data (emails, SSNs, credit cards, IP addresses, phone numbers).

Installation

npm install @reaatech/otel-genai-semconv-utils
# or
pnpm add @reaatech/otel-genai-semconv-utils

Feature Overview

  • Provider-aware token counting — tiktoken integration for OpenAI, estimation fallbacks for Anthropic, Vertex AI, and Bedrock
  • Built-in pricing tables — pre-configured pricing for GPT-4, GPT-4o, Claude 3, Gemini, and Bedrock model families
  • Custom pricing overrides — inject per-model pricing at construction time or via setter methods
  • PII redaction — five default patterns (email, SSN, credit card, phone, IP) with add/remove/exclude API
  • Object deep redaction — recursively redact PII from nested objects and arrays
  • LRU caching — token counts and cost calculations are cached with configurable TTL and size limits
  • Singleton accessorsgetDefaultTokenCounter(), getDefaultCostCalculator(), getDefaultPIIRedactor() for zero-config use

Quick Start

import { CostCalculator, TokenCounter, PIIRedactor } from "@reaatech/otel-genai-semconv-utils";

const calculator = new CostCalculator();
const cost = calculator.calculate({
  provider: "openai",
  model: "gpt-4",
  inputTokens: 1000,
  outputTokens: 500,
});
// { total: 0.045, input: 0.03, output: 0.015, currency: "USD" }

const counter = new TokenCounter();
const tokens = counter.countTokens("Hello, world!");
// ~4 (estimated at 4 chars/token)

const redactor = new PIIRedactor();
const safe = redactor.redact("Contact [email protected] or 555-1234");
// "Contact [REDACTED_EMAIL] or [REDACTED_PHONE]"

API Reference

CostCalculator (class)

Constructor

new CostCalculator(options?: { customPricing?: Record<string, PricingInfo> })

Methods

| Method | Description | |--------|-------------| | calculate(params) | Compute cost from provider, model, input/output token counts | | calculateFromUsage(params) | Compute cost from a TokenUsage object | | getPricing(provider, model) | Look up pricing for a specific model (checks custom first, then defaults) | | setCustomPricing(model, pricing) | Override pricing for a single model | | setCustomPricingBatch(pricing) | Override pricing for multiple models | | getAllPricing() | Returns all pricing data (including custom overrides) | | clearCache() | Invalidate the cost calculation cache | | getCacheSize() | Number of cached cost calculations |

CostCalculationParams

| Property | Type | Description | |----------|------|-------------| | provider | ProviderType | Provider: openai, anthropic, vertexai, bedrock | | model | string | Model name/ID | | inputTokens | number | Input/prompt token count | | outputTokens | number | Output/completion token count | | currency | string | Currency code (default: "USD") |

TokenCounter (class)

Constructor

new TokenCounter(options?: {
  provider?: ProviderType;
  customCounter?: ITokenCounter;
  enableCache?: boolean;
  cacheTTL?: number;
  maxCacheSize?: number;
})

Methods

| Method | Description | |--------|-------------| | countTokens(text) | Count tokens in a text string | | countMessageTokens(message) | Count tokens for a single message (role + content) | | countConversationTokens(messages) | Count tokens for an entire conversation | | setCustomCounter(counter) | Replace the token counting implementation | | clearCache() | Invalidate the token count cache | | getCacheSize() | Number of cached token counts |

ITokenCounter (interface)

Implement this to create a custom token counter:

interface ITokenCounter {
  countTokens(text: string): number;
  countMessageTokens(message: { role: string; content: string }): number;
  countConversationTokens(messages: Array<{ role: string; content: string }>): number;
}

EstimationTokenCounter (class)

A character-based token estimator using ~4 characters per token (English text). Used as the fallback when no provider-specific counter is configured.

PIIRedactor (class)

Constructor

new PIIRedactor(options?: PIIRedactionOptions)

PIIRedactionOptions

| Property | Type | Default | Description | |----------|------|---------|-------------| | enabled | boolean | true | Enable/disable redaction | | redactMessageContent | boolean | false | Whether to redact message content | | hashInsteadOfRedact | boolean | false | Hash values instead of replacing with [REDACTED_*] | | customPatterns | PIIPattern[] | — | Additional regex patterns to detect | | excludePatterns | string[] | — | Pattern descriptions to skip |

Methods

| Method | Description | |--------|-------------| | redact(text) | Redact PII from a string | | redactObject(obj) | Deep redact PII from an object | | containsPII(text) | Check if text contains any PII | | detectPIITypes(text) | List which PII types were detected | | addPattern(pattern) | Add a custom detection pattern | | removePattern(description) | Remove a pattern by description | | excludePattern(description) | Exclude a pattern (skip during redaction) | | includePattern(description) | Re-include a previously excluded pattern |

Default PII Patterns

| Pattern | Replacement | Description | |---------|-------------|-------------| | Email addresses | [REDACTED_EMAIL] | [email protected] | | SSN | [REDACTED_SSN] | 123-45-6789 | | Credit cards | [REDACTED_CC] | 13–19 digit numbers | | Phone numbers | [REDACTED_PHONE] | 10+ digit sequences | | IP addresses | [REDACTED_IP] | IPv4 addresses |

Usage Patterns

Custom Pricing Overrides

const calculator = new CostCalculator({
  customPricing: {
    "gpt-4": { input: 0.03, output: 0.06 },
    "my-custom-model": { input: 0.001, output: 0.002, provider: "openai" },
  },
});

Provider-Specific Token Counters

import { OpenAITokenCounter } from "@reaatech/otel-genai-semconv-openai";
import { TokenCounter } from "@reaatech/otel-genai-semconv-utils";

const counter = new TokenCounter({
  customCounter: new OpenAITokenCounter(),
});
const tokens = counter.countTokens("Hello, world!");

Selective PII Redaction

const redactor = new PIIRedactor({ excludePatterns: ["Email addresses"] });
redactor.redact("[email protected] called 555-1234");
// "[email protected] called [REDACTED_PHONE]"

Related Packages

License

MIT