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

@llm-ports/adapter-openai

v0.1.0-alpha.20

Published

OpenAI SDK adapter for llm-ports. Implements LLMPort and EmbeddingsPort. baseURL support covers 10+ OpenAI-compatible providers (Azure, Groq, Together, Fireworks, DeepInfra, Perplexity, Cerebras, LiteLLM proxy).

Downloads

2,456

Readme

@llm-ports/adapter-openai

OpenAI SDK adapter for llm-ports. Implements LLMPort and EmbeddingsPort. The same adapter serves OpenAI plus 12+ OpenAI-compatible providers via baseURL, including Groq, Together AI, Fireworks AI, Cerebras, Clarifai, and SambaNova.

Install

pnpm add @llm-ports/core @llm-ports/adapter-openai openai zod

Configure

import { createRegistryFromEnv } from "@llm-ports/core";
import { createOpenAIAdapter } from "@llm-ports/adapter-openai";

const registry = createRegistryFromEnv({
  adapters: {
    openai: createOpenAIAdapter({
      apiKey: process.env.OPENAI_API_KEY!,
    }),
  },
});

const llm = registry.getPort();
const embed = registry.getEmbeddingsPort();

Compat providers

The same adapter works for any provider that exposes an OpenAI-shaped API. Just supply a baseURL:

| Provider | baseURL | |----------|-----------| | OpenAI (default) | (none) | | Azure OpenAI | https://<resource>.openai.azure.com/openai/deployments/<deployment> | | Groq | https://api.groq.com/openai/v1 | | Together AI | https://api.together.xyz/v1 | | Fireworks AI | https://api.fireworks.ai/inference/v1 | | DeepInfra | https://api.deepinfra.com/v1/openai | | Perplexity | https://api.perplexity.ai | | Cerebras | https://api.cerebras.ai/v1 | | Clarifai | https://api.clarifai.com/v2/ext/openai/v1 | | SambaNova | https://api.sambanova.ai/v1 | | LiteLLM proxy | self-hosted, e.g. http://localhost:4000 | | Ollama compat-mode | http://localhost:11434/v1 (prefer adapter-ollama for native API) |

Each compatible provider has its own pricing — supply via pricingOverrides:

createOpenAIAdapter({
  apiKey: process.env.GROQ_API_KEY!,
  baseURL: "https://api.groq.com/openai/v1",
  displayName: "groq",
  pricingOverrides: {
    "llama-3.3-70b-versatile": { inputPer1M: 0.59, outputPer1M: 0.79 },
  },
});

Adapter options

interface OpenAIAdapterOptions {
  apiKey: string;
  baseURL?: string;                            // for OpenAI-compat providers
  fetch?: typeof fetch;                        // inject custom fetch (tests, proxies)
  validationStrategy?: ValidationStrategy;
  pricingOverrides?: Record<string, ModelPricing>;
  displayName?: string;                        // friendlier alias in error messages
  imageSizeLimitBytes?: number;                // default 20 MB
  dangerouslyAllowBrowser?: boolean;           // opt in to browser execution (alpha.9)
  maxRetries?: number;                         // SDK-level retries (default 2)
  transientAuthRetries?: number;               // project-key 401 burst retries (default 2)
  transientAuthBackoffMs?: (attempt: number) => number;
  onRetry?: OnRetry;                           // observability hook
}

dangerouslyAllowBrowser (alpha.9+)

The OpenAI SDK refuses to construct in a browser environment unless dangerouslyAllowBrowser: true is passed explicitly. Set this option only when the API key is NOT a long-lived secret: short-lived proxy tokens, BYO-key UIs where the end user supplies their own key, or trusted internal tools running behind auth. For server-side proxy patterns where the secret stays on the server, leave it unset.

const adapter = createOpenAIAdapter({
  apiKey: ephemeralUserKey,
  dangerouslyAllowBrowser: true,
});

Bundled pricing

The bundled OPENAI_PRICING table covers GPT-5 family (gpt-5, gpt-5-mini, gpt-5-nano), GPT-4o family, o3 / o3-mini, and the embedding models. Override per model via pricingOverrides.

Bundled pricing does NOT cover compat-provider models (Groq, Together AI, Fireworks, Cerebras, Clarifai, SambaNova, LiteLLM proxy, etc.) — supply pricingOverrides for those.

Supported features

| Feature | Status | |---------|--------| | generateText | ✓ | | generateStructured (Zod schemas) | ✓ (uses native response_format: json_object + retry-with-feedback) | | streamText | ✓ | | streamStructured (partial JSON) | ✓ (best-effort partial parse) | | runAgent (multi-turn tool use) | ✓ | | generateEmbedding / generateEmbeddings | ✓ (text-embedding-3-small / -large) | | Vision input — base64 images | ✓ (data URI) | | Vision input — URL images | ✓ | | Audio input — base64 wav/mp3 | ✓ | | Audio input — base64 ogg | ✗ (OpenAI doesn't support ogg) | | Audio input — URL audio | ✗ (OpenAI requires base64) | | Prompt caching | ✓ — reported via cachedTokens | | AbortSignal cancellation | ✓ entry + in-flight (alpha.6) |

Content blocks supported

text, image (base64 → data URI; URL passthrough), audio (base64 wav/mp3 only), tool_use, tool_result. Throws ContentBlockUnsupportedError for unsupported variants.

Known reasoning models (auto-handled)

Reasoning models consume output tokens on hidden chain-of-thought before producing visible text. The adapter detects this on first call (empty visible text + finish_reason=length + a reasoning signal in the response) and retries once with the budget expanded by a headroom multiplier.

KNOWN_REASONING_MODELS is a static catalog that pre-seeds the cache at port creation so the first call against a known reasoning model already uses the expanded budget — no wasted round-trip:

| Pattern | Provider example | |---|---| | o1* / o3* / o4* | OpenAI native | | gpt-5-nano* | OpenAI native | | gpt-oss-* | Cerebras (baseURL=https://api.cerebras.ai/v1) | | qwen3[._-]?6* | Clarifai (canonical ID Qwen3_6-35B-A3B-FP8) | | minimax[-_]?m2[._]7* | SambaNova (canonical ID MiniMax-M2.7) |

Unknown reasoning models still get caught by runtime learning on first call; the catalog only saves the first-call round-trip. User-supplied pricingOverrides[modelId].capabilities.reasoningModel always wins.

import { createOpenAIAdapter } from "@llm-ports/adapter-openai";

const clarifai = createOpenAIAdapter({
  apiKey: process.env.CLARIFAI_PAT!,
  baseURL: "https://api.clarifai.com/v2/ext/openai/v1",
  displayName: "clarifai",
  pricingOverrides: {
    "Qwen3_6-35B-A3B-FP8": { inputPer1M: 0.76, outputPer1M: 0.43 },
  },
});

Cancellation

Full AbortSignal support shipped in 0.1.0-alpha.6. The signal is threaded as the 2nd-arg request options to client.chat.completions.create, so controller.abort() cancels the in-flight HTTP request — both for one-shot calls and for streaming. runAgent also re-checks the signal between steps. See the Cancellation guide.

Reading next