@@ -2529,43 +2529,96 @@ describe('ToolService - Action Capability Gating', () => {
25292529 }
25302530 } ) ;
25312531
2532- it ( 'resolves stateful routing for host file tools with the controller conversation ID' , async ( ) => {
2533- const capabilities = [
2534- AgentCapabilities . tools ,
2535- AgentCapabilities . execute_code ,
2536- AgentCapabilities . stateful_code_sessions ,
2537- ] ;
2538- const req = createMockReq ( capabilities ) ;
2539- req . body = { } ;
2540- mockGetEndpointsConfig . mockResolvedValue ( createEndpointsConfig ( capabilities ) ) ;
2541- process . env . LIBRECHAT_CODE_BASEURL_STATEFUL = 'http://code-stateful.test/v1' ;
2532+ it . each ( [ 'read_file' , 'create_file' , 'edit_file' ] ) (
2533+ 'resolves stateful routing for standalone %s with the controller conversation ID' ,
2534+ async ( toolName ) => {
2535+ const capabilities = [
2536+ AgentCapabilities . tools ,
2537+ AgentCapabilities . execute_code ,
2538+ AgentCapabilities . stateful_code_sessions ,
2539+ ] ;
2540+ const req = createMockReq ( capabilities ) ;
2541+ req . body = { } ;
2542+ mockGetEndpointsConfig . mockResolvedValue ( createEndpointsConfig ( capabilities ) ) ;
2543+ process . env . LIBRECHAT_CODE_BASEURL_STATEFUL = 'http://code-stateful.test/v1' ;
2544+
2545+ try {
2546+ const result = await loadToolsForExecution ( {
2547+ req,
2548+ res : { } ,
2549+ conversationId : 'resolved-api-conversation' ,
2550+ agent : {
2551+ id : 'stateful-agent' ,
2552+ tools : [ Tools . execute_code ] ,
2553+ stateful_code_sessions : true ,
2554+ stateful_code_environment : 'conversation' ,
2555+ } ,
2556+ toolNames : [ toolName ] ,
2557+ actionsEnabled : false ,
2558+ } ) ;
2559+
2560+ expect ( result . configurable . codeExecutionContext . executionProfile ) . toBe ( 'stateful' ) ;
2561+ expect ( mockResolveCodeExecutionContext ) . toHaveBeenLastCalledWith (
2562+ expect . objectContaining ( {
2563+ statefulSessions : true ,
2564+ conversationId : 'resolved-api-conversation' ,
2565+ } ) ,
2566+ ) ;
2567+ } finally {
2568+ delete process . env . LIBRECHAT_CODE_BASEURL_STATEFUL ;
2569+ }
2570+ } ,
2571+ ) ;
2572+
2573+ it . each ( [ 'read_file' , 'create_file' , 'edit_file' ] ) (
2574+ 'keeps standalone %s on the selected attached worker' ,
2575+ async ( toolName ) => {
2576+ const capabilities = [
2577+ AgentCapabilities . tools ,
2578+ AgentCapabilities . execute_code ,
2579+ AgentCapabilities . stateful_code_sessions ,
2580+ ] ;
2581+ const req = createMockReq ( capabilities ) ;
2582+ req . config . endpoints . agents . statefulCodeSessions = {
2583+ environments : [
2584+ {
2585+ id : 'personal-machine' ,
2586+ type : 'attached' ,
2587+ baseURL : 'https://attached-code.test/v1' ,
2588+ workerId : 'worker-personal' ,
2589+ } ,
2590+ ] ,
2591+ } ;
2592+ mockGetEndpointsConfig . mockResolvedValue ( createEndpointsConfig ( capabilities ) ) ;
2593+ mockResolveCodeExecutionContext . mockImplementationOnce (
2594+ jest . requireActual ( '@librechat/api' ) . resolveCodeExecutionContext ,
2595+ ) ;
25422596
2543- try {
25442597 const result = await loadToolsForExecution ( {
25452598 req,
25462599 res : { } ,
25472600 conversationId : 'resolved-api-conversation' ,
25482601 agent : {
2549- id : 'stateful -agent' ,
2602+ id : 'attached -agent' ,
25502603 tools : [ Tools . execute_code ] ,
25512604 stateful_code_sessions : true ,
2552- stateful_code_environment : 'conversation ' ,
2605+ code_environment_id : 'personal-machine ' ,
25532606 } ,
2554- toolNames : [ AgentConstants . READ_FILE ] ,
2607+ toolNames : [ toolName ] ,
25552608 actionsEnabled : false ,
25562609 } ) ;
25572610
2558- expect ( result . configurable . codeExecutionContext . executionProfile ) . toBe ( 'stateful' ) ;
2559- expect ( mockResolveCodeExecutionContext ) . toHaveBeenLastCalledWith (
2611+ expect ( result . configurable . codeExecutionContext ) . toEqual (
25602612 expect . objectContaining ( {
2561- statefulSessions : true ,
2562- conversationId : 'resolved-api-conversation' ,
2613+ baseUrl : 'https://attached-code.test/v1' ,
2614+ executionProfile : 'stateful' ,
2615+ environmentType : 'attached' ,
2616+ environmentId : 'personal-machine' ,
2617+ bridgeWorkerId : 'worker-personal' ,
25632618 } ) ,
25642619 ) ;
2565- } finally {
2566- delete process . env . LIBRECHAT_CODE_BASEURL_STATEFUL ;
2567- }
2568- } ) ;
2620+ } ,
2621+ ) ;
25692622
25702623 it ( 'preserves attached routing when workspace search is the only requested tool' , async ( ) => {
25712624 const capabilities = [
0 commit comments