@billama/sdk
v1.0.5
Published
Official TypeScript/JavaScript SDK for Billama: Universal AI compute grid, billing clearinghouse, and streaming API.
Downloads
553
Maintainers
Readme
@billama/sdk
The official TypeScript/JavaScript SDK for Billama — the universal decentralized AI compute grid, billing clearinghouse, and streaming gateway.
Features
- ⚡ Universal Runtime: Pure ESM and CJS support with zero heavy dependencies. Operates seamlessly in Node.js 18+, Bun, Deno, Next.js (App Router & Edge runtime), Cloudflare Workers, and modern browsers.
- 🤖 Wire-Compatible AI: Direct streaming chat completions compatible with OpenAI and Ollama formats, plus automated Bifrost routing and NeMo Switchyard dynamic model cascading.
- 📊 Telemetry Headers: Built-in parsing of custom Billama response headers (
x-billama-model,x-billama-prompt-tokens,x-billama-completion-tokens,x-billama-cost-savings,x-billama-route-target). - 💳 Centralized Billing Clearinghouse: Query ledger balances in micro-dollars (
$0.0001precision), create checkout sessions, record application metered feature usage, and verify HMAC-SHA256 processor webhooks. - 🎨 RenderGrid & Batch Compute: Submit long-running background tasks for 3D Blender rendering, batch embeddings, vision inference, and audio stem separation.
- 🛡️ Built-in Route Guards: Turnkey middleware for Next.js App Router and Express to enforce wallet balances and prevent over-quota execution.
- ⚛️ React Ready: Optional
@billama/sdk/reactpackage with hooks (useBillamaBalance,useBillamaChat) and<BillamaProvider />.
Installation
# pnpm
pnpm add @billama/sdk
# npm
npm install @billama/sdk
# yarn
yarn add @billama/sdkQuickstart
1. Initialize the Client
import { Billama } from "@billama/sdk";
export const billama = new Billama({
apiKey: process.env.BILLAMA_API_KEY, // Default: process.env.BILLAMA_API_KEY ("blm_live_...")
baseUrl: process.env.BILLAMA_BASE_URL || "https://api.billama.net",
organizationId: process.env.BILLAMA_ORG_ID, // Optional default organization
});2. Streaming Chat Completions
const stream = await billama.chat.completions.create({
model: "llama3.3:70b", // Or "auto" for dynamic Bifrost cost/quality routing
messages: [
{ role: "system", content: "You are an expert grant reviewer." },
{ role: "user", content: "Draft an executive summary for our clean energy proposal." },
],
budgetCapUsd: 0.05, // Optional: abort if stream exceeds $0.05
stream: true,
});
for await (const chunk of stream) {
const token = chunk.choices[0]?.delta?.content;
if (token) process.stdout.write(token);
// Inspect Billama dynamic routing telemetry
if (chunk.billamaTelemetry) {
// { model: 'llama3.3:70b', routeTarget: 'SWITCHYARD_BIFROST', costSavings: '74%' }
}
}3. Generate Vector Embeddings
const response = await billama.embeddings.create({
model: "bge-m3",
input: "Federal Uniform Guidance 2 CFR 200 Subpart E cost principles",
});
const vector = response.data[0].embedding; // 1536-dimensional array4. Universal Ledger & Application Billing
Query wallet balances, initiate deposits, or record metered feature quotas:
// 1. Get current balance
const balance = await billama.billing.getBalance();
console.log(`Available Balance: $${balance.balance.toFixed(4)} ${balance.currency}`);
// 2. Create payment or subscription checkout session
const session = await billama.billing.createCheckoutSession({
mode: "subscription",
returnUrl: "https://myapp.com/billing/success",
lineItems: [
{ name: "Pro Plan", amountUsd: 19.99, quantity: 1 }
],
metadata: { userId: "usr_123" }
});
console.log(`Redirect user to: ${session.url}`);
// 3. Record metered application usage (e.g. FitDjinn, Ironclad Grants)
await billama.billing.recordUsage({
appId: "ironclad",
featureKey: "grant_drafts",
quantity: 1,
customerId: "cust_456",
idempotencyKey: "draft_uuid_789"
});5. Webhook Signature Verification
Zero-trust HMAC-SHA256 webhook validation:
import { billama } from "./billama";
export async function POST(req: Request) {
const rawBody = await req.text();
const signature = req.headers.get("x-billama-signature");
const secret = process.env.BILLAMA_WEBHOOK_SECRET!;
try {
const event = await billama.webhooks.constructEvent(rawBody, signature, secret);
if (event.event === "payment.succeeded") {
console.log(`Deposit confirmed for payment: ${event.data.paymentId}`);
}
return new Response(JSON.stringify({ received: true }), { status: 200 });
} catch (err) {
return new Response("Invalid webhook signature", { status: 400 });
}
}6. RenderGrid & Batch Compute Jobs
Submit asynchronous compute jobs for Blender rendering, audio stem separation, or vision ML:
const job = await billama.jobs.submit({
jobType: "AUDIO_SEPARATION",
payload: {
audioUrl: "https://seaweedfs.local/stems/recording.wav",
stems: ["vocals", "drums", "bass", "other"]
}
});
console.log(`Job submitted: ${job.id}, Status: ${job.status}`);
// Poll or query status
const status = await billama.jobs.get(job.id);7. Next.js App Router Balance Guard
Prevent downstream API invocation if an organization’s balance is depleted:
import { billama } from "@/lib/billama";
import { createBalanceGuard } from "@billama/sdk";
const requireCredit = createBalanceGuard(billama, 0.02); // Require at least $0.02
export async function POST(req: Request) {
await requireCredit(); // Throws InsufficientBalanceError (402) if depleted
// Execute AI generation...
}8. React Hooks (@billama/sdk/react)
import { BillamaProvider, useBillamaBalance, useBillamaChat } from "@billama/sdk/react";
function App() {
return (
<BillamaProvider options={{ apiKey: "blm_live_..." }}>
<BillingDashboard />
<AICopilot />
</BillamaProvider>
);
}
function BillingDashboard() {
const { balance, loading, error, refresh } = useBillamaBalance();
if (loading) return <div>Loading balance...</div>;
return <div>Balance: ${balance?.balance.toFixed(4)}</div>;
}
function AICopilot() {
const { messages, sendMessage, isStreaming } = useBillamaChat({
model: "llama3.3:70b"
});
return (
<div>
{messages.map((m, idx) => (
<p key={idx}><strong>{m.role}:</strong> {m.content}</p>
))}
<button disabled={isStreaming} onClick={() => sendMessage("Generate workout plan")}>
Ask Djinn
</button>
</div>
);
}Publishing to npm
To publish this package under your registered organization scope:
# 1. Login to npm if not already authenticated
npm login
# 2. Run automated tests and build
pnpm run prepublishOnly
# 3. Publish to npm under public access
pnpm publish --access publicLicense
MIT © billamabilling
