@@ -255,6 +255,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => {
255255 } ,
256256 ] ) ,
257257 setModeConfig : vi . fn ( ) ,
258+ clearModeConfig : vi . fn ( ) . mockResolvedValue ( undefined ) ,
258259 getModeConfigId : vi . fn ( ) . mockResolvedValue ( undefined ) ,
259260 activateProfile : vi . fn ( ) . mockResolvedValue ( {
260261 name : "test-config" ,
@@ -422,6 +423,69 @@ describe("ClineProvider - API Handler Rebuild Guard", () => {
422423 expect ( vscode . window . showErrorMessage ) . toHaveBeenCalledWith ( "errors.create_api_config" )
423424 } )
424425
426+ test ( "removes a mode binding that did not exist before when activation fails" , async ( ) => {
427+ const manager = provider [ "providerSettingsManager" ]
428+ const { mode } = await provider . getState ( )
429+ vi . mocked ( manager . getModeConfigId ) . mockResolvedValue ( undefined )
430+ vi . spyOn ( provider . contextProxy , "setProviderSettings" ) . mockRejectedValueOnce ( new Error ( "write failed" ) )
431+
432+ await provider . upsertProviderProfile ( "test-config" , {
433+ apiProvider : providerIdentifiers . openrouter ,
434+ openRouterModelId : "anthropic/claude" ,
435+ } )
436+
437+ expect ( manager . clearModeConfig ) . toHaveBeenCalledWith ( mode )
438+ expect ( manager . setModeConfig ) . not . toHaveBeenLastCalledWith ( mode , undefined )
439+ } )
440+
441+ test ( "rebuilds a delegated task from its own configuration, not the global settings, when activation fails" , async ( ) => {
442+ const manager = provider [ "providerSettingsManager" ]
443+ const childConfiguration = {
444+ apiProvider : providerIdentifiers . anthropic ,
445+ apiModelId : "claude-handoff-model" ,
446+ }
447+ expect ( provider . contextProxy . getProviderSettings ( ) ) . not . toMatchObject ( childConfiguration )
448+ const childTask = new Task ( { ...defaultTaskOptions , apiConfiguration : childConfiguration } )
449+ await provider . addClineToStack ( childTask )
450+ vi . mocked ( manager . hasConfig ) . mockResolvedValue ( true )
451+ vi . mocked ( manager . getProfile ) . mockResolvedValue ( { name : "test-config" , id : "test-id" } )
452+ vi . spyOn ( provider . contextProxy , "setProviderSettings" ) . mockRejectedValueOnce ( new Error ( "write failed" ) )
453+
454+ await provider . upsertProviderProfile ( "test-config" , {
455+ apiProvider : providerIdentifiers . openrouter ,
456+ openRouterModelId : "anthropic/claude" ,
457+ } )
458+
459+ expect ( childTask . updateApiConfiguration ) . toHaveBeenLastCalledWith ( childConfiguration )
460+ } )
461+
462+ test ( "reports a partial state, after running every rollback step, when the rollback itself fails" , async ( ) => {
463+ const manager = provider [ "providerSettingsManager" ]
464+ vi . mocked ( manager . hasConfig ) . mockResolvedValue ( true )
465+ vi . mocked ( manager . getProfile ) . mockResolvedValue ( { name : "test-config" , id : "test-id" } )
466+ vi . mocked ( manager . getModeConfigId ) . mockResolvedValue ( "previous-mode-id" )
467+ const previousSettings = provider . contextProxy . getProviderSettings ( )
468+ const setProviderSettings = vi
469+ . spyOn ( provider . contextProxy , "setProviderSettings" )
470+ . mockRejectedValueOnce ( new Error ( "activation write failed" ) )
471+ // Activation writes the mode binding first, then the rollback fails to restore it.
472+ vi . mocked ( manager . setModeConfig )
473+ . mockResolvedValueOnce ( undefined )
474+ . mockRejectedValue ( new Error ( "restore failed" ) )
475+
476+ const result = await provider . upsertProviderProfile ( "test-config" , {
477+ apiProvider : providerIdentifiers . openrouter ,
478+ openRouterModelId : "anthropic/claude" ,
479+ } )
480+
481+ expect ( result ) . toBeUndefined ( )
482+ // The failed mode restore did not stop the other steps.
483+ expect ( manager . saveConfig ) . toHaveBeenLastCalledWith ( "test-config" , { id : "test-id" } )
484+ expect ( setProviderSettings ) . toHaveBeenLastCalledWith ( previousSettings )
485+ expect ( vscode . window . showErrorMessage ) . toHaveBeenCalledWith ( "errors.update_profile_model_partial" )
486+ expect ( vscode . window . showErrorMessage ) . not . toHaveBeenCalledWith ( "errors.create_api_config" )
487+ } )
488+
425489 test ( "deletes a profile that did not exist before when activation fails" , async ( ) => {
426490 const manager = provider [ "providerSettingsManager" ]
427491 vi . mocked ( manager . hasConfig ) . mockResolvedValueOnce ( false ) . mockResolvedValue ( true )
0 commit comments