Update z3ed CLI tool and project build configuration
- Updated `.clang-tidy` and `.clangd` configurations for improved code quality checks and diagnostics. - Added new submodules for JSON and HTTP libraries to support future features. - Refined README and documentation files to standardize naming conventions and improve clarity. - Introduced a new command palette in the CLI for easier command access and execution. - Implemented various CLI handlers for managing ROM, sprites, palettes, and dungeon functionalities. - Enhanced the TUI components for better user interaction and command execution. - Added AI service integration for generating commands based on user prompts, expanding the CLI's capabilities.
This commit is contained in:
23
src/cli/service/ai_service.cc
Normal file
23
src/cli/service/ai_service.cc
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "cli/service/ai_service.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace cli {
|
||||
|
||||
absl::StatusOr<std::vector<std::string>> MockAIService::GetCommands(
|
||||
const std::string& prompt) {
|
||||
if (prompt == "Make all the soldiers in Hyrule Castle wear red armor.") {
|
||||
return std::vector<std::string>{
|
||||
"palette export --group sprites_aux1 --id 4 --to soldier_palette.col",
|
||||
"palette set-color --file soldier_palette.col --index 5 --color \"#FF0000\"",
|
||||
"palette import --group sprites_aux1 --id 4 --from soldier_palette.col"};
|
||||
} else if (prompt.find("Place a tree at coordinates") != std::string::npos) {
|
||||
// Example prompt: "Place a tree at coordinates (10, 20) on the light world map"
|
||||
// For simplicity, we'll hardcode the tile id for a tree
|
||||
return std::vector<std::string>{"overworld set-tile --map 0 --x 10 --y 20 --tile 0x02E"};
|
||||
}
|
||||
return absl::UnimplementedError("Prompt not supported by mock AI service.");
|
||||
}
|
||||
|
||||
} // namespace cli
|
||||
} // namespace yaze
|
||||
|
||||
28
src/cli/service/ai_service.h
Normal file
28
src/cli/service/ai_service.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef YAZE_SRC_CLI_AI_SERVICE_H_
|
||||
#define YAZE_SRC_CLI_AI_SERVICE_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/status/statusor.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace cli {
|
||||
|
||||
class AIService {
|
||||
public:
|
||||
virtual ~AIService() = default;
|
||||
virtual absl::StatusOr<std::vector<std::string>> GetCommands(
|
||||
const std::string& prompt) = 0;
|
||||
};
|
||||
|
||||
class MockAIService : public AIService {
|
||||
public:
|
||||
absl::StatusOr<std::vector<std::string>> GetCommands(
|
||||
const std::string& prompt) override;
|
||||
};
|
||||
|
||||
} // namespace cli
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_SRC_CLI_AI_SERVICE_H_
|
||||
87
src/cli/service/gemini_ai_service.cc
Normal file
87
src/cli/service/gemini_ai_service.cc
Normal file
@@ -0,0 +1,87 @@
|
||||
#include "cli/service/gemini_ai_service.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "absl/strings/str_cat.h"
|
||||
|
||||
#ifdef YAZE_WITH_JSON
|
||||
#include "incl/httplib.h"
|
||||
#include "third_party/json/src/json.hpp"
|
||||
#endif
|
||||
|
||||
namespace yaze {
|
||||
namespace cli {
|
||||
|
||||
GeminiAIService::GeminiAIService(const std::string& api_key) : api_key_(api_key) {}
|
||||
|
||||
absl::StatusOr<std::vector<std::string>> GeminiAIService::GetCommands(
|
||||
const std::string& prompt) {
|
||||
#ifndef YAZE_WITH_JSON
|
||||
return absl::UnimplementedError(
|
||||
"Gemini AI service requires JSON support. Build with -DYAZE_WITH_JSON=ON");
|
||||
#else
|
||||
if (api_key_.empty()) {
|
||||
return absl::FailedPreconditionError("GEMINI_API_KEY not set.");
|
||||
}
|
||||
|
||||
httplib::Client cli("https://generativelanguage.googleapis.com");
|
||||
nlohmann::json request_body = {
|
||||
{"contents",
|
||||
{{"parts",
|
||||
{{"text",
|
||||
"You are an expert ROM hacker for The Legend of Zelda: A Link to the Past. "
|
||||
"Your task is to generate a sequence of `z3ed` CLI commands to achieve the user's request. "
|
||||
"Respond only with a JSON array of strings, where each string is a `z3ed` command. "
|
||||
"Do not include any other text or explanation. "
|
||||
"Available commands: "
|
||||
"palette export --group <group> --id <id> --to <file>, "
|
||||
"palette import --group <group> --id <id> --from <file>, "
|
||||
"palette set-color --file <file> --index <index> --color <hex_color>, "
|
||||
"overworld set-tile --map <map_id> --x <x> --y <y> --tile <tile_id>. "
|
||||
"User request: " + prompt}}}}}
|
||||
};
|
||||
|
||||
httplib::Headers headers = {
|
||||
{"Content-Type", "application/json"},
|
||||
{"x-goog-api-key", api_key_},
|
||||
};
|
||||
|
||||
auto res = cli.Post("/v1beta/models/gemini-pro:generateContent", headers, request_body.dump(), "application/json");
|
||||
|
||||
if (!res) {
|
||||
return absl::InternalError("Failed to connect to Gemini API.");
|
||||
}
|
||||
|
||||
if (res->status != 200) {
|
||||
return absl::InternalError(absl::StrCat("Gemini API error: ", res->status, " ", res->body));
|
||||
}
|
||||
|
||||
nlohmann::json response_json = nlohmann::json::parse(res->body);
|
||||
std::vector<std::string> commands;
|
||||
|
||||
try {
|
||||
for (const auto& candidate : response_json["candidates"]) {
|
||||
for (const auto& part : candidate["content"]["parts"]) {
|
||||
std::string text_content = part["text"];
|
||||
// Assuming the AI returns a JSON array of strings directly in the text content
|
||||
// This might need more robust parsing depending on actual AI output format
|
||||
nlohmann::json commands_array = nlohmann::json::parse(text_content);
|
||||
if (commands_array.is_array()) {
|
||||
for (const auto& cmd : commands_array) {
|
||||
if (cmd.is_string()) {
|
||||
commands.push_back(cmd.get<std::string>());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const nlohmann::json::exception& e) {
|
||||
return absl::InternalError(absl::StrCat("Failed to parse Gemini API response: ", e.what()));
|
||||
}
|
||||
|
||||
return commands;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace cli
|
||||
} // namespace yaze
|
||||
27
src/cli/service/gemini_ai_service.h
Normal file
27
src/cli/service/gemini_ai_service.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef YAZE_SRC_CLI_GEMINI_AI_SERVICE_H_
|
||||
#define YAZE_SRC_CLI_GEMINI_AI_SERVICE_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "cli/service/ai_service.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace cli {
|
||||
|
||||
class GeminiAIService : public AIService {
|
||||
public:
|
||||
explicit GeminiAIService(const std::string& api_key);
|
||||
absl::StatusOr<std::vector<std::string>> GetCommands(
|
||||
const std::string& prompt) override;
|
||||
|
||||
private:
|
||||
std::string api_key_;
|
||||
};
|
||||
|
||||
} // namespace cli
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_SRC_CLI_GEMINI_AI_SERVICE_H_
|
||||
Reference in New Issue
Block a user