Problem
modelPreferences persists favorites as opaque string[]. That leaves each client to choose its own identifier encoding. Gateway options use catalog ids such as anthropic/claude-sonnet-4, while mobile remote catalog options use remote:${providerID}:${modelID} because their displayed ids are unstable. The CLI and VS Code extension already represent a favorite as { providerID, modelID }.
The result is that the same model can have different favorite keys across surfaces. A delimited string is also not safely reversible because a provider-local model id can itself contain delimiters. Favorites cannot therefore synchronize reliably across web, mobile, CLI, and the extension.
Required API Contract
Introduce a versioned structured favorites contract rather than changing the existing string-based procedures in place:
type FavoriteModelRef = {
providerID: string
modelID: string
}
get(): {
favorites: FavoriteModelRef[]
lastSelected: { model: string; variant?: string } | null
}
addFavorite({ favorite: FavoriteModelRef })
removeFavorite({ favorite: FavoriteModelRef })
setFavorites({ favorites: FavoriteModelRef[] })
The structured API must:
- Treat the pair of
providerID and modelID as the unique favorite identity.
- Preserve the current per-user scope, 500-item limit, idempotent add/remove behavior, and atomic concurrent mutations.
- Return and accept structured values without requiring clients to serialize or parse a delimited string.
- Apply organization availability filtering through an explicit mapping from available catalog models to
FavoriteModelRef. Do not split arbitrary model strings to derive a reference.
- Retain unavailable references in storage. Clients can hide models absent from their current catalog, but one device must not delete another device's favorite merely because it cannot resolve it.
Migration And Compatibility
The existing string API is already consumed by released web and mobile clients, so the structured contract must be introduced as a new versioned API or an equivalent backward-compatible transition. Do not generically parse existing strings as provider/model. Existing values include client-specific encodings and provider-local model ids can contain delimiters.
Define an explicit, non-lossy migration path for existing records. Known values may be mapped through an authoritative catalog mapping; values without an unambiguous mapping must not be silently misidentified or discarded. Retire the legacy string contract only after web and mobile have migrated.
App Follow-Up
- Web and mobile must send and consume
FavoriteModelRef values.
- Mobile must remove the
remote:${providerID}:${modelID} favorite-key convention and use the structured remote catalog reference directly.
- The gateway model adapter must provide a canonical
FavoriteModelRef rather than leaking a UI row id.
- All surfaces must use the same structured identity before cloud synchronization is enabled for CLI and VS Code.
Acceptance Criteria
- The API has a documented structured favorite type shared by all clients.
- A favorite written by one surface can be matched by another without client-specific string parsing.
- Existing favorite records have a defined compatibility and migration behavior.
- Organization filtering does not remove stored favorites merely because they are temporarily unavailable.
- Legacy and structured clients can coexist for the migration period.
Client Implementation
CLI and VS Code integration is tracked in Kilo-Org/kilocode#12069. The client work is blocked on the structured API and keeps cloud authentication and synchronization in the CLI service layer.
Problem
modelPreferencespersists favorites as opaquestring[]. That leaves each client to choose its own identifier encoding. Gateway options use catalog ids such asanthropic/claude-sonnet-4, while mobile remote catalog options useremote:${providerID}:${modelID}because their displayed ids are unstable. The CLI and VS Code extension already represent a favorite as{ providerID, modelID }.The result is that the same model can have different favorite keys across surfaces. A delimited string is also not safely reversible because a provider-local model id can itself contain delimiters. Favorites cannot therefore synchronize reliably across web, mobile, CLI, and the extension.
Required API Contract
Introduce a versioned structured favorites contract rather than changing the existing string-based procedures in place:
The structured API must:
providerIDandmodelIDas the unique favorite identity.FavoriteModelRef. Do not split arbitrary model strings to derive a reference.Migration And Compatibility
The existing string API is already consumed by released web and mobile clients, so the structured contract must be introduced as a new versioned API or an equivalent backward-compatible transition. Do not generically parse existing strings as
provider/model. Existing values include client-specific encodings and provider-local model ids can contain delimiters.Define an explicit, non-lossy migration path for existing records. Known values may be mapped through an authoritative catalog mapping; values without an unambiguous mapping must not be silently misidentified or discarded. Retire the legacy string contract only after web and mobile have migrated.
App Follow-Up
FavoriteModelRefvalues.remote:${providerID}:${modelID}favorite-key convention and use the structured remote catalog reference directly.FavoriteModelRefrather than leaking a UI row id.Acceptance Criteria
Client Implementation
CLI and VS Code integration is tracked in Kilo-Org/kilocode#12069. The client work is blocked on the structured API and keeps cloud authentication and synchronization in the CLI service layer.