UNPKG

@langchain/langgraph

Version:
208 lines (207 loc) 8.54 kB
import { BaseChannel } from "../channels/base.js"; import { OverwriteValue } from "../constants.js"; import { RunnableLike } from "../pregel/runnable_types.js"; import { SerializableSchema } from "./types.js"; import { ReducedValue } from "./values/reduced.js"; import { UntrackedValue } from "./values/untracked.js"; import { DeltaValue } from "./values/delta.js"; import { JSONSchema } from "@langchain/core/utils/json_schema"; //#region src/state/schema.d.ts declare const STATE_SCHEMA_SYMBOL: unique symbol; /** * Maps a single StateSchema field definition to its corresponding Channel type. * * This utility type inspects the type of the field and returns an appropriate * `BaseChannel` type, parameterized with the state "value" and "input" types according to the field's shape. * * Rules: * - If the field (`F`) is a `DeltaValue<V, I>`, the channel will store values of type `V` * and accept input of type `I` (or an `Overwrite`). * - If the field (`F`) is a `ReducedValue<V, I>`, the channel will store values of type `V` * and accept input of type `I`. * - If the field is a `UntrackedValue<V>`, the channel will store and accept values of type `V`. * - If the field is a `SerializableSchema<I, O>`, the channel will store values of type `O` * (the schema's output/validated value) and accept input of type `I`. * - For all other types, a generic `BaseChannel<unknown, unknown>` is used as fallback. * * @template F - The StateSchema field type to map to a Channel type. * * @example * ```typescript * type MyField = ReducedValue<number, string>; * type ChannelType = StateSchemaFieldToChannel<MyField>; * // ChannelType is BaseChannel<number, string> * ``` */ type StateSchemaFieldToChannel<F> = F extends DeltaValue<infer V, infer I> ? BaseChannel<V, OverwriteValue<V> | I> : F extends ReducedValue<infer V, infer I> ? BaseChannel<V, OverwriteValue<V> | I> : F extends UntrackedValue<infer V> ? BaseChannel<V, V> : F extends SerializableSchema<infer I, infer O> ? BaseChannel<O, I> : BaseChannel<unknown, unknown>; /** * Converts StateSchema fields into a strongly-typed * State Definition object, where each field is mapped to its channel type. * * This utility type is used internally to create the shape of the state channels for a given schema, * substituting each field with the result of `StateSchemaFieldToChannel`. * * If you define a state schema as: * ```typescript * const fields = { * a: ReducedValue<number, string>(), * b: UntrackedValue<boolean>(), * c: SomeSerializableSchemaType, // SerializableSchema<in, out> * } * ``` * then `StateSchemaFieldsToStateDefinition<typeof fields>` yields: * ```typescript * { * a: BaseChannel<number, string>; * b: BaseChannel<boolean, boolean>; * c: BaseChannel<typeof schema's output type, typeof schema's input type>; * } * ``` * * @template TFields - The mapping of field names to StateSchema field types. * @returns An object type mapping field names to channel types. * * @see StateSchemaFieldToChannel */ type StateSchemaFieldsToStateDefinition<TFields extends StateSchemaFields> = { [K in keyof TFields]: StateSchemaFieldToChannel<TFields[K]> }; /** * Valid field types for StateSchema. * Either a LangGraph state value type or a raw schema (e.g., Zod schema). */ type StateSchemaField<Input = unknown, Output = Input> = DeltaValue<Input, Output> | ReducedValue<Input, Output> | UntrackedValue<Output> | SerializableSchema<Input, Output>; /** * Init object for StateSchema constructor. * Uses `any` to allow variance in generic types (e.g., ReducedValue<string, string[]>). */ type StateSchemaFields = { [key: string]: StateSchemaField<any, any>; }; /** * Infer the State type from a StateSchemaFields. * This is the type of the full state object. * * - ReducedValue<Value, Input> → Value (the stored type) * - UntrackedValue<Value> → Value * - SerializableSchema<Input, Output> → Output (the validated type) */ type InferStateSchemaValue<TFields extends StateSchemaFields> = { [K in keyof TFields]: TFields[K] extends DeltaValue<any, any> ? TFields[K]["ValueType"] : TFields[K] extends ReducedValue<any, any> ? TFields[K]["ValueType"] : TFields[K] extends UntrackedValue<any> ? TFields[K]["ValueType"] : TFields[K] extends SerializableSchema<any, infer TOutput> ? TOutput : never }; /** * Infer the Update type from a StateSchemaFields. * This is the type for partial updates to state. * * - ReducedValue<Value, Input> → Input (the reducer input type) * - UntrackedValue<Value> → Value * - SerializableSchema<Input, Output> → Input (what you provide) */ type InferStateSchemaUpdate<TFields extends StateSchemaFields> = { [K in keyof TFields]?: TFields[K] extends DeltaValue<infer V, infer I> ? OverwriteValue<V> | I : TFields[K] extends ReducedValue<infer V, infer I> ? OverwriteValue<V> | I : TFields[K] extends UntrackedValue<any> ? TFields[K]["ValueType"] : TFields[K] extends SerializableSchema<infer TInput, any> ? TInput : never }; /** * StateSchema provides a unified API for defining LangGraph state schemas. * * @example * ```ts * import { z } from "zod"; * import { StateSchema, ReducedValue, MessagesValue } from "@langchain/langgraph"; * * const AgentState = new StateSchema({ * // Prebuilt messages value * messages: MessagesValue, * // Basic LastValue channel from any standard schema * currentStep: z.string(), * // LastValue with native default * count: z.number().default(0), * // ReducedValue for fields needing reducers * history: new ReducedValue( * z.array(z.string()).default(() => []), * { * inputSchema: z.string(), * reducer: (current, next) => [...current, next], * } * ), * }); * * // Extract types * type State = typeof AgentState.State; * type Update = typeof AgentState.Update; * * // Use in StateGraph * const graph = new StateGraph(AgentState); * ``` */ declare class StateSchema<TFields extends StateSchemaFields> { readonly fields: TFields; /** * Symbol for runtime identification. * @internal Used by isInstance for runtime type checking */ private readonly [STATE_SCHEMA_SYMBOL]; /** * Type declaration for the full state type. * Use: `typeof myState.State` */ State: InferStateSchemaValue<TFields>; /** * Type declaration for the update type. * Use: `typeof myState.Update` */ Update: InferStateSchemaUpdate<TFields>; /** * Type declaration for node functions. * Use: `typeof myState.Node` to type node functions outside the graph builder. * * @example * ```typescript * const AgentState = new StateSchema({ * count: z.number().default(0), * }); * * const myNode: typeof AgentState.Node = (state) => { * return { count: state.count + 1 }; * }; * ``` */ Node: RunnableLike<InferStateSchemaValue<TFields>, InferStateSchemaUpdate<TFields>>; constructor(fields: TFields); /** * Get the channel definitions for use with StateGraph. * This converts the StateSchema fields into BaseChannel instances. */ getChannels(): Record<string, BaseChannel>; /** * Get the JSON schema for the full state type. * Used by Studio and API for schema introspection. */ getJsonSchema(): JSONSchema; /** * Get the JSON schema for the update/input type. * All fields are optional in updates. */ getInputJsonSchema(): JSONSchema; /** * Get the list of channel keys (excluding managed values). */ getChannelKeys(): string[]; /** * Get all keys (channels + managed values). */ getAllKeys(): string[]; /** * Validate input data against the schema. * This validates each field using its corresponding schema. * * @param data - The input data to validate * @returns The validated data with coerced types */ validateInput<T>(data: T): Promise<T>; /** * Type guard to check if a value is a StateSchema instance. * * @param value - The value to check. * @returns True if the value is a StateSchema instance with the correct runtime tag. */ static isInstance<TFields extends StateSchemaFields>(value: StateSchema<TFields>): value is StateSchema<TFields>; static isInstance(value: unknown): value is StateSchema<any>; } type AnyStateSchema = StateSchema<any>; //#endregion export { AnyStateSchema, InferStateSchemaUpdate, InferStateSchemaValue, StateSchema, StateSchemaField, StateSchemaFieldToChannel, StateSchemaFields, StateSchemaFieldsToStateDefinition }; //# sourceMappingURL=schema.d.ts.map