@tanstack/ai
Version:
Type-safe TypeScript AI SDK for streaming chat, tool calling, agents, structured outputs, and multimodal generation.
161 lines (160 loc) • 5.89 kB
TypeScript
import { InternalLogger } from '../../logger/internal-logger.js';
import { TokenUsage } from '../../types.js';
/**
* Configuration for evaluate adapter instances.
*/
export interface EvaluateAdapterConfig {
apiKey?: string;
baseUrl?: string;
timeout?: number;
headers?: Record<string, string>;
}
/**
* Shared JSON value for `state` and question `instructions`.
* A JSON array is one value, not a batch.
*/
export type EvaluateJsonValue = string | object | Array<unknown>;
/** Content the model judges. A JSON array is one state, not a batch. */
export type EvaluateState = EvaluateJsonValue;
/** Question text. Matches TypeSafe: string, object, or array. */
export type EvaluateInstructions = EvaluateJsonValue;
/**
* TypeSafe choice question on the adapter wire.
*
* Generic parameters:
* - TOptions: option key to description (or `null` when the key is enough)
*/
export interface WireChoiceQuestion<TOptions extends Record<string, string | null> = Record<string, string | null>> {
type: 'choice';
instructions: EvaluateInstructions;
criteria: TOptions;
}
/**
* TypeSafe score question on the adapter wire.
*
* Generic parameters:
* - TLevels: ordered level labels, at least two
*/
export interface WireScoreQuestion<TLevels extends ReadonlyArray<string> = ReadonlyArray<string>> {
type: 'score';
instructions: EvaluateInstructions;
criteria: TLevels;
}
/**
* TypeSafe yes/no question on the adapter wire.
* Public helpers call this `boolean`. The wire type is `noul`.
*/
export interface WireNoulQuestion {
type: 'noul';
instructions: EvaluateInstructions;
criteria?: {
true?: string;
false?: string;
};
}
/** Question payload adapters send to the provider. */
export type WireQuestion = WireChoiceQuestion | WireScoreQuestion | WireNoulQuestion;
/** TypeSafe choice answer. Adapters do not invent a public `.value`. */
export interface WireChoiceAnswer {
type: 'choice';
choice: string;
probabilities: Record<string, number>;
confidence: number;
}
/** TypeSafe score answer. `score` is the raw fraction. */
export interface WireScoreAnswer {
type: 'score';
score: number;
legend: Record<string, string>;
probabilities: Record<string, number>;
confidence: number;
}
/** TypeSafe yes/no answer. `noul` is P(true). */
export interface WireNoulAnswer {
type: 'noul';
noul: number;
}
/** Provider payload for one question. The activity maps this to a unified answer. */
export type WireAnswer = WireChoiceAnswer | WireScoreAnswer | WireNoulAnswer;
/**
* Options passed to {@link EvaluateAdapter.evaluate}.
*/
export interface EvaluateOptions<TProviderOptions extends object = Record<string, unknown>> {
model: string;
/** Shared state every question judges. A JSON array is one state, not a batch. */
state: EvaluateState;
/** TypeSafe wire questions, keyed by the caller's question ids. */
questions: Record<string, WireQuestion>;
/** Provider-specific options forwarded by `decide()`. */
modelOptions?: TProviderOptions;
/** Forwarded to the provider request for cancellation. */
abortSignal?: AbortSignal;
/**
* Internal logger threaded from `decide()`. Adapters must call
* `logger.request()` before the provider call and `logger.errors()` in catch
* blocks.
*/
logger: InternalLogger;
}
/**
* Provider-level evaluate result. Adapters return the wire payload plus usage.
* The activity maps answers to the unified public shape.
*/
export interface EvaluateAdapterResult {
/** Resolved model id from the provider. */
model: string;
answers: Record<string, WireAnswer>;
usage: TokenUsage;
}
/**
* Evaluate adapter interface with pre-resolved generics.
*
* An adapter is created by a provider function: `provider('model')` → `adapter`.
* All type resolution happens at the provider call site, not in this interface.
*
* Generic parameters:
* - TModel: The specific model name (e.g. `'jev-latest'`)
* - TProviderOptions: Provider-specific options (already resolved)
*/
export interface EvaluateAdapter<TModel extends string = string, TProviderOptions extends object = Record<string, unknown>> {
/** Discriminator for adapter kind */
readonly kind: 'evaluate';
/** Adapter name identifier */
readonly name: string;
/** The model this adapter is configured for */
readonly model: TModel;
/**
* @internal Type-only properties for inference. Not assigned at runtime.
*/
'~types': {
providerOptions: TProviderOptions;
};
/**
* Evaluate typed questions against `state`. Return the provider payload.
* Do not invent unified `.value` fields. The activity maps wire answers.
*/
evaluate: (options: EvaluateOptions<TProviderOptions>) => Promise<EvaluateAdapterResult>;
}
/**
* An EvaluateAdapter with any/unknown type parameters.
* Useful as a constraint in generic functions and interfaces.
*/
export type AnyEvaluateAdapter = EvaluateAdapter<any, any>;
/**
* Abstract base class for evaluate adapters.
* Extend this class to implement an evaluate adapter for a specific provider.
*
* Generic parameters match EvaluateAdapter. The provider function resolves them.
*/
export declare abstract class BaseEvaluateAdapter<TModel extends string = string, TProviderOptions extends object = Record<string, unknown>> implements EvaluateAdapter<TModel, TProviderOptions> {
readonly kind: "evaluate";
abstract readonly name: string;
readonly model: TModel;
'~types': {
providerOptions: TProviderOptions;
};
protected config: EvaluateAdapterConfig;
constructor(config: EvaluateAdapterConfig | undefined, model: TModel);
abstract evaluate(options: EvaluateOptions<TProviderOptions>): Promise<EvaluateAdapterResult>;
protected generateId(): string;
}