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.model.chat.tool.annotation.ToolDef; 019import com.agentsflex.core.util.ArrayUtil; 020import com.agentsflex.core.util.ClassUtil; 021 022import java.lang.reflect.Method; 023import java.lang.reflect.Modifier; 024import java.util.ArrayList; 025import java.util.List; 026 027/** 028 * 扫描带有 {@link ToolDef} 注解的方法,并将其转换为 {@link Tool} 实例。 029 */ 030public class ToolScanner { 031 032 /** 033 * 从指定对象实例中扫描并提取带 {@link ToolDef} 注解的方法,生成工具列表。 034 * 035 * @param object 对象实例(用于非静态方法) 036 * @param methodNames 可选,指定要扫描的方法名;若为空则扫描所有带注解的方法 037 * @return 工具列表 038 */ 039 public static List<Tool> scan(Object object, String... methodNames) { 040 return doScan(object.getClass(), object, methodNames); 041 } 042 043 /** 044 * 从指定类中扫描并提取带 {@link ToolDef} 注解的静态方法,生成工具列表。 045 * 046 * @param clazz 类(仅扫描静态方法) 047 * @param methodNames 可选,指定要扫描的方法名;若为空则扫描所有带注解的方法 048 * @return 工具列表 049 */ 050 public static List<Tool> scan(Class<?> clazz, String... methodNames) { 051 return doScan(clazz, null, methodNames); 052 } 053 054 private static List<Tool> doScan(Class<?> clazz, Object object, String... methodNames) { 055 clazz = ClassUtil.getUsefulClass(clazz); 056 List<Method> methodList = ClassUtil.getAllMethods(clazz, method -> { 057 if (object == null && !Modifier.isStatic(method.getModifiers())) { 058 return false; 059 } 060 if (method.getAnnotation(ToolDef.class) == null) { 061 return false; 062 } 063 return methodNames.length == 0 || ArrayUtil.contains(methodNames, method.getName()); 064 }); 065 066 List<Tool> tools = new ArrayList<>(); 067 for (Method method : methodList) { 068 MethodTool tool = new MethodTool(); 069 tool.setClazz(clazz); 070 tool.setMethod(method); 071 if (!Modifier.isStatic(method.getModifiers())) { 072 tool.setObject(object); 073 } 074 tools.add(tool); 075 } 076 return tools; 077 } 078}