90 const std::string& prompt) {
92 const std::string normalized = absl::AsciiStrToLower(prompt);
94 if (normalized.empty()) {
96 "Let's start with a prompt about the overworld or dungeons.";
100 if (absl::StrContains(normalized,
"place") &&
101 absl::StrContains(normalized,
"tree")) {
103 "Sure, I can do that. Here's the command to place a tree.";
104 response.
commands.push_back(
"overworld set-tile --map 0 --x 10 --y 20 --tile 0x02E");
106 "The user asked to place a tree tile16, so I generated the matching set-tile command.";
110 if (absl::StrContains(normalized,
"list") &&
111 absl::StrContains(normalized,
"resource")) {
112 std::string resource_type =
"dungeon";
113 if (absl::StrContains(normalized,
"overworld")) {
114 resource_type =
"overworld";
115 }
else if (absl::StrContains(normalized,
"sprite")) {
116 resource_type =
"sprite";
117 }
else if (absl::StrContains(normalized,
"palette")) {
118 resource_type =
"palette";
123 call.
args.emplace(
"type", resource_type);
125 absl::StrFormat(
"Fetching %s labels from the ROM...", resource_type);
127 "Using the resource-list tool keeps the LLM in sync with project labels.";
132 if (absl::StrContains(normalized,
"search") &&
133 (absl::StrContains(normalized,
"resource") ||
134 absl::StrContains(normalized,
"label"))) {
137 call.
args.emplace(
"query", ExtractKeyword(normalized));
139 "Let me look through the labelled resources for matches.";
141 "Resource search provides fuzzy matching against the ROM label catalogue.";
146 if (absl::StrContains(normalized,
"sprite") &&
147 absl::StrContains(normalized,
"room")) {
150 call.
args.emplace(
"room", ExtractRoomId(normalized));
152 "Let me inspect the dungeon room sprites for you.";
154 "Calling the sprite inspection tool provides precise coordinates for the agent.";
159 if (absl::StrContains(normalized,
"describe") &&
160 absl::StrContains(normalized,
"room")) {
162 call.
tool_name =
"dungeon-describe-room";
163 call.
args.emplace(
"room", ExtractRoomId(normalized));
165 "I'll summarize the room's metadata and hazards.";
167 "Room description tool surfaces lighting, effects, and object counts before planning edits.";
173 "I'm just a mock service. Please load a provider like ollama or gemini.";
178 const std::vector<agent::ChatMessage>& history) {
179 if (history.empty()) {
180 return absl::InvalidArgumentError(
"History cannot be empty.");
184 for (
auto it = history.rbegin(); it != history.rend(); ++it) {
186 (absl::StrContains(it->message,
"=== ") ||
187 absl::StrContains(it->message,
"\"id\"") ||
188 absl::StrContains(it->message,
"\n{"))) {
191 "Here's what I found:\n" + it->message +
192 "\nLet me know if you'd like to make a change.";
194 "Summarized the latest tool output for the user.";
199 auto user_it = std::find_if(history.rbegin(), history.rend(),
201 return message.sender ==
202 agent::ChatMessage::Sender::kUser;
204 if (user_it == history.rend()) {
205 return absl::InvalidArgumentError(
206 "History does not contain a user message.");