import { BOUNDS, LIMITS, MATERIALS } from './world-rules.ts' /** * The self-contained prompt a person pastes into their agent so "build me a * castle" just works in their room. Works for MCP-only agents (Kody's * `execute` tool) and for agents with the Kody CLI. */ export function agentPrompt(input: { roomUrl: string; roomCode: string; roomName: string; userName: string }) { const first = input.userName.split(/\s+/)[0] || input.userName const materials = MATERIALS.map((m) => m.key).join(', ') return `You're joining a live, shared 3D voxel world in Kody World Builder: the room "${input.roomName}". Room link: ${input.roomUrl} Room code: ${input.roomCode} Everyone in the room watches your blocks appear live as you place them. HOW TO CALL IT Run the code below through Kody. If you're connected to Kody over MCP, pass it to Kody's \`execute\` tool. No local code or shell is needed. If you have a terminal, \`npx -y @kodycodes/cli@latest execute --file build.mjs\` also works. Package: @kentcdodds/world-builder. Import each function from 'kody:@kentcdodds/world-builder/'. Always pass room: '${input.roomCode}'. For agentName, use your own assistant name: "Claude", "ChatGPT", "Grok", etc. The room shows you as "${first}'s ". STEPS 1. Look before you build: import describeWorld from 'kody:@kentcdodds/world-builder/describe-world' const info = await describeWorld({ room: '${input.roomCode}' }) This returns occupiedBounds, a heightMap of 8x8 cells (-1 = empty), and recentBuilds. Pick an empty spot. You can pass region: { minX, maxX, minY, maxY, minZ, maxZ } to get the exact blocks in an area. 2. Start a build: import startBuild from 'kody:@kentcdodds/world-builder/start-build' const { buildId } = await startBuild({ room: '${input.roomCode}', agentName: '', prompt: '' }) 3. Place blocks, in order from the ground up: import placeBlocks from 'kody:@kentcdodds/world-builder/place-blocks' await placeBlocks({ buildId, blocks: [{ x, y, z, material }, ...] }) Each call takes up to ${LIMITS.maxAgentBlocksPerCall} blocks, and the server streams them in batches of 24 so people watch the build grow. One execute run stops after about 90 seconds, and 600 blocks take about 5 to 10 seconds to stream. For builds over about 1,200 blocks, split the work across several execute runs: run startBuild once, keep the buildId, then do one or two placeBlocks calls per run. To remove blocks, use remove-blocks with { buildId, blocks: [{ x, y, z }] }. 4. Finish: import finishBuild from 'kody:@kentcdodds/world-builder/finish-build' await finishBuild({ buildId }) // or { buildId, status: 'failed' } if you give up WORLD RULES - The y axis points up, and the ground is y = 0. x runs ${BOUNDS.minX}..${BOUNDS.maxX}, z runs ${BOUNDS.minZ}..${BOUNDS.maxZ}, and y runs ${BOUNDS.minY}..${BOUNDS.maxY}. Every coordinate must be an integer. - Materials: ${materials}. - Blocks that are out of bounds or use an unknown material are skipped, and the reply counts them in "rejected". - Limits: ${LIMITS.maxAgentBlocksPerCall} blocks per call, about ${LIMITS.agentBlocksPerMinute} blocks per minute per agent, and ${LIMITS.maxBlocksPerWorld.toLocaleString('en-US')} blocks per room. If a call fails with a rate limit, wait about a minute and continue from where you stopped. - Placing a block where one already exists replaces it. Don't build over other people's work unless you're asked to. TIPS - Plan the full structure as a list of blocks in code (loops for walls, floors and towers), then place it in chunks. - A good castle is about 20x20 blocks and 900 to 1,200 blocks in total. Use a stone wall ring with crenellations, four taller towers, a gate, wood details, and a few glass windows. - When you're done, tell me what you built and where (its x/z center). Reply "Ready" and wait for my build request.` }