npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lore-hex/trusted-router

v0.8.0

Published

JavaScript SDK and CLI for TrustedRouter — typed errors, retries, failover, and attestation verification.

Downloads

709

Readme

TrustedRouter JavaScript SDK and CLI

npm version npm downloads CI TypeScript types License: Apache-2.0 Verifiable trust

OpenAI-compatible JS/TS client for TrustedRouter — the hosted, attested LLM router that lets you point one OpenAI-shaped client at every provider (Anthropic, OpenAI, Google Vertex, Gemini, DeepSeek, Mistral, Cerebras) and prove the prompt path doesn't log.

  • Inference API: https://api.trustedrouter.com/v1
  • Control API: https://trustedrouter.com/v1
  • Trust release: https://trust.trustedrouter.com
  • Source: https://github.com/Lore-Hex/trusted-router-js
  • License: Apache-2.0
npm install @lore-hex/trusted-router

Runs on Node 20+, Deno, Bun, and modern browsers — no native deps. The attestation verifier uses the WebCrypto SubtleCrypto API.

Command-line interface

The same npm package includes the official trustedrouter CLI. Install it globally, invoke it through npx, or keep it as a project dependency:

npm install --global @lore-hex/trusted-router
export TRUSTEDROUTER_API_KEY="sk-tr-v1-..."

trustedrouter chat "Explain confidential computing in one paragraph"
printf '%s\n' 'Summarize this input' | trustedrouter chat - --stream
trustedrouter models --json
trustedrouter providers --json
trustedrouter regions --json
trustedrouter trust --json
trustedrouter attest --verify --json
trustedrouter attest --session --json

# No global install:
npx --yes @lore-hex/trusted-router models --json

chat accepts a positional prompt, an explicit -, or piped stdin when the prompt is omitted. Stdin must be valid UTF-8, is capped at 8 MiB, and preserves its leading/trailing whitespace. It defaults to trustedrouter/auto; use --model and --max-tokens to override that. --stream --json emits one compact JSONL chat.delta record per non-empty text delta followed by chat.done. Compact JSON and JSONL recursively sort object keys so byte output is deterministic.

Every non-streaming command success in --json mode has the stable shape {"command":"...","data":...,"ok":true}. Errors go only to stderr as {"error":{"message":"...","type":"..."},"ok":false}, with status_code and request_id when available. Exit codes are stable by family: 0 success, 1 API/runtime failure, 2 usage/input error, and 3 authentication/permission failure.

attest --verify checks the document signature and workload identity against the published trust release. attest --session additionally binds the check to the live connection's nonce and TLS exporter and runs a same-socket follow-up challenge.

The CLI reads TRUSTEDROUTER_API_KEY (or the legacy TR_API_KEY) and never accepts a bearer as a command-line argument, where it could leak through shell history or the process list. Optional deployment overrides are TRUSTEDROUTER_BASE_URL, TRUSTEDROUTER_CONTROL_BASE_URL, and TRUSTEDROUTER_WORKSPACE_ID; TR_BASE_URL remains a legacy base-URL alias. Explicit --help output is always plain text, even alongside --json. Run trustedrouter --help or trustedrouter chat --help for the complete command reference. Invoking the CLI without a command is a usage error (exit 2).

Quick start

import { TrustedRouter, AUTO_MODEL } from "@lore-hex/trusted-router";

const client = new TrustedRouter({ apiKey: "sk-tr-v1-..." });

const resp = await client.chatCompletions({
  model: AUTO_MODEL,                  // "trustedrouter/auto" — multi-provider failover
  messages: [{ role: "user", content: "hello" }],
});

console.log(resp.choices[0].message.content);

chatCompletions(...) defaults to AUTO_MODEL when model is omitted.

Routing, privacy, and orchestration

The package exports stable aliases for normal routing (AUTO_MODEL, FAST_MODEL), privacy (ZDR_MODEL, E2E_MODEL, CONFIDENTIAL_MODEL, EU_MODEL, US_MODEL), and named orchestration models including SOCRATES_MODEL, PROMETHEUS_MODEL, ZEUS_MODEL, and ATHENA_MODEL.

Use ProviderPreferences when privacy or US provider jurisdiction must remain a hard routing requirement with an explicit model. Use EU_MODEL for the EU-focused routing pool:

import { ProviderPreferences } from "@lore-hex/trusted-router";

const response = await client.chatCompletions({
  model: "z-ai/glm-5.2",
  messages: [{ role: "user", content: "Review this contract." }],
  provider: ProviderPreferences.confidential(),
});

All five atomic orchestration primitives have typed builders with matching wire formats across the official SDKs: fusionTool (Synth), advisorTool, selectorTool, mapReduceTool, and subagentTool.

Cost allocation tags

Attach up to 50 AWS-style string tags to any inference request. Tags remain outside model prompts and provider payloads and appear in TrustedRouter generation and activity metadata.

const response = await client.chatCompletions({
  model: "trustedrouter/zdr",
  messages: [{ role: "user", content: "Summarize this contract." }],
  tags: {
    environment: "production",
    team: "legal",
    "cost-center": "legal-01",
  },
  user: "user_123",
  session_id: "matter_456",
});

The same tags, user, session_id, and trace fields work with Responses, Messages, and Embeddings. Request tags override API key default tags with the same key.

Node TLS session verification

G6 TLS session pinning uses Node TLS sockets, so import it from the Node-only session subpath rather than the browser-safe package root:

import {
  verifyGatewaySession,
  fetchAttestationAgain,
} from "@lore-hex/trusted-router/session";

fetchAttestationAgain(session) re-fetches and verifies the document over the already-pinned socket and returns a verified GatewayAttestation. This is a return-type change from the earlier raw Uint8Array; an HTTP 200 alone is no longer exposed as though it were a trusted follow-up.

Fusion

Fan a request across a panel of models and let a judge model pick or synthesize one answer. fusion(...) returns the same OpenAI-shape chat.completion as chatCompletions. FUSION_FREEDOM_PANEL / FUSION_FREEDOM_FALLBACK_JUDGES are the recommended most-permissive configuration.

import {
  TrustedRouter,
  FUSION_FREEDOM_PANEL,
  FUSION_FREEDOM_FALLBACK_JUDGES,
} from "@lore-hex/trusted-router";

const client = new TrustedRouter({ apiKey: "sk-tr-v1-..." });

const resp = await client.fusion({
  messages: [{ role: "user", content: "explain how mRNA vaccines work" }],
  analysisModels: FUSION_FREEDOM_PANEL,   // the panel
  // omit selectionStrategy to use synthesize_non_refusals
  fallbackJudges: FUSION_FREEDOM_FALLBACK_JUDGES, // tried in order if a judge refuses/fails
});

console.log(resp.choices[0].message.content);

Or attach fusionTool(...) to any chat call yourself. preset: "quality" or "budget" picks a built-in panel.

Browser sign-in / delegated keys

Browser apps should not ask users to paste a full TrustedRouter key. Use the OAuth/PKCE delegation flow to mint a limited inference key for your app, then store that delegated key in browser storage.

import { TrustedRouter } from "@lore-hex/trusted-router";

const tr = new TrustedRouter();

// Sign-in button handler.
const auth = await tr.createOAuthAuthorization({
  callbackUrl: `${location.origin}/auth/callback`,
  keyLabel: "Lore Web",
  limit: "5",
  usageLimitType: "monthly",
});

sessionStorage.setItem("tr_oauth", JSON.stringify({
  state: auth.state,
  codeVerifier: auth.codeVerifier,
}));
location.assign(auth.url);

On the callback page:

const params = new URLSearchParams(location.search);
const saved = JSON.parse(sessionStorage.getItem("tr_oauth") || "{}");
if (params.get("state") !== saved.state) throw new Error("OAuth state mismatch");

const { key } = await new TrustedRouter().exchangeOAuthKey({
  code: params.get("code"),
  codeVerifier: saved.codeVerifier,
});

localStorage.setItem("tr_delegated_key", key);

createOAuthAuthorization(...) generates an RFC7636 S256 PKCE verifier and challenge locally. exchangeOAuthKey(...) posts only the one-time code and verifier, and deliberately omits any existing bearer key.

Sign in with TrustedRouter

For browser SPAs, BrowserOAuthFlow (from @lore-hex/trusted-router/oauth) wraps the lower-level helpers above: initiate(...) builds the authorize URL and stashes { state, codeVerifier } in sessionStorage, and handleCallback(...) validates state, exchanges the code, and returns the delegated key + verified identity. Then client.userInfo() reads the signed-in user.

import { TrustedRouter } from "@lore-hex/trusted-router";
import { BrowserOAuthFlow } from "@lore-hex/trusted-router/oauth";

const flow = new BrowserOAuthFlow(`${location.origin}/auth/callback`, {
  client: new TrustedRouter(),
});

// sign-in button:
const { url } = await flow.initiate({ keyLabel: "My App", limit: "5" });
location.assign(url);

// on /auth/callback (reads location.search; throws on state mismatch):
const { key, identity } = await flow.handleCallback();
localStorage.setItem("tr_delegated_key", key);

// later:
const { data } = await new TrustedRouter({ apiKey: key }).userInfo();

Full flow, endpoints, and security notes: Sign in with TrustedRouter.

Streaming

for await (const token of client.chatCompletionsText({
  messages: [{ role: "user", content: "Write a haiku" }],
})) {
  process.stdout.write(token);
}

chatCompletionsChunks(...) yields the raw OpenAI chat.completion.chunk objects (with finish_reason, model, id) when you need more than just the text delta. chatCompletionsRawStream(...) yields the underlying SSE bytes — useful if you're writing an HTTP relay that doesn't want to parse.

Inference endpoint and failover

Inference calls default to DEFAULT_API_BASE_URL. The default client probes the published US Central, US East, and Europe gateways in parallel on its first inference request, pins the lowest-latency healthy region, and keeps the other regions plus the global apex as idempotent failover targets. Reuse one client to retain region affinity and connection pooling, reuse DNS results, and improve prompt-cache locality. Set regionalAffinity: false to use only the global endpoint. A custom baseUrl is never probed or rewritten. A custom fetch defaults affinity off; opt in with regionalAffinity: true when its transport can reach the public regional hosts. Pass baseUrl only for a custom inference endpoint (e.g. a self-hosted gateway). Metadata, OAuth, billing, credits, activity, and broadcast helpers use the control plane at DEFAULT_CONTROL_BASE_URL; override it with controlBaseUrl only when you need a custom control endpoint.

Alias domains

The regions above all live under one name on one DNS provider, and the domain sits above every cloud behind it. A zone that stops answering, a registrar lock, or a resolver handing out a stale record takes the API down no matter how many regions are healthy.

ALIAS_API_BASE_URLSapi.allyrouter.com and api.uptimerouter.com — are exact aliases of the primary, on separate domains served by separate DNS providers, resolving to the same attested enclaves. They sit at the end of the candidate list, after the regional gateways, so a healthy deployment never touches them. Nothing to configure; it is on by default.

Failover changes host only on connection failures and on 502, 503, or 504. A 500 means a server received and processed the request. You are not charged twice for it — authorization is idempotent per Idempotency-Key and settlement happens once — but the work would run a second time, so the answer could differ and TrustedRouter pays the provider again. A 500 is retried on the same host.

Aliases are used only for the default baseUrl. A custom one — a private deployment, a test server, a regional pin — is never rewritten. Set regionalFailover: false to keep every attempt on a single host.

Typed errors

Every HTTP failure throws a typed subclass of TrustedRouterError so callers can discriminate without inspecting status codes:

import {
  TrustedRouter, RateLimitError, AuthenticationError,
  BadRequestError, EndpointNotSupportedError, InternalError,
} from "@lore-hex/trusted-router";

try {
  await client.chatCompletions({ messages: [...] });
} catch (err) {
  if (err instanceof RateLimitError) {
    await sleep((err.retryAfter ?? 5) * 1000);
  } else if (err instanceof AuthenticationError) {
    refreshKey();
  } else if (err instanceof BadRequestError) {
    console.warn("bad request:", err.message);
  } else if (err instanceof EndpointNotSupportedError) {
    disableOptionalFeature();
  } else if (err instanceof InternalError) {
    // auto-retried; still failing
  } else {
    throw err;
  }
}

All subclasses inherit TrustedRouterError.

Every error also carries layer, source, provider, and requestId when the server supplies them, so retry logic can distinguish router failures from provider failures without parsing human-readable messages.

Automatic retries

By default the client retries 429 and 5xx responses up to 2 times with exponential backoff + jitter (capped at 30s, honors Retry-After). Disable with maxRetries: 0:

const client = new TrustedRouter({ apiKey: "...", maxRetries: 0 });

Typed inference and control-plane mutation methods mint one idempotency key at the logical call boundary and reuse it unchanged for every retry. The generic client.request(...) and client.rawRequest(...) escape hatches deliberately do not guess whether an arbitrary write is idempotent: pass idempotencyKey explicitly if an unsafe method such as POST should be replayed after an ambiguous transport failure or an ordinary retryable status. A failure known to happen before any bytes were sent remains safe to retry without a key.

Regional failover applies only to inference routes and preserves the same idempotency key when it advances to another healthy gateway. Control-plane calls retry on the configured control host.

Per-call extras

Every chat method (and request() for ad-hoc paths) accepts:

| Option | Purpose | |---|---| | apiKey | Override the instance bearer for this call only (threadsafe) | | extraHeaders | Object of headers to merge in (trace IDs, custom routing) | | workspaceId | Sets X-TrustedRouter-Workspace for workspace-scoped management calls | | idempotencyKey | Supplies the replay key; typed mutations auto-mint one when omitted, while generic request() does not | | timeout | Per-call timeout in milliseconds (uses AbortController) |

await client.billingCheckout({
  amount: 25,
  paymentMethod: "stablecoin",
  idempotencyKey: `checkout-${userId}-${orderId}`, // never double-charge
});

Attestation verification (the differentiator)

Every TrustedRouter response is generated inside a Google Confidential Space workload. The gateway's /attestation endpoint mints a Google-signed JWT that commits to the workload image digest, image reference, your nonce, and the TLS leaf cert SHA-256. Verifying it proves the prompt path you're about to use is the exact build the trust page advertises:

import { TrustedRouter } from "@lore-hex/trusted-router";
import {
  verifyGatewayAttestation, policyFromTrustRelease,
} from "@lore-hex/trusted-router/attestation";

const client = new TrustedRouter({ apiKey: "sk-tr-v1-..." });
const policy = await policyFromTrustRelease();   // pulls live trust release

const nonce = crypto.randomUUID().replace(/-/g, "");
const jwt = await client.attestation();           // raw JWT bytes (Uint8Array)

const attestation = await verifyGatewayAttestation(jwt, {
  policy,
  nonceHex: nonce,
  // Optionally pass the live TLS cert DER bytes for extra binding.
});

console.log("verified gateway:", attestation.imageDigest);

verifyGatewayAttestation() throws AttestationVerificationError on any failure — bad signature, expired JWT, wrong issuer, audience mismatch, image_digest mismatch, image_reference mismatch, missing nonce echo, or TLS cert mismatch. Never returns falsey for a failed verification.

Bring your own fetch

Pass fetchImpl for custom transports (proxies, retries you manage, observability hooks):

const client = new TrustedRouter({
  apiKey: "...",
  fetchImpl: async (url, init) => myInstrumentedFetch(url, init),
});

Other endpoints

client.models();             // OpenAI-shape catalog via the control plane
client.providers();          // provider list via the control plane
client.regions();            // deployed regions via the control plane
client.credits({ workspaceId: "ws_..." }); // prepaid balance via the control plane
client.activity({ since: "2026-01-01", limit: 50 }); // control-plane activity
client.messages({            // Anthropic shape, preserves system + content blocks
  model: "anthropic/claude-3-5-sonnet",
  messages: [{ role: "user", content: "hi" }],
  maxTokens: 512,
});
client.billingCheckout({ amount: 25, paymentMethod: "stablecoin", idempotencyKey: "..." });

client.embeddings(...) uses the attested inference plane. Embedding model catalog routes such as /embeddings/models are control-plane metadata.

For routes the SDK doesn't wrap, drop down to client.request(...):

await client.request("GET", "/some/new/route", {
  extraHeaders: { "x-trace": "abc" },
});

Contributing

npm install
npm run check        # syntax check
npm test             # node --test

CI runs lint + tests on every push to main and PR.