@langchain/langgraph
Version:
208 lines (207 loc) • 8.54 kB
TypeScript
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