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

logique-ai-monitor

v0.2.0

Published

Node/TypeScript SDK for AI Usage Monitor

Readme

logique-ai-monitor — Node/TypeScript SDK

Lightweight, non-blocking SDK for reporting AI usage events to the AI Usage Monitor ingestion API.

Emits AUM Event Contract v1 — the same event format as the Laravel SDK (logique/ai-usage-monitor-sdk): buffered, batched, async/non-blocking, with retry.

Getting an API key

Each application authenticates with its own key, minted from the Monitor dashboard:

  1. Sign in to the Monitor dashboard and open API keys in the top nav.
  2. Click Create key, enter your application slug (lowercase a-z 0-9 -, e.g. ams-whatsapp), an optional label, and an optional expiry.
  3. The full key (aum_…) is shown once — copy it immediately. The server stores only a hash and can never display it again; if you lose it, mint a new one.
  4. Put the key in your app's environment as AUM_API_KEY (see below). Never commit it.

The app you report (see Quick start) must match the slug the key was minted for, or the event is rejected with 403. Rotate by minting a new key, deploying it, then revoking the old one from the dashboard — revoked or expired keys are rejected with 401.

Install

npm install logique-ai-monitor

Requires Node 18+ (uses the global fetch and AbortSignal.timeout).

Quick start

import { AiMonitor } from 'logique-ai-monitor';

const monitor = new AiMonitor({
  apiKey: process.env.AUM_API_KEY!,
  endpoint: process.env.AUM_ENDPOINT!,        // base URL, e.g. https://YOUR-MONITOR-HOST/api/v1
  // environment is read from process.env.AUM_ENVIRONMENT automatically
  // (production | staging | development, default production) — set it in .env,
  // or pass `environment: '...'` here to override.
  batchSize: 50,                              // optional, default 50
  flushIntervalMs: 10_000,                    // optional: also flush every 10s (low-volume apps)
  onError: (info) => console.warn('AUM', info), // optional: surface delivery failures
});

// call after each AI operation — non-blocking, returns void
monitor.report({
  // app defaults to process.env.AUM_APP — pass `app: '...'` to override per call.
  provider: 'google',                         // google | openai | anthropic | azure_openai | other
  model: 'gemini-2.5-flash',                  // exact provider model name
  usage: {
    input_tokens: 1240,
    output_tokens: 320,
  },
  // optional:
  service: 'lead-classifier',                 // sub-component slug
  operation: 'chat',                          // chat | completion | embedding | image_generation | audio | other
  status: 'success',                          // success | error
  timing: { duration_ms: 867 },
  metadata: { feature: 'intent-classification' },
});

// flush remaining buffer on graceful shutdown — flush() AWAITS delivery
process.on('SIGTERM', async () => {
  await monitor.flush();
  monitor.close();
  process.exit(0);
});

Reporting an error call:

monitor.report({
  app: 'ams-whatsapp',
  provider: 'openai',
  model: 'gpt-4o',
  status: 'error',
  error: { type: 'rate_limit', message: 'Too many requests' },
  usage: { input_tokens: 0, output_tokens: 0 },  // report tokens consumed, or 0 on total failure
});

Environment variables

| Variable | Required | Description | |----------|----------|-------------| | AUM_API_KEY | Yes | Per-app Bearer token issued by Monitor. | | AUM_ENDPOINT | Yes | Monitor base URL, e.g. https://YOUR-MONITOR-HOST/api/v1. The SDK appends /events/batch. | | AUM_APP | No | Registered application slug used as the default app for report() calls. Must be exactly the slug entered in the Application field when the key was created on /api-keys — a mismatch rejects every event with 403. An explicit app config option or per-report param overrides it. | | AUM_ENVIRONMENT | No | Deployment environment reported on every event — any lowercase slug (production, staging, development, dev, uat, …). Default production. An explicit environment config option overrides it; a malformed value falls back to production. |

Config options

| Option | Type | Default | Description | |--------|------|---------|-------------| | apiKey | string | — | Bearer token. | | endpoint | string | — | Monitor API base URL (no /events/batch, no trailing slash). | | app | string | AUM_APP | Default app for report() calls. Must equal the Application slug the key was minted for. | | environment | string (lowercase slug) | AUM_ENVIRONMENT, else production | Reported on every event — dynamic, not limited to an enum. content is suppressed when production. | | batchSize | number | 50 | Auto-flush when the buffer reaches this size. | | timeoutMs | number | 5000 | HTTP request timeout in ms. | | flushIntervalMs | number | — | If set, also auto-flush on this interval (delivers low-volume buffers). | | onError | (info) => void | — | Called on terminal delivery failure (client / oversized / exhausted). |

Event fields

| Field | Required | Description | |-------|----------|-------------| | app | Yes | App slug, e.g. ams-whatsapp. Must match the API key. | | provider | Yes | google | openai | anthropic | azure_openai | other. | | model | Yes | Exact model name from provider, e.g. gpt-4o. | | usage.input_tokens | Yes* | Input tokens (default 0). | | usage.output_tokens | Yes* | Output tokens (default 0). | | usage.cached_input_tokens / reasoning_tokens / images / audio_seconds / raw | No | Extra usage dimensions for pricing. | | service | No | Sub-component slug, e.g. lead-classifier. | | operation | No | Defaults to chat. | | status | No | success (default) or error. | | error | When status=error | { type, message? }. | | trace_id / span_id | No | Auto-generated (UUID) when omitted; pass to correlate multi-step traces. | | parent_span_id | No | Parent span id, or null for a root span. | | timing | No | { start_time?, end_time?, duration_ms? }. | | content | No | { prompt?, completion?, redacted? } — only sent when environment !== production. | | metadata | No | Arbitrary key-value pairs. |

* Auto-filled to 0 when omitted, so failed calls can still be reported.

The SDK auto-sets event_id (UUID v4), schema_version ("1.0"), and timestamp on every event.

Behavior

  • Non-blocking: report() returns immediately; auto-flush at batchSize sends in the background via setImmediate.
  • Never throws into your app: invalid input is dropped (reported via onError), never thrown.
  • Buffered: events accumulate until batchSize (or flushIntervalMs), then flush as one batch.
  • flush() awaits delivery: use it on graceful shutdown so the final batch is not lost.
  • Retry: 429 and 5xx trigger up to 3 retries with exponential backoff (5s → 30s → 60s) + jitter; Retry-After is honored on 429.
  • Oversized batches: a 413 splits the batch and re-sends; a lone oversized event is dropped and reported.
  • Resilient: after retries are exhausted, delivery failures are swallowed — the host app is never affected.
  • Idempotent: each event carries a stable event_id (UUID v4) for Monitor-side deduplication.

Build output

Dual ESM + CJS via tsup:

dist/index.js    — ESM
dist/index.cjs   — CommonJS
dist/index.d.ts  — TypeScript declarations

Development

npm install
npm test          # run Vitest suite (incl. schema conformance vs docs/contract/event.schema.json)
npm run typecheck # tsc --noEmit
npm run build     # tsup ESM+CJS