@@ -377,6 +377,99 @@ void testGetOrder() {
377377 assertThat (advisor .getOrder ()).isEqualTo (customOrder );
378378 }
379379
380+ @ Test
381+ void testBuilderGetters () {
382+ ToolCallingManager customManager = mock (ToolCallingManager .class );
383+ int customOrder = BaseAdvisor .HIGHEST_PRECEDENCE + 500 ;
384+
385+ ToolCallAdvisor .Builder <?> builder = ToolCallAdvisor .builder ()
386+ .toolCallingManager (customManager )
387+ .advisorOrder (customOrder );
388+
389+ assertThat (builder .getToolCallingManager ()).isEqualTo (customManager );
390+ assertThat (builder .getAdvisorOrder ()).isEqualTo (customOrder );
391+ }
392+
393+ @ Test
394+ void testExtendedAdvisorWithCustomHooks () {
395+ int [] hookCallCounts = { 0 , 0 , 0 }; // initializeLoop, beforeCall, afterCall
396+
397+ // Create extended advisor to verify hooks are called
398+ TestableToolCallAdvisor advisor = new TestableToolCallAdvisor (this .toolCallingManager ,
399+ BaseAdvisor .HIGHEST_PRECEDENCE + 300 , hookCallCounts );
400+
401+ ChatClientRequest request = createMockRequest (true );
402+ ChatClientResponse response = createMockResponse (false );
403+
404+ CallAdvisor terminalAdvisor = new TerminalCallAdvisor ((req , chain ) -> response );
405+
406+ CallAdvisorChain realChain = DefaultAroundAdvisorChain .builder (ObservationRegistry .NOOP )
407+ .pushAll (List .of (advisor , terminalAdvisor ))
408+ .build ();
409+
410+ advisor .adviseCall (request , realChain );
411+
412+ // Verify hooks were called
413+ assertThat (hookCallCounts [0 ]).isEqualTo (1 ); // doInitializeLoop called once
414+ assertThat (hookCallCounts [1 ]).isEqualTo (1 ); // doBeforeCall called once
415+ assertThat (hookCallCounts [2 ]).isEqualTo (1 ); // doAfterCall called once
416+ }
417+
418+ @ Test
419+ void testExtendedAdvisorHooksCalledMultipleTimesWithToolCalls () {
420+ int [] hookCallCounts = { 0 , 0 , 0 }; // initializeLoop, beforeCall, afterCall
421+
422+ TestableToolCallAdvisor advisor = new TestableToolCallAdvisor (this .toolCallingManager ,
423+ BaseAdvisor .HIGHEST_PRECEDENCE + 300 , hookCallCounts );
424+
425+ ChatClientRequest request = createMockRequest (true );
426+ ChatClientResponse responseWithToolCall = createMockResponse (true );
427+ ChatClientResponse finalResponse = createMockResponse (false );
428+
429+ int [] callCount = { 0 };
430+ CallAdvisor terminalAdvisor = new TerminalCallAdvisor ((req , chain ) -> {
431+ callCount [0 ]++;
432+ return callCount [0 ] == 1 ? responseWithToolCall : finalResponse ;
433+ });
434+
435+ CallAdvisorChain realChain = DefaultAroundAdvisorChain .builder (ObservationRegistry .NOOP )
436+ .pushAll (List .of (advisor , terminalAdvisor ))
437+ .build ();
438+
439+ // Mock tool execution result
440+ List <Message > conversationHistory = List .of (new UserMessage ("test" ),
441+ AssistantMessage .builder ().content ("" ).build (), ToolResponseMessage .builder ().build ());
442+ ToolExecutionResult toolExecutionResult = ToolExecutionResult .builder ()
443+ .conversationHistory (conversationHistory )
444+ .build ();
445+ when (this .toolCallingManager .executeToolCalls (any (Prompt .class ), any (ChatResponse .class )))
446+ .thenReturn (toolExecutionResult );
447+
448+ advisor .adviseCall (request , realChain );
449+
450+ // Verify hooks were called correct number of times
451+ assertThat (hookCallCounts [0 ]).isEqualTo (1 ); // doInitializeLoop called once
452+ // (before loop)
453+ assertThat (hookCallCounts [1 ]).isEqualTo (2 ); // doBeforeCall called twice (each
454+ // iteration)
455+ assertThat (hookCallCounts [2 ]).isEqualTo (2 ); // doAfterCall called twice (each
456+ // iteration)
457+ }
458+
459+ @ Test
460+ void testExtendedBuilderWithCustomBuilder () {
461+ ToolCallingManager customManager = mock (ToolCallingManager .class );
462+ int customOrder = BaseAdvisor .HIGHEST_PRECEDENCE + 450 ;
463+
464+ TestableToolCallAdvisor advisor = TestableToolCallAdvisor .testBuilder ()
465+ .toolCallingManager (customManager )
466+ .advisorOrder (customOrder )
467+ .build ();
468+
469+ assertThat (advisor ).isNotNull ();
470+ assertThat (advisor .getOrder ()).isEqualTo (customOrder );
471+ }
472+
380473 // Helper methods
381474
382475 private ChatClientRequest createMockRequest (boolean withToolCallingOptions ) {
@@ -472,6 +565,65 @@ public ChatClientResponse adviseCall(ChatClientRequest req, CallAdvisorChain cha
472565 return this .responseFunction .apply (req , chain );
473566 }
474567
475- };
568+ }
569+
570+ /**
571+ * Test subclass of ToolCallAdvisor to verify extensibility and hook methods.
572+ */
573+ private static class TestableToolCallAdvisor extends ToolCallAdvisor {
574+
575+ private final int [] hookCallCounts ;
576+
577+ TestableToolCallAdvisor (ToolCallingManager toolCallingManager , int advisorOrder , int [] hookCallCounts ) {
578+ super (toolCallingManager , advisorOrder );
579+ this .hookCallCounts = hookCallCounts ;
580+ }
581+
582+ @ Override
583+ protected ChatClientRequest doInitializeLoop (ChatClientRequest chatClientRequest ,
584+ CallAdvisorChain callAdvisorChain ) {
585+ if (this .hookCallCounts != null ) {
586+ this .hookCallCounts [0 ]++;
587+ }
588+ return super .doInitializeLoop (chatClientRequest , callAdvisorChain );
589+ }
590+
591+ @ Override
592+ protected ChatClientRequest doBeforeCall (ChatClientRequest chatClientRequest ,
593+ CallAdvisorChain callAdvisorChain ) {
594+ if (this .hookCallCounts != null ) {
595+ this .hookCallCounts [1 ]++;
596+ }
597+ return super .doBeforeCall (chatClientRequest , callAdvisorChain );
598+ }
599+
600+ @ Override
601+ protected ChatClientResponse doAfterCall (ChatClientResponse chatClientResponse ,
602+ CallAdvisorChain callAdvisorChain ) {
603+ if (this .hookCallCounts != null ) {
604+ this .hookCallCounts [2 ]++;
605+ }
606+ return super .doAfterCall (chatClientResponse , callAdvisorChain );
607+ }
608+
609+ static TestableBuilder testBuilder () {
610+ return new TestableBuilder ();
611+ }
612+
613+ static class TestableBuilder extends ToolCallAdvisor .Builder <TestableBuilder > {
614+
615+ @ Override
616+ protected TestableBuilder self () {
617+ return this ;
618+ }
619+
620+ @ Override
621+ public TestableToolCallAdvisor build () {
622+ return new TestableToolCallAdvisor (getToolCallingManager (), getAdvisorOrder (), null );
623+ }
624+
625+ }
626+
627+ }
476628
477629}
0 commit comments