@@ -3047,46 +3047,71 @@ export function getProviderModels(providerId: string): string[] {
30473047 return PROVIDER_DEFINITIONS [ providerId ] ?. models . map ( ( m ) => m . id ) || [ ]
30483048}
30493049
3050+ interface ModelCatalogEntry {
3051+ providerId : string
3052+ declIndex : number
3053+ releaseTime : number
3054+ }
3055+
3056+ /**
3057+ * Lowercased model ID → catalog position metadata, built once from the static
3058+ * provider catalog. Dynamic providers contribute nothing here because their model
3059+ * lists are populated at runtime (not at module load), and only catalog models are
3060+ * ever reordered by release date.
3061+ */
3062+ const MODEL_CATALOG_INDEX : Map < string , ModelCatalogEntry > = new Map (
3063+ Object . entries ( PROVIDER_DEFINITIONS ) . flatMap ( ( [ providerId , provider ] ) =>
3064+ provider . models . map ( ( model , declIndex ) : [ string , ModelCatalogEntry ] => {
3065+ const parsed = model . releaseDate ? Date . parse ( model . releaseDate ) : Number . NaN
3066+ return [
3067+ model . id . toLowerCase ( ) ,
3068+ {
3069+ providerId,
3070+ declIndex,
3071+ releaseTime : Number . isNaN ( parsed ) ? Number . NEGATIVE_INFINITY : parsed ,
3072+ } ,
3073+ ]
3074+ } )
3075+ )
3076+ )
3077+
30503078/**
3051- * Reorders catalog model IDs so that, within each provider, newer models (by
3052- * release date) come first, while preserving the existing provider grouping order.
3079+ * Reorders model IDs so that, within each provider, newer models (by release date)
3080+ * come first — while preserving the caller's existing provider grouping order. The
3081+ * relative order of providers is taken from the order they first appear in `modelIds`,
3082+ * so the cross-provider layout the user already sees is never reshuffled.
30533083 *
30543084 * Models without a known release date keep their declaration order and sort after
30553085 * dated models within the same provider. IDs not found in the catalog (e.g.
30563086 * dynamically-discovered provider models) are left in their original order at the end.
30573087 */
30583088export function orderModelIdsByReleaseDate ( modelIds : string [ ] ) : string [ ] {
3059- const catalogIndex = new Map <
3060- string ,
3061- { providerIndex : number ; declIndex : number ; releaseTime : number }
3062- > ( )
3063- Object . values ( PROVIDER_DEFINITIONS ) . forEach ( ( provider , providerIndex ) => {
3064- provider . models . forEach ( ( model , declIndex ) => {
3065- const parsed = model . releaseDate ? Date . parse ( model . releaseDate ) : Number . NaN
3066- catalogIndex . set ( model . id . toLowerCase ( ) , {
3067- providerIndex,
3068- declIndex,
3069- releaseTime : Number . isNaN ( parsed ) ? Number . NEGATIVE_INFINITY : parsed ,
3070- } )
3071- } )
3072- } )
3073-
3074- return modelIds
3075- . map ( ( id , inputIndex ) => ( { id, inputIndex, meta : catalogIndex . get ( id . toLowerCase ( ) ) } ) )
3076- . sort ( ( a , b ) => {
3077- if ( ! a . meta || ! b . meta ) {
3078- if ( ! a . meta && ! b . meta ) return a . inputIndex - b . inputIndex
3079- return a . meta ? - 1 : 1
3080- }
3081- if ( a . meta . providerIndex !== b . meta . providerIndex ) {
3082- return a . meta . providerIndex - b . meta . providerIndex
3083- }
3084- if ( a . meta . releaseTime !== b . meta . releaseTime ) {
3085- return b . meta . releaseTime - a . meta . releaseTime
3086- }
3087- return a . meta . declIndex - b . meta . declIndex
3089+ const groups = new Map < string , string [ ] > ( )
3090+ const unknown : string [ ] = [ ]
3091+
3092+ for ( const id of modelIds ) {
3093+ const meta = MODEL_CATALOG_INDEX . get ( id . toLowerCase ( ) )
3094+ if ( ! meta ) {
3095+ unknown . push ( id )
3096+ continue
3097+ }
3098+ const bucket = groups . get ( meta . providerId )
3099+ if ( bucket ) bucket . push ( id )
3100+ else groups . set ( meta . providerId , [ id ] )
3101+ }
3102+
3103+ const ordered : string [ ] = [ ]
3104+ for ( const bucket of groups . values ( ) ) {
3105+ bucket . sort ( ( a , b ) => {
3106+ const ma = MODEL_CATALOG_INDEX . get ( a . toLowerCase ( ) ) !
3107+ const mb = MODEL_CATALOG_INDEX . get ( b . toLowerCase ( ) ) !
3108+ if ( ma . releaseTime !== mb . releaseTime ) return mb . releaseTime - ma . releaseTime
3109+ return ma . declIndex - mb . declIndex
30883110 } )
3089- . map ( ( entry ) => entry . id )
3111+ ordered . push ( ...bucket )
3112+ }
3113+ ordered . push ( ...unknown )
3114+ return ordered
30903115}
30913116
30923117export const DYNAMIC_MODEL_PROVIDERS = [
0 commit comments