136 lines
4.7 KiB
C++
136 lines
4.7 KiB
C++
#ifndef HUMANUS_TOOL_BASH_H
|
|
#define HUMANUS_TOOL_BASH_H
|
|
|
|
#include "base.h"
|
|
#include "../mcp/include/mcp_stdio_client.h"
|
|
#include "../toml.hpp"
|
|
#include "../config.h"
|
|
#include <filesystem>
|
|
|
|
namespace humanus {
|
|
|
|
// A tool for executing shell commands using MCP shell server
|
|
struct Shell : BaseTool {
|
|
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");
|
|
|
|
std::unique_ptr<mcp::stdio_client> _client;
|
|
bool _initialized = false;
|
|
MCPToolConfig _config;
|
|
|
|
std::string last_request_id_;
|
|
|
|
Shell() : BaseTool(name_, description_, parameters_) {
|
|
|
|
}
|
|
|
|
~Shell() {
|
|
// 确保客户端正确关闭
|
|
if (_client && _client->is_running()) {
|
|
try {
|
|
if (!last_request_id_.empty()) {
|
|
_client->send_notification("notifications/cancelled", {
|
|
{"requestId", last_request_id_},
|
|
{"reason", "Client shutdown"}
|
|
});
|
|
}
|
|
} catch (...) {
|
|
// 忽略关闭时的错误
|
|
}
|
|
}
|
|
}
|
|
|
|
// 初始化客户端连接
|
|
bool initialize() {
|
|
if (_initialized) return true;
|
|
|
|
bool success = _client->initialize("humanus", "1.0.0");
|
|
if (success) {
|
|
_initialized = true;
|
|
}
|
|
return success;
|
|
}
|
|
|
|
ToolResult execute(const json& args) override {
|
|
try {
|
|
// 确保客户端已初始化
|
|
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<std::string>();
|
|
} else {
|
|
return ToolError("Invalid command format");
|
|
}
|
|
} else {
|
|
return ToolError("Command is required");
|
|
}
|
|
|
|
json tool_args = args;
|
|
tool_args.erase("command");
|
|
|
|
// 调用shell工具
|
|
json result = _client->call_tool("shell_" + command, tool_args);
|
|
|
|
bool is_error = result.value("isError", false);
|
|
|
|
// 根据是否有错误返回不同的ToolResult
|
|
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
|