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

@octoryn/sdk

v0.1.0

Published

Octoryn LLM TypeScript SDK — OpenAI-compatible client for Octoryn Gateway with audit, usage, and BYOK extensions.

Readme

@octoryn/sdk

Octoryn LLM TypeScript SDK — OpenAI-compatible client for Octoryn Gateway.

@octoryn/sdk ships an Octoryn client that talks to the Octoryn Gateway (default: https://api.octopusos.dev/v1). The chat / images / audio / embeddings / moderations surface is byte-for-byte OpenAI-compatible, plus first-class extensions for audit, usage, and BYOK. Runs in Node 18+, Bun, Cloudflare Workers, Deno, and browsers.

Install

npm install @octoryn/sdk
# or
pnpm add @octoryn/sdk
yarn add @octoryn/sdk
bun add @octoryn/sdk

Node 18+ (or any runtime with global fetch and FormData).

Quickstart

import { Octoryn } from "@octoryn/sdk";

const client = new Octoryn({ apiKey: process.env.OCTORYN_API_KEY! });
const out = await client.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [{ role: "user", content: "Hello, Octoryn" }],
});
console.log(out.choices[0]?.message.content, "run:", out.octoryn.runId);

Authentication

API key (recommended)

Get a key in the web console at https://app.octopusos.dev:

const client = new Octoryn({ apiKey: process.env.OCTORYN_API_KEY! });

OIDC (refresh-token)

For human / SSO flows the SDK ships an OAuth2 refresh-token credential. It auto-refreshes the short-lived access token (single-flight) and lets you persist the new token-set with onRefresh:

import { Octoryn, createOidcCredential } from "@octoryn/sdk";
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
import { join } from "node:path";

const path = join(process.env.HOME!, ".octoryn", "tokens.json");
const cached = existsSync(path) ? JSON.parse(readFileSync(path, "utf8")) : {};

const credential = createOidcCredential({
  identityUrl: "https://identity.octopusos.dev",
  clientId: "cli",
  refreshToken: cached.refresh_token ?? process.env.OCTORYN_REFRESH_TOKEN!,
  accessToken: cached.access_token,
  expiresAt: cached.expires_at,
  onRefresh: (set) => {
    mkdirSync(join(process.env.HOME!, ".octoryn"), { recursive: true });
    writeFileSync(path, JSON.stringify(set));
  },
});

const client = new Octoryn({ credential });

Pass either apiKey or credential, never both.

Use the official openai SDK (drop-in)

The Octoryn Gateway is bytewise OpenAI-compatible for chat, images, audio, embeddings, and moderations. Point the official openai SDK at the Octoryn base URL and existing code keeps working:

import OpenAI from "openai";
const client = new OpenAI({
  baseURL: "https://api.octopusos.dev/v1",
  apiKey: process.env.OCTORYN_API_KEY!,
});
await client.chat.completions.create({ model: "gpt-4o-mini", messages: [...] });

If you'd rather import from @octoryn/sdk while keeping the OpenAI surface, use the bundled alias:

import { OpenAI } from "@octoryn/sdk/openai-compat";

Modality cookbook

Chat

const out = await client.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [{ role: "user", content: "Summarize the OSI model in one sentence." }],
});
console.log(out.choices[0]?.message.content);

// Stream
const stream = await client.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [{ role: "user", content: "Count 1..5" }],
  stream: true,
});
for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta.content ?? "");
}

Images

const res = await client.images.generate({
  model: "dall-e-3",
  prompt: "a small octopus drawing a vector logo, flat illustration",
  size: "1024x1024",
});
console.log(res.data[0]?.url);

Speech (TTS)

import { writeFile } from "node:fs/promises";
const speech = await client.audio.speech.create({
  model: "tts-1",
  voice: "alloy",
  input: "Octoryn is online.",
  response_format: "mp3",
});
await writeFile("out.mp3", new Uint8Array(await speech.arrayBuffer()));

Transcription (STT)

import { readFile } from "node:fs/promises";
const data = await readFile("meeting.mp3");
const tx = await client.audio.transcriptions.create({
  file: { data, name: "meeting.mp3", type: "audio/mpeg" },
  model: "whisper-1",
});
// In browsers / Workers, pass a `Blob` or `File` directly:
//   file: new File([blob], "clip.webm", { type: "audio/webm" })
console.log(tx.text);

Video

const job = await client.videos.generateAndWait(
  {
    model: "veo-3",
    prompt: "a slow-motion octopus opening a jar underwater",
    duration_seconds: 5,
    resolution: "720p",
    aspect_ratio: "16:9",
  },
  { pollIntervalMs: 2000, timeoutMs: 600_000 },
);
console.log(job.status, job.video_url);

Realtime

const session = await client.realtime.sessions.create({
  provider: "openai",
  model: "gpt-4o-realtime-preview",
  voice: "verse",
});
console.log(session.ws_url, session.audio_sample_rate);
// The SDK does not bundle a WebSocket/WebRTC client. Connect to ws_url
// with the transport of your choice (browser WebSocket, ws, undici, ...).

Embeddings

const emb = await client.embeddings.create({
  model: "text-embedding-3-small",
  input: ["hello", "world"],
});
console.log(emb.data.length);

Moderations

const mod = await client.moderations.create({ input: "I love clean code." });
console.log(mod.results[0]?.flagged);

Models

const list = await client.models.list();
for (const m of list.data) console.log(m.id);

Browser & Edge runtimes

@octoryn/sdk is a thin wrapper over fetch and FormData. It works unmodified in Node 18+, Bun, Cloudflare Workers, Deno, and modern browsers. For audio.transcriptions you can pass a native Blob or File directly (no buffer wrapper needed).

Errors & retries

| Class | When | | ------------------------------ | ------------------------------------------------- | | OctorynAuthError | 401 / 403 | | OctorynRateLimitedError | 429 rate_limited — exposes retryAfterS | | OctorynQuotaExceededError | 429 quota_exceeded | | OctorynKsiBlockedError | 422 ksi_blocked — exposes reasons, channel | | OctorynUpstreamError | 503 upstream — exposes upstream | | OctorynAPIError | base class for all of the above |

import { OctorynRateLimitedError } from "@octoryn/sdk";

try {
  await client.chat.completions.create({ model: "gpt-4o-mini", messages: [...] });
} catch (e) {
  if (e instanceof OctorynRateLimitedError) {
    await new Promise((r) => setTimeout(r, (e.retryAfterS ?? 1) * 1000));
  } else {
    throw e;
  }
}

The client retries 5xx and network errors up to 3 times with exponential backoff. Override per-client with new Octoryn({ apiKey, retry: { maxAttempts: 5, backoffMs: 200 } }).

BYOK / Audit / Usage

const created = await client.byok.create({
  provider: "openai",
  api_key: "sk-...",
  label: "prod",
});
console.log(created.id, created.plaintext_key); // plaintext shown ONCE

const runs = await client.audit.list({ limit: 20 });
const detail = await client.audit.get(runs.data[0]!.id);
const verified = await client.audit.verify(detail.id);

const summary = await client.usage.get();
const records = await client.usage.records({ limit: 50 });

Versioning & License

Octoryn follows semver from 1.0.0. Pre-1.0 minor bumps may break. See CHANGELOG.md (added in Phase 7) and https://octopusos.dev.

Proprietary © Octopus Core Pty Ltd (ACN 696 931 236). Octoryn™ is a trademark of Octopus Core Pty Ltd.