@@ -250,7 +250,7 @@ describe("ClineProvider - API Handler Rebuild Guard", () => {
250250 } )
251251
252252 describe ( "upsertProviderProfile" , ( ) => {
253- test ( "does NOT rebuild API handler when provider and model unchanged" , async ( ) => {
253+ test ( "does NOT rebuild API handler when provider and model unchanged, but task.apiConfiguration is synced " , async ( ) => {
254254 // Create a task with the current config
255255 const mockTask = new Task ( {
256256 ...defaultTaskOptions ,
@@ -289,6 +289,10 @@ describe("ClineProvider - API Handler Rebuild Guard", () => {
289289 expect ( buildApiHandlerMock ) . not . toHaveBeenCalled ( )
290290 // Verify the task's api property was NOT reassigned (still same reference)
291291 expect ( mockTask . api ) . toBe ( originalApi )
292+ // Verify task.apiConfiguration was synchronized with non-model fields
293+ expect ( ( mockTask as any ) . apiConfiguration . openRouterModelId ) . toBe ( "openai/gpt-4" )
294+ expect ( ( mockTask as any ) . apiConfiguration . rateLimitSeconds ) . toBe ( 5 )
295+ expect ( ( mockTask as any ) . apiConfiguration . modelTemperature ) . toBe ( 0.7 )
292296 } )
293297
294298 test ( "rebuilds API handler when provider changes" , async ( ) => {
@@ -386,12 +390,13 @@ describe("ClineProvider - API Handler Rebuild Guard", () => {
386390 } )
387391
388392 describe ( "activateProviderProfile" , ( ) => {
389- test ( "does NOT rebuild API handler when provider and model unchanged" , async ( ) => {
393+ test ( "does NOT rebuild API handler when provider and model unchanged, but task.apiConfiguration is synced " , async ( ) => {
390394 const mockTask = new Task ( {
391395 ...defaultTaskOptions ,
392396 apiConfiguration : {
393397 apiProvider : "openrouter" ,
394398 openRouterModelId : "openai/gpt-4" ,
399+ modelTemperature : 0.3 ,
395400 } ,
396401 } )
397402 const originalApi = {
@@ -406,12 +411,14 @@ describe("ClineProvider - API Handler Rebuild Guard", () => {
406411
407412 buildApiHandlerMock . mockClear ( )
408413
409- // Mock activateProfile to return same provider/model
414+ // Mock activateProfile to return same provider/model but different non-model setting
410415 ; ( provider as any ) . providerSettingsManager . activateProfile = vi . fn ( ) . mockResolvedValue ( {
411416 name : "test-config" ,
412417 id : "test-id" ,
413418 apiProvider : "openrouter" ,
414419 openRouterModelId : "openai/gpt-4" ,
420+ modelTemperature : 0.9 ,
421+ rateLimitSeconds : 7 ,
415422 } )
416423
417424 await provider . activateProviderProfile ( { name : "test-config" } )
@@ -420,9 +427,13 @@ describe("ClineProvider - API Handler Rebuild Guard", () => {
420427 expect ( buildApiHandlerMock ) . not . toHaveBeenCalled ( )
421428 // Verify the API reference wasn't changed
422429 expect ( mockTask . api ) . toBe ( originalApi )
430+ // Verify task.apiConfiguration was synchronized
431+ expect ( ( mockTask as any ) . apiConfiguration . openRouterModelId ) . toBe ( "openai/gpt-4" )
432+ expect ( ( mockTask as any ) . apiConfiguration . modelTemperature ) . toBe ( 0.9 )
433+ expect ( ( mockTask as any ) . apiConfiguration . rateLimitSeconds ) . toBe ( 7 )
423434 } )
424435
425- test ( "rebuilds API handler when provider changes" , async ( ) => {
436+ test ( "rebuilds API handler when provider changes and syncs task.apiConfiguration " , async ( ) => {
426437 const mockTask = new Task ( {
427438 ...defaultTaskOptions ,
428439 apiConfiguration : {
@@ -458,9 +469,12 @@ describe("ClineProvider - API Handler Rebuild Guard", () => {
458469 apiModelId : "claude-3-5-sonnet-20241022" ,
459470 } ) ,
460471 )
472+ // And task.apiConfiguration synced
473+ expect ( ( mockTask as any ) . apiConfiguration . apiProvider ) . toBe ( "anthropic" )
474+ expect ( ( mockTask as any ) . apiConfiguration . apiModelId ) . toBe ( "claude-3-5-sonnet-20241022" )
461475 } )
462476
463- test ( "rebuilds API handler when model changes" , async ( ) => {
477+ test ( "rebuilds API handler when model changes and syncs task.apiConfiguration " , async ( ) => {
464478 const mockTask = new Task ( {
465479 ...defaultTaskOptions ,
466480 apiConfiguration : {
@@ -496,6 +510,57 @@ describe("ClineProvider - API Handler Rebuild Guard", () => {
496510 openRouterModelId : "anthropic/claude-3-5-sonnet-20241022" ,
497511 } ) ,
498512 )
513+ // And task.apiConfiguration synced
514+ expect ( ( mockTask as any ) . apiConfiguration . apiProvider ) . toBe ( "openrouter" )
515+ expect ( ( mockTask as any ) . apiConfiguration . openRouterModelId ) . toBe ( "anthropic/claude-3-5-sonnet-20241022" )
516+ } )
517+ } )
518+
519+ describe ( "profile switching sequence" , ( ) => {
520+ test ( "A -> B -> A updates task.apiConfiguration each time" , async ( ) => {
521+ const mockTask = new Task ( {
522+ ...defaultTaskOptions ,
523+ apiConfiguration : {
524+ apiProvider : "openrouter" ,
525+ openRouterModelId : "openai/gpt-4" ,
526+ } ,
527+ } )
528+ mockTask . api = {
529+ getModel : vi . fn ( ) . mockReturnValue ( {
530+ id : "openai/gpt-4" ,
531+ info : { contextWindow : 128000 } ,
532+ } ) ,
533+ } as any
534+
535+ await provider . addClineToStack ( mockTask )
536+
537+ // First switch: A -> B (openrouter -> anthropic)
538+ buildApiHandlerMock . mockClear ( )
539+ ; ( provider as any ) . providerSettingsManager . activateProfile = vi . fn ( ) . mockResolvedValue ( {
540+ name : "anthropic-config" ,
541+ id : "anthropic-id" ,
542+ apiProvider : "anthropic" ,
543+ apiModelId : "claude-3-5-sonnet-20241022" ,
544+ } )
545+ await provider . activateProviderProfile ( { name : "anthropic-config" } )
546+
547+ expect ( buildApiHandlerMock ) . toHaveBeenCalled ( )
548+ expect ( ( mockTask as any ) . apiConfiguration . apiProvider ) . toBe ( "anthropic" )
549+ expect ( ( mockTask as any ) . apiConfiguration . apiModelId ) . toBe ( "claude-3-5-sonnet-20241022" )
550+
551+ // Second switch: B -> A (anthropic -> openrouter gpt-4)
552+ buildApiHandlerMock . mockClear ( )
553+ ; ( provider as any ) . providerSettingsManager . activateProfile = vi . fn ( ) . mockResolvedValue ( {
554+ name : "test-config" ,
555+ id : "test-id" ,
556+ apiProvider : "openrouter" ,
557+ openRouterModelId : "openai/gpt-4" ,
558+ } )
559+ await provider . activateProviderProfile ( { name : "test-config" } )
560+
561+ // API handler may or may not rebuild depending on mock model id, but apiConfiguration must be updated
562+ expect ( ( mockTask as any ) . apiConfiguration . apiProvider ) . toBe ( "openrouter" )
563+ expect ( ( mockTask as any ) . apiConfiguration . openRouterModelId ) . toBe ( "openai/gpt-4" )
499564 } )
500565 } )
501566
0 commit comments