Skip to content

Set lifecycle=active on constructed ModelInfo descriptors (issue #13) - #14

Merged
imonlinux merged 1 commit into
mainfrom
fix/modelinfo-lifecycle
Nov 9, 2026
Merged

imonlinux merged 1 commit into
mainfrom
fix/modelinfo-lifecycle

Conversation

@imonlinux

Copy link
Copy Markdown
Owner

Closes #13.

Summary

The anthropic SDK 2.x line (which HA 2026.11 pairs at 2.3.0) made lifecycle a required field on anthropic.types.ModelInfo. Every descriptor the integration constructs without it raises pydantic ValidationError: lifecycle Field required. The reporter (@mkruseonline) hit this on OpenRouter model-list refreshes; this PR sets lifecycle="active" at all five construction sites:

  • openai_chat_provider.normalize_model() (list refresh and retrieve passthrough)
  • openai_chat_provider.fetch_model() retrieve-failure fallback
  • openai_chat_provider.fetch_model() non-Model-body fallback (z.ai empty-200)
  • coordinator.get_model_info() not-found fallback
  • anthropic_provider.fetch_model() empty-response fallback

SDKs elsewhere in the manifest pin range (0.108.0+) declare the field as an allowed extra rather than a schema field, so passing it unconditionally is safe across the entire range; the pinned test tree (anthropic 0.125.0) exercises exactly that path.

Test plan

  • New regression test: models.retrieve failure degrades to a descriptor carrying lifecycle="active"
  • Lifecycle assertions added to normalize-model, both fetch-degrade, and coordinator not-found tests
  • Full suite on the pinned tree: 146 passed, 2 skipped (145/2 baseline + 1)
  • ModelInfo(lifecycle="active") construction verified against anthropic==2.3.0 on Python 3.13: clean

Ships as 1.3.2 (manifest + CHANGELOG included).

The anthropic SDK 2.x line (which HA 2026.11 pairs at 2.3.0) made
`lifecycle` a required field on anthropic.types.ModelInfo. Every model
descriptor this integration constructs without it raises
`pydantic ValidationError: lifecycle Field required`, which broke
OpenRouter model-list refreshes on 2026.11 (reported by mkruseonline)
and, on the same construction shape, four more paths:

- openai_chat_provider.normalize_model() (list refresh + retrieve passthrough)
- openai_chat_provider.fetch_model() retrieve-failure fallback
- openai_chat_provider.fetch_model() non-Model-body fallback (z.ai empty-200)
- coordinator.get_model_info() not-found fallback
- anthropic_provider.fetch_model() empty-response fallback

All five sites now construct with lifecycle="active". SDKs elsewhere in
the manifest pin range (0.108.0+) declare the field as an allowed extra
rather than a schema field, so passing it unconditionally is safe across
the entire range; the pinned test tree (anthropic 0.125.0) exercises
exactly that path. Construction verified clean against anthropic==2.3.0
on Python 3.13.

Tests: new retrieve-failure regression test; lifecycle assertions added
to normalize-model, both fetch-degrade, and coordinator not-found tests.
Suite: 146 passed, 2 skipped (145/2 baseline + 1).
@imonlinux
imonlinux merged commit 1a98cd6 into main Nov 9, 2026
3 checks passed
@imonlinux
imonlinux deleted the fix/modelinfo-lifecycle branch November 9, 2026 21:26
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.

ModelInfo validation error: missing lifecycle field when fetching OpenRouter models

1 participant