Expands a struct module into JSON schema object properties, for the
Mod.t() references Claudex.Tool.Schema finds in a @spec that
aren't one of the built-in types.
Two sources of field info, tried in this order:
- an Ecto schema — read via the module's own
__schema__/1reflection. Claudex has no compile-time dependency on Ecto; this only runs when the referenced module itself implements__schema__/1, so it works whether or not your project has Ecto installed at all. Verified against Ecto 3.14 — a field whose type Claudex doesn't recognize (an older Ecto's internal representation for a parameterized type, or a customEcto.Typethat doesn't implementtype/0) raisesClaudex.Tool.SchemaError. Association fields (belongs_to,has_many,has_one,many_to_many) are skipped — Ecto doesn't even include them in__schema__(:fields). Embeds (embeds_one,embeds_many) are genuine data, not a relationship, and are expanded. - a plain struct with
@type t :: %__MODULE__{...}— read from the module's own compiled typespec.
A struct with neither still expands, with every field left unconstrained
(%{}) — the field names alone are more useful to Claude than nothing,
and "no type info at all" isn't the same failure as "a type Claudex
can't map."
Ecto doesn't expose which fields are NOT NULL, so an Ecto-backed
object's required list is always empty. A plain struct's required
list is inferred from its typespec: a field typed t | nil (or bare
nil) is optional, anything else is required.
Every object built here sets additionalProperties: false, since the
field set is known and closed — the same thing Claudex.Tool does for
the top-level input_schema, and what a tool declared strict: true
needs at every level rather than only the outermost one.
Summary
Functions
Expands module into an object schema.
Functions
@spec expand(module(), Claudex.Tool.Schema.context()) :: :cycle | {:ok, map()} | :unsupported
Expands module into an object schema.
Returns :cycle when module was already seen earlier on this
expansion path (ctx.visited) — a self- or mutually-referential
struct, not an error — and :unsupported when module isn't loaded,
or is loaded but is neither a struct nor an Ecto schema. Callers decide
what to do with each: Claudex.Tool.Schema falls back to an
unconstrained schema for :cycle and raises Claudex.Tool.SchemaError
for :unsupported.