Skip to main content

JavaScript SDK

The official Perf SDK for JavaScript and TypeScript provides a type-safe, feature-rich client for the Perf API with streaming support, automatic retries, and comprehensive error handling.

Installation

npm install @perf_technology/sdk
# or
yarn add @perf_technology/sdk
# or
pnpm add @perf_technology/sdk

Quick Start

import { PerfClient } from '@perf_technology/sdk';

const client = new PerfClient({
  apiKey: 'pk_live_your_key_here',
});

// Simple chat completion
const response = await client.chat({
  messages: [{ role: 'user', content: 'Hello, world!' }],
  maxCostPerCall: 0.01,
});

console.log(response.output);
console.log(`Cost: $${response.billing.costUsd}`);
console.log(`Model: ${response.modelUsed}`);

Configuration

const client = new PerfClient({
  apiKey: 'pk_live_xxx',           // Required: Your API key
  baseUrl: 'https://api.withperf.pro', // Optional: Custom base URL
  timeout: 30000,                  // Optional: Request timeout in ms (default: 30000)
  maxRetries: 3,                   // Optional: Max retry attempts (default: 3)
});

Chat Completions

Basic Request

const response = await client.chat({
  messages: [
    { role: 'system', content: 'You are a helpful assistant.' },
    { role: 'user', content: 'What is the capital of France?' }
  ],
});

console.log(response.output); // "The capital of France is Paris."

With Cost Control

const response = await client.chat({
  messages: [{ role: 'user', content: 'Explain quantum computing' }],
  maxCostPerCall: 0.005,  // Maximum 0.5 cents
});

if (response.billing.costWarning) {
  console.log('Cost exceeded budget, cheaper model was used');
}

Request Options

const response = await client.chat({
  messages: [{ role: 'user', content: 'Generate a haiku' }],

  // Cost control
  maxCostPerCall: 0.01,

  // Generation parameters
  temperature: 0.7,
  maxTokens: 500,
  topP: 0.9,
  frequencyPenalty: 0.5,
  presencePenalty: 0.5,
  stop: ['\n\n'],

  // Output format
  responseFormat: 'json',

  // Tracking
  userId: 'user_123',
  metadata: {
    sessionId: 'sess_abc',
    feature: 'chat',
  },
});

Streaming

Stream responses for real-time output:
const stream = await client.chatStream({
  messages: [{ role: 'user', content: 'Write a short story' }],
});

for await (const chunk of stream) {
  if (chunk.done) {
    // Final chunk with metadata
    console.log(`\nModel: ${chunk.modelUsed}`);
    console.log(`Cost: $${chunk.billing.costUsd}`);
  } else {
    // Content chunk
    process.stdout.write(chunk.chunk);
  }
}

Stream to String Helper

const content = await client.chatStreamToString({
  messages: [{ role: 'user', content: 'Tell me a joke' }],
});

console.log(content);

Error Handling

The SDK provides typed error classes for different error scenarios:
import {
  PerfClient,
  PerfError,
  AuthenticationError,
  RateLimitError,
  ValidationError,
  ServerError,
} from '@perf_technology/sdk';

try {
  const response = await client.chat({
    messages: [{ role: 'user', content: 'Hello' }],
  });
} catch (error) {
  if (error instanceof RateLimitError) {
    console.log(`Rate limited. Retry after ${error.retryAfter}s`);
    // Wait and retry
  } else if (error instanceof AuthenticationError) {
    console.error('Invalid API key');
    // Don't retry - fix the API key
  } else if (error instanceof ValidationError) {
    console.error(`Invalid request: ${error.message}`);
    // Fix the request parameters
  } else if (error instanceof ServerError) {
    console.error('Server error - will auto-retry');
    // SDK will automatically retry
  } else if (error instanceof PerfError) {
    console.error(`Error: ${error.code} - ${error.message}`);

    if (error.isRetryable) {
      // Safe to retry
    }
  }
}

Error Properties

All PerfError instances have these properties:
PropertyTypeDescription
codestringMachine-readable error code
messagestringHuman-readable description
statusnumberHTTP status code
requestIdstringUnique request ID for debugging
isRetryablebooleanWhether safe to retry

Rate Limit Error

if (error instanceof RateLimitError) {
  console.log(error.retryAfter);  // Seconds to wait
  console.log(error.limit);       // Rate limit ceiling
  console.log(error.remaining);   // Remaining requests
  console.log(error.reset);       // Unix timestamp when limit resets
}

TypeScript Support

The SDK is written in TypeScript and exports all types:
import type {
  ChatRequest,
  ChatResponse,
  Message,
  StreamChunk,
  PerfClientOptions,
} from '@perf_technology/sdk';

const request: ChatRequest = {
  messages: [{ role: 'user', content: 'Hello' }],
  maxCostPerCall: 0.01,
};

Response Types

ChatResponse

interface ChatResponse {
  modelUsed: string;
  output: string;
  billing: {
    costUsd: number;
    costWarning: boolean;
  };
  tokens: {
    input: number;
    output: number;
    total: number;
  };
  metadata: {
    callId: string;
    taskType: string;
    complexityScore: number;
    routingReason: string;
    latencyMs: number;
    fallbackUsed: boolean;
    validationPassed: boolean;
    timestamp: string;
  };
}

StreamChunk

// Content chunk
interface ContentChunk {
  chunk: string;
  done: false;
}

// Final chunk
interface FinalChunk {
  chunk: '';
  done: true;
  modelUsed: string;
  billing: { costUsd: number };
  tokens: { input: number; output: number; total: number };
  metadata: { /* ... */ };
}

Examples

Multi-turn Conversation

const messages = [
  { role: 'user', content: 'What is 2+2?' },
];

const response1 = await client.chat({ messages });
console.log(response1.output); // "4"

messages.push({ role: 'assistant', content: response1.output });
messages.push({ role: 'user', content: 'Multiply that by 3' });

const response2 = await client.chat({ messages });
console.log(response2.output); // "12"

JSON Output

const response = await client.chat({
  messages: [{
    role: 'user',
    content: 'Extract: John Smith, [email protected], 555-1234. Return JSON with name, email, phone.'
  }],
  responseFormat: 'json',
  temperature: 0.2,
});

const data = JSON.parse(response.output);
console.log(data.name);  // "John Smith"
console.log(data.email); // "[email protected]"

React Hook Example

import { useState, useCallback } from 'react';
import { PerfClient } from '@perf_technology/sdk';

const client = new PerfClient({ apiKey: process.env.PERF_API_KEY });

export function useChat() {
  const [messages, setMessages] = useState([]);
  const [isLoading, setIsLoading] = useState(false);

  const sendMessage = useCallback(async (content: string) => {
    const userMessage = { role: 'user', content };
    setMessages(prev => [...prev, userMessage]);
    setIsLoading(true);

    try {
      const response = await client.chat({
        messages: [...messages, userMessage],
      });

      setMessages(prev => [
        ...prev,
        { role: 'assistant', content: response.output }
      ]);
    } finally {
      setIsLoading(false);
    }
  }, [messages]);

  return { messages, sendMessage, isLoading };
}

Requirements

  • Node.js 18.0.0 or higher
  • TypeScript 5.0+ (for TypeScript users)

Support