001/* 002 * Copyright (c) 2023-2026, Agents-Flex (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.agentsflex.core.model.chat.tool; 017 018import com.agentsflex.core.message.ToolCall; 019 020import java.util.*; 021 022/** 023 * 函数调用执行器,支持责任链拦截。 024 * <p> 025 * 执行顺序:全局拦截器 → 用户拦截器 → 实际函数调用。 026 */ 027public class ToolExecutor { 028 029 private final Tool tool; 030 private final ToolCall toolCall; 031 private List<ToolInterceptor> interceptors; 032 033 public ToolExecutor(Tool tool, ToolCall toolCall) { 034 this(tool, toolCall, null); 035 } 036 037 public ToolExecutor(Tool tool, ToolCall toolCall, 038 List<ToolInterceptor> userInterceptors) { 039 this.tool = tool; 040 this.toolCall = toolCall; 041 this.interceptors = buildInterceptorChain(userInterceptors); 042 } 043 044 private List<ToolInterceptor> buildInterceptorChain( 045 List<ToolInterceptor> userInterceptors) { 046 047 // 1. 全局拦截器 048 List<ToolInterceptor> chain = new ArrayList<>(GlobalToolInterceptors.getInterceptors()); 049 050 // 2. 用户拦截器 051 if (userInterceptors != null) { 052 chain.addAll(userInterceptors); 053 } 054 055 return chain; 056 } 057 058 /** 059 * 动态添加拦截器(添加到链尾) 060 */ 061 public void addInterceptor(ToolInterceptor interceptor) { 062 if (interceptors == null) { 063 interceptors = new ArrayList<>(); 064 } 065 this.interceptors.add(interceptor); 066 } 067 068 public void addInterceptors(List<ToolInterceptor> interceptors) { 069 if (interceptors == null) { 070 interceptors = new ArrayList<>(); 071 } 072 this.interceptors.addAll(interceptors); 073 } 074 075 /** 076 * 执行函数调用,触发拦截链。 077 * 078 * @return 函数返回值 079 * @throws RuntimeException 包装原始异常 080 */ 081 public Object execute() { 082 try (ToolContextHolder.ToolContextScope scope = ToolContextHolder.beginExecute(tool, toolCall)) { 083 ToolChain chain = buildChain(0); 084 return chain.proceed(scope.context); 085 } catch (Exception e) { 086 if (e instanceof RuntimeException) { 087 throw (RuntimeException) e; 088 } else { 089 throw new RuntimeException("Error invoking function: " + tool.getName(), e); 090 } 091 } 092 } 093 094 private ToolChain buildChain(int index) { 095 if (index >= interceptors.size()) { 096 return ctx -> ctx.getTool().invoke(ctx.getArgsMap()); 097 } 098 099 ToolInterceptor current = interceptors.get(index); 100 ToolChain next = buildChain(index + 1); 101 return ctx -> current.intercept(ctx, next); 102 } 103 104 105 public Tool getTool() { 106 return tool; 107 } 108 109 public ToolCall getToolCall() { 110 return toolCall; 111 } 112 113 public List<ToolInterceptor> getInterceptors() { 114 return interceptors; 115 } 116 117}