feat(redstone): wiki_recipe_image — composite real recipe PNG and upload
Previous wiki_recipe only returned the page thumbnail, so "send me the
recipe image" delivered a picture of the item, not the recipe itself.
minecraft.wiki renders recipes as live HTML grids, not standalone PNGs,
so we now generate the image ourselves.
mcp/lib/minecraft-wiki-tools.ts:
- parseCraftingGrid(html): pulls the 3×3 input grid + result item URL
from <span class="mcui mcui-Crafting_Table">. Each <span class="invslot">
is either empty (chunk starts with </span>) or has an <img src="/images/
Invicon_X.png?h">. Reading-order chunks → grid; first non-null after
the 9th input slot → result.
- composeRecipePng(grid, result): fetches each unique sprite, resizes
to 64×64 via sharp (nearest-neighbour to keep pixel art crisp),
composites onto a #8b8b8b inventory-style background with #6f6f6f
slot squares + dark borders, places an SVG-rendered "→" arrow,
then the result cell next to it. PNG buffer returned.
- New tool wiki_recipe_image(title, chat, caption?) that runs the
pipeline end-to-end and uploads via tg.sendPhotoBytes — one tool
call, image already in the chat when it returns.
mcp/lib/types.ts:
- TgClient gains sendPhotoBytes({ chat_id, bytes, filename?, caption?,
parse_mode?, reply_to_message_id? }). Multipart/form-data POST to
sendPhoto, since Telegram's URL-mode can only fetch public URLs and
the composited PNG only lives in memory. 30s timeout (vs the 20s on
the JSON call) because uploads are bigger.
mcp/package.json + bot/package.json: add sharp ^0.33.5. mcp/ pulls it
in too so /mc/mcp/lib resolves it at the bot's runtime (the bot's
node_modules is at /app while the lib files live at /mc/mcp/lib).
Persona prompt: wiki_recipe_image is now the FIRST call for any
"recipe" / "send me the recipe image" request. Single tool turn ends
with the photo already in the chat. wiki_recipe stays as a fallback
when the page has no 3×3 crafting widget (smelting / brewing / smithing
use different mcui classes).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1210,10 +1210,11 @@ function redstonePersona(user: User, chatType: string, chatId: number, srv: stri
|
||||
"- Minecraft server: check status (server_status), start/stop/restart services (server_up/down/restart), tail logs (server_logs), look up players in the bot's database (players_list/player_get).",
|
||||
"- Admin-only tools (the caller's role is shown in the context block): run RCON commands (rcon), trigger a world backup (backup), and modify player records (player_upsert/set_*/remove, seen_list). If a non-admin asks for one, politely refuse and don't call it.",
|
||||
"- Minecraft wiki: look things up on minecraft.wiki and surface images into the chat.",
|
||||
"- For 'how do I craft X?' / 'recipe for X' questions: call wiki_recipe(title=…) directly (use wiki_search first only if you're unsure of the exact page title). wiki_recipe returns the ingredient list (e.g. 'Block of Iron + Iron Ingot') AND the page's main item thumbnail URL. Then call tg_send_photo with that thumbnail_url and a caption like 'Anvil — Block of Iron ×3 + Iron Ingot' — visual + the recipe in one go. Minecraft Wiki does NOT host standalone recipe images (recipes are rendered live as HTML grids), so don't waste a turn calling wiki_page_images looking for one.",
|
||||
"- For 'recipe for X' / 'how do I craft X' / 'send me the recipe image': call wiki_recipe_image(title=…, chat=<chatId>) — ONE call that composites a real 3×3 grid PNG from the wiki's slot sprites and uploads it straight to the chat. Returns {sent:true,message_id} when it's already in the chat — you do NOT need a separate tg_send_photo turn afterwards. Only add a short text reply if you want to caption the recipe with extra context.",
|
||||
"- If wiki_recipe_image fails (e.g. 'no 3×3 crafting recipe' — the item is smelted, brewed, or only obtained from loot), use wiki_recipe to fetch the ingredient text, then tg_send_photo with the page's thumbnail_url as a fallback so SOMETHING visual lands.",
|
||||
"- For 'what is X?' / general lookup: wiki_page for the intro extract + thumbnail. Then a short text reply, optionally + tg_send_photo of the thumbnail.",
|
||||
"- For specific images that aren't the page's main thumbnail (block variants, GUI screenshots, charts): wiki_page_images with an optional filename filter.",
|
||||
"- IMAGE DELIVERY IS MANDATORY when the user asks for a picture / image / recipe / what something looks like. You MUST end the turn by calling tg_send_photo with a real URL — never describe the image in words and stop. If wiki_recipe / wiki_page returns no thumbnail at all, say so plainly instead of inventing one.",
|
||||
"- For specific non-thumbnail images (block variants, GUI screenshots, charts): wiki_page_images with an optional filename filter.",
|
||||
"- IMAGE DELIVERY IS MANDATORY when the user asks for a picture / image / recipe / what something looks like. End the turn with a tool call that actually puts a photo into the chat (wiki_recipe_image OR tg_send_photo). Never describe an image in words and stop.",
|
||||
"- When you use a tool, you usually don't need a separate text reply unless you're adding context — the tool's effect IS the response. After a server_status / players_list lookup, summarize the answer in one sentence.",
|
||||
"",
|
||||
"Stickers — drop emojis inline and the bot does the rest:",
|
||||
|
||||
Reference in New Issue
Block a user