livepilot 1.26.0 → 1.26.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/README.md +1 -1
- package/installer/codex.js +87 -9
- package/livepilot/.Codex-plugin/plugin.json +8 -0
- package/livepilot/.claude-plugin/plugin.json +8 -0
- package/livepilot/.mcp.json +8 -0
- package/livepilot/agents/livepilot-producer/AGENT.md +314 -0
- package/livepilot/commands/arrange.md +47 -0
- package/livepilot/commands/beat.md +81 -0
- package/livepilot/commands/evaluate.md +51 -0
- package/livepilot/commands/memory.md +22 -0
- package/livepilot/commands/mix.md +47 -0
- package/livepilot/commands/perform.md +42 -0
- package/livepilot/commands/session.md +13 -0
- package/livepilot/commands/sounddesign.md +58 -0
- package/livepilot/rubrics/default_preset_check.md +82 -0
- package/livepilot/rubrics/layer_accumulation.md +79 -0
- package/livepilot/rubrics/layer_precision.md +79 -0
- package/livepilot/rubrics/modulation_presence.md +63 -0
- package/livepilot/rubrics/sound_design_depth.md +40 -0
- package/livepilot/skills/livepilot-arrangement/SKILL.md +164 -0
- package/livepilot/skills/livepilot-composition-engine/SKILL.md +151 -0
- package/livepilot/skills/livepilot-composition-engine/references/form-patterns.md +97 -0
- package/livepilot/skills/livepilot-composition-engine/references/transition-archetypes.md +102 -0
- package/livepilot/skills/livepilot-core/SKILL.md +261 -0
- package/livepilot/skills/livepilot-core/references/ableton-workflow-patterns.md +831 -0
- package/livepilot/skills/livepilot-core/references/affordances/_schema.md +160 -0
- package/livepilot/skills/livepilot-core/references/affordances/devices/auto-filter.yaml +133 -0
- package/livepilot/skills/livepilot-core/references/affordances/devices/chorus-ensemble.yaml +91 -0
- package/livepilot/skills/livepilot-core/references/affordances/devices/compressor.yaml +98 -0
- package/livepilot/skills/livepilot-core/references/affordances/devices/convolution-reverb.yaml +113 -0
- package/livepilot/skills/livepilot-core/references/affordances/devices/corpus.yaml +84 -0
- package/livepilot/skills/livepilot-core/references/affordances/devices/drift.yaml +105 -0
- package/livepilot/skills/livepilot-core/references/affordances/devices/echo.yaml +108 -0
- package/livepilot/skills/livepilot-core/references/affordances/devices/eq-eight.yaml +95 -0
- package/livepilot/skills/livepilot-core/references/affordances/devices/glue-compressor.yaml +88 -0
- package/livepilot/skills/livepilot-core/references/affordances/devices/granulator-iii.yaml +104 -0
- package/livepilot/skills/livepilot-core/references/affordances/devices/hybrid-reverb.yaml +83 -0
- package/livepilot/skills/livepilot-core/references/affordances/devices/operator.yaml +98 -0
- package/livepilot/skills/livepilot-core/references/affordances/devices/ping-pong-delay.yaml +104 -0
- package/livepilot/skills/livepilot-core/references/affordances/devices/poli.yaml +98 -0
- package/livepilot/skills/livepilot-core/references/affordances/devices/saturator.yaml +98 -0
- package/livepilot/skills/livepilot-core/references/affordances/devices/shifter.yaml +77 -0
- package/livepilot/skills/livepilot-core/references/affordances/devices/simpler.yaml +113 -0
- package/livepilot/skills/livepilot-core/references/affordances/devices/utility.yaml +95 -0
- package/livepilot/skills/livepilot-core/references/affordances/devices/vinyl-distortion.yaml +92 -0
- package/livepilot/skills/livepilot-core/references/affordances/devices/wavetable.yaml +98 -0
- package/livepilot/skills/livepilot-core/references/artist-vocabularies.md +389 -0
- package/livepilot/skills/livepilot-core/references/automation-atlas.md +272 -0
- package/livepilot/skills/livepilot-core/references/concepts/_schema.md +158 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/akufen.yaml +116 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/aphex-twin.yaml +133 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/arca-sophie.yaml +131 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/autechre.yaml +130 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/basic-channel.yaml +140 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/basinski.yaml +126 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/boards-of-canada.yaml +124 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/burial.yaml +127 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/com-truise-tycho.yaml +121 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/daft-punk.yaml +117 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/dj-premier-rza.yaml +119 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/gas.yaml +134 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/hawtin.yaml +127 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/isolee-luomo.yaml +130 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/j-dilla.yaml +133 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/jeff-mills.yaml +120 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/johannsson-richter.yaml +132 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/madlib.yaml +124 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/moodymann-theo-parrish.yaml +121 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/oneohtrix-point-never.yaml +126 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/photek-source-direct.yaml +120 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/rashad-spinn-traxman.yaml +122 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/robert-henke.yaml +113 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/shackleton.yaml +124 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/skream-mala.yaml +119 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/stars-of-the-lid.yaml +119 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/tim-hecker.yaml +122 -0
- package/livepilot/skills/livepilot-core/references/concepts/artists/villalobos.yaml +135 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/ambient.yaml +137 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/boom_bap.yaml +124 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/deep-minimal.yaml +130 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/deep_house.yaml +130 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/detroit_techno.yaml +116 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/disco.yaml +123 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/downtempo.yaml +129 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/drone.yaml +133 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/drum-and-bass.yaml +119 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/dub-techno.yaml +132 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/dub.yaml +129 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/dubstep.yaml +120 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/experimental.yaml +136 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/footwork.yaml +119 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/hip-hop.yaml +132 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/house.yaml +126 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/hyperpop.yaml +128 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/idm.yaml +134 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/lo_fi.yaml +129 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/microhouse.yaml +138 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/minimal-techno.yaml +116 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/modern-classical.yaml +123 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/soul.yaml +125 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/synthwave.yaml +123 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/techno.yaml +123 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/trap.yaml +120 -0
- package/livepilot/skills/livepilot-core/references/concepts/genres/uk-garage.yaml +121 -0
- package/livepilot/skills/livepilot-core/references/device-atlas/00-index.md +110 -0
- package/livepilot/skills/livepilot-core/references/device-atlas/distortion-and-character.md +687 -0
- package/livepilot/skills/livepilot-core/references/device-atlas/drums-and-percussion.md +753 -0
- package/livepilot/skills/livepilot-core/references/device-atlas/dynamics-and-punch.md +525 -0
- package/livepilot/skills/livepilot-core/references/device-atlas/eq-and-filtering.md +402 -0
- package/livepilot/skills/livepilot-core/references/device-atlas/midi-tools.md +963 -0
- package/livepilot/skills/livepilot-core/references/device-atlas/movement-and-modulation.md +874 -0
- package/livepilot/skills/livepilot-core/references/device-atlas/space-and-depth.md +571 -0
- package/livepilot/skills/livepilot-core/references/device-atlas/spectral-and-weird.md +714 -0
- package/livepilot/skills/livepilot-core/references/device-atlas/synths-native.md +953 -0
- package/livepilot/skills/livepilot-core/references/device-knowledge/00-index.md +34 -0
- package/livepilot/skills/livepilot-core/references/device-knowledge/automation-as-music.md +204 -0
- package/livepilot/skills/livepilot-core/references/device-knowledge/chains-genre.md +173 -0
- package/livepilot/skills/livepilot-core/references/device-knowledge/creative-thinking.md +211 -0
- package/livepilot/skills/livepilot-core/references/device-knowledge/effects-distortion.md +188 -0
- package/livepilot/skills/livepilot-core/references/device-knowledge/effects-space.md +162 -0
- package/livepilot/skills/livepilot-core/references/device-knowledge/effects-spectral.md +229 -0
- package/livepilot/skills/livepilot-core/references/device-knowledge/instruments-synths.md +243 -0
- package/livepilot/skills/livepilot-core/references/genre-vocabularies.md +382 -0
- package/livepilot/skills/livepilot-core/references/m4l-devices.md +352 -0
- package/livepilot/skills/livepilot-core/references/memory-guide.md +178 -0
- package/livepilot/skills/livepilot-core/references/midi-recipes.md +402 -0
- package/livepilot/skills/livepilot-core/references/mixing-patterns.md +578 -0
- package/livepilot/skills/livepilot-core/references/overview.md +300 -0
- package/livepilot/skills/livepilot-core/references/pack-knowledge.md +319 -0
- package/livepilot/skills/livepilot-core/references/sample-manipulation.md +724 -0
- package/livepilot/skills/livepilot-core/references/sound-design-deep.md +140 -0
- package/livepilot/skills/livepilot-core/references/sound-design.md +393 -0
- package/livepilot/skills/livepilot-corpus-builder/SKILL.md +379 -0
- package/livepilot/skills/livepilot-creative-director/SKILL.md +462 -0
- package/livepilot/skills/livepilot-creative-director/references/anti-repetition-rules.md +214 -0
- package/livepilot/skills/livepilot-creative-director/references/creative-brief-template.md +222 -0
- package/livepilot/skills/livepilot-creative-director/references/hybrid-compilation.md +185 -0
- package/livepilot/skills/livepilot-creative-director/references/move-family-diversity-rule.md +258 -0
- package/livepilot/skills/livepilot-creative-director/references/phase-6-execution.md +409 -0
- package/livepilot/skills/livepilot-creative-director/references/the-four-move-rule.md +192 -0
- package/livepilot/skills/livepilot-devices/SKILL.md +213 -0
- package/livepilot/skills/livepilot-devices/references/load_browser_item-uri-grammar.md +82 -0
- package/livepilot/skills/livepilot-evaluation/SKILL.md +195 -0
- package/livepilot/skills/livepilot-evaluation/references/capability-modes.md +176 -0
- package/livepilot/skills/livepilot-evaluation/references/evaluation-contracts.md +121 -0
- package/livepilot/skills/livepilot-evaluation/references/memory-promotion.md +110 -0
- package/livepilot/skills/livepilot-mix-engine/SKILL.md +144 -0
- package/livepilot/skills/livepilot-mix-engine/references/mix-critics.md +143 -0
- package/livepilot/skills/livepilot-mix-engine/references/mix-moves.md +105 -0
- package/livepilot/skills/livepilot-mixing/SKILL.md +164 -0
- package/livepilot/skills/livepilot-notes/SKILL.md +130 -0
- package/livepilot/skills/livepilot-performance-engine/SKILL.md +122 -0
- package/livepilot/skills/livepilot-performance-engine/references/performance-safety.md +98 -0
- package/livepilot/skills/livepilot-release/SKILL.md +151 -0
- package/livepilot/skills/livepilot-sample-engine/SKILL.md +117 -0
- package/livepilot/skills/livepilot-sample-engine/references/sample-critics.md +87 -0
- package/livepilot/skills/livepilot-sample-engine/references/sample-philosophy.md +51 -0
- package/livepilot/skills/livepilot-sample-engine/references/sample-techniques.md +131 -0
- package/livepilot/skills/livepilot-sound-design-engine/SKILL.md +247 -0
- package/livepilot/skills/livepilot-sound-design-engine/references/patch-model.md +119 -0
- package/livepilot/skills/livepilot-sound-design-engine/references/sound-design-critics.md +118 -0
- package/livepilot/skills/livepilot-wonder/SKILL.md +143 -0
- package/m4l_device/LivePilot_Analyzer.amxd +0 -0
- package/m4l_device/LivePilot_Elektron.amxd +0 -0
- package/m4l_device/LivePilot_Elektron.maxpat +758 -0
- package/m4l_device/livepilot_bridge.js +1 -1
- package/m4l_device/livepilot_elektron_bridge.js +82 -0
- package/mcp_server/__init__.py +1 -1
- package/mcp_server/composer/develop/apply.py +1 -1
- package/mcp_server/composer/full/apply.py +32 -6
- package/mcp_server/composer/full/brief_builder.py +9 -0
- package/mcp_server/evaluation/feature_extractors.py +152 -8
- package/mcp_server/m4l_bridge.py +5 -0
- package/mcp_server/mix_engine/state_builder.py +19 -2
- package/mcp_server/mix_engine/tools.py +22 -0
- package/mcp_server/runtime/execution_router.py +6 -0
- package/mcp_server/runtime/mcp_dispatch.py +18 -0
- package/mcp_server/runtime/remote_commands.py +2 -0
- package/mcp_server/server.py +11 -7
- package/mcp_server/sound_design/tools.py +33 -0
- package/mcp_server/tools/_agent_os_engine/evaluation.py +7 -44
- package/mcp_server/tools/_agent_os_engine/models.py +2 -1
- package/mcp_server/tools/_conductor.py +5 -2
- package/mcp_server/tools/_evaluation_contracts.py +1 -1
- package/mcp_server/tools/_snapshot_normalizer.py +32 -3
- package/package.json +20 -5
- package/remote_script/LivePilot/__init__.py +1 -1
- package/remote_script/LivePilot/server.py +63 -2
- package/requirements.txt +3 -3
- package/server.json +3 -3
|
@@ -9,6 +9,8 @@ from __future__ import annotations
|
|
|
9
9
|
from fastmcp import Context
|
|
10
10
|
|
|
11
11
|
from ..server import mcp
|
|
12
|
+
from ..evaluation.feature_extractors import extract_character_profile
|
|
13
|
+
from ..tools._snapshot_normalizer import normalize_sonic_snapshot
|
|
12
14
|
from .models import (
|
|
13
15
|
LayerStrategy,
|
|
14
16
|
PatchBlock,
|
|
@@ -189,9 +191,36 @@ def _fetch_sound_design_data(ctx: Context, track_index: int) -> dict:
|
|
|
189
191
|
# Get devices from track_info response (already included by Remote Script)
|
|
190
192
|
devices: list[dict] = track_info.get("devices", [])
|
|
191
193
|
|
|
194
|
+
sonic = None
|
|
195
|
+
try:
|
|
196
|
+
spectral = ctx.lifespan_context.get("spectral")
|
|
197
|
+
if spectral and spectral.is_connected:
|
|
198
|
+
sonic = {}
|
|
199
|
+
spec_data = spectral.get("spectrum")
|
|
200
|
+
if spec_data:
|
|
201
|
+
sonic["bands"] = spec_data["value"]
|
|
202
|
+
rms_snap = spectral.get("rms")
|
|
203
|
+
if rms_snap:
|
|
204
|
+
sonic["rms"] = rms_snap["value"]
|
|
205
|
+
peak_snap = spectral.get("peak")
|
|
206
|
+
if peak_snap:
|
|
207
|
+
sonic["peak"] = peak_snap["value"]
|
|
208
|
+
key_snap = spectral.get("key")
|
|
209
|
+
if key_snap:
|
|
210
|
+
sonic["detected_key"] = key_snap["value"]
|
|
211
|
+
for key in ("spectral_shape", "mel_bands", "chroma", "onset", "novelty", "loudness"):
|
|
212
|
+
snap = spectral.get(key)
|
|
213
|
+
if snap:
|
|
214
|
+
sonic[key] = snap["value"]
|
|
215
|
+
if not sonic:
|
|
216
|
+
sonic = None
|
|
217
|
+
except Exception:
|
|
218
|
+
sonic = None
|
|
219
|
+
|
|
192
220
|
return {
|
|
193
221
|
"track_info": track_info,
|
|
194
222
|
"devices": devices,
|
|
223
|
+
"sonic_snapshot": normalize_sonic_snapshot(sonic, source="sound_design"),
|
|
195
224
|
}
|
|
196
225
|
|
|
197
226
|
|
|
@@ -262,9 +291,11 @@ def analyze_sound_design(ctx: Context, track_index: int) -> dict:
|
|
|
262
291
|
issues, data["track_info"].get("name", "")
|
|
263
292
|
)
|
|
264
293
|
moves = plan_sound_design_moves(issues, state)
|
|
294
|
+
sonic_character = extract_character_profile(data.get("sonic_snapshot") or {})
|
|
265
295
|
|
|
266
296
|
return {
|
|
267
297
|
"state": state.to_dict(),
|
|
298
|
+
"sonic_character": sonic_character,
|
|
268
299
|
"issues": [i.to_dict() for i in issues],
|
|
269
300
|
"suggested_moves": [m.to_dict() for m in moves],
|
|
270
301
|
"issue_count": len(issues),
|
|
@@ -295,6 +326,7 @@ def get_sound_design_issues(ctx: Context, track_index: int) -> dict:
|
|
|
295
326
|
)
|
|
296
327
|
|
|
297
328
|
return {
|
|
329
|
+
"sonic_character": extract_character_profile(data.get("sonic_snapshot") or {}),
|
|
298
330
|
"issues": [i.to_dict() for i in issues],
|
|
299
331
|
"issue_count": len(issues),
|
|
300
332
|
}
|
|
@@ -330,6 +362,7 @@ def plan_sound_design_move(ctx: Context, track_index: int) -> dict:
|
|
|
330
362
|
moves = plan_sound_design_moves(issues, state)
|
|
331
363
|
|
|
332
364
|
result: dict = {
|
|
365
|
+
"sonic_character": extract_character_profile(data.get("sonic_snapshot") or {}),
|
|
333
366
|
"moves": [m.to_dict() for m in moves],
|
|
334
367
|
"move_count": len(moves),
|
|
335
368
|
"issue_count": len(issues),
|
|
@@ -11,6 +11,10 @@ import re
|
|
|
11
11
|
from dataclasses import asdict, dataclass, field
|
|
12
12
|
from typing import Any, Optional
|
|
13
13
|
|
|
14
|
+
from ...evaluation.feature_extractors import (
|
|
15
|
+
extract_dimension_value as _shared_extract_dimension_value,
|
|
16
|
+
)
|
|
17
|
+
from .._snapshot_normalizer import normalize_sonic_snapshot
|
|
14
18
|
from .models import QUALITY_DIMENSIONS, GoalVector, WorldModel, _clamp
|
|
15
19
|
from .taste import compute_taste_fit
|
|
16
20
|
|
|
@@ -29,50 +33,10 @@ def _extract_dimension_value(
|
|
|
29
33
|
"""
|
|
30
34
|
if not sonic:
|
|
31
35
|
return None
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
# Finding 2 fix: tolerate either shape so raw analyzer output works.
|
|
35
|
-
bands = sonic.get("spectrum") or sonic.get("bands")
|
|
36
|
-
if not bands:
|
|
37
|
-
return None
|
|
38
|
-
rms = sonic.get("rms")
|
|
39
|
-
peak = sonic.get("peak")
|
|
40
|
-
|
|
41
|
-
if dimension == "brightness":
|
|
42
|
-
high = bands.get("high", 0)
|
|
43
|
-
presence = bands.get("presence", 0)
|
|
44
|
-
return _clamp((high + presence) / 2.0)
|
|
45
|
-
elif dimension == "warmth":
|
|
46
|
-
return _clamp(bands.get("low_mid", 0))
|
|
47
|
-
elif dimension == "weight":
|
|
48
|
-
sub = bands.get("sub", 0)
|
|
49
|
-
low = bands.get("low", 0)
|
|
50
|
-
return _clamp((sub + low) / 2.0)
|
|
51
|
-
elif dimension == "clarity":
|
|
52
|
-
low_mid = bands.get("low_mid", 0)
|
|
53
|
-
return _clamp(1.0 - low_mid)
|
|
54
|
-
elif dimension == "density":
|
|
55
|
-
# Spectral flatness: geometric mean / arithmetic mean of band values.
|
|
56
|
-
# Higher = more evenly distributed energy (noise-like).
|
|
57
|
-
# Lower = more tonal (energy concentrated in few bands).
|
|
58
|
-
vals = [max(v, 1e-10) for v in bands.values() if isinstance(v, (int, float))]
|
|
59
|
-
if not vals:
|
|
60
|
-
return None
|
|
61
|
-
geo_mean = math.exp(sum(math.log(v) for v in vals) / len(vals))
|
|
62
|
-
arith_mean = sum(vals) / len(vals)
|
|
63
|
-
return _clamp(geo_mean / max(arith_mean, 1e-10))
|
|
64
|
-
elif dimension == "energy":
|
|
65
|
-
return _clamp(rms) if rms is not None else None
|
|
66
|
-
elif dimension == "punch":
|
|
67
|
-
if rms and peak and rms > 0:
|
|
68
|
-
crest_db = 20.0 * math.log10(max(peak / rms, 1.0))
|
|
69
|
-
# Normalize: 0 dB = 0.0, 20 dB = 1.0
|
|
70
|
-
return _clamp(crest_db / 20.0)
|
|
71
|
-
return None
|
|
72
|
-
else:
|
|
73
|
-
# Unmeasurable in Phase 1 (width, depth, motion, contrast,
|
|
74
|
-
# groove, tension, novelty, polish, emotion, cohesion)
|
|
36
|
+
normalized = normalize_sonic_snapshot(sonic, source="agent_os")
|
|
37
|
+
if normalized is None:
|
|
75
38
|
return None
|
|
39
|
+
return _shared_extract_dimension_value(normalized, dimension)
|
|
76
40
|
|
|
77
41
|
def compute_evaluation_score(
|
|
78
42
|
goal: GoalVector,
|
|
@@ -203,4 +167,3 @@ def compute_evaluation_score(
|
|
|
203
167
|
# I5: hint for the agent to track consecutive undos
|
|
204
168
|
"consecutive_undo_hint": not keep_change,
|
|
205
169
|
}
|
|
206
|
-
|
|
@@ -33,6 +33,8 @@ MEASURABLE_PROXIES: dict[str, str] = {
|
|
|
33
33
|
"density": "spectral flatness (geometric/arithmetic mean ratio)",
|
|
34
34
|
"energy": "RMS level",
|
|
35
35
|
"punch": "crest factor in dB (20*log10(peak/rms))",
|
|
36
|
+
"motion": "spectral novelty + onset strength",
|
|
37
|
+
"novelty": "FluCoMa novelty score",
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
VALID_MODES = frozenset({"observe", "improve", "explore", "finish", "diagnose"})
|
|
@@ -129,4 +131,3 @@ class TechniqueCard:
|
|
|
129
131
|
"verification": self.verification,
|
|
130
132
|
"evidence": self.evidence,
|
|
131
133
|
}
|
|
132
|
-
|
|
@@ -70,7 +70,7 @@ class ConductorPlan:
|
|
|
70
70
|
_ROUTING_PATTERNS: list[tuple[str, str, str, str, list[str]]] = [
|
|
71
71
|
# Mix requests
|
|
72
72
|
(r"clean|mud|muddy|low.?mid|eq|equaliz", "mix_engine", "mix", "analyze_mix", ["plan_mix_move", "evaluate_mix_move"]),
|
|
73
|
-
(r"
|
|
73
|
+
(r"dynamics|compress|crest|over.?compress|flat.?dynamics", "mix_engine", "mix", "analyze_mix", ["plan_mix_move"]),
|
|
74
74
|
(r"wide|wider|width|stereo|narrow|mono.?compat", "mix_engine", "mix", "analyze_mix", ["plan_mix_move"]),
|
|
75
75
|
(r"glue|cohes|bus.?comp|mix.?bus", "mix_engine", "mix", "analyze_mix", ["plan_mix_move"]),
|
|
76
76
|
(r"balance|level|volume.?balanc|gain.?stag", "mix_engine", "mix", "analyze_mix", ["plan_mix_move"]),
|
|
@@ -87,6 +87,7 @@ _ROUTING_PATTERNS: list[tuple[str, str, str, str, list[str]]] = [
|
|
|
87
87
|
|
|
88
88
|
# Sound design requests
|
|
89
89
|
(r"synth|patch|oscillat|timbre|timbral|wavetable|operator", "sound_design", "sound_design", "analyze_sound_design", ["plan_sound_design_move"]),
|
|
90
|
+
(r"punch|punchy|hit.?harder|snap|attack|transient", "sound_design", "sound_design", "analyze_sound_design", ["plan_sound_design_move"]),
|
|
90
91
|
(r"haunted|lush|aggressive|warm.?pad|fat.?bass|bright.?lead", "sound_design", "sound_design", "analyze_sound_design", ["plan_sound_design_move"]),
|
|
91
92
|
(r"modulation|lfo|movement|evolv|texture", "sound_design", "sound_design", "get_patch_model", ["analyze_sound_design"]),
|
|
92
93
|
(r"layer|sub.?layer|transient.?layer|body", "sound_design", "sound_design", "analyze_sound_design", ["plan_sound_design_move"]),
|
|
@@ -254,7 +255,7 @@ def classify_request(request: str) -> ConductorPlan:
|
|
|
254
255
|
|
|
255
256
|
# Determine capability requirements
|
|
256
257
|
caps = ["session_access"]
|
|
257
|
-
if any(r.engine
|
|
258
|
+
if any(r.engine in ("mix_engine", "sound_design") for r in routes):
|
|
258
259
|
caps.append("analyzer")
|
|
259
260
|
if any(r.engine in ("reference_engine",) for r in routes):
|
|
260
261
|
caps.append("offline_perception")
|
|
@@ -267,6 +268,8 @@ def classify_request(request: str) -> ConductorPlan:
|
|
|
267
268
|
notes.append("Multi-engine task — start with get_session_kernel for shared state")
|
|
268
269
|
if any(r.engine == "mix_engine" for r in routes):
|
|
269
270
|
notes.append("Mix engine works best with analyzer data — check get_capability_state")
|
|
271
|
+
if any(r.engine == "sound_design" for r in routes):
|
|
272
|
+
notes.append("Sound design should use analyzer character before level or pan changes")
|
|
270
273
|
|
|
271
274
|
# V2: Search semantic moves for matching intents
|
|
272
275
|
semantic_moves = _find_matching_semantic_moves(lower)
|
|
@@ -22,7 +22,7 @@ from typing import Optional
|
|
|
22
22
|
# must report confidence=0.0 for that dimension.
|
|
23
23
|
MEASURABLE_DIMENSIONS: frozenset[str] = frozenset({
|
|
24
24
|
"brightness", "warmth", "weight", "clarity",
|
|
25
|
-
"density", "energy", "punch",
|
|
25
|
+
"density", "energy", "punch", "motion", "novelty",
|
|
26
26
|
})
|
|
27
27
|
|
|
28
28
|
# All valid quality dimensions (measurable + unmeasurable).
|
|
@@ -13,6 +13,18 @@ import time
|
|
|
13
13
|
from typing import Optional
|
|
14
14
|
|
|
15
15
|
|
|
16
|
+
_RICH_ANALYZER_KEYS = (
|
|
17
|
+
"spectral_shape",
|
|
18
|
+
"mel_bands",
|
|
19
|
+
"chroma",
|
|
20
|
+
"onset",
|
|
21
|
+
"onsets",
|
|
22
|
+
"novelty",
|
|
23
|
+
"loudness",
|
|
24
|
+
"sub_detail",
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
16
28
|
def normalize_sonic_snapshot(
|
|
17
29
|
raw: Optional[dict],
|
|
18
30
|
source: str = "unknown",
|
|
@@ -20,6 +32,9 @@ def normalize_sonic_snapshot(
|
|
|
20
32
|
"""Normalize a raw analyzer/perception output into canonical snapshot form.
|
|
21
33
|
|
|
22
34
|
Accepts both {"bands": {...}} and {"spectrum": {...}} shapes.
|
|
35
|
+
Rich analyzer streams are preserved when present so evaluators can
|
|
36
|
+
reason from FluCoMa character descriptors instead of collapsing every
|
|
37
|
+
decision down to the 9-band spectrum.
|
|
23
38
|
Returns None if input is empty or None.
|
|
24
39
|
|
|
25
40
|
Canonical form:
|
|
@@ -28,6 +43,12 @@ def normalize_sonic_snapshot(
|
|
|
28
43
|
"rms": float or None,
|
|
29
44
|
"peak": float or None,
|
|
30
45
|
"detected_key": str or None,
|
|
46
|
+
"spectral_shape": dict or None,
|
|
47
|
+
"mel_bands": list or None,
|
|
48
|
+
"chroma": dict/list or None,
|
|
49
|
+
"onset": dict or None,
|
|
50
|
+
"novelty": dict or None,
|
|
51
|
+
"loudness": dict or None,
|
|
31
52
|
"source": str,
|
|
32
53
|
"normalized_at_ms": int,
|
|
33
54
|
}
|
|
@@ -35,11 +56,12 @@ def normalize_sonic_snapshot(
|
|
|
35
56
|
if not raw or not isinstance(raw, dict):
|
|
36
57
|
return None
|
|
37
58
|
|
|
38
|
-
bands = raw.get("spectrum") or raw.get("bands")
|
|
39
|
-
|
|
59
|
+
bands = raw.get("spectrum") or raw.get("bands") or {}
|
|
60
|
+
has_rich_analyzer_data = any(raw.get(k) is not None for k in _RICH_ANALYZER_KEYS)
|
|
61
|
+
if not bands and not has_rich_analyzer_data:
|
|
40
62
|
return None
|
|
41
63
|
|
|
42
|
-
|
|
64
|
+
normalized = {
|
|
43
65
|
"spectrum": bands,
|
|
44
66
|
"rms": raw.get("rms"),
|
|
45
67
|
"peak": raw.get("peak"),
|
|
@@ -47,3 +69,10 @@ def normalize_sonic_snapshot(
|
|
|
47
69
|
"source": source,
|
|
48
70
|
"normalized_at_ms": int(time.time() * 1000),
|
|
49
71
|
}
|
|
72
|
+
|
|
73
|
+
for key in _RICH_ANALYZER_KEYS:
|
|
74
|
+
if key in raw and raw.get(key) is not None:
|
|
75
|
+
out_key = "onset" if key == "onsets" else key
|
|
76
|
+
normalized[out_key] = raw.get(key)
|
|
77
|
+
|
|
78
|
+
return normalized
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "livepilot",
|
|
3
|
-
"version": "1.26.
|
|
3
|
+
"version": "1.26.2",
|
|
4
4
|
"mcpName": "io.github.dreamrec/livepilot",
|
|
5
|
-
"description": "Agentic production system for Ableton Live 12
|
|
5
|
+
"description": "Agentic production system for Ableton Live 12 — 465 tools, 56 domains, 44 semantic moves. Device atlas (5264 devices, 120 enriched, 7 indexes), Splice intelligence (gRPC + GraphQL describe-a-sound + preview + collections + presets), 9-band spectral perception auto-loaded via ensure_analyzer_on_master, Creative Director skill, technique memory, 12 creative intelligence engines",
|
|
6
6
|
"author": "Pilot Studio",
|
|
7
7
|
"license": "BSL-1.1",
|
|
8
8
|
"type": "commonjs",
|
|
9
9
|
"bin": {
|
|
10
|
-
"livepilot": "
|
|
10
|
+
"livepilot": "bin/livepilot.js"
|
|
11
11
|
},
|
|
12
12
|
"repository": {
|
|
13
13
|
"type": "git",
|
|
14
|
-
"url": "https://github.com/dreamrec/LivePilot"
|
|
14
|
+
"url": "git+https://github.com/dreamrec/LivePilot.git"
|
|
15
15
|
},
|
|
16
16
|
"homepage": "https://github.com/dreamrec/LivePilot",
|
|
17
17
|
"bugs": {
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
"files": [
|
|
48
48
|
"bin/**/*.js",
|
|
49
49
|
"installer/**/*.js",
|
|
50
|
+
"livepilot/**",
|
|
50
51
|
"mcp_server/**/*.py",
|
|
51
52
|
"mcp_server/**/*.json",
|
|
52
53
|
"mcp_server/**/*.yaml",
|
|
@@ -56,6 +57,9 @@
|
|
|
56
57
|
"m4l_device/LivePilot_Analyzer.amxd",
|
|
57
58
|
"m4l_device/LivePilot_Analyzer.adv",
|
|
58
59
|
"m4l_device/livepilot_bridge.js",
|
|
60
|
+
"m4l_device/LivePilot_Elektron.amxd",
|
|
61
|
+
"m4l_device/LivePilot_Elektron.maxpat",
|
|
62
|
+
"m4l_device/livepilot_elektron_bridge.js",
|
|
59
63
|
"m4l_device/BUILD_GUIDE.md",
|
|
60
64
|
"requirements.txt",
|
|
61
65
|
"README.md",
|
|
@@ -64,6 +68,17 @@
|
|
|
64
68
|
"server.json",
|
|
65
69
|
"!**/__pycache__/**",
|
|
66
70
|
"!**/*.pyc",
|
|
67
|
-
"!**/.DS_Store"
|
|
71
|
+
"!**/.DS_Store",
|
|
72
|
+
"!livepilot/skills/livepilot-core/references/device-atlas/synths-m4l.md",
|
|
73
|
+
"!livepilot/skills/livepilot-core/references/device-atlas/plugins-synths.md",
|
|
74
|
+
"!livepilot/skills/livepilot-core/references/device-atlas/utility-and-workflow.md",
|
|
75
|
+
"!livepilot/skills/livepilot-core/references/device-atlas/samples-and-irs.md",
|
|
76
|
+
"!livepilot/skills/livepilot-core/references/device-atlas/presets-by-vibe.md",
|
|
77
|
+
"!livepilot/skills/livepilot-devices/references/m4l-vendor/**",
|
|
78
|
+
"!livepilot/skills/livepilot-devices/references/m4l-depth-pass-findings.md",
|
|
79
|
+
"!livepilot/skills/livepilot-devices/references/m4l-depth-pass-resume.md",
|
|
80
|
+
"!livepilot/skills/livepilot-devices/references/m4l-library-deep.md",
|
|
81
|
+
"!livepilot/skills/livepilot-devices/references/m4l-master-reference.md",
|
|
82
|
+
"!livepilot/skills/livepilot-devices/references/m4l-technique-map.md"
|
|
68
83
|
]
|
|
69
84
|
}
|
|
@@ -5,7 +5,7 @@ Entry point for the ControlSurface. Ableton calls create_instance(c_instance)
|
|
|
5
5
|
when this script is selected in Preferences > Link, Tempo & MIDI.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
__version__ = "1.26.
|
|
8
|
+
__version__ = "1.26.2"
|
|
9
9
|
|
|
10
10
|
from _Framework.ControlSurface import ControlSurface
|
|
11
11
|
from . import router
|
|
@@ -60,6 +60,67 @@ WRITE_COMMANDS = frozenset([
|
|
|
60
60
|
"clear_clip_automation",
|
|
61
61
|
])
|
|
62
62
|
|
|
63
|
+
# Future-safe write detection. WRITE_COMMANDS remains the explicit allow-list
|
|
64
|
+
# for older handlers and readability; the prefix classifier catches newer
|
|
65
|
+
# mutating handlers so they still receive the write timeout and settle delay.
|
|
66
|
+
READ_COMMAND_PREFIXES = ("get_", "list_", "scan_")
|
|
67
|
+
READ_ONLY_COMMANDS = frozenset([
|
|
68
|
+
"ping",
|
|
69
|
+
"reload_handlers",
|
|
70
|
+
])
|
|
71
|
+
WRITE_COMMAND_PREFIXES = (
|
|
72
|
+
"add_",
|
|
73
|
+
"apply_",
|
|
74
|
+
"arrangement_automation_",
|
|
75
|
+
"assign_",
|
|
76
|
+
"back_to_",
|
|
77
|
+
"capture_",
|
|
78
|
+
"cleanup_",
|
|
79
|
+
"clear_",
|
|
80
|
+
"continue_",
|
|
81
|
+
"copy_",
|
|
82
|
+
"create_",
|
|
83
|
+
"delete_",
|
|
84
|
+
"duplicate_",
|
|
85
|
+
"find_and_load_",
|
|
86
|
+
"fire_",
|
|
87
|
+
"flatten_",
|
|
88
|
+
"force_",
|
|
89
|
+
"freeze_",
|
|
90
|
+
"import_",
|
|
91
|
+
"insert_",
|
|
92
|
+
"jump_",
|
|
93
|
+
"load_",
|
|
94
|
+
"modify_",
|
|
95
|
+
"move_",
|
|
96
|
+
"nudge_",
|
|
97
|
+
"quantize_",
|
|
98
|
+
"randomize_",
|
|
99
|
+
"recall_",
|
|
100
|
+
"remove_",
|
|
101
|
+
"replace_",
|
|
102
|
+
"reset_",
|
|
103
|
+
"set_",
|
|
104
|
+
"start_",
|
|
105
|
+
"stop_",
|
|
106
|
+
"store_",
|
|
107
|
+
"tap_",
|
|
108
|
+
"toggle_",
|
|
109
|
+
"transpose_",
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def is_write_command(command_type):
|
|
114
|
+
"""Return True if a command is expected to mutate Live state."""
|
|
115
|
+
if command_type in WRITE_COMMANDS:
|
|
116
|
+
return True
|
|
117
|
+
if command_type in READ_ONLY_COMMANDS:
|
|
118
|
+
return False
|
|
119
|
+
if command_type.startswith(READ_COMMAND_PREFIXES):
|
|
120
|
+
return False
|
|
121
|
+
return command_type.startswith(WRITE_COMMAND_PREFIXES)
|
|
122
|
+
|
|
123
|
+
|
|
63
124
|
# Commands that need longer timeouts (e.g., freeze renders audio)
|
|
64
125
|
SLOW_WRITE_COMMANDS = frozenset([
|
|
65
126
|
"freeze_track",
|
|
@@ -277,7 +338,7 @@ class LivePilotServer(object):
|
|
|
277
338
|
cmd_type = command.get("type", "")
|
|
278
339
|
|
|
279
340
|
# Determine timeout based on read vs write vs slow write
|
|
280
|
-
is_write = cmd_type
|
|
341
|
+
is_write = is_write_command(cmd_type)
|
|
281
342
|
if cmd_type in SLOW_WRITE_COMMANDS:
|
|
282
343
|
timeout = 35
|
|
283
344
|
elif is_write:
|
|
@@ -343,7 +404,7 @@ class LivePilotServer(object):
|
|
|
343
404
|
return
|
|
344
405
|
|
|
345
406
|
cmd_type = command.get("type", "")
|
|
346
|
-
is_write = cmd_type
|
|
407
|
+
is_write = is_write_command(cmd_type)
|
|
347
408
|
|
|
348
409
|
try:
|
|
349
410
|
song = self._cs.song()
|
package/requirements.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# LivePilot MCP Server dependencies
|
|
2
|
-
numpy>=2.4.
|
|
3
|
-
fastmcp>=3.
|
|
2
|
+
numpy>=2.4.6
|
|
3
|
+
fastmcp>=3.3.1,<3.4.0 # pinned upper bound — _get_all_tools() accesses private internals
|
|
4
4
|
midiutil>=1.2.1
|
|
5
5
|
pretty_midi>=0.2.11
|
|
6
6
|
# v1.8 Perception Layer (offline analysis)
|
|
@@ -13,7 +13,7 @@ mutagen>=1.47.0
|
|
|
13
13
|
# falls back to the SQLite sounds.db which only returns locally downloaded
|
|
14
14
|
# samples (see docs/2026-04-14-bugs-discovered.md — P0-2).
|
|
15
15
|
grpcio>=1.80.0
|
|
16
|
-
protobuf>=7.
|
|
16
|
+
protobuf>=7.35.0
|
|
17
17
|
|
|
18
18
|
# Known benign warning during install:
|
|
19
19
|
# ERROR: pip's dependency resolver does not currently take into account
|
package/server.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
3
|
"name": "io.github.dreamrec/livepilot",
|
|
4
|
-
"description": "465-tool agentic MCP production system for Ableton Live 12 \u2014
|
|
4
|
+
"description": "465-tool agentic MCP production system for Ableton Live 12 \u2014 56 domains, 44 semantic moves, device atlas (5264 devices), Splice intelligence (gRPC + GraphQL), 9-band spectral perception auto-loaded, Creative Director skill, technique memory, 12 creative engines",
|
|
5
5
|
"repository": {
|
|
6
6
|
"url": "https://github.com/dreamrec/LivePilot",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "1.26.
|
|
9
|
+
"version": "1.26.2",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "livepilot",
|
|
14
|
-
"version": "1.26.
|
|
14
|
+
"version": "1.26.2",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
}
|