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

interceptor-engine

v0.1.0

Published

Observes Gemini API calls via fetch, emits events, logs, and reports for AI observability.

Readme

Interceptor Engine

Interceptor Engine patches global fetch and provides real-time API observability for running apps.

  • Detects Gemini calls (generativelanguage.googleapis.com)
  • Emits normalized events (api-call, api-error)
  • Prints live terminal logs and summary reports
  • Stores in-memory history and aggregate metrics
  • Redacts sensitive data in output

Prerequisites

  • Node.js 18+ (or any runtime where global.fetch exists)
  • Import this module before your first API call

Install

npm install interceptor-engine

Quick Start (JavaScript)

const {
  emitter,
  setConfig,
  getMetrics,
  getCallHistory,
  reportNow
} = require('interceptor-engine');

setConfig({
  emitAllCalls: true,
  realtimeConsole: true,
  reportIntervalMs: 60000
});

emitter.on('api-call', (event) => {
  console.log('Observed:', event.method, event.status, event.url);
});

emitter.on('api-error', (event) => {
  console.error('API error:', event.error);
});

// Your app runs normally and uses fetch...

// On-demand report:
reportNow('manual-check');

console.log('Metrics:', getMetrics());
console.log('Recent calls:', getCallHistory({ limit: 5 }));

Quick Start (TypeScript)

const interceptor = require('interceptor-engine') as {
  emitter: import('events').EventEmitter;
  setConfig: (config: Partial<InterceptorConfig>) => InterceptorConfig;
  getMetrics: () => InterceptorMetrics;
  getCallHistory: (options?: CallHistoryOptions) => InterceptorEvent[];
  reportNow: (context?: string) => void;
};

type InterceptorConfig = {
  slowThresholdMs: number;
  emitGeminiCalls: boolean;
  emitSlowCalls: boolean;
  emitAllCalls: boolean;
  maxHistory: number;
  redactSensitiveData: boolean;
  redactKeys: string[];
  redactionText: string;
  realtimeConsole: boolean;
  consoleShowPromptPreview: boolean;
  promptPreviewMaxChars: number;
  reportIntervalMs: number;
  printReportOnExit: boolean;
};

type CallHistoryOptions = {
  limit?: number;
  onlyGemini?: boolean;
  onlyErrors?: boolean;
  minTimeMs?: number;
  query?: string;
};

type InterceptorEvent = {
  id: number;
  timestamp: string;
  url: string;
  method: string;
  status: number | string;
  time: number;
  model: string;
  response: string;
  isAICall: boolean;
  aiType: string;
  prompt: string;
  aiResponse: string;
  requestBody: string;
  error?: string;
};

type InterceptorMetrics = {
  totalSeen: number;
  totalCaptured: number;
  geminiCalls: number;
  slowCalls: number;
  errorCalls: number;
  totalLatencyMs: number;
  avgLatencyMs: number;
  historySize: number;
};

interceptor.emitter.on('api-call', (event: InterceptorEvent) => {
  console.log(event.model, event.time);
});

How It Works

  1. Module load patches global.fetch
  2. Every call is timed and normalized
  3. Gemini request/response fields are extracted when endpoint matches
  4. Sensitive values are redacted before logging/storage
  5. Event is emitted and optionally logged in real time
  6. History/metrics are updated for reporting and querying

Exported API

emitter

Event emitter for runtime notifications.

  • api-call: emitted for captured calls
  • api-error: emitted when a captured call fails

setConfig(nextConfig)

Updates runtime behavior. Unknown keys are ignored.

Arguments:

  • nextConfig.slowThresholdMs (number): ms threshold for slow calls
  • nextConfig.emitGeminiCalls (boolean): capture Gemini calls
  • nextConfig.emitSlowCalls (boolean): capture slow calls
  • nextConfig.emitAllCalls (boolean): capture every fetch call
  • nextConfig.maxHistory (number): max in-memory events
  • nextConfig.redactSensitiveData (boolean): redact outputs
  • nextConfig.redactKeys (string[]): key names for redaction matching
  • nextConfig.redactionText (string): replacement text
  • nextConfig.realtimeConsole (boolean): print live call lines
  • nextConfig.consoleShowPromptPreview (boolean): include prompt snippet
  • nextConfig.promptPreviewMaxChars (number): prompt preview length
  • nextConfig.reportIntervalMs (number): periodic report interval; <=0 disables
  • nextConfig.printReportOnExit (boolean): print final report at process exit

Returns: current config object.

getConfig()

Returns current resolved config.

getCallHistory(options?)

Returns recent captured events.

Arguments:

  • options.limit (number, default 50)
  • options.onlyGemini (boolean, default false)
  • options.onlyErrors (boolean, default false)
  • options.minTimeMs (number, default 0)
  • options.query (string, default '')

Returns: InterceptorEvent[].

getMetrics()

Returns aggregate counters and latency stats.

reportNow(context?)

Prints a report immediately to console.

  • context (string, default 'manual')

clearHistory()

Clears in-memory call history only.

resetMetrics()

Resets aggregate counters and uptime baseline.

startObserving() / stopObserving()

Starts/stops runtime console and periodic reporting observers.

restoreFetch()

Restores the original global fetch and stops observers.

isIntercepting()

Returns true if fetch is currently patched.

Event Shape (api-call)

{
  id: 1,
  timestamp: '2026-04-02T12:34:56.000Z',
  url: 'https://generativelanguage.googleapis.com/...',
  method: 'POST',
  status: 200,
  time: 123,
  model: 'gemini-2.0-flash',
  response: '{...}',
  isAICall: true,
  aiType: 'gemini',
  prompt: 'User prompt text',
  aiResponse: 'Model response text',
  requestBody: '{...}',
  error: undefined
}

Real-Project Integration Pattern

Import once in your app bootstrap file:

// src/bootstrap.js
require('interceptor-engine');

// then import/start the rest of your app
require('./server');

This ensures all later fetch calls are observed.

Notes

  • Gemini parsing is endpoint-based; non-Gemini calls are still observable when emitAllCalls is true.
  • History is in-memory only (process lifetime).
  • Redaction is best-effort and configurable.