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

syntropylabs-evalkit

v0.1.28

Published

EvalKit TypeScript SDK — OpenTelemetry-based LLM observability and tracing

Readme

EvalKit TypeScript SDK

OpenTelemetry-based LLM observability, tracing, and evaluation for Node.js — by Syntropy Labs.

One init() call auto-instruments your LLM providers (OpenAI, Anthropic, Bedrock, Cohere, Google, Vertex, LangChain), databases (Postgres, MySQL, MongoDB, Redis), and HTTP clients — then ships traces to the EvalKit platform.

The Python SDK is published as syntropylabs-evalkit on PyPI.

Install

npm install syntropylabs-evalkit

Provider SDKs are optional peer dependencies — install only what you use:

npm install openai @anthropic-ai/sdk

Quick start

import evalkit from "syntropylabs-evalkit";

evalkit.init({
  subscriptionKey: process.env.EVALKIT_SUBSCRIPTION_KEY!,
  serviceName: "my-service",
});

// That's it — any OpenAI / Anthropic / DB / HTTP call from here is traced.

Call init() as early as possible (top of your entrypoint, before other imports run requests) so auto-instrumentation can hook the libraries.

Framework middleware

Each incoming request becomes a root trace, with downstream LLM/DB/HTTP calls nested underneath.

import express from "express";
import evalkit from "syntropylabs-evalkit";

evalkit.init({ subscriptionKey: process.env.EVALKIT_SUBSCRIPTION_KEY!, serviceName: "api" });

const app = express();
app.use(evalkit.expressMiddleware());

Supported adapters: expressMiddleware(), fastifyPlugin(), koaMiddleware(), honoMiddleware(), hapiPlugin(), and createNestjsInterceptor().

Manual tracing helpers

import evalkit from "syntropylabs-evalkit";

// Open a span by hand
const { end } = evalkit.startSpan("embed-documents", { count: 42 });
try {
  await embed(docs);
  end("OK", { "result.count": docs.length });
} catch (e) {
  end("ERROR", { "error.message": String(e) });
  throw e;
}

await evalkit.flush(); // force-flush before process exit

Tracing your own functions & tools (APM)

Auto-instrumentation covers libraries (LLM / HTTP / DB). For your code, opt in — a function, a tool, a class, or a whole service object:

import evalkit, { Traced } from "syntropylabs-evalkit";

// One function -> function_call span (input / output / latency)
const rankResults = evalkit.traceFunction("rank-results", rank);

// One tool -> tool_call span (Input/Output panels + tool metrics)
const searchWeb = evalkit.traceTool("search_web", (q: string) => runSearch(q));

// Every method of a class, APM-style
@Traced()
class OrderService {
  place(order: Order) { /* ... */ }
  cancel(id: string)  { /* ... */ }
}

// Or one method
class Service {
  @evalkit.TraceMethod()
  async compute() { /* ... */ }
}

// Every function of a service object (parity with Python's trace_module)
export const orders = evalkit.traceObject({ place, cancel }, { prefix: "orders" });

NestJS — trace the whole app automatically

NestJS exposes a DI registry, so the SDK can wrap every provider/controller method for you — no per-class decorators. One line in main.ts: pass the app and the SDK resolves DiscoveryService itself (no @nestjs/core import needed):

const app = await NestFactory.create(AppModule);
evalkit.init({ subscriptionKey: "tk_live_…", serviceName: "orchestrator" });
await evalkit.enableNestjsAutoTrace(app);   // ← the only line you add
await app.listen(5000);

Route metadata (@Get, @Body, guards) is preserved, so routing and auth are unaffected. The call never throws — if discovery can't be resolved it's a no-op. You can still pass a DiscoveryService directly if you prefer.

Auto-discovery is only possible where the framework has a registry (NestJS). For Express / Fastify / Koa / Hono / Hapi, use traceObject / traceFunction on your own modules — incoming HTTP and LLM/DB/HTTP calls are already auto-traced.

Client-side tools you run yourself only show their output if you wrap them with traceTool — the SDK sees the model's request but never your function's return value. Server-side tools (OpenAI web_search, …) and LangChain tools are captured automatically.

Offline evaluation

import { evaluate } from "syntropylabs-evalkit";

// Deterministic, local scoring — runs synchronously, pushed as an eval_result span
const { scores } = evaluate({
  output: "The answer is AWS and Azure.",
  expectedTools: ["search", "summarize"],
  toolCalls: [{ name: "search" }, { name: "summarize" }],
  constraints: { requiredTerms: ["AWS", "Azure"] },
});

Scenario generation & simulation

import evalkit from "syntropylabs-evalkit";

const scenarios = await evalkit.generateScenarios({ /* ... */ });
const { simulationId, results } = await evalkit.simulateUser({ /* ... */ });

Configuration

| Option | Description | | ------------------ | ------------------------------------------------------------- | | subscriptionKey | EvalKit trace-project subscription key (required). | | serviceName | Logical service name attached to every trace. | | environment | "development" | "staging" | "production". | | baseUrl | Override the trace ingest endpoint (defaults to hosted). | | apiUrl | Override the control-plane endpoint (scenario generation). | | maxBodyBytes | Max captured HTTP request/response body size (default 10 MB). |

See the exported EvalKitOptions type for the full set (appVersion, deviceId, debug, batch tuning).

License

Proprietary — © 2026 Syntropy Labs. See LICENSE.