gateforge-sdk
v0.1.1
Published
Transparent LLM observability proxy for TypeScript/Node.js — automatic token tracking, latency metrics, and cost visibility with zero API changes.
Maintainers
Readme
GateForge SDK for TypeScript/JavaScript
Transparent LLM observability proxy — automatic token tracking, latency metrics, and cost visibility with zero changes to your existing API calls.
Installation
npm install gateforge-sdk
# or
pnpm add gateforge-sdkQuick Start
import { GoogleGenAI } from "@google/genai";
import { wrapAiClient } from "gateforge-sdk";
const ai = wrapAiClient(
new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY }),
process.env.GATEFORGE_API_KEY ?? "",
);
// Use exactly as before — all params and return types are unchanged
const response = await ai.models.generateContent({
model: "gemini-2.5-flash",
contents: [{ role: "user", parts: [{ text: "Hello!" }] }],
});
// Streaming works identically
const stream = await ai.models.generateContentStream({
model: "gemini-2.5-flash",
contents: [{ role: "user", parts: [{ text: "Tell me a story" }] }],
});
for await (const chunk of stream) {
process.stdout.write(chunk.text ?? "");
}
// ↑ After the stream ends, metrics are sent to GateForge automaticallyHow It Works
The SDK wraps your AI client with a transparent JavaScript Proxy:
generateContent→ response passes through unchanged;usageMetadatais capturedgenerateContentStream→ async generator yields every chunk unchanged;usageMetadatafrom the last chunk is captured- All other methods (caches, files, etc.) pass through untouched
- Metrics are sent fire-and-forget with a 3-second timeout — never blocks, never throws
If GATEFORGE_API_KEY is empty the proxy is a no-op and returns the original client.
Manual Tracking
For operations outside the LLM call (tool execution, PII detection, etc.):
import { trackMetrics } from "gateforge-sdk";
trackMetrics(process.env.GATEFORGE_API_KEY!, {
category: "tool",
model: "gemini-2.5-flash",
toolName: "search_documents",
promptTokens: 0,
completionTokens: 0,
latencyMs: 240,
conversationId: "conv_abc123",
});Per-call Context
Inject conversation IDs and iteration numbers via getContext:
import { AsyncLocalStorage } from "async_hooks";
const store = new AsyncLocalStorage<{ conversationId: string }>();
const ai = wrapAiClient(rawAi, apiKey, {
getContext: () => ({
conversationId: store.getStore()?.conversationId,
category: "reasoning",
}),
});PII Utilities
import { detectAndAnonymizePII, rehydratePII } from "gateforge-sdk";
const { sanitized, entities } = detectAndAnonymizePII(
"Contact [email protected] at 555-0100"
);
// sanitized: "Contact [EMAIL_001] at [PHONE_NUMBER_002]"
const original = rehydratePII(response, entities);Requirements
- Node.js >= 18
- Works with any AI client that implements
.models.generateContent[Stream]()
