{"version":3,"file":"schema.cjs","names":["ReducedValue","getSchemaDefaultGetter","BinaryOperatorAggregate","UntrackedValue","UntrackedValueChannel","isStandardSchema","LastValue","getJsonSchemaFromSchema"],"sources":["../../src/state/schema.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { JSONSchema } from \"@langchain/core/utils/json_schema\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nimport type { RunnableLike } from \"../pregel/runnable_types.js\";\nimport {\n  BaseChannel,\n  LastValue,\n  BinaryOperatorAggregate,\n} from \"../channels/index.js\";\nimport { UntrackedValueChannel } from \"../channels/untracked_value.js\";\n\nimport type { SerializableSchema } from \"./types.js\";\nimport { isStandardSchema } from \"./types.js\";\nimport { getJsonSchemaFromSchema, getSchemaDefaultGetter } from \"./adapter.js\";\nimport type { OverwriteValue } from \"../constants.js\";\nimport { ReducedValue } from \"./values/reduced.js\";\nimport { UntrackedValue } from \"./values/untracked.js\";\n\nconst STATE_SCHEMA_SYMBOL = Symbol.for(\"langgraph.state.state_schema\");\n\n/**\n * Maps a single StateSchema field definition to its corresponding Channel type.\n *\n * This utility type inspects the type of the field and returns an appropriate\n * `BaseChannel` type, parameterized with the state \"value\" and \"input\" types according to the field's shape.\n *\n * Rules:\n * - If the field (`F`) is a `ReducedValue<V, I>`, the channel will store values of type `V`\n *   and accept input of type `I`.\n * - If the field is a `UntrackedValue<V>`, the channel will store and accept values of type `V`.\n * - If the field is a `SerializableSchema<I, O>`, the channel will store values of type `O`\n *   (the schema's output/validated value) and accept input of type `I`.\n * - For all other types, a generic `BaseChannel<unknown, unknown>` is used as fallback.\n *\n * @template F - The StateSchema field type to map to a Channel type.\n *\n * @example\n * ```typescript\n * type MyField = ReducedValue<number, string>;\n * type ChannelType = StateSchemaFieldToChannel<MyField>;\n * // ChannelType is BaseChannel<number, string>\n * ```\n */\nexport type StateSchemaFieldToChannel<F> =\n  F extends ReducedValue<infer V, infer I>\n    ? BaseChannel<V, OverwriteValue<V> | I>\n    : F extends UntrackedValue<infer V>\n      ? BaseChannel<V, V>\n      : F extends SerializableSchema<infer I, infer O>\n        ? BaseChannel<O, I>\n        : BaseChannel<unknown, unknown>;\n\n/**\n * Converts StateSchema fields into a strongly-typed\n * State Definition object, where each field is mapped to its channel type.\n *\n * This utility type is used internally to create the shape of the state channels for a given schema,\n * substituting each field with the result of `StateSchemaFieldToChannel`.\n *\n * If you define a state schema as:\n * ```typescript\n * const fields = {\n *   a: ReducedValue<number, string>(),\n *   b: UntrackedValue<boolean>(),\n *   c: SomeSerializableSchemaType, // SerializableSchema<in, out>\n * }\n * ```\n * then `StateSchemaFieldsToStateDefinition<typeof fields>` yields:\n * ```typescript\n * {\n *   a: BaseChannel<number, string>;\n *   b: BaseChannel<boolean, boolean>;\n *   c: BaseChannel<typeof schema's output type, typeof schema's input type>;\n * }\n * ```\n *\n * @template TFields - The mapping of field names to StateSchema field types.\n * @returns An object type mapping field names to channel types.\n *\n * @see StateSchemaFieldToChannel\n */\nexport type StateSchemaFieldsToStateDefinition<\n  TFields extends StateSchemaFields,\n> = {\n  [K in keyof TFields]: StateSchemaFieldToChannel<TFields[K]>;\n};\n\n/**\n * Valid field types for StateSchema.\n * Either a LangGraph state value type or a raw schema (e.g., Zod schema).\n */\nexport type StateSchemaField<Input = unknown, Output = Input> =\n  | ReducedValue<Input, Output>\n  | UntrackedValue<Output>\n  | SerializableSchema<Input, Output>;\n\n/**\n * Init object for StateSchema constructor.\n * Uses `any` to allow variance in generic types (e.g., ReducedValue<string, string[]>).\n */\nexport type StateSchemaFields = {\n  [key: string]: StateSchemaField<any, any>;\n};\n\n/**\n * Infer the State type from a StateSchemaFields.\n * This is the type of the full state object.\n *\n * - ReducedValue<Value, Input> → Value (the stored type)\n * - UntrackedValue<Value> → Value\n * - SerializableSchema<Input, Output> → Output (the validated type)\n */\nexport type InferStateSchemaValue<TFields extends StateSchemaFields> = {\n  [K in keyof TFields]: TFields[K] extends ReducedValue<any, any>\n    ? TFields[K][\"ValueType\"]\n    : TFields[K] extends UntrackedValue<any>\n      ? TFields[K][\"ValueType\"]\n      : TFields[K] extends SerializableSchema<any, infer TOutput>\n        ? TOutput\n        : never;\n};\n\n/**\n * Infer the Update type from a StateSchemaFields.\n * This is the type for partial updates to state.\n *\n * - ReducedValue<Value, Input> → Input (the reducer input type)\n * - UntrackedValue<Value> → Value\n * - SerializableSchema<Input, Output> → Input (what you provide)\n */\nexport type InferStateSchemaUpdate<TFields extends StateSchemaFields> = {\n  [K in keyof TFields]?: TFields[K] extends ReducedValue<infer V, infer I>\n    ? OverwriteValue<V> | I\n    : TFields[K] extends UntrackedValue<any>\n      ? TFields[K][\"ValueType\"]\n      : TFields[K] extends SerializableSchema<infer TInput, any>\n        ? TInput\n        : never;\n};\n\n/**\n * StateSchema provides a unified API for defining LangGraph state schemas.\n *\n * @example\n * ```ts\n * import { z } from \"zod\";\n * import { StateSchema, ReducedValue, MessagesValue } from \"@langchain/langgraph\";\n *\n * const AgentState = new StateSchema({\n *   // Prebuilt messages value\n *   messages: MessagesValue,\n *   // Basic LastValue channel from any standard schema\n *   currentStep: z.string(),\n *   // LastValue with native default\n *   count: z.number().default(0),\n *   // ReducedValue for fields needing reducers\n *   history: new ReducedValue(\n *     z.array(z.string()).default(() => []),\n *     {\n *       inputSchema: z.string(),\n *       reducer: (current, next) => [...current, next],\n *     }\n *   ),\n * });\n *\n * // Extract types\n * type State = typeof AgentState.State;\n * type Update = typeof AgentState.Update;\n *\n * // Use in StateGraph\n * const graph = new StateGraph(AgentState);\n * ```\n */\nexport class StateSchema<TFields extends StateSchemaFields> {\n  /**\n   * Symbol for runtime identification.\n   * @internal Used by isInstance for runtime type checking\n   */\n  // @ts-expect-error - Symbol is read via `in` operator in isInstance\n  private readonly [STATE_SCHEMA_SYMBOL] = true;\n\n  /**\n   * Type declaration for the full state type.\n   * Use: `typeof myState.State`\n   */\n  declare State: InferStateSchemaValue<TFields>;\n\n  /**\n   * Type declaration for the update type.\n   * Use: `typeof myState.Update`\n   */\n  declare Update: InferStateSchemaUpdate<TFields>;\n\n  /**\n   * Type declaration for node functions.\n   * Use: `typeof myState.Node` to type node functions outside the graph builder.\n   *\n   * @example\n   * ```typescript\n   * const AgentState = new StateSchema({\n   *   count: z.number().default(0),\n   * });\n   *\n   * const myNode: typeof AgentState.Node = (state) => {\n   *   return { count: state.count + 1 };\n   * };\n   * ```\n   */\n  declare Node: RunnableLike<\n    InferStateSchemaValue<TFields>,\n    InferStateSchemaUpdate<TFields>\n  >;\n\n  constructor(readonly fields: TFields) {}\n\n  /**\n   * Get the channel definitions for use with StateGraph.\n   * This converts the StateSchema fields into BaseChannel instances.\n   */\n  getChannels(): Record<string, BaseChannel> {\n    const channels: Record<string, BaseChannel> = {};\n\n    for (const [key, value] of Object.entries(this.fields)) {\n      if (ReducedValue.isInstance(value)) {\n        // ReducedValue -> BinaryOperatorAggregate\n        const defaultGetter = getSchemaDefaultGetter(value.valueSchema);\n        channels[key] = new BinaryOperatorAggregate(\n          value.reducer,\n          defaultGetter\n        );\n      } else if (UntrackedValue.isInstance(value)) {\n        // UntrackedValue -> UntrackedValueChannel\n        const defaultGetter = value.schema\n          ? getSchemaDefaultGetter(value.schema)\n          : undefined;\n        channels[key] = new UntrackedValueChannel({\n          guard: value.guard,\n          initialValueFactory: defaultGetter,\n        });\n      } else if (isStandardSchema(value)) {\n        // Plain schema -> LastValue channel\n        const defaultGetter = getSchemaDefaultGetter(value);\n        channels[key] = new LastValue(defaultGetter);\n      } else {\n        throw new Error(\n          `Invalid state field \"${key}\": must be a schema, ReducedValue, UntrackedValue, or ManagedValue`\n        );\n      }\n    }\n\n    return channels;\n  }\n\n  /**\n   * Get the JSON schema for the full state type.\n   * Used by Studio and API for schema introspection.\n   */\n  getJsonSchema(): JSONSchema {\n    const properties: Record<string, JSONSchema> = {};\n    const required: string[] = [];\n\n    for (const [key, value] of Object.entries(this.fields)) {\n      let fieldSchema: JSONSchema | undefined;\n\n      if (ReducedValue.isInstance(value)) {\n        fieldSchema = getJsonSchemaFromSchema(value.valueSchema) as JSONSchema;\n        // Merge jsonSchemaExtra (e.g. langgraph_type) into the field schema,\n        // even if base schema is undefined\n        if (value.jsonSchemaExtra) {\n          fieldSchema = { ...(fieldSchema ?? {}), ...value.jsonSchemaExtra };\n        }\n      } else if (UntrackedValue.isInstance(value)) {\n        fieldSchema = value.schema\n          ? (getJsonSchemaFromSchema(value.schema) as JSONSchema)\n          : undefined;\n      } else if (isStandardSchema(value)) {\n        fieldSchema = getJsonSchemaFromSchema(value) as JSONSchema;\n      }\n\n      if (fieldSchema) {\n        properties[key] = fieldSchema;\n\n        // Field is required if it doesn't have a default\n        let hasDefault = false;\n        if (ReducedValue.isInstance(value)) {\n          hasDefault = getSchemaDefaultGetter(value.valueSchema) !== undefined;\n        } else if (UntrackedValue.isInstance(value)) {\n          hasDefault = value.schema\n            ? getSchemaDefaultGetter(value.schema) !== undefined\n            : false;\n        } else {\n          hasDefault = getSchemaDefaultGetter(value) !== undefined;\n        }\n\n        if (!hasDefault) {\n          required.push(key);\n        }\n      }\n    }\n\n    return {\n      type: \"object\",\n      properties,\n      required: required.length > 0 ? required : undefined,\n    };\n  }\n\n  /**\n   * Get the JSON schema for the update/input type.\n   * All fields are optional in updates.\n   */\n  getInputJsonSchema(): JSONSchema {\n    const properties: Record<string, JSONSchema> = {};\n\n    for (const [key, value] of Object.entries(this.fields)) {\n      let fieldSchema: JSONSchema | undefined;\n\n      if (ReducedValue.isInstance(value)) {\n        // Use input schema for updates\n        fieldSchema = getJsonSchemaFromSchema(value.inputSchema) as JSONSchema;\n        // Merge jsonSchemaExtra (e.g. langgraph_type) into the field schema,\n        // even if base schema is undefined\n        if (value.jsonSchemaExtra) {\n          fieldSchema = { ...(fieldSchema ?? {}), ...value.jsonSchemaExtra };\n        }\n      } else if (UntrackedValue.isInstance(value)) {\n        fieldSchema = value.schema\n          ? (getJsonSchemaFromSchema(value.schema) as JSONSchema)\n          : undefined;\n      } else if (isStandardSchema(value)) {\n        fieldSchema = getJsonSchemaFromSchema(value) as JSONSchema;\n      }\n\n      if (fieldSchema) {\n        properties[key] = fieldSchema;\n      }\n    }\n\n    return {\n      type: \"object\",\n      properties,\n    };\n  }\n\n  /**\n   * Get the list of channel keys (excluding managed values).\n   */\n  getChannelKeys(): string[] {\n    return Object.entries(this.fields).map(([key]) => key);\n  }\n\n  /**\n   * Get all keys (channels + managed values).\n   */\n  getAllKeys(): string[] {\n    return Object.keys(this.fields);\n  }\n\n  /**\n   * Validate input data against the schema.\n   * This validates each field using its corresponding schema.\n   *\n   * @param data - The input data to validate\n   * @returns The validated data with coerced types\n   */\n  async validateInput<T>(data: T): Promise<T> {\n    if (data == null || typeof data !== \"object\") {\n      return data;\n    }\n\n    const result: Record<string, unknown> = {};\n\n    for (const [key, value] of Object.entries(data)) {\n      const fieldDef = this.fields[key];\n\n      if (fieldDef === undefined) {\n        // Unknown field, pass through\n        result[key] = value;\n        continue;\n      }\n\n      // Get the schema to use for validation\n      let schema: StandardSchemaV1 | undefined;\n\n      if (ReducedValue.isInstance(fieldDef)) {\n        schema = fieldDef.inputSchema;\n      } else if (UntrackedValue.isInstance(fieldDef)) {\n        schema = fieldDef.schema;\n      } else if (isStandardSchema(fieldDef)) {\n        schema = fieldDef;\n      }\n\n      if (schema) {\n        // Validate using standard schema\n        const validationResult = await schema[\"~standard\"].validate(value);\n        if (validationResult.issues) {\n          throw new Error(\n            `Validation failed for field \"${key}\": ${JSON.stringify(\n              validationResult.issues\n            )}`\n          );\n        }\n        result[key] = validationResult.value;\n      } else {\n        // No schema or not a standard schema, pass through\n        result[key] = value;\n      }\n    }\n\n    return result as T;\n  }\n\n  /**\n   * Type guard to check if a value is a StateSchema instance.\n   *\n   * @param value - The value to check.\n   * @returns True if the value is a StateSchema instance with the correct runtime tag.\n   */\n  static isInstance<TFields extends StateSchemaFields>(\n    value: StateSchema<TFields>\n  ): value is StateSchema<TFields>;\n\n  static isInstance(value: unknown): value is StateSchema<any>;\n\n  static isInstance<TFields extends StateSchemaFields>(\n    value: unknown\n  ): value is StateSchema<TFields> {\n    return (\n      typeof value === \"object\" &&\n      value !== null &&\n      STATE_SCHEMA_SYMBOL in value &&\n      value[STATE_SCHEMA_SYMBOL] === true\n    );\n  }\n}\n\nexport type AnyStateSchema = StateSchema<any>;\n"],"mappings":"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"}