@tanstack/ai
Version:
Type-safe TypeScript AI SDK for streaming chat, tool calling, agents, structured outputs, and multimodal generation.
102 lines (101 loc) • 4.58 kB
TypeScript
/**
* How hard a model thinks. `off` asks for no thinking. The levels are ordered
* from least to most, and the clamp rule walks this order.
*/
export type ReasoningLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
/** Every level, from least to most thinking. */
export declare const REASONING_LEVELS: ReadonlyArray<ReasoningLevel>;
/**
* A model's levels: the provider value to send for each level the model has.
* A level with no entry is not supported.
*/
export type ReasoningLevels = Partial<Record<ReasoningLevel, string>>;
/**
* What a model supports, at the type level. Adapters declare it per model in
* `'~types'.reasoning`. `levels` is a union of the model's levels. `budget`
* says whether the model takes a thinking token budget.
*/
export interface ReasoningCapability {
levels: ReasoningLevel;
budget: boolean;
}
/**
* The `reasoning` option of `chat()`: a level, or an object. `summary` asks
* the provider to stream the thinking text (default `true`). `budgetTokens`
* sets an exact thinking budget, on models that take one.
*/
export type ReasoningOption<TCapability extends ReasoningCapability = ReasoningCapability> = TCapability['levels'] | ({
level: TCapability['levels'];
summary?: boolean;
} & (true extends TCapability['budget'] ? {
budgetTokens?: number;
} : {
budgetTokens?: never;
}));
/** The reasoning capability an adapter declares in `'~types'`, or `never`. */
export type AdapterReasoning<TAdapter> = TAdapter extends {
'~types': {
reasoning?: infer TCapability;
};
} ? TCapability : never;
/** The `reasoning` option a model's capability allows. `never` for a model that does not reason. */
export type ReasoningOptionFor<TCapability> = [TCapability] extends [never] ? never : TCapability extends ReasoningCapability ? ReasoningOption<TCapability> : never;
/** The `reasoning` an adapter gets in `TextOptions`, after `chat()` normalized it. */
export interface ReasoningRequest {
level: ReasoningLevel;
summary: boolean;
budgetTokens?: number;
}
/**
* A model's reasoning data at runtime. `false`: the model does not reason.
* Otherwise the levels it has, and whether it takes a token budget.
*/
export type ModelReasoning = false | {
levels: ReasoningLevels;
budget: boolean;
};
/**
* The type-level capability of a model's reasoning data, for an adapter's
* `'~types'.reasoning`. Provider packages keep the data in their model meta
* `as const`, and derive the levels from it with this type.
*/
export type ModelReasoningCapability<TReasoning extends {
levels: ReasoningLevels;
budget: boolean;
}> = {
levels: keyof TReasoning['levels'] & ReasoningLevel;
budget: TReasoning['budget'];
};
/** A level or an object, as the user passed it, into the one shape adapters read. */
export declare function normalizeReasoning(option: ReasoningOption | undefined): ReasoningRequest | undefined;
/**
* The levels a model supports, from least to most thinking: the levels in its
* data. A model that does not reason, or has no data, supports only `off`.
*/
export declare function supportedReasoningLevels(reasoning: ModelReasoning | undefined): ReadonlyArray<ReasoningLevel>;
/**
* A level the model supports: the level itself, else the nearest supported
* level above it, else the nearest below it, else `off`. The same rule as pi.
*/
export declare function clampReasoningLevel(reasoning: ModelReasoning | undefined, level: ReasoningLevel): ReasoningLevel;
/**
* pi's thinking budgets for budget-based models. `xhigh` and `max` get the
* `high` budget: budget-based models have no higher level.
*/
export declare const DEFAULT_REASONING_BUDGETS: Readonly<Record<Exclude<ReasoningLevel, 'off'>, number>>;
/** The thinking budget for a request: `budgetTokens`, else pi's table. `0` for `off`. */
export declare function reasoningBudget(request: ReasoningRequest): number;
/** A request resolved for one model: the clamped level and its provider value. */
export interface ResolvedReasoning {
level: ReasoningLevel;
/** The provider value to send for `level`. */
value: string;
summary: boolean;
budgetTokens?: number;
}
/**
* Resolve `request` for a model: clamp the level to the model's levels, and
* look up its provider value. `undefined` when there is nothing to send: no
* request, or a model that does not reason, has no data, or has no levels.
*/
export declare function resolveReasoning(request: ReasoningRequest | undefined, reasoning: ModelReasoning | undefined): ResolvedReasoning | undefined;