@sema-agent/core
Version:
Stateless, task-oriented AI agent core
42 lines (41 loc) • 2.74 kB
TypeScript
import type { Brain } from "../core/types.js";
export interface RoutingBrainOptions {
/** Which field of the Model selects the route. Default "provider". */
by?: "provider" | "api";
/** Brain used when no route matches. If omitted, an unmatched model yields an error. */
fallback?: Brain;
}
/** The two `Model` fields a route can be named by — a catalog entry that carries only a provider word is as good a subject as a whole `Model`. */
type RouteWords = {
readonly provider?: string | undefined;
readonly api?: string | undefined;
};
/**
* THE judge of which line serves a model: the model's route word (`provider`, or `api` when `by` says so) IF the route table
* has an OWN route under that word, else `undefined` — the fallback (the deployment's gateway) serves it. A word the model
* carries without a route, and a model with no string word at all, both answer `undefined`: a route that is not mounted is
* not a line, whatever the model says.
*
* `routes` is the route TABLE itself — the very object a host hands {@link createRoutingBrain}, which asks this function for
* every request — so the judge and the router answer from one reading of one table, whatever its shape. The question is
* `Object.hasOwn(routes, word)`: it evaluates no entry and lists no keys, so a non-enumerable own route is a route, a lazily
* keyed table is asked about the one name it is asked about, and a name the table only inherits (`constructor`, `__proto__`)
* is not a route. The judge never reads a route's value: a route mounted under the word IS the line, and when its value is not
* a brain the router fails that request on that line (an error terminal naming the route) rather than moving it to the
* fallback — so the line this answers is the line the request was sent to, either way. A table that cannot answer the question
* (it is not an object, or its trap throws) throws here, and the router fails the request with an error terminal.
*/
export declare function brainLaneOf(model: RouteWords, routes: Readonly<Record<string, unknown>>, by?: NonNullable<RoutingBrainOptions["by"]>): string | undefined;
/**
* Route to different brains by a Model field (default `model.provider`). Lets one Runner serve
* multiple providers/gateways; compose with `createFailoverBrain` for per-route failover. Which route serves a
* model is {@link brainLaneOf}'s answer.
*
* @example
* createRoutingBrain({
* "vllm": createOpenAIBrain({ baseUrl: VLLM }),
* "openai": createOpenAIBrain({ baseUrl: OPENAI, apiKey }),
* }, { fallback: createOpenAIBrain({ baseUrl: VLLM }) });
*/
export declare function createRoutingBrain(routes: Record<string, Brain>, opts?: RoutingBrainOptions): Brain;
export {};