From eb77c83236c2ada35a5055933abfff32d5d6c933 Mon Sep 17 00:00:00 2001 From: hkr04 Date: Sat, 29 Mar 2025 00:04:23 +0800 Subject: [PATCH] remove unused codes; refactor project structure --- CMakeLists.txt | 17 +- agent/humanus.h | 1 - agent/planning.cpp | 248 ------------------ agent/planning.h | 91 ------- agent/swe.h | 69 ----- agent/toolcall.h | 2 - {spdlog => common/spdlog}/async.h | 0 {spdlog => common/spdlog}/async_logger-inl.h | 0 {spdlog => common/spdlog}/async_logger.h | 0 {spdlog => common/spdlog}/cfg/argv.h | 0 {spdlog => common/spdlog}/cfg/env.h | 0 {spdlog => common/spdlog}/cfg/helpers-inl.h | 0 {spdlog => common/spdlog}/cfg/helpers.h | 0 {spdlog => common/spdlog}/common-inl.h | 0 {spdlog => common/spdlog}/common.h | 0 .../spdlog}/details/backtracer-inl.h | 0 .../spdlog}/details/backtracer.h | 0 .../spdlog}/details/circular_q.h | 0 .../spdlog}/details/console_globals.h | 0 .../spdlog}/details/file_helper-inl.h | 0 .../spdlog}/details/file_helper.h | 0 .../spdlog}/details/fmt_helper.h | 0 .../spdlog}/details/log_msg-inl.h | 0 {spdlog => common/spdlog}/details/log_msg.h | 0 .../spdlog}/details/log_msg_buffer-inl.h | 0 .../spdlog}/details/log_msg_buffer.h | 0 .../spdlog}/details/mpmc_blocking_q.h | 0 .../spdlog}/details/null_mutex.h | 0 {spdlog => common/spdlog}/details/os-inl.h | 0 {spdlog => common/spdlog}/details/os.h | 0 .../spdlog}/details/periodic_worker-inl.h | 0 .../spdlog}/details/periodic_worker.h | 0 .../spdlog}/details/registry-inl.h | 0 {spdlog => common/spdlog}/details/registry.h | 0 .../spdlog}/details/synchronous_factory.h | 0 .../spdlog}/details/tcp_client-windows.h | 0 .../spdlog}/details/tcp_client.h | 0 .../spdlog}/details/thread_pool-inl.h | 0 .../spdlog}/details/thread_pool.h | 0 .../spdlog}/details/udp_client-windows.h | 0 .../spdlog}/details/udp_client.h | 0 .../spdlog}/details/windows_include.h | 0 {spdlog => common/spdlog}/fmt/bin_to_hex.h | 0 {spdlog => common/spdlog}/fmt/bundled/args.h | 0 {spdlog => common/spdlog}/fmt/bundled/base.h | 0 .../spdlog}/fmt/bundled/chrono.h | 0 {spdlog => common/spdlog}/fmt/bundled/color.h | 0 .../spdlog}/fmt/bundled/compile.h | 0 {spdlog => common/spdlog}/fmt/bundled/core.h | 0 .../spdlog}/fmt/bundled/fmt.license.rst | 0 .../spdlog}/fmt/bundled/format-inl.h | 0 .../spdlog}/fmt/bundled/format.h | 0 {spdlog => common/spdlog}/fmt/bundled/os.h | 0 .../spdlog}/fmt/bundled/ostream.h | 0 .../spdlog}/fmt/bundled/printf.h | 0 .../spdlog}/fmt/bundled/ranges.h | 0 {spdlog => common/spdlog}/fmt/bundled/std.h | 0 {spdlog => common/spdlog}/fmt/bundled/xchar.h | 0 {spdlog => common/spdlog}/fmt/chrono.h | 0 {spdlog => common/spdlog}/fmt/compile.h | 0 {spdlog => common/spdlog}/fmt/fmt.h | 0 {spdlog => common/spdlog}/fmt/ostr.h | 0 {spdlog => common/spdlog}/fmt/ranges.h | 0 {spdlog => common/spdlog}/fmt/std.h | 0 {spdlog => common/spdlog}/fmt/xchar.h | 0 {spdlog => common/spdlog}/formatter.h | 0 {spdlog => common/spdlog}/fwd.h | 0 {spdlog => common/spdlog}/logger-inl.h | 0 {spdlog => common/spdlog}/logger.h | 0 {spdlog => common/spdlog}/mdc.h | 0 .../spdlog}/pattern_formatter-inl.h | 0 {spdlog => common/spdlog}/pattern_formatter.h | 0 .../spdlog}/sinks/android_sink.h | 0 .../spdlog}/sinks/ansicolor_sink-inl.h | 0 .../spdlog}/sinks/ansicolor_sink.h | 0 .../spdlog}/sinks/base_sink-inl.h | 0 {spdlog => common/spdlog}/sinks/base_sink.h | 0 .../spdlog}/sinks/basic_file_sink-inl.h | 0 .../spdlog}/sinks/basic_file_sink.h | 0 .../spdlog}/sinks/callback_sink.h | 0 .../spdlog}/sinks/daily_file_sink.h | 0 {spdlog => common/spdlog}/sinks/dist_sink.h | 0 .../spdlog}/sinks/dup_filter_sink.h | 0 .../spdlog}/sinks/hourly_file_sink.h | 0 {spdlog => common/spdlog}/sinks/kafka_sink.h | 0 {spdlog => common/spdlog}/sinks/mongo_sink.h | 0 {spdlog => common/spdlog}/sinks/msvc_sink.h | 0 {spdlog => common/spdlog}/sinks/null_sink.h | 0 .../spdlog}/sinks/ostream_sink.h | 0 {spdlog => common/spdlog}/sinks/qt_sinks.h | 0 .../spdlog}/sinks/ringbuffer_sink.h | 0 .../spdlog}/sinks/rotating_file_sink-inl.h | 0 .../spdlog}/sinks/rotating_file_sink.h | 0 {spdlog => common/spdlog}/sinks/sink-inl.h | 0 {spdlog => common/spdlog}/sinks/sink.h | 0 .../spdlog}/sinks/stdout_color_sinks-inl.h | 0 .../spdlog}/sinks/stdout_color_sinks.h | 0 .../spdlog}/sinks/stdout_sinks-inl.h | 0 .../spdlog}/sinks/stdout_sinks.h | 0 {spdlog => common/spdlog}/sinks/syslog_sink.h | 0 .../spdlog}/sinks/systemd_sink.h | 0 {spdlog => common/spdlog}/sinks/tcp_sink.h | 0 {spdlog => common/spdlog}/sinks/udp_sink.h | 0 .../spdlog}/sinks/win_eventlog_sink.h | 0 .../spdlog}/sinks/wincolor_sink-inl.h | 0 .../spdlog}/sinks/wincolor_sink.h | 0 {spdlog => common/spdlog}/spdlog-inl.h | 0 {spdlog => common/spdlog}/spdlog.h | 0 {spdlog => common/spdlog}/stopwatch.h | 0 {spdlog => common/spdlog}/tweakme.h | 0 {spdlog => common/spdlog}/version.h | 0 toml.hpp => common/toml.hpp | 0 config.h => include/config.h | 40 +-- llm.h => include/llm.h | 0 logger.h => include/logger.h | 0 prompt.h => include/prompt.h | 0 schema.h => include/schema.h | 0 snake/game.py | 103 -------- snake/snake_game.py | 61 ----- snake/snake_game_architecture.txt | 34 --- config.cpp => src/config.cpp | 69 ++--- llm.cpp => src/llm.cpp | 0 logger.cpp => src/logger.cpp | 0 prompt.cpp => src/prompt.cpp | 47 ---- schema.cpp => src/schema.cpp | 0 tool/base.h | 41 +-- tool/create_chat_completion.cpp | 128 --------- tool/create_chat_completion.h | 48 ---- tool/shell.h | 128 --------- 129 files changed, 94 insertions(+), 1033 deletions(-) delete mode 100644 agent/planning.cpp delete mode 100644 agent/planning.h delete mode 100644 agent/swe.h rename {spdlog => common/spdlog}/async.h (100%) rename {spdlog => common/spdlog}/async_logger-inl.h (100%) rename {spdlog => common/spdlog}/async_logger.h (100%) rename {spdlog => common/spdlog}/cfg/argv.h (100%) rename {spdlog => common/spdlog}/cfg/env.h (100%) rename {spdlog => common/spdlog}/cfg/helpers-inl.h (100%) rename {spdlog => common/spdlog}/cfg/helpers.h (100%) rename {spdlog => common/spdlog}/common-inl.h (100%) rename {spdlog => common/spdlog}/common.h (100%) rename {spdlog => common/spdlog}/details/backtracer-inl.h (100%) rename {spdlog => common/spdlog}/details/backtracer.h (100%) rename {spdlog => common/spdlog}/details/circular_q.h (100%) rename {spdlog => common/spdlog}/details/console_globals.h (100%) rename {spdlog => common/spdlog}/details/file_helper-inl.h (100%) rename {spdlog => common/spdlog}/details/file_helper.h (100%) rename {spdlog => common/spdlog}/details/fmt_helper.h (100%) rename {spdlog => common/spdlog}/details/log_msg-inl.h (100%) rename {spdlog => common/spdlog}/details/log_msg.h (100%) rename {spdlog => common/spdlog}/details/log_msg_buffer-inl.h (100%) rename {spdlog => common/spdlog}/details/log_msg_buffer.h (100%) rename {spdlog => common/spdlog}/details/mpmc_blocking_q.h (100%) rename {spdlog => common/spdlog}/details/null_mutex.h (100%) rename {spdlog => common/spdlog}/details/os-inl.h (100%) rename {spdlog => common/spdlog}/details/os.h (100%) rename {spdlog => common/spdlog}/details/periodic_worker-inl.h (100%) rename {spdlog => common/spdlog}/details/periodic_worker.h (100%) rename {spdlog => common/spdlog}/details/registry-inl.h (100%) rename {spdlog => common/spdlog}/details/registry.h (100%) rename {spdlog => common/spdlog}/details/synchronous_factory.h (100%) rename {spdlog => common/spdlog}/details/tcp_client-windows.h (100%) rename {spdlog => common/spdlog}/details/tcp_client.h (100%) rename {spdlog => common/spdlog}/details/thread_pool-inl.h (100%) rename {spdlog => common/spdlog}/details/thread_pool.h (100%) rename {spdlog => common/spdlog}/details/udp_client-windows.h (100%) rename {spdlog => common/spdlog}/details/udp_client.h (100%) rename {spdlog => common/spdlog}/details/windows_include.h (100%) rename {spdlog => common/spdlog}/fmt/bin_to_hex.h (100%) rename {spdlog => common/spdlog}/fmt/bundled/args.h (100%) rename {spdlog => common/spdlog}/fmt/bundled/base.h (100%) rename {spdlog => common/spdlog}/fmt/bundled/chrono.h (100%) rename {spdlog => common/spdlog}/fmt/bundled/color.h (100%) rename {spdlog => common/spdlog}/fmt/bundled/compile.h (100%) rename {spdlog => common/spdlog}/fmt/bundled/core.h (100%) rename {spdlog => common/spdlog}/fmt/bundled/fmt.license.rst (100%) rename {spdlog => common/spdlog}/fmt/bundled/format-inl.h (100%) rename {spdlog => common/spdlog}/fmt/bundled/format.h (100%) rename {spdlog => common/spdlog}/fmt/bundled/os.h (100%) rename {spdlog => common/spdlog}/fmt/bundled/ostream.h (100%) rename {spdlog => common/spdlog}/fmt/bundled/printf.h (100%) rename {spdlog => common/spdlog}/fmt/bundled/ranges.h (100%) rename {spdlog => common/spdlog}/fmt/bundled/std.h (100%) rename {spdlog => common/spdlog}/fmt/bundled/xchar.h (100%) rename {spdlog => common/spdlog}/fmt/chrono.h (100%) rename {spdlog => common/spdlog}/fmt/compile.h (100%) rename {spdlog => common/spdlog}/fmt/fmt.h (100%) rename {spdlog => common/spdlog}/fmt/ostr.h (100%) rename {spdlog => common/spdlog}/fmt/ranges.h (100%) rename {spdlog => common/spdlog}/fmt/std.h (100%) rename {spdlog => common/spdlog}/fmt/xchar.h (100%) rename {spdlog => common/spdlog}/formatter.h (100%) rename {spdlog => common/spdlog}/fwd.h (100%) rename {spdlog => common/spdlog}/logger-inl.h (100%) rename {spdlog => common/spdlog}/logger.h (100%) rename {spdlog => common/spdlog}/mdc.h (100%) rename {spdlog => common/spdlog}/pattern_formatter-inl.h (100%) rename {spdlog => common/spdlog}/pattern_formatter.h (100%) rename {spdlog => common/spdlog}/sinks/android_sink.h (100%) rename {spdlog => common/spdlog}/sinks/ansicolor_sink-inl.h (100%) rename {spdlog => common/spdlog}/sinks/ansicolor_sink.h (100%) rename {spdlog => common/spdlog}/sinks/base_sink-inl.h (100%) rename {spdlog => common/spdlog}/sinks/base_sink.h (100%) rename {spdlog => common/spdlog}/sinks/basic_file_sink-inl.h (100%) rename {spdlog => common/spdlog}/sinks/basic_file_sink.h (100%) rename {spdlog => common/spdlog}/sinks/callback_sink.h (100%) rename {spdlog => common/spdlog}/sinks/daily_file_sink.h (100%) rename {spdlog => common/spdlog}/sinks/dist_sink.h (100%) rename {spdlog => common/spdlog}/sinks/dup_filter_sink.h (100%) rename {spdlog => common/spdlog}/sinks/hourly_file_sink.h (100%) rename {spdlog => common/spdlog}/sinks/kafka_sink.h (100%) rename {spdlog => common/spdlog}/sinks/mongo_sink.h (100%) rename {spdlog => common/spdlog}/sinks/msvc_sink.h (100%) rename {spdlog => common/spdlog}/sinks/null_sink.h (100%) rename {spdlog => common/spdlog}/sinks/ostream_sink.h (100%) rename {spdlog => common/spdlog}/sinks/qt_sinks.h (100%) rename {spdlog => common/spdlog}/sinks/ringbuffer_sink.h (100%) rename {spdlog => common/spdlog}/sinks/rotating_file_sink-inl.h (100%) rename {spdlog => common/spdlog}/sinks/rotating_file_sink.h (100%) rename {spdlog => common/spdlog}/sinks/sink-inl.h (100%) rename {spdlog => common/spdlog}/sinks/sink.h (100%) rename {spdlog => common/spdlog}/sinks/stdout_color_sinks-inl.h (100%) rename {spdlog => common/spdlog}/sinks/stdout_color_sinks.h (100%) rename {spdlog => common/spdlog}/sinks/stdout_sinks-inl.h (100%) rename {spdlog => common/spdlog}/sinks/stdout_sinks.h (100%) rename {spdlog => common/spdlog}/sinks/syslog_sink.h (100%) rename {spdlog => common/spdlog}/sinks/systemd_sink.h (100%) rename {spdlog => common/spdlog}/sinks/tcp_sink.h (100%) rename {spdlog => common/spdlog}/sinks/udp_sink.h (100%) rename {spdlog => common/spdlog}/sinks/win_eventlog_sink.h (100%) rename {spdlog => common/spdlog}/sinks/wincolor_sink-inl.h (100%) rename {spdlog => common/spdlog}/sinks/wincolor_sink.h (100%) rename {spdlog => common/spdlog}/spdlog-inl.h (100%) rename {spdlog => common/spdlog}/spdlog.h (100%) rename {spdlog => common/spdlog}/stopwatch.h (100%) rename {spdlog => common/spdlog}/tweakme.h (100%) rename {spdlog => common/spdlog}/version.h (100%) rename toml.hpp => common/toml.hpp (100%) rename config.h => include/config.h (92%) rename llm.h => include/llm.h (100%) rename logger.h => include/logger.h (100%) rename prompt.h => include/prompt.h (100%) rename schema.h => include/schema.h (100%) delete mode 100644 snake/game.py delete mode 100644 snake/snake_game.py delete mode 100644 snake/snake_game_architecture.txt rename config.cpp => src/config.cpp (87%) rename llm.cpp => src/llm.cpp (100%) rename logger.cpp => src/logger.cpp (100%) rename prompt.cpp => src/prompt.cpp (80%) rename schema.cpp => src/schema.cpp (100%) delete mode 100644 tool/create_chat_completion.cpp delete mode 100644 tool/create_chat_completion.h delete mode 100644 tool/shell.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 99bc6ca..35a43fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,8 @@ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/server) # include include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/common) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/mcp/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/mcp/common) @@ -90,13 +92,13 @@ file(GLOB MEMORY_SOURCES "memory/*/*/*.cc" ) -# 创建humanus核心库,包含所有共享组件 +# humanus core add_library(humanus - config.cpp - llm.cpp - prompt.cpp - logger.cpp - schema.cpp + src/config.cpp + src/llm.cpp + src/prompt.cpp + src/logger.cpp + src/schema.cpp ${AGENT_SOURCES} ${TOOL_SOURCES} ${FLOW_SOURCES} @@ -104,9 +106,10 @@ add_library(humanus ) target_link_libraries(humanus PUBLIC Threads::Threads mcp ${OPENSSL_LIBRARIES}) + if(Python3_FOUND) target_link_libraries(humanus PUBLIC ${Python3_LIBRARIES}) endif() -# 添加examples目录 +# examples add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/examples) \ No newline at end of file diff --git a/agent/humanus.h b/agent/humanus.h index c1bf25b..9798f83 100644 --- a/agent/humanus.h +++ b/agent/humanus.h @@ -9,7 +9,6 @@ #include "tool/terminate.h" #include "tool/puppeteer.h" #include "tool/filesystem.h" -#include "tool/shell.h" namespace humanus { diff --git a/agent/planning.cpp b/agent/planning.cpp deleted file mode 100644 index 2653ab1..0000000 --- a/agent/planning.cpp +++ /dev/null @@ -1,248 +0,0 @@ -#include "planning.h" -#include - -namespace humanus { - -// Initialize the agent with a default plan ID and validate required tools. -void PlanningAgent::initialize_plan_and_verify_tools() { - active_plan_id = "plan_" + std::to_string(std::chrono::system_clock::now().time_since_epoch().count()); - - if (available_tools.tools_map.find("planning") == available_tools.tools_map.end()) { - available_tools.add_tool(std::make_shared()); - } -} - -// Decide the next action based on plan status. -bool PlanningAgent::think() { - std::string prompt; - if (!active_plan_id.empty()) { - prompt = "CURRENT PLAN STATUS:\n" + get_plan(); - } - memory->add_message(Message::user_message(prompt)); - - // Get the current step index before thinking - current_step_index = _get_current_step_index(); - - bool result = ToolCallAgent::think(); // Will set tool_calls - - // After thinking, if we decided to execute a tool and it's not a planning tool or special tool, - // associate it with the current step for tracking - if (result && !tool_calls.empty()) { - auto latest_tool_call = tool_calls.back(); // Get the most recent tool call - if (latest_tool_call.function.name != "planning" - && !_is_special_tool(latest_tool_call.function.name) - && current_step_index >= 0) { - step_execution_tracker[latest_tool_call.id] = { - {"step_index", current_step_index}, - {"tool_name", latest_tool_call.function.name}, - {"step_status", "pending"} // Will be updated after execution - }; - } - } - - return result; -} - -// Execute a step and track its completion status. -std::string PlanningAgent::act() { - std::string result = ToolCallAgent::act(); - - // After executing the tool, update the plan status - if (!tool_calls.empty()) { - auto latest_tool_call = tool_calls.back(); - - // Update the execution status to completed - if (step_execution_tracker.find(latest_tool_call.id) != step_execution_tracker.end()) { - step_execution_tracker[latest_tool_call.id]["status"] = "completed"; - step_execution_tracker[latest_tool_call.id]["result"] = result; - - // Update the plan status if this was a non-planning, non-special tool - if ( - latest_tool_call.function.name != "planning" - && !_is_special_tool(latest_tool_call.function.name) - ) { - update_plan_status(latest_tool_call.id); - } - } - } - - return result; -} - -// Retrieve the current plan status. -std::string PlanningAgent::get_plan() { - if (active_plan_id.empty()) { - return "No active plan. Please create a plan first."; - } - - ToolResult result = available_tools.execute( - "planning", - {{"command", "get"}, {"plan_id", active_plan_id}} - ); - - return result.to_string(); -} - -// Run the agent with an optional initial request. -std::string PlanningAgent::run(const std::string& request) { - if (!request.empty()) { - create_initial_plan(request); - } - - return BaseAgent::run(); -} - -// Update the current plan progress based on completed tool execution. -// Only marks a step as completed if the associated tool has been successfully executed. -void PlanningAgent::update_plan_status(const std::string& tool_call_id) { - if (active_plan_id.empty()) { - return; - } - - if (step_execution_tracker.find(tool_call_id) == step_execution_tracker.end()) { - logger->warn("No step tracking found for tool call " + tool_call_id); - return; - } - - auto tracker = step_execution_tracker[tool_call_id]; - if (tracker["status"] != "completed") { - logger->warn("Tool call " + tool_call_id + " has not completed successfully"); - return; - } - - int step_index = tracker["step_index"]; - - try { - // Mark the step as completed - ToolResult result = available_tools.execute( - "planning", - { - {"command", "mark_step"}, - {"plan_id", active_plan_id}, - {"step_index", step_index}, - {"step_status", "completed"} - } - ); - logger->info( - "Marked step " + std::to_string(step_index) + " as completed in plan " + active_plan_id - + "\n\n" + result.to_string() + "\n\n" - ); - } catch (const std::exception& e) { - logger->warn("Failed to update plan status: " + std::string(e.what())); - } -} - -// Parse the current plan to identify the first non-completed step's index. -// Returns -1 if no active step is found. -int PlanningAgent::_get_current_step_index() { - if (active_plan_id.empty()) { - return -1; - } - - auto plan = get_plan(); - - auto splitlines = [](const std::string& s) { - std::vector lines; - std::istringstream iss(s); - std::string line; - while (std::getline(iss, line)) { - lines.push_back(line); - } - return lines; - }; - - try { - std::vector plan_lines = splitlines(plan); - int steps_index = -1; - - // Find the index of the "Steps:" line - for (size_t i = 0; i < plan_lines.size(); ++i) { - if (plan_lines[i].find("Steps:") == 0) { - steps_index = i; - break; - } - } - - if (steps_index == -1) { - return -1; - } - - // Find the first non-completed step - for (size_t i = steps_index + 1; i < plan_lines.size(); ++i) { - std::string line = plan_lines[i]; - if (line.find("[ ]") != std::string::npos || line.find("[→]") != std::string::npos) { // not_started or in_progress - // Mark current step as in_progress - available_tools.execute( - "planning", - { - {"command", "mark_step"}, - {"plan_id", active_plan_id}, - {"step_index", i}, - {"step_status", "in_progress"} - } - ); - return i; - } - } - - return -1; // # No active step found - } catch (const std::exception& e) { - logger->warn("Error finding current step index: " + std::string(e.what())); - return -1; - } -} - -// Create an initial plan based on the request. -void PlanningAgent::create_initial_plan(const std::string& request) { - logger->info("Creating initial plan with ID: " + active_plan_id); - - std::vector messages = { - Message::user_message( - "Analyze the request and create a plan with ID " + active_plan_id + ": " + request - ) - }; - memory->add_messages(messages); - json response = llm->ask_tool( - messages, - system_prompt, - next_step_prompt, - available_tools.to_params(), - tool_choice - ); - - tool_calls = ToolCall::from_json_list(response["tool_calls"]); - - Message assistant_msg = Message::assistant_message( - response["content"], tool_calls - ); - - memory->add_message(assistant_msg); - - bool plan_created = false; - for (const ToolCall& tool_call : tool_calls) { - if (tool_call.function.name == "planning") { - std::string result = execute_tool(tool_call); - logger->info("Executed tool " + tool_call.function.name + " with result: " + result); - - // Add tool response to memory - Message tool_msg = Message::tool_message( - result, - tool_call.id, - tool_call.function.name - ); - memory->add_message(tool_msg); - plan_created = true; - break; - } - } - - if (!plan_created) { - logger->warn("No plan created from initial request"); - Message tool_msg = Message::assistant_message( - "Error: Parameter `plan_id` is required for command: create" - ); - memory->add_message(tool_msg); - } -} - -} // namespace humanus \ No newline at end of file diff --git a/agent/planning.h b/agent/planning.h deleted file mode 100644 index 16bce7a..0000000 --- a/agent/planning.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef HUMANUS_AGENT_PLANNING_H -#define HUMANUS_AGENT_PLANNING_H - -#include "toolcall.h" -#include "tool/planning.h" -#include "prompt.h" - -namespace humanus { - -/** - * An agent that creates and manages plans to solve tasks. - - * This agent uses a planning tool to create and manage structured plans, - * and tracks progress through individual steps until task completion. -*/ -struct PlanningAgent : ToolCallAgent { - std::string active_plan_id; - - // Add a dictionary to track the step status for each tool call - std::map step_execution_tracker; - int current_step_index; - - PlanningAgent( - const ToolCollection& available_tools = ToolCollection( - { - std::make_shared(), - std::make_shared() - } - ), - const std::string& tool_choice = "auto", - const std::set& special_tool_names = {"terminate"}, - const std::string& name = "planning", - const std::string& description = "An agent that creates and manages plans to solve tasks", - const std::string& system_prompt = prompt::planning::PLANNING_SYSTEM_PROMPT, - const std::string& next_step_prompt = prompt::planning::NEXT_STEP_PROMPT, - const std::shared_ptr& llm = nullptr, - const std::shared_ptr& memory = nullptr, - AgentState state = AgentState::IDLE, - int max_steps = 20, - int current_step = 0, - int duplicate_threshold = 2 - ) : ToolCallAgent( - available_tools, - tool_choice, - special_tool_names, - name, - description, - system_prompt, - next_step_prompt, - llm, - memory, - state, - max_steps, - current_step, - duplicate_threshold - ) { - current_step_index = -1; // will be set in think() - initialize_plan_and_verify_tools(); - } - - // Initialize the agent with a default plan ID and validate required tools. - void initialize_plan_and_verify_tools(); - - // Decide the next action based on plan status. - bool think() override; - - // Execute a step and track its completion status. - std::string act() override; - - // Retrieve the current plan status. - std::string get_plan(); - - // Run the agent with an optional initial request. - std::string run(const std::string& request = "") override; - - // Update the current plan progress based on completed tool execution. - // Only marks a step as completed if the associated tool has been successfully executed. - void update_plan_status(const std::string& tool_call_id); - - // Parse the current plan to identify the first non-completed step's index. - // Returns None if no active step is found. - int _get_current_step_index(); - - // Create an initial plan based on the request. - void create_initial_plan(const std::string& request); -}; - - -} // namespace humanus - -#endif // HUMANUS_AGENT_PLANNING_H \ No newline at end of file diff --git a/agent/swe.h b/agent/swe.h deleted file mode 100644 index d131d3c..0000000 --- a/agent/swe.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef HUMANUS_AGENT_SWE_H -#define HUMANUS_AGENT_SWE_H - -#include "toolcall.h" -#include "tool/tool_collection.h" -#include "tool/terminate.h" -#include "tool/shell.h" -#include "tool/filesystem.h" -#include "prompt.h" - -namespace humanus { - -// An agent that implements the SWEAgent paradigm for executing code and natural conversations. -struct SweAgent : ToolCallAgent { - std::string working_dir; - - SweAgent( - const std::string& working_dir = ".", - const ToolCollection& available_tools = ToolCollection( - { - std::make_shared(), - std::make_shared(), - std::make_shared() - } - ), - const std::string& tool_choice = "auto", - const std::set& special_tool_names = {"terminate"}, - const std::string& name = "swe", - const std::string& description = "an autonomous AI programmer that interacts directly with the computer to solve tasks.", - const std::string& system_prompt = prompt::swe::SYSTEM_PROMPT, - const std::string& next_step_prompt = prompt::swe::NEXT_STEP_TEMPLATE, - const std::shared_ptr& llm = nullptr, - const std::shared_ptr& memory = nullptr, - AgentState state = AgentState::IDLE, - int max_steps = 100, - int current_step = 0, - int duplicate_threshold = 2 - ) : ToolCallAgent( - available_tools, - tool_choice, - special_tool_names, - name, - description, - system_prompt, - next_step_prompt, - llm, - memory, - state, - max_steps, - current_step, - duplicate_threshold - ), - working_dir(working_dir) {} - - bool think() override { - // Update working directory - working_dir = std::filesystem::current_path().string(); // TODO: Maybe use predefined working directory? - next_step_prompt = prompt::swe::NEXT_STEP_TEMPLATE; - next_step_prompt = next_step_prompt.replace( - next_step_prompt.find("{working_dir}"), std::string("{working_dir}").length(), working_dir - ); - - return ToolCallAgent::think(); - } -}; - -} - -#endif // HUMANUS_AGENT_SWE_H diff --git a/agent/toolcall.h b/agent/toolcall.h index 76e03a4..eea39c1 100644 --- a/agent/toolcall.h +++ b/agent/toolcall.h @@ -4,7 +4,6 @@ #include "react.h" #include "prompt.h" #include "tool/tool_collection.h" -#include "tool/create_chat_completion.h" #include "tool/terminate.h" namespace humanus { @@ -19,7 +18,6 @@ struct ToolCallAgent : ReActAgent { ToolCallAgent( const ToolCollection& available_tools = ToolCollection( { - std::make_shared(), std::make_shared() } ), diff --git a/spdlog/async.h b/common/spdlog/async.h similarity index 100% rename from spdlog/async.h rename to common/spdlog/async.h diff --git a/spdlog/async_logger-inl.h b/common/spdlog/async_logger-inl.h similarity index 100% rename from spdlog/async_logger-inl.h rename to common/spdlog/async_logger-inl.h diff --git a/spdlog/async_logger.h b/common/spdlog/async_logger.h similarity index 100% rename from spdlog/async_logger.h rename to common/spdlog/async_logger.h diff --git a/spdlog/cfg/argv.h b/common/spdlog/cfg/argv.h similarity index 100% rename from spdlog/cfg/argv.h rename to common/spdlog/cfg/argv.h diff --git a/spdlog/cfg/env.h b/common/spdlog/cfg/env.h similarity index 100% rename from spdlog/cfg/env.h rename to common/spdlog/cfg/env.h diff --git a/spdlog/cfg/helpers-inl.h b/common/spdlog/cfg/helpers-inl.h similarity index 100% rename from spdlog/cfg/helpers-inl.h rename to common/spdlog/cfg/helpers-inl.h diff --git a/spdlog/cfg/helpers.h b/common/spdlog/cfg/helpers.h similarity index 100% rename from spdlog/cfg/helpers.h rename to common/spdlog/cfg/helpers.h diff --git a/spdlog/common-inl.h b/common/spdlog/common-inl.h similarity index 100% rename from spdlog/common-inl.h rename to common/spdlog/common-inl.h diff --git a/spdlog/common.h b/common/spdlog/common.h similarity index 100% rename from spdlog/common.h rename to common/spdlog/common.h diff --git a/spdlog/details/backtracer-inl.h b/common/spdlog/details/backtracer-inl.h similarity index 100% rename from spdlog/details/backtracer-inl.h rename to common/spdlog/details/backtracer-inl.h diff --git a/spdlog/details/backtracer.h b/common/spdlog/details/backtracer.h similarity index 100% rename from spdlog/details/backtracer.h rename to common/spdlog/details/backtracer.h diff --git a/spdlog/details/circular_q.h b/common/spdlog/details/circular_q.h similarity index 100% rename from spdlog/details/circular_q.h rename to common/spdlog/details/circular_q.h diff --git a/spdlog/details/console_globals.h b/common/spdlog/details/console_globals.h similarity index 100% rename from spdlog/details/console_globals.h rename to common/spdlog/details/console_globals.h diff --git a/spdlog/details/file_helper-inl.h b/common/spdlog/details/file_helper-inl.h similarity index 100% rename from spdlog/details/file_helper-inl.h rename to common/spdlog/details/file_helper-inl.h diff --git a/spdlog/details/file_helper.h b/common/spdlog/details/file_helper.h similarity index 100% rename from spdlog/details/file_helper.h rename to common/spdlog/details/file_helper.h diff --git a/spdlog/details/fmt_helper.h b/common/spdlog/details/fmt_helper.h similarity index 100% rename from spdlog/details/fmt_helper.h rename to common/spdlog/details/fmt_helper.h diff --git a/spdlog/details/log_msg-inl.h b/common/spdlog/details/log_msg-inl.h similarity index 100% rename from spdlog/details/log_msg-inl.h rename to common/spdlog/details/log_msg-inl.h diff --git a/spdlog/details/log_msg.h b/common/spdlog/details/log_msg.h similarity index 100% rename from spdlog/details/log_msg.h rename to common/spdlog/details/log_msg.h diff --git a/spdlog/details/log_msg_buffer-inl.h b/common/spdlog/details/log_msg_buffer-inl.h similarity index 100% rename from spdlog/details/log_msg_buffer-inl.h rename to common/spdlog/details/log_msg_buffer-inl.h diff --git a/spdlog/details/log_msg_buffer.h b/common/spdlog/details/log_msg_buffer.h similarity index 100% rename from spdlog/details/log_msg_buffer.h rename to common/spdlog/details/log_msg_buffer.h diff --git a/spdlog/details/mpmc_blocking_q.h b/common/spdlog/details/mpmc_blocking_q.h similarity index 100% rename from spdlog/details/mpmc_blocking_q.h rename to common/spdlog/details/mpmc_blocking_q.h diff --git a/spdlog/details/null_mutex.h b/common/spdlog/details/null_mutex.h similarity index 100% rename from spdlog/details/null_mutex.h rename to common/spdlog/details/null_mutex.h diff --git a/spdlog/details/os-inl.h b/common/spdlog/details/os-inl.h similarity index 100% rename from spdlog/details/os-inl.h rename to common/spdlog/details/os-inl.h diff --git a/spdlog/details/os.h b/common/spdlog/details/os.h similarity index 100% rename from spdlog/details/os.h rename to common/spdlog/details/os.h diff --git a/spdlog/details/periodic_worker-inl.h b/common/spdlog/details/periodic_worker-inl.h similarity index 100% rename from spdlog/details/periodic_worker-inl.h rename to common/spdlog/details/periodic_worker-inl.h diff --git a/spdlog/details/periodic_worker.h b/common/spdlog/details/periodic_worker.h similarity index 100% rename from spdlog/details/periodic_worker.h rename to common/spdlog/details/periodic_worker.h diff --git a/spdlog/details/registry-inl.h b/common/spdlog/details/registry-inl.h similarity index 100% rename from spdlog/details/registry-inl.h rename to common/spdlog/details/registry-inl.h diff --git a/spdlog/details/registry.h b/common/spdlog/details/registry.h similarity index 100% rename from spdlog/details/registry.h rename to common/spdlog/details/registry.h diff --git a/spdlog/details/synchronous_factory.h b/common/spdlog/details/synchronous_factory.h similarity index 100% rename from spdlog/details/synchronous_factory.h rename to common/spdlog/details/synchronous_factory.h diff --git a/spdlog/details/tcp_client-windows.h b/common/spdlog/details/tcp_client-windows.h similarity index 100% rename from spdlog/details/tcp_client-windows.h rename to common/spdlog/details/tcp_client-windows.h diff --git a/spdlog/details/tcp_client.h b/common/spdlog/details/tcp_client.h similarity index 100% rename from spdlog/details/tcp_client.h rename to common/spdlog/details/tcp_client.h diff --git a/spdlog/details/thread_pool-inl.h b/common/spdlog/details/thread_pool-inl.h similarity index 100% rename from spdlog/details/thread_pool-inl.h rename to common/spdlog/details/thread_pool-inl.h diff --git a/spdlog/details/thread_pool.h b/common/spdlog/details/thread_pool.h similarity index 100% rename from spdlog/details/thread_pool.h rename to common/spdlog/details/thread_pool.h diff --git a/spdlog/details/udp_client-windows.h b/common/spdlog/details/udp_client-windows.h similarity index 100% rename from spdlog/details/udp_client-windows.h rename to common/spdlog/details/udp_client-windows.h diff --git a/spdlog/details/udp_client.h b/common/spdlog/details/udp_client.h similarity index 100% rename from spdlog/details/udp_client.h rename to common/spdlog/details/udp_client.h diff --git a/spdlog/details/windows_include.h b/common/spdlog/details/windows_include.h similarity index 100% rename from spdlog/details/windows_include.h rename to common/spdlog/details/windows_include.h diff --git a/spdlog/fmt/bin_to_hex.h b/common/spdlog/fmt/bin_to_hex.h similarity index 100% rename from spdlog/fmt/bin_to_hex.h rename to common/spdlog/fmt/bin_to_hex.h diff --git a/spdlog/fmt/bundled/args.h b/common/spdlog/fmt/bundled/args.h similarity index 100% rename from spdlog/fmt/bundled/args.h rename to common/spdlog/fmt/bundled/args.h diff --git a/spdlog/fmt/bundled/base.h b/common/spdlog/fmt/bundled/base.h similarity index 100% rename from spdlog/fmt/bundled/base.h rename to common/spdlog/fmt/bundled/base.h diff --git a/spdlog/fmt/bundled/chrono.h b/common/spdlog/fmt/bundled/chrono.h similarity index 100% rename from spdlog/fmt/bundled/chrono.h rename to common/spdlog/fmt/bundled/chrono.h diff --git a/spdlog/fmt/bundled/color.h b/common/spdlog/fmt/bundled/color.h similarity index 100% rename from spdlog/fmt/bundled/color.h rename to common/spdlog/fmt/bundled/color.h diff --git a/spdlog/fmt/bundled/compile.h b/common/spdlog/fmt/bundled/compile.h similarity index 100% rename from spdlog/fmt/bundled/compile.h rename to common/spdlog/fmt/bundled/compile.h diff --git a/spdlog/fmt/bundled/core.h b/common/spdlog/fmt/bundled/core.h similarity index 100% rename from spdlog/fmt/bundled/core.h rename to common/spdlog/fmt/bundled/core.h diff --git a/spdlog/fmt/bundled/fmt.license.rst b/common/spdlog/fmt/bundled/fmt.license.rst similarity index 100% rename from spdlog/fmt/bundled/fmt.license.rst rename to common/spdlog/fmt/bundled/fmt.license.rst diff --git a/spdlog/fmt/bundled/format-inl.h b/common/spdlog/fmt/bundled/format-inl.h similarity index 100% rename from spdlog/fmt/bundled/format-inl.h rename to common/spdlog/fmt/bundled/format-inl.h diff --git a/spdlog/fmt/bundled/format.h b/common/spdlog/fmt/bundled/format.h similarity index 100% rename from spdlog/fmt/bundled/format.h rename to common/spdlog/fmt/bundled/format.h diff --git a/spdlog/fmt/bundled/os.h b/common/spdlog/fmt/bundled/os.h similarity index 100% rename from spdlog/fmt/bundled/os.h rename to common/spdlog/fmt/bundled/os.h diff --git a/spdlog/fmt/bundled/ostream.h b/common/spdlog/fmt/bundled/ostream.h similarity index 100% rename from spdlog/fmt/bundled/ostream.h rename to common/spdlog/fmt/bundled/ostream.h diff --git a/spdlog/fmt/bundled/printf.h b/common/spdlog/fmt/bundled/printf.h similarity index 100% rename from spdlog/fmt/bundled/printf.h rename to common/spdlog/fmt/bundled/printf.h diff --git a/spdlog/fmt/bundled/ranges.h b/common/spdlog/fmt/bundled/ranges.h similarity index 100% rename from spdlog/fmt/bundled/ranges.h rename to common/spdlog/fmt/bundled/ranges.h diff --git a/spdlog/fmt/bundled/std.h b/common/spdlog/fmt/bundled/std.h similarity index 100% rename from spdlog/fmt/bundled/std.h rename to common/spdlog/fmt/bundled/std.h diff --git a/spdlog/fmt/bundled/xchar.h b/common/spdlog/fmt/bundled/xchar.h similarity index 100% rename from spdlog/fmt/bundled/xchar.h rename to common/spdlog/fmt/bundled/xchar.h diff --git a/spdlog/fmt/chrono.h b/common/spdlog/fmt/chrono.h similarity index 100% rename from spdlog/fmt/chrono.h rename to common/spdlog/fmt/chrono.h diff --git a/spdlog/fmt/compile.h b/common/spdlog/fmt/compile.h similarity index 100% rename from spdlog/fmt/compile.h rename to common/spdlog/fmt/compile.h diff --git a/spdlog/fmt/fmt.h b/common/spdlog/fmt/fmt.h similarity index 100% rename from spdlog/fmt/fmt.h rename to common/spdlog/fmt/fmt.h diff --git a/spdlog/fmt/ostr.h b/common/spdlog/fmt/ostr.h similarity index 100% rename from spdlog/fmt/ostr.h rename to common/spdlog/fmt/ostr.h diff --git a/spdlog/fmt/ranges.h b/common/spdlog/fmt/ranges.h similarity index 100% rename from spdlog/fmt/ranges.h rename to common/spdlog/fmt/ranges.h diff --git a/spdlog/fmt/std.h b/common/spdlog/fmt/std.h similarity index 100% rename from spdlog/fmt/std.h rename to common/spdlog/fmt/std.h diff --git a/spdlog/fmt/xchar.h b/common/spdlog/fmt/xchar.h similarity index 100% rename from spdlog/fmt/xchar.h rename to common/spdlog/fmt/xchar.h diff --git a/spdlog/formatter.h b/common/spdlog/formatter.h similarity index 100% rename from spdlog/formatter.h rename to common/spdlog/formatter.h diff --git a/spdlog/fwd.h b/common/spdlog/fwd.h similarity index 100% rename from spdlog/fwd.h rename to common/spdlog/fwd.h diff --git a/spdlog/logger-inl.h b/common/spdlog/logger-inl.h similarity index 100% rename from spdlog/logger-inl.h rename to common/spdlog/logger-inl.h diff --git a/spdlog/logger.h b/common/spdlog/logger.h similarity index 100% rename from spdlog/logger.h rename to common/spdlog/logger.h diff --git a/spdlog/mdc.h b/common/spdlog/mdc.h similarity index 100% rename from spdlog/mdc.h rename to common/spdlog/mdc.h diff --git a/spdlog/pattern_formatter-inl.h b/common/spdlog/pattern_formatter-inl.h similarity index 100% rename from spdlog/pattern_formatter-inl.h rename to common/spdlog/pattern_formatter-inl.h diff --git a/spdlog/pattern_formatter.h b/common/spdlog/pattern_formatter.h similarity index 100% rename from spdlog/pattern_formatter.h rename to common/spdlog/pattern_formatter.h diff --git a/spdlog/sinks/android_sink.h b/common/spdlog/sinks/android_sink.h similarity index 100% rename from spdlog/sinks/android_sink.h rename to common/spdlog/sinks/android_sink.h diff --git a/spdlog/sinks/ansicolor_sink-inl.h b/common/spdlog/sinks/ansicolor_sink-inl.h similarity index 100% rename from spdlog/sinks/ansicolor_sink-inl.h rename to common/spdlog/sinks/ansicolor_sink-inl.h diff --git a/spdlog/sinks/ansicolor_sink.h b/common/spdlog/sinks/ansicolor_sink.h similarity index 100% rename from spdlog/sinks/ansicolor_sink.h rename to common/spdlog/sinks/ansicolor_sink.h diff --git a/spdlog/sinks/base_sink-inl.h b/common/spdlog/sinks/base_sink-inl.h similarity index 100% rename from spdlog/sinks/base_sink-inl.h rename to common/spdlog/sinks/base_sink-inl.h diff --git a/spdlog/sinks/base_sink.h b/common/spdlog/sinks/base_sink.h similarity index 100% rename from spdlog/sinks/base_sink.h rename to common/spdlog/sinks/base_sink.h diff --git a/spdlog/sinks/basic_file_sink-inl.h b/common/spdlog/sinks/basic_file_sink-inl.h similarity index 100% rename from spdlog/sinks/basic_file_sink-inl.h rename to common/spdlog/sinks/basic_file_sink-inl.h diff --git a/spdlog/sinks/basic_file_sink.h b/common/spdlog/sinks/basic_file_sink.h similarity index 100% rename from spdlog/sinks/basic_file_sink.h rename to common/spdlog/sinks/basic_file_sink.h diff --git a/spdlog/sinks/callback_sink.h b/common/spdlog/sinks/callback_sink.h similarity index 100% rename from spdlog/sinks/callback_sink.h rename to common/spdlog/sinks/callback_sink.h diff --git a/spdlog/sinks/daily_file_sink.h b/common/spdlog/sinks/daily_file_sink.h similarity index 100% rename from spdlog/sinks/daily_file_sink.h rename to common/spdlog/sinks/daily_file_sink.h diff --git a/spdlog/sinks/dist_sink.h b/common/spdlog/sinks/dist_sink.h similarity index 100% rename from spdlog/sinks/dist_sink.h rename to common/spdlog/sinks/dist_sink.h diff --git a/spdlog/sinks/dup_filter_sink.h b/common/spdlog/sinks/dup_filter_sink.h similarity index 100% rename from spdlog/sinks/dup_filter_sink.h rename to common/spdlog/sinks/dup_filter_sink.h diff --git a/spdlog/sinks/hourly_file_sink.h b/common/spdlog/sinks/hourly_file_sink.h similarity index 100% rename from spdlog/sinks/hourly_file_sink.h rename to common/spdlog/sinks/hourly_file_sink.h diff --git a/spdlog/sinks/kafka_sink.h b/common/spdlog/sinks/kafka_sink.h similarity index 100% rename from spdlog/sinks/kafka_sink.h rename to common/spdlog/sinks/kafka_sink.h diff --git a/spdlog/sinks/mongo_sink.h b/common/spdlog/sinks/mongo_sink.h similarity index 100% rename from spdlog/sinks/mongo_sink.h rename to common/spdlog/sinks/mongo_sink.h diff --git a/spdlog/sinks/msvc_sink.h b/common/spdlog/sinks/msvc_sink.h similarity index 100% rename from spdlog/sinks/msvc_sink.h rename to common/spdlog/sinks/msvc_sink.h diff --git a/spdlog/sinks/null_sink.h b/common/spdlog/sinks/null_sink.h similarity index 100% rename from spdlog/sinks/null_sink.h rename to common/spdlog/sinks/null_sink.h diff --git a/spdlog/sinks/ostream_sink.h b/common/spdlog/sinks/ostream_sink.h similarity index 100% rename from spdlog/sinks/ostream_sink.h rename to common/spdlog/sinks/ostream_sink.h diff --git a/spdlog/sinks/qt_sinks.h b/common/spdlog/sinks/qt_sinks.h similarity index 100% rename from spdlog/sinks/qt_sinks.h rename to common/spdlog/sinks/qt_sinks.h diff --git a/spdlog/sinks/ringbuffer_sink.h b/common/spdlog/sinks/ringbuffer_sink.h similarity index 100% rename from spdlog/sinks/ringbuffer_sink.h rename to common/spdlog/sinks/ringbuffer_sink.h diff --git a/spdlog/sinks/rotating_file_sink-inl.h b/common/spdlog/sinks/rotating_file_sink-inl.h similarity index 100% rename from spdlog/sinks/rotating_file_sink-inl.h rename to common/spdlog/sinks/rotating_file_sink-inl.h diff --git a/spdlog/sinks/rotating_file_sink.h b/common/spdlog/sinks/rotating_file_sink.h similarity index 100% rename from spdlog/sinks/rotating_file_sink.h rename to common/spdlog/sinks/rotating_file_sink.h diff --git a/spdlog/sinks/sink-inl.h b/common/spdlog/sinks/sink-inl.h similarity index 100% rename from spdlog/sinks/sink-inl.h rename to common/spdlog/sinks/sink-inl.h diff --git a/spdlog/sinks/sink.h b/common/spdlog/sinks/sink.h similarity index 100% rename from spdlog/sinks/sink.h rename to common/spdlog/sinks/sink.h diff --git a/spdlog/sinks/stdout_color_sinks-inl.h b/common/spdlog/sinks/stdout_color_sinks-inl.h similarity index 100% rename from spdlog/sinks/stdout_color_sinks-inl.h rename to common/spdlog/sinks/stdout_color_sinks-inl.h diff --git a/spdlog/sinks/stdout_color_sinks.h b/common/spdlog/sinks/stdout_color_sinks.h similarity index 100% rename from spdlog/sinks/stdout_color_sinks.h rename to common/spdlog/sinks/stdout_color_sinks.h diff --git a/spdlog/sinks/stdout_sinks-inl.h b/common/spdlog/sinks/stdout_sinks-inl.h similarity index 100% rename from spdlog/sinks/stdout_sinks-inl.h rename to common/spdlog/sinks/stdout_sinks-inl.h diff --git a/spdlog/sinks/stdout_sinks.h b/common/spdlog/sinks/stdout_sinks.h similarity index 100% rename from spdlog/sinks/stdout_sinks.h rename to common/spdlog/sinks/stdout_sinks.h diff --git a/spdlog/sinks/syslog_sink.h b/common/spdlog/sinks/syslog_sink.h similarity index 100% rename from spdlog/sinks/syslog_sink.h rename to common/spdlog/sinks/syslog_sink.h diff --git a/spdlog/sinks/systemd_sink.h b/common/spdlog/sinks/systemd_sink.h similarity index 100% rename from spdlog/sinks/systemd_sink.h rename to common/spdlog/sinks/systemd_sink.h diff --git a/spdlog/sinks/tcp_sink.h b/common/spdlog/sinks/tcp_sink.h similarity index 100% rename from spdlog/sinks/tcp_sink.h rename to common/spdlog/sinks/tcp_sink.h diff --git a/spdlog/sinks/udp_sink.h b/common/spdlog/sinks/udp_sink.h similarity index 100% rename from spdlog/sinks/udp_sink.h rename to common/spdlog/sinks/udp_sink.h diff --git a/spdlog/sinks/win_eventlog_sink.h b/common/spdlog/sinks/win_eventlog_sink.h similarity index 100% rename from spdlog/sinks/win_eventlog_sink.h rename to common/spdlog/sinks/win_eventlog_sink.h diff --git a/spdlog/sinks/wincolor_sink-inl.h b/common/spdlog/sinks/wincolor_sink-inl.h similarity index 100% rename from spdlog/sinks/wincolor_sink-inl.h rename to common/spdlog/sinks/wincolor_sink-inl.h diff --git a/spdlog/sinks/wincolor_sink.h b/common/spdlog/sinks/wincolor_sink.h similarity index 100% rename from spdlog/sinks/wincolor_sink.h rename to common/spdlog/sinks/wincolor_sink.h diff --git a/spdlog/spdlog-inl.h b/common/spdlog/spdlog-inl.h similarity index 100% rename from spdlog/spdlog-inl.h rename to common/spdlog/spdlog-inl.h diff --git a/spdlog/spdlog.h b/common/spdlog/spdlog.h similarity index 100% rename from spdlog/spdlog.h rename to common/spdlog/spdlog.h diff --git a/spdlog/stopwatch.h b/common/spdlog/stopwatch.h similarity index 100% rename from spdlog/stopwatch.h rename to common/spdlog/stopwatch.h diff --git a/spdlog/tweakme.h b/common/spdlog/tweakme.h similarity index 100% rename from spdlog/tweakme.h rename to common/spdlog/tweakme.h diff --git a/spdlog/version.h b/common/spdlog/version.h similarity index 100% rename from spdlog/version.h rename to common/spdlog/version.h diff --git a/toml.hpp b/common/toml.hpp similarity index 100% rename from toml.hpp rename to common/toml.hpp diff --git a/config.h b/include/config.h similarity index 92% rename from config.h rename to include/config.h index ea70141..6e1bddf 100644 --- a/config.h +++ b/include/config.h @@ -3,6 +3,8 @@ #include "schema.h" #include "prompt.h" +#include "logger.h" +#include "toml.hpp" #include #include #include @@ -15,7 +17,7 @@ namespace humanus { // Get project root directory static std::filesystem::path get_project_root() { - return std::filesystem::path(__FILE__).parent_path(); + return std::filesystem::path(__FILE__).parent_path().parent_path(); } static const std::filesystem::path PROJECT_ROOT = get_project_root(); @@ -166,7 +168,7 @@ struct MCPToolConfig { std::vector args; json env_vars = json::object(); - static MCPToolConfig load_from_toml(const std::string& tool_name); + static MCPToolConfig load_from_toml(const toml::table& tool_table); }; enum class EmbeddingType { @@ -228,6 +230,7 @@ struct MemoryConfig { struct AppConfig { std::unordered_map llm; + std::unordered_map mcp_tool; std::unordered_map tool_parser; std::unordered_map embedding_model; std::unordered_map vector_store; @@ -242,6 +245,7 @@ private: Config() { _load_initial_llm_config(); + _load_initial_mcp_tool_config(); _load_initial_embedding_model_config(); _load_initial_vector_store_config(); _initialized = true; @@ -250,10 +254,6 @@ private: Config(const Config&) = delete; Config& operator=(const Config&) = delete; - /** - * @brief Get the config path - * @return The config path - */ static std::filesystem::path _get_llm_config_path() { auto root = PROJECT_ROOT; auto config_path = root / "config" / "config_llm.toml"; @@ -263,6 +263,15 @@ private: throw std::runtime_error("LLM Config file not found"); } + static std::filesystem::path _get_mcp_tool_config_path() { + auto root = PROJECT_ROOT; + auto config_path = root / "config" / "config_mcp.toml"; + if (std::filesystem::exists(config_path)) { + return config_path; + } + throw std::runtime_error("MCP Tool Config file not found"); + } + static std::filesystem::path _get_embedding_model_config_path() { auto root = PROJECT_ROOT; auto config_path = root / "config" / "config_embd.toml"; @@ -281,19 +290,12 @@ private: throw std::runtime_error("Vector Store Config file not found"); } - /** - * @brief Load the initial config - */ void _load_initial_llm_config(); - /** - * @brief Load the initial embedding model config - */ + void _load_initial_mcp_tool_config(); + void _load_initial_embedding_model_config(); - /** - * @brief Load the initial vector store config - */ void _load_initial_vector_store_config(); public: @@ -319,6 +321,14 @@ public: return _config.llm; } + /** + * @brief Get the MCP tool settings + * @return The MCP tool settings map + */ + const std::unordered_map& mcp_tool() const { + return _config.mcp_tool; + } + /** * @brief Get the tool helpers * @return The tool helpers map diff --git a/llm.h b/include/llm.h similarity index 100% rename from llm.h rename to include/llm.h diff --git a/logger.h b/include/logger.h similarity index 100% rename from logger.h rename to include/logger.h diff --git a/prompt.h b/include/prompt.h similarity index 100% rename from prompt.h rename to include/prompt.h diff --git a/schema.h b/include/schema.h similarity index 100% rename from schema.h rename to include/schema.h diff --git a/snake/game.py b/snake/game.py deleted file mode 100644 index 65f062c..0000000 --- a/snake/game.py +++ /dev/null @@ -1,103 +0,0 @@ -import pygame -import sys -import random - -# Initialize Pygame -pygame.init() - -# Constants -SCREEN_WIDTH, SCREEN_HEIGHT = 640, 480 -GRID_SIZE = 20 -FPS = 10 - -# Colors -WHITE = (255, 255, 255) -BLACK = (0, 0, 0) -GREEN = (0, 255, 0) -RED = (255, 0, 0) - - -class Game: - def __init__(self): - # Set up the display - self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) - self.clock = pygame.time.Clock() - self.snake = Snake([(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)], (0, -1), 1) - self.food = Food(self.generate_food_position()) - - def generate_food_position(self): - return (random.randint(0, (SCREEN_WIDTH // GRID_SIZE) - 1) * GRID_SIZE, - random.randint(0, (SCREEN_HEIGHT // GRID_SIZE) - 1) * GRID_SIZE) - - def main_loop(self): - while True: - for event in pygame.event.get(): - if event.type == pygame.QUIT: - pygame.quit() - sys.exit() - - # Handle user input and update game state - self.handle_input() - self.update_game_state() - - # Draw everything - self.screen.fill(BLACK) - self.draw_snake() - self.draw_food() - pygame.display.flip() - - # Cap the frame rate - self.clock.tick(FPS) - - def handle_input(self): - keys = pygame.key.get_pressed() - if keys[pygame.K_UP] and self.snake.direction != (0, 1): - self.snake.change_direction((0, -1)) - elif keys[pygame.K_DOWN] and self.snake.direction != (0, -1): - self.snake.change_direction((0, 1)) - elif keys[pygame.K_LEFT] and self.snake.direction != (1, 0): - self.snake.change_direction((-1, 0)) - elif keys[pygame.K_RIGHT] and self.snake.direction != (-1, 0): - self.snake.change_direction((1, 0)) - - def update_game_state(self): - self.snake.move() - if self.snake.position[0] == self.food.position: - self.snake.grow() - self.food.position = self.generate_food_position() - - def draw_snake(self): - for segment in self.snake.position: - pygame.draw.rect(self.screen, GREEN, (segment[0], segment[1], GRID_SIZE, GRID_SIZE)) - - def draw_food(self): - pygame.draw.rect(self.screen, RED, (self.food.position[0], self.food.position[1], GRID_SIZE, GRID_SIZE)) - - -class Snake: - def __init__(self, position, direction, length): - self.position = position - self.direction = direction - self.length = length - - def move(self): - head_x, head_y = self.position[0] - new_dir_x, new_dir_y = self.direction - new_head = (head_x + new_dir_x * GRID_SIZE, head_y + new_dir_y * GRID_SIZE) - self.position.insert(0, new_head) - if len(self.position) > self.length: - self.position.pop() - - def change_direction(self, new_direction): - self.direction = new_direction - - def grow(self): - self.length += 1 - - -class Food: - def __init__(self, position): - self.position = position - - def spawn(self, board_size): - pass # This method is not used in this implementation \ No newline at end of file diff --git a/snake/snake_game.py b/snake/snake_game.py deleted file mode 100644 index e41b5c4..0000000 --- a/snake/snake_game.py +++ /dev/null @@ -1,61 +0,0 @@ -import pygame -import sys -from pygame.locals import * - -class Snake: - def __init__(self, start_position, length=3): - self.body = [start_position] * length - self.direction = (0, 1) # Initially, the snake is moving to the right - - def move(self): - head_x, head_y = self.body[0] - dir_x, dir_y = self.direction - new_head = (head_x + dir_x, head_y + dir_y) - self.body.insert(0, new_head) - self.body.pop() - - def change_direction(self, new_direction): - if (new_direction[0] == -self.direction[0] and new_direction[1] == -self.direction[1]): - return - self.direction = new_direction - - def grow(self): - self.body.append(self.body[-1]) - -# Initialize Pygame -pygame.init() -window_size = (400, 400) -screen = pygame.display.set_mode(window_size) -clock = pygame.time.Clock() - -# Create a snake at position (20, 20) -snake = Snake((20, 20)) - -# Main game loop -while True: - for event in pygame.event.get(): - if event.type == QUIT: - pygame.quit() - sys.exit() - elif event.type == KEYDOWN: - if event.key == K_UP: - snake.change_direction((0, -1)) - elif event.key == K_DOWN: - snake.change_direction((0, 1)) - elif event.key == K_LEFT: - snake.change_direction((-1, 0)) - elif event.key == K_RIGHT: - snake.change_direction((1, 0)) - - # Move the snake - snake.move() - - # Clear screen - screen.fill((0, 0, 0)) - # Draw the snake (for simplicity, we will just print its position) - for part in snake.body: - print(part) # In a real game, you would draw the snake on the screen here - - # Update display - pygame.display.update() - clock.tick(10) # Limit the frame rate to 10 FPS \ No newline at end of file diff --git a/snake/snake_game_architecture.txt b/snake/snake_game_architecture.txt deleted file mode 100644 index bea94e9..0000000 --- a/snake/snake_game_architecture.txt +++ /dev/null @@ -1,34 +0,0 @@ -Snake Game Architecture -====================== - -- Game Class - - Responsibilities: - - Initialize game objects (snake, food, and board) - - Main game loop - - Handle user input for snake direction - - Update the game state (move snake, check for collisions, etc.) - - Keep track of the score - - Display the game on the screen - -- Snake Class - - Attributes: - - Position (list of tuples representing the coordinates of each segment) - - Direction (tuple representing the current direction of movement) - - Length (integer representing the length of the snake) - - Methods: - - Move (update the position of each segment) - - Change direction (based on user input) - - Grow (increase the length of the snake when it eats food) - -- Food Class - - Attributes: - - Position (tuple representing the coordinates of the food) - - Methods: - - Spawn (randomly generate a new position for the food) - -- Board Class (Optional) - - Attributes: - - Size (width and height of the game board) - - Methods: - - Draw (draw the boundaries of the game board) - - Check collision (check if the snake has collided with the walls or itself) \ No newline at end of file diff --git a/config.cpp b/src/config.cpp similarity index 87% rename from config.cpp rename to src/config.cpp index 67ed213..53256de 100644 --- a/config.cpp +++ b/src/config.cpp @@ -1,41 +1,22 @@ #include "config.h" -#include "logger.h" -#include "toml.hpp" -#include -#include namespace humanus { -MCPToolConfig MCPToolConfig::load_from_toml(const std::string& tool_name) { +MCPToolConfig MCPToolConfig::load_from_toml(const toml::table &tool_table) { MCPToolConfig config; try { - // Get config file path - auto config_path = PROJECT_ROOT / "config" / "config_mcp.toml"; - if (!std::filesystem::exists(config_path)) { - throw std::runtime_error("MCP config file not found: " + config_path.string()); - } - - // Parse TOML file - const auto& data = toml::parse_file(config_path.string()); - - // Check if tool config exists - if (!data.contains(tool_name) || !data[tool_name].is_table()) { - throw std::runtime_error("Tool configuration not found in MCP config file: " + tool_name); - } - - const auto& tool_table = *data[tool_name].as_table(); - // Read type if (!tool_table.contains("type") || !tool_table["type"].is_string()) { - throw std::runtime_error("Tool configuration missing type field: " + tool_name); + throw std::runtime_error("Tool configuration missing type field, expected sse or stdio."); } + config.type = tool_table["type"].as_string()->get(); if (config.type == "stdio") { // Read command if (!tool_table.contains("command") || !tool_table["command"].is_string()) { - throw std::runtime_error("stdio type tool configuration missing command field: " + tool_name); + throw std::runtime_error("stdio type tool configuration missing command field."); } config.command = tool_table["command"].as_string()->get(); @@ -70,12 +51,12 @@ MCPToolConfig MCPToolConfig::load_from_toml(const std::string& tool_name) { config.url = tool_table["url"].as_string()->get(); } else { if (!tool_table.contains("host") || !tool_table["host"].is_string()) { - throw std::runtime_error("sse type tool configuration missing host field: " + tool_name); + throw std::runtime_error("sse type tool configuration missing host field"); } config.host = tool_table["host"].as_string()->get(); if (!tool_table.contains("port") || !tool_table["port"].is_integer()) { - throw std::runtime_error("sse type tool configuration missing port field: " + tool_name); + throw std::runtime_error("sse type tool configuration missing port field"); } config.port = tool_table["port"].as_integer()->get(); } @@ -83,7 +64,7 @@ MCPToolConfig MCPToolConfig::load_from_toml(const std::string& tool_name) { throw std::runtime_error("Unsupported tool type: " + config.type); } } catch (const std::exception& e) { - std::cerr << "Failed to load MCP tool configuration: " << e.what() << std::endl; + logger->error("Failed to load MCP tool configuration: " + std::string(e.what())); throw; } @@ -97,7 +78,7 @@ std::mutex Config::_mutex; void Config::_load_initial_llm_config() { try { auto config_path = _get_llm_config_path(); - std::cout << "Loading LLM config file from: " << config_path.string() << std::endl; + logger->info("Loading LLM config file from: " + config_path.string()); const auto& data = toml::parse_file(config_path.string()); @@ -180,17 +161,41 @@ void Config::_load_initial_llm_config() { _config.tool_parser["default"] = ToolParser(); } } catch (const std::exception& e) { - std::cerr << "Loading config file failed: " << e.what() << std::endl; + logger->warn("Failed to load LLM configuration: " + std::string(e.what())); // Set default configuration _config.llm["default"] = LLMConfig(); _config.tool_parser["default"] = ToolParser(); } } +void Config::_load_initial_mcp_tool_config() { + try { + auto config_path = _get_mcp_tool_config_path(); + logger->info("Loading MCP tool config file from: " + config_path.string()); + + const auto& data = toml::parse_file(config_path.string()); + + // Load MCP tool configuration + for (const auto& [key, value] : data) { + const auto& tool_table = *value.as_table(); + + _config.mcp_tool[std::string(key.str())] = MCPToolConfig::load_from_toml(tool_table); + } + + if (_config.mcp_tool.empty()) { + throw std::runtime_error("No MCP tool configuration found"); + } else if (_config.mcp_tool.find("default") == _config.mcp_tool.end()) { + _config.mcp_tool["default"] = _config.mcp_tool.begin()->second; + } + } catch (const std::exception& e) { + logger->warn("Failed to load MCP tool configuration: " + std::string(e.what())); + } +} + void Config::_load_initial_embedding_model_config() { try { auto config_path = _get_embedding_model_config_path(); - std::cout << "Loading embedding model config file from: " << config_path.string() << std::endl; + logger->info("Loading embedding model config file from: " + config_path.string()); const auto& data = toml::parse_file(config_path.string()); @@ -237,7 +242,7 @@ void Config::_load_initial_embedding_model_config() { _config.embedding_model["default"] = _config.embedding_model.begin()->second; } } catch (const std::exception& e) { - std::cerr << "Loading embedding model config file failed: " << e.what() << std::endl; + logger->warn("Failed to load embedding model configuration: " + std::string(e.what())); // Set default configuration _config.embedding_model["default"] = EmbeddingModelConfig(); } @@ -246,7 +251,7 @@ void Config::_load_initial_embedding_model_config() { void Config::_load_initial_vector_store_config() { try { auto config_path = _get_vector_store_config_path(); - std::cout << "Loading vector store config file from: " << config_path.string() << std::endl; + logger->info("Loading vector store config file from: " + config_path.string()); const auto& data = toml::parse_file(config_path.string()); @@ -296,7 +301,7 @@ void Config::_load_initial_vector_store_config() { _config.vector_store["default"] = _config.vector_store.begin()->second; } } catch (const std::exception& e) { - std::cerr << "Loading vector store config file failed: " << e.what() << std::endl; + logger->warn("Failed to load vector store configuration: " + std::string(e.what())); // Set default configuration _config.vector_store["default"] = VectorStoreConfig(); } diff --git a/llm.cpp b/src/llm.cpp similarity index 100% rename from llm.cpp rename to src/llm.cpp diff --git a/logger.cpp b/src/logger.cpp similarity index 100% rename from logger.cpp rename to src/logger.cpp diff --git a/prompt.cpp b/src/prompt.cpp similarity index 80% rename from prompt.cpp rename to src/prompt.cpp index 43ec42e..91644a3 100644 --- a/prompt.cpp +++ b/src/prompt.cpp @@ -25,53 +25,6 @@ Unless required by user, you should always at most use one tool at a time, obser Detect the language of the user input and respond in the same language for thoughts.)"; } // namespace humanus -namespace planning { -const char* PLANNING_SYSTEM_PROMPT = R"(Based on the current state, what's your next step? -Consider: -1. Do you need to create or refine a plan? -2. Are you ready to execute a specific step? -3. Have you completed the task? - -Provide reasoning, then select the appropriate tool or action.)"; - -const char* NEXT_STEP_PROMPT = R"(Based on the current state, what's your next step? -Consider: -1. Do you need to create or refine a plan? -2. Are you ready to execute a specific step? -3. Have you completed the task? - -Provide reasoning, then select the appropriate tool or action.)"; -} // namespace planning - -namespace swe { -const char* SYSTEM_PROMPT = R"(SETTING: You are an autonomous programmer, and you're working directly in the command line with a special interface. - -The special interface consists of a file editor that shows you {WINDOW} lines of a file at a time. -In addition to typical shell commands, you can also use specific commands to help you navigate and edit files. -To call a command, you need to invoke it with a function call/tool call. - -Please note that THE EDIT COMMAND REQUIRES PROPER INDENTATION. -If you'd like to add the line ' print(x)' you must fully write that out, with all those spaces before the code! Indentation is important and code that is not indented correctly will fail and require fixing before it can be run. - -RESPONSE FORMAT: -Your shell prompt is formatted as follows: -(Open file: ) -(Current directory: ) -shell-$ - -First, you should _always_ include a general thought about what you're going to do next. -Then, for every response, you must include exactly _ONE_ tool call/function call. - -Remember, you should always include a _SINGLE_ tool call/function call and then wait for a response from the shell before continuing with more discussion and commands. Everything you include in the DISCUSSION section will be saved for future reference. -If you'd like to issue two commands at once, PLEASE DO NOT DO THAT! Please instead first submit just the first tool call, and then after receiving a response you'll be able to issue the second tool call. -Note that the environment does NOT support interactive session commands (e.g. python, vim), so please do not invoke them.)"; - -const char* NEXT_STEP_TEMPLATE = R"({observation} -(Open file: {open_file}) -(Current directory: {working_dir}) -shell-$)"; -} // namespace swe - namespace toolcall { const char* SYSTEM_PROMPT = "You are an agent that can execute tool calls"; diff --git a/schema.cpp b/src/schema.cpp similarity index 100% rename from schema.cpp rename to src/schema.cpp diff --git a/tool/base.h b/tool/base.h index c4e29d6..d240a59 100644 --- a/tool/base.h +++ b/tool/base.h @@ -108,29 +108,32 @@ struct BaseMCPTool : BaseTool { BaseMCPTool(const std::string& name, const std::string& description, const json& parameters) : BaseTool(name, description, parameters) { + try { + // Load tool configuration from config file + auto _config = Config::get_instance().mcp_tool().at(name); - // Load tool configuration from config file - auto _config = MCPToolConfig::load_from_toml(name); - - if (_config.type == "stdio") { - std::string command = _config.command; - if (!_config.args.empty()) { - for (const auto& arg : _config.args) { - command += " " + arg; + if (_config.type == "stdio") { + std::string command = _config.command; + if (!_config.args.empty()) { + for (const auto& arg : _config.args) { + command += " " + arg; + } + } + _client = std::make_unique(command, _config.env_vars); + } else if (_config.type == "sse") { + if (!_config.host.empty() && _config.port > 0) { + _client = std::make_unique(_config.host, _config.port); + } else if (!_config.url.empty()) { + _client = std::make_unique(_config.url, "/sse"); + } else { + throw std::runtime_error("MCP SSE configuration missing host or port or url"); } } - _client = std::make_unique(command, _config.env_vars); - } else if (_config.type == "sse") { - if (!_config.host.empty() && _config.port > 0) { - _client = std::make_unique(_config.host, _config.port); - } else if (!_config.url.empty()) { - _client = std::make_unique(_config.url, "/sse"); - } else { - throw std::runtime_error("MCP SSE configuration missing host or port or url"); - } - } - _client->initialize(name + "_client", "0.0.1"); + _client->initialize(name + "_client", "0.0.1"); + } catch (const std::exception& e) { + throw std::runtime_error("Failed to initialize MCP tool client for `" + name + "`: " + std::string(e.what())); + } } ToolResult execute(const json& arguments) override { diff --git a/tool/create_chat_completion.cpp b/tool/create_chat_completion.cpp deleted file mode 100644 index a1a36ab..0000000 --- a/tool/create_chat_completion.cpp +++ /dev/null @@ -1,128 +0,0 @@ -#include "create_chat_completion.h" - -namespace humanus { - -json CreateChatCompletion::_build_parameters() const { - if (response_type == "string") { - return { - {"type", "object"}, - {"properties", { - {"response", { - {"type", "string"}, - {"description", "The response text that should be delivered to the user."} - }} - }}, - {"required", required} - }; - } - - // TODO: handle other types - - return _create_type_schema(response_type); -} - -json CreateChatCompletion::_create_type_schema(const std::string& type_hint) const { - // Handle basic types - if (type_mapping.find(type_hint) != type_mapping.end()) { - return { - {"type", "object"}, - {"properties", { - {"response", { - {"type", type_mapping.at(type_hint)}, - {"description", "Response of type " + type_hint} - }} - }}, - {"required", required} - }; - } - - // Handle array types - if (type_hint.find("array") == 0) { - std::string item_type = "string"; // Default item type - return { - {"type", "object"}, - {"properties", { - {"response", { - {"type", "array"}, - {"items", {{"type", type_mapping.at(item_type)}}} - }} - }}, - {"required", required} - }; - } - - // Handle dictionary type - if (type_hint.find("object") == 0) { - return { - {"type", "object"}, - {"properties", { - {"response", { - {"type", "object"}, - {"additionalProperties", {{"type", "string"}}} - }} - }}, - {"required", required} - }; - } - - // Default return string type - return { - {"type", "object"}, - {"properties", { - {"response", { - {"type", "string"}, - {"description", "The response text that should be delivered to the user."} - }} - }}, - {"required", required} - }; -} - -json CreateChatCompletion::_get_type_info(const std::string& type_hint) const { - return { - {"type", type_mapping.count(type_hint) ? type_mapping.at(type_hint) : "string"}, - {"description", "Value of type " + type_hint} - }; -} - -json CreateChatCompletion::_create_union_schema(const std::vector& types) const { - json type_infos = json::array(); - for (const auto& t : types) { - type_infos.push_back(_get_type_info(t)); - } - - return { - {"type", "object"}, - {"properties", { - {"response", {{"anyOf", type_infos}}} - }}, - {"required", required} - }; -} - -// Execute the chat completion with type conversion. -ToolResult CreateChatCompletion::execute(const json& args) { - std::vector req_fields = args.contains("required") ? args["required"].get>() : required; - - // Handle case when required is a list - if (!req_fields.empty()) { - if (req_fields.size() == 1) { - std::string required_field = req_fields[0]; - return ToolResult(args.contains(required_field) ? args.at(required_field) : ""); - } else { - // Return multiple fields as an object - json result = json::object(); - for (const auto& field : req_fields) { - result[field] = args.contains(field) ? args.at(field) : ""; - } - return ToolResult(result); - } - } else { - std::string required_field = "response"; - return ToolResult(args.contains(required_field) ? args.at(required_field) : ""); - } - - // TODO: handle other types (Only string and array are supported for now) -} - -} // namespace humanuse \ No newline at end of file diff --git a/tool/create_chat_completion.h b/tool/create_chat_completion.h deleted file mode 100644 index 4808091..0000000 --- a/tool/create_chat_completion.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef HUMANUS_TOOL_CREATE_CHAT_COMPLETION_H -#define HUMANUS_TOOL_CREATE_CHAT_COMPLETION_H - -#include "base.h" -#include -#include -#include -#include -#include - -namespace humanus { - -struct CreateChatCompletion : BaseTool { - inline static const std::string name_ = "create_chat_completion"; - inline static const std::string description_ = "Creates a structured completion with specified output formatting."; - - // Type mapping table, used for JSON schema - inline static std::unordered_map type_mapping = { - {"string", "string"}, - {"int", "integer"}, - {"float", "number"}, - {"double", "number"}, - {"bool", "boolean"}, - {"object", "object"}, - {"array", "array"} - }; - - std::string response_type; - std::vector required; - - CreateChatCompletion(const std::string& response_type = "string", const std::vector& required = {"response"}) : BaseTool(name_, description_, json::object()), response_type(response_type), required(required) { - parameters = _build_parameters(); - } - - json _build_parameters() const; - - json _create_type_schema(const std::string& type_hint) const; - - json _get_type_info(const std::string& type_hint) const; - - json _create_union_schema(const std::vector& types) const; - - ToolResult execute(const json& args) override; -}; - -} - -#endif // HUMANUS_TOOL_CREATE_CHAT_COMPLETION_H diff --git a/tool/shell.h b/tool/shell.h deleted file mode 100644 index 792d9b7..0000000 --- a/tool/shell.h +++ /dev/null @@ -1,128 +0,0 @@ -#ifndef HUMANUS_TOOL_BASH_H -#define HUMANUS_TOOL_BASH_H - -#include "base.h" -#include "mcp_stdio_client.h" -#include "toml.hpp" -#include "config.h" -#include - -namespace humanus { - -// A tool for executing shell commands using MCP shell server -// https://github.com/kevinwatt/shell-mcp.git -struct Shell : BaseMCPTool { - inline static const std::string name_ = "shell"; - inline static const std::string description_ = "Execute a shell command in the terminal."; - inline static const json parameters_ = json::parse(R"json({ - "type": "object", - "properties": { - "command": { - "type": "string", - "description": "Command to execute. Available commands:\n- ls: List directory contents\n- cat: Concatenate and display file contents\n- pwd: Show current working directory\n- df: Show disk usage\n- echo: Display text\n- ps: Show process status\n- free: Show memory usage\n- uptime: Show system uptime\n- date: Show system date and time\n- grep: Search text patterns in files\n- w: Show who is logged on and what they are doing\n- whois: Query WHOIS domain registration information\n- find: Search for files in a directory hierarchy\n- netstat: Network connection information\n- lspci: List PCI devices\n- lsusb: List USB devices\n- dig: DNS lookup utility\n- nslookup: Query DNS records\n- ip: Show / manipulate routing, network devices, interfaces and tunnels\n- whereis: Locate the binary, source, and manual page files for a command", - "enum": [ - "ls", - "cat", - "pwd", - "df", - "echo", - "ps", - "free", - "uptime", - "date", - "grep", - "w", - "whois", - "find", - "netstat", - "lspci", - "lsusb", - "dig", - "nslookup", - "ip", - "whereis" - ] - }, - "args": { - "type": "array", - "description": "Additional arguments to pass to the command" - }, - "timeout": { - "type": "number", - "description": "Execution timeout in ms" - } - }, - "required": ["command"] - })json"); - - inline static std::set allowed_commands = { - "ls", - "cat", - "pwd", - "df", - // "echo", // Not working now - "ps", - "free", - "uptime", - "date", - "grep", - "w", - "whois", - "find", - "netstat", - "lspci", - "lsusb", - "dig", - "nslookup", - "ip", - "whereis" - }; - - Shell() : BaseMCPTool(name_, description_, parameters_) {} - - ToolResult execute(const json& args) override { - try { - // Ensure client is initialized - if (!_client) { - return ToolError("Failed to initialize shell client"); - } - - std::string command; - if (args.contains("command")) { - if (args["command"].is_string()) { - command = args["command"].get(); - } else { - return ToolError("Invalid command format"); - } - } else { - return ToolError("'command' is required"); - } - - if (allowed_commands.find(command) == allowed_commands.end()) { - return ToolError("Unknown command '" + command + "'. Please use one of the following commands: " + - std::accumulate(allowed_commands.begin(), allowed_commands.end(), std::string(), - [](const std::string& a, const std::string& b) { - return a + (a.empty() ? "" : ", ") + b; - })); - } - - // Call shell tool - json result = _client->call_tool("shell_" + command, args); - - bool is_error = result.value("isError", false); - - // Return different ToolResult based on whether there is an error - if (is_error) { - return ToolError(result.value("content", json::array())); - } else { - return ToolResult(result.value("content", json::array())); - } - } catch (const std::exception& e) { - return ToolError("Error executing shell command: " + std::string(e.what())); - } - } -}; - -} - -#endif // HUMANUS_TOOL_BASH_H