Package Exports
- @altsafe/aidirector
Readme
@altsafe/aidirector
Official TypeScript SDK for AI Director — the intelligent AI API gateway with automatic failover, response caching, and JSON extraction.
Features
- 🔐 HMAC Authentication — Secure request signing (Node.js & browser)
- ⚡ 10-minute Timeout — Handles long-running AI requests
- 🔄 Automatic Retries — Exponential backoff with configurable limits
- 📦 Structured Errors — Type-safe error handling
- 🌊 Streaming Support — Real-time response streaming
- 🎯 Full TypeScript — Complete type definitions
Installation
npm install @altsafe/aidirector
# or
bun add @altsafe/aidirector
# or
pnpm add @altsafe/aidirectorQuick Start
import { AIDirector } from '@altsafe/aidirector';
const client = new AIDirector({
secretKey: process.env.AIDIRECTOR_SECRET_KEY!,
baseUrl: 'https://your-api.example.com',
});
const result = await client.generate({
chainId: 'your-chain-id',
prompt: 'Generate 5 user profiles with name and email',
schema: { name: 'string', email: 'string' },
});
if (result.success) {
console.log('Users:', result.data.valid);
console.log('Model:', result.meta.modelUsed);
console.log('Cached:', result.meta.cached);
}Usage Examples
Next.js Server Actions
'use server';
import { AIDirector } from '@altsafe/aidirector';
const client = new AIDirector({
secretKey: process.env.AIDIRECTOR_SECRET_KEY!,
});
export async function generateContent(prompt: string) {
return client.generate({
chainId: process.env.DEFAULT_CHAIN_ID!,
prompt,
});
}API Routes
// app/api/generate/route.ts
import { NextResponse } from 'next/server';
import { AIDirector } from '@altsafe/aidirector';
const client = new AIDirector({
secretKey: process.env.AIDIRECTOR_SECRET_KEY!,
});
export async function POST(request: Request) {
const { prompt, chainId } = await request.json();
const result = await client.generate({ chainId, prompt });
return NextResponse.json(result);
}Streaming
await client.generateStream(
{
chainId: 'my-chain',
prompt: 'Write a long story...',
},
{
onChunk: (chunk) => process.stdout.write(chunk),
onComplete: (result) => console.log('\nDone!', result.meta),
onError: (error) => console.error('Error:', error),
}
);Error Handling
import {
AIDirector,
TimeoutError,
RateLimitError,
ValidationError,
isAIDirectorError,
isRetryableError,
} from '@altsafe/aidirector';
try {
const result = await client.generate({ chainId, prompt });
} catch (error) {
if (error instanceof TimeoutError) {
console.log('Request timed out after', error.timeoutMs, 'ms');
} else if (error instanceof RateLimitError) {
console.log('Rate limited, retry after', error.retryAfterMs, 'ms');
} else if (error instanceof ValidationError) {
console.log('Validation failed:', error.validationErrors);
} else if (isAIDirectorError(error)) {
console.log('AI Director error:', error.code, error.message);
// Check if we should retry
if (isRetryableError(error)) {
console.log('This error is retryable');
}
}
}API Reference
new AIDirector(config)
| Option | Type | Default | Description |
|---|---|---|---|
secretKey |
string |
— | Required. Your API secret key |
baseUrl |
string |
localhost:3000 |
API base URL |
timeout |
number |
600000 |
Request timeout (ms) |
maxRetries |
number |
3 |
Max retry attempts |
debug |
boolean |
false |
Enable console logging |
client.generate(options)
Generate content using your fallback chain.
| Option | Type | Required | Description |
|---|---|---|---|
chainId |
string |
Yes | Fallback chain ID |
prompt |
string |
Yes | Prompt to send |
schema |
object |
No | JSON schema for validation |
timeout |
number |
No | Override timeout for this request |
options.temperature |
number |
No | Randomness (0-2) |
options.maxTokens |
number |
No | Max output tokens |
options.topP |
number |
No | Nucleus sampling (0-1) |
options.topK |
number |
No | Top-K sampling |
options.systemPrompt |
string |
No | System prompt to prepend |
Returns: Promise<GenerateResult>
interface GenerateResult {
success: boolean;
data: {
valid: unknown[]; // Schema-compliant objects
invalid: unknown[]; // Failed validation but parsed
rawContent?: string; // Raw AI response
};
meta: {
cached: boolean;
modelUsed: string;
tokensUsed: { input: number; output: number };
latencyMs: number;
attemptedModels: string[];
finishReason?: string;
};
error?: {
code: string;
message: string;
retryable?: boolean;
};
}client.generateStream(options, callbacks)
Stream responses in real-time.
interface StreamCallbacks {
onChunk?: (chunk: string) => void;
onComplete?: (result: GenerateResult) => void;
onError?: (error: Error) => void;
onProgress?: (progress: StreamProgress) => void;
}client.listModels()
List all available AI models.
const models = await client.listModels();
// Returns: ModelInfo[]client.listChains()
Get your fallback chains (requires session auth).
const chains = await client.listChains();
// Returns: ChainInfo[]client.getUsage(options?)
Get usage statistics for your account.
const usage = await client.getUsage({
startDate: new Date('2024-01-01'),
endDate: new Date(),
});
// Returns: UsageStatsclient.health()
Health check to verify API connection.
const { ok, latencyMs, version } = await client.health();client.withConfig(overrides)
Create a new client with different configuration.
const debugClient = client.withConfig({ debug: true });
const fastClient = client.withConfig({ timeout: 30000 });Error Classes
| Error | Code | Retryable | Properties | Description |
|---|---|---|---|---|
ConfigurationError |
CONFIGURATION_ERROR |
No | — | Invalid client setup |
AuthenticationError |
AUTH_ERROR |
No | statusCode |
Invalid credentials |
RateLimitError |
RATE_LIMITED |
Yes | retryAfterMs |
Too many requests |
TimeoutError |
TIMEOUT |
Yes | timeoutMs |
Request timed out |
NetworkError |
NETWORK_ERROR |
Yes | originalError |
Connection failed |
ChainExecutionError |
CHAIN_FAILED |
No | attemptedModels |
All models failed |
ValidationError |
VALIDATION_ERROR |
No | validationErrors |
Schema validation failed |
ServerError |
SERVER_ERROR |
Yes | statusCode |
Internal server error |
Error Helpers
import { isAIDirectorError, isRetryableError } from '@altsafe/aidirector';
// Check if error is from AI Director
if (isAIDirectorError(error)) {
console.log(error.code, error.message);
}
// Check if error should be retried
if (isRetryableError(error)) {
// Implement retry logic
}Advanced: HMAC Utilities
For custom integrations, you can use the HMAC utilities directly:
import {
generateSignature,
getKeyPrefix,
isValidSecretKey
} from '@altsafe/aidirector';
// Validate a secret key format
if (isValidSecretKey(key)) {
console.log('Valid key');
}
// Get key prefix for headers
const prefix = getKeyPrefix(secretKey); // "aid_sk_xxxx"
// Generate signature for custom requests
const signature = await generateSignature(
secretKey,
'POST',
'/api/v1/generate',
JSON.stringify(body),
Date.now()
);TypeScript Types
All types are exported for your convenience:
import type {
// Configuration
AIDirectorConfig,
// Generation
GenerateOptions,
GenerateResult,
GenerateData,
GenerateMeta,
GenerateError,
GenerationParameters,
TokenUsage,
// Streaming
StreamCallbacks,
StreamProgress,
// Chains & Models
ChainInfo,
ChainStep,
ModelInfo,
// Usage & Health
UsageStats,
HealthResult,
} from '@altsafe/aidirector';Security
⚠️ Server-side only! Never expose your secret key to browsers.
- ✅ Next.js API routes / Server Actions
- ✅ Express.js / Fastify
- ✅ Angular Universal (SSR)
- ✅ Edge Functions (Vercel, Cloudflare)
- ❌ Client-side JavaScript
Store your secret key in environment variables:
AIDIRECTOR_SECRET_KEY=aid_sk_your_secret_key_hereLicense
MIT © altsafe