@@ -290,6 +290,10 @@ vi.mock("../../config/ContextProxy", () => {
290290 )
291291 } )
292292 setProviderSettings = vi . fn ( ) . mockImplementation ( ( settings : Record < string , any > ) => this . setValues ( settings ) )
293+ resetAllState = vi . fn ( ) . mockImplementation ( ( ) => {
294+ const keys = this . context ?. globalState ?. keys ?.( ) ?? [ ]
295+ return Promise . all ( keys . map ( ( key : string ) => this . setValue ( key , undefined ) ) ) . then ( ( ) => undefined )
296+ } )
293297 }
294298 return { ContextProxy : MockContextProxy }
295299} )
@@ -482,6 +486,7 @@ vi.mock("../../config/ProviderSettingsManager", () => ({
482486 } ) ) ,
483487 setModeConfig : vi . fn ( ) . mockResolvedValue ( undefined ) ,
484488 getModeConfigId : vi . fn ( ) . mockResolvedValue ( undefined ) ,
489+ resetAllConfigs : vi . fn ( ) . mockResolvedValue ( undefined ) ,
485490 }
486491 } ) ,
487492} ) )
@@ -492,6 +497,7 @@ vi.mock("../../config/CustomModesManager", () => ({
492497 return {
493498 updateCustomMode : vi . fn ( ) . mockResolvedValue ( undefined ) ,
494499 getCustomModes : vi . fn ( ) . mockResolvedValue ( [ ] ) ,
500+ resetCustomModes : vi . fn ( ) . mockResolvedValue ( undefined ) ,
495501 dispose : vi . fn ( ) ,
496502 }
497503 } ) ,
@@ -1038,6 +1044,106 @@ describe("ClineProvider - Parallel Mode Support", () => {
10381044 } )
10391045 } )
10401046
1047+ describe ( "profile mutations" , ( ) => {
1048+ it ( "should synchronize viewLocalState when activateProviderProfile mutates ContextProxy" , async ( ) => {
1049+ const provider = new ClineProvider ( mockContext , mockOutputChannel , "sidebar" , new ContextProxy ( mockContext ) )
1050+ vi . spyOn ( provider . providerSettingsManager , "activateProfile" ) . mockResolvedValueOnce ( {
1051+ name : "new-profile" ,
1052+ id : "new-profile-id" ,
1053+ apiProvider : "openrouter" ,
1054+ openRouterModelId : "openrouter/new-model" ,
1055+ } as any )
1056+ vi . spyOn ( provider . providerSettingsManager , "listConfig" ) . mockResolvedValueOnce ( [
1057+ { id : "new-profile-id" , name : "new-profile" , apiProvider : "openrouter" } ,
1058+ ] as any )
1059+ ; ( provider as any ) . viewLocalState = {
1060+ currentApiConfigName : "stale-profile" ,
1061+ apiConfiguration : { apiProvider : "anthropic" } ,
1062+ }
1063+
1064+ await provider . activateProviderProfile ( { name : "new-profile" } )
1065+ const state = await provider . getState ( )
1066+
1067+ expect ( state . currentApiConfigName ) . toBe ( "new-profile" )
1068+ expect ( state . apiConfiguration ) . toMatchObject ( {
1069+ apiProvider : "openrouter" ,
1070+ openRouterModelId : "openrouter/new-model" ,
1071+ } )
1072+
1073+ await provider . dispose ( )
1074+ } )
1075+
1076+ it ( "should synchronize viewLocalState when upsertProviderProfile activates a saved profile" , async ( ) => {
1077+ const provider = new ClineProvider ( mockContext , mockOutputChannel , "sidebar" , new ContextProxy ( mockContext ) )
1078+ vi . spyOn ( provider . providerSettingsManager , "listConfig" ) . mockResolvedValue ( [
1079+ { id : "test-id" , name : "saved-profile" , apiProvider : "bedrock" } ,
1080+ ] as any )
1081+ ; ( provider as any ) . viewLocalState = {
1082+ currentApiConfigName : "stale-profile" ,
1083+ apiConfiguration : { apiProvider : "anthropic" } ,
1084+ }
1085+
1086+ await provider . upsertProviderProfile ( "saved-profile" , {
1087+ apiProvider : "bedrock" ,
1088+ awsRegion : "us-east-1" ,
1089+ } as any )
1090+ const state = await provider . getState ( )
1091+
1092+ expect ( state . currentApiConfigName ) . toBe ( "saved-profile" )
1093+ expect ( state . apiConfiguration ) . toMatchObject ( {
1094+ apiProvider : "bedrock" ,
1095+ awsRegion : "us-east-1" ,
1096+ } )
1097+
1098+ await provider . dispose ( )
1099+ } )
1100+
1101+ it ( "should synchronize viewLocalState when deleteProviderProfile selects a replacement profile" , async ( ) => {
1102+ const provider = new ClineProvider ( mockContext , mockOutputChannel , "sidebar" , new ContextProxy ( mockContext ) )
1103+ await provider . contextProxy . setValue ( "currentApiConfigName" as any , "deleted-profile" )
1104+ await provider . contextProxy . setValue ( "listApiConfigMeta" as any , [
1105+ { id : "deleted-id" , name : "deleted-profile" , apiProvider : "anthropic" } ,
1106+ { id : "replacement-id" , name : "replacement-profile" , apiProvider : "openrouter" } ,
1107+ ] )
1108+ ; ( provider as any ) . viewLocalState = {
1109+ currentApiConfigName : "deleted-profile" ,
1110+ apiConfiguration : { apiProvider : "anthropic" } ,
1111+ }
1112+
1113+ await provider . deleteProviderProfile ( {
1114+ id : "deleted-id" ,
1115+ name : "deleted-profile" ,
1116+ apiProvider : "anthropic" ,
1117+ } as any )
1118+ const state = await provider . getState ( )
1119+
1120+ expect ( state . currentApiConfigName ) . toBe ( "replacement-profile" )
1121+ expect ( state . listApiConfigMeta ) . toEqual ( [
1122+ { id : "replacement-id" , name : "replacement-profile" , apiProvider : "openrouter" } ,
1123+ ] )
1124+
1125+ await provider . dispose ( )
1126+ } )
1127+
1128+ it ( "should clear viewLocalState when resetState resets ContextProxy" , async ( ) => {
1129+ vi . mocked ( vscode . window . showInformationMessage ) . mockImplementationOnce (
1130+ async ( _message : string , _options : unknown , confirm : unknown ) => confirm as any ,
1131+ )
1132+ const provider = new ClineProvider ( mockContext , mockOutputChannel , "sidebar" , new ContextProxy ( mockContext ) )
1133+ ; ( provider as any ) . viewLocalState = {
1134+ mode : "architect" ,
1135+ currentApiConfigName : "stale-profile" ,
1136+ apiConfiguration : { apiProvider : "openrouter" } ,
1137+ }
1138+
1139+ await provider . resetState ( )
1140+
1141+ expect ( ( provider as any ) . viewLocalState ) . toEqual ( { } )
1142+
1143+ await provider . dispose ( )
1144+ } )
1145+ } )
1146+
10411147 describe ( "handleModeSwitch integration" , ( ) => {
10421148 it ( "should update viewLocalState.mode when handleModeSwitch is called" , async ( ) => {
10431149 const postMessage = vi . fn ( )
0 commit comments