148 lines
4.6 KiB
C++
148 lines
4.6 KiB
C++
#include "agent/humanus.h"
|
|
#include "logger.h"
|
|
#include "prompt.h"
|
|
#include "flow/flow_factory.h"
|
|
#include "memory/mem0/base.h"
|
|
|
|
#if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
|
|
#include <signal.h>
|
|
#include <unistd.h>
|
|
#elif defined (_WIN32)
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#ifndef NOMINMAX
|
|
#define NOMINMAX
|
|
#endif
|
|
#include <windows.h>
|
|
#include <signal.h>
|
|
#endif
|
|
|
|
using namespace humanus;
|
|
|
|
#if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__)) || defined (_WIN32)
|
|
static void sigint_handler(int signo) {
|
|
if (signo == SIGINT) {
|
|
logger->info("Interrupted by user\n");
|
|
exit(0);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static bool readline_utf8(std::string & line, bool multiline_input) {
|
|
#if defined(_WIN32)
|
|
std::wstring wline;
|
|
if (!std::getline(std::wcin, wline)) {
|
|
// Input stream is bad or EOF received
|
|
line.clear();
|
|
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
|
|
return false;
|
|
}
|
|
|
|
int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wline[0], (int)wline.size(), NULL, 0, NULL, NULL);
|
|
line.resize(size_needed);
|
|
WideCharToMultiByte(CP_UTF8, 0, &wline[0], (int)wline.size(), &line[0], size_needed, NULL, NULL);
|
|
#else
|
|
if (!std::getline(std::cin, line)) {
|
|
// Input stream is bad or EOF received
|
|
line.clear();
|
|
return false;
|
|
}
|
|
#endif
|
|
if (!line.empty()) {
|
|
char last = line.back();
|
|
if (last == '/') { // Always return control on '/' symbol
|
|
line.pop_back();
|
|
return false;
|
|
}
|
|
if (last == '\\') { // '\\' changes the default action
|
|
line.pop_back();
|
|
multiline_input = !multiline_input;
|
|
}
|
|
}
|
|
line += '\n';
|
|
|
|
// By default, continue input if multiline_input is set
|
|
return multiline_input;
|
|
}
|
|
|
|
int main() {
|
|
|
|
// ctrl+C handling
|
|
{
|
|
#if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
|
|
struct sigaction sigint_action;
|
|
sigint_action.sa_handler = sigint_handler;
|
|
sigemptyset (&sigint_action.sa_mask);
|
|
sigint_action.sa_flags = 0;
|
|
sigaction(SIGINT, &sigint_action, NULL);
|
|
#elif defined (_WIN32)
|
|
auto console_ctrl_handler = +[](DWORD ctrl_type) -> BOOL {
|
|
return (ctrl_type == CTRL_C_EVENT) ? (sigint_handler(SIGINT), true) : false;
|
|
};
|
|
SetConsoleCtrlHandler(reinterpret_cast<PHANDLER_ROUTINE>(console_ctrl_handler), true);
|
|
SetConsoleCP(CP_UTF8);
|
|
SetConsoleOutputCP(CP_UTF8);
|
|
_setmode(_fileno(stdin), _O_WTEXT); // wide character input mode
|
|
#endif
|
|
}
|
|
|
|
auto memory = std::make_shared<mem0::Memory>(mem0::MemoryConfig());
|
|
|
|
std::shared_ptr<BaseAgent> agent_ptr = std::make_shared<Humanus>(
|
|
ToolCollection( // Add general-purpose tools to the tool collection
|
|
{
|
|
std::make_shared<PythonExecute>(),
|
|
std::make_shared<Puppeteer>(), // for web browsing
|
|
std::make_shared<Filesystem>(),
|
|
std::make_shared<Terminate>()
|
|
}
|
|
),
|
|
"auto",
|
|
std::set<std::string>{"terminate"},
|
|
"humanus_mem0",
|
|
"A versatile agent that can solve various tasks using multiple tools",
|
|
prompt::humanus::SYSTEM_PROMPT,
|
|
prompt::humanus::NEXT_STEP_PROMPT,
|
|
nullptr,
|
|
memory
|
|
);
|
|
|
|
std::map<std::string, std::shared_ptr<BaseAgent>> agents;
|
|
agents["default"] = agent_ptr;
|
|
|
|
auto flow = FlowFactory::create_flow(
|
|
FlowType::PLANNING,
|
|
nullptr, // llm
|
|
nullptr, // planning_tool
|
|
std::vector<std::string>{}, // executor_keys
|
|
"", // active_plan_id
|
|
agents, // agents
|
|
std::vector<std::shared_ptr<BaseTool>>{}, // tools
|
|
"default" // primary_agent_key
|
|
);
|
|
|
|
while (true) {
|
|
if (agent_ptr->current_step == agent_ptr->max_steps) {
|
|
std::cout << "Automatically paused after " << agent_ptr->current_step << " steps." << std::endl;
|
|
std::cout << "Enter your prompt (enter an empty line to resume or 'exit' to quit): ";
|
|
agent_ptr->reset(false);
|
|
} else {
|
|
std::cout << "Enter your prompt (or 'exit' to quit): ";
|
|
}
|
|
|
|
if (agent_ptr->state != AgentState::IDLE) {
|
|
break;
|
|
}
|
|
|
|
std::string prompt;
|
|
readline_utf8(prompt, false);
|
|
if (prompt == "exit" || prompt == "exit\n") {
|
|
logger->info("Goodbye!");
|
|
break;
|
|
}
|
|
|
|
std::cout << "Processing your request..." << std::endl;
|
|
memory->current_request = prompt;
|
|
auto result = flow->execute(prompt);
|
|
std::cout << result << std::endl;
|
|
}
|
|
} |