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

@enprompta/sdk

v1.1.1

Published

Official TypeScript SDK for Enprompta — auto-instrument OpenAI and Anthropic, serve versioned prompts from the registry, and ship traces to the observability dashboard.

Readme

@enprompta/sdk

Official TypeScript SDK for Enprompta -- the prompt registry, observability, and evaluation platform for AI apps.

Installation

npm install @enprompta/sdk
# or
pnpm add @enprompta/sdk
# or
yarn add @enprompta/sdk

Quick Start: Auto-trace every LLM call

Pass the provider client(s) you import to init({ modules }). This is the reliable way to instrument — we patch the exact module your code calls, which works the same in ESM, CommonJS, and bundled apps:

import { init } from '@enprompta/sdk'
import OpenAI from 'openai'

init({
  apiKey: process.env.ENPROMPTA_API_KEY,
  modules: { openai: OpenAI },   // also: { anthropic: Anthropic, google: GenerativeModel }
})

// Every call on that client is now traced — no other code changes.
const openai = new OpenAI()
const response = await openai.chat.completions.create({
  model: 'gpt-4o',
  messages: [{ role: 'user', content: 'Hello' }]
})
// Trace appears in your Enprompta dashboard automatically

Auto-instrumentation captures: provider, model, prompt, response, tokens, latency, cost, and errors.

Why modules? In ESM apps (the default for modern Node/TS) and bundlers, the SDK can't reliably reach into your provider package via require() — it may resolve a different copy of the module than the one you imported, so the patch silently does nothing. Passing the client you imported removes that ambiguity. If you call init() without modules and nothing gets instrumented, the SDK now logs a warning telling you to switch to this form. (CommonJS apps may omit modules and rely on auto-detection.)

Framework instrumentation (LangChain, …)

init() captures the raw LLM call. To capture the whole agent/RAG trace -- retrievals, tool calls, sub-agent steps, and their nesting -- bridge the OpenInference instrumentors for the frameworks you use. They emit typed, nested OpenTelemetry spans that Enprompta ingests as first-class span types (Retrieval, Tool, Reranker, Agent, …).

npm install @opentelemetry/sdk-trace-node @opentelemetry/sdk-trace-base \
  @opentelemetry/exporter-trace-otlp-http @opentelemetry/resources
npm install @enprompta/instrument-langchain   # your stack's instrumentor(s): also @enprompta/instrument-openai
import { instrumentFrameworks } from '@enprompta/sdk'

instrumentFrameworks({ apiKey: process.env.ENPROMPTA_API_KEY! })            // auto-detect
// ...or pick explicitly:
instrumentFrameworks({ apiKey: process.env.ENPROMPTA_API_KEY!, frameworks: ['langchain'] })

Exports to Enprompta's OTLP endpoint over a Bearer API key, coexisting with an existing OpenTelemetry setup. Returns a handle -- call .uninstrument() to stop. (The JS OpenInference ecosystem is younger than Python's; supported names today are langchain and openai.)

What you get

  • Auto-instrumentation for OpenAI, Anthropic, and Gemini (@google/generative-ai) -- patch on import, no wrapper functions
  • Framework instrumentation -- one-line LangChain capture via the OpenInference bridge (instrumentFrameworks())
  • Prompt registry -- serve versioned prompts from Enprompta, swap them without redeploying
  • Manual tracing helpers -- observe(), tracedOpenAI(), traces.wrap() for fine-grained control
  • Nested spans -- track RAG pipelines, agent workflows, tool calls
  • Type-safe -- full TypeScript declarations
  • Async batching -- traces sent in batches, never blocks your app
  • Fail-silent -- tracing errors never crash your code

Programmatic API

For prompt management, execution, evaluation, and analytics:

import { Enprompta } from '@enprompta/sdk'

// Initialize with API key
const client = new Enprompta({
  apiKey: process.env.ENPROMPTA_API_KEY
})

// List prompts
const { data: prompts } = await client.prompts.list()

// Create a prompt
const prompt = await client.prompts.create({
  title: 'Email Writer',
  content: 'Write a professional email about {{topic}}',
  visibility: 'PRIVATE'
})

// Execute a prompt
const result = await client.prompts.execute(prompt.id, {
  variables: { topic: 'project update' },
  provider: 'openai',
  model: 'gpt-4o'
})

console.log(result.output)

Authentication

API Key

const client = new Enprompta({
  apiKey: 'ep_your_api_key'
})

OAuth2 Client Credentials

const client = new Enprompta({
  clientId: 'your_client_id',
  clientSecret: 'your_client_secret',
  scopes: ['prompts:read', 'prompts:write']
})

Features

Prompts

// List with pagination
const { data, pagination } = await client.prompts.list({
  limit: 20,
  visibility: 'PRIVATE'
})

// Create
const prompt = await client.prompts.create({
  title: 'My Prompt',
  content: 'Hello {{name}}',
  variables: [{ name: 'name', type: 'text', required: true }]
})

// Get
const prompt = await client.prompts.get('prompt_id')

// Update
await client.prompts.update('prompt_id', { title: 'New Title' })

// Delete
await client.prompts.delete('prompt_id')

// Execute
const result = await client.prompts.execute('prompt_id', {
  variables: { name: 'World' },
  provider: 'openai',
  model: 'gpt-4'
})

Executions

// List executions
const { data } = await client.executions.list({
  promptId: 'prompt_id',
  startDate: '2024-01-01'
})

// Get statistics
const stats = await client.executions.getStats({ groupBy: 'day' })

Teams

const teams = await client.teams.list()
const team = await client.teams.create({ name: 'Engineering' })
await client.teams.update('team_id', { name: 'New Name' })

Webhooks

const webhook = await client.webhooks.create({
  name: 'My Webhook',
  url: 'https://example.com/webhook',
  events: ['prompt.created', 'execution.completed']
})

LLM Observability & Tracing

observe() Function

Wrap any LLM function with automatic tracing:

import { Enprompta, observe } from '@enprompta/sdk'
import OpenAI from 'openai'

const client = new Enprompta({ apiKey: 'ep_your_api_key' })
const openai = new OpenAI()

const generateResponse = observe(
  client,
  { provider: 'openai', model: 'gpt-4' },
  async (prompt: string) => {
    const response = await openai.chat.completions.create({
      model: 'gpt-4',
      messages: [{ role: 'user', content: prompt }]
    })
    return response.choices[0].message.content
  }
)

// Traces are automatically recorded with timing, tokens, and cost
const result = await generateResponse('Explain quantum computing')

Auto-traced OpenAI Client

Wrap your OpenAI client for zero-code tracing:

import { Enprompta, tracedOpenAI } from '@enprompta/sdk'
import OpenAI from 'openai'

const enprompta = new Enprompta({ apiKey: 'ep_...' })
const openai = tracedOpenAI(enprompta, new OpenAI())

// All calls are now automatically traced!
const response = await openai.chat.completions.create({
  model: 'gpt-4',
  messages: [{ role: 'user', content: 'Hello' }]
})

traces.wrap() Helper

For more control, use the built-in wrap helper:

const result = await client.traces.wrap(
  { provider: 'openai', model: 'gpt-4', input: 'Hello' },
  async () => {
    const response = await openai.chat.completions.create({
      model: 'gpt-4',
      messages: [{ role: 'user', content: 'Hello' }]
    })
    return {
      output: response.choices[0].message.content,
      inputTokens: response.usage?.prompt_tokens,
      outputTokens: response.usage?.completion_tokens
    }
  }
)

console.log(`Trace ID: ${result.traceId}`)

Nested Spans for Complex Pipelines

Track multi-step operations like RAG:

// Record the main trace
const trace = await client.traces.record({
  provider: 'openai',
  model: 'gpt-4',
  input: 'What are our refund policies?',
  output: 'Based on our documentation...',
  latencyMs: 2500
})

// Add spans for each step
await client.traces.createSpan(trace.traceId, {
  name: 'vector_search',
  spanType: 'RETRIEVAL',
  input: { query: 'refund policies', topK: 5 },
  output: { documentIds: ['doc1', 'doc2'] },
  durationMs: 150
})

await client.traces.createSpan(trace.traceId, {
  name: 'embedding',
  spanType: 'EMBEDDING',
  tokens: 8,
  durationMs: 50
})

Analytics

const analytics = await client.traces.getAnalytics(30)
console.log(`Total traces: ${analytics.totalTraces}`)
console.log(`Total cost: $${analytics.totalCost.toFixed(2)}`)
console.log(`Avg latency: ${analytics.avgLatency}ms`)

Middleware

import { Enprompta, LoggingMiddleware, RetryMiddleware } from '@enprompta/sdk'

const client = new Enprompta({
  apiKey: 'ep_your_api_key',
  middleware: [
    new LoggingMiddleware({ level: 'debug' }),
    new RetryMiddleware({ maxRetries: 3 })
  ]
})

Custom Middleware

import { Middleware, RequestContext, NextFunction } from '@enprompta/sdk'

class CustomMiddleware implements Middleware {
  name = 'custom'
  priority = 100

  async handle(ctx: RequestContext, next: NextFunction) {
    console.log('Before request')
    const response = await next(ctx)
    console.log('After request')
    return response
  }
}

Retry Strategies

import { Enprompta, RetryStrategies } from '@enprompta/sdk'

const client = new Enprompta({
  apiKey: 'ep_your_api_key',
  retry: {
    strategy: RetryStrategies.exponential,
    maxRetries: 3,
    baseDelay: 1000
  }
})

Available strategies:

  • exponential - 1s, 2s, 4s, 8s...
  • linear - 1s, 2s, 3s, 4s...
  • fixed - Always same delay
  • aggressive - Quick retries (100ms base)
  • conservative - Long delays (5s base)
  • rateLimitAware - Uses Retry-After header

Error Handling

import {
  EnpromptaError,
  AuthenticationError,
  RateLimitError,
  ValidationError,
  NotFoundError
} from '@enprompta/sdk'

try {
  await client.prompts.get('invalid_id')
} catch (error) {
  if (error instanceof NotFoundError) {
    console.log('Prompt not found')
  } else if (error instanceof RateLimitError) {
    console.log(`Retry after ${error.retryAfter}s`)
  } else if (error instanceof EnpromptaError) {
    console.log(`Error ${error.code}: ${error.message}`)
  }
}

TypeScript Support

Full TypeScript support with comprehensive type definitions:

import type {
  Prompt,
  Execution,
  Team,
  Webhook,
  CreatePromptParams,
  ExecutePromptParams,
  PaginatedResponse
} from '@enprompta/sdk'

Requirements

  • Node.js 18+
  • TypeScript 4.7+ (for TypeScript users)

Documentation

Full documentation: https://enprompta.com/docs/sdk/typescript

License

MIT