feat: Add configuration options for conversational agent, including verbosity, reasoning display, and tool iteration limits
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
#include "absl/status/statusor.h"
|
||||
#include "absl/strings/ascii.h"
|
||||
#include "absl/strings/match.h"
|
||||
#include "absl/strings/numbers.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/strings/str_replace.h"
|
||||
@@ -628,6 +629,10 @@ absl::Status HandleSimpleChatCommand(const std::vector<std::string>& arg_vec,
|
||||
std::optional<std::string> batch_file;
|
||||
std::optional<std::string> single_message;
|
||||
bool non_interactive = false;
|
||||
bool verbose = false;
|
||||
bool show_reasoning = true;
|
||||
int max_tool_iterations = 4;
|
||||
int max_retry_attempts = 3;
|
||||
|
||||
for (size_t i = 0; i < arg_vec.size(); ++i) {
|
||||
const std::string& arg = arg_vec[i];
|
||||
@@ -639,13 +644,35 @@ absl::Status HandleSimpleChatCommand(const std::vector<std::string>& arg_vec,
|
||||
++i;
|
||||
} else if (arg == "--non-interactive" || arg == "-n") {
|
||||
non_interactive = true;
|
||||
} else if (arg == "--verbose" || arg == "-v") {
|
||||
verbose = true;
|
||||
} else if (arg == "--no-reasoning") {
|
||||
show_reasoning = false;
|
||||
} else if (absl::StartsWith(arg, "--max-tool-iterations=")) {
|
||||
absl::SimpleAtoi(arg.substr(22), &max_tool_iterations);
|
||||
} else if (arg == "--max-tool-iterations" && i + 1 < arg_vec.size()) {
|
||||
absl::SimpleAtoi(arg_vec[i + 1], &max_tool_iterations);
|
||||
++i;
|
||||
} else if (absl::StartsWith(arg, "--max-retries=")) {
|
||||
absl::SimpleAtoi(arg.substr(14), &max_retry_attempts);
|
||||
} else if (arg == "--max-retries" && i + 1 < arg_vec.size()) {
|
||||
absl::SimpleAtoi(arg_vec[i + 1], &max_retry_attempts);
|
||||
++i;
|
||||
} else if (!absl::StartsWith(arg, "--") && !single_message.has_value()) {
|
||||
// Treat first non-flag argument as the message
|
||||
single_message = arg;
|
||||
}
|
||||
}
|
||||
|
||||
// Configure agent
|
||||
agent::AgentConfig config;
|
||||
config.verbose = verbose;
|
||||
config.show_reasoning = show_reasoning;
|
||||
config.max_tool_iterations = max_tool_iterations;
|
||||
config.max_retry_attempts = max_retry_attempts;
|
||||
|
||||
SimpleChatSession session;
|
||||
session.SetConfig(config);
|
||||
session.SetRomContext(&rom);
|
||||
|
||||
// Priority: batch file > single message > interactive/piped
|
||||
|
||||
@@ -151,6 +151,11 @@ ConversationalAgentService::ConversationalAgentService() {
|
||||
ai_service_ = CreateAIService();
|
||||
}
|
||||
|
||||
ConversationalAgentService::ConversationalAgentService(const AgentConfig& config)
|
||||
: config_(config) {
|
||||
ai_service_ = CreateAIService();
|
||||
}
|
||||
|
||||
void ConversationalAgentService::SetRomContext(Rom* rom) {
|
||||
rom_context_ = rom;
|
||||
tool_dispatcher_.SetRomContext(rom_context_);
|
||||
@@ -174,16 +179,27 @@ absl::StatusOr<ChatMessage> ConversationalAgentService::SendMessage(
|
||||
history_.push_back(CreateMessage(ChatMessage::Sender::kUser, message));
|
||||
}
|
||||
|
||||
constexpr int kMaxToolIterations = 4;
|
||||
const int max_iterations = config_.max_tool_iterations;
|
||||
bool waiting_for_text_response = false;
|
||||
|
||||
for (int iteration = 0; iteration < kMaxToolIterations; ++iteration) {
|
||||
if (config_.verbose) {
|
||||
util::PrintInfo(absl::StrCat("Starting agent loop (max ", max_iterations, " iterations)"));
|
||||
util::PrintInfo(absl::StrCat("History size: ", history_.size(), " messages"));
|
||||
}
|
||||
|
||||
for (int iteration = 0; iteration < max_iterations; ++iteration) {
|
||||
if (config_.verbose) {
|
||||
util::PrintSeparator();
|
||||
std::cout << util::colors::kCyan << "Iteration " << (iteration + 1)
|
||||
<< "/" << max_iterations << util::colors::kReset << std::endl;
|
||||
}
|
||||
|
||||
// Show loading indicator while waiting for AI response
|
||||
util::LoadingIndicator loader(
|
||||
waiting_for_text_response
|
||||
? "Generating final response..."
|
||||
: "Thinking...",
|
||||
true);
|
||||
!config_.verbose); // Hide spinner in verbose mode
|
||||
loader.Start();
|
||||
|
||||
auto response_or = ai_service_->GenerateResponse(history_);
|
||||
@@ -198,12 +214,28 @@ absl::StatusOr<ChatMessage> ConversationalAgentService::SendMessage(
|
||||
|
||||
const auto& agent_response = response_or.value();
|
||||
|
||||
if (config_.verbose) {
|
||||
util::PrintInfo("Received agent response:");
|
||||
std::cout << util::colors::kDim << " - Tool calls: "
|
||||
<< agent_response.tool_calls.size() << util::colors::kReset << std::endl;
|
||||
std::cout << util::colors::kDim << " - Commands: "
|
||||
<< agent_response.commands.size() << util::colors::kReset << std::endl;
|
||||
std::cout << util::colors::kDim << " - Text response: "
|
||||
<< (agent_response.text_response.empty() ? "empty" : "present")
|
||||
<< util::colors::kReset << std::endl;
|
||||
if (!agent_response.reasoning.empty() && config_.show_reasoning) {
|
||||
std::cout << util::colors::kYellow << " 💭 Reasoning: "
|
||||
<< util::colors::kDim << agent_response.reasoning
|
||||
<< util::colors::kReset << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (!agent_response.tool_calls.empty()) {
|
||||
// Check if we were waiting for a text response but got more tool calls instead
|
||||
if (waiting_for_text_response) {
|
||||
util::PrintWarning(
|
||||
absl::StrCat("LLM called tools again instead of providing final response (Iteration: ",
|
||||
iteration, "/", kMaxToolIterations, ")"));
|
||||
iteration + 1, "/", max_iterations, ")"));
|
||||
}
|
||||
|
||||
bool executed_tool = false;
|
||||
@@ -228,6 +260,15 @@ absl::StatusOr<ChatMessage> ConversationalAgentService::SendMessage(
|
||||
const std::string& tool_output = tool_result_or.value();
|
||||
if (!tool_output.empty()) {
|
||||
util::PrintSuccess("Tool executed successfully");
|
||||
|
||||
if (config_.verbose) {
|
||||
std::cout << util::colors::kDim << "Tool output (truncated):"
|
||||
<< util::colors::kReset << std::endl;
|
||||
std::string preview = tool_output.substr(0, std::min(size_t(200), tool_output.size()));
|
||||
if (tool_output.size() > 200) preview += "...";
|
||||
std::cout << util::colors::kDim << preview << util::colors::kReset << std::endl;
|
||||
}
|
||||
|
||||
// Add tool result with a clear marker for the LLM
|
||||
std::string marked_output = "[TOOL RESULT] " + tool_output;
|
||||
history_.push_back(
|
||||
@@ -249,7 +290,7 @@ absl::StatusOr<ChatMessage> ConversationalAgentService::SendMessage(
|
||||
agent_response.commands.empty()) {
|
||||
util::PrintWarning(
|
||||
absl::StrCat("LLM did not provide text_response after receiving tool results (Iteration: ",
|
||||
iteration, "/", kMaxToolIterations, ")"));
|
||||
iteration + 1, "/", max_iterations, ")"));
|
||||
// Continue to give it another chance
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -29,9 +29,17 @@ struct ChatMessage {
|
||||
std::optional<TableData> table_data;
|
||||
};
|
||||
|
||||
struct AgentConfig {
|
||||
int max_tool_iterations = 4; // Maximum number of tool calling iterations
|
||||
int max_retry_attempts = 3; // Maximum retries on errors
|
||||
bool verbose = false; // Enable verbose diagnostic output
|
||||
bool show_reasoning = true; // Show LLM reasoning in output
|
||||
};
|
||||
|
||||
class ConversationalAgentService {
|
||||
public:
|
||||
ConversationalAgentService();
|
||||
explicit ConversationalAgentService(const AgentConfig& config);
|
||||
|
||||
// Send a message from the user and get the agent's response.
|
||||
absl::StatusOr<ChatMessage> SendMessage(const std::string& message);
|
||||
@@ -45,11 +53,16 @@ class ConversationalAgentService {
|
||||
// Clear the current conversation history, preserving ROM/tool context.
|
||||
void ResetConversation();
|
||||
|
||||
// Configuration
|
||||
void SetConfig(const AgentConfig& config) { config_ = config; }
|
||||
const AgentConfig& GetConfig() const { return config_; }
|
||||
|
||||
private:
|
||||
std::vector<ChatMessage> history_;
|
||||
std::unique_ptr<AIService> ai_service_;
|
||||
ToolDispatcher tool_dispatcher_;
|
||||
Rom* rom_context_ = nullptr;
|
||||
AgentConfig config_;
|
||||
};
|
||||
|
||||
} // namespace agent
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "cli/util/terminal_colors.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace cli {
|
||||
|
||||
@@ -34,6 +34,11 @@ class SimpleChatSession {
|
||||
// Set ROM context for tool execution
|
||||
void SetRomContext(Rom* rom);
|
||||
|
||||
// Set agent configuration
|
||||
void SetConfig(const AgentConfig& config) {
|
||||
agent_service_.SetConfig(config);
|
||||
}
|
||||
|
||||
// Send a single message and get response (blocking)
|
||||
absl::Status SendAndWaitForResponse(const std::string& message,
|
||||
std::string* response_out = nullptr);
|
||||
|
||||
Reference in New Issue
Block a user