@tanstack/ai
Version:
Type-safe TypeScript AI SDK for streaming chat, tool calling, agents, structured outputs, and multimodal generation.
92 lines (91 loc) • 3.82 kB
TypeScript
import { BaseTextAdapter, StructuredOutputOptions, StructuredOutputResult } from '../activities/chat/adapter.js';
import { AdapterYieldChunk } from '../utilities/adapter-yield-chunk.js';
import { DefaultMessageMetadataByModality, Modality, TextOptions } from '../types.js';
/** One scripted answer of the fake model. */
export interface FakeResponse {
/** The visible text. */
text?: string;
/** Thinking text, streamed before the answer. */
thinking?: string;
/**
* Tool calls. `id` defaults to `fake-call-<fake>-<call>-<index>`, unique
* across fakes.
*/
toolCalls?: Array<{
name: string;
input?: unknown;
id?: string;
}>;
/** Default: `'tool_calls'` when there are tool calls, else `'stop'`. */
finishReason?: 'stop' | 'length' | 'content_filter' | 'tool_calls';
/** Fail the call with a `RUN_ERROR` that has this message. */
error?: string;
}
/** Counters of a fake adapter. */
export interface FakeTextState {
/** How many model calls the fake answered. */
callCount: number;
}
/** A scripted answer, or a function that builds one from the request. */
export type FakeResponseStep = FakeResponse | ((call: {
request: TextOptions;
state: FakeTextState;
}) => FakeResponse | Promise<FakeResponse>);
export interface FakeTextOptions<TModel extends string> {
/** The model id. Default `'fake-model'`. */
model?: TModel;
/** The model's context window in tokens. Data for the caller. */
contextWindow?: number;
/** Stream the text at this many tokens (4 characters each) per second. */
tokensPerSecond?: number;
/**
* Estimate prompt caching per `threadId`: the part of the request that
* matches the thread's previous request counts as cached.
*/
cache?: boolean;
}
/**
* A text adapter that answers from a script. Use it to test `chat()`, tools,
* and middleware with no network and no API key. Create it with `fakeText()`.
*/
export declare class FakeTextAdapter<TModel extends string> extends BaseTextAdapter<TModel, Record<string, unknown>, ReadonlyArray<Modality>, DefaultMessageMetadataByModality> {
readonly name = "fake";
/** The context window from the options. */
readonly contextWindow: number | undefined;
readonly state: FakeTextState;
private queue;
private readonly previousRequests;
private readonly options;
private readonly instance;
constructor(model: TModel, options: FakeTextOptions<TModel>);
/** Replace the queue of answers. */
setResponses(responses: Array<FakeResponseStep>): void;
/** Add answers to the end of the queue. */
appendResponses(responses: Array<FakeResponseStep>): void;
/** How many answers are still queued. */
pendingResponses(): number;
private nextResponse;
private usage;
private pace;
chatStream(options: TextOptions): AsyncIterable<AdapterYieldChunk>;
/** Answers with the next queued response. Its `text` must be JSON. */
structuredOutput(options: StructuredOutputOptions<Record<string, unknown>>): Promise<StructuredOutputResult<unknown>>;
}
/**
* Create a scripted fake text adapter for tests. Queue answers with
* `setResponses`, then pass the fake to `chat()` as its adapter.
*
* - An empty queue answers with a `RUN_ERROR`: "No more fake responses queued".
* - Usage is estimated as `ceil(characters / 4)` over the request and the
* answer, so a long message can overflow a small `contextWindow`.
*
* @example
* ```ts
* const fake = fakeText()
* fake.setResponses([{ text: 'Hello' }])
* for await (const chunk of chat({ adapter: fake, messages })) {
* // ...
* }
* ```
*/
export declare function fakeText<const TModel extends string = 'fake-model'>(options?: FakeTextOptions<TModel>): FakeTextAdapter<TModel>;