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

@cle-does-things/llms-sdk-wasm

v0.1.3

Published

Unified interface to call OpenAI and Anthropic-compatible LLM APIs from your browser

Readme

@cle-does-things/llms-sdk-wasm

WASM bindings for llms-sdk, to call OpenAI- and Anthropic-compatible LLMs from the browser.

Installation

npm install @cle-does-things/llms-sdk-wasm

Or use directly in a browser via a bundler that supports WASM (e.g. Vite, Webpack, Rollup).

Quick Start

import init, { chat } from "@cle-does-things/llms-sdk-wasm";

await init();

const response = await chat({
  api_type: "openai",
  api_key: "sk-...",
  model: "gpt-5.4-mini",
  messages: [
    { role: "user", content: [{ type: "text", text: "Hello!" }] }
  ],
  stream: false,
  parallel_tool_calls: false,
});

console.log(response.message.content);

API

Initialization

import init from "@cle-does-things/llms-sdk-wasm";
await init(); // loads and instantiates the WASM module

chat(request, retry_policy?)

Sends a single non-streaming chat request and returns the full response.

Parameters:

  • request: LLMRequest — the chat request (see LLMRequest)
  • support_developer: boolean — Whether or not the OpenAI-like clients support developer as a role instead of system.

Returns: Promise<LLMResponse>

const response = await chat({
  api_type: "openai",
  base_url: "https://api.openai.com/v1",  // optional
  api_key: "sk-...",
  model: "gpt-5.4-mini",
  messages: [
    { role: "system", content: [{ type: "text", text: "You are a helpful assistant." }] },
    { role: "user", content: [{ type: "text", text: "Explain quantum computing." }] }
  ],
  max_output_tokens: 256,
  temperature: 0.7,
  top_p: 1.0,
  stream: false,
  parallel_tool_calls: false,
});

// response.id          — provider-generated response ID
// response.created_at  — unix timestamp
// response.message     — { role, content: MessagePart[] }
// response.usage       — { input_tokens, output_tokens, cache_read_tokens, cache_write_tokens }

streamChat(request, callback, retry_policy?)

Streams a chat response, invoking the callback for each chunk.

Parameters:

  • request: LLMRequest — the chat request
  • support_developer: boolean — Whether or not the OpenAI-like clients support developer as a role instead of system.
  • callback: (error: any, chunk: LLMStreamingResponse) => void — called on every stream event

Returns: Promise<void>

await streamChat(request, (err, chunk) => {
  if (err) {
    console.error("Stream error:", err);
    return;
  }

  switch (chunk.type) {
    case "delta":
      console.log("Text:", chunk.delta);
      console.log("Done?", chunk.stop);
      break;
    case "thinkingDelta":
      console.log("Reasoning:", chunk.delta);
      break;
    case "toolDelta":
      console.log("Tool call:", chunk.name, chunk.partial_arguments);
      break;
    case "complete":
      console.log("Final message:", chunk.message);
      console.log("Usage:", chunk.usage);
      break;
  }
});

Content Helpers

Build MessagePart objects for multimodal inputs:

import { imagePart, documentPart, audioPart } from "@cle-does-things/llms-sdk-wasm";

// Image from URL or Uint8Array
const img = imagePart("https://example.com/image.png");
const imgFromBytes = imagePart({ bytes: new Uint8Array([...]) });

// Document (PDF, etc.) from URL or Uint8Array
const doc = documentPart("https://example.com/doc.pdf");

// Audio from Uint8Array
const audio = audioPart({ bytes: new Uint8Array([...]) });

Types

LLMRequest

| Field | Type | Required | Description | |-------|------|----------|-------------| | api_type | "openai" \| "anthropic" | ✅ | Provider type | | base_url | string | | Override the default API base URL | | api_key | string | ✅ | API key | | model | string | ✅ | Model identifier | | messages | Message[] | ✅ | Conversation history | | max_output_tokens | number | | Maximum tokens to generate | | temperature | number | | Sampling temperature | | top_p | number | | Nucleus sampling | | reasoning_effort | ReasoningEffort | | Control reasoning depth (none … maximum) | | prompt_cache_ttl | string | | Prompt cache TTL hint | | stream | boolean | ✅ | Enable streaming | | output_format | OutputFormat | | Structured output JSON schema | | tools | Tool[] | | Available function tools | | tool_choice | ToolChoice | | Tool selection mode (auto, none, required) | | parallel_tool_calls | boolean | ✅ | Allow parallel tool calls |

Message

interface Message {
  role: "user" | "assistant" | "tool" | "system";
  content: MessagePart[];
}

MessagePart

A discriminated union of content types:

| Tag | Fields | |-----|--------| | { type: "text" } | text: string | | { type: "image" } | image_data: string, is_base64: boolean, mime_type?: string | | { type: "document" } | document_data: string, is_base64: boolean, mime_type?: string | | { type: "audio" } | audio_data: string, mime_type: string | | { type: "toolCall" } | id: string, name: string, arguments: string | | { type: "toolResult" } | tool_call_id: string, result: string | | { type: "thinking" } | thinking: string, signature?: string |

LLMResponse

interface LLMResponse {
  id: string;
  created_at?: number;
  message: Message;
  usage: LLMUsage;
}

LLMUsage

interface LLMUsage {
  input_tokens: number;
  output_tokens: number;
  cache_read_tokens?: number;
  cache_write_tokens?: number;
  other_tokens?: Map<string, number>;
}

Streaming Types

type LLMStreamingResponse =
  | { type: "delta"; response_id: string; created_at?: number; delta?: string; stop: boolean }
  | { type: "thinkingDelta"; response_id: string; created_at?: number; delta?: string }
  | { type: "toolDelta"; response_id: string; tool_call_id: string; name: string; partial_arguments: string }
  | { type: "complete"; id: string; created_at?: number; message: Message; deltas: LLMStreamingDelta[]; thinking_deltas?: LLMThinkingDelta[]; usage?: LLMUsage; tool_calls?: ToolCallPart[] };

Demo

A complete browser demo is included in demo.html. Open it in a browser (via a local server) after building the WASM package:

cd packages/wasm
wasm-pack build --target web
# serve the directory, e.g.
npx serve .

Then open http://localhost:3000/demo.html.

Building from Source

Requires Rust and wasm-pack:

npm run build

The compiled package is output to pkg/.

License

MIT