remove unused codes; refactor project structure

main
hkr04 2025-03-29 00:04:23 +08:00
parent 4c7a790811
commit eb77c83236
129 changed files with 94 additions and 1033 deletions

View File

@ -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)

View File

@ -9,7 +9,6 @@
#include "tool/terminate.h"
#include "tool/puppeteer.h"
#include "tool/filesystem.h"
#include "tool/shell.h"
namespace humanus {

View File

@ -1,248 +0,0 @@
#include "planning.h"
#include <iomanip>
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<PlanningTool>());
}
}
// 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<std::string> lines;
std::istringstream iss(s);
std::string line;
while (std::getline(iss, line)) {
lines.push_back(line);
}
return lines;
};
try {
std::vector<std::string> 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<Message> 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

View File

@ -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<std::string, json> step_execution_tracker;
int current_step_index;
PlanningAgent(
const ToolCollection& available_tools = ToolCollection(
{
std::make_shared<PlanningTool>(),
std::make_shared<Terminate>()
}
),
const std::string& tool_choice = "auto",
const std::set<std::string>& 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>& llm = nullptr,
const std::shared_ptr<BaseMemory>& 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

View File

@ -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<Shell>(),
std::make_shared<Filesystem>(),
std::make_shared<Terminate>()
}
),
const std::string& tool_choice = "auto",
const std::set<std::string>& 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>& llm = nullptr,
const std::shared_ptr<BaseMemory>& 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

View File

@ -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<CreateChatCompletion>(),
std::make_shared<Terminate>()
}
),

Some files were not shown because too many files have changed in this diff Show More