AI.Tools.Params (fnord v0.9.29)

View Source

JSON Schema validation and coercion for tool call arguments.

Provides centralized argument validation for all AI tools, including type coercion, required field checking, enum validation, and support for JSON Schema composition keywords (anyOf, oneOf, allOf). $ref/$defs are not supported.

Usage

Called centrally by AI.Tools.perform_tool_call/3 to validate arguments against a tool's spec before execution. Also used by Frobs.Prompt for interactive parameter collection.

Summary

Functions

Check whether all sub-schemas in a composition have simple, promptable types (string, integer, number, boolean).

Merge a list of schemas into a single schema. Used for allOf resolution.

Recursively normalize a schema map to string keys, including any composition keyword sub-schemas.

Normalize a parsed JSON spec into a canonical map with string keys.

Check whether a composition schema represents a nullable type -- i.e., anyOf/oneOf with exactly two sub-schemas where one is {type: "null"}.

Return a deterministic parameter list: [{name, schema, required?}].

Resolve a schema to its effective type. Returns the type string for flat schemas, or {:composition, keyword, sub_schemas} for composition schemas.

Validate that required keys are present and coerce all provided values.

Validate and coerce a single parameter value according to schema.

Validate and coerce tool call arguments against a tool spec.

Validate a map of prefilled args against a spec. Rejects unknown keys and coerces known keys. Returns {:ok, coerced_map} or {:error, reason, message}.

Functions

all_simple_types?(sub_schemas)

@spec all_simple_types?([map()]) :: boolean()

Check whether all sub-schemas in a composition have simple, promptable types (string, integer, number, boolean).

merge_schemas(schemas)

@spec merge_schemas([map()]) :: map()

Merge a list of schemas into a single schema. Used for allOf resolution.

Combines type (last wins), properties (deep merge), required (union), and enum (intersection). Other keys are merged with last-wins semantics.

normalize_schema(schema)

@spec normalize_schema(map()) :: map()

Recursively normalize a schema map to string keys, including any composition keyword sub-schemas.

normalize_spec(spec)

@spec normalize_spec(map()) :: {:ok, map()} | {:error, atom(), String.t()}

Normalize a parsed JSON spec into a canonical map with string keys.

Returns {:ok, %{properties: map, required: list}} or {:error, reason, msg}.

nullable_schema?(keyword, sub_schemas)

@spec nullable_schema?(String.t(), [map()]) :: {:nullable, map()} | :not_nullable

Check whether a composition schema represents a nullable type -- i.e., anyOf/oneOf with exactly two sub-schemas where one is {type: "null"}.

Returns {:nullable, non_null_schema} or :not_nullable.

param_list(normalized)

@spec param_list(map() | %{properties: map(), required: [binary()]}) ::
  {:ok, list()} | {:error, atom(), String.t()}

Return a deterministic parameter list: [{name, schema, required?}].

resolve_schema_type(schema)

@spec resolve_schema_type(map()) ::
  {:ok, String.t()}
  | {:composition, String.t(), [map()]}
  | {:error, :unresolvable}

Resolve a schema to its effective type. Returns the type string for flat schemas, or {:composition, keyword, sub_schemas} for composition schemas.

validate_all_args(spec_or_normalized, args_map)

@spec validate_all_args(map() | %{properties: map(), required: [binary()]}, map()) ::
  {:ok, map()}
  | {:error, {:missing_required, [binary()]}}
  | {:error, atom(), any()}

Validate that required keys are present and coerce all provided values.

Returns {:ok, coerced_map} or {:error, {:missing_required, keys}} or {:error, {:invalid, reason}}.

validate_and_coerce_param(schema, value)

@spec validate_and_coerce_param(map(), any()) ::
  {:ok, any()} | {:error, atom(), String.t()}

Validate and coerce a single parameter value according to schema.

Supports flat type-based schemas and composition keywords (anyOf, oneOf, allOf). Resolution order: type > anyOf > oneOf > allOf.

Returns {:ok, coerced} or {:error, reason, message}.

validate_json_args(spec, args)

@spec validate_json_args(map(), map()) ::
  {:ok, map()}
  | {:error, :missing_argument, binary()}
  | {:error, :invalid_argument, binary()}

Validate and coerce tool call arguments against a tool spec.

Accepts the full tool spec (as returned by module.spec()), a raw spec with a parameters key, or a pre-normalized %{properties: ..., required: ...}.

Returns {:ok, coerced_args} or an AI.Tools.args_error().

validate_prefilled_args(spec_or_normalized, args_map)

@spec validate_prefilled_args(
  map() | %{properties: map(), required: [binary()]},
  map()
) ::
  {:ok, map()} | {:error, atom(), any()}

Validate a map of prefilled args against a spec. Rejects unknown keys and coerces known keys. Returns {:ok, coerced_map} or {:error, reason, message}.