Skip to content

fix: preserve capabilities when model/1 receives a populated LLMDB.Model struct#601

Closed
mhsdef wants to merge 1 commit intoagentjido:mainfrom
mhsdef:fix/model-struct-capabilities-preservation
Closed

fix: preserve capabilities when model/1 receives a populated LLMDB.Model struct#601
mhsdef wants to merge 1 commit intoagentjido:mainfrom
mhsdef:fix/model-struct-capabilities-preservation

Conversation

@mhsdef
Copy link
Copy Markdown
Contributor

@mhsdef mhsdef commented Apr 13, 2026

Description

When ReqLLM.model/1 receives a fully-populated %LLMDB.Model{} struct (e.g. constructed via LLMDB.Model.new!/1 with explicit capabilities), it was tearing the struct apart, stripping nil fields, running it through LLMDB.Enrich.enrich_model/1, and rebuilding via LLMDB.Model.new(). This caused caller-provided fields like capabilities to be overwritten by Zoi schema defaults (e.g. json.schema: false, tools.enabled: false).

This matters because the recommended advanced usage path — constructing an explicit LLMDB.Model struct for models not yet in the catalog or with incorrect catalog data — was silently losing the capabilities the caller set. This caused determine_output_mode/2 to fall back to :tool_strict instead of using native :json_schema structured output, even when the caller explicitly declared json: %{schema: true}.

Root cause: LLMDB.Enrich.enrich_model/1 only derives family and provider_model_id — it doesn't do catalog lookups. After enrichment, the original non-nil values were being discarded. The fix merges enriched fields (family, provider_model_id) back under the caller's original values, so explicit capabilities are never overwritten.

Type of Change

  • Bug fix (non-breaking change fixing an issue)
  • New feature (non-breaking change adding functionality)
  • Breaking change (fix or feature causing existing functionality to change)
  • Documentation update

Breaking Changes

None. The existing behavior for bare structs (e.g. LLMDB.Model.new!(%{id: "foo", provider: :openai}) with no capabilities) is unchanged — enrichment still fills in family and provider_model_id.

Testing

  • Tests pass (mix test) — 2814 tests, 0 failures
  • Quality checks pass (mix quality)
  • New test: verifies capabilities survive the model/1 round-trip for a fully-populated struct
  • Existing enrichment test still passes (bare struct gets family/provider_model_id derived)

Checklist

  • My code follows the project's style guidelines
  • I have updated the documentation accordingly
  • I have added tests that prove my fix/feature works
  • All new and existing tests pass
  • My commits follow conventional commit format
  • I have NOT edited CHANGELOG.md (it is auto-generated by git_ops)

Related Issues

Discovered while investigating why determine_output_mode/2 was returning :tool_strict for models with json.schema: true capabilities — the capabilities were being silently dropped during model/1 normalization.

…del struct

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@mhsdef mhsdef force-pushed the fix/model-struct-capabilities-preservation branch from d7ece78 to c14d508 Compare April 13, 2026 05:50
@mhsdef mhsdef closed this Apr 13, 2026
@mhsdef
Copy link
Copy Markdown
Contributor Author

mhsdef commented Apr 13, 2026

Nope.

@mhsdef mhsdef deleted the fix/model-struct-capabilities-preservation branch April 13, 2026 05:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant