@smarthivelabs-devs/ai-nexus
v1.4.0
Published
Official Node.js SDK for the SmartHive AI Nexus API
Downloads
732
Readme
AI Nexus Node SDK
The official TypeScript / Node.js SDK for AI Nexus — SmartHive's unified AI gateway.
One API. Every capability. Zero provider lock-in.
npm install @smarthivelabs-devs/ai-nexusOverview
AI Nexus routes your requests through an intelligent layer of named model profiles. You call aeon, prism, or any profile you configure — the gateway handles routing, failover, and orchestration transparently.
Capabilities available through this SDK:
- Chat & reasoning (including streaming, tool calling, vision, extended thinking)
- Image generation (async with job polling)
- Video generation & understanding
- Speech synthesis & transcription
- Embeddings & semantic search
- Document ingestion & retrieval (RAG)
- Text translation
- Content moderation
- Realtime voice sessions (WebRTC)
- Agent execution (stateful, multi-turn)
Quick start
import { AiNexus } from "@smarthivelabs-devs/ai-nexus";
const nexus = new AiNexus({ apiKey: process.env.AI_NEXUS_API_KEY! });
const response = await nexus.chat.create({
model: "aeon",
messages: [{ role: "user", content: "What is the SmartHive AI Nexus?" }],
});
console.log(response.choices[0].message.content);Environment variables
AI_NEXUS_API_KEY=nxs_your_key_here
AI_NEXUS_BASE_URL=https://ai-nexus-core.smarthivelabs.dev # optionalClient configuration
const nexus = new AiNexus({
apiKey: process.env.AI_NEXUS_API_KEY!,
baseUrl: "https://ai-nexus-core.smarthivelabs.dev", // default
maxRetries: 2, // default
timeout: 30_000, // default (ms)
defaultHeaders: { "x-app-id": "my-app" },
});Per-request overrides — withOptions() returns a fresh client without mutating the original:
const response = await nexus
.withOptions({ timeout: 60_000 })
.chat.create({ model: "aeon-pro", messages: [...] });Canonical model profiles
| Profile slug | Capability | Notes |
|---|---|---|
| aeon | chat | Flagship balanced model |
| aeon-swift | chat | Optimised for low latency |
| aeon-pro | chat | Maximum reasoning depth |
| aeon-lite | chat | Lightweight, cost-efficient |
| solaris | chat | High-quality mid-tier |
| prism | chat | Gemini-powered alternative |
| prism-pro | vision | Understands images |
| weave | embeddings | Fast semantic search vectors |
| weave-pro | embeddings | High-dimensional embeddings |
| lux | image_generation | Text-to-image (DALL-E 3) |
| lux-ultra | image_generation | Premium image generation |
| iris | transcribe | Speech-to-text (Whisper) |
| iris-turbo | transcribe | Fast speech-to-text |
| echo | speak | Text-to-speech (ElevenLabs) |
| echo-swift | speak | Fast text-to-speech |
| babel | translate | Natural language translation |
| flux | video_generation | Text-to-video |
| flux-pro | video_generation | Premium video generation |
| rift | video_understanding | Video analysis & Q&A |
Custom profiles can be created in the AI Nexus admin panel and used by slug.
Chat
Blocking response
const response = await nexus.chat.create({
model: "aeon",
messages: [
{ role: "system", content: "You are a concise assistant." },
{ role: "user", content: "Explain quantum entanglement in one paragraph." },
],
temperature: 0.7,
max_tokens: 500,
});
console.log(response.choices[0].message.content);
console.log(response.usage); // { prompt_tokens, completion_tokens, total_tokens }Streaming response
const stream = await nexus.chat.create({
model: "aeon",
messages: [{ role: "user", content: "Tell me a story." }],
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta.content ?? "");
}Vision (image input)
const response = await nexus.chat.create({
model: "prism-pro",
messages: [
{
role: "user",
content: [
{ type: "image_url", image_url: { url: "https://example.com/diagram.png" } },
{ type: "text", text: "Describe what you see in this diagram." },
],
},
],
});Extended thinking
Enable extended reasoning for supported models (Anthropic extended thinking, OpenAI o-series). The model reasons silently before responding, producing higher-quality answers for complex problems.
const response = await nexus.chat.create({
model: "aeon-pro",
messages: [{ role: "user", content: "Design a distributed rate-limiting system." }],
thinking: {
type: "enabled",
budget_tokens: 8000, // how many tokens the model can spend thinking
},
});
console.log(response.choices[0].message.content);
console.log(response.usage.thinking_tokens); // tokens used for reasoningFor OpenAI o-series models, use reasoning_effort instead:
const response = await nexus.chat.create({
model: "your-o3-profile",
messages: [{ role: "user", content: "Prove the fundamental theorem of calculus." }],
thinking: { reasoning_effort: "high" },
});Streaming with thinking
Thinking content streams before the response. Check delta.thinking to capture reasoning as it arrives:
const stream = await nexus.chat.create({
model: "aeon-pro",
messages: [{ role: "user", content: "What is the optimal strategy here?" }],
stream: true,
thinking: { type: "enabled", budget_tokens: 5000 },
});
for await (const chunk of stream) {
const delta = chunk.choices[0]?.delta;
if (delta.thinking) process.stdout.write(`[thinking] ${delta.thinking}`);
if (delta.content) process.stdout.write(delta.content);
}Tool calling
const response = await nexus.chat.create({
model: "aeon",
messages: [{ role: "user", content: "What is the weather in London?" }],
tools: [
{
type: "function",
function: {
name: "get_weather",
description: "Get current weather for a city",
parameters: {
type: "object",
properties: { city: { type: "string" } },
required: ["city"],
},
},
},
],
tool_choice: "auto",
});
const toolCall = response.choices[0].message.tool_calls?.[0];
if (toolCall) {
const args = JSON.parse(toolCall.function.arguments);
// call your weather function with args.city ...
}Multi-turn conversation
const messages = [
{ role: "user" as const, content: "My name is Alex." },
];
const r1 = await nexus.chat.create({ model: "aeon", messages });
messages.push(r1.choices[0].message);
messages.push({ role: "user", content: "What is my name?" });
const r2 = await nexus.chat.create({ model: "aeon", messages });
console.log(r2.choices[0].message.content); // "Your name is Alex."RAG — knowledge base context
Pass knowledgeBaseId to automatically inject retrieved context into the prompt server-side:
const response = await nexus.chat.create({
model: "aeon",
messages: [{ role: "user", content: "What is our refund policy?" }],
knowledgeBaseId: "kb_abc123",
});Fallback model profiles
Pass fallbackModels to any capability call. If the primary profile fails (provider outage, rate-limit, etc.), the service retries each slug in sequence and returns the first success:
const response = await nexus.chat.create({
model: "aeon",
fallbackModels: ["solaris", "prism"], // tried in order if "aeon" fails
messages: [{ role: "user", content: "Hello" }],
});Works across all capabilities:
// Embeddings
await nexus.embeddings.create({
model: "weave",
fallbackModels: ["weave-pro"],
input: "Semantic search query",
});
// Images
await nexus.images.generate({
model: "lux",
fallbackModels: ["lux-ultra"],
prompt: "A neon cityscape at night",
});
// Audio
await nexus.audio.transcribe({ model: "iris", fallbackModels: ["iris-turbo"], audioUrl: "..." });
await nexus.audio.speak({ model: "echo", fallbackModels: ["echo-swift"], text: "Hello" });
// Translation
await nexus.translate.create({ model: "babel", fallbackModels: ["nexus-translate"], text: "Hi", targetLang: "DE" });
// Video generation & understanding
await nexus.videos.generate({ model: "flux", fallbackModels: ["flux-pro"], prompt: "..." });
await nexus.videoUnderstanding.analyze({ model: "rift", fallbackModels: ["nexus-insight"], videoId: "vid_abc" });How it differs from provider-level failover: Profile-level failover (configured in the admin panel) retries across different providers for the same profile.
fallbackModelslets your application code name entirely different profiles — useful when you want a cheaper or lower-latency backup that the admin may not have wired into the primary profile's routes.
Orchestration modes
Model profiles can be backed by multiple routes and configured with an orchestration mode that controls how those routes collaborate:
| Mode | Behaviour |
|---|---|
| SINGLE | One route handles the request (default) |
| ENSEMBLE | All routes answer in parallel; orchestrator synthesizes the best response |
| ORCHESTRATED | Orchestrator assigns sub-tasks to specialist routes, then synthesizes |
| CHAIN | Routes run sequentially — each feeds its output to the next |
| DEBATE | Rounds of debate: routes see each other's answers, revise positions, orchestrator calls consensus |
Orchestration is configured per profile in the admin panel. From the SDK, you just call the profile slug — the mode is transparent to your application code.
Multi-part responses
Some orchestration modes (ENSEMBLE, DEBATE) may return structured multi-part output when the orchestrator determines a segmented answer serves the request better:
const response = await nexus.chat.create({
model: "your-ensemble-profile",
messages: [{ role: "user", content: "Compare these three frameworks in depth." }],
});
if (response.mode === "parts" && response.parts) {
for (const part of response.parts) {
console.log(`[${part.role}]`, part.content);
}
} else {
console.log(response.choices[0].message.content);
}DEBATE mode — how it works
When a profile uses DEBATE mode:
- Round 1 — all model routes answer independently in parallel
- Round 2 — each route sees the other routes' answers and updates or defends its position
- Round 3 — the orchestrator checks for convergence (agreement), then synthesizes or calls a majority vote
This is the closest approximation in AI to how human reasoning works across competing mental models. Use it for high-stakes decisions, research synthesis, or any task where a single model's blind spots could be costly.
Embeddings
const result = await nexus.embeddings.create({
model: "weave",
input: ["SmartHive powers collaborative AI workspaces", "AI Nexus routes intelligently"],
});
const vectors = result.data.map((e) => e.embedding);Images
Image generation is asynchronous. Poll getJob() until status === "completed":
const job = await nexus.images.generate({
model: "lux",
prompt: "A futuristic city skyline at dusk, photorealistic",
size: "1024x1024",
quality: "hd",
});
let result = job;
while (result.status !== "completed" && result.status !== "failed") {
await new Promise((r) => setTimeout(r, 3000));
result = await nexus.images.getJob(job.jobId);
}
console.log(result.data?.[0].url);Audio
Speech synthesis (text-to-speech)
const { data, contentType } = await nexus.audio.speak({
model: "echo",
text: "Hello from AI Nexus.",
voiceProfile: "aria",
speed: 1.1,
});
// data is an ArrayBuffer — write to file or stream to clientTranscription (speech-to-text)
const result = await nexus.audio.transcribe({
model: "iris",
audioUrl: "https://storage.smarthivelabs.dev/recordings/meeting.mp3",
language: "en",
});
console.log(result.text);
console.log(result.duration); // secondsTranslation
const result = await nexus.translate.create({
model: "babel",
text: "The quick brown fox",
targetLang: "ES",
});
console.log(result.translatedText); // "El rápido zorro marrón"
console.log(result.detectedSourceLang); // "EN"Video generation
const job = await nexus.videos.generate({
model: "flux",
prompt: "A drone shot flying over a mountain range at sunrise",
duration: 5,
aspectRatio: "16:9",
});
let result = job;
while (result.status !== "completed" && result.status !== "failed") {
await new Promise((r) => setTimeout(r, 10_000));
result = await nexus.videos.getJob(job.jobId);
}
console.log(result.url);Video understanding
const result = await nexus.videoUnderstanding.analyze({
model: "rift",
videoId: "vid_abc123",
query: "What safety violations are visible in this footage?",
});
console.log(result.text);Documents & retrieval (RAG)
Ingest a document
const doc = await nexus.documents.ingest({
storageUrl: "https://storage.smarthivelabs.dev/docs/policy.pdf",
knowledgeBaseId: "kb_abc123",
metadata: { department: "legal", version: "2026-Q1" },
});
// Poll until indexed
let detail = await nexus.documents.get(doc.documentId);
while (detail.status === "processing" || detail.status === "queued") {
await new Promise((r) => setTimeout(r, 2000));
detail = await nexus.documents.get(doc.documentId);
}Semantic search
const results = await nexus.retrieval.query({
query: "What is the notice period for contract termination?",
knowledgeBaseId: "kb_abc123",
topK: 5,
minScore: 0.7,
});
for (const hit of results.results) {
console.log(`[score ${hit.score.toFixed(2)}]`, hit.content);
}Moderation
const check = await nexus.moderation.check({
input: "User-submitted text to check",
});
if (check.flagged) {
console.log("Flagged categories:", check.categories);
}Agents
Single-turn
const result = await nexus.agents.run({
agentId: "agent_support_bot",
input: "My order hasn't arrived. Order #SH-9821.",
});
console.log(result.output);
console.log(result.finishReason); // "stop" | "tool_calls" | "length"Multi-turn with session continuity
const first = await nexus.agents.run({
agentId: "agent_support_bot",
input: "Start a return for order SH-9821.",
});
const second = await nexus.agents.run({
agentId: "agent_support_bot",
input: "Actually, I'd like store credit instead of a refund.",
sessionId: first.sessionId,
});Streaming agent response
const stream = await nexus.agents.run({
agentId: "agent_support_bot",
input: "Summarise my last three orders.",
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta.content ?? "");
}Realtime voice sessions
const session = await nexus.realtime.sessions.create({
agentId: "agent_voice_assistant",
mode: "duplex",
features: ["transcription", "tts", "vad"],
});
// Use session.livekitUrl + session.livekitToken to connect via the Expo or Web SDK
console.log(session.sessionId, session.livekitUrl);Models
// List all available profiles
const profiles = await nexus.models.list();
for (const profile of profiles) {
console.log(profile.displayName ?? profile.slug, profile.capability);
if (profile.enabled === false) console.log(" (disabled)");
}
// Get a specific profile
const profile = await nexus.models.get("aeon");
console.log(profile.orchestrationMode); // "SINGLE" | "ENSEMBLE" | ...Usage
const report = await nexus.usage.list({
startDate: "2026-01-01",
endDate: "2026-01-31",
});
console.log(report.summary);
// { totalRequests: 12400, totalTokens: 8200000, totalCostUsd: 42.50 }
for (const event of report.data) {
console.log(event.createdAt, event.modelDisplayName, event.totalTokens);
}Credits & billing
AI Nexus uses a prepaid credits model. Each project has a USD credit balance. Every API call deducts the billed amount from the balance in real time. When the balance reaches zero, all API keys for that project are blocked immediately.
How deduction works
| Call type | Deducted | |---|---| | Chat / completion | Billed tokens × retail price per 1K | | Embeddings | Billed tokens × retail price per 1K | | Images, audio, video | Fixed per-use rate (no token pricing) |
If no retail markup is set on a model profile, cost = provider cost (at-cost billing).
Handling a 402 response
When a project runs out of credits the API returns HTTP 402 Payment Required:
{
"statusCode": 402,
"error": "Payment Required",
"message": "Insufficient credits — top up your project balance to continue."
}The SDK surfaces this as AiNexusAPIError with status === 402:
import { AiNexusAPIError } from "@smarthivelabs-devs/ai-nexus";
try {
await nexus.chat.create({ model: "aeon", messages: [...] });
} catch (err) {
if (err instanceof AiNexusAPIError && err.status === 402) {
console.error("Out of credits. Top up at https://ai-nexus-admin.smarthivelabs.dev");
// redirect user, notify billing system, etc.
}
}Note: The SDK does not automatically retry 402 errors — retrying without adding credits will always fail.
Adding credits
Credits are added per-project from the AI Nexus admin dashboard:
- Open Projects → [your project] → Credits
- Enter a USD amount and click Add Credits
There is no minimum top-up amount. Credits do not expire.
Error handling
import { AiNexusError, AiNexusAPIError, AiNexusRateLimitError } from "@smarthivelabs-devs/ai-nexus";
try {
await nexus.chat.create({ model: "aeon", messages: [...] });
} catch (err) {
if (err instanceof AiNexusRateLimitError) {
console.log("Rate limited. Retry after:", err.retryAfter, "s");
} else if (err instanceof AiNexusAPIError) {
console.log("API error:", err.status, err.message);
} else if (err instanceof AiNexusError) {
console.log("SDK error:", err.message);
} else {
throw err;
}
}Error hierarchy:
AiNexusError
├─ AiNexusAPIError — HTTP 4xx / 5xx responses
│ ├─ AiNexusAuthError — 401 / 403
│ ├─ AiNexusInsufficientCreditsError — 402 (project out of credits)
│ └─ AiNexusRateLimitError — 429 (has .retryAfter seconds)
└─ AiNexusConnectionError — network-level failures
└─ AiNexusTimeoutError — request exceeded timeoutAutomatic retries
The SDK automatically retries on transient errors (408, 429, 500, 502, 503, 504) with exponential backoff:
| Attempt | Delay | |---|---| | 1st retry | 500 ms | | 2nd retry | 1 000 ms | | 3rd retry | 2 000 ms (cap 8 s) |
Configure with maxRetries in the client options (default: 2).
TypeScript types
All types are exported from the main entry point:
import type {
// Core
AiNexusClientOptions,
// Orchestration
OrchestrationMode,
ChatPart,
// Chat
ChatMessage,
ChatCreateParams,
ChatResponse,
ChatStreamChunk,
ChatTool,
// Models
ModelProfile,
ModelCapability,
// Usage
UsageEvent,
// ... and 40+ more
} from "@smarthivelabs-devs/ai-nexus";CommonJS
const { AiNexus } = require("@smarthivelabs-devs/ai-nexus");
const nexus = new AiNexus({ apiKey: process.env.AI_NEXUS_API_KEY });Related packages
| Package | Purpose |
|---|---|
| @smarthivelabs-devs/react-ai-nexus | React hooks (useChat, useAgent, useVoiceCall, ...) |
| @smarthivelabs-devs/next-ai-nexus | Next.js App Router / Pages Router proxy handlers |
| @smarthivelabs-devs/ai-nexus-expo | Expo / React Native with audio recording + LiveKit |
License
MIT © SmartHive Labs
