After the send path emits the bare model id (e.g. "model-a:free"), the
restore/refresh path compared the qualified catalog row value
(@custom:hetmer.net:model-a:free) against the bare state model, so no
row rendered as active/"Selected". Normalize both sides through
_modelPickerOptionIdentity (the same identity used for picker dedup)
and keep the provider equality gate, so exactly one row is restored.
Adds a round-trip regression test (send -> persist -> restore) with a
colon-bearing custom model id asserting exactly one "Selected" row with
the model intact, and updates the #5748 source-assertions to the
normalized comparison.
The #6884 prefix strip built its prefix from explicitProvider, which
re-parses the value at its LAST colon. For a colon-bearing model id
rendered by the normal catalog path (e.g. @custom:backup:model-a:free,
no data-model), the strip truncated the model to just "free". Build the
strip prefix from the option metadata's authoritative provider
(routedProvider, e.g. custom:backup), falling back to the parsed
provider only when no option metadata exists. The #1771 gate is kept:
non-custom namespaces like @safe:gpt-4o-mini are still preserved.
Adds regression coverage for the colon-bearing model case beside the
existing #6884 normal-catalog test.
Deduplicate configured model badges so one configured model shows a single picker entry, with provider-collision + colon-bearing-id routing correctness. Thanks @happy5318.
Co-authored-by: happy5318 <happy5318@users.noreply.github.com>