{"ok":true,"site":{"host":"lumenapeiron.com","url":"https://lumenapeiron.com/","type":"live","desc":"Create, explore, and animate IFS fractal flames in real time with Lumen Apeiron — a free, GPU-accelerated fractal flame editor that runs entirely in your browser with WebGPU.","tools":[{"name":"get_flame","kind":"answer","impl":"imperative","description":"Get a compact summary of the active flame fractal. Returns transform count, variation types and weights per transform, render settings (exposure, gamma, vibrancy, contrast, draw mode, dimensions), and color info. Use this to understand the current state before making changes.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_flame_detail","kind":"answer","impl":"imperative","description":"Get detailed data for a specific part of the flame. Specify section: \"transform\" (with transformId or index), \"render\" for all render settings, or \"full\" for the complete descriptor. Use for precise inspection before targeted edits. Note that the returned camera is the base un-animated camera; Timeline animations are applied dynamically during render and do not appear here.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"section":{"type":"string","enum":["transform","render","full"],"description":"Section of the flame to retrieve: \"transform\", \"render\", or \"full\"."},"transformId":{"type":"string","description":"Transform ID string (e.g. \"_benchmark_31415_0\"). Required when section is \"transform\" unless index is provided."},"index":{"type":"integer","description":"0-based positional index (0, 1, 2...). Can be used instead of transformId when section is \"transform\"."}},"required":["section"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"list_commands","kind":"answer","impl":"imperative","description":"List available commands that can be executed via execute_command. Supports pagination via limit and offset, and filtering by prefix (e.g. \"flame.\", \"timeline.\"). Returns command IDs, labels, descriptions, and a prefixes category index. Use to discover what actions are available.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"prefix":{"type":"string","description":"Filter commands by ID prefix, e.g. 'flame.' or 'timeline.'"},"limit":{"type":"integer","description":"Maximum number of commands to return (default: 30, max: 200)."},"offset":{"type":"integer","description":"Number of commands to skip for pagination (default: 0)."}}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"list_variations","kind":"answer","impl":"imperative","description":"List the variation type names this build registers, for flame.addTransform, flame.addVariation and flame.setVariation. Names end in \"Var\" for 2D flames (\"sphericalVar\", not \"spherical\"); the 3D registry uses its own names (\"spiral3D\"). Defaults to the family the current flame renders in. Pass search to filter, parametricOnly for the ones that take params (their parameter names come back with them), and starters:true for a short list to teach from. Read-only: it costs no step.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"search":{"type":"string","description":"Case-insensitive substring, e.g. \"julia\" or \"blur\""},"dimensions":{"type":"integer","enum":[2,3],"description":"Which registry to list (default: the current flame's)"},"parametricOnly":{"type":"boolean","description":"Only variations that take parameters, listed with their parameter names"},"starters":{"type":"boolean","description":"A short cross-section of the classic families, enough to teach from"},"limit":{"type":"integer","description":"Names per page, 1-200 (default 80)"},"offset":{"type":"integer","description":"Skip this many names"}}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_undo_state","kind":"answer","impl":"imperative","description":"Check what undo and redo would do. Returns the target type (flame or timeline) for both undo and redo, or null if the stack is empty. Use before undo/redo to confirm the action.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"arcade_status","kind":"answer","impl":"imperative","description":"Read the Arcade session state: phase (idle, driving, ended), mode, topic, steps used and remaining, elapsed time, whether the editor is locked, whether a recording is active, the last narration, and — during a duel — the time left on the clock. Call it when unsure what to do next.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"arcade_get_animatable_paths","kind":"answer","impl":"imperative","description":"List every parameter path the timeline can keyframe for the current flame (render settings, palette, camera, per-transform affine coefficients, probability, colour, variation weights, final transform) with current values and limits. A path with no \"type\" is a number; transformPaths gives the per-transform grammar; easing and interpolation names are the enums on arcade_set_keyframes.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"diff_flames","kind":"act","impl":"imperative","description":"Compare the current flame against a target flame descriptor. Returns overall similarity (0-100%), render settings differences, matched transform pairs with per-aspect similarity scores, and unmatched transforms. Use for iterative refinement toward a goal.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"target":{"type":"object","description":"The target FlameDescriptor to compare against"}},"required":["target"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"create_share_link","kind":"act","impl":"imperative","description":"Generate a self-contained shareable URL for the current flame. The link encodes the full flame state into the URL query string, generates no server-side state, and never expires. Returns the full longUrl and the encoded base64 payload string.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"score_flame","kind":"act","impl":"imperative","description":"Evaluates a flame mathematically to generate RPG/Arena-style stats (Power Level, Complexity, Chaos, Symmetry, Energy). If no flame is provided, evaluates the current workspace flame.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"flame":{"type":"object","description":"Optional. The flame descriptor to score. Omit to score the current workspace flame."}}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"score_clash_round","kind":"act","impl":"imperative","description":"Deterministically score a round of flame clash based on offscreen iteration density in the shared coordinate volume. Attribution is determined by transform key prefixes (p1_ and p2_). Returns ownership shares for both fighters, contested share, and the round verdict.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"clashFlame":{"type":"object","description":"The merged clash FlameDescriptor from create_clash_flame."},"sampleBudget":{"type":"integer","description":"Simulation sample budget (iterations). Default is 25000."},"seed":{"type":"integer","description":"Deterministic random seed. Default is 4242."}},"required":["clashFlame"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"simulate_clash","kind":"act","impl":"imperative","description":"Simulate a multi-round territory clash between two flames. Returns round outcomes, ownership metrics, narrative events, and the progressive staged clash flame descriptors.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"flameA":{"type":"object","description":"First fighter flame descriptor (Player 1)."},"flameB":{"type":"object","description":"Second fighter flame descriptor (Player 2)."},"rounds":{"type":"integer","description":"Number of battle rounds. Default is 3."},"seed":{"type":"integer","description":"Deterministic random seed. Default is 31415."},"separation":{"type":"number","description":"Distance from origin in 3D. Default is 2.2."},"dimensions":{"type":"integer","enum":[2,3],"description":"Staging dimension: 2 for 2D, 3 for 3D. Default is 3."},"tintA":{"type":"number","description":"Palette hue for Player 1. Default is 0.15."},"tintB":{"type":"number","description":"Palette hue for Player 2. Default is 0.65."},"stanceA":{"type":"string","enum":["balanced","resonance","bastion","entropy"],"description":"Tactical battle stance for Player 1. Default is balanced."},"stanceB":{"type":"string","enum":["balanced","resonance","bastion","entropy"],"description":"Tactical battle stance for Player 2. Default is balanced."}},"required":["flameA","flameB"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_flame","kind":"act","impl":"imperative","description":"Load a complete flame descriptor, replacing the current flame. The descriptor is validated through the schema before loading. Use get_flame first to understand the expected structure, then modify and set it back.","inputSchema":{"type":"object","properties":{"flame":{"type":"object","description":"Complete FlameDescriptor object to load"},"label":{"type":"string","description":"Optional undo history label for this load"}},"required":["flame"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"randomize_flame","kind":"act","impl":"imperative","description":"Generate a new random flame, replacing the current one. Provide a seed for reproducible results. Optionally configure transform count and variation count ranges. The result is deterministic per seed.","inputSchema":{"type":"object","properties":{"seed":{"type":"integer","description":"Random seed (0 to 4294967295). Same seed produces the same flame."},"minTransforms":{"type":"integer","minimum":1,"maximum":10,"description":"Minimum transforms. Default 2."},"maxTransforms":{"type":"integer","minimum":1,"maximum":10,"description":"Maximum transforms. Default 4."},"minVariations":{"type":"integer","minimum":1,"maximum":10,"description":"Minimum variations per transform. Default 1."},"maxVariations":{"type":"integer","minimum":1,"maximum":10,"description":"Maximum variations per transform. Default 2."},"strength":{"type":"number","minimum":0,"maximum":1,"description":"Generation strength 0-1. Default 0.5."}}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"mutate_flame","kind":"act","impl":"imperative","description":"Mutate the current flame with controlled randomness. Choose a preset (Subtle, Moderate, Chaotic, Structural) or fine-tune individual rates. Deterministic per seed and input flame. Use for iterative refinement.","inputSchema":{"type":"object","properties":{"seed":{"type":"integer","description":"Random seed for reproducible mutations"},"preset":{"type":"string","enum":["Subtle","Moderate","Chaotic","Structural"],"description":"Mutation intensity preset. Default Moderate."},"mutateAffine":{"type":"boolean","description":"Mutate affine transforms. Default true."},"mutateColors":{"type":"boolean","description":"Mutate colors. Default true."},"mutateVariations":{"type":"string","enum":["modify","all","none"],"description":"Variation mutation mode. Default modify."}}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"execute_command","kind":"act","impl":"imperative","description":"Execute any registered command by ID. Use list_commands to discover available commands. Arguments are passed as an array. Commands are validated before execution for safety. This is an escape hatch for advanced use.","inputSchema":{"type":"object","properties":{"commandId":{"type":"string","description":"The command ID to execute, e.g. 'flame.setExposure'"},"args":{"type":"array","items":{},"description":"Arguments array for the command"}},"required":["commandId"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"arcade_start_lesson","kind":"act","impl":"imperative","description":"Start a Teach session: locks the editor, starts recording, and returns the lesson brief (goal, allowed commands with their argument shapes, step budget). Topics: variations, affine, color, camera, genetics, sonification, render. Then use arcade_narrate and execute_command, and finish with arcade_end_lesson.","inputSchema":{"type":"object","properties":{"topic":{"type":"string","enum":["variations","affine","color","camera","genetics","sonification","render"],"description":"Lesson topic"},"startFrom":{"type":"string","enum":["blank","current"],"description":"Start from a blank canvas or the current flame (default depends on the topic)"}},"required":["topic"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"arcade_narrate","kind":"act","impl":"imperative","description":"Say one SHORT sentence to the viewer about the step you are about to take. It is burned into the replay as a caption over the flame, so keep it under 25 words — a longer one is held on screen longer but is harder to read while the picture is changing. Two ideas means two calls. Counts as one step of the budget. Only valid while an Arcade session is active.","inputSchema":{"type":"object","properties":{"text":{"type":"string","description":"One sentence, at most 400 characters. Aim for under 25 words: it is shown as a caption over the flame, not as prose on a page."}},"required":["text"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"arcade_end_lesson","kind":"act","impl":"imperative","description":"Finish the Teach session: stops recording, saves the lesson to the user's library, unlocks the editor and shows the replay card. Provide a short title and a one-sentence summary.","inputSchema":{"type":"object","properties":{"title":{"type":"string","description":"At most 80 characters"},"summary":{"type":"string","description":"At most 400 characters"}}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"arcade_start_cinema","kind":"act","impl":"imperative","description":"Start a Cinema session on the current flame: locks the editor, starts recording and opens the timeline. Then call arcade_get_animatable_paths, then arcade_set_keyframes (which plays the result), and finish with arcade_end_cinema.","inputSchema":{"type":"object","properties":{}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"arcade_set_keyframes","kind":"act","impl":"imperative","description":"Apply animation tracks (validated against arcade_get_animatable_paths) and play them once. mode \"add\" keeps the tracks already placed, \"replace\" (default) discards them. Prefer one call per idea: each is a recorded step the viewer watches land. fps 1-60, durationFrames 2-1800, track { path, keyframes: [{ frame, value, easing?, interp? }] }. Needs an active Cinema session.","inputSchema":{"type":"object","properties":{"fps":{"type":"integer","description":"Frames per second, 1-60 (default 30)"},"durationFrames":{"type":"integer","description":"Total frames, 2-1800"},"loopMode":{"type":"string","enum":["off","seamless","cycle"]},"mode":{"type":"string","enum":["replace","add"],"description":"add = merge with the tracks already placed (same path wins from this call); replace = start over (default)"},"play":{"type":"boolean","description":"Start playback after applying (default true)"},"tracks":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"keyframes":{"type":"array","items":{"type":"object","properties":{"frame":{"type":"integer"},"value":{"description":"number, string, or [r,g,b] / [r,g,b,a] for colour paths"},"easing":{"type":"string","enum":["linear","easeIn","easeOut","easeInOut","bounce","elastic"]},"interp":{"type":"string","enum":["linear","constant","spline"]}},"required":["frame","value"]}}},"required":["path","keyframes"]}}},"required":["durationFrames","tracks"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"arcade_end_cinema","kind":"act","impl":"imperative","description":"Finish the Cinema session: stops recording, saves the animation session to the user's library, unlocks the editor and shows the replay card. Provide a short title.","inputSchema":{"type":"object","properties":{"title":{"type":"string","description":"At most 80 characters"},"summary":{"type":"string","description":"At most 400 characters"}}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"arcade_start_duel","kind":"act","impl":"imperative","description":"Start a Duel: you and the viewer edit your own flames side by side against one clock. Opens the split screen, gives you your own flame, and records both sides. Then read yours with get_flame and change it with execute_command (flame.* and camera.* only), narrate with arcade_narrate, and call arcade_duel_ready when you are happy. You cannot end the duel; the clock does.","inputSchema":{"type":"object","properties":{"durationSeconds":{"type":"integer","description":"Clock for both sides, 60-600 (default 180)"},"rivalFrom":{"type":"string","enum":["mirror","blank"],"description":"mirror (default) starts you from a copy of the viewer's flame; blank starts you from an empty canvas"},"startFrom":{"type":"string","enum":["current","random-2d","random-3d"],"description":"What the viewer's side starts as. current (default) is the flame they have open; random-2d and random-3d replace it with a generated one, which is how a 3D duel is asked for. Use whichever the viewer named in the prompt."}}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"arcade_duel_ready","kind":"act","impl":"imperative","description":"Declare your flame finished and give it a title. This does NOT end the duel — the clock does that, and the viewer can end it early. You may keep polishing afterwards and call this again to change the title. Costs no steps.","inputSchema":{"type":"object","properties":{"title":{"type":"string","description":"At most 80 characters"},"summary":{"type":"string","description":"At most 400 characters"}}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"arcade_end_duel","kind":"act","impl":"imperative","description":"Deprecated: you cannot end a duel. The clock ends it, and the viewer can end it early. Call arcade_duel_ready instead to name your flame.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"undo","kind":"act","impl":"imperative","description":"Undo the last action. Returns the new undo/redo state after the operation. Use get_undo_state first to check what will be undone.","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 action. Returns the new undo/redo state after the operation.","inputSchema":{"type":"object","properties":{}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"load_share_link","kind":"act","impl":"imperative","description":"Load a flame from a share link payload. Provide the encoded string (the value after ?flame= in a share URL). The flame will be decoded, validated, and loaded into the workspace.","inputSchema":{"type":"object","properties":{"encoded":{"type":"string","description":"The encoded share payload string (from ?flame= parameter)"}},"required":["encoded"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"create_clash_flame","kind":"act","impl":"imperative","description":"Merges two flames into a single arena view, positioning them in a shared 2D or 3D coordinate space. In 3D mode, combatants are staged on opposite sides of the origin with distinct palette tinting and an orbital camera. Returns the combined flame descriptor.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"flameA":{"type":"object","description":"The first flame descriptor (Player 1). Will be positioned on the left/negative axis."},"flameB":{"type":"object","description":"The second flame descriptor (Player 2). Will be positioned on the right/positive axis."},"dimensions":{"type":"integer","enum":[2,3],"description":"Staging dimension: 2 for 2D side-by-side, 3 for 3D shared volume. Default is 2."},"axis":{"type":"string","enum":["x","y","z"],"description":"Separation axis in 3D. Default is \"x\"."},"separation":{"type":"number","description":"Distance from origin to each combatant. Default is 2.2 in 3D."},"distance":{"type":"number","description":"Legacy distance alias for 2D separation. Default is 2.0."},"tintA":{"type":"number","description":"Palette hue coordinate for Player 1 (0.0–1.0). Default is 0.15."},"tintB":{"type":"number","description":"Palette hue coordinate for Player 2 (0.0–1.0). Default is 0.65."},"tint":{"type":"string","enum":["override","blend","none"],"description":"Tint application mode. Default is \"override\" in 3D and \"none\" in 2D."},"powerA":{"type":"number","description":"Optional power level override for Player 1."},"powerB":{"type":"number","description":"Optional power level override for Player 2."}},"required":["flameA","flameB"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"open_arena","kind":"act","impl":"imperative","description":"Opens the Flame Clash Arena HUD overlay in the user interface. Pass calculated stats from score_flame and optional flame descriptors for Player 1 and Player 2. If flames are omitted, uses the workspace flame and a generated mutated opponent.","inputSchema":{"type":"object","properties":{"player1Name":{"type":"string","description":"Name of fighter 1."},"player1Stats":{"type":"object","description":"Stats for fighter 1 (e.g. from score_flame)."},"player1Flame":{"type":"object","description":"Optional FlameDescriptor for fighter 1."},"player2Name":{"type":"string","description":"Name of fighter 2."},"player2Stats":{"type":"object","description":"Stats for fighter 2 (e.g. from score_flame)."},"player2Flame":{"type":"object","description":"Optional FlameDescriptor for fighter 2."}},"required":["player1Stats","player2Stats"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"open_art_director","kind":"act","impl":"imperative","description":"Opens the Evolutionary Art Director UI in the user interface. Use this tool after generating candidate flames (via breed_flames or manually) to present them to the user for selection. You must provide an array of flame candidates. The user will select one, which you should monitor via context/events or instruct the user to notify you.","inputSchema":{"type":"object","properties":{"generation":{"type":"number","description":"The current generation number."},"candidates":{"type":"array","items":{"type":"object","properties":{"flame":{"type":"object"},"fitness":{"type":"number"}}},"description":"The candidate flames generated for this iteration."}},"required":["generation","candidates"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"breed_flames","kind":"act","impl":"imperative","description":"Takes two flames (Parent A and Parent B) and breeds them using a genetic crossover algorithm. Returns an array of child flames (default 3 children). Useful for Evolutionary Art Director workflows.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"flameA":{"type":"object","description":"The first parent flame descriptor."},"flameB":{"type":"object","description":"The second parent flame descriptor."},"count":{"type":"number","description":"How many child flames to generate. Default is 3."},"crossoverMode":{"type":"string","enum":["uniform","weighted","shuffle","alternate","smart"],"description":"Crossover strategy: uniform, weighted, shuffle, alternate, or smart. Default is smart."},"mutationStrength":{"type":"number","description":"Post-crossover mutation strength (0 to 1). 0 is pure crossover, 1 is heavy mutation. Default is 0.1."}},"required":["flameA","flameB"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"create_custom_variation","kind":"act","impl":"imperative","description":"Compiles and registers a new custom math variation. Returns the generated ID on success (like \"custom_e1e54335_2e3b_4431_a197_9ef33d1c0afd\"), which you can then use in a flame descriptor (e.g. `variations: { \"custom_e1e54335_...\": { type: \"custom_e1e54335_...\", weight: 1.0 } }`).","inputSchema":{"type":"object","properties":{"name":{"type":"string","description":"Human-readable name for the variation (e.g. \"My Swirl\")."},"body":{"type":"string","description":"JavaScript-syntax expression body, transpiled to WGSL. Receives `pos` (a 2-component vector with .x and .y) and must `return` a 2-component vector built with vec2f(x, y).\n\nUse JavaScript syntax, NOT WGSL syntax:\n  - `let r = length(pos);`   NOT  `let r: f32 = length(pos);`\n  - `vec2f(a, b)`            NOT  `vec2<f32>(a, b)`\nMultiple statements are fine. Semicolons required.\n\nAvailable: sin, cos, tan, atan2, sqrt, length, abs, floor, pow, min, max, vec2f, f32, and the constants PI and EPS. `Math.*` is NOT available — call `sqrt(x)`, not `Math.sqrt(x)`.\n\nExample: `let r = length(pos); let a = atan2(pos.y, pos.x) + r; return vec2f(r*cos(a), r*sin(a));`"},"wgslBody":{"type":"string","description":"Deprecated alias for `body`."},"updateId":{"type":"string","description":"Optional. If you want to overwrite an existing custom variation, provide its ID here (e.g., \"custom_e1e54335_2e3b_4431_a197_9ef33d1c0afd\"). If omitted, a new variation is created."}},"required":["name"]},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"animate_clash","kind":"act","impl":"imperative","description":"Keyframes an interactive 3D camera choreography and territory fight into the timeline. Sets up establishing orbit, convergence collision, and victory resolution across 3 rounds.","inputSchema":{"type":"object","properties":{"simulation":{"type":"object","description":"Optional pre-computed clash simulation result from simulate_clash."},"flameA":{"type":"object","description":"Fighter 1 flame descriptor."},"flameB":{"type":"object","description":"Fighter 2 flame descriptor."},"framesPerRound":{"type":"integer","description":"Number of timeline frames per round. Default is 60."}}},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"}],"category":"Media & Personal","favicon":"/favicons/lumenapeiron.com.png","apiSurface":"spec","toolCount":34}}