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

@ai-setu/client

v0.16.1

Published

AI Setu client — drop-in OpenAI SDK with workspace credit accounting and multi-provider routing.

Readme

@ai-setu/client

Read this first, agent. This package = drop-in for the official openai SDK, pointed at the AI Setu gateway. If you know OpenAI SDK, you know this. Same methods, same shapes, same streaming. Only thing change: one workspace key, and model carry a provider/ prefix. Everything below is copy-paste safe.

TL;DR (the only three lines you need)

npm i @ai-setu/client
export AI_SETU_API_KEY=tt_live_…
import { AiSetu } from '@ai-setu/client';
const client = new AiSetu();
const res = await client.chat.completions.create({
  model: 'openai/gpt-4o-mini',
  messages: [{ role: 'user', content: 'hi' }],
});
console.log(res.choices[0].message.content);

Done. new AiSetu() with no args read AI_SETU_API_KEY from env. No baseURL, no createClient, no factory. One import, one symbol.

Rules for agent (follow these, no guess)

  1. Model string provider/model (platform key) or @<slug>/<model> (your BYOK Connection — see below). Good: openai/gpt-4o-mini, anthropic/claude-sonnet-4-5, @azure-qdc/gpt-4o-mini. A bare name with no prefix routes by catalog.
  2. No pick endpoint. Client talk to gateway only. You no set URLs for normal use. Provider chosen by the model prefix, not by base URL.
  3. Method names = OpenAI SDK exactly. chat.completions.create, embeddings.create, streaming by stream: true + for await. Whatever you learned on openai, it transfer here unchanged.
  4. Key go in env AI_SETU_API_KEY (shape tt_live_…). Or pass new AiSetu({ apiKey }). Never hardcode key in source you commit.
  5. Need balance / usage / keys? That NOT this package. Use @ai-setu/admin. This one stay pure inference.
  6. Node ≥ 20 or edge runtime (Vercel, Cloudflare Workers).

Models — pick by prefix

openai/gpt-4o            openai/gpt-4o-mini       openai/text-embedding-3-small
anthropic/claude-sonnet-4-5                       anthropic/claude-haiku-4-5
bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0   (BYOK — your AWS account)

Streaming (same as OpenAI)

const stream = await client.chat.completions.create({
  model: 'anthropic/claude-sonnet-4-5',
  messages: [{ role: 'user', content: 'Write me a haiku.' }],
  stream: true,
});
for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? '');
}

Embeddings

const e = await client.embeddings.create({
  model: 'openai/text-embedding-3-small',
  input: 'hello world',
});

Errors — catch logic from OpenAI SDK transfer straight

Use type guards, no instanceof on subclasses. Reason: the openai SDK make APIError itself from inside its pipeline, so subclass drift every release. Guard narrow the type back to APIError — you still get err.code, err.status, err.requestID.

import {
  AuthenticationError,
  RateLimitError,
  isInsufficientCreditsError,
  getInsufficientCreditsDetails,
  isProviderError,
} from '@ai-setu/client';

try {
  await client.chat.completions.create({
    /* … */
  });
} catch (err) {
  if (err instanceof AuthenticationError) {
    /* bad key */
  } else if (err instanceof RateLimitError) {
    /* slow down */
  } else if (isInsufficientCreditsError(err)) {
    const { balanceMicros, topupUrl } = getInsufficientCreditsDetails(err);
    console.error(`Out of credits (balance ${balanceMicros} micros). Top up: ${topupUrl}`);
  } else if (isProviderError(err)) {
    /* upstream provider broke */
  }
}

Environments — one switch move whole app

Default = production (gateway.aisetu.ai). Point at a different gateway (e.g. a self-hosted deployment) with a full URL override:

export AI_SETU_BASE_URL=https://gateway.your-deployment.example.com

Precedence (first match win):

  1. new AiSetu({ baseUrl }) — explicit per-instance
  2. AI_SETU_BASE_URL — full URL override (self-host / on-prem)
  3. production default

(Base always normalise to end in /v1.)

Runtime + connection pooling (you usually no touch this)

  • Node ≥ 20 — one process-wide keep-alive undici.Agent back every AiSetu. Sequential calls reuse the TCP connection (~5ms p50 vs ~30ms cold).
  • Edge (Cloudflare Workers / Vercel) — fall back to platform fetch, which already pool. undici is optional dep, edge bundlers skip it.

Pool defaults: connections 32, allowH2 true, keepAliveTimeout 30s, keepAliveMaxTimeout 90s (match gateway idle), bodyTimeout 0 (no cap — long thinking-model streams can run for minutes; cancel with AbortSignal).

Override the pool only if you must:

import { Agent, ProxyAgent } from 'undici';
import { AiSetu } from '@ai-setu/client';

// Corporate proxy:
const proxied = new AiSetu({ dispatcher: new ProxyAgent({ uri: 'http://proxy:8080' }) });

// Self-signed CA (baseUrl normalise to …/v1):
const onPrem = new AiSetu({
  baseUrl: 'https://gateway.internal.example',
  dispatcher: new Agent({ connect: { ca: fs.readFileSync('ca.pem') } }),
});

// No pooling at all (platform fetch on Node):
const unpooled = new AiSetu({ dispatcher: null });

Process-wide swap (before any AiSetu construct), or share the singleton with sibling SDKs:

import { setSharedDispatcher, getSharedDispatcher } from '@ai-setu/client';
import { Agent } from 'undici';
import { AiSetuAdmin } from '@ai-setu/admin';

setSharedDispatcher(new Agent({ connections: 64, allowH2: true }));
const admin = new AiSetuAdmin({ dispatcher: getSharedDispatcher() });

BYOK: route per request with @<slug>/<model>

Your provider keys live in Connections (each has a slug). Pick one per request inside the model string — @<slug>/<model> — and the gateway routes through that Connection's key. One client, mix Connections freely, no re-init. A leading @ marks a slug (so a slug can equal a provider name); an unknown or out-of-scope slug fails closed (4xx), never a silent platform-key fallback.

const c = new AiSetu();

await c.chat.completions.create({
  model: '@azure-qdc/gpt-5.4-mini', // route via the Connection slug "azure-qdc"
  messages: [{ role: 'user', content: 'hi' }],
});

await c.chat.completions.create({
  model: 'openai/gpt-4o-mini', // platform key (no @slug)
  messages: [{ role: 'user', content: 'hi' }],
});

Pin one Connection for the whole client with the connection option (a leading @ is optional):

const c = new AiSetu({ connection: '@azure-qdc' });

Verify your BYOK Connection served (not the platform key)

The gateway stamps attribution headers on every response; the SDK parses them so you can confirm — per request — that your own key served:

const c = new AiSetu({
  onRouting: (r) => {
    if (!r.byok) throw new Error('expected BYOK, got platform key — bad slug?');
  },
});

await c.chat.completions.create({
  model: '@azure-qdc/gpt-5.4-mini',
  messages: [{ role: 'user', content: 'hi' }],
});

// Or read synchronously after any call:
c.lastRouting;
// { provider: 'openai', byok: true,
//   credentialId: '…uuid…', connectionSlug: 'azure-qdc' }

RoutingInfo:

| field | meaning | | ----------------- | ------------------------------------------------------------------ | | provider | provider that served (openai, anthropic, …) | | byok | true = your key served; false = platform key (or unknown slug) | | credentialId | the Credential that served (BYOK only) | | connectionSlug | the Connection slug that served (BYOK only) | | credentialLabel | deprecated alias of connectionSlug (same value) |

Callback is best-effort — an exception inside onRouting is swallowed so a faulty listener can't break inference. Headers absent (gateway older than this feature) → no callback, lastRouting stays undefined. Credential id / slug are not secrets — you own the Connection.

Legacy: the workspaceCredential option + the label/model model string are deprecated. workspaceCredential still works (alias of connection); the bare label/model form does not — use @<slug>/<model>.

Why not raw OpenAI SDK with custom baseURL?

You can. AiSetu just do it for you and add: env-var-first construct (new AiSetu() no args), keep-alive pool tuned to the gateway, and per-request BYOK routing (@<slug>/<model> / the connection option). No care about those? Point openai at the gateway yourself.

The four AI Setu packages — which one you grab

| Package | Use it when | | ------------------------------------------------------------------ | -------------------------------------------------------------------------------- | | @ai-setu/client | Runtime agent / app call inference. Drop-in for openai. | | @ai-setu/admin | Scripts / CI / builder agent run control-plane ops in TypeScript. | | @ai-setu/cli | Same control-plane ops from the shell. | | @ai-setu/mcp | Builder agent (Claude Code, Cursor) drive onboarding + ops conversationally. |

Full agent runbook = llms.txt.

License

MIT.