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

@ottocode/ai-sdk

v0.1.8

Published

A drop-in SDK for accessing AI models (OpenAI, Anthropic, Google, Moonshot, MiniMax, Z.AI) through the [Setu](https://github.com/slashforge/setu) proxy with automatic x402 payments via Solana USDC.

Downloads

1,010

Readme

@ottocode/ai-sdk

A drop-in SDK for accessing AI models (OpenAI, Anthropic, Google, Moonshot, MiniMax, Z.AI) through the Setu proxy with automatic x402 payments via Solana USDC.

All you need is a Solana wallet — the SDK handles authentication, payment negotiation, and provider routing automatically.

Install

bun add @ottocode/ai-sdk ai
# or
npm install @ottocode/ai-sdk ai

Quick Start

import { createSetu } from '@ottocode/ai-sdk';
import { generateText } from 'ai';

const setu = createSetu({
  auth: { privateKey: process.env.SOLANA_PRIVATE_KEY! },
});

const { text } = await generateText({
  model: setu.model('claude-sonnet-4-20250514'),
  prompt: 'Hello!',
});

console.log(text);

The SDK auto-resolves which provider to use based on the model name. It returns ai-sdk compatible model instances that work directly with generateText(), streamText(), etc.

Provider Auto-Resolution

Models are resolved to providers by prefix:

| Prefix | Provider | API Format | |---|---|---| | claude- | Anthropic | Messages | | gpt-, o1, o3, o4, codex- | OpenAI | Responses | | gemini- | Google | Native | | kimi- | Moonshot | OpenAI Chat | | MiniMax- | MiniMax | Messages | | z1- | Z.AI | OpenAI Chat |

setu.model('claude-sonnet-4-20250514');   // → anthropic
setu.model('gpt-4o');                      // → openai
setu.model('gemini-2.5-pro');             // → google
setu.model('kimi-k2');                    // → moonshot

Explicit Provider

Override auto-resolution when needed:

const model = setu.provider('openai').model('gpt-4o');
const model = setu.provider('anthropic', 'anthropic-messages').model('claude-sonnet-4-20250514');

Configuration

const setu = createSetu({
  // Required: Solana wallet private key (base58)
  auth: { privateKey: '...' },

  // Optional: Setu API base URL (default: https://api.setu.ottocode.io)
  baseURL: 'https://api.setu.ottocode.io',

  // Optional: Solana RPC URL (default: https://api.mainnet-beta.solana.com)
  rpcURL: 'https://api.mainnet-beta.solana.com',

  // Optional: Payment callbacks
  callbacks: { /* see Payment Callbacks */ },

  // Optional: Cache configuration
  cache: { /* see Caching */ },

  // Optional: Payment options
  payment: { /* see Payment Options */ },

  // Optional: Custom model→provider mappings
  modelMap: {
    'my-custom-model': 'openai',
  },

  // Optional: Register custom providers
  providers: [
    {
      id: 'my-provider',
      apiFormat: 'openai-chat',
      modelPrefix: 'myp-',
    },
  ],
});

Payment Callbacks

Monitor and control the payment lifecycle:

const setu = createSetu({
  auth: { privateKey: '...' },
  callbacks: {
    // Called when a 402 is received and payment is needed
    onPaymentRequired: (amountUsd, currentBalance) => {
      console.log(`Payment required: $${amountUsd}`);
    },

    // Called when the SDK is signing a transaction
    onPaymentSigning: () => {
      console.log('Signing payment...');
    },

    // Called after successful payment
    onPaymentComplete: ({ amountUsd, newBalance, transactionId }) => {
      console.log(`Paid $${amountUsd}, balance: $${newBalance}`);
    },

    // Called on payment failure
    onPaymentError: (error) => {
      console.error('Payment failed:', error);
    },

    // Called after each request with cost info (streaming & non-streaming)
    onBalanceUpdate: ({ costUsd, balanceRemaining, inputTokens, outputTokens }) => {
      console.log(`Cost: $${costUsd}, remaining: $${balanceRemaining}`);
    },

    // Optional: interactive approval before payment
    onPaymentApproval: async ({ amountUsd, currentBalance }) => {
      // return 'crypto' to pay, 'fiat' for fiat flow, 'cancel' to abort
      return 'crypto';
    },
  },
});

Payment Options

const setu = createSetu({
  auth: { privateKey: '...' },
  payment: {
    // 'auto' (default) — pay automatically
    // 'approval' — call onPaymentApproval before each payment
    topupApprovalMode: 'auto',

    // Auto-pay without approval if wallet USDC balance >= threshold
    autoPayThresholdUsd: 5.0,

    // Max retries for a single API request (default: 3)
    maxRequestAttempts: 3,

    // Max total payment attempts per wallet (default: 20)
    maxPaymentAttempts: 20,
  },
});

Caching

Anthropic Cache Control

By default, the SDK automatically injects cache_control: { type: 'ephemeral' } on the first system block and the last message for Anthropic models. This saves ~90% on cached token costs.

// Default: auto caching (1 system + 1 message breakpoint)
createSetu({ auth });

// Disable completely
createSetu({ auth, cache: { anthropicCaching: false } });

// Manual: SDK won't inject cache_control — set it yourself in messages
createSetu({ auth, cache: { anthropicCaching: { strategy: 'manual' } } });

// Custom breakpoint count and placement
createSetu({
  auth,
  cache: {
    anthropicCaching: {
      systemBreakpoints: 2,       // cache first 2 system blocks
      systemPlacement: 'first',   // 'first' | 'last' | 'all'
      messageBreakpoints: 3,      // cache last 3 messages
      messagePlacement: 'last',   // 'first' | 'last' | 'all'
    },
  },
});

// Full custom transform
createSetu({
  auth,
  cache: {
    anthropicCaching: {
      strategy: 'custom',
      transform: (body) => {
        // modify body however you want
        return body;
      },
    },
  },
});

| Option | Default | Description | |---|---|---| | strategy | 'auto' | 'auto', 'manual', 'custom', or false | | systemBreakpoints | 1 | Number of system blocks to cache | | messageBreakpoints | 1 | Number of messages to cache | | systemPlacement | 'first' | Which system blocks: 'first', 'last', 'all' | | messagePlacement | 'last' | Which messages: 'first', 'last', 'all' | | cacheType | 'ephemeral' | The cache_control.type value |

Setu Server-Side Caching

Provider-agnostic caching at the Setu proxy layer:

createSetu({
  auth,
  cache: {
    promptCacheKey: 'my-session-123',
    promptCacheRetention: 'in_memory', // or '24h'
  },
});

OpenAI / Google

  • OpenAI: Automatic server-side prefix caching — no configuration needed
  • Google: Requires pre-uploaded cachedContent at the application level

Balance

// Setu account balance
const balance = await setu.balance();
// { walletAddress, balance, totalSpent, totalTopups, requestCount }

// On-chain USDC balance
const wallet = await setu.walletBalance('mainnet');
// { walletAddress, usdcBalance, network }

// Wallet address
console.log(setu.walletAddress);

Custom Providers

Register providers at init or runtime:

// At init
const setu = createSetu({
  auth,
  providers: [
    { id: 'my-provider', apiFormat: 'openai-chat', modelPrefix: 'myp-' },
  ],
});

// At runtime
setu.registry.register({
  id: 'another-provider',
  apiFormat: 'anthropic-messages',
  models: ['specific-model-id'],
});

// Map a specific model to a provider
setu.registry.mapModel('some-model', 'openai');

API Formats

| Format | Description | Used by | |---|---|---| | openai-responses | OpenAI Responses API | OpenAI | | anthropic-messages | Anthropic Messages API | Anthropic, MiniMax | | openai-chat | OpenAI Chat Completions (compatible) | Moonshot, Z.AI | | google-native | Google GenerativeAI native | Google |

Low-Level: Custom Fetch

Use the x402-aware fetch wrapper directly:

const customFetch = setu.fetch();

const response = await customFetch('https://api.setu.ottocode.io/v1/messages', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ model: 'claude-sonnet-4-20250514', messages: [...] }),
});

Standalone Utilities

import {
  fetchBalance,
  fetchWalletUsdcBalance,
  getPublicKeyFromPrivate,
  addAnthropicCacheControl,
  createSetuFetch,
} from '@ottocode/ai-sdk';

// Get wallet address from private key
const address = getPublicKeyFromPrivate(privateKey);

// Fetch balance without creating a full Setu instance
const balance = await fetchBalance({ privateKey });

// Fetch on-chain USDC
const usdc = await fetchWalletUsdcBalance({ privateKey }, 'mainnet');

// Create a standalone x402-aware fetch
const setuFetch = createSetuFetch({
  wallet: createWalletContext({ privateKey }),
  baseURL: 'https://api.setu.ottocode.io',
});

How It Works

  1. You call setu.model('claude-sonnet-4-20250514') — the SDK resolves this to Anthropic
  2. It creates an ai-sdk provider (@ai-sdk/anthropic) pointed at the Setu proxy
  3. A custom fetch wrapper intercepts all requests to:
    • Inject wallet auth headers (address, nonce, signature)
    • Inject Anthropic cache control (if enabled)
    • Handle 402 responses by signing USDC payments via x402
    • Sniff balance/cost info from SSE stream comments
  4. The Setu proxy verifies the wallet, checks balance, forwards to the real provider, tracks usage

Requirements

  • Solana wallet with USDC (for payments)
  • ai SDK v6+ as a peer dependency
  • Node.js 18+ or Bun

License

MIT