What happens
Open Settings → a provider connection whose provider serves a model that models.dev has started listing since this Maka build was cut. The connection detail shows that model a row asking the user to declare its capabilities by hand — reasoning, vision, thinking levels — even though the Runtime Host already knows all of them and is describing the model correctly everywhere else in the app.
Why
installRefreshedModelMetadata() swaps a module-level variable in the process that calls it (packages/core/src/model-metadata.ts:71). The Runtime Host calls it at startup, so the Host's activeMetadata() is the refreshed catalog. The Desktop renderer is a different process — often on a different machine — and its own activeMetadata() is, and always will be, the snapshot compiled into that build.
That is by design: since #4411 clients are supposed to read Host-resolved catalogEntries rather than resolve a catalog themselves. apps/desktop/src/renderer/settings/provider-connection-detail.tsx:222 is one of the last places that did not get converted. It asks hasModelMetadata(connection.providerType, modelId) — a question about the renderer's own bundled table — to decide whether a model needs a hand-written capability declaration:
const capabilityModelIds = enabledModelIds.filter(
(modelId) =>
isRelay ||
relayProfileDraft[modelId] !== undefined ||
!hasModelMetadata(connection.providerType, modelId),
);
The intent of that third condition is "the app cannot describe this model, so ask the user". After #4467 the app can describe it; only this renderer cannot.
What the fix needs to decide
The data is already at hand: useConnectionDetail computes modelChoices from connection.catalogEntries (apps/desktop/src/renderer/settings/use-connection-detail.ts:314), and the component already receives it. What is missing is a way to ask a ModelCatalogEntry the actual question.
ModelCatalogEntry (packages/core/src/model-catalog.ts:64) carries displayName?, description?, contextWindow?, supportsVision, thinkingLevels — but no field that states "metadata describes this model". Inferring it from whether some optional field happens to be present would put a second, weaker copy of the rule in the renderer, which is the split this whole line of work exists to close. The Host knows the answer directly; the entry should say so.
That makes it a wire change, and therefore an epoch bump — worth knowing before starting. The renderer edit itself is a few lines.
Not in scope
apps/desktop/src/renderer/settings/provider-endpoint-presentation.ts:98 also calls into the bundled table, via modelMetadataIdsForProvider(). That one is correct as written: it uses those ids only to look up lookupModelProviderOverride, which reads generatedModelProviderOverrides — build-time generated data that a Host refresh deliberately does not install. Both sides come from the same generation, so they stay consistent. Please leave it alone.
Impact
Cosmetic and recoverable: one extra form row on a normal user path. No persisted state is wrong, and nothing else reads the affected condition.
Refs #4398, follows #4411 and #4467.
What happens
Open Settings → a provider connection whose provider serves a model that models.dev has started listing since this Maka build was cut. The connection detail shows that model a row asking the user to declare its capabilities by hand — reasoning, vision, thinking levels — even though the Runtime Host already knows all of them and is describing the model correctly everywhere else in the app.
Why
installRefreshedModelMetadata()swaps a module-level variable in the process that calls it (packages/core/src/model-metadata.ts:71). The Runtime Host calls it at startup, so the Host'sactiveMetadata()is the refreshed catalog. The Desktop renderer is a different process — often on a different machine — and its ownactiveMetadata()is, and always will be, the snapshot compiled into that build.That is by design: since #4411 clients are supposed to read Host-resolved
catalogEntriesrather than resolve a catalog themselves.apps/desktop/src/renderer/settings/provider-connection-detail.tsx:222is one of the last places that did not get converted. It askshasModelMetadata(connection.providerType, modelId)— a question about the renderer's own bundled table — to decide whether a model needs a hand-written capability declaration:The intent of that third condition is "the app cannot describe this model, so ask the user". After #4467 the app can describe it; only this renderer cannot.
What the fix needs to decide
The data is already at hand:
useConnectionDetailcomputesmodelChoicesfromconnection.catalogEntries(apps/desktop/src/renderer/settings/use-connection-detail.ts:314), and the component already receives it. What is missing is a way to ask aModelCatalogEntrythe actual question.ModelCatalogEntry(packages/core/src/model-catalog.ts:64) carriesdisplayName?,description?,contextWindow?,supportsVision,thinkingLevels— but no field that states "metadata describes this model". Inferring it from whether some optional field happens to be present would put a second, weaker copy of the rule in the renderer, which is the split this whole line of work exists to close. The Host knows the answer directly; the entry should say so.That makes it a wire change, and therefore an epoch bump — worth knowing before starting. The renderer edit itself is a few lines.
Not in scope
apps/desktop/src/renderer/settings/provider-endpoint-presentation.ts:98also calls into the bundled table, viamodelMetadataIdsForProvider(). That one is correct as written: it uses those ids only to look uplookupModelProviderOverride, which readsgeneratedModelProviderOverrides— build-time generated data that a Host refresh deliberately does not install. Both sides come from the same generation, so they stay consistent. Please leave it alone.Impact
Cosmetic and recoverable: one extra form row on a normal user path. No persisted state is wrong, and nothing else reads the affected condition.
Refs #4398, follows #4411 and #4467.