@tanstack/ai
Version:
Type-safe TypeScript AI SDK for streaming chat, tool calling, agents, structured outputs, and multimodal generation.
44 lines (43 loc) • 2.32 kB
TypeScript
import { ChatMiddleware } from './middleware/types.js';
/**
* Shared type-level helpers for inferring the runtime `context` requirement
* from typed tools and middleware.
*
* These primitives are consumed by both the chat activity options
* (`./index.ts`, which merges tool + middleware requirements) and the tool
* execution layer (`./tools/tool-calls.ts`, which only sees tools). They live
* here so the two call sites share one definition instead of maintaining
* divergent copies.
*/
/** True only when `T` is exactly `unknown`. */
type IsUnknown<T> = unknown extends T ? [T] extends [unknown] ? true : false : false;
/**
* Drops an `unknown` context requirement to `never` so that untyped tools and
* middleware (which default `TContext` to `unknown`) contribute no requirement
* to the merged context.
*/
type KnownContext<T> = IsUnknown<T> extends true ? never : T;
/**
* Merge two inferred context requirements, treating `never` as "no
* requirement". Using this instead of a raw intersection keeps a `never`
* (untyped) contributor from collapsing the whole merge to `never`.
*/
export type MergeContext<TLeft, TRight> = [TLeft] extends [never] ? TRight : [TRight] extends [never] ? TLeft : TLeft & TRight;
/** Collapse a union of context requirements into their intersection. */
export type UnionToIntersection<T> = [T] extends [never] ? never : (T extends unknown ? (value: T) => void : never) extends (value: infer TIntersection) => void ? TIntersection : never;
/** Strip `undefined` from a context requirement. */
export type DefinedContext<T> = Exclude<T, undefined>;
/**
* Extract the `context` requirement declared by a tool execute function's
* second argument, dropping `unknown` (untyped) contexts to `never`.
*/
type ContextFromExecute<T> = T extends (...args: any) => any ? NonNullable<Parameters<T>[1]> extends {
context: infer TUserContext;
} ? KnownContext<TUserContext> : never : never;
/** Extract the context requirement declared by a single tool. */
export type ContextFromTool<T> = T extends {
execute?: infer TExecute;
} ? ContextFromExecute<TExecute> : never;
/** Extract the context requirement declared by a single middleware. */
export type ContextFromMiddleware<T> = T extends ChatMiddleware<infer TContext> ? KnownContext<TContext> : never;
export {};