zorvyn
v1.1.2
Published
A production-ready, modular AI SDK for Node.js and TypeScript applications
Maintainers
Readme
zorvyn
A production-ready, modular AI SDK for Node.js and TypeScript
Features
- 🔌 Pluggable providers — swap OpenAI for any LLM with zero core changes
- 🧩 Composable middleware — logging, caching, retry in a clean pipeline
- 💬 Conversation memory — rolling in-memory history management
- 🌊 Streaming — first-class
AsyncGeneratorstreaming API - 🛡️ Strict TypeScript — full type safety + generated
.d.tsdeclarations - 🖥️ CLI tool —
npx zorvyn ask "your prompt"from any terminal - ✅ Tested — Jest unit tests with full coverage
Installation
npm install zorvynSet your API key:
cp .env.example .env
# Edit .env and set OPENAI_API_KEY=sk-...Quick Start
import { AIClient } from 'zorvyn';
import { OpenAIProvider } from 'zorvyn/providers';
import { LoggingMiddleware, RetryMiddleware } from 'zorvyn/middleware';
const client = new AIClient({
provider: new OpenAIProvider({ apiKey: process.env.OPENAI_API_KEY }),
middleware: [
new LoggingMiddleware({ level: 'info' }),
new RetryMiddleware({ maxRetries: 3 }),
],
defaults: { model: 'gpt-4o', temperature: 0.7 },
});
// Single-turn
const response = await client.ask('Explain closures in JavaScript.');
console.log(response.content);
// Multi-turn chat
const response2 = await client.chat([
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'What is TypeScript?' },
]);
// Streaming
for await (const chunk of client.stream('Write a haiku about coding.')) {
process.stdout.write(chunk.delta);
}Conversation Memory
import { AIClient, ConversationMemory } from 'zorvyn';
const memory = new ConversationMemory({ maxTurns: 20, systemPrompt: 'Be concise.' });
const client = new AIClient({ provider });
async function chat(userInput: string): Promise<string> {
const messages = memory.buildNextMessages(userInput);
const response = await client.chat(messages);
memory.addTurn(
{ role: 'user', content: userInput },
{ role: 'assistant', content: response.content },
);
return response.content;
}Middleware System
Middleware is composable and runs in order (outer → inner):
import { CachingMiddleware, LoggingMiddleware, RetryMiddleware } from 'zorvyn/middleware';
const client = new AIClient({
provider,
middleware: [
new LoggingMiddleware({ level: 'info' }), // outermost — sees all events
new CachingMiddleware({ ttlSeconds: 60 }), // serves cached responses
new RetryMiddleware({ maxRetries: 3 }), // innermost — closest to provider
],
});Writing Custom Middleware
import type { IMiddleware, MiddlewareContext, MiddlewareNext, MiddlewareResult } from 'zorvyn';
export class MetricsMiddleware implements IMiddleware {
readonly name = 'MetricsMiddleware';
async execute(context: MiddlewareContext, next: MiddlewareNext): Promise<MiddlewareResult> {
const start = Date.now();
const result = await next(context);
const duration = Date.now() - start;
myMetricsService.record({ duration, provider: context.providerName });
return result;
}
}Writing a Custom Provider
import { BaseProvider } from 'zorvyn/providers';
import type { AIResponse, ChatMessage, AskOptions, ChatOptions, StreamOptions, StreamChunk } from 'zorvyn';
export class AnthropicProvider extends BaseProvider {
readonly name = 'anthropic';
readonly defaultModel = 'claude-3-opus-20240229';
protected async doAsk(prompt: string, options: AskOptions): Promise<AIResponse> {
// Call Anthropic API here...
}
protected async doChat(messages: ChatMessage[], options: ChatOptions): Promise<AIResponse> {
// ...
}
protected async *doStream(prompt: string, options: StreamOptions): AsyncGenerator<StreamChunk> {
// ...
}
protected async checkApiKey(): Promise<boolean> {
return true; // validate key with a lightweight API call
}
}CLI Usage
# Single question
npx zorvyn ask "What is the capital of France?"
# Streaming output
npx zorvyn ask "Write a short poem" --stream
# With options
npx zorvyn ask "Explain recursion" --model gpt-4o --temperature 0.3
# Interactive chat session
npx zorvyn chat --system "You are a Socratic tutor."
# Validate API key
npx zorvyn validateEnvironment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| OPENAI_API_KEY | — | Your OpenAI API key |
| ZORVYN_DEFAULT_PROVIDER | openai | Active provider |
| ZORVYN_DEFAULT_MODEL | gpt-4o | Default model |
| ZORVYN_TIMEOUT_MS | 30000 | Request timeout |
| ZORVYN_MAX_RETRIES | 3 | Retry attempts |
| ZORVYN_RATE_LIMIT_RPM | 60 | Max requests/minute |
| ZORVYN_CACHE_ENABLED | true | Enable response cache |
| ZORVYN_CACHE_TTL_SECONDS | 300 | Cache TTL |
| ZORVYN_LOG_LEVEL | info | debug\|info\|warn\|error\|silent |
API Reference
AIClient
| Method | Signature | Description |
|--------|-----------|-------------|
| ask | (prompt: string, opts?: AskOptions) => Promise<AIResponse> | Single-turn completion |
| chat | (messages: ChatMessage[], opts?: ChatOptions) => Promise<AIResponse> | Multi-turn completion |
| stream | (prompt: string, opts?: StreamOptions) => AsyncGenerator<StreamChunk> | Streaming completion |
| validateProvider | () => Promise<boolean> | Validate API key |
AIResponse
interface AIResponse {
content: string; // the generated text
model: string; // model used
finishReason: string; // 'stop' | 'length' | ...
usage: TokenUsage; // { promptTokens, completionTokens, totalTokens }
latencyMs: number; // request round-trip time
provider: string; // provider name
createdAt: string; // ISO timestamp
}Development
# Install dependencies
npm install
# Build
npm run build
# Run tests
npm test
# Watch mode
npm run test:watch
npm run build:watchProject Structure
zorvyn/
├── src/
│ ├── index.ts # Public API entrypoint
│ ├── client/
│ │ └── AIClient.ts # Core client class
│ ├── providers/
│ │ ├── BaseProvider.ts # Abstract provider contract
│ │ ├── OpenAIProvider.ts # OpenAI implementation
│ │ └── MockProvider.ts # In-memory mock for testing
│ ├── middleware/
│ │ ├── MiddlewareEngine.ts
│ │ ├── LoggingMiddleware.ts
│ │ ├── CachingMiddleware.ts
│ │ └── RetryMiddleware.ts
│ ├── features/
│ │ ├── ChatFormatter.ts
│ │ ├── ConversationMemory.ts
│ │ └── StreamHandler.ts
│ ├── errors/ # Typed error hierarchy
│ ├── utils/ # Env, validation, rate limiter
│ ├── types/ # Shared TypeScript interfaces
│ └── cli/ # CLI tool (bin: zorvyn)
├── tests/ # Jest unit tests
├── package.json
└── tsconfig.jsonLicense
MIT © zorvyn contributors
