@@ -9,7 +9,7 @@ import { URI } from '../../../../../../../base/common/uri.js';
99import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../../../base/test/common/utils.js' ;
1010import { NullLogService } from '../../../../../../../platform/log/common/log.js' ;
1111import { TestConfigurationService } from '../../../../../../../platform/configuration/test/common/testConfigurationService.js' ;
12- import { RunSubagentTool } from '../../../../common/tools/builtinTools/runSubagentTool.js' ;
12+ import { RUN_SUBAGENT_MAX_NESTING_DEPTH , RunSubagentTool } from '../../../../common/tools/builtinTools/runSubagentTool.js' ;
1313import { MockLanguageModelToolsService } from '../mockLanguageModelToolsService.js' ;
1414import { IChatAgentHistoryEntry , IChatAgentRequest , IChatAgentResult , IChatAgentService , UserSelectedTools } from '../../../../common/participants/chatAgents.js' ;
1515import { IChatProgress , IChatService } from '../../../../common/chatService/chatService.js' ;
@@ -502,12 +502,12 @@ suite('RunSubagentTool', () => {
502502 */
503503 let callIdCounter = 0 ;
504504 function createInvokableTool ( opts : {
505- maxDepth : number ;
505+ allowInvocationsFromSubagents : boolean ;
506506 capturedRequests : IChatAgentRequest [ ] ;
507507 } ) {
508508 const mockToolsService = testDisposables . add ( new MockLanguageModelToolsService ( ) ) ;
509509 const configService = new TestConfigurationService ( {
510- [ ChatConfiguration . SubagentsMaxDepth ] : opts . maxDepth ,
510+ [ ChatConfiguration . SubagentsAllowInvocationsFromSubagents ] : opts . allowInvocationsFromSubagents ,
511511 } ) ;
512512 const promptsService = new MockPromptsService ( ) ;
513513
@@ -565,9 +565,9 @@ suite('RunSubagentTool', () => {
565565 const countTokens = async ( ) => 0 ;
566566 const noProgress : ToolProgress = { report ( ) { } } ;
567567
568- test ( 'disables runSubagent tool when maxDepth is 0 ' , async ( ) => {
568+ test ( 'disables runSubagent tool when nesting is disabled ' , async ( ) => {
569569 const capturedRequests : IChatAgentRequest [ ] = [ ] ;
570- const { tool } = createInvokableTool ( { maxDepth : 0 , capturedRequests } ) ;
570+ const { tool } = createInvokableTool ( { allowInvocationsFromSubagents : false , capturedRequests } ) ;
571571 const sessionUri = URI . parse ( 'test://session/depth0' ) ;
572572
573573 await tool . invoke ( createInvocation ( sessionUri ) , countTokens , noProgress , CancellationToken . None ) ;
@@ -576,9 +576,9 @@ suite('RunSubagentTool', () => {
576576 assert . strictEqual ( capturedRequests [ 0 ] . userSelectedTools ?. [ 'runSubagent' ] , false ) ;
577577 } ) ;
578578
579- test ( 'enables runSubagent tool at depth 0 when maxDepth >= 1 ' , async ( ) => {
579+ test ( 'enables runSubagent tool at depth 0 when nesting is enabled ' , async ( ) => {
580580 const capturedRequests : IChatAgentRequest [ ] = [ ] ;
581- const { tool } = createInvokableTool ( { maxDepth : 3 , capturedRequests } ) ;
581+ const { tool } = createInvokableTool ( { allowInvocationsFromSubagents : true , capturedRequests } ) ;
582582 const sessionUri = URI . parse ( 'test://session/depth-enabled' ) ;
583583
584584 await tool . invoke ( createInvocation ( sessionUri ) , countTokens , noProgress , CancellationToken . None ) ;
@@ -587,38 +587,40 @@ suite('RunSubagentTool', () => {
587587 assert . strictEqual ( capturedRequests [ 0 ] . userSelectedTools ?. [ 'runSubagent' ] , true ) ;
588588 } ) ;
589589
590- test ( 'disables runSubagent tool when depth reaches maxDepth ' , async ( ) => {
590+ test ( 'disables runSubagent tool when depth reaches hard limit ' , async ( ) => {
591591 const capturedRequests : IChatAgentRequest [ ] = [ ] ;
592592 const sessionUri = URI . parse ( 'test://session/depth-limit' ) ;
593593
594- // maxDepth=1, so the first invoke (depth 0→1) should allow nesting,
595- // but the second invoke (depth 1→2) should not since 1+1 <= 1 is false .
596- const { tool, mockChatAgentService } = createInvokableTool ( { maxDepth : 1 , capturedRequests } ) ;
594+ // When nesting is enabled, the tool enforces a hardcoded maximum depth of 5.
595+ // Simulate nested invocation until we exceed the limit and ensure it disables nesting .
596+ const { tool, mockChatAgentService } = createInvokableTool ( { allowInvocationsFromSubagents : true , capturedRequests } ) ;
597597
598598 // Simulate nested invocation: the first invoke's invokeAgent callback
599599 // triggers a second invoke on the same tool (same session).
600600 capturedRequests . length = 0 ;
601+ let nestedInvocations = 0 ;
601602 mockChatAgentService . invokeAgent = async ( _id : string , request : IChatAgentRequest ) => {
602603 capturedRequests . push ( request ) ;
603- // On the first call (depth 0), simulate a nested subagent call
604- if ( capturedRequests . length === 1 ) {
604+ // Keep nesting until we go beyond the hardcoded maxDepth
605+ if ( nestedInvocations ++ < RUN_SUBAGENT_MAX_NESTING_DEPTH + 1 ) {
605606 await tool . invoke ( createInvocation ( sessionUri ) , countTokens , noProgress , CancellationToken . None ) ;
606607 }
607608 return { } ;
608609 } ;
609610
610611 await tool . invoke ( createInvocation ( sessionUri ) , countTokens , noProgress , CancellationToken . None ) ;
611612
612- assert . strictEqual ( capturedRequests . length , 2 ) ;
613- // First call at depth 0: should enable (0 + 1 <= 1)
614- assert . strictEqual ( capturedRequests [ 0 ] . userSelectedTools ?. [ 'runSubagent' ] , true ) ;
615- // Second call at depth 1: should disable (1 + 1 <= 1 is false)
616- assert . strictEqual ( capturedRequests [ 1 ] . userSelectedTools ?. [ 'runSubagent' ] , false ) ;
613+ assert . ok ( capturedRequests . length >= 2 ) ;
614+ // At depth 0..(maxDepth-1), nesting is allowed. Once depth reaches maxDepth, the next call should disable nesting.
615+ const enabledFlags = capturedRequests . map ( r => r . userSelectedTools ?. [ 'runSubagent' ] ) ;
616+ assert . strictEqual ( enabledFlags [ 0 ] , true ) ;
617+ assert . strictEqual ( enabledFlags [ 1 ] , true ) ;
618+ assert . strictEqual ( enabledFlags [ RUN_SUBAGENT_MAX_NESTING_DEPTH ] , false ) ;
617619 } ) ;
618620
619621 test ( 'depth is decremented after invoke completes' , async ( ) => {
620622 const capturedRequests : IChatAgentRequest [ ] = [ ] ;
621- const { tool } = createInvokableTool ( { maxDepth : 2 , capturedRequests } ) ;
623+ const { tool } = createInvokableTool ( { allowInvocationsFromSubagents : true , capturedRequests } ) ;
622624 const sessionUri = URI . parse ( 'test://session/depth-decrement' ) ;
623625
624626 // First invoke
0 commit comments