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
AllPerfError instances have these properties:
| Property | Type | Description |
|---|---|---|
code | string | Machine-readable error code |
message | string | Human-readable description |
status | number | HTTP status code |
requestId | string | Unique request ID for debugging |
isRetryable | boolean | Whether 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, john@example.com, 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); // "john@example.com"
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
- npm: @perf_technology/sdk
- Documentation: docs.withperf.pro
- Email: support@withperf.pro