@blueforge-studio/ai-routing
Pure routing core for AI generation: (domain, artifact, quality) -> an ordered, priced, explainable plan of provider/model candidates. No I/O, no gateway imports.
Informations sur le paquet
Versions
| Version | Publiée |
|---|---|
| 0.1.0 | 2026-10-16 |
Chaîne d'approvisionnement par version
| Version | Sig | SBOM | Att |
|---|---|---|---|
| 0.1.0 |
Cliquez sur une version pour voir ses détails.
Chaîne d'approvisionnement
Provenance
- Publié par
- web:5
- Quand
- 2026-10-16T21:12:01Z
- sha256 (calculé par le registre)
- 22c57eb24fdc3068c3f2036bb7751237db46070148689f24996f574f730066f8
Observé par le registre au moment de la publication.
Déclaré par la compilation
L'éditeur n'a rien déclaré sur sa compilation.
Pièces jointes
- Signature
- aucune
- SBOM
- aucune
Dépendances
README
@blueforge-studio/ai-routing
A pure routing core for AI generation. Give it a request (domain, artifact, quality) and your rules; get back an ordered, priced, explainable plan of provider/model candidates. It does no I/O, makes no HTTP calls and imports no gateway, so any gateway (image, audio, video, vision, text) can use it without pulling in the others' SDKs.
Design, inventory of the mechanisms it generalises, and decisions: docs/superpowers/specs/2026-10-16-ai-routing-unification.md. This is v0.1: the core only. No gateway uses it yet (image-gateway is the planned first adopter, behind an opt-in).
Use
import { defineRules, resolve, escalate, explain, memoryStickyStore } from "@blueforge-studio/ai-routing";
const rules = defineRules([ // lowest priority first
{ name: "package", rules: { domain: "image", artifacts: {
"*": { tiers: {
draft: { routes: [{ provider: "gemini", model: "flash-image-2.5", config: { width: 512 } }] },
standard: { routes: [{ provider: "gemini", model: "flash-image-2.5" }, { provider: "gemini", model: "flash-image-3.1" }] },
premium: { routes: [{ provider: "imagen", model: "imagen-ultra" }] } } },
texture: { defaultTier: "draft", tiers: { draft: { config: { width: 256 } } } }, // patch config only
} } },
{ name: "project", rules: { domain: "image", artifacts: { avatar: { tiers: { standard: { routes: [/* ... */] } } } } } },
]);
const sticky = memoryStickyStore(); // keep a book on one model
const plan = resolve(rules, { domain: "image", artifact: "chapter-cover", stickyKey: "book-7", maxCostUsd: 0.08 }, {
isAvailable: ({ provider }) => hasKey(provider), // from your gateway
price: ({ model }) => costFromAiPricing(model) ?? null, // null = unknown, never 0
sticky,
});
if (plan.failure) throw new Error(explain(plan));
for (const c of plan.candidates) { /* try c in order with the gateway's own client */ }
const better = escalate(rules, plan, { isAvailable, price, sticky }); // "the cheap result failed validation, retry on the next tier"
Concepts
- Quality is
draft | standard | premiumin every domain. What a tier means (model, size, resolution) is set by each domain's rules. - Layers: rule sets, lowest priority first (package defaults < project < env < per call). A layer's
routesreplace the route list for an (artifact, tier); itsconfigdeep-merges into the current routes' config (so "texture draft changes only width/height"). Within one layer the artifact's rules apply after the*defaults; across layers the higher layer wins, so layer priority outranks specificity. Every candidate records the layer its routes came from. - Strategies:
fallback(as given),round-robin(fromcursor),weighted(weighted-random order, so the order doubles as the fallback chain; weight 0 or less is a last resort, not dropped). Injectrng(seeseededRng) for reproducible plans. - Capabilities:
request.requiresmust all be provided (route.provides) or the route is excluded. A route that does not say what it provides fails any requirement. Nothing is ever substituted (an image-to-video request never gets a text-to-video model). - Availability comes from you (
ctx.isAvailable): keys present, healthy, credit left. - Sticky: with a
stickyKeyand actx.stickystore, the first resolution records its primary; later ones return it while it stays available. Entries are per (domain, artifact, tier, key), so an escalated retry never rewrites the cheap tier's choice.onUnavailabledefaults tofailwhen astickyKeyis set (a style-bound set must not silently change look) andfallbackotherwise. - Cost:
ctx.pricereturns dollars ornull. Unknown isnull, never 0, and a throwing, negative or NaN price becomesnullwith a trace line.maxCostUsddrops known-expensive candidates and keeps unknown ones;allowDowngradesteps down a tier when nothing fits. The core owns no budget state;jobKeyis carried for your bookkeeping. - Failure is a value: an empty plan with
failure(no-rules | no-routes | none-available | primary-unavailable | over-budget), never an exception, exceptdefineRuleswhich throws once with every problem and its path. - Explainable and deterministic: same rules + request + context (+ seeded rng) gives an identical plan.
explain(plan)prints the order, costs, origin layers and the full trace.
Not here
Executing requests, retries, HTTP, a model catalogue, prices (use ai-pricing), budget state (use ai-budget), persistence for sticky choices (bring a store), default model lists (each gateway ships its own package layer when it adopts this).