/**
* Provider-neutral reasoning controls discovered for one opaque model id.
*
* Effort ids deliberately remain strings: providers can add values without a
* RouteKit release. Ordering is provider-authored and therefore suitable for
* selector presentation and deterministic cross-wire aliases.
*/
export type ReasoningEffortOption = {
id: string;
label?: string;
description?: string;
aliases?: readonly string[];
};
export type ReasoningCapabilityProvenance = "provider" | "config" | "builtin" | "unknown";
export type ReasoningCapabilityStatus = "supported" | "unsupported" | "unknown";
export type ModelReasoningCapabilities = {
status: ReasoningCapabilityStatus;
efforts?: readonly ReasoningEffortOption[];
defaultEffort?: string;
budget?: {
minTokens?: number;
maxTokens?: number;
defaultTokens?: number;
};
adaptive?: boolean;
/**
* Opaque provider-adapter discriminator. Model routing never interprets it;
* only the provider source that authored the capability may consume it.
*/
wireShape?: string;
provenance: ReasoningCapabilityProvenance;
refreshedAt?: string;
};
export type ReasoningSelection = {
mode: "auto";
} | {
mode: "disabled";
} | {
mode: "adaptive";
} | {
mode: "effort";
effort: string;
} | {
mode: "budget";
budgetTokens: number;
};
/**
* Canonical effort descriptor for picker and catalog projection.
*
* `label` is always populated (`description ?? label ?? id`) so surfaces do
* not reimplement presentation fallbacks.
*/
export type ReasoningEffortDescriptor = {
id: string;
label: string;
aliases: readonly string[];
};
/**
* One served model as seen by a client surface.
*
* `clientModel` is the surface-specific spelling used for discovery and
* launch (for example Claude's `claude-` alias or Cursor's `routekit/`
* namespace). Qualification happens against that spelling plus the served
* `model` id so both advertised and unsuffixed requests resolve.
*/
export type ModelEffortVariantEntry = {
model: string;
clientModel: string;
reasoning?: ModelReasoningCapabilities;
};
export type ModelEffortVariant = {
/** Client-facing model id, including any effort qualification. */
id: string;
/** Canonical served model id. */
model: string;
selection: ReasoningSelection;
effort?: ReasoningEffortDescriptor;
};
/**
* Surface-specific spelling of effort-qualified model ids.
*
* A new surface supplies only these callbacks. Filtering, alias normalization,
* exact-base precedence, and structured errors stay in contracts.
*/
export type ModelEffortVariantCodec = {
qualify(baseClientModel: string, effort: string): string;
/**
* When `candidate` is a qualification of `baseClientModel`, return the
* opaque effort token. Must not invent tokens for unrelated models.
*/
effortToken(candidate: string, baseClientModel: string): string | undefined;
};
export type ReasoningSelectionErrorCode = "unknown_capability" | "unsupported" | "unsupported_effort" | "unsupported_adaptive" | "unsupported_budget" | "budget_out_of_range" | "invalid_selection";
export type ReasoningSelectionResolution = {
ok: true;
selection: ReasoningSelection;
} | {
ok: false;
code: ReasoningSelectionErrorCode;
message: string;
};
export type ModelEffortVariantErrorCode = "unknown_model" | "unsupported_effort" | "collision";
export type ModelEffortVariantResolution = {
ok: true;
model: string;
clientModel: string;
selection: ReasoningSelection;
} | {
ok: false;
code: ModelEffortVariantErrorCode;
message: string;
};
/** Default `:` qualification used by Claude and Cursor pickers. */
export declare const EFFORT_QUALIFIED_MODEL_CODEC: ModelEffortVariantCodec;
export declare function resolveReasoningEffort(capabilities: ModelReasoningCapabilities, requested: string): string | undefined;
/**
* Ordered unique effort descriptors advertised for one model.
*
* Only `status: "supported"` capabilities contribute. Aliases are retained on
* the descriptor for resolution but are never separate picker entries.
*/
export declare function reasoningEffortDescriptors(capabilities: ModelReasoningCapabilities | undefined): ReasoningEffortDescriptor[];
export declare function parseReasoningSelection(value: unknown): ReasoningSelectionResolution;
export declare function reasoningSelectionEquals(left: ReasoningSelection, right: ReasoningSelection): boolean;
/**
* Validate and canonicalize a selection against discovered capabilities.
*
* Codex's historical `"none"` → disabled mapping stays at the gateway boundary;
* this helper treats `"none"` like any other opaque effort id.
*/
export declare function resolveReasoningSelection(capabilities: ModelReasoningCapabilities | undefined, selection: ReasoningSelection): ReasoningSelectionResolution;
export declare function reasoningSelectionFromEffort(capabilities: ModelReasoningCapabilities | undefined, requested: string): ReasoningSelectionResolution;
/**
* Expand one served model into the base client id plus one variant per
* discovered effort. Aliases are not advertised as separate entries.
*/
export declare function enumerateModelEffortVariants(entry: ModelEffortVariantEntry, codec?: ModelEffortVariantCodec): ModelEffortVariant[];
/**
* Detect generated client ids that collide across distinct served models or
* effort selections. Exact base ids always win at resolve time; collisions are
* reported so surfaces can refuse to advertise ambiguous catalogs.
*/
export declare function modelEffortVariantCollisions(entries: readonly ModelEffortVariantEntry[], codec?: ModelEffortVariantCodec): string[];
/**
* Resolve a client-facing model id back to its served model and selection.
*
* Exact served/`clientModel` ids win before qualification. Qualification is
* codec-defined against known bases (longest first), never a global delimiter
* split, so opaque model ids that themselves contain `:` remain addressable.
*/
export declare function resolveModelEffortVariant(requested: string, entries: readonly ModelEffortVariantEntry[], codec?: ModelEffortVariantCodec): ModelEffortVariantResolution;
/**
* Project a launch/session effort selection onto a client model id.
*
* Surfaces that encode effort in the model name use this helper so launchers,
* pickers, and gateway discovery stay aligned. Non-effort selections leave the
* base id unchanged.
*/
export declare function effortQualifiedClientModel(baseClientModel: string, selection: ReasoningSelection | undefined, codec?: ModelEffortVariantCodec): string;
/**
* Conservative Codex picker heuristic for a model's discovered provenance.
*
* Codex uses the Responses API, so OpenRouter models are listed only when
* their existing reasoning metadata says `supported`. Other providers remain
* eligible when capability discovery is absent or inconclusive. This is only
* a picker heuristic; it does not guarantee compatibility with encrypted
* Responses reasoning state or continuation across models.
*/
export declare function isCodexPickerEligibleModel(input: {
provider?: string;
reasoning?: Pick;
}): boolean;