The model menu — search, provider grouping, -fast family collapse, keyboard
selection, the per-row thinking/effort submenu — was welded to the chat
composer's session writes, so any other surface wanting a model picker had to
fork it and drift.
Splits rendering from meaning. ModelCatalogMenu owns the catalog and the
navigation; a ModelMenuController decides what a selection DOES. The composer
is now one controller over it, keeping its session scoping, sticky manual
pick, preset restore, MoA presets, and rollback-on-failed-write intact.
ModelEditSubmenu becomes pure: it reports edits instead of performing them.
It previously called setCurrentReasoningEffort and config.set inline, so any
non-composer host would have silently retargeted the user's live chat when
they picked an effort. Its default effort is passed in rather than read from a
store, which is what lets it render outside a session at all.
Exported through the SDK so plugins consume the real component instead of a
copy. The composer's existing behaviour suite passes unchanged against it.