JavaScript / TypeScript SDK (gavio)
npm package
gavio· Node 18+ · TypeScript · dual ESM + CJS · zero runtime deps
Source: packages/gavio-js.
Install
npm install gavio # or: pnpm add gavio · yarn add gavio · bun add gavioShips full type definitions — no @types/gavio needed.
Gateway API
Object config + a fluent .use() / .withAdapter() chain. Everything is async (Promise-based).
import { Gateway } from 'gavio'
import { piiGuard } from 'gavio/interceptors/pii'
const gw = new Gateway({ provider: 'anthropic', model: 'claude-sonnet-4-6' })
.use(piiGuard({ sensitivity: 'strict' }))
const r = await gw.complete({
messages: [{ role: 'user', content: 'Hello' }],
agentId: 'my-agent',
parentTraceId: null, // set for multi-agent DAG tracing
sessionId: 'sess-123',
options: { temperature: 0.7, maxTokens: 1000 },
})
r.content // string, PII restored
r.costUsd // number
r.traceId // UUID v7
r.usage.totalTokens
r.interceptorsFired // string[]
r.audit // AuditRecordConstructor options: { provider, model, devMode, dryRun }. Chain methods: .use(interceptor), .withAdapter(adapter).
devMode: true→ mock provider + stdout audit auto-wired.dryRun: true→ interceptors log but never modify/block.
Sub-path imports
Import only what you use (tree-shakeable):
import { Gateway } from 'gavio'
import { piiGuard } from 'gavio/interceptors/pii'
import { emailScanner } from 'gavio/interceptors/pii/scanners'
import { auditInterceptor } from 'gavio/interceptors/audit'
import { stdoutSink } from 'gavio/interceptors/audit/sinks'
import { retryInterceptor, timeoutPolicy, fallbackChain } from 'gavio/interceptors/reliability'
import { anthropicAdapter, openaiAdapter } from 'gavio/providers'
import { GavioTestKit, mockProvider } from 'gavio/testing'Interceptors
Interceptors are factory functions returning an interceptor object:
import { piiGuard } from 'gavio/interceptors/pii'
import { auditInterceptor } from 'gavio/interceptors/audit'
import { retryInterceptor, timeoutPolicy } from 'gavio/interceptors/reliability'
const gw = new Gateway({ provider: 'anthropic', model: 'claude-sonnet-4-6' })
.use(auditInterceptor({ sink: 'stdout' })) // outermost
.use(piiGuard({ sensitivity: 'strict', mode: 'redact' }))
.use(timeoutPolicy({ timeoutMs: 30_000 }))
.use(retryInterceptor({ maxAttempts: 3, baseDelayMs: 500, jitter: true }))piiGuard options: scanners, sensitivity, mode ('redact' | 'mask' | 'tag' | 'block'), restoreOnResponse, logEntityTypes, dryRun. See interceptors.md.
Providers
| Provider | provider: | Env var |
|---|---|---|
| Anthropic | 'anthropic' | ANTHROPIC_API_KEY |
| OpenAI | 'openai' | OPENAI_API_KEY |
| Gemini | 'gemini' | GEMINI_API_KEY |
| Azure OpenAI | 'azure_openai' | AZURE_OPENAI_API_KEY + AZURE_OPENAI_ENDPOINT |
| Ollama | 'ollama' | — (local; OLLAMA_HOST) |
| Mock | dev mode / mockProvider() | — |
Gemini, Azure OpenAI, and Ollama were added in v0.2.0.
import { anthropicAdapter } from 'gavio/providers/anthropic'
const gw = new Gateway().withAdapter(anthropicAdapter({ apiKey: process.env.ANTHROPIC_API_KEY, timeoutMs: 30_000 }))Adapters use native fetch — no node-fetch or vendor SDK.
Inspector
Enable the embedded pipeline visualizer (F-DX-09/10, off by default) and open http://127.0.0.1:7411 — live traces, waterfalls, PII diffs, agent call graphs, replay, stats. Full guide: Inspector.
const gw = new Gateway({ devMode: true, inspect: true })Embeddings
gw.embed({ texts }) (F-SEC-10, since v0.9.0) runs embedding inputs through the same interceptor pipeline as completions — PII is scanned and redacted before the provider's embedding API is called; one vector per input in r.embeddings.
Testing
GavioTestKit + mockProvider (works with any runner; examples use vitest):
import { describe, it, expect } from 'vitest'
import { GavioTestKit, mockProvider } from 'gavio/testing'
import { piiGuard } from 'gavio/interceptors/pii'
it('redacts and restores', async () => {
const kit = new GavioTestKit({
interceptors: [piiGuard()],
provider: mockProvider({ response: 'done [EMAIL_1]' }),
})
const r = await kit.run({ messages: [{ role: 'user', content: 'to jan@example.com' }] })
expect(kit.preRequestText()).not.toContain('jan@example.com')
expect(kit.piiDetected('EMAIL')).toBe(true)
expect(r.content).toBe('done jan@example.com')
})cd packages/gavio-js
npm ci
npm run typecheck # tsc --noEmit (strict)
npm test # vitest, incl. shared cross-SDK vectors
npm run build # dual ESM+CJS build → dist/Module format & runtimes
- Dual build:
import 'gavio'(ESM) andrequire('gavio')(CJS) both work via theexportsmap; type defs resolve per sub-path. - Runtimes: Node 18+ (primary), Deno 1.40+, Bun 1.0+. Cloudflare Workers / Vercel Edge run the core (fetch-based, no Node-only APIs).
- Uses
node:cryptofor SHA-256 audit hashes and monotonic UUID v7.