@mindverseai/hydra-sdk
v0.2.1
Published
Hydra routing, unified BYOK inference, streaming, usage and prepaid billing client
Readme
Hydra SDK · 0.2.1
A dependency-free, typed Node 22+ client for routing decisions and optional BYOK inference. This checkout builds version 0.2.1; a registry release is a separate publishing step. Install the built archive with npm install ./downloads/mindverseai-hydra-sdk-0.2.1.tgz, or use the download link in your deployed console. Once this version is published: npm install @mindverseai/[email protected].
import {Hydra, collectCompletion} from '@mindverseai/hydra-sdk';
const hydra = new Hydra({
apiKey: process.env.HYDRA_API_KEY,
baseURL: process.env.HYDRA_BASE_URL || 'https://hydraroute.com',
});Use a customer console key, never the shared engine key. Server use only. HTTP is allowed only on localhost; all other origins require HTTPS. The default host is not a claim that this checkout has been deployed. Requests have a 120-second client timeout and no automatic retries. Set timeoutMs (1–120000) or pass {signal} per call. Canceling does not guarantee the provider stopped or waived its charges.
Hydra engine API
const result = await hydra.decide('Explain PostgreSQL and SQLite.', {
profile: 'balanced', open_source: false,
});
const receipt = await hydra.receipt(result.requestId);
console.log(result.decision.selected_model);decide() uses /v1/answers for model selection by the Hetzner engine. Its raw routing JSON remains in result.raw; normalized evidence is in result.decision. The operator confirms that answer, execution and usage fields describe the router's internal work, not downstream inference. Missing fields stay null. Receipt checksums cover technical metadata, not prompts, and are not digital signatures.
hydra.execute(prompt, handlers, options) and hydra.withRouting(handlers) retain the original customer-side execution interface. Pass a Map or object of exact model IDs to callbacks. The SDK first checks that the deployment has a verified decision-only engine; otherwise it returns ROUTING_ONLY_UNAVAILABLE without sending the prompt. Router-internal execution metadata does not block the handler. The selected model must match a registered handler, which executes exactly once in your process using your provider SDK. Unknown models fail closed. Provider credentials are not sent to Hydra by these routing-only methods.
Unified inference
In the console, enable Hydra + inference, connect your own provider account, add prepaid Hydra credit, and create an inference-enabled API key. Existing keys keep their Hydra API access without BYOK permission. Provider/model availability depends on the operator's enabled routes and your provider access.
const models = await hydra.models.list();
const result = await hydra.chat.completions.create({
model: 'hydra-auto', // or an available exact models.data[].id
messages: [{role: 'user', content: 'Summarize the trade-offs.'}],
max_tokens: 1024,
hydra: {profile: 'balanced', baseline_model: 'openai/gpt-5.6-sol'},
}, {idempotencyKey: crypto.randomUUID()});
console.log(result.choices[0].message.content);
console.log(result.hydra.net_savings_estimate);hydra.complete() is equivalent. This is an OpenAI-shaped Chat Completions interface, not every provider endpoint or every OpenAI parameter. Unknown parameters fail explicitly. Supported features include text, inline PNG/JPEG/WebP images on vision models, custom function tools, streaming, JSON/JSON-schema output, and supported reasoning settings. Only n=1 is accepted. Remote image URLs, audio/video, embeddings, Responses, built-in search, file tools, batch jobs, logprobs, and arbitrary upstream URLs are not exposed. Check capabilities, token limits, and pricing_status from /v1/models.
The provider bills your account directly. Hydra deducts 5% of the catalog usage estimate from your prepaid service credit. Monetary totals are decimal USD strings. The estimate uses reported cached, cache-write, input and output tokens; it cannot know private invoice discounts, credits or taxes. Automatic routing requires automatic_routing_available: true in hydra.inference() and is currently unavailable in production. Use an available explicit model ID after provider activation. Once available, it uses the latest user text, up to 4,000 characters. The engine currently does not accept a candidate list; hydra.allowed_models is enforced after routing. An unavailable selected model returns 422 without executing a substitute. A successful routing decision still uses decision quota.
Idempotency keys prevent a second inference after reservation. A repeated accepted key returns 409; Hydra does not store or replay responses. Check inferenceRequests() or inferenceRequest(requestId) after an uncertain result. Do not blindly retry with a new key. Routing work occurs before inference reservation.
Streaming and conversation state
const stream = await hydra.complete({
model: 'hydra-auto', messages: [{role: 'user', content: 'Tell me a story.'}],
stream: true, max_tokens: 1024,
}, {idempotencyKey: crypto.randomUUID()});
const result = await collectCompletion(stream, {
onChunk(chunk) { process.stdout.write(chunk.choices[0]?.delta.content || ''); },
});
// Keep the entire assistant message for follow-up requests.
const assistant = result.choices[0].message;Alternatively iterate for await (const chunk of stream). Breaking the loop cancels the request; await stream.cancel() also works before reading. An HTTP-200 stream can fail in-band: the iterator throws HydraError. Successful streams include final usage and hydra cost metadata before [DONE], even if stream_options.include_usage is false. Do not treat an early text fragment as a completed/billed request.
Return the entire original assistant message, including hydra_state, unchanged in follow-up history. The opaque state preserves native thinking/signatures and expires after 24 hours. It is bound to your workspace and pins the original model and connection; a tool conversation never silently moves to a different provider. Automatically routed continuations retain the original routing attribution for savings, without another routing call. collectCompletion assembles tool fragments and continuation state for you.
Tool calling
Hydra returns tool requests; your application decides whether and how to run them. Validate arguments and apply your own authorization before any side effect. This bounded example uses a read-only tool:
const messages = [{role: 'user', content: 'What time is it in Madrid?'}];
const tools = [{type: 'function', function: {
name: 'get_time', description: 'Current time in Europe/Madrid',
parameters: {type: 'object', properties: {}, additionalProperties: false},
}}];
for (let step = 0; step < 4; step++) {
const result = await hydra.complete({model: 'hydra-auto', messages, tools, max_tokens: 1024},
{idempotencyKey: crypto.randomUUID()});
const message = result.choices[0].message;
messages.push(message);
if (!message.tool_calls?.length) { console.log(message.content); break; }
for (const call of message.tool_calls) {
const args = JSON.parse(call.function.arguments);
if (call.function.name !== 'get_time' || Object.keys(args).length) throw Error('Invalid tool');
messages.push({role: 'tool', tool_call_id: call.id,
content: JSON.stringify({time: new Date().toLocaleString('en-GB', {timeZone: 'Europe/Madrid'})})});
}
if (step === 3) throw Error('Tool step limit reached');
}Return one result for every pending tool call before adding another non-tool message. tool_choice supports auto/none/required/a named function; parallel and strict-tool controls depend on provider capabilities. Each generation is a separate provider call and prepaid fee.
Per-request credentials
Stored credentials are write-only and envelope encrypted in Hydra's vault. For an ephemeral alternative, supply credentials from your server's secret manager:
await hydra.complete({
model: 'openai/gpt-5.6-luna', messages: [{role: 'user', content: 'Hello'}],
hydra: {credentials: {provider: 'openai', secret: {api_key: process.env.OPENAI_API_KEY}}},
});These credentials are not persisted. Hydra still receives and uses the plaintext credential while calling the provider; this is not zero-knowledge. Do not log request bodies. Azure and Vertex accept per-request {access_token, expires_at} (Unix seconds, 60–7200 seconds ahead). Vertex also supports a service-account email and PKCS8 private key; Azure also supports an API key. See the console/configuration guide for Cloudflare account IDs, Azure deployment maps, and Vertex project/location. hydra.connection_id chooses one stored connection; do not combine it with credentials.
Usage, savings and prepaid records
const {wallet} = await hydra.inference();
const usage = await hydra.inferenceUsage({days: 30}); // 7, 30, 90
const page = await hydra.inferenceRequests({limit: 25});
const next = page.next_cursor && await hydra.inferenceRequests({cursor: page.next_cursor});
const record = page.data[0] && await hydra.inferenceRequest(page.data[0].id);
const ledger = await hydra.ledger({limit: 25});Savings compare the same reported token counts against an uncached chosen baseline, then subtract Hydra's fee. Negative values remain visible. This is an estimate, not evidence of equal output quality or actual invoice savings. Unknown usage is null, not invented token counts; no Hydra fee is charged when usage is unavailable or a stream is interrupted. The provider may still charge for such calls. Routing-only requests are excluded from measured inference savings.
Errors expose status, code, and requestId. Wallet holds prevent overspending; unused reservations are released after completion. A terminated Worker is reconciled by the scheduled job without replaying inference. Credentials and account access still depend on the provider's terms and your account permissions.
