Skip to content

[PUBLISHED ON NPMJS] @takk/caduceus@1.0.0

Latest

Choose a tag to compare

@github-actions github-actions released this 30 Jun 00:28

STATUS: PUBLISHED ON NPMJS. This version was published to the npm registry on 2026-06-30T00:44:15Z with provenance attestation. View on npm: https://www.npmjs.com/package/@takk/caduceus/v/1.0.0

STATUS: REVIEW REQUIRED, NOT YET ON NPMJS. This GitHub Release was created by the release.yml workflow. The Creator must review the contents (tag, changelog, attached commit, pack-smoke result in the workflow logs) and then explicitly run npm-publish.yml to publish this version to the npm registry.

1.0.0 - 2026-06-30T00:12:31Z

Initial stable release. Caduceus is a universal, zero-runtime-dependency NPM library and CLI that gives any provider a single shape: it normalizes OpenAI, Anthropic, and Gemini requests, responses, streams, and tool calls into one typed vocabulary, then routes each request across a pool of heterogeneous models by one of seven strategies, with per-model circuit breakers, hard USD budgets, automatic failover, and an auditable route trace that names which model answered. The core never speaks HTTP; it is routing logic over an injectable dispatch, which keeps it provider-agnostic, node-free, and testable offline. It is the open, local-first transport layer for multi-agent Massive Intelligence (IM) systems and non-human entities, and it feeds the agent pool of the @takk/coryphaeus orchestrator.

Added

Transport

  • Caduceus (@takk/caduceus/transport): the router most callers use. It exposes registerProvider, registerModel, providers, models, plan (the strategy ordering and per-candidate cost forecast without any call), complete (route, fail over, and return a RouteResult), stream (route and return a normalized event stream from the first model that connects), breakerSnapshot, and resetBreakers. Route options carry a fixed request id, a strategy override, a candidate-model restriction, and a hard per-request USD ceiling. Time is an injectable clock, so latency and breaker timing are deterministic.

The compatibility matrix

  • encodeRequest, decodeResponse, decodeStream, collectStream, encodeResponse, streamChunksOf, and createEchoDispatch (@takk/caduceus/codec): the only place that knows how each provider shapes a request, a response, a token usage, a tool call, and a stream. It encodes one normalized ChatRequest into the OpenAI, Anthropic, or Gemini wire body; decodes each provider's response and streaming events back into one typed vocabulary; translates tool definitions and tool calls in both directions; and runs in reverse so the offline echo dispatch exercises the full encode, dispatch, decode path with no network.

Strategies

  • STRATEGY_KINDS, createStrategy, orderCandidates, and isStrategyKind (@takk/caduceus/strategy): the seven configurable routing strategies, the opposite of a black-box gateway. Cost-then-quality, cost-first, quality-first, latency-first, weighted, round-robin, and sequential-cascade order the candidate models; the router then tries them in order, skipping open breakers and failing over on error. Round-robin carries a cursor so successive requests start at different models.

Circuit breakers

  • CircuitBreaker and BreakerRegistry (@takk/caduceus/breaker): one closed, open, half-open state machine per model over the injected clock. A breaker trips open after a configurable failure threshold so the router stops sending it traffic; after a cooldown it goes half-open and lets a single probe through, where a success closes it and a failure re-opens it. The registry creates a breaker per model lazily and snapshots every model's state.

Rate-limit recovery

  • resolveRetry, backoffDelay, isRateLimitStatus, defaultWait, and the RetryConfig and WaitFn types (@takk/caduceus): on a rate-limit (HTTP 429) the router does not fail over blindly. It honors the provider's Retry-After (or an exponential backoff, both capped) and retries the same model up to maxRetries before failing over, recording the retry count and total wait in the trace as retries and waitedMs. The wait is injectable so the policy is deterministic and node-free. The Node fetch dispatch parses the Retry-After header into retryAfterMs on a 429.
  • withKeyRotation (@takk/caduceus/adapter): wraps a per-key dispatch factory so each retry presents a fresh key, the @takk/keymesh integration seam for key rotation and rate-limit recovery without a hard dependency. The key pool is fixed by the host.

Budget

  • estimateTokens, estimateRequestTokens, costOf, forecastUsd, BudgetTracker, and ZERO_COST (@takk/caduceus/budget): token estimation from a request, USD pricing against a per-model cost profile (a cached rate defaults to the input rate), and a running ledger with an optional hard ceiling. The router forecasts each call and assertCanAfford raises a typed BUDGET_EXCEEDED before a breaching call is dispatched. The same primitive scopes a per-request, per-task, or per-day ceiling.

Providers and models

  • defineProvider, defineModel, ProviderRegistry, providerId, modelId, isProviderShape, qualityOf, weightOf, costRank, and latencyOf (@takk/caduceus/provider). A provider is an endpoint family with one wire shape; a model is a routing candidate, treated as a black box, carrying the cost, quality, and latency metadata the strategies sort on. Descriptors are validated and frozen, and a model resolves to its provider and shape through the registry.

The auditable route trace

  • provenanceOf, traceJson, renderTraceDot, renderTraceMermaid, sealTrace, verifyTraceSeal, and sha256Hex (@takk/caduceus/trace): every route records which models were tried, in what order, each breaker's state, each attempt's cost and latency, and which model finally answered. It renders to JSON, Graphviz DOT, or Mermaid as a transport graph, exposes the provenance of the answer, and seals with a SHA-256 digest over the Web Crypto API for tamper-evidence. The seal is an integrity seal, not a signature.

Adapters and the tool

  • dispatchFromVercel, dispatchFromOpenAIChat, respondWith, streamWith, withKeyRotation, agentClientFromCaduceus, createTransportTool, describeRouteTool, parseRouteToolInput, toJsonSafe, and ROUTE_TOOL_NAME (@takk/caduceus/adapter). Two-line bridges wrap a Vercel AI SDK call or an OpenAI-style chat function as the injected dispatch; agentClientFromCaduceus implements the @takk/coryphaeus AgentClient contract so the transport feeds the orchestrator's agent pool with no hard dependency; and the transport is exposed as a framework-agnostic tool (name caduceus_route) with a JSON Schema and a JSON-safe handler, ready to register with an MCP server or any tool-calling API. Model-supplied input is parsed defensively; the pool is fixed by the host.

The injectable dispatch and the Node fetch transport

  • The Dispatch contract is the seam that keeps the core provider-agnostic: it takes a fully encoded ProviderCall and returns a decoded JSON body or a raw chunk iterable. createFetchDispatch (@takk/caduceus/node) is the real transport over the global fetch, building the chat-completions, messages, or generateContent URL for each shape and parsing Server-Sent Events into the chunk objects the codec normalizes. The Node entry also adds disk loaders (loadProviders, loadModels, loadRequest, loadTrace, readJsonFile), each defensively validated. @takk/caduceus/edge re-exports the node-free core for Cloudflare Workers, Vercel Edge, Bun, Deno, and the browser.

CLI

  • The caduceus binary: providers (list the registered provider and model pool), plan <request.json> (the strategy ordering and a cost forecast, no network), route ... --mock (route offline with the deterministic echo dispatch, optionally writing the trace to a file), and trace <trace.json> (render a saved trace to DOT, Mermaid, or JSON). Exit codes: 0 ok, 2 usage or input error, 21 no route could be completed, 30 the budget ceiling tripped. The CLI carries no provider credentials; real runs use the library API with the Node fetch dispatch or an injected one.

Errors

  • CaduceusError with a stable, machine-readable code (@takk/caduceus): INVALID_CONFIG, INVALID_PROVIDER, INVALID_MODEL, INVALID_REQUEST, INVALID_STRATEGY, INVALID_SHAPE, BUDGET_EXCEEDED, NO_ROUTE, DISPATCH_FAILED, INVALID_STATE, INVALID_SNAPSHOT, NUMERIC. Callers branch on error.code, never on the message.

Examples and the transport benchmark

  • Five runnable examples that route against the built dist: a failover route with a DOT render, the seven strategies' orderings, a circuit breaker tripping and recovering, a hard USD budget ceiling, and a Vercel adapter plus the routing tool and the AgentClient bridge.
  • A transport benchmark (benchmarks/transport-benchmark.mjs) that runs the built router over a controlled failure model on a fixed seed, 4000 requests per regime. It measures the mechanisms the transport contributes: three-way failover over independent 40% provider failures lifts the success rate from 59.4% to 93.5% (against the 93.6% theoretical bound of one minus the failure probability cubed), and a circuit breaker over one fully-down provider cuts wasted calls to it by 49.9%. It is a mechanism demonstration, not an LLM quality claim.

Engineering

  • Zero required runtime dependencies; a node-free core (the trace seal uses the Web Crypto API, not node:crypto; the fetch dispatch lives in ./node); dual ESM and CJS distribution with separate .d.ts and .d.cts per subpath; eleven functional subpath exports plus ./package.json.
  • TypeScript 6 in maximum strict mode (exactOptionalPropertyTypes, useUnknownInCatchVariables, noUncheckedIndexedAccess, noPropertyAccessFromIndexSignature, verbatimModuleSyntax, isolatedModules). Biome 2.5 lint clean.
  • 159 tests across 13 suites passing under Vitest 4 on Node 20, 22, and 24. Coverage: statements 94.61%, branches 83.65%, functions 99.12%, lines 94.49%, above the 80/80/80/80 thresholds.
  • publint clean and @arethetypeswrong/cli green across all eleven subpaths. size-limit under budget on every bundle (brotli core 8.63 kB). A distribution smoke test exercises the compiled ESM and CJS artifacts and spawns the compiled CLI as a single Node process.
  • SLSA provenance attestation on every published version via GitHub Actions OIDC.

Not in 1.0 (documented non-goals)

  • A learned, quality-measured router (the 1.0 strategies are transparent and deterministic; quality-by-measurement with evaluators and bandits is planned behind the same Strategy seam).
  • Bundled provider SDKs (the dispatch seam keeps the core SDK-free; the Node fetch dispatch is the one bundled transport), a hosted gateway, a runnable MCP server binary, multimodal content parts, and signed and timestamped trace seals, all planned for later releases.