@@ -97,12 +97,17 @@ const manifestNormalizationSnapshot = vi.hoisted(() => ({
9797 ] ,
9898} ) ) ;
9999
100+ const providerModelNormalizationMock = vi . hoisted ( ( ) => ( {
101+ normalizeProviderModelIdWithRuntime : vi . fn ( ( ) => undefined ) ,
102+ } ) ) ;
103+
100104vi . mock ( "../plugins/current-plugin-metadata-snapshot.js" , ( ) => ( {
101105 getCurrentPluginMetadataSnapshot : ( ) => manifestNormalizationSnapshot ,
102106} ) ) ;
103107
104108vi . mock ( "./provider-model-normalization.runtime.js" , ( ) => ( {
105- normalizeProviderModelIdWithRuntime : ( ) => undefined ,
109+ normalizeProviderModelIdWithRuntime :
110+ providerModelNormalizationMock . normalizeProviderModelIdWithRuntime ,
106111} ) ) ;
107112
108113vi . mock ( "./model-selection-cli.js" , ( ) => ( {
@@ -850,6 +855,36 @@ describe("model-selection", () => {
850855 expect ( index . byAlias . get ( "smart" ) ?. ref ) . toEqual ( { provider : "openai" , model : "gpt-4o" } ) ;
851856 expect ( index . byKey . get ( modelKey ( "anthropic" , "claude-3-5-sonnet" ) ) ) . toEqual ( [ "fast" ] ) ;
852857 } ) ;
858+
859+ it ( "does not normalize configured model keys that have no alias" , ( ) => {
860+ providerModelNormalizationMock . normalizeProviderModelIdWithRuntime . mockClear ( ) ;
861+ const models = Object . fromEntries (
862+ Array . from ( { length : 25 } , ( _ , index ) => [ `openai/gpt-5.5-aliasless-${ index } ` , { } ] ) ,
863+ ) ;
864+ const cfg : Partial < OpenClawConfig > = {
865+ agents : {
866+ defaults : {
867+ models : {
868+ ...models ,
869+ "openai/gpt-5.5-mini" : { alias : "mini" } ,
870+ } ,
871+ } ,
872+ } ,
873+ } ;
874+
875+ const index = buildModelAliasIndex ( {
876+ cfg : cfg as OpenClawConfig ,
877+ defaultProvider : "openai" ,
878+ } ) ;
879+
880+ expect ( index . byAlias . get ( "mini" ) ?. ref ) . toEqual ( {
881+ provider : "openai" ,
882+ model : "gpt-5.5-mini" ,
883+ } ) ;
884+ expect (
885+ providerModelNormalizationMock . normalizeProviderModelIdWithRuntime ,
886+ ) . toHaveBeenCalledTimes ( 1 ) ;
887+ } ) ;
853888 } ) ;
854889
855890 describe ( "buildAllowedModelSet" , ( ) => {
@@ -1770,6 +1805,32 @@ describe("model-selection", () => {
17701805 expect ( result ) . toEqual ( { provider : "openai" , model : "gpt-5.5" } ) ;
17711806 } ) ;
17721807
1808+ it ( "resolves provider-qualified defaults without normalizing every aliasless configured model" , ( ) => {
1809+ providerModelNormalizationMock . normalizeProviderModelIdWithRuntime . mockClear ( ) ;
1810+ const models = Object . fromEntries (
1811+ Array . from ( { length : 25 } , ( _ , index ) => [ `anthropic/claude-extra-${ index } ` , { } ] ) ,
1812+ ) ;
1813+ const cfg = {
1814+ agents : {
1815+ defaults : {
1816+ model : { primary : "openai/gpt-5.5" } ,
1817+ models,
1818+ } ,
1819+ } ,
1820+ } as OpenClawConfig ;
1821+
1822+ const result = resolveConfiguredModelRef ( {
1823+ cfg,
1824+ defaultProvider : "anthropic" ,
1825+ defaultModel : "claude-sonnet-4-6" ,
1826+ } ) ;
1827+
1828+ expect ( result ) . toEqual ( { provider : "openai" , model : "gpt-5.5" } ) ;
1829+ expect (
1830+ providerModelNormalizationMock . normalizeProviderModelIdWithRuntime ,
1831+ ) . toHaveBeenCalledTimes ( 1 ) ;
1832+ } ) ;
1833+
17731834 it ( "should use default provider/model if config is empty" , ( ) => {
17741835 const cfg : Partial < OpenClawConfig > = { } ;
17751836 const result = resolveConfiguredModelRef ( {
0 commit comments