{"ok":true,"site":{"host":"bananalabs-sable.vercel.app","url":"https://bananalabs-sable.vercel.app/","type":"live","desc":"BananaLabs DJ","tools":[{"name":"get_session","kind":"answer","impl":"imperative","description":"Compact live snapshot: decks, mixer, arrangement, proposal pending. Use before editing.","title":"Get session","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_track","kind":"answer","impl":"imperative","description":"Full track analysis: BPM, Camelot key, sections, energy curve, vocal regions, beat/downbeat samples, waveform peaks, lyrics preview. No mix-point suggestions — choose bars yourself.","title":"Get track","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"type":"object","properties":{"track_id":{"type":"string"},"detail":{"type":"string","enum":["full","compact"]}},"required":["track_id"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"search_library","kind":"answer","impl":"imperative","description":"List/filter library tracks by title/artist, BPM range, or Camelot key (e.g. 8A). Paginated: limit (default 25, max 100) + offset; response includes total and has_more — keep paging until has_more is false instead of guessing the rest.","title":"Search library","annotations":{"readOnlyHint":true,"untrustedContentHint":true},"inputSchema":{"type":"object","properties":{"query":{"type":"string"},"bpm_min":{"type":"number"},"bpm_max":{"type":"number"},"key":{"type":"string"},"limit":{"type":"number"},"offset":{"type":"number"}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"suggest_compatible","kind":"answer","impl":"imperative","description":"Ranks other tracks by BPM/key/energy distance to a seed. Metrics only — you choose the set.","title":"Suggest compatible","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"track_id":{"type":"string"},"bpm_min":{"type":"number"},"bpm_max":{"type":"number"}},"required":["track_id"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_set_quality","kind":"answer","impl":"imperative","description":"Returns numeric BPM/key/energy metrics plus craft notes from verify_set. Prefer verify_set as the gate before propose.","title":"Get set quality","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"source":{"type":"string","enum":["arrangement","proposal"]}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_dj_playbook","kind":"answer","impl":"imperative","description":"The rulebook: chop formula first (INTRO→UP+→DROP→[DOWN]→DROP+→OUTRO), then what each recipe compiles, verify error codes, Camelot/BPM refs. Read it once before your first set.","title":"Get DJ playbook","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"topic":{"type":"string","enum":["all","recipes","verify"]}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_mix_points","kind":"answer","impl":"imperative","description":"Phrase candidates: peak drop, 8/16 before that drop, vocal_end, safe_leave, breakdown, mix-in/out, grid. Prefer phraseBars. Leave on safe_leave, not mid-line.","title":"Get mix points","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"track_id":{"type":"string"}},"required":["track_id"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"verify_set","kind":"act","impl":"imperative","description":"Craft gate — run before proposing/applying and after any rewrite. ready:true means no broken automation. Errors (must fix): double-bass on a blend, echo without FX, mid-vocal leave, key-unknown pad, overlap past the Camelot cap, |ΔBPM|>3 without a tempo lane, unknown transition type. echo_out / cut / backspin do not share a clock and do not need a tempo ramp. Warnings are observations — keep them if you meant it.","title":"Verify set","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"source":{"type":"string","enum":["arrangement","proposal"]}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"apply_transition_recipe","kind":"act","impl":"imperative","description":"Compile a join you chose on incoming entry (index≥1). tease_slam (the chop default) parks incoming at drop−bars so its build teases in filtered under the outgoing, rides the tempo lane across the window, then roll + throw and the slam on the 1. drop_swap parks incoming at drop−8 (the build), leaves after the vocal line, then peels. power_cut / backspin / air_cut park incoming on its drop. air_cut = suck-out, one bar of dead air, slam — no shared clock. echo_out = echo-throw leave (dry holds, delay fills, cut on the 1; incoming from its drop/heat, never bar 0, no tempo ramp). Never pad-blend two vocal leads; only half/double-time records still air-slam. The result echoes the parked trims and the compiled commit (commit_bars, commit_on_drop) — trust that echo over your own bar math.","title":"Apply transition recipe","inputSchema":{"type":"object","properties":{"index":{"type":"number"},"recipe":{"type":"string","enum":["tease_slam","drop_swap","double_drop","power_cut","air_cut","build_cut","bass_swap","eq_swap","filter_sweep","echo_out","loop_out","loop_roll","backspin","hook_layer","half_bridge","tempo_ride","power_block"]},"bars":{"type":"number"}},"required":["index","recipe"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_crate_health","kind":"answer","impl":"imperative","description":"START HERE before composing a set. Cards carry MEASURED facts only: bpm, bpm_lane, key+confidence (a ? means untrusted), energy, brightness, drop/heat/hole/safe_leave, vocals, cue_before_drop_8/16. mood and genre are MusicBrainz or tag_track — never DSP. Roles are craft-only. Next step: prepare_set (chop formula by default).","title":"Crate health","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"plan_set_arc","kind":"act","impl":"imperative","description":"Peak-first track order + mix windows + drop cues. Does not pick the join (1-bar cut placeholder). Optional apply=true stages set_propose.","title":"Plan set arc","inputSchema":{"type":"object","properties":{"arc":{"type":"string","enum":["journey","peak_time","warm_up","cool_down","chill","power_block"]},"track_count":{"type":"number"},"apply":{"type":"boolean"}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"prepare_set","kind":"act","impl":"imperative","description":"Default action for 'make me a set'. Chop formula: INTRO→UP+→DROP→[DOWN]→DROP+→OUTRO. 16–32 bar heat/drop clips, sudden entries, never intros. Default join: tease_slam — the incoming build teases in filtered under the outgoing, the tempo lane rides the BPM gap, roll + throw, slam on the 1 (loop_roll / backspin / power_cut for variety and no-drop cases; no two identical slams in a row). Blend + echo only when intent is chill/deep/warm-up/smooth. The engine owns bar math — you never compute in_bars/out_bars. Options: intent; track_count; order; join_overrides; apply (default true); hear (default true). Rewrite any join with apply_transition_recipe, then verify_set.","title":"Prepare set","inputSchema":{"type":"object","properties":{"intent":{"type":"string"},"track_count":{"type":"number"},"order":{"type":"array","items":{"type":"string"},"description":"Explicit track_ids in play order; omit for auto arc"},"join_overrides":{"type":"array","items":{"type":"object","properties":{"index":{"type":"number"},"recipe":{"type":"string","enum":["tease_slam","drop_swap","double_drop","power_cut","air_cut","build_cut","bass_swap","eq_swap","filter_sweep","echo_out","loop_out","loop_roll","backspin","hook_layer","half_bridge","tempo_ride","power_block"]},"bars":{"type":"number"}},"required":["index"]}},"hear":{"type":"boolean"},"apply":{"type":"boolean"}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"preview_join","kind":"act","impl":"imperative","description":"Listen-score a join (index ≥ 1) — the ear you lack. Auditions the ACTUAL overlap windows from the stored chroma (harmony.blend_ok / bass_only / clash): measured audio beats the Camelot label. echo_out is scored as a leave (incoming is not in the window). Isolator recipes are not failed for raw-file bass or a guessed key. Fails mid-vocal leave, measured-clash pad blends, and pad blends that break the cap. Returns drops/cues plus the compiled commit (commit_bars, commit_on_drop): on a drop recipe the commit must land on the incoming drop's 1, otherwise your cue math drifted.","title":"Preview join","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"index":{"type":"number"},"hear":{"type":"boolean"}},"required":["index"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"tag_track","kind":"act","impl":"imperative","description":"You are the curator of mood, genre, and role. The detector measures audio (bpm, energy, brightness, drop) but cannot know a euphoric anthem from a minor key. MusicBrainz may fill genre on import; override here (genreSource=agent). Also: role opener|builder|bridge|peak|reset|closer, energyLevel 1–10.","title":"Tag track craft","inputSchema":{"type":"object","properties":{"track_id":{"type":"string"},"role":{"type":"string","enum":["opener","builder","bridge","peak","reset","closer"]},"energy_level":{"type":"number"},"mood":{"type":"string","enum":["dark","bright","driving","warm"]},"genre_hint":{"type":"string"}},"required":["track_id"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"apply_power_block","kind":"act","impl":"imperative","description":"Trim each arrangement entry to the first drop/hook (~32 bars) and set every join to a 1-bar cut.","title":"Apply power block","inputSchema":{"type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"analyze_track","kind":"act","impl":"imperative","description":"Re-run analysis for a track already in the library (BPM, sections, energy, waveform).","title":"Analyze track","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"track_id":{"type":"string"}},"required":["track_id"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"fetch_lyrics","kind":"answer","impl":"imperative","description":"Fetch synced lyrics (LRCLIB) and store on the track. Then use find_lyric to map words → bars.","title":"Fetch lyrics","inputSchema":{"type":"object","properties":{"track_id":{"type":"string"}},"required":["track_id"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_lyrics","kind":"answer","impl":"imperative","description":"Return stored lyric words {t seconds, w}. Empty if not fetched yet.","title":"Get lyrics","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"track_id":{"type":"string"},"offset":{"type":"number"},"limit":{"type":"number"}},"required":["track_id"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"find_lyric","kind":"answer","impl":"imperative","description":"Search stored lyrics for query. Returns start_bars/end_bars for seek/loop/trim. fetch_lyrics first if none.","title":"Find lyric","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"track_id":{"type":"string"},"query":{"type":"string"},"limit":{"type":"number"}},"required":["track_id","query"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_cue","kind":"act","impl":"imperative","description":"Arm channel Cue (PFL). Any armed Cue solos those channels to master (web has no separate phones out).","title":"Channel cue","inputSchema":{"type":"object","properties":{"deck":{"type":"string","enum":["A","B","C","D"]},"enabled":{"type":"boolean"}},"required":["deck","enabled"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_insert_track","kind":"act","impl":"imperative","description":"Insert a track into the working arrangement at index. Prefer cue parking over raw bars: cue = auto | drop | mix_in | <bars>. 'auto' parks from the join compiler (incoming N bars before its drop for swap recipes, on the drop for cuts, drop/heat for echo) and 'drop'/'mix_in' pick that cue explicitly. Raw in_bars/out_bars still work but are NOT phrase-snapped — verify_set will flag off-grid bars. transition accepts types (cut, drop_swap, …) or recipe names (power_cut, bass_swap, half_bridge, power_block). Result echoes the parked entry and, for index ≥ 1, where the compiled xfader commit lands (commit_on_drop).","title":"Insert track","inputSchema":{"type":"object","properties":{"index":{"type":"number"},"track_id":{"type":"string"},"cue":{"type":["string","number"],"description":"auto | drop | mix_in | bars — parking handled by the compiler"},"in_bars":{"type":"number"},"out_bars":{"type":"number"},"transition":{"type":"string","enum":["cut","blend","eq_swap","filter_sweep","echo_out","loop_out","build_cut","drop_swap","double_drop","loop_roll","backspin","hook_layer","air_cut","tempo_ride","tease_slam","tease_slam","drop_swap","double_drop","power_cut","air_cut","build_cut","bass_swap","eq_swap","filter_sweep","echo_out","loop_out","loop_roll","backspin","hook_layer","half_bridge","tempo_ride","power_block"]},"bars":{"type":"number"}},"required":["index","track_id"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_remove_track","kind":"act","impl":"imperative","description":"Remove arrangement entry at index.","title":"Remove track","inputSchema":{"type":"object","properties":{"index":{"type":"number"}},"required":["index"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_move_track","kind":"act","impl":"imperative","description":"Reorder arrangement entry from_index → to_index.","title":"Move track","inputSchema":{"type":"object","properties":{"from_index":{"type":"number"},"to_index":{"type":"number"}},"required":["from_index","to_index"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_set_trim","kind":"act","impl":"imperative","description":"Set in_bars/out_bars for an arrangement entry. Bars within ±1 of the 8-bar phrase grid are auto-snapped to it (a 71 becomes 72) — off-phrase commits are the #1 'beats don't match' complaint. Values further off-grid pass through untouched and verify_set will flag them.","title":"Set trim","inputSchema":{"type":"object","properties":{"index":{"type":"number"},"in_bars":{"type":"number"},"out_bars":{"type":"number"}},"required":["index","in_bars","out_bars"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_set_transition","kind":"act","impl":"imperative","description":"Set the join INTO the entry at index (index ≥ 1). Accepts transition types (cut, blend, drop_swap, echo_out, …) or recipe names (power_cut, bass_swap, half_bridge, power_block — resolved to their types). Prefer apply_transition_recipe for recipes: it also parks the cue bars. Result echoes the compiled commit (commit_bars on the set clock, commit_on_drop) — if commit_on_drop is false on a drop recipe, your cue math drifted from the recipe shape.","title":"Set transition","inputSchema":{"type":"object","properties":{"index":{"type":"number"},"type":{"type":"string","enum":["cut","blend","eq_swap","filter_sweep","echo_out","loop_out","build_cut","drop_swap","double_drop","loop_roll","backspin","hook_layer","air_cut","tempo_ride","tease_slam","tease_slam","drop_swap","double_drop","power_cut","air_cut","build_cut","bass_swap","eq_swap","filter_sweep","echo_out","loop_out","loop_roll","backspin","hook_layer","half_bridge","tempo_ride","power_block"]},"bars":{"type":"number"}},"required":["index","type"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_clear","kind":"act","impl":"imperative","description":"Clear the working arrangement (not the library).","title":"Clear set","inputSchema":{"type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_propose","kind":"act","impl":"imperative","description":"Stage an arrangement for human Accept/Reject. You author tracks and joins. Do not invent tracks. verify_set ready:true means no broken automation.","title":"Propose set","inputSchema":{"type":"object","properties":{"entries":{"type":"array","items":{"type":"object","properties":{"track_id":{"type":"string"},"in_bars":{"type":"number"},"out_bars":{"type":"number"},"transition":{"type":"string","enum":["cut","blend","eq_swap","filter_sweep","echo_out","loop_out","build_cut","drop_swap","double_drop","loop_roll","backspin","hook_layer","air_cut","tempo_ride","tease_slam","tease_slam","drop_swap","double_drop","power_cut","air_cut","build_cut","bass_swap","eq_swap","filter_sweep","echo_out","loop_out","loop_roll","backspin","hook_layer","half_bridge","tempo_ride","power_block"]},"recipe":{"type":"string","enum":["tease_slam","drop_swap","double_drop","power_cut","air_cut","build_cut","bass_swap","eq_swap","filter_sweep","echo_out","loop_out","loop_roll","backspin","hook_layer","half_bridge","tempo_ride","power_block"]},"bars":{"type":"number"}},"required":["track_id","in_bars","out_bars"]}},"automation":{"type":"array","items":{"type":"object","properties":{"param":{"type":"string","enum":["tempo","xfader","filter_a","filter_b","eq_low_a","eq_mid_a","eq_high_a","eq_low_b","eq_mid_b","eq_high_b","fader_a","fader_b","gain_a","gain_b","fx_wet","fx_arm"]},"start_bars":{"type":"number"},"end_bars":{"type":"number"},"start_value":{"type":"number"},"end_value":{"type":"number"},"curve":{"type":"string","enum":["linear","exponential","ease_in","ease_out"]}},"required":["param","start_bars","end_bars","start_value","end_value"]}},"reason":{"type":"string"}},"required":["entries"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_apply_proposal","kind":"act","impl":"imperative","description":"Apply the pending proposal to the arrangement.","title":"Apply proposal","inputSchema":{"type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_reject_proposal","kind":"act","impl":"imperative","description":"Discard the pending proposal.","title":"Reject proposal","inputSchema":{"type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_set_timeline","kind":"answer","impl":"imperative","description":"Flattened set timeline with deck assignment, overlaps from transitions, duration, and automation lanes. Use before adding tempo/mixer automations (bars are absolute from set start).","title":"Get set timeline","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_set_tempo","kind":"act","impl":"imperative","description":"Set master set tempo in BPM (null clears → first track BPM). Tempo automation overrides while active.","title":"Set master tempo","inputSchema":{"type":"object","properties":{"bpm":{"type":["number","null"]}},"required":["bpm"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_add_automation","kind":"act","impl":"imperative","description":"Add a set-timeline automation lane (absolute bars). param=tempo for BPM ramps (e.g. 124→128 over 16 bars). Also xfader, filter_a/b, eq_*_a/b, fader_a/b, gain_a/b. curve: linear|exponential|ease_in|ease_out. Play performs these with transitions.","title":"Add automation","inputSchema":{"type":"object","properties":{"param":{"type":"string","enum":["tempo","xfader","filter_a","filter_b","eq_low_a","eq_mid_a","eq_high_a","eq_low_b","eq_mid_b","eq_high_b","fader_a","fader_b","gain_a","gain_b","fx_wet","fx_arm"]},"start_bars":{"type":"number"},"end_bars":{"type":"number"},"start_value":{"type":"number"},"end_value":{"type":"number"},"curve":{"type":"string","enum":["linear","exponential","ease_in","ease_out"]}},"required":["param","start_bars","end_bars","start_value","end_value"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_remove_automation","kind":"act","impl":"imperative","description":"Remove an automation lane by id (from get_session / get_set_timeline).","title":"Remove automation","inputSchema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_clear_automation","kind":"act","impl":"imperative","description":"Clear all explicit automation lanes (compiled transition automations remain).","title":"Clear automation","inputSchema":{"type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"download_set","kind":"act","impl":"imperative","description":"Offline-bounce the arrangement (transitions + automation) to a WAV file and download it. Same as TopBar Download. Does not use the live Rec bus.","title":"Download set WAV","inputSchema":{"type":"object","properties":{"filename":{"type":"string","description":"Optional base filename without extension"}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"review_set","kind":"act","impl":"imperative","description":"Bounce the arrangement offline and MEASURE each join from the rendered audio: dead air at the commit, level jump across the 1, bass stacking during the tease, whether the tease rises, whether the drop's FIRST hit lands open (first_hit < 0.7 = the slam ramps through the 1), whether the slam lifts. Trust these numbers over imagination — what fails here fails in the room. Loop rolls and tempo rides render like live. Run after prepare_set / apply_transition_recipe. With fix:true, writes gainstage lanes that level every entry's solo loudness to the set mean (kills hot/sagging slams) — then re-run to confirm. Pass index to focus one join.","title":"Review set (bounce + measure)","inputSchema":{"type":"object","properties":{"index":{"type":"number","description":"Optional join index (≥1) to focus"},"fix":{"type":"boolean","description":"Write gain-staging lanes from the measurements"}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_play","kind":"act","impl":"imperative","description":"Perform the arrangement: loads A/B alternating, applies transition types and automation (tempo/EQ/filter/xfader). Optional start_bars seeks first.","title":"Play set","inputSchema":{"type":"object","properties":{"start_bars":{"type":"number"}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_pause","kind":"act","impl":"imperative","description":"Pause set performance.","title":"Pause set","inputSchema":{"type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_seek","kind":"act","impl":"imperative","description":"Seek set playhead to absolute bars (also works while paused).","title":"Seek set","inputSchema":{"type":"object","properties":{"bars":{"type":"number"}},"required":["bars"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"fx_set","kind":"act","impl":"imperative","description":"Master FX unit: type off|delay|reverb|echo, wet 0–1, time_beats, feedback.","title":"Set FX","inputSchema":{"type":"object","properties":{"type":{"type":"string","enum":["off","delay","reverb","echo"]},"wet":{"type":"number"},"time_beats":{"type":"number"},"feedback":{"type":"number"}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"history","kind":"answer","impl":"imperative","description":"Undo or redo the last SetDoc mutation.","title":"History","inputSchema":{"type":"object","properties":{"action":{"type":"string","enum":["undo","redo"]}},"required":["action"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"}],"category":"Media & Personal","favicon":"/favicons/bananalabs-sable.vercel.app.svg","apiSurface":"spec","toolCount":41}}