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.response; 017 018import com.agentsflex.core.message.AiMessage; 019import com.agentsflex.core.message.ToolCall; 020import com.agentsflex.core.message.ToolMessage; 021import com.agentsflex.core.model.chat.ChatContext; 022import com.agentsflex.core.model.chat.tool.Tool; 023import com.agentsflex.core.model.chat.tool.ToolExecutor; 024import com.agentsflex.core.model.chat.tool.ToolInterceptor; 025import com.agentsflex.core.prompt.Prompt; 026import com.agentsflex.core.util.CollectionUtil; 027import com.agentsflex.core.util.StringUtil; 028import com.alibaba.fastjson2.JSON; 029 030import java.util.*; 031 032public class AiMessageResponse extends AbstractBaseMessageResponse<AiMessage> { 033 034 private final ChatContext context; 035 private final String rawText; 036 private final AiMessage message; 037 038 public AiMessageResponse(ChatContext context, String rawText, AiMessage message) { 039 this.context = context; 040 this.rawText = rawText; 041 this.message = message; 042 } 043 044 045 public ChatContext getContext() { 046 return context; 047 } 048 049 public String getRawText() { 050 return rawText; 051 } 052 053 @Override 054 public AiMessage getMessage() { 055 return message; 056 } 057 058 public boolean hasToolCalls() { 059 if (this.message == null) { 060 return false; 061 } 062 return message.hasToolCalls(); 063 } 064 065 066 public List<ToolExecutor> getToolExecutors(ToolInterceptor... interceptors) { 067 if (this.message == null) { 068 return Collections.emptyList(); 069 } 070 071 List<ToolCall> calls = message.getToolCalls(); 072 if (calls == null || calls.isEmpty()) { 073 return Collections.emptyList(); 074 } 075 076 Prompt prompt = getContext().getPrompt(); 077 Map<String, Tool> toolsMap = prompt.getToolsMap(); 078 079 if (toolsMap == null || toolsMap.isEmpty()) { 080 return Collections.emptyList(); 081 } 082 083 List<ToolExecutor> toolExecutors = new ArrayList<>(calls.size()); 084 for (ToolCall toolCall : calls) { 085 Tool tool = toolsMap.get(toolCall.getName()); 086 if (tool != null) { 087 ToolExecutor executor = new ToolExecutor(tool, toolCall); 088 if (interceptors != null && interceptors.length > 0) { 089 executor.addInterceptors(Arrays.asList(interceptors)); 090 } 091 toolExecutors.add(executor); 092 } 093 } 094 return toolExecutors; 095 } 096 097 098 public List<Object> executeToolCallsAndGetResults(ToolInterceptor... interceptors) { 099 List<ToolExecutor> toolExecutors = getToolExecutors(interceptors); 100 101 for (ToolExecutor toolExecutor : toolExecutors) { 102 toolExecutor.addInterceptors(Arrays.asList(interceptors)); 103 } 104 105 List<Object> results = new ArrayList<>(); 106 for (ToolExecutor toolExecutor : toolExecutors) { 107 results.add(toolExecutor.execute()); 108 } 109 return results; 110 } 111 112 113 public List<ToolMessage> executeToolCallsAndGetToolMessages(ToolInterceptor... interceptors) { 114 List<ToolExecutor> toolExecutors = getToolExecutors(interceptors); 115 116 if (CollectionUtil.noItems(toolExecutors)) { 117 return Collections.emptyList(); 118 } 119 120 List<ToolMessage> toolMessages = new ArrayList<>(toolExecutors.size()); 121 for (ToolExecutor toolExecutor : toolExecutors) { 122 ToolMessage toolMessage = new ToolMessage(); 123 String callId = toolExecutor.getToolCall().getId(); 124 if (StringUtil.hasText(callId)) { 125 toolMessage.setToolCallId(callId); 126 } else { 127 toolMessage.setToolCallId(toolExecutor.getToolCall().getName()); 128 } 129 Object result = toolExecutor.execute(); 130 if (result instanceof CharSequence || result instanceof Number) { 131 toolMessage.setContent(result.toString()); 132 } else { 133 toolMessage.setContent(JSON.toJSONString(result)); 134 } 135 toolMessages.add(toolMessage); 136 } 137 return toolMessages; 138 } 139 140 141 public static AiMessageResponse error(ChatContext context, String rawText, String errorMessage) { 142 AiMessageResponse errorResp = new AiMessageResponse(context, rawText, null); 143 errorResp.setError(true); 144 errorResp.setErrorMessage(errorMessage); 145 return errorResp; 146 } 147 148 149 @Override 150 public String toString() { 151 return "AiMessageResponse{" + 152 "context=" + context + 153 ", rawText='" + rawText + '\'' + 154 ", message=" + message + 155 ", error=" + error + 156 ", errorMessage='" + errorMessage + '\'' + 157 ", errorType='" + errorType + '\'' + 158 ", errorCode='" + errorCode + '\'' + 159 '}'; 160 } 161}