yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
tool_dispatcher.cc
Go to the documentation of this file.
2
3#include <algorithm>
4#include <memory>
5#include <regex>
6#include <sstream>
7#include <string>
8
9#include "absl/strings/str_cat.h"
16#ifdef YAZE_WITH_GRPC
18#endif
23
24namespace yaze {
25namespace cli {
26namespace agent {
27
28namespace {
29
30// Map tool name to handler type
31ToolCallType GetToolCallType(const std::string& tool_name) {
32 // Resource commands
33 if (tool_name == "resource-list") return ToolCallType::kResourceList;
34 if (tool_name == "resource-search") return ToolCallType::kResourceSearch;
35
36 // Dungeon commands
37 if (tool_name == "dungeon-list-sprites") return ToolCallType::kDungeonListSprites;
38 if (tool_name == "dungeon-describe-room") return ToolCallType::kDungeonDescribeRoom;
39 if (tool_name == "dungeon-export-room") return ToolCallType::kDungeonExportRoom;
40 if (tool_name == "dungeon-list-objects") return ToolCallType::kDungeonListObjects;
41 if (tool_name == "dungeon-get-room-tiles") return ToolCallType::kDungeonGetRoomTiles;
42 if (tool_name == "dungeon-set-room-property") return ToolCallType::kDungeonSetRoomProperty;
43
44 // Overworld commands
45 if (tool_name == "overworld-find-tile") return ToolCallType::kOverworldFindTile;
46 if (tool_name == "overworld-describe-map") return ToolCallType::kOverworldDescribeMap;
47 if (tool_name == "overworld-list-warps") return ToolCallType::kOverworldListWarps;
48 if (tool_name == "overworld-list-sprites") return ToolCallType::kOverworldListSprites;
49 if (tool_name == "overworld-get-entrance") return ToolCallType::kOverworldGetEntrance;
50 if (tool_name == "overworld-tile-stats") return ToolCallType::kOverworldTileStats;
51
52 // Message & Dialogue commands
53 if (tool_name == "message-list") return ToolCallType::kMessageList;
54 if (tool_name == "message-read") return ToolCallType::kMessageRead;
55 if (tool_name == "message-search") return ToolCallType::kMessageSearch;
56 if (tool_name == "dialogue-list") return ToolCallType::kDialogueList;
57 if (tool_name == "dialogue-read") return ToolCallType::kDialogueRead;
58 if (tool_name == "dialogue-search") return ToolCallType::kDialogueSearch;
59
60 // GUI Automation commands
61 if (tool_name == "gui-place-tile") return ToolCallType::kGuiPlaceTile;
62 if (tool_name == "gui-click") return ToolCallType::kGuiClick;
63 if (tool_name == "gui-discover-tool") return ToolCallType::kGuiDiscover;
64 if (tool_name == "gui-screenshot") return ToolCallType::kGuiScreenshot;
65
66 // Music commands
67 if (tool_name == "music-list") return ToolCallType::kMusicList;
68 if (tool_name == "music-info") return ToolCallType::kMusicInfo;
69 if (tool_name == "music-tracks") return ToolCallType::kMusicTracks;
70
71 // Sprite commands
72 if (tool_name == "sprite-list") return ToolCallType::kSpriteList;
73 if (tool_name == "sprite-properties") return ToolCallType::kSpriteProperties;
74 if (tool_name == "sprite-palette") return ToolCallType::kSpritePalette;
75
76 // Emulator & Debugger commands
77 if (tool_name == "emulator-step") return ToolCallType::kEmulatorStep;
78 if (tool_name == "emulator-run") return ToolCallType::kEmulatorRun;
79 if (tool_name == "emulator-pause") return ToolCallType::kEmulatorPause;
80 if (tool_name == "emulator-reset") return ToolCallType::kEmulatorReset;
81 if (tool_name == "emulator-get-state") return ToolCallType::kEmulatorGetState;
82 if (tool_name == "emulator-set-breakpoint") return ToolCallType::kEmulatorSetBreakpoint;
83 if (tool_name == "emulator-clear-breakpoint") return ToolCallType::kEmulatorClearBreakpoint;
84 if (tool_name == "emulator-list-breakpoints") return ToolCallType::kEmulatorListBreakpoints;
85 if (tool_name == "emulator-read-memory") return ToolCallType::kEmulatorReadMemory;
86 if (tool_name == "emulator-write-memory") return ToolCallType::kEmulatorWriteMemory;
87 if (tool_name == "emulator-get-registers") return ToolCallType::kEmulatorGetRegisters;
88 if (tool_name == "emulator-get-metrics") return ToolCallType::kEmulatorGetMetrics;
89
91}
92
93// Create the appropriate command handler for a tool call type
94std::unique_ptr<resources::CommandHandler> CreateHandler(ToolCallType type) {
95 using namespace yaze::cli::handlers;
96
97 switch (type) {
98 // Resource commands
100 return std::make_unique<ResourceListCommandHandler>();
102 return std::make_unique<ResourceSearchCommandHandler>();
103
104 // Dungeon commands
106 return std::make_unique<DungeonListSpritesCommandHandler>();
108 return std::make_unique<DungeonDescribeRoomCommandHandler>();
110 return std::make_unique<DungeonExportRoomCommandHandler>();
112 return std::make_unique<DungeonListObjectsCommandHandler>();
114 return std::make_unique<DungeonGetRoomTilesCommandHandler>();
116 return std::make_unique<DungeonSetRoomPropertyCommandHandler>();
117
118 // Overworld commands
120 return std::make_unique<OverworldFindTileCommandHandler>();
122 return std::make_unique<OverworldDescribeMapCommandHandler>();
124 return std::make_unique<OverworldListWarpsCommandHandler>();
126 return std::make_unique<OverworldListSpritesCommandHandler>();
128 return std::make_unique<OverworldGetEntranceCommandHandler>();
130 return std::make_unique<OverworldTileStatsCommandHandler>();
131
132 // Message & Dialogue commands
134 return std::make_unique<MessageListCommandHandler>();
136 return std::make_unique<MessageReadCommandHandler>();
138 return std::make_unique<MessageSearchCommandHandler>();
140 return std::make_unique<DialogueListCommandHandler>();
142 return std::make_unique<DialogueReadCommandHandler>();
144 return std::make_unique<DialogueSearchCommandHandler>();
145
146 // GUI Automation commands
148 return std::make_unique<GuiPlaceTileCommandHandler>();
150 return std::make_unique<GuiClickCommandHandler>();
152 return std::make_unique<GuiDiscoverToolCommandHandler>();
154 return std::make_unique<GuiScreenshotCommandHandler>();
155
156 // Music commands
158 return std::make_unique<MusicListCommandHandler>();
160 return std::make_unique<MusicInfoCommandHandler>();
162 return std::make_unique<MusicTracksCommandHandler>();
163
164 // Sprite commands
166 return std::make_unique<SpriteListCommandHandler>();
168 return std::make_unique<SpritePropertiesCommandHandler>();
170 return std::make_unique<SpritePaletteCommandHandler>();
171
172 // Emulator & Debugger commands
173#ifdef YAZE_WITH_GRPC
175 return std::make_unique<EmulatorStepCommandHandler>();
177 return std::make_unique<EmulatorRunCommandHandler>();
179 return std::make_unique<EmulatorPauseCommandHandler>();
181 return std::make_unique<EmulatorResetCommandHandler>();
183 return std::make_unique<EmulatorGetStateCommandHandler>();
185 return std::make_unique<EmulatorSetBreakpointCommandHandler>();
187 return std::make_unique<EmulatorClearBreakpointCommandHandler>();
189 return std::make_unique<EmulatorListBreakpointsCommandHandler>();
191 return std::make_unique<EmulatorReadMemoryCommandHandler>();
193 return std::make_unique<EmulatorWriteMemoryCommandHandler>();
195 return std::make_unique<EmulatorGetRegistersCommandHandler>();
197 return std::make_unique<EmulatorGetMetricsCommandHandler>();
198#endif
199
200 default:
201 return nullptr;
202 }
203}
204
205// Convert tool call arguments map to command-line style vector
206std::vector<std::string> ConvertArgsToVector(
207 const std::map<std::string, std::string>& args) {
208 std::vector<std::string> result;
209
210 for (const auto& [key, value] : args) {
211 // Convert to --key=value format
212 result.push_back(absl::StrCat("--", key, "=", value));
213 }
214
215 // Always request JSON format for tool calls (easier for AI to parse)
216 bool has_format = false;
217 for (const auto& arg : result) {
218 if (arg.find("--format=") == 0) {
219 has_format = true;
220 break;
221 }
222 }
223 if (!has_format) {
224 result.push_back("--format=json");
225 }
226
227 return result;
228}
229
230} // namespace
231
232absl::StatusOr<std::string> ToolDispatcher::Dispatch(const ToolCall& call) {
233 // Determine tool call type
234 ToolCallType type = GetToolCallType(call.tool_name);
235
236 if (type == ToolCallType::kUnknown) {
237 return absl::InvalidArgumentError(
238 absl::StrCat("Unknown tool: ", call.tool_name));
239 }
240
241 // Create the appropriate command handler
242 auto handler = CreateHandler(type);
243 if (!handler) {
244 return absl::InternalError(
245 absl::StrCat("Failed to create handler for tool: ", call.tool_name));
246 }
247
248 // Convert arguments to command-line style
249 std::vector<std::string> args = ConvertArgsToVector(call.args);
250
251 // Check if ROM context is required but not available
252 if (!rom_context_) {
253 return absl::FailedPreconditionError(
254 absl::StrCat("Tool '", call.tool_name,
255 "' requires ROM context but none is available"));
256 }
257
258 // Execute the command handler
259 // The handler will internally use OutputFormatter to capture output
260 // We need to capture stdout to get the formatted output
261
262 // Redirect stdout to capture the output
263 std::stringstream output_buffer;
264 std::streambuf* old_cout = std::cout.rdbuf(output_buffer.rdbuf());
265
266 // Execute the handler
267 absl::Status status = handler->Run(args, rom_context_);
268
269 // Restore stdout
270 std::cout.rdbuf(old_cout);
271
272 if (!status.ok()) {
273 return status;
274 }
275
276 // Return the captured output
277 std::string output = output_buffer.str();
278 if (output.empty()) {
279 return absl::InternalError(
280 absl::StrCat("Tool '", call.tool_name, "' produced no output"));
281 }
282
283 return output;
284}
285
286} // namespace agent
287} // namespace cli
288} // namespace yaze
absl::StatusOr< std::string > Dispatch(const ToolCall &tool_call)
std::unique_ptr< resources::CommandHandler > CreateHandler(ToolCallType type)
ToolCallType GetToolCallType(const std::string &tool_name)
std::vector< std::string > ConvertArgsToVector(const std::map< std::string, std::string > &args)
Main namespace for the application.
std::map< std::string, std::string > args
Definition common.h:14
std::string tool_name
Definition common.h:13