{"ok":true,"site":{"host":"glyphdance.vercel.app","url":"https://glyphdance.vercel.app/","type":"live","desc":"glyphdance is an agentically powered ASCII art animation studio.","tools":[{"name":"paint_cells","kind":"act","impl":"imperative","description":"Paint cells on one frame (brush/eraser/fill/line). Batch ALL cells for one frame into a single call. Coordinates are 0-based with y=0 at the top row; out-of-bounds cells are rejected. Paint in color — vary fg across elements, never a whole piece in one fg.","inputSchema":{"type":"object","properties":{"frame":{"type":"number","description":"0-based frame index; the UI calls frame N+1 \"frame 1\", and the document context below lists every frame with its index"},"cells":{"type":"array","items":{"type":"object","properties":{"x":{"type":"number","description":"0-based column"},"y":{"type":"number","description":"0-based row, y=0 is the top row"},"ch":{"type":"string","description":"exactly one character; \" \" erases"},"fg":{"type":"string","description":"foreground hex color, e.g. \"#4ade80\""},"bg":{"type":"string","description":"background hex color, or \"\" for transparent"}},"required":["x","y","ch","fg"]},"description":"cells to paint on that frame"}},"required":["frame","cells"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"recolor_cells","kind":"act","impl":"imperative","description":"Change ONLY the colors of existing cells on one frame, keeping their characters (the Paint tool). Use this to recolor art that is already drawn.","inputSchema":{"type":"object","properties":{"frame":{"type":"number","description":"0-based frame index; the UI calls frame N+1 \"frame 1\", and the document context below lists every frame with its index"},"cells":{"type":"array","items":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"},"fg":{"type":"string"},"bg":{"type":"string"}},"required":["x","y","fg","bg"]}}},"required":["frame","cells"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"add_frame","kind":"act","impl":"imperative","description":"Insert a blank frame after the given 0-based frame index.","inputSchema":{"type":"object","properties":{"after":{"type":"number","description":"0-based frame index; the UI calls frame N+1 \"frame 1\", and the document context below lists every frame with its index"}},"required":["after"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"duplicate_frame","kind":"act","impl":"imperative","description":"Duplicate a frame, inserting the copy right after it.","inputSchema":{"type":"object","properties":{"index":{"type":"number","description":"0-based frame index; the UI calls frame N+1 \"frame 1\", and the document context below lists every frame with its index"}},"required":["index"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"delete_frame","kind":"transact","impl":"imperative","description":"Delete a frame. The document must keep at least one frame, so deleting the last remaining frame is rejected.","annotations":{"destructiveHint":true},"inputSchema":{"type":"object","properties":{"index":{"type":"number","description":"0-based frame index; the UI calls frame N+1 \"frame 1\", and the document context below lists every frame with its index"}},"required":["index"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"clear_frame","kind":"act","impl":"imperative","description":"Erase every cell in a frame (keeps its holdMs). To hand the user a blank slate, clear every frame instead of deleting them.","annotations":{"destructiveHint":true},"inputSchema":{"type":"object","properties":{"frame":{"type":"number","description":"0-based frame index; the UI calls frame N+1 \"frame 1\", and the document context below lists every frame with its index"}},"required":["frame"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"move_frame","kind":"act","impl":"imperative","description":"Move a frame from one 0-based position to another.","inputSchema":{"type":"object","properties":{"from":{"type":"number","description":"0-based frame index; the UI calls frame N+1 \"frame 1\", and the document context below lists every frame with its index"},"to":{"type":"number","description":"0-based frame index; the UI calls frame N+1 \"frame 1\", and the document context below lists every frame with its index"}},"required":["from","to"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_hold","kind":"act","impl":"imperative","description":"Set how long a frame displays during playback, in milliseconds.","inputSchema":{"type":"object","properties":{"index":{"type":"number","description":"0-based frame index; the UI calls frame N+1 \"frame 1\", and the document context below lists every frame with its index"},"holdMs":{"type":"number","description":"display time in milliseconds"}},"required":["index","holdMs"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_theme","kind":"act","impl":"imperative","description":"Switch the document theme (canvas background + stamp colors). Only use when the user asks for a different mood or palette.","inputSchema":{"type":"object","properties":{"themeId":{"type":"string","description":"one of: dracula, monokai, nord, solarized, tokyo, onedark"}},"required":["themeId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"rename_document","kind":"act","impl":"imperative","description":"Rename the document.","inputSchema":{"type":"object","properties":{"name":{"type":"string"}},"required":["name"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"resize_canvas","kind":"act","impl":"imperative","description":"Resize the canvas (width 4-64, height 4-48). Existing art is re-centered on the new canvas; art that does not fit is cropped.","inputSchema":{"type":"object","properties":{"width":{"type":"number"},"height":{"type":"number"}},"required":["width","height"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_active_frame","kind":"act","impl":"imperative","description":"Select which frame is active in the timeline (does not change any art).","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"index":{"type":"number","description":"0-based frame index; the UI calls frame N+1 \"frame 1\", and the document context below lists every frame with its index"}},"required":["index"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"add_stamp","kind":"act","impl":"imperative","description":"Create a reusable stamp the user keeps in their Stamps panel. id: lowercase letters/digits/dashes, 1-20 chars, unique across built-in and user stamps. frames: the stamp art — each frame is an array of equal-length row strings, spaces are transparent. Any size, any frame count. Search the catalog (below) before creating: if a built-in stamp fits, place it instead.","inputSchema":{"type":"object","properties":{"id":{"type":"string"},"fg":{"type":"string","description":"default foreground hex color for the stamp"},"frames":{"type":"array","items":{"type":"array","items":{"type":"string"},"description":"one animation frame: rows of characters"},"description":"animation frames of the stamp"}},"required":["id","fg","frames"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"delete_stamp","kind":"transact","impl":"imperative","description":"Remove a user-created stamp by id. Built-in stamps cannot be deleted.","annotations":{"destructiveHint":true},"inputSchema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"place_stamp","kind":"act","impl":"imperative","description":"Paint a stamp (built-in or user-created) CENTERED on x,y on one frame — this is how you USE stamps, never hand-draw a stamp's cells. Art that extends past the grid edge is clipped to the grid, so placements near the edge partially apply. stampFrame picks which of the stamp's art frames to use (default 0). Coordinates are 0-based with y=0 at the top row.","inputSchema":{"type":"object","properties":{"stampId":{"type":"string","description":"built-in id or user stamp id"},"frame":{"type":"number","description":"0-based frame index; the UI calls frame N+1 \"frame 1\", and the document context below lists every frame with its index"},"x":{"type":"number","description":"center column, 0-based"},"y":{"type":"number","description":"center row, 0-based, y=0 is top"},"fg":{"type":"string","description":"foreground hex color for the placed art"},"bg":{"type":"string","description":"background hex color, or \"\" for transparent"},"stampFrame":{"type":"number","description":"which art frame of the stamp to use (default 0)"}},"required":["stampId","frame","x","y","fg","bg"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"undo","kind":"act","impl":"imperative","description":"Undo the last change to the document — the same undo stack as the toolbar Undo button and keyboard shortcut. Reports \"nothing to undo\" when the stack is empty.","inputSchema":{"type":"object","properties":{}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"redo","kind":"act","impl":"imperative","description":"Redo the last undone change — the same redo stack as the toolbar Redo button and keyboard shortcut. Reports \"nothing to redo\" when the stack is empty.","inputSchema":{"type":"object","properties":{}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_font","kind":"act","impl":"imperative","description":"Set the canvas pixel font — the same font picker as the Document panel. fontId is one of: \"cozette\" (default, widest glyph coverage), \"vga\" (authentic IBM VGA 8x16), \"jetbrains\" (JetBrains Mono), \"system\" (system monospace).","inputSchema":{"type":"object","properties":{"fontId":{"type":"string","description":"one of cozette, vga, jetbrains, system"}},"required":["fontId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"play","kind":"act","impl":"imperative","description":"Start playing the animation — the same state as the timeline play button. Reports \"already playing\" when playback is already running.","inputSchema":{"type":"object","properties":{}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"pause","kind":"act","impl":"imperative","description":"Pause the animation — the same state as the timeline pause button. Pausing leaves the playhead on the current frame so you can inspect or edit it. Reports \"already paused\" when playback is already stopped.","inputSchema":{"type":"object","properties":{}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"describe_document","kind":"answer","impl":"imperative","description":"Read the current document: canvas size, frame count, active frame, theme, canvas font, user stamps, and every frame rendered as text with a column ruler, row numbers, and a color legend. Call this first to see what you are editing. Frame indices in actions are 0-based; the UI shows them 1-based.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"}],"category":"Media & Personal","favicon":"/favicons/glyphdance.vercel.app.svg","apiSurface":"spec","toolCount":21}}