import { z } from "zod"; import type { EngineHealthReading } from "../shared/engine-health.js"; import type { ModelRegistry } from "../shared/types.js"; import type { WorkflowError, WorkflowRunDetail } from "./runtime.js"; /** `inherit` (the default) takes the engine's configured chain, `none` opts the * node out entirely, and a list is that node's own chain, used verbatim. * * Members are plain strings rather than the engine enum on purpose: this module * is reached from `model.ts`, which the repository parses definitions with, and * the engine list lives in a module that resolves the instance home on import. * Pulling that in decides `JINN_HOME` for anything that reads a definition. A * name no engine answers to is inert anyway — the walk only offers members the * model registry actually has. */ export declare const nodeFallbackSchema: z.ZodUnion, z.ZodLiteral<"none">, z.ZodArray]>; export type NodeFallback = z.infer; /** The configured `engines..fallback` chains, read fresh so a hot config * reload lands on the next attempt. */ export interface EngineChainSource { chainFor(engine: string): readonly string[]; } export interface EngineSubstitution { /** The engine this attempt runs on instead. */ engine: string; /** The engine the node's own precedence resolved to, and which could not serve. */ from: string; reason: string; } export interface SubstituteDeps { models: () => ModelRegistry; engineFallback?: EngineChainSource; /** Which engines are out of allowance right now, read fresh like `models` so a * record written mid-run lands on the next attempt. Absent = nothing is known * and every installed member is equally preferred. */ engineHealth?: () => EngineHealthReading; } /** * What a failure says about the ENGINE, or `undefined` when it says nothing — * because it is not the engine's own account of the turn, or because it names * something no other provider gets past. * * Exported because the substitution walk and the health record read the same * signal, and a run that swapped engines while the record still called the old * one healthy would be two answers to one question. */ export declare function engineAvailabilityFailure(failure: WorkflowError | undefined): { reason: string; resetsAt?: number; } | undefined; /** * Every engine that could stand in for `baseEngine`, in the order to try them. * * An inherited chain is walked transitively — an engine's own cover has cover of * its own — with a visited set, because config.yaml deliberately allows two * engines to name each other. Breadth first, so first preferences are exhausted * before their seconds. An explicit chain is the node's whole answer and is not * walked further. */ export declare function engineChain(baseEngine: string, fallback: NodeFallback | undefined, chainFor: (engine: string) => readonly string[]): string[]; /** * The substitution the node's next attempt should make, or `undefined` when it * should not make one — because the failure is one no other engine gets past, * because the node opted out, or because every alternative is already spent. * Both the retry boundary and the dispatcher ask through here, so they cannot * reach different answers about whether a run is out of options. */ export declare function selectSubstituteEngine(run: WorkflowRunDetail, nodeId: string, baseEngine: string, failure: WorkflowError | undefined, deps: SubstituteDeps): EngineSubstitution | undefined; //# sourceMappingURL=engine-chain.d.ts.map